| 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; | 
| -} | 
|  |