1*af101e7fSchristos /*
2*af101e7fSchristos  * The Initial Developer of the Original Code is International
3*af101e7fSchristos  * Business Machines Corporation. Portions created by IBM
4*af101e7fSchristos  * Corporation are Copyright (C) 2005 International Business
5*af101e7fSchristos  * Machines Corporation. All Rights Reserved.
6*af101e7fSchristos  *
7*af101e7fSchristos  * This program is free software; you can redistribute it and/or modify
8*af101e7fSchristos  * it under the terms of the Common Public License as published by
9*af101e7fSchristos  * IBM Corporation; either version 1 of the License, or (at your option)
10*af101e7fSchristos  * any later version.
11*af101e7fSchristos  *
12*af101e7fSchristos  * This program is distributed in the hope that it will be useful,
13*af101e7fSchristos  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*af101e7fSchristos  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*af101e7fSchristos  * Common Public License for more details.
16*af101e7fSchristos  *
17*af101e7fSchristos  * You should have received a copy of the Common Public License
18*af101e7fSchristos  * along with this program; if not, a copy can be viewed at
19*af101e7fSchristos  * http://www.opensource.org/licenses/cpl1.0.php.
20*af101e7fSchristos  */
21*af101e7fSchristos 
22*af101e7fSchristos #include "data_init.h"
23*af101e7fSchristos #include "data_common.h"
24*af101e7fSchristos 
25*af101e7fSchristos #include <tpm_pkcs11.h>
26*af101e7fSchristos #include <tpm_utils.h>
27*af101e7fSchristos 
28*af101e7fSchristos #include <stdlib.h>
29*af101e7fSchristos #include <unistd.h>
30*af101e7fSchristos #define _GNU_SOURCE
31*af101e7fSchristos #include <getopt.h>
32*af101e7fSchristos 
33*af101e7fSchristos 
34*af101e7fSchristos BOOL  g_bYes      = FALSE;		// Yes/No prompt reply
35*af101e7fSchristos char *g_pszToken  = NULL;		// Token label to be used
36*af101e7fSchristos 
37*af101e7fSchristos /*
38*af101e7fSchristos  * parseCallback
39*af101e7fSchristos  *   Process the command specific options.
40*af101e7fSchristos  */
41*af101e7fSchristos int
parseCallback(int a_iOpt,const char * a_pszOptArg)42*af101e7fSchristos parseCallback( int         a_iOpt,
43*af101e7fSchristos                const char *a_pszOptArg ) {
44*af101e7fSchristos 
45*af101e7fSchristos 	switch ( a_iOpt ) {
46*af101e7fSchristos 		// Use the specified token label when finding the token
47*af101e7fSchristos 		case 'k':
48*af101e7fSchristos 			if ( !a_pszOptArg )
49*af101e7fSchristos 				return -1;
50*af101e7fSchristos 
51*af101e7fSchristos 			g_pszToken = strdup( a_pszOptArg );
52*af101e7fSchristos 			break;
53*af101e7fSchristos 
54*af101e7fSchristos 		case 'y':
55*af101e7fSchristos 			g_bYes = TRUE;
56*af101e7fSchristos 			break;
57*af101e7fSchristos 	}
58*af101e7fSchristos 
59*af101e7fSchristos 	return 0;
60*af101e7fSchristos }
61*af101e7fSchristos 
62*af101e7fSchristos /*
63*af101e7fSchristos  * usageCallback
64*af101e7fSchristos  *   Display command usage information.
65*af101e7fSchristos  */
66*af101e7fSchristos void
usageCallback(const char * a_pszCmd)67*af101e7fSchristos usageCallback( const char *a_pszCmd ) {
68*af101e7fSchristos 
69*af101e7fSchristos 	logCmdHelp( a_pszCmd );
70*af101e7fSchristos 	logCmdOption( "-k, --token STRING",
71*af101e7fSchristos 			_("Use STRING to identify the label of the PKCS#11 token to be used") );
72*af101e7fSchristos 	logCmdOption( "-y, --yes",
73*af101e7fSchristos 			_("Reply 'yes' to the clear TPM token prompt") );
74*af101e7fSchristos }
75*af101e7fSchristos 
76*af101e7fSchristos /*
77*af101e7fSchristos  * parseCmd
78*af101e7fSchristos  *   Parse the command line options.
79*af101e7fSchristos  */
80*af101e7fSchristos int
parseCmd(int a_iArgc,char ** a_pszArgv)81*af101e7fSchristos parseCmd( int    a_iArgc,
82*af101e7fSchristos           char **a_pszArgv ) {
83*af101e7fSchristos 
84*af101e7fSchristos 	char *pszShortOpts = "k:y";
85*af101e7fSchristos 	struct option  stLongOpts[] = {
86*af101e7fSchristos 					{ "token", required_argument, NULL, 'k' },
87*af101e7fSchristos 					{ "yes", no_argument, NULL, 'y' },
88*af101e7fSchristos 				};
89*af101e7fSchristos 	int  iNumLongOpts = sizeof( stLongOpts ) / sizeof( struct option );
90*af101e7fSchristos 
91*af101e7fSchristos 	return genericOptHandler( a_iArgc, a_pszArgv,
92*af101e7fSchristos 					pszShortOpts, stLongOpts, iNumLongOpts,
93*af101e7fSchristos 					parseCallback, usageCallback );
94*af101e7fSchristos }
95*af101e7fSchristos 
96*af101e7fSchristos int
main(int a_iArgc,char ** a_pszArgv)97*af101e7fSchristos main( int    a_iArgc,
98*af101e7fSchristos       char **a_pszArgv ) {
99*af101e7fSchristos 
100*af101e7fSchristos 	int  rc = 1;
101*af101e7fSchristos 
102*af101e7fSchristos 	// Create buffers for PIN prompts for formatting using sprintf
103*af101e7fSchristos 	char  szSoNewPinPrompt[ strlen( TOKEN_SO_NEW_PIN_PROMPT ) + 16 ];
104*af101e7fSchristos 	char  szUserNewPinPrompt[ strlen( TOKEN_USER_NEW_PIN_PROMPT ) + 16 ];
105*af101e7fSchristos 
106*af101e7fSchristos 	char *pszReply      = NULL;
107*af101e7fSchristos 	char *pszSoPin      = NULL;
108*af101e7fSchristos 	char *pszNewSoPin   = NULL;
109*af101e7fSchristos 	char *pszNewUserPin = NULL;
110*af101e7fSchristos 
111*af101e7fSchristos 	CK_RV              rv       = CKR_OK;
112*af101e7fSchristos 	CK_SESSION_HANDLE  hSession = 0;
113*af101e7fSchristos 
114*af101e7fSchristos 	// Set up i18n
115*af101e7fSchristos 	initIntlSys( );
116*af101e7fSchristos 
117*af101e7fSchristos 	// Parse the command
118*af101e7fSchristos 	if ( parseCmd( a_iArgc, a_pszArgv ) == -1 )
119*af101e7fSchristos 		goto out;
120*af101e7fSchristos 
121*af101e7fSchristos 	// Open the PKCS#11 TPM Token
122*af101e7fSchristos 	rv = openToken( g_pszToken );
123*af101e7fSchristos 	if ( rv != CKR_OK )
124*af101e7fSchristos 		goto out;
125*af101e7fSchristos 
126*af101e7fSchristos 	// Check if the token is already initialized
127*af101e7fSchristos 	if ( isTokenInitialized( ) ) {
128*af101e7fSchristos 		// Warn and ask the user before clearing
129*af101e7fSchristos 		if ( !g_bYes ) {
130*af101e7fSchristos 			pszReply = getReply( TOKEN_CLEAR_PROMPT, 1 );
131*af101e7fSchristos 			if ( !pszReply ||
132*af101e7fSchristos 				( strlen( pszReply ) == 0 ) ||
133*af101e7fSchristos 				( strcasecmp( pszReply, TOKEN_CLEAR_NO ) == 0 ) ) {
134*af101e7fSchristos 				goto out;
135*af101e7fSchristos 			}
136*af101e7fSchristos 		}
137*af101e7fSchristos 
138*af101e7fSchristos 		// Prompt for the current SO password
139*af101e7fSchristos 		pszSoPin = getPlainPasswd( TOKEN_SO_PIN_PROMPT, FALSE );
140*af101e7fSchristos 		if ( !pszSoPin )
141*af101e7fSchristos 			goto out;
142*af101e7fSchristos 	}
143*af101e7fSchristos 	else
144*af101e7fSchristos 		pszSoPin = strdup( TOKEN_SO_INIT_PIN );
145*af101e7fSchristos 
146*af101e7fSchristos 	// Clear the TPM token
147*af101e7fSchristos 	rv = initToken( pszSoPin );
148*af101e7fSchristos 	if ( rv != CKR_OK )
149*af101e7fSchristos 		goto out;
150*af101e7fSchristos 
151*af101e7fSchristos 	// Open a session
152*af101e7fSchristos 	rv = openTokenSession( CKF_RW_SESSION, &hSession );
153*af101e7fSchristos 	if ( rv != CKR_OK )
154*af101e7fSchristos 		goto out;
155*af101e7fSchristos 
156*af101e7fSchristos 	// Login to the token
157*af101e7fSchristos 	rv = loginToken( hSession, CKU_SO, TOKEN_SO_INIT_PIN );
158*af101e7fSchristos 	if ( rv != CKR_OK )
159*af101e7fSchristos 		goto out;
160*af101e7fSchristos 
161*af101e7fSchristos 	sprintf( szSoNewPinPrompt, TOKEN_SO_NEW_PIN_PROMPT, getMinPinLen( ), getMaxPinLen( ) );
162*af101e7fSchristos 	while ( TRUE ) {
163*af101e7fSchristos 		// Prompt for a new SO password
164*af101e7fSchristos 		pszNewSoPin = getPlainPasswd( szSoNewPinPrompt, TRUE );
165*af101e7fSchristos 		if ( !pszNewSoPin )
166*af101e7fSchristos 			goto out;
167*af101e7fSchristos 
168*af101e7fSchristos 		// Set the new password
169*af101e7fSchristos 		rv = setPin( hSession, TOKEN_SO_INIT_PIN, pszNewSoPin );
170*af101e7fSchristos 		if ( rv == CKR_OK )
171*af101e7fSchristos 			break;
172*af101e7fSchristos 
173*af101e7fSchristos 		if ( ( rv == CKR_PIN_INVALID ) || ( rv == CKR_PIN_LEN_RANGE ) )
174*af101e7fSchristos 			logError( TOKEN_INVALID_PIN );
175*af101e7fSchristos 		else
176*af101e7fSchristos 			goto out;
177*af101e7fSchristos 
178*af101e7fSchristos 		shredPasswd( pszNewSoPin );
179*af101e7fSchristos 	}
180*af101e7fSchristos 
181*af101e7fSchristos 	// Open a new session
182*af101e7fSchristos 	closeTokenSession( hSession );
183*af101e7fSchristos 	hSession = 0;
184*af101e7fSchristos 	rv = openTokenSession( CKF_RW_SESSION, &hSession );
185*af101e7fSchristos 	if ( rv != CKR_OK )
186*af101e7fSchristos 		goto out;
187*af101e7fSchristos 
188*af101e7fSchristos 	// Login to the token
189*af101e7fSchristos 	rv = loginToken( hSession, CKU_USER, TOKEN_USER_INIT_PIN );
190*af101e7fSchristos 	if ( rv != CKR_OK )
191*af101e7fSchristos 		goto out;
192*af101e7fSchristos 
193*af101e7fSchristos 	sprintf( szUserNewPinPrompt, TOKEN_USER_NEW_PIN_PROMPT, getMinPinLen( ), getMaxPinLen( ) );
194*af101e7fSchristos 	while ( TRUE ) {
195*af101e7fSchristos 		// Prompt for a new User password
196*af101e7fSchristos 		pszNewUserPin = getPlainPasswd( szUserNewPinPrompt, TRUE );
197*af101e7fSchristos 		if ( !pszNewUserPin )
198*af101e7fSchristos 			goto out;
199*af101e7fSchristos 
200*af101e7fSchristos 		// Set the new password
201*af101e7fSchristos 		rv = setPin( hSession, TOKEN_USER_INIT_PIN, pszNewUserPin );
202*af101e7fSchristos 		if ( rv == CKR_OK )
203*af101e7fSchristos 			break;
204*af101e7fSchristos 
205*af101e7fSchristos 		if ( ( rv == CKR_PIN_INVALID ) || ( rv == CKR_PIN_LEN_RANGE ) )
206*af101e7fSchristos 			logError( TOKEN_INVALID_PIN );
207*af101e7fSchristos 		else
208*af101e7fSchristos 			goto out;
209*af101e7fSchristos 
210*af101e7fSchristos 		shredPasswd( pszNewUserPin );
211*af101e7fSchristos 	}
212*af101e7fSchristos 
213*af101e7fSchristos 	rc = 0;
214*af101e7fSchristos 
215*af101e7fSchristos out:
216*af101e7fSchristos 	free( pszReply );
217*af101e7fSchristos 	shredPasswd( pszSoPin );
218*af101e7fSchristos 	shredPasswd( pszNewSoPin );
219*af101e7fSchristos 	shredPasswd( pszNewUserPin );
220*af101e7fSchristos 
221*af101e7fSchristos 	if ( hSession )
222*af101e7fSchristos 		closeTokenSession( hSession );
223*af101e7fSchristos 
224*af101e7fSchristos 	closeToken( );
225*af101e7fSchristos 
226*af101e7fSchristos 	if ( rc == 0 )
227*af101e7fSchristos 		logInfo( TOKEN_CMD_SUCCESS, a_pszArgv[ 0 ] );
228*af101e7fSchristos 	else
229*af101e7fSchristos 		logInfo( TOKEN_CMD_FAILED, a_pszArgv[ 0 ] );
230*af101e7fSchristos 
231*af101e7fSchristos 	return rc;
232*af101e7fSchristos }
233