📄 pkcs15_get.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #15 Get-item Routines *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "pkcs15.h"
#include "asn1.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/pkcs15.h"
#include "misc/asn1.h"
#endif /* Compiler-specific includes */
#ifdef USE_PKCS15
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Set any optional attributes that may be associated with a key */
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int setKeyAttributes( IN_HANDLE const CRYPT_HANDLE iCryptHandle,
INOUT const PKCS15_INFO *pkcs15infoPtr,
IN_FLAGS_Z( ACTION_PERM ) const int actionFlags )
{
int status;
assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
REQUIRES( isHandleRangeValid( iCryptHandle ) );
REQUIRES( actionFlags >= ACTION_PERM_FLAG_NONE && \
actionFlags < ACTION_PERM_FLAG_MAX );
/* This check is a bit odd because normally an action flag
value of ACTION_PERM_FLAG_NONE would indicate that the
object can't be used, but setting it to CRYPT_UNUSED would
create a value outside the normal allowed range so we use
_NONE to indicate a don't-care value */
if( actionFlags != 0 )
{
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
return( status );
}
if( pkcs15infoPtr->openPGPKeyIDlength > 0 )
{
MESSAGE_DATA msgData;
setMessageData( &msgData, ( void * ) pkcs15infoPtr->openPGPKeyID,
pkcs15infoPtr->openPGPKeyIDlength );
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
if( cryptStatusError( status ) )
return( status );
}
if( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )
{
MESSAGE_DATA msgData;
/* This isn't really used for anything but is required to generate
the OpenPGP keyID, which includes the key creation time in the
ID-generation process */
setMessageData( &msgData, ( void * ) &pkcs15infoPtr->validFrom,
sizeof( time_t ) );
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_PGPVALIDITY );
if( cryptStatusError( status ) )
return( status );
}
return( CRYPT_OK );
}
/* Get an encoded trusted certificate */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
static int getTrustedCert( IN_ARRAY( noPkcs15objects ) \
const PKCS15_INFO *pkcs15info,
IN_LENGTH_SHORT const int noPkcs15objects,
OUT_BUFFER( dataMaxLength, *dataLength ) void *data,
IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength,
OUT_LENGTH_SHORT_Z int *dataLength,
const BOOLEAN resetCertIndex )
{
static int trustedCertIndex;
const PKCS15_INFO *pkcs15infoPtr;
int certStartOffset, certDataTotalSize;
assert( isReadPtr( pkcs15info, \
sizeof( PKCS15_INFO ) * noPkcs15objects ) );
assert( isWritePtr( data, dataMaxLength ) );
assert( isWritePtr( dataLength, sizeof( int ) ) );
REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
REQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );
/* Clear return values */
memset( data, 0, min( 16, dataMaxLength ) );
*dataLength = 0;
/* If this is the first certificate, reset the index value. This is
pretty ugly since this sort of state-information value should be
stored with the caller, however there's no way to pass this back and
forth in a MESSAGE_DATA without resorting to an even uglier hack and
it's safe since this attribute is only ever read by the init thread
when it reads the configuration data at startup */
if( resetCertIndex )
trustedCertIndex = 0;
else
{
/* Move on to the next certificate */
if( trustedCertIndex >= noPkcs15objects - 1 )
return( CRYPT_ERROR_NOTFOUND );
trustedCertIndex++;
}
/* Find the next trusted certificate */
for( pkcs15infoPtr = NULL;
trustedCertIndex < noPkcs15objects && \
trustedCertIndex < FAILSAFE_ITERATIONS_MED; trustedCertIndex++ )
{
if( pkcs15info[ trustedCertIndex ].implicitTrust )
{
pkcs15infoPtr = &pkcs15info[ trustedCertIndex ];
break;
}
}
ENSURES( trustedCertIndex < FAILSAFE_ITERATIONS_MED );
if( pkcs15infoPtr == NULL )
return( CRYPT_ERROR_NOTFOUND );
certStartOffset = pkcs15infoPtr->certOffset;
certDataTotalSize = pkcs15infoPtr->certDataSize;
/* Return the data to the caller */
REQUIRES( rangeCheck( certStartOffset,
certDataTotalSize - certStartOffset,
certDataTotalSize ) );
return( attributeCopyParams( data, dataMaxLength, dataLength,
( BYTE * ) pkcs15infoPtr->certData + certStartOffset,
certDataTotalSize - certStartOffset ) );
}
/* Get an encoded configuration item */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
static int getConfigItem( IN_ARRAY( noPkcs15objects ) \
const PKCS15_INFO *pkcs15info,
IN_LENGTH_SHORT const int noPkcs15objects,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE dataType,
OUT_BUFFER_OPT( dataMaxLength, *dataLength ) void *data,
IN_LENGTH_SHORT_Z const int dataMaxLength,
OUT_LENGTH_SHORT_Z int *dataLength )
{
const PKCS15_INFO *pkcs15infoPtr;
int dataStartOffset, dataTotalSize, i;
assert( isReadPtr( pkcs15info, \
sizeof( PKCS15_INFO ) * noPkcs15objects ) );
assert( ( data == NULL && dataMaxLength == 0 ) || \
isWritePtr( data, dataMaxLength ) );
assert( isWritePtr( dataLength, sizeof( int ) ) );
REQUIRES( noPkcs15objects > 0 && noPkcs15objects < MAX_INTLENGTH_SHORT );
REQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
dataType == CRYPT_IATTRIBUTE_USERINDEX || \
dataType == CRYPT_IATTRIBUTE_USERINFO );
REQUIRES( ( data == NULL && dataMaxLength == 0 ) || \
( data != NULL && \
dataMaxLength >= 16 && \
dataMaxLength < MAX_INTLENGTH_SHORT ) );
/* Clear return values */
*dataLength = 0;
if( data != NULL )
memset( data, 0, min( 16, dataMaxLength ) );
/* Find the particular data type that we're looking for */
for( pkcs15infoPtr = NULL, i = 0;
i < noPkcs15objects && i < FAILSAFE_ITERATIONS_MED; i++ )
{
if( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_DATA && \
pkcs15info[ i ].dataType == dataType ) )
{
pkcs15infoPtr = &pkcs15info[ i ];
break;
}
}
ENSURES( i < FAILSAFE_ITERATIONS_MED );
if( pkcs15infoPtr == NULL )
return( CRYPT_ERROR_NOTFOUND );
dataStartOffset = pkcs15infoPtr->dataOffset;
dataTotalSize = pkcs15infoPtr->dataDataSize;
/* If it's just a length check, we're done */
if( data == NULL )
{
*dataLength = dataTotalSize - dataStartOffset;
return( CRYPT_OK );
}
/* Return the data to the caller */
REQUIRES( rangeCheck( dataStartOffset,
dataTotalSize - dataStartOffset,
dataTotalSize ) );
return( attributeCopyParams( data, dataMaxLength, dataLength,
( BYTE * ) pkcs15infoPtr->dataData + dataStartOffset,
dataTotalSize - dataStartOffset ) );
}
/****************************************************************************
* *
* Get a Key *
* *
****************************************************************************/
/* Read key data from a PKCS #15 collection */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
static int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,
OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,
IN_ENUM( KEYMGMT_ITEM ) \
const KEYMGMT_ITEM_TYPE itemType,
IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
IN_BUFFER( keyIDlength ) const void *keyID,
IN_LENGTH_KEYID const int keyIDlength,
IN_OPT void *auxInfo,
INOUT_OPT int *auxInfoLength,
IN_FLAGS_Z( KEYMGMT ) const int flags )
{
CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
CRYPT_CONTEXT iCryptContext;
const PKCS15_INFO *pkcs15infoPtr;
MESSAGE_DATA msgData;
const BOOLEAN publicComponentsOnly = \
( itemType != KEYMGMT_ITEM_PRIVATEKEY ) ? TRUE : FALSE;
const int auxInfoMaxLength = *auxInfoLength;
int pubkeyActionFlags = 0, privkeyActionFlags = 0, status;
assert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );
assert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );
assert( isReadPtr( keyID, keyIDlength ) );
assert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \
isReadPtr( auxInfo, auxInfoMaxLength ) );
REQUIRES( keysetInfoPtr->type == KEYSET_FILE && \
keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
REQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_URI || \
keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_PGPKEYID || \
keyIDtype == CRYPT_IKEYID_ISSUERID );
REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
keyIDlength < MAX_ATTRIBUTE_SIZE );
REQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \
( auxInfo != NULL && \
*auxInfoLength > 0 && \
*auxInfoLength < MAX_INTLENGTH_SHORT ) );
REQUIRES( flags >= KEYMGMT_FLAG_NONE && flags < KEYMGMT_FLAG_MAX );
/* Clear return values */
*iCryptHandle = CRYPT_ERROR;
/* Locate the appropriate object in the PKCS #15 collection and make
sure that the components that we need are present: Either a public
key or a certificate for any type of read, and a private key as well
for a private-key read */
pkcs15infoPtr = findEntry( keysetInfoPtr->keyData,
keysetInfoPtr->keyDataNoObjects, keyIDtype,
keyID, keyIDlength, flags );
if( pkcs15infoPtr == NULL )
{
retExt( CRYPT_ERROR_NOTFOUND,
( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO,
"No information present for this ID" ) );
}
if( pkcs15infoPtr->pubKeyData == NULL && \
pkcs15infoPtr->certData == NULL )
{
/* There's not enough information present to get a public key or the
public portions of a private key */
retExt( CRYPT_ERROR_NOTFOUND,
( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO,
"No public key or certificate data present for this ID" ) );
}
if( !publicComponentsOnly && pkcs15infoPtr->privKeyData == NULL )
{
/* There's not enough information present to get a private key */
retExt( CRYPT_ERROR_NOTFOUND,
( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO,
"No private key data present for this ID" ) );
}
/* If we're just checking whether an object exists, return now. If all
that we want is the key label, copy it back to the caller and exit */
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
return( CRYPT_OK );
if( flags & KEYMGMT_FLAG_LABEL_ONLY )
{
return( attributeCopyParams( auxInfo, auxInfoMaxLength,
auxInfoLength, pkcs15infoPtr->label,
pkcs15infoPtr->labelLength ) );
}
/* If we're reading the private key, make sure that the user has
supplied a password. This is checked by the kernel but we perform
another check here just to be safe*/
if( !publicComponentsOnly && auxInfo == NULL )
return( CRYPT_ERROR_WRONGKEY );
/* Read the public components */
status = readPublicKeyComponents( pkcs15infoPtr, keysetInfoPtr->objectHandle,
keyIDtype, keyID, keyIDlength,
publicComponentsOnly,
&iCryptContext, &iDataCert,
&pubkeyActionFlags,
&privkeyActionFlags, KEYSET_ERRINFO );
if( cryptStatusError( status ) )
return( status );
/* If we're only interested in the public components, set the key
permissions and exit */
if( publicComponentsOnly )
{
status = setKeyAttributes( iCryptContext, pkcs15infoPtr,
( pkcs15infoPtr->pubKeyData != NULL ) ? \
pubkeyActionFlags : 0 );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
retExt( status,
( status, KEYSET_ERRINFO,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -