Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/cryptohi/seckey.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
#include "cryptohi.h"
5
#include "keyhi.h"
6
#include "secoid.h"
7
#include "secitem.h"
8
#include "secder.h"
9
#include "base64.h"
10
#include "secasn1.h"
11
#include "cert.h"
12
#include "pk11func.h"
13
#include "secerr.h"
14
#include "secdig.h"
15
#include "prtime.h"
16
#include "keyi.h"
17
18
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
19
SEC_ASN1_MKSUB(SEC_IntegerTemplate)
20
21
const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
22
    { SEC_ASN1_SEQUENCE,
23
      0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
24
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
25
      offsetof(CERTSubjectPublicKeyInfo, algorithm),
26
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
27
    { SEC_ASN1_BIT_STRING,
28
      offsetof(CERTSubjectPublicKeyInfo, subjectPublicKey) },
29
    { 0 }
30
};
31
32
const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
33
    {
34
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
35
      { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge, spki) },
36
      { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge, challenge) },
37
      { 0 }
38
    };
39
40
const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
41
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
42
    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.rsa.modulus) },
43
    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.rsa.publicExponent) },
44
    { 0 }
45
};
46
47
static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = {
48
    { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0,
49
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }
50
};
51
52
/* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */
53
const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] =
54
    {
55
      { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) },
56
      { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
57
            SEC_ASN1_CONTEXT_SPECIFIC | 0,
58
        offsetof(SECKEYRSAPSSParams, hashAlg),
59
        seckey_PointerToAlgorithmIDTemplate },
60
      { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
61
            SEC_ASN1_CONTEXT_SPECIFIC | 1,
62
        offsetof(SECKEYRSAPSSParams, maskAlg),
63
        seckey_PointerToAlgorithmIDTemplate },
64
      { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
65
            SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2,
66
        offsetof(SECKEYRSAPSSParams, saltLength),
67
        SEC_ASN1_SUB(SEC_IntegerTemplate) },
68
      { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
69
            SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3,
70
        offsetof(SECKEYRSAPSSParams, trailerField),
71
        SEC_ASN1_SUB(SEC_IntegerTemplate) },
72
      { 0 }
73
    };
74
75
const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
76
    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dsa.publicValue) },
77
    { 0 }
78
};
79
80
const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
81
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
82
    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) },
83
    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) },
84
    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) },
85
    { 0 }
86
};
87
88
const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
89
    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.publicValue) },
90
    { 0 }
91
};
92
93
const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
94
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
95
    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.prime) },
96
    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.base) },
97
    /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
98
    { SEC_ASN1_SKIP_REST },
99
    { 0 }
100
};
101
102
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
103
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
104
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate)
105
SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
106
107
/*
108
 * See bugzilla bug 125359
109
 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
110
 * all of the templates above that en/decode into integers must be converted
111
 * from ASN.1's signed integer type.  This is done by marking either the
112
 * source or destination (encoding or decoding, respectively) type as
113
 * siUnsignedInteger.
114
 */
115
static void
116
prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
117
0
{
118
0
    pubk->u.rsa.modulus.type = siUnsignedInteger;
119
0
    pubk->u.rsa.publicExponent.type = siUnsignedInteger;
120
0
}
121
122
static void
123
prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
124
0
{
125
0
    pubk->u.dsa.publicValue.type = siUnsignedInteger;
126
0
}
127
128
static void
129
prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
130
0
{
131
0
    params->prime.type = siUnsignedInteger;
132
0
    params->subPrime.type = siUnsignedInteger;
133
0
    params->base.type = siUnsignedInteger;
134
0
}
135
136
static void
137
prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
138
0
{
139
0
    pubk->u.dh.prime.type = siUnsignedInteger;
140
0
    pubk->u.dh.base.type = siUnsignedInteger;
141
0
    pubk->u.dh.publicValue.type = siUnsignedInteger;
142
0
}
143
144
/* Create an RSA key pair is any slot able to do so.
145
** The created keys are "session" (temporary), not "token" (permanent),
146
** and they are "sensitive", which makes them costly to move to another token.
147
*/
148
SECKEYPrivateKey *
149
SECKEY_CreateRSAPrivateKey(int keySizeInBits, SECKEYPublicKey **pubk, void *cx)
150
0
{
151
0
    SECKEYPrivateKey *privk;
152
0
    PK11RSAGenParams param;
153
0
    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, cx);
154
0
    if (!slot) {
155
0
        return NULL;
156
0
    }
157
0
158
0
    param.keySizeInBits = keySizeInBits;
159
0
    param.pe = 65537L;
160
0
161
0
    privk = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &param, pubk,
162
0
                                 PR_FALSE, PR_TRUE, cx);
163
0
    PK11_FreeSlot(slot);
164
0
    return (privk);
165
0
}
166
167
/* Create a DH key pair in any slot able to do so,
168
** This is a "session" (temporary), not "token" (permanent) key.
169
** Because of the high probability that this key will need to be moved to
170
** another token, and the high cost of moving "sensitive" keys, we attempt
171
** to create this key pair without the "sensitive" attribute, but revert to
172
** creating a "sensitive" key if necessary.
173
*/
174
SECKEYPrivateKey *
175
SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
176
0
{
177
0
    SECKEYPrivateKey *privk;
178
0
    PK11SlotInfo *slot;
179
0
180
0
    if (!param || !param->base.data || !param->prime.data ||
181
0
        SECKEY_BigIntegerBitLength(&param->prime) < DH_MIN_P_BITS ||
182
0
        param->base.len == 0 || param->base.len > param->prime.len + 1 ||
183
0
        (param->base.len == 1 && param->base.data[0] == 0)) {
184
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
185
0
        return NULL;
186
0
    }
187
0
188
0
    slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, cx);
189
0
    if (!slot) {
190
0
        return NULL;
191
0
    }
192
0
193
0
    privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
194
0
                                 pubk, PR_FALSE, PR_FALSE, cx);
195
0
    if (!privk)
196
0
        privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
197
0
                                     pubk, PR_FALSE, PR_TRUE, cx);
198
0
199
0
    PK11_FreeSlot(slot);
200
0
    return (privk);
201
0
}
202
203
/* Create an EC key pair in any slot able to do so,
204
** This is a "session" (temporary), not "token" (permanent) key.
205
** Because of the high probability that this key will need to be moved to
206
** another token, and the high cost of moving "sensitive" keys, we attempt
207
** to create this key pair without the "sensitive" attribute, but revert to
208
** creating a "sensitive" key if necessary.
209
*/
210
SECKEYPrivateKey *
211
SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
212
0
{
213
0
    SECKEYPrivateKey *privk;
214
0
    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN, cx);
215
0
    if (!slot) {
216
0
        return NULL;
217
0
    }
218
0
219
0
    privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
220
0
                                            param, pubk,
221
0
                                            PK11_ATTR_SESSION |
222
0
                                                PK11_ATTR_INSENSITIVE |
223
0
                                                PK11_ATTR_PUBLIC,
224
0
                                            CKF_DERIVE, CKF_DERIVE | CKF_SIGN,
225
0
                                            cx);
226
0
    if (!privk)
227
0
        privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
228
0
                                                param, pubk,
229
0
                                                PK11_ATTR_SESSION |
230
0
                                                    PK11_ATTR_SENSITIVE |
231
0
                                                    PK11_ATTR_PRIVATE,
232
0
                                                CKF_DERIVE, CKF_DERIVE | CKF_SIGN,
233
0
                                                cx);
234
0
235
0
    PK11_FreeSlot(slot);
236
0
    return (privk);
237
0
}
238
239
void
240
SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
241
0
{
242
0
    if (privk) {
243
0
        if (privk->pkcs11Slot) {
244
0
            if (privk->pkcs11IsTemp) {
245
0
                PK11_DestroyObject(privk->pkcs11Slot, privk->pkcs11ID);
246
0
            }
247
0
            PK11_FreeSlot(privk->pkcs11Slot);
248
0
        }
249
0
        if (privk->arena) {
250
0
            PORT_FreeArena(privk->arena, PR_TRUE);
251
0
        }
252
0
    }
253
0
}
254
255
void
256
SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
257
0
{
258
0
    if (pubk) {
259
0
        if (pubk->pkcs11Slot) {
260
0
            if (!PK11_IsPermObject(pubk->pkcs11Slot, pubk->pkcs11ID)) {
261
0
                PK11_DestroyObject(pubk->pkcs11Slot, pubk->pkcs11ID);
262
0
            }
263
0
            PK11_FreeSlot(pubk->pkcs11Slot);
264
0
        }
265
0
        if (pubk->arena) {
266
0
            PORT_FreeArena(pubk->arena, PR_FALSE);
267
0
        }
268
0
    }
269
0
}
270
271
SECStatus
272
SECKEY_CopySubjectPublicKeyInfo(PLArenaPool *arena,
273
                                CERTSubjectPublicKeyInfo *to,
274
                                CERTSubjectPublicKeyInfo *from)
275
0
{
276
0
    SECStatus rv;
277
0
    SECItem spk;
278
0
279
0
    rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
280
0
    if (rv == SECSuccess) {
281
0
        /*
282
0
         * subjectPublicKey is a bit string, whose length is in bits.
283
0
         * Convert the length from bits to bytes for SECITEM_CopyItem.
284
0
         */
285
0
        spk = from->subjectPublicKey;
286
0
        DER_ConvertBitString(&spk);
287
0
        rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
288
0
        /* Set the length back to bits. */
289
0
        if (rv == SECSuccess) {
290
0
            to->subjectPublicKey.len = from->subjectPublicKey.len;
291
0
        }
292
0
    }
293
0
294
0
    return rv;
295
0
}
296
297
/* Procedure to update the pqg parameters for a cert's public key.
298
 * pqg parameters only need to be updated for DSA certificates.
299
 * The procedure uses calls to itself recursively to update a certificate
300
 * issuer's pqg parameters.  Some important rules are:
301
 *    - Do nothing if the cert already has PQG parameters.
302
 *    - If the cert does not have PQG parameters, obtain them from the issuer.
303
 *    - A valid cert chain cannot have a DSA cert without
304
 *      pqg parameters that has a parent that is not a DSA cert.  */
305
306
static SECStatus
307
seckey_UpdateCertPQGChain(CERTCertificate *subjectCert, int count)
308
0
{
309
0
    SECStatus rv;
310
0
    SECOidData *oid = NULL;
311
0
    int tag;
312
0
    CERTSubjectPublicKeyInfo *subjectSpki = NULL;
313
0
    CERTSubjectPublicKeyInfo *issuerSpki = NULL;
314
0
    CERTCertificate *issuerCert = NULL;
315
0
316
0
    /* increment cert chain length counter*/
317
0
    count++;
318
0
319
0
    /* check if cert chain length exceeds the maximum length*/
320
0
    if (count > CERT_MAX_CERT_CHAIN) {
321
0
        return SECFailure;
322
0
    }
323
0
324
0
    oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);
325
0
    if (oid != NULL) {
326
0
        tag = oid->offset;
327
0
328
0
        /* Check if cert has a DSA or EC public key. If not, return
329
0
         * success since no PQG params need to be updated.
330
0
         *
331
0
         * Question: do we really need to do this for EC keys. They don't have
332
0
         * PQG parameters, but they do have parameters. The question is does
333
0
         * the child cert inherit thost parameters for EC from the parent, or
334
0
         * do we always include those parameters in each cert.
335
0
         */
336
0
337
0
        if ((tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
338
0
            (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
339
0
            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
340
0
            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
341
0
            (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
342
0
            (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
343
0
            (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
344
0
345
0
            return SECSuccess;
346
0
        }
347
0
    } else {
348
0
        return SECFailure; /* return failure if oid is NULL */
349
0
    }
350
0
351
0
    /* if cert has PQG parameters, return success */
352
0
353
0
    subjectSpki = &subjectCert->subjectPublicKeyInfo;
354
0
355
0
    if (subjectSpki->algorithm.parameters.len != 0) {
356
0
        return SECSuccess;
357
0
    }
358
0
359
0
    /* check if the cert is self-signed */
360
0
    if (subjectCert->isRoot) {
361
0
        /* fail since cert is self-signed and has no pqg params. */
362
0
        return SECFailure;
363
0
    }
364
0
365
0
    /* get issuer cert */
366
0
    issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
367
0
    if (!issuerCert) {
368
0
        return SECFailure;
369
0
    }
370
0
371
0
    /* if parent is not DSA, return failure since
372
0
       we don't allow this case. */
373
0
374
0
    oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
375
0
    if (oid != NULL) {
376
0
        tag = oid->offset;
377
0
378
0
        /* Check if issuer cert has a DSA public key. If not,
379
0
         * return failure.   */
380
0
381
0
        if ((tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
382
0
            (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
383
0
            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
384
0
            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
385
0
            (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
386
0
            (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
387
0
            (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
388
0
            rv = SECFailure;
389
0
            goto loser;
390
0
        }
391
0
    } else {
392
0
        rv = SECFailure; /* return failure if oid is NULL */
393
0
        goto loser;
394
0
    }
395
0
396
0
    /* at this point the subject cert has no pqg parameters and the
397
0
     * issuer cert has a DSA public key.  Update the issuer's
398
0
     * pqg parameters with a recursive call to this same function. */
399
0
400
0
    rv = seckey_UpdateCertPQGChain(issuerCert, count);
401
0
    if (rv != SECSuccess) {
402
0
        rv = SECFailure;
403
0
        goto loser;
404
0
    }
405
0
406
0
    /* ensure issuer has pqg parameters */
407
0
408
0
    issuerSpki = &issuerCert->subjectPublicKeyInfo;
409
0
    if (issuerSpki->algorithm.parameters.len == 0) {
410
0
        rv = SECFailure;
411
0
    }
412
0
413
0
    /* if update was successful and pqg params present, then copy the
414
0
     * parameters to the subject cert's key. */
415
0
416
0
    if (rv == SECSuccess) {
417
0
        rv = SECITEM_CopyItem(subjectCert->arena,
418
0
                              &subjectSpki->algorithm.parameters,
419
0
                              &issuerSpki->algorithm.parameters);
420
0
    }
421
0
422
0
loser:
423
0
    if (issuerCert) {
424
0
        CERT_DestroyCertificate(issuerCert);
425
0
    }
426
0
    return rv;
427
0
}
428
429
SECStatus
430
SECKEY_UpdateCertPQG(CERTCertificate *subjectCert)
431
0
{
432
0
    if (!subjectCert) {
433
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
434
0
        return SECFailure;
435
0
    }
436
0
    return seckey_UpdateCertPQGChain(subjectCert, 0);
437
0
}
438
439
/* Decode the DSA PQG parameters.  The params could be stored in two
440
 * possible formats, the old fortezza-only wrapped format or
441
 * the normal standard format.  Store the decoded parameters in
442
 * a V3 certificate data structure.  */
443
444
static SECStatus
445
seckey_DSADecodePQG(PLArenaPool *arena, SECKEYPublicKey *pubk,
446
                    const SECItem *params)
447
0
{
448
0
    SECStatus rv;
449
0
    SECItem newparams;
450
0
451
0
    if (params == NULL)
452
0
        return SECFailure;
453
0
454
0
    if (params->data == NULL)
455
0
        return SECFailure;
456
0
457
0
    PORT_Assert(arena);
458
0
459
0
    /* make a copy of the data into the arena so QuickDER output is valid */
460
0
    rv = SECITEM_CopyItem(arena, &newparams, params);
461
0
462
0
    /* Check if params use the standard format.
463
0
     * The value 0xa1 will appear in the first byte of the parameter data
464
0
     * if the PQG parameters are not using the standard format.  This
465
0
     * code should be changed to use a better method to detect non-standard
466
0
     * parameters.    */
467
0
468
0
    if ((newparams.data[0] != 0xa1) &&
469
0
        (newparams.data[0] != 0xa0)) {
470
0
471
0
        if (SECSuccess == rv) {
472
0
            /* PQG params are in the standard format */
473
0
            prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
474
0
            rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
475
0
                                        SECKEY_PQGParamsTemplate,
476
0
                                        &newparams);
477
0
        }
478
0
    } else {
479
0
480
0
        if (SECSuccess == rv) {
481
0
            /* else the old fortezza-only wrapped format is used. */
482
0
            PORT_SetError(SEC_ERROR_BAD_DER);
483
0
            rv = SECFailure;
484
0
        }
485
0
    }
486
0
    return rv;
487
0
}
488
489
/* Function used to make an oid tag to a key type */
490
KeyType
491
seckey_GetKeyType(SECOidTag tag)
492
0
{
493
0
    KeyType keyType;
494
0
495
0
    switch (tag) {
496
0
        case SEC_OID_X500_RSA_ENCRYPTION:
497
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
498
0
            keyType = rsaKey;
499
0
            break;
500
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
501
0
            keyType = rsaPssKey;
502
0
            break;
503
0
        case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
504
0
            keyType = rsaOaepKey;
505
0
            break;
506
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
507
0
            keyType = dsaKey;
508
0
            break;
509
0
        case SEC_OID_MISSI_KEA_DSS_OLD:
510
0
        case SEC_OID_MISSI_KEA_DSS:
511
0
        case SEC_OID_MISSI_DSS_OLD:
512
0
        case SEC_OID_MISSI_DSS:
513
0
            keyType = fortezzaKey;
514
0
            break;
515
0
        case SEC_OID_MISSI_KEA:
516
0
        case SEC_OID_MISSI_ALT_KEA:
517
0
            keyType = keaKey;
518
0
            break;
519
0
        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
520
0
            keyType = dhKey;
521
0
            break;
522
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
523
0
            keyType = ecKey;
524
0
            break;
525
0
        /* accommodate applications that hand us a signature type when they
526
0
         * should be handing us a cipher type */
527
0
        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
528
0
        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
529
0
        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
530
0
        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
531
0
        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
532
0
        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
533
0
            keyType = rsaKey;
534
0
            break;
535
0
        default:
536
0
            keyType = nullKey;
537
0
    }
538
0
    return keyType;
539
0
}
540
541
/* Function used to determine what kind of cert we are dealing with. */
542
KeyType
543
CERT_GetCertKeyType(const CERTSubjectPublicKeyInfo *spki)
544
0
{
545
0
    return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
546
0
}
547
548
/* Ensure pubKey contains an OID */
549
static SECStatus
550
seckey_HasCurveOID(const SECKEYPublicKey *pubKey)
551
0
{
552
0
    SECItem oid;
553
0
    SECStatus rv;
554
0
    PORTCheapArenaPool tmpArena;
555
0
556
0
    PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
557
0
    /* If we can decode it, an OID is available. */
558
0
    rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &oid,
559
0
                                SEC_ASN1_GET(SEC_ObjectIDTemplate),
560
0
                                &pubKey->u.ec.DEREncodedParams);
561
0
    PORT_DestroyCheapArena(&tmpArena);
562
0
    return rv;
563
0
}
564
565
static SECKEYPublicKey *
566
seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
567
0
{
568
0
    SECKEYPublicKey *pubk;
569
0
    SECItem os, newOs, newParms;
570
0
    SECStatus rv;
571
0
    PLArenaPool *arena;
572
0
    SECOidTag tag;
573
0
574
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
575
0
    if (arena == NULL)
576
0
        return NULL;
577
0
578
0
    pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
579
0
    if (pubk == NULL) {
580
0
        PORT_FreeArena(arena, PR_FALSE);
581
0
        return NULL;
582
0
    }
583
0
584
0
    pubk->arena = arena;
585
0
    pubk->pkcs11Slot = 0;
586
0
    pubk->pkcs11ID = CK_INVALID_HANDLE;
587
0
588
0
    /* Convert bit string length from bits to bytes */
589
0
    os = spki->subjectPublicKey;
590
0
    DER_ConvertBitString(&os);
591
0
592
0
    tag = SECOID_GetAlgorithmTag(&spki->algorithm);
593
0
594
0
    /* copy the DER into the arena, since Quick DER returns data that points
595
0
       into the DER input, which may get freed by the caller */
596
0
    rv = SECITEM_CopyItem(arena, &newOs, &os);
597
0
    if (rv == SECSuccess)
598
0
        switch (tag) {
599
0
            case SEC_OID_X500_RSA_ENCRYPTION:
600
0
            case SEC_OID_PKCS1_RSA_ENCRYPTION:
601
0
            case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
602
0
                pubk->keyType = rsaKey;
603
0
                prepare_rsa_pub_key_for_asn1(pubk);
604
0
                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
605
0
                if (rv == SECSuccess)
606
0
                    return pubk;
607
0
                break;
608
0
            case SEC_OID_ANSIX9_DSA_SIGNATURE:
609
0
            case SEC_OID_SDN702_DSA_SIGNATURE:
610
0
                pubk->keyType = dsaKey;
611
0
                prepare_dsa_pub_key_for_asn1(pubk);
612
0
                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
613
0
                if (rv != SECSuccess)
614
0
                    break;
615
0
616
0
                rv = seckey_DSADecodePQG(arena, pubk,
617
0
                                         &spki->algorithm.parameters);
618
0
619
0
                if (rv == SECSuccess)
620
0
                    return pubk;
621
0
                break;
622
0
            case SEC_OID_X942_DIFFIE_HELMAN_KEY:
623
0
                pubk->keyType = dhKey;
624
0
                prepare_dh_pub_key_for_asn1(pubk);
625
0
                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
626
0
                if (rv != SECSuccess)
627
0
                    break;
628
0
629
0
                /* copy the DER into the arena, since Quick DER returns data that points
630
0
                   into the DER input, which may get freed by the caller */
631
0
                rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
632
0
                if (rv != SECSuccess)
633
0
                    break;
634
0
635
0
                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
636
0
                                            &newParms);
637
0
638
0
                if (rv == SECSuccess)
639
0
                    return pubk;
640
0
                break;
641
0
            case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
642
0
                pubk->keyType = ecKey;
643
0
                pubk->u.ec.size = 0;
644
0
645
0
                /* Since PKCS#11 directly takes the DER encoding of EC params
646
0
                 * and public value, we don't need any decoding here.
647
0
                 */
648
0
                rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams,
649
0
                                      &spki->algorithm.parameters);
650
0
                if (rv != SECSuccess) {
651
0
                    break;
652
0
                }
653
0
                rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
654
0
                if (rv != SECSuccess) {
655
0
                    break;
656
0
                }
657
0
                pubk->u.ec.encoding = ECPoint_Undefined;
658
0
                rv = seckey_HasCurveOID(pubk);
659
0
                if (rv == SECSuccess) {
660
0
                    return pubk;
661
0
                }
662
0
                break;
663
0
664
0
            default:
665
0
                PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
666
0
                break;
667
0
        }
668
0
669
0
    SECKEY_DestroyPublicKey(pubk);
670
0
    return NULL;
671
0
}
672
673
/* required for JSS */
674
SECKEYPublicKey *
675
SECKEY_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
676
0
{
677
0
    return seckey_ExtractPublicKey(spki);
678
0
}
679
680
SECKEYPublicKey *
681
CERT_ExtractPublicKey(CERTCertificate *cert)
682
0
{
683
0
    return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
684
0
}
685
686
int
687
SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
688
0
{
689
0
    SECOidTag tag;
690
0
    SECItem oid = { siBuffer, NULL, 0 };
691
0
692
0
    /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
693
0
     * followed by the length of the curve oid and the curve oid.
694
0
     */
695
0
    oid.len = encodedParams->data[1];
696
0
    oid.data = encodedParams->data + 2;
697
0
    if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
698
0
        return 0;
699
0
700
0
    switch (tag) {
701
0
        case SEC_OID_SECG_EC_SECP112R1:
702
0
        case SEC_OID_SECG_EC_SECP112R2:
703
0
            return 112;
704
0
705
0
        case SEC_OID_SECG_EC_SECT113R1:
706
0
        case SEC_OID_SECG_EC_SECT113R2:
707
0
            return 113;
708
0
709
0
        case SEC_OID_SECG_EC_SECP128R1:
710
0
        case SEC_OID_SECG_EC_SECP128R2:
711
0
            return 128;
712
0
713
0
        case SEC_OID_SECG_EC_SECT131R1:
714
0
        case SEC_OID_SECG_EC_SECT131R2:
715
0
            return 131;
716
0
717
0
        case SEC_OID_SECG_EC_SECP160K1:
718
0
        case SEC_OID_SECG_EC_SECP160R1:
719
0
        case SEC_OID_SECG_EC_SECP160R2:
720
0
            return 160;
721
0
722
0
        case SEC_OID_SECG_EC_SECT163K1:
723
0
        case SEC_OID_SECG_EC_SECT163R1:
724
0
        case SEC_OID_SECG_EC_SECT163R2:
725
0
        case SEC_OID_ANSIX962_EC_C2PNB163V1:
726
0
        case SEC_OID_ANSIX962_EC_C2PNB163V2:
727
0
        case SEC_OID_ANSIX962_EC_C2PNB163V3:
728
0
            return 163;
729
0
730
0
        case SEC_OID_ANSIX962_EC_C2PNB176V1:
731
0
            return 176;
732
0
733
0
        case SEC_OID_ANSIX962_EC_C2TNB191V1:
734
0
        case SEC_OID_ANSIX962_EC_C2TNB191V2:
735
0
        case SEC_OID_ANSIX962_EC_C2TNB191V3:
736
0
        case SEC_OID_ANSIX962_EC_C2ONB191V4:
737
0
        case SEC_OID_ANSIX962_EC_C2ONB191V5:
738
0
            return 191;
739
0
740
0
        case SEC_OID_SECG_EC_SECP192K1:
741
0
        case SEC_OID_ANSIX962_EC_PRIME192V1:
742
0
        case SEC_OID_ANSIX962_EC_PRIME192V2:
743
0
        case SEC_OID_ANSIX962_EC_PRIME192V3:
744
0
            return 192;
745
0
746
0
        case SEC_OID_SECG_EC_SECT193R1:
747
0
        case SEC_OID_SECG_EC_SECT193R2:
748
0
            return 193;
749
0
750
0
        case SEC_OID_ANSIX962_EC_C2PNB208W1:
751
0
            return 208;
752
0
753
0
        case SEC_OID_SECG_EC_SECP224K1:
754
0
        case SEC_OID_SECG_EC_SECP224R1:
755
0
            return 224;
756
0
757
0
        case SEC_OID_SECG_EC_SECT233K1:
758
0
        case SEC_OID_SECG_EC_SECT233R1:
759
0
            return 233;
760
0
761
0
        case SEC_OID_SECG_EC_SECT239K1:
762
0
        case SEC_OID_ANSIX962_EC_C2TNB239V1:
763
0
        case SEC_OID_ANSIX962_EC_C2TNB239V2:
764
0
        case SEC_OID_ANSIX962_EC_C2TNB239V3:
765
0
        case SEC_OID_ANSIX962_EC_C2ONB239V4:
766
0
        case SEC_OID_ANSIX962_EC_C2ONB239V5:
767
0
        case SEC_OID_ANSIX962_EC_PRIME239V1:
768
0
        case SEC_OID_ANSIX962_EC_PRIME239V2:
769
0
        case SEC_OID_ANSIX962_EC_PRIME239V3:
770
0
            return 239;
771
0
772
0
        case SEC_OID_SECG_EC_SECP256K1:
773
0
        case SEC_OID_ANSIX962_EC_PRIME256V1:
774
0
            return 256;
775
0
776
0
        case SEC_OID_ANSIX962_EC_C2PNB272W1:
777
0
            return 272;
778
0
779
0
        case SEC_OID_SECG_EC_SECT283K1:
780
0
        case SEC_OID_SECG_EC_SECT283R1:
781
0
            return 283;
782
0
783
0
        case SEC_OID_ANSIX962_EC_C2PNB304W1:
784
0
            return 304;
785
0
786
0
        case SEC_OID_ANSIX962_EC_C2TNB359V1:
787
0
            return 359;
788
0
789
0
        case SEC_OID_ANSIX962_EC_C2PNB368W1:
790
0
            return 368;
791
0
792
0
        case SEC_OID_SECG_EC_SECP384R1:
793
0
            return 384;
794
0
795
0
        case SEC_OID_SECG_EC_SECT409K1:
796
0
        case SEC_OID_SECG_EC_SECT409R1:
797
0
            return 409;
798
0
799
0
        case SEC_OID_ANSIX962_EC_C2TNB431R1:
800
0
            return 431;
801
0
802
0
        case SEC_OID_SECG_EC_SECP521R1:
803
0
            return 521;
804
0
805
0
        case SEC_OID_SECG_EC_SECT571K1:
806
0
        case SEC_OID_SECG_EC_SECT571R1:
807
0
            return 571;
808
0
809
0
        case SEC_OID_CURVE25519:
810
0
            return 255;
811
0
812
0
        default:
813
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
814
0
            return 0;
815
0
    }
816
0
}
817
818
int
819
SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
820
0
{
821
0
    SECOidTag tag;
822
0
    SECItem oid = { siBuffer, NULL, 0 };
823
0
824
0
    /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
825
0
     * followed by the length of the curve oid and the curve oid.
826
0
     */
827
0
    oid.len = encodedParams->data[1];
828
0
    oid.data = encodedParams->data + 2;
829
0
    if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
830
0
        return 0;
831
0
832
0
    switch (tag) {
833
0
        case SEC_OID_SECG_EC_SECP112R1:
834
0
            return 112;
835
0
        case SEC_OID_SECG_EC_SECP112R2:
836
0
            return 110;
837
0
838
0
        case SEC_OID_SECG_EC_SECT113R1:
839
0
        case SEC_OID_SECG_EC_SECT113R2:
840
0
            return 113;
841
0
842
0
        case SEC_OID_SECG_EC_SECP128R1:
843
0
            return 128;
844
0
        case SEC_OID_SECG_EC_SECP128R2:
845
0
            return 126;
846
0
847
0
        case SEC_OID_SECG_EC_SECT131R1:
848
0
        case SEC_OID_SECG_EC_SECT131R2:
849
0
            return 131;
850
0
851
0
        case SEC_OID_SECG_EC_SECP160K1:
852
0
        case SEC_OID_SECG_EC_SECP160R1:
853
0
        case SEC_OID_SECG_EC_SECP160R2:
854
0
            return 161;
855
0
856
0
        case SEC_OID_SECG_EC_SECT163K1:
857
0
            return 163;
858
0
        case SEC_OID_SECG_EC_SECT163R1:
859
0
            return 162;
860
0
        case SEC_OID_SECG_EC_SECT163R2:
861
0
        case SEC_OID_ANSIX962_EC_C2PNB163V1:
862
0
            return 163;
863
0
        case SEC_OID_ANSIX962_EC_C2PNB163V2:
864
0
        case SEC_OID_ANSIX962_EC_C2PNB163V3:
865
0
            return 162;
866
0
867
0
        case SEC_OID_ANSIX962_EC_C2PNB176V1:
868
0
            return 161;
869
0
870
0
        case SEC_OID_ANSIX962_EC_C2TNB191V1:
871
0
            return 191;
872
0
        case SEC_OID_ANSIX962_EC_C2TNB191V2:
873
0
            return 190;
874
0
        case SEC_OID_ANSIX962_EC_C2TNB191V3:
875
0
            return 189;
876
0
        case SEC_OID_ANSIX962_EC_C2ONB191V4:
877
0
            return 191;
878
0
        case SEC_OID_ANSIX962_EC_C2ONB191V5:
879
0
            return 188;
880
0
881
0
        case SEC_OID_SECG_EC_SECP192K1:
882
0
        case SEC_OID_ANSIX962_EC_PRIME192V1:
883
0
        case SEC_OID_ANSIX962_EC_PRIME192V2:
884
0
        case SEC_OID_ANSIX962_EC_PRIME192V3:
885
0
            return 192;
886
0
887
0
        case SEC_OID_SECG_EC_SECT193R1:
888
0
        case SEC_OID_SECG_EC_SECT193R2:
889
0
            return 193;
890
0
891
0
        case SEC_OID_ANSIX962_EC_C2PNB208W1:
892
0
            return 193;
893
0
894
0
        case SEC_OID_SECG_EC_SECP224K1:
895
0
            return 225;
896
0
        case SEC_OID_SECG_EC_SECP224R1:
897
0
            return 224;
898
0
899
0
        case SEC_OID_SECG_EC_SECT233K1:
900
0
            return 232;
901
0
        case SEC_OID_SECG_EC_SECT233R1:
902
0
            return 233;
903
0
904
0
        case SEC_OID_SECG_EC_SECT239K1:
905
0
        case SEC_OID_ANSIX962_EC_C2TNB239V1:
906
0
            return 238;
907
0
        case SEC_OID_ANSIX962_EC_C2TNB239V2:
908
0
            return 237;
909
0
        case SEC_OID_ANSIX962_EC_C2TNB239V3:
910
0
            return 236;
911
0
        case SEC_OID_ANSIX962_EC_C2ONB239V4:
912
0
            return 238;
913
0
        case SEC_OID_ANSIX962_EC_C2ONB239V5:
914
0
            return 237;
915
0
        case SEC_OID_ANSIX962_EC_PRIME239V1:
916
0
        case SEC_OID_ANSIX962_EC_PRIME239V2:
917
0
        case SEC_OID_ANSIX962_EC_PRIME239V3:
918
0
            return 239;
919
0
920
0
        case SEC_OID_SECG_EC_SECP256K1:
921
0
        case SEC_OID_ANSIX962_EC_PRIME256V1:
922
0
            return 256;
923
0
924
0
        case SEC_OID_ANSIX962_EC_C2PNB272W1:
925
0
            return 257;
926
0
927
0
        case SEC_OID_SECG_EC_SECT283K1:
928
0
            return 281;
929
0
        case SEC_OID_SECG_EC_SECT283R1:
930
0
            return 282;
931
0
932
0
        case SEC_OID_ANSIX962_EC_C2PNB304W1:
933
0
            return 289;
934
0
935
0
        case SEC_OID_ANSIX962_EC_C2TNB359V1:
936
0
            return 353;
937
0
938
0
        case SEC_OID_ANSIX962_EC_C2PNB368W1:
939
0
            return 353;
940
0
941
0
        case SEC_OID_SECG_EC_SECP384R1:
942
0
            return 384;
943
0
944
0
        case SEC_OID_SECG_EC_SECT409K1:
945
0
            return 407;
946
0
        case SEC_OID_SECG_EC_SECT409R1:
947
0
            return 409;
948
0
949
0
        case SEC_OID_ANSIX962_EC_C2TNB431R1:
950
0
            return 418;
951
0
952
0
        case SEC_OID_SECG_EC_SECP521R1:
953
0
            return 521;
954
0
955
0
        case SEC_OID_SECG_EC_SECT571K1:
956
0
        case SEC_OID_SECG_EC_SECT571R1:
957
0
            return 570;
958
0
959
0
        case SEC_OID_CURVE25519:
960
0
            return 255;
961
0
962
0
        default:
963
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
964
0
            return 0;
965
0
    }
966
0
}
967
968
/* The number of bits in the number from the first non-zero bit onward. */
969
unsigned
970
SECKEY_BigIntegerBitLength(const SECItem *number)
971
0
{
972
0
    const unsigned char *p;
973
0
    unsigned octets;
974
0
    unsigned bits;
975
0
976
0
    if (!number || !number->data) {
977
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
978
0
        return 0;
979
0
    }
980
0
981
0
    p = number->data;
982
0
    octets = number->len;
983
0
    while (octets > 0 && !*p) {
984
0
        ++p;
985
0
        --octets;
986
0
    }
987
0
    if (octets == 0) {
988
0
        return 0;
989
0
    }
990
0
    /* bits = 7..1 because we know at least one bit is set already */
991
0
    /* Note: This could do a binary search, but this is faster for keys if we
992
0
     * assume that good keys will have the MSB set. */
993
0
    for (bits = 7; bits > 0; --bits) {
994
0
        if (*p & (1 << bits)) {
995
0
            break;
996
0
        }
997
0
    }
998
0
    return octets * 8 + bits - 7;
999
0
}
1000
1001
/* returns key strength in bytes (not bits) */
1002
unsigned
1003
SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
1004
0
{
1005
0
    return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
1006
0
}
1007
1008
/* returns key strength in bits */
1009
unsigned
1010
SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
1011
0
{
1012
0
    unsigned bitSize = 0;
1013
0
1014
0
    if (!pubk) {
1015
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
1016
0
        return 0;
1017
0
    }
1018
0
1019
0
    /* interpret modulus length as key strength */
1020
0
    switch (pubk->keyType) {
1021
0
        case rsaKey:
1022
0
            bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
1023
0
            break;
1024
0
        case dsaKey:
1025
0
            bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.params.prime);
1026
0
            break;
1027
0
        case dhKey:
1028
0
            bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.prime);
1029
0
            break;
1030
0
        case ecKey:
1031
0
            bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
1032
0
            break;
1033
0
        default:
1034
0
            PORT_SetError(SEC_ERROR_INVALID_KEY);
1035
0
            break;
1036
0
    }
1037
0
    return bitSize;
1038
0
}
1039
1040
/* returns signature length in bytes (not bits) */
1041
unsigned
1042
SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
1043
0
{
1044
0
    unsigned char b0;
1045
0
    unsigned size;
1046
0
1047
0
    switch (pubk->keyType) {
1048
0
        case rsaKey:
1049
0
        case rsaPssKey:
1050
0
            b0 = pubk->u.rsa.modulus.data[0];
1051
0
            return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
1052
0
        case dsaKey:
1053
0
            return pubk->u.dsa.params.subPrime.len * 2;
1054
0
        case ecKey:
1055
0
            /* Get the base point order length in bits and adjust */
1056
0
            size = SECKEY_ECParamsToBasePointOrderLen(
1057
0
                &pubk->u.ec.DEREncodedParams);
1058
0
            return ((size + 7) / 8) * 2;
1059
0
        default:
1060
0
            break;
1061
0
    }
1062
0
    PORT_SetError(SEC_ERROR_INVALID_KEY);
1063
0
    return 0;
1064
0
}
1065
1066
SECKEYPrivateKey *
1067
SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
1068
0
{
1069
0
    SECKEYPrivateKey *copyk;
1070
0
    PLArenaPool *arena;
1071
0
1072
0
    if (!privk || !privk->pkcs11Slot) {
1073
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1074
0
        return NULL;
1075
0
    }
1076
0
1077
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1078
0
    if (arena == NULL) {
1079
0
        return NULL;
1080
0
    }
1081
0
1082
0
    copyk = (SECKEYPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
1083
0
    if (copyk) {
1084
0
        copyk->arena = arena;
1085
0
        copyk->keyType = privk->keyType;
1086
0
1087
0
        /* copy the PKCS #11 parameters */
1088
0
        copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
1089
0
        /* if the key we're referencing was a temparary key we have just
1090
0
         * created, that we want to go away when we're through, we need
1091
0
         * to make a copy of it */
1092
0
        if (privk->pkcs11IsTemp) {
1093
0
            copyk->pkcs11ID =
1094
0
                PK11_CopyKey(privk->pkcs11Slot, privk->pkcs11ID);
1095
0
            if (copyk->pkcs11ID == CK_INVALID_HANDLE)
1096
0
                goto fail;
1097
0
        } else {
1098
0
            copyk->pkcs11ID = privk->pkcs11ID;
1099
0
        }
1100
0
        copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
1101
0
        copyk->wincx = privk->wincx;
1102
0
        copyk->staticflags = privk->staticflags;
1103
0
        return copyk;
1104
0
    } else {
1105
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1106
0
    }
1107
0
1108
0
fail:
1109
0
    PORT_FreeArena(arena, PR_FALSE);
1110
0
    return NULL;
1111
0
}
1112
1113
SECKEYPublicKey *
1114
SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
1115
0
{
1116
0
    SECKEYPublicKey *copyk;
1117
0
    PLArenaPool *arena;
1118
0
    SECStatus rv = SECSuccess;
1119
0
1120
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1121
0
    if (arena == NULL) {
1122
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1123
0
        return NULL;
1124
0
    }
1125
0
1126
0
    copyk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
1127
0
    if (!copyk) {
1128
0
        PORT_FreeArena(arena, PR_FALSE);
1129
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1130
0
        return NULL;
1131
0
    }
1132
0
1133
0
    copyk->arena = arena;
1134
0
    copyk->keyType = pubk->keyType;
1135
0
    if (pubk->pkcs11Slot &&
1136
0
        PK11_IsPermObject(pubk->pkcs11Slot, pubk->pkcs11ID)) {
1137
0
        copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
1138
0
        copyk->pkcs11ID = pubk->pkcs11ID;
1139
0
    } else {
1140
0
        copyk->pkcs11Slot = NULL; /* go get own reference */
1141
0
        copyk->pkcs11ID = CK_INVALID_HANDLE;
1142
0
    }
1143
0
    switch (pubk->keyType) {
1144
0
        case rsaKey:
1145
0
            rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
1146
0
                                  &pubk->u.rsa.modulus);
1147
0
            if (rv == SECSuccess) {
1148
0
                rv = SECITEM_CopyItem(arena, &copyk->u.rsa.publicExponent,
1149
0
                                      &pubk->u.rsa.publicExponent);
1150
0
                if (rv == SECSuccess)
1151
0
                    return copyk;
1152
0
            }
1153
0
            break;
1154
0
        case dsaKey:
1155
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
1156
0
                                  &pubk->u.dsa.publicValue);
1157
0
            if (rv != SECSuccess)
1158
0
                break;
1159
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
1160
0
                                  &pubk->u.dsa.params.prime);
1161
0
            if (rv != SECSuccess)
1162
0
                break;
1163
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
1164
0
                                  &pubk->u.dsa.params.subPrime);
1165
0
            if (rv != SECSuccess)
1166
0
                break;
1167
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
1168
0
                                  &pubk->u.dsa.params.base);
1169
0
            break;
1170
0
        case dhKey:
1171
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dh.prime, &pubk->u.dh.prime);
1172
0
            if (rv != SECSuccess)
1173
0
                break;
1174
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dh.base, &pubk->u.dh.base);
1175
0
            if (rv != SECSuccess)
1176
0
                break;
1177
0
            rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue,
1178
0
                                  &pubk->u.dh.publicValue);
1179
0
            break;
1180
0
        case ecKey:
1181
0
            copyk->u.ec.size = pubk->u.ec.size;
1182
0
            rv = seckey_HasCurveOID(pubk);
1183
0
            if (rv != SECSuccess) {
1184
0
                break;
1185
0
            }
1186
0
            rv = SECITEM_CopyItem(arena, &copyk->u.ec.DEREncodedParams,
1187
0
                                  &pubk->u.ec.DEREncodedParams);
1188
0
            if (rv != SECSuccess) {
1189
0
                break;
1190
0
            }
1191
0
            copyk->u.ec.encoding = ECPoint_Undefined;
1192
0
            rv = SECITEM_CopyItem(arena, &copyk->u.ec.publicValue,
1193
0
                                  &pubk->u.ec.publicValue);
1194
0
            break;
1195
0
        case nullKey:
1196
0
            return copyk;
1197
0
        default:
1198
0
            PORT_SetError(SEC_ERROR_INVALID_KEY);
1199
0
            rv = SECFailure;
1200
0
            break;
1201
0
    }
1202
0
    if (rv == SECSuccess)
1203
0
        return copyk;
1204
0
1205
0
    SECKEY_DestroyPublicKey(copyk);
1206
0
    return NULL;
1207
0
}
1208
1209
SECKEYPublicKey *
1210
SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
1211
0
{
1212
0
    SECKEYPublicKey *pubk;
1213
0
    PLArenaPool *arena;
1214
0
    CERTCertificate *cert;
1215
0
    SECStatus rv;
1216
0
1217
0
    /*
1218
0
     * First try to look up the cert.
1219
0
     */
1220
0
    cert = PK11_GetCertFromPrivateKey(privk);
1221
0
    if (cert) {
1222
0
        pubk = CERT_ExtractPublicKey(cert);
1223
0
        CERT_DestroyCertificate(cert);
1224
0
        return pubk;
1225
0
    }
1226
0
1227
0
    /* couldn't find the cert, build pub key by hand */
1228
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1229
0
    if (arena == NULL) {
1230
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1231
0
        return NULL;
1232
0
    }
1233
0
    pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
1234
0
                                               sizeof(SECKEYPublicKey));
1235
0
    if (pubk == NULL) {
1236
0
        PORT_FreeArena(arena, PR_FALSE);
1237
0
        return NULL;
1238
0
    }
1239
0
    pubk->keyType = privk->keyType;
1240
0
    pubk->pkcs11Slot = NULL;
1241
0
    pubk->pkcs11ID = CK_INVALID_HANDLE;
1242
0
    pubk->arena = arena;
1243
0
1244
0
    switch (privk->keyType) {
1245
0
        case nullKey:
1246
0
        case dhKey:
1247
0
        case dsaKey:
1248
0
            /* Nothing to query, if the cert isn't there, we're done -- no way
1249
0
             * to get the public key */
1250
0
            break;
1251
0
        case rsaKey:
1252
0
            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
1253
0
                                    CKA_MODULUS, arena, &pubk->u.rsa.modulus);
1254
0
            if (rv != SECSuccess)
1255
0
                break;
1256
0
            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
1257
0
                                    CKA_PUBLIC_EXPONENT, arena, &pubk->u.rsa.publicExponent);
1258
0
            if (rv != SECSuccess)
1259
0
                break;
1260
0
            return pubk;
1261
0
            break;
1262
0
        case ecKey:
1263
0
            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
1264
0
                                    CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
1265
0
            if (rv != SECSuccess) {
1266
0
                break;
1267
0
            }
1268
0
            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
1269
0
                                    CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
1270
0
            if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) {
1271
0
                break;
1272
0
            }
1273
0
            pubk->u.ec.encoding = ECPoint_Undefined;
1274
0
            return pubk;
1275
0
        default:
1276
0
            break;
1277
0
    }
1278
0
1279
0
    PORT_FreeArena(arena, PR_FALSE);
1280
0
    return NULL;
1281
0
}
1282
1283
static CERTSubjectPublicKeyInfo *
1284
seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk)
1285
0
{
1286
0
    CERTSubjectPublicKeyInfo *spki;
1287
0
    PLArenaPool *arena;
1288
0
    SECItem params = { siBuffer, NULL, 0 };
1289
0
1290
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1291
0
    if (arena == NULL) {
1292
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1293
0
        return NULL;
1294
0
    }
1295
0
1296
0
    spki = (CERTSubjectPublicKeyInfo *)PORT_ArenaZAlloc(arena, sizeof(*spki));
1297
0
    if (spki != NULL) {
1298
0
        SECStatus rv;
1299
0
        SECItem *rv_item;
1300
0
1301
0
        spki->arena = arena;
1302
0
        switch (pubk->keyType) {
1303
0
            case rsaKey:
1304
0
                rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
1305
0
                                           SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
1306
0
                if (rv == SECSuccess) {
1307
0
                    /*
1308
0
                     * DER encode the public key into the subjectPublicKeyInfo.
1309
0
                     */
1310
0
                    prepare_rsa_pub_key_for_asn1(pubk);
1311
0
                    rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
1312
0
                                                 pubk, SECKEY_RSAPublicKeyTemplate);
1313
0
                    if (rv_item != NULL) {
1314
0
                        /*
1315
0
                         * The stored value is supposed to be a BIT_STRING,
1316
0
                         * so convert the length.
1317
0
                         */
1318
0
                        spki->subjectPublicKey.len <<= 3;
1319
0
                        /*
1320
0
                         * We got a good one; return it.
1321
0
                         */
1322
0
                        return spki;
1323
0
                    }
1324
0
                }
1325
0
                break;
1326
0
            case dsaKey:
1327
0
                /* DER encode the params. */
1328
0
                prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
1329
0
                rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
1330
0
                                             SECKEY_PQGParamsTemplate);
1331
0
                if (rv_item != NULL) {
1332
0
                    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
1333
0
                                               SEC_OID_ANSIX9_DSA_SIGNATURE,
1334
0
                                               &params);
1335
0
                    if (rv == SECSuccess) {
1336
0
                        /*
1337
0
                         * DER encode the public key into the subjectPublicKeyInfo.
1338
0
                         */
1339
0
                        prepare_dsa_pub_key_for_asn1(pubk);
1340
0
                        rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
1341
0
                                                     pubk,
1342
0
                                                     SECKEY_DSAPublicKeyTemplate);
1343
0
                        if (rv_item != NULL) {
1344
0
                            /*
1345
0
                             * The stored value is supposed to be a BIT_STRING,
1346
0
                             * so convert the length.
1347
0
                             */
1348
0
                            spki->subjectPublicKey.len <<= 3;
1349
0
                            /*
1350
0
                             * We got a good one; return it.
1351
0
                             */
1352
0
                            return spki;
1353
0
                        }
1354
0
                    }
1355
0
                }
1356
0
                SECITEM_FreeItem(&params, PR_FALSE);
1357
0
                break;
1358
0
            case ecKey:
1359
0
                rv = SECITEM_CopyItem(arena, &params,
1360
0
                                      &pubk->u.ec.DEREncodedParams);
1361
0
                if (rv != SECSuccess)
1362
0
                    break;
1363
0
1364
0
                rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
1365
0
                                           SEC_OID_ANSIX962_EC_PUBLIC_KEY,
1366
0
                                           &params);
1367
0
                if (rv != SECSuccess)
1368
0
                    break;
1369
0
1370
0
                rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
1371
0
                                      &pubk->u.ec.publicValue);
1372
0
1373
0
                if (rv == SECSuccess) {
1374
0
                    /*
1375
0
                     * The stored value is supposed to be a BIT_STRING,
1376
0
                     * so convert the length.
1377
0
                     */
1378
0
                    spki->subjectPublicKey.len <<= 3;
1379
0
                    /*
1380
0
                     * We got a good one; return it.
1381
0
                     */
1382
0
                    return spki;
1383
0
                }
1384
0
                break;
1385
0
            case dhKey: /* later... */
1386
0
1387
0
                break;
1388
0
            default:
1389
0
                break;
1390
0
        }
1391
0
    } else {
1392
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1393
0
    }
1394
0
1395
0
    PORT_FreeArena(arena, PR_FALSE);
1396
0
    return NULL;
1397
0
}
1398
1399
CERTSubjectPublicKeyInfo *
1400
SECKEY_CreateSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
1401
0
{
1402
0
    CERTSubjectPublicKeyInfo *spki;
1403
0
    SECKEYPublicKey *tempKey;
1404
0
1405
0
    if (!pubk) {
1406
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1407
0
        return NULL;
1408
0
    }
1409
0
1410
0
    tempKey = SECKEY_CopyPublicKey(pubk);
1411
0
    if (!tempKey) {
1412
0
        return NULL;
1413
0
    }
1414
0
    spki = seckey_CreateSubjectPublicKeyInfo_helper(tempKey);
1415
0
    SECKEY_DestroyPublicKey(tempKey);
1416
0
    return spki;
1417
0
}
1418
1419
void
1420
SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
1421
0
{
1422
0
    if (spki && spki->arena) {
1423
0
        PORT_FreeArena(spki->arena, PR_FALSE);
1424
0
    }
1425
0
}
1426
1427
SECItem *
1428
SECKEY_EncodeDERSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
1429
0
{
1430
0
    CERTSubjectPublicKeyInfo *spki = NULL;
1431
0
    SECItem *spkiDER = NULL;
1432
0
1433
0
    /* get the subjectpublickeyinfo */
1434
0
    spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
1435
0
    if (spki == NULL) {
1436
0
        goto finish;
1437
0
    }
1438
0
1439
0
    /* DER-encode the subjectpublickeyinfo */
1440
0
    spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL /*dest*/, spki,
1441
0
                                 CERT_SubjectPublicKeyInfoTemplate);
1442
0
1443
0
    SECKEY_DestroySubjectPublicKeyInfo(spki);
1444
0
1445
0
finish:
1446
0
    return spkiDER;
1447
0
}
1448
1449
CERTSubjectPublicKeyInfo *
1450
SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider)
1451
0
{
1452
0
    PLArenaPool *arena;
1453
0
    CERTSubjectPublicKeyInfo *spki;
1454
0
    SECStatus rv;
1455
0
    SECItem newSpkider;
1456
0
1457
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1458
0
    if (arena == NULL) {
1459
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1460
0
        return NULL;
1461
0
    }
1462
0
1463
0
    spki = (CERTSubjectPublicKeyInfo *)
1464
0
        PORT_ArenaZAlloc(arena, sizeof(CERTSubjectPublicKeyInfo));
1465
0
    if (spki != NULL) {
1466
0
        spki->arena = arena;
1467
0
1468
0
        /* copy the DER into the arena, since Quick DER returns data that points
1469
0
           into the DER input, which may get freed by the caller */
1470
0
        rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
1471
0
        if (rv == SECSuccess) {
1472
0
            rv = SEC_QuickDERDecodeItem(arena, spki,
1473
0
                                        CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
1474
0
        }
1475
0
        if (rv == SECSuccess)
1476
0
            return spki;
1477
0
    } else {
1478
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1479
0
    }
1480
0
1481
0
    PORT_FreeArena(arena, PR_FALSE);
1482
0
    return NULL;
1483
0
}
1484
1485
/*
1486
 * Decode a base64 ascii encoded DER encoded subject public key info.
1487
 */
1488
CERTSubjectPublicKeyInfo *
1489
SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(const char *spkistr)
1490
0
{
1491
0
    CERTSubjectPublicKeyInfo *spki;
1492
0
    SECStatus rv;
1493
0
    SECItem der;
1494
0
1495
0
    rv = ATOB_ConvertAsciiToItem(&der, spkistr);
1496
0
    if (rv != SECSuccess)
1497
0
        return NULL;
1498
0
1499
0
    spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
1500
0
1501
0
    PORT_Free(der.data);
1502
0
    return spki;
1503
0
}
1504
1505
/*
1506
 * Decode a base64 ascii encoded DER encoded public key and challenge
1507
 * Verify digital signature and make sure challenge matches
1508
 */
1509
CERTSubjectPublicKeyInfo *
1510
SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
1511
                                             void *wincx)
1512
0
{
1513
0
    CERTSubjectPublicKeyInfo *spki = NULL;
1514
0
    CERTPublicKeyAndChallenge pkac;
1515
0
    SECStatus rv;
1516
0
    SECItem signedItem;
1517
0
    PLArenaPool *arena = NULL;
1518
0
    CERTSignedData sd;
1519
0
    SECItem sig;
1520
0
    SECKEYPublicKey *pubKey = NULL;
1521
0
    unsigned int len;
1522
0
1523
0
    signedItem.data = NULL;
1524
0
1525
0
    /* convert the base64 encoded data to binary */
1526
0
    rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
1527
0
    if (rv != SECSuccess) {
1528
0
        goto loser;
1529
0
    }
1530
0
1531
0
    /* create an arena */
1532
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1533
0
    if (arena == NULL) {
1534
0
        goto loser;
1535
0
    }
1536
0
1537
0
    /* decode the outer wrapping of signed data */
1538
0
    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
1539
0
    rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem);
1540
0
    if (rv) {
1541
0
        goto loser;
1542
0
    }
1543
0
1544
0
    /* decode the public key and challenge wrapper */
1545
0
    PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
1546
0
    rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate,
1547
0
                                &sd.data);
1548
0
    if (rv) {
1549
0
        goto loser;
1550
0
    }
1551
0
1552
0
    /* decode the subject public key info */
1553
0
    spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
1554
0
    if (spki == NULL) {
1555
0
        goto loser;
1556
0
    }
1557
0
1558
0
    /* get the public key */
1559
0
    pubKey = seckey_ExtractPublicKey(spki);
1560
0
    if (pubKey == NULL) {
1561
0
        goto loser;
1562
0
    }
1563
0
1564
0
    /* check the signature */
1565
0
    sig = sd.signature;
1566
0
    DER_ConvertBitString(&sig);
1567
0
    rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
1568
0
                                       &(sd.signatureAlgorithm), NULL, wincx);
1569
0
    if (rv != SECSuccess) {
1570
0
        goto loser;
1571
0
    }
1572
0
1573
0
    /* check the challenge */
1574
0
    if (challenge) {
1575
0
        len = PORT_Strlen(challenge);
1576
0
        /* length is right */
1577
0
        if (len != pkac.challenge.len) {
1578
0
            goto loser;
1579
0
        }
1580
0
        /* actual data is right */
1581
0
        if (PORT_Memcmp(challenge, pkac.challenge.data, len) != 0) {
1582
0
            goto loser;
1583
0
        }
1584
0
    }
1585
0
    goto done;
1586
0
1587
0
loser:
1588
0
    /* make sure that we return null if we got an error */
1589
0
    if (spki) {
1590
0
        SECKEY_DestroySubjectPublicKeyInfo(spki);
1591
0
    }
1592
0
    spki = NULL;
1593
0
1594
0
done:
1595
0
    if (signedItem.data) {
1596
0
        PORT_Free(signedItem.data);
1597
0
    }
1598
0
    if (arena) {
1599
0
        PORT_FreeArena(arena, PR_FALSE);
1600
0
    }
1601
0
    if (pubKey) {
1602
0
        SECKEY_DestroyPublicKey(pubKey);
1603
0
    }
1604
0
1605
0
    return spki;
1606
0
}
1607
1608
void
1609
SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
1610
                             PRBool freeit)
1611
0
{
1612
0
    PLArenaPool *poolp;
1613
0
1614
0
    if (pvk != NULL) {
1615
0
        if (pvk->arena) {
1616
0
            poolp = pvk->arena;
1617
0
            /* zero structure since PORT_FreeArena does not support
1618
0
             * this yet.
1619
0
             */
1620
0
            PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
1621
0
            PORT_Memset(pvk, 0, sizeof(*pvk));
1622
0
            if (freeit == PR_TRUE) {
1623
0
                PORT_FreeArena(poolp, PR_TRUE);
1624
0
            } else {
1625
0
                pvk->arena = poolp;
1626
0
            }
1627
0
        } else {
1628
0
            SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
1629
0
            SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
1630
0
            SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
1631
0
            PORT_Memset(pvk, 0, sizeof(*pvk));
1632
0
            if (freeit == PR_TRUE) {
1633
0
                PORT_Free(pvk);
1634
0
            }
1635
0
        }
1636
0
    }
1637
0
}
1638
1639
void
1640
SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
1641
                                      PRBool freeit)
1642
0
{
1643
0
    PLArenaPool *poolp;
1644
0
1645
0
    if (epki != NULL) {
1646
0
        if (epki->arena) {
1647
0
            poolp = epki->arena;
1648
0
            /* zero structure since PORT_FreeArena does not support
1649
0
             * this yet.
1650
0
             */
1651
0
            PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
1652
0
            PORT_Memset(epki, 0, sizeof(*epki));
1653
0
            if (freeit == PR_TRUE) {
1654
0
                PORT_FreeArena(poolp, PR_TRUE);
1655
0
            } else {
1656
0
                epki->arena = poolp;
1657
0
            }
1658
0
        } else {
1659
0
            SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
1660
0
            SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
1661
0
            PORT_Memset(epki, 0, sizeof(*epki));
1662
0
            if (freeit == PR_TRUE) {
1663
0
                PORT_Free(epki);
1664
0
            }
1665
0
        }
1666
0
    }
1667
0
}
1668
1669
SECStatus
1670
SECKEY_CopyPrivateKeyInfo(PLArenaPool *poolp,
1671
                          SECKEYPrivateKeyInfo *to,
1672
                          const SECKEYPrivateKeyInfo *from)
1673
0
{
1674
0
    SECStatus rv = SECFailure;
1675
0
1676
0
    if ((to == NULL) || (from == NULL)) {
1677
0
        return SECFailure;
1678
0
    }
1679
0
1680
0
    rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
1681
0
    if (rv != SECSuccess) {
1682
0
        return SECFailure;
1683
0
    }
1684
0
    rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
1685
0
    if (rv != SECSuccess) {
1686
0
        return SECFailure;
1687
0
    }
1688
0
    rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
1689
0
1690
0
    return rv;
1691
0
}
1692
1693
SECStatus
1694
SECKEY_CopyEncryptedPrivateKeyInfo(PLArenaPool *poolp,
1695
                                   SECKEYEncryptedPrivateKeyInfo *to,
1696
                                   const SECKEYEncryptedPrivateKeyInfo *from)
1697
0
{
1698
0
    SECStatus rv = SECFailure;
1699
0
1700
0
    if ((to == NULL) || (from == NULL)) {
1701
0
        return SECFailure;
1702
0
    }
1703
0
1704
0
    rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
1705
0
    if (rv != SECSuccess) {
1706
0
        return SECFailure;
1707
0
    }
1708
0
    rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
1709
0
1710
0
    return rv;
1711
0
}
1712
1713
KeyType
1714
SECKEY_GetPrivateKeyType(const SECKEYPrivateKey *privKey)
1715
0
{
1716
0
    return privKey->keyType;
1717
0
}
1718
1719
KeyType
1720
SECKEY_GetPublicKeyType(const SECKEYPublicKey *pubKey)
1721
0
{
1722
0
    return pubKey->keyType;
1723
0
}
1724
1725
SECKEYPublicKey *
1726
SECKEY_ImportDERPublicKey(const SECItem *derKey, CK_KEY_TYPE type)
1727
0
{
1728
0
    SECKEYPublicKey *pubk = NULL;
1729
0
    SECStatus rv = SECFailure;
1730
0
    SECItem newDerKey;
1731
0
    PLArenaPool *arena = NULL;
1732
0
1733
0
    if (!derKey) {
1734
0
        return NULL;
1735
0
    }
1736
0
1737
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1738
0
    if (arena == NULL) {
1739
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1740
0
        goto finish;
1741
0
    }
1742
0
1743
0
    pubk = PORT_ArenaZNew(arena, SECKEYPublicKey);
1744
0
    if (pubk == NULL) {
1745
0
        goto finish;
1746
0
    }
1747
0
    pubk->arena = arena;
1748
0
1749
0
    rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
1750
0
    if (SECSuccess != rv) {
1751
0
        goto finish;
1752
0
    }
1753
0
1754
0
    pubk->pkcs11Slot = NULL;
1755
0
    pubk->pkcs11ID = CK_INVALID_HANDLE;
1756
0
1757
0
    switch (type) {
1758
0
        case CKK_RSA:
1759
0
            prepare_rsa_pub_key_for_asn1(pubk);
1760
0
            rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
1761
0
            pubk->keyType = rsaKey;
1762
0
            break;
1763
0
        case CKK_DSA:
1764
0
            prepare_dsa_pub_key_for_asn1(pubk);
1765
0
            rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
1766
0
            pubk->keyType = dsaKey;
1767
0
            break;
1768
0
        case CKK_DH:
1769
0
            prepare_dh_pub_key_for_asn1(pubk);
1770
0
            rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
1771
0
            pubk->keyType = dhKey;
1772
0
            break;
1773
0
        default:
1774
0
            rv = SECFailure;
1775
0
            break;
1776
0
    }
1777
0
1778
0
finish:
1779
0
    if (rv != SECSuccess) {
1780
0
        if (arena != NULL) {
1781
0
            PORT_FreeArena(arena, PR_FALSE);
1782
0
        }
1783
0
        pubk = NULL;
1784
0
    }
1785
0
    return pubk;
1786
0
}
1787
1788
SECKEYPrivateKeyList *
1789
SECKEY_NewPrivateKeyList(void)
1790
0
{
1791
0
    PLArenaPool *arena = NULL;
1792
0
    SECKEYPrivateKeyList *ret = NULL;
1793
0
1794
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1795
0
    if (arena == NULL) {
1796
0
        goto loser;
1797
0
    }
1798
0
1799
0
    ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
1800
0
                                                   sizeof(SECKEYPrivateKeyList));
1801
0
    if (ret == NULL) {
1802
0
        goto loser;
1803
0
    }
1804
0
1805
0
    ret->arena = arena;
1806
0
1807
0
    PR_INIT_CLIST(&ret->list);
1808
0
1809
0
    return (ret);
1810
0
1811
0
loser:
1812
0
    if (arena != NULL) {
1813
0
        PORT_FreeArena(arena, PR_FALSE);
1814
0
    }
1815
0
1816
0
    return (NULL);
1817
0
}
1818
1819
void
1820
SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys)
1821
0
{
1822
0
    while (!PR_CLIST_IS_EMPTY(&keys->list)) {
1823
0
        SECKEY_RemovePrivateKeyListNode(
1824
0
            (SECKEYPrivateKeyListNode *)(PR_LIST_HEAD(&keys->list)));
1825
0
    }
1826
0
1827
0
    PORT_FreeArena(keys->arena, PR_FALSE);
1828
0
1829
0
    return;
1830
0
}
1831
1832
void
1833
SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node)
1834
0
{
1835
0
    PR_ASSERT(node->key);
1836
0
    SECKEY_DestroyPrivateKey(node->key);
1837
0
    node->key = NULL;
1838
0
    PR_REMOVE_LINK(&node->links);
1839
0
    return;
1840
0
}
1841
1842
SECStatus
1843
SECKEY_AddPrivateKeyToListTail(SECKEYPrivateKeyList *list,
1844
                               SECKEYPrivateKey *key)
1845
0
{
1846
0
    SECKEYPrivateKeyListNode *node;
1847
0
1848
0
    node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena,
1849
0
                                                        sizeof(SECKEYPrivateKeyListNode));
1850
0
    if (node == NULL) {
1851
0
        goto loser;
1852
0
    }
1853
0
1854
0
    PR_INSERT_BEFORE(&node->links, &list->list);
1855
0
    node->key = key;
1856
0
    return (SECSuccess);
1857
0
1858
0
loser:
1859
0
    return (SECFailure);
1860
0
}
1861
1862
SECKEYPublicKeyList *
1863
SECKEY_NewPublicKeyList(void)
1864
0
{
1865
0
    PLArenaPool *arena = NULL;
1866
0
    SECKEYPublicKeyList *ret = NULL;
1867
0
1868
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1869
0
    if (arena == NULL) {
1870
0
        goto loser;
1871
0
    }
1872
0
1873
0
    ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena,
1874
0
                                                  sizeof(SECKEYPublicKeyList));
1875
0
    if (ret == NULL) {
1876
0
        goto loser;
1877
0
    }
1878
0
1879
0
    ret->arena = arena;
1880
0
1881
0
    PR_INIT_CLIST(&ret->list);
1882
0
1883
0
    return (ret);
1884
0
1885
0
loser:
1886
0
    if (arena != NULL) {
1887
0
        PORT_FreeArena(arena, PR_FALSE);
1888
0
    }
1889
0
1890
0
    return (NULL);
1891
0
}
1892
1893
void
1894
SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys)
1895
0
{
1896
0
    while (!PR_CLIST_IS_EMPTY(&keys->list)) {
1897
0
        SECKEY_RemovePublicKeyListNode(
1898
0
            (SECKEYPublicKeyListNode *)(PR_LIST_HEAD(&keys->list)));
1899
0
    }
1900
0
1901
0
    PORT_FreeArena(keys->arena, PR_FALSE);
1902
0
1903
0
    return;
1904
0
}
1905
1906
void
1907
SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node)
1908
0
{
1909
0
    PR_ASSERT(node->key);
1910
0
    SECKEY_DestroyPublicKey(node->key);
1911
0
    node->key = NULL;
1912
0
    PR_REMOVE_LINK(&node->links);
1913
0
    return;
1914
0
}
1915
1916
SECStatus
1917
SECKEY_AddPublicKeyToListTail(SECKEYPublicKeyList *list,
1918
                              SECKEYPublicKey *key)
1919
0
{
1920
0
    SECKEYPublicKeyListNode *node;
1921
0
1922
0
    node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena,
1923
0
                                                       sizeof(SECKEYPublicKeyListNode));
1924
0
    if (node == NULL) {
1925
0
        goto loser;
1926
0
    }
1927
0
1928
0
    PR_INSERT_BEFORE(&node->links, &list->list);
1929
0
    node->key = key;
1930
0
    return (SECSuccess);
1931
0
1932
0
loser:
1933
0
    return (SECFailure);
1934
0
}
1935
1936
#define SECKEY_CacheAttribute(key, attribute)                                                   \
1937
0
    if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \
1938
0
        key->staticflags |= SECKEY_##attribute;                                                 \
1939
0
    } else {                                                                                    \
1940
0
        key->staticflags &= (~SECKEY_##attribute);                                              \
1941
0
    }
1942
1943
SECStatus
1944
SECKEY_CacheStaticFlags(SECKEYPrivateKey *key)
1945
0
{
1946
0
    SECStatus rv = SECFailure;
1947
0
    if (key && key->pkcs11Slot && key->pkcs11ID) {
1948
0
        key->staticflags |= SECKEY_Attributes_Cached;
1949
0
        SECKEY_CacheAttribute(key, CKA_PRIVATE);
1950
0
        SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE);
1951
0
        rv = SECSuccess;
1952
0
    }
1953
0
    return rv;
1954
0
}
1955
1956
SECOidTag
1957
SECKEY_GetECCOid(const SECKEYECParams *params)
1958
0
{
1959
0
    SECItem oid = { siBuffer, NULL, 0 };
1960
0
    SECOidData *oidData = NULL;
1961
0
1962
0
    /*
1963
0
     * params->data needs to contain the ASN encoding of an object ID (OID)
1964
0
     * representing a named curve. Here, we strip away everything
1965
0
     * before the actual OID and use the OID to look up a named curve.
1966
0
     */
1967
0
    if (params->data[0] != SEC_ASN1_OBJECT_ID)
1968
0
        return 0;
1969
0
    oid.len = params->len - 2;
1970
0
    oid.data = params->data + 2;
1971
0
    if ((oidData = SECOID_FindOID(&oid)) == NULL)
1972
0
        return 0;
1973
0
1974
0
    return oidData->offset;
1975
0
}
1976
1977
static CK_MECHANISM_TYPE
1978
sec_GetHashMechanismByOidTag(SECOidTag tag)
1979
0
{
1980
0
    switch (tag) {
1981
0
        case SEC_OID_SHA512:
1982
0
            return CKM_SHA512;
1983
0
        case SEC_OID_SHA384:
1984
0
            return CKM_SHA384;
1985
0
        case SEC_OID_SHA256:
1986
0
            return CKM_SHA256;
1987
0
        case SEC_OID_SHA224:
1988
0
            return CKM_SHA224;
1989
0
        case SEC_OID_SHA1:
1990
0
            return CKM_SHA_1;
1991
0
        default:
1992
0
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1993
0
            return CKM_INVALID_MECHANISM;
1994
0
    }
1995
0
}
1996
1997
static CK_RSA_PKCS_MGF_TYPE
1998
sec_GetMgfTypeByOidTag(SECOidTag tag)
1999
0
{
2000
0
    switch (tag) {
2001
0
        case SEC_OID_SHA512:
2002
0
            return CKG_MGF1_SHA512;
2003
0
        case SEC_OID_SHA384:
2004
0
            return CKG_MGF1_SHA384;
2005
0
        case SEC_OID_SHA256:
2006
0
            return CKG_MGF1_SHA256;
2007
0
        case SEC_OID_SHA224:
2008
0
            return CKG_MGF1_SHA224;
2009
0
        case SEC_OID_SHA1:
2010
0
            return CKG_MGF1_SHA1;
2011
0
        default:
2012
0
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
2013
0
            return 0;
2014
0
    }
2015
0
}
2016
2017
SECStatus
2018
sec_RSAPSSParamsToMechanism(CK_RSA_PKCS_PSS_PARAMS *mech,
2019
                            const SECKEYRSAPSSParams *params)
2020
0
{
2021
0
    SECStatus rv = SECSuccess;
2022
0
    SECOidTag hashAlgTag;
2023
0
    unsigned long saltLength;
2024
0
    unsigned long trailerField;
2025
0
2026
0
    PORT_Memset(mech, 0, sizeof(CK_RSA_PKCS_PSS_PARAMS));
2027
0
2028
0
    if (params->hashAlg) {
2029
0
        hashAlgTag = SECOID_GetAlgorithmTag(params->hashAlg);
2030
0
    } else {
2031
0
        hashAlgTag = SEC_OID_SHA1; /* default, SHA-1 */
2032
0
    }
2033
0
    mech->hashAlg = sec_GetHashMechanismByOidTag(hashAlgTag);
2034
0
    if (mech->hashAlg == CKM_INVALID_MECHANISM) {
2035
0
        return SECFailure;
2036
0
    }
2037
0
2038
0
    if (params->maskAlg) {
2039
0
        SECAlgorithmID maskHashAlg;
2040
0
        SECOidTag maskHashAlgTag;
2041
0
        PORTCheapArenaPool tmpArena;
2042
0
2043
0
        if (SECOID_GetAlgorithmTag(params->maskAlg) != SEC_OID_PKCS1_MGF1) {
2044
0
            /* only MGF1 is known to PKCS#11 */
2045
0
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
2046
0
            return SECFailure;
2047
0
        }
2048
0
2049
0
        PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
2050
0
        rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &maskHashAlg,
2051
0
                                    SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
2052
0
                                    &params->maskAlg->parameters);
2053
0
        PORT_DestroyCheapArena(&tmpArena);
2054
0
        if (rv != SECSuccess) {
2055
0
            return rv;
2056
0
        }
2057
0
        maskHashAlgTag = SECOID_GetAlgorithmTag(&maskHashAlg);
2058
0
        mech->mgf = sec_GetMgfTypeByOidTag(maskHashAlgTag);
2059
0
        if (mech->mgf == 0) {
2060
0
            return SECFailure;
2061
0
        }
2062
0
    } else {
2063
0
        mech->mgf = CKG_MGF1_SHA1; /* default, MGF1 with SHA-1 */
2064
0
    }
2065
0
2066
0
    if (params->saltLength.data) {
2067
0
        rv = SEC_ASN1DecodeInteger((SECItem *)&params->saltLength, &saltLength);
2068
0
        if (rv != SECSuccess) {
2069
0
            return rv;
2070
0
        }
2071
0
    } else {
2072
0
        saltLength = 20; /* default, 20 */
2073
0
    }
2074
0
    mech->sLen = saltLength;
2075
0
2076
0
    if (params->trailerField.data) {
2077
0
        rv = SEC_ASN1DecodeInteger((SECItem *)&params->trailerField, &trailerField);
2078
0
        if (rv != SECSuccess) {
2079
0
            return rv;
2080
0
        }
2081
0
        if (trailerField != 1) {
2082
0
            /* the value must be 1, which represents the trailer field
2083
0
             * with hexadecimal value 0xBC */
2084
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
2085
0
            return SECFailure;
2086
0
        }
2087
0
    }
2088
0
2089
0
    return rv;
2090
0
}