keyload.c
来自「cryptlib安全工具包」· C语言 代码 · 共 1,016 行 · 第 1/3 页
C
1,016 行
dlpKey->qLen < bytesToBits( DLPPARAM_MIN_Q ) || \
dlpKey->qLen > bytesToBits( DLPPARAM_MAX_Q ) || \
dlpKey->gLen < bytesToBits( DLPPARAM_MIN_G ) || \
dlpKey->gLen > bytesToBits( DLPPARAM_MAX_G ) || \
dlpKey->yLen < bytesToBits( 0 ) || \
dlpKey->yLen > bytesToBits( DLPPARAM_MAX_Y ) )
/* y may be 0 if only x and the public parameters are available */
{
return( CRYPT_ARGERROR_STR1 );
}
if( dlpKey->isPublicKey )
return( CRYPT_OK );
/* Check the private components */
if( dlpKey->xLen < bytesToBits( DLPPARAM_MIN_X ) || \
dlpKey->xLen > bytesToBits( DLPPARAM_MAX_X ) )
return( CRYPT_ARGERROR_STR1 );
return( CRYPT_OK );
}
assert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) );
/* Check the general info and make sure that all required values are
initialised */
if( rsaKey->isPublicKey != TRUE && rsaKey->isPublicKey != FALSE )
return( CRYPT_ARGERROR_STR1 );
if( rsaKey->nLen <= 0 || rsaKey->eLen <= 0 || \
rsaKey->dLen < 0 || rsaKey->pLen < 0 || rsaKey->qLen < 0 || \
rsaKey->uLen < 0 || rsaKey->e1Len < 0 || rsaKey->e2Len < 0 )
return( CRYPT_ARGERROR_STR1 );
/* Check the public components */
if( isShortPKCKey( rsaKey->nLen ) )
{
/* Special-case handling for insecure-sized public keys */
return( CRYPT_ERROR_NOSECURE );
}
if( rsaKey->nLen < bytesToBits( RSAPARAM_MIN_N ) || \
rsaKey->nLen > bytesToBits( RSAPARAM_MAX_N ) || \
rsaKey->eLen < bytesToBits( RSAPARAM_MIN_E ) || \
rsaKey->eLen > bytesToBits( RSAPARAM_MAX_E ) || \
rsaKey->eLen > rsaKey->nLen )
return( CRYPT_ARGERROR_STR1 );
if( rsaKey->isPublicKey )
return( CRYPT_OK );
/* Check the private components. This can get somewhat complex, possible
combinations are:
d, p, q
d, p, q, u
d, p, q, e1, e2, u
p, q, e1, e2, u
The reason for some of the odder combinations is that some
implementations don't use all of the values (for example d isn't
needed at all for the CRT shortcut) or recreate them when the key is
loaded. If only d, p, and q are present we recreate e1 and e2 from
them, we also create u if necessary */
if( rsaKey->pLen < bytesToBits( RSAPARAM_MIN_P ) || \
rsaKey->pLen > bytesToBits( RSAPARAM_MAX_P ) || \
rsaKey->pLen >= rsaKey->nLen || \
rsaKey->qLen < bytesToBits( RSAPARAM_MIN_Q ) || \
rsaKey->qLen > bytesToBits( RSAPARAM_MAX_Q ) || \
rsaKey->qLen >= rsaKey->nLen )
return( CRYPT_ARGERROR_STR1 );
if( rsaKey->dLen <= 0 && rsaKey->e1Len <= 0 )
{
/* Must have either d or e1 et al */
return( CRYPT_ARGERROR_STR1 );
}
if( rsaKey->dLen > 0 && \
( rsaKey->dLen < bytesToBits( RSAPARAM_MIN_D ) || \
rsaKey->dLen > bytesToBits( RSAPARAM_MAX_D ) ) )
return( CRYPT_ARGERROR_STR1 );
if( rsaKey->e1Len > 0 && \
( rsaKey->e1Len < bytesToBits( RSAPARAM_MIN_EXP1 ) || \
rsaKey->e1Len > bytesToBits( RSAPARAM_MAX_EXP1 ) || \
rsaKey->e2Len < bytesToBits( RSAPARAM_MIN_EXP2 ) || \
rsaKey->e2Len > bytesToBits( RSAPARAM_MAX_EXP2 ) ) )
return( CRYPT_ARGERROR_STR1 );
if( rsaKey->uLen > 0 && \
( rsaKey->uLen < bytesToBits( RSAPARAM_MIN_U ) || \
rsaKey->uLen > bytesToBits( RSAPARAM_MAX_U ) ) )
return( CRYPT_ARGERROR_STR1 );
return( CRYPT_OK );
}
#endif /* USE_FIPS140 */
/****************************************************************************
* *
* Key Load Functions *
* *
****************************************************************************/
/* Load a key into a CONTEXT_INFO structure. These functions are called by
the various higher-level functions that move a key into a context */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int loadKeyConvFunction( INOUT CONTEXT_INFO *contextInfoPtr,
IN_BUFFER( keyLength ) const void *key,
IN_LENGTH_KEY const int keyLength )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
REQUIRES( contextInfoPtr->type == CONTEXT_CONV );
REQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );
/* If we don't need an IV, record it as being set */
if( !needsIV( contextInfoPtr->ctxConv->mode ) || \
isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
contextInfoPtr->flags |= CONTEXT_FLAG_IV_SET;
/* Perform the key setup */
return( capabilityInfoPtr->initKeyFunction( contextInfoPtr, key,
keyLength ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int loadKeyPKCFunction( INOUT CONTEXT_INFO *contextInfoPtr,
IN_BUFFER_OPT( keyLength ) const void *key,
IN_LENGTH_SHORT_Z const int keyLength )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
int status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( ( key == NULL ) || isReadPtr( key, keyLength ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC );
REQUIRES( ( key == NULL && keyLength == 0 ) || \
( key != NULL && \
keyLength > 16 && keyLength < MAX_INTLENGTH_SHORT ) );
/* The key data for this function may be NULL if the values
have been read from encoded X.509/SSH/SSL/PPG data straight
into the context bignums */
#ifndef USE_FIPS140
/* If we're loading from externally-supplied parameters, make sure that
the parameters make sense */
if( key != NULL )
{
status = checkPKCparams( capabilityInfoPtr->cryptAlgo, key );
if( cryptStatusError( status ) )
return( status );
contextInfoPtr->flags |= 0x08; /* Tell lib_kg to check params too */
}
#endif /* USE_FIPS140 */
/* Load the keying info */
status = capabilityInfoPtr->initKeyFunction( contextInfoPtr, key,
keyLength );
if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) )
clearTempBignums( contextInfoPtr->ctxPKC );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int loadKeyMacFunction( INOUT CONTEXT_INFO *contextInfoPtr,
IN_BUFFER( keyLength ) const void *key,
IN_LENGTH_KEY const int keyLength )
{
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isReadPtr( key, keyLength ) );
REQUIRES( contextInfoPtr->type == CONTEXT_MAC );
REQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );
return( contextInfoPtr->capabilityInfo->initKeyFunction( contextInfoPtr,
key, keyLength ) );
}
/****************************************************************************
* *
* Key Component Load Functions *
* *
****************************************************************************/
/* Load an encoded X.509/SSH/SSL/PGP key into a context. This is used for
two purposes, to load public key components into native contexts and to
save encoded X.509 public-key data for use in certificates associated
with non-native contexts held in a device. The latter is required
because there's no key data stored with the context itself that we can
use to create the SubjectPublicKeyInfo, however it's necessary to have
SubjectPublicKeyInfo available for certificate requests/certificates.
Normally this is sufficient because cryptlib always generates native
contexts for public keys/certificates and for private keys the data is
generated in the device with the encoded public components attached to
the context as described above. However for DH keys this gets a bit more
complex because although the private key is generated in the device, in
the case of the DH responder this is only the DH x value, with the
parameters (p and g) being supplied externally by the initiator. This
means that it's necessary to decode at least some of the public key data
in order to create the y value after the x value has been generated in
the device. The only situation where this functionality is currently
needed is for the SSHv2 code, which at the moment always uses native DH
contexts. For this reason we leave off resolving this issue until it's
actually required */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int setEncodedKey( INOUT CONTEXT_INFO *contextInfoPtr,
IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyType,
IN_BUFFER( keyDataLen ) const void *keyData,
IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
const int keyDataLen )
{
static const int actionFlags = \
MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
static const int actionFlagsDH = ACTION_PERM_NONE_EXTERNAL_ALL;
static const int actionFlagsPGP = \
MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
STREAM stream;
KEYFORMAT_TYPE formatType;
int status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isReadPtr( keyData, keyDataLen ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC );
REQUIRES( needsKey( contextInfoPtr ) || \
( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY ) );
REQUIRES( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \
keyType == CRYPT_IATTRIBUTE_KEY_PGP || \
keyType == CRYPT_IATTRIBUTE_KEY_SSH || \
keyType == CRYPT_IATTRIBUTE_KEY_SSH1 || \
keyType == CRYPT_IATTRIBUTE_KEY_SSL || \
keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL );
REQUIRES( keyDataLen >= MIN_CRYPT_OBJECTSIZE && \
keyDataLen < MAX_INTLENGTH_SHORT );
/* If the keys are held externally (e.g. in a crypto device), copy the
SubjectPublicKeyInfo data in and set up any other information that we
may need from it. This information is used when loading a context
from a key contained in a device, for which the actual key components
aren't directly available in the context but may be needed in the
future for things like certificate requests and certificates */
if( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY )
{
REQUIRES( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \
keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );
if( ( contextInfoPtr->ctxPKC->publicKeyInfo = \
clAlloc( "setEncodedKey", keyDataLen ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
memcpy( contextInfoPtr->ctxPKC->publicKeyInfo, keyData, keyDataLen );
contextInfoPtr->ctxPKC->publicKeyInfoSize = keyDataLen;
return( contextInfoPtr->ctxPKC->calculateKeyIDFunction( contextInfoPtr ) );
}
/* Read the appropriately-formatted key data into the context, applying
a lowest-common-denominator set of usage flags to the loaded key */
status = attributeToFormatType( keyType, &formatType );
if( cryptStatusError( status ) )
return( status );
sMemConnect( &stream, keyData, keyDataLen );
status = contextInfoPtr->ctxPKC->readPublicKeyFunction( &stream,
contextInfoPtr, formatType );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
return( status );
/* If it's a partial load of the initial public portions of a private
key with further key component operations to follow, there's nothing
more to do at this point and we're done */
if( keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \
keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL )
return( contextInfoPtr->ctxPKC->calculateKeyIDFunction( contextInfoPtr ) );
/* Perform an internal load that uses the key component values that
we've just read into the context */
contextInfoPtr->flags |= CONTEXT_FLAG_ISPUBLICKEY;
status = contextInfoPtr->loadKeyFunction( contextInfoPtr, NULL, 0 );
if( cryptStatusError( status ) )
{
/* Map the status to a more appropriate code if necessary */
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
}
contextInfoPtr->flags |= CONTEXT_FLAG_KEY_SET;
/* Restrict the key usage to public-key-only actions if necessary. For
PGP key loads (which, apart from the restrictions specified with the
stored key data aren't constrained by the presence of ACLs in the
form of certificates) we allow external usage, for DH (whose keys can be
both public and private keys even though technically it's a public
key) we allow both encryption and decryption usage, and for public
keys read from certificates we allow internal usage only */
status = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_SETATTRIBUTE,
( keyType == CRYPT_IATTRIBUTE_KEY_PGP ) ? \
( void * ) &actionFlagsPGP : \
( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH ) ? \
( void * ) &actionFlagsDH : \
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusError( status ) )
return( status );
return( contextInfoPtr->ctxPKC->calculateKeyIDFunction( contextInfoPtr ) );
}
/* Load the components of a composite PKC key into a context */
#ifndef USE_FIPS140
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int setKeyComponents( INOUT CONTEXT_INFO *contextInfoPtr,
IN_BUFFER( keyDataLen ) const void *keyData,
IN_LENGTH_SHORT_MIN( 32 ) const int keyDataLen )
{
static const int actionFlags = \
MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
BOOLEAN isPublicKey;
int status;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isReadPtr( keyData, keyDataLen ) );
REQUIRES( contextInfoPtr->type == CONTEXT_PKC && \
needsKey( contextInfoPtr ) );
REQUIRES( keyDataLen == sizeof( CRYPT_PKCINFO_RSA ) || \
keyDataLen == sizeof( CRYPT_PKCINFO_DLP ) || \
keyDataLen == sizeof( CRYPT_PKCINFO_ECC ) );
/* If it's a private key we need to have a key label set before we can
continue. The checking for this is a bit complex because at this
point all that the context knows is that it's a generic PKC context,
but it won't know whether it's a public- or private-key context until
the key is actually loaded. To determine what it'll become we look
into the key data to see what's being loaded */
isPublicKey = isEccAlgo( capabilityInfoPtr->cryptAlgo ) ? \
( ( CRYPT_PKCINFO_ECC * ) keyData )->isPublicKey : \
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?