| 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...) Expand all 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 |