📄 certproc.c
字号:
/****************************************************************************
* *
* cryptlib Certificate Handling Test Routines *
* Copyright Peter Gutmann 1997-2005 *
* *
****************************************************************************/
#include "cryptlib.h"
#include "test/test.h"
#if defined( __MVS__ ) || defined( __VMCMS__ )
/* Suspend conversion of literals to ASCII. */
#pragma convlit( suspend )
#endif /* IBM big iron */
#if defined( __ILEC400__ )
#pragma convert( 0 )
#endif /* IBM medium iron */
extern BYTE FAR_BSS certBuffer[ BUFFER_SIZE ];
/****************************************************************************
* *
* Certificate Processing Test *
* *
****************************************************************************/
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" ) },
/* Subject altName */
{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( "dave@wetas-r-us.com" ) },
{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( "http://www.wetas-r-us.com" ) },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
static const CERT_DATA FAR_BSS certProcessData[] = {
/* 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" ) },
/* Subject altName */
{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( "dave@wetas-r-us.com" ) },
{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( "http://www.wetas-r-us.com" ) },
/* Re-select the subject name after poking around in the altName */
{ CRYPT_CERTINFO_SUBJECTNAME, IS_NUMERIC, CRYPT_UNUSED },
{ CRYPT_ATTRIBUTE_NONE, IS_VOID }
};
/* Create a certification request */
static int createCertRequest( void *certRequest,
const CRYPT_ALGO_TYPE cryptAlgo,
const BOOLEAN useCRMF )
{
CRYPT_CERTIFICATE cryptCert;
CRYPT_CONTEXT cryptContext;
int length, status;
/* Create a new key */
status = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );
if( cryptStatusError( status ) )
return( status );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
TEXT( "Private key" ),
paramStrlen( TEXT( "Private key" ) ) );
status = cryptGenerateKey( cryptContext );
if( cryptStatusError( status ) )
return( status );
/* Create the certification request */
status = cryptCreateCert( &cryptCert, CRYPT_UNUSED, useCRMF ? \
CRYPT_CERTTYPE_REQUEST_CERT : CRYPT_CERTTYPE_CERTREQUEST );
if( cryptStatusError( status ) )
return( status );
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusError( status ) )
return( status );
if( !addCertFields( cryptCert, certRequestData, __LINE__ ) )
return( -1 );
#ifndef _WIN32_WCE
if( useCRMF )
{
const time_t startTime = time( NULL ) - 1000;
const time_t endTime = time( NULL ) + 86400;
/* Since we're using a CRMF request, set some fields that can't
be specified in the standard cert request */
status = cryptSetAttributeString( cryptCert,
CRYPT_CERTINFO_VALIDFROM, &startTime, sizeof( time_t ) );
if( cryptStatusOK( status ) )
status = cryptSetAttributeString( cryptCert,
CRYPT_CERTINFO_VALIDTO, &endTime, sizeof( time_t ) );
}
#endif /* _WIN32_WCE */
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, cryptContext );
if( cryptStatusOK( status ) )
status = cryptExportCert( certRequest, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );
if( cryptStatusOK( status ) )
status = cryptDestroyCert( cryptCert );
if( cryptStatusError( status ) )
return( status );
/* Clean up */
cryptDestroyContext( cryptContext );
return( length );
}
/* Create a certificate from a cert request */
static int createCertificate( void *certificate, const void *certRequest,
const int certReqLength,
const CRYPT_CONTEXT caKeyContext )
{
CRYPT_CERTIFICATE cryptCert, cryptCertRequest;
int length, status;
/* Import and verify the certification request */
status = cryptImportCert( certRequest, certReqLength, CRYPT_UNUSED,
&cryptCertRequest );
if( cryptStatusOK( status ) )
status = cryptCheckCert( cryptCertRequest, CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( status );
/* Create the certificate */
status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_CERTREQUEST, cryptCertRequest );
if( cryptStatusOK( status ) )
status = cryptSignCert( cryptCert, caKeyContext );
if( cryptStatusOK( status ) )
status = cryptExportCert( certificate, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );
if( cryptStatusOK( status ) )
status = cryptDestroyCert( cryptCert );
/* Clean up */
cryptDestroyCert( cryptCertRequest );
return( ( cryptStatusOK( status ) ) ? length : status );
}
/* Create a certificate directly, used for algorithms that don't support
self-signed cert requests */
static int createCertDirect( void *certificate,
const CRYPT_ALGO_TYPE cryptAlgo,
const CRYPT_CONTEXT caKeyContext )
{
CRYPT_CERTIFICATE cryptCert;
CRYPT_CONTEXT cryptContext;
int length, status;
/* Create a new key */
status = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );
if( cryptStatusError( status ) )
return( status );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
TEXT( "Private key" ),
paramStrlen( TEXT( "Private key" ) ) );
status = cryptGenerateKey( cryptContext );
if( cryptStatusError( status ) )
return( status );
/* Create the certification */
status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
status = cryptSetAttribute( cryptCert,
CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
if( cryptStatusError( status ) )
return( status );
if( !addCertFields( cryptCert, certProcessData, __LINE__ ) )
return( FALSE );
status = cryptSignCert( cryptCert, caKeyContext );
if( cryptStatusOK( status ) )
status = cryptExportCert( certificate, BUFFER_SIZE, &length,
CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );
if( cryptStatusOK( status ) )
status = cryptDestroyCert( cryptCert );
/* Clean up */
cryptDestroyContext( cryptContext );
return( ( cryptStatusOK( status ) ) ? length : status );
}
/* Test the full certification process */
static int certProcess( const CRYPT_ALGO_TYPE cryptAlgo,
const char *algoName,
const CRYPT_CONTEXT cryptCAKey,
const BOOLEAN useCRMF )
{
CRYPT_CERTIFICATE cryptCert;
const char *certName = \
( cryptAlgo == CRYPT_ALGO_RSA ) ? \
( useCRMF ? "prcrtrsa_c" : "prcrtrsa" ) : \
( cryptAlgo == CRYPT_ALGO_DSA ) ? "prcrtdsa" : \
( cryptAlgo == CRYPT_ALGO_DH ) ? "prcrtdh" : \
( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? "prcrtelg" : "prcrtxxx";
int length, status;
printf( "Testing %s certificate processing%s...\n", algoName,
useCRMF ? " from CRMF request" : "" );
/* Some algorithms can't create self-signed cert requests so we have to
create the cert directly */
if( cryptAlgo != CRYPT_ALGO_ELGAMAL && cryptAlgo != CRYPT_ALGO_DH )
{
const char *reqName = \
( cryptAlgo == CRYPT_ALGO_RSA ) ? \
( useCRMF ? "prreqrsa_c" : "prreqrsa" ) : \
( cryptAlgo == CRYPT_ALGO_DSA ) ? "prreqdsa" : \
( cryptAlgo == CRYPT_ALGO_DH ) ? "prreqdh" : \
( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? "prreqelg" : "prreqxxx";
/* Create the certification request */
status = length = createCertRequest( certBuffer, cryptAlgo, useCRMF );
if( cryptStatusError( status ) )
{
printf( "Certification request creation failed with error code "
"%d, line %d.\n", status, __LINE__ );
return( FALSE );
}
debugDump( reqName, certBuffer, length );
/* Create a certificate from the certification request */
status = createCertificate( certBuffer, certBuffer, length,
cryptCAKey );
}
else
status = createCertDirect( certBuffer, cryptAlgo, cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Certificate creation failed with error code %d, line "
"%d.\n", status, __LINE__ );
return( FALSE );
}
length = status;
debugDump( certName, certBuffer, length );
/* Import the certificate and check its validity using the CA key (we use
the private key context since it's handy, in practice we should use
the public key certificate */
status = cryptImportCert( certBuffer, length, CRYPT_UNUSED,
&cryptCert );
if( cryptStatusOK( status ) )
status = cryptCheckCert( cryptCert, cryptCAKey );
if( cryptStatusError( status ) )
{
printf( "Certificate validation failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Clean up */
cryptDestroyCert( cryptCert );
printf( "%s certificate processing succeeded.\n\n", algoName );
return( TRUE );
}
int testCertProcess( void )
{
CRYPT_CONTEXT cryptCAKey;
int status;
/* Get the CA's private 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 );
}
/* Test each PKC algorithm */
if( !certProcess( CRYPT_ALGO_RSA, "RSA", cryptCAKey, FALSE ) )
return( FALSE );
if( !certProcess( CRYPT_ALGO_DSA, "DSA", cryptCAKey, FALSE ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -