📄 dev_pk11.c
字号:
the move to user state is automatic once the user PIN is set by the
SO */
if( type == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR )
{
/* Make sure that there's an SSO PIN present from a previous device
initialisation */
if( strlen( pkcs11Info->defaultSSOPIN ) <= 0 )
{
setErrorInfo( deviceInfo, CRYPT_DEVINFO_INITIALISE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_NOTINITED );
}
/* Change the SSO PIN from the init PIN. Once we've done this we
clear the initial SSO PIN, since it's no longer valid in the new
state */
status = C_SetPIN( pkcs11Info->hSession, pkcs11Info->defaultSSOPIN,
strlen( pkcs11Info->defaultSSOPIN ),
( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );
zeroise( pkcs11Info->defaultSSOPIN, CRYPT_MAX_TEXTSIZE );
return( mapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
}
if( type == CRYPT_DEVINFO_SET_AUTHENT_USER )
{
status = C_InitPIN( pkcs11Info->hSession, ( CK_CHAR_PTR ) data,
( CK_ULONG ) dataLength );
return( mapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
}
/* Handle initialisation and zeroisation */
if( type == CRYPT_DEVINFO_INITIALISE || \
type == CRYPT_DEVINFO_ZEROISE )
{
CK_SESSION_HANDLE hSession;
CK_CHAR label[ 32 ];
/* If there's a session active with the device, log out and terminate
the session, since the token init will reset this */
if( pkcs11Info->hSession != CRYPT_ERROR )
{
C_Logout( pkcs11Info->hSession );
C_CloseSession( pkcs11Info->hSession );
pkcs11Info->hSession = CRYPT_ERROR;
}
/* Initialise/clear the device, setting the initial SSO PIN */
memset( label, ' ', 32 );
status = C_InitToken( pkcs11Info->slotID,
( CK_CHAR_PTR ) data,
( CK_ULONG ) dataLength, label );
if( status != CKR_OK )
return( mapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
/* Reopen the session with the device */
status = C_OpenSession( pkcs11Info->slotID,
CKF_RW_SESSION | CKF_SERIAL_SESSION,
NULL_PTR, NULL_PTR, &hSession );
if( status != CKR_OK )
return( mapError( pkcs11Info, status, CRYPT_ERROR_OPEN ) );
pkcs11Info->hSession = hSession;
/* If it's a straight zeroise, we're done */
if( type == CRYPT_DEVINFO_ZEROISE )
return( CRYPT_OK );
/* We're initialising it, log in as supervisor. In theory we could
also set the initial user PIN to the same as the SSO PIN at this
point because the user usually won't be aware of the presence of
an SSO role or the need to set a PIN for it, but this can run into
problems with tokens that only allow the user PIN to be modified
by the SSO after they've set it for the first time, so if the user
*is* aware of the existence of an SSO role then once they log in
as SSO they can no longer set the user PIN */
status = C_Login( pkcs11Info->hSession, CKU_SO,
( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );
if( status != CKR_OK )
{
C_Logout( pkcs11Info->hSession );
C_CloseSession( pkcs11Info->hSession );
pkcs11Info->hSession = CRYPT_ERROR;
return( mapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
}
/* Remember the default SSO PIN for use with a future C_SetPIN() */
memcpy( pkcs11Info->defaultSSOPIN, data, dataLength );
pkcs11Info->defaultSSOPIN[ dataLength ] = '\0';
/* We're logged in and ready to go */
deviceInfo->flags |= DEVICE_LOGGEDIN;
return( CRYPT_OK );
}
/* Handle high-reliability time */
if( type == CRYPT_IATTRIBUTE_TIME )
{
CK_TOKEN_INFO tokenInfo;
time_t *timePtr = ( time_t * ) data, theTime;
/* Get the token's time, returned as part of the token info
structure */
status = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );
if( status != CKR_OK )
return( mapError( pkcs11Info, status, CRYPT_ERROR_SIGNALLED ) );
if( ( theTime = getTokenTime( &tokenInfo ) ) < MIN_TIME_VALUE )
return( CRYPT_ERROR_NOTAVAIL );
*timePtr = getTime();
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL ); /* Get rid of compiler warning */
}
/****************************************************************************
* *
* Misc.Device Interface Routines *
* *
****************************************************************************/
/* Get random data from the device */
static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
const int length )
{
CK_RV status;
PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
status = C_GenerateRandom( pkcs11Info->hSession, buffer, length );
return( mapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
}
/* Get the label for an object. We can't use a dynBuf for this because it's
a PKCS #11 attribute rather than a cryptlib attribute */
static int getObjectLabel( PKCS11_INFO *pkcs11Info,
const CK_OBJECT_HANDLE hObject,
char *label, int *labelLength )
{
CK_ATTRIBUTE keyLabelTemplate = \
{ CKA_LABEL, NULL_PTR, 0 };
CK_RV status;
char labelBuffer[ CRYPT_MAX_TEXTSIZE ], *labelPtr = labelBuffer;
status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
&keyLabelTemplate, 1 );
if( status == CKR_OK )
{
if( keyLabelTemplate.ulValueLen > CRYPT_MAX_TEXTSIZE && \
( labelPtr = clAlloc( "getObjectLabel", \
( size_t ) ( keyLabelTemplate.ulValueLen ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
keyLabelTemplate.pValue = labelPtr;
status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
&keyLabelTemplate, 1 );
}
if( status != CKR_OK )
{
*labelLength = 0;
if( label != NULL )
label[ 0 ] = '\0';
}
else
{
*labelLength = min( keyLabelTemplate.ulValueLen, CRYPT_MAX_TEXTSIZE );
if( label != NULL )
memcpy( label, labelPtr, *labelLength );
}
if( labelPtr != labelBuffer )
clFree( "getObjectLabel", labelPtr );
return( mapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
}
/* Instantiate a cert object from a handle */
static int instantiateCert( PKCS11_INFO *pkcs11Info,
const CK_OBJECT_HANDLE hCertificate,
CRYPT_CERTIFICATE *iCryptCert,
const BOOLEAN createContext )
{
CK_ATTRIBUTE dataTemplate = \
{ CKA_VALUE, NULL_PTR, 0 };
CK_RV status;
MESSAGE_CREATEOBJECT_INFO createInfo;
BYTE buffer[ MAX_BUFFER_SIZE ], *bufPtr = buffer;
int cryptStatus;
*iCryptCert = CRYPT_ERROR;
/* Fetch the cert data into local memory. We can't use a dynBuf for
this because it's a PKCS #11 attribute rather than a cryptlib
attribute */
status = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,
&dataTemplate, 1 );
if( status == CKR_OK )
{
if( dataTemplate.ulValueLen > MAX_BUFFER_SIZE && \
( bufPtr = clAlloc( "instantiateCert", \
( size_t ) ( dataTemplate.ulValueLen ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
dataTemplate.pValue = bufPtr;
status = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,
&dataTemplate, 1 );
}
if( status != CKR_OK )
{
if( bufPtr != buffer )
clFree( "instantiateCert", bufPtr );
return( mapError( pkcs11Info, status, CRYPT_ERROR_NOTFOUND ) );
}
/* Import the cert as a cryptlib object */
setMessageCreateObjectIndirectInfo( &createInfo, bufPtr,
dataTemplate.ulValueLen,
CRYPT_CERTTYPE_CERTIFICATE );
createInfo.arg1 = createContext ? CRYPT_CERTTYPE_CERTIFICATE : \
CERTFORMAT_DATAONLY;
cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( bufPtr != buffer )
clFree( "instantiateCert", bufPtr );
if( cryptStatusOK( cryptStatus ) )
*iCryptCert = createInfo.cryptHandle;
return( cryptStatus );
}
/* Find a certificate object based on various search criteria:
- Find cert matching a given label - certFromLabel()
- Find cert matching a given ID - certFromID()
- Find cert matching the ID of an object hObject - certFromObject()
- Find cert matching a supplied template - certFromTemplate()
- Find any X.509 cert - certFromLabel(), no label supplied.
These are general-purpose functions whose behaviour can be modified through
the following action codes */
typedef enum {
FINDCERT_NORMAL, /* Instantiate standard cert+context */
FINDCERT_DATAONLY, /* Instantiate data-only cert */
FINDCERT_P11OBJECT /* Return handle to PKCS #11 object */
} FINDCERT_ACTION;
static int findCertFromLabel( PKCS11_INFO *pkcs11Info,
const char *label, const int labelLength,
CRYPT_CERTIFICATE *iCryptCert,
const FINDCERT_ACTION findAction )
{
static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
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_LABEL, NULL, 0 }
};
CK_OBJECT_HANDLE hCertificate;
int cryptStatus;
*iCryptCert = CRYPT_ERROR;
/* Try and find the cert with the given label */
if( label != NULL )
{
certTemplate[ 2 ].pValue = ( CK_VOID_PTR ) label;
certTemplate[ 2 ].ulValueLen = labelLength;
}
cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate,
( label == NULL ) ? 2 : 3 );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
if( findAction == FINDCERT_P11OBJECT )
{
*iCryptCert = hCertificate;
return( CRYPT_OK );
}
return( instantiateCert( pkcs11Info, hCertificate, iCryptCert,
( findAction == FINDCERT_NORMAL ) ? \
TRUE : FALSE ) );
}
static int findCertFromID( PKCS11_INFO *pkcs11Info,
const void *certID,
const int certIDlength,
CRYPT_CERTIFICATE *iCryptCert,
const FINDCERT_ACTION findAction )
{
static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
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_ID, ( CK_VOID_PTR ) certID, certIDlength }
};
CK_OBJECT_HANDLE hCertificate;
int cryptStatus;
*iCryptCert = CRYPT_ERROR;
/* Try and find the cert with the given ID */
cryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
if( findAction == FINDCERT_P11OBJECT )
{
*iCryptCert = hCertificate;
return( CRYPT_OK );
}
return( instantiateCert( pkcs11Info, hCertificate, iCryptCert,
( findAction == FINDCERT_NORMAL ) ? \
TRUE : FALSE ) );
}
static int findCertFromObject( PKCS11_INFO *pkcs11Info,
const CK_OBJECT_HANDLE hObject,
CRYPT_CERTIFICATE *iCryptCert,
const FINDCERT_ACTION findAction )
{
static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
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_ID, NULL, 0 }
};
CK_ATTRIBUTE idTemplate = \
{ CKA_ID, NULL_PTR, 0 };
CK_RV status;
BYTE buffer[ MAX_BUFFER_SIZE ], *bufPtr = buffer;
int cryptStatus;
*iCryptCert = CRYPT_ERROR;
/* We're looking for a cert whose ID matches the object, read the key ID
from the device. We can't use a dynBuf for this because it's a PKCS
#11 attribute rather than a cryptlib attribute */
status = C_GetAttributeValue( pkcs11Info->hSession, hObject,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -