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