1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11pk12.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,628 @@ 1.4 + 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +/* 1.9 + * This file PKCS #12 fuctions that should really be moved to the 1.10 + * PKCS #12 directory, however we can't do that in a point release 1.11 + * because that will break binary compatibility, so we keep them here for now. 1.12 + */ 1.13 + 1.14 +#include "seccomon.h" 1.15 +#include "secmod.h" 1.16 +#include "secmodi.h" 1.17 +#include "pkcs11.h" 1.18 +#include "pk11func.h" 1.19 +#include "secitem.h" 1.20 +#include "key.h" 1.21 +#include "secoid.h" 1.22 +#include "secasn1.h" 1.23 +#include "secerr.h" 1.24 +#include "prerror.h" 1.25 + 1.26 + 1.27 + 1.28 +/* These data structures should move to a common .h file shared between the 1.29 + * wrappers and the pkcs 12 code. */ 1.30 + 1.31 +/* 1.32 +** RSA Raw Private Key structures 1.33 +*/ 1.34 + 1.35 +/* member names from PKCS#1, section 7.2 */ 1.36 +struct SECKEYRSAPrivateKeyStr { 1.37 + PLArenaPool * arena; 1.38 + SECItem version; 1.39 + SECItem modulus; 1.40 + SECItem publicExponent; 1.41 + SECItem privateExponent; 1.42 + SECItem prime1; 1.43 + SECItem prime2; 1.44 + SECItem exponent1; 1.45 + SECItem exponent2; 1.46 + SECItem coefficient; 1.47 +}; 1.48 +typedef struct SECKEYRSAPrivateKeyStr SECKEYRSAPrivateKey; 1.49 + 1.50 + 1.51 +/* 1.52 +** DSA Raw Private Key structures 1.53 +*/ 1.54 + 1.55 +struct SECKEYDSAPrivateKeyStr { 1.56 + SECKEYPQGParams params; 1.57 + SECItem privateValue; 1.58 +}; 1.59 +typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey; 1.60 + 1.61 +/* 1.62 +** Diffie-Hellman Raw Private Key structures 1.63 +** Structure member names suggested by PKCS#3. 1.64 +*/ 1.65 +struct SECKEYDHPrivateKeyStr { 1.66 + PLArenaPool * arena; 1.67 + SECItem prime; 1.68 + SECItem base; 1.69 + SECItem privateValue; 1.70 +}; 1.71 +typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey; 1.72 + 1.73 +/* 1.74 +** raw private key object 1.75 +*/ 1.76 +struct SECKEYRawPrivateKeyStr { 1.77 + PLArenaPool *arena; 1.78 + KeyType keyType; 1.79 + union { 1.80 + SECKEYRSAPrivateKey rsa; 1.81 + SECKEYDSAPrivateKey dsa; 1.82 + SECKEYDHPrivateKey dh; 1.83 + } u; 1.84 +}; 1.85 +typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey; 1.86 + 1.87 +SEC_ASN1_MKSUB(SEC_AnyTemplate) 1.88 +SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 1.89 + 1.90 +/* ASN1 Templates for new decoder/encoder */ 1.91 +/* 1.92 + * Attribute value for PKCS8 entries (static?) 1.93 + */ 1.94 +const SEC_ASN1Template SECKEY_AttributeTemplate[] = { 1.95 + { SEC_ASN1_SEQUENCE, 1.96 + 0, NULL, sizeof(SECKEYAttribute) }, 1.97 + { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) }, 1.98 + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(SECKEYAttribute, attrValue), 1.99 + SEC_ASN1_SUB(SEC_AnyTemplate) }, 1.100 + { 0 } 1.101 +}; 1.102 + 1.103 +const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = { 1.104 + { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate }, 1.105 +}; 1.106 + 1.107 +const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = { 1.108 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) }, 1.109 + { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo,version) }, 1.110 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.111 + offsetof(SECKEYPrivateKeyInfo,algorithm), 1.112 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.113 + { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo,privateKey) }, 1.114 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.115 + offsetof(SECKEYPrivateKeyInfo,attributes), 1.116 + SECKEY_SetOfAttributeTemplate }, 1.117 + { 0 } 1.118 +}; 1.119 + 1.120 +const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = { 1.121 + { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate } 1.122 +}; 1.123 + 1.124 +const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = { 1.125 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) }, 1.126 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.version) }, 1.127 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.modulus) }, 1.128 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.publicExponent) }, 1.129 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.privateExponent) }, 1.130 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.prime1) }, 1.131 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.prime2) }, 1.132 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.exponent1) }, 1.133 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.exponent2) }, 1.134 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.coefficient) }, 1.135 + { 0 } 1.136 +}; 1.137 + 1.138 +const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = { 1.139 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dsa.privateValue) }, 1.140 +}; 1.141 + 1.142 +const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = { 1.143 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.privateValue) }, 1.144 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.base) }, 1.145 + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dh.prime) }, 1.146 +}; 1.147 + 1.148 +const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = { 1.149 + { SEC_ASN1_SEQUENCE, 1.150 + 0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) }, 1.151 + { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 1.152 + offsetof(SECKEYEncryptedPrivateKeyInfo,algorithm), 1.153 + SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 1.154 + { SEC_ASN1_OCTET_STRING, 1.155 + offsetof(SECKEYEncryptedPrivateKeyInfo,encryptedData) }, 1.156 + { 0 } 1.157 +}; 1.158 + 1.159 +const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = { 1.160 + { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate } 1.161 +}; 1.162 + 1.163 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate) 1.164 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate) 1.165 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate) 1.166 +SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate) 1.167 + 1.168 +/* 1.169 + * See bugzilla bug 125359 1.170 + * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, 1.171 + * all of the templates above that en/decode into integers must be converted 1.172 + * from ASN.1's signed integer type. This is done by marking either the 1.173 + * source or destination (encoding or decoding, respectively) type as 1.174 + * siUnsignedInteger. 1.175 + */ 1.176 + 1.177 +static void 1.178 +prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) 1.179 +{ 1.180 + key->u.rsa.modulus.type = siUnsignedInteger; 1.181 + key->u.rsa.publicExponent.type = siUnsignedInteger; 1.182 + key->u.rsa.privateExponent.type = siUnsignedInteger; 1.183 + key->u.rsa.prime1.type = siUnsignedInteger; 1.184 + key->u.rsa.prime2.type = siUnsignedInteger; 1.185 + key->u.rsa.exponent1.type = siUnsignedInteger; 1.186 + key->u.rsa.exponent2.type = siUnsignedInteger; 1.187 + key->u.rsa.coefficient.type = siUnsignedInteger; 1.188 +} 1.189 + 1.190 +static void 1.191 +prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) 1.192 +{ 1.193 + key->u.dsa.privateValue.type = siUnsignedInteger; 1.194 + key->u.dsa.params.prime.type = siUnsignedInteger; 1.195 + key->u.dsa.params.subPrime.type = siUnsignedInteger; 1.196 + key->u.dsa.params.base.type = siUnsignedInteger; 1.197 +} 1.198 + 1.199 +static void 1.200 +prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) 1.201 +{ 1.202 + key->u.dh.privateValue.type = siUnsignedInteger; 1.203 + key->u.dh.prime.type = siUnsignedInteger; 1.204 + key->u.dh.base.type = siUnsignedInteger; 1.205 +} 1.206 + 1.207 + 1.208 +SECStatus 1.209 +PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI, 1.210 + SECItem *nickname, SECItem *publicValue, PRBool isPerm, 1.211 + PRBool isPrivate, unsigned int keyUsage, void *wincx) 1.212 +{ 1.213 + return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI, 1.214 + nickname, publicValue, isPerm, isPrivate, keyUsage, NULL, wincx); 1.215 +} 1.216 + 1.217 +SECStatus 1.218 +PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI, 1.219 + SECItem *nickname, SECItem *publicValue, PRBool isPerm, 1.220 + PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey** privk, 1.221 + void *wincx) 1.222 +{ 1.223 + SECKEYPrivateKeyInfo *pki = NULL; 1.224 + PLArenaPool *temparena = NULL; 1.225 + SECStatus rv = SECFailure; 1.226 + 1.227 + temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.228 + if (!temparena) 1.229 + return rv; 1.230 + pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo); 1.231 + if (!pki) { 1.232 + PORT_FreeArena(temparena, PR_FALSE); 1.233 + return rv; 1.234 + } 1.235 + pki->arena = temparena; 1.236 + 1.237 + rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate, 1.238 + derPKI); 1.239 + if( rv != SECSuccess ) { 1.240 + goto finish; 1.241 + } 1.242 + 1.243 + rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname, 1.244 + publicValue, isPerm, isPrivate, keyUsage, privk, wincx); 1.245 + 1.246 +finish: 1.247 + /* this zeroes the key and frees the arena */ 1.248 + SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/); 1.249 + return rv; 1.250 +} 1.251 + 1.252 +SECStatus 1.253 +PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, 1.254 + SECItem *nickname, SECItem *publicValue, PRBool isPerm, 1.255 + PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk, 1.256 + void *wincx) 1.257 +{ 1.258 + CK_BBOOL cktrue = CK_TRUE; 1.259 + CK_BBOOL ckfalse = CK_FALSE; 1.260 + CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; 1.261 + CK_KEY_TYPE keyType = CKK_RSA; 1.262 + CK_OBJECT_HANDLE objectID; 1.263 + CK_ATTRIBUTE theTemplate[20]; 1.264 + int templateCount = 0; 1.265 + SECStatus rv = SECFailure; 1.266 + CK_ATTRIBUTE *attrs; 1.267 + CK_ATTRIBUTE *signedattr = NULL; 1.268 + int signedcount = 0; 1.269 + CK_ATTRIBUTE *ap; 1.270 + SECItem *ck_id = NULL; 1.271 + 1.272 + attrs = theTemplate; 1.273 + 1.274 + 1.275 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; 1.276 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; 1.277 + PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, 1.278 + sizeof(CK_BBOOL) ); attrs++; 1.279 + PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, 1.280 + sizeof(CK_BBOOL) ); attrs++; 1.281 + PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse, 1.282 + sizeof(CK_BBOOL) ); attrs++; 1.283 + 1.284 + switch (lpk->keyType) { 1.285 + case rsaKey: 1.286 + keyType = CKK_RSA; 1.287 + PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? 1.288 + &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; 1.289 + PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? 1.290 + &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; 1.291 + PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? 1.292 + &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; 1.293 + PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, 1.294 + (keyUsage & KU_DIGITAL_SIGNATURE) ? 1.295 + &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; 1.296 + ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus); 1.297 + if (ck_id == NULL) { 1.298 + goto loser; 1.299 + } 1.300 + PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; 1.301 + if (nickname) { 1.302 + PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; 1.303 + } 1.304 + signedattr = attrs; 1.305 + PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data, 1.306 + lpk->u.rsa.modulus.len); attrs++; 1.307 + PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 1.308 + lpk->u.rsa.publicExponent.data, 1.309 + lpk->u.rsa.publicExponent.len); attrs++; 1.310 + PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, 1.311 + lpk->u.rsa.privateExponent.data, 1.312 + lpk->u.rsa.privateExponent.len); attrs++; 1.313 + PK11_SETATTRS(attrs, CKA_PRIME_1, 1.314 + lpk->u.rsa.prime1.data, 1.315 + lpk->u.rsa.prime1.len); attrs++; 1.316 + PK11_SETATTRS(attrs, CKA_PRIME_2, 1.317 + lpk->u.rsa.prime2.data, 1.318 + lpk->u.rsa.prime2.len); attrs++; 1.319 + PK11_SETATTRS(attrs, CKA_EXPONENT_1, 1.320 + lpk->u.rsa.exponent1.data, 1.321 + lpk->u.rsa.exponent1.len); attrs++; 1.322 + PK11_SETATTRS(attrs, CKA_EXPONENT_2, 1.323 + lpk->u.rsa.exponent2.data, 1.324 + lpk->u.rsa.exponent2.len); attrs++; 1.325 + PK11_SETATTRS(attrs, CKA_COEFFICIENT, 1.326 + lpk->u.rsa.coefficient.data, 1.327 + lpk->u.rsa.coefficient.len); attrs++; 1.328 + break; 1.329 + case dsaKey: 1.330 + keyType = CKK_DSA; 1.331 + /* To make our intenal PKCS #11 module work correctly with 1.332 + * our database, we need to pass in the public key value for 1.333 + * this dsa key. We have a netscape only CKA_ value to do this. 1.334 + * Only send it to internal slots */ 1.335 + if( publicValue == NULL ) { 1.336 + goto loser; 1.337 + } 1.338 + if (PK11_IsInternal(slot)) { 1.339 + PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, 1.340 + publicValue->data, publicValue->len); attrs++; 1.341 + } 1.342 + PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++; 1.343 + PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); attrs++; 1.344 + if(nickname) { 1.345 + PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); 1.346 + attrs++; 1.347 + } 1.348 + ck_id = PK11_MakeIDFromPubKey(publicValue); 1.349 + if (ck_id == NULL) { 1.350 + goto loser; 1.351 + } 1.352 + PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; 1.353 + signedattr = attrs; 1.354 + PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data, 1.355 + lpk->u.dsa.params.prime.len); attrs++; 1.356 + PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data, 1.357 + lpk->u.dsa.params.subPrime.len); attrs++; 1.358 + PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data, 1.359 + lpk->u.dsa.params.base.len); attrs++; 1.360 + PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data, 1.361 + lpk->u.dsa.privateValue.len); attrs++; 1.362 + break; 1.363 + case dhKey: 1.364 + keyType = CKK_DH; 1.365 + /* To make our intenal PKCS #11 module work correctly with 1.366 + * our database, we need to pass in the public key value for 1.367 + * this dh key. We have a netscape only CKA_ value to do this. 1.368 + * Only send it to internal slots */ 1.369 + if (PK11_IsInternal(slot)) { 1.370 + PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, 1.371 + publicValue->data, publicValue->len); attrs++; 1.372 + } 1.373 + PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++; 1.374 + if(nickname) { 1.375 + PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); 1.376 + attrs++; 1.377 + } 1.378 + ck_id = PK11_MakeIDFromPubKey(publicValue); 1.379 + if (ck_id == NULL) { 1.380 + goto loser; 1.381 + } 1.382 + PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; 1.383 + signedattr = attrs; 1.384 + PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data, 1.385 + lpk->u.dh.prime.len); attrs++; 1.386 + PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data, 1.387 + lpk->u.dh.base.len); attrs++; 1.388 + PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data, 1.389 + lpk->u.dh.privateValue.len); attrs++; 1.390 + break; 1.391 + /* what about fortezza??? */ 1.392 + default: 1.393 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.394 + goto loser; 1.395 + } 1.396 + templateCount = attrs - theTemplate; 1.397 + PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)); 1.398 + PORT_Assert(signedattr != NULL); 1.399 + signedcount = attrs - signedattr; 1.400 + 1.401 + for (ap=signedattr; signedcount; ap++, signedcount--) { 1.402 + pk11_SignedToUnsigned(ap); 1.403 + } 1.404 + 1.405 + rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, 1.406 + theTemplate, templateCount, isPerm, &objectID); 1.407 + 1.408 + /* create and return a SECKEYPrivateKey */ 1.409 + if( rv == SECSuccess && privk != NULL) { 1.410 + *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx); 1.411 + if( *privk == NULL ) { 1.412 + rv = SECFailure; 1.413 + } 1.414 + } 1.415 +loser: 1.416 + if (ck_id) { 1.417 + SECITEM_ZfreeItem(ck_id, PR_TRUE); 1.418 + } 1.419 + return rv; 1.420 +} 1.421 + 1.422 +SECStatus 1.423 +PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, 1.424 + SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue, 1.425 + PRBool isPerm, PRBool isPrivate, unsigned int keyUsage, 1.426 + SECKEYPrivateKey **privk, void *wincx) 1.427 +{ 1.428 + CK_KEY_TYPE keyType = CKK_RSA; 1.429 + SECStatus rv = SECFailure; 1.430 + SECKEYRawPrivateKey *lpk = NULL; 1.431 + const SEC_ASN1Template *keyTemplate, *paramTemplate; 1.432 + void *paramDest = NULL; 1.433 + PLArenaPool *arena = NULL; 1.434 + 1.435 + arena = PORT_NewArena(2048); 1.436 + if(!arena) { 1.437 + return SECFailure; 1.438 + } 1.439 + 1.440 + /* need to change this to use RSA/DSA keys */ 1.441 + lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena, 1.442 + sizeof(SECKEYRawPrivateKey)); 1.443 + if(lpk == NULL) { 1.444 + goto loser; 1.445 + } 1.446 + lpk->arena = arena; 1.447 + 1.448 + switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { 1.449 + case SEC_OID_PKCS1_RSA_ENCRYPTION: 1.450 + prepare_rsa_priv_key_export_for_asn1(lpk); 1.451 + keyTemplate = SECKEY_RSAPrivateKeyExportTemplate; 1.452 + paramTemplate = NULL; 1.453 + paramDest = NULL; 1.454 + lpk->keyType = rsaKey; 1.455 + keyType = CKK_RSA; 1.456 + break; 1.457 + case SEC_OID_ANSIX9_DSA_SIGNATURE: 1.458 + prepare_dsa_priv_key_export_for_asn1(lpk); 1.459 + keyTemplate = SECKEY_DSAPrivateKeyExportTemplate; 1.460 + paramTemplate = SECKEY_PQGParamsTemplate; 1.461 + paramDest = &(lpk->u.dsa.params); 1.462 + lpk->keyType = dsaKey; 1.463 + keyType = CKK_DSA; 1.464 + break; 1.465 + case SEC_OID_X942_DIFFIE_HELMAN_KEY: 1.466 + if(!publicValue) { 1.467 + goto loser; 1.468 + } 1.469 + prepare_dh_priv_key_export_for_asn1(lpk); 1.470 + keyTemplate = SECKEY_DHPrivateKeyExportTemplate; 1.471 + paramTemplate = NULL; 1.472 + paramDest = NULL; 1.473 + lpk->keyType = dhKey; 1.474 + keyType = CKK_DH; 1.475 + break; 1.476 + 1.477 + default: 1.478 + keyTemplate = NULL; 1.479 + paramTemplate = NULL; 1.480 + paramDest = NULL; 1.481 + break; 1.482 + } 1.483 + 1.484 + if(!keyTemplate) { 1.485 + goto loser; 1.486 + } 1.487 + 1.488 + /* decode the private key and any algorithm parameters */ 1.489 + rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey); 1.490 + if(rv != SECSuccess) { 1.491 + goto loser; 1.492 + } 1.493 + if(paramDest && paramTemplate) { 1.494 + rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate, 1.495 + &(pki->algorithm.parameters)); 1.496 + if(rv != SECSuccess) { 1.497 + goto loser; 1.498 + } 1.499 + } 1.500 + 1.501 + rv = PK11_ImportAndReturnPrivateKey(slot,lpk,nickname,publicValue, isPerm, 1.502 + isPrivate, keyUsage, privk, wincx); 1.503 + 1.504 + 1.505 +loser: 1.506 + if (arena != NULL) { 1.507 + PORT_FreeArena(arena, PR_TRUE); 1.508 + } 1.509 + 1.510 + return rv; 1.511 +} 1.512 + 1.513 +SECStatus 1.514 +PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki, 1.515 + SECItem *nickname, SECItem *publicValue, PRBool isPerm, 1.516 + PRBool isPrivate, unsigned int keyUsage, void *wincx) 1.517 +{ 1.518 + return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname, 1.519 + publicValue, isPerm, isPrivate, keyUsage, NULL, wincx); 1.520 + 1.521 +} 1.522 + 1.523 +SECItem * 1.524 +PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx) 1.525 +{ 1.526 + SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx); 1.527 + SECItem *derPKI; 1.528 + 1.529 + if (!pki) { 1.530 + return NULL; 1.531 + } 1.532 + derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki, 1.533 + SECKEY_PrivateKeyInfoTemplate); 1.534 + SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); 1.535 + return derPKI; 1.536 +} 1.537 + 1.538 +static PRBool 1.539 +ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, 1.540 + PLArenaPool *arena, SECItem *output) 1.541 +{ 1.542 + SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type, 1.543 + arena, output); 1.544 + return rv == SECSuccess; 1.545 +} 1.546 + 1.547 +/* 1.548 + * The caller is responsible for freeing the return value by passing it to 1.549 + * SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE). 1.550 + */ 1.551 +SECKEYPrivateKeyInfo * 1.552 +PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx) 1.553 +{ 1.554 + /* PrivateKeyInfo version (always zero) */ 1.555 + const unsigned char pkiVersion = 0; 1.556 + /* RSAPrivateKey version (always zero) */ 1.557 + const unsigned char rsaVersion = 0; 1.558 + PLArenaPool *arena = NULL; 1.559 + SECKEYRawPrivateKey rawKey; 1.560 + SECKEYPrivateKeyInfo *pki; 1.561 + SECItem *encoded; 1.562 + SECStatus rv; 1.563 + 1.564 + if (pk->keyType != rsaKey) { 1.565 + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); 1.566 + goto loser; 1.567 + } 1.568 + 1.569 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.570 + if (!arena) { 1.571 + goto loser; 1.572 + } 1.573 + memset(&rawKey, 0, sizeof(rawKey)); 1.574 + rawKey.keyType = pk->keyType; 1.575 + rawKey.u.rsa.version.type = siUnsignedInteger; 1.576 + rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1); 1.577 + if (!rawKey.u.rsa.version.data) { 1.578 + goto loser; 1.579 + } 1.580 + rawKey.u.rsa.version.data[0] = rsaVersion; 1.581 + rawKey.u.rsa.version.len = 1; 1.582 + 1.583 + /* Read the component attributes of the private key */ 1.584 + prepare_rsa_priv_key_export_for_asn1(&rawKey); 1.585 + if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) || 1.586 + !ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena, 1.587 + &rawKey.u.rsa.publicExponent) || 1.588 + !ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena, 1.589 + &rawKey.u.rsa.privateExponent) || 1.590 + !ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) || 1.591 + !ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) || 1.592 + !ReadAttribute(pk, CKA_EXPONENT_1, arena, 1.593 + &rawKey.u.rsa.exponent1) || 1.594 + !ReadAttribute(pk, CKA_EXPONENT_2, arena, 1.595 + &rawKey.u.rsa.exponent2) || 1.596 + !ReadAttribute(pk, CKA_COEFFICIENT, arena, 1.597 + &rawKey.u.rsa.coefficient)) { 1.598 + goto loser; 1.599 + } 1.600 + 1.601 + pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo); 1.602 + if (!pki) { 1.603 + goto loser; 1.604 + } 1.605 + encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey, 1.606 + SECKEY_RSAPrivateKeyExportTemplate); 1.607 + if (!encoded) { 1.608 + goto loser; 1.609 + } 1.610 + rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, 1.611 + SEC_OID_PKCS1_RSA_ENCRYPTION, NULL); 1.612 + if (rv != SECSuccess) { 1.613 + goto loser; 1.614 + } 1.615 + pki->version.type = siUnsignedInteger; 1.616 + pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1); 1.617 + if (!pki->version.data) { 1.618 + goto loser; 1.619 + } 1.620 + pki->version.data[0] = pkiVersion; 1.621 + pki->version.len = 1; 1.622 + pki->arena = arena; 1.623 + 1.624 + return pki; 1.625 + 1.626 +loser: 1.627 + if (arena) { 1.628 + PORT_FreeArena(arena, PR_TRUE); 1.629 + } 1.630 + return NULL; 1.631 +}