📄 testscrt.c
字号:
status = cryptSetAttributeString( cryptRequest,
CRYPT_CERTINFO_VALIDFROM, &startTime, sizeof( time_t ) );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptRequest, privateKey );
if( cryptKeyset != CRYPT_UNUSED )
{
if( cryptStatusError( \
cryptAddPrivateKey( cryptKeyset, privateKey,
TEST_PRIVKEY_PASSWORD ) ) )
return( FALSE );
}
}
else
{
CRYPT_CONTEXT cryptContext;
/* It's a new request, generate a private key and create a self-
signed request */
if( useFixedKey )
{
/* Use a fixed private key, for testing purposes */
if( cryptAlgo == CRYPT_ALGO_RSA )
loadRSAContextsEx( CRYPT_UNUSED, NULL, &cryptContext, NULL,
USER_PRIVKEY_LABEL );
else
loadDSAContextsEx( CRYPT_UNUSED, &cryptContext, NULL,
USER_PRIVKEY_LABEL, NULL );
status = CRYPT_OK;
}
else
{
cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
USER_PRIVKEY_LABEL,
strlen( USER_PRIVKEY_LABEL ) );
cryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, 64 );
status = cryptGenerateKey( cryptContext );
}
if( cryptStatusOK( status ) )
status = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,
CRYPT_CERTTYPE_REQUEST_CERT );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptRequest,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptRequest, requestData ) )
status = CRYPT_ERROR_FAILED;
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptRequest, cryptContext );
if( cryptKeyset != CRYPT_UNUSED )
{
if( cryptStatusError( \
cryptAddPrivateKey( cryptKeyset, cryptContext,
TEST_PRIVKEY_PASSWORD ) ) )
return( FALSE );
}
cryptDestroyContext( cryptContext );
}
if( cryptStatusError( status ) )
{
printf( "Creation of CMP request failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
return( cryptRequest );
}
static int createCmpRevRequest( const CRYPT_CERTIFICATE cryptCert )
{
CRYPT_CERTIFICATE cryptRequest;
int status;
/* Create the CMP (CRMF) revocation request */
status = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,
CRYPT_CERTTYPE_REQUEST_REVOCATION );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptRequest, CRYPT_CERTINFO_CERTIFICATE,
cryptCert );
if( cryptStatusError( status ) )
{
printf( "Creation of CMP revocation request failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
return( cryptRequest );
}
static int createCmpSession( const CRYPT_CONTEXT cryptCACert,
const char *server, const char *user,
const char *password,
const CRYPT_CONTEXT privateKey,
const BOOLEAN isRevocation,
const BOOLEAN isUpdate,
const BOOLEAN isPKIBoot )
{
CRYPT_SESSION cryptSession;
int status;
/* Create the CMP session */
status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
CRYPT_SESSION_CMP );
if( status == CRYPT_ERROR_PARAM3 ) /* CMP session access not available */
return( CRYPT_ERROR_NOTAVAIL );
if( cryptStatusError( status ) )
{
printf( "cryptCreateSession() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Set up the user and server information. Revocation requests can be
signed or MACd so we handle either. When requesting a cert using a
signed request (i.e.not an initialisation request) we use an update
since we're reusing the previously-generated cert data to request a
new one and some CAs won't allow this reuse for a straight request
but require explicit use of an update request */
if( privateKey != CRYPT_UNUSED )
{
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_CMP_REQUESTTYPE,
isRevocation ? \
CRYPT_REQUESTTYPE_REVOCATION : \
isUpdate ? \
CRYPT_REQUESTTYPE_KEYUPDATE : \
CRYPT_REQUESTTYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_PRIVATEKEY,
privateKey );
}
else
{
status = cryptSetAttributeString( cryptSession,
CRYPT_SESSINFO_USERNAME, user,
strlen( user ) );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_CMP_REQUESTTYPE,
isPKIBoot ? \
CRYPT_REQUESTTYPE_PKIBOOT : \
isRevocation ? \
CRYPT_REQUESTTYPE_REVOCATION : \
CRYPT_REQUESTTYPE_INITIALISATION );
if( cryptStatusOK( status ) )
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 ) && cryptCACert != CRYPT_UNUSED )
status = cryptSetAttribute( cryptSession,
CRYPT_SESSINFO_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_TYPE cryptAlgo,
const CRYPT_CONTEXT cryptCACert,
const BOOLEAN isPKIBoot,
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 with absent subject DN...\n", description );
#else
printf( "Testing %s processing...\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 */
cryptSession = createCmpSession( cryptCACert, caInfoPtr->url,
caInfoPtr->user, caInfoPtr->password,
privateKey, FALSE, useExistingKey,
isPKIBoot );
if( cryptSession <= 0 )
{
if( cryptKeyset != CRYPT_UNUSED )
cryptKeysetClose( cryptKeyset );
return( cryptSession );
}
/* Set up the 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 */
if( !isPKIBoot )
{
#if ( CA_NO == 1 ) || ( CA_NO == 7 ) || ( CA_NO == 10 )
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 );
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 );
}
}
/* Activate the session */
status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
if( cryptStatusError( status ) )
{
if( cryptKeyset != CRYPT_UNUSED )
cryptKeysetClose( cryptKeyset );
printExtError( cryptSession, "Attempt to activate CMP client 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 );
}
/* If it's a PKIBoot, which just sets (implicitly) trusted certs, we're
done */
if( isPKIBoot )
{
cryptDestroySession( cryptSession );
return( TRUE );
}
/* 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 ) && ( CA_NO != 10 )
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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -