📄 testdev.c
字号:
/****************************************************************************
* *
* cryptlib Device Test Routines *
* Copyright Peter Gutmann 1997-2003 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "../test/test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged MSC include handling */
#if defined( __MVS__ ) || defined( __VMCMS__ )
/* Suspend conversion of literals to ASCII. */
#pragma convlit( suspend )
#endif /* EBCDIC systems */
/* Set the following to a nonzero value to test cryptlib's device init
capability. THIS WILL ZEROISE/ERASE THE DEVICE BEING TESTED AS A PART
OF THE PROCESS. All data contained in it will be destroyed */
#define TEST_INITIALISE_CARD 0
/* Set the following to test the keygen capabilities of the device. If the
device is very slow (e.g. a smart card), you can set this once initially
to generate the test keys and then clear it to use the initially-
generated keys from then on */
#define TEST_KEYGEN 0
/****************************************************************************
* *
* Device Information *
* *
****************************************************************************/
/* Device information tables for PKCS #11 device types. This lists all the
devices we know about and can check for. If you have a PKCS #11 device
that isn't listed below, you need to add an entry with its name and a
password and key object label usable for testing to the table, and also
add the name of the driver as a CRYPT_OPTION_DEVICE_PKCS11_DVRxx entry so
cryptlib can load the appropriate driver for it. To add this, use the
updateConfig() function in testlib.c, see the code comments there for more
details.
The SEIS EID cards name their private key objects slightly differently
from the name used in the software-only eID driver, if you're using a
card-based version you need to switch the commented lines below to the
alternate name.
The Rainbow iKey uses Datakey drivers, so the Datakey test below will work
for both Datakey cards/keys and iKeys.
The iD2 driver implements multiple virtual slots, one for each key type,
so the entry is given in the extended driver::slot name format to tell
cryptlib which slot to use.
To reset the Rainbow card after it locks up and stops responding to
commands, run /samples/cryptoki20/sample.exe, enter 1 CR, 4 CR, 5 CR,
7 CR 2 CR "rainbow" CR, g CR "test" CR q CR (you need to follow that
sequence exactly for it to work).
The presence of a device entry in this table doesn't necessarily mean
that the PKCS #11 driver that it comes with functions correctly, or at
all. In particular the ActivCard driver is so broken it's incredible it
works at all, the iButton driver is still in beta so it has some features
unimplemented, the Telesec driver is even more broken than the ActivCard
one (this one's so bad it doesn't even work with Netscape), and the
Utimaco driver apparently has some really strange bugs, as well as
screwing up Windows power management so that suspends either aren't
possible any more or will crash apps. At the other end of the scale the
Datakey, Eracom, iD2, and nCipher drivers are pretty good */
typedef struct {
const char *name;
const char *description;
const char *password;
const char *keyLabel;
} DEVICE_CONFIG_INFO;
static const DEVICE_CONFIG_INFO pkcs11DeviceInfo[] = {
{ "[Autodetect]", "Automatically detect device", "test", "Test user key" },
{ "ActivCard Cryptoki Library", "ActivCard", "test", "Test user key" },
{ "CryptoFlex", "CryptoFlex", "ABCD1234", "012345678901234567890123456789ME" },
{ "Cryptographic Token Interface", "AET SafeSign", "test", "Test user key" },
{ "Cryptoki for CardMan API", "Utimaco", "test", "Test user key" },
{ "Cryptoki for eID", "Nexus soft-token", "1234", "Private key" },
{ "Cryptoki for eID", "Nexus signature token", "1234", "eID private nonrepudiation key" },
{ "Cryptoki for eID", "Nexus signature token", "1234", "eID private key encipherment key" },
{ "CryptoKit Extended Version", "Eutron (via Cylink)", "12345678", "Test user key" },
{ "Datakey Cryptoki DLL - NETSCAPE", "Datakey pre-4.1, post-4.4 driver", "test", "Test user key" },
{ "Datakey Cryptoki DLL - Version", "Datakey 4.1-4.4 driver", "test", "Test user key" },
{ "Eracom Cryptoki", "Eracom", "test", "Test user key" },
{ "ERACOM Software Only", "Eracom 1.x soft-token", "0000", "Test user key" },
{ "Software Only", "Eracom 2.x soft-token", "0000", "Test user key" },
{ "G&D PKCS#11 Library", "Giesecke and Devrient", "test", "Test user key" },
{ "iButton", "Dallas iButton", "test", "Test user key" },
{ "iD2 Cryptographic Library::iD2 Smart Card (PIN1)", "iD2 signature token::Slot 1", "1234", "Digital Signature" },
{ "iD2 Cryptographic Library::iD2 Smart Card (PIN2)", "iD2 signature token::Slot 2", "5678", "Non Repudiation" },
{ "ISG", "CryptoSwift HSM", "test", "Test user key" },
{ "ISG Cryptoki API library", "CryptoSwift card", "test", "Test user key" },
{ "NShield 75", "nCipher", "test", "Test user key" },
{ "PKCS#11 Private Cryptoki", "GemSAFE", "1234", "Test user key" },
{ "Safelayer PKCS#11", "Safelayer", "test", "Test user key" },
{ "Schlumberger", "Schlumberger", "QWERTYUI", "Test user key" },
{ "SignLite security module", "IBM SignLite", "test", "Test user key" },
{ "Spyrus Rosetta", "Spyrus Rosetta", "test", "Test user key" },
{ "Spyrus Lynks", "Spyrus Lynks", "test", "Test user key" },
{ "TCrypt", "Telesec", "123456", "Test user key" },
{ "TrustCenter PKCS#11 Library", "GPKCS11", "12345678", "Test user key" },
{ NULL, NULL, NULL }
};
/* Device information for Fortezza cards */
#define FORTEZZA_ZEROISE_PIN "ZeroizedCard"
#define FORTEZZA_SSO_DEFAULT_PIN "Mosaic"
#define FORTEZZA_SSO_PIN "0000"
#define FORTEZZA_USER_PIN "0000"
static const DEVICE_CONFIG_INFO fortezzaDeviceInfo = \
{ "[Autodetect]", "Automatically detect device", FORTEZZA_USER_PIN, "Test user key" };
/* Device information for CryptoAPI */
static const DEVICE_CONFIG_INFO capiDeviceInfo[] = {
{ "[Autodetect]", "Automatically detect device", "test", "Test user key" },
{ "Microsoft Base Cryptographic Provider v1.0::User", "Microsoft Base Cryptographic Provider", "test", "Test user key" },
{ NULL, NULL, NULL }
};
/* Data used to create certs in the device */
static const CERT_DATA paaCertData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "NZ" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "Honest Dave's PAA" },
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, "Certification Policy Division" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "Dave the PAA" },
/* 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_ATTRIBUTE_NONE, IS_VOID }
};
static const CERT_DATA cACertData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "NZ" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "Dave's Wetaburgers and CA" },
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, "Certification Division" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "Dave Himself" },
/* 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 },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static const CERT_DATA userCertData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "NZ" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "Dave's Wetaburgers" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "Dave's key" },
/* X.509v3 general-purpose certificate */
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,
CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYENCIPHERMENT },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static const CERT_DATA userSigOnlyCertData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "NZ" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "Dave's Wetaburgers" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "Dave's signing key" },
/* X.509v3 signature-only certificate */
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static const CERT_DATA userKeyAgreeCertData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, "NZ" },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, "Dave's Wetaburgers" },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, "Dave's key agreement key" },
/* X.509v3 key agreement certificate */
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYAGREEMENT },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Delete leftover keys created during testing */
static void deleteTestKey( const CRYPT_DEVICE cryptDevice,
const char *keyName, const char *keyDescription )
{
if( cryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, keyName ) == CRYPT_OK )
printf( "(Deleted a %s key object, presumably a leftover from a "
"previous run).\n", keyDescription );
}
/* Create a key and certificate in a device */
static BOOLEAN createKey( const CRYPT_DEVICE cryptDevice,
const CRYPT_ALGO_TYPE cryptAlgo,
const char *description, const char *dumpName,
const CRYPT_CONTEXT signingKey )
{
CRYPT_CONTEXT cryptContext;
CRYPT_CERTIFICATE cryptCert;
BYTE certBuffer[ BUFFER_SIZE ], labelBuffer[ CRYPT_MAX_TEXTSIZE ];
const BOOLEAN isCA = ( signingKey == CRYPT_UNUSED ) ? TRUE : FALSE;
const CERT_DATA *certData = ( isCA ) ? cACertData : \
( cryptAlgo == CRYPT_ALGO_RSA ) ? userCertData : \
( cryptAlgo == CRYPT_ALGO_DSA ) ? userSigOnlyCertData : \
userKeyAgreeCertData;
int certificateLength, status;
sprintf( labelBuffer, "Test %s key", description );
/* Generate a key in the device */
printf( "Generating a %s key in the device...", description );
status = cryptDeviceCreateContext( cryptDevice, &cryptContext,
cryptAlgo );
if( cryptStatusError( status ) )
{
printf( "\ncryptDeviceCreateContext() failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL, labelBuffer,
strlen( labelBuffer ) );
status = cryptGenerateKey( cryptContext );
if( cryptStatusError( status ) )
{
cryptDestroyContext( cryptContext );
printf( "\ncryptGenerateKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( " succeeded." );
/* Create a certificate for the key */
printf( "Generating a certificate for the key..." );
cryptCreateCert( &cryptCert, CRYPT_UNUSED, ( isCA ) ? \
CRYPT_CERTTYPE_CERTIFICATE : CRYPT_CERTTYPE_CERTCHAIN );
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptCert, certData ) )
return( FALSE );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, isCA ? cryptContext : signingKey );
cryptDestroyContext( cryptContext );
if( cryptStatusError( status ) )
{
cryptDestroyCert( cryptCert );
printf( "\nCreation of certificate failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
puts( " succeeded." );
/* Dump the resulting cert for debugging */
if( dumpName != NULL )
{
status = cryptExportCert( certBuffer, &certificateLength, isCA ? \
CRYPT_CERTFORMAT_CERTIFICATE : CRYPT_CERTFORMAT_CERTCHAIN,
cryptCert );
if( cryptStatusOK( status ) )
debugDump( dumpName, certBuffer, certificateLength );
}
/* Update the key with the 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( " succeeded." );
return( TRUE );
}
/****************************************************************************
* *
* Device Logon/Initialisation *
* *
****************************************************************************/
/* Print information about a device and log in if necessary */
static const DEVICE_CONFIG_INFO *checkLogonDevice( const CRYPT_DEVICE cryptDevice,
const CRYPT_DEVICE_TYPE deviceType,
const DEVICE_CONFIG_INFO *deviceInfo,
const BOOLEAN isAutoDetect,
const BOOLEAN willInitialise )
{
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';
printf( "Device label is '%s'.\n", tokenLabel );
}
/* Check whether the device corresponds to a known device. We do this
because some devices require specific test passwords and whatnot in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -