Back to index

lightning-sunbird  0.9+nobinonly
seckey.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Dr Stephen Henson <stephen.henson@gemplus.com>
00023  *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 #include "cryptohi.h"
00039 #include "keyhi.h"
00040 #include "secoid.h"
00041 #include "secitem.h"
00042 #include "secder.h"
00043 #include "base64.h"
00044 #include "secasn1.h"
00045 #include "cert.h"
00046 #include "pk11func.h"
00047 #include "secerr.h"
00048 #include "secdig.h"
00049 #include "prtime.h"
00050 #include "ec.h"
00051 
00052 const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
00053     { SEC_ASN1_SEQUENCE,
00054          0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
00055     { SEC_ASN1_INLINE,
00056          offsetof(CERTSubjectPublicKeyInfo,algorithm),
00057          SECOID_AlgorithmIDTemplate },
00058     { SEC_ASN1_BIT_STRING,
00059          offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
00060     { 0, }
00061 };
00062 
00063 const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
00064 {
00065     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
00066     { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },
00067     { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },
00068     { 0 }
00069 };
00070 
00071 const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
00072     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
00073     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },
00074     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },
00075     { 0, }
00076 };
00077 
00078 const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
00079     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },
00080     { 0, }
00081 };
00082 
00083 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
00084     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
00085     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
00086     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
00087     { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
00088     { 0, }
00089 };
00090 
00091 const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
00092     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
00093     { 0, }
00094 };
00095 
00096 const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
00097     { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(SECKEYPublicKey) },
00098     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
00099     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
00100     /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
00101     { SEC_ASN1_SKIP_REST },
00102     { 0, }
00103 };
00104 
00105 const SEC_ASN1Template SECKEY_FortezzaParameterTemplate[] = {
00106     { SEC_ASN1_SEQUENCE,  0, NULL, sizeof(SECKEYPQGParams) },
00107     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPQGParams,prime), },
00108     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPQGParams,subPrime), },
00109     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPQGParams,base), },
00110     { 0 },
00111 };
00112  
00113 const SEC_ASN1Template SECKEY_FortezzaDiffParameterTemplate[] = {
00114     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYDiffPQGParams) },
00115     { SEC_ASN1_INLINE, offsetof(SECKEYDiffPQGParams,DiffKEAParams), 
00116                        SECKEY_FortezzaParameterTemplate},
00117     { SEC_ASN1_INLINE, offsetof(SECKEYDiffPQGParams,DiffDSAParams), 
00118                        SECKEY_FortezzaParameterTemplate},
00119     { 0 },
00120 };
00121 
00122 const SEC_ASN1Template SECKEY_FortezzaPreParamTemplate[] = {
00123     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
00124       SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(SECKEYPQGDualParams,CommParams),
00125                 SECKEY_FortezzaParameterTemplate},
00126     { 0, }
00127 };
00128 
00129 const SEC_ASN1Template SECKEY_FortezzaAltPreParamTemplate[] = {
00130     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
00131       SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(SECKEYPQGDualParams,DiffParams),
00132                 SECKEY_FortezzaDiffParameterTemplate},
00133     { 0, }
00134 };
00135 
00136 const SEC_ASN1Template SECKEY_KEAPublicKeyTemplate[] = {
00137     { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.kea.publicValue), },
00138     { 0, }
00139 };
00140 
00141 const SEC_ASN1Template SECKEY_KEAParamsTemplate[] = {
00142     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPublicKey,u.kea.params.hash), }, 
00143     { 0, }
00144 };
00145 
00146 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
00147 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
00148 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
00149 
00150 /*
00151  * See bugzilla bug 125359
00152  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
00153  * all of the templates above that en/decode into integers must be converted
00154  * from ASN.1's signed integer type.  This is done by marking either the
00155  * source or destination (encoding or decoding, respectively) type as
00156  * siUnsignedInteger.
00157  */
00158 static void
00159 prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
00160 {
00161     pubk->u.rsa.modulus.type = siUnsignedInteger;
00162     pubk->u.rsa.publicExponent.type = siUnsignedInteger;
00163 }
00164 
00165 static void
00166 prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
00167 {
00168     pubk->u.dsa.publicValue.type = siUnsignedInteger;
00169 }
00170 
00171 static void
00172 prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
00173 {
00174     params->prime.type = siUnsignedInteger;
00175     params->subPrime.type = siUnsignedInteger;
00176     params->base.type = siUnsignedInteger;
00177 }
00178 
00179 static void
00180 prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
00181 {
00182     pubk->u.dh.prime.type = siUnsignedInteger;
00183     pubk->u.dh.base.type = siUnsignedInteger;
00184     pubk->u.dh.publicValue.type = siUnsignedInteger;
00185 }
00186 
00187 static void
00188 prepare_kea_pub_key_for_asn1(SECKEYPublicKey *pubk)
00189 {
00190     pubk->u.kea.publicValue.type = siUnsignedInteger;
00191 }
00192 
00193 /* Create an RSA key pair is any slot able to do so.
00194 ** The created keys are "session" (temporary), not "token" (permanent), 
00195 ** and they are "sensitive", which makes them costly to move to another token.
00196 */
00197 SECKEYPrivateKey *
00198 SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx)
00199 {
00200     SECKEYPrivateKey *privk;
00201     PK11RSAGenParams param;
00202     PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);
00203     if (!slot) {
00204        return NULL;
00205     }
00206 
00207     param.keySizeInBits = keySizeInBits;
00208     param.pe = 65537L;
00209     
00210     privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,
00211                                    PR_FALSE, PR_TRUE, cx);
00212     PK11_FreeSlot(slot);
00213     return(privk);
00214 }
00215 
00216 /* Create a DH key pair in any slot able to do so, 
00217 ** This is a "session" (temporary), not "token" (permanent) key. 
00218 ** Because of the high probability that this key will need to be moved to
00219 ** another token, and the high cost of moving "sensitive" keys, we attempt
00220 ** to create this key pair without the "sensitive" attribute, but revert to 
00221 ** creating a "sensitive" key if necessary.
00222 */
00223 SECKEYPrivateKey *
00224 SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
00225 {
00226     SECKEYPrivateKey *privk;
00227     PK11SlotInfo *slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,cx);
00228     if (!slot) {
00229        return NULL;
00230     }
00231 
00232     privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 
00233                                  pubk, PR_FALSE, PR_FALSE, cx);
00234     if (!privk) 
00235        privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param, 
00236                                     pubk, PR_FALSE, PR_TRUE, cx);
00237 
00238     PK11_FreeSlot(slot);
00239     return(privk);
00240 }
00241 
00242 /* Create an EC key pair in any slot able to do so, 
00243 ** This is a "session" (temporary), not "token" (permanent) key. 
00244 ** Because of the high probability that this key will need to be moved to
00245 ** another token, and the high cost of moving "sensitive" keys, we attempt
00246 ** to create this key pair without the "sensitive" attribute, but revert to 
00247 ** creating a "sensitive" key if necessary.
00248 */
00249 SECKEYPrivateKey *
00250 SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
00251 {
00252     SECKEYPrivateKey *privk;
00253     PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx);
00254     if (!slot) {
00255        return NULL;
00256     }
00257 
00258     privk = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, param, 
00259                                  pubk, PR_FALSE, PR_FALSE, cx);
00260     if (!privk) 
00261        privk = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, param, 
00262                                     pubk, PR_FALSE, PR_TRUE, cx);
00263 
00264     PK11_FreeSlot(slot);
00265     return(privk);
00266 }
00267 
00268 void
00269 SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
00270 {
00271     if (privk) {
00272        if (privk->pkcs11Slot) {
00273            if (privk->pkcs11IsTemp) {
00274               PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);
00275            }
00276            PK11_FreeSlot(privk->pkcs11Slot);
00277 
00278        }
00279        if (privk->arena) {
00280            PORT_FreeArena(privk->arena, PR_TRUE);
00281        }
00282     }
00283 }
00284 
00285 void
00286 SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
00287 {
00288     if (pubk) {
00289        if (pubk->pkcs11Slot) {
00290            if (!PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
00291               PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);
00292            }
00293            PK11_FreeSlot(pubk->pkcs11Slot);
00294        }
00295        if (pubk->arena) {
00296            PORT_FreeArena(pubk->arena, PR_FALSE);
00297        }
00298     }
00299 }
00300 
00301 SECStatus
00302 SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,
00303                           CERTSubjectPublicKeyInfo *to,
00304                           CERTSubjectPublicKeyInfo *from)
00305 {
00306     SECStatus rv;
00307     SECItem spk;
00308 
00309     rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
00310     if (rv == SECSuccess) {
00311        /*
00312         * subjectPublicKey is a bit string, whose length is in bits.
00313         * Convert the length from bits to bytes for SECITEM_CopyItem.
00314         */
00315        spk = from->subjectPublicKey;
00316        DER_ConvertBitString(&spk);
00317        rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
00318        /* Set the length back to bits. */
00319        if (rv == SECSuccess) {
00320            to->subjectPublicKey.len = from->subjectPublicKey.len;
00321        }
00322     }
00323 
00324     return rv;
00325 }
00326 
00327 SECStatus
00328 SECKEY_KEASetParams(SECKEYKEAParams * params, SECKEYPublicKey * pubKey) {
00329 
00330     if (pubKey->keyType == fortezzaKey) {
00331         /* the key is a fortezza V1 public key  */
00332 
00333        /* obtain hash of pubkey->u.fortezza.params.prime.data +
00334                         pubkey->u.fortezza.params.subPrime.data +
00335                        pubkey->u.fortezza.params.base.data  */
00336 
00337        /* store hash in params->hash */
00338 
00339     } else if (pubKey->keyType == keaKey) {
00340 
00341         /* the key is a new fortezza KEA public key. */
00342         SECITEM_CopyItem(pubKey->arena, &params->hash, 
00343                         &pubKey->u.kea.params.hash );
00344 
00345     } else {
00346 
00347        /* the key has no KEA parameters */
00348        return SECFailure;
00349     }
00350     return SECSuccess;
00351 }
00352 
00353 
00354 SECStatus
00355 SECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2) 
00356 {
00357 
00358     SECStatus rv;
00359 
00360     SECKEYPublicKey *pubKey1 = 0;
00361     SECKEYPublicKey *pubKey2 = 0;
00362 
00363     SECKEYKEAParams params1;
00364     SECKEYKEAParams params2;
00365 
00366 
00367     rv = SECFailure;
00368 
00369     /* get cert1's public key */
00370     pubKey1 = CERT_ExtractPublicKey(cert1);
00371     if ( !pubKey1 ) {
00372        return(SECFailure);
00373     }
00374     
00375 
00376     /* get cert2's public key */
00377     pubKey2 = CERT_ExtractPublicKey(cert2);
00378     if ( !pubKey2 ) {
00379        return(SECFailure);
00380     }
00381 
00382     /* handle the case when both public keys are new
00383      * fortezza KEA public keys.    */
00384 
00385     if ((pubKey1->keyType == keaKey) &&
00386         (pubKey2->keyType == keaKey) ) {
00387 
00388         rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.kea.params.hash,
00389                                 &pubKey2->u.kea.params.hash);
00390        goto done;
00391     }
00392 
00393     /* handle the case when both public keys are old fortezza
00394      * public keys.              */
00395 
00396     if ((pubKey1->keyType == fortezzaKey) &&
00397         (pubKey2->keyType == fortezzaKey) ) {
00398 
00399         rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.prime,
00400                                 &pubKey2->u.fortezza.keaParams.prime);
00401 
00402        if (rv == SECEqual) {
00403            rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.subPrime,
00404                                     &pubKey2->u.fortezza.keaParams.subPrime);
00405        }
00406 
00407        if (rv == SECEqual) {
00408            rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.base,
00409                                     &pubKey2->u.fortezza.keaParams.base);
00410        }
00411        
00412        goto done;
00413     }
00414 
00415 
00416     /* handle the case when the public keys are a mixture of 
00417      * old and new.                          */
00418 
00419     rv = SECKEY_KEASetParams(&params1, pubKey1);
00420     if (rv != SECSuccess) return rv;
00421 
00422     rv = SECKEY_KEASetParams(&params2, pubKey2);
00423     if (rv != SECSuccess) return rv;
00424 
00425     rv = (SECStatus)SECITEM_CompareItem(&params1.hash, &params2.hash);
00426 
00427 done:
00428     SECKEY_DestroyPublicKey(pubKey1);
00429     SECKEY_DestroyPublicKey(pubKey2);
00430 
00431     return rv;   /* returns SECEqual if parameters are equal */
00432 
00433 }
00434 
00435 
00436 /* Procedure to update the pqg parameters for a cert's public key.
00437  * pqg parameters only need to be updated for DSA and fortezza certificates.
00438  * The procedure uses calls to itself recursively to update a certificate
00439  * issuer's pqg parameters.  Some important rules are:
00440  *    - Do nothing if the cert already has PQG parameters.
00441  *    - If the cert does not have PQG parameters, obtain them from the issuer.
00442  *    - A valid cert chain cannot have a DSA or Fortezza cert without
00443  *      pqg parameters that has a parent that is not a DSA or Fortezza cert.
00444  *    - pqg paramters are stored in two different formats: the standard
00445  *      DER encoded format and the fortezza-only wrapped format.  The params
00446  *      should be copied from issuer to subject cert without modifying the
00447  *      formats.  The public key extraction code will deal with the different
00448  *      formats at the time of extraction.  */
00449 
00450 static SECStatus
00451 seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count)
00452 {
00453     SECStatus rv, rvCompare;
00454     SECOidData *oid=NULL;
00455     int tag;
00456     CERTSubjectPublicKeyInfo * subjectSpki=NULL;
00457     CERTSubjectPublicKeyInfo * issuerSpki=NULL;
00458     CERTCertificate *issuerCert = NULL;
00459 
00460     rv = SECSuccess;
00461 
00462     /* increment cert chain length counter*/
00463     count++;
00464 
00465     /* check if cert chain length exceeds the maximum length*/
00466     if (count > CERT_MAX_CERT_CHAIN) {
00467        return SECFailure;
00468     }
00469 
00470     oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);            
00471     if (oid != NULL) {  
00472         tag = oid->offset;
00473              
00474         /* Check if cert has a DSA or Fortezza public key. If not, return
00475          * success since no PQG params need to be updated.  */
00476 
00477        if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&
00478             (tag != SEC_OID_MISSI_DSS_OLD) &&
00479              (tag != SEC_OID_MISSI_KEA_DSS) &&
00480              (tag != SEC_OID_MISSI_DSS) &&               
00481              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
00482              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
00483              (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
00484              (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
00485              (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
00486             
00487             return SECSuccess;
00488         }
00489     } else {
00490         return SECFailure;  /* return failure if oid is NULL */  
00491     }
00492 
00493     /* if cert has PQG parameters, return success */
00494 
00495     subjectSpki=&subjectCert->subjectPublicKeyInfo;
00496 
00497     if (subjectSpki->algorithm.parameters.len != 0) {
00498         return SECSuccess;
00499     }
00500 
00501     /* check if the cert is self-signed */
00502     rvCompare = (SECStatus)SECITEM_CompareItem(&subjectCert->derSubject,
00503                                 &subjectCert->derIssuer);
00504     if (rvCompare == SECEqual) {
00505       /* fail since cert is self-signed and has no pqg params. */
00506        return SECFailure;     
00507     }
00508      
00509     /* get issuer cert */
00510     issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
00511     if ( ! issuerCert ) {
00512        return SECFailure;
00513     }
00514 
00515     /* if parent is not DSA or fortezza, return failure since
00516        we don't allow this case. */
00517 
00518     oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
00519     if (oid != NULL) {  
00520         tag = oid->offset;
00521              
00522         /* Check if issuer cert has a DSA or Fortezza public key. If not,
00523          * return failure.   */
00524 
00525        if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&
00526             (tag != SEC_OID_MISSI_DSS_OLD) &&
00527              (tag != SEC_OID_MISSI_KEA_DSS) &&
00528              (tag != SEC_OID_MISSI_DSS) &&               
00529              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
00530              (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
00531              (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
00532              (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
00533              (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {            
00534             rv = SECFailure;
00535             goto loser;
00536         }
00537     } else {
00538         rv = SECFailure;  /* return failure if oid is NULL */  
00539         goto loser;
00540     }
00541 
00542 
00543     /* at this point the subject cert has no pqg parameters and the
00544      * issuer cert has a DSA or fortezza public key.  Update the issuer's
00545      * pqg parameters with a recursive call to this same function. */
00546 
00547     rv = seckey_UpdateCertPQGChain(issuerCert, count);
00548     if (rv != SECSuccess) {
00549         rv = SECFailure;
00550         goto loser;
00551     }
00552 
00553     /* ensure issuer has pqg parameters */
00554 
00555     issuerSpki=&issuerCert->subjectPublicKeyInfo;
00556     if (issuerSpki->algorithm.parameters.len == 0) {
00557         rv = SECFailure; 
00558     }
00559 
00560     /* if update was successful and pqg params present, then copy the
00561      * parameters to the subject cert's key. */
00562 
00563     if (rv == SECSuccess) {
00564         rv = SECITEM_CopyItem(subjectCert->arena,
00565                               &subjectSpki->algorithm.parameters, 
00566                            &issuerSpki->algorithm.parameters);
00567     }
00568 
00569 loser:
00570     if (issuerCert) {
00571         CERT_DestroyCertificate(issuerCert);
00572     }
00573     return rv;
00574 
00575 }
00576  
00577 
00578 SECStatus
00579 SECKEY_UpdateCertPQG(CERTCertificate * subjectCert)
00580 {
00581     if (!subjectCert) {
00582         PORT_SetError(SEC_ERROR_INVALID_ARGS);
00583        return SECFailure;
00584     }
00585     return seckey_UpdateCertPQGChain(subjectCert,0);
00586 }
00587    
00588 
00589 /* Decode the PQG parameters.  The params could be stored in two
00590  * possible formats, the old fortezza-only wrapped format or
00591  * the standard DER encoded format.   Store the decoded parameters in an
00592  * old fortezza cert data structure */
00593  
00594 SECStatus
00595 SECKEY_FortezzaDecodePQGtoOld(PRArenaPool *arena, SECKEYPublicKey *pubk,
00596                               SECItem *params) {
00597     SECStatus rv;
00598     SECKEYPQGDualParams dual_params;
00599     SECItem newparams;
00600 
00601     PORT_Assert(arena);
00602 
00603     if (params == NULL) return SECFailure; 
00604     
00605     if (params->data == NULL) return SECFailure;
00606 
00607     /* make a copy of the data into the arena so QuickDER output is valid */
00608     rv = SECITEM_CopyItem(arena, &newparams, params);
00609 
00610     /* Check if params use the standard format.
00611      * The value 0xa1 will appear in the first byte of the parameter data
00612      * if the PQG parameters are not using the standard format. This
00613      * code should be changed to use a better method to detect non-standard
00614      * parameters.    */
00615 
00616     if ((newparams.data[0] != 0xa1) &&
00617         (newparams.data[0] != 0xa0)) {
00618 
00619         if (SECSuccess == rv) {
00620             /* PQG params are in the standard format */
00621 
00622            /* Store DSA PQG parameters */
00623            prepare_pqg_params_for_asn1(&pubk->u.fortezza.params);
00624             rv = SEC_QuickDERDecodeItem(arena, &pubk->u.fortezza.params,
00625                               SECKEY_PQGParamsTemplate,
00626                               &newparams);
00627         }
00628 
00629        if (SECSuccess == rv) {
00630 
00631            /* Copy the DSA PQG parameters to the KEA PQG parameters. */
00632            rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
00633                                   &pubk->u.fortezza.params.prime);
00634         }
00635         if (SECSuccess == rv) {
00636             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
00637                                   &pubk->u.fortezza.params.subPrime);
00638         }
00639         if (SECSuccess == rv) {
00640             rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
00641                                   &pubk->u.fortezza.params.base);
00642         }
00643     } else {
00644 
00645        dual_params.CommParams.prime.len = 0;
00646         dual_params.CommParams.subPrime.len = 0;
00647        dual_params.CommParams.base.len = 0;
00648        dual_params.DiffParams.DiffDSAParams.prime.len = 0;
00649         dual_params.DiffParams.DiffDSAParams.subPrime.len = 0;
00650        dual_params.DiffParams.DiffDSAParams.base.len = 0;
00651 
00652         /* else the old fortezza-only wrapped format is used. */
00653 
00654         if (SECSuccess == rv) {
00655            if (newparams.data[0] == 0xa1) {
00656                 rv = SEC_QuickDERDecodeItem(arena, &dual_params, 
00657                                 SECKEY_FortezzaPreParamTemplate, &newparams);
00658            } else {
00659                 rv = SEC_QuickDERDecodeItem(arena, &dual_params, 
00660                                     SECKEY_FortezzaAltPreParamTemplate, &newparams);
00661             }
00662         }
00663        
00664         if ( (dual_params.CommParams.prime.len > 0) &&
00665              (dual_params.CommParams.subPrime.len > 0) && 
00666              (dual_params.CommParams.base.len > 0) ) {
00667             /* copy in common params */
00668            if (SECSuccess == rv) {
00669                rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.prime,
00670                                       &dual_params.CommParams.prime);
00671             }
00672             if (SECSuccess == rv) {
00673                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.subPrime,
00674                                       &dual_params.CommParams.subPrime);
00675             }
00676             if (SECSuccess == rv) {
00677                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.base,
00678                                       &dual_params.CommParams.base);
00679             }
00680 
00681            /* Copy the DSA PQG parameters to the KEA PQG parameters. */
00682             if (SECSuccess == rv) {
00683                rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
00684                                       &pubk->u.fortezza.params.prime);
00685             }
00686             if (SECSuccess == rv) {
00687                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
00688                                       &pubk->u.fortezza.params.subPrime);
00689             }
00690             if (SECSuccess == rv) {
00691                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
00692                                       &pubk->u.fortezza.params.base);
00693             }
00694         } else {
00695 
00696            /* else copy in different params */
00697 
00698            /* copy DSA PQG parameters */
00699             if (SECSuccess == rv) {
00700                rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.prime,
00701                                   &dual_params.DiffParams.DiffDSAParams.prime);
00702             }
00703             if (SECSuccess == rv) {
00704                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.subPrime,
00705                                   &dual_params.DiffParams.DiffDSAParams.subPrime);
00706             }
00707             if (SECSuccess == rv) {
00708                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.base,
00709                                   &dual_params.DiffParams.DiffDSAParams.base);
00710             }
00711 
00712            /* copy KEA PQG parameters */
00713 
00714             if (SECSuccess == rv) {
00715                rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
00716                                   &dual_params.DiffParams.DiffKEAParams.prime);
00717             }
00718             if (SECSuccess == rv) {
00719                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
00720                                   &dual_params.DiffParams.DiffKEAParams.subPrime);
00721             }
00722             if (SECSuccess == rv) {
00723                 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
00724                                   &dual_params.DiffParams.DiffKEAParams.base);
00725             }
00726         }
00727     }
00728     return rv;
00729 }
00730 
00731 
00732 /* Decode the DSA PQG parameters.  The params could be stored in two
00733  * possible formats, the old fortezza-only wrapped format or
00734  * the normal standard format.  Store the decoded parameters in
00735  * a V3 certificate data structure.  */ 
00736 
00737 SECStatus
00738 SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params) {
00739     SECStatus rv;
00740     SECKEYPQGDualParams dual_params;
00741     SECItem newparams;
00742 
00743     if (params == NULL) return SECFailure; 
00744     
00745     if (params->data == NULL) return SECFailure;
00746 
00747     PORT_Assert(arena);
00748 
00749     /* make a copy of the data into the arena so QuickDER output is valid */
00750     rv = SECITEM_CopyItem(arena, &newparams, params);
00751 
00752     /* Check if params use the standard format.
00753      * The value 0xa1 will appear in the first byte of the parameter data
00754      * if the PQG parameters are not using the standard format.  This
00755      * code should be changed to use a better method to detect non-standard
00756      * parameters.    */
00757 
00758     if ((newparams.data[0] != 0xa1) &&
00759         (newparams.data[0] != 0xa0)) {
00760     
00761         if (SECSuccess == rv) {
00762              /* PQG params are in the standard format */
00763              prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
00764              rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
00765                                  SECKEY_PQGParamsTemplate,
00766                                  &newparams);
00767         }
00768     } else {
00769 
00770        dual_params.CommParams.prime.len = 0;
00771         dual_params.CommParams.subPrime.len = 0;
00772        dual_params.CommParams.base.len = 0;
00773        dual_params.DiffParams.DiffDSAParams.prime.len = 0;
00774         dual_params.DiffParams.DiffDSAParams.subPrime.len = 0;
00775        dual_params.DiffParams.DiffDSAParams.base.len = 0;
00776 
00777         if (SECSuccess == rv) {
00778             /* else the old fortezza-only wrapped format is used. */
00779             if (newparams.data[0] == 0xa1) {
00780                 rv = SEC_QuickDERDecodeItem(arena, &dual_params, 
00781                                 SECKEY_FortezzaPreParamTemplate, &newparams);
00782            } else {
00783                 rv = SEC_QuickDERDecodeItem(arena, &dual_params, 
00784                                     SECKEY_FortezzaAltPreParamTemplate, &newparams);
00785             }
00786         }
00787 
00788         if ( (dual_params.CommParams.prime.len > 0) &&
00789              (dual_params.CommParams.subPrime.len > 0) && 
00790              (dual_params.CommParams.base.len > 0) ) {
00791             /* copy in common params */
00792 
00793             if (SECSuccess == rv) {           
00794                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
00795                                       &dual_params.CommParams.prime);
00796             }
00797             if (SECSuccess == rv) {
00798                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
00799                                       &dual_params.CommParams.subPrime);
00800             }
00801             if (SECSuccess == rv) {
00802                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
00803                                     &dual_params.CommParams.base);
00804             }
00805         } else {
00806 
00807            /* else copy in different params */
00808 
00809            /* copy DSA PQG parameters */
00810             if (SECSuccess == rv) {
00811                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
00812                                       &dual_params.DiffParams.DiffDSAParams.prime);
00813             }
00814             if (SECSuccess == rv) {
00815                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
00816                                       &dual_params.DiffParams.DiffDSAParams.subPrime);
00817             }
00818             if (SECSuccess == rv) {
00819                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
00820                                       &dual_params.DiffParams.DiffDSAParams.base);
00821             }
00822         }
00823     }
00824     return rv;
00825 }
00826 
00827 
00828 /* Decodes the DER encoded fortezza public key and stores the results in a
00829  * structure of type SECKEYPublicKey. */
00830 
00831 SECStatus
00832 SECKEY_FortezzaDecodeCertKey(PRArenaPool *arena, SECKEYPublicKey *pubk,
00833                              SECItem *rawkey, SECItem *params) {
00834 
00835        unsigned char *rawptr = rawkey->data;
00836        unsigned char *end = rawkey->data + rawkey->len;
00837        unsigned char *clearptr;
00838 
00839        /* first march down and decode the raw key data */
00840 
00841        /* version */ 
00842        pubk->u.fortezza.KEAversion = *rawptr++;
00843        if (*rawptr++ != 0x01) {
00844               return SECFailure;
00845        }
00846 
00847        /* KMID */
00848        PORT_Memcpy(pubk->u.fortezza.KMID,rawptr,
00849                             sizeof(pubk->u.fortezza.KMID));
00850        rawptr += sizeof(pubk->u.fortezza.KMID);
00851 
00852        /* clearance (the string up to the first byte with the hi-bit on */
00853        clearptr = rawptr;
00854        while ((rawptr < end) && (*rawptr++ & 0x80));
00855 
00856        if (rawptr >= end) { return SECFailure; }
00857        pubk->u.fortezza.clearance.len = rawptr - clearptr;
00858        pubk->u.fortezza.clearance.data = 
00859               (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.clearance.len);
00860        if (pubk->u.fortezza.clearance.data == NULL) {
00861               return SECFailure;
00862        }
00863        PORT_Memcpy(pubk->u.fortezza.clearance.data,clearptr,
00864                                    pubk->u.fortezza.clearance.len);
00865 
00866        /* KEAPrivilege (the string up to the first byte with the hi-bit on */
00867        clearptr = rawptr;
00868        while ((rawptr < end) && (*rawptr++ & 0x80));
00869        if (rawptr >= end) { return SECFailure; }
00870        pubk->u.fortezza.KEApriviledge.len = rawptr - clearptr;
00871        pubk->u.fortezza.KEApriviledge.data = 
00872               (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.KEApriviledge.len);
00873        if (pubk->u.fortezza.KEApriviledge.data == NULL) {
00874               return SECFailure;
00875        }
00876        PORT_Memcpy(pubk->u.fortezza.KEApriviledge.data,clearptr,
00877                             pubk->u.fortezza.KEApriviledge.len);
00878 
00879 
00880        /* now copy the key. The next to bytes are the key length, and the
00881         * key follows */
00882        pubk->u.fortezza.KEAKey.len = (*rawptr << 8) | rawptr[1];
00883 
00884        rawptr += 2;
00885        if (rawptr+pubk->u.fortezza.KEAKey.len > end) { return SECFailure; }
00886        pubk->u.fortezza.KEAKey.data = 
00887                      (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.KEAKey.len);
00888        if (pubk->u.fortezza.KEAKey.data == NULL) {
00889               return SECFailure;
00890        }
00891        PORT_Memcpy(pubk->u.fortezza.KEAKey.data,rawptr,
00892                                    pubk->u.fortezza.KEAKey.len);
00893        rawptr += pubk->u.fortezza.KEAKey.len;
00894 
00895        /* shared key */
00896        if (rawptr >= end) {
00897            pubk->u.fortezza.DSSKey.len = pubk->u.fortezza.KEAKey.len;
00898            /* this depends on the fact that we are going to get freed with an
00899             * ArenaFree call. We cannot free DSSKey and KEAKey separately */
00900            pubk->u.fortezza.DSSKey.data=
00901                                    pubk->u.fortezza.KEAKey.data;
00902            pubk->u.fortezza.DSSpriviledge.len = 
00903                             pubk->u.fortezza.KEApriviledge.len;
00904            pubk->u.fortezza.DSSpriviledge.data =
00905                      pubk->u.fortezza.DSSpriviledge.data;
00906            goto done;
00907        }
00908               
00909 
00910        /* DSS Version is next */
00911        pubk->u.fortezza.DSSversion = *rawptr++;
00912 
00913        if (*rawptr++ != 2) {
00914               return SECFailure;
00915        }
00916 
00917        /* DSSPrivilege (the string up to the first byte with the hi-bit on */
00918        clearptr = rawptr;
00919        while ((rawptr < end) && (*rawptr++ & 0x80));
00920        if (rawptr >= end) { return SECFailure; }
00921        pubk->u.fortezza.DSSpriviledge.len = rawptr - clearptr;
00922        pubk->u.fortezza.DSSpriviledge.data = 
00923               (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.DSSpriviledge.len);
00924        if (pubk->u.fortezza.DSSpriviledge.data == NULL) {
00925               return SECFailure;
00926        }
00927        PORT_Memcpy(pubk->u.fortezza.DSSpriviledge.data,clearptr,
00928                             pubk->u.fortezza.DSSpriviledge.len);
00929 
00930        /* finally copy the DSS key. The next to bytes are the key length,
00931         *  and the key follows */
00932        pubk->u.fortezza.DSSKey.len = (*rawptr << 8) | rawptr[1];
00933 
00934        rawptr += 2;
00935        if (rawptr+pubk->u.fortezza.DSSKey.len > end){ return SECFailure; }
00936        pubk->u.fortezza.DSSKey.data = 
00937                      (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.DSSKey.len);
00938        if (pubk->u.fortezza.DSSKey.data == NULL) {
00939               return SECFailure;
00940        }
00941        PORT_Memcpy(pubk->u.fortezza.DSSKey.data,rawptr,
00942                                    pubk->u.fortezza.DSSKey.len);
00943 
00944        /* ok, now we decode the parameters */
00945 done:
00946 
00947         return SECKEY_FortezzaDecodePQGtoOld(arena, pubk, params);
00948 }
00949 
00950 
00951 /* Function used to determine what kind of cert we are dealing with. */
00952 KeyType 
00953 CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
00954     int tag;
00955     KeyType keyType;
00956 
00957     tag = SECOID_GetAlgorithmTag(&spki->algorithm);
00958     switch (tag) {
00959       case SEC_OID_X500_RSA_ENCRYPTION:
00960       case SEC_OID_PKCS1_RSA_ENCRYPTION:
00961        keyType = rsaKey;
00962        break;
00963       case SEC_OID_ANSIX9_DSA_SIGNATURE:
00964        keyType = dsaKey;
00965        break;
00966       case SEC_OID_MISSI_KEA_DSS_OLD:
00967       case SEC_OID_MISSI_KEA_DSS:
00968       case SEC_OID_MISSI_DSS_OLD:
00969       case SEC_OID_MISSI_DSS:  
00970        keyType = fortezzaKey;
00971        break;
00972       case SEC_OID_MISSI_KEA:
00973       case SEC_OID_MISSI_ALT_KEA:
00974        keyType = keaKey;
00975        break;
00976       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
00977        keyType = dhKey;
00978        break;
00979       case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
00980        keyType = ecKey;
00981        break;
00982       default:
00983        keyType = nullKey;
00984     }
00985     return keyType;
00986 }
00987 
00988 static SECKEYPublicKey *
00989 seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
00990 {
00991     SECKEYPublicKey *pubk;
00992     SECItem os, newOs, newParms;
00993     SECStatus rv;
00994     PRArenaPool *arena;
00995     SECOidTag tag;
00996 
00997     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
00998     if (arena == NULL)
00999        return NULL;
01000 
01001     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
01002     if (pubk == NULL) {
01003        PORT_FreeArena (arena, PR_FALSE);
01004        return NULL;
01005     }
01006 
01007     pubk->arena = arena;
01008     pubk->pkcs11Slot = 0;
01009     pubk->pkcs11ID = CK_INVALID_HANDLE;
01010 
01011 
01012     /* Convert bit string length from bits to bytes */
01013     os = spki->subjectPublicKey;
01014     DER_ConvertBitString (&os);
01015 
01016     tag = SECOID_GetAlgorithmTag(&spki->algorithm);
01017 
01018     /* copy the DER into the arena, since Quick DER returns data that points
01019        into the DER input, which may get freed by the caller */
01020     rv = SECITEM_CopyItem(arena, &newOs, &os);
01021     if ( rv == SECSuccess )
01022     switch ( tag ) {
01023       case SEC_OID_X500_RSA_ENCRYPTION:
01024       case SEC_OID_PKCS1_RSA_ENCRYPTION:
01025        pubk->keyType = rsaKey;
01026        prepare_rsa_pub_key_for_asn1(pubk);        
01027         rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
01028        if (rv == SECSuccess)
01029            return pubk;
01030        break;
01031       case SEC_OID_ANSIX9_DSA_SIGNATURE:
01032       case SEC_OID_SDN702_DSA_SIGNATURE:
01033        pubk->keyType = dsaKey;
01034        prepare_dsa_pub_key_for_asn1(pubk);
01035        rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
01036        if (rv != SECSuccess) break;
01037 
01038         rv = SECKEY_DSADecodePQG(arena, pubk,
01039                                  &spki->algorithm.parameters); 
01040 
01041        if (rv == SECSuccess) return pubk;
01042        break;
01043       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
01044        pubk->keyType = dhKey;
01045        prepare_dh_pub_key_for_asn1(pubk);
01046        rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
01047        if (rv != SECSuccess) break;
01048 
01049         /* copy the DER into the arena, since Quick DER returns data that points
01050            into the DER input, which may get freed by the caller */
01051         rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
01052         if ( rv != SECSuccess )
01053             break;
01054 
01055         rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
01056                                  &newParms); 
01057 
01058        if (rv == SECSuccess) return pubk;
01059        break;
01060       case SEC_OID_MISSI_KEA_DSS_OLD:
01061       case SEC_OID_MISSI_KEA_DSS:
01062       case SEC_OID_MISSI_DSS_OLD:
01063       case SEC_OID_MISSI_DSS:
01064        pubk->keyType = fortezzaKey;
01065        rv = SECKEY_FortezzaDecodeCertKey(arena, pubk, &newOs,
01066                                       &spki->algorithm.parameters);
01067        if (rv == SECSuccess)
01068            return pubk;
01069        break;
01070 
01071       case SEC_OID_MISSI_KEA:
01072        pubk->keyType = keaKey;
01073 
01074        prepare_kea_pub_key_for_asn1(pubk);
01075         rv = SEC_QuickDERDecodeItem(arena, pubk,
01076                                 SECKEY_KEAPublicKeyTemplate, &newOs);
01077         if (rv != SECSuccess) break;
01078 
01079         /* copy the DER into the arena, since Quick DER returns data that points
01080            into the DER input, which may get freed by the caller */
01081         rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
01082         if ( rv != SECSuccess )
01083             break;
01084 
01085         rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_KEAParamsTemplate,
01086                         &newParms);
01087 
01088        if (rv == SECSuccess)
01089            return pubk;
01090 
01091         break;
01092 
01093       case SEC_OID_MISSI_ALT_KEA:
01094        pubk->keyType = keaKey;
01095 
01096         rv = SECITEM_CopyItem(arena,&pubk->u.kea.publicValue,&newOs);
01097         if (rv != SECSuccess) break;
01098  
01099         /* copy the DER into the arena, since Quick DER returns data that points
01100            into the DER input, which may get freed by the caller */
01101         rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
01102         if ( rv != SECSuccess )
01103             break;
01104 
01105         rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_KEAParamsTemplate,
01106                         &newParms);
01107 
01108        if (rv == SECSuccess)
01109            return pubk;
01110 
01111         break;
01112 
01113       case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
01114        pubk->keyType = ecKey;
01115        pubk->u.ec.size = 0;
01116 
01117        /* Since PKCS#11 directly takes the DER encoding of EC params
01118         * and public value, we don't need any decoding here.
01119         */
01120         rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams, 
01121            &spki->algorithm.parameters);
01122         if ( rv != SECSuccess )
01123             break;
01124         rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
01125        if (rv == SECSuccess) return pubk;
01126        break;
01127 
01128       default:
01129        rv = SECFailure;
01130        break;
01131     }
01132 
01133     SECKEY_DestroyPublicKey (pubk);
01134     return NULL;
01135 }
01136 
01137 
01138 /* required for JSS */
01139 SECKEYPublicKey *
01140 SECKEY_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
01141 {
01142     return seckey_ExtractPublicKey(spki);
01143 }
01144 
01145 SECKEYPublicKey *
01146 CERT_ExtractPublicKey(CERTCertificate *cert)
01147 {
01148     SECStatus rv;
01149 
01150     if (!cert) {
01151         PORT_SetError(SEC_ERROR_INVALID_ARGS);
01152        return NULL;
01153     }
01154     rv = SECKEY_UpdateCertPQG(cert);
01155     if (rv != SECSuccess) return NULL;
01156 
01157     return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
01158 }
01159 
01160 /*
01161  * Get the public key for the fortezza KMID. NOTE this requires the
01162  * PQG paramters to be set. We probably should have a fortezza call that 
01163  * just extracts the kmid for us directly so this function can work
01164  * without having the whole cert chain
01165  */
01166 SECKEYPublicKey *
01167 CERT_KMIDPublicKey(CERTCertificate *cert)
01168 {
01169     return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
01170 }
01171 
01172 int
01173 SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
01174 {
01175     SECOidTag tag;
01176     SECItem oid = { siBuffer, NULL, 0};
01177        
01178     /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
01179      * followed by the length of the curve oid and the curve oid.
01180      */
01181     oid.len = encodedParams->data[1];
01182     oid.data = encodedParams->data + 2;
01183     if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
01184        return 0;
01185 
01186     switch (tag) {
01187     case SEC_OID_SECG_EC_SECP112R1:
01188     case SEC_OID_SECG_EC_SECP112R2:
01189         return 112;
01190 
01191     case SEC_OID_SECG_EC_SECT113R1:
01192     case SEC_OID_SECG_EC_SECT113R2:
01193        return 113;
01194 
01195     case SEC_OID_SECG_EC_SECP128R1:
01196     case SEC_OID_SECG_EC_SECP128R2:
01197        return 128;
01198 
01199     case SEC_OID_SECG_EC_SECT131R1:
01200     case SEC_OID_SECG_EC_SECT131R2:
01201        return 131;
01202 
01203     case SEC_OID_SECG_EC_SECP160K1:
01204     case SEC_OID_SECG_EC_SECP160R1:
01205     case SEC_OID_SECG_EC_SECP160R2:
01206        return 160;
01207 
01208     case SEC_OID_SECG_EC_SECT163K1:
01209     case SEC_OID_SECG_EC_SECT163R1:
01210     case SEC_OID_SECG_EC_SECT163R2:
01211     case SEC_OID_ANSIX962_EC_C2PNB163V1:
01212     case SEC_OID_ANSIX962_EC_C2PNB163V2:
01213     case SEC_OID_ANSIX962_EC_C2PNB163V3:
01214        return 163;
01215 
01216     case SEC_OID_ANSIX962_EC_C2PNB176V1:
01217        return 176;
01218 
01219     case SEC_OID_ANSIX962_EC_C2TNB191V1:
01220     case SEC_OID_ANSIX962_EC_C2TNB191V2:
01221     case SEC_OID_ANSIX962_EC_C2TNB191V3:
01222     case SEC_OID_ANSIX962_EC_C2ONB191V4:
01223     case SEC_OID_ANSIX962_EC_C2ONB191V5:
01224        return 191;
01225 
01226     case SEC_OID_SECG_EC_SECP192K1:
01227     case SEC_OID_ANSIX962_EC_PRIME192V1:
01228     case SEC_OID_ANSIX962_EC_PRIME192V2:
01229     case SEC_OID_ANSIX962_EC_PRIME192V3:
01230        return 192;
01231 
01232     case SEC_OID_SECG_EC_SECT193R1:
01233     case SEC_OID_SECG_EC_SECT193R2:
01234        return 193;
01235 
01236     case SEC_OID_ANSIX962_EC_C2PNB208W1:
01237        return 208;
01238 
01239     case SEC_OID_SECG_EC_SECP224K1:
01240     case SEC_OID_SECG_EC_SECP224R1:
01241        return 224;
01242 
01243     case SEC_OID_SECG_EC_SECT233K1:
01244     case SEC_OID_SECG_EC_SECT233R1:
01245        return 233;
01246 
01247     case SEC_OID_SECG_EC_SECT239K1:
01248     case SEC_OID_ANSIX962_EC_C2TNB239V1:
01249     case SEC_OID_ANSIX962_EC_C2TNB239V2:
01250     case SEC_OID_ANSIX962_EC_C2TNB239V3:
01251     case SEC_OID_ANSIX962_EC_C2ONB239V4:
01252     case SEC_OID_ANSIX962_EC_C2ONB239V5:
01253     case SEC_OID_ANSIX962_EC_PRIME239V1:
01254     case SEC_OID_ANSIX962_EC_PRIME239V2:
01255     case SEC_OID_ANSIX962_EC_PRIME239V3:
01256        return 239;
01257 
01258     case SEC_OID_SECG_EC_SECP256K1:
01259     case SEC_OID_ANSIX962_EC_PRIME256V1:
01260        return 256;
01261 
01262     case SEC_OID_ANSIX962_EC_C2PNB272W1:
01263        return 272;
01264 
01265     case SEC_OID_SECG_EC_SECT283K1:
01266     case SEC_OID_SECG_EC_SECT283R1:
01267        return 283;
01268 
01269     case SEC_OID_ANSIX962_EC_C2PNB304W1:
01270        return 304;
01271 
01272     case SEC_OID_ANSIX962_EC_C2TNB359V1:
01273        return 359;
01274 
01275     case SEC_OID_ANSIX962_EC_C2PNB368W1:
01276        return 368;
01277 
01278     case SEC_OID_SECG_EC_SECP384R1:
01279        return 384;
01280 
01281     case SEC_OID_SECG_EC_SECT409K1:
01282     case SEC_OID_SECG_EC_SECT409R1:
01283        return 409;
01284 
01285     case SEC_OID_ANSIX962_EC_C2TNB431R1:
01286        return 431;
01287 
01288     case SEC_OID_SECG_EC_SECP521R1:
01289        return 521;
01290 
01291     case SEC_OID_SECG_EC_SECT571K1:
01292     case SEC_OID_SECG_EC_SECT571R1:
01293        return 571;
01294 
01295     default:
01296        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
01297        return 0;
01298     }
01299 }
01300 
01301 int
01302 SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
01303 {
01304     SECOidTag tag;
01305     SECItem oid = { siBuffer, NULL, 0};
01306        
01307     /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
01308      * followed by the length of the curve oid and the curve oid.
01309      */
01310     oid.len = encodedParams->data[1];
01311     oid.data = encodedParams->data + 2;
01312     if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
01313        return 0;
01314 
01315     switch (tag) {
01316     case SEC_OID_SECG_EC_SECP112R1:
01317         return 112;
01318     case SEC_OID_SECG_EC_SECP112R2:
01319         return 110;
01320 
01321     case SEC_OID_SECG_EC_SECT113R1:
01322     case SEC_OID_SECG_EC_SECT113R2:
01323        return 113;
01324 
01325     case SEC_OID_SECG_EC_SECP128R1:
01326        return 128;
01327     case SEC_OID_SECG_EC_SECP128R2:
01328        return 126;
01329 
01330     case SEC_OID_SECG_EC_SECT131R1:
01331     case SEC_OID_SECG_EC_SECT131R2:
01332        return 131;
01333 
01334     case SEC_OID_SECG_EC_SECP160K1:
01335     case SEC_OID_SECG_EC_SECP160R1:
01336     case SEC_OID_SECG_EC_SECP160R2:
01337        return 161;
01338 
01339     case SEC_OID_SECG_EC_SECT163K1:
01340        return 163;
01341     case SEC_OID_SECG_EC_SECT163R1:
01342        return 162;
01343     case SEC_OID_SECG_EC_SECT163R2:
01344     case SEC_OID_ANSIX962_EC_C2PNB163V1:
01345        return 163;
01346     case SEC_OID_ANSIX962_EC_C2PNB163V2:
01347     case SEC_OID_ANSIX962_EC_C2PNB163V3:
01348        return 162;
01349 
01350     case SEC_OID_ANSIX962_EC_C2PNB176V1:
01351        return 161;
01352 
01353     case SEC_OID_ANSIX962_EC_C2TNB191V1:
01354        return 191;
01355     case SEC_OID_ANSIX962_EC_C2TNB191V2:
01356        return 190;
01357     case SEC_OID_ANSIX962_EC_C2TNB191V3:
01358        return 189;
01359     case SEC_OID_ANSIX962_EC_C2ONB191V4:
01360        return 191;
01361     case SEC_OID_ANSIX962_EC_C2ONB191V5:
01362        return 188;
01363 
01364     case SEC_OID_SECG_EC_SECP192K1:
01365     case SEC_OID_ANSIX962_EC_PRIME192V1:
01366     case SEC_OID_ANSIX962_EC_PRIME192V2:
01367     case SEC_OID_ANSIX962_EC_PRIME192V3:
01368        return 192;
01369 
01370     case SEC_OID_SECG_EC_SECT193R1:
01371     case SEC_OID_SECG_EC_SECT193R2:
01372        return 193;
01373 
01374     case SEC_OID_ANSIX962_EC_C2PNB208W1:
01375        return 193;
01376 
01377     case SEC_OID_SECG_EC_SECP224K1:
01378        return 225;
01379     case SEC_OID_SECG_EC_SECP224R1:
01380        return 224;
01381 
01382     case SEC_OID_SECG_EC_SECT233K1:
01383        return 232;
01384     case SEC_OID_SECG_EC_SECT233R1:
01385        return 233;
01386 
01387     case SEC_OID_SECG_EC_SECT239K1:
01388     case SEC_OID_ANSIX962_EC_C2TNB239V1:
01389        return 238;
01390     case SEC_OID_ANSIX962_EC_C2TNB239V2:
01391        return 237;
01392     case SEC_OID_ANSIX962_EC_C2TNB239V3:
01393        return 236;
01394     case SEC_OID_ANSIX962_EC_C2ONB239V4:
01395        return 238;
01396     case SEC_OID_ANSIX962_EC_C2ONB239V5:
01397        return 237;
01398     case SEC_OID_ANSIX962_EC_PRIME239V1:
01399     case SEC_OID_ANSIX962_EC_PRIME239V2:
01400     case SEC_OID_ANSIX962_EC_PRIME239V3:
01401        return 239;
01402 
01403     case SEC_OID_SECG_EC_SECP256K1:
01404     case SEC_OID_ANSIX962_EC_PRIME256V1:
01405        return 256;
01406 
01407     case SEC_OID_ANSIX962_EC_C2PNB272W1:
01408        return 257;
01409 
01410     case SEC_OID_SECG_EC_SECT283K1:
01411        return 281;
01412     case SEC_OID_SECG_EC_SECT283R1:
01413        return 282;
01414 
01415     case SEC_OID_ANSIX962_EC_C2PNB304W1:
01416        return 289;
01417 
01418     case SEC_OID_ANSIX962_EC_C2TNB359V1:
01419        return 353;
01420 
01421     case SEC_OID_ANSIX962_EC_C2PNB368W1:
01422        return 353;
01423 
01424     case SEC_OID_SECG_EC_SECP384R1:
01425        return 384;
01426 
01427     case SEC_OID_SECG_EC_SECT409K1:
01428        return 407;
01429     case SEC_OID_SECG_EC_SECT409R1:
01430        return 409;
01431 
01432     case SEC_OID_ANSIX962_EC_C2TNB431R1:
01433        return 418;
01434 
01435     case SEC_OID_SECG_EC_SECP521R1:
01436        return 521;
01437 
01438     case SEC_OID_SECG_EC_SECT571K1:
01439     case SEC_OID_SECG_EC_SECT571R1:
01440        return 570;
01441 
01442     default:
01443        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
01444        return 0;
01445     }
01446 }
01447 
01448 /* returns key strength in bytes (not bits) */
01449 unsigned
01450 SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
01451 {
01452     unsigned char b0;
01453 
01454     /* interpret modulus length as key strength... in
01455      * fortezza that's the public key length */
01456 
01457     switch (pubk->keyType) {
01458     case rsaKey:
01459        b0 = pubk->u.rsa.modulus.data[0];
01460        return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
01461     case dsaKey:
01462        b0 = pubk->u.dsa.publicValue.data[0];
01463        return b0 ? pubk->u.dsa.publicValue.len :
01464            pubk->u.dsa.publicValue.len - 1;
01465     case dhKey:
01466        b0 = pubk->u.dh.publicValue.data[0];
01467        return b0 ? pubk->u.dh.publicValue.len :
01468            pubk->u.dh.publicValue.len - 1;
01469     case fortezzaKey:
01470        return PR_MAX(pubk->u.fortezza.KEAKey.len, pubk->u.fortezza.DSSKey.len);
01471     case ecKey:
01472        /* Get the key size in bits and adjust */
01473        if (pubk->u.ec.size == 0) {
01474            pubk->u.ec.size = 
01475               SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
01476        } 
01477        return (pubk->u.ec.size + 7)/8;
01478     default:
01479        break;
01480     }
01481     PORT_SetError(SEC_ERROR_INVALID_KEY);
01482     return 0;
01483 }
01484 
01485 /* returns key strength in bits */
01486 unsigned
01487 SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
01488 {
01489     switch (pubk->keyType) {
01490     case rsaKey:
01491     case dsaKey:
01492     case dhKey:
01493     case fortezzaKey:
01494        return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
01495     case ecKey:
01496        if (pubk->u.ec.size == 0) {
01497            pubk->u.ec.size = 
01498               SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
01499        } 
01500        return pubk->u.ec.size;
01501     default:
01502        break;
01503     }
01504     PORT_SetError(SEC_ERROR_INVALID_KEY);
01505     return 0;
01506 }
01507 
01508 /* returns signature length in bytes (not bits) */
01509 unsigned
01510 SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
01511 {
01512     unsigned char b0;
01513     unsigned size;
01514 
01515     switch (pubk->keyType) {
01516     case rsaKey:
01517        b0 = pubk->u.rsa.modulus.data[0];
01518        return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
01519     case fortezzaKey:
01520     case dsaKey:
01521        return DSA_SIGNATURE_LEN;
01522     case ecKey:
01523        /* Get the base point order length in bits and adjust */
01524        size = SECKEY_ECParamsToBasePointOrderLen(
01525               &pubk->u.ec.DEREncodedParams);
01526        return ((size + 7)/8) * 2;
01527     default:
01528        break;
01529     }
01530     PORT_SetError(SEC_ERROR_INVALID_KEY);
01531     return 0;
01532 }
01533 
01534 SECKEYPrivateKey *
01535 SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk)
01536 {
01537     SECKEYPrivateKey *copyk;
01538     PRArenaPool *arena;
01539     
01540     if (!privk || !privk->pkcs11Slot) {
01541        PORT_SetError(SEC_ERROR_INVALID_ARGS);
01542        return NULL;
01543     }
01544     
01545     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01546     if (arena == NULL) {
01547        return NULL;
01548     }
01549 
01550     copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey));
01551     if (copyk) {
01552        copyk->arena = arena;
01553        copyk->keyType = privk->keyType;
01554 
01555        /* copy the PKCS #11 parameters */
01556        copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
01557        /* if the key we're referencing was a temparary key we have just
01558         * created, that we want to go away when we're through, we need
01559         * to make a copy of it */
01560        if (privk->pkcs11IsTemp) {
01561            copyk->pkcs11ID = 
01562                      PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID);
01563            if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail;
01564        } else {
01565            copyk->pkcs11ID = privk->pkcs11ID;
01566        }
01567        copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
01568        copyk->wincx = privk->wincx;
01569        copyk->staticflags = privk->staticflags;
01570        return copyk;
01571     } else {
01572        PORT_SetError (SEC_ERROR_NO_MEMORY);
01573     }
01574 
01575 fail:
01576     PORT_FreeArena (arena, PR_FALSE);
01577     return NULL;
01578 }
01579 
01580 SECKEYPublicKey *
01581 SECKEY_CopyPublicKey(SECKEYPublicKey *pubk)
01582 {
01583     SECKEYPublicKey *copyk;
01584     PRArenaPool *arena;
01585     SECStatus rv = SECSuccess;
01586 
01587     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01588     if (arena == NULL) {
01589        PORT_SetError (SEC_ERROR_NO_MEMORY);
01590        return NULL;
01591     }
01592 
01593     copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
01594     if (!copyk) {
01595         PORT_SetError (SEC_ERROR_NO_MEMORY);
01596         PORT_FreeArena (arena, PR_FALSE);
01597         return NULL;
01598     }
01599 
01600     copyk->arena = arena;
01601     copyk->keyType = pubk->keyType;
01602     if (pubk->pkcs11Slot && 
01603         PK11_IsPermObject(pubk->pkcs11Slot,pubk->pkcs11ID)) {
01604         copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
01605         copyk->pkcs11ID = pubk->pkcs11ID;
01606     } else {
01607         copyk->pkcs11Slot = NULL;  /* go get own reference */
01608         copyk->pkcs11ID = CK_INVALID_HANDLE;
01609     }
01610     switch (pubk->keyType) {
01611       case rsaKey:
01612           rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
01613                                 &pubk->u.rsa.modulus);
01614           if (rv == SECSuccess) {
01615               rv = SECITEM_CopyItem (arena, &copyk->u.rsa.publicExponent,
01616                                      &pubk->u.rsa.publicExponent);
01617               if (rv == SECSuccess)
01618                   return copyk;
01619           }
01620           break;
01621       case dsaKey:
01622           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
01623                                 &pubk->u.dsa.publicValue);
01624           if (rv != SECSuccess) break;
01625           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
01626                                 &pubk->u.dsa.params.prime);
01627           if (rv != SECSuccess) break;
01628           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
01629                                 &pubk->u.dsa.params.subPrime);
01630           if (rv != SECSuccess) break;
01631           rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
01632                                 &pubk->u.dsa.params.base);
01633           break;
01634       case keaKey:
01635           rv = SECITEM_CopyItem(arena, &copyk->u.kea.publicValue,
01636                                 &pubk->u.kea.publicValue);
01637           if (rv != SECSuccess) break;
01638           rv = SECITEM_CopyItem(arena, &copyk->u.kea.params.hash,
01639                                 &pubk->u.kea.params.hash);
01640           break;
01641       case fortezzaKey:
01642           copyk->u.fortezza.KEAversion = pubk->u.fortezza.KEAversion;
01643           copyk->u.fortezza.DSSversion = pubk->u.fortezza.DSSversion;
01644           PORT_Memcpy(copyk->u.fortezza.KMID, pubk->u.fortezza.KMID,
01645                       sizeof(pubk->u.fortezza.KMID));
01646           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.clearance, 
01647                                 &pubk->u.fortezza.clearance);
01648           if (rv != SECSuccess) break;
01649           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.KEApriviledge, 
01650                                 &pubk->u.fortezza.KEApriviledge);
01651           if (rv != SECSuccess) break;
01652           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.DSSpriviledge, 
01653                                 &pubk->u.fortezza.DSSpriviledge);
01654           if (rv != SECSuccess) break;
01655           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.KEAKey, 
01656                                 &pubk->u.fortezza.KEAKey);
01657           if (rv != SECSuccess) break;
01658           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.DSSKey, 
01659                                 &pubk->u.fortezza.DSSKey);
01660           if (rv != SECSuccess) break;
01661           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.prime, 
01662                                 &pubk->u.fortezza.params.prime);
01663           if (rv != SECSuccess) break;
01664           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.subPrime, 
01665                                 &pubk->u.fortezza.params.subPrime);
01666           if (rv != SECSuccess) break;
01667           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.base, 
01668                                 &pubk->u.fortezza.params.base);
01669           if (rv != SECSuccess) break;
01670           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.prime, 
01671                                 &pubk->u.fortezza.keaParams.prime);
01672           if (rv != SECSuccess) break;
01673           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.subPrime, 
01674                                 &pubk->u.fortezza.keaParams.subPrime);
01675           if (rv != SECSuccess) break;
01676           rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.base, 
01677                                 &pubk->u.fortezza.keaParams.base);
01678           break;
01679       case dhKey:
01680           rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
01681           if (rv != SECSuccess) break;
01682           rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
01683           if (rv != SECSuccess) break;
01684           rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue, 
01685                                 &pubk->u.dh.publicValue);
01686           break;
01687       case ecKey:
01688           copyk->u.ec.size = pubk->u.ec.size;
01689           rv = SECITEM_CopyItem(arena,&copyk->u.ec.DEREncodedParams,
01690                                 &pubk->u.ec.DEREncodedParams);
01691           if (rv != SECSuccess) break;
01692           rv = SECITEM_CopyItem(arena,&copyk->u.ec.publicValue,
01693                                 &pubk->u.ec.publicValue);
01694           break;
01695       case nullKey:
01696           return copyk;
01697       default:
01698           rv = SECFailure;
01699           break;
01700     }
01701     if (rv == SECSuccess)
01702         return copyk;
01703 
01704     SECKEY_DestroyPublicKey (copyk);
01705     return NULL;
01706 }
01707 
01708 
01709 SECKEYPublicKey *
01710 SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
01711 {
01712     SECKEYPublicKey *pubk;
01713     PRArenaPool *arena;
01714     CERTCertificate *cert;
01715     SECStatus rv;
01716 
01717     /*
01718      * First try to look up the cert.
01719      */
01720     cert = PK11_GetCertFromPrivateKey(privk);
01721     if (cert) {
01722        pubk = CERT_ExtractPublicKey(cert);
01723        CERT_DestroyCertificate(cert);
01724        return pubk;
01725     }
01726 
01727     /* couldn't find the cert, build pub key by hand */
01728     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
01729     if (arena == NULL) {
01730        PORT_SetError (SEC_ERROR_NO_MEMORY);
01731        return NULL;
01732     }
01733     pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
01734                                              sizeof (SECKEYPublicKey));
01735     if (pubk == NULL) {
01736        PORT_FreeArena(arena,PR_FALSE);
01737        return NULL;
01738     }
01739     pubk->keyType = privk->keyType;
01740     pubk->pkcs11Slot = NULL;
01741     pubk->pkcs11ID = CK_INVALID_HANDLE;
01742     pubk->arena = arena;
01743 
01744     /*
01745      * fortezza is at the head of this switch, since we don't want to
01746      * allocate an arena... CERT_ExtractPublicKey will to that for us.
01747      */
01748     switch(privk->keyType) {
01749       case fortezzaKey:
01750       case nullKey:
01751       case dhKey:
01752       case dsaKey:
01753        /* Nothing to query, if the cert isn't there, we're done -- no way
01754         * to get the public key */
01755        break;
01756       case rsaKey:
01757        rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
01758                             CKA_MODULUS,arena,&pubk->u.rsa.modulus);
01759        if (rv != SECSuccess)  break;
01760        rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
01761                      CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent);
01762        if (rv != SECSuccess)  break;
01763        return pubk;
01764        break;
01765     default:
01766        break;
01767     }
01768 
01769     PORT_FreeArena (arena, PR_FALSE);
01770     return NULL;
01771 }
01772 
01773 CERTSubjectPublicKeyInfo *
01774 SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
01775 {
01776     CERTSubjectPublicKeyInfo *spki;
01777     PRArenaPool *arena;
01778     SECItem params = { siBuffer, NULL, 0 };
01779 
01780     if (!pubk) {
01781         PORT_SetError(SEC_ERROR_INVALID_ARGS);
01782         return NULL;
01783     }
01784 
01785     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01786     if (arena == NULL) {
01787        PORT_SetError(SEC_ERROR_NO_MEMORY);
01788        return NULL;
01789     }
01790 
01791     spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki));
01792     if (spki != NULL) {
01793        SECStatus rv;
01794        SECItem *rv_item;
01795        
01796        spki->arena = arena;
01797        switch(pubk->keyType) {
01798          case rsaKey:
01799            rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
01800                                  SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
01801            if (rv == SECSuccess) {
01802               /*
01803                * DER encode the public key into the subjectPublicKeyInfo.
01804                */
01805               prepare_rsa_pub_key_for_asn1(pubk);
01806               rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
01807                                         pubk, SECKEY_RSAPublicKeyTemplate);
01808               if (rv_item != NULL) {
01809                   /*
01810                    * The stored value is supposed to be a BIT_STRING,
01811                    * so convert the length.
01812                    */
01813                   spki->subjectPublicKey.len <<= 3;
01814                   /*
01815                    * We got a good one; return it.
01816                    */
01817                   return spki;
01818               }
01819            }
01820            break;
01821          case dsaKey:
01822            /* DER encode the params. */
01823            prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
01824            rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
01825                                     SECKEY_PQGParamsTemplate);
01826            if (rv_item != NULL) {
01827               rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
01828                                       SEC_OID_ANSIX9_DSA_SIGNATURE,
01829                                       &params);
01830               if (rv == SECSuccess) {
01831                   /*
01832                    * DER encode the public key into the subjectPublicKeyInfo.
01833                    */
01834                   prepare_dsa_pub_key_for_asn1(pubk);
01835                   rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
01836                                            pubk,
01837                                            SECKEY_DSAPublicKeyTemplate);
01838                   if (rv_item != NULL) {
01839                      /*
01840                       * The stored value is supposed to be a BIT_STRING,
01841                       * so convert the length.
01842                       */
01843                      spki->subjectPublicKey.len <<= 3;
01844                      /*
01845                       * We got a good one; return it.
01846                       */
01847                      return spki;
01848                   }
01849               }
01850            }
01851            SECITEM_FreeItem(&params, PR_FALSE);
01852            break;
01853          case ecKey:
01854            rv = SECITEM_CopyItem(arena, &params, 
01855                               &pubk->u.ec.DEREncodedParams);
01856            if (rv != SECSuccess) break;
01857 
01858            rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
01859                                    SEC_OID_ANSIX962_EC_PUBLIC_KEY,
01860                                    &params);
01861            if (rv != SECSuccess) break;
01862 
01863            rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
01864                               &pubk->u.ec.publicValue);
01865 
01866            if (rv == SECSuccess) {
01867                /*
01868                * The stored value is supposed to be a BIT_STRING,
01869                * so convert the length.
01870                */
01871                spki->subjectPublicKey.len <<= 3;
01872               /*
01873                * We got a good one; return it.
01874                */
01875               return spki;
01876            }
01877            break;
01878          case keaKey:
01879          case dhKey: /* later... */
01880 
01881          break;  
01882          case fortezzaKey:
01883 #ifdef notdef
01884            /* encode the DSS parameters (PQG) */
01885            rv = FortezzaBuildParams(&params,pubk);
01886            if (rv != SECSuccess) break;
01887 
01888            /* set the algorithm */
01889            rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
01890                                    SEC_OID_MISSI_KEA_DSS, &params);
01891            PORT_Free(params.data);
01892            if (rv == SECSuccess) {
01893               /*
01894                * Encode the public key into the subjectPublicKeyInfo.
01895                * Fortezza key material is not standard DER
01896                */
01897               rv = FortezzaEncodeCertKey(arena,&spki->subjectPublicKey,pubk);
01898               if (rv == SECSuccess) {
01899                   /*
01900                    * The stored value is supposed to be a BIT_STRING,
01901                    * so convert the length.
01902                    */
01903                   spki->subjectPublicKey.len <<= 3;
01904 
01905                   /*
01906                    * We got a good one; return it.
01907                    */
01908                   return spki;
01909               }
01910            }
01911 #endif
01912            break;
01913          default:
01914            break;
01915        }
01916     } else {
01917        PORT_SetError(SEC_ERROR_NO_MEMORY);
01918     }
01919 
01920     PORT_FreeArena(arena, PR_FALSE);
01921     return NULL;
01922 }
01923 
01924 void
01925 SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
01926 {
01927     if (spki && spki->arena) {
01928        PORT_FreeArena(spki->arena, PR_FALSE);
01929     }
01930 }
01931 
01932 /*
01933  * this only works for RSA keys... need to do something
01934  * similiar to CERT_ExtractPublicKey for other key times.
01935  */
01936 SECKEYPublicKey *
01937 SECKEY_DecodeDERPublicKey(SECItem *pubkder)
01938 {
01939     PRArenaPool *arena;
01940     SECKEYPublicKey *pubk;
01941     SECStatus rv;
01942     SECItem newPubkder;
01943 
01944     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
01945     if (arena == NULL) {
01946        PORT_SetError (SEC_ERROR_NO_MEMORY);
01947        return NULL;
01948     }
01949 
01950     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
01951     if (pubk != NULL) {
01952        pubk->arena = arena;
01953        pubk->pkcs11Slot = NULL;
01954        pubk->pkcs11ID = 0;
01955        prepare_rsa_pub_key_for_asn1(pubk);
01956         /* copy the DER into the arena, since Quick DER returns data that points
01957            into the DER input, which may get freed by the caller */
01958         rv = SECITEM_CopyItem(arena, &newPubkder, pubkder);
01959         if ( rv == SECSuccess ) {
01960            rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,
01961                             &newPubkder);
01962         }
01963        if (rv == SECSuccess)
01964            return pubk;
01965        SECKEY_DestroyPublicKey (pubk);
01966     } else {
01967        PORT_SetError (SEC_ERROR_NO_MEMORY);
01968     }
01969 
01970     PORT_FreeArena (arena, PR_FALSE);
01971     return NULL;
01972 }
01973 
01974 /*
01975  * Decode a base64 ascii encoded DER encoded public key.
01976  */
01977 SECKEYPublicKey *
01978 SECKEY_ConvertAndDecodePublicKey(char *pubkstr)
01979 {
01980     SECKEYPublicKey *pubk;
01981     SECStatus rv;
01982     SECItem der;
01983 
01984     rv = ATOB_ConvertAsciiToItem (&der, pubkstr);
01985     if (rv != SECSuccess)
01986        return NULL;
01987 
01988     pubk = SECKEY_DecodeDERPublicKey (&der);
01989 
01990     PORT_Free (der.data);
01991     return pubk;
01992 }
01993 
01994 SECItem *
01995 SECKEY_EncodeDERSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
01996 {
01997     CERTSubjectPublicKeyInfo *spki=NULL;
01998     SECItem *spkiDER=NULL;
01999 
02000     /* get the subjectpublickeyinfo */
02001     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
02002     if( spki == NULL ) {
02003        goto finish;
02004     }
02005 
02006     /* DER-encode the subjectpublickeyinfo */
02007     spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
02008                                    CERT_SubjectPublicKeyInfoTemplate);
02009 finish:
02010     if (spki!=NULL) {
02011        SECKEY_DestroySubjectPublicKeyInfo(spki);
02012     }
02013     return spkiDER;
02014 }
02015 
02016 
02017 CERTSubjectPublicKeyInfo *
02018 SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider)
02019 {
02020     PRArenaPool *arena;
02021     CERTSubjectPublicKeyInfo *spki;
02022     SECStatus rv;
02023     SECItem newSpkider;
02024 
02025     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
02026     if (arena == NULL) {
02027        PORT_SetError(SEC_ERROR_NO_MEMORY);
02028        return NULL;
02029     }
02030 
02031     spki = (CERTSubjectPublicKeyInfo *)
02032               PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo));
02033     if (spki != NULL) {
02034        spki->arena = arena;
02035 
02036         /* copy the DER into the arena, since Quick DER returns data that points
02037            into the DER input, which may get freed by the caller */
02038         rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
02039         if ( rv == SECSuccess ) {
02040             rv = SEC_QuickDERDecodeItem(arena,spki,
02041                                 CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
02042         }
02043        if (rv == SECSuccess)
02044            return spki;
02045     } else {
02046        PORT_SetError(SEC_ERROR_NO_MEMORY);
02047     }
02048 
02049     PORT_FreeArena(arena, PR_FALSE);
02050     return NULL;
02051 }
02052 
02053 /*
02054  * Decode a base64 ascii encoded DER encoded subject public key info.
02055  */
02056 CERTSubjectPublicKeyInfo *
02057 SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr)
02058 {
02059     CERTSubjectPublicKeyInfo *spki;
02060     SECStatus rv;
02061     SECItem der;
02062 
02063     rv = ATOB_ConvertAsciiToItem(&der, spkistr);
02064     if (rv != SECSuccess)
02065        return NULL;
02066 
02067     spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
02068 
02069     PORT_Free(der.data);
02070     return spki;
02071 }
02072 
02073 /*
02074  * Decode a base64 ascii encoded DER encoded public key and challenge
02075  * Verify digital signature and make sure challenge matches
02076  */
02077 CERTSubjectPublicKeyInfo *
02078 SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
02079                                                         void *wincx)
02080 {
02081     CERTSubjectPublicKeyInfo *spki = NULL;
02082     CERTPublicKeyAndChallenge pkac;
02083     SECStatus rv;
02084     SECItem signedItem;
02085     PRArenaPool *arena = NULL;
02086     CERTSignedData sd;
02087     SECItem sig;
02088     SECKEYPublicKey *pubKey = NULL;
02089     unsigned int len;
02090     
02091     signedItem.data = NULL;
02092     
02093     /* convert the base64 encoded data to binary */
02094     rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
02095     if (rv != SECSuccess) {
02096        goto loser;
02097     }
02098 
02099     /* create an arena */
02100     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
02101     if (arena == NULL) {
02102        goto loser;
02103     }
02104 
02105     /* decode the outer wrapping of signed data */
02106     PORT_Memset(&sd, 0, sizeof(CERTSignedData));
02107     rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem );
02108     if ( rv ) {
02109        goto loser;
02110     }
02111 
02112     /* decode the public key and challenge wrapper */
02113     PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
02114     rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate, 
02115                          &sd.data);
02116     if ( rv ) {
02117        goto loser;
02118     }
02119 
02120     /* decode the subject public key info */
02121     spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
02122     if ( spki == NULL ) {
02123        goto loser;
02124     }
02125     
02126     /* get the public key */
02127     pubKey = seckey_ExtractPublicKey(spki);
02128     if ( pubKey == NULL ) {
02129        goto loser;
02130     }
02131 
02132     /* check the signature */
02133     sig = sd.signature;
02134     DER_ConvertBitString(&sig);
02135     rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
02136                      &sd.signatureAlgorithm, NULL, wincx);
02137     if ( rv != SECSuccess ) {
02138        goto loser;
02139     }
02140     
02141     /* check the challenge */
02142     if ( challenge ) {
02143        len = PORT_Strlen(challenge);
02144        /* length is right */
02145        if ( len != pkac.challenge.len ) {
02146            goto loser;
02147        }
02148        /* actual data is right */
02149        if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) {
02150            goto loser;
02151        }
02152     }
02153     goto done;
02154 
02155 loser:
02156     /* make sure that we return null if we got an error */
02157     if ( spki ) {
02158        SECKEY_DestroySubjectPublicKeyInfo(spki);
02159     }
02160     spki = NULL;
02161     
02162 done:
02163     if ( signedItem.data ) {
02164        PORT_Free(signedItem.data);
02165     }
02166     if ( arena ) {
02167        PORT_FreeArena(arena, PR_FALSE);
02168     }
02169     if ( pubKey ) {
02170        SECKEY_DestroyPublicKey(pubKey);
02171     }
02172     
02173     return spki;
02174 }
02175 
02176 void
02177 SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
02178                           PRBool freeit)
02179 {
02180     PRArenaPool *poolp;
02181 
02182     if(pvk != NULL) {
02183        if(pvk->arena) {
02184            poolp = pvk->arena;
02185            /* zero structure since PORT_FreeArena does not support
02186             * this yet.
02187             */
02188            PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
02189            PORT_Memset((char *)pvk, 0, sizeof(*pvk));
02190            if(freeit == PR_TRUE) {
02191               PORT_FreeArena(poolp, PR_TRUE);
02192            } else {
02193               pvk->arena = poolp;
02194            }
02195        } else {
02196            SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
02197            SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
02198            SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
02199            PORT_Memset((char *)pvk, 0, sizeof(pvk));
02200            if(freeit == PR_TRUE) {
02201               PORT_Free(pvk);
02202            }
02203        }
02204     }
02205 }
02206 
02207 void
02208 SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
02209                                   PRBool freeit)
02210 {
02211     PRArenaPool *poolp;
02212 
02213     if(epki != NULL) {
02214        if(epki->arena) {
02215            poolp = epki->arena;
02216            /* zero structure since PORT_FreeArena does not support
02217             * this yet.
02218             */
02219            PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
02220            PORT_Memset((char *)epki, 0, sizeof(*epki));
02221            if(freeit == PR_TRUE) {
02222               PORT_FreeArena(poolp, PR_TRUE);
02223            } else {
02224               epki->arena = poolp;
02225            }
02226        } else {
02227            SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
02228            SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
02229            PORT_Memset((char *)epki, 0, sizeof(epki));
02230            if(freeit == PR_TRUE) {
02231               PORT_Free(epki);
02232            }
02233        }
02234     }
02235 }
02236 
02237 SECStatus
02238 SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp,
02239                        SECKEYPrivateKeyInfo *to,
02240                        SECKEYPrivateKeyInfo *from)
02241 {
02242     SECStatus rv = SECFailure;
02243 
02244     if((to == NULL) || (from == NULL)) {
02245        return SECFailure;
02246     }
02247 
02248     rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
02249     if(rv != SECSuccess) {
02250        return SECFailure;
02251     }
02252     rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
02253     if(rv != SECSuccess) {
02254        return SECFailure;
02255     }
02256     rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
02257 
02258     return rv;
02259 }
02260 
02261 SECStatus
02262 SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp, 
02263                                SECKEYEncryptedPrivateKeyInfo *to,
02264                                SECKEYEncryptedPrivateKeyInfo *from)
02265 {
02266     SECStatus rv = SECFailure;
02267 
02268     if((to == NULL) || (from == NULL)) {
02269        return SECFailure;
02270     }
02271 
02272     rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
02273     if(rv != SECSuccess) {
02274        return SECFailure;
02275     }
02276     rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
02277 
02278     return rv;
02279 }
02280 
02281 KeyType
02282 SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey)
02283 {
02284    return privKey->keyType;
02285 }
02286 
02287 KeyType
02288 SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey)
02289 {
02290    return pubKey->keyType;
02291 }
02292 
02293 SECKEYPublicKey*
02294 SECKEY_ImportDERPublicKey(SECItem *derKey, CK_KEY_TYPE type)
02295 {
02296     SECKEYPublicKey *pubk = NULL;
02297     SECStatus rv = SECFailure;
02298     SECItem newDerKey;
02299 
02300     if (!derKey) {
02301         return NULL;
02302     } 
02303 
02304     pubk = PORT_ZNew(SECKEYPublicKey);
02305     if(pubk == NULL) {
02306         goto finish;
02307     }
02308     pubk->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
02309     if (NULL == pubk->arena) {
02310         goto finish;
02311     }
02312     rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
02313     if (SECSuccess != rv) {
02314         goto finish;
02315     }
02316 
02317     pubk->pkcs11Slot = NULL;
02318     pubk->pkcs11ID = CK_INVALID_HANDLE;
02319 
02320     switch( type ) {
02321       case CKK_RSA:
02322        prepare_rsa_pub_key_for_asn1(pubk);
02323         rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
02324         pubk->keyType = rsaKey;
02325         break;
02326       case CKK_DSA:
02327        prepare_dsa_pub_key_for_asn1(pubk);
02328         rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
02329         pubk->keyType = dsaKey;
02330         break;
02331       case CKK_DH:
02332        prepare_dh_pub_key_for_asn1(pubk);
02333         rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
02334         pubk->keyType = dhKey;
02335         break;
02336       default:
02337         rv = SECFailure;
02338         break;
02339     }
02340 
02341 finish:
02342     if( rv != SECSuccess && pubk != NULL) {
02343         if (pubk->arena) {
02344             PORT_FreeArena(pubk->arena, PR_TRUE);
02345         }
02346         PORT_Free(pubk);
02347         pubk = NULL;
02348     }
02349     return pubk;
02350 }
02351 
02352 SECKEYPrivateKeyList*
02353 SECKEY_NewPrivateKeyList(void)
02354 {
02355     PRArenaPool *arena = NULL;
02356     SECKEYPrivateKeyList *ret = NULL;
02357 
02358     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
02359     if ( arena == NULL ) {
02360         goto loser;
02361     }
02362 
02363     ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
02364                 sizeof(SECKEYPrivateKeyList));
02365     if ( ret == NULL ) {
02366         goto loser;
02367     }
02368 
02369     ret->arena = arena;
02370 
02371     PR_INIT_CLIST(&ret->list);
02372 
02373     return(ret);
02374 
02375 loser:
02376     if ( arena != NULL ) {
02377         PORT_FreeArena(arena, PR_FALSE);
02378     }
02379 
02380     return(NULL);
02381 }
02382 
02383 void
02384 SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys)
02385 {
02386     while( !PR_CLIST_IS_EMPTY(&keys->list) ) {
02387         SECKEY_RemovePrivateKeyListNode(
02388             (SECKEYPrivateKeyListNode*)(PR_LIST_HEAD(&keys->list)) );
02389     }
02390 
02391     PORT_FreeArena(keys->arena, PR_FALSE);
02392 
02393     return;
02394 }
02395 
02396 
02397 void
02398 SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node)
02399 {
02400     PR_ASSERT(node->key);
02401     SECKEY_DestroyPrivateKey(node->key);
02402     node->key = NULL;
02403     PR_REMOVE_LINK(&node->links);
02404     return;
02405 
02406 }
02407 
02408 SECStatus
02409 SECKEY_AddPrivateKeyToListTail( SECKEYPrivateKeyList *list,
02410                                 SECKEYPrivateKey *key)
02411 {
02412     SECKEYPrivateKeyListNode *node;
02413 
02414     node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena,
02415                 sizeof(SECKEYPrivateKeyListNode));
02416     if ( node == NULL ) {
02417         goto loser;
02418     }
02419 
02420     PR_INSERT_BEFORE(&node->links, &list->list);
02421     node->key = key;
02422     return(SECSuccess);
02423 
02424 loser:
02425     return(SECFailure);
02426 }
02427 
02428 
02429 SECKEYPublicKeyList*
02430 SECKEY_NewPublicKeyList(void)
02431 {
02432     PRArenaPool *arena = NULL;
02433     SECKEYPublicKeyList *ret = NULL;
02434 
02435     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
02436     if ( arena == NULL ) {
02437         goto loser;
02438     }
02439 
02440     ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena,
02441                 sizeof(SECKEYPublicKeyList));
02442     if ( ret == NULL ) {
02443         goto loser;
02444     }
02445 
02446     ret->arena = arena;
02447 
02448     PR_INIT_CLIST(&ret->list);
02449 
02450     return(ret);
02451 
02452 loser:
02453     if ( arena != NULL ) {
02454         PORT_FreeArena(arena, PR_FALSE);
02455     }
02456 
02457     return(NULL);
02458 }
02459 
02460 void
02461 SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys)
02462 {
02463     while( !PR_CLIST_IS_EMPTY(&keys->list) ) {
02464         SECKEY_RemovePublicKeyListNode(
02465             (SECKEYPublicKeyListNode*)(PR_LIST_HEAD(&keys->list)) );
02466     }
02467 
02468     PORT_FreeArena(keys->arena, PR_FALSE);
02469 
02470     return;
02471 }
02472 
02473 
02474 void
02475 SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node)
02476 {
02477     PR_ASSERT(node->key);
02478     SECKEY_DestroyPublicKey(node->key);
02479     node->key = NULL;
02480     PR_REMOVE_LINK(&node->links);
02481     return;
02482 
02483 }
02484 
02485 SECStatus
02486 SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list,
02487                                 SECKEYPublicKey *key)
02488 {
02489     SECKEYPublicKeyListNode *node;
02490 
02491     node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena,
02492                 sizeof(SECKEYPublicKeyListNode));
02493     if ( node == NULL ) {
02494         goto loser;
02495     }
02496 
02497     PR_INSERT_BEFORE(&node->links, &list->list);
02498     node->key = key;
02499     return(SECSuccess);
02500 
02501 loser:
02502     return(SECFailure);
02503 }
02504 
02505 #define SECKEY_CacheAttribute(key, attribute) \
02506     if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute)) { \
02507         key->staticflags |= SECKEY_##attribute; \
02508     } else { \
02509         key->staticflags &= (~SECKEY_##attribute); \
02510     }
02511 
02512 SECStatus
02513 SECKEY_CacheStaticFlags(SECKEYPrivateKey* key)
02514 {
02515     SECStatus rv = SECFailure;
02516     if (key && key->pkcs11Slot && key->pkcs11ID) {
02517         key->staticflags |= SECKEY_Attributes_Cached;
02518         SECKEY_CacheAttribute(key, CKA_PRIVATE);
02519         rv = SECSuccess;
02520     }
02521     return rv;
02522 }