diff options
author | wyllys <none@none> | 2007-11-28 14:21:48 -0800 |
---|---|---|
committer | wyllys <none@none> | 2007-11-28 14:21:48 -0800 |
commit | 5b3e1433c6213363bcb6387e66fc84ee9ff21a5d (patch) | |
tree | 2492c64b0cae444183da692fbfc22b43ec8e091e | |
parent | 967072a15e834441c4b221b17b3859169a2c9af2 (diff) | |
download | illumos-joyent-5b3e1433c6213363bcb6387e66fc84ee9ff21a5d.tar.gz |
6620497 KMF does not build proper PKCS12 PDUs
6624214 kmf_get_cert_extn can leak memory
6629477 libkmf is crashed in OpenSSL_StoreKey if keytype is not KMF_RSA or KMF_DSA
-rw-r--r-- | usr/src/cmd/cmd-crypto/pktool/import.c | 113 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h | 8 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c | 87 | ||||
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c | 36 | ||||
-rw-r--r-- | usr/src/lib/libkmf/include/kmfapi.h | 2 | ||||
-rw-r--r-- | usr/src/lib/libkmf/include/kmftypes.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libkmf/libkmf/common/certgetsetop.c | 6 | ||||
-rw-r--r-- | usr/src/lib/libkmf/libkmf/common/certop.c | 4 | ||||
-rw-r--r-- | usr/src/lib/libkmf/libkmf/common/generalop.c | 5 | ||||
-rw-r--r-- | usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c | 1094 | ||||
-rw-r--r-- | usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c | 18 |
11 files changed, 964 insertions, 412 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/import.c b/usr/src/cmd/cmd-crypto/pktool/import.c index 3354d0a8f6..edcb62332f 100644 --- a/usr/src/cmd/cmd-crypto/pktool/import.c +++ b/usr/src/cmd/cmd-crypto/pktool/import.c @@ -45,19 +45,29 @@ #include <kmfapi.h> +#define NEW_ATTRLIST(a, n) \ +{ \ + a = (KMF_ATTRIBUTE *)malloc(n * sizeof (KMF_ATTRIBUTE)); \ + if (a == NULL) { \ + rv = KMF_ERR_MEMORY; \ + goto end; \ + } \ + (void) memset(a, 0, n * sizeof (KMF_ATTRIBUTE)); \ +} + static KMF_RETURN pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred, char *outfile, char *certfile, char *keyfile, char *dir, char *keydir, KMF_ENCODE_FORMAT outformat) { KMF_RETURN rv = KMF_OK; - KMF_DATA *certs = NULL; + KMF_X509_DER_CERT *certs = NULL; KMF_RAW_KEY_DATA *keys = NULL; int ncerts = 0; int nkeys = 0; int i; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; - KMF_ATTRIBUTE attrlist[16]; + KMF_ATTRIBUTE *attrlist = NULL; int numattr = 0; rv = kmf_import_objects(kmfhandle, outfile, cred, @@ -71,6 +81,8 @@ pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred, if (rv == KMF_OK && ncerts > 0) { char newcertfile[MAXPATHLEN]; + NEW_ATTRLIST(attrlist, (3 + (3 * ncerts))); + kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattr++; @@ -108,16 +120,25 @@ pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred, num++; } + if (certs[i].kmf_private.label != NULL) { + kmf_set_attr_at_index(attrlist, num, + KMF_CERT_LABEL_ATTR, + certs[i].kmf_private.label, + strlen(certs[i].kmf_private.label)); + num++; + } kmf_set_attr_at_index(attrlist, num, - KMF_CERT_DATA_ATTR, &certs[i], sizeof (KMF_DATA)); + KMF_CERT_DATA_ATTR, &certs[i].certificate, + sizeof (KMF_DATA)); num++; rv = kmf_store_cert(kmfhandle, num, attrlist); } + free(attrlist); } if (rv == KMF_OK && nkeys > 0) { char newkeyfile[MAXPATHLEN]; - numattr = 0; + NEW_ATTRLIST(attrlist, (4 + (4 * nkeys))); kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, @@ -162,10 +183,12 @@ pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred, num++; } - kmf_set_attr_at_index(attrlist, num, - KMF_CERT_DATA_ATTR, &certs[i], - sizeof (KMF_DATA)); - num++; + if (i < ncerts) { + kmf_set_attr_at_index(attrlist, num, + KMF_CERT_DATA_ATTR, &certs[i], + sizeof (KMF_CERT_DATA_ATTR)); + num++; + } kmf_set_attr_at_index(attrlist, num, KMF_RAW_KEY_ATTR, &keys[i], @@ -174,13 +197,15 @@ pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred, rv = kmf_store_key(kmfhandle, num, attrlist); } + free(attrlist); } +end: /* * Cleanup memory. */ if (certs) { for (i = 0; i < ncerts; i++) - kmf_free_data(&certs[i]); + kmf_free_kmf_cert(kmfhandle, &certs[i]); free(certs); } if (keys) { @@ -202,13 +227,13 @@ pk_import_pk12_nss( char *nickname, char *trustflags, char *filename) { KMF_RETURN rv = KMF_OK; - KMF_DATA *certs = NULL; + KMF_X509_DER_CERT *certs = NULL; KMF_RAW_KEY_DATA *keys = NULL; int ncerts = 0; int nkeys = 0; int i; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; - KMF_ATTRIBUTE attrlist[16]; + KMF_ATTRIBUTE *attrlist = NULL; int numattr = 0; rv = configure_nss(kmfhandle, dir, prefix); @@ -223,6 +248,8 @@ pk_import_pk12_nss( "key(s) in %s\n"), ncerts, nkeys, filename); if (rv == KMF_OK) { + NEW_ATTRLIST(attrlist, (3 + (2 * ncerts))); + kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattr++; @@ -244,7 +271,13 @@ pk_import_pk12_nss( for (i = 0; rv == KMF_OK && i < ncerts; i++) { int num = numattr; - if (i == 0 && nickname != NULL) { + if (certs[i].kmf_private.label != NULL) { + kmf_set_attr_at_index(attrlist, num, + KMF_CERT_LABEL_ATTR, + certs[i].kmf_private.label, + strlen(certs[i].kmf_private.label)); + num++; + } else if (i == 0 && nickname != NULL) { kmf_set_attr_at_index(attrlist, num, KMF_CERT_LABEL_ATTR, nickname, strlen(nickname)); @@ -252,10 +285,13 @@ pk_import_pk12_nss( } kmf_set_attr_at_index(attrlist, num, - KMF_CERT_DATA_ATTR, &certs[i], sizeof (KMF_DATA)); + KMF_CERT_DATA_ATTR, + &certs[i].certificate, sizeof (KMF_DATA)); num++; rv = kmf_store_cert(kmfhandle, num, attrlist); } + free(attrlist); + attrlist = NULL; if (rv != KMF_OK) { display_error(kmfhandle, rv, gettext("Error storing certificate in NSS token")); @@ -264,6 +300,7 @@ pk_import_pk12_nss( if (rv == KMF_OK) { numattr = 0; + NEW_ATTRLIST(attrlist, (4 + (2 * nkeys))); kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, @@ -295,10 +332,12 @@ pk_import_pk12_nss( for (i = 0; i < nkeys; i++) { int num = numattr; - kmf_set_attr_at_index(attrlist, num, - KMF_CERT_DATA_ATTR, &certs[i], - sizeof (KMF_DATA)); - num++; + if (i < ncerts) { + kmf_set_attr_at_index(attrlist, num, + KMF_CERT_DATA_ATTR, &certs[i], + sizeof (KMF_DATA)); + num++; + } kmf_set_attr_at_index(attrlist, num, KMF_RAW_KEY_ATTR, &keys[i], @@ -307,14 +346,16 @@ pk_import_pk12_nss( rv = kmf_store_key(kmfhandle, num, attrlist); } + free(attrlist); } +end: /* * Cleanup memory. */ if (certs) { for (i = 0; i < ncerts; i++) - kmf_free_data(&certs[i]); + kmf_free_kmf_cert(kmfhandle, &certs[i]); free(certs); } if (keys) { @@ -455,13 +496,13 @@ pk_import_pk12_pk11( char *filename) { KMF_RETURN rv = KMF_OK; - KMF_DATA *certs = NULL; + KMF_X509_DER_CERT *certs = NULL; KMF_RAW_KEY_DATA *keys = NULL; int ncerts = 0; int nkeys = 0; int i; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; - KMF_ATTRIBUTE attrlist[16]; + KMF_ATTRIBUTE *attrlist = NULL; int numattr = 0; rv = select_token(kmfhandle, token_spec, FALSE); @@ -474,6 +515,7 @@ pk_import_pk12_pk11( &certs, &ncerts, &keys, &nkeys); if (rv == KMF_OK) { + NEW_ATTRLIST(attrlist, (3 + (2 * nkeys))); kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, @@ -498,10 +540,12 @@ pk_import_pk12_pk11( for (i = 0; i < nkeys; i++) { int num = numattr; - kmf_set_attr_at_index(attrlist, num, - KMF_CERT_DATA_ATTR, &certs[i], - sizeof (KMF_DATA)); - num++; + if (i < ncerts) { + kmf_set_attr_at_index(attrlist, num, + KMF_CERT_DATA_ATTR, &certs[i].certificate, + sizeof (KMF_DATA)); + num++; + } kmf_set_attr_at_index(attrlist, num, KMF_RAW_KEY_ATTR, &keys[i], @@ -511,40 +555,51 @@ pk_import_pk12_pk11( rv = kmf_store_key(kmfhandle, num, attrlist); } + free(attrlist); } if (rv == KMF_OK) { + numattr = 0; + NEW_ATTRLIST(attrlist, (1 + (2 * ncerts))); (void) printf(gettext("Found %d certificate(s) and %d " "key(s) in %s\n"), ncerts, nkeys, filename); - numattr = 0; + kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); numattr++; for (i = 0; rv == KMF_OK && i < ncerts; i++) { int num = numattr; - - if (i == 0 && label != NULL) { + if (certs[i].kmf_private.label != NULL) { + kmf_set_attr_at_index(attrlist, num, + KMF_CERT_LABEL_ATTR, + certs[i].kmf_private.label, + strlen(certs[i].kmf_private.label)); + num++; + } else if (i == 0 && label != NULL) { kmf_set_attr_at_index(attrlist, num, KMF_CERT_LABEL_ATTR, label, strlen(label)); num++; } kmf_set_attr_at_index(attrlist, num, - KMF_CERT_DATA_ATTR, &certs[i], sizeof (KMF_DATA)); + KMF_CERT_DATA_ATTR, &certs[i].certificate, + sizeof (KMF_DATA)); num++; rv = kmf_store_cert(kmfhandle, num, attrlist); } + free(attrlist); } +end: /* * Cleanup memory. */ if (certs) { for (i = 0; i < ncerts; i++) - kmf_free_data(&certs[i]); + kmf_free_kmf_cert(kmfhandle, &certs[i]); free(certs); } if (keys) { diff --git a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h index a5fc30e1b3..a9f4ef22ac 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h @@ -61,11 +61,11 @@ extern int do_delete(int argc, char *argv[]); extern void usage_create(boolean_t do_print); extern void usage_delete(boolean_t do_print); -extern int PEM_get_rsa_key_certs(const char *, - char *, KMF_RAW_KEY_DATA **, KMF_DATA **); +extern int PEM_get_rsa_key_certs(KMF_HANDLE_T, const char *, + char *, KMF_RAW_KEY_DATA **, KMF_X509_DER_CERT **); -extern int PKCS12_get_rsa_key_certs(const char *, - const char *, KMF_RAW_KEY_DATA **, KMF_DATA **); +extern int PKCS12_get_rsa_key_certs(KMF_HANDLE_T, const char *, + const char *, KMF_RAW_KEY_DATA **, KMF_X509_DER_CERT **); extern int get_passphrase(const char *password_file, char *buf, int buf_size); extern int kssl_send_command(char *buf, int cmd); diff --git a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c index 670fea791c..bf1de6fadc 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c @@ -89,7 +89,8 @@ usage_create(boolean_t do_print) */ static kssl_params_t * kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts, - KMF_DATA *certs, int *paramsize, char *token_label, KMF_DATA *idstr, + KMF_X509_DER_CERT *certs, int *paramsize, + char *token_label, KMF_DATA *idstr, KMF_CREDENTIAL *creds) { int i, tcsize; @@ -128,7 +129,7 @@ kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts, } tcsize = 0; for (i = 0; i < ncerts; i++) - tcsize += certs[i].Length; + tcsize += certs[i].certificate.Length; bufsize = sizeof (kssl_params_t); bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t))); @@ -271,7 +272,7 @@ kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts, /* First, an array of certificate sizes */ for (i = 0; i < ncerts; i++) { - uint32_t certsz = (uint32_t)certs[i].Length; + uint32_t certsz = (uint32_t)certs[i].certificate.Length; char *p = buf + (i * sizeof (uint32_t)); bcopy(&certsz, p, sizeof (uint32_t)); } @@ -283,8 +284,9 @@ kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts, /* Now add the certificate data (ASN.1 DER encoded) */ for (i = 0; i < ncerts; i++) { - bcopy(certs[i].Data, buf, certs[i].Length); - buf += certs[i].Length; + bcopy(certs[i].certificate.Data, buf, + certs[i].certificate.Length); + buf += certs[i].certificate.Length; } *paramsize = bufsize; @@ -571,11 +573,11 @@ out: } static kssl_params_t * -load_from_pkcs11(const char *token_label, const char *password_file, +load_from_pkcs11(KMF_HANDLE_T kmfh, + const char *token_label, const char *password_file, const char *certname, int *bufsize) { KMF_RETURN rv; - KMF_HANDLE_T kmfh; KMF_X509_DER_CERT cert; KMF_KEY_HANDLE key, rawkey; KMF_CREDENTIAL creds; @@ -593,11 +595,6 @@ load_from_pkcs11(const char *token_label, const char *password_file, boolean_t false = B_FALSE; boolean_t true = B_TRUE; - rv = kmf_initialize(&kmfh, NULL, NULL); - if (rv != KMF_OK) { - REPORT_KMF_ERROR(rv, "Error initializing KMF", err); - return (0); - } if (get_passphrase(password_file, password_buf, sizeof (password_buf)) <= 0) { perror("Unable to read passphrase"); @@ -745,8 +742,7 @@ load_from_pkcs11(const char *token_label, const char *password_file, if (rv == KMF_OK) kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp, - 1, &cert.certificate, bufsize, - (char *)token_label, &iddata, &creds); + 1, &cert, bufsize, (char *)token_label, &iddata, &creds); done: if (ncerts != 0) kmf_free_kmf_cert(kmfh, &cert); @@ -755,9 +751,6 @@ done: if (idstr) free(idstr); - if (kmfh != NULL) - (void) kmf_finalize(kmfh); - return (kssl_params); } @@ -767,7 +760,8 @@ done: * Load a chain of certificates from a PEM file. */ static kssl_params_t * -add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) +add_cacerts(KMF_HANDLE_T kmfh, + kssl_params_t *old_params, const char *cacert_chain_file) { int i, newlen; uint32_t certlen = 0, ncerts; @@ -775,7 +769,6 @@ add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) KMF_RETURN rv; KMF_X509_DER_CERT *certs = NULL; kssl_params_t *kssl_params; - KMF_HANDLE_T kmfh; char *err = NULL; int numattr = 0; KMF_ATTRIBUTE attrlist[16]; @@ -783,11 +776,6 @@ add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) kstype = KMF_KEYSTORE_OPENSSL; - rv = kmf_initialize(&kmfh, NULL, NULL); - if (rv != KMF_OK) { - REPORT_KMF_ERROR(rv, "Error initializing KMF", err); - return (0); - } ncerts = 0; kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (KMF_KEYSTORE_TYPE)); @@ -804,14 +792,12 @@ add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) rv = kmf_find_cert(kmfh, numattr, attrlist); if (rv != KMF_OK) { REPORT_KMF_ERROR(rv, "Error finding CA certificates", err); - (void) KMF_Finalize(kmfh); return (0); } certs = (KMF_X509_DER_CERT *)malloc(ncerts * sizeof (KMF_X509_DER_CERT)); if (certs == NULL) { (void) fprintf(stderr, "memory allocation error.\n"); - (void) KMF_Finalize(kmfh); return (NULL); } bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT)); @@ -822,8 +808,6 @@ add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) numattr++; rv = kmf_find_cert(kmfh, numattr, attrlist); - (void) kmf_finalize(kmfh); - if (rv != KMF_OK || ncerts == 0) { bzero(old_params, old_params->kssl_params_size); free(old_params); @@ -881,15 +865,16 @@ add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) * Find a key and certificate(s) from a single PEM file. */ static kssl_params_t * -load_from_pem(const char *filename, const char *password_file, int *paramsize) +load_from_pem(KMF_HANDLE_T kmfh, const char *filename, + const char *password_file, int *paramsize) { int ncerts = 0, i; kssl_params_t *kssl_params; KMF_RAW_KEY_DATA *rsa = NULL; - KMF_DATA *certs = NULL; + KMF_X509_DER_CERT *certs = NULL; - ncerts = PEM_get_rsa_key_certs(filename, (char *)password_file, - &rsa, &certs); + ncerts = PEM_get_rsa_key_certs(kmfh, + filename, (char *)password_file, &rsa, &certs); if (rsa == NULL || certs == NULL || ncerts == 0) { return (NULL); } @@ -901,7 +886,7 @@ load_from_pem(const char *filename, const char *password_file, int *paramsize) NULL, NULL); for (i = 0; i < ncerts; i++) - kmf_free_data(&certs[i]); + kmf_free_kmf_cert(kmfh, &certs[i]); free(certs); kmf_free_raw_key(rsa); @@ -912,15 +897,15 @@ load_from_pem(const char *filename, const char *password_file, int *paramsize) * Load a raw key and certificate(s) from a PKCS#12 file. */ static kssl_params_t * -load_from_pkcs12(const char *filename, const char *password_file, - int *paramsize) +load_from_pkcs12(KMF_HANDLE_T kmfh, const char *filename, + const char *password_file, int *paramsize) { KMF_RAW_KEY_DATA *rsa = NULL; kssl_params_t *kssl_params; - KMF_DATA *certs = NULL; + KMF_X509_DER_CERT *certs = NULL; int ncerts = 0, i; - ncerts = PKCS12_get_rsa_key_certs(filename, + ncerts = PKCS12_get_rsa_key_certs(kmfh, filename, password_file, &rsa, &certs); if (certs == NULL || ncerts == 0) { @@ -936,7 +921,7 @@ load_from_pkcs12(const char *filename, const char *password_file, NULL, NULL); for (i = 0; i < ncerts; i++) - kmf_free_data(&certs[i]); + kmf_free_kmf_cert(kmfh, &certs[i]); free(certs); kmf_free_raw_key(rsa); @@ -1057,6 +1042,9 @@ do_create(int argc, char *argv[]) int pcnt; kssl_params_t *kssl_params; int bufsize; + KMF_HANDLE_T kmfh = NULL; + KMF_RETURN rv = KMF_OK; + char *err = NULL; argc -= 1; argv += 1; @@ -1135,6 +1123,12 @@ do_create(int argc, char *argv[]) goto err; } + rv = kmf_initialize(&kmfh, NULL, NULL); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error initializing KMF", err); + return (0); + } + if (strcmp(format, "pkcs11") == 0) { if (token_label == NULL || certname == NULL) { goto err; @@ -1147,19 +1141,19 @@ do_create(int argc, char *argv[]) getenv("SOFTTOKEN_DIR")); } } - kssl_params = load_from_pkcs11( + kssl_params = load_from_pkcs11(kmfh, token_label, password_file, certname, &bufsize); } else if (strcmp(format, "pkcs12") == 0) { if (cert_key_file == NULL) { goto err; } - kssl_params = load_from_pkcs12( + kssl_params = load_from_pkcs12(kmfh, cert_key_file, password_file, &bufsize); } else if (strcmp(format, "pem") == 0) { if (cert_key_file == NULL) { goto err; } - kssl_params = load_from_pem( + kssl_params = load_from_pem(kmfh, cert_key_file, password_file, &bufsize); } else { (void) fprintf(stderr, "Unsupported cert format: %s\n", format); @@ -1167,6 +1161,7 @@ do_create(int argc, char *argv[]) } if (kssl_params == NULL) { + (void) kmf_finalize(kmfh); return (FAILURE); } @@ -1182,8 +1177,11 @@ do_create(int argc, char *argv[]) kssl_params->kssl_session_cache_size = scache_size; if (cacert_chain_file != NULL) { - kssl_params = add_cacerts(kssl_params, cacert_chain_file); + kssl_params = add_cacerts(kmfh, kssl_params, cacert_chain_file); if (kssl_params == NULL) { + bzero(kssl_params, bufsize); + free(kssl_params); + (void) kmf_finalize(kmfh); return (FAILURE); } } @@ -1195,6 +1193,9 @@ do_create(int argc, char *argv[]) err = kssl_params->kssl_token.ck_rv; (void) fprintf(stderr, "Error loading cert and key: 0x%x\n", err); + bzero(kssl_params, bufsize); + free(kssl_params); + (void) kmf_finalize(kmfh); return (FAILURE); } @@ -1203,9 +1204,11 @@ do_create(int argc, char *argv[]) bzero(kssl_params, bufsize); free(kssl_params); + (void) kmf_finalize(kmfh); return (SUCCESS); err: usage_create(B_TRUE); + (void) kmf_finalize(kmfh); return (SMF_EXIT_ERR_CONFIG); } diff --git a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c index 42fca362e3..dae4d83a2e 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c @@ -39,24 +39,18 @@ * in plaintext in the given "password_file" parameter. */ int -PKCS12_get_rsa_key_certs(const char *filename, const char *password_file, - KMF_RAW_KEY_DATA **rsa, KMF_DATA **certs) +PKCS12_get_rsa_key_certs(KMF_HANDLE_T kmfh, + const char *filename, const char *password_file, + KMF_RAW_KEY_DATA **rsa, KMF_X509_DER_CERT **certs) { char password_buf[1024]; - KMF_HANDLE_T kmfh; KMF_RETURN rv = KMF_OK; KMF_CREDENTIAL pk12cred; - KMF_DATA *tcerts; + KMF_X509_DER_CERT *tcerts; KMF_RAW_KEY_DATA *keys; int ncerts, nkeys; char *err = NULL; - rv = kmf_initialize(&kmfh, NULL, NULL); - if (rv != KMF_OK) { - REPORT_KMF_ERROR(rv, "Error initializing KMF", err); - return (0); - } - tcerts = NULL; keys = NULL; ncerts = 0; @@ -81,7 +75,7 @@ done: int i; if (tcerts != NULL) { for (i = 0; i < ncerts; i++) - kmf_free_data(&tcerts[i]); + kmf_free_kmf_cert(kmfh, &tcerts[i]); free(tcerts); } tcerts = NULL; @@ -96,8 +90,6 @@ done: *certs = tcerts; *rsa = keys; - (void) kmf_finalize(kmfh); - return (ncerts); } @@ -107,24 +99,18 @@ done: * be present in the file. */ int -PEM_get_rsa_key_certs(const char *filename, char *password_file, - KMF_RAW_KEY_DATA **rsa, KMF_DATA **certs) +PEM_get_rsa_key_certs(KMF_HANDLE_T kmfh, + const char *filename, char *password_file, + KMF_RAW_KEY_DATA **rsa, KMF_X509_DER_CERT **certs) { - KMF_HANDLE_T kmfh; KMF_RETURN rv = KMF_OK; KMF_CREDENTIAL creds; - KMF_DATA *tcerts; + KMF_X509_DER_CERT *tcerts; KMF_RAW_KEY_DATA *keys; int ncerts, nkeys; char *err = NULL; char password_buf[1024]; - rv = kmf_initialize(&kmfh, NULL, NULL); - if (rv != KMF_OK) { - REPORT_KMF_ERROR(rv, "Error initializing KMF", err); - return (0); - } - tcerts = NULL; keys = NULL; ncerts = 0; @@ -149,7 +135,7 @@ done: int i; if (tcerts != NULL) { for (i = 0; i < ncerts; i++) - kmf_free_data(&tcerts[i]); + kmf_free_kmf_cert(kmfh, &tcerts[i]); free(tcerts); } tcerts = NULL; @@ -166,7 +152,5 @@ done: if (rsa != NULL) *rsa = keys; - (void) kmf_finalize(kmfh); - return (ncerts); } diff --git a/usr/src/lib/libkmf/include/kmfapi.h b/usr/src/lib/libkmf/include/kmfapi.h index 4826248ddb..ad732f6ffd 100644 --- a/usr/src/lib/libkmf/include/kmfapi.h +++ b/usr/src/lib/libkmf/include/kmfapi.h @@ -245,7 +245,7 @@ extern KMF_RETURN kmf_build_pk12(KMF_HANDLE_T, int, KMF_X509_DER_CERT *, int, KMF_KEY_HANDLE *, KMF_CREDENTIAL *, char *); extern KMF_RETURN kmf_import_objects(KMF_HANDLE_T, char *, KMF_CREDENTIAL *, - KMF_DATA **, int *, KMF_RAW_KEY_DATA **, int *); + KMF_X509_DER_CERT **, int *, KMF_RAW_KEY_DATA **, int *); /* * OCSP operations diff --git a/usr/src/lib/libkmf/include/kmftypes.h b/usr/src/lib/libkmf/include/kmftypes.h index e820b68b13..211525f974 100644 --- a/usr/src/lib/libkmf/include/kmftypes.h +++ b/usr/src/lib/libkmf/include/kmftypes.h @@ -201,9 +201,10 @@ typedef struct { KMF_RAW_DSA_KEY dsa; KMF_RAW_SYM_KEY sym; }rawdata; + char *label; + KMF_DATA id; } KMF_RAW_KEY_DATA; - typedef struct { KMF_KEYSTORE_TYPE kstype; KMF_KEY_ALG keyalg; diff --git a/usr/src/lib/libkmf/libkmf/common/certgetsetop.c b/usr/src/lib/libkmf/libkmf/common/certgetsetop.c index 35dad63b69..1dcdb8aaa8 100644 --- a/usr/src/lib/libkmf/libkmf/common/certgetsetop.c +++ b/usr/src/lib/libkmf/libkmf/common/certgetsetop.c @@ -139,8 +139,9 @@ kmf_get_cert_extn(const KMF_DATA *certdata, if (ret != KMF_OK) return (ret); - if (cert->certificate.extensions.numberOfExtensions == 0) - return (KMF_ERR_EXTENSION_NOT_FOUND); + if (cert->certificate.extensions.numberOfExtensions == 0) { + goto end; + } (void) memset((void *)extdata, 0, sizeof (KMF_X509_EXTENSION)); for (i = 0; !found && @@ -152,6 +153,7 @@ kmf_get_cert_extn(const KMF_DATA *certdata, found++; } } +end: if (!found) ret = KMF_ERR_EXTENSION_NOT_FOUND; diff --git a/usr/src/lib/libkmf/libkmf/common/certop.c b/usr/src/lib/libkmf/libkmf/common/certop.c index b01dfc6204..4d5e151ce7 100644 --- a/usr/src/lib/libkmf/libkmf/common/certop.c +++ b/usr/src/lib/libkmf/libkmf/common/certop.c @@ -2680,13 +2680,13 @@ kmf_build_pk12(KMF_HANDLE_T handle, int numcerts, KMF_RETURN kmf_import_objects(KMF_HANDLE_T handle, char *filename, KMF_CREDENTIAL *cred, - KMF_DATA **certs, int *ncerts, + KMF_X509_DER_CERT **certs, int *ncerts, KMF_RAW_KEY_DATA **rawkeys, int *nkeys) { KMF_RETURN rv; KMF_PLUGIN *plugin; KMF_RETURN (*import_objects)(KMF_HANDLE *, char *, KMF_CREDENTIAL *, - KMF_DATA **, int *, KMF_RAW_KEY_DATA **, int *); + KMF_X509_DER_CERT **, int *, KMF_RAW_KEY_DATA **, int *); CLEAR_ERROR(handle, rv); if (rv != KMF_OK) diff --git a/usr/src/lib/libkmf/libkmf/common/generalop.c b/usr/src/lib/libkmf/libkmf/common/generalop.c index f41f9ec71f..1e2f2504a4 100644 --- a/usr/src/lib/libkmf/libkmf/common/generalop.c +++ b/usr/src/lib/libkmf/libkmf/common/generalop.c @@ -1225,6 +1225,11 @@ kmf_free_raw_key(KMF_RAW_KEY_DATA *key) free_raw_sym(&key->rawdata.sym); break; } + if (key->label) { + free(key->label); + key->label = NULL; + } + kmf_free_data(&key->id); } void 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 88ff83dbea..1e7a166065 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 @@ -132,12 +132,35 @@ static uchar_t G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, #define SET_SYS_ERROR(h, c) h->lasterr.kstype = -1; h->lasterr.errcode = c; +/* + * Declare some new macros for managing stacks of EVP_PKEYS, similar to + * what wanboot did. + */ +DECLARE_STACK_OF(EVP_PKEY) + +#define sk_EVP_PKEY_new_null() SKM_sk_new_null(EVP_PKEY) +#define sk_EVP_PKEY_free(st) SKM_sk_free(EVP_PKEY, (st)) +#define sk_EVP_PKEY_num(st) SKM_sk_num(EVP_PKEY, (st)) +#define sk_EVP_PKEY_value(st, i) SKM_sk_value(EVP_PKEY, (st), (i)) +#define sk_EVP_PKEY_push(st, val) SKM_sk_push(EVP_PKEY, (st), (val)) +#define sk_EVP_PKEY_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY, (st), \ + (free_func)) + mutex_t init_lock = DEFAULTMUTEX; static int ssl_initialized = 0; static BIO *bio_err = NULL; static int test_for_file(char *, mode_t); +static KMF_RETURN +openssl_parse_bag(PKCS12_SAFEBAG *, char *, int, + STACK_OF(EVP_PKEY) *, STACK_OF(X509) *); + +static KMF_RETURN +local_export_pk12(KMF_HANDLE_T, KMF_CREDENTIAL *, int, KMF_X509_DER_CERT *, + int, KMF_KEY_HANDLE *, char *); + +static KMF_RETURN set_pkey_attrib(EVP_PKEY *, ASN1_TYPE *, int); static KMF_RETURN extract_pem(KMF_HANDLE *, char *, char *, KMF_BIGINT *, char *, @@ -1389,6 +1412,9 @@ ssl_write_key(KMF_HANDLE *kmfh, KMF_ENCODE_FORMAT format, BIO *out, RSA *rsa; DSA *dsa; + if (pkey == NULL || out == NULL) + return (KMF_ERR_BAD_PARAMETER); + switch (format) { case KMF_FORMAT_ASN1: if (pkey->type == EVP_PKEY_RSA) { @@ -1865,8 +1891,10 @@ OpenSSL_DeleteKey(KMF_HANDLE_T handle, /* If the file exists, make sure it is a proper key. */ pkey = openssl_load_key(handle, key->keylabel); if (pkey == NULL) { - free(key->keylabel); - key->keylabel = NULL; + if (key->keylabel != NULL) { + free(key->keylabel); + key->keylabel = NULL; + } return (KMF_ERR_KEY_NOT_FOUND); } EVP_PKEY_free(pkey); @@ -2418,6 +2446,7 @@ static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) for (i = 0; i < sk_X509_num(certs); i++) { /*LINTED*/ X509 *x = sk_X509_value(certs, i); + /* Use pubkey_digest to get the key ID value */ (void) X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) return (x); @@ -2749,7 +2778,11 @@ fetch_key(KMF_HANDLE_T handle, char *path, key->keyclass = keyclass; key->keyp = (void *)pkey; key->israw = FALSE; - key->keylabel = path; + if (path != NULL && + ((key->keylabel = strdup(path)) == NULL)) { + EVP_PKEY_free(pkey); + return (KMF_ERR_MEMORY); + } } else { EVP_PKEY_free(pkey); pkey = NULL; @@ -2792,8 +2825,11 @@ fetch_key(KMF_HANDLE_T handle, char *path, key->kstype = KMF_KEYSTORE_OPENSSL; key->keyclass = keyclass; key->israw = TRUE; - key->keylabel = path; key->keyp = (void *)rkey; + if (path != NULL && + ((key->keylabel = strdup(path)) == NULL)) { + rv = KMF_ERR_MEMORY; + } } } out: @@ -2927,225 +2963,110 @@ OpenSSL_FindKey(KMF_HANDLE_T handle, goto out; \ } -static KMF_RETURN -write_pkcs12(KMF_HANDLE *kmfh, - BIO *bio, - KMF_CREDENTIAL *cred, - EVP_PKEY *pkey, - X509 *sslcert) +static int +add_alias_to_bag(PKCS12_SAFEBAG *bag, X509 *xcert) { - KMF_RETURN rv = KMF_OK; - STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; - PKCS12_SAFEBAG *bag = NULL; - PKCS7 *cert_authsafe = NULL; - PKCS8_PRIV_KEY_INFO *p8 = NULL; - PKCS7 *key_authsafe = NULL; - STACK_OF(PKCS7) *authsafe_stack = NULL; - PKCS12 *p12_elem = NULL; - char *lab = NULL; - int lab_len = 0; - unsigned char keyid[EVP_MAX_MD_SIZE]; - unsigned int keyidlen = 0; - - /* Must have at least a cert OR a key */ - if (sslcert == NULL && pkey == NULL) - return (KMF_ERR_BAD_PARAMETER); + if (xcert != NULL && xcert->aux != NULL && + xcert->aux->alias != NULL) { + if (PKCS12_add_friendlyname_asc(bag, + (const char *)xcert->aux->alias->data, + xcert->aux->alias->length) == 0) + return (0); + } + return (1); +} - (void) memset(keyid, 0, sizeof (keyid)); - /* - * Section 1: - * - * The first PKCS#12 container (safebag) will hold the certificates - * associated with this key. The result of this section is a - * PIN-encrypted PKCS#7 container (authsafe). If there are no - * certificates, there is no point in creating the "safebag" or the - * "authsafe" so we go to the next section. - */ - if (sslcert != NULL && pkey != NULL) { - if (X509_check_private_key(sslcert, pkey)) { - (void) X509_digest(sslcert, EVP_sha1(), keyid, - &keyidlen); - } else { - /* The key doesn't match the cert */ - HANDLE_PK12_ERROR - } - } +static PKCS7 * +add_cert_to_safe(X509 *sslcert, KMF_CREDENTIAL *cred, + uchar_t *keyid, unsigned int keyidlen) +{ + PKCS12_SAFEBAG *bag = NULL; + PKCS7 *cert_authsafe = NULL; + STACK_OF(PKCS12_SAFEBAG) *bag_stack; bag_stack = sk_PKCS12_SAFEBAG_new_null(); if (bag_stack == NULL) - return (KMF_ERR_MEMORY); + return (NULL); - if (sslcert != NULL) { - /* Convert cert from X509 struct to PKCS#12 bag */ - bag = PKCS12_x5092certbag(sslcert); - if (bag == NULL) { - HANDLE_PK12_ERROR - } + /* Convert cert from X509 struct to PKCS#12 bag */ + bag = PKCS12_x5092certbag(sslcert); + if (bag == NULL) { + goto out; + } - /* Add the key id to the certificate bag. */ - if (keyidlen > 0 && - !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { - HANDLE_PK12_ERROR - } + /* Add the key id to the certificate bag. */ + if (keyidlen > 0 && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { + goto out; + } - /* Pile it on the bag_stack. */ - if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { - HANDLE_PK12_ERROR - } -#if 0 - /* No support for CA certs yet */ - if (cacerts != NULL && ncacerts > 0) { - int i; - for (i = 0; i < ncacerts; i++) { - KMF_X509_DER_CERT *c = &cacerts[i]; - X509 *ca = NULL; - - uchar_t *p = (uchar_t *)c->certificate.Data; - ca = d2i_X509(NULL, &p, c->certificate.Length); - if (ca == NULL) { - HANDLE_PK12_ERROR - } - /* Convert CA cert to PKCS#12 bag. */ - bag = PKCS12_x5092certbag(ca); - if (bag == NULL) { - sk_PKCS12_SAFEBAG_pop_free(bag_stack, - PKCS12_SAFEBAG_free); - HANDLE_PK12_ERROR - } - /* Pile it onto the bag_stack. */ - if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { - HANDLE_PK12_ERROR - } - } - } -#endif - /* Turn bag_stack of certs into encrypted authsafe. */ - cert_authsafe = PKCS12_pack_p7encdata( - NID_pbe_WithSHA1And40BitRC2_CBC, - cred->cred, cred->credlen, NULL, 0, - PKCS12_DEFAULT_ITER, bag_stack); - - /* Clear away this bag_stack, we're done with it. */ - sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); - bag_stack = NULL; + if (!add_alias_to_bag(bag, sslcert)) + goto out; - if (cert_authsafe == NULL) { - HANDLE_PK12_ERROR - } + /* Pile it on the bag_stack. */ + if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { + goto out; } - /* - * Section 2: - * - * The second PKCS#12 container (safebag) will hold the private key - * that goes with the certificates above. The results of this section - * is an unencrypted PKCS#7 container (authsafe). If there is no - * private key, there is no point in creating the "safebag" or the - * "authsafe" so we go to the next section. - */ - if (pkey != NULL) { - p8 = EVP_PKEY2PKCS8(pkey); - if (p8 == NULL) { - HANDLE_PK12_ERROR - } - /* Put the shrouded key into a PKCS#12 bag. */ - bag = PKCS12_MAKE_SHKEYBAG( - NID_pbe_WithSHA1And3_Key_TripleDES_CBC, - cred->cred, cred->credlen, - NULL, 0, PKCS12_DEFAULT_ITER, p8); - - /* Clean up the PKCS#8 shrouded key, don't need it now. */ - PKCS8_PRIV_KEY_INFO_free(p8); - p8 = NULL; - - if (bag == NULL) { - HANDLE_PK12_ERROR - } - if (keyidlen && - !PKCS12_add_localkeyid(bag, keyid, keyidlen)) { - HANDLE_PK12_ERROR - } - if (lab != NULL) { - if (!PKCS12_add_friendlyname(bag, - (char *)lab, lab_len)) { - HANDLE_PK12_ERROR - } - } - /* Start a PKCS#12 safebag container for the private key. */ - bag_stack = sk_PKCS12_SAFEBAG_new_null(); - if (bag_stack == NULL) { - HANDLE_PK12_ERROR - } + /* Turn bag_stack of certs into encrypted authsafe. */ + cert_authsafe = PKCS12_pack_p7encdata( + NID_pbe_WithSHA1And40BitRC2_CBC, + cred->cred, cred->credlen, NULL, 0, + PKCS12_DEFAULT_ITER, bag_stack); - /* Pile on the private key on the bag_stack. */ - if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) { - HANDLE_PK12_ERROR - } - key_authsafe = PKCS12_pack_p7data(bag_stack); - - /* Clear away this bag_stack, we're done with it. */ +out: + if (bag_stack != NULL) sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); - bag_stack = NULL; - if (key_authsafe == NULL) { - HANDLE_PK12_ERROR - } - } - /* - * Section 3: - * - * This is where the two PKCS#7 containers, one for the certificates - * and one for the private key, are put together into a PKCS#12 - * element. This final PKCS#12 element is written to the export file. - */ + return (cert_authsafe); +} - /* Start a PKCS#7 stack. */ - authsafe_stack = sk_PKCS7_new_null(); - if (authsafe_stack == NULL) { - HANDLE_PK12_ERROR - } - if (key_authsafe != NULL) { - if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { - HANDLE_PK12_ERROR - } - } - if (cert_authsafe != NULL) { - if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { - HANDLE_PK12_ERROR - } - } - p12_elem = PKCS12_init(NID_pkcs7_data); - if (p12_elem == NULL) { - sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); - HANDLE_PK12_ERROR - } +static PKCS7 * +add_key_to_safe(EVP_PKEY *pkey, KMF_CREDENTIAL *cred, + uchar_t *keyid, unsigned int keyidlen, + char *label, int label_len) +{ + PKCS8_PRIV_KEY_INFO *p8 = NULL; + STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; + PKCS12_SAFEBAG *bag = NULL; + PKCS7 *key_authsafe = NULL; - /* Put the PKCS#7 stack into the PKCS#12 element. */ - if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { - HANDLE_PK12_ERROR + p8 = EVP_PKEY2PKCS8(pkey); + if (p8 == NULL) { + return (NULL); } - /* Clear away the PKCS#7 stack, we're done with it. */ - sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); - authsafe_stack = NULL; + /* Put the shrouded key into a PKCS#12 bag. */ + bag = PKCS12_MAKE_SHKEYBAG( + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + cred->cred, cred->credlen, + NULL, 0, PKCS12_DEFAULT_ITER, p8); - /* Set the integrity MAC on the PKCS#12 element. */ - if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, - NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { - HANDLE_PK12_ERROR - } + /* Clean up the PKCS#8 shrouded key, don't need it now. */ + PKCS8_PRIV_KEY_INFO_free(p8); + p8 = NULL; - /* Write the PKCS#12 element to the export file. */ - if (!i2d_PKCS12_bio(bio, p12_elem)) { - HANDLE_PK12_ERROR + if (bag == NULL) { + return (NULL); } + if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) + goto out; + if (label != NULL && !PKCS12_add_friendlyname(bag, label, label_len)) + goto out; + + /* Start a PKCS#12 safebag container for the private key. */ + bag_stack = sk_PKCS12_SAFEBAG_new_null(); + if (bag_stack == NULL) + goto out; + + /* Pile on the private key on the bag_stack. */ + if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) + goto out; + + key_authsafe = PKCS12_pack_p7data(bag_stack); - PKCS12_free(p12_elem); out: - if (rv != KMF_OK) { - /* Clear away this bag_stack, we're done with it. */ + if (bag_stack != NULL) sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); - sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); - } - return (rv); + bag_stack = NULL; + return (key_authsafe); } static EVP_PKEY * @@ -3246,8 +3167,95 @@ ImportRawDSAKey(KMF_RAW_DSA_KEY *key) return (newkey); } +static EVP_PKEY * +raw_key_to_pkey(KMF_KEY_HANDLE *key) +{ + EVP_PKEY *pkey = NULL; + KMF_RAW_KEY_DATA *rawkey; + ASN1_TYPE *attr = NULL; + KMF_RETURN ret; + + if (key == NULL || !key->israw) + return (NULL); + + rawkey = (KMF_RAW_KEY_DATA *)key->keyp; + if (rawkey->keytype == KMF_RSA) { + pkey = ImportRawRSAKey(&rawkey->rawdata.rsa); + } else if (rawkey->keytype == KMF_DSA) { + pkey = ImportRawDSAKey(&rawkey->rawdata.dsa); + } else { + /* wrong kind of key */ + return (NULL); + } + + if (rawkey->label != NULL) { + if ((attr = ASN1_TYPE_new()) == NULL) { + EVP_PKEY_free(pkey); + return (NULL); + } + attr->value.bmpstring = ASN1_STRING_type_new(V_ASN1_BMPSTRING); + (void) ASN1_STRING_set(attr->value.bmpstring, rawkey->label, + strlen(rawkey->label)); + attr->type = V_ASN1_BMPSTRING; + attr->value.ptr = (char *)attr->value.bmpstring; + ret = set_pkey_attrib(pkey, attr, NID_friendlyName); + if (ret != KMF_OK) { + EVP_PKEY_free(pkey); + ASN1_TYPE_free(attr); + return (NULL); + } + } + if (rawkey->id.Data != NULL) { + if ((attr = ASN1_TYPE_new()) == NULL) { + EVP_PKEY_free(pkey); + return (NULL); + } + attr->value.octet_string = + ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + attr->type = V_ASN1_OCTET_STRING; + (void) ASN1_STRING_set(attr->value.octet_string, + rawkey->id.Data, rawkey->id.Length); + attr->value.ptr = (char *)attr->value.octet_string; + ret = set_pkey_attrib(pkey, attr, NID_localKeyID); + if (ret != KMF_OK) { + EVP_PKEY_free(pkey); + ASN1_TYPE_free(attr); + return (NULL); + } + } + return (pkey); +} + +/* + * Search a list of private keys to find one that goes with the certificate. + */ +static EVP_PKEY * +find_matching_key(X509 *xcert, int numkeys, KMF_KEY_HANDLE *keylist) +{ + int i; + EVP_PKEY *pkey = NULL; + + if (numkeys == 0 || keylist == NULL || xcert == NULL) + return (NULL); + for (i = 0; i < numkeys; i++) { + if (keylist[i].israw) + pkey = raw_key_to_pkey(&keylist[i]); + else + pkey = (EVP_PKEY *)keylist[i].keyp; + if (pkey != NULL) { + if (X509_check_private_key(xcert, pkey)) { + return (pkey); + } else { + EVP_PKEY_free(pkey); + pkey = NULL; + } + } + } + return (pkey); +} + static KMF_RETURN -ExportPK12FromRawData(KMF_HANDLE_T handle, +local_export_pk12(KMF_HANDLE_T handle, KMF_CREDENTIAL *cred, int numcerts, KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, @@ -3256,10 +3264,15 @@ ExportPK12FromRawData(KMF_HANDLE_T handle, KMF_RETURN rv = KMF_OK; KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; BIO *bio = NULL; - X509 *xcert = NULL; - EVP_PKEY *pkey = NULL; + PKCS7 *cert_authsafe = NULL; + PKCS7 *key_authsafe = NULL; + STACK_OF(PKCS7) *authsafe_stack = NULL; + PKCS12 *p12_elem = NULL; int i; + if (numcerts == 0 && numkeys == 0) + return (KMF_ERR_BAD_PARAMETER); + /* * Open the output file. */ @@ -3269,41 +3282,134 @@ ExportPK12FromRawData(KMF_HANDLE_T handle, goto cleanup; } - if (numcerts > 0 && numkeys > 0) { + /* Start a PKCS#7 stack. */ + authsafe_stack = sk_PKCS7_new_null(); + if (authsafe_stack == NULL) { + rv = KMF_ERR_MEMORY; + goto cleanup; + } + if (numcerts > 0) { for (i = 0; rv == KMF_OK && i < numcerts; i++) { - KMF_RAW_KEY_DATA *key = NULL; const uchar_t *p = certlist[i].certificate.Data; long len = certlist[i].certificate.Length; - - if (i < numkeys) { - key = (KMF_RAW_KEY_DATA *)keylist[i].keyp; - - if (key->keytype == KMF_RSA) { - pkey = ImportRawRSAKey( - &key->rawdata.rsa); - } else if (key->keytype == KMF_DSA) { - pkey = ImportRawDSAKey( - &key->rawdata.dsa); - } else { - rv = KMF_ERR_BAD_PARAMETER; - } - } + X509 *xcert = NULL; + EVP_PKEY *pkey = NULL; + unsigned char keyid[EVP_MAX_MD_SIZE]; + unsigned int keyidlen = 0; xcert = d2i_X509(NULL, &p, len); if (xcert == NULL) { SET_ERROR(kmfh, ERR_get_error()); rv = KMF_ERR_ENCODING; } - /* Stick the key and the cert into a PKCS#12 file */ - rv = write_pkcs12(kmfh, bio, cred, pkey, xcert); - if (xcert) + if (certlist[i].kmf_private.label != NULL) { + /* Set alias attribute */ + (void) X509_alias_set1(xcert, + (uchar_t *)certlist[i].kmf_private.label, + strlen(certlist[i].kmf_private.label)); + } + /* Check if there is a key corresponding to this cert */ + pkey = find_matching_key(xcert, numkeys, keylist); + + /* + * If key is found, get fingerprint and create a + * safebag. + */ + if (pkey != NULL) { + (void) X509_digest(xcert, EVP_sha1(), + keyid, &keyidlen); + key_authsafe = add_key_to_safe(pkey, cred, + keyid, keyidlen, + certlist[i].kmf_private.label, + (certlist[i].kmf_private.label ? + strlen(certlist[i].kmf_private.label) : 0)); + + if (key_authsafe == NULL) { + X509_free(xcert); + EVP_PKEY_free(pkey); + goto cleanup; + } + /* Put the key safe into the Auth Safe */ + if (!sk_PKCS7_push(authsafe_stack, + key_authsafe)) { + X509_free(xcert); + EVP_PKEY_free(pkey); + goto cleanup; + } + } + + /* create a certificate safebag */ + cert_authsafe = add_cert_to_safe(xcert, cred, keyid, + keyidlen); + if (cert_authsafe == NULL) { + X509_free(xcert); + EVP_PKEY_free(pkey); + goto cleanup; + } + if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) { X509_free(xcert); + EVP_PKEY_free(pkey); + goto cleanup; + } + + X509_free(xcert); if (pkey) EVP_PKEY_free(pkey); } + } else if (numcerts == 0 && numkeys > 0) { + /* + * If only adding keys to the file. + */ + for (i = 0; i < numkeys; i++) { + EVP_PKEY *pkey = NULL; + + if (keylist[i].israw) + pkey = raw_key_to_pkey(&keylist[i]); + else + pkey = (EVP_PKEY *)keylist[i].keyp; + + if (pkey == NULL) + continue; + + key_authsafe = add_key_to_safe(pkey, cred, + NULL, 0, NULL, 0); + + if (key_authsafe == NULL) { + EVP_PKEY_free(pkey); + goto cleanup; + } + if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) { + EVP_PKEY_free(pkey); + goto cleanup; + } + } + } + p12_elem = PKCS12_init(NID_pkcs7_data); + if (p12_elem == NULL) { + goto cleanup; + } + + /* Put the PKCS#7 stack into the PKCS#12 element. */ + if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) { + goto cleanup; + } + + /* Set the integrity MAC on the PKCS#12 element. */ + if (!PKCS12_set_mac(p12_elem, cred->cred, cred->credlen, + NULL, 0, PKCS12_DEFAULT_ITER, NULL)) { + goto cleanup; + } + + /* Write the PKCS#12 element to the export file. */ + if (!i2d_PKCS12_bio(bio, p12_elem)) { + goto cleanup; } + PKCS12_free(p12_elem); cleanup: + /* Clear away the PKCS#7 stack, we're done with it. */ + if (authsafe_stack) + sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); if (bio != NULL) (void) BIO_free_all(bio); @@ -3311,7 +3417,6 @@ cleanup: return (rv); } - KMF_RETURN openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, KMF_X509_DER_CERT *certlist, int numkeys, KMF_KEY_HANDLE *keylist, @@ -3322,27 +3427,27 @@ openssl_build_pk12(KMF_HANDLE_T handle, int numcerts, if (certlist == NULL && keylist == NULL) return (KMF_ERR_BAD_PARAMETER); - rv = ExportPK12FromRawData(handle, p12cred, numcerts, certlist, + rv = local_export_pk12(handle, p12cred, numcerts, certlist, numkeys, keylist, filename); return (rv); } - KMF_RETURN OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) { KMF_RETURN rv; KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; - BIO *bio = NULL; - X509 *xcert = NULL; char *fullpath = NULL; - EVP_PKEY *pkey = NULL; char *dirpath = NULL; char *certfile = NULL; char *keyfile = NULL; char *filename = NULL; KMF_CREDENTIAL *p12cred = NULL; + KMF_X509_DER_CERT certdata; + KMF_KEY_HANDLE key; + int gotkey = 0; + int gotcert = 0; if (handle == NULL) return (KMF_ERR_BAD_PARAMETER); @@ -3362,10 +3467,14 @@ OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) return (KMF_ERR_AMBIGUOUS_PATHNAME); } - rv = load_X509cert(kmfh, NULL, NULL, NULL, fullpath, &xcert); + (void) memset(&certdata, 0, sizeof (certdata)); + rv = kmf_load_cert(kmfh, NULL, NULL, NULL, NULL, + fullpath, &certdata.certificate); if (rv != KMF_OK) goto end; + gotcert++; + certdata.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; free(fullpath); } @@ -3383,11 +3492,11 @@ OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) return (KMF_ERR_AMBIGUOUS_PATHNAME); } - pkey = openssl_load_key(handle, fullpath); - if (pkey == NULL) { - rv = KMF_ERR_KEY_NOT_FOUND; + (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); + rv = fetch_key(handle, fullpath, KMF_ASYM_PRI, &key); + if (rv != KMF_OK) goto end; - } + gotkey++; } /* @@ -3400,12 +3509,6 @@ OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) goto end; } - if ((bio = BIO_new_file(filename, "wb")) == NULL) { - SET_ERROR(kmfh, ERR_get_error()); - rv = KMF_ERR_OPEN_FILE; - goto end; - } - /* Stick the key and the cert into a PKCS#12 file */ p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); if (p12cred == NULL) { @@ -3413,23 +3516,20 @@ OpenSSL_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) goto end; } - rv = write_pkcs12(kmfh, bio, p12cred, pkey, xcert); + rv = local_export_pk12(handle, p12cred, 1, &certdata, + 1, &key, filename); end: if (fullpath) free(fullpath); - if (xcert) - X509_free(xcert); - if (pkey) - EVP_PKEY_free(pkey); - if (bio) - (void) BIO_free(bio); + if (gotcert) + kmf_free_kmf_cert(handle, &certdata); + if (gotkey) + kmf_free_kmf_key(handle, &key); return (rv); } - -#define MAX_CHAIN_LENGTH 100 /* * Helper function to extract keys and certificates from * a single PEM file. Typically the file should contain a @@ -3451,7 +3551,7 @@ extract_pem(KMF_HANDLE *kmfh, EVP_PKEY *pkey = NULL; X509_INFO *info; X509 *x; - X509_INFO *cert_infos[MAX_CHAIN_LENGTH]; + X509_INFO **cert_infos = NULL; KMF_DATA *certlist = NULL; if (priv_key) @@ -3459,19 +3559,23 @@ extract_pem(KMF_HANDLE *kmfh, if (certs) *certs = NULL; fp = fopen(filename, "r"); - if (fp == NULL) { + if (fp == NULL) return (KMF_ERR_OPEN_FILE); - } + x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin); if (x509_info_stack == NULL) { (void) fclose(fp); return (KMF_ERR_ENCODING); } + cert_infos = (X509_INFO **)malloc(sk_X509_INFO_num(x509_info_stack) * + sizeof (X509_INFO *)); + if (cert_infos == NULL) { + (void) fclose(fp); + rv = KMF_ERR_MEMORY; + goto err; + } - - for (i = 0; - i < sk_X509_INFO_num(x509_info_stack) && i < MAX_CHAIN_LENGTH; - i++) { + for (i = 0; i < sk_X509_INFO_num(x509_info_stack); i++) { /* LINTED */ cert_infos[ncerts] = sk_X509_INFO_value(x509_info_stack, i); ncerts++; @@ -3551,21 +3655,275 @@ err: if (x509_info_stack) sk_X509_INFO_free(x509_info_stack); + if (cert_infos != NULL) + free(cert_infos); + return (rv); } +static KMF_RETURN +openssl_parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *pin, + STACK_OF(EVP_PKEY) *keys, STACK_OF(X509) *certs) +{ + KMF_RETURN ret; + int i; + + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + /*LINTED*/ + PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, i); + ret = openssl_parse_bag(bag, pin, (pin ? strlen(pin) : 0), + keys, certs); + + if (ret != KMF_OK) + return (ret); + } + + return (ret); +} + +static KMF_RETURN +set_pkey_attrib(EVP_PKEY *pkey, ASN1_TYPE *attrib, int nid) +{ + X509_ATTRIBUTE *attr = NULL; + + if (pkey == NULL || attrib == NULL) + return (KMF_ERR_BAD_PARAMETER); + + if (pkey->attributes == NULL) { + pkey->attributes = sk_X509_ATTRIBUTE_new_null(); + if (pkey->attributes == NULL) + return (KMF_ERR_MEMORY); + } + attr = X509_ATTRIBUTE_create(nid, attrib->type, attrib->value.ptr); + if (attr != NULL) { + int i; + X509_ATTRIBUTE *a; + for (i = 0; + i < sk_X509_ATTRIBUTE_num(pkey->attributes); i++) { + /*LINTED*/ + a = sk_X509_ATTRIBUTE_value(pkey->attributes, i); + if (OBJ_obj2nid(a->object) == nid) { + X509_ATTRIBUTE_free(a); + /*LINTED*/ + sk_X509_ATTRIBUTE_set(pkey->attributes, + i, attr); + return (KMF_OK); + } + } + if (sk_X509_ATTRIBUTE_push(pkey->attributes, attr) == NULL) { + X509_ATTRIBUTE_free(attr); + return (KMF_ERR_MEMORY); + } + } else { + return (KMF_ERR_MEMORY); + } + + return (KMF_OK); +} + +static KMF_RETURN +openssl_parse_bag(PKCS12_SAFEBAG *bag, char *pass, int passlen, + STACK_OF(EVP_PKEY) *keylist, STACK_OF(X509) *certlist) +{ + KMF_RETURN ret = KMF_OK; + PKCS8_PRIV_KEY_INFO *p8 = NULL; + EVP_PKEY *pkey = NULL; + X509 *xcert = NULL; + ASN1_TYPE *keyid = NULL; + ASN1_TYPE *fname = NULL; + uchar_t *data = NULL; + + keyid = PKCS12_get_attr(bag, NID_localKeyID); + fname = PKCS12_get_attr(bag, NID_friendlyName); + + switch (M_PKCS12_bag_type(bag)) { + case NID_keyBag: + if (keylist == NULL) + goto end; + pkey = EVP_PKCS82PKEY(bag->value.keybag); + if (pkey == NULL) + ret = KMF_ERR_PKCS12_FORMAT; + + break; + case NID_pkcs8ShroudedKeyBag: + if (keylist == NULL) + goto end; + p8 = M_PKCS12_decrypt_skey(bag, pass, passlen); + if (p8 == NULL) + return (KMF_ERR_AUTH_FAILED); + pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (pkey == NULL) + ret = KMF_ERR_PKCS12_FORMAT; + break; + case NID_certBag: + if (certlist == NULL) + goto end; + if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) + return (KMF_ERR_PKCS12_FORMAT); + xcert = M_PKCS12_certbag2x509(bag); + if (xcert == NULL) { + ret = KMF_ERR_PKCS12_FORMAT; + goto end; + } + if (keyid != NULL) { + if (X509_keyid_set1(xcert, + keyid->value.octet_string->data, + keyid->value.octet_string->length) == 0) { + ret = KMF_ERR_PKCS12_FORMAT; + goto end; + } + } + if (fname != NULL) { + int len, r; + len = ASN1_STRING_to_UTF8(&data, + fname->value.asn1_string); + if (len > 0 && data != NULL) { + r = X509_alias_set1(xcert, data, len); + if (r == NULL) { + ret = KMF_ERR_PKCS12_FORMAT; + goto end; + } + } else { + ret = KMF_ERR_PKCS12_FORMAT; + goto end; + } + } + if (sk_X509_push(certlist, xcert) == 0) + ret = KMF_ERR_MEMORY; + else + xcert = NULL; + break; + case NID_safeContentsBag: + return (openssl_parse_bags(bag->value.safes, pass, + keylist, certlist)); + default: + ret = KMF_ERR_PKCS12_FORMAT; + break; + } + + /* + * Set the ID and/or FriendlyName attributes on the key. + * If converting to PKCS11 objects, these can translate to CKA_ID + * and CKA_LABEL values. + */ + if (pkey != NULL && ret == KMF_OK) { + ASN1_TYPE *attr = NULL; + if (keyid != NULL && keyid->type == V_ASN1_OCTET_STRING) { + if ((attr = ASN1_TYPE_new()) == NULL) + return (KMF_ERR_MEMORY); + attr->value.octet_string = + ASN1_STRING_dup(keyid->value.octet_string); + attr->type = V_ASN1_OCTET_STRING; + attr->value.ptr = (char *)attr->value.octet_string; + ret = set_pkey_attrib(pkey, attr, NID_localKeyID); + OPENSSL_free(attr); + } + + if (ret == KMF_OK && fname != NULL && + fname->type == V_ASN1_BMPSTRING) { + if ((attr = ASN1_TYPE_new()) == NULL) + return (KMF_ERR_MEMORY); + attr->value.bmpstring = + ASN1_STRING_dup(fname->value.bmpstring); + attr->type = V_ASN1_BMPSTRING; + attr->value.ptr = (char *)attr->value.bmpstring; + ret = set_pkey_attrib(pkey, attr, NID_friendlyName); + OPENSSL_free(attr); + } + + if (ret == KMF_OK && keylist != NULL && + sk_EVP_PKEY_push(keylist, pkey) == 0) + ret = KMF_ERR_MEMORY; + } + if (ret == KMF_OK && keylist != NULL) + pkey = NULL; +end: + if (pkey != NULL) + EVP_PKEY_free(pkey); + if (xcert != NULL) + X509_free(xcert); + if (data != NULL) + OPENSSL_free(data); + + return (ret); +} + +static KMF_RETURN +openssl_pkcs12_parse(PKCS12 *p12, char *pin, + STACK_OF(EVP_PKEY) *keys, + STACK_OF(X509) *certs, + STACK_OF(X509) *ca) +/*ARGSUSED*/ +{ + KMF_RETURN ret = KMF_OK; + STACK_OF(PKCS7) *asafes = NULL; + STACK_OF(PKCS12_SAFEBAG) *bags = NULL; + int i, bagnid; + PKCS7 *p7; + + if (p12 == NULL || (keys == NULL && certs == NULL)) + return (KMF_ERR_BAD_PARAMETER); + + if (pin == NULL || *pin == NULL) { + if (PKCS12_verify_mac(p12, NULL, 0)) { + pin = NULL; + } else if (PKCS12_verify_mac(p12, "", 0)) { + pin = ""; + } else { + return (KMF_ERR_AUTH_FAILED); + } + } else if (!PKCS12_verify_mac(p12, pin, -1)) { + return (KMF_ERR_AUTH_FAILED); + } + + if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) + return (KMF_ERR_PKCS12_FORMAT); + + for (i = 0; ret == KMF_OK && i < sk_PKCS7_num(asafes); i++) { + bags = NULL; + /*LINTED*/ + p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); + + if (bagnid == NID_pkcs7_data) { + bags = PKCS12_unpack_p7data(p7); + } else if (bagnid == NID_pkcs7_encrypted) { + bags = PKCS12_unpack_p7encdata(p7, pin, + (pin ? strlen(pin) : 0)); + } else { + continue; + } + if (bags == NULL) { + ret = KMF_ERR_PKCS12_FORMAT; + goto out; + } + + if (openssl_parse_bags(bags, pin, keys, certs) != KMF_OK) + ret = KMF_ERR_PKCS12_FORMAT; + + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + } +out: + if (asafes != NULL) + sk_PKCS7_pop_free(asafes, PKCS7_free); + + return (ret); +} + /* * Helper function to decrypt and parse PKCS#12 import file. */ static KMF_RETURN extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, - EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca) + STACK_OF(EVP_PKEY) **priv_key, STACK_OF(X509) **certs, + STACK_OF(X509) **ca) /* ARGSUSED */ { - PKCS12 *pk12, *pk12_tmp; - EVP_PKEY *temp_pkey = NULL; - X509 *temp_cert = NULL; - STACK_OF(X509) *temp_ca = NULL; + PKCS12 *pk12, *pk12_tmp; + STACK_OF(EVP_PKEY) *pkeylist = NULL; + STACK_OF(X509) *xcertlist = NULL; + STACK_OF(X509) *cacertlist = NULL; if ((pk12 = PKCS12_new()) == NULL) { return (KMF_ERR_MEMORY); @@ -3582,17 +3940,40 @@ extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, } pk12 = pk12_tmp; - if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert, - &temp_ca) <= 0) { + xcertlist = sk_X509_new_null(); + if (xcertlist == NULL) { + PKCS12_free(pk12); + return (KMF_ERR_MEMORY); + } + pkeylist = sk_EVP_PKEY_new_null(); + if (pkeylist == NULL) { + sk_X509_pop_free(xcertlist, X509_free); + PKCS12_free(pk12); + return (KMF_ERR_MEMORY); + } + + if (openssl_pkcs12_parse(pk12, (char *)pin, pkeylist, xcertlist, + cacertlist) != KMF_OK) { + sk_X509_pop_free(xcertlist, X509_free); + sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); PKCS12_free(pk12); return (KMF_ERR_PKCS12_FORMAT); } -end_extract_pkcs12: + if (priv_key && pkeylist) + *priv_key = pkeylist; + else if (pkeylist) + sk_EVP_PKEY_pop_free(pkeylist, EVP_PKEY_free); + if (certs && xcertlist) + *certs = xcertlist; + else if (xcertlist) + sk_X509_pop_free(xcertlist, X509_free); + if (ca && cacertlist) + *ca = cacertlist; + else if (cacertlist) + sk_X509_pop_free(cacertlist, X509_free); - *priv_key = temp_pkey; - *cert = temp_cert; - *ca = temp_ca; +end_extract_pkcs12: PKCS12_free(pk12); return (KMF_OK); @@ -3706,24 +4087,33 @@ cleanup: static KMF_RETURN add_cert_to_list(KMF_HANDLE *kmfh, X509 *sslcert, - KMF_DATA **certlist, int *ncerts) + KMF_X509_DER_CERT **certlist, int *ncerts) { KMF_RETURN rv = KMF_OK; - KMF_DATA *list = (*certlist); - KMF_DATA cert; + KMF_X509_DER_CERT *list = (*certlist); + KMF_X509_DER_CERT cert; int n = (*ncerts); if (list == NULL) { - list = (KMF_DATA *)malloc(sizeof (KMF_DATA)); + list = (KMF_X509_DER_CERT *)malloc(sizeof (KMF_X509_DER_CERT)); } else { - list = (KMF_DATA *)realloc(list, sizeof (KMF_DATA) * (n + 1)); + list = (KMF_X509_DER_CERT *)realloc(list, + sizeof (KMF_X509_DER_CERT) * (n + 1)); } if (list == NULL) return (KMF_ERR_MEMORY); - rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert); + (void) memset(&cert, 0, sizeof (cert)); + rv = ssl_cert2KMFDATA(kmfh, sslcert, &cert.certificate); if (rv == KMF_OK) { + int len = 0; + /* Get the alias name for the cert if there is one */ + char *a = (char *)X509_alias_get0(sslcert, &len); + if (a != NULL) + cert.kmf_private.label = strdup(a); + cert.kmf_private.keystore_type = KMF_KEYSTORE_OPENSSL; + list[n] = cert; (*ncerts) = n + 1; @@ -3760,10 +4150,29 @@ add_key_to_list(KMF_RAW_KEY_DATA **keylist, return (KMF_OK); } +static X509_ATTRIBUTE * +find_attr(STACK_OF(X509_ATTRIBUTE) *attrs, int nid) +{ + X509_ATTRIBUTE *a; + int i; + + if (attrs == NULL) + return (NULL); + + for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) { + /*LINTED*/ + a = sk_X509_ATTRIBUTE_value(attrs, i); + if (OBJ_obj2nid(a->object) == nid) + return (a); + } + return (NULL); +} + static KMF_RETURN convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) { KMF_RETURN rv = KMF_OK; + X509_ATTRIBUTE *attr; if (pkey == NULL || key == NULL) return (KMF_ERR_BAD_PARAMETER); @@ -3784,6 +4193,46 @@ convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) default: return (KMF_ERR_BAD_PARAMETER); } + /* + * If friendlyName, add it to record. + */ + attr = find_attr(pkey->attributes, NID_friendlyName); + if (attr != NULL) { + ASN1_TYPE *ty = NULL; + int numattr = sk_ASN1_TYPE_num(attr->value.set); + if (attr->single == 0 && numattr > 0) { + /*LINTED*/ + ty = sk_ASN1_TYPE_value(attr->value.set, 0); + } + if (ty != NULL) { + key->label = uni2asc(ty->value.bmpstring->data, + ty->value.bmpstring->length); + } + } else { + key->label = NULL; + } + + /* + * If KeyID, add it to record as a KMF_DATA object. + */ + attr = find_attr(pkey->attributes, NID_localKeyID); + if (attr != NULL) { + ASN1_TYPE *ty = NULL; + int numattr = sk_ASN1_TYPE_num(attr->value.set); + if (attr->single == 0 && numattr > 0) { + /*LINTED*/ + ty = sk_ASN1_TYPE_value(attr->value.set, 0); + } + key->id.Data = (uchar_t *)malloc( + ty->value.octet_string->length); + if (key->id.Data == NULL) + return (KMF_ERR_MEMORY); + (void) memcpy(key->id.Data, ty->value.octet_string->data, + ty->value.octet_string->length); + key->id.Length = ty->value.octet_string->length; + } else { + (void) memset(&key->id, 0, sizeof (KMF_DATA)); + } return (rv); } @@ -3791,16 +4240,20 @@ convertToRawKey(EVP_PKEY *pkey, KMF_RAW_KEY_DATA *key) static KMF_RETURN convertPK12Objects( KMF_HANDLE *kmfh, - EVP_PKEY *sslkey, X509 *sslcert, STACK_OF(X509) *sslcacerts, + STACK_OF(EVP_PKEY) *sslkeys, + STACK_OF(X509) *sslcert, + STACK_OF(X509) *sslcacerts, KMF_RAW_KEY_DATA **keylist, int *nkeys, - KMF_DATA **certlist, int *ncerts) + KMF_X509_DER_CERT **certlist, int *ncerts) { KMF_RETURN rv = KMF_OK; KMF_RAW_KEY_DATA key; int i; - if (sslkey != NULL) { - rv = convertToRawKey(sslkey, &key); + for (i = 0; sslkeys != NULL && i < sk_EVP_PKEY_num(sslkeys); i++) { + /*LINTED*/ + EVP_PKEY *pkey = sk_EVP_PKEY_value(sslkeys, i); + rv = convertToRawKey(pkey, &key); if (rv == KMF_OK) rv = add_key_to_list(keylist, &key, nkeys); @@ -3809,8 +4262,10 @@ convertPK12Objects( } /* Now add the certificate to the certlist */ - if (sslcert != NULL) { - rv = add_cert_to_list(kmfh, sslcert, certlist, ncerts); + for (i = 0; sslcert != NULL && i < sk_X509_num(sslcert); i++) { + /*LINTED*/ + X509 *cert = sk_X509_value(sslcert, i); + rv = add_cert_to_list(kmfh, cert, certlist, ncerts); if (rv != KMF_OK) return (rv); } @@ -3838,15 +4293,15 @@ convertPK12Objects( KMF_RETURN openssl_import_objects(KMF_HANDLE *kmfh, char *filename, KMF_CREDENTIAL *cred, - KMF_DATA **certlist, int *ncerts, + KMF_X509_DER_CERT **certlist, int *ncerts, KMF_RAW_KEY_DATA **keylist, int *nkeys) { KMF_RETURN rv = KMF_OK; - EVP_PKEY *privkey = NULL; KMF_ENCODE_FORMAT format; BIO *bio = NULL; - X509 *cert = NULL; - STACK_OF(X509) *cacerts = NULL; + STACK_OF(EVP_PKEY) *privkeys = NULL; + STACK_OF(X509) *certs = NULL; + STACK_OF(X509) *cacerts = NULL; /* * auto-detect the file format, regardless of what @@ -3877,37 +4332,64 @@ openssl_import_objects(KMF_HANDLE *kmfh, } rv = extract_pkcs12(bio, (uchar_t *)cred->cred, - (uint32_t)cred->credlen, &privkey, &cert, &cacerts); + (uint32_t)cred->credlen, &privkeys, &certs, &cacerts); if (rv == KMF_OK) /* Convert keys and certs to exportable format */ - rv = convertPK12Objects(kmfh, privkey, cert, cacerts, + rv = convertPK12Objects(kmfh, privkeys, certs, cacerts, keylist, nkeys, certlist, ncerts); - } else { + EVP_PKEY *pkey; + KMF_DATA *certdata = NULL; + KMF_X509_DER_CERT *kmfcerts = NULL; + int i; rv = extract_pem(kmfh, NULL, NULL, NULL, filename, (uchar_t *)cred->cred, (uint32_t)cred->credlen, - &privkey, certlist, ncerts); + &pkey, &certdata, ncerts); /* Reached end of import file? */ - if (rv == KMF_OK) - /* Convert keys and certs to exportable format */ - rv = convertPK12Objects(kmfh, privkey, NULL, NULL, + if (rv == KMF_OK && pkey != NULL) { + privkeys = sk_EVP_PKEY_new_null(); + if (privkeys == NULL) { + rv = KMF_ERR_MEMORY; + goto end; + } + (void) sk_EVP_PKEY_push(privkeys, pkey); + /* convert the certificate list here */ + if (*ncerts > 0 && certlist != NULL) { + kmfcerts = (KMF_X509_DER_CERT *)malloc(*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 = + KMF_KEYSTORE_OPENSSL; + } + *certlist = kmfcerts; + } + /* + * Convert keys to exportable format, the certs + * are already OK. + */ + rv = convertPK12Objects(kmfh, privkeys, NULL, NULL, keylist, nkeys, NULL, NULL); + } } - end: - if (privkey) - EVP_PKEY_free(privkey); - if (bio != NULL) (void) BIO_free(bio); - if (cert) - X509_free(cert); - + if (privkeys) + sk_EVP_PKEY_pop_free(privkeys, EVP_PKEY_free); + if (certs) + sk_X509_pop_free(certs, X509_free); if (cacerts) - sk_X509_free(cacerts); + sk_X509_pop_free(cacerts, X509_free); return (rv); } @@ -4659,7 +5141,11 @@ OpenSSL_StoreKey(KMF_HANDLE_T handle, int numattr, } else { rv = KMF_ERR_BAD_PARAMETER; } - rv = ssl_write_key(kmfh, format, out, &cred, pkey, TRUE); + if (pkey != NULL) { + rv = ssl_write_key(kmfh, format, out, + &cred, pkey, TRUE); + EVP_PKEY_free(pkey); + } } end: @@ -4667,6 +5153,7 @@ end: if (out) (void) BIO_free(out); + if (rv == KMF_OK) (void) chmod(fullpath, 0400); @@ -5239,30 +5726,27 @@ OpenSSL_CheckCRLDate(KMF_HANDLE_T handle, char *crlname) return (ret); bcrl = BIO_new_file(crlname, "rb"); - if (bcrl == NULL) { + if (bcrl == NULL) { SET_ERROR(kmfh, ERR_get_error()); ret = KMF_ERR_OPEN_FILE; goto cleanup; } - if (crl_format == KMF_FORMAT_ASN1) { + if (crl_format == KMF_FORMAT_ASN1) xcrl = d2i_X509_CRL_bio(bcrl, NULL); - } else if (crl_format == KMF_FORMAT_PEM) { + else if (crl_format == KMF_FORMAT_PEM) xcrl = PEM_read_bio_X509_CRL(bcrl, NULL, NULL, NULL); - } if (xcrl == NULL) { SET_ERROR(kmfh, ERR_get_error()); ret = KMF_ERR_BAD_CRLFILE; goto cleanup; } - i = X509_cmp_time(X509_CRL_get_lastUpdate(xcrl), NULL); if (i >= 0) { ret = KMF_ERR_VALIDITY_PERIOD; goto cleanup; } - if (X509_CRL_get_nextUpdate(xcrl)) { i = X509_cmp_time(X509_CRL_get_nextUpdate(xcrl), NULL); 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 189412acb7..694c4ba4da 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 @@ -2889,6 +2889,13 @@ store_raw_key(KMF_HANDLE_T handle, return (KMF_ERR_BAD_PARAMETER); keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr); + /* + * If the caller did not specify a label, see if the raw key + * came with one (possible if it came from a PKCS#12 file). + */ + if (keylabel == NULL) { + keylabel = rawkey->label; + } i = 0; SETATTR(templ, i, CKA_CLASS, &oClass, sizeof (CK_OBJECT_CLASS)); i++; @@ -2923,12 +2930,14 @@ store_raw_key(KMF_HANDLE_T handle, goto cleanup; } start = convertDate(notbefore); + free(notbefore); rv = kmf_get_cert_end_date_str(handle, cert, ¬after); if (rv != KMF_OK) { goto cleanup; } end = convertDate(notafter); + free(notafter); if (id.Data != NULL && id.Data != NULL && id.Length > 0) { SETATTR(templ, i, CKA_ID, id.Data, id.Length); i++; @@ -2990,6 +2999,11 @@ store_raw_key(KMF_HANDLE_T handle, SETATTR(templ, i, CKA_LABEL, keylabel, strlen(keylabel)); i++; } + if (id.Data == NULL && rawkey->id.Data != NULL) { + SETATTR(templ, i, CKA_ID, rawkey->id.Data, + rawkey->id.Length); + i++; + } if (keytype == CKK_RSA) { SETATTR(templ, i, CKA_MODULUS, rawkey->rawdata.rsa.mod.val, @@ -3070,6 +3084,10 @@ store_raw_key(KMF_HANDLE_T handle, rv = KMF_ERR_INTERNAL; } cleanup: + if (start != NULL) + free(start); + if (end != NULL) + free(end); kmf_free_data(&id); kmf_free_data(&subject); kmf_free_signed_cert(x509); |