10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53089Swyllys * Common Development and Distribution License (the "License"). 63089Swyllys * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 223812Shylee * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This file contains the functions that are shared among 300Sstevel@tonic-gate * the various services this tool will ultimately provide. 3117Sdinak * The functions in this file return PKCS#11 CK_RV errors. 3217Sdinak * Only one session and one login per token is supported 3317Sdinak * at this time. 340Sstevel@tonic-gate */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <stdio.h> 370Sstevel@tonic-gate #include <stdlib.h> 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #include <ctype.h> 403089Swyllys #include <sys/types.h> 413089Swyllys #include <sys/stat.h> 423089Swyllys #include <fcntl.h> 433089Swyllys #include <tzfile.h> 440Sstevel@tonic-gate #include <cryptoutil.h> 450Sstevel@tonic-gate #include <security/cryptoki.h> 463089Swyllys #include <kmfapi.h> 470Sstevel@tonic-gate 483089Swyllys #include "common.h" 4917Sdinak 5017Sdinak /* Local status variables. */ 5117Sdinak static boolean_t initialized = B_FALSE; 5217Sdinak static boolean_t session_opened = B_FALSE; 5317Sdinak static boolean_t logged_in = B_FALSE; 5417Sdinak 55864Sdinak /* Supporting structures and global variables for getopt_av(). */ 56864Sdinak typedef struct av_opts_s { 57864Sdinak int shortnm; /* short name character */ 58864Sdinak char *longnm; /* long name string, NOT terminated */ 59864Sdinak int longnm_len; /* length of long name string */ 60864Sdinak boolean_t has_arg; /* takes optional argument */ 61864Sdinak } av_opts; 62864Sdinak static av_opts *opts_av = NULL; 63864Sdinak static const char *_save_optstr = NULL; 64864Sdinak static int _save_numopts = 0; 65864Sdinak 66864Sdinak int optind_av = 1; 67864Sdinak char *optarg_av = NULL; 68864Sdinak 693089Swyllys static void close_sess(CK_SESSION_HANDLE); 703089Swyllys static void logout_token(CK_SESSION_HANDLE); 713089Swyllys 7217Sdinak /* 7317Sdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 7417Sdinak * along with setting/resetting state variables. 7517Sdinak */ 7617Sdinak CK_RV 7717Sdinak init_pk11(void) 7817Sdinak { 7917Sdinak CK_RV rv = CKR_OK; 8017Sdinak 8117Sdinak /* If C_Initialize() already called, nothing to do here. */ 8217Sdinak if (initialized == B_TRUE) 8317Sdinak return (CKR_OK); 8417Sdinak 8517Sdinak /* Reset state variables because C_Initialize() not yet done. */ 8617Sdinak session_opened = B_FALSE; 8717Sdinak logged_in = B_FALSE; 8817Sdinak 8917Sdinak /* Initialize PKCS#11 library. */ 9017Sdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 9117Sdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 9217Sdinak return (rv); 9317Sdinak } 9417Sdinak 9517Sdinak initialized = B_TRUE; 9617Sdinak return (CKR_OK); 9717Sdinak } 9817Sdinak 9917Sdinak /* 10017Sdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 10117Sdinak * if any, are closed, and thereby any logins are logged out also. 10217Sdinak */ 10317Sdinak void 10417Sdinak final_pk11(CK_SESSION_HANDLE sess) 10517Sdinak { 10617Sdinak 10717Sdinak /* If the library wasn't initialized, nothing to do here. */ 10817Sdinak if (!initialized) 10917Sdinak return; 11017Sdinak 11117Sdinak /* Make sure the sesion is closed first. */ 11217Sdinak close_sess(sess); 11317Sdinak 11417Sdinak (void) C_Finalize(NULL); 11517Sdinak initialized = B_FALSE; 11617Sdinak } 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* 11917Sdinak * Close PKCS#11 session and reset state variables. Any logins are 12017Sdinak * logged out. 12117Sdinak */ 1223089Swyllys static void 12317Sdinak close_sess(CK_SESSION_HANDLE sess) 12417Sdinak { 12517Sdinak 12617Sdinak if (sess == NULL) { 12717Sdinak return; 12817Sdinak } 12917Sdinak 13017Sdinak /* If session is already closed, nothing to do here. */ 13117Sdinak if (!session_opened) 13217Sdinak return; 1330Sstevel@tonic-gate 13417Sdinak /* Make sure user is logged out of token. */ 13517Sdinak logout_token(sess); 13617Sdinak 13717Sdinak (void) C_CloseSession(sess); 13817Sdinak session_opened = B_FALSE; 13917Sdinak } 14017Sdinak 14117Sdinak /* 14217Sdinak * Log user out of token and reset status variable. 14317Sdinak */ 1443089Swyllys static void 14517Sdinak logout_token(CK_SESSION_HANDLE sess) 14617Sdinak { 14717Sdinak 14817Sdinak if (sess == NULL) { 14917Sdinak return; 15017Sdinak } 15117Sdinak 15217Sdinak /* If already logged out, nothing to do here. */ 15317Sdinak if (!logged_in) 15417Sdinak return; 15517Sdinak 15617Sdinak (void) C_Logout(sess); 15717Sdinak logged_in = B_FALSE; 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* 16117Sdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 16217Sdinak * If two prompts are given, the PIN is confirmed with second prompt. 16317Sdinak * Note that getphassphrase() may return data in static memory area. 16417Sdinak */ 16517Sdinak CK_RV 16617Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 16717Sdinak { 16817Sdinak char *save_phrase, *phrase1, *phrase2; 16917Sdinak 1703089Swyllys 1713089Swyllys #ifdef DEBUG 1723089Swyllys if (getenv("TOKENPIN") != NULL) { 1733089Swyllys *pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN")); 1743089Swyllys *pinlen = strlen((char *)(*pin)); 1753089Swyllys return (CKR_OK); 1763089Swyllys } 1773089Swyllys #endif /* DEBUG */ 1780Sstevel@tonic-gate 17917Sdinak /* Prompt user for a PIN. */ 18017Sdinak if (prompt1 == NULL) { 18117Sdinak return (CKR_ARGUMENTS_BAD); 18217Sdinak } 18317Sdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 18417Sdinak return (CKR_FUNCTION_FAILED); 18517Sdinak } 18617Sdinak 18717Sdinak /* Duplicate 1st PIN in separate chunk of memory. */ 18817Sdinak if ((save_phrase = strdup(phrase1)) == NULL) 18917Sdinak return (CKR_HOST_MEMORY); 19017Sdinak 19117Sdinak /* If second prompt given, PIN confirmation is requested. */ 19217Sdinak if (prompt2 != NULL) { 19317Sdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 19417Sdinak free(save_phrase); 19517Sdinak return (CKR_FUNCTION_FAILED); 19617Sdinak } 19717Sdinak if (strcmp(save_phrase, phrase2) != 0) { 19817Sdinak free(save_phrase); 19917Sdinak return (CKR_PIN_INCORRECT); 20017Sdinak } 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate 20317Sdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 20417Sdinak *pinlen = strlen(save_phrase); 20517Sdinak return (CKR_OK); 20617Sdinak } 20717Sdinak 20817Sdinak /* 20917Sdinak * Gets yes/no response from user. If either no prompt is supplied, a 21017Sdinak * default prompt is used. If not message for invalid input is supplied, 21117Sdinak * a default will not be provided. If the user provides no response, 21217Sdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 21317Sdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 21417Sdinak */ 21517Sdinak boolean_t 21617Sdinak yesno(char *prompt, char *invalid, boolean_t dflt) 21717Sdinak { 21817Sdinak char *response, buf[1024]; 21917Sdinak char *yes = gettext("yes"); 22017Sdinak char *no = gettext("no"); 22117Sdinak 2223089Swyllys 2233089Swyllys #ifdef DEBUG 2243089Swyllys /* If debugging or testing, return TRUE and avoid prompting */ 2253089Swyllys if (getenv("TOKENPIN") != NULL) { 2263089Swyllys return (B_TRUE); 2273089Swyllys } 2283089Swyllys #endif /* DEBUG */ 22917Sdinak 23017Sdinak if (prompt == NULL) 23117Sdinak prompt = gettext("Enter (y)es or (n)o? "); 23217Sdinak 23317Sdinak for (;;) { 23417Sdinak /* Prompt user. */ 23517Sdinak (void) printf("%s", prompt); 23617Sdinak (void) fflush(stdout); 23717Sdinak 23817Sdinak /* Get the response. */ 23917Sdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 24017Sdinak break; /* go to default response */ 24117Sdinak 24217Sdinak /* Skip any leading white space. */ 24317Sdinak while (isspace(*response)) 24417Sdinak response++; 24517Sdinak if (*response == '\0') 24617Sdinak break; /* go to default response */ 24717Sdinak 24817Sdinak /* Is it valid input? Return appropriately. */ 24917Sdinak if (strncasecmp(response, yes, 1) == 0) 25017Sdinak return (B_TRUE); 25117Sdinak if (strncasecmp(response, no, 1) == 0) 25217Sdinak return (B_FALSE); 25317Sdinak 25417Sdinak /* Indicate invalid input, and try again. */ 25517Sdinak if (invalid != NULL) 2565051Swyllys (void) printf("%s", invalid); 25717Sdinak } 25817Sdinak return (dflt); 25917Sdinak } 26017Sdinak 26117Sdinak /* 26217Sdinak * Gets the list of slots which have tokens in them. Keeps adjusting 26317Sdinak * the size of the slot list buffer until the call is successful or an 26417Sdinak * irrecoverable error occurs. 26517Sdinak */ 26617Sdinak CK_RV 26717Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 26817Sdinak { 26917Sdinak CK_ULONG tmp_count = 0; 27017Sdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 27117Sdinak int rv = CKR_OK; 27217Sdinak 27317Sdinak if (!initialized) 27417Sdinak if ((rv = init_pk11()) != CKR_OK) 27517Sdinak return (rv); 27617Sdinak 27717Sdinak /* 27817Sdinak * Get the slot count first because we don't know how many 27917Sdinak * slots there are and how many of those slots even have tokens. 28017Sdinak * Don't specify an arbitrary buffer size for the slot list; 28117Sdinak * it may be too small (see section 11.5 of PKCS#11 spec). 28217Sdinak * Also select only those slots that have tokens in them, 28317Sdinak * because this tool has no need to know about empty slots. 28417Sdinak */ 28517Sdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 28617Sdinak return (rv); 28717Sdinak 28817Sdinak if (tmp_count == 0) { 28917Sdinak *slot_list = NULL_PTR; 29017Sdinak *slot_count = 0; 29117Sdinak return (CKR_OK); 29217Sdinak } 29317Sdinak 29417Sdinak /* Allocate initial space for the slot list. */ 29517Sdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 29617Sdinak sizeof (CK_SLOT_ID))) == NULL) 29717Sdinak return (CKR_HOST_MEMORY); 29817Sdinak 29917Sdinak /* Then get the slot list itself. */ 30017Sdinak for (;;) { 30117Sdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 30217Sdinak *slot_list = tmp_list; 30317Sdinak *slot_count = tmp_count; 30417Sdinak break; 30517Sdinak } 30617Sdinak 30717Sdinak if (rv != CKR_BUFFER_TOO_SMALL) { 30817Sdinak free(tmp_list); 30917Sdinak break; 31017Sdinak } 31117Sdinak 31217Sdinak /* If the number of slots grew, try again. */ 31317Sdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 31417Sdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 31517Sdinak free(tmp_list); 31617Sdinak rv = CKR_HOST_MEMORY; 31717Sdinak break; 31817Sdinak } 31917Sdinak tmp_list = tmp2_list; 32017Sdinak } 32117Sdinak 32217Sdinak return (rv); 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate /* 326864Sdinak * Breaks out the getopt-style option string into a structure that can be 327864Sdinak * traversed later for calls to getopt_av(). Option string is NOT altered, 328864Sdinak * but the struct fields point to locations within option string. 329864Sdinak */ 330864Sdinak static int 331864Sdinak populate_opts(char *optstring) 332864Sdinak { 333864Sdinak int i; 334864Sdinak av_opts *temp; 335864Sdinak char *marker; 336864Sdinak 337864Sdinak if (optstring == NULL || *optstring == '\0') 338864Sdinak return (0); 339864Sdinak 340864Sdinak /* 341864Sdinak * This tries to imitate getopt(3c) Each option must conform to: 342864Sdinak * <short name char> [ ':' ] [ '(' <long name string> ')' ] 343864Sdinak * If long name is missing, the short name is used for long name. 344864Sdinak */ 345864Sdinak for (i = 0; *optstring != '\0'; i++) { 346864Sdinak if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 347864Sdinak realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 3483089Swyllys if (opts_av != NULL) 3493089Swyllys free(opts_av); 350864Sdinak opts_av = NULL; 351864Sdinak return (0); 3523089Swyllys } else { 353864Sdinak opts_av = (av_opts *)temp; 3543089Swyllys } 355864Sdinak 3563089Swyllys (void) memset(&opts_av[i], 0, sizeof (av_opts)); 357864Sdinak marker = optstring; /* may need optstring later */ 358864Sdinak 359864Sdinak opts_av[i].shortnm = *marker++; /* set short name */ 360864Sdinak 361864Sdinak if (*marker == ':') { /* check for opt arg */ 362864Sdinak marker++; 363864Sdinak opts_av[i].has_arg = B_TRUE; 364864Sdinak } 365864Sdinak 366864Sdinak if (*marker == '(') { /* check and set long name */ 367864Sdinak marker++; 368864Sdinak opts_av[i].longnm = marker; 369864Sdinak opts_av[i].longnm_len = strcspn(marker, ")"); 370864Sdinak optstring = marker + opts_av[i].longnm_len + 1; 371864Sdinak } else { 372864Sdinak /* use short name option character */ 373864Sdinak opts_av[i].longnm = optstring; 374864Sdinak opts_av[i].longnm_len = 1; 375864Sdinak optstring = marker; 376864Sdinak } 377864Sdinak } 378864Sdinak 379864Sdinak return (i); 380864Sdinak } 381864Sdinak 382864Sdinak /* 383864Sdinak * getopt_av() is very similar to getopt(3c) in that the takes an option 384864Sdinak * string, compares command line arguments for matches, and returns a single 385864Sdinak * letter option when a match is found. However, getopt_av() differs from 386864Sdinak * getopt(3c) by requiring that only longname options and values be found 387864Sdinak * on the command line and all leading dashes are omitted. In other words, 388864Sdinak * it tries to enforce only longname "option=value" arguments on the command 389864Sdinak * line. Boolean options are not allowed either. 390864Sdinak */ 391864Sdinak int 392864Sdinak getopt_av(int argc, char * const *argv, const char *optstring) 393864Sdinak { 394864Sdinak int i; 395864Sdinak int len; 3963089Swyllys char *cur_option; 397864Sdinak 398864Sdinak if (optind_av >= argc) 399864Sdinak return (EOF); 400864Sdinak 401864Sdinak /* First time or when optstring changes from previous one */ 402864Sdinak if (_save_optstr != optstring) { 403864Sdinak if (opts_av != NULL) 4045051Swyllys free(opts_av); 405864Sdinak opts_av = NULL; 406864Sdinak _save_optstr = optstring; 407864Sdinak _save_numopts = populate_opts((char *)optstring); 408864Sdinak } 409864Sdinak 410864Sdinak for (i = 0; i < _save_numopts; i++) { 4113089Swyllys cur_option = argv[optind_av]; 4123089Swyllys 4133089Swyllys if (strcmp(cur_option, "--") == 0) { 414864Sdinak optind_av++; 415864Sdinak break; 416864Sdinak } 417864Sdinak 4183089Swyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) { 4193089Swyllys len = 1; 4203089Swyllys cur_option++; /* remove "-" */ 4213089Swyllys } else { 4223089Swyllys len = strcspn(cur_option, "="); 4233089Swyllys } 424864Sdinak 4253089Swyllys if (len == opts_av[i].longnm_len && strncmp(cur_option, 426864Sdinak opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 427864Sdinak /* matched */ 428864Sdinak if (!opts_av[i].has_arg) { 429864Sdinak optind_av++; 430864Sdinak return (opts_av[i].shortnm); 431864Sdinak } 432864Sdinak 433864Sdinak /* needs optarg */ 4343089Swyllys if (cur_option[len] == '=') { 4353089Swyllys optarg_av = &(cur_option[len+1]); 436864Sdinak optind_av++; 437864Sdinak return (opts_av[i].shortnm); 438864Sdinak } 439864Sdinak 440864Sdinak optarg_av = NULL; 441864Sdinak optind_av++; 442864Sdinak return ((int)'?'); 443864Sdinak } 444864Sdinak } 445864Sdinak 446864Sdinak return (EOF); 447864Sdinak } 4483089Swyllys 4493089Swyllys KMF_KEYSTORE_TYPE 4503089Swyllys KS2Int(char *keystore_str) 4513089Swyllys { 4523089Swyllys if (keystore_str == NULL) 4533089Swyllys return (0); 4543089Swyllys if (!strcasecmp(keystore_str, "pkcs11")) 4553089Swyllys return (KMF_KEYSTORE_PK11TOKEN); 4563089Swyllys else if (!strcasecmp(keystore_str, "nss")) 4573089Swyllys return (KMF_KEYSTORE_NSS); 4583089Swyllys else if (!strcasecmp(keystore_str, "file")) 4593089Swyllys return (KMF_KEYSTORE_OPENSSL); 4603089Swyllys else 4613089Swyllys return (0); 4623089Swyllys } 4633089Swyllys 4643089Swyllys 4653089Swyllys int 4663089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg) 4673089Swyllys { 4683089Swyllys if (algm == NULL) { 4693089Swyllys *sigAlg = KMF_ALGID_MD5WithRSA; 4703089Swyllys *ktype = KMF_RSA; 4713089Swyllys } else if (strcasecmp(algm, "DSA") == 0) { 4723089Swyllys *sigAlg = KMF_ALGID_SHA1WithDSA; 4733089Swyllys *ktype = KMF_DSA; 4743089Swyllys } else if (strcasecmp(algm, "RSA") == 0) { 4753089Swyllys *sigAlg = KMF_ALGID_MD5WithRSA; 4763089Swyllys *ktype = KMF_RSA; 4773089Swyllys } else { 4783089Swyllys return (-1); 4793089Swyllys } 4803089Swyllys return (0); 4813089Swyllys } 4823089Swyllys 4833089Swyllys int 4843089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 4853089Swyllys { 4863089Swyllys if (algm == NULL) 4873089Swyllys *ktype = KMF_AES; 4883089Swyllys else if (strcasecmp(algm, "aes") == 0) 4893089Swyllys *ktype = KMF_AES; 4903089Swyllys else if (strcasecmp(algm, "arcfour") == 0) 4913089Swyllys *ktype = KMF_RC4; 4923089Swyllys else if (strcasecmp(algm, "des") == 0) 4933089Swyllys *ktype = KMF_DES; 4943089Swyllys else if (strcasecmp(algm, "3des") == 0) 4953089Swyllys *ktype = KMF_DES3; 4963812Shylee else if (strcasecmp(algm, "generic") == 0) 4973812Shylee *ktype = KMF_GENERIC_SECRET; 4983089Swyllys else 4993089Swyllys return (-1); 5003089Swyllys 5013089Swyllys return (0); 5023089Swyllys } 5033089Swyllys 5043089Swyllys int 5053089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime) 5063089Swyllys { 5073089Swyllys int num; 5083089Swyllys char timetok[6]; 5093089Swyllys 5103089Swyllys if (ltimestr == NULL || !strlen(ltimestr)) { 5113089Swyllys /* default to 1 year lifetime */ 5123089Swyllys *ltime = SECSPERDAY * DAYSPERNYEAR; 5133089Swyllys return (0); 5143089Swyllys } 5153089Swyllys 5163089Swyllys (void) memset(timetok, 0, sizeof (timetok)); 5173089Swyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 5183089Swyllys return (-1); 5193089Swyllys 5203089Swyllys if (!strcasecmp(timetok, "day") || 5213089Swyllys !strcasecmp(timetok, "days")) { 5223089Swyllys *ltime = num * SECSPERDAY; 5233089Swyllys } else if (!strcasecmp(timetok, "hour") || 5245051Swyllys !strcasecmp(timetok, "hours")) { 5253089Swyllys *ltime = num * SECSPERHOUR; 5263089Swyllys } else if (!strcasecmp(timetok, "year") || 5275051Swyllys !strcasecmp(timetok, "years")) { 5283089Swyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR; 5293089Swyllys } else { 5303089Swyllys *ltime = 0; 5313089Swyllys return (-1); 5323089Swyllys } 5333089Swyllys 5343089Swyllys return (0); 5353089Swyllys } 5363089Swyllys 5373089Swyllys int 5383089Swyllys OT2Int(char *objclass) 5393089Swyllys { 5403089Swyllys char *c = NULL; 5413089Swyllys int retval = 0; 5423089Swyllys 5433089Swyllys if (objclass == NULL) 5443089Swyllys return (-1); 5453089Swyllys 5463089Swyllys c = strchr(objclass, ':'); 5473089Swyllys if (c != NULL) { 5483089Swyllys if (!strcasecmp(c, ":private")) 5493089Swyllys retval = PK_PRIVATE_OBJ; 5503089Swyllys else if (!strcasecmp(c, ":public")) 5513089Swyllys retval = PK_PUBLIC_OBJ; 5523089Swyllys else if (!strcasecmp(c, ":both")) 5533089Swyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 5543089Swyllys else /* unrecognized option */ 5553089Swyllys return (-1); 5563089Swyllys 5573089Swyllys *c = '\0'; 5583089Swyllys } 5593089Swyllys 5603089Swyllys if (!strcasecmp(objclass, "public")) { 5613089Swyllys if (retval) 5623089Swyllys return (-1); 5635051Swyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ); 5643089Swyllys } else if (!strcasecmp(objclass, "private")) { 5653089Swyllys if (retval) 5663089Swyllys return (-1); 5673089Swyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 5683089Swyllys } else if (!strcasecmp(objclass, "both")) { 5693089Swyllys if (retval) 5703089Swyllys return (-1); 5713089Swyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 5723089Swyllys } else if (!strcasecmp(objclass, "cert")) { 5733089Swyllys return (retval | PK_CERT_OBJ); 5743089Swyllys } else if (!strcasecmp(objclass, "key")) { 5753089Swyllys if (retval == 0) /* return all keys */ 5763089Swyllys return (retval | PK_KEY_OBJ); 5773089Swyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 5783089Swyllys /* return all keys */ 5793089Swyllys return (retval | PK_KEY_OBJ); 5803089Swyllys else if (retval & PK_PUBLIC_OBJ) 5813089Swyllys /* Only return public keys */ 5823089Swyllys return (retval | PK_PUBKEY_OBJ); 5833089Swyllys else if (retval & PK_PRIVATE_OBJ) 5843089Swyllys /* Only return private keys */ 5853089Swyllys return (retval | PK_PRIKEY_OBJ); 5863089Swyllys } else if (!strcasecmp(objclass, "crl")) { 5873089Swyllys if (retval) 5883089Swyllys return (-1); 5893089Swyllys return (retval | PK_CRL_OBJ); 5903089Swyllys } 5913089Swyllys 5923089Swyllys if (retval == 0) /* No matches found */ 5933089Swyllys retval = -1; 5943089Swyllys return (retval); 5953089Swyllys } 5963089Swyllys 5973089Swyllys KMF_ENCODE_FORMAT 5983089Swyllys Str2Format(char *formstr) 5993089Swyllys { 6003089Swyllys if (formstr == NULL || !strcasecmp(formstr, "der")) 6013089Swyllys return (KMF_FORMAT_ASN1); 6023089Swyllys if (!strcasecmp(formstr, "pem")) 6033089Swyllys return (KMF_FORMAT_PEM); 6043089Swyllys if (!strcasecmp(formstr, "pkcs12")) 6053089Swyllys return (KMF_FORMAT_PKCS12); 6065051Swyllys if (!strcasecmp(formstr, "raw")) 6075051Swyllys return (KMF_FORMAT_RAWKEY); 6083089Swyllys 6093089Swyllys return (KMF_FORMAT_UNDEF); 6103089Swyllys } 6113089Swyllys 6123089Swyllys 6133089Swyllys KMF_RETURN 6143089Swyllys select_token(void *kmfhandle, char *token, 6153089Swyllys int readonly) 6163089Swyllys { 6175051Swyllys KMF_ATTRIBUTE attlist[10]; 6185051Swyllys int i = 0; 6195051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 6203089Swyllys KMF_RETURN rv = KMF_OK; 6213089Swyllys 6223089Swyllys if (token == NULL) 6233089Swyllys return (KMF_ERR_BAD_PARAMETER); 6243089Swyllys 6255051Swyllys kmf_set_attr_at_index(attlist, i, 6265051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 6275051Swyllys sizeof (kstype)); 6285051Swyllys i++; 6293089Swyllys 6305051Swyllys if (token) { 6315051Swyllys kmf_set_attr_at_index(attlist, i, 6325051Swyllys KMF_TOKEN_LABEL_ATTR, token, 6335051Swyllys strlen(token)); 6345051Swyllys i++; 6355051Swyllys } 6365051Swyllys 6375051Swyllys kmf_set_attr_at_index(attlist, i, 6385051Swyllys KMF_READONLY_ATTR, &readonly, 6395051Swyllys sizeof (readonly)); 6405051Swyllys i++; 6415051Swyllys 6425051Swyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 6433089Swyllys if (rv == KMF_ERR_TOKEN_SELECTED) 6443089Swyllys rv = KMF_OK; 6453089Swyllys return (rv); 6463089Swyllys } 6473089Swyllys 6483089Swyllys 6493089Swyllys KMF_RETURN 6503089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix) 6513089Swyllys { 6525051Swyllys 6535051Swyllys KMF_ATTRIBUTE attlist[10]; 6545051Swyllys int i = 0; 6555051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 6563089Swyllys KMF_RETURN rv = KMF_OK; 6575051Swyllys 6585051Swyllys kmf_set_attr_at_index(attlist, i, 6595051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 6605051Swyllys sizeof (kstype)); 6615051Swyllys i++; 6623089Swyllys 6635051Swyllys if (dir) { 6645051Swyllys kmf_set_attr_at_index(attlist, i, 6655051Swyllys KMF_DIRPATH_ATTR, dir, 6665051Swyllys strlen(dir)); 6675051Swyllys i++; 6685051Swyllys } 6693089Swyllys 6705051Swyllys if (prefix) { 6715051Swyllys kmf_set_attr_at_index(attlist, i, 6725051Swyllys KMF_CERTPREFIX_ATTR, prefix, 6735051Swyllys strlen(prefix)); 6745051Swyllys i++; 6755051Swyllys 6765051Swyllys kmf_set_attr_at_index(attlist, i, 6775051Swyllys KMF_KEYPREFIX_ATTR, prefix, 6785051Swyllys strlen(prefix)); 6795051Swyllys i++; 6805051Swyllys } 6815051Swyllys 6825051Swyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 6833089Swyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 6843089Swyllys rv = KMF_OK; 6853089Swyllys 6863089Swyllys return (rv); 6873089Swyllys } 6883089Swyllys 6893089Swyllys 6903089Swyllys KMF_RETURN 6913089Swyllys get_pk12_password(KMF_CREDENTIAL *cred) 6923089Swyllys { 6933089Swyllys KMF_RETURN rv = KMF_OK; 6943089Swyllys char prompt[1024]; 6953089Swyllys 6963089Swyllys /* 6973089Swyllys * Get the password to use for the PK12 encryption. 6983089Swyllys */ 6993089Swyllys (void) strlcpy(prompt, 7005051Swyllys gettext("Enter password to use for " 7015051Swyllys "accessing the PKCS12 file: "), sizeof (prompt)); 7023089Swyllys 7033089Swyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 7045051Swyllys (ulong_t *)&cred->credlen) != CKR_OK) { 7053089Swyllys cred->cred = NULL; 7063089Swyllys cred->credlen = 0; 7073089Swyllys } 7083089Swyllys 7093089Swyllys return (rv); 7103089Swyllys } 7113089Swyllys 712*5221Swyllys #define FILENAME_PROMPT gettext("Filename:") 713*5221Swyllys #define FILENAME_MINLEN 1 714*5221Swyllys #define FILENAME_MAXLEN MAXPATHLEN 7153089Swyllys 716*5221Swyllys #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:") 717*5221Swyllys #define STATE_PROMPT gettext("State or Province Name (full name) " \ 718*5221Swyllys "[Some-State]:") 719*5221Swyllys #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:") 720*5221Swyllys #define ORG_PROMPT gettext("Organization Name (eg, company) []:") 721*5221Swyllys #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:") 722*5221Swyllys #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:") 723*5221Swyllys #define EMAIL_PROMPT gettext("Email Address []:") 724*5221Swyllys 725*5221Swyllys #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \ 726*5221Swyllys "0x01020304):") 727*5221Swyllys #define SERNO_MINLEN 3 728*5221Swyllys #define SERNO_MAXLEN 42 729*5221Swyllys 730*5221Swyllys #define LABEL_PROMPT gettext("Enter a label for the certificate:") 731*5221Swyllys #define LABEL_MINLEN 1 732*5221Swyllys #define LABEL_MAXLEN 1024 7333089Swyllys 7343089Swyllys #define COUNTRY_DEFAULT "US" 735*5221Swyllys #define STATE_DEFAULT NULL 736*5221Swyllys #define INVALID_INPUT gettext("Invalid input; please re-enter ...") 7373089Swyllys 7383089Swyllys #define SUBNAMESIZ 1024 7393089Swyllys #define RDN_MIN 1 7403089Swyllys #define RDN_MAX 64 7413089Swyllys #define COUNTRYNAME_MIN 2 7423089Swyllys #define COUNTRYNAME_MAX 2 7433089Swyllys 7443089Swyllys static char * 7453089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len) 7463089Swyllys { 7473089Swyllys char buf[1024]; 7483089Swyllys char *response = NULL; 7493089Swyllys char *ret = NULL; 7503089Swyllys int len; 7513089Swyllys 7523089Swyllys for (;;) { 7533089Swyllys (void) printf("\t%s", prompt); 7543089Swyllys (void) fflush(stdout); 7553089Swyllys 7563089Swyllys response = fgets(buf, sizeof (buf), stdin); 7573089Swyllys if (response == NULL) { 7583089Swyllys if (default_str != NULL) { 7593089Swyllys ret = strdup(default_str); 7603089Swyllys } 7613089Swyllys break; 7623089Swyllys } 7633089Swyllys 7643089Swyllys /* Skip any leading white space. */ 7653089Swyllys while (isspace(*response)) 7663089Swyllys response++; 7673089Swyllys if (*response == '\0') { 7683089Swyllys if (default_str != NULL) { 7693089Swyllys ret = strdup(default_str); 7703089Swyllys } 7713089Swyllys break; 7723089Swyllys } 7733089Swyllys 7743089Swyllys len = strlen(response); 7753089Swyllys response[len-1] = '\0'; /* get rid of "LF" */ 7763089Swyllys len--; 7773089Swyllys if (len >= min_len && len <= max_len) { 7783089Swyllys ret = strdup(response); 7793089Swyllys break; 7803089Swyllys } 7813089Swyllys 7823089Swyllys (void) printf("%s\n", INVALID_INPUT); 7833089Swyllys 7843089Swyllys } 7853089Swyllys 7863089Swyllys return (ret); 7873089Swyllys } 7883089Swyllys 7893089Swyllys int 790*5221Swyllys get_filename(char *txt, char **result) 791*5221Swyllys { 792*5221Swyllys char prompt[1024]; 793*5221Swyllys char *fname = NULL; 794*5221Swyllys 795*5221Swyllys (void) snprintf(prompt, sizeof (prompt), 796*5221Swyllys gettext("Enter filename for the %s: "), 797*5221Swyllys txt); 798*5221Swyllys fname = get_input_string(prompt, NULL, 799*5221Swyllys FILENAME_MINLEN, FILENAME_MAXLEN); 800*5221Swyllys *result = fname; 801*5221Swyllys return (0); 802*5221Swyllys } 803*5221Swyllys 804*5221Swyllys int 805*5221Swyllys get_certlabel(char **result) 806*5221Swyllys { 807*5221Swyllys char *label = NULL; 808*5221Swyllys 809*5221Swyllys label = get_input_string(LABEL_PROMPT, NULL, 810*5221Swyllys LABEL_MINLEN, LABEL_MAXLEN); 811*5221Swyllys *result = label; 812*5221Swyllys return (0); 813*5221Swyllys } 814*5221Swyllys 815*5221Swyllys int 816*5221Swyllys get_serial(char **result) 817*5221Swyllys { 818*5221Swyllys char *serial = NULL; 819*5221Swyllys 820*5221Swyllys serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN, 821*5221Swyllys SERNO_MAXLEN); 822*5221Swyllys 823*5221Swyllys *result = serial; 824*5221Swyllys return (0); 825*5221Swyllys } 826*5221Swyllys 827*5221Swyllys int 8283089Swyllys get_subname(char **result) 8293089Swyllys { 8303089Swyllys char *country = NULL; 8313089Swyllys char *state = NULL; 8323089Swyllys char *locality = NULL; 8333089Swyllys char *org = NULL; 8343089Swyllys char *unit = NULL; 8353089Swyllys char *name = NULL; 8363089Swyllys char *email = NULL; 8373089Swyllys char *subname = NULL; 8383089Swyllys 8393089Swyllys (void) printf("Entering following fields for subject (a DN) ...\n"); 8403089Swyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 8413089Swyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX); 8423089Swyllys if (country == NULL) 8433089Swyllys return (-1); 8443089Swyllys 8453089Swyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 8463089Swyllys RDN_MIN, RDN_MAX); 8473089Swyllys 8483089Swyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 8493089Swyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 8503089Swyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 8513089Swyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 8523089Swyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 8533089Swyllys 8543089Swyllys /* Now create a subject name from the input strings */ 8553089Swyllys if ((subname = malloc(SUBNAMESIZ)) == NULL) 8563089Swyllys goto out; 8573089Swyllys 8583089Swyllys (void) memset(subname, 0, SUBNAMESIZ); 8593089Swyllys (void) strlcpy(subname, "C=", SUBNAMESIZ); 8603089Swyllys (void) strlcat(subname, country, SUBNAMESIZ); 861*5221Swyllys if (state != NULL) { 862*5221Swyllys (void) strlcat(subname, ", ST=", SUBNAMESIZ); 863*5221Swyllys (void) strlcat(subname, state, SUBNAMESIZ); 864*5221Swyllys } 8653089Swyllys 866*5221Swyllys if (locality != NULL) { 867*5221Swyllys (void) strlcat(subname, ", L=", SUBNAMESIZ); 8683089Swyllys (void) strlcat(subname, locality, SUBNAMESIZ); 8693089Swyllys } 8703089Swyllys 871*5221Swyllys if (org != NULL) { 872*5221Swyllys (void) strlcat(subname, ", O=", SUBNAMESIZ); 8733089Swyllys (void) strlcat(subname, org, SUBNAMESIZ); 8743089Swyllys } 8753089Swyllys 876*5221Swyllys if (unit != NULL) { 877*5221Swyllys (void) strlcat(subname, ", OU=", SUBNAMESIZ); 8783089Swyllys (void) strlcat(subname, unit, SUBNAMESIZ); 8793089Swyllys } 8803089Swyllys 881*5221Swyllys if (name != NULL) { 882*5221Swyllys (void) strlcat(subname, ", CN=", SUBNAMESIZ); 8833089Swyllys (void) strlcat(subname, name, SUBNAMESIZ); 8843089Swyllys } 8853089Swyllys 886*5221Swyllys if (email != NULL) { 887*5221Swyllys (void) strlcat(subname, ", E=", SUBNAMESIZ); 8883089Swyllys (void) strlcat(subname, email, SUBNAMESIZ); 8893089Swyllys } 8903089Swyllys 8913089Swyllys out: 8923089Swyllys if (country) 8933089Swyllys free(country); 8943089Swyllys if (state) 8953089Swyllys free(state); 8963089Swyllys if (locality) 8973089Swyllys free(locality); 8983089Swyllys if (org) 8993089Swyllys free(org); 9003089Swyllys if (unit) 9013089Swyllys free(unit); 9023089Swyllys if (name) 9033089Swyllys free(name); 9043089Swyllys if (email) 9053089Swyllys free(email); 9063089Swyllys 9073089Swyllys if (subname == NULL) 9083089Swyllys return (-1); 9093089Swyllys else { 9103089Swyllys *result = subname; 9113089Swyllys return (0); 9123089Swyllys } 9133089Swyllys } 9143089Swyllys 9153089Swyllys /* 9163089Swyllys * Parse a string of KeyUsage values and convert 9173089Swyllys * them to the correct KU Bits. 9183089Swyllys * The field may be marked "critical" by prepending 9193089Swyllys * "critical:" to the list. 9203089Swyllys * EX: critical:digitialSignature,keyEncipherment 9213089Swyllys */ 9223089Swyllys KMF_RETURN 9233089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 9243089Swyllys { 9253089Swyllys KMF_RETURN ret = KMF_OK; 9263089Swyllys uint16_t kuval; 9273089Swyllys char *k; 9283089Swyllys 9293089Swyllys *kubits = 0; 9303089Swyllys if (kustr == NULL || !strlen(kustr)) 9313089Swyllys return (KMF_ERR_BAD_PARAMETER); 9323089Swyllys 9333089Swyllys /* Check to see if this is critical */ 9343089Swyllys if (!strncasecmp(kustr, "critical:", strlen("critical:"))) { 9353089Swyllys *critical = TRUE; 9363089Swyllys kustr += strlen("critical:"); 9373089Swyllys } else { 9383089Swyllys *critical = FALSE; 9393089Swyllys } 9403089Swyllys 9413089Swyllys k = strtok(kustr, ","); 9423089Swyllys while (k != NULL) { 9435051Swyllys kuval = kmf_string_to_ku(k); 9443089Swyllys if (kuval == 0) { 9453089Swyllys *kubits = 0; 9463089Swyllys return (KMF_ERR_BAD_PARAMETER); 9473089Swyllys } 9483089Swyllys *kubits |= kuval; 9493089Swyllys k = strtok(NULL, ","); 9503089Swyllys } 9513089Swyllys 9523089Swyllys return (ret); 9533089Swyllys } 9543089Swyllys 9553089Swyllys /* 9563089Swyllys * Verify the alternate subject label is real or invalid. 9573089Swyllys * 9583089Swyllys * The field may be marked "critical" by prepending 9593089Swyllys * "critical:" to the list. 9603089Swyllys * EX: "critical:IP=1.2.3.4" 9613089Swyllys */ 9623089Swyllys KMF_RETURN 9633089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 9643089Swyllys { 9653089Swyllys char *p; 9663089Swyllys KMF_RETURN rv = KMF_OK; 9673089Swyllys 9683089Swyllys /* Check to see if this is critical */ 9693089Swyllys if (!strncasecmp(arg, "critical:", strlen("critical:"))) { 9703089Swyllys *critical = TRUE; 9713089Swyllys arg += strlen("critical:"); 9723089Swyllys } else { 9733089Swyllys *critical = FALSE; 9743089Swyllys } 9753089Swyllys 9763089Swyllys /* Make sure there is an "=" sign */ 9773089Swyllys p = strchr(arg, '='); 9783089Swyllys if (p == NULL) 9793089Swyllys return (KMF_ERR_BAD_PARAMETER); 9803089Swyllys 9813089Swyllys p[0] = '\0'; 9823089Swyllys 9833089Swyllys if (strcmp(arg, "IP") == 0) 9843089Swyllys *type = GENNAME_IPADDRESS; 9853089Swyllys else if (strcmp(arg, "DNS") == 0) 9863089Swyllys *type = GENNAME_DNSNAME; 9873089Swyllys else if (strcmp(arg, "EMAIL") == 0) 9883089Swyllys *type = GENNAME_RFC822NAME; 9893089Swyllys else if (strcmp(arg, "URI") == 0) 9903089Swyllys *type = GENNAME_URI; 9913089Swyllys else if (strcmp(arg, "DN") == 0) 9923089Swyllys *type = GENNAME_DIRECTORYNAME; 9933089Swyllys else if (strcmp(arg, "RID") == 0) 9943089Swyllys *type = GENNAME_REGISTEREDID; 9953089Swyllys else 9963089Swyllys rv = KMF_ERR_BAD_PARAMETER; 9973089Swyllys 9983089Swyllys p[0] = '='; 9993089Swyllys 10003089Swyllys return (rv); 10013089Swyllys } 10023089Swyllys 10033089Swyllys int 10043089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype, 10053089Swyllys char *token_spec, KMF_CREDENTIAL *cred) 10063089Swyllys { 10073089Swyllys char prompt[1024]; 10083089Swyllys char *p = NULL; 10093089Swyllys 10103089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) { 10113089Swyllys p = strchr(token_spec, ':'); 10123089Swyllys if (p != NULL) 10133089Swyllys *p = 0; 10143089Swyllys } 10153089Swyllys /* 10163089Swyllys * Login to the token first. 10173089Swyllys */ 10183089Swyllys (void) snprintf(prompt, sizeof (prompt), 10195051Swyllys gettext(DEFAULT_TOKEN_PROMPT), token_spec); 10203089Swyllys 10213089Swyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 10225051Swyllys (ulong_t *)&cred->credlen) != CKR_OK) { 10233089Swyllys cred->cred = NULL; 10243089Swyllys cred->credlen = 0; 10253089Swyllys } 10263089Swyllys 10273089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 10283089Swyllys *p = ':'; 10293089Swyllys return (KMF_OK); 10303089Swyllys } 10313089Swyllys 10323089Swyllys KMF_RETURN 10333089Swyllys verify_file(char *filename) 10343089Swyllys { 10353089Swyllys KMF_RETURN ret = KMF_OK; 10363089Swyllys int fd; 10373089Swyllys 10383089Swyllys /* 10393089Swyllys * Attempt to open with the EXCL flag so that if 10403089Swyllys * it already exists, the open will fail. It will 10413089Swyllys * also fail if the file cannot be created due to 10423089Swyllys * permissions on the parent directory, or if the 10433089Swyllys * parent directory itself does not exist. 10443089Swyllys */ 10453089Swyllys fd = open(filename, O_CREAT | O_EXCL, 0600); 10463089Swyllys if (fd == -1) 10473089Swyllys return (KMF_ERR_OPEN_FILE); 10483089Swyllys 10493089Swyllys /* If we were able to create it, delete it. */ 10503089Swyllys (void) close(fd); 10513089Swyllys (void) unlink(filename); 10523089Swyllys 10533089Swyllys return (ret); 10543089Swyllys } 10553089Swyllys 10563089Swyllys void 10573089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix) 10583089Swyllys { 10593089Swyllys KMF_RETURN rv1, rv2; 10603089Swyllys char *plugin_errmsg = NULL; 10613089Swyllys char *kmf_errmsg = NULL; 10623089Swyllys 10635051Swyllys rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg); 10645051Swyllys rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg); 10653089Swyllys 10663089Swyllys cryptoerror(LOG_STDERR, "%s:", prefix); 10673089Swyllys if (rv1 == KMF_OK && plugin_errmsg) { 10685051Swyllys cryptoerror(LOG_STDERR, gettext("keystore error: %s"), 10695051Swyllys plugin_errmsg); 10705051Swyllys kmf_free_str(plugin_errmsg); 10713089Swyllys } 10723089Swyllys 10733089Swyllys if (rv2 == KMF_OK && kmf_errmsg) { 10745051Swyllys cryptoerror(LOG_STDERR, gettext("libkmf error: %s"), 10755051Swyllys kmf_errmsg); 10765051Swyllys kmf_free_str(kmf_errmsg); 10773089Swyllys } 10783089Swyllys 10793089Swyllys if (rv1 != KMF_OK && rv2 != KMF_OK) 10803089Swyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 10813089Swyllys 10823089Swyllys } 1083