📄 devices.c
字号:
cryptDestroyContext( cryptContext );
if( status == CRYPT_ERROR_PERMISSION )
isWriteProtected = TRUE;
}
/* To force the code not to try to create keys and certs in a writeable
device, uncomment the following line of code. This requires that keys/
certs of the required type are already present in the device */
/* KLUDGE_WARN( "write-protect status" );
isWriteProtected = TRUE; */
if( !isWriteProtected && TEST_KEYGEN )
{
/* If it's a device that we can initialise, go through a full
initialisation */
if( deviceType != CRYPT_DEVICE_CRYPTOAPI && TEST_INITIALISE_CARD )
{
status = initialiseDevice( cryptDevice, deviceType,
deviceInfo );
if( status == FALSE )
{
cryptDeviceClose( cryptDevice );
return( FALSE );
}
}
else
{
/* There may be test keys lying around from an earlier run, in
which case we try to delete them to make sure they won't
interfere with the current one */
deleteTestKey( cryptDevice, "Test CA key", "CA" );
deleteTestKey( cryptDevice, deviceInfo->keyLabel, "user" );
if( deviceType == CRYPT_DEVICE_PKCS11 )
{
deleteTestKey( cryptDevice, RSA_PUBKEY_LABEL, "RSA public" );
deleteTestKey( cryptDevice, RSA_PRIVKEY_LABEL, "RSA private" );
deleteTestKey( cryptDevice, DSA_PUBKEY_LABEL, "DSA public" );
deleteTestKey( cryptDevice, DSA_PRIVKEY_LABEL, "DSA private" );
deleteTestKey( cryptDevice, SYMMETRIC_KEY_LABEL, "symmetric" );
}
if( deviceType == CRYPT_DEVICE_FORTEZZA )
deleteTestKey( cryptDevice, "Test KEA key", "KEA" );
if( deviceType == CRYPT_DEVICE_CRYPTOAPI )
{
deleteTestKey( cryptDevice, "Encryption key", "RSA private" );
deleteTestKey( cryptDevice, "Signature key", "secondary RSA private" );
}
}
}
#ifdef TEST_DH
return( testLowlevel( cryptDevice, CRYPT_ALGO_DH, FALSE ) );
#endif /* TEST_DH */
/* Report what the device can do. This is intended mostly for simple
crypto accelerators and may fail with for devices that work only
with the higher-level functions centered around certificates,
signatures,and key wrapping, so we skip the tests for devices that
allow only high-level access */
#if TEST_ALGORITHMS
if( deviceType != CRYPT_DEVICE_FORTEZZA )
testResult = testDeviceCapabilities( cryptDevice, deviceName,
isWriteProtected );
#else
puts( "Skipping device algorithm tests." );
#endif /* TEST_ALGORITHMS */
/* If it's a smart device, try various device-specific operations */
if( deviceType == CRYPT_DEVICE_FORTEZZA || \
deviceType == CRYPT_DEVICE_PKCS11 || \
deviceType == CRYPT_DEVICE_CRYPTOAPI )
partialSuccess = testDeviceHighlevel( cryptDevice, deviceType,
deviceInfo->keyLabel, deviceInfo->password,
isWriteProtected );
/* Clean up */
status = cryptDeviceClose( cryptDevice );
if( cryptStatusError( status ) )
{
printf( "cryptDeviceClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
if( !testResult && !partialSuccess )
return( FALSE );
if( testResult && partialSuccess )
printf( "%s tests succeeded.\n\n", deviceName );
else
printf( "Some %s tests succeeded.\n\n", deviceName );
return( TRUE );
}
int testDevices( void )
{
int i, status;
/* Test Fortezza devices */
#if 0
status = testCryptoDevice( CRYPT_DEVICE_FORTEZZA, "Fortezza card",
&fortezzaDeviceInfo );
if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTAVAIL )
return( status );
#endif /* 0 */
/* Test PKCS #11 devices */
#if 1
for( i = 0; pkcs11DeviceInfo[ i ].name != NULL; i++ )
{
status = testCryptoDevice( CRYPT_DEVICE_PKCS11, "PKCS #11 crypto token",
&pkcs11DeviceInfo[ i ] );
if( cryptStatusError( status ) && \
!( status == CRYPT_ERROR_NOTAVAIL || \
( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )
return( status );
}
#endif /* 0 */
#if 0 /* For test purposes only to check CAPI data, don't use the CAPI code */
#ifdef __WINDOWS__
for( i = 0; capiDeviceInfo[ i ].name != NULL; i++ )
{
status = testCryptoDevice( CRYPT_DEVICE_CRYPTOAPI, "Microsoft CryptoAPI",
&capiDeviceInfo[ i ] );
if( cryptStatusError( status ) && \
!( status == CRYPT_ERROR_NOTAVAIL || \
( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )
return( status );
}
#endif /* __WINDOWS__ */
#endif /* 0 */
putchar( '\n' );
return( TRUE );
}
/****************************************************************************
* *
* Full Device Initialisation Test *
* *
****************************************************************************/
/* The following code takes two unitialised devices and turns one into a
fully initialised CA device, which then runs a PnP PKI session that turns
the other into a fully initialised user device.
The following configuration options can be used to change the beaviour of
the self-test, for example to run it on the local machine in loopback mode
vs. running on two distinct machines. Defining an IP address (or host
name) for SERVER_MACHINE_ADDRESS will have the client connect to that
address instead of running a local loopback test */
#if 0
#define SERVER_MACHINE_ADDRESS "161.5.99.22"
#define SERVER_MACHINE_PORT 4080
#define CLIENT_DEVICE_TYPE CRYPT_DEVICE_FORTEZZA
#define SERVER_DEVICE_TYPE CRYPT_DEVICE_FORTEZZA
#define CLIENT_ID "25CHS-UDQBU-BPASM"
#define CLIENT_AUTHENTICATOR "5ZCJ8-34A5C-YSXRD-C9EME"
#define CLIENT_TOKEN_SLOT CRYPT_USE_DEFAULT
#define NET_TIMEOUT 300
#else
#define SERVER_MACHINE_ADDRESS "localhost"
#define SERVER_MACHINE_PORT 80
#define CLIENT_DEVICE_TYPE CRYPT_DEVICE_FORTEZZA
#define SERVER_DEVICE_TYPE CRYPT_DEVICE_FORTEZZA
#define CLIENT_TOKEN_SLOT 1
#define NET_TIMEOUT CRYPT_USE_DEFAULT
#endif /* Loopback vs. general test */
/* Default PIN values */
#if CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA
#define DEFAULT_SSO_PIN FORTEZZA_SSO_DEFAULT_PIN
#else
#define DEFAULT_SSO_PIN "0000"
#endif /* Fortezza vs. PKCS #11 default SSO PINs */
#define SSO_PIN "0000"
#define USER_PIN "0000"
/* Set up a client/server to connect locally (usually) or to a custom
address and port if we're running on distinct machines. For the client
this simply tells it where to connect, for the server in loopback mode
this binds it to the local address so that we don't inadvertently open
up outside ports */
static BOOLEAN setConnectInfo( const CRYPT_SESSION cryptSession,
const char *address, const int port,
const int timeout )
{
int status;
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME,
address, strlen( address ) );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_SERVER_PORT, port );
if( cryptStatusOK( status ) && timeout != CRYPT_USE_DEFAULT )
{
cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,
NET_TIMEOUT );
status = cryptSetAttribute( cryptSession,
CRYPT_OPTION_NET_WRITETIMEOUT,
NET_TIMEOUT );
}
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute/AttributeString() failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
return( TRUE );
}
/* Create a CA cert in a device */
static const CERT_DATA rootCACertData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "AT" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "IAEA" },
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, "SGTIE" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "IAEA CA root" },
/* Self-signed X.509v3 CA certificate */
{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },
{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,
CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },
/* Access information */
{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_AUTHORITYINFO_RTCS },
{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, "http://localhost" },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static int createCACert( const CRYPT_DEVICE cryptDevice )
{
CRYPT_CONTEXT cryptContext;
CRYPT_CERTIFICATE cryptCert;
int status;
/* Generate a key in the device */
printf( "Generating a CA key in the device..." );
status = cryptDeviceCreateContext( cryptDevice, &cryptContext,
( SERVER_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA ) ? \
CRYPT_ALGO_DSA : CRYPT_ALGO_RSA );
if( cryptStatusError( status ) )
{
printf( "\ncryptDeviceCreateContext() failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
"CA key", strlen( "CA key" ) );
if( cryptStatusOK( status ) )
status = cryptGenerateKey( cryptContext );
if( cryptStatusError( status ) )
{
cryptDestroyContext( cryptContext );
printf( "\ncryptGenerateKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( " done." );
/* Create a certificate for the key */
printf( "Generating a CA certificate for the key..." );
status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( FALSE );
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptCert, rootCACertData, __LINE__ ) )
return( FALSE );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, cryptContext );
cryptDestroyContext( cryptContext );
if( cryptStatusError( status ) )
{
cryptDestroyCert( cryptCert );
printf( "\nCreation of certificate failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
puts( " done." );
/* Update the key with the CA cert */
printf( "Updating device with certificate..." );
status = cryptAddPublicKey( cryptDevice, cryptCert );
cryptDestroyCert( cryptCert );
if( cryptStatusError( status ) )
{
printf( "\ncryptAddPublicKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( " done." );
return( TRUE );
}
/* Connect to a device */
static int connectDevice( CRYPT_DEVICE *cryptDevice, CRYPT_DEVICE_TYPE type,
const int slotNo )
{
char buffer[ 128 ];
int status;
/* Clear return value */
*cryptDevice = -1;
/* Connect to the device */
if( slotNo == CRYPT_USE_DEFAULT )
{
printf( "Connecting to crypto device in default slot..." );
strcpy( buffer, "[Autodetect]" );
}
else
{
printf( "Connecting to crypto device in slot %d...", slotNo );
sprintf( buffer, "[Autodetect]::%d", slotNo );
}
status = cryptDeviceOpen( cryptDevice, CRYPT_UNUSED, type, buffer );
if( cryptStatusError( status ) )
{
if( status == CRYPT_ERROR_PARAM3 || status == CRYPT_ERROR_NOTFOUND )
puts( "\nDevice not detected, skipping test." );
else
printf( "\ncryptDeviceOpen() failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
puts( " done." );
return( TRUE );
}
/* Log on to a device */
static int logonDevice( const CRYPT_DEVICE cryptDevice, const char *userPIN )
{
char tokenLabel[ CRYPT_MAX_TEXTSIZE + 1 ];
int loggedOn, tokenLabelSize, status;
/* Tell the user what we're talking to */
status = cryptGetAttributeString( cryptDevice, CRYPT_DEVINFO_LABEL,
tokenLabel, &tokenLabelSize );
if( cryptStatusError( status ) )
puts( "(Device doesn't appear to have a label)." );
else
{
tokenLabel[ tokenLabelSize ] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -