security/nss/lib/pk11wrap/pk11akey.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 /*
     5  * This file contains functions to manage asymetric keys, (public and
     6  * private keys).
     7  */
     8 #include "seccomon.h"
     9 #include "secmod.h"
    10 #include "secmodi.h"
    11 #include "secmodti.h"
    12 #include "pkcs11.h"
    13 #include "pkcs11t.h"
    14 #include "pk11func.h"
    15 #include "cert.h"
    16 #include "key.h"
    17 #include "secitem.h"
    18 #include "secasn1.h" 
    19 #include "secoid.h" 
    20 #include "secerr.h"
    21 #include "sslerr.h"
    22 #include "sechash.h"
    24 #include "secpkcs5.h"  
    25 #include "blapit.h"
    27 static SECItem *
    28 pk11_MakeIDFromPublicKey(SECKEYPublicKey *pubKey)
    29 {
    30     /* set the ID to the public key so we can find it again */
    31     SECItem *pubKeyIndex =  NULL;
    32     switch (pubKey->keyType) {
    33     case rsaKey:
    34       pubKeyIndex = &pubKey->u.rsa.modulus;
    35       break;
    36     case dsaKey:
    37       pubKeyIndex = &pubKey->u.dsa.publicValue;
    38       break;
    39     case dhKey:
    40       pubKeyIndex = &pubKey->u.dh.publicValue;
    41       break;      
    42     case ecKey:
    43       pubKeyIndex = &pubKey->u.ec.publicValue;
    44       break;      
    45     default:
    46       return NULL;
    47     }
    48     PORT_Assert(pubKeyIndex != NULL);
    50     return PK11_MakeIDFromPubKey(pubKeyIndex);
    51 } 
    53 /*
    54  * import a public key into the desired slot
    55  *
    56  * This function takes a public key structure and creates a public key in a 
    57  * given slot. If isToken is set, then a persistant public key is created.
    58  *
    59  * Note: it is possible for this function to return a handle for a key which
    60  * is persistant, even if isToken is not set.
    61  */
    62 CK_OBJECT_HANDLE
    63 PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, 
    64 								PRBool isToken)
    65 {
    66     CK_BBOOL cktrue = CK_TRUE;
    67     CK_BBOOL ckfalse = CK_FALSE;
    68     CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
    69     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
    70     CK_OBJECT_HANDLE objectID;
    71     CK_ATTRIBUTE theTemplate[11];
    72     CK_ATTRIBUTE *signedattr = NULL;
    73     CK_ATTRIBUTE *attrs = theTemplate;
    74     SECItem *ckaId = NULL;
    75     SECItem *pubValue = NULL;
    76     int signedcount = 0;
    77     int templateCount = 0;
    78     SECStatus rv;
    80     /* if we already have an object in the desired slot, use it */
    81     if (!isToken && pubKey->pkcs11Slot == slot) {
    82 	return pubKey->pkcs11ID;
    83     }
    85     /* free the existing key */
    86     if (pubKey->pkcs11Slot != NULL) {
    87 	PK11SlotInfo *oSlot = pubKey->pkcs11Slot;
    88 	if (!PK11_IsPermObject(pubKey->pkcs11Slot,pubKey->pkcs11ID)) {
    89 	    PK11_EnterSlotMonitor(oSlot);
    90 	    (void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
    91 							pubKey->pkcs11ID);
    92 	    PK11_ExitSlotMonitor(oSlot);
    93 	}
    94 	PK11_FreeSlot(oSlot);
    95 	pubKey->pkcs11Slot = NULL;
    96     }
    97     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
    98     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
    99     PK11_SETATTRS(attrs, CKA_TOKEN, isToken ? &cktrue : &ckfalse,
   100 						 sizeof(CK_BBOOL) ); attrs++;
   101     if (isToken) {
   102 	ckaId = pk11_MakeIDFromPublicKey(pubKey);
   103 	if (ckaId == NULL) {
   104 	    PORT_SetError( SEC_ERROR_BAD_KEY );
   105 	    return CK_INVALID_HANDLE;
   106 	}
   107 	PK11_SETATTRS(attrs, CKA_ID, ckaId->data, ckaId->len); attrs++;
   108     }
   110     /* now import the key */
   111     {
   112         switch (pubKey->keyType) {
   113         case rsaKey:
   114 	    keyType = CKK_RSA;
   115 	    PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, sizeof(CK_BBOOL) ); attrs++;
   116 	    PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue, 
   117 						sizeof(CK_BBOOL) ); attrs++;
   118 	    PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); attrs++;
   119  	    signedattr = attrs;
   120 	    PK11_SETATTRS(attrs, CKA_MODULUS, pubKey->u.rsa.modulus.data,
   121 					 pubKey->u.rsa.modulus.len); attrs++;
   122 	    PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
   123 	     	pubKey->u.rsa.publicExponent.data,
   124 				 pubKey->u.rsa.publicExponent.len); attrs++;
   125 	    break;
   126         case dsaKey:
   127 	    keyType = CKK_DSA;
   128 	    PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
   129  	    signedattr = attrs;
   130 	    PK11_SETATTRS(attrs, CKA_PRIME,    pubKey->u.dsa.params.prime.data,
   131 				pubKey->u.dsa.params.prime.len); attrs++;
   132 	    PK11_SETATTRS(attrs,CKA_SUBPRIME,pubKey->u.dsa.params.subPrime.data,
   133 				pubKey->u.dsa.params.subPrime.len); attrs++;
   134 	    PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.dsa.params.base.data,
   135 					pubKey->u.dsa.params.base.len); attrs++;
   136 	    PK11_SETATTRS(attrs, CKA_VALUE,    pubKey->u.dsa.publicValue.data, 
   137 					pubKey->u.dsa.publicValue.len); attrs++;
   138 	    break;
   139 	case fortezzaKey:
   140 	    keyType = CKK_DSA;
   141 	    PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
   142  	    signedattr = attrs;
   143 	    PK11_SETATTRS(attrs, CKA_PRIME,pubKey->u.fortezza.params.prime.data,
   144 				pubKey->u.fortezza.params.prime.len); attrs++;
   145 	    PK11_SETATTRS(attrs,CKA_SUBPRIME,
   146 				pubKey->u.fortezza.params.subPrime.data,
   147 				pubKey->u.fortezza.params.subPrime.len);attrs++;
   148 	    PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.fortezza.params.base.data,
   149 				pubKey->u.fortezza.params.base.len); attrs++;
   150 	    PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.fortezza.DSSKey.data, 
   151 				pubKey->u.fortezza.DSSKey.len); attrs++;
   152             break;
   153         case dhKey:
   154 	    keyType = CKK_DH;
   155 	    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
   156  	    signedattr = attrs;
   157 	    PK11_SETATTRS(attrs, CKA_PRIME,    pubKey->u.dh.prime.data,
   158 				pubKey->u.dh.prime.len); attrs++;
   159 	    PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.dh.base.data,
   160 					pubKey->u.dh.base.len); attrs++;
   161 	    PK11_SETATTRS(attrs, CKA_VALUE,    pubKey->u.dh.publicValue.data, 
   162 					pubKey->u.dh.publicValue.len); attrs++;
   163 	    break;
   164         case ecKey:
   165 	    keyType = CKK_EC;
   166 	    PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
   167 	    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
   168  	    signedattr = attrs;
   169 	    PK11_SETATTRS(attrs, CKA_EC_PARAMS, 
   170 		          pubKey->u.ec.DEREncodedParams.data,
   171 		          pubKey->u.ec.DEREncodedParams.len); attrs++;
   172 	    if (PR_GetEnv("NSS_USE_DECODED_CKA_EC_POINT")) {
   173 	    	PK11_SETATTRS(attrs, CKA_EC_POINT, 
   174 			  pubKey->u.ec.publicValue.data,
   175 			  pubKey->u.ec.publicValue.len); attrs++;
   176 	    } else {
   177 		pubValue = SEC_ASN1EncodeItem(NULL, NULL,
   178 			&pubKey->u.ec.publicValue,
   179 			SEC_ASN1_GET(SEC_OctetStringTemplate));
   180 		if (pubValue == NULL) {
   181 		    if (ckaId) {
   182 			SECITEM_FreeItem(ckaId,PR_TRUE);
   183 		    }
   184 		    return CK_INVALID_HANDLE;
   185 		}
   186 	    	PK11_SETATTRS(attrs, CKA_EC_POINT, 
   187 			  pubValue->data, pubValue->len); attrs++;
   188 	    }
   189 	    break;
   190 	default:
   191 	    if (ckaId) {
   192 		SECITEM_FreeItem(ckaId,PR_TRUE);
   193 	    }
   194 	    PORT_SetError( SEC_ERROR_BAD_KEY );
   195 	    return CK_INVALID_HANDLE;
   196 	}
   198 	templateCount = attrs - theTemplate;
   199 	signedcount = attrs - signedattr;
   200 	PORT_Assert(templateCount <= (sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)));
   201 	for (attrs=signedattr; signedcount; attrs++, signedcount--) {
   202 		pk11_SignedToUnsigned(attrs);
   203 	} 
   204         rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
   205 				 	templateCount, isToken, &objectID);
   206 	if (ckaId) {
   207 	    SECITEM_FreeItem(ckaId,PR_TRUE);
   208 	}
   209 	if (pubValue) {
   210 	    SECITEM_FreeItem(pubValue,PR_TRUE);
   211 	}
   212 	if ( rv != SECSuccess) {
   213 	    return CK_INVALID_HANDLE;
   214 	}
   215     }
   217     pubKey->pkcs11ID = objectID;
   218     pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
   220     return objectID;
   221 }
   223 /*
   224  * take an attribute and copy it into a secitem
   225  */
   226 static CK_RV
   227 pk11_Attr2SecItem(PLArenaPool *arena, const CK_ATTRIBUTE *attr, SECItem *item)
   228 {
   229     item->data = NULL;
   231     (void)SECITEM_AllocItem(arena, item, attr->ulValueLen);
   232     if (item->data == NULL) {
   233 	return CKR_HOST_MEMORY;
   234     } 
   235     PORT_Memcpy(item->data, attr->pValue, item->len);
   236     return CKR_OK;
   237 }
   240 /*
   241  * get a curve length from a set of ecParams.
   242  * 
   243  * We need this so we can reliably determine if the ecPoint passed to us
   244  * was encoded or not. With out this, for many curves, we would incorrectly
   245  * identify an unencoded curve as an encoded curve 1 in 65536 times, and for
   246  * a few we would make that same mistake 1 in 32768 times. These are bad 
   247  * numbers since they are rare enough to pass tests, but common enough to
   248  * be tripped over in the field. 
   249  *
   250  * This function will only work for curves we recognized as of March 2009.
   251  * The assumption is curves in use after March of 2009 would be supplied by
   252  * PKCS #11 modules that already pass the correct encoding to us.
   253  *
   254  * Point length = (Roundup(curveLenInBits/8)*2+1)
   255  */
   256 static int
   257 pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams)
   258 {
   259    SECItem oid;
   260    SECOidTag tag;
   261    SECStatus rv;
   263    /* decode the OID tag */
   264    rv = SEC_QuickDERDecodeItem(arena, &oid,
   265 		SEC_ASN1_GET(SEC_ObjectIDTemplate), ecParams);
   266    if (rv != SECSuccess) {
   267 	/* could be explict curves, allow them to work if the 
   268 	 * PKCS #11 module support them. If we try to parse the
   269 	 * explicit curve value in the future, we may return -1 here
   270 	 * to indicate an invalid parameter if the explicit curve
   271 	 * decode fails. */
   272 	return 0;
   273    }
   275    tag = SECOID_FindOIDTag(&oid);
   276    switch (tag) {
   277     case SEC_OID_SECG_EC_SECP112R1:
   278     case SEC_OID_SECG_EC_SECP112R2:
   279 	return 29; /* curve len in bytes = 14 bytes */
   280     case SEC_OID_SECG_EC_SECT113R1:
   281     case SEC_OID_SECG_EC_SECT113R2:
   282 	return 31; /* curve len in bytes = 15 bytes */
   283     case SEC_OID_SECG_EC_SECP128R1:
   284     case SEC_OID_SECG_EC_SECP128R2:
   285 	return 33; /* curve len in bytes = 16 bytes */
   286     case SEC_OID_SECG_EC_SECT131R1:
   287     case SEC_OID_SECG_EC_SECT131R2:
   288 	return 35; /* curve len in bytes = 17 bytes */
   289     case SEC_OID_SECG_EC_SECP160K1:
   290     case SEC_OID_SECG_EC_SECP160R1:
   291     case SEC_OID_SECG_EC_SECP160R2:
   292 	return 41; /* curve len in bytes = 20 bytes */
   293     case SEC_OID_SECG_EC_SECT163K1:
   294     case SEC_OID_SECG_EC_SECT163R1:
   295     case SEC_OID_SECG_EC_SECT163R2:
   296     case SEC_OID_ANSIX962_EC_C2PNB163V1:
   297     case SEC_OID_ANSIX962_EC_C2PNB163V2:
   298     case SEC_OID_ANSIX962_EC_C2PNB163V3:
   299 	return 43; /* curve len in bytes = 21 bytes */
   300     case SEC_OID_ANSIX962_EC_C2PNB176V1:
   301 	return 45; /* curve len in bytes = 22 bytes */
   302     case SEC_OID_ANSIX962_EC_C2TNB191V1:
   303     case SEC_OID_ANSIX962_EC_C2TNB191V2:
   304     case SEC_OID_ANSIX962_EC_C2TNB191V3:
   305     case SEC_OID_SECG_EC_SECP192K1:
   306     case SEC_OID_ANSIX962_EC_PRIME192V1:
   307     case SEC_OID_ANSIX962_EC_PRIME192V2:
   308     case SEC_OID_ANSIX962_EC_PRIME192V3:
   309 	return 49; /*curve len in bytes = 24 bytes */
   310     case SEC_OID_SECG_EC_SECT193R1:
   311     case SEC_OID_SECG_EC_SECT193R2:
   312 	return 51; /*curve len in bytes = 25 bytes */
   313     case SEC_OID_ANSIX962_EC_C2PNB208W1:
   314 	return 53; /*curve len in bytes = 26 bytes */
   315     case SEC_OID_SECG_EC_SECP224K1:
   316     case SEC_OID_SECG_EC_SECP224R1:
   317 	return 57; /*curve len in bytes = 28 bytes */
   318     case SEC_OID_SECG_EC_SECT233K1:
   319     case SEC_OID_SECG_EC_SECT233R1:
   320     case SEC_OID_SECG_EC_SECT239K1:
   321     case SEC_OID_ANSIX962_EC_PRIME239V1:
   322     case SEC_OID_ANSIX962_EC_PRIME239V2:
   323     case SEC_OID_ANSIX962_EC_PRIME239V3:
   324     case SEC_OID_ANSIX962_EC_C2TNB239V1:
   325     case SEC_OID_ANSIX962_EC_C2TNB239V2:
   326     case SEC_OID_ANSIX962_EC_C2TNB239V3:
   327 	return 61; /*curve len in bytes = 30 bytes */
   328     case SEC_OID_ANSIX962_EC_PRIME256V1:
   329     case SEC_OID_SECG_EC_SECP256K1:
   330 	return 65; /*curve len in bytes = 32 bytes */
   331     case SEC_OID_ANSIX962_EC_C2PNB272W1:
   332 	return 69; /*curve len in bytes = 34 bytes */
   333     case SEC_OID_SECG_EC_SECT283K1:
   334     case SEC_OID_SECG_EC_SECT283R1:
   335 	return 73; /*curve len in bytes = 36 bytes */
   336     case SEC_OID_ANSIX962_EC_C2PNB304W1:
   337 	return 77; /*curve len in bytes = 38 bytes */
   338     case SEC_OID_ANSIX962_EC_C2TNB359V1:
   339 	return 91; /*curve len in bytes = 45 bytes */
   340     case SEC_OID_ANSIX962_EC_C2PNB368W1:
   341 	return 93; /*curve len in bytes = 46 bytes */
   342     case SEC_OID_SECG_EC_SECP384R1:
   343 	return 97; /*curve len in bytes = 48 bytes */
   344     case SEC_OID_SECG_EC_SECT409K1:
   345     case SEC_OID_SECG_EC_SECT409R1:
   346 	return 105; /*curve len in bytes = 52 bytes */
   347     case SEC_OID_ANSIX962_EC_C2TNB431R1:
   348 	return 109; /*curve len in bytes = 54 bytes */
   349     case SEC_OID_SECG_EC_SECP521R1:
   350 	return 133; /*curve len in bytes = 66 bytes */
   351     case SEC_OID_SECG_EC_SECT571K1:
   352     case SEC_OID_SECG_EC_SECT571R1:
   353 	return 145; /*curve len in bytes = 72 bytes */
   354     /* unknown or unrecognized OIDs. return unknown length */
   355     default:
   356 	break;
   357    }
   358    return 0;
   359 }
   361 /*
   362  * returns the decoded point. In some cases the point may already be decoded.
   363  * this function tries to detect those cases and return the point in 
   364  * publicKeyValue. In other cases it's DER encoded. In those cases the point
   365  * is first decoded and returned. Space for the point is allocated out of 
   366  * the passed in arena.
   367  */
   368 static CK_RV
   369 pk11_get_Decoded_ECPoint(PLArenaPool *arena, const SECItem *ecParams,
   370 	const CK_ATTRIBUTE *ecPoint, SECItem *publicKeyValue)
   371 {
   372     SECItem encodedPublicValue;
   373     SECStatus rv;
   374     int keyLen;
   376     if (ecPoint->ulValueLen == 0) {
   377 	return CKR_ATTRIBUTE_VALUE_INVALID;
   378     }
   380     /*
   381      * The PKCS #11 spec requires ecPoints to be encoded as a DER OCTET String.
   382      * NSS has mistakenly passed unencoded values, and some PKCS #11 vendors
   383      * followed that mistake. Now we need to detect which encoding we were
   384      * passed in. The task is made more complicated by the fact the the
   385      * DER encoding byte (SEC_ASN_OCTET_STRING) is the same as the 
   386      * EC_POINT_FORM_UNCOMPRESSED byte (0x04), so we can't use that to
   387      * determine which curve we are using.
   388      */
   390     /* get the expected key length for the passed in curve.
   391      * pk11_get_EC_PointLenInBytes only returns valid values for curves
   392      * NSS has traditionally recognized. If the curve is not recognized,
   393      * it will return '0', and we have to figure out if the key was
   394      * encoded or not heuristically. If the ecParams are invalid, it
   395      * will return -1 for the keyLen.
   396      */
   397     keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams);
   398     if (keyLen < 0) {
   399 	return CKR_ATTRIBUTE_VALUE_INVALID;
   400     }
   403     /* If the point is uncompressed and the lengths match, it
   404      * must be an unencoded point */
   405     if ((*((char *)ecPoint->pValue) == EC_POINT_FORM_UNCOMPRESSED) 
   406 	&& (ecPoint->ulValueLen == keyLen)) {
   407 	    return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
   408     }
   410     /* now assume the key passed to us was encoded and decode it */
   411     if (*((char *)ecPoint->pValue) == SEC_ASN1_OCTET_STRING) {
   412 	/* OK, now let's try to decode it and see if it's valid */
   413 	encodedPublicValue.data = ecPoint->pValue;
   414 	encodedPublicValue.len = ecPoint->ulValueLen;
   415 	rv = SEC_QuickDERDecodeItem(arena, publicKeyValue,
   416 		SEC_ASN1_GET(SEC_OctetStringTemplate), &encodedPublicValue);
   418 	/* it coded correctly & we know the key length (and they match)
   419 	 * then we are done, return the results. */
   420         if (keyLen && rv == SECSuccess && publicKeyValue->len == keyLen) {
   421 	    return CKR_OK;
   422 	}
   424 	/* if we know the key length, one of the above tests should have
   425 	 * succeded. If it doesn't the module gave us bad data */
   426 	if (keyLen) {
   427 	    return CKR_ATTRIBUTE_VALUE_INVALID;
   428 	}
   431 	/* We don't know the key length, so we don't know deterministically
   432 	 * which encoding was used. We now will try to pick the most likely 
   433 	 * form that's correct, with a preference for the encoded form if we
   434 	 * can't determine for sure. We do this by checking the key we got
   435 	 * back from SEC_QuickDERDecodeItem for defects. If no defects are
   436 	 * found, we assume the encoded parameter was was passed to us.
   437 	 * our defect tests include:
   438 	 *   1) it didn't decode.
   439 	 *   2) The decode key had an invalid length (must be odd).
   440 	 *   3) The decoded key wasn't an UNCOMPRESSED key.
   441 	 *   4) The decoded key didn't include the entire encoded block
   442 	 *   except the DER encoding values. (fixing DER length to one
   443 	 *   particular value).
   444 	 */
   445 	if ((rv != SECSuccess)
   446 	    || ((publicKeyValue->len & 1) != 1)
   447 	    || (publicKeyValue->data[0] != EC_POINT_FORM_UNCOMPRESSED)
   448 	    || (PORT_Memcmp(&encodedPublicValue.data[encodedPublicValue.len -
   449 		 	    publicKeyValue->len], publicKeyValue->data, 
   450 			    publicKeyValue->len) != 0)) {
   451 	    /* The decoded public key was flawed, the original key must have
   452 	     * already been in decoded form. Do a quick sanity check then 
   453 	     * return the original key value.
   454 	     */
   455 	    if ((encodedPublicValue.len & 1) == 0) {
   456 		return CKR_ATTRIBUTE_VALUE_INVALID;
   457 	    }
   458 	    return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
   459 	}
   461 	/* as best we can figure, the passed in key was encoded, and we've
   462 	 * now decoded it. Note: there is a chance this could be wrong if the 
   463 	 * following conditions hold:
   464 	 *  1) The first byte or bytes of the X point looks like a valid length
   465 	 * of precisely the right size (2*curveSize -1). this means for curves
   466 	 * less than 512 bits (64 bytes), this will happen 1 in 256 times*.
   467 	 * for curves between 512 and 1024, this will happen 1 in 65,536 times*
   468 	 * for curves between 1024 and 256K this will happen 1 in 16 million*
   469 	 *  2) The length of the 'DER length field' is odd 
   470 	 * (making both the encoded and decode
   471 	 * values an odd length. this is true of all curves less than 512,
   472 	 * as well as curves between 1024 and 256K).
   473 	 *  3) The X[length of the 'DER length field'] == 0x04, 1 in 256.
   474 	 *
   475 	 *  (* assuming all values are equally likely in the first byte, 
   476 	 * This isn't true if the curve length is not a multiple of 8. In these
   477 	 * cases, if the DER length is possible, it's more likely, 
   478 	 * if it's not possible, then we have no false decodes).
   479 	 * 
   480 	 * For reference here are the odds for the various curves we currently
   481 	 * have support for (and the only curves SSL will negotiate at this
   482 	 * time). NOTE: None of the supported curves will show up here 
   483 	 * because we return a valid length for all of these curves. 
   484 	 * The only way to get here is to have some application (not SSL) 
   485 	 * which supports some unknown curve and have some vendor supplied 
   486 	 * PKCS #11 module support that curve. NOTE: in this case, one 
   487 	 * presumes that that pkcs #11 module is likely to be using the 
   488 	 * correct encodings.
   489 	 *
   490 	 * Prime Curves (GFp):
   491 	 *   Bit	False	    Odds of 
   492 	 *  Size	DER Len	 False Decode Positive
   493 	 *  112 	27	   1 in 65536 
   494 	 *  128 	31	   1 in 65536 
   495 	 *  160 	39	   1 in 65536 
   496 	 *  192 	47	   1 in 65536 
   497 	 *  224 	55	   1 in 65536 
   498 	 *  239 	59	   1 in 32768 (top byte can only be 0-127)
   499 	 *  256 	63	   1 in 65536 
   500 	 *  521 	129,131	     0        (decoded value would be even)
   501 	 *
   502 	 * Binary curves (GF2m).
   503 	 *   Bit	False	    Odds of 
   504 	 *  Size	DER Len	 False Decode Positive
   505 	 *  131 	33	     0        (top byte can only be 0-7)
   506 	 *  163 	41	     0        (top byte can only be 0-7)
   507 	 *  176 	43	   1 in 65536 
   508 	 *  191 	47	   1 in 32768 (top byte can only be 0-127)
   509 	 *  193 	49	     0        (top byte can only be 0-1)
   510 	 *  208 	51	   1 in 65536 
   511 	 *  233 	59	     0        (top byte can only be 0-1)
   512 	 *  239 	59	   1 in 32768 (top byte can only be 0-127)
   513 	 *  272 	67	   1 in 65536 
   514 	 *  283 	71	     0        (top byte can only be 0-7)
   515 	 *  304 	75	   1 in 65536 
   516 	 *  359 	89	   1 in 32768 (top byte can only be 0-127)
   517 	 *  368 	91	   1 in 65536 
   518 	 *  409 	103	     0        (top byte can only be 0-1)
   519 	 *  431 	107	   1 in 32768 (top byte can only be 0-127)
   520 	 *  571 	129,143	     0        (decoded value would be even)
   521 	 *
   522 	 */
   524 	return CKR_OK;
   525     }
   527     /* In theory, we should handle the case where the curve == 0 and
   528      * the first byte is EC_POINT_FORM_UNCOMPRESSED, (which would be
   529      * handled by doing a santity check on the key length and returning
   530      * pk11_Attr2SecItem() to copy the ecPoint to the publicKeyValue).
   531      *
   532      * This test is unnecessary, however, due to the fact that 
   533      * EC_POINT_FORM_UNCOMPRESSED == SEC_ASIN1_OCTET_STRING, that case is
   534      * handled in the above if. That means if we get here, the initial
   535      * byte of our ecPoint value was invalid, so we can safely return.
   536      * invalid attribute.
   537      */
   539     return CKR_ATTRIBUTE_VALUE_INVALID;
   540 }
   542 /*
   543  * extract a public key from a slot and id
   544  */
   545 SECKEYPublicKey *
   546 PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id)
   547 {
   548     CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
   549     PLArenaPool *arena;
   550     PLArenaPool *tmp_arena;
   551     SECKEYPublicKey *pubKey;
   552     int templateCount = 0;
   553     CK_KEY_TYPE pk11KeyType;
   554     CK_RV crv;
   555     CK_ATTRIBUTE template[8];
   556     CK_ATTRIBUTE *attrs= template;
   557     CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value;
   558     CK_ATTRIBUTE *ecparams;
   560     /* if we didn't know the key type, get it */
   561     if (keyType== nullKey) {
   563         pk11KeyType = PK11_ReadULongAttribute(slot,id,CKA_KEY_TYPE);
   564 	if (pk11KeyType ==  CK_UNAVAILABLE_INFORMATION) {
   565 	    return NULL;
   566 	}
   567 	switch (pk11KeyType) {
   568 	case CKK_RSA:
   569 	    keyType = rsaKey;
   570 	    break;
   571 	case CKK_DSA:
   572 	    keyType = dsaKey;
   573 	    break;
   574 	case CKK_DH:
   575 	    keyType = dhKey;
   576 	    break;
   577 	case CKK_EC:
   578 	    keyType = ecKey;
   579 	    break;
   580 	default:
   581 	    PORT_SetError( SEC_ERROR_BAD_KEY );
   582 	    return NULL;
   583 	}
   584     }
   587     /* now we need to create space for the public key */
   588     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
   589     if (arena == NULL) return NULL;
   590     tmp_arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
   591     if (tmp_arena == NULL) {
   592 	PORT_FreeArena (arena, PR_FALSE);
   593 	return NULL;
   594     }
   597     pubKey = (SECKEYPublicKey *) 
   598 			PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
   599     if (pubKey == NULL) {
   600 	PORT_FreeArena (arena, PR_FALSE);
   601 	PORT_FreeArena (tmp_arena, PR_FALSE);
   602 	return NULL;
   603     }
   605     pubKey->arena = arena;
   606     pubKey->keyType = keyType;
   607     pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
   608     pubKey->pkcs11ID = id;
   609     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, 
   610 						sizeof(keyClass)); attrs++;
   611     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType, 
   612 						sizeof(pk11KeyType) ); attrs++;
   613     switch (pubKey->keyType) {
   614     case rsaKey:
   615 	modulus = attrs;
   616 	PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); attrs++; 
   617 	exponent = attrs;
   618 	PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0); attrs++; 
   620 	templateCount = attrs - template;
   621 	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
   622 	crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
   623 	if (crv != CKR_OK) break;
   625 	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) {
   626 	    crv = CKR_OBJECT_HANDLE_INVALID;
   627 	    break;
   628 	} 
   629 	crv = pk11_Attr2SecItem(arena,modulus,&pubKey->u.rsa.modulus);
   630 	if (crv != CKR_OK) break;
   631 	crv = pk11_Attr2SecItem(arena,exponent,&pubKey->u.rsa.publicExponent);
   632 	if (crv != CKR_OK) break;
   633 	break;
   634     case dsaKey:
   635 	prime = attrs;
   636 	PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 
   637 	subprime = attrs;
   638 	PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++; 
   639 	base = attrs;
   640 	PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 
   641 	value = attrs;
   642 	PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 
   643 	templateCount = attrs - template;
   644 	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
   645 	crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
   646 	if (crv != CKR_OK) break;
   648 	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {
   649 	    crv = CKR_OBJECT_HANDLE_INVALID;
   650 	    break;
   651 	} 
   652 	crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dsa.params.prime);
   653 	if (crv != CKR_OK) break;
   654 	crv = pk11_Attr2SecItem(arena,subprime,&pubKey->u.dsa.params.subPrime);
   655 	if (crv != CKR_OK) break;
   656 	crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dsa.params.base);
   657 	if (crv != CKR_OK) break;
   658 	crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dsa.publicValue);
   659 	if (crv != CKR_OK) break;
   660 	break;
   661     case dhKey:
   662 	prime = attrs;
   663 	PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 
   664 	base = attrs;
   665 	PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 
   666 	value =attrs;
   667 	PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 
   668 	templateCount = attrs - template;
   669 	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
   670 	crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
   671 	if (crv != CKR_OK) break;
   673 	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) {
   674 	    crv = CKR_OBJECT_HANDLE_INVALID;
   675 	    break;
   676 	} 
   677 	crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dh.prime);
   678 	if (crv != CKR_OK) break;
   679 	crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dh.base);
   680 	if (crv != CKR_OK) break;
   681 	crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue);
   682 	if (crv != CKR_OK) break;
   683 	break;
   684     case ecKey:
   685 	pubKey->u.ec.size = 0;
   686 	ecparams = attrs;
   687 	PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0); attrs++; 
   688 	value =attrs;
   689 	PK11_SETATTRS(attrs, CKA_EC_POINT, NULL, 0); attrs++; 
   690 	templateCount = attrs - template;
   691 	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
   692 	crv = PK11_GetAttributes(arena,slot,id,template,templateCount);
   693 	if (crv != CKR_OK) break;
   695 	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_EC)) {
   696 	    crv = CKR_OBJECT_HANDLE_INVALID;
   697 	    break;
   698 	} 
   700 	crv = pk11_Attr2SecItem(arena,ecparams,
   701 	                        &pubKey->u.ec.DEREncodedParams);
   702 	if (crv != CKR_OK) break;
   703 	crv = pk11_get_Decoded_ECPoint(arena,
   704 		 &pubKey->u.ec.DEREncodedParams, value, 
   705 		 &pubKey->u.ec.publicValue);
   706 	break;
   707     case fortezzaKey:
   708     case nullKey:
   709     default:
   710 	crv = CKR_OBJECT_HANDLE_INVALID;
   711 	break;
   712     }
   714     PORT_FreeArena(tmp_arena,PR_FALSE);
   716     if (crv != CKR_OK) {
   717 	PORT_FreeArena(arena,PR_FALSE);
   718 	PK11_FreeSlot(slot);
   719 	PORT_SetError( PK11_MapError(crv) );
   720 	return NULL;
   721     }
   723     return pubKey;
   724 }
   726 /*
   727  * Build a Private Key structure from raw PKCS #11 information.
   728  */
   729 SECKEYPrivateKey *
   730 PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, 
   731 			PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
   732 {
   733     PLArenaPool *arena;
   734     SECKEYPrivateKey *privKey;
   735     PRBool isPrivate;
   736     SECStatus rv;
   738     /* don't know? look it up */
   739     if (keyType == nullKey) {
   740 	CK_KEY_TYPE pk11Type = CKK_RSA;
   742 	pk11Type = PK11_ReadULongAttribute(slot,privID,CKA_KEY_TYPE);
   743 	isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN,PR_FALSE);
   744 	switch (pk11Type) {
   745 	case CKK_RSA: keyType = rsaKey; break;
   746 	case CKK_DSA: keyType = dsaKey; break;
   747 	case CKK_DH: keyType = dhKey; break;
   748 	case CKK_KEA: keyType = fortezzaKey; break;
   749 	case CKK_EC: keyType = ecKey; break;
   750 	default:
   751 		break;
   752 	}
   753     }
   755     /* if the key is private, make sure we are authenticated to the
   756      * token before we try to use it */
   757     isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE,PR_FALSE);
   758     if (isPrivate) {
   759 	rv = PK11_Authenticate(slot, PR_TRUE, wincx);
   760  	if (rv != SECSuccess) {
   761  	    return NULL;
   762  	}
   763     }
   765     /* now we need to create space for the private key */
   766     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
   767     if (arena == NULL) return NULL;
   769     privKey = (SECKEYPrivateKey *) 
   770 			PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
   771     if (privKey == NULL) {
   772 	PORT_FreeArena(arena, PR_FALSE);
   773 	return NULL;
   774     }
   776     privKey->arena = arena;
   777     privKey->keyType = keyType;
   778     privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
   779     privKey->pkcs11ID = privID;
   780     privKey->pkcs11IsTemp = isTemp;
   781     privKey->wincx = wincx;
   783     return privKey;
   784 }
   787 PK11SlotInfo *
   788 PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
   789 {
   790     PK11SlotInfo *slot = key->pkcs11Slot;
   791     slot = PK11_ReferenceSlot(slot);
   792     return slot;
   793 }
   795 /*
   796  * Get the modulus length for raw parsing
   797  */
   798 int
   799 PK11_GetPrivateModulusLen(SECKEYPrivateKey *key)
   800 {
   801     CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 };
   802     PK11SlotInfo *slot = key->pkcs11Slot;
   803     CK_RV crv;
   804     int length;
   806     switch (key->keyType) {
   807     case rsaKey:
   808 	crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1);
   809 	if (crv != CKR_OK) {
   810 	    PORT_SetError( PK11_MapError(crv) );
   811 	    return -1;
   812 	}
   813 	length = theTemplate.ulValueLen;
   814 	if ( *(unsigned char *)theTemplate.pValue == 0) {
   815 	    length--;
   816 	}
   817 	if (theTemplate.pValue != NULL)
   818 	    PORT_Free(theTemplate.pValue);
   819 	return (int) length;
   821     case fortezzaKey:
   822     case dsaKey:
   823     case dhKey:
   824     default:
   825 	break;
   826     }
   827     if (theTemplate.pValue != NULL)
   828 	PORT_Free(theTemplate.pValue);
   829     PORT_SetError( SEC_ERROR_INVALID_KEY );
   830     return -1;
   831 }
   835 /*
   836  * take a private key in one pkcs11 module and load it into another:
   837  *  NOTE: the source private key is a rare animal... it can't be sensitive.
   838  *  This is used to do a key gen using one pkcs11 module and storing the
   839  *  result into another.
   840  */
   841 static SECKEYPrivateKey *
   842 pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
   843 		SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags) 
   844 {
   845     CK_ATTRIBUTE privTemplate[] = {
   846         /* class must be first */
   847 	{ CKA_CLASS, NULL, 0 },
   848 	{ CKA_KEY_TYPE, NULL, 0 },
   849 	{ CKA_ID, NULL, 0 },
   850 	/* RSA - the attributes below will be replaced for other 
   851 	 *       key types.
   852 	 */
   853 	{ CKA_MODULUS, NULL, 0 },
   854 	{ CKA_PRIVATE_EXPONENT, NULL, 0 },
   855 	{ CKA_PUBLIC_EXPONENT, NULL, 0 },
   856 	{ CKA_PRIME_1, NULL, 0 },
   857 	{ CKA_PRIME_2, NULL, 0 },
   858 	{ CKA_EXPONENT_1, NULL, 0 },
   859 	{ CKA_EXPONENT_2, NULL, 0 },
   860 	{ CKA_COEFFICIENT, NULL, 0 },
   861 	{ CKA_DECRYPT, NULL, 0 },
   862 	{ CKA_DERIVE, NULL, 0 },
   863 	{ CKA_SIGN, NULL, 0 },
   864 	{ CKA_SIGN_RECOVER, NULL, 0 },
   865 	{ CKA_UNWRAP, NULL, 0 },
   866 	/* reserve space for the attributes that may be
   867 	 * specified in attrFlags */
   868 	{ CKA_TOKEN, NULL, 0 },
   869 	{ CKA_PRIVATE, NULL, 0 },
   870 	{ CKA_MODIFIABLE, NULL, 0 },
   871 	{ CKA_SENSITIVE, NULL, 0 },
   872 	{ CKA_EXTRACTABLE, NULL, 0 },
   873 #define NUM_RESERVED_ATTRS 5    /* number of reserved attributes above */
   874     };
   875     CK_BBOOL cktrue = CK_TRUE;
   876     CK_BBOOL ckfalse = CK_FALSE;
   877     CK_ATTRIBUTE *attrs = NULL, *ap;
   878     const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]);
   879     PLArenaPool *arena;
   880     CK_OBJECT_HANDLE objectID;
   881     int i, count = 0;
   882     int extra_count = 0;
   883     CK_RV crv;
   884     SECStatus rv;
   885     PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
   887     if (pk11_BadAttrFlags(attrFlags)) {
   888 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   889 	return NULL;
   890     }
   892     for (i=0; i < templateSize; i++) {
   893 	if (privTemplate[i].type == CKA_MODULUS) {
   894 	    attrs= &privTemplate[i];
   895 	    count = i;
   896 	    break;
   897 	}
   898     }
   899     PORT_Assert(attrs != NULL);
   900     if (attrs == NULL) {
   901 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   902 	return NULL;
   903     }
   905     ap = attrs;
   907     switch (privKey->keyType) {
   908     case rsaKey:
   909 	count = templateSize - NUM_RESERVED_ATTRS;
   910 	extra_count = count - (attrs - privTemplate);
   911 	break;
   912     case dsaKey:
   913 	ap->type = CKA_PRIME; ap++; count++; extra_count++;
   914 	ap->type = CKA_SUBPRIME; ap++; count++; extra_count++;
   915 	ap->type = CKA_BASE; ap++; count++; extra_count++;
   916 	ap->type = CKA_VALUE; ap++; count++; extra_count++;
   917 	ap->type = CKA_SIGN; ap++; count++; extra_count++;
   918 	break;
   919     case dhKey:
   920 	ap->type = CKA_PRIME; ap++; count++; extra_count++;
   921 	ap->type = CKA_BASE; ap++; count++; extra_count++;
   922 	ap->type = CKA_VALUE; ap++; count++; extra_count++;
   923 	ap->type = CKA_DERIVE; ap++; count++; extra_count++;
   924 	break;
   925     case ecKey:
   926 	ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++;
   927 	ap->type = CKA_VALUE; ap++; count++; extra_count++;
   928 	ap->type = CKA_DERIVE; ap++; count++; extra_count++;
   929 	ap->type = CKA_SIGN; ap++; count++; extra_count++;
   930 	break;
   931      default:
   932 	count = 0;
   933 	extra_count = 0;
   934 	break;
   935      }
   937      if (count == 0) {
   938 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   939 	return NULL;
   940      }
   942      arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
   943      if (arena == NULL) return NULL;
   944      /*
   945       * read out the old attributes.
   946       */
   947      crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
   948 		privTemplate,count);
   949      if (crv != CKR_OK) {
   950 	PORT_SetError( PK11_MapError(crv) );
   951 	PORT_FreeArena(arena, PR_TRUE);
   952 	return NULL;
   953      }
   955      /* Set token, private, modifiable, sensitive, and extractable */
   956      count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
   957 					&cktrue, &ckfalse);
   959      /* Not everyone can handle zero padded key values, give
   960       * them the raw data as unsigned */
   961      for (ap=attrs; extra_count; ap++, extra_count--) {
   962 	pk11_SignedToUnsigned(ap);
   963      }
   965      /* now Store the puppies */
   966      rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate, 
   967 						count, token, &objectID);
   968      PORT_FreeArena(arena, PR_TRUE);
   969      if (rv != SECSuccess) {
   970 	return NULL;
   971      }
   973      /* try loading the public key */
   974      if (pubKey) {
   975 	PK11_ImportPublicKey(slot, pubKey, token);
   976 	if (pubKey->pkcs11Slot) {
   977 	    PK11_FreeSlot(pubKey->pkcs11Slot);
   978 	    pubKey->pkcs11Slot = NULL;
   979 	    pubKey->pkcs11ID = CK_INVALID_HANDLE;
   980 	}
   981      }
   983      /* build new key structure */
   984      return PK11_MakePrivKey(slot, privKey->keyType, !token, 
   985 						objectID, privKey->wincx);
   986 }
   988 static SECKEYPrivateKey *
   989 pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
   990 		SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) 
   991 {
   992     PK11AttrFlags attrFlags = 0;
   993     if (token) {
   994 	attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
   995     } else {
   996 	attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC);
   997     }
   998     if (sensitive) {
   999 	attrFlags |= PK11_ATTR_SENSITIVE;
  1000     } else {
  1001 	attrFlags |= PK11_ATTR_INSENSITIVE;
  1003     return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags);
  1006 /*
  1007  * export this for PSM
  1008  */
  1009 SECKEYPrivateKey *
  1010 PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
  1011 		SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) 
  1013     return pk11_loadPrivKey(slot,privKey,pubKey,token,sensitive);
  1017 /*
  1018  * Use the token to generate a key pair.
  1019  */
  1020 SECKEYPrivateKey *
  1021 PK11_GenerateKeyPairWithOpFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
  1022    void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, 
  1023    CK_FLAGS opFlags, CK_FLAGS opFlagsMask, void *wincx)
  1025     /* we have to use these native types because when we call PKCS 11 modules
  1026      * we have to make sure that we are using the correct sizes for all the
  1027      * parameters. */
  1028     CK_BBOOL ckfalse = CK_FALSE;
  1029     CK_BBOOL cktrue = CK_TRUE;
  1030     CK_ULONG modulusBits;
  1031     CK_BYTE publicExponent[4];
  1032     CK_ATTRIBUTE privTemplate[] = {
  1033 	{ CKA_SENSITIVE, NULL, 0},
  1034 	{ CKA_TOKEN,  NULL, 0},
  1035 	{ CKA_PRIVATE,  NULL, 0},
  1036 	{ CKA_DERIVE,  NULL, 0},
  1037 	{ CKA_UNWRAP,  NULL, 0},
  1038 	{ CKA_SIGN,  NULL, 0},
  1039 	{ CKA_DECRYPT,  NULL, 0},
  1040 	{ CKA_EXTRACTABLE, NULL, 0},
  1041 	{ CKA_MODIFIABLE,  NULL, 0},
  1042     };
  1043     CK_ATTRIBUTE rsaPubTemplate[] = {
  1044 	{ CKA_MODULUS_BITS, NULL, 0},
  1045 	{ CKA_PUBLIC_EXPONENT, NULL, 0},
  1046 	{ CKA_TOKEN,  NULL, 0},
  1047 	{ CKA_DERIVE,  NULL, 0},
  1048 	{ CKA_WRAP,  NULL, 0},
  1049 	{ CKA_VERIFY,  NULL, 0},
  1050 	{ CKA_VERIFY_RECOVER,  NULL, 0},
  1051 	{ CKA_ENCRYPT,  NULL, 0},
  1052 	{ CKA_MODIFIABLE,  NULL, 0},
  1053     };
  1054     CK_ATTRIBUTE dsaPubTemplate[] = {
  1055 	{ CKA_PRIME, NULL, 0 },
  1056 	{ CKA_SUBPRIME, NULL, 0 },
  1057 	{ CKA_BASE, NULL, 0 },
  1058 	{ CKA_TOKEN,  NULL, 0},
  1059 	{ CKA_DERIVE,  NULL, 0},
  1060 	{ CKA_WRAP,  NULL, 0},
  1061 	{ CKA_VERIFY,  NULL, 0},
  1062 	{ CKA_VERIFY_RECOVER,  NULL, 0},
  1063 	{ CKA_ENCRYPT,  NULL, 0},
  1064 	{ CKA_MODIFIABLE,  NULL, 0},
  1065     };
  1066     CK_ATTRIBUTE dhPubTemplate[] = {
  1067       { CKA_PRIME, NULL, 0 }, 
  1068       { CKA_BASE, NULL, 0 }, 
  1069       { CKA_TOKEN,  NULL, 0},
  1070       { CKA_DERIVE,  NULL, 0},
  1071       { CKA_WRAP,  NULL, 0},
  1072       { CKA_VERIFY,  NULL, 0},
  1073       { CKA_VERIFY_RECOVER,  NULL, 0},
  1074       { CKA_ENCRYPT,  NULL, 0},
  1075       { CKA_MODIFIABLE,  NULL, 0},
  1076     };
  1077     CK_ATTRIBUTE ecPubTemplate[] = {
  1078       { CKA_EC_PARAMS, NULL, 0 }, 
  1079       { CKA_TOKEN,  NULL, 0},
  1080       { CKA_DERIVE,  NULL, 0},
  1081       { CKA_WRAP,  NULL, 0},
  1082       { CKA_VERIFY,  NULL, 0},
  1083       { CKA_VERIFY_RECOVER,  NULL, 0},
  1084       { CKA_ENCRYPT,  NULL, 0},
  1085       { CKA_MODIFIABLE,  NULL, 0},
  1086     };
  1087     SECKEYECParams * ecParams;
  1089     /*CK_ULONG key_size = 0;*/
  1090     CK_ATTRIBUTE *pubTemplate;
  1091     int privCount = 0;
  1092     int pubCount = 0;
  1093     PK11RSAGenParams *rsaParams;
  1094     SECKEYPQGParams *dsaParams;
  1095     SECKEYDHParams * dhParams;
  1096     CK_MECHANISM mechanism;
  1097     CK_MECHANISM test_mech;
  1098     CK_MECHANISM test_mech2;
  1099     CK_SESSION_HANDLE session_handle;
  1100     CK_RV crv;
  1101     CK_OBJECT_HANDLE privID,pubID;
  1102     SECKEYPrivateKey *privKey;
  1103     KeyType keyType;
  1104     PRBool restore;
  1105     int peCount,i;
  1106     CK_ATTRIBUTE *attrs;
  1107     CK_ATTRIBUTE *privattrs;
  1108     CK_ATTRIBUTE setTemplate;
  1109     CK_MECHANISM_INFO mechanism_info;
  1110     CK_OBJECT_CLASS keyClass;
  1111     SECItem *cka_id;
  1112     PRBool haslock = PR_FALSE;
  1113     PRBool pubIsToken = PR_FALSE;
  1114     PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
  1115     /* subset of attrFlags applicable to the public key */
  1116     PK11AttrFlags pubKeyAttrFlags = attrFlags &
  1117 	(PK11_ATTR_TOKEN | PK11_ATTR_SESSION
  1118 	| PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
  1120     if (pk11_BadAttrFlags(attrFlags)) {
  1121 	PORT_SetError( SEC_ERROR_INVALID_ARGS );
  1122 	return NULL;
  1125     if (!param) {
  1126         PORT_SetError( SEC_ERROR_INVALID_ARGS );
  1127         return NULL;
  1130     /*
  1131      * The opFlags and opFlagMask parameters allow us to control the
  1132      * settings of the key usage attributes (CKA_ENCRYPT and friends).
  1133      * opFlagMask is set to one if the flag is specified in opFlags and 
  1134      *  zero if it is to take on a default value calculated by 
  1135      *  PK11_GenerateKeyPairWithOpFlags.
  1136      * opFlags specifies the actual value of the flag 1 or 0. 
  1137      *   Bits not corresponding to one bits in opFlagMask should be zero.
  1138      */
  1140     /* if we are trying to turn on a flag, it better be in the mask */
  1141     PORT_Assert ((opFlags & ~opFlagsMask) == 0);
  1142     opFlags &= opFlagsMask;
  1144     PORT_Assert(slot != NULL);
  1145     if (slot == NULL) {
  1146 	PORT_SetError( SEC_ERROR_NO_MODULE);
  1147 	return NULL;
  1150     /* if our slot really doesn't do this mechanism, Generate the key
  1151      * in our internal token and write it out */
  1152     if (!PK11_DoesMechanism(slot,type)) {
  1153 	PK11SlotInfo *int_slot = PK11_GetInternalSlot();
  1155 	/* don't loop forever looking for a slot */
  1156 	if (slot == int_slot) {
  1157 	    PK11_FreeSlot(int_slot);
  1158 	    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
  1159 	    return NULL;
  1162 	/* if there isn't a suitable slot, then we can't do the keygen */
  1163 	if (int_slot == NULL) {
  1164 	    PORT_SetError( SEC_ERROR_NO_MODULE );
  1165 	    return NULL;
  1168 	/* generate the temporary key to load */
  1169 	privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE, 
  1170 							PR_FALSE, wincx);
  1171 	PK11_FreeSlot(int_slot);
  1173 	/* if successful, load the temp key into the new token */
  1174 	if (privKey != NULL) {
  1175 	    SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
  1176 						privKey,*pubKey,attrFlags);
  1177 	    SECKEY_DestroyPrivateKey(privKey);
  1178 	    if (newPrivKey == NULL) {
  1179 		SECKEY_DestroyPublicKey(*pubKey);
  1180 		*pubKey = NULL;
  1182 	    return newPrivKey;
  1184 	return NULL;
  1188     mechanism.mechanism = type;
  1189     mechanism.pParameter = NULL;
  1190     mechanism.ulParameterLen = 0;
  1191     test_mech.pParameter = NULL;
  1192     test_mech.ulParameterLen = 0;
  1193     test_mech2.mechanism = CKM_INVALID_MECHANISM;
  1194     test_mech2.pParameter = NULL;
  1195     test_mech2.ulParameterLen = 0;
  1197     /* set up the private key template */
  1198     privattrs = privTemplate;
  1199     privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
  1200 						&cktrue, &ckfalse);
  1202     /* set up the mechanism specific info */
  1203     switch (type) {
  1204     case CKM_RSA_PKCS_KEY_PAIR_GEN:
  1205     case CKM_RSA_X9_31_KEY_PAIR_GEN:
  1206 	rsaParams = (PK11RSAGenParams *)param;
  1207 	if (rsaParams->pe == 0) {
  1208 	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1209 	    return NULL;
  1211 	modulusBits = rsaParams->keySizeInBits;
  1212 	peCount = 0;
  1214 	/* convert pe to a PKCS #11 string */
  1215 	for (i=0; i < 4; i++) {
  1216 	    if (peCount || (rsaParams->pe & 
  1217 				((unsigned long)0xff000000L >> (i*8)))) {
  1218 		publicExponent[peCount] = 
  1219 				(CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);
  1220 		peCount++;
  1223 	PORT_Assert(peCount != 0);
  1224 	attrs = rsaPubTemplate;
  1225 	PK11_SETATTRS(attrs, CKA_MODULUS_BITS, 
  1226 				&modulusBits, sizeof(modulusBits)); attrs++;
  1227 	PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
  1228 				publicExponent, peCount);attrs++;
  1229 	pubTemplate = rsaPubTemplate;
  1230 	keyType = rsaKey;
  1231 	test_mech.mechanism = CKM_RSA_PKCS;
  1232 	break;
  1233     case CKM_DSA_KEY_PAIR_GEN:
  1234 	dsaParams = (SECKEYPQGParams *)param;
  1235 	attrs = dsaPubTemplate;
  1236 	PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
  1237 				dsaParams->prime.len); attrs++;
  1238 	PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
  1239 					dsaParams->subPrime.len); attrs++;
  1240 	PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
  1241 						dsaParams->base.len); attrs++;
  1242 	pubTemplate = dsaPubTemplate;
  1243 	keyType = dsaKey;
  1244 	test_mech.mechanism = CKM_DSA;
  1245 	break;
  1246     case CKM_DH_PKCS_KEY_PAIR_GEN:
  1247         dhParams = (SECKEYDHParams *)param;
  1248         attrs = dhPubTemplate;
  1249         PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
  1250                       dhParams->prime.len);   attrs++;
  1251         PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
  1252                       dhParams->base.len);    attrs++;
  1253         pubTemplate = dhPubTemplate;
  1254         keyType = dhKey;
  1255         test_mech.mechanism = CKM_DH_PKCS_DERIVE;
  1256 	break;
  1257     case CKM_EC_KEY_PAIR_GEN:
  1258         ecParams = (SECKEYECParams *)param;
  1259         attrs = ecPubTemplate;
  1260         PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, 
  1261 	              ecParams->len);   attrs++;
  1262         pubTemplate = ecPubTemplate;
  1263         keyType = ecKey;
  1264 	/*
  1265 	 * ECC supports 2 different mechanism types (unlike RSA, which
  1266 	 * supports different usages with the same mechanism).
  1267 	 * We may need to query both mechanism types and or the results
  1268 	 * together -- but we only do that if either the user has
  1269 	 * requested both usages, or not specified any usages.
  1270 	 */
  1271 	if ((opFlags & (CKF_SIGN|CKF_DERIVE)) == (CKF_SIGN|CKF_DERIVE)) {
  1272 	    /* We've explicitly turned on both flags, use both mechanism */
  1273 	    test_mech.mechanism = CKM_ECDH1_DERIVE;
  1274 	    test_mech2.mechanism = CKM_ECDSA;
  1275 	} else if (opFlags & CKF_SIGN) {
  1276 	    /* just do signing */
  1277 	    test_mech.mechanism = CKM_ECDSA;
  1278 	} else if (opFlags & CKF_DERIVE) {
  1279 	    /* just do ECDH */
  1280 	    test_mech.mechanism = CKM_ECDH1_DERIVE;
  1281 	} else {
  1282 	    /* neither was specified default to both */
  1283 	    test_mech.mechanism = CKM_ECDH1_DERIVE;
  1284 	    test_mech2.mechanism = CKM_ECDSA;
  1286         break;
  1287     default:
  1288 	PORT_SetError( SEC_ERROR_BAD_KEY );
  1289 	return NULL;
  1292     /* now query the slot to find out how "good" a key we can generate */
  1293     if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1294     crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
  1295 				test_mech.mechanism,&mechanism_info);
  1296     /*
  1297      * EC keys are used in multiple different types of mechanism, if we
  1298      * are using dual use keys, we need to query the second mechanism
  1299      * as well.
  1300      */
  1301     if (test_mech2.mechanism != CKM_INVALID_MECHANISM) {
  1302 	CK_MECHANISM_INFO mechanism_info2;
  1303 	CK_RV crv2;
  1305 	if (crv != CKR_OK) {
  1306 	    /* the first failed, make sure there is no trash in the
  1307 	     * mechanism flags when we or it below */
  1308 	    mechanism_info.flags = 0;
  1310 	crv2 = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
  1311 				test_mech2.mechanism, &mechanism_info2);
  1312 	if (crv2 == CKR_OK) {
  1313 	    crv = CKR_OK; /* succeed if either mechnaism info succeeds */
  1314 	    /* combine the 2 sets of mechnanism flags */
  1315 	    mechanism_info.flags |= mechanism_info2.flags;
  1318     if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1319     if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
  1320 	/* must be old module... guess what it should be... */
  1321 	switch (test_mech.mechanism) {
  1322 	case CKM_RSA_PKCS:
  1323 	    mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT | 
  1324 		CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);
  1325 	    break;
  1326 	case CKM_DSA:
  1327 	    mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
  1328 	    break;
  1329 	case CKM_DH_PKCS_DERIVE:
  1330 	    mechanism_info.flags = CKF_DERIVE;
  1331 	    break;
  1332 	case CKM_ECDH1_DERIVE:
  1333 	    mechanism_info.flags = CKF_DERIVE;
  1334 	    if (test_mech2.mechanism == CKM_ECDSA) {
  1335 		mechanism_info.flags |= CKF_SIGN | CKF_VERIFY;
  1337 	    break;
  1338 	case CKM_ECDSA:
  1339 	    mechanism_info.flags =  CKF_SIGN | CKF_VERIFY;
  1340 	    break;
  1341 	default:
  1342 	    break;
  1345     /* now adjust our flags according to the user's key usage passed to us */
  1346     mechanism_info.flags = (mechanism_info.flags & (~opFlagsMask)) | opFlags;
  1347     /* set the public key attributes */
  1348     attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
  1349 						&cktrue, &ckfalse);
  1350     PK11_SETATTRS(attrs, CKA_DERIVE, 
  1351 		mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
  1352 					 sizeof(CK_BBOOL)); attrs++;
  1353     PK11_SETATTRS(attrs, CKA_WRAP, 
  1354 		mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
  1355 					 sizeof(CK_BBOOL)); attrs++;
  1356     PK11_SETATTRS(attrs, CKA_VERIFY, 
  1357 		mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
  1358 					 sizeof(CK_BBOOL)); attrs++;
  1359     PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER, 
  1360 		mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
  1361 					 sizeof(CK_BBOOL)); attrs++;
  1362     PK11_SETATTRS(attrs, CKA_ENCRYPT, 
  1363 		mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,
  1364 					 sizeof(CK_BBOOL)); attrs++;
  1365     /* set the private key attributes */
  1366     PK11_SETATTRS(privattrs, CKA_DERIVE, 
  1367 		mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
  1368 					 sizeof(CK_BBOOL)); privattrs++;
  1369     PK11_SETATTRS(privattrs, CKA_UNWRAP, 
  1370 		mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
  1371 					 sizeof(CK_BBOOL)); privattrs++;
  1372     PK11_SETATTRS(privattrs, CKA_SIGN, 
  1373 		mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
  1374 					 sizeof(CK_BBOOL)); privattrs++;
  1375     PK11_SETATTRS(privattrs, CKA_DECRYPT, 
  1376 		mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
  1377 					 sizeof(CK_BBOOL)); privattrs++;
  1379     if (token) {
  1380 	session_handle = PK11_GetRWSession(slot);
  1381 	haslock = PK11_RWSessionHasLock(slot,session_handle);
  1382 	restore = PR_TRUE;
  1383     } else {
  1384 	session_handle = slot->session;
  1385 	if (session_handle != CK_INVALID_SESSION)
  1386 	    PK11_EnterSlotMonitor(slot);
  1387 	restore = PR_FALSE;
  1388 	haslock = PR_TRUE;
  1391     if (session_handle == CK_INVALID_SESSION) {
  1392     	PORT_SetError(SEC_ERROR_BAD_DATA);
  1393 	return NULL;
  1395     privCount = privattrs - privTemplate;
  1396     pubCount = attrs - pubTemplate;
  1397     crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
  1398 	pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);
  1400     if (crv != CKR_OK) {
  1401 	if (restore)  {
  1402 	    PK11_RestoreROSession(slot,session_handle);
  1403 	} else PK11_ExitSlotMonitor(slot);
  1404 	PORT_SetError( PK11_MapError(crv) );
  1405 	return NULL;
  1407     /* This locking code is dangerous and needs to be more thought
  1408      * out... the real problem is that we're holding the mutex open this long
  1409      */
  1410     if (haslock) { PK11_ExitSlotMonitor(slot); }
  1412     /* swap around the ID's for older PKCS #11 modules */
  1413     keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);
  1414     if (keyClass != CKO_PUBLIC_KEY) {
  1415 	CK_OBJECT_HANDLE tmp = pubID;
  1416 	pubID = privID;
  1417 	privID = tmp;
  1420     *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
  1421     if (*pubKey == NULL) {
  1422 	if (restore)  {
  1423 	    /* we may have to restore the mutex so it get's exited properly
  1424 	     * in RestoreROSession */
  1425             if (haslock)  PK11_EnterSlotMonitor(slot); 
  1426 	    PK11_RestoreROSession(slot,session_handle);
  1428 	PK11_DestroyObject(slot,pubID);
  1429 	PK11_DestroyObject(slot,privID);
  1430 	return NULL;
  1433     /* set the ID to the public key so we can find it again */
  1434     cka_id = pk11_MakeIDFromPublicKey(*pubKey);
  1435     pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN,PR_FALSE);
  1437     PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
  1439     if (haslock) { PK11_EnterSlotMonitor(slot); }
  1440     crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
  1441 		&setTemplate, 1);
  1443     if (crv == CKR_OK && pubIsToken) {
  1444     	crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
  1445 		&setTemplate, 1);
  1449     if (restore) {
  1450 	PK11_RestoreROSession(slot,session_handle);
  1451     } else {
  1452 	PK11_ExitSlotMonitor(slot);
  1454     SECITEM_FreeItem(cka_id,PR_TRUE);
  1457     if (crv != CKR_OK) {
  1458 	PK11_DestroyObject(slot,pubID);
  1459 	PK11_DestroyObject(slot,privID);
  1460 	PORT_SetError( PK11_MapError(crv) );
  1461 	*pubKey = NULL;
  1462 	return NULL;
  1465     privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx);
  1466     if (privKey == NULL) {
  1467 	SECKEY_DestroyPublicKey(*pubKey);
  1468 	PK11_DestroyObject(slot,privID);
  1469 	*pubKey = NULL;
  1470 	return NULL;
  1473     return privKey;
  1476 SECKEYPrivateKey *
  1477 PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
  1478    void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
  1480     return PK11_GenerateKeyPairWithOpFlags(slot,type,param,pubKey,attrFlags,
  1481 					   0, 0, wincx);
  1484 /*
  1485  * Use the token to generate a key pair.
  1486  */
  1487 SECKEYPrivateKey *
  1488 PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
  1489    void *param, SECKEYPublicKey **pubKey, PRBool token, 
  1490 					PRBool sensitive, void *wincx)
  1492     PK11AttrFlags attrFlags = 0;
  1494     if (token) {
  1495 	attrFlags |= PK11_ATTR_TOKEN;
  1496     } else {
  1497 	attrFlags |= PK11_ATTR_SESSION;
  1499     if (sensitive) {
  1500 	attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE);
  1501     } else {
  1502 	attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC);
  1504     return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey,
  1505 						attrFlags, wincx);
  1508 /* build a public KEA key from the public value */
  1509 SECKEYPublicKey *
  1510 PK11_MakeKEAPubKey(unsigned char *keyData,int length)
  1512     SECKEYPublicKey *pubk;
  1513     SECItem pkData;
  1514     SECStatus rv;
  1515     PLArenaPool *arena;
  1517     pkData.data = keyData;
  1518     pkData.len = length;
  1520     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
  1521     if (arena == NULL)
  1522 	return NULL;
  1524     pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
  1525     if (pubk == NULL) {
  1526 	PORT_FreeArena (arena, PR_FALSE);
  1527 	return NULL;
  1530     pubk->arena = arena;
  1531     pubk->pkcs11Slot = 0;
  1532     pubk->pkcs11ID = CK_INVALID_HANDLE;
  1533     pubk->keyType = fortezzaKey;
  1534     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
  1535     if (rv != SECSuccess) {
  1536 	PORT_FreeArena (arena, PR_FALSE);
  1537 	return NULL;
  1539     return pubk;
  1542 /*
  1543  * NOTE: This function doesn't return a SECKEYPrivateKey struct to represent
  1544  * the new private key object.  If it were to create a session object that
  1545  * could later be looked up by its nickname, it would leak a SECKEYPrivateKey.
  1546  * So isPerm must be true.
  1547  */
  1548 SECStatus 
  1549 PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
  1550 			SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
  1551 			SECItem *nickname, SECItem *publicValue, PRBool isPerm,
  1552 			PRBool isPrivate, KeyType keyType, 
  1553 			unsigned int keyUsage, void *wincx)
  1555     if (!isPerm) {
  1556 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1557 	return SECFailure;
  1559     return PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(slot, epki,
  1560 		pwitem, nickname, publicValue, isPerm, isPrivate, keyType,
  1561 		keyUsage, NULL, wincx);
  1564 SECStatus
  1565 PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
  1566 			SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
  1567 			SECItem *nickname, SECItem *publicValue, PRBool isPerm,
  1568 			PRBool isPrivate, KeyType keyType,
  1569 			unsigned int keyUsage, SECKEYPrivateKey **privk,
  1570 			void *wincx)
  1572     CK_MECHANISM_TYPE pbeMechType;
  1573     SECItem *crypto_param = NULL;
  1574     PK11SymKey *key = NULL;
  1575     SECStatus rv = SECSuccess;
  1576     CK_MECHANISM_TYPE cryptoMechType;
  1577     SECKEYPrivateKey *privKey = NULL;
  1578     PRBool faulty3DES = PR_FALSE;
  1579     int usageCount = 0;
  1580     CK_KEY_TYPE key_type;
  1581     CK_ATTRIBUTE_TYPE *usage = NULL;
  1582     CK_ATTRIBUTE_TYPE rsaUsage[] = {
  1583 		 CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
  1584     CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
  1585     CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
  1586     CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE };
  1587     if((epki == NULL) || (pwitem == NULL))
  1588 	return SECFailure;
  1590     pbeMechType = PK11_AlgtagToMechanism(SECOID_FindOIDTag(
  1591 					&epki->algorithm.algorithm));
  1593     switch (keyType) {
  1594     default:
  1595     case rsaKey:
  1596 	key_type = CKK_RSA;
  1597 	switch  (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
  1598 	case KU_KEY_ENCIPHERMENT:
  1599 	    usage = rsaUsage;
  1600 	    usageCount = 2;
  1601 	    break;
  1602 	case KU_DIGITAL_SIGNATURE:
  1603 	    usage = &rsaUsage[2];
  1604 	    usageCount = 2;
  1605 	    break;
  1606 	case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
  1607 	case 0: /* default to everything */
  1608 	    usage = rsaUsage;
  1609 	    usageCount = 4;
  1610 	    break;
  1612         break;
  1613     case dhKey:
  1614 	key_type = CKK_DH;
  1615 	usage = dhUsage;
  1616 	usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
  1617 	break;
  1618     case dsaKey:
  1619 	key_type = CKK_DSA;
  1620 	usage = dsaUsage;
  1621 	usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
  1622 	break;
  1623     case ecKey:
  1624 	key_type = CKK_EC;
  1625 	switch  (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) {
  1626 	case KU_DIGITAL_SIGNATURE:
  1627 	    usage = ecUsage;
  1628 	    usageCount = 1;
  1629 	    break;
  1630 	case KU_KEY_AGREEMENT:
  1631 	    usage = &ecUsage[1];
  1632 	    usageCount = 1;
  1633 	    break;
  1634 	case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT:
  1635 	default: /* default to everything */
  1636 	    usage = ecUsage;
  1637 	    usageCount = 2;
  1638 	    break;
  1640 	break;	
  1643 try_faulty_3des:
  1645     key = PK11_PBEKeyGen(slot, &epki->algorithm, pwitem, faulty3DES, wincx);
  1646     if (key == NULL) {
  1647 	rv = SECFailure;
  1648 	goto done;
  1650     cryptoMechType = pk11_GetPBECryptoMechanism(&epki->algorithm,
  1651 					 &crypto_param, pwitem, faulty3DES);
  1652     if (cryptoMechType == CKM_INVALID_MECHANISM) {
  1653 	rv = SECFailure;
  1654 	goto done;
  1658     cryptoMechType = PK11_GetPadMechanism(cryptoMechType);
  1660     PORT_Assert(usage != NULL);
  1661     PORT_Assert(usageCount != 0);
  1662     privKey = PK11_UnwrapPrivKey(slot, key, cryptoMechType, 
  1663 				 crypto_param, &epki->encryptedData, 
  1664 				 nickname, publicValue, isPerm, isPrivate,
  1665 				 key_type, usage, usageCount, wincx);
  1666     if(privKey) {
  1667 	if (privk) {
  1668 	    *privk = privKey;
  1669 	} else {
  1670 	    SECKEY_DestroyPrivateKey(privKey);
  1672 	privKey = NULL;
  1673 	rv = SECSuccess;
  1674 	goto done;
  1677     /* if we are unable to import the key and the pbeMechType is 
  1678      * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
  1679      * the encrypted blob was created with a buggy key generation method
  1680      * which is described in the PKCS 12 implementation notes.  So we
  1681      * need to try importing via that method.
  1682      */ 
  1683     if((pbeMechType == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) {
  1684 	/* clean up after ourselves before redoing the key generation. */
  1686 	PK11_FreeSymKey(key);
  1687 	key = NULL;
  1689 	if(crypto_param) {
  1690 	    SECITEM_ZfreeItem(crypto_param, PR_TRUE);
  1691 	    crypto_param = NULL;
  1694 	faulty3DES = PR_TRUE;
  1695 	goto try_faulty_3des;
  1698     /* key import really did fail */
  1699     rv = SECFailure;
  1701 done:
  1702     if(crypto_param != NULL) {
  1703 	SECITEM_ZfreeItem(crypto_param, PR_TRUE);
  1706     if(key != NULL) {
  1707     	PK11_FreeSymKey(key);
  1710     return rv;
  1713 SECKEYPrivateKeyInfo *
  1714 PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
  1716     SECKEYPrivateKeyInfo *pki = NULL;
  1717     SECKEYPrivateKey     *pk  = PK11_FindKeyByAnyCert(cert, wincx);
  1718     if (pk != NULL) {
  1719 	pki = PK11_ExportPrivKeyInfo(pk, wincx);
  1720 	SECKEY_DestroyPrivateKey(pk);
  1722     return pki;
  1725 SECKEYEncryptedPrivateKeyInfo * 
  1726 PK11_ExportEncryptedPrivKeyInfo(
  1727    PK11SlotInfo     *slot,      /* optional, encrypt key in this slot */
  1728    SECOidTag         algTag,    /* encrypt key with this algorithm */
  1729    SECItem          *pwitem,    /* password for PBE encryption */
  1730    SECKEYPrivateKey *pk,        /* encrypt this private key */
  1731    int               iteration, /* interations for PBE alg */
  1732    void             *wincx)     /* context for password callback ? */
  1734     SECKEYEncryptedPrivateKeyInfo *epki      = NULL;
  1735     PLArenaPool                   *arena     = NULL;
  1736     SECAlgorithmID                *algid;
  1737     SECOidTag			  pbeAlgTag = SEC_OID_UNKNOWN;
  1738     SECItem                       *crypto_param = NULL;
  1739     PK11SymKey                    *key       = NULL;
  1740     SECKEYPrivateKey		  *tmpPK = NULL;
  1741     SECStatus                      rv        = SECSuccess;
  1742     CK_RV                          crv;
  1743     CK_ULONG                       encBufLen;
  1744     CK_MECHANISM_TYPE              pbeMechType;
  1745     CK_MECHANISM_TYPE              cryptoMechType;
  1746     CK_MECHANISM                   cryptoMech;
  1748     if (!pwitem || !pk) {
  1749 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1750 	return NULL;
  1753     algid = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, SEC_OID_UNKNOWN,
  1754 				&pbeAlgTag, 0, NULL, iteration);
  1755     if (algid == NULL) {
  1756 	return NULL;
  1759     arena = PORT_NewArena(2048);
  1760     if (arena)
  1761 	epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo);
  1762     if(epki == NULL) {
  1763 	rv = SECFailure;
  1764 	goto loser;
  1766     epki->arena = arena;
  1769     /* if we didn't specify a slot, use the slot the private key was in */
  1770     if (!slot) {
  1771 	slot = pk->pkcs11Slot;
  1774     /* if we specified a different slot, and the private key slot can do the
  1775      * pbe key gen, generate the key in the private key slot so we don't have 
  1776      * to move it later */
  1777     pbeMechType = PK11_AlgtagToMechanism(pbeAlgTag);
  1778     if (slot != pk->pkcs11Slot) {
  1779 	if (PK11_DoesMechanism(pk->pkcs11Slot,pbeMechType)) {
  1780 	    slot = pk->pkcs11Slot;
  1783     key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, wincx);
  1784     if (key == NULL) {
  1785 	rv = SECFailure;
  1786 	goto loser;
  1789     cryptoMechType = PK11_GetPBECryptoMechanism(algid, &crypto_param, pwitem);
  1790     if (cryptoMechType == CKM_INVALID_MECHANISM) {
  1791 	rv = SECFailure;
  1792 	goto loser;
  1795     cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMechType);
  1796     cryptoMech.pParameter = crypto_param ? crypto_param->data : NULL;
  1797     cryptoMech.ulParameterLen = crypto_param ? crypto_param->len : 0;
  1799     /* If the key isn't in the private key slot, move it */
  1800     if (key->slot != pk->pkcs11Slot) {
  1801 	PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot,
  1802 						key->type, CKA_WRAP, key);
  1803 	if (newkey == NULL) {
  1804             /* couldn't import the wrapping key, try exporting the
  1805              * private key */
  1806 	    tmpPK = pk11_loadPrivKey(key->slot, pk, NULL, PR_FALSE, PR_TRUE);
  1807 	    if (tmpPK == NULL) {
  1808 		rv = SECFailure;
  1809 		goto loser;
  1811 	    pk = tmpPK;
  1812 	} else {
  1813 	    /* free the old key and use the new key */
  1814 	    PK11_FreeSymKey(key);
  1815 	    key = newkey;
  1819     /* we are extracting an encrypted privateKey structure.
  1820      * which needs to be freed along with the buffer into which it is
  1821      * returned.  eventually, we should retrieve an encrypted key using
  1822      * pkcs8/pkcs5.
  1823      */
  1824     encBufLen = 0;
  1825     PK11_EnterSlotMonitor(pk->pkcs11Slot);
  1826     crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, 
  1827     		&cryptoMech, key->objectID, pk->pkcs11ID, NULL, 
  1828 		&encBufLen); 
  1829     PK11_ExitSlotMonitor(pk->pkcs11Slot);
  1830     if (crv != CKR_OK) {
  1831 	rv = SECFailure;
  1832 	goto loser;
  1834     epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen);
  1835     if (!epki->encryptedData.data) {
  1836 	rv = SECFailure;
  1837 	goto loser;
  1839     PK11_EnterSlotMonitor(pk->pkcs11Slot);
  1840     crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, 
  1841     		&cryptoMech, key->objectID, pk->pkcs11ID, 
  1842 		epki->encryptedData.data, &encBufLen); 
  1843     PK11_ExitSlotMonitor(pk->pkcs11Slot);
  1844     epki->encryptedData.len = (unsigned int) encBufLen;
  1845     if(crv != CKR_OK) {
  1846 	rv = SECFailure;
  1847 	goto loser;
  1850     if(!epki->encryptedData.len) {
  1851 	rv = SECFailure;
  1852 	goto loser;
  1855     rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid);
  1857 loser:
  1858     if(crypto_param != NULL) {
  1859 	SECITEM_ZfreeItem(crypto_param, PR_TRUE);
  1860 	crypto_param = NULL;
  1863     if(key != NULL) {
  1864     	PK11_FreeSymKey(key);
  1866     if (tmpPK != NULL) {
  1867 	SECKEY_DestroyPrivateKey(tmpPK);
  1869     SECOID_DestroyAlgorithmID(algid, PR_TRUE);
  1871     if(rv == SECFailure) {
  1872 	if(arena != NULL) {
  1873 	    PORT_FreeArena(arena, PR_TRUE);
  1875 	epki = NULL;
  1878     return epki;
  1881 SECKEYEncryptedPrivateKeyInfo * 
  1882 PK11_ExportEncryptedPrivateKeyInfo(
  1883    PK11SlotInfo    *slot,      /* optional, encrypt key in this slot */
  1884    SECOidTag        algTag,    /* encrypt key with this algorithm */
  1885    SECItem         *pwitem,    /* password for PBE encryption */
  1886    CERTCertificate *cert,      /* wrap priv key for this user cert */
  1887    int              iteration, /* interations for PBE alg */
  1888    void            *wincx)     /* context for password callback ? */
  1890     SECKEYEncryptedPrivateKeyInfo *epki = NULL;
  1891     SECKEYPrivateKey              *pk   = PK11_FindKeyByAnyCert(cert, wincx);
  1892     if (pk != NULL) {
  1893 	epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk, 
  1894 	                                       iteration, wincx);
  1895 	SECKEY_DestroyPrivateKey(pk);
  1897     return epki;
  1900 SECItem*
  1901 PK11_DEREncodePublicKey(const SECKEYPublicKey *pubk)
  1903     return SECKEY_EncodeDERSubjectPublicKeyInfo(pubk);
  1906 char *
  1907 PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey)
  1909     return PK11_GetObjectNickname(privKey->pkcs11Slot,privKey->pkcs11ID);
  1912 char *
  1913 PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey)
  1915     return PK11_GetObjectNickname(pubKey->pkcs11Slot,pubKey->pkcs11ID);
  1918 SECStatus
  1919 PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname)
  1921     return PK11_SetObjectNickname(privKey->pkcs11Slot,
  1922 					privKey->pkcs11ID,nickname);
  1925 SECStatus
  1926 PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname)
  1928     return PK11_SetObjectNickname(pubKey->pkcs11Slot,
  1929 					pubKey->pkcs11ID,nickname);
  1932 SECKEYPQGParams *
  1933 PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey)
  1935     CK_ATTRIBUTE pTemplate[] = {
  1936 	{ CKA_PRIME, NULL, 0 },
  1937 	{ CKA_SUBPRIME, NULL, 0 },
  1938 	{ CKA_BASE, NULL, 0 },
  1939     };
  1940     int pTemplateLen = sizeof(pTemplate)/sizeof(pTemplate[0]);
  1941     PLArenaPool *arena = NULL;
  1942     SECKEYPQGParams *params;
  1943     CK_RV crv;
  1946     arena = PORT_NewArena(2048);
  1947     if (arena == NULL) {
  1948 	goto loser;
  1950     params=(SECKEYPQGParams *)PORT_ArenaZAlloc(arena,sizeof(SECKEYPQGParams));
  1951     if (params == NULL) {
  1952 	goto loser;
  1955     crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, 
  1956 						pTemplate, pTemplateLen);
  1957     if (crv != CKR_OK) {
  1958         PORT_SetError( PK11_MapError(crv) );
  1959 	goto loser;
  1962     params->arena = arena;
  1963     params->prime.data = pTemplate[0].pValue;
  1964     params->prime.len = pTemplate[0].ulValueLen;
  1965     params->subPrime.data = pTemplate[1].pValue;
  1966     params->subPrime.len = pTemplate[1].ulValueLen;
  1967     params->base.data = pTemplate[2].pValue;
  1968     params->base.len = pTemplate[2].ulValueLen;
  1970     return params;
  1972 loser:
  1973     if (arena != NULL) {
  1974 	PORT_FreeArena(arena,PR_FALSE);
  1976     return NULL;
  1979 SECKEYPrivateKey*
  1980 PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
  1981 				      SECKEYPrivateKey *privKey)
  1983     CK_RV             crv;
  1984     CK_OBJECT_HANDLE  newKeyID;
  1986     static const CK_BBOOL     ckfalse = CK_FALSE;
  1987     static const CK_ATTRIBUTE template[1] = { 
  1988        { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse }
  1989     };
  1991     if (destSlot && destSlot != privKey->pkcs11Slot) {
  1992 	SECKEYPrivateKey *newKey =
  1993 	       pk11_loadPrivKey(destSlot, 
  1994 				privKey, 
  1995 			        NULL,     /* pubKey    */
  1996 			        PR_FALSE, /* token     */
  1997 			        PR_FALSE);/* sensitive */
  1998 	if (newKey)
  1999 	    return newKey;
  2001     destSlot = privKey->pkcs11Slot;
  2002     PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx);
  2003     PK11_EnterSlotMonitor(destSlot);
  2004     crv = PK11_GETTAB(destSlot)->C_CopyObject(	destSlot->session, 
  2005 						privKey->pkcs11ID,
  2006 						(CK_ATTRIBUTE *)template, 
  2007 						1, &newKeyID);
  2008     PK11_ExitSlotMonitor(destSlot);
  2010     if (crv != CKR_OK) {
  2011 	PORT_SetError( PK11_MapError(crv) );
  2012 	return NULL;
  2015     return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/, 
  2016 			    newKeyID, privKey->wincx);
  2019 SECKEYPrivateKey*
  2020 PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx)
  2022     PK11SlotInfo* slot = privk->pkcs11Slot;
  2023     CK_ATTRIBUTE template[1];
  2024     CK_ATTRIBUTE *attrs = template;
  2025     CK_BBOOL cktrue = CK_TRUE;
  2026     CK_RV crv;
  2027     CK_OBJECT_HANDLE newKeyID;
  2028     CK_SESSION_HANDLE rwsession;
  2030     PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
  2032     PK11_Authenticate(slot, PR_TRUE, wincx);
  2033     rwsession = PK11_GetRWSession(slot);
  2034     if (rwsession == CK_INVALID_SESSION) {
  2035     	PORT_SetError(SEC_ERROR_BAD_DATA);
  2036 	return NULL;
  2038     crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID,
  2039         template, 1, &newKeyID);
  2040     PK11_RestoreROSession(slot, rwsession);
  2042     if (crv != CKR_OK) {
  2043         PORT_SetError( PK11_MapError(crv) );
  2044         return NULL;
  2047     return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
  2048         newKeyID, NULL /*wincx*/);
  2051 /*
  2052  * destroy a private key if there are no matching certs.
  2053  * this function also frees the privKey structure.
  2054  */
  2055 SECStatus
  2056 PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force)
  2058     CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);
  2059     SECStatus rv = SECWouldBlock;
  2061     if (!cert || force) {
  2062 	/* now, then it's safe for the key to go away */
  2063 	rv = PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);
  2065     if (cert) {
  2066 	CERT_DestroyCertificate(cert);
  2068     SECKEY_DestroyPrivateKey(privKey);
  2069     return rv;
  2072 /*
  2073  * destroy a private key if there are no matching certs.
  2074  * this function also frees the privKey structure.
  2075  */
  2076 SECStatus
  2077 PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey)
  2079     /* now, then it's safe for the key to go away */
  2080     if (pubKey->pkcs11Slot == NULL) {
  2081 	return SECFailure;
  2083     PK11_DestroyTokenObject(pubKey->pkcs11Slot,pubKey->pkcs11ID);
  2084     SECKEY_DestroyPublicKey(pubKey);
  2085     return SECSuccess;
  2088 /*
  2089  * key call back structure.
  2090  */
  2091 typedef struct pk11KeyCallbackStr {
  2092 	SECStatus (* callback)(SECKEYPrivateKey *,void *);
  2093 	void *callbackArg;
  2094 	void *wincx;
  2095 } pk11KeyCallback;
  2097 /*
  2098  * callback to map Object Handles to Private Keys;
  2099  */
  2100 SECStatus
  2101 pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
  2103     SECStatus rv = SECSuccess;
  2104     SECKEYPrivateKey *privKey;
  2105     pk11KeyCallback *keycb = (pk11KeyCallback *) arg;
  2106     if (!arg) {
  2107         return SECFailure;
  2110     privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);
  2112     if (privKey == NULL) {
  2113 	return SECFailure;
  2116     if (keycb->callback) {
  2117 	rv = (*keycb->callback)(privKey,keycb->callbackArg);
  2120     SECKEY_DestroyPrivateKey(privKey);	    
  2121     return rv;
  2124 /***********************************************************************
  2125  * PK11_TraversePrivateKeysInSlot
  2127  * Traverses all the private keys on a slot.
  2129  * INPUTS
  2130  *      slot
  2131  *          The PKCS #11 slot whose private keys you want to traverse.
  2132  *      callback
  2133  *          A callback function that will be called for each key.
  2134  *      arg
  2135  *          An argument that will be passed to the callback function.
  2136  */
  2137 SECStatus
  2138 PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot,
  2139     SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg)
  2141     pk11KeyCallback perKeyCB;
  2142     pk11TraverseSlot perObjectCB;
  2143     CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY;
  2144     CK_BBOOL ckTrue = CK_TRUE;
  2145     CK_ATTRIBUTE theTemplate[2];
  2146     int templateSize = 2;
  2148     theTemplate[0].type = CKA_CLASS;
  2149     theTemplate[0].pValue = &privkClass;
  2150     theTemplate[0].ulValueLen = sizeof(privkClass);
  2151     theTemplate[1].type = CKA_TOKEN;
  2152     theTemplate[1].pValue = &ckTrue;
  2153     theTemplate[1].ulValueLen = sizeof(ckTrue);
  2155     if(slot==NULL) {
  2156         return SECSuccess;
  2159     perObjectCB.callback = pk11_DoKeys;
  2160     perObjectCB.callbackArg = &perKeyCB;
  2161     perObjectCB.findTemplate = theTemplate;
  2162     perObjectCB.templateCount = templateSize;
  2163     perKeyCB.callback = callback;
  2164     perKeyCB.callbackArg = arg;
  2165     perKeyCB.wincx = NULL;
  2167     return PK11_TraverseSlot(slot, &perObjectCB);
  2170 /*
  2171  * return the private key with the given ID
  2172  */
  2173 CK_OBJECT_HANDLE
  2174 pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)
  2176     CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
  2177     CK_ATTRIBUTE theTemplate[] = {
  2178 	{ CKA_ID, NULL, 0 },
  2179 	{ CKA_CLASS, NULL, 0 },
  2180     };
  2181     /* if you change the array, change the variable below as well */
  2182     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  2183     CK_ATTRIBUTE *attrs = theTemplate;
  2185     PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++;
  2186     PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
  2188     return pk11_FindObjectByTemplate(slot,theTemplate,tsize);
  2192 SECKEYPrivateKey *
  2193 PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
  2195     CK_OBJECT_HANDLE keyHandle;
  2196     SECKEYPrivateKey *privKey;
  2198     keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
  2199     if (keyHandle == CK_INVALID_HANDLE) { 
  2200 	return NULL;
  2202     privKey =  PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
  2203     return privKey;
  2206 /*
  2207  * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
  2208  * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
  2209  * smart cards happy.
  2210  */
  2211 SECItem *
  2212 PK11_MakeIDFromPubKey(SECItem *pubKeyData) 
  2214     PK11Context *context;
  2215     SECItem *certCKA_ID;
  2216     SECStatus rv;
  2218     if (pubKeyData->len <= SHA1_LENGTH) {
  2219 	/* probably an already hashed value. The strongest known public
  2220 	 * key values <= 160 bits would be less than 40 bit symetric in
  2221 	 * strength. Don't hash them, just return the value. There are
  2222 	 * none at the time of this writing supported by previous versions
  2223 	 * of NSS, so change is binary compatible safe */
  2224 	return SECITEM_DupItem(pubKeyData);
  2227     context = PK11_CreateDigestContext(SEC_OID_SHA1);
  2228     if (context == NULL) {
  2229 	return NULL;
  2232     rv = PK11_DigestBegin(context);
  2233     if (rv == SECSuccess) {
  2234     	rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len);
  2236     if (rv != SECSuccess) {
  2237 	PK11_DestroyContext(context,PR_TRUE);
  2238 	return NULL;
  2241     certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
  2242     if (certCKA_ID == NULL) {
  2243 	PK11_DestroyContext(context,PR_TRUE);
  2244 	return NULL;
  2247     certCKA_ID->len = SHA1_LENGTH;
  2248     certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len);
  2249     if (certCKA_ID->data == NULL) {
  2250 	PORT_Free(certCKA_ID);
  2251 	PK11_DestroyContext(context,PR_TRUE);
  2252         return NULL;
  2255     rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len,
  2256 								SHA1_LENGTH);
  2257     PK11_DestroyContext(context,PR_TRUE);
  2258     if (rv != SECSuccess) {
  2259     	SECITEM_FreeItem(certCKA_ID,PR_TRUE);
  2260 	return NULL;
  2263     return certCKA_ID;
  2266 /* Looking for PK11_GetKeyIDFromPrivateKey?
  2267  * Call PK11_GetLowLevelKeyIDForPrivateKey instead.
  2268  */
  2271 SECItem *
  2272 PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey)
  2274     return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID);
  2277 static SECStatus
  2278 privateKeyListCallback(SECKEYPrivateKey *key, void *arg)
  2280     SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList*)arg;
  2281     return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key));
  2284 SECKEYPrivateKeyList*
  2285 PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot)
  2287     SECStatus status;
  2288     SECKEYPrivateKeyList *keys;
  2290     keys = SECKEY_NewPrivateKeyList();
  2291     if(keys == NULL) return NULL;
  2293     status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback,
  2294 		(void*)keys);
  2296     if( status != SECSuccess ) {
  2297 	SECKEY_DestroyPrivateKeyList(keys);
  2298 	keys = NULL;
  2301     return keys;
  2304 SECKEYPublicKeyList*
  2305 PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname)
  2307     CK_ATTRIBUTE findTemp[4];
  2308     CK_ATTRIBUTE *attrs;
  2309     CK_BBOOL ckTrue = CK_TRUE;
  2310     CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY;
  2311     int tsize = 0;
  2312     int objCount = 0;
  2313     CK_OBJECT_HANDLE *key_ids;
  2314     SECKEYPublicKeyList *keys;
  2315     int i,len;
  2318     attrs = findTemp;
  2319     PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
  2320     PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
  2321     if (nickname) {
  2322 	len = PORT_Strlen(nickname);
  2323 	PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
  2325     tsize = attrs - findTemp;
  2326     PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
  2328     key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
  2329     if (key_ids == NULL) {
  2330 	return NULL;
  2332     keys = SECKEY_NewPublicKeyList();
  2333     if (keys == NULL) {
  2334 	PORT_Free(key_ids);
  2335 	return NULL;
  2338     for (i=0; i < objCount ; i++) {
  2339 	SECKEYPublicKey *pubKey = 
  2340 				PK11_ExtractPublicKey(slot,nullKey,key_ids[i]);
  2341 	if (pubKey) {
  2342 	    SECKEY_AddPublicKeyToListTail(keys, pubKey);
  2346    PORT_Free(key_ids);
  2347    return keys;
  2350 SECKEYPrivateKeyList*
  2351 PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
  2353     CK_ATTRIBUTE findTemp[4];
  2354     CK_ATTRIBUTE *attrs;
  2355     CK_BBOOL ckTrue = CK_TRUE;
  2356     CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
  2357     int tsize = 0;
  2358     int objCount = 0;
  2359     CK_OBJECT_HANDLE *key_ids;
  2360     SECKEYPrivateKeyList *keys;
  2361     int i,len;
  2364     attrs = findTemp;
  2365     PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
  2366     PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
  2367     if (nickname) {
  2368 	len = PORT_Strlen(nickname);
  2369 	PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
  2371     tsize = attrs - findTemp;
  2372     PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
  2374     key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
  2375     if (key_ids == NULL) {
  2376 	return NULL;
  2378     keys = SECKEY_NewPrivateKeyList();
  2379     if (keys == NULL) {
  2380 	PORT_Free(key_ids);
  2381 	return NULL;
  2384     for (i=0; i < objCount ; i++) {
  2385 	SECKEYPrivateKey *privKey = 
  2386 		PK11_MakePrivKey(slot,nullKey,PR_TRUE,key_ids[i],wincx);
  2387 	SECKEY_AddPrivateKeyToListTail(keys, privKey);
  2390    PORT_Free(key_ids);
  2391    return keys;

mercurial