📄 keyex_rw.c
字号:
are hashed, this is because the "iterated hashing" treats the salt +
password as an infinitely-repeated sequence of values and hashes the
resulting string for PGP-iteration-count bytes worth. Instead of
being written directly the count is encoded in a complex manner which
saves a whole byte, so before we can write it we have to encode it
into the base + exponent form expected by PGP. This has a default
base of 16 + the user-supplied base value, we can set this to zero
since the iteration count used by cryptlib is always a multiple of
16, the remainder is just log2 of what's left of the iteration
count */
assert( keySetupIterations % 16 == 0 );
keySetupIterations /= 32; /* Remove fixed offset before log2 op.*/
while( keySetupIterations > 0 )
{
count++;
keySetupIterations >>= 1;
}
count <<= 4; /* Exponent comes first */
/* Write the SKE packet */
pgpWritePacketHeader( stream, PGP_PACKET_SKE, 4 + PGP_SALTSIZE + 1 );
sputc( stream, PGP_VERSION_OPENPGP );
sputc( stream, cryptlibToPgpAlgo( cryptAlgo ) );
sputc( stream, 3 ); /* S2K = salted, iterated hash */
sputc( stream, cryptlibToPgpAlgo( hashAlgo ) );
swrite( stream, salt, PGP_SALTSIZE );
return( sputc( stream, count ) );
}
#endif /* USE_PGP */
/****************************************************************************
* *
* Public-key Encrypted Key Routines *
* *
****************************************************************************/
/* Read/write CMS key transport data */
static int readCmsKeytrans( STREAM *stream, QUERY_INFO *queryInfo )
{
long value;
int status;
/* Read the header and version number */
readSequence( stream, NULL );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
return( status );
if( value != KEYTRANS_VERSION )
return( CRYPT_ERROR_BADDATA );
/* Read the key ID and PKC algorithm information */
value = getStreamObjectLength( stream );
if( cryptStatusError( value ) )
return( value );
queryInfo->iAndSStart = sMemBufPtr( stream );
queryInfo->iAndSLength = value;
readUniversal( stream );
status = readAlgoID( stream, &queryInfo->cryptAlgo );
if( cryptStatusError( status ) )
return( status );
/* Finally, read the start of the encrypted key. We never read the data
itself since it's passed directly to the PKC decrypt function */
status = readOctetStringHole( stream, &queryInfo->dataLength,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
queryInfo->dataStart = sMemBufPtr( stream );
return( status );
}
static int writeCmsKeytrans( STREAM *stream,
const CRYPT_CONTEXT iCryptContext,
const BYTE *buffer, const int length,
const void *auxInfo, const int auxInfoLength )
{
const int dataLength = \
sizeofContextAlgoID( iCryptContext, CRYPT_ALGO_NONE,
ALGOID_FLAG_ALGOID_ONLY ) + \
( int ) sizeofObject( length );
writeSequence( stream, sizeofShortInteger( KEYTRANS_VERSION ) +
auxInfoLength + dataLength );
writeShortInteger( stream, KEYTRANS_VERSION, DEFAULT_TAG );
swrite( stream, auxInfo, auxInfoLength );
writeContextAlgoID( stream, iCryptContext, CRYPT_ALGO_NONE,
ALGOID_FLAG_ALGOID_ONLY );
return( writeOctetString( stream, buffer, length, DEFAULT_TAG ) );
}
/* Read/write cryptlib key transport data */
static int writeCryptlibKeytrans( STREAM *stream,
const CRYPT_CONTEXT iCryptContext,
const BYTE *buffer, const int length,
const void *auxInfo,
const int auxInfoLength )
{
RESOURCE_DATA msgData;
BYTE keyID[ CRYPT_MAX_HASHSIZE ];
const int dataLength = \
sizeofContextAlgoID( iCryptContext, CRYPT_ALGO_NONE,
ALGOID_FLAG_ALGOID_ONLY ) + \
( int ) sizeofObject( length );
setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEYID );
writeSequence( stream, sizeofShortInteger( KEYTRANS_EX_VERSION ) +
( int ) sizeofObject( msgData.length ) + dataLength );
writeShortInteger( stream, KEYTRANS_EX_VERSION, DEFAULT_TAG );
writeOctetString( stream, msgData.data, msgData.length, CTAG_KT_SKI );
writeContextAlgoID( stream, iCryptContext, CRYPT_ALGO_NONE,
ALGOID_FLAG_ALGOID_ONLY );
return( writeOctetString( stream, buffer, length, DEFAULT_TAG ) );
}
static int readCryptlibKeytrans( STREAM *stream, QUERY_INFO *queryInfo )
{
long value;
int status;
/* Read the header and version number */
readSequence( stream, NULL );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
return( status );
if( value != KEYTRANS_EX_VERSION )
return( CRYPT_ERROR_BADDATA );
/* Read the key ID and PKC algorithm information */
readOctetStringTag( stream, queryInfo->keyID, &queryInfo->keyIDlength,
CRYPT_MAX_HASHSIZE, CTAG_KT_SKI );
status = readAlgoID( stream, &queryInfo->cryptAlgo );
if( cryptStatusError( status ) )
return( status );
/* Finally, read the start of the encrypted key. We never read the data
itself since it's passed directly to the PKC decrypt function */
status = readOctetStringHole( stream, &queryInfo->dataLength,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
queryInfo->dataStart = sMemBufPtr( stream );
return( status );
}
#ifdef USE_PGP
/* Read/write PGP key transport data:
PKE:
byte ctb = PGP_PACKET_PKE
byte[] length
byte version = 2 or 3
byte[8] keyID
byte PKC algo
mpi(s) encrypted session key */
static int readPgpKeytrans( STREAM *stream, QUERY_INFO *queryInfo )
{
int value, status;
/* 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 = getPacketInfo( stream, queryInfo );
if( cryptStatusError( status ) )
return( status );
value = sgetc( stream );
if( value != PGP_VERSION_2 && value != PGP_VERSION_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;
if( ( queryInfo->cryptAlgo = \
pgpToCryptlibAlgo( sgetc( stream ),
PGP_ALGOCLASS_PKCCRYPT ) ) == CRYPT_ALGO_NONE )
return( CRYPT_ERROR_NOTAVAIL );
/* Read the encrypted key */
if( queryInfo->cryptAlgo == CRYPT_ALGO_RSA )
{
queryInfo->dataStart = sMemBufPtr( stream ) + 2;
status = pgpReadMPI( stream, NULL );
if( cryptStatusError( status ) )
return( status );
queryInfo->dataLength = bitsToBytes( status );
return( CRYPT_OK );
}
queryInfo->dataStart = sMemBufPtr( stream );
status = pgpReadMPI( stream, NULL );
if( cryptStatusError( status ) )
return( status );
queryInfo->dataLength = bitsToBytes( status ) + 2;
if( queryInfo->dataLength < 56 || \
queryInfo->dataLength > CRYPT_MAX_PKCSIZE + 2 )
return( CRYPT_ERROR_BADDATA );
status = pgpReadMPI( stream, NULL );
if( cryptStatusError( status ) )
return( status );
queryInfo->dataLength += bitsToBytes( status ) + 2;
if( queryInfo->dataLength < ( 56 * 2 ) || \
queryInfo->dataLength > ( ( CRYPT_MAX_PKCSIZE + 2 ) * 2 ) )
return( CRYPT_ERROR_BADDATA );
return( CRYPT_OK );
}
static int writePgpKeytrans( STREAM *stream,
const CRYPT_CONTEXT iCryptContext,
const BYTE *buffer, const int length,
const void *auxInfo, const int auxInfoLength )
{
CRYPT_ALGO_TYPE cryptAlgo;
BYTE keyID[ PGP_KEYID_SIZE ];
int status;
/* Get the key information */
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, keyID, PGP_KEYID_SIZE );
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
}
if( cryptStatusError( status ) )
return( status );
/* Write the PKE packet */
pgpWritePacketHeader( stream, PGP_PACKET_PKE,
1 + PGP_KEYID_SIZE + 1 + \
( ( cryptAlgo == CRYPT_ALGO_RSA ) ? \
sizeofMPI( length ) : length ) );
sputc( stream, 3 ); /* Version = 3 (OpenPGP) */
swrite( stream, keyID, PGP_KEYID_SIZE );
sputc( stream, cryptlibToPgpAlgo( cryptAlgo ) );
return( ( cryptAlgo == CRYPT_ALGO_RSA ) ? \
pgpWriteMPI( stream, buffer, length ) :
swrite( stream, buffer, length ) );
}
#endif /* USE_PGP */
/****************************************************************************
* *
* Key Agreement Routines *
* *
****************************************************************************/
#if 0 /* 24/11/02 Removed since Fortezza is effectively dead */
/* Read/write a KeyAgreeRecipientInfo (= FortezzaRecipientInfo) record */
int readKeyAgreeInfo( STREAM *stream, QUERY_INFO *queryInfo,
CRYPT_CONTEXT *iKeyAgreeContext )
{
CRYPT_CONTEXT iLocalKeyAgreeContext;
long value;
int status;
/* Clear return value */
if( iKeyAgreeContext != NULL )
*iKeyAgreeContext = CRYPT_ERROR;
/* Read the header and version number */
readConstructed( stream, NULL, CTAG_RI_KEYAGREE );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
return( status );
if( value != 3 )
return( CRYPT_ERROR_BADDATA );
/* Read the public key information and encryption algorithm information */
status = iCryptReadSubjectPublicKey( stream, &iLocalKeyAgreeContext,
FALSE );
if( cryptStatusError( status ) )
return( status );
/* If we're doing a query we're not interested in the key agreement
context so we just copy out the information we need and destroy it */
if( iKeyAgreeContext == NULL )
{
RESOURCE_DATA msgData;
setMessageData( &msgData, queryInfo->keyID,
queryInfo->keyIDlength );
status = krnlSendMessage( iLocalKeyAgreeContext,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEYID );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iLocalKeyAgreeContext,
IMESSAGE_GETATTRIBUTE,
&queryInfo->cryptAlgo,
CRYPT_CTXINFO_ALGO );
krnlSendNotifier( iLocalKeyAgreeContext, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Make the key agreement context externally visible */
*iKeyAgreeContext = iLocalKeyAgreeContext;
return( CRYPT_OK );
}
int writeKeyAgreeInfo( STREAM *stream, const CRYPT_CONTEXT iCryptContext,
const void *wrappedKey, const int wrappedKeyLength,
const void *ukm, const int ukmLength,
const void *auxInfo, const int auxInfoLength )
{
RESOURCE_DATA msgData;
BYTE rKeyID[ 1024 ];
int rKeyIDlength, recipientKeyInfoSize, status;
/* Get the recipients key ID and determine how large the recipient key
info will be */
setMessageData( &msgData, rKeyID, 1024 );
status = krnlSendMessage( iCryptContext, MESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
if( cryptStatusError( status ) )
return( status );
rKeyIDlength = msgData.length;
recipientKeyInfoSize = ( int ) ( \
sizeofObject( sizeofObject( rKeyIDlength ) ) + \
sizeofObject( wrappedKeyLength ) );
/* Write the FortezzaRecipientInfo header and version number */
writeConstructed( stream, ( int ) sizeofShortInteger( 3 ) + \
sizeofObject( sizeofObject( auxInfoLength ) ) + \
sizeofObject( sizeofObject( ukmLength ) ) + \
sizeofOID( ALGOID_FORTEZZA_KEYWRAP ) + \
sizeofObject( sizeofObject( recipientKeyInfoSize ) ),
CTAG_RI_KEYAGREE );
writeShortInteger( stream, 3, DEFAULT_TAG );
/* Write the originator's keyIdentifier, UKM, and Fortezza key wrap OID */
writeConstructed( stream, ( int ) sizeofObject( auxInfoLength ),
CTAG_KA_ORIG );
writeOctetString( stream, auxInfo, auxInfoLength, 0 );
writeConstructed( stream, ( int ) sizeofObject( ukmLength ),
CTAG_KA_UKM );
writeOctetString( stream, ukm, ukmLength, DEFAULT_TAG );
swrite( stream, ALGOID_FORTEZZA_KEYWRAP,
sizeofOID( ALGOID_FORTEZZA_KEYWRAP ) );
/* Write the recipient keying info */
writeSequence( stream, ( int ) sizeofObject( recipientKeyInfoSize ) );
writeSequence( stream, recipientKeyInfoSize );
writeConstructed( stream, ( int ) sizeofObject( rKeyIDlength ), 0 );
writeOctetString( stream, rKeyID, rKeyIDlength, DEFAULT_TAG );
return( writeOctetString( stream, wrappedKey, wrappedKeyLength,
DEFAULT_TAG ) );
}
#endif /* 0 */
/****************************************************************************
* *
* Key Exchange Read/Write Function Access Information *
* *
****************************************************************************/
const READKEYTRANS_FUNCTION keytransReadTable[] = {
NULL, /* KEYEX_NONE */
readCmsKeytrans, /* KEYEX_CMS */
readCryptlibKeytrans, /* KEYEX_CRYPTLIB */
#ifdef USE_PGP
readPgpKeytrans, /* KEYEX_PGP */
#else
NULL, /* KEYEX_PGP */
#endif /* USE_PGP */
NULL, NULL, NULL
};
const WRITEKEYTRANS_FUNCTION keytransWriteTable[] = {
NULL, /* KEYEX_NONE */
writeCmsKeytrans, /* KEYEX_CMS */
writeCryptlibKeytrans, /* KEYEX_CRYPTLIB */
#ifdef USE_PGP
writePgpKeytrans, /* KEYEX_PGP */
#else
NULL, /* KEYEX_PGP */
#endif /* USE_PGP */
NULL, NULL, NULL
};
const READKEK_FUNCTION kekReadTable[] = {
NULL, /* KEYEX_NONE */
readCryptlibKek, /* KEYEX_CMS */
readCryptlibKek, /* KEYEX_CRYPTLIB */
#ifdef USE_PGP
readPgpKek, /* KEYEX_PGP */
#else
NULL, /* KEYEX_PGP */
#endif /* USE_PGP */
NULL, NULL, NULL
};
const WRITEKEK_FUNCTION kekWriteTable[] = {
NULL, /* KEYEX_NONE */
writeCryptlibKek, /* KEYEX_CMS */
writeCryptlibKek, /* KEYEX_CRYPTLIB */
#ifdef USE_PGP
writePgpKek, /* KEYEX_PGP */
#else
NULL, /* KEYEX_PGP */
#endif /* USE_PGP */
NULL, NULL, NULL
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -