📄 pkcs15.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #15 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 */
/* Each PKCS #15 file can contain information for multiple personalities
(although it's extremely unlikely to contain more than one or two), we
allow a maximum of MAX_PKCS15_OBJECTS per file in order to discourage
them from being used as general-purpose public-key keysets, which they're
not supposed to be. A setting of 16 objects consumes ~2K of memory
(16 x ~128) and seems like a sensible upper bound so we choose that as
the limit */
#ifdef CONFIG_CONSERVE_MEMORY
#define MAX_PKCS15_OBJECTS 8
#else
#define MAX_PKCS15_OBJECTS 16
#endif /* CONFIG_CONSERVE_MEMORY */
#ifdef USE_PKCS15
/* OID information used to read a PKCS #15 file */
static const CMS_CONTENT_INFO FAR_BSS oidInfoPkcs15Data = { 0, 0 };
static const OID_INFO FAR_BSS keyFileOIDinfo[] = {
{ OID_PKCS15_CONTENTTYPE, CRYPT_OK, &oidInfoPkcs15Data },
{ NULL, 0 }, { NULL, 0 }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Get the hash of various certificate name fields */
CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \
int getCertID( IN_HANDLE const CRYPT_HANDLE iCryptHandle,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE nameType,
OUT_BUFFER( nameIdMaxLen, *nameIdLen ) BYTE *nameID,
IN_LENGTH_SHORT_MIN( KEYID_SIZE ) const int nameIdMaxLen,
OUT_LENGTH_SHORT_Z int *nameIdLen )
{
HASHFUNCTION_ATOMIC hashFunctionAtomic;
DYNBUF idDB;
int status;
assert( isWritePtr( nameID, nameIdMaxLen ) );
assert( isWritePtr( nameIdLen, sizeof( int ) ) );
REQUIRES( isHandleRangeValid( iCryptHandle ) );
REQUIRES( nameType == CRYPT_IATTRIBUTE_SPKI || \
nameType == CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER || \
nameType == CRYPT_IATTRIBUTE_SUBJECT || \
nameType == CRYPT_IATTRIBUTE_ISSUER );
REQUIRES( nameIdMaxLen >= KEYID_SIZE && \
nameIdMaxLen < MAX_INTLENGTH_SHORT );
/* Clear return value */
*nameIdLen = 0;
/* Get the attribute data and hash algorithm information and hash the
attribute to get the ID */
status = dynCreate( &idDB, iCryptHandle, nameType );
if( cryptStatusError( status ) )
return( status );
getHashAtomicParameters( CRYPT_ALGO_SHA1, &hashFunctionAtomic, NULL );
hashFunctionAtomic( nameID, nameIdMaxLen, dynData( idDB ),
dynLength( idDB ) );
dynDestroy( &idDB );
*nameIdLen = nameIdMaxLen;
return( CRYPT_OK );
}
/* Locate an object based on an ID */
#define matchID( src, srcLen, dest, destLen ) \
( ( srcLen ) > 0 && ( srcLen ) == ( destLen ) && \
!memcmp( ( src ), ( dest ), ( destLen ) ) )
CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
PKCS15_INFO *findEntry( IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info,
IN_LENGTH_SHORT const int noPkcs15objects,
IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
IN_BUFFER_OPT( keyIDlength ) const void *keyID,
IN_LENGTH_KEYID_Z const int keyIDlength,
IN_FLAGS_Z( KEYMGMT ) const int requestedUsage )
{
int i;
assert( isReadPtr( pkcs15info, \
sizeof( PKCS15_INFO ) * noPkcs15objects ) );
assert( ( keyID == NULL && keyIDlength == 0 ) || \
isReadPtr( keyID, keyIDlength ) );
REQUIRES_N( noPkcs15objects >= 1 && \
noPkcs15objects < MAX_INTLENGTH_SHORT );
REQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_URI || \
keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_PGPKEYID || \
keyIDtype == CRYPT_IKEYID_ISSUERID || \
keyIDtype == CRYPT_KEYIDEX_ID || \
keyIDtype == CRYPT_KEYIDEX_SUBJECTNAMEID );
REQUIRES_N( ( keyID == NULL && keyIDlength == 0 ) || \
( keyID != NULL && \
keyIDlength >= MIN_NAME_LENGTH && \
keyIDlength < MAX_ATTRIBUTE_SIZE ) );
REQUIRES_N( requestedUsage >= KEYMGMT_FLAG_NONE && \
requestedUsage < KEYMGMT_FLAG_MAX );
REQUIRES_N( ( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
/* If there's no ID to search on, don't try and do anything. This can
occur when we're trying to build a chain and the necessary chaining
data isn't present */
if( keyID == NULL || keyIDlength <= 0 )
return( NULL );
/* Try and locate the appropriate object in the PKCS #15 collection */
for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
{
const PKCS15_INFO *pkcs15infoPtr = &pkcs15info[ i ];
const int compositeUsage = pkcs15infoPtr->pubKeyUsage | \
pkcs15infoPtr->privKeyUsage;
/* If there's no entry at this position, continue */
if( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )
continue;
/* If there's an explicit usage requested, make sure that the key
usage matches this. This can get slightly complex because the
advertised usage isn't necessarily the same as the usage
permitted by the associated certificate (PKCS #11 apps are
particularly good at setting bogus usage types) and the overall
result can be further influenced by trusted usage settings, so
all that we check for here is an indicated usage for the key
matching the requested usage */
if( ( requestedUsage & KEYMGMT_FLAG_USAGE_CRYPT ) && \
!( compositeUsage & ENCR_USAGE_MASK ) )
continue;
if( ( requestedUsage & KEYMGMT_FLAG_USAGE_SIGN ) && \
!( compositeUsage & SIGN_USAGE_MASK ) )
continue;
/* Check for a match based on the ID type */
switch( keyIDtype )
{
case CRYPT_KEYID_NAME:
case CRYPT_KEYID_URI:
if( matchID( pkcs15infoPtr->label, pkcs15infoPtr->labelLength,
keyID, keyIDlength ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
break;
case CRYPT_IKEYID_KEYID:
if( matchID( pkcs15infoPtr->keyID, pkcs15infoPtr->keyIDlength,
keyID, keyIDlength ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
break;
case CRYPT_IKEYID_PGPKEYID:
/* For the PGP keyID we compare both IDs for the reasons
given in the PGP keyset read code */
if( matchID( pkcs15infoPtr->pgp2KeyID,
pkcs15infoPtr->pgp2KeyIDlength, keyID,
keyIDlength ) || \
matchID( pkcs15infoPtr->openPGPKeyID,
pkcs15infoPtr->openPGPKeyIDlength, keyID,
keyIDlength ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
break;
case CRYPT_IKEYID_ISSUERID:
if( matchID( pkcs15infoPtr->iAndSID,
pkcs15infoPtr->iAndSIDlength, keyID,
keyIDlength ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
break;
case CRYPT_KEYIDEX_ID:
if( matchID( pkcs15infoPtr->iD, pkcs15infoPtr->iDlength,
keyID, keyIDlength ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
break;
case CRYPT_KEYIDEX_SUBJECTNAMEID:
if( matchID( pkcs15infoPtr->subjectNameID,
pkcs15infoPtr->subjectNameIDlength, keyID,
keyIDlength ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
break;
default:
retIntError_Null();
}
}
ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
/* If we're trying to match on the PGP key ID and didn't find anything,
retry it using the first PGP_KEYID_SIZE bytes of the object ID. This
is necessary because calculation of the OpenPGP ID requires the
presence of data that may not be present in non-PGP keys so we can't
calculate a real OpenPGP ID but have to use the next-best thing
(sol lucet omnibus) */
if( keyIDtype == CRYPT_IKEYID_PGPKEYID )
{
for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
{
const PKCS15_INFO *pkcs15infoPtr = &pkcs15info[ i ];
if( pkcs15infoPtr->type != PKCS15_SUBTYPE_NONE && \
pkcs15infoPtr->iDlength >= PGP_KEYID_SIZE && \
!memcmp( keyID, pkcs15infoPtr->iD, PGP_KEYID_SIZE ) )
return( ( PKCS15_INFO * ) pkcs15infoPtr );
}
ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
}
return( NULL );
}
/* Find a free PKCS #15 entry */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
PKCS15_INFO *findFreeEntry( IN_ARRAY( noPkcs15objects ) \
const PKCS15_INFO *pkcs15info,
IN_LENGTH_SHORT const int noPkcs15objects,
OUT_OPT_LENGTH_SHORT_Z int *index )
{
int i;
assert( isReadPtr( pkcs15info, \
sizeof( PKCS15_INFO ) * noPkcs15objects ) );
assert( ( index == NULL ) || isWritePtr( index, sizeof( int ) ) );
REQUIRES_N( noPkcs15objects >= 1 && \
noPkcs15objects < MAX_INTLENGTH_SHORT );
/* Clear return value */
if( index != NULL )
*index = CRYPT_ERROR;
for( i = 0; i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
{
if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
break;
}
ENSURES_N( i < FAILSAFE_ITERATIONS_MED );
if( i >= noPkcs15objects )
return( NULL );
if( index != NULL )
{
/* Remember the index value (used for enumerating PKCS #15 entries)
for this entry */
*index = i;
}
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
}
/* Free object entries */
STDC_NONNULL_ARG( ( 1 ) ) \
void pkcs15freeEntry( INOUT PKCS15_INFO *pkcs15info )
{
assert( isWritePtr( pkcs15info, sizeof( PKCS15_INFO ) ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -