📄 write.c
字号:
int complianceLevel;
/* PKIX allows empty subject DNs if a subject altName is present,
however creating certs like this breaks every cert-using
protocol supported by cryptlib so we only allow it at the
highest compliance level. In addition we have to be very
careful to ensure that the empty subject DN can't end up
becoming an empty issuer DN, for example if it's a self-signed
or CA cert */
if( status != CRYPT_ERROR_NOTINITED || \
( type == CRYPT_CERTTYPE_CERTIFICATE && \
subjectCertInfoPtr->cCertCert->subjectUniqueID != NULL ) || \
( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
return( status );
if( cryptStatusError( \
krnlSendMessage( subjectCertInfoPtr->ownerHandle,
IMESSAGE_GETATTRIBUTE, &complianceLevel,
CRYPT_OPTION_CERT_COMPLIANCELEVEL ) ) || \
complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL )
/* We only allow this behaviour at the highest compliance
level */
return( status );
attributeListPtr = \
findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL && attributeListPtr->intValue )
/* It's a CA cert, the subject DN can't be empty */
return( status );
attributeListPtr = \
findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_SUBJECTALTNAME,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr == NULL )
/* Either a subject DN or subject altName must be present */
return( status );
/* There's a subject altName present but no subject DN, mark the
altName as critical */
attributeListPtr->flags |= ATTR_FLAG_CRITICAL;
}
/* If we're creating a non-self-signed cert, check whether the
subject's DN is the same as the issuer's DN. If this is the case,
the resulting object would appear to be self-signed so we disallow
it */
if( ( type == CRYPT_CERTTYPE_CERTIFICATE || \
type == CRYPT_CERTTYPE_ATTRIBUTE_CERT ) && \
!( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) && \
compareDN( issuerCertInfoPtr->subjectName,
subjectCertInfoPtr->subjectName, FALSE ) )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,
CRYPT_ERRTYPE_ISSUERCONSTRAINT );
return( CRYPT_ERROR_NOTINITED );
}
}
/* Handle various default certificate extensions if necessary */
if( type == CRYPT_CERTTYPE_CERTIFICATE || \
type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )
{
/* Constrain the subject validity period to be within the issuer
validity period */
if( subjectCertInfoPtr->startTime < issuerCertInfoPtr->startTime )
subjectCertInfoPtr->startTime = issuerCertInfoPtr->startTime;
if( subjectCertInfoPtr->endTime > issuerCertInfoPtr->endTime )
subjectCertInfoPtr->endTime = issuerCertInfoPtr->endTime;
/* If it's a >= v3 cert, add the standard X.509v3 extensions if these
aren't already present */
if( ( type == CRYPT_CERTTYPE_CERTIFICATE ) && \
( subjectCertInfoPtr->version >= 3 ) )
{
status = addStandardExtensions( subjectCertInfoPtr );
if( cryptStatusError( status ) )
return( status );
}
}
if( type == CRYPT_CERTTYPE_CERTIFICATE || \
type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \
( type == CRYPT_CERTTYPE_CRL && issuerCertInfoPtr != NULL ) )
{
/* Copy the issuer DN if this isn't already present */
if( subjectCertInfoPtr->issuerName == NULL )
{
status = copyDN( &subjectCertInfoPtr->issuerName,
issuerCertInfoPtr->subjectName );
if( cryptStatusError( status ) )
return( status );
}
/* Copy any required extensions from the issuer to the subject cert
if necessary */
if( !( subjectCertInfoPtr->flags & CERT_FLAG_SELFSIGNED ) )
{
status = copyIssuerAttributes( &subjectCertInfoPtr->attributes,
issuerCertInfoPtr->attributes,
subjectCertInfoPtr->type,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
}
}
if( type == CRYPT_CERTTYPE_CRL && issuerCertInfoPtr != NULL )
{
/* If it's a CRL, compare the revoked cert issuer DN and signer DN
to make sure we're not trying to revoke someone else's certs, and
prepare the revocation entries */
if( !compareDN( subjectCertInfoPtr->issuerName,
issuerCertInfoPtr->subjectName, FALSE ) )
{
setErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ERROR_INVALID );
}
}
if( type == CRYPT_CERTTYPE_RTCS_RESPONSE )
{
/* If it's an RTCS response, prepare the cert status list entries
prior to encoding them */
status = prepareCertStatusEntries( subjectCertInfoPtr->cCertVal->validityInfo,
&subjectCertInfoPtr->cCertVal->currentValidity,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
}
if( type == CRYPT_CERTTYPE_CRL || type == CRYPT_CERTTYPE_OCSP_RESPONSE )
{
/* If it's a CRL or OCSP response, prepare the revocation list
entries prior to encoding them */
status = prepareRevocationEntries( subjectCertInfoPtr->cCertRev->revocations,
subjectCertInfoPtr->cCertRev->revocationTime,
&subjectCertInfoPtr->cCertRev->currentRevocation,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
}
/* Now that we've set up the attributes, perform the remainder of the
checks. Because RTCS is a CMS standard rather than PKIX, the RTCS
attributes are CMS rather than certificate attributes */
status = checkAttributes( ( type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \
ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,
subjectCertInfoPtr->attributes,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
if( cryptStatusOK( status ) )
status = checkCert( subjectCertInfoPtr, issuerCertInfoPtr, FALSE,
&subjectCertInfoPtr->errorLocus,
&subjectCertInfoPtr->errorType );
if( cryptStatusOK( status ) && \
( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \
subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) )
subjectCertInfoPtr->cCertCert->maxCheckLevel = \
CRYPT_COMPLIANCELEVEL_PKIX_FULL;
return( status );
}
/****************************************************************************
* *
* Write a Certificate Object *
* *
****************************************************************************/
/* Write certificate information:
CertificateInfo ::= SEQUENCE {
version [ 0 ] EXPLICIT INTEGER DEFAULT(0),
serialNumber INTEGER,
signature AlgorithmIdentifier,
issuer Name
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
extensions [ 3 ] Extensions OPTIONAL
} */
static int writeCertInfo( STREAM *stream, CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
const CRYPT_CONTEXT iIssuerCryptContext )
{
const CERT_CERT_INFO *certCertInfo = subjectCertInfoPtr->cCertCert;
int length, extensionSize, status;
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
CRYPT_CERTTYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how the issuer name will be encoded */
subjectCertInfoPtr->issuerDNsize = \
( issuerCertInfoPtr->subjectDNptr != NULL ) ? \
issuerCertInfoPtr->subjectDNsize : \
sizeofDN( subjectCertInfoPtr->issuerName );
subjectCertInfoPtr->subjectDNsize = \
sizeofDN( subjectCertInfoPtr->subjectName );
/* Determine the size of the certificate information */
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
length = sizeofInteger( certCertInfo->serialNumber,
certCertInfo->serialNumberLength ) + \
sizeofContextAlgoID( iIssuerCryptContext, certCertInfo->hashAlgo,
ALGOID_FLAG_ALGOID_ONLY ) + \
subjectCertInfoPtr->issuerDNsize + \
sizeofObject( sizeofUTCTime() * 2 ) + \
subjectCertInfoPtr->subjectDNsize + \
subjectCertInfoPtr->publicKeyInfoSize;
if( extensionSize > 0 )
length += ( int ) \
sizeofObject( sizeofShortInteger( X509VERSION_3 ) ) + \
sizeofObject( sizeofObject( extensionSize ) );
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* If there are extensions present, mark this as a v3 certificate */
if( extensionSize )
{
writeConstructed( stream, sizeofShortInteger( X509VERSION_3 ),
CTAG_CE_VERSION );
writeShortInteger( stream, X509VERSION_3, DEFAULT_TAG );
}
/* Write the serial number and signature algorithm identifier */
writeInteger( stream, certCertInfo->serialNumber,
certCertInfo->serialNumberLength, DEFAULT_TAG );
status = writeContextAlgoID( stream, iIssuerCryptContext,
certCertInfo->hashAlgo,
ALGOID_FLAG_ALGOID_ONLY );
if( cryptStatusError( status ) )
return( status );
/* Write the issuer name, validity period, subject name, and public key
information */
if( issuerCertInfoPtr->subjectDNptr != NULL )
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
else
{
status = writeDN( stream, subjectCertInfoPtr->issuerName, DEFAULT_TAG );
if( cryptStatusError( status ) )
return( status );
}
writeSequence( stream, sizeofUTCTime() * 2 );
writeUTCTime( stream, subjectCertInfoPtr->startTime, DEFAULT_TAG );
writeUTCTime( stream, subjectCertInfoPtr->endTime, DEFAULT_TAG );
status = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );
if( cryptStatusOK( status ) )
status = swrite( stream, subjectCertInfoPtr->publicKeyInfo,
subjectCertInfoPtr->publicKeyInfoSize );
if( cryptStatusError( status ) || extensionSize <= 0 )
return( status );
/* Write the extensions */
return( writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_CERTIFICATE, extensionSize ) );
}
/* Write attribute certificate information:
AttributeCertificateInfo ::= SEQUENCE {
version INTEGER DEFAULT(1),
owner [ 1 ] Name,
issuer Name,
signature AlgorithmIdentifier,
serialNumber INTEGER,
validity Validity,
attributes SEQUENCE OF Attribute,
extensions Extensions OPTIONAL
} */
static int writeAttributeCertInfo( STREAM *stream,
CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
const CRYPT_CONTEXT iIssuerCryptContext )
{
const CERT_CERT_INFO *certCertInfo = subjectCertInfoPtr->cCertCert;
int length, extensionSize, issuerNameSize, status;
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
CRYPT_CERTTYPE_ATTRIBUTE_CERT );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how the issuer name will be encoded */
issuerNameSize = ( issuerCertInfoPtr->subjectDNptr != NULL ) ? \
issuerCertInfoPtr->subjectDNsize : \
sizeofDN( subjectCertInfoPtr->issuerName );
/* Determine the size of the certificate information */
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
length = ( int ) sizeofObject( sizeofDN( subjectCertInfoPtr->subjectName ) ) + \
issuerNameSize + \
sizeofContextAlgoID( iIssuerCryptContext, certCertInfo->hashAlgo,
ALGOID_FLAG_ALGOID_ONLY ) + \
sizeofInteger( certCertInfo->serialNumber,
certCertInfo->serialNumberLength ) + \
sizeofObject( sizeofUTCTime() * 2 ) + \
sizeofObject( 0 ) + \
( extensionSize ? ( int ) sizeofObject( extensionSize ) : 0 );
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* Write the owner and issuer name */
writeConstructed( stream, sizeofDN( subjectCertInfoPtr->subjectName ),
CTAG_AC_ENTITYNAME );
status = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );
if( cryptStatusOK( status ) )
{
if( issuerCertInfoPtr->subjectDNptr != NULL )
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
else
status = writeDN( stream, subjectCertInfoPtr->issuerName, DEFAULT_TAG );
}
if( cryptStatusError( status ) )
return( status );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -