📄 read.c
字号:
}
else
status = readUniversal( stream );
}
if( cryptStatusError( status ) )
return( status );
/* Fix up any problems in attributes */
return( fixAttributes( certInfoPtr ) );
}
/* Read an RTCS request/response */
static int readRtcsRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;
int length, endPos, status;
/* Read the outer wrapper and SEQUENCE OF request info and make the
currently selected one the start of the list */
readSequence( stream, &length );
endPos = stell( stream ) + length;
status = readSequence( stream, &length );
while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
{
const int innerStartPos = stell( stream );
status = readRtcsRequestEntry( stream, &certValInfo->validityInfo,
certInfoPtr );
length -= stell( stream ) - innerStartPos;
}
if( cryptStatusError( status ) )
/* The invalid attribute isn't quite a user certificate, but it's the
data that arose from a user certificate so it's the most
appropriate locus for the error */
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
status ) );
certValInfo->currentValidity = certValInfo->validityInfo;
/* Read the extensions if there are any present. Because some requests
will have broken encoding of lengths, we allow for a bit of slop for
software that gets the length encoding wrong by a few bytes */
if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
{
status = readAttributes( stream, &certInfoPtr->attributes,
CRYPT_CERTTYPE_RTCS_REQUEST, endPos - stell( stream ),
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
}
/* Fix up any problems in attributes */
return( fixAttributes( certInfoPtr ) );
}
static int readRtcsResponseInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;
int length, endPos, status;
/* Read the SEQUENCE OF validity info and make the currently selected
one the start of the list */
status = readSequence( stream, &length );
endPos = stell( stream ) + length;
while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
{
const int innerStartPos = stell( stream );
status = readRtcsResponseEntry( stream, &certValInfo->validityInfo,
certInfoPtr, FALSE );
length -= stell( stream ) - innerStartPos;
}
if( cryptStatusError( status ) )
/* The invalid attribute isn't quite a user certificate, but it's the
data that arose from a user certificate so it's the most
appropriate locus for the error */
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
status ) );
certValInfo->currentValidity = certValInfo->validityInfo;
if( stell( stream ) > endPos - MIN_ATTRIBUTE_SIZE )
return( CRYPT_OK );
/* Read the extensions */
return( readAttributes( stream, &certInfoPtr->attributes,
CRYPT_CERTTYPE_RTCS_RESPONSE, endPos - stell( stream ),
&certInfoPtr->errorLocus, &certInfoPtr->errorType ) );
}
/* Read an OCSP request/response */
static int readOcspRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
int length, endPos, status;
/* Read the wrapper, version information, and requestor name */
readSequence( stream, &length );
endPos = stell( stream ) + length;
if( peekTag( stream ) == MAKE_CTAG( CTAG_OR_VERSION ) )
{
long version;
readConstructed( stream, NULL, CTAG_OR_VERSION );
status = readShortInteger( stream, &version );
if( cryptStatusError( status ) )
return( status );
certInfoPtr->version = version + 1; /* Zero-based */
}
else
certInfoPtr->version = 1;
if( peekTag( stream ) == MAKE_CTAG( CTAG_OR_DUMMY ) )
readUniversal( stream );
/* Read the SEQUENCE OF revocation info and make the currently selected
one the start of the list */
status = readSequence( stream, &length );
while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
{
const int innerStartPos = stell( stream );
status = readOcspRequestEntry( stream, &certRevInfo->revocations,
certInfoPtr );
length -= stell( stream ) - innerStartPos;
}
if( cryptStatusError( status ) )
/* The invalid attribute isn't quite a user certificate, but it's the
data that arose from a user certificate so it's the most
appropriate locus for the error */
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
status ) );
certRevInfo->currentRevocation = certRevInfo->revocations;
/* Read the extensions if there are any present. Because some requests
will have broken encoding of lengths, we allow for a bit of slop for
software that gets the length encoding wrong by a few bytes */
if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
{
status = readAttributes( stream, &certInfoPtr->attributes,
CRYPT_CERTTYPE_OCSP_REQUEST, endPos - stell( stream ),
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
}
/* Fix up any problems in attributes */
return( fixAttributes( certInfoPtr ) );
}
static int readOcspResponseInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
int length, endPos, status;
/* Read the wrapper, version information, and responder ID */
certInfoPtr->version = 1;
readSequence( stream, &length ); /* tbsResponseData */
endPos = stell( stream ) + length;
if( peekTag( stream ) == MAKE_CTAG( CTAG_OP_VERSION ) )
{
long version;
readConstructed( stream, NULL, CTAG_OP_VERSION );
status = readShortInteger( stream, &version );
if( cryptStatusError( status ) )
return( status );
certInfoPtr->version = version + 1; /* Zero-based */
}
if( peekTag( stream ) == MAKE_CTAG( 1 ) )
{
/* It's a DN, read it as the issuer name in case the caller is
interested in it */
readConstructed( stream, NULL, 1 );
status = readIssuerDN( stream, certInfoPtr );
if( cryptStatusError( status ) )
return( status );
}
else
/* We can't do much with a key hash, in any case all current
responders use the issuer DN to identify the responder so
this shouldn't be much of a problem */
readUniversal( stream );
readGeneralizedTime( stream, NULL ); /* producedAt */
/* Read the SEQUENCE OF revocation info and make the currently selected
one the start of the list */
status = readSequence( stream, &length );
while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
{
const int innerStartPos = stell( stream );
status = readOcspResponseEntry( stream, &certRevInfo->revocations,
certInfoPtr );
length -= stell( stream ) - innerStartPos;
}
if( cryptStatusError( status ) )
/* The invalid attribute isn't quite a user certificate, but it's the
data that arose from a user certificate so it's the most
appropriate locus for the error */
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
status ) );
certRevInfo->currentRevocation = certRevInfo->revocations;
/* Read the extensions if there are any present */
if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
status = readAttributes( stream, &certInfoPtr->attributes,
CRYPT_CERTTYPE_OCSP_RESPONSE, endPos - stell( stream ),
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
/* In theory some OCSP responses can be sort of self-signed via attached
certs, but there are so many incompatible ways to delegate trust and
signing authority mentioned in the RFC without any indication of
which one implementors will follow that we require the user to supply
the sig check certificate rather than assuming that some particular
trust delegation mechanism will happen to be in place */
/* certInfoPtr->flags |= CERT_FLAG_SELFSIGNED; */
return( status );
}
/* Read PKI user info */
static int readPkiUserInfo( STREAM *stream, CERT_INFO *userInfoPtr )
{
CRYPT_CONTEXT iCryptContext;
CERT_PKIUSER_INFO *certUserInfo = userInfoPtr->cCertUser;
MESSAGE_CREATEOBJECT_INFO createInfo;
ATTRIBUTE_LIST *attributeListCursor;
QUERY_INFO queryInfo;
STREAM userInfoStream;
BYTE userInfo[ 128 ];
int userInfoSize, length, status;
/* Read the user name and encryption algorithm info and the start of the
encrypted data */
userInfoPtr->subjectDNptr = sMemBufPtr( stream );
userInfoPtr->subjectDNsize = stell( stream );
status = readDN( stream, &userInfoPtr->subjectName );
userInfoPtr->subjectDNsize = stell( stream ) - userInfoPtr->subjectDNsize;
if( cryptStatusOK( status ) )
{
readContextAlgoID( stream, NULL, &queryInfo, DEFAULT_TAG );
status = readOctetString( stream, userInfo, &userInfoSize, 128 );
if( cryptStatusOK( status ) && \
userInfoSize != PKIUSER_ENCR_AUTHENTICATOR_SIZE )
status = CRYPT_ERROR_BADDATA;
}
if( cryptStatusError( status ) )
return( status );
/* Clone the CA key for our own use, load the IV from the encryption
info, and use the cloned context to decrypt the user info. We need to
do this to prevent problems if multiple threads try to simultaneously
decrypt with the CA key. Since user objects aren't fully implemented
yet, we use a fixed key as the CA key for now (most CA guidelines
merely require that the CA protect its user database via standard
(physical/ACL) security measures, so this is no less secure than what's
required by various CA guidelines).
When we do this for real we probably need an extra level of
indirection to go from the CA secret to the database decryption key
so that we can change the encryption algorithm and so that we don't
have to directly apply the CA secret key to the user database */
setMessageCreateObjectInfo( &createInfo, queryInfo.cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, "interop interop interop ", 24 );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY );
iCryptContext = createInfo.cryptHandle;
}
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, queryInfo.iv, queryInfo.ivLength );
krnlSendMessage( iCryptContext,IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV );
status = krnlSendMessage( iCryptContext, IMESSAGE_CTX_DECRYPT,
userInfo, userInfoSize );
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
}
if( cryptStatusError( status ) )
return( status );
/* Read the user info. If we get a bad data error at this point we
report it as a wrong decryption key rather than bad data since it's
more likely to be the former */
sMemConnect( &userInfoStream, userInfo, userInfoSize );
readSequence( &userInfoStream, NULL );
readOctetString( &userInfoStream, certUserInfo->pkiIssuePW, &length,
PKIUSER_AUTHENTICATOR_SIZE );
status = readOctetString( &userInfoStream, certUserInfo->pkiRevPW,
&length, PKIUSER_AUTHENTICATOR_SIZE );
sMemDisconnect( &userInfoStream );
zeroise( userInfo, userInfoSize );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_WRONGKEY );
/* Read the user ID and any other attributes */
status = readAttributes( stream, &userInfoPtr->attributes,
CRYPT_CERTTYPE_PKIUSER, sMemDataLeft( stream ),
&userInfoPtr->errorLocus,
&userInfoPtr->errorType );
if( cryptStatusError( status ) )
return( status );
/* In use the PKI user info is applied as a template to certificates to
modify their contents before issue. This is done by merging the
user info with the cert before it's issued. Since there can be
overlapping or conflicting attributes in the two objects, the ones in
the PKI user info are marked as locked to ensure that they override
any conflicting attributes that may be present in the cert */
for( attributeListCursor = userInfoPtr->attributes;
attributeListCursor != NULL && \
!isBlobAttribute( attributeListCursor );
attributeListCursor = attributeListCursor->next )
attributeListCursor->flags |= ATTR_FLAG_LOCKED;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Read Function Access Information *
* *
****************************************************************************/
const CERTREAD_INFO certReadTable[] = {
{ CRYPT_CERTTYPE_CERTIFICATE, readCertInfo },
{ CRYPT_CERTTYPE_ATTRIBUTE_CERT, readAttributeCertInfo },
{ CRYPT_CERTTYPE_CERTREQUEST, readCertRequestInfo },
{ CRYPT_CERTTYPE_REQUEST_CERT, readCrmfRequestInfo },
{ CRYPT_CERTTYPE_REQUEST_REVOCATION, readRevRequestInfo },
{ CRYPT_CERTTYPE_CRL, readCRLInfo },
{ CRYPT_CERTTYPE_CMS_ATTRIBUTES, readCmsAttributes },
{ CRYPT_CERTTYPE_RTCS_REQUEST, readRtcsRequestInfo },
{ CRYPT_CERTTYPE_RTCS_RESPONSE, readRtcsResponseInfo },
{ CRYPT_CERTTYPE_OCSP_REQUEST, readOcspRequestInfo },
{ CRYPT_CERTTYPE_OCSP_RESPONSE, readOcspResponseInfo },
{ CRYPT_CERTTYPE_PKIUSER, readPkiUserInfo },
{ CRYPT_ICERTTYPE_CMS_CERTSET, NULL },
{ CRYPT_ICERTTYPE_SSL_CERTCHAIN, NULL },
{ CRYPT_CERTTYPE_NONE, NULL }
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -