📄 cryptcrt.c
字号:
}
if( certInfoPtr->publicKeyData != NULL )
clFree( "certificateMessageFunction", certInfoPtr->publicKeyData );
if( certInfoPtr->subjectDNdata != NULL )
clFree( "certificateMessageFunction", certInfoPtr->subjectDNdata );
if( certInfoPtr->issuerDNdata != NULL )
clFree( "certificateMessageFunction", certInfoPtr->issuerDNdata );
if( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
{
if( certInfoPtr->cCertRev->responderUrl != NULL )
clFree( "certificateMessageFunction",
certInfoPtr->cCertRev->responderUrl );
}
if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )
{
if( certInfoPtr->cCertVal->responderUrl != NULL )
clFree( "certificateMessageFunction",
certInfoPtr->cCertVal->responderUrl );
}
/* Clear the DN's if necessary */
if( certInfoPtr->issuerName != NULL )
deleteDN( &certInfoPtr->issuerName );
if( certInfoPtr->subjectName != NULL )
deleteDN( &certInfoPtr->subjectName );
/* Clear the attributes and validity/revocation info if necessary */
if( certInfoPtr->attributes != NULL )
deleteAttributes( &certInfoPtr->attributes );
if( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )
{
if( certInfoPtr->cCertVal->validityInfo != NULL )
deleteValidityEntries( &certInfoPtr->cCertVal->validityInfo );
}
if( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
{
if( certInfoPtr->cCertRev->revocations != NULL )
deleteRevocationEntries( &certInfoPtr->cCertRev->revocations );
}
/* Clear the certificate chain if necessary */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \
certInfoPtr->cCertCert->chainEnd > 0 )
{
int i;
ENSURES( certInfoPtr->cCertCert->chainEnd >= 0 && \
certInfoPtr->cCertCert->chainEnd < MAX_CHAINLENGTH );
for( i = 0; i < certInfoPtr->cCertCert->chainEnd && \
i < MAX_CHAINLENGTH; i++ )
{
krnlSendNotifier( certInfoPtr->cCertCert->chain[ i ],
IMESSAGE_DECREFCOUNT );
}
ENSURES( i < MAX_CHAINLENGTH );
}
return( CRYPT_OK );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
/* If it's a certificate chain lock the currently selected
certificate in the chain unless the message being processed is a
certificate cursor movement command or something specifically
directed at the entire chain (for example a get type or self-
signed status command - we want to get the type/status of the
chain, not of the certificates within it) */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \
certInfoPtr->cCertCert->chainPos >= 0 && \
!( ( message == MESSAGE_SETATTRIBUTE ) && \
( messageValue == CRYPT_CERTINFO_CURRENT_CERTIFICATE ) ) && \
!( ( message == MESSAGE_GETATTRIBUTE ) && \
( messageValue == CRYPT_CERTINFO_CERTTYPE || \
messageValue == CRYPT_CERTINFO_SELFSIGNED ) ) )
{
CERT_INFO *certChainInfoPtr;
int status;
ENSURES( certInfoPtr->cCertCert->chainPos >= 0 && \
certInfoPtr->cCertCert->chainPos < MAX_CHAINLENGTH );
status = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ],
OBJECT_TYPE_CERTIFICATE,
( void ** ) &certChainInfoPtr,
CRYPT_ARGERROR_OBJECT );
if( cryptStatusError( status ) )
return( status );
status = processCertAttribute( certChainInfoPtr, message,
messageDataPtr, messageValue );
krnlReleaseObject( certChainInfoPtr->objectHandle );
return( status );
}
return( processCertAttribute( certInfoPtr, message, messageDataPtr,
messageValue ) );
}
/* Process messages that compare the object */
if( message == MESSAGE_COMPARE )
{
const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
if( messageValue == MESSAGE_COMPARE_CERTOBJ )
{
/* A certificate object compare passes in a cert handle rather
than data */
return( compareCertInfo( certInfoPtr, messageValue, NULL, 0,
*( ( CRYPT_CERTIFICATE * ) messageDataPtr ) ) ? \
CRYPT_OK : CRYPT_ERROR );
}
return( compareCertInfo( certInfoPtr, messageValue, msgData->data,
msgData->length, CRYPT_UNUSED ) ? \
CRYPT_OK : CRYPT_ERROR );
}
/* Process messages that check a certificate */
if( message == MESSAGE_CHECK )
return( checkCertUsage( certInfoPtr, messageValue ) );
/* Process internal notification messages */
if( message == MESSAGE_CHANGENOTIFY )
{
/* If the object is being accessed for cryptlib-internal use, save/
restore the internal state */
if( messageValue == MESSAGE_CHANGENOTIFY_STATE )
{
if( messageDataPtr == MESSAGE_VALUE_TRUE )
{
/* Save the current volatile state so that any changes made
while the object is in use aren't reflected back to the
caller after the cryptlib-internal use has completed */
saveSelectionState( certInfoPtr->selectionState,
certInfoPtr );
}
else
{
/* Restore the volatile state from before the object was
used */
restoreSelectionState( certInfoPtr->selectionState,
certInfoPtr );
}
return( CRYPT_OK );
}
retIntError();
}
/* Process object-specific messages */
if( message == MESSAGE_CRT_SIGN )
{
int status;
REQUIRES( certInfoPtr->certificate == NULL );
/* Make sure that the signing object can actually be used for
signing */
status = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_SIGN );
if( cryptStatusError( status ) )
{
/* The only time that we can use a signing object that can't
sign is when we have a CRMF request, which can be created
with an encryption-only key if the private key POP is
performed via an out-of-band mechanism. If this is the case
we make sure that the key can decrypt, which is the other way
of performing POP if a signing key isn't available */
if( certInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )
return( CRYPT_ARGERROR_VALUE );
status = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_DECRYPT );
if( cryptStatusError( status ) )
return( CRYPT_ARGERROR_VALUE );
}
/* We're changing data in a certificate, clear the error
information */
clearErrorInfo( certInfoPtr );
return( signCert( certInfoPtr, messageValue ) );
}
if( message == MESSAGE_CRT_SIGCHECK )
{
REQUIRES( certInfoPtr->certificate != NULL || \
certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );
/* We're checking data in a certificate, clear the error
information */
clearErrorInfo( certInfoPtr );
return( checkCertValidity( certInfoPtr, messageValue ) );
}
if( message == MESSAGE_CRT_EXPORT )
{
MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
return( exportCertData( certInfoPtr, messageValue,
msgData->data, msgData->length,
&msgData->length ) );
}
retIntError();
}
/* Create a certificate object, returning a pointer to the locked
certificate info ready for further initialisation */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createCertificateInfo( OUT_PTR CERT_INFO **certInfoPtrPtr,
IN_HANDLE const CRYPT_USER iCryptOwner,
IN_ENUM( CRYPT_CERTTYPE ) \
const CRYPT_CERTTYPE_TYPE certType )
{
CRYPT_CERTIFICATE iCertificate;
CERT_INFO *certInfoPtr;
OBJECT_SUBTYPE subType;
int storageSize, status;
assert( isWritePtr( certInfoPtrPtr, sizeof( CERT_INFO * ) ) );
REQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \
isHandleRangeValid( iCryptOwner ) );
REQUIRES( certType > CRYPT_CERTTYPE_NONE && \
certType < CRYPT_CERTTYPE_LAST );
/* Clear the return values */
*certInfoPtrPtr = NULL;
/* Set up subtype-specific information */
switch( certType )
{
case CRYPT_CERTTYPE_CERTIFICATE:
case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
subType = ( certType == CRYPT_CERTTYPE_CERTIFICATE ) ? \
SUBTYPE_CERT_CERT : SUBTYPE_CERT_ATTRCERT;
storageSize = sizeof( CERT_CERT_INFO );
break;
case CRYPT_CERTTYPE_CERTCHAIN:
/* A certificate chain is a special case of a cert (and/or vice
versa) so it uses the same subtype-specific storage */
subType = SUBTYPE_CERT_CERTCHAIN;
storageSize = sizeof( CERT_CERT_INFO );
break;
case CRYPT_CERTTYPE_CERTREQUEST:
subType = SUBTYPE_CERT_CERTREQ;
storageSize = 0;
break;
case CRYPT_CERTTYPE_REQUEST_CERT:
case CRYPT_CERTTYPE_REQUEST_REVOCATION:
subType = ( certType == CRYPT_CERTTYPE_REQUEST_CERT ) ? \
SUBTYPE_CERT_REQ_CERT : SUBTYPE_CERT_REQ_REV;
storageSize = sizeof( CERT_REQ_INFO );
break;
case CRYPT_CERTTYPE_CRL:
subType = SUBTYPE_CERT_CRL;
storageSize = sizeof( CERT_REV_INFO );
break;
case CRYPT_CERTTYPE_CMS_ATTRIBUTES:
subType = SUBTYPE_CERT_CMSATTR;
storageSize = 0;
break;
case CRYPT_CERTTYPE_RTCS_REQUEST:
case CRYPT_CERTTYPE_RTCS_RESPONSE:
subType = ( certType == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
SUBTYPE_CERT_RTCS_REQ : SUBTYPE_CERT_RTCS_RESP;
storageSize = sizeof( CERT_VAL_INFO );
break;
case CRYPT_CERTTYPE_OCSP_REQUEST:
case CRYPT_CERTTYPE_OCSP_RESPONSE:
subType = ( certType == CRYPT_CERTTYPE_OCSP_REQUEST ) ? \
SUBTYPE_CERT_OCSP_REQ : SUBTYPE_CERT_OCSP_RESP;
storageSize = sizeof( CERT_REV_INFO );
break;
case CRYPT_CERTTYPE_PKIUSER:
subType = SUBTYPE_CERT_PKIUSER;
storageSize = sizeof( CERT_PKIUSER_INFO );
break;
default:
retIntError();
}
/* Create the certificate object */
status = krnlCreateObject( &iCertificate, ( void ** ) &certInfoPtr,
sizeof( CERT_INFO ) + storageSize,
OBJECT_TYPE_CERTIFICATE, subType,
CREATEOBJECT_FLAG_NONE, iCryptOwner,
ACTION_PERM_NONE_ALL,
certificateMessageFunction );
if( cryptStatusError( status ) )
return( status );
certInfoPtr->objectHandle = iCertificate;
certInfoPtr->ownerHandle = iCryptOwner;
certInfoPtr->type = certType;
switch( certInfoPtr->type )
{
case CRYPT_CERTTYPE_CERTIFICATE:
case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
case CRYPT_CERTTYPE_CERTCHAIN:
certInfoPtr->cCertCert = ( CERT_CERT_INFO * ) certInfoPtr->storage;
certInfoPtr->cCertCert->chainPos = CRYPT_ERROR;
certInfoPtr->cCertCert->trustedUsage = CRYPT_ERROR;
break;
case CRYPT_CERTTYPE_REQUEST_CERT:
case CRYPT_CERTTYPE_REQUEST_REVOCATION:
certInfoPtr->cCertReq = ( CERT_REQ_INFO * ) certInfoPtr->storage;
break;
case CRYPT_CERTTYPE_CRL:
case CRYPT_CERTTYPE_OCSP_REQUEST:
case CRYPT_CERTTYPE_OCSP_RESPONSE:
certInfoPtr->cCertRev = ( CERT_REV_INFO * ) certInfoPtr->storage;
break;
case CRYPT_CERTTYPE_RTCS_REQUEST:
case CRYPT_CERTTYPE_RTCS_RESPONSE:
certInfoPtr->cCertVal = ( CERT_VAL_INFO * ) certInfoPtr->storage;
break;
case CRYPT_CERTTYPE_PKIUSER:
certInfoPtr->cCertUser = ( CERT_PKIUSER_INFO * ) certInfoPtr->storage;
break;
case CRYPT_CERTTYPE_CERTREQUEST:
case CRYPT_CERTTYPE_CMS_ATTRIBUTES:
/* No special storage requirements */
break;
default:
retIntError();
}
/* Set up the default version number. These values are set here mostly
so that attempting to read the version attribute won't return a
version of 0.
In some cases this is an indication only and will be modified based
on information added to the object (for example the CRL version is
implicitly set based on whether extensions are added or not). If this
can happen we start with the lowest version available (the default
v1) which will be automatically incremented whenever information that
can't be represented with that format version is added */
switch( certType )
{
case CRYPT_CERTTYPE_CERTIFICATE:
case CRYPT_CERTTYPE_CERTCHAIN:
certInfoPtr->version = 3;
break;
case CRYPT_CERTTYPE_ATTRIBUTE_CERT:
certInfoPtr->version = 2;
break;
default:
certInfoPtr->version = 1;
break;
}
/* Set up any internal objects to contain invalid handles */
certInfoPtr->iPubkeyContext = CRYPT_ERROR;
/* Set the state information to its initial state */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -