📄 mech_privk.c
字号:
if( cryptStatusError( status ) )
return( status );
padSize = roundUp( payloadSize + 1, blockSize ) - payloadSize;
ENSURES( !( ( payloadSize + padSize ) & ( blockSize - 1 ) ) );
ENSURES( padSize >= 1 && padSize <= CRYPT_MAX_IVSIZE );
/* If this is just a length check, we're done */
if( mechanismInfo->wrappedData == NULL )
{
mechanismInfo->wrappedDataLength = payloadSize + padSize;
return( CRYPT_OK );
}
/* Make sure that the wrapped key fits in the output buffer */
if( payloadSize + padSize > mechanismInfo->wrappedDataLength )
return( CRYPT_ERROR_OVERFLOW );
/* Write the private key data, PKCS #5-pad it, and encrypt it */
sMemOpen( &stream, mechanismInfo->wrappedData,
mechanismInfo->wrappedDataLength );
status = exportPrivateKeyData( &stream, mechanismInfo->keyContext,
formatType, "private_key", 11 );
sMemDisconnect( &stream );
if( cryptStatusOK( status ) )
{
BYTE startSample[ 8 + 8 ], endSample[ 8 + 8 ];
BYTE *dataPtr = mechanismInfo->wrappedData;
const void *dataEndPtr = dataPtr + payloadSize + padSize - 8;
int i;
/* Sample the first and last 8 bytes of data so that we can check
that they really have been encrypted */
memcpy( startSample, dataPtr, 8 );
memcpy( endSample, dataEndPtr, 8 );
/* Add the PKCS #5 padding and encrypt the data */
for( i = 0; i < padSize; i++ )
dataPtr[ payloadSize + i ] = padSize;
status = krnlSendMessage( mechanismInfo->wrapContext,
IMESSAGE_CTX_ENCRYPT,
mechanismInfo->wrappedData,
payloadSize + padSize );
/* Make sure that the original data samples differ from the final
data. We don't perform a retIntError() exit at this point because
we need to continue and zeroise the data that we're working with */
if( cryptStatusOK( status ) && \
( !memcmp( startSample, dataPtr, 8 ) || \
!memcmp( endSample, dataEndPtr, 8 ) ) )
{
assert( DEBUG_WARN );
status = CRYPT_ERROR_FAILED;
}
zeroise( startSample, 8 );
zeroise( endSample, 8 );
}
if( cryptStatusError( status ) )
{
zeroise( mechanismInfo->wrappedData,
mechanismInfo->wrappedDataLength );
return( status );
}
mechanismInfo->wrappedDataLength = payloadSize + padSize;
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int privateKeyUnwrap( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo,
IN_ENUM( PRIVATEKEY_WRAP ) \
const PRIVATEKEY_WRAP_TYPE type )
{
const KEYFORMAT_TYPE formatType = ( type == PRIVATEKEY_WRAP_NORMAL ) ? \
KEYFORMAT_PRIVATE : KEYFORMAT_PRIVATE_OLD;
void *buffer;
int blockSize, status;
UNUSED_ARG( dummy );
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
REQUIRES( type > PRIVATEKEY_WRAP_NONE && type < PRIVATEKEY_WRAP_LAST );
/* Make sure that the data has a sane length and is a multiple of the
cipher block size. Since we force the use of CBC mode we know that
it has to have this property. Any required length checks have
already been enforced by the kernel ACLs */
status = krnlSendMessage( mechanismInfo->wrapContext,
IMESSAGE_GETATTRIBUTE, &blockSize,
CRYPT_CTXINFO_IVSIZE );
if( cryptStatusError( status ) )
return( status );
if( mechanismInfo->wrappedDataLength & ( blockSize - 1 ) )
return( CRYPT_ERROR_BADDATA );
/* Copy the encrypted private key data to a temporary pagelocked buffer,
decrypt it, and read it into the context. If we get a corrupted-data
error then it's far more likely to be because we decrypted with the
wrong key than because any data was corrupted so we convert it to a
wrong-key error */
if( ( status = krnlMemalloc( &buffer, \
mechanismInfo->wrappedDataLength ) ) != CRYPT_OK )
return( status );
memcpy( buffer, mechanismInfo->wrappedData,
mechanismInfo->wrappedDataLength );
status = krnlSendMessage( mechanismInfo->wrapContext,
IMESSAGE_CTX_DECRYPT, buffer,
mechanismInfo->wrappedDataLength );
if( cryptStatusOK( status ) )
{
status = checkKeyIntegrity( buffer,
mechanismInfo->wrappedDataLength,
blockSize );
}
if( cryptStatusOK( status ) )
{
STREAM stream;
sMemConnect( &stream, buffer, mechanismInfo->wrappedDataLength );
status = importPrivateKeyData( &stream, mechanismInfo->keyContext,
formatType );
sMemDisconnect( &stream );
if( status == CRYPT_ERROR_BADDATA )
status = CRYPT_ERROR_WRONGKEY;
}
zeroise( buffer, mechanismInfo->wrappedDataLength );
krnlMemfree( &buffer );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int exportPrivateKey( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyWrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_NORMAL ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKey( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyUnwrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_NORMAL ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int exportPrivateKeyPKCS8( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyWrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_OLD ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyPKCS8( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyUnwrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_OLD ) );
}
/****************************************************************************
* *
* PGP Private Key Wrap/Unwrap Mechanisms *
* *
****************************************************************************/
#ifdef USE_PGPKEYS
/* Perform PGP private key wrapping/unwrapping. There are several variations
of this that are handled through common private key wrap mechanism
functions. The variations are:
PGP2: mpi_enc( d ), mpi_enc( p ), mpi_enc( q ), mpi_enc( u ),
uint16 checksum
OpenPGP_Old: enc( mpi [...],
uint16 checksum )
OpenPGP: enc( mpi [...],
byte[20] mdc ) */
typedef enum { PRIVATEKEYPGP_WRAP_NONE, PRIVATEKEYPGP_WRAP_PGP2,
PRIVATEKEYPGP_WRAP_OPENPGP_OLD,
PRIVATEKEYPGP_WRAP_OPENPGP,
PRIVATEKEYPGP_WRAP_LAST } PRIVATEKEYPGP_WRAP_TYPE;
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int privateKeyUnwrapPGP( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo,
IN_ENUM( PRIVATEKEYPGP_WRAP ) \
const PRIVATEKEYPGP_WRAP_TYPE type )
{
CRYPT_ALGO_TYPE cryptAlgo;
STREAM stream;
void *buffer;
int bytesToChecksum = DUMMY_INIT, status;
UNUSED_ARG( dummy );
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
REQUIRES( type > PRIVATEKEYPGP_WRAP_NONE && \
type < PRIVATEKEYPGP_WRAP_LAST );
/* Get various algorithm parameters */
status = krnlSendMessage( mechanismInfo->keyContext,
IMESSAGE_GETATTRIBUTE, &cryptAlgo,
CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
/* Copy the encrypted private key data to a temporary buffer and decrypt
it */
if( ( status = krnlMemalloc( &buffer, \
mechanismInfo->wrappedDataLength ) ) != CRYPT_OK )
return( status );
memcpy( buffer, mechanismInfo->wrappedData,
mechanismInfo->wrappedDataLength );
if( type == PRIVATEKEYPGP_WRAP_PGP2 )
{
status = pgp2DecryptKey( buffer, mechanismInfo->wrappedDataLength,
&bytesToChecksum, mechanismInfo->wrapContext,
( cryptAlgo != CRYPT_ALGO_RSA ) ? \
TRUE : FALSE );
}
else
{
status = krnlSendMessage( mechanismInfo->wrapContext,
IMESSAGE_CTX_DECRYPT, buffer,
mechanismInfo->wrappedDataLength );
}
if( cryptStatusError( status ) )
{
zeroise( buffer, mechanismInfo->wrappedDataLength );
krnlMemfree( &buffer );
return( status );
}
/* Perform one of PGP's assorted key checksumming operations and read
the key data into the context */
if( type == PRIVATEKEYPGP_WRAP_PGP2 || \
type == PRIVATEKEYPGP_WRAP_OPENPGP_OLD )
{
/* Before the use of MDCs for private-key data there was a mutant
halfway stage that use the PGP 2.x checksum but encrypted all of
the key data in the OpenPGP manner. If we're using this halfway
variant then the amount of data to checksum is the total amount
minus the size of the checksum */
if( type == PRIVATEKEYPGP_WRAP_OPENPGP_OLD )
bytesToChecksum = mechanismInfo->wrappedDataLength - UINT16_SIZE;
status = checkPgp2KeyIntegrity( buffer, mechanismInfo->wrappedDataLength,
bytesToChecksum,
( cryptAlgo != CRYPT_ALGO_RSA ) ? \
TRUE : FALSE );
}
else
{
status = checkOpenPgpKeyIntegrity( buffer,
mechanismInfo->wrappedDataLength );
}
if( cryptStatusOK( status ) )
{
sMemConnect( &stream, buffer, mechanismInfo->wrappedDataLength );
status = importPrivateKeyData( &stream, mechanismInfo->keyContext,
KEYFORMAT_PGP );
sMemDisconnect( &stream );
if( status == CRYPT_ERROR_BADDATA )
status = CRYPT_ERROR_WRONGKEY;
}
zeroise( buffer, mechanismInfo->wrappedDataLength );
krnlMemfree( &buffer );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyPGP2( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyUnwrapPGP( dummy, mechanismInfo,
PRIVATEKEYPGP_WRAP_PGP2 ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyOpenPGPOld( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyUnwrapPGP( dummy, mechanismInfo,
PRIVATEKEYPGP_WRAP_OPENPGP_OLD ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyOpenPGP( STDC_UNUSED void *dummy,
INOUT MECHANISM_WRAP_INFO *mechanismInfo )
{
assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
return( privateKeyUnwrapPGP( dummy, mechanismInfo,
PRIVATEKEYPGP_WRAP_OPENPGP ) );
}
#endif /* USE_PGPKEYS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -