📄 cryptcrt.c
字号:
{
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
}
if( cryptStatusError( status ) )
return( status );
/* Send the public-key data to the context */
setMessageData( &msgData, spkiPtr, spkiLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
deferredLoad ? \
CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL : \
CRYPT_IATTRIBUTE_KEY_SPKI );
if( cryptStatusError( status ) )
{
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
return( status );
}
*iPubkeyContext = createInfo.cryptHandle;
assert( cryptStatusError( \
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_PRIVATE ) ) );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Certificate Management API Functions *
* *
****************************************************************************/
/* Handle data sent to or read from a cert object */
static int processCertData( CERT_INFO *certInfoPtr,
const MESSAGE_TYPE message,
void *messageDataPtr, const int messageValue )
{
RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
int *valuePtr = ( int * ) messageDataPtr;
/* Process get/set/delete attribute messages */
if( message == MESSAGE_GETATTRIBUTE )
{
if( messageValue == CRYPT_ATTRIBUTE_ERRORTYPE )
{
*valuePtr = certInfoPtr->errorType;
return( CRYPT_OK );
}
if( messageValue == CRYPT_ATTRIBUTE_ERRORLOCUS )
{
*valuePtr = certInfoPtr->errorLocus;
return( CRYPT_OK );
}
return( getCertComponent( certInfoPtr, messageValue, valuePtr, NULL ) );
}
if( message == MESSAGE_GETATTRIBUTE_S )
return( getCertComponent( certInfoPtr, messageValue,
msgData->data, &msgData->length ) );
if( message == MESSAGE_SETATTRIBUTE )
{
const BOOLEAN validCursorPosition = \
( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \
messageValue >= CRYPT_CERTINFO_FIRST_CMS && \
messageValue <= CRYPT_CERTINFO_LAST_CMS : \
messageValue >= CRYPT_CERTINFO_FIRST_EXTENSION && \
messageValue <= CRYPT_CERTINFO_LAST_EXTENSION;
/* If it's a completed certificate, we can only add a restricted
class of component selection control values to the object */
#ifndef __WINCE__ /* String too long for compiler */
assert( certInfoPtr->certificate == NULL || \
isDNSelectionComponent( messageValue ) || \
isGeneralNameSelectionComponent( messageValue ) || \
isCursorComponent( messageValue ) || \
isControlComponent( messageValue ) || \
messageValue == CRYPT_IATTRIBUTE_INITIALISED || \
messageValue == CRYPT_IATTRIBUTE_PKIUSERINFO );
#endif /* !__WINCE__ */
/* If it's an initialisation message, there's nothing to do (we get
these when importing a cert, when the import is complete the
import code sends this message to move the cert into the high
state because it's already signed) */
if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
return( CRYPT_OK );
/* If the passed-in value is a cursor-positioning code, make sure
that it's valid */
if( *valuePtr < 0 && *valuePtr != CRYPT_UNUSED && \
( *valuePtr > CRYPT_CURSOR_FIRST || *valuePtr < CRYPT_CURSOR_LAST ) &&
!validCursorPosition && messageValue != CRYPT_CERTINFO_SELFSIGNED )
return( CRYPT_ARGERROR_NUM1 );
return( addCertComponent( certInfoPtr, messageValue, valuePtr,
CRYPT_UNUSED ) );
}
if( message == MESSAGE_SETATTRIBUTE_S )
return( addCertComponent( certInfoPtr, messageValue, msgData->data,
msgData->length ) );
if( message == MESSAGE_DELETEATTRIBUTE )
return( deleteCertComponent( certInfoPtr, messageValue ) );
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Handle a message sent to a certificate context */
static int certificateMessageFunction( const void *objectInfoPtr,
const MESSAGE_TYPE message,
void *messageDataPtr,
const int messageValue )
{
CERT_INFO *certInfoPtr = ( CERT_INFO * ) objectInfoPtr;
/* Process destroy object messages */
if( message == MESSAGE_DESTROY )
{
/* Clear the encoded certificate and miscellaneous components if
necessary. Note that there's no need to clear the associated
encryption context (if any) since this is a dependent object of
the cert and is destroyed by the kernel when the cert is
destroyed */
if( certInfoPtr->certificate != NULL )
{
zeroise( certInfoPtr->certificate, certInfoPtr->certificateSize );
clFree( "certificateMessageFunction", certInfoPtr->certificate );
}
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
{
if( certInfoPtr->cCertCert->serialNumber != NULL && \
certInfoPtr->cCertCert->serialNumber != \
certInfoPtr->cCertCert->serialNumberBuffer )
clFree( "certificateMessageFunction",
certInfoPtr->cCertCert->serialNumber );
}
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
if( certInfoPtr->cCertReq->serialNumber != NULL && \
certInfoPtr->cCertReq->serialNumber != \
certInfoPtr->cCertReq->serialNumberBuffer )
clFree( "certificateMessageFunction",
certInfoPtr->cCertReq->serialNumber );
}
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE )
{
if( certInfoPtr->cCertCert->subjectUniqueID != NULL )
clFree( "certificateMessageFunction",
certInfoPtr->cCertCert->subjectUniqueID );
if( certInfoPtr->cCertCert->issuerUniqueID != NULL )
clFree( "certificateMessageFunction",
certInfoPtr->cCertCert->issuerUniqueID );
}
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 cert chain if necessary */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \
certInfoPtr->cCertCert->chainEnd > 0)
{
int i;
for( i = 0; i < certInfoPtr->cCertCert->chainEnd; i++ )
krnlSendNotifier( certInfoPtr->cCertCert->chain[ i ],
IMESSAGE_DECREFCOUNT );
}
return( CRYPT_OK );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
/* If it's a cert chain, lock the currently selected cert 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 certs 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;
status = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ],
OBJECT_TYPE_CERTIFICATE,
( void ** ) &certChainInfoPtr,
CRYPT_ARGERROR_OBJECT );
if( cryptStatusError( status ) )
return( status );
status = processCertData( certChainInfoPtr, message, messageDataPtr,
messageValue );
krnlReleaseObject( certChainInfoPtr->objectHandle );
return( status );
}
return( processCertData( certInfoPtr, message, messageDataPtr,
messageValue ) );
}
/* Process messages that compare the object */
if( message == MESSAGE_COMPARE )
return( compareCertInfo( certInfoPtr, messageValue,
messageDataPtr ) );
/* Process messages that check a certificate */
if( message == MESSAGE_CHECK )
{
int complianceLevel, keyUsageValue, checkKeyFlag = CHECKKEY_FLAG_NONE;
int status;
/* Map the check type to a key usage that we check for */
switch( messageValue )
{
case MESSAGE_CHECK_PKC_PRIVATE:
/* This check type can be encountered when checking a private
key with a cert attached */
keyUsageValue = CRYPT_UNUSED;
checkKeyFlag = CHECKKEY_FLAG_PRIVATEKEY;
break;
case MESSAGE_CHECK_PKC_ENCRYPT:
case MESSAGE_CHECK_PKC_ENCRYPT_AVAIL:
keyUsageValue = CRYPT_KEYUSAGE_KEYENCIPHERMENT;
break;
case MESSAGE_CHECK_PKC_DECRYPT:
case MESSAGE_CHECK_PKC_DECRYPT_AVAIL:
keyUsageValue = CRYPT_KEYUSAGE_KEYENCIPHERMENT;
checkKeyFlag = CHECKKEY_FLAG_PRIVATEKEY;
break;
case MESSAGE_CHECK_PKC_SIGN:
case MESSAGE_CHECK_PKC_SIGN_AVAIL:
keyUsageValue = CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_NONREPUDIATION | \
CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_CRLSIGN;
checkKeyFlag = CHECKKEY_FLAG_PRIVATEKEY;
break;
case MESSAGE_CHECK_PKC_SIGCHECK:
case MESSAGE_CHECK_PKC_SIGCHECK_AVAIL:
keyUsageValue = CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_NONREPUDIATION | \
CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_CRLSIGN;
break;
case MESSAGE_CHECK_PKC_KA_EXPORT:
case MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL:
/* exportOnly usage falls back to plain keyAgreement if
necessary */
keyUsageValue = CRYPT_KEYUSAGE_KEYAGREEMENT | \
CRYPT_KEYUSAGE_ENCIPHERONLY;
break;
case MESSAGE_CHECK_PKC_KA_IMPORT:
case MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL:
/* importOnly usage falls back to plain keyAgreement if
necessary */
keyUsageValue = CRYPT_KEYUSAGE_KEYAGREEMENT | \
CRYPT_KEYUSAGE_DECIPHERONLY;
break;
case MESSAGE_CHECK_CA:
case MESSAGE_CHECK_CACERT:
/* A special-case version of MESSAGE_CHECK_PKC_SIGN/
MESSAGE_CHECK_PKC_SIGCHECK that applies only to
certificates */
keyUsageValue = CRYPT_KEYUSAGE_KEYCERTSIGN;
checkKeyFlag = CHECKKEY_FLAG_CA;
break;
case MESSAGE_CHECK_PKC:
/* If we're just checking for generic PKC functionality
then any kind of usage is OK */
return( CRYPT_OK );
default:
assert( NOTREACHED );
return( CRYPT_ERROR_INVALID );
}
assert( keyUsageValue != CRYPT_UNUSED || \
checkKeyFlag != CHECKKEY_FLAG_NONE );
/* Cert requests are special-case objects in that the key they
contain is usable only for signature checking of the self-
signature on the object (it can't be used for general-purpose
usages, which would make it equivalent to a trusted self-signed
cert). This is problematic because the keyUsage may indicate
that the key is valid for other things as well, or not valid for
signature checking. To get around this, we indicate that the key
has a single trusted usage, signature checking, and disallow any
other usage regardless of what the keyUsage says. The actual
keyUsage usage is only valid once the request has been converted
into a certificate */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
{
if( messageValue == MESSAGE_CHECK_PKC_SIGCHECK || \
messageValue == MESSAGE_CHECK_PKC_SIGCHECK_AVAIL )
return( CRYPT_OK );
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_TRUSTED_USAGE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -