xref: /netbsd-src/crypto/external/cpl/tpm-tools/dist/lib/tpm_utils.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*
2  * The Initial Developer of the Original Code is International
3  * Business Machines Corporation. Portions created by IBM
4  * Corporation are Copyright (C) 2005 International Business
5  * Machines Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the Common Public License as published by
9  * IBM Corporation; either version 1 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * Common Public License for more details.
16  *
17  * You should have received a copy of the Common Public License
18  * along with this program; if not, a copy can be viewed at
19  * http://www.opensource.org/licenses/cpl1.0.php.
20  */
21 
22 #include "config.h"
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <trousers/tss.h>
26 #include <trousers/trousers.h>
27 
28 #include "tpm_tspi.h"
29 #include "tpm_utils.h"
30 
31 BOOL useUnicode = FALSE;
32 
33 static const struct option sGenLongOpts[] = {
34 	{ "help", no_argument, NULL, 'h' },
35 	{ "version", no_argument, NULL, 'v' },
36 	{ "log", required_argument, NULL, 'l' },
37 	{ "unicode", no_argument, NULL, 'u' },
38 };
39 
40 static const char *pszGenShortOpts = "hvl:u";
41 
42 void initIntlSys( ) {
43 
44 	setlocale( LC_ALL, "" );
45 	bindtextdomain( PACKAGE, LOCALEDIR );
46 	textdomain( PACKAGE );
47 }
48 
49 int
50 genericOptHandler( int a_iNumArgs, char **a_pszArgs,
51 		   const char *a_pszShortOpts,
52 		   struct option *a_sLongOpts, int a_iNumOpts,
53 		   CmdOptParser a_tCmdOptParser, CmdHelpFunction a_tCmdHelpFunction ) {
54 
55 	CmdHelpFunction  tCmdHelp = ( a_tCmdHelpFunction ) ? a_tCmdHelpFunction
56 							   : logCmdHelp;
57 
58 	char  szShortOpts[strlen( pszGenShortOpts )
59 			  + ( ( a_pszShortOpts == NULL ) ? 0 : strlen( a_pszShortOpts ) )
60 			  + 1];
61 
62 	int            iNumGenLongOpts = sizeof( sGenLongOpts ) / sizeof( struct option );
63 	struct option  sLongOpts[iNumGenLongOpts + a_iNumOpts + 1];
64 
65 	int  iOpt;
66 	int  rc;
67 
68 	strcpy( szShortOpts, pszGenShortOpts);
69 	if ( a_pszShortOpts )
70 		strcat( szShortOpts, a_pszShortOpts );
71 
72 	memset( sLongOpts, 0, sizeof( sLongOpts ) );
73 	memcpy( sLongOpts, sGenLongOpts, sizeof( sGenLongOpts ) );
74 	if ( a_sLongOpts ) {
75 		memcpy( sLongOpts + iNumGenLongOpts,
76 			a_sLongOpts,
77 			a_iNumOpts * sizeof( struct option ) );
78 	}
79 
80 	while ( ( iOpt = getopt_long( a_iNumArgs, a_pszArgs,
81 					szShortOpts, sLongOpts, NULL ) ) != -1 ) {
82 
83 		switch ( iOpt ) {
84 			case 'h':
85 				tCmdHelp( a_pszArgs[0] );
86 				return -1;
87 
88 			case 'v':
89 				logMsg( _("%s version: %s\n"), a_pszArgs[0], CMD_VERSION );
90 				return -1;
91 
92 			case 'l':
93 				if ( !optarg ) {
94 					tCmdHelp( a_pszArgs[0] );
95 					return -1;
96 				}
97 
98 				if ( strcmp( optarg, LOG_NONE ) == 0 )
99 					iLogLevel = LOG_LEVEL_NONE;
100 				else if ( strcmp( optarg, LOG_ERROR ) == 0 )
101 					iLogLevel = LOG_LEVEL_ERROR;
102 				else if ( strcmp( optarg, LOG_INFO ) == 0 )
103 					iLogLevel = LOG_LEVEL_INFO;
104 				else if ( strcmp( optarg, LOG_DEBUG ) == 0 )
105 					iLogLevel = LOG_LEVEL_DEBUG;
106 				else {
107 					logMsg( _("Valid log levels are: %s, %s, %s, %s\n"),
108 						LOG_NONE,
109 						LOG_ERROR,
110 						LOG_INFO,
111 						LOG_DEBUG );
112 					tCmdHelp( a_pszArgs[0] );
113 					return -1;
114 				}
115 				break;
116 			case 'u':
117 				useUnicode = TRUE;
118 				break;
119 			case '?':
120 				tCmdHelp( a_pszArgs[0] );
121 				return -1;
122 
123 			default:
124 				if ( !a_tCmdOptParser )
125 					return -1;
126 
127 				rc = a_tCmdOptParser( iOpt, optarg );
128 				if ( rc != 0 )
129 					return rc;
130 				break;
131 		}
132 	}
133 
134 	return 0;
135 }
136 
137 /*
138  * This function should be called when you are done with a password
139  * the above getPasswd function to properly clean up.
140  */
141 void shredPasswd( char *a_pszPasswd ) {
142 
143 	if ( a_pszPasswd ) {
144 		memset( a_pszPasswd, 0, strlen( a_pszPasswd ) );
145 		free( a_pszPasswd );
146 	}
147 }
148 
149 /*
150  * You must free the memory passed back to you when you are finished.
151  * Loop will always terminate by the second pass.
152  * Safest use of getpass is to zero the memory as soon as possible.
153  */
154 char *getPlainPasswd(const char *a_pszPrompt, BOOL a_bConfirm) {
155 	int len;
156 	return _getPasswd(a_pszPrompt, &len, a_bConfirm, FALSE);
157 }
158 
159 #ifndef TSS_LIB_IS_12
160 char *getPasswd(const char *a_pszPrompt, int* a_iLen,
161 		BOOL a_bConfirm) {
162 	return _getPasswd( a_pszPrompt, a_iLen, a_bConfirm, useUnicode);
163 }
164 #endif
165 char *_getPasswd(const char *a_pszPrompt, int* a_iLen,
166 		BOOL a_bConfirm, BOOL a_bUseUnicode) {
167 
168 	char *pszPrompt = (char *)a_pszPrompt;
169 	char *pszPasswd = NULL;
170 	char *pszRetPasswd = NULL;
171 
172 	do {
173 		// Get password value from user - this is a static buffer
174 		// and should never be freed
175 		pszPasswd = getpass( pszPrompt );
176 		if (!pszPasswd && pszRetPasswd) {
177 			shredPasswd( pszRetPasswd );
178 			return NULL;
179 		}
180 
181 		// If this is confirmation pass check for match
182 		if ( pszRetPasswd ) {
183 			// Matched work complete
184 			if ( strcmp( pszPasswd, pszRetPasswd ) == 0)
185 				goto out;
186 
187 			// No match clean-up
188 			logMsg( _("Passwords didn't match\n") );
189 
190 			// pszPasswd will be cleaned up at out label
191 			shredPasswd( pszRetPasswd );
192 			pszRetPasswd = NULL;
193 			goto out;
194 		}
195 
196 		// Save this passwd for next pass and/or return val
197 		pszRetPasswd = strdup( pszPasswd );
198 		if ( !pszRetPasswd )
199 			goto out;
200 
201 		pszPrompt = _("Confirm password: ");
202 	} while (a_bConfirm);
203 
204 out:
205 	if (pszRetPasswd) {
206 		*a_iLen = strlen(pszRetPasswd);
207 
208 		if (a_bUseUnicode) {
209 			shredPasswd(pszRetPasswd);
210 			pszRetPasswd = (char *)Trspi_Native_To_UNICODE((BYTE *)pszPasswd, (unsigned int *)a_iLen);
211 		}
212 	}
213 
214 	// pszPasswd is a static buffer, just clear it
215 	if ( pszPasswd )
216 		memset( pszPasswd, 0, strlen( pszPasswd ) );
217 
218 	return pszRetPasswd;
219 }
220 
221 /*
222  * You must free the memory passed back to you when you are finished.
223  */
224 char *getReply( const char *a_pszPrompt, int a_iMaxLen ) {
225 
226 	char *pszReply  = NULL;
227 	int   iReplyLen = a_iMaxLen + 2; // Room for newline and trailing zero
228 
229 	if ( iReplyLen <= 0 )
230 		goto out;
231 
232 	pszReply = (char *)calloc( iReplyLen, 1 );
233 	if ( !pszReply )
234 		goto out;
235 
236 	logMsg( "%s", a_pszPrompt );
237 	pszReply = fgets( pszReply, iReplyLen, stdin );
238 	if ( !pszReply )
239 		goto out;
240 
241 	// Be certain that a complete line was read
242 	if ( ( pszReply[ a_iMaxLen ] != '\n' ) && ( pszReply[ a_iMaxLen ] != '\0' ) ) {
243 		free( pszReply );
244 		pszReply = NULL;
245 		goto out;
246 	}
247 
248 	for ( iReplyLen -= 1; iReplyLen >= 0; iReplyLen-- ) {
249 		if ( pszReply[ iReplyLen ] == '\0' )
250 			continue;
251 
252 		if ( pszReply[ iReplyLen ] == '\n' )
253 			pszReply[ iReplyLen ] = '\0';
254 		break;
255 	}
256 
257 out:
258 	return pszReply;
259 }
260