Mercurial > illumos > illumos-gate
changeset 3408:67ca9373b99e
6501154 kssladm could use KMF
author | wyllys |
---|---|
date | Thu, 11 Jan 2007 18:12:31 -0800 |
parents | d9ac3b8746e4 |
children | 95e86faf5436 |
files | usr/src/cmd/cmd-crypto/pktool/delete.c usr/src/cmd/cmd-crypto/pktool/list.c usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/Makefile usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/openssl_util.c usr/src/lib/libkmf/include/kmfapi.h usr/src/lib/libkmf/include/kmftypes.h usr/src/lib/libkmf/libkmf/common/certop.c usr/src/lib/libkmf/libkmf/common/generalop.c usr/src/lib/libkmf/libkmf/common/mapfile-vers usr/src/lib/libkmf/libkmf/common/pk11tokens.c usr/src/lib/libkmf/plugins/kmf_openssl/common/mapfile-vers usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c |
diffstat | 16 files changed, 1209 insertions(+), 1204 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/cmd-crypto/pktool/delete.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/cmd/cmd-crypto/pktool/delete.c Thu Jan 11 18:12:31 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -280,6 +280,7 @@ parms.findLabel = (char *)objlabel; parms.keytype = 0; parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0); + parms.pkcs11parms.token = 1; parms.cred.cred = tokencred->cred; parms.cred.credlen = tokencred->credlen;
--- a/usr/src/cmd/cmd-crypto/pktool/list.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/cmd/cmd-crypto/pktool/list.c Thu Jan 11 18:12:31 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -291,6 +291,7 @@ parms.cred = *tokencred; parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0); + parms.pkcs11parms.token = 1; /* list asymmetric private keys */ rv = pk_list_keys(kmfhandle, &parms); @@ -303,6 +304,7 @@ parms.format = KMF_FORMAT_RAWKEY; parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0); + parms.pkcs11parms.token = 1; /* list symmetric keys */ rv = pk_list_keys(kmfhandle, &parms); @@ -313,6 +315,7 @@ parms.findLabel = objlabel; parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0); + parms.pkcs11parms.token = 1; /* list asymmetric public keys (if any) */ rv = pk_list_keys(kmfhandle, &parms);
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/Makefile Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/Makefile Thu Jan 11 18:12:31 2007 -0800 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -31,13 +30,12 @@ PROG= kssladm include $(SRC)/cmd/Makefile.cmd -include $(SRC)/lib/openssl/Makefile.openssl OBJS = \ kssladm.o \ kssladm_create.o \ kssladm_delete.o \ - openssl_util.o + ksslutil.o SRCS = $(OBJS:%.o=%.c) @@ -47,12 +45,7 @@ CFLAGS += $(CCVERBOSE) -CPPFLAGS += $(OPENSSL_CPPFLAGS) -DYNFLAGS += $(OPENSSL_DYNFLAGS) -LDFLAGS += $(OPENSSL_LDFLAGS) -LINTFLAGS += $(OPENSSL_LDFLAGS) - -LDLIBS += -lnsl -lpkcs11 -lcrypto -lcryptoutil +LDLIBS += -lkmf -lpkcs11 -lcryptoutil -lnsl all: $(PROG)
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h Thu Jan 11 18:12:31 2007 -0800 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,13 +38,21 @@ #endif #include <netinet/in.h> -#include <openssl/rsa.h> +#include <kmfapi.h> #define SUCCESS 0 #define FAILURE 1 #define ERROR_USAGE 2 #define MAX_CHAIN_LENGTH 12 +#define REPORT_KMF_ERROR(r, t, e) { \ + (void) KMF_GetKMFErrorString(r, &e); \ + (void) fprintf(stderr, t ": %s\n", \ + (e != NULL ? e : "<unknown error>")); \ + if (e) free(e); \ +} + +#define MAX_ATTR_CNT 8 extern boolean_t verbose; @@ -53,11 +61,12 @@ extern void usage_create(boolean_t do_print); extern void usage_delete(boolean_t do_print); -extern uchar_t *get_modulus(uchar_t *ber_buf, int buflen, int *modlen); -extern uchar_t **PEM_get_rsa_key_certs(const char *filename, - char *password_file, RSA **rsa, int **cert_sizes, int *ncerts); -extern uchar_t **PKCS12_get_rsa_key_certs(const char *filename, - const char *password_file, RSA **rsa, int **cert_sizes, int *ncerts); +extern int PEM_get_rsa_key_certs(const char *, + char *, KMF_RAW_KEY_DATA **, KMF_DATA **); + +extern int PKCS12_get_rsa_key_certs(const char *, + const char *, KMF_RAW_KEY_DATA **, KMF_DATA **); + extern int get_passphrase(const char *password_file, char *buf, int buf_size); extern int kssl_send_command(char *buf, int cmd); extern int parse_and_set_addr(char *arg1, char *arg2, struct sockaddr_in *addr);
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c Thu Jan 11 18:12:31 2007 -0800 @@ -20,28 +20,32 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. 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 <arpa/inet.h> #include <errno.h> #include <sys/sysmacros.h> -#include <netdb.h> /* hostent */ -#include <netinet/in.h> -#include <openssl/rsa.h> #include <security/cryptoki.h> #include <security/pkcs11.h> -#include <cryptoutil.h> #include <stdio.h> #include <strings.h> +#include <sys/types.h> +#include <sys/stat.h> #include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <fcntl.h> +#include <inet/kssl/kssl.h> +#include <cryptoutil.h> #include <libscf.h> -#include <inet/kssl/kssl.h> #include "kssladm.h" +#include <kmfapi.h> + void usage_create(boolean_t do_print) { @@ -69,56 +73,6 @@ "\t[-v]\n"); } -static uchar_t * -get_cert_val(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE cert_obj, int *len) -{ - CK_RV rv; - uchar_t *buf; - CK_ATTRIBUTE cert_attrs[] = {{CKA_VALUE, NULL_PTR, 0}}; - - /* the certs ... */ - rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot get cert size." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - buf = malloc(cert_attrs[0].ulValueLen); - if (buf == NULL) - return (NULL); - cert_attrs[0].pValue = buf; - - rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot get cert value." - " error = %s\n", pkcs11_strerror(rv)); - free(buf); - return (NULL); - } - - *len = cert_attrs[0].ulValueLen; - return (buf); -} - -#define OPT_ATTR_CNT 6 -#define MAX_ATTR_CNT 16 - -int known_attr_cnt = 0; - -#define CKA_TOKEN_INDEX 1 -/* - * The order of the attributes must stay in the same order - * as in the attribute template, privkey_tmpl, in load_from_pkcs11(). - */ -CK_ATTRIBUTE key_gattrs[MAX_ATTR_CNT] = { - {CKA_MODULUS, NULL_PTR, 0}, - {CKA_TOKEN, NULL_PTR, 0}, - {CKA_CLASS, NULL_PTR, 0}, - {CKA_KEY_TYPE, NULL_PTR, 0}, -}; -CK_ATTRIBUTE known_cert_attrs[1]; - /* * Everything is allocated in one single contiguous buffer. * The layout is the following: @@ -134,522 +88,28 @@ * to sc_sizes[0] and sc_certs_offset points to sc_certs[0]. */ static kssl_params_t * -pkcs11_to_kssl(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE privkey_obj, - boolean_t is_nxkey, int *paramsize, char *label, char *pin, int pinlen) -{ - int i; - CK_RV rv; - int total_attr_cnt; - uint32_t cert_size, bufsize; - char *buf; - kssl_key_t *key; - kssl_params_t *kssl_params; - CK_ATTRIBUTE privkey_opt_attrs[OPT_ATTR_CNT] = { - {CKA_PUBLIC_EXPONENT, NULL_PTR, 0}, - {CKA_PRIME_1, NULL_PTR, 0}, - {CKA_PRIME_2, NULL_PTR, 0}, - {CKA_EXPONENT_1, NULL_PTR, 0}, - {CKA_EXPONENT_2, NULL_PTR, 0}, - {CKA_COEFFICIENT, NULL_PTR, 0} - }; - kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT]; - - /* Get the certificate size */ - bufsize = sizeof (kssl_params_t); - cert_size = (uint32_t)known_cert_attrs[0].ulValueLen; - bufsize += cert_size + MAX_CHAIN_LENGTH * sizeof (uint32_t); - - /* These are attributes for which we have the value and length */ - for (i = 0; i < known_attr_cnt; i++) { - bufsize += sizeof (crypto_object_attribute_t) + - key_gattrs[i].ulValueLen; - } - total_attr_cnt = known_attr_cnt; - - if (!is_nxkey) { - /* Add CKA_PRIVATE_EXPONENT for extractable key */ - key_gattrs[total_attr_cnt].type = CKA_PRIVATE_EXPONENT; - key_gattrs[total_attr_cnt].pValue = NULL_PTR; - key_gattrs[total_attr_cnt].ulValueLen = 0; - - rv = C_GetAttributeValue(sess, privkey_obj, - &key_gattrs[total_attr_cnt], 1); - if (rv != CKR_OK) { - (void) fprintf(stderr, - "Cannot get private key object attribute." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - bufsize += sizeof (crypto_object_attribute_t) + - key_gattrs[total_attr_cnt].ulValueLen; - total_attr_cnt++; - } - - /* - * Get the optional key attributes. The return values could be - * CKR_ATTRIBUTE_TYPE_INVALID with ulValueLen set to -1 OR - * CKR_OK with ulValueLen set to 0. The latter is done by - * soft token and seems dubious. - */ - if (!is_nxkey) { - rv = C_GetAttributeValue(sess, privkey_obj, privkey_opt_attrs, - OPT_ATTR_CNT); - if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) { - (void) fprintf(stderr, - "Cannot get private key object attributes." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - for (i = 0; i < OPT_ATTR_CNT; i++) { - if (privkey_opt_attrs[i].ulValueLen == (CK_ULONG)-1 || - privkey_opt_attrs[i].ulValueLen == 0) - continue; - /* Structure copy */ - key_gattrs[total_attr_cnt] = privkey_opt_attrs[i]; - bufsize += sizeof (crypto_object_attribute_t) + - privkey_opt_attrs[i].ulValueLen; - total_attr_cnt++; - } - } else - bufsize += pinlen; - - /* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */ - bufsize += sizeof (uint32_t); - - /* Now the big memory allocation */ - if ((buf = calloc(bufsize, 1)) == NULL) { - (void) fprintf(stderr, - "Cannot allocate memory for the kssl_params " - "and values\n"); - return (NULL); - } - - /* LINTED */ - kssl_params = (kssl_params_t *)buf; - - buf = (char *)(kssl_params + 1); - - if (is_nxkey) { - kssl_params->kssl_is_nxkey = 1; - bcopy(label, kssl_params->kssl_token.toklabel, - CRYPTO_EXT_SIZE_LABEL); - kssl_params->kssl_token.pinlen = pinlen; - kssl_params->kssl_token.tokpin_offset = - buf - (char *)kssl_params; - kssl_params->kssl_token.ck_rv = 0; - bcopy(pin, buf, pinlen); - buf += pinlen; - } - - /* the keys attributes structs array */ - key = &kssl_params->kssl_privkey; - key->ks_format = CRYPTO_KEY_ATTR_LIST; - key->ks_count = total_attr_cnt; - key->ks_attrs_offset = buf - (char *)kssl_params; - buf += total_attr_cnt * sizeof (kssl_object_attribute_t); - - /* These are attributes for which we already have the value */ - for (i = 0; i < known_attr_cnt; i++) { - bcopy(key_gattrs[i].pValue, buf, key_gattrs[i].ulValueLen); - kssl_attrs[i].ka_type = key_gattrs[i].type; - kssl_attrs[i].ka_value_offset = buf - (char *)kssl_params; - kssl_attrs[i].ka_value_len = key_gattrs[i].ulValueLen; - buf += key_gattrs[i].ulValueLen; - } - - if (total_attr_cnt > known_attr_cnt) { - /* These are attributes for which we need to get the value */ - for (i = known_attr_cnt; i < total_attr_cnt; i++) { - key_gattrs[i].pValue = buf; - kssl_attrs[i].ka_type = key_gattrs[i].type; - kssl_attrs[i].ka_value_offset = - buf - (char *)kssl_params; - kssl_attrs[i].ka_value_len = key_gattrs[i].ulValueLen; - buf += key_gattrs[i].ulValueLen; - } - - rv = C_GetAttributeValue(sess, privkey_obj, - &key_gattrs[known_attr_cnt], - total_attr_cnt - known_attr_cnt); - if (rv != CKR_OK) { - (void) fprintf(stderr, - "Cannot get private key object attributes." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - } - - bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, - total_attr_cnt * sizeof (kssl_object_attribute_t)); - - buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); - kssl_params->kssl_certs.sc_count = 1; - bcopy(&cert_size, buf, sizeof (uint32_t)); - kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params; - buf += MAX_CHAIN_LENGTH * sizeof (uint32_t); - - /* now the certs values */ - bcopy(known_cert_attrs[0].pValue, buf, known_cert_attrs[0].ulValueLen); - free(known_cert_attrs[0].pValue); - kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params; - - *paramsize = bufsize; - bzero(pin, pinlen); - (void) C_Logout(sess); - (void) C_CloseSession(sess); - return (kssl_params); -} - -#define max_num_cert 32 - -static kssl_params_t * -load_from_pkcs11(const char *token_label, const char *password_file, - const char *certname, int *bufsize) -{ - static CK_BBOOL true = TRUE; - static CK_BBOOL false = FALSE; - - CK_RV rv; - CK_SLOT_ID slot; - CK_SLOT_ID_PTR pk11_slots; - CK_ULONG slotcnt = 10; - CK_TOKEN_INFO token_info; - CK_SESSION_HANDLE sess; - static CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - static CK_CERTIFICATE_TYPE cert_type = CKC_X_509; - CK_ATTRIBUTE cert_tmpl[4] = { - {CKA_TOKEN, &true, sizeof (true)}, - {CKA_LABEL, NULL_PTR, 0}, - {CKA_CLASS, &cert_class, sizeof (cert_class)}, - {CKA_CERTIFICATE_TYPE, &cert_type, sizeof (cert_type)} - }; - CK_ULONG cert_tmpl_count = 4, cert_obj_count = 1; - CK_OBJECT_HANDLE cert_obj, privkey_obj; - CK_OBJECT_HANDLE cert_objs[max_num_cert]; - static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY; - static CK_KEY_TYPE privkey_type = CKK_RSA; - CK_ATTRIBUTE privkey_tmpl[] = { - /* - * The order of attributes must stay in the same order - * as in the global attribute array, key_gattrs. - */ - {CKA_MODULUS, NULL_PTR, 0}, - {CKA_TOKEN, &true, sizeof (true)}, - {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, - {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)} - }; - CK_ULONG privkey_tmpl_count = 4, privkey_obj_count = 1; - CK_BBOOL is_extractable; - CK_ATTRIBUTE privkey_attrs[1] = { - {CKA_EXTRACTABLE, NULL_PTR, 0}, - }; - boolean_t bingo = B_FALSE; - int i, blen, mlen; - uchar_t *mval, *ber_buf; - char token_label_padded[sizeof (token_info.label) + 1]; - char passphrase[MAX_PIN_LENGTH]; - CK_ULONG ulPinLen; - - (void) snprintf(token_label_padded, sizeof (token_label_padded), - "%-32s", token_label); - - rv = C_Initialize(NULL_PTR); - - if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { - (void) fprintf(stderr, - "Cannot initialize PKCS#11. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - /* Get slot count */ - rv = C_GetSlotList(1, NULL_PTR, &slotcnt); - if (rv != CKR_OK || slotcnt == 0) { - (void) fprintf(stderr, - "Cannot get PKCS#11 slot list. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - pk11_slots = calloc(slotcnt, sizeof (CK_SLOT_ID)); - if (pk11_slots == NULL) { - (void) fprintf(stderr, - "Cannot get memory for %ld slots\n", slotcnt); - return (NULL); - } - - rv = C_GetSlotList(1, pk11_slots, &slotcnt); - if (rv != CKR_OK) { - (void) fprintf(stderr, - "Cannot get PKCS#11 slot list. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - if (verbose) - (void) printf("Found %ld slots\n", slotcnt); - - /* Search the token that matches the label */ - while (slotcnt > 0) { - rv = C_GetTokenInfo(pk11_slots[--slotcnt], &token_info); - if (rv != CKR_OK) - continue; - - if (verbose) - (void) printf("slot [%ld] = %s\n", - slotcnt, token_info.label); - if (memcmp(token_label_padded, token_info.label, - sizeof (token_info.label)) == 0) { - bingo = B_TRUE; - slot = pk11_slots[slotcnt]; - break; - } - if (verbose) { - token_info.label[31] = '\0'; - (void) printf("found slot [%s]\n", token_info.label); - } - } - - if (!bingo) { - (void) fprintf(stderr, "no matching PKCS#11 token found\n"); - return (NULL); - } - - rv = C_OpenSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, - &sess); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot open session. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - /* - * Some tokens may not be setting CKF_LOGIN_REQUIRED. So, we do - * not check for this flag and always login to be safe. - */ - ulPinLen = get_passphrase(password_file, passphrase, - sizeof (passphrase)); - if (ulPinLen == 0) { - (void) fprintf(stderr, "Unable to read passphrase"); - return (NULL); - } - - rv = C_Login(sess, CKU_USER, (CK_UTF8CHAR_PTR)passphrase, - ulPinLen); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot login to the token." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - cert_tmpl[1].pValue = (CK_VOID_PTR) certname; - cert_tmpl[1].ulValueLen = strlen(certname); - - rv = C_FindObjectsInit(sess, cert_tmpl, cert_tmpl_count); - if (rv != CKR_OK) { - (void) fprintf(stderr, - "Cannot initialize cert search." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - rv = C_FindObjects(sess, cert_objs, - (certname == NULL ? 1 : max_num_cert), &cert_obj_count); - if (rv != CKR_OK) { - (void) fprintf(stderr, - "Cannot retrieve cert object. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - /* Who cares if this fails! */ - (void) C_FindObjectsFinal(sess); - if (verbose) - (void) printf("found %ld certificates\n", cert_obj_count); - - if (cert_obj_count == 0) { - (void) fprintf(stderr, "\"%s\" not found.\n", certname); - (void) fprintf(stderr, "no certs. bye.\n"); - return (NULL); - } - - cert_obj = cert_objs[0]; - - /* Get the modulus value from the certificate */ - ber_buf = get_cert_val(sess, cert_obj, &blen); - if (ber_buf == NULL) { - (void) fprintf(stderr, - "Cannot get certificate data for \"%s\".\n", certname); - return (NULL); - } - - /* Store it for later use. We free the buffer at that time. */ - known_cert_attrs[0].type = CKA_VALUE; - known_cert_attrs[0].pValue = ber_buf; - known_cert_attrs[0].ulValueLen = blen; - - mval = get_modulus(ber_buf, blen, &mlen); - if (mval == NULL) { - (void) fprintf(stderr, - "Cannot get Modulus in certificate \"%s\".\n", certname); - return (NULL); - } - - /* Now get the private key */ - privkey_tmpl[0].pValue = mval; - privkey_tmpl[0].ulValueLen = mlen; - - rv = C_FindObjectsInit(sess, privkey_tmpl, privkey_tmpl_count); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot intialize private key search." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - rv = C_FindObjects(sess, &privkey_obj, 1, &privkey_obj_count); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot retrieve private key object " - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - /* Who cares if this fails! */ - (void) C_FindObjectsFinal(sess); - - if (privkey_obj_count == 0) { - (void) fprintf(stderr, "no private keys. bye.\n"); - return (NULL); - } - - (void) printf("found %ld private keys\n", privkey_obj_count); - if (verbose) { - (void) printf("private key attributes: \n"); - (void) printf("\tmodulus: size %d \n", mlen); - } - - /* - * Store it for later use. The index of the attributes - * is the same in both the structures. - */ - known_attr_cnt = privkey_tmpl_count; - for (i = 0; i < privkey_tmpl_count; i++) - key_gattrs[i] = privkey_tmpl[i]; - - /* - * Get CKA_EXTRACTABLE value. We set the default value - * TRUE if the token returns CKR_ATTRIBUTE_TYPE_INVALID. - * The token would supply this attribute if the key - * is not extractable. - */ - privkey_attrs[0].pValue = &is_extractable; - privkey_attrs[0].ulValueLen = sizeof (is_extractable); - rv = C_GetAttributeValue(sess, privkey_obj, privkey_attrs, 1); - if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) { - (void) fprintf(stderr, - "Cannot get CKA_EXTRACTABLE attribute." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - - if (rv == CKR_ATTRIBUTE_TYPE_INVALID) - is_extractable = TRUE; - key_gattrs[known_attr_cnt++] = privkey_attrs[0]; - - if (is_extractable) { - /* Now wrap the key, then unwrap it */ - CK_BYTE aes_key_val[16] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; - static CK_BYTE aes_param[16] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, 16}; - CK_OBJECT_HANDLE aes_key_obj, sess_privkey_obj; - CK_BYTE *wrapped_privkey; - CK_ULONG wrapped_privkey_len; - - CK_ATTRIBUTE unwrap_tmpl[] = { - /* code below depends on the following attribute order */ - {CKA_TOKEN, &false, sizeof (false)}, - {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, - {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}, - {CKA_SENSITIVE, &false, sizeof (false)}, - {CKA_PRIVATE, &false, sizeof (false)} - }; - - rv = SUNW_C_KeyToObject(sess, CKM_AES_CBC_PAD, aes_key_val, 16, - &aes_key_obj); - - if (rv != CKR_OK) { - (void) fprintf(stderr, - "Cannot create wrapping key. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - /* get the size of the wrapped key */ - rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj, - NULL, &wrapped_privkey_len); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot get key size. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - - wrapped_privkey = malloc(wrapped_privkey_len * sizeof (CK_BYTE)); - if (wrapped_privkey == NULL) { - return (NULL); - } - - /* do the actual key wrapping */ - rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj, - wrapped_privkey, &wrapped_privkey_len); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot wrap private key. error = %s\n", - pkcs11_strerror(rv)); - return (NULL); - } - (void) printf("private key successfully wrapped, " - "wrapped blob length: %ld\n", - wrapped_privkey_len); - - rv = C_UnwrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, - wrapped_privkey, wrapped_privkey_len, - unwrap_tmpl, 5, &sess_privkey_obj); - if (rv != CKR_OK) { - (void) fprintf(stderr, "Cannot unwrap private key." - " error = %s\n", pkcs11_strerror(rv)); - return (NULL); - } - (void) printf("session private key successfully unwrapped\n"); - - privkey_obj = sess_privkey_obj; - /* Store the one modified attribute and the two new attributes. */ - key_gattrs[CKA_TOKEN_INDEX] = unwrap_tmpl[0]; - key_gattrs[known_attr_cnt++] = unwrap_tmpl[3]; - key_gattrs[known_attr_cnt++] = unwrap_tmpl[4]; - } - - return (pkcs11_to_kssl(sess, privkey_obj, !is_extractable, bufsize, - token_label_padded, passphrase, ulPinLen)); -} - -#define MAX_OPENSSL_ATTR_CNT 8 - -/* - * See the comments for pkcs11_to_kssl() for the layout of the - * returned buffer. - */ -static kssl_params_t * -openssl_to_kssl(RSA *rsa, int ncerts, uchar_t *cert_bufs[], int *cert_sizes, - int *paramsize) +kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts, + KMF_DATA *certs, int *paramsize, char *token_label, KMF_DATA *idstr, + KMF_CREDENTIAL *creds) { int i, tcsize; kssl_params_t *kssl_params; kssl_key_t *key; char *buf; uint32_t bufsize; - kssl_object_attribute_t kssl_attrs[MAX_OPENSSL_ATTR_CNT]; - kssl_object_attribute_t kssl_tmpl_attrs[MAX_OPENSSL_ATTR_CNT] = { + static CK_BBOOL true = TRUE; + static CK_BBOOL false = FALSE; + static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + static CK_KEY_TYPE keytype = CKK_RSA; + kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT]; + CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = { + {CKA_TOKEN, &true, sizeof (true)}, + {CKA_EXTRACTABLE, &false, sizeof (false)}, + {CKA_CLASS, &class, sizeof (class) }, + {CKA_KEY_TYPE, &keytype, sizeof (keytype) }, + {CKA_ID, NULL, 0} + }; + kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = { {SUN_CKA_MODULUS, NULL, 0}, {SUN_CKA_PUBLIC_EXPONENT, NULL, 0}, {SUN_CKA_PRIVATE_EXPONENT, NULL, 0}, @@ -659,42 +119,64 @@ {SUN_CKA_EXPONENT_2, NULL, 0}, {SUN_CKA_COEFFICIENT, NULL, 0} }; - BIGNUM *priv_key_bignums[MAX_OPENSSL_ATTR_CNT]; + KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT]; int attr_cnt; + if (nxkey && idstr != NULL) { + exkey_attrs[4].pValue = idstr->Data; + exkey_attrs[4].ulValueLen = idstr->Length; + } tcsize = 0; for (i = 0; i < ncerts; i++) - tcsize += cert_sizes[i]; + tcsize += certs[i].Length; bufsize = sizeof (kssl_params_t); - bufsize += (tcsize + MAX_CHAIN_LENGTH * sizeof (uint32_t)); + bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t))); - /* and the key attributes */ - priv_key_bignums[0] = rsa->n; /* MODULUS */ - priv_key_bignums[1] = rsa->e; /* PUBLIC_EXPONENT */ - priv_key_bignums[2] = rsa->d; /* PRIVATE_EXPONENT */ - priv_key_bignums[3] = rsa->p; /* PRIME_1 */ - priv_key_bignums[4] = rsa->q; /* PRIME_2 */ - priv_key_bignums[5] = rsa->dmp1; /* EXPONENT_1 */ - priv_key_bignums[6] = rsa->dmq1; /* EXPONENT_2 */ - priv_key_bignums[7] = rsa->iqmp; /* COEFFICIENT */ + if (!nxkey) { + bzero(priv_key_bignums, sizeof (KMF_BIGINT) * + MAX_ATTR_CNT); + /* and the key attributes */ + priv_key_bignums[0] = rsa->rawdata.rsa.mod; + priv_key_bignums[1] = rsa->rawdata.rsa.pubexp; + priv_key_bignums[2] = rsa->rawdata.rsa.priexp; + priv_key_bignums[3] = rsa->rawdata.rsa.prime1; + priv_key_bignums[4] = rsa->rawdata.rsa.prime2; + priv_key_bignums[5] = rsa->rawdata.rsa.exp1; + priv_key_bignums[6] = rsa->rawdata.rsa.exp2; + priv_key_bignums[7] = rsa->rawdata.rsa.coef; + + if (rsa->rawdata.rsa.mod.val == NULL || + rsa->rawdata.rsa.priexp.val == NULL) { + (void) fprintf(stderr, + "missing required attributes in private key.\n"); + return (NULL); + } - if (rsa->n == NULL || rsa->d == NULL) { - (void) fprintf(stderr, - "missing required attributes in private key.\n"); - return (NULL); - } - - attr_cnt = 0; - for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) { - if (priv_key_bignums[i] == NULL) - continue; - kssl_attrs[attr_cnt].ka_type = kssl_tmpl_attrs[i].ka_type; - kssl_attrs[attr_cnt].ka_value_len = - BN_num_bytes(priv_key_bignums[i]); - bufsize += sizeof (crypto_object_attribute_t) + - kssl_attrs[attr_cnt].ka_value_len; - attr_cnt++; + attr_cnt = 0; + for (i = 0; i < MAX_ATTR_CNT; i++) { + if (priv_key_bignums[i].val == NULL) + continue; + kssl_attrs[attr_cnt].ka_type = + kssl_tmpl_attrs[i].ka_type; + kssl_attrs[attr_cnt].ka_value_len = + priv_key_bignums[i].len; + bufsize += sizeof (crypto_object_attribute_t) + + kssl_attrs[attr_cnt].ka_value_len; + attr_cnt++; + } + } else { + /* + * Compute space for the attributes and values that the + * kssl kernel module will need in order to search for + * the private key. + */ + for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) { + bufsize += sizeof (crypto_object_attribute_t) + + exkey_attrs[attr_cnt].ulValueLen; + } + if (creds) + bufsize += creds->credlen; } /* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */ @@ -713,60 +195,458 @@ buf = (char *)(kssl_params + 1); - /* the keys attributes structs array */ - key = &kssl_params->kssl_privkey; - key->ks_format = CRYPTO_KEY_ATTR_LIST; - key->ks_count = attr_cnt; - key->ks_attrs_offset = buf - (char *)kssl_params; - buf += attr_cnt * sizeof (kssl_object_attribute_t); + if (!nxkey) { + /* the keys attributes structs array */ + key = &kssl_params->kssl_privkey; + key->ks_format = CRYPTO_KEY_ATTR_LIST; + key->ks_count = attr_cnt; + key->ks_attrs_offset = buf - (char *)kssl_params; + buf += attr_cnt * sizeof (kssl_object_attribute_t); + + attr_cnt = 0; + /* then the key attributes values */ + for (i = 0; i < MAX_ATTR_CNT; i++) { + if (priv_key_bignums[i].val == NULL) + continue; + (void) memcpy(buf, priv_key_bignums[i].val, + priv_key_bignums[i].len); + kssl_attrs[attr_cnt].ka_value_offset = + buf - (char *)kssl_params; + buf += kssl_attrs[attr_cnt].ka_value_len; + attr_cnt++; + } + } else { + char tlabel[CRYPTO_EXT_SIZE_LABEL]; + bzero(tlabel, sizeof (tlabel)); + (void) strlcpy(tlabel, token_label, sizeof (tlabel)); + + /* + * For a non-extractable key, we must provide the PIN + * so the kssl module can access the token to find + * the key handle. + */ + kssl_params->kssl_is_nxkey = 1; + bcopy(tlabel, kssl_params->kssl_token.toklabel, + CRYPTO_EXT_SIZE_LABEL); + kssl_params->kssl_token.pinlen = creds->credlen; + kssl_params->kssl_token.tokpin_offset = + buf - (char *)kssl_params; + kssl_params->kssl_token.ck_rv = 0; + bcopy(creds->cred, buf, creds->credlen); + buf += creds->credlen; - attr_cnt = 0; - /* then the key attributes values */ - for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) { - if (priv_key_bignums[i] == NULL) - continue; - (void) BN_bn2bin(priv_key_bignums[i], (unsigned char *)buf); - kssl_attrs[attr_cnt].ka_value_offset = - buf - (char *)kssl_params; - buf += kssl_attrs[attr_cnt].ka_value_len; - attr_cnt++; + /* + * Next in the buffer, we must provide the attributes + * that the kssl module will use to search in the + * token to find the protected key handle. + */ + key = &kssl_params->kssl_privkey; + key->ks_format = CRYPTO_KEY_ATTR_LIST; + key->ks_count = attr_cnt; + key->ks_attrs_offset = buf - (char *)kssl_params; + + buf += attr_cnt * sizeof (kssl_object_attribute_t); + for (i = 0; i < attr_cnt; i++) { + bcopy(exkey_attrs[i].pValue, buf, + exkey_attrs[i].ulValueLen); + + kssl_attrs[i].ka_type = exkey_attrs[i].type; + kssl_attrs[i].ka_value_offset = + buf - (char *)kssl_params; + kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen; + + buf += exkey_attrs[i].ulValueLen; + } + } + /* Copy the key attributes array here */ + bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, + attr_cnt * sizeof (kssl_object_attribute_t)); + + buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); + + /* + * Finally, add the certificate chain to the buffer. + */ + kssl_params->kssl_certs.sc_count = ncerts; + + /* First, an array of certificate sizes */ + for (i = 0; i < ncerts; i++) { + uint32_t certsz = (uint32_t)certs[i].Length; + char *p = buf + (i * sizeof (uint32_t)); + bcopy(&certsz, p, sizeof (uint32_t)); } - bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, - attr_cnt * sizeof (kssl_object_attribute_t)); - - buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); - kssl_params->kssl_certs.sc_count = ncerts; - bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t)); kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params; buf += MAX_CHAIN_LENGTH * sizeof (uint32_t); kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params; - /* now the certs values */ + + /* Now add the certificate data (ASN.1 DER encoded) */ for (i = 0; i < ncerts; i++) { - bcopy(cert_bufs[i], buf, cert_sizes[i]); - buf += cert_sizes[i]; + bcopy(certs[i].Data, buf, certs[i].Length); + buf += certs[i].Length; } *paramsize = bufsize; return (kssl_params); } -static kssl_params_t * -add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file, - const char *password_file) +/* + * Extract a sensitive key via wrap/unwrap operations. + * + * This function requires that we call PKCS#11 API directly since + * KMF does not yet support wrapping/unwrapping of keys. By extracting + * a sensitive key in wrapped form, we then unwrap it into a session key + * object. KMF is then used to find the session key and return it in + * KMF_RAW_KEY format which is then passed along to KSSL by the caller. + */ +static KMF_RETURN +get_sensitive_key_data(KMF_HANDLE_T kmfh, KMF_FINDKEY_PARAMS *fkparams, + KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey) { - int i, ncerts, newlen; - int *cert_sizes; - uint32_t certlen = 0; + KMF_RETURN rv = KMF_OK; + static CK_BYTE aes_param[16]; + static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY; + static CK_KEY_TYPE privkey_type = CKK_RSA; + static CK_BBOOL true = TRUE; + static CK_BBOOL false = FALSE; + char *err = NULL; + char wrapkey_label[BUFSIZ]; + int fd; + uint32_t nkeys = 0; + CK_RV ckrv; + CK_SESSION_HANDLE pk11session; + CK_BYTE aes_key_val[16]; + + CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, + sizeof (aes_param)}; + CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE; + CK_BYTE *wrapped_privkey = NULL; + CK_ULONG wrapped_privkey_len = 0; + + CK_ATTRIBUTE unwrap_tmpl[] = { + /* code below depends on the following attribute order */ + {CKA_TOKEN, &false, sizeof (false)}, + {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, + {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}, + {CKA_SENSITIVE, &false, sizeof (false)}, + {CKA_PRIVATE, &false, sizeof (false)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * Create a wrap key with random data. + */ + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) { + perror("Error reading /dev/urandom"); + return (KMF_ERR_INTERNAL); + } + if (read(fd, aes_key_val, sizeof (aes_key_val)) != + sizeof (aes_key_val)) { + perror("Error reading from /dev/urandom"); + (void) close(fd); + return (KMF_ERR_INTERNAL); + } + (void) close(fd); + + pk11session = KMF_GetPK11Handle(kmfh); + + /* + * Login to create the wrap key stuff. + */ + ckrv = C_Login(pk11session, CKU_USER, + (CK_UTF8CHAR_PTR)fkparams->cred.cred, + fkparams->cred.credlen); + if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) { + (void) fprintf(stderr, + "Cannot login to the token. error = %s\n", + pkcs11_strerror(ckrv)); + return (KMF_ERR_INTERNAL); + } + + /* + * Turn the random key into a PKCS#11 session object. + */ + ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val, + sizeof (aes_key_val), &aes_key_obj); + if (ckrv != CKR_OK) { + (void) fprintf(stderr, + "Cannot create wrapping key. error = %s\n", + pkcs11_strerror(ckrv)); + return (KMF_ERR_INTERNAL); + } + + /* + * Find the original private key that we are going to wrap. + */ + rv = KMF_FindKey(kmfh, fkparams, key, &nkeys); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error finding private key", err); + goto out; + } + + /* + * Get the size of the wrapped private key. + */ + bzero(aes_param, sizeof (aes_param)); + ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech, + aes_key_obj, (CK_OBJECT_HANDLE)key->keyp, + NULL, &wrapped_privkey_len); + if (ckrv != CKR_OK) { + /* + * Most common error here is that the token doesn't + * support the wrapping mechanism or the key is + * marked non-extractable. Return an error and let + * the caller deal with it gracefully. + */ + (void) fprintf(stderr, + "Cannot get wrap key size. error = %s\n", + pkcs11_strerror(ckrv)); + rv = KMF_ERR_INTERNAL; + goto out; + } + wrapped_privkey = malloc(wrapped_privkey_len); + if (wrapped_privkey == NULL) { + rv = KMF_ERR_MEMORY; + goto out; + } + /* + * Now get the actual wrapped key data. + */ + ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech, + aes_key_obj, (CK_OBJECT_HANDLE)key->keyp, + wrapped_privkey, &wrapped_privkey_len); + if (ckrv != CKR_OK) { + (void) fprintf(stderr, + "Cannot wrap private key. error = %s\n", + pkcs11_strerror(ckrv)); + rv = KMF_ERR_INTERNAL; + goto out; + } + /* + * Create a label for the wrapped session key so we can find + * it easier later. + */ + snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d", + getpid()); + + unwrap_tmpl[5].pValue = wrapkey_label; + unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label); + + /* + * Unwrap the key into the template and create a temporary + * session private key. + */ + ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj, + wrapped_privkey, wrapped_privkey_len, + unwrap_tmpl, 6, &sess_privkey_obj); + if (ckrv != CKR_OK) { + (void) fprintf(stderr, + "Cannot unwrap private key. error = %s\n", + pkcs11_strerror(ckrv)); + rv = KMF_ERR_INTERNAL; + goto out; + } + + /* + * Use KMF to find the session key and return it as RAW data + * so we can pass it along to KSSL. + */ + fkparams->kstype = KMF_KEYSTORE_PK11TOKEN; + fkparams->keyclass = KMF_ASYM_PRI; + fkparams->format = KMF_FORMAT_RAWKEY; + fkparams->findLabel = wrapkey_label; + fkparams->pkcs11parms.sensitive = FALSE; + fkparams->pkcs11parms.private = FALSE; + fkparams->pkcs11parms.token = FALSE; /* <-- very important! */ + + rv = KMF_FindKey(kmfh, fkparams, rawkey, &nkeys); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error finding raw private key", err); + goto out; + } +out: + if (wrapped_privkey) + free(wrapped_privkey); + + if (aes_key_obj != CK_INVALID_HANDLE) + C_DestroyObject(pk11session, aes_key_obj); + + if (sess_privkey_obj != CK_INVALID_HANDLE) + C_DestroyObject(pk11session, sess_privkey_obj); + + return (rv); +} + +static kssl_params_t * +load_from_pkcs11(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; + KMF_FINDCERT_PARAMS fcparams; + KMF_FINDKEY_PARAMS fkparams; + KMF_CONFIG_PARAMS cfgparams; + KMF_DATA iddata = { NULL, 0 }; + kssl_params_t *kssl_params = NULL; + uint32_t ncerts, nkeys; + char *err, *idstr = NULL; + char password_buf[1024]; + int nxkey = 0; + + 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"); + goto done; + } + creds.cred = password_buf; + creds.credlen = strlen(password_buf); + + bzero(&cfgparams, sizeof (cfgparams)); + bzero(&fcparams, sizeof (fcparams)); + bzero(&fkparams, sizeof (fkparams)); + + cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN; + cfgparams.pkcs11config.label = (char *)token_label; + cfgparams.pkcs11config.readonly = B_FALSE; + + rv = KMF_ConfigureKeystore(kmfh, &cfgparams); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err); + goto done; + } + + /* + * Find the certificate matching the given label. + */ + fcparams.kstype = KMF_KEYSTORE_PK11TOKEN; + fcparams.certLabel = (char *)certname; + rv = KMF_FindCert(kmfh, &fcparams, &cert, &ncerts); + if (rv != KMF_OK || ncerts == 0) + goto done; + + /* + * Find the associated private key for this cert by + * keying off of the label and the ASCII ID string. + */ + rv = KMF_GetCertIDString(&cert.certificate, &idstr); + if (rv != KMF_OK) + goto done; + + fkparams.kstype = KMF_KEYSTORE_PK11TOKEN; + fkparams.keyclass = KMF_ASYM_PRI; + fkparams.cred = creds; + fkparams.format = KMF_FORMAT_RAWKEY; + fkparams.findLabel = (char *)certname; + fkparams.idstr = idstr; + fkparams.pkcs11parms.private = TRUE; + fkparams.pkcs11parms.token = TRUE; + + rv = KMF_FindKey(kmfh, &fkparams, &key, &nkeys); + if (rv == KMF_ERR_SENSITIVE_KEY) { + KMF_FreeKMFKey(kmfh, &key); + /* + * Get a normal key handle and then do a wrap/unwrap + * in order to get the necessary raw data fields needed + * to send to KSSL. + */ + fkparams.format = KMF_FORMAT_NATIVE; + rv = get_sensitive_key_data(kmfh, &fkparams, &key, &rawkey); + if (rv == KMF_OK) { + /* Swap "key" for "rawkey" */ + KMF_FreeKMFKey(kmfh, &key); + + key = rawkey; + } else { + KMF_FreeKMFKey(kmfh, &key); + + /* Let kssl try to find the key. */ + nxkey = 1; + rv = KMF_GetCertIDData(&cert.certificate, &iddata); + } + } else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) { + KMF_FreeKMFKey(kmfh, &key); + + /* Let kssl try to find the key. */ + nxkey = 1; + rv = KMF_GetCertIDData(&cert.certificate, &iddata); + } else if (rv != KMF_OK || nkeys == 0) + goto done; + + 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); +done: + if (ncerts != 0) + KMF_FreeKMFCert(kmfh, &cert); + if (nkeys != 0) + KMF_FreeKMFKey(kmfh, &key); + if (idstr) + free(idstr); + + if (kmfh != NULL) + (void) KMF_Finalize(kmfh); + + return (kssl_params); +} + +/* + * add_cacerts + * + * 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) +{ + int i, newlen; + uint32_t certlen = 0, ncerts; char *buf; - uchar_t **cert_bufs; + KMF_RETURN rv; + KMF_X509_DER_CERT *certs = NULL; + KMF_FINDCERT_PARAMS fcparms; kssl_params_t *kssl_params; + KMF_HANDLE_T kmfh; + char *err = NULL; + + bzero(&fcparms, sizeof (fcparms)); + fcparms.kstype = KMF_KEYSTORE_OPENSSL; + fcparms.sslparms.certfile = (char *)cacert_chain_file; - ncerts = 0; - cert_bufs = PEM_get_rsa_key_certs(cacert_chain_file, - (char *)password_file, NULL, &cert_sizes, &ncerts); - if (cert_bufs == NULL || ncerts == 0) { + rv = KMF_Initialize(&kmfh, NULL, NULL); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error initializing KMF", err); + return (0); + } + rv = KMF_FindCert(kmfh, &fcparms, NULL, &ncerts); + 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)); + rv = KMF_FindCert(kmfh, &fcparms, certs, &ncerts); + + (void) KMF_Finalize(kmfh); + + if (rv != KMF_OK || ncerts == 0) { bzero(old_params, old_params->kssl_params_size); free(old_params); return (NULL); @@ -778,7 +658,7 @@ newlen = old_params->kssl_params_size; for (i = 0; i < ncerts; i++) - newlen += cert_sizes[i]; + newlen += certs[i].certificate.Length; /* * Get a bigger structure and update the @@ -789,12 +669,16 @@ kssl_params->kssl_params_size = newlen; kssl_params->kssl_certs.sc_count += ncerts; - /* Put the cert_sizes starting from sc_sizes[1] */ + /* Put the cert size info starting from sc_sizes[1] */ buf = (char *)kssl_params; buf += kssl_params->kssl_certs.sc_sizes_offset; bcopy(buf, &certlen, sizeof (uint32_t)); buf += sizeof (uint32_t); - bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t)); + for (i = 0; i < ncerts; i++) { + uint32_t size = (uint32_t)certs[i].certificate.Length; + bcopy(&size, buf, sizeof (uint32_t)); + buf += sizeof (uint32_t); + } /* Put the cert_bufs starting from sc_certs[1] */ buf = (char *)kssl_params; @@ -803,60 +687,65 @@ /* now the certs values */ for (i = 0; i < ncerts; i++) { - bcopy(cert_bufs[i], buf, cert_sizes[i]); - buf += cert_sizes[i]; + bcopy(certs[i].certificate.Data, buf, + certs[i].certificate.Length); + buf += certs[i].certificate.Length; } for (i = 0; i < ncerts; i++) - free(cert_bufs[i]); - free(cert_bufs); - free(cert_sizes); + KMF_FreeKMFCert(kmfh, &certs[i]); + free(certs); return (kssl_params); } +/* + * 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) { - uchar_t **cert_bufs; - int *cert_sizes, ncerts, i; - RSA *rsa; + int ncerts = 0, i; kssl_params_t *kssl_params; + KMF_RAW_KEY_DATA *rsa = NULL; + KMF_DATA *certs = NULL; - ncerts = 0; - cert_bufs = PEM_get_rsa_key_certs(filename, (char *)password_file, - &rsa, &cert_sizes, &ncerts); - if (rsa == NULL || cert_bufs == NULL || ncerts == 0) { + ncerts = PEM_get_rsa_key_certs(filename, (char *)password_file, + &rsa, &certs); + if (rsa == NULL || certs == NULL || ncerts == 0) { return (NULL); } if (verbose) (void) printf("%d certificates read successfully\n", ncerts); - kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs, - cert_sizes, paramsize); + kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL, + NULL, NULL); for (i = 0; i < ncerts; i++) - free(cert_bufs[i]); - free(cert_bufs); - free(cert_sizes); - RSA_free(rsa); + KMF_FreeData(&certs[i]); + free(certs); + KMF_FreeRawKey(rsa); + return (kssl_params); } +/* + * 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) { - RSA *rsa; + KMF_RAW_KEY_DATA *rsa = NULL; kssl_params_t *kssl_params; - uchar_t **cert_bufs; - int *cert_sizes, ncerts, i; + KMF_DATA *certs = NULL; + int ncerts = 0, i; - ncerts = 0; - cert_bufs = PKCS12_get_rsa_key_certs(filename, password_file, &rsa, - &cert_sizes, &ncerts); - if (cert_bufs == NULL || ncerts == 0) { + ncerts = PKCS12_get_rsa_key_certs(filename, + password_file, &rsa, &certs); + + if (certs == NULL || ncerts == 0) { (void) fprintf(stderr, "Unable to read cert and/or key from %s\n", filename); return (NULL); @@ -865,19 +754,17 @@ if (verbose) (void) printf("%d certificates read successfully\n", ncerts); - kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs, - cert_sizes, paramsize); + kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL, + NULL, NULL); for (i = 0; i < ncerts; i++) - free(cert_bufs[i]); - free(cert_bufs); - free(cert_sizes); + KMF_FreeData(&certs[i]); + free(certs); - RSA_free(rsa); + KMF_FreeRawKey(rsa); return (kssl_params); } - int parse_and_set_addr(char *server_address, char *server_port, struct sockaddr_in *addr) @@ -1105,6 +992,9 @@ return (FAILURE); } + /* + * Add the list of supported ciphers to the buffer. + */ bcopy(kssl_suites, kssl_params->kssl_suites, sizeof (kssl_params->kssl_suites)); kssl_params->kssl_params_size = bufsize; @@ -1114,8 +1004,7 @@ kssl_params->kssl_session_cache_size = scache_size; if (cacert_chain_file != NULL) { - kssl_params = add_cacerts(kssl_params, cacert_chain_file, - password_file); + kssl_params = add_cacerts(kssl_params, cacert_chain_file); if (kssl_params == NULL) { return (FAILURE); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c Thu Jan 11 18:12:31 2007 -0800 @@ -0,0 +1,172 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <assert.h> +#include <strings.h> + +#include <kmfapi.h> +#include "kssladm.h" + +/* + * Extract the Certificate and raw key data from a PKCS#12 file. + * The password needed for decrypting the PKCS#12 PDU is stored + * 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) +{ + char password_buf[1024]; + KMF_HANDLE_T kmfh; + KMF_RETURN rv = KMF_OK; + KMF_CREDENTIAL pk12cred; + KMF_DATA *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; + nkeys = 0; + + if (get_passphrase(password_file, password_buf, + sizeof (password_buf)) <= 0) { + perror("Unable to read passphrase"); + goto done; + } + pk12cred.cred = password_buf; + pk12cred.credlen = strlen(password_buf); + + rv = KMF_ImportPK12(kmfh, (char *)filename, &pk12cred, &tcerts, &ncerts, + &keys, &nkeys); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error importing PKCS12 data", err); + } + +done: + if (rv != KMF_OK) { + int i; + if (tcerts != NULL) { + for (i = 0; i < ncerts; i++) + KMF_FreeData(&tcerts[i]); + free(tcerts); + } + tcerts = NULL; + ncerts = 0; + if (keys != NULL) { + for (i = 0; i < nkeys; i++) + KMF_FreeRawKey(&keys[i]); + free(keys); + } + keys = NULL; + } + *certs = tcerts; + *rsa = keys; + + (void) KMF_Finalize(kmfh); + + return (ncerts); +} + +/* + * Parse a PEM file which should contain RSA private keys and + * their associated X.509v3 certificates. More than 1 may + * 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) +{ + KMF_HANDLE_T kmfh; + KMF_RETURN rv = KMF_OK; + KMF_CREDENTIAL creds; + KMF_DATA *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; + nkeys = 0; + + if (get_passphrase(password_file, password_buf, + sizeof (password_buf)) <= 0) { + perror("Unable to read passphrase"); + goto done; + } + creds.cred = password_buf; + creds.credlen = strlen(password_buf); + + rv = KMF_ImportKeypair(kmfh, (char *)filename, &creds, &tcerts, &ncerts, + &keys, &nkeys); + if (rv != KMF_OK) { + REPORT_KMF_ERROR(rv, "Error importing key data", err); + } + +done: + if (rv != KMF_OK) { + int i; + if (tcerts != NULL) { + for (i = 0; i < ncerts; i++) + KMF_FreeData(&tcerts[i]); + free(tcerts); + } + tcerts = NULL; + ncerts = 0; + if (keys != NULL) { + for (i = 0; i < nkeys; i++) + KMF_FreeRawKey(&keys[i]); + free(keys); + } + keys = NULL; + } + if (certs != NULL) + *certs = tcerts; + if (rsa != NULL) + *rsa = keys; + + (void) KMF_Finalize(kmfh); + + return (ncerts); +}
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/openssl_util.c Thu Jan 11 16:21:40 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,406 +0,0 @@ -/* - * 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 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <assert.h> -#include <strings.h> -#include <openssl/err.h> -#include <openssl/pem.h> -#include <openssl/x509.h> -#include <openssl/pkcs12.h> -#include "kssladm.h" - -static void -print_crypto_error(void) -{ - ERR_load_crypto_strings(); - ERR_print_errors_fp(stderr); -} - -/* ARGSUSED */ -static int -pem_password_callback(char *buf, int size, int rwflag, void *userdata) -{ - return (get_passphrase((const char *)userdata, buf, size)); -} - - -static STACK_OF(X509_INFO) * -PEM_get_x509_info_stack(const char *filename, char *password_file) -{ - FILE *fp; - STACK_OF(X509_INFO) *x509_info_stack; - - fp = fopen(filename, "r"); - if (fp == NULL) { - perror("Unable to open pem file for reading"); - return (NULL); - } - if (verbose) - (void) printf("In PEM_get_x509_info_stack: %s opened\n", - filename); - - OpenSSL_add_all_algorithms(); - - x509_info_stack = PEM_X509_INFO_read( - fp, NULL, pem_password_callback, password_file); - (void) fclose(fp); - - if (x509_info_stack == NULL) { - print_crypto_error(); - } - - return (x509_info_stack); -} - -static EVP_PKEY * -PEM_get_key(const char *filename, const char *password_file) -{ - FILE *fp; - EVP_PKEY *pkey = NULL; - - fp = fopen(filename, "r"); - if (fp == NULL) { - perror("Unable to open pem file for reading"); - return (NULL); - } - if (verbose) - (void) printf("In PEM_get_key: %s opened\n", filename); - - OpenSSL_add_all_algorithms(); - - pkey = PEM_read_PrivateKey(fp, NULL, pem_password_callback, - (char *)password_file); - (void) fclose(fp); - - if (pkey == NULL) { - print_crypto_error(); - } - - return (pkey); -} - -uchar_t * -get_modulus(uchar_t *ber_buf, int buflen, int *modlen) -{ - int i, j, v; - X509 *x; - EVP_PKEY *pkey; - BIGNUM *bn; - uchar_t *m = NULL, *mptr; - - x = d2i_X509(NULL, (const unsigned char **) &ber_buf, buflen); - if (x != NULL) { - pkey = X509_get_pubkey(x); - if (pkey == NULL) { - X509_free(x); - return (NULL); - } - - bn = pkey->pkey.rsa->n; - mptr = m = malloc(bn->top * BN_BYTES); - for (i = bn->top - 1; i >= 0; i--) { - for (j = BN_BITS2 - 8; j >= 0; j -= 8) { - v = ((int)(bn->d[i] >> (long)j)) & 0xff; - *m = v; - m++; - } - } - *modlen = bn->top * BN_BYTES; - EVP_PKEY_free(pkey); - X509_free(x); - } - - return (mptr); -} - -static uchar_t * -X509_to_bytes(X509 *cert, int *cert_size) -{ - uchar_t *cert_buf = NULL; - int size; - - size = i2d_X509(cert, &cert_buf); - if (size < 0) { - perror("Invalid cert\n"); - return (NULL); - } - - *cert_size = size; - return (cert_buf); -} - -static uchar_t ** -init_cert_vars(int **rlens) -{ - int i; - uchar_t **cert_bufs; - int *lcert_lens; - - cert_bufs = (uchar_t **)malloc(MAX_CHAIN_LENGTH * sizeof (uchar_t **)); - if (cert_bufs == NULL) - return (NULL); - for (i = 0; i < MAX_CHAIN_LENGTH; i++) - cert_bufs[i] = NULL; - - lcert_lens = malloc(MAX_CHAIN_LENGTH * sizeof (int)); - if (lcert_lens == NULL) { - free(cert_bufs); - return (NULL); - } - for (i = 0; i < MAX_CHAIN_LENGTH; i++) - lcert_lens[i] = 0; - - *rlens = lcert_lens; - return (cert_bufs); -} - -static void -print_subject(X509 *x) -{ - char buf[256]; - - (void) X509_NAME_oneline(X509_get_subject_name(x), - buf, sizeof (buf)); - (void) fprintf(stdout, "/* subject: %s */ \n", buf); -} - -/* - * Returns DER encoded certs in an array of pointers - * and their sizes in cert_sizes. If the rsa argument is - * not NULL, we return the RSA key in it. The caller needs - * to free the structures when done. - */ -uchar_t ** -PEM_get_rsa_key_certs(const char *filename, char *password_file, - RSA **rsa, int **cert_sizes, int *n) -{ - int i, cert_size, ncerts; - int *cert_lens; - uchar_t **cert_bufs; - EVP_PKEY *pkey = NULL; - X509_INFO *info; - X509_INFO *cert_infos[MAX_CHAIN_LENGTH]; - STACK_OF(X509_INFO) *x509_info_stack; - - x509_info_stack = PEM_get_x509_info_stack(filename, password_file); - if (x509_info_stack == NULL) { - return (NULL); - } - - ncerts = 0; - /* LINTED */ - while ((info = sk_X509_INFO_pop(x509_info_stack)) != NULL && - ncerts < MAX_CHAIN_LENGTH) { - cert_infos[ncerts] = info; - ncerts++; - if (verbose) - print_subject(info->x509); - } - - if (ncerts == 0) { - (void) fprintf(stderr, "No cert found\n"); - return (NULL); - } - - if (rsa != NULL) { - X509 *x; - - pkey = PEM_get_key(filename, password_file); - if (pkey == NULL) - return (NULL); - - x = cert_infos[ncerts - 1]->x509; - if (!X509_check_private_key(x, pkey)) { - (void) fprintf(stderr, "Error: Server certificate " - "and server private key do not match.\n"); - EVP_PKEY_free(pkey); - return (NULL); - } - - *rsa = EVP_PKEY_get1_RSA(pkey); - } - - if ((cert_bufs = init_cert_vars(&cert_lens)) == NULL) { - if (pkey != NULL) - EVP_PKEY_free(pkey); - return (NULL); - } - - /* - * cert_infos[] is constructed from a stack of certificates structure - * and hence the order is high level CA certificate first. SSL protocol - * needs the certificates in the order of low level CA certificate - * first. So, we walk cert_infos[] in reverse order below. - */ - for (i = 0; i < ncerts; i++) { - info = cert_infos[ncerts - 1 - i]; - cert_bufs[i] = X509_to_bytes(info->x509, &cert_size); - cert_lens[i] = cert_size; - X509_INFO_free(info); - } - - *cert_sizes = cert_lens; - *n = ncerts; - return (cert_bufs); -} - -static PKCS12 * -PKCS12_load(const char *filename) -{ - FILE *fp; - PKCS12 *p12; - - fp = fopen(filename, "r"); - if (fp == NULL) { - perror("Unable to open file for reading"); - return (NULL); - } - - OpenSSL_add_all_algorithms(); - - p12 = d2i_PKCS12_fp(fp, NULL); - (void) fclose(fp); - if (p12 == NULL) { - ERR_load_PKCS12_strings(); - ERR_print_errors_fp(stderr); - (void) fprintf(stderr, "Unable to load from %s\n", filename); - return (NULL); - } - - return (p12); -} - -/* - * Returns DER encoded certs in an array of pointers and their - * sizes in cert_sizes. The RSA key is returned in the rsa argument. - * The caller needs to free the structures when done. - */ -uchar_t ** -PKCS12_get_rsa_key_certs(const char *filename, const char *password_file, - RSA **rsa, int **cert_sizes, int *n) -{ - int i, ncerts, cert_size; - int *cert_lens; - char *password = NULL; - char password_buf[1024]; - uchar_t **cert_bufs = NULL; - uchar_t *cert_buf; - PKCS12 *p12 = NULL; - EVP_PKEY *pkey = NULL; - X509 *x509 = NULL; - X509 *certs[MAX_CHAIN_LENGTH]; - STACK_OF(X509) *ca = NULL; - - p12 = PKCS12_load(filename); - if (p12 == NULL) { - return (NULL); - } - - if (! PKCS12_verify_mac(p12, NULL, 0)) { - if (get_passphrase( - password_file, password_buf, sizeof (password_buf)) <= 0) { - perror("Unable to read passphrase"); - goto done; - } - - password = password_buf; - } - - if (PKCS12_parse(p12, password, &pkey, &x509, &ca) <= 0) { - (void) fprintf(stderr, "Unable to parse PKCS12 file.\n"); - goto done; - } - - if (pkey == NULL) { - (void) fprintf(stderr, "No key returned\n"); - goto done; - } - if (x509 == NULL) { - (void) fprintf(stderr, "No cert returned\n"); - goto done; - } - - if (!X509_check_private_key(x509, pkey)) { - (void) fprintf(stderr, "Error: Server certificate and server " - "private key do not match.\n"); - goto done; - } - - cert_buf = X509_to_bytes(x509, &cert_size); - if (cert_buf == NULL) - goto done; - X509_free(x509); - - *rsa = EVP_PKEY_get1_RSA(pkey); - if (*rsa == NULL) { - goto done; - } - - if ((cert_bufs = init_cert_vars(&cert_lens)) == NULL) { - RSA_free(*rsa); - goto done; - } - - ncerts = 0; - cert_bufs[0] = cert_buf; - cert_lens[0] = cert_size; - ncerts++; - - /* LINTED */ - while ((ca != NULL) && ((x509 = sk_X509_pop(ca)) != NULL) && - ncerts < MAX_CHAIN_LENGTH) { - certs[ncerts] = x509; - ncerts++; - if (verbose) - print_subject(x509); - } - - /* - * certs[1..ncerts-1] is constructed from a stack of certificates - * structure and hence the order is high level CA certificate first. - * SSL protocol needs the certificates in the order of low level CA - * certificate first. So, we walk certs[] in reverse order below. - */ - for (i = 1; i < ncerts; i++) { - x509 = certs[ncerts - i]; - cert_bufs[i] = X509_to_bytes(x509, &cert_size); - cert_lens[i] = cert_size; - X509_free(x509); - } - - *cert_sizes = cert_lens; - *n = ncerts; - -done: - if (pkey != NULL) - EVP_PKEY_free(pkey); - if (p12 != NULL) - PKCS12_free(p12); - - return (cert_bufs); -}
--- a/usr/src/lib/libkmf/include/kmfapi.h Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/include/kmfapi.h Thu Jan 11 18:12:31 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * @@ -269,6 +269,8 @@ extern KMF_RETURN KMF_ExportPK12(KMF_HANDLE_T, KMF_EXPORTP12_PARAMS *, char *); extern KMF_RETURN KMF_ImportPK12(KMF_HANDLE_T, char *, KMF_CREDENTIAL *, KMF_DATA **, int *, KMF_RAW_KEY_DATA **, int *); +extern KMF_RETURN KMF_ImportKeypair(KMF_HANDLE_T, char *, KMF_CREDENTIAL *, + KMF_DATA **, int *, KMF_RAW_KEY_DATA **, int *); /* * Get OCSP response operation. @@ -339,6 +341,7 @@ /* APIs for PKCS#11 token */ extern KMF_RETURN KMF_PK11TokenLookup(KMF_HANDLE_T, char *, CK_SLOT_ID *); +extern CK_SESSION_HANDLE KMF_GetPK11Handle(KMF_HANDLE_T); #ifdef __cplusplus }
--- a/usr/src/lib/libkmf/include/kmftypes.h Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/include/kmftypes.h Thu Jan 11 18:12:31 2007 -0800 @@ -23,7 +23,7 @@ * * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -110,8 +110,10 @@ KMF_FORMAT_ASN1 = 1, /* DER */ KMF_FORMAT_PEM = 2, KMF_FORMAT_PKCS12 = 3, - KMF_FORMAT_RAWKEY = 4 /* For FindKey operation */ + KMF_FORMAT_RAWKEY = 4, /* For FindKey operation */ + KMF_FORMAT_PEM_KEYPAIR = 5 } KMF_ENCODE_FORMAT; +#define KMF_FORMAT_NATIVE KMF_FORMAT_UNDEF typedef enum { KMF_ALL_CERTS = 0, @@ -193,6 +195,7 @@ boolean_t private; /* for finding CKA_PRIVATE objects */ boolean_t sensitive; boolean_t not_extractable; + boolean_t token; /* true == token object, false == session */ } KMF_PKCS11_PARAMS; typedef struct { @@ -599,7 +602,10 @@ KMF_ERR_UNINITIALIZED_TOKEN = 0x4d, KMF_ERR_INCOMPLETE_TBS_CERT = 0x4e, KMF_ERR_MISSING_ERRCODE = 0x4f, - KMF_KEYSTORE_ALREADY_INITIALIZED = 0x50 + KMF_KEYSTORE_ALREADY_INITIALIZED = 0x50, + KMF_ERR_SENSITIVE_KEY = 0x51, + KMF_ERR_UNEXTRACTABLE_KEY = 0x52, + KMF_ERR_KEY_MISMATCH = 0x53 } KMF_RETURN; typedef enum {
--- a/usr/src/lib/libkmf/libkmf/common/certop.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/libkmf/common/certop.c Thu Jan 11 18:12:31 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright(c) 1995-2000 Intel Corporation. All rights reserved. @@ -2289,6 +2289,49 @@ return (rv); } +KMF_RETURN +KMF_ImportKeypair(KMF_HANDLE_T handle, char *filename, + KMF_CREDENTIAL *cred, + KMF_DATA **certs, int *ncerts, + KMF_RAW_KEY_DATA **rawkeys, int *nkeys) +{ + KMF_RETURN rv; + KMF_PLUGIN *plugin; + KMF_RETURN (*import_keypair)(KMF_HANDLE *, + char *, KMF_CREDENTIAL *, + KMF_DATA **, int *, + KMF_RAW_KEY_DATA **, int *); + + CLEAR_ERROR(handle, rv); + if (rv != KMF_OK) + return (rv); + + if (filename == NULL || + cred == NULL || + certs == NULL || ncerts == NULL || + rawkeys == NULL || nkeys == NULL) + return (KMF_ERR_BAD_PARAMETER); + + /* + * Use the Keypair reader from the OpenSSL plugin. + */ + plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); + if (plugin == NULL || plugin->dldesc == NULL) { + return (KMF_ERR_PLUGIN_NOTFOUND); + } + + import_keypair = (KMF_RETURN(*)())dlsym(plugin->dldesc, + "openssl_import_keypair"); + if (import_keypair == NULL) { + return (KMF_ERR_FUNCTION_NOT_FOUND); + } + + /* Use OpenSSL interfaces to get raw key and cert data */ + rv = import_keypair(handle, filename, cred, certs, ncerts, + rawkeys, nkeys); + + return (rv); +} KMF_BOOL IsEqualOid(KMF_OID *Oid1, KMF_OID *Oid2)
--- a/usr/src/lib/libkmf/libkmf/common/generalop.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/libkmf/common/generalop.c Thu Jan 11 18:12:31 2007 -0800 @@ -19,10 +19,9 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 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" @@ -135,7 +134,10 @@ {KMF_ERR_UNINITIALIZED_TOKEN, "KMF_ERR_UNINITIALIZED_TOKEN"}, {KMF_ERR_INCOMPLETE_TBS_CERT, "KMF_ERR_INCOMPLETE_TBS_CERT"}, {KMF_ERR_MISSING_ERRCODE, "KMF_ERR_MISSING_ERRCODE"}, - {KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"} + {KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"}, + {KMF_ERR_SENSITIVE_KEY, "KMF_ERR_SENSITIVE_KEY"}, + {KMF_ERR_UNEXTRACTABLE_KEY, "KMF_ERR_UNEXTRACTABLE_KEY"}, + {KMF_ERR_KEY_MISMATCH, "KMF_ERR_KEY_MISMATCH"} }; @@ -720,6 +722,8 @@ } else { *fmt = KMF_FORMAT_ASN1; } + } else if (memcmp(buf, "Bag Attr", 8) == 0) { + *fmt = KMF_FORMAT_PEM_KEYPAIR; } else { /* Cannot determine this file format */ *fmt = 0;
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers Thu Jan 11 18:12:31 2007 -0800 @@ -18,8 +18,7 @@ # # CDDL HEADER END # -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -105,12 +104,14 @@ KMF_GetKMFErrorString; KMF_GetOCSPForCert; KMF_GetOCSPStatusForCert; + KMF_GetPK11Handle; KMF_GetPluginErrorString; KMF_GetPolicy; KMF_GetSymKeyValue; KMF_HexString2Bytes; KMF_ImportCRL; KMF_ImportCert; + KMF_ImportKeypair; KMF_ImportPK12; KMF_Initialize; KMF_IsCRLFile;
--- a/usr/src/lib/libkmf/libkmf/common/pk11tokens.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/libkmf/common/pk11tokens.c Thu Jan 11 18:12:31 2007 -0800 @@ -17,11 +17,10 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -529,3 +528,9 @@ return (kmf_rv); } + +CK_SESSION_HANDLE +KMF_GetPK11Handle(KMF_HANDLE_T kmfh) +{ + return (kmfh->pk11handle); +}
--- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/mapfile-vers Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/mapfile-vers Thu Jan 11 18:12:31 2007 -0800 @@ -18,8 +18,7 @@ # # CDDL HEADER END # -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -56,6 +55,7 @@ OpenSSL_StorePrivateKey; OpenSSL_VerifyCRLFile; openssl_read_pkcs12; + openssl_import_keypair; local: *; };
--- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c Thu Jan 11 18:12:31 2007 -0800 @@ -20,12 +20,13 @@ * * OpenSSL keystore wrapper * - * Copyright 2006 Sun Microsystems, Inc. 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 <stdlib.h> #include <kmfapiP.h> #include <ber_der.h> #include <oidsalg.h> @@ -99,6 +100,13 @@ mutex_t init_lock = DEFAULTMUTEX; static int ssl_initialized = 0; +static KMF_RETURN +extract_objects(KMF_HANDLE *, char *, CK_UTF8CHAR *, CK_ULONG, + EVP_PKEY **, KMF_DATA **, int *); + +static KMF_RETURN +kmf_load_cert(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *, KMF_DATA *); + KMF_RETURN OpenSSL_FindCert(KMF_HANDLE_T, KMF_FINDCERT_PARAMS *, @@ -567,6 +575,99 @@ return (rv); } +static int +datacmp(const void *a, const void *b) +{ + KMF_DATA *adata = (KMF_DATA *)a; + KMF_DATA *bdata = (KMF_DATA *)b; + if (adata->Length > bdata->Length) + return (-1); + if (adata->Length < bdata->Length) + return (1); + return (0); +} + +static KMF_RETURN +load_certs(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params, char *pathname, + KMF_DATA **certlist, uint32_t *numcerts) +{ + KMF_RETURN rv = KMF_OK; + int i; + KMF_DATA *certs = NULL; + int nc = 0; + int hits = 0; + KMF_ENCODE_FORMAT format; + + rv = KMF_GetFileFormat(pathname, &format); + if (rv != KMF_OK) { + if (rv == KMF_ERR_OPEN_FILE) + rv = KMF_ERR_CERT_NOT_FOUND; + return (rv); + } + if (format == KMF_FORMAT_ASN1) { + /* load a single certificate */ + certs = (KMF_DATA *)malloc(sizeof (KMF_DATA)); + if (certs == NULL) + return (KMF_ERR_MEMORY); + certs->Data = NULL; + certs->Length = 0; + rv = kmf_load_cert(kmfh, params, pathname, certs); + if (rv == KMF_OK) { + *certlist = certs; + *numcerts = 1; + } + 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_objects(kmfh, pathname, + (uchar_t *)NULL, 0, NULL, + &certs, &nc); + } else { + return (KMF_ERR_ENCODING); + } + + if (rv != KMF_OK) + return (rv); + + for (i = 0; i < nc; i++) { + if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) { + rv = KMF_CheckCertDate(kmfh, &certs[i]); + } else if (params->find_cert_validity == KMF_EXPIRED_CERTS) { + rv = KMF_CheckCertDate(kmfh, &certs[i]); + if (rv == KMF_OK) + rv = KMF_ERR_CERT_NOT_FOUND; + if (rv == KMF_ERR_VALIDITY_PERIOD) + rv = KMF_OK; + } + if (rv != KMF_OK) { + /* Remove this cert from the list by clearing it. */ + KMF_FreeData(&certs[i]); + } else { + hits++; /* count valid certs found */ + } + rv = KMF_OK; + } + if (rv == KMF_OK && hits == 0) { + rv = KMF_ERR_CERT_NOT_FOUND; + } else if (rv == KMF_OK && hits > 0) { + /* + * Sort the list of certs by length to put the cleared ones + * at the end so they don't get accessed by the caller. + */ + qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp); + *certlist = certs; + + /* since we sorted the list, just return the number of hits */ + *numcerts = hits; + } + return (rv); +} + static KMF_RETURN kmf_load_cert(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params, @@ -631,7 +732,8 @@ if (format == KMF_FORMAT_ASN1) pkey = d2i_PrivateKey_bio(keyfile, NULL); - else if (format == KMF_FORMAT_PEM) + else if (format == KMF_FORMAT_PEM || + format == KMF_FORMAT_PEM_KEYPAIR) pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL); end: @@ -652,8 +754,8 @@ { KMF_RETURN rv = KMF_OK; KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; - KMF_DATA certdata = {NULL, 0}; char *fullpath; + int i; if (num_certs == NULL || params == NULL) return (KMF_ERR_BAD_PARAMETER); @@ -677,6 +779,9 @@ } while ((dp = readdir(dirp)) != NULL) { char *fname; + KMF_DATA *certlist = NULL; + uint32_t numcerts = 0; + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; @@ -684,34 +789,43 @@ fname = get_fullpath(fullpath, (char *)&dp->d_name); - rv = kmf_load_cert(kmfh, params, fname, - &certdata); + rv = load_certs(kmfh, params, fname, &certlist, + &numcerts); if (rv != KMF_OK) { free(fname); - KMF_FreeData(&certdata); + if (certlist != NULL) { + for (i = 0; i < numcerts; i++) + KMF_FreeData(&certlist[i]); + free(certlist); + } continue; } /* If load succeeds, add certdata to the list */ if (kmf_cert != NULL) { - kmf_cert[n].certificate.Data = certdata.Data; - kmf_cert[n].certificate.Length = - certdata.Length; - - kmf_cert[n].kmf_private.keystore_type = - KMF_KEYSTORE_OPENSSL; - kmf_cert[n].kmf_private.flags = - KMF_FLAG_CERT_VALID; - kmf_cert[n].kmf_private.label = fname; - - certdata.Data = NULL; - certdata.Length = 0; + for (i = 0; i < numcerts; i++) { + kmf_cert[n].certificate.Data = + certlist[i].Data; + kmf_cert[n].certificate.Length = + certlist[i].Length; + + kmf_cert[n].kmf_private.keystore_type = + KMF_KEYSTORE_OPENSSL; + kmf_cert[n].kmf_private.flags = + KMF_FLAG_CERT_VALID; + kmf_cert[n].kmf_private.label = + strdup(fname); + n++; + } + free(certlist); } else { - free(fname); - KMF_FreeData(&certdata); + for (i = 0; i < numcerts; i++) + KMF_FreeData(&certlist[i]); + free(certlist); + n += numcerts; } - n++; + free(fname); } (*num_certs) = n; if (*num_certs == 0) @@ -721,33 +835,42 @@ exit: (void) closedir(dirp); } else { - /* Just try to load a single certificate */ - rv = kmf_load_cert(kmfh, params, fullpath, &certdata); + KMF_DATA *certlist = NULL; + uint32_t numcerts = 0; + + rv = load_certs(kmfh, params, fullpath, &certlist, &numcerts); if (rv != KMF_OK) { free(fullpath); - KMF_FreeData(&certdata); return (rv); } - if (kmf_cert != NULL) { - kmf_cert->certificate.Data = certdata.Data; - kmf_cert->certificate.Length = certdata.Length; - kmf_cert->kmf_private.keystore_type = - KMF_KEYSTORE_OPENSSL; - kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID; - kmf_cert->kmf_private.label = fullpath; + if (kmf_cert != NULL && certlist != NULL) { + for (i = 0; i < numcerts; i++) { + kmf_cert[i].certificate.Data = + certlist[i].Data; + kmf_cert[i].certificate.Length = + certlist[i].Length; + kmf_cert[i].kmf_private.keystore_type = + KMF_KEYSTORE_OPENSSL; + kmf_cert[i].kmf_private.flags = + KMF_FLAG_CERT_VALID; + kmf_cert[i].kmf_private.label = + strdup(fullpath); + } + free(certlist); } else { - KMF_FreeData(&certdata); + if (certlist != NULL) { + for (i = 0; i < numcerts; i++) + KMF_FreeData(&certlist[i]); + free(certlist); + } } - - *num_certs = 1; - } - - if (kmf_cert == NULL || rv != KMF_OK) - free(fullpath); + *num_certs = numcerts; + } + + free(fullpath); return (rv); - } void @@ -3265,6 +3388,107 @@ 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 + * private key and an associated public key wrapped in an x509 cert. + * However, the file may be just a list of X509 certs with no keys. + */ +static KMF_RETURN +extract_objects(KMF_HANDLE *kmfh, char *filename, CK_UTF8CHAR *pin, + CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs, + int *numcerts) +/* ARGSUSED */ +{ + KMF_RETURN rv = KMF_OK; + FILE *fp; + STACK_OF(X509_INFO) *x509_info_stack; + int i, ncerts = 0; + EVP_PKEY *pkey = NULL; + X509_INFO *info; + X509 *x; + X509_INFO *cert_infos[MAX_CHAIN_LENGTH]; + KMF_DATA *certlist = NULL; + + if (priv_key) + *priv_key = NULL; + if (certs) + *certs = NULL; + fp = fopen(filename, "r"); + 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); + } + + /*LINTED*/ + while ((info = sk_X509_INFO_pop(x509_info_stack)) != NULL && + ncerts < MAX_CHAIN_LENGTH) { + cert_infos[ncerts] = info; + ncerts++; + } + + if (ncerts == 0) { + (void) fclose(fp); + return (KMF_ERR_CERT_NOT_FOUND); + } + + if (priv_key != NULL) { + rewind(fp); + pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin); + } + (void) fclose(fp); + + x = cert_infos[ncerts - 1]->x509; + /* + * Make sure the private key matchs the last cert in the file. + */ + if (pkey != NULL && !X509_check_private_key(x, pkey)) { + EVP_PKEY_free(pkey); + return (KMF_ERR_KEY_MISMATCH); + } + + certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA)); + if (certlist == NULL) { + if (pkey != NULL) + EVP_PKEY_free(pkey); + X509_INFO_free(info); + return (KMF_ERR_MEMORY); + } + + /* + * Convert all of the certs to DER format. + */ + for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) { + info = cert_infos[ncerts - 1 - i]; + + rv = ssl_cert2KMFDATA(kmfh, info->x509, &certlist[i]); + + if (rv != KMF_OK) { + free(certlist); + certlist = NULL; + ncerts = 0; + } + X509_INFO_free(info); + } + + if (numcerts != NULL) + *numcerts = ncerts; + if (certs != NULL) + *certs = certlist; + + if (priv_key == NULL && pkey != NULL) + EVP_PKEY_free(pkey); + else if (priv_key != NULL && pkey != NULL) + *priv_key = pkey; + + return (rv); +} + /* * Helper function to decrypt and parse PKCS#12 import file. */ @@ -3517,7 +3741,7 @@ } /* Also add any included CA certs to the list */ - for (i = 0; i != sk_X509_num(sslcacerts); i++) { + for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) { X509 *c; /* * sk_X509_value() is macro that embeds a cast to (X509 *). @@ -3601,6 +3825,54 @@ } KMF_RETURN +openssl_import_keypair(KMF_HANDLE *kmfh, + char *filename, KMF_CREDENTIAL *cred, + KMF_DATA **certlist, int *ncerts, + KMF_RAW_KEY_DATA **keylist, int *nkeys) +{ + KMF_RETURN rv = KMF_OK; + EVP_PKEY *privkey = NULL; + KMF_ENCODE_FORMAT format; + + /* + * auto-detect the file format, regardless of what + * the 'format' parameters in the params say. + */ + rv = KMF_GetFileFormat(filename, &format); + if (rv != KMF_OK) { + if (rv == KMF_ERR_OPEN_FILE) + rv = KMF_ERR_CERT_NOT_FOUND; + return (rv); + } + + /* This function only works on PEM files */ + if (format != KMF_FORMAT_PEM && + format != KMF_FORMAT_PEM_KEYPAIR) + return (KMF_ERR_ENCODING); + + *certlist = NULL; + *keylist = NULL; + *ncerts = 0; + *nkeys = 0; + rv = extract_objects(kmfh, filename, + (uchar_t *)cred->cred, + (uint32_t)cred->credlen, + &privkey, certlist, ncerts); + + /* Reached end of import file? */ + if (rv == KMF_OK) + /* Convert keys and certs to exportable format */ + rv = convertPK12Objects(kmfh, privkey, NULL, NULL, + keylist, nkeys, NULL, NULL); + +end: + if (privkey) + EVP_PKEY_free(privkey); + + return (rv); +} + +KMF_RETURN OpenSSL_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params, KMF_RAW_KEY_DATA *key) {
--- a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c Thu Jan 11 16:21:40 2007 -0800 +++ b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c Thu Jan 11 18:12:31 2007 -0800 @@ -21,7 +21,7 @@ /* * PKCS11 token KMF Plugin * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -57,6 +57,9 @@ search_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *, boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *); +static CK_RV +getObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **); + static KMF_RETURN keyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **); @@ -213,13 +216,12 @@ CK_CERTIFICATE_TYPE cktype; CK_OBJECT_CLASS class; - CK_BBOOL cktrusted, token; CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len; CK_BYTE *subject = NULL, *value = NULL; - CK_BYTE *label = NULL; - CK_ULONG label_len = 0; + char *label = NULL; CK_ATTRIBUTE templ[10]; + (void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE)); SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class)); /* Is this a certificate object ? */ @@ -230,30 +232,32 @@ } SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype)); - SETATTR(templ, 1, CKA_TOKEN, &token, sizeof (token)); - SETATTR(templ, 2, CKA_TRUSTED, &cktrusted, sizeof (cktrusted)); - - ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 3); + ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1); if (ckrv != CKR_OK || cktype != CKC_X_509) { SET_ERROR(kmfh, ckrv); return (ckrv); } else { + int i = 0; /* What attributes are available and how big are they? */ - subject_len = issuer_len = serno_len = id_len = value_len = - label_len = 0; - SETATTR(templ, 0, CKA_SUBJECT, NULL, subject_len); - SETATTR(templ, 1, CKA_ISSUER, NULL, issuer_len); - SETATTR(templ, 2, CKA_SERIAL_NUMBER, NULL, serno_len); - SETATTR(templ, 3, CKA_ID, NULL, id_len); - SETATTR(templ, 4, CKA_VALUE, NULL, value_len); - SETATTR(templ, 5, CKA_LABEL, NULL, label_len); + subject_len = issuer_len = serno_len = id_len = value_len = 0; + + SETATTR(templ, i, CKA_SUBJECT, NULL, subject_len); + i++; + SETATTR(templ, i, CKA_ISSUER, NULL, issuer_len); + i++; + SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len); + i++; + SETATTR(templ, i, CKA_ID, NULL, id_len); + i++; + SETATTR(templ, i, CKA_VALUE, NULL, value_len); + i++; /* * Query the object with NULL values in the pValue spot * so we know how much space to allocate for each field. */ - ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 6); + ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i); if (ckrv != CKR_OK) { SET_ERROR(kmfh, ckrv); return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */ @@ -264,7 +268,6 @@ serno_len = templ[2].ulValueLen; id_len = templ[3].ulValueLen; value_len = templ[4].ulValueLen; - label_len = templ[5].ulValueLen; /* * For PKCS#11 CKC_X_509 certificate objects, @@ -288,17 +291,6 @@ SETATTR(templ, i, CKA_VALUE, value, value_len); i++; - if (label_len > 0) { - label = malloc(label_len + 1); - if (label == NULL) { - rv = KMF_ERR_MEMORY; - goto errout; - } - (void) memset(label, 0, label_len + 1); - SETATTR(templ, i, CKA_LABEL, label, - label_len); - i++; - } /* re-query the object with room for the value attr */ ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, @@ -315,7 +307,11 @@ kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED; kmfcert->kmf_private.keystore_type = KMF_KEYSTORE_PK11TOKEN; - kmfcert->kmf_private.label = (char *)label; + + ckrv = getObjectLabel(kmfh, hObj, &label); + if (ckrv == CKR_OK && label != NULL) { + kmfcert->kmf_private.label = (char *)label; + } rv = KMF_OK; } @@ -1024,7 +1020,7 @@ CK_RV ckrv; CK_ULONG subject_len, issuer_len, serno_len; - CK_BYTE *subject, *issuer, *serial; + CK_BYTE *subject, *issuer, *serial, nullserno; CK_BBOOL true = TRUE; CK_CERTIFICATE_TYPE certtype = CKC_X_509; CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; @@ -1082,8 +1078,13 @@ serial = signed_cert_ptr->certificate.serialNumber.val; serno_len = signed_cert_ptr->certificate.serialNumber.len; } else { - rv = KMF_ERR_ENCODING; - goto cleanup; + /* + * RFC3280 says to gracefully handle certs with serial numbers + * of 0. + */ + nullserno = '\0'; + serial = &nullserno; + serno_len = 1; } /* Generate an ID from the SPKI data */ @@ -1110,7 +1111,6 @@ SETATTR(x509templ, i, CKA_LABEL, label, strlen(label)); i++; } - /* * The cert object handle is actually "leaked" here. If the app * really wants to clean up the data space, it will have to call @@ -1999,6 +1999,7 @@ get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa) { KMF_RETURN rv = KMF_OK; + CK_RV ckrv; CK_SESSION_HANDLE sess = kmfh->pk11handle; CK_ATTRIBUTE rsa_pri_attrs[8] = { { CKA_MODULUS, NULL, 0 }, @@ -2013,10 +2014,16 @@ CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE); int i; - if ((rv = C_GetAttributeValue(sess, obj, + if ((ckrv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != CKR_OK) { - SET_ERROR(kmfh, rv); - return (KMF_ERR_INTERNAL); + 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); + else + return (KMF_ERR_INTERNAL); } /* Allocate memory for each attribute. */ @@ -2314,7 +2321,6 @@ CK_ATTRIBUTE pTmpl[10]; CK_OBJECT_CLASS class; CK_BBOOL true = TRUE; - CK_BBOOL false = FALSE; CK_ULONG alg; CK_BBOOL is_token; @@ -2332,15 +2338,13 @@ else want_keys = MAXINT; /* count them all */ + is_token = parms->pkcs11parms.token; if (parms->keyclass == KMF_ASYM_PUB) { class = CKO_PUBLIC_KEY; - is_token = false; } else if (parms->keyclass == KMF_ASYM_PRI) { class = CKO_PRIVATE_KEY; - is_token = true; } else if (parms->keyclass == KMF_SYMMETRIC) { class = CKO_SECRET_KEY; - is_token = true; } else { return (KMF_ERR_BAD_KEY_CLASS); } @@ -2403,7 +2407,11 @@ i++; } - if (is_token) { + /* + * Authenticate if the object is a token object, + * a private or secred key, or if the user passed in credentials. + */ + if (parms->cred.credlen > 0) { rv = pk11_authenticate(handle, &parms->cred); if (rv != KMF_OK) { return (rv); @@ -2462,17 +2470,18 @@ /* "numkeys" indicates the number that were actually found */ *numkeys = n; } - if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0 && - parms->format == KMF_FORMAT_RAWKEY) { - /* Convert keys to "rawkey" format */ - for (i = 0; i < (*numkeys); i++) { - KMF_RAW_KEY_DATA *rkey = NULL; - rv = keyObj2RawKey(handle, &keys[i], &rkey); - if (rv == KMF_OK) { - keys[i].keyp = rkey; - keys[i].israw = TRUE; - } else { - break; + if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) { + if (parms->format == KMF_FORMAT_RAWKEY) { + /* Convert keys to "rawkey" format */ + for (i = 0; i < (*numkeys); i++) { + KMF_RAW_KEY_DATA *rkey = NULL; + rv = keyObj2RawKey(handle, &keys[i], &rkey); + if (rv == KMF_OK) { + keys[i].keyp = rkey; + keys[i].israw = TRUE; + } else { + break; + } } } } @@ -2604,6 +2613,7 @@ SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++; SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++; SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length); i++; + SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++; /* * Only set the KeyUsage stuff if the KU extension was present.