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 114