📄 certchn.c
字号:
signed */
status = krnlSendMessage( certChainPtr->certChain[ certChainEnd - 1 ],
RESOURCE_IMESSAGE_GETATTRIBUTE, &selfSigned,
CRYPT_CERTINFO_SELFSIGNED );
if( cryptStatusOK( status ) && selfSigned )
certChainPtr->flags |= CERT_FLAG_SELFSIGNED;
unlockResource( certChainPtr );
return( CRYPT_OK );
}
/* Read certificate chain/sequence information */
int readCertChain( STREAM *stream, CRYPT_CERTIFICATE *iCryptCert,
const CRYPT_USER cryptOwner,
const CRYPT_CERTTYPE_TYPE type,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const BOOLEAN dataOnlyCert )
{
CRYPT_CERTIFICATE iCertChain[ MAX_CHAINLENGTH ];
int certSequenceLength, endPos, certChainEnd = 0, status;
assert( type == CRYPT_CERTTYPE_CERTCHAIN || \
type == CRYPT_CERTTYPE_CMS_CERTSET || \
type == CRYPT_CERTTYPE_SSL_CERTCHAIN );
assert( ( keyIDtype == CRYPT_KEYID_NONE && keyID == NULL && \
keyIDlength == 0 ) || \
( ( keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \
keyID != NULL && keyIDlength > 16 ) );
/* If it's a PKCS #7 chain, skip the contentType OID, read the content
encapsulation and header if necessary, and burrow into the PKCS #7
content */
if( type == CRYPT_CERTTYPE_CERTCHAIN )
{
long integer;
int length;
/* Read the wrapper */
readUniversal( stream );
readConstructed( stream, NULL, 0 );
readSequence( stream, NULL );
/* Read the version number (1 = PKCS #7 v1.5, 2 = PKCS #7 v1.6,
3 = S/MIME with attribute certificate(s)), empty SET OF
DigestAlgorithmIdentifier, and ContentInfo header */
readShortInteger( stream, &integer );
status = readSet( stream, &length );
if( cryptStatusOK( status ) && ( integer < 1 || integer > 3 ) )
status = CRYPT_ERROR_BADDATA;
if( cryptStatusError( status ) )
return( status );
if( length > 0 )
sSkip( stream, length );
/* Read the ContentInfo header, contentType OID and the inner content
encapsulation */
readSequence( stream, NULL );
status = readOID( stream, OID_CMS_DATA );
if( cryptStatusError( status ) )
return( status );
checkEOC( stream );
}
if( type == CRYPT_CERTTYPE_CERTCHAIN || \
type == CRYPT_CERTTYPE_CMS_CERTSET )
{
status = readConstructed( stream, &certSequenceLength, 0 );
if( cryptStatusError( status ) )
return( status );
}
else
/* There's no outer wrapper to give us length information for an SSL
cert chain, however the length will be equal to the total stream
size */
certSequenceLength = sMemBufSize( stream );
endPos = ( int ) ( stell( stream ) + certSequenceLength );
/* We've finally reached the certificate(s), read the collection of certs
into cert objects. We allow for a bit of slop for software which gets
the length encoding wrong by a few bytes */
while( !certSequenceLength || \
stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
{
CRYPT_CERTIFICATE iNewCert;
/* Make sure we don't overflow the chain */
if( certChainEnd >= MAX_CHAINLENGTH )
{
freeCertChain( iCertChain, certChainEnd );
return( CRYPT_ERROR_OVERFLOW );
}
/* If it's an SSL cert chain, there's a 24-bit length field between
certs */
if( type == CRYPT_CERTTYPE_SSL_CERTCHAIN )
sSkip( stream, 3 );
/* Read the next cert and add it to the chain. When importing the
chain from an external (untrusted) source we create standard certs
so we can check the signatures on each link in the chain. When
importing from a trusted source we create data-only certs, once
we've got all the certs and know which cert is the leaf, we can
go back and decode the public key information for it */
status = importCert( sMemBufPtr( stream ), sMemDataLeft( stream ),
&iNewCert, cryptOwner, CRYPT_KEYID_NONE,
NULL, 0, dataOnlyCert ? \
CERTFORMAT_DATAONLY : CERTFORMAT_NORMAL );
if( !cryptStatusError( status ) )
{
iCertChain[ certChainEnd++ ] = iNewCert;
status = sSkip( stream, status );
}
if( cryptStatusError( status ) )
{
freeCertChain( iCertChain, certChainEnd );
return( status );
}
/* If it's encoded using the indefinite form and we find the EOC
octets, exit */
if( !certSequenceLength && checkEOC( stream ) )
break;
}
/* Build the complete chain from the individual certs */
return( buildCertChain( iCryptCert, iCertChain, certChainEnd,
keyIDtype, keyID, keyIDlength ) );
}
/* Fetch a sequence of certs from an object to create a cert chain */
int assembleCertChain( CRYPT_CERTIFICATE *iCertificate,
const CRYPT_HANDLE iCertSource,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const int options )
{
CRYPT_CERTIFICATE iCertChain[ MAX_CHAINLENGTH ], lastCert;
MESSAGE_KEYMGMT_INFO getnextcertInfo;
const int chainOptions = options & KEYMGMT_FLAG_DATAONLY_CERT;
int stateInfo = CRYPT_ERROR, certChainEnd = 1, status;
/* Get the initial cert based on the key ID */
setMessageKeymgmtInfo( &getnextcertInfo, keyIDtype, keyID, keyIDlength,
&stateInfo, sizeof( int ),
options & KEYMGMT_MASK_CERTOPTIONS );
status = krnlSendMessage( iCertSource, RESOURCE_IMESSAGE_KEY_GETFIRSTCERT,
&getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );
if( cryptStatusError( status ) )
return( status );
iCertChain[ 0 ] = lastCert = getnextcertInfo.cryptHandle;
/* Fetch subsequent certs which make up the chain based on the state
information. Since the basic options apply only to the leaf cert,
we only allow the data-only-cert flag at this point */
setMessageKeymgmtInfo( &getnextcertInfo, CRYPT_KEYID_NONE, NULL, 0,
&stateInfo, sizeof( int ), chainOptions );
do
{
int selfSigned;
/* If we've reached a self-signed cert, stop */
krnlSendMessage( lastCert, RESOURCE_IMESSAGE_GETATTRIBUTE,
&selfSigned, CRYPT_CERTINFO_SELFSIGNED );
if( selfSigned )
break;
/* Get the next cert in the chain from the source, import it, and
add it to the collection */
getnextcertInfo.cryptHandle = CRYPT_ERROR; /* Reset result handle */
status = krnlSendMessage( iCertSource, RESOURCE_IMESSAGE_KEY_GETNEXTCERT,
&getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );
if( cryptStatusOK( status ) )
{
if( certChainEnd >= MAX_CHAINLENGTH )
status = CRYPT_ERROR_OVERFLOW;
else
iCertChain[ certChainEnd++ ] = \
lastCert = getnextcertInfo.cryptHandle;
}
if( status == CRYPT_ERROR_NOTFOUND )
{
status = CRYPT_OK;
break; /* End of chain reached */
}
}
while( cryptStatusOK( status ) );
if( cryptStatusError( status ) )
{
freeCertChain( iCertChain, certChainEnd );
return( status );
}
/* Build the complete chain from the individual certs */
return( buildCertChain( iCertificate, iCertChain, certChainEnd,
CRYPT_KEYID_NONE, NULL, 0 ) );
}
/****************************************************************************
* *
* Write Certificate-bagging Records *
* *
****************************************************************************/
/* Determine the size of and write a sequence of certificates from a base
cert up to the root */
static int sizeofCertSequence( const CERT_INFO *certInfoPtr )
{
int length = certInfoPtr->certificateSize, i;
/* Evaluate the size of the issuer certificates in the chain */
for( i = 0; i < certInfoPtr->certChainEnd; i++ )
{
CERT_INFO *certChainPtr;
getCheckInternalResource( certInfoPtr->certChain[ i ], certChainPtr,
OBJECT_TYPE_CERTIFICATE );
length += certChainPtr->certificateSize;
unlockResource( certChainPtr );
}
return( length );
}
static int writeCertSequence( STREAM *stream, const CERT_INFO *certInfoPtr )
{
int i, status;
/* Write the current certificate and the associated cert chain up to the
root */
swrite( stream, certInfoPtr->certificate, certInfoPtr->certificateSize );
for( i = 0; i < certInfoPtr->certChainEnd; i++ )
{
CERT_INFO *certChainPtr;
getCheckInternalResource( certInfoPtr->certChain[ i ], certChainPtr,
OBJECT_TYPE_CERTIFICATE );
status = swrite( stream, certChainPtr->certificate,
certChainPtr->certificateSize );
unlockResource( certChainPtr );
}
return( status );
}
/* Write certificate chain/sequence information:
CertChain ::= SEQUENCE {
contentType OBJECT IDENTIFIER, -- signedData
content [ 0 ] EXPLICIT SEQUENCE {
version INTEGER (1),
digestAlgorithms SET OF AlgorithmIdentifier, -- SIZE(0)
contentInfo SEQUENCE {
signedData OBJECT IDENTIFIER -- data
}
certificates [ 0 ] IMPLICIT SET OF {
Certificate
}
}
signerInfos SET OF SignerInfo -- SIZE(0)
} */
int sizeofCertSet( const CERT_INFO *certInfoPtr )
{
return( ( int ) sizeofObject( sizeofCertSequence( certInfoPtr ) ) );
}
int writeCertSet( STREAM *stream, const CERT_INFO *certInfoPtr )
{
writeConstructed( stream, sizeofCertSequence( certInfoPtr ), 0 );
return( writeCertSequence( stream, certInfoPtr ) );
}
int writeCertChain( STREAM *stream, const CERT_INFO *certInfoPtr )
{
int innerLength;
/* Determine how big the encoded cert chain/sequence will be */
innerLength = sizeofShortInteger( 1 ) + ( int ) sizeofObject( 0 ) + \
( int ) sizeofObject( sizeofOID( OID_CMS_DATA ) ) + \
( int ) sizeofObject( sizeofCertSequence( certInfoPtr ) ) + \
( int ) sizeofObject( 0 );
/* Write the outer SEQUENCE wrapper and contentType and content wrapper */
writeSequence( stream,
sizeofOID( OID_CMS_SIGNEDDATA ) + \
( int ) sizeofObject( sizeofObject( innerLength ) ) );
swrite( stream, OID_CMS_SIGNEDDATA, sizeofOID( OID_CMS_SIGNEDDATA ) );
writeConstructed( stream, sizeofObject( innerLength ), 0 );
writeSequence( stream, innerLength );
/* Write the inner content */
writeShortInteger( stream, 1, DEFAULT_TAG );
writeSet( stream, 0 );
writeSequence( stream, sizeofOID( OID_CMS_DATA ) );
swrite( stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );
writeCertSet( stream, certInfoPtr );
return( writeSet( stream, 0 ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -