📄 write.c
字号:
if( cryptStatusError( requestEntrySize ) )
return( requestEntrySize );
requestInfoLength += requestEntrySize;
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
if( cryptStatusError( extensionSize ) )
return( extensionSize );
length = sizeofObject( requestInfoLength ) + \
( ( extensionSize > 0 ) ? sizeofObject( extensionSize ) : 0 );
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* Write the SEQUENCE OF request wrapper and the request information */
status = writeSequence( stream, requestInfoLength );
for( validityInfo = certValInfo->validityInfo, iterationCount = 0;
cryptStatusOK( status ) && validityInfo != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
validityInfo = validityInfo->next, iterationCount++ )
{
status = writeRtcsRequestEntry( stream, validityInfo );
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
if( cryptStatusError( status ) || extensionSize <= 0 )
return( status );
/* Write the attributes */
return( writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_RTCS_REQUEST, extensionSize ) );
}
/* Write an RTCS response:
RTCSResponse ::= SEQUENCE {
SEQUENCE OF SEQUENCE {
certHash OCTET STRING SIZE(20),
RESPONSEINFO
}
} */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeRtcsResponseInfo( 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 = 0, extensionSize, validityInfoLength = 0;
int iterationCount, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
REQUIRES( issuerCertInfoPtr == NULL );
REQUIRES( iIssuerCryptContext == CRYPT_UNUSED );
/* RTCS can legitimately return an empty response if there's a problem
with the responder so we don't require that any responses be present
as for CRLs/OCSP */
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, NULL,
PRE_SET_VALINFO, PRE_CHECK_NONE,
PRE_FLAG_NONE );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded RTCS response will be */
for( validityInfo = certValInfo->validityInfo, iterationCount = 0;
validityInfo != NULL && iterationCount < FAILSAFE_ITERATIONS_LARGE;
validityInfo = validityInfo->next, iterationCount++ )
{
const int responseEntrySize = \
sizeofRtcsResponseEntry( validityInfo,
certValInfo->responseType == RTCSRESPONSE_TYPE_EXTENDED );
if( cryptStatusError( responseEntrySize ) )
return( responseEntrySize );
validityInfoLength += responseEntrySize;
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
if( cryptStatusError( extensionSize ) )
return( extensionSize );
length += sizeofObject( validityInfoLength ) + \
( ( extensionSize > 0 ) ? sizeofObject( extensionSize ) : 0 );
/* Write the SEQUENCE OF status information wrapper and the certificate
status information */
status = writeSequence( stream, validityInfoLength );
for( validityInfo = certValInfo->validityInfo, iterationCount = 0;
cryptStatusOK( status ) && validityInfo != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
validityInfo = validityInfo->next, iterationCount++ )
{
status = writeRtcsResponseEntry( stream, validityInfo,
certValInfo->responseType == RTCSRESPONSE_TYPE_EXTENDED );
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
if( cryptStatusError( status ) || extensionSize <= 0 )
return( status );
/* Write the attributes */
return( writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_RTCS_RESPONSE, extensionSize ) );
}
/* Write an OCSP request:
OCSPRequest ::= SEQUENCE { -- Write, v1
reqName [1] EXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,
reqList SEQUENCE OF SEQUENCE {
SEQUENCE { -- certID
hashAlgo AlgorithmIdentifier,
iNameHash OCTET STRING,
iKeyHash OCTET STRING,
serialNo INTEGER
} }
}
OCSPRequest ::= SEQUENCE { -- Write, v2
version [0] EXPLICIT INTEGER (1),
reqName [1] EXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,
reqList SEQUENCE OF SEQUENCE {
certID [2] EXPLICIT OCTET STRING -- Certificate hash
}
} */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int writeOcspRequestInfo( INOUT STREAM *stream,
INOUT CERT_INFO *subjectCertInfoPtr,
IN_OPT const CERT_INFO *issuerCertInfoPtr,
IN_HANDLE_OPT \
const CRYPT_CONTEXT iIssuerCryptContext )
{
CERT_REV_INFO *certRevInfo = subjectCertInfoPtr->cCertRev;
REVOCATION_INFO *revocationInfo;
int length, extensionSize, revocationInfoLength = 0;
int iterationCount, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( issuerCertInfoPtr == NULL || \
isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
REQUIRES( iIssuerCryptContext == CRYPT_UNUSED || \
isHandleRangeValid( iIssuerCryptContext ) );/* Not used here */
/* 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
OCSP request. We don't check for problems (which in any case,
could only occur if there's an out-of-memory error) because
there's not much that we can meaningfully do if the add fails */
attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_OCSP_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_OCSP_NONCE,
CRYPT_ATTRIBUTE_NONE, nonce, 16,
ATTR_FLAG_NONE, &dummy1, &dummy2 );
}
attributeListPtr = findAttributeField( subjectCertInfoPtr->attributes,
CRYPT_CERTINFO_OCSP_NONCE,
CRYPT_ATTRIBUTE_NONE );
}
if( cryptStatusError( status ) )
return( status );
if( attributeListPtr != NULL )
{
BYTE *noncePtr = attributeListPtr->value;
/* Because of OCSP's inexplicable use of integers to encode the
nonce octet string we have to tweak the first byte to ensure
that the integer encoding works as a standard OCTET STRING */
noncePtr[ 0 ] &= 0x7F;
if( noncePtr[ 0 ] == 0 )
noncePtr[ 0 ]++;
}
/* Perform the pre-encoding checks */
if( issuerCertInfoPtr != NULL )
{
/* It's a signed request, there has to be an issuer DN present */
status = preEncodeCertificate( subjectCertInfoPtr,
issuerCertInfoPtr, PRE_SET_REVINFO,
PRE_CHECK_ISSUERDN | \
PRE_CHECK_REVENTRIES,
PRE_FLAG_DN_IN_ISSUERCERT );
}
else
{
status = preEncodeCertificate( subjectCertInfoPtr, NULL,
PRE_SET_REVINFO,
PRE_CHECK_REVENTRIES,
PRE_FLAG_NONE );
}
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded OCSP request will be */
for( revocationInfo = certRevInfo->revocations, iterationCount = 0;
revocationInfo != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
revocationInfo = revocationInfo->next, iterationCount++ )
{
const int requestEntrySize = sizeofOcspRequestEntry( revocationInfo );
if( cryptStatusError( requestEntrySize ) )
return( requestEntrySize );
revocationInfoLength += requestEntrySize;
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
extensionSize = sizeofAttributes( subjectCertInfoPtr->attributes );
if( cryptStatusError( extensionSize ) )
return( extensionSize );
length = ( ( subjectCertInfoPtr->version == 2 ) ? \
sizeofObject( sizeofShortInteger( CTAG_OR_VERSION ) ) : 0 ) + \
( ( issuerCertInfoPtr != NULL ) ? \
sizeofObject( sizeofObject( issuerCertInfoPtr->subjectDNsize ) ) : 0 ) + \
sizeofObject( revocationInfoLength ) + \
( ( extensionSize > 0 ) ? \
sizeofObject( sizeofObject( extensionSize ) ) : 0 );
/* Write the outer SEQUENCE wrapper */
writeSequence( stream, length );
/* If we're using v2 identifiers, mark this as a v2 request */
if( subjectCertInfoPtr->version == 2 )
{
writeConstructed( stream, sizeofShortInteger( 1 ), CTAG_OR_VERSION );
writeShortInteger( stream, 1, DEFAULT_TAG );
}
/* If we're signing the request, write the issuer DN as a GeneralName */
if( issuerCertInfoPtr != NULL )
{
writeConstructed( stream,
sizeofObject( issuerCertInfoPtr->subjectDNsize ), 1 );
writeConstructed( stream, issuerCertInfoPtr->subjectDNsize, 4 );
swrite( stream, issuerCertInfoPtr->subjectDNptr,
issuerCertInfoPtr->subjectDNsize );
}
/* Write the SEQUENCE OF revocation information wrapper and the
revocation information */
status = writeSequence( stream, revocationInfoLength );
for( revocationInfo = certRevInfo->revocations, iterationCount = 0;
cryptStatusOK( status ) && revocationInfo != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
revocationInfo = revocationInfo->next, iterationCount++ )
{
status = writeOcspRequestEntry( stream, revocationInfo );
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
if( cryptStatusError( status ) || extensionSize <= 0 )
return( status );
/* Write the attributes */
return( writeAttributes( stream, subjectCertInfoPtr->attributes,
CRYPT_CERTTYPE_OCSP_REQUEST, extensionSize ) );
}
/* Write an OCSP response:
OCSPResponse ::= SEQUENCE {
version [0] EXPLICIT INTEGER (1),
respID [1] EXPLICIT Name,
producedAt GeneralizedTime,
responses SEQUENCE OF Response
exts [1] EXPLICIT Extensions OPTIONAL,
} */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int writeOcspResponseInfo( INOUT STREAM *stream,
INOUT CERT_INFO *subjectCertInfoPtr,
const CERT_INFO *issuerCertInfoPtr,
IN_HANDLE \
const CRYPT_CONTEXT iIssuerCryptContext )
{
CERT_REV_INFO *certRevInfo = subjectCertInfoPtr->cCertRev;
REVOCATION_INFO *revocationInfo;
int length = 0, extensionSize, revocationInfoLength = 0;
int iterationCount, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );
assert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );
REQUIRES( isHandleRangeValid( iIssuerCryptContext ) );/* Not used here */
/* Perform any necessary pre-encoding steps */
if( sIsNullStream( stream ) )
{
status = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,
PRE_SET_NONE,
PRE_CHECK_ISSUERDN | \
PRE_CHECK_REVENTRIES,
PRE_FLAG_DN_IN_ISSUERCERT );
if( cryptStatusError( status ) )
return( status );
}
/* Determine how big the encoded OCSP response will be */
for( revocationInfo = certRevInfo->revocations, iterationCount = 0;
revocationInfo != NULL && \
iterationCount < FAILSAFE_ITERATIONS_LARGE;
revocationInfo = revocationInfo->next, iterationCount++ )
{
const int responseEntrySize = sizeofOcspResponseEntry( revocationInfo );
if( cryptStatusError( responseEntrySize ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -