Bug Summary

File:root/firefox-clang/security/nss/lib/softoken/lowkey.c
Warning:line 481, column 21
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lowkey.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D SOFTOKEN_LIB_NAME="libsoftokn3.so" -D SHLIB_VERSION="3" -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/lib/softoken -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c /root/firefox-clang/security/nss/lib/softoken/lowkey.c
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
15SEC_ASN1_MKSUB(SEC_AnyTemplate)
16SEC_ASN1_MKSUB(SEC_BitStringTemplate)
17SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
18SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
19SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
20
21const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
22 { SEC_ASN1_SEQUENCE0x10,
23 0, NULL((void*)0), sizeof(NSSLOWKEYAttribute) },
24 { SEC_ASN1_OBJECT_ID0x06, offsetof(NSSLOWKEYAttribute, attrType)__builtin_offsetof(NSSLOWKEYAttribute, attrType) },
25 { SEC_ASN1_SET_OF(0x02000 | 0x11) | SEC_ASN1_XTRN0,
26 offsetof(NSSLOWKEYAttribute, attrValue)__builtin_offsetof(NSSLOWKEYAttribute, attrValue),
27 SEC_ASN1_SUB(SEC_AnyTemplate)SEC_AnyTemplate_Util },
28 { 0 }
29};
30
31const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
32 { SEC_ASN1_SET_OF(0x02000 | 0x11), 0, nsslowkey_AttributeTemplate },
33};
34/* ASN1 Templates for new decoder/encoder */
35const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
36 { SEC_ASN1_SEQUENCE0x10,
37 0, NULL((void*)0), sizeof(NSSLOWKEYPrivateKeyInfo) },
38 { SEC_ASN1_INTEGER0x02,
39 offsetof(NSSLOWKEYPrivateKeyInfo, version)__builtin_offsetof(NSSLOWKEYPrivateKeyInfo, version) },
40 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
41 offsetof(NSSLOWKEYPrivateKeyInfo, algorithm)__builtin_offsetof(NSSLOWKEYPrivateKeyInfo, algorithm),
42 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
43 { SEC_ASN1_OCTET_STRING0x04,
44 offsetof(NSSLOWKEYPrivateKeyInfo, privateKey)__builtin_offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) },
45 { SEC_ASN1_OPTIONAL0x00100 | SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_CONTEXT_SPECIFIC0x80 | 0,
46 offsetof(NSSLOWKEYPrivateKeyInfo, attributes)__builtin_offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
47 nsslowkey_SetOfAttributeTemplate },
48 { SEC_ASN1_OPTIONAL0x00100 | SEC_ASN1_CONTEXT_SPECIFIC0x80 | SEC_ASN1_XTRN0 | 1,
49 offsetof(NSSLOWKEYPrivateKeyInfo, publicKey)__builtin_offsetof(NSSLOWKEYPrivateKeyInfo, publicKey),
50 SEC_ASN1_SUB(SEC_BitStringTemplate)SEC_BitStringTemplate_Util },
51 { 0 }
52};
53
54const SEC_ASN1Template nsslowkey_SubjectPublicKeyInfoTemplate[] = {
55 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYSubjectPublicKeyInfo) },
56 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
57 offsetof(NSSLOWKEYSubjectPublicKeyInfo, algorithm)__builtin_offsetof(NSSLOWKEYSubjectPublicKeyInfo, algorithm),
58 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
59 { SEC_ASN1_BIT_STRING0x03,
60 offsetof(NSSLOWKEYSubjectPublicKeyInfo, subjectPublicKey)__builtin_offsetof(NSSLOWKEYSubjectPublicKeyInfo, subjectPublicKey
)
},
61 { 0 }
62};
63
64const SEC_ASN1Template nsslowkey_RSAPublicKeyTemplate[] = {
65 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPublicKey) },
66 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus)__builtin_offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) },
67 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent)__builtin_offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) },
68 { 0 }
69};
70
71const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
72 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(PQGParams) },
73 { SEC_ASN1_INTEGER0x02, offsetof(PQGParams, prime)__builtin_offsetof(PQGParams, prime) },
74 { SEC_ASN1_INTEGER0x02, offsetof(PQGParams, subPrime)__builtin_offsetof(PQGParams, subPrime) },
75 { SEC_ASN1_INTEGER0x02, offsetof(PQGParams, base)__builtin_offsetof(PQGParams, base) },
76 { 0 }
77};
78
79const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
80 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPrivateKey) },
81 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.version)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
82 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
83 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
84 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent
)
},
85 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
86 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
87 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
88 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
89 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient)__builtin_offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
90 { 0 }
91};
92
93const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
94 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPrivateKey) },
95 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) },
96 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
97 { 0 }
98};
99
100const SEC_ASN1Template nsslowkey_PQBothSeedAndPrivateKeyTemplate[] = {
101 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPrivateKey) },
102 { SEC_ASN1_OCTET_STRING0x04, offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem)__builtin_offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem) },
103 { SEC_ASN1_OCTET_STRING0x04, offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem)__builtin_offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem) },
104 { 0 }
105};
106
107const SEC_ASN1Template nsslowkey_PQSeedTemplate[] = {
108 /* the explicit | 0 here is source code doumentation, tell
109 * clang warnings to let it ride */
110 { SEC_ASN1_CONTEXT_SPECIFIC0x80 | SEC_ASN1_XTRN0 | 0, // NOLINT(misc-redundant-expression)
111 offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem)__builtin_offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem),
112 SEC_ASN1_SUB(SEC_OctetStringTemplate)SEC_OctetStringTemplate_Util },
113 { 0 }
114};
115const SEC_ASN1Template nsslowkey_PQPrivateKeyTemplate[] = {
116 { SEC_ASN1_OCTET_STRING0x04, offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem)__builtin_offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem) },
117 { 0 }
118};
119
120const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
121 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
122};
123
124const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
125 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPrivateKey) },
126 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) },
127 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) },
128 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dh.base)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dh.base) },
129 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.dh.prime)__builtin_offsetof(NSSLOWKEYPrivateKey, u.dh.prime) },
130 { 0 }
131};
132
133/* NOTE: The SECG specification allows the private key structure
134 * to contain curve parameters but recommends that they be stored
135 * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
136 * instead.
137 */
138const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
139 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPrivateKey) },
140 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPrivateKey, u.ec.version)__builtin_offsetof(NSSLOWKEYPrivateKey, u.ec.version) },
141 { SEC_ASN1_OCTET_STRING0x04,
142 offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) },
143 /* We only support named curves for which the parameters are
144 * encoded as an object ID.
145 */
146 { SEC_ASN1_OPTIONAL0x00100 | SEC_ASN1_CONSTRUCTED0x20 |
147 SEC_ASN1_EXPLICIT0x00200 | SEC_ASN1_CONTEXT_SPECIFIC0x80 |
148 SEC_ASN1_XTRN0 | 0,
149 offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID)__builtin_offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID
)
,
150 SEC_ASN1_SUB(SEC_ObjectIDTemplate)SEC_ObjectIDTemplate_Util },
151 { SEC_ASN1_OPTIONAL0x00100 | SEC_ASN1_CONSTRUCTED0x20 |
152 SEC_ASN1_EXPLICIT0x00200 | SEC_ASN1_CONTEXT_SPECIFIC0x80 |
153 SEC_ASN1_XTRN0 | 1,
154 offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue)__builtin_offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue),
155 SEC_ASN1_SUB(SEC_BitStringTemplate)SEC_BitStringTemplate_Util },
156 { 0 }
157};
158/*
159 * See bugzilla bug 125359
160 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
161 * all of the templates above that en/decode into integers must be converted
162 * from ASN.1's signed integer type. This is done by marking either the
163 * source or destination (encoding or decoding, respectively) type as
164 * siUnsignedInteger.
165 */
166
167void
168prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
169{
170 key->u.rsa.modulus.type = siUnsignedInteger;
171 key->u.rsa.publicExponent.type = siUnsignedInteger;
172 key->u.rsa.privateExponent.type = siUnsignedInteger;
173 key->u.rsa.prime1.type = siUnsignedInteger;
174 key->u.rsa.prime2.type = siUnsignedInteger;
175 key->u.rsa.exponent1.type = siUnsignedInteger;
176 key->u.rsa.exponent2.type = siUnsignedInteger;
177 key->u.rsa.coefficient.type = siUnsignedInteger;
178}
179
180void
181prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *key)
182{
183 key->u.rsa.modulus.type = siUnsignedInteger;
184 key->u.rsa.publicExponent.type = siUnsignedInteger;
185}
186
187void
188prepare_low_pqg_params_for_asn1(PQGParams *params)
189{
190 params->prime.type = siUnsignedInteger;
191 params->subPrime.type = siUnsignedInteger;
192 params->base.type = siUnsignedInteger;
193}
194
195void
196prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
197{
198 key->u.dsa.publicValue.type = siUnsignedInteger;
199 key->u.dsa.privateValue.type = siUnsignedInteger;
200 key->u.dsa.params.prime.type = siUnsignedInteger;
201 key->u.dsa.params.subPrime.type = siUnsignedInteger;
202 key->u.dsa.params.base.type = siUnsignedInteger;
203}
204
205void
206prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
207{
208 key->u.dsa.privateValue.type = siUnsignedInteger;
209}
210
211void
212prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
213{
214 key->u.dh.prime.type = siUnsignedInteger;
215 key->u.dh.base.type = siUnsignedInteger;
216 key->u.dh.publicValue.type = siUnsignedInteger;
217 key->u.dh.privateValue.type = siUnsignedInteger;
218}
219
220void
221prepare_low_ecparams_for_asn1(ECParams *params)
222{
223 params->DEREncoding.type = siUnsignedInteger;
224 params->curveOID.type = siUnsignedInteger;
225}
226
227void
228prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
229{
230 key->u.ec.version.type = siUnsignedInteger;
231 key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
232 key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
233 key->u.ec.privateValue.type = siUnsignedInteger;
234 key->u.ec.publicValue.type = siUnsignedInteger;
235}
236
237void
238nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
239{
240 if (privk && privk->arena) {
241 PORT_FreeArenaPORT_FreeArena_Util(privk->arena, PR_TRUE1);
242 }
243}
244
245void
246nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
247{
248 if (pubk && pubk->arena) {
249 PORT_FreeArenaPORT_FreeArena_Util(pubk->arena, PR_TRUE1);
250 }
251}
252unsigned
253nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
254{
255 /* interpret modulus length as key strength... in
256 * fortezza that's the public key length */
257
258 switch (pubk->keyType) {
259 case NSSLOWKEYRSAKey:
260 if (pubk->u.rsa.modulus.len == 0) {
261 return 0;
262 }
263 if (pubk->u.rsa.modulus.data[0] == 0) {
264 return pubk->u.rsa.modulus.len - 1;
265 }
266 return pubk->u.rsa.modulus.len;
267 default:
268 break;
269 }
270 return 0;
271}
272
273unsigned
274nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
275{
276 switch (privk->keyType) {
277 case NSSLOWKEYRSAKey:
278 if (privk->u.rsa.modulus.len == 0) {
279 return 0;
280 }
281 if (privk->u.rsa.modulus.data[0] == 0) {
282 return privk->u.rsa.modulus.len - 1;
283 }
284 return privk->u.rsa.modulus.len;
285 default:
286 break;
287 }
288 return 0;
289}
290
291NSSLOWKEYPublicKey *
292nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
293{
294 NSSLOWKEYPublicKey *pubk;
295 SECItem publicValue;
296 PLArenaPool *arena;
297
298 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
299 if (arena == NULL((void*)0)) {
300 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
301 return NULL((void*)0);
302 }
303
304 switch (privk->keyType) {
305 case NSSLOWKEYRSAKey:
306 case NSSLOWKEYNullKey:
307 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena,
308 sizeof(NSSLOWKEYPublicKey));
309 if (pubk != NULL((void*)0)) {
310 SECStatus rv;
311
312 pubk->arena = arena;
313 pubk->keyType = privk->keyType;
314 if (privk->keyType == NSSLOWKEYNullKey)
315 return pubk;
316 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.rsa.modulus,
317 &privk->u.rsa.modulus);
318 if (rv == SECSuccess) {
319 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.rsa.publicExponent,
320 &privk->u.rsa.publicExponent);
321 if (rv == SECSuccess) {
322 /* this key was already verified fully as
323 * a private key */
324 pubk->u.rsa.needVerify = PR_FALSE0;
325 return pubk;
326 }
327 }
328 } else {
329 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
330 }
331 break;
332 case NSSLOWKEYDSAKey:
333 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena,
334 sizeof(NSSLOWKEYPublicKey));
335 if (pubk != NULL((void*)0)) {
336 SECStatus rv;
337
338 pubk->arena = arena;
339 pubk->keyType = privk->keyType;
340 /* if the public key value doesn't exist, calculate it */
341 if (privk->u.dsa.publicValue.len == 0) {
342 rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime,
343 &privk->u.dsa.privateValue, &publicValue, 0);
344 if (rv != SECSuccess) {
345 break;
346 }
347 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(privk->arena, &privk->u.dsa.publicValue, &publicValue);
348 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&publicValue, PR_FALSE0);
349 if (rv != SECSuccess) {
350 break;
351 }
352 }
353 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dsa.publicValue,
354 &privk->u.dsa.publicValue);
355 if (rv != SECSuccess)
356 break;
357 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dsa.params.prime,
358 &privk->u.dsa.params.prime);
359 if (rv != SECSuccess)
360 break;
361 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dsa.params.subPrime,
362 &privk->u.dsa.params.subPrime);
363 if (rv != SECSuccess)
364 break;
365 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dsa.params.base,
366 &privk->u.dsa.params.base);
367 if (rv == SECSuccess)
368 return pubk;
369 }
370 break;
371 case NSSLOWKEYDHKey:
372 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena,
373 sizeof(NSSLOWKEYPublicKey));
374 if (pubk != NULL((void*)0)) {
375 SECStatus rv;
376
377 pubk->arena = arena;
378 pubk->keyType = privk->keyType;
379 /* if the public key value doesn't exist, calculate it */
380 if (privk->u.dh.publicValue.len == 0) {
381 rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime,
382 &privk->u.dh.privateValue, &publicValue, 0);
383 if (rv != SECSuccess) {
384 break;
385 }
386 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(privk->arena, &privk->u.dh.publicValue, &publicValue);
387 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&publicValue, PR_FALSE0);
388 if (rv != SECSuccess) {
389 break;
390 }
391 }
392 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dh.publicValue,
393 &privk->u.dh.publicValue);
394 if (rv != SECSuccess)
395 break;
396 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dh.prime,
397 &privk->u.dh.prime);
398 if (rv != SECSuccess)
399 break;
400 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.dh.base,
401 &privk->u.dh.base);
402 if (rv == SECSuccess)
403 return pubk;
404 }
405 break;
406 case NSSLOWKEYECKey:
407 case NSSLOWKEYECEdwardsKey:
408 case NSSLOWKEYECMontgomeryKey:
409 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena,
410 sizeof(NSSLOWKEYPublicKey));
411 if (pubk != NULL((void*)0)) {
412 SECStatus rv;
413
414 pubk->arena = arena;
415 pubk->keyType = privk->keyType;
416
417 /* if the public key value doesn't exist, calculate it */
418 if (privk->u.ec.publicValue.len == 0) {
419 /* Checking if it's an ed25519 or x25519 key.
420 If it's the case, we derive the public key using the private key. */
421 SECOidTag privKeyOIDTag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&privk->u.ec.ecParams.curveOID);
422 if (privKeyOIDTag == SEC_OID_ED25519_PUBLIC_KEYSEC_OID_ED25519) {
423 PORT_Memsetmemset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue));
424 if (SECITEM_AllocItemSECITEM_AllocItem_Util(privk->arena, &privk->u.ec.publicValue, Ed25519_PUBLIC_KEYLEN32) == NULL((void*)0)) {
425 break;
426 }
427
428 rv = ED_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue);
429 if (rv != CKR_OK0x00000000UL) {
430 break;
431 }
432 } else if (privKeyOIDTag == SEC_OID_X25519) {
433 PORT_Memsetmemset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue));
434 if (SECITEM_AllocItemSECITEM_AllocItem_Util(privk->arena, &privk->u.ec.publicValue, X25519_PUBLIC_KEYLEN32) == NULL((void*)0)) {
435 break;
436 }
437
438 rv = X25519_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue);
439 if (rv != CKR_OK0x00000000UL) {
440 break;
441 }
442 }
443 }
444
445 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.ec.publicValue,
446 &privk->u.ec.publicValue);
447 if (rv != SECSuccess)
448 break;
449 pubk->u.ec.ecParams.arena = arena;
450 /* Copy the rest of the params */
451 rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
452 &(privk->u.ec.ecParams));
453 if (rv == SECSuccess)
454 return pubk;
455 }
456 break;
457 case NSSLOWKEYMLDSAKey:
458 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena,
459 sizeof(NSSLOWKEYPublicKey));
460 if (pubk != NULL((void*)0)) {
461 SECStatus rv;
462 SECItem seed = { siBuffer, NULL((void*)0), 0 };
463 MLDSAPrivateKey newPrivKey;
464
465 pubk->arena = arena;
466 pubk->keyType = privk->keyType;
467
468 /* privatekey value is encoded (rho, K, tr, s1, s2, t0) */
469 /* publickey value is encoded (rho, t1) */
470 /* Future, we can calculate public key directly from
471 * privatekey value as follows :
472 * A^ = ExpandA(rho);
473 * t = NTT-1(A^ o NSS(s1)) + s2
474 * (t1, t0) = Power2Round(t)
475 * we now have rho and t1 so we can encode public key.
476 * these functions are all specified in FIPS-204. For now
477 * we just use the seed if it's a available and regenerate
478 * both keys, and discard the private key. */
479 if (privk->u.mldsa.seedLen == 0) {
480 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_PKCS11_FUNCTION_FAILED);
481 rv = SECFailure;
Value stored to 'rv' is never read
482 break;
483 }
484 seed.data = privk->u.mldsa.seed;
485 seed.len = privk->u.mldsa.seedLen;
486 rv = MLDSA_NewKey(privk->u.mldsa.paramSet, &seed,
487 &newPrivKey, &pubk->u.mldsa);
488 if (rv != SECSuccess) {
489 break;
490 }
491 PORT_SafeZero(&newPrivKey, sizeof(newPrivKey));
492 return pubk;
493 }
494 break;
495 case NSSLOWKEYMLKEMKey:
496 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena,
497 sizeof(NSSLOWKEYPublicKey));
498 if (pubk != NULL((void*)0)) {
499 size_t pubKeyLen;
500 SECItem *item = NULL((void*)0);
501
502 pubk->arena = arena;
503 pubk->keyType = privk->keyType;
504 pubk->u.mlkem.mlkemParams = privk->u.mlkem.mlkemParams;
505 /* privatekey value is encoded (dPKE||ePKE||H(ePKE)||z) */
506 /* publickey value is encoded (ePKE) */
507 /* size(dPKE) = 384k and size(ePKE)=384k+32,
508 * so size(dPKE) = size(ePKE)-32 */
509 pubKeyLen = sftk_kyber_pubKeyLen(pubk->u.mlkem.mlkemParams);
510 if (privk->u.mlkem.key.len < 2 * pubKeyLen) {
511 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
512 break;
513 }
514 item = SECITEM_AllocItemSECITEM_AllocItem_Util(arena, &pubk->u.mlkem.key, (int)pubKeyLen);
515 if (item == NULL((void*)0)) {
516 break;
517 }
518 PORT_Memcpymemcpy(pubk->u.mlkem.key.data,
519 privk->u.mlkem.key.data + pubKeyLen - 32,
520 pubKeyLen);
521 return pubk;
522 }
523 break;
524 /* No Fortezza in Low Key implementations (Fortezza keys aren't
525 * stored in our data base */
526 default:
527 break;
528 }
529
530 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1);
531 return NULL((void*)0);
532}
533
534NSSLOWKEYPrivateKey *
535nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
536{
537 NSSLOWKEYPrivateKey *returnKey = NULL((void*)0);
538 SECStatus rv = SECFailure;
539 PLArenaPool *poolp;
540
541 if (!privKey) {
542 return NULL((void*)0);
543 }
544
545 poolp = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
546 if (!poolp) {
547 return NULL((void*)0);
548 }
549
550 returnKey = (NSSLOWKEYPrivateKey *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(poolp, sizeof(NSSLOWKEYPrivateKey));
551 if (!returnKey) {
552 rv = SECFailure;
553 goto loser;
554 }
555
556 returnKey->keyType = privKey->keyType;
557 returnKey->arena = poolp;
558
559 switch (privKey->keyType) {
560 case NSSLOWKEYRSAKey:
561 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.modulus),
562 &(privKey->u.rsa.modulus));
563 if (rv != SECSuccess)
564 break;
565 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.version),
566 &(privKey->u.rsa.version));
567 if (rv != SECSuccess)
568 break;
569 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.publicExponent),
570 &(privKey->u.rsa.publicExponent));
571 if (rv != SECSuccess)
572 break;
573 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.privateExponent),
574 &(privKey->u.rsa.privateExponent));
575 if (rv != SECSuccess)
576 break;
577 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.prime1),
578 &(privKey->u.rsa.prime1));
579 if (rv != SECSuccess)
580 break;
581 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.prime2),
582 &(privKey->u.rsa.prime2));
583 if (rv != SECSuccess)
584 break;
585 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.exponent1),
586 &(privKey->u.rsa.exponent1));
587 if (rv != SECSuccess)
588 break;
589 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.exponent2),
590 &(privKey->u.rsa.exponent2));
591 if (rv != SECSuccess)
592 break;
593 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.rsa.coefficient),
594 &(privKey->u.rsa.coefficient));
595 if (rv != SECSuccess)
596 break;
597 break;
598 case NSSLOWKEYDSAKey:
599 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dsa.publicValue),
600 &(privKey->u.dsa.publicValue));
601 if (rv != SECSuccess)
602 break;
603 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dsa.privateValue),
604 &(privKey->u.dsa.privateValue));
605 if (rv != SECSuccess)
606 break;
607 returnKey->u.dsa.params.arena = poolp;
608 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dsa.params.prime),
609 &(privKey->u.dsa.params.prime));
610 if (rv != SECSuccess)
611 break;
612 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dsa.params.subPrime),
613 &(privKey->u.dsa.params.subPrime));
614 if (rv != SECSuccess)
615 break;
616 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dsa.params.base),
617 &(privKey->u.dsa.params.base));
618 if (rv != SECSuccess)
619 break;
620 break;
621 case NSSLOWKEYDHKey:
622 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dh.publicValue),
623 &(privKey->u.dh.publicValue));
624 if (rv != SECSuccess)
625 break;
626 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dh.privateValue),
627 &(privKey->u.dh.privateValue));
628 if (rv != SECSuccess)
629 break;
630 returnKey->u.dsa.params.arena = poolp;
631 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dh.prime),
632 &(privKey->u.dh.prime));
633 if (rv != SECSuccess)
634 break;
635 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.dh.base),
636 &(privKey->u.dh.base));
637 if (rv != SECSuccess)
638 break;
639 break;
640 case NSSLOWKEYECKey:
641 case NSSLOWKEYECEdwardsKey:
642 case NSSLOWKEYECMontgomeryKey:
643 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.ec.version),
644 &(privKey->u.ec.version));
645 if (rv != SECSuccess)
646 break;
647 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.ec.publicValue),
648 &(privKey->u.ec.publicValue));
649 if (rv != SECSuccess)
650 break;
651 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.ec.privateValue),
652 &(privKey->u.ec.privateValue));
653 if (rv != SECSuccess)
654 break;
655 returnKey->u.ec.ecParams.arena = poolp;
656 /* Copy the rest of the params */
657 rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
658 &(privKey->u.ec.ecParams));
659 if (rv != SECSuccess)
660 break;
661 break;
662 case NSSLOWKEYMLDSAKey:
663 returnKey->u.mldsa = privKey->u.mldsa;
664 rv = SECSuccess;
665 break;
666 case NSSLOWKEYMLKEMKey:
667 returnKey->u.mlkem.mlkemParams = privKey->u.mlkem.mlkemParams;
668 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.mlkem.key),
669 &(privKey->u.mlkem.key));
670 if (rv != SECSuccess)
671 break;
672 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(poolp, &(returnKey->u.mlkem.seed),
673 &(privKey->u.mlkem.seed));
674 if (rv != SECSuccess)
675 break;
676 break;
677 default:
678 rv = SECFailure;
679 }
680
681loser:
682
683 if (rv != SECSuccess) {
684 PORT_FreeArenaPORT_FreeArena_Util(poolp, PR_TRUE1);
685 returnKey = NULL((void*)0);
686 }
687
688 return returnKey;
689}