Coverage Report

Created: 2026-06-07 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/softoken/lowkey.c
Line
Count
Source
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 "lowkeyi.h"
5
#include "secoid.h"
6
#include "secitem.h"
7
#include "secder.h"
8
#include "base64.h"
9
#include "secasn1.h"
10
#include "secerr.h"
11
#include "softoken.h"
12
#include "ec.h"
13
#include "kem.h"
14
15
SEC_ASN1_MKSUB(SEC_AnyTemplate)
16
SEC_ASN1_MKSUB(SEC_BitStringTemplate)
17
SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
18
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
19
SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
20
21
const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
22
    { SEC_ASN1_SEQUENCE,
23
      0, NULL, sizeof(NSSLOWKEYAttribute) },
24
    { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
25
    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
26
      offsetof(NSSLOWKEYAttribute, attrValue),
27
      SEC_ASN1_SUB(SEC_AnyTemplate) },
28
    { 0 }
29
};
30
31
const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
32
    { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
33
};
34
/* ASN1 Templates for new decoder/encoder */
35
const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
36
    { SEC_ASN1_SEQUENCE,
37
      0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
38
    { SEC_ASN1_INTEGER,
39
      offsetof(NSSLOWKEYPrivateKeyInfo, version) },
40
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
41
      offsetof(NSSLOWKEYPrivateKeyInfo, algorithm),
42
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
43
    { SEC_ASN1_OCTET_STRING,
44
      offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) },
45
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
46
      offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
47
      nsslowkey_SetOfAttributeTemplate },
48
    { 0 }
49
};
50
51
const SEC_ASN1Template nsslowkey_SubjectPublicKeyInfoTemplate[] = {
52
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYSubjectPublicKeyInfo) },
53
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
54
      offsetof(NSSLOWKEYSubjectPublicKeyInfo, algorithm),
55
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
56
    { SEC_ASN1_BIT_STRING,
57
      offsetof(NSSLOWKEYSubjectPublicKeyInfo, subjectPublicKey) },
58
    { 0 }
59
};
60
61
const SEC_ASN1Template nsslowkey_RSAPublicKeyTemplate[] = {
62
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
63
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) },
64
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) },
65
    { 0 }
66
};
67
68
const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
69
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
70
    { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) },
71
    { SEC_ASN1_INTEGER, offsetof(PQGParams, subPrime) },
72
    { SEC_ASN1_INTEGER, offsetof(PQGParams, base) },
73
    { 0 }
74
};
75
76
const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
77
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
78
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
79
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
80
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
81
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) },
82
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
83
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
84
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
85
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
86
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
87
    { 0 }
88
};
89
90
const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
91
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
92
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) },
93
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
94
    { 0 }
95
};
96
97
const SEC_ASN1Template nsslowkey_PQBothSeedAndPrivateKeyTemplate[] = {
98
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
99
    { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem) },
100
    { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem) },
101
    { 0 }
102
};
103
104
const SEC_ASN1Template nsslowkey_PQSeedTemplate[] = {
105
    /* the explicit | 0 here is source code doumentation, tell
106
     * clang warnings to let it ride */
107
    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, // NOLINT(misc-redundant-expression)
108
      offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem),
109
      SEC_ASN1_SUB(SEC_OctetStringTemplate) },
110
    { 0 }
111
};
112
const SEC_ASN1Template nsslowkey_PQPrivateKeyTemplate[] = {
113
    { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem) },
114
    { 0 }
115
};
116
117
const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
118
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
119
};
120
121
const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
122
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
123
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) },
124
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) },
125
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.base) },
126
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.prime) },
127
    { 0 }
128
};
129
130
/* NOTE: The SECG specification allows the private key structure
131
 * to contain curve parameters but recommends that they be stored
132
 * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
133
 * instead.
134
 */
135
const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
136
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
137
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.ec.version) },
138
    { SEC_ASN1_OCTET_STRING,
139
      offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) },
140
    /* We only support named curves for which the parameters are
141
     * encoded as an object ID.
142
     */
143
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
144
          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
145
          SEC_ASN1_XTRN | 0,
146
      offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID),
147
      SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
148
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
149
          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
150
          SEC_ASN1_XTRN | 1,
151
      offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue),
152
      SEC_ASN1_SUB(SEC_BitStringTemplate) },
153
    { 0 }
154
};
155
/*
156
 * See bugzilla bug 125359
157
 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
158
 * all of the templates above that en/decode into integers must be converted
159
 * from ASN.1's signed integer type.  This is done by marking either the
160
 * source or destination (encoding or decoding, respectively) type as
161
 * siUnsignedInteger.
162
 */
163
164
void
165
prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
166
0
{
167
0
    key->u.rsa.modulus.type = siUnsignedInteger;
168
0
    key->u.rsa.publicExponent.type = siUnsignedInteger;
169
0
    key->u.rsa.privateExponent.type = siUnsignedInteger;
170
0
    key->u.rsa.prime1.type = siUnsignedInteger;
171
0
    key->u.rsa.prime2.type = siUnsignedInteger;
172
0
    key->u.rsa.exponent1.type = siUnsignedInteger;
173
0
    key->u.rsa.exponent2.type = siUnsignedInteger;
174
0
    key->u.rsa.coefficient.type = siUnsignedInteger;
175
0
}
176
177
void
178
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *key)
179
0
{
180
0
    key->u.rsa.modulus.type = siUnsignedInteger;
181
0
    key->u.rsa.publicExponent.type = siUnsignedInteger;
182
0
}
183
184
void
185
prepare_low_pqg_params_for_asn1(PQGParams *params)
186
0
{
187
0
    params->prime.type = siUnsignedInteger;
188
0
    params->subPrime.type = siUnsignedInteger;
189
0
    params->base.type = siUnsignedInteger;
190
0
}
191
192
void
193
prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
194
0
{
195
0
    key->u.dsa.publicValue.type = siUnsignedInteger;
196
0
    key->u.dsa.privateValue.type = siUnsignedInteger;
197
0
    key->u.dsa.params.prime.type = siUnsignedInteger;
198
0
    key->u.dsa.params.subPrime.type = siUnsignedInteger;
199
0
    key->u.dsa.params.base.type = siUnsignedInteger;
200
0
}
201
202
void
203
prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
204
0
{
205
0
    key->u.dsa.privateValue.type = siUnsignedInteger;
206
0
}
207
208
void
209
prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
210
0
{
211
0
    key->u.dh.prime.type = siUnsignedInteger;
212
0
    key->u.dh.base.type = siUnsignedInteger;
213
0
    key->u.dh.publicValue.type = siUnsignedInteger;
214
0
    key->u.dh.privateValue.type = siUnsignedInteger;
215
0
}
216
217
void
218
prepare_low_ecparams_for_asn1(ECParams *params)
219
0
{
220
0
    params->DEREncoding.type = siUnsignedInteger;
221
0
    params->curveOID.type = siUnsignedInteger;
222
0
}
223
224
void
225
prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
226
0
{
227
0
    key->u.ec.version.type = siUnsignedInteger;
228
0
    key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
229
0
    key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
230
0
    key->u.ec.privateValue.type = siUnsignedInteger;
231
0
    key->u.ec.publicValue.type = siUnsignedInteger;
232
0
}
233
234
void
235
nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
236
105k
{
237
105k
    if (privk && privk->arena) {
238
105k
        PORT_FreeArena(privk->arena, PR_TRUE);
239
105k
    }
240
105k
}
241
242
void
243
nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
244
148k
{
245
148k
    if (pubk && pubk->arena) {
246
148k
        PORT_FreeArena(pubk->arena, PR_TRUE);
247
148k
    }
248
148k
}
249
unsigned
250
nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
251
15.1k
{
252
    /* interpret modulus length as key strength... in
253
     * fortezza that's the public key length */
254
255
15.1k
    switch (pubk->keyType) {
256
15.1k
        case NSSLOWKEYRSAKey:
257
15.1k
            if (pubk->u.rsa.modulus.len == 0) {
258
0
                return 0;
259
0
            }
260
15.1k
            if (pubk->u.rsa.modulus.data[0] == 0) {
261
0
                return pubk->u.rsa.modulus.len - 1;
262
0
            }
263
15.1k
            return pubk->u.rsa.modulus.len;
264
0
        default:
265
0
            break;
266
15.1k
    }
267
0
    return 0;
268
15.1k
}
269
270
unsigned
271
nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
272
113k
{
273
113k
    switch (privk->keyType) {
274
113k
        case NSSLOWKEYRSAKey:
275
113k
            if (privk->u.rsa.modulus.len == 0) {
276
0
                return 0;
277
0
            }
278
113k
            if (privk->u.rsa.modulus.data[0] == 0) {
279
0
                return privk->u.rsa.modulus.len - 1;
280
0
            }
281
113k
            return privk->u.rsa.modulus.len;
282
0
        default:
283
0
            break;
284
113k
    }
285
0
    return 0;
286
113k
}
287
288
NSSLOWKEYPublicKey *
289
nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
290
0
{
291
0
    NSSLOWKEYPublicKey *pubk;
292
0
    SECItem publicValue;
293
0
    PLArenaPool *arena;
294
295
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
296
0
    if (arena == NULL) {
297
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
298
0
        return NULL;
299
0
    }
300
301
0
    switch (privk->keyType) {
302
0
        case NSSLOWKEYRSAKey:
303
0
        case NSSLOWKEYNullKey:
304
0
            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
305
0
                                                          sizeof(NSSLOWKEYPublicKey));
306
0
            if (pubk != NULL) {
307
0
                SECStatus rv;
308
309
0
                pubk->arena = arena;
310
0
                pubk->keyType = privk->keyType;
311
0
                if (privk->keyType == NSSLOWKEYNullKey)
312
0
                    return pubk;
313
0
                rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
314
0
                                      &privk->u.rsa.modulus);
315
0
                if (rv == SECSuccess) {
316
0
                    rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent,
317
0
                                          &privk->u.rsa.publicExponent);
318
0
                    if (rv == SECSuccess) {
319
                        /* this key was already verified fully as
320
                         * a private key */
321
0
                        pubk->u.rsa.needVerify = PR_FALSE;
322
0
                        return pubk;
323
0
                    }
324
0
                }
325
0
            } else {
326
0
                PORT_SetError(SEC_ERROR_NO_MEMORY);
327
0
            }
328
0
            break;
329
0
        case NSSLOWKEYDSAKey:
330
0
            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
331
0
                                                          sizeof(NSSLOWKEYPublicKey));
332
0
            if (pubk != NULL) {
333
0
                SECStatus rv;
334
335
0
                pubk->arena = arena;
336
0
                pubk->keyType = privk->keyType;
337
                /* if the public key value doesn't exist, calculate it */
338
0
                if (privk->u.dsa.publicValue.len == 0) {
339
0
                    rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime,
340
0
                                   &privk->u.dsa.privateValue, &publicValue, 0);
341
0
                    if (rv != SECSuccess) {
342
0
                        break;
343
0
                    }
344
0
                    rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue);
345
0
                    SECITEM_ZfreeItem(&publicValue, PR_FALSE);
346
0
                    if (rv != SECSuccess) {
347
0
                        break;
348
0
                    }
349
0
                }
350
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
351
0
                                      &privk->u.dsa.publicValue);
352
0
                if (rv != SECSuccess)
353
0
                    break;
354
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
355
0
                                      &privk->u.dsa.params.prime);
356
0
                if (rv != SECSuccess)
357
0
                    break;
358
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
359
0
                                      &privk->u.dsa.params.subPrime);
360
0
                if (rv != SECSuccess)
361
0
                    break;
362
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
363
0
                                      &privk->u.dsa.params.base);
364
0
                if (rv == SECSuccess)
365
0
                    return pubk;
366
0
            }
367
0
            break;
368
0
        case NSSLOWKEYDHKey:
369
0
            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
370
0
                                                          sizeof(NSSLOWKEYPublicKey));
371
0
            if (pubk != NULL) {
372
0
                SECStatus rv;
373
374
0
                pubk->arena = arena;
375
0
                pubk->keyType = privk->keyType;
376
                /* if the public key value doesn't exist, calculate it */
377
0
                if (privk->u.dh.publicValue.len == 0) {
378
0
                    rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime,
379
0
                                   &privk->u.dh.privateValue, &publicValue, 0);
380
0
                    if (rv != SECSuccess) {
381
0
                        break;
382
0
                    }
383
0
                    rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue);
384
0
                    SECITEM_ZfreeItem(&publicValue, PR_FALSE);
385
0
                    if (rv != SECSuccess) {
386
0
                        break;
387
0
                    }
388
0
                }
389
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
390
0
                                      &privk->u.dh.publicValue);
391
0
                if (rv != SECSuccess)
392
0
                    break;
393
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
394
0
                                      &privk->u.dh.prime);
395
0
                if (rv != SECSuccess)
396
0
                    break;
397
0
                rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
398
0
                                      &privk->u.dh.base);
399
0
                if (rv == SECSuccess)
400
0
                    return pubk;
401
0
            }
402
0
            break;
403
0
        case NSSLOWKEYECKey:
404
0
            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
405
0
                                                          sizeof(NSSLOWKEYPublicKey));
406
0
            if (pubk != NULL) {
407
0
                SECStatus rv;
408
409
0
                pubk->arena = arena;
410
0
                pubk->keyType = privk->keyType;
411
412
                /* if the public key value doesn't exist, calculate it */
413
0
                if (privk->u.ec.publicValue.len == 0) {
414
                    /* Checking if it's an ed25519 or x25519 key.
415
                       If it's the case, we derive the public key using the private key. */
416
0
                    SECOidTag privKeyOIDTag = SECOID_FindOIDTag(&privk->u.ec.ecParams.curveOID);
417
0
                    if (privKeyOIDTag == SEC_OID_ED25519_PUBLIC_KEY) {
418
0
                        PORT_Memset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue));
419
0
                        if (SECITEM_AllocItem(privk->arena, &privk->u.ec.publicValue, Ed25519_PUBLIC_KEYLEN) == NULL) {
420
0
                            break;
421
0
                        }
422
423
0
                        rv = ED_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue);
424
0
                        if (rv != CKR_OK) {
425
0
                            break;
426
0
                        }
427
0
                    } else if (privKeyOIDTag == SEC_OID_X25519) {
428
0
                        PORT_Memset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue));
429
0
                        if (SECITEM_AllocItem(privk->arena, &privk->u.ec.publicValue, X25519_PUBLIC_KEYLEN) == NULL) {
430
0
                            break;
431
0
                        }
432
433
0
                        rv = X25519_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue);
434
0
                        if (rv != CKR_OK) {
435
0
                            break;
436
0
                        }
437
0
                    }
438
0
                }
439
440
0
                rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
441
0
                                      &privk->u.ec.publicValue);
442
0
                if (rv != SECSuccess)
443
0
                    break;
444
0
                pubk->u.ec.ecParams.arena = arena;
445
                /* Copy the rest of the params */
446
0
                rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
447
0
                                   &(privk->u.ec.ecParams));
448
0
                if (rv == SECSuccess)
449
0
                    return pubk;
450
0
            }
451
0
            break;
452
0
        case NSSLOWKEYMLDSAKey:
453
0
            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
454
0
                                                          sizeof(NSSLOWKEYPublicKey));
455
0
            if (pubk != NULL) {
456
0
                SECStatus rv;
457
0
                SECItem seed = { siBuffer, NULL, 0 };
458
0
                MLDSAPrivateKey newPrivKey;
459
460
0
                pubk->arena = arena;
461
0
                pubk->keyType = privk->keyType;
462
463
                /* privatekey value is encoded (rho, K, tr, s1, s2, t0) */
464
                /* publickey value is encoded (rho, t1) */
465
                /* Future, we can calculate public key directly from
466
                 * privatekey value as follows :
467
                 * A^ = ExpandA(rho);
468
                 * t = NTT-1(A^ o NSS(s1)) + s2
469
                 * (t1, t0) = Power2Round(t)
470
                 * we now have rho and t1 so we can encode public key.
471
                 * these functions are all specified in FIPS-204. For now
472
                 * we just use the seed if it's a available and regenerate
473
                 * both keys, and discard the private key. */
474
0
                if (privk->u.mldsa.seedLen == 0) {
475
0
                    PORT_SetError(SEC_ERROR_PKCS11_FUNCTION_FAILED);
476
0
                    rv = SECFailure;
477
0
                    break;
478
0
                }
479
0
                seed.data = privk->u.mldsa.seed;
480
0
                seed.len = privk->u.mldsa.seedLen;
481
0
                rv = MLDSA_NewKey(privk->u.mldsa.paramSet, &seed,
482
0
                                  &newPrivKey, &pubk->u.mldsa);
483
0
                if (rv != SECSuccess) {
484
0
                    break;
485
0
                }
486
0
                PORT_SafeZero(&newPrivKey, sizeof(newPrivKey));
487
0
                return pubk;
488
0
            }
489
0
            break;
490
0
        case NSSLOWKEYMLKEMKey:
491
0
            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
492
0
                                                          sizeof(NSSLOWKEYPublicKey));
493
0
            if (pubk != NULL) {
494
0
                size_t pubKeyLen;
495
0
                SECItem *item = NULL;
496
497
0
                pubk->arena = arena;
498
0
                pubk->keyType = privk->keyType;
499
0
                pubk->u.mlkem.mlkemParams = privk->u.mlkem.mlkemParams;
500
                /* privatekey value is encoded (dPKE||ePKE||H(ePKE)||z) */
501
                /* publickey value is encoded (ePKE) */
502
                /* size(dPKE) = 384k and size(ePKE)=384k+32,
503
                 * so size(dPKE) = size(ePKE)-32 */
504
0
                pubKeyLen = sftk_kyber_pubKeyLen(pubk->u.mlkem.mlkemParams);
505
0
                if (privk->u.mlkem.key.len < 2 * pubKeyLen) {
506
0
                    PORT_SetError(SEC_ERROR_BAD_KEY);
507
0
                    break;
508
0
                }
509
0
                item = SECITEM_AllocItem(arena, &pubk->u.mlkem.key, (int)pubKeyLen);
510
0
                if (item == NULL) {
511
0
                    break;
512
0
                }
513
0
                PORT_Memcpy(pubk->u.mlkem.key.data,
514
0
                            privk->u.mlkem.key.data + pubKeyLen - 32,
515
0
                            pubKeyLen);
516
0
                return pubk;
517
0
            }
518
0
            break;
519
        /* No Fortezza in Low Key implementations (Fortezza keys aren't
520
         * stored in our data base */
521
0
        default:
522
0
            break;
523
0
    }
524
525
0
    PORT_FreeArena(arena, PR_TRUE);
526
0
    return NULL;
527
0
}
528
529
NSSLOWKEYPrivateKey *
530
nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
531
0
{
532
0
    NSSLOWKEYPrivateKey *returnKey = NULL;
533
0
    SECStatus rv = SECFailure;
534
0
    PLArenaPool *poolp;
535
536
0
    if (!privKey) {
537
0
        return NULL;
538
0
    }
539
540
0
    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
541
0
    if (!poolp) {
542
0
        return NULL;
543
0
    }
544
545
0
    returnKey = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
546
0
    if (!returnKey) {
547
0
        rv = SECFailure;
548
0
        goto loser;
549
0
    }
550
551
0
    returnKey->keyType = privKey->keyType;
552
0
    returnKey->arena = poolp;
553
554
0
    switch (privKey->keyType) {
555
0
        case NSSLOWKEYRSAKey:
556
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus),
557
0
                                  &(privKey->u.rsa.modulus));
558
0
            if (rv != SECSuccess)
559
0
                break;
560
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version),
561
0
                                  &(privKey->u.rsa.version));
562
0
            if (rv != SECSuccess)
563
0
                break;
564
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent),
565
0
                                  &(privKey->u.rsa.publicExponent));
566
0
            if (rv != SECSuccess)
567
0
                break;
568
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent),
569
0
                                  &(privKey->u.rsa.privateExponent));
570
0
            if (rv != SECSuccess)
571
0
                break;
572
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1),
573
0
                                  &(privKey->u.rsa.prime1));
574
0
            if (rv != SECSuccess)
575
0
                break;
576
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2),
577
0
                                  &(privKey->u.rsa.prime2));
578
0
            if (rv != SECSuccess)
579
0
                break;
580
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1),
581
0
                                  &(privKey->u.rsa.exponent1));
582
0
            if (rv != SECSuccess)
583
0
                break;
584
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2),
585
0
                                  &(privKey->u.rsa.exponent2));
586
0
            if (rv != SECSuccess)
587
0
                break;
588
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient),
589
0
                                  &(privKey->u.rsa.coefficient));
590
0
            if (rv != SECSuccess)
591
0
                break;
592
0
            break;
593
0
        case NSSLOWKEYDSAKey:
594
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
595
0
                                  &(privKey->u.dsa.publicValue));
596
0
            if (rv != SECSuccess)
597
0
                break;
598
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue),
599
0
                                  &(privKey->u.dsa.privateValue));
600
0
            if (rv != SECSuccess)
601
0
                break;
602
0
            returnKey->u.dsa.params.arena = poolp;
603
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime),
604
0
                                  &(privKey->u.dsa.params.prime));
605
0
            if (rv != SECSuccess)
606
0
                break;
607
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime),
608
0
                                  &(privKey->u.dsa.params.subPrime));
609
0
            if (rv != SECSuccess)
610
0
                break;
611
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base),
612
0
                                  &(privKey->u.dsa.params.base));
613
0
            if (rv != SECSuccess)
614
0
                break;
615
0
            break;
616
0
        case NSSLOWKEYDHKey:
617
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
618
0
                                  &(privKey->u.dh.publicValue));
619
0
            if (rv != SECSuccess)
620
0
                break;
621
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue),
622
0
                                  &(privKey->u.dh.privateValue));
623
0
            if (rv != SECSuccess)
624
0
                break;
625
0
            returnKey->u.dsa.params.arena = poolp;
626
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime),
627
0
                                  &(privKey->u.dh.prime));
628
0
            if (rv != SECSuccess)
629
0
                break;
630
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base),
631
0
                                  &(privKey->u.dh.base));
632
0
            if (rv != SECSuccess)
633
0
                break;
634
0
            break;
635
0
        case NSSLOWKEYECKey:
636
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version),
637
0
                                  &(privKey->u.ec.version));
638
0
            if (rv != SECSuccess)
639
0
                break;
640
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue),
641
0
                                  &(privKey->u.ec.publicValue));
642
0
            if (rv != SECSuccess)
643
0
                break;
644
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue),
645
0
                                  &(privKey->u.ec.privateValue));
646
0
            if (rv != SECSuccess)
647
0
                break;
648
0
            returnKey->u.ec.ecParams.arena = poolp;
649
            /* Copy the rest of the params */
650
0
            rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
651
0
                               &(privKey->u.ec.ecParams));
652
0
            if (rv != SECSuccess)
653
0
                break;
654
0
            break;
655
0
        case NSSLOWKEYMLDSAKey:
656
0
            returnKey->u.mldsa = privKey->u.mldsa;
657
0
            rv = SECSuccess;
658
0
            break;
659
0
        case NSSLOWKEYMLKEMKey:
660
0
            returnKey->u.mlkem.mlkemParams = privKey->u.mlkem.mlkemParams;
661
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.mlkem.key),
662
0
                                  &(privKey->u.mlkem.key));
663
0
            if (rv != SECSuccess)
664
0
                break;
665
0
            rv = SECITEM_CopyItem(poolp, &(returnKey->u.mlkem.seed),
666
0
                                  &(privKey->u.mlkem.seed));
667
0
            if (rv != SECSuccess)
668
0
                break;
669
0
            break;
670
0
        default:
671
0
            rv = SECFailure;
672
0
    }
673
674
0
loser:
675
676
0
    if (rv != SECSuccess) {
677
0
        PORT_FreeArena(poolp, PR_TRUE);
678
0
        returnKey = NULL;
679
0
    }
680
681
0
    return returnKey;
682
0
}