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 /* 22*9126SWyllys.Ingersoll@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * This file contains the functions that are shared among 280Sstevel@tonic-gate * the various services this tool will ultimately provide. 2917Sdinak * The functions in this file return PKCS#11 CK_RV errors. 3017Sdinak * Only one session and one login per token is supported 3117Sdinak * at this time. 320Sstevel@tonic-gate */ 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include <stdio.h> 350Sstevel@tonic-gate #include <stdlib.h> 360Sstevel@tonic-gate #include <string.h> 370Sstevel@tonic-gate #include <ctype.h> 383089Swyllys #include <sys/types.h> 393089Swyllys #include <sys/stat.h> 403089Swyllys #include <fcntl.h> 413089Swyllys #include <tzfile.h> 420Sstevel@tonic-gate #include <cryptoutil.h> 430Sstevel@tonic-gate #include <security/cryptoki.h> 443089Swyllys #include <kmfapi.h> 450Sstevel@tonic-gate 463089Swyllys #include "common.h" 4717Sdinak 4817Sdinak /* Local status variables. */ 4917Sdinak static boolean_t initialized = B_FALSE; 5017Sdinak static boolean_t session_opened = B_FALSE; 5117Sdinak static boolean_t logged_in = B_FALSE; 5217Sdinak 53864Sdinak /* Supporting structures and global variables for getopt_av(). */ 54864Sdinak typedef struct av_opts_s { 55864Sdinak int shortnm; /* short name character */ 56864Sdinak char *longnm; /* long name string, NOT terminated */ 57864Sdinak int longnm_len; /* length of long name string */ 58864Sdinak boolean_t has_arg; /* takes optional argument */ 59864Sdinak } av_opts; 60864Sdinak static av_opts *opts_av = NULL; 61864Sdinak static const char *_save_optstr = NULL; 62864Sdinak static int _save_numopts = 0; 63864Sdinak 64864Sdinak int optind_av = 1; 65864Sdinak char *optarg_av = NULL; 66864Sdinak 673089Swyllys static void close_sess(CK_SESSION_HANDLE); 683089Swyllys static void logout_token(CK_SESSION_HANDLE); 693089Swyllys 7017Sdinak /* 7117Sdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 7217Sdinak * along with setting/resetting state variables. 7317Sdinak */ 746669Swyllys static CK_RV 756669Swyllys init_pkcs11(void) 7617Sdinak { 7717Sdinak CK_RV rv = CKR_OK; 7817Sdinak 7917Sdinak /* If C_Initialize() already called, nothing to do here. */ 8017Sdinak if (initialized == B_TRUE) 8117Sdinak return (CKR_OK); 8217Sdinak 8317Sdinak /* Reset state variables because C_Initialize() not yet done. */ 8417Sdinak session_opened = B_FALSE; 8517Sdinak logged_in = B_FALSE; 8617Sdinak 8717Sdinak /* Initialize PKCS#11 library. */ 8817Sdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 8917Sdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 9017Sdinak return (rv); 9117Sdinak } 9217Sdinak 9317Sdinak initialized = B_TRUE; 9417Sdinak return (CKR_OK); 9517Sdinak } 9617Sdinak 9717Sdinak /* 9817Sdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 9917Sdinak * if any, are closed, and thereby any logins are logged out also. 10017Sdinak */ 10117Sdinak void 10217Sdinak final_pk11(CK_SESSION_HANDLE sess) 10317Sdinak { 10417Sdinak 10517Sdinak /* If the library wasn't initialized, nothing to do here. */ 10617Sdinak if (!initialized) 10717Sdinak return; 10817Sdinak 10917Sdinak /* Make sure the sesion is closed first. */ 11017Sdinak close_sess(sess); 11117Sdinak 11217Sdinak (void) C_Finalize(NULL); 11317Sdinak initialized = B_FALSE; 11417Sdinak } 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate /* 11717Sdinak * Close PKCS#11 session and reset state variables. Any logins are 11817Sdinak * logged out. 11917Sdinak */ 1203089Swyllys static void 12117Sdinak close_sess(CK_SESSION_HANDLE sess) 12217Sdinak { 12317Sdinak 12417Sdinak if (sess == NULL) { 12517Sdinak return; 12617Sdinak } 12717Sdinak 12817Sdinak /* If session is already closed, nothing to do here. */ 12917Sdinak if (!session_opened) 13017Sdinak return; 1310Sstevel@tonic-gate 13217Sdinak /* Make sure user is logged out of token. */ 13317Sdinak logout_token(sess); 13417Sdinak 13517Sdinak (void) C_CloseSession(sess); 13617Sdinak session_opened = B_FALSE; 13717Sdinak } 13817Sdinak 13917Sdinak /* 14017Sdinak * Log user out of token and reset status variable. 14117Sdinak */ 1423089Swyllys static void 14317Sdinak logout_token(CK_SESSION_HANDLE sess) 14417Sdinak { 14517Sdinak 14617Sdinak if (sess == NULL) { 14717Sdinak return; 14817Sdinak } 14917Sdinak 15017Sdinak /* If already logged out, nothing to do here. */ 15117Sdinak if (!logged_in) 15217Sdinak return; 15317Sdinak 15417Sdinak (void) C_Logout(sess); 15517Sdinak logged_in = B_FALSE; 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 15917Sdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 16017Sdinak * If two prompts are given, the PIN is confirmed with second prompt. 16117Sdinak * Note that getphassphrase() may return data in static memory area. 16217Sdinak */ 16317Sdinak CK_RV 16417Sdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 16517Sdinak { 1666051Swyllys char *save_phrase, *phrase1, *phrase2; 1670Sstevel@tonic-gate 16817Sdinak /* Prompt user for a PIN. */ 16917Sdinak if (prompt1 == NULL) { 17017Sdinak return (CKR_ARGUMENTS_BAD); 17117Sdinak } 17217Sdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 17317Sdinak return (CKR_FUNCTION_FAILED); 17417Sdinak } 17517Sdinak 17617Sdinak /* Duplicate 1st PIN in separate chunk of memory. */ 17717Sdinak if ((save_phrase = strdup(phrase1)) == NULL) 17817Sdinak return (CKR_HOST_MEMORY); 17917Sdinak 18017Sdinak /* If second prompt given, PIN confirmation is requested. */ 18117Sdinak if (prompt2 != NULL) { 18217Sdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 18317Sdinak free(save_phrase); 18417Sdinak return (CKR_FUNCTION_FAILED); 18517Sdinak } 18617Sdinak if (strcmp(save_phrase, phrase2) != 0) { 18717Sdinak free(save_phrase); 18817Sdinak return (CKR_PIN_INCORRECT); 18917Sdinak } 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 19217Sdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 19317Sdinak *pinlen = strlen(save_phrase); 19417Sdinak return (CKR_OK); 19517Sdinak } 19617Sdinak 1976051Swyllys int 1986051Swyllys yn_to_int(char *ynstr) 1996051Swyllys { 2006051Swyllys char *y = gettext("yes"); 2016051Swyllys char *n = gettext("no"); 2026051Swyllys if (ynstr == NULL) 2036051Swyllys return (-1); 2046051Swyllys 2056051Swyllys if (strncasecmp(ynstr, y, 1) == 0) 2066051Swyllys return (1); 2076051Swyllys else if (strncasecmp(ynstr, n, 1) == 0) 2086051Swyllys return (0); 2096051Swyllys else 2106051Swyllys return (-1); 2116051Swyllys } 2126051Swyllys 21317Sdinak /* 21417Sdinak * Gets yes/no response from user. If either no prompt is supplied, a 21517Sdinak * default prompt is used. If not message for invalid input is supplied, 21617Sdinak * a default will not be provided. If the user provides no response, 21717Sdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 21817Sdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 21917Sdinak */ 22017Sdinak boolean_t 22117Sdinak yesno(char *prompt, char *invalid, boolean_t dflt) 22217Sdinak { 2236051Swyllys char *response, buf[1024]; 2246051Swyllys int ans; 22517Sdinak 22617Sdinak if (prompt == NULL) 22717Sdinak prompt = gettext("Enter (y)es or (n)o? "); 22817Sdinak 22917Sdinak for (;;) { 23017Sdinak /* Prompt user. */ 23117Sdinak (void) printf("%s", prompt); 23217Sdinak (void) fflush(stdout); 23317Sdinak 23417Sdinak /* Get the response. */ 23517Sdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 23617Sdinak break; /* go to default response */ 23717Sdinak 23817Sdinak /* Skip any leading white space. */ 23917Sdinak while (isspace(*response)) 24017Sdinak response++; 24117Sdinak if (*response == '\0') 24217Sdinak break; /* go to default response */ 24317Sdinak 2446051Swyllys ans = yn_to_int(response); 2456051Swyllys if (ans == 1) 24617Sdinak return (B_TRUE); 2476051Swyllys else if (ans == 0) 24817Sdinak return (B_FALSE); 24917Sdinak 25017Sdinak /* Indicate invalid input, and try again. */ 25117Sdinak if (invalid != NULL) 2525051Swyllys (void) printf("%s", invalid); 25317Sdinak } 25417Sdinak return (dflt); 25517Sdinak } 25617Sdinak 25717Sdinak /* 25817Sdinak * Gets the list of slots which have tokens in them. Keeps adjusting 25917Sdinak * the size of the slot list buffer until the call is successful or an 26017Sdinak * irrecoverable error occurs. 26117Sdinak */ 26217Sdinak CK_RV 26317Sdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 26417Sdinak { 26517Sdinak CK_ULONG tmp_count = 0; 26617Sdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 26717Sdinak int rv = CKR_OK; 26817Sdinak 26917Sdinak if (!initialized) 2706669Swyllys if ((rv = init_pkcs11()) != CKR_OK) 27117Sdinak return (rv); 27217Sdinak 27317Sdinak /* 27417Sdinak * Get the slot count first because we don't know how many 27517Sdinak * slots there are and how many of those slots even have tokens. 27617Sdinak * Don't specify an arbitrary buffer size for the slot list; 27717Sdinak * it may be too small (see section 11.5 of PKCS#11 spec). 27817Sdinak * Also select only those slots that have tokens in them, 27917Sdinak * because this tool has no need to know about empty slots. 28017Sdinak */ 28117Sdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 28217Sdinak return (rv); 28317Sdinak 28417Sdinak if (tmp_count == 0) { 28517Sdinak *slot_list = NULL_PTR; 28617Sdinak *slot_count = 0; 28717Sdinak return (CKR_OK); 28817Sdinak } 28917Sdinak 29017Sdinak /* Allocate initial space for the slot list. */ 29117Sdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 29217Sdinak sizeof (CK_SLOT_ID))) == NULL) 29317Sdinak return (CKR_HOST_MEMORY); 29417Sdinak 29517Sdinak /* Then get the slot list itself. */ 29617Sdinak for (;;) { 29717Sdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 29817Sdinak *slot_list = tmp_list; 29917Sdinak *slot_count = tmp_count; 30017Sdinak break; 30117Sdinak } 30217Sdinak 30317Sdinak if (rv != CKR_BUFFER_TOO_SMALL) { 30417Sdinak free(tmp_list); 30517Sdinak break; 30617Sdinak } 30717Sdinak 30817Sdinak /* If the number of slots grew, try again. */ 30917Sdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 31017Sdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 31117Sdinak free(tmp_list); 31217Sdinak rv = CKR_HOST_MEMORY; 31317Sdinak break; 31417Sdinak } 31517Sdinak tmp_list = tmp2_list; 31617Sdinak } 31717Sdinak 31817Sdinak return (rv); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate /* 322864Sdinak * Breaks out the getopt-style option string into a structure that can be 323864Sdinak * traversed later for calls to getopt_av(). Option string is NOT altered, 324864Sdinak * but the struct fields point to locations within option string. 325864Sdinak */ 326864Sdinak static int 327864Sdinak populate_opts(char *optstring) 328864Sdinak { 329864Sdinak int i; 330864Sdinak av_opts *temp; 331864Sdinak char *marker; 332864Sdinak 333864Sdinak if (optstring == NULL || *optstring == '\0') 334864Sdinak return (0); 335864Sdinak 336864Sdinak /* 337864Sdinak * This tries to imitate getopt(3c) Each option must conform to: 338864Sdinak * <short name char> [ ':' ] [ '(' <long name string> ')' ] 339864Sdinak * If long name is missing, the short name is used for long name. 340864Sdinak */ 341864Sdinak for (i = 0; *optstring != '\0'; i++) { 342864Sdinak if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 343864Sdinak realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 3443089Swyllys if (opts_av != NULL) 3453089Swyllys free(opts_av); 346864Sdinak opts_av = NULL; 347864Sdinak return (0); 3483089Swyllys } else { 349864Sdinak opts_av = (av_opts *)temp; 3503089Swyllys } 351864Sdinak 3523089Swyllys (void) memset(&opts_av[i], 0, sizeof (av_opts)); 353864Sdinak marker = optstring; /* may need optstring later */ 354864Sdinak 355864Sdinak opts_av[i].shortnm = *marker++; /* set short name */ 356864Sdinak 357864Sdinak if (*marker == ':') { /* check for opt arg */ 358864Sdinak marker++; 359864Sdinak opts_av[i].has_arg = B_TRUE; 360864Sdinak } 361864Sdinak 362864Sdinak if (*marker == '(') { /* check and set long name */ 363864Sdinak marker++; 364864Sdinak opts_av[i].longnm = marker; 365864Sdinak opts_av[i].longnm_len = strcspn(marker, ")"); 366864Sdinak optstring = marker + opts_av[i].longnm_len + 1; 367864Sdinak } else { 368864Sdinak /* use short name option character */ 369864Sdinak opts_av[i].longnm = optstring; 370864Sdinak opts_av[i].longnm_len = 1; 371864Sdinak optstring = marker; 372864Sdinak } 373864Sdinak } 374864Sdinak 375864Sdinak return (i); 376864Sdinak } 377864Sdinak 378864Sdinak /* 379864Sdinak * getopt_av() is very similar to getopt(3c) in that the takes an option 380864Sdinak * string, compares command line arguments for matches, and returns a single 381864Sdinak * letter option when a match is found. However, getopt_av() differs from 382864Sdinak * getopt(3c) by requiring that only longname options and values be found 383864Sdinak * on the command line and all leading dashes are omitted. In other words, 384864Sdinak * it tries to enforce only longname "option=value" arguments on the command 385864Sdinak * line. Boolean options are not allowed either. 386864Sdinak */ 387864Sdinak int 388864Sdinak getopt_av(int argc, char * const *argv, const char *optstring) 389864Sdinak { 390864Sdinak int i; 391864Sdinak int len; 3923089Swyllys char *cur_option; 393864Sdinak 394864Sdinak if (optind_av >= argc) 395864Sdinak return (EOF); 396864Sdinak 397864Sdinak /* First time or when optstring changes from previous one */ 398864Sdinak if (_save_optstr != optstring) { 399864Sdinak if (opts_av != NULL) 4005051Swyllys free(opts_av); 401864Sdinak opts_av = NULL; 402864Sdinak _save_optstr = optstring; 403864Sdinak _save_numopts = populate_opts((char *)optstring); 404864Sdinak } 405864Sdinak 406864Sdinak for (i = 0; i < _save_numopts; i++) { 4073089Swyllys cur_option = argv[optind_av]; 4083089Swyllys 4093089Swyllys if (strcmp(cur_option, "--") == 0) { 410864Sdinak optind_av++; 411864Sdinak break; 412864Sdinak } 413864Sdinak 4143089Swyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) { 4153089Swyllys len = 1; 4163089Swyllys cur_option++; /* remove "-" */ 4173089Swyllys } else { 4183089Swyllys len = strcspn(cur_option, "="); 4193089Swyllys } 420864Sdinak 4213089Swyllys if (len == opts_av[i].longnm_len && strncmp(cur_option, 422864Sdinak opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 423864Sdinak /* matched */ 424864Sdinak if (!opts_av[i].has_arg) { 425864Sdinak optind_av++; 426864Sdinak return (opts_av[i].shortnm); 427864Sdinak } 428864Sdinak 429864Sdinak /* needs optarg */ 4303089Swyllys if (cur_option[len] == '=') { 4313089Swyllys optarg_av = &(cur_option[len+1]); 432864Sdinak optind_av++; 433864Sdinak return (opts_av[i].shortnm); 434864Sdinak } 435864Sdinak 436864Sdinak optarg_av = NULL; 437864Sdinak optind_av++; 438864Sdinak return ((int)'?'); 439864Sdinak } 440864Sdinak } 441864Sdinak 442864Sdinak return (EOF); 443864Sdinak } 4443089Swyllys 4453089Swyllys KMF_KEYSTORE_TYPE 4463089Swyllys KS2Int(char *keystore_str) 4473089Swyllys { 4483089Swyllys if (keystore_str == NULL) 4493089Swyllys return (0); 4506051Swyllys if (strcasecmp(keystore_str, "pkcs11") == 0) 4513089Swyllys return (KMF_KEYSTORE_PK11TOKEN); 4526051Swyllys else if (strcasecmp(keystore_str, "nss") == 0) 4533089Swyllys return (KMF_KEYSTORE_NSS); 4546051Swyllys else if (strcasecmp(keystore_str, "file") == 0) 4553089Swyllys return (KMF_KEYSTORE_OPENSSL); 4563089Swyllys else 4573089Swyllys return (0); 4583089Swyllys } 4593089Swyllys 4603089Swyllys 4613089Swyllys int 4623089Swyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg) 4633089Swyllys { 4643089Swyllys if (algm == NULL) { 4653089Swyllys *sigAlg = KMF_ALGID_MD5WithRSA; 4663089Swyllys *ktype = KMF_RSA; 4673089Swyllys } else if (strcasecmp(algm, "DSA") == 0) { 4683089Swyllys *sigAlg = KMF_ALGID_SHA1WithDSA; 4693089Swyllys *ktype = KMF_DSA; 4703089Swyllys } else if (strcasecmp(algm, "RSA") == 0) { 4713089Swyllys *sigAlg = KMF_ALGID_MD5WithRSA; 4723089Swyllys *ktype = KMF_RSA; 4733089Swyllys } else { 4743089Swyllys return (-1); 4753089Swyllys } 4763089Swyllys return (0); 4773089Swyllys } 4783089Swyllys 4793089Swyllys int 4803089Swyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 4813089Swyllys { 4823089Swyllys if (algm == NULL) 4833089Swyllys *ktype = KMF_AES; 4843089Swyllys else if (strcasecmp(algm, "aes") == 0) 4853089Swyllys *ktype = KMF_AES; 4863089Swyllys else if (strcasecmp(algm, "arcfour") == 0) 4873089Swyllys *ktype = KMF_RC4; 4883089Swyllys else if (strcasecmp(algm, "des") == 0) 4893089Swyllys *ktype = KMF_DES; 4903089Swyllys else if (strcasecmp(algm, "3des") == 0) 4913089Swyllys *ktype = KMF_DES3; 4923812Shylee else if (strcasecmp(algm, "generic") == 0) 4933812Shylee *ktype = KMF_GENERIC_SECRET; 4943089Swyllys else 4953089Swyllys return (-1); 4963089Swyllys 4973089Swyllys return (0); 4983089Swyllys } 4993089Swyllys 5003089Swyllys int 5013089Swyllys Str2Lifetime(char *ltimestr, uint32_t *ltime) 5023089Swyllys { 5033089Swyllys int num; 5043089Swyllys char timetok[6]; 5053089Swyllys 5066051Swyllys if (ltimestr == NULL || strlen(ltimestr) == 0) { 5073089Swyllys /* default to 1 year lifetime */ 5083089Swyllys *ltime = SECSPERDAY * DAYSPERNYEAR; 5093089Swyllys return (0); 5103089Swyllys } 5113089Swyllys 5123089Swyllys (void) memset(timetok, 0, sizeof (timetok)); 5133089Swyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 5143089Swyllys return (-1); 5153089Swyllys 5166051Swyllys if (strcasecmp(timetok, "day") == 0|| 5176051Swyllys strcasecmp(timetok, "days") == 0) { 5183089Swyllys *ltime = num * SECSPERDAY; 5196051Swyllys } else if (strcasecmp(timetok, "hour") == 0|| 5206051Swyllys strcasecmp(timetok, "hours") == 0) { 5213089Swyllys *ltime = num * SECSPERHOUR; 5226051Swyllys } else if (strcasecmp(timetok, "year") == 0 || 5236051Swyllys strcasecmp(timetok, "years") == 0) { 5243089Swyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR; 5253089Swyllys } else { 5263089Swyllys *ltime = 0; 5273089Swyllys return (-1); 5283089Swyllys } 5293089Swyllys 5303089Swyllys return (0); 5313089Swyllys } 5323089Swyllys 5333089Swyllys int 5343089Swyllys OT2Int(char *objclass) 5353089Swyllys { 5363089Swyllys char *c = NULL; 5373089Swyllys int retval = 0; 5383089Swyllys 5393089Swyllys if (objclass == NULL) 5403089Swyllys return (-1); 5413089Swyllys 5423089Swyllys c = strchr(objclass, ':'); 5433089Swyllys if (c != NULL) { 5446051Swyllys if (strcasecmp(c, ":private") == 0) 5453089Swyllys retval = PK_PRIVATE_OBJ; 5466051Swyllys else if (strcasecmp(c, ":public") == 0) 5473089Swyllys retval = PK_PUBLIC_OBJ; 5486051Swyllys else if (strcasecmp(c, ":both") == 0) 5493089Swyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 5503089Swyllys else /* unrecognized option */ 5513089Swyllys return (-1); 5523089Swyllys 5533089Swyllys *c = '\0'; 5543089Swyllys } 5553089Swyllys 5566051Swyllys if (strcasecmp(objclass, "public") == 0) { 5573089Swyllys if (retval) 5583089Swyllys return (-1); 5595051Swyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ); 5606051Swyllys } else if (strcasecmp(objclass, "private") == 0) { 5613089Swyllys if (retval) 5623089Swyllys return (-1); 5633089Swyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 5646051Swyllys } else if (strcasecmp(objclass, "both") == 0) { 5653089Swyllys if (retval) 5663089Swyllys return (-1); 5673089Swyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 5686051Swyllys } else if (strcasecmp(objclass, "cert") == 0) { 5693089Swyllys return (retval | PK_CERT_OBJ); 5706051Swyllys } else if (strcasecmp(objclass, "key") == 0) { 5713089Swyllys if (retval == 0) /* return all keys */ 5723089Swyllys return (retval | PK_KEY_OBJ); 5733089Swyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 5743089Swyllys /* return all keys */ 5753089Swyllys return (retval | PK_KEY_OBJ); 5763089Swyllys else if (retval & PK_PUBLIC_OBJ) 5773089Swyllys /* Only return public keys */ 5783089Swyllys return (retval | PK_PUBKEY_OBJ); 5793089Swyllys else if (retval & PK_PRIVATE_OBJ) 5803089Swyllys /* Only return private keys */ 5813089Swyllys return (retval | PK_PRIKEY_OBJ); 5826051Swyllys } else if (strcasecmp(objclass, "crl") == 0) { 5833089Swyllys if (retval) 5843089Swyllys return (-1); 5853089Swyllys return (retval | PK_CRL_OBJ); 5863089Swyllys } 5873089Swyllys 5883089Swyllys if (retval == 0) /* No matches found */ 5893089Swyllys retval = -1; 5903089Swyllys return (retval); 5913089Swyllys } 5923089Swyllys 5933089Swyllys KMF_ENCODE_FORMAT 5943089Swyllys Str2Format(char *formstr) 5953089Swyllys { 5966051Swyllys if (formstr == NULL || strcasecmp(formstr, "der") == 0) 5973089Swyllys return (KMF_FORMAT_ASN1); 5986051Swyllys if (strcasecmp(formstr, "pem") == 0) 5993089Swyllys return (KMF_FORMAT_PEM); 6006051Swyllys if (strcasecmp(formstr, "pkcs12") == 0) 6013089Swyllys return (KMF_FORMAT_PKCS12); 6026051Swyllys if (strcasecmp(formstr, "raw") == 0) 6035051Swyllys return (KMF_FORMAT_RAWKEY); 6043089Swyllys 6053089Swyllys return (KMF_FORMAT_UNDEF); 6063089Swyllys } 6073089Swyllys 6083089Swyllys KMF_RETURN 6096051Swyllys select_token(void *kmfhandle, char *token, int readonly) 6103089Swyllys { 6115051Swyllys KMF_ATTRIBUTE attlist[10]; 6125051Swyllys int i = 0; 6135051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 6143089Swyllys KMF_RETURN rv = KMF_OK; 6153089Swyllys 6163089Swyllys if (token == NULL) 6173089Swyllys return (KMF_ERR_BAD_PARAMETER); 6183089Swyllys 6195051Swyllys kmf_set_attr_at_index(attlist, i, 6205051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 6215051Swyllys sizeof (kstype)); 6225051Swyllys i++; 6233089Swyllys 6245051Swyllys if (token) { 6255051Swyllys kmf_set_attr_at_index(attlist, i, 6265051Swyllys KMF_TOKEN_LABEL_ATTR, token, 6275051Swyllys strlen(token)); 6285051Swyllys i++; 6295051Swyllys } 6305051Swyllys 6315051Swyllys kmf_set_attr_at_index(attlist, i, 6325051Swyllys KMF_READONLY_ATTR, &readonly, 6335051Swyllys sizeof (readonly)); 6345051Swyllys i++; 6355051Swyllys 6365051Swyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 6373089Swyllys if (rv == KMF_ERR_TOKEN_SELECTED) 6383089Swyllys rv = KMF_OK; 6393089Swyllys return (rv); 6403089Swyllys } 6413089Swyllys 6423089Swyllys KMF_RETURN 6433089Swyllys configure_nss(void *kmfhandle, char *dir, char *prefix) 6443089Swyllys { 6455051Swyllys KMF_ATTRIBUTE attlist[10]; 6465051Swyllys int i = 0; 6475051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 6483089Swyllys KMF_RETURN rv = KMF_OK; 6495051Swyllys 6505051Swyllys kmf_set_attr_at_index(attlist, i, 6515051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 6525051Swyllys sizeof (kstype)); 6535051Swyllys i++; 6543089Swyllys 6555051Swyllys if (dir) { 6565051Swyllys kmf_set_attr_at_index(attlist, i, 6575051Swyllys KMF_DIRPATH_ATTR, dir, 6585051Swyllys strlen(dir)); 6595051Swyllys i++; 6605051Swyllys } 6613089Swyllys 6625051Swyllys if (prefix) { 6635051Swyllys kmf_set_attr_at_index(attlist, i, 6645051Swyllys KMF_CERTPREFIX_ATTR, prefix, 6655051Swyllys strlen(prefix)); 6665051Swyllys i++; 6675051Swyllys 6685051Swyllys kmf_set_attr_at_index(attlist, i, 6695051Swyllys KMF_KEYPREFIX_ATTR, prefix, 6705051Swyllys strlen(prefix)); 6715051Swyllys i++; 6725051Swyllys } 6735051Swyllys 6745051Swyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 6753089Swyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 6763089Swyllys rv = KMF_OK; 6773089Swyllys 6783089Swyllys return (rv); 6793089Swyllys } 6803089Swyllys 6813089Swyllys KMF_RETURN 6823089Swyllys get_pk12_password(KMF_CREDENTIAL *cred) 6833089Swyllys { 6843089Swyllys KMF_RETURN rv = KMF_OK; 6853089Swyllys char prompt[1024]; 6863089Swyllys 6873089Swyllys /* 6883089Swyllys * Get the password to use for the PK12 encryption. 6893089Swyllys */ 6903089Swyllys (void) strlcpy(prompt, 6915051Swyllys gettext("Enter password to use for " 6925051Swyllys "accessing the PKCS12 file: "), sizeof (prompt)); 6933089Swyllys 6943089Swyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 6955051Swyllys (ulong_t *)&cred->credlen) != CKR_OK) { 6963089Swyllys cred->cred = NULL; 6973089Swyllys cred->credlen = 0; 6983089Swyllys } 6993089Swyllys 7003089Swyllys return (rv); 7013089Swyllys } 7023089Swyllys 7035221Swyllys #define FILENAME_PROMPT gettext("Filename:") 7045221Swyllys #define FILENAME_MINLEN 1 7055221Swyllys #define FILENAME_MAXLEN MAXPATHLEN 7063089Swyllys 7075221Swyllys #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:") 7085221Swyllys #define STATE_PROMPT gettext("State or Province Name (full name) " \ 7095221Swyllys "[Some-State]:") 7105221Swyllys #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:") 7115221Swyllys #define ORG_PROMPT gettext("Organization Name (eg, company) []:") 7125221Swyllys #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:") 7135221Swyllys #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:") 7145221Swyllys #define EMAIL_PROMPT gettext("Email Address []:") 7155221Swyllys 7165221Swyllys #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \ 7175221Swyllys "0x01020304):") 7185221Swyllys #define SERNO_MINLEN 3 7195221Swyllys #define SERNO_MAXLEN 42 7205221Swyllys 7215221Swyllys #define LABEL_PROMPT gettext("Enter a label for the certificate:") 7225221Swyllys #define LABEL_MINLEN 1 7235221Swyllys #define LABEL_MAXLEN 1024 7243089Swyllys 7253089Swyllys #define COUNTRY_DEFAULT "US" 7265221Swyllys #define STATE_DEFAULT NULL 7275221Swyllys #define INVALID_INPUT gettext("Invalid input; please re-enter ...") 7283089Swyllys 7293089Swyllys #define SUBNAMESIZ 1024 7303089Swyllys #define RDN_MIN 1 7313089Swyllys #define RDN_MAX 64 7323089Swyllys #define COUNTRYNAME_MIN 2 7333089Swyllys #define COUNTRYNAME_MAX 2 7343089Swyllys 7353089Swyllys static char * 7363089Swyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len) 7373089Swyllys { 7383089Swyllys char buf[1024]; 7393089Swyllys char *response = NULL; 7403089Swyllys char *ret = NULL; 7413089Swyllys int len; 7423089Swyllys 7433089Swyllys for (;;) { 7443089Swyllys (void) printf("\t%s", prompt); 7453089Swyllys (void) fflush(stdout); 7463089Swyllys 7473089Swyllys response = fgets(buf, sizeof (buf), stdin); 7483089Swyllys if (response == NULL) { 7493089Swyllys if (default_str != NULL) { 7503089Swyllys ret = strdup(default_str); 7513089Swyllys } 7523089Swyllys break; 7533089Swyllys } 7543089Swyllys 7553089Swyllys /* Skip any leading white space. */ 7563089Swyllys while (isspace(*response)) 7573089Swyllys response++; 7583089Swyllys if (*response == '\0') { 7593089Swyllys if (default_str != NULL) { 7603089Swyllys ret = strdup(default_str); 7613089Swyllys } 7623089Swyllys break; 7633089Swyllys } 7643089Swyllys 7653089Swyllys len = strlen(response); 7663089Swyllys response[len-1] = '\0'; /* get rid of "LF" */ 7673089Swyllys len--; 7683089Swyllys if (len >= min_len && len <= max_len) { 7693089Swyllys ret = strdup(response); 7703089Swyllys break; 7713089Swyllys } 7723089Swyllys 7733089Swyllys (void) printf("%s\n", INVALID_INPUT); 7743089Swyllys 7753089Swyllys } 7763089Swyllys 7773089Swyllys return (ret); 7783089Swyllys } 7793089Swyllys 7803089Swyllys int 7815221Swyllys get_filename(char *txt, char **result) 7825221Swyllys { 7835221Swyllys char prompt[1024]; 7845221Swyllys char *fname = NULL; 7855221Swyllys 7865221Swyllys (void) snprintf(prompt, sizeof (prompt), 7875221Swyllys gettext("Enter filename for the %s: "), 7885221Swyllys txt); 7895221Swyllys fname = get_input_string(prompt, NULL, 7905221Swyllys FILENAME_MINLEN, FILENAME_MAXLEN); 7915221Swyllys *result = fname; 7925221Swyllys return (0); 7935221Swyllys } 7945221Swyllys 7955221Swyllys int 7965221Swyllys get_certlabel(char **result) 7975221Swyllys { 7985221Swyllys char *label = NULL; 7995221Swyllys 8005221Swyllys label = get_input_string(LABEL_PROMPT, NULL, 8015221Swyllys LABEL_MINLEN, LABEL_MAXLEN); 8025221Swyllys *result = label; 8035221Swyllys return (0); 8045221Swyllys } 8055221Swyllys 8065221Swyllys int 8075221Swyllys get_serial(char **result) 8085221Swyllys { 8095221Swyllys char *serial = NULL; 8105221Swyllys 8115221Swyllys serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN, 8125221Swyllys SERNO_MAXLEN); 8135221Swyllys 8145221Swyllys *result = serial; 8155221Swyllys return (0); 8165221Swyllys } 8175221Swyllys 8185221Swyllys int 8193089Swyllys get_subname(char **result) 8203089Swyllys { 8213089Swyllys char *country = NULL; 8223089Swyllys char *state = NULL; 8233089Swyllys char *locality = NULL; 8243089Swyllys char *org = NULL; 8253089Swyllys char *unit = NULL; 8263089Swyllys char *name = NULL; 8273089Swyllys char *email = NULL; 8283089Swyllys char *subname = NULL; 8293089Swyllys 8303089Swyllys (void) printf("Entering following fields for subject (a DN) ...\n"); 8313089Swyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 8323089Swyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX); 8333089Swyllys if (country == NULL) 8343089Swyllys return (-1); 8353089Swyllys 8363089Swyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 8373089Swyllys RDN_MIN, RDN_MAX); 8383089Swyllys 8393089Swyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 8403089Swyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 8413089Swyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 8423089Swyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 8433089Swyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 8443089Swyllys 8453089Swyllys /* Now create a subject name from the input strings */ 8463089Swyllys if ((subname = malloc(SUBNAMESIZ)) == NULL) 8473089Swyllys goto out; 8483089Swyllys 8493089Swyllys (void) memset(subname, 0, SUBNAMESIZ); 8503089Swyllys (void) strlcpy(subname, "C=", SUBNAMESIZ); 8513089Swyllys (void) strlcat(subname, country, SUBNAMESIZ); 8525221Swyllys if (state != NULL) { 8535221Swyllys (void) strlcat(subname, ", ST=", SUBNAMESIZ); 8545221Swyllys (void) strlcat(subname, state, SUBNAMESIZ); 8555221Swyllys } 8563089Swyllys 8575221Swyllys if (locality != NULL) { 8585221Swyllys (void) strlcat(subname, ", L=", SUBNAMESIZ); 8593089Swyllys (void) strlcat(subname, locality, SUBNAMESIZ); 8603089Swyllys } 8613089Swyllys 8625221Swyllys if (org != NULL) { 8635221Swyllys (void) strlcat(subname, ", O=", SUBNAMESIZ); 8643089Swyllys (void) strlcat(subname, org, SUBNAMESIZ); 8653089Swyllys } 8663089Swyllys 8675221Swyllys if (unit != NULL) { 8685221Swyllys (void) strlcat(subname, ", OU=", SUBNAMESIZ); 8693089Swyllys (void) strlcat(subname, unit, SUBNAMESIZ); 8703089Swyllys } 8713089Swyllys 8725221Swyllys if (name != NULL) { 8735221Swyllys (void) strlcat(subname, ", CN=", SUBNAMESIZ); 8743089Swyllys (void) strlcat(subname, name, SUBNAMESIZ); 8753089Swyllys } 8763089Swyllys 8775221Swyllys if (email != NULL) { 8785221Swyllys (void) strlcat(subname, ", E=", SUBNAMESIZ); 8793089Swyllys (void) strlcat(subname, email, SUBNAMESIZ); 8803089Swyllys } 8813089Swyllys 8823089Swyllys out: 8833089Swyllys if (country) 8843089Swyllys free(country); 8853089Swyllys if (state) 8863089Swyllys free(state); 8873089Swyllys if (locality) 8883089Swyllys free(locality); 8893089Swyllys if (org) 8903089Swyllys free(org); 8913089Swyllys if (unit) 8923089Swyllys free(unit); 8933089Swyllys if (name) 8943089Swyllys free(name); 8953089Swyllys if (email) 8963089Swyllys free(email); 8973089Swyllys 8983089Swyllys if (subname == NULL) 8993089Swyllys return (-1); 9003089Swyllys else { 9013089Swyllys *result = subname; 9023089Swyllys return (0); 9033089Swyllys } 9043089Swyllys } 9053089Swyllys 9063089Swyllys /* 9073089Swyllys * Parse a string of KeyUsage values and convert 9083089Swyllys * them to the correct KU Bits. 9093089Swyllys * The field may be marked "critical" by prepending 9103089Swyllys * "critical:" to the list. 9113089Swyllys * EX: critical:digitialSignature,keyEncipherment 9123089Swyllys */ 9133089Swyllys KMF_RETURN 9143089Swyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 9153089Swyllys { 9163089Swyllys KMF_RETURN ret = KMF_OK; 9173089Swyllys uint16_t kuval; 9183089Swyllys char *k; 9193089Swyllys 9203089Swyllys *kubits = 0; 9216051Swyllys if (kustr == NULL || strlen(kustr) == 0) 9223089Swyllys return (KMF_ERR_BAD_PARAMETER); 9233089Swyllys 9243089Swyllys /* Check to see if this is critical */ 9256051Swyllys if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) { 9263089Swyllys *critical = TRUE; 9273089Swyllys kustr += strlen("critical:"); 9283089Swyllys } else { 9293089Swyllys *critical = FALSE; 9303089Swyllys } 9313089Swyllys 9323089Swyllys k = strtok(kustr, ","); 9333089Swyllys while (k != NULL) { 9345051Swyllys kuval = kmf_string_to_ku(k); 9353089Swyllys if (kuval == 0) { 9363089Swyllys *kubits = 0; 9373089Swyllys return (KMF_ERR_BAD_PARAMETER); 9383089Swyllys } 9393089Swyllys *kubits |= kuval; 9403089Swyllys k = strtok(NULL, ","); 9413089Swyllys } 9423089Swyllys 9433089Swyllys return (ret); 9443089Swyllys } 9453089Swyllys 9463089Swyllys /* 9473089Swyllys * Verify the alternate subject label is real or invalid. 9483089Swyllys * 9493089Swyllys * The field may be marked "critical" by prepending 9503089Swyllys * "critical:" to the list. 9513089Swyllys * EX: "critical:IP=1.2.3.4" 9523089Swyllys */ 9533089Swyllys KMF_RETURN 9543089Swyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 9553089Swyllys { 9563089Swyllys char *p; 9573089Swyllys KMF_RETURN rv = KMF_OK; 9583089Swyllys 9593089Swyllys /* Check to see if this is critical */ 9606051Swyllys if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) { 9613089Swyllys *critical = TRUE; 9623089Swyllys arg += strlen("critical:"); 9633089Swyllys } else { 9643089Swyllys *critical = FALSE; 9653089Swyllys } 9663089Swyllys 9673089Swyllys /* Make sure there is an "=" sign */ 9683089Swyllys p = strchr(arg, '='); 9693089Swyllys if (p == NULL) 9703089Swyllys return (KMF_ERR_BAD_PARAMETER); 9713089Swyllys 9723089Swyllys p[0] = '\0'; 9733089Swyllys 9743089Swyllys if (strcmp(arg, "IP") == 0) 9753089Swyllys *type = GENNAME_IPADDRESS; 9763089Swyllys else if (strcmp(arg, "DNS") == 0) 9773089Swyllys *type = GENNAME_DNSNAME; 9783089Swyllys else if (strcmp(arg, "EMAIL") == 0) 9793089Swyllys *type = GENNAME_RFC822NAME; 9803089Swyllys else if (strcmp(arg, "URI") == 0) 9813089Swyllys *type = GENNAME_URI; 9823089Swyllys else if (strcmp(arg, "DN") == 0) 9833089Swyllys *type = GENNAME_DIRECTORYNAME; 9843089Swyllys else if (strcmp(arg, "RID") == 0) 9853089Swyllys *type = GENNAME_REGISTEREDID; 9866051Swyllys else if (strcmp(arg, "KRB") == 0) 9876051Swyllys *type = GENNAME_KRB5PRINC; 9886051Swyllys else if (strcmp(arg, "UPN") == 0) 9896051Swyllys *type = GENNAME_SCLOGON_UPN; 9903089Swyllys else 9913089Swyllys rv = KMF_ERR_BAD_PARAMETER; 9923089Swyllys 9933089Swyllys p[0] = '='; 9943089Swyllys 9953089Swyllys return (rv); 9963089Swyllys } 9973089Swyllys 9983089Swyllys int 9993089Swyllys get_token_password(KMF_KEYSTORE_TYPE kstype, 10003089Swyllys char *token_spec, KMF_CREDENTIAL *cred) 10013089Swyllys { 10023089Swyllys char prompt[1024]; 10038132SWyllys.Ingersoll@Sun.COM char temptoken[32]; 10043089Swyllys char *p = NULL; 10058132SWyllys.Ingersoll@Sun.COM char *t = NULL; 1006*9126SWyllys.Ingersoll@Sun.COM int len; 10073089Swyllys 1008*9126SWyllys.Ingersoll@Sun.COM (void) memset(temptoken, 0, sizeof (temptoken)); 10093089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) { 10103089Swyllys p = strchr(token_spec, ':'); 10113089Swyllys if (p != NULL) 10128132SWyllys.Ingersoll@Sun.COM *p = 0; 10133089Swyllys } 1014*9126SWyllys.Ingersoll@Sun.COM len = strlen(token_spec); 1015*9126SWyllys.Ingersoll@Sun.COM if (len > sizeof (temptoken)) 1016*9126SWyllys.Ingersoll@Sun.COM len = sizeof (temptoken); 1017*9126SWyllys.Ingersoll@Sun.COM 1018*9126SWyllys.Ingersoll@Sun.COM (void) strncpy(temptoken, token_spec, len); 10198132SWyllys.Ingersoll@Sun.COM 10208132SWyllys.Ingersoll@Sun.COM /* 10218132SWyllys.Ingersoll@Sun.COM * Strip trailing whitespace 10228132SWyllys.Ingersoll@Sun.COM */ 1023*9126SWyllys.Ingersoll@Sun.COM t = temptoken + (len - 1); 10248132SWyllys.Ingersoll@Sun.COM while (isspace(*t) && t >= temptoken) { 10258132SWyllys.Ingersoll@Sun.COM *t = 0x00; 10268132SWyllys.Ingersoll@Sun.COM t--; 10278132SWyllys.Ingersoll@Sun.COM } 10288132SWyllys.Ingersoll@Sun.COM 10293089Swyllys /* 10303089Swyllys * Login to the token first. 10313089Swyllys */ 10323089Swyllys (void) snprintf(prompt, sizeof (prompt), 10338132SWyllys.Ingersoll@Sun.COM gettext(DEFAULT_TOKEN_PROMPT), temptoken); 10343089Swyllys 10353089Swyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 10365051Swyllys (ulong_t *)&cred->credlen) != CKR_OK) { 10373089Swyllys cred->cred = NULL; 10383089Swyllys cred->credlen = 0; 10393089Swyllys } 10403089Swyllys 10413089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 10423089Swyllys *p = ':'; 10433089Swyllys return (KMF_OK); 10443089Swyllys } 10453089Swyllys 10463089Swyllys KMF_RETURN 10473089Swyllys verify_file(char *filename) 10483089Swyllys { 10493089Swyllys KMF_RETURN ret = KMF_OK; 10503089Swyllys int fd; 10513089Swyllys 10523089Swyllys /* 10533089Swyllys * Attempt to open with the EXCL flag so that if 10543089Swyllys * it already exists, the open will fail. It will 10553089Swyllys * also fail if the file cannot be created due to 10563089Swyllys * permissions on the parent directory, or if the 10573089Swyllys * parent directory itself does not exist. 10583089Swyllys */ 10593089Swyllys fd = open(filename, O_CREAT | O_EXCL, 0600); 10603089Swyllys if (fd == -1) 10613089Swyllys return (KMF_ERR_OPEN_FILE); 10623089Swyllys 10633089Swyllys /* If we were able to create it, delete it. */ 10643089Swyllys (void) close(fd); 10653089Swyllys (void) unlink(filename); 10663089Swyllys 10673089Swyllys return (ret); 10683089Swyllys } 10693089Swyllys 10703089Swyllys void 10713089Swyllys display_error(void *handle, KMF_RETURN errcode, char *prefix) 10723089Swyllys { 10733089Swyllys KMF_RETURN rv1, rv2; 10743089Swyllys char *plugin_errmsg = NULL; 10753089Swyllys char *kmf_errmsg = NULL; 10763089Swyllys 10775051Swyllys rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg); 10785051Swyllys rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg); 10793089Swyllys 10803089Swyllys cryptoerror(LOG_STDERR, "%s:", prefix); 10813089Swyllys if (rv1 == KMF_OK && plugin_errmsg) { 10825051Swyllys cryptoerror(LOG_STDERR, gettext("keystore error: %s"), 10835051Swyllys plugin_errmsg); 10845051Swyllys kmf_free_str(plugin_errmsg); 10853089Swyllys } 10863089Swyllys 10873089Swyllys if (rv2 == KMF_OK && kmf_errmsg) { 10885051Swyllys cryptoerror(LOG_STDERR, gettext("libkmf error: %s"), 10895051Swyllys kmf_errmsg); 10905051Swyllys kmf_free_str(kmf_errmsg); 10913089Swyllys } 10923089Swyllys 10933089Swyllys if (rv1 != KMF_OK && rv2 != KMF_OK) 10943089Swyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 10953089Swyllys 10963089Swyllys } 10976051Swyllys 10986051Swyllys static KMF_RETURN 10996051Swyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid) 11006051Swyllys { 11016051Swyllys if (newoid != NULL && ekus != NULL) { 11026051Swyllys ekus->eku_count++; 11036051Swyllys 11046051Swyllys ekus->critlist = realloc(ekus->critlist, 11056051Swyllys ekus->eku_count * sizeof (int)); 11066051Swyllys if (ekus->critlist != NULL) 11076051Swyllys ekus->critlist[ekus->eku_count-1] = critical; 11086051Swyllys else 11096051Swyllys return (KMF_ERR_MEMORY); 11106051Swyllys 11116051Swyllys ekus->ekulist = realloc( 11126051Swyllys ekus->ekulist, ekus->eku_count * sizeof (KMF_OID)); 11136051Swyllys if (ekus->ekulist != NULL) 11146051Swyllys ekus->ekulist[ekus->eku_count-1] = *newoid; 11156051Swyllys else 11166051Swyllys return (KMF_ERR_MEMORY); 11176051Swyllys } 11186051Swyllys return (KMF_OK); 11196051Swyllys } 11206051Swyllys 11216051Swyllys void 11226051Swyllys free_eku_list(EKU_LIST *ekus) 11236051Swyllys { 11246051Swyllys if (ekus != NULL && ekus->eku_count > 0) { 11256051Swyllys int i; 11266051Swyllys for (i = 0; i < ekus->eku_count; i++) { 11276051Swyllys kmf_free_data(&ekus->ekulist[i]); 11286051Swyllys } 11296051Swyllys free(ekus->ekulist); 11306051Swyllys free(ekus->critlist); 11316051Swyllys } 11326051Swyllys } 11336051Swyllys 11346051Swyllys static KMF_RETURN 11356051Swyllys parse_ekus(char *ekustr, EKU_LIST *ekus) 11366051Swyllys { 11376051Swyllys KMF_RETURN rv = KMF_OK; 11386051Swyllys KMF_OID *newoid; 11396051Swyllys int critical; 11406051Swyllys 11416051Swyllys if (strncasecmp(ekustr, "critical:", 11426051Swyllys strlen("critical:")) == 0) { 11436051Swyllys critical = TRUE; 11446051Swyllys ekustr += strlen("critical:"); 11456051Swyllys } else { 11466051Swyllys critical = FALSE; 11476051Swyllys } 11486051Swyllys newoid = kmf_ekuname_to_oid(ekustr); 11496051Swyllys if (newoid != NULL) { 11506051Swyllys rv = addToEKUList(ekus, critical, newoid); 11516051Swyllys free(newoid); 11526051Swyllys } else { 11536051Swyllys rv = PK_ERR_USAGE; 11546051Swyllys } 11556051Swyllys 11566051Swyllys return (rv); 11576051Swyllys } 11586051Swyllys 11596051Swyllys KMF_RETURN 11606051Swyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist) 11616051Swyllys { 11626051Swyllys KMF_RETURN rv = KMF_OK; 11636051Swyllys char *p; 11646051Swyllys EKU_LIST *ekus = NULL; 11656051Swyllys 11666051Swyllys if (ekuliststr == NULL || strlen(ekuliststr) == 0) 11676051Swyllys return (0); 11686051Swyllys 11696051Swyllys /* 11706051Swyllys * The list should be comma separated list of EKU Names. 11716051Swyllys */ 11726051Swyllys p = strtok(ekuliststr, ","); 11736051Swyllys 11746051Swyllys /* If no tokens found, then maybe it's just a single EKU value */ 11756051Swyllys if (p == NULL) { 11766051Swyllys rv = parse_ekus(ekuliststr, ekus); 11776051Swyllys } 11786051Swyllys 11796051Swyllys while (p != NULL) { 11806051Swyllys rv = parse_ekus(p, ekus); 11816051Swyllys 11826051Swyllys if (rv != KMF_OK) 11836051Swyllys break; 11846051Swyllys p = strtok(NULL, ","); 11856051Swyllys } 11866051Swyllys 11876051Swyllys if (rv != KMF_OK) 11886051Swyllys free_eku_list(ekus); 11896051Swyllys else 11906051Swyllys *ekulist = ekus; 11916051Swyllys 11926051Swyllys return (rv); 11936051Swyllys } 11946354Swyllys 11956354Swyllys KMF_RETURN 11966354Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth) 11976354Swyllys { 11986354Swyllys CK_TOKEN_INFO info; 11996354Swyllys CK_SLOT_ID slot; 12006354Swyllys CK_RV ckrv; 12016354Swyllys KMF_RETURN rv; 12026354Swyllys 12036354Swyllys *auth = 0; 12046354Swyllys rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot); 12056354Swyllys if (rv != KMF_OK) 12066354Swyllys return (rv); 12076354Swyllys 12086354Swyllys ckrv = C_GetTokenInfo(slot, &info); 12096354Swyllys if (ckrv != KMF_OK) 12106354Swyllys return (KMF_ERR_INTERNAL); 12116354Swyllys 12126354Swyllys *auth = (info.flags & CKF_LOGIN_REQUIRED); 12136354Swyllys 12146354Swyllys return (KMF_OK); 12156354Swyllys } 1216