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