Back to index

lightning-sunbird  0.9+nobinonly
lowcert.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 Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * Certificate handling code
00040  *
00041  * $Id: lowcert.c,v 1.20.2.1 2006/04/04 18:44:18 wtchang%redhat.com Exp $
00042  */
00043 
00044 #include "seccomon.h"
00045 #include "secder.h"
00046 #include "nssilock.h"
00047 #include "prmon.h"
00048 #include "prtime.h"
00049 #include "lowkeyi.h"
00050 #include "pcert.h"
00051 #include "secasn1.h"
00052 #include "secoid.h"
00053 #include "secerr.h"
00054 #include "softoken.h"
00055 
00056 
00057 static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
00058     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
00059     { SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
00060           SECOID_AlgorithmIDTemplate },
00061     { SEC_ASN1_BIT_STRING,
00062           offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
00063     { 0, }
00064 };
00065 
00066 static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
00067     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
00068     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
00069     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
00070     { 0, }
00071 };
00072 static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
00073     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
00074     { 0, }
00075 };
00076 static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
00077     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
00078     { 0, }
00079 };
00080 
00081 /*
00082  * See bugzilla bug 125359
00083  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
00084  * all of the templates above that en/decode into integers must be converted
00085  * from ASN.1's signed integer type.  This is done by marking either the
00086  * source or destination (encoding or decoding, respectively) type as
00087  * siUnsignedInteger.
00088  */
00089 
00090 static void
00091 prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
00092 {
00093     pubk->u.rsa.modulus.type = siUnsignedInteger;
00094     pubk->u.rsa.publicExponent.type = siUnsignedInteger;
00095 }
00096 
00097 static void
00098 prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
00099 {
00100     pubk->u.dsa.publicValue.type = siUnsignedInteger;
00101     pubk->u.dsa.params.prime.type = siUnsignedInteger;
00102     pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
00103     pubk->u.dsa.params.base.type = siUnsignedInteger;
00104 }
00105 
00106 static void
00107 prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
00108 {
00109     pubk->u.dh.prime.type = siUnsignedInteger;
00110     pubk->u.dh.base.type = siUnsignedInteger;
00111     pubk->u.dh.publicValue.type = siUnsignedInteger;
00112 }
00113 
00114 /*
00115  * Allow use of default cert database, so that apps(such as mozilla) don't
00116  * have to pass the handle all over the place.
00117  */
00118 static NSSLOWCERTCertDBHandle *default_pcert_db_handle = 0;
00119 
00120 void
00121 nsslowcert_SetDefaultCertDB(NSSLOWCERTCertDBHandle *handle)
00122 {
00123     default_pcert_db_handle = handle;
00124     
00125     return;
00126 }
00127 
00128 NSSLOWCERTCertDBHandle *
00129 nsslowcert_GetDefaultCertDB(void)
00130 {
00131     return(default_pcert_db_handle);
00132 }
00133 
00134 /*
00135  * simple cert decoder to avoid the cost of asn1 engine
00136  */ 
00137 static unsigned char *
00138 nsslowcert_dataStart(unsigned char *buf, unsigned int length, 
00139                      unsigned int *data_length, PRBool includeTag,
00140                         unsigned char* rettag) {
00141     unsigned char tag;
00142     unsigned int used_length= 0;
00143 
00144     tag = buf[used_length++];
00145 
00146     if (rettag) {
00147         *rettag = tag;
00148     }
00149 
00150     /* blow out when we come to the end */
00151     if (tag == 0) {
00152        return NULL;
00153     }
00154 
00155     *data_length = buf[used_length++];
00156 
00157     if (*data_length&0x80) {
00158        int  len_count = *data_length & 0x7f;
00159 
00160        *data_length = 0;
00161 
00162        while (len_count-- > 0) {
00163            *data_length = (*data_length << 8) | buf[used_length++];
00164        } 
00165     }
00166 
00167     if (*data_length > (length-used_length) ) {
00168        *data_length = length-used_length;
00169        return NULL;
00170     }
00171     if (includeTag) *data_length += used_length;
00172 
00173     return (buf + (includeTag ? 0 : used_length));      
00174 }
00175 
00176 static void SetTimeType(SECItem* item, unsigned char tagtype)
00177 {
00178     switch (tagtype) {
00179         case SEC_ASN1_UTC_TIME:
00180             item->type = siUTCTime;
00181             break;
00182 
00183         case SEC_ASN1_GENERALIZED_TIME:
00184             item->type = siGeneralizedTime;
00185             break;
00186 
00187         default:
00188             PORT_Assert(0);
00189             break;
00190     }
00191 }
00192 
00193 static int
00194 nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
00195        SECItem *notBefore, SECItem *notAfter)
00196 {
00197     unsigned char tagtype;
00198     notBefore->data = nsslowcert_dataStart(buf,buf_length,
00199                                           &notBefore->len,PR_FALSE, &tagtype);
00200     if (notBefore->data == NULL) return SECFailure;
00201     SetTimeType(notBefore, tagtype);
00202     buf_length -= (notBefore->data-buf) + notBefore->len;
00203     buf = notBefore->data + notBefore->len;
00204     notAfter->data = nsslowcert_dataStart(buf,buf_length,
00205                                           &notAfter->len,PR_FALSE, &tagtype);
00206     if (notAfter->data == NULL) return SECFailure;
00207     SetTimeType(notAfter, tagtype);
00208     return SECSuccess;
00209 }
00210 
00211 static int
00212 nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
00213        SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
00214        SECItem *valid, SECItem *subjkey)
00215 {
00216     unsigned char *buf;
00217     unsigned int buf_length;
00218     unsigned char *dummy;
00219     unsigned int dummylen;
00220 
00221     /* get past the signature wrap */
00222     buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
00223     if (buf == NULL) return SECFailure;
00224     /* get into the raw cert data */
00225     buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
00226     if (buf == NULL) return SECFailure;
00227     /* skip past any optional version number */
00228     if ((buf[0] & 0xa0) == 0xa0) {
00229        dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
00230        if (dummy == NULL) return SECFailure;
00231        buf_length -= (dummy-buf) + dummylen;
00232        buf = dummy + dummylen;
00233     }
00234     /* serial number */
00235     if (derSN) {
00236        derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
00237     }
00238     serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
00239     if (serial->data == NULL) return SECFailure;
00240     buf_length -= (serial->data-buf) + serial->len;
00241     buf = serial->data + serial->len;
00242     /* skip the OID */
00243     dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
00244     if (dummy == NULL) return SECFailure;
00245     buf_length -= (dummy-buf) + dummylen;
00246     buf = dummy + dummylen;
00247     /* issuer */
00248     issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
00249     if (issuer->data == NULL) return SECFailure;
00250     buf_length -= (issuer->data-buf) + issuer->len;
00251     buf = issuer->data + issuer->len;
00252 
00253     /* only wanted issuer/SN */
00254     if (valid == NULL) {
00255        return SECSuccess;
00256     }
00257     /* validity */
00258     valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
00259     if (valid->data == NULL) return SECFailure;
00260     buf_length -= (valid->data-buf) + valid->len;
00261     buf = valid->data + valid->len;
00262     /*subject */
00263     subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
00264     if (subject->data == NULL) return SECFailure;
00265     buf_length -= (subject->data-buf) + subject->len;
00266     buf = subject->data + subject->len;
00267     /* subject  key info */
00268     subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
00269     if (subjkey->data == NULL) return SECFailure;
00270     buf_length -= (subjkey->data-buf) + subjkey->len;
00271     buf = subjkey->data + subjkey->len;
00272     return SECSuccess;
00273 }
00274 
00275 SECStatus
00276 nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
00277 {
00278     int rv;
00279     NSSLOWCERTValidity validity;
00280 
00281     rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
00282                             &validity.notBefore,&validity.notAfter);
00283     if (rv != SECSuccess) {
00284        return rv;
00285     }
00286     
00287     /* convert DER not-before time */
00288     rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
00289     if (rv) {
00290         return(SECFailure);
00291     }
00292     
00293     /* convert DER not-after time */
00294     rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
00295     if (rv) {
00296         return(SECFailure);
00297     }
00298 
00299     return(SECSuccess);
00300 }
00301 
00302 /*
00303  * is certa newer than certb?  If one is expired, pick the other one.
00304  */
00305 PRBool
00306 nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
00307 {
00308     PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
00309     SECStatus rv;
00310     PRBool newerbefore, newerafter;
00311     
00312     rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
00313     if ( rv != SECSuccess ) {
00314        return(PR_FALSE);
00315     }
00316     
00317     rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
00318     if ( rv != SECSuccess ) {
00319        return(PR_TRUE);
00320     }
00321 
00322     newerbefore = PR_FALSE;
00323     if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
00324        newerbefore = PR_TRUE;
00325     }
00326 
00327     newerafter = PR_FALSE;
00328     if ( LL_CMP(notAfterA, >, notAfterB) ) {
00329        newerafter = PR_TRUE;
00330     }
00331     
00332     if ( newerbefore && newerafter ) {
00333        return(PR_TRUE);
00334     }
00335     
00336     if ( ( !newerbefore ) && ( !newerafter ) ) {
00337        return(PR_FALSE);
00338     }
00339 
00340     /* get current time */
00341     now = PR_Now();
00342 
00343     if ( newerbefore ) {
00344        /* cert A was issued after cert B, but expires sooner */
00345        /* if A is expired, then pick B */
00346        if ( LL_CMP(notAfterA, <, now ) ) {
00347            return(PR_FALSE);
00348        }
00349        return(PR_TRUE);
00350     } else {
00351        /* cert B was issued after cert A, but expires sooner */
00352        /* if B is expired, then pick A */
00353        if ( LL_CMP(notAfterB, <, now ) ) {
00354            return(PR_TRUE);
00355        }
00356        return(PR_FALSE);
00357     }
00358 }
00359 
00360 #define SOFT_DEFAULT_CHUNKSIZE 2048
00361 
00362 static SECStatus
00363 nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, 
00364                            SECItem *issuer, SECItem *sn, SECItem *key)
00365 {
00366     unsigned int len = sn->len + issuer->len;
00367 
00368     if (!arena) {
00369         PORT_SetError(SEC_ERROR_INVALID_ARGS);
00370        goto loser;
00371     }
00372     key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
00373     if ( !key->data ) {
00374        goto loser;
00375     }
00376 
00377     key->len = len;
00378     /* copy the serialNumber */
00379     PORT_Memcpy(key->data, sn->data, sn->len);
00380 
00381     /* copy the issuer */
00382     PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
00383 
00384     return(SECSuccess);
00385 
00386 loser:
00387     return(SECFailure);
00388 }
00389 
00390 static SECStatus
00391 nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
00392        int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
00393 {
00394     unsigned int len = sn->len + issuer->len;
00395 
00396     key->data = pkcs11_allocStaticData(len, space, spaceLen);
00397     if ( !key->data ) {
00398        goto loser;
00399     }
00400 
00401     key->len = len;
00402     /* copy the serialNumber */
00403     PORT_Memcpy(key->data, sn->data, sn->len);
00404 
00405     /* copy the issuer */
00406     PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
00407 
00408     return(SECSuccess);
00409 
00410 loser:
00411     return(SECFailure);
00412 }
00413 
00414 
00415 
00416 /*
00417  * take a DER certificate and decode it into a certificate structure
00418  */
00419 NSSLOWCERTCertificate *
00420 nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
00421 {
00422     NSSLOWCERTCertificate *cert;
00423     int rv;
00424 
00425     /* allocate the certificate structure */
00426     cert = nsslowcert_CreateCert();
00427     
00428     if ( !cert ) {
00429        goto loser;
00430     }
00431     
00432        /* point to passed in DER data */
00433     cert->derCert = *derSignedCert;
00434     cert->nickname = NULL;
00435     cert->certKey.data = NULL;
00436     cert->referenceCount = 1;
00437 
00438     /* decode the certificate info */
00439     rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
00440        &cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
00441        &cert->validity, &cert->derSubjKeyInfo);
00442 
00443     /* cert->subjectKeyID;   x509v3 subject key identifier */
00444     cert->subjectKeyID.data = NULL;
00445     cert->subjectKeyID.len = 0;
00446     cert->dbEntry = NULL;
00447     cert ->trust = NULL;
00448     cert ->dbhandle = NULL;
00449 
00450     /* generate and save the database key for the cert */
00451     rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
00452               sizeof(cert->certKeySpace), &cert->derIssuer, 
00453               &cert->serialNumber, &cert->certKey);
00454     if ( rv ) {
00455        goto loser;
00456     }
00457 
00458     /* set the nickname */
00459     if ( nickname == NULL ) {
00460        cert->nickname = NULL;
00461     } else {
00462        /* copy and install the nickname */
00463        cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
00464                             sizeof(cert->nicknameSpace));
00465     }
00466 
00467 #ifdef FIXME
00468     /* initialize the subjectKeyID */
00469     rv = cert_GetKeyID(cert);
00470     if ( rv != SECSuccess ) {
00471        goto loser;
00472     }
00473 
00474     /* set the email address */
00475     cert->emailAddr = CERT_GetCertificateEmailAddress(cert);
00476     
00477 #endif
00478     
00479     cert->referenceCount = 1;
00480     
00481     return(cert);
00482     
00483 loser:
00484     if (cert) {
00485        nsslowcert_DestroyCertificate(cert);
00486     }
00487     
00488     return(0);
00489 }
00490 
00491 char *
00492 nsslowcert_FixupEmailAddr(char *emailAddr)
00493 {
00494     char *retaddr;
00495     char *str;
00496 
00497     if ( emailAddr == NULL ) {
00498        return(NULL);
00499     }
00500     
00501     /* copy the string */
00502     str = retaddr = PORT_Strdup(emailAddr);
00503     if ( str == NULL ) {
00504        return(NULL);
00505     }
00506     
00507     /* make it lower case */
00508     while ( *str ) {
00509        *str = tolower( *str );
00510        str++;
00511     }
00512     
00513     return(retaddr);
00514 }
00515 
00516 
00517 /*
00518  * Generate a database key, based on serial number and issuer, from a
00519  * DER certificate.
00520  */
00521 SECStatus
00522 nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
00523 {
00524     int rv;
00525     NSSLOWCERTCertKey certkey;
00526 
00527     PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));    
00528 
00529     rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
00530        &certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
00531 
00532     if ( rv ) {
00533        goto loser;
00534     }
00535 
00536     return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
00537                                &certkey.serialNumber, key));
00538 loser:
00539     return(SECFailure);
00540 }
00541 
00542 NSSLOWKEYPublicKey *
00543 nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
00544 {
00545     NSSLOWCERTSubjectPublicKeyInfo spki;
00546     NSSLOWKEYPublicKey *pubk;
00547     SECItem os;
00548     SECStatus rv;
00549     PRArenaPool *arena;
00550     SECOidTag tag;
00551     SECItem newDerSubjKeyInfo;
00552 
00553     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
00554     if (arena == NULL)
00555         return NULL;
00556 
00557     pubk = (NSSLOWKEYPublicKey *) 
00558               PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
00559     if (pubk == NULL) {
00560         PORT_FreeArena (arena, PR_FALSE);
00561         return NULL;
00562     }
00563 
00564     pubk->arena = arena;
00565     PORT_Memset(&spki,0,sizeof(spki));
00566 
00567     /* copy the DER into the arena, since Quick DER returns data that points
00568        into the DER input, which may get freed by the caller */
00569     rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
00570     if ( rv != SECSuccess ) {
00571         PORT_FreeArena (arena, PR_FALSE);
00572         return NULL;
00573     }
00574 
00575     /* we haven't bothered decoding the spki struct yet, do it now */
00576     rv = SEC_QuickDERDecodeItem(arena, &spki, 
00577               nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
00578     if (rv != SECSuccess) {
00579        PORT_FreeArena (arena, PR_FALSE);
00580        return NULL;
00581     }
00582 
00583     /* Convert bit string length from bits to bytes */
00584     os = spki.subjectPublicKey;
00585     DER_ConvertBitString (&os);
00586 
00587     tag = SECOID_GetAlgorithmTag(&spki.algorithm);
00588     switch ( tag ) {
00589       case SEC_OID_X500_RSA_ENCRYPTION:
00590       case SEC_OID_PKCS1_RSA_ENCRYPTION:
00591         pubk->keyType = NSSLOWKEYRSAKey;
00592         prepare_low_rsa_pub_key_for_asn1(pubk);
00593         rv = SEC_QuickDERDecodeItem(arena, pubk, 
00594                             nsslowcert_RSAPublicKeyTemplate, &os);
00595         if (rv == SECSuccess)
00596             return pubk;
00597         break;
00598       case SEC_OID_ANSIX9_DSA_SIGNATURE:
00599         pubk->keyType = NSSLOWKEYDSAKey;
00600         prepare_low_dsa_pub_key_for_asn1(pubk);
00601         rv = SEC_QuickDERDecodeItem(arena, pubk,
00602                              nsslowcert_DSAPublicKeyTemplate, &os);
00603         if (rv == SECSuccess) return pubk;
00604         break;
00605       case SEC_OID_X942_DIFFIE_HELMAN_KEY:
00606         pubk->keyType = NSSLOWKEYDHKey;
00607         prepare_low_dh_pub_key_for_asn1(pubk);
00608         rv = SEC_QuickDERDecodeItem(arena, pubk,
00609                              nsslowcert_DHPublicKeyTemplate, &os);
00610         if (rv == SECSuccess) return pubk;
00611         break;
00612 #ifdef NSS_ENABLE_ECC
00613       case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
00614         pubk->keyType = NSSLOWKEYECKey;
00615        /* Since PKCS#11 directly takes the DER encoding of EC params
00616         * and public value, we don't need any decoding here.
00617         */
00618         rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding, 
00619            &spki.algorithm.parameters);
00620         if ( rv != SECSuccess )
00621             break;   
00622 
00623        /* Fill out the rest of the ecParams structure 
00624         * based on the encoded params
00625         */
00626        if (EC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
00627            &pubk->u.ec.ecParams) != SECSuccess) 
00628            break;
00629 
00630         rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
00631        if (rv == SECSuccess) return pubk;
00632         break;
00633 #endif /* NSS_ENABLE_ECC */
00634       default:
00635         rv = SECFailure;
00636         break;
00637     }
00638 
00639     nsslowkey_DestroyPublicKey (pubk);
00640     return NULL;
00641 }
00642