Import 1.9b4 NSS tag from cvs
[mozilla-nss.git] / security / nss / lib / softoken / legacydb / lowkey.c
blob5ee64d1f247f5c8d3af931926a99ebe2d6a127f7
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 #include "lowkeyi.h"
38 #include "secoid.h"
39 #include "secitem.h"
40 #include "secder.h"
41 #include "secasn1.h"
42 #include "secerr.h"
44 SEC_ASN1_MKSUB(SEC_AnyTemplate)
45 SEC_ASN1_MKSUB(SEC_BitStringTemplate)
46 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
47 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
49 static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
50 { SEC_ASN1_SEQUENCE,
51 0, NULL, sizeof(NSSLOWKEYAttribute) },
52 { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
53 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue),
54 SEC_ASN1_SUB(SEC_AnyTemplate) },
55 { 0 }
58 static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
59 { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
61 /* ASN1 Templates for new decoder/encoder */
62 const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
63 { SEC_ASN1_SEQUENCE,
64 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
65 { SEC_ASN1_INTEGER,
66 offsetof(NSSLOWKEYPrivateKeyInfo,version) },
67 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
68 offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
69 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
70 { SEC_ASN1_OCTET_STRING,
71 offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
72 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
73 offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
74 nsslowkey_SetOfAttributeTemplate },
75 { 0 }
78 const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
79 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
80 { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
81 { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
82 { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
83 { 0, }
86 const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
87 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
88 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
89 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
90 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
91 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
92 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
93 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
94 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
95 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
96 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
97 { 0 }
98 };
101 const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
102 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
103 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
104 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
105 { 0, }
108 const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
109 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
112 const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
113 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
114 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
115 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
116 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
117 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
118 { 0, }
121 #ifdef NSS_ENABLE_ECC
123 /* XXX This is just a placeholder for later when we support
124 * generic curves and need full-blown support for parsing EC
125 * parameters. For now, we only support named curves in which
126 * EC params are simply encoded as an object ID and we don't
127 * use nsslowkey_ECParamsTemplate.
129 const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
130 { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
131 { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
132 { 0, }
136 /* NOTE: The SECG specification allows the private key structure
137 * to contain curve parameters but recommends that they be stored
138 * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
139 * instead.
141 const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
142 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
143 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
144 { SEC_ASN1_OCTET_STRING,
145 offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
146 /* XXX The following template works for now since we only
147 * support named curves for which the parameters are
148 * encoded as an object ID. When we support generic curves,
149 * we'll need to define nsslowkey_ECParamsTemplate
151 #if 1
152 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
153 SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
154 offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
155 SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
156 #else
157 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
158 SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
159 offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
160 nsslowkey_ECParamsTemplate },
161 #endif
162 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
163 SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
164 SEC_ASN1_XTRN | 1,
165 offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
166 SEC_ASN1_SUB(SEC_BitStringTemplate) },
167 { 0, }
172 * smaller version of EC_FillParams. In this code, we only need
173 * oid and DER data.
175 SECStatus
176 LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
177 ECParams *params)
179 SECOidTag tag;
180 SECItem oid = { siBuffer, NULL, 0};
182 #if EC_DEBUG
183 int i;
185 printf("Encoded params in EC_DecodeParams: ");
186 for (i = 0; i < encodedParams->len; i++) {
187 printf("%02x:", encodedParams->data[i]);
189 printf("\n");
190 #endif
192 oid.len = encodedParams->len - 2;
193 oid.data = encodedParams->data + 2;
194 if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
195 ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
196 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
197 return SECFailure;
200 params->arena = arena;
202 /* For named curves, fill out curveOID */
203 params->curveOID.len = oid.len;
204 params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
205 if (params->curveOID.data == NULL) {
206 return SECFailure;
208 memcpy(params->curveOID.data, oid.data, oid.len);
210 return SECSuccess;
213 /* Copy all of the fields from srcParams into dstParams
215 SECStatus
216 LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
217 const ECParams *srcParams)
219 SECStatus rv = SECFailure;
221 dstParams->arena = arena;
222 rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
223 &srcParams->DEREncoding);
224 if (rv != SECSuccess) {
225 goto loser;
227 rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
228 &srcParams->curveOID);
229 if (rv != SECSuccess) {
230 goto loser;
233 return SECSuccess;
235 loser:
236 return SECFailure;
238 #endif /* NSS_ENABLE_ECC */
240 * See bugzilla bug 125359
241 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
242 * all of the templates above that en/decode into integers must be converted
243 * from ASN.1's signed integer type. This is done by marking either the
244 * source or destination (encoding or decoding, respectively) type as
245 * siUnsignedInteger.
248 void
249 prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
251 key->u.rsa.modulus.type = siUnsignedInteger;
252 key->u.rsa.publicExponent.type = siUnsignedInteger;
253 key->u.rsa.privateExponent.type = siUnsignedInteger;
254 key->u.rsa.prime1.type = siUnsignedInteger;
255 key->u.rsa.prime2.type = siUnsignedInteger;
256 key->u.rsa.exponent1.type = siUnsignedInteger;
257 key->u.rsa.exponent2.type = siUnsignedInteger;
258 key->u.rsa.coefficient.type = siUnsignedInteger;
261 void
262 prepare_low_pqg_params_for_asn1(PQGParams *params)
264 params->prime.type = siUnsignedInteger;
265 params->subPrime.type = siUnsignedInteger;
266 params->base.type = siUnsignedInteger;
269 void
270 prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
272 key->u.dsa.publicValue.type = siUnsignedInteger;
273 key->u.dsa.privateValue.type = siUnsignedInteger;
274 key->u.dsa.params.prime.type = siUnsignedInteger;
275 key->u.dsa.params.subPrime.type = siUnsignedInteger;
276 key->u.dsa.params.base.type = siUnsignedInteger;
279 void
280 prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
282 key->u.dsa.privateValue.type = siUnsignedInteger;
285 void
286 prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
288 key->u.dh.prime.type = siUnsignedInteger;
289 key->u.dh.base.type = siUnsignedInteger;
290 key->u.dh.publicValue.type = siUnsignedInteger;
291 key->u.dh.privateValue.type = siUnsignedInteger;
294 #ifdef NSS_ENABLE_ECC
295 void
296 prepare_low_ecparams_for_asn1(ECParams *params)
298 params->DEREncoding.type = siUnsignedInteger;
299 params->curveOID.type = siUnsignedInteger;
302 void
303 prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
305 key->u.ec.version.type = siUnsignedInteger;
306 key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
307 key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
308 key->u.ec.privateValue.type = siUnsignedInteger;
309 key->u.ec.publicValue.type = siUnsignedInteger;
311 #endif /* NSS_ENABLE_ECC */
313 void
314 nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
316 if (privk && privk->arena) {
317 PORT_FreeArena(privk->arena, PR_TRUE);
321 void
322 nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
324 if (pubk && pubk->arena) {
325 PORT_FreeArena(pubk->arena, PR_FALSE);
328 unsigned
329 nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
331 unsigned char b0;
333 /* interpret modulus length as key strength... in
334 * fortezza that's the public key length */
336 switch (pubk->keyType) {
337 case NSSLOWKEYRSAKey:
338 b0 = pubk->u.rsa.modulus.data[0];
339 return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
340 default:
341 break;
343 return 0;
346 unsigned
347 nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
350 unsigned char b0;
352 switch (privk->keyType) {
353 case NSSLOWKEYRSAKey:
354 b0 = privk->u.rsa.modulus.data[0];
355 return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
356 default:
357 break;
359 return 0;
362 NSSLOWKEYPublicKey *
363 nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
365 NSSLOWKEYPublicKey *pubk;
366 PLArenaPool *arena;
369 arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
370 if (arena == NULL) {
371 PORT_SetError (SEC_ERROR_NO_MEMORY);
372 return NULL;
375 switch(privk->keyType) {
376 case NSSLOWKEYRSAKey:
377 case NSSLOWKEYNullKey:
378 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
379 sizeof (NSSLOWKEYPublicKey));
380 if (pubk != NULL) {
381 SECStatus rv;
383 pubk->arena = arena;
384 pubk->keyType = privk->keyType;
385 if (privk->keyType == NSSLOWKEYNullKey) return pubk;
386 rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
387 &privk->u.rsa.modulus);
388 if (rv == SECSuccess) {
389 rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
390 &privk->u.rsa.publicExponent);
391 if (rv == SECSuccess)
392 return pubk;
394 } else {
395 PORT_SetError (SEC_ERROR_NO_MEMORY);
397 break;
398 case NSSLOWKEYDSAKey:
399 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
400 sizeof(NSSLOWKEYPublicKey));
401 if (pubk != NULL) {
402 SECStatus rv;
404 pubk->arena = arena;
405 pubk->keyType = privk->keyType;
406 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
407 &privk->u.dsa.publicValue);
408 if (rv != SECSuccess) break;
409 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
410 &privk->u.dsa.params.prime);
411 if (rv != SECSuccess) break;
412 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
413 &privk->u.dsa.params.subPrime);
414 if (rv != SECSuccess) break;
415 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
416 &privk->u.dsa.params.base);
417 if (rv == SECSuccess) return pubk;
419 break;
420 case NSSLOWKEYDHKey:
421 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
422 sizeof(NSSLOWKEYPublicKey));
423 if (pubk != NULL) {
424 SECStatus rv;
426 pubk->arena = arena;
427 pubk->keyType = privk->keyType;
428 rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
429 &privk->u.dh.publicValue);
430 if (rv != SECSuccess) break;
431 rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
432 &privk->u.dh.prime);
433 if (rv != SECSuccess) break;
434 rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
435 &privk->u.dh.base);
436 if (rv == SECSuccess) return pubk;
438 break;
439 #ifdef NSS_ENABLE_ECC
440 case NSSLOWKEYECKey:
441 pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
442 sizeof(NSSLOWKEYPublicKey));
443 if (pubk != NULL) {
444 SECStatus rv;
446 pubk->arena = arena;
447 pubk->keyType = privk->keyType;
448 rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
449 &privk->u.ec.publicValue);
450 if (rv != SECSuccess) break;
451 pubk->u.ec.ecParams.arena = arena;
452 /* Copy the rest of the params */
453 rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
454 &(privk->u.ec.ecParams));
455 if (rv == SECSuccess) return pubk;
457 break;
458 #endif /* NSS_ENABLE_ECC */
459 /* No Fortezza in Low Key implementations (Fortezza keys aren't
460 * stored in our data base */
461 default:
462 break;
465 PORT_FreeArena (arena, PR_FALSE);
466 return NULL;