📄 certio.c
字号:
if( !memcmp( oid, OID_CMS_SIGNEDDATA, oidLength ) )
isCertChain = TRUE;
else
if( !memcmp( oid, OID_X509_USERCERTIFICATE, oidLength ) )
{
/* Oddball wrapper type, set the payload offset to point to
the certificate and indicate no wrapper present */
*offset = ( int ) stell( stream );
status = readSequence( stream, NULL );
return( cryptStatusError( status ) ? \
status : CRYPT_CERTTYPE_NONE );
}
else
if( memcmp( oid, OID_NS_CERTSEQ, oidLength ) )
return( CRYPT_ERROR_BADDATA );
readConstructed( stream, NULL, 0 );
status = readSequence( stream, NULL );
if( cryptStatusError( status ) )
return( status );
/* If it's a PKCS #7 certificate chain, burrow into the inner PKCS #7
content */
if( isCertChain )
{
long integer;
/* Read the version number (1 = PKCS #7 v1.5, 2 = PKCS #7 v1.6,
3 = S/MIME with attribute certificate(s)) and SET OF
DigestAlgorithmIdentifier (this is empty for a pure cert chain,
nonempty for signed data) */
status = readShortInteger( stream, &integer );
if( cryptStatusOK( status ) && ( integer < 1 || integer > 3 ) )
status = CRYPT_ERROR_BADDATA;
if( cryptStatusOK( status ) )
status = readSet( stream, &value );
if( cryptStatusError( status ) )
return( status );
if( value )
sSkip( stream, value );
/* 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 );
readConstructed( stream, NULL, 0 );
}
/* We've finally reached the certificate(s), retry the read of the
certificate start */
status = readSequence( stream, NULL );
return( cryptStatusError( status ) ? status : CRYPT_CERTTYPE_CERTCHAIN );
}
static int getCertObjectInfo( const void *object, const int objectTotalLength,
int *objectOffset, int *objectLength,
CRYPT_CERTTYPE_TYPE *objectType,
const CERTFORMAT_TYPE formatType )
{
STREAM stream;
CRYPT_CERTTYPE_TYPE wrapperType = CRYPT_CERTTYPE_NONE;
CRYPT_CERTTYPE_TYPE type = CRYPT_CERTTYPE_NONE;
int tag, length, status;
/* Set initial default values */
*objectOffset = 0;
*objectLength = CRYPT_ERROR;
*objectType = CRYPT_ERROR;
sMemConnect( &stream, object, objectTotalLength );
/* If it's an SSL cert chain there's no recognisable tagging, however the
caller will have told us what it is */
if( formatType == CERTFORMAT_SSLCHAIN )
{
BYTE *objectPtr = ( void * ) object;
*objectLength = objectTotalLength;
*objectType = CRYPT_CERTTYPE_SSL_CERTCHAIN;
return( CRYPT_OK );
}
/* First we check for the easy ones, CMS attributes or a CMS cert chain,
both of which begin with a [0] IMPLICIT SET */
if( peekTag( &stream ) == MAKE_CTAG( 0 ) || \
formatType == CERTFORMAT_CERTSET )
{
*objectLength = objectTotalLength;
*objectType = ( formatType == CERTFORMAT_CERTSET ) ? \
CRYPT_CERTTYPE_CMS_CERTSET : CRYPT_CERTTYPE_CMS_ATTRIBUTES;
return( CRYPT_OK );
}
/* Check that the start of the object is in order and gets its length */
status = readSequence( &stream, &length );
if( cryptStatusOK( status ) && !length )
status = getObjectLength( object, objectTotalLength );
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
*objectLength = length ? ( int ) sizeofObject( length ) : status;
/* If it's a PKCS #7 certificate chain or Netscape cert.sequence,
there'll be an object identifier present. Some sources also wrap
certs up in oddball OID's, so we check for these as well */
if( peekTag( &stream ) == BER_OBJECT_IDENTIFIER )
{
status = decodeCertWrapper( &stream, objectOffset );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
*objectType = ( status != CRYPT_CERTTYPE_NONE ) ? \
status : CRYPT_CERTTYPE_CERTIFICATE;
return( CRYPT_OK );
}
/* If it's a PKCS #12 mess, there'll be a version number, 3, present */
if( peekTag( &stream ) == BER_INTEGER )
{
long value;
int offset;
/* Strip off the amazing number of layers of bloat which PKCS #12
lards a certificate with */
status = readShortInteger( &stream, &value );
if( cryptStatusError( status ) || value != 3 )
return( CRYPT_ERROR_BADDATA );
readSequence( &stream, NULL );
readOID( &stream, OID_CMS_DATA );
readConstructed( &stream, NULL, 0 );
readOctetStringHole( &stream, NULL, DEFAULT_TAG );
readSequence( &stream, NULL );
readSequence( &stream, NULL );
readOID( &stream, OID_CMS_DATA );
readConstructed( &stream, NULL, 0 );
readOctetStringHole( &stream, NULL, DEFAULT_TAG );
readSequence( &stream, NULL );
readSequence( &stream, NULL );
readOID( &stream,
MKOID( "\x06\x0B\x2A\x86\x48\x86\xF7\x0D\x01\x0C\x0A\x01\x03" ) );
readConstructed( &stream, NULL, 0 );
readSequence( &stream, NULL );
readOID( &stream,
MKOID( "\x06\x0A\x2A\x86\x48\x86\xF7\x0D\x01\x09\x16\x01" ) );
readConstructed( &stream, NULL, 0 );
readOctetStringHole( &stream, &length, DEFAULT_TAG );
offset = ( int ) stell( &stream ); /* Certificate start */
readSequence( &stream, NULL );
status = readSequence( &stream, NULL );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
return( status );
}
/* We've finally reached the cert, record its offset and length */
*objectOffset = offset;
*objectLength = length;
*objectType = CRYPT_CERTTYPE_CERTIFICATE;
return( CRYPT_OK );
}
/* Read the inner sequence and skip optional tagged fields and the
INTEGER value */
readSequence( &stream, &length );
if( peekTag( &stream ) == MAKE_CTAG( 0 ) )
readUniversal( &stream );
if( peekTag( &stream ) == MAKE_CTAG( 1 ) )
readUniversal( &stream );
if( peekTag( &stream ) == MAKE_CTAG( 2 ) )
readUniversal( &stream );
if( peekTag( &stream ) == BER_INTEGER )
readUniversal( &stream );
status = sGetStatus( &stream );
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
if( length == 0 )
{
/* PKI user object with absent (non-specified) DN */
sMemDisconnect( &stream );
*objectType = CRYPT_CERTTYPE_PKIUSER;
return( CRYPT_OK );
}
/* If we've hit a [1] it's an attribute cert, if we've hit a
GeneralizedTime it's an OCSP response, if we've hit a SET it's PKI
user info, and if we've hit a [0] or [1] primitive tag (implicitly
tagged INTEGER) or [3]...[9] it's a CRMF revocation request */
tag = peekTag( &stream );
if( tag == MAKE_CTAG( 1 ) || tag == BER_TIME_GENERALIZED || \
tag == BER_SET )
{
sMemDisconnect( &stream );
*objectType = \
( tag == MAKE_CTAG( 1 ) ) ? CRYPT_CERTTYPE_ATTRIBUTE_CERT : \
( tag == BER_TIME_GENERALIZED ) ? \
CRYPT_CERTTYPE_OCSP_RESPONSE : CRYPT_CERTTYPE_PKIUSER;
return( CRYPT_OK );
}
if( tag == MAKE_CTAG_PRIMITIVE( 0 ) || \
tag == MAKE_CTAG_PRIMITIVE( 1 ) || \
( tag >= MAKE_CTAG( 3 ) && tag <= MAKE_CTAG( 9 ) ) )
{
sMemDisconnect( &stream );
*objectType = CRYPT_CERTTYPE_REQUEST_REVOCATION;
return( CRYPT_OK );
}
/* Read the next SEQUENCE. If it's followed by an OID, it's the
AlgorithmIdentifier in a cert or CRL. If it's followed by a SET, it's
the Name in a cert request or attribute cert. If it's followed by a
tag in the range [0]...[9] it's a horror from CRMF */
readSequence( &stream, &length );
tag = peekTag( &stream );
if( tag == BER_OBJECT_IDENTIFIER )
{
/* Skip the AlgorithmIdentifier data and the following Name. For a
cert we now have a SEQUENCE (from the Validity), for a CRL a
UTCTime or GeneralizedTime */
sSkip( &stream, length );
readUniversal( &stream );
tag = readTag( &stream );
sMemDisconnect( &stream );
if( tag == BER_SEQUENCE )
{
*objectType = CRYPT_CERTTYPE_CERTIFICATE;
return( CRYPT_OK );
}
if( tag == BER_TIME_UTC || tag == BER_TIME_GENERALIZED )
{
*objectType = CRYPT_CERTTYPE_CRL;
return( CRYPT_OK );
}
return( CRYPT_ERROR_BADDATA );
}
if( tag >= MAKE_CTAG( 0 ) && tag <= MAKE_CTAG( 9 ) )
{
/* Cert requests and revocation requests have the same format,
however revocation requests should have the cert serial number
present while cert requests shouldn't (at least in any normal
implementation), so we use this to distinguish the two. If
this ever fails in the future, we can also look for things like
[6] (the public key) as a clue that it's a cert request */
sMemDisconnect( &stream );
*objectType = ( tag == MAKE_CTAG( 1 ) ) ? \
CRYPT_CERTTYPE_REQUEST_REVOCATION : CRYPT_CERTTYPE_REQUEST_CERT;
return( CRYPT_OK );
}
if( tag == BER_SET )
{
sSkip( &stream, length );
readSequence( &stream, NULL );
tag = readTag( &stream );
sMemDisconnect( &stream );
if( tag == BER_OBJECT_IDENTIFIER )
{
*objectType = CRYPT_CERTTYPE_ATTRIBUTE_CERT;
return( CRYPT_OK );
}
if( tag == BER_SEQUENCE )
{
*objectType = CRYPT_CERTTYPE_CERTREQUEST;
return( CRYPT_OK );
}
return( CRYPT_ERROR_BADDATA );
}
/* Read the next SEQUENCE. If it's followed by a yet another SEQUENCE
or a tag from [0] ... [3] it's an OCSP request */
readSequence( &stream, &length );
tag = peekTag( &stream );
if( tag == BER_SEQUENCE || \
( tag >= MAKE_CTAG( 0 ) && tag <= MAKE_CTAG( 3 ) ) )
{
sMemDisconnect( &stream );
*objectType = CRYPT_CERTTYPE_OCSP_REQUEST;
return( CRYPT_OK );
}
/* It's nothing identifiable */
sMemDisconnect( &stream );
return( CRYPT_ERROR_BADDATA );
}
/****************************************************************************
* *
* Import/Export Functions *
* *
****************************************************************************/
/* Import a certificate object. If the import type is set to create a data-
only cert, its publicKeyInfo pointer is set to the start of the encoded
public key to allow it to be decoded later. Returns the length of the
certificate */
int importCert( const void *certObject, const int certObjectLength,
CRYPT_CERTIFICATE *certificate,
const CRYPT_USER cryptOwner,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const CERTFORMAT_TYPE formatType )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -