OLD | NEW |
1 /* | 1 /* |
2 * Verification stuff. | 2 * Verification stuff. |
3 * | 3 * |
4 * This Source Code Form is subject to the terms of the Mozilla Public | 4 * This Source Code Form is subject to the terms of the Mozilla Public |
5 * License, v. 2.0. If a copy of the MPL was not distributed with this | 5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | 7 |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include "cryptohi.h" | 9 #include "cryptohi.h" |
10 #include "sechash.h" | 10 #include "sechash.h" |
(...skipping 17 matching lines...) Loading... |
28 ** Store the DigestInfo length into digestInfoLen. | 28 ** Store the DigestInfo length into digestInfoLen. |
29 ** | 29 ** |
30 ** This function does *not* verify that the AlgorithmIdentifier in the | 30 ** This function does *not* verify that the AlgorithmIdentifier in the |
31 ** DigestInfo identifies givenDigestAlg or that the DigestInfo is encoded | 31 ** DigestInfo identifies givenDigestAlg or that the DigestInfo is encoded |
32 ** correctly; verifyPKCS1DigestInfo does that. | 32 ** correctly; verifyPKCS1DigestInfo does that. |
33 ** | 33 ** |
34 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION | 34 ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION |
35 */ | 35 */ |
36 static SECStatus | 36 static SECStatus |
37 recoverPKCS1DigestInfo(SECOidTag givenDigestAlg, | 37 recoverPKCS1DigestInfo(SECOidTag givenDigestAlg, |
38 /*out*/ SECOidTag* digestAlgOut, | 38 /*out*/ SECOidTag *digestAlgOut, |
39 /*out*/ unsigned char** digestInfo, | 39 /*out*/ unsigned char **digestInfo, |
40 /*out*/ unsigned int* digestInfoLen, | 40 /*out*/ unsigned int *digestInfoLen, |
41 SECKEYPublicKey* key, | 41 SECKEYPublicKey *key, |
42 const SECItem* sig, void* wincx) | 42 const SECItem *sig, void *wincx) |
43 { | 43 { |
44 SGNDigestInfo* di = NULL; | 44 SGNDigestInfo *di = NULL; |
45 SECItem it; | 45 SECItem it; |
46 PRBool rv = SECSuccess; | 46 PRBool rv = SECSuccess; |
47 | 47 |
48 PORT_Assert(digestAlgOut); | 48 PORT_Assert(digestAlgOut); |
49 PORT_Assert(digestInfo); | 49 PORT_Assert(digestInfo); |
50 PORT_Assert(digestInfoLen); | 50 PORT_Assert(digestInfoLen); |
51 PORT_Assert(key); | 51 PORT_Assert(key); |
52 PORT_Assert(key->keyType == rsaKey); | 52 PORT_Assert(key->keyType == rsaKey); |
53 PORT_Assert(sig); | 53 PORT_Assert(sig); |
54 | 54 |
55 it.data = NULL; | 55 it.data = NULL; |
56 it.len = SECKEY_PublicKeyStrength(key); | 56 it.len = SECKEY_PublicKeyStrength(key); |
57 if (it.len != 0) { | 57 if (it.len != 0) { |
58 it.data = (unsigned char *)PORT_Alloc(it.len); | 58 it.data = (unsigned char *)PORT_Alloc(it.len); |
59 } | 59 } |
60 if (it.len == 0 || it.data == NULL ) { | 60 if (it.len == 0 || it.data == NULL) { |
61 rv = SECFailure; | 61 rv = SECFailure; |
62 } | 62 } |
63 | 63 |
64 if (rv == SECSuccess) { | 64 if (rv == SECSuccess) { |
65 /* decrypt the block */ | 65 /* decrypt the block */ |
66 rv = PK11_VerifyRecover(key, sig, &it, wincx); | 66 rv = PK11_VerifyRecover(key, sig, &it, wincx); |
67 } | 67 } |
68 | 68 |
69 if (rv == SECSuccess) { | 69 if (rv == SECSuccess) { |
70 if (givenDigestAlg != SEC_OID_UNKNOWN) { | 70 if (givenDigestAlg != SEC_OID_UNKNOWN) { |
71 /* We don't need to parse the DigestInfo if the caller gave us the | 71 /* We don't need to parse the DigestInfo if the caller gave us the |
72 * digest algorithm to use. Later verifyPKCS1DigestInfo will verify | 72 * digest algorithm to use. Later verifyPKCS1DigestInfo will verify |
73 * that the DigestInfo identifies the given digest algorithm and | 73 * that the DigestInfo identifies the given digest algorithm and |
74 * that the DigestInfo is encoded absolutely correctly. | 74 * that the DigestInfo is encoded absolutely correctly. |
75 */ | 75 */ |
76 *digestInfoLen = it.len; | 76 *digestInfoLen = it.len; |
77 *digestInfo = (unsigned char*)it.data; | 77 *digestInfo = (unsigned char *)it.data; |
78 *digestAlgOut = givenDigestAlg; | 78 *digestAlgOut = givenDigestAlg; |
79 return SECSuccess; | 79 return SECSuccess; |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 if (rv == SECSuccess) { | 83 if (rv == SECSuccess) { |
84 /* The caller didn't specify a digest algorithm to use, so choose the | 84 /* The caller didn't specify a digest algorithm to use, so choose the |
85 * digest algorithm by parsing the AlgorithmIdentifier within the | 85 * digest algorithm by parsing the AlgorithmIdentifier within the |
86 * DigestInfo. | 86 * DigestInfo. |
87 */ | 87 */ |
88 di = SGN_DecodeDigestInfo(&it); | 88 di = SGN_DecodeDigestInfo(&it); |
89 if (!di) { | 89 if (!di) { |
90 rv = SECFailure; | 90 rv = SECFailure; |
91 } | 91 } |
92 } | 92 } |
93 | 93 |
94 if (rv == SECSuccess) { | 94 if (rv == SECSuccess) { |
95 *digestAlgOut = SECOID_GetAlgorithmTag(&di->digestAlgorithm); | 95 *digestAlgOut = SECOID_GetAlgorithmTag(&di->digestAlgorithm); |
96 if (*digestAlgOut == SEC_OID_UNKNOWN) { | 96 if (*digestAlgOut == SEC_OID_UNKNOWN) { |
97 rv = SECFailure; | 97 rv = SECFailure; |
98 } | 98 } |
99 } | 99 } |
100 | 100 |
101 if (di) { | 101 if (di) { |
102 SGN_DestroyDigestInfo(di); | 102 SGN_DestroyDigestInfo(di); |
103 } | 103 } |
104 | 104 |
105 if (rv == SECSuccess) { | 105 if (rv == SECSuccess) { |
106 *digestInfoLen = it.len; | 106 *digestInfoLen = it.len; |
107 *digestInfo = (unsigned char*)it.data; | 107 *digestInfo = (unsigned char *)it.data; |
108 } else { | 108 } else { |
109 if (it.data) { | 109 if (it.data) { |
110 PORT_Free(it.data); | 110 PORT_Free(it.data); |
111 } | 111 } |
112 *digestInfo = NULL; | 112 *digestInfo = NULL; |
113 *digestInfoLen = 0; | 113 *digestInfoLen = 0; |
114 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 114 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
115 } | 115 } |
116 | 116 |
117 return rv; | 117 return rv; |
118 } | 118 } |
119 | 119 |
120 struct VFYContextStr { | 120 struct VFYContextStr { |
121 SECOidTag hashAlg; /* the hash algorithm */ | 121 SECOidTag hashAlg; /* the hash algorithm */ |
122 SECKEYPublicKey *key; | 122 SECKEYPublicKey *key; |
123 /* | 123 /* |
124 * This buffer holds either the digest or the full signature | 124 * This buffer holds either the digest or the full signature |
125 * depending on the type of the signature (key->keyType). It is | 125 * depending on the type of the signature (key->keyType). It is |
126 * defined as a union to make sure it always has enough space. | 126 * defined as a union to make sure it always has enough space. |
127 * | 127 * |
128 * Use the "buffer" union member to reference the buffer. | 128 * Use the "buffer" union member to reference the buffer. |
129 * Note: do not take the size of the "buffer" union member. Take | 129 * Note: do not take the size of the "buffer" union member. Take |
130 * the size of the union or some other union member instead. | 130 * the size of the union or some other union member instead. |
131 */ | 131 */ |
132 union { | 132 union { |
133 » unsigned char buffer[1]; | 133 unsigned char buffer[1]; |
134 | 134 |
135 » /* the full DSA signature... 40 bytes */ | 135 /* the full DSA signature... 40 bytes */ |
136 » unsigned char dsasig[DSA_MAX_SIGNATURE_LEN]; | 136 unsigned char dsasig[DSA_MAX_SIGNATURE_LEN]; |
137 » /* the full ECDSA signature */ | 137 /* the full ECDSA signature */ |
138 » unsigned char ecdsasig[2 * MAX_ECKEY_LEN]; | 138 unsigned char ecdsasig[2 * MAX_ECKEY_LEN]; |
139 } u; | 139 } u; |
140 unsigned int pkcs1RSADigestInfoLen; | 140 unsigned int pkcs1RSADigestInfoLen; |
141 /* the encoded DigestInfo from a RSA PKCS#1 signature */ | 141 /* the encoded DigestInfo from a RSA PKCS#1 signature */ |
142 unsigned char *pkcs1RSADigestInfo; | 142 unsigned char *pkcs1RSADigestInfo; |
143 void * wincx; | 143 void *wincx; |
144 void *hashcx; | 144 void *hashcx; |
145 const SECHashObject *hashobj; | 145 const SECHashObject *hashobj; |
146 SECOidTag encAlg; /* enc alg */ | 146 SECOidTag encAlg; /* enc alg */ |
147 PRBool hasSignature; /* true if the signature was provided in the | 147 PRBool hasSignature; /* true if the signature was provided in the |
148 * VFY_CreateContext call. If false, the | 148 * VFY_CreateContext call. If false, the |
149 * signature must be provided with a | 149 * signature must be provided with a |
150 * VFY_EndWithSignature call. */ | 150 * VFY_EndWithSignature call. */ |
151 }; | 151 }; |
152 | 152 |
153 static SECStatus | 153 static SECStatus |
154 verifyPKCS1DigestInfo(const VFYContext* cx, const SECItem* digest) | 154 verifyPKCS1DigestInfo(const VFYContext *cx, const SECItem *digest) |
155 { | 155 { |
156 SECItem pkcs1DigestInfo; | 156 SECItem pkcs1DigestInfo; |
157 pkcs1DigestInfo.data = cx->pkcs1RSADigestInfo; | 157 pkcs1DigestInfo.data = cx->pkcs1RSADigestInfo; |
158 pkcs1DigestInfo.len = cx->pkcs1RSADigestInfoLen; | 158 pkcs1DigestInfo.len = cx->pkcs1RSADigestInfoLen; |
159 return _SGN_VerifyPKCS1DigestInfo( | 159 return _SGN_VerifyPKCS1DigestInfo( |
160 cx->hashAlg, digest, &pkcs1DigestInfo, | 160 cx->hashAlg, digest, &pkcs1DigestInfo, |
161 PR_TRUE /*XXX: unsafeAllowMissingParameters*/); | 161 PR_TRUE /*XXX: unsafeAllowMissingParameters*/); |
162 } | 162 } |
163 | 163 |
164 /* | 164 /* |
165 * decode the ECDSA or DSA signature from it's DER wrapping. | 165 * decode the ECDSA or DSA signature from it's DER wrapping. |
166 * The unwrapped/raw signature is placed in the buffer pointed | 166 * The unwrapped/raw signature is placed in the buffer pointed |
167 * to by dsig and has enough room for len bytes. | 167 * to by dsig and has enough room for len bytes. |
168 */ | 168 */ |
169 static SECStatus | 169 static SECStatus |
170 decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig, | 170 decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig, |
171 » » unsigned int len) { | 171 unsigned int len) |
| 172 { |
172 SECItem *dsasig = NULL; /* also used for ECDSA */ | 173 SECItem *dsasig = NULL; /* also used for ECDSA */ |
173 SECStatus rv=SECSuccess; | 174 SECStatus rv = SECSuccess; |
174 | 175 |
175 if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) && | 176 if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) && |
176 » (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { | 177 (algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { |
177 if (sig->len != len) { | 178 if (sig->len != len) { |
178 » PORT_SetError(SEC_ERROR_BAD_DER); | 179 PORT_SetError(SEC_ERROR_BAD_DER); |
179 » return SECFailure; | 180 return SECFailure; |
180 » } | 181 } |
181 | 182 |
182 » PORT_Memcpy(dsig, sig->data, sig->len); | 183 PORT_Memcpy(dsig, sig->data, sig->len); |
183 » return SECSuccess; | 184 return SECSuccess; |
184 } | 185 } |
185 | 186 |
186 if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) { | 187 if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) { |
187 » if (len > MAX_ECKEY_LEN * 2) { | 188 if (len > MAX_ECKEY_LEN * 2) { |
188 » PORT_SetError(SEC_ERROR_BAD_DER); | 189 PORT_SetError(SEC_ERROR_BAD_DER); |
189 » return SECFailure; | 190 return SECFailure; |
190 » } | 191 } |
191 } | 192 } |
192 dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len); | 193 dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len); |
193 | 194 |
194 if ((dsasig == NULL) || (dsasig->len != len)) { | 195 if ((dsasig == NULL) || (dsasig->len != len)) { |
195 » rv = SECFailure; | 196 rv = SECFailure; |
196 } else { | 197 } else { |
197 » PORT_Memcpy(dsig, dsasig->data, dsasig->len); | 198 PORT_Memcpy(dsig, dsasig->data, dsasig->len); |
198 } | 199 } |
199 | 200 |
200 if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE); | 201 if (dsasig != NULL) |
201 if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER); | 202 SECITEM_FreeItem(dsasig, PR_TRUE); |
| 203 if (rv == SECFailure) |
| 204 PORT_SetError(SEC_ERROR_BAD_DER); |
202 return rv; | 205 return rv; |
203 } | 206 } |
204 | 207 |
205 const SEC_ASN1Template hashParameterTemplate[] = | 208 const SEC_ASN1Template hashParameterTemplate[] = |
206 { | 209 { |
207 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) }, | 210 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) }, |
208 { SEC_ASN1_OBJECT_ID, 0 }, | 211 { SEC_ASN1_OBJECT_ID, 0 }, |
209 { SEC_ASN1_SKIP_REST }, | 212 { SEC_ASN1_SKIP_REST }, |
210 { 0, } | 213 { 0 } |
211 }; | 214 }; |
212 | 215 |
213 /* | 216 /* |
214 * Pulls the hash algorithm, signing algorithm, and key type out of a | 217 * Pulls the hash algorithm, signing algorithm, and key type out of a |
215 * composite algorithm. | 218 * composite algorithm. |
216 * | 219 * |
217 * sigAlg: the composite algorithm to dissect. | 220 * sigAlg: the composite algorithm to dissect. |
218 * hashalg: address of a SECOidTag which will be set with the hash algorithm. | 221 * hashalg: address of a SECOidTag which will be set with the hash algorithm. |
219 * encalg: address of a SECOidTag which will be set with the signing alg. | 222 * encalg: address of a SECOidTag which will be set with the signing alg. |
220 * | 223 * |
221 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the | 224 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the |
222 * algorithm was not found or was not a signing algorithm. | 225 * algorithm was not found or was not a signing algorithm. |
223 */ | 226 */ |
224 SECStatus | 227 SECStatus |
225 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg, | 228 sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg, |
226 const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg) | 229 const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg) |
227 { | 230 { |
228 int len; | 231 int len; |
229 PLArenaPool *arena; | 232 PLArenaPool *arena; |
230 SECStatus rv; | 233 SECStatus rv; |
231 SECItem oid; | 234 SECItem oid; |
232 | 235 |
233 PR_ASSERT(hashalg!=NULL); | 236 PR_ASSERT(hashalg != NULL); |
234 PR_ASSERT(encalg!=NULL); | 237 PR_ASSERT(encalg != NULL); |
235 | 238 |
236 switch (sigAlg) { | 239 switch (sigAlg) { |
237 /* We probably shouldn't be generating MD2 signatures either */ | 240 /* We probably shouldn't be generating MD2 signatures either */ |
238 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: | 241 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: |
239 *hashalg = SEC_OID_MD2; | 242 *hashalg = SEC_OID_MD2; |
240 » break; | 243 break; |
241 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: | 244 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: |
242 *hashalg = SEC_OID_MD5; | 245 *hashalg = SEC_OID_MD5; |
243 » break; | 246 break; |
244 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: | 247 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: |
245 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: | 248 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: |
246 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: | 249 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: |
247 *hashalg = SEC_OID_SHA1; | 250 *hashalg = SEC_OID_SHA1; |
248 » break; | 251 break; |
249 case SEC_OID_PKCS1_RSA_ENCRYPTION: | 252 case SEC_OID_PKCS1_RSA_ENCRYPTION: |
250 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: | 253 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
251 *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */ | 254 *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */ |
252 » break; | 255 break; |
253 | 256 |
254 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: | 257 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: |
255 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: | 258 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: |
256 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: | 259 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: |
257 » *hashalg = SEC_OID_SHA224; | 260 *hashalg = SEC_OID_SHA224; |
258 » break; | 261 break; |
259 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: | 262 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: |
260 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: | 263 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: |
261 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: | 264 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: |
262 » *hashalg = SEC_OID_SHA256; | 265 *hashalg = SEC_OID_SHA256; |
263 » break; | 266 break; |
264 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: | 267 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: |
265 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: | 268 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: |
266 » *hashalg = SEC_OID_SHA384; | 269 *hashalg = SEC_OID_SHA384; |
267 » break; | 270 break; |
268 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: | 271 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: |
269 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: | 272 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: |
270 » *hashalg = SEC_OID_SHA512; | 273 *hashalg = SEC_OID_SHA512; |
271 » break; | 274 break; |
272 | 275 |
273 /* what about normal DSA? */ | 276 /* what about normal DSA? */ |
274 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: | 277 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: |
275 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: | 278 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: |
276 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: | 279 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: |
277 *hashalg = SEC_OID_SHA1; | 280 *hashalg = SEC_OID_SHA1; |
278 » break; | 281 break; |
279 case SEC_OID_MISSI_DSS: | 282 case SEC_OID_MISSI_DSS: |
280 case SEC_OID_MISSI_KEA_DSS: | 283 case SEC_OID_MISSI_KEA_DSS: |
281 case SEC_OID_MISSI_KEA_DSS_OLD: | 284 case SEC_OID_MISSI_KEA_DSS_OLD: |
282 case SEC_OID_MISSI_DSS_OLD: | 285 case SEC_OID_MISSI_DSS_OLD: |
283 *hashalg = SEC_OID_SHA1; | 286 *hashalg = SEC_OID_SHA1; |
284 » break; | 287 break; |
285 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST: | 288 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST: |
286 » /* This is an EC algorithm. Recommended means the largest | 289 /* This is an EC algorithm. Recommended means the largest |
287 » * hash algorithm that is not reduced by the keysize of | 290 * hash algorithm that is not reduced by the keysize of |
288 » * the EC algorithm. Note that key strength is in bytes and | 291 * the EC algorithm. Note that key strength is in bytes and |
289 » * algorithms are specified in bits. Never use an algorithm | 292 * algorithms are specified in bits. Never use an algorithm |
290 » * weaker than sha1. */ | 293 * weaker than sha1. */ |
291 » len = SECKEY_PublicKeyStrength(key); | 294 len = SECKEY_PublicKeyStrength(key); |
292 » if (len < 28) { /* 28 bytes == 224 bits */ | 295 if (len < 28) { /* 28 bytes == 224 bits */ |
293 » *hashalg = SEC_OID_SHA1; | 296 *hashalg = SEC_OID_SHA1; |
294 » } else if (len < 32) { /* 32 bytes == 256 bits */ | 297 } else if (len < 32) { /* 32 bytes == 256 bits */ |
295 » *hashalg = SEC_OID_SHA224; | 298 *hashalg = SEC_OID_SHA224; |
296 » } else if (len < 48) { /* 48 bytes == 384 bits */ | 299 } else if (len < 48) { /* 48 bytes == 384 bits */ |
297 » *hashalg = SEC_OID_SHA256; | 300 *hashalg = SEC_OID_SHA256; |
298 » } else if (len < 64) { /* 48 bytes == 512 bits */ | 301 } else if (len < 64) { /* 48 bytes == 512 bits */ |
299 » *hashalg = SEC_OID_SHA384; | 302 *hashalg = SEC_OID_SHA384; |
300 » } else { | 303 } else { |
301 » /* use the largest in this case */ | 304 /* use the largest in this case */ |
302 » *hashalg = SEC_OID_SHA512; | 305 *hashalg = SEC_OID_SHA512; |
303 » } | 306 } |
304 » break; | 307 break; |
305 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST: | 308 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST: |
306 » if (param == NULL) { | 309 if (param == NULL) { |
307 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 310 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
308 » return SECFailure; | 311 return SECFailure; |
309 » } | 312 } |
310 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 313 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
311 » if (arena == NULL) { | 314 if (arena == NULL) { |
312 » return SECFailure; | 315 return SECFailure; |
313 » } | 316 } |
314 » rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param); | 317 rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, para
m); |
315 » if (rv == SECSuccess) { | 318 if (rv == SECSuccess) { |
316 *hashalg = SECOID_FindOIDTag(&oid); | 319 *hashalg = SECOID_FindOIDTag(&oid); |
317 } | 320 } |
318 PORT_FreeArena(arena, PR_FALSE); | 321 PORT_FreeArena(arena, PR_FALSE); |
319 if (rv != SECSuccess) { | 322 if (rv != SECSuccess) { |
320 » return rv; | 323 return rv; |
321 » } | 324 } |
322 » /* only accept hash algorithms */ | 325 /* only accept hash algorithms */ |
323 » if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) { | 326 if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) { |
324 » /* error set by HASH_GetHashTypeByOidTag */ | 327 /* error set by HASH_GetHashTypeByOidTag */ |
325 » return SECFailure; | 328 return SECFailure; |
326 » } | 329 } |
327 » break; | 330 break; |
328 /* we don't implement MD4 hashes */ | 331 /* we don't implement MD4 hashes */ |
329 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: | 332 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: |
330 default: | 333 default: |
331 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 334 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
332 » return SECFailure; | 335 return SECFailure; |
333 } | 336 } |
334 /* get the "encryption" algorithm */ | 337 /* get the "encryption" algorithm */ |
335 switch (sigAlg) { | 338 switch (sigAlg) { |
336 case SEC_OID_PKCS1_RSA_ENCRYPTION: | 339 case SEC_OID_PKCS1_RSA_ENCRYPTION: |
337 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: | 340 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: |
338 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: | 341 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: |
339 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: | 342 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: |
340 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: | 343 case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: |
341 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: | 344 case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: |
342 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: | 345 case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: |
343 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: | 346 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: |
344 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: | 347 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: |
345 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: | 348 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: |
346 » *encalg = SEC_OID_PKCS1_RSA_ENCRYPTION; | 349 *encalg = SEC_OID_PKCS1_RSA_ENCRYPTION; |
347 » break; | 350 break; |
348 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: | 351 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
349 » *encalg = SEC_OID_PKCS1_RSA_PSS_SIGNATURE; | 352 *encalg = SEC_OID_PKCS1_RSA_PSS_SIGNATURE; |
350 » break; | 353 break; |
351 | 354 |
352 /* what about normal DSA? */ | 355 /* what about normal DSA? */ |
353 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: | 356 case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: |
354 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: | 357 case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: |
355 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: | 358 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST: |
356 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: | 359 case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST: |
357 » *encalg = SEC_OID_ANSIX9_DSA_SIGNATURE; | 360 *encalg = SEC_OID_ANSIX9_DSA_SIGNATURE; |
358 » break; | 361 break; |
359 case SEC_OID_MISSI_DSS: | 362 case SEC_OID_MISSI_DSS: |
360 case SEC_OID_MISSI_KEA_DSS: | 363 case SEC_OID_MISSI_KEA_DSS: |
361 case SEC_OID_MISSI_KEA_DSS_OLD: | 364 case SEC_OID_MISSI_KEA_DSS_OLD: |
362 case SEC_OID_MISSI_DSS_OLD: | 365 case SEC_OID_MISSI_DSS_OLD: |
363 » *encalg = SEC_OID_MISSI_DSS; | 366 *encalg = SEC_OID_MISSI_DSS; |
364 » break; | 367 break; |
365 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: | 368 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: |
366 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: | 369 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: |
367 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: | 370 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: |
368 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: | 371 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: |
369 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: | 372 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: |
370 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST: | 373 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST: |
371 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST: | 374 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST: |
372 » *encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY; | 375 *encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
373 » break; | 376 break; |
374 /* we don't implement MD4 hashes */ | 377 /* we don't implement MD4 hashes */ |
375 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: | 378 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: |
376 default: | 379 default: |
377 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 380 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
378 » return SECFailure; | 381 return SECFailure; |
379 } | 382 } |
380 return SECSuccess; | 383 return SECSuccess; |
381 } | 384 } |
382 | 385 |
383 /* | 386 /* |
384 * we can verify signatures that come from 2 different sources: | 387 * we can verify signatures that come from 2 different sources: |
385 * one in with the signature contains a signature oid, and the other | 388 * one in with the signature contains a signature oid, and the other |
386 * in which the signature is managed by a Public key (encAlg) oid | 389 * in which the signature is managed by a Public key (encAlg) oid |
387 * and a hash oid. The latter is the more basic, so that's what | 390 * and a hash oid. The latter is the more basic, so that's what |
388 * our base vfyCreate function takes. | 391 * our base vfyCreate function takes. |
389 * | 392 * |
390 * There is one noteworthy corner case, if we are using an RSA key, and the | 393 * There is one noteworthy corner case, if we are using an RSA key, and the |
391 * signature block is provided, then the hashAlg can be specified as | 394 * signature block is provided, then the hashAlg can be specified as |
392 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied | 395 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied |
393 * in the RSA signature block. | 396 * in the RSA signature block. |
394 */ | 397 */ |
395 static VFYContext * | 398 static VFYContext * |
396 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig, | 399 vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig, |
397 » SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx) | 400 SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wi
ncx) |
398 { | 401 { |
399 VFYContext *cx; | 402 VFYContext *cx; |
400 SECStatus rv; | 403 SECStatus rv; |
401 unsigned int sigLen; | 404 unsigned int sigLen; |
402 KeyType type; | 405 KeyType type; |
403 | 406 |
404 /* make sure the encryption algorithm matches the key type */ | 407 /* make sure the encryption algorithm matches the key type */ |
405 /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */ | 408 /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */ |
406 type = seckey_GetKeyType(encAlg); | 409 type = seckey_GetKeyType(encAlg); |
407 if ((key->keyType != type) && | 410 if ((key->keyType != type) && |
408 » ((key->keyType != rsaKey) || (type != rsaPssKey))) { | 411 ((key->keyType != rsaKey) || (type != rsaPssKey))) { |
409 » PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH); | 412 PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH); |
410 » return NULL; | 413 return NULL; |
411 } | 414 } |
412 | 415 |
413 cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext)); | 416 cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext)); |
414 if (cx == NULL) { | 417 if (cx == NULL) { |
415 » goto loser; | 418 goto loser; |
416 } | 419 } |
417 | 420 |
418 cx->wincx = wincx; | 421 cx->wincx = wincx; |
419 cx->hasSignature = (sig != NULL); | 422 cx->hasSignature = (sig != NULL); |
420 cx->encAlg = encAlg; | 423 cx->encAlg = encAlg; |
421 cx->hashAlg = hashAlg; | 424 cx->hashAlg = hashAlg; |
422 cx->key = SECKEY_CopyPublicKey(key); | 425 cx->key = SECKEY_CopyPublicKey(key); |
423 cx->pkcs1RSADigestInfo = NULL; | 426 cx->pkcs1RSADigestInfo = NULL; |
424 rv = SECSuccess; | 427 rv = SECSuccess; |
425 if (sig) { | 428 if (sig) { |
426 » switch (type) { | 429 switch (type) { |
427 » case rsaKey: | 430 case rsaKey: |
428 » rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg, | 431 rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg, |
429 » » » » » &cx->pkcs1RSADigestInfo, | 432 &cx->pkcs1RSADigestInfo, |
430 » » » » » &cx->pkcs1RSADigestInfoLen, | 433 &cx->pkcs1RSADigestInfoLen, |
431 » » » » » cx->key, | 434 cx->key, |
432 » » » » » sig, wincx); | 435 sig, wincx); |
433 » break; | 436 break; |
434 » case dsaKey: | 437 case dsaKey: |
435 » case ecKey: | 438 case ecKey: |
436 » sigLen = SECKEY_SignatureLen(key); | 439 sigLen = SECKEY_SignatureLen(key); |
437 » if (sigLen == 0) { | 440 if (sigLen == 0) { |
438 » » /* error set by SECKEY_SignatureLen */ | 441 /* error set by SECKEY_SignatureLen */ |
439 » » rv = SECFailure;» | 442 rv = SECFailure; |
440 » » break; | 443 break; |
441 » } | 444 } |
442 » rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen); | 445 rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen); |
443 » break; | 446 break; |
444 » default: | 447 default: |
445 » rv = SECFailure; | 448 rv = SECFailure; |
446 » PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); | 449 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
447 » break; | 450 break; |
448 » } | 451 } |
449 } | 452 } |
450 | 453 |
451 if (rv) goto loser; | 454 if (rv) |
| 455 goto loser; |
452 | 456 |
453 /* check hash alg again, RSA may have changed it.*/ | 457 /* check hash alg again, RSA may have changed it.*/ |
454 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) { | 458 if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) { |
455 » /* error set by HASH_GetHashTypeByOidTag */ | 459 /* error set by HASH_GetHashTypeByOidTag */ |
456 » goto loser; | 460 goto loser; |
457 } | 461 } |
458 | 462 |
459 if (hash) { | 463 if (hash) { |
460 » *hash = cx->hashAlg; | 464 *hash = cx->hashAlg; |
461 } | 465 } |
462 return cx; | 466 return cx; |
463 | 467 |
464 loser: | 468 loser: |
465 if (cx) { | 469 if (cx) { |
466 » VFY_DestroyContext(cx, PR_TRUE); | 470 VFY_DestroyContext(cx, PR_TRUE); |
467 } | 471 } |
468 return 0; | 472 return 0; |
469 } | 473 } |
470 | 474 |
471 VFYContext * | 475 VFYContext * |
472 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg, | 476 VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg, |
473 » » void *wincx) | 477 void *wincx) |
474 { | 478 { |
475 SECOidTag encAlg, hashAlg; | 479 SECOidTag encAlg, hashAlg; |
476 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg); | 480 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg); |
477 if (rv != SECSuccess) { | 481 if (rv != SECSuccess) { |
478 » return NULL; | 482 return NULL; |
479 } | 483 } |
480 return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx); | 484 return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx); |
481 } | 485 } |
482 | 486 |
483 VFYContext * | 487 VFYContext * |
484 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig, | 488 VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig, |
485 » » » SECOidTag encAlg, SECOidTag hashAlg, | 489 SECOidTag encAlg, SECOidTag hashAlg, |
486 » » » SECOidTag *hash, void *wincx) | 490 SECOidTag *hash, void *wincx) |
487 { | 491 { |
488 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx); | 492 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx); |
489 } | 493 } |
490 | 494 |
491 VFYContext * | 495 VFYContext * |
492 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig, | 496 VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig, |
493 » const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx) | 497 const SECAlgorithmID *sigAlgorithm, SECOidTag *
hash, void *wincx) |
494 { | 498 { |
495 SECOidTag encAlg, hashAlg; | 499 SECOidTag encAlg, hashAlg; |
496 SECStatus rv = sec_DecodeSigAlg(key, | 500 SECStatus rv = sec_DecodeSigAlg(key, |
497 » » SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm), | 501 SECOID_GetAlgorithmTag((SECAlgorithmID *)sig
Algorithm), |
498 » » &sigAlgorithm->parameters, &encAlg, &hashAlg); | 502 &sigAlgorithm->parameters, &encAlg, &hashAlg
); |
499 if (rv != SECSuccess) { | 503 if (rv != SECSuccess) { |
500 » return NULL; | 504 return NULL; |
501 } | 505 } |
502 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx); | 506 return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx); |
503 } | 507 } |
504 | 508 |
505 void | 509 void |
506 VFY_DestroyContext(VFYContext *cx, PRBool freeit) | 510 VFY_DestroyContext(VFYContext *cx, PRBool freeit) |
507 { | 511 { |
508 if (cx) { | 512 if (cx) { |
509 » if (cx->hashcx != NULL) { | 513 if (cx->hashcx != NULL) { |
510 » (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); | 514 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); |
511 » cx->hashcx = NULL; | 515 cx->hashcx = NULL; |
512 » } | 516 } |
513 » if (cx->key) { | 517 if (cx->key) { |
514 » SECKEY_DestroyPublicKey(cx->key); | 518 SECKEY_DestroyPublicKey(cx->key); |
515 » } | 519 } |
516 if (cx->pkcs1RSADigestInfo) { | 520 if (cx->pkcs1RSADigestInfo) { |
517 PORT_Free(cx->pkcs1RSADigestInfo); | 521 PORT_Free(cx->pkcs1RSADigestInfo); |
518 } | 522 } |
519 » if (freeit) { | 523 if (freeit) { |
520 » PORT_ZFree(cx, sizeof(VFYContext)); | 524 PORT_ZFree(cx, sizeof(VFYContext)); |
521 » } | 525 } |
522 } | 526 } |
523 } | 527 } |
524 | 528 |
525 SECStatus | 529 SECStatus |
526 VFY_Begin(VFYContext *cx) | 530 VFY_Begin(VFYContext *cx) |
527 { | 531 { |
528 if (cx->hashcx != NULL) { | 532 if (cx->hashcx != NULL) { |
529 » (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); | 533 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); |
530 » cx->hashcx = NULL; | 534 cx->hashcx = NULL; |
531 } | 535 } |
532 | 536 |
533 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg); | 537 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg); |
534 if (!cx->hashobj) | 538 if (!cx->hashobj) |
535 » return SECFailure;» /* error code is set */ | 539 return SECFailure; /* error code is set */ |
536 | 540 |
537 cx->hashcx = (*cx->hashobj->create)(); | 541 cx->hashcx = (*cx->hashobj->create)(); |
538 if (cx->hashcx == NULL) | 542 if (cx->hashcx == NULL) |
539 » return SECFailure; | 543 return SECFailure; |
540 | 544 |
541 (*cx->hashobj->begin)(cx->hashcx); | 545 (*cx->hashobj->begin)(cx->hashcx); |
542 return SECSuccess; | 546 return SECSuccess; |
543 } | 547 } |
544 | 548 |
545 SECStatus | 549 SECStatus |
546 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen) | 550 VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen) |
547 { | 551 { |
548 if (cx->hashcx == NULL) { | 552 if (cx->hashcx == NULL) { |
549 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 553 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
550 » return SECFailure; | 554 return SECFailure; |
551 } | 555 } |
552 (*cx->hashobj->update)(cx->hashcx, input, inputLen); | 556 (*cx->hashobj->update)(cx->hashcx, input, inputLen); |
553 return SECSuccess; | 557 return SECSuccess; |
554 } | 558 } |
555 | 559 |
556 SECStatus | 560 SECStatus |
557 VFY_EndWithSignature(VFYContext *cx, SECItem *sig) | 561 VFY_EndWithSignature(VFYContext *cx, SECItem *sig) |
558 { | 562 { |
559 unsigned char final[HASH_LENGTH_MAX]; | 563 unsigned char final[HASH_LENGTH_MAX]; |
560 unsigned part; | 564 unsigned part; |
561 SECItem hash,dsasig; /* dsasig is also used for ECDSA */ | 565 SECItem hash, dsasig; /* dsasig is also used for ECDSA */ |
562 SECStatus rv; | 566 SECStatus rv; |
563 | 567 |
564 if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) { | 568 if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) { |
565 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 569 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
566 » return SECFailure; | 570 return SECFailure; |
567 } | 571 } |
568 | 572 |
569 if (cx->hashcx == NULL) { | 573 if (cx->hashcx == NULL) { |
570 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 574 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
571 » return SECFailure; | 575 return SECFailure; |
572 } | 576 } |
573 (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final)); | 577 (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final)); |
574 switch (cx->key->keyType) { | 578 switch (cx->key->keyType) { |
575 case ecKey: | 579 case ecKey: |
576 case dsaKey: | 580 case dsaKey: |
577 » dsasig.data = cx->u.buffer; | 581 dsasig.data = cx->u.buffer; |
578 » dsasig.len = SECKEY_SignatureLen(cx->key); | 582 dsasig.len = SECKEY_SignatureLen(cx->key); |
579 » if (dsasig.len == 0) { | 583 if (dsasig.len == 0) { |
580 » return SECFailure; | 584 return SECFailure; |
581 » } | 585 } |
582 » if (sig) { | 586 if (sig) { |
583 » rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data, | 587 rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data, |
584 » » » » » dsasig.len); | 588 dsasig.len); |
585 » if (rv != SECSuccess) { | 589 if (rv != SECSuccess) { |
586 » » PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 590 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
587 » » return SECFailure; | 591 return SECFailure; |
588 » } | 592 } |
589 » } | 593 } |
590 » hash.data = final; | 594 hash.data = final; |
591 » hash.len = part; | 595 hash.len = part; |
592 » if (PK11_Verify(cx->key,&dsasig,&hash,cx->wincx) != SECSuccess) { | 596 if (PK11_Verify(cx->key, &dsasig, &hash, cx->wincx) != SECSuccess) { |
593 » » PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 597 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
594 » » return SECFailure; | 598 return SECFailure; |
595 » } | 599 } |
596 » break; | 600 break; |
597 case rsaKey: | 601 case rsaKey: { |
598 { | 602 SECItem digest; |
599 SECItem digest; | 603 digest.data = final; |
600 digest.data = final; | 604 digest.len = part; |
601 digest.len = part; | 605 if (sig) { |
602 » if (sig) { | 606 SECOidTag hashid; |
603 » SECOidTag hashid; | 607 PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN); |
604 » PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN); | 608 rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid, |
605 » rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid, | 609 &cx->pkcs1RSADigestInfo, |
606 » » » » » &cx->pkcs1RSADigestInfo, | 610 &cx->pkcs1RSADigestInfoLen, |
607 » » » » » &cx->pkcs1RSADigestInfoLen, | 611 cx->key, |
608 » » » » » cx->key, | 612 sig, cx->wincx); |
609 » » » » » sig, cx->wincx); | 613 PORT_Assert(cx->hashAlg == hashid); |
610 » PORT_Assert(cx->hashAlg == hashid); | 614 if (rv != SECSuccess) { |
611 » if (rv != SECSuccess) { | 615 return SECFailure; |
612 » » return SECFailure; | 616 } |
613 » } | 617 } |
614 » } | 618 return verifyPKCS1DigestInfo(cx, &digest); |
615 » return verifyPKCS1DigestInfo(cx, &digest); | 619 } |
616 } | 620 default: |
617 default: | 621 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
618 » PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 622 return SECFailure; /* shouldn't happen */ |
619 » return SECFailure; /* shouldn't happen */ | |
620 } | 623 } |
621 return SECSuccess; | 624 return SECSuccess; |
622 } | 625 } |
623 | 626 |
624 SECStatus | 627 SECStatus |
625 VFY_End(VFYContext *cx) | 628 VFY_End(VFYContext *cx) |
626 { | 629 { |
627 return VFY_EndWithSignature(cx,NULL); | 630 return VFY_EndWithSignature(cx, NULL); |
628 } | 631 } |
629 | 632 |
630 /************************************************************************/ | 633 /************************************************************************/ |
631 /* | 634 /* |
632 * Verify that a previously-computed digest matches a signature. | 635 * Verify that a previously-computed digest matches a signature. |
633 */ | 636 */ |
634 static SECStatus | 637 static SECStatus |
635 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key, | 638 vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key, |
636 » » const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg, | 639 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg, |
637 » » void *wincx) | 640 void *wincx) |
638 { | 641 { |
639 SECStatus rv; | 642 SECStatus rv; |
640 VFYContext *cx; | 643 VFYContext *cx; |
641 SECItem dsasig; /* also used for ECDSA */ | 644 SECItem dsasig; /* also used for ECDSA */ |
642 | 645 |
643 rv = SECFailure; | 646 rv = SECFailure; |
644 | 647 |
645 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx); | 648 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx); |
646 if (cx != NULL) { | 649 if (cx != NULL) { |
647 » switch (key->keyType) { | 650 switch (key->keyType) { |
648 » case rsaKey: | 651 case rsaKey: |
649 » rv = verifyPKCS1DigestInfo(cx, digest); | 652 rv = verifyPKCS1DigestInfo(cx, digest); |
650 » break; | 653 break; |
651 » case dsaKey: | 654 case dsaKey: |
652 » case ecKey: | 655 case ecKey: |
653 » dsasig.data = cx->u.buffer; | 656 dsasig.data = cx->u.buffer; |
654 » dsasig.len = SECKEY_SignatureLen(cx->key); | 657 dsasig.len = SECKEY_SignatureLen(cx->key); |
655 » if (dsasig.len == 0) { | 658 if (dsasig.len == 0) { |
656 » » break; | 659 break; |
657 » } | 660 } |
658 » if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx) | 661 if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx)
!= |
659 » » != SECSuccess) { | 662 SECSuccess) { |
660 » » PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 663 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
661 » } else { | 664 } else { |
662 » » rv = SECSuccess; | 665 rv = SECSuccess; |
663 » } | 666 } |
664 » break; | 667 break; |
665 » default: | 668 default: |
666 » break; | 669 break; |
667 » } | 670 } |
668 » VFY_DestroyContext(cx, PR_TRUE); | 671 VFY_DestroyContext(cx, PR_TRUE); |
669 } | 672 } |
670 return rv; | 673 return rv; |
671 } | 674 } |
672 | 675 |
673 SECStatus | 676 SECStatus |
674 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key, | 677 VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key, |
675 » » const SECItem *sig, SECOidTag encAlg, | 678 const SECItem *sig, SECOidTag encAlg, |
676 » » SECOidTag hashAlg, void *wincx) | 679 SECOidTag hashAlg, void *wincx) |
677 { | 680 { |
678 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx); | 681 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx); |
679 } | 682 } |
680 | 683 |
681 SECStatus | 684 SECStatus |
682 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, | 685 VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, |
683 » » SECOidTag algid, void *wincx) | 686 SECOidTag algid, void *wincx) |
684 { | 687 { |
685 SECOidTag encAlg, hashAlg; | 688 SECOidTag encAlg, hashAlg; |
686 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg); | 689 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg); |
687 if (rv != SECSuccess) { | 690 if (rv != SECSuccess) { |
688 » return SECFailure; | 691 return SECFailure; |
689 } | 692 } |
690 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx); | 693 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx); |
691 } | 694 } |
692 | 695 |
693 /* | 696 /* |
694 * this function takes an optional hash oid, which the digest function | 697 * this function takes an optional hash oid, which the digest function |
695 * will be compared with our target hash value. | 698 * will be compared with our target hash value. |
696 */ | 699 */ |
697 SECStatus | 700 SECStatus |
698 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest, | 701 VFY_VerifyDigestWithAlgorithmID(const SECItem *digest, |
699 » » const SECKEYPublicKey *key, const SECItem *sig, | 702 const SECKEYPublicKey *key, const SECItem *sig, |
700 » » const SECAlgorithmID *sigAlgorithm, | 703 const SECAlgorithmID *sigAlgorithm, |
701 » » SECOidTag hashCmp, void *wincx) | 704 SECOidTag hashCmp, void *wincx) |
702 { | 705 { |
703 SECOidTag encAlg, hashAlg; | 706 SECOidTag encAlg, hashAlg; |
704 SECStatus rv = sec_DecodeSigAlg(key, | 707 SECStatus rv = sec_DecodeSigAlg(key, |
705 » » SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm), | 708 SECOID_GetAlgorithmTag((SECAlgorithmID *)sig
Algorithm), |
706 » » &sigAlgorithm->parameters, &encAlg, &hashAlg); | 709 &sigAlgorithm->parameters, &encAlg, &hashAlg
); |
707 if (rv != SECSuccess) { | 710 if (rv != SECSuccess) { |
708 » return rv; | 711 return rv; |
709 } | 712 } |
710 if ( hashCmp != SEC_OID_UNKNOWN && | 713 if (hashCmp != SEC_OID_UNKNOWN && |
711 » hashAlg != SEC_OID_UNKNOWN && | 714 hashAlg != SEC_OID_UNKNOWN && |
712 » hashCmp != hashAlg) { | 715 hashCmp != hashAlg) { |
713 » PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | 716 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
714 » return SECFailure; | 717 return SECFailure; |
715 } | 718 } |
716 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx); | 719 return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx); |
717 } | 720 } |
718 | 721 |
719 static SECStatus | 722 static SECStatus |
720 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key, | 723 vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key, |
721 » const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg, | 724 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg, |
722 » SECOidTag *hash, void *wincx) | 725 SECOidTag *hash, void *wincx) |
723 { | 726 { |
724 SECStatus rv; | 727 SECStatus rv; |
725 VFYContext *cx; | 728 VFYContext *cx; |
726 | 729 |
727 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx); | 730 cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx); |
728 if (cx == NULL) | 731 if (cx == NULL) |
729 » return SECFailure; | 732 return SECFailure; |
730 | 733 |
731 rv = VFY_Begin(cx); | 734 rv = VFY_Begin(cx); |
732 if (rv == SECSuccess) { | 735 if (rv == SECSuccess) { |
733 » rv = VFY_Update(cx, (unsigned char *)buf, len); | 736 rv = VFY_Update(cx, (unsigned char *)buf, len); |
734 » if (rv == SECSuccess) | 737 if (rv == SECSuccess) |
735 » rv = VFY_End(cx); | 738 rv = VFY_End(cx); |
736 } | 739 } |
737 | 740 |
738 VFY_DestroyContext(cx, PR_TRUE); | 741 VFY_DestroyContext(cx, PR_TRUE); |
739 return rv; | 742 return rv; |
740 } | 743 } |
741 | 744 |
742 SECStatus | 745 SECStatus |
743 VFY_VerifyDataDirect(const unsigned char *buf, int len, | 746 VFY_VerifyDataDirect(const unsigned char *buf, int len, |
744 » » const SECKEYPublicKey *key, const SECItem *sig, | 747 const SECKEYPublicKey *key, const SECItem *sig, |
745 » » SECOidTag encAlg, SECOidTag hashAlg, | 748 SECOidTag encAlg, SECOidTag hashAlg, |
746 » » SECOidTag *hash, void *wincx) | 749 SECOidTag *hash, void *wincx) |
747 { | 750 { |
748 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx); | 751 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx); |
749 } | 752 } |
750 | 753 |
751 SECStatus | 754 SECStatus |
752 VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key, | 755 VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key, |
753 » const SECItem *sig, SECOidTag algid, void *wincx) | 756 const SECItem *sig, SECOidTag algid, void *wincx) |
754 { | 757 { |
755 SECOidTag encAlg, hashAlg; | 758 SECOidTag encAlg, hashAlg; |
756 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg); | 759 SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg); |
757 if (rv != SECSuccess) { | 760 if (rv != SECSuccess) { |
758 » return rv; | 761 return rv; |
759 } | 762 } |
760 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx); | 763 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx); |
761 } | 764 } |
762 | 765 |
763 SECStatus | 766 SECStatus |
764 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len, | 767 VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len, |
765 » » » const SECKEYPublicKey *key, | 768 const SECKEYPublicKey *key, |
766 » » » const SECItem *sig, | 769 const SECItem *sig, |
767 » » » const SECAlgorithmID *sigAlgorithm, | 770 const SECAlgorithmID *sigAlgorithm, |
768 » » » SECOidTag *hash, void *wincx) | 771 SECOidTag *hash, void *wincx) |
769 { | 772 { |
770 SECOidTag encAlg, hashAlg; | 773 SECOidTag encAlg, hashAlg; |
771 SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm); | 774 SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm); |
772 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, | 775 SECStatus rv = sec_DecodeSigAlg(key, sigAlg, |
773 » » &sigAlgorithm->parameters, &encAlg, &hashAlg); | 776 &sigAlgorithm->parameters, &encAlg, &hashAlg
); |
774 if (rv != SECSuccess) { | 777 if (rv != SECSuccess) { |
775 » return rv; | 778 return rv; |
776 } | 779 } |
777 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx); | 780 return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx); |
778 } | 781 } |
OLD | NEW |