/src/nss-nspr/nss/lib/softoken/lowkey.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 "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 | | |
14 | | SEC_ASN1_MKSUB(SEC_AnyTemplate) |
15 | | SEC_ASN1_MKSUB(SEC_BitStringTemplate) |
16 | | SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) |
17 | | SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
18 | | |
19 | | const SEC_ASN1Template nsslowkey_AttributeTemplate[] = { |
20 | | { SEC_ASN1_SEQUENCE, |
21 | | 0, NULL, sizeof(NSSLOWKEYAttribute) }, |
22 | | { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) }, |
23 | | { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, |
24 | | offsetof(NSSLOWKEYAttribute, attrValue), |
25 | | SEC_ASN1_SUB(SEC_AnyTemplate) }, |
26 | | { 0 } |
27 | | }; |
28 | | |
29 | | const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = { |
30 | | { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate }, |
31 | | }; |
32 | | /* ASN1 Templates for new decoder/encoder */ |
33 | | const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = { |
34 | | { SEC_ASN1_SEQUENCE, |
35 | | 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) }, |
36 | | { SEC_ASN1_INTEGER, |
37 | | offsetof(NSSLOWKEYPrivateKeyInfo, version) }, |
38 | | { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
39 | | offsetof(NSSLOWKEYPrivateKeyInfo, algorithm), |
40 | | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
41 | | { SEC_ASN1_OCTET_STRING, |
42 | | offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) }, |
43 | | { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, |
44 | | offsetof(NSSLOWKEYPrivateKeyInfo, attributes), |
45 | | nsslowkey_SetOfAttributeTemplate }, |
46 | | { 0 } |
47 | | }; |
48 | | |
49 | | const SEC_ASN1Template nsslowkey_SubjectPublicKeyInfoTemplate[] = { |
50 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYSubjectPublicKeyInfo) }, |
51 | | { SEC_ASN1_INLINE | SEC_ASN1_XTRN, |
52 | | offsetof(NSSLOWKEYSubjectPublicKeyInfo, algorithm), |
53 | | SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
54 | | { SEC_ASN1_BIT_STRING, |
55 | | offsetof(NSSLOWKEYSubjectPublicKeyInfo, subjectPublicKey) }, |
56 | | { 0 } |
57 | | }; |
58 | | |
59 | | const SEC_ASN1Template nsslowkey_RSAPublicKeyTemplate[] = { |
60 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) }, |
61 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) }, |
62 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) }, |
63 | | { 0 } |
64 | | }; |
65 | | |
66 | | const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = { |
67 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, |
68 | | { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) }, |
69 | | { SEC_ASN1_INTEGER, offsetof(PQGParams, subPrime) }, |
70 | | { SEC_ASN1_INTEGER, offsetof(PQGParams, base) }, |
71 | | { 0 } |
72 | | }; |
73 | | |
74 | | const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = { |
75 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, |
76 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) }, |
77 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) }, |
78 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) }, |
79 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) }, |
80 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) }, |
81 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) }, |
82 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) }, |
83 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) }, |
84 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) }, |
85 | | { 0 } |
86 | | }; |
87 | | |
88 | | const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = { |
89 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, |
90 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) }, |
91 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) }, |
92 | | { 0 } |
93 | | }; |
94 | | |
95 | | const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = { |
96 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) }, |
97 | | }; |
98 | | |
99 | | const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = { |
100 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, |
101 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) }, |
102 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) }, |
103 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.base) }, |
104 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.prime) }, |
105 | | { 0 } |
106 | | }; |
107 | | |
108 | | /* NOTE: The SECG specification allows the private key structure |
109 | | * to contain curve parameters but recommends that they be stored |
110 | | * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo |
111 | | * instead. |
112 | | */ |
113 | | const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = { |
114 | | { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, |
115 | | { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.ec.version) }, |
116 | | { SEC_ASN1_OCTET_STRING, |
117 | | offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) }, |
118 | | /* We only support named curves for which the parameters are |
119 | | * encoded as an object ID. |
120 | | */ |
121 | | { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | |
122 | | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | |
123 | | SEC_ASN1_XTRN | 0, |
124 | | offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID), |
125 | | SEC_ASN1_SUB(SEC_ObjectIDTemplate) }, |
126 | | { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | |
127 | | SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | |
128 | | SEC_ASN1_XTRN | 1, |
129 | | offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue), |
130 | | SEC_ASN1_SUB(SEC_BitStringTemplate) }, |
131 | | { 0 } |
132 | | }; |
133 | | /* |
134 | | * See bugzilla bug 125359 |
135 | | * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, |
136 | | * all of the templates above that en/decode into integers must be converted |
137 | | * from ASN.1's signed integer type. This is done by marking either the |
138 | | * source or destination (encoding or decoding, respectively) type as |
139 | | * siUnsignedInteger. |
140 | | */ |
141 | | |
142 | | void |
143 | | prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) |
144 | 0 | { |
145 | 0 | key->u.rsa.modulus.type = siUnsignedInteger; |
146 | 0 | key->u.rsa.publicExponent.type = siUnsignedInteger; |
147 | 0 | key->u.rsa.privateExponent.type = siUnsignedInteger; |
148 | 0 | key->u.rsa.prime1.type = siUnsignedInteger; |
149 | 0 | key->u.rsa.prime2.type = siUnsignedInteger; |
150 | 0 | key->u.rsa.exponent1.type = siUnsignedInteger; |
151 | 0 | key->u.rsa.exponent2.type = siUnsignedInteger; |
152 | 0 | key->u.rsa.coefficient.type = siUnsignedInteger; |
153 | 0 | } |
154 | | |
155 | | void |
156 | | prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *key) |
157 | 0 | { |
158 | 0 | key->u.rsa.modulus.type = siUnsignedInteger; |
159 | 0 | key->u.rsa.publicExponent.type = siUnsignedInteger; |
160 | 0 | } |
161 | | |
162 | | void |
163 | | prepare_low_pqg_params_for_asn1(PQGParams *params) |
164 | 0 | { |
165 | 0 | params->prime.type = siUnsignedInteger; |
166 | 0 | params->subPrime.type = siUnsignedInteger; |
167 | 0 | params->base.type = siUnsignedInteger; |
168 | 0 | } |
169 | | |
170 | | void |
171 | | prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) |
172 | 0 | { |
173 | 0 | key->u.dsa.publicValue.type = siUnsignedInteger; |
174 | 0 | key->u.dsa.privateValue.type = siUnsignedInteger; |
175 | 0 | key->u.dsa.params.prime.type = siUnsignedInteger; |
176 | 0 | key->u.dsa.params.subPrime.type = siUnsignedInteger; |
177 | 0 | key->u.dsa.params.base.type = siUnsignedInteger; |
178 | 0 | } |
179 | | |
180 | | void |
181 | | prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key) |
182 | 0 | { |
183 | 0 | key->u.dsa.privateValue.type = siUnsignedInteger; |
184 | 0 | } |
185 | | |
186 | | void |
187 | | prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) |
188 | 0 | { |
189 | 0 | key->u.dh.prime.type = siUnsignedInteger; |
190 | 0 | key->u.dh.base.type = siUnsignedInteger; |
191 | 0 | key->u.dh.publicValue.type = siUnsignedInteger; |
192 | 0 | key->u.dh.privateValue.type = siUnsignedInteger; |
193 | 0 | } |
194 | | |
195 | | void |
196 | | prepare_low_ecparams_for_asn1(ECParams *params) |
197 | 0 | { |
198 | 0 | params->DEREncoding.type = siUnsignedInteger; |
199 | 0 | params->curveOID.type = siUnsignedInteger; |
200 | 0 | } |
201 | | |
202 | | void |
203 | | prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) |
204 | 0 | { |
205 | 0 | key->u.ec.version.type = siUnsignedInteger; |
206 | 0 | key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger; |
207 | 0 | key->u.ec.ecParams.curveOID.type = siUnsignedInteger; |
208 | 0 | key->u.ec.privateValue.type = siUnsignedInteger; |
209 | 0 | key->u.ec.publicValue.type = siUnsignedInteger; |
210 | 0 | } |
211 | | |
212 | | void |
213 | | nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) |
214 | 2 | { |
215 | 2 | if (privk && privk->arena) { |
216 | 0 | PORT_FreeArena(privk->arena, PR_TRUE); |
217 | 0 | } |
218 | 2 | } |
219 | | |
220 | | void |
221 | | nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk) |
222 | 2 | { |
223 | 2 | if (pubk && pubk->arena) { |
224 | 0 | PORT_FreeArena(pubk->arena, PR_TRUE); |
225 | 0 | } |
226 | 2 | } |
227 | | unsigned |
228 | | nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk) |
229 | 0 | { |
230 | | /* interpret modulus length as key strength... in |
231 | | * fortezza that's the public key length */ |
232 | |
|
233 | 0 | switch (pubk->keyType) { |
234 | 0 | case NSSLOWKEYRSAKey: |
235 | 0 | if (pubk->u.rsa.modulus.len == 0) { |
236 | 0 | return 0; |
237 | 0 | } |
238 | 0 | if (pubk->u.rsa.modulus.data[0] == 0) { |
239 | 0 | return pubk->u.rsa.modulus.len - 1; |
240 | 0 | } |
241 | 0 | return pubk->u.rsa.modulus.len; |
242 | 0 | default: |
243 | 0 | break; |
244 | 0 | } |
245 | 0 | return 0; |
246 | 0 | } |
247 | | |
248 | | unsigned |
249 | | nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk) |
250 | 0 | { |
251 | 0 | switch (privk->keyType) { |
252 | 0 | case NSSLOWKEYRSAKey: |
253 | 0 | if (privk->u.rsa.modulus.len == 0) { |
254 | 0 | return 0; |
255 | 0 | } |
256 | 0 | if (privk->u.rsa.modulus.data[0] == 0) { |
257 | 0 | return privk->u.rsa.modulus.len - 1; |
258 | 0 | } |
259 | 0 | return privk->u.rsa.modulus.len; |
260 | 0 | default: |
261 | 0 | break; |
262 | 0 | } |
263 | 0 | return 0; |
264 | 0 | } |
265 | | |
266 | | NSSLOWKEYPublicKey * |
267 | | nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) |
268 | 0 | { |
269 | 0 | NSSLOWKEYPublicKey *pubk; |
270 | 0 | SECItem publicValue; |
271 | 0 | PLArenaPool *arena; |
272 | |
|
273 | 0 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
274 | 0 | if (arena == NULL) { |
275 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
276 | 0 | return NULL; |
277 | 0 | } |
278 | | |
279 | 0 | switch (privk->keyType) { |
280 | 0 | case NSSLOWKEYRSAKey: |
281 | 0 | case NSSLOWKEYNullKey: |
282 | 0 | pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, |
283 | 0 | sizeof(NSSLOWKEYPublicKey)); |
284 | 0 | if (pubk != NULL) { |
285 | 0 | SECStatus rv; |
286 | |
|
287 | 0 | pubk->arena = arena; |
288 | 0 | pubk->keyType = privk->keyType; |
289 | 0 | if (privk->keyType == NSSLOWKEYNullKey) |
290 | 0 | return pubk; |
291 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus, |
292 | 0 | &privk->u.rsa.modulus); |
293 | 0 | if (rv == SECSuccess) { |
294 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent, |
295 | 0 | &privk->u.rsa.publicExponent); |
296 | 0 | if (rv == SECSuccess) |
297 | 0 | return pubk; |
298 | 0 | } |
299 | 0 | } else { |
300 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
301 | 0 | } |
302 | 0 | break; |
303 | 0 | case NSSLOWKEYDSAKey: |
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 | | /* if the public key value doesn't exist, calculate it */ |
312 | 0 | if (privk->u.dsa.publicValue.len == 0) { |
313 | 0 | rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime, |
314 | 0 | &privk->u.dsa.privateValue, &publicValue, 0); |
315 | 0 | if (rv != SECSuccess) { |
316 | 0 | break; |
317 | 0 | } |
318 | 0 | rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue); |
319 | 0 | SECITEM_ZfreeItem(&publicValue, PR_FALSE); |
320 | 0 | if (rv != SECSuccess) { |
321 | 0 | break; |
322 | 0 | } |
323 | 0 | } |
324 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue, |
325 | 0 | &privk->u.dsa.publicValue); |
326 | 0 | if (rv != SECSuccess) |
327 | 0 | break; |
328 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime, |
329 | 0 | &privk->u.dsa.params.prime); |
330 | 0 | if (rv != SECSuccess) |
331 | 0 | break; |
332 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime, |
333 | 0 | &privk->u.dsa.params.subPrime); |
334 | 0 | if (rv != SECSuccess) |
335 | 0 | break; |
336 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base, |
337 | 0 | &privk->u.dsa.params.base); |
338 | 0 | if (rv == SECSuccess) |
339 | 0 | return pubk; |
340 | 0 | } |
341 | 0 | break; |
342 | 0 | case NSSLOWKEYDHKey: |
343 | 0 | pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, |
344 | 0 | sizeof(NSSLOWKEYPublicKey)); |
345 | 0 | if (pubk != NULL) { |
346 | 0 | SECStatus rv; |
347 | |
|
348 | 0 | pubk->arena = arena; |
349 | 0 | pubk->keyType = privk->keyType; |
350 | | /* if the public key value doesn't exist, calculate it */ |
351 | 0 | if (privk->u.dh.publicValue.len == 0) { |
352 | 0 | rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime, |
353 | 0 | &privk->u.dh.privateValue, &publicValue, 0); |
354 | 0 | if (rv != SECSuccess) { |
355 | 0 | break; |
356 | 0 | } |
357 | 0 | rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue); |
358 | 0 | SECITEM_ZfreeItem(&publicValue, PR_FALSE); |
359 | 0 | if (rv != SECSuccess) { |
360 | 0 | break; |
361 | 0 | } |
362 | 0 | } |
363 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue, |
364 | 0 | &privk->u.dh.publicValue); |
365 | 0 | if (rv != SECSuccess) |
366 | 0 | break; |
367 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime, |
368 | 0 | &privk->u.dh.prime); |
369 | 0 | if (rv != SECSuccess) |
370 | 0 | break; |
371 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.dh.base, |
372 | 0 | &privk->u.dh.base); |
373 | 0 | if (rv == SECSuccess) |
374 | 0 | return pubk; |
375 | 0 | } |
376 | 0 | break; |
377 | 0 | case NSSLOWKEYECKey: |
378 | 0 | pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, |
379 | 0 | sizeof(NSSLOWKEYPublicKey)); |
380 | 0 | if (pubk != NULL) { |
381 | 0 | SECStatus rv; |
382 | |
|
383 | 0 | pubk->arena = arena; |
384 | 0 | pubk->keyType = privk->keyType; |
385 | | |
386 | | /* if the public key value doesn't exist, calculate it */ |
387 | 0 | if (privk->u.ec.publicValue.len == 0) { |
388 | | /* Checking if it's an ed25519 or x25519 key. |
389 | | If it's the case, we derive the public key using the private key. */ |
390 | 0 | SECOidTag privKeyOIDTag = SECOID_FindOIDTag(&privk->u.ec.ecParams.curveOID); |
391 | 0 | if (privKeyOIDTag == SEC_OID_ED25519_PUBLIC_KEY) { |
392 | 0 | PORT_Memset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue)); |
393 | 0 | if (SECITEM_AllocItem(privk->arena, &privk->u.ec.publicValue, Ed25519_PUBLIC_KEYLEN) == NULL) { |
394 | 0 | break; |
395 | 0 | } |
396 | | |
397 | 0 | rv = ED_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue); |
398 | 0 | if (rv != CKR_OK) { |
399 | 0 | break; |
400 | 0 | } |
401 | 0 | } else if (privKeyOIDTag == SEC_OID_X25519) { |
402 | 0 | PORT_Memset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue)); |
403 | 0 | if (SECITEM_AllocItem(privk->arena, &privk->u.ec.publicValue, X25519_PUBLIC_KEYLEN) == NULL) { |
404 | 0 | break; |
405 | 0 | } |
406 | | |
407 | 0 | rv = X25519_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue); |
408 | 0 | if (rv != CKR_OK) { |
409 | 0 | break; |
410 | 0 | } |
411 | 0 | } |
412 | 0 | } |
413 | | |
414 | 0 | rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, |
415 | 0 | &privk->u.ec.publicValue); |
416 | 0 | if (rv != SECSuccess) |
417 | 0 | break; |
418 | 0 | pubk->u.ec.ecParams.arena = arena; |
419 | | /* Copy the rest of the params */ |
420 | 0 | rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams), |
421 | 0 | &(privk->u.ec.ecParams)); |
422 | 0 | if (rv == SECSuccess) |
423 | 0 | return pubk; |
424 | 0 | } |
425 | 0 | break; |
426 | | /* No Fortezza in Low Key implementations (Fortezza keys aren't |
427 | | * stored in our data base */ |
428 | 0 | default: |
429 | 0 | break; |
430 | 0 | } |
431 | | |
432 | 0 | PORT_FreeArena(arena, PR_TRUE); |
433 | 0 | return NULL; |
434 | 0 | } |
435 | | |
436 | | NSSLOWKEYPrivateKey * |
437 | | nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey) |
438 | 0 | { |
439 | 0 | NSSLOWKEYPrivateKey *returnKey = NULL; |
440 | 0 | SECStatus rv = SECFailure; |
441 | 0 | PLArenaPool *poolp; |
442 | |
|
443 | 0 | if (!privKey) { |
444 | 0 | return NULL; |
445 | 0 | } |
446 | | |
447 | 0 | poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
448 | 0 | if (!poolp) { |
449 | 0 | return NULL; |
450 | 0 | } |
451 | | |
452 | 0 | returnKey = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey)); |
453 | 0 | if (!returnKey) { |
454 | 0 | rv = SECFailure; |
455 | 0 | goto loser; |
456 | 0 | } |
457 | | |
458 | 0 | returnKey->keyType = privKey->keyType; |
459 | 0 | returnKey->arena = poolp; |
460 | |
|
461 | 0 | switch (privKey->keyType) { |
462 | 0 | case NSSLOWKEYRSAKey: |
463 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus), |
464 | 0 | &(privKey->u.rsa.modulus)); |
465 | 0 | if (rv != SECSuccess) |
466 | 0 | break; |
467 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version), |
468 | 0 | &(privKey->u.rsa.version)); |
469 | 0 | if (rv != SECSuccess) |
470 | 0 | break; |
471 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent), |
472 | 0 | &(privKey->u.rsa.publicExponent)); |
473 | 0 | if (rv != SECSuccess) |
474 | 0 | break; |
475 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent), |
476 | 0 | &(privKey->u.rsa.privateExponent)); |
477 | 0 | if (rv != SECSuccess) |
478 | 0 | break; |
479 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1), |
480 | 0 | &(privKey->u.rsa.prime1)); |
481 | 0 | if (rv != SECSuccess) |
482 | 0 | break; |
483 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2), |
484 | 0 | &(privKey->u.rsa.prime2)); |
485 | 0 | if (rv != SECSuccess) |
486 | 0 | break; |
487 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1), |
488 | 0 | &(privKey->u.rsa.exponent1)); |
489 | 0 | if (rv != SECSuccess) |
490 | 0 | break; |
491 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2), |
492 | 0 | &(privKey->u.rsa.exponent2)); |
493 | 0 | if (rv != SECSuccess) |
494 | 0 | break; |
495 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient), |
496 | 0 | &(privKey->u.rsa.coefficient)); |
497 | 0 | if (rv != SECSuccess) |
498 | 0 | break; |
499 | 0 | break; |
500 | 0 | case NSSLOWKEYDSAKey: |
501 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue), |
502 | 0 | &(privKey->u.dsa.publicValue)); |
503 | 0 | if (rv != SECSuccess) |
504 | 0 | break; |
505 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue), |
506 | 0 | &(privKey->u.dsa.privateValue)); |
507 | 0 | if (rv != SECSuccess) |
508 | 0 | break; |
509 | 0 | returnKey->u.dsa.params.arena = poolp; |
510 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime), |
511 | 0 | &(privKey->u.dsa.params.prime)); |
512 | 0 | if (rv != SECSuccess) |
513 | 0 | break; |
514 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime), |
515 | 0 | &(privKey->u.dsa.params.subPrime)); |
516 | 0 | if (rv != SECSuccess) |
517 | 0 | break; |
518 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base), |
519 | 0 | &(privKey->u.dsa.params.base)); |
520 | 0 | if (rv != SECSuccess) |
521 | 0 | break; |
522 | 0 | break; |
523 | 0 | case NSSLOWKEYDHKey: |
524 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue), |
525 | 0 | &(privKey->u.dh.publicValue)); |
526 | 0 | if (rv != SECSuccess) |
527 | 0 | break; |
528 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue), |
529 | 0 | &(privKey->u.dh.privateValue)); |
530 | 0 | if (rv != SECSuccess) |
531 | 0 | break; |
532 | 0 | returnKey->u.dsa.params.arena = poolp; |
533 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime), |
534 | 0 | &(privKey->u.dh.prime)); |
535 | 0 | if (rv != SECSuccess) |
536 | 0 | break; |
537 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base), |
538 | 0 | &(privKey->u.dh.base)); |
539 | 0 | if (rv != SECSuccess) |
540 | 0 | break; |
541 | 0 | break; |
542 | 0 | case NSSLOWKEYECKey: |
543 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version), |
544 | 0 | &(privKey->u.ec.version)); |
545 | 0 | if (rv != SECSuccess) |
546 | 0 | break; |
547 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue), |
548 | 0 | &(privKey->u.ec.publicValue)); |
549 | 0 | if (rv != SECSuccess) |
550 | 0 | break; |
551 | 0 | rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue), |
552 | 0 | &(privKey->u.ec.privateValue)); |
553 | 0 | if (rv != SECSuccess) |
554 | 0 | break; |
555 | 0 | returnKey->u.ec.ecParams.arena = poolp; |
556 | | /* Copy the rest of the params */ |
557 | 0 | rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams), |
558 | 0 | &(privKey->u.ec.ecParams)); |
559 | 0 | if (rv != SECSuccess) |
560 | 0 | break; |
561 | 0 | break; |
562 | 0 | default: |
563 | 0 | rv = SECFailure; |
564 | 0 | } |
565 | | |
566 | 0 | loser: |
567 | |
|
568 | 0 | if (rv != SECSuccess) { |
569 | 0 | PORT_FreeArena(poolp, PR_TRUE); |
570 | 0 | returnKey = NULL; |
571 | 0 | } |
572 | |
|
573 | 0 | return returnKey; |
574 | 0 | } |