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