| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Signature stuff. | 2 * Signature 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 22 matching lines...) Expand all Loading... |
| 33 SECStatus rv; | 33 SECStatus rv; |
| 34 | 34 |
| 35 /* OK, map a PKCS #7 hash and encrypt algorithm into | 35 /* OK, map a PKCS #7 hash and encrypt algorithm into |
| 36 * a standard hashing algorithm. Why did we pass in the whole | 36 * a standard hashing algorithm. Why did we pass in the whole |
| 37 * PKCS #7 algTag if we were just going to change here you might | 37 * PKCS #7 algTag if we were just going to change here you might |
| 38 * ask. Well the answer is for some cards we may have to do the | 38 * ask. Well the answer is for some cards we may have to do the |
| 39 * hashing on card. It may not support CKM_RSA_PKCS sign algorithm, | 39 * hashing on card. It may not support CKM_RSA_PKCS sign algorithm, |
| 40 * it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS. | 40 * it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS. |
| 41 */ | 41 */ |
| 42 /* we have a private key, not a public key, so don't pass it in */ | 42 /* we have a private key, not a public key, so don't pass it in */ |
| 43 rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg); | 43 rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg); |
| 44 if (rv != SECSuccess) { | 44 if (rv != SECSuccess) { |
| 45 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 45 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
| 46 » return 0; | 46 return 0; |
| 47 } | 47 } |
| 48 keyType = seckey_GetKeyType(signalg); | 48 keyType = seckey_GetKeyType(signalg); |
| 49 | 49 |
| 50 /* verify our key type */ | 50 /* verify our key type */ |
| 51 if (key->keyType != keyType && | 51 if (key->keyType != keyType && |
| 52 » !((key->keyType == dsaKey) && (keyType == fortezzaKey)) ) { | 52 !((key->keyType == dsaKey) && (keyType == fortezzaKey))) { |
| 53 » PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | 53 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
| 54 » return 0; | 54 return 0; |
| 55 } | 55 } |
| 56 | 56 |
| 57 cx = (SGNContext*) PORT_ZAlloc(sizeof(SGNContext)); | 57 cx = (SGNContext *)PORT_ZAlloc(sizeof(SGNContext)); |
| 58 if (cx) { | 58 if (cx) { |
| 59 » cx->hashalg = hashalg; | 59 cx->hashalg = hashalg; |
| 60 » cx->signalg = signalg; | 60 cx->signalg = signalg; |
| 61 » cx->key = key; | 61 cx->key = key; |
| 62 } | 62 } |
| 63 return cx; | 63 return cx; |
| 64 } | 64 } |
| 65 | 65 |
| 66 void | 66 void |
| 67 SGN_DestroyContext(SGNContext *cx, PRBool freeit) | 67 SGN_DestroyContext(SGNContext *cx, PRBool freeit) |
| 68 { | 68 { |
| 69 if (cx) { | 69 if (cx) { |
| 70 » if (cx->hashcx != NULL) { | 70 if (cx->hashcx != NULL) { |
| 71 » (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); | 71 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); |
| 72 » cx->hashcx = NULL; | 72 cx->hashcx = NULL; |
| 73 » } | 73 } |
| 74 » if (freeit) { | 74 if (freeit) { |
| 75 » PORT_ZFree(cx, sizeof(SGNContext)); | 75 PORT_ZFree(cx, sizeof(SGNContext)); |
| 76 » } | 76 } |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 | 79 |
| 80 SECStatus | 80 SECStatus |
| 81 SGN_Begin(SGNContext *cx) | 81 SGN_Begin(SGNContext *cx) |
| 82 { | 82 { |
| 83 if (cx->hashcx != NULL) { | 83 if (cx->hashcx != NULL) { |
| 84 » (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); | 84 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE); |
| 85 » cx->hashcx = NULL; | 85 cx->hashcx = NULL; |
| 86 } | 86 } |
| 87 | 87 |
| 88 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashalg); | 88 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashalg); |
| 89 if (!cx->hashobj) | 89 if (!cx->hashobj) |
| 90 » return SECFailure;» /* error code is already set */ | 90 return SECFailure; /* error code is already set */ |
| 91 | 91 |
| 92 cx->hashcx = (*cx->hashobj->create)(); | 92 cx->hashcx = (*cx->hashobj->create)(); |
| 93 if (cx->hashcx == NULL) | 93 if (cx->hashcx == NULL) |
| 94 » return SECFailure; | 94 return SECFailure; |
| 95 | 95 |
| 96 (*cx->hashobj->begin)(cx->hashcx); | 96 (*cx->hashobj->begin)(cx->hashcx); |
| 97 return SECSuccess; | 97 return SECSuccess; |
| 98 } | 98 } |
| 99 | 99 |
| 100 SECStatus | 100 SECStatus |
| 101 SGN_Update(SGNContext *cx, const unsigned char *input, unsigned int inputLen) | 101 SGN_Update(SGNContext *cx, const unsigned char *input, unsigned int inputLen) |
| 102 { | 102 { |
| 103 if (cx->hashcx == NULL) { | 103 if (cx->hashcx == NULL) { |
| 104 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 104 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 105 » return SECFailure; | 105 return SECFailure; |
| 106 } | 106 } |
| 107 (*cx->hashobj->update)(cx->hashcx, input, inputLen); | 107 (*cx->hashobj->update)(cx->hashcx, input, inputLen); |
| 108 return SECSuccess; | 108 return SECSuccess; |
| 109 } | 109 } |
| 110 | 110 |
| 111 /* XXX Old template; want to expunge it eventually. */ | 111 /* XXX Old template; want to expunge it eventually. */ |
| 112 static DERTemplate SECAlgorithmIDTemplate[] = { | 112 static DERTemplate SECAlgorithmIDTemplate[] = { |
| 113 { DER_SEQUENCE, | 113 { DER_SEQUENCE, |
| 114 » 0, NULL, sizeof(SECAlgorithmID) }, | 114 0, NULL, sizeof(SECAlgorithmID) }, |
| 115 { DER_OBJECT_ID, | 115 { DER_OBJECT_ID, |
| 116 » offsetof(SECAlgorithmID,algorithm), }, | 116 offsetof(SECAlgorithmID, algorithm) }, |
| 117 { DER_OPTIONAL | DER_ANY, | 117 { DER_OPTIONAL | DER_ANY, |
| 118 » offsetof(SECAlgorithmID,parameters), }, | 118 offsetof(SECAlgorithmID, parameters) }, |
| 119 { 0, } | 119 { 0 } |
| 120 }; | 120 }; |
| 121 | 121 |
| 122 /* | 122 /* |
| 123 * XXX OLD Template. Once all uses have been switched over to new one, | 123 * XXX OLD Template. Once all uses have been switched over to new one, |
| 124 * remove this. | 124 * remove this. |
| 125 */ | 125 */ |
| 126 static DERTemplate SGNDigestInfoTemplate[] = { | 126 static DERTemplate SGNDigestInfoTemplate[] = { |
| 127 { DER_SEQUENCE, | 127 { DER_SEQUENCE, |
| 128 » 0, NULL, sizeof(SGNDigestInfo) }, | 128 0, NULL, sizeof(SGNDigestInfo) }, |
| 129 { DER_INLINE, | 129 { DER_INLINE, |
| 130 » offsetof(SGNDigestInfo,digestAlgorithm), | 130 offsetof(SGNDigestInfo, digestAlgorithm), |
| 131 » SECAlgorithmIDTemplate, }, | 131 SECAlgorithmIDTemplate }, |
| 132 { DER_OCTET_STRING, | 132 { DER_OCTET_STRING, |
| 133 » offsetof(SGNDigestInfo,digest), }, | 133 offsetof(SGNDigestInfo, digest) }, |
| 134 { 0, } | 134 { 0 } |
| 135 }; | 135 }; |
| 136 | 136 |
| 137 SECStatus | 137 SECStatus |
| 138 SGN_End(SGNContext *cx, SECItem *result) | 138 SGN_End(SGNContext *cx, SECItem *result) |
| 139 { | 139 { |
| 140 unsigned char digest[HASH_LENGTH_MAX]; | 140 unsigned char digest[HASH_LENGTH_MAX]; |
| 141 unsigned part1; | 141 unsigned part1; |
| 142 int signatureLen; | 142 int signatureLen; |
| 143 SECStatus rv; | 143 SECStatus rv; |
| 144 SECItem digder, sigitem; | 144 SECItem digder, sigitem; |
| 145 PLArenaPool *arena = 0; | 145 PLArenaPool *arena = 0; |
| 146 SECKEYPrivateKey *privKey = cx->key; | 146 SECKEYPrivateKey *privKey = cx->key; |
| 147 SGNDigestInfo *di = 0; | 147 SGNDigestInfo *di = 0; |
| 148 | 148 |
| 149 result->data = 0; | 149 result->data = 0; |
| 150 digder.data = 0; | 150 digder.data = 0; |
| 151 | 151 |
| 152 /* Finish up digest function */ | 152 /* Finish up digest function */ |
| 153 if (cx->hashcx == NULL) { | 153 if (cx->hashcx == NULL) { |
| 154 » PORT_SetError(SEC_ERROR_INVALID_ARGS); | 154 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 155 » return SECFailure; | 155 return SECFailure; |
| 156 } | 156 } |
| 157 (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest)); | 157 (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest)); |
| 158 | 158 |
| 159 | |
| 160 if (privKey->keyType == rsaKey) { | 159 if (privKey->keyType == rsaKey) { |
| 161 | 160 |
| 162 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 161 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 163 » if ( !arena ) { | 162 if (!arena) { |
| 164 » rv = SECFailure; | 163 rv = SECFailure; |
| 165 » goto loser; | 164 goto loser; |
| 166 » } | 165 } |
| 167 | |
| 168 » /* Construct digest info */ | |
| 169 » di = SGN_CreateDigestInfo(cx->hashalg, digest, part1); | |
| 170 » if (!di) { | |
| 171 » rv = SECFailure; | |
| 172 » goto loser; | |
| 173 » } | |
| 174 | 166 |
| 175 » /* Der encode the digest as a DigestInfo */ | 167 /* Construct digest info */ |
| 168 di = SGN_CreateDigestInfo(cx->hashalg, digest, part1); |
| 169 if (!di) { |
| 170 rv = SECFailure; |
| 171 goto loser; |
| 172 } |
| 173 |
| 174 /* Der encode the digest as a DigestInfo */ |
| 176 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, | 175 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, |
| 177 di); | 176 di); |
| 178 » if (rv != SECSuccess) { | 177 if (rv != SECSuccess) { |
| 179 » goto loser; | 178 goto loser; |
| 180 » } | 179 } |
| 181 } else { | 180 } else { |
| 182 » digder.data = digest; | 181 digder.data = digest; |
| 183 » digder.len = part1; | 182 digder.len = part1; |
| 184 } | 183 } |
| 185 | 184 |
| 186 /* | 185 /* |
| 187 ** Encrypt signature after constructing appropriate PKCS#1 signature | 186 ** Encrypt signature after constructing appropriate PKCS#1 signature |
| 188 ** block | 187 ** block |
| 189 */ | 188 */ |
| 190 signatureLen = PK11_SignatureLen(privKey); | 189 signatureLen = PK11_SignatureLen(privKey); |
| 191 if (signatureLen <= 0) { | 190 if (signatureLen <= 0) { |
| 192 » PORT_SetError(SEC_ERROR_INVALID_KEY); | 191 PORT_SetError(SEC_ERROR_INVALID_KEY); |
| 193 » rv = SECFailure; | 192 rv = SECFailure; |
| 194 » goto loser; | 193 goto loser; |
| 195 } | 194 } |
| 196 sigitem.len = signatureLen; | 195 sigitem.len = signatureLen; |
| 197 sigitem.data = (unsigned char*) PORT_Alloc(signatureLen); | 196 sigitem.data = (unsigned char *)PORT_Alloc(signatureLen); |
| 198 | 197 |
| 199 if (sigitem.data == NULL) { | 198 if (sigitem.data == NULL) { |
| 200 » rv = SECFailure; | 199 rv = SECFailure; |
| 201 » goto loser; | 200 goto loser; |
| 202 } | 201 } |
| 203 | 202 |
| 204 rv = PK11_Sign(privKey, &sigitem, &digder); | 203 rv = PK11_Sign(privKey, &sigitem, &digder); |
| 205 if (rv != SECSuccess) { | 204 if (rv != SECSuccess) { |
| 206 » PORT_Free(sigitem.data); | 205 PORT_Free(sigitem.data); |
| 207 » sigitem.data = NULL; | 206 sigitem.data = NULL; |
| 208 » goto loser; | 207 goto loser; |
| 209 } | 208 } |
| 210 | 209 |
| 211 if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || | 210 if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || |
| 212 (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { | 211 (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { |
| 213 /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ | 212 /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ |
| 214 » rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len); | 213 rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len); |
| 215 » PORT_Free(sigitem.data); | 214 PORT_Free(sigitem.data); |
| 216 » if (rv != SECSuccess) | 215 if (rv != SECSuccess) |
| 217 » goto loser; | 216 goto loser; |
| 218 } else { | 217 } else { |
| 219 » result->len = sigitem.len; | 218 result->len = sigitem.len; |
| 220 » result->data = sigitem.data; | 219 result->data = sigitem.data; |
| 221 } | 220 } |
| 222 | 221 |
| 223 loser: | 222 loser: |
| 224 SGN_DestroyDigestInfo(di); | 223 SGN_DestroyDigestInfo(di); |
| 225 if (arena != NULL) { | 224 if (arena != NULL) { |
| 226 » PORT_FreeArena(arena, PR_FALSE); | 225 PORT_FreeArena(arena, PR_FALSE); |
| 227 } | 226 } |
| 228 return rv; | 227 return rv; |
| 229 } | 228 } |
| 230 | 229 |
| 231 /************************************************************************/ | 230 /************************************************************************/ |
| 232 | 231 |
| 233 /* | 232 /* |
| 234 ** Sign a block of data returning in result a bunch of bytes that are the | 233 ** Sign a block of data returning in result a bunch of bytes that are the |
| 235 ** signature. Returns zero on success, an error code on failure. | 234 ** signature. Returns zero on success, an error code on failure. |
| 236 */ | 235 */ |
| 237 SECStatus | 236 SECStatus |
| 238 SEC_SignData(SECItem *res, const unsigned char *buf, int len, | 237 SEC_SignData(SECItem *res, const unsigned char *buf, int len, |
| 239 » SECKEYPrivateKey *pk, SECOidTag algid) | 238 SECKEYPrivateKey *pk, SECOidTag algid) |
| 240 { | 239 { |
| 241 SECStatus rv; | 240 SECStatus rv; |
| 242 SGNContext *sgn; | 241 SGNContext *sgn; |
| 243 | 242 |
| 244 | |
| 245 sgn = SGN_NewContext(algid, pk); | 243 sgn = SGN_NewContext(algid, pk); |
| 246 | 244 |
| 247 if (sgn == NULL) | 245 if (sgn == NULL) |
| 248 » return SECFailure; | 246 return SECFailure; |
| 249 | 247 |
| 250 rv = SGN_Begin(sgn); | 248 rv = SGN_Begin(sgn); |
| 251 if (rv != SECSuccess) | 249 if (rv != SECSuccess) |
| 252 » goto loser; | 250 goto loser; |
| 253 | 251 |
| 254 rv = SGN_Update(sgn, buf, len); | 252 rv = SGN_Update(sgn, buf, len); |
| 255 if (rv != SECSuccess) | 253 if (rv != SECSuccess) |
| 256 » goto loser; | 254 goto loser; |
| 257 | 255 |
| 258 rv = SGN_End(sgn, res); | 256 rv = SGN_End(sgn, res); |
| 259 | 257 |
| 260 loser: | 258 loser: |
| 261 SGN_DestroyContext(sgn, PR_TRUE); | 259 SGN_DestroyContext(sgn, PR_TRUE); |
| 262 return rv; | 260 return rv; |
| 263 } | 261 } |
| 264 | 262 |
| 265 /************************************************************************/ | 263 /************************************************************************/ |
| 266 | 264 |
| 267 DERTemplate CERTSignedDataTemplate[] = | 265 DERTemplate CERTSignedDataTemplate[] = |
| 268 { | 266 { |
| 269 { DER_SEQUENCE, | 267 { DER_SEQUENCE, |
| 270 » 0, NULL, sizeof(CERTSignedData) }, | 268 0, NULL, sizeof(CERTSignedData) }, |
| 271 { DER_ANY, | 269 { DER_ANY, |
| 272 » offsetof(CERTSignedData,data), }, | 270 offsetof(CERTSignedData, data) }, |
| 273 { DER_INLINE, | 271 { DER_INLINE, |
| 274 » offsetof(CERTSignedData,signatureAlgorithm), | 272 offsetof(CERTSignedData, signatureAlgorithm), |
| 275 » SECAlgorithmIDTemplate, }, | 273 SECAlgorithmIDTemplate }, |
| 276 { DER_BIT_STRING, | 274 { DER_BIT_STRING, |
| 277 » offsetof(CERTSignedData,signature), }, | 275 offsetof(CERTSignedData, signature) }, |
| 278 { 0, } | 276 { 0 } |
| 279 }; | 277 }; |
| 280 | 278 |
| 281 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | 279 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
| 282 | 280 |
| 283 const SEC_ASN1Template CERT_SignedDataTemplate[] = | 281 const SEC_ASN1Template CERT_SignedDataTemplate[] = |
| 284 { | 282 { |
| 285 { SEC_ASN1_SEQUENCE, | 283 { SEC_ASN1_SEQUENCE, |
| 286 » 0, NULL, sizeof(CERTSignedData) }, | 284 0, NULL, sizeof(CERTSignedData) }, |
| 287 { SEC_ASN1_ANY, | 285 { SEC_ASN1_ANY, |
| 288 » offsetof(CERTSignedData,data), }, | 286 offsetof(CERTSignedData, data) }, |
| 289 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | 287 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
| 290 » offsetof(CERTSignedData,signatureAlgorithm), | 288 offsetof(CERTSignedData, signatureAlgorithm), |
| 291 » SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), }, | 289 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
| 292 { SEC_ASN1_BIT_STRING, | 290 { SEC_ASN1_BIT_STRING, |
| 293 » offsetof(CERTSignedData,signature), }, | 291 offsetof(CERTSignedData, signature) }, |
| 294 { 0, } | 292 { 0 } |
| 295 }; | 293 }; |
| 296 | 294 |
| 297 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate) | 295 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate) |
| 298 | 296 |
| 299 | |
| 300 SECStatus | 297 SECStatus |
| 301 SEC_DerSignData(PLArenaPool *arena, SECItem *result, | 298 SEC_DerSignData(PLArenaPool *arena, SECItem *result, |
| 302 » const unsigned char *buf, int len, SECKEYPrivateKey *pk, | 299 const unsigned char *buf, int len, SECKEYPrivateKey *pk, |
| 303 » SECOidTag algID) | 300 SECOidTag algID) |
| 304 { | 301 { |
| 305 SECItem it; | 302 SECItem it; |
| 306 CERTSignedData sd; | 303 CERTSignedData sd; |
| 307 SECStatus rv; | 304 SECStatus rv; |
| 308 | 305 |
| 309 it.data = 0; | 306 it.data = 0; |
| 310 | 307 |
| 311 /* XXX We should probably have some asserts here to make sure the key type | 308 /* XXX We should probably have some asserts here to make sure the key type |
| 312 * and algID match | 309 * and algID match |
| 313 */ | 310 */ |
| 314 | 311 |
| 315 if (algID == SEC_OID_UNKNOWN) { | 312 if (algID == SEC_OID_UNKNOWN) { |
| 316 » switch(pk->keyType) { | 313 switch (pk->keyType) { |
| 317 » case rsaKey: | 314 case rsaKey: |
| 318 » algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; | 315 algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
| 319 » break; | 316 break; |
| 320 » case dsaKey: | 317 case dsaKey: |
| 321 » /* get Signature length (= q_len*2) and work from there */ | 318 /* get Signature length (= q_len*2) and work from there */ |
| 322 » switch (PK11_SignatureLen(pk)) { | 319 switch (PK11_SignatureLen(pk)) { |
| 323 » » case 448: | 320 case 448: |
| 324 » » algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; | 321 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; |
| 325 » » break; | 322 break; |
| 326 » » case 512: | 323 case 512: |
| 327 » » algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; | 324 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; |
| 328 » » break; | 325 break; |
| 329 » » default: | 326 default: |
| 330 » » algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; | 327 algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; |
| 331 » » break; | 328 break; |
| 332 » } | 329 } |
| 333 » break; | 330 break; |
| 334 » case ecKey: | 331 case ecKey: |
| 335 » algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; | 332 algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; |
| 336 » break; | 333 break; |
| 337 » default: | 334 default: |
| 338 » PORT_SetError(SEC_ERROR_INVALID_KEY); | 335 PORT_SetError(SEC_ERROR_INVALID_KEY); |
| 339 » return SECFailure; | 336 return SECFailure; |
| 340 » } | 337 } |
| 341 } | 338 } |
| 342 | 339 |
| 343 /* Sign input buffer */ | 340 /* Sign input buffer */ |
| 344 rv = SEC_SignData(&it, buf, len, pk, algID); | 341 rv = SEC_SignData(&it, buf, len, pk, algID); |
| 345 if (rv) goto loser; | 342 if (rv) |
| 343 goto loser; |
| 346 | 344 |
| 347 /* Fill out SignedData object */ | 345 /* Fill out SignedData object */ |
| 348 PORT_Memset(&sd, 0, sizeof(sd)); | 346 PORT_Memset(&sd, 0, sizeof(sd)); |
| 349 sd.data.data = (unsigned char*) buf; | 347 sd.data.data = (unsigned char *)buf; |
| 350 sd.data.len = len; | 348 sd.data.len = len; |
| 351 sd.signature.data = it.data; | 349 sd.signature.data = it.data; |
| 352 sd.signature.len = it.len << 3;» » /* convert to bit string */ | 350 sd.signature.len = it.len << 3; /* convert to bit string */ |
| 353 rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0); | 351 rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0); |
| 354 if (rv) goto loser; | 352 if (rv) |
| 353 goto loser; |
| 355 | 354 |
| 356 /* DER encode the signed data object */ | 355 /* DER encode the signed data object */ |
| 357 rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd); | 356 rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd); |
| 358 /* FALL THROUGH */ | 357 /* FALL THROUGH */ |
| 359 | 358 |
| 360 loser: | 359 loser: |
| 361 PORT_Free(it.data); | 360 PORT_Free(it.data); |
| 362 return rv; | 361 return rv; |
| 363 } | 362 } |
| 364 | 363 |
| 365 SECStatus | 364 SECStatus |
| 366 SGN_Digest(SECKEYPrivateKey *privKey, | 365 SGN_Digest(SECKEYPrivateKey *privKey, |
| 367 » » SECOidTag algtag, SECItem *result, SECItem *digest) | 366 SECOidTag algtag, SECItem *result, SECItem *digest) |
| 368 { | 367 { |
| 369 int modulusLen; | 368 int modulusLen; |
| 370 SECStatus rv; | 369 SECStatus rv; |
| 371 SECItem digder; | 370 SECItem digder; |
| 372 PLArenaPool *arena = 0; | 371 PLArenaPool *arena = 0; |
| 373 SGNDigestInfo *di = 0; | 372 SGNDigestInfo *di = 0; |
| 374 | 373 |
| 375 | |
| 376 result->data = 0; | 374 result->data = 0; |
| 377 | 375 |
| 378 if (privKey->keyType == rsaKey) { | 376 if (privKey->keyType == rsaKey) { |
| 379 | 377 |
| 380 » arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 378 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 381 » if ( !arena ) { | 379 if (!arena) { |
| 382 » rv = SECFailure; | 380 rv = SECFailure; |
| 383 » goto loser; | 381 goto loser; |
| 384 » } | 382 } |
| 385 | |
| 386 » /* Construct digest info */ | |
| 387 » di = SGN_CreateDigestInfo(algtag, digest->data, digest->len); | |
| 388 » if (!di) { | |
| 389 » rv = SECFailure; | |
| 390 » goto loser; | |
| 391 » } | |
| 392 | 383 |
| 393 » /* Der encode the digest as a DigestInfo */ | 384 /* Construct digest info */ |
| 385 di = SGN_CreateDigestInfo(algtag, digest->data, digest->len); |
| 386 if (!di) { |
| 387 rv = SECFailure; |
| 388 goto loser; |
| 389 } |
| 390 |
| 391 /* Der encode the digest as a DigestInfo */ |
| 394 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, | 392 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, |
| 395 di); | 393 di); |
| 396 » if (rv != SECSuccess) { | 394 if (rv != SECSuccess) { |
| 397 » goto loser; | 395 goto loser; |
| 398 » } | 396 } |
| 399 } else { | 397 } else { |
| 400 » digder.data = digest->data; | 398 digder.data = digest->data; |
| 401 » digder.len = digest->len; | 399 digder.len = digest->len; |
| 402 } | 400 } |
| 403 | 401 |
| 404 /* | 402 /* |
| 405 ** Encrypt signature after constructing appropriate PKCS#1 signature | 403 ** Encrypt signature after constructing appropriate PKCS#1 signature |
| 406 ** block | 404 ** block |
| 407 */ | 405 */ |
| 408 modulusLen = PK11_SignatureLen(privKey); | 406 modulusLen = PK11_SignatureLen(privKey); |
| 409 if (modulusLen <= 0) { | 407 if (modulusLen <= 0) { |
| 410 » PORT_SetError(SEC_ERROR_INVALID_KEY); | 408 PORT_SetError(SEC_ERROR_INVALID_KEY); |
| 411 » rv = SECFailure; | 409 rv = SECFailure; |
| 412 » goto loser; | 410 goto loser; |
| 413 } | 411 } |
| 414 result->len = modulusLen; | 412 result->len = modulusLen; |
| 415 result->data = (unsigned char*) PORT_Alloc(modulusLen); | 413 result->data = (unsigned char *)PORT_Alloc(modulusLen); |
| 416 result->type = siBuffer; | 414 result->type = siBuffer; |
| 417 | 415 |
| 418 if (result->data == NULL) { | 416 if (result->data == NULL) { |
| 419 » rv = SECFailure; | 417 rv = SECFailure; |
| 420 » goto loser; | 418 goto loser; |
| 421 } | 419 } |
| 422 | 420 |
| 423 rv = PK11_Sign(privKey, result, &digder); | 421 rv = PK11_Sign(privKey, result, &digder); |
| 424 if (rv != SECSuccess) { | 422 if (rv != SECSuccess) { |
| 425 » PORT_Free(result->data); | 423 PORT_Free(result->data); |
| 426 » result->data = NULL; | 424 result->data = NULL; |
| 427 } | 425 } |
| 428 | 426 |
| 429 loser: | 427 loser: |
| 430 SGN_DestroyDigestInfo(di); | 428 SGN_DestroyDigestInfo(di); |
| 431 if (arena != NULL) { | 429 if (arena != NULL) { |
| 432 » PORT_FreeArena(arena, PR_FALSE); | 430 PORT_FreeArena(arena, PR_FALSE); |
| 433 } | 431 } |
| 434 return rv; | 432 return rv; |
| 435 } | 433 } |
| 436 | 434 |
| 437 SECOidTag | 435 SECOidTag |
| 438 SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag) | 436 SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag) |
| 439 { | 437 { |
| 440 SECOidTag sigTag = SEC_OID_UNKNOWN; | 438 SECOidTag sigTag = SEC_OID_UNKNOWN; |
| 441 | 439 |
| 442 switch (keyType) { | 440 switch (keyType) { |
| 443 case rsaKey: | 441 case rsaKey: |
| 444 » switch (hashAlgTag) { | 442 switch (hashAlgTag) { |
| 445 » case SEC_OID_MD2: | 443 case SEC_OID_MD2: |
| 446 » sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;» break; | 444 sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; |
| 447 » case SEC_OID_MD5: | 445 break; |
| 448 » sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;» break; | 446 case SEC_OID_MD5: |
| 449 » case SEC_OID_SHA1: | 447 sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; |
| 450 » sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;» break; | 448 break; |
| 451 » case SEC_OID_SHA224: | 449 case SEC_OID_SHA1: |
| 452 » sigTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;» break; | 450 sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; |
| 453 » case SEC_OID_UNKNOWN:» /* default for RSA if not specified */ | 451 break; |
| 454 » case SEC_OID_SHA256: | 452 case SEC_OID_SHA224: |
| 455 » sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;» break; | 453 sigTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; |
| 456 » case SEC_OID_SHA384: | 454 break; |
| 457 » sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;» break; | 455 case SEC_OID_UNKNOWN: /* default for RSA if not specified */ |
| 458 » case SEC_OID_SHA512: | 456 case SEC_OID_SHA256: |
| 459 » sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;» break; | 457 sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
| 460 » default: | 458 break; |
| 461 » break; | 459 case SEC_OID_SHA384: |
| 462 » } | 460 sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; |
| 463 » break; | 461 break; |
| 464 case dsaKey: | 462 case SEC_OID_SHA512: |
| 465 » switch (hashAlgTag) { | 463 sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; |
| 466 » case SEC_OID_UNKNOWN:» /* default for DSA if not specified */ | 464 break; |
| 467 » case SEC_OID_SHA1: | 465 default: |
| 468 » sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break; | 466 break; |
| 469 » case SEC_OID_SHA224: | 467 } |
| 470 » sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; break; | 468 break; |
| 471 » case SEC_OID_SHA256: | 469 case dsaKey: |
| 472 » sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; break; | 470 switch (hashAlgTag) { |
| 473 » default: | 471 case SEC_OID_UNKNOWN: /* default for DSA if not specified */ |
| 474 » break; | 472 case SEC_OID_SHA1: |
| 475 » } | 473 sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; |
| 476 » break; | 474 break; |
| 477 case ecKey: | 475 case SEC_OID_SHA224: |
| 478 » switch (hashAlgTag) { | 476 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; |
| 479 » case SEC_OID_UNKNOWN:» /* default for ECDSA if not specified */ | 477 break; |
| 480 » case SEC_OID_SHA1: | 478 case SEC_OID_SHA256: |
| 481 sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; break; | 479 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; |
| 482 » case SEC_OID_SHA224: | 480 break; |
| 483 sigTag = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE; break; | 481 default: |
| 484 » case SEC_OID_SHA256: | 482 break; |
| 485 sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; break; | 483 } |
| 486 » case SEC_OID_SHA384: | 484 break; |
| 487 sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; break; | 485 case ecKey: |
| 488 » case SEC_OID_SHA512: | 486 switch (hashAlgTag) { |
| 489 sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; break; | 487 case SEC_OID_UNKNOWN: /* default for ECDSA if not specified */ |
| 490 » default: | 488 case SEC_OID_SHA1: |
| 491 » break; | 489 sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; |
| 492 » } | 490 break; |
| 493 default: | 491 case SEC_OID_SHA224: |
| 494 » break; | 492 sigTag = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE; |
| 493 break; |
| 494 case SEC_OID_SHA256: |
| 495 sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; |
| 496 break; |
| 497 case SEC_OID_SHA384: |
| 498 sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; |
| 499 break; |
| 500 case SEC_OID_SHA512: |
| 501 sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; |
| 502 break; |
| 503 default: |
| 504 break; |
| 505 } |
| 506 default: |
| 507 break; |
| 495 } | 508 } |
| 496 return sigTag; | 509 return sigTag; |
| 497 } | 510 } |
| OLD | NEW |