📄 keyfile.c
字号:
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusError( status ) )
{
printf( "cryptCreateCert() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, publicKeyContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptCert, cACertData, __LINE__ ) )
return( FALSE );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, privateKeyContext );
destroyContexts( CRYPT_UNUSED, publicKeyContext, privateKeyContext );
if( cryptStatusError( status ) )
{
printf( "Certificate creation failed with error code %d, "
"line %d.\n", status, __LINE__ );
cryptDestroyCert( status );
return( FALSE );
}
/* Open the keyset, update it with the certificate, and close it */
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 );
}
status = cryptAddPublicKey( cryptKeyset, cryptCert );
if( cryptStatusError( status ) )
{
printExtError( cryptKeyset, "cryptAddPublicKey()", 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 int writeFileCertChain( const CERT_DATA *certRequestData,
const C_STR keyFileName,
const C_STR certFileName,
const BOOLEAN isTestRun,
const BOOLEAN writeLongChain )
{
CRYPT_KEYSET cryptKeyset;
CRYPT_CERTIFICATE cryptCertChain;
CRYPT_CONTEXT cryptCAKey, cryptKey;
int status;
if( isTestRun )
{
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 ) )
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,
keyFileName, 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 ) )
{
printExtError( cryptKeyset, "cryptAddPrivateKey()", 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, __LINE__ ) )
return( FALSE );
#ifndef _WIN32_WCE /* Windows CE doesn't support ANSI C time functions */
if( cryptStatusOK( status ) && !isTestRun )
{
const time_t validity = time( NULL ) + ( 86400L * 365 * 3 );
/* 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 */
status = cryptSetAttributeString( cryptCertChain,
CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
}
#endif /* WinCE */
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 ) )
{
printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
__LINE__ );
return( FALSE );
}
if( certFileName != NULL )
{
FILE *filePtr;
BYTE certBuffer[ BUFFER_SIZE ];
int length;
/* Save the cert to disk for use in request/response protocols */
status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE,
cryptCertChain );
if( cryptStatusError( status ) )
{
printf( "cryptExportCert() failed with error code %d, "
"line %d.\n", status, __LINE__ );
return( FALSE );
}
if( ( filePtr = fopen( convertFileName( certFileName ), \
"wb" ) ) != NULL )
{
fwrite( certBuffer, length, 1, filePtr );
fclose( filePtr );
}
}
cryptDestroyCert( cryptCertChain );
status = cryptKeysetClose( cryptKeyset );
if( cryptStatusError( status ) )
{
printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
if( isTestRun )
puts( "Cert chain write to key file succeeded.\n" );
return( TRUE );
}
static const CERT_DATA FAR_BSS certRequestData[] = {
/* Identification information */
{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
{ 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 */
{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
};
int testWriteFileCertChain( void )
{
return( writeFileCertChain( certRequestData, TEST_PRIVKEY_FILE, NULL,
TRUE, FALSE ) );
}
int testWriteFileLongCertChain( void )
{
return( writeFileCertChain( certRequestData, TEST_PRIVKEY_FILE, NULL,
TRUE, 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 ) )
{
printExtError( cryptKeyset, "cryptDeletePrivateKey()", 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 ) )
{
printExtError( cryptKeyset, "password change", 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, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusOK( status ) && \
!addCertFields( cryptCert, cACertData, __LINE__ ) )
return( FALSE );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, cryptContext );
if( cryptStatusError( status ) )
{
printf( "Certificate creation failed with error code %d, "
"line %d.\n", status, __LINE__ );
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 ) )
{
printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
__LINE__ );
return( FALSE );
}
status = cryptAddPublicKey( cryptKeyset, cryptCert );
if( cryptStatusError( status ) )
{
printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -