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 
ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg)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 
ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg)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 
VerifyRSAPSS_End(SECKEYPublicKey * public_key,HASHContext * hash_context,HASH_HashType mask_hash_alg,unsigned int salt_len,const unsigned char * signature,unsigned int signature_len)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 
SignatureVerifier()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 
~SignatureVerifier()85 SignatureVerifier::~SignatureVerifier() {
86   Reset();
87 }
88 
VerifyInit(SignatureAlgorithm signature_algorithm,const uint8_t * signature,int signature_len,const uint8_t * public_key_info,int public_key_info_len)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 
VerifyInitRSAPSS(HashAlgorithm hash_alg,HashAlgorithm mask_hash_alg,int salt_len,const uint8_t * signature,int signature_len,const uint8_t * public_key_info,int public_key_info_len)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 
VerifyUpdate(const uint8_t * data_part,int data_part_len)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 
VerifyFinal()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
DecodePublicKeyInfo(const uint8_t * public_key_info,int public_key_info_len)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 
Reset()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
214