common.c revision 56664548661c43ae04de4a32bce3510ed36aeaf9
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* This file contains the functions that are shared among
* the various services this tool will ultimately provide.
* The functions in this file return PKCS#11 CK_RV errors.
* Only one session and one login per token is supported
* at this time.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <tzfile.h>
#include <cryptoutil.h>
#include <security/cryptoki.h>
#include <kmfapi.h>
#include "common.h"
/* Local status variables. */
/* Supporting structures and global variables for getopt_av(). */
typedef struct av_opts_s {
int shortnm; /* short name character */
char *longnm; /* long name string, NOT terminated */
int longnm_len; /* length of long name string */
} av_opts;
static const char *_save_optstr = NULL;
static int _save_numopts = 0;
int optind_av = 1;
static void close_sess(CK_SESSION_HANDLE);
static void logout_token(CK_SESSION_HANDLE);
/*
* Perform PKCS#11 setup here. Currently only C_Initialize is required,
*/
static CK_RV
init_pkcs11(void)
{
/* If C_Initialize() already called, nothing to do here. */
if (initialized == B_TRUE)
return (CKR_OK);
/* Reset state variables because C_Initialize() not yet done. */
/* Initialize PKCS#11 library. */
return (rv);
}
return (CKR_OK);
}
/*
* Finalize PKCS#11 library and reset state variables. Open sessions,
* if any, are closed, and thereby any logins are logged out also.
*/
void
{
/* If the library wasn't initialized, nothing to do here. */
if (!initialized)
return;
/* Make sure the sesion is closed first. */
(void) C_Finalize(NULL);
}
/*
* Close PKCS#11 session and reset state variables. Any logins are
* logged out.
*/
static void
{
return;
}
/* If session is already closed, nothing to do here. */
if (!session_opened)
return;
/* Make sure user is logged out of token. */
(void) C_CloseSession(sess);
}
/*
* Log user out of token and reset status variable.
*/
static void
{
return;
}
/* If already logged out, nothing to do here. */
if (!logged_in)
return;
}
/*
* Gets PIN from user. Caller needs to free the returned PIN when done.
* If two prompts are given, the PIN is confirmed with second prompt.
* Note that getphassphrase() may return data in static memory area.
*/
{
/* Prompt user for a PIN. */
return (CKR_ARGUMENTS_BAD);
}
return (CKR_FUNCTION_FAILED);
}
/* Duplicate 1st PIN in separate chunk of memory. */
return (CKR_HOST_MEMORY);
/* If second prompt given, PIN confirmation is requested. */
return (CKR_FUNCTION_FAILED);
}
return (CKR_PIN_INCORRECT);
}
}
return (CKR_OK);
}
int
{
char *y = gettext("yes");
char *n = gettext("no");
return (-1);
return (1);
return (0);
else
return (-1);
}
/*
* default prompt is used. If not message for invalid input is supplied,
* a default will not be provided. If the user provides no response,
* the input default B_TRUE == yes, B_FALSE == no is returned.
* Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
*/
{
int ans;
for (;;) {
/* Prompt user. */
/* Get the response. */
break; /* go to default response */
/* Skip any leading white space. */
response++;
if (*response == '\0')
break; /* go to default response */
if (ans == 1)
return (B_TRUE);
else if (ans == 0)
return (B_FALSE);
/* Indicate invalid input, and try again. */
}
return (dflt);
}
/*
* Gets the list of slots which have tokens in them. Keeps adjusting
* the size of the slot list buffer until the call is successful or an
* irrecoverable error occurs.
*/
{
if (!initialized)
return (rv);
/*
* Get the slot count first because we don't know how many
* slots there are and how many of those slots even have tokens.
* Don't specify an arbitrary buffer size for the slot list;
* it may be too small (see section 11.5 of PKCS#11 spec).
* Also select only those slots that have tokens in them,
* because this tool has no need to know about empty slots.
*/
return (rv);
if (tmp_count == 0) {
*slot_count = 0;
return (CKR_OK);
}
/* Allocate initial space for the slot list. */
sizeof (CK_SLOT_ID))) == NULL)
return (CKR_HOST_MEMORY);
/* Then get the slot list itself. */
for (;;) {
*slot_count = tmp_count;
break;
}
if (rv != CKR_BUFFER_TOO_SMALL) {
break;
}
/* If the number of slots grew, try again. */
break;
}
}
return (rv);
}
/*
* Breaks out the getopt-style option string into a structure that can be
* traversed later for calls to getopt_av(). Option string is NOT altered,
* but the struct fields point to locations within option string.
*/
static int
populate_opts(char *optstring)
{
int i;
char *marker;
return (0);
/*
* This tries to imitate getopt(3c) Each option must conform to:
* <short name char> [ ':' ] [ '(' <long name string> ')' ]
* If long name is missing, the short name is used for long name.
*/
for (i = 0; *optstring != '\0'; i++) {
return (0);
} else {
}
marker++;
}
marker++;
} else {
/* use short name option character */
}
}
return (i);
}
/*
* getopt_av() is very similar to getopt(3c) in that the takes an option
* string, compares command line arguments for matches, and returns a single
* letter option when a match is found. However, getopt_av() differs from
* getopt(3c) by requiring that only longname options and values be found
* on the command line and all leading dashes are omitted. In other words,
* it tries to enforce only longname "option=value" arguments on the command
* line. Boolean options are not allowed either.
*/
int
{
int i;
int len;
char *cur_option;
return (EOF);
/* First time or when optstring changes from previous one */
if (_save_optstr != optstring) {
}
for (i = 0; i < _save_numopts; i++) {
optind_av++;
break;
}
len = 1;
cur_option++; /* remove "-" */
} else {
}
/* matched */
optind_av++;
}
/* needs optarg */
optind_av++;
}
optind_av++;
return ((int)'?');
}
}
return (EOF);
}
KS2Int(char *keystore_str)
{
if (keystore_str == NULL)
return (0);
return (KMF_KEYSTORE_PK11TOKEN);
return (KMF_KEYSTORE_NSS);
return (KMF_KEYSTORE_OPENSSL);
else
return (0);
}
int
{
} else {
return (-1);
}
return (0);
}
int
{
else
return (-1);
return (0);
}
int
{
int num;
char timetok[6];
/* default to 1 year lifetime */
return (0);
}
return (-1);
} else {
*ltime = 0;
return (-1);
}
return (0);
}
int
{
char *c = NULL;
int retval = 0;
return (-1);
if (c != NULL) {
if (strcasecmp(c, ":private") == 0)
else if (strcasecmp(c, ":public") == 0)
else if (strcasecmp(c, ":both") == 0)
else /* unrecognized option */
return (-1);
*c = '\0';
}
if (retval)
return (-1);
if (retval)
return (-1);
if (retval)
return (-1);
return (retval | PK_CERT_OBJ);
if (retval == 0) /* return all keys */
return (retval | PK_KEY_OBJ);
/* return all keys */
return (retval | PK_KEY_OBJ);
else if (retval & PK_PUBLIC_OBJ)
/* Only return public keys */
return (retval | PK_PUBKEY_OBJ);
else if (retval & PK_PRIVATE_OBJ)
/* Only return private keys */
return (retval | PK_PRIKEY_OBJ);
if (retval)
return (-1);
return (retval | PK_CRL_OBJ);
}
if (retval == 0) /* No matches found */
retval = -1;
return (retval);
}
Str2Format(char *formstr)
{
return (KMF_FORMAT_ASN1);
return (KMF_FORMAT_PEM);
return (KMF_FORMAT_PKCS12);
return (KMF_FORMAT_RAWKEY);
return (KMF_FORMAT_UNDEF);
}
{
int i = 0;
return (KMF_ERR_BAD_PARAMETER);
sizeof (kstype));
i++;
if (token) {
i++;
}
sizeof (readonly));
i++;
if (rv == KMF_ERR_TOKEN_SELECTED)
return (rv);
}
{
int i = 0;
sizeof (kstype));
i++;
if (dir) {
i++;
}
if (prefix) {
i++;
i++;
}
if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
return (rv);
}
{
char prompt[1024];
/*
* Get the password to use for the PK12 encryption.
*/
gettext("Enter password to use for "
"accessing the PKCS12 file: "), sizeof (prompt));
}
return (rv);
}
#define FILENAME_MINLEN 1
#define FILENAME_MAXLEN MAXPATHLEN
"[Some-State]:")
"0x01020304):")
#define SERNO_MINLEN 3
#define SERNO_MAXLEN 42
#define LABEL_MINLEN 1
#define LABEL_MAXLEN 1024
#define COUNTRY_DEFAULT "US"
#define STATE_DEFAULT NULL
#define SUBNAMESIZ 1024
#define RDN_MIN 1
#define RDN_MAX 64
#define COUNTRYNAME_MIN 2
#define COUNTRYNAME_MAX 2
static char *
{
char buf[1024];
int len;
for (;;) {
if (default_str != NULL) {
}
break;
}
/* Skip any leading white space. */
response++;
if (*response == '\0') {
if (default_str != NULL) {
}
break;
}
len--;
break;
}
}
return (ret);
}
int
{
char prompt[1024];
gettext("Enter filename for the %s: "),
txt);
return (0);
}
int
get_certlabel(char **result)
{
return (0);
}
int
get_serial(char **result)
{
return (0);
}
int
get_subname(char **result)
{
(void) printf("Entering following fields for subject (a DN) ...\n");
return (-1);
/* Now create a subject name from the input strings */
goto out;
}
}
}
}
}
}
out:
if (country)
if (state)
if (locality)
if (org)
if (unit)
if (name)
if (email)
return (-1);
else {
return (0);
}
}
/*
* Parse a string of KeyUsage values and convert
* them to the correct KU Bits.
* The field may be marked "critical" by prepending
* "critical:" to the list.
* EX: critical:digitialSignature,keyEncipherment
*/
{
char *k;
*kubits = 0;
return (KMF_ERR_BAD_PARAMETER);
/* Check to see if this is critical */
} else {
}
while (k != NULL) {
kuval = kmf_string_to_ku(k);
if (kuval == 0) {
*kubits = 0;
return (KMF_ERR_BAD_PARAMETER);
}
}
return (ret);
}
/*
* Verify the alternate subject label is real or invalid.
*
* The field may be marked "critical" by prepending
* "critical:" to the list.
* EX: "critical:IP=1.2.3.4"
*/
{
char *p;
/* Check to see if this is critical */
} else {
}
/* Make sure there is an "=" sign */
if (p == NULL)
return (KMF_ERR_BAD_PARAMETER);
p[0] = '\0';
*type = GENNAME_DNSNAME;
*type = GENNAME_URI;
else
p[0] = '=';
return (rv);
}
int
{
char prompt[1024];
char temptoken[32];
char *p = NULL;
char *t = NULL;
int len;
if (kstype == KMF_KEYSTORE_PK11TOKEN) {
if (p != NULL)
*p = 0;
}
/*
* Strip trailing whitespace
*/
*t = 0x00;
t--;
}
/*
* Login to the token first.
*/
}
*p = ':';
return (KMF_OK);
}
verify_file(char *filename)
{
int fd;
/*
* Attempt to open with the EXCL flag so that if
* it already exists, the open will fail. It will
* also fail if the file cannot be created due to
* permissions on the parent directory, or if the
* parent directory itself does not exist.
*/
if (fd == -1)
return (KMF_ERR_OPEN_FILE);
/* If we were able to create it, delete it. */
return (ret);
}
void
{
char *plugin_errmsg = NULL;
char *kmf_errmsg = NULL;
}
}
}
static KMF_RETURN
{
else
return (KMF_ERR_MEMORY);
else
return (KMF_ERR_MEMORY);
}
return (KMF_OK);
}
void
{
int i;
}
}
}
static KMF_RETURN
{
int critical;
strlen("critical:")) == 0) {
} else {
}
} else {
rv = PK_ERR_USAGE;
}
return (rv);
}
{
char *p;
return (0);
return (KMF_ERR_MEMORY);
/*
* The list should be comma separated list of EKU Names.
*/
/* If no tokens found, then maybe it's just a single EKU value */
if (p == NULL) {
}
while (p != NULL) {
break;
}
else
return (rv);
}
{
*auth = 0;
return (rv);
return (KMF_ERR_INTERNAL);
return (KMF_OK);
}