📄 certcomp.c
字号:
/* Find a field in an attribute. This returns a pointer to the attribute
field containing the given GeneralName or GeneralName component, the given
DN, or the given field */
static ATTRIBUTE_LIST *selectNameOrField( CERT_INFO *certInfoPtr,
const CRYPT_ATTRIBUTE_TYPE certInfoType )
{
/* If it's a GeneralName selection component or a GeneralName component,
locate the attribute field which it corresponds to */
if( isGeneralNameSelectionComponent( certInfoType ) || \
isGeneralNameComponent( certInfoType ) )
return( selectGeneralName( certInfoPtr, certInfoType, SELECT_SELECT ) );
/* If it's a DN selection component, move to the DirectoryName within the
appropriate GeneralName */
if( isDNSelectionComponent( certInfoType ) )
return( selectGeneralName( certInfoPtr, certInfoType, SELECT_SELECT ) );
/* It's a standard attribute field, try and locate it (if it's something
else which isn't allowed, we'll get a null pointer returned) */
return( findAttributeField( certInfoPtr->attributes, certInfoType,
CRYPT_ATTRIBUTE_NONE ) );
}
/* Copy various components into a certificate object */
static int copyPublicKey( CERT_INFO *certInfoPtr,
const CRYPT_HANDLE cryptHandle )
{
CRYPT_CONTEXT iCryptContext;
int status;
/* Make sure we haven't already got a public key present */
if( certInfoPtr->iCryptContext != CRYPT_ERROR )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_INITED );
}
/* Get the context handle and make sure the context is of the correct
type */
status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_GETDEPENDENT,
&iCryptContext, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iCryptContext, RESOURCE_IMESSAGE_CHECK,
NULL, RESOURCE_MESSAGE_CHECK_PKC );
if( cryptStatusError( status ) )
{
setErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
CRYPT_ERRTYPE_ATTR_VALUE );
return( status );
}
/* Take a copy of the context for the certificate */
status = krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETDEPENDENT,
&iCryptContext, SETDEP_OPTION_INCREF );
certInfoPtr->iCryptContext = iCryptContext;
return( status );
}
static int copyIssuerDN( CERT_INFO *destCertInfoPtr,
const CERT_INFO *srcCertInfoPtr )
{
void *dnDataPtr;
if( ( dnDataPtr = malloc( srcCertInfoPtr->issuerDNsize ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memcpy( dnDataPtr, srcCertInfoPtr->issuerDNptr,
srcCertInfoPtr->issuerDNsize );
destCertInfoPtr->issuerDNptr = destCertInfoPtr->issuerDNdata = dnDataPtr;
destCertInfoPtr->issuerDNsize = srcCertInfoPtr->issuerDNsize;
return( CRYPT_OK );
}
static int copyRevocationInformation( CERT_INFO *crlInfoPtr,
const CERT_INFO *revInfoPtr )
{
int status;
/* If there's an issuer name recorded, make sure it matches the one
in the cert which is being added */
if( crlInfoPtr->issuerDNptr != NULL )
{
if( crlInfoPtr->issuerDNsize != revInfoPtr->issuerDNsize || \
memcmp( crlInfoPtr->issuerDNptr, revInfoPtr->issuerDNptr,
crlInfoPtr->issuerDNsize ) )
{
setErrorInfo( crlInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ERROR_INVALID );
}
}
else
{
/* There's no issuer name present yet, set the CRL issuer name to
the cert's issuer to make sure we can't add certs or sign the
CRL with a different issuer. We do this here rather than
after setting the revocation list entry because of the
difficulty of undoing the revocation entry addition */
status = copyIssuerDN( crlInfoPtr, revInfoPtr );
if( cryptStatusError( status ) )
return( status );
}
/* Add the cert information to the revocation list and make it the
currently selected entry */
status = addRevocationEntry( &crlInfoPtr->revocations,
&crlInfoPtr->currentRevocation,
CRYPT_CERTINFO_SERIALNUMBER,
revInfoPtr->serialNumber,
revInfoPtr->serialNumberLength );
if( status == CRYPT_ERROR_DUPLICATE )
/* If this cert is already present in the list, set the extended
error code for it */
setErrorInfo( crlInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( status );
}
/****************************************************************************
* *
* Add a Component *
* *
****************************************************************************/
/* Add a certificate component */
int addCertComponent( CERT_INFO *certInfoPtr,
const CRYPT_ATTRIBUTE_TYPE certInfoType,
const void *certInfo, const int certInfoLength )
{
int status = CRYPT_OK;
/* If it's a certificate pseudo-component, update the certificate info */
if( certInfoType >= CRYPT_FIRST_PSEUDOINFO && \
certInfoType <= CRYPT_LAST_PSEUDOINFO )
{
ATTRIBUTE_LIST *attributeListPtr;
const int value = *( ( int * ) certInfo );
/* General certificate flags */
if( certInfoType == CRYPT_CERTINFO_SELFSIGNED )
{
if( value )
certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
else
certInfoPtr->flags &= ~CERT_FLAG_SELFSIGNED;
return( CRYPT_OK );
}
/* Trust information */
if( certInfoType == CRYPT_CERTINFO_TRUSTED_USAGE )
{
certInfoPtr->trustedUsage = value;
return( CRYPT_OK );
}
if( certInfoType == CRYPT_CERTINFO_TRUSTED_IMPLICIT )
{
if( value )
return( addTrustInfo( certInfoPtr ) );
return( deleteTrustInfo( certInfoPtr ) );
}
/* Magic "just works" certificate */
if( certInfoType == CRYPT_CERTINFO_XYZZY )
{
const BYTE *policyOID = OID_CRYPTLIB_XYZZYCERT;
const int keyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
CRYPT_KEYUSAGE_NONREPUDIATION | \
CRYPT_KEYUSAGE_KEYENCIPHERMENT | \
CRYPT_KEYUSAGE_KEYCERTSIGN | \
CRYPT_KEYUSAGE_CRLSIGN;
const time_t expiryTime = time( NULL ) + ( 86400 * 365 * 20 );
RESOURCE_DATA msgData;
/* Clear any existing attribute values before trying to set new
ones */
krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_DELETEATTRIBUTE,
NULL, CRYPT_CERTINFO_VALIDTO );
krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_DELETEATTRIBUTE,
NULL, CRYPT_CERTINFO_KEYUSAGE );
krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_DELETEATTRIBUTE,
NULL, CRYPT_CERTINFO_CERTIFICATEPOLICIES );
/* Give the cert a 20-year expiry time, make it a self-signed CA
cert with all key usage types enabled, and set the policy OID
to identify it as a XYZZY cert */
setResourceData( &msgData, ( void * ) &expiryTime,
sizeof( time_t ) );
status = krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_VALIDTO );
if( cryptStatusOK( status ) )
status = krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE,
CRYPT_CERTINFO_SELFSIGNED );
if( cryptStatusOK( status ) )
status = krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE,
CRYPT_CERTINFO_CA );
if( cryptStatusOK( status ) )
status = krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE,
( void * ) &keyUsage,
CRYPT_CERTINFO_KEYUSAGE );
if( cryptStatusOK( status ) )
{
setResourceData( &msgData, OID_CRYPTLIB_XYZZYCERT,
sizeofOID( OID_CRYPTLIB_XYZZYCERT ) );
status = krnlSendMessage( certInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CERTINFO_CERTPOLICYID );
}
return( cryptStatusError( status ) ? CRYPT_ERROR_FAILED : status );
}
/* Certificate cursor movement (which selects a cert in a cert
chain, an entry in a CRL, or a request/response in an OCSP
object) */
if( certInfoType == CRYPT_CERTINFO_CURRENT_CERTIFICATE )
{
const BOOLEAN isCertChain = \
( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) ? \
TRUE : FALSE;
/* We can only select items in a cert chain, CRL, or OCSP
request/response */
if( !isCertChain && certInfoPtr->type != CRYPT_CERTTYPE_CRL && \
certInfoPtr->type != CRYPT_CERTTYPE_OCSP_REQUEST && \
certInfoPtr->type != CRYPT_CERTTYPE_OCSP_RESPONSE )
return( CRYPT_ARGERROR_OBJECT );
switch( value )
{
case CRYPT_CURSOR_FIRST:
if( isCertChain )
certInfoPtr->certChainPos = CRYPT_ERROR;
else
{
certInfoPtr->currentRevocation = certInfoPtr->revocations;
if( certInfoPtr->currentRevocation == NULL )
return( CRYPT_ERROR_NOTFOUND );
}
break;
case CRYPT_CURSOR_PREVIOUS:
if( isCertChain )
{
if( certInfoPtr->certChainPos == CRYPT_ERROR )
return( CRYPT_ERROR_NOTFOUND );
certInfoPtr->certChainPos--;
}
else
{
REVOCATION_INFO *revInfo = certInfoPtr->revocations;
if( certInfoPtr->currentRevocation == NULL )
return( CRYPT_ERROR_NOTFOUND );
/* Find the previous element in the list */
if( revInfo != certInfoPtr->currentRevocation )
while( revInfo->next != certInfoPtr->currentRevocation )
revInfo = revInfo->next;
certInfoPtr->currentRevocation = revInfo;
}
break;
case CRYPT_CURSOR_NEXT:
if( isCertChain )
{
if( certInfoPtr->certChainPos >= certInfoPtr->certChainEnd - 1 )
return( CRYPT_ERROR_NOTFOUND );
certInfoPtr->certChainPos++;
}
else
{
if( certInfoPtr->currentRevocation == NULL || \
certInfoPtr->currentRevocation->next == NULL )
return( CRYPT_ERROR_NOTFOUND );
certInfoPtr->currentRevocation = certInfoPtr->currentRevocation->next;
}
break;
case CRYPT_CURSOR_LAST:
if( isCertChain )
certInfoPtr->certChainPos = certInfoPtr->certChainEnd - 1;
else
{
REVOCATION_INFO *revInfo = certInfoPtr->revocations;
/* Go to the end of the list */
if( revInfo != NULL )
while( revInfo->next != NULL )
revInfo = revInfo->next;
if( revInfo == NULL )
return( CRYPT_ERROR_NOTFOUND );
certInfoPtr->currentRevocation = revInfo;
}
break;
default:
return( CRYPT_ARGERROR_NUM1 );
}
return( CRYPT_OK );
}
assert( certInfoType == CRYPT_CERTINFO_CURRENT_EXTENSION || \
certInfoType == CRYPT_CERTINFO_CURRENT_FIELD || \
certInfoType == CRYPT_CERTINFO_CURRENT_COMPONENT );
/* If the new position is specified relative to a previous position,
try and move to that position. Note that the seemingly illogical
comparison is used because the cursor positioning codes are
negative values */
if( value <= CRYPT_CURSOR_FIRST && value >= CRYPT_CURSOR_LAST )
{
/* If it's an absolute positioning code, pre-set the attribute
cursor if required */
if( value == CRYPT_CURSOR_FIRST || value == CRYPT_CURSOR_LAST )
{
/* If it's an absolute attribute positioning code, reset the
attribute cursor to the start of the list before we try to
move it */
if( certInfoType == CRYPT_CERTINFO_CURRENT_EXTENSION )
certInfoPtr->attributeCursor = certInfoPtr->attributes;
else
/* It's a field or component positioning code, initialise
the attribute cursor if necessary */
if( certInfoPtr->attributeCursor == NULL )
certInfoPtr->attributeCursor = certInfoPtr->attributes;
}
/* Move the attribute cursor */
if( certInfoPtr->attributeCursor == NULL )
{
status = ( value == CRYPT_CURSOR_FIRST || \
value == CRYPT_CURSOR_LAST ) ? \
CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_NOTINITED;
return( status );
}
status = moveAttributeCursor( &certInfoPtr->attributeCursor,
certInfoType, value );
return( status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -