Index: mozilla/security/nss/lib/cryptohi/seckey.c |
=================================================================== |
--- mozilla/security/nss/lib/cryptohi/seckey.c (revision 191424) |
+++ mozilla/security/nss/lib/cryptohi/seckey.c (working copy) |
@@ -1,1937 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-#include "cryptohi.h" |
-#include "keyhi.h" |
-#include "secoid.h" |
-#include "secitem.h" |
-#include "secder.h" |
-#include "base64.h" |
-#include "secasn1.h" |
-#include "cert.h" |
-#include "pk11func.h" |
-#include "secerr.h" |
-#include "secdig.h" |
-#include "prtime.h" |
-#include "keyi.h" |
- |
-SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
-SEC_ASN1_MKSUB(SEC_IntegerTemplate) |
- |
-const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = { |
- { SEC_ASN1_SEQUENCE, |
- 0, NULL, sizeof(CERTSubjectPublicKeyInfo) }, |
- { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
- offsetof(CERTSubjectPublicKeyInfo,algorithm), |
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
- { SEC_ASN1_BIT_STRING, |
- offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), }, |
- { 0, } |
-}; |
- |
-const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] = |
-{ |
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) }, |
- { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) }, |
- { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) }, |
- { 0 } |
-}; |
- |
-const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = { |
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), }, |
- { 0, } |
-}; |
- |
-static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = { |
- { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0, |
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) } |
-}; |
- |
-/* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */ |
-const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] = |
-{ |
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONTEXT_SPECIFIC | 0, |
- offsetof(SECKEYRSAPSSParams, hashAlg), |
- seckey_PointerToAlgorithmIDTemplate }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_CONTEXT_SPECIFIC | 1, |
- offsetof(SECKEYRSAPSSParams, maskAlg), |
- seckey_PointerToAlgorithmIDTemplate }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2, |
- offsetof(SECKEYRSAPSSParams, saltLength), |
- SEC_ASN1_SUB(SEC_IntegerTemplate) }, |
- { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | |
- SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3, |
- offsetof(SECKEYRSAPSSParams, trailerField), |
- SEC_ASN1_SUB(SEC_IntegerTemplate) }, |
- { 0 } |
-}; |
- |
-const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = { |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), }, |
- { 0, } |
-}; |
- |
-const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { |
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) }, |
- { 0, } |
-}; |
- |
-const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = { |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), }, |
- { 0, } |
-}; |
- |
-const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = { |
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), }, |
- { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), }, |
- /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */ |
- { SEC_ASN1_SKIP_REST }, |
- { 0, } |
-}; |
- |
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate) |
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate) |
-SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate) |
-SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate) |
- |
-/* |
- * See bugzilla bug 125359 |
- * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, |
- * all of the templates above that en/decode into integers must be converted |
- * from ASN.1's signed integer type. This is done by marking either the |
- * source or destination (encoding or decoding, respectively) type as |
- * siUnsignedInteger. |
- */ |
-static void |
-prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk) |
-{ |
- pubk->u.rsa.modulus.type = siUnsignedInteger; |
- pubk->u.rsa.publicExponent.type = siUnsignedInteger; |
-} |
- |
-static void |
-prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk) |
-{ |
- pubk->u.dsa.publicValue.type = siUnsignedInteger; |
-} |
- |
-static void |
-prepare_pqg_params_for_asn1(SECKEYPQGParams *params) |
-{ |
- params->prime.type = siUnsignedInteger; |
- params->subPrime.type = siUnsignedInteger; |
- params->base.type = siUnsignedInteger; |
-} |
- |
-static void |
-prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk) |
-{ |
- pubk->u.dh.prime.type = siUnsignedInteger; |
- pubk->u.dh.base.type = siUnsignedInteger; |
- pubk->u.dh.publicValue.type = siUnsignedInteger; |
-} |
- |
-/* Create an RSA key pair is any slot able to do so. |
-** The created keys are "session" (temporary), not "token" (permanent), |
-** and they are "sensitive", which makes them costly to move to another token. |
-*/ |
-SECKEYPrivateKey * |
-SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx) |
-{ |
- SECKEYPrivateKey *privk; |
- PK11RSAGenParams param; |
- PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx); |
- if (!slot) { |
- return NULL; |
- } |
- |
- param.keySizeInBits = keySizeInBits; |
- param.pe = 65537L; |
- |
- privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,¶m,pubk, |
- PR_FALSE, PR_TRUE, cx); |
- PK11_FreeSlot(slot); |
- return(privk); |
-} |
- |
-/* Create a DH key pair in any slot able to do so, |
-** This is a "session" (temporary), not "token" (permanent) key. |
-** Because of the high probability that this key will need to be moved to |
-** another token, and the high cost of moving "sensitive" keys, we attempt |
-** to create this key pair without the "sensitive" attribute, but revert to |
-** creating a "sensitive" key if necessary. |
-*/ |
-SECKEYPrivateKey * |
-SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx) |
-{ |
- SECKEYPrivateKey *privk; |
- PK11SlotInfo *slot; |
- |
- if (!param || !param->base.data || !param->prime.data || |
- param->prime.len < 512/8 || param->base.len == 0 || |
- param->base.len > param->prime.len + 1 || |
- (param->base.len == 1 && param->base.data[0] == 0)) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx); |
- if (!slot) { |
- return NULL; |
- } |
- |
- privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, |
- pubk, PR_FALSE, PR_FALSE, cx); |
- if (!privk) |
- privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, |
- pubk, PR_FALSE, PR_TRUE, cx); |
- |
- PK11_FreeSlot(slot); |
- return(privk); |
-} |
- |
-/* Create an EC key pair in any slot able to do so, |
-** This is a "session" (temporary), not "token" (permanent) key. |
-** Because of the high probability that this key will need to be moved to |
-** another token, and the high cost of moving "sensitive" keys, we attempt |
-** to create this key pair without the "sensitive" attribute, but revert to |
-** creating a "sensitive" key if necessary. |
-*/ |
-SECKEYPrivateKey * |
-SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx) |
-{ |
- SECKEYPrivateKey *privk; |
- PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx); |
- if (!slot) { |
- return NULL; |
- } |
- |
- privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, |
- param, pubk, |
- PK11_ATTR_SESSION | PK11_ATTR_INSENSITIVE | |
- PK11_ATTR_PUBLIC, |
- CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx); |
- if (!privk) |
- privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, |
- param, pubk, |
- PK11_ATTR_SESSION | PK11_ATTR_SENSITIVE | |
- PK11_ATTR_PRIVATE, |
- CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx); |
- |
- PK11_FreeSlot(slot); |
- return(privk); |
-} |
- |
-void |
-SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk) |
-{ |
- if (privk) { |
- if (privk->pkcs11Slot) { |
- if (privk->pkcs11IsTemp) { |
- PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID); |
- } |
- PK11_FreeSlot(privk->pkcs11Slot); |
- |
- } |
- if (privk->arena) { |
- PORT_FreeArena(privk->arena, PR_TRUE); |
- } |
- } |
-} |
- |
-void |
-SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk) |
-{ |
- if (pubk) { |
- if (pubk->pkcs11Slot) { |
- if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) { |
- PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID); |
- } |
- PK11_FreeSlot(pubk->pkcs11Slot); |
- } |
- if (pubk->arena) { |
- PORT_FreeArena(pubk->arena, PR_FALSE); |
- } |
- } |
-} |
- |
-SECStatus |
-SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena, |
- CERTSubjectPublicKeyInfo *to, |
- CERTSubjectPublicKeyInfo *from) |
-{ |
- SECStatus rv; |
- SECItem spk; |
- |
- rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm); |
- if (rv == SECSuccess) { |
- /* |
- * subjectPublicKey is a bit string, whose length is in bits. |
- * Convert the length from bits to bytes for SECITEM_CopyItem. |
- */ |
- spk = from->subjectPublicKey; |
- DER_ConvertBitString(&spk); |
- rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk); |
- /* Set the length back to bits. */ |
- if (rv == SECSuccess) { |
- to->subjectPublicKey.len = from->subjectPublicKey.len; |
- } |
- } |
- |
- return rv; |
-} |
- |
-/* Procedure to update the pqg parameters for a cert's public key. |
- * pqg parameters only need to be updated for DSA certificates. |
- * The procedure uses calls to itself recursively to update a certificate |
- * issuer's pqg parameters. Some important rules are: |
- * - Do nothing if the cert already has PQG parameters. |
- * - If the cert does not have PQG parameters, obtain them from the issuer. |
- * - A valid cert chain cannot have a DSA cert without |
- * pqg parameters that has a parent that is not a DSA cert. */ |
- |
-static SECStatus |
-seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count) |
-{ |
- SECStatus rv; |
- SECOidData *oid=NULL; |
- int tag; |
- CERTSubjectPublicKeyInfo * subjectSpki=NULL; |
- CERTSubjectPublicKeyInfo * issuerSpki=NULL; |
- CERTCertificate *issuerCert = NULL; |
- |
- rv = SECSuccess; |
- |
- /* increment cert chain length counter*/ |
- count++; |
- |
- /* check if cert chain length exceeds the maximum length*/ |
- if (count > CERT_MAX_CERT_CHAIN) { |
- return SECFailure; |
- } |
- |
- oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm); |
- if (oid != NULL) { |
- tag = oid->offset; |
- |
- /* Check if cert has a DSA or EC public key. If not, return |
- * success since no PQG params need to be updated. |
- * |
- * Question: do we really need to do this for EC keys. They don't have |
- * PQG parameters, but they do have parameters. The question is does |
- * the child cert inherit thost parameters for EC from the parent, or |
- * do we always include those parameters in each cert. |
- */ |
- |
- if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) && |
- (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) && |
- (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) && |
- (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && |
- (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && |
- (tag != SEC_OID_SDN702_DSA_SIGNATURE) && |
- (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { |
- |
- return SECSuccess; |
- } |
- } else { |
- return SECFailure; /* return failure if oid is NULL */ |
- } |
- |
- /* if cert has PQG parameters, return success */ |
- |
- subjectSpki=&subjectCert->subjectPublicKeyInfo; |
- |
- if (subjectSpki->algorithm.parameters.len != 0) { |
- return SECSuccess; |
- } |
- |
- /* check if the cert is self-signed */ |
- if (subjectCert->isRoot) { |
- /* fail since cert is self-signed and has no pqg params. */ |
- return SECFailure; |
- } |
- |
- /* get issuer cert */ |
- issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA); |
- if ( ! issuerCert ) { |
- return SECFailure; |
- } |
- |
- /* if parent is not DSA, return failure since |
- we don't allow this case. */ |
- |
- oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm); |
- if (oid != NULL) { |
- tag = oid->offset; |
- |
- /* Check if issuer cert has a DSA public key. If not, |
- * return failure. */ |
- |
- if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) && |
- (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) && |
- (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) && |
- (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) && |
- (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) && |
- (tag != SEC_OID_SDN702_DSA_SIGNATURE) && |
- (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) { |
- rv = SECFailure; |
- goto loser; |
- } |
- } else { |
- rv = SECFailure; /* return failure if oid is NULL */ |
- goto loser; |
- } |
- |
- |
- /* at this point the subject cert has no pqg parameters and the |
- * issuer cert has a DSA public key. Update the issuer's |
- * pqg parameters with a recursive call to this same function. */ |
- |
- rv = seckey_UpdateCertPQGChain(issuerCert, count); |
- if (rv != SECSuccess) { |
- rv = SECFailure; |
- goto loser; |
- } |
- |
- /* ensure issuer has pqg parameters */ |
- |
- issuerSpki=&issuerCert->subjectPublicKeyInfo; |
- if (issuerSpki->algorithm.parameters.len == 0) { |
- rv = SECFailure; |
- } |
- |
- /* if update was successful and pqg params present, then copy the |
- * parameters to the subject cert's key. */ |
- |
- if (rv == SECSuccess) { |
- rv = SECITEM_CopyItem(subjectCert->arena, |
- &subjectSpki->algorithm.parameters, |
- &issuerSpki->algorithm.parameters); |
- } |
- |
-loser: |
- if (issuerCert) { |
- CERT_DestroyCertificate(issuerCert); |
- } |
- return rv; |
- |
-} |
- |
- |
-SECStatus |
-SECKEY_UpdateCertPQG(CERTCertificate * subjectCert) |
-{ |
- if (!subjectCert) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return SECFailure; |
- } |
- return seckey_UpdateCertPQGChain(subjectCert,0); |
-} |
- |
- |
-/* Decode the DSA PQG parameters. The params could be stored in two |
- * possible formats, the old fortezza-only wrapped format or |
- * the normal standard format. Store the decoded parameters in |
- * a V3 certificate data structure. */ |
- |
-SECStatus |
-SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params) { |
- SECStatus rv; |
- SECItem newparams; |
- |
- if (params == NULL) return SECFailure; |
- |
- if (params->data == NULL) return SECFailure; |
- |
- PORT_Assert(arena); |
- |
- /* make a copy of the data into the arena so QuickDER output is valid */ |
- rv = SECITEM_CopyItem(arena, &newparams, params); |
- |
- /* Check if params use the standard format. |
- * The value 0xa1 will appear in the first byte of the parameter data |
- * if the PQG parameters are not using the standard format. This |
- * code should be changed to use a better method to detect non-standard |
- * parameters. */ |
- |
- if ((newparams.data[0] != 0xa1) && |
- (newparams.data[0] != 0xa0)) { |
- |
- if (SECSuccess == rv) { |
- /* PQG params are in the standard format */ |
- prepare_pqg_params_for_asn1(&pubk->u.dsa.params); |
- rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params, |
- SECKEY_PQGParamsTemplate, |
- &newparams); |
- } |
- } else { |
- |
- if (SECSuccess == rv) { |
- /* else the old fortezza-only wrapped format is used. */ |
- PORT_SetError(SEC_ERROR_BAD_DER); |
- rv = SECFailure; |
- } |
- } |
- return rv; |
-} |
- |
- |
-/* Function used to make an oid tag to a key type */ |
-KeyType |
-seckey_GetKeyType (SECOidTag tag) { |
- KeyType keyType; |
- |
- switch (tag) { |
- case SEC_OID_X500_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_RSA_ENCRYPTION: |
- keyType = rsaKey; |
- break; |
- case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
- keyType = rsaPssKey; |
- break; |
- case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION: |
- keyType = rsaOaepKey; |
- break; |
- case SEC_OID_ANSIX9_DSA_SIGNATURE: |
- keyType = dsaKey; |
- break; |
- case SEC_OID_MISSI_KEA_DSS_OLD: |
- case SEC_OID_MISSI_KEA_DSS: |
- case SEC_OID_MISSI_DSS_OLD: |
- case SEC_OID_MISSI_DSS: |
- keyType = fortezzaKey; |
- break; |
- case SEC_OID_MISSI_KEA: |
- case SEC_OID_MISSI_ALT_KEA: |
- keyType = keaKey; |
- break; |
- case SEC_OID_X942_DIFFIE_HELMAN_KEY: |
- keyType = dhKey; |
- break; |
- case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
- keyType = ecKey; |
- break; |
- /* accommodate applications that hand us a signature type when they |
- * should be handing us a cipher type */ |
- case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: |
- keyType = rsaKey; |
- break; |
- default: |
- keyType = nullKey; |
- } |
- return keyType; |
-} |
- |
-/* Function used to determine what kind of cert we are dealing with. */ |
-KeyType |
-CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) |
-{ |
- return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm)); |
-} |
- |
-static SECKEYPublicKey * |
-seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) |
-{ |
- SECKEYPublicKey *pubk; |
- SECItem os, newOs, newParms; |
- SECStatus rv; |
- PRArenaPool *arena; |
- SECOidTag tag; |
- |
- arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) |
- return NULL; |
- |
- pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); |
- if (pubk == NULL) { |
- PORT_FreeArena (arena, PR_FALSE); |
- return NULL; |
- } |
- |
- pubk->arena = arena; |
- pubk->pkcs11Slot = 0; |
- pubk->pkcs11ID = CK_INVALID_HANDLE; |
- |
- |
- /* Convert bit string length from bits to bytes */ |
- os = spki->subjectPublicKey; |
- DER_ConvertBitString (&os); |
- |
- tag = SECOID_GetAlgorithmTag(&spki->algorithm); |
- |
- /* copy the DER into the arena, since Quick DER returns data that points |
- into the DER input, which may get freed by the caller */ |
- rv = SECITEM_CopyItem(arena, &newOs, &os); |
- if ( rv == SECSuccess ) |
- switch ( tag ) { |
- case SEC_OID_X500_RSA_ENCRYPTION: |
- case SEC_OID_PKCS1_RSA_ENCRYPTION: |
- pubk->keyType = rsaKey; |
- prepare_rsa_pub_key_for_asn1(pubk); |
- rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs); |
- if (rv == SECSuccess) |
- return pubk; |
- break; |
- case SEC_OID_ANSIX9_DSA_SIGNATURE: |
- case SEC_OID_SDN702_DSA_SIGNATURE: |
- pubk->keyType = dsaKey; |
- prepare_dsa_pub_key_for_asn1(pubk); |
- rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs); |
- if (rv != SECSuccess) break; |
- |
- rv = SECKEY_DSADecodePQG(arena, pubk, |
- &spki->algorithm.parameters); |
- |
- if (rv == SECSuccess) return pubk; |
- break; |
- case SEC_OID_X942_DIFFIE_HELMAN_KEY: |
- pubk->keyType = dhKey; |
- prepare_dh_pub_key_for_asn1(pubk); |
- rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs); |
- if (rv != SECSuccess) break; |
- |
- /* copy the DER into the arena, since Quick DER returns data that points |
- into the DER input, which may get freed by the caller */ |
- rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters); |
- if ( rv != SECSuccess ) |
- break; |
- |
- rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate, |
- &newParms); |
- |
- if (rv == SECSuccess) return pubk; |
- break; |
- case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
- pubk->keyType = ecKey; |
- pubk->u.ec.size = 0; |
- |
- /* Since PKCS#11 directly takes the DER encoding of EC params |
- * and public value, we don't need any decoding here. |
- */ |
- rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams, |
- &spki->algorithm.parameters); |
- if ( rv != SECSuccess ) |
- break; |
- rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs); |
- if (rv == SECSuccess) return pubk; |
- break; |
- |
- default: |
- PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
- rv = SECFailure; |
- break; |
- } |
- |
- SECKEY_DestroyPublicKey (pubk); |
- return NULL; |
-} |
- |
- |
-/* required for JSS */ |
-SECKEYPublicKey * |
-SECKEY_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) |
-{ |
- return seckey_ExtractPublicKey(spki); |
-} |
- |
-SECKEYPublicKey * |
-CERT_ExtractPublicKey(CERTCertificate *cert) |
-{ |
- SECStatus rv; |
- |
- if (!cert) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- rv = SECKEY_UpdateCertPQG(cert); |
- if (rv != SECSuccess) return NULL; |
- |
- return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo); |
-} |
- |
-int |
-SECKEY_ECParamsToKeySize(const SECItem *encodedParams) |
-{ |
- SECOidTag tag; |
- SECItem oid = { siBuffer, NULL, 0}; |
- |
- /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), |
- * followed by the length of the curve oid and the curve oid. |
- */ |
- oid.len = encodedParams->data[1]; |
- oid.data = encodedParams->data + 2; |
- if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN) |
- return 0; |
- |
- switch (tag) { |
- case SEC_OID_SECG_EC_SECP112R1: |
- case SEC_OID_SECG_EC_SECP112R2: |
- return 112; |
- |
- case SEC_OID_SECG_EC_SECT113R1: |
- case SEC_OID_SECG_EC_SECT113R2: |
- return 113; |
- |
- case SEC_OID_SECG_EC_SECP128R1: |
- case SEC_OID_SECG_EC_SECP128R2: |
- return 128; |
- |
- case SEC_OID_SECG_EC_SECT131R1: |
- case SEC_OID_SECG_EC_SECT131R2: |
- return 131; |
- |
- case SEC_OID_SECG_EC_SECP160K1: |
- case SEC_OID_SECG_EC_SECP160R1: |
- case SEC_OID_SECG_EC_SECP160R2: |
- return 160; |
- |
- case SEC_OID_SECG_EC_SECT163K1: |
- case SEC_OID_SECG_EC_SECT163R1: |
- case SEC_OID_SECG_EC_SECT163R2: |
- case SEC_OID_ANSIX962_EC_C2PNB163V1: |
- case SEC_OID_ANSIX962_EC_C2PNB163V2: |
- case SEC_OID_ANSIX962_EC_C2PNB163V3: |
- return 163; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB176V1: |
- return 176; |
- |
- case SEC_OID_ANSIX962_EC_C2TNB191V1: |
- case SEC_OID_ANSIX962_EC_C2TNB191V2: |
- case SEC_OID_ANSIX962_EC_C2TNB191V3: |
- case SEC_OID_ANSIX962_EC_C2ONB191V4: |
- case SEC_OID_ANSIX962_EC_C2ONB191V5: |
- return 191; |
- |
- case SEC_OID_SECG_EC_SECP192K1: |
- case SEC_OID_ANSIX962_EC_PRIME192V1: |
- case SEC_OID_ANSIX962_EC_PRIME192V2: |
- case SEC_OID_ANSIX962_EC_PRIME192V3: |
- return 192; |
- |
- case SEC_OID_SECG_EC_SECT193R1: |
- case SEC_OID_SECG_EC_SECT193R2: |
- return 193; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB208W1: |
- return 208; |
- |
- case SEC_OID_SECG_EC_SECP224K1: |
- case SEC_OID_SECG_EC_SECP224R1: |
- return 224; |
- |
- case SEC_OID_SECG_EC_SECT233K1: |
- case SEC_OID_SECG_EC_SECT233R1: |
- return 233; |
- |
- case SEC_OID_SECG_EC_SECT239K1: |
- case SEC_OID_ANSIX962_EC_C2TNB239V1: |
- case SEC_OID_ANSIX962_EC_C2TNB239V2: |
- case SEC_OID_ANSIX962_EC_C2TNB239V3: |
- case SEC_OID_ANSIX962_EC_C2ONB239V4: |
- case SEC_OID_ANSIX962_EC_C2ONB239V5: |
- case SEC_OID_ANSIX962_EC_PRIME239V1: |
- case SEC_OID_ANSIX962_EC_PRIME239V2: |
- case SEC_OID_ANSIX962_EC_PRIME239V3: |
- return 239; |
- |
- case SEC_OID_SECG_EC_SECP256K1: |
- case SEC_OID_ANSIX962_EC_PRIME256V1: |
- return 256; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB272W1: |
- return 272; |
- |
- case SEC_OID_SECG_EC_SECT283K1: |
- case SEC_OID_SECG_EC_SECT283R1: |
- return 283; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB304W1: |
- return 304; |
- |
- case SEC_OID_ANSIX962_EC_C2TNB359V1: |
- return 359; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB368W1: |
- return 368; |
- |
- case SEC_OID_SECG_EC_SECP384R1: |
- return 384; |
- |
- case SEC_OID_SECG_EC_SECT409K1: |
- case SEC_OID_SECG_EC_SECT409R1: |
- return 409; |
- |
- case SEC_OID_ANSIX962_EC_C2TNB431R1: |
- return 431; |
- |
- case SEC_OID_SECG_EC_SECP521R1: |
- return 521; |
- |
- case SEC_OID_SECG_EC_SECT571K1: |
- case SEC_OID_SECG_EC_SECT571R1: |
- return 571; |
- |
- default: |
- PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); |
- return 0; |
- } |
-} |
- |
-int |
-SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams) |
-{ |
- SECOidTag tag; |
- SECItem oid = { siBuffer, NULL, 0}; |
- |
- /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), |
- * followed by the length of the curve oid and the curve oid. |
- */ |
- oid.len = encodedParams->data[1]; |
- oid.data = encodedParams->data + 2; |
- if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN) |
- return 0; |
- |
- switch (tag) { |
- case SEC_OID_SECG_EC_SECP112R1: |
- return 112; |
- case SEC_OID_SECG_EC_SECP112R2: |
- return 110; |
- |
- case SEC_OID_SECG_EC_SECT113R1: |
- case SEC_OID_SECG_EC_SECT113R2: |
- return 113; |
- |
- case SEC_OID_SECG_EC_SECP128R1: |
- return 128; |
- case SEC_OID_SECG_EC_SECP128R2: |
- return 126; |
- |
- case SEC_OID_SECG_EC_SECT131R1: |
- case SEC_OID_SECG_EC_SECT131R2: |
- return 131; |
- |
- case SEC_OID_SECG_EC_SECP160K1: |
- case SEC_OID_SECG_EC_SECP160R1: |
- case SEC_OID_SECG_EC_SECP160R2: |
- return 161; |
- |
- case SEC_OID_SECG_EC_SECT163K1: |
- return 163; |
- case SEC_OID_SECG_EC_SECT163R1: |
- return 162; |
- case SEC_OID_SECG_EC_SECT163R2: |
- case SEC_OID_ANSIX962_EC_C2PNB163V1: |
- return 163; |
- case SEC_OID_ANSIX962_EC_C2PNB163V2: |
- case SEC_OID_ANSIX962_EC_C2PNB163V3: |
- return 162; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB176V1: |
- return 161; |
- |
- case SEC_OID_ANSIX962_EC_C2TNB191V1: |
- return 191; |
- case SEC_OID_ANSIX962_EC_C2TNB191V2: |
- return 190; |
- case SEC_OID_ANSIX962_EC_C2TNB191V3: |
- return 189; |
- case SEC_OID_ANSIX962_EC_C2ONB191V4: |
- return 191; |
- case SEC_OID_ANSIX962_EC_C2ONB191V5: |
- return 188; |
- |
- case SEC_OID_SECG_EC_SECP192K1: |
- case SEC_OID_ANSIX962_EC_PRIME192V1: |
- case SEC_OID_ANSIX962_EC_PRIME192V2: |
- case SEC_OID_ANSIX962_EC_PRIME192V3: |
- return 192; |
- |
- case SEC_OID_SECG_EC_SECT193R1: |
- case SEC_OID_SECG_EC_SECT193R2: |
- return 193; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB208W1: |
- return 193; |
- |
- case SEC_OID_SECG_EC_SECP224K1: |
- return 225; |
- case SEC_OID_SECG_EC_SECP224R1: |
- return 224; |
- |
- case SEC_OID_SECG_EC_SECT233K1: |
- return 232; |
- case SEC_OID_SECG_EC_SECT233R1: |
- return 233; |
- |
- case SEC_OID_SECG_EC_SECT239K1: |
- case SEC_OID_ANSIX962_EC_C2TNB239V1: |
- return 238; |
- case SEC_OID_ANSIX962_EC_C2TNB239V2: |
- return 237; |
- case SEC_OID_ANSIX962_EC_C2TNB239V3: |
- return 236; |
- case SEC_OID_ANSIX962_EC_C2ONB239V4: |
- return 238; |
- case SEC_OID_ANSIX962_EC_C2ONB239V5: |
- return 237; |
- case SEC_OID_ANSIX962_EC_PRIME239V1: |
- case SEC_OID_ANSIX962_EC_PRIME239V2: |
- case SEC_OID_ANSIX962_EC_PRIME239V3: |
- return 239; |
- |
- case SEC_OID_SECG_EC_SECP256K1: |
- case SEC_OID_ANSIX962_EC_PRIME256V1: |
- return 256; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB272W1: |
- return 257; |
- |
- case SEC_OID_SECG_EC_SECT283K1: |
- return 281; |
- case SEC_OID_SECG_EC_SECT283R1: |
- return 282; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB304W1: |
- return 289; |
- |
- case SEC_OID_ANSIX962_EC_C2TNB359V1: |
- return 353; |
- |
- case SEC_OID_ANSIX962_EC_C2PNB368W1: |
- return 353; |
- |
- case SEC_OID_SECG_EC_SECP384R1: |
- return 384; |
- |
- case SEC_OID_SECG_EC_SECT409K1: |
- return 407; |
- case SEC_OID_SECG_EC_SECT409R1: |
- return 409; |
- |
- case SEC_OID_ANSIX962_EC_C2TNB431R1: |
- return 418; |
- |
- case SEC_OID_SECG_EC_SECP521R1: |
- return 521; |
- |
- case SEC_OID_SECG_EC_SECT571K1: |
- case SEC_OID_SECG_EC_SECT571R1: |
- return 570; |
- |
- default: |
- PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); |
- return 0; |
- } |
-} |
- |
-/* returns key strength in bytes (not bits) */ |
-unsigned |
-SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk) |
-{ |
- unsigned char b0; |
- unsigned size; |
- |
- /* interpret modulus length as key strength */ |
- if (!pubk) |
- goto loser; |
- switch (pubk->keyType) { |
- case rsaKey: |
- if (!pubk->u.rsa.modulus.data) break; |
- b0 = pubk->u.rsa.modulus.data[0]; |
- return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; |
- case dsaKey: |
- if (!pubk->u.dsa.publicValue.data) break; |
- b0 = pubk->u.dsa.publicValue.data[0]; |
- return b0 ? pubk->u.dsa.publicValue.len : |
- pubk->u.dsa.publicValue.len - 1; |
- case dhKey: |
- if (!pubk->u.dh.publicValue.data) break; |
- b0 = pubk->u.dh.publicValue.data[0]; |
- return b0 ? pubk->u.dh.publicValue.len : |
- pubk->u.dh.publicValue.len - 1; |
- case ecKey: |
- /* Get the key size in bits and adjust */ |
- size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); |
- return (size + 7)/8; |
- default: |
- break; |
- } |
-loser: |
- PORT_SetError(SEC_ERROR_INVALID_KEY); |
- return 0; |
-} |
- |
-/* returns key strength in bits */ |
-unsigned |
-SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk) |
-{ |
- unsigned size; |
- switch (pubk->keyType) { |
- case rsaKey: |
- case dsaKey: |
- case dhKey: |
- return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */ |
- case ecKey: |
- size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); |
- return size; |
- default: |
- break; |
- } |
- PORT_SetError(SEC_ERROR_INVALID_KEY); |
- return 0; |
-} |
- |
-/* returns signature length in bytes (not bits) */ |
-unsigned |
-SECKEY_SignatureLen(const SECKEYPublicKey *pubk) |
-{ |
- unsigned char b0; |
- unsigned size; |
- |
- switch (pubk->keyType) { |
- case rsaKey: |
- b0 = pubk->u.rsa.modulus.data[0]; |
- return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1; |
- case dsaKey: |
- return pubk->u.dsa.params.subPrime.len * 2; |
- case ecKey: |
- /* Get the base point order length in bits and adjust */ |
- size = SECKEY_ECParamsToBasePointOrderLen( |
- &pubk->u.ec.DEREncodedParams); |
- return ((size + 7)/8) * 2; |
- default: |
- break; |
- } |
- PORT_SetError(SEC_ERROR_INVALID_KEY); |
- return 0; |
-} |
- |
-SECKEYPrivateKey * |
-SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk) |
-{ |
- SECKEYPrivateKey *copyk; |
- PRArenaPool *arena; |
- |
- if (!privk || !privk->pkcs11Slot) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- return NULL; |
- } |
- |
- copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey)); |
- if (copyk) { |
- copyk->arena = arena; |
- copyk->keyType = privk->keyType; |
- |
- /* copy the PKCS #11 parameters */ |
- copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot); |
- /* if the key we're referencing was a temparary key we have just |
- * created, that we want to go away when we're through, we need |
- * to make a copy of it */ |
- if (privk->pkcs11IsTemp) { |
- copyk->pkcs11ID = |
- PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID); |
- if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail; |
- } else { |
- copyk->pkcs11ID = privk->pkcs11ID; |
- } |
- copyk->pkcs11IsTemp = privk->pkcs11IsTemp; |
- copyk->wincx = privk->wincx; |
- copyk->staticflags = privk->staticflags; |
- return copyk; |
- } else { |
- PORT_SetError (SEC_ERROR_NO_MEMORY); |
- } |
- |
-fail: |
- PORT_FreeArena (arena, PR_FALSE); |
- return NULL; |
-} |
- |
-SECKEYPublicKey * |
-SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk) |
-{ |
- SECKEYPublicKey *copyk; |
- PRArenaPool *arena; |
- SECStatus rv = SECSuccess; |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- PORT_SetError (SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey)); |
- if (!copyk) { |
- PORT_FreeArena (arena, PR_FALSE); |
- PORT_SetError (SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- copyk->arena = arena; |
- copyk->keyType = pubk->keyType; |
- if (pubk->pkcs11Slot && |
- PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) { |
- copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot); |
- copyk->pkcs11ID = pubk->pkcs11ID; |
- } else { |
- copyk->pkcs11Slot = NULL; /* go get own reference */ |
- copyk->pkcs11ID = CK_INVALID_HANDLE; |
- } |
- switch (pubk->keyType) { |
- case rsaKey: |
- rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus, |
- &pubk->u.rsa.modulus); |
- if (rv == SECSuccess) { |
- rv = SECITEM_CopyItem (arena, ©k->u.rsa.publicExponent, |
- &pubk->u.rsa.publicExponent); |
- if (rv == SECSuccess) |
- return copyk; |
- } |
- break; |
- case dsaKey: |
- rv = SECITEM_CopyItem(arena, ©k->u.dsa.publicValue, |
- &pubk->u.dsa.publicValue); |
- if (rv != SECSuccess) break; |
- rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.prime, |
- &pubk->u.dsa.params.prime); |
- if (rv != SECSuccess) break; |
- rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.subPrime, |
- &pubk->u.dsa.params.subPrime); |
- if (rv != SECSuccess) break; |
- rv = SECITEM_CopyItem(arena, ©k->u.dsa.params.base, |
- &pubk->u.dsa.params.base); |
- break; |
- case dhKey: |
- rv = SECITEM_CopyItem(arena,©k->u.dh.prime,&pubk->u.dh.prime); |
- if (rv != SECSuccess) break; |
- rv = SECITEM_CopyItem(arena,©k->u.dh.base,&pubk->u.dh.base); |
- if (rv != SECSuccess) break; |
- rv = SECITEM_CopyItem(arena, ©k->u.dh.publicValue, |
- &pubk->u.dh.publicValue); |
- break; |
- case ecKey: |
- copyk->u.ec.size = pubk->u.ec.size; |
- rv = SECITEM_CopyItem(arena,©k->u.ec.DEREncodedParams, |
- &pubk->u.ec.DEREncodedParams); |
- if (rv != SECSuccess) break; |
- rv = SECITEM_CopyItem(arena,©k->u.ec.publicValue, |
- &pubk->u.ec.publicValue); |
- break; |
- case nullKey: |
- return copyk; |
- default: |
- PORT_SetError(SEC_ERROR_INVALID_KEY); |
- rv = SECFailure; |
- break; |
- } |
- if (rv == SECSuccess) |
- return copyk; |
- |
- SECKEY_DestroyPublicKey (copyk); |
- return NULL; |
-} |
- |
- |
-SECKEYPublicKey * |
-SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) |
-{ |
- SECKEYPublicKey *pubk; |
- PRArenaPool *arena; |
- CERTCertificate *cert; |
- SECStatus rv; |
- |
- /* |
- * First try to look up the cert. |
- */ |
- cert = PK11_GetCertFromPrivateKey(privk); |
- if (cert) { |
- pubk = CERT_ExtractPublicKey(cert); |
- CERT_DestroyCertificate(cert); |
- return pubk; |
- } |
- |
- /* couldn't find the cert, build pub key by hand */ |
- arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- PORT_SetError (SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, |
- sizeof (SECKEYPublicKey)); |
- if (pubk == NULL) { |
- PORT_FreeArena(arena,PR_FALSE); |
- return NULL; |
- } |
- pubk->keyType = privk->keyType; |
- pubk->pkcs11Slot = NULL; |
- pubk->pkcs11ID = CK_INVALID_HANDLE; |
- pubk->arena = arena; |
- |
- switch(privk->keyType) { |
- case nullKey: |
- case dhKey: |
- case dsaKey: |
- /* Nothing to query, if the cert isn't there, we're done -- no way |
- * to get the public key */ |
- break; |
- case rsaKey: |
- rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID, |
- CKA_MODULUS,arena,&pubk->u.rsa.modulus); |
- if (rv != SECSuccess) break; |
- rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID, |
- CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent); |
- if (rv != SECSuccess) break; |
- return pubk; |
- break; |
- default: |
- break; |
- } |
- |
- PORT_FreeArena (arena, PR_FALSE); |
- return NULL; |
-} |
- |
-CERTSubjectPublicKeyInfo * |
-SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk) |
-{ |
- CERTSubjectPublicKeyInfo *spki; |
- PRArenaPool *arena; |
- SECItem params = { siBuffer, NULL, 0 }; |
- |
- if (!pubk) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki)); |
- if (spki != NULL) { |
- SECStatus rv; |
- SECItem *rv_item; |
- |
- spki->arena = arena; |
- switch(pubk->keyType) { |
- case rsaKey: |
- rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, |
- SEC_OID_PKCS1_RSA_ENCRYPTION, 0); |
- if (rv == SECSuccess) { |
- /* |
- * DER encode the public key into the subjectPublicKeyInfo. |
- */ |
- prepare_rsa_pub_key_for_asn1(pubk); |
- rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, |
- pubk, SECKEY_RSAPublicKeyTemplate); |
- if (rv_item != NULL) { |
- /* |
- * The stored value is supposed to be a BIT_STRING, |
- * so convert the length. |
- */ |
- spki->subjectPublicKey.len <<= 3; |
- /* |
- * We got a good one; return it. |
- */ |
- return spki; |
- } |
- } |
- break; |
- case dsaKey: |
- /* DER encode the params. */ |
- prepare_pqg_params_for_asn1(&pubk->u.dsa.params); |
- rv_item = SEC_ASN1EncodeItem(arena, ¶ms, &pubk->u.dsa.params, |
- SECKEY_PQGParamsTemplate); |
- if (rv_item != NULL) { |
- rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, |
- SEC_OID_ANSIX9_DSA_SIGNATURE, |
- ¶ms); |
- if (rv == SECSuccess) { |
- /* |
- * DER encode the public key into the subjectPublicKeyInfo. |
- */ |
- prepare_dsa_pub_key_for_asn1(pubk); |
- rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, |
- pubk, |
- SECKEY_DSAPublicKeyTemplate); |
- if (rv_item != NULL) { |
- /* |
- * The stored value is supposed to be a BIT_STRING, |
- * so convert the length. |
- */ |
- spki->subjectPublicKey.len <<= 3; |
- /* |
- * We got a good one; return it. |
- */ |
- return spki; |
- } |
- } |
- } |
- SECITEM_FreeItem(¶ms, PR_FALSE); |
- break; |
- case ecKey: |
- rv = SECITEM_CopyItem(arena, ¶ms, |
- &pubk->u.ec.DEREncodedParams); |
- if (rv != SECSuccess) break; |
- |
- rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, |
- SEC_OID_ANSIX962_EC_PUBLIC_KEY, |
- ¶ms); |
- if (rv != SECSuccess) break; |
- |
- rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey, |
- &pubk->u.ec.publicValue); |
- |
- if (rv == SECSuccess) { |
- /* |
- * The stored value is supposed to be a BIT_STRING, |
- * so convert the length. |
- */ |
- spki->subjectPublicKey.len <<= 3; |
- /* |
- * We got a good one; return it. |
- */ |
- return spki; |
- } |
- break; |
- case dhKey: /* later... */ |
- |
- break; |
- default: |
- break; |
- } |
- } else { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- } |
- |
- PORT_FreeArena(arena, PR_FALSE); |
- return NULL; |
-} |
- |
-void |
-SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki) |
-{ |
- if (spki && spki->arena) { |
- PORT_FreeArena(spki->arena, PR_FALSE); |
- } |
-} |
- |
-/* |
- * this only works for RSA keys... need to do something |
- * similiar to CERT_ExtractPublicKey for other key times. |
- */ |
-SECKEYPublicKey * |
-SECKEY_DecodeDERPublicKey(SECItem *pubkder) |
-{ |
- PRArenaPool *arena; |
- SECKEYPublicKey *pubk; |
- SECStatus rv; |
- SECItem newPubkder; |
- |
- arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- PORT_SetError (SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey)); |
- if (pubk != NULL) { |
- pubk->arena = arena; |
- pubk->pkcs11Slot = NULL; |
- pubk->pkcs11ID = 0; |
- prepare_rsa_pub_key_for_asn1(pubk); |
- /* copy the DER into the arena, since Quick DER returns data that points |
- into the DER input, which may get freed by the caller */ |
- rv = SECITEM_CopyItem(arena, &newPubkder, pubkder); |
- if ( rv == SECSuccess ) { |
- rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, |
- &newPubkder); |
- } |
- if (rv == SECSuccess) |
- return pubk; |
- SECKEY_DestroyPublicKey (pubk); |
- } else { |
- PORT_SetError (SEC_ERROR_NO_MEMORY); |
- } |
- |
- PORT_FreeArena (arena, PR_FALSE); |
- return NULL; |
-} |
- |
-/* |
- * Decode a base64 ascii encoded DER encoded public key. |
- */ |
-SECKEYPublicKey * |
-SECKEY_ConvertAndDecodePublicKey(char *pubkstr) |
-{ |
- SECKEYPublicKey *pubk; |
- SECStatus rv; |
- SECItem der; |
- |
- rv = ATOB_ConvertAsciiToItem (&der, pubkstr); |
- if (rv != SECSuccess) |
- return NULL; |
- |
- pubk = SECKEY_DecodeDERPublicKey (&der); |
- |
- PORT_Free (der.data); |
- return pubk; |
-} |
- |
-SECItem * |
-SECKEY_EncodeDERSubjectPublicKeyInfo(SECKEYPublicKey *pubk) |
-{ |
- CERTSubjectPublicKeyInfo *spki=NULL; |
- SECItem *spkiDER=NULL; |
- |
- /* get the subjectpublickeyinfo */ |
- spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); |
- if( spki == NULL ) { |
- goto finish; |
- } |
- |
- /* DER-encode the subjectpublickeyinfo */ |
- spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki, |
- CERT_SubjectPublicKeyInfoTemplate); |
- |
- SECKEY_DestroySubjectPublicKeyInfo(spki); |
- |
-finish: |
- return spkiDER; |
-} |
- |
- |
-CERTSubjectPublicKeyInfo * |
-SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider) |
-{ |
- PRArenaPool *arena; |
- CERTSubjectPublicKeyInfo *spki; |
- SECStatus rv; |
- SECItem newSpkider; |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- spki = (CERTSubjectPublicKeyInfo *) |
- PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo)); |
- if (spki != NULL) { |
- spki->arena = arena; |
- |
- /* copy the DER into the arena, since Quick DER returns data that points |
- into the DER input, which may get freed by the caller */ |
- rv = SECITEM_CopyItem(arena, &newSpkider, spkider); |
- if ( rv == SECSuccess ) { |
- rv = SEC_QuickDERDecodeItem(arena,spki, |
- CERT_SubjectPublicKeyInfoTemplate, &newSpkider); |
- } |
- if (rv == SECSuccess) |
- return spki; |
- } else { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- } |
- |
- PORT_FreeArena(arena, PR_FALSE); |
- return NULL; |
-} |
- |
-/* |
- * Decode a base64 ascii encoded DER encoded subject public key info. |
- */ |
-CERTSubjectPublicKeyInfo * |
-SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr) |
-{ |
- CERTSubjectPublicKeyInfo *spki; |
- SECStatus rv; |
- SECItem der; |
- |
- rv = ATOB_ConvertAsciiToItem(&der, spkistr); |
- if (rv != SECSuccess) |
- return NULL; |
- |
- spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); |
- |
- PORT_Free(der.data); |
- return spki; |
-} |
- |
-/* |
- * Decode a base64 ascii encoded DER encoded public key and challenge |
- * Verify digital signature and make sure challenge matches |
- */ |
-CERTSubjectPublicKeyInfo * |
-SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge, |
- void *wincx) |
-{ |
- CERTSubjectPublicKeyInfo *spki = NULL; |
- CERTPublicKeyAndChallenge pkac; |
- SECStatus rv; |
- SECItem signedItem; |
- PRArenaPool *arena = NULL; |
- CERTSignedData sd; |
- SECItem sig; |
- SECKEYPublicKey *pubKey = NULL; |
- unsigned int len; |
- |
- signedItem.data = NULL; |
- |
- /* convert the base64 encoded data to binary */ |
- rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr); |
- if (rv != SECSuccess) { |
- goto loser; |
- } |
- |
- /* create an arena */ |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- goto loser; |
- } |
- |
- /* decode the outer wrapping of signed data */ |
- PORT_Memset(&sd, 0, sizeof(CERTSignedData)); |
- rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem ); |
- if ( rv ) { |
- goto loser; |
- } |
- |
- /* decode the public key and challenge wrapper */ |
- PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge)); |
- rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, |
- &sd.data); |
- if ( rv ) { |
- goto loser; |
- } |
- |
- /* decode the subject public key info */ |
- spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki); |
- if ( spki == NULL ) { |
- goto loser; |
- } |
- |
- /* get the public key */ |
- pubKey = seckey_ExtractPublicKey(spki); |
- if ( pubKey == NULL ) { |
- goto loser; |
- } |
- |
- /* check the signature */ |
- sig = sd.signature; |
- DER_ConvertBitString(&sig); |
- rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig, |
- &(sd.signatureAlgorithm), NULL, wincx); |
- if ( rv != SECSuccess ) { |
- goto loser; |
- } |
- |
- /* check the challenge */ |
- if ( challenge ) { |
- len = PORT_Strlen(challenge); |
- /* length is right */ |
- if ( len != pkac.challenge.len ) { |
- goto loser; |
- } |
- /* actual data is right */ |
- if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) { |
- goto loser; |
- } |
- } |
- goto done; |
- |
-loser: |
- /* make sure that we return null if we got an error */ |
- if ( spki ) { |
- SECKEY_DestroySubjectPublicKeyInfo(spki); |
- } |
- spki = NULL; |
- |
-done: |
- if ( signedItem.data ) { |
- PORT_Free(signedItem.data); |
- } |
- if ( arena ) { |
- PORT_FreeArena(arena, PR_FALSE); |
- } |
- if ( pubKey ) { |
- SECKEY_DestroyPublicKey(pubKey); |
- } |
- |
- return spki; |
-} |
- |
-void |
-SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk, |
- PRBool freeit) |
-{ |
- PRArenaPool *poolp; |
- |
- if(pvk != NULL) { |
- if(pvk->arena) { |
- poolp = pvk->arena; |
- /* zero structure since PORT_FreeArena does not support |
- * this yet. |
- */ |
- PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len); |
- PORT_Memset((char *)pvk, 0, sizeof(*pvk)); |
- if(freeit == PR_TRUE) { |
- PORT_FreeArena(poolp, PR_TRUE); |
- } else { |
- pvk->arena = poolp; |
- } |
- } else { |
- SECITEM_ZfreeItem(&pvk->version, PR_FALSE); |
- SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE); |
- SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE); |
- PORT_Memset((char *)pvk, 0, sizeof(*pvk)); |
- if(freeit == PR_TRUE) { |
- PORT_Free(pvk); |
- } |
- } |
- } |
-} |
- |
-void |
-SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki, |
- PRBool freeit) |
-{ |
- PRArenaPool *poolp; |
- |
- if(epki != NULL) { |
- if(epki->arena) { |
- poolp = epki->arena; |
- /* zero structure since PORT_FreeArena does not support |
- * this yet. |
- */ |
- PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len); |
- PORT_Memset((char *)epki, 0, sizeof(*epki)); |
- if(freeit == PR_TRUE) { |
- PORT_FreeArena(poolp, PR_TRUE); |
- } else { |
- epki->arena = poolp; |
- } |
- } else { |
- SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE); |
- SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE); |
- PORT_Memset((char *)epki, 0, sizeof(*epki)); |
- if(freeit == PR_TRUE) { |
- PORT_Free(epki); |
- } |
- } |
- } |
-} |
- |
-SECStatus |
-SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp, |
- SECKEYPrivateKeyInfo *to, |
- SECKEYPrivateKeyInfo *from) |
-{ |
- SECStatus rv = SECFailure; |
- |
- if((to == NULL) || (from == NULL)) { |
- return SECFailure; |
- } |
- |
- rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm); |
- if(rv != SECSuccess) { |
- return SECFailure; |
- } |
- rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey); |
- if(rv != SECSuccess) { |
- return SECFailure; |
- } |
- rv = SECITEM_CopyItem(poolp, &to->version, &from->version); |
- |
- return rv; |
-} |
- |
-SECStatus |
-SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp, |
- SECKEYEncryptedPrivateKeyInfo *to, |
- SECKEYEncryptedPrivateKeyInfo *from) |
-{ |
- SECStatus rv = SECFailure; |
- |
- if((to == NULL) || (from == NULL)) { |
- return SECFailure; |
- } |
- |
- rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm); |
- if(rv != SECSuccess) { |
- return SECFailure; |
- } |
- rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData); |
- |
- return rv; |
-} |
- |
-KeyType |
-SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey) |
-{ |
- return privKey->keyType; |
-} |
- |
-KeyType |
-SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey) |
-{ |
- return pubKey->keyType; |
-} |
- |
-SECKEYPublicKey* |
-SECKEY_ImportDERPublicKey(SECItem *derKey, CK_KEY_TYPE type) |
-{ |
- SECKEYPublicKey *pubk = NULL; |
- SECStatus rv = SECFailure; |
- SECItem newDerKey; |
- PRArenaPool *arena = NULL; |
- |
- if (!derKey) { |
- return NULL; |
- } |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- goto finish; |
- } |
- |
- pubk = PORT_ArenaZNew(arena, SECKEYPublicKey); |
- if (pubk == NULL) { |
- goto finish; |
- } |
- pubk->arena = arena; |
- |
- rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey); |
- if (SECSuccess != rv) { |
- goto finish; |
- } |
- |
- pubk->pkcs11Slot = NULL; |
- pubk->pkcs11ID = CK_INVALID_HANDLE; |
- |
- switch( type ) { |
- case CKK_RSA: |
- prepare_rsa_pub_key_for_asn1(pubk); |
- rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey); |
- pubk->keyType = rsaKey; |
- break; |
- case CKK_DSA: |
- prepare_dsa_pub_key_for_asn1(pubk); |
- rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey); |
- pubk->keyType = dsaKey; |
- break; |
- case CKK_DH: |
- prepare_dh_pub_key_for_asn1(pubk); |
- rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey); |
- pubk->keyType = dhKey; |
- break; |
- default: |
- rv = SECFailure; |
- break; |
- } |
- |
-finish: |
- if (rv != SECSuccess) { |
- if (arena != NULL) { |
- PORT_FreeArena(arena, PR_TRUE); |
- } |
- pubk = NULL; |
- } |
- return pubk; |
-} |
- |
-SECKEYPrivateKeyList* |
-SECKEY_NewPrivateKeyList(void) |
-{ |
- PRArenaPool *arena = NULL; |
- SECKEYPrivateKeyList *ret = NULL; |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if ( arena == NULL ) { |
- goto loser; |
- } |
- |
- ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena, |
- sizeof(SECKEYPrivateKeyList)); |
- if ( ret == NULL ) { |
- goto loser; |
- } |
- |
- ret->arena = arena; |
- |
- PR_INIT_CLIST(&ret->list); |
- |
- return(ret); |
- |
-loser: |
- if ( arena != NULL ) { |
- PORT_FreeArena(arena, PR_FALSE); |
- } |
- |
- return(NULL); |
-} |
- |
-void |
-SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys) |
-{ |
- while( !PR_CLIST_IS_EMPTY(&keys->list) ) { |
- SECKEY_RemovePrivateKeyListNode( |
- (SECKEYPrivateKeyListNode*)(PR_LIST_HEAD(&keys->list)) ); |
- } |
- |
- PORT_FreeArena(keys->arena, PR_FALSE); |
- |
- return; |
-} |
- |
- |
-void |
-SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node) |
-{ |
- PR_ASSERT(node->key); |
- SECKEY_DestroyPrivateKey(node->key); |
- node->key = NULL; |
- PR_REMOVE_LINK(&node->links); |
- return; |
- |
-} |
- |
-SECStatus |
-SECKEY_AddPrivateKeyToListTail( SECKEYPrivateKeyList *list, |
- SECKEYPrivateKey *key) |
-{ |
- SECKEYPrivateKeyListNode *node; |
- |
- node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena, |
- sizeof(SECKEYPrivateKeyListNode)); |
- if ( node == NULL ) { |
- goto loser; |
- } |
- |
- PR_INSERT_BEFORE(&node->links, &list->list); |
- node->key = key; |
- return(SECSuccess); |
- |
-loser: |
- return(SECFailure); |
-} |
- |
- |
-SECKEYPublicKeyList* |
-SECKEY_NewPublicKeyList(void) |
-{ |
- PRArenaPool *arena = NULL; |
- SECKEYPublicKeyList *ret = NULL; |
- |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if ( arena == NULL ) { |
- goto loser; |
- } |
- |
- ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena, |
- sizeof(SECKEYPublicKeyList)); |
- if ( ret == NULL ) { |
- goto loser; |
- } |
- |
- ret->arena = arena; |
- |
- PR_INIT_CLIST(&ret->list); |
- |
- return(ret); |
- |
-loser: |
- if ( arena != NULL ) { |
- PORT_FreeArena(arena, PR_FALSE); |
- } |
- |
- return(NULL); |
-} |
- |
-void |
-SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys) |
-{ |
- while( !PR_CLIST_IS_EMPTY(&keys->list) ) { |
- SECKEY_RemovePublicKeyListNode( |
- (SECKEYPublicKeyListNode*)(PR_LIST_HEAD(&keys->list)) ); |
- } |
- |
- PORT_FreeArena(keys->arena, PR_FALSE); |
- |
- return; |
-} |
- |
- |
-void |
-SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node) |
-{ |
- PR_ASSERT(node->key); |
- SECKEY_DestroyPublicKey(node->key); |
- node->key = NULL; |
- PR_REMOVE_LINK(&node->links); |
- return; |
- |
-} |
- |
-SECStatus |
-SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list, |
- SECKEYPublicKey *key) |
-{ |
- SECKEYPublicKeyListNode *node; |
- |
- node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena, |
- sizeof(SECKEYPublicKeyListNode)); |
- if ( node == NULL ) { |
- goto loser; |
- } |
- |
- PR_INSERT_BEFORE(&node->links, &list->list); |
- node->key = key; |
- return(SECSuccess); |
- |
-loser: |
- return(SECFailure); |
-} |
- |
-#define SECKEY_CacheAttribute(key, attribute) \ |
- if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \ |
- key->staticflags |= SECKEY_##attribute; \ |
- } else { \ |
- key->staticflags &= (~SECKEY_##attribute); \ |
- } |
- |
-SECStatus |
-SECKEY_CacheStaticFlags(SECKEYPrivateKey* key) |
-{ |
- SECStatus rv = SECFailure; |
- if (key && key->pkcs11Slot && key->pkcs11ID) { |
- key->staticflags |= SECKEY_Attributes_Cached; |
- SECKEY_CacheAttribute(key, CKA_PRIVATE); |
- SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE); |
- rv = SECSuccess; |
- } |
- return rv; |
-} |