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 19namespace crypto { 20 21namespace { 22 23HASH_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 33SECOidTag 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 45SECStatus 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 75SignatureVerifier::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 85SignatureVerifier::~SignatureVerifier() { 86 Reset(); 87} 88 89bool 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 125bool 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 153void 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 163bool 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 181SECKEYPublicKey* 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 197void 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 214