📄 keyfile.c
字号:
__LINE__ );
return( FALSE );
}
cryptDestroyContext( cryptContext );
cryptDestroyCert( cryptCert );
/* Try and read the key+cert back before we close the keyset. This
ensures that the in-memory data has been updated correctly. We use
the generic RSA key label to read it since this isn't a real user
key */
if( !useAltKeyfile )
{
status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
cryptDestroyContext( cryptContext );
if( cryptStatusError( status ) )
{
printExtError( cryptKeyset,
"private key read from in-memory cached keyset data",
status, __LINE__ );
return( FALSE );
}
}
/* Close the keyset, which flushes the in-memory changes to disk. The
cacheing of data in memory ensures that all keyset updates are atomic,
so that it's nearly impossible to corrupt a private key keyset during
an update */
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Try and read the key+cert back from disk rather than the cached, in-
memory version */
if( !useAltKeyfile )
{
status = getPrivateKey( &cryptContext, TEST_PRIVKEY_FILE,
RSA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
cryptDestroyContext( cryptContext );
if( cryptStatusError( status ) )
{
printExtError( cryptKeyset,
"private key read from on-disk keyset data",
status, __LINE__ );
return( FALSE );
}
}
puts( "Single-step key+cert write to key file succeeded.\n" );
return( TRUE );
}
int testSingleStepFileCert( void )
{
return( writeSingleStepFileCert( FALSE ) );
}
int testSingleStepAltFileCert( void )
{
return( writeSingleStepFileCert( TRUE ) );
}
/* Write two keys and certs (signature + encryption) with the same DN to a
file */
int testDoubleCertFile( void )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptSigCert, cryptEncryptCert;
CRYPT_CONTEXT cryptCAKey, cryptSigContext, cryptEncryptContext;
int status;
puts( "Testing separate signature+encryption certificate write to key "
"file..." );
doubleCertOK = FALSE;
/* Get the CA's key */
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 );
}
/* Generate two keys to certify. We can't just use the built-in test key
because cryptlib will detect it being added to the keyset a second time
(if we reuse it for both keys) and because the label is a generic one
that doesn't work if there are two keys */
status = cryptCreateContext( &cryptSigContext, CRYPT_UNUSED,
CRYPT_ALGO_RSA );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSigContext,
CRYPT_CTXINFO_LABEL, DUAL_SIGNKEY_LABEL,
paramStrlen( DUAL_SIGNKEY_LABEL ) );
if( cryptStatusOK( status ) )
status = cryptGenerateKey( cryptSigContext );
if( cryptStatusError( status ) )
{
printf( "Test key generation failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptCreateContext( &cryptEncryptContext, CRYPT_UNUSED,
CRYPT_ALGO_RSA );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptEncryptContext,
CRYPT_CTXINFO_LABEL, DUAL_ENCRYPTKEY_LABEL,
paramStrlen( DUAL_ENCRYPTKEY_LABEL ) );
if( cryptStatusOK( status ) )
status = cryptGenerateKey( cryptEncryptContext );
if( cryptStatusError( status ) )
{
printf( "Test key generation failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Create the certs containing the keys. In order to avoid clashes with
other keys with the same CN in the public-key database, we give the
certs abnormal CNs. This isn't necessary for cryptlib to manage them,
but because later code tries to delete leftover certs from previous
runs with the generic name used in the self-tests, which would also
delete these certs */
status = cryptCreateCert( &cryptSigCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSigCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptSigContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptSigCert, certRequestData, __LINE__ ) )
return( FALSE );
if( cryptStatusOK( status ) )
{
status = cryptDeleteAttribute( cryptSigCert,
CRYPT_CERTINFO_COMMONNAME );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptSigCert,
CRYPT_CERTINFO_COMMONNAME, TEXT( "Dave Smith (Dual)" ),
paramStrlen( TEXT( "Dave Smith (Dual)" ) ) );
}
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptSigCert,
CRYPT_CERTINFO_KEYUSAGE, CRYPT_KEYUSAGE_DIGITALSIGNATURE );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptSigCert, cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Signature cert creation failed with error code %d, "
"line %d.\n", status, __LINE__ );
printErrorAttributeInfo( cryptSigCert );
return( FALSE );
}
status = cryptCreateCert( &cryptEncryptCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptEncryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptEncryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptEncryptCert, certRequestData, __LINE__ ) )
return( FALSE );
if( cryptStatusOK( status ) )
{
status = cryptDeleteAttribute( cryptEncryptCert,
CRYPT_CERTINFO_COMMONNAME );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptEncryptCert,
CRYPT_CERTINFO_COMMONNAME, TEXT( "Dave Smith (Dual)" ),
paramStrlen( TEXT( "Dave Smith (Dual)" ) ) );
}
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptEncryptCert,
CRYPT_CERTINFO_KEYUSAGE, CRYPT_KEYUSAGE_KEYENCIPHERMENT );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptEncryptCert, cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Encryption cert creation failed with error code %d, "
"line %d.\n", status, __LINE__ );
printErrorAttributeInfo( cryptEncryptCert );
return( FALSE );
}
cryptDestroyContext( cryptCAKey );
/* Open the keyset, write the keys and certificates, and close it */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
DUAL_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, cryptSigContext,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) )
status = cryptAddPrivateKey( cryptKeyset, cryptEncryptContext,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
__LINE__ );
return( FALSE );
}
status = cryptAddPublicKey( cryptKeyset, cryptSigCert );
if( cryptStatusOK( status ) )
status = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );
if( cryptStatusError( status ) )
{
printExtError( cryptKeyset, "cryptAddPublicKey()", 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 )
{
C_CHR 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 );
#ifdef UNICODE_STRINGS
length /= sizeof( wchar_t );
#endif /* UNICODE_STRINGS */
name[ length ] = TEXT( '\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 )
{
/* We can get a notfound 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 that isn't being found */
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 ) )
{
printExtError( cryptKeyset, "cryptGetPrivateKey()", 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 */
#ifndef _WIN32_WCE /* Windows CE doesn't support ANSI C time functions */
int testRenewedCertFile( void )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptOldCert, cryptNewCert;
CRYPT_CONTEXT cryptCAKey, cryptContext;
time_t writtenValidTo = 0 /* Dummy */, 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, __LINE__ ) )
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__ );
printErrorAttributeInfo( 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, __LINE__ ) )
return( FALSE );
if( cryptStatusOK( status ) )
{
time_t validity = time( NULL );
/* Valid for one month starting yesterday (it's actually valid for
one month + one day to sidestep the one-month sanity check in the
private key read code that warns of about-to-expire keys) */
validity -= 86400;
cryptSetAttributeString( cryptNewCert,
CRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -