1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/cryptohi/seckey.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1891 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "cryptohi.h" 1.8 +#include "keyhi.h" 1.9 +#include "secoid.h" 1.10 +#include "secitem.h" 1.11 +#include "secder.h" 1.12 +#include "base64.h" 1.13 +#include "secasn1.h" 1.14 +#include "cert.h" 1.15 +#include "pk11func.h" 1.16 +#include "secerr.h" 1.17 +#include "secdig.h" 1.18 +#include "prtime.h" 1.19 +#include "keyi.h" 1.20 + 1.21 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1.22 +SEC_ASN1_MKSUB(SEC_IntegerTemplate) 1.23 + 1.24 +const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = { 1.25 + { SEC_ASN1_SEQUENCE, 1.26 + 0, NULL, sizeof(CERTSubjectPublicKeyInfo) }, 1.27 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.28 + offsetof(CERTSubjectPublicKeyInfo,algorithm), 1.29 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.30 + { SEC_ASN1_BIT_STRING, 1.31 + offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), }, 1.32 + { 0, } 1.33 +}; 1.34 + 1.35 +const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] = 1.36 +{ 1.37 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) }, 1.38 + { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) }, 1.39 + { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) }, 1.40 + { 0 } 1.41 +}; 1.42 + 1.43 +const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = { 1.44 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) }, 1.45 + { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), }, 1.46 + { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), }, 1.47 + { 0, } 1.48 +}; 1.49 + 1.50 +static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = { 1.51 + { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0, 1.52 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) } 1.53 +}; 1.54 + 1.55 +/* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */ 1.56 +const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] = 1.57 +{ 1.58 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) }, 1.59 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1.60 + SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.61 + offsetof(SECKEYRSAPSSParams, hashAlg), 1.62 + seckey_PointerToAlgorithmIDTemplate }, 1.63 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1.64 + SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.65 + offsetof(SECKEYRSAPSSParams, maskAlg), 1.66 + seckey_PointerToAlgorithmIDTemplate }, 1.67 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1.68 + SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2, 1.69 + offsetof(SECKEYRSAPSSParams, saltLength), 1.70 + SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1.71 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1.72 + SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3, 1.73 + offsetof(SECKEYRSAPSSParams, trailerField), 1.74 + SEC_ASN1_SUB(SEC_IntegerTemplate) }, 1.75 + { 0 } 1.76 +}; 1.77 + 1.78 +const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = { 1.79 + { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), }, 1.80 + { 0, } 1.81 +}; 1.82 + 1.83 +const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { 1.84 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, 1.85 + { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) }, 1.86 + { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) }, 1.87 + { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) }, 1.88 + { 0, } 1.89 +}; 1.90 + 1.91 +const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = { 1.92 + { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), }, 1.93 + { 0, } 1.94 +}; 1.95 + 1.96 +const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = { 1.97 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) }, 1.98 + { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), }, 1.99 + { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), }, 1.100 + /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */ 1.101 + { SEC_ASN1_SKIP_REST }, 1.102 + { 0, } 1.103 +}; 1.104 + 1.105 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate) 1.106 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate) 1.107 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate) 1.108 +SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate) 1.109 + 1.110 +/* 1.111 + * See bugzilla bug 125359 1.112 + * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, 1.113 + * all of the templates above that en/decode into integers must be converted 1.114 + * from ASN.1's signed integer type. This is done by marking either the 1.115 + * source or destination (encoding or decoding, respectively) type as 1.116 + * siUnsignedInteger. 1.117 + */ 1.118 +static void 1.119 +prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk) 1.120 +{ 1.121 + pubk->u.rsa.modulus.type = siUnsignedInteger; 1.122 + pubk->u.rsa.publicExponent.type = siUnsignedInteger; 1.123 +} 1.124 + 1.125 +static void 1.126 +prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk) 1.127 +{ 1.128 + pubk->u.dsa.publicValue.type = siUnsignedInteger; 1.129 +} 1.130 + 1.131 +static void 1.132 +prepare_pqg_params_for_asn1(SECKEYPQGParams *params) 1.133 +{ 1.134 + params->prime.type = siUnsignedInteger; 1.135 + params->subPrime.type = siUnsignedInteger; 1.136 + params->base.type = siUnsignedInteger; 1.137 +} 1.138 + 1.139 +static void 1.140 +prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk) 1.141 +{ 1.142 + pubk->u.dh.prime.type = siUnsignedInteger; 1.143 + pubk->u.dh.base.type = siUnsignedInteger; 1.144 + pubk->u.dh.publicValue.type = siUnsignedInteger; 1.145 +} 1.146 + 1.147 +/* Create an RSA key pair is any slot able to do so. 1.148 +** The created keys are "session" (temporary), not "token" (permanent), 1.149 +** and they are "sensitive", which makes them costly to move to another token. 1.150 +*/ 1.151 +SECKEYPrivateKey * 1.152 +SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx) 1.153 +{ 1.154 + SECKEYPrivateKey *privk; 1.155 + PK11RSAGenParams param; 1.156 + PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx); 1.157 + if (!slot) { 1.158 + return NULL; 1.159 + } 1.160 + 1.161 + param.keySizeInBits = keySizeInBits; 1.162 + param.pe = 65537L; 1.163 + 1.164 + privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,¶m,pubk, 1.165 + PR_FALSE, PR_TRUE, cx); 1.166 + PK11_FreeSlot(slot); 1.167 + return(privk); 1.168 +} 1.169 + 1.170 +/* Create a DH key pair in any slot able to do so, 1.171 +** This is a "session" (temporary), not "token" (permanent) key. 1.172 +** Because of the high probability that this key will need to be moved to 1.173 +** another token, and the high cost of moving "sensitive" keys, we attempt 1.174 +** to create this key pair without the "sensitive" attribute, but revert to 1.175 +** creating a "sensitive" key if necessary. 1.176 +*/ 1.177 +SECKEYPrivateKey * 1.178 +SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx) 1.179 +{ 1.180 + SECKEYPrivateKey *privk; 1.181 + PK11SlotInfo *slot; 1.182 + 1.183 + if (!param || !param->base.data || !param->prime.data || 1.184 + param->prime.len < 512/8 || param->base.len == 0 || 1.185 + param->base.len > param->prime.len + 1 || 1.186 + (param->base.len == 1 && param->base.data[0] == 0)) { 1.187 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.188 + return NULL; 1.189 + } 1.190 + 1.191 + slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx); 1.192 + if (!slot) { 1.193 + return NULL; 1.194 + } 1.195 + 1.196 + privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 1.197 + pubk, PR_FALSE, PR_FALSE, cx); 1.198 + if (!privk) 1.199 + privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 1.200 + pubk, PR_FALSE, PR_TRUE, cx); 1.201 + 1.202 + PK11_FreeSlot(slot); 1.203 + return(privk); 1.204 +} 1.205 + 1.206 +/* Create an EC key pair in any slot able to do so, 1.207 +** This is a "session" (temporary), not "token" (permanent) key. 1.208 +** Because of the high probability that this key will need to be moved to 1.209 +** another token, and the high cost of moving "sensitive" keys, we attempt 1.210 +** to create this key pair without the "sensitive" attribute, but revert to 1.211 +** creating a "sensitive" key if necessary. 1.212 +*/ 1.213 +SECKEYPrivateKey * 1.214 +SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx) 1.215 +{ 1.216 + SECKEYPrivateKey *privk; 1.217 + PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx); 1.218 + if (!slot) { 1.219 + return NULL; 1.220 + } 1.221 + 1.222 + privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, 1.223 + param, pubk, 1.224 + PK11_ATTR_SESSION | PK11_ATTR_INSENSITIVE | 1.225 + PK11_ATTR_PUBLIC, 1.226 + CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx); 1.227 + if (!privk) 1.228 + privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, 1.229 + param, pubk, 1.230 + PK11_ATTR_SESSION | PK11_ATTR_SENSITIVE | 1.231 + PK11_ATTR_PRIVATE, 1.232 + CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx); 1.233 + 1.234 + PK11_FreeSlot(slot); 1.235 + return(privk); 1.236 +} 1.237 + 1.238 +void 1.239 +SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk) 1.240 +{ 1.241 + if (privk) { 1.242 + if (privk->pkcs11Slot) { 1.243 + if (privk->pkcs11IsTemp) { 1.244 + PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID); 1.245 + } 1.246 + PK11_FreeSlot(privk->pkcs11Slot); 1.247 + 1.248 + } 1.249 + if (privk->arena) { 1.250 + PORT_FreeArena(privk->arena, PR_TRUE); 1.251 + } 1.252 + } 1.253 +} 1.254 + 1.255 +void 1.256 +SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk) 1.257 +{ 1.258 + if (pubk) { 1.259 + if (pubk->pkcs11Slot) { 1.260 + if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) { 1.261 + PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID); 1.262 + } 1.263 + PK11_FreeSlot(pubk->pkcs11Slot); 1.264 + } 1.265 + if (pubk->arena) { 1.266 + PORT_FreeArena(pubk->arena, PR_FALSE); 1.267 + } 1.268 + } 1.269 +} 1.270 + 1.271 +SECStatus 1.272 +SECKEY_CopySubjectPublicKeyInfo(PLArenaPool *arena, 1.273 + CERTSubjectPublicKeyInfo *to, 1.274 + CERTSubjectPublicKeyInfo *from) 1.275 +{ 1.276 + SECStatus rv; 1.277 + SECItem spk; 1.278 + 1.279 + rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm); 1.280 + if (rv == SECSuccess) { 1.281 + /* 1.282 + * subjectPublicKey is a bit string, whose length is in bits. 1.283 + * Convert the length from bits to bytes for SECITEM_CopyItem. 1.284 + */ 1.285 + spk = from->subjectPublicKey; 1.286 + DER_ConvertBitString(&spk); 1.287 + rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk); 1.288 + /* Set the length back to bits. */ 1.289 + if (rv == SECSuccess) { 1.290 + to->subjectPublicKey.len = from->subjectPublicKey.len; 1.291 + } 1.292 + } 1.293 + 1.294 + return rv; 1.295 +} 1.296 + 1.297 +/* Procedure to update the pqg parameters for a cert's public key. 1.298 + * pqg parameters only need to be updated for DSA certificates. 1.299 + * The procedure uses calls to itself recursively to update a certificate 1.300 + * issuer's pqg parameters. Some important rules are: 1.301 + * - Do nothing if the cert already has PQG parameters. 1.302 + * - If the cert does not have PQG parameters, obtain them from the issuer. 1.303 + * - A valid cert chain cannot have a DSA cert without 1.304 + * pqg parameters that has a parent that is not a DSA cert. */ 1.305 + 1.306 +static SECStatus 1.307 +seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count) 1.308 +{ 1.309 + SECStatus rv; 1.310 + SECOidData *oid=NULL; 1.311 + int tag; 1.312 + CERTSubjectPublicKeyInfo * subjectSpki=NULL; 1.313 + CERTSubjectPublicKeyInfo * issuerSpki=NULL; 1.314 + CERTCertificate *issuerCert = NULL; 1.315 + 1.316 + rv = SECSuccess; 1.317 + 1.318 + /* increment cert chain length counter*/ 1.319 + count++; 1.320 + 1.321 + /* check if cert chain length exceeds the maximum length*/ 1.322 + if (count > CERT_MAX_CERT_CHAIN) { 1.323 + return SECFailure; 1.324 + } 1.325 + 1.326 + oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm); 1.327 + if (oid != NULL) { 1.328 + tag = oid->offset; 1.329 + 1.330 + /* Check if cert has a DSA or EC public key. If not, return 1.331 + * success since no PQG params need to be updated. 1.332 + * 1.333 + * Question: do we really need to do this for EC keys. They don't have 1.334 + * PQG parameters, but they do have parameters. The question is does 1.335 + * the child cert inherit thost parameters for EC from the parent, or 1.336 + * do we always include those parameters in each cert. 1.337 + */ 1.338 + 1.339 + if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) && 1.340 + (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) && 1.341 + (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) && 1.342 + (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && 1.343 + (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && 1.344 + (tag != SEC_OID_SDN702_DSA_SIGNATURE) && 1.345 + (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { 1.346 + 1.347 + return SECSuccess; 1.348 + } 1.349 + } else { 1.350 + return SECFailure; /* return failure if oid is NULL */ 1.351 + } 1.352 + 1.353 + /* if cert has PQG parameters, return success */ 1.354 + 1.355 + subjectSpki=&subjectCert->subjectPublicKeyInfo; 1.356 + 1.357 + if (subjectSpki->algorithm.parameters.len != 0) { 1.358 + return SECSuccess; 1.359 + } 1.360 + 1.361 + /* check if the cert is self-signed */ 1.362 + if (subjectCert->isRoot) { 1.363 + /* fail since cert is self-signed and has no pqg params. */ 1.364 + return SECFailure; 1.365 + } 1.366 + 1.367 + /* get issuer cert */ 1.368 + issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA); 1.369 + if ( ! issuerCert ) { 1.370 + return SECFailure; 1.371 + } 1.372 + 1.373 + /* if parent is not DSA, return failure since 1.374 + we don't allow this case. */ 1.375 + 1.376 + oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm); 1.377 + if (oid != NULL) { 1.378 + tag = oid->offset; 1.379 + 1.380 + /* Check if issuer cert has a DSA public key. If not, 1.381 + * return failure. */ 1.382 + 1.383 + if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) && 1.384 + (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) && 1.385 + (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) && 1.386 + (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && 1.387 + (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && 1.388 + (tag != SEC_OID_SDN702_DSA_SIGNATURE) && 1.389 + (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { 1.390 + rv = SECFailure; 1.391 + goto loser; 1.392 + } 1.393 + } else { 1.394 + rv = SECFailure; /* return failure if oid is NULL */ 1.395 + goto loser; 1.396 + } 1.397 + 1.398 + 1.399 + /* at this point the subject cert has no pqg parameters and the 1.400 + * issuer cert has a DSA public key. Update the issuer's 1.401 + * pqg parameters with a recursive call to this same function. */ 1.402 + 1.403 + rv = seckey_UpdateCertPQGChain(issuerCert, count); 1.404 + if (rv != SECSuccess) { 1.405 + rv = SECFailure; 1.406 + goto loser; 1.407 + } 1.408 + 1.409 + /* ensure issuer has pqg parameters */ 1.410 + 1.411 + issuerSpki=&issuerCert->subjectPublicKeyInfo; 1.412 + if (issuerSpki->algorithm.parameters.len == 0) { 1.413 + rv = SECFailure; 1.414 + } 1.415 + 1.416 + /* if update was successful and pqg params present, then copy the 1.417 + * parameters to the subject cert's key. */ 1.418 + 1.419 + if (rv == SECSuccess) { 1.420 + rv = SECITEM_CopyItem(subjectCert->arena, 1.421 + &subjectSpki->algorithm.parameters, 1.422 + &issuerSpki->algorithm.parameters); 1.423 + } 1.424 + 1.425 +loser: 1.426 + if (issuerCert) { 1.427 + CERT_DestroyCertificate(issuerCert); 1.428 + } 1.429 + return rv; 1.430 + 1.431 +} 1.432 + 1.433 + 1.434 +SECStatus 1.435 +SECKEY_UpdateCertPQG(CERTCertificate * subjectCert) 1.436 +{ 1.437 + if (!subjectCert) { 1.438 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.439 + return SECFailure; 1.440 + } 1.441 + return seckey_UpdateCertPQGChain(subjectCert,0); 1.442 +} 1.443 + 1.444 + 1.445 +/* Decode the DSA PQG parameters. The params could be stored in two 1.446 + * possible formats, the old fortezza-only wrapped format or 1.447 + * the normal standard format. Store the decoded parameters in 1.448 + * a V3 certificate data structure. */ 1.449 + 1.450 +static SECStatus 1.451 +seckey_DSADecodePQG(PLArenaPool *arena, SECKEYPublicKey *pubk, 1.452 + const SECItem *params) { 1.453 + SECStatus rv; 1.454 + SECItem newparams; 1.455 + 1.456 + if (params == NULL) return SECFailure; 1.457 + 1.458 + if (params->data == NULL) return SECFailure; 1.459 + 1.460 + PORT_Assert(arena); 1.461 + 1.462 + /* make a copy of the data into the arena so QuickDER output is valid */ 1.463 + rv = SECITEM_CopyItem(arena, &newparams, params); 1.464 + 1.465 + /* Check if params use the standard format. 1.466 + * The value 0xa1 will appear in the first byte of the parameter data 1.467 + * if the PQG parameters are not using the standard format. This 1.468 + * code should be changed to use a better method to detect non-standard 1.469 + * parameters. */ 1.470 + 1.471 + if ((newparams.data[0] != 0xa1) && 1.472 + (newparams.data[0] != 0xa0)) { 1.473 + 1.474 + if (SECSuccess == rv) { 1.475 + /* PQG params are in the standard format */ 1.476 + prepare_pqg_params_for_asn1(&pubk->u.dsa.params); 1.477 + rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params, 1.478 + SECKEY_PQGParamsTemplate, 1.479 + &newparams); 1.480 + } 1.481 + } else { 1.482 + 1.483 + if (SECSuccess == rv) { 1.484 + /* else the old fortezza-only wrapped format is used. */ 1.485 + PORT_SetError(SEC_ERROR_BAD_DER); 1.486 + rv = SECFailure; 1.487 + } 1.488 + } 1.489 + return rv; 1.490 +} 1.491 + 1.492 + 1.493 +/* Function used to make an oid tag to a key type */ 1.494 +KeyType 1.495 +seckey_GetKeyType (SECOidTag tag) { 1.496 + KeyType keyType; 1.497 + 1.498 + switch (tag) { 1.499 + case SEC_OID_X500_RSA_ENCRYPTION: 1.500 + case SEC_OID_PKCS1_RSA_ENCRYPTION: 1.501 + keyType = rsaKey; 1.502 + break; 1.503 + case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: 1.504 + keyType = rsaPssKey; 1.505 + break; 1.506 + case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION: 1.507 + keyType = rsaOaepKey; 1.508 + break; 1.509 + case SEC_OID_ANSIX9_DSA_SIGNATURE: 1.510 + keyType = dsaKey; 1.511 + break; 1.512 + case SEC_OID_MISSI_KEA_DSS_OLD: 1.513 + case SEC_OID_MISSI_KEA_DSS: 1.514 + case SEC_OID_MISSI_DSS_OLD: 1.515 + case SEC_OID_MISSI_DSS: 1.516 + keyType = fortezzaKey; 1.517 + break; 1.518 + case SEC_OID_MISSI_KEA: 1.519 + case SEC_OID_MISSI_ALT_KEA: 1.520 + keyType = keaKey; 1.521 + break; 1.522 + case SEC_OID_X942_DIFFIE_HELMAN_KEY: 1.523 + keyType = dhKey; 1.524 + break; 1.525 + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: 1.526 + keyType = ecKey; 1.527 + break; 1.528 + /* accommodate applications that hand us a signature type when they 1.529 + * should be handing us a cipher type */ 1.530 + case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 1.531 + case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: 1.532 + case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: 1.533 + case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: 1.534 + case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: 1.535 + case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: 1.536 + keyType = rsaKey; 1.537 + break; 1.538 + default: 1.539 + keyType = nullKey; 1.540 + } 1.541 + return keyType; 1.542 +} 1.543 + 1.544 +/* Function used to determine what kind of cert we are dealing with. */ 1.545 +KeyType 1.546 +CERT_GetCertKeyType (const CERTSubjectPublicKeyInfo *spki) 1.547 +{ 1.548 + return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm)); 1.549 +} 1.550 + 1.551 +static SECKEYPublicKey * 1.552 +seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki) 1.553 +{ 1.554 + SECKEYPublicKey *pubk; 1.555 + SECItem os, newOs, newParms; 1.556 + SECStatus rv; 1.557 + PLArenaPool *arena; 1.558 + SECOidTag tag; 1.559 + 1.560 + arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); 1.561 + if (arena == NULL) 1.562 + return NULL; 1.563 + 1.564 + pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); 1.565 + if (pubk == NULL) { 1.566 + PORT_FreeArena (arena, PR_FALSE); 1.567 + return NULL; 1.568 + } 1.569 + 1.570 + pubk->arena = arena; 1.571 + pubk->pkcs11Slot = 0; 1.572 + pubk->pkcs11ID = CK_INVALID_HANDLE; 1.573 + 1.574 + 1.575 + /* Convert bit string length from bits to bytes */ 1.576 + os = spki->subjectPublicKey; 1.577 + DER_ConvertBitString (&os); 1.578 + 1.579 + tag = SECOID_GetAlgorithmTag(&spki->algorithm); 1.580 + 1.581 + /* copy the DER into the arena, since Quick DER returns data that points 1.582 + into the DER input, which may get freed by the caller */ 1.583 + rv = SECITEM_CopyItem(arena, &newOs, &os); 1.584 + if ( rv == SECSuccess ) 1.585 + switch ( tag ) { 1.586 + case SEC_OID_X500_RSA_ENCRYPTION: 1.587 + case SEC_OID_PKCS1_RSA_ENCRYPTION: 1.588 + pubk->keyType = rsaKey; 1.589 + prepare_rsa_pub_key_for_asn1(pubk); 1.590 + rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs); 1.591 + if (rv == SECSuccess) 1.592 + return pubk; 1.593 + break; 1.594 + case SEC_OID_ANSIX9_DSA_SIGNATURE: 1.595 + case SEC_OID_SDN702_DSA_SIGNATURE: 1.596 + pubk->keyType = dsaKey; 1.597 + prepare_dsa_pub_key_for_asn1(pubk); 1.598 + rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs); 1.599 + if (rv != SECSuccess) break; 1.600 + 1.601 + rv = seckey_DSADecodePQG(arena, pubk, 1.602 + &spki->algorithm.parameters); 1.603 + 1.604 + if (rv == SECSuccess) return pubk; 1.605 + break; 1.606 + case SEC_OID_X942_DIFFIE_HELMAN_KEY: 1.607 + pubk->keyType = dhKey; 1.608 + prepare_dh_pub_key_for_asn1(pubk); 1.609 + rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs); 1.610 + if (rv != SECSuccess) break; 1.611 + 1.612 + /* copy the DER into the arena, since Quick DER returns data that points 1.613 + into the DER input, which may get freed by the caller */ 1.614 + rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters); 1.615 + if ( rv != SECSuccess ) 1.616 + break; 1.617 + 1.618 + rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate, 1.619 + &newParms); 1.620 + 1.621 + if (rv == SECSuccess) return pubk; 1.622 + break; 1.623 + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: 1.624 + pubk->keyType = ecKey; 1.625 + pubk->u.ec.size = 0; 1.626 + 1.627 + /* Since PKCS#11 directly takes the DER encoding of EC params 1.628 + * and public value, we don't need any decoding here. 1.629 + */ 1.630 + rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams, 1.631 + &spki->algorithm.parameters); 1.632 + if ( rv != SECSuccess ) 1.633 + break; 1.634 + rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs); 1.635 + if (rv == SECSuccess) return pubk; 1.636 + break; 1.637 + 1.638 + default: 1.639 + PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); 1.640 + rv = SECFailure; 1.641 + break; 1.642 + } 1.643 + 1.644 + SECKEY_DestroyPublicKey (pubk); 1.645 + return NULL; 1.646 +} 1.647 + 1.648 + 1.649 +/* required for JSS */ 1.650 +SECKEYPublicKey * 1.651 +SECKEY_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki) 1.652 +{ 1.653 + return seckey_ExtractPublicKey(spki); 1.654 +} 1.655 + 1.656 +SECKEYPublicKey * 1.657 +CERT_ExtractPublicKey(CERTCertificate *cert) 1.658 +{ 1.659 + SECStatus rv; 1.660 + 1.661 + if (!cert) { 1.662 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.663 + return NULL; 1.664 + } 1.665 + rv = SECKEY_UpdateCertPQG(cert); 1.666 + if (rv != SECSuccess) return NULL; 1.667 + 1.668 + return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo); 1.669 +} 1.670 + 1.671 +int 1.672 +SECKEY_ECParamsToKeySize(const SECItem *encodedParams) 1.673 +{ 1.674 + SECOidTag tag; 1.675 + SECItem oid = { siBuffer, NULL, 0}; 1.676 + 1.677 + /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), 1.678 + * followed by the length of the curve oid and the curve oid. 1.679 + */ 1.680 + oid.len = encodedParams->data[1]; 1.681 + oid.data = encodedParams->data + 2; 1.682 + if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN) 1.683 + return 0; 1.684 + 1.685 + switch (tag) { 1.686 + case SEC_OID_SECG_EC_SECP112R1: 1.687 + case SEC_OID_SECG_EC_SECP112R2: 1.688 + return 112; 1.689 + 1.690 + case SEC_OID_SECG_EC_SECT113R1: 1.691 + case SEC_OID_SECG_EC_SECT113R2: 1.692 + return 113; 1.693 + 1.694 + case SEC_OID_SECG_EC_SECP128R1: 1.695 + case SEC_OID_SECG_EC_SECP128R2: 1.696 + return 128; 1.697 + 1.698 + case SEC_OID_SECG_EC_SECT131R1: 1.699 + case SEC_OID_SECG_EC_SECT131R2: 1.700 + return 131; 1.701 + 1.702 + case SEC_OID_SECG_EC_SECP160K1: 1.703 + case SEC_OID_SECG_EC_SECP160R1: 1.704 + case SEC_OID_SECG_EC_SECP160R2: 1.705 + return 160; 1.706 + 1.707 + case SEC_OID_SECG_EC_SECT163K1: 1.708 + case SEC_OID_SECG_EC_SECT163R1: 1.709 + case SEC_OID_SECG_EC_SECT163R2: 1.710 + case SEC_OID_ANSIX962_EC_C2PNB163V1: 1.711 + case SEC_OID_ANSIX962_EC_C2PNB163V2: 1.712 + case SEC_OID_ANSIX962_EC_C2PNB163V3: 1.713 + return 163; 1.714 + 1.715 + case SEC_OID_ANSIX962_EC_C2PNB176V1: 1.716 + return 176; 1.717 + 1.718 + case SEC_OID_ANSIX962_EC_C2TNB191V1: 1.719 + case SEC_OID_ANSIX962_EC_C2TNB191V2: 1.720 + case SEC_OID_ANSIX962_EC_C2TNB191V3: 1.721 + case SEC_OID_ANSIX962_EC_C2ONB191V4: 1.722 + case SEC_OID_ANSIX962_EC_C2ONB191V5: 1.723 + return 191; 1.724 + 1.725 + case SEC_OID_SECG_EC_SECP192K1: 1.726 + case SEC_OID_ANSIX962_EC_PRIME192V1: 1.727 + case SEC_OID_ANSIX962_EC_PRIME192V2: 1.728 + case SEC_OID_ANSIX962_EC_PRIME192V3: 1.729 + return 192; 1.730 + 1.731 + case SEC_OID_SECG_EC_SECT193R1: 1.732 + case SEC_OID_SECG_EC_SECT193R2: 1.733 + return 193; 1.734 + 1.735 + case SEC_OID_ANSIX962_EC_C2PNB208W1: 1.736 + return 208; 1.737 + 1.738 + case SEC_OID_SECG_EC_SECP224K1: 1.739 + case SEC_OID_SECG_EC_SECP224R1: 1.740 + return 224; 1.741 + 1.742 + case SEC_OID_SECG_EC_SECT233K1: 1.743 + case SEC_OID_SECG_EC_SECT233R1: 1.744 + return 233; 1.745 + 1.746 + case SEC_OID_SECG_EC_SECT239K1: 1.747 + case SEC_OID_ANSIX962_EC_C2TNB239V1: 1.748 + case SEC_OID_ANSIX962_EC_C2TNB239V2: 1.749 + case SEC_OID_ANSIX962_EC_C2TNB239V3: 1.750 + case SEC_OID_ANSIX962_EC_C2ONB239V4: 1.751 + case SEC_OID_ANSIX962_EC_C2ONB239V5: 1.752 + case SEC_OID_ANSIX962_EC_PRIME239V1: 1.753 + case SEC_OID_ANSIX962_EC_PRIME239V2: 1.754 + case SEC_OID_ANSIX962_EC_PRIME239V3: 1.755 + return 239; 1.756 + 1.757 + case SEC_OID_SECG_EC_SECP256K1: 1.758 + case SEC_OID_ANSIX962_EC_PRIME256V1: 1.759 + return 256; 1.760 + 1.761 + case SEC_OID_ANSIX962_EC_C2PNB272W1: 1.762 + return 272; 1.763 + 1.764 + case SEC_OID_SECG_EC_SECT283K1: 1.765 + case SEC_OID_SECG_EC_SECT283R1: 1.766 + return 283; 1.767 + 1.768 + case SEC_OID_ANSIX962_EC_C2PNB304W1: 1.769 + return 304; 1.770 + 1.771 + case SEC_OID_ANSIX962_EC_C2TNB359V1: 1.772 + return 359; 1.773 + 1.774 + case SEC_OID_ANSIX962_EC_C2PNB368W1: 1.775 + return 368; 1.776 + 1.777 + case SEC_OID_SECG_EC_SECP384R1: 1.778 + return 384; 1.779 + 1.780 + case SEC_OID_SECG_EC_SECT409K1: 1.781 + case SEC_OID_SECG_EC_SECT409R1: 1.782 + return 409; 1.783 + 1.784 + case SEC_OID_ANSIX962_EC_C2TNB431R1: 1.785 + return 431; 1.786 + 1.787 + case SEC_OID_SECG_EC_SECP521R1: 1.788 + return 521; 1.789 + 1.790 + case SEC_OID_SECG_EC_SECT571K1: 1.791 + case SEC_OID_SECG_EC_SECT571R1: 1.792 + return 571; 1.793 + 1.794 + default: 1.795 + PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 1.796 + return 0; 1.797 + } 1.798 +} 1.799 + 1.800 +int 1.801 +SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams) 1.802 +{ 1.803 + SECOidTag tag; 1.804 + SECItem oid = { siBuffer, NULL, 0}; 1.805 + 1.806 + /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), 1.807 + * followed by the length of the curve oid and the curve oid. 1.808 + */ 1.809 + oid.len = encodedParams->data[1]; 1.810 + oid.data = encodedParams->data + 2; 1.811 + if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN) 1.812 + return 0; 1.813 + 1.814 + switch (tag) { 1.815 + case SEC_OID_SECG_EC_SECP112R1: 1.816 + return 112; 1.817 + case SEC_OID_SECG_EC_SECP112R2: 1.818 + return 110; 1.819 + 1.820 + case SEC_OID_SECG_EC_SECT113R1: 1.821 + case SEC_OID_SECG_EC_SECT113R2: 1.822 + return 113; 1.823 + 1.824 + case SEC_OID_SECG_EC_SECP128R1: 1.825 + return 128; 1.826 + case SEC_OID_SECG_EC_SECP128R2: 1.827 + return 126; 1.828 + 1.829 + case SEC_OID_SECG_EC_SECT131R1: 1.830 + case SEC_OID_SECG_EC_SECT131R2: 1.831 + return 131; 1.832 + 1.833 + case SEC_OID_SECG_EC_SECP160K1: 1.834 + case SEC_OID_SECG_EC_SECP160R1: 1.835 + case SEC_OID_SECG_EC_SECP160R2: 1.836 + return 161; 1.837 + 1.838 + case SEC_OID_SECG_EC_SECT163K1: 1.839 + return 163; 1.840 + case SEC_OID_SECG_EC_SECT163R1: 1.841 + return 162; 1.842 + case SEC_OID_SECG_EC_SECT163R2: 1.843 + case SEC_OID_ANSIX962_EC_C2PNB163V1: 1.844 + return 163; 1.845 + case SEC_OID_ANSIX962_EC_C2PNB163V2: 1.846 + case SEC_OID_ANSIX962_EC_C2PNB163V3: 1.847 + return 162; 1.848 + 1.849 + case SEC_OID_ANSIX962_EC_C2PNB176V1: 1.850 + return 161; 1.851 + 1.852 + case SEC_OID_ANSIX962_EC_C2TNB191V1: 1.853 + return 191; 1.854 + case SEC_OID_ANSIX962_EC_C2TNB191V2: 1.855 + return 190; 1.856 + case SEC_OID_ANSIX962_EC_C2TNB191V3: 1.857 + return 189; 1.858 + case SEC_OID_ANSIX962_EC_C2ONB191V4: 1.859 + return 191; 1.860 + case SEC_OID_ANSIX962_EC_C2ONB191V5: 1.861 + return 188; 1.862 + 1.863 + case SEC_OID_SECG_EC_SECP192K1: 1.864 + case SEC_OID_ANSIX962_EC_PRIME192V1: 1.865 + case SEC_OID_ANSIX962_EC_PRIME192V2: 1.866 + case SEC_OID_ANSIX962_EC_PRIME192V3: 1.867 + return 192; 1.868 + 1.869 + case SEC_OID_SECG_EC_SECT193R1: 1.870 + case SEC_OID_SECG_EC_SECT193R2: 1.871 + return 193; 1.872 + 1.873 + case SEC_OID_ANSIX962_EC_C2PNB208W1: 1.874 + return 193; 1.875 + 1.876 + case SEC_OID_SECG_EC_SECP224K1: 1.877 + return 225; 1.878 + case SEC_OID_SECG_EC_SECP224R1: 1.879 + return 224; 1.880 + 1.881 + case SEC_OID_SECG_EC_SECT233K1: 1.882 + return 232; 1.883 + case SEC_OID_SECG_EC_SECT233R1: 1.884 + return 233; 1.885 + 1.886 + case SEC_OID_SECG_EC_SECT239K1: 1.887 + case SEC_OID_ANSIX962_EC_C2TNB239V1: 1.888 + return 238; 1.889 + case SEC_OID_ANSIX962_EC_C2TNB239V2: 1.890 + return 237; 1.891 + case SEC_OID_ANSIX962_EC_C2TNB239V3: 1.892 + return 236; 1.893 + case SEC_OID_ANSIX962_EC_C2ONB239V4: 1.894 + return 238; 1.895 + case SEC_OID_ANSIX962_EC_C2ONB239V5: 1.896 + return 237; 1.897 + case SEC_OID_ANSIX962_EC_PRIME239V1: 1.898 + case SEC_OID_ANSIX962_EC_PRIME239V2: 1.899 + case SEC_OID_ANSIX962_EC_PRIME239V3: 1.900 + return 239; 1.901 + 1.902 + case SEC_OID_SECG_EC_SECP256K1: 1.903 + case SEC_OID_ANSIX962_EC_PRIME256V1: 1.904 + return 256; 1.905 + 1.906 + case SEC_OID_ANSIX962_EC_C2PNB272W1: 1.907 + return 257; 1.908 + 1.909 + case SEC_OID_SECG_EC_SECT283K1: 1.910 + return 281; 1.911 + case SEC_OID_SECG_EC_SECT283R1: 1.912 + return 282; 1.913 + 1.914 + case SEC_OID_ANSIX962_EC_C2PNB304W1: 1.915 + return 289; 1.916 + 1.917 + case SEC_OID_ANSIX962_EC_C2TNB359V1: 1.918 + return 353; 1.919 + 1.920 + case SEC_OID_ANSIX962_EC_C2PNB368W1: 1.921 + return 353; 1.922 + 1.923 + case SEC_OID_SECG_EC_SECP384R1: 1.924 + return 384; 1.925 + 1.926 + case SEC_OID_SECG_EC_SECT409K1: 1.927 + return 407; 1.928 + case SEC_OID_SECG_EC_SECT409R1: 1.929 + return 409; 1.930 + 1.931 + case SEC_OID_ANSIX962_EC_C2TNB431R1: 1.932 + return 418; 1.933 + 1.934 + case SEC_OID_SECG_EC_SECP521R1: 1.935 + return 521; 1.936 + 1.937 + case SEC_OID_SECG_EC_SECT571K1: 1.938 + case SEC_OID_SECG_EC_SECT571R1: 1.939 + return 570; 1.940 + 1.941 + default: 1.942 + PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 1.943 + return 0; 1.944 + } 1.945 +} 1.946 + 1.947 +/* returns key strength in bytes (not bits) */ 1.948 +unsigned 1.949 +SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk) 1.950 +{ 1.951 + unsigned char b0; 1.952 + unsigned size; 1.953 + 1.954 + /* interpret modulus length as key strength */ 1.955 + if (!pubk) 1.956 + goto loser; 1.957 + switch (pubk->keyType) { 1.958 + case rsaKey: 1.959 + if (!pubk->u.rsa.modulus.data) break; 1.960 + b0 = pubk->u.rsa.modulus.data[0]; 1.961 + return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; 1.962 + case dsaKey: 1.963 + if (!pubk->u.dsa.publicValue.data) break; 1.964 + b0 = pubk->u.dsa.publicValue.data[0]; 1.965 + return b0 ? pubk->u.dsa.publicValue.len : 1.966 + pubk->u.dsa.publicValue.len - 1; 1.967 + case dhKey: 1.968 + if (!pubk->u.dh.publicValue.data) break; 1.969 + b0 = pubk->u.dh.publicValue.data[0]; 1.970 + return b0 ? pubk->u.dh.publicValue.len : 1.971 + pubk->u.dh.publicValue.len - 1; 1.972 + case ecKey: 1.973 + /* Get the key size in bits and adjust */ 1.974 + size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); 1.975 + return (size + 7)/8; 1.976 + default: 1.977 + break; 1.978 + } 1.979 +loser: 1.980 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.981 + return 0; 1.982 +} 1.983 + 1.984 +/* returns key strength in bits */ 1.985 +unsigned 1.986 +SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk) 1.987 +{ 1.988 + unsigned size; 1.989 + switch (pubk->keyType) { 1.990 + case rsaKey: 1.991 + case dsaKey: 1.992 + case dhKey: 1.993 + return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */ 1.994 + case ecKey: 1.995 + size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); 1.996 + return size; 1.997 + default: 1.998 + break; 1.999 + } 1.1000 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.1001 + return 0; 1.1002 +} 1.1003 + 1.1004 +/* returns signature length in bytes (not bits) */ 1.1005 +unsigned 1.1006 +SECKEY_SignatureLen(const SECKEYPublicKey *pubk) 1.1007 +{ 1.1008 + unsigned char b0; 1.1009 + unsigned size; 1.1010 + 1.1011 + switch (pubk->keyType) { 1.1012 + case rsaKey: 1.1013 + b0 = pubk->u.rsa.modulus.data[0]; 1.1014 + return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; 1.1015 + case dsaKey: 1.1016 + return pubk->u.dsa.params.subPrime.len * 2; 1.1017 + case ecKey: 1.1018 + /* Get the base point order length in bits and adjust */ 1.1019 + size = SECKEY_ECParamsToBasePointOrderLen( 1.1020 + &pubk->u.ec.DEREncodedParams); 1.1021 + return ((size + 7)/8) * 2; 1.1022 + default: 1.1023 + break; 1.1024 + } 1.1025 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.1026 + return 0; 1.1027 +} 1.1028 + 1.1029 +SECKEYPrivateKey * 1.1030 +SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk) 1.1031 +{ 1.1032 + SECKEYPrivateKey *copyk; 1.1033 + PLArenaPool *arena; 1.1034 + 1.1035 + if (!privk || !privk->pkcs11Slot) { 1.1036 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1037 + return NULL; 1.1038 + } 1.1039 + 1.1040 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1041 + if (arena == NULL) { 1.1042 + return NULL; 1.1043 + } 1.1044 + 1.1045 + copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey)); 1.1046 + if (copyk) { 1.1047 + copyk->arena = arena; 1.1048 + copyk->keyType = privk->keyType; 1.1049 + 1.1050 + /* copy the PKCS #11 parameters */ 1.1051 + copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot); 1.1052 + /* if the key we're referencing was a temparary key we have just 1.1053 + * created, that we want to go away when we're through, we need 1.1054 + * to make a copy of it */ 1.1055 + if (privk->pkcs11IsTemp) { 1.1056 + copyk->pkcs11ID = 1.1057 + PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID); 1.1058 + if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail; 1.1059 + } else { 1.1060 + copyk->pkcs11ID = privk->pkcs11ID; 1.1061 + } 1.1062 + copyk->pkcs11IsTemp = privk->pkcs11IsTemp; 1.1063 + copyk->wincx = privk->wincx; 1.1064 + copyk->staticflags = privk->staticflags; 1.1065 + return copyk; 1.1066 + } else { 1.1067 + PORT_SetError (SEC_ERROR_NO_MEMORY); 1.1068 + } 1.1069 + 1.1070 +fail: 1.1071 + PORT_FreeArena (arena, PR_FALSE); 1.1072 + return NULL; 1.1073 +} 1.1074 + 1.1075 +SECKEYPublicKey * 1.1076 +SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk) 1.1077 +{ 1.1078 + SECKEYPublicKey *copyk; 1.1079 + PLArenaPool *arena; 1.1080 + SECStatus rv = SECSuccess; 1.1081 + 1.1082 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1083 + if (arena == NULL) { 1.1084 + PORT_SetError (SEC_ERROR_NO_MEMORY); 1.1085 + return NULL; 1.1086 + } 1.1087 + 1.1088 + copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey)); 1.1089 + if (!copyk) { 1.1090 + PORT_FreeArena (arena, PR_FALSE); 1.1091 + PORT_SetError (SEC_ERROR_NO_MEMORY); 1.1092 + return NULL; 1.1093 + } 1.1094 + 1.1095 + copyk->arena = arena; 1.1096 + copyk->keyType = pubk->keyType; 1.1097 + if (pubk->pkcs11Slot && 1.1098 + PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) { 1.1099 + copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot); 1.1100 + copyk->pkcs11ID = pubk->pkcs11ID; 1.1101 + } else { 1.1102 + copyk->pkcs11Slot = NULL; /* go get own reference */ 1.1103 + copyk->pkcs11ID = CK_INVALID_HANDLE; 1.1104 + } 1.1105 + switch (pubk->keyType) { 1.1106 + case rsaKey: 1.1107 + rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus, 1.1108 + &pubk->u.rsa.modulus); 1.1109 + if (rv == SECSuccess) { 1.1110 + rv = SECITEM_CopyItem (arena, ©k->u.rsa.publicExponent, 1.1111 + &pubk->u.rsa.publicExponent); 1.1112 + if (rv == SECSuccess) 1.1113 + return copyk; 1.1114 + } 1.1115 + break; 1.1116 + case dsaKey: 1.1117 + rv = SECITEM_CopyItem(arena, ©k->u.dsa.publicValue, 1.1118 + &pubk->u.dsa.publicValue); 1.1119 + if (rv != SECSuccess) break; 1.1120 + rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.prime, 1.1121 + &pubk->u.dsa.params.prime); 1.1122 + if (rv != SECSuccess) break; 1.1123 + rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.subPrime, 1.1124 + &pubk->u.dsa.params.subPrime); 1.1125 + if (rv != SECSuccess) break; 1.1126 + rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.base, 1.1127 + &pubk->u.dsa.params.base); 1.1128 + break; 1.1129 + case dhKey: 1.1130 + rv = SECITEM_CopyItem(arena,©k->u.dh.prime,&pubk->u.dh.prime); 1.1131 + if (rv != SECSuccess) break; 1.1132 + rv = SECITEM_CopyItem(arena,©k->u.dh.base,&pubk->u.dh.base); 1.1133 + if (rv != SECSuccess) break; 1.1134 + rv = SECITEM_CopyItem(arena, ©k->u.dh.publicValue, 1.1135 + &pubk->u.dh.publicValue); 1.1136 + break; 1.1137 + case ecKey: 1.1138 + copyk->u.ec.size = pubk->u.ec.size; 1.1139 + rv = SECITEM_CopyItem(arena,©k->u.ec.DEREncodedParams, 1.1140 + &pubk->u.ec.DEREncodedParams); 1.1141 + if (rv != SECSuccess) break; 1.1142 + rv = SECITEM_CopyItem(arena,©k->u.ec.publicValue, 1.1143 + &pubk->u.ec.publicValue); 1.1144 + break; 1.1145 + case nullKey: 1.1146 + return copyk; 1.1147 + default: 1.1148 + PORT_SetError(SEC_ERROR_INVALID_KEY); 1.1149 + rv = SECFailure; 1.1150 + break; 1.1151 + } 1.1152 + if (rv == SECSuccess) 1.1153 + return copyk; 1.1154 + 1.1155 + SECKEY_DestroyPublicKey (copyk); 1.1156 + return NULL; 1.1157 +} 1.1158 + 1.1159 + 1.1160 +SECKEYPublicKey * 1.1161 +SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) 1.1162 +{ 1.1163 + SECKEYPublicKey *pubk; 1.1164 + PLArenaPool *arena; 1.1165 + CERTCertificate *cert; 1.1166 + SECStatus rv; 1.1167 + 1.1168 + /* 1.1169 + * First try to look up the cert. 1.1170 + */ 1.1171 + cert = PK11_GetCertFromPrivateKey(privk); 1.1172 + if (cert) { 1.1173 + pubk = CERT_ExtractPublicKey(cert); 1.1174 + CERT_DestroyCertificate(cert); 1.1175 + return pubk; 1.1176 + } 1.1177 + 1.1178 + /* couldn't find the cert, build pub key by hand */ 1.1179 + arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); 1.1180 + if (arena == NULL) { 1.1181 + PORT_SetError (SEC_ERROR_NO_MEMORY); 1.1182 + return NULL; 1.1183 + } 1.1184 + pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, 1.1185 + sizeof (SECKEYPublicKey)); 1.1186 + if (pubk == NULL) { 1.1187 + PORT_FreeArena(arena,PR_FALSE); 1.1188 + return NULL; 1.1189 + } 1.1190 + pubk->keyType = privk->keyType; 1.1191 + pubk->pkcs11Slot = NULL; 1.1192 + pubk->pkcs11ID = CK_INVALID_HANDLE; 1.1193 + pubk->arena = arena; 1.1194 + 1.1195 + switch(privk->keyType) { 1.1196 + case nullKey: 1.1197 + case dhKey: 1.1198 + case dsaKey: 1.1199 + /* Nothing to query, if the cert isn't there, we're done -- no way 1.1200 + * to get the public key */ 1.1201 + break; 1.1202 + case rsaKey: 1.1203 + rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID, 1.1204 + CKA_MODULUS,arena,&pubk->u.rsa.modulus); 1.1205 + if (rv != SECSuccess) break; 1.1206 + rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID, 1.1207 + CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent); 1.1208 + if (rv != SECSuccess) break; 1.1209 + return pubk; 1.1210 + break; 1.1211 + default: 1.1212 + break; 1.1213 + } 1.1214 + 1.1215 + PORT_FreeArena (arena, PR_FALSE); 1.1216 + return NULL; 1.1217 +} 1.1218 + 1.1219 +static CERTSubjectPublicKeyInfo * 1.1220 +seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk) 1.1221 +{ 1.1222 + CERTSubjectPublicKeyInfo *spki; 1.1223 + PLArenaPool *arena; 1.1224 + SECItem params = { siBuffer, NULL, 0 }; 1.1225 + 1.1226 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1227 + if (arena == NULL) { 1.1228 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1229 + return NULL; 1.1230 + } 1.1231 + 1.1232 + spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki)); 1.1233 + if (spki != NULL) { 1.1234 + SECStatus rv; 1.1235 + SECItem *rv_item; 1.1236 + 1.1237 + spki->arena = arena; 1.1238 + switch(pubk->keyType) { 1.1239 + case rsaKey: 1.1240 + rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, 1.1241 + SEC_OID_PKCS1_RSA_ENCRYPTION, 0); 1.1242 + if (rv == SECSuccess) { 1.1243 + /* 1.1244 + * DER encode the public key into the subjectPublicKeyInfo. 1.1245 + */ 1.1246 + prepare_rsa_pub_key_for_asn1(pubk); 1.1247 + rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, 1.1248 + pubk, SECKEY_RSAPublicKeyTemplate); 1.1249 + if (rv_item != NULL) { 1.1250 + /* 1.1251 + * The stored value is supposed to be a BIT_STRING, 1.1252 + * so convert the length. 1.1253 + */ 1.1254 + spki->subjectPublicKey.len <<= 3; 1.1255 + /* 1.1256 + * We got a good one; return it. 1.1257 + */ 1.1258 + return spki; 1.1259 + } 1.1260 + } 1.1261 + break; 1.1262 + case dsaKey: 1.1263 + /* DER encode the params. */ 1.1264 + prepare_pqg_params_for_asn1(&pubk->u.dsa.params); 1.1265 + rv_item = SEC_ASN1EncodeItem(arena, ¶ms, &pubk->u.dsa.params, 1.1266 + SECKEY_PQGParamsTemplate); 1.1267 + if (rv_item != NULL) { 1.1268 + rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, 1.1269 + SEC_OID_ANSIX9_DSA_SIGNATURE, 1.1270 + ¶ms); 1.1271 + if (rv == SECSuccess) { 1.1272 + /* 1.1273 + * DER encode the public key into the subjectPublicKeyInfo. 1.1274 + */ 1.1275 + prepare_dsa_pub_key_for_asn1(pubk); 1.1276 + rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, 1.1277 + pubk, 1.1278 + SECKEY_DSAPublicKeyTemplate); 1.1279 + if (rv_item != NULL) { 1.1280 + /* 1.1281 + * The stored value is supposed to be a BIT_STRING, 1.1282 + * so convert the length. 1.1283 + */ 1.1284 + spki->subjectPublicKey.len <<= 3; 1.1285 + /* 1.1286 + * We got a good one; return it. 1.1287 + */ 1.1288 + return spki; 1.1289 + } 1.1290 + } 1.1291 + } 1.1292 + SECITEM_FreeItem(¶ms, PR_FALSE); 1.1293 + break; 1.1294 + case ecKey: 1.1295 + rv = SECITEM_CopyItem(arena, ¶ms, 1.1296 + &pubk->u.ec.DEREncodedParams); 1.1297 + if (rv != SECSuccess) break; 1.1298 + 1.1299 + rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, 1.1300 + SEC_OID_ANSIX962_EC_PUBLIC_KEY, 1.1301 + ¶ms); 1.1302 + if (rv != SECSuccess) break; 1.1303 + 1.1304 + rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey, 1.1305 + &pubk->u.ec.publicValue); 1.1306 + 1.1307 + if (rv == SECSuccess) { 1.1308 + /* 1.1309 + * The stored value is supposed to be a BIT_STRING, 1.1310 + * so convert the length. 1.1311 + */ 1.1312 + spki->subjectPublicKey.len <<= 3; 1.1313 + /* 1.1314 + * We got a good one; return it. 1.1315 + */ 1.1316 + return spki; 1.1317 + } 1.1318 + break; 1.1319 + case dhKey: /* later... */ 1.1320 + 1.1321 + break; 1.1322 + default: 1.1323 + break; 1.1324 + } 1.1325 + } else { 1.1326 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1327 + } 1.1328 + 1.1329 + PORT_FreeArena(arena, PR_FALSE); 1.1330 + return NULL; 1.1331 +} 1.1332 + 1.1333 +CERTSubjectPublicKeyInfo * 1.1334 +SECKEY_CreateSubjectPublicKeyInfo(const SECKEYPublicKey *pubk) 1.1335 +{ 1.1336 + CERTSubjectPublicKeyInfo *spki; 1.1337 + SECKEYPublicKey *tempKey; 1.1338 + 1.1339 + if (!pubk) { 1.1340 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1341 + return NULL; 1.1342 + } 1.1343 + 1.1344 + tempKey = SECKEY_CopyPublicKey(pubk); 1.1345 + if (!tempKey) { 1.1346 + return NULL; 1.1347 + } 1.1348 + spki = seckey_CreateSubjectPublicKeyInfo_helper(tempKey); 1.1349 + SECKEY_DestroyPublicKey(tempKey); 1.1350 + return spki; 1.1351 +} 1.1352 + 1.1353 +void 1.1354 +SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki) 1.1355 +{ 1.1356 + if (spki && spki->arena) { 1.1357 + PORT_FreeArena(spki->arena, PR_FALSE); 1.1358 + } 1.1359 +} 1.1360 + 1.1361 +SECItem * 1.1362 +SECKEY_EncodeDERSubjectPublicKeyInfo(const SECKEYPublicKey *pubk) 1.1363 +{ 1.1364 + CERTSubjectPublicKeyInfo *spki=NULL; 1.1365 + SECItem *spkiDER=NULL; 1.1366 + 1.1367 + /* get the subjectpublickeyinfo */ 1.1368 + spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); 1.1369 + if( spki == NULL ) { 1.1370 + goto finish; 1.1371 + } 1.1372 + 1.1373 + /* DER-encode the subjectpublickeyinfo */ 1.1374 + spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki, 1.1375 + CERT_SubjectPublicKeyInfoTemplate); 1.1376 + 1.1377 + SECKEY_DestroySubjectPublicKeyInfo(spki); 1.1378 + 1.1379 +finish: 1.1380 + return spkiDER; 1.1381 +} 1.1382 + 1.1383 + 1.1384 +CERTSubjectPublicKeyInfo * 1.1385 +SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider) 1.1386 +{ 1.1387 + PLArenaPool *arena; 1.1388 + CERTSubjectPublicKeyInfo *spki; 1.1389 + SECStatus rv; 1.1390 + SECItem newSpkider; 1.1391 + 1.1392 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1393 + if (arena == NULL) { 1.1394 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1395 + return NULL; 1.1396 + } 1.1397 + 1.1398 + spki = (CERTSubjectPublicKeyInfo *) 1.1399 + PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo)); 1.1400 + if (spki != NULL) { 1.1401 + spki->arena = arena; 1.1402 + 1.1403 + /* copy the DER into the arena, since Quick DER returns data that points 1.1404 + into the DER input, which may get freed by the caller */ 1.1405 + rv = SECITEM_CopyItem(arena, &newSpkider, spkider); 1.1406 + if ( rv == SECSuccess ) { 1.1407 + rv = SEC_QuickDERDecodeItem(arena,spki, 1.1408 + CERT_SubjectPublicKeyInfoTemplate, &newSpkider); 1.1409 + } 1.1410 + if (rv == SECSuccess) 1.1411 + return spki; 1.1412 + } else { 1.1413 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1414 + } 1.1415 + 1.1416 + PORT_FreeArena(arena, PR_FALSE); 1.1417 + return NULL; 1.1418 +} 1.1419 + 1.1420 +/* 1.1421 + * Decode a base64 ascii encoded DER encoded subject public key info. 1.1422 + */ 1.1423 +CERTSubjectPublicKeyInfo * 1.1424 +SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(const char *spkistr) 1.1425 +{ 1.1426 + CERTSubjectPublicKeyInfo *spki; 1.1427 + SECStatus rv; 1.1428 + SECItem der; 1.1429 + 1.1430 + rv = ATOB_ConvertAsciiToItem(&der, spkistr); 1.1431 + if (rv != SECSuccess) 1.1432 + return NULL; 1.1433 + 1.1434 + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); 1.1435 + 1.1436 + PORT_Free(der.data); 1.1437 + return spki; 1.1438 +} 1.1439 + 1.1440 +/* 1.1441 + * Decode a base64 ascii encoded DER encoded public key and challenge 1.1442 + * Verify digital signature and make sure challenge matches 1.1443 + */ 1.1444 +CERTSubjectPublicKeyInfo * 1.1445 +SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge, 1.1446 + void *wincx) 1.1447 +{ 1.1448 + CERTSubjectPublicKeyInfo *spki = NULL; 1.1449 + CERTPublicKeyAndChallenge pkac; 1.1450 + SECStatus rv; 1.1451 + SECItem signedItem; 1.1452 + PLArenaPool *arena = NULL; 1.1453 + CERTSignedData sd; 1.1454 + SECItem sig; 1.1455 + SECKEYPublicKey *pubKey = NULL; 1.1456 + unsigned int len; 1.1457 + 1.1458 + signedItem.data = NULL; 1.1459 + 1.1460 + /* convert the base64 encoded data to binary */ 1.1461 + rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr); 1.1462 + if (rv != SECSuccess) { 1.1463 + goto loser; 1.1464 + } 1.1465 + 1.1466 + /* create an arena */ 1.1467 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1468 + if (arena == NULL) { 1.1469 + goto loser; 1.1470 + } 1.1471 + 1.1472 + /* decode the outer wrapping of signed data */ 1.1473 + PORT_Memset(&sd, 0, sizeof(CERTSignedData)); 1.1474 + rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem ); 1.1475 + if ( rv ) { 1.1476 + goto loser; 1.1477 + } 1.1478 + 1.1479 + /* decode the public key and challenge wrapper */ 1.1480 + PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge)); 1.1481 + rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, 1.1482 + &sd.data); 1.1483 + if ( rv ) { 1.1484 + goto loser; 1.1485 + } 1.1486 + 1.1487 + /* decode the subject public key info */ 1.1488 + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki); 1.1489 + if ( spki == NULL ) { 1.1490 + goto loser; 1.1491 + } 1.1492 + 1.1493 + /* get the public key */ 1.1494 + pubKey = seckey_ExtractPublicKey(spki); 1.1495 + if ( pubKey == NULL ) { 1.1496 + goto loser; 1.1497 + } 1.1498 + 1.1499 + /* check the signature */ 1.1500 + sig = sd.signature; 1.1501 + DER_ConvertBitString(&sig); 1.1502 + rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig, 1.1503 + &(sd.signatureAlgorithm), NULL, wincx); 1.1504 + if ( rv != SECSuccess ) { 1.1505 + goto loser; 1.1506 + } 1.1507 + 1.1508 + /* check the challenge */ 1.1509 + if ( challenge ) { 1.1510 + len = PORT_Strlen(challenge); 1.1511 + /* length is right */ 1.1512 + if ( len != pkac.challenge.len ) { 1.1513 + goto loser; 1.1514 + } 1.1515 + /* actual data is right */ 1.1516 + if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) { 1.1517 + goto loser; 1.1518 + } 1.1519 + } 1.1520 + goto done; 1.1521 + 1.1522 +loser: 1.1523 + /* make sure that we return null if we got an error */ 1.1524 + if ( spki ) { 1.1525 + SECKEY_DestroySubjectPublicKeyInfo(spki); 1.1526 + } 1.1527 + spki = NULL; 1.1528 + 1.1529 +done: 1.1530 + if ( signedItem.data ) { 1.1531 + PORT_Free(signedItem.data); 1.1532 + } 1.1533 + if ( arena ) { 1.1534 + PORT_FreeArena(arena, PR_FALSE); 1.1535 + } 1.1536 + if ( pubKey ) { 1.1537 + SECKEY_DestroyPublicKey(pubKey); 1.1538 + } 1.1539 + 1.1540 + return spki; 1.1541 +} 1.1542 + 1.1543 +void 1.1544 +SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk, 1.1545 + PRBool freeit) 1.1546 +{ 1.1547 + PLArenaPool *poolp; 1.1548 + 1.1549 + if(pvk != NULL) { 1.1550 + if(pvk->arena) { 1.1551 + poolp = pvk->arena; 1.1552 + /* zero structure since PORT_FreeArena does not support 1.1553 + * this yet. 1.1554 + */ 1.1555 + PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len); 1.1556 + PORT_Memset((char *)pvk, 0, sizeof(*pvk)); 1.1557 + if(freeit == PR_TRUE) { 1.1558 + PORT_FreeArena(poolp, PR_TRUE); 1.1559 + } else { 1.1560 + pvk->arena = poolp; 1.1561 + } 1.1562 + } else { 1.1563 + SECITEM_ZfreeItem(&pvk->version, PR_FALSE); 1.1564 + SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE); 1.1565 + SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE); 1.1566 + PORT_Memset((char *)pvk, 0, sizeof(*pvk)); 1.1567 + if(freeit == PR_TRUE) { 1.1568 + PORT_Free(pvk); 1.1569 + } 1.1570 + } 1.1571 + } 1.1572 +} 1.1573 + 1.1574 +void 1.1575 +SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki, 1.1576 + PRBool freeit) 1.1577 +{ 1.1578 + PLArenaPool *poolp; 1.1579 + 1.1580 + if(epki != NULL) { 1.1581 + if(epki->arena) { 1.1582 + poolp = epki->arena; 1.1583 + /* zero structure since PORT_FreeArena does not support 1.1584 + * this yet. 1.1585 + */ 1.1586 + PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len); 1.1587 + PORT_Memset((char *)epki, 0, sizeof(*epki)); 1.1588 + if(freeit == PR_TRUE) { 1.1589 + PORT_FreeArena(poolp, PR_TRUE); 1.1590 + } else { 1.1591 + epki->arena = poolp; 1.1592 + } 1.1593 + } else { 1.1594 + SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE); 1.1595 + SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE); 1.1596 + PORT_Memset((char *)epki, 0, sizeof(*epki)); 1.1597 + if(freeit == PR_TRUE) { 1.1598 + PORT_Free(epki); 1.1599 + } 1.1600 + } 1.1601 + } 1.1602 +} 1.1603 + 1.1604 +SECStatus 1.1605 +SECKEY_CopyPrivateKeyInfo(PLArenaPool *poolp, 1.1606 + SECKEYPrivateKeyInfo *to, 1.1607 + const SECKEYPrivateKeyInfo *from) 1.1608 +{ 1.1609 + SECStatus rv = SECFailure; 1.1610 + 1.1611 + if((to == NULL) || (from == NULL)) { 1.1612 + return SECFailure; 1.1613 + } 1.1614 + 1.1615 + rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm); 1.1616 + if(rv != SECSuccess) { 1.1617 + return SECFailure; 1.1618 + } 1.1619 + rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey); 1.1620 + if(rv != SECSuccess) { 1.1621 + return SECFailure; 1.1622 + } 1.1623 + rv = SECITEM_CopyItem(poolp, &to->version, &from->version); 1.1624 + 1.1625 + return rv; 1.1626 +} 1.1627 + 1.1628 +SECStatus 1.1629 +SECKEY_CopyEncryptedPrivateKeyInfo(PLArenaPool *poolp, 1.1630 + SECKEYEncryptedPrivateKeyInfo *to, 1.1631 + const SECKEYEncryptedPrivateKeyInfo *from) 1.1632 +{ 1.1633 + SECStatus rv = SECFailure; 1.1634 + 1.1635 + if((to == NULL) || (from == NULL)) { 1.1636 + return SECFailure; 1.1637 + } 1.1638 + 1.1639 + rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm); 1.1640 + if(rv != SECSuccess) { 1.1641 + return SECFailure; 1.1642 + } 1.1643 + rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData); 1.1644 + 1.1645 + return rv; 1.1646 +} 1.1647 + 1.1648 +KeyType 1.1649 +SECKEY_GetPrivateKeyType(const SECKEYPrivateKey *privKey) 1.1650 +{ 1.1651 + return privKey->keyType; 1.1652 +} 1.1653 + 1.1654 +KeyType 1.1655 +SECKEY_GetPublicKeyType(const SECKEYPublicKey *pubKey) 1.1656 +{ 1.1657 + return pubKey->keyType; 1.1658 +} 1.1659 + 1.1660 +SECKEYPublicKey* 1.1661 +SECKEY_ImportDERPublicKey(const SECItem *derKey, CK_KEY_TYPE type) 1.1662 +{ 1.1663 + SECKEYPublicKey *pubk = NULL; 1.1664 + SECStatus rv = SECFailure; 1.1665 + SECItem newDerKey; 1.1666 + PLArenaPool *arena = NULL; 1.1667 + 1.1668 + if (!derKey) { 1.1669 + return NULL; 1.1670 + } 1.1671 + 1.1672 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1673 + if (arena == NULL) { 1.1674 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1675 + goto finish; 1.1676 + } 1.1677 + 1.1678 + pubk = PORT_ArenaZNew(arena, SECKEYPublicKey); 1.1679 + if (pubk == NULL) { 1.1680 + goto finish; 1.1681 + } 1.1682 + pubk->arena = arena; 1.1683 + 1.1684 + rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey); 1.1685 + if (SECSuccess != rv) { 1.1686 + goto finish; 1.1687 + } 1.1688 + 1.1689 + pubk->pkcs11Slot = NULL; 1.1690 + pubk->pkcs11ID = CK_INVALID_HANDLE; 1.1691 + 1.1692 + switch( type ) { 1.1693 + case CKK_RSA: 1.1694 + prepare_rsa_pub_key_for_asn1(pubk); 1.1695 + rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey); 1.1696 + pubk->keyType = rsaKey; 1.1697 + break; 1.1698 + case CKK_DSA: 1.1699 + prepare_dsa_pub_key_for_asn1(pubk); 1.1700 + rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey); 1.1701 + pubk->keyType = dsaKey; 1.1702 + break; 1.1703 + case CKK_DH: 1.1704 + prepare_dh_pub_key_for_asn1(pubk); 1.1705 + rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey); 1.1706 + pubk->keyType = dhKey; 1.1707 + break; 1.1708 + default: 1.1709 + rv = SECFailure; 1.1710 + break; 1.1711 + } 1.1712 + 1.1713 +finish: 1.1714 + if (rv != SECSuccess) { 1.1715 + if (arena != NULL) { 1.1716 + PORT_FreeArena(arena, PR_FALSE); 1.1717 + } 1.1718 + pubk = NULL; 1.1719 + } 1.1720 + return pubk; 1.1721 +} 1.1722 + 1.1723 +SECKEYPrivateKeyList* 1.1724 +SECKEY_NewPrivateKeyList(void) 1.1725 +{ 1.1726 + PLArenaPool *arena = NULL; 1.1727 + SECKEYPrivateKeyList *ret = NULL; 1.1728 + 1.1729 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1730 + if ( arena == NULL ) { 1.1731 + goto loser; 1.1732 + } 1.1733 + 1.1734 + ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena, 1.1735 + sizeof(SECKEYPrivateKeyList)); 1.1736 + if ( ret == NULL ) { 1.1737 + goto loser; 1.1738 + } 1.1739 + 1.1740 + ret->arena = arena; 1.1741 + 1.1742 + PR_INIT_CLIST(&ret->list); 1.1743 + 1.1744 + return(ret); 1.1745 + 1.1746 +loser: 1.1747 + if ( arena != NULL ) { 1.1748 + PORT_FreeArena(arena, PR_FALSE); 1.1749 + } 1.1750 + 1.1751 + return(NULL); 1.1752 +} 1.1753 + 1.1754 +void 1.1755 +SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys) 1.1756 +{ 1.1757 + while( !PR_CLIST_IS_EMPTY(&keys->list) ) { 1.1758 + SECKEY_RemovePrivateKeyListNode( 1.1759 + (SECKEYPrivateKeyListNode*)(PR_LIST_HEAD(&keys->list)) ); 1.1760 + } 1.1761 + 1.1762 + PORT_FreeArena(keys->arena, PR_FALSE); 1.1763 + 1.1764 + return; 1.1765 +} 1.1766 + 1.1767 + 1.1768 +void 1.1769 +SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node) 1.1770 +{ 1.1771 + PR_ASSERT(node->key); 1.1772 + SECKEY_DestroyPrivateKey(node->key); 1.1773 + node->key = NULL; 1.1774 + PR_REMOVE_LINK(&node->links); 1.1775 + return; 1.1776 + 1.1777 +} 1.1778 + 1.1779 +SECStatus 1.1780 +SECKEY_AddPrivateKeyToListTail( SECKEYPrivateKeyList *list, 1.1781 + SECKEYPrivateKey *key) 1.1782 +{ 1.1783 + SECKEYPrivateKeyListNode *node; 1.1784 + 1.1785 + node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena, 1.1786 + sizeof(SECKEYPrivateKeyListNode)); 1.1787 + if ( node == NULL ) { 1.1788 + goto loser; 1.1789 + } 1.1790 + 1.1791 + PR_INSERT_BEFORE(&node->links, &list->list); 1.1792 + node->key = key; 1.1793 + return(SECSuccess); 1.1794 + 1.1795 +loser: 1.1796 + return(SECFailure); 1.1797 +} 1.1798 + 1.1799 + 1.1800 +SECKEYPublicKeyList* 1.1801 +SECKEY_NewPublicKeyList(void) 1.1802 +{ 1.1803 + PLArenaPool *arena = NULL; 1.1804 + SECKEYPublicKeyList *ret = NULL; 1.1805 + 1.1806 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.1807 + if ( arena == NULL ) { 1.1808 + goto loser; 1.1809 + } 1.1810 + 1.1811 + ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena, 1.1812 + sizeof(SECKEYPublicKeyList)); 1.1813 + if ( ret == NULL ) { 1.1814 + goto loser; 1.1815 + } 1.1816 + 1.1817 + ret->arena = arena; 1.1818 + 1.1819 + PR_INIT_CLIST(&ret->list); 1.1820 + 1.1821 + return(ret); 1.1822 + 1.1823 +loser: 1.1824 + if ( arena != NULL ) { 1.1825 + PORT_FreeArena(arena, PR_FALSE); 1.1826 + } 1.1827 + 1.1828 + return(NULL); 1.1829 +} 1.1830 + 1.1831 +void 1.1832 +SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys) 1.1833 +{ 1.1834 + while( !PR_CLIST_IS_EMPTY(&keys->list) ) { 1.1835 + SECKEY_RemovePublicKeyListNode( 1.1836 + (SECKEYPublicKeyListNode*)(PR_LIST_HEAD(&keys->list)) ); 1.1837 + } 1.1838 + 1.1839 + PORT_FreeArena(keys->arena, PR_FALSE); 1.1840 + 1.1841 + return; 1.1842 +} 1.1843 + 1.1844 + 1.1845 +void 1.1846 +SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node) 1.1847 +{ 1.1848 + PR_ASSERT(node->key); 1.1849 + SECKEY_DestroyPublicKey(node->key); 1.1850 + node->key = NULL; 1.1851 + PR_REMOVE_LINK(&node->links); 1.1852 + return; 1.1853 + 1.1854 +} 1.1855 + 1.1856 +SECStatus 1.1857 +SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list, 1.1858 + SECKEYPublicKey *key) 1.1859 +{ 1.1860 + SECKEYPublicKeyListNode *node; 1.1861 + 1.1862 + node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena, 1.1863 + sizeof(SECKEYPublicKeyListNode)); 1.1864 + if ( node == NULL ) { 1.1865 + goto loser; 1.1866 + } 1.1867 + 1.1868 + PR_INSERT_BEFORE(&node->links, &list->list); 1.1869 + node->key = key; 1.1870 + return(SECSuccess); 1.1871 + 1.1872 +loser: 1.1873 + return(SECFailure); 1.1874 +} 1.1875 + 1.1876 +#define SECKEY_CacheAttribute(key, attribute) \ 1.1877 + if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \ 1.1878 + key->staticflags |= SECKEY_##attribute; \ 1.1879 + } else { \ 1.1880 + key->staticflags &= (~SECKEY_##attribute); \ 1.1881 + } 1.1882 + 1.1883 +SECStatus 1.1884 +SECKEY_CacheStaticFlags(SECKEYPrivateKey* key) 1.1885 +{ 1.1886 + SECStatus rv = SECFailure; 1.1887 + if (key && key->pkcs11Slot && key->pkcs11ID) { 1.1888 + key->staticflags |= SECKEY_Attributes_Cached; 1.1889 + SECKEY_CacheAttribute(key, CKA_PRIVATE); 1.1890 + SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE); 1.1891 + rv = SECSuccess; 1.1892 + } 1.1893 + return rv; 1.1894 +}