1*5252Sdinak /* 2*5252Sdinak * CDDL HEADER START 3*5252Sdinak * 4*5252Sdinak * The contents of this file are subject to the terms of the 5*5252Sdinak * Common Development and Distribution License (the "License"). 6*5252Sdinak * You may not use this file except in compliance with the License. 7*5252Sdinak * 8*5252Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5252Sdinak * or http://www.opensolaris.org/os/licensing. 10*5252Sdinak * See the License for the specific language governing permissions 11*5252Sdinak * and limitations under the License. 12*5252Sdinak * 13*5252Sdinak * When distributing Covered Code, include this CDDL HEADER in each 14*5252Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5252Sdinak * If applicable, add the following below this CDDL HEADER, with the 16*5252Sdinak * fields enclosed by brackets "[]" replaced with your own identifying 17*5252Sdinak * information: Portions Copyright [yyyy] [name of copyright owner] 18*5252Sdinak * 19*5252Sdinak * CDDL HEADER END 20*5252Sdinak */ 21*5252Sdinak /* 22*5252Sdinak * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5252Sdinak * Use is subject to license terms. 24*5252Sdinak */ 25*5252Sdinak 26*5252Sdinak #pragma ident "%Z%%M% %I% %E% SMI" 27*5252Sdinak 28*5252Sdinak #include <stdio.h> 29*5252Sdinak #include <string.h> 30*5252Sdinak #include <fcntl.h> 31*5252Sdinak #include <locale.h> 32*5252Sdinak #include <cryptoutil.h> 33*5252Sdinak 34*5252Sdinak #define MAX_PASS_TRIES 5 /* maximum tries to get passphrase */ 35*5252Sdinak 36*5252Sdinak #define DEFAULT_TOKEN_PROMPT gettext("Enter PIN for %s: ") 37*5252Sdinak #define DEFAULT_TOKEN_REPROMPT gettext("Re-enter PIN for %s: ") 38*5252Sdinak #define DEFAULT_TOKEN_MINSIZE gettext("PIN must be at least %d characters.\n") 39*5252Sdinak 40*5252Sdinak #define DEFAULT_USER_PROMPT gettext("Enter key: ") 41*5252Sdinak #define DEFAULT_USER_REPROMPT gettext("Re-enter key: ") 42*5252Sdinak #define DEFAULT_USER_MINSIZE gettext("Key must be at least %d characters.\n") 43*5252Sdinak 44*5252Sdinak #define DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL 45*5252Sdinak 46*5252Sdinak /* 47*5252Sdinak * Default token name 48*5252Sdinak */ 49*5252Sdinak char * 50*5252Sdinak pkcs11_default_token(void) 51*5252Sdinak { 52*5252Sdinak return (DEFAULT_PK11TOKEN); 53*5252Sdinak } 54*5252Sdinak 55*5252Sdinak /* 56*5252Sdinak * Prompt user for a passphrase or the PIN for a token. 57*5252Sdinak * 58*5252Sdinak * An optional minimum length can be enforced. Caller can optionally also 59*5252Sdinak * reprompt for the passphrase/PIN to confirm it was entered correctly. 60*5252Sdinak * The caller must free the buffer containing the passphrase/PIN with free(). 61*5252Sdinak * 0 returned for success, -1 for failure with the first passphrase/PIN, 62*5252Sdinak * -2 for failure with the optional second passphrase/PIN used to confirm. 63*5252Sdinak */ 64*5252Sdinak int 65*5252Sdinak pkcs11_get_pass(char *token_name, char **pdata, size_t *psize, size_t min_psize, 66*5252Sdinak boolean_t with_confirmation) 67*5252Sdinak { 68*5252Sdinak char prompt[1024]; 69*5252Sdinak char *tmpbuf = NULL; 70*5252Sdinak char *databuf = NULL; 71*5252Sdinak int tries; 72*5252Sdinak 73*5252Sdinak if (token_name != NULL) 74*5252Sdinak (void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_PROMPT, 75*5252Sdinak token_name); 76*5252Sdinak else 77*5252Sdinak (void) snprintf(prompt, sizeof (prompt), DEFAULT_USER_PROMPT); 78*5252Sdinak 79*5252Sdinak for (tries = MAX_PASS_TRIES; tries > 0; tries--) { 80*5252Sdinak tmpbuf = getpassphrase(prompt); 81*5252Sdinak if (tmpbuf == NULL) 82*5252Sdinak return (-1); 83*5252Sdinak 84*5252Sdinak if (strnlen(tmpbuf, min_psize) >= min_psize) 85*5252Sdinak break; 86*5252Sdinak 87*5252Sdinak if (token_name != NULL) 88*5252Sdinak (void) printf(DEFAULT_TOKEN_MINSIZE, min_psize); 89*5252Sdinak else 90*5252Sdinak (void) printf(DEFAULT_USER_MINSIZE, min_psize); 91*5252Sdinak } 92*5252Sdinak if (tries == 0) { 93*5252Sdinak (void) printf(gettext("Exceeded number of attempts.\n")); 94*5252Sdinak return (-1); 95*5252Sdinak } 96*5252Sdinak 97*5252Sdinak databuf = strdup(tmpbuf); 98*5252Sdinak (void) memset(tmpbuf, 0, strlen(tmpbuf)); /* clean up */ 99*5252Sdinak if (databuf == NULL) 100*5252Sdinak return (-1); 101*5252Sdinak 102*5252Sdinak if (with_confirmation) { 103*5252Sdinak if (token_name != NULL) 104*5252Sdinak (void) snprintf(prompt, sizeof (prompt), 105*5252Sdinak DEFAULT_TOKEN_REPROMPT, token_name); 106*5252Sdinak else 107*5252Sdinak (void) snprintf(prompt, sizeof (prompt), 108*5252Sdinak DEFAULT_USER_REPROMPT); 109*5252Sdinak tmpbuf = getpassphrase(prompt); 110*5252Sdinak if (tmpbuf == NULL) { 111*5252Sdinak /* clean up */ 112*5252Sdinak (void) memset(databuf, 0, strlen(databuf)); 113*5252Sdinak free(databuf); 114*5252Sdinak return (-2); 115*5252Sdinak } 116*5252Sdinak 117*5252Sdinak if (strcmp(databuf, tmpbuf) != 0) { 118*5252Sdinak /* clean up */ 119*5252Sdinak (void) memset(tmpbuf, 0, strlen(tmpbuf)); 120*5252Sdinak (void) memset(databuf, 0, strlen(databuf)); 121*5252Sdinak free(databuf); 122*5252Sdinak return (-2); 123*5252Sdinak } 124*5252Sdinak } 125*5252Sdinak 126*5252Sdinak *pdata = databuf; 127*5252Sdinak *psize = strlen(databuf); 128*5252Sdinak 129*5252Sdinak return (0); 130*5252Sdinak } 131