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