📄 dev_pk11.c
字号:
void deviceEndPKCS11( void )
{
int i;
for( i = 0; i < MAX_PKCS11_DRIVERS; i++ )
{
if( pkcs11InfoTbl[ i ].hPKCS11 != NULL_INSTANCE )
{
pkcs11InfoTbl[ i ].pC_Finalize( NULL_PTR );
DynamicUnload( pkcs11InfoTbl[ i ].hPKCS11 );
}
pkcs11InfoTbl[ i ].hPKCS11 = NULL_INSTANCE;
}
pkcs11Initialised = FALSE;
}
void deviceInitPKCS11( void )
{
int tblIndex = 0, optionIndex;
/* If we've previously tried to init the drivers, don't try it again */
if( pkcs11Initialised )
return;
memset( pkcs11InfoTbl, 0, sizeof( pkcs11InfoTbl ) );
/* Try and link in each driver specified in the config options. Since
this is a general systemwide config option, we always query the built-
in default user object */
for( optionIndex = 0; optionIndex < MAX_PKCS11_DRIVERS; optionIndex++ )
{
RESOURCE_DATA msgData;
char deviceDriverName[ MAX_PATH_LENGTH + 1 ];
int status;
setResourceData( &msgData, deviceDriverName, MAX_PATH_LENGTH );
status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
optionIndex + CRYPT_OPTION_DEVICE_PKCS11_DVR01 );
if( cryptStatusError( status ) )
continue;
deviceDriverName[ msgData.length ] = '\0';
status = loadPKCS11driver( &pkcs11InfoTbl[ tblIndex++ ],
deviceDriverName );
if( cryptStatusOK( status ) )
pkcs11Initialised = TRUE;
}
}
#else
void deviceInitPKCS11( void )
{
/* If we've previously tried to init the drivers, don't try it again */
if( pkcs11Initialised )
return;
if( C_Initialize( NULL_PTR ) != CKR_OK )
return;
pkcs11Initialised = TRUE;
}
void deviceEndPKCS11( void )
{
if( pkcs11Initialised )
C_Finalize( NULL_PTR );
pkcs11Initialised = FALSE;
}
#endif /* DYNAMIC_LOAD */
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Map a PKCS #11-specific error to a cryptlib error */
static int mapError( DEVICE_INFO *deviceInfo, const CK_RV errorCode,
const int defaultError )
{
deviceInfo->errorCode = ( int ) errorCode;
switch( ( int ) errorCode )
{
case CKR_OK:
return( CRYPT_OK );
case CKR_HOST_MEMORY:
case CKR_DEVICE_MEMORY:
return( CRYPT_ERROR_MEMORY );
case CKR_DEVICE_ERROR:
case CKR_DEVICE_REMOVED:
return( CRYPT_ERROR_SIGNALLED );
case CKR_PIN_INCORRECT:
case CKR_PIN_INVALID:
case CKR_PIN_LEN_RANGE:
return( CRYPT_ERROR_WRONGKEY );
case CKR_SIGNATURE_INVALID:
return( CRYPT_ERROR_SIGNATURE );
case CKR_TOKEN_WRITE_PROTECTED:
case CKR_USER_NOT_LOGGED_IN:
case CKR_INFORMATION_SENSITIVE:
return( CRYPT_ERROR_PERMISSION );
case CKR_DATA_LEN_RANGE:
return( CRYPT_ERROR_OVERFLOW );
case CKR_USER_ALREADY_LOGGED_IN:
return( CRYPT_ERROR_INITED );
case CKR_USER_PIN_NOT_INITIALIZED:
return( CRYPT_ERROR_NOTINITED );
}
return( defaultError );
}
/* Find an object based on a given template. There are two variations of
this, one which finds one and only one object, and the other which
returns the first object it finds without treating the presence of
multiple objects as an error.
The way in which this call works has special significance, there are PKCS
#11 implementations which don't allow any other calls during the init/find/
final sequence, so the code is structured to always call them one after
the other without any intervening calls. In addition some drivers are
confused over whether they're 1.x or 2.x and may or may not implement
C_FindObjectsFinal(). Because of this we call it if it exists, if it
doesn't we assume the driver can handle cleanup itself (this situation
shouldn't occur because we've checked for 1.x drivers earlier, but there
are one or two drivers where it does happen) */
static int findDeviceObjects( DEVICE_INFO *deviceInfo,
CK_OBJECT_HANDLE *hObject,
const CK_ATTRIBUTE *template,
const CK_ULONG templateCount,
const BOOLEAN onlyOne )
{
CK_OBJECT_HANDLE hObjectArray[ 2 ];
CK_ULONG ulObjectCount;
CK_RV status;
status = C_FindObjectsInit( deviceInfo->deviceHandle,
( CK_ATTRIBUTE_PTR ) template,
templateCount );
if( status == CKR_OK )
{
status = C_FindObjects( deviceInfo->deviceHandle, hObjectArray,
2, &ulObjectCount );
if( C_FindObjectsFinal != NULL )
C_FindObjectsFinal( deviceInfo->deviceHandle );
}
if( status != CKR_OK )
return( mapError( deviceInfo, status, CRYPT_ERROR_NOTFOUND ) );
if( !ulObjectCount )
return( CRYPT_ERROR_NOTFOUND );
if( ulObjectCount > 1 && onlyOne )
return( CRYPT_ERROR_DUPLICATE );
if( hObject != NULL )
*hObject = hObjectArray[ 0 ];
return( CRYPT_OK );
}
static int findObject( DEVICE_INFO *deviceInfo, CK_OBJECT_HANDLE *hObject,
const CK_ATTRIBUTE *template,
const CK_ULONG templateCount )
{
return( findDeviceObjects( deviceInfo, hObject,
template, templateCount, TRUE ) );
}
static int findObjectEx( DEVICE_INFO *deviceInfo, CK_OBJECT_HANDLE *hObject,
const CK_ATTRIBUTE *template,
const CK_ULONG templateCount )
{
return( findDeviceObjects( deviceInfo, hObject,
template, templateCount, FALSE ) );
}
/* Set up certificate information and load it into the card */
static int updateCertificate( DEVICE_INFO *deviceInfo,
const CRYPT_HANDLE iCryptHandle )
{
static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
static const CK_BBOOL bTrue = TRUE;
CK_ATTRIBUTE certTemplate[] = {
{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
{ CKA_ID, NULL_PTR, 0 },
{ CKA_SUBJECT, NULL_PTR, 0 },
{ CKA_ISSUER, NULL_PTR, 0 },
{ CKA_SERIAL_NUMBER, NULL_PTR, 0 },
{ CKA_VALUE, NULL_PTR, 0 },
};
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
{ CKA_ID, NULL_PTR, 0 }
};
CK_OBJECT_HANDLE hObject;
CK_RV status;
RESOURCE_DATA msgData;
STREAM stream;
BYTE keyID[ CRYPT_MAX_HASHSIZE ], certBuffer[ MAX_BUFFER_SIZE ];
BYTE sBuffer[ MAX_BUFFER_SIZE ], iAndSBuffer[ MAX_BUFFER_SIZE ];
BYTE *sBufPtr = sBuffer, *iAndSBufPtr = iAndSBuffer;
BYTE *certBufPtr = certBuffer;
int length, cryptStatus;
/* Get the key ID for the cert and use it to locate the corresponding
public or private key object. This is used both as a check to ensure
that the certificate corresponds to a key in the device and to allow
further attributes used for the certificate to be copied from the key.
In theory this would allow us to read the label from the key so that
we can reuse it for the cert, but there doesn't seem to be any good
reason for this and it could lead to problems with multiple certs with
the same labels so we don't do it */
setResourceData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
if( cryptStatusError( cryptStatus ) )
return( CRYPT_ARGERROR_NUM1 );
keyTemplate[ 1 ].pValue = msgData.data;
keyTemplate[ 1 ].ulValueLen = msgData.length;
cryptStatus = findObject( deviceInfo, &hObject, keyTemplate, 2 );
if( cryptStatusError( cryptStatus ) )
{
/* Couldn't find a private key with this ID, try for a public key */
keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &pubkeyClass;
cryptStatus = findObject( deviceInfo, &hObject, keyTemplate, 2 );
}
if( cryptStatusError( cryptStatus ) )
return( CRYPT_ERROR_NOTFOUND );
certTemplate[ 3 ].pValue = msgData.data;
certTemplate[ 3 ].ulValueLen = msgData.length;
/* Get the subjectName from the cert */
setResourceData( &msgData, NULL, 0 );
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SUBJECT );
if( cryptStatusOK( cryptStatus ) && msgData.length > MAX_BUFFER_SIZE && \
( sBufPtr = malloc( msgData.length ) ) == NULL )
cryptStatus = CRYPT_ERROR_MEMORY;
if( cryptStatusOK( cryptStatus ) )
{
msgData.data = sBufPtr;
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_SUBJECT );
}
if( cryptStatusError( cryptStatus ) )
{
if( sBufPtr != sBuffer && sBufPtr != NULL )
free( sBufPtr );
return( cryptStatus );
}
certTemplate[ 4 ].pValue = msgData.data;
certTemplate[ 4 ].ulValueLen = msgData.length;
/* Get the issuerAndSerialNumber from the cert */
setResourceData( &msgData, NULL, 0 );
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( cryptStatus ) && msgData.length > MAX_BUFFER_SIZE && \
( iAndSBufPtr = malloc( msgData.length ) ) == NULL )
cryptStatus = CRYPT_ERROR_MEMORY;
if( cryptStatusOK( cryptStatus ) )
{
msgData.data = iAndSBufPtr;
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
}
if( cryptStatusError( cryptStatus ) )
{
if( sBufPtr != sBuffer )
free( sBufPtr );
if( iAndSBufPtr != iAndSBuffer && iAndSBufPtr != NULL )
free( iAndSBufPtr );
return( cryptStatus );
}
sMemConnect( &stream, iAndSBufPtr, msgData.length );
readSequence( &stream, NULL );
certTemplate[ 5 ].pValue = sMemBufPtr( &stream );
readSequence( &stream, &length );
certTemplate[ 5 ].ulValueLen = ( int ) sizeofObject( length );
sSkip( &stream, length );
certTemplate[ 6 ].pValue = sMemBufPtr( &stream );
readTag( &stream );
certTemplate[ 6 ].ulValueLen = \
( int ) sizeofObject( readShortLength( &stream ) );
assert( sStatusOK( &stream ) );
sMemDisconnect( &stream );
/* Get the certificate data */
setResourceData( &msgData, NULL, 0 );
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENC_CERT );
if( cryptStatusOK( cryptStatus ) && msgData.length > MAX_BUFFER_SIZE && \
( certBufPtr = malloc( msgData.length ) ) == NULL )
cryptStatus = CRYPT_ERROR_MEMORY;
if( cryptStatusOK( cryptStatus ) )
{
msgData.data = certBufPtr;
cryptStatus = krnlSendMessage( iCryptHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENC_CERT );
}
if( cryptStatusError( cryptStatus ) )
{
if( sBufPtr != sBuffer )
free( sBufPtr );
if( iAndSBufPtr != iAndSBuffer )
free( iAndSBufPtr );
if( certBufPtr != certBuffer && certBufPtr != NULL )
free( certBufPtr );
return( cryptStatus );
}
certTemplate[ 7 ].pValue = msgData.data;
certTemplate[ 7 ].ulValueLen = msgData.length;
/* We've finally got everything available, try and update the device with
the certificate data. In theory we should also set CKA_PRIVATE = FALSE
but the Dallas iButton driver doesn't allow this so we have to rely on
drivers doing the right thing with the default setting */
#ifndef NO_UPDATE
status = C_CreateObject( deviceInfo->deviceHandle,
( CK_ATTRIBUTE_PTR ) certTemplate, 8,
&hObject );
if( status != CKR_OK )
cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
#endif /* NO_UPDATE */
/* Clean up */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -