📄 cryptcrt.c
字号:
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* Only cert objects with associated public keys are valid for check
messages (which are checking the capabilities of the key) */
assert( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );
/* Cert collections are pure container objects for which the base
cert object doesn't correspond to an actual cert */
if( certInfoPtr->flags & CERT_FLAG_CERTCOLLECTION )
{
assert( NOTREACHED );
return( CRYPT_ERROR_INVALID );
}
/* Check the key usage for the cert */
status = krnlSendMessage( certInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE, &complianceLevel,
CRYPT_OPTION_CERT_COMPLIANCELEVEL );
if( cryptStatusError( status ) )
return( status );
status = checkKeyUsage( certInfoPtr, checkKeyFlag, keyUsageValue,
complianceLevel, &certInfoPtr->errorLocus,
&certInfoPtr->errorType );
if( cryptStatusError( status ) )
/* Convert the status value to the correct form */
return( CRYPT_ARGERROR_OBJECT );
return( CRYPT_OK );
}
/* 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 */
saveSelectionState( certInfoPtr->selectionState,
certInfoPtr );
}
else
{
/* Restore the volatile state from before the object was
used */
restoreSelectionState( certInfoPtr->selectionState,
certInfoPtr );
}
return( CRYPT_OK );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Process object-specific messages */
if( message == MESSAGE_CRT_SIGN )
{
int status;
assert( 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 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 )
{
assert( 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 )
{
RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
int status;
assert( messageValue > CRYPT_CERTFORMAT_NONE && \
messageValue < CRYPT_CERTFORMAT_LAST );
/* Unsigned object types like CMS attributes aren't signed like other
cert.objects so they aren't pre-encoded when we sign them, and
have the potential to change on each use if the same CMS
attributes are reused for multiple signatures. Because of this
we write them out on export rather than copying the pre-encoded
form from an internal buffer */
if( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES )
{
STREAM stream;
int i;
assert( messageValue == CRYPT_ICERTFORMAT_DATA );
for( i = 0; \
certWriteTable[ i ].type != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \
certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE; i++ );
if( certWriteTable[ i ].type == CRYPT_CERTTYPE_NONE )
{
assert( NOTREACHED );
return( CRYPT_ERROR_NOTAVAIL );
}
sMemOpen( &stream, msgData->data, msgData->length );
status = certWriteTable[ i ].writeFunction( &stream, certInfoPtr,
NULL, CRYPT_UNUSED );
msgData->length = stell( &stream );
sMemDisconnect( &stream );
return( status );
}
/* Some objects aren't signed, or are pseudo-signed or optionally
signed, and have to be handled specially. RTCS requests and
responses are never signed (they're pure data containers like
CMS attributes, with protection being provided by CMS). OCSP
requests can be optionally signed but usually aren't, so if
we're fed an OCSP request without any associated encoded data we
pseudo-sign it to produce encoded data. PKI user data is never
signed but needs to go through a one-off setup process to
initialise the user data fields so it has the same semantics as a
pseudo-signed object. CRMF revocation requests are never signed
(thus ruling out suicide-note revocations) */
if( ( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \
certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
certInfoPtr->type == CRYPT_CERTTYPE_PKIUSER || \
certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION ) && \
certInfoPtr->certificate == NULL )
{
status = signCert( certInfoPtr, CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( status );
}
/* If we're exporting a single cert from a chain, lock the currently
selected cert in the chain and export that */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \
certInfoPtr->cCertCert->chainPos >= 0 && \
( messageValue == CRYPT_CERTFORMAT_CERTIFICATE || \
messageValue == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \
messageValue == CRYPT_CERTFORMAT_XML_CERTIFICATE ) )
{
CERT_INFO *certChainInfoPtr;
status = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ],
OBJECT_TYPE_CERTIFICATE,
( void ** ) &certChainInfoPtr,
CRYPT_ARGERROR_OBJECT );
if( cryptStatusError( status ) )
return( status );
status = exportCert( msgData->data, &msgData->length,
messageValue, certChainInfoPtr,
msgData->length );
krnlReleaseObject( certChainInfoPtr->objectHandle );
return( status );
}
assert( ( ( certInfoPtr->flags & CERT_FLAG_CERTCOLLECTION ) && \
certInfoPtr->certificate == NULL ) || \
certInfoPtr->certificate != NULL );
return( exportCert( msgData->data, &msgData->length,
messageValue, certInfoPtr, msgData->length ) );
}
assert( NOTREACHED );
return( CRYPT_ERROR ); /* Get rid of compiler warning */
}
/* Create a certificate object, returning a pointer to the locked cert info
ready for further initialisation */
int createCertificateInfo( CERT_INFO **certInfoPtrPtr,
const CRYPT_USER cryptOwner,
const CRYPT_CERTTYPE_TYPE certType )
{
CRYPT_CERTIFICATE iCertificate;
CERT_INFO *certInfoPtr;
int storageSize, subType;
assert( certInfoPtrPtr != NULL );
/* 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 cert 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:
assert( NOTREACHED );
return( CRYPT_ERROR );
}
/* Create the certificate object */
iCertificate = krnlCreateObject( ( void ** ) &certInfoPtr,
sizeof( CERT_INFO ) + storageSize,
OBJECT_TYPE_CERTIFICATE, subType,
CREATEOBJECT_FLAG_NONE, cryptOwner,
ACTION_PERM_NONE_ALL,
certificateMessageFunction );
if( cryptStatusError( iCertificate ) )
return( iCertificate );
certInfoPtr->objectHandle = iCertificate;
certInfoPtr->ownerHandle = cryptOwner;
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;
}
/* 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 that 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 + -