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 "secmodti.h"
15 #include "secmodt.h"
16 #include "pkcs11.h"
17 #include "pk11func.h"
18 #include "secitem.h"
19 #include "keyhi.h"
20 #include "secoid.h"
21 #include "secasn1.h"
22 #include "secerr.h"
23 #include "prerror.h"
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 ** DSA Raw Private Key structures
49 */
50 
51 struct SECKEYDSAPrivateKeyStr {
52     SECKEYPQGParams params;
53     SECItem privateValue;
54 };
55 typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey;
56 
57 /*
58 ** Diffie-Hellman Raw Private Key structures
59 ** Structure member names suggested by PKCS#3.
60 */
61 struct SECKEYDHPrivateKeyStr {
62     PLArenaPool *arena;
63     SECItem prime;
64     SECItem base;
65     SECItem privateValue;
66 };
67 typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey;
68 
69 /*
70 ** Elliptic Curve Private Key structures
71 ** <https://tools.ietf.org/html/rfc5915#section-3>
72 */
73 struct SECKEYECPrivateKeyStr {
74     PLArenaPool *arena;
75     SECItem version;
76     SECItem curveOID;    /* optional/ignored */
77     SECItem publicValue; /* required (for now) */
78     SECItem privateValue;
79 };
80 typedef struct SECKEYECPrivateKeyStr SECKEYECPrivateKey;
81 
82 /*
83 ** raw private key object
84 */
85 struct SECKEYRawPrivateKeyStr {
86     PLArenaPool *arena;
87     KeyType keyType;
88     union {
89         SECKEYRSAPrivateKey rsa;
90         SECKEYDSAPrivateKey dsa;
91         SECKEYDHPrivateKey dh;
92         SECKEYECPrivateKey ec;
93     } u;
94 };
95 typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey;
96 
97 SEC_ASN1_MKSUB(SEC_AnyTemplate)
98 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
99 
100 /* ASN1 Templates for new decoder/encoder */
101 /*
102  * Attribute value for PKCS8 entries (static?)
103  */
104 const SEC_ASN1Template SECKEY_AttributeTemplate[] = {
105     { SEC_ASN1_SEQUENCE,
106       0, NULL, sizeof(SECKEYAttribute) },
107     { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) },
108     { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(SECKEYAttribute, attrValue),
109       SEC_ASN1_SUB(SEC_AnyTemplate) },
110     { 0 }
111 };
112 
113 const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = {
114     { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },
115 };
116 
117 const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = {
118     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) },
119     { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo, version) },
120     { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
121       offsetof(SECKEYPrivateKeyInfo, algorithm),
122       SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
123     { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo, privateKey) },
124     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
125       offsetof(SECKEYPrivateKeyInfo, attributes),
126       SECKEY_SetOfAttributeTemplate },
127     { 0 }
128 };
129 
130 const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = {
131     { SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }
132 };
133 
134 const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = {
135     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) },
136     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.version) },
137     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.modulus) },
138     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.publicExponent) },
139     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.privateExponent) },
140     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.prime1) },
141     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.prime2) },
142     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.exponent1) },
143     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.exponent2) },
144     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.coefficient) },
145     { 0 }
146 };
147 
148 const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = {
149     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dsa.privateValue) },
150 };
151 
152 const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = {
153     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.privateValue) },
154     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.base) },
155     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.prime) },
156 };
157 
158 SEC_ASN1_MKSUB(SEC_BitStringTemplate)
159 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
160 
161 const SEC_ASN1Template SECKEY_ECPrivateKeyExportTemplate[] = {
162     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) },
163     { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.ec.version) },
164     { SEC_ASN1_OCTET_STRING,
165       offsetof(SECKEYRawPrivateKey, u.ec.privateValue) },
166     /* This value will always be ignored. u.ec.curveOID will always be
167      * overriden with the outer AlgorithmID.parameters. */
168     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
169           SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
170           SEC_ASN1_XTRN | 0,
171       offsetof(SECKEYRawPrivateKey, u.ec.curveOID),
172       SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
173     /* The public value is optional per RFC, but required in NSS. We
174      * can't do scalar mult on ECs to get a raw point with PK11 APIs. */
175     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
176           SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
177           SEC_ASN1_XTRN | 1,
178       offsetof(SECKEYRawPrivateKey, u.ec.publicValue),
179       SEC_ASN1_SUB(SEC_BitStringTemplate) },
180     { 0 }
181 };
182 
183 const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
184     { SEC_ASN1_SEQUENCE,
185       0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) },
186     { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
187       offsetof(SECKEYEncryptedPrivateKeyInfo, algorithm),
188       SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
189     { SEC_ASN1_OCTET_STRING,
190       offsetof(SECKEYEncryptedPrivateKeyInfo, encryptedData) },
191     { 0 }
192 };
193 
194 const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
195     { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
196 };
197 
198 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)199 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
200 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
201 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)
202 
203 /*
204  * See bugzilla bug 125359
205  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
206  * all of the templates above that en/decode into integers must be converted
207  * from ASN.1's signed integer type.  This is done by marking either the
208  * source or destination (encoding or decoding, respectively) type as
209  * siUnsignedInteger.
210  */
211 
212 static void
213 prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
214 {
215     key->u.rsa.modulus.type = siUnsignedInteger;
216     key->u.rsa.publicExponent.type = siUnsignedInteger;
217     key->u.rsa.privateExponent.type = siUnsignedInteger;
218     key->u.rsa.prime1.type = siUnsignedInteger;
219     key->u.rsa.prime2.type = siUnsignedInteger;
220     key->u.rsa.exponent1.type = siUnsignedInteger;
221     key->u.rsa.exponent2.type = siUnsignedInteger;
222     key->u.rsa.coefficient.type = siUnsignedInteger;
223 }
224 
225 static void
prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey * key)226 prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
227 {
228     key->u.dsa.privateValue.type = siUnsignedInteger;
229     key->u.dsa.params.prime.type = siUnsignedInteger;
230     key->u.dsa.params.subPrime.type = siUnsignedInteger;
231     key->u.dsa.params.base.type = siUnsignedInteger;
232 }
233 
234 static void
prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey * key)235 prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
236 {
237     key->u.dh.privateValue.type = siUnsignedInteger;
238     key->u.dh.prime.type = siUnsignedInteger;
239     key->u.dh.base.type = siUnsignedInteger;
240 }
241 
242 static void
prepare_ec_priv_key_export_for_asn1(SECKEYRawPrivateKey * key)243 prepare_ec_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
244 {
245     key->u.ec.version.type = siUnsignedInteger;
246     key->u.ec.curveOID.type = siUnsignedInteger;
247     key->u.ec.privateValue.type = siUnsignedInteger;
248     key->u.ec.publicValue.type = siUnsignedInteger;
249 }
250 
251 SECStatus
PK11_ImportDERPrivateKeyInfo(PK11SlotInfo * slot,SECItem * derPKI,SECItem * nickname,SECItem * publicValue,PRBool isPerm,PRBool isPrivate,unsigned int keyUsage,void * wincx)252 PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI,
253                              SECItem *nickname, SECItem *publicValue, PRBool isPerm,
254                              PRBool isPrivate, unsigned int keyUsage, void *wincx)
255 {
256     return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI,
257                                                     nickname, publicValue,
258                                                     isPerm, isPrivate, keyUsage,
259                                                     NULL, wincx);
260 }
261 
262 SECStatus
PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo * slot,SECItem * derPKI,SECItem * nickname,SECItem * publicValue,PRBool isPerm,PRBool isPrivate,unsigned int keyUsage,SECKEYPrivateKey ** privk,void * wincx)263 PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI,
264                                          SECItem *nickname, SECItem *publicValue,
265                                          PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
266                                          SECKEYPrivateKey **privk, void *wincx)
267 {
268     SECKEYPrivateKeyInfo *pki = NULL;
269     PLArenaPool *temparena = NULL;
270     SECStatus rv = SECFailure;
271 
272     temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
273     if (!temparena)
274         return rv;
275     pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo);
276     if (!pki) {
277         PORT_FreeArena(temparena, PR_FALSE);
278         return rv;
279     }
280     pki->arena = temparena;
281 
282     rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
283                             derPKI);
284     if (rv != SECSuccess) {
285         /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the
286          * validity of the data in pki. The best we can do is free the arena
287          * and return. */
288         PORT_FreeArena(temparena, PR_TRUE);
289         return rv;
290     }
291     if (pki->privateKey.data == NULL) {
292         /* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey
293          * is a zero-length octet string, free the arena and return a failure
294          * to avoid trying to zero the corresponding SECItem in
295          * SECKEY_DestroyPrivateKeyInfo(). */
296         PORT_FreeArena(temparena, PR_TRUE);
297         PORT_SetError(SEC_ERROR_BAD_KEY);
298         return SECFailure;
299     }
300 
301     rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
302                                                publicValue, isPerm, isPrivate,
303                                                keyUsage, privk, wincx);
304 
305     /* this zeroes the key and frees the arena */
306     SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
307     return rv;
308 }
309 
310 SECStatus
PK11_ImportAndReturnPrivateKey(PK11SlotInfo * slot,SECKEYRawPrivateKey * lpk,SECItem * nickname,SECItem * publicValue,PRBool isPerm,PRBool isPrivate,unsigned int keyUsage,SECKEYPrivateKey ** privk,void * wincx)311 PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
312                                SECItem *nickname, SECItem *publicValue, PRBool isPerm,
313                                PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
314                                void *wincx)
315 {
316     CK_BBOOL cktrue = CK_TRUE;
317     CK_BBOOL ckfalse = CK_FALSE;
318     CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
319     CK_KEY_TYPE keyType = CKK_RSA;
320     CK_OBJECT_HANDLE objectID;
321     CK_ATTRIBUTE theTemplate[20];
322     int templateCount = 0;
323     SECStatus rv = SECFailure;
324     CK_ATTRIBUTE *attrs;
325     CK_ATTRIBUTE *signedattr = NULL;
326     int signedcount = 0;
327     CK_ATTRIBUTE *ap;
328     SECItem *ck_id = NULL;
329 
330     attrs = theTemplate;
331 
332     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
333     attrs++;
334     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
335     attrs++;
336     PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse,
337                   sizeof(CK_BBOOL));
338     attrs++;
339     PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse,
340                   sizeof(CK_BBOOL));
341     attrs++;
342     PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
343                   sizeof(CK_BBOOL));
344     attrs++;
345 
346     switch (lpk->keyType) {
347         case rsaKey:
348             keyType = CKK_RSA;
349             PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue : &ckfalse,
350                           sizeof(CK_BBOOL));
351             attrs++;
352             PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue : &ckfalse,
353                           sizeof(CK_BBOOL));
354             attrs++;
355             PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
356                           sizeof(CK_BBOOL));
357             attrs++;
358             PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
359                           (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
360                                                             : &ckfalse,
361                           sizeof(CK_BBOOL));
362             attrs++;
363             ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
364             if (ck_id == NULL) {
365                 goto loser;
366             }
367             PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
368             attrs++;
369             if (nickname) {
370                 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
371                 attrs++;
372             }
373             signedattr = attrs;
374             PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
375                           lpk->u.rsa.modulus.len);
376             attrs++;
377             PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
378                           lpk->u.rsa.publicExponent.data,
379                           lpk->u.rsa.publicExponent.len);
380             attrs++;
381             PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT,
382                           lpk->u.rsa.privateExponent.data,
383                           lpk->u.rsa.privateExponent.len);
384             attrs++;
385             PK11_SETATTRS(attrs, CKA_PRIME_1,
386                           lpk->u.rsa.prime1.data,
387                           lpk->u.rsa.prime1.len);
388             attrs++;
389             PK11_SETATTRS(attrs, CKA_PRIME_2,
390                           lpk->u.rsa.prime2.data,
391                           lpk->u.rsa.prime2.len);
392             attrs++;
393             PK11_SETATTRS(attrs, CKA_EXPONENT_1,
394                           lpk->u.rsa.exponent1.data,
395                           lpk->u.rsa.exponent1.len);
396             attrs++;
397             PK11_SETATTRS(attrs, CKA_EXPONENT_2,
398                           lpk->u.rsa.exponent2.data,
399                           lpk->u.rsa.exponent2.len);
400             attrs++;
401             PK11_SETATTRS(attrs, CKA_COEFFICIENT,
402                           lpk->u.rsa.coefficient.data,
403                           lpk->u.rsa.coefficient.len);
404             attrs++;
405             break;
406         case dsaKey:
407             keyType = CKK_DSA;
408             /* To make our intenal PKCS #11 module work correctly with
409              * our database, we need to pass in the public key value for
410              * this dsa key. We have a netscape only CKA_ value to do this.
411              * Only send it to internal slots */
412             if (publicValue == NULL) {
413                 goto loser;
414             }
415             if (PK11_IsInternal(slot)) {
416                 PK11_SETATTRS(attrs, CKA_NSS_DB,
417                               publicValue->data, publicValue->len);
418                 attrs++;
419             }
420             PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
421             attrs++;
422             PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL));
423             attrs++;
424             if (nickname) {
425                 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
426                 attrs++;
427             }
428             ck_id = PK11_MakeIDFromPubKey(publicValue);
429             if (ck_id == NULL) {
430                 goto loser;
431             }
432             PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
433             attrs++;
434             signedattr = attrs;
435             PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data,
436                           lpk->u.dsa.params.prime.len);
437             attrs++;
438             PK11_SETATTRS(attrs, CKA_SUBPRIME, lpk->u.dsa.params.subPrime.data,
439                           lpk->u.dsa.params.subPrime.len);
440             attrs++;
441             PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data,
442                           lpk->u.dsa.params.base.len);
443             attrs++;
444             PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data,
445                           lpk->u.dsa.privateValue.len);
446             attrs++;
447             break;
448         case dhKey:
449             keyType = CKK_DH;
450             /* To make our intenal PKCS #11 module work correctly with
451              * our database, we need to pass in the public key value for
452              * this dh key. We have a netscape only CKA_ value to do this.
453              * Only send it to internal slots */
454             if (PK11_IsInternal(slot)) {
455                 PK11_SETATTRS(attrs, CKA_NSS_DB,
456                               publicValue->data, publicValue->len);
457                 attrs++;
458             }
459             PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
460             attrs++;
461             if (nickname) {
462                 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
463                 attrs++;
464             }
465             ck_id = PK11_MakeIDFromPubKey(publicValue);
466             if (ck_id == NULL) {
467                 goto loser;
468             }
469             PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
470             attrs++;
471             signedattr = attrs;
472             PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data,
473                           lpk->u.dh.prime.len);
474             attrs++;
475             PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data,
476                           lpk->u.dh.base.len);
477             attrs++;
478             PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data,
479                           lpk->u.dh.privateValue.len);
480             attrs++;
481             break;
482         case ecKey:
483             keyType = CKK_EC;
484             if (lpk->u.ec.publicValue.len == 0) {
485                 goto loser;
486             }
487             if (PK11_IsInternal(slot)) {
488                 PK11_SETATTRS(attrs, CKA_NSS_DB,
489                               lpk->u.ec.publicValue.data,
490                               lpk->u.ec.publicValue.len);
491                 attrs++;
492             }
493             PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
494                           sizeof(CK_BBOOL));
495             attrs++;
496             PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
497                           (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
498                                                             : &ckfalse,
499                           sizeof(CK_BBOOL));
500             attrs++;
501             PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue : &ckfalse,
502                           sizeof(CK_BBOOL));
503             attrs++;
504             if (nickname) {
505                 PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
506                 attrs++;
507             }
508             ck_id = PK11_MakeIDFromPubKey(&lpk->u.ec.publicValue);
509             if (ck_id == NULL) {
510                 goto loser;
511             }
512             PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
513             attrs++;
514             /* No signed attrs for EC */
515             /* curveOID always is a copy of AlgorithmID.parameters. */
516             PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
517                           lpk->u.ec.curveOID.len);
518             attrs++;
519             PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
520                           lpk->u.ec.privateValue.len);
521             attrs++;
522             PK11_SETATTRS(attrs, CKA_EC_POINT, lpk->u.ec.publicValue.data,
523                           lpk->u.ec.publicValue.len);
524             attrs++;
525             break;
526         default:
527             PORT_SetError(SEC_ERROR_BAD_KEY);
528             goto loser;
529     }
530     templateCount = attrs - theTemplate;
531     PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
532     if (lpk->keyType != ecKey) {
533         PORT_Assert(signedattr);
534         signedcount = attrs - signedattr;
535         for (ap = signedattr; signedcount; ap++, signedcount--) {
536             pk11_SignedToUnsigned(ap);
537         }
538     }
539 
540     rv = PK11_CreateNewObject(slot, CK_INVALID_HANDLE,
541                               theTemplate, templateCount, isPerm, &objectID);
542 
543     /* create and return a SECKEYPrivateKey */
544     if (rv == SECSuccess && privk != NULL) {
545         *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
546         if (*privk == NULL) {
547             rv = SECFailure;
548         }
549     }
550 loser:
551     if (ck_id) {
552         SECITEM_ZfreeItem(ck_id, PR_TRUE);
553     }
554     return rv;
555 }
556 
557 SECStatus
PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo * slot,SECKEYPrivateKeyInfo * pki,SECItem * nickname,SECItem * publicValue,PRBool isPerm,PRBool isPrivate,unsigned int keyUsage,SECKEYPrivateKey ** privk,void * wincx)558 PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
559                                       SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
560                                       PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
561                                       SECKEYPrivateKey **privk, void *wincx)
562 {
563     SECStatus rv = SECFailure;
564     SECKEYRawPrivateKey *lpk = NULL;
565     const SEC_ASN1Template *keyTemplate, *paramTemplate;
566     void *paramDest = NULL;
567     PLArenaPool *arena = NULL;
568 
569     arena = PORT_NewArena(2048);
570     if (!arena) {
571         return SECFailure;
572     }
573 
574     /* need to change this to use RSA/DSA keys */
575     lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
576                                                   sizeof(SECKEYRawPrivateKey));
577     if (lpk == NULL) {
578         goto loser;
579     }
580     lpk->arena = arena;
581 
582     switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
583         case SEC_OID_PKCS1_RSA_ENCRYPTION:
584             prepare_rsa_priv_key_export_for_asn1(lpk);
585             keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
586             paramTemplate = NULL;
587             paramDest = NULL;
588             lpk->keyType = rsaKey;
589             break;
590         case SEC_OID_ANSIX9_DSA_SIGNATURE:
591             prepare_dsa_priv_key_export_for_asn1(lpk);
592             keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
593             paramTemplate = SECKEY_PQGParamsTemplate;
594             paramDest = &(lpk->u.dsa.params);
595             lpk->keyType = dsaKey;
596             break;
597         case SEC_OID_X942_DIFFIE_HELMAN_KEY:
598             if (!publicValue) {
599                 goto loser;
600             }
601             prepare_dh_priv_key_export_for_asn1(lpk);
602             keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
603             paramTemplate = NULL;
604             paramDest = NULL;
605             lpk->keyType = dhKey;
606             break;
607         case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
608             prepare_ec_priv_key_export_for_asn1(lpk);
609             keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
610             paramTemplate = NULL;
611             paramDest = NULL;
612             lpk->keyType = ecKey;
613             break;
614 
615         default:
616             keyTemplate = NULL;
617             paramTemplate = NULL;
618             paramDest = NULL;
619             break;
620     }
621 
622     if (!keyTemplate) {
623         goto loser;
624     }
625 
626     /* decode the private key and any algorithm parameters */
627     rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
628     if (rv != SECSuccess) {
629         goto loser;
630     }
631 
632     if (lpk->keyType == ecKey) {
633         /* Convert length in bits to length in bytes. */
634         lpk->u.ec.publicValue.len >>= 3;
635 
636         /* Always override curveOID, we're ignoring any given value. */
637         rv = SECITEM_CopyItem(arena, &lpk->u.ec.curveOID,
638                               &pki->algorithm.parameters);
639         if (rv != SECSuccess) {
640             goto loser;
641         }
642     }
643 
644     if (paramDest && paramTemplate) {
645         rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,
646                                 &(pki->algorithm.parameters));
647         if (rv != SECSuccess) {
648             goto loser;
649         }
650     }
651 
652     rv = PK11_ImportAndReturnPrivateKey(slot, lpk, nickname, publicValue, isPerm,
653                                         isPrivate, keyUsage, privk, wincx);
654 
655 loser:
656     if (arena != NULL) {
657         PORT_FreeArena(arena, PR_TRUE);
658     }
659 
660     return rv;
661 }
662 
663 SECStatus
PK11_ImportPrivateKeyInfo(PK11SlotInfo * slot,SECKEYPrivateKeyInfo * pki,SECItem * nickname,SECItem * publicValue,PRBool isPerm,PRBool isPrivate,unsigned int keyUsage,void * wincx)664 PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki,
665                           SECItem *nickname, SECItem *publicValue, PRBool isPerm,
666                           PRBool isPrivate, unsigned int keyUsage, void *wincx)
667 {
668     return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
669                                                  publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
670 }
671 
672 SECItem *
PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey * pk,void * wincx)673 PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx)
674 {
675     SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx);
676     SECItem *derPKI;
677 
678     if (!pki) {
679         return NULL;
680     }
681     derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki,
682                                 SECKEY_PrivateKeyInfoTemplate);
683     SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE);
684     return derPKI;
685 }
686 
687 static PRBool
ReadAttribute(SECKEYPrivateKey * key,CK_ATTRIBUTE_TYPE type,PLArenaPool * arena,SECItem * output)688 ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
689               PLArenaPool *arena, SECItem *output)
690 {
691     SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type,
692                                       arena, output);
693     return rv == SECSuccess;
694 }
695 
696 /*
697  * The caller is responsible for freeing the return value by passing it to
698  * SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE).
699  */
700 SECKEYPrivateKeyInfo *
PK11_ExportPrivKeyInfo(SECKEYPrivateKey * pk,void * wincx)701 PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx)
702 {
703     /* PrivateKeyInfo version (always zero) */
704     const unsigned char pkiVersion = 0;
705     /* RSAPrivateKey version (always zero) */
706     const unsigned char rsaVersion = 0;
707     /* ECPrivateKey version (always one) */
708     const unsigned char ecVersion = 1;
709     PLArenaPool *arena = NULL;
710     SECKEYRawPrivateKey rawKey;
711     SECKEYPrivateKeyInfo *pki;
712     SECItem *encoded;
713     const SEC_ASN1Template *keyTemplate;
714     SECStatus rv;
715 
716     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
717     if (!arena) {
718         goto loser;
719     }
720     memset(&rawKey, 0, sizeof(rawKey));
721     rawKey.keyType = pk->keyType;
722     pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo);
723     if (!pki) {
724         goto loser;
725     }
726 
727     switch (pk->keyType) {
728         case rsaKey: {
729             rawKey.u.rsa.version.type = siUnsignedInteger;
730             rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
731             if (!rawKey.u.rsa.version.data) {
732                 goto loser;
733             }
734 
735             rawKey.u.rsa.version.data[0] = rsaVersion;
736             rawKey.u.rsa.version.len = 1;
737 
738             /* Read the component attributes of the private key */
739             prepare_rsa_priv_key_export_for_asn1(&rawKey);
740             if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) ||
741                 !ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena,
742                                &rawKey.u.rsa.publicExponent) ||
743                 !ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena,
744                                &rawKey.u.rsa.privateExponent) ||
745                 !ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) ||
746                 !ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) ||
747                 !ReadAttribute(pk, CKA_EXPONENT_1, arena,
748                                &rawKey.u.rsa.exponent1) ||
749                 !ReadAttribute(pk, CKA_EXPONENT_2, arena,
750                                &rawKey.u.rsa.exponent2) ||
751                 !ReadAttribute(pk, CKA_COEFFICIENT, arena,
752                                &rawKey.u.rsa.coefficient)) {
753                 goto loser;
754             }
755 
756             keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
757 
758             rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
759             if (rv != SECSuccess) {
760                 goto loser;
761             }
762 
763         } break;
764         case ecKey: {
765             rawKey.u.ec.version.type = siUnsignedInteger;
766             rawKey.u.ec.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
767             if (!rawKey.u.ec.version.data) {
768                 goto loser;
769             }
770             rawKey.u.ec.version.data[0] = ecVersion;
771             rawKey.u.ec.version.len = 1;
772 
773             SECItem curveOID;
774             /* Read the component attributes of the private key */
775             prepare_ec_priv_key_export_for_asn1(&rawKey);
776             if (!ReadAttribute(pk, CKA_VALUE, arena,
777                                &rawKey.u.ec.privateValue) ||
778                 !ReadAttribute(pk, CKA_EC_PARAMS, arena, &curveOID)) {
779                 goto loser;
780             }
781             if (!ReadAttribute(pk, CKA_EC_POINT, arena,
782                                &rawKey.u.ec.publicValue)) {
783                 SECKEYPublicKey *pubk = SECKEY_ConvertToPublicKey(pk);
784                 if (pubk == NULL)
785                     goto loser;
786                 rv = SECITEM_CopyItem(arena, &rawKey.u.ec.publicValue, &pubk->u.ec.publicValue);
787                 SECKEY_DestroyPublicKey(pubk);
788                 if (rv != SECSuccess) {
789                     goto loser;
790                 }
791             }
792 
793             keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
794             /* Convert length in bytes to length in bits. */
795             rawKey.u.ec.publicValue.len <<= 3;
796 
797             rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_ANSIX962_EC_PUBLIC_KEY, &curveOID);
798             if (rv != SECSuccess) {
799                 goto loser;
800             }
801 
802         } break;
803         default: {
804             PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
805             goto loser;
806         }
807     }
808 
809     encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey, keyTemplate);
810     if (!encoded) {
811         goto loser;
812     }
813     pki->version.type = siUnsignedInteger;
814     pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
815     if (!pki->version.data) {
816         goto loser;
817     }
818     pki->version.data[0] = pkiVersion;
819     pki->version.len = 1;
820     pki->arena = arena;
821 
822     return pki;
823 
824 loser:
825     if (arena) {
826         PORT_FreeArena(arena, PR_TRUE);
827     }
828     return NULL;
829 }
830