certrd.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,383 行 · 第 1/4 页
C
1,383 行
int fixEmailAddress;
krnlSendMessage( certInfoPtr->ownerHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress,
CRYPT_OPTION_CERT_FIXEMAILADDRESS );
if( fixEmailAddress )
status = convertEmailAddress( certInfoPtr );
}
/* Certification requests are always self-signed */
certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
return( status );
}
/* Read the information in a CRMF certificate request. This enforces the
requirement that the request must contain at least a subject DN and a
public key */
int readCRMFRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
int status;
/* Skip the outer SEQUENCE, request ID, and inner SEQUENCE (these have
already been checked earlier on) */
readSequence( stream, NULL );
readUniversal( stream );
status = readSequence( stream, NULL );
/* Skip any junk before the Validity, SubjectName, or
SubjectPublicKeyInfo */
while( cryptStatusOK( status ) && \
( peekTag( stream ) != MAKE_CTAG( CTAG_CF_VALIDITY ) && \
peekTag( stream ) != MAKE_CTAG( CTAG_CF_SUBJECT ) && \
peekTag( stream ) != MAKE_CTAG( CTAG_CF_PUBLICKEY ) ) )
status = readUniversal( stream );
if( cryptStatusError( status ) )
return( status );
/* If there's validity data present, read it */
if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_VALIDITY ) )
{
status = readCRMFValidity( stream, &certInfoPtr->startTime,
&certInfoPtr->endTime,
&certInfoPtr->errorLocus );
if( cryptStatusError( status ) )
return( certErrorReturn( certInfoPtr, certInfoPtr->errorLocus,
status ) );
/* Skip any subsequent junk until we find the subject name or public
key */
while( cryptStatusOK( status ) && \
( peekTag( stream ) != MAKE_CTAG( CTAG_CF_SUBJECT ) && \
peekTag( stream ) != MAKE_CTAG( CTAG_CF_PUBLICKEY ) ) )
status = readUniversal( stream );
if( cryptStatusError( status ) )
return( status );
}
/* Read the subject name and public key information */
if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_SUBJECT ) )
{
readConstructed( stream, NULL, CTAG_CF_SUBJECT );
status = readSubjectDN( stream, certInfoPtr );
if( cryptStatusError( status ) )
return( status );
}
certInfoPtr->publicKeyInfo = sMemBufPtr( stream );
if( certInfoPtr->flags & CERT_FLAG_DATAONLY )
/* We're doing deferred handling of the public key, skip it for now */
status = readUniversal( stream );
else
/* CRMF uses yet more nonstandard tagging for the public key, so we
have to read it with an oddball tag instead of the default
SEQUENCE */
status = readPublicKey( stream, &certInfoPtr->iCryptContext,
READKEY_OPTION_NONE,
MAKE_CTAG( CTAG_CF_PUBLICKEY ) );
if( cryptStatusError( status ) )
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,
status ) );
/* Read the attributes */
if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_EXTENSIONS ) )
{
int length;
status = readConstructed( stream, &length, CTAG_CF_EXTENSIONS );
if( cryptStatusOK( status ) && length >= MIN_ATTRIBUTE_SIZE )
status = readAttributes( stream, &certInfoPtr->attributes,
CRYPT_CERTTYPE_REQUEST_CERT, length,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
}
/* Convert an email address in a DN into an altName if required */
if( cryptStatusOK( status ) )
{
int fixEmailAddress;
krnlSendMessage( certInfoPtr->ownerHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress,
CRYPT_OPTION_CERT_FIXEMAILADDRESS );
if( fixEmailAddress )
status = convertEmailAddress( certInfoPtr );
}
/* CRMF certification requests are always self-signed */
certInfoPtr->flags |= CERT_FLAG_SELFSIGNED;
return( status );
}
/* Read the information in a CRMF revocation request. This enforces the
requirement that the request must contain at least an issuer DN and a
serial number */
int readRevRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
long startPos;
int length, status;
/* Find out how much cert template is present */
status = readSequence( stream, &length );
startPos = stell( stream );
/* Skip any junk before the SerialNumber */
while( cryptStatusOK( status ) && \
peekTag( stream ) != MAKE_CTAG_PRIMITIVE( CTAG_CF_SERIALNUMBER ) )
status = readUniversal( stream );
if( cryptStatusError( status ) )
return( status );
/* Read the serial number */
status = readSerialNumber( stream, &certInfoPtr->serialNumber,
&certInfoPtr->serialNumberLength,
MAKE_CTAG_PRIMITIVE( CTAG_CF_SERIALNUMBER ) );
if( cryptStatusError( status ) )
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,
status ) );
/* Skip any junk before the IssuerName */
while( cryptStatusOK( status ) && \
peekTag( stream ) != MAKE_CTAG( CTAG_CF_ISSUER ) )
status = readUniversal( stream );
if( cryptStatusError( status ) )
return( status );
/* Read the issuer name. We don't actually care about the contents but
we have to decode them anyway in case the caller wants to view them */
readConstructed( stream, NULL, CTAG_CF_ISSUER );
status = readIssuerDN( stream, certInfoPtr );
if( cryptStatusError( status ) )
return( status );
/* Skip any further junk which may be present in the template */
if( startPos - length > 0 )
sSkip( stream, startPos - length );
/* Read the attributes */
if( peekTag( stream ) == MAKE_CTAG( CTAG_CF_EXTENSIONS ) )
{
int length;
status = readConstructed( stream, &length, CTAG_CF_EXTENSIONS );
if( cryptStatusOK( status ) && length >= MIN_ATTRIBUTE_SIZE )
status = readAttributes( stream, &certInfoPtr->attributes,
CRYPT_CERTTYPE_REQUEST_REVOCATION, length,
&certInfoPtr->errorLocus, &certInfoPtr->errorType );
}
/* Convert an email address in a DN into an altName if required */
if( cryptStatusOK( status ) )
{
int fixEmailAddress;
krnlSendMessage( certInfoPtr->ownerHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress,
CRYPT_OPTION_CERT_FIXEMAILADDRESS );
if( fixEmailAddress )
status = convertEmailAddress( certInfoPtr );
}
return( status );
}
/* Read an OCSP request:
OCSPRequest ::= SEQUENCE { -- Read
SEQUENCE { -- tbsRequest
version [0] EXPLICIT INTEGER DEFAULT 0,
-- Must be 1 if !certID used
reqName [1] EXPLICIT ... OPTIONAL
-- Ignored
reqList SEQUENCE OF Response
}
... -- Ignored
}
} */
int readOCSPRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
BYTE idBuffer[ 1024 ], *idBufPtr = idBuffer;
int length, endPos, status;
/* Read the wrapper, version information, and requestor name */
readSequence( stream, &length );
endPos = ( int ) stell( stream ) + length;
if( peekTag( stream ) == MAKE_CTAG( CTAG_RQ_VERSION ) )
{
long version;
readConstructed( stream, NULL, CTAG_RQ_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_RQ_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( !cryptStatusError( status ) && length > 16 )
{
const int innerStartPos = ( int ) stell( stream );
status = readOCSPentry( stream, &certInfoPtr->revocations,
certInfoPtr, TRUE );
length -= ( int ) stell( stream ) - innerStartPos;
}
if( cryptStatusError( status ) )
/* The invalid attribute isn't quite a user certificate, but it's the
data which arose from a user certificate so it's the most
appropriate locus for the error */
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
status ) );
certInfoPtr->currentRevocation = certInfoPtr->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 which 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 );
/* Convert an email address in a DN into an altName if required */
if( cryptStatusOK( status ) )
{
int fixEmailAddress;
krnlSendMessage( certInfoPtr->ownerHandle,
RESOURCE_IMESSAGE_GETATTRIBUTE, &fixEmailAddress,
CRYPT_OPTION_CERT_FIXEMAILADDRESS );
if( fixEmailAddress )
status = convertEmailAddress( certInfoPtr );
}
return( sGetStatus( stream ) );
}
/* Read OCSP response information:
OCSPResponse ::= SEQUENCE { -- tbsRespData
version [0] EXPLICIT ... OPTIONAL,-- Ignored
respID CHOICE {
[1] EXPLICIT Name, -- Read in case caller needs it
[2] EXPLICIT KeyHash -- Ignored
},
producedAt ..., -- Ignored
responses SEQUENCE OF Response
exts [1] EXPLICIT Extensions OPTIONAL,
} */
int readOCSPResponseInfo( STREAM *stream, CERT_INFO *certInfoPtr )
{
int length, endPos, status;
/* Read the wrapper, version information, and responder ID */
readSequence( stream, &length ); /* tbsResponseData */
endPos = ( int ) stell( stream ) + length;
if( peekTag( stream ) == MAKE_CTAG( CTAG_RP_VERSION ) )
{
long version;
readConstructed( stream, NULL, CTAG_RP_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( 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 to 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( !cryptStatusError( status ) && length > 16 )
{
const int innerStartPos = ( int ) stell( stream );
status = readOCSPentry( stream, &certInfoPtr->revocations,
certInfoPtr, FALSE );
length -= ( int ) stell( stream ) - innerStartPos;
}
if( cryptStatusError( status ) )
/* The invalid attribute isn't quite a user certificate, but it's the
data which arose from a user certificate so it's the most
appropriate locus for the error */
return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_USERCERTIFICATE,
status ) );
certInfoPtr->currentRevocation = certInfoPtr->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 weird 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 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?