PageRenderTime 123ms CodeModel.GetById 16ms app.highlight 96ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/lib/cryptohi/seckey.c

http://github.com/zpao/v8monkey
C | 1961 lines | 1470 code | 283 blank | 208 comment | 288 complexity | 8f8ef2d574c41de21600325cdb364368 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* ***** BEGIN LICENSE BLOCK *****
   2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   3 *
   4 * The contents of this file are subject to the Mozilla Public License Version
   5 * 1.1 (the "License"); you may not use this file except in compliance with
   6 * the License. You may obtain a copy of the License at
   7 * http://www.mozilla.org/MPL/
   8 *
   9 * Software distributed under the License is distributed on an "AS IS" basis,
  10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11 * for the specific language governing rights and limitations under the
  12 * License.
  13 *
  14 * The Original Code is the Netscape security libraries.
  15 *
  16 * The Initial Developer of the Original Code is
  17 * Netscape Communications Corporation.
  18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19 * the Initial Developer. All Rights Reserved.
  20 *
  21 * Contributor(s):
  22 *   Dr Stephen Henson <stephen.henson@gemplus.com>
  23 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  24 *
  25 * Alternatively, the contents of this file may be used under the terms of
  26 * either the GNU General Public License Version 2 or later (the "GPL"), or
  27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28 * in which case the provisions of the GPL or the LGPL are applicable instead
  29 * of those above. If you wish to allow use of your version of this file only
  30 * under the terms of either the GPL or the LGPL, and not to allow others to
  31 * use your version of this file under the terms of the MPL, indicate your
  32 * decision by deleting the provisions above and replace them with the notice
  33 * and other provisions required by the GPL or the LGPL. If you do not delete
  34 * the provisions above, a recipient may use your version of this file under
  35 * the terms of any one of the MPL, the GPL or the LGPL.
  36 *
  37 * ***** END LICENSE BLOCK ***** */
  38#include "cryptohi.h"
  39#include "keyhi.h"
  40#include "secoid.h"
  41#include "secitem.h"
  42#include "secder.h"
  43#include "base64.h"
  44#include "secasn1.h"
  45#include "cert.h"
  46#include "pk11func.h"
  47#include "secerr.h"
  48#include "secdig.h"
  49#include "prtime.h"
  50#include "ec.h"
  51#include "keyi.h"
  52
  53SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  54SEC_ASN1_MKSUB(SEC_IntegerTemplate)
  55
  56const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
  57    { SEC_ASN1_SEQUENCE,
  58	  0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
  59    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  60	  offsetof(CERTSubjectPublicKeyInfo,algorithm),
  61	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  62    { SEC_ASN1_BIT_STRING,
  63	  offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
  64    { 0, }
  65};
  66
  67const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
  68{
  69    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
  70    { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },
  71    { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },
  72    { 0 }
  73};
  74
  75const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
  76    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
  77    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },
  78    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },
  79    { 0, }
  80};
  81
  82static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = {
  83    { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0,
  84      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }
  85};
  86
  87/* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */
  88const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] =
  89{
  90    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) },
  91    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
  92          SEC_ASN1_CONTEXT_SPECIFIC | 0,
  93          offsetof(SECKEYRSAPSSParams, hashAlg),
  94          seckey_PointerToAlgorithmIDTemplate },
  95    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
  96          SEC_ASN1_CONTEXT_SPECIFIC | 1,
  97          offsetof(SECKEYRSAPSSParams, maskAlg),
  98          seckey_PointerToAlgorithmIDTemplate },
  99    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
 100          SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2,
 101          offsetof(SECKEYRSAPSSParams, saltLength),
 102          SEC_ASN1_SUB(SEC_IntegerTemplate) },
 103    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
 104          SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3,
 105          offsetof(SECKEYRSAPSSParams, trailerField),
 106          SEC_ASN1_SUB(SEC_IntegerTemplate) },
 107    { 0 }
 108};
 109
 110const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
 111    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },
 112    { 0, }
 113};
 114
 115const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
 116    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
 117    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
 118    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
 119    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
 120    { 0, }
 121};
 122
 123const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
 124    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
 125    { 0, }
 126};
 127
 128const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
 129    { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(SECKEYPublicKey) },
 130    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
 131    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
 132    /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
 133    { SEC_ASN1_SKIP_REST },
 134    { 0, }
 135};
 136
 137SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
 138SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
 139SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate)
 140SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
 141
 142/*
 143 * See bugzilla bug 125359
 144 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
 145 * all of the templates above that en/decode into integers must be converted
 146 * from ASN.1's signed integer type.  This is done by marking either the
 147 * source or destination (encoding or decoding, respectively) type as
 148 * siUnsignedInteger.
 149 */
 150static void
 151prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
 152{
 153    pubk->u.rsa.modulus.type = siUnsignedInteger;
 154    pubk->u.rsa.publicExponent.type = siUnsignedInteger;
 155}
 156
 157static void
 158prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
 159{
 160    pubk->u.dsa.publicValue.type = siUnsignedInteger;
 161}
 162
 163static void
 164prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
 165{
 166    params->prime.type = siUnsignedInteger;
 167    params->subPrime.type = siUnsignedInteger;
 168    params->base.type = siUnsignedInteger;
 169}
 170
 171static void
 172prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
 173{
 174    pubk->u.dh.prime.type = siUnsignedInteger;
 175    pubk->u.dh.base.type = siUnsignedInteger;
 176    pubk->u.dh.publicValue.type = siUnsignedInteger;
 177}
 178
 179/* Create an RSA key pair is any slot able to do so.
 180** The created keys are "session" (temporary), not "token" (permanent), 
 181** and they are "sensitive", which makes them costly to move to another token.
 182*/
 183SECKEYPrivateKey *
 184SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx)
 185{
 186    SECKEYPrivateKey *privk;
 187    PK11RSAGenParams param;
 188    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);
 189    if (!slot) {
 190	return NULL;
 191    }
 192
 193    param.keySizeInBits = keySizeInBits;
 194    param.pe = 65537L;
 195    
 196    privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,
 197					PR_FALSE, PR_TRUE, cx);
 198    PK11_FreeSlot(slot);
 199    return(privk);
 200}
 201
 202/* Create a DH key pair in any slot able to do so, 
 203** This is a "session" (temporary), not "token" (permanent) key. 
 204** Because of the high probability that this key will need to be moved to
 205** another token, and the high cost of moving "sensitive" keys, we attempt
 206** to create this key pair without the "sensitive" attribute, but revert to 
 207** creating a "sensitive" key if necessary.
 208*/
 209SECKEYPrivateKey *
 210SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
 211{
 212    SECKEYPrivateKey *privk;
 213    PK11SlotInfo *slot;
 214
 215    if (!param || !param->base.data || !param->prime.data ||
 216        param->prime.len < 512/8 || param->base.len == 0 || 
 217        param->base.len > param->prime.len + 1 || 
 218	(param->base.len == 1 && param->base.data[0] == 0)) {
 219	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 220	return NULL;
 221    }
 222
 223    slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
 224    if (!slot) {
 225	return NULL;
 226    }
 227
 228    privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 
 229                                 pubk, PR_FALSE, PR_FALSE, cx);
 230    if (!privk) 
 231	privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 
 232	                             pubk, PR_FALSE, PR_TRUE, cx);
 233
 234    PK11_FreeSlot(slot);
 235    return(privk);
 236}
 237
 238/* Create an EC key pair in any slot able to do so, 
 239** This is a "session" (temporary), not "token" (permanent) key. 
 240** Because of the high probability that this key will need to be moved to
 241** another token, and the high cost of moving "sensitive" keys, we attempt
 242** to create this key pair without the "sensitive" attribute, but revert to 
 243** creating a "sensitive" key if necessary.
 244*/
 245SECKEYPrivateKey *
 246SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
 247{
 248    SECKEYPrivateKey *privk;
 249    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx);
 250    if (!slot) {
 251	return NULL;
 252    }
 253
 254    privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, 
 255                        param, pubk,
 256                        PK11_ATTR_SESSION | PK11_ATTR_INSENSITIVE | 
 257                        PK11_ATTR_PUBLIC,
 258                        CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx);
 259    if (!privk) 
 260        privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN, 
 261                        param, pubk,
 262                        PK11_ATTR_SESSION | PK11_ATTR_SENSITIVE | 
 263                        PK11_ATTR_PRIVATE,
 264                        CKF_DERIVE, CKF_DERIVE|CKF_SIGN,cx);
 265
 266    PK11_FreeSlot(slot);
 267    return(privk);
 268}
 269
 270void
 271SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
 272{
 273    if (privk) {
 274	if (privk->pkcs11Slot) {
 275	    if (privk->pkcs11IsTemp) {
 276	    	PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);
 277	    }
 278	    PK11_FreeSlot(privk->pkcs11Slot);
 279
 280	}
 281    	if (privk->arena) {
 282	    PORT_FreeArena(privk->arena, PR_TRUE);
 283	}
 284    }
 285}
 286
 287void
 288SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
 289{
 290    if (pubk) {
 291	if (pubk->pkcs11Slot) {
 292	    if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
 293		PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);
 294	    }
 295	    PK11_FreeSlot(pubk->pkcs11Slot);
 296	}
 297    	if (pubk->arena) {
 298	    PORT_FreeArena(pubk->arena, PR_FALSE);
 299	}
 300    }
 301}
 302
 303SECStatus
 304SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,
 305			     CERTSubjectPublicKeyInfo *to,
 306			     CERTSubjectPublicKeyInfo *from)
 307{
 308    SECStatus rv;
 309    SECItem spk;
 310
 311    rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
 312    if (rv == SECSuccess) {
 313	/*
 314	 * subjectPublicKey is a bit string, whose length is in bits.
 315	 * Convert the length from bits to bytes for SECITEM_CopyItem.
 316	 */
 317	spk = from->subjectPublicKey;
 318	DER_ConvertBitString(&spk);
 319	rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
 320	/* Set the length back to bits. */
 321	if (rv == SECSuccess) {
 322	    to->subjectPublicKey.len = from->subjectPublicKey.len;
 323	}
 324    }
 325
 326    return rv;
 327}
 328
 329/* Procedure to update the pqg parameters for a cert's public key.
 330 * pqg parameters only need to be updated for DSA certificates.
 331 * The procedure uses calls to itself recursively to update a certificate
 332 * issuer's pqg parameters.  Some important rules are:
 333 *    - Do nothing if the cert already has PQG parameters.
 334 *    - If the cert does not have PQG parameters, obtain them from the issuer.
 335 *    - A valid cert chain cannot have a DSA cert without
 336 *      pqg parameters that has a parent that is not a DSA cert.  */
 337
 338static SECStatus
 339seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count)
 340{
 341    SECStatus rv;
 342    SECOidData *oid=NULL;
 343    int tag;
 344    CERTSubjectPublicKeyInfo * subjectSpki=NULL;
 345    CERTSubjectPublicKeyInfo * issuerSpki=NULL;
 346    CERTCertificate *issuerCert = NULL;
 347
 348    rv = SECSuccess;
 349
 350    /* increment cert chain length counter*/
 351    count++;
 352
 353    /* check if cert chain length exceeds the maximum length*/
 354    if (count > CERT_MAX_CERT_CHAIN) {
 355	return SECFailure;
 356    }
 357
 358    oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);            
 359    if (oid != NULL) {  
 360        tag = oid->offset;
 361             
 362        /* Check if cert has a DSA public key. If not, return
 363         * success since no PQG params need to be updated.  */
 364
 365	if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
 366             (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
 367             (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
 368             (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
 369             (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
 370            
 371            return SECSuccess;
 372        }
 373    } else {
 374        return SECFailure;  /* return failure if oid is NULL */  
 375    }
 376
 377    /* if cert has PQG parameters, return success */
 378
 379    subjectSpki=&subjectCert->subjectPublicKeyInfo;
 380
 381    if (subjectSpki->algorithm.parameters.len != 0) {
 382        return SECSuccess;
 383    }
 384
 385    /* check if the cert is self-signed */
 386    if (subjectCert->isRoot) {
 387      /* fail since cert is self-signed and has no pqg params. */
 388	return SECFailure;     
 389    }
 390     
 391    /* get issuer cert */
 392    issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
 393    if ( ! issuerCert ) {
 394	return SECFailure;
 395    }
 396
 397    /* if parent is not DSA, return failure since
 398       we don't allow this case. */
 399
 400    oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
 401    if (oid != NULL) {  
 402        tag = oid->offset;
 403             
 404        /* Check if issuer cert has a DSA public key. If not,
 405         * return failure.   */
 406
 407	if ( (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
 408             (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
 409             (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
 410             (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
 411             (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {            
 412            rv = SECFailure;
 413            goto loser;
 414        }
 415    } else {
 416        rv = SECFailure;  /* return failure if oid is NULL */  
 417        goto loser;
 418    }
 419
 420
 421    /* at this point the subject cert has no pqg parameters and the
 422     * issuer cert has a DSA public key.  Update the issuer's
 423     * pqg parameters with a recursive call to this same function. */
 424
 425    rv = seckey_UpdateCertPQGChain(issuerCert, count);
 426    if (rv != SECSuccess) {
 427        rv = SECFailure;
 428        goto loser;
 429    }
 430
 431    /* ensure issuer has pqg parameters */
 432
 433    issuerSpki=&issuerCert->subjectPublicKeyInfo;
 434    if (issuerSpki->algorithm.parameters.len == 0) {
 435        rv = SECFailure; 
 436    }
 437
 438    /* if update was successful and pqg params present, then copy the
 439     * parameters to the subject cert's key. */
 440
 441    if (rv == SECSuccess) {
 442        rv = SECITEM_CopyItem(subjectCert->arena,
 443                              &subjectSpki->algorithm.parameters, 
 444	   		      &issuerSpki->algorithm.parameters);
 445    }
 446
 447loser:
 448    if (issuerCert) {
 449        CERT_DestroyCertificate(issuerCert);
 450    }
 451    return rv;
 452
 453}
 454 
 455
 456SECStatus
 457SECKEY_UpdateCertPQG(CERTCertificate * subjectCert)
 458{
 459    if (!subjectCert) {
 460        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 461	return SECFailure;
 462    }
 463    return seckey_UpdateCertPQGChain(subjectCert,0);
 464}
 465   
 466
 467/* Decode the DSA PQG parameters.  The params could be stored in two
 468 * possible formats, the old fortezza-only wrapped format or
 469 * the normal standard format.  Store the decoded parameters in
 470 * a V3 certificate data structure.  */ 
 471
 472SECStatus
 473SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params) {
 474    SECStatus rv;
 475    SECItem newparams;
 476
 477    if (params == NULL) return SECFailure; 
 478    
 479    if (params->data == NULL) return SECFailure;
 480
 481    PORT_Assert(arena);
 482
 483    /* make a copy of the data into the arena so QuickDER output is valid */
 484    rv = SECITEM_CopyItem(arena, &newparams, params);
 485
 486    /* Check if params use the standard format.
 487     * The value 0xa1 will appear in the first byte of the parameter data
 488     * if the PQG parameters are not using the standard format.  This
 489     * code should be changed to use a better method to detect non-standard
 490     * parameters.    */
 491
 492    if ((newparams.data[0] != 0xa1) &&
 493        (newparams.data[0] != 0xa0)) {
 494    
 495        if (SECSuccess == rv) {
 496             /* PQG params are in the standard format */
 497             prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
 498             rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
 499                                 SECKEY_PQGParamsTemplate,
 500                                 &newparams);
 501        }
 502    } else {
 503
 504        if (SECSuccess == rv) {
 505            /* else the old fortezza-only wrapped format is used. */
 506            PORT_SetError(SEC_ERROR_BAD_DER);
 507            rv = SECFailure;
 508        }
 509    }
 510    return rv;
 511}
 512
 513
 514/* Function used to make an oid tag to a key type */
 515KeyType 
 516seckey_GetKeyType (SECOidTag tag) {
 517    KeyType keyType;
 518
 519    switch (tag) {
 520      case SEC_OID_X500_RSA_ENCRYPTION:
 521      case SEC_OID_PKCS1_RSA_ENCRYPTION:
 522	keyType = rsaKey;
 523	break;
 524      case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
 525	keyType = rsaPssKey;
 526	break;
 527      case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
 528	keyType = rsaOaepKey;
 529	break;
 530      case SEC_OID_ANSIX9_DSA_SIGNATURE:
 531	keyType = dsaKey;
 532	break;
 533      case SEC_OID_MISSI_KEA_DSS_OLD:
 534      case SEC_OID_MISSI_KEA_DSS:
 535      case SEC_OID_MISSI_DSS_OLD:
 536      case SEC_OID_MISSI_DSS:  
 537	keyType = fortezzaKey;
 538	break;
 539      case SEC_OID_MISSI_KEA:
 540      case SEC_OID_MISSI_ALT_KEA:
 541	keyType = keaKey;
 542	break;
 543      case SEC_OID_X942_DIFFIE_HELMAN_KEY:
 544	keyType = dhKey;
 545	break;
 546      case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
 547	keyType = ecKey;
 548	break;
 549      /* accommodate applications that hand us a signature type when they 
 550	* should be handing us a cipher type */
 551      case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
 552      case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
 553      case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
 554      case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
 555      case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
 556      case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
 557	keyType = rsaKey;
 558	break;
 559      default:
 560	keyType = nullKey;
 561    }
 562    return keyType;
 563}
 564
 565/* Function used to determine what kind of cert we are dealing with. */
 566KeyType 
 567CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) 
 568{
 569    return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
 570}
 571
 572static SECKEYPublicKey *
 573seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
 574{
 575    SECKEYPublicKey *pubk;
 576    SECItem os, newOs, newParms;
 577    SECStatus rv;
 578    PRArenaPool *arena;
 579    SECOidTag tag;
 580
 581    arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
 582    if (arena == NULL)
 583	return NULL;
 584
 585    pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
 586    if (pubk == NULL) {
 587	PORT_FreeArena (arena, PR_FALSE);
 588	return NULL;
 589    }
 590
 591    pubk->arena = arena;
 592    pubk->pkcs11Slot = 0;
 593    pubk->pkcs11ID = CK_INVALID_HANDLE;
 594
 595
 596    /* Convert bit string length from bits to bytes */
 597    os = spki->subjectPublicKey;
 598    DER_ConvertBitString (&os);
 599
 600    tag = SECOID_GetAlgorithmTag(&spki->algorithm);
 601
 602    /* copy the DER into the arena, since Quick DER returns data that points
 603       into the DER input, which may get freed by the caller */
 604    rv = SECITEM_CopyItem(arena, &newOs, &os);
 605    if ( rv == SECSuccess )
 606    switch ( tag ) {
 607      case SEC_OID_X500_RSA_ENCRYPTION:
 608      case SEC_OID_PKCS1_RSA_ENCRYPTION:
 609	pubk->keyType = rsaKey;
 610	prepare_rsa_pub_key_for_asn1(pubk);        
 611        rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
 612	if (rv == SECSuccess)
 613	    return pubk;
 614	break;
 615      case SEC_OID_ANSIX9_DSA_SIGNATURE:
 616      case SEC_OID_SDN702_DSA_SIGNATURE:
 617	pubk->keyType = dsaKey;
 618	prepare_dsa_pub_key_for_asn1(pubk);
 619	rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
 620	if (rv != SECSuccess) break;
 621
 622        rv = SECKEY_DSADecodePQG(arena, pubk,
 623                                 &spki->algorithm.parameters); 
 624
 625	if (rv == SECSuccess) return pubk;
 626	break;
 627      case SEC_OID_X942_DIFFIE_HELMAN_KEY:
 628	pubk->keyType = dhKey;
 629	prepare_dh_pub_key_for_asn1(pubk);
 630	rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
 631	if (rv != SECSuccess) break;
 632
 633        /* copy the DER into the arena, since Quick DER returns data that points
 634           into the DER input, which may get freed by the caller */
 635        rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
 636        if ( rv != SECSuccess )
 637            break;
 638
 639        rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
 640                                 &newParms); 
 641
 642	if (rv == SECSuccess) return pubk;
 643	break;
 644      case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
 645	pubk->keyType = ecKey;
 646	pubk->u.ec.size = 0;
 647
 648	/* Since PKCS#11 directly takes the DER encoding of EC params
 649	 * and public value, we don't need any decoding here.
 650	 */
 651        rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams, 
 652	    &spki->algorithm.parameters);
 653        if ( rv != SECSuccess )
 654            break;
 655        rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
 656	if (rv == SECSuccess) return pubk;
 657	break;
 658
 659      default:
 660	PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
 661	rv = SECFailure;
 662	break;
 663    }
 664
 665    SECKEY_DestroyPublicKey (pubk);
 666    return NULL;
 667}
 668
 669
 670/* required for JSS */
 671SECKEYPublicKey *
 672SECKEY_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
 673{
 674    return seckey_ExtractPublicKey(spki);
 675}
 676
 677SECKEYPublicKey *
 678CERT_ExtractPublicKey(CERTCertificate *cert)
 679{
 680    SECStatus rv;
 681
 682    if (!cert) {
 683        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 684	return NULL;
 685    }
 686    rv = SECKEY_UpdateCertPQG(cert);
 687    if (rv != SECSuccess) return NULL;
 688
 689    return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
 690}
 691
 692int
 693SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
 694{
 695    SECOidTag tag;
 696    SECItem oid = { siBuffer, NULL, 0};
 697	
 698    /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
 699     * followed by the length of the curve oid and the curve oid.
 700     */
 701    oid.len = encodedParams->data[1];
 702    oid.data = encodedParams->data + 2;
 703    if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
 704	return 0;
 705
 706    switch (tag) {
 707    case SEC_OID_SECG_EC_SECP112R1:
 708    case SEC_OID_SECG_EC_SECP112R2:
 709        return 112;
 710
 711    case SEC_OID_SECG_EC_SECT113R1:
 712    case SEC_OID_SECG_EC_SECT113R2:
 713	return 113;
 714
 715    case SEC_OID_SECG_EC_SECP128R1:
 716    case SEC_OID_SECG_EC_SECP128R2:
 717	return 128;
 718
 719    case SEC_OID_SECG_EC_SECT131R1:
 720    case SEC_OID_SECG_EC_SECT131R2:
 721	return 131;
 722
 723    case SEC_OID_SECG_EC_SECP160K1:
 724    case SEC_OID_SECG_EC_SECP160R1:
 725    case SEC_OID_SECG_EC_SECP160R2:
 726	return 160;
 727
 728    case SEC_OID_SECG_EC_SECT163K1:
 729    case SEC_OID_SECG_EC_SECT163R1:
 730    case SEC_OID_SECG_EC_SECT163R2:
 731    case SEC_OID_ANSIX962_EC_C2PNB163V1:
 732    case SEC_OID_ANSIX962_EC_C2PNB163V2:
 733    case SEC_OID_ANSIX962_EC_C2PNB163V3:
 734	return 163;
 735
 736    case SEC_OID_ANSIX962_EC_C2PNB176V1:
 737	return 176;
 738
 739    case SEC_OID_ANSIX962_EC_C2TNB191V1:
 740    case SEC_OID_ANSIX962_EC_C2TNB191V2:
 741    case SEC_OID_ANSIX962_EC_C2TNB191V3:
 742    case SEC_OID_ANSIX962_EC_C2ONB191V4:
 743    case SEC_OID_ANSIX962_EC_C2ONB191V5:
 744	return 191;
 745
 746    case SEC_OID_SECG_EC_SECP192K1:
 747    case SEC_OID_ANSIX962_EC_PRIME192V1:
 748    case SEC_OID_ANSIX962_EC_PRIME192V2:
 749    case SEC_OID_ANSIX962_EC_PRIME192V3:
 750	return 192;
 751
 752    case SEC_OID_SECG_EC_SECT193R1:
 753    case SEC_OID_SECG_EC_SECT193R2:
 754	return 193;
 755
 756    case SEC_OID_ANSIX962_EC_C2PNB208W1:
 757	return 208;
 758
 759    case SEC_OID_SECG_EC_SECP224K1:
 760    case SEC_OID_SECG_EC_SECP224R1:
 761	return 224;
 762
 763    case SEC_OID_SECG_EC_SECT233K1:
 764    case SEC_OID_SECG_EC_SECT233R1:
 765	return 233;
 766
 767    case SEC_OID_SECG_EC_SECT239K1:
 768    case SEC_OID_ANSIX962_EC_C2TNB239V1:
 769    case SEC_OID_ANSIX962_EC_C2TNB239V2:
 770    case SEC_OID_ANSIX962_EC_C2TNB239V3:
 771    case SEC_OID_ANSIX962_EC_C2ONB239V4:
 772    case SEC_OID_ANSIX962_EC_C2ONB239V5:
 773    case SEC_OID_ANSIX962_EC_PRIME239V1:
 774    case SEC_OID_ANSIX962_EC_PRIME239V2:
 775    case SEC_OID_ANSIX962_EC_PRIME239V3:
 776	return 239;
 777
 778    case SEC_OID_SECG_EC_SECP256K1:
 779    case SEC_OID_ANSIX962_EC_PRIME256V1:
 780	return 256;
 781
 782    case SEC_OID_ANSIX962_EC_C2PNB272W1:
 783	return 272;
 784
 785    case SEC_OID_SECG_EC_SECT283K1:
 786    case SEC_OID_SECG_EC_SECT283R1:
 787	return 283;
 788
 789    case SEC_OID_ANSIX962_EC_C2PNB304W1:
 790	return 304;
 791
 792    case SEC_OID_ANSIX962_EC_C2TNB359V1:
 793	return 359;
 794
 795    case SEC_OID_ANSIX962_EC_C2PNB368W1:
 796	return 368;
 797
 798    case SEC_OID_SECG_EC_SECP384R1:
 799	return 384;
 800
 801    case SEC_OID_SECG_EC_SECT409K1:
 802    case SEC_OID_SECG_EC_SECT409R1:
 803	return 409;
 804
 805    case SEC_OID_ANSIX962_EC_C2TNB431R1:
 806	return 431;
 807
 808    case SEC_OID_SECG_EC_SECP521R1:
 809	return 521;
 810
 811    case SEC_OID_SECG_EC_SECT571K1:
 812    case SEC_OID_SECG_EC_SECT571R1:
 813	return 571;
 814
 815    default:
 816	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
 817	return 0;
 818    }
 819}
 820
 821int
 822SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
 823{
 824    SECOidTag tag;
 825    SECItem oid = { siBuffer, NULL, 0};
 826	
 827    /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
 828     * followed by the length of the curve oid and the curve oid.
 829     */
 830    oid.len = encodedParams->data[1];
 831    oid.data = encodedParams->data + 2;
 832    if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
 833	return 0;
 834
 835    switch (tag) {
 836    case SEC_OID_SECG_EC_SECP112R1:
 837        return 112;
 838    case SEC_OID_SECG_EC_SECP112R2:
 839        return 110;
 840
 841    case SEC_OID_SECG_EC_SECT113R1:
 842    case SEC_OID_SECG_EC_SECT113R2:
 843	return 113;
 844
 845    case SEC_OID_SECG_EC_SECP128R1:
 846	return 128;
 847    case SEC_OID_SECG_EC_SECP128R2:
 848	return 126;
 849
 850    case SEC_OID_SECG_EC_SECT131R1:
 851    case SEC_OID_SECG_EC_SECT131R2:
 852	return 131;
 853
 854    case SEC_OID_SECG_EC_SECP160K1:
 855    case SEC_OID_SECG_EC_SECP160R1:
 856    case SEC_OID_SECG_EC_SECP160R2:
 857	return 161;
 858
 859    case SEC_OID_SECG_EC_SECT163K1:
 860	return 163;
 861    case SEC_OID_SECG_EC_SECT163R1:
 862	return 162;
 863    case SEC_OID_SECG_EC_SECT163R2:
 864    case SEC_OID_ANSIX962_EC_C2PNB163V1:
 865	return 163;
 866    case SEC_OID_ANSIX962_EC_C2PNB163V2:
 867    case SEC_OID_ANSIX962_EC_C2PNB163V3:
 868	return 162;
 869
 870    case SEC_OID_ANSIX962_EC_C2PNB176V1:
 871	return 161;
 872
 873    case SEC_OID_ANSIX962_EC_C2TNB191V1:
 874	return 191;
 875    case SEC_OID_ANSIX962_EC_C2TNB191V2:
 876	return 190;
 877    case SEC_OID_ANSIX962_EC_C2TNB191V3:
 878	return 189;
 879    case SEC_OID_ANSIX962_EC_C2ONB191V4:
 880	return 191;
 881    case SEC_OID_ANSIX962_EC_C2ONB191V5:
 882	return 188;
 883
 884    case SEC_OID_SECG_EC_SECP192K1:
 885    case SEC_OID_ANSIX962_EC_PRIME192V1:
 886    case SEC_OID_ANSIX962_EC_PRIME192V2:
 887    case SEC_OID_ANSIX962_EC_PRIME192V3:
 888	return 192;
 889
 890    case SEC_OID_SECG_EC_SECT193R1:
 891    case SEC_OID_SECG_EC_SECT193R2:
 892	return 193;
 893
 894    case SEC_OID_ANSIX962_EC_C2PNB208W1:
 895	return 193;
 896
 897    case SEC_OID_SECG_EC_SECP224K1:
 898	return 225;
 899    case SEC_OID_SECG_EC_SECP224R1:
 900	return 224;
 901
 902    case SEC_OID_SECG_EC_SECT233K1:
 903	return 232;
 904    case SEC_OID_SECG_EC_SECT233R1:
 905	return 233;
 906
 907    case SEC_OID_SECG_EC_SECT239K1:
 908    case SEC_OID_ANSIX962_EC_C2TNB239V1:
 909	return 238;
 910    case SEC_OID_ANSIX962_EC_C2TNB239V2:
 911	return 237;
 912    case SEC_OID_ANSIX962_EC_C2TNB239V3:
 913	return 236;
 914    case SEC_OID_ANSIX962_EC_C2ONB239V4:
 915	return 238;
 916    case SEC_OID_ANSIX962_EC_C2ONB239V5:
 917	return 237;
 918    case SEC_OID_ANSIX962_EC_PRIME239V1:
 919    case SEC_OID_ANSIX962_EC_PRIME239V2:
 920    case SEC_OID_ANSIX962_EC_PRIME239V3:
 921	return 239;
 922
 923    case SEC_OID_SECG_EC_SECP256K1:
 924    case SEC_OID_ANSIX962_EC_PRIME256V1:
 925	return 256;
 926
 927    case SEC_OID_ANSIX962_EC_C2PNB272W1:
 928	return 257;
 929
 930    case SEC_OID_SECG_EC_SECT283K1:
 931	return 281;
 932    case SEC_OID_SECG_EC_SECT283R1:
 933	return 282;
 934
 935    case SEC_OID_ANSIX962_EC_C2PNB304W1:
 936	return 289;
 937
 938    case SEC_OID_ANSIX962_EC_C2TNB359V1:
 939	return 353;
 940
 941    case SEC_OID_ANSIX962_EC_C2PNB368W1:
 942	return 353;
 943
 944    case SEC_OID_SECG_EC_SECP384R1:
 945	return 384;
 946
 947    case SEC_OID_SECG_EC_SECT409K1:
 948	return 407;
 949    case SEC_OID_SECG_EC_SECT409R1:
 950	return 409;
 951
 952    case SEC_OID_ANSIX962_EC_C2TNB431R1:
 953	return 418;
 954
 955    case SEC_OID_SECG_EC_SECP521R1:
 956	return 521;
 957
 958    case SEC_OID_SECG_EC_SECT571K1:
 959    case SEC_OID_SECG_EC_SECT571R1:
 960	return 570;
 961
 962    default:
 963	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
 964	return 0;
 965    }
 966}
 967
 968/* returns key strength in bytes (not bits) */
 969unsigned
 970SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
 971{
 972    unsigned char b0;
 973    unsigned size;
 974
 975    /* interpret modulus length as key strength */
 976    if (!pubk)
 977    	goto loser;
 978    switch (pubk->keyType) {
 979    case rsaKey:
 980	if (!pubk->u.rsa.modulus.data) break;
 981    	b0 = pubk->u.rsa.modulus.data[0];
 982    	return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
 983    case dsaKey:
 984	if (!pubk->u.dsa.publicValue.data) break;
 985    	b0 = pubk->u.dsa.publicValue.data[0];
 986    	return b0 ? pubk->u.dsa.publicValue.len :
 987	    pubk->u.dsa.publicValue.len - 1;
 988    case dhKey:
 989	if (!pubk->u.dh.publicValue.data) break;
 990    	b0 = pubk->u.dh.publicValue.data[0];
 991    	return b0 ? pubk->u.dh.publicValue.len :
 992	    pubk->u.dh.publicValue.len - 1;
 993    case ecKey:
 994	/* Get the key size in bits and adjust */
 995	size =	SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
 996	return (size + 7)/8;
 997    default:
 998	break;
 999    }
1000loser:
1001    PORT_SetError(SEC_ERROR_INVALID_KEY);
1002    return 0;
1003}
1004
1005/* returns key strength in bits */
1006unsigned
1007SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
1008{
1009    unsigned size;
1010    switch (pubk->keyType) {
1011    case rsaKey:
1012    case dsaKey:
1013    case dhKey:
1014	return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
1015    case ecKey:
1016	size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
1017	return size;
1018    default:
1019	break;
1020    }
1021    PORT_SetError(SEC_ERROR_INVALID_KEY);
1022    return 0;
1023}
1024
1025/* returns signature length in bytes (not bits) */
1026unsigned
1027SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
1028{
1029    unsigned char b0;
1030    unsigned size;
1031
1032    switch (pubk->keyType) {
1033    case rsaKey:
1034    	b0 = pubk->u.rsa.modulus.data[0];
1035    	return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
1036    case dsaKey:
1037    	return DSA_SIGNATURE_LEN;
1038    case ecKey:
1039	/* Get the base point order length in bits and adjust */
1040	size =	SECKEY_ECParamsToBasePointOrderLen(
1041		&pubk->u.ec.DEREncodedParams);
1042	return ((size + 7)/8) * 2;
1043    default:
1044	break;
1045    }
1046    PORT_SetError(SEC_ERROR_INVALID_KEY);
1047    return 0;
1048}
1049
1050SECKEYPrivateKey *
1051SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
1052{
1053    SECKEYPrivateKey *copyk;
1054    PRArenaPool *arena;
1055    
1056    if (!privk || !privk->pkcs11Slot) {
1057	PORT_SetError(SEC_ERROR_INVALID_ARGS);
1058	return NULL;
1059    }
1060    
1061    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1062    if (arena == NULL) {
1063	return NULL;
1064    }
1065
1066    copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey));
1067    if (copyk) {
1068	copyk->arena = arena;
1069	copyk->keyType = privk->keyType;
1070
1071	/* copy the PKCS #11 parameters */
1072	copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
1073	/* if the key we're referencing was a temparary key we have just
1074	 * created, that we want to go away when we're through, we need
1075	 * to make a copy of it */
1076	if (privk->pkcs11IsTemp) {
1077	    copyk->pkcs11ID = 
1078			PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID);
1079	    if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail;
1080	} else {
1081	    copyk->pkcs11ID = privk->pkcs11ID;
1082	}
1083	copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
1084	copyk->wincx = privk->wincx;
1085	copyk->staticflags = privk->staticflags;
1086	return copyk;
1087    } else {
1088	PORT_SetError (SEC_ERROR_NO_MEMORY);
1089    }
1090
1091fail:
1092    PORT_FreeArena (arena, PR_FALSE);
1093    return NULL;
1094}
1095
1096SECKEYPublicKey *
1097SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
1098{
1099    SECKEYPublicKey *copyk;
1100    PRArenaPool *arena;
1101    SECStatus rv = SECSuccess;
1102
1103    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1104    if (arena == NULL) {
1105	PORT_SetError (SEC_ERROR_NO_MEMORY);
1106	return NULL;
1107    }
1108
1109    copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
1110    if (!copyk) {
1111        PORT_FreeArena (arena, PR_FALSE);
1112        PORT_SetError (SEC_ERROR_NO_MEMORY);
1113        return NULL;
1114    }
1115
1116    copyk->arena = arena;
1117    copyk->keyType = pubk->keyType;
1118    if (pubk->pkcs11Slot && 
1119        PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
1120        copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
1121        copyk->pkcs11ID = pubk->pkcs11ID;
1122    } else {
1123        copyk->pkcs11Slot = NULL;	/* go get own reference */
1124        copyk->pkcs11ID = CK_INVALID_HANDLE;
1125    }
1126    switch (pubk->keyType) {
1127      case rsaKey:
1128          rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
1129                                &pubk->u.rsa.modulus);
1130          if (rv == SECSuccess) {
1131              rv = SECITEM_CopyItem (arena, &copyk->u.rsa.publicExponent,
1132                                     &pubk->u.rsa.publicExponent);
1133              if (rv == SECSuccess)
1134                  return copyk;
1135          }
1136          break;
1137      case dsaKey:
1138          rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
1139                                &pubk->u.dsa.publicValue);
1140          if (rv != SECSuccess) break;
1141          rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
1142                                &pubk->u.dsa.params.prime);
1143          if (rv != SECSuccess) break;
1144          rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
1145                                &pubk->u.dsa.params.subPrime);
1146          if (rv != SECSuccess) break;
1147          rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
1148                                &pubk->u.dsa.params.base);
1149          break;
1150      case dhKey:
1151          rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
1152          if (rv != SECSuccess) break;
1153          rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
1154          if (rv != SECSuccess) break;
1155          rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue, 
1156                                &pubk->u.dh.publicValue);
1157          break;
1158      case ecKey:
1159          copyk->u.ec.size = pubk->u.ec.size;
1160          rv = SECITEM_CopyItem(arena,&copyk->u.ec.DEREncodedParams,
1161                                &pubk->u.ec.DEREncodedParams);
1162          if (rv != SECSuccess) break;
1163          rv = SECITEM_CopyItem(arena,&copyk->u.ec.publicValue,
1164                                &pubk->u.ec.publicValue);
1165          break;
1166      case nullKey:
1167          return copyk;
1168      default:
1169          PORT_SetError(SEC_ERROR_INVALID_KEY);
1170          rv = SECFailure;
1171          break;
1172    }
1173    if (rv == SECSuccess)
1174        return copyk;
1175
1176    SECKEY_DestroyPublicKey (copyk);
1177    return NULL;
1178}
1179
1180
1181SECKEYPublicKey *
1182SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
1183{
1184    SECKEYPublicKey *pubk;
1185    PRArenaPool *arena;
1186    CERTCertificate *cert;
1187    SECStatus rv;
1188
1189    /*
1190     * First try to look up the cert.
1191     */
1192    cert = PK11_GetCertFromPrivateKey(privk);
1193    if (cert) {
1194	pubk = CERT_ExtractPublicKey(cert);
1195	CERT_DestroyCertificate(cert);
1196	return pubk;
1197    }
1198
1199    /* couldn't find the cert, build pub key by hand */
1200    arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1201    if (arena == NULL) {
1202	PORT_SetError (SEC_ERROR_NO_MEMORY);
1203	return NULL;
1204    }
1205    pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
1206						   sizeof (SECKEYPublicKey));
1207    if (pubk == NULL) {
1208	PORT_FreeArena(arena,PR_FALSE);
1209	return NULL;
1210    }
1211    pubk->keyType = privk->keyType;
1212    pubk->pkcs11Slot = NULL;
1213    pubk->pkcs11ID = CK_INVALID_HANDLE;
1214    pubk->arena = arena;
1215
1216    switch(privk->keyType) {
1217      case nullKey:
1218      case dhKey:
1219      case dsaKey:
1220	/* Nothing to query, if the cert isn't there, we're done -- no way
1221	 * to get the public key */
1222	break;
1223      case rsaKey:
1224	rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
1225				CKA_MODULUS,arena,&pubk->u.rsa.modulus);
1226	if (rv != SECSuccess)  break;
1227	rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
1228			CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent);
1229	if (rv != SECSuccess)  break;
1230	return pubk;
1231	break;
1232    default:
1233	break;
1234    }
1235
1236    PORT_FreeArena (arena, PR_FALSE);
1237    return NULL;
1238}
1239
1240CERTSubjectPublicKeyInfo *
1241SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
1242{
1243    CERTSubjectPublicKeyInfo *spki;
1244    PRArenaPool *arena;
1245    SECItem params = { siBuffer, NULL, 0 };
1246
1247    if (!pubk) {
1248        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1249        return NULL;
1250    }
1251
1252    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1253    if (arena == NULL) {
1254	PORT_SetError(SEC_ERROR_NO_MEMORY);
1255	return NULL;
1256    }
1257
1258    spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki));
1259    if (spki != NULL) {
1260	SECStatus rv;
1261	SECItem *rv_item;
1262	
1263	spki->arena = arena;
1264	switch(pubk->keyType) {
1265	  case rsaKey:
1266	    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
1267				     SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
1268	    if (rv == SECSuccess) {
1269		/*
1270		 * DER encode the public key into the subjectPublicKeyInfo.
1271		 */
1272		prepare_rsa_pub_key_for_asn1(pubk);
1273		rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
1274					     pubk, SECKEY_RSAPublicKeyTemplate);
1275		if (rv_item != NULL) {
1276		    /*
1277		     * The stored value is supposed to be a BIT_STRING,
1278		     * so convert the length.
1279		     */
1280		    spki->subjectPublicKey.len <<= 3;
1281		    /*
1282		     * We got a good one; return it.
1283		     */
1284		    return spki;
1285		}
1286	    }
1287	    break;
1288	  case dsaKey:
1289	    /* DER encode the params. */
1290	    prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
1291	    rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
1292					 SECKEY_PQGParamsTemplate);
1293	    if (rv_item != NULL) {
1294		rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
1295					   SEC_OID_ANSIX9_DSA_SIGNATURE,
1296					   &params);
1297		if (rv == SECSuccess) {
1298		    /*
1299		     * DER encode the public key into the subjectPublicKeyInfo.
1300		     */
1301		    prepare_dsa_pub_key_for_asn1(pubk);
1302		    rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
1303						 pubk,
1304						 SECKEY_DSAPublicKeyTemplate);
1305		    if (rv_item != NULL) {
1306			/*
1307			 * The stored value is supposed to be a BIT_STRING,
1308			 * so convert the length.
1309			 */
1310			spki->subjectPublicKey.len <<= 3;
1311			/*
1312			 * We got a good one; return it.
1313			 */
1314			return spki;
1315		    }
1316		}
1317	    }
1318	    SECITEM_FreeItem(&params, PR_FALSE);
1319	    break;
1320	  case ecKey:
1321	    rv = SECITEM_CopyItem(arena, &params, 
1322				  &pubk->u.ec.DEREncodedParams);
1323	    if (rv != SECSuccess) break;
1324
1325	    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
1326				       SEC_OID_ANSIX962_EC_PUBLIC_KEY,
1327				       &params);
1328	    if (rv != SECSuccess) break;
1329
1330	    rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
1331				  &pubk->u.ec.publicValue);
1332
1333	    if (rv == SECSuccess) {
1334	        /*
1335		 * The stored value is supposed to be a BIT_STRING,
1336		 * so convert the length.
1337		 */
1338	        spki->subjectPublicKey.len <<= 3;
1339		/*
1340		 * We got a good one; return it.
1341		 */
1342		return spki;
1343	    }
1344	    break;
1345	  case dhKey: /* later... */
1346
1347	    break;
1348	  default:
1349	    break;
1350	}
1351    } else {
1352	PORT_SetError(SEC_ERROR_NO_MEMORY);
1353    }
1354
1355    PORT_FreeArena(arena, PR_FALSE);
1356    return NULL;
1357}
1358
1359void
1360SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
1361{
1362    if (spki && spki->arena) {
1363	PORT_FreeArena(spki->arena, PR_FALSE);
1364    }
1365}
1366
1367/*
1368 * this only works for RSA keys... need to do something
1369 * similiar to CERT_ExtractPublicKey for other key times.
1370 */
1371SECKEYPublicKey *
1372SECKEY_DecodeDERPublicKey(SECItem *pubkder)
1373{
1374    PRArenaPool *arena;
1375    SECKEYPublicKey *pubk;
1376    SECStatus rv;
1377    SECItem newPubkder;
1378
1379    arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1380    if (arena == NULL) {
1381	PORT_SetError (SEC_ERROR_NO_MEMORY);
1382	return NULL;
1383    }
1384
1385    pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
1386    if (pubk != NULL) {
1387	pubk->arena = arena;
1388	pubk->pkcs11Slot = NULL;
1389	pubk->pkcs11ID = 0;
1390	prepare_rsa_pub_key_for_asn1(pubk);
1391        /* copy the DER into the arena, since Quick DER returns data that points
1392           into the DER input, which may get freed by the caller */
1393        rv = SECITEM_CopyItem(arena, &newPubkder, pubkder);
1394        if ( rv == SECSuccess ) {
1395	    rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,
1396				&newPubkder);
1397        }
1398	if (rv == SECSuccess)
1399	    return pubk;
1400	SECKEY_DestroyPublicKey (pubk);
1401    } else {
1402	PORT_SetError (SEC_ERROR_NO_MEMORY);
1403    }
1404
1405    PORT_FreeArena (arena, PR_FALSE);
1406    return NULL;
1407}
1408
1409/*
1410 * Decode a base64 ascii encoded DER encoded public key.
1411 */
1412SECKEYPublicKey *
1413SECKEY_ConvertAndDecodePublicKey(char *pubkstr)
1414{
1415    SECKEYPublicKey *pubk;
1416    SECStatus rv;
1417    SECItem der;
1418
1419    rv = ATOB_ConvertAsciiToItem (&der, pubkstr);
1420    if (rv != SECSuccess)
1421	return NULL;
1422
1423    pubk = SECKEY_DecodeDERPublicKey (&der);
1424
1425    PORT_Free (der.data);
1426    return pubk;
1427}
1428
1429SECItem *
1430SECKEY_EncodeDERSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
1431{
1432    CERTSubjectPublicKeyInfo *spki=NULL;
1433    SECItem *spkiDER=NULL;
1434
1435    /* get the subjectpublickeyinfo */
1436    spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
1437    if( spki == NULL ) {
1438	goto finish;
1439    }
1440
1441    /* DER-encode the subjectpublickeyinfo */
1442    spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
1443					CERT_SubjectPublicKeyInfoTemplate);
1444
1445    SECKEY_DestroySubjectPublicKeyInfo(spki);
1446
1447finish:
1448    return spkiDER;
1449}
1450
1451
1452CERTSubjectPublicKeyInfo *
1453SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider)
1454{
1455    PRArenaPool *arena;
1456    CERTSubjectPublicKeyInfo *spki;
1457    SECStatus rv;
1458    SECItem newSpkider;
1459
1460    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1461    if (arena == NULL) {
1462	PORT_SetError(SEC_ERROR_NO_MEMORY);
1463	return NULL;
1464    }
1465
1466    spki = (CERTSubjectPublicKeyInfo *)
1467		PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo));
1468    if (spki != NULL) {
1469	spki->arena = arena;
1470
1471        /* copy the DER into the arena, since Quick DER returns data that points
1472           into the DER input, which may get freed by the caller */
1473        rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
1474        if ( rv == SECSuccess ) {
1475            rv = SEC_QuickDERDecodeItem(arena,spki,
1476				    CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
1477        }
1478	if (rv == SECSuccess)
1479	    return spki;
1480    } else {
1481	PORT_SetError(SEC_ERROR_NO_MEMORY);
1482    }
1483
1484    PORT_FreeArena(arena, PR_FALSE);
1485    return NULL;
1486}
1487
1488/*
1489 * Decode a base64 ascii encoded DER encoded subject public key info.
1490 */
1491CERTSubjectPublicKeyInfo *
1492SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr)
1493{
1494    CERTSubjectPublicKeyInfo *spki;
1495    SECStatus rv;
1496    SECItem der;
1497
1498    rv = ATOB_ConvertAsciiToItem(&der, spkistr);
1499    if (rv != SECSuccess)
1500	return NULL;
1501
1502    spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
1503
1504    PORT_Free(der.data);
1505    return spki;
1506}
1507
1508/*
1509 * Decode a base64 ascii encoded DER encoded public key and challenge
1510 * Verify digital signature and make sure challenge matches
1511 */
1512CERTSubjectPublicKeyInfo *
1513SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
1514								void *wincx)
1515{
1516    CERTSubjectPublicKeyInfo *spki = NULL;
1517    CERTPublicKeyAndChallenge pkac;
1518    SECStatus rv;
1519    SECItem signedItem;
1520    PRArenaPool *arena = NULL;
1521    CERTSignedData sd;
1522    SECItem sig;
1523    SECKEYPublicKey *pubKey = NULL;
1524    unsigned int len;
1525    
1526    signedItem.data = NULL;
1527    
1528    /* convert the base64 encoded data to binary */
1529    rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
1530    if (rv != SECSuccess) {
1531	goto loser;
1532    }
1533
1534    /* create an arena */
1535    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1536    if (arena == NULL) {
1537	goto loser;
1538    }
1539
1540    /* decode the outer wrapping of signed data */
1541    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
1542    rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem );
1543    if ( rv ) {
1544	goto loser;
1545    }
1546
1547    /* decode the public key and challenge wrapper */
1548    PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
1549    rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, 
1550			    &sd.data);
1551    if ( rv ) {
1552	goto loser;
1553    }
1554
1555    /* decode the subject public key info */
1556    spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
1557    if ( spki == NULL ) {
1558	goto loser;
1559    }
1560    
1561    /* get the public key */
1562    pubKey = seckey_ExtractPublicKey(spki);
1563    if ( pubKey == NULL ) {
1564	goto loser;
1565    }
1566
1567    /* check the signature */
1568    sig = sd.signature;
1569    DER_ConvertBitString(&sig);
1570    rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
1571			&(sd.signatureAlgorithm), NULL, wincx);
1572    if ( rv != SECSuccess ) {
1573	goto loser;
1574    }
1575    
1576    /* check the challenge */
1577    if ( challenge ) {
1578	len = PORT_Strlen(challenge);
1579	/* length is right */
1580	if ( len != pkac.challenge.len ) {
1581	    goto loser;
1582	}
1583	/* actual data is right */
1584	if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) {
1585	    goto loser;
1586	}
1587    }
1588    goto done;
1589
1590loser:
1591    /* make sure that we return null if we got an error */
1592    if ( spki ) {
1593	SECKEY_DestroySubjectPublicKeyInfo(spki);
1594    }
1595    spki = NULL;
1596    
1597done:
1598    if ( signedItem.data ) {
1599	PORT_Free(signedItem.data);
1600    }
1601    if ( arena ) {
1602	PORT_FreeArena(arena, PR_FALSE);
1603    }
1604    if ( pubKey ) {
1605	SECKEY_DestroyPublicKey(pubKey);
1606    }
1607    
1608    return spki;
1609}
1610
1611void
1612SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
1613			     PRBool freeit)
1614{
1615    PRArenaPool *poolp;
1616
1617    if(pvk != NULL) {
1618	if(pvk->arena) {
1619	    poolp = pvk->arena;
1620	    /* zero structure since PORT_FreeArena does not support
1621	     * this yet.
1622	     */
1623	    PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
1624	    PORT_Memset((char *)pvk, 0, sizeof(*pvk));
1625	    if(freeit == PR_TRUE) {
1626		PORT_FreeArena(poolp, PR_TRUE);
1627	    } else {
1628		pvk->arena = poolp;
1629	    }
1630	} else {
1631	    SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
1632	    SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
1633	    SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
1634	    PORT_Memset((char *)pvk, 0, sizeof(*pvk));
1635	    if(freeit == PR_TRUE) {
1636		PORT_Free(pvk);
1637	    }
1638	}
1639    }
1640}
1641
1642void
1643SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
1644				      PRBool freeit)
1645{
1646    PRArenaPool *poolp;
1647
1648    if(epki != NULL) {
1649	if(epki->arena) {
1650	    poolp = epki->arena;
1651	    /* zero structure since PORT_FreeArena does not support
1652	     * this yet.
1653	     */
1654	    PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
1655	    PORT_Memset((char *)epki, 0, sizeof(*epki));
1656	    if(freeit == PR_TRUE) {
1657		PORT_FreeArena(poolp, PR_TRUE);
1658	    } else {
1659		epki->arena = poolp;
1660	    }
1661	} else {
1662	    SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
1663	    SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
1664	    PORT_Memset((char *)epki, 0, sizeof(*epki));
1665	    if(freeit == PR_TRUE) {
1666		PORT_Free(epki);
1667	    }
1668	}
1669    }
1670}
1671
1672SECStatus
1673SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp,
1674			  SECKEYPrivateKeyInfo *to,
1675			  SECKEYPrivateKeyInfo *from)
1676{
1677    SECStatus rv = SECFailure;
1678
1679    if((to == NULL) || (from == NULL)) {
1680	return SECFailure;
1681    }
1682
1683    rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
1684    if(rv != SECSuccess) {
1685	return SECFailure;
1686    }
1687    rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
1688    if(rv != SECSuccess) {
1689	return SECFailure;
1690    }
1691    rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
1692
1693    return rv;
1694}
1695
1696SECStatus
1697SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp, 
1698				   SECKEYEncryptedPrivateKeyInfo *to,
1699				   SECKEYEncryptedPrivateKeyInfo *from)
1700{
1701    SECStatus rv = SECFailure;
1702
1703    if((to == NULL) || (from == NULL)) {
1704	return SECFailure;
1705    }
1706
1707    rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
1708    if(rv != SECSuccess) {
1709	return SECFailure;
1710    }
1711    rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
1712
1713    return rv;
1714}
1715
1716KeyType
1717SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey)
1718{
1719   return privKey->keyType;
1720}
1721
1722KeyType
1723SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey)
1724{
1725   return pubKey->keyType;
1726}
1727
1728SECKEYPublicKey*
1729SECKEY_ImportDERPublicKey(SECItem *derKey, CK_KEY_TYPE type)
1730{
1731    SECKEYPublicKey *pubk = NULL;
1732    SECStatus rv = SECFailure;
1733    SECItem newDerKey;
1734    PRArenaPool *arena = NULL;
1735
1736    if (!derKey) {
1737        return NULL;
1738    } 
1739
1740    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1741    if (arena == NULL) {
1742	PORT_SetError(SEC_ERROR_NO_MEMORY);
1743        goto finish;
1744    }
1745
1746    pubk = PORT_ArenaZNew(arena, SECKEYPublicKey);
1747    if (pubk == NULL) {
1748        goto finish;
1749    }
1750    pubk->arena = arena;
1751
1752    rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
1753    if (SECSuccess != rv) {
1754        goto finish;
1755    }
1756
1757    pubk->pkcs11Slot = NULL;
1758    pubk->pkcs11ID = CK_INVALID_HANDLE;
1759
1760    switch( type ) {
1761      case CKK_RSA:
1762	prepare_rsa_pub_key_for_asn1(pubk);
1763        rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
1764        pubk->keyType = rsaKey;
1765        break;
1766      case CKK_DSA:
1767	prepare_dsa_pub_key_for_asn1(pubk);
1768        rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
1769        pubk->keyType = dsaKey;
1770        break;
1771      case CKK_DH:
1772	prepare_dh_pub_key_for_asn1(pubk);
1773        rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
1774        pubk->keyType = dhKey;
1775        break;
1776      default:
1777        rv = SECFailure;
1778        break;
1779    }
1780
1781finish:
1782    if (rv != SECSuccess) {
1783        if (arena != NULL) {
1784            PORT_FreeArena(arena, PR_TRUE);
1785        }
1786        pubk = NULL;
1787    }
1788    return pubk;
1789}
1790
1791SECKEYPrivateKeyList*
1792SECKEY_NewPrivateKeyList(void)
1793{
1794    PRArenaPool *arena = NULL;
1795    SECKEYPrivateKeyList *ret = NULL;
1796
1797    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1798    if ( arena == NULL ) {
1799        goto loser;
1800    }
1801
1802    ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
1803                sizeof(SECKEYP

Large files files are truncated, but you can click here to view the full file