📄 ca_issue.c
字号:
iReplaceCertificate );
if( cryptStatusOK( status ) )
{
status = getItemData( dbmsInfo, &iOrigCertificate, &dummy,
KEYMGMT_ITEM_PUBLICKEY, CRYPT_IKEYID_KEYID,
keyID, keyIDlength, KEYMGMT_FLAG_NONE,
errorInfo );
if( status == CRYPT_ERROR_NOTFOUND )
{
/* If the original certificate fetch fails with a notfound error
this is OK since we may be resuming from a point where the
revocation has already occurred or the certificate may have
already expired or been otherwise replaced, so we just slide
in the new certificate */
return( completeCert( dbmsInfo, iReplaceCertificate,
CERTADD_RENEWAL_COMPLETE, errorInfo ) );
}
}
if( cryptStatusError( status ) )
{
retExtErr( status,
( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
"Couldn't get information for the certificate to be "
"renewed: " ) );
}
/* Replace the original certificate with the new one */
status = revokeCertDirect( dbmsInfo, iOrigCertificate,
CRYPT_CERTACTION_REVOKE_CERT, errorInfo );
if( cryptStatusOK( status ) )
status = completeCert( dbmsInfo, iReplaceCertificate,
CERTADD_RENEWAL_COMPLETE, errorInfo );
krnlSendNotifier( iOrigCertificate, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Issue a certificate from a certificate request */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
int caIssueCert( INOUT DBMS_INFO *dbmsInfo,
OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,
IN_HANDLE const CRYPT_CERTIFICATE caKey,
IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,
IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,
INOUT ERROR_INFO *errorInfo )
{
CRYPT_CERTIFICATE iLocalCertificate;
MESSAGE_CREATEOBJECT_INFO createInfo;
BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
BYTE certData[ MAX_CERT_SIZE + 8 ];
char issuerID[ ENCODED_DBXKEYID_SIZE + 8 ];
char certID[ ENCODED_DBXKEYID_SIZE + 8 ];
char reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ];
CERTADD_TYPE addType = CERTADD_NORMAL, issueType;
int certDataLength = DUMMY_INIT, issuerIDlength, certIDlength;
int reqCertIDlength = DUMMY_INIT, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
assert( ( iCertificate == NULL ) || \
isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
REQUIRES( isHandleRangeValid( caKey ) );
REQUIRES( isHandleRangeValid( iCertRequest ) );
REQUIRES( action == CRYPT_CERTACTION_ISSUE_CERT || \
action == CRYPT_CERTACTION_CERT_CREATION );
REQUIRES( errorInfo != NULL );
/* Clear return value */
if( iCertificate != NULL )
*iCertificate = CRYPT_ERROR;
/* Extract the information that we need from the certificate request */
status = getCertIssueType( dbmsInfo, iCertRequest, &issueType, FALSE );
if( cryptStatusOK( status ) )
status = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength,
iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
{
if( cryptArgError( status ) )
status = CAMGMT_ARGERROR_REQUEST;
retExtArg( status,
( status, errorInfo,
"Couldn't extract certificate request information "
"needed to issue certificate" ) );
}
/* We're ready to perform the certificate issue transaction. First we
turn the request into a certificate */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
iLocalCertificate = createInfo.cryptHandle;
status = krnlSendMessage( iLocalCertificate, IMESSAGE_SETATTRIBUTE,
( void * ) &iCertRequest,
CRYPT_CERTINFO_CERTREQUEST );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Couldn't create certificate from certificate request "
"data" ) );
}
/* Sanitise the new certificate of potentially dangerous attributes */
status = sanitiseCertAttributes( iLocalCertificate );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
retExtArg( status,
( status, errorInfo,
"Certificate request contains attributes that would "
"result in the creation of a CA rather than a normal "
"user certificate" ) );
}
/* Finally, sign the certificate */
status = krnlSendMessage( iLocalCertificate, IMESSAGE_CRT_SIGN, NULL,
caKey );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
if( status == CRYPT_ARGERROR_VALUE )
status = CAMGMT_ARGERROR_CAKEY;
retExtArg( status,
( status, errorInfo,
"Couldn't sign certificate created from certificate "
"request" ) );
}
/* Extract the information that we need from the newly-created
certificate */
status = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength,
iLocalCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusOK( status ) )
status = getKeyID( issuerID, ENCODED_DBXKEYID_SIZE, &issuerIDlength,
iLocalCertificate,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( status ) )
status = extractCertData( iLocalCertificate,
CRYPT_CERTFORMAT_CERTIFICATE, certData,
MAX_CERT_SIZE, &certDataLength );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Couldn't extract new certificate data to add to "
"certificate store" ) );
}
/* If we're doing a partial certificate creation, handle the
complexities created by things like certificate renewals that create
pseudo-duplicates while the update is taking place */
if( action == CRYPT_CERTACTION_CERT_CREATION )
{
status = checkDuplicateAdd( dbmsInfo, iLocalCertificate, issueType );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, errorInfo,
"Certificate already exists in certificate store" ) );
}
/* This is a partial add, make sure that the certificate is added in
the appropriate manner */
addType = CERTADD_PARTIAL;
}
/* Update the certificate store */
status = addCert( dbmsInfo, iLocalCertificate, CRYPT_CERTTYPE_CERTIFICATE,
addType, DBMS_UPDATE_BEGIN, errorInfo );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, action, certID, certIDlength,
reqCertID, reqCertIDlength, NULL, 0,
certData, certDataLength,
DBMS_UPDATE_CONTINUE );
if( cryptStatusOK( status ) )
{
initBoundData( boundDataPtr );
setBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );
status = dbmsUpdate(
"DELETE FROM certRequests WHERE certID = ?",
boundDataPtr, DBMS_UPDATE_COMMIT );
}
else
{
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );
}
/* If the operation failed, record the details */
if( cryptStatusError( status ) )
{
updateCertErrorLog( dbmsInfo, status,
( action == CRYPT_CERTACTION_ISSUE_CERT ) ? \
"Certificate issue operation failed" : \
"Certificate creation operation failed",
NULL, 0, reqCertID, reqCertIDlength, NULL, 0,
NULL, 0 );
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
retExtErr( status,
( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
( action == CRYPT_CERTACTION_ISSUE_CERT ) ? \
"Certificate issue operation failed: " : \
"Certificate creation operation failed: " ) );
}
/* The certificate has been successfully issued, return it to the caller
if necessary */
if( iCertificate != NULL )
*iCertificate = iLocalCertificate;
else
{
/* The caller isn't interested in the certificate, destroy it */
krnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );
}
return( CRYPT_OK );
}
/* Complete a previously-started certificate issue */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
int caIssueCertComplete( INOUT DBMS_INFO *dbmsInfo,
IN_HANDLE const CRYPT_CERTIFICATE iCertificate,
IN_ENUM( CRYPT_CERTACTION ) \
const CRYPT_CERTACTION_TYPE action,
INOUT ERROR_INFO *errorInfo )
{
char certID[ ENCODED_DBXKEYID_SIZE + 8 ];
int certIDlength, status;
assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );
REQUIRES( isHandleRangeValid( iCertificate ) );
REQUIRES( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE || \
action == CRYPT_CERTACTION_CERT_CREATION_DROP || \
action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
REQUIRES( errorInfo != NULL );
/* Extract the information that we need from the certificate */
status = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength,
iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA );
if( cryptStatusError( status ) )
return( status );
/* If we're completing the certificate issue process, replace the
incomplete certificate with the completed one and exit */
if( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE )
{
CERTADD_TYPE issueType;
status = getCertIssueType( dbmsInfo, iCertificate, &issueType, TRUE );
if( cryptStatusError( status ) )
{
retExt( status,
( status, errorInfo,
"Couldn't get original certificate issue type to "
"complete certificate issue operation: " ) );
}
status = completeCert( dbmsInfo, iCertificate, issueType, errorInfo );
if( cryptStatusError( status ) )
return( status );
/* If we're doing a certificate renewal, complete the multi-phase
update required to replace an existing certificate */
if( issueType == CERTADD_PARTIAL_RENEWAL )
{
return( completeCertRenewal( dbmsInfo, iCertificate,
errorInfo ) );
}
return( CRYPT_OK );
}
/* If we're abandoning the certificate issue process, delete the
incomplete certificate and exit */
if( action == CRYPT_CERTACTION_CERT_CREATION_DROP )
{
BOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;
char incompleteCertID[ ENCODED_DBXKEYID_SIZE + 8 ];
memcpy( incompleteCertID, certID, certIDlength );
memcpy( incompleteCertID, KEYID_ESC1, KEYID_ESC_SIZE );
initBoundData( boundDataPtr );
setBoundData( boundDataPtr, 0, incompleteCertID, certIDlength );
status = dbmsUpdate(
"DELETE FROM certificates WHERE certID = ?",
boundDataPtr, DBMS_UPDATE_BEGIN );
if( cryptStatusOK( status ) )
status = updateCertLog( dbmsInfo, action, NULL, 0, NULL, 0,
certID, certIDlength, NULL, 0,
DBMS_UPDATE_COMMIT );
else
{
/* Something went wrong, abort the transaction */
dbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );
}
if( cryptStatusOK( status ) )
return( CRYPT_OK );
/* The drop operation failed, record the details and fall back to a
straight delete */
updateCertErrorLog( dbmsInfo, status,
"Certificate creation - drop operation failed, "
"performing straight delete", NULL, 0, NULL, 0,
certID, certIDlength, NULL, 0 );
status = dbmsUpdate(
"DELETE FROM certificates WHERE certID = ?",
boundDataPtr, DBMS_UPDATE_NORMAL );
if( cryptStatusError( status ) )
{
updateCertErrorLogMsg( dbmsInfo, status, "Fallback straight "
"delete failed" );
retExtErr( status,
( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
"Certificate creation - drop operation failed: " ) );
}
return( CRYPT_OK );
}
/* We're reversing a certificate creation as a compensating transaction
for an aborted certificate issue, we need to explicitly revoke the
certificate rather than just deleting it */
ENSURES( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );
return( revokeCertDirect( dbmsInfo, iCertificate,
CRYPT_CERTACTION_CERT_CREATION_REVERSE,
errorInfo ) );
}
#endif /* USE_DBMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -