security/nss/lib/pk11wrap/pk11pk12.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    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"
    25 /* These data structures should move to a common .h file shared between the
    26  * wrappers and the pkcs 12 code. */
    28 /*
    29 ** RSA Raw Private Key structures
    30 */
    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;
    48 /*
    49 ** DSA Raw Private Key structures
    50 */
    52 struct SECKEYDSAPrivateKeyStr {
    53     SECKEYPQGParams params;
    54     SECItem privateValue;
    55 };
    56 typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey;
    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;
    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;
    84 SEC_ASN1_MKSUB(SEC_AnyTemplate)
    85 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
    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 };
   100 const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = {
   101     { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },
   102 };
   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 };
   117 const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = {
   118     { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }
   119 };
   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 };
   135 const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = {
   136     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.dsa.privateValue) },
   137 };
   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 };
   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 };
   156 const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
   157         { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
   158 };
   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)
   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  */
   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 }
   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 }
   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 }
   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 }
   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;
   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;
   234     rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
   235 		derPKI);
   236     if( rv != SECSuccess ) {
   237 	goto finish;
   238     }
   240     rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
   241 		publicValue, isPerm, isPrivate, keyUsage, privk, wincx);
   243 finish:
   244     /* this zeroes the key and frees the arena */
   245     SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
   246     return rv;
   247 }
   249 SECStatus
   250 PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, 
   251 	SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
   252 	PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
   253 	void *wincx) 
   254 {
   255     CK_BBOOL cktrue = CK_TRUE;
   256     CK_BBOOL ckfalse = CK_FALSE;
   257     CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
   258     CK_KEY_TYPE keyType = CKK_RSA;
   259     CK_OBJECT_HANDLE objectID;
   260     CK_ATTRIBUTE theTemplate[20];
   261     int templateCount = 0;
   262     SECStatus rv = SECFailure;
   263     CK_ATTRIBUTE *attrs;
   264     CK_ATTRIBUTE *signedattr = NULL;
   265     int signedcount = 0;
   266     CK_ATTRIBUTE *ap;
   267     SECItem *ck_id = NULL;
   269     attrs = theTemplate;
   272     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
   273     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
   274     PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, 
   275 						sizeof(CK_BBOOL) ); attrs++;
   276     PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, 
   277 						sizeof(CK_BBOOL) ); attrs++;
   278     PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
   279 						 sizeof(CK_BBOOL) ); attrs++;
   281     switch (lpk->keyType) {
   282     case rsaKey:
   283 	    keyType = CKK_RSA;
   284 	    PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ?
   285 				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
   286 	    PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ?
   287 				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
   288 	    PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? 
   289 				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
   290 	    PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, 
   291 				(keyUsage & KU_DIGITAL_SIGNATURE) ? 
   292 				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;
   293 	    ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
   294 	    if (ck_id == NULL) {
   295 		goto loser;
   296 	    }
   297 	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
   298 	    if (nickname) {
   299 		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; 
   300 	    } 
   301 	    signedattr = attrs;
   302 	    PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
   303 						lpk->u.rsa.modulus.len); attrs++;
   304 	    PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
   305 	     			lpk->u.rsa.publicExponent.data,
   306 				lpk->u.rsa.publicExponent.len); attrs++;
   307 	    PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, 
   308 	     			lpk->u.rsa.privateExponent.data,
   309 				lpk->u.rsa.privateExponent.len); attrs++;
   310 	    PK11_SETATTRS(attrs, CKA_PRIME_1, 
   311 	     			lpk->u.rsa.prime1.data,
   312 				lpk->u.rsa.prime1.len); attrs++;
   313 	    PK11_SETATTRS(attrs, CKA_PRIME_2, 
   314 	     			lpk->u.rsa.prime2.data,
   315 				lpk->u.rsa.prime2.len); attrs++;
   316 	    PK11_SETATTRS(attrs, CKA_EXPONENT_1, 
   317 	     			lpk->u.rsa.exponent1.data,
   318 				lpk->u.rsa.exponent1.len); attrs++;
   319 	    PK11_SETATTRS(attrs, CKA_EXPONENT_2, 
   320 	     			lpk->u.rsa.exponent2.data,
   321 				lpk->u.rsa.exponent2.len); attrs++;
   322 	    PK11_SETATTRS(attrs, CKA_COEFFICIENT, 
   323 	     			lpk->u.rsa.coefficient.data,
   324 				lpk->u.rsa.coefficient.len); attrs++;
   325 	    break;
   326     case dsaKey:
   327 	    keyType = CKK_DSA;
   328 	    /* To make our intenal PKCS #11 module work correctly with 
   329 	     * our database, we need to pass in the public key value for 
   330 	     * this dsa key. We have a netscape only CKA_ value to do this.
   331 	     * Only send it to internal slots */
   332 	    if( publicValue == NULL ) {
   333 		goto loser;
   334 	    }
   335 	    if (PK11_IsInternal(slot)) {
   336 	        PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
   337 				publicValue->data, publicValue->len); attrs++;
   338 	    }
   339 	    PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++;
   340 	    PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); attrs++;
   341 	    if(nickname) {
   342 		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
   343 		attrs++; 
   344 	    } 
   345 	    ck_id = PK11_MakeIDFromPubKey(publicValue);
   346 	    if (ck_id == NULL) {
   347 		goto loser;
   348 	    }
   349 	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
   350 	    signedattr = attrs;
   351 	    PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dsa.params.prime.data,
   352 				lpk->u.dsa.params.prime.len); attrs++;
   353 	    PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data,
   354 				lpk->u.dsa.params.subPrime.len); attrs++;
   355 	    PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dsa.params.base.data,
   356 					lpk->u.dsa.params.base.len); attrs++;
   357 	    PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dsa.privateValue.data, 
   358 					lpk->u.dsa.privateValue.len); attrs++;
   359 	    break;
   360      case dhKey:
   361 	    keyType = CKK_DH;
   362 	    /* To make our intenal PKCS #11 module work correctly with 
   363 	     * our database, we need to pass in the public key value for 
   364 	     * this dh key. We have a netscape only CKA_ value to do this.
   365 	     * Only send it to internal slots */
   366 	    if (PK11_IsInternal(slot)) {
   367 	        PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
   368 				publicValue->data, publicValue->len); attrs++;
   369 	    }
   370 	    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++;
   371 	    if(nickname) {
   372 		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
   373 		attrs++; 
   374 	    } 
   375 	    ck_id = PK11_MakeIDFromPubKey(publicValue);
   376 	    if (ck_id == NULL) {
   377 		goto loser;
   378 	    }
   379 	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;
   380 	    signedattr = attrs;
   381 	    PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dh.prime.data,
   382 				lpk->u.dh.prime.len); attrs++;
   383 	    PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dh.base.data,
   384 					lpk->u.dh.base.len); attrs++;
   385 	    PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dh.privateValue.data, 
   386 					lpk->u.dh.privateValue.len); attrs++;
   387 	    break;
   388 	/* what about fortezza??? */
   389     default:
   390 	    PORT_SetError(SEC_ERROR_BAD_KEY);
   391 	    goto loser;
   392     }
   393     templateCount = attrs - theTemplate;
   394     PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE));
   395     PORT_Assert(signedattr != NULL);
   396     signedcount = attrs - signedattr;
   398     for (ap=signedattr; signedcount; ap++, signedcount--) {
   399 	pk11_SignedToUnsigned(ap);
   400     }
   402     rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,
   403 			theTemplate, templateCount, isPerm, &objectID);
   405     /* create and return a SECKEYPrivateKey */
   406     if( rv == SECSuccess && privk != NULL) {
   407 	*privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
   408 	if( *privk == NULL ) {
   409 	    rv = SECFailure;
   410 	}
   411     }
   412 loser:
   413     if (ck_id) {
   414 	SECITEM_ZfreeItem(ck_id, PR_TRUE);
   415     }
   416     return rv;
   417 }
   419 SECStatus
   420 PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
   421 	SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
   422 	PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
   423 	SECKEYPrivateKey **privk, void *wincx) 
   424 {
   425     CK_KEY_TYPE keyType = CKK_RSA;
   426     SECStatus rv = SECFailure;
   427     SECKEYRawPrivateKey *lpk = NULL;
   428     const SEC_ASN1Template *keyTemplate, *paramTemplate;
   429     void *paramDest = NULL;
   430     PLArenaPool *arena = NULL;
   432     arena = PORT_NewArena(2048);
   433     if(!arena) {
   434 	return SECFailure;
   435     }
   437     /* need to change this to use RSA/DSA keys */
   438     lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
   439 						  sizeof(SECKEYRawPrivateKey));
   440     if(lpk == NULL) {
   441 	goto loser;
   442     }
   443     lpk->arena = arena;
   445     switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
   446 	case SEC_OID_PKCS1_RSA_ENCRYPTION:
   447 	    prepare_rsa_priv_key_export_for_asn1(lpk);
   448 	    keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
   449 	    paramTemplate = NULL;
   450 	    paramDest = NULL;
   451 	    lpk->keyType = rsaKey;
   452 	    keyType = CKK_RSA;
   453 	    break;
   454 	case SEC_OID_ANSIX9_DSA_SIGNATURE:
   455 	    prepare_dsa_priv_key_export_for_asn1(lpk);
   456 	    keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
   457 	    paramTemplate = SECKEY_PQGParamsTemplate;
   458 	    paramDest = &(lpk->u.dsa.params);
   459 	    lpk->keyType = dsaKey;
   460 	    keyType = CKK_DSA;
   461 	    break;
   462 	case SEC_OID_X942_DIFFIE_HELMAN_KEY:
   463 	    if(!publicValue) {
   464 		goto loser;
   465 	    }
   466 	    prepare_dh_priv_key_export_for_asn1(lpk);
   467 	    keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
   468 	    paramTemplate = NULL;
   469 	    paramDest = NULL;
   470 	    lpk->keyType = dhKey;
   471 	    keyType = CKK_DH;
   472 	    break;
   474 	default:
   475 	    keyTemplate   = NULL;
   476 	    paramTemplate = NULL;
   477 	    paramDest     = NULL;
   478 	    break;
   479     }
   481     if(!keyTemplate) {
   482 	goto loser;
   483     }
   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     }
   498     rv = PK11_ImportAndReturnPrivateKey(slot,lpk,nickname,publicValue, isPerm, 
   499 	isPrivate,  keyUsage, privk, wincx);
   502 loser:
   503     if (arena != NULL) {
   504 	PORT_FreeArena(arena, PR_TRUE);
   505     }
   507     return rv;
   508 }
   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);
   518 }
   520 SECItem *
   521 PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx)
   522 {
   523     SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx);
   524     SECItem *derPKI;
   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 }
   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 }
   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;
   561     if (pk->keyType != rsaKey) {
   562         PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   563         goto loser;
   564     }
   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;
   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     }
   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;
   621     return pki;
   623 loser:
   624     if (arena) {
   625         PORT_FreeArena(arena, PR_TRUE);
   626     }
   627     return NULL;
   628 }

mercurial