📄 write.c
字号:
/* Make sure that everything is in order */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, NULL, PRE_SET_NONE,
PRE_CHECK_ISSUERDN | PRE_CHECK_SERIALNO,
PRE_FLAG_NONE );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded certificate request will be */
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
if( cryptStatusError( extensionSize ) )
return( extensionSize );
payloadLength = sizeofInteger( subjectCertInfoPtr->cCertCert->serialNumber,
subjectCertInfoPtr->cCertCert->serialNumberLength ) + \
sizeofObject( subjectCertInfoPtr->issuerDNsize ) + \
( ( extensionSize > 0 ) ? \
sizeofObject( extensionSize ) : 0 );
/* Write the header, inner header, serial number and issuer DN */
writeSequence( stream, sizeofObject( payloadLength ) );
writeSequence( stream, payloadLength );
writeInteger( stream, subjectCertInfoPtr->cCertCert->serialNumber,
subjectCertInfoPtr->cCertCert->serialNumberLength,
CTAG_CF_SERIALNUMBER );
writeConstructed( stream, subjectCertInfoPtr->issuerDNsize,
CTAG_CF_ISSUER );
status = swrite( stream, subjectCertInfoPtr->issuerDNptr,
subjectCertInfoPtr->issuerDNsize );
if( cryptStatusError( status ) || extensionSize <= 0 )
return( status );
/* Write the attributes */
writeConstructed( stream, extensionSize, CTAG_CF_EXTENSIONS );
return( writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_REQUEST_REVOCATION, extensionSize ) );
}
/* Write CRL information:
CRLInfo ::= SEQUENCE {
version INTEGER DEFAULT(0),
signature AlgorithmIdentifier,
issuer Name,
thisUpdate UTCTime,
nextUpdate UTCTime OPTIONAL,
revokedCertificates SEQUENCE OF RevokedCerts,
extensions [ 0 ] Extensions OPTIONAL
} */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeCRLInfo( INOUT STREAM *stream,
INOUT CERT_INFO *subjectCertInfoPtr,
IN_OPT const CERT_INFO *issuerCertInfoPtr,
IN_HANDLE_OPT const CRYPT_CONTEXT iIssuerCryptContext )
{
const CERT_REV_INFO *certRevInfo = subjectCertInfoPtr->cCertRev;
REVOCATION_INFO *revocationInfo;
const BOOLEAN isCrlEntry = ( issuerCertInfoPtr == NULL ) ? TRUE : FALSE;
int length, algoIdInfoSize, extensionSize, revocationInfoLength = 0;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( ( issuerCertInfoPtr == NULL && \
iIssuerCryptContext == CRYPT_UNUSED ) || \
( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) && \
isHandleRangeValid( iIssuerCryptContext ) ) );
REQUIRES( ( issuerCertInfoPtr == NULL && \
iIssuerCryptContext == CRYPT_UNUSED ) || \
( issuerCertInfoPtr != NULL && \
isHandleRangeValid( iIssuerCryptContext ) ) );
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
if( isCrlEntry )
{
status = preEncodeCertificate( subjectCertInfoPtr, NULL,
PRE_SET_REVINFO, 0,
PRE_FLAG_NONE );
}
else
{
status = preEncodeCertificate( subjectCertInfoPtr,
issuerCertInfoPtr,
PRE_SET_ISSUERDN | PRE_SET_ISSUERATTR | \
PRE_SET_REVINFO,
PRE_CHECK_ISSUERCERTDN | PRE_CHECK_ISSUERDN,
PRE_FLAG_DN_IN_ISSUERCERT );
}
if( cryptStatusError( status ) )
return( status );
}
/* Process CRL entries and version information */
subjectCertInfoPtr->version = \
( subjectCertInfoPtr->attributes != NULL ) ? 2 : 1;
for( revocationInfo = certRevInfo->revocations;
revocationInfo != NULL; revocationInfo = revocationInfo->next )
{
const int crlEntrySize = sizeofCRLentry( revocationInfo );
if( cryptStatusError( crlEntrySize ) )
return( crlEntrySize );
revocationInfoLength += crlEntrySize;
/* If there are per-entry extensions present it's a v2 CRL */
if( revocationInfo->attributes != NULL )
subjectCertInfoPtr->version = 2;
}
/* If we're being asked to write a single CRL entry, we don't try and go
any further since the remaining CRL fields (and issuer info) may not
be set up */
if( isCrlEntry )
return( writeCRLentry( stream, certRevInfo->currentRevocation ) );
/* Determine how big the encoded CRL will be */
algoIdInfoSize = sizeofContextAlgoID( iIssuerCryptContext,
certRevInfo->hashAlgo );
if( cryptStatusError( algoIdInfoSize ) )
return( algoIdInfoSize );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
if( cryptStatusError( extensionSize ) )
return( extensionSize );
length = algoIdInfoSize + \
issuerCertInfoPtr->subjectDNsize + sizeofUTCTime() + \
( ( subjectCertInfoPtr->endTime > MIN_TIME_VALUE ) ? \
sizeofUTCTime() : 0 ) + \
sizeofObject( revocationInfoLength );
if( extensionSize > 0 )
{
length += sizeofShortInteger( X509VERSION_2 ) + \
sizeofObject( sizeofObject( extensionSize ) );
}
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* If there are extensions present, mark this as a v2 CRL */
if( extensionSize > 0 )
writeShortInteger( stream, X509VERSION_2, DEFAULT_TAG );
/* Write the signature algorithm identifier, issuer name, and CRL time */
status = writeContextAlgoID( stream, iIssuerCryptContext,
certRevInfo->hashAlgo );
if( cryptStatusError( status ) )
return( status );
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
writeUTCTime( stream, subjectCertInfoPtr->startTime, DEFAULT_TAG );
if( subjectCertInfoPtr->endTime > MIN_TIME_VALUE )
writeUTCTime( stream, subjectCertInfoPtr->endTime, DEFAULT_TAG );
/* Write the SEQUENCE OF revoked certificates wrapper and the revoked
certificate information */
status = writeSequence( stream, revocationInfoLength );
for( revocationInfo = certRevInfo->revocations;
cryptStatusOK( status ) && revocationInfo != NULL;
revocationInfo = revocationInfo->next )
status = writeCRLentry( stream, revocationInfo );
if( cryptStatusError( status ) || extensionSize <= 0 )
return( status );
/* Write the extensions */
return( writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_CRL, extensionSize ) );
}
/* Write CMS attributes */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeCmsAttributes( INOUT STREAM *stream,
INOUT CERT_INFO *attributeInfoPtr,
STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,
STDC_UNUSED const CRYPT_CONTEXT iIssuerCryptContext )
{
int addDefaultAttributes, attributeSize, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( attributeInfoPtr, sizeof( CERT_INFO ) ) );
REQUIRES( issuerCertInfoPtr == NULL );
REQUIRES( iIssuerCryptContext == CRYPT_UNUSED );
REQUIRES( attributeInfoPtr->attributes != NULL );
status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE, &addDefaultAttributes,
CRYPT_OPTION_CMS_DEFAULTATTRIBUTES );
if( cryptStatusError( status ) )
return( status );
/* Make sure that there's a hash and content type present */
if( findAttributeField( attributeInfoPtr->attributes,
CRYPT_CERTINFO_CMS_MESSAGEDIGEST,
CRYPT_ATTRIBUTE_NONE ) == NULL )
{
setErrorInfo( attributeInfoPtr, CRYPT_CERTINFO_CMS_MESSAGEDIGEST,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_INVALID );
}
if( !checkAttributePresent( attributeInfoPtr->attributes,
CRYPT_CERTINFO_CMS_CONTENTTYPE ) )
{
const int value = CRYPT_CONTENT_DATA;
/* If there's no content type and we're not adding it automatically,
complain */
if( !addDefaultAttributes )
{
setErrorInfo( attributeInfoPtr, CRYPT_CERTINFO_CMS_CONTENTTYPE,
CRYPT_ERRTYPE_ATTR_ABSENT );
return( CRYPT_ERROR_INVALID );
}
/* There's no content type present, treat it as straight data (which
means that this is signedData) */
status = addCertComponent( attributeInfoPtr, CRYPT_CERTINFO_CMS_CONTENTTYPE,
&value, CRYPT_UNUSED );
if( cryptStatusError( status ) )
return( status );
}
/* If there's no signing time attribute present and we're adding the
default attributes, add it now. This will usually already have been
added by the caller via getReliableTime(), if it hasn't then we
default to using the system time source because the signing object
isn't available at this point to provide a time source */
if( addDefaultAttributes && \
!checkAttributePresent( attributeInfoPtr->attributes,
CRYPT_CERTINFO_CMS_SIGNINGTIME ) )
{
const time_t currentTime = getTime();
/* If the time is screwed up we can't provide a signed indication
of the time */
if( currentTime <= MIN_TIME_VALUE )
{
setErrorInfo( attributeInfoPtr, CRYPT_CERTINFO_VALIDFROM,
CRYPT_ERRTYPE_ATTR_VALUE );
return( CRYPT_ERROR_NOTINITED );
}
status = addCertComponent( attributeInfoPtr, CRYPT_CERTINFO_CMS_SIGNINGTIME,
¤tTime, sizeof( time_t ) );
if( cryptStatusError( status ) )
return( status );
}
/* Check that the attributes are in order and determine how big the whole
mess will be */
status = checkAttributes( ATTRIBUTE_CMS, attributeInfoPtr->attributes,
&attributeInfoPtr->errorLocus,
&attributeInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
attributeSize = sizeofAttributes( attributeInfoPtr->attributes );
if( cryptStatusError( attributeSize ) || attributeSize <= 0 )
return( attributeSize );
/* Write the attributes */
return( writeAttributes( stream, attributeInfoPtr->attributes,
CRYPT_CERTTYPE_CMS_ATTRIBUTES, attributeSize ) );
}
/* Write an RTCS request:
RTCSRequests ::= SEQUENCE {
SEQUENCE OF SEQUENCE {
certHash OCTET STRING SIZE(20)
},
attributes Attributes OPTIONAL
} */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeRtcsRequestInfo( INOUT STREAM *stream,
INOUT CERT_INFO *subjectCertInfoPtr,
STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,
STDC_UNUSED \
const CRYPT_CONTEXT iIssuerCryptContext )
{
CERT_VAL_INFO *certValInfo = subjectCertInfoPtr->cCertVal;
VALIDITY_INFO *validityInfo;
int length, extensionSize, requestInfoLength = 0;
int iterationCount, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
REQUIRES( issuerCertInfoPtr == NULL );
REQUIRES( iIssuerCryptContext == CRYPT_UNUSED );
/* Perform any necessary pre-encoding steps. We should really update the
nonce when we write the data for real, but to do that we'd have to re-
calculate the extension information (via preEncodeCertifiate()) for
null-stream and real writes just because the one extension changes so
we calculate it when we do the dummy write instead. This is safe
because the write process always performs a real write immediately
after the null-stream write */
if( sIsNullStream( stream ) )
{
ATTRIBUTE_LIST *attributeListPtr;
MESSAGE_DATA msgData;
/* To ensure freshness we always use a new nonce when we write an
RTCS request */
attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_CMS_NONCE,
CRYPT_ATTRIBUTE_NONE );
if( attributeListPtr != NULL )
{
setMessageData( &msgData, attributeListPtr->value, 16 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
attributeListPtr->valueLength = 16;
}
else
{
CRYPT_ATTRIBUTE_TYPE dummy1;
CRYPT_ERRTYPE_TYPE dummy2;
BYTE nonce[ CRYPT_MAX_HASHSIZE + 8 ];
setMessageData( &msgData, nonce, 16 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM_NONCE );
if( cryptStatusOK( status ) )
status = addAttributeField( &subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_CMS_NONCE,
CRYPT_ATTRIBUTE_NONE, nonce, 16,
ATTR_FLAG_NONE, &dummy1, &dummy2 );
}
if( cryptStatusError( status ) )
return( status );
/* Perform the pre-encoding checks */
status = preEncodeCertificate( subjectCertInfoPtr, NULL,
PRE_SET_NONE, PRE_CHECK_VALENTRIES,
PRE_FLAG_NONE );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded RTCS request will be */
for( validityInfo = certValInfo->validityInfo, iterationCount = 0;
validityInfo != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
validityInfo = validityInfo->next, iterationCount++ )
{
const int requestEntrySize = sizeofRtcsRequestEntry( validityInfo );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -