Back to index

lightning-sunbird  0.9+nobinonly
pk11pk12.c
Go to the documentation of this file.
00001 
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape security libraries.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
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  * This file PKCS #12 fuctions that should really be moved to the
00039  * PKCS #12 directory, however we can't do that in a point release
00040  * because that will break binary compatibility, so we keep them here for now.
00041  */
00042 
00043 #include "seccomon.h"
00044 #include "secmod.h"
00045 #include "secmodi.h"
00046 #include "pkcs11.h"
00047 #include "pk11func.h"
00048 #include "secitem.h"
00049 #include "key.h"
00050 #include "secoid.h"
00051 #include "secasn1.h"
00052 #include "secerr.h"
00053 
00054 
00055 
00056 /* These data structures should move to a common .h file shared between the
00057  * wrappers and the pkcs 12 code. */
00058 
00059 /*
00060 ** RSA Raw Private Key structures
00061 */
00062 
00063 /* member names from PKCS#1, section 7.2 */
00064 struct SECKEYRSAPrivateKeyStr {
00065     PRArenaPool * arena;
00066     SECItem version;
00067     SECItem modulus;
00068     SECItem publicExponent;
00069     SECItem privateExponent;
00070     SECItem prime1;
00071     SECItem prime2;
00072     SECItem exponent1;
00073     SECItem exponent2;
00074     SECItem coefficient;
00075 };
00076 typedef struct SECKEYRSAPrivateKeyStr SECKEYRSAPrivateKey;
00077 
00078 
00079 /*
00080 ** DSA Raw Private Key structures
00081 */
00082 
00083 struct SECKEYDSAPrivateKeyStr {
00084     SECKEYPQGParams params;
00085     SECItem privateValue;
00086 };
00087 typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey;
00088 
00089 /*
00090 ** Diffie-Hellman Raw Private Key structures
00091 ** Structure member names suggested by PKCS#3.
00092 */
00093 struct SECKEYDHPrivateKeyStr {
00094     PRArenaPool * arena;
00095     SECItem prime;
00096     SECItem base;
00097     SECItem privateValue;
00098 };
00099 typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey;
00100 
00101 /*
00102 ** raw private key object
00103 */
00104 struct SECKEYRawPrivateKeyStr {
00105     PLArenaPool *arena;
00106     KeyType keyType;
00107     union {
00108         SECKEYRSAPrivateKey rsa;
00109         SECKEYDSAPrivateKey dsa;
00110         SECKEYDHPrivateKey  dh;
00111     } u;
00112 };
00113 typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey;
00114 
00115 
00116 /* ASN1 Templates for new decoder/encoder */
00117 /*
00118  * Attribute value for PKCS8 entries (static?)
00119  */
00120 const SEC_ASN1Template SECKEY_AttributeTemplate[] = {
00121     { SEC_ASN1_SEQUENCE,
00122         0, NULL, sizeof(SECKEYAttribute) },
00123     { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) },
00124     { SEC_ASN1_SET_OF, offsetof(SECKEYAttribute, attrValue),
00125         SEC_AnyTemplate },
00126     { 0 }
00127 };
00128 
00129 const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = {
00130     { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },
00131 };
00132 
00133 const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = {
00134     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) },
00135     { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo,version) },
00136     { SEC_ASN1_INLINE, offsetof(SECKEYPrivateKeyInfo,algorithm),
00137         SECOID_AlgorithmIDTemplate },
00138     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo,privateKey) },
00139     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00140         offsetof(SECKEYPrivateKeyInfo,attributes),
00141         SECKEY_SetOfAttributeTemplate },
00142     { 0 }
00143 };
00144 
00145 const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = {
00146     { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }
00147 };
00148 
00149 const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = {
00150     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) },
00151     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.version) },
00152     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.modulus) },
00153     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.publicExponent) },
00154     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.privateExponent) },
00155     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.prime1) },
00156     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.prime2) },
00157     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.exponent1) },
00158     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.exponent2) },
00159     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.coefficient) },
00160     { 0 }
00161 };
00162 
00163 const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = {
00164     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dsa.privateValue) },
00165 };
00166 
00167 const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = {
00168     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.privateValue) },
00169     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.base) },
00170     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.prime) },
00171 };
00172 
00173 const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
00174     { SEC_ASN1_SEQUENCE,
00175         0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) },
00176     { SEC_ASN1_INLINE,
00177         offsetof(SECKEYEncryptedPrivateKeyInfo,algorithm),
00178         SECOID_AlgorithmIDTemplate },
00179     { SEC_ASN1_OCTET_STRING,
00180         offsetof(SECKEYEncryptedPrivateKeyInfo,encryptedData) },
00181     { 0 }
00182 };
00183 
00184 const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
00185         { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
00186 };
00187 
00188 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate)
00189 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
00190 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
00191 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)
00192 
00193 /*
00194  * See bugzilla bug 125359
00195  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
00196  * all of the templates above that en/decode into integers must be converted
00197  * from ASN.1's signed integer type.  This is done by marking either the
00198  * source or destination (encoding or decoding, respectively) type as
00199  * siUnsignedInteger.
00200  */
00201 
00202 static void
00203 prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
00204 {
00205     key->u.rsa.modulus.type = siUnsignedInteger;
00206     key->u.rsa.publicExponent.type = siUnsignedInteger;
00207     key->u.rsa.privateExponent.type = siUnsignedInteger;
00208     key->u.rsa.prime1.type = siUnsignedInteger;
00209     key->u.rsa.prime2.type = siUnsignedInteger;
00210     key->u.rsa.exponent1.type = siUnsignedInteger;
00211     key->u.rsa.exponent2.type = siUnsignedInteger;
00212     key->u.rsa.coefficient.type = siUnsignedInteger;
00213 }
00214 
00215 static void
00216 prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
00217 {
00218     key->u.dsa.privateValue.type = siUnsignedInteger;
00219     key->u.dsa.params.prime.type = siUnsignedInteger;
00220     key->u.dsa.params.subPrime.type = siUnsignedInteger;
00221     key->u.dsa.params.base.type = siUnsignedInteger;
00222 }
00223 
00224 static void
00225 prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
00226 {
00227     key->u.dh.privateValue.type = siUnsignedInteger;
00228     key->u.dh.prime.type = siUnsignedInteger;
00229     key->u.dh.base.type = siUnsignedInteger;
00230 }
00231 
00232 
00233 SECStatus
00234 PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI, 
00235        SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
00236        PRBool isPrivate, unsigned int keyUsage, void *wincx) 
00237 {
00238     return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI,
00239        nickname, publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
00240 }
00241 
00242 SECStatus
00243 PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI, 
00244        SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
00245        PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey** privk,
00246        void *wincx) 
00247 {
00248     SECKEYPrivateKeyInfo *pki = NULL;
00249     PRArenaPool *temparena = NULL;
00250     SECStatus rv = SECFailure;
00251 
00252     temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00253     if (!temparena)
00254         return rv;
00255     pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo);
00256     if (!pki) {
00257         PORT_FreeArena(temparena, PR_FALSE);
00258         return rv;
00259     }
00260     pki->arena = temparena;
00261 
00262     rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
00263               derPKI);
00264     if( rv != SECSuccess ) {
00265        goto finish;
00266     }
00267 
00268     rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
00269               publicValue, isPerm, isPrivate, keyUsage, privk, wincx);
00270 
00271 finish:
00272     /* this zeroes the key and frees the arena */
00273     SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
00274     return rv;
00275 }
00276         
00277 SECStatus
00278 PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, 
00279        SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
00280        PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
00281        void *wincx) 
00282 {
00283     CK_BBOOL cktrue = CK_TRUE;
00284     CK_BBOOL ckfalse = CK_FALSE;
00285     CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
00286     CK_KEY_TYPE keyType = CKK_RSA;
00287     CK_OBJECT_HANDLE objectID;
00288     CK_ATTRIBUTE theTemplate[20];
00289     int templateCount = 0;
00290     SECStatus rv = SECFailure;
00291     PRArenaPool *arena;
00292     CK_ATTRIBUTE *attrs;
00293     CK_ATTRIBUTE *signedattr = NULL;
00294     int signedcount = 0;
00295     CK_ATTRIBUTE *ap;
00296     SECItem *ck_id = NULL;
00297 
00298     arena = PORT_NewArena(2048);
00299     if(!arena) {
00300        return SECFailure;
00301     }
00302 
00303     attrs = theTemplate;
00304 
00305 
00306     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
00307     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
00308     PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, 
00309                                           sizeof(CK_BBOOL) ); attrs++;
00310     PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, 
00311                                           sizeof(CK_BBOOL) ); attrs++;
00312     PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
00313                                            sizeof(CK_BBOOL) ); attrs++;
00314 
00315     switch (lpk->keyType) {
00316     case rsaKey:
00317            keyType = CKK_RSA;
00318            PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ?
00319                             &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
00320            PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ?
00321                             &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
00322            PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? 
00323                             &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
00324            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, 
00325                             (keyUsage & KU_DIGITAL_SIGNATURE) ? 
00326                             &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
00327            ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
00328            if (ck_id == NULL) {
00329               goto loser;
00330            }
00331            PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
00332            if (nickname) {
00333               PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; 
00334            } 
00335            signedattr = attrs;
00336            PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
00337                                           lpk->u.rsa.modulus.len); attrs++;
00338            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
00339                             lpk->u.rsa.publicExponent.data,
00340                             lpk->u.rsa.publicExponent.len); attrs++;
00341            PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, 
00342                             lpk->u.rsa.privateExponent.data,
00343                             lpk->u.rsa.privateExponent.len); attrs++;
00344            PK11_SETATTRS(attrs, CKA_PRIME_1, 
00345                             lpk->u.rsa.prime1.data,
00346                             lpk->u.rsa.prime1.len); attrs++;
00347            PK11_SETATTRS(attrs, CKA_PRIME_2, 
00348                             lpk->u.rsa.prime2.data,
00349                             lpk->u.rsa.prime2.len); attrs++;
00350            PK11_SETATTRS(attrs, CKA_EXPONENT_1, 
00351                             lpk->u.rsa.exponent1.data,
00352                             lpk->u.rsa.exponent1.len); attrs++;
00353            PK11_SETATTRS(attrs, CKA_EXPONENT_2, 
00354                             lpk->u.rsa.exponent2.data,
00355                             lpk->u.rsa.exponent2.len); attrs++;
00356            PK11_SETATTRS(attrs, CKA_COEFFICIENT, 
00357                             lpk->u.rsa.coefficient.data,
00358                             lpk->u.rsa.coefficient.len); attrs++;
00359            break;
00360     case dsaKey:
00361            keyType = CKK_DSA;
00362            /* To make our intenal PKCS #11 module work correctly with 
00363             * our database, we need to pass in the public key value for 
00364             * this dsa key. We have a netscape only CKA_ value to do this.
00365             * Only send it to internal slots */
00366            if( publicValue == NULL ) {
00367               goto loser;
00368            }
00369            if (PK11_IsInternal(slot)) {
00370                PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
00371                             publicValue->data, publicValue->len); attrs++;
00372            }
00373            PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++;
00374            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); attrs++;
00375            if(nickname) {
00376               PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
00377               attrs++; 
00378            } 
00379            ck_id = PK11_MakeIDFromPubKey(publicValue);
00380            if (ck_id == NULL) {
00381               goto loser;
00382            }
00383            PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
00384            signedattr = attrs;
00385            PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dsa.params.prime.data,
00386                             lpk->u.dsa.params.prime.len); attrs++;
00387            PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data,
00388                             lpk->u.dsa.params.subPrime.len); attrs++;
00389            PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dsa.params.base.data,
00390                                    lpk->u.dsa.params.base.len); attrs++;
00391            PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dsa.privateValue.data, 
00392                                    lpk->u.dsa.privateValue.len); attrs++;
00393            break;
00394      case dhKey:
00395            keyType = CKK_DH;
00396            /* To make our intenal PKCS #11 module work correctly with 
00397             * our database, we need to pass in the public key value for 
00398             * this dh key. We have a netscape only CKA_ value to do this.
00399             * Only send it to internal slots */
00400            if (PK11_IsInternal(slot)) {
00401                PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
00402                             publicValue->data, publicValue->len); attrs++;
00403            }
00404            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++;
00405            if(nickname) {
00406               PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
00407               attrs++; 
00408            } 
00409            ck_id = PK11_MakeIDFromPubKey(publicValue);
00410            if (ck_id == NULL) {
00411               goto loser;
00412            }
00413            PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
00414            signedattr = attrs;
00415            PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dh.prime.data,
00416                             lpk->u.dh.prime.len); attrs++;
00417            PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dh.base.data,
00418                                    lpk->u.dh.base.len); attrs++;
00419            PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dh.privateValue.data, 
00420                                    lpk->u.dh.privateValue.len); attrs++;
00421            break;
00422        /* what about fortezza??? */
00423     default:
00424            PORT_SetError(SEC_ERROR_BAD_KEY);
00425            goto loser;
00426     }
00427     templateCount = attrs - theTemplate;
00428     PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE));
00429     PORT_Assert(signedattr != NULL);
00430     signedcount = attrs - signedattr;
00431 
00432     for (ap=signedattr; signedcount; ap++, signedcount--) {
00433        pk11_SignedToUnsigned(ap);
00434     }
00435 
00436     rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,
00437                      theTemplate, templateCount, isPerm, &objectID);
00438 
00439     /* create and return a SECKEYPrivateKey */
00440     if( rv == SECSuccess && privk != NULL) {
00441        *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
00442        if( *privk == NULL ) {
00443            rv = SECFailure;
00444        }
00445     }
00446 loser:
00447     if (ck_id) {
00448        SECITEM_ZfreeItem(ck_id, PR_TRUE);
00449     }
00450     return rv;
00451 }
00452 
00453 SECStatus
00454 PK11_ImportPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, 
00455        SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
00456        PRBool isPrivate, unsigned int keyUsage, void *wincx) 
00457 {
00458     return PK11_ImportAndReturnPrivateKey(slot, lpk, nickname, publicValue,
00459        isPerm, isPrivate, keyUsage, NULL, wincx);
00460 }
00461 
00462 SECStatus
00463 PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
00464        SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
00465        PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
00466        SECKEYPrivateKey **privk, void *wincx) 
00467 {
00468     CK_KEY_TYPE keyType = CKK_RSA;
00469     SECStatus rv = SECFailure;
00470     SECKEYRawPrivateKey *lpk = NULL;
00471     const SEC_ASN1Template *keyTemplate, *paramTemplate;
00472     void *paramDest = NULL;
00473     PRArenaPool *arena;
00474 
00475     arena = PORT_NewArena(2048);
00476     if(!arena) {
00477        return SECFailure;
00478     }
00479 
00480     /* need to change this to use RSA/DSA keys */
00481     lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
00482                                             sizeof(SECKEYRawPrivateKey));
00483     if(lpk == NULL) {
00484        goto loser;
00485     }
00486     lpk->arena = arena;
00487 
00488     switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
00489        case SEC_OID_PKCS1_RSA_ENCRYPTION:
00490            prepare_rsa_priv_key_export_for_asn1(lpk);
00491            keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
00492            paramTemplate = NULL;
00493            paramDest = NULL;
00494            lpk->keyType = rsaKey;
00495            keyType = CKK_RSA;
00496            break;
00497        case SEC_OID_ANSIX9_DSA_SIGNATURE:
00498            prepare_dsa_priv_key_export_for_asn1(lpk);
00499            keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
00500            paramTemplate = SECKEY_PQGParamsTemplate;
00501            paramDest = &(lpk->u.dsa.params);
00502            lpk->keyType = dsaKey;
00503            keyType = CKK_DSA;
00504            break;
00505        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
00506            if(!publicValue) {
00507               goto loser;
00508            }
00509            prepare_dh_priv_key_export_for_asn1(lpk);
00510            keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
00511            paramTemplate = NULL;
00512            paramDest = NULL;
00513            lpk->keyType = dhKey;
00514            keyType = CKK_DH;
00515            break;
00516 
00517        default:
00518            keyTemplate   = NULL;
00519            paramTemplate = NULL;
00520            paramDest     = NULL;
00521            break;
00522     }
00523 
00524     if(!keyTemplate) {
00525        goto loser;
00526     }
00527 
00528     /* decode the private key and any algorithm parameters */
00529     rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
00530     if(rv != SECSuccess) {
00531        goto loser;
00532     }
00533     if(paramDest && paramTemplate) {
00534        rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate, 
00535                              &(pki->algorithm.parameters));
00536        if(rv != SECSuccess) {
00537            goto loser;
00538        }
00539     }
00540 
00541     rv = PK11_ImportAndReturnPrivateKey(slot,lpk,nickname,publicValue, isPerm, 
00542        isPrivate,  keyUsage, privk, wincx);
00543 
00544 
00545 loser:
00546     if (lpk!= NULL) {
00547        PORT_FreeArena(arena, PR_TRUE);
00548     }
00549 
00550     return rv;
00551 }
00552 
00553 SECStatus
00554 PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki, 
00555        SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
00556        PRBool isPrivate, unsigned int keyUsage, void *wincx) 
00557 {
00558     return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
00559        publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
00560 
00561 }
00562