Back to index

lightning-sunbird  0.9+nobinonly
pk11akey.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>, and
00024  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 /*
00040  * This file contains functions to manage asymetric keys, (public and
00041  * private keys).
00042  */
00043 #include "seccomon.h"
00044 #include "secmod.h"
00045 #include "secmodi.h"
00046 #include "secmodti.h"
00047 #include "pkcs11.h"
00048 #include "pkcs11t.h"
00049 #include "pk11func.h"
00050 #include "cert.h"
00051 #include "key.h"
00052 #include "secitem.h"
00053 #include "secasn1.h" 
00054 #include "secoid.h" 
00055 #include "secerr.h"
00056 #include "sslerr.h"
00057 #include "sechash.h"
00058 
00059 #include "secpkcs5.h"  
00060 #include "ec.h"
00061 
00062 /*
00063  * import a public key into the desired slot
00064  */
00065 CK_OBJECT_HANDLE
00066 PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, 
00067                                                         PRBool isToken)
00068 {
00069     CK_BBOOL cktrue = CK_TRUE;
00070     CK_BBOOL ckfalse = CK_FALSE;
00071     CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
00072     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
00073     CK_OBJECT_HANDLE objectID;
00074     CK_ATTRIBUTE theTemplate[10];
00075     CK_ATTRIBUTE *signedattr = NULL;
00076     CK_ATTRIBUTE *attrs = theTemplate;
00077     int signedcount = 0;
00078     int templateCount = 0;
00079     SECStatus rv;
00080 
00081     /* if we already have an object in the desired slot, use it */
00082     if (!isToken && pubKey->pkcs11Slot == slot) {
00083        return pubKey->pkcs11ID;
00084     }
00085 
00086     /* free the existing key */
00087     if (pubKey->pkcs11Slot != NULL) {
00088        PK11SlotInfo *oSlot = pubKey->pkcs11Slot;
00089        PK11_EnterSlotMonitor(oSlot);
00090        (void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
00091                                                  pubKey->pkcs11ID);
00092        PK11_ExitSlotMonitor(oSlot);
00093        PK11_FreeSlot(oSlot);
00094        pubKey->pkcs11Slot = NULL;
00095     }
00096     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
00097     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
00098     PK11_SETATTRS(attrs, CKA_TOKEN, isToken ? &cktrue : &ckfalse,
00099                                            sizeof(CK_BBOOL) ); attrs++;
00100 
00101     /* now import the key */
00102     {
00103         switch (pubKey->keyType) {
00104         case rsaKey:
00105            keyType = CKK_RSA;
00106            PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, sizeof(CK_BBOOL) ); attrs++;
00107            PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue, 
00108                                           sizeof(CK_BBOOL) ); attrs++;
00109            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); attrs++;
00110            signedattr = attrs;
00111            PK11_SETATTRS(attrs, CKA_MODULUS, pubKey->u.rsa.modulus.data,
00112                                     pubKey->u.rsa.modulus.len); attrs++;
00113            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
00114               pubKey->u.rsa.publicExponent.data,
00115                              pubKey->u.rsa.publicExponent.len); attrs++;
00116            break;
00117         case dsaKey:
00118            keyType = CKK_DSA;
00119            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
00120            signedattr = attrs;
00121            PK11_SETATTRS(attrs, CKA_PRIME,    pubKey->u.dsa.params.prime.data,
00122                             pubKey->u.dsa.params.prime.len); attrs++;
00123            PK11_SETATTRS(attrs,CKA_SUBPRIME,pubKey->u.dsa.params.subPrime.data,
00124                             pubKey->u.dsa.params.subPrime.len); attrs++;
00125            PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.dsa.params.base.data,
00126                                    pubKey->u.dsa.params.base.len); attrs++;
00127            PK11_SETATTRS(attrs, CKA_VALUE,    pubKey->u.dsa.publicValue.data, 
00128                                    pubKey->u.dsa.publicValue.len); attrs++;
00129            break;
00130        case fortezzaKey:
00131            keyType = CKK_DSA;
00132            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
00133            signedattr = attrs;
00134            PK11_SETATTRS(attrs, CKA_PRIME,pubKey->u.fortezza.params.prime.data,
00135                             pubKey->u.fortezza.params.prime.len); attrs++;
00136            PK11_SETATTRS(attrs,CKA_SUBPRIME,
00137                             pubKey->u.fortezza.params.subPrime.data,
00138                             pubKey->u.fortezza.params.subPrime.len);attrs++;
00139            PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.fortezza.params.base.data,
00140                             pubKey->u.fortezza.params.base.len); attrs++;
00141            PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.fortezza.DSSKey.data, 
00142                             pubKey->u.fortezza.DSSKey.len); attrs++;
00143             break;
00144         case dhKey:
00145            keyType = CKK_DH;
00146            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
00147            signedattr = attrs;
00148            PK11_SETATTRS(attrs, CKA_PRIME,    pubKey->u.dh.prime.data,
00149                             pubKey->u.dh.prime.len); attrs++;
00150            PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.dh.base.data,
00151                                    pubKey->u.dh.base.len); attrs++;
00152            PK11_SETATTRS(attrs, CKA_VALUE,    pubKey->u.dh.publicValue.data, 
00153                                    pubKey->u.dh.publicValue.len); attrs++;
00154            break;
00155         case ecKey:
00156            keyType = CKK_EC;
00157            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
00158            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
00159            signedattr = attrs;
00160            PK11_SETATTRS(attrs, CKA_EC_PARAMS, 
00161                         pubKey->u.ec.DEREncodedParams.data,
00162                         pubKey->u.ec.DEREncodedParams.len); attrs++;
00163            PK11_SETATTRS(attrs, CKA_EC_POINT, pubKey->u.ec.publicValue.data,
00164                        pubKey->u.ec.publicValue.len); attrs++;
00165            break;
00166        default:
00167            PORT_SetError( SEC_ERROR_BAD_KEY );
00168            return CK_INVALID_HANDLE;
00169        }
00170 
00171        templateCount = attrs - theTemplate;
00172        signedcount = attrs - signedattr;
00173        PORT_Assert(templateCount <= (sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)));
00174        for (attrs=signedattr; signedcount; attrs++, signedcount--) {
00175               pk11_SignedToUnsigned(attrs);
00176        } 
00177         rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
00178                                    templateCount, isToken, &objectID);
00179        if ( rv != SECSuccess) {
00180            return CK_INVALID_HANDLE;
00181        }
00182     }
00183 
00184     pubKey->pkcs11ID = objectID;
00185     pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
00186 
00187     return objectID;
00188 }
00189 
00190 /*
00191  * take an attribute and copy it into a secitem
00192  */
00193 static CK_RV
00194 pk11_Attr2SecItem(PRArenaPool *arena, CK_ATTRIBUTE *attr, SECItem *item) 
00195 {
00196     item->data = NULL;
00197 
00198     (void)SECITEM_AllocItem(arena, item, attr->ulValueLen);
00199     if (item->data == NULL) {
00200        return CKR_HOST_MEMORY;
00201     } 
00202     PORT_Memcpy(item->data, attr->pValue, item->len);
00203     return CKR_OK;
00204 }
00205 
00206 /*
00207  * extract a public key from a slot and id
00208  */
00209 SECKEYPublicKey *
00210 PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id)
00211 {
00212     CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
00213     PRArenaPool *arena;
00214     PRArenaPool *tmp_arena;
00215     SECKEYPublicKey *pubKey;
00216     int templateCount = 0;
00217     CK_KEY_TYPE pk11KeyType;
00218     CK_RV crv;
00219     CK_ATTRIBUTE template[8];
00220     CK_ATTRIBUTE *attrs= template;
00221     CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value;
00222     CK_ATTRIBUTE *ecparams;
00223 
00224     /* if we didn't know the key type, get it */
00225     if (keyType== nullKey) {
00226 
00227         pk11KeyType = PK11_ReadULongAttribute(slot,id,CKA_KEY_TYPE);
00228        if (pk11KeyType ==  CK_UNAVAILABLE_INFORMATION) {
00229            return NULL;
00230        }
00231        switch (pk11KeyType) {
00232        case CKK_RSA:
00233            keyType = rsaKey;
00234            break;
00235        case CKK_DSA:
00236            keyType = dsaKey;
00237            break;
00238        case CKK_DH:
00239            keyType = dhKey;
00240            break;
00241        case CKK_EC:
00242            keyType = ecKey;
00243            break;
00244        default:
00245            PORT_SetError( SEC_ERROR_BAD_KEY );
00246            return NULL;
00247        }
00248     }
00249 
00250 
00251     /* now we need to create space for the public key */
00252     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
00253     if (arena == NULL) return NULL;
00254     tmp_arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
00255     if (tmp_arena == NULL) {
00256        PORT_FreeArena (arena, PR_FALSE);
00257        return NULL;
00258     }
00259 
00260 
00261     pubKey = (SECKEYPublicKey *) 
00262                      PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
00263     if (pubKey == NULL) {
00264        PORT_FreeArena (arena, PR_FALSE);
00265        PORT_FreeArena (tmp_arena, PR_FALSE);
00266        return NULL;
00267     }
00268 
00269     pubKey->arena = arena;
00270     pubKey->keyType = keyType;
00271     pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
00272     pubKey->pkcs11ID = id;
00273     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, 
00274                                           sizeof(keyClass)); attrs++;
00275     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType, 
00276                                           sizeof(pk11KeyType) ); attrs++;
00277     switch (pubKey->keyType) {
00278     case rsaKey:
00279        modulus = attrs;
00280        PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); attrs++; 
00281        exponent = attrs;
00282        PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0); attrs++; 
00283 
00284        templateCount = attrs - template;
00285        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
00286        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
00287        if (crv != CKR_OK) break;
00288 
00289        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) {
00290            crv = CKR_OBJECT_HANDLE_INVALID;
00291            break;
00292        } 
00293        crv = pk11_Attr2SecItem(arena,modulus,&pubKey->u.rsa.modulus);
00294        if (crv != CKR_OK) break;
00295        crv = pk11_Attr2SecItem(arena,exponent,&pubKey->u.rsa.publicExponent);
00296        if (crv != CKR_OK) break;
00297        break;
00298     case dsaKey:
00299        prime = attrs;
00300        PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 
00301        subprime = attrs;
00302        PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++; 
00303        base = attrs;
00304        PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 
00305        value = attrs;
00306        PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 
00307        templateCount = attrs - template;
00308        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
00309        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
00310        if (crv != CKR_OK) break;
00311 
00312        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {
00313            crv = CKR_OBJECT_HANDLE_INVALID;
00314            break;
00315        } 
00316        crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dsa.params.prime);
00317        if (crv != CKR_OK) break;
00318        crv = pk11_Attr2SecItem(arena,subprime,&pubKey->u.dsa.params.subPrime);
00319        if (crv != CKR_OK) break;
00320        crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dsa.params.base);
00321        if (crv != CKR_OK) break;
00322        crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dsa.publicValue);
00323        if (crv != CKR_OK) break;
00324        break;
00325     case dhKey:
00326        prime = attrs;
00327        PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 
00328        base = attrs;
00329        PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 
00330        value =attrs;
00331        PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 
00332        templateCount = attrs - template;
00333        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
00334        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
00335        if (crv != CKR_OK) break;
00336 
00337        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) {
00338            crv = CKR_OBJECT_HANDLE_INVALID;
00339            break;
00340        } 
00341        crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dh.prime);
00342        if (crv != CKR_OK) break;
00343        crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dh.base);
00344        if (crv != CKR_OK) break;
00345        crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue);
00346        if (crv != CKR_OK) break;
00347        break;
00348     case ecKey:
00349        pubKey->u.ec.size = 0;
00350        ecparams = attrs;
00351        PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0); attrs++; 
00352        value =attrs;
00353        PK11_SETATTRS(attrs, CKA_EC_POINT, NULL, 0); attrs++; 
00354        templateCount = attrs - template;
00355        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
00356        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
00357        if (crv != CKR_OK) break;
00358 
00359        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_EC)) {
00360            crv = CKR_OBJECT_HANDLE_INVALID;
00361            break;
00362        } 
00363 
00364        crv = pk11_Attr2SecItem(arena,ecparams,
00365                                &pubKey->u.ec.DEREncodedParams);
00366        if (crv != CKR_OK) break;
00367        crv = pk11_Attr2SecItem(arena,value,&pubKey->u.ec.publicValue);
00368        if (crv != CKR_OK) break;
00369        break;
00370     case fortezzaKey:
00371     case nullKey:
00372     default:
00373        crv = CKR_OBJECT_HANDLE_INVALID;
00374        break;
00375     }
00376 
00377     PORT_FreeArena(tmp_arena,PR_FALSE);
00378 
00379     if (crv != CKR_OK) {
00380        PORT_FreeArena(arena,PR_FALSE);
00381        PK11_FreeSlot(slot);
00382        PORT_SetError( PK11_MapError(crv) );
00383        return NULL;
00384     }
00385 
00386     return pubKey;
00387 }
00388 
00389 /*
00390  * Build a Private Key structure from raw PKCS #11 information.
00391  */
00392 SECKEYPrivateKey *
00393 PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, 
00394                      PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
00395 {
00396     PRArenaPool *arena;
00397     SECKEYPrivateKey *privKey;
00398     PRBool isPrivate;
00399     SECStatus rv;
00400 
00401     /* don't know? look it up */
00402     if (keyType == nullKey) {
00403        CK_KEY_TYPE pk11Type = CKK_RSA;
00404 
00405        pk11Type = PK11_ReadULongAttribute(slot,privID,CKA_KEY_TYPE);
00406        isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN);
00407        switch (pk11Type) {
00408        case CKK_RSA: keyType = rsaKey; break;
00409        case CKK_DSA: keyType = dsaKey; break;
00410        case CKK_DH: keyType = dhKey; break;
00411        case CKK_KEA: keyType = fortezzaKey; break;
00412        case CKK_EC: keyType = ecKey; break;
00413        default:
00414               break;
00415        }
00416     }
00417 
00418     /* if the key is private, make sure we are authenticated to the
00419      * token before we try to use it */
00420     isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE);
00421     if (isPrivate) {
00422        rv = PK11_Authenticate(slot, PR_TRUE, wincx);
00423        if (rv != SECSuccess) {
00424            return NULL;
00425        }
00426     }
00427 
00428     /* now we need to create space for the private key */
00429     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
00430     if (arena == NULL) return NULL;
00431 
00432     privKey = (SECKEYPrivateKey *) 
00433                      PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
00434     if (privKey == NULL) {
00435        PORT_FreeArena(arena, PR_FALSE);
00436        return NULL;
00437     }
00438 
00439     privKey->arena = arena;
00440     privKey->keyType = keyType;
00441     privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
00442     privKey->pkcs11ID = privID;
00443     privKey->pkcs11IsTemp = isTemp;
00444     privKey->wincx = wincx;
00445 
00446     return privKey;
00447 }
00448 
00449 
00450 PK11SlotInfo *
00451 PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
00452 {
00453     PK11SlotInfo *slot = key->pkcs11Slot;
00454     slot = PK11_ReferenceSlot(slot);
00455     return slot;
00456 }
00457 
00458 /*
00459  * Get the modulus length for raw parsing
00460  */
00461 int
00462 PK11_GetPrivateModulusLen(SECKEYPrivateKey *key)
00463 {
00464     CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 };
00465     PK11SlotInfo *slot = key->pkcs11Slot;
00466     CK_RV crv;
00467     int length;
00468 
00469     switch (key->keyType) {
00470     case rsaKey:
00471        crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1);
00472        if (crv != CKR_OK) {
00473            PORT_SetError( PK11_MapError(crv) );
00474            return -1;
00475        }
00476        length = theTemplate.ulValueLen;
00477        if ( *(unsigned char *)theTemplate.pValue == 0) {
00478            length--;
00479        }
00480        if (theTemplate.pValue != NULL)
00481            PORT_Free(theTemplate.pValue);
00482        return (int) length;
00483        
00484     case fortezzaKey:
00485     case dsaKey:
00486     case dhKey:
00487     default:
00488        break;
00489     }
00490     if (theTemplate.pValue != NULL)
00491        PORT_Free(theTemplate.pValue);
00492     PORT_SetError( SEC_ERROR_INVALID_KEY );
00493     return -1;
00494 }
00495 
00496 
00497 
00498 /*
00499  * take a private key in one pkcs11 module and load it into another:
00500  *  NOTE: the source private key is a rare animal... it can't be sensitive.
00501  *  This is used to do a key gen using one pkcs11 module and storing the
00502  *  result into another.
00503  */
00504 static SECKEYPrivateKey *
00505 pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
00506               SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags) 
00507 {
00508     CK_ATTRIBUTE privTemplate[] = {
00509         /* class must be first */
00510        { CKA_CLASS, NULL, 0 },
00511        { CKA_KEY_TYPE, NULL, 0 },
00512        { CKA_ID, NULL, 0 },
00513 #ifdef notdef
00514        { CKA_LABEL, NULL, 0 },
00515        { CKA_SUBJECT, NULL, 0 },
00516 #endif
00517        /* RSA */
00518        { CKA_MODULUS, NULL, 0 },
00519        { CKA_PRIVATE_EXPONENT, NULL, 0 },
00520        { CKA_PUBLIC_EXPONENT, NULL, 0 },
00521        { CKA_PRIME_1, NULL, 0 },
00522        { CKA_PRIME_2, NULL, 0 },
00523        { CKA_EXPONENT_1, NULL, 0 },
00524        { CKA_EXPONENT_2, NULL, 0 },
00525        { CKA_COEFFICIENT, NULL, 0 },
00526        /* reserve space for the attributes that may be
00527         * specified in attrFlags */
00528        { CKA_TOKEN, NULL, 0 },
00529        { CKA_PRIVATE, NULL, 0 },
00530        { CKA_MODIFIABLE, NULL, 0 },
00531        { CKA_SENSITIVE, NULL, 0 },
00532        { CKA_EXTRACTABLE, NULL, 0 },
00533 #define NUM_RESERVED_ATTRS 5    /* number of reserved attributes above */
00534     };
00535     CK_BBOOL cktrue = CK_TRUE;
00536     CK_BBOOL ckfalse = CK_FALSE;
00537     CK_ATTRIBUTE *attrs = NULL, *ap;
00538     const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]);
00539     PRArenaPool *arena;
00540     CK_OBJECT_HANDLE objectID;
00541     int i, count = 0;
00542     int extra_count = 0;
00543     CK_RV crv;
00544     SECStatus rv;
00545     PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
00546 
00547     if (pk11_BadAttrFlags(attrFlags)) {
00548        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00549        return NULL;
00550     }
00551 
00552     for (i=0; i < templateSize; i++) {
00553        if (privTemplate[i].type == CKA_MODULUS) {
00554            attrs= &privTemplate[i];
00555            count = i;
00556            break;
00557        }
00558     }
00559     PORT_Assert(attrs != NULL);
00560     if (attrs == NULL) {
00561        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
00562        return NULL;
00563     }
00564 
00565     ap = attrs;
00566 
00567     switch (privKey->keyType) {
00568     case rsaKey:
00569        count = templateSize - NUM_RESERVED_ATTRS;
00570        extra_count = count - (attrs - privTemplate);
00571        break;
00572     case dsaKey:
00573        ap->type = CKA_PRIME; ap++; count++; extra_count++;
00574        ap->type = CKA_SUBPRIME; ap++; count++; extra_count++;
00575        ap->type = CKA_BASE; ap++; count++; extra_count++;
00576        ap->type = CKA_VALUE; ap++; count++; extra_count++;
00577        break;
00578     case dhKey:
00579        ap->type = CKA_PRIME; ap++; count++; extra_count++;
00580        ap->type = CKA_BASE; ap++; count++; extra_count++;
00581        ap->type = CKA_VALUE; ap++; count++; extra_count++;
00582        break;
00583     case ecKey:
00584        ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++;
00585        ap->type = CKA_VALUE; ap++; count++; extra_count++;
00586        break;
00587      default:
00588        count = 0;
00589        extra_count = 0;
00590        break;
00591      }
00592 
00593      if (count == 0) {
00594        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
00595        return NULL;
00596      }
00597 
00598      arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
00599      if (arena == NULL) return NULL;
00600      /*
00601       * read out the old attributes.
00602       */
00603      crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
00604               privTemplate,count);
00605      if (crv != CKR_OK) {
00606        PORT_SetError( PK11_MapError(crv) );
00607        PORT_FreeArena(arena, PR_TRUE);
00608        return NULL;
00609      }
00610 
00611      /* Set token, private, modifiable, sensitive, and extractable */
00612      count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
00613                                    &cktrue, &ckfalse);
00614 
00615      /* Not everyone can handle zero padded key values, give
00616       * them the raw data as unsigned */
00617      for (ap=attrs; extra_count; ap++, extra_count--) {
00618        pk11_SignedToUnsigned(ap);
00619      }
00620 
00621      /* now Store the puppies */
00622      rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate, 
00623                                           count, token, &objectID);
00624      PORT_FreeArena(arena, PR_TRUE);
00625      if (rv != SECSuccess) {
00626        return NULL;
00627      }
00628 
00629      /* try loading the public key */
00630      if (pubKey) {
00631        PK11_ImportPublicKey(slot, pubKey, token);
00632        if (pubKey->pkcs11Slot) {
00633            PK11_FreeSlot(pubKey->pkcs11Slot);
00634            pubKey->pkcs11Slot = NULL;
00635            pubKey->pkcs11ID = CK_INVALID_HANDLE;
00636        }
00637      }
00638 
00639      /* build new key structure */
00640      return PK11_MakePrivKey(slot, privKey->keyType, !token, 
00641                                           objectID, privKey->wincx);
00642 }
00643 
00644 static SECKEYPrivateKey *
00645 pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
00646               SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) 
00647 {
00648     PK11AttrFlags attrFlags = 0;
00649     if (token) {
00650        attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
00651     } else {
00652        attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC);
00653     }
00654     if (sensitive) {
00655        attrFlags |= PK11_ATTR_SENSITIVE;
00656     } else {
00657        attrFlags |= PK11_ATTR_INSENSITIVE;
00658     }
00659     return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags);
00660 }
00661 
00662 /*
00663  * export this for PSM
00664  */
00665 SECKEYPrivateKey *
00666 PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
00667               SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) 
00668 {
00669     return pk11_loadPrivKey(slot,privKey,pubKey,token,sensitive);
00670 }
00671 
00672 
00673 /*
00674  * Use the token to generate a key pair.
00675  */
00676 SECKEYPrivateKey *
00677 PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
00678    void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
00679 {
00680     /* we have to use these native types because when we call PKCS 11 modules
00681      * we have to make sure that we are using the correct sizes for all the
00682      * parameters. */
00683     CK_BBOOL ckfalse = CK_FALSE;
00684     CK_BBOOL cktrue = CK_TRUE;
00685     CK_ULONG modulusBits;
00686     CK_BYTE publicExponent[4];
00687     CK_ATTRIBUTE privTemplate[] = {
00688        { CKA_SENSITIVE, NULL, 0},
00689        { CKA_TOKEN,  NULL, 0},
00690        { CKA_PRIVATE,  NULL, 0},
00691        { CKA_DERIVE,  NULL, 0},
00692        { CKA_UNWRAP,  NULL, 0},
00693        { CKA_SIGN,  NULL, 0},
00694        { CKA_DECRYPT,  NULL, 0},
00695        { CKA_EXTRACTABLE, NULL, 0},
00696        { CKA_MODIFIABLE,  NULL, 0},
00697     };
00698     CK_ATTRIBUTE rsaPubTemplate[] = {
00699        { CKA_MODULUS_BITS, NULL, 0},
00700        { CKA_PUBLIC_EXPONENT, NULL, 0},
00701        { CKA_TOKEN,  NULL, 0},
00702        { CKA_DERIVE,  NULL, 0},
00703        { CKA_WRAP,  NULL, 0},
00704        { CKA_VERIFY,  NULL, 0},
00705        { CKA_VERIFY_RECOVER,  NULL, 0},
00706        { CKA_ENCRYPT,  NULL, 0},
00707        { CKA_MODIFIABLE,  NULL, 0},
00708     };
00709     CK_ATTRIBUTE dsaPubTemplate[] = {
00710        { CKA_PRIME, NULL, 0 },
00711        { CKA_SUBPRIME, NULL, 0 },
00712        { CKA_BASE, NULL, 0 },
00713        { CKA_TOKEN,  NULL, 0},
00714        { CKA_DERIVE,  NULL, 0},
00715        { CKA_WRAP,  NULL, 0},
00716        { CKA_VERIFY,  NULL, 0},
00717        { CKA_VERIFY_RECOVER,  NULL, 0},
00718        { CKA_ENCRYPT,  NULL, 0},
00719        { CKA_MODIFIABLE,  NULL, 0},
00720     };
00721     CK_ATTRIBUTE dhPubTemplate[] = {
00722       { CKA_PRIME, NULL, 0 }, 
00723       { CKA_BASE, NULL, 0 }, 
00724       { CKA_TOKEN,  NULL, 0},
00725       { CKA_DERIVE,  NULL, 0},
00726       { CKA_WRAP,  NULL, 0},
00727       { CKA_VERIFY,  NULL, 0},
00728       { CKA_VERIFY_RECOVER,  NULL, 0},
00729       { CKA_ENCRYPT,  NULL, 0},
00730       { CKA_MODIFIABLE,  NULL, 0},
00731     };
00732     CK_ATTRIBUTE ecPubTemplate[] = {
00733       { CKA_EC_PARAMS, NULL, 0 }, 
00734       { CKA_TOKEN,  NULL, 0},
00735       { CKA_DERIVE,  NULL, 0},
00736       { CKA_WRAP,  NULL, 0},
00737       { CKA_VERIFY,  NULL, 0},
00738       { CKA_VERIFY_RECOVER,  NULL, 0},
00739       { CKA_ENCRYPT,  NULL, 0},
00740       { CKA_MODIFIABLE,  NULL, 0},
00741     };
00742     SECKEYECParams * ecParams;
00743 
00744     /*CK_ULONG key_size = 0;*/
00745     CK_ATTRIBUTE *pubTemplate;
00746     int privCount = 0;
00747     int pubCount = 0;
00748     PK11RSAGenParams *rsaParams;
00749     SECKEYPQGParams *dsaParams;
00750     SECKEYDHParams * dhParams;
00751     CK_MECHANISM mechanism;
00752     CK_MECHANISM test_mech;
00753     CK_SESSION_HANDLE session_handle;
00754     CK_RV crv;
00755     CK_OBJECT_HANDLE privID,pubID;
00756     SECKEYPrivateKey *privKey;
00757     KeyType keyType;
00758     PRBool restore;
00759     int peCount,i;
00760     CK_ATTRIBUTE *attrs;
00761     CK_ATTRIBUTE *privattrs;
00762     SECItem *pubKeyIndex;
00763     CK_ATTRIBUTE setTemplate;
00764     CK_MECHANISM_INFO mechanism_info;
00765     CK_OBJECT_CLASS keyClass;
00766     SECItem *cka_id;
00767     PRBool haslock = PR_FALSE;
00768     PRBool pubIsToken = PR_FALSE;
00769     PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
00770     /* subset of attrFlags applicable to the public key */
00771     PK11AttrFlags pubKeyAttrFlags = attrFlags &
00772        (PK11_ATTR_TOKEN | PK11_ATTR_SESSION
00773        | PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
00774 
00775     if (pk11_BadAttrFlags(attrFlags)) {
00776        PORT_SetError( SEC_ERROR_INVALID_ARGS );
00777        return NULL;
00778     }
00779 
00780     PORT_Assert(slot != NULL);
00781     if (slot == NULL) {
00782        PORT_SetError( SEC_ERROR_NO_MODULE);
00783        return NULL;
00784     }
00785 
00786     /* if our slot really doesn't do this mechanism, Generate the key
00787      * in our internal token and write it out */
00788     if (!PK11_DoesMechanism(slot,type)) {
00789        PK11SlotInfo *int_slot = PK11_GetInternalSlot();
00790 
00791        /* don't loop forever looking for a slot */
00792        if (slot == int_slot) {
00793            PK11_FreeSlot(int_slot);
00794            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
00795            return NULL;
00796        }
00797 
00798        /* if there isn't a suitable slot, then we can't do the keygen */
00799        if (int_slot == NULL) {
00800            PORT_SetError( SEC_ERROR_NO_MODULE );
00801            return NULL;
00802        }
00803 
00804        /* generate the temporary key to load */
00805        privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE, 
00806                                                  PR_FALSE, wincx);
00807        PK11_FreeSlot(int_slot);
00808 
00809        /* if successful, load the temp key into the new token */
00810        if (privKey != NULL) {
00811            SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
00812                                           privKey,*pubKey,attrFlags);
00813            SECKEY_DestroyPrivateKey(privKey);
00814            if (newPrivKey == NULL) {
00815               SECKEY_DestroyPublicKey(*pubKey);
00816               *pubKey = NULL;
00817            }
00818            return newPrivKey;
00819        }
00820        return NULL;
00821    }
00822 
00823 
00824     mechanism.mechanism = type;
00825     mechanism.pParameter = NULL;
00826     mechanism.ulParameterLen = 0;
00827     test_mech.pParameter = NULL;
00828     test_mech.ulParameterLen = 0;
00829 
00830     /* set up the private key template */
00831     privattrs = privTemplate;
00832     privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
00833                                           &cktrue, &ckfalse);
00834 
00835     /* set up the mechanism specific info */
00836     switch (type) {
00837     case CKM_RSA_PKCS_KEY_PAIR_GEN:
00838     case CKM_RSA_X9_31_KEY_PAIR_GEN:
00839        rsaParams = (PK11RSAGenParams *)param;
00840        if (rsaParams->pe == 0) {
00841            PORT_SetError(SEC_ERROR_INVALID_ARGS);
00842            return NULL;
00843        }
00844        modulusBits = rsaParams->keySizeInBits;
00845        peCount = 0;
00846 
00847        /* convert pe to a PKCS #11 string */
00848        for (i=0; i < 4; i++) {
00849            if (peCount || (rsaParams->pe & 
00850                             ((unsigned long)0xff000000L >> (i*8)))) {
00851               publicExponent[peCount] = 
00852                             (CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);
00853               peCount++;
00854            }
00855        }
00856        PORT_Assert(peCount != 0);
00857        attrs = rsaPubTemplate;
00858        PK11_SETATTRS(attrs, CKA_MODULUS_BITS, 
00859                             &modulusBits, sizeof(modulusBits)); attrs++;
00860        PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
00861                             publicExponent, peCount);attrs++;
00862        pubTemplate = rsaPubTemplate;
00863        keyType = rsaKey;
00864        test_mech.mechanism = CKM_RSA_PKCS;
00865        break;
00866     case CKM_DSA_KEY_PAIR_GEN:
00867        dsaParams = (SECKEYPQGParams *)param;
00868        attrs = dsaPubTemplate;
00869        PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
00870                             dsaParams->prime.len); attrs++;
00871        PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
00872                                    dsaParams->subPrime.len); attrs++;
00873        PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
00874                                           dsaParams->base.len); attrs++;
00875        pubTemplate = dsaPubTemplate;
00876        keyType = dsaKey;
00877        test_mech.mechanism = CKM_DSA;
00878        break;
00879     case CKM_DH_PKCS_KEY_PAIR_GEN:
00880         dhParams = (SECKEYDHParams *)param;
00881         attrs = dhPubTemplate;
00882         PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
00883                       dhParams->prime.len);   attrs++;
00884         PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
00885                       dhParams->base.len);    attrs++;
00886         pubTemplate = dhPubTemplate;
00887         keyType = dhKey;
00888         test_mech.mechanism = CKM_DH_PKCS_DERIVE;
00889        break;
00890     case CKM_EC_KEY_PAIR_GEN:
00891         ecParams = (SECKEYECParams *)param;
00892         attrs = ecPubTemplate;
00893         PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, 
00894                      ecParams->len);   attrs++;
00895         pubTemplate = ecPubTemplate;
00896         keyType = ecKey;
00897        /* XXX An EC key can be used for other mechanisms too such
00898         * as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect
00899         * that in test_mech.mechanism so the CKA_SIGN, CKA_VERIFY
00900         * attributes are set correctly? 
00901         */
00902         test_mech.mechanism = CKM_ECDH1_DERIVE;
00903         break;
00904     default:
00905        PORT_SetError( SEC_ERROR_BAD_KEY );
00906        return NULL;
00907     }
00908 
00909     /* now query the slot to find out how "good" a key we can generate */
00910     if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
00911     crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
00912                             test_mech.mechanism,&mechanism_info);
00913     if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
00914     if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
00915        /* must be old module... guess what it should be... */
00916        switch (test_mech.mechanism) {
00917        case CKM_RSA_PKCS:
00918               mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT | 
00919                      CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);;
00920               break;
00921        case CKM_DSA:
00922               mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
00923               break;
00924        case CKM_DH_PKCS_DERIVE:
00925               mechanism_info.flags = CKF_DERIVE;
00926               break;
00927        case CKM_ECDH1_DERIVE:
00928               mechanism_info.flags = CKF_DERIVE;
00929               break;
00930        case CKM_ECDSA:
00931        case CKM_ECDSA_SHA1:
00932               mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
00933               break;
00934        default:
00935               break;
00936        }
00937     }
00938     /* set the public key attributes */
00939     attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
00940                                           &cktrue, &ckfalse);
00941     PK11_SETATTRS(attrs, CKA_DERIVE, 
00942               mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
00943                                     sizeof(CK_BBOOL)); attrs++;
00944     PK11_SETATTRS(attrs, CKA_WRAP, 
00945               mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
00946                                     sizeof(CK_BBOOL)); attrs++;
00947     PK11_SETATTRS(attrs, CKA_VERIFY, 
00948               mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
00949                                     sizeof(CK_BBOOL)); attrs++;
00950     PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER, 
00951               mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
00952                                     sizeof(CK_BBOOL)); attrs++;
00953     PK11_SETATTRS(attrs, CKA_ENCRYPT, 
00954               mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,
00955                                     sizeof(CK_BBOOL)); attrs++;
00956     /* set the private key attributes */
00957     PK11_SETATTRS(privattrs, CKA_DERIVE, 
00958               mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
00959                                     sizeof(CK_BBOOL)); privattrs++;
00960     PK11_SETATTRS(privattrs, CKA_UNWRAP, 
00961               mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
00962                                     sizeof(CK_BBOOL)); privattrs++;
00963     PK11_SETATTRS(privattrs, CKA_SIGN, 
00964               mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
00965                                     sizeof(CK_BBOOL)); privattrs++;
00966     PK11_SETATTRS(privattrs, CKA_DECRYPT, 
00967               mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
00968                                     sizeof(CK_BBOOL)); privattrs++;
00969 
00970     if (token) {
00971        session_handle = PK11_GetRWSession(slot);
00972        haslock = PK11_RWSessionHasLock(slot,session_handle);
00973        restore = PR_TRUE;
00974     } else {
00975        session_handle = slot->session;
00976        if (session_handle != CK_INVALID_SESSION)
00977            PK11_EnterSlotMonitor(slot);
00978        restore = PR_FALSE;
00979        haslock = PR_TRUE;
00980     }
00981 
00982     if (session_handle == CK_INVALID_SESSION) {
00983        PORT_SetError(SEC_ERROR_BAD_DATA);
00984        return NULL;
00985     }
00986     privCount = privattrs - privTemplate;
00987     pubCount = attrs - pubTemplate;
00988     crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
00989        pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);
00990 
00991     if (crv != CKR_OK) {
00992        if (restore)  {
00993            PK11_RestoreROSession(slot,session_handle);
00994        } else PK11_ExitSlotMonitor(slot);
00995        PORT_SetError( PK11_MapError(crv) );
00996        return NULL;
00997     }
00998     /* This locking code is dangerous and needs to be more thought
00999      * out... the real problem is that we're holding the mutex open this long
01000      */
01001     if (haslock) { PK11_ExitSlotMonitor(slot); }
01002 
01003     /* swap around the ID's for older PKCS #11 modules */
01004     keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);
01005     if (keyClass != CKO_PUBLIC_KEY) {
01006        CK_OBJECT_HANDLE tmp = pubID;
01007        pubID = privID;
01008        privID = tmp;
01009     }
01010 
01011     *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
01012     if (*pubKey == NULL) {
01013        if (restore)  {
01014            /* we may have to restore the mutex so it get's exited properly
01015             * in RestoreROSession */
01016             if (haslock)  PK11_EnterSlotMonitor(slot); 
01017            PK11_RestoreROSession(slot,session_handle);
01018        } 
01019        PK11_DestroyObject(slot,pubID);
01020        PK11_DestroyObject(slot,privID);
01021        return NULL;
01022     }
01023 
01024     /* set the ID to the public key so we can find it again */
01025     pubKeyIndex =  NULL;
01026     switch (type) {
01027     case CKM_RSA_PKCS_KEY_PAIR_GEN:
01028     case CKM_RSA_X9_31_KEY_PAIR_GEN:
01029       pubKeyIndex = &(*pubKey)->u.rsa.modulus;
01030       break;
01031     case CKM_DSA_KEY_PAIR_GEN:
01032       pubKeyIndex = &(*pubKey)->u.dsa.publicValue;
01033       break;
01034     case CKM_DH_PKCS_KEY_PAIR_GEN:
01035       pubKeyIndex = &(*pubKey)->u.dh.publicValue;
01036       break;      
01037     case CKM_EC_KEY_PAIR_GEN:
01038       pubKeyIndex = &(*pubKey)->u.ec.publicValue;
01039       break;      
01040     }
01041     PORT_Assert(pubKeyIndex != NULL);
01042 
01043     cka_id = PK11_MakeIDFromPubKey(pubKeyIndex);
01044     pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);
01045 
01046     PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
01047 
01048     if (haslock) { PK11_EnterSlotMonitor(slot); }
01049     crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
01050               &setTemplate, 1);
01051    
01052     if (crv == CKR_OK && pubIsToken) {
01053        crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
01054               &setTemplate, 1);
01055     }
01056 
01057 
01058     if (restore) {
01059        PK11_RestoreROSession(slot,session_handle);
01060     } else {
01061        PK11_ExitSlotMonitor(slot);
01062     }
01063     SECITEM_FreeItem(cka_id,PR_TRUE);
01064 
01065 
01066     if (crv != CKR_OK) {
01067        PK11_DestroyObject(slot,pubID);
01068        PK11_DestroyObject(slot,privID);
01069        PORT_SetError( PK11_MapError(crv) );
01070        *pubKey = NULL;
01071        return NULL;
01072     }
01073 
01074     privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx);
01075     if (privKey == NULL) {
01076        SECKEY_DestroyPublicKey(*pubKey);
01077        PK11_DestroyObject(slot,privID);
01078        *pubKey = NULL;
01079        return NULL;
01080     }
01081 
01082     return privKey;
01083 }
01084 
01085 /*
01086  * Use the token to generate a key pair.
01087  */
01088 SECKEYPrivateKey *
01089 PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
01090    void *param, SECKEYPublicKey **pubKey, PRBool token, 
01091                                    PRBool sensitive, void *wincx)
01092 {
01093     PK11AttrFlags attrFlags = 0;
01094 
01095     if (token) {
01096        attrFlags |= PK11_ATTR_TOKEN;
01097     } else {
01098        attrFlags |= PK11_ATTR_SESSION;
01099     }
01100     if (sensitive) {
01101        attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE);
01102     } else {
01103        attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC);
01104     }
01105     return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey,
01106                                           attrFlags, wincx);
01107 }
01108 
01109 /* build a public KEA key from the public value */
01110 SECKEYPublicKey *
01111 PK11_MakeKEAPubKey(unsigned char *keyData,int length)
01112 {
01113     SECKEYPublicKey *pubk;
01114     SECItem pkData;
01115     SECStatus rv;
01116     PRArenaPool *arena;
01117 
01118     pkData.data = keyData;
01119     pkData.len = length;
01120 
01121     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
01122     if (arena == NULL)
01123        return NULL;
01124 
01125     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
01126     if (pubk == NULL) {
01127        PORT_FreeArena (arena, PR_FALSE);
01128        return NULL;
01129     }
01130 
01131     pubk->arena = arena;
01132     pubk->pkcs11Slot = 0;
01133     pubk->pkcs11ID = CK_INVALID_HANDLE;
01134     pubk->keyType = fortezzaKey;
01135     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
01136     if (rv != SECSuccess) {
01137        PORT_FreeArena (arena, PR_FALSE);
01138        return NULL;
01139     }
01140     return pubk;
01141 }
01142 
01143 SECStatus 
01144 PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
01145                      SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
01146                      SECItem *nickname, SECItem *publicValue, PRBool isPerm,
01147                      PRBool isPrivate, KeyType keyType, 
01148                      unsigned int keyUsage, void *wincx)
01149 {
01150     CK_MECHANISM_TYPE mechanism;
01151     SECItem *pbe_param, crypto_param;
01152     PK11SymKey *key = NULL;
01153     SECStatus rv = SECSuccess;
01154     CK_MECHANISM cryptoMech, pbeMech;
01155     CK_RV crv;
01156     SECKEYPrivateKey *privKey = NULL;
01157     PRBool faulty3DES = PR_FALSE;
01158     int usageCount = 0;
01159     CK_KEY_TYPE key_type;
01160     CK_ATTRIBUTE_TYPE *usage = NULL;
01161     CK_ATTRIBUTE_TYPE rsaUsage[] = {
01162                CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
01163     CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
01164     CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
01165     CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE };
01166     if((epki == NULL) || (pwitem == NULL))
01167        return SECFailure;
01168 
01169     crypto_param.data = NULL;
01170 
01171     mechanism = PK11_AlgtagToMechanism(SECOID_FindOIDTag(
01172                                    &epki->algorithm.algorithm));
01173 
01174     switch (keyType) {
01175     default:
01176     case rsaKey:
01177        key_type = CKK_RSA;
01178        switch  (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
01179        case KU_KEY_ENCIPHERMENT:
01180            usage = rsaUsage;
01181            usageCount = 2;
01182            break;
01183        case KU_DIGITAL_SIGNATURE:
01184            usage = &rsaUsage[2];
01185            usageCount = 2;
01186            break;
01187        case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
01188        case 0: /* default to everything */
01189            usage = rsaUsage;
01190            usageCount = 4;
01191            break;
01192        }
01193         break;
01194     case dhKey:
01195        key_type = CKK_DH;
01196        usage = dhUsage;
01197        usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
01198        break;
01199     case dsaKey:
01200        key_type = CKK_DSA;
01201        usage = dsaUsage;
01202        usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
01203        break;
01204     case ecKey:
01205        key_type = CKK_EC;
01206        switch  (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) {
01207        case KU_DIGITAL_SIGNATURE:
01208            usage = ecUsage;
01209            usageCount = 1;
01210            break;
01211        case KU_KEY_AGREEMENT:
01212            usage = &ecUsage[1];
01213            usageCount = 1;
01214            break;
01215        case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT:
01216        default: /* default to everything */
01217            usage = ecUsage;
01218            usageCount = 2;
01219            break;
01220        }
01221        break; 
01222     }
01223 
01224 try_faulty_3des:
01225     pbe_param = PK11_ParamFromAlgid(&epki->algorithm);
01226 
01227     key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem, 
01228                                                  faulty3DES, wincx);
01229     if((key == NULL) || (pbe_param == NULL)) {
01230        rv = SECFailure;
01231        goto done;
01232     }
01233 
01234     pbeMech.mechanism = mechanism;
01235     pbeMech.pParameter = pbe_param->data;
01236     pbeMech.ulParameterLen = pbe_param->len;
01237 
01238     crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, 
01239                                            pwitem, faulty3DES);
01240     if(crv != CKR_OK) {
01241        rv = SECFailure;
01242        goto done;
01243     }
01244 
01245     cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
01246     crypto_param.data = (unsigned char*)cryptoMech.pParameter;
01247     crypto_param.len = cryptoMech.ulParameterLen;
01248 
01249     PORT_Assert(usage != NULL);
01250     PORT_Assert(usageCount != 0);
01251     privKey = PK11_UnwrapPrivKey(slot, key, cryptoMech.mechanism, 
01252                              &crypto_param, &epki->encryptedData, 
01253                              nickname, publicValue, isPerm, isPrivate,
01254                              key_type, usage, usageCount, wincx);
01255     if(privKey) {
01256        SECKEY_DestroyPrivateKey(privKey);
01257        privKey = NULL;
01258        rv = SECSuccess;
01259        goto done;
01260     }
01261 
01262     /* if we are unable to import the key and the mechanism is 
01263      * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
01264      * the encrypted blob was created with a buggy key generation method
01265      * which is described in the PKCS 12 implementation notes.  So we
01266      * need to try importing via that method.
01267      */ 
01268     if((mechanism == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) {
01269        /* clean up after ourselves before redoing the key generation. */
01270 
01271        PK11_FreeSymKey(key);
01272        key = NULL;
01273 
01274        if(pbe_param) {
01275            SECITEM_ZfreeItem(pbe_param, PR_TRUE);
01276            pbe_param = NULL;
01277        }
01278 
01279        if(crypto_param.data) {
01280            SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
01281            crypto_param.data = NULL;
01282            cryptoMech.pParameter = NULL;
01283            crypto_param.len = cryptoMech.ulParameterLen = 0;
01284        }
01285 
01286        faulty3DES = PR_TRUE;
01287        goto try_faulty_3des;
01288     }
01289 
01290     /* key import really did fail */
01291     rv = SECFailure;
01292 
01293 done:
01294     if(pbe_param != NULL) {
01295        SECITEM_ZfreeItem(pbe_param, PR_TRUE);
01296        pbe_param = NULL;
01297     }
01298 
01299     if(crypto_param.data != NULL) {
01300        SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
01301     }
01302 
01303     if(key != NULL) {
01304        PK11_FreeSymKey(key);
01305     }
01306 
01307     return rv;
01308 }
01309 
01310 SECKEYPrivateKeyInfo *
01311 PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
01312 {
01313     return NULL;
01314 }
01315 
01316 SECKEYEncryptedPrivateKeyInfo * 
01317 PK11_ExportEncryptedPrivKeyInfo(
01318    PK11SlotInfo     *slot,      /* optional, encrypt key in this slot */
01319    SECOidTag         algTag,    /* encrypt key with this algorithm */
01320    SECItem          *pwitem,    /* password for PBE encryption */
01321    SECKEYPrivateKey *pk,        /* encrypt this private key */
01322    int               iteration, /* interations for PBE alg */
01323    void             *wincx)     /* context for password callback ? */
01324 {
01325     SECKEYEncryptedPrivateKeyInfo *epki      = NULL;
01326     PRArenaPool                   *arena     = NULL;
01327     SECAlgorithmID                *algid;
01328     SECItem                       *pbe_param = NULL;
01329     PK11SymKey                    *key       = NULL;
01330     SECStatus                      rv        = SECSuccess;
01331     CK_RV                          crv;
01332     CK_ULONG                       encBufLen;
01333     CK_MECHANISM_TYPE              mechanism;
01334     CK_MECHANISM                   pbeMech;
01335     CK_MECHANISM                   cryptoMech;
01336     SECItem                        crypto_param;
01337 
01338     if (!pwitem || !pk) {
01339        PORT_SetError(SEC_ERROR_INVALID_ARGS);
01340        return NULL;
01341     }
01342 
01343     algid = SEC_PKCS5CreateAlgorithmID(algTag, NULL, iteration);
01344     if (algid == NULL) {
01345        return NULL;
01346     }
01347 
01348     crypto_param.data = NULL;
01349 
01350     arena = PORT_NewArena(2048);
01351     if (arena)
01352        epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo);
01353     if(epki == NULL) {
01354        rv = SECFailure;
01355        goto loser;
01356     }
01357     epki->arena = arena;
01358 
01359     mechanism = PK11_AlgtagToMechanism(algTag);
01360     pbe_param = PK11_ParamFromAlgid(algid);
01361     if (!pbe_param || mechanism == CKM_INVALID_MECHANISM) {
01362        rv = SECFailure;
01363        goto loser;
01364     }
01365     pbeMech.mechanism = mechanism;
01366     pbeMech.pParameter = pbe_param->data;
01367     pbeMech.ulParameterLen = pbe_param->len;
01368 
01369     /* if we didn't specify a slot, use the slot the private key was in */
01370     if (!slot) {
01371        slot = pk->pkcs11Slot;
01372     }
01373 
01374     /* if we specified a different slot, and the private key slot can do the
01375      * pbe key gen, generate the key in the private key slot so we don't have 
01376      * to move it later */
01377     if (slot != pk->pkcs11Slot) {
01378        if (PK11_DoesMechanism(pk->pkcs11Slot,mechanism)) {
01379            slot = pk->pkcs11Slot;
01380        }
01381     }
01382     key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem, 
01383                                                  PR_FALSE, wincx);
01384 
01385     if((key == NULL) || (pbe_param == NULL)) {
01386        rv = SECFailure;
01387        goto loser;
01388     }
01389 
01390     crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, 
01391                                           pwitem, PR_FALSE);
01392     if(crv != CKR_OK) {
01393        rv = SECFailure;
01394        goto loser;
01395     }
01396     cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
01397     crypto_param.data = (unsigned char *)cryptoMech.pParameter;
01398     crypto_param.len = cryptoMech.ulParameterLen;
01399 
01400     /* If the key isn't in the private key slot, move it */
01401     if (key->slot != pk->pkcs11Slot) {
01402        PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot,
01403                                           key->type, CKA_WRAP, key);
01404        if (newkey == NULL) {
01405            rv= SECFailure;
01406            goto loser;
01407        }
01408 
01409        /* free the old key and use the new key */
01410        PK11_FreeSymKey(key);
01411        key = newkey;
01412     }
01413        
01414     /* we are extracting an encrypted privateKey structure.
01415      * which needs to be freed along with the buffer into which it is
01416      * returned.  eventually, we should retrieve an encrypted key using
01417      * pkcs8/pkcs5.
01418      */
01419     encBufLen = 0;
01420     PK11_EnterSlotMonitor(pk->pkcs11Slot);
01421     crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, 
01422               &cryptoMech, key->objectID, pk->pkcs11ID, NULL, 
01423               &encBufLen); 
01424     PK11_ExitSlotMonitor(pk->pkcs11Slot);
01425     if (crv != CKR_OK) {
01426        rv = SECFailure;
01427        goto loser;
01428     }
01429     epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen);
01430     if (!epki->encryptedData.data) {
01431        rv = SECFailure;
01432        goto loser;
01433     }
01434     PK11_EnterSlotMonitor(pk->pkcs11Slot);
01435     crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, 
01436               &cryptoMech, key->objectID, pk->pkcs11ID, 
01437               epki->encryptedData.data, &encBufLen); 
01438     PK11_ExitSlotMonitor(pk->pkcs11Slot);
01439     epki->encryptedData.len = (unsigned int) encBufLen;
01440     if(crv != CKR_OK) {
01441        rv = SECFailure;
01442        goto loser;
01443     }
01444 
01445     if(!epki->encryptedData.len) {
01446        rv = SECFailure;
01447        goto loser;
01448     }
01449 
01450     rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid);
01451 
01452 loser:
01453     if(pbe_param != NULL) {
01454        SECITEM_ZfreeItem(pbe_param, PR_TRUE);
01455        pbe_param = NULL;
01456     }
01457 
01458     if(crypto_param.data != NULL) {
01459        SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
01460        crypto_param.data = NULL;
01461     }
01462 
01463     if(key != NULL) {
01464        PK11_FreeSymKey(key);
01465     }
01466     SECOID_DestroyAlgorithmID(algid, PR_TRUE);
01467 
01468     if(rv == SECFailure) {
01469        if(arena != NULL) {
01470            PORT_FreeArena(arena, PR_TRUE);
01471        }
01472        epki = NULL;
01473     }
01474 
01475     return epki;
01476 }
01477 
01478 SECKEYEncryptedPrivateKeyInfo * 
01479 PK11_ExportEncryptedPrivateKeyInfo(
01480    PK11SlotInfo    *slot,      /* optional, encrypt key in this slot */
01481    SECOidTag        algTag,    /* encrypt key with this algorithm */
01482    SECItem         *pwitem,    /* password for PBE encryption */
01483    CERTCertificate *cert,      /* wrap priv key for this user cert */
01484    int              iteration, /* interations for PBE alg */
01485    void            *wincx)     /* context for password callback ? */
01486 {
01487     SECKEYEncryptedPrivateKeyInfo *epki = NULL;
01488     SECKEYPrivateKey              *pk   = PK11_FindKeyByAnyCert(cert, wincx);
01489     if (pk != NULL) {
01490        epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk, 
01491                                               iteration, wincx);
01492        SECKEY_DestroyPrivateKey(pk);
01493     }
01494     return epki;
01495 }
01496 
01497 SECItem*
01498 PK11_DEREncodePublicKey(SECKEYPublicKey *pubk)
01499 {
01500     CERTSubjectPublicKeyInfo *spki=NULL;
01501     SECItem *spkiDER = NULL;
01502 
01503     if( pubk == NULL ) {
01504         return NULL;
01505     }
01506 
01507     /* get the subjectpublickeyinfo */
01508     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
01509     if( spki == NULL ) {
01510         goto finish;
01511     }
01512 
01513     /* DER-encode the subjectpublickeyinfo */
01514     spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
01515                     CERT_SubjectPublicKeyInfoTemplate);
01516 
01517 finish:
01518     return spkiDER;
01519 }
01520 
01521 char *
01522 PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey)
01523 {
01524     return PK11_GetObjectNickname(privKey->pkcs11Slot,privKey->pkcs11ID);
01525 }
01526 
01527 char *
01528 PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey)
01529 {
01530     return PK11_GetObjectNickname(pubKey->pkcs11Slot,pubKey->pkcs11ID);
01531 }
01532 
01533 SECStatus
01534 PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname)
01535 {
01536     return PK11_SetObjectNickname(privKey->pkcs11Slot,
01537                                    privKey->pkcs11ID,nickname);
01538 }
01539 
01540 SECStatus
01541 PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname)
01542 {
01543     return PK11_SetObjectNickname(pubKey->pkcs11Slot,
01544                                    pubKey->pkcs11ID,nickname);
01545 }
01546 
01547 SECKEYPQGParams *
01548 PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey)
01549 {
01550     CK_ATTRIBUTE pTemplate[] = {
01551        { CKA_PRIME, NULL, 0 },
01552        { CKA_SUBPRIME, NULL, 0 },
01553        { CKA_BASE, NULL, 0 },
01554     };
01555     int pTemplateLen = sizeof(pTemplate)/sizeof(pTemplate[0]);
01556     PRArenaPool *arena = NULL;
01557     SECKEYPQGParams *params;
01558     CK_RV crv;
01559 
01560 
01561     arena = PORT_NewArena(2048);
01562     if (arena == NULL) {
01563        goto loser;
01564     }
01565     params=(SECKEYPQGParams *)PORT_ArenaZAlloc(arena,sizeof(SECKEYPQGParams));
01566     if (params == NULL) {
01567        goto loser;
01568     }
01569 
01570     crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, 
01571                                           pTemplate, pTemplateLen);
01572     if (crv != CKR_OK) {
01573         PORT_SetError( PK11_MapError(crv) );
01574        goto loser;
01575     }
01576 
01577     params->arena = arena;
01578     params->prime.data = pTemplate[0].pValue;
01579     params->prime.len = pTemplate[0].ulValueLen;
01580     params->subPrime.data = pTemplate[1].pValue;
01581     params->subPrime.len = pTemplate[1].ulValueLen;
01582     params->base.data = pTemplate[2].pValue;
01583     params->base.len = pTemplate[2].ulValueLen;
01584 
01585     return params;
01586 
01587 loser:
01588     if (arena != NULL) {
01589        PORT_FreeArena(arena,PR_FALSE);
01590     }
01591     return NULL;
01592 }
01593 
01594 SECKEYPrivateKey*
01595 PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
01596                                   SECKEYPrivateKey *privKey)
01597 {
01598     CK_RV             crv;
01599     CK_OBJECT_HANDLE  newKeyID;
01600 
01601     static const CK_BBOOL     ckfalse = CK_FALSE;
01602     static const CK_ATTRIBUTE template[1] = { 
01603        { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse }
01604     };
01605 
01606     if (destSlot && destSlot != privKey->pkcs11Slot) {
01607        SECKEYPrivateKey *newKey =
01608               pk11_loadPrivKey(destSlot, 
01609                             privKey, 
01610                              NULL,     /* pubKey    */
01611                              PR_FALSE, /* token     */
01612                              PR_FALSE);/* sensitive */
01613        if (newKey)
01614            return newKey;
01615     }
01616     destSlot = privKey->pkcs11Slot;
01617     PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx);
01618     PK11_EnterSlotMonitor(destSlot);
01619     crv = PK11_GETTAB(destSlot)->C_CopyObject(   destSlot->session, 
01620                                           privKey->pkcs11ID,
01621                                           (CK_ATTRIBUTE *)template, 
01622                                           1, &newKeyID);
01623     PK11_ExitSlotMonitor(destSlot);
01624 
01625     if (crv != CKR_OK) {
01626        PORT_SetError( PK11_MapError(crv) );
01627        return NULL;
01628     }
01629 
01630     return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/, 
01631                          newKeyID, privKey->wincx);
01632 }
01633 
01634 SECKEYPrivateKey*
01635 PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx)
01636 {
01637     PK11SlotInfo* slot = privk->pkcs11Slot;
01638     CK_ATTRIBUTE template[1];
01639     CK_ATTRIBUTE *attrs = template;
01640     CK_BBOOL cktrue = CK_TRUE;
01641     CK_RV crv;
01642     CK_OBJECT_HANDLE newKeyID;
01643     CK_SESSION_HANDLE rwsession;
01644 
01645     PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
01646 
01647     PK11_Authenticate(slot, PR_TRUE, wincx);
01648     rwsession = PK11_GetRWSession(slot);
01649     if (rwsession == CK_INVALID_SESSION) {
01650        PORT_SetError(SEC_ERROR_BAD_DATA);
01651        return NULL;
01652     }
01653     crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID,
01654         template, 1, &newKeyID);
01655     PK11_RestoreROSession(slot, rwsession);
01656 
01657     if (crv != CKR_OK) {
01658         PORT_SetError( PK11_MapError(crv) );
01659         return NULL;
01660     }
01661 
01662     return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
01663         newKeyID, NULL /*wincx*/);
01664 }
01665 
01666 /*
01667  * destroy a private key if there are no matching certs.
01668  * this function also frees the privKey structure.
01669  */
01670 SECStatus
01671 PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force)
01672 {
01673     CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);
01674 
01675     /* found a cert matching the private key?. */
01676     if (!force  && cert != NULL) {
01677        /* yes, don't delete the key */
01678         CERT_DestroyCertificate(cert);
01679        SECKEY_DestroyPrivateKey(privKey);
01680        return SECWouldBlock;
01681     }
01682     /* now, then it's safe for the key to go away */
01683     PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);
01684     SECKEY_DestroyPrivateKey(privKey);
01685     return SECSuccess;
01686 }
01687 
01688 /*
01689  * destroy a private key if there are no matching certs.
01690  * this function also frees the privKey structure.
01691  */
01692 SECStatus
01693 PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey)
01694 {
01695     /* now, then it's safe for the key to go away */
01696     if (pubKey->pkcs11Slot == NULL) {
01697        return SECFailure;
01698     }
01699     PK11_DestroyTokenObject(pubKey->pkcs11Slot,pubKey->pkcs11ID);
01700     SECKEY_DestroyPublicKey(pubKey);
01701     return SECSuccess;
01702 }
01703 
01704 /*
01705  * key call back structure.
01706  */
01707 typedef struct pk11KeyCallbackStr {
01708        SECStatus (* callback)(SECKEYPrivateKey *,void *);
01709        void *callbackArg;
01710        void *wincx;
01711 } pk11KeyCallback;
01712 
01713 /*
01714  * callback to map Object Handles to Private Keys;
01715  */
01716 SECStatus
01717 pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
01718 {
01719     SECStatus rv = SECSuccess;
01720     SECKEYPrivateKey *privKey;
01721     pk11KeyCallback *keycb = (pk11KeyCallback *) arg;
01722     if (!arg) {
01723         return SECFailure;
01724     }
01725 
01726     privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);
01727 
01728     if (privKey == NULL) {
01729        return SECFailure;
01730     }
01731 
01732     if (keycb->callback) {
01733        rv = (*keycb->callback)(privKey,keycb->callbackArg);
01734     }
01735 
01736     SECKEY_DestroyPrivateKey(privKey);        
01737     return rv;
01738 }
01739 
01740 /***********************************************************************
01741  * PK11_TraversePrivateKeysInSlot
01742  *
01743  * Traverses all the private keys on a slot.
01744  *
01745  * INPUTS
01746  *      slot
01747  *          The PKCS #11 slot whose private keys you want to traverse.
01748  *      callback
01749  *          A callback function that will be called for each key.
01750  *      arg
01751  *          An argument that will be passed to the callback function.
01752  */
01753 SECStatus
01754 PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot,
01755     SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg)
01756 {
01757     pk11KeyCallback perKeyCB;
01758     pk11TraverseSlot perObjectCB;
01759     CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY;
01760     CK_BBOOL ckTrue = CK_TRUE;
01761     CK_ATTRIBUTE theTemplate[2];
01762     int templateSize = 2;
01763 
01764     theTemplate[0].type = CKA_CLASS;
01765     theTemplate[0].pValue = &privkClass;
01766     theTemplate[0].ulValueLen = sizeof(privkClass);
01767     theTemplate[1].type = CKA_TOKEN;
01768     theTemplate[1].pValue = &ckTrue;
01769     theTemplate[1].ulValueLen = sizeof(ckTrue);
01770 
01771     if(slot==NULL) {
01772         return SECSuccess;
01773     }
01774 
01775     perObjectCB.callback = pk11_DoKeys;
01776     perObjectCB.callbackArg = &perKeyCB;
01777     perObjectCB.findTemplate = theTemplate;
01778     perObjectCB.templateCount = templateSize;
01779     perKeyCB.callback = callback;
01780     perKeyCB.callbackArg = arg;
01781     perKeyCB.wincx = NULL;
01782 
01783     return PK11_TraverseSlot(slot, &perObjectCB);
01784 }
01785 
01786 /*
01787  * return the private key with the given ID
01788  */
01789 CK_OBJECT_HANDLE
01790 pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)
01791 {
01792     CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
01793     CK_ATTRIBUTE theTemplate[] = {
01794        { CKA_ID, NULL, 0 },
01795        { CKA_CLASS, NULL, 0 },
01796     };
01797     /* if you change the array, change the variable below as well */
01798     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
01799     CK_ATTRIBUTE *attrs = theTemplate;
01800 
01801     PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++;
01802     PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
01803 
01804     return pk11_FindObjectByTemplate(slot,theTemplate,tsize);
01805 } 
01806 
01807 
01808 SECKEYPrivateKey *
01809 PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
01810 {
01811     CK_OBJECT_HANDLE keyHandle;
01812     SECKEYPrivateKey *privKey;
01813 
01814     keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
01815     if (keyHandle == CK_INVALID_HANDLE) { 
01816        return NULL;
01817     }
01818     privKey =  PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
01819     return privKey;
01820 }
01821 
01822 /*
01823  * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
01824  * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
01825  * smart cards happy.
01826  */
01827 SECItem *
01828 PK11_MakeIDFromPubKey(SECItem *pubKeyData) 
01829 {
01830     PK11Context *context;
01831     SECItem *certCKA_ID;
01832     SECStatus rv;
01833 
01834     context = PK11_CreateDigestContext(SEC_OID_SHA1);
01835     if (context == NULL) {
01836        return NULL;
01837     }
01838 
01839     rv = PK11_DigestBegin(context);
01840     if (rv == SECSuccess) {
01841        rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len);
01842     }
01843     if (rv != SECSuccess) {
01844        PK11_DestroyContext(context,PR_TRUE);
01845        return NULL;
01846     }
01847 
01848     certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
01849     if (certCKA_ID == NULL) {
01850        PK11_DestroyContext(context,PR_TRUE);
01851        return NULL;
01852     }
01853 
01854     certCKA_ID->len = SHA1_LENGTH;
01855     certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len);
01856     if (certCKA_ID->data == NULL) {
01857        PORT_Free(certCKA_ID);
01858        PK11_DestroyContext(context,PR_TRUE);
01859         return NULL;
01860     }
01861 
01862     rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len,
01863                                                         SHA1_LENGTH);
01864     PK11_DestroyContext(context,PR_TRUE);
01865     if (rv != SECSuccess) {
01866        SECITEM_FreeItem(certCKA_ID,PR_TRUE);
01867        return NULL;
01868     }
01869 
01870     return certCKA_ID;
01871 }
01872 
01873 SECItem *
01874 PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx)
01875 {
01876     CK_ATTRIBUTE theTemplate[] = {
01877        { CKA_ID, NULL, 0 },
01878     };
01879     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
01880     SECItem *item = NULL;
01881     CK_RV crv;
01882 
01883     crv = PK11_GetAttributes(NULL,key->pkcs11Slot,key->pkcs11ID,
01884                                                  theTemplate,tsize);
01885     if (crv != CKR_OK) {
01886        PORT_SetError( PK11_MapError(crv) );
01887        goto loser;
01888     }
01889 
01890     item = PORT_ZNew(SECItem);
01891     if (item) {
01892         item->data = (unsigned char*) theTemplate[0].pValue;
01893         item->len = theTemplate[0].ulValueLen;
01894     }
01895 
01896 loser:
01897     return item;
01898 }
01899 
01900 SECItem *
01901 PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey)
01902 {
01903     return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID);
01904 }
01905 
01906 static SECStatus
01907 privateKeyListCallback(SECKEYPrivateKey *key, void *arg)
01908 {
01909     SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList*)arg;
01910     return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key));
01911 }
01912 
01913 SECKEYPrivateKeyList*
01914 PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot)
01915 {
01916     SECStatus status;
01917     SECKEYPrivateKeyList *keys;
01918 
01919     keys = SECKEY_NewPrivateKeyList();
01920     if(keys == NULL) return NULL;
01921 
01922     status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback,
01923               (void*)keys);
01924 
01925     if( status != SECSuccess ) {
01926        SECKEY_DestroyPrivateKeyList(keys);
01927        keys = NULL;
01928     }
01929 
01930     return keys;
01931 }
01932 
01933 SECKEYPublicKeyList*
01934 PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname)
01935 {
01936     CK_ATTRIBUTE findTemp[4];
01937     CK_ATTRIBUTE *attrs;
01938     CK_BBOOL ckTrue = CK_TRUE;
01939     CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY;
01940     int tsize = 0;
01941     int objCount = 0;
01942     CK_OBJECT_HANDLE *key_ids;
01943     SECKEYPublicKeyList *keys;
01944     int i,len;
01945 
01946 
01947     attrs = findTemp;
01948     PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
01949     PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
01950     if (nickname) {
01951        len = PORT_Strlen(nickname)-1;
01952        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
01953     }
01954     tsize = attrs - findTemp;
01955     PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
01956 
01957     key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
01958     if (key_ids == NULL) {
01959        return NULL;
01960     }
01961     keys = SECKEY_NewPublicKeyList();
01962     if (keys == NULL) {
01963        PORT_Free(key_ids);
01964        return NULL;
01965     }
01966 
01967     for (i=0; i < objCount ; i++) {
01968        SECKEYPublicKey *pubKey = 
01969                             PK11_ExtractPublicKey(slot,nullKey,key_ids[i]);
01970        if (pubKey) {
01971            SECKEY_AddPublicKeyToListTail(keys, pubKey);
01972        }
01973    }
01974 
01975    PORT_Free(key_ids);
01976    return keys;
01977 }
01978 
01979 SECKEYPrivateKeyList*
01980 PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
01981 {
01982     CK_ATTRIBUTE findTemp[4];
01983     CK_ATTRIBUTE *attrs;
01984     CK_BBOOL ckTrue = CK_TRUE;
01985     CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
01986     int tsize = 0;
01987     int objCount = 0;
01988     CK_OBJECT_HANDLE *key_ids;
01989     SECKEYPrivateKeyList *keys;
01990     int i,len;
01991 
01992 
01993     attrs = findTemp;
01994     PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
01995     PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
01996     if (nickname) {
01997        len = PORT_Strlen(nickname)-1;
01998        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
01999     }
02000     tsize = attrs - findTemp;
02001     PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
02002 
02003     key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
02004     if (key_ids == NULL) {
02005        return NULL;
02006     }
02007     keys = SECKEY_NewPrivateKeyList();
02008     if (keys == NULL) {
02009        PORT_Free(key_ids);
02010        return NULL;
02011     }
02012 
02013     for (i=0; i < objCount ; i++) {
02014        SECKEYPrivateKey *privKey = 
02015               PK11_MakePrivKey(slot,nullKey,PR_TRUE,key_ids[i],wincx);
02016        SECKEY_AddPrivateKeyToListTail(keys, privKey);
02017    }
02018 
02019    PORT_Free(key_ids);
02020    return keys;
02021 }
02022