1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/crypto/signature_verifier.h"
6
7 #include <stdlib.h>
8
9 #include "base/crypto/cssm_init.h"
10 #include "base/logging.h"
11
12 namespace base {
13
SignatureVerifier()14 SignatureVerifier::SignatureVerifier() : csp_handle_(0), sig_handle_(0) {
15 EnsureCSSMInit();
16
17 static CSSM_VERSION version = {2, 0};
18 CSSM_RETURN crtn;
19 crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &kCssmMemoryFunctions, 0,
20 CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE,
21 NULL, 0, NULL, &csp_handle_);
22 DCHECK(crtn == CSSM_OK);
23 }
24
~SignatureVerifier()25 SignatureVerifier::~SignatureVerifier() {
26 Reset();
27 if (csp_handle_) {
28 CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_);
29 DCHECK(crtn == CSSM_OK);
30 }
31 }
32
VerifyInit(const uint8 * signature_algorithm,int signature_algorithm_len,const uint8 * signature,int signature_len,const uint8 * public_key_info,int public_key_info_len)33 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
34 int signature_algorithm_len,
35 const uint8* signature,
36 int signature_len,
37 const uint8* public_key_info,
38 int public_key_info_len) {
39 signature_.assign(signature, signature + signature_len);
40 public_key_info_.assign(public_key_info,
41 public_key_info + public_key_info_len);
42
43 CSSM_ALGORITHMS key_alg = CSSM_ALGID_RSA; // TODO(wtc): hardcoded.
44
45 memset(&public_key_, 0, sizeof(public_key_));
46 public_key_.KeyData.Data = const_cast<uint8*>(&public_key_info_[0]);
47 public_key_.KeyData.Length = public_key_info_.size();
48 public_key_.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
49 public_key_.KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
50 public_key_.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_X509;
51 public_key_.KeyHeader.AlgorithmId = key_alg;
52 public_key_.KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
53 public_key_.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
54 public_key_.KeyHeader.KeyUsage = CSSM_KEYUSE_VERIFY;
55 CSSM_KEY_SIZE key_size;
56 CSSM_RETURN crtn;
57 crtn = CSSM_QueryKeySizeInBits(csp_handle_, NULL, &public_key_, &key_size);
58 if (crtn) {
59 NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn;
60 return false;
61 }
62 public_key_.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
63
64 // TODO(wtc): decode signature_algorithm...
65 CSSM_ALGORITHMS sig_alg = CSSM_ALGID_SHA1WithRSA;
66
67 crtn = CSSM_CSP_CreateSignatureContext(csp_handle_, sig_alg, NULL,
68 &public_key_, &sig_handle_);
69 if (crtn) {
70 NOTREACHED();
71 return false;
72 }
73 crtn = CSSM_VerifyDataInit(sig_handle_);
74 if (crtn) {
75 NOTREACHED();
76 return false;
77 }
78 return true;
79 }
80
VerifyUpdate(const uint8 * data_part,int data_part_len)81 void SignatureVerifier::VerifyUpdate(const uint8* data_part,
82 int data_part_len) {
83 CSSM_DATA data;
84 data.Data = const_cast<uint8*>(data_part);
85 data.Length = data_part_len;
86 CSSM_RETURN crtn = CSSM_VerifyDataUpdate(sig_handle_, &data, 1);
87 DCHECK(crtn == CSSM_OK);
88 }
89
VerifyFinal()90 bool SignatureVerifier::VerifyFinal() {
91 CSSM_DATA sig;
92 sig.Data = const_cast<uint8*>(&signature_[0]);
93 sig.Length = signature_.size();
94 CSSM_RETURN crtn = CSSM_VerifyDataFinal(sig_handle_, &sig);
95 Reset();
96
97 // crtn is CSSMERR_CSP_VERIFY_FAILED if signature verification fails.
98 return (crtn == CSSM_OK);
99 }
100
Reset()101 void SignatureVerifier::Reset() {
102 CSSM_RETURN crtn;
103 if (sig_handle_) {
104 crtn = CSSM_DeleteContext(sig_handle_);
105 DCHECK(crtn == CSSM_OK);
106 sig_handle_ = 0;
107 }
108 signature_.clear();
109
110 // Can't call CSSM_FreeKey on public_key_ because we constructed
111 // public_key_ manually.
112 }
113
114 } // namespace base
115
116