📄 ca_rev.c
字号:
/****************************************************************************
* *
* cryptlib DBMS CA Cert Revocation Interface *
* Copyright Peter Gutmann 1996-2005 *
* *
****************************************************************************/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "dbms.h"
#include "asn1.h"
#include "rpc.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "../keyset/keyset.h"
#include "../keyset/dbms.h"
#include "../misc/asn1.h"
#include "../misc/rpc.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/dbms.h"
#include "misc/asn1.h"
#include "misc/rpc.h"
#endif /* Compiler-specific includes */
#ifdef USE_DBMS
/****************************************************************************
* *
* Cert Revocation Functions *
* *
****************************************************************************/
/* Get the cert indicated in a revocation request */
static int getCertToRevoke( DBMS_INFO *dbmsInfo,
CRYPT_CERTIFICATE *iCertificate,
const CRYPT_CERTIFICATE iCertRequest )
{
char issuerID[ DBXKEYID_BUFFER_SIZE ];
int dummy, length, status;
*iCertificate = CRYPT_ERROR;
/* Extract the certificate identity information from the request and try
and fetch it from the cert store */
status = length = getKeyID( issuerID, iCertRequest,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusError( status ) )
return( status );
return( getItemData( dbmsInfo, iCertificate, &dummy,
CRYPT_IKEYID_ISSUERID, issuerID, length,
KEYMGMT_ITEM_PUBLICKEY, KEYMGMT_FLAG_NONE ) );
}
/* Handle an indirect cert revocation (one where we need to reverse a cert
issue or otherwise remove the cert without obtaining a direct revocation
request from the user). The various revocation situations are:
Complete cert renewal original cert supplied
CERTACTION_REVOKE_CERT reason = superseded
fail -> straight delete
Reverse issue due to cancel in CMP original cert supplied
CERTACTION_CREATION_REVERSE reason = neverValid
date = cert issue date
fail -> straight delete
Undo issue after restart original cert supplied
CERTACTION_CREATION_REVERSE reason = neverValid
date = cert issue date
fail -> straight delete
( Standard revocation original cert not supplied
CERTACTION_REVOKE_CERT reason = <in request>
delete request
fail -> no action ) */
int revokeCertDirect( DBMS_INFO *dbmsInfo,
const CRYPT_CERTIFICATE iCertificate,
const CRYPT_CERTACTION_TYPE action )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
time_t certDate;
int status;
assert( isHandleRangeValid( iCertificate ) );
assert( action == CRYPT_CERTACTION_REVOKE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
/* Get any information needed for the revocation from the cert */
if( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )
{
RESOURCE_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 info 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 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 );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, ( void * ) &iCertificate,
CRYPT_CERTINFO_CERTIFICATE );
if( cryptStatusOK( status ) )
{
if( action == CRYPT_CERTACTION_REVOKE_CERT )
{
static const int crlReason = CRYPT_CRLREASON_SUPERSEDED;
/* We're revoking the cert because we're about to replace it, set
the revocation reason to superseded */
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, ( void * ) &crlReason,
CRYPT_CERTINFO_CRLREASON );
}
else
{
static const int crlReason = CRYPT_CRLREASON_NEVERVALID;
RESOURCE_DATA msgData;
/* We're revoking a cert issued in error, set the revocation and
invalidity dates to the same value (the time of cert 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
way to indicate that a cert 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( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_REVOCATIONDATE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_INVALIDITYDATE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, ( void * ) &crlReason,
CRYPT_CERTINFO_CRLREASON );
}
}
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED );
if( cryptStatusOK( status ) )
status = caRevokeCert( dbmsInfo, createInfo.cryptHandle,
iCertificate, action );
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Revoke a cert from the revocation request */
int caRevokeCert( DBMS_INFO *dbmsInfo, const CRYPT_CERTIFICATE iCertRequest,
const CRYPT_CERTIFICATE iCertificate,
const CRYPT_CERTACTION_TYPE action )
{
CRYPT_CERTIFICATE iLocalCertificate = iCertificate;
CRYPT_CERTIFICATE iLocalCRL = iCertRequest;
BYTE certData[ MAX_CERT_SIZE ];
char reqCertID[ DBXKEYID_BUFFER_SIZE ], *reqCertIDptr = reqCertID;
char subjCertID[ DBXKEYID_BUFFER_SIZE ];
const BOOLEAN reqPresent = \
( action == CRYPT_CERTACTION_RESTART_REVOKE_CERT || \
( action == CRYPT_CERTACTION_REVOKE_CERT && \
iCertificate == CRYPT_UNUSED ) ) ? TRUE : FALSE;
int certDataLength, status = CRYPT_OK;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( isHandleRangeValid( iCertRequest ) );
assert( action == CRYPT_CERTACTION_REVOKE_CERT || \
action == CRYPT_CERTACTION_RESTART_REVOKE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
/* This function handles a number of operations, 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 cert 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 */
assert( ( 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 cert management operation, which passes in a single-entry
CRL), fetch the cert 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 cert being revoked via the revocation request and create
the CRL to contain the revocation information */
status = getKeyID( reqCertID, iCertRequest,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( !cryptStatusError( status ) )
status = getCertToRevoke( dbmsInfo, &iLocalCertificate,
iCertRequest );
if( cryptStatusError( status ) )
return( status );
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
iLocalCRL = createInfo.cryptHandle;
/* Fill in the CRL from the revocation request */
status = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,
( void * ) &iCertRequest,
CRYPT_IATTRIBUTE_REVREQUEST );
}
else
/* This is a direct revocation done as part of an internal cert
management operation, there's no explicit request for the
revocation present, and the caller has passed us a CRL ready to
use */
reqCertIDptr = NULL;
if( cryptStatusOK( status ) )
status = getKeyID( subjCertID, iLocalCertificate,
CRYPT_CERTINFO_FINGERPRINT_SHA );
if( !cryptStatusError( status ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -