diff options
author | Wyllys Ingersoll <wyllys.ingersoll@sun.com> | 2010-03-22 13:57:47 -0700 |
---|---|---|
committer | Wyllys Ingersoll <wyllys.ingersoll@sun.com> | 2010-03-22 13:57:47 -0700 |
commit | e65e5c2d2f32a99e8c5f740cabae9075dab03ce7 (patch) | |
tree | 09b70c15a705c7de105b96d1c7c0057ebc13b9e5 | |
parent | c7facc54c4abed9e554ff80225311e6b7048d3c9 (diff) | |
download | illumos-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
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) { |