📄 certchk.c
字号:
return( TRUE );
}
/* Compare two altNames component by component */
static CRYPT_ATTRIBUTE_TYPE compareAltNames( const ATTRIBUTE_LIST *subjectAttributes,
const ATTRIBUTE_LIST *issuerAttributes )
{
ATTRIBUTE_LIST *subjectAttributeListPtr, *issuerAttributeListPtr;
/* Check the otherName */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_OTHERNAME_TYPEID );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_OTHERNAME_TYPEID );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_OTHERNAME_TYPEID );
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_OTHERNAME_VALUE );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_OTHERNAME_VALUE );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_OTHERNAME_VALUE );
/* Check the email address */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_RFC822NAME );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_RFC822NAME );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_RFC822NAME );
/* Check the DNS name */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_DNSNAME );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_DNSNAME );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_DNSNAME );
/* Check the directory name */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_DIRECTORYNAME );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_DIRECTORYNAME );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_DIRECTORYNAME );
/* Check the EDI party name */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER );
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME );
/* Check the URI */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
/* Check the IP address */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_IPADDRESS );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_IPADDRESS );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_IPADDRESS );
/* Check the registered ID */
subjectAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_ISSUERALTNAME, CRYPT_CERTINFO_REGISTEREDID );
issuerAttributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_REGISTEREDID );
if( !compareAttributeComponents( subjectAttributeListPtr,
issuerAttributeListPtr ) )
return( CRYPT_CERTINFO_REGISTEREDID );
return( CRYPT_ATTRIBUTE_NONE );
}
/* Perform a wildcarded compare or two strings in attributes */
static BOOLEAN wildcardStringMatch( const char *wildcardString,
const char *string )
{
while( *wildcardString && *string )
{
/* Match a wildcard */
if( *wildcardString == '*' )
{
BOOLEAN isMatch = FALSE;
/* Skip '*'s and exit if we've reached the end of the pattern */
while( *wildcardString == '*' )
wildcardString++;
if( !*wildcardString )
return( TRUE );
/* Match to the next literal, then match the next section with
backtracking in case of a mismatch */
while( *string && *wildcardString != *string )
string++;
while( *string && !isMatch )
{
isMatch = wildcardStringMatch( wildcardString, string );
if( !isMatch )
string++;
}
return( isMatch );
}
else
if( *wildcardString != *string )
return( FALSE );
wildcardString++;
string++;
}
/* If there are literals left in the wildcard or text string, we haven't
found a match yet */
if( *wildcardString && ( *wildcardString != '*' || *++wildcardString ) )
return( FALSE );
return( *string ? FALSE : TRUE );
}
static BOOLEAN wildcardMatch( const ATTRIBUTE_LIST *constrainedAttribute,
const ATTRIBUTE_LIST *attribute,
const BOOLEAN errorStatus )
{
const char *constrainedString = \
( constrainedAttribute->dataLength <= CRYPT_MAX_TEXTSIZE ) ? \
( char * ) constrainedAttribute->smallData : constrainedAttribute->data;
const char *string = ( attribute->dataLength <= CRYPT_MAX_TEXTSIZE ) ? \
( char * ) attribute->smallData : attribute->data;
int count = 0, i;
/* Perform a quick damage-control check to prevent excessive recursion:
There shouldn't be more than ten wildcard chars present (realistically
there shouldn't be more than one) */
for( i = 0; string[ i ]; i++ )
if( string[ i ] == '*' )
count++;
if( count > 10 )
return( errorStatus );
/* Pass the call on to the string matcher (this is recursive so we can't
do the match in this function) */
return( wildcardStringMatch( string, constrainedString ) );
}
/* Check name constraints placed by an issuer. matchValue = TRUE for
excluded subtrees (fail on a match), FALSE for included subtrees (fail on
a mismatch) */
int checkNameConstraints( CERT_INFO *subjectCertInfoPtr,
const ATTRIBUTE_LIST *issuerAttributes,
const BOOLEAN matchValue )
{
const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
const CRYPT_ATTRIBUTE_TYPE constraintType = ( matchValue ) ? \
CRYPT_CERTINFO_EXCLUDEDSUBTREES : CRYPT_CERTINFO_PERMITTEDSUBTREES;
ATTRIBUTE_LIST *attributeListPtr, *constrainedAttributeListPtr;
int status = CRYPT_OK;
/* Compare the DN if a constraint exists */
attributeListPtr = findAttributeField( issuerAttributes,
constraintType, CRYPT_CERTINFO_DIRECTORYNAME );
if( compareDN( subjectCertInfoPtr->subjectName,
attributeListPtr->data, TRUE ) == matchValue )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* Compare the Internet-related names if constraints exist */
attributeListPtr = findAttributeField( issuerAttributes,
constraintType, CRYPT_CERTINFO_RFC822NAME );
constrainedAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_RFC822NAME );
if( attributeListPtr != NULL && constrainedAttributeListPtr != NULL && \
wildcardMatch( constrainedAttributeListPtr, attributeListPtr,
FALSE ) == matchValue )
status = CRYPT_ERROR_INVALID;
attributeListPtr = findAttributeField( issuerAttributes,
constraintType, CRYPT_CERTINFO_DNSNAME );
constrainedAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_DNSNAME );
if( attributeListPtr != NULL && constrainedAttributeListPtr != NULL && \
wildcardMatch( constrainedAttributeListPtr, attributeListPtr,
FALSE ) == matchValue )
status = CRYPT_ERROR_INVALID;
attributeListPtr = findAttributeField( issuerAttributes,
constraintType, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
constrainedAttributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );
if( attributeListPtr != NULL && constrainedAttributeListPtr != NULL && \
wildcardMatch( constrainedAttributeListPtr, attributeListPtr,
FALSE ) == matchValue )
status = CRYPT_ERROR_INVALID;
if( cryptStatusError( status ) )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SUBJECTALTNAME,
CRYPT_ERRTYPE_CONSTRAINT );
return( status );
}
return( CRYPT_OK );
}
/* Check policy constraints placed by an issuer */
int checkPolicyConstraints( CERT_INFO *subjectCertInfoPtr,
const ATTRIBUTE_LIST *issuerAttributes )
{
ATTRIBUTE_LIST *attributeListPtr, *constrainedAttributeListPtr;
/* Compare the issuer and subject policies if constraints exist */
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ATTRIBUTE_NONE );
constrainedAttributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ATTRIBUTE_NONE );
if( constrainedAttributeListPtr == NULL || \
attributeListPtr->dataLength != constrainedAttributeListPtr->dataLength || \
memcmp( attributeListPtr->smallData, constrainedAttributeListPtr->smallData,
attributeListPtr->dataLength ) )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTPOLICYID,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Check for Constraint Violations *
* *
****************************************************************************/
/* Check the validity of a CRL based on an issuer cert */
static int checkCRL( CERT_INFO *crlInfoPtr,
const CERT_INFO *issuerCertInfoPtr )
{
ATTRIBUTE_LIST *attributeListPtr;
/* If it's a delta CRL, make sure the CRL numbers make sense (that is,
that the delta CRL was issued after the full CRL) */
attributeListPtr = findAttribute( crlInfoPtr->attributes,
CRYPT_CERTINFO_DELTACRLINDICATOR );
if( attributeListPtr != NULL )
{
const int deltaCRLindicator = ( int ) attributeListPtr->value;
attributeListPtr = findAttribute( crlInfoPtr->attributes,
CRYPT_CERTINFO_CRLNUMBER );
if( attributeListPtr != NULL && \
attributeListPtr->value >= deltaCRLindicator )
{
setErrorInfo( crlInfoPtr, CRYPT_CERTINFO_DELTACRLINDICATOR,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
}
/* If a key usage attribute is present, make sure the issuer can sign
CRL's */
attributeListPtr = findAttribute( issuerCertInfoPtr->attributes,
CRYPT_CERTINFO_KEYUSAGE );
if( attributeListPtr != NULL )
{
if( !( attributeListPtr->value & issuerCertInfoPtr->trustedUsage & \
CRYPT_KEYUSAGE_CRLSIGN ) )
{
setErrorInfo( crlInfoPtr,
( attributeListPtr->value & CRYPT_KEYUSAGE_CRLSIGN ) ? \
CRYPT_CERTINFO_TRUSTED_USAGE : CRYPT_CERTINFO_KEYUSAGE,
CRYPT_ERRTYPE_ISSUERCONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
}
else
/* There's no key usage present, make sure the issuer is at least
trusted to sign CRL's */
if( !( issuerCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_CRLSIGN ) )
{
setErrorInfo( crlInfoPtr, CRYPT_CERTINFO_TRUSTED_USAGE,
CRYPT_ERRTYPE_ISSUERCONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* If a basic constraints attribute is present, make sure the issuer is
a CA */
attributeListPtr = findAttribute( issuerCertInfoPtr->attributes,
CRYPT_CERTINFO_CA );
if( attributeListPtr != NULL && !attributeListPtr->value )
{
setErrorInfo( crlInfoPtr, CRYPT_CERTINFO_CA,
CRYPT_ERRTYPE_ISSUERCONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
return( CRYPT_OK );
}
/* Check the validity of a subject cert based on an issuer cert */
int checkCert( CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr )
{
const ATTRIBUTE_LIST *subjectAttributes = subjectCertInfoPtr->attributes;
const ATTRIBUTE_LIST *issuerAttributes = issuerCertInfoPtr->attributes;
ATTRIBUTE_LIST *attributeListPtr;
BOOLEAN subjectIsCA = FALSE, issuerIsCA = FALSE, boolean1, boolean2;
const time_t currentTime = time( NULL );
int validityNesting, status;
/* If it's some form of certificate request or an OCSP object, there's
nothing to check (yet) */
if( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \
subjectCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \
subjectCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION || \
subjectCertInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \
subjectCertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )
return( CRYPT_OK );
/* If we're checking a CRL, call the special-case routine for this */
if( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CRL )
return( checkCRL( subjectCertInfoPtr, issuerCertInfoPtr ) );
/* Check that the validity period is in order. If we're checking an
existing cert then the start time has to be valid, if we're creating
a new cert then it doesn't have to be valid since the cert could be
created for use in the future */
if( subjectCertInfoPtr->startTime >= subjectCertInfoPtr->endTime || \
( subjectCertInfoPtr->certificate != NULL && \
currentTime < subjectCertInfoPtr->startTime ) )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_VALIDFROM,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
if( currentTime > subjectCertInfoPtr->endTime )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_VALIDTO,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
/* If it's a self-signed cert and we've already checked it, there's no
need to perform any further checks again except to make sure that the
trusted usage hasn't changed */
if( ( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
( subjectCertInfoPtr->flags & CERT_FLAG_CERTCHECKED ) )
{
if( !( subjectCertInfoPtr->trustedUsage & CRYPT_KEYUSAGE_KEYCERTSIGN ) )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_TRUSTED_USAGE,
CRYPT_ERRTYPE_CONSTRAINT );
return( CRYPT_ERROR_INVALID );
}
return( CRYPT_OK );
}
/* Determine whether the subject or issuer are CA certs */
attributeListPtr = findAttributeField( subjectAttributes,
CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
subjectIsCA = ( BOOLEAN ) attributeListPtr->value;
attributeListPtr = findAttributeField( issuerAttributes,
CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
issuerIsCA = ( BOOLEAN ) attributeListPtr->value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -