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