📄 certcomp.c
字号:
/* It's an absolute attribute position, try and move to the
attribute */
if( certInfoType == CRYPT_CERTINFO_CURRENT_EXTENSION )
{
attributeListPtr = findAttribute( certInfoPtr->attributes, value );
if( attributeListPtr == NULL )
return( CRYPT_ERROR_NOTFOUND );
certInfoPtr->attributeCursor = attributeListPtr;
return( CRYPT_OK );
}
/* It's an absolute field postion, try and move to the field */
attributeListPtr = selectNameOrField( certInfoPtr, value );
if( attributeListPtr == NULL )
return( CRYPT_ERROR_NOTFOUND );
certInfoPtr->attributeCursor = attributeListPtr;
return( CRYPT_OK );
}
/* We're adding data to a certificate, clear the error information */
clearErrorInfo( certInfoPtr );
/* If it's a public key, take a copy of the context for the certificates
use */
if( certInfoType == CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO )
return( copyPublicKey( certInfoPtr,
*( ( CRYPT_HANDLE * ) certInfo ) ) );
/* If it's a cert request, copy the public key context, the DN, any
valid attributes, and any other relevant bits and pieces if it's a
CRMF request */
if( certInfoType == CRYPT_CERTINFO_CERTREQUEST )
{
CRYPT_CERTIFICATE certRequest = *( ( CRYPT_CERTIFICATE * ) certInfo );
CERT_INFO *certRequestInfoPtr;
/* Make sure we haven't already got a public key or DN present */
if( certInfoPtr->iCryptContext != CRYPT_ERROR || \
certInfoPtr->subjectName != NULL )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTREQUEST,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Copy the public key context, the DN, and the attributes. We copy
the attributes across after the DN because that copy is the
hardest to undo (if there are already attributes present, the
copied attributes will be mixed in among them so it's not really
possible to undo the copy later without performing a complex
selective delete) */
getCheckInternalResource( certRequest, certRequestInfoPtr,
OBJECT_TYPE_CERTIFICATE );
if( certRequestInfoPtr->type != CRYPT_CERTTYPE_CERTREQUEST && \
certRequestInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )
unlockResourceExit( certRequestInfoPtr, CRYPT_ARGERROR_NUM1 );
status = copyDN( &certInfoPtr->subjectName,
certRequestInfoPtr->subjectName );
if( cryptStatusOK( status ) && \
certRequestInfoPtr->attributes != NULL )
{
status = copyAttributes( &certInfoPtr->attributes,
certRequestInfoPtr->attributes,
&certInfoPtr->errorLocus,
&certInfoPtr->errorType );
if( cryptStatusError( status ) )
deleteDN( &certInfoPtr->subjectName );
}
if( cryptStatusOK( status ) )
{
/* The copies succeeded, add a reference from the cert to the
context associated with the cert request */
certInfoPtr->iCryptContext = certRequestInfoPtr->iCryptContext;
krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETDEPENDENT,
&certRequestInfoPtr->iCryptContext,
SETDEP_OPTION_INCREF );
}
if( certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
{
/* If it's a CRMF request there could also be a validity period
specified */
if( certRequestInfoPtr->startTime )
certInfoPtr->startTime = certRequestInfoPtr->startTime;
if( certRequestInfoPtr->endTime )
certInfoPtr->endTime = certRequestInfoPtr->endTime;
}
unlockResourceExit( certRequestInfoPtr, status );
}
/* If it's a revocation request, copy what we need to identify the cert
to be revoked and any revocation information */
if( certInfoType == CRYPT_IATTRIBUTE_REVREQUEST )
{
CRYPT_CERTIFICATE certRequest = *( ( CRYPT_CERTIFICATE * ) certInfo );
CERT_INFO *certRequestInfoPtr;
getCheckInternalResource( certRequest, certRequestInfoPtr,
OBJECT_TYPE_CERTIFICATE );
status = copyRevocationInformation( certInfoPtr, certRequestInfoPtr );
if( cryptStatusOK( status ) )
status = copyRevocationAttributes( &certInfoPtr->attributes,
certRequestInfoPtr->attributes,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
unlockResourceExit( certRequestInfoPtr, status );
}
/* If it's a certificate, copy across various components or store the
entire cert where required */
if( certInfoType == CRYPT_CERTINFO_USERCERTIFICATE )
{
CRYPT_CERTIFICATE userCert = *( ( CRYPT_HANDLE * ) certInfo );
CERT_INFO *userCertInfoPtr;
/* Make sure we've been passed a cert ready for use */
status = krnlSendMessage( userCert, RESOURCE_IMESSAGE_GETDEPENDENT,
&userCert, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
getCheckInternalResource( userCert, userCertInfoPtr,
OBJECT_TYPE_CERTIFICATE );
if( userCertInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \
userCertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )
/* Must be either a straight certificate or the cert at the end
of a chain (certs in the middle of the chain are extracted
by the higher-level code and passed down as standalone
certs) */
status = CRYPT_ARGERROR_NUM1;
else
if( userCertInfoPtr->certificate == NULL )
status = CRYPT_ERROR_NOTINITED; /* Must be ready for use */
if( cryptStatusError( status ) )
unlockResourceExit( userCertInfoPtr, status );
/* If it's a cert chain we're adding the complete cert, just store it
and exit */
if( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )
{
int i;
unlockResource( userCertInfoPtr );
if( certInfoPtr->certChainEnd >= MAX_CHAINLENGTH )
return( CRYPT_ERROR_OVERFLOW );
/* Perform a simple check to make sure it hasn't been added
already */
for( i = 0; i < certInfoPtr->certChainEnd; i++ )
if( cryptStatusOK( \
krnlSendMessage( userCert, RESOURCE_IMESSAGE_COMPARE,
&certInfoPtr->certChain[ i ],
RESOURCE_MESSAGE_COMPARE_FINGERPRINT ) ) )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Add the user cert and increment its reference count */
krnlSendNotifier( userCert, RESOURCE_IMESSAGE_INCREFCOUNT );
certInfoPtr->certChain[ certInfoPtr->certChainEnd++ ] = userCert;
return( CRYPT_OK );
}
/* If it's a CRMF cert request, copy the public key and DN. We copy
the full DN rather than just the encoded form in case the user
wants to query the request details after creating it */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )
{
status = copyDN( &certInfoPtr->subjectName,
userCertInfoPtr->subjectName );
if( cryptStatusError( status ) )
unlockResourceExit( userCertInfoPtr, status );
status = copyPublicKey( certInfoPtr,
*( ( CRYPT_HANDLE * ) certInfo ) );
if( cryptStatusError( status ) )
deleteDN( &certInfoPtr->subjectName );
unlockResourceExit( userCertInfoPtr, status );
}
/* If it's a CRMF revocation request, copy across the issuer and
serial number */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
/* If the info is already present we can't add it again */
if( certInfoPtr->issuerName != NULL )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
unlockResourceExit( userCertInfoPtr, CRYPT_ERROR_INITED );
}
/* Copy across the issuer name and serial number. We don't care
about any internal structure so we just copy the pre-encoded
form, we could in theory copy the full DN but it isn't really
the issuer (creator) of the object so it's better if it
appears to have no issuer DN than a misleading one */
status = copyIssuerDN( certInfoPtr, userCertInfoPtr );
if( cryptStatusError( status ) )
unlockResourceExit( userCertInfoPtr, status );
if( ( certInfoPtr->serialNumber = \
malloc( userCertInfoPtr->serialNumberLength ) ) == NULL )
unlockResourceExit( userCertInfoPtr, CRYPT_ERROR_MEMORY );
memcpy( certInfoPtr->serialNumber, userCertInfoPtr->serialNumber,
userCertInfoPtr->serialNumberLength );
certInfoPtr->serialNumberLength = userCertInfoPtr->serialNumberLength;
/* If it's a CRMF revocation request we also need to copy the
subject DN for use in CMP */
if( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )
{
if( ( certInfoPtr->subjectDNdata = \
malloc( userCertInfoPtr->subjectDNsize ) ) == NULL )
{
free( certInfoPtr->serialNumber );
certInfoPtr->serialNumber = NULL;
free( certInfoPtr->issuerDNdata );
certInfoPtr->issuerDNdata = NULL;
unlockResourceExit( userCertInfoPtr, CRYPT_ERROR_MEMORY );
}
memcpy( certInfoPtr->subjectDNdata, userCertInfoPtr->subjectDNptr,
userCertInfoPtr->subjectDNsize );
certInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;
certInfoPtr->subjectDNsize = userCertInfoPtr->subjectDNsize;
}
unlockResourceExit( userCertInfoPtr, status );
}
/* If it's an OCSP request, remember the OCSP responder URL if
there's one present (we can't leave it to be read out of the cert
because authorityInfoAccess isn't a valid attribute for OCSP
requests) and copy the cert information to the revocation list */
if( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )
{
int sizeofOCSPv1ID( const CERT_INFO *certInfoPtr );
int writeOCSPv1ID( STREAM *stream, const CERT_INFO *certInfoPtr,
const void *issuerKeyHash );
ATTRIBUTE_LIST *attributeListPtr = NULL;
SELECTION_STATE savedState;
STREAM stream;
BYTE certHash[ CRYPT_MAX_HASHSIZE ];
int certHashLength = CRYPT_MAX_HASHSIZE;
/* Check whether the user cert conatains an OCSP responder URL
in the OCSP authorityInfoAccess GeneralName. Since this
changes the GeneralName selection state within the cert we
save it around the selection calls */
saveSelectionState( savedState, userCertInfoPtr );
if( selectGeneralName( userCertInfoPtr,
CRYPT_CERTINFO_AUTHORITYINFO_OCSP, SELECT_SELECT ) != NULL )
attributeListPtr = selectGeneralName( userCertInfoPtr,
CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,
SELECT_SET );
restoreSelectionState( savedState, userCertInfoPtr );
if( attributeListPtr != NULL && certInfoPtr->ocspUrl == NULL )
{
/* There's an OCSP responder URL present, copy it to the OCSP
request */
if( ( certInfoPtr->ocspUrl = \
malloc( attributeListPtr->dataLength ) ) == NULL )
unlockResourceExit( userCertInfoPtr,
CRYPT_ERROR_MEMORY );
memcpy( certInfoPtr->ocspUrl,
( attributeListPtr->data != NULL ) ? \
attributeListPtr->data : attributeListPtr->smallData,
attributeListPtr->dataLength );
certInfoPtr->ocspUrlSize = attributeListPtr->dataLength;
}
/* If the caller wants an OCSPv1 ID, we add the necessary
information as a pre-encoded blob since we can't do much with
the ID fields */
if( certInfoPtr->version == 1 )
{
BYTE idBuffer[ 256 ], *idBufPtr = idBuffer;
int idLength;
idLength = sizeofOCSPv1ID( userCertInfoPtr );
if( idLength > 256 && \
( idBufPtr = malloc( idLength ) ) == NULL )
unlockResourceExit( userCertInfoPtr,
CRYPT_ERROR_MEMORY );
sMemOpen( &stream, idBufPtr, idLength );
status = writeOCSPv1ID( &stream, userCertInfoPtr,
certInfoPtr->certHash );
sMemDisconnect( &stream );
if( cryptStatusOK( status ) )
status = addRevocationEntry( &certInfoPtr->revocations,
&certInfoPtr->currentRevocation,
CRYPT_ATTRIBUTE_NONE,
idBufPtr, idLength );
if( idBufPtr != idBuffer )
free( idBufPtr );
}
else
{
/* It's not an OCSPv1 request, make the version explicit */
certInfoPtr->version = 2;
/* It's a v2 request, add the cert hash. We read the cert
hash indirectly since it's computed on demand and may not
have been evaluated yet */
status = getCertComponent( userCertInfoPtr,
CRYPT_CERTINFO_FINGERPRINT_SHA,
certHash, &certHashLength );
if( cryptStatusOK( status ) )
status = addRevocationEntry( &certInfoPtr->revocations,
&certInfoPtr->currentRevocation,
CRYPT_CERTINFO_FINGERPRINT,
certHash, certHashLength );
}
if( status == CRYPT_ERROR_DUPLICATE )
/* If this cert is already present in the list, set the
extended error code for it */
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
unlockResourceExit( userCertInfoPtr, status );
}
/* It's a CRL, copy the revocation information across */
assert( certInfoPtr->type == CRYPT_CERTTYPE_CRL );
status = copyRevocationInformation( certInfoPtr, userCertInfoPtr );
unlockResourceExit( userCertInfoPtr, status );
}
/* If it's a CA certificate, get the hash of the public key (for an OCSP
request), possibly overwriting a previous hash if there are multiple
entries in the request */
if( certInfoType == CRYPT_CERTINFO_CACERTIFICATE )
{
CRYPT_CERTIFICATE caCert = *( ( CRYPT_HANDLE * ) certInfo );
CERT_INFO *caCertInfoPtr;
HASHFUNCTION hashFunction;
STREAM stream;
int length, hashSize;
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
/* If we've already added revocation entries with v2 IDs we can't add
a CA cert which implies v1 IDs */
if( certInfoPtr->version == 2 )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Make sure we've been passed a cert ready for use */
status = krnlSendMessage( caCert, RESOURCE_IMESSAGE_GETDEPENDENT,
&caCert, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
getCheckInternalResource( caCert, caCertInfoPtr,
OBJECT_TYPE_CERTIFICATE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -