1898Skais /*
2898Skais * CDDL HEADER START
3898Skais *
4898Skais * The contents of this file are subject to the terms of the
51933Skrishna * Common Development and Distribution License (the "License").
61933Skrishna * You may not use this file except in compliance with the License.
7898Skais *
8898Skais * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9898Skais * or http://www.opensolaris.org/os/licensing.
10898Skais * See the License for the specific language governing permissions
11898Skais * and limitations under the License.
12898Skais *
13898Skais * When distributing Covered Code, include this CDDL HEADER in each
14898Skais * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15898Skais * If applicable, add the following below this CDDL HEADER, with the
16898Skais * fields enclosed by brackets "[]" replaced with your own identifying
17898Skais * information: Portions Copyright [yyyy] [name of copyright owner]
18898Skais *
19898Skais * CDDL HEADER END
20898Skais */
211933Skrishna
22898Skais /*
23*12381SVladimir.Kotal@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24898Skais */
25898Skais
26898Skais #include <errno.h>
271933Skrishna #include <sys/sysmacros.h>
28898Skais #include <security/cryptoki.h>
29898Skais #include <security/pkcs11.h>
30898Skais #include <stdio.h>
31898Skais #include <strings.h>
323408Swyllys #include <sys/types.h>
333408Swyllys #include <sys/stat.h>
34898Skais #include <sys/socket.h>
353408Swyllys #include <netinet/in.h>
363408Swyllys #include <arpa/inet.h>
373408Swyllys #include <netdb.h>
383408Swyllys #include <fcntl.h>
393408Swyllys #include <inet/kssl/kssl.h>
403408Swyllys #include <cryptoutil.h>
41898Skais #include <libscf.h>
42898Skais #include "kssladm.h"
43898Skais
443408Swyllys #include <kmfapi.h>
453408Swyllys
46898Skais void
usage_create(boolean_t do_print)47898Skais usage_create(boolean_t do_print)
48898Skais {
49898Skais if (do_print)
50898Skais (void) fprintf(stderr, "Usage:\n");
51898Skais (void) fprintf(stderr, "kssladm create"
525051Swyllys " -f pkcs11 [-d softtoken_directory] -T <token_label>"
535051Swyllys " -C <certificate_label> -x <proxy_port>"
545051Swyllys " [-h <ca_certchain_file>]"
555051Swyllys " [options] [<server_address>] [<server_port>]\n");
56898Skais
57898Skais (void) fprintf(stderr, "kssladm create"
585051Swyllys " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
595051Swyllys " [options] [<server_address>] [<server_port>]\n");
60898Skais
61898Skais (void) fprintf(stderr, "kssladm create"
625051Swyllys " -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
635051Swyllys " [options] [<server_address>] [<server_port>]\n");
64898Skais
65898Skais (void) fprintf(stderr, "options are:\n"
665051Swyllys "\t[-c <ciphersuites>]\n"
675051Swyllys "\t[-p <password_file>]\n"
685051Swyllys "\t[-t <ssl_session_cache_timeout>]\n"
695051Swyllys "\t[-z <ssl_session_cache_size>]\n"
705051Swyllys "\t[-v]\n");
71898Skais }
72898Skais
73898Skais /*
74898Skais * Everything is allocated in one single contiguous buffer.
75898Skais * The layout is the following:
76898Skais * . the kssl_params_t structure
772800Skrishna * . optional buffer containing pin (if key is non extractable)
78898Skais * . the array of key attribute structs, (value of ck_attrs)
79898Skais * . the key attributes values (values of ck_attrs[i].ck_value);
801933Skrishna * . the array of sizes of the certificates, (referred to as sc_sizes[])
811933Skrishna * . the certificates values (referred to as sc_certs[])
82898Skais *
83898Skais * The address of the certs and key attributes values are offsets
841933Skrishna * from the beginning of the big buffer. sc_sizes_offset points
851933Skrishna * to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
86898Skais */
87898Skais static kssl_params_t *
kmf_to_kssl(int nxkey,KMF_RAW_KEY_DATA * rsa,int ncerts,KMF_X509_DER_CERT * certs,int * paramsize,char * token_label,KMF_DATA * idstr,KMF_CREDENTIAL * creds)883408Swyllys kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts,
895536Swyllys KMF_X509_DER_CERT *certs, int *paramsize,
905536Swyllys char *token_label, KMF_DATA *idstr,
913408Swyllys KMF_CREDENTIAL *creds)
92898Skais {
931933Skrishna int i, tcsize;
94898Skais kssl_params_t *kssl_params;
95898Skais kssl_key_t *key;
96898Skais char *buf;
97898Skais uint32_t bufsize;
983408Swyllys static CK_BBOOL true = TRUE;
993408Swyllys static CK_BBOOL false = FALSE;
1003408Swyllys static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
1013408Swyllys static CK_KEY_TYPE keytype = CKK_RSA;
1023408Swyllys kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
1033408Swyllys CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = {
1043408Swyllys {CKA_TOKEN, &true, sizeof (true)},
1053408Swyllys {CKA_EXTRACTABLE, &false, sizeof (false)},
1063408Swyllys {CKA_CLASS, &class, sizeof (class) },
1073408Swyllys {CKA_KEY_TYPE, &keytype, sizeof (keytype) },
1083408Swyllys {CKA_ID, NULL, 0}
1093408Swyllys };
1103408Swyllys kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = {
111898Skais {SUN_CKA_MODULUS, NULL, 0},
112898Skais {SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
113898Skais {SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
114898Skais {SUN_CKA_PRIME_1, NULL, 0},
115898Skais {SUN_CKA_PRIME_2, NULL, 0},
116898Skais {SUN_CKA_EXPONENT_1, NULL, 0},
117898Skais {SUN_CKA_EXPONENT_2, NULL, 0},
118898Skais {SUN_CKA_COEFFICIENT, NULL, 0}
119898Skais };
1203408Swyllys KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT];
121898Skais int attr_cnt;
122898Skais
1233408Swyllys if (nxkey && idstr != NULL) {
1243408Swyllys exkey_attrs[4].pValue = idstr->Data;
1253408Swyllys exkey_attrs[4].ulValueLen = idstr->Length;
1263408Swyllys }
1271933Skrishna tcsize = 0;
1281933Skrishna for (i = 0; i < ncerts; i++)
1295536Swyllys tcsize += certs[i].certificate.Length;
1301933Skrishna
131898Skais bufsize = sizeof (kssl_params_t);
1323408Swyllys bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t)));
133898Skais
1343408Swyllys if (!nxkey) {
1353408Swyllys bzero(priv_key_bignums, sizeof (KMF_BIGINT) *
1365051Swyllys MAX_ATTR_CNT);
1373408Swyllys /* and the key attributes */
1383408Swyllys priv_key_bignums[0] = rsa->rawdata.rsa.mod;
1393408Swyllys priv_key_bignums[1] = rsa->rawdata.rsa.pubexp;
1403408Swyllys priv_key_bignums[2] = rsa->rawdata.rsa.priexp;
1413408Swyllys priv_key_bignums[3] = rsa->rawdata.rsa.prime1;
1423408Swyllys priv_key_bignums[4] = rsa->rawdata.rsa.prime2;
1433408Swyllys priv_key_bignums[5] = rsa->rawdata.rsa.exp1;
1443408Swyllys priv_key_bignums[6] = rsa->rawdata.rsa.exp2;
1453408Swyllys priv_key_bignums[7] = rsa->rawdata.rsa.coef;
1463408Swyllys
1473408Swyllys if (rsa->rawdata.rsa.mod.val == NULL ||
1485051Swyllys rsa->rawdata.rsa.priexp.val == NULL) {
1493408Swyllys (void) fprintf(stderr,
1505051Swyllys "missing required attributes in private key.\n");
1513408Swyllys return (NULL);
1523408Swyllys }
153898Skais
1543408Swyllys attr_cnt = 0;
1553408Swyllys for (i = 0; i < MAX_ATTR_CNT; i++) {
1563408Swyllys if (priv_key_bignums[i].val == NULL)
1573408Swyllys continue;
1583408Swyllys kssl_attrs[attr_cnt].ka_type =
1595051Swyllys kssl_tmpl_attrs[i].ka_type;
1603408Swyllys kssl_attrs[attr_cnt].ka_value_len =
1615051Swyllys priv_key_bignums[i].len;
1623408Swyllys bufsize += sizeof (crypto_object_attribute_t) +
1633408Swyllys kssl_attrs[attr_cnt].ka_value_len;
1643408Swyllys attr_cnt++;
1653408Swyllys }
1663408Swyllys } else {
1673408Swyllys /*
1683408Swyllys * Compute space for the attributes and values that the
1693408Swyllys * kssl kernel module will need in order to search for
1703408Swyllys * the private key.
1713408Swyllys */
1723408Swyllys for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) {
1733408Swyllys bufsize += sizeof (crypto_object_attribute_t) +
1745051Swyllys exkey_attrs[attr_cnt].ulValueLen;
1753408Swyllys }
1763408Swyllys if (creds)
1773408Swyllys bufsize += creds->credlen;
178898Skais }
179898Skais
1802800Skrishna /* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
1811933Skrishna bufsize += sizeof (uint32_t);
1821933Skrishna
183898Skais /* Now the big memory allocation */
184898Skais if ((buf = calloc(bufsize, 1)) == NULL) {
185898Skais (void) fprintf(stderr,
186898Skais "Cannot allocate memory for the kssl_params "
187898Skais "and values\n");
188898Skais return (NULL);
189898Skais }
190898Skais
191898Skais /* LINTED */
192898Skais kssl_params = (kssl_params_t *)buf;
193898Skais
194898Skais buf = (char *)(kssl_params + 1);
195898Skais
1963408Swyllys if (!nxkey) {
1973408Swyllys /* the keys attributes structs array */
1983408Swyllys key = &kssl_params->kssl_privkey;
1993408Swyllys key->ks_format = CRYPTO_KEY_ATTR_LIST;
2003408Swyllys key->ks_count = attr_cnt;
2013408Swyllys key->ks_attrs_offset = buf - (char *)kssl_params;
2023408Swyllys buf += attr_cnt * sizeof (kssl_object_attribute_t);
2033408Swyllys
2043408Swyllys attr_cnt = 0;
2053408Swyllys /* then the key attributes values */
2063408Swyllys for (i = 0; i < MAX_ATTR_CNT; i++) {
2073408Swyllys if (priv_key_bignums[i].val == NULL)
2083408Swyllys continue;
2093408Swyllys (void) memcpy(buf, priv_key_bignums[i].val,
2105051Swyllys priv_key_bignums[i].len);
2113408Swyllys kssl_attrs[attr_cnt].ka_value_offset =
2123408Swyllys buf - (char *)kssl_params;
2133408Swyllys buf += kssl_attrs[attr_cnt].ka_value_len;
2143408Swyllys attr_cnt++;
2153408Swyllys }
2163408Swyllys } else {
2173408Swyllys char tlabel[CRYPTO_EXT_SIZE_LABEL];
2183408Swyllys bzero(tlabel, sizeof (tlabel));
2193408Swyllys (void) strlcpy(tlabel, token_label, sizeof (tlabel));
2203408Swyllys
2213408Swyllys /*
2223408Swyllys * For a non-extractable key, we must provide the PIN
2233408Swyllys * so the kssl module can access the token to find
2243408Swyllys * the key handle.
2253408Swyllys */
2263408Swyllys kssl_params->kssl_is_nxkey = 1;
2273408Swyllys bcopy(tlabel, kssl_params->kssl_token.toklabel,
2285051Swyllys CRYPTO_EXT_SIZE_LABEL);
2293408Swyllys kssl_params->kssl_token.pinlen = creds->credlen;
2303408Swyllys kssl_params->kssl_token.tokpin_offset =
2315051Swyllys buf - (char *)kssl_params;
2323408Swyllys kssl_params->kssl_token.ck_rv = 0;
2333408Swyllys bcopy(creds->cred, buf, creds->credlen);
2343408Swyllys buf += creds->credlen;
235898Skais
2363408Swyllys /*
2373408Swyllys * Next in the buffer, we must provide the attributes
2383408Swyllys * that the kssl module will use to search in the
2393408Swyllys * token to find the protected key handle.
2403408Swyllys */
2413408Swyllys key = &kssl_params->kssl_privkey;
2423408Swyllys key->ks_format = CRYPTO_KEY_ATTR_LIST;
2433408Swyllys key->ks_count = attr_cnt;
2443408Swyllys key->ks_attrs_offset = buf - (char *)kssl_params;
2453408Swyllys
2463408Swyllys buf += attr_cnt * sizeof (kssl_object_attribute_t);
2473408Swyllys for (i = 0; i < attr_cnt; i++) {
2483408Swyllys bcopy(exkey_attrs[i].pValue, buf,
2495051Swyllys exkey_attrs[i].ulValueLen);
2503408Swyllys
2513408Swyllys kssl_attrs[i].ka_type = exkey_attrs[i].type;
2523408Swyllys kssl_attrs[i].ka_value_offset =
2535051Swyllys buf - (char *)kssl_params;
2543408Swyllys kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen;
2553408Swyllys
2563408Swyllys buf += exkey_attrs[i].ulValueLen;
2573408Swyllys }
2583408Swyllys }
2593408Swyllys /* Copy the key attributes array here */
2603408Swyllys bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
2615051Swyllys attr_cnt * sizeof (kssl_object_attribute_t));
2623408Swyllys
2633408Swyllys buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
2643408Swyllys
2653408Swyllys /*
2663408Swyllys * Finally, add the certificate chain to the buffer.
2673408Swyllys */
2683408Swyllys kssl_params->kssl_certs.sc_count = ncerts;
2693408Swyllys
2703408Swyllys /* First, an array of certificate sizes */
2713408Swyllys for (i = 0; i < ncerts; i++) {
2725536Swyllys uint32_t certsz = (uint32_t)certs[i].certificate.Length;
2733408Swyllys char *p = buf + (i * sizeof (uint32_t));
2743408Swyllys bcopy(&certsz, p, sizeof (uint32_t));
275898Skais }
276898Skais
2771933Skrishna kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
2781933Skrishna buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
2791933Skrishna
2801933Skrishna kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
2813408Swyllys
2823408Swyllys /* Now add the certificate data (ASN.1 DER encoded) */
2831933Skrishna for (i = 0; i < ncerts; i++) {
2845536Swyllys bcopy(certs[i].certificate.Data, buf,
2855536Swyllys certs[i].certificate.Length);
2865536Swyllys buf += certs[i].certificate.Length;
2871933Skrishna }
2881933Skrishna
289898Skais *paramsize = bufsize;
290898Skais return (kssl_params);
291898Skais }
292898Skais
2933408Swyllys /*
2943408Swyllys * Extract a sensitive key via wrap/unwrap operations.
2953408Swyllys *
2963408Swyllys * This function requires that we call PKCS#11 API directly since
2973408Swyllys * KMF does not yet support wrapping/unwrapping of keys. By extracting
2983408Swyllys * a sensitive key in wrapped form, we then unwrap it into a session key
2993408Swyllys * object. KMF is then used to find the session key and return it in
3003408Swyllys * KMF_RAW_KEY format which is then passed along to KSSL by the caller.
3013408Swyllys */
3023408Swyllys static KMF_RETURN
get_sensitive_key_data(KMF_HANDLE_T kmfh,KMF_CREDENTIAL * creds,char * keylabel,char * idstr,KMF_KEY_HANDLE * key,KMF_KEY_HANDLE * rawkey)3035051Swyllys get_sensitive_key_data(KMF_HANDLE_T kmfh,
3045051Swyllys KMF_CREDENTIAL *creds, char *keylabel,
3055051Swyllys char *idstr, KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey)
3061933Skrishna {
3073408Swyllys KMF_RETURN rv = KMF_OK;
3083408Swyllys static CK_BYTE aes_param[16];
3093408Swyllys static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
3103408Swyllys static CK_KEY_TYPE privkey_type = CKK_RSA;
3113408Swyllys static CK_BBOOL false = FALSE;
3125051Swyllys boolean_t kmftrue = B_TRUE;
3135051Swyllys boolean_t kmffalse = B_FALSE;
3143408Swyllys char *err = NULL;
3153408Swyllys char wrapkey_label[BUFSIZ];
3163408Swyllys int fd;
3173408Swyllys uint32_t nkeys = 0;
3183408Swyllys CK_RV ckrv;
3193408Swyllys CK_SESSION_HANDLE pk11session;
3203408Swyllys CK_BYTE aes_key_val[16];
3215051Swyllys int numattr = 0;
3225051Swyllys int idx;
3235051Swyllys KMF_ATTRIBUTE attrlist[16];
3245051Swyllys KMF_KEYSTORE_TYPE kstype;
3255051Swyllys KMF_KEY_CLASS kclass;
3265051Swyllys KMF_ENCODE_FORMAT format;
3273408Swyllys
3283408Swyllys CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param,
3293408Swyllys sizeof (aes_param)};
3303408Swyllys CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE;
3313408Swyllys CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE;
3323408Swyllys CK_BYTE *wrapped_privkey = NULL;
3333408Swyllys CK_ULONG wrapped_privkey_len = 0;
3343408Swyllys
3353408Swyllys CK_ATTRIBUTE unwrap_tmpl[] = {
3363408Swyllys /* code below depends on the following attribute order */
3373408Swyllys {CKA_TOKEN, &false, sizeof (false)},
3383408Swyllys {CKA_CLASS, &privkey_class, sizeof (privkey_class)},
3393408Swyllys {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
3403408Swyllys {CKA_SENSITIVE, &false, sizeof (false)},
3413408Swyllys {CKA_PRIVATE, &false, sizeof (false)},
3423408Swyllys {CKA_LABEL, NULL, 0}
3433408Swyllys };
3443408Swyllys
3453408Swyllys /*
3463408Swyllys * Create a wrap key with random data.
3473408Swyllys */
3483408Swyllys fd = open("/dev/urandom", O_RDONLY);
3493408Swyllys if (fd == -1) {
3503408Swyllys perror("Error reading /dev/urandom");
3513408Swyllys return (KMF_ERR_INTERNAL);
3523408Swyllys }
3533408Swyllys if (read(fd, aes_key_val, sizeof (aes_key_val)) !=
3545051Swyllys sizeof (aes_key_val)) {
3553408Swyllys perror("Error reading from /dev/urandom");
3563408Swyllys (void) close(fd);
3573408Swyllys return (KMF_ERR_INTERNAL);
3583408Swyllys }
3593408Swyllys (void) close(fd);
3603408Swyllys
3615051Swyllys pk11session = kmf_get_pk11_handle(kmfh);
3623408Swyllys
3633408Swyllys /*
3643408Swyllys * Login to create the wrap key stuff.
3653408Swyllys */
3663408Swyllys ckrv = C_Login(pk11session, CKU_USER,
3675051Swyllys (CK_UTF8CHAR_PTR)creds->cred, creds->credlen);
3683408Swyllys if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) {
3693408Swyllys (void) fprintf(stderr,
3705051Swyllys "Cannot login to the token. error = %s\n",
3715051Swyllys pkcs11_strerror(ckrv));
3723408Swyllys return (KMF_ERR_INTERNAL);
3733408Swyllys }
3743408Swyllys
3753408Swyllys /*
3763408Swyllys * Turn the random key into a PKCS#11 session object.
3773408Swyllys */
3783408Swyllys ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val,
3795051Swyllys sizeof (aes_key_val), &aes_key_obj);
3803408Swyllys if (ckrv != CKR_OK) {
3813408Swyllys (void) fprintf(stderr,
3825051Swyllys "Cannot create wrapping key. error = %s\n",
3835051Swyllys pkcs11_strerror(ckrv));
3843408Swyllys return (KMF_ERR_INTERNAL);
3853408Swyllys }
3863408Swyllys
3873408Swyllys /*
3883408Swyllys * Find the original private key that we are going to wrap.
3893408Swyllys */
3905051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN;
3915051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3925051Swyllys &kstype, sizeof (kstype));
3935051Swyllys numattr++;
3945051Swyllys
3955051Swyllys kclass = KMF_ASYM_PRI;
3965051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
3975051Swyllys &kclass, sizeof (kclass));
3985051Swyllys numattr++;
3995051Swyllys
4005051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
4015051Swyllys creds, sizeof (KMF_CREDENTIAL));
4025051Swyllys numattr++;
4035051Swyllys
4045051Swyllys if (keylabel) {
4055051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
4065051Swyllys keylabel, strlen(keylabel));
4075051Swyllys numattr++;
4085051Swyllys }
4095051Swyllys if (idstr) {
4105051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
4115051Swyllys idstr, strlen(idstr));
4125051Swyllys numattr++;
4135051Swyllys }
4145051Swyllys format = KMF_FORMAT_NATIVE;
4155051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
4165051Swyllys &format, sizeof (format));
4175051Swyllys numattr++;
4185051Swyllys
4195051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
4205051Swyllys &kmftrue, sizeof (kmftrue));
4215051Swyllys numattr++;
4225051Swyllys
4235051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
4245051Swyllys &kmftrue, sizeof (kmftrue));
4255051Swyllys numattr++;
4265051Swyllys
4275051Swyllys nkeys = 1;
4285051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
4295051Swyllys &nkeys, sizeof (nkeys));
4305051Swyllys numattr++;
4315051Swyllys
4325051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
4335051Swyllys key, sizeof (KMF_KEY_HANDLE));
4345051Swyllys numattr++;
4355051Swyllys
4365051Swyllys rv = kmf_find_key(kmfh, numattr, attrlist);
4373408Swyllys if (rv != KMF_OK) {
4383408Swyllys REPORT_KMF_ERROR(rv, "Error finding private key", err);
4393408Swyllys goto out;
4403408Swyllys }
4413408Swyllys
4423408Swyllys /*
4433408Swyllys * Get the size of the wrapped private key.
4443408Swyllys */
4453408Swyllys bzero(aes_param, sizeof (aes_param));
4463408Swyllys ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
4475051Swyllys aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
4485051Swyllys NULL, &wrapped_privkey_len);
4493408Swyllys if (ckrv != CKR_OK) {
4503408Swyllys /*
4513408Swyllys * Most common error here is that the token doesn't
4523408Swyllys * support the wrapping mechanism or the key is
4533408Swyllys * marked non-extractable. Return an error and let
4543408Swyllys * the caller deal with it gracefully.
4553408Swyllys */
4563408Swyllys (void) fprintf(stderr,
4575051Swyllys "Cannot get wrap key size. error = %s\n",
4585051Swyllys pkcs11_strerror(ckrv));
4593408Swyllys rv = KMF_ERR_INTERNAL;
4603408Swyllys goto out;
4613408Swyllys }
4623408Swyllys wrapped_privkey = malloc(wrapped_privkey_len);
4633408Swyllys if (wrapped_privkey == NULL) {
4643408Swyllys rv = KMF_ERR_MEMORY;
4653408Swyllys goto out;
4663408Swyllys }
4673408Swyllys /*
4683408Swyllys * Now get the actual wrapped key data.
4693408Swyllys */
4703408Swyllys ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
4715051Swyllys aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
4725051Swyllys wrapped_privkey, &wrapped_privkey_len);
4733408Swyllys if (ckrv != CKR_OK) {
4743408Swyllys (void) fprintf(stderr,
4755051Swyllys "Cannot wrap private key. error = %s\n",
4765051Swyllys pkcs11_strerror(ckrv));
4773408Swyllys rv = KMF_ERR_INTERNAL;
4783408Swyllys goto out;
4793408Swyllys }
4803408Swyllys /*
4813408Swyllys * Create a label for the wrapped session key so we can find
4823408Swyllys * it easier later.
4833408Swyllys */
48410520SBhargava.Yenduri@Sun.COM (void) snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d",
4855051Swyllys getpid());
4863408Swyllys
4873408Swyllys unwrap_tmpl[5].pValue = wrapkey_label;
4883408Swyllys unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label);
4893408Swyllys
4903408Swyllys /*
4913408Swyllys * Unwrap the key into the template and create a temporary
4923408Swyllys * session private key.
4933408Swyllys */
4943408Swyllys ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj,
4955051Swyllys wrapped_privkey, wrapped_privkey_len,
4965051Swyllys unwrap_tmpl, 6, &sess_privkey_obj);
4973408Swyllys if (ckrv != CKR_OK) {
4983408Swyllys (void) fprintf(stderr,
4995051Swyllys "Cannot unwrap private key. error = %s\n",
5005051Swyllys pkcs11_strerror(ckrv));
5013408Swyllys rv = KMF_ERR_INTERNAL;
5023408Swyllys goto out;
5033408Swyllys }
5043408Swyllys
5053408Swyllys /*
5063408Swyllys * Use KMF to find the session key and return it as RAW data
5073408Swyllys * so we can pass it along to KSSL.
5083408Swyllys */
5095051Swyllys kclass = KMF_ASYM_PRI;
5105051Swyllys if ((idx = kmf_find_attr(KMF_KEYCLASS_ATTR, attrlist, numattr)) != -1) {
5115051Swyllys attrlist[idx].pValue = &kclass;
5125051Swyllys }
5135051Swyllys
5145051Swyllys format = KMF_FORMAT_RAWKEY;
5155051Swyllys if ((idx = kmf_find_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
5165051Swyllys numattr)) != -1) {
5175051Swyllys attrlist[idx].pValue = &format;
5185051Swyllys }
5195051Swyllys if (wrapkey_label != NULL &&
5205051Swyllys (idx = kmf_find_attr(KMF_KEYLABEL_ATTR, attrlist, numattr)) != -1) {
5215051Swyllys attrlist[idx].pValue = wrapkey_label;
5225051Swyllys attrlist[idx].valueLen = strlen(wrapkey_label);
5235051Swyllys }
5243408Swyllys
5255051Swyllys if ((idx = kmf_find_attr(KMF_PRIVATE_BOOL_ATTR, attrlist,
5265051Swyllys numattr)) != -1) {
5275051Swyllys attrlist[idx].pValue = &kmffalse;
5285051Swyllys }
5295051Swyllys if ((idx = kmf_find_attr(KMF_TOKEN_BOOL_ATTR, attrlist,
5305051Swyllys numattr)) != -1) {
5315051Swyllys attrlist[idx].pValue = &kmffalse;
5325051Swyllys }
5335051Swyllys
5345051Swyllys if ((idx = kmf_find_attr(KMF_KEY_HANDLE_ATTR, attrlist,
5355051Swyllys numattr)) != -1) {
5365051Swyllys attrlist[idx].pValue = rawkey;
5375051Swyllys }
5385051Swyllys /*
5395051Swyllys * Clear the IDSTR attribute since it is not part of the
5405051Swyllys * wrapped session key.
5415051Swyllys */
5425051Swyllys if ((idx = kmf_find_attr(KMF_IDSTR_ATTR, attrlist,
5435051Swyllys numattr)) != -1) {
5445051Swyllys attrlist[idx].pValue = NULL;
5455051Swyllys attrlist[idx].valueLen = 0;
5465051Swyllys }
5475051Swyllys
5485051Swyllys /* The wrapped key should not be sensitive. */
5495051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_SENSITIVE_BOOL_ATTR,
5505051Swyllys &false, sizeof (false));
5515051Swyllys numattr++;
5525051Swyllys
5535051Swyllys rv = kmf_find_key(kmfh, numattr, attrlist);
5543408Swyllys if (rv != KMF_OK) {
5553408Swyllys REPORT_KMF_ERROR(rv, "Error finding raw private key", err);
5563408Swyllys goto out;
5573408Swyllys }
5583408Swyllys out:
5593408Swyllys if (wrapped_privkey)
5603408Swyllys free(wrapped_privkey);
5613408Swyllys
5623408Swyllys if (aes_key_obj != CK_INVALID_HANDLE)
56310520SBhargava.Yenduri@Sun.COM (void) C_DestroyObject(pk11session, aes_key_obj);
5643408Swyllys
5653408Swyllys if (sess_privkey_obj != CK_INVALID_HANDLE)
56610520SBhargava.Yenduri@Sun.COM (void) C_DestroyObject(pk11session, sess_privkey_obj);
5673408Swyllys
5683408Swyllys return (rv);
5693408Swyllys }
5703408Swyllys
5713408Swyllys static kssl_params_t *
load_from_pkcs11(KMF_HANDLE_T kmfh,const char * token_label,const char * password_file,const char * certname,int * bufsize)5725536Swyllys load_from_pkcs11(KMF_HANDLE_T kmfh,
5735536Swyllys const char *token_label, const char *password_file,
5743408Swyllys const char *certname, int *bufsize)
5753408Swyllys {
5763408Swyllys KMF_RETURN rv;
5773408Swyllys KMF_X509_DER_CERT cert;
5783408Swyllys KMF_KEY_HANDLE key, rawkey;
5793408Swyllys KMF_CREDENTIAL creds;
5803408Swyllys KMF_DATA iddata = { NULL, 0 };
5813408Swyllys kssl_params_t *kssl_params = NULL;
5823408Swyllys uint32_t ncerts, nkeys;
5833408Swyllys char *err, *idstr = NULL;
5843408Swyllys char password_buf[1024];
5853408Swyllys int nxkey = 0;
5865051Swyllys int numattr = 0;
5875051Swyllys KMF_ATTRIBUTE attrlist[16];
5885051Swyllys KMF_KEYSTORE_TYPE kstype;
5895051Swyllys KMF_KEY_CLASS kclass;
5905051Swyllys KMF_ENCODE_FORMAT format;
5915051Swyllys boolean_t false = B_FALSE;
5925051Swyllys boolean_t true = B_TRUE;
5933408Swyllys
5943408Swyllys if (get_passphrase(password_file, password_buf,
5955051Swyllys sizeof (password_buf)) <= 0) {
5963408Swyllys perror("Unable to read passphrase");
5973408Swyllys goto done;
5983408Swyllys }
5993408Swyllys creds.cred = password_buf;
6003408Swyllys creds.credlen = strlen(password_buf);
6013408Swyllys
6025051Swyllys (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
6035051Swyllys (void) memset(&rawkey, 0, sizeof (KMF_KEY_HANDLE));
6045051Swyllys
6055051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN;
6065051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6075051Swyllys &kstype, sizeof (kstype));
6085051Swyllys numattr++;
6093408Swyllys
6105051Swyllys if (token_label && strlen(token_label)) {
6115051Swyllys kmf_set_attr_at_index(attrlist, numattr,
6125051Swyllys KMF_TOKEN_LABEL_ATTR,
6135051Swyllys (void *)token_label, strlen(token_label));
6145051Swyllys numattr++;
6155051Swyllys }
6163408Swyllys
6175051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_READONLY_ATTR,
6185051Swyllys &false, sizeof (false));
6195051Swyllys numattr++;
6205051Swyllys
6215051Swyllys rv = kmf_configure_keystore(kmfh, numattr, attrlist);
6223408Swyllys if (rv != KMF_OK) {
6233408Swyllys REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err);
6243408Swyllys goto done;
6253408Swyllys }
6263408Swyllys
6273408Swyllys /*
6283408Swyllys * Find the certificate matching the given label.
6293408Swyllys */
6305051Swyllys numattr = 0;
6315051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN;
6325051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6335051Swyllys &kstype, sizeof (kstype));
6345051Swyllys numattr++;
6355051Swyllys
6365051Swyllys if (certname) {
6375051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
6385051Swyllys (void *)certname, strlen(certname));
6395051Swyllys numattr++;
6405051Swyllys }
6415051Swyllys ncerts = 1;
6425051Swyllys
6435051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
6445051Swyllys &ncerts, sizeof (ncerts));
6455051Swyllys numattr++;
6465051Swyllys
6475051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
6485051Swyllys &cert, sizeof (cert));
6495051Swyllys numattr++;
6505051Swyllys
6515051Swyllys rv = kmf_find_cert(kmfh, numattr, attrlist);
6523408Swyllys if (rv != KMF_OK || ncerts == 0)
6533408Swyllys goto done;
6543408Swyllys
6553408Swyllys /*
6563408Swyllys * Find the associated private key for this cert by
6573408Swyllys * keying off of the label and the ASCII ID string.
6583408Swyllys */
6595051Swyllys rv = kmf_get_cert_id_str(&cert.certificate, &idstr);
6603408Swyllys if (rv != KMF_OK)
6613408Swyllys goto done;
6623408Swyllys
6635051Swyllys numattr = 1; /* attrlist[0] is already set to kstype */
6645051Swyllys
6655051Swyllys kclass = KMF_ASYM_PRI;
6665051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
6675051Swyllys &kclass, sizeof (kclass));
6685051Swyllys numattr++;
6695051Swyllys
6705051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
6715051Swyllys &creds, sizeof (KMF_CREDENTIAL));
6725051Swyllys numattr++;
6735051Swyllys
6745051Swyllys format = KMF_FORMAT_RAWKEY;
6755051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
6765051Swyllys &format, sizeof (format));
6775051Swyllys numattr++;
6783408Swyllys
6795051Swyllys if (certname) {
6805051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
6815051Swyllys (void *)certname, strlen(certname));
6825051Swyllys numattr++;
6835051Swyllys }
6845051Swyllys if (idstr) {
6855051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
6865051Swyllys (void *)idstr, strlen(idstr));
6875051Swyllys numattr++;
6885051Swyllys }
6895051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
6905051Swyllys &true, sizeof (true));
6915051Swyllys numattr++;
6925051Swyllys
6935051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
6945051Swyllys &true, sizeof (true));
6955051Swyllys numattr++;
6965051Swyllys
6975051Swyllys /* We only expect to find 1 key at most */
6985051Swyllys nkeys = 1;
6995051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
7005051Swyllys &nkeys, sizeof (nkeys));
7015051Swyllys numattr++;
7025051Swyllys
7035051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
7045051Swyllys &key, sizeof (KMF_KEY_HANDLE));
7055051Swyllys numattr++;
7065051Swyllys
7075051Swyllys rv = kmf_find_key(kmfh, numattr, attrlist);
7083408Swyllys if (rv == KMF_ERR_SENSITIVE_KEY) {
7095051Swyllys kmf_free_kmf_key(kmfh, &key);
7103408Swyllys /*
7113408Swyllys * Get a normal key handle and then do a wrap/unwrap
7123408Swyllys * in order to get the necessary raw data fields needed
7133408Swyllys * to send to KSSL.
7143408Swyllys */
7155051Swyllys format = KMF_FORMAT_NATIVE;
7165051Swyllys rv = get_sensitive_key_data(kmfh, &creds,
7175051Swyllys (char *)certname, idstr, &key, &rawkey);
7183408Swyllys if (rv == KMF_OK) {
7193408Swyllys /* Swap "key" for "rawkey" */
7205051Swyllys kmf_free_kmf_key(kmfh, &key);
7213408Swyllys
7223408Swyllys key = rawkey;
7233408Swyllys } else {
7245051Swyllys kmf_free_kmf_key(kmfh, &key);
7253408Swyllys
7263408Swyllys /* Let kssl try to find the key. */
7273408Swyllys nxkey = 1;
7285051Swyllys rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
7293408Swyllys }
7303408Swyllys } else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
7315051Swyllys kmf_free_kmf_key(kmfh, &key);
7323408Swyllys
7335051Swyllys /* Let kssl try to find the key. */
7345051Swyllys nxkey = 1;
7355051Swyllys rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
7363408Swyllys } else if (rv != KMF_OK || nkeys == 0)
7373408Swyllys goto done;
7383408Swyllys
7393408Swyllys if (rv == KMF_OK)
7403408Swyllys kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp,
7415536Swyllys 1, &cert, bufsize, (char *)token_label, &iddata, &creds);
7423408Swyllys done:
7433408Swyllys if (ncerts != 0)
7445051Swyllys kmf_free_kmf_cert(kmfh, &cert);
7453408Swyllys if (nkeys != 0)
7465051Swyllys kmf_free_kmf_key(kmfh, &key);
7473408Swyllys if (idstr)
7483408Swyllys free(idstr);
7493408Swyllys
7503408Swyllys return (kssl_params);
7513408Swyllys }
7523408Swyllys
7533408Swyllys /*
7543408Swyllys * add_cacerts
7553408Swyllys *
7563408Swyllys * Load a chain of certificates from a PEM file.
7573408Swyllys */
7583408Swyllys static kssl_params_t *
add_cacerts(KMF_HANDLE_T kmfh,kssl_params_t * old_params,const char * cacert_chain_file)7595536Swyllys add_cacerts(KMF_HANDLE_T kmfh,
7605536Swyllys kssl_params_t *old_params, const char *cacert_chain_file)
7613408Swyllys {
7623408Swyllys int i, newlen;
7633408Swyllys uint32_t certlen = 0, ncerts;
7641933Skrishna char *buf;
7653408Swyllys KMF_RETURN rv;
7663408Swyllys KMF_X509_DER_CERT *certs = NULL;
7671933Skrishna kssl_params_t *kssl_params;
7683408Swyllys char *err = NULL;
7695051Swyllys int numattr = 0;
7705051Swyllys KMF_ATTRIBUTE attrlist[16];
7715051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
7723408Swyllys
7735051Swyllys kstype = KMF_KEYSTORE_OPENSSL;
7741933Skrishna
7755051Swyllys ncerts = 0;
7765051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
7775051Swyllys &kstype, sizeof (KMF_KEYSTORE_TYPE));
7785051Swyllys numattr++;
7795051Swyllys
7805051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
7815051Swyllys (void *)cacert_chain_file, strlen(cacert_chain_file));
7825051Swyllys numattr++;
7835051Swyllys
7845051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
7855051Swyllys &ncerts, sizeof (ncerts));
7865051Swyllys numattr++;
7875051Swyllys
7885051Swyllys rv = kmf_find_cert(kmfh, numattr, attrlist);
7893408Swyllys if (rv != KMF_OK) {
7903408Swyllys REPORT_KMF_ERROR(rv, "Error finding CA certificates", err);
7913408Swyllys return (0);
7923408Swyllys }
7933408Swyllys certs = (KMF_X509_DER_CERT *)malloc(ncerts *
7945051Swyllys sizeof (KMF_X509_DER_CERT));
7953408Swyllys if (certs == NULL) {
7963408Swyllys (void) fprintf(stderr, "memory allocation error.\n");
7973408Swyllys return (NULL);
7983408Swyllys }
7993408Swyllys bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT));
8003408Swyllys
8015051Swyllys /* add new attribute for the cert list to be returned */
8025051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
8035051Swyllys certs, (ncerts * sizeof (KMF_X509_DER_CERT)));
8045051Swyllys numattr++;
8055051Swyllys rv = kmf_find_cert(kmfh, numattr, attrlist);
8065051Swyllys
8073408Swyllys if (rv != KMF_OK || ncerts == 0) {
8082800Skrishna bzero(old_params, old_params->kssl_params_size);
8091933Skrishna free(old_params);
8101933Skrishna return (NULL);
8111933Skrishna }
8121933Skrishna
8131933Skrishna if (verbose) {
8141933Skrishna (void) printf("%d certificates read successfully\n", ncerts);
8151933Skrishna }
8161933Skrishna
8171933Skrishna newlen = old_params->kssl_params_size;
8181933Skrishna for (i = 0; i < ncerts; i++)
8193408Swyllys newlen += certs[i].certificate.Length;
8201933Skrishna
8211933Skrishna /*
8221933Skrishna * Get a bigger structure and update the
8231933Skrishna * fields to account for the additional certs.
8241933Skrishna */
8251933Skrishna kssl_params = realloc(old_params, newlen);
8261933Skrishna
8271933Skrishna kssl_params->kssl_params_size = newlen;
8281933Skrishna kssl_params->kssl_certs.sc_count += ncerts;
8291933Skrishna
8303408Swyllys /* Put the cert size info starting from sc_sizes[1] */
8311933Skrishna buf = (char *)kssl_params;
8321933Skrishna buf += kssl_params->kssl_certs.sc_sizes_offset;
8331933Skrishna bcopy(buf, &certlen, sizeof (uint32_t));
8341933Skrishna buf += sizeof (uint32_t);
8353408Swyllys for (i = 0; i < ncerts; i++) {
8363408Swyllys uint32_t size = (uint32_t)certs[i].certificate.Length;
8373408Swyllys bcopy(&size, buf, sizeof (uint32_t));
8383408Swyllys buf += sizeof (uint32_t);
8393408Swyllys }
8401933Skrishna
8411933Skrishna /* Put the cert_bufs starting from sc_certs[1] */
8421933Skrishna buf = (char *)kssl_params;
8431933Skrishna buf += kssl_params->kssl_certs.sc_certs_offset;
8441933Skrishna buf += certlen;
8451933Skrishna
8461933Skrishna /* now the certs values */
8471933Skrishna for (i = 0; i < ncerts; i++) {
8483408Swyllys bcopy(certs[i].certificate.Data, buf,
8495051Swyllys certs[i].certificate.Length);
8503408Swyllys buf += certs[i].certificate.Length;
8511933Skrishna }
8521933Skrishna
8531933Skrishna for (i = 0; i < ncerts; i++)
8545051Swyllys kmf_free_kmf_cert(kmfh, &certs[i]);
8553408Swyllys free(certs);
8561933Skrishna
8571933Skrishna return (kssl_params);
8581933Skrishna }
8591933Skrishna
8603408Swyllys /*
8613408Swyllys * Find a key and certificate(s) from a single PEM file.
8623408Swyllys */
8631933Skrishna static kssl_params_t *
load_from_pem(KMF_HANDLE_T kmfh,const char * filename,const char * password_file,int * paramsize)8645536Swyllys load_from_pem(KMF_HANDLE_T kmfh, const char *filename,
8655536Swyllys const char *password_file, int *paramsize)
866898Skais {
8673408Swyllys int ncerts = 0, i;
868898Skais kssl_params_t *kssl_params;
8693408Swyllys KMF_RAW_KEY_DATA *rsa = NULL;
8705536Swyllys KMF_X509_DER_CERT *certs = NULL;
871898Skais
8725536Swyllys ncerts = PEM_get_rsa_key_certs(kmfh,
8735536Swyllys filename, (char *)password_file, &rsa, &certs);
8743408Swyllys if (rsa == NULL || certs == NULL || ncerts == 0) {
875898Skais return (NULL);
876898Skais }
877898Skais
878898Skais if (verbose)
8791933Skrishna (void) printf("%d certificates read successfully\n", ncerts);
880898Skais
8813408Swyllys kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
8825051Swyllys NULL, NULL);
883898Skais
8841933Skrishna for (i = 0; i < ncerts; i++)
8855536Swyllys kmf_free_kmf_cert(kmfh, &certs[i]);
8863408Swyllys free(certs);
8875051Swyllys kmf_free_raw_key(rsa);
8883408Swyllys
889898Skais return (kssl_params);
890898Skais }
891898Skais
8923408Swyllys /*
8933408Swyllys * Load a raw key and certificate(s) from a PKCS#12 file.
8943408Swyllys */
8951933Skrishna static kssl_params_t *
load_from_pkcs12(KMF_HANDLE_T kmfh,const char * filename,const char * password_file,int * paramsize)8965536Swyllys load_from_pkcs12(KMF_HANDLE_T kmfh, const char *filename,
8975536Swyllys const char *password_file, int *paramsize)
898898Skais {
8993408Swyllys KMF_RAW_KEY_DATA *rsa = NULL;
900898Skais kssl_params_t *kssl_params;
9015536Swyllys KMF_X509_DER_CERT *certs = NULL;
9023408Swyllys int ncerts = 0, i;
903898Skais
9045536Swyllys ncerts = PKCS12_get_rsa_key_certs(kmfh, filename,
9055051Swyllys password_file, &rsa, &certs);
9063408Swyllys
9073408Swyllys if (certs == NULL || ncerts == 0) {
908898Skais (void) fprintf(stderr,
909898Skais "Unable to read cert and/or key from %s\n", filename);
910898Skais return (NULL);
911898Skais }
912898Skais
913898Skais if (verbose)
9141933Skrishna (void) printf("%d certificates read successfully\n", ncerts);
9151933Skrishna
9163408Swyllys kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
9175051Swyllys NULL, NULL);
918898Skais
9191933Skrishna for (i = 0; i < ncerts; i++)
9205536Swyllys kmf_free_kmf_cert(kmfh, &certs[i]);
9213408Swyllys free(certs);
922898Skais
9235051Swyllys kmf_free_raw_key(rsa);
924898Skais return (kssl_params);
925898Skais }
926898Skais
927898Skais int
parse_and_set_addr(char * server_address,char * server_port,struct sockaddr_in6 * addr)928898Skais parse_and_set_addr(char *server_address, char *server_port,
92910520SBhargava.Yenduri@Sun.COM struct sockaddr_in6 *addr)
930898Skais {
931*12381SVladimir.Kotal@Sun.COM long long tmp_port;
932*12381SVladimir.Kotal@Sun.COM char *ep;
933*12381SVladimir.Kotal@Sun.COM
934898Skais if (server_port == NULL) {
935898Skais return (-1);
936898Skais }
937898Skais
938898Skais if (server_address == NULL) {
93910520SBhargava.Yenduri@Sun.COM addr->sin6_addr = in6addr_any;
940898Skais } else {
94110520SBhargava.Yenduri@Sun.COM struct hostent *hp;
94210520SBhargava.Yenduri@Sun.COM int error_num;
943898Skais
94410520SBhargava.Yenduri@Sun.COM if ((hp = (getipnodebyname(server_address, AF_INET6,
94510520SBhargava.Yenduri@Sun.COM AI_DEFAULT, &error_num))) == NULL) {
94610520SBhargava.Yenduri@Sun.COM (void) fprintf(stderr, "Error: Unknown host: %s\n",
94710520SBhargava.Yenduri@Sun.COM server_address);
94810520SBhargava.Yenduri@Sun.COM return (-1);
94910520SBhargava.Yenduri@Sun.COM }
950898Skais
95110520SBhargava.Yenduri@Sun.COM (void) memcpy((caddr_t)&addr->sin6_addr, hp->h_addr,
95210520SBhargava.Yenduri@Sun.COM hp->h_length);
95310520SBhargava.Yenduri@Sun.COM freehostent(hp);
954898Skais }
955898Skais
956898Skais errno = 0;
957*12381SVladimir.Kotal@Sun.COM tmp_port = strtoll(server_port, &ep, 10);
958*12381SVladimir.Kotal@Sun.COM if (server_port == ep || *ep != '\0' || errno != 0) {
959898Skais (void) fprintf(stderr, "Error: Invalid Port value: %s\n",
960898Skais server_port);
961898Skais return (-1);
962898Skais }
963*12381SVladimir.Kotal@Sun.COM if (tmp_port < 1 || tmp_port > 65535) {
964*12381SVladimir.Kotal@Sun.COM (void) fprintf(stderr, "Error: Port out of range: %s\n",
965*12381SVladimir.Kotal@Sun.COM server_port);
966*12381SVladimir.Kotal@Sun.COM return (-1);
967*12381SVladimir.Kotal@Sun.COM }
968*12381SVladimir.Kotal@Sun.COM /* It is safe to convert since the value is inside the boundaries. */
969*12381SVladimir.Kotal@Sun.COM addr->sin6_port = tmp_port;
970898Skais
971898Skais return (0);
972898Skais }
973898Skais
974898Skais /*
975898Skais * The order of the ciphers is important. It is used as the
976898Skais * default order (when -c is not specified).
977898Skais */
978898Skais struct csuite {
979898Skais const char *suite;
980898Skais uint16_t val;
981898Skais boolean_t seen;
982898Skais } cipher_suites[CIPHER_SUITE_COUNT - 1] = {
983898Skais {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE},
984898Skais {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE},
9856788Skrishna {"rsa_aes_256_cbc_sha", TLS_RSA_WITH_AES_256_CBC_SHA, B_FALSE},
9866788Skrishna {"rsa_aes_128_cbc_sha", TLS_RSA_WITH_AES_128_CBC_SHA, B_FALSE},
987898Skais {"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE},
988898Skais {"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE},
989898Skais };
990898Skais
9911933Skrishna static int
check_suites(char * suites,uint16_t * sarray)992898Skais check_suites(char *suites, uint16_t *sarray)
993898Skais {
994898Skais int i;
995898Skais int err = 0;
996898Skais char *suite;
997898Skais int sindx = 0;
998898Skais
999898Skais if (suites != NULL) {
1000898Skais for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
1001898Skais sarray[i] = CIPHER_NOTSET;
1002898Skais } else {
1003898Skais for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
1004898Skais sarray[i] = cipher_suites[i].val;
1005898Skais return (err);
1006898Skais }
1007898Skais
1008898Skais suite = strtok(suites, ",");
1009898Skais do {
1010898Skais for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
1011898Skais if (strcasecmp(suite, cipher_suites[i].suite) == 0) {
1012898Skais if (!cipher_suites[i].seen) {
1013898Skais sarray[sindx++] = cipher_suites[i].val;
1014898Skais cipher_suites[i].seen = B_TRUE;
1015898Skais }
1016898Skais break;
1017898Skais }
1018898Skais }
1019898Skais
1020898Skais if (i == (CIPHER_SUITE_COUNT - 1)) {
1021898Skais (void) fprintf(stderr,
1022898Skais "Unknown Cipher suite name: %s\n", suite);
1023898Skais err++;
1024898Skais }
1025898Skais } while ((suite = strtok(NULL, ",")) != NULL);
1026898Skais
1027898Skais return (err);
1028898Skais }
1029898Skais
1030898Skais int
do_create(int argc,char * argv[])1031898Skais do_create(int argc, char *argv[])
1032898Skais {
1033898Skais const char *softtoken_dir = NULL;
1034898Skais const char *token_label = NULL;
1035898Skais const char *password_file = NULL;
10361933Skrishna const char *cert_key_file = NULL;
10371933Skrishna const char *cacert_chain_file = NULL;
1038898Skais const char *certname = NULL;
1039898Skais char *suites = NULL;
1040898Skais uint32_t timeout = DEFAULT_SID_TIMEOUT;
1041898Skais uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES;
10422800Skrishna uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
1043898Skais int proxy_port = -1;
104410520SBhargava.Yenduri@Sun.COM struct sockaddr_in6 server_addr;
1045898Skais char *format = NULL;
1046898Skais char *port, *addr;
1047898Skais char c;
1048898Skais int pcnt;
1049898Skais kssl_params_t *kssl_params;
1050898Skais int bufsize;
10515536Swyllys KMF_HANDLE_T kmfh = NULL;
10525536Swyllys KMF_RETURN rv = KMF_OK;
10535536Swyllys char *err = NULL;
1054898Skais
1055898Skais argc -= 1;
1056898Skais argv += 1;
1057898Skais
10581933Skrishna while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) {
1059898Skais switch (c) {
1060898Skais case 'd':
1061898Skais softtoken_dir = optarg;
1062898Skais break;
1063898Skais case 'c':
1064898Skais suites = optarg;
1065898Skais break;
1066898Skais case 'C':
1067898Skais certname = optarg;
1068898Skais break;
1069898Skais case 'f':
1070898Skais format = optarg;
1071898Skais break;
10721933Skrishna case 'h':
10731933Skrishna cacert_chain_file = optarg;
10741933Skrishna break;
1075898Skais case 'i':
10761933Skrishna cert_key_file = optarg;
1077898Skais break;
1078898Skais case 'T':
1079898Skais token_label = optarg;
1080898Skais break;
1081898Skais case 'p':
1082898Skais password_file = optarg;
1083898Skais break;
1084898Skais case 't':
1085898Skais timeout = atoi(optarg);
1086898Skais break;
1087898Skais case 'x':
1088898Skais proxy_port = atoi(optarg);
1089898Skais break;
1090898Skais case 'v':
1091898Skais verbose = B_TRUE;
1092898Skais break;
1093898Skais case 'z':
1094898Skais scache_size = atoi(optarg);
1095898Skais break;
1096898Skais default:
1097898Skais goto err;
1098898Skais }
1099898Skais }
1100898Skais
1101898Skais pcnt = argc - optind;
1102898Skais if (pcnt == 0) {
1103898Skais port = "443"; /* default SSL port */
1104898Skais addr = NULL;
1105898Skais } else if (pcnt == 1) {
1106898Skais port = argv[optind];
1107898Skais addr = NULL;
1108898Skais } else if (pcnt == 2) {
1109898Skais addr = argv[optind];
1110898Skais port = argv[optind + 1];
1111898Skais } else {
1112898Skais goto err;
1113898Skais }
1114898Skais
1115898Skais if (parse_and_set_addr(addr, port, &server_addr) < 0) {
1116898Skais goto err;
1117898Skais }
1118898Skais
1119898Skais if (verbose) {
112010520SBhargava.Yenduri@Sun.COM char buffer[128];
112110520SBhargava.Yenduri@Sun.COM
112210520SBhargava.Yenduri@Sun.COM (void) inet_ntop(AF_INET6, &server_addr.sin6_addr, buffer,
112310520SBhargava.Yenduri@Sun.COM sizeof (buffer));
112410520SBhargava.Yenduri@Sun.COM (void) printf("addr = %s, port = %d\n", buffer,
112510520SBhargava.Yenduri@Sun.COM server_addr.sin6_port);
1126898Skais }
1127898Skais
1128898Skais if (format == NULL || proxy_port == -1) {
1129898Skais goto err;
1130898Skais }
1131898Skais
11322800Skrishna if (check_suites(suites, kssl_suites) != 0) {
11332800Skrishna goto err;
11342800Skrishna }
11352800Skrishna
11365536Swyllys rv = kmf_initialize(&kmfh, NULL, NULL);
11375536Swyllys if (rv != KMF_OK) {
11385536Swyllys REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
11395536Swyllys return (0);
11405536Swyllys }
11415536Swyllys
1142898Skais if (strcmp(format, "pkcs11") == 0) {
1143898Skais if (token_label == NULL || certname == NULL) {
1144898Skais goto err;
1145898Skais }
1146898Skais if (softtoken_dir != NULL) {
1147898Skais (void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1);
1148898Skais if (verbose) {
1149898Skais (void) printf(
1150898Skais "SOFTTOKEN_DIR=%s\n",
1151898Skais getenv("SOFTTOKEN_DIR"));
1152898Skais }
1153898Skais }
11545536Swyllys kssl_params = load_from_pkcs11(kmfh,
1155898Skais token_label, password_file, certname, &bufsize);
1156898Skais } else if (strcmp(format, "pkcs12") == 0) {
11571933Skrishna if (cert_key_file == NULL) {
1158898Skais goto err;
1159898Skais }
11605536Swyllys kssl_params = load_from_pkcs12(kmfh,
11611933Skrishna cert_key_file, password_file, &bufsize);
1162898Skais } else if (strcmp(format, "pem") == 0) {
11631933Skrishna if (cert_key_file == NULL) {
1164898Skais goto err;
1165898Skais }
11665536Swyllys kssl_params = load_from_pem(kmfh,
11671933Skrishna cert_key_file, password_file, &bufsize);
1168898Skais } else {
1169898Skais (void) fprintf(stderr, "Unsupported cert format: %s\n", format);
1170898Skais goto err;
1171898Skais }
1172898Skais
1173898Skais if (kssl_params == NULL) {
11745536Swyllys (void) kmf_finalize(kmfh);
1175898Skais return (FAILURE);
1176898Skais }
1177898Skais
11783408Swyllys /*
11793408Swyllys * Add the list of supported ciphers to the buffer.
11803408Swyllys */
11812800Skrishna bcopy(kssl_suites, kssl_params->kssl_suites,
11822800Skrishna sizeof (kssl_params->kssl_suites));
1183898Skais kssl_params->kssl_params_size = bufsize;
1184898Skais kssl_params->kssl_addr = server_addr;
1185898Skais kssl_params->kssl_session_cache_timeout = timeout;
1186898Skais kssl_params->kssl_proxy_port = proxy_port;
1187898Skais kssl_params->kssl_session_cache_size = scache_size;
1188898Skais
11891933Skrishna if (cacert_chain_file != NULL) {
11905536Swyllys kssl_params = add_cacerts(kmfh, kssl_params, cacert_chain_file);
11911933Skrishna if (kssl_params == NULL) {
11925536Swyllys bzero(kssl_params, bufsize);
11935536Swyllys free(kssl_params);
11945536Swyllys (void) kmf_finalize(kmfh);
11951933Skrishna return (FAILURE);
11961933Skrishna }
11971933Skrishna }
11981933Skrishna
1199898Skais if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) {
12002800Skrishna int err = CRYPTO_FAILED;
12012800Skrishna
12022800Skrishna if (kssl_params->kssl_is_nxkey)
12032800Skrishna err = kssl_params->kssl_token.ck_rv;
12042800Skrishna (void) fprintf(stderr,
12052800Skrishna "Error loading cert and key: 0x%x\n", err);
12065536Swyllys bzero(kssl_params, bufsize);
12075536Swyllys free(kssl_params);
12085536Swyllys (void) kmf_finalize(kmfh);
1209898Skais return (FAILURE);
1210898Skais }
1211898Skais
1212898Skais if (verbose)
1213898Skais (void) printf("Successfully loaded cert and key\n");
1214898Skais
12152800Skrishna bzero(kssl_params, bufsize);
1216898Skais free(kssl_params);
12175536Swyllys (void) kmf_finalize(kmfh);
1218898Skais return (SUCCESS);
1219898Skais
1220898Skais err:
1221898Skais usage_create(B_TRUE);
12225536Swyllys (void) kmf_finalize(kmfh);
1223898Skais return (SMF_EXIT_ERR_CONFIG);
1224898Skais }
1225