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