📄 keyex_rw.c
字号:
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int writeCryptlibKeytrans( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iCryptContext,
IN_BUFFER( encryptedKeyLength ) \
const BYTE *encryptedKey,
IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \
const int encryptedKeyLength,
STDC_UNUSED const void *auxInfo,
STDC_UNUSED const int auxInfoLength )
{
MESSAGE_DATA msgData;
BYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];
const int algoIdInfoSize = \
sizeofContextAlgoID( iCryptContext, CRYPT_ALGO_NONE );
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( encryptedKey, encryptedKeyLength ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( encryptedKeyLength >= MIN_PKCSIZE && \
encryptedKeyLength < MAX_INTLENGTH_SHORT );
REQUIRES( auxInfo == NULL && auxInfoLength == 0 );
if( cryptStatusError( algoIdInfoSize ) )
return( algoIdInfoSize );
setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEYID );
if( cryptStatusError( status ) )
return( status );
writeSequence( stream, sizeofShortInteger( KEYTRANS_EX_VERSION ) +
( int ) sizeofObject( msgData.length ) + algoIdInfoSize + \
( int ) sizeofObject( encryptedKeyLength ) );
writeShortInteger( stream, KEYTRANS_EX_VERSION, DEFAULT_TAG );
writeOctetString( stream, msgData.data, msgData.length, CTAG_KT_SKI );
writeContextAlgoID( stream, iCryptContext, CRYPT_ALGO_NONE );
return( writeOctetString( stream, encryptedKey, encryptedKeyLength,
DEFAULT_TAG ) );
}
#ifdef USE_PGP
/* Read/write PGP key transport data:
PKE:
byte ctb = PGP_PACKET_PKE
byte[] length
byte version = PGP_VERSION_PGP2 or 3 (= OpenPGP, not the expected PGP3)
byte[8] keyID
byte PKC algo
mpi(s) encrypted session key */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readPgpKeytrans( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
const int startPos = stell( stream );
int value, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
/* Make sure that the packet header is in order and check the packet
version. For this packet type a version number of 3 denotes OpenPGP
whereas for signatures it denotes PGP 2.x, so we translate the value
that we return to the caller */
status = getPgpPacketInfo( stream, queryInfo );
if( cryptStatusError( status ) )
return( status );
value = sgetc( stream );
if( value != PGP_VERSION_2 && value != 3 )
return( CRYPT_ERROR_BADDATA );
queryInfo->version = ( value == PGP_VERSION_2 ) ? \
PGP_VERSION_2 : PGP_VERSION_OPENPGP;
/* Get the PGP key ID and algorithm */
status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
if( cryptStatusError( status ) )
return( status );
queryInfo->keyIDlength = PGP_KEYID_SIZE;
status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
PGP_ALGOCLASS_PKCCRYPT );
if( cryptStatusError( status ) )
return( status );
/* Read the RSA-encrypted key, recording the position and length of the
raw RSA-encrypted integer value. We have to be careful how we handle
this because readInteger16Ubits() returns the canonicalised form of
the values (with leading zeroes truncated) so an stell() before the
read doesn't necessarily represent the start of the payload:
startPos dataStart stell()
| | |
v v <-- length -->v
+---+-----------+---------------+
| | |///////////////| Stream
+---+-----------+---------------+ */
if( queryInfo->cryptAlgo == CRYPT_ALGO_RSA )
{
status = readInteger16Ubits( stream, NULL, &queryInfo->dataLength,
MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );
if( cryptStatusError( status ) )
return( status );
queryInfo->dataStart = ( stell( stream ) - startPos ) - \
queryInfo->dataLength;
}
else
{
const int dataStartPos = stell( stream );
int dummy;
REQUIRES( queryInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL );
/* Read the Elgamal-encrypted key, recording the position and
combined lengths of the MPI pair. Again, we can't use the length
returned by readInteger16Ubits() to determine the overall size
but have to calculate it from the position in the stream */
status = readInteger16Ubits( stream, NULL, &dummy, MIN_PKCSIZE,
CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readInteger16Ubits( stream, NULL, &dummy, MIN_PKCSIZE,
CRYPT_MAX_PKCSIZE );
if( cryptStatusError( status ) )
return( status );
queryInfo->dataStart = dataStartPos - startPos;
queryInfo->dataLength = stell( stream ) - dataStartPos;
}
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int writePgpKeytrans( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iCryptContext,
IN_BUFFER( encryptedKeyLength ) \
const BYTE *encryptedKey,
IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \
const int encryptedKeyLength,
STDC_UNUSED const void *auxInfo,
STDC_UNUSED const int auxInfoLength )
{
CRYPT_ALGO_TYPE cryptAlgo;
BYTE keyID[ PGP_KEYID_SIZE + 8 ];
int pgpAlgo, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( encryptedKey, encryptedKeyLength ) );
REQUIRES( isHandleRangeValid( iCryptContext ) );
REQUIRES( encryptedKeyLength >= MIN_PKCSIZE && \
encryptedKeyLength < MAX_INTLENGTH_SHORT );
REQUIRES( auxInfo == NULL && auxInfoLength == 0 );
/* Get the key information */
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
{
MESSAGE_DATA msgData;
setMessageData( &msgData, keyID, PGP_KEYID_SIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
}
if( cryptStatusError( status ) )
return( status );
status = cryptlibToPgpAlgo( cryptAlgo, &pgpAlgo );
ENSURES( cryptStatusOK( status ) );
/* Write the PKE packet */
pgpWritePacketHeader( stream, PGP_PACKET_PKE,
PGP_VERSION_SIZE + PGP_KEYID_SIZE + PGP_ALGOID_SIZE + \
( ( cryptAlgo == CRYPT_ALGO_RSA ) ? \
sizeofInteger16U( encryptedKeyLength ) : \
encryptedKeyLength ) );
sputc( stream, 3 ); /* Version = 3 (OpenPGP) */
swrite( stream, keyID, PGP_KEYID_SIZE );
sputc( stream, pgpAlgo );
return( ( cryptAlgo == CRYPT_ALGO_RSA ) ? \
writeInteger16Ubits( stream, encryptedKey, encryptedKeyLength ) :
swrite( stream, encryptedKey, encryptedKeyLength ) );
}
#endif /* USE_PGP */
/****************************************************************************
* *
* Key Exchange Read/Write Access Function *
* *
****************************************************************************/
typedef struct {
const KEYEX_TYPE type;
const READKEYTRANS_FUNCTION function;
} KEYTRANS_READ_INFO;
static const KEYTRANS_READ_INFO keytransReadTable[] = {
{ KEYEX_CMS, readCmsKeytrans },
{ KEYEX_CRYPTLIB, readCryptlibKeytrans },
#ifdef USE_PGP
{ KEYEX_PGP, readPgpKeytrans },
#endif /* USE_PGP */
{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }
};
typedef struct {
const KEYEX_TYPE type;
const WRITEKEYTRANS_FUNCTION function;
} KEYTRANS_WRITE_INFO;
static const KEYTRANS_WRITE_INFO keytransWriteTable[] = {
{ KEYEX_CMS, writeCmsKeytrans },
{ KEYEX_CRYPTLIB, writeCryptlibKeytrans },
#ifdef USE_PGP
{ KEYEX_PGP, writePgpKeytrans },
#endif /* USE_PGP */
{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }
};
typedef struct {
const KEYEX_TYPE type;
const READKEK_FUNCTION function;
} KEK_READ_INFO;
static const KEK_READ_INFO kekReadTable[] = {
{ KEYEX_CMS, readCryptlibKek },
{ KEYEX_CRYPTLIB, readCryptlibKek },
#ifdef USE_PGP
{ KEYEX_PGP, readPgpKek },
#endif /* USE_PGP */
{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }
};
typedef struct {
const KEYEX_TYPE type;
const WRITEKEK_FUNCTION function;
} KEK_WRITE_INFO;
static const KEK_WRITE_INFO kekWriteTable[] = {
{ KEYEX_CMS, writeCryptlibKek },
{ KEYEX_CRYPTLIB, writeCryptlibKek },
#ifdef USE_PGP
{ KEYEX_PGP, writePgpKek },
#endif /* USE_PGP */
{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }
};
CHECK_RETVAL_PTR \
READKEYTRANS_FUNCTION getReadKeytransFunction( IN_ENUM( KEYEX ) \
const KEYEX_TYPE keyexType )
{
int i;
REQUIRES_N( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST );
for( i = 0;
keytransReadTable[ i ].type != KEYEX_NONE && \
i < FAILSAFE_ARRAYSIZE( keytransReadTable, KEYTRANS_READ_INFO );
i++ )
{
if( keytransReadTable[ i ].type == keyexType )
return( keytransReadTable[ i ].function );
}
ENSURES_N( i < FAILSAFE_ARRAYSIZE( keytransReadTable, KEYTRANS_READ_INFO ) );
return( NULL );
}
CHECK_RETVAL_PTR \
WRITEKEYTRANS_FUNCTION getWriteKeytransFunction( IN_ENUM( KEYEX ) \
const KEYEX_TYPE keyexType )
{
int i;
REQUIRES_N( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST );
for( i = 0;
keytransWriteTable[ i ].type != KEYEX_NONE && \
i < FAILSAFE_ARRAYSIZE( keytransWriteTable, KEYTRANS_WRITE_INFO );
i++ )
{
if( keytransWriteTable[ i ].type == keyexType )
return( keytransWriteTable[ i ].function );
}
ENSURES_N( i < FAILSAFE_ARRAYSIZE( keytransWriteTable, KEYTRANS_WRITE_INFO ) );
return( NULL );
}
CHECK_RETVAL_PTR \
READKEK_FUNCTION getReadKekFunction( IN_ENUM( KEYEX ) \
const KEYEX_TYPE keyexType )
{
int i;
REQUIRES_N( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST );
for( i = 0;
kekReadTable[ i ].type != KEYEX_NONE && \
i < FAILSAFE_ARRAYSIZE( kekReadTable, KEK_READ_INFO );
i++ )
{
if( kekReadTable[ i ].type == keyexType )
return( kekReadTable[ i ].function );
}
ENSURES_N( i < FAILSAFE_ARRAYSIZE( kekReadTable, KEK_READ_INFO ) );
return( NULL );
}
CHECK_RETVAL_PTR \
WRITEKEK_FUNCTION getWriteKekFunction( IN_ENUM( KEYEX ) \
const KEYEX_TYPE keyexType )
{
int i;
REQUIRES_N( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST );
for( i = 0;
kekWriteTable[ i ].type != KEYEX_NONE && \
i < FAILSAFE_ARRAYSIZE( kekWriteTable, KEK_WRITE_INFO );
i++ )
{
if( kekWriteTable[ i ].type == keyexType )
return( kekWriteTable[ i ].function );
}
ENSURES_N( i < FAILSAFE_ARRAYSIZE( kekWriteTable, KEK_WRITE_INFO ) );
return( NULL );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -