xref: /netbsd-src/crypto/external/cpl/tpm-tools/dist/lib/tpm_pkcs11.c (revision 8cc77b481a5f7140fcf2d44453fb92dcd15fbbc6)
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 <tpm_pkcs11.h>
23 
24 #include <stdlib.h>
25 #include <dlfcn.h>
26 #include <opencryptoki/pkcs11.h>
27 
28 
29 /*
30  * Global variables
31  */
32 char *                g_pszSoLib = TPM_OPENCRYPTOKI_SO;
33 void *                g_pSoLib   = NULL; // Handle of libopencryptoki library
34 CK_FUNCTION_LIST_PTR  g_pFcnList = NULL; // Function List
35 
36 BOOL           g_bInit      = FALSE;	// Indicates if C_Initialize has been called
37 BOOL           g_bTokenOpen = FALSE;	// Indicates if the token has been opened
38 CK_SLOT_ID     g_tSlotId;		// Slot ID of the TPM token
39 CK_TOKEN_INFO  g_tToken;		// TPM token information
40 
41 
42 void
pkcsDebug(const char * a_pszName,CK_RV a_tResult)43 pkcsDebug( const char *a_pszName,
44            CK_RV       a_tResult ) {
45 
46 	logDebug( _("%s success\n"), a_pszName );
47 }
48 
49 void
pkcsError(const char * a_pszName,CK_RV a_tResult)50 pkcsError( const char *a_pszName,
51            CK_RV       a_tResult ) {
52 
53 	logError( _("%s failed: 0x%08x (%ld)\n"), a_pszName, a_tResult, a_tResult );
54 }
55 
56 void
pkcsResult(const char * a_pszName,CK_RV a_tResult)57 pkcsResult( const char *a_pszName,
58             CK_RV       a_tResult ) {
59 
60 	if ( a_tResult == CKR_OK )
61 		pkcsDebug( a_pszName, a_tResult );
62 	else
63 		pkcsError( a_pszName, a_tResult );
64 }
65 
66 void
pkcsResultException(const char * a_pszName,CK_RV a_tResult,CK_RV a_tExcept)67 pkcsResultException( const char *a_pszName,
68                      CK_RV       a_tResult,
69                      CK_RV       a_tExcept ) {
70 
71 	if ( ( a_tResult == CKR_OK ) || ( a_tResult == a_tExcept ) )
72 		pkcsDebug( a_pszName, a_tResult );
73 	else
74 		pkcsError( a_pszName, a_tResult );
75 }
76 
77 /*
78  * pkcsSlotInfo
79  *   Display some information about the slot.
80  */
81 void
pkcsSlotInfo(CK_SLOT_INFO * a_ptSlotInfo)82 pkcsSlotInfo(CK_SLOT_INFO *a_ptSlotInfo ) {
83 
84 	char szSlotDesc[ sizeof( a_ptSlotInfo->slotDescription ) + 1 ];
85 	char szSlotMfr[ sizeof( a_ptSlotInfo->manufacturerID ) + 1 ];
86 
87 	__memset( szSlotDesc, 0, sizeof( szSlotDesc ) );
88 	__memset( szSlotMfr, 0, sizeof( szSlotMfr ) );
89 
90 	strncpy( szSlotDesc, (char *)a_ptSlotInfo->slotDescription,
91 			sizeof( a_ptSlotInfo->slotDescription ) );
92 	strncpy( szSlotMfr, (char *)a_ptSlotInfo->manufacturerID,
93 			sizeof( a_ptSlotInfo->manufacturerID ) );
94 
95 	logDebug( _("Slot description: %s\n"), szSlotDesc );
96 	logDebug( _("Slot manufacturer: %s\n"), szSlotMfr );
97 	if ( a_ptSlotInfo->flags & CKF_TOKEN_PRESENT )
98 		logDebug( _("Token is present\n") );
99 	else
100 		logDebug( _("Token is not present\n") );
101 }
102 
103 /*
104  * pkcsTokenInfo
105  *   Display some information about the token.
106  */
107 void
pkcsTokenInfo(CK_TOKEN_INFO * a_ptTokenInfo)108 pkcsTokenInfo(CK_TOKEN_INFO *a_ptTokenInfo ) {
109 
110 	char szTokenLabel[ sizeof( a_ptTokenInfo->label ) + 1 ];
111 	char szTokenMfr[ sizeof( a_ptTokenInfo->manufacturerID ) + 1 ];
112 	char szTokenModel[ sizeof( a_ptTokenInfo->model ) + 1 ];
113 
114 	__memset( szTokenLabel, 0, sizeof( szTokenLabel ) );
115 	__memset( szTokenMfr, 0, sizeof( szTokenMfr ) );
116 	__memset( szTokenModel, 0, sizeof( szTokenModel ) );
117 
118 	strncpy( szTokenLabel, (char *)a_ptTokenInfo->label,
119 			sizeof( a_ptTokenInfo->label ) );
120 	strncpy( szTokenMfr, (char *)a_ptTokenInfo->manufacturerID,
121 			sizeof( a_ptTokenInfo->manufacturerID ) );
122 	strncpy( szTokenModel, (char *)a_ptTokenInfo->model,
123 			sizeof( a_ptTokenInfo->model ) );
124 
125 	logDebug( _("Token Label: %s\n"), szTokenLabel );
126 	logDebug( _("Token manufacturer: %s\n"), szTokenMfr );
127 	logDebug( _("Token model: %s\n"), szTokenModel );
128 
129 	if ( a_ptTokenInfo->flags & CKF_TOKEN_INITIALIZED )
130 		logDebug( _("Token is initialized\n") );
131 	else
132 		logDebug( _("Token is not initialized\n") );
133 }
134 
135 /*
136  * openToken
137  *   Iterate through the available slots and tokens looking
138  *   for the TPM token and "opening" it if it is found.
139  */
140 CK_RV
openToken(char * a_pszTokenLabel)141 openToken( char *a_pszTokenLabel ) {
142 
143 	CK_C_GetFunctionList  fGetFunctionList;
144 
145 	unsigned int  i;
146 
147 	CK_RV          rv;
148 	CK_ULONG       ulSlots;
149 	CK_SLOT_ID    *ptSlots = NULL;
150 	CK_SLOT_INFO   tSlotInfo;
151 	CK_TOKEN_INFO  tTokenInfo;
152 
153 	char  szTokenLabel[ sizeof( tTokenInfo.label ) ];
154 	char *pszTokenLabel;
155 
156 	// Load the PKCS#11 library
157 	g_pSoLib = dlopen( g_pszSoLib, RTLD_NOW );
158 	if ( !g_pSoLib ) {
159 		logError( _("The PKCS#11 library cannot be loaded: %s\n"), dlerror( ) );
160 		rv = CKR_GENERAL_ERROR;
161 		goto out;
162 	}
163 	fGetFunctionList = (CK_C_GetFunctionList)dlsym( g_pSoLib, "C_GetFunctionList" );
164 	if ( !fGetFunctionList ) {
165 		logError( _("Unable to find the C_GetFunctionList function: %s\n"), dlerror( ) );
166 		rv = CKR_GENERAL_ERROR;
167 		goto out;
168 	}
169 	rv = fGetFunctionList( &g_pFcnList );
170 	pkcsResult( "C_GetFunctionList", rv );
171 	if ( rv != CKR_OK )
172 		goto out;
173 
174 	// Set the name of the TPM token
175 	__memset( szTokenLabel, ' ', sizeof( szTokenLabel ) );
176 	if ( a_pszTokenLabel ) {
177 		if ( strlen( a_pszTokenLabel ) > sizeof( szTokenLabel ) ) {
178 			logError( _("The token label cannot be greater than %ld characters\n"), sizeof( szTokenLabel ) );
179 			rv = CKR_GENERAL_ERROR;
180 			goto out;
181 		}
182 		pszTokenLabel = a_pszTokenLabel;
183 	}
184 	else
185 		pszTokenLabel = TPM_TOKEN_LABEL;
186 	strncpy( szTokenLabel, pszTokenLabel, strlen( pszTokenLabel ) );
187 
188 	// Initialize the PKCS#11 library
189 	rv = g_pFcnList->C_Initialize( NULL );
190 	pkcsResult( "C_Initialize", rv );
191 	if ( rv != CKR_OK )
192 		goto out;
193 	g_bInit = TRUE;
194 
195 	// Determine the number of slots that are present
196 	rv = g_pFcnList->C_GetSlotList( FALSE, NULL, &ulSlots );
197 	pkcsResult( "C_GetSlotList", rv );
198 	if ( rv != CKR_OK )
199 		goto out;
200 
201 	if ( ulSlots == 0 ) {
202 		logError( _("No PKCS#11 slots present\n") );
203 		rv = CKR_TOKEN_NOT_PRESENT;
204 		goto out;
205 	}
206 
207 	// Allocate a buffer to hold the slot ids
208 	logDebug( _("Slots present: %ld\n"), ulSlots );
209 	ptSlots = (CK_SLOT_ID_PTR)calloc( 1, sizeof( CK_SLOT_ID ) * ulSlots );
210 	if ( !ptSlots ) {
211 		logError( _("Unable to obtain memory for PKCS#11 slot IDs\n") );
212 		rv = CKR_HOST_MEMORY;
213 		goto out;
214 	}
215 
216 	// Retrieve the list of slot ids that are present
217 	rv = g_pFcnList->C_GetSlotList( FALSE, ptSlots, &ulSlots );
218 	pkcsResult( "C_GetSlotList", rv );
219 	if ( rv != CKR_OK )
220 		goto out;
221 
222 	// Iterate through the slots looking for the TPM token
223 	for ( i = 0; i < ulSlots; i++ ) {
224 		// Obtain information about the slot
225 		logDebug( _("Retrieving slot information for SlotID %ld\n"), ptSlots[ i ] );
226 		rv = g_pFcnList->C_GetSlotInfo( ptSlots[ i ], &tSlotInfo );
227 		pkcsResult( "C_GetSlotInfo", rv );
228 		if ( rv != CKR_OK )
229 			goto out;
230 		pkcsSlotInfo( &tSlotInfo );
231 
232 		if ( tSlotInfo.flags & CKF_TOKEN_PRESENT ) {
233 			// The slot token is present, obtain information about the token
234 			logDebug( _("Retrieving token information for SlotID %ld\n"), ptSlots[ i ] );
235 			rv = g_pFcnList->C_GetTokenInfo( ptSlots[ i ], &tTokenInfo );
236 			pkcsResult( "C_GetTokenInfo", rv );
237 			if ( rv != CKR_OK )
238 				goto out;
239 			pkcsTokenInfo( &tTokenInfo );
240 
241 			// Check for the TPM token
242 			if ( !strncmp( (char *)tTokenInfo.label, szTokenLabel, sizeof( szTokenLabel ) ) ) {
243 				g_bTokenOpen = TRUE;
244 				g_tSlotId = ptSlots[ i ];
245 				g_tToken = tTokenInfo;
246 				break;
247 			}
248 		}
249 	}
250 
251 	if ( !g_bTokenOpen ) {
252 		logError( _("PKCS#11 TPM Token is not present\n") );
253 		rv = CKR_TOKEN_NOT_PRESENT;
254 	}
255 
256 out:
257 	if (rv != CKR_OK)
258 		free(ptSlots);
259 
260 	if ( !g_bTokenOpen && g_bInit ) {
261 		g_pFcnList->C_Finalize( NULL );
262 		g_bInit = FALSE;
263 	}
264 
265 	if ( !g_bTokenOpen && g_pSoLib ) {
266 		dlclose( g_pSoLib );
267 		g_pSoLib = NULL;
268 	}
269 
270 	return rv;
271 }
272 
273 /*
274  * closeToken
275  *   "Close" the TPM token.
276  */
277 CK_RV
closeToken()278 closeToken( ) {
279 
280 	CK_RV  rv = CKR_OK;
281 
282 	// Tear down the PKCS#11 environment
283 	if ( g_bInit ) {
284 		rv = g_pFcnList->C_Finalize( NULL );
285 		pkcsResult( "C_Finalize", rv );
286 	}
287 
288 	// Unload the PKCS#11 library
289 	if ( g_pSoLib )
290 		dlclose( g_pSoLib );
291 
292 	g_bTokenOpen = FALSE;
293 	g_bInit      = FALSE;
294 	g_pSoLib     = NULL;
295 
296 	return rv;
297 }
298 
299 /*
300  * initToken
301  *   Invoke the PKCS#11 C_InitToken API.
302  */
303 CK_RV
initToken(char * a_pszPin)304 initToken( char *a_pszPin ) {
305 
306 	CK_RV  rv;
307 
308 	if ( !g_bTokenOpen )
309 		return CKR_GENERAL_ERROR;
310 
311 	rv = g_pFcnList->C_InitToken( g_tSlotId, (CK_CHAR *)a_pszPin, strlen( a_pszPin ), g_tToken.label );
312 	pkcsResult( "C_InitToken", rv );
313 
314 	return rv;
315 }
316 
317 /*
318  * openTokenSession
319  *   Invoke the PKCS#11 C_OpenSession API.
320  */
321 CK_RV
openTokenSession(CK_FLAGS a_tType,CK_SESSION_HANDLE * a_phSession)322 openTokenSession( CK_FLAGS           a_tType,
323                   CK_SESSION_HANDLE *a_phSession ) {
324 
325 	CK_RV  rv;
326 
327 	if ( !g_bTokenOpen )
328 		return CKR_GENERAL_ERROR;
329 
330 	a_tType |= CKF_SERIAL_SESSION; // This flag must always be set
331 	rv = g_pFcnList->C_OpenSession( g_tSlotId, a_tType, NULL, NULL, a_phSession );
332 	pkcsResult( "C_OpenSession", rv );
333 
334 	return rv;
335 }
336 
337 /*
338  * closeTokenSession
339  *   Invoke the PKCS#11 C_CloseSession API.
340  */
341 CK_RV
closeTokenSession(CK_SESSION_HANDLE a_hSession)342 closeTokenSession( CK_SESSION_HANDLE  a_hSession ) {
343 
344 	CK_RV  rv;
345 
346 	if ( !g_bTokenOpen )
347 		return CKR_GENERAL_ERROR;
348 
349 	rv = g_pFcnList->C_CloseSession( a_hSession );
350 	pkcsResult( "C_CloseSession", rv );
351 
352 	return rv;
353 }
354 
355 /*
356  * closeAllTokenSessions
357  *   Invoke the PKCS#11 C_CloseAllSessions API.
358  */
359 CK_RV
closeAllTokenSessions()360 closeAllTokenSessions( ) {
361 
362 	CK_RV  rv;
363 
364 	if ( !g_bTokenOpen )
365 		return CKR_GENERAL_ERROR;
366 
367 	rv = g_pFcnList->C_CloseAllSessions( g_tSlotId );
368 	pkcsResult( "C_CloseAllSessions", rv );
369 
370 	return rv;
371 }
372 
373 /*
374  * loginToken
375  *   Invoke the PKCS#11 C_Login API for the specified user type.
376  */
377 CK_RV
loginToken(CK_SESSION_HANDLE a_hSession,CK_USER_TYPE a_tType,char * a_pszPin)378 loginToken( CK_SESSION_HANDLE  a_hSession,
379             CK_USER_TYPE       a_tType,
380             char              *a_pszPin ) {
381 
382 	CK_RV  rv;
383 
384 	if ( !g_bTokenOpen )
385 		return CKR_GENERAL_ERROR;
386 
387 	rv = g_pFcnList->C_Login( a_hSession, a_tType, (CK_CHAR *)a_pszPin, strlen( a_pszPin ) );
388 	pkcsResult( "C_Login", rv );
389 
390 	return rv;
391 }
392 
393 /*
394  *   Invoke the PKCS#11 C_InitPin API.
395  */
396 CK_RV
initPin(CK_SESSION_HANDLE a_hSession,char * a_pszPin)397 initPin( CK_SESSION_HANDLE  a_hSession,
398          char              *a_pszPin ) {
399 
400 	CK_RV  rv;
401 
402 	if ( !g_bTokenOpen )
403 		return CKR_GENERAL_ERROR;
404 
405 	rv = g_pFcnList->C_InitPIN( a_hSession, (CK_CHAR *)a_pszPin, strlen( a_pszPin ) );
406 	pkcsResult( "C_InitPIN", rv );
407 
408 	return rv;
409 }
410 
411 /*
412  * setPin
413  *   Invoke the PKCS#11 C_SetPIN API.
414  */
415 CK_RV
setPin(CK_SESSION_HANDLE a_hSession,char * a_pszOldPin,char * a_pszNewPin)416 setPin( CK_SESSION_HANDLE  a_hSession,
417         char              *a_pszOldPin,
418         char              *a_pszNewPin ) {
419 
420 	CK_RV  rv;
421 
422 	if ( !g_bTokenOpen )
423 		return CKR_GENERAL_ERROR;
424 
425 	rv = g_pFcnList->C_SetPIN( a_hSession, (CK_CHAR *)a_pszOldPin, strlen( a_pszOldPin ),
426 			(CK_CHAR *)a_pszNewPin, strlen( a_pszNewPin ) );
427 	pkcsResult( "C_SetPIN", rv );
428 
429 	return rv;
430 }
431 
432 /*
433  * generateKey
434  *   Invoke the PKCS#11 C_GenerateKey API to generate a key
435  *   for the specified mechanism with the specified attributes.
436  */
437 CK_RV
generateKey(CK_SESSION_HANDLE a_hSession,CK_MECHANISM * a_ptMechanism,CK_ATTRIBUTE * a_ptAttrList,CK_ULONG a_ulAttrCount,CK_OBJECT_HANDLE * a_phObject)438 generateKey( CK_SESSION_HANDLE  a_hSession,
439              CK_MECHANISM      *a_ptMechanism,
440              CK_ATTRIBUTE      *a_ptAttrList,
441              CK_ULONG           a_ulAttrCount,
442              CK_OBJECT_HANDLE  *a_phObject ) {
443 
444 	CK_RV  rv;
445 
446 	if ( !g_bTokenOpen )
447 		return CKR_GENERAL_ERROR;
448 
449 	rv = g_pFcnList->C_GenerateKey( a_hSession, a_ptMechanism, a_ptAttrList, a_ulAttrCount, a_phObject );
450 	pkcsResult( "C_GenerateKey", rv );
451 
452 	return rv;
453 }
454 
455 /*
456  * createObject
457  *   Invoke the PKCS#11 C_CreateObject API to create an object
458  *   with the specified attributes.
459  */
460 CK_RV
createObject(CK_SESSION_HANDLE a_hSession,CK_ATTRIBUTE * a_ptAttrList,CK_ULONG a_ulAttrCount,CK_OBJECT_HANDLE * a_phObject)461 createObject( CK_SESSION_HANDLE  a_hSession,
462               CK_ATTRIBUTE      *a_ptAttrList,
463               CK_ULONG           a_ulAttrCount,
464               CK_OBJECT_HANDLE  *a_phObject ) {
465 
466 	CK_RV  rv;
467 
468 	if ( !g_bTokenOpen )
469 		return CKR_GENERAL_ERROR;
470 
471 	rv = g_pFcnList->C_CreateObject( a_hSession, a_ptAttrList, a_ulAttrCount, a_phObject );
472 	pkcsResult( "C_CreateObject", rv );
473 
474 	return rv;
475 }
476 
477 /*
478  * destroyObject
479  *   Invoke the PKCS#11 C_DestroyObject API.
480  */
481 CK_RV
destroyObject(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject)482 destroyObject( CK_SESSION_HANDLE  a_hSession,
483                CK_OBJECT_HANDLE   a_hObject ) {
484 
485 	CK_RV  rv;
486 
487 	if ( !g_bTokenOpen )
488 		return CKR_GENERAL_ERROR;
489 
490 	rv = g_pFcnList->C_DestroyObject( a_hSession, a_hObject );
491 	pkcsResult( "C_DestroyObject", rv );
492 
493 	return rv;
494 }
495 
496 /*
497  * getObjectAttributes
498  *   Invoke the PKCS#11 C_GetAttributeValue API to retrieve
499  *   the specified attributes.
500  */
501 CK_RV
getObjectAttributes(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,CK_ATTRIBUTE * a_ptAttrList,CK_ULONG a_ulAttrCount)502 getObjectAttributes( CK_SESSION_HANDLE  a_hSession,
503                      CK_OBJECT_HANDLE   a_hObject,
504                      CK_ATTRIBUTE      *a_ptAttrList,
505                      CK_ULONG           a_ulAttrCount ) {
506 
507 	CK_RV  rv;
508 
509 	if ( !g_bTokenOpen )
510 		return CKR_GENERAL_ERROR;
511 
512 	rv = g_pFcnList->C_GetAttributeValue( a_hSession, a_hObject, a_ptAttrList, a_ulAttrCount );
513 	pkcsResultException( "C_GetAttributeValue", rv, CKR_ATTRIBUTE_TYPE_INVALID );
514 
515 	return rv;
516 }
517 
518 /*
519  * findObjects
520  *   Return a list of object handles for all objects that
521  *   match the specified attributes.
522  */
523 CK_RV
findObjects(CK_SESSION_HANDLE a_hSession,CK_ATTRIBUTE * a_ptAttrList,CK_ULONG a_ulAttrCount,CK_OBJECT_HANDLE ** a_phObjList,CK_ULONG * a_pulObjCount)524 findObjects( CK_SESSION_HANDLE  a_hSession,
525              CK_ATTRIBUTE      *a_ptAttrList,
526              CK_ULONG           a_ulAttrCount,
527              CK_OBJECT_HANDLE **a_phObjList,
528              CK_ULONG          *a_pulObjCount ) {
529 
530 	CK_RV             rv, rv_temp;
531 	CK_ULONG          ulCount    = 0;
532 	CK_ULONG          ulCurCount = 0;
533 	CK_ULONG          ulMaxCount = 0;
534 	CK_OBJECT_HANDLE *phObjList  = NULL;
535 
536 	*a_phObjList = NULL;
537 	*a_pulObjCount = 0;
538 
539 	if ( !g_bTokenOpen )
540 		return CKR_GENERAL_ERROR;
541 
542 	// Initialize the find operation
543 	rv = g_pFcnList->C_FindObjectsInit( a_hSession, a_ptAttrList, a_ulAttrCount );
544 	pkcsResult( "C_FindObjectsInit", rv );
545 	if ( rv != CKR_OK )
546 		goto out;
547 
548 	// Iterate until all object handles have been returned
549 	do {
550 		// Allocate (or increase) the object handle list buffer
551 		CK_OBJECT_HANDLE *phTemp = phObjList;
552 
553 		ulMaxCount += TPM_FIND_MAX;
554 		phObjList = (CK_OBJECT_HANDLE *)calloc( sizeof( CK_OBJECT_HANDLE ), ulMaxCount );
555 		if ( !phObjList ) {
556 			logError( _("Unable to obtain memory for object handle list\n") );
557 			rv = CKR_HOST_MEMORY;
558 			goto done;
559 		}
560 
561 		// Copy the list of object handles
562 		if ( phTemp ) {
563 			memcpy( phObjList, phTemp, ulCurCount * sizeof( CK_OBJECT_HANDLE ) );
564 			free( phTemp );
565 		}
566 
567 		// Find the matching objects
568 		rv = g_pFcnList->C_FindObjects( a_hSession, phObjList + ulCurCount, TPM_FIND_MAX, &ulCount );
569 		pkcsResult( "C_FindObjects", rv );
570 		if ( rv != CKR_OK )
571 			goto done;
572 
573 		ulCurCount += ulCount;
574 	} while ( ulCurCount == ulMaxCount );
575 
576 	*a_phObjList = phObjList;
577 	*a_pulObjCount = ulCurCount;
578 
579 done:
580 	// Terminate the find operation
581 	rv_temp = g_pFcnList->C_FindObjectsFinal( a_hSession );
582 	pkcsResult( "C_FindObjectsFinal", rv_temp );
583 
584 out:
585 	if ( ( rv != CKR_OK ) && phObjList )
586 		free( phObjList );
587 
588 	return rv;
589 }
590 
591 /*
592  * displayByteArray
593  *   Format a byte array for display.
594  */
595 void
displayByteArray(const char * a_pszLabel,CK_ATTRIBUTE * a_ptAttr,int a_bExtended)596 displayByteArray( const char   *a_pszLabel,
597                   CK_ATTRIBUTE *a_ptAttr,
598                   int           a_bExtended ) {
599 
600 	const char *pszPre  = ( a_bExtended ) ? "\t" : "";
601 	const char *pszPost = ( a_bExtended ) ? "\n" : "";
602 
603 	logMsg( "%s%s'", pszPre, a_pszLabel );
604 
605 	if ( a_ptAttr->ulValueLen )
606 		logHex( a_ptAttr->ulValueLen, a_ptAttr->pValue );
607 	else
608 		logMsg( "(null)" );
609 
610 	logMsg( "'%s", pszPost );
611 }
612 
613 /*
614  * displayCertObject
615  *   Format a certificate object for display.
616  */
617 CK_RV
displayCertObject(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,int a_bExtended)618 displayCertObject( CK_SESSION_HANDLE  a_hSession,
619                    CK_OBJECT_HANDLE   a_hObject,
620                    int                a_bExtended ) {
621 
622 	CK_RV                rv;
623 	CK_OBJECT_CLASS  tClass;
624 	CK_BBOOL             bToken;
625 	CK_BBOOL             bPrivate;
626 	CK_BBOOL             bModifiable;
627 	CK_CHAR             *pszLabel    = NULL;
628 	CK_CERTIFICATE_TYPE  tType;
629 	CK_BBOOL             bTrusted;
630 
631 	CK_ATTRIBUTE  tCertList[] = {
632 			{ CKA_CLASS, &tClass, sizeof( tClass ) },
633 			{ CKA_TOKEN, &bToken, sizeof( bToken ) },
634 			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },
635 			{ CKA_MODIFIABLE, &bModifiable, sizeof( bModifiable ) },
636 			{ CKA_LABEL, NULL, 0 },
637 			{ CKA_CERTIFICATE_TYPE, &tType, sizeof( tType ) },
638 			{ CKA_TRUSTED, &bTrusted, sizeof( bTrusted ) },
639 		};
640 	CK_ATTRIBUTE  tX509List[] = {
641 			{ CKA_SUBJECT, NULL, 0 },
642 			{ CKA_ID, NULL, 0 },
643 			{ CKA_ISSUER, NULL, 0 },
644 			{ CKA_SERIAL_NUMBER, NULL, 0 },
645 			{ CKA_VALUE, NULL, 0 },
646 		};
647 	CK_ATTRIBUTE  tX509AttrList[] = {
648 			{ CKA_OWNER, NULL, 0 },
649 			{ CKA_AC_ISSUER, NULL, 0 },
650 			{ CKA_SERIAL_NUMBER, NULL, 0 },
651 			{ CKA_ATTR_TYPES, NULL, 0 },
652 			{ CKA_VALUE, NULL, 0 },
653 		};
654 	CK_ULONG      ulCertCount     = sizeof( tCertList ) / sizeof( CK_ATTRIBUTE );
655 	CK_ULONG      ulX509Count     = sizeof( tX509List ) / sizeof( CK_ATTRIBUTE );
656 	CK_ULONG      ulX509AttrCount = sizeof( tX509AttrList ) / sizeof( CK_ATTRIBUTE );
657 	CK_ATTRIBUTE *ptAttrList;
658 	CK_ULONG      ulAttrCount;
659 
660 	// Retrieve the common certificate attributes
661 	rv = getObjectAttributes( a_hSession, a_hObject, tCertList, ulCertCount );
662 	if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
663 		return rv;
664 
665 	// Allocate storage for the object label (extra byte for null
666 	// terminated string)
667 	if ( tCertList[ 4 ].ulValueLen > 0 ) {
668 		pszLabel = tCertList[ 4 ].pValue = calloc( 1, tCertList[ 4 ].ulValueLen + 1 );
669 
670 		rv = getObjectAttributes( a_hSession, a_hObject, tCertList, ulCertCount );
671 		if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
672 			return rv;
673 	}
674 
675 	// Determine the attributes to retrieve based on the certficate type
676 	switch ( tType ) {
677 		case CKC_X_509:
678 			ptAttrList = tX509List;
679 			ulAttrCount = ulX509Count;
680 			break;
681 
682 		case CKC_X_509_ATTR_CERT:
683 			ptAttrList = tX509AttrList;
684 			ulAttrCount = ulX509AttrCount;
685 			break;
686 
687 		default:
688 			ptAttrList = NULL;
689 			ulAttrCount = 0;
690 	}
691 
692 	if ( ptAttrList ) {
693 		CK_ULONG  ulMalloc;
694 
695 		// Retrieve the specific certificate type attributes (for obtaining
696 		// the attribute lengths)
697 		rv = getObjectAttributes( a_hSession, a_hObject, ptAttrList, ulAttrCount );
698 		if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
699 			return rv;
700 
701 		for ( ulMalloc = 0; ulMalloc < ulAttrCount; ulMalloc++ ) {
702 			// Allocate the storage (with an extra byte for null terminated
703 			// strings - just in case)
704 			if ( ptAttrList[ ulMalloc ].ulValueLen > 0 )
705 				ptAttrList[ ulMalloc ].pValue =
706 					calloc( 1, ptAttrList[ ulMalloc ].ulValueLen );
707 		}
708 
709 		// Now retrieve all the specific certificate type attributes
710 		rv = getObjectAttributes( a_hSession, a_hObject, ptAttrList, ulAttrCount );
711 		if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
712 			return rv;
713 	}
714 
715 	if ( a_bExtended ) {
716 		logMsg( _("Certificate Object\n") );
717 		switch ( tType ) {
718 			case CKC_X_509:
719 				logMsg( _("\tX509 Certificate\n") );
720 				break;
721 
722 			case CKC_X_509_ATTR_CERT:
723 				logMsg( _("\tX509 Attribute Certificate\n") );
724 				break;
725 
726 			default:
727 				logMsg( _("\tUnknown Certificate Type (%08x)\n"), tType );
728 		}
729 		if ( tCertList[ 1 ].ulValueLen > 0 )
730 			logMsg( _("\tToken Object: %s\n"), bToken ? _("true") : _("false") );
731 		if ( tCertList[ 2 ].ulValueLen > 0 )
732 			logMsg( _("\tPrivate Object: %s\n"), bPrivate ? _("true") : _("false") );
733 		if ( tCertList[ 3 ].ulValueLen > 0 )
734 			logMsg( _("\tModifiable Object: %s\n"), bModifiable ? _("true") : _("false") );
735 		if ( tCertList[ 4 ].ulValueLen > 0 )
736 			logMsg( _("\tLabel: '%s'\n"), pszLabel );
737 		if ( tCertList[ 5 ].ulValueLen > 0 )
738 			logMsg( _("\tTrusted: %s\n"), bTrusted ? _("true") : _("false") );
739 
740 		// Display the attributes based on the certficate type
741 		switch ( tType ) {
742 			case CKC_X_509:
743 				if ( tX509List[ 0 ].ulValueLen > 0 )
744 					displayByteArray( _("Subject: "), &tX509List[ 0 ], a_bExtended );
745 				if ( tX509List[ 1 ].ulValueLen > 0 ) {
746 					logMsg( _("\tId: '%s' ("), tX509List[ 1 ].pValue );
747 					displayByteArray( "", &tX509List[ 1 ], FALSE );
748 					logMsg( ")\n" );
749 				}
750 				if ( tX509List[ 2 ].ulValueLen > 0 )
751 					displayByteArray( _("Issuer: "), &tX509List[ 2 ], a_bExtended );
752 				if ( tX509List[ 3 ].ulValueLen > 0 )
753 					displayByteArray( _("Serial Number: "), &tX509List[ 3 ], a_bExtended );
754 				if ( tX509List[ 4 ].ulValueLen > 0 )
755 					displayByteArray( _("Value: "), &tX509List[ 4 ], a_bExtended );
756 				break;
757 
758 			case CKC_X_509_ATTR_CERT:
759 				if ( tX509AttrList[ 0 ].ulValueLen > 0 )
760 					displayByteArray( _("Owner: "), &tX509AttrList[ 0 ], a_bExtended );
761 				if ( tX509AttrList[ 1 ].ulValueLen > 0 )
762 					displayByteArray( _("Issuer: "), &tX509AttrList[ 1 ], a_bExtended );
763 				if ( tX509AttrList[ 2 ].ulValueLen > 0 )
764 					displayByteArray( _("Serial Number: "), &tX509AttrList[ 2 ], a_bExtended );
765 				if ( tX509AttrList[ 3 ].ulValueLen > 0 )
766 					displayByteArray( _("Attribute Types: "), &tX509AttrList[ 3 ], a_bExtended );
767 				if ( tX509AttrList[ 4 ].ulValueLen > 0 )
768 					displayByteArray( _("Value: "), &tX509AttrList[ 4 ], a_bExtended );
769 				break;
770 		}
771 	}
772 	else {
773 		// Display the attributes based on the certficate type
774 		logMsg( _("Certificate: ") );
775 		switch ( tType ) {
776 			case CKC_X_509:
777 				logMsg( _("Type: X509 Public Key") );
778 				break;
779 
780 			case CKC_X_509_ATTR_CERT:
781 				logMsg( _("Type: X509 Attribute") );
782 				break;
783 
784 			default:
785 				logMsg( _("Unknown Type (%08x)"), tType );
786 		}
787 
788 		if ( tCertList[ 4 ].ulValueLen > 0 )
789 			logMsg( _(", Label: '%s'"), pszLabel );
790 
791 		logMsg( "\n" );
792 	}
793 
794 	return rv;
795 }
796 
797 /*
798  * displayAsymKeyObject
799  *   Format an asymmetric key object for display.
800  */
801 CK_RV
displayAsymKeyObject(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,int a_bExtended)802 displayAsymKeyObject( CK_SESSION_HANDLE  a_hSession,
803                       CK_OBJECT_HANDLE   a_hObject,
804                       int                a_bExtended ) {
805 
806 	CK_RV            rv;
807 	CK_OBJECT_CLASS  tClass;
808 	CK_BBOOL         bToken;
809 	CK_BBOOL         bPrivate;
810 	CK_BBOOL         bModifiable;
811 	CK_CHAR         *pszLabel     = NULL;
812 	CK_KEY_TYPE      tType;
813 	CK_CHAR         *pszId        = NULL;
814 
815 	CK_ATTRIBUTE  tKeyList[] = {
816 			{ CKA_CLASS, &tClass, sizeof( tClass ) },
817 			{ CKA_TOKEN, &bToken, sizeof( bToken ) },
818 			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },
819 			{ CKA_MODIFIABLE, &bModifiable, sizeof( bModifiable ) },
820 			{ CKA_LABEL, NULL, 0 },
821 			{ CKA_KEY_TYPE, &tType, sizeof( tType ) },
822 			{ CKA_SUBJECT, NULL, 0 },
823 			{ CKA_ID, NULL, 0 },
824 		};
825 	CK_ULONG      ulKeyCount = sizeof( tKeyList ) / sizeof( CK_ATTRIBUTE );
826 
827 	// Retrieve the common key attributes
828 	rv = getObjectAttributes( a_hSession, a_hObject, tKeyList, ulKeyCount );
829 	if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
830 		return rv;
831 
832 	// Allocate storage for the object id
833 	if ( ( tKeyList[ 4 ].ulValueLen > 0 ) || ( tKeyList[ 6 ].ulValueLen > 0 ) || ( tKeyList[ 7 ].ulValueLen > 0 ) ) {
834 		if ( tKeyList[ 4 ].ulValueLen > 0 )
835 			pszLabel = tKeyList[ 4 ].pValue =
836 				calloc( 1, tKeyList[ 4 ].ulValueLen + 1 );
837 
838 		if ( tKeyList[ 6 ].ulValueLen > 0 )
839 			tKeyList[ 6 ].pValue =
840 				calloc( 1, tKeyList[ 6 ].ulValueLen + 1 );
841 
842 		if ( tKeyList[ 7 ].ulValueLen > 0 )
843 			pszId = tKeyList[ 7 ].pValue =
844 				calloc( 1, tKeyList[ 7 ].ulValueLen + 1 );
845 
846 		rv = getObjectAttributes( a_hSession, a_hObject, tKeyList, ulKeyCount );
847 		if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
848 			return rv;
849 	}
850 
851 	if ( a_bExtended ) {
852 		logMsg( _("Key Object\n") );
853 		switch ( tClass ) {
854 			case CKO_PUBLIC_KEY:
855 				logMsg( _("\tPublic Key\n") );
856 				break;
857 
858 			case CKO_PRIVATE_KEY:
859 				logMsg( _("\tPrivate Key\n") );
860 				break;
861 		}
862 		if ( tKeyList[ 1 ].ulValueLen > 0 )
863 			logMsg( _("\tToken Object: %s\n"), bToken ? _("true") : _("false") );
864 		if ( tKeyList[ 2 ].ulValueLen > 0 )
865 			logMsg( _("\tPrivate Object: %s\n"), bPrivate ? _("true") : _("false") );
866 		if ( tKeyList[ 3 ].ulValueLen > 0 )
867 			logMsg( _("\tModifiable Object: %s\n"), bModifiable ? _("true") : _("false") );
868 		if ( tKeyList[ 4 ].ulValueLen > 0 )
869 			logMsg( _("\tLabel: '%s'\n"), pszLabel );
870 		if ( tKeyList[ 5 ].ulValueLen > 0 )
871 			logMsg( _("\tType: %ld\n"), tType );
872 		if ( tKeyList[ 6 ].ulValueLen > 0 )
873 			displayByteArray( _("Subject: "), &tKeyList[ 6 ], a_bExtended );
874 		if ( tKeyList[ 7 ].ulValueLen > 0 ) {
875 			logMsg( _("\tId: '%s' ("), pszId );
876 			displayByteArray( "", &tKeyList[ 7 ], FALSE );
877 			logMsg( ")\n" );
878 		}
879 	}
880 	else {
881 		switch ( tClass ) {
882 			case CKO_PUBLIC_KEY:
883 				logMsg( _("Public Key: ") );
884 				break;
885 
886 			case CKO_PRIVATE_KEY:
887 				logMsg( _("Private Key: ") );
888 				break;
889 		}
890 
891 		if ( tKeyList[ 5 ].ulValueLen > 0 )
892 			logMsg( _("Type: %ld"), tType );
893 		if ( tKeyList[ 4 ].ulValueLen > 0 )
894 			logMsg( _(", Label: '%s'"), pszLabel );
895 
896 		logMsg( "\n" );
897 	}
898 
899 	return rv;
900 }
901 
902 /*
903  * displaySymKeyObject
904  *   Format a symmetric key object for display.
905  */
906 CK_RV
displaySymKeyObject(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,int a_bExtended)907 displaySymKeyObject( CK_SESSION_HANDLE  a_hSession,
908                      CK_OBJECT_HANDLE   a_hObject,
909                      int                a_bExtended ) {
910 
911 	CK_RV            rv;
912 	CK_OBJECT_CLASS  tClass;
913 	CK_BBOOL         bToken;
914 	CK_BBOOL         bPrivate;
915 	CK_BBOOL         bModifiable;
916 	CK_CHAR         *pszLabel     = NULL;
917 	CK_KEY_TYPE      tType;
918 
919 	CK_ATTRIBUTE  tKeyList[] = {
920 			{ CKA_CLASS, &tClass, sizeof( tClass ) },
921 			{ CKA_TOKEN, &bToken, sizeof( bToken ) },
922 			{ CKA_PRIVATE, &bPrivate, sizeof( bPrivate ) },
923 			{ CKA_MODIFIABLE, &bModifiable, sizeof( bModifiable ) },
924 			{ CKA_LABEL, NULL, 0 },
925 			{ CKA_KEY_TYPE, &tType, sizeof( tType ) },
926 		};
927 	CK_ULONG      ulKeyCount = sizeof( tKeyList ) / sizeof( CK_ATTRIBUTE );
928 
929 	// Retrieve the common key attributes
930 	rv = getObjectAttributes( a_hSession, a_hObject, tKeyList, ulKeyCount );
931 	if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
932 		return rv;
933 
934 	// Allocate storage for the object id
935 	if ( tKeyList[ 4 ].ulValueLen > 0 ) {
936 		pszLabel = tKeyList[ 4 ].pValue =
937 			calloc( 1, tKeyList[ 4 ].ulValueLen + 1 );
938 
939 		rv = getObjectAttributes( a_hSession, a_hObject, tKeyList, ulKeyCount );
940 		if ( ( rv != CKR_OK ) && ( rv != CKR_ATTRIBUTE_TYPE_INVALID ) )
941 			return rv;
942 	}
943 
944 	if ( a_bExtended ) {
945 		logMsg( _("Key Object\n") );
946 		switch ( tClass ) {
947 			case CKO_SECRET_KEY:
948 				logMsg( _("\tSecret Key\n") );
949 				break;
950 		}
951 		if ( tKeyList[ 1 ].ulValueLen > 0 )
952 			logMsg( _("\tToken Object: %s\n"), bToken ? _("true") : _("false") );
953 		if ( tKeyList[ 2 ].ulValueLen > 0 )
954 			logMsg( _("\tPrivate Object: %s\n"), bPrivate ? _("true") : _("false") );
955 		if ( tKeyList[ 3 ].ulValueLen > 0 )
956 			logMsg( _("\tModifiable Object: %s\n"), bModifiable ? _("true") : _("false") );
957 		if ( tKeyList[ 4 ].ulValueLen > 0 )
958 			logMsg( _("\tLabel: '%s'\n"), pszLabel );
959 		if ( tKeyList[ 5 ].ulValueLen > 0 )
960 			logMsg( _("\tType: %ld\n"), tType );
961 	}
962 	else {
963 		switch ( tClass ) {
964 			case CKO_SECRET_KEY:
965 				logMsg( _("Secret Key: ") );
966 				break;
967 		}
968 
969 		if ( tKeyList[ 5 ].ulValueLen > 0 )
970 			logMsg( _("Type: %ld"), tType );
971 		if ( tKeyList[ 4 ].ulValueLen > 0 )
972 			logMsg( _(", Label: '%s'"), pszLabel );
973 
974 		logMsg( "\n" );
975 	}
976 
977 	return rv;
978 }
979 
980 /*
981  * displayObject
982  *   Format and display objects.
983  */
984 CK_RV
displayObject(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,int a_bExtended)985 displayObject( CK_SESSION_HANDLE  a_hSession,
986                CK_OBJECT_HANDLE   a_hObject,
987 	       int                a_bExtended ) {
988 
989 	CK_RV            rv;
990 	CK_OBJECT_CLASS  tClass;
991 	CK_ATTRIBUTE     tAttr[] = {
992 			{ CKA_CLASS, &tClass, sizeof( tClass ) },
993 		};
994 	CK_ULONG         ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
995 
996 	// Retrieve the class attribute of the object
997 	rv = getObjectAttributes( a_hSession, a_hObject, tAttr, ulAttrCount );
998 	if ( rv != CKR_OK )
999 		return rv;
1000 
1001 	// Use the object class to determine how to format it for display
1002 	switch ( tClass ) {
1003 		case CKO_DATA:
1004 			logMsg( _("Data object\n") );
1005 			break;
1006 
1007 		case CKO_CERTIFICATE:
1008 			displayCertObject( a_hSession, a_hObject, a_bExtended );
1009 			break;
1010 
1011 		case CKO_PUBLIC_KEY:
1012 		case CKO_PRIVATE_KEY:
1013 			displayAsymKeyObject( a_hSession, a_hObject, a_bExtended );
1014 			break;
1015 
1016 		case CKO_SECRET_KEY:
1017 			displaySymKeyObject( a_hSession, a_hObject, a_bExtended );
1018 			break;
1019 
1020 		case CKO_HW_FEATURE:
1021 		case CKO_DOMAIN_PARAMETERS:
1022 		default:
1023 			logMsg( _("Object class=%ld\n"), tClass );
1024 			break;
1025 	}
1026 
1027 	return rv;
1028 }
1029 
1030 /*
1031  * checkKey
1032  *   Check that the key object attributes match the key class
1033  *   and key type specified.
1034  */
1035 CK_RV
checkKey(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,CK_OBJECT_CLASS a_tKeyClass,CK_KEY_TYPE a_tKeyType)1036 checkKey( CK_SESSION_HANDLE  a_hSession,
1037           CK_OBJECT_HANDLE   a_hObject,
1038           CK_OBJECT_CLASS    a_tKeyClass,
1039           CK_KEY_TYPE        a_tKeyType ) {
1040 
1041 	CK_RV  rv;
1042 
1043 	CK_OBJECT_CLASS  tClass;
1044 	CK_KEY_TYPE      tType;
1045 	CK_ATTRIBUTE     tAttr[] = {
1046 			{ CKA_CLASS, &tClass, sizeof( tClass ) },
1047 			{ CKA_KEY_TYPE, &tType, sizeof( tType ) },
1048 		};
1049 	CK_ULONG         ulAttrCount = sizeof( tAttr ) / sizeof( CK_ATTRIBUTE );
1050 
1051 	// Retrieve the class attribute and key type attribute of the object
1052 	rv = getObjectAttributes( a_hSession, a_hObject, tAttr, ulAttrCount );
1053 	if ( rv != CKR_OK )
1054 		return rv;
1055 
1056 	if ( tClass != a_tKeyClass )
1057 		return CKR_GENERAL_ERROR;
1058 
1059 	if ( tType != a_tKeyType )
1060 		return CKR_GENERAL_ERROR;
1061 
1062 	return CKR_OK;
1063 }
1064 
1065 /*
1066  * encryptData
1067  *   Use a callback mechanism to encrypt some data.
1068  */
1069 CK_RV
encryptData(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,CK_MECHANISM * a_ptMechanism,TokenCryptGet a_fGet,TokenCryptPut a_fPut)1070 encryptData( CK_SESSION_HANDLE  a_hSession,
1071              CK_OBJECT_HANDLE   a_hObject,
1072              CK_MECHANISM      *a_ptMechanism,
1073              TokenCryptGet      a_fGet,
1074              TokenCryptPut      a_fPut ) {
1075 
1076 	CK_RV         rv;
1077 	CK_BBOOL      bCancel       = FALSE;
1078 
1079 	CK_BYTE      *pbInData      = NULL;
1080 	CK_ULONG      ulInDataLen   = 0;
1081 	CK_BBOOL      bContinue     = TRUE;
1082 
1083 	CK_BYTE      *pbBuffer      = NULL;
1084 	CK_ULONG      ulBufferLen   = 0;
1085 	CK_ULONG      ulOutDataLen  = 0;
1086 
1087 	if ( !g_bTokenOpen )
1088 		return CKR_GENERAL_ERROR;
1089 
1090 	// Check the key
1091 	rv = checkKey( a_hSession, a_hObject, CKO_SECRET_KEY, CKK_AES );
1092 	if ( rv != CKR_OK )
1093 		goto out;
1094 
1095 	// Initialize the encryption operation
1096 	rv = g_pFcnList->C_EncryptInit( a_hSession, a_ptMechanism, a_hObject );
1097 	pkcsResult( "C_EncryptInit", rv );
1098 	if ( rv != CKR_OK )
1099 		goto out;
1100 
1101 	while ( bContinue ) {
1102 		// Retrieve some data to encrypt
1103 		if ( a_fGet( &pbInData, &ulInDataLen, &bContinue, TRUE ) == -1 ) {
1104 			bCancel = TRUE;
1105 			goto out;
1106 		}
1107 
1108 		// Check the output buffer size needed
1109 		rv = g_pFcnList->C_EncryptUpdate( a_hSession, pbInData, ulInDataLen,
1110 			NULL, &ulOutDataLen );
1111 		pkcsResult( "C_EncryptUpdate", rv );
1112 		if ( rv != CKR_OK )
1113 			goto out;
1114 
1115 		// Check if a larger buffer is needed
1116 		if ( ulOutDataLen > ulBufferLen ) {
1117 			free( pbBuffer );
1118 			ulBufferLen = ulOutDataLen;
1119 			pbBuffer = calloc( 1, ulBufferLen );
1120 			if ( !pbBuffer ) {
1121 				logError( _("Unable to obtain memory for the encrypted data buffer\n") );
1122 				rv = CKR_HOST_MEMORY;
1123 				goto out;
1124 			}
1125 		}
1126 
1127 		// Encrypt the input data
1128 		rv = g_pFcnList->C_EncryptUpdate( a_hSession, pbInData, ulInDataLen,
1129 			pbBuffer, &ulOutDataLen );
1130 		pkcsResult( "C_EncryptUpdate", rv );
1131 		if ( rv != CKR_OK )
1132 			goto out;
1133 
1134 		if ( ulOutDataLen > 0 ) {
1135 			if ( a_fPut( pbBuffer, ulOutDataLen, bContinue, TRUE ) == -1 ) {
1136 				bCancel = TRUE;
1137 				goto out;
1138 			}
1139 		}
1140 	}
1141 
1142 out:
1143 	// For AES any remaining data will cause an error, so provide
1144 	// a buffer which will not be filled in anyway
1145 	ulOutDataLen = ulBufferLen;
1146 	rv = g_pFcnList->C_EncryptFinal( a_hSession, pbBuffer, &ulOutDataLen );
1147 	pkcsResult( "C_EncryptFinal", rv );
1148 
1149 	free( pbBuffer );
1150 
1151 	if ( bCancel )
1152 		rv = CKR_FUNCTION_CANCELED;
1153 
1154 	return rv;
1155 }
1156 
1157 /*
1158  * decryptData
1159  *   Use a callback mechanism to decrypt some data.
1160  */
1161 CK_RV
decryptData(CK_SESSION_HANDLE a_hSession,CK_OBJECT_HANDLE a_hObject,CK_MECHANISM * a_ptMechanism,TokenCryptGet a_fGet,TokenCryptPut a_fPut)1162 decryptData( CK_SESSION_HANDLE  a_hSession,
1163              CK_OBJECT_HANDLE   a_hObject,
1164              CK_MECHANISM      *a_ptMechanism,
1165              TokenCryptGet      a_fGet,
1166              TokenCryptPut      a_fPut ) {
1167 
1168 	CK_RV         rv;
1169 	CK_BBOOL      bCancel       = FALSE;
1170 
1171 	CK_BYTE      *pbInData      = NULL;
1172 	CK_ULONG      ulInDataLen   = 0;
1173 	CK_BBOOL      bContinue     = TRUE;
1174 
1175 	CK_BYTE      *pbBuffer      = NULL;
1176 	CK_ULONG      ulBufferLen   = 0;
1177 	CK_ULONG      ulOutDataLen  = 0;
1178 
1179 	if ( !g_bTokenOpen )
1180 		return CKR_GENERAL_ERROR;
1181 
1182 	// Check the key
1183 	rv = checkKey( a_hSession, a_hObject, CKO_SECRET_KEY, CKK_AES );
1184 	if ( rv != CKR_OK )
1185 		goto out;
1186 
1187 	// Initialize the decryption operation
1188 	rv = g_pFcnList->C_DecryptInit( a_hSession, a_ptMechanism, a_hObject );
1189 	pkcsResult( "C_DecryptInit", rv );
1190 	if ( rv != CKR_OK )
1191 		goto out;
1192 
1193 	while ( bContinue ) {
1194 		// Retrieve some data to encrypt
1195 		if ( a_fGet( &pbInData, &ulInDataLen, &bContinue, FALSE ) == -1 ) {
1196 			bCancel = TRUE;
1197 			goto out;
1198 		}
1199 
1200 		// Check the output buffer size needed
1201 		rv = g_pFcnList->C_DecryptUpdate( a_hSession, pbInData, ulInDataLen,
1202 			NULL, &ulOutDataLen );
1203 		pkcsResult( "C_DecryptUpdate", rv );
1204 		if ( rv != CKR_OK )
1205 			goto out;
1206 
1207 		// Check if a larger buffer is needed
1208 		if ( ulOutDataLen > ulBufferLen ) {
1209 			free( pbBuffer );
1210 			ulBufferLen = ulOutDataLen;
1211 			pbBuffer = calloc( 1, ulBufferLen );
1212 			if ( !pbBuffer ) {
1213 				logError( _("Unable to obtain memory for the encrypted data buffer\n") );
1214 				rv = CKR_HOST_MEMORY;
1215 				goto out;
1216 			}
1217 		}
1218 
1219 		// Decrypt the input data
1220 		rv = g_pFcnList->C_DecryptUpdate( a_hSession, pbInData, ulInDataLen,
1221 			pbBuffer, &ulOutDataLen );
1222 		pkcsResult( "C_DecryptUpdate", rv );
1223 		if ( rv != CKR_OK )
1224 			goto out;
1225 
1226 		if ( a_fPut( pbBuffer, ulOutDataLen, bContinue, FALSE ) == -1 ) {
1227 			bCancel = TRUE;
1228 			goto out;
1229 		}
1230 	}
1231 
1232 out:
1233 	// For AES any remaining data will cause an error, so provide
1234 	// a buffer which will not be filled in anyway
1235 	rv = g_pFcnList->C_DecryptFinal( a_hSession, pbBuffer, &ulOutDataLen );
1236 	pkcsResult( "C_DecryptFinal", rv );
1237 
1238 	free( pbBuffer );
1239 
1240 	if ( bCancel )
1241 		rv = CKR_FUNCTION_CANCELED;
1242 
1243 	return rv;
1244 }
1245 
1246 /*
1247  * isTokenInitialized
1248  *   Returns an indicator as to whether the TPM token has been initialized.
1249  */
1250 BOOL
isTokenInitialized()1251 isTokenInitialized( ) {
1252 
1253 	if ( g_bTokenOpen && ( g_tToken.flags & CKF_TOKEN_INITIALIZED ) )
1254 		return TRUE;
1255 
1256 	return FALSE;
1257 }
1258 
1259 /*
1260  * getMinPinLen
1261  *   Returns the the minimum PIN length that the TPM token accepts.
1262  */
1263 int
getMinPinLen()1264 getMinPinLen( ) {
1265 
1266 	if ( !g_bTokenOpen )
1267 		return 0;
1268 
1269 	return (int)g_tToken.ulMinPinLen;
1270 }
1271 
1272 /*
1273  * getMaxPinLen
1274  *   Returns the the maximum PIN length that the TPM token accepts.
1275  */
1276 int
getMaxPinLen()1277 getMaxPinLen( ) {
1278 
1279 	if ( !g_bTokenOpen )
1280 		return 0;
1281 
1282 	return (int)g_tToken.ulMaxPinLen;
1283 }
1284