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 */ 32char * g_pszSoLib = TPM_OPENCRYPTOKI_SO; 33void * g_pSoLib = NULL; // Handle of libopencryptoki library 34CK_FUNCTION_LIST_PTR g_pFcnList = NULL; // Function List 35 36BOOL g_bInit = FALSE; // Indicates if C_Initialize has been called 37BOOL g_bTokenOpen = FALSE; // Indicates if the token has been opened 38CK_SLOT_ID g_tSlotId; // Slot ID of the TPM token 39CK_TOKEN_INFO g_tToken; // TPM token information 40 41 42void 43pkcsDebug( const char *a_pszName, 44 CK_RV a_tResult ) { 45 46 logDebug( _("%s success\n"), a_pszName ); 47} 48 49void 50pkcsError( 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 56void 57pkcsResult( 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 66void 67pkcsResultException( 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 */ 81void 82pkcsSlotInfo(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 */ 107void 108pkcsTokenInfo(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 */ 140CK_RV 141openToken( 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 256out: 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 */ 277CK_RV 278closeToken( ) { 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 */ 303CK_RV 304initToken( 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 */ 321CK_RV 322openTokenSession( 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 */ 341CK_RV 342closeTokenSession( 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 */ 359CK_RV 360closeAllTokenSessions( ) { 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 */ 377CK_RV 378loginToken( 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 */ 396CK_RV 397initPin( 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 */ 415CK_RV 416setPin( 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 */ 437CK_RV 438generateKey( 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 */ 460CK_RV 461createObject( 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 */ 481CK_RV 482destroyObject( 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 */ 501CK_RV 502getObjectAttributes( 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 */ 523CK_RV 524findObjects( 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 579done: 580 // Terminate the find operation 581 rv_temp = g_pFcnList->C_FindObjectsFinal( a_hSession ); 582 pkcsResult( "C_FindObjectsFinal", rv_temp ); 583 584out: 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 */ 595void 596displayByteArray( 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 */ 617CK_RV 618displayCertObject( 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 */ 801CK_RV 802displayAsymKeyObject( 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 */ 906CK_RV 907displaySymKeyObject( 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 */ 984CK_RV 985displayObject( 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 */ 1035CK_RV 1036checkKey( 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 */ 1069CK_RV 1070encryptData( 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 1142out: 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 */ 1161CK_RV 1162decryptData( 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 1232out: 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 */ 1250BOOL 1251isTokenInitialized( ) { 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 */ 1263int 1264getMinPinLen( ) { 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 */ 1276int 1277getMaxPinLen( ) { 1278 1279 if ( !g_bTokenOpen ) 1280 return 0; 1281 1282 return (int)g_tToken.ulMaxPinLen; 1283} 1284