summaryrefslogtreecommitdiff
path: root/security/nss/lib/softoken/legacydb/lowkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/softoken/legacydb/lowkey.c')
-rw-r--r--security/nss/lib/softoken/legacydb/lowkey.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/security/nss/lib/softoken/legacydb/lowkey.c b/security/nss/lib/softoken/legacydb/lowkey.c
new file mode 100644
index 000000000..5ee64d1f2
--- /dev/null
+++ b/security/nss/lib/softoken/legacydb/lowkey.c
@@ -0,0 +1,468 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "lowkeyi.h"
+#include "secoid.h"
+#include "secitem.h"
+#include "secder.h"
+#include "secasn1.h"
+#include "secerr.h"
+
+SEC_ASN1_MKSUB(SEC_AnyTemplate)
+SEC_ASN1_MKSUB(SEC_BitStringTemplate)
+SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+
+static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYAttribute) },
+ { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
+ { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue),
+ SEC_ASN1_SUB(SEC_AnyTemplate) },
+ { 0 }
+};
+
+static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
+};
+/* ASN1 Templates for new decoder/encoder */
+const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
+ { SEC_ASN1_INTEGER,
+ offsetof(NSSLOWKEYPrivateKeyInfo,version) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
+ nsslowkey_SetOfAttributeTemplate },
+ { 0 }
+};
+
+const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
+ { 0, }
+};
+
+const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
+ { 0 }
+};
+
+
+const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
+ { 0, }
+};
+
+const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
+};
+
+const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
+ { 0, }
+};
+
+#ifdef NSS_ENABLE_ECC
+
+/* XXX This is just a placeholder for later when we support
+ * generic curves and need full-blown support for parsing EC
+ * parameters. For now, we only support named curves in which
+ * EC params are simply encoded as an object ID and we don't
+ * use nsslowkey_ECParamsTemplate.
+ */
+const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
+ { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
+ { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
+ { 0, }
+};
+
+
+/* NOTE: The SECG specification allows the private key structure
+ * to contain curve parameters but recommends that they be stored
+ * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
+ * instead.
+ */
+const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
+ /* XXX The following template works for now since we only
+ * support named curves for which the parameters are
+ * encoded as an object ID. When we support generic curves,
+ * we'll need to define nsslowkey_ECParamsTemplate
+ */
+#if 1
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID),
+ SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
+#else
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams),
+ nsslowkey_ECParamsTemplate },
+#endif
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
+ SEC_ASN1_XTRN | 1,
+ offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
+ SEC_ASN1_SUB(SEC_BitStringTemplate) },
+ { 0, }
+};
+
+
+/*
+ * smaller version of EC_FillParams. In this code, we only need
+ * oid and DER data.
+ */
+SECStatus
+LGEC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
+ ECParams *params)
+{
+ SECOidTag tag;
+ SECItem oid = { siBuffer, NULL, 0};
+
+#if EC_DEBUG
+ int i;
+
+ printf("Encoded params in EC_DecodeParams: ");
+ for (i = 0; i < encodedParams->len; i++) {
+ printf("%02x:", encodedParams->data[i]);
+ }
+ printf("\n");
+#endif
+
+ oid.len = encodedParams->len - 2;
+ oid.data = encodedParams->data + 2;
+ if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
+ ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
+ params->arena = arena;
+
+ /* For named curves, fill out curveOID */
+ params->curveOID.len = oid.len;
+ params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len);
+ if (params->curveOID.data == NULL) {
+ return SECFailure;
+ }
+ memcpy(params->curveOID.data, oid.data, oid.len);
+
+ return SECSuccess;
+}
+
+/* Copy all of the fields from srcParams into dstParams
+ */
+SECStatus
+LGEC_CopyParams(PRArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams)
+{
+ SECStatus rv = SECFailure;
+
+ dstParams->arena = arena;
+ rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
+ &srcParams->DEREncoding);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv =SECITEM_CopyItem(arena, &dstParams->curveOID,
+ &srcParams->curveOID);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ return SECSuccess;
+
+loser:
+ return SECFailure;
+}
+#endif /* NSS_ENABLE_ECC */
+/*
+ * See bugzilla bug 125359
+ * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
+ * all of the templates above that en/decode into integers must be converted
+ * from ASN.1's signed integer type. This is done by marking either the
+ * source or destination (encoding or decoding, respectively) type as
+ * siUnsignedInteger.
+ */
+
+void
+prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.rsa.modulus.type = siUnsignedInteger;
+ key->u.rsa.publicExponent.type = siUnsignedInteger;
+ key->u.rsa.privateExponent.type = siUnsignedInteger;
+ key->u.rsa.prime1.type = siUnsignedInteger;
+ key->u.rsa.prime2.type = siUnsignedInteger;
+ key->u.rsa.exponent1.type = siUnsignedInteger;
+ key->u.rsa.exponent2.type = siUnsignedInteger;
+ key->u.rsa.coefficient.type = siUnsignedInteger;
+}
+
+void
+prepare_low_pqg_params_for_asn1(PQGParams *params)
+{
+ params->prime.type = siUnsignedInteger;
+ params->subPrime.type = siUnsignedInteger;
+ params->base.type = siUnsignedInteger;
+}
+
+void
+prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.dsa.publicValue.type = siUnsignedInteger;
+ key->u.dsa.privateValue.type = siUnsignedInteger;
+ key->u.dsa.params.prime.type = siUnsignedInteger;
+ key->u.dsa.params.subPrime.type = siUnsignedInteger;
+ key->u.dsa.params.base.type = siUnsignedInteger;
+}
+
+void
+prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.dsa.privateValue.type = siUnsignedInteger;
+}
+
+void
+prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.dh.prime.type = siUnsignedInteger;
+ key->u.dh.base.type = siUnsignedInteger;
+ key->u.dh.publicValue.type = siUnsignedInteger;
+ key->u.dh.privateValue.type = siUnsignedInteger;
+}
+
+#ifdef NSS_ENABLE_ECC
+void
+prepare_low_ecparams_for_asn1(ECParams *params)
+{
+ params->DEREncoding.type = siUnsignedInteger;
+ params->curveOID.type = siUnsignedInteger;
+}
+
+void
+prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
+{
+ key->u.ec.version.type = siUnsignedInteger;
+ key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
+ key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
+ key->u.ec.privateValue.type = siUnsignedInteger;
+ key->u.ec.publicValue.type = siUnsignedInteger;
+}
+#endif /* NSS_ENABLE_ECC */
+
+void
+nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
+{
+ if (privk && privk->arena) {
+ PORT_FreeArena(privk->arena, PR_TRUE);
+ }
+}
+
+void
+nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
+{
+ if (pubk && pubk->arena) {
+ PORT_FreeArena(pubk->arena, PR_FALSE);
+ }
+}
+unsigned
+nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
+{
+ unsigned char b0;
+
+ /* interpret modulus length as key strength... in
+ * fortezza that's the public key length */
+
+ switch (pubk->keyType) {
+ case NSSLOWKEYRSAKey:
+ b0 = pubk->u.rsa.modulus.data[0];
+ return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+unsigned
+nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
+{
+
+ unsigned char b0;
+
+ switch (privk->keyType) {
+ case NSSLOWKEYRSAKey:
+ b0 = privk->u.rsa.modulus.data[0];
+ return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+NSSLOWKEYPublicKey *
+nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
+{
+ NSSLOWKEYPublicKey *pubk;
+ PLArenaPool *arena;
+
+
+ arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ switch(privk->keyType) {
+ case NSSLOWKEYRSAKey:
+ case NSSLOWKEYNullKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof (NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ if (privk->keyType == NSSLOWKEYNullKey) return pubk;
+ rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
+ &privk->u.rsa.modulus);
+ if (rv == SECSuccess) {
+ rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
+ &privk->u.rsa.publicExponent);
+ if (rv == SECSuccess)
+ return pubk;
+ }
+ } else {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ }
+ break;
+ case NSSLOWKEYDSAKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
+ &privk->u.dsa.publicValue);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
+ &privk->u.dsa.params.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
+ &privk->u.dsa.params.subPrime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
+ &privk->u.dsa.params.base);
+ if (rv == SECSuccess) return pubk;
+ }
+ break;
+ case NSSLOWKEYDHKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
+ &privk->u.dh.publicValue);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
+ &privk->u.dh.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
+ &privk->u.dh.base);
+ if (rv == SECSuccess) return pubk;
+ }
+ break;
+#ifdef NSS_ENABLE_ECC
+ case NSSLOWKEYECKey:
+ pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPublicKey));
+ if (pubk != NULL) {
+ SECStatus rv;
+
+ pubk->arena = arena;
+ pubk->keyType = privk->keyType;
+ rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
+ &privk->u.ec.publicValue);
+ if (rv != SECSuccess) break;
+ pubk->u.ec.ecParams.arena = arena;
+ /* Copy the rest of the params */
+ rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
+ &(privk->u.ec.ecParams));
+ if (rv == SECSuccess) return pubk;
+ }
+ break;
+#endif /* NSS_ENABLE_ECC */
+ /* No Fortezza in Low Key implementations (Fortezza keys aren't
+ * stored in our data base */
+ default:
+ break;
+ }
+
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+}
+