/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
*/
/*
* This file implements the import operation for this tool.
* The basic flow of the process is to decrypt the PKCS#12
* input file if it has a password, parse the elements in
* the file, find the soft token, log into it, import the
* PKCS#11 objects into the soft token, and log out.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "common.h"
#include <kmfapi.h>
#define NEW_ATTRLIST(a, n) \
{ \
a = (KMF_ATTRIBUTE *)malloc(n * sizeof (KMF_ATTRIBUTE)); \
if (a == NULL) { \
rv = KMF_ERR_MEMORY; \
goto end; \
} \
(void) memset(a, 0, n * sizeof (KMF_ATTRIBUTE)); \
}
static KMF_RETURN
pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred,
char *outfile, char *certfile, char *keyfile,
KMF_ENCODE_FORMAT outformat)
{
KMF_RETURN rv = KMF_OK;
KMF_X509_DER_CERT *certs = NULL;
KMF_RAW_KEY_DATA *keys = NULL;
int ncerts = 0;
int nkeys = 0;
int i;
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
KMF_ATTRIBUTE *attrlist = NULL;
int numattr = 0;
rv = kmf_import_objects(kmfhandle, outfile, cred,
&certs, &ncerts, &keys, &nkeys);
if (rv == KMF_OK) {
(void) printf(gettext("Found %d certificate(s) and %d "
"key(s) in %s\n"), ncerts, nkeys, outfile);
}
if (rv == KMF_OK && ncerts > 0) {
char newcertfile[MAXPATHLEN];
NEW_ATTRLIST(attrlist, (3 + (3 * ncerts)));
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_ENCODE_FORMAT_ATTR, &outformat, sizeof (outformat));
numattr++;
for (i = 0; rv == KMF_OK && i < ncerts; i++) {
int num = numattr;
/*
* If storing more than 1 cert, gotta change
* the name so we don't overwrite the previous one.
* Just append a _# to the name.
*/
if (i > 0) {
(void) snprintf(newcertfile,
sizeof (newcertfile), "%s_%d", certfile, i);
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_FILENAME_ATTR, newcertfile,
strlen(newcertfile));
num++;
} else {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_FILENAME_ATTR, certfile,
strlen(certfile));
num++;
}
if (certs[i].kmf_private.label != NULL) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_LABEL_ATTR,
certs[i].kmf_private.label,
strlen(certs[i].kmf_private.label));
num++;
}
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_DATA_ATTR, &certs[i].certificate,
sizeof (KMF_DATA));
num++;
rv = kmf_store_cert(kmfhandle, num, attrlist);
}
free(attrlist);
}
if (rv == KMF_OK && nkeys > 0) {
char newkeyfile[MAXPATHLEN];
numattr = 0;
NEW_ATTRLIST(attrlist, (4 + (4 * nkeys)));
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype,
sizeof (kstype));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_ENCODE_FORMAT_ATTR, &outformat,
sizeof (outformat));
numattr++;
if (cred != NULL && cred->credlen > 0) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CREDENTIAL_ATTR, cred,
sizeof (KMF_CREDENTIAL));
numattr++;
}
/* The order of certificates and keys should match */
for (i = 0; rv == KMF_OK && i < nkeys; i++) {
int num = numattr;
if (i > 0) {
(void) snprintf(newkeyfile,
sizeof (newkeyfile), "%s_%d", keyfile, i);
kmf_set_attr_at_index(attrlist, num,
KMF_KEY_FILENAME_ATTR, newkeyfile,
strlen(newkeyfile));
num++;
} else {
kmf_set_attr_at_index(attrlist, num,
KMF_KEY_FILENAME_ATTR, keyfile,
strlen(keyfile));
num++;
}
if (i < ncerts) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_DATA_ATTR, &certs[i],
sizeof (KMF_CERT_DATA_ATTR));
num++;
}
kmf_set_attr_at_index(attrlist, num,
KMF_RAW_KEY_ATTR, &keys[i],
sizeof (KMF_RAW_KEY_DATA));
num++;
rv = kmf_store_key(kmfhandle, num, attrlist);
}
free(attrlist);
}
end:
/*
* Cleanup memory.
*/
if (certs) {
for (i = 0; i < ncerts; i++)
kmf_free_kmf_cert(kmfhandle, &certs[i]);
free(certs);
}
if (keys) {
for (i = 0; i < nkeys; i++)
kmf_free_raw_key(&keys[i]);
free(keys);
}
return (rv);
}
static KMF_RETURN
pk_import_pk12_nss(
KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *kmfcred,
KMF_CREDENTIAL *tokencred,
char *token_spec, char *dir, char *prefix,
char *nickname, char *trustflags, char *filename)
{
KMF_RETURN rv = KMF_OK;
KMF_X509_DER_CERT *certs = NULL;
KMF_RAW_KEY_DATA *keys = NULL;
int ncerts = 0;
int nkeys = 0;
int i;
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
KMF_ATTRIBUTE *attrlist = NULL;
int numattr = 0;
rv = configure_nss(kmfhandle, dir, prefix);
if (rv != KMF_OK)
return (rv);
rv = kmf_import_objects(kmfhandle, filename, kmfcred,
&certs, &ncerts, &keys, &nkeys);
if (rv == KMF_OK)
(void) printf(gettext("Found %d certificate(s) and %d "
"key(s) in %s\n"), ncerts, nkeys, filename);
if (rv == KMF_OK) {
numattr = 0;
NEW_ATTRLIST(attrlist, (4 + (2 * nkeys)));
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype,
sizeof (kstype));
numattr++;
if (token_spec != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_TOKEN_LABEL_ATTR, token_spec,
strlen(token_spec));
numattr++;
}
if (nickname != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYLABEL_ATTR, nickname,
strlen(nickname));
numattr++;
}
if (tokencred->credlen > 0) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CREDENTIAL_ATTR, tokencred,
sizeof (KMF_CREDENTIAL));
numattr++;
}
/* The order of certificates and keys should match */
for (i = 0; i < nkeys; i++) {
int num = numattr;
if (i < ncerts) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_DATA_ATTR, &certs[i],
sizeof (KMF_DATA));
num++;
}
kmf_set_attr_at_index(attrlist, num,
KMF_RAW_KEY_ATTR, &keys[i],
sizeof (KMF_RAW_KEY_DATA));
num++;
rv = kmf_store_key(kmfhandle, num, attrlist);
}
free(attrlist);
attrlist = NULL;
}
if (rv == KMF_OK) {
numattr = 0;
NEW_ATTRLIST(attrlist, (3 + (2 * ncerts)));
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
numattr++;
if (token_spec != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_TOKEN_LABEL_ATTR, token_spec,
strlen(token_spec));
numattr++;
}
if (trustflags != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_TRUSTFLAG_ATTR, trustflags,
strlen(trustflags));
numattr++;
}
for (i = 0; rv == KMF_OK && i < ncerts; i++) {
int num = numattr;
if (certs[i].kmf_private.label != NULL) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_LABEL_ATTR,
certs[i].kmf_private.label,
strlen(certs[i].kmf_private.label));
num++;
} else if (i == 0 && nickname != NULL) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_LABEL_ATTR, nickname,
strlen(nickname));
num++;
}
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_DATA_ATTR,
&certs[i].certificate, sizeof (KMF_DATA));
num++;
rv = kmf_store_cert(kmfhandle, num, attrlist);
}
free(attrlist);
attrlist = NULL;
if (rv != KMF_OK) {
display_error(kmfhandle, rv,
gettext("Error storing certificate in NSS token"));
}
}
end:
/*
* Cleanup memory.
*/
if (certs) {
for (i = 0; i < ncerts; i++)
kmf_free_kmf_cert(kmfhandle, &certs[i]);
free(certs);
}
if (keys) {
for (i = 0; i < nkeys; i++)
kmf_free_raw_key(&keys[i]);
free(keys);
}
return (rv);
}
static KMF_RETURN
pk_import_cert(
KMF_HANDLE_T kmfhandle,
KMF_KEYSTORE_TYPE kstype,
char *label, char *token_spec, char *filename,
char *dir, char *prefix, char *trustflags)
{
KMF_RETURN rv = KMF_OK;
KMF_ATTRIBUTE attrlist[32];
KMF_CREDENTIAL tokencred;
int i = 0;
if (kstype == KMF_KEYSTORE_PK11TOKEN) {
rv = select_token(kmfhandle, token_spec, FALSE);
} else if (kstype == KMF_KEYSTORE_NSS) {
rv = configure_nss(kmfhandle, dir, prefix);
}
if (rv != KMF_OK)
return (rv);
kmf_set_attr_at_index(attrlist, i,
KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (KMF_KEYSTORE_TYPE));
i++;
kmf_set_attr_at_index(attrlist, i, KMF_CERT_FILENAME_ATTR,
filename, strlen(filename));
i++;
if (label != NULL) {
kmf_set_attr_at_index(attrlist, i, KMF_CERT_LABEL_ATTR,
label, strlen(label));
i++;
}
if (kstype == KMF_KEYSTORE_NSS) {
if (trustflags != NULL) {
kmf_set_attr_at_index(attrlist, i, KMF_TRUSTFLAG_ATTR,
trustflags, strlen(trustflags));
i++;
}
if (token_spec != NULL) {
kmf_set_attr_at_index(attrlist, i,
KMF_TOKEN_LABEL_ATTR,
token_spec, strlen(token_spec));
i++;
}
}
rv = kmf_import_cert(kmfhandle, i, attrlist);
if (rv == KMF_ERR_AUTH_FAILED) {
/*
* The token requires a credential, prompt and try again.
*/
(void) get_token_password(kstype, token_spec, &tokencred);
kmf_set_attr_at_index(attrlist, i, KMF_CREDENTIAL_ATTR,
&tokencred, sizeof (KMF_CREDENTIAL));
i++;
rv = kmf_import_cert(kmfhandle, i, attrlist);
}
return (rv);
}
static KMF_RETURN
pk_import_file_crl(void *kmfhandle,
char *infile,
char *outfile,
KMF_ENCODE_FORMAT outfmt)
{
int numattr = 0;
KMF_ATTRIBUTE attrlist[8];
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
&kstype, sizeof (kstype));
numattr++;
if (infile) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CRL_FILENAME_ATTR, infile, strlen(infile));
numattr++;
}
if (outfile) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CRL_OUTFILE_ATTR, outfile, strlen(outfile));
numattr++;
}
kmf_set_attr_at_index(attrlist, numattr,
KMF_ENCODE_FORMAT_ATTR, &outfmt, sizeof (outfmt));
numattr++;
return (kmf_import_crl(kmfhandle, numattr, attrlist));
}
static KMF_RETURN
pk_import_nss_crl(void *kmfhandle,
boolean_t verify_crl_flag,
char *infile,
char *outdir,
char *prefix)
{
KMF_RETURN rv;
int numattr = 0;
KMF_ATTRIBUTE attrlist[4];
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
rv = configure_nss(kmfhandle, outdir, prefix);
if (rv != KMF_OK)
return (rv);
kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
&kstype, sizeof (kstype));
numattr++;
if (infile) {
kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_FILENAME_ATTR,
infile, strlen(infile));
numattr++;
}
kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_CHECK_ATTR,
&verify_crl_flag, sizeof (verify_crl_flag));
numattr++;
return (kmf_import_crl(kmfhandle, numattr, attrlist));
}
static KMF_RETURN
pk_import_pk12_pk11(
KMF_HANDLE_T kmfhandle,
KMF_CREDENTIAL *p12cred,
KMF_CREDENTIAL *tokencred,
char *label, char *token_spec,
char *filename)
{
KMF_RETURN rv = KMF_OK;
KMF_X509_DER_CERT *certs = NULL;
KMF_RAW_KEY_DATA *keys = NULL;
int ncerts = 0;
int nkeys = 0;
int i;
KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
KMF_ATTRIBUTE *attrlist = NULL;
int numattr = 0;
rv = select_token(kmfhandle, token_spec, FALSE);
if (rv != KMF_OK) {
return (rv);
}
rv = kmf_import_objects(kmfhandle, filename, p12cred,
&certs, &ncerts, &keys, &nkeys);
if (rv == KMF_OK) {
NEW_ATTRLIST(attrlist, (3 + (2 * nkeys)));
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype,
sizeof (kstype));
numattr++;
if (label != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYLABEL_ATTR, label,
strlen(label));
numattr++;
}
if (tokencred != NULL && tokencred->credlen > 0) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CREDENTIAL_ATTR, tokencred,
sizeof (KMF_CREDENTIAL));
numattr++;
}
/* The order of certificates and keys should match */
for (i = 0; i < nkeys; i++) {
int num = numattr;
if (i < ncerts) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_DATA_ATTR, &certs[i].certificate,
sizeof (KMF_DATA));
num++;
}
kmf_set_attr_at_index(attrlist, num,
KMF_RAW_KEY_ATTR, &keys[i],
sizeof (KMF_RAW_KEY_DATA));
num++;
rv = kmf_store_key(kmfhandle, num, attrlist);
}
free(attrlist);
}
if (rv == KMF_OK) {
numattr = 0;
NEW_ATTRLIST(attrlist, (1 + (2 * ncerts)));
(void) printf(gettext("Found %d certificate(s) and %d "
"key(s) in %s\n"), ncerts, nkeys, filename);
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
numattr++;
for (i = 0; rv == KMF_OK && i < ncerts; i++) {
int num = numattr;
if (certs[i].kmf_private.label != NULL) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_LABEL_ATTR,
certs[i].kmf_private.label,
strlen(certs[i].kmf_private.label));
num++;
} else if (i == 0 && label != NULL) {
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_LABEL_ATTR, label, strlen(label));
num++;
}
kmf_set_attr_at_index(attrlist, num,
KMF_CERT_DATA_ATTR, &certs[i].certificate,
sizeof (KMF_DATA));
num++;
rv = kmf_store_cert(kmfhandle, num, attrlist);
}
free(attrlist);
}
end:
/*
* Cleanup memory.
*/
if (certs) {
for (i = 0; i < ncerts; i++)
kmf_free_kmf_cert(kmfhandle, &certs[i]);
free(certs);
}
if (keys) {
for (i = 0; i < nkeys; i++)
kmf_free_raw_key(&keys[i]);
free(keys);
}
return (rv);
}
/*ARGSUSED*/
static KMF_RETURN
pk_import_keys(KMF_HANDLE_T kmfhandle,
KMF_KEYSTORE_TYPE kstype, char *token_spec,
KMF_CREDENTIAL *cred, char *filename,
char *label, char *senstr, char *extstr)
{
KMF_RETURN rv = KMF_OK;
KMF_ATTRIBUTE attrlist[16];
KMF_KEYSTORE_TYPE fileks = KMF_KEYSTORE_OPENSSL;
int numattr = 0;
KMF_KEY_HANDLE key;
KMF_RAW_KEY_DATA rawkey;
KMF_KEY_CLASS class = KMF_ASYM_PRI;
int numkeys = 1;
if (kstype == KMF_KEYSTORE_PK11TOKEN) {
rv = select_token(kmfhandle, token_spec, FALSE);
}
if (rv != KMF_OK)
return (rv);
/*
* First, set up to read the keyfile using the FILE plugin
* mechanisms.
*/
kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
&fileks, sizeof (fileks));
numattr++;
kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
&numkeys, sizeof (numkeys));
numattr++;
kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
&key, sizeof (key));
numattr++;
kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
&rawkey, sizeof (rawkey));
numattr++;
kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
&class, sizeof (class));
numattr++;
kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
filename, strlen(filename));
numattr++;
rv = kmf_find_key(kmfhandle, numattr, attrlist);
if (rv == KMF_OK) {
numattr = 0;
kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
&kstype, sizeof (kstype));
numattr++;
if (cred != NULL && cred->credlen > 0) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
numattr++;
}
if (label != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYLABEL_ATTR, label, strlen(label));
numattr++;
}
kmf_set_attr_at_index(attrlist, numattr,
KMF_RAW_KEY_ATTR, &rawkey, sizeof (rawkey));
numattr++;
rv = kmf_store_key(kmfhandle, numattr, attrlist);
if (rv == KMF_OK) {
(void) printf(gettext("Importing %d keys\n"), numkeys);
}
kmf_free_kmf_key(kmfhandle, &key);
kmf_free_raw_key(&rawkey);
} else {
cryptoerror(LOG_STDERR,
gettext("Failed to load key from file (%s)\n"),
filename);
}
return (rv);
}
static KMF_RETURN
pk_import_rawkey(KMF_HANDLE_T kmfhandle,
KMF_KEYSTORE_TYPE kstype, char *token,
KMF_CREDENTIAL *cred,
char *filename, char *label, KMF_KEY_ALG keyAlg,
char *senstr, char *extstr)
{
KMF_RETURN rv = KMF_OK;
KMF_ATTRIBUTE attrlist[16];
int numattr = 0;
uint32_t keylen;
boolean_t sensitive = B_FALSE;
boolean_t not_extractable = B_FALSE;
KMF_DATA keydata = { 0, NULL };
KMF_KEY_HANDLE rawkey;
rv = kmf_read_input_file(kmfhandle, filename, &keydata);
if (rv != KMF_OK)
return (rv);
rv = select_token(kmfhandle, token, FALSE);
if (rv != KMF_OK) {
return (rv);
}
if (senstr != NULL) {
if (tolower(senstr[0]) == 'y')
sensitive = B_TRUE;
else if (tolower(senstr[0]) == 'n')
sensitive = B_FALSE;
else {
cryptoerror(LOG_STDERR,
gettext("Incorrect sensitive option value.\n"));
return (KMF_ERR_BAD_PARAMETER);
}
}
if (extstr != NULL) {
if (tolower(extstr[0]) == 'y')
not_extractable = B_FALSE;
else if (tolower(extstr[0]) == 'n')
not_extractable = B_TRUE;
else {
cryptoerror(LOG_STDERR,
gettext("Incorrect extractable option value.\n"));
return (KMF_ERR_BAD_PARAMETER);
}
}
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEY_HANDLE_ATTR, &rawkey, sizeof (rawkey));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYALG_ATTR, &keyAlg, sizeof (KMF_KEY_ALG));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEY_DATA_ATTR, keydata.Data, keydata.Length);
numattr++;
/* Key length is given in bits not bytes */
keylen = keydata.Length * 8;
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYLENGTH_ATTR, &keylen, sizeof (keydata.Length));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_SENSITIVE_BOOL_ATTR, &sensitive, sizeof (sensitive));
numattr++;
kmf_set_attr_at_index(attrlist, numattr,
KMF_NON_EXTRACTABLE_BOOL_ATTR, &not_extractable,
sizeof (not_extractable));
numattr++;
if (label != NULL) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_KEYLABEL_ATTR, label, strlen(label));
numattr++;
}
if (cred != NULL && cred->credlen > 0) {
kmf_set_attr_at_index(attrlist, numattr,
KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
numattr++;
}
rv = kmf_create_sym_key(kmfhandle, numattr, attrlist);
return (rv);
}
/*
* Import objects from into KMF repositories.
*/
int
pk_import(int argc, char *argv[])
{
int opt;
extern int optind_av;
extern char *optarg_av;
char *token_spec = NULL;
char *filename = NULL;
char *keyfile = NULL;
char *certfile = NULL;
char *crlfile = NULL;
char *label = NULL;
char *dir = NULL;
char *prefix = NULL;
char *trustflags = NULL;
char *verify_crl = NULL;
char *keytype = "generic";
char *senstr = NULL;
char *extstr = NULL;
boolean_t verify_crl_flag = B_FALSE;
int oclass = 0;
KMF_KEYSTORE_TYPE kstype = 0;
KMF_ENCODE_FORMAT kfmt = 0;
KMF_ENCODE_FORMAT okfmt = KMF_FORMAT_ASN1;
KMF_RETURN rv = KMF_OK;
KMF_CREDENTIAL pk12cred = { NULL, 0 };
KMF_CREDENTIAL tokencred = { NULL, 0 };
KMF_HANDLE_T kmfhandle = NULL;
KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET;
/* Parse command line options. Do NOT i18n/l10n. */
while ((opt = getopt_av(argc, argv,
"T:(token)i:(infile)"
"k:(keystore)y:(objtype)"
"d:(dir)p:(prefix)"
"n:(certlabel)N:(label)"
"K:(outkey)c:(outcert)"
"v:(verifycrl)l:(outcrl)"
"E:(keytype)s:(sensitive)x:(extractable)"
"t:(trust)F:(outformat)")) != EOF) {
if (EMPTYSTRING(optarg_av))
return (PK_ERR_USAGE);
switch (opt) {
case 'T': /* token specifier */
if (token_spec)
return (PK_ERR_USAGE);
token_spec = optarg_av;
break;
case 'c': /* output cert file name */
if (certfile)
return (PK_ERR_USAGE);
certfile = optarg_av;
break;
case 'l': /* output CRL file name */
if (crlfile)
return (PK_ERR_USAGE);
crlfile = optarg_av;
break;
case 'K': /* output key file name */
if (keyfile)
return (PK_ERR_USAGE);
keyfile = optarg_av;
break;
case 'i': /* input file name */
if (filename)
return (PK_ERR_USAGE);
filename = optarg_av;
break;
case 'k':
kstype = KS2Int(optarg_av);
if (kstype == 0)
return (PK_ERR_USAGE);
break;
case 'y':
oclass = OT2Int(optarg_av);
if (oclass == -1)
return (PK_ERR_USAGE);
break;
case 'd':
dir = optarg_av;
break;
case 'p':
if (prefix)
return (PK_ERR_USAGE);
prefix = optarg_av;
break;
case 'n':
case 'N':
if (label)
return (PK_ERR_USAGE);
label = optarg_av;
break;
case 'F':
okfmt = Str2Format(optarg_av);
if (okfmt == KMF_FORMAT_UNDEF)
return (PK_ERR_USAGE);
break;
case 't':
if (trustflags)
return (PK_ERR_USAGE);
trustflags = optarg_av;
break;
case 'v':
verify_crl = optarg_av;
if (tolower(verify_crl[0]) == 'y')
verify_crl_flag = B_TRUE;
else if (tolower(verify_crl[0]) == 'n')
verify_crl_flag = B_FALSE;
else
return (PK_ERR_USAGE);
break;
case 'E':
keytype = optarg_av;
break;
case 's':
if (senstr)
return (PK_ERR_USAGE);
senstr = optarg_av;
break;
case 'x':
if (extstr)
return (PK_ERR_USAGE);
extstr = optarg_av;
break;
default:
return (PK_ERR_USAGE);
}
}
/* Assume keystore = PKCS#11 if not specified */
if (kstype == 0)
kstype = KMF_KEYSTORE_PK11TOKEN;
/* Filename arg is required. */
if (EMPTYSTRING(filename)) {
cryptoerror(LOG_STDERR, gettext("The 'infile' parameter"
"is required for the import operation.\n"));
return (PK_ERR_USAGE);
}
/* No additional args allowed. */
argc -= optind_av;
argv += optind_av;
if (argc)
return (PK_ERR_USAGE);
DIR_OPTION_CHECK(kstype, dir);
/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
kstype != KMF_KEYSTORE_PK11TOKEN) {
(void) fprintf(stderr, gettext("The objtype parameter "
"is only relevant if keystore=pkcs11\n"));
return (PK_ERR_USAGE);
}
/*
* You must specify a certlabel (cert label) when importing
* into NSS or PKCS#11.
*/
if (kstype == KMF_KEYSTORE_NSS &&
(oclass != PK_CRL_OBJ) && EMPTYSTRING(label)) {
cryptoerror(LOG_STDERR, gettext("The 'label' argument "
"is required for this operation\n"));
return (PK_ERR_USAGE);
}
if ((rv = kmf_get_file_format(filename, &kfmt)) != KMF_OK) {
char *kmferrstr = NULL;
KMF_RETURN rv2;
/*
* Allow for raw key data to be imported.
*/
if (rv == KMF_ERR_ENCODING) {
rv = KMF_OK;
kfmt = KMF_FORMAT_RAWKEY;
/*
* Set the object class only if it was not
* given on the command line or if it was
* specified as a symmetric key object.
*/
if (oclass == 0 || (oclass & PK_SYMKEY_OBJ)) {
oclass = PK_SYMKEY_OBJ;
} else {
cryptoerror(LOG_STDERR, gettext(
"The input file does not contain the "
"object type indicated on command "
"line."));
return (KMF_ERR_BAD_PARAMETER);
}
} else {
if (rv == KMF_ERR_OPEN_FILE) {
cryptoerror(LOG_STDERR,
gettext("Cannot open file (%s)\n."),
filename);
} else {
rv2 = kmf_get_kmf_error_str(rv, &kmferrstr);
if (rv2 == KMF_OK && kmferrstr) {
cryptoerror(LOG_STDERR,
gettext("libkmf error: %s"),
kmferrstr);
kmf_free_str(kmferrstr);
}
}
return (rv);
}
}
/* Check parameters for raw key import operation */
if (kfmt == KMF_FORMAT_RAWKEY) {
if (keytype != NULL &&
Str2SymKeyType(keytype, &keyAlg) != 0) {
cryptoerror(LOG_STDERR,
gettext("Unrecognized keytype(%s).\n"), keytype);
return (PK_ERR_USAGE);
}
if (senstr != NULL && extstr != NULL &&
kstype != KMF_KEYSTORE_PK11TOKEN) {
cryptoerror(LOG_STDERR,
gettext("The sensitive or extractable option "
"applies only when importing a key from a file "
"into a PKCS#11 keystore.\n"));
return (PK_ERR_USAGE);
}
}
/* If no objtype was given, treat it as a certificate */
if (oclass == 0 && (kfmt == KMF_FORMAT_ASN1 ||
kfmt == KMF_FORMAT_PEM))
oclass = PK_CERT_OBJ;
if (kstype == KMF_KEYSTORE_NSS) {
if (oclass == PK_CRL_OBJ &&
(kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
cryptoerror(LOG_STDERR, gettext(
"CRL data can only be imported as DER or "
"PEM format"));
return (PK_ERR_USAGE);
}
if (oclass == PK_CERT_OBJ &&
(kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
cryptoerror(LOG_STDERR, gettext(
"Certificates can only be imported as DER or "
"PEM format"));
return (PK_ERR_USAGE);
}
/* we do not import private keys except in PKCS12 bundles */
if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) {
cryptoerror(LOG_STDERR, gettext(
"Private key data can only be imported as part "
"of a PKCS12 file.\n"));
return (PK_ERR_USAGE);
}
}
if (kstype == KMF_KEYSTORE_OPENSSL && oclass != PK_CRL_OBJ) {
if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
cryptoerror(LOG_STDERR, gettext(
"The 'outkey' and 'outcert' parameters "
"are required for the import operation "
"when the 'file' keystore is used.\n"));
return (PK_ERR_USAGE);
}
}
if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
token_spec = PK_DEFAULT_PK11TOKEN;
else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
token_spec = DEFAULT_NSS_TOKEN;
if (kfmt == KMF_FORMAT_PKCS12) {
(void) get_pk12_password(&pk12cred);
}
if ((kfmt == KMF_FORMAT_PKCS12 || kfmt == KMF_FORMAT_RAWKEY ||
(kfmt == KMF_FORMAT_PEM && (oclass & PK_KEY_OBJ))) &&
(kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)) {
(void) get_token_password(kstype, token_spec, &tokencred);
}
if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
cryptoerror(LOG_STDERR, gettext("Error initializing "
"KMF: 0x%02x\n"), rv);
goto end;
}
switch (kstype) {
case KMF_KEYSTORE_PK11TOKEN:
if (kfmt == KMF_FORMAT_PKCS12)
rv = pk_import_pk12_pk11(
kmfhandle, &pk12cred,
&tokencred, label,
token_spec, filename);
else if (oclass == PK_CERT_OBJ)
rv = pk_import_cert(
kmfhandle, kstype,
label, token_spec,
filename,
NULL, NULL, NULL);
else if (oclass == PK_CRL_OBJ)
rv = pk_import_file_crl(
kmfhandle, filename,
crlfile, okfmt);
else if (kfmt == KMF_FORMAT_RAWKEY &&
oclass == PK_SYMKEY_OBJ) {
rv = pk_import_rawkey(kmfhandle,
kstype, token_spec, &tokencred,
filename, label,
keyAlg, senstr, extstr);
} else if (kfmt == KMF_FORMAT_PEM ||
kfmt == KMF_FORMAT_PEM_KEYPAIR) {
rv = pk_import_keys(kmfhandle,
kstype, token_spec, &tokencred,
filename, label, senstr, extstr);
} else {
rv = PK_ERR_USAGE;
}
break;
case KMF_KEYSTORE_NSS:
if (dir == NULL)
dir = PK_DEFAULT_DIRECTORY;
if (kfmt == KMF_FORMAT_PKCS12)
rv = pk_import_pk12_nss(
kmfhandle, &pk12cred,
&tokencred,
token_spec, dir, prefix,
label, trustflags, filename);
else if (oclass == PK_CERT_OBJ) {
rv = pk_import_cert(
kmfhandle, kstype,
label, token_spec,
filename, dir, prefix, trustflags);
} else if (oclass == PK_CRL_OBJ) {
rv = pk_import_nss_crl(
kmfhandle, verify_crl_flag,
filename, dir, prefix);
}
break;
case KMF_KEYSTORE_OPENSSL:
if (kfmt == KMF_FORMAT_PKCS12)
rv = pk_import_pk12_files(
kmfhandle, &pk12cred,
filename, certfile, keyfile,
okfmt);
else if (oclass == PK_CRL_OBJ) {
rv = pk_import_file_crl(
kmfhandle, filename,
crlfile, okfmt);
} else
/*
* It doesn't make sense to import anything
* else for the files plugin.
*/
return (PK_ERR_USAGE);
break;
default:
rv = PK_ERR_USAGE;
break;
}
end:
if (rv != KMF_OK)
display_error(kmfhandle, rv,
gettext("Error importing objects"));
if (tokencred.cred != NULL)
free(tokencred.cred);
if (pk12cred.cred != NULL)
free(pk12cred.cred);
(void) kmf_finalize(kmfhandle);
if (rv != KMF_OK)
return (PK_ERR_USAGE);
return (0);
}