OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 "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 "crypto/nss_util.h" |
| 13 |
| 14 namespace crypto { |
| 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 crypto |
OLD | NEW |