kssladm_create.c revision c892ebf1bef94f4f922f282c11516677c134dbe0
/*
* 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
* 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 <errno.h>
#include <sys/sysmacros.h>
#include <netdb.h> /* hostent */
#include <security/cryptoki.h>
#include <cryptoutil.h>
#include <stdio.h>
#include <strings.h>
#include <libscf.h>
#include "kssladm.h"
void
{
if (do_print)
" -f pkcs11 [-d softtoken_directory] -T <token_label>"
" -C <certificate_label> -x <proxy_port>"
" [-h <ca_certchain_file>]"
" [options] [<server_address>] [<server_port>]\n");
" -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
" [options] [<server_address>] [<server_port>]\n");
" -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
" [options] [<server_address>] [<server_port>]\n");
"\t[-c <ciphersuites>]\n"
"\t[-p <password_file>]\n"
"\t[-t <ssl_session_cache_timeout>]\n"
"\t[-z <ssl_session_cache_size>]\n"
"\t[-v]\n");
}
static uchar_t *
{
/* the certs ... */
return (NULL);
}
return (NULL);
return (NULL);
}
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().
*/
{CKA_MODULUS, NULL_PTR, 0},
{CKA_KEY_TYPE, NULL_PTR, 0},
};
/*
* Everything is allocated in one single contiguous buffer.
* The layout is the following:
* . the kssl_params_t structure
* . optional buffer containing pin (if key is non extractable)
* . the array of key attribute structs, (value of ck_attrs)
* . the key attributes values (values of ck_attrs[i].ck_value);
* . the array of sizes of the certificates, (referred to as sc_sizes[])
* . the certificates values (referred to as sc_certs[])
*
* The address of the certs and key attributes values are offsets
* from the beginning of the big buffer. sc_sizes_offset points
* to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
*/
static kssl_params_t *
{
int i;
int total_attr_cnt;
char *buf;
{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}
};
/* Get the certificate size */
bufsize = sizeof (kssl_params_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;
}
if (!is_nxkey) {
/* Add CKA_PRIVATE_EXPONENT for extractable key */
"Cannot get private key object attribute."
return (NULL);
}
bufsize += sizeof (crypto_object_attribute_t) +
}
/*
* 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) {
"Cannot get private key object attributes."
return (NULL);
}
for (i = 0; i < OPT_ATTR_CNT; i++) {
privkey_opt_attrs[i].ulValueLen == 0)
continue;
/* Structure copy */
bufsize += sizeof (crypto_object_attribute_t) +
}
} else
/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
/* Now the big memory allocation */
"Cannot allocate memory for the kssl_params "
"and values\n");
return (NULL);
}
/* LINTED */
if (is_nxkey) {
buf - (char *)kssl_params;
}
/* the keys attributes structs array */
/* These are attributes for which we already have the value */
for (i = 0; i < known_attr_cnt; i++) {
}
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++) {
buf - (char *)kssl_params;
}
"Cannot get private key object attributes."
return (NULL);
}
}
total_attr_cnt * sizeof (kssl_object_attribute_t));
/* now the certs values */
(void) C_CloseSession(sess);
return (kssl_params);
}
#define max_num_cert 32
static kssl_params_t *
{
{CKA_TOKEN, &true, sizeof (true)},
};
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_EXTRACTABLE, NULL_PTR, 0},
};
char passphrase[MAX_PIN_LENGTH];
"%-32s", token_label);
"Cannot initialize PKCS#11. error = %s\n",
return (NULL);
}
/* Get slot count */
"Cannot get PKCS#11 slot list. error = %s\n",
return (NULL);
}
if (pk11_slots == NULL) {
"Cannot get memory for %ld slots\n", slotcnt);
return (NULL);
}
"Cannot get PKCS#11 slot list. error = %s\n",
return (NULL);
}
if (verbose)
/* Search the token that matches the label */
while (slotcnt > 0) {
continue;
if (verbose)
(void) printf("slot [%ld] = %s\n",
sizeof (token_info.label)) == 0) {
break;
}
if (verbose) {
}
}
if (!bingo) {
return (NULL);
}
&sess);
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.
*/
sizeof (passphrase));
if (ulPinLen == 0) {
return (NULL);
}
ulPinLen);
return (NULL);
}
"Cannot initialize cert search."
return (NULL);
}
"Cannot retrieve cert object. error = %s\n",
return (NULL);
}
/* Who cares if this fails! */
(void) C_FindObjectsFinal(sess);
if (verbose)
if (cert_obj_count == 0) {
return (NULL);
}
/* Get the modulus value from the certificate */
"Cannot get certificate data for \"%s\".\n", certname);
return (NULL);
}
/* Store it for later use. We free the buffer at that time. */
"Cannot get Modulus in certificate \"%s\".\n", certname);
return (NULL);
}
/* Now get the private key */
return (NULL);
}
return (NULL);
}
/* Who cares if this fails! */
(void) C_FindObjectsFinal(sess);
if (privkey_obj_count == 0) {
return (NULL);
}
if (verbose) {
(void) printf("private key attributes: \n");
}
/*
* Store it for later use. The index of the attributes
* is the same in both the structures.
*/
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.
*/
"Cannot get CKA_EXTRACTABLE attribute."
return (NULL);
}
if (rv == CKR_ATTRIBUTE_TYPE_INVALID)
if (is_extractable) {
/* Now wrap the key, then unwrap it */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
CK_ATTRIBUTE unwrap_tmpl[] = {
/* code below depends on the following attribute order */
{CKA_TOKEN, &false, sizeof (false)},
{CKA_SENSITIVE, &false, sizeof (false)},
{CKA_PRIVATE, &false, sizeof (false)}
};
&aes_key_obj);
"Cannot create wrapping key. error = %s\n",
return (NULL);
}
/* get the size of the wrapped key */
return (NULL);
}
if (wrapped_privkey == NULL) {
return (NULL);
}
/* do the actual key wrapping */
return (NULL);
}
(void) printf("private key successfully wrapped, "
"wrapped blob length: %ld\n",
return (NULL);
}
(void) printf("session private key successfully unwrapped\n");
/* Store the one modified attribute and the two new attributes. */
}
}
#define MAX_OPENSSL_ATTR_CNT 8
/*
* See the comments for pkcs11_to_kssl() for the layout of the
* returned buffer.
*/
static kssl_params_t *
int *paramsize)
{
int i, tcsize;
char *buf;
{SUN_CKA_MODULUS, NULL, 0},
{SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
{SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
{SUN_CKA_PRIME_1, NULL, 0},
{SUN_CKA_PRIME_2, NULL, 0},
{SUN_CKA_EXPONENT_1, NULL, 0},
{SUN_CKA_EXPONENT_2, NULL, 0},
{SUN_CKA_COEFFICIENT, NULL, 0}
};
int attr_cnt;
tcsize = 0;
for (i = 0; i < ncerts; i++)
tcsize += cert_sizes[i];
bufsize = sizeof (kssl_params_t);
/* and the key attributes */
"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;
bufsize += sizeof (crypto_object_attribute_t) +
attr_cnt++;
}
/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
/* Now the big memory allocation */
"Cannot allocate memory for the kssl_params "
"and values\n");
return (NULL);
}
/* LINTED */
/* the keys attributes structs array */
attr_cnt = 0;
/* then the key attributes values */
for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) {
if (priv_key_bignums[i] == NULL)
continue;
buf - (char *)kssl_params;
attr_cnt++;
}
attr_cnt * sizeof (kssl_object_attribute_t));
/* now the certs values */
for (i = 0; i < ncerts; i++) {
buf += cert_sizes[i];
}
return (kssl_params);
}
static kssl_params_t *
const char *password_file)
{
int *cert_sizes;
char *buf;
ncerts = 0;
return (NULL);
}
if (verbose) {
}
for (i = 0; i < ncerts; i++)
newlen += cert_sizes[i];
/*
* Get a bigger structure and update the
* fields to account for the additional certs.
*/
/* Put the cert_sizes starting from sc_sizes[1] */
buf = (char *)kssl_params;
/* Put the cert_bufs starting from sc_certs[1] */
buf = (char *)kssl_params;
/* now the certs values */
for (i = 0; i < ncerts; i++) {
buf += cert_sizes[i];
}
for (i = 0; i < ncerts; i++)
return (kssl_params);
}
static kssl_params_t *
{
int *cert_sizes, ncerts, i;
ncerts = 0;
return (NULL);
}
if (verbose)
for (i = 0; i < ncerts; i++)
return (kssl_params);
}
static kssl_params_t *
int *paramsize)
{
int *cert_sizes, ncerts, i;
ncerts = 0;
&cert_sizes, &ncerts);
return (NULL);
}
if (verbose)
for (i = 0; i < ncerts; i++)
return (kssl_params);
}
int
struct sockaddr_in *addr)
{
if (server_port == NULL) {
return (-1);
}
if (server_address == NULL) {
} else {
"Error: Unknown host: %s\n",
return (-1);
}
hp->h_addr_list[0],
}
}
errno = 0;
return (-1);
}
return (0);
}
/*
* The order of the ciphers is important. It is used as the
* default order (when -c is not specified).
*/
struct csuite {
const char *suite;
};
static int
{
int i;
int err = 0;
char *suite;
int sindx = 0;
for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
sarray[i] = CIPHER_NOTSET;
} else {
for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
return (err);
}
do {
for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
if (!cipher_suites[i].seen) {
}
break;
}
}
if (i == (CIPHER_SUITE_COUNT - 1)) {
"Unknown Cipher suite name: %s\n", suite);
err++;
}
return (err);
}
int
{
const char *softtoken_dir = NULL;
const char *token_label = NULL;
const char *password_file = NULL;
const char *cert_key_file = NULL;
const char *cacert_chain_file = NULL;
int proxy_port = -1;
struct sockaddr_in server_addr;
char c;
int pcnt;
int bufsize;
argc -= 1;
argv += 1;
switch (c) {
case 'd':
break;
case 'c':
break;
case 'C':
break;
case 'f':
break;
case 'h':
break;
case 'i':
break;
case 'T':
break;
case 'p':
break;
case 't':
break;
case 'x':
break;
case 'v':
break;
case 'z':
break;
default:
goto err;
}
}
if (pcnt == 0) {
} else if (pcnt == 1) {
} else if (pcnt == 2) {
} else {
goto err;
}
goto err;
}
if (verbose) {
(void) printf("addr=%s, port = %d\n",
}
goto err;
}
goto err;
}
goto err;
}
if (softtoken_dir != NULL) {
if (verbose) {
(void) printf(
"SOFTTOKEN_DIR=%s\n",
getenv("SOFTTOKEN_DIR"));
}
}
if (cert_key_file == NULL) {
goto err;
}
if (cert_key_file == NULL) {
goto err;
}
} else {
goto err;
}
if (kssl_params == NULL) {
return (FAILURE);
}
sizeof (kssl_params->kssl_suites));
if (cacert_chain_file != NULL) {
if (kssl_params == NULL) {
return (FAILURE);
}
}
int err = CRYPTO_FAILED;
if (kssl_params->kssl_is_nxkey)
"Error loading cert and key: 0x%x\n", err);
return (FAILURE);
}
if (verbose)
(void) printf("Successfully loaded cert and key\n");
return (SUCCESS);
err:
return (SMF_EXIT_ERR_CONFIG);
}