Coverage Report

Created: 2018-09-25 14:53

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