📄 keyload.c
字号:
/****************************************************************************
* *
* cryptlib Key Load Routines *
* Copyright Peter Gutmann 1992-2008 *
* *
****************************************************************************/
#define PKC_CONTEXT /* Indicate that we're working with PKC contexts */
#if defined( INC_ALL )
#include "crypt.h"
#include "context.h"
#else
#include "crypt.h"
#include "context/context.h"
#endif /* Compiler-specific includes */
/* The default size of the salt for PKCS #5v2 key derivation, needed when we
set the CRYPT_CTXINFO_KEYING_VALUE */
#define PKCS5_SALT_SIZE 8 /* 64 bits */
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Convert a key attribute type into a key format type */
CHECK_RETVAL \
int attributeToFormatType( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,
OUT_ENUM_OPT( KEYFORMAT ) KEYFORMAT_TYPE *keyformat )
{
static const MAP_TABLE attributeMapTbl[] = {
{ CRYPT_IATTRIBUTE_KEY_SSH, KEYFORMAT_SSH },
{ CRYPT_IATTRIBUTE_KEY_SSH1, KEYFORMAT_SSH1 },
{ CRYPT_IATTRIBUTE_KEY_SSL, KEYFORMAT_SSL },
{ CRYPT_IATTRIBUTE_KEY_PGP, KEYFORMAT_PGP },
{ CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL, KEYFORMAT_PGP },
{ CRYPT_IATTRIBUTE_KEY_SPKI, KEYFORMAT_CERT },
{ CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL, KEYFORMAT_CERT },
{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
};
int value, status;
assert( isWritePtr( keyformat, sizeof( KEYFORMAT_TYPE ) ) );
REQUIRES( isAttribute( attribute ) || \
isInternalAttribute( attribute ) );
/* Clear return value */
*keyformat = KEYFORMAT_NONE;
status = mapValue( attribute, &value, attributeMapTbl,
FAILSAFE_ARRAYSIZE( attributeMapTbl, MAP_TABLE ) );
ENSURES( cryptStatusOK( status ) );
*keyformat = value;
return( CRYPT_OK );
}
/****************************************************************************
* *
* Key Parameter Handling Functions *
* *
****************************************************************************/
/* Initialise key parameters such as the IV and encryption mode, shared by
most capabilities. This is never called directly, but is accessed
through function pointers in the capability lists */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int initKeyParams( INOUT CONTEXT_INFO *contextInfoPtr,
IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,
IN_OPT const void *data,
IN_INT const int dataLength )
{
CONV_INFO *convInfo = contextInfoPtr->ctxConv;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_CONV );
REQUIRES( paramType > KEYPARAM_NONE && paramType < KEYPARAM_LAST );
/* Set the en/decryption mode if required */
switch( paramType )
{
case KEYPARAM_MODE:
{
const CAPABILITY_INFO *capabilityInfoPtr = \
contextInfoPtr->capabilityInfo;
REQUIRES( data == NULL );
REQUIRES( dataLength > CRYPT_MODE_NONE && \
dataLength < CRYPT_MODE_LAST );
switch( dataLength )
{
case CRYPT_MODE_ECB:
contextInfoPtr->encryptFunction = \
capabilityInfoPtr->encryptFunction;
contextInfoPtr->decryptFunction = \
capabilityInfoPtr->decryptFunction;
break;
case CRYPT_MODE_CBC:
contextInfoPtr->encryptFunction = \
capabilityInfoPtr->encryptCBCFunction;
contextInfoPtr->decryptFunction = \
capabilityInfoPtr->decryptCBCFunction;
break;
case CRYPT_MODE_CFB:
contextInfoPtr->encryptFunction = \
capabilityInfoPtr->encryptCFBFunction;
contextInfoPtr->decryptFunction = \
capabilityInfoPtr->decryptCFBFunction;
break;
case CRYPT_MODE_OFB:
contextInfoPtr->encryptFunction = \
capabilityInfoPtr->encryptOFBFunction;
contextInfoPtr->decryptFunction = \
capabilityInfoPtr->decryptOFBFunction;
break;
default:
retIntError();
}
ENSURES( ( contextInfoPtr->encryptFunction == NULL && \
contextInfoPtr->decryptFunction == NULL ) || \
( contextInfoPtr->encryptFunction != NULL && \
contextInfoPtr->decryptFunction != NULL ) );
if( contextInfoPtr->encryptFunction == NULL || \
contextInfoPtr->decryptFunction == NULL )
{
setErrorInfo( contextInfoPtr, CRYPT_CTXINFO_MODE,
CRYPT_ERRTYPE_ATTR_PRESENT );
return( CRYPT_ERROR_NOTAVAIL );
}
convInfo->mode = dataLength;
return( CRYPT_OK );
}
case KEYPARAM_IV:
assert( isReadPtr( data, dataLength ) );
REQUIRES( data != NULL && \
dataLength >= 8 && dataLength <= CRYPT_MAX_IVSIZE );
/* Load an IV of the required length */
memcpy( convInfo->iv, data, dataLength );
convInfo->ivLength = dataLength;
convInfo->ivCount = 0;
memcpy( convInfo->currentIV, convInfo->iv, dataLength );
contextInfoPtr->flags |= CONTEXT_FLAG_IV_SET;
return( CRYPT_OK );
}
retIntError();
}
/* Trim a user-supplied key down to an appropriate size */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int adjustUserKeySize( const CONTEXT_INFO *contextInfoPtr,
IN_RANGE( MIN_KEYSIZE, \
CRYPT_MAX_PKCSIZE ) const int requestedKeySize,
OUT_LENGTH_PKC_Z int *keyLength )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isWritePtr( keyLength, sizeof( int ) ) );
REQUIRES( requestedKeySize >= MIN_KEYSIZE && \
requestedKeySize <= CRYPT_MAX_PKCSIZE );
/* Clear return value */
*keyLength = 0;
/* Trim the key to the appropriate size */
if( requestedKeySize < capabilityInfoPtr->minKeySize || \
requestedKeySize > capabilityInfoPtr->maxKeySize )
return( CRYPT_ARGERROR_NUM1 );
ENSURES( requestedKeySize > MIN_KEYSIZE && \
requestedKeySize <= CRYPT_MAX_PKCSIZE );
/* If it's a PKC key we're done */
if( contextInfoPtr->type == CONTEXT_PKC )
{
*keyLength = requestedKeySize;
return( CRYPT_OK );
}
/* For conventional/MAC keys we need to limit the maximum working key
length to a sane size since the other side may not be able to handle
stupidly large keys */
*keyLength = min( requestedKeySize, MAX_WORKING_KEYSIZE );
return( CRYPT_OK );
}
/* Determine the optimal size for a generated key. This isn't as easy as
just taking the default key size since some algorithms have variable key
sizes (RCx) or alternative key sizes where the default isn't necessarily
the best choice (two-key vs.three-key 3DES) */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int getDefaultKeysize( const CONTEXT_INFO *contextInfoPtr,
OUT_LENGTH_PKC_Z int *keyLength )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
int localKeyLength;
assert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isWritePtr( keyLength, sizeof( int ) ) );
/* Clear return value */
*keyLength = 0;
/* For PKC contexts where we're generating a new key we want to use the
recommended (rather than the longest possible) key size whereas for
conventional contexts we want to use the longest possible size (this
will be adjusted further down if necessary for those algorithms where
it's excessively long) */
if( contextInfoPtr->type == CONTEXT_PKC )
localKeyLength = capabilityInfoPtr->keySize;
else
localKeyLength = capabilityInfoPtr->maxKeySize;
#if defined( USE_RC2 ) || defined( USE_RC4 )
/* Although RC2 will handle keys of up to 1024 bits and RC4 up to 2048
bits they're never used with this maximum size but (at least in non-
crippled implementations) always fixed at 128 bits, so we limit them
to the default rather than maximum possible size */
if( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RC2 || \
capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RC4 )
localKeyLength = capabilityInfoPtr->keySize;
#endif /* USE_RC2 || USE_RC4 */
ENSURES( localKeyLength > MIN_KEYSIZE && \
localKeyLength <= CRYPT_MAX_PKCSIZE );
/* Trim the key size to fit */
return( adjustUserKeySize( contextInfoPtr, localKeyLength, keyLength ) );
}
/* Check that user-supplied supplied PKC parameters make sense (algorithm-
parameter-specific validity checks are performed at a lower level).
Although the checks are somewhat specific to particular PKC algorithm
classes we have to do them at this point in order to avoid duplicating
them in every plug-in PKC module, and because strictly speaking it's the
job of the higher-level code to ensure that the lower-level routines get
fed at least approximately valid input */
#ifndef USE_FIPS140
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int checkPKCparams( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
const void *keyInfo )
{
const CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) keyInfo;
REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
cryptAlgo <= CRYPT_ALGO_LAST_PKC );
REQUIRES( keyInfo != NULL );
/* The ECC check is somewhat different to the others because ECC key
sizes work in different ways so we have to special-case this one */
if( isEccAlgo( cryptAlgo ) )
{
const CRYPT_PKCINFO_ECC *eccKey = ( CRYPT_PKCINFO_ECC * ) keyInfo;
assert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_ECC ) ) );
/* Check the general info and make sure that all required values are
initialised */
if( ( eccKey->isPublicKey != TRUE && eccKey->isPublicKey != FALSE ) )
return( CRYPT_ARGERROR_STR1 );
if( eccKey->pLen <= 0 || eccKey->aLen <= 0 || eccKey->bLen <= 0 || \
eccKey->gxLen <= 0 || eccKey->gyLen <= 0 || eccKey->rLen <= 0 || \
eccKey->qxLen <= 0 || eccKey->qyLen <= 0 || eccKey->dLen < 0 )
return( CRYPT_ARGERROR_STR1 );
/* Check the parameters and public components */
if( eccKey->pLen < bytesToBits( ECCPARAM_MIN_P ) || \
eccKey->pLen > bytesToBits( ECCPARAM_MAX_P ) || \
eccKey->aLen < bytesToBits( ECCPARAM_MIN_A ) || \
eccKey->aLen > bytesToBits( ECCPARAM_MAX_A ) || \
eccKey->bLen < bytesToBits( ECCPARAM_MIN_B ) || \
eccKey->bLen > bytesToBits( ECCPARAM_MAX_B ) || \
eccKey->gxLen < bytesToBits( ECCPARAM_MIN_GX ) || \
eccKey->gxLen > bytesToBits( ECCPARAM_MAX_GX ) || \
eccKey->gyLen < bytesToBits( ECCPARAM_MIN_GY ) || \
eccKey->gyLen > bytesToBits( ECCPARAM_MAX_GY ) || \
eccKey->rLen < bytesToBits( ECCPARAM_MIN_R ) || \
eccKey->rLen > bytesToBits( ECCPARAM_MAX_R ) )
return( CRYPT_ARGERROR_STR1 );
if( eccKey->qxLen < bytesToBits( ECCPARAM_MIN_QX ) || \
eccKey->qxLen > bytesToBits( ECCPARAM_MAX_QX ) || \
eccKey->qyLen < bytesToBits( ECCPARAM_MIN_QY ) || \
eccKey->qyLen > bytesToBits( ECCPARAM_MAX_QY ) )
return( CRYPT_ARGERROR_STR1 );
if( eccKey->isPublicKey )
return( CRYPT_OK );
/* Check the private components */
if( eccKey->dLen < bytesToBits( ECCPARAM_MIN_D ) || \
eccKey->dLen > bytesToBits( ECCPARAM_MAX_D ) )
return( CRYPT_ARGERROR_STR1 );
return( CRYPT_OK );
}
/* For the non-ECC algorithms the DLP check is simpler than the RSA one
because there are less odd parameter combinations possible so we get
this one out of the way first. Note that we don't get PKCS #3 DH
keys at this level so we always require that q be present */
if( isDlpAlgo( cryptAlgo ) )
{
const CRYPT_PKCINFO_DLP *dlpKey = ( CRYPT_PKCINFO_DLP * ) keyInfo;
assert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) );
/* Check the general info and make sure that all required values are
initialised */
if( ( dlpKey->isPublicKey != TRUE && dlpKey->isPublicKey != FALSE ) )
return( CRYPT_ARGERROR_STR1 );
if( dlpKey->pLen <= 0 || dlpKey->qLen <= 0 || dlpKey->gLen <= 0 || \
dlpKey->yLen < 0 || dlpKey->xLen < 0 )
return( CRYPT_ARGERROR_STR1 );
/* Check the public components */
if( isShortPKCKey( dlpKey->pLen ) )
{
/* Special-case handling for insecure-sized public keys */
return( CRYPT_ERROR_NOSECURE );
}
if( dlpKey->pLen < bytesToBits( DLPPARAM_MIN_P ) || \
dlpKey->pLen > bytesToBits( DLPPARAM_MAX_P ) || \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -