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