| OLD | NEW |
| (Empty) |
| 1 | |
| 2 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 5 /* | |
| 6 * This file PKCS #12 fuctions that should really be moved to the | |
| 7 * PKCS #12 directory, however we can't do that in a point release | |
| 8 * because that will break binary compatibility, so we keep them here for now. | |
| 9 */ | |
| 10 | |
| 11 #include "seccomon.h" | |
| 12 #include "secmod.h" | |
| 13 #include "secmodi.h" | |
| 14 #include "pkcs11.h" | |
| 15 #include "pk11func.h" | |
| 16 #include "secitem.h" | |
| 17 #include "key.h" | |
| 18 #include "secoid.h" | |
| 19 #include "secasn1.h" | |
| 20 #include "secerr.h" | |
| 21 #include "prerror.h" | |
| 22 | |
| 23 | |
| 24 | |
| 25 /* These data structures should move to a common .h file shared between the | |
| 26 * wrappers and the pkcs 12 code. */ | |
| 27 | |
| 28 /* | |
| 29 ** RSA Raw Private Key structures | |
| 30 */ | |
| 31 | |
| 32 /* member names from PKCS#1, section 7.2 */ | |
| 33 struct SECKEYRSAPrivateKeyStr { | |
| 34 PLArenaPool * arena; | |
| 35 SECItem version; | |
| 36 SECItem modulus; | |
| 37 SECItem publicExponent; | |
| 38 SECItem privateExponent; | |
| 39 SECItem prime1; | |
| 40 SECItem prime2; | |
| 41 SECItem exponent1; | |
| 42 SECItem exponent2; | |
| 43 SECItem coefficient; | |
| 44 }; | |
| 45 typedef struct SECKEYRSAPrivateKeyStr SECKEYRSAPrivateKey; | |
| 46 | |
| 47 | |
| 48 /* | |
| 49 ** DSA Raw Private Key structures | |
| 50 */ | |
| 51 | |
| 52 struct SECKEYDSAPrivateKeyStr { | |
| 53 SECKEYPQGParams params; | |
| 54 SECItem privateValue; | |
| 55 }; | |
| 56 typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey; | |
| 57 | |
| 58 /* | |
| 59 ** Diffie-Hellman Raw Private Key structures | |
| 60 ** Structure member names suggested by PKCS#3. | |
| 61 */ | |
| 62 struct SECKEYDHPrivateKeyStr { | |
| 63 PLArenaPool * arena; | |
| 64 SECItem prime; | |
| 65 SECItem base; | |
| 66 SECItem privateValue; | |
| 67 }; | |
| 68 typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey; | |
| 69 | |
| 70 /* | |
| 71 ** raw private key object | |
| 72 */ | |
| 73 struct SECKEYRawPrivateKeyStr { | |
| 74 PLArenaPool *arena; | |
| 75 KeyType keyType; | |
| 76 union { | |
| 77 SECKEYRSAPrivateKey rsa; | |
| 78 SECKEYDSAPrivateKey dsa; | |
| 79 SECKEYDHPrivateKey dh; | |
| 80 } u; | |
| 81 }; | |
| 82 typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey; | |
| 83 | |
| 84 SEC_ASN1_MKSUB(SEC_AnyTemplate) | |
| 85 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | |
| 86 | |
| 87 /* ASN1 Templates for new decoder/encoder */ | |
| 88 /* | |
| 89 * Attribute value for PKCS8 entries (static?) | |
| 90 */ | |
| 91 const SEC_ASN1Template SECKEY_AttributeTemplate[] = { | |
| 92 { SEC_ASN1_SEQUENCE, | |
| 93 0, NULL, sizeof(SECKEYAttribute) }, | |
| 94 { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) }, | |
| 95 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(SECKEYAttribute, attrValue), | |
| 96 SEC_ASN1_SUB(SEC_AnyTemplate) }, | |
| 97 { 0 } | |
| 98 }; | |
| 99 | |
| 100 const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = { | |
| 101 { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate }, | |
| 102 }; | |
| 103 | |
| 104 const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = { | |
| 105 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) }, | |
| 106 { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo,version) }, | |
| 107 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 108 offsetof(SECKEYPrivateKeyInfo,algorithm), | |
| 109 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 110 { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo,privateKey) }, | |
| 111 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 112 offsetof(SECKEYPrivateKeyInfo,attributes), | |
| 113 SECKEY_SetOfAttributeTemplate }, | |
| 114 { 0 } | |
| 115 }; | |
| 116 | |
| 117 const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = { | |
| 118 { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate } | |
| 119 }; | |
| 120 | |
| 121 const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = { | |
| 122 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) }, | |
| 123 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.version) }, | |
| 124 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.modulus) }, | |
| 125 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.publicExponent) }, | |
| 126 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.privateExponent) }, | |
| 127 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.prime1) }, | |
| 128 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.prime2) }, | |
| 129 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.exponent1) }, | |
| 130 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.exponent2) }, | |
| 131 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.coefficient) }, | |
| 132 { 0 } | |
| 133 }; | |
| 134 | |
| 135 const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = { | |
| 136 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dsa.privateValue) }, | |
| 137 }; | |
| 138 | |
| 139 const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = { | |
| 140 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.privateValue) }, | |
| 141 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.base) }, | |
| 142 { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.prime) }, | |
| 143 }; | |
| 144 | |
| 145 const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = { | |
| 146 { SEC_ASN1_SEQUENCE, | |
| 147 0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) }, | |
| 148 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 149 offsetof(SECKEYEncryptedPrivateKeyInfo,algorithm), | |
| 150 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 151 { SEC_ASN1_OCTET_STRING, | |
| 152 offsetof(SECKEYEncryptedPrivateKeyInfo,encryptedData) }, | |
| 153 { 0 } | |
| 154 }; | |
| 155 | |
| 156 const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = { | |
| 157 { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate } | |
| 158 }; | |
| 159 | |
| 160 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate) | |
| 161 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate) | |
| 162 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate) | |
| 163 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate) | |
| 164 | |
| 165 /* | |
| 166 * See bugzilla bug 125359 | |
| 167 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, | |
| 168 * all of the templates above that en/decode into integers must be converted | |
| 169 * from ASN.1's signed integer type. This is done by marking either the | |
| 170 * source or destination (encoding or decoding, respectively) type as | |
| 171 * siUnsignedInteger. | |
| 172 */ | |
| 173 | |
| 174 static void | |
| 175 prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) | |
| 176 { | |
| 177 key->u.rsa.modulus.type = siUnsignedInteger; | |
| 178 key->u.rsa.publicExponent.type = siUnsignedInteger; | |
| 179 key->u.rsa.privateExponent.type = siUnsignedInteger; | |
| 180 key->u.rsa.prime1.type = siUnsignedInteger; | |
| 181 key->u.rsa.prime2.type = siUnsignedInteger; | |
| 182 key->u.rsa.exponent1.type = siUnsignedInteger; | |
| 183 key->u.rsa.exponent2.type = siUnsignedInteger; | |
| 184 key->u.rsa.coefficient.type = siUnsignedInteger; | |
| 185 } | |
| 186 | |
| 187 static void | |
| 188 prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) | |
| 189 { | |
| 190 key->u.dsa.privateValue.type = siUnsignedInteger; | |
| 191 key->u.dsa.params.prime.type = siUnsignedInteger; | |
| 192 key->u.dsa.params.subPrime.type = siUnsignedInteger; | |
| 193 key->u.dsa.params.base.type = siUnsignedInteger; | |
| 194 } | |
| 195 | |
| 196 static void | |
| 197 prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) | |
| 198 { | |
| 199 key->u.dh.privateValue.type = siUnsignedInteger; | |
| 200 key->u.dh.prime.type = siUnsignedInteger; | |
| 201 key->u.dh.base.type = siUnsignedInteger; | |
| 202 } | |
| 203 | |
| 204 | |
| 205 SECStatus | |
| 206 PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI, | |
| 207 SECItem *nickname, SECItem *publicValue, PRBool isPerm, | |
| 208 PRBool isPrivate, unsigned int keyUsage, void *wincx) | |
| 209 { | |
| 210 return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI, | |
| 211 nickname, publicValue, isPerm, isPrivate, keyUsage, NULL, wincx); | |
| 212 } | |
| 213 | |
| 214 SECStatus | |
| 215 PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI, | |
| 216 SECItem *nickname, SECItem *publicValue, PRBool isPerm, | |
| 217 PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey** privk, | |
| 218 void *wincx) | |
| 219 { | |
| 220 SECKEYPrivateKeyInfo *pki = NULL; | |
| 221 PLArenaPool *temparena = NULL; | |
| 222 SECStatus rv = SECFailure; | |
| 223 | |
| 224 temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 225 if (!temparena) | |
| 226 return rv; | |
| 227 pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo); | |
| 228 if (!pki) { | |
| 229 PORT_FreeArena(temparena, PR_FALSE); | |
| 230 return rv; | |
| 231 } | |
| 232 pki->arena = temparena; | |
| 233 | |
| 234 rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate, | |
| 235 derPKI); | |
| 236 if( rv != SECSuccess ) { | |
| 237 /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the | |
| 238 * validity of the data in pki. The best we can do is free the arena | |
| 239 * and return. | |
| 240 */ | |
| 241 PORT_FreeArena(temparena, PR_TRUE); | |
| 242 return rv; | |
| 243 } | |
| 244 | |
| 245 rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname, | |
| 246 publicValue, isPerm, isPrivate, keyUsage, privk, wincx); | |
| 247 | |
| 248 /* this zeroes the key and frees the arena */ | |
| 249 SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/); | |
| 250 return rv; | |
| 251 } | |
| 252 | |
| 253 SECStatus | |
| 254 PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, | |
| 255 SECItem *nickname, SECItem *publicValue, PRBool isPerm, | |
| 256 PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk, | |
| 257 void *wincx) | |
| 258 { | |
| 259 CK_BBOOL cktrue = CK_TRUE; | |
| 260 CK_BBOOL ckfalse = CK_FALSE; | |
| 261 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; | |
| 262 CK_KEY_TYPE keyType = CKK_RSA; | |
| 263 CK_OBJECT_HANDLE objectID; | |
| 264 CK_ATTRIBUTE theTemplate[20]; | |
| 265 int templateCount = 0; | |
| 266 SECStatus rv = SECFailure; | |
| 267 CK_ATTRIBUTE *attrs; | |
| 268 CK_ATTRIBUTE *signedattr = NULL; | |
| 269 int signedcount = 0; | |
| 270 CK_ATTRIBUTE *ap; | |
| 271 SECItem *ck_id = NULL; | |
| 272 | |
| 273 attrs = theTemplate; | |
| 274 | |
| 275 | |
| 276 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; | |
| 277 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; | |
| 278 PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, | |
| 279 sizeof(CK_BBOOL) ); attrs++; | |
| 280 PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, | |
| 281 sizeof(CK_BBOOL) ); attrs++; | |
| 282 PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse, | |
| 283 sizeof(CK_BBOOL) ); attrs++; | |
| 284 | |
| 285 switch (lpk->keyType) { | |
| 286 case rsaKey: | |
| 287 keyType = CKK_RSA; | |
| 288 PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? | |
| 289 &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; | |
| 290 PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT)
? | |
| 291 &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; | |
| 292 PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? | |
| 293 &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; | |
| 294 PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, | |
| 295 (keyUsage & KU_DIGITAL_SIGNATURE) ? | |
| 296 &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; | |
| 297 ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus); | |
| 298 if (ck_id == NULL) { | |
| 299 goto loser; | |
| 300 } | |
| 301 PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; | |
| 302 if (nickname) { | |
| 303 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
attrs++; | |
| 304 } | |
| 305 signedattr = attrs; | |
| 306 PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data, | |
| 307 lpk->u.rsa.modulus.len); attrs++
; | |
| 308 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, | |
| 309 lpk->u.rsa.publicExponent.data, | |
| 310 lpk->u.rsa.publicExponent.len); attrs++; | |
| 311 PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, | |
| 312 lpk->u.rsa.privateExponent.data, | |
| 313 lpk->u.rsa.privateExponent.len); attrs++; | |
| 314 PK11_SETATTRS(attrs, CKA_PRIME_1, | |
| 315 lpk->u.rsa.prime1.data, | |
| 316 lpk->u.rsa.prime1.len); attrs++; | |
| 317 PK11_SETATTRS(attrs, CKA_PRIME_2, | |
| 318 lpk->u.rsa.prime2.data, | |
| 319 lpk->u.rsa.prime2.len); attrs++; | |
| 320 PK11_SETATTRS(attrs, CKA_EXPONENT_1, | |
| 321 lpk->u.rsa.exponent1.data, | |
| 322 lpk->u.rsa.exponent1.len); attrs++; | |
| 323 PK11_SETATTRS(attrs, CKA_EXPONENT_2, | |
| 324 lpk->u.rsa.exponent2.data, | |
| 325 lpk->u.rsa.exponent2.len); attrs++; | |
| 326 PK11_SETATTRS(attrs, CKA_COEFFICIENT, | |
| 327 lpk->u.rsa.coefficient.data, | |
| 328 lpk->u.rsa.coefficient.len); attrs++; | |
| 329 break; | |
| 330 case dsaKey: | |
| 331 keyType = CKK_DSA; | |
| 332 /* To make our intenal PKCS #11 module work correctly with | |
| 333 * our database, we need to pass in the public key value for | |
| 334 * this dsa key. We have a netscape only CKA_ value to do this. | |
| 335 * Only send it to internal slots */ | |
| 336 if( publicValue == NULL ) { | |
| 337 goto loser; | |
| 338 } | |
| 339 if (PK11_IsInternal(slot)) { | |
| 340 PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, | |
| 341 publicValue->data, publicValue->len); attrs++; | |
| 342 } | |
| 343 PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++; | |
| 344 PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); a
ttrs++; | |
| 345 if(nickname) { | |
| 346 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); | |
| 347 attrs++; | |
| 348 } | |
| 349 ck_id = PK11_MakeIDFromPubKey(publicValue); | |
| 350 if (ck_id == NULL) { | |
| 351 goto loser; | |
| 352 } | |
| 353 PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; | |
| 354 signedattr = attrs; | |
| 355 PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data, | |
| 356 lpk->u.dsa.params.prime.len); attrs++; | |
| 357 PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data, | |
| 358 lpk->u.dsa.params.subPrime.len); attrs++; | |
| 359 PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data, | |
| 360 lpk->u.dsa.params.base.len); attrs++; | |
| 361 PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data, | |
| 362 lpk->u.dsa.privateValue.len); attrs++; | |
| 363 break; | |
| 364 case dhKey: | |
| 365 keyType = CKK_DH; | |
| 366 /* To make our intenal PKCS #11 module work correctly with | |
| 367 * our database, we need to pass in the public key value for | |
| 368 * this dh key. We have a netscape only CKA_ value to do this. | |
| 369 * Only send it to internal slots */ | |
| 370 if (PK11_IsInternal(slot)) { | |
| 371 PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, | |
| 372 publicValue->data, publicValue->len); attrs++; | |
| 373 } | |
| 374 PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++
; | |
| 375 if(nickname) { | |
| 376 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); | |
| 377 attrs++; | |
| 378 } | |
| 379 ck_id = PK11_MakeIDFromPubKey(publicValue); | |
| 380 if (ck_id == NULL) { | |
| 381 goto loser; | |
| 382 } | |
| 383 PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; | |
| 384 signedattr = attrs; | |
| 385 PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data, | |
| 386 lpk->u.dh.prime.len); attrs++; | |
| 387 PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data, | |
| 388 lpk->u.dh.base.len); attrs++; | |
| 389 PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data, | |
| 390 lpk->u.dh.privateValue.len); attrs++; | |
| 391 break; | |
| 392 /* what about fortezza??? */ | |
| 393 default: | |
| 394 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 395 goto loser; | |
| 396 } | |
| 397 templateCount = attrs - theTemplate; | |
| 398 PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 399 PORT_Assert(signedattr != NULL); | |
| 400 signedcount = attrs - signedattr; | |
| 401 | |
| 402 for (ap=signedattr; signedcount; ap++, signedcount--) { | |
| 403 pk11_SignedToUnsigned(ap); | |
| 404 } | |
| 405 | |
| 406 rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, | |
| 407 theTemplate, templateCount, isPerm, &objectID); | |
| 408 | |
| 409 /* create and return a SECKEYPrivateKey */ | |
| 410 if( rv == SECSuccess && privk != NULL) { | |
| 411 *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx); | |
| 412 if( *privk == NULL ) { | |
| 413 rv = SECFailure; | |
| 414 } | |
| 415 } | |
| 416 loser: | |
| 417 if (ck_id) { | |
| 418 SECITEM_ZfreeItem(ck_id, PR_TRUE); | |
| 419 } | |
| 420 return rv; | |
| 421 } | |
| 422 | |
| 423 SECStatus | |
| 424 PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, | |
| 425 SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue, | |
| 426 PRBool isPerm, PRBool isPrivate, unsigned int keyUsage, | |
| 427 SECKEYPrivateKey **privk, void *wincx) | |
| 428 { | |
| 429 SECStatus rv = SECFailure; | |
| 430 SECKEYRawPrivateKey *lpk = NULL; | |
| 431 const SEC_ASN1Template *keyTemplate, *paramTemplate; | |
| 432 void *paramDest = NULL; | |
| 433 PLArenaPool *arena = NULL; | |
| 434 | |
| 435 arena = PORT_NewArena(2048); | |
| 436 if(!arena) { | |
| 437 return SECFailure; | |
| 438 } | |
| 439 | |
| 440 /* need to change this to use RSA/DSA keys */ | |
| 441 lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena, | |
| 442 sizeof(SECKEYRawPrivateKey)); | |
| 443 if(lpk == NULL) { | |
| 444 goto loser; | |
| 445 } | |
| 446 lpk->arena = arena; | |
| 447 | |
| 448 switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { | |
| 449 case SEC_OID_PKCS1_RSA_ENCRYPTION: | |
| 450 prepare_rsa_priv_key_export_for_asn1(lpk); | |
| 451 keyTemplate = SECKEY_RSAPrivateKeyExportTemplate; | |
| 452 paramTemplate = NULL; | |
| 453 paramDest = NULL; | |
| 454 lpk->keyType = rsaKey; | |
| 455 break; | |
| 456 case SEC_OID_ANSIX9_DSA_SIGNATURE: | |
| 457 prepare_dsa_priv_key_export_for_asn1(lpk); | |
| 458 keyTemplate = SECKEY_DSAPrivateKeyExportTemplate; | |
| 459 paramTemplate = SECKEY_PQGParamsTemplate; | |
| 460 paramDest = &(lpk->u.dsa.params); | |
| 461 lpk->keyType = dsaKey; | |
| 462 break; | |
| 463 case SEC_OID_X942_DIFFIE_HELMAN_KEY: | |
| 464 if(!publicValue) { | |
| 465 goto loser; | |
| 466 } | |
| 467 prepare_dh_priv_key_export_for_asn1(lpk); | |
| 468 keyTemplate = SECKEY_DHPrivateKeyExportTemplate; | |
| 469 paramTemplate = NULL; | |
| 470 paramDest = NULL; | |
| 471 lpk->keyType = dhKey; | |
| 472 break; | |
| 473 | |
| 474 default: | |
| 475 keyTemplate = NULL; | |
| 476 paramTemplate = NULL; | |
| 477 paramDest = NULL; | |
| 478 break; | |
| 479 } | |
| 480 | |
| 481 if(!keyTemplate) { | |
| 482 goto loser; | |
| 483 } | |
| 484 | |
| 485 /* decode the private key and any algorithm parameters */ | |
| 486 rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey); | |
| 487 if(rv != SECSuccess) { | |
| 488 goto loser; | |
| 489 } | |
| 490 if(paramDest && paramTemplate) { | |
| 491 rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate, | |
| 492 &(pki->algorithm.parameters)); | |
| 493 if(rv != SECSuccess) { | |
| 494 goto loser; | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 rv = PK11_ImportAndReturnPrivateKey(slot,lpk,nickname,publicValue, isPerm, | |
| 499 isPrivate, keyUsage, privk, wincx); | |
| 500 | |
| 501 | |
| 502 loser: | |
| 503 if (arena != NULL) { | |
| 504 PORT_FreeArena(arena, PR_TRUE); | |
| 505 } | |
| 506 | |
| 507 return rv; | |
| 508 } | |
| 509 | |
| 510 SECStatus | |
| 511 PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki, | |
| 512 SECItem *nickname, SECItem *publicValue, PRBool isPerm, | |
| 513 PRBool isPrivate, unsigned int keyUsage, void *wincx) | |
| 514 { | |
| 515 return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname, | |
| 516 publicValue, isPerm, isPrivate, keyUsage, NULL, wincx); | |
| 517 | |
| 518 } | |
| 519 | |
| 520 SECItem * | |
| 521 PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx) | |
| 522 { | |
| 523 SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx); | |
| 524 SECItem *derPKI; | |
| 525 | |
| 526 if (!pki) { | |
| 527 return NULL; | |
| 528 } | |
| 529 derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki, | |
| 530 SECKEY_PrivateKeyInfoTemplate); | |
| 531 SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); | |
| 532 return derPKI; | |
| 533 } | |
| 534 | |
| 535 static PRBool | |
| 536 ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, | |
| 537 PLArenaPool *arena, SECItem *output) | |
| 538 { | |
| 539 SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type, | |
| 540 arena, output); | |
| 541 return rv == SECSuccess; | |
| 542 } | |
| 543 | |
| 544 /* | |
| 545 * The caller is responsible for freeing the return value by passing it to | |
| 546 * SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE). | |
| 547 */ | |
| 548 SECKEYPrivateKeyInfo * | |
| 549 PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx) | |
| 550 { | |
| 551 /* PrivateKeyInfo version (always zero) */ | |
| 552 const unsigned char pkiVersion = 0; | |
| 553 /* RSAPrivateKey version (always zero) */ | |
| 554 const unsigned char rsaVersion = 0; | |
| 555 PLArenaPool *arena = NULL; | |
| 556 SECKEYRawPrivateKey rawKey; | |
| 557 SECKEYPrivateKeyInfo *pki; | |
| 558 SECItem *encoded; | |
| 559 SECStatus rv; | |
| 560 | |
| 561 if (pk->keyType != rsaKey) { | |
| 562 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 563 goto loser; | |
| 564 } | |
| 565 | |
| 566 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 567 if (!arena) { | |
| 568 goto loser; | |
| 569 } | |
| 570 memset(&rawKey, 0, sizeof(rawKey)); | |
| 571 rawKey.keyType = pk->keyType; | |
| 572 rawKey.u.rsa.version.type = siUnsignedInteger; | |
| 573 rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1); | |
| 574 if (!rawKey.u.rsa.version.data) { | |
| 575 goto loser; | |
| 576 } | |
| 577 rawKey.u.rsa.version.data[0] = rsaVersion; | |
| 578 rawKey.u.rsa.version.len = 1; | |
| 579 | |
| 580 /* Read the component attributes of the private key */ | |
| 581 prepare_rsa_priv_key_export_for_asn1(&rawKey); | |
| 582 if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) || | |
| 583 !ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena, | |
| 584 &rawKey.u.rsa.publicExponent) || | |
| 585 !ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena, | |
| 586 &rawKey.u.rsa.privateExponent) || | |
| 587 !ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) || | |
| 588 !ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) || | |
| 589 !ReadAttribute(pk, CKA_EXPONENT_1, arena, | |
| 590 &rawKey.u.rsa.exponent1) || | |
| 591 !ReadAttribute(pk, CKA_EXPONENT_2, arena, | |
| 592 &rawKey.u.rsa.exponent2) || | |
| 593 !ReadAttribute(pk, CKA_COEFFICIENT, arena, | |
| 594 &rawKey.u.rsa.coefficient)) { | |
| 595 goto loser; | |
| 596 } | |
| 597 | |
| 598 pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo); | |
| 599 if (!pki) { | |
| 600 goto loser; | |
| 601 } | |
| 602 encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey, | |
| 603 SECKEY_RSAPrivateKeyExportTemplate); | |
| 604 if (!encoded) { | |
| 605 goto loser; | |
| 606 } | |
| 607 rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, | |
| 608 SEC_OID_PKCS1_RSA_ENCRYPTION, NULL); | |
| 609 if (rv != SECSuccess) { | |
| 610 goto loser; | |
| 611 } | |
| 612 pki->version.type = siUnsignedInteger; | |
| 613 pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1); | |
| 614 if (!pki->version.data) { | |
| 615 goto loser; | |
| 616 } | |
| 617 pki->version.data[0] = pkiVersion; | |
| 618 pki->version.len = 1; | |
| 619 pki->arena = arena; | |
| 620 | |
| 621 return pki; | |
| 622 | |
| 623 loser: | |
| 624 if (arena) { | |
| 625 PORT_FreeArena(arena, PR_TRUE); | |
| 626 } | |
| 627 return NULL; | |
| 628 } | |
| OLD | NEW |