11c9bd843Sdinak /*
21c9bd843Sdinak  * CDDL HEADER START
31c9bd843Sdinak  *
41c9bd843Sdinak  * The contents of this file are subject to the terms of the
51c9bd843Sdinak  * Common Development and Distribution License (the "License").
61c9bd843Sdinak  * You may not use this file except in compliance with the License.
71c9bd843Sdinak  *
81c9bd843Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91c9bd843Sdinak  * or http://www.opensolaris.org/os/licensing.
101c9bd843Sdinak  * See the License for the specific language governing permissions
111c9bd843Sdinak  * and limitations under the License.
121c9bd843Sdinak  *
131c9bd843Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
141c9bd843Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151c9bd843Sdinak  * If applicable, add the following below this CDDL HEADER, with the
161c9bd843Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
171c9bd843Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
181c9bd843Sdinak  *
191c9bd843Sdinak  * CDDL HEADER END
201c9bd843Sdinak  */
211c9bd843Sdinak /*
22*c545f712SDina K Nimeh  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
231c9bd843Sdinak  * Use is subject to license terms.
241c9bd843Sdinak  */
251c9bd843Sdinak 
261c9bd843Sdinak #include <stdio.h>
271c9bd843Sdinak #include <string.h>
281c9bd843Sdinak #include <fcntl.h>
291c9bd843Sdinak #include <locale.h>
301c9bd843Sdinak #include <cryptoutil.h>
311c9bd843Sdinak 
321c9bd843Sdinak #define	MAX_PASS_TRIES		5	/* maximum tries to get passphrase */
331c9bd843Sdinak 
341c9bd843Sdinak #define	DEFAULT_TOKEN_PROMPT	gettext("Enter PIN for %s: ")
351c9bd843Sdinak #define	DEFAULT_TOKEN_REPROMPT	gettext("Re-enter PIN for %s: ")
361c9bd843Sdinak #define	DEFAULT_TOKEN_MINSIZE	gettext("PIN must be at least %d characters.\n")
371c9bd843Sdinak 
38*c545f712SDina K Nimeh #define	DEFAULT_USER_PROMPT	gettext("Enter passphrase: ")
39*c545f712SDina K Nimeh #define	DEFAULT_USER_REPROMPT	gettext("Re-enter passphrase: ")
40*c545f712SDina K Nimeh #define	DEFAULT_USER_MINSIZE	\
41*c545f712SDina K Nimeh 			gettext("Passphrase must be at least %d characters.\n")
421c9bd843Sdinak 
431c9bd843Sdinak #define	DEFAULT_PK11TOKEN	SOFT_TOKEN_LABEL
441c9bd843Sdinak 
451c9bd843Sdinak /*
461c9bd843Sdinak  * Default token name
471c9bd843Sdinak  */
481c9bd843Sdinak char *
pkcs11_default_token(void)491c9bd843Sdinak pkcs11_default_token(void)
501c9bd843Sdinak {
511c9bd843Sdinak 	return (DEFAULT_PK11TOKEN);
521c9bd843Sdinak }
531c9bd843Sdinak 
541c9bd843Sdinak /*
551c9bd843Sdinak  * Prompt user for a passphrase or the PIN for a token.
561c9bd843Sdinak  *
571c9bd843Sdinak  * An optional minimum length can be enforced.  Caller can optionally also
581c9bd843Sdinak  * reprompt for the passphrase/PIN to confirm it was entered correctly.
591c9bd843Sdinak  * The caller must free the buffer containing the passphrase/PIN with free().
601c9bd843Sdinak  * 0 returned for success, -1 for failure with the first passphrase/PIN,
611c9bd843Sdinak  * -2 for failure with the optional second passphrase/PIN used to confirm.
621c9bd843Sdinak  */
631c9bd843Sdinak int
pkcs11_get_pass(char * token_name,char ** pdata,size_t * psize,size_t min_psize,boolean_t with_confirmation)641c9bd843Sdinak pkcs11_get_pass(char *token_name, char **pdata, size_t *psize, size_t min_psize,
651c9bd843Sdinak     boolean_t with_confirmation)
661c9bd843Sdinak {
671c9bd843Sdinak 	char	prompt[1024];
681c9bd843Sdinak 	char	*tmpbuf = NULL;
691c9bd843Sdinak 	char	*databuf = NULL;
701c9bd843Sdinak 	int	tries;
711c9bd843Sdinak 
721c9bd843Sdinak 	if (token_name != NULL)
731c9bd843Sdinak 		(void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_PROMPT,
741c9bd843Sdinak 		    token_name);
751c9bd843Sdinak 	else
761c9bd843Sdinak 		(void) snprintf(prompt, sizeof (prompt), DEFAULT_USER_PROMPT);
771c9bd843Sdinak 
781c9bd843Sdinak 	for (tries = MAX_PASS_TRIES; tries > 0; tries--) {
791c9bd843Sdinak 		tmpbuf = getpassphrase(prompt);
801c9bd843Sdinak 		if (tmpbuf == NULL)
811c9bd843Sdinak 			return (-1);
821c9bd843Sdinak 
831c9bd843Sdinak 		if (strnlen(tmpbuf, min_psize) >= min_psize)
841c9bd843Sdinak 			break;
851c9bd843Sdinak 
861c9bd843Sdinak 		if (token_name != NULL)
871c9bd843Sdinak 			(void) printf(DEFAULT_TOKEN_MINSIZE, min_psize);
881c9bd843Sdinak 		else
891c9bd843Sdinak 			(void) printf(DEFAULT_USER_MINSIZE, min_psize);
901c9bd843Sdinak 	}
911c9bd843Sdinak 	if (tries == 0) {
921c9bd843Sdinak 		(void) printf(gettext("Exceeded number of attempts.\n"));
931c9bd843Sdinak 		return (-1);
941c9bd843Sdinak 	}
951c9bd843Sdinak 
961c9bd843Sdinak 	databuf = strdup(tmpbuf);
971c9bd843Sdinak 	(void) memset(tmpbuf, 0, strlen(tmpbuf));	/* clean up */
981c9bd843Sdinak 	if (databuf == NULL)
991c9bd843Sdinak 		return (-1);
1001c9bd843Sdinak 
1011c9bd843Sdinak 	if (with_confirmation) {
1021c9bd843Sdinak 		if (token_name != NULL)
1031c9bd843Sdinak 			(void) snprintf(prompt, sizeof (prompt),
1041c9bd843Sdinak 			    DEFAULT_TOKEN_REPROMPT, token_name);
1051c9bd843Sdinak 		else
1061c9bd843Sdinak 			(void) snprintf(prompt, sizeof (prompt),
1071c9bd843Sdinak 			    DEFAULT_USER_REPROMPT);
1081c9bd843Sdinak 		tmpbuf = getpassphrase(prompt);
1091c9bd843Sdinak 		if (tmpbuf == NULL) {
1101c9bd843Sdinak 			/* clean up */
1111c9bd843Sdinak 			(void) memset(databuf, 0, strlen(databuf));
1121c9bd843Sdinak 			free(databuf);
1131c9bd843Sdinak 			return (-2);
1141c9bd843Sdinak 		}
1151c9bd843Sdinak 
1161c9bd843Sdinak 		if (strcmp(databuf, tmpbuf) != 0) {
1171c9bd843Sdinak 			/* clean up */
1181c9bd843Sdinak 			(void) memset(tmpbuf, 0, strlen(tmpbuf));
1191c9bd843Sdinak 			(void) memset(databuf, 0, strlen(databuf));
1201c9bd843Sdinak 			free(databuf);
1211c9bd843Sdinak 			return (-2);
1221c9bd843Sdinak 		}
1231c9bd843Sdinak 	}
1241c9bd843Sdinak 
1251c9bd843Sdinak 	*pdata = databuf;
1261c9bd843Sdinak 	*psize = strlen(databuf);
1271c9bd843Sdinak 
1281c9bd843Sdinak 	return (0);
1291c9bd843Sdinak }
130