📄 testdev.c
字号:
/****************************************************************************
* *
* cryptlib Device Test Routines *
* Copyright Peter Gutmann 1997-2001 *
* *
****************************************************************************/
#ifdef _MSC_VER
#include "../cryptlib.h"
#include "../test/test.h"
#else
#include "cryptlib.h"
#include "test/test.h"
#endif /* Braindamaged MSC include handling */
/****************************************************************************
* *
* Crypto Device Routines Test *
* *
****************************************************************************/
#ifdef TEST_DEVICE
/* 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
which 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 (note that 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 which 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, and iD2 drivers are pretty good */
typedef struct {
const char *name;
const char *password;
const char *keyLabel;
} DEVICE_INFO;
static const DEVICE_INFO pkcs11DeviceInfo[] = {
{ "ActivCard Cryptoki Library", "test", "Test user key" },
{ "CryptoFlex", "ABCD1234", "012345678901234567890123456789ME" },
{ "Cryptoki for CardMan API", "test", "Test user key" }, /* Utimaco */
{ "Cryptoki for eID", "1234", "Private key" }, /* Nexus PKCS #12 token */
{ "Cryptoki for eID", "1234", "eID private nonrepudiation key" }, /* Smart card key */
{ "Cryptoki for eID", "1234", "eID private key encipherment key" }, /* Smart card key */
{ "CryptoKit Extended Version", "12345678", "Test user key" },/* Eutron (via Cylink) */
{ "Datakey Cryptoki DLL - NETSCAPE", "test", "Test user key" }, /* Pre-4.1, post-4.4 driver */
{ "Datakey Cryptoki DLL - Version", "test", "Test user key" }, /* 4.1-4.4 driver */
{ "Eracom Cryptoki", "test", "Test user key" }, /* Eracom */
{ "ERACOM Software Only", "0000", "Test user key" }, /* Eracom 1.x soft-PKCS11 */
{ "Software Only", "0000", "Test user key" }, /* Eracom 2.x soft-PKCS11 */
{ "iButton", "test", "Test user key" }, /* Dallas iButton */
{ "iD2 Cryptographic Library::iD2 Smart Card (PIN1)", "1234", "Digital Signature" },
{ "iD2 Cryptographic Library::iD2 Smart Card (PIN2)", "5678", "Non Repudiation" },
{ "ISG", "test", "Test user key" }, /* CryptoSwift HSM */
{ "ISG Cryptoki API library", "test", "Test user key" }, /* CryptoSwift card */
{ "NShield 75", "abc", "sleuteltje" }, /* nCipher */
{ "PKCS#11 Private Cryptoki", "1234", "Test user key" }, /* GemSAFE */
{ "Safelayer PKCS#11", "test", "Test user key" }, /* Safelayer */
{ "Schlumberger", "QWERTYUI", "Test user key" }, /* Schlumberger */
{ "SignLite security module", "test", "Test user key" }, /* IBM SignLite */
{ "Spyrus Rosetta", "test", "Test user key" }, /* Spyrus */
{ "Spyrus Lynks", "test", "Test user key" }, /* Spyrus */
{ "TCrypt", "123456", "Test user key" }, /* Telesec */
{ "TrustCenter PKCS#11 Library", "12345678", "Test user key" }, /* GPKCS11 */
{ NULL, NULL, NULL }
};
/* Uncomment the following to test cryptlib's CAW functionality. Note that
this will zeroise the card being tested as a part of the process, all data
contained in it will be destroyed. In addition to uncommenting the
following, you also need to set the zeroise and default SSO PIN's below */
/* #define TEST_CAW_FUNCTIONALITY */
/* Device information for Fortezza cards */
#define FORTEZZA_ZEROISE_PIN "XXXXXXXXXXXX"
#define FORTEZZA_SSO_DEFAULT_PIN "XXXXXX"
#define FORTEZZA_SSO_PIN "0000"
#define FORTEZZA_USER_PIN "0000"
static const DEVICE_INFO fortezzaDeviceInfo = \
{ "", FORTEZZA_USER_PIN, "Test user key" };
/* 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 }
};
/* 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 );
}
/* Log in to a device */
static BOOLEAN deviceLogin( const CRYPT_DEVICE cryptDevice,
const CRYPT_DEVICE_TYPE deviceType,
const DEVICE_INFO *deviceInfo )
{
int status;
printf( "Logging on to the device..." );
status = cryptSetAttributeString( cryptDevice,
CRYPT_DEVINFO_AUTHENT_USER, deviceInfo->password,
strlen( deviceInfo->password ) );
if( status == CRYPT_ERROR_NOTINITED && \
deviceType == CRYPT_DEVICE_PKCS11 )
{
/* It's an uninitialised PKCS #11 device, try initialising it.
Testing CAW functionality is somewhat more complex than a
straight init and is handled separately */
puts( " device needs to be initialised." );
printf( "Initialising device..." );
status = cryptSetAttributeString( cryptDevice,
CRYPT_DEVINFO_INITIALISE, deviceInfo->password,
strlen( deviceInfo->password ) );
if( cryptStatusOK( status ) )
{
/* After the init we're logged on as SSO, to perform any useful
testing we have to re-log on as a user since most devices
which actually enforce SSO vs user roles won't allow standard
operations to be performed while the SSO role is in effect.
Since the initialisation sets the user PIN to the same value
as the SSO PIN, we can just re-authenticate ourselves using
the same PIN (in the real world and if SSO vs user roles are
being enforced, the SSO would change the user PIN before
handing the device over to the user) */
printf( " succeeded.\nLogging on to the device..." );
status = cryptSetAttributeString( cryptDevice,
CRYPT_DEVINFO_AUTHENT_USER, deviceInfo->password,
strlen( deviceInfo->password ) );
}
}
if( cryptStatusError( status ) )
{
printf( "\nDevice %s failed with error code %d, line %d.\n",
( status == CRYPT_ERROR_WRONGKEY ) ? \
"login" : "initialisation/setup", status, __LINE__ );
return( FALSE );
}
puts( " succeeded." );
return( TRUE );
}
/* Test the general capabilities of a device */
static BOOLEAN testDeviceCapabilities( const CRYPT_DEVICE cryptDevice,
const char *deviceName,
const BOOLEAN isWriteProtected )
{
CRYPT_ALGO cryptAlgo;
int failCount = 0;
printf( "Checking %s capabilities...\n", deviceName );
for( cryptAlgo = CRYPT_ALGO_FIRST_CONVENTIONAL;
cryptAlgo <= CRYPT_ALGO_LAST; cryptAlgo++ )
if( cryptStatusOK( cryptDeviceQueryCapability( cryptDevice,
cryptAlgo, NULL ) ) && \
!testLowlevel( cryptDevice, cryptAlgo, isWriteProtected ) )
/* The test failed, we don't exit at this point but only remember
that there was a problem since we want to test every possible
algorithm */
failCount++;
if( isWriteProtected )
puts( "No tests were performed since the device is write-protected." );
else
if( failCount )
printf( "%d test%s failed.\n", failCount,
( failCount > 1 ) ? "s" : "" );
else
puts( "Device capabilities test succeeded." );
return( TRUE );
}
/* Create a key and certificate in a device */
static BOOLEAN createKey( const CRYPT_DEVICE cryptDevice,
const CRYPT_ALGO 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -