📄 testsess.c
字号:
but require explicit use of an update request */
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME, user,
strlen( user ) );
if( cryptStatusOK( status ) )
if( privateKey != CRYPT_UNUSED )
{
cryptSetAttribute( cryptSession, CRYPT_SESSINFO_CMP_REQUESTTYPE,
isRevocation ? CRYPT_REQUESTTYPE_REVOCATION : \
isUpdate ? CRYPT_REQUESTTYPE_KEYUPDATE : \
CRYPT_REQUESTTYPE_CERTIFICATE );
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY,
privateKey );
}
else
{
cryptSetAttribute( cryptSession, CRYPT_SESSINFO_CMP_REQUESTTYPE,
isRevocation ? CRYPT_REQUESTTYPE_REVOCATION : \
CRYPT_REQUESTTYPE_INITIALISATION );
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_PASSWORD, password,
strlen( password ) );
}
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_SERVER_NAME, server,
strlen( server ) );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_CMP_CACERTIFICATE, cryptCACert );
if( cryptStatusError( status ) )
{
printf( "Addition of session information failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
return( cryptSession );
}
/* Request a particular cert type */
static int requestCert( const char *description, const CA_INFO *caInfoPtr,
const char *readKeysetName, const char *writeKeysetName,
const CERT_DATA *requestData, const CRYPT_ALGO cryptAlgo,
const CRYPT_CONTEXT cryptCACert,
CRYPT_CERTIFICATE *issuedCert )
{
CRYPT_SESSION cryptSession;
CRYPT_KEYSET cryptKeyset = CRYPT_UNUSED;
CRYPT_CONTEXT privateKey = CRYPT_UNUSED;
CRYPT_CERTIFICATE cryptCmpRequest, cryptCmpResponse;
const BOOLEAN useExistingKey = ( requestData == NULL ) ? TRUE : FALSE;
int status;
#ifdef SERVER_PROVIDES_DN
printf( "Testing %s processing...\n", description );
#else
printf( "Testing %s processing with absent subject DN...\n", description );
#endif /* SERVER_PROVIDES_DN */
/* Read the key needed to request a new cert from a keyset if necessary,
and create a keyset to save a new key to if required. We have to do
the write last in case the read and write keyset are the same */
if( readKeysetName != NULL )
{
status = getPrivateKey( &privateKey, readKeysetName,
USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "Couldn't get private key to request new certificate, "
"status = %d.\n", status );
return( FALSE );
}
}
if( writeKeysetName != NULL )
{
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
CRYPT_KEYSET_FILE, writeKeysetName,
CRYPT_KEYOPT_CREATE );
if( cryptStatusError( status ) )
{
printf( "Couldn't create keyset to store certificate to, "
"status = %d.\n", status );
return( FALSE );
}
}
/* Create the CMP session and certification request. Some CAs explicitly
disallow multiple dissimilar certs to exist for the same key (in fact
for non-test servers other CAs probably enforce this as well) but
generating a new key for each request is time-consuming so we only do
it if it's enforced by the CA */
cryptSession = createCmpSession( cryptCACert, caInfoPtr->serverName,
caInfoPtr->userName, caInfoPtr->password,
privateKey, FALSE, useExistingKey );
if( cryptSession <= 0 )
{
if( cryptKeyset != CRYPT_UNUSED )
cryptKeysetClose( cryptKeyset );
return( cryptSession );
}
#if ( CA_NO == 1 ) || ( CA_NO == 7 )
cryptCmpRequest = createCmpRequest( requestData,
useExistingKey ? privateKey : CRYPT_UNUSED,
cryptAlgo, FALSE, cryptKeyset );
#else
KLUDGE_WARN( "fixed key for request" );
cryptCmpRequest = createCmpRequest( requestData,
useExistingKey ? privateKey : CRYPT_UNUSED,
cryptAlgo, TRUE, cryptKeyset );
#endif /* cryptlib and Initech won't allow two certs for same key */
if( !cryptCmpRequest )
return( FALSE );
if( privateKey != CRYPT_UNUSED )
cryptDestroyContext( privateKey );
/* Set up the request and activate the session */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,
cryptCmpRequest );
cryptDestroyCert( cryptCmpRequest );
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( cryptStatusError( status ) )
{
if( cryptKeyset != CRYPT_UNUSED )
cryptKeysetClose( cryptKeyset );
printExtError( cryptSession, "Attempt to activate CMP session",
status, __LINE__ );
cryptDestroySession( cryptSession );
if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_READ )
{
/* These servers are constantly appearing and disappearing so if
we get a straight connect error we don't treat it as a serious
failure */
puts( " (Server could be down, faking it and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
if( status == CRYPT_ERROR_FAILED )
{
/* A general failed response is more likely to be due to the
server doing something unexpected than a cryptlib problem so
we don't treat it as a fatal error */
puts( " (This is more likely to be an issue with the server than "
"with cryptlib,\n faking it and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
return( FALSE );
}
/* Obtain the response information */
status = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,
&cryptCmpResponse );
cryptDestroySession( cryptSession );
if( cryptStatusError( status ) )
{
printf( "cryptGetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
#if CA_NO != 1
puts( "Returned certificate details are:" );
printCertInfo( cryptCmpResponse );
#endif /* Keep the cryptlib results on one screen */
if( cryptKeyset != CRYPT_UNUSED )
{
status = cryptAddPublicKey( cryptKeyset, cryptCmpResponse );
if( cryptStatusError( status ) )
{
printf( "Couldn't write certificate to keyset, status = %d.\n",
status );
return( FALSE );
}
cryptKeysetClose( cryptKeyset );
}
if( issuedCert != NULL )
*issuedCert = cryptCmpResponse;
else
cryptDestroyCert( cryptCmpResponse );
/* Clean up */
printf( "%s processing succeeded.\n\n", description );
return( TRUE );
}
/* Revoke a previously-issued cert */
static int revokeCert( const char *description, const CA_INFO *caInfoPtr,
const char *keysetName,
const CRYPT_CERTIFICATE certToRevoke,
const CRYPT_CONTEXT cryptCACert,
const BOOLEAN signRequest )
{
CRYPT_SESSION cryptSession;
CRYPT_CONTEXT privateKey = CRYPT_UNUSED;
CRYPT_CERTIFICATE cryptCmpRequest, cryptCert = certToRevoke;
int status;
printf( "Testing %s revocation processing...\n", description );
/* Get the cert to revoke if necessary. In some cases the server won't
accept a revocation password, so we have to get the private key as
well to sign the request */
if( signRequest || cryptCert == CRYPT_UNUSED )
{
CRYPT_KEYSET cryptKeyset;
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
CRYPT_KEYSET_FILE, keysetName,
CRYPT_KEYOPT_READONLY );
if( cryptStatusOK( status ) && signRequest )
status = getPrivateKey( &privateKey, keysetName,
USER_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) && cryptCert == CRYPT_UNUSED )
status = cryptGetPublicKey( cryptKeyset, &cryptCert,
CRYPT_KEYID_NAME,
USER_PRIVKEY_LABEL );
cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
puts( "Couldn't fetch certificate/key to revoke.\n" );
return( FALSE );
}
}
/* Create the CMP session and revocation request */
cryptSession = createCmpSession( cryptCACert, caInfoPtr->serverName,
caInfoPtr->userName, caInfoPtr->password,
privateKey, TRUE, FALSE );
if( privateKey != CRYPT_UNUSED )
cryptDestroyContext( privateKey );
if( cryptSession <= 0 )
return( cryptSession );
cryptCmpRequest = createCmpRevRequest( cryptCert );
if( !cryptCmpRequest )
return( FALSE );
/* Set up the request and activate the session */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,
cryptCmpRequest );
cryptDestroyCert( cryptCmpRequest );
if( cryptStatusError( status ) )
{
printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( cryptStatusError( status ) )
{
printExtError( cryptSession, "Attempt to activate CMP session",
status, __LINE__ );
cryptDestroySession( cryptSession );
if( cryptCert != certToRevoke )
cryptDestroyCert( cryptCert );
if( status == CRYPT_ERROR_OPEN || status == CRYPT_ERROR_READ )
{
/* These servers are constantly appearing and disappearing so if
we get a straight connect error we don't treat it as a serious
failure */
puts( " (Server could be down, faking it and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
if( status == CRYPT_ERROR_FAILED )
{
/* A general failed response is more likely to be due to the
server doing something unexpected than a cryptlib problem so
we don't treat it as a fatal error */
puts( " (This is more likely to be an issue with the server than "
"with cryptlib,\n faking it and continuing...)\n" );
return( CRYPT_ERROR_FAILED );
}
return( FALSE );
}
/* Clean up */
if( cryptCert != certToRevoke )
cryptDestroyCert( cryptCert );
cryptDestroySession( cryptSession );
printf( "%s processing succeeded.\n\n", description );
return( TRUE );
}
/* Test the full range of CMP functionality. This performs the following
tests:
RSA sign:
ir + ip + reject (requires cmp.c mod)
ir + ip + certconf + pkiconf
kur + kup + certconf + pkiconf
cr + cp + certconf + pkiconf (not performed since same as kur)
rr + rp (of ir cert)
rr + rp (of kur cert)
RSA encr.:
ir + ip + reject (requires cmp.c mod)
ir + ip + certconf + pkiconf
rr + rp (of ir cert)
DSA:
cr + cp + certconf + pkiconf (success implies that ir/kur/rr
works since they've already been tested for RSA) */
int testSessionCMP( void )
{
CRYPT_CERTIFICATE cryptCACert, cryptCert;
BYTE readFileName[ BUFFER_SIZE ], writeFileName[ BUFFER_SIZE ];
#if CA_NO == 1
CA_INFO cryptlibCAInfo, *caInfoPtr = &cryptlibCAInfo;
char userID[ 64 ], issuePW[ 64 ], revPW[ 64 ];
#else
CA_INFO *caInfoPtr = &caInfo[ CA_NO ];
#endif /* cryptlib */
int status;
/* Get the cert of the CA who will issue the cert */
status = importCertFromTemplate( &cryptCACert, CMP_CA_FILE_TEMPLATE,
CA_NO );
if( cryptStatusError( status ) )
{
printf( "Couldn't get CMP CA certificate, status = %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Test each cert request type: Initialisation, cert request using cert
from initialisation for authentication, key update of cert from
initialisation, revocation of both certs. We don't write the updated
existing key to a keyset because it's already present as a side-effect
of the way the all-in-one test code reuses existing keys where
required. In addition we insert a 1s delay in between requests to
give the server time to recycle */
#ifdef TEST_IR
#if CA_NO == 1
{
CRYPT_KEYSET cryptCertStore;
CRYPT_CERTIFICATE cryptPKIUser;
int length;
/* cryptlib implements per-user (rather than shared interop) IDs and
passwords so we need to read the user ID and password information
before we can perform any operations */
status = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,
CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,
CRYPT_KEYOPT_NONE );
if( status == CRYPT_ERROR_PARAM3 )
{
/* This type of keyset access isn't available, return a special error
code to indicate that the test wasn't performed, but that this
isn't a reason to abort processing */
cryptDestroyCert( cryptCACert );
puts( "No certificate store available, aborting CMP test.\n" );
return( CRYPT_ERROR_NOTAVAIL );
}
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptCAGetItem( cryptCertStore, &cryptPKIUser,
CRYPT_CERTTYPE_PKIUSER, CRYPT_KEYID_NAME,
"Test PKI user" );
cryptKeysetClose( cryptCertStore );
if( cryptStatusError( status ) )
return( extErrorExit( cryptCertStore, "cryptCAGetItem()", status,
__LINE__ ) );
status = cryptGetAttributeString( cryptPKIUser,
CRYPT_CERTINFO_PKIUSER_ID,
userID, &length );
if( cryptStatusOK( status ) )
{
userID[ length ] = '\0';
status = cryptGetAttributeString( cryptPKIUser,
CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,
issuePW, &length );
}
if( cryptStatusOK( status ) )
{
issuePW[ length ] = '\0';
status = cryptGetAttributeString( cryptPKIUser,
CRYPT_CERTINFO_PKIUSER_RE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -