OLD | NEW |
| (Empty) |
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 <cryptohi.h> | |
8 #include <keyhi.h> | |
9 #include <stdlib.h> | |
10 | |
11 #include "base/logging.h" | |
12 #include "base/nss_util.h" | |
13 | |
14 namespace base { | |
15 | |
16 SignatureVerifier::SignatureVerifier() : vfy_context_(NULL) { | |
17 EnsureNSSInit(); | |
18 } | |
19 | |
20 SignatureVerifier::~SignatureVerifier() { | |
21 Reset(); | |
22 } | |
23 | |
24 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, | |
25 int signature_algorithm_len, | |
26 const uint8* signature, | |
27 int signature_len, | |
28 const uint8* public_key_info, | |
29 int public_key_info_len) { | |
30 signature_.assign(signature, signature + signature_len); | |
31 | |
32 CERTSubjectPublicKeyInfo* spki = NULL; | |
33 SECItem spki_der; | |
34 spki_der.type = siBuffer; | |
35 spki_der.data = const_cast<uint8*>(public_key_info); | |
36 spki_der.len = public_key_info_len; | |
37 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); | |
38 if (!spki) | |
39 return false; | |
40 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); | |
41 SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. | |
42 if (!public_key) | |
43 return false; | |
44 | |
45 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
46 if (!arena) { | |
47 SECKEY_DestroyPublicKey(public_key); | |
48 return false; | |
49 } | |
50 | |
51 SECItem sig_alg_der; | |
52 sig_alg_der.type = siBuffer; | |
53 sig_alg_der.data = const_cast<uint8*>(signature_algorithm); | |
54 sig_alg_der.len = signature_algorithm_len; | |
55 SECAlgorithmID sig_alg_id; | |
56 SECStatus rv; | |
57 rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, SECOID_AlgorithmIDTemplate, | |
58 &sig_alg_der); | |
59 if (rv != SECSuccess) { | |
60 SECKEY_DestroyPublicKey(public_key); | |
61 PORT_FreeArena(arena, PR_TRUE); | |
62 return false; | |
63 } | |
64 | |
65 SECItem sig; | |
66 sig.type = siBuffer; | |
67 sig.data = const_cast<uint8*>(signature); | |
68 sig.len = signature_len; | |
69 SECOidTag hash_alg_tag; | |
70 vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig, | |
71 &sig_alg_id, &hash_alg_tag, | |
72 NULL); | |
73 SECKEY_DestroyPublicKey(public_key); // Done with public_key. | |
74 PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id. | |
75 if (!vfy_context_) { | |
76 // A corrupted RSA signature could be detected without the data, so | |
77 // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE | |
78 // (-8182). | |
79 return false; | |
80 } | |
81 | |
82 rv = VFY_Begin(vfy_context_); | |
83 if (rv != SECSuccess) { | |
84 NOTREACHED(); | |
85 return false; | |
86 } | |
87 return true; | |
88 } | |
89 | |
90 void SignatureVerifier::VerifyUpdate(const uint8* data_part, | |
91 int data_part_len) { | |
92 SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); | |
93 DCHECK(rv == SECSuccess); | |
94 } | |
95 | |
96 bool SignatureVerifier::VerifyFinal() { | |
97 SECStatus rv = VFY_End(vfy_context_); | |
98 Reset(); | |
99 | |
100 // If signature verification fails, the error code is | |
101 // SEC_ERROR_BAD_SIGNATURE (-8182). | |
102 return (rv == SECSuccess); | |
103 } | |
104 | |
105 void SignatureVerifier::Reset() { | |
106 if (vfy_context_) { | |
107 VFY_DestroyContext(vfy_context_, PR_TRUE); | |
108 vfy_context_ = NULL; | |
109 } | |
110 signature_.clear(); | |
111 } | |
112 | |
113 } // namespace base | |
OLD | NEW |