15252Sdinak /*
25252Sdinak * CDDL HEADER START
35252Sdinak *
45252Sdinak * The contents of this file are subject to the terms of the
55252Sdinak * Common Development and Distribution License (the "License").
65252Sdinak * You may not use this file except in compliance with the License.
75252Sdinak *
85252Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95252Sdinak * or http://www.opensolaris.org/os/licensing.
105252Sdinak * See the License for the specific language governing permissions
115252Sdinak * and limitations under the License.
125252Sdinak *
135252Sdinak * When distributing Covered Code, include this CDDL HEADER in each
145252Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155252Sdinak * If applicable, add the following below this CDDL HEADER, with the
165252Sdinak * fields enclosed by brackets "[]" replaced with your own identifying
175252Sdinak * information: Portions Copyright [yyyy] [name of copyright owner]
185252Sdinak *
195252Sdinak * CDDL HEADER END
205252Sdinak */
215252Sdinak /*
22*8407SDina.Nimeh@Sun.Com * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
235252Sdinak * Use is subject to license terms.
245252Sdinak */
255252Sdinak
265252Sdinak #include <stdio.h>
275252Sdinak #include <string.h>
285252Sdinak #include <fcntl.h>
295252Sdinak #include <locale.h>
305252Sdinak #include <cryptoutil.h>
315252Sdinak
325252Sdinak #define MAX_PASS_TRIES 5 /* maximum tries to get passphrase */
335252Sdinak
345252Sdinak #define DEFAULT_TOKEN_PROMPT gettext("Enter PIN for %s: ")
355252Sdinak #define DEFAULT_TOKEN_REPROMPT gettext("Re-enter PIN for %s: ")
365252Sdinak #define DEFAULT_TOKEN_MINSIZE gettext("PIN must be at least %d characters.\n")
375252Sdinak
38*8407SDina.Nimeh@Sun.Com #define DEFAULT_USER_PROMPT gettext("Enter passphrase: ")
39*8407SDina.Nimeh@Sun.Com #define DEFAULT_USER_REPROMPT gettext("Re-enter passphrase: ")
40*8407SDina.Nimeh@Sun.Com #define DEFAULT_USER_MINSIZE \
41*8407SDina.Nimeh@Sun.Com gettext("Passphrase must be at least %d characters.\n")
425252Sdinak
435252Sdinak #define DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL
445252Sdinak
455252Sdinak /*
465252Sdinak * Default token name
475252Sdinak */
485252Sdinak char *
pkcs11_default_token(void)495252Sdinak pkcs11_default_token(void)
505252Sdinak {
515252Sdinak return (DEFAULT_PK11TOKEN);
525252Sdinak }
535252Sdinak
545252Sdinak /*
555252Sdinak * Prompt user for a passphrase or the PIN for a token.
565252Sdinak *
575252Sdinak * An optional minimum length can be enforced. Caller can optionally also
585252Sdinak * reprompt for the passphrase/PIN to confirm it was entered correctly.
595252Sdinak * The caller must free the buffer containing the passphrase/PIN with free().
605252Sdinak * 0 returned for success, -1 for failure with the first passphrase/PIN,
615252Sdinak * -2 for failure with the optional second passphrase/PIN used to confirm.
625252Sdinak */
635252Sdinak int
pkcs11_get_pass(char * token_name,char ** pdata,size_t * psize,size_t min_psize,boolean_t with_confirmation)645252Sdinak pkcs11_get_pass(char *token_name, char **pdata, size_t *psize, size_t min_psize,
655252Sdinak boolean_t with_confirmation)
665252Sdinak {
675252Sdinak char prompt[1024];
685252Sdinak char *tmpbuf = NULL;
695252Sdinak char *databuf = NULL;
705252Sdinak int tries;
715252Sdinak
725252Sdinak if (token_name != NULL)
735252Sdinak (void) snprintf(prompt, sizeof (prompt), DEFAULT_TOKEN_PROMPT,
745252Sdinak token_name);
755252Sdinak else
765252Sdinak (void) snprintf(prompt, sizeof (prompt), DEFAULT_USER_PROMPT);
775252Sdinak
785252Sdinak for (tries = MAX_PASS_TRIES; tries > 0; tries--) {
795252Sdinak tmpbuf = getpassphrase(prompt);
805252Sdinak if (tmpbuf == NULL)
815252Sdinak return (-1);
825252Sdinak
835252Sdinak if (strnlen(tmpbuf, min_psize) >= min_psize)
845252Sdinak break;
855252Sdinak
865252Sdinak if (token_name != NULL)
875252Sdinak (void) printf(DEFAULT_TOKEN_MINSIZE, min_psize);
885252Sdinak else
895252Sdinak (void) printf(DEFAULT_USER_MINSIZE, min_psize);
905252Sdinak }
915252Sdinak if (tries == 0) {
925252Sdinak (void) printf(gettext("Exceeded number of attempts.\n"));
935252Sdinak return (-1);
945252Sdinak }
955252Sdinak
965252Sdinak databuf = strdup(tmpbuf);
975252Sdinak (void) memset(tmpbuf, 0, strlen(tmpbuf)); /* clean up */
985252Sdinak if (databuf == NULL)
995252Sdinak return (-1);
1005252Sdinak
1015252Sdinak if (with_confirmation) {
1025252Sdinak if (token_name != NULL)
1035252Sdinak (void) snprintf(prompt, sizeof (prompt),
1045252Sdinak DEFAULT_TOKEN_REPROMPT, token_name);
1055252Sdinak else
1065252Sdinak (void) snprintf(prompt, sizeof (prompt),
1075252Sdinak DEFAULT_USER_REPROMPT);
1085252Sdinak tmpbuf = getpassphrase(prompt);
1095252Sdinak if (tmpbuf == NULL) {
1105252Sdinak /* clean up */
1115252Sdinak (void) memset(databuf, 0, strlen(databuf));
1125252Sdinak free(databuf);
1135252Sdinak return (-2);
1145252Sdinak }
1155252Sdinak
1165252Sdinak if (strcmp(databuf, tmpbuf) != 0) {
1175252Sdinak /* clean up */
1185252Sdinak (void) memset(tmpbuf, 0, strlen(tmpbuf));
1195252Sdinak (void) memset(databuf, 0, strlen(databuf));
1205252Sdinak free(databuf);
1215252Sdinak return (-2);
1225252Sdinak }
1235252Sdinak }
1245252Sdinak
1255252Sdinak *pdata = databuf;
1265252Sdinak *psize = strlen(databuf);
1275252Sdinak
1285252Sdinak return (0);
1295252Sdinak }
130