| 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 |