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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <string.h> 28 #include <fcntl.h> 29 #include <locale.h> 30 #include <cryptoutil.h> 31 32 #define MAX_PASS_TRIES 5 /* maximum tries to get passphrase */ 33 34 #define DEFAULT_TOKEN_PROMPT gettext("Enter PIN for %s: ") 35 #define DEFAULT_TOKEN_REPROMPT gettext("Re-enter PIN for %s: ") 36 #define DEFAULT_TOKEN_MINSIZE gettext("PIN must be at least %d characters.\n") 37 38 #define DEFAULT_USER_PROMPT gettext("Enter passphrase: ") 39 #define DEFAULT_USER_REPROMPT gettext("Re-enter passphrase: ") 40 #define DEFAULT_USER_MINSIZE \ 41 gettext("Passphrase must be at least %d characters.\n") 42 43 #define DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL 44 45 /* 46 * Default token name 47 */ 48 char * 49 pkcs11_default_token(void) 50 { 51 return (DEFAULT_PK11TOKEN); 52 } 53 54 /* 55 * Prompt user for a passphrase or the PIN for a token. 56 * 57 * An optional minimum length can be enforced. Caller can optionally also 58 * reprompt for the passphrase/PIN to confirm it was entered correctly. 59 * The caller must free the buffer containing the passphrase/PIN with free(). 60 * 0 returned for success, -1 for failure with the first passphrase/PIN, 61 * -2 for failure with the optional second passphrase/PIN used to confirm. 62 */ 63 int 64 pkcs11_get_pass(char *token_name, char **pdata, size_t *psize, size_t min_psize, 65 boolean_t with_confirmation) 66 { 67 char prompt[1024]; 68 char *tmpbuf = NULL; 69 char *databuf = NULL; 70 int tries; 71 72 if (token_name != NULL) 73 (void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_PROMPT, 74 token_name); 75 else 76 (void) snprintf(prompt, sizeof (prompt), DEFAULT_USER_PROMPT); 77 78 for (tries = MAX_PASS_TRIES; tries > 0; tries--) { 79 tmpbuf = getpassphrase(prompt); 80 if (tmpbuf == NULL) 81 return (-1); 82 83 if (strnlen(tmpbuf, min_psize) >= min_psize) 84 break; 85 86 if (token_name != NULL) 87 (void) printf(DEFAULT_TOKEN_MINSIZE, min_psize); 88 else 89 (void) printf(DEFAULT_USER_MINSIZE, min_psize); 90 } 91 if (tries == 0) { 92 (void) printf(gettext("Exceeded number of attempts.\n")); 93 return (-1); 94 } 95 96 databuf = strdup(tmpbuf); 97 (void) memset(tmpbuf, 0, strlen(tmpbuf)); /* clean up */ 98 if (databuf == NULL) 99 return (-1); 100 101 if (with_confirmation) { 102 if (token_name != NULL) 103 (void) snprintf(prompt, sizeof (prompt), 104 DEFAULT_TOKEN_REPROMPT, token_name); 105 else 106 (void) snprintf(prompt, sizeof (prompt), 107 DEFAULT_USER_REPROMPT); 108 tmpbuf = getpassphrase(prompt); 109 if (tmpbuf == NULL) { 110 /* clean up */ 111 (void) memset(databuf, 0, strlen(databuf)); 112 free(databuf); 113 return (-2); 114 } 115 116 if (strcmp(databuf, tmpbuf) != 0) { 117 /* clean up */ 118 (void) memset(tmpbuf, 0, strlen(tmpbuf)); 119 (void) memset(databuf, 0, strlen(databuf)); 120 free(databuf); 121 return (-2); 122 } 123 } 124 125 *pdata = databuf; 126 *psize = strlen(databuf); 127 128 return (0); 129 } 130