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