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 <pk11pub.h> 10 #include <secerr.h> 11 #include <sechash.h> 12 #include <stdint.h> 13 #include <stdlib.h> 14 15 #include "base/logging.h" 16 #include "crypto/nss_util.h" 17 #include "crypto/third_party/nss/chromium-nss.h" 18 19 namespace crypto { 20 21 namespace { 22 23 HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) { 24 switch (hash_alg) { 25 case SignatureVerifier::SHA1: 26 return HASH_AlgSHA1; 27 case SignatureVerifier::SHA256: 28 return HASH_AlgSHA256; 29 } 30 return HASH_AlgNULL; 31 } 32 33 SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, 34 HASHContext* hash_context, 35 HASH_HashType mask_hash_alg, 36 unsigned int salt_len, 37 const unsigned char* signature, 38 unsigned int signature_len) { 39 unsigned int hash_len = HASH_ResultLenContext(hash_context); 40 std::vector<unsigned char> hash(hash_len); 41 HASH_End(hash_context, &hash[0], &hash_len, hash.size()); 42 43 unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key); 44 if (signature_len != modulus_len) { 45 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 46 return SECFailure; 47 } 48 std::vector<unsigned char> enc(signature_len); 49 SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0], 50 const_cast<unsigned char*>(signature), 51 signature_len, NULL); 52 if (rv != SECSuccess) { 53 LOG(WARNING) << "PK11_PubEncryptRaw failed"; 54 return rv; 55 } 56 return emsa_pss_verify(&hash[0], &enc[0], enc.size(), 57 HASH_GetType(hash_context), mask_hash_alg, 58 salt_len); 59 } 60 61 } // namespace 62 63 SignatureVerifier::SignatureVerifier() 64 : vfy_context_(NULL), 65 hash_alg_(SHA1), 66 mask_hash_alg_(SHA1), 67 salt_len_(0), 68 public_key_(NULL), 69 hash_context_(NULL) { 70 EnsureNSSInit(); 71 } 72 73 SignatureVerifier::~SignatureVerifier() { 74 Reset(); 75 } 76 77 bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm, 78 int signature_algorithm_len, 79 const uint8_t* signature, 80 int signature_len, 81 const uint8_t* public_key_info, 82 int public_key_info_len) { 83 if (vfy_context_ || hash_context_) 84 return false; 85 86 signature_.assign(signature, signature + signature_len); 87 88 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, 89 public_key_info_len); 90 if (!public_key) 91 return false; 92 93 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 94 if (!arena) { 95 SECKEY_DestroyPublicKey(public_key); 96 return false; 97 } 98 99 SECItem sig_alg_der; 100 sig_alg_der.type = siBuffer; 101 sig_alg_der.data = const_cast<uint8_t*>(signature_algorithm); 102 sig_alg_der.len = signature_algorithm_len; 103 SECAlgorithmID sig_alg_id; 104 SECStatus rv; 105 rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, 106 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), 107 &sig_alg_der); 108 if (rv != SECSuccess) { 109 SECKEY_DestroyPublicKey(public_key); 110 PORT_FreeArena(arena, PR_TRUE); 111 return false; 112 } 113 114 SECItem sig; 115 sig.type = siBuffer; 116 sig.data = const_cast<uint8_t*>(signature); 117 sig.len = signature_len; 118 SECOidTag hash_alg_tag; 119 vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig, 120 &sig_alg_id, &hash_alg_tag, 121 NULL); 122 SECKEY_DestroyPublicKey(public_key); // Done with public_key. 123 PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id. 124 if (!vfy_context_) { 125 // A corrupted RSA signature could be detected without the data, so 126 // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE 127 // (-8182). 128 return false; 129 } 130 131 rv = VFY_Begin(vfy_context_); 132 if (rv != SECSuccess) { 133 NOTREACHED(); 134 return false; 135 } 136 return true; 137 } 138 139 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, 140 HashAlgorithm mask_hash_alg, 141 int salt_len, 142 const uint8_t* signature, 143 int signature_len, 144 const uint8_t* public_key_info, 145 int public_key_info_len) { 146 if (vfy_context_ || hash_context_) 147 return false; 148 149 signature_.assign(signature, signature + signature_len); 150 151 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, 152 public_key_info_len); 153 if (!public_key) 154 return false; 155 156 public_key_ = public_key; 157 hash_alg_ = hash_alg; 158 mask_hash_alg_ = mask_hash_alg; 159 salt_len_ = salt_len; 160 hash_context_ = HASH_Create(ToNSSHashType(hash_alg_)); 161 if (!hash_context_) 162 return false; 163 HASH_Begin(hash_context_); 164 return true; 165 } 166 167 void SignatureVerifier::VerifyUpdate(const uint8_t* data_part, 168 int data_part_len) { 169 if (vfy_context_) { 170 SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); 171 DCHECK_EQ(SECSuccess, rv); 172 } else { 173 HASH_Update(hash_context_, data_part, data_part_len); 174 } 175 } 176 177 bool SignatureVerifier::VerifyFinal() { 178 SECStatus rv; 179 if (vfy_context_) { 180 rv = VFY_End(vfy_context_); 181 } else { 182 rv = VerifyRSAPSS_End(public_key_, hash_context_, 183 ToNSSHashType(mask_hash_alg_), salt_len_, 184 signature_.data(), 185 signature_.size()); 186 } 187 Reset(); 188 189 // If signature verification fails, the error code is 190 // SEC_ERROR_BAD_SIGNATURE (-8182). 191 return (rv == SECSuccess); 192 } 193 194 // static 195 SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo( 196 const uint8_t* public_key_info, 197 int public_key_info_len) { 198 CERTSubjectPublicKeyInfo* spki = NULL; 199 SECItem spki_der; 200 spki_der.type = siBuffer; 201 spki_der.data = const_cast<uint8_t*>(public_key_info); 202 spki_der.len = public_key_info_len; 203 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); 204 if (!spki) 205 return NULL; 206 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); 207 SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. 208 return public_key; 209 } 210 211 void SignatureVerifier::Reset() { 212 if (vfy_context_) { 213 VFY_DestroyContext(vfy_context_, PR_TRUE); 214 vfy_context_ = NULL; 215 } 216 if (hash_context_) { 217 HASH_Destroy(hash_context_); 218 hash_context_ = NULL; 219 } 220 if (public_key_) { 221 SECKEY_DestroyPublicKey(public_key_); 222 public_key_ = NULL; 223 } 224 signature_.clear(); 225 } 226 227 } // namespace crypto 228