1af101e7fSchristos /*
2af101e7fSchristos  * The Initial Developer of the Original Code is International
3af101e7fSchristos  * Business Machines Corporation. Portions created by IBM
4af101e7fSchristos  * Corporation are Copyright (C) 2005, 2006 International Business
5af101e7fSchristos  * Machines Corporation. All Rights Reserved.
6af101e7fSchristos  *
7af101e7fSchristos  * This program is free software; you can redistribute it and/or modify
8af101e7fSchristos  * it under the terms of the Common Public License as published by
9af101e7fSchristos  * IBM Corporation; either version 1 of the License, or (at your option)
10af101e7fSchristos  * any later version.
11af101e7fSchristos  *
12af101e7fSchristos  * This program is distributed in the hope that it will be useful,
13af101e7fSchristos  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14af101e7fSchristos  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15af101e7fSchristos  * Common Public License for more details.
16af101e7fSchristos  *
17af101e7fSchristos  * You should have received a copy of the Common Public License
18af101e7fSchristos  * along with this program; if not, a copy can be viewed at
19af101e7fSchristos  * http://www.opensource.org/licenses/cpl1.0.php.
20af101e7fSchristos  */
21af101e7fSchristos 
22af101e7fSchristos #include "data_protect.h"
23af101e7fSchristos #include "data_common.h"
24af101e7fSchristos 
25af101e7fSchristos #include <tpm_pkcs11.h>
26af101e7fSchristos #include <tpm_utils.h>
27af101e7fSchristos 
28af101e7fSchristos #include <stdlib.h>
29af101e7fSchristos #include <unistd.h>
30af101e7fSchristos #define _GNU_SOURCE
31af101e7fSchristos #include <getopt.h>
32af101e7fSchristos #include <errno.h>
33af101e7fSchristos 
34af101e7fSchristos 
35af101e7fSchristos /*
36af101e7fSchristos  * Global variables
37af101e7fSchristos  */
38af101e7fSchristos int       g_bEncrypt     = TRUE;	// Encrypt/Decrypt operation specifier
39af101e7fSchristos 
40af101e7fSchristos char     *g_pszInFile    = NULL;	// Input file name
41af101e7fSchristos FILE     *g_pInFile      = NULL;	// Input file stream
42af101e7fSchristos CK_BYTE  *g_pbInData     = NULL;	// Input file buffer
43af101e7fSchristos 
44af101e7fSchristos char     *g_pszOutFile   = NULL;	// Output file name
45af101e7fSchristos FILE     *g_pOutFile     = NULL;	// Output file stream
46af101e7fSchristos CK_ULONG  g_ulOutBuffLen = 0;		// Output file buffer length
47af101e7fSchristos CK_BYTE  *g_pbOutData    = NULL;	// Output file buffer
48af101e7fSchristos CK_ULONG  g_ulOutDataLen = 0;		// Length of data contained in output buffer
49af101e7fSchristos 
50af101e7fSchristos char     *g_pszToken     = NULL;	// Token label to be used
51af101e7fSchristos 
52af101e7fSchristos /*
53af101e7fSchristos  * parseCallback
54af101e7fSchristos  *   Process the command specific options.
55af101e7fSchristos  */
56af101e7fSchristos int
parseCallback(int a_iOpt,const char * a_pszOptArg)57af101e7fSchristos parseCallback( int         a_iOpt,
58af101e7fSchristos                const char *a_pszOptArg ) {
59af101e7fSchristos 
60af101e7fSchristos 	switch ( a_iOpt ) {
61af101e7fSchristos 		case 'd':
62af101e7fSchristos 			g_bEncrypt = FALSE;
63af101e7fSchristos 			break;
64af101e7fSchristos 
65af101e7fSchristos 		case 'e':
66af101e7fSchristos 			g_bEncrypt = TRUE;
67af101e7fSchristos 			break;
68af101e7fSchristos 
69af101e7fSchristos 		case 'i':
70af101e7fSchristos 			if ( !a_pszOptArg )
71af101e7fSchristos 				return -1;
72af101e7fSchristos 
73af101e7fSchristos 			g_pszInFile = strdup( a_pszOptArg );
74af101e7fSchristos 			break;
75af101e7fSchristos 
76af101e7fSchristos 		// Use the specified token label when finding the token
77af101e7fSchristos 		case 'k':
78af101e7fSchristos 			if ( !a_pszOptArg )
79af101e7fSchristos 				return -1;
80af101e7fSchristos 
81af101e7fSchristos 			g_pszToken = strdup( a_pszOptArg );
82af101e7fSchristos 			break;
83af101e7fSchristos 
84af101e7fSchristos 		case 'o':
85af101e7fSchristos 			if ( !a_pszOptArg )
86af101e7fSchristos 				return -1;
87af101e7fSchristos 
88af101e7fSchristos 			g_pszOutFile = strdup( a_pszOptArg );
89af101e7fSchristos 			break;
90af101e7fSchristos 	}
91af101e7fSchristos 
92af101e7fSchristos 	return 0;
93af101e7fSchristos }
94af101e7fSchristos 
95af101e7fSchristos /*
96af101e7fSchristos  * usageCallback
97af101e7fSchristos  *   Display command usage information.
98af101e7fSchristos  */
99af101e7fSchristos void
usageCallback(const char * a_szCmd)100af101e7fSchristos usageCallback( const char *a_szCmd ) {
101af101e7fSchristos 
102af101e7fSchristos 	logCmdHelp( a_szCmd );
103af101e7fSchristos 	logCmdOption( "-d, --decrypt",
104af101e7fSchristos 			_("Decrypt the input data") );
105af101e7fSchristos 	logCmdOption( "-e, --encrypt",
106af101e7fSchristos 			_("Encrypt the input data (default)") );
107af101e7fSchristos 	logCmdOption( "-i, --infile FILE",
108af101e7fSchristos 			_("Use FILE as the input to the specified operation") );
109af101e7fSchristos 	logCmdOption( "-k, --token STRING",
110af101e7fSchristos 			_("Use STRING to identify the label of the PKCS#11 token to be used") );
111af101e7fSchristos 	logCmdOption( "-o, --outfile FILE",
112af101e7fSchristos 			_("Use FILE as the output of the specified operation") );
113af101e7fSchristos }
114af101e7fSchristos 
115af101e7fSchristos /*
116af101e7fSchristos  * parseCmd
117af101e7fSchristos  *   Parse the command line options.
118af101e7fSchristos  */
119af101e7fSchristos int
parseCmd(int a_iArgc,char ** a_szArgv)120af101e7fSchristos parseCmd( int    a_iArgc,
121af101e7fSchristos           char **a_szArgv ) {
122af101e7fSchristos 
123af101e7fSchristos 	int  rc;
124af101e7fSchristos 
125af101e7fSchristos 	char          *szShortOpts = "dei:k:o:";
126af101e7fSchristos 	struct option  stLongOpts[]  = {
127af101e7fSchristos 			{ "decrypt", no_argument, NULL, 'd' },
128af101e7fSchristos 			{ "encrypt", no_argument, NULL, 'e' },
129af101e7fSchristos 			{ "infile", required_argument, NULL, 'i' },
130af101e7fSchristos 			{ "token", required_argument, NULL, 'k' },
131af101e7fSchristos 			{ "outfile", required_argument, NULL, 'o' },
132af101e7fSchristos 		};
133af101e7fSchristos 	int  iNumLongOpts = sizeof( stLongOpts ) / sizeof( struct option );
134af101e7fSchristos 
135af101e7fSchristos 	rc = genericOptHandler( a_iArgc, a_szArgv,
136af101e7fSchristos 		szShortOpts, stLongOpts, iNumLongOpts,
137af101e7fSchristos 		parseCallback, usageCallback );
138af101e7fSchristos 	if ( rc == -1 )
139af101e7fSchristos 		return -1;
140af101e7fSchristos 
141af101e7fSchristos 	// Make sure "-i" is specified until stdin support is added
142af101e7fSchristos 	if ( !g_pszInFile ) {
143af101e7fSchristos 		logMsg( TOKEN_INPUT_FILE_ERROR );
144af101e7fSchristos 		rc = -1;
145af101e7fSchristos 	}
146af101e7fSchristos 
147af101e7fSchristos 	// Make sure "-o" is specified until stdout support is added
148af101e7fSchristos 	if ( !g_pszOutFile ) {
149af101e7fSchristos 		logMsg( TOKEN_OUTPUT_FILE_ERROR );
150af101e7fSchristos 		rc = -1;
151af101e7fSchristos 	}
152af101e7fSchristos 
153af101e7fSchristos 	if ( rc == -1 ) {
154af101e7fSchristos 		usageCallback( a_szArgv[ 0 ] );
155af101e7fSchristos 		return -1;
156af101e7fSchristos 	}
157af101e7fSchristos 
158af101e7fSchristos 	return 0;
159af101e7fSchristos }
160af101e7fSchristos 
161af101e7fSchristos /*
162af101e7fSchristos  * makeKey
163af101e7fSchristos  *   Make the 256-bit AES symmetric key used to encrypt
164af101e7fSchristos  *   or decrypt the input data.
165af101e7fSchristos  */
166af101e7fSchristos int
makeKey(CK_SESSION_HANDLE a_hSession)167af101e7fSchristos makeKey( CK_SESSION_HANDLE  a_hSession ) {
168af101e7fSchristos 
169af101e7fSchristos 	int  rc = -1;
170af101e7fSchristos 
171af101e7fSchristos 	// Generate a 256-bit AES key
172af101e7fSchristos 	CK_RV             rv;
173af101e7fSchristos 	CK_BBOOL          bTrue       = TRUE;
174af101e7fSchristos 	CK_BBOOL          bFalse      = FALSE;
175af101e7fSchristos 	CK_OBJECT_CLASS   tKeyClass   = CKO_SECRET_KEY;
176af101e7fSchristos 	CK_KEY_TYPE       tKeyType    = CKK_AES;
177af101e7fSchristos 	CK_ULONG          ulKeyLen    = 32;
178af101e7fSchristos 	CK_MECHANISM      tMechanism  = { CKM_AES_KEY_GEN, NULL, 0 };
179af101e7fSchristos 	CK_ATTRIBUTE      tAttr[]     = {
180af101e7fSchristos 			{ CKA_CLASS, &tKeyClass, sizeof( tKeyClass ) },
181af101e7fSchristos 			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },
182af101e7fSchristos 			{ CKA_PRIVATE, &bTrue, sizeof( bTrue ) },
183af101e7fSchristos 			{ CKA_MODIFIABLE, &bFalse, sizeof( bFalse ) },
184af101e7fSchristos 			{ CKA_LABEL, TOKEN_PROTECT_KEY_LABEL, strlen( TOKEN_PROTECT_KEY_LABEL ) },
185af101e7fSchristos 			{ CKA_KEY_TYPE, &tKeyType, sizeof( tKeyType ) },
186af101e7fSchristos 			{ CKA_SENSITIVE, &bTrue, sizeof( bTrue ) },
187af101e7fSchristos 			{ CKA_ENCRYPT, &bTrue, sizeof( bTrue ) },
188af101e7fSchristos 			{ CKA_DECRYPT, &bTrue, sizeof( bTrue ) },
189af101e7fSchristos 			{ CKA_SIGN, &bFalse, sizeof( bFalse ) },
190af101e7fSchristos 			{ CKA_VERIFY, &bFalse, sizeof( bFalse ) },
191af101e7fSchristos 			{ CKA_WRAP, &bTrue, sizeof( bTrue ) },
192af101e7fSchristos 			{ CKA_UNWRAP, &bTrue, sizeof( bTrue ) },
193af101e7fSchristos 			{ CKA_EXTRACTABLE, &bFalse, sizeof( bFalse ) },
194af101e7fSchristos 			{ CKA_VALUE_LEN, &ulKeyLen, sizeof( ulKeyLen ) },
195af101e7fSchristos 		};
196af101e7fSchristos 	CK_ULONG          ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
197af101e7fSchristos 	CK_OBJECT_HANDLE  hObject;
198af101e7fSchristos 
199af101e7fSchristos 	// Generate the key on the token
200af101e7fSchristos 	rv = generateKey( a_hSession, &tMechanism, tAttr, ulAttrCount, &hObject );
201af101e7fSchristos 	if ( rv != CKR_OK )
202af101e7fSchristos 		goto out;
203af101e7fSchristos 
204af101e7fSchristos 	rc = 0;
205af101e7fSchristos out:
206af101e7fSchristos 	return rc;
207af101e7fSchristos }
208af101e7fSchristos 
209af101e7fSchristos /*
210af101e7fSchristos  * getKey
211af101e7fSchristos  *   Get the symmetric key used for encryption or decryption.
212af101e7fSchristos  */
213af101e7fSchristos int
getKey(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE * a_phObject)214af101e7fSchristos getKey( CK_SESSION_HANDLE  a_hSession,
215af101e7fSchristos         CK_OBJECT_HANDLE  *a_phObject ) {
216af101e7fSchristos 
217af101e7fSchristos 	int  rc = -1;
218af101e7fSchristos 
219af101e7fSchristos 	CK_RV             rv;
220af101e7fSchristos 	CK_BBOOL          bTrue       = TRUE;
221af101e7fSchristos 	CK_OBJECT_CLASS   tKeyClass   = CKO_SECRET_KEY;
222af101e7fSchristos 	CK_ATTRIBUTE      tAttr[]     = {
223af101e7fSchristos 			{ CKA_CLASS, &tKeyClass, sizeof( tKeyClass ) },
224af101e7fSchristos 			{ CKA_TOKEN, &bTrue, sizeof( bTrue ) },
225af101e7fSchristos 			{ CKA_LABEL, TOKEN_PROTECT_KEY_LABEL, strlen( TOKEN_PROTECT_KEY_LABEL ) },
226af101e7fSchristos 		};
227af101e7fSchristos 	CK_ULONG          ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
228af101e7fSchristos 	CK_OBJECT_HANDLE *phObjList   = NULL;
229af101e7fSchristos 	CK_ULONG          ulObjCount  = 0;
230af101e7fSchristos 
231af101e7fSchristos 	*a_phObject = 0;
232af101e7fSchristos 
233af101e7fSchristos 	// Search for the protection key
234af101e7fSchristos 	rv = findObjects( a_hSession, tAttr, ulAttrCount, &phObjList, &ulObjCount );
235af101e7fSchristos 	if ( rv != CKR_OK )
236af101e7fSchristos 		goto out;
237af101e7fSchristos 
238af101e7fSchristos 	if ( ulObjCount == 0 ) {
239af101e7fSchristos 		// Key doesn't exist, create it
240af101e7fSchristos 		if ( makeKey( a_hSession ) == -1 )
241af101e7fSchristos 			goto out;
242af101e7fSchristos 
243af101e7fSchristos 		// Search for the protection key again
244af101e7fSchristos 		rv = findObjects( a_hSession, tAttr, ulAttrCount, &phObjList, &ulObjCount );
245af101e7fSchristos 		if ( rv != CKR_OK )
246af101e7fSchristos 			goto out;
247af101e7fSchristos 
248af101e7fSchristos 	}
249af101e7fSchristos 
250af101e7fSchristos 	// Make sure we found it
251af101e7fSchristos 	if ( ulObjCount == 0 ) {
252af101e7fSchristos 		logError( TOKEN_NO_KEY_ERROR );
253af101e7fSchristos 		goto out;
254af101e7fSchristos 	}
255af101e7fSchristos 
256af101e7fSchristos 	// Return the handle to the key
257af101e7fSchristos 	*a_phObject = phObjList[ 0 ];
258af101e7fSchristos 
259af101e7fSchristos 	rc = 0;
260af101e7fSchristos 
261af101e7fSchristos out:
262af101e7fSchristos 	return rc;
263af101e7fSchristos }
264af101e7fSchristos 
265af101e7fSchristos /*
266af101e7fSchristos  * readData
267af101e7fSchristos  *   Callback routine that reads the input data for the encryption
268af101e7fSchristos  *   or decryption operation.  The operation (encryption or decryption)
269af101e7fSchristos  *   determines some of the logic in this routine.
270af101e7fSchristos  */
271af101e7fSchristos int
readData(CK_BYTE ** a_pbData,CK_ULONG * a_pulDataLen,CK_BBOOL * a_pbMoreData,CK_BBOOL a_bEncrypt)272af101e7fSchristos readData( CK_BYTE  **a_pbData,
273af101e7fSchristos           CK_ULONG  *a_pulDataLen,
274af101e7fSchristos           CK_BBOOL  *a_pbMoreData,
275af101e7fSchristos           CK_BBOOL   a_bEncrypt ) {
276af101e7fSchristos 
277af101e7fSchristos 	CK_ULONG  iBytes;
278af101e7fSchristos 	CK_BBOOL  bMoreData = TRUE;
279af101e7fSchristos 
280af101e7fSchristos 	if ( !g_pInFile ) {
281af101e7fSchristos 		// Open the input file
282af101e7fSchristos 		errno = 0;
283af101e7fSchristos 		g_pInFile = fopen( g_pszInFile, "r" );
284af101e7fSchristos 		if ( !g_pInFile ) {
285af101e7fSchristos 			logError( TOKEN_FILE_OPEN_ERROR, g_pszInFile, strerror( errno ) );
286af101e7fSchristos 			return -1;
287af101e7fSchristos 		}
288af101e7fSchristos 
289af101e7fSchristos 		// Allocate an input buffer
290af101e7fSchristos 		g_pbInData = malloc( TOKEN_BUFFER_SIZE );
291af101e7fSchristos 		if ( !g_pbInData ) {
292af101e7fSchristos 			logError( TOKEN_MEMORY_ERROR );
293af101e7fSchristos 			return -1;
294af101e7fSchristos 		}
295af101e7fSchristos 	}
296af101e7fSchristos 
297af101e7fSchristos 	// Read the data
298af101e7fSchristos 	iBytes = fread( g_pbInData, 1, TOKEN_BUFFER_SIZE, g_pInFile );
299af101e7fSchristos 	if ( feof( g_pInFile ) ) {
300af101e7fSchristos 		fclose( g_pInFile );
301af101e7fSchristos 
302af101e7fSchristos 		// End of file encountered, indicate that there is
303af101e7fSchristos 		// no more data
304af101e7fSchristos 		bMoreData = FALSE;
305af101e7fSchristos 	}
306af101e7fSchristos 	else {
307af101e7fSchristos 		// Not end of file so make sure the buffer was filled
308af101e7fSchristos 		if ( iBytes != TOKEN_BUFFER_SIZE ) {
309af101e7fSchristos 			// Error encountered, terminate
310af101e7fSchristos 			fclose( g_pInFile );
311af101e7fSchristos 			return -1;
312af101e7fSchristos 		}
313af101e7fSchristos 	}
314af101e7fSchristos 
315af101e7fSchristos 	if ( !bMoreData && a_bEncrypt ) {
316af101e7fSchristos 		// No more data, so if we are encrypting then we MUST add padding
317af101e7fSchristos 		int  iCount   = iBytes - 1;
318af101e7fSchristos 		int  iPadding = TOKEN_AES_BLOCKSIZE - ( iBytes % TOKEN_AES_BLOCKSIZE );
319af101e7fSchristos 
320af101e7fSchristos 		iBytes += iPadding;
321af101e7fSchristos 
322af101e7fSchristos 		g_pbInData[iCount + iPadding] = iPadding;
323af101e7fSchristos 		iPadding--;
324af101e7fSchristos 		while ( iPadding > 0 ) {
325af101e7fSchristos 			g_pbInData[iCount + iPadding] = 0;
326af101e7fSchristos 			iPadding--;
327af101e7fSchristos 		}
328af101e7fSchristos 	}
329af101e7fSchristos 
330af101e7fSchristos 	*a_pbData = g_pbInData;
331af101e7fSchristos 	*a_pulDataLen = iBytes;
332af101e7fSchristos 	*a_pbMoreData = bMoreData;
333af101e7fSchristos 
334af101e7fSchristos 	return 0;
335af101e7fSchristos }
336af101e7fSchristos 
337af101e7fSchristos /*
338af101e7fSchristos  * writeData
339af101e7fSchristos  *   Callback routine that writes the output data for the encryption
340af101e7fSchristos  *   or decryption operation.  The operation (encryption or decryption)
341af101e7fSchristos  *   determines some of the logic in this routine.
342af101e7fSchristos  */
343af101e7fSchristos int
writeData(CK_BYTE * a_pbData,CK_ULONG a_ulDataLen,CK_BBOOL a_bMoreData,CK_BBOOL a_bEncrypt)344af101e7fSchristos writeData( CK_BYTE  *a_pbData,
345af101e7fSchristos            CK_ULONG  a_ulDataLen,
346af101e7fSchristos            CK_BBOOL  a_bMoreData,
347af101e7fSchristos            CK_BBOOL  a_bEncrypt ) {
348af101e7fSchristos 
349af101e7fSchristos 	size_t tWriteCount;
350af101e7fSchristos 
351af101e7fSchristos 	if ( !g_pOutFile ) {
352af101e7fSchristos 		// Open the output file
353af101e7fSchristos 		errno = 0;
354af101e7fSchristos 		g_pOutFile = fopen( g_pszOutFile, "w" );
355af101e7fSchristos 		if ( !g_pOutFile ) {
356af101e7fSchristos 			logError( TOKEN_FILE_OPEN_ERROR, g_pszOutFile, strerror( errno ) );
357af101e7fSchristos 			return -1;
358af101e7fSchristos 		}
359af101e7fSchristos 	}
360af101e7fSchristos 
361af101e7fSchristos 	if ( !a_bMoreData ) {
362af101e7fSchristos 		// No more data so remove padding if we are decrypting
363af101e7fSchristos 		if ( !a_bEncrypt ) {
364af101e7fSchristos 			int      iPadding;
365af101e7fSchristos 
366af101e7fSchristos 			if ( a_ulDataLen == 0 ) {
367af101e7fSchristos 				// Remove padding from previous block is current
368af101e7fSchristos 				// block is zero length
369af101e7fSchristos 				if ( g_pbOutData ) {
370af101e7fSchristos 					iPadding = g_pbOutData[g_ulOutDataLen - 1];
371af101e7fSchristos 					g_ulOutDataLen -= iPadding;
372af101e7fSchristos 				}
373af101e7fSchristos 			}
374af101e7fSchristos 			else {
375af101e7fSchristos 				// Remove padding from current block
376af101e7fSchristos 				iPadding = a_pbData[a_ulDataLen - 1];
377af101e7fSchristos 				a_ulDataLen -= iPadding;
378af101e7fSchristos 			}
379af101e7fSchristos 		}
380af101e7fSchristos 	}
381af101e7fSchristos 
382af101e7fSchristos 	// Write the previous buffer if there is one
383*739b7041Schristos 	if ( g_pbOutData && ( g_ulOutDataLen > 0 ) ) {
384af101e7fSchristos 		tWriteCount = fwrite( g_pbOutData, 1, g_ulOutDataLen, g_pOutFile );
385af101e7fSchristos 
386*739b7041Schristos 		if ( tWriteCount != g_ulOutDataLen ) {
387*739b7041Schristos 			logError(TOKEN_FILE_WRITE_ERROR, g_pOutFile, "short write");
388*739b7041Schristos 			return -1;
389*739b7041Schristos 		}
390*739b7041Schristos 	}
391*739b7041Schristos 
392af101e7fSchristos 	if ( a_bMoreData ) {
393af101e7fSchristos 		// Allocate a (new) buffer if necessary
394af101e7fSchristos 		if ( a_ulDataLen > g_ulOutBuffLen ) {
395af101e7fSchristos 			free( g_pbOutData );
396af101e7fSchristos 
397af101e7fSchristos 			g_ulOutBuffLen = a_ulDataLen;
398af101e7fSchristos 			g_pbOutData = malloc( g_ulOutBuffLen );
399af101e7fSchristos 			if ( !g_pbOutData ) {
400af101e7fSchristos 				logError( TOKEN_MEMORY_ERROR );
401af101e7fSchristos 				return -1;
402af101e7fSchristos 			}
403af101e7fSchristos 		}
404af101e7fSchristos 
405af101e7fSchristos 		// Copy the current data to the holding buffer
406af101e7fSchristos 		if ( a_ulDataLen > 0 )
407af101e7fSchristos 			memcpy( g_pbOutData, a_pbData, a_ulDataLen );
408af101e7fSchristos 		g_ulOutDataLen = a_ulDataLen;
409af101e7fSchristos 	}
410af101e7fSchristos 	else {
411af101e7fSchristos 		// No more data so write the last piece of data
412*739b7041Schristos 		if ( a_ulDataLen > 0 ) {
413af101e7fSchristos 			tWriteCount = fwrite( a_pbData, 1, a_ulDataLen, g_pOutFile );
414af101e7fSchristos 
415*739b7041Schristos 			if ( tWriteCount != a_ulDataLen ) {
416*739b7041Schristos 				logError(TOKEN_FILE_WRITE_ERROR, g_pOutFile, "short write");
417*739b7041Schristos 				return -1;
418*739b7041Schristos 			}
419*739b7041Schristos 		}
420*739b7041Schristos 
421af101e7fSchristos 		fclose( g_pOutFile );
422af101e7fSchristos 	}
423af101e7fSchristos 
424af101e7fSchristos 	return 0;
425af101e7fSchristos }
426af101e7fSchristos 
427af101e7fSchristos int
main(int a_iArgc,char ** a_szArgv)428af101e7fSchristos main( int    a_iArgc,
429af101e7fSchristos       char **a_szArgv ) {
430af101e7fSchristos 
431af101e7fSchristos 	int  rc = 1;
432af101e7fSchristos 
433af101e7fSchristos 	char *pszPin = NULL;
434af101e7fSchristos 
435af101e7fSchristos 	CK_RV              rv;
436af101e7fSchristos 	CK_SESSION_HANDLE  hSession;
437af101e7fSchristos 	CK_OBJECT_HANDLE   hObject;
438af101e7fSchristos 	CK_MECHANISM       tMechanism = { CKM_AES_ECB, NULL, 0 };
439af101e7fSchristos 
440af101e7fSchristos 	// Set up i18n
441af101e7fSchristos 	initIntlSys( );
442af101e7fSchristos 
443af101e7fSchristos 	// Parse the command
444af101e7fSchristos 	if ( parseCmd( a_iArgc, a_szArgv ) == -1 )
445af101e7fSchristos 		goto out;
446af101e7fSchristos 
447af101e7fSchristos 	// Open the PKCS#11 TPM Token
448af101e7fSchristos 	rv = openToken( g_pszToken );
449af101e7fSchristos 	if ( rv != CKR_OK )
450af101e7fSchristos 		goto out;
451af101e7fSchristos 
452af101e7fSchristos 	// Make sure the token is initialized
453af101e7fSchristos 	if ( !isTokenInitialized( ) ) {
454af101e7fSchristos 		logMsg( TOKEN_NOT_INIT_ERROR );
455af101e7fSchristos 		goto out;
456af101e7fSchristos 	}
457af101e7fSchristos 
458af101e7fSchristos 	// Open a session
459af101e7fSchristos 	rv = openTokenSession( CKF_RW_SESSION, &hSession );
460af101e7fSchristos 	if ( rv != CKR_OK )
461af101e7fSchristos 		goto out;
462af101e7fSchristos 
463af101e7fSchristos 	pszPin = getPlainPasswd( TOKEN_USER_PIN_PROMPT, FALSE );
464af101e7fSchristos 	if ( !pszPin )
465af101e7fSchristos 		goto out;
466af101e7fSchristos 
467af101e7fSchristos 	// Login to the token
468af101e7fSchristos 	rv = loginToken( hSession, CKU_USER, pszPin );
469af101e7fSchristos 	if ( rv != CKR_OK )
470af101e7fSchristos 		goto out;
471af101e7fSchristos 
472af101e7fSchristos 	// Obtain the key
473af101e7fSchristos 	if ( getKey( hSession, &hObject ) == -1 )
474af101e7fSchristos 		goto out;
475af101e7fSchristos 
476af101e7fSchristos 	// Perform the operation
477af101e7fSchristos 	if ( g_bEncrypt )
478af101e7fSchristos 		rv = encryptData( hSession, hObject, &tMechanism,
479af101e7fSchristos 			readData, writeData );
480af101e7fSchristos 	else
481af101e7fSchristos 		rv = decryptData( hSession, hObject, &tMechanism,
482af101e7fSchristos 			readData, writeData );
483af101e7fSchristos 
484af101e7fSchristos 	if ( rv != CKR_OK )
485af101e7fSchristos 		goto out;
486af101e7fSchristos 
487af101e7fSchristos 	rc = 0;
488af101e7fSchristos 
489af101e7fSchristos out:
490af101e7fSchristos 	shredPasswd( pszPin );
491af101e7fSchristos 
492af101e7fSchristos 	if ( hSession )
493af101e7fSchristos 		closeTokenSession( hSession );
494af101e7fSchristos 
495af101e7fSchristos 	closeToken( );
496af101e7fSchristos 
497af101e7fSchristos 	free( g_pszInFile );
498af101e7fSchristos 	free( g_pszOutFile );
499af101e7fSchristos 	free( g_pbInData );
500af101e7fSchristos 	free( g_pbOutData );
501af101e7fSchristos 
502af101e7fSchristos 	if ( rc == 0 )
503af101e7fSchristos 		logInfo( TOKEN_CMD_SUCCESS, a_szArgv[ 0 ] );
504af101e7fSchristos 	else
505af101e7fSchristos 		logInfo( TOKEN_CMD_FAILED, a_szArgv[ 0 ] );
506af101e7fSchristos 
507af101e7fSchristos 	return rc;
508af101e7fSchristos }
509