security/nss/lib/cryptohi/seckey.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 #include "cryptohi.h"
     5 #include "keyhi.h"
     6 #include "secoid.h"
     7 #include "secitem.h"
     8 #include "secder.h"
     9 #include "base64.h"
    10 #include "secasn1.h"
    11 #include "cert.h"
    12 #include "pk11func.h"
    13 #include "secerr.h"
    14 #include "secdig.h"
    15 #include "prtime.h"
    16 #include "keyi.h"
    18 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
    19 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
    21 const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
    22     { SEC_ASN1_SEQUENCE,
    23 	  0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
    24     { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
    25 	  offsetof(CERTSubjectPublicKeyInfo,algorithm),
    26 	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    27     { SEC_ASN1_BIT_STRING,
    28 	  offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
    29     { 0, }
    30 };
    32 const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
    33 {
    34     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
    35     { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },
    36     { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },
    37     { 0 }
    38 };
    40 const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
    41     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
    42     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },
    43     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },
    44     { 0, }
    45 };
    47 static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = {
    48     { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0,
    49       SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }
    50 };
    52 /* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */
    53 const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] =
    54 {
    55     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) },
    56     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
    57           SEC_ASN1_CONTEXT_SPECIFIC | 0,
    58           offsetof(SECKEYRSAPSSParams, hashAlg),
    59           seckey_PointerToAlgorithmIDTemplate },
    60     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
    61           SEC_ASN1_CONTEXT_SPECIFIC | 1,
    62           offsetof(SECKEYRSAPSSParams, maskAlg),
    63           seckey_PointerToAlgorithmIDTemplate },
    64     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
    65           SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2,
    66           offsetof(SECKEYRSAPSSParams, saltLength),
    67           SEC_ASN1_SUB(SEC_IntegerTemplate) },
    68     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
    69           SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3,
    70           offsetof(SECKEYRSAPSSParams, trailerField),
    71           SEC_ASN1_SUB(SEC_IntegerTemplate) },
    72     { 0 }
    73 };
    75 const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
    76     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },
    77     { 0, }
    78 };
    80 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
    81     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
    82     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
    83     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
    84     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
    85     { 0, }
    86 };
    88 const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
    89     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
    90     { 0, }
    91 };
    93 const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
    94     { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(SECKEYPublicKey) },
    95     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
    96     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
    97     /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
    98     { SEC_ASN1_SKIP_REST },
    99     { 0, }
   100 };
   102 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
   103 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
   104 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate)
   105 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
   107 /*
   108  * See bugzilla bug 125359
   109  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
   110  * all of the templates above that en/decode into integers must be converted
   111  * from ASN.1's signed integer type.  This is done by marking either the
   112  * source or destination (encoding or decoding, respectively) type as
   113  * siUnsignedInteger.
   114  */
   115 static void
   116 prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
   117 {
   118     pubk->u.rsa.modulus.type = siUnsignedInteger;
   119     pubk->u.rsa.publicExponent.type = siUnsignedInteger;
   120 }
   122 static void
   123 prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
   124 {
   125     pubk->u.dsa.publicValue.type = siUnsignedInteger;
   126 }
   128 static void
   129 prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
   130 {
   131     params->prime.type = siUnsignedInteger;
   132     params->subPrime.type = siUnsignedInteger;
   133     params->base.type = siUnsignedInteger;
   134 }
   136 static void
   137 prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
   138 {
   139     pubk->u.dh.prime.type = siUnsignedInteger;
   140     pubk->u.dh.base.type = siUnsignedInteger;
   141     pubk->u.dh.publicValue.type = siUnsignedInteger;
   142 }
   144 /* Create an RSA key pair is any slot able to do so.
   145 ** The created keys are "session" (temporary), not "token" (permanent), 
   146 ** and they are "sensitive", which makes them costly to move to another token.
   147 */
   148 SECKEYPrivateKey *
   149 SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx)
   150 {
   151     SECKEYPrivateKey *privk;
   152     PK11RSAGenParams param;
   153     PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);
   154     if (!slot) {
   155 	return NULL;
   156     }
   158     param.keySizeInBits = keySizeInBits;
   159     param.pe = 65537L;
   161     privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,
   162 					PR_FALSE, PR_TRUE, cx);
   163     PK11_FreeSlot(slot);
   164     return(privk);
   165 }
   167 /* Create a DH key pair in any slot able to do so, 
   168 ** This is a "session" (temporary), not "token" (permanent) key. 
   169 ** Because of the high probability that this key will need to be moved to
   170 ** another token, and the high cost of moving "sensitive" keys, we attempt
   171 ** to create this key pair without the "sensitive" attribute, but revert to 
   172 ** creating a "sensitive" key if necessary.
   173 */
   174 SECKEYPrivateKey *
   175 SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
   176 {
   177     SECKEYPrivateKey *privk;
   178     PK11SlotInfo *slot;
   180     if (!param || !param->base.data || !param->prime.data ||
   181         param->prime.len < 512/8 || param->base.len == 0 || 
   182         param->base.len > param->prime.len + 1 || 
   183 	(param->base.len == 1 && param->base.data[0] == 0)) {
   184 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   185 	return NULL;
   186     }
   188     slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
   189     if (!slot) {
   190 	return NULL;
   191     }
   193     privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 
   194                                  pubk, PR_FALSE, PR_FALSE, cx);
   195     if (!privk) 
   196 	privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 
   197 	                             pubk, PR_FALSE, PR_TRUE, cx);
   199     PK11_FreeSlot(slot);
   200     return(privk);
   201 }
   203 /* Create an EC key pair in any slot able to do so, 
   204 ** This is a "session" (temporary), not "token" (permanent) key. 
   205 ** Because of the high probability that this key will need to be moved to
   206 ** another token, and the high cost of moving "sensitive" keys, we attempt
   207 ** to create this key pair without the "sensitive" attribute, but revert to 
   208 ** creating a "sensitive" key if necessary.
   209 */
   210 SECKEYPrivateKey *
   211 SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
   212 {
   213     SECKEYPrivateKey *privk;
   214     PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx);
   215     if (!slot) {
   216 	return NULL;
   217     }
   219     privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, 
   220                         param, pubk,
   221                         PK11_ATTR_SESSION | PK11_ATTR_INSENSITIVE | 
   222                         PK11_ATTR_PUBLIC,
   223                         CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx);
   224     if (!privk) 
   225         privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, 
   226                         param, pubk,
   227                         PK11_ATTR_SESSION | PK11_ATTR_SENSITIVE | 
   228                         PK11_ATTR_PRIVATE,
   229                         CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx);
   231     PK11_FreeSlot(slot);
   232     return(privk);
   233 }
   235 void
   236 SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
   237 {
   238     if (privk) {
   239 	if (privk->pkcs11Slot) {
   240 	    if (privk->pkcs11IsTemp) {
   241 	    	PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);
   242 	    }
   243 	    PK11_FreeSlot(privk->pkcs11Slot);
   245 	}
   246     	if (privk->arena) {
   247 	    PORT_FreeArena(privk->arena, PR_TRUE);
   248 	}
   249     }
   250 }
   252 void
   253 SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
   254 {
   255     if (pubk) {
   256 	if (pubk->pkcs11Slot) {
   257 	    if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
   258 		PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);
   259 	    }
   260 	    PK11_FreeSlot(pubk->pkcs11Slot);
   261 	}
   262     	if (pubk->arena) {
   263 	    PORT_FreeArena(pubk->arena, PR_FALSE);
   264 	}
   265     }
   266 }
   268 SECStatus
   269 SECKEY_CopySubjectPublicKeyInfo(PLArenaPool *arena,
   270 			     CERTSubjectPublicKeyInfo *to,
   271 			     CERTSubjectPublicKeyInfo *from)
   272 {
   273     SECStatus rv;
   274     SECItem spk;
   276     rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
   277     if (rv == SECSuccess) {
   278 	/*
   279 	 * subjectPublicKey is a bit string, whose length is in bits.
   280 	 * Convert the length from bits to bytes for SECITEM_CopyItem.
   281 	 */
   282 	spk = from->subjectPublicKey;
   283 	DER_ConvertBitString(&spk);
   284 	rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
   285 	/* Set the length back to bits. */
   286 	if (rv == SECSuccess) {
   287 	    to->subjectPublicKey.len = from->subjectPublicKey.len;
   288 	}
   289     }
   291     return rv;
   292 }
   294 /* Procedure to update the pqg parameters for a cert's public key.
   295  * pqg parameters only need to be updated for DSA certificates.
   296  * The procedure uses calls to itself recursively to update a certificate
   297  * issuer's pqg parameters.  Some important rules are:
   298  *    - Do nothing if the cert already has PQG parameters.
   299  *    - If the cert does not have PQG parameters, obtain them from the issuer.
   300  *    - A valid cert chain cannot have a DSA cert without
   301  *      pqg parameters that has a parent that is not a DSA cert.  */
   303 static SECStatus
   304 seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count)
   305 {
   306     SECStatus rv;
   307     SECOidData *oid=NULL;
   308     int tag;
   309     CERTSubjectPublicKeyInfo * subjectSpki=NULL;
   310     CERTSubjectPublicKeyInfo * issuerSpki=NULL;
   311     CERTCertificate *issuerCert = NULL;
   313     rv = SECSuccess;
   315     /* increment cert chain length counter*/
   316     count++;
   318     /* check if cert chain length exceeds the maximum length*/
   319     if (count > CERT_MAX_CERT_CHAIN) {
   320 	return SECFailure;
   321     }
   323     oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);            
   324     if (oid != NULL) {  
   325         tag = oid->offset;
   327         /* Check if cert has a DSA or EC public key. If not, return
   328          * success since no PQG params need to be updated.
   329 	 *
   330 	 * Question: do we really need to do this for EC keys. They don't have
   331 	 * PQG parameters, but they do have parameters. The question is does
   332 	 * the child cert inherit thost parameters for EC from the parent, or
   333 	 * do we always include those parameters in each cert.
   334 	 */
   336 	if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
   337              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
   338              (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
   339              (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
   340              (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
   341              (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
   342              (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
   344             return SECSuccess;
   345         }
   346     } else {
   347         return SECFailure;  /* return failure if oid is NULL */  
   348     }
   350     /* if cert has PQG parameters, return success */
   352     subjectSpki=&subjectCert->subjectPublicKeyInfo;
   354     if (subjectSpki->algorithm.parameters.len != 0) {
   355         return SECSuccess;
   356     }
   358     /* check if the cert is self-signed */
   359     if (subjectCert->isRoot) {
   360       /* fail since cert is self-signed and has no pqg params. */
   361 	return SECFailure;     
   362     }
   364     /* get issuer cert */
   365     issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
   366     if ( ! issuerCert ) {
   367 	return SECFailure;
   368     }
   370     /* if parent is not DSA, return failure since
   371        we don't allow this case. */
   373     oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
   374     if (oid != NULL) {  
   375         tag = oid->offset;
   377         /* Check if issuer cert has a DSA public key. If not,
   378          * return failure.   */
   380 	if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
   381              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
   382              (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
   383              (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
   384              (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
   385              (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
   386              (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {            
   387             rv = SECFailure;
   388             goto loser;
   389         }
   390     } else {
   391         rv = SECFailure;  /* return failure if oid is NULL */  
   392         goto loser;
   393     }
   396     /* at this point the subject cert has no pqg parameters and the
   397      * issuer cert has a DSA public key.  Update the issuer's
   398      * pqg parameters with a recursive call to this same function. */
   400     rv = seckey_UpdateCertPQGChain(issuerCert, count);
   401     if (rv != SECSuccess) {
   402         rv = SECFailure;
   403         goto loser;
   404     }
   406     /* ensure issuer has pqg parameters */
   408     issuerSpki=&issuerCert->subjectPublicKeyInfo;
   409     if (issuerSpki->algorithm.parameters.len == 0) {
   410         rv = SECFailure; 
   411     }
   413     /* if update was successful and pqg params present, then copy the
   414      * parameters to the subject cert's key. */
   416     if (rv == SECSuccess) {
   417         rv = SECITEM_CopyItem(subjectCert->arena,
   418                               &subjectSpki->algorithm.parameters, 
   419 	   		      &issuerSpki->algorithm.parameters);
   420     }
   422 loser:
   423     if (issuerCert) {
   424         CERT_DestroyCertificate(issuerCert);
   425     }
   426     return rv;
   428 }
   431 SECStatus
   432 SECKEY_UpdateCertPQG(CERTCertificate * subjectCert)
   433 {
   434     if (!subjectCert) {
   435         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   436 	return SECFailure;
   437     }
   438     return seckey_UpdateCertPQGChain(subjectCert,0);
   439 }
   442 /* Decode the DSA PQG parameters.  The params could be stored in two
   443  * possible formats, the old fortezza-only wrapped format or
   444  * the normal standard format.  Store the decoded parameters in
   445  * a V3 certificate data structure.  */ 
   447 static SECStatus
   448 seckey_DSADecodePQG(PLArenaPool *arena, SECKEYPublicKey *pubk,
   449                     const SECItem *params) {
   450     SECStatus rv;
   451     SECItem newparams;
   453     if (params == NULL) return SECFailure; 
   455     if (params->data == NULL) return SECFailure;
   457     PORT_Assert(arena);
   459     /* make a copy of the data into the arena so QuickDER output is valid */
   460     rv = SECITEM_CopyItem(arena, &newparams, params);
   462     /* Check if params use the standard format.
   463      * The value 0xa1 will appear in the first byte of the parameter data
   464      * if the PQG parameters are not using the standard format.  This
   465      * code should be changed to use a better method to detect non-standard
   466      * parameters.    */
   468     if ((newparams.data[0] != 0xa1) &&
   469         (newparams.data[0] != 0xa0)) {
   471         if (SECSuccess == rv) {
   472              /* PQG params are in the standard format */
   473              prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
   474              rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
   475                                  SECKEY_PQGParamsTemplate,
   476                                  &newparams);
   477         }
   478     } else {
   480         if (SECSuccess == rv) {
   481             /* else the old fortezza-only wrapped format is used. */
   482             PORT_SetError(SEC_ERROR_BAD_DER);
   483             rv = SECFailure;
   484         }
   485     }
   486     return rv;
   487 }
   490 /* Function used to make an oid tag to a key type */
   491 KeyType 
   492 seckey_GetKeyType (SECOidTag tag) {
   493     KeyType keyType;
   495     switch (tag) {
   496       case SEC_OID_X500_RSA_ENCRYPTION:
   497       case SEC_OID_PKCS1_RSA_ENCRYPTION:
   498 	keyType = rsaKey;
   499 	break;
   500       case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
   501 	keyType = rsaPssKey;
   502 	break;
   503       case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
   504 	keyType = rsaOaepKey;
   505 	break;
   506       case SEC_OID_ANSIX9_DSA_SIGNATURE:
   507 	keyType = dsaKey;
   508 	break;
   509       case SEC_OID_MISSI_KEA_DSS_OLD:
   510       case SEC_OID_MISSI_KEA_DSS:
   511       case SEC_OID_MISSI_DSS_OLD:
   512       case SEC_OID_MISSI_DSS:  
   513 	keyType = fortezzaKey;
   514 	break;
   515       case SEC_OID_MISSI_KEA:
   516       case SEC_OID_MISSI_ALT_KEA:
   517 	keyType = keaKey;
   518 	break;
   519       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
   520 	keyType = dhKey;
   521 	break;
   522       case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
   523 	keyType = ecKey;
   524 	break;
   525       /* accommodate applications that hand us a signature type when they 
   526 	* should be handing us a cipher type */
   527       case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
   528       case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
   529       case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
   530       case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
   531       case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
   532       case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
   533 	keyType = rsaKey;
   534 	break;
   535       default:
   536 	keyType = nullKey;
   537     }
   538     return keyType;
   539 }
   541 /* Function used to determine what kind of cert we are dealing with. */
   542 KeyType 
   543 CERT_GetCertKeyType (const CERTSubjectPublicKeyInfo *spki) 
   544 {
   545     return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
   546 }
   548 static SECKEYPublicKey *
   549 seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
   550 {
   551     SECKEYPublicKey *pubk;
   552     SECItem os, newOs, newParms;
   553     SECStatus rv;
   554     PLArenaPool *arena;
   555     SECOidTag tag;
   557     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
   558     if (arena == NULL)
   559 	return NULL;
   561     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
   562     if (pubk == NULL) {
   563 	PORT_FreeArena (arena, PR_FALSE);
   564 	return NULL;
   565     }
   567     pubk->arena = arena;
   568     pubk->pkcs11Slot = 0;
   569     pubk->pkcs11ID = CK_INVALID_HANDLE;
   572     /* Convert bit string length from bits to bytes */
   573     os = spki->subjectPublicKey;
   574     DER_ConvertBitString (&os);
   576     tag = SECOID_GetAlgorithmTag(&spki->algorithm);
   578     /* copy the DER into the arena, since Quick DER returns data that points
   579        into the DER input, which may get freed by the caller */
   580     rv = SECITEM_CopyItem(arena, &newOs, &os);
   581     if ( rv == SECSuccess )
   582     switch ( tag ) {
   583       case SEC_OID_X500_RSA_ENCRYPTION:
   584       case SEC_OID_PKCS1_RSA_ENCRYPTION:
   585 	pubk->keyType = rsaKey;
   586 	prepare_rsa_pub_key_for_asn1(pubk);        
   587         rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
   588 	if (rv == SECSuccess)
   589 	    return pubk;
   590 	break;
   591       case SEC_OID_ANSIX9_DSA_SIGNATURE:
   592       case SEC_OID_SDN702_DSA_SIGNATURE:
   593 	pubk->keyType = dsaKey;
   594 	prepare_dsa_pub_key_for_asn1(pubk);
   595 	rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
   596 	if (rv != SECSuccess) break;
   598         rv = seckey_DSADecodePQG(arena, pubk,
   599                                  &spki->algorithm.parameters); 
   601 	if (rv == SECSuccess) return pubk;
   602 	break;
   603       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
   604 	pubk->keyType = dhKey;
   605 	prepare_dh_pub_key_for_asn1(pubk);
   606 	rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
   607 	if (rv != SECSuccess) break;
   609         /* copy the DER into the arena, since Quick DER returns data that points
   610            into the DER input, which may get freed by the caller */
   611         rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
   612         if ( rv != SECSuccess )
   613             break;
   615         rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
   616                                  &newParms); 
   618 	if (rv == SECSuccess) return pubk;
   619 	break;
   620       case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
   621 	pubk->keyType = ecKey;
   622 	pubk->u.ec.size = 0;
   624 	/* Since PKCS#11 directly takes the DER encoding of EC params
   625 	 * and public value, we don't need any decoding here.
   626 	 */
   627         rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams, 
   628 	    &spki->algorithm.parameters);
   629         if ( rv != SECSuccess )
   630             break;
   631         rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
   632 	if (rv == SECSuccess) return pubk;
   633 	break;
   635       default:
   636 	PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
   637 	rv = SECFailure;
   638 	break;
   639     }
   641     SECKEY_DestroyPublicKey (pubk);
   642     return NULL;
   643 }
   646 /* required for JSS */
   647 SECKEYPublicKey *
   648 SECKEY_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
   649 {
   650     return seckey_ExtractPublicKey(spki);
   651 }
   653 SECKEYPublicKey *
   654 CERT_ExtractPublicKey(CERTCertificate *cert)
   655 {
   656     SECStatus rv;
   658     if (!cert) {
   659         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   660 	return NULL;
   661     }
   662     rv = SECKEY_UpdateCertPQG(cert);
   663     if (rv != SECSuccess) return NULL;
   665     return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
   666 }
   668 int
   669 SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
   670 {
   671     SECOidTag tag;
   672     SECItem oid = { siBuffer, NULL, 0};
   674     /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
   675      * followed by the length of the curve oid and the curve oid.
   676      */
   677     oid.len = encodedParams->data[1];
   678     oid.data = encodedParams->data + 2;
   679     if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
   680 	return 0;
   682     switch (tag) {
   683     case SEC_OID_SECG_EC_SECP112R1:
   684     case SEC_OID_SECG_EC_SECP112R2:
   685         return 112;
   687     case SEC_OID_SECG_EC_SECT113R1:
   688     case SEC_OID_SECG_EC_SECT113R2:
   689 	return 113;
   691     case SEC_OID_SECG_EC_SECP128R1:
   692     case SEC_OID_SECG_EC_SECP128R2:
   693 	return 128;
   695     case SEC_OID_SECG_EC_SECT131R1:
   696     case SEC_OID_SECG_EC_SECT131R2:
   697 	return 131;
   699     case SEC_OID_SECG_EC_SECP160K1:
   700     case SEC_OID_SECG_EC_SECP160R1:
   701     case SEC_OID_SECG_EC_SECP160R2:
   702 	return 160;
   704     case SEC_OID_SECG_EC_SECT163K1:
   705     case SEC_OID_SECG_EC_SECT163R1:
   706     case SEC_OID_SECG_EC_SECT163R2:
   707     case SEC_OID_ANSIX962_EC_C2PNB163V1:
   708     case SEC_OID_ANSIX962_EC_C2PNB163V2:
   709     case SEC_OID_ANSIX962_EC_C2PNB163V3:
   710 	return 163;
   712     case SEC_OID_ANSIX962_EC_C2PNB176V1:
   713 	return 176;
   715     case SEC_OID_ANSIX962_EC_C2TNB191V1:
   716     case SEC_OID_ANSIX962_EC_C2TNB191V2:
   717     case SEC_OID_ANSIX962_EC_C2TNB191V3:
   718     case SEC_OID_ANSIX962_EC_C2ONB191V4:
   719     case SEC_OID_ANSIX962_EC_C2ONB191V5:
   720 	return 191;
   722     case SEC_OID_SECG_EC_SECP192K1:
   723     case SEC_OID_ANSIX962_EC_PRIME192V1:
   724     case SEC_OID_ANSIX962_EC_PRIME192V2:
   725     case SEC_OID_ANSIX962_EC_PRIME192V3:
   726 	return 192;
   728     case SEC_OID_SECG_EC_SECT193R1:
   729     case SEC_OID_SECG_EC_SECT193R2:
   730 	return 193;
   732     case SEC_OID_ANSIX962_EC_C2PNB208W1:
   733 	return 208;
   735     case SEC_OID_SECG_EC_SECP224K1:
   736     case SEC_OID_SECG_EC_SECP224R1:
   737 	return 224;
   739     case SEC_OID_SECG_EC_SECT233K1:
   740     case SEC_OID_SECG_EC_SECT233R1:
   741 	return 233;
   743     case SEC_OID_SECG_EC_SECT239K1:
   744     case SEC_OID_ANSIX962_EC_C2TNB239V1:
   745     case SEC_OID_ANSIX962_EC_C2TNB239V2:
   746     case SEC_OID_ANSIX962_EC_C2TNB239V3:
   747     case SEC_OID_ANSIX962_EC_C2ONB239V4:
   748     case SEC_OID_ANSIX962_EC_C2ONB239V5:
   749     case SEC_OID_ANSIX962_EC_PRIME239V1:
   750     case SEC_OID_ANSIX962_EC_PRIME239V2:
   751     case SEC_OID_ANSIX962_EC_PRIME239V3:
   752 	return 239;
   754     case SEC_OID_SECG_EC_SECP256K1:
   755     case SEC_OID_ANSIX962_EC_PRIME256V1:
   756 	return 256;
   758     case SEC_OID_ANSIX962_EC_C2PNB272W1:
   759 	return 272;
   761     case SEC_OID_SECG_EC_SECT283K1:
   762     case SEC_OID_SECG_EC_SECT283R1:
   763 	return 283;
   765     case SEC_OID_ANSIX962_EC_C2PNB304W1:
   766 	return 304;
   768     case SEC_OID_ANSIX962_EC_C2TNB359V1:
   769 	return 359;
   771     case SEC_OID_ANSIX962_EC_C2PNB368W1:
   772 	return 368;
   774     case SEC_OID_SECG_EC_SECP384R1:
   775 	return 384;
   777     case SEC_OID_SECG_EC_SECT409K1:
   778     case SEC_OID_SECG_EC_SECT409R1:
   779 	return 409;
   781     case SEC_OID_ANSIX962_EC_C2TNB431R1:
   782 	return 431;
   784     case SEC_OID_SECG_EC_SECP521R1:
   785 	return 521;
   787     case SEC_OID_SECG_EC_SECT571K1:
   788     case SEC_OID_SECG_EC_SECT571R1:
   789 	return 571;
   791     default:
   792 	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   793 	return 0;
   794     }
   795 }
   797 int
   798 SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
   799 {
   800     SECOidTag tag;
   801     SECItem oid = { siBuffer, NULL, 0};
   803     /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
   804      * followed by the length of the curve oid and the curve oid.
   805      */
   806     oid.len = encodedParams->data[1];
   807     oid.data = encodedParams->data + 2;
   808     if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
   809 	return 0;
   811     switch (tag) {
   812     case SEC_OID_SECG_EC_SECP112R1:
   813         return 112;
   814     case SEC_OID_SECG_EC_SECP112R2:
   815         return 110;
   817     case SEC_OID_SECG_EC_SECT113R1:
   818     case SEC_OID_SECG_EC_SECT113R2:
   819 	return 113;
   821     case SEC_OID_SECG_EC_SECP128R1:
   822 	return 128;
   823     case SEC_OID_SECG_EC_SECP128R2:
   824 	return 126;
   826     case SEC_OID_SECG_EC_SECT131R1:
   827     case SEC_OID_SECG_EC_SECT131R2:
   828 	return 131;
   830     case SEC_OID_SECG_EC_SECP160K1:
   831     case SEC_OID_SECG_EC_SECP160R1:
   832     case SEC_OID_SECG_EC_SECP160R2:
   833 	return 161;
   835     case SEC_OID_SECG_EC_SECT163K1:
   836 	return 163;
   837     case SEC_OID_SECG_EC_SECT163R1:
   838 	return 162;
   839     case SEC_OID_SECG_EC_SECT163R2:
   840     case SEC_OID_ANSIX962_EC_C2PNB163V1:
   841 	return 163;
   842     case SEC_OID_ANSIX962_EC_C2PNB163V2:
   843     case SEC_OID_ANSIX962_EC_C2PNB163V3:
   844 	return 162;
   846     case SEC_OID_ANSIX962_EC_C2PNB176V1:
   847 	return 161;
   849     case SEC_OID_ANSIX962_EC_C2TNB191V1:
   850 	return 191;
   851     case SEC_OID_ANSIX962_EC_C2TNB191V2:
   852 	return 190;
   853     case SEC_OID_ANSIX962_EC_C2TNB191V3:
   854 	return 189;
   855     case SEC_OID_ANSIX962_EC_C2ONB191V4:
   856 	return 191;
   857     case SEC_OID_ANSIX962_EC_C2ONB191V5:
   858 	return 188;
   860     case SEC_OID_SECG_EC_SECP192K1:
   861     case SEC_OID_ANSIX962_EC_PRIME192V1:
   862     case SEC_OID_ANSIX962_EC_PRIME192V2:
   863     case SEC_OID_ANSIX962_EC_PRIME192V3:
   864 	return 192;
   866     case SEC_OID_SECG_EC_SECT193R1:
   867     case SEC_OID_SECG_EC_SECT193R2:
   868 	return 193;
   870     case SEC_OID_ANSIX962_EC_C2PNB208W1:
   871 	return 193;
   873     case SEC_OID_SECG_EC_SECP224K1:
   874 	return 225;
   875     case SEC_OID_SECG_EC_SECP224R1:
   876 	return 224;
   878     case SEC_OID_SECG_EC_SECT233K1:
   879 	return 232;
   880     case SEC_OID_SECG_EC_SECT233R1:
   881 	return 233;
   883     case SEC_OID_SECG_EC_SECT239K1:
   884     case SEC_OID_ANSIX962_EC_C2TNB239V1:
   885 	return 238;
   886     case SEC_OID_ANSIX962_EC_C2TNB239V2:
   887 	return 237;
   888     case SEC_OID_ANSIX962_EC_C2TNB239V3:
   889 	return 236;
   890     case SEC_OID_ANSIX962_EC_C2ONB239V4:
   891 	return 238;
   892     case SEC_OID_ANSIX962_EC_C2ONB239V5:
   893 	return 237;
   894     case SEC_OID_ANSIX962_EC_PRIME239V1:
   895     case SEC_OID_ANSIX962_EC_PRIME239V2:
   896     case SEC_OID_ANSIX962_EC_PRIME239V3:
   897 	return 239;
   899     case SEC_OID_SECG_EC_SECP256K1:
   900     case SEC_OID_ANSIX962_EC_PRIME256V1:
   901 	return 256;
   903     case SEC_OID_ANSIX962_EC_C2PNB272W1:
   904 	return 257;
   906     case SEC_OID_SECG_EC_SECT283K1:
   907 	return 281;
   908     case SEC_OID_SECG_EC_SECT283R1:
   909 	return 282;
   911     case SEC_OID_ANSIX962_EC_C2PNB304W1:
   912 	return 289;
   914     case SEC_OID_ANSIX962_EC_C2TNB359V1:
   915 	return 353;
   917     case SEC_OID_ANSIX962_EC_C2PNB368W1:
   918 	return 353;
   920     case SEC_OID_SECG_EC_SECP384R1:
   921 	return 384;
   923     case SEC_OID_SECG_EC_SECT409K1:
   924 	return 407;
   925     case SEC_OID_SECG_EC_SECT409R1:
   926 	return 409;
   928     case SEC_OID_ANSIX962_EC_C2TNB431R1:
   929 	return 418;
   931     case SEC_OID_SECG_EC_SECP521R1:
   932 	return 521;
   934     case SEC_OID_SECG_EC_SECT571K1:
   935     case SEC_OID_SECG_EC_SECT571R1:
   936 	return 570;
   938     default:
   939 	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   940 	return 0;
   941     }
   942 }
   944 /* returns key strength in bytes (not bits) */
   945 unsigned
   946 SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
   947 {
   948     unsigned char b0;
   949     unsigned size;
   951     /* interpret modulus length as key strength */
   952     if (!pubk)
   953     	goto loser;
   954     switch (pubk->keyType) {
   955     case rsaKey:
   956 	if (!pubk->u.rsa.modulus.data) break;
   957     	b0 = pubk->u.rsa.modulus.data[0];
   958     	return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
   959     case dsaKey:
   960 	if (!pubk->u.dsa.publicValue.data) break;
   961     	b0 = pubk->u.dsa.publicValue.data[0];
   962     	return b0 ? pubk->u.dsa.publicValue.len :
   963 	    pubk->u.dsa.publicValue.len - 1;
   964     case dhKey:
   965 	if (!pubk->u.dh.publicValue.data) break;
   966     	b0 = pubk->u.dh.publicValue.data[0];
   967     	return b0 ? pubk->u.dh.publicValue.len :
   968 	    pubk->u.dh.publicValue.len - 1;
   969     case ecKey:
   970 	/* Get the key size in bits and adjust */
   971 	size =	SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
   972 	return (size + 7)/8;
   973     default:
   974 	break;
   975     }
   976 loser:
   977     PORT_SetError(SEC_ERROR_INVALID_KEY);
   978     return 0;
   979 }
   981 /* returns key strength in bits */
   982 unsigned
   983 SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
   984 {
   985     unsigned size;
   986     switch (pubk->keyType) {
   987     case rsaKey:
   988     case dsaKey:
   989     case dhKey:
   990 	return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
   991     case ecKey:
   992 	size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
   993 	return size;
   994     default:
   995 	break;
   996     }
   997     PORT_SetError(SEC_ERROR_INVALID_KEY);
   998     return 0;
   999 }
  1001 /* returns signature length in bytes (not bits) */
  1002 unsigned
  1003 SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
  1005     unsigned char b0;
  1006     unsigned size;
  1008     switch (pubk->keyType) {
  1009     case rsaKey:
  1010     	b0 = pubk->u.rsa.modulus.data[0];
  1011     	return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
  1012     case dsaKey:
  1013 	return pubk->u.dsa.params.subPrime.len * 2;
  1014     case ecKey:
  1015 	/* Get the base point order length in bits and adjust */
  1016 	size =	SECKEY_ECParamsToBasePointOrderLen(
  1017 		&pubk->u.ec.DEREncodedParams);
  1018 	return ((size + 7)/8) * 2;
  1019     default:
  1020 	break;
  1022     PORT_SetError(SEC_ERROR_INVALID_KEY);
  1023     return 0;
  1026 SECKEYPrivateKey *
  1027 SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
  1029     SECKEYPrivateKey *copyk;
  1030     PLArenaPool *arena;
  1032     if (!privk || !privk->pkcs11Slot) {
  1033 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1034 	return NULL;
  1037     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1038     if (arena == NULL) {
  1039 	return NULL;
  1042     copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey));
  1043     if (copyk) {
  1044 	copyk->arena = arena;
  1045 	copyk->keyType = privk->keyType;
  1047 	/* copy the PKCS #11 parameters */
  1048 	copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
  1049 	/* if the key we're referencing was a temparary key we have just
  1050 	 * created, that we want to go away when we're through, we need
  1051 	 * to make a copy of it */
  1052 	if (privk->pkcs11IsTemp) {
  1053 	    copyk->pkcs11ID = 
  1054 			PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID);
  1055 	    if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail;
  1056 	} else {
  1057 	    copyk->pkcs11ID = privk->pkcs11ID;
  1059 	copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
  1060 	copyk->wincx = privk->wincx;
  1061 	copyk->staticflags = privk->staticflags;
  1062 	return copyk;
  1063     } else {
  1064 	PORT_SetError (SEC_ERROR_NO_MEMORY);
  1067 fail:
  1068     PORT_FreeArena (arena, PR_FALSE);
  1069     return NULL;
  1072 SECKEYPublicKey *
  1073 SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
  1075     SECKEYPublicKey *copyk;
  1076     PLArenaPool *arena;
  1077     SECStatus rv = SECSuccess;
  1079     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1080     if (arena == NULL) {
  1081 	PORT_SetError (SEC_ERROR_NO_MEMORY);
  1082 	return NULL;
  1085     copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
  1086     if (!copyk) {
  1087         PORT_FreeArena (arena, PR_FALSE);
  1088         PORT_SetError (SEC_ERROR_NO_MEMORY);
  1089         return NULL;
  1092     copyk->arena = arena;
  1093     copyk->keyType = pubk->keyType;
  1094     if (pubk->pkcs11Slot && 
  1095         PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
  1096         copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
  1097         copyk->pkcs11ID = pubk->pkcs11ID;
  1098     } else {
  1099         copyk->pkcs11Slot = NULL;	/* go get own reference */
  1100         copyk->pkcs11ID = CK_INVALID_HANDLE;
  1102     switch (pubk->keyType) {
  1103       case rsaKey:
  1104           rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
  1105                                 &pubk->u.rsa.modulus);
  1106           if (rv == SECSuccess) {
  1107               rv = SECITEM_CopyItem (arena, &copyk->u.rsa.publicExponent,
  1108                                      &pubk->u.rsa.publicExponent);
  1109               if (rv == SECSuccess)
  1110                   return copyk;
  1112           break;
  1113       case dsaKey:
  1114           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
  1115                                 &pubk->u.dsa.publicValue);
  1116           if (rv != SECSuccess) break;
  1117           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
  1118                                 &pubk->u.dsa.params.prime);
  1119           if (rv != SECSuccess) break;
  1120           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
  1121                                 &pubk->u.dsa.params.subPrime);
  1122           if (rv != SECSuccess) break;
  1123           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
  1124                                 &pubk->u.dsa.params.base);
  1125           break;
  1126       case dhKey:
  1127           rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
  1128           if (rv != SECSuccess) break;
  1129           rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
  1130           if (rv != SECSuccess) break;
  1131           rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue, 
  1132                                 &pubk->u.dh.publicValue);
  1133           break;
  1134       case ecKey:
  1135           copyk->u.ec.size = pubk->u.ec.size;
  1136           rv = SECITEM_CopyItem(arena,&copyk->u.ec.DEREncodedParams,
  1137                                 &pubk->u.ec.DEREncodedParams);
  1138           if (rv != SECSuccess) break;
  1139           rv = SECITEM_CopyItem(arena,&copyk->u.ec.publicValue,
  1140                                 &pubk->u.ec.publicValue);
  1141           break;
  1142       case nullKey:
  1143           return copyk;
  1144       default:
  1145           PORT_SetError(SEC_ERROR_INVALID_KEY);
  1146           rv = SECFailure;
  1147           break;
  1149     if (rv == SECSuccess)
  1150         return copyk;
  1152     SECKEY_DestroyPublicKey (copyk);
  1153     return NULL;
  1157 SECKEYPublicKey *
  1158 SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
  1160     SECKEYPublicKey *pubk;
  1161     PLArenaPool *arena;
  1162     CERTCertificate *cert;
  1163     SECStatus rv;
  1165     /*
  1166      * First try to look up the cert.
  1167      */
  1168     cert = PK11_GetCertFromPrivateKey(privk);
  1169     if (cert) {
  1170 	pubk = CERT_ExtractPublicKey(cert);
  1171 	CERT_DestroyCertificate(cert);
  1172 	return pubk;
  1175     /* couldn't find the cert, build pub key by hand */
  1176     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  1177     if (arena == NULL) {
  1178 	PORT_SetError (SEC_ERROR_NO_MEMORY);
  1179 	return NULL;
  1181     pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
  1182 						   sizeof (SECKEYPublicKey));
  1183     if (pubk == NULL) {
  1184 	PORT_FreeArena(arena,PR_FALSE);
  1185 	return NULL;
  1187     pubk->keyType = privk->keyType;
  1188     pubk->pkcs11Slot = NULL;
  1189     pubk->pkcs11ID = CK_INVALID_HANDLE;
  1190     pubk->arena = arena;
  1192     switch(privk->keyType) {
  1193       case nullKey:
  1194       case dhKey:
  1195       case dsaKey:
  1196 	/* Nothing to query, if the cert isn't there, we're done -- no way
  1197 	 * to get the public key */
  1198 	break;
  1199       case rsaKey:
  1200 	rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
  1201 				CKA_MODULUS,arena,&pubk->u.rsa.modulus);
  1202 	if (rv != SECSuccess)  break;
  1203 	rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
  1204 			CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent);
  1205 	if (rv != SECSuccess)  break;
  1206 	return pubk;
  1207 	break;
  1208     default:
  1209 	break;
  1212     PORT_FreeArena (arena, PR_FALSE);
  1213     return NULL;
  1216 static CERTSubjectPublicKeyInfo *
  1217 seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk)
  1219     CERTSubjectPublicKeyInfo *spki;
  1220     PLArenaPool *arena;
  1221     SECItem params = { siBuffer, NULL, 0 };
  1223     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1224     if (arena == NULL) {
  1225 	PORT_SetError(SEC_ERROR_NO_MEMORY);
  1226 	return NULL;
  1229     spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki));
  1230     if (spki != NULL) {
  1231 	SECStatus rv;
  1232 	SECItem *rv_item;
  1234 	spki->arena = arena;
  1235 	switch(pubk->keyType) {
  1236 	  case rsaKey:
  1237 	    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1238 				     SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
  1239 	    if (rv == SECSuccess) {
  1240 		/*
  1241 		 * DER encode the public key into the subjectPublicKeyInfo.
  1242 		 */
  1243 		prepare_rsa_pub_key_for_asn1(pubk);
  1244 		rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
  1245 					     pubk, SECKEY_RSAPublicKeyTemplate);
  1246 		if (rv_item != NULL) {
  1247 		    /*
  1248 		     * The stored value is supposed to be a BIT_STRING,
  1249 		     * so convert the length.
  1250 		     */
  1251 		    spki->subjectPublicKey.len <<= 3;
  1252 		    /*
  1253 		     * We got a good one; return it.
  1254 		     */
  1255 		    return spki;
  1258 	    break;
  1259 	  case dsaKey:
  1260 	    /* DER encode the params. */
  1261 	    prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
  1262 	    rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
  1263 					 SECKEY_PQGParamsTemplate);
  1264 	    if (rv_item != NULL) {
  1265 		rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1266 					   SEC_OID_ANSIX9_DSA_SIGNATURE,
  1267 					   &params);
  1268 		if (rv == SECSuccess) {
  1269 		    /*
  1270 		     * DER encode the public key into the subjectPublicKeyInfo.
  1271 		     */
  1272 		    prepare_dsa_pub_key_for_asn1(pubk);
  1273 		    rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
  1274 						 pubk,
  1275 						 SECKEY_DSAPublicKeyTemplate);
  1276 		    if (rv_item != NULL) {
  1277 			/*
  1278 			 * The stored value is supposed to be a BIT_STRING,
  1279 			 * so convert the length.
  1280 			 */
  1281 			spki->subjectPublicKey.len <<= 3;
  1282 			/*
  1283 			 * We got a good one; return it.
  1284 			 */
  1285 			return spki;
  1289 	    SECITEM_FreeItem(&params, PR_FALSE);
  1290 	    break;
  1291 	  case ecKey:
  1292 	    rv = SECITEM_CopyItem(arena, &params, 
  1293 				  &pubk->u.ec.DEREncodedParams);
  1294 	    if (rv != SECSuccess) break;
  1296 	    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
  1297 				       SEC_OID_ANSIX962_EC_PUBLIC_KEY,
  1298 				       &params);
  1299 	    if (rv != SECSuccess) break;
  1301 	    rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
  1302 				  &pubk->u.ec.publicValue);
  1304 	    if (rv == SECSuccess) {
  1305 	        /*
  1306 		 * The stored value is supposed to be a BIT_STRING,
  1307 		 * so convert the length.
  1308 		 */
  1309 	        spki->subjectPublicKey.len <<= 3;
  1310 		/*
  1311 		 * We got a good one; return it.
  1312 		 */
  1313 		return spki;
  1315 	    break;
  1316 	  case dhKey: /* later... */
  1318 	    break;
  1319 	  default:
  1320 	    break;
  1322     } else {
  1323 	PORT_SetError(SEC_ERROR_NO_MEMORY);
  1326     PORT_FreeArena(arena, PR_FALSE);
  1327     return NULL;
  1330 CERTSubjectPublicKeyInfo *
  1331 SECKEY_CreateSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
  1333     CERTSubjectPublicKeyInfo *spki;
  1334     SECKEYPublicKey *tempKey;
  1336     if (!pubk) {
  1337         PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1338         return NULL;
  1341     tempKey = SECKEY_CopyPublicKey(pubk);
  1342     if (!tempKey) {
  1343         return NULL;
  1345     spki = seckey_CreateSubjectPublicKeyInfo_helper(tempKey);
  1346     SECKEY_DestroyPublicKey(tempKey);
  1347     return spki;
  1350 void
  1351 SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
  1353     if (spki && spki->arena) {
  1354 	PORT_FreeArena(spki->arena, PR_FALSE);
  1358 SECItem *
  1359 SECKEY_EncodeDERSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
  1361     CERTSubjectPublicKeyInfo *spki=NULL;
  1362     SECItem *spkiDER=NULL;
  1364     /* get the subjectpublickeyinfo */
  1365     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
  1366     if( spki == NULL ) {
  1367 	goto finish;
  1370     /* DER-encode the subjectpublickeyinfo */
  1371     spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
  1372 					CERT_SubjectPublicKeyInfoTemplate);
  1374     SECKEY_DestroySubjectPublicKeyInfo(spki);
  1376 finish:
  1377     return spkiDER;
  1381 CERTSubjectPublicKeyInfo *
  1382 SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider)
  1384     PLArenaPool *arena;
  1385     CERTSubjectPublicKeyInfo *spki;
  1386     SECStatus rv;
  1387     SECItem newSpkider;
  1389     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1390     if (arena == NULL) {
  1391 	PORT_SetError(SEC_ERROR_NO_MEMORY);
  1392 	return NULL;
  1395     spki = (CERTSubjectPublicKeyInfo *)
  1396 		PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo));
  1397     if (spki != NULL) {
  1398 	spki->arena = arena;
  1400         /* copy the DER into the arena, since Quick DER returns data that points
  1401            into the DER input, which may get freed by the caller */
  1402         rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
  1403         if ( rv == SECSuccess ) {
  1404             rv = SEC_QuickDERDecodeItem(arena,spki,
  1405 				    CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
  1407 	if (rv == SECSuccess)
  1408 	    return spki;
  1409     } else {
  1410 	PORT_SetError(SEC_ERROR_NO_MEMORY);
  1413     PORT_FreeArena(arena, PR_FALSE);
  1414     return NULL;
  1417 /*
  1418  * Decode a base64 ascii encoded DER encoded subject public key info.
  1419  */
  1420 CERTSubjectPublicKeyInfo *
  1421 SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(const char *spkistr)
  1423     CERTSubjectPublicKeyInfo *spki;
  1424     SECStatus rv;
  1425     SECItem der;
  1427     rv = ATOB_ConvertAsciiToItem(&der, spkistr);
  1428     if (rv != SECSuccess)
  1429 	return NULL;
  1431     spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
  1433     PORT_Free(der.data);
  1434     return spki;
  1437 /*
  1438  * Decode a base64 ascii encoded DER encoded public key and challenge
  1439  * Verify digital signature and make sure challenge matches
  1440  */
  1441 CERTSubjectPublicKeyInfo *
  1442 SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
  1443 								void *wincx)
  1445     CERTSubjectPublicKeyInfo *spki = NULL;
  1446     CERTPublicKeyAndChallenge pkac;
  1447     SECStatus rv;
  1448     SECItem signedItem;
  1449     PLArenaPool *arena = NULL;
  1450     CERTSignedData sd;
  1451     SECItem sig;
  1452     SECKEYPublicKey *pubKey = NULL;
  1453     unsigned int len;
  1455     signedItem.data = NULL;
  1457     /* convert the base64 encoded data to binary */
  1458     rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
  1459     if (rv != SECSuccess) {
  1460 	goto loser;
  1463     /* create an arena */
  1464     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1465     if (arena == NULL) {
  1466 	goto loser;
  1469     /* decode the outer wrapping of signed data */
  1470     PORT_Memset(&sd, 0, sizeof(CERTSignedData));
  1471     rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem );
  1472     if ( rv ) {
  1473 	goto loser;
  1476     /* decode the public key and challenge wrapper */
  1477     PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
  1478     rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, 
  1479 			    &sd.data);
  1480     if ( rv ) {
  1481 	goto loser;
  1484     /* decode the subject public key info */
  1485     spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
  1486     if ( spki == NULL ) {
  1487 	goto loser;
  1490     /* get the public key */
  1491     pubKey = seckey_ExtractPublicKey(spki);
  1492     if ( pubKey == NULL ) {
  1493 	goto loser;
  1496     /* check the signature */
  1497     sig = sd.signature;
  1498     DER_ConvertBitString(&sig);
  1499     rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
  1500 			&(sd.signatureAlgorithm), NULL, wincx);
  1501     if ( rv != SECSuccess ) {
  1502 	goto loser;
  1505     /* check the challenge */
  1506     if ( challenge ) {
  1507 	len = PORT_Strlen(challenge);
  1508 	/* length is right */
  1509 	if ( len != pkac.challenge.len ) {
  1510 	    goto loser;
  1512 	/* actual data is right */
  1513 	if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) {
  1514 	    goto loser;
  1517     goto done;
  1519 loser:
  1520     /* make sure that we return null if we got an error */
  1521     if ( spki ) {
  1522 	SECKEY_DestroySubjectPublicKeyInfo(spki);
  1524     spki = NULL;
  1526 done:
  1527     if ( signedItem.data ) {
  1528 	PORT_Free(signedItem.data);
  1530     if ( arena ) {
  1531 	PORT_FreeArena(arena, PR_FALSE);
  1533     if ( pubKey ) {
  1534 	SECKEY_DestroyPublicKey(pubKey);
  1537     return spki;
  1540 void
  1541 SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
  1542 			     PRBool freeit)
  1544     PLArenaPool *poolp;
  1546     if(pvk != NULL) {
  1547 	if(pvk->arena) {
  1548 	    poolp = pvk->arena;
  1549 	    /* zero structure since PORT_FreeArena does not support
  1550 	     * this yet.
  1551 	     */
  1552 	    PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
  1553 	    PORT_Memset((char *)pvk, 0, sizeof(*pvk));
  1554 	    if(freeit == PR_TRUE) {
  1555 		PORT_FreeArena(poolp, PR_TRUE);
  1556 	    } else {
  1557 		pvk->arena = poolp;
  1559 	} else {
  1560 	    SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
  1561 	    SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
  1562 	    SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
  1563 	    PORT_Memset((char *)pvk, 0, sizeof(*pvk));
  1564 	    if(freeit == PR_TRUE) {
  1565 		PORT_Free(pvk);
  1571 void
  1572 SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
  1573 				      PRBool freeit)
  1575     PLArenaPool *poolp;
  1577     if(epki != NULL) {
  1578 	if(epki->arena) {
  1579 	    poolp = epki->arena;
  1580 	    /* zero structure since PORT_FreeArena does not support
  1581 	     * this yet.
  1582 	     */
  1583 	    PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
  1584 	    PORT_Memset((char *)epki, 0, sizeof(*epki));
  1585 	    if(freeit == PR_TRUE) {
  1586 		PORT_FreeArena(poolp, PR_TRUE);
  1587 	    } else {
  1588 		epki->arena = poolp;
  1590 	} else {
  1591 	    SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
  1592 	    SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
  1593 	    PORT_Memset((char *)epki, 0, sizeof(*epki));
  1594 	    if(freeit == PR_TRUE) {
  1595 		PORT_Free(epki);
  1601 SECStatus
  1602 SECKEY_CopyPrivateKeyInfo(PLArenaPool *poolp,
  1603 			  SECKEYPrivateKeyInfo *to,
  1604 			  const SECKEYPrivateKeyInfo *from)
  1606     SECStatus rv = SECFailure;
  1608     if((to == NULL) || (from == NULL)) {
  1609 	return SECFailure;
  1612     rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
  1613     if(rv != SECSuccess) {
  1614 	return SECFailure;
  1616     rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
  1617     if(rv != SECSuccess) {
  1618 	return SECFailure;
  1620     rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
  1622     return rv;
  1625 SECStatus
  1626 SECKEY_CopyEncryptedPrivateKeyInfo(PLArenaPool *poolp,
  1627 				   SECKEYEncryptedPrivateKeyInfo *to,
  1628 				   const SECKEYEncryptedPrivateKeyInfo *from)
  1630     SECStatus rv = SECFailure;
  1632     if((to == NULL) || (from == NULL)) {
  1633 	return SECFailure;
  1636     rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
  1637     if(rv != SECSuccess) {
  1638 	return SECFailure;
  1640     rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
  1642     return rv;
  1645 KeyType
  1646 SECKEY_GetPrivateKeyType(const SECKEYPrivateKey *privKey)
  1648    return privKey->keyType;
  1651 KeyType
  1652 SECKEY_GetPublicKeyType(const SECKEYPublicKey *pubKey)
  1654    return pubKey->keyType;
  1657 SECKEYPublicKey*
  1658 SECKEY_ImportDERPublicKey(const SECItem *derKey, CK_KEY_TYPE type)
  1660     SECKEYPublicKey *pubk = NULL;
  1661     SECStatus rv = SECFailure;
  1662     SECItem newDerKey;
  1663     PLArenaPool *arena = NULL;
  1665     if (!derKey) {
  1666         return NULL;
  1669     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1670     if (arena == NULL) {
  1671 	PORT_SetError(SEC_ERROR_NO_MEMORY);
  1672         goto finish;
  1675     pubk = PORT_ArenaZNew(arena, SECKEYPublicKey);
  1676     if (pubk == NULL) {
  1677         goto finish;
  1679     pubk->arena = arena;
  1681     rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
  1682     if (SECSuccess != rv) {
  1683         goto finish;
  1686     pubk->pkcs11Slot = NULL;
  1687     pubk->pkcs11ID = CK_INVALID_HANDLE;
  1689     switch( type ) {
  1690       case CKK_RSA:
  1691 	prepare_rsa_pub_key_for_asn1(pubk);
  1692         rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
  1693         pubk->keyType = rsaKey;
  1694         break;
  1695       case CKK_DSA:
  1696 	prepare_dsa_pub_key_for_asn1(pubk);
  1697         rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
  1698         pubk->keyType = dsaKey;
  1699         break;
  1700       case CKK_DH:
  1701 	prepare_dh_pub_key_for_asn1(pubk);
  1702         rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
  1703         pubk->keyType = dhKey;
  1704         break;
  1705       default:
  1706         rv = SECFailure;
  1707         break;
  1710 finish:
  1711     if (rv != SECSuccess) {
  1712         if (arena != NULL) {
  1713             PORT_FreeArena(arena, PR_FALSE);
  1715         pubk = NULL;
  1717     return pubk;
  1720 SECKEYPrivateKeyList*
  1721 SECKEY_NewPrivateKeyList(void)
  1723     PLArenaPool *arena = NULL;
  1724     SECKEYPrivateKeyList *ret = NULL;
  1726     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1727     if ( arena == NULL ) {
  1728         goto loser;
  1731     ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
  1732                 sizeof(SECKEYPrivateKeyList));
  1733     if ( ret == NULL ) {
  1734         goto loser;
  1737     ret->arena = arena;
  1739     PR_INIT_CLIST(&ret->list);
  1741     return(ret);
  1743 loser:
  1744     if ( arena != NULL ) {
  1745         PORT_FreeArena(arena, PR_FALSE);
  1748     return(NULL);
  1751 void
  1752 SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys)
  1754     while( !PR_CLIST_IS_EMPTY(&keys->list) ) {
  1755         SECKEY_RemovePrivateKeyListNode(
  1756             (SECKEYPrivateKeyListNode*)(PR_LIST_HEAD(&keys->list)) );
  1759     PORT_FreeArena(keys->arena, PR_FALSE);
  1761     return;
  1765 void
  1766 SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node)
  1768     PR_ASSERT(node->key);
  1769     SECKEY_DestroyPrivateKey(node->key);
  1770     node->key = NULL;
  1771     PR_REMOVE_LINK(&node->links);
  1772     return;
  1776 SECStatus
  1777 SECKEY_AddPrivateKeyToListTail( SECKEYPrivateKeyList *list,
  1778                                 SECKEYPrivateKey *key)
  1780     SECKEYPrivateKeyListNode *node;
  1782     node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena,
  1783                 sizeof(SECKEYPrivateKeyListNode));
  1784     if ( node == NULL ) {
  1785         goto loser;
  1788     PR_INSERT_BEFORE(&node->links, &list->list);
  1789     node->key = key;
  1790     return(SECSuccess);
  1792 loser:
  1793     return(SECFailure);
  1797 SECKEYPublicKeyList*
  1798 SECKEY_NewPublicKeyList(void)
  1800     PLArenaPool *arena = NULL;
  1801     SECKEYPublicKeyList *ret = NULL;
  1803     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1804     if ( arena == NULL ) {
  1805         goto loser;
  1808     ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena,
  1809                 sizeof(SECKEYPublicKeyList));
  1810     if ( ret == NULL ) {
  1811         goto loser;
  1814     ret->arena = arena;
  1816     PR_INIT_CLIST(&ret->list);
  1818     return(ret);
  1820 loser:
  1821     if ( arena != NULL ) {
  1822         PORT_FreeArena(arena, PR_FALSE);
  1825     return(NULL);
  1828 void
  1829 SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys)
  1831     while( !PR_CLIST_IS_EMPTY(&keys->list) ) {
  1832         SECKEY_RemovePublicKeyListNode(
  1833             (SECKEYPublicKeyListNode*)(PR_LIST_HEAD(&keys->list)) );
  1836     PORT_FreeArena(keys->arena, PR_FALSE);
  1838     return;
  1842 void
  1843 SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node)
  1845     PR_ASSERT(node->key);
  1846     SECKEY_DestroyPublicKey(node->key);
  1847     node->key = NULL;
  1848     PR_REMOVE_LINK(&node->links);
  1849     return;
  1853 SECStatus
  1854 SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list,
  1855                                 SECKEYPublicKey *key)
  1857     SECKEYPublicKeyListNode *node;
  1859     node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena,
  1860                 sizeof(SECKEYPublicKeyListNode));
  1861     if ( node == NULL ) {
  1862         goto loser;
  1865     PR_INSERT_BEFORE(&node->links, &list->list);
  1866     node->key = key;
  1867     return(SECSuccess);
  1869 loser:
  1870     return(SECFailure);
  1873 #define SECKEY_CacheAttribute(key, attribute) \
  1874     if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \
  1875         key->staticflags |= SECKEY_##attribute; \
  1876     } else { \
  1877         key->staticflags &= (~SECKEY_##attribute); \
  1880 SECStatus
  1881 SECKEY_CacheStaticFlags(SECKEYPrivateKey* key)
  1883     SECStatus rv = SECFailure;
  1884     if (key && key->pkcs11Slot && key->pkcs11ID) {
  1885         key->staticflags |= SECKEY_Attributes_Cached;
  1886         SECKEY_CacheAttribute(key, CKA_PRIVATE);
  1887         SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE);
  1888         rv = SECSuccess;
  1890     return rv;

mercurial