📄 ca_rev.c
字号:
/****************************************************************************
* *
* cryptlib DBMS CA Certificate Revocation Interface *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "dbms.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/dbms.h"
#endif /* Compiler-specific includes */
#ifdef USE_DBMS
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Get the certificate indicated in a revocation request */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int getCertToRevoke( INOUT DBMS_INFO *dbmsInfo,
OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
INOUT ERROR_INFO *errorInfo )
{
char issuerID[ ENCODED_DBXKEYID_SIZE + 8 ];
int dummy, issuerIDlength, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
REQUIRES( isHandleRangeValid( iCertRequest ) );
REQUIRES( errorInfo != NULL );
/* Clear return value */
*iCertificate = CRYPT_ERROR;
/* Extract the certificate identity information from the request and try
and fetch it from the certificate store */
status = getKeyID( issuerID, ENCODED_DBXKEYID_SIZE, &issuerIDlength,
iCertRequest, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
return( status );
return( getItemData( dbmsInfo, iCertificate, &dummy,
KEYMGMT_ITEM_PUBLICKEY, CRYPT_IKEYID_ISSUERID,
issuerID, issuerIDlength, KEYMGMT_FLAG_NONE,
errorInfo ) );
}
/****************************************************************************
* *
* Certificate Revocation Functions *
* *
****************************************************************************/
/* Handle an indirect certificate revocation (one where we need to reverse a
certificate issue or otherwise remove the certificate without obtaining a
direct revocation request from the user). The various revocation
situations are:
Complete cert renewal original certificate supplied
CERTACTION_REVOKE_CERT reason = superseded
fail -> straight delete
Reverse issue due to cancel in CMP original certificate supplied
CERTACTION_CREATION_REVERSE reason = neverValid
date = certificate issue date
fail -> straight delete
Undo issue after restart original certificate supplied
CERTACTION_CREATION_REVERSE reason = neverValid
date = certificate issue date
fail -> straight delete
( Standard revocation original certificate not supplied
CERTACTION_REVOKE_CERT reason = <in request>
delete request
fail -> no action ) */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
int revokeCertDirect( INOUT DBMS_INFO *dbmsInfo,
IN_HANDLE const CRYPT_CERTIFICATE iCertificate,
IN_ENUM( CRYPT_CERTACTION ) \
const CRYPT_CERTACTION_TYPE action,
INOUT ERROR_INFO *errorInfo )
{
CRYPT_CERTIFICATE iLocalCRL;
MESSAGE_CREATEOBJECT_INFO createInfo;
time_t certDate;
int status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
REQUIRES( isHandleRangeValid( iCertificate ) );
REQUIRES( action == CRYPT_CERTACTION_REVOKE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
REQUIRES( errorInfo != NULL );
/* Get any information needed for the revocation from the certificate */
if( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )
{
MESSAGE_DATA msgData;
setMessageData( &msgData, &certDate, sizeof( time_t ) );
status = krnlSendMessage( iCertificate, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_VALIDFROM );
if( cryptStatusError( status ) )
return( status );
}
/* Create a (single-entry) CRL to contain the revocation information for
the certificate and revoke it via the standard channels. We go
directly to a CRL rather than doing it via a revocation request
because we need to add information that can only be added by a CA and
only to a CRL */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
iLocalCRL = createInfo.cryptHandle;
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,
( void * ) &iCertificate,
CRYPT_CERTINFO_CERTIFICATE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Couldn't create CRL entry from certificate to be "
"revoked" ) );
}
if( action == CRYPT_CERTACTION_REVOKE_CERT )
{
static const int crlReason = CRYPT_CRLREASON_SUPERSEDED;
/* We're revoking the certificate because we're about to replace it,
set the revocation reason to superseded */
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,
( void * ) &crlReason,
CRYPT_CERTINFO_CRLREASON );
}
else
{
static const int crlReason = CRYPT_CRLREASON_NEVERVALID;
MESSAGE_DATA msgData;
/* We're revoking a certificate issued in error, set the revocation
and invalidity dates to the same value (the time of certificate
issue) in the hope of ensuring that it's regarded as never being
valid. This isn't too accurate but since X.509 makes the
assumption that all CAs are perfect and never make mistakes
there's no other way to indicate that a certificate was issued in
error. In addition to this we set the extended reason to
neverValid, but not too many implementations will check this */
setMessageData( &msgData, &certDate, sizeof( time_t ) );
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_REVOCATIONDATE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_INVALIDITYDATE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,
( void * ) &crlReason, CRYPT_CERTINFO_CRLREASON );
}
if( cryptStatusOK( status ) )
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Couldn't add revocation status information to CRL for "
"certificate revocation" ) );
}
status = caRevokeCert( dbmsInfo, iLocalCRL, iCertificate, action,
errorInfo );
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Revoke a certificate from a revocation request */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
int caRevokeCert( INOUT DBMS_INFO *dbmsInfo,
IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
IN_HANDLE_OPT const CRYPT_CERTIFICATE iCertificate,
IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,
INOUT ERROR_INFO *errorInfo )
{
CRYPT_CERTIFICATE iLocalCertificate = iCertificate;
CRYPT_CERTIFICATE iLocalCRL = iCertRequest;
BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
BYTE certData[ MAX_CERT_SIZE + 8 ];
char reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ], *reqCertIDptr = reqCertID;
char subjCertID[ ENCODED_DBXKEYID_SIZE + 8 ];
char specialCertID[ ENCODED_DBXKEYID_SIZE + 8 ];
const BOOLEAN reqPresent = \
( action == CRYPT_CERTACTION_RESTART_REVOKE_CERT || \
( action == CRYPT_CERTACTION_REVOKE_CERT && \
iCertificate == CRYPT_UNUSED ) ) ? TRUE : FALSE;
int certDataLength = DUMMY_INIT, reqCertIDlength, subjCertIDlength;
int specialCertIDlength = DUMMY_INIT, status = CRYPT_OK;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
REQUIRES( isHandleRangeValid( iCertRequest ) );
REQUIRES( iCertificate == CRYPT_UNUSED || \
isHandleRangeValid( iCertificate ) );
REQUIRES( action == CRYPT_CERTACTION_REVOKE_CERT || \
action == CRYPT_CERTACTION_RESTART_REVOKE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
REQUIRES( errorInfo != NULL );
/* This function handles a number of operations as summarised in the
table below:
Operation Action Request On disk Cert
--------- ------ ------- ------- ----
Complete revocation RESTART_REVOKE_CERT Rev.req Yes --
on restart
Standard revocation REVOKE_CERT Rev.req Yes --
Complete renewal REVOKE_CERT crlEntry -- Supplied
Reverse issue (CMP CREATION_REVERSE crlEntry -- Supplied
or due to restart)
The following assertion checks that the certificate parameter is
correct. Checking the request parameter isn't so easy since it
requires multiple function calls, and is done as part of the code */
REQUIRES( ( action == CRYPT_CERTACTION_RESTART_REVOKE_CERT && \
iCertificate == CRYPT_UNUSED ) || \
( action == CRYPT_CERTACTION_REVOKE_CERT ) || \
( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE && \
isHandleRangeValid( iCertificate ) ) );
/* If it's a standard revocation (rather than one done as part of an
internal certificate management operation, which passes in a single-
entry CRL) fetch the certificate that we're going to revoke and set
up a CRL object to contain the revocation information */
if( iCertificate == CRYPT_UNUSED )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
/* Get the certificate being revoked via the revocation request */
status = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength,
iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( status ) )
status = getCertToRevoke( dbmsInfo, &iLocalCertificate,
iCertRequest, errorInfo );
if( cryptStatusError( status ) )
{
retExtErr( status,
( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
"Couldn't find certificate to revoke in "
"certificate store: " ) );
}
/* Create the CRL to contain the revocation information */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
{
/* Fill in the CRL from the revocation request */
iLocalCRL = createInfo.cryptHandle;
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,
( void * ) &iCertRequest,
CRYPT_IATTRIBUTE_REVREQUEST );
if( cryptStatusError( status ) )
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Couldn't create CRL from revocation request" ) );
}
}
else
{
/* This is a direct revocation done as part of an internal
certificate management operation, there's no explicit request
for the revocation present and the caller has passed us a CRL
ready to use */
reqCertIDptr = NULL;
reqCertIDlength = 0;
}
status = getKeyID( subjCertID, ENCODED_DBXKEYID_SIZE, &subjCertIDlength,
iLocalCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( status ) )
status = extractCertData( iLocalCRL, CRYPT_IATTRIBUTE_CRLENTRY,
certData, MAX_CERT_SIZE, &certDataLength );
if( cryptStatusError( status ) )
{
/* If we created the necessary objects locally rather than having
them passed in by the caller we have to clean them up again
before we exit */
if( iCertificate == CRYPT_UNUSED )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
krnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );
}
retExt( status,
( status, errorInfo,
"Couldn't extract CRL data to add to certificate store" ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -