📄 keyfile.c
字号:
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptAddPublicKey( cryptKeyset, cryptCert );
if( cryptStatusError( status ) )
{
printf( "cryptAddPublicKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
cryptDestroyCert( cryptCert );
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( "Certificate update to key file succeeded.\n" );
return( TRUE );
}
/* Update a keyset to contain a cert chain */
static const CERT_DATA certRequestData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
#if defined( CREATE_SERVER_CERT )
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Server cert" ) },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "localhost" ) },
#elif defined( CREATE_ICA_CERT )
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Intermediate CA cert" ) },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave's Spare CA" ) },
#elif defined( CREATE_SCEPCA_CERT )
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Intermediate CA cert" ) },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave's SCEP CA" ) },
#else
{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Procurement" ) },
{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave Smith" ) },
{ CRYPT_CERTINFO_EMAIL, IS_STRING, 0, TEXT( "dave@wetaburgers.com" ) },
{ CRYPT_CERTINFO_SUBJECTNAME, IS_NUMERIC, CRYPT_UNUSED }, /* Re-select subject DN */
#endif /* CREATE_SERVER_CERT */
/* Extensions for various special-case usages such as OCSP and CMP */
#ifdef CREATE_TSA_CERT
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },
{ CRYPT_CERTINFO_EXTKEY_TIMESTAMPING, IS_NUMERIC, CRYPT_UNUSED },
#endif /* CREATE_TSA_CERT */
#ifdef CREATE_SERVER_CERT
{ CRYPT_CERTINFO_AUTHORITYINFO_OCSP, IS_NUMERIC, CRYPT_UNUSED },
{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( "http://localhost" ) },
#endif /* CREATE_SERVER_CERT */
#if defined( CREATE_ICA_CERT )
{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYCERTSIGN },
#elif defined( CREATE_SCEPCA_CERT )
{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },
{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_KEYENCIPHERMENT },
#endif /* Assorted CA certs */
{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
};
static int writeFileCertChain( const BOOLEAN writeLongChain )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptCertChain;
CRYPT_CONTEXT cryptCAKey, cryptKey;
int status;
printf( "Testing %scert chain write to key file ...\n",
writeLongChain ? "long " : "" );
/* Generate a key to certify. We can't just reuse the built-in test key
because this has already been used as the CA key and the keyset code
won't allow it to be added to a keyset as both a CA key and user key,
so we have to generate a new one */
status = cryptCreateContext( &cryptKey, CRYPT_UNUSED, CRYPT_ALGO_RSA );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptKey, CRYPT_CTXINFO_LABEL,
USER_PRIVKEY_LABEL,
paramStrlen( USER_PRIVKEY_LABEL ) );
if( cryptStatusOK( status ) )
{
cryptSetAttribute( cryptKey, CRYPT_CTXINFO_KEYSIZE, 64 );
status = cryptGenerateKey( cryptKey );
}
if( cryptStatusError( status ) )
{
printf( "Test key generation failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Get the CA's key. The length of the chain is determined by the
number of certs attached to the CAs cert, so handling long vs.short
chains is pretty simple */
if( writeLongChain )
status = getPrivateKey( &cryptCAKey, ICA_PRIVKEY_FILE,
USER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );
else
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 );
}
/* Create the keyset and add the private key to it */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
TEST_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, cryptKey,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "cryptAddPrivateKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Create the cert chain for the new key */
status = cryptCreateCert( &cryptCertChain, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTCHAIN );
if( cryptStatusOK( status ) )
status = cryptSetAttribute( cryptCertChain,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptKey );
cryptDestroyContext( cryptKey );
if( cryptStatusOK( status ) && \
!addCertFields( cryptCertChain, certRequestData ) )
return( FALSE );
#ifdef CREATE_CUSTOM_CERT
{
const time_t validity = time( NULL ) + ( 86400L * 365 * 5 );
/* Make it valid for 5 years instead of 1 to avoid problems when users
run the self-test with very old copies of the code */
cryptSetAttributeString( cryptCertChain,
CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
}
#endif /* CREATE_CUSTOM_CERT */
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCertChain, cryptCAKey );
cryptDestroyContext( cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Cert chain creation failed with error code %d, line %d.\n",
status, __LINE__ );
printErrorAttributeInfo( cryptCertChain );
return( FALSE );
}
/* Add the cert chain to the file */
status = cryptAddPublicKey( cryptKeyset, cryptCertChain );
if( cryptStatusError( status ) )
{
printf( "cryptAddPrivateKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
cryptDestroyCert( cryptCertChain );
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( "Cert chain write to key file succeeded.\n" );
return( TRUE );
}
int testWriteFileCertChain( void )
{
return( writeFileCertChain( FALSE ) );
}
int testWriteFileLongCertChain( void )
{
return( writeFileCertChain( TRUE ) );
}
/* Delete a key from a file */
int testDeleteFileKey( void )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CONTEXT cryptContext;
int status;
puts( "Testing delete from key file..." );
/* Open the file keyset */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Delete the key from the file. Since we don't need the DSA key any
more we use it as the key to delete */
status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,
DSA_PRIVKEY_LABEL );
if( cryptStatusError( status ) )
{
printf( "cryptDeleteKey() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptGetPublicKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,
DSA_PRIVKEY_LABEL );
if( cryptStatusOK( status ) )
{
cryptDestroyContext( cryptContext );
puts( "cryptDeleteKey() claimed the key was deleted but it's still "
"present." );
return( FALSE );
}
/* Close the keyset */
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( "Delete from key file succeeded.\n" );
return( TRUE );
}
/* Change the password for a key in a file */
int testChangeFileKeyPassword( void )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CONTEXT cryptContext;
int status;
puts( "Testing change of key password for key file..." );
/* Open the file keyset */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Read the key using the old password, delete it, and write it back
using the new password. To keep things simple we just use the same
password (since the key will be used again later), the test of the
delete function earlier on has already confirmed that the old key
and password will be deleted so there's no chance of a false positive */
status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusOK( status ) )
status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,
RSA_PRIVKEY_LABEL );
if( cryptStatusOK( status ) )
status = cryptAddPrivateKey( cryptKeyset, cryptContext,
TEST_PRIVKEY_PASSWORD );
if( cryptStatusError( status ) )
{
printf( "Password change failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
cryptDestroyContext( cryptContext );
/* Close the keyset */
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
puts( "Password change for key in key file succeeded.\n" );
return( TRUE );
}
/* Write a key and cert to a file in a single operation */
static int writeSingleStepFileCert( const BOOLEAN useAltKeyfile )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptCert;
CRYPT_CONTEXT cryptContext;
int status;
puts( "Testing single-step key+cert write to key file ..." );
/* Create a self-signed CA certificate */
if( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptContext ) )
return( FALSE );
status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusError( status ) )
{
printf( "cryptCreateCert() failed with error code %d.\n", status );
return( FALSE );
}
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && !addCertFields( cryptCert, cACertData ) )
return( FALSE );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, cryptContext );
if( cryptStatusError( status ) )
{
printf( "Certificate creation failed with error code %d.\n", status );
cryptDestroyCert( status );
return( FALSE );
}
/* Open the keyset, write the key and certificate, and close it */
status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
useAltKeyfile ? TEST_PRIVKEY_ALT_FILE : TEST_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, cryptCert );
if( cryptStatusError( status ) )
{
printf( "cryptAddPublicKey() failed with error code %d, line %d.\n",
status, __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 ) )
{
printf( "Private key read from in-memory cached keyset data "
"failed with error code %d,\n line %d.\n", 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 ) )
{
printf( "Private key read from on-disk keyset data failed with "
"error code %d, line %d.\n", 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 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -