| 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 <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 SECOidTag ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg) { | |
| 34 switch (sig_alg) { | |
| 35 case SignatureVerifier::RSA_PKCS1_SHA1: | |
| 36 return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | |
| 37 case SignatureVerifier::RSA_PKCS1_SHA256: | |
| 38 return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; | |
| 39 case SignatureVerifier::ECDSA_SHA256: | |
| 40 return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; | |
| 41 } | |
| 42 return SEC_OID_UNKNOWN; | |
| 43 } | |
| 44 | |
| 45 SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, | |
| 46 HASHContext* hash_context, | |
| 47 HASH_HashType mask_hash_alg, | |
| 48 unsigned int salt_len, | |
| 49 const unsigned char* signature, | |
| 50 unsigned int signature_len) { | |
| 51 unsigned int hash_len = HASH_ResultLenContext(hash_context); | |
| 52 std::vector<unsigned char> hash(hash_len); | |
| 53 HASH_End(hash_context, &hash[0], &hash_len, hash.size()); | |
| 54 | |
| 55 unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key); | |
| 56 if (signature_len != modulus_len) { | |
| 57 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 58 return SECFailure; | |
| 59 } | |
| 60 std::vector<unsigned char> enc(signature_len); | |
| 61 SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0], | |
| 62 const_cast<unsigned char*>(signature), | |
| 63 signature_len, NULL); | |
| 64 if (rv != SECSuccess) { | |
| 65 LOG(WARNING) << "PK11_PubEncryptRaw failed"; | |
| 66 return rv; | |
| 67 } | |
| 68 return emsa_pss_verify(&hash[0], &enc[0], enc.size(), | |
| 69 HASH_GetType(hash_context), mask_hash_alg, | |
| 70 salt_len); | |
| 71 } | |
| 72 | |
| 73 } // namespace | |
| 74 | |
| 75 SignatureVerifier::SignatureVerifier() | |
| 76 : vfy_context_(NULL), | |
| 77 hash_alg_(SHA1), | |
| 78 mask_hash_alg_(SHA1), | |
| 79 salt_len_(0), | |
| 80 public_key_(NULL), | |
| 81 hash_context_(NULL) { | |
| 82 EnsureNSSInit(); | |
| 83 } | |
| 84 | |
| 85 SignatureVerifier::~SignatureVerifier() { | |
| 86 Reset(); | |
| 87 } | |
| 88 | |
| 89 bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm, | |
| 90 const uint8_t* signature, | |
| 91 int signature_len, | |
| 92 const uint8_t* public_key_info, | |
| 93 int public_key_info_len) { | |
| 94 if (vfy_context_ || hash_context_) | |
| 95 return false; | |
| 96 | |
| 97 signature_.assign(signature, signature + signature_len); | |
| 98 | |
| 99 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, | |
| 100 public_key_info_len); | |
| 101 if (!public_key) | |
| 102 return false; | |
| 103 | |
| 104 SECItem sig; | |
| 105 sig.type = siBuffer; | |
| 106 sig.data = const_cast<uint8_t*>(signature); | |
| 107 sig.len = signature_len; | |
| 108 vfy_context_ = VFY_CreateContext( | |
| 109 public_key, &sig, ToNSSSignatureType(signature_algorithm), nullptr); | |
| 110 SECKEY_DestroyPublicKey(public_key); // Done with public_key. | |
| 111 if (!vfy_context_) { | |
| 112 // A corrupted RSA signature could be detected without the data, so | |
| 113 // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE | |
| 114 // (-8182). | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 if (VFY_Begin(vfy_context_) != SECSuccess) { | |
| 119 NOTREACHED(); | |
| 120 return false; | |
| 121 } | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, | |
| 126 HashAlgorithm mask_hash_alg, | |
| 127 int salt_len, | |
| 128 const uint8_t* signature, | |
| 129 int signature_len, | |
| 130 const uint8_t* public_key_info, | |
| 131 int public_key_info_len) { | |
| 132 if (vfy_context_ || hash_context_) | |
| 133 return false; | |
| 134 | |
| 135 signature_.assign(signature, signature + signature_len); | |
| 136 | |
| 137 SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info, | |
| 138 public_key_info_len); | |
| 139 if (!public_key) | |
| 140 return false; | |
| 141 | |
| 142 public_key_ = public_key; | |
| 143 hash_alg_ = hash_alg; | |
| 144 mask_hash_alg_ = mask_hash_alg; | |
| 145 salt_len_ = salt_len; | |
| 146 hash_context_ = HASH_Create(ToNSSHashType(hash_alg_)); | |
| 147 if (!hash_context_) | |
| 148 return false; | |
| 149 HASH_Begin(hash_context_); | |
| 150 return true; | |
| 151 } | |
| 152 | |
| 153 void SignatureVerifier::VerifyUpdate(const uint8_t* data_part, | |
| 154 int data_part_len) { | |
| 155 if (vfy_context_) { | |
| 156 SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len); | |
| 157 DCHECK_EQ(SECSuccess, rv); | |
| 158 } else { | |
| 159 HASH_Update(hash_context_, data_part, data_part_len); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 bool SignatureVerifier::VerifyFinal() { | |
| 164 SECStatus rv; | |
| 165 if (vfy_context_) { | |
| 166 rv = VFY_End(vfy_context_); | |
| 167 } else { | |
| 168 rv = VerifyRSAPSS_End(public_key_, hash_context_, | |
| 169 ToNSSHashType(mask_hash_alg_), salt_len_, | |
| 170 signature_.data(), | |
| 171 signature_.size()); | |
| 172 } | |
| 173 Reset(); | |
| 174 | |
| 175 // If signature verification fails, the error code is | |
| 176 // SEC_ERROR_BAD_SIGNATURE (-8182). | |
| 177 return (rv == SECSuccess); | |
| 178 } | |
| 179 | |
| 180 // static | |
| 181 SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo( | |
| 182 const uint8_t* public_key_info, | |
| 183 int public_key_info_len) { | |
| 184 CERTSubjectPublicKeyInfo* spki = NULL; | |
| 185 SECItem spki_der; | |
| 186 spki_der.type = siBuffer; | |
| 187 spki_der.data = const_cast<uint8_t*>(public_key_info); | |
| 188 spki_der.len = public_key_info_len; | |
| 189 spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der); | |
| 190 if (!spki) | |
| 191 return NULL; | |
| 192 SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki); | |
| 193 SECKEY_DestroySubjectPublicKeyInfo(spki); // Done with spki. | |
| 194 return public_key; | |
| 195 } | |
| 196 | |
| 197 void SignatureVerifier::Reset() { | |
| 198 if (vfy_context_) { | |
| 199 VFY_DestroyContext(vfy_context_, PR_TRUE); | |
| 200 vfy_context_ = NULL; | |
| 201 } | |
| 202 if (hash_context_) { | |
| 203 HASH_Destroy(hash_context_); | |
| 204 hash_context_ = NULL; | |
| 205 } | |
| 206 if (public_key_) { | |
| 207 SECKEY_DestroyPublicKey(public_key_); | |
| 208 public_key_ = NULL; | |
| 209 } | |
| 210 signature_.clear(); | |
| 211 } | |
| 212 | |
| 213 } // namespace crypto | |
| OLD | NEW |