📄 devices.c
字号:
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 );
}
/* Run a persistent server session, recycling the connection if the client
kept the link open */
static int activatePersistentServerSession( const CRYPT_SESSION cryptSession )
{
BOOLEAN connectionActive = FALSE;
int status;
puts( "Running (persistent) CMP server session." );
do
{
/* Activate the connection */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE,
TRUE );
if( status == CRYPT_ERROR_READ && connectionActive )
/* The other side closed the connection after a previous
successful transaction, this isn't an error */
return( CRYPT_OK );
/* Print connection info */
if( !connectionActive )
{
time_t theTime;
char serverName[ 128 ];
int serverNameLength, serverPort, nameStatus;
time( &theTime );
nameStatus = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_CLIENT_NAME,
serverName, &serverNameLength );
if( cryptStatusOK( nameStatus ) )
{
serverName[ serverNameLength ] = '\0';
cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CLIENT_PORT,
&serverPort );
printf( "Connect attempt from %s, port %d, on %s",
serverName, serverPort, ctime( &theTime ) );
}
}
if( cryptStatusOK( status ) )
{
char userID[ CRYPT_MAX_TEXTSIZE ];
int userIDsize, requestType;
status = cryptGetAttribute( cryptSession,
CRYPT_SESSINFO_CMP_REQUESTTYPE,
&requestType );
if( cryptStatusOK( status ) )
status = cryptGetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME,
userID, &userIDsize );
if( cryptStatusError( status ) )
printf( "cryptGetAttribute/AttributeString() failed with "
"error code %d, line %d.\n", status, __LINE__ );
else
{
userID[ userIDsize ] = '\0';
printf( "CA operation type was %d, user '%s'.\n",
requestType, userID );
}
}
/* Check whether the connection is still active. If it is, we
recycle the session so that we can process another request */
cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CONNECTIONACTIVE,
&connectionActive );
}
while( cryptStatusOK( status ) && connectionActive );
puts( "CMP server session completed." );
return( status );
}
/* 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..." );
cryptCreateCert( &cryptCert, CRYPT_UNUSED, CRYPT_CERTTYPE_CERTIFICATE );
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptCert, rootCACertData ) )
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';
printf( "Device label is '%s'.\n", tokenLabel );
}
/* See if we need to authenticate ourselves */
status = cryptGetAttribute( cryptDevice, CRYPT_DEVINFO_LOGGEDIN,
&loggedOn );
if( cryptStatusError( status ) )
{
puts( "Couldn't obtain device login status." );
return( FALSE );
}
if( loggedOn )
{
/* Device may not require a login, or has already been logged in
via a keypad or similar mechanism */
puts( "Device is already logged in, skipping login." );
return( TRUE );
}
/* Try and log in */
printf( "Logging on to the device..." );
status = cryptSetAttributeString( cryptDevice,
CRYPT_DEVINFO_AUTHENT_USER, userPIN,
strlen( userPIN ) );
if( status == CRYPT_ERROR_INITED )
{
/* Some devices may not require any login, in which case we're
done */
puts( " device is already logged in." );
return( TRUE );
}
if( status == CRYPT_ERROR_NOTINITED )
{
/* It's an uninitialised device, tell the user and exit */
puts( " device needs to be initialised." );
return( FALSE );
}
if( cryptStatusError( status ) )
{
printf( "\nDevice login failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( " done." );
return( TRUE );
}
/* Initialise a device */
static int initDevice( const CRYPT_DEVICE cryptDevice,
const char *defaultSSOPIN, const char *ssoPIN,
const char *userPIN )
{
int status;
/* PKCS #11 doesn't distinguish between zeroisation and initialisation,
so we need to zeroise the device if it's a Fortezza card */
if( CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA )
{
printf( "Zeroising device..." );
status = cryptSetAttributeString( cryptDevice,
CRYPT_DEVINFO_ZEROISE, FORTEZZA_ZEROISE_PIN,
strlen( FORTEZZA_ZEROISE_PIN ) );
if( cryptStatusError( status ) )
{
printf( "\nCouldn't zeroise device, status = %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( " done." );
}
/* Initialise the device and set the SO PIN */
printf( "Initialising device with default SO PIN '%s'...",
defaultSSOPIN );
status = cryptSetAttributeString( cryptDevice, CRYPT_DEVINFO_INITIALISE,
defaultSSOPIN, strlen( defaultSSOPIN ) );
if( cryptStatusError( status ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -