Coverage Report

Created: 2025-07-01 06:25

/src/nss/lib/pk11wrap/pk11pk12.c
Line
Count
Source (jump to first uncovered line)
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
/* The template operates a private key consisting only of private key. */
184
const SEC_ASN1Template SECKEY_ECRawPrivateKeyTemplate[] = {
185
    { SEC_ASN1_OCTET_STRING,
186
      offsetof(SECKEYRawPrivateKey, u.ec.privateValue) },
187
    { 0 }
188
};
189
190
const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
191
    { SEC_ASN1_SEQUENCE,
192
      0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) },
193
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
194
      offsetof(SECKEYEncryptedPrivateKeyInfo, algorithm),
195
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
196
    { SEC_ASN1_OCTET_STRING,
197
      offsetof(SECKEYEncryptedPrivateKeyInfo, encryptedData) },
198
    { 0 }
199
};
200
201
const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
202
    { SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
203
};
204
205
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate)
206
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
207
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
208
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)
209
210
/*
211
 * See bugzilla bug 125359
212
 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
213
 * all of the templates above that en/decode into integers must be converted
214
 * from ASN.1's signed integer type.  This is done by marking either the
215
 * source or destination (encoding or decoding, respectively) type as
216
 * siUnsignedInteger.
217
 */
218
219
static void
220
prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
221
0
{
222
0
    key->u.rsa.modulus.type = siUnsignedInteger;
223
0
    key->u.rsa.publicExponent.type = siUnsignedInteger;
224
0
    key->u.rsa.privateExponent.type = siUnsignedInteger;
225
0
    key->u.rsa.prime1.type = siUnsignedInteger;
226
0
    key->u.rsa.prime2.type = siUnsignedInteger;
227
0
    key->u.rsa.exponent1.type = siUnsignedInteger;
228
0
    key->u.rsa.exponent2.type = siUnsignedInteger;
229
0
    key->u.rsa.coefficient.type = siUnsignedInteger;
230
0
}
231
232
static void
233
prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
234
0
{
235
0
    key->u.dsa.privateValue.type = siUnsignedInteger;
236
0
    key->u.dsa.params.prime.type = siUnsignedInteger;
237
0
    key->u.dsa.params.subPrime.type = siUnsignedInteger;
238
0
    key->u.dsa.params.base.type = siUnsignedInteger;
239
0
}
240
241
static void
242
prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
243
0
{
244
0
    key->u.dh.privateValue.type = siUnsignedInteger;
245
0
    key->u.dh.prime.type = siUnsignedInteger;
246
0
    key->u.dh.base.type = siUnsignedInteger;
247
0
}
248
249
static void
250
prepare_ec_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
251
0
{
252
0
    key->u.ec.version.type = siUnsignedInteger;
253
0
    key->u.ec.curveOID.type = siUnsignedInteger;
254
0
    key->u.ec.privateValue.type = siUnsignedInteger;
255
0
    key->u.ec.publicValue.type = siUnsignedInteger;
256
0
}
257
258
SECStatus
259
PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI,
260
                             SECItem *nickname, SECItem *publicValue, PRBool isPerm,
261
                             PRBool isPrivate, unsigned int keyUsage, void *wincx)
262
0
{
263
0
    return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI,
264
0
                                                    nickname, publicValue,
265
0
                                                    isPerm, isPrivate, keyUsage,
266
0
                                                    NULL, wincx);
267
0
}
268
269
SECStatus
270
PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI,
271
                                         SECItem *nickname, SECItem *publicValue,
272
                                         PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
273
                                         SECKEYPrivateKey **privk, void *wincx)
274
0
{
275
0
    SECKEYPrivateKeyInfo *pki = NULL;
276
0
    PLArenaPool *temparena = NULL;
277
0
    SECStatus rv = SECFailure;
278
279
0
    temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
280
0
    if (!temparena) {
281
0
        return rv;
282
0
    }
283
284
0
    pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo);
285
0
    if (!pki) {
286
0
        PORT_FreeArena(temparena, PR_FALSE);
287
0
        return rv;
288
0
    }
289
0
    pki->arena = temparena;
290
291
0
    rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
292
0
                            derPKI);
293
0
    if (rv != SECSuccess) {
294
        /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the
295
         * validity of the data in pki. The best we can do is free the arena
296
         * and return. */
297
0
        PORT_FreeArena(temparena, PR_TRUE);
298
0
        return rv;
299
0
    }
300
0
    if (pki->privateKey.data == NULL) {
301
        /* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey
302
         * is a zero-length octet string, free the arena and return a failure
303
         * to avoid trying to zero the corresponding SECItem in
304
         * SECKEY_DestroyPrivateKeyInfo(). */
305
0
        PORT_FreeArena(temparena, PR_TRUE);
306
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
307
0
        return SECFailure;
308
0
    }
309
310
0
    rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
311
0
                                               publicValue, isPerm, isPrivate,
312
0
                                               keyUsage, privk, wincx);
313
314
    /* this zeroes the key and frees the arena */
315
0
    SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
316
0
    return rv;
317
0
}
318
319
SECStatus
320
PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
321
                               SECItem *nickname, SECItem *publicValue, PRBool isPerm,
322
                               PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
323
                               void *wincx)
324
0
{
325
0
    CK_BBOOL cktrue = CK_TRUE;
326
0
    CK_BBOOL ckfalse = CK_FALSE;
327
0
    CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
328
0
    CK_KEY_TYPE keyType = CKK_RSA;
329
0
    CK_OBJECT_HANDLE objectID;
330
0
    CK_ATTRIBUTE theTemplate[20];
331
0
    int templateCount = 0;
332
0
    SECStatus rv = SECFailure;
333
0
    CK_ATTRIBUTE *attrs;
334
0
    CK_ATTRIBUTE *signedattr = NULL;
335
0
    int signedcount = 0;
336
0
    CK_ATTRIBUTE *ap;
337
0
    SECItem *ck_id = NULL;
338
339
0
    attrs = theTemplate;
340
341
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
342
0
    attrs++;
343
0
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
344
0
    attrs++;
345
0
    PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse,
346
0
                  sizeof(CK_BBOOL));
347
0
    attrs++;
348
0
    PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse,
349
0
                  sizeof(CK_BBOOL));
350
0
    attrs++;
351
0
    PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
352
0
                  sizeof(CK_BBOOL));
353
0
    attrs++;
354
355
0
    switch (lpk->keyType) {
356
0
        case rsaKey:
357
0
            keyType = CKK_RSA;
358
0
            PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue : &ckfalse,
359
0
                          sizeof(CK_BBOOL));
360
0
            attrs++;
361
0
            PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue : &ckfalse,
362
0
                          sizeof(CK_BBOOL));
363
0
            attrs++;
364
0
            PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
365
0
                          sizeof(CK_BBOOL));
366
0
            attrs++;
367
0
            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
368
0
                          (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
369
0
                                                            : &ckfalse,
370
0
                          sizeof(CK_BBOOL));
371
0
            attrs++;
372
0
            ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
373
0
            if (ck_id == NULL) {
374
0
                goto loser;
375
0
            }
376
0
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
377
0
            attrs++;
378
0
            if (nickname) {
379
0
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
380
0
                attrs++;
381
0
            }
382
0
            signedattr = attrs;
383
0
            PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
384
0
                          lpk->u.rsa.modulus.len);
385
0
            attrs++;
386
0
            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
387
0
                          lpk->u.rsa.publicExponent.data,
388
0
                          lpk->u.rsa.publicExponent.len);
389
0
            attrs++;
390
0
            PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT,
391
0
                          lpk->u.rsa.privateExponent.data,
392
0
                          lpk->u.rsa.privateExponent.len);
393
0
            attrs++;
394
0
            PK11_SETATTRS(attrs, CKA_PRIME_1,
395
0
                          lpk->u.rsa.prime1.data,
396
0
                          lpk->u.rsa.prime1.len);
397
0
            attrs++;
398
0
            PK11_SETATTRS(attrs, CKA_PRIME_2,
399
0
                          lpk->u.rsa.prime2.data,
400
0
                          lpk->u.rsa.prime2.len);
401
0
            attrs++;
402
0
            PK11_SETATTRS(attrs, CKA_EXPONENT_1,
403
0
                          lpk->u.rsa.exponent1.data,
404
0
                          lpk->u.rsa.exponent1.len);
405
0
            attrs++;
406
0
            PK11_SETATTRS(attrs, CKA_EXPONENT_2,
407
0
                          lpk->u.rsa.exponent2.data,
408
0
                          lpk->u.rsa.exponent2.len);
409
0
            attrs++;
410
0
            PK11_SETATTRS(attrs, CKA_COEFFICIENT,
411
0
                          lpk->u.rsa.coefficient.data,
412
0
                          lpk->u.rsa.coefficient.len);
413
0
            attrs++;
414
0
            break;
415
0
        case dsaKey:
416
0
            keyType = CKK_DSA;
417
            /* To make our intenal PKCS #11 module work correctly with
418
             * our database, we need to pass in the public key value for
419
             * this dsa key. We have a netscape only CKA_ value to do this.
420
             * Only send it to internal slots */
421
0
            if (publicValue == NULL) {
422
0
                goto loser;
423
0
            }
424
0
            if (PK11_IsInternal(slot)) {
425
0
                PK11_SETATTRS(attrs, CKA_NSS_DB,
426
0
                              publicValue->data, publicValue->len);
427
0
                attrs++;
428
0
            }
429
0
            PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
430
0
            attrs++;
431
0
            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL));
432
0
            attrs++;
433
0
            if (nickname) {
434
0
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
435
0
                attrs++;
436
0
            }
437
0
            ck_id = PK11_MakeIDFromPubKey(publicValue);
438
0
            if (ck_id == NULL) {
439
0
                goto loser;
440
0
            }
441
0
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
442
0
            attrs++;
443
0
            signedattr = attrs;
444
0
            PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data,
445
0
                          lpk->u.dsa.params.prime.len);
446
0
            attrs++;
447
0
            PK11_SETATTRS(attrs, CKA_SUBPRIME, lpk->u.dsa.params.subPrime.data,
448
0
                          lpk->u.dsa.params.subPrime.len);
449
0
            attrs++;
450
0
            PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data,
451
0
                          lpk->u.dsa.params.base.len);
452
0
            attrs++;
453
0
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data,
454
0
                          lpk->u.dsa.privateValue.len);
455
0
            attrs++;
456
0
            break;
457
0
        case dhKey:
458
0
            keyType = CKK_DH;
459
            /* To make our intenal PKCS #11 module work correctly with
460
             * our database, we need to pass in the public key value for
461
             * this dh key. We have a netscape only CKA_ value to do this.
462
             * Only send it to internal slots */
463
0
            if (PK11_IsInternal(slot)) {
464
0
                PK11_SETATTRS(attrs, CKA_NSS_DB,
465
0
                              publicValue->data, publicValue->len);
466
0
                attrs++;
467
0
            }
468
0
            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
469
0
            attrs++;
470
0
            if (nickname) {
471
0
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
472
0
                attrs++;
473
0
            }
474
0
            ck_id = PK11_MakeIDFromPubKey(publicValue);
475
0
            if (ck_id == NULL) {
476
0
                goto loser;
477
0
            }
478
0
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
479
0
            attrs++;
480
0
            signedattr = attrs;
481
0
            PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data,
482
0
                          lpk->u.dh.prime.len);
483
0
            attrs++;
484
0
            PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data,
485
0
                          lpk->u.dh.base.len);
486
0
            attrs++;
487
0
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data,
488
0
                          lpk->u.dh.privateValue.len);
489
0
            attrs++;
490
0
            break;
491
0
        case ecKey:
492
0
            keyType = CKK_EC;
493
0
            if (lpk->u.ec.publicValue.len != 0) {
494
0
                if (PK11_IsInternal(slot)) {
495
0
                    PK11_SETATTRS(attrs, CKA_NSS_DB,
496
0
                                  lpk->u.ec.publicValue.data,
497
0
                                  lpk->u.ec.publicValue.len);
498
0
                    attrs++;
499
0
                }
500
0
            }
501
502
0
            PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse,
503
0
                          sizeof(CK_BBOOL));
504
0
            attrs++;
505
0
            PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
506
0
                          (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
507
0
                                                            : &ckfalse,
508
0
                          sizeof(CK_BBOOL));
509
0
            attrs++;
510
0
            PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue : &ckfalse,
511
0
                          sizeof(CK_BBOOL));
512
0
            attrs++;
513
0
            if (nickname) {
514
0
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
515
0
                attrs++;
516
0
            }
517
0
            ck_id = PK11_MakeIDFromPubKey(&lpk->u.ec.publicValue);
518
0
            if (ck_id == NULL) {
519
0
                goto loser;
520
0
            }
521
0
            PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
522
0
            attrs++;
523
            /* No signed attrs for EC */
524
            /* curveOID always is a copy of AlgorithmID.parameters. */
525
0
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
526
0
                          lpk->u.ec.curveOID.len);
527
0
            attrs++;
528
0
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
529
0
                          lpk->u.ec.privateValue.len);
530
0
            attrs++;
531
0
            PK11_SETATTRS(attrs, CKA_EC_POINT, lpk->u.ec.publicValue.data,
532
0
                          lpk->u.ec.publicValue.len);
533
0
            attrs++;
534
0
            break;
535
0
        case edKey:
536
0
            keyType = CKK_EC_EDWARDS;
537
0
            PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
538
0
            attrs++;
539
0
            if (nickname) {
540
0
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
541
0
                attrs++;
542
0
            }
543
544
            /* No signed attrs for EC */
545
            /* curveOID always is a copy of AlgorithmID.parameters. */
546
0
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
547
0
                          lpk->u.ec.curveOID.len);
548
0
            attrs++;
549
0
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
550
0
                          lpk->u.ec.privateValue.len);
551
0
            attrs++;
552
0
            break;
553
0
        case ecMontKey:
554
0
            keyType = CKK_EC_MONTGOMERY;
555
556
0
            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
557
0
            attrs++;
558
559
0
            if (nickname) {
560
0
                PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
561
0
                attrs++;
562
0
            }
563
564
            /* No signed attrs for EC */
565
            /* curveOID always is a copy of AlgorithmID.parameters. */
566
0
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
567
0
                          lpk->u.ec.curveOID.len);
568
0
            attrs++;
569
570
0
            PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data,
571
0
                          lpk->u.ec.privateValue.len);
572
0
            attrs++;
573
0
            break;
574
0
        default:
575
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
576
0
            goto loser;
577
0
    }
578
0
    templateCount = attrs - theTemplate;
579
0
    PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
580
0
    if (lpk->keyType != ecKey && lpk->keyType != edKey && lpk->keyType != ecMontKey) {
581
0
        PORT_Assert(signedattr);
582
0
        signedcount = attrs - signedattr;
583
0
        for (ap = signedattr; signedcount; ap++, signedcount--) {
584
0
            pk11_SignedToUnsigned(ap);
585
0
        }
586
0
    }
587
588
0
    rv = PK11_CreateNewObject(slot, CK_INVALID_HANDLE,
589
0
                              theTemplate, templateCount, isPerm, &objectID);
590
591
    /* create and return a SECKEYPrivateKey */
592
0
    if (rv == SECSuccess && privk != NULL) {
593
0
        *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
594
0
        if (*privk == NULL) {
595
0
            rv = SECFailure;
596
0
        }
597
0
    }
598
0
loser:
599
0
    if (ck_id) {
600
0
        SECITEM_ZfreeItem(ck_id, PR_TRUE);
601
0
    }
602
0
    return rv;
603
0
}
604
605
SECStatus
606
PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
607
                                      SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
608
                                      PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
609
                                      SECKEYPrivateKey **privk, void *wincx)
610
0
{
611
0
    SECStatus rv = SECFailure;
612
0
    SECKEYRawPrivateKey *lpk = NULL;
613
0
    const SEC_ASN1Template *keyTemplate, *paramTemplate;
614
0
    void *paramDest = NULL;
615
0
    PLArenaPool *arena = NULL;
616
617
0
    arena = PORT_NewArena(2048);
618
0
    if (!arena) {
619
0
        return SECFailure;
620
0
    }
621
622
    /* need to change this to use RSA/DSA keys */
623
0
    lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
624
0
                                                  sizeof(SECKEYRawPrivateKey));
625
0
    if (lpk == NULL) {
626
0
        goto loser;
627
0
    }
628
0
    lpk->arena = arena;
629
630
0
    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
631
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
632
0
            prepare_rsa_priv_key_export_for_asn1(lpk);
633
0
            keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
634
0
            paramTemplate = NULL;
635
0
            paramDest = NULL;
636
0
            lpk->keyType = rsaKey;
637
0
            break;
638
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
639
0
            prepare_dsa_priv_key_export_for_asn1(lpk);
640
0
            keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
641
0
            paramTemplate = SECKEY_PQGParamsTemplate;
642
0
            paramDest = &(lpk->u.dsa.params);
643
0
            lpk->keyType = dsaKey;
644
0
            break;
645
0
        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
646
0
            if (!publicValue) {
647
0
                goto loser;
648
0
            }
649
0
            prepare_dh_priv_key_export_for_asn1(lpk);
650
0
            keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
651
0
            paramTemplate = NULL;
652
0
            paramDest = NULL;
653
0
            lpk->keyType = dhKey;
654
0
            break;
655
0
        case SEC_OID_ED25519_PUBLIC_KEY:
656
0
            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
657
0
            paramTemplate = NULL;
658
0
            paramDest = NULL;
659
0
            lpk->keyType = edKey;
660
0
            break;
661
0
        case SEC_OID_X25519:
662
0
            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
663
0
            paramTemplate = NULL;
664
0
            paramDest = NULL;
665
0
            lpk->keyType = ecMontKey;
666
0
            break;
667
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
668
0
            prepare_ec_priv_key_export_for_asn1(lpk);
669
0
            keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
670
0
            paramTemplate = NULL;
671
0
            paramDest = NULL;
672
0
            lpk->keyType = ecKey;
673
0
            break;
674
675
0
        default:
676
0
            keyTemplate = NULL;
677
0
            paramTemplate = NULL;
678
0
            paramDest = NULL;
679
0
            break;
680
0
    }
681
682
0
    if (!keyTemplate) {
683
0
        goto loser;
684
0
    }
685
686
    /* decode the private key and any algorithm parameters */
687
0
    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
688
0
    if (rv != SECSuccess) {
689
0
        goto loser;
690
0
    }
691
692
0
    if (lpk->keyType == ecKey) {
693
        /* Convert length in bits to length in bytes. */
694
0
        lpk->u.ec.publicValue.len >>= 3;
695
696
        /* Always override curveOID, we're ignoring any given value. */
697
0
        rv = SECITEM_CopyItem(arena, &lpk->u.ec.curveOID,
698
0
                              &pki->algorithm.parameters);
699
0
        if (rv != SECSuccess) {
700
0
            goto loser;
701
0
        }
702
0
    }
703
704
0
    if (lpk->keyType == edKey || lpk->keyType == ecMontKey) {
705
        /* SECKEY_ECRawPrivateKeyTemplate (used for both key types) does not reference
706
           publicKey, curveOID, ec verion. */
707
0
        if (pki->algorithm.parameters.len != 0) {
708
            /* Currently supporting only (Pure)Ed25519/X25519 .*/
709
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
710
0
            goto loser;
711
0
        }
712
713
0
        SECOidData *oid25519 = SECOID_FindOIDByTag(SECOID_GetAlgorithmTag(&pki->algorithm));
714
0
        if (!oid25519) {
715
0
            goto loser;
716
0
        }
717
718
0
        if (!SECITEM_AllocItem(arena, &lpk->u.ec.curveOID, oid25519->oid.len + 2)) {
719
0
            goto loser;
720
0
        }
721
0
        lpk->u.ec.curveOID.data[0] = SEC_ASN1_OBJECT_ID;
722
0
        lpk->u.ec.curveOID.data[1] = oid25519->oid.len;
723
0
        PORT_Memcpy(lpk->u.ec.curveOID.data + 2, oid25519->oid.data, oid25519->oid.len);
724
0
    }
725
726
0
    if (paramDest && paramTemplate) {
727
0
        rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,
728
0
                                &(pki->algorithm.parameters));
729
0
        if (rv != SECSuccess) {
730
0
            goto loser;
731
0
        }
732
0
    }
733
734
0
    rv = PK11_ImportAndReturnPrivateKey(slot, lpk, nickname, publicValue, isPerm,
735
0
                                        isPrivate, keyUsage, privk, wincx);
736
0
loser:
737
0
    if (arena != NULL) {
738
0
        PORT_FreeArena(arena, PR_TRUE);
739
0
    }
740
741
0
    return rv;
742
0
}
743
744
SECStatus
745
PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki,
746
                          SECItem *nickname, SECItem *publicValue, PRBool isPerm,
747
                          PRBool isPrivate, unsigned int keyUsage, void *wincx)
748
0
{
749
0
    return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
750
0
                                                 publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
751
0
}
752
753
SECItem *
754
PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx)
755
0
{
756
0
    SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx);
757
0
    SECItem *derPKI;
758
759
0
    if (!pki) {
760
0
        return NULL;
761
0
    }
762
0
    derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki,
763
0
                                SECKEY_PrivateKeyInfoTemplate);
764
0
    SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE);
765
0
    return derPKI;
766
0
}
767
768
static PRBool
769
ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
770
              PLArenaPool *arena, SECItem *output)
771
0
{
772
0
    SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type,
773
0
                                      arena, output);
774
0
    return rv == SECSuccess;
775
0
}
776
777
/*
778
 * The caller is responsible for freeing the return value by passing it to
779
 * SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE).
780
 */
781
SECKEYPrivateKeyInfo *
782
PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx)
783
0
{
784
    /* PrivateKeyInfo version (always zero) */
785
0
    const unsigned char pkiVersion = 0;
786
    /* RSAPrivateKey version (always zero) */
787
0
    const unsigned char rsaVersion = 0;
788
    /* ECPrivateKey version (always one) */
789
0
    const unsigned char ecVersion = 1;
790
0
    PLArenaPool *arena = NULL;
791
0
    SECKEYRawPrivateKey rawKey;
792
0
    SECKEYPrivateKeyInfo *pki;
793
0
    SECItem *encoded;
794
0
    const SEC_ASN1Template *keyTemplate;
795
0
    SECStatus rv;
796
797
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
798
0
    if (!arena) {
799
0
        goto loser;
800
0
    }
801
0
    memset(&rawKey, 0, sizeof(rawKey));
802
0
    rawKey.keyType = pk->keyType;
803
0
    pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo);
804
0
    if (!pki) {
805
0
        goto loser;
806
0
    }
807
808
0
    switch (pk->keyType) {
809
0
        case rsaKey: {
810
0
            rawKey.u.rsa.version.type = siUnsignedInteger;
811
0
            rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
812
0
            if (!rawKey.u.rsa.version.data) {
813
0
                goto loser;
814
0
            }
815
816
0
            rawKey.u.rsa.version.data[0] = rsaVersion;
817
0
            rawKey.u.rsa.version.len = 1;
818
819
            /* Read the component attributes of the private key */
820
0
            prepare_rsa_priv_key_export_for_asn1(&rawKey);
821
0
            if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) ||
822
0
                !ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena,
823
0
                               &rawKey.u.rsa.publicExponent) ||
824
0
                !ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena,
825
0
                               &rawKey.u.rsa.privateExponent) ||
826
0
                !ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) ||
827
0
                !ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) ||
828
0
                !ReadAttribute(pk, CKA_EXPONENT_1, arena,
829
0
                               &rawKey.u.rsa.exponent1) ||
830
0
                !ReadAttribute(pk, CKA_EXPONENT_2, arena,
831
0
                               &rawKey.u.rsa.exponent2) ||
832
0
                !ReadAttribute(pk, CKA_COEFFICIENT, arena,
833
0
                               &rawKey.u.rsa.coefficient)) {
834
0
                goto loser;
835
0
            }
836
837
0
            keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
838
839
0
            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
840
0
            if (rv != SECSuccess) {
841
0
                goto loser;
842
0
            }
843
844
0
        } break;
845
0
        case ecKey: {
846
0
            rawKey.u.ec.version.type = siUnsignedInteger;
847
0
            rawKey.u.ec.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
848
0
            if (!rawKey.u.ec.version.data) {
849
0
                goto loser;
850
0
            }
851
0
            rawKey.u.ec.version.data[0] = ecVersion;
852
0
            rawKey.u.ec.version.len = 1;
853
854
0
            SECItem curveOID;
855
            /* Read the component attributes of the private key */
856
0
            prepare_ec_priv_key_export_for_asn1(&rawKey);
857
0
            if (!ReadAttribute(pk, CKA_VALUE, arena,
858
0
                               &rawKey.u.ec.privateValue) ||
859
0
                !ReadAttribute(pk, CKA_EC_PARAMS, arena, &curveOID)) {
860
0
                goto loser;
861
0
            }
862
0
            if (!ReadAttribute(pk, CKA_EC_POINT, arena,
863
0
                               &rawKey.u.ec.publicValue)) {
864
0
                SECKEYPublicKey *pubk = SECKEY_ConvertToPublicKey(pk);
865
0
                if (pubk == NULL)
866
0
                    goto loser;
867
0
                rv = SECITEM_CopyItem(arena, &rawKey.u.ec.publicValue, &pubk->u.ec.publicValue);
868
0
                SECKEY_DestroyPublicKey(pubk);
869
0
                if (rv != SECSuccess) {
870
0
                    goto loser;
871
0
                }
872
0
            }
873
874
0
            keyTemplate = SECKEY_ECPrivateKeyExportTemplate;
875
            /* Convert length in bytes to length in bits. */
876
0
            rawKey.u.ec.publicValue.len <<= 3;
877
878
0
            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_ANSIX962_EC_PUBLIC_KEY, &curveOID);
879
0
            if (rv != SECSuccess) {
880
0
                goto loser;
881
0
            }
882
883
0
        } break;
884
0
        case edKey: {
885
0
            if (!ReadAttribute(pk, CKA_VALUE, arena,
886
0
                               &rawKey.u.ec.privateValue)) {
887
0
                goto loser;
888
0
            }
889
890
0
            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
891
            /* Currently, Ed25519 does not support any parameter.  */
892
0
            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_ED25519_PUBLIC_KEY, NULL);
893
0
            if (rv != SECSuccess) {
894
0
                goto loser;
895
0
            }
896
0
        } break;
897
0
        case ecMontKey: {
898
0
            if (!ReadAttribute(pk, CKA_VALUE, arena,
899
0
                               &rawKey.u.ec.privateValue)) {
900
0
                goto loser;
901
0
            }
902
903
0
            keyTemplate = SECKEY_ECRawPrivateKeyTemplate;
904
            /* Currently, X25519 does not support any parameter.  */
905
0
            rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, SEC_OID_X25519, NULL);
906
0
            if (rv != SECSuccess) {
907
0
                goto loser;
908
0
            }
909
0
        } break;
910
0
        default: {
911
0
            PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
912
0
            goto loser;
913
0
        }
914
0
    }
915
916
0
    encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey, keyTemplate);
917
0
    if (!encoded) {
918
0
        goto loser;
919
0
    }
920
0
    pki->version.type = siUnsignedInteger;
921
0
    pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
922
0
    if (!pki->version.data) {
923
0
        goto loser;
924
0
    }
925
0
    pki->version.data[0] = pkiVersion;
926
0
    pki->version.len = 1;
927
0
    pki->arena = arena;
928
929
0
    return pki;
930
931
0
loser:
932
0
    if (arena) {
933
0
        PORT_FreeArena(arena, PR_TRUE);
934
0
    }
935
0
    return NULL;
936
0
}