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