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 "secasn1.h"
9 #include "secerr.h"
10 
11 SEC_ASN1_MKSUB(SEC_AnyTemplate)
12 SEC_ASN1_MKSUB(SEC_BitStringTemplate)
13 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
14 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
15 
16 static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
17     { SEC_ASN1_SEQUENCE,
18       0, NULL, sizeof(NSSLOWKEYAttribute) },
19     { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
20     { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue),
21       SEC_ASN1_SUB(SEC_AnyTemplate) },
22     { 0 }
23 };
24 
25 static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
26     { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
27 };
28 /* ASN1 Templates for new decoder/encoder */
29 const SEC_ASN1Template lg_nsslowkey_PrivateKeyInfoTemplate[] = {
30     { SEC_ASN1_SEQUENCE,
31       0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
32     { SEC_ASN1_INTEGER,
33       offsetof(NSSLOWKEYPrivateKeyInfo, version) },
34     { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
35       offsetof(NSSLOWKEYPrivateKeyInfo, algorithm),
36       SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
37     { SEC_ASN1_OCTET_STRING,
38       offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) },
39     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
40       offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
41       nsslowkey_SetOfAttributeTemplate },
42     { 0 }
43 };
44 
45 const SEC_ASN1Template lg_nsslowkey_PQGParamsTemplate[] = {
46     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
47     { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) },
48     { SEC_ASN1_INTEGER, offsetof(PQGParams, subPrime) },
49     { SEC_ASN1_INTEGER, offsetof(PQGParams, base) },
50     { 0 }
51 };
52 
53 const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate[] = {
54     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
55     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
56     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
57     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
58     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) },
59     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
60     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
61     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
62     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
63     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
64     { 0 }
65 };
66 
67 /*
68  * Allows u.rsa.modulus to be zero length for secret keys with an empty
69  * CKA_ID incorrectly generated in NSS 3.13.3 or earlier.  Only used for
70  * decoding.  See bug 715073.
71  */
72 const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate2[] = {
73     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
74     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
75     { SEC_ASN1_ANY, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
76     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
77     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) },
78     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
79     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
80     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
81     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
82     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
83     { 0 }
84 };
85 
86 const SEC_ASN1Template lg_nsslowkey_DSAPrivateKeyTemplate[] = {
87     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
88     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) },
89     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
90     { 0 }
91 };
92 
93 const SEC_ASN1Template lg_nsslowkey_DHPrivateKeyTemplate[] = {
94     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
95     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) },
96     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) },
97     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.base) },
98     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.prime) },
99     { 0 }
100 };
101 
102 /* NOTE: The SECG specification allows the private key structure
103  * to contain curve parameters but recommends that they be stored
104  * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
105  * instead.
106  */
107 const SEC_ASN1Template lg_nsslowkey_ECPrivateKeyTemplate[] = {
108     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
109     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.ec.version) },
110     { SEC_ASN1_OCTET_STRING,
111       offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) },
112     /* We only support named curves for which the parameters are
113      * encoded as an object ID.
114      */
115     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
116           SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
117       offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID),
118       SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
119     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
120           SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
121           SEC_ASN1_XTRN | 1,
122       offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue),
123       SEC_ASN1_SUB(SEC_BitStringTemplate) },
124     { 0 }
125 };
126 
127 /*
128  * smaller version of EC_FillParams. In this code, we only need
129  * oid and DER data.
130  */
131 SECStatus
LGEC_FillParams(PLArenaPool * arena,const SECItem * encodedParams,ECParams * params)132 LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
133                 ECParams *params)
134 {
135     SECOidTag tag;
136     SECItem oid = { siBuffer, NULL, 0 };
137 
138 #if EC_DEBUG
139     int i;
140 
141     printf("Encoded params in EC_DecodeParams: ");
142     for (i = 0; i < encodedParams->len; i++) {
143         printf("%02x:", encodedParams->data[i]);
144     }
145     printf("\n");
146 #endif
147 
148     oid.len = encodedParams->len - 2;
149     oid.data = encodedParams->data + 2;
150     if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
151         ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
152         PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
153         return SECFailure;
154     }
155 
156     params->arena = arena;
157 
158     /* For named curves, fill out curveOID */
159     params->curveOID.len = oid.len;
160     params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len);
161     if (params->curveOID.data == NULL) {
162         return SECFailure;
163     }
164     memcpy(params->curveOID.data, oid.data, oid.len);
165 
166     return SECSuccess;
167 }
168 
169 /* Copy all of the fields from srcParams into dstParams
170  */
171 SECStatus
LGEC_CopyParams(PLArenaPool * arena,ECParams * dstParams,const ECParams * srcParams)172 LGEC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
173                 const ECParams *srcParams)
174 {
175     SECStatus rv = SECFailure;
176 
177     dstParams->arena = arena;
178     rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
179                           &srcParams->DEREncoding);
180     if (rv != SECSuccess) {
181         goto loser;
182     }
183     rv = SECITEM_CopyItem(arena, &dstParams->curveOID,
184                           &srcParams->curveOID);
185     if (rv != SECSuccess) {
186         goto loser;
187     }
188 
189     return SECSuccess;
190 
191 loser:
192     return SECFailure;
193 }
194 /*
195  * See bugzilla bug 125359
196  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
197  * all of the templates above that en/decode into integers must be converted
198  * from ASN.1's signed integer type.  This is done by marking either the
199  * source or destination (encoding or decoding, respectively) type as
200  * siUnsignedInteger.
201  */
202 
203 void
lg_prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey * key)204 lg_prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
205 {
206     key->u.rsa.modulus.type = siUnsignedInteger;
207     key->u.rsa.publicExponent.type = siUnsignedInteger;
208     key->u.rsa.privateExponent.type = siUnsignedInteger;
209     key->u.rsa.prime1.type = siUnsignedInteger;
210     key->u.rsa.prime2.type = siUnsignedInteger;
211     key->u.rsa.exponent1.type = siUnsignedInteger;
212     key->u.rsa.exponent2.type = siUnsignedInteger;
213     key->u.rsa.coefficient.type = siUnsignedInteger;
214 }
215 
216 void
lg_prepare_low_pqg_params_for_asn1(PQGParams * params)217 lg_prepare_low_pqg_params_for_asn1(PQGParams *params)
218 {
219     params->prime.type = siUnsignedInteger;
220     params->subPrime.type = siUnsignedInteger;
221     params->base.type = siUnsignedInteger;
222 }
223 
224 void
lg_prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey * key)225 lg_prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
226 {
227     key->u.dsa.publicValue.type = siUnsignedInteger;
228     key->u.dsa.privateValue.type = siUnsignedInteger;
229     key->u.dsa.params.prime.type = siUnsignedInteger;
230     key->u.dsa.params.subPrime.type = siUnsignedInteger;
231     key->u.dsa.params.base.type = siUnsignedInteger;
232 }
233 
234 void
lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey * key)235 lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
236 {
237     key->u.dh.prime.type = siUnsignedInteger;
238     key->u.dh.base.type = siUnsignedInteger;
239     key->u.dh.publicValue.type = siUnsignedInteger;
240     key->u.dh.privateValue.type = siUnsignedInteger;
241 }
242 
243 void
lg_prepare_low_ecparams_for_asn1(ECParams * params)244 lg_prepare_low_ecparams_for_asn1(ECParams *params)
245 {
246     params->DEREncoding.type = siUnsignedInteger;
247     params->curveOID.type = siUnsignedInteger;
248 }
249 
250 void
lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey * key)251 lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
252 {
253     key->u.ec.version.type = siUnsignedInteger;
254     key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
255     key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
256     key->u.ec.privateValue.type = siUnsignedInteger;
257     key->u.ec.publicValue.type = siUnsignedInteger;
258 }
259 
260 void
lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey * privk)261 lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
262 {
263     if (privk && privk->arena) {
264         PORT_FreeArena(privk->arena, PR_TRUE);
265     }
266 }
267 
268 void
lg_nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey * pubk)269 lg_nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
270 {
271     if (pubk && pubk->arena) {
272         PORT_FreeArena(pubk->arena, PR_FALSE);
273     }
274 }
275 
276 NSSLOWKEYPublicKey *
lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey * privk)277 lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
278 {
279     NSSLOWKEYPublicKey *pubk;
280     PLArenaPool *arena;
281 
282     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
283     if (arena == NULL) {
284         PORT_SetError(SEC_ERROR_NO_MEMORY);
285         return NULL;
286     }
287 
288     switch (privk->keyType) {
289         case NSSLOWKEYRSAKey:
290         case NSSLOWKEYNullKey:
291             pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
292                                                           sizeof(NSSLOWKEYPublicKey));
293             if (pubk != NULL) {
294                 SECStatus rv;
295 
296                 pubk->arena = arena;
297                 pubk->keyType = privk->keyType;
298                 if (privk->keyType == NSSLOWKEYNullKey)
299                     return pubk;
300                 rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
301                                       &privk->u.rsa.modulus);
302                 if (rv == SECSuccess) {
303                     rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent,
304                                           &privk->u.rsa.publicExponent);
305                     if (rv == SECSuccess)
306                         return pubk;
307                 }
308             } else {
309                 PORT_SetError(SEC_ERROR_NO_MEMORY);
310             }
311             break;
312         case NSSLOWKEYDSAKey:
313             pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
314                                                           sizeof(NSSLOWKEYPublicKey));
315             if (pubk != NULL) {
316                 SECStatus rv;
317 
318                 pubk->arena = arena;
319                 pubk->keyType = privk->keyType;
320                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
321                                       &privk->u.dsa.publicValue);
322                 if (rv != SECSuccess)
323                     break;
324                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
325                                       &privk->u.dsa.params.prime);
326                 if (rv != SECSuccess)
327                     break;
328                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
329                                       &privk->u.dsa.params.subPrime);
330                 if (rv != SECSuccess)
331                     break;
332                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
333                                       &privk->u.dsa.params.base);
334                 if (rv == SECSuccess)
335                     return pubk;
336             }
337             break;
338         case NSSLOWKEYDHKey:
339             pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
340                                                           sizeof(NSSLOWKEYPublicKey));
341             if (pubk != NULL) {
342                 SECStatus rv;
343 
344                 pubk->arena = arena;
345                 pubk->keyType = privk->keyType;
346                 rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
347                                       &privk->u.dh.publicValue);
348                 if (rv != SECSuccess)
349                     break;
350                 rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
351                                       &privk->u.dh.prime);
352                 if (rv != SECSuccess)
353                     break;
354                 rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
355                                       &privk->u.dh.base);
356                 if (rv == SECSuccess)
357                     return pubk;
358             }
359             break;
360         case NSSLOWKEYECKey:
361             pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
362                                                           sizeof(NSSLOWKEYPublicKey));
363             if (pubk != NULL) {
364                 SECStatus rv;
365 
366                 pubk->arena = arena;
367                 pubk->keyType = privk->keyType;
368                 rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
369                                       &privk->u.ec.publicValue);
370                 if (rv != SECSuccess)
371                     break;
372                 pubk->u.ec.ecParams.arena = arena;
373                 /* Copy the rest of the params */
374                 rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
375                                      &(privk->u.ec.ecParams));
376                 if (rv == SECSuccess)
377                     return pubk;
378             }
379             break;
380         /* No Fortezza in Low Key implementations (Fortezza keys aren't
381          * stored in our data base */
382         default:
383             break;
384     }
385 
386     PORT_FreeArena(arena, PR_FALSE);
387     return NULL;
388 }
389