summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWyllys Ingersoll <wyllys.ingersoll@sun.com>2010-03-22 13:57:47 -0700
committerWyllys Ingersoll <wyllys.ingersoll@sun.com>2010-03-22 13:57:47 -0700
commite65e5c2d2f32a99e8c5f740cabae9075dab03ce7 (patch)
tree09b70c15a705c7de105b96d1c7c0057ebc13b9e5
parentc7facc54c4abed9e554ff80225311e6b7048d3c9 (diff)
downloadillumos-joyent-e65e5c2d2f32a99e8c5f740cabae9075dab03ce7.tar.gz
PSARC 2010/032 EC and SHA2 for KMF
6902640 pktool/KMF needs to support ECDSA keys and certificates 6787016 pktool can offer the ability to generate RSA keypairs
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/Makefile10
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/common.c146
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/common.h22
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/gencert.c251
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/gencsr.c273
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/genkeypair.c523
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/list.c14
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/pktool.c65
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/signcsr.c6
-rw-r--r--usr/src/lib/libkmf/ber_der/common/clasn1.c396
-rw-r--r--usr/src/lib/libkmf/ber_der/common/decode.c6
-rw-r--r--usr/src/lib/libkmf/ber_der/common/mapfile-vers6
-rw-r--r--usr/src/lib/libkmf/ber_der/inc/ber_der.h9
-rw-r--r--usr/src/lib/libkmf/include/algorithm.h47
-rw-r--r--usr/src/lib/libkmf/include/kmfapiP.h25
-rw-r--r--usr/src/lib/libkmf/include/kmftypes.h123
-rw-r--r--usr/src/lib/libkmf/libkmf/Makefile.com3
-rw-r--r--usr/src/lib/libkmf/libkmf/common/algoid.c16
-rw-r--r--usr/src/lib/libkmf/libkmf/common/algorithm.c152
-rw-r--r--usr/src/lib/libkmf/libkmf/common/certop.c235
-rw-r--r--usr/src/lib/libkmf/libkmf/common/csrcrlop.c111
-rw-r--r--usr/src/lib/libkmf/libkmf/common/kmfoids.c190
-rw-r--r--usr/src/lib/libkmf/libkmf/common/mapfile-vers76
-rw-r--r--usr/src/lib/libkmf/libkmf/common/pk11keys.c406
-rw-r--r--usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c50
-rw-r--r--usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c306
-rw-r--r--usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c763
27 files changed, 2671 insertions, 1559 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/Makefile b/usr/src/cmd/cmd-crypto/pktool/Makefile
index 0c375bd153..7e94f51d21 100644
--- a/usr/src/cmd/cmd-crypto/pktool/Makefile
+++ b/usr/src/cmd/cmd-crypto/pktool/Makefile
@@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -37,7 +37,8 @@ OBJS = pktool.o \
gencsr.o \
download.o \
genkey.o \
- signcsr.o
+ signcsr.o \
+ genkeypair.o
include ../../Makefile.cmd
@@ -47,10 +48,11 @@ POFILES = $(OBJS:%.o=%.po)
POFILE = $(PROG)_msg.po
MSGFILES=$(SRCS:%.c=%.i)
-CPPFLAGS += -I. -I$(KMFDIR)/include -I/usr/include/libxml2
+CPPFLAGS += -I. -I$(KMFDIR)/include -I/usr/include/libxml2 \
+ -I$(KMFDIR)/ber_der/inc
+
CFLAGS += $(CCVERBOSE) -DDEBUG
-#LDFLAGS += -L$(SRC)/lib/libkmf/libkmf/$(MACH)
LDLIBS += -lkmf -lpkcs11 -lcryptoutil
.KEEP_STATE:
diff --git a/usr/src/cmd/cmd-crypto/pktool/common.c b/usr/src/cmd/cmd-crypto/pktool/common.c
index 8c95c2e480..95992e5d82 100644
--- a/usr/src/cmd/cmd-crypto/pktool/common.c
+++ b/usr/src/cmd/cmd-crypto/pktool/common.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -67,6 +67,72 @@ char *optarg_av = NULL;
static void close_sess(CK_SESSION_HANDLE);
static void logout_token(CK_SESSION_HANDLE);
+struct oid_table_entry {
+ const KMF_OID *oid;
+ char *name;
+};
+
+struct oid_table_entry oid_table[] = {
+ { &KMFOID_ECC_secp112r1, "secp112r1"},
+ { &KMFOID_ECC_secp112r2, "secp112r2"},
+ { &KMFOID_ECC_secp128r1, "secp128r1"},
+ { &KMFOID_ECC_secp128r2, "secp128r2"},
+ { &KMFOID_ECC_secp160k1, "secp160k1"},
+ { &KMFOID_ECC_secp160r1, "secp160r1"},
+ { &KMFOID_ECC_secp160r2, "secp160r2"},
+ { &KMFOID_ECC_secp192k1, "secp192k1"},
+ { &KMFOID_ECC_secp192r1, "secp192r1"},
+ { &KMFOID_ECC_secp224k1, "secp224k1"},
+ { &KMFOID_ECC_secp224r1, "secp224r1"},
+ { &KMFOID_ECC_secp256k1, "secp256k1"},
+ { &KMFOID_ECC_secp256r1, "secp256r1"},
+ { &KMFOID_ECC_secp384r1, "secp384r1"},
+ { &KMFOID_ECC_secp521r1, "secp521r1"},
+ { &KMFOID_ECC_sect113r1, "sect113r1"},
+ { &KMFOID_ECC_sect113r2, "sect113r2"},
+ { &KMFOID_ECC_sect131r1, "sect131r1"},
+ { &KMFOID_ECC_sect131r2, "sect131r2"},
+ { &KMFOID_ECC_sect163k1, "sect163k1"},
+ { &KMFOID_ECC_sect163r1, "sect163r1"},
+ { &KMFOID_ECC_sect163r2, "sect163r2"},
+ { &KMFOID_ECC_sect193r1, "sect193r1"},
+ { &KMFOID_ECC_sect193r2, "sect193r2"},
+ { &KMFOID_ECC_sect233k1, "sect233k1"},
+ { &KMFOID_ECC_sect233r1, "sect233r1"},
+ { &KMFOID_ECC_sect239k1, "sect239k1"},
+ { &KMFOID_ECC_sect283k1, "sect283k1"},
+ { &KMFOID_ECC_sect283r1, "sect283r1"},
+ { &KMFOID_ECC_sect409k1, "sect409k1"},
+ { &KMFOID_ECC_sect409r1, "sect409r1"},
+ { &KMFOID_ECC_sect571k1, "sect571k1"},
+ { &KMFOID_ECC_sect571r1, "sect571r1"},
+ { &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
+ { &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
+ { &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
+ { &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
+ { &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
+ { &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
+ { &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
+ { &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
+ { &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
+ { &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
+ { &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
+ { &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
+ { &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
+ { &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
+ { &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
+ { &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
+ { &KMFOID_ECC_prime192v2, "prime192v2"},
+ { &KMFOID_ECC_prime192v3, "prime192v3"},
+ { &KMFOID_MD5, "md5"},
+ { &KMFOID_SHA1, "sha1"},
+ { &KMFOID_SHA256, "sha256"},
+ { &KMFOID_SHA384, "sha384"},
+ { &KMFOID_SHA512, "sha512"}
+};
+int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
+#define number_of_curves (number_of_oids - 5)
+
/*
* Perform PKCS#11 setup here. Currently only C_Initialize is required,
* along with setting/resetting state variables.
@@ -457,19 +523,64 @@ KS2Int(char *keystore_str)
return (0);
}
+/*
+ * compare_oids
+ * return 1 if equal
+ */
+boolean_t
+compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
+{
+ return ((oid1->Length == oid2->Length) &&
+ !memcmp(oid1->Data, oid2->Data, oid1->Length));
+}
int
-Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
+Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
+ KMF_ALGORITHM_INDEX *sigAlg)
{
if (algm == NULL) {
+ /* Default to SHA1+RSA */
*sigAlg = KMF_ALGID_SHA1WithRSA;
*ktype = KMF_RSA;
} else if (strcasecmp(algm, "DSA") == 0) {
- *sigAlg = KMF_ALGID_SHA1WithDSA;
+ if (hashoid == NULL ||
+ compare_oids(hashoid, &KMFOID_SHA1))
+ *sigAlg = KMF_ALGID_SHA1WithDSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA256))
+ *sigAlg = KMF_ALGID_SHA256WithDSA;
+ else
+ return (-1); /* unsupported hash/key combo */
*ktype = KMF_DSA;
} else if (strcasecmp(algm, "RSA") == 0) {
- *sigAlg = KMF_ALGID_SHA1WithRSA;
+ if (hashoid == NULL ||
+ compare_oids(hashoid, &KMFOID_SHA1))
+ *sigAlg = KMF_ALGID_SHA1WithRSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA256))
+ *sigAlg = KMF_ALGID_SHA256WithRSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA384))
+ *sigAlg = KMF_ALGID_SHA384WithRSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA512))
+ *sigAlg = KMF_ALGID_SHA512WithRSA;
+ else if (compare_oids(hashoid, &KMFOID_MD5))
+ *sigAlg = KMF_ALGID_MD5WithRSA;
+ else
+ return (-1); /* unsupported hash/key combo */
*ktype = KMF_RSA;
+ } else if (strcasecmp(algm, "EC") == 0) {
+ /* EC keys may be used with some SHA2 hashes */
+ if (hashoid == NULL ||
+ compare_oids(hashoid, &KMFOID_SHA1))
+ *sigAlg = KMF_ALGID_SHA1WithECDSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA256))
+ *sigAlg = KMF_ALGID_SHA256WithECDSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA384))
+ *sigAlg = KMF_ALGID_SHA384WithECDSA;
+ else if (compare_oids(hashoid, &KMFOID_SHA512))
+ *sigAlg = KMF_ALGID_SHA512WithECDSA;
+ else
+ return (-1); /* unsupported hash/key combo */
+
+ *ktype = KMF_ECDSA;
} else {
return (-1);
}
@@ -1218,3 +1329,30 @@ token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
return (KMF_OK);
}
+
+void
+show_ecc_curves()
+{
+ int i;
+
+ (void) printf(gettext("Supported ECC curve names:\n"));
+ for (i = 0; i < number_of_curves; i++) {
+ (void) printf("%s", oid_table[i].name);
+ if (i > 0 && ((i+1) % 5) == 0)
+ (void) printf("\n");
+ else if (i+1 < number_of_curves)
+ (void) printf(", ");
+ }
+ (void) printf("\n");
+}
+
+KMF_OID *
+ecc_name_to_oid(char *name)
+{
+ int i;
+ for (i = 0; i < number_of_oids; i++) {
+ if (strcasecmp(name, oid_table[i].name) == 0)
+ return ((KMF_OID *)oid_table[i].oid);
+ }
+ return (NULL);
+}
diff --git a/usr/src/cmd/cmd-crypto/pktool/common.h b/usr/src/cmd/cmd-crypto/pktool/common.h
index 5414d58b41..89e824b1a6 100644
--- a/usr/src/cmd/cmd-crypto/pktool/common.h
+++ b/usr/src/cmd/cmd-crypto/pktool/common.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _PKTOOL_COMMON_H
#define _PKTOOL_COMMON_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This file contains data and functions shared between all the
* modules that comprise this tool.
@@ -70,7 +68,7 @@ extern "C" {
PK_CERT_OBJ| PK_CRL_OBJ | PK_KEY_OBJ)
#define PK_DEFAULT_KEYTYPE "rsa"
-#define PK_DEFAULT_KEYLENGTH 1024
+#define PK_DEFAULT_KEYLENGTH 2048
#define PK_DEFAULT_DIRECTORY "."
#define PK_DEFAULT_SERIALNUM 1
#define PK_DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL
@@ -114,7 +112,7 @@ extern int optind_av;
int OT2Int(char *);
int PK2Int(char *);
KMF_KEYSTORE_TYPE KS2Int(char *);
-int Str2KeyType(char *, KMF_KEY_ALG *, KMF_ALGORITHM_INDEX *);
+int Str2KeyType(char *, KMF_OID *, KMF_KEY_ALG *, KMF_ALGORITHM_INDEX *);
int Str2SymKeyType(char *, KMF_KEY_ALG *);
int Str2Lifetime(char *, uint32_t *);
KMF_RETURN select_token(void *, char *, int);
@@ -128,6 +126,20 @@ KMF_RETURN verify_keyusage(char *arg, uint16_t *, int *);
KMF_RETURN verify_file(char *);
KMF_RETURN verify_ekunames(char *, EKU_LIST **);
KMF_RETURN token_auth_needed(KMF_HANDLE_T, char *, int *);
+KMF_OID *ecc_name_to_oid(char *);
+void show_ecc_curves();
+KMF_RETURN genkeypair_pkcs11(KMF_HANDLE_T, char *, char *, KMF_KEY_ALG,
+ int, KMF_CREDENTIAL *, KMF_OID *,
+ KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
+
+KMF_RETURN genkeypair_file(KMF_HANDLE_T,
+ KMF_KEY_ALG, int, KMF_ENCODE_FORMAT,
+ char *, KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
+
+KMF_RETURN genkeypair_nss(KMF_HANDLE_T,
+ char *, char *, char *, char *,
+ KMF_KEY_ALG, int, KMF_CREDENTIAL *,
+ KMF_OID *, KMF_KEY_HANDLE *, KMF_KEY_HANDLE *);
void free_eku_list(EKU_LIST *);
diff --git a/usr/src/cmd/cmd-crypto/pktool/gencert.c b/usr/src/cmd/cmd-crypto/pktool/gencert.c
index 3afd08a588..2b107b85be 100644
--- a/usr/src/cmd/cmd-crypto/pktool/gencert.c
+++ b/usr/src/cmd/cmd-crypto/pktool/gencert.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -52,7 +52,7 @@ gencert_pkcs11(KMF_HANDLE_T kmfhandle,
KMF_ALGORITHM_INDEX sigAlg,
int keylen, uint32_t ltime, KMF_BIGINT *serial,
uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
- EKU_LIST *ekulist)
+ EKU_LIST *ekulist, KMF_OID *curveoid)
{
KMF_RETURN kmfrv = KMF_OK;
KMF_KEY_HANDLE pubk, prik;
@@ -90,54 +90,17 @@ gencert_pkcs11(KMF_HANDLE_T kmfhandle,
/* Select a PKCS11 token */
kmfrv = select_token(kmfhandle, token, FALSE);
-
if (kmfrv != KMF_OK) {
return (kmfrv);
}
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYSTORE_TYPE_ATTR, &kstype,
- sizeof (kstype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYALG_ATTR, &keytype,
- sizeof (keytype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYLENGTH_ATTR, &keylength,
- sizeof (keylength));
- numattr++;
-
- if (certlabel != NULL) {
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYLABEL_ATTR, certlabel,
- strlen(certlabel));
- numattr++;
- }
-
- if (tokencred != NULL && tokencred->cred != NULL) {
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_CREDENTIAL_ATTR, tokencred,
- sizeof (KMF_CREDENTIAL));
- numattr++;
- }
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_PRIVKEY_HANDLE_ATTR, &prik,
- sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_PUBKEY_HANDLE_ATTR, &pubk,
- sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
- if (kmfrv != KMF_OK) {
+ /*
+ * Share the "genkeypair" routine for creating the keypair.
+ */
+ kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
+ keytype, keylength, tokencred, curveoid, &prik, &pubk);
+ if (kmfrv != KMF_OK)
return (kmfrv);
- }
SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
"keypair");
@@ -297,9 +260,6 @@ gencert_file(KMF_HANDLE_T kmfhandle,
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
KMF_ATTRIBUTE attrlist[10];
int numattr = 0;
- KMF_KEY_ALG keytype;
- uint32_t keylength;
- KMF_ENCODE_FORMAT format;
(void) memset(&signedCert, 0, sizeof (signedCert));
(void) memset(&certSubject, 0, sizeof (certSubject));
@@ -321,16 +281,6 @@ gencert_file(KMF_HANDLE_T kmfhandle,
return (PK_ERR_USAGE);
}
- fullkeypath = strdup(outkey);
- if (verify_file(fullkeypath)) {
- cryptoerror(LOG_STDERR,
- gettext("Cannot write the indicated output "
- "key file (%s).\n"), fullkeypath);
- free(fullkeypath);
- free(fullcertpath);
- return (PK_ERR_USAGE);
- }
-
/* If the subject name cannot be parsed, flag it now and exit */
if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
cryptoerror(LOG_STDERR,
@@ -346,51 +296,13 @@ gencert_file(KMF_HANDLE_T kmfhandle,
return (PK_ERR_USAGE);
}
- keylength = keylen; /* bits */
- keytype = keyAlg;
- format = fmt;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYSTORE_TYPE_ATTR, &kstype,
- sizeof (kstype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYALG_ATTR, &keytype,
- sizeof (keytype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYLENGTH_ATTR, &keylength,
- sizeof (keylength));
- numattr++;
-
- if (fullkeypath != NULL) {
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEY_FILENAME_ATTR, fullkeypath,
- strlen(fullkeypath));
- numattr++;
- }
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_ENCODE_FORMAT_ATTR, &format,
- sizeof (format));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_PRIVKEY_HANDLE_ATTR, &prik,
- sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_PUBKEY_HANDLE_ATTR, &pubk,
- sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
- if (kmfrv != KMF_OK) {
- goto cleanup;
- }
+ /*
+ * Share the "genkeypair" routine for creating the keypair.
+ */
+ kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
+ fmt, outkey, &prik, &pubk);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
"keypair");
@@ -496,7 +408,7 @@ gencert_nss(KMF_HANDLE_T kmfhandle,
int keylen, char *trust,
uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
int kucrit, KMF_CREDENTIAL *tokencred,
- EKU_LIST *ekulist)
+ EKU_LIST *ekulist, KMF_OID *curveoid)
{
KMF_RETURN kmfrv;
KMF_KEY_HANDLE pubk, prik;
@@ -507,8 +419,6 @@ gencert_nss(KMF_HANDLE_T kmfhandle,
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
KMF_ATTRIBUTE attrlist[16];
int numattr = 0;
- KMF_KEY_ALG keytype;
- uint32_t keylength;
if (token == NULL)
token = DEFAULT_NSS_TOKEN;
@@ -536,59 +446,11 @@ gencert_nss(KMF_HANDLE_T kmfhandle,
return (PK_ERR_USAGE);
}
- keylength = keylen; /* bits */
- keytype = keyAlg;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYSTORE_TYPE_ATTR, &kstype,
- sizeof (kstype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYALG_ATTR, &keytype,
- sizeof (keytype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYLENGTH_ATTR, &keylength,
- sizeof (keylength));
- numattr++;
-
- if (nickname != NULL) {
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_KEYLABEL_ATTR, nickname,
- strlen(nickname));
- numattr++;
- }
-
- if (tokencred != NULL && tokencred->cred != NULL) {
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_CREDENTIAL_ATTR, tokencred,
- sizeof (KMF_CREDENTIAL));
- numattr++;
- }
-
- if (token != NULL) {
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_TOKEN_LABEL_ATTR, token,
- strlen(token));
- numattr++;
- }
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_PRIVKEY_HANDLE_ATTR, &prik,
- sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr,
- KMF_PUBKEY_HANDLE_ATTR, &pubk,
- sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
- if (kmfrv != KMF_OK) {
+ kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
+ prefix, keyAlg, keylen, tokencred, curveoid,
+ &prik, &pubk);
+ if (kmfrv != KMF_OK)
return (kmfrv);
- }
SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
"keypair");
@@ -716,6 +578,7 @@ pk_gencert(int argc, char *argv[])
char *altname = NULL;
char *keyusagestr = NULL;
char *ekustr = NULL;
+ char *hashname = NULL;
KMF_GENERALNAMECHOICES alttype = 0;
KMF_BIGINT serial = { NULL, 0 };
uint32_t ltime;
@@ -729,14 +592,18 @@ pk_gencert(int argc, char *argv[])
uint16_t kubits = 0;
int altcrit = 0, kucrit = 0;
EKU_LIST *ekulist = NULL;
+ KMF_OID *curveoid = NULL; /* ECC */
+ KMF_OID *hashoid = NULL;
+ int y_flag = 0;
while ((opt = getopt_av(argc, argv,
"ik:(keystore)s:(subject)n:(nickname)A:(altname)"
"T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
"r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
- "K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
+ "K:(outkey)S:(serial)F:(format)u:(keyusage)C:(curve)"
+ "E(listcurves)h:(hash)")) != EOF) {
- if (opt != 'i' && EMPTYSTRING(optarg_av))
+ if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
return (PK_ERR_USAGE);
switch (opt) {
@@ -796,6 +663,7 @@ pk_gencert(int argc, char *argv[])
optarg_av);
return (PK_ERR_USAGE);
}
+ y_flag++;
break;
case 'r':
if (trust)
@@ -828,6 +696,38 @@ pk_gencert(int argc, char *argv[])
case 'e':
ekustr = optarg_av;
break;
+ case 'C':
+ curveoid = ecc_name_to_oid(optarg_av);
+ if (curveoid == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unrecognized ECC "
+ "curve.\n"));
+ return (PK_ERR_USAGE);
+ }
+ break;
+ case 'E':
+ /*
+ * This argument is only to be used
+ * by itself, no other options should
+ * be present.
+ */
+ if (argc != 2) {
+ cryptoerror(LOG_STDERR,
+ gettext("listcurves has no other "
+ "options.\n"));
+ return (PK_ERR_USAGE);
+ }
+ show_ecc_curves();
+ return (0);
+ case 'h':
+ hashname = optarg_av;
+ hashoid = ecc_name_to_oid(optarg_av);
+ if (hashoid == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unrecognized hash.\n"));
+ return (PK_ERR_USAGE);
+ }
+ break;
default:
return (PK_ERR_USAGE);
}
@@ -881,11 +781,25 @@ pk_gencert(int argc, char *argv[])
return (PK_ERR_USAGE);
}
- if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
- cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
- keytype);
+ if (Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg) != 0) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unsupported key/hash combination (%s/%s).\n"),
+ keytype, (hashname ? hashname : "none"));
+ return (PK_ERR_USAGE);
+ }
+ if (curveoid != NULL && keyAlg != KMF_ECDSA) {
+ cryptoerror(LOG_STDERR, gettext("EC curves are only "
+ "valid for EC keytypes.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (keyAlg == KMF_ECDSA && curveoid == NULL) {
+ cryptoerror(LOG_STDERR, gettext("A curve must be "
+ "specifed when using EC keys.\n"));
return (PK_ERR_USAGE);
}
+ /* Adjust default keylength for NSS and DSA */
+ if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
+ keylen = 1024;
/*
* Check the subject name.
@@ -976,6 +890,12 @@ pk_gencert(int argc, char *argv[])
goto end;
}
}
+ if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
+ (void) fprintf(stderr, gettext("ECC certificates are"
+ "only supported with the pkcs11 and nss keystores\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
if (tokenname == NULL || !strlen(tokenname)) {
@@ -997,13 +917,14 @@ pk_gencert(int argc, char *argv[])
tokenname, subname, altname, alttype, altcrit,
certlabel, dir, prefix, keyAlg, sigAlg, keylen,
trust, ltime, &serial, kubits, kucrit, &tokencred,
- ekulist);
+ ekulist, curveoid);
} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
rv = gencert_pkcs11(kmfhandle,
tokenname, subname, altname, alttype, altcrit,
certlabel, keyAlg, sigAlg, keylen, ltime,
- &serial, kubits, kucrit, &tokencred, ekulist);
+ &serial, kubits, kucrit, &tokencred, ekulist,
+ curveoid);
} else if (kstype == KMF_KEYSTORE_OPENSSL) {
rv = gencert_file(kmfhandle,
diff --git a/usr/src/cmd/cmd-crypto/pktool/gencsr.c b/usr/src/cmd/cmd-crypto/pktool/gencsr.c
index f65f4cf949..be85b222b1 100644
--- a/usr/src/cmd/cmd-crypto/pktool/gencsr.c
+++ b/usr/src/cmd/cmd-crypto/pktool/gencsr.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*
*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,82 +51,37 @@ gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
char *certlabel, KMF_KEY_ALG keyAlg,
int keylen, uint16_t kubits, int kucrit,
KMF_ENCODE_FORMAT fmt, char *csrfile,
- KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
+ KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
+ KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
{
KMF_RETURN kmfrv = KMF_OK;
KMF_KEY_HANDLE pubk, prik;
KMF_X509_NAME csrSubject;
KMF_CSR_DATA csr;
- KMF_ALGORITHM_INDEX sigAlg;
KMF_DATA signedCsr = {NULL, 0};
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
int numattr = 0;
KMF_ATTRIBUTE attrlist[16];
- boolean_t storekey = TRUE;
(void) memset(&csr, 0, sizeof (csr));
(void) memset(&csrSubject, 0, sizeof (csrSubject));
- if (keyAlg == KMF_DSA)
- sigAlg = KMF_ALGID_SHA1WithDSA;
- else
- sigAlg = KMF_ALGID_SHA1WithRSA;
-
-
/* If the subject name cannot be parsed, flag it now and exit */
- if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
+ if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK)
return (kmfrv);
- }
/* Select a PKCS11 token */
kmfrv = select_token(kmfhandle, token, FALSE);
- if (kmfrv != KMF_OK) {
+ if (kmfrv != KMF_OK)
return (kmfrv);
- }
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
- &kstype, sizeof (kstype));
- numattr++;
-
- if (certlabel != NULL && strlen(certlabel)) {
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
- certlabel, strlen(certlabel));
- numattr++;
- }
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
- &keylen, sizeof (keylen));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
- &keyAlg, sizeof (keyAlg));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
- tokencred, sizeof (KMF_CREDENTIAL));
- numattr++;
-
- if (token && strlen(token)) {
- kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
- token, strlen(token));
- numattr++;
- }
- kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
- &pubk, sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
- &prik, sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
- &storekey, sizeof (storekey));
- numattr++;
-
- kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
- if (kmfrv != KMF_OK) {
+ /*
+ * Share the "genkeypair" routine for creating the keypair.
+ */
+ kmfrv = genkeypair_pkcs11(kmfhandle, token, certlabel,
+ keyAlg, keylen, tokencred, curveoid, &prik, &pubk);
+ if (kmfrv != KMF_OK)
return (kmfrv);
- }
SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
@@ -217,21 +172,17 @@ gencsr_file(KMF_HANDLE_T kmfhandle,
int keylen, KMF_ENCODE_FORMAT fmt,
char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
int altcrit, uint16_t kubits, int kucrit,
- char *outcsr, char *outkey, EKU_LIST *ekulist)
+ char *outcsr, char *outkey, EKU_LIST *ekulist,
+ KMF_ALGORITHM_INDEX sigAlg)
{
KMF_RETURN kmfrv;
KMF_KEY_HANDLE pubk, prik;
KMF_X509_NAME csrSubject;
KMF_CSR_DATA csr;
- KMF_ALGORITHM_INDEX sigAlg;
KMF_DATA signedCsr = {NULL, 0};
char *fullcsrpath = NULL;
char *fullkeypath = NULL;
- int numattr = 0;
- KMF_ATTRIBUTE attrlist[16];
- KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
- boolean_t storekey = TRUE;
(void) memset(&csr, 0, sizeof (csr));
(void) memset(&csrSubject, 0, sizeof (csrSubject));
@@ -251,63 +202,18 @@ gencsr_file(KMF_HANDLE_T kmfhandle,
return (PK_ERR_USAGE);
}
- fullkeypath = strdup(outkey);
- if (verify_file(fullcsrpath)) {
- cryptoerror(LOG_STDERR,
- gettext("Cannot write the indicated output "
- "key file (%s).\n"), fullkeypath);
- free(fullcsrpath);
- return (PK_ERR_USAGE);
- }
-
- if (keyAlg == KMF_DSA)
- sigAlg = KMF_ALGID_SHA1WithDSA;
- else
- sigAlg = KMF_ALGID_SHA1WithRSA;
-
/* If the subject name cannot be parsed, flag it now and exit */
if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
return (kmfrv);
}
+ /*
+ * Share the "genkeypair" routine for creating the keypair.
+ */
+ kmfrv = genkeypair_file(kmfhandle, keyAlg, keylen,
+ fmt, outkey, &prik, &pubk);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
- &kstype, sizeof (kstype));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
- fullkeypath, strlen(fullkeypath));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
- &keylen, sizeof (keylen));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
- &keyAlg, sizeof (keyAlg));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
- &fmt, sizeof (fmt));
- numattr++;
-
- (void) memset(&prik, 0, sizeof (prik));
- kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
- &prik, sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- (void) memset(&pubk, 0, sizeof (pubk));
- kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
- &pubk, sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
- &storekey, sizeof (storekey));
- numattr++;
-
- kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
- if (kmfrv != KMF_OK) {
- goto cleanup;
- }
SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
"SetCSRPubKey");
@@ -361,28 +267,22 @@ gencsr_nss(KMF_HANDLE_T kmfhandle,
KMF_KEY_ALG keyAlg, int keylen,
uint16_t kubits, int kucrit,
KMF_ENCODE_FORMAT fmt, char *csrfile,
- KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
+ KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist,
+ KMF_ALGORITHM_INDEX sigAlg, KMF_OID *curveoid)
{
KMF_RETURN kmfrv;
KMF_KEY_HANDLE pubk, prik;
KMF_X509_NAME csrSubject;
KMF_CSR_DATA csr;
- KMF_ALGORITHM_INDEX sigAlg;
KMF_DATA signedCsr = {NULL, 0};
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
int numattr = 0;
KMF_ATTRIBUTE attrlist[16];
- boolean_t storekey = TRUE;
if (token == NULL)
token = DEFAULT_NSS_TOKEN;
- if (keyAlg == KMF_DSA)
- sigAlg = KMF_ALGID_SHA1WithDSA;
- else
- sigAlg = KMF_ALGID_SHA1WithRSA;
-
kmfrv = configure_nss(kmfhandle, dir, prefix);
if (kmfrv != KMF_OK)
return (kmfrv);
@@ -397,50 +297,11 @@ gencsr_nss(KMF_HANDLE_T kmfhandle,
return (kmfrv);
}
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
- &kstype, sizeof (kstype));
- numattr++;
-
- if (nickname != NULL && strlen(nickname)) {
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
- nickname, strlen(nickname));
- numattr++;
- }
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
- &keylen, sizeof (keylen));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
- &keyAlg, sizeof (keyAlg));
- numattr++;
-
- if (tokencred != NULL && tokencred->credlen > 0) {
- kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
- tokencred, sizeof (KMF_CREDENTIAL));
- numattr++;
- }
-
- if (token && strlen(token)) {
- kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
- token, strlen(token));
- numattr++;
- }
- kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
- &pubk, sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
- &prik, sizeof (KMF_KEY_HANDLE));
- numattr++;
-
- kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
- &storekey, sizeof (storekey));
- numattr++;
-
- kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
- if (kmfrv != KMF_OK) {
- goto cleanup;
- }
+ kmfrv = genkeypair_nss(kmfhandle, token, nickname, dir,
+ prefix, keyAlg, keylen, tokencred, curveoid,
+ &prik, &pubk);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
"kmf_set_csr_pubkey");
@@ -524,6 +385,7 @@ pk_gencsr(int argc, char *argv[])
char *altname = NULL;
char *kustr = NULL;
char *ekustr = NULL;
+ char *hashname = NULL;
uint16_t kubits = 0;
char *keytype = PK_DEFAULT_KEYTYPE;
KMF_HANDLE_T kmfhandle = NULL;
@@ -536,15 +398,15 @@ pk_gencsr(int argc, char *argv[])
KMF_GENERALNAMECHOICES alttype = 0;
int altcrit = 0, kucrit = 0;
EKU_LIST *ekulist = NULL;
+ KMF_OID *curveoid = NULL; /* ECC */
+ KMF_OID *hashoid = NULL;
+ int y_flag = 0;
while ((opt = getopt_av(argc, argv,
"ik:(keystore)s:(subject)n:(nickname)A:(altname)"
"u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
- "y:(keylen)l:(label)c:(outcsr)e:(eku)"
- "K:(outkey)F:(format)")) != EOF) {
-
- if (opt != 'i' && EMPTYSTRING(optarg_av))
- return (PK_ERR_USAGE);
+ "y:(keylen)l:(label)c:(outcsr)e:(eku)C:(curve)"
+ "K:(outkey)F:(format)E(listcurves)h:(hash)")) != EOF) {
switch (opt) {
case 'A':
@@ -612,6 +474,7 @@ pk_gencsr(int argc, char *argv[])
"key length (%s)\n"), optarg_av);
return (PK_ERR_USAGE);
}
+ y_flag++;
break;
case 'c':
if (outcsr)
@@ -631,6 +494,38 @@ pk_gencsr(int argc, char *argv[])
case 'e':
ekustr = optarg_av;
break;
+ case 'C':
+ curveoid = ecc_name_to_oid(optarg_av);
+ if (curveoid == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unrecognized ECC "
+ "curve.\n"));
+ return (PK_ERR_USAGE);
+ }
+ break;
+ case 'E':
+ /*
+ * This argument is only to be used
+ * by itself, no other options should
+ * be present.
+ */
+ if (argc != 2) {
+ cryptoerror(LOG_STDERR,
+ gettext("listcurves has no other "
+ "options.\n"));
+ return (PK_ERR_USAGE);
+ }
+ show_ecc_curves();
+ return (0);
+ case 'h':
+ hashname = optarg_av;
+ hashoid = ecc_name_to_oid(optarg_av);
+ if (hashoid == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unrecognized hash.\n"));
+ return (PK_ERR_USAGE);
+ }
+ break;
default:
cryptoerror(LOG_STDERR, gettext(
"unrecognized gencsr option '%s'\n"),
@@ -761,13 +656,33 @@ pk_gencsr(int argc, char *argv[])
goto end;
}
}
-
- if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
- cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
- keytype);
+ if ((rv = Str2KeyType(keytype, hashoid, &keyAlg, &sigAlg)) != 0) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unsupported key/hash combination (%s/%s).\n"),
+ keytype, (hashname ? hashname : "none"));
+ goto end;
+ }
+ if (curveoid != NULL && keyAlg != KMF_ECDSA) {
+ cryptoerror(LOG_STDERR, gettext("EC curves are only "
+ "valid for EC keytypes.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (keyAlg == KMF_ECDSA && curveoid == NULL) {
+ cryptoerror(LOG_STDERR, gettext("A curve must be "
+ "specifed when using EC keys.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
+ (void) fprintf(stderr, gettext("ECC certificates are"
+ "only supported with the pkcs11 and nss keystores\n"));
+ rv = PK_ERR_USAGE;
goto end;
}
+ /* Adjust default keylength for NSS and DSA */
+ if (keyAlg == KMF_DSA && !y_flag && kstype == KMF_KEYSTORE_NSS)
+ keylen = 1024;
+
if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
if (tokenname == NULL || !strlen(tokenname)) {
if (kstype == KMF_KEYSTORE_NSS) {
@@ -794,19 +709,21 @@ pk_gencsr(int argc, char *argv[])
tokenname, subname, altname, alttype, altcrit,
certlabel, dir, prefix,
keyAlg, keylen, kubits, kucrit,
- fmt, outcsr, &tokencred, ekulist);
+ fmt, outcsr, &tokencred, ekulist,
+ sigAlg, curveoid);
} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
rv = gencsr_pkcs11(kmfhandle,
tokenname, subname, altname, alttype, altcrit,
certlabel, keyAlg, keylen,
- kubits, kucrit, fmt, outcsr, &tokencred, ekulist);
+ kubits, kucrit, fmt, outcsr, &tokencred,
+ ekulist, sigAlg, curveoid);
} else if (kstype == KMF_KEYSTORE_OPENSSL) {
rv = gencsr_file(kmfhandle,
keyAlg, keylen, fmt, subname, altname,
alttype, altcrit, kubits, kucrit,
- outcsr, outkey, ekulist);
+ outcsr, outkey, ekulist, sigAlg);
}
end:
diff --git a/usr/src/cmd/cmd-crypto/pktool/genkeypair.c b/usr/src/cmd/cmd-crypto/pktool/genkeypair.c
new file mode 100644
index 0000000000..27c0af0cd2
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/pktool/genkeypair.c
@@ -0,0 +1,523 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <libgen.h>
+#include <errno.h>
+#include <cryptoutil.h>
+#include <security/cryptoki.h>
+#include "common.h"
+
+#include <kmfapi.h>
+
+#define SET_VALUE(f, s) \
+ kmfrv = f; \
+ if (kmfrv != KMF_OK) { \
+ cryptoerror(LOG_STDERR, \
+ gettext("Failed to set %s: 0x%02x\n"), \
+ s, kmfrv); \
+ goto cleanup; \
+ }
+
+KMF_RETURN
+genkeypair_pkcs11(KMF_HANDLE_T kmfhandle,
+ char *token, char *keylabel, KMF_KEY_ALG keyAlg,
+ int keylen, KMF_CREDENTIAL *tokencred, KMF_OID *curveoid,
+ KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey)
+{
+ KMF_RETURN kmfrv = KMF_OK;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
+ KMF_ATTRIBUTE attrlist[16];
+ int numattr = 0;
+ KMF_KEY_ALG keytype;
+ uint32_t keylength;
+
+ keylength = keylen; /* bits */
+ keytype = keyAlg;
+
+ /* Select a PKCS11 token */
+ kmfrv = select_token(kmfhandle, token, FALSE);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYSTORE_TYPE_ATTR, &kstype,
+ sizeof (kstype));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYALG_ATTR, &keytype,
+ sizeof (keytype));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYLENGTH_ATTR, &keylength,
+ sizeof (keylength));
+ numattr++;
+
+ if (keylabel != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYLABEL_ATTR, keylabel,
+ strlen(keylabel));
+ numattr++;
+ }
+
+ if (tokencred != NULL && tokencred->cred != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_CREDENTIAL_ATTR, tokencred,
+ sizeof (KMF_CREDENTIAL));
+ numattr++;
+ }
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_PRIVKEY_HANDLE_ATTR, &prik,
+ sizeof (KMF_KEY_HANDLE));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_PUBKEY_HANDLE_ATTR, &pubk,
+ sizeof (KMF_KEY_HANDLE));
+ numattr++;
+
+ if (keytype == KMF_ECDSA && curveoid != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_ECC_CURVE_OID_ATTR, curveoid,
+ sizeof (KMF_OID));
+ numattr++;
+ }
+
+ kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+cleanup:
+ if (kmfrv == KMF_OK) {
+ if (outPriKey != NULL)
+ *outPriKey = prik;
+ if (outPubKey != NULL)
+ *outPubKey = pubk;
+ }
+
+ return (kmfrv);
+}
+
+KMF_RETURN
+genkeypair_file(KMF_HANDLE_T kmfhandle,
+ KMF_KEY_ALG keyAlg, int keylen, KMF_ENCODE_FORMAT fmt,
+ char *outkey,
+ KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey)
+{
+ KMF_RETURN kmfrv;
+ KMF_KEY_HANDLE pubk, prik;
+ char *fullkeypath = NULL;
+ KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
+ KMF_ATTRIBUTE attrlist[10];
+ int numattr = 0;
+ KMF_KEY_ALG keytype;
+ uint32_t keylength;
+ KMF_ENCODE_FORMAT format;
+
+ if (EMPTYSTRING(outkey)) {
+ cryptoerror(LOG_STDERR,
+ gettext("No output file was specified for "
+ "the key\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ fullkeypath = strdup(outkey);
+ if (verify_file(fullkeypath)) {
+ cryptoerror(LOG_STDERR,
+ gettext("Cannot write the indicated output "
+ "key file (%s).\n"), fullkeypath);
+ free(fullkeypath);
+ return (PK_ERR_USAGE);
+ }
+
+ keylength = keylen; /* bits */
+ keytype = keyAlg;
+ format = fmt;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYSTORE_TYPE_ATTR, &kstype,
+ sizeof (kstype));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYALG_ATTR, &keytype,
+ sizeof (keytype));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYLENGTH_ATTR, &keylength,
+ sizeof (keylength));
+ numattr++;
+
+ if (fullkeypath != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEY_FILENAME_ATTR, fullkeypath,
+ strlen(fullkeypath));
+ numattr++;
+ }
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_ENCODE_FORMAT_ATTR, &format,
+ sizeof (format));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_PRIVKEY_HANDLE_ATTR, &prik,
+ sizeof (KMF_KEY_HANDLE));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_PUBKEY_HANDLE_ATTR, &pubk,
+ sizeof (KMF_KEY_HANDLE));
+ numattr++;
+
+ kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
+ if (kmfrv != KMF_OK) {
+ goto cleanup;
+ }
+
+cleanup:
+ if (fullkeypath != NULL)
+ free(fullkeypath);
+
+ if (kmfrv == KMF_OK) {
+ if (outPriKey != NULL)
+ *outPriKey = prik;
+ if (outPubKey != NULL)
+ *outPubKey = pubk;
+ }
+
+ return (kmfrv);
+}
+
+KMF_RETURN
+genkeypair_nss(KMF_HANDLE_T kmfhandle,
+ char *token,
+ char *nickname, char *dir, char *prefix,
+ KMF_KEY_ALG keyAlg,
+ int keylen, KMF_CREDENTIAL *tokencred,
+ KMF_OID *curveoid,
+ KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey)
+{
+ KMF_RETURN kmfrv;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
+ KMF_ATTRIBUTE attrlist[16];
+ int numattr = 0;
+ KMF_KEY_ALG keytype;
+ uint32_t keylength;
+
+ if (token == NULL)
+ token = DEFAULT_NSS_TOKEN;
+
+ kmfrv = configure_nss(kmfhandle, dir, prefix);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
+
+ keylength = keylen; /* bits */
+ keytype = keyAlg;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYSTORE_TYPE_ATTR, &kstype,
+ sizeof (kstype));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYALG_ATTR, &keytype,
+ sizeof (keytype));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYLENGTH_ATTR, &keylength,
+ sizeof (keylength));
+ numattr++;
+
+ if (nickname != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_KEYLABEL_ATTR, nickname,
+ strlen(nickname));
+ numattr++;
+ }
+
+ if (tokencred != NULL && tokencred->cred != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_CREDENTIAL_ATTR, tokencred,
+ sizeof (KMF_CREDENTIAL));
+ numattr++;
+ }
+
+ if (token != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_TOKEN_LABEL_ATTR, token,
+ strlen(token));
+ numattr++;
+ }
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_PRIVKEY_HANDLE_ATTR, &prik,
+ sizeof (KMF_KEY_HANDLE));
+ numattr++;
+
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_PUBKEY_HANDLE_ATTR, &pubk,
+ sizeof (KMF_KEY_HANDLE));
+ numattr++;
+
+ if (keytype == KMF_ECDSA && curveoid != NULL) {
+ kmf_set_attr_at_index(attrlist, numattr,
+ KMF_ECC_CURVE_OID_ATTR, curveoid,
+ sizeof (KMF_OID));
+ numattr++;
+ }
+
+ kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+cleanup:
+ if (kmfrv == KMF_OK) {
+ if (outPriKey != NULL)
+ *outPriKey = prik;
+ if (outPubKey != NULL)
+ *outPubKey = pubk;
+ }
+ return (kmfrv);
+}
+
+int
+pk_genkeypair(int argc, char *argv[])
+{
+ int rv;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ char *tokenname = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *keytype = PK_DEFAULT_KEYTYPE;
+ int keylen = PK_DEFAULT_KEYLENGTH;
+ char *label = NULL;
+ char *outkey = NULL;
+ char *format = NULL;
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
+ KMF_KEY_ALG keyAlg = KMF_RSA;
+ KMF_ALGORITHM_INDEX sigAlg;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
+ KMF_OID *curveoid = NULL; /* ECC */
+ int y_flag = 0;
+
+ while ((opt = getopt_av(argc, argv,
+ "k:(keystore)s:(subject)n:(nickname)"
+ "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
+ "l:(label)K:(outkey)F:(format)C:(curve)"
+ "E(listcurves)")) != EOF) {
+
+ if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
+
+ switch (opt) {
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 'l':
+ case 'n':
+ if (label)
+ return (PK_ERR_USAGE);
+ label = optarg_av;
+ break;
+ case 'T':
+ if (tokenname)
+ return (PK_ERR_USAGE);
+ tokenname = optarg_av;
+ break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 't':
+ keytype = optarg_av;
+ break;
+ case 'y':
+ if (sscanf(optarg_av, "%d",
+ &keylen) != 1) {
+ cryptoerror(LOG_STDERR,
+ gettext("key length must be"
+ "a numeric value (%s)\n"),
+ optarg_av);
+ return (PK_ERR_USAGE);
+ }
+ y_flag++;
+ break;
+ case 'K':
+ if (outkey)
+ return (PK_ERR_USAGE);
+ outkey = optarg_av;
+ break;
+ case 'F':
+ if (format)
+ return (PK_ERR_USAGE);
+ format = optarg_av;
+ break;
+ case 'C':
+ curveoid = ecc_name_to_oid(optarg_av);
+ if (curveoid == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext(
+ "Unrecognized ECC curve.\n"));
+ return (PK_ERR_USAGE);
+ }
+ break;
+ case 'E':
+ show_ecc_curves();
+ return (0);
+ default:
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc) {
+ return (PK_ERR_USAGE);
+ }
+
+ if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ /* Assume keystore = PKCS#11 if not specified. */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
+
+ DIR_OPTION_CHECK(kstype, dir);
+
+ if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
+ cryptoerror(LOG_STDERR,
+ gettext("Error parsing format string (%s).\n"),
+ format);
+ return (PK_ERR_USAGE);
+ }
+
+ if (Str2KeyType(keytype, NULL, &keyAlg, &sigAlg) != 0) {
+ cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
+ keytype);
+ return (PK_ERR_USAGE);
+ }
+ if (curveoid != NULL && keyAlg != KMF_ECDSA) {
+ cryptoerror(LOG_STDERR, gettext("EC curves are only "
+ "valid for EC keytypes.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (keyAlg == KMF_ECDSA && curveoid == NULL) {
+ cryptoerror(LOG_STDERR, gettext("A curve must be "
+ "specifed when using EC keys.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) {
+ (void) fprintf(stderr, gettext("ECC certificates are"
+ "only supported with the pkcs11 and nss keystores\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
+ /* Adjust default keylength for NSS and DSA */
+ if (keyAlg == KMF_DSA && kstype == KMF_KEYSTORE_NSS) {
+ /* NSS only allows for 512-1024 bit DSA keys */
+ if (!y_flag)
+ /* If nothing was given, default to 1024 */
+ keylen = 1024;
+ else if (keylen > 1024 || keylen < 512) {
+ (void) fprintf(stderr, gettext("NSS keystore only "
+ "supports DSA keylengths of 512 - 1024 bits\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
+ }
+
+ if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
+ if (label == NULL) {
+ (void) fprintf(stderr,
+ gettext("No key label specified\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
+ if (tokenname == NULL || !strlen(tokenname)) {
+ if (kstype == KMF_KEYSTORE_NSS) {
+ tokenname = "internal";
+ } else {
+ tokenname = PK_DEFAULT_PK11TOKEN;
+ }
+ }
+
+ (void) get_token_password(kstype, tokenname, &tokencred);
+ }
+
+ if (kstype == KMF_KEYSTORE_NSS) {
+ if (dir == NULL)
+ dir = PK_DEFAULT_DIRECTORY;
+
+ rv = genkeypair_nss(kmfhandle,
+ tokenname, label, dir, prefix, keyAlg, keylen,
+ &tokencred, curveoid, NULL, NULL);
+
+ } else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ rv = genkeypair_pkcs11(kmfhandle,
+ tokenname, label, keyAlg, keylen,
+ &tokencred, curveoid, NULL, NULL);
+
+ } else if (kstype == KMF_KEYSTORE_OPENSSL) {
+ rv = genkeypair_file(kmfhandle, keyAlg, keylen,
+ fmt, outkey, NULL, NULL);
+ }
+
+ if (rv != KMF_OK)
+ display_error(kmfhandle, rv,
+ gettext("Error creating and keypair"));
+end:
+ if (tokencred.cred != NULL)
+ free(tokencred.cred);
+
+ (void) kmf_finalize(kmfhandle);
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/pktool/list.c b/usr/src/cmd/cmd-crypto/pktool/list.c
index ad20acb868..840b67df32 100644
--- a/usr/src/cmd/cmd-crypto/pktool/list.c
+++ b/usr/src/cmd/cmd-crypto/pktool/list.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This file implements the token object list operation for this tool.
* It loads the PKCS#11 modules, finds the object to list, lists it,
@@ -126,12 +124,16 @@ describeKey(KMF_KEY_HANDLE *key)
return (gettext("RSA public key"));
if (key->keyalg == KMF_DSA)
return (gettext("DSA public key"));
+ if (key->keyalg == KMF_ECDSA)
+ return (gettext("ECDSA public key"));
}
if (key->keyclass == KMF_ASYM_PRI) {
if (key->keyalg == KMF_RSA)
- return ("RSA private key");
+ return (gettext("RSA private key"));
if (key->keyalg == KMF_DSA)
- return ("DSA private key");
+ return (gettext("DSA private key"));
+ if (key->keyalg == KMF_ECDSA)
+ return (gettext("ECDSA private key"));
}
if (key->keyclass == KMF_SYMMETRIC) {
switch (key->keyalg) {
@@ -320,7 +322,7 @@ list_pk11_objects(KMF_HANDLE_T kmfhandle, char *token, int oclass,
KMF_CREDENTIAL cred = {NULL, 0};
/*
- * Symmetric keys and RSA/DSA private keys are always
+ * Symmetric keys and RSA/DSA/ECDSA private keys are always
* created with the "CKA_PRIVATE" field == TRUE, so
* make sure we search for them with it also set.
*/
diff --git a/usr/src/cmd/cmd-crypto/pktool/pktool.c b/usr/src/cmd/cmd-crypto/pktool/pktool.c
index 15a906b2a7..c6ddb6a2c4 100644
--- a/usr/src/cmd/cmd-crypto/pktool/pktool.c
+++ b/usr/src/cmd/cmd-crypto/pktool/pktool.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -67,6 +67,7 @@ extern int pk_download(int argc, char *argv[]);
extern int pk_genkey(int argc, char *argv[]);
extern int pk_signcsr(int argc, char *argv[]);
extern int pk_inittoken(int argc, char *argv[]);
+extern int pk_genkeypair(int argc, char *argv[]);
/* Forward declarations for "built-in" verb actions. */
static int pk_help(int argc, char *argv[]);
@@ -296,16 +297,20 @@ static int pk_help(int argc, char *argv[]);
#define GENCERT_VERB "gencert"
#define GENCERT_SUMM gettext("creates a self-signed X.509v3 certificate")
#define GENCERT_SYN \
+ "gencert listcurves\n\t" \
+\
"gencert keystore=nss\n\t\t" \
"label=cert-nickname\n\t\t" \
- "serial=serial number hex string]\n\t\t" \
+ "serial=serial number hex string\n\t\t" \
"[ -i ] | [subject=subject-DN]\n\t\t" \
"[ altname=[critical:]SubjectAltName ]\n\t\t" \
"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
"[ token=token[:manuf[:serial]]]\n\t\t" \
"[ dir=directory-path ]\n\t\t" \
"[ prefix=DBprefix ]\n\t\t" \
- "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keytype=rsa | ec [curve=ECC Curve Name] " \
+ "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
+ "[ keytype=dsa [hash=sha1]]\n\t\t" \
"[ keylen=key-size ]\n\t\t" \
"[ trust=trust-value ]\n\t\t" \
"[ eku=[critical:]EKU name,...]\n\t\t" \
@@ -318,7 +323,9 @@ static int pk_help(int argc, char *argv[]);
"[ altname=[critical:]SubjectAltName ]\n\t\t" \
"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
"[ token=token[:manuf[:serial]]]\n\t\t" \
- "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keytype=rsa | ec [curve=ECC Curve Name] " \
+ "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
+ "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
"[ keylen=key-size ]\n\t\t" \
"[ eku=[critical:]EKU name,...]\n\t\t" \
"[ lifetime=number-hour|number-day|number-year ]\n\t" \
@@ -331,8 +338,8 @@ static int pk_help(int argc, char *argv[]);
"[ altname=[critical:]SubjectAltName ]\n\t\t" \
"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
"[ format=der|pem ]\n\t\t" \
- "[ prefix=DBprefix ]\n\t\t" \
- "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keytype=rsa [hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
+ "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
"[ keylen=key-size ]\n\t\t" \
"[ eku=[critical:]EKU name,...]\n\t\t" \
"[ lifetime=number-hour|number-day|number-year ]\n\t"
@@ -343,6 +350,8 @@ static int pk_help(int argc, char *argv[]);
"request file")
#define GENCSR_SYN \
+ "gencsr listcurves\n\t" \
+\
"gencsr keystore=nss \n\t\t" \
"nickname=cert-nickname\n\t\t" \
"outcsr=csr-fn\n\t\t" \
@@ -352,7 +361,9 @@ static int pk_help(int argc, char *argv[]);
"[ token=token[:manuf[:serial]]]\n\t\t" \
"[ dir=directory-path ]\n\t\t" \
"[ prefix=DBprefix ]\n\t\t" \
- "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keytype=rsa | ec [curve=ECC Curve Name] " \
+ "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
+ "[ keytype=dsa [hash=sha1]]\n\t\t" \
"[ keylen=key-size ]\n\t\t" \
"[ eku=[critical:]EKU name,...]\n\t\t" \
"[ format=pem|der ]\n\t" \
@@ -364,7 +375,9 @@ static int pk_help(int argc, char *argv[]);
"[ altname=[critical:]SubjectAltName ]\n\t\t" \
"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
"[ token=token[:manuf[:serial]]]\n\t\t" \
- "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keytype=rsa | ec [curve=ECC Curve Name] " \
+ "[hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
+ "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
"[ keylen=key-size ]\n\t\t" \
"[ eku=[critical:]EKU name,...]\n\t\t" \
"[ format=pem|der ]]\n\t" \
@@ -375,7 +388,8 @@ static int pk_help(int argc, char *argv[]);
"[ -i ] | [subject=subject-DN]\n\t\t" \
"[ altname=[critical:]SubjectAltName ]\n\t\t" \
"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
- "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keytype=rsa [hash=md5 | sha1 | sha256 | sha384 | sha512]]\n\t\t" \
+ "[ keytype=dsa [hash=sha1 | sha256 ]]\n\t\t" \
"[ keylen=key-size ]\n\t\t" \
"[ eku=[critical:]EKU name,...]\n\t\t" \
"[ format=pem|der ]\n\t"
@@ -476,7 +490,33 @@ static int pk_help(int argc, char *argv[]);
"[ currlabel=token[:manuf[:serial]]]\n\t\t" \
"[ newlabel=new token label ]\n\t"
-#define HELP_IDX 12
+#define GENKEYPAIR_IDX 12
+#define GENKEYPAIR_VERB "genkeypair"
+#define GENKEYPAIR_SUMM gettext("creates an asymmetric keypair")
+#define GENKEYPAIR_SYN \
+ "genkeypair listcurves\n\t" \
+\
+ "genkeypair keystore=nss\n\t\t" \
+ "label=key-nickname\n\t\t" \
+ "[ token=token[:manuf[:serial]]]\n\t\t" \
+ "[ dir=directory-path ]\n\t\t" \
+ "[ prefix=DBprefix ]\n\t\t" \
+ "[ keytype=rsa | dsa | ec [curve=ECC Curve Name]]\n\t\t" \
+ "[ keylen=key-size ]\n\t" \
+ \
+ "genkeypair [ keystore=pkcs11 ]\n\t\t" \
+ "label=key-label\n\t\t" \
+ "[ token=token[:manuf[:serial]]]\n\t\t" \
+ "[ keytype=rsa | dsa | ec [curve=ECC Curve Name]]\n\t\t" \
+ "[ keylen=key-size ]\n\t" \
+ \
+ "genkeypair keystore=file\n\t\t" \
+ "outkey=key_filename\n\t\t" \
+ "[ format=der|pem ]\n\t\t" \
+ "[ keytype=rsa|dsa ]\n\t\t" \
+ "[ keylen=key-size ]\n\t"
+
+#define HELP_IDX 13
#define HELP_VERB "help"
#define HELP_SUMM gettext("displays help message")
#define HELP_SYN "help\t(help and usage)"
@@ -495,6 +535,7 @@ static verbcmd cmds[] = {
{ NULL, pk_genkey, 0, NULL, NULL},
{ NULL, pk_signcsr, 0, NULL, NULL},
{ NULL, pk_inittoken, 0, NULL, NULL},
+ { NULL, pk_genkeypair, 0, NULL, NULL},
{ NULL, pk_help, 0, NULL, NULL}
};
@@ -554,6 +595,10 @@ init_command_list()
cmds[INITTOKEN_IDX].summary = INITTOKEN_SUMM;
cmds[INITTOKEN_IDX].synopsis = INITTOKEN_SYN;
+ cmds[GENKEYPAIR_IDX].verb = GENKEYPAIR_VERB;
+ cmds[GENKEYPAIR_IDX].summary = GENKEYPAIR_SUMM;
+ cmds[GENKEYPAIR_IDX].synopsis = GENKEYPAIR_SYN;
+
cmds[HELP_IDX].verb = HELP_VERB;
cmds[HELP_IDX].summary = HELP_SUMM;
cmds[HELP_IDX].synopsis = HELP_SYN;
diff --git a/usr/src/cmd/cmd-crypto/pktool/signcsr.c b/usr/src/cmd/cmd-crypto/pktool/signcsr.c
index df85d3ec84..87c04662a9 100644
--- a/usr/src/cmd/cmd-crypto/pktool/signcsr.c
+++ b/usr/src/cmd/cmd-crypto/pktool/signcsr.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*
*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -268,6 +268,9 @@ pk_signcsr_files(KMF_HANDLE_T handle,
KMF_DATA certdata = {NULL, 0};
int numattr, count;
+ (void) memset(&cakey, 0, sizeof (cakey));
+ (void) memset(&signedCert, 0, sizeof (signedCert));
+
rv = read_csrdata(handle, csrfile, &csrdata);
if (rv != KMF_OK) {
cryptoerror(LOG_STDERR,
@@ -370,6 +373,7 @@ pk_signcsr_pk11_nss(KMF_HANDLE_T handle,
boolean_t private_bool = B_TRUE;
(void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE));
+ (void) memset(&signedCert, 0, sizeof (signedCert));
rv = read_csrdata(handle, csrfile, &csrdata);
if (rv != KMF_OK) {
diff --git a/usr/src/lib/libkmf/ber_der/common/clasn1.c b/usr/src/lib/libkmf/ber_der/common/clasn1.c
index d6e31390fd..2e1c3400c1 100644
--- a/usr/src/lib/libkmf/ber_der/common/clasn1.c
+++ b/usr/src/lib/libkmf/ber_der/common/clasn1.c
@@ -1,16 +1,15 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1995-1999 Intel Corporation. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <strings.h>
#include <kmftypes.h>
#include <ber_der.h>
+#include <kmfber_int.h>
#include <kmfapi.h>
#include <kmfapiP.h>
@@ -23,14 +22,18 @@ const KMF_OID extension_request_oid = {OID_PKCS_9_LENGTH + 1,
OID_ExtensionRequest};
static KMF_RETURN
-encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
+encode_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid,
+ boolean_t encode_params)
{
KMF_RETURN ret = KMF_OK;
if (kmfber_printf(asn1, "{D", &algoid->algorithm) == -1) {
ret = KMF_ERR_BAD_CERT_FORMAT;
}
- if (algoid->parameters.Data == NULL ||
+ if (!encode_params) {
+ if (kmfber_printf(asn1, "}") == -1)
+ return (KMF_ERR_BAD_CERT_FORMAT);
+ } else if (algoid->parameters.Data == NULL ||
algoid->parameters.Length == 0) {
if (kmfber_printf(asn1, "n}") == -1)
return (KMF_ERR_BAD_CERT_FORMAT);
@@ -196,31 +199,98 @@ free_decoded_cert(KMF_X509_CERTIFICATE *certptr)
}
static KMF_RETURN
-get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
+get_sequence_data(BerElement *asn1, BerValue *seqdata)
{
- KMF_RETURN ret = KMF_OK;
- ber_tag_t tag, newtag;
+ ber_tag_t tag;
ber_len_t size;
- BerValue AlgOID = {NULL, 0};
tag = kmfber_next_element(asn1, &size, NULL);
- if (tag != BER_CONSTRUCTED_SEQUENCE)
+ if (tag == BER_OBJECT_IDENTIFIER) {
+ /* The whole block is the OID. */
+ size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
+ seqdata->bv_val = malloc(size);
+ if (seqdata->bv_val == NULL) {
+ return (KMF_ERR_MEMORY);
+ }
+ /* read the raw data into the Algoritm params area. */
+ if (kmfber_read(asn1, seqdata->bv_val, size) ==
+ -1) {
+ return (KMF_ERR_BAD_CERT_FORMAT);
+ }
+ seqdata->bv_len = size;
+ return (KMF_OK);
+ } else if (tag != BER_CONSTRUCTED_SEQUENCE)
+ return (KMF_ERR_BAD_CERT_FORMAT);
+
+ if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) {
return (KMF_ERR_BAD_CERT_FORMAT);
+ }
+ /*
+ * We need to read the tag and the length bytes too,
+ * so adjust the size.
+ */
+ size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
+ seqdata->bv_val = malloc(size);
+ if (seqdata->bv_val == NULL) {
+ return (KMF_ERR_MEMORY);
+ }
+ /* read the raw data into the Algoritm params area. */
+ if (kmfber_read(asn1, seqdata->bv_val, size) ==
+ -1) {
+ return (KMF_ERR_BAD_CERT_FORMAT);
+ }
+ seqdata->bv_len = size;
+ return (KMF_OK);
+}
+
+static KMF_RETURN
+get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
+{
+ KMF_RETURN rv = KMF_OK;
+ ber_tag_t tag;
+ ber_len_t size;
+ BerValue algoid_data;
+ BerValue AlgOID;
+ BerElement *oidasn1 = NULL;
+
+ /* Read the entire OID seq into it's own data block */
+ rv = get_sequence_data(asn1, &algoid_data);
+ if (rv != KMF_OK)
+ return (rv);
+
+ /* Now parse just this block so we don't overrun */
+ if ((oidasn1 = kmfder_init(&algoid_data)) == NULL)
+ return (KMF_ERR_MEMORY);
+ tag = kmfber_next_element(oidasn1, &size, NULL);
+ if (tag == BER_OBJECT_IDENTIFIER) {
+ algoid->algorithm.Data = (uchar_t *)algoid_data.bv_val;
+ algoid->algorithm.Length = algoid_data.bv_len;
+ algoid->parameters.Data = NULL;
+ algoid->parameters.Length = 0;
+ kmfber_free(oidasn1, 1);
+ return (KMF_OK);
+ }
- if ((tag = kmfber_scanf(asn1, "{Dt", &AlgOID, &newtag)) == -1) {
+ if ((tag = kmfber_scanf(oidasn1, "{D", &AlgOID)) == -1) {
+ kmfber_free(oidasn1, 1);
return (KMF_ERR_BAD_CERT_FORMAT);
}
algoid->algorithm.Data = (uchar_t *)AlgOID.bv_val;
algoid->algorithm.Length = AlgOID.bv_len;
- if (newtag == BER_NULL) {
- (void) kmfber_scanf(asn1, "n}");
+ tag = kmfber_next_element(oidasn1, &size, NULL);
+ if (tag == BER_NULL) {
+ (void) kmfber_scanf(oidasn1, "n}");
+ algoid->parameters.Data = NULL;
+ algoid->parameters.Length = 0;
+ } else if (tag == KMFBER_END_OF_SEQORSET || tag == KMFBER_DEFAULT) {
+ /* close sequence, we are done with Algoid */
algoid->parameters.Data = NULL;
algoid->parameters.Length = 0;
} else {
- /* Peek at the tag and length bytes */
- if ((kmfber_scanf(asn1, "tl", &tag, &size)) == -1) {
- ret = KMF_ERR_BAD_CERT_FORMAT;
+ /* The rest of the data is the algorithm parameters */
+ if ((kmfber_scanf(oidasn1, "tl", &tag, &size)) == -1) {
+ rv = KMF_ERR_BAD_CERT_FORMAT;
goto cleanup;
}
@@ -231,26 +301,24 @@ get_algoid(BerElement *asn1, KMF_X509_ALGORITHM_IDENTIFIER *algoid)
size += kmfber_calc_taglen(tag) + kmfber_calc_lenlen(size);
algoid->parameters.Data = malloc(size);
if (algoid->parameters.Data == NULL) {
- ret = KMF_ERR_MEMORY;
+ rv = KMF_ERR_MEMORY;
goto cleanup;
}
/* read the raw data into the Algoritm params area. */
- if (kmfber_read(asn1, (char *)algoid->parameters.Data,
+ if (kmfber_read(oidasn1, (char *)algoid->parameters.Data,
size) == -1) {
- ret = KMF_ERR_BAD_CERT_FORMAT;
+ rv = KMF_ERR_BAD_CERT_FORMAT;
goto cleanup;
}
algoid->parameters.Length = size;
- if ((tag = kmfber_scanf(asn1, "}")) == -1) {
- ret = KMF_ERR_BAD_CERT_FORMAT;
- }
}
cleanup:
- if (ret != KMF_OK) {
+ if (rv != KMF_OK) {
free_algoid(algoid);
}
+ kmfber_free(oidasn1, 1);
- return (ret);
+ return (rv);
}
static KMF_RETURN
@@ -274,7 +342,11 @@ encode_spki(BerElement *asn1, KMF_X509_SPKI *spki)
if (kmfber_printf(asn1, "{") == -1)
return (KMF_ERR_BAD_CERT_FORMAT);
- if ((ret = encode_algoid(asn1, &spki->algorithm)) != KMF_OK)
+ /*
+ * The SPKI is the only place where algorithm parameters
+ * should be encoded.
+ */
+ if ((ret = encode_algoid(asn1, &spki->algorithm, TRUE)) != KMF_OK)
return (ret);
if (kmfber_printf(asn1, "B}", spki->subjectPublicKey.Data,
@@ -346,6 +418,7 @@ cleanup:
return (ret);
}
+
KMF_RETURN
DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
{
@@ -356,7 +429,7 @@ DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
if (rawdata == NULL || signature == NULL)
return (KMF_ERR_BAD_PARAMETER);
- if (rawdata->Data == NULL || rawdata->Length != DSA_RAW_SIG_LEN)
+ if (rawdata->Data == NULL || rawdata->Length == 0)
return (KMF_ERR_BAD_PARAMETER);
asn1 = kmfder_alloc();
@@ -364,10 +437,10 @@ DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
return (KMF_ERR_MEMORY);
/*
- * The DSA signature is the concatenation of 2 SHA-1 hashed
+ * The [EC]DSA signature is the concatenation of 2
* bignum values.
*/
- n = DSA_RAW_SIG_LEN/2;
+ n = rawdata->Length/2;
if (kmfber_printf(asn1, "{II}",
rawdata->Data, n, &rawdata->Data[n], n) == -1) {
kmfber_free(asn1, 1);
@@ -388,12 +461,60 @@ DerEncodeDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
return (KMF_OK);
}
+/*
+ * ECDSA and DSA encode signatures the same way.
+ */
+KMF_RETURN
+DerEncodeECDSASignature(KMF_DATA *rawdata, KMF_DATA *signature)
+{
+ return (DerEncodeDSASignature(rawdata, signature));
+}
+
+/*
+ * Convert a signed DSA sig to a fixed-length unsigned one.
+ * This is necessary because DER encoding seeks to use the
+ * minimal amount of bytes but we need a full 20 byte DSA
+ * value with leading 0x00 bytes.
+ */
+static KMF_RETURN
+convert_signed_to_fixed(BerValue *src, BerValue *dst)
+{
+ int cnt;
+ char *p;
+ if (dst->bv_len > src->bv_len) {
+ cnt = dst->bv_len - src->bv_len;
+ /* prepend with leading 0s */
+ (void) memset(dst->bv_val, 0x00, cnt);
+ (void) memcpy(dst->bv_val + cnt, src->bv_val,
+ src->bv_len);
+ return (KMF_OK);
+ }
+ if (dst->bv_len == src->bv_len) {
+ (void) memcpy(dst->bv_val, src->bv_val,
+ dst->bv_len);
+ return (KMF_OK);
+ }
+ /*
+ * src is larger than dest, strip leading 0s.
+ * This should not be necessary, but do it just in case.
+ */
+ cnt = src->bv_len - dst->bv_len;
+ p = src->bv_val;
+ while (cnt-- > 0) {
+ if (*p++ != 0x00)
+ return (KMF_ERR_ENCODING);
+ }
+ (void) memcpy(dst->bv_val, p, dst->bv_len);
+ return (KMF_OK);
+}
+
KMF_RETURN
DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
{
KMF_RETURN ret = KMF_OK;
BerElement *asn1 = NULL;
BerValue buf, *R = NULL, *S = NULL;
+ BerValue fixedR, fixedS;
buf.bv_val = (char *)encoded->Data;
buf.bv_len = encoded->Length;
@@ -413,14 +534,50 @@ DerDecodeDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
goto cleanup;
}
signature->Length = R->bv_len + S->bv_len;
+ /*
+ * If either of the values had a leading 0 lopped off
+ * they will be 1 byte short and need to be adjusted below.
+ * The stripping is correct as per ASN.1 rules.
+ *
+ * We don't know the exact length that the R and S values
+ * must be, it depends on the signature algorithm and,
+ * in the case of EC, the curve used. So instead of
+ * checking for a specific length, we just check to see
+ * if the value came out to be an odd number. If so,
+ * then we know it needs a leading 0x00 byte which
+ * will be added below when we convert it to a fixed
+ * length.
+ */
+ if ((R->bv_len % 2) != 0)
+ signature->Length++;
+ if ((S->bv_len % 2) != 0)
+ signature->Length++;
+
signature->Data = malloc(signature->Length);
if (signature->Data == NULL) {
ret = KMF_ERR_MEMORY;
goto cleanup;
}
- (void) memcpy(signature->Data, R->bv_val, R->bv_len);
- (void) memcpy(&signature->Data[R->bv_len], S->bv_val, S->bv_len);
+ fixedR.bv_val = (char *)signature->Data;
+ /* adjust length if it needs a leading 0x00 byte */
+ fixedR.bv_len = R->bv_len + (R->bv_len % 2);
+
+ fixedS.bv_val = (char *)(signature->Data + fixedR.bv_len);
+ /* adjust length if it needs a leading 0x00 byte */
+ fixedS.bv_len = S->bv_len + (S->bv_len % 2);
+
+ /*
+ * This will add back any missing leading 0's
+ * that were stripped off earlier when the signature
+ * was parsed. This ensures that the 2 parts of the
+ * signature are the right length and have the proper
+ * leading 0's prepended.
+ */
+ ret = convert_signed_to_fixed(R, &fixedR);
+ if (ret)
+ goto cleanup;
+ ret = convert_signed_to_fixed(S, &fixedS);
cleanup:
if (R && R->bv_val)
free(R->bv_val);
@@ -436,6 +593,13 @@ cleanup:
}
KMF_RETURN
+DerDecodeECDSASignature(KMF_DATA *encoded, KMF_DATA *signature)
+{
+ /* ECDSA can be decoded using same code as standard DSA */
+ return (DerDecodeDSASignature(encoded, signature));
+}
+
+KMF_RETURN
DerDecodeSPKI(KMF_DATA *EncodedSPKI, KMF_X509_SPKI *spki)
{
KMF_RETURN ret = KMF_OK;
@@ -1472,7 +1636,8 @@ encode_tbs_cert(BerElement *asn1, KMF_X509_TBS_CERT *tbscert)
goto cleanup;
}
- if ((ret = encode_algoid(asn1, &tbscert->signature)) != KMF_OK)
+ /* Don't encode alg parameters in signature algid area */
+ if ((ret = encode_algoid(asn1, &tbscert->signature, FALSE)) != KMF_OK)
goto cleanup;
/* Encode the Issuer RDN */
@@ -1601,9 +1766,9 @@ DerEncodeSignedCertificate(KMF_X509_CERTIFICATE *signed_cert_ptr,
goto cleanup;
}
- /* Add the Algorithm & Signature Sequence */
+ /* Add the Algorithm & Signature Sequence (no parameters) */
if ((ret = encode_algoid(asn1,
- &signature->algorithmIdentifier)) != KMF_OK)
+ &signature->algorithmIdentifier, FALSE)) != KMF_OK)
goto cleanup;
if (signature->encrypted.Length > 0) {
@@ -1721,90 +1886,6 @@ cleanup:
return (ret);
}
-/*
- * Name: GetKeyFromSpki
- *
- * Description:
- * This function parses the KMF_X509_SPKI into its
- * key and parameter components based on the key generation algorithm.
- * NOTE: Currently, it only checks for the RSA and DSA algorithms.
- * The RSA algorithm is equivalent to the default behavior.
- * All other algorithms will default to the parameters = NULL and the
- * key data equal to whatever is in the CSSM_KEY structure for the key
- *
- * Parameters:
- * AlgId (input) : Algorithm identifier
- * SpkiPtr (input): SPKI structure that contains the key
- * key_ptr(output): The output key
- *
- */
-KMF_RETURN
-GetKeyFromSpki(KMF_ALGORITHM_INDEX AlgId,
- KMF_X509_SPKI *SpkiPtr,
- KMF_DATA **key_ptr)
-{
- KMF_RETURN ret = KMF_OK;
- BerElement *asn1;
- BerValue *encodedkey = NULL;
-
- if (!key_ptr || !SpkiPtr) {
- return (KMF_ERR_BAD_PARAMETER);
- }
- *key_ptr = NULL;
-
- switch (AlgId) {
- case KMF_ALGID_DSA:
- asn1 = kmfder_alloc();
- if (asn1 == NULL) {
- return (KMF_ERR_MEMORY);
- }
-
- if ((ret = encode_spki(asn1, SpkiPtr)) != KMF_OK) {
- ret = KMF_ERR_MEMORY;
- goto cleanup;
- }
-
- if (kmfber_flatten(asn1, &encodedkey) == -1) {
- ret = KMF_ERR_MEMORY;
- goto cleanup;
- }
-
- *key_ptr = malloc(sizeof (KMF_DATA));
-
- if (!*key_ptr) {
- ret = KMF_ERR_MEMORY;
- goto cleanup;
- }
-
- (*key_ptr)->Length = encodedkey->bv_len;
- (*key_ptr)->Data = (uchar_t *)encodedkey->bv_val;
-cleanup:
- kmfber_free(asn1, 1);
- if (encodedkey)
- free(encodedkey);
- break;
- default: /* RSA */
- *key_ptr = malloc(sizeof (KMF_DATA));
-
- if (!*key_ptr) {
- return (KMF_ERR_MEMORY);
- }
- (*key_ptr)->Length = SpkiPtr->subjectPublicKey.Length;
- (*key_ptr)->Data = malloc((*key_ptr)->Length);
-
- if (!(*key_ptr)->Data) {
- free(*key_ptr);
- *key_ptr = NULL;
- return (KMF_ERR_MEMORY);
- }
- (void) memcpy((*key_ptr)->Data,
- SpkiPtr->subjectPublicKey.Data,
- (*key_ptr)->Length);
- return (ret);
- }
- return (ret);
-}
-
static KMF_RETURN
decode_csr_extensions(BerElement *asn1, KMF_X509_EXTENSIONS *extns)
{
@@ -2133,7 +2214,6 @@ encode_tbs_csr(BerElement *asn1, KMF_TBS_CSR *tbscsr)
if ((ret = encode_spki(asn1, &tbscsr->subjectPublicKeyInfo)) != KMF_OK)
goto cleanup;
-
if ((ret = encode_csr_extensions(asn1, tbscsr)) != KMF_OK)
goto cleanup;
@@ -2216,6 +2296,56 @@ cleanup:
return (rv);
}
+KMF_RETURN
+DerEncodeECPrivateKey(KMF_DATA *encodedkey, KMF_RAW_EC_KEY *eckey)
+{
+ KMF_RETURN rv = KMF_OK;
+ BerElement *asn1 = NULL;
+ uchar_t ver = 1;
+ BerValue *data = NULL;
+
+ asn1 = kmfder_alloc();
+ if (asn1 == NULL)
+ return (KMF_ERR_MEMORY);
+
+ if (kmfber_printf(asn1, "{io",
+ ver, eckey->value.val, eckey->value.len) == -1) {
+ rv = KMF_ERR_ENCODING;
+ goto cleanup;
+ }
+ /*
+ * Indicate that we are using the named curve option
+ * for the parameters.
+ */
+ if (kmfber_printf(asn1, "T", 0xA0) == -1) {
+ rv = KMF_ERR_ENCODING;
+ goto cleanup;
+ }
+ if (kmfber_printf(asn1, "l", eckey->params.Length) == -1) {
+ rv = KMF_ERR_ENCODING;
+ goto cleanup;
+ }
+ if (kmfber_write(asn1, (char *)eckey->params.Data,
+ eckey->params.Length, 0) == -1) {
+ rv = KMF_ERR_ENCODING;
+ goto cleanup;
+ }
+ if (kmfber_printf(asn1, "}") == -1) {
+ rv = KMF_ERR_ENCODING;
+ goto cleanup;
+ }
+ if (kmfber_flatten(asn1, &data) == -1) {
+ rv = KMF_ERR_MEMORY;
+ goto cleanup;
+ }
+ encodedkey->Data = (uchar_t *)data->bv_val;
+ encodedkey->Length = data->bv_len;
+
+cleanup:
+ kmfber_free(asn1, 1);
+ return (rv);
+}
+
KMF_RETURN
DerEncodeTbsCsr(KMF_TBS_CSR *tbs_csr_ptr,
@@ -2288,7 +2418,7 @@ DerEncodeSignedCsr(KMF_CSR_DATA *signed_csr_ptr,
/* Add the Algorithm & Signature Sequence */
if ((ret = encode_algoid(asn1,
- &signature->algorithmIdentifier)) != KMF_OK)
+ &signature->algorithmIdentifier, FALSE)) != KMF_OK)
goto cleanup;
if (signature->encrypted.Length > 0) {
@@ -2325,6 +2455,24 @@ cleanup:
return (ret);
}
+static KMF_RETURN
+ber_copy_data(KMF_DATA *dst, KMF_DATA *src)
+{
+ KMF_RETURN ret = KMF_OK;
+
+ if (dst == NULL || src == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ dst->Data = malloc(src->Length);
+ if (dst->Data == NULL)
+ return (KMF_ERR_MEMORY);
+
+ dst->Length = src->Length;
+ (void) memcpy(dst->Data, src->Data, src->Length);
+
+ return (ret);
+}
+
KMF_RETURN
ExtractSPKIData(
const KMF_X509_SPKI *pKey,
@@ -2388,6 +2536,16 @@ ExtractSPKIData(
*uNumKeyParts = KMF_NUMBER_DSA_PUBLIC_KEY_PARTS;
break;
+ case KMF_ALGID_SHA1WithECDSA:
+ case KMF_ALGID_ECDSA:
+ (void) ber_copy_data(&pKeyParts[KMF_ECDSA_PARAMS],
+ (KMF_DATA *)&pKey->algorithm.parameters);
+
+ (void) ber_copy_data(&pKeyParts[KMF_ECDSA_POINT],
+ (KMF_DATA *)&pKey->subjectPublicKey);
+
+ *uNumKeyParts = 2;
+ break;
case KMF_ALGID_RSA:
case KMF_ALGID_MD2WithRSA:
diff --git a/usr/src/lib/libkmf/ber_der/common/decode.c b/usr/src/lib/libkmf/ber_der/common/decode.c
index 459c49fdbe..cdae8d84a9 100644
--- a/usr/src/lib/libkmf/ber_der/common/decode.c
+++ b/usr/src/lib/libkmf/ber_der/common/decode.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -345,10 +345,10 @@ ber_get_bigint(BerElement *ber, struct berval **bv)
(*bv)->bv_len = len;
- /* If DER encoding, strip leading 0's */
+ /* If DER encoding, strip leading 0's if high-order bit is set */
if (ber->ber_options & KMFBER_OPT_USE_DER) {
char *p = (*bv)->bv_val;
- while ((*p == 0x00) && ((*bv)->bv_len > 0)) {
+ while ((*p == 0x00) && ((*bv)->bv_len > 0) && (p[1] & 0x80)) {
p++;
(*bv)->bv_len--;
}
diff --git a/usr/src/lib/libkmf/ber_der/common/mapfile-vers b/usr/src/lib/libkmf/ber_der/common/mapfile-vers
index 0a97cd2eab..cda7690c8d 100644
--- a/usr/src/lib/libkmf/ber_der/common/mapfile-vers
+++ b/usr/src/lib/libkmf/ber_der/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -43,6 +43,7 @@ SUNWprivate_1.1 {
CopyRDN;
CopySPKI;
DerDecodeDSASignature;
+ DerDecodeECDSASignature;
DerDecodeExtension;
DerDecodeName;
DerDecodeSPKI;
@@ -52,6 +53,8 @@ SUNWprivate_1.1 {
DerDecodeTbsCsr;
DerEncodeDSAPrivateKey;
DerEncodeDSASignature;
+ DerEncodeECDSASignature;
+ DerEncodeECPrivateKey;
DerEncodeName;
DerEncodeRSAPrivateKey;
DerEncodeSPKI;
@@ -61,7 +64,6 @@ SUNWprivate_1.1 {
DerEncodeTbsCsr;
ExtractSPKIData;
ExtractX509CertParts;
- GetKeyFromSpki;
kmfber_alloc;
kmfber_bvfree;
kmfber_first_element;
diff --git a/usr/src/lib/libkmf/ber_der/inc/ber_der.h b/usr/src/lib/libkmf/ber_der/inc/ber_der.h
index abf112351d..4c2da6c91a 100644
--- a/usr/src/lib/libkmf/ber_der/inc/ber_der.h
+++ b/usr/src/lib/libkmf/ber_der/inc/ber_der.h
@@ -1,11 +1,9 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
- * Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4
- *
* The contents of this file are subject to the Netscape Public License
* Version 1.0(the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
@@ -143,8 +141,6 @@ extern KMF_RETURN DerDecodeTbsCsr(const KMF_DATA *, KMF_TBS_CSR **);
extern KMF_RETURN DerEncodeTbsCsr(KMF_TBS_CSR *, KMF_DATA *);
KMF_RETURN ExtractX509CertParts(KMF_DATA *, KMF_DATA *, KMF_DATA *);
-KMF_RETURN GetKeyFromSpki(KMF_ALGORITHM_INDEX, KMF_X509_SPKI *,
- KMF_DATA **);
extern KMF_RETURN DerEncodeName(KMF_X509_NAME *, KMF_DATA *);
KMF_RETURN DerDecodeName(KMF_DATA *, KMF_X509_NAME *);
KMF_RETURN DerDecodeExtension(KMF_DATA *, KMF_X509_EXTENSION **);
@@ -154,6 +150,8 @@ KMF_RETURN CopySPKI(KMF_X509_SPKI *,
extern KMF_RETURN DerDecodeSPKI(KMF_DATA *, KMF_X509_SPKI *);
extern KMF_RETURN DerDecodeDSASignature(KMF_DATA *, KMF_DATA *);
extern KMF_RETURN DerEncodeDSASignature(KMF_DATA *, KMF_DATA *);
+extern KMF_RETURN DerEncodeECDSASignature(KMF_DATA *, KMF_DATA *);
+extern KMF_RETURN DerDecodeECDSASignature(KMF_DATA *, KMF_DATA *);
KMF_RETURN DerEncodeAlgoid(KMF_DATA *, KMF_DATA *);
KMF_RETURN DerDecodeSPKI(KMF_DATA *, KMF_X509_SPKI *);
KMF_RETURN DerEncodeSPKI(KMF_X509_SPKI *, KMF_DATA *);
@@ -162,5 +160,6 @@ extern KMF_RETURN ExtractSPKIData(const KMF_X509_SPKI *,
extern KMF_RETURN AddRDN(KMF_X509_NAME *, KMF_X509_RDN *);
KMF_RETURN DerEncodeRSAPrivateKey(KMF_DATA *, KMF_RAW_RSA_KEY *);
KMF_RETURN DerEncodeDSAPrivateKey(KMF_DATA *, KMF_RAW_DSA_KEY *);
+KMF_RETURN DerEncodeECPrivateKey(KMF_DATA *, KMF_RAW_EC_KEY *);
#endif /* BER_DER_H */
diff --git a/usr/src/lib/libkmf/include/algorithm.h b/usr/src/lib/libkmf/include/algorithm.h
deleted file mode 100644
index 00e2eabddf..0000000000
--- a/usr/src/lib/libkmf/include/algorithm.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
- */
-
-#ifndef _ALGORITHM_H
-#define _ALGORITHM_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <kmftypes.h>
-#include <security/cryptoki.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct pkcs_algorithm_map
-{
- CK_MECHANISM_TYPE pkcs_mechanism;
- uint32_t algorithm;
- uint32_t context_type;
- uint32_t enc_mode;
- CK_BBOOL bMultiPart;
- CK_BBOOL fix_keylength;
- uint32_t keylength;
- CK_BBOOL fix_blocksize;
- uint32_t block_size;
- CK_BBOOL requires_iv;
- uint32_t iv_length;
- CK_FLAGS required_flags;
- CK_KEY_TYPE key_type;
- char *szDescription;
-} PKCS_ALGORITHM_MAP;
-
-extern KMF_SIGNATURE_MODE PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX);
-extern PKCS_ALGORITHM_MAP* pkcs_get_alg_map(KMF_ALGCLASS, uint32_t,
- uint32_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ALGORITHM_H */
diff --git a/usr/src/lib/libkmf/include/kmfapiP.h b/usr/src/lib/libkmf/include/kmfapiP.h
index 1e0d108f92..27deeb460c 100644
--- a/usr/src/lib/libkmf/include/kmfapiP.h
+++ b/usr/src/lib/libkmf/include/kmfapiP.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _KMFAPIP_H
@@ -143,13 +143,6 @@ typedef struct {
KMF_HANDLE_T,
int, KMF_ATTRIBUTE *);
- KMF_RETURN (*VerifyDataWithCert) (
- KMF_HANDLE_T,
- KMF_ALGORITHM_INDEX,
- KMF_DATA *,
- KMF_DATA *,
- KMF_DATA *);
-
KMF_RETURN (*StoreKey) (
KMF_HANDLE_T,
int,
@@ -224,6 +217,10 @@ VerifyDataWithKey(KMF_HANDLE_T, KMF_DATA *, KMF_ALGORITHM_INDEX,
extern KMF_BOOL pkcs_algid_to_keytype(
KMF_ALGORITHM_INDEX, CK_KEY_TYPE *);
+extern KMF_RETURN PKCS_DigestData(KMF_HANDLE_T,
+ CK_SESSION_HANDLE, CK_MECHANISM_TYPE,
+ KMF_DATA *, KMF_DATA *, boolean_t);
+
extern KMF_RETURN PKCS_VerifyData(
KMF_HANDLE *,
KMF_ALGORITHM_INDEX,
@@ -247,10 +244,6 @@ extern KMF_RETURN copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
extern KMF_OID *x509_algid_to_algoid(KMF_ALGORITHM_INDEX);
extern KMF_ALGORITHM_INDEX x509_algoid_to_algid(KMF_OID *);
-extern KMF_RETURN PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
- const KMF_X509_SPKI *, CK_KEY_TYPE, CK_OBJECT_HANDLE *,
- KMF_BOOL *);
-
extern KMF_RETURN GetIDFromSPKI(KMF_X509_SPKI *, KMF_DATA *);
extern KMF_RETURN kmf_select_token(KMF_HANDLE_T, char *, int);
extern KMF_RETURN kmf_set_altname(KMF_X509_EXTENSIONS *,
@@ -295,6 +288,9 @@ extern KMF_RETURN test_attributes(int, KMF_ATTRIBUTE_TESTER *,
#define KMF_DSA_BASE (2)
#define KMF_DSA_PUBLIC_VALUE (3)
+#define KMF_ECDSA_PARAMS (0)
+#define KMF_ECDSA_POINT (1)
+
#ifndef max
#define max(a, b) ((a) < (b) ? (b) : (a))
#endif
@@ -341,7 +337,10 @@ typedef struct conf_entrylist {
struct conf_entrylist *next;
} conf_entrylist_t;
-
+extern KMF_RETURN get_pk11_data(KMF_ALGORITHM_INDEX,
+ CK_KEY_TYPE *, CK_MECHANISM_TYPE *, CK_MECHANISM_TYPE *, boolean_t);
+extern KMF_RETURN kmf_create_pk11_session(CK_SESSION_HANDLE *,
+ CK_MECHANISM_TYPE, CK_FLAGS);
extern KMF_RETURN get_entrylist(conf_entrylist_t **);
extern void free_entrylist(conf_entrylist_t *);
extern void free_entry(conf_entry_t *);
diff --git a/usr/src/lib/libkmf/include/kmftypes.h b/usr/src/lib/libkmf/include/kmftypes.h
index dbbf680537..01e38862dc 100644
--- a/usr/src/lib/libkmf/include/kmftypes.h
+++ b/usr/src/lib/libkmf/include/kmftypes.h
@@ -115,6 +115,9 @@ typedef enum {
* Algorithms
* This type defines a set of constants used to identify cryptographic
* algorithms.
+ *
+ * When adding new ALGID, be careful not to rearrange existing
+ * values, doing so can cause problem in the STC test suite.
*/
typedef enum {
KMF_ALGID_NONE = 0,
@@ -125,7 +128,20 @@ typedef enum {
KMF_ALGID_MD5WithRSA,
KMF_ALGID_MD2WithRSA,
KMF_ALGID_SHA1WithRSA,
- KMF_ALGID_SHA1WithDSA
+ KMF_ALGID_SHA1WithDSA,
+
+ KMF_ALGID_ECDSA,
+
+ KMF_ALGID_SHA256WithRSA,
+ KMF_ALGID_SHA384WithRSA,
+ KMF_ALGID_SHA512WithRSA,
+
+ KMF_ALGID_SHA256WithDSA,
+
+ KMF_ALGID_SHA1WithECDSA,
+ KMF_ALGID_SHA256WithECDSA,
+ KMF_ALGID_SHA384WithECDSA,
+ KMF_ALGID_SHA512WithECDSA
} KMF_ALGORITHM_INDEX;
/*
@@ -146,7 +162,8 @@ typedef enum {
KMF_RC4 = 4,
KMF_DES = 5,
KMF_DES3 = 6,
- KMF_GENERIC_SECRET = 7
+ KMF_GENERIC_SECRET = 7,
+ KMF_ECDSA = 8
}KMF_KEY_ALG;
typedef enum {
@@ -156,7 +173,6 @@ typedef enum {
KMF_SYMMETRIC = 3 /* symmetric key */
}KMF_KEY_CLASS;
-
typedef enum {
KMF_CERT = 0,
KMF_CSR = 1,
@@ -187,6 +203,11 @@ typedef struct {
} KMF_RAW_SYM_KEY;
typedef struct {
+ KMF_BIGINT value;
+ KMF_OID params;
+} KMF_RAW_EC_KEY;
+
+typedef struct {
KMF_KEY_ALG keytype;
boolean_t sensitive;
boolean_t not_extractable;
@@ -194,6 +215,7 @@ typedef struct {
KMF_RAW_RSA_KEY rsa;
KMF_RAW_DSA_KEY dsa;
KMF_RAW_SYM_KEY sym;
+ KMF_RAW_EC_KEY ec;
}rawdata;
char *label;
KMF_DATA id;
@@ -355,20 +377,6 @@ typedef enum {
} KMF_OCSP_REVOKED_STATUS;
typedef enum {
- KMF_ALGCLASS_NONE = 0,
- KMF_ALGCLASS_CUSTOM,
- KMF_ALGCLASS_SIGNATURE,
- KMF_ALGCLASS_SYMMETRIC,
- KMF_ALGCLASS_DIGEST,
- KMF_ALGCLASS_RANDOMGEN,
- KMF_ALGCLASS_UNIQUEGEN,
- KMF_ALGCLASS_MAC,
- KMF_ALGCLASS_ASYMMETRIC,
- KMF_ALGCLASS_KEYGEN,
- KMF_ALGCLASS_DERIVEKEY
-} KMF_ALGCLASS;
-
-typedef enum {
KMF_CERT_ISSUER = 1,
KMF_CERT_SUBJECT,
KMF_CERT_VERSION,
@@ -786,7 +794,8 @@ typedef enum {
KMF_CIPHERTEXT_DATA_ATTR,
KMF_VALIDATE_RESULT_ATTR,
KMF_KEY_DATA_ATTR,
- KMF_PK11_USER_TYPE_ATTR
+ KMF_PK11_USER_TYPE_ATTR,
+ KMF_ECC_CURVE_OID_ATTR
} KMF_ATTR_TYPE;
typedef struct {
@@ -1155,11 +1164,14 @@ KMFOID_PKIX_KP_OCSPSigning,
KMFOID_SHA1,
KMFOID_RSA,
KMFOID_DSA,
+KMFOID_MD5,
KMFOID_MD5WithRSA,
KMFOID_MD2WithRSA,
KMFOID_SHA1WithRSA,
+KMFOID_SHA256WithRSA,
+KMFOID_SHA384WithRSA,
+KMFOID_SHA512WithRSA,
KMFOID_SHA1WithDSA,
-KMFOID_OIW_DSAWithSHA1,
KMFOID_X9CM_DSA,
KMFOID_X9CM_DSAWithSHA1;
@@ -1171,6 +1183,79 @@ KMFOID_PKINIT_Kdc,
KMFOID_MS_KP_SCLogon,
KMFOID_MS_KP_SCLogon_UPN;
+/* For ECC support */
+extern const KMF_OID
+KMFOID_EC_PUBLIC_KEY,
+KMFOID_SHA1WithECDSA,
+KMFOID_SHA224WithECDSA,
+KMFOID_SHA256WithECDSA,
+KMFOID_SHA384WithECDSA,
+KMFOID_SHA512WithECDSA,
+KMFOID_SHA224WithDSA,
+KMFOID_SHA256WithDSA,
+KMFOID_SHA224,
+KMFOID_SHA256,
+KMFOID_SHA384,
+KMFOID_SHA512,
+KMFOID_ECC_secp112r1,
+KMFOID_ECC_secp112r2,
+KMFOID_ECC_secp128r1,
+KMFOID_ECC_secp128r2,
+KMFOID_ECC_secp160k1,
+KMFOID_ECC_secp160r1,
+KMFOID_ECC_secp160r2,
+KMFOID_ECC_secp192k1,
+KMFOID_ECC_secp224k1,
+KMFOID_ECC_secp224r1,
+KMFOID_ECC_secp256k1,
+KMFOID_ECC_secp384r1,
+KMFOID_ECC_secp521r1,
+KMFOID_ECC_sect113r1,
+KMFOID_ECC_sect113r2,
+KMFOID_ECC_sect131r1,
+KMFOID_ECC_sect131r2,
+KMFOID_ECC_sect163k1,
+KMFOID_ECC_sect163r1,
+KMFOID_ECC_sect163r2,
+KMFOID_ECC_sect193r1,
+KMFOID_ECC_sect193r2,
+KMFOID_ECC_sect233k1,
+KMFOID_ECC_sect233r1,
+KMFOID_ECC_sect239k1,
+KMFOID_ECC_sect283k1,
+KMFOID_ECC_sect283r1,
+KMFOID_ECC_sect409k1,
+KMFOID_ECC_sect409r1,
+KMFOID_ECC_sect571k1,
+KMFOID_ECC_sect571r1,
+KMFOID_ECC_c2pnb163v1,
+KMFOID_ECC_c2pnb163v2,
+KMFOID_ECC_c2pnb163v3,
+KMFOID_ECC_c2pnb176v1,
+KMFOID_ECC_c2tnb191v1,
+KMFOID_ECC_c2tnb191v2,
+KMFOID_ECC_c2tnb191v3,
+KMFOID_ECC_c2pnb208w1,
+KMFOID_ECC_c2tnb239v1,
+KMFOID_ECC_c2tnb239v2,
+KMFOID_ECC_c2tnb239v3,
+KMFOID_ECC_c2pnb272w1,
+KMFOID_ECC_c2pnb304w1,
+KMFOID_ECC_c2tnb359v1,
+KMFOID_ECC_c2pnb368w1,
+KMFOID_ECC_c2tnb431r1,
+KMFOID_ECC_prime192v2,
+KMFOID_ECC_prime192v3,
+KMFOID_ECC_secp192r1,
+KMFOID_ECC_secp256r1;
+
+/*
+ * ANSI X9-62 prime192v1 is same as secp192r1 and
+ * ANSI X9-62 prime256v1 is same as secp256r1
+ */
+#define KMFOID_ANSIX962_prime192v1 KMFOID_ECC_secp192r1
+#define KMFOID_ANSIX962_prime256v1 KMFOID_ECC_secp256r1
+
/*
* KMF Certificate validation codes. These may be masked together.
*/
diff --git a/usr/src/lib/libkmf/libkmf/Makefile.com b/usr/src/lib/libkmf/libkmf/Makefile.com
index af34cf87a3..b11f172a71 100644
--- a/usr/src/lib/libkmf/libkmf/Makefile.com
+++ b/usr/src/lib/libkmf/libkmf/Makefile.com
@@ -18,7 +18,7 @@
#
# CDDL HEADER END
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -27,7 +27,6 @@ VERS= .1
OBJECTS= \
algoid.o \
- algorithm.o \
certgetsetop.o \
certop.o \
client.o \
diff --git a/usr/src/lib/libkmf/libkmf/common/algoid.c b/usr/src/lib/libkmf/libkmf/common/algoid.c
index f33634f007..51804af492 100644
--- a/usr/src/lib/libkmf/libkmf/common/algoid.c
+++ b/usr/src/lib/libkmf/libkmf/common/algoid.c
@@ -2,12 +2,10 @@
* Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <string.h>
@@ -28,9 +26,17 @@ static KMF_OID_ID ALGOID_ID_Table[] = {
{(KMF_OID *)&KMFOID_RSA, KMF_ALGID_RSA},
{(KMF_OID *)&KMFOID_DSA, KMF_ALGID_DSA},
{(KMF_OID *)&KMFOID_MD5WithRSA, KMF_ALGID_MD5WithRSA},
- {(KMF_OID *)&KMFOID_MD2WithRSA, KMF_ALGID_MD2WithRSA},
{(KMF_OID *)&KMFOID_SHA1WithRSA, KMF_ALGID_SHA1WithRSA},
- {(KMF_OID *)&KMFOID_SHA1WithDSA, KMF_ALGID_SHA1WithDSA}
+ {(KMF_OID *)&KMFOID_SHA1WithDSA, KMF_ALGID_SHA1WithDSA},
+ {(KMF_OID *)&KMFOID_SHA256WithDSA, KMF_ALGID_SHA256WithDSA},
+ {(KMF_OID *)&KMFOID_SHA1WithECDSA, KMF_ALGID_SHA1WithECDSA},
+ {(KMF_OID *)&KMFOID_SHA256WithECDSA, KMF_ALGID_SHA256WithECDSA},
+ {(KMF_OID *)&KMFOID_SHA256WithRSA, KMF_ALGID_SHA256WithRSA},
+ {(KMF_OID *)&KMFOID_SHA384WithECDSA, KMF_ALGID_SHA384WithECDSA},
+ {(KMF_OID *)&KMFOID_SHA384WithRSA, KMF_ALGID_SHA384WithRSA},
+ {(KMF_OID *)&KMFOID_SHA512WithECDSA, KMF_ALGID_SHA512WithECDSA},
+ {(KMF_OID *)&KMFOID_SHA512WithRSA, KMF_ALGID_SHA512WithRSA},
+ {(KMF_OID *)&KMFOID_EC_PUBLIC_KEY, KMF_ALGID_ECDSA}
};
#define NUM_ALGOIDS ((sizeof (ALGOID_ID_Table))/(sizeof (ALGOID_ID_Table[0])))
diff --git a/usr/src/lib/libkmf/libkmf/common/algorithm.c b/usr/src/lib/libkmf/libkmf/common/algorithm.c
deleted file mode 100644
index d0ed3912a3..0000000000
--- a/usr/src/lib/libkmf/libkmf/common/algorithm.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
- */
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <kmfapiP.h>
-#include <algorithm.h>
-#include <security/cryptoki.h>
-
-typedef struct _pkcs_key_type_map
-{
- KMF_ALGORITHM_INDEX kmfAlgorithmId;
- CK_KEY_TYPE ckKeyType;
-}
-PKCS_KEY_TYPE_MAP;
-
-static const PKCS_KEY_TYPE_MAP _PKCS2KMFKeyTypeMap[] = {
- { KMF_ALGID_RSA, CKK_RSA },
- { KMF_ALGID_DSA, CKK_DSA }
-};
-
-#define SUP(_ckmech_, _kmfalg_, _kmfcls_, _kmfmode_, _multi_, \
- _fixkelen_, _keylen_, _fixblksz_, _blksz_, _reqiv_, _ivlen_,\
- _regalgflg_, _keytype_, _desc_) \
- { _ckmech_, _kmfalg_, _kmfcls_, _kmfmode_, _multi_, _fixkelen_,\
- _keylen_, _fixblksz_, _blksz_, _reqiv_, _ivlen_, _regalgflg_,\
- _keytype_, _desc_ },
-
-static const PKCS_ALGORITHM_MAP _PKCS2KMFMap[] = {
-/*
- * PKCS #11 Mechanism,
- * Alg. ID
- * Alg. Class
- * Alg. Mode
- * Milti-Part
- * Fix Key Length
- * Key Length
- * Fix Block Size
- * Block Size
- * Needs IV
- * IV Length
- * Alg. Flags
- * Type
- * Description
- */
-SUP(CKM_RSA_PKCS_KEY_PAIR_GEN, KMF_ALGID_RSA, KMF_ALGCLASS_KEYGEN,\
- KMF_ALGMODE_NONE, 0, 0, 0,\
- 0, 0, 0, 0, CKF_GENERATE_KEY_PAIR,\
- CKK_RSA, "RSA PKCS #1 Key Pair Generation")
-SUP(CKM_RSA_X_509, KMF_ALGID_RSA, KMF_ALGCLASS_ASYMMETRIC, KMF_ALGMODE_NONE,
- 0, 0, 0, 0, 0, 0, 0, CKF_ENCRYPT,
- CKK_RSA, "RSA RAW Encryption")
-SUP(CKM_RSA_X_509, KMF_ALGID_RSA, KMF_ALGCLASS_ASYMMETRIC, KMF_ALGMODE_NONE,
- 0, 0, 0, 0, 0, 0, 0, CKF_SIGN_RECOVER,
- CKK_RSA, "RSA RAW Private Key Encryption")
-SUP(CKM_RSA_X_509, KMF_ALGID_RSA, KMF_ALGCLASS_SIGNATURE, KMF_ALGMODE_NONE,
- 0, 0, 0, 0, 0, 0, 0, CKF_SIGN,
- CKK_RSA, "RSA RAW Signature")
-SUP(CKM_RSA_PKCS, KMF_ALGID_RSA, KMF_ALGCLASS_SIGNATURE,
- KMF_ALGMODE_PKCS1_EMSA_V15,
- 0, 0, 0, 0, 0, 0, 0, CKF_SIGN, CKK_RSA,
- "RSA PKCS #1 Signature")
-SUP(CKM_MD2_RSA_PKCS, KMF_ALGID_MD2WithRSA, KMF_ALGCLASS_SIGNATURE,
- KMF_ALGMODE_PKCS1_EMSA_V15, 1, 0, 0, 0, 0,
- 0, 0, CKF_SIGN, CKK_RSA, "MD2 w/RSA Signature")
-SUP(CKM_MD5_RSA_PKCS, KMF_ALGID_MD5WithRSA, KMF_ALGCLASS_SIGNATURE,
- KMF_ALGMODE_PKCS1_EMSA_V15, 1, 0, 0, 0, 0,
- 0, 0, CKF_SIGN, CKK_RSA, "MD5 w/RSA Signature")
-SUP(CKM_SHA1_RSA_PKCS, KMF_ALGID_SHA1WithRSA, KMF_ALGCLASS_SIGNATURE,
- KMF_ALGMODE_PKCS1_EMSA_V15, 1, 0, 0, 0, 0,
- 0, 0, CKF_SIGN, CKK_RSA, "SHA-1 w/RSA Signature")
-
-SUP(CKM_DSA_KEY_PAIR_GEN, KMF_ALGID_DSA, KMF_ALGCLASS_KEYGEN, KMF_ALGMODE_NONE,
- 0, 0, 0, 0, 0, 0, 0,
- CKF_GENERATE_KEY_PAIR, CKK_DSA, "DSA Key Pair Generation")
-
-SUP(CKM_DSA, KMF_ALGID_DSA, KMF_ALGCLASS_SIGNATURE, KMF_ALGMODE_NONE,
- 0, 0, 0, 0, 0, 0, 0, CKF_SIGN,
- CKK_DSA, "DSA Signature")
-
-SUP(CKM_DSA_SHA1, KMF_ALGID_SHA1WithDSA, KMF_ALGCLASS_SIGNATURE,
- KMF_ALGMODE_NONE, 1, 0, 0, 0, 0, 0,
- 0, CKF_SIGN, CKK_DSA, "SHA-1 w/DSA Signature")
-
-SUP(CKM_SHA_1, KMF_ALGID_SHA1, KMF_ALGCLASS_DIGEST, KMF_ALGMODE_NONE,
- 1, 1, 20, 0, 0, 0, 0, CKF_DIGEST, (CK_KEY_TYPE)-1, "SHA-1")
-};
-
-/* Undefine the macro definitions */
-#undef SUP
-
-/* Number of items in the algorithm map table */
-#define _PKCS2KMFMapCount (\
- sizeof (_PKCS2KMFMap) / sizeof (_PKCS2KMFMap[0]))
-
-/* Indicator that the algorithm was not found */
-#define PKCS_ALGORITHM_NOT_FOUND ((uint32_t)(~0))
-
-/*
- * Name: pkcs_get_alg_map
- *
- * Description:
- * Searches the _PKCS2KMFMap table for a matching set of alg.
- * description parameters.
- *
- * Parameters:
- * algType (input) - KMF_ALGCLASS_* identifier to match.
- * algID (input) - KMF_ALGID_* identifier to match.
- * mode (input) - KMF_ALGMODE_* identifier to match. Use
- * KMF_ALGMODE_NONE if a mode does not apply.
- *
- * Returns:
- * Pointer to the lookup table entry that matches requested parameters.
- * Ptr->keylength will equal PKCS11CONVERT_NOT_FOUND if no match is found.
- */
-PKCS_ALGORITHM_MAP *
-pkcs_get_alg_map(KMF_ALGCLASS algType, uint32_t algID, uint32_t mode)
-{
- uint32_t i = 0;
-
- for (i = 0; i < _PKCS2KMFMapCount; i++) {
- if ((_PKCS2KMFMap[i].context_type == algType) &&
- (_PKCS2KMFMap[i].algorithm == algID) &&
- (_PKCS2KMFMap[i].enc_mode == mode)) {
- return ((PKCS_ALGORITHM_MAP *)&(_PKCS2KMFMap[i]));
- }
- }
-
- return (NULL);
-}
-
-KMF_BOOL
-pkcs_algid_to_keytype(KMF_ALGORITHM_INDEX AlgId,
- CK_KEY_TYPE *pckKeyType)
-{
- uint32_t uIndex;
- uint32_t uMapSize =
- sizeof (_PKCS2KMFKeyTypeMap) / sizeof (PKCS_KEY_TYPE_MAP);
-
- for (uIndex = 0; uIndex < uMapSize; uIndex++) {
- if (_PKCS2KMFKeyTypeMap[uIndex].kmfAlgorithmId == AlgId) {
- *pckKeyType = _PKCS2KMFKeyTypeMap[uIndex].ckKeyType;
- return (1);
- }
- }
-
- return (0);
-}
diff --git a/usr/src/lib/libkmf/libkmf/common/certop.c b/usr/src/lib/libkmf/libkmf/common/certop.c
index da56202051..3302fa8de5 100644
--- a/usr/src/lib/libkmf/libkmf/common/certop.c
+++ b/usr/src/lib/libkmf/libkmf/common/certop.c
@@ -71,13 +71,23 @@ get_keyalg_from_cert(KMF_DATA *cert, KMF_KEY_ALG *keyalg)
switch (AlgorithmId) {
case KMF_ALGID_MD5WithRSA:
- case KMF_ALGID_MD2WithRSA:
case KMF_ALGID_SHA1WithRSA:
+ case KMF_ALGID_SHA256WithRSA:
+ case KMF_ALGID_SHA384WithRSA:
+ case KMF_ALGID_SHA512WithRSA:
*keyalg = KMF_RSA;
break;
case KMF_ALGID_SHA1WithDSA:
+ case KMF_ALGID_SHA256WithDSA:
*keyalg = KMF_DSA;
break;
+ case KMF_ALGID_SHA1WithECDSA:
+ case KMF_ALGID_SHA256WithECDSA:
+ case KMF_ALGID_SHA384WithECDSA:
+ case KMF_ALGID_SHA512WithECDSA:
+ case KMF_ALGID_ECDSA:
+ *keyalg = KMF_ECDSA;
+ break;
default:
rv = KMF_ERR_BAD_ALGORITHM;
}
@@ -410,8 +420,8 @@ kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
int freethekey = 0;
KMF_POLICY_RECORD *policy;
KMF_OID *oid = NULL;
- KMF_ALGORITHM_INDEX AlgId;
KMF_X509_CERTIFICATE *x509cert;
+ KMF_X509_TBS_CERT *decodedTbsCert = NULL;
KMF_ATTRIBUTE_TESTER required_attrs[] = {
{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
{KMF_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA), sizeof (KMF_DATA)}
@@ -466,18 +476,6 @@ kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
}
sign_key_ptr = &sign_key;
freethekey = 1;
-
- ret = get_sigalg_from_cert(signer_cert, &AlgId);
- if (ret != KMF_OK)
- goto out;
- else
- oid = x509_algid_to_algoid(AlgId);
- } else if (sign_key_ptr != NULL) {
- if (sign_key_ptr->keyalg == KMF_RSA) {
- oid = (KMF_OID *)&KMFOID_SHA1WithRSA;
- } else if (sign_key_ptr->keyalg == KMF_DSA) {
- oid = (KMF_OID *)&KMFOID_SHA1WithDSA;
- }
}
/* Now we are ready to sign */
@@ -490,11 +488,22 @@ kmf_sign_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
ret = KMF_ERR_BAD_PARAMETER;
goto out;
}
+
+ /* determine signature OID from cert request */
+ oid = CERT_ALG_OID(x509cert);
+
ret = kmf_encode_cert_record(x509cert, &unsignedCert);
- if (ret == KMF_OK)
- tbs_cert = &unsignedCert;
- else
+ if (ret != KMF_OK)
goto out;
+
+ tbs_cert = &unsignedCert;
+ }
+ /* If OID still not found, decode the TBS Cert and pull it out */
+ if (oid == NULL) {
+ ret = DerDecodeTbsCertificate(tbs_cert, &decodedTbsCert);
+ if (ret != KMF_OK)
+ goto out;
+ oid = &decodedTbsCert->signature.algorithm;
}
signed_cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist,
@@ -515,6 +524,10 @@ out:
kmf_free_kmf_key(handle, &sign_key);
kmf_free_data(&unsignedCert);
+ if (decodedTbsCert != NULL) {
+ kmf_free_tbs_cert(decodedTbsCert);
+ free(decodedTbsCert);
+ }
return (ret);
}
@@ -564,7 +577,7 @@ kmf_sign_data(KMF_HANDLE_T handle, int numattr,
KMF_DATA *tbs_data = NULL; /* to be signed data */
KMF_DATA *output = NULL;
KMF_KEY_HANDLE sign_key, *sign_key_ptr;
- KMF_ALGORITHM_INDEX AlgId;
+ KMF_ALGORITHM_INDEX AlgId = KMF_ALGID_NONE;
KMF_DATA signature = {0, NULL};
KMF_OID *oid;
KMF_POLICY_RECORD *policy;
@@ -665,9 +678,7 @@ kmf_sign_data(KMF_HANDLE_T handle, int numattr,
ret = get_sigalg_from_cert(signer_cert, &AlgId);
if (ret != KMF_OK)
goto cleanup;
- else
- oid = x509_algid_to_algoid(AlgId);
-
+ oid = x509_algid_to_algoid(AlgId);
} else if (oid == NULL && ret == KMF_OK) {
/* AlgID was given by caller, convert it to OID */
oid = x509_algid_to_algoid(AlgId);
@@ -691,13 +702,15 @@ kmf_sign_data(KMF_HANDLE_T handle, int numattr,
/*
* For DSA, NSS returns an encoded signature. Decode the
- * signature as DSA signature should be 40-byte long.
+ * signature and expect a 40-byte DSA signature.
*/
if (plugin->type == KMF_KEYSTORE_NSS &&
- AlgId == KMF_ALGID_SHA1WithDSA) {
+ (AlgId == KMF_ALGID_SHA1WithDSA ||
+ AlgId == KMF_ALGID_SHA256WithDSA)) {
ret = DerDecodeDSASignature(output, &signature);
if (ret != KMF_OK)
goto cleanup;
+
output->Length = signature.Length;
(void) memcpy(output->Data, signature.Data, signature.Length);
}
@@ -712,7 +725,6 @@ cleanup:
if (signer_cert != NULL && sign_key_ptr != NULL)
kmf_free_kmf_key(handle, sign_key_ptr);
-
return (ret);
}
@@ -806,6 +818,8 @@ kmf_verify_data(KMF_HANDLE_T handle,
/* If the caller passed a signer cert instead of a key use it. */
if (signer_cert != NULL) {
+ KMF_X509_CERTIFICATE *SignerCert = NULL;
+
policy = handle->policy;
ret = check_key_usage(handle, signer_cert, KMF_KU_SIGN_DATA);
if (ret == KMF_ERR_EXTENSION_NOT_FOUND && policy->ku_bits == 0)
@@ -813,17 +827,35 @@ kmf_verify_data(KMF_HANDLE_T handle,
if (ret != KMF_OK)
return (ret);
- if (kstype == KMF_KEYSTORE_NSS)
- kstype = KMF_KEYSTORE_PK11TOKEN;
- plugin = FindPlugin(handle, kstype);
- if (plugin == NULL)
- return (KMF_ERR_PLUGIN_NOTFOUND);
- if (plugin->funclist->VerifyDataWithCert == NULL)
- return (KMF_ERR_FUNCTION_NOT_FOUND);
+ /* Decode the signer cert so we can get the SPKI data */
+ ret = DerDecodeSignedCertificate(signer_cert, &SignerCert);
+ if (ret != KMF_OK)
+ return (ret);
- CLEAR_ERROR(handle, ret);
- ret = plugin->funclist->VerifyDataWithCert(handle,
- sigAlg, indata, insig, signer_cert);
+ /* If no algorithm specified, use the certs signature alg */
+ if (sigAlg == KMF_ALGID_NONE)
+ sigAlg = x509_algoid_to_algid(CERT_ALG_OID(SignerCert));
+
+ if (sigAlg == KMF_ALGID_NONE) {
+ kmf_free_signed_cert(SignerCert);
+ free(SignerCert);
+ return (KMF_ERR_BAD_ALGORITHM);
+ }
+
+ /*
+ * Verify the data locally (i.e. using PKCS#11).
+ * The verify operation uses a public key and does not
+ * require access to a specific keystore. Save time
+ * (and code) by just using the frameworks implementation
+ * of the verify operation using crypto framework
+ * APIs.
+ */
+ ret = PKCS_VerifyData(handle, sigAlg,
+ &SignerCert->certificate.subjectPublicKeyInfo,
+ indata, insig);
+
+ kmf_free_signed_cert(SignerCert);
+ free(SignerCert);
} else {
/* Retrieve public key data from keystore */
plugin = FindPlugin(handle, kstype);
@@ -836,10 +868,9 @@ kmf_verify_data(KMF_HANDLE_T handle,
}
ret = DerDecodeSPKI(&derkey, &spki);
- if (ret == KMF_OK) {
+ if (ret == KMF_OK)
ret = PKCS_VerifyData(handle, sigAlg, &spki,
indata, insig);
- }
if (derkey.Data != NULL)
free(derkey.Data);
@@ -946,54 +977,6 @@ kmf_verify_cert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
}
/*
- * Utility routine for verifying generic data using a
- * certificate to derive the public key. This is
- * done in a specific plugin because there are situations
- * where we want to force this operation to happen in
- * a specific keystore.
- * For example:
- * libelfsign.so.1 verifies signatures on crypto libraries.
- * We must use pkcs11 functions to verify the pkcs11
- * plugins in order to keep the validation within the
- * Cryptographic Framework's FIPS-140 boundary. To avoid
- * a circular dependency, pksc11_softtoken.so.1 is
- * interposed by libkcfd.so.1 via kcfd, which prevents
- * libpkcs11.so.1's interfaces from being used when libkmf.so.1
- * is called from kcfd.
- */
-static KMF_RETURN
-plugin_verify_data_with_cert(KMF_HANDLE_T handle,
- KMF_KEYSTORE_TYPE kstype,
- KMF_ALGORITHM_INDEX algid,
- KMF_DATA *indata,
- KMF_DATA *insig,
- const KMF_DATA *SignerCert)
-{
- KMF_PLUGIN *plugin;
- KMF_RETURN ret = KMF_OK;
-
- /*
- * If NSS, use PKCS#11, we are not accessing the database(s),
- * we just prefer the "verify" operation from the crypto framework.
- */
- if (kstype == KMF_KEYSTORE_NSS)
- kstype = KMF_KEYSTORE_PK11TOKEN;
-
- plugin = FindPlugin(handle, kstype);
- if (plugin == NULL)
- return (KMF_ERR_PLUGIN_NOTFOUND);
-
- if (plugin->funclist->VerifyDataWithCert == NULL)
- return (KMF_ERR_FUNCTION_NOT_FOUND);
-
- CLEAR_ERROR(handle, ret);
- ret = (plugin->funclist->VerifyDataWithCert(handle,
- algid, indata, insig, (KMF_DATA *)SignerCert));
-
- return (ret);
-}
-
-/*
* Name: kmf_encrypt
*
* Description:
@@ -1078,8 +1061,15 @@ kmf_encrypt(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
algid = x509_algoid_to_algid(alg);
- /* DSA does not support encrypt */
- if (algid == KMF_ALGID_DSA || algid == KMF_ALGID_NONE) {
+ /* [EC]DSA does not support encrypt */
+ if (algid == KMF_ALGID_DSA ||
+ algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA ||
+ algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA ||
+ algid == KMF_ALGID_NONE) {
kmf_free_signed_cert(x509cert);
free(x509cert);
return (KMF_ERR_BAD_ALGORITHM);
@@ -1186,8 +1176,9 @@ kmf_decrypt(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
AlgorithmId = x509_algoid_to_algid((KMF_OID *)
&spki_ptr->algorithm.algorithm);
- /* DSA does not support decrypt */
- if (AlgorithmId == KMF_ALGID_DSA) {
+ /* [EC]DSA does not support decrypt */
+ if (AlgorithmId == KMF_ALGID_DSA ||
+ AlgorithmId == KMF_ALGID_ECDSA) {
ret = KMF_ERR_BAD_ALGORITHM;
goto cleanup;
}
@@ -2991,12 +2982,26 @@ sign_cert(KMF_HANDLE_T handle,
algid = x509_algoid_to_algid(signature_oid);
- /*
- * For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded
- * signature. So we must encode the signature correctly.
- */
- if (algid == KMF_ALGID_SHA1WithDSA) {
+ if (algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
+ /* ASN.1 encode ECDSA signature */
+ KMF_DATA signature;
+
+ ret = DerEncodeECDSASignature(&signed_data, &signature);
+ kmf_free_data(&signed_data);
+
+ if (ret != KMF_OK)
+ goto cleanup;
+ subj_cert->signature.encrypted = signature;
+ } else if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA) {
+ /*
+ * For DSA, kmf_sign_data() returns a 40-byte
+ * signature. We must encode the signature correctly.
+ */
KMF_DATA signature;
ret = DerEncodeDSASignature(&signed_data, &signature);
@@ -3068,10 +3073,18 @@ verify_cert_with_key(KMF_HANDLE_T handle,
if (algid == KMF_ALGID_NONE)
return (KMF_ERR_BAD_ALGORITHM);
- if (algid == KMF_ALGID_SHA1WithDSA) {
+ if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA) {
ret = DerDecodeDSASignature(&signed_data, &signature);
if (ret != KMF_OK)
goto cleanup;
+ } else if (algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
+ ret = DerDecodeECDSASignature(&signed_data, &signature);
+ if (ret != KMF_OK)
+ goto cleanup;
} else {
signature.Data = signed_data.Data;
signature.Length = signed_data.Length;
@@ -3091,7 +3104,12 @@ cleanup:
kmf_free_signed_cert(signed_cert);
free(signed_cert);
}
- if (algid == KMF_ALGID_SHA1WithDSA) {
+ if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA ||
+ algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
free(signature.Data);
}
@@ -3149,27 +3167,39 @@ verify_cert_with_cert(KMF_HANDLE_T handle,
/* Decode the to-be-verified cert so we know what algorithm to use */
ret = DerDecodeSignedCertificate(CertToBeVerifiedData,
&ToBeVerifiedCert);
-
if (ret != KMF_OK)
goto cleanup;
algid = x509_algoid_to_algid(CERT_SIG_OID(ToBeVerifiedCert));
- if (algid == KMF_ALGID_SHA1WithDSA) {
+ if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA) {
ret = DerDecodeDSASignature(&signed_data, &signature);
if (ret != KMF_OK)
goto cleanup;
+ } else if (algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
+ ret = DerDecodeECDSASignature(&signed_data, &signature);
+ if (ret != KMF_OK)
+ goto cleanup;
} else {
signature.Data = signed_data.Data;
signature.Length = signed_data.Length;
}
+ ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
+ if (ret != KMF_OK)
+ goto cleanup;
+
/*
* Force use of PKCS11 API for kcfd/libelfsign. This is
* required for the Cryptographic Framework's FIPS-140 boundary.
*/
- ret = plugin_verify_data_with_cert(handle, KMF_KEYSTORE_PK11TOKEN,
- algid, &data_to_verify, &signature, SignerCertData);
+ ret = PKCS_VerifyData(handle, algid,
+ &SignerCert->certificate.subjectPublicKeyInfo,
+ &data_to_verify, &signature);
cleanup:
kmf_free_data(&data_to_verify);
@@ -3185,7 +3215,12 @@ cleanup:
free(ToBeVerifiedCert);
}
- if (algid == KMF_ALGID_SHA1WithDSA) {
+ if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA ||
+ algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
free(signature.Data);
}
diff --git a/usr/src/lib/libkmf/libkmf/common/csrcrlop.c b/usr/src/lib/libkmf/libkmf/common/csrcrlop.c
index 6c0f363157..165fce83d4 100644
--- a/usr/src/lib/libkmf/libkmf/common/csrcrlop.c
+++ b/usr/src/lib/libkmf/libkmf/common/csrcrlop.c
@@ -369,6 +369,7 @@ sign_csr(KMF_HANDLE_T handle,
KMF_DATA signed_data = {0, NULL};
KMF_RETURN ret = KMF_OK;
KMF_ATTRIBUTE attlist[5];
+ KMF_ALGORITHM_INDEX algid;
int i = 0;
if (!SignedCsr)
@@ -425,7 +426,29 @@ sign_csr(KMF_HANDLE_T handle,
if (ret)
goto cleanup;
- subj_csr.signature.encrypted = signed_data;
+ algid = x509_algoid_to_algid(&algo->algorithm);
+ if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA ||
+ algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
+ /*
+ * For DSA and ECDSA, we must encode the
+ * signature correctly.
+ */
+ KMF_DATA signature;
+
+ ret = DerEncodeDSASignature(&signed_data, &signature);
+ kmf_free_data(&signed_data);
+
+ if (ret != KMF_OK)
+ goto cleanup;
+
+ subj_csr.signature.encrypted = signature;
+ } else {
+ subj_csr.signature.encrypted = signed_data;
+ }
/* Now, re-encode the CSR with the new signature */
ret = DerEncodeSignedCsr(&subj_csr, SignedCsr);
@@ -573,12 +596,43 @@ kmf_verify_csr(KMF_HANDLE_T handle, int numattr,
x509alg = &csrdata->signature.algorithmIdentifier;
algid = x509_algoid_to_algid(&x509alg->algorithm);
+ if (algid == KMF_ALGID_SHA1WithDSA ||
+ algid == KMF_ALGID_SHA256WithDSA) {
+ /* Decode the DSA signature before verifying it */
+ KMF_DATA signature;
+ rv = DerDecodeDSASignature(&csrdata->signature.encrypted,
+ &signature);
+ if (rv != KMF_OK)
+ goto end;
+
+ rv = PKCS_VerifyData(handle, algid,
+ &csrdata->csr.subjectPublicKeyInfo,
+ &rawcsr, &signature);
+
+ kmf_free_data(&signature);
+ } else if (algid == KMF_ALGID_SHA1WithECDSA ||
+ algid == KMF_ALGID_SHA256WithECDSA ||
+ algid == KMF_ALGID_SHA384WithECDSA ||
+ algid == KMF_ALGID_SHA512WithECDSA) {
+ KMF_DATA signature;
+ rv = DerDecodeECDSASignature(&csrdata->signature.encrypted,
+ &signature);
+ if (rv != KMF_OK)
+ goto end;
- rv = PKCS_VerifyData(handle, algid,
- &csrdata->csr.subjectPublicKeyInfo,
- &rawcsr,
- &csrdata->signature.encrypted);
+ rv = PKCS_VerifyData(handle, algid,
+ &csrdata->csr.subjectPublicKeyInfo,
+ &rawcsr, &signature);
+ kmf_free_data(&signature);
+ } else {
+ rv = PKCS_VerifyData(handle, algid,
+ &csrdata->csr.subjectPublicKeyInfo,
+ &rawcsr,
+ &csrdata->signature.encrypted);
+ }
+
+end:
kmf_free_data(&rawcsr);
return (rv);
}
@@ -842,50 +896,3 @@ kmf_is_crl_file(KMF_HANDLE_T handle, char *filename, KMF_ENCODE_FORMAT *pformat)
return (IsCRLFileFn(handle, filename, pformat));
}
-
-/*
- * Phase 1 APIs still needed to maintain compat with elfsign.
- */
-KMF_RETURN
-KMF_CreateCSRFile(KMF_DATA *csrdata, KMF_ENCODE_FORMAT format,
- char *csrfile)
-{
- return (kmf_create_csr_file(csrdata, format, csrfile));
-}
-
-KMF_RETURN
-KMF_SetCSRPubKey(KMF_HANDLE_T handle,
- KMF_KEY_HANDLE *KMFKey,
- KMF_CSR_DATA *Csr)
-{
- return (kmf_set_csr_pubkey(handle, KMFKey, Csr));
-}
-
-KMF_RETURN
-KMF_SetCSRVersion(KMF_CSR_DATA *CsrData, uint32_t version)
-{
- return (kmf_set_csr_version(CsrData, version));
-}
-
-KMF_RETURN
-KMF_SetCSRSignatureAlgorithm(KMF_CSR_DATA *CsrData,
- KMF_ALGORITHM_INDEX sigAlg)
-{
- return (kmf_set_csr_sig_alg(CsrData, sigAlg));
-}
-
-KMF_RETURN
-KMF_SignCSR(KMF_HANDLE_T handle,
- const KMF_CSR_DATA *tbsCsr,
- KMF_KEY_HANDLE *Signkey,
- KMF_DATA *SignedCsr)
-{
- return (kmf_sign_csr(handle, tbsCsr, Signkey, SignedCsr));
-}
-
-KMF_RETURN
-KMF_SetCSRSubjectName(KMF_CSR_DATA *CsrData,
- KMF_X509_NAME *subject_name_ptr)
-{
- return (kmf_set_csr_subject(CsrData, subject_name_ptr));
-}
diff --git a/usr/src/lib/libkmf/libkmf/common/kmfoids.c b/usr/src/lib/libkmf/libkmf/common/kmfoids.c
index a29ea9ee31..bc1eb3bf1a 100644
--- a/usr/src/lib/libkmf/libkmf/common/kmfoids.c
+++ b/usr/src/lib/libkmf/libkmf/common/kmfoids.c
@@ -1,13 +1,11 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright(c) 1995-2000 Intel Corporation. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <kmfapi.h>
/* From X.520 */
@@ -363,6 +361,9 @@ OID_RSAEncryption[] = { OID_PKCS_1, 1 },
OID_MD2WithRSA[] = { OID_PKCS_1, 2 },
OID_MD5WithRSA[] = { OID_PKCS_1, 4 },
OID_SHA1WithRSA[] = { OID_PKCS_1, 5 },
+OID_SHA256WithRSA[] = { OID_PKCS_1, 11 },
+OID_SHA384WithRSA[] = { OID_PKCS_1, 12 },
+OID_SHA512WithRSA[] = { OID_PKCS_1, 13 },
OID_X9CM_DSA[] = { OID_X9CM_X9ALGORITHM, 1 },
OID_X9CM_DSAWithSHA1[] = { OID_X9CM_X9ALGORITHM, 3};
@@ -373,9 +374,10 @@ KMFOID_DSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSA},
KMFOID_MD5WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD5WithRSA},
KMFOID_MD2WithRSA = {OID_PKCS_1_LENGTH+1, OID_MD2WithRSA},
KMFOID_SHA1WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA1WithRSA},
-KMFOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSAWithSHA1},
-KMFOID_OIW_DSAWithSHA1 = {OID_OIW_ALGORITHM_LENGTH+1,
- OID_OIW_DSAWithSHA1},
+KMFOID_SHA256WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA256WithRSA},
+KMFOID_SHA384WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA384WithRSA},
+KMFOID_SHA512WithRSA = {OID_PKCS_1_LENGTH+1, OID_SHA512WithRSA},
+KMFOID_SHA1WithDSA = {OID_OIW_ALGORITHM_LENGTH+1, OID_OIW_DSAWithSHA1},
KMFOID_X9CM_DSA = {OID_X9CM_X9ALGORITHM_LENGTH+1, OID_X9CM_DSA},
KMFOID_X9CM_DSAWithSHA1 = {OID_X9CM_X9ALGORITHM_LENGTH+1,
OID_X9CM_DSAWithSHA1};
@@ -400,3 +402,179 @@ KMFOID_MS_KP_SCLogon = {OID_MS_KP_SC_LOGON_LENGTH,
OID_pkinit_kp_sc_logon},
KMFOID_MS_KP_SCLogon_UPN = {OID_MS_KP_SC_LOGON_UPN_LENGTH,
OID_pkinit_san_upn};
+
+/*
+ * MD5
+ * iso(1) member-body(2) us(840) rsadsi(113549)
+ * digestAlgorithm(2) 5
+ */
+#define RSADSI 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d
+#define OID_id_md5 RSADSI, 0x02, 0x05
+
+/*
+ * SHA2 OIDs
+ */
+#define NIST_ALG 96, 134, 72, 1, 101, 3, 4
+#define NIST_HASH NIST_ALG, 2
+#define OID_id_sha256 NIST_HASH, 1
+#define OID_id_sha384 NIST_HASH, 2
+#define OID_id_sha512 NIST_HASH, 3
+#define OID_id_sha224 NIST_HASH, 4
+
+#define OID_id_dsa_with_sha224 NIST_ALG, 3, 1
+#define OID_id_dsa_with_sha256 NIST_ALG, 3, 2
+
+/*
+ * For ECC support.
+ */
+#define CERTICOM_OID 0x2b, 0x81, 0x04
+#define SECG_OID CERTICOM_OID, 0x00
+
+#define ANSI_X962_OID 0x2a, 0x86, 0x48, 0xce, 0x3d
+#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03
+#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
+#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01
+
+#define ANSI_X962_SIG_OID ANSI_X962_OID, 0x04
+#define OID_ecdsa_with_sha224 ANSI_X962_SIG_OID, 3, 1
+#define OID_ecdsa_with_sha256 ANSI_X962_SIG_OID, 3, 2
+#define OID_ecdsa_with_sha384 ANSI_X962_SIG_OID, 3, 3
+#define OID_ecdsa_with_sha512 ANSI_X962_SIG_OID, 3, 4
+
+static uint8_t
+OID_secp112r1[] = { 0x6, 0x5, SECG_OID, 0x06 },
+OID_secp112r2[] = { 0x6, 0x5, SECG_OID, 0x07 },
+OID_secp128r1[] = { 0x6, 0x5, SECG_OID, 0x1c },
+OID_secp128r2[] = { 0x6, 0x5, SECG_OID, 0x1d },
+OID_secp160k1[] = { 0x6, 0x5, SECG_OID, 0x09 },
+OID_secp160r1[] = { 0x6, 0x5, SECG_OID, 0x08 },
+OID_secp160r2[] = { 0x6, 0x5, SECG_OID, 0x1e },
+OID_secp192k1[] = { 0x6, 0x5, SECG_OID, 0x1f },
+OID_secp224k1[] = { 0x6, 0x5, SECG_OID, 0x20 },
+OID_secp224r1[] = { 0x6, 0x5, SECG_OID, 0x21 },
+OID_secp256k1[] = { 0x6, 0x5, SECG_OID, 0x0a },
+OID_secp384r1[] = { 0x6, 0x5, SECG_OID, 0x22 },
+OID_secp521r1[] = { 0x6, 0x5, SECG_OID, 0x23 },
+OID_sect113r1[] = { 0x6, 0x5, SECG_OID, 0x04 },
+OID_sect113r2[] = { 0x6, 0x5, SECG_OID, 0x05 },
+OID_sect131r1[] = { 0x6, 0x5, SECG_OID, 0x16 },
+OID_sect131r2[] = { 0x6, 0x5, SECG_OID, 0x17 },
+OID_sect163k1[] = { 0x6, 0x5, SECG_OID, 0x01 },
+OID_sect163r1[] = { 0x6, 0x5, SECG_OID, 0x02 },
+OID_sect163r2[] = { 0x6, 0x5, SECG_OID, 0x0f },
+OID_sect193r1[] = { 0x6, 0x5, SECG_OID, 0x18 },
+OID_sect193r2[] = { 0x6, 0x5, SECG_OID, 0x19 },
+OID_sect233k1[] = { 0x6, 0x5, SECG_OID, 0x1a },
+OID_sect233r1[] = { 0x6, 0x5, SECG_OID, 0x1b },
+OID_sect239k1[] = { 0x6, 0x5, SECG_OID, 0x03 },
+OID_sect283k1[] = { 0x6, 0x5, SECG_OID, 0x10 },
+OID_sect283r1[] = { 0x6, 0x5, SECG_OID, 0x11 },
+OID_sect409k1[] = { 0x6, 0x5, SECG_OID, 0x24 },
+OID_sect409r1[] = { 0x6, 0x5, SECG_OID, 0x25 },
+OID_sect571k1[] = { 0x6, 0x5, SECG_OID, 0x26 },
+OID_sect571r1[] = { 0x6, 0x5, SECG_OID, 0x27 },
+OID_c2pnb163v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x01 },
+OID_c2pnb163v2[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x02 },
+OID_c2pnb163v3[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x03 },
+OID_c2pnb176v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x04 },
+OID_c2tnb191v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x05 },
+OID_c2tnb191v2[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x06 },
+OID_c2tnb191v3[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x07 },
+OID_c2pnb208w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0a },
+OID_c2tnb239v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0b },
+OID_c2tnb239v2[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0c },
+OID_c2tnb239v3[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x0d },
+OID_c2pnb272w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x10 },
+OID_c2pnb304w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x11 },
+OID_c2tnb359v1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x12 },
+OID_c2pnb368w1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x13 },
+OID_c2tnb431r1[] = { 0x6, 0x8, ANSI_X962_GF2m_OID, 0x14 },
+
+OID_prime192v2[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x02 },
+OID_prime192v3[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x03 },
+
+OID_secp192r1[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x01 },
+OID_secp256r1[] = { 0x6, 0x8, ANSI_X962_GFp_OID, 0x07 };
+
+const KMF_OID
+KMFOID_ECC_secp112r1 = {sizeof (OID_secp112r1), OID_secp112r1},
+KMFOID_ECC_secp112r2 = {sizeof (OID_secp112r2), OID_secp112r2},
+KMFOID_ECC_secp128r1 = {sizeof (OID_secp128r1), OID_secp128r1},
+KMFOID_ECC_secp128r2 = {sizeof (OID_secp128r2), OID_secp128r2},
+KMFOID_ECC_secp160k1 = {sizeof (OID_secp160k1), OID_secp160k1},
+KMFOID_ECC_secp160r1 = {sizeof (OID_secp160r1), OID_secp160r1},
+KMFOID_ECC_secp160r2 = {sizeof (OID_secp160r2), OID_secp160r2},
+KMFOID_ECC_secp192k1 = {sizeof (OID_secp192k1), OID_secp192k1},
+KMFOID_ECC_secp224k1 = {sizeof (OID_secp224k1), OID_secp224k1},
+KMFOID_ECC_secp224r1 = {sizeof (OID_secp224r1), OID_secp224r1},
+KMFOID_ECC_secp256k1 = {sizeof (OID_secp256k1), OID_secp256k1},
+KMFOID_ECC_secp384r1 = {sizeof (OID_secp384r1), OID_secp384r1},
+KMFOID_ECC_secp521r1 = {sizeof (OID_secp521r1), OID_secp521r1},
+KMFOID_ECC_sect113r1 = {sizeof (OID_sect113r1), OID_sect113r1},
+KMFOID_ECC_sect113r2 = {sizeof (OID_sect113r2), OID_sect113r2},
+KMFOID_ECC_sect131r1 = {sizeof (OID_sect131r1), OID_sect131r1},
+KMFOID_ECC_sect131r2 = {sizeof (OID_sect131r2), OID_sect131r2},
+KMFOID_ECC_sect163k1 = {sizeof (OID_sect163k1), OID_sect163k1},
+KMFOID_ECC_sect163r1 = {sizeof (OID_sect163r1), OID_sect163r1},
+KMFOID_ECC_sect163r2 = {sizeof (OID_sect163r2), OID_sect163r2},
+KMFOID_ECC_sect193r1 = {sizeof (OID_sect193r1), OID_sect193r1},
+KMFOID_ECC_sect193r2 = {sizeof (OID_sect193r2), OID_sect193r2},
+KMFOID_ECC_sect233k1 = {sizeof (OID_sect233k1), OID_sect233k1},
+KMFOID_ECC_sect233r1 = {sizeof (OID_sect233r1), OID_sect233r1},
+KMFOID_ECC_sect239k1 = {sizeof (OID_sect239k1), OID_sect239k1},
+KMFOID_ECC_sect283k1 = {sizeof (OID_sect283k1), OID_sect283k1},
+KMFOID_ECC_sect283r1 = {sizeof (OID_sect283r1), OID_sect283r1},
+KMFOID_ECC_sect409k1 = {sizeof (OID_sect409k1), OID_sect409k1},
+KMFOID_ECC_sect409r1 = {sizeof (OID_sect409r1), OID_sect409r1},
+KMFOID_ECC_sect571k1 = {sizeof (OID_sect571k1), OID_sect571k1},
+KMFOID_ECC_sect571r1 = {sizeof (OID_sect571r1), OID_sect571r1},
+KMFOID_ECC_c2pnb163v1 = {sizeof (OID_c2pnb163v1), OID_c2pnb163v1},
+KMFOID_ECC_c2pnb163v2 = {sizeof (OID_c2pnb163v2), OID_c2pnb163v2},
+KMFOID_ECC_c2pnb163v3 = {sizeof (OID_c2pnb163v3), OID_c2pnb163v3},
+KMFOID_ECC_c2pnb176v1 = {sizeof (OID_c2pnb176v1), OID_c2pnb176v1},
+KMFOID_ECC_c2tnb191v1 = {sizeof (OID_c2tnb191v1), OID_c2tnb191v1},
+KMFOID_ECC_c2tnb191v2 = {sizeof (OID_c2tnb191v2), OID_c2tnb191v2},
+KMFOID_ECC_c2tnb191v3 = {sizeof (OID_c2tnb191v3), OID_c2tnb191v3},
+KMFOID_ECC_c2pnb208w1 = {sizeof (OID_c2pnb208w1), OID_c2pnb208w1},
+KMFOID_ECC_c2tnb239v1 = {sizeof (OID_c2tnb239v1), OID_c2tnb239v1},
+KMFOID_ECC_c2tnb239v2 = {sizeof (OID_c2tnb239v2), OID_c2tnb239v2},
+KMFOID_ECC_c2tnb239v3 = {sizeof (OID_c2tnb239v3), OID_c2tnb239v3},
+KMFOID_ECC_c2pnb272w1 = {sizeof (OID_c2pnb272w1), OID_c2pnb272w1},
+KMFOID_ECC_c2pnb304w1 = {sizeof (OID_c2pnb304w1), OID_c2pnb304w1},
+KMFOID_ECC_c2tnb359v1 = {sizeof (OID_c2tnb359v1), OID_c2tnb359v1},
+KMFOID_ECC_c2pnb368w1 = {sizeof (OID_c2pnb368w1), OID_c2pnb368w1},
+KMFOID_ECC_c2tnb431r1 = {sizeof (OID_c2tnb431r1), OID_c2tnb431r1},
+KMFOID_ECC_prime192v2 = {sizeof (OID_prime192v2), OID_prime192v2},
+KMFOID_ECC_prime192v3 = {sizeof (OID_prime192v3), OID_prime192v3},
+KMFOID_ECC_secp192r1 = {sizeof (OID_secp192r1), OID_secp192r1},
+KMFOID_ECC_secp256r1 = {sizeof (OID_secp256r1), OID_secp256r1};
+
+static uint8_t
+OID_EC_PUBLIC_KEY[] = {ANSI_X962_OID, 0x02, 0x01},
+OID_ECDSA_SHA1[] = {ANSI_X962_OID, 0x04, 0x01},
+OID_ECDSA_SHA224[] = {ANSI_X962_OID, 0x04, 0x03, 0x01},
+OID_ECDSA_SHA256[] = {ANSI_X962_OID, 0x04, 0x03, 0x02},
+OID_ECDSA_SHA384[] = {ANSI_X962_OID, 0x04, 0x03, 0x03},
+OID_ECDSA_SHA512[] = {ANSI_X962_OID, 0x04, 0x03, 0x04},
+OID_DSA_SHA224[] = {OID_id_dsa_with_sha224},
+OID_DSA_SHA256[] = {OID_id_dsa_with_sha256},
+OID_SHA224[] = {OID_id_sha224},
+OID_SHA256[] = {OID_id_sha256},
+OID_SHA384[] = {OID_id_sha384},
+OID_SHA512[] = {OID_id_sha512},
+OID_MD5[] = {OID_id_md5};
+
+const KMF_OID
+KMFOID_EC_PUBLIC_KEY = { sizeof (OID_EC_PUBLIC_KEY), OID_EC_PUBLIC_KEY},
+KMFOID_SHA1WithECDSA = { sizeof (OID_ECDSA_SHA1), OID_ECDSA_SHA1},
+KMFOID_SHA224WithECDSA = { sizeof (OID_ECDSA_SHA224), OID_ECDSA_SHA224},
+KMFOID_SHA256WithECDSA = { sizeof (OID_ECDSA_SHA256), OID_ECDSA_SHA256},
+KMFOID_SHA384WithECDSA = { sizeof (OID_ECDSA_SHA384), OID_ECDSA_SHA384},
+KMFOID_SHA512WithECDSA = { sizeof (OID_ECDSA_SHA512), OID_ECDSA_SHA512},
+KMFOID_SHA224WithDSA = { sizeof (OID_DSA_SHA224), OID_DSA_SHA224},
+KMFOID_SHA256WithDSA = { sizeof (OID_DSA_SHA256), OID_DSA_SHA256},
+KMFOID_SHA224 = { sizeof (OID_SHA224), OID_SHA224},
+KMFOID_SHA256 = { sizeof (OID_SHA256), OID_SHA256},
+KMFOID_SHA384 = { sizeof (OID_SHA384), OID_SHA384},
+KMFOID_SHA512 = { sizeof (OID_SHA512), OID_SHA512},
+KMFOID_MD5 = { sizeof (OID_MD5), OID_MD5};
diff --git a/usr/src/lib/libkmf/libkmf/common/mapfile-vers b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
index f1d5b722df..d221e5b79d 100644
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers
@@ -75,6 +75,58 @@ SUNW_1.1 {
KMFOID_Description;
KMFOID_DestinationIndicator;
KMFOID_DistinguishedName;
+ KMFOID_EC_PUBLIC_KEY;
+ KMFOID_ECC_c2pnb163v1;
+ KMFOID_ECC_c2pnb163v2;
+ KMFOID_ECC_c2pnb163v3;
+ KMFOID_ECC_c2pnb176v1;
+ KMFOID_ECC_c2pnb208w1;
+ KMFOID_ECC_c2pnb272w1;
+ KMFOID_ECC_c2pnb304w1;
+ KMFOID_ECC_c2pnb368w1;
+ KMFOID_ECC_c2tnb191v1;
+ KMFOID_ECC_c2tnb191v2;
+ KMFOID_ECC_c2tnb191v3;
+ KMFOID_ECC_c2tnb239v1;
+ KMFOID_ECC_c2tnb239v2;
+ KMFOID_ECC_c2tnb239v3;
+ KMFOID_ECC_c2tnb359v1;
+ KMFOID_ECC_c2tnb431r1;
+ KMFOID_ECC_prime192v2;
+ KMFOID_ECC_prime192v3;
+ KMFOID_ECC_secp112r1;
+ KMFOID_ECC_secp112r2;
+ KMFOID_ECC_secp128r1;
+ KMFOID_ECC_secp128r2;
+ KMFOID_ECC_secp160k1;
+ KMFOID_ECC_secp160r1;
+ KMFOID_ECC_secp160r2;
+ KMFOID_ECC_secp192k1;
+ KMFOID_ECC_secp224k1;
+ KMFOID_ECC_secp224r1;
+ KMFOID_ECC_secp256k1;
+ KMFOID_ECC_secp384r1;
+ KMFOID_ECC_secp521r1;
+ KMFOID_ECC_sect113r1;
+ KMFOID_ECC_sect113r2;
+ KMFOID_ECC_sect131r1;
+ KMFOID_ECC_sect131r2;
+ KMFOID_ECC_sect163k1;
+ KMFOID_ECC_sect163r1;
+ KMFOID_ECC_sect163r2;
+ KMFOID_ECC_sect193r1;
+ KMFOID_ECC_sect193r2;
+ KMFOID_ECC_sect233k1;
+ KMFOID_ECC_sect233r1;
+ KMFOID_ECC_sect239k1;
+ KMFOID_ECC_sect283k1;
+ KMFOID_ECC_sect283r1;
+ KMFOID_ECC_sect409k1;
+ KMFOID_ECC_sect409r1;
+ KMFOID_ECC_sect571k1;
+ KMFOID_ECC_sect571r1;
+ KMFOID_ECC_secp192r1;
+ KMFOID_ECC_secp256r1;
KMFOID_EmailAddress;
KMFOID_EnhancedSearchGuide;
KMFOID_ExtendedCertificateAttributes;
@@ -95,6 +147,7 @@ SUNW_1.1 {
KMFOID_KnowledgeInformation;
KMFOID_LocalityName;
KMFOID_MD2WithRSA;
+ KMFOID_MD5;
KMFOID_MD5WithRSA;
KMFOID_Member;
KMFOID_MessageDigest;
@@ -102,7 +155,6 @@ SUNW_1.1 {
KMFOID_MS_KP_SCLogon_UPN;
KMFOID_Name;
KMFOID_NameConstraints;
- KMFOID_OIW_DSAWithSHA1;
KMFOID_ObjectClass;
KMFOID_OrganizationName;
KMFOID_OrganizationalUnitName;
@@ -139,7 +191,21 @@ SUNW_1.1 {
KMFOID_RoleOccupant;
KMFOID_SHA1;
KMFOID_SHA1WithDSA;
+ KMFOID_SHA1WithECDSA;
KMFOID_SHA1WithRSA;
+ KMFOID_SHA224;
+ KMFOID_SHA256;
+ KMFOID_SHA384;
+ KMFOID_SHA512;
+ KMFOID_SHA224WithDSA;
+ KMFOID_SHA256WithDSA;
+ KMFOID_SHA224WithECDSA;
+ KMFOID_SHA256WithECDSA;
+ KMFOID_SHA256WithRSA;
+ KMFOID_SHA384WithECDSA;
+ KMFOID_SHA384WithRSA;
+ KMFOID_SHA512WithECDSA;
+ KMFOID_SHA512WithRSA;
KMFOID_SearchGuide;
KMFOID_SeeAlso;
KMFOID_SerialNumber;
@@ -323,10 +389,12 @@ SUNWprivate_1.1 {
free_entrylist;
get_entrylist;
kmf_select_token;
+ kmf_create_pk11_session;
parsePolicyElement;
- PKCS_AcquirePublicKeyHandle;
- PKCS_GetDefaultSignatureMode;
- pkcs_get_alg_map;
+ PKCS_VerifyData;
+ PKCS_DigestData;
+ PKCS_EncryptData;
+ get_pk11_data;
x509_algid_to_algoid;
x509_algoid_to_algid;
local:
diff --git a/usr/src/lib/libkmf/libkmf/common/pk11keys.c b/usr/src/lib/libkmf/libkmf/common/pk11keys.c
index 5a6e945009..df2cd0f8df 100644
--- a/usr/src/lib/libkmf/libkmf/common/pk11keys.c
+++ b/usr/src/lib/libkmf/libkmf/common/pk11keys.c
@@ -1,26 +1,91 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <kmfapiP.h>
#include <sha1.h>
#include <security/cryptoki.h>
-#include <algorithm.h>
#include <ber_der.h>
#define MAX_PUBLIC_KEY_TEMPLATES (20)
#define MAX_PRIVATE_KEY_TEMPLATES (24)
#define MAX_SECRET_KEY_TEMPLATES (24)
-static KMF_RETURN
-create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
+typedef struct
+{
+ KMF_ALGORITHM_INDEX kmfAlgorithmId;
+ CK_KEY_TYPE ckKeyType;
+ CK_MECHANISM_TYPE signmech;
+ CK_MECHANISM_TYPE vfymech;
+ CK_MECHANISM_TYPE hashmech;
+} ALG_INFO;
+
+static const ALG_INFO alg_info_map[] = {
+ { KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, NULL},
+ { KMF_ALGID_DSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
+ { KMF_ALGID_ECDSA, CKK_EC, CKM_ECDSA, CKM_ECDSA, CKM_SHA_1 },
+ { KMF_ALGID_SHA1WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 },
+ { KMF_ALGID_SHA256WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA256 },
+
+ /*
+ * For RSA, the verify can be done using a single mechanism,
+ * but signing must be done separately because not all hardware
+ * tokens support the combined hash+key operations.
+ */
+ { KMF_ALGID_MD5WithRSA, CKK_RSA, CKM_RSA_PKCS,
+ CKM_MD5_RSA_PKCS, CKM_MD5},
+ { KMF_ALGID_SHA1WithRSA, CKK_RSA, CKM_RSA_PKCS,
+ CKM_SHA1_RSA_PKCS, CKM_SHA_1},
+ { KMF_ALGID_SHA256WithRSA, CKK_RSA, CKM_RSA_PKCS,
+ CKM_SHA256_RSA_PKCS, CKM_SHA256},
+ { KMF_ALGID_SHA384WithRSA, CKK_RSA, CKM_RSA_PKCS,
+ CKM_SHA384_RSA_PKCS, CKM_SHA384},
+ { KMF_ALGID_SHA512WithRSA, CKK_RSA, CKM_RSA_PKCS,
+ CKM_SHA512_RSA_PKCS, CKM_SHA512},
+ { KMF_ALGID_SHA1WithECDSA, CKK_EC, CKM_ECDSA,
+ CKM_ECDSA, CKM_SHA_1},
+ { KMF_ALGID_SHA256WithECDSA, CKK_EC, CKM_ECDSA,
+ CKM_ECDSA, CKM_SHA256},
+ { KMF_ALGID_SHA384WithECDSA, CKK_EC, CKM_ECDSA,
+ CKM_ECDSA, CKM_SHA384},
+ { KMF_ALGID_SHA512WithECDSA, CKK_EC, CKM_ECDSA,
+ CKM_ECDSA, CKM_SHA512}
+};
+
+KMF_RETURN
+get_pk11_data(KMF_ALGORITHM_INDEX AlgId,
+ CK_KEY_TYPE *keytype, CK_MECHANISM_TYPE *signmech,
+ CK_MECHANISM_TYPE *hashmech, boolean_t vfy)
+{
+ uint32_t uIndex;
+ uint32_t uMapSize =
+ sizeof (alg_info_map) / sizeof (ALG_INFO);
+
+ for (uIndex = 0; uIndex < uMapSize; uIndex++) {
+ if (alg_info_map[uIndex].kmfAlgorithmId == AlgId) {
+ if (keytype)
+ *keytype = alg_info_map[uIndex].ckKeyType;
+ if (hashmech)
+ *hashmech = alg_info_map[uIndex].hashmech;
+ if (signmech)
+ *signmech =
+ (vfy ? alg_info_map[uIndex].vfymech :
+ alg_info_map[uIndex].signmech);
+ return (KMF_OK);
+ }
+ }
+ /* no match */
+ return (KMF_ERR_BAD_ALGORITHM);
+}
+
+KMF_RETURN
+kmf_create_pk11_session(CK_SESSION_HANDLE *sessionp,
+ CK_MECHANISM_TYPE wanted_mech,
CK_FLAGS wanted_flags)
{
CK_RV rv;
@@ -56,7 +121,8 @@ create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
for (i = 0; i < pulCount; i++) {
rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
- if (rv == CKR_OK && (info.flags & wanted_flags))
+ if (rv == CKR_OK &&
+ (info.flags & wanted_flags) == wanted_flags)
break;
}
if (i < pulCount) {
@@ -173,7 +239,7 @@ PKCS_CreatePublicKey(
}
/* Fill in the common key attributes */
- if (!pkcs_algid_to_keytype(AlgorithmId, &ckKeyType)) {
+ if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) {
goto cleanup;
}
if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
@@ -210,6 +276,7 @@ PKCS_CreatePublicKey(
MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS,
(CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data,
(CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) ||
+
!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT,
(CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data,
@@ -239,6 +306,20 @@ PKCS_CreatePublicKey(
goto cleanup;
}
break;
+ case CKK_EC:
+ if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT,
+ (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data,
+ (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) ||
+
+ !PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
+ MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS,
+ (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data,
+ (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) {
+ mrReturn = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+ break;
default:
mrReturn = KMF_ERR_BAD_PARAMETER;
}
@@ -274,18 +355,16 @@ cleanup:
* - Public Key with label:
* Attempts to find a public key with the corresponding label.
*/
-KMF_RETURN
+static KMF_RETURN
PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
const KMF_X509_SPKI *pKey,
CK_KEY_TYPE ckRequestedKeyType,
- CK_OBJECT_HANDLE *pckKeyHandle,
- KMF_BOOL *pbTemporary)
+ CK_OBJECT_HANDLE *pckKeyHandle)
{
KMF_RETURN mrReturn = KMF_OK;
-
/* Key searching variables */
- CK_OBJECT_HANDLE ckKeyHandle;
+ CK_OBJECT_HANDLE ckKeyHandle = 0;
CK_OBJECT_CLASS ckObjClass;
CK_KEY_TYPE ckKeyType;
CK_ATTRIBUTE ckTemplate[3];
@@ -299,8 +378,6 @@ PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
if (mrReturn != KMF_OK)
return (mrReturn);
- *pbTemporary = KMF_TRUE;
-
/* Fetch the key class and algorithm from the object */
ckNumTemplates = 0;
if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
@@ -309,21 +386,20 @@ PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
!PKCS_AddTemplate(ckTemplate, &ckNumTemplates,
ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType,
sizeof (ckKeyType))) {
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
return (KMF_ERR_INTERNAL);
}
ckRv = C_GetAttributeValue(ckSession, ckKeyHandle,
ckTemplate, ckNumTemplates);
if (ckRv != CKR_OK) {
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
return (ckRv);
}
/* Make sure the results match the expected values */
if ((ckKeyType != ckRequestedKeyType) ||
(ckObjClass != CKO_PUBLIC_KEY)) {
- if (*pbTemporary == KMF_TRUE) {
- (void) C_DestroyObject(ckSession, ckKeyHandle);
- }
-
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
return (KMF_ERR_BAD_KEY_FORMAT);
}
@@ -333,95 +409,136 @@ PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession,
return (KMF_OK);
}
-KMF_SIGNATURE_MODE
-PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX AlgId)
-{
- KMF_SIGNATURE_MODE AlgMode;
-
- switch (AlgId) {
- case KMF_ALGID_RSA:
- case KMF_ALGID_MD5WithRSA:
- case KMF_ALGID_MD2WithRSA:
- case KMF_ALGID_SHA1WithRSA:
- AlgMode = KMF_ALGMODE_PKCS1_EMSA_V15;
- break;
- default:
- AlgMode = KMF_ALGMODE_NONE;
- break;
- }
-
- return (AlgMode);
-}
-
+/*
+ * Utility routine for verifying generic data using
+ * the cryptographic framework (PKCS#11).
+ * There are situations where we want to force this
+ * operation to happen in a specific keystore.
+ * For example:
+ * libelfsign.so.1 verifies signatures on crypto libraries.
+ * We must use pkcs11 functions to verify the pkcs11
+ * plugins in order to keep the validation within the
+ * Cryptographic Framework's FIPS-140 boundary. To avoid
+ * a circular dependency, pksc11_softtoken.so.1 is
+ * interposed by libkcfd.so.1 via kcfd, which prevents
+ * libpkcs11.so.1's interfaces from being used when libkmf.so.1
+ * is called from kcfd.
+ *
+ * This also saves code and time because verify operations
+ * only use public keys and do not need acccess to any
+ * keystore specific functions.
+ */
KMF_RETURN
-PKCS_VerifyData(KMF_HANDLE_T kmfh,
+PKCS_VerifyData(KMF_HANDLE_T handle,
KMF_ALGORITHM_INDEX AlgorithmId,
KMF_X509_SPKI *keyp,
KMF_DATA *data,
- KMF_DATA *signed_data)
+ KMF_DATA *signature)
{
- KMF_RETURN rv = KMF_OK;
- PKCS_ALGORITHM_MAP *pAlgMap = NULL;
- CK_RV ckRv;
- CK_MECHANISM ckMechanism;
- CK_OBJECT_HANDLE ckKeyHandle;
- KMF_BOOL bTempKey;
+ KMF_RETURN rv = KMF_OK;
+ CK_RV ckRv;
+ KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
+ CK_MECHANISM ckMechanism;
+ CK_MECHANISM_TYPE mechtype, hashmech;
+ CK_OBJECT_HANDLE ckKeyHandle = 0;
+ CK_KEY_TYPE pk11keytype;
CK_SESSION_HANDLE ckSession = 0;
+ CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 };
+ CK_BYTE *dataptr;
+ CK_ULONG datalen;
+ KMF_DATA hashData = {NULL, 0};
+ uchar_t digest[1024];
if (AlgorithmId == KMF_ALGID_NONE)
return (KMF_ERR_BAD_ALGORITHM);
- pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
- AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
-
- if (!pAlgMap)
+ if (get_pk11_data(AlgorithmId, &pk11keytype, &mechtype, &hashmech, 1))
return (KMF_ERR_BAD_ALGORITHM);
- rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
- CKF_VERIFY);
-
+ /*
+ * Verify in metaslot/softtoken since only the public key is needed
+ * and not all hardware tokens support the combined [hash]-RSA/DSA/EC
+ * mechanisms.
+ */
+ rv = kmf_create_pk11_session(&ckSession, mechtype, 0);
if (rv != KMF_OK)
return (rv);
/* Fetch the verifying key */
rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
- pAlgMap->key_type, &ckKeyHandle, &bTempKey);
+ pk11keytype, &ckKeyHandle);
if (rv != KMF_OK) {
(void) C_CloseSession(ckSession);
return (rv);
}
+ dataptr = data->Data;
+ datalen = data->Length;
+ /*
+ * For some mechanisms, we must compute the hash separately
+ * and then do the verify.
+ */
+ if (hashmech != 0 &&
+ (mechtype == CKM_ECDSA ||
+ mechtype == CKM_DSA ||
+ mechtype == CKM_RSA_PKCS)) {
+ hashData.Data = digest;
+ hashData.Length = sizeof (digest);
+
+ rv = PKCS_DigestData(handle, ckSession,
+ hashmech, data, &hashData,
+ (mechtype == CKM_RSA_PKCS));
+ if (rv)
+ goto cleanup;
- ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
+ dataptr = hashData.Data;
+ datalen = hashData.Length;
+ }
+ if (mechtype == CKM_DSA &&
+ hashmech == CKM_SHA256) {
+ /*
+ * FIPS 186-3 says that when using DSA
+ * the hash must be truncated to the size of the
+ * subprime.
+ */
+ ckRv = C_GetAttributeValue(ckSession,
+ ckKeyHandle, &subprime, 1);
+ if (ckRv != CKR_OK) {
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckRv;
+ rv = KMF_ERR_INTERNAL;
+ goto cleanup;
+ }
+ datalen = subprime.ulValueLen;
+ }
+
+ ckMechanism.mechanism = mechtype;
ckMechanism.pParameter = NULL;
ckMechanism.ulParameterLen = 0;
ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
if (ckRv != CKR_OK) {
- if (bTempKey)
- (void) C_DestroyObject(ckSession, ckKeyHandle);
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
- (void) C_CloseSession(ckSession);
- return (KMF_ERR_INTERNAL);
+ rv = KMF_ERR_INTERNAL;
+ goto cleanup;
}
-
- ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data,
- (CK_ULONG)data->Length,
- (CK_BYTE *)signed_data->Data,
- (CK_ULONG)signed_data->Length);
+ ckRv = C_Verify(ckSession,
+ dataptr, datalen,
+ (CK_BYTE *)signature->Data,
+ (CK_ULONG)signature->Length);
if (ckRv != CKR_OK) {
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
rv = KMF_ERR_INTERNAL;
}
- if (bTempKey)
- (void) C_DestroyObject(ckSession, ckKeyHandle);
+cleanup:
+ if (ckKeyHandle != 0)
+ (void) C_DestroyObject(ckSession, ckKeyHandle);
(void) C_CloseSession(ckSession);
return (rv);
-
}
KMF_RETURN
@@ -432,11 +549,11 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
KMF_DATA *ciphertext)
{
KMF_RETURN rv = KMF_OK;
- PKCS_ALGORITHM_MAP *pAlgMap = NULL;
CK_RV ckRv;
CK_MECHANISM ckMechanism;
- CK_OBJECT_HANDLE ckKeyHandle;
- KMF_BOOL bTempKey;
+ CK_MECHANISM_TYPE mechtype;
+ CK_KEY_TYPE keytype;
+ CK_OBJECT_HANDLE ckKeyHandle = 0;
CK_SESSION_HANDLE ckSession = NULL;
CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0;
uint8_t *in_data, *out_data;
@@ -446,21 +563,16 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) /
sizeof (CK_ATTRIBUTE));
- pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
- AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
-
- if (!pAlgMap)
+ if (get_pk11_data(AlgorithmId, &keytype, &mechtype, NULL, 0))
return (KMF_ERR_BAD_ALGORITHM);
- rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
- CKF_ENCRYPT);
-
+ rv = kmf_create_pk11_session(&ckSession, mechtype, CKF_ENCRYPT);
if (rv != KMF_OK)
return (rv);
/* Get the public key used in encryption */
rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
- pAlgMap->key_type, &ckKeyHandle, &bTempKey);
+ keytype, &ckKeyHandle);
if (rv != KMF_OK) {
(void) C_CloseSession(ckSession);
@@ -471,7 +583,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
ckNumTemplates = 0;
if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates,
CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
(void) C_CloseSession(ckSession);
return (KMF_ERR_INTERNAL);
@@ -481,7 +593,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
ckTemplate, ckNumTemplates);
if (ckRv != CKR_OK) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
@@ -491,13 +603,13 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
out_len = ckTemplate[0].ulValueLen;
if (out_len > ciphertext->Length) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
(void) C_CloseSession(ckSession);
return (KMF_ERR_BUFFER_SIZE);
}
- ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
+ ckMechanism.mechanism = mechtype;
ckMechanism.pParameter = NULL_PTR;
ckMechanism.ulParameterLen = 0;
@@ -512,7 +624,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
for (i = 0; i < blocks; i++) {
ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
if (ckRv != CKR_OK) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
@@ -523,7 +635,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
(CK_BYTE_PTR)out_data, &out_len);
if (ckRv != CKR_OK) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
@@ -540,7 +652,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
/* Encrypt the remaining data */
ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle);
if (ckRv != CKR_OK) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
@@ -553,7 +665,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
(CK_BYTE_PTR)out_data, &out_len);
if (ckRv != CKR_OK) {
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
kmfh->lasterr.errcode = ckRv;
@@ -568,7 +680,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
ciphertext->Length = total_encrypted;
- if (bTempKey)
+ if (ckKeyHandle != 0)
(void) C_DestroyObject(ckSession, ckKeyHandle);
(void) C_CloseSession(ckSession);
@@ -577,7 +689,7 @@ PKCS_EncryptData(KMF_HANDLE_T kmfh,
}
static void
-DigestData(KMF_DATA *IDInput, KMF_DATA *IDOutput)
+create_id_hash(KMF_DATA *IDInput, KMF_DATA *IDOutput)
{
SHA1_CTX ctx;
@@ -616,9 +728,12 @@ GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID)
/* Check the KEY algorithm */
if (algId == KMF_ALGID_RSA) {
- DigestData(&KeyParts[KMF_RSA_MODULUS], ID);
+ create_id_hash(&KeyParts[KMF_RSA_MODULUS], ID);
} else if (algId == KMF_ALGID_DSA) {
- DigestData(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID);
+ create_id_hash(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID);
+ } else if (algId == KMF_ALGID_SHA1WithECDSA ||
+ algId == KMF_ALGID_ECDSA) {
+ create_id_hash(&KeyParts[KMF_ECDSA_POINT], ID);
} else {
/* We only support RSA and DSA keys for now */
rv = KMF_ERR_BAD_ALGORITHM;
@@ -637,3 +752,112 @@ GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID)
return (rv);
}
+
+/*
+ * For PKCS1 encoding (necessary for RSA signatures), we
+ * must prepend the following prefixes before computing
+ * the digest.
+ */
+static uchar_t SHA1_DER_PREFIX[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
+ 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
+};
+static uchar_t MD5_DER_PREFIX[] = {
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
+ 0x04, 0x10
+};
+static uchar_t SHA256_DER_PREFIX[] = {0x30, 0x31, 0x30, 0x0d,
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
+ 0x00, 0x04, 0x20};
+
+static uchar_t SHA384_DER_PREFIX[] = {0x30, 0x41, 0x30, 0x0d,
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
+ 0x00, 0x04, 0x30};
+
+static uchar_t SHA512_DER_PREFIX[] = {0x30, 0x51, 0x30, 0x0d,
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
+ 0x00, 0x04, 0x40};
+
+#define MAX_SHA2_DIGEST_LENGTH 64
+/*
+ * Compute hashes using metaslot (or softtoken).
+ * Not all hardware tokens support the combined HASH + RSA/EC
+ * Signing operations so it is safer to separate the hashing
+ * from the signing. This function generates a hash using a
+ * separate session. The resulting digest can be signed later.
+ */
+KMF_RETURN
+PKCS_DigestData(KMF_HANDLE_T handle,
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_TYPE mechtype,
+ KMF_DATA *tobesigned, KMF_DATA *output,
+ boolean_t pkcs1_encoding)
+{
+ KMF_RETURN rv = KMF_OK;
+ CK_RV ckrv;
+ CK_MECHANISM mechanism;
+ KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
+ CK_BYTE outbuf[MAX_SHA2_DIGEST_LENGTH +
+ sizeof (SHA512_DER_PREFIX)];
+ CK_ULONG outlen = sizeof (outbuf);
+
+ mechanism.mechanism = mechtype;
+ mechanism.pParameter = NULL;
+ mechanism.ulParameterLen = 0;
+
+ ckrv = C_DigestInit(hSession, &mechanism);
+ if (ckrv != CKR_OK) {
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckrv;
+ rv = KMF_ERR_INTERNAL;
+ goto end;
+ }
+
+ ckrv = C_Digest(hSession, tobesigned->Data,
+ tobesigned->Length, outbuf, &outlen);
+ if (ckrv != CKR_OK) {
+ kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kmfh->lasterr.errcode = ckrv;
+ rv = KMF_ERR_INTERNAL;
+ }
+
+ if (pkcs1_encoding) {
+ uchar_t *pfx;
+ int pfxlen;
+ switch (mechtype) {
+ case CKM_MD5:
+ pfx = MD5_DER_PREFIX;
+ pfxlen = sizeof (MD5_DER_PREFIX);
+ break;
+ case CKM_SHA_1:
+ pfx = SHA1_DER_PREFIX;
+ pfxlen = sizeof (SHA1_DER_PREFIX);
+ break;
+ case CKM_SHA256:
+ pfx = SHA256_DER_PREFIX;
+ pfxlen = sizeof (SHA256_DER_PREFIX);
+ break;
+ case CKM_SHA384:
+ pfx = SHA384_DER_PREFIX;
+ pfxlen = sizeof (SHA384_DER_PREFIX);
+ break;
+ case CKM_SHA512:
+ pfx = SHA512_DER_PREFIX;
+ pfxlen = sizeof (SHA512_DER_PREFIX);
+ break;
+ default:
+ rv = KMF_ERR_BAD_ALGORITHM;
+ goto end;
+ }
+ (void) memcpy(output->Data, pfx, pfxlen);
+ (void) memcpy(output->Data + pfxlen, outbuf, outlen);
+ output->Length = outlen + pfxlen;
+ } else {
+ (void) memcpy(output->Data, outbuf, outlen);
+ output->Length = outlen;
+ }
+
+end:
+ return (rv);
+}
diff --git a/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c b/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c
index 5fe4f0a766..8a0e6ba862 100644
--- a/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c
+++ b/usr/src/lib/libkmf/plugins/kmf_nss/common/nss_spi.c
@@ -22,7 +22,7 @@
/*
* NSS keystore wrapper
*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -154,7 +154,6 @@ KMF_PLUGIN_FUNCLIST nss_plugin_table =
NSS_CreateSymKey,
NSS_GetSymKeyValue,
NSS_SetTokenPin,
- NULL, /* VerifyData */
NSS_StoreKey,
NULL /* Finalize */
};
@@ -683,7 +682,6 @@ NSS_FreeKMFCert(KMF_HANDLE_T handle,
}
}
-
KMF_RETURN
NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
{
@@ -817,6 +815,7 @@ NSS_CreateKeypair(KMF_HANDLE_T handle,
PK11SlotInfo *nss_slot = NULL;
SECKEYPrivateKey *NSSprivkey = NULL;
SECKEYPublicKey *NSSpubkey = NULL;
+ SECKEYECParams *ecparams = NULL;
PQGParams *pqgParams = NULL;
KMF_CREDENTIAL cred;
boolean_t storekey = TRUE;
@@ -936,6 +935,20 @@ NSS_CreateKeypair(KMF_HANDLE_T handle,
}
nssparams = pqgParams;
+ } else if (keytype == KMF_ECDSA) {
+ KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
+ attrlist, numattr);
+ if (eccoid == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ ecparams = SECITEM_AllocItem(NULL, NULL, (eccoid->Length));
+ if (!ecparams)
+ return (KMF_ERR_MEMORY);
+
+ (void) memcpy(ecparams->data, eccoid->Data, eccoid->Length);
+
+ mechanism = CKM_EC_KEY_PAIR_GEN;
+ nssparams = ecparams;
} else {
rv = KMF_ERR_BAD_PARAMETER;
goto cleanup;
@@ -988,6 +1001,9 @@ cleanup:
if (pqgParams != NULL)
PK11_PQG_DestroyParams(pqgParams);
+ if (ecparams != NULL)
+ SECITEM_FreeItem(ecparams, PR_TRUE);
+
if (nss_slot != NULL)
PK11_FreeSlot(nss_slot);
@@ -1027,9 +1043,23 @@ NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
else if (AlgId == KMF_ALGID_SHA1WithRSA)
signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+ else if (AlgId == KMF_ALGID_SHA256WithRSA)
+ signAlgTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+ else if (AlgId == KMF_ALGID_SHA384WithRSA)
+ signAlgTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+ else if (AlgId == KMF_ALGID_SHA512WithRSA)
+ signAlgTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
else if (AlgId == KMF_ALGID_SHA1WithDSA)
signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
- else
+ else if (AlgId == KMF_ALGID_SHA1WithECDSA || AlgId == KMF_ALGID_ECDSA)
+ signAlgTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
+ else if (AlgId == KMF_ALGID_SHA256WithECDSA)
+ signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
+ else if (AlgId == KMF_ALGID_SHA384WithECDSA)
+ signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
+ else if (AlgId == KMF_ALGID_SHA512WithECDSA)
+ signAlgTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
+ else /* NSS does not support DSA with SHA2 hashes (FIPS 186-3) */
return (KMF_ERR_BAD_PARAMETER);
rv = SEC_SignData(&signed_data, tobesigned->Data,
@@ -1321,6 +1351,8 @@ pk11keytype2kmf(CK_KEY_TYPE type)
return (KMF_DES);
case CKK_DES3:
return (KMF_DES3);
+ case CKK_EC:
+ return (KMF_ECDSA);
default:
/* not supported */
return (KMF_KEYALG_NONE);
@@ -1437,6 +1469,8 @@ NSS_FindKey(KMF_HANDLE_T handle,
keys[count].keyalg = KMF_RSA;
else if (pubnode->key->keyType == dsaKey)
keys[count].keyalg = KMF_DSA;
+ else if (pubnode->key->keyType == ecKey)
+ keys[count].keyalg = KMF_ECDSA;
}
if (match)
count++;
@@ -1469,6 +1503,8 @@ NSS_FindKey(KMF_HANDLE_T handle,
keys[count].keyalg = KMF_RSA;
else if (prinode->key->keyType == dsaKey)
keys[count].keyalg = KMF_DSA;
+ else if (prinode->key->keyType == ecKey)
+ keys[count].keyalg = KMF_ECDSA;
}
if (match)
count++;
@@ -2188,12 +2224,16 @@ NSS_StoreKey(KMF_HANDLE_T handle,
&rawkey->rawdata.rsa);
if (rv != KMF_OK)
goto cleanup;
-
} else if (rawkey->keytype == KMF_DSA) {
rv = DerEncodeDSAPrivateKey(&derkey,
&rawkey->rawdata.dsa);
if (rv != KMF_OK)
goto cleanup;
+ } else if (rawkey->keytype == KMF_ECDSA) {
+ rv = DerEncodeECPrivateKey(&derkey,
+ &rawkey->rawdata.ec);
+ if (rv != KMF_OK)
+ goto cleanup;
}
rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm;
rpk.privateKey.data = derkey.Data;
diff --git a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
index 59def17c80..f7ffa36662 100644
--- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
+++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c
@@ -259,10 +259,6 @@ OpenSSL_VerifyCRLFile(KMF_HANDLE_T, char *, KMF_DATA *);
KMF_RETURN
OpenSSL_CheckCRLDate(KMF_HANDLE_T, char *);
-KMF_RETURN
-OpenSSL_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX,
- KMF_DATA *, KMF_DATA *, KMF_DATA *);
-
static
KMF_PLUGIN_FUNCLIST openssl_plugin_table =
{
@@ -290,7 +286,6 @@ KMF_PLUGIN_FUNCLIST openssl_plugin_table =
OpenSSL_CreateSymKey,
OpenSSL_GetSymKeyValue,
NULL, /* SetTokenPin */
- OpenSSL_VerifyDataWithCert,
OpenSSL_StoreKey,
NULL /* Finalize */
};
@@ -678,7 +673,6 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
rv = KMF_ERR_CERT_NOT_FOUND;
return (rv);
}
-
if (format == KMF_FORMAT_ASN1) {
/* load a single certificate */
certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
@@ -697,13 +691,12 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
certs = NULL;
}
return (rv);
-
} else if (format == KMF_FORMAT_PKCS12) {
/* We need a credential to access a PKCS#12 file */
rv = KMF_ERR_BAD_CERT_FORMAT;
-
} else if (format == KMF_FORMAT_PEM ||
format != KMF_FORMAT_PEM_KEYPAIR) {
+
/* This function only works on PEM files */
rv = extract_pem(kmfh, issuer, subject, serial, pathname,
(uchar_t *)NULL, 0, NULL, &certs, &nc);
@@ -724,7 +717,6 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
if (rv == KMF_ERR_VALIDITY_PERIOD)
rv = KMF_OK;
}
-
if (rv != KMF_OK) {
/* Remove this cert from the list by clearing it. */
kmf_free_data(&certs[i]);
@@ -733,7 +725,6 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
}
rv = KMF_OK;
}
-
if (rv == KMF_OK && hits > 0) {
/*
* Sort the list of certs by length to put the cleared ones
@@ -744,23 +735,17 @@ load_certs(KMF_HANDLE *kmfh, char *issuer, char *subject, KMF_BIGINT *serial,
/* since we sorted the list, just return the number of hits */
*numcerts = hits;
-
} else {
- if (rv == KMF_OK && hits == 0) {
+ if (rv == KMF_OK && hits == 0)
rv = KMF_ERR_CERT_NOT_FOUND;
- }
-
if (certs != NULL) {
- kmf_free_data(certs);
free(certs);
certs = NULL;
}
}
-
return (rv);
}
-
static KMF_RETURN
kmf_load_cert(KMF_HANDLE *kmfh,
char *issuer, char *subject, KMF_BIGINT *serial,
@@ -1211,9 +1196,7 @@ OpenSSL_FreeKMFCert(KMF_HANDLE_T handle,
{
if (kmf_cert != NULL) {
if (kmf_cert->certificate.Data != NULL) {
- free(kmf_cert->certificate.Data);
- kmf_cert->certificate.Data = NULL;
- kmf_cert->certificate.Length = 0;
+ kmf_free_data(&kmf_cert->certificate);
}
if (kmf_cert->kmf_private.label)
free(kmf_cert->kmf_private.label);
@@ -1333,8 +1316,7 @@ OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
if (rv == KMF_ERR_CERT_NOT_FOUND) {
free(fname);
- if (certdata.Data)
- free(certdata.Data);
+ kmf_free_data(&certdata);
rv = KMF_OK;
continue;
} else if (rv != KMF_OK) {
@@ -1349,8 +1331,7 @@ OpenSSL_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist)
break;
}
free(fname);
- if (certdata.Data)
- free(certdata.Data);
+ kmf_free_data(&certdata);
}
}
(void) closedir(dirp);
@@ -1370,8 +1351,7 @@ out:
if (fullpath != NULL)
free(fullpath);
- if (certdata.Data)
- free(certdata.Data);
+ kmf_free_data(&certdata);
return (rv);
}
@@ -1767,6 +1747,21 @@ cleanup:
return (rv);
}
+/*
+ * Make sure the BN conversion is properly padded with 0x00
+ * bytes. If not, signature verification for DSA signatures
+ * may fail in the case where the bignum value does not use
+ * all of the bits.
+ */
+static int
+fixbnlen(BIGNUM *bn, unsigned char *buf, int len) {
+ int bytes = len - BN_num_bytes(bn);
+ while (bytes-- > 0)
+ *buf++ = 0;
+
+ return (BN_bn2bin(bn, buf));
+}
+
KMF_RETURN
OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
KMF_OID *AlgOID, KMF_DATA *tobesigned, KMF_DATA *output)
@@ -1786,7 +1781,7 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
/* Map the OID to an OpenSSL algorithm */
AlgId = x509_algoid_to_algid(AlgOID);
if (AlgId == KMF_ALGID_NONE)
- return (KMF_ERR_BAD_PARAMETER);
+ return (KMF_ERR_BAD_ALGORITHM);
if (key->keyalg == KMF_RSA) {
EVP_PKEY *pkey = (EVP_PKEY *)key->keyp;
@@ -1798,10 +1793,16 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
md = EVP_md2();
else if (AlgId == KMF_ALGID_SHA1WithRSA)
md = EVP_sha1();
+ else if (AlgId == KMF_ALGID_SHA256WithRSA)
+ md = EVP_sha256();
+ else if (AlgId == KMF_ALGID_SHA384WithRSA)
+ md = EVP_sha384();
+ else if (AlgId == KMF_ALGID_SHA512WithRSA)
+ md = EVP_sha512();
else if (AlgId == KMF_ALGID_RSA)
md = NULL;
else
- return (KMF_ERR_BAD_PARAMETER);
+ return (KMF_ERR_BAD_ALGORITHM);
if ((md == NULL) && (AlgId == KMF_ALGID_RSA)) {
RSA *rsa = EVP_PKEY_get1_RSA((EVP_PKEY *)pkey);
@@ -1836,6 +1837,14 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
uint32_t hashlen;
DSA_SIG *dsasig;
+ if (AlgId == KMF_ALGID_DSA ||
+ AlgId == KMF_ALGID_SHA1WithDSA)
+ md = EVP_sha1();
+ else if (AlgId == KMF_ALGID_SHA256WithDSA)
+ md = EVP_sha256();
+ else /* Bad algorithm */
+ return (KMF_ERR_BAD_ALGORITHM);
+
/*
* OpenSSL EVP_Sign operation automatically converts to
* ASN.1 output so we do the operations separately so we
@@ -1844,24 +1853,27 @@ OpenSSL_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
* not all mechanisms return ASN.1 encodings (PKCS#11
* and NSS return raw signature data).
*/
- md = EVP_sha1();
EVP_MD_CTX_init(&ctx);
(void) EVP_DigestInit_ex(&ctx, md, NULL);
(void) EVP_DigestUpdate(&ctx, tobesigned->Data,
tobesigned->Length);
(void) EVP_DigestFinal_ex(&ctx, hash, &hashlen);
- (void) EVP_MD_CTX_cleanup(&ctx);
+ /* Only sign first 20 bytes for SHA2 */
+ if (AlgId == KMF_ALGID_SHA256WithDSA)
+ hashlen = 20;
dsasig = DSA_do_sign(hash, hashlen, dsa);
if (dsasig != NULL) {
int i;
- output->Length = i = BN_bn2bin(dsasig->r, output->Data);
- output->Length += BN_bn2bin(dsasig->s,
- &output->Data[i]);
+ output->Length = i = fixbnlen(dsasig->r, output->Data,
+ hashlen);
+ output->Length += fixbnlen(dsasig->s, &output->Data[i],
+ hashlen);
DSA_SIG_free(dsasig);
} else {
SET_ERROR(kmfh, ERR_get_error());
}
+ (void) EVP_MD_CTX_cleanup(&ctx);
} else {
return (KMF_ERR_BAD_PARAMETER);
}
@@ -2429,7 +2441,7 @@ OpenSSL_CreateOCSPRequest(KMF_HANDLE_T handle,
end:
/*
- * We don't need to free "id" explicitly, because OCSP_REQUEST_free()
+ * We don't need to free "id" explicitely, because OCSP_REQUEST_free()
* will also deallocate certid's space.
*/
if (req != NULL) {
@@ -3203,6 +3215,12 @@ raw_key_to_pkey(KMF_KEY_HANDLE *key)
pkey = ImportRawRSAKey(&rawkey->rawdata.rsa);
} else if (rawkey->keytype == KMF_DSA) {
pkey = ImportRawDSAKey(&rawkey->rawdata.dsa);
+ } else if (rawkey->keytype == KMF_ECDSA) {
+ /*
+ * OpenSSL in Solaris does not support EC for
+ * legal reasons
+ */
+ return (NULL);
} else {
/* wrong kind of key */
return (NULL);
@@ -3649,7 +3667,9 @@ extract_pem(KMF_HANDLE *kmfh,
&certlist[matchcerts++]);
if (rv != KMF_OK) {
- kmf_free_data(certlist);
+ int j;
+ for (j = 0; j < matchcerts; j++)
+ kmf_free_data(&certlist[j]);
free(certlist);
certlist = NULL;
ncerts = matchcerts = 0;
@@ -3659,10 +3679,11 @@ extract_pem(KMF_HANDLE *kmfh,
if (numcerts != NULL)
*numcerts = matchcerts;
- if (certs != NULL) {
+ if (certs != NULL)
*certs = certlist;
- } else if (certlist != NULL) {
- kmf_free_data(certlist);
+ else if (certlist != NULL) {
+ for (i = 0; i < ncerts; i++)
+ kmf_free_data(&certlist[i]);
free(certlist);
certlist = NULL;
}
@@ -3688,7 +3709,6 @@ err:
return (rv);
}
-
static KMF_RETURN
openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin,
STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs)
@@ -3728,7 +3748,7 @@ set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid)
X509_ATTRIBUTE *a;
for (i = 0;
i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
+ /* LINTED E_BAD_PTR_CASE_ALIGN */
a = sk_X509_ATTRIBUTE_value(pkey->attributes, i);
if (OBJ_obj2nid(a->object) == nid) {
X509_ATTRIBUTE_free(a);
@@ -4385,14 +4405,12 @@ openssl_import_objects(KMF_HANDLE *kmfh,
(void) sk_EVP_PKEY_push(privkeys, pkey);
/* convert the certificate list here */
if (*ncerts > 0 && certlist != NULL) {
- kmfcerts = (KMF_X509_DER_CERT *)malloc(*ncerts *
+ kmfcerts = (KMF_X509_DER_CERT *)calloc(*ncerts,
sizeof (KMF_X509_DER_CERT));
if (kmfcerts == NULL) {
rv = KMF_ERR_MEMORY;
goto end;
}
- (void) memset(kmfcerts, 0, *ncerts *
- sizeof (KMF_X509_DER_CERT));
for (i = 0; i < *ncerts; i++) {
kmfcerts[i].certificate = certdata[i];
kmfcerts[i].kmf_private.keystore_type =
@@ -4781,208 +4799,6 @@ OpenSSL_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey,
}
/*
- * id-sha1 OBJECT IDENTIFIER ::= {
- * iso(1) identified-organization(3) oiw(14) secsig(3)
- * algorithms(2) 26
- * }
- */
-#define ASN1_SHA1_OID_PREFIX_LEN 15
-static uchar_t SHA1_DER_PREFIX[ASN1_SHA1_OID_PREFIX_LEN] = {
- 0x30, 0x21, 0x30, 0x09,
- 0x06, 0x05, 0x2b, 0x0e,
- 0x03, 0x02, 0x1a, 0x05,
- 0x00, 0x04, 0x14
-};
-
-/*
- * id-md2 OBJECT IDENTIFIER ::= {
- * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2
- * }
- */
-#define ASN1_MD2_OID_PREFIX_LEN 18
-static uchar_t MD2_DER_PREFIX[ASN1_MD2_OID_PREFIX_LEN] = {
- 0x30, 0x20, 0x30, 0x0c,
- 0x06, 0x08, 0x2a, 0x86,
- 0x48, 0x86, 0xf7, 0x0d,
- 0x02, 0x02, 0x05, 0x00,
- 0x04, 0x10
-};
-
-/*
- * id-md5 OBJECT IDENTIFIER ::= {
- * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5
- * }
- */
-#define ASN1_MD5_OID_PREFIX_LEN 18
-static uchar_t MD5_DER_PREFIX[ASN1_MD5_OID_PREFIX_LEN] = {
- 0x30, 0x20, 0x30, 0x0c,
- 0x06, 0x08, 0x2a, 0x86,
- 0x48, 0x86, 0xf7, 0x0d,
- 0x02, 0x05, 0x05, 0x00,
- 0x04, 0x10
-};
-
-KMF_RETURN
-OpenSSL_VerifyDataWithCert(KMF_HANDLE_T handle,
- KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
- KMF_DATA *insig, KMF_DATA *cert)
-{
- KMF_RETURN ret = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- X509 *xcert = NULL;
- EVP_PKEY *pkey = NULL;
- uchar_t *p;
- uchar_t *rsaout = NULL;
- uchar_t *pfx = NULL;
- const EVP_MD *md;
- int pfxlen = 0, len;
-
- if (handle == NULL || indata == NULL ||
- indata->Data == NULL || indata->Length == 0 ||
- insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
- cert == NULL || cert->Data == NULL || cert->Length == 0)
- return (KMF_ERR_BAD_PARAMETER);
-
- p = cert->Data;
- xcert = d2i_X509(NULL, (const uchar_t **)&p, cert->Length);
- if (xcert == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- ret = KMF_ERR_BAD_CERT_FORMAT;
- goto cleanup;
- }
-
- pkey = X509_get_pubkey(xcert);
- if (pkey == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- ret = KMF_ERR_BAD_CERT_FORMAT;
- goto cleanup;
- }
-
- if (algid != KMF_ALGID_NONE) {
- switch (algid) {
- case KMF_ALGID_MD5WithRSA:
- md = EVP_md5();
- break;
- case KMF_ALGID_MD2WithRSA:
- md = EVP_md2();
- break;
- case KMF_ALGID_SHA1WithRSA:
- md = EVP_sha1();
- break;
- case KMF_ALGID_RSA:
- md = NULL;
- break;
- default:
- ret = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- } else {
- /* Get the hash type from the cert signature */
- md = EVP_get_digestbyobj(xcert->sig_alg->algorithm);
- if (md == NULL) {
- SET_ERROR(kmfh, ERR_get_error());
- ret = KMF_ERR_BAD_PARAMETER;
- goto cleanup;
- }
- }
- if (md != NULL) {
- switch (EVP_MD_type(md)) {
- case NID_md2:
- case NID_md2WithRSAEncryption:
- pfxlen = ASN1_MD2_OID_PREFIX_LEN;
- pfx = MD2_DER_PREFIX;
- break;
- case NID_md5:
- case NID_md5WithRSAEncryption:
- pfxlen = ASN1_MD5_OID_PREFIX_LEN;
- pfx = MD5_DER_PREFIX;
- break;
- case NID_sha1:
- case NID_sha1WithRSAEncryption:
- pfxlen = ASN1_SHA1_OID_PREFIX_LEN;
- pfx = SHA1_DER_PREFIX;
- break;
- default: /* Unsupported */
- pfxlen = 0;
- pfx = NULL;
- break;
- }
- }
-
- /* RSA with no hash is a special case */
- rsaout = malloc(RSA_size(pkey->pkey.rsa));
- if (rsaout == NULL)
- return (KMF_ERR_MEMORY);
-
- /* Decrypt the input signature */
- len = RSA_public_decrypt(insig->Length,
- insig->Data, rsaout, pkey->pkey.rsa, RSA_PKCS1_PADDING);
- if (len < 1) {
- SET_ERROR(kmfh, ERR_get_error());
- ret = KMF_ERR_BAD_PARAMETER;
- } else {
- size_t hashlen = 0;
- uint32_t dlen;
- char *digest = NULL;
-
- /*
- * If the AlgId requires it, hash the input data before
- * comparing it to the decrypted signature.
- */
- if (md) {
- EVP_MD_CTX ctx;
-
- hashlen = md->md_size;
-
- digest = malloc(hashlen + pfxlen);
- if (digest == NULL)
- return (KMF_ERR_MEMORY);
- /* Add the prefix to the comparison buffer. */
- if (pfx && pfxlen > 0) {
- (void) memcpy(digest, pfx, pfxlen);
- }
- (void) EVP_DigestInit(&ctx, md);
- (void) EVP_DigestUpdate(&ctx, indata->Data,
- indata->Length);
-
- /* Add the digest AFTER the ASN1 prefix */
- (void) EVP_DigestFinal(&ctx,
- (uchar_t *)digest + pfxlen, &dlen);
-
- dlen += pfxlen;
- } else {
- digest = (char *)indata->Data;
- dlen = indata->Length;
- }
-
- /*
- * The result of the RSA decryption should be ASN1(OID | Hash).
- * Compare the output hash to the input data for the final
- * result.
- */
- if (memcmp(rsaout, digest, dlen))
- ret = KMF_ERR_INTERNAL;
- else
- ret = KMF_OK;
-
- /* If we had to allocate space for the digest, free it now */
- if (hashlen)
- free(digest);
- }
-cleanup:
- if (pkey)
- EVP_PKEY_free(pkey);
-
- if (xcert)
- X509_free(xcert);
-
- if (rsaout)
- free(rsaout);
-
- return (ret);
-}
-
-/*
* substitute for the unsafe access(2) function.
* If the file in question already exists, return 1.
* else 0. If an error occurs during testing (other
diff --git a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
index 8d65701ebd..104612f1e9 100644
--- a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
+++ b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
@@ -21,7 +21,7 @@
/*
* PKCS11 token KMF Plugin
*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -31,7 +31,6 @@
#include <kmfapiP.h>
#include <ber_der.h>
-#include <algorithm.h>
#include <fcntl.h>
#include <sha1.h>
#include <bignum.h>
@@ -127,10 +126,6 @@ KMF_RETURN
KMFPK11_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
KMF_RETURN
-KMFPK11_VerifyDataWithCert(KMF_HANDLE_T, KMF_ALGORITHM_INDEX, KMF_DATA *,
- KMF_DATA *, KMF_DATA *);
-
-KMF_RETURN
KMFPK11_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *);
@@ -161,7 +156,6 @@ KMF_PLUGIN_FUNCLIST pk11token_plugin_table =
KMFPK11_CreateSymKey,
KMFPK11_GetSymKeyValue,
KMFPK11_SetTokenPin,
- KMFPK11_VerifyDataWithCert,
KMFPK11_StoreKey,
NULL /* Finalize */
};
@@ -777,7 +771,7 @@ KMFPK11_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
KMF_RETURN
KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
- KMF_DATA *eData)
+ KMF_DATA *eData)
{
KMF_RETURN ret = KMF_OK;
CK_RV rv;
@@ -789,9 +783,11 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
BerElement *asn1 = NULL;
BerValue *PubKeyParams = NULL, *EncodedKey = NULL;
KMF_X509_SPKI spki;
+ CK_BYTE ec_params[256], ec_point[256];
CK_ATTRIBUTE rsaTemplate[4];
CK_ATTRIBUTE dsaTemplate[6];
+ CK_ATTRIBUTE ecdsaTemplate[6];
if (kmfh == NULL)
return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
@@ -809,21 +805,16 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
(void) memset(&Base, 0, sizeof (Base));
(void) memset(&Value, 0, sizeof (Value));
- SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
- SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
- SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data, Modulus.Length);
- SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT, Exponent.Data,
- Exponent.Length);
-
- SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass, sizeof (ckObjClass));
- SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType, sizeof (ckKeyType));
- SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data, Prime.Length);
- SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data, Subprime.Length);
- SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data, Base.Length);
- SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data, Value.Length);
-
switch (pKey->keyalg) {
case KMF_RSA:
+ SETATTR(rsaTemplate, 0, CKA_CLASS, &ckObjClass,
+ sizeof (ckObjClass));
+ SETATTR(rsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType,
+ sizeof (ckKeyType));
+ SETATTR(rsaTemplate, 2, CKA_MODULUS, Modulus.Data,
+ Modulus.Length);
+ SETATTR(rsaTemplate, 3, CKA_PUBLIC_EXPONENT,
+ Exponent.Data, Exponent.Length);
/* Get the length of the fields */
rv = C_GetAttributeValue(kmfh->pk11handle,
(CK_OBJECT_HANDLE)pKey->keyp, rsaTemplate, 4);
@@ -893,6 +884,19 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
break;
case KMF_DSA:
+ SETATTR(dsaTemplate, 0, CKA_CLASS, &ckObjClass,
+ sizeof (ckObjClass));
+ SETATTR(dsaTemplate, 1, CKA_KEY_TYPE, &ckKeyType,
+ sizeof (ckKeyType));
+ SETATTR(dsaTemplate, 2, CKA_PRIME, Prime.Data,
+ Prime.Length);
+ SETATTR(dsaTemplate, 3, CKA_SUBPRIME, Subprime.Data,
+ Subprime.Length);
+ SETATTR(dsaTemplate, 4, CKA_BASE, Base.Data,
+ Base.Length);
+ SETATTR(dsaTemplate, 5, CKA_VALUE, Value.Data,
+ Value.Length);
+
/* Get the length of the fields */
rv = C_GetAttributeValue(kmfh->pk11handle,
(CK_OBJECT_HANDLE)pKey->keyp, dsaTemplate, 6);
@@ -1008,6 +1012,41 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
kmfber_free(asn1, 1);
free(Value.Data);
break;
+ case KMF_ECDSA:
+ /* The EC_PARAMS are the PubKey algorithm parameters */
+ PubKeyParams = calloc(1, sizeof (BerValue));
+ if (PubKeyParams == NULL)
+ return (KMF_ERR_MEMORY);
+ EncodedKey = calloc(1, sizeof (BerValue));
+ if (EncodedKey == NULL) {
+ free(PubKeyParams);
+ return (KMF_ERR_MEMORY);
+ }
+ SETATTR(ecdsaTemplate, 0, CKA_EC_PARAMS,
+ &ec_params, sizeof (ec_params));
+ SETATTR(ecdsaTemplate, 1, CKA_EC_POINT,
+ &ec_point, sizeof (ec_point));
+
+ /* Get the length of the fields */
+ rv = C_GetAttributeValue(kmfh->pk11handle,
+ (CK_OBJECT_HANDLE)pKey->keyp,
+ ecdsaTemplate, 2);
+ if (rv != CKR_OK) {
+ SET_ERROR(kmfh, rv);
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+ /* The params are to be used as algorithm parameters */
+ PubKeyParams->bv_val = (char *)ec_params;
+ PubKeyParams->bv_len = ecdsaTemplate[0].ulValueLen;
+ /*
+ * The EC_POINT is to be used as the subject pub key.
+ */
+ EncodedKey->bv_val = (char *)ec_point;
+ EncodedKey->bv_len = ecdsaTemplate[1].ulValueLen;
+
+ /* Use the EC_PUBLIC_KEY OID */
+ Algorithm = (KMF_OID *)&KMFOID_EC_PUBLIC_KEY;
+ break;
default:
return (KMF_ERR_BAD_PARAMETER);
}
@@ -1036,12 +1075,14 @@ KMFPK11_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *pKey,
cleanup:
if (EncodedKey) {
- free(EncodedKey->bv_val);
+ if (pKey->keyalg != KMF_ECDSA)
+ free(EncodedKey->bv_val);
free(EncodedKey);
}
if (PubKeyParams) {
- free(PubKeyParams->bv_val);
+ if (pKey->keyalg != KMF_ECDSA)
+ free(PubKeyParams->bv_val);
free(PubKeyParams);
}
@@ -1363,32 +1404,18 @@ out:
return (rv);
}
-KMF_RETURN
-KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
- int numattr,
- KMF_ATTRIBUTE *attlist)
+static CK_RV
+gendsa_keypair(KMF_HANDLE *kmfh, boolean_t storekey,
+ CK_OBJECT_HANDLE *pubKey,
+ CK_OBJECT_HANDLE *priKey)
{
- KMF_RETURN rv = KMF_OK;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
-
- CK_RV ckrv = 0;
- CK_OBJECT_HANDLE pubKey = CK_INVALID_HANDLE;
- CK_OBJECT_HANDLE priKey = CK_INVALID_HANDLE;
- CK_SESSION_HANDLE hSession = kmfh->pk11handle;
-
- static CK_OBJECT_CLASS priClass = CKO_PRIVATE_KEY;
- static CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
-
- static CK_ULONG modulusBits = 1024;
- uint32_t modulusBits_size = sizeof (CK_ULONG);
- static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
+ CK_RV ckrv = CKR_OK;
+ CK_SESSION_HANDLE hSession = kmfh->pk11handle;
+ static CK_ULONG dsaKeyType = CKK_DSA;
static CK_BBOOL true = TRUE;
- static CK_BBOOL ontoken = TRUE;
static CK_BBOOL false = FALSE;
- static CK_ULONG dsaKeyType = CKK_DSA;
-
- CK_ATTRIBUTE rsaPubKeyTemplate[16];
- CK_ATTRIBUTE rsaPriKeyTemplate[16];
+ static CK_OBJECT_CLASS priClass = CKO_PRIVATE_KEY;
+ static CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
static CK_BYTE ckDsaPrime[128] = {
0xb2, 0x6b, 0xc3, 0xfb, 0xe3, 0x26, 0xf4, 0xc2,
@@ -1434,7 +1461,7 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
static CK_ATTRIBUTE ckDsaPubKeyTemplate[] = {
{ CKA_CLASS, &pubClass, sizeof (pubClass) },
{ CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType) },
- { CKA_TOKEN, &ontoken, sizeof (ontoken)},
+ { CKA_TOKEN, &true, sizeof (true)},
{ CKA_PRIVATE, &false, sizeof (false)},
{ CKA_PRIME, &ckDsaPrime, sizeof (ckDsaPrime) },
{ CKA_SUBPRIME, &ckDsaSubPrime, sizeof (ckDsaSubPrime)},
@@ -1450,26 +1477,201 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
static CK_ATTRIBUTE ckDsaPriKeyTemplate[] = {
{CKA_CLASS, &priClass, sizeof (priClass)},
{CKA_KEY_TYPE, &dsaKeyType, sizeof (dsaKeyType)},
- {CKA_TOKEN, &ontoken, sizeof (ontoken)},
+ {CKA_TOKEN, &true, sizeof (true)},
{CKA_PRIVATE, &true, sizeof (true)},
{CKA_SIGN, &true, sizeof (true)},
};
+#define NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
+ sizeof (CK_ATTRIBUTE))
+#define MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
+ sizeof (CK_ATTRIBUTE))
+ CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
+
+ SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
+ (storekey ? &true : &false), sizeof (CK_BBOOL));
+
+ ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
+ ckDsaPubKeyTemplate,
+ (sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
+ ckDsaPriKeyTemplate,
+ (sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
+ pubKey, priKey);
+ if (ckrv != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+ return (KMF_ERR_KEYGEN_FAILED);
+ }
+
+ return (ckrv);
+}
+
+static CK_RV
+genrsa_keypair(KMF_HANDLE *kmfh, CK_ULONG modulusBits,
+ boolean_t storekey, KMF_BIGINT *rsaexp,
+ CK_OBJECT_HANDLE *pubKey,
+ CK_OBJECT_HANDLE *priKey)
+{
+ CK_RV ckrv = CKR_OK;
+ CK_SESSION_HANDLE hSession = kmfh->pk11handle;
+ CK_ATTRIBUTE rsaPubKeyTemplate[16];
+ CK_ATTRIBUTE rsaPriKeyTemplate[16];
+ CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0};
+ int numpubattr = 0, numpriattr = 0;
+ static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
+ static CK_BBOOL true = TRUE;
+ static CK_BBOOL false = FALSE;
+
+ SETATTR(rsaPubKeyTemplate, numpubattr, CKA_TOKEN,
+ (storekey ? &true : &false), sizeof (CK_BBOOL));
+ numpubattr++;
+
+ SETATTR(rsaPubKeyTemplate, numpubattr, CKA_MODULUS_BITS,
+ &modulusBits, sizeof (modulusBits));
+ numpubattr++;
+
+ if (rsaexp != NULL && (rsaexp->len > 0 && rsaexp->val != NULL)) {
+ SETATTR(rsaPubKeyTemplate, numpubattr,
+ CKA_PUBLIC_EXPONENT,
+ rsaexp->val, rsaexp->len);
+ numpubattr++;
+ } else {
+ SETATTR(rsaPubKeyTemplate, numpubattr,
+ CKA_PUBLIC_EXPONENT, &PubExpo, sizeof (PubExpo));
+ numpubattr++;
+ }
+ SETATTR(rsaPubKeyTemplate, numpubattr, CKA_ENCRYPT,
+ &true, sizeof (true));
+ numpubattr++;
+ SETATTR(rsaPubKeyTemplate, numpubattr, CKA_VERIFY,
+ &true, sizeof (true));
+ numpubattr++;
+ SETATTR(rsaPubKeyTemplate, numpubattr, CKA_WRAP,
+ &true, sizeof (true));
+ numpubattr++;
+
+ SETATTR(rsaPriKeyTemplate, numpriattr, CKA_TOKEN,
+ (storekey ? &true : &false), sizeof (CK_BBOOL));
+ numpriattr++;
+ SETATTR(rsaPriKeyTemplate, numpriattr, CKA_PRIVATE, &true,
+ sizeof (true));
+ numpriattr++;
+ SETATTR(rsaPriKeyTemplate, numpriattr, CKA_DECRYPT, &true,
+ sizeof (true));
+ numpriattr++;
+ SETATTR(rsaPriKeyTemplate, numpriattr, CKA_SIGN, &true,
+ sizeof (true));
+ numpriattr++;
+ SETATTR(rsaPriKeyTemplate, numpriattr, CKA_UNWRAP, &true,
+ sizeof (true));
+ numpriattr++;
+
+ ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
+ rsaPubKeyTemplate, numpubattr,
+ rsaPriKeyTemplate, numpriattr,
+ pubKey, priKey);
+ if (ckrv != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+ return (ckrv);
+ }
+
+ return (ckrv);
+}
+
+static CK_RV
+genecc_keypair(KMF_HANDLE *kmfh,
+ boolean_t ontoken,
+ KMF_OID *curveoid,
+ CK_OBJECT_HANDLE *pubKey,
+ CK_OBJECT_HANDLE *priKey)
+{
+ CK_RV ckrv;
+ CK_SESSION_HANDLE hSession = kmfh->pk11handle;
+ CK_MECHANISM keyGenMech = {CKM_EC_KEY_PAIR_GEN, NULL, 0};
+ const ulong_t publicKey = CKO_PUBLIC_KEY;
+ const ulong_t privateKey = CKO_PRIVATE_KEY;
+ const ulong_t keytype = CKK_EC;
+ static CK_BBOOL true = TRUE;
+ static CK_BBOOL false = FALSE;
+ CK_ATTRIBUTE public_template[6];
+ CK_ATTRIBUTE private_template[6];
+ int numpubattr, numpriattr;
+
+ numpubattr = 0;
+ SETATTR(public_template, numpubattr, CKA_CLASS,
+ &publicKey, sizeof (publicKey));
+ numpubattr++;
+ SETATTR(public_template, numpubattr, CKA_KEY_TYPE,
+ &keytype, sizeof (keytype));
+ numpubattr++;
+ SETATTR(public_template, numpubattr, CKA_EC_PARAMS,
+ curveoid->Data, curveoid->Length);
+ numpubattr++;
+ SETATTR(public_template, numpubattr, CKA_TOKEN,
+ ontoken ? &true : &false, sizeof (true));
+ numpubattr++;
+ SETATTR(public_template, numpubattr, CKA_VERIFY,
+ &true, sizeof (true));
+ numpubattr++;
+ SETATTR(public_template, numpubattr, CKA_PRIVATE,
+ &false, sizeof (false));
+ numpubattr++;
+
+ numpriattr = 0;
+ SETATTR(private_template, numpriattr, CKA_CLASS,
+ &privateKey, sizeof (privateKey));
+ numpriattr++;
+ SETATTR(private_template, numpriattr, CKA_KEY_TYPE,
+ &keytype, sizeof (keytype));
+ numpriattr++;
+ SETATTR(private_template, numpriattr, CKA_TOKEN,
+ ontoken ? &true : &false, sizeof (true));
+ numpriattr++;
+ SETATTR(private_template, numpriattr, CKA_PRIVATE,
+ &true, sizeof (true));
+ numpriattr++;
+ SETATTR(private_template, numpriattr, CKA_SIGN,
+ &true, sizeof (true));
+ numpriattr++;
+ SETATTR(private_template, numpriattr, CKA_DERIVE,
+ &true, sizeof (true));
+ numpriattr++;
+
+ ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
+ public_template, numpubattr,
+ private_template, numpriattr,
+ pubKey, priKey);
+ if (ckrv != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+ return (ckrv);
+ }
+
+ return (ckrv);
+}
+
+KMF_RETURN
+KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
+ int numattr,
+ KMF_ATTRIBUTE *attlist)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
+ KMF_DATA IDInput, IDOutput;
+ KMF_CREDENTIAL *cred;
+ KMF_KEY_ALG keytype = KMF_RSA;
+ KMF_KEY_HANDLE *pubkey, *privkey;
+
+ CK_RV ckrv = 0;
+ CK_SESSION_HANDLE hSession = kmfh->pk11handle;
CK_ATTRIBUTE labelattr[1];
CK_ATTRIBUTE idattr[1];
+ CK_OBJECT_HANDLE pubKey, priKey;
+
char IDHashData[SHA1_HASH_LENGTH];
- KMF_DATA IDInput, IDOutput;
+ static CK_ULONG modulusBits = 1024;
+ uint32_t modulusBits_size = sizeof (CK_ULONG);
SHA1_CTX ctx;
- KMF_CREDENTIAL *cred;
- KMF_KEY_ALG keytype = KMF_RSA;
boolean_t storekey = TRUE;
char *keylabel = NULL;
- KMF_KEY_HANDLE *pubkey, *privkey;
-
-#define NUMBER_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
- sizeof (CK_ATTRIBUTE))
-#define MAX_DSA_PRI_TEMPLATES (sizeof (ckDsaPriKeyTemplate) / \
- sizeof (CK_ATTRIBUTE))
if (kmfh == NULL)
return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
@@ -1504,12 +1706,10 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
(void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE));
(void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE));
if (keytype == KMF_RSA) {
- CK_MECHANISM keyGenMech = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0};
- CK_BYTE *modulus;
+ CK_BYTE *modulus = NULL;
CK_ULONG modulusLength = 0;
- CK_ATTRIBUTE modattr[1];
KMF_BIGINT *rsaexp = NULL;
- int numpubattr = 0, numpriattr = 0;
+ CK_ATTRIBUTE modattr[1];
rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attlist, numattr,
&modulusBits, &modulusBits_size);
@@ -1519,64 +1719,14 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
if (rv != KMF_OK)
return (KMF_ERR_BAD_PARAMETER);
- SETATTR(rsaPubKeyTemplate, numpubattr, CKA_TOKEN,
- (storekey ? &true : &false), sizeof (CK_BBOOL));
- numpubattr++;
+ rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attlist, numattr);
- SETATTR(rsaPubKeyTemplate, numpubattr, CKA_MODULUS_BITS,
- &modulusBits, sizeof (modulusBits));
- numpubattr++;
+ /* Generate the RSA keypair */
+ ckrv = genrsa_keypair(kmfh, modulusBits, storekey,
+ rsaexp, &pubKey, &priKey);
- if ((rsaexp = kmf_get_attr_ptr(KMF_RSAEXP_ATTR, attlist,
- numattr)) != NULL &&
- (rsaexp->len > 0 && rsaexp->val != NULL)) {
- SETATTR(rsaPubKeyTemplate, numpubattr,
- CKA_PUBLIC_EXPONENT,
- rsaexp->val, rsaexp->len);
- numpubattr++;
- } else {
- rv = KMF_OK;
- SETATTR(rsaPubKeyTemplate, numpubattr,
- CKA_PUBLIC_EXPONENT, &PubExpo, sizeof (PubExpo));
- numpubattr++;
- }
- SETATTR(rsaPubKeyTemplate, numpubattr, CKA_ENCRYPT,
- &true, sizeof (true));
- numpubattr++;
- SETATTR(rsaPubKeyTemplate, numpubattr, CKA_VERIFY,
- &true, sizeof (true));
- numpubattr++;
- SETATTR(rsaPubKeyTemplate, numpubattr, CKA_WRAP,
- &true, sizeof (true));
- numpubattr++;
-
- SETATTR(rsaPriKeyTemplate, numpriattr, CKA_TOKEN,
- (storekey ? &true : &false), sizeof (CK_BBOOL));
- numpriattr++;
- SETATTR(rsaPriKeyTemplate, numpriattr, CKA_PRIVATE, &true,
- sizeof (true));
- numpriattr++;
- SETATTR(rsaPriKeyTemplate, numpriattr, CKA_DECRYPT, &true,
- sizeof (true));
- numpriattr++;
- SETATTR(rsaPriKeyTemplate, numpriattr, CKA_SIGN, &true,
- sizeof (true));
- numpriattr++;
- SETATTR(rsaPriKeyTemplate, numpriattr, CKA_UNWRAP, &true,
- sizeof (true));
- numpriattr++;
-
-
- pubKey = CK_INVALID_HANDLE;
- priKey = CK_INVALID_HANDLE;
- ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
- rsaPubKeyTemplate, numpubattr,
- rsaPriKeyTemplate, numpriattr,
- &pubKey, &priKey);
- if (ckrv != CKR_OK) {
- SET_ERROR(kmfh, ckrv);
- return (KMF_ERR_KEYGEN_FAILED);
- }
+ if (ckrv != CKR_OK)
+ return (KMF_ERR_BAD_PARAMETER);
privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
privkey->keyalg = KMF_RSA;
@@ -1615,37 +1765,79 @@ KMFPK11_CreateKeypair(KMF_HANDLE_T handle,
IDInput.Length = modulusLength;
} else if (keytype == KMF_DSA) {
- CK_MECHANISM keyGenMech = {CKM_DSA_KEY_PAIR_GEN, NULL, 0};
CK_BYTE *keyvalue;
CK_ULONG valueLen;
CK_ATTRIBUTE valattr[1];
- SETATTR(ckDsaPriKeyTemplate, 2, CKA_TOKEN,
- (storekey ? &true : &false), sizeof (CK_BBOOL));
+ /* Generate the DSA keypair */
+ ckrv = gendsa_keypair(kmfh, storekey, &pubKey, &priKey);
+ if (ckrv != CKR_OK)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
+ privkey->keyalg = KMF_DSA;
+ privkey->keyclass = KMF_ASYM_PRI;
+ privkey->keyp = (void *)priKey;
+
+ pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
+ pubkey->keyalg = KMF_DSA;
+ pubkey->keyclass = KMF_ASYM_PUB;
+ pubkey->keyp = (void *)pubKey;
+
+ /* Get the Public Value to use as input for creating the ID */
SETATTR(valattr, 0, CKA_VALUE, NULL, &valueLen);
- ckrv = C_GenerateKeyPair(hSession, &keyGenMech,
- ckDsaPubKeyTemplate,
- (sizeof (ckDsaPubKeyTemplate)/sizeof (CK_ATTRIBUTE)),
- ckDsaPriKeyTemplate,
- (sizeof (ckDsaPriKeyTemplate)/sizeof (CK_ATTRIBUTE)),
- &pubKey, &priKey);
+ ckrv = C_GetAttributeValue(hSession,
+ (CK_OBJECT_HANDLE)pubKey, valattr, 1);
+ if (ckrv != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+
+ valueLen = valattr[0].ulValueLen;
+ keyvalue = malloc(valueLen);
+ if (keyvalue == NULL)
+ return (KMF_ERR_MEMORY);
+
+ valattr[0].pValue = keyvalue;
+ ckrv = C_GetAttributeValue(hSession,
+ (CK_OBJECT_HANDLE)pubKey, valattr, 1);
if (ckrv != CKR_OK) {
SET_ERROR(kmfh, ckrv);
- return (KMF_ERR_KEYGEN_FAILED);
+ free(keyvalue);
+ return (KMF_ERR_BAD_PARAMETER);
}
+ IDInput.Data = keyvalue;
+ IDInput.Length = valueLen;
+ } else if (keytype == KMF_ECDSA) {
+ CK_BYTE *keyvalue;
+ CK_ULONG valueLen;
+ CK_ATTRIBUTE valattr[1];
+ KMF_OID *eccoid = kmf_get_attr_ptr(KMF_ECC_CURVE_OID_ATTR,
+ attlist, numattr);
+
+ if (eccoid == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
+
+ ckrv = genecc_keypair(kmfh, storekey, eccoid,
+ &pubKey, &priKey);
+ if (ckrv != CKR_OK)
+ return (KMF_ERR_BAD_PARAMETER);
+
privkey->kstype = KMF_KEYSTORE_PK11TOKEN;
- privkey->keyalg = KMF_DSA;
+ privkey->keyalg = KMF_ECDSA;
privkey->keyclass = KMF_ASYM_PRI;
privkey->keyp = (void *)priKey;
pubkey->kstype = KMF_KEYSTORE_PK11TOKEN;
- pubkey->keyalg = KMF_DSA;
+ pubkey->keyalg = KMF_ECDSA;
pubkey->keyclass = KMF_ASYM_PUB;
pubkey->keyp = (void *)pubKey;
- /* Get the Public Value to use as input for creating the ID */
+ /* Get the EC_POINT to use as input for creating the ID */
+ SETATTR(valattr, 0, CKA_EC_POINT, NULL, &valueLen);
+
ckrv = C_GetAttributeValue(hSession,
(CK_OBJECT_HANDLE)pubKey, valattr, 1);
if (ckrv != CKR_OK) {
@@ -1812,12 +2004,17 @@ KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
KMF_DATA *tobesigned,
KMF_DATA *output)
{
+ KMF_RETURN rv = KMF_OK;
CK_RV ckrv;
KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
CK_SESSION_HANDLE hSession = kmfh->pk11handle;
CK_MECHANISM mechanism;
- PKCS_ALGORITHM_MAP *pAlgMap;
+ CK_MECHANISM_TYPE mechtype, hashmech;
+ CK_KEY_TYPE keytype;
KMF_ALGORITHM_INDEX AlgId;
+ KMF_DATA hashData = {NULL, 0};
+ uchar_t digest[1024];
+ CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 };
if (kmfh == NULL)
return (KMF_ERR_UNINITIALIZED); /* Plugin Not Initialized */
@@ -1834,14 +2031,36 @@ KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
if (AlgId == KMF_ALGID_NONE)
return (KMF_ERR_BAD_PARAMETER);
- /* Map the Algorithm OID to a PKCS#11 mechanism */
- pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
- AlgId, PKCS_GetDefaultSignatureMode(AlgId));
-
- if (pAlgMap == NULL)
+ /* Get the PKCS11 signing key type and mechtype */
+ if (get_pk11_data(AlgId, &keytype, &mechtype, &hashmech, 0))
return (KMF_ERR_BAD_PARAMETER);
- mechanism.mechanism = pAlgMap->pkcs_mechanism;
+ (void) memset(digest, 0, sizeof (digest));
+ hashData.Data = digest;
+ hashData.Length = sizeof (digest);
+ rv = PKCS_DigestData(handle, hSession, hashmech, tobesigned, &hashData,
+ (mechtype == CKM_RSA_PKCS));
+ if (rv)
+ return (rv);
+
+ if (mechtype == CKM_DSA && hashmech == CKM_SHA256) {
+ /*
+ * FIPS 186-3 says that when signing with DSA
+ * the hash must be truncated to the size of the
+ * subprime.
+ */
+ ckrv = C_GetAttributeValue(hSession,
+ (CK_OBJECT_HANDLE)keyp->keyp,
+ &subprime, 1);
+ if (ckrv != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+ return (KMF_ERR_INTERNAL);
+ }
+ hashData.Length = subprime.ulValueLen;
+ }
+
+ /* the mechtype from the 'get_pk11_info' refers to the signing */
+ mechanism.mechanism = mechtype;
mechanism.pParameter = NULL;
mechanism.ulParameterLen = 0;
@@ -1851,7 +2070,7 @@ KMFPK11_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp,
return (KMF_ERR_INTERNAL);
}
- ckrv = C_Sign(hSession, tobesigned->Data, tobesigned->Length,
+ ckrv = C_Sign(hSession, hashData.Data, hashData.Length,
output->Data, (CK_ULONG *)&output->Length);
if (ckrv != CKR_OK) {
@@ -2069,6 +2288,8 @@ KMFPK11_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr,
key->keyalg = KMF_RSA;
else if (keytype == CKK_DSA)
key->keyalg = KMF_DSA;
+ else if (keytype == CKK_EC)
+ key->keyalg = KMF_ECDSA;
else {
/* For asymmetric keys, we only support RSA and DSA */
rv = KMF_ERR_KEY_NOT_FOUND;
@@ -2104,7 +2325,8 @@ KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
CK_SESSION_HANDLE hSession = kmfh->pk11handle;
CK_MECHANISM mechanism;
- PKCS_ALGORITHM_MAP *pAlgMap;
+ CK_MECHANISM_TYPE mechtype;
+ CK_KEY_TYPE keytype;
KMF_ALGORITHM_INDEX AlgId;
CK_ULONG out_len = 0, block_len = 0, total_decrypted = 0;
uint8_t *in_data, *out_data;
@@ -2126,13 +2348,10 @@ KMFPK11_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key,
return (KMF_ERR_BAD_PARAMETER);
/* Map the Algorithm ID to a PKCS#11 mechanism */
- pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
- AlgId, PKCS_GetDefaultSignatureMode(AlgId));
-
- if (pAlgMap == NULL)
+ if (get_pk11_data(AlgId, &keytype, &mechtype, NULL, 0))
return (KMF_ERR_BAD_PARAMETER);
- mechanism.mechanism = pAlgMap->pkcs_mechanism;
+ mechanism.mechanism = mechtype;
mechanism.pParameter = NULL;
mechanism.ulParameterLen = 0;
@@ -2390,6 +2609,64 @@ ret1:
return (rv);
}
+static KMF_RETURN
+get_raw_ec(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_EC_KEY *rawec)
+{
+ KMF_RETURN rv = KMF_OK;
+ CK_RV ckrv;
+ CK_SESSION_HANDLE sess = kmfh->pk11handle;
+ CK_ATTRIBUTE ec_attrs[2] = {
+ { CKA_EC_PARAMS, NULL, 0},
+ { CKA_VALUE, NULL, 0}
+ };
+ CK_ULONG count = sizeof (ec_attrs) / sizeof (CK_ATTRIBUTE);
+ int i;
+
+ if ((ckrv = C_GetAttributeValue(sess, obj,
+ ec_attrs, 2)) != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+
+ /* Tell the caller know why the key data cannot be retrieved. */
+ if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
+ return (KMF_ERR_SENSITIVE_KEY);
+ else if (ckrv == CKR_KEY_UNEXTRACTABLE)
+ return (KMF_ERR_UNEXTRACTABLE_KEY);
+ return (KMF_ERR_INTERNAL);
+ }
+ for (i = 0; i < count; i++) {
+ if (ec_attrs[i].ulValueLen == (CK_ULONG)-1 ||
+ ec_attrs[i].ulValueLen == 0) {
+ ec_attrs[i].ulValueLen = 0;
+ continue;
+ }
+ if ((ec_attrs[i].pValue =
+ malloc(ec_attrs[i].ulValueLen)) == NULL) {
+ rv = KMF_ERR_MEMORY;
+ goto end;
+ }
+ }
+ if ((ckrv = C_GetAttributeValue(sess, obj,
+ ec_attrs, count)) != CKR_OK) {
+ SET_ERROR(kmfh, ckrv);
+ rv = KMF_ERR_INTERNAL;
+ goto end;
+ }
+
+ rawec->params.Data = ec_attrs[0].pValue;
+ rawec->params.Length = ec_attrs[0].ulValueLen;
+ rawec->value.val = ec_attrs[1].pValue;
+ rawec->value.len = ec_attrs[1].ulValueLen;
+
+end:
+ if (rv != KMF_OK) {
+ for (i = 0; i < count; i++) {
+ if (ec_attrs[i].pValue != NULL)
+ free(ec_attrs[i].pValue);
+ }
+ (void) memset(rawec, 0, sizeof (KMF_RAW_EC_KEY));
+ }
+ return (rv);
+}
static KMF_RETURN
get_raw_dsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_DSA_KEY *rawdsa)
@@ -2544,6 +2821,9 @@ keyObj2RawKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *inkey,
rkey->not_extractable = B_TRUE;
rv = KMF_OK;
}
+ } else if (inkey->keyalg == KMF_ECDSA) {
+ rv = get_raw_ec(kmfh, (CK_OBJECT_HANDLE)inkey->keyp,
+ &rkey->rawdata.ec);
} else {
rv = KMF_ERR_BAD_PARAMETER;
}
@@ -2569,6 +2849,9 @@ kmf2pk11keytype(KMF_KEY_ALG keyalg, CK_KEY_TYPE *type)
case KMF_DSA:
*type = CKK_DSA;
break;
+ case KMF_ECDSA:
+ *type = CKK_EC;
+ break;
case KMF_AES:
*type = CKK_AES;
break;
@@ -2802,6 +3085,8 @@ KMFPK11_FindKey(KMF_HANDLE_T handle,
keys[n].keyalg = KMF_RSA;
} else if (keytype == CKK_DSA) {
keys[n].keyalg = KMF_DSA;
+ } else if (keytype == CKK_EC) {
+ keys[n].keyalg = KMF_ECDSA;
} else if (keytype == CKK_AES) {
keys[n].keyalg = KMF_AES;
keys[n].keyclass =
@@ -2936,6 +3221,8 @@ store_raw_key(KMF_HANDLE_T handle,
keytype = CKK_RSA;
else if (rawkey->keytype == KMF_DSA)
keytype = CKK_DSA;
+ else if (rawkey->keytype == KMF_ECDSA)
+ keytype = CKK_EC;
else
return (KMF_ERR_BAD_PARAMETER);
@@ -2960,7 +3247,8 @@ store_raw_key(KMF_HANDLE_T handle,
SETATTR(templ, i, CKA_KEY_TYPE, &keytype, sizeof (keytype)); i++;
SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
- SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
+ if (keytype != CKK_EC)
+ SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr);
if (cert != NULL) {
@@ -3107,7 +3395,7 @@ store_raw_key(KMF_HANDLE_T handle,
rawkey->rawdata.rsa.coef.len);
i++;
}
- } else {
+ } else if (keytype == CKK_DSA) {
SETATTR(templ, i, CKA_PRIME,
rawkey->rawdata.dsa.prime.val,
rawkey->rawdata.dsa.prime.len);
@@ -3124,6 +3412,19 @@ store_raw_key(KMF_HANDLE_T handle,
rawkey->rawdata.dsa.value.val,
rawkey->rawdata.dsa.value.len);
i++;
+ } else if (keytype == CKK_EC) {
+ SETATTR(templ, i, CKA_SIGN, &cktrue, sizeof (cktrue));
+ i++;
+ SETATTR(templ, i, CKA_DERIVE, &cktrue, sizeof (cktrue));
+ i++;
+ SETATTR(templ, i, CKA_VALUE,
+ rawkey->rawdata.ec.value.val,
+ rawkey->rawdata.ec.value.len);
+ i++;
+ SETATTR(templ, i, CKA_EC_PARAMS,
+ rawkey->rawdata.ec.params.Data,
+ rawkey->rawdata.ec.params.Length);
+ i++;
}
ckrv = C_CreateObject(kmfh->pk11handle, templ, i, &keyobj);
@@ -3525,176 +3826,6 @@ end:
}
static KMF_RETURN
-create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech,
- CK_FLAGS wanted_flags)
-{
- CK_RV rv;
- KMF_RETURN kmf_rv = KMF_OK;
- CK_SLOT_ID_PTR pSlotList;
- CK_ULONG pulCount;
- CK_MECHANISM_INFO info;
- int i;
-
- rv = C_Initialize(NULL);
- if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
- kmf_rv = KMF_ERR_UNINITIALIZED;
- goto out;
- }
-
- rv = C_GetSlotList(0, NULL, &pulCount);
- if (rv != CKR_OK) {
- kmf_rv = KMF_ERR_UNINITIALIZED;
- goto out;
- }
-
- pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID));
- if (pSlotList == NULL) {
- kmf_rv = KMF_ERR_MEMORY;
- goto out;
- }
-
- rv = C_GetSlotList(0, pSlotList, &pulCount);
- if (rv != CKR_OK) {
- kmf_rv = KMF_ERR_UNINITIALIZED;
- goto out;
- }
-
- for (i = 0; i < pulCount; i++) {
- rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info);
- if (rv == CKR_OK && (info.flags & wanted_flags))
- break;
- }
- if (i < pulCount) {
- rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION,
- NULL, NULL, sessionp);
-
- if (rv != CKR_OK) {
- kmf_rv = KMF_ERR_UNINITIALIZED;
- }
- } else {
- kmf_rv = KMF_ERR_UNINITIALIZED;
- }
-
-out:
- if (pSlotList != NULL)
- free(pSlotList);
- return (kmf_rv);
-
-}
-static KMF_RETURN
-verify_data(KMF_HANDLE_T handle,
- KMF_ALGORITHM_INDEX AlgorithmId,
- KMF_X509_SPKI *keyp,
- KMF_DATA *data,
- KMF_DATA *signed_data)
-{
- KMF_RETURN ret;
- PKCS_ALGORITHM_MAP *pAlgMap = NULL;
- CK_RV ckRv;
- CK_MECHANISM ckMechanism;
- CK_OBJECT_HANDLE ckKeyHandle;
- KMF_BOOL bTempKey;
- KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
- CK_SESSION_HANDLE ckSession = NULL;
-
- if (AlgorithmId == KMF_ALGID_NONE)
- return (KMF_ERR_BAD_ALGORITHM);
-
- pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE,
- AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId));
-
- if (!pAlgMap)
- return (KMF_ERR_BAD_ALGORITHM);
-
- ret = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism,
- CKF_VERIFY);
- if (ret != KMF_OK)
- return (ret);
-
- /* Fetch the verifying key */
- ret = PKCS_AcquirePublicKeyHandle(ckSession, keyp,
- pAlgMap->key_type, &ckKeyHandle, &bTempKey);
-
- if (ret != KMF_OK) {
- return (ret);
- }
-
- ckMechanism.mechanism = pAlgMap->pkcs_mechanism;
- ckMechanism.pParameter = NULL;
- ckMechanism.ulParameterLen = 0;
-
- ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle);
- if (ckRv != CKR_OK) {
- if (bTempKey)
- (void) C_DestroyObject(ckSession, ckKeyHandle);
- SET_ERROR(kmfh, ckRv);
- ret = KMF_ERR_INTERNAL;
- goto cleanup;
- }
-
- ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data,
- (CK_ULONG)data->Length, (CK_BYTE *)signed_data->Data,
- (CK_ULONG)signed_data->Length);
-
- if (ckRv != CKR_OK) {
- SET_ERROR(kmfh, ckRv);
- ret = KMF_ERR_INTERNAL;
- }
-
-cleanup:
- if (bTempKey)
- (void) C_DestroyObject(ckSession, ckKeyHandle);
-
- (void) C_CloseSession(ckSession);
-
- return (ret);
-}
-
-KMF_RETURN
-KMFPK11_VerifyDataWithCert(KMF_HANDLE_T handle,
- KMF_ALGORITHM_INDEX algid, KMF_DATA *indata,
- KMF_DATA *insig, KMF_DATA *SignerCertData)
-{
- KMF_RETURN ret = KMF_OK;
- KMF_X509_CERTIFICATE *SignerCert = NULL;
- KMF_X509_SPKI *pubkey;
-
- if (handle == NULL || indata == NULL ||
- indata->Data == NULL || indata->Length == 0 ||
- insig == NULL|| insig->Data == NULL || insig->Length == 0 ||
- SignerCertData == NULL || SignerCertData->Data == NULL ||
- SignerCertData->Length == 0)
- return (KMF_ERR_BAD_PARAMETER);
-
- /* Decode the signer cert so we can get the SPKI data */
- ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert);
- if (ret != KMF_OK)
- goto cleanup;
-
- /* Get the public key info from the signer certificate */
- pubkey = &SignerCert->certificate.subjectPublicKeyInfo;
-
- /* If no algorithm specified, use the certs signature algorithm */
- if (algid == KMF_ALGID_NONE) {
- algid = x509_algoid_to_algid(CERT_ALG_OID(SignerCert));
- }
-
- if (algid == KMF_ALGID_NONE) {
- ret = KMF_ERR_BAD_ALGORITHM;
- } else {
- ret = verify_data(handle, algid, pubkey, indata, insig);
- }
-
-cleanup:
- if (SignerCert) {
- kmf_free_signed_cert(SignerCert);
- free(SignerCert);
- }
-
- return (ret);
-}
-
-static KMF_RETURN
create_generic_secret_key(KMF_HANDLE_T handle,
int numattr, KMF_ATTRIBUTE *attrlist, CK_OBJECT_HANDLE *key)
{