📄 testkey.c
字号:
if( cryptStatusError( status ) )
{
printf( "cryptAddPrivateKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptAddPublicKey( cryptKeyset, cryptSigCert );
if( cryptStatusOK( status ) )
status = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );
if( cryptStatusError( status ) )
{
printf( "cryptAddPublicKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Write the two certs to a public-key database if there's one available
(because it may not be present, we fail quietly if access to this
keyset type isn't available or the keyset isn't present, it'll be
picked up later by other tests).
This cert write is needed later to test the encryption vs signature
cert handling. Since they may have been added earlier, we try and
delete them first (we can't use the existing version since the
issuerAndSerialNumber won't match the ones in the private-key
keyset) */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,
CRYPT_KEYOPT_NONE );
if( status != CRYPT_ERROR_PARAM3 && status != CRYPT_ERROR_OPEN )
{
char name[ CRYPT_MAX_TEXTSIZE + 1 ];
int length;
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
if( status == CRYPT_ERROR_OPEN )
return( CRYPT_ERROR_FAILED );
return( FALSE );
}
cryptGetAttributeString( cryptSigCert, CRYPT_CERTINFO_COMMONNAME,
name, &length );
name[ length ] = '\0';
do
status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
while( cryptStatusOK( status ) );
if( status != CRYPT_ERROR_NOTFOUND )
/* Deletion of the existing keys failed for some reason, we can't
continue */
return( extErrorExit( cryptKeyset, "cryptDeleteKey()",
status, __LINE__ ) );
status = cryptAddPublicKey( cryptKeyset, cryptSigCert );
if( status == CRYPT_ERROR_NOTFOUND )
/* This can occur if a database keyset is defined but hasn't been
initialised yet so the necessary tables don't exist, it can be
opened but an attempt to add a key will return a not found
error since it's the table itself rather than any item within
it which isn't being found */
status = CRYPT_OK;
else
{
if( cryptStatusOK( status ) )
status = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );
if( cryptStatusError( status ) )
return( extErrorExit( cryptKeyset, "cryptAddPublicKey()",
status, __LINE__ ) );
/* The double-cert keyset is set up, remember this for later
tests */
doubleCertOK = TRUE;
}
cryptKeysetClose( cryptKeyset );
}
/* Clean up */
cryptDestroyContext( cryptSigContext );
cryptDestroyContext( cryptEncryptContext );
cryptDestroyCert( cryptSigCert );
cryptDestroyCert( cryptEncryptCert );
/* Try and read the keys+certs back */
status = getPrivateKey( &cryptSigContext, DUAL_PRIVKEY_FILE,
DUAL_SIGNKEY_LABEL, TEST_PRIVKEY_PASSWORD );
cryptDestroyContext( cryptSigContext );
if( cryptStatusOK( status ) )
{
status = getPrivateKey( &cryptEncryptContext, DUAL_PRIVKEY_FILE,
DUAL_ENCRYPTKEY_LABEL, TEST_PRIVKEY_PASSWORD );
cryptDestroyContext( cryptEncryptContext );
}
if( cryptStatusError( status ) )
{
printf( "Private key read failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( "Separate signature+encryption certificate write to key file "
"succeeded.\n" );
return( TRUE );
}
/* Write a key and two certs of different validity periods to a file */
int testRenewedCertFile( void )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptOldCert, cryptNewCert;
CRYPT_CONTEXT cryptCAKey, cryptContext;
time_t writtenValidTo, readValidTo;
int dummy, status;
puts( "Testing renewed certificate write to key file ..." );
/* Get the CA's key and the key to certify */
status = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,
CA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "CA private key read failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
if( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptContext ) )
return( FALSE );
/* Create the certs containing the keys */
status = cryptCreateCert( &cryptOldCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptOldCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptOldCert, certRequestData ) )
return( FALSE );
if( cryptStatusOK( status ) )
{
time_t validity = time( NULL );
/* Valid for one month ending tomorrow (we can't make it already-
expired or cryptlib will complain) */
validity += 86400;
cryptSetAttributeString( cryptOldCert,
CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
validity -= ( 86400 * 31 );
status = cryptSetAttributeString( cryptOldCert,
CRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );
}
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptOldCert, cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Signature cert creation failed with error code %d, "
"line %d.\n", status, __LINE__ );
printCertErrorInfo( cryptOldCert );
return( FALSE );
}
status = cryptCreateCert( &cryptNewCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptNewCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptNewCert, certRequestData ) )
return( FALSE );
if( cryptStatusOK( status ) )
{
time_t validity = time( NULL );
/* Valid for one month starting yesterday */
validity -= 86400;
cryptSetAttributeString( cryptNewCert,
CRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );
validity += ( 86400 * 31 );
status = cryptSetAttributeString( cryptNewCert,
CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
writtenValidTo = validity;
}
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptNewCert, cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Encryption cert creation failed with error code %d, "
"line %d.\n", status, __LINE__ );
printCertErrorInfo( cryptNewCert );
return( FALSE );
}
cryptDestroyContext( cryptCAKey );
/* Open the keyset, write the key and certificates, and close it */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
RENEW_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptAddPrivateKey( cryptKeyset, cryptContext,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "cryptAddPrivateKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptAddPublicKey( cryptKeyset, cryptOldCert );
if( cryptStatusOK( status ) )
status = cryptAddPublicKey( cryptKeyset, cryptNewCert );
if( cryptStatusError( status ) )
{
printf( "cryptAddPublicKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Clean up */
cryptDestroyContext( cryptContext );
cryptDestroyCert( cryptOldCert );
cryptDestroyCert( cryptNewCert );
/* Try and read the (newest) key+cert back */
status = getPrivateKey( &cryptContext, RENEW_PRIVKEY_FILE,
RSA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "Private key read failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptGetAttributeString( cryptContext,
CRYPT_CERTINFO_VALIDTO, &readValidTo, &dummy );
if( cryptStatusError( status ) || writtenValidTo != readValidTo )
{
printf( "Returned cert != latest valid cert, line %d.\n", __LINE__ );
return( FALSE );
}
cryptDestroyContext( cryptContext );
puts( "Renewed certificate write to key file succeeded.\n" );
return( TRUE );
}
/* Read/write a certificate from a public-key keyset. Returns
CRYPT_ERROR_NOTAVAIL if this keyset type isn't available from this
cryptlib build, CRYPT_ERROR_FAILED if the keyset/data source access
failed */
static int testKeysetRead( const CRYPT_KEYSET_TYPE keysetType,
const char *keysetName,
const char *keyName,
const CRYPT_CERTTYPE_TYPE type )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptCert;
int value, status;
/* Open the keyset with a check to make sure this access method exists
so we can return an appropriate error message */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,
keysetName, CRYPT_KEYOPT_READONLY );
if( status == CRYPT_ERROR_PARAM3 )
/* This type of keyset access not available */
return( CRYPT_ERROR_NOTAVAIL );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( CRYPT_ERROR_FAILED );
}
/* Read the certificate from the keyset */
status = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,
keyName );
if( cryptStatusError( status ) )
{
/* The access to network-accessible keysets can be rather
temperamental and can fail at this point even though it's not a
fatal error. The calling code knows this and will continue the
self-test with an appropriate warning, so we explicitly clean up
after ourselves to make sure we don't get a CRYPT_ORPHAN on
shutdown */
status = extErrorExit( cryptKeyset, "cryptGetPublicKey()", status,
__LINE__ );
cryptKeysetClose( cryptKeyset );
return( status );
}
/* Make sure we got what we were expecting */
cryptGetAttribute( cryptCert, CRYPT_CERTINFO_CERTTYPE, &value );
if( value != type )
{
printf( "Expecting certificate object type %d, got %d.", type, value );
return( FALSE );
}
if( value == CRYPT_CERTTYPE_CERTCHAIN )
{
value = 0;
cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CURRENT_CERTIFICATE,
CRYPT_CURSOR_FIRST );
do
value++;
while( cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_CURRENT_CERTIFICATE, CRYPT_CURSOR_NEXT ) == CRYPT_OK );
printf( "Cert chain length = %d.\n", value );
}
/* Check the cert against the CRL. Any kind of error is a failure since
the cert isn't in the CRL */
if( keysetType != CRYPT_KEYSET_LDAP && \
keysetType != CRYPT_KEYSET_HTTP )
{
puts( "Checking certificate against CRL." );
status = cryptCheckCert( cryptCert, cryptKeyset );
if( cryptStatusError( status ) )
return( extErrorExit( cryptKeyset, "cryptCheckCert() (for CRL "
"in keyset)", status, __LINE__ ) );
}
/* Close the keyset */
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
cryptDestroyCert( cryptCert );
return( TRUE );
}
static int testKeysetWrite( const CRYPT_KEYSET_TYPE keysetType,
const char *keysetName )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptCert;
char name[ CRYPT_MAX_TEXTSIZE + 1 ];
int length, status;
/* Import the certificate from a file - this is easier than creating one
from scratch */
status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 1 );
if( cryptStatusError( status ) )
{
puts( "Couldn't read certificate from file, skipping test of keyset "
"write..." );
return( TRUE );
}
/* Create the database keyset with a check to make sure this access
method exists so we can return an appropriate error message. If the
database table already exists, this will return a duplicate data
error so we retry the open with no flags to open the existing database
keyset for write access */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,
keysetName, CRYPT_KEYOPT_CREATE );
if( cryptStatusOK( status ) )
printf( "Created new certificate database '%s'.\n", keysetName );
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( cryptCert );
return( CRYPT_ERROR_NOTAVAIL );
}
if( status == CRYPT_ERROR_DUPLICATE )
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,
keysetName, 0 );
if( cryptStatusError( status ) )
{
cryptDestroyCert( cryptCert );
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -