security/nss/lib/pk11wrap/pk11pk12.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial