📄 pkcs15_atrd.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #15 Attribute Read Routines *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "pkcs15.h"
#include "asn1.h"
#include "asn1_ext.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/pkcs15.h"
#include "misc/asn1.h"
#include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */
#ifdef USE_PKCS15
/* A macro to check that we're OK to read more data beyond this point */
#define canContinue( stream, status, endPos ) \
( cryptStatusOK( status ) && stell( stream ) < endPos )
/* OID information used to read a PKCS #15 file */
static const OID_INFO FAR_BSS dataObjectOIDinfo[] = {
{ OID_CRYPTLIB_CONTENTTYPE, TRUE },
{ WILDCARD_OID, FALSE },
{ NULL, 0 }, { NULL, 0 }
};
static const OID_INFO FAR_BSS cryptlibDataOIDinfo[] = {
{ OID_CRYPTLIB_CONFIGDATA, CRYPT_IATTRIBUTE_CONFIGDATA },
{ OID_CRYPTLIB_USERINDEX, CRYPT_IATTRIBUTE_USERINDEX },
{ OID_CRYPTLIB_USERINFO, CRYPT_IATTRIBUTE_USERINFO },
{ WILDCARD_OID, CRYPT_ATTRIBUTE_NONE },
{ NULL, 0 }, { NULL, 0 }
};
/* Permitted object subtypes. PKCS #15 uses context-specific tagging to
identify the subtypes within an object type so we store a list of
permitted tags for each object type */
typedef struct {
PKCS15_OBJECT_TYPE type; /* Object type */
int subTypes[ 5 ]; /* Subtype tags */
} ALLOWED_ATTRIBUTE_TYPES;
static const ALLOWED_ATTRIBUTE_TYPES allowedTypesTbl[] = {
{ PKCS15_OBJECT_PUBKEY,
{ BER_SEQUENCE, MAKE_CTAG( CTAG_PK_DH ), MAKE_CTAG( CTAG_PK_DSA ),
MAKE_CTAG( CTAG_PK_KEA ), CRYPT_ERROR } },
{ PKCS15_OBJECT_PRIVKEY,
{ BER_SEQUENCE, MAKE_CTAG( CTAG_PK_DH ), MAKE_CTAG( CTAG_PK_DSA ),
MAKE_CTAG( CTAG_PK_KEA ), CRYPT_ERROR } },
{ PKCS15_OBJECT_CERT,
{ BER_SEQUENCE, CRYPT_ERROR } },
{ PKCS15_OBJECT_DATA,
{ MAKE_CTAG( CTAG_DO_OIDDO ), CRYPT_ERROR } },
{ PKCS15_OBJECT_NONE, { CRYPT_ERROR } },
{ PKCS15_OBJECT_NONE, { CRYPT_ERROR } }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Read a sequence of PKCS #15 key identifiers */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readKeyIdentifiers( INOUT STREAM *stream,
INOUT PKCS15_INFO *pkcs15infoPtr,
IN_LENGTH const int endPos )
{
int iterationCount, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
REQUIRES( endPos > 0 && endPos > stell( stream ) && \
endPos < MAX_INTLENGTH );
for( status = CRYPT_OK, iterationCount = 0;
cryptStatusOK( status ) && stell( stream ) < endPos && \
iterationCount < FAILSAFE_ITERATIONS_MED; iterationCount++ )
{
long value;
int payloadLength;
/* Read each identifier type and copy the useful ones into the PKCS
#15 information */
readSequence( stream, &payloadLength );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
return( status );
switch( value )
{
case PKCS15_KEYID_ISSUERANDSERIALNUMBER:
{
HASHFUNCTION_ATOMIC hashFunctionAtomic;
void *iAndSPtr = DUMMY_INIT_PTR;
int iAndSLength, hashSize;
/* If we've already got the iAndSID, use that version
instead */
if( pkcs15infoPtr->iAndSIDlength > 0 )
{
status = readUniversal( stream );
continue;
}
/* Hash the full issuerAndSerialNumber to get an iAndSID */
getHashAtomicParameters( CRYPT_ALGO_SHA1,
&hashFunctionAtomic, &hashSize );
status = getStreamObjectLength( stream, &iAndSLength );
if( cryptStatusOK( status ) )
status = sMemGetDataBlock( stream, &iAndSPtr,
iAndSLength );
if( cryptStatusOK( status ) )
status = sSkip( stream, iAndSLength );
if( cryptStatusError( status ) )
return( status );
hashFunctionAtomic( pkcs15infoPtr->iAndSID, KEYID_SIZE,
iAndSPtr, iAndSLength );
pkcs15infoPtr->iAndSIDlength = hashSize;
break;
}
case PKCS15_KEYID_SUBJECTKEYIDENTIFIER:
status = readOctetString( stream, pkcs15infoPtr->keyID,
&pkcs15infoPtr->keyIDlength,
8, CRYPT_MAX_HASHSIZE );
break;
case PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH:
/* If we've already got the iAndSID by hashing the
issuerAndSerialNumber, use that version instead */
if( pkcs15infoPtr->iAndSIDlength > 0 )
{
status = readUniversal( stream );
continue;
}
status = readOctetString( stream, pkcs15infoPtr->iAndSID,
&pkcs15infoPtr->iAndSIDlength,
KEYID_SIZE, KEYID_SIZE );
break;
case PKCS15_KEYID_ISSUERNAMEHASH:
status = readOctetString( stream, pkcs15infoPtr->issuerNameID,
&pkcs15infoPtr->issuerNameIDlength,
KEYID_SIZE, KEYID_SIZE );
break;
case PKCS15_KEYID_SUBJECTNAMEHASH:
status = readOctetString( stream, pkcs15infoPtr->subjectNameID,
&pkcs15infoPtr->subjectNameIDlength,
KEYID_SIZE, KEYID_SIZE );
break;
case PKCS15_KEYID_PGP2:
status = readOctetString( stream, pkcs15infoPtr->pgp2KeyID,
&pkcs15infoPtr->pgp2KeyIDlength,
PGP_KEYID_SIZE, PGP_KEYID_SIZE );
break;
case PKCS15_KEYID_OPENPGP:
status = readOctetString( stream, pkcs15infoPtr->openPGPKeyID,
&pkcs15infoPtr->openPGPKeyIDlength,
PGP_KEYID_SIZE, PGP_KEYID_SIZE );
break;
default:
status = readUniversal( stream );
}
}
if( iterationCount >= FAILSAFE_ITERATIONS_MED )
{
/* This could be either an internal error or some seriously
malformed data, since we can't tell without human intervention
we throw a debug exception but otherwise treat it as bad data */
assert( DEBUG_WARN );
return( CRYPT_ERROR_BADDATA );
}
return( status );
}
/****************************************************************************
* *
* Read PKCS #15 Attributes *
* *
****************************************************************************/
/* Read public/private key attributes */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readPubkeyAttributes( INOUT STREAM *stream,
INOUT PKCS15_INFO *pkcs15infoPtr,
IN_LENGTH const int endPos,
const BOOLEAN isPubKeyObject )
{
int usageFlags, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
REQUIRES( endPos > 0 && endPos > stell( stream ) && \
endPos < MAX_INTLENGTH );
status = readBitString( stream, &usageFlags ); /* Usage flags */
if( canContinue( stream, status, endPos ) && /* Native flag */
peekTag( stream ) == BER_BOOLEAN )
status = readUniversal( stream );
if( canContinue( stream, status, endPos ) && /* Access flags */
peekTag( stream ) == BER_BITSTRING )
status = readUniversal( stream );
if( canContinue( stream, status, endPos ) && /* Key reference */
peekTag( stream ) == BER_INTEGER )
status = readUniversal( stream );
if( canContinue( stream, status, endPos ) && /* Start date */
peekTag( stream ) == BER_TIME_GENERALIZED )
status = readGeneralizedTime( stream, &pkcs15infoPtr->validFrom );
if( canContinue( stream, status, endPos ) && /* End date */
peekTag( stream ) == MAKE_CTAG( CTAG_KA_VALIDTO ) )
status = readGeneralizedTimeTag( stream, &pkcs15infoPtr->validTo,
CTAG_KA_VALIDTO );
if( cryptStatusError( status ) )
return( status );
if( isPubKeyObject )
pkcs15infoPtr->pubKeyUsage = usageFlags;
else
pkcs15infoPtr->privKeyUsage = usageFlags;
return( CRYPT_OK );
}
/* Read certificate attributes */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCertAttributes( INOUT STREAM *stream,
INOUT PKCS15_INFO *pkcs15infoPtr,
IN_LENGTH const int endPos )
{
int length, status = CRYPT_OK;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
REQUIRES( endPos > 0 && endPos > stell( stream ) && \
endPos < MAX_INTLENGTH );
if( peekTag( stream ) == BER_BOOLEAN ) /* Authority flag */
status = readUniversal( stream );
if( canContinue( stream, status, endPos ) && /* Identifier */
peekTag( stream ) == BER_SEQUENCE )
status = readUniversal( stream );
if( canContinue( stream, status, endPos ) && /* Thumbprint */
peekTag( stream ) == MAKE_CTAG( CTAG_CA_DUMMY ) )
status = readUniversal( stream );
if( canContinue( stream, status, endPos ) && /* Trusted usage */
peekTag( stream ) == MAKE_CTAG( CTAG_CA_TRUSTED_USAGE ) )
{
readConstructed( stream, NULL, CTAG_CA_TRUSTED_USAGE );
status = readBitString( stream, &pkcs15infoPtr->trustedUsage );
}
if( canContinue( stream, status, endPos ) && /* Identifiers */
peekTag( stream ) == MAKE_CTAG( CTAG_CA_IDENTIFIERS ) )
{
status = readConstructed( stream, &length, CTAG_CA_IDENTIFIERS );
if( cryptStatusOK( status ) )
status = readKeyIdentifiers( stream, pkcs15infoPtr,
stell( stream ) + length );
}
if( canContinue( stream, status, endPos ) && /* Implicitly trusted */
peekTag( stream ) == MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) )
status = readBooleanTag( stream, &pkcs15infoPtr->implicitTrust,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -