int deviceInitHardware( void ) { CAPABILITY_INFO *capabilityInfo; static BOOLEAN initCalled = FALSE; int noCapabilities, i, status; /* If we've previously tried to initialise the hardware, don't try it again */ if( initCalled ) return( CRYPT_OK ); initCalled = TRUE; /* Get the hardware capability information */ status = hwGetCapabilities( &capabilityInfo, &noCapabilities ); if( cryptStatusError( status ) ) return( status ); ENSURES( noCapabilities > 0 && \ noCapabilities < MAX_DEVICE_CAPABILITIES ); /* Build the list of available capabilities */ memset( capabilityInfoList, 0, sizeof( CAPABILITY_INFO_LIST ) * MAX_DEVICE_CAPABILITIES ); for( i = 0; i < noCapabilities && \ capabilityInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE; i++ ) { REQUIRES( sanityCheckCapability( &capabilityInfo[ i ] ) ); capabilityInfoList[ i ].info = &capabilityInfo[ i ]; capabilityInfoList[ i ].next = NULL; if( i > 0 ) capabilityInfoList[ i - 1 ].next = &capabilityInfoList[ i ]; } ENSURES( i < noCapabilities ); return( CRYPT_OK ); }
static int getCapabilities( DEVICE_INFO *deviceInfo, const PKCS11_MECHANISM_INFO *mechanismInfoPtr, const int maxMechanisms ) { CAPABILITY_INFO_LIST *capabilityInfoListTail = \ ( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList; int i; assert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) ); assert( isReadPtr( mechanismInfoPtr, \ maxMechanisms * sizeof( PKCS11_MECHANISM_INFO ) ) ); static_assert( sizeof( CAPABILITY_INFO ) == sizeof( VARIABLE_CAPABILITY_INFO ), "Variable capability-info-struct" ); /* Find the end of the list to add new capabilities */ if( capabilityInfoListTail != NULL ) { while( capabilityInfoListTail->next != NULL ) capabilityInfoListTail = capabilityInfoListTail->next; } /* Add capability information for each recognised mechanism type */ for( i = 0; i < maxMechanisms && \ mechanismInfoPtr[ i ].mechanism != CKM_NONE; i++ ) { CAPABILITY_INFO_LIST *newCapabilityList; CAPABILITY_INFO *newCapability; const CRYPT_ALGO_TYPE cryptAlgo = mechanismInfoPtr[ i ].cryptAlgo; /* If the assertion below triggers then the PKCS #11 driver is broken since it's returning inconsistent information such as illegal key length data, conflicting algorithm information, etc etc. This assertion is included here to detect buggy drivers early on rather than forcing users to step through the PKCS #11 glue code to find out why an operation is failing. Because some tinkertoy implementations support only the bare minimum functionality (e.g.RSA private key ops and nothing else), we allow asymmetric functionality for PKCs */ newCapability = getCapability( deviceInfo, &mechanismInfoPtr[ i ], maxMechanisms - i ); if( newCapability == NULL ) continue; REQUIRES( sanityCheckCapability( newCapability ) ); if( ( newCapabilityList = \ clAlloc( "getCapabilities", \ sizeof( CAPABILITY_INFO_LIST ) ) ) == NULL ) { clFree( "getCapabilities", newCapability ); continue; } newCapabilityList->info = newCapability; newCapabilityList->next = NULL; if( deviceInfo->capabilityInfoList == NULL ) deviceInfo->capabilityInfoList = newCapabilityList; else capabilityInfoListTail->next = newCapabilityList; capabilityInfoListTail = newCapabilityList; /* Since there may be alternative mechanisms to the current one defined, we have to skip mechanisms until we find a ones for a new algorithm */ while( mechanismInfoPtr[ i + 1 ].cryptAlgo == cryptAlgo && \ i < maxMechanisms ) i++; ENSURES( i < maxMechanisms ); } ENSURES( i < maxMechanisms ); return( ( deviceInfo->capabilityInfoList == NULL ) ? CRYPT_ERROR : CRYPT_OK ); }