📄 pkcs15_rd.c
字号:
int readKeyset( STREAM *stream, PKCS15_INFO *pkcs15info, const long endPos )
{
int status = CRYPT_OK;
/* Scan all the objects in the file. We allow a bit of slop to handle
incorrect length encodings */
while( cryptStatusOK( status ) && \
stell( stream ) < endPos - MIN_OBJECT_SIZE )
{
const int tag = peekTag( stream );
const PKCS15_OBJECT_TYPE type = EXTRACT_CTAG( tag );
long innerEndPos;
/* Read the [n] [0] wrapper to find out what we're dealing with. We
use the long form since keysets with large numbers of objects can
grow larger than the maximum size allowed by the standard form */
if( type < 0 || type >= PKCS15_OBJECT_LAST )
{
status = CRYPT_ERROR_BADDATA;
break;
}
readLongConstructed( stream, NULL, tag );
status = readLongConstructed( stream, &innerEndPos, CTAG_OV_DIRECT );
if( cryptStatusError( status ) )
break;
innerEndPos += stell( stream );
if( innerEndPos < 16 || innerEndPos > MAX_INTLENGTH )
return( CRYPT_ERROR_BADDATA ); /* Safety check */
/* Scan all objects of this type, again allowing for slop */
while( cryptStatusOK( status ) && \
stell( stream ) < innerEndPos - MIN_OBJECT_SIZE )
{
PKCS15_INFO pkcs15objectInfo, *pkcs15infoPtr;
BYTE buffer[ 16 ];
void *objectData;
int headerSize, objectLength;
/* Read the current object. We can't use getObjectLength() here
because we're reading from a file rather than a memory stream */
status = sread( stream, buffer, 16 );
if( !cryptStatusError( status ) ) /* sread() returns length */
status = ( status == 16 || status == CRYPT_OK ) ? \
CRYPT_OK : CRYPT_ERROR_UNDERFLOW;
if( cryptStatusOK( status ) )
{
STREAM headerStream;
sMemConnect( &headerStream, buffer, 16 );
status = readGenericHole( &headerStream, &objectLength,
DEFAULT_TAG );
headerSize = stell( &headerStream );
sMemDisconnect( &headerStream );
}
if( cryptStatusOK( status ) && \
( objectLength < MIN_OBJECT_SIZE || \
objectLength > MAX_PRIVATE_KEYSIZE + 1024 ) )
status = CRYPT_ERROR_BADDATA;
if( cryptStatusOK( status ) )
{
objectLength += headerSize;
if( ( objectData = clAlloc( "readKeyset", \
objectLength ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
}
if( cryptStatusError( status ) )
break;
memcpy( objectData, buffer, 16 );
status = sread( stream, ( BYTE * ) objectData + 16,
objectLength - 16 );
if( !cryptStatusError( status ) ) /* sread() returns length */
status = checkObjectEncoding( objectData, objectLength );
if( !cryptStatusError( status ) ) /* cOE() returns length */
{
STREAM objectStream;
sMemConnect( &objectStream, objectData, objectLength );
status = readObjectAttributes( &objectStream,
&pkcs15objectInfo, type );
sMemDisconnect( &objectStream );
}
if( cryptStatusError( status ) )
{
clFree( "readKeyset", objectData );
break;
}
/* Find out where to add the object data */
pkcs15infoPtr = findEntry( pkcs15info, CRYPT_KEYIDEX_ID,
pkcs15objectInfo.iD,
pkcs15objectInfo.iDlength,
KEYMGMT_FLAG_NONE );
if( pkcs15infoPtr == NULL )
{
int i;
/* This personality isn't present yet, find out where we can
add the object data and copy the fixed information
over */
for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
break;
if( i == MAX_PKCS15_OBJECTS )
{
clFree( "readKeyset", objectData );
status = CRYPT_ERROR_OVERFLOW;
break;
}
pkcs15info[ i ] = pkcs15objectInfo;
pkcs15infoPtr = &pkcs15info[ i ];
pkcs15infoPtr->index = i;
}
/* If any new ID information has become available, copy it over.
The keyID defaults to the iD, so we only copy the newly-read
keyID over if it's something other than the existing iD */
if( pkcs15infoPtr->iDlength != pkcs15objectInfo.keyIDlength || \
memcmp( pkcs15infoPtr->iD, pkcs15objectInfo.keyID,
pkcs15objectInfo.keyIDlength ) )
{
memcpy( pkcs15infoPtr->keyID, pkcs15objectInfo.keyID,
pkcs15objectInfo.keyIDlength );
pkcs15infoPtr->keyIDlength = pkcs15objectInfo.keyIDlength;
}
if( pkcs15objectInfo.iAndSIDlength )
{
memcpy( pkcs15infoPtr->iAndSID, pkcs15objectInfo.iAndSID,
pkcs15objectInfo.iAndSIDlength );
pkcs15infoPtr->iAndSIDlength = pkcs15objectInfo.iAndSIDlength;
}
if( pkcs15objectInfo.subjectNameIDlength )
{
memcpy( pkcs15infoPtr->subjectNameID,
pkcs15objectInfo.subjectNameID,
pkcs15objectInfo.subjectNameIDlength );
pkcs15infoPtr->subjectNameIDlength = \
pkcs15objectInfo.subjectNameIDlength;
}
if( pkcs15objectInfo.issuerNameIDlength )
{
memcpy( pkcs15infoPtr->issuerNameID,
pkcs15objectInfo.issuerNameID,
pkcs15objectInfo.issuerNameIDlength );
pkcs15infoPtr->issuerNameIDlength = \
pkcs15objectInfo.issuerNameIDlength;
}
if( pkcs15objectInfo.pgp2KeyIDlength )
{
memcpy( pkcs15infoPtr->pgp2KeyID,
pkcs15objectInfo.pgp2KeyID,
pkcs15objectInfo.pgp2KeyIDlength );
pkcs15infoPtr->pgp2KeyIDlength = \
pkcs15objectInfo.pgp2KeyIDlength;
}
if( pkcs15objectInfo.openPGPKeyIDlength )
{
memcpy( pkcs15infoPtr->openPGPKeyID,
pkcs15objectInfo.openPGPKeyID,
pkcs15objectInfo.openPGPKeyIDlength );
pkcs15infoPtr->openPGPKeyIDlength = \
pkcs15objectInfo.openPGPKeyIDlength;
}
/* Copy over any other new information that may have become
available. The semantics when multiple date ranges are
present (for example one for a key, one for a cert) are a
bit uncertain, we use the most recent date available on the
assumption that this reflects the newest information */
if( pkcs15objectInfo.validFrom > pkcs15infoPtr->validFrom )
pkcs15infoPtr->validFrom = pkcs15objectInfo.validFrom;
if( pkcs15objectInfo.validTo > pkcs15infoPtr->validTo )
pkcs15infoPtr->validTo = pkcs15objectInfo.validTo;
/* Copy the payload over */
switch( type )
{
case PKCS15_OBJECT_PUBKEY:
pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
pkcs15infoPtr->pubKeyData = objectData;
pkcs15infoPtr->pubKeyDataSize = objectLength;
pkcs15infoPtr->pubKeyOffset = pkcs15objectInfo.pubKeyOffset;
pkcs15infoPtr->pubKeyUsage = pkcs15objectInfo.pubKeyUsage;
break;
case PKCS15_OBJECT_PRIVKEY:
pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
pkcs15infoPtr->privKeyData = objectData;
pkcs15infoPtr->privKeyDataSize = objectLength;
pkcs15infoPtr->privKeyOffset = pkcs15objectInfo.privKeyOffset;
pkcs15infoPtr->privKeyUsage = pkcs15objectInfo.privKeyUsage;
break;
case PKCS15_OBJECT_CERT:
case PKCS15_OBJECT_TRUSTEDCERT:
case PKCS15_OBJECT_USEFULCERT:
if( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )
pkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;
pkcs15infoPtr->certData = objectData;
pkcs15infoPtr->certDataSize = objectLength;
pkcs15infoPtr->certOffset = pkcs15objectInfo.certOffset;
pkcs15infoPtr->trustedUsage = pkcs15objectInfo.trustedUsage;
pkcs15infoPtr->implicitTrust = pkcs15objectInfo.implicitTrust;
break;
case PKCS15_OBJECT_SECRETKEY:
assert( NOTREACHED );
case PKCS15_OBJECT_DATA:
pkcs15infoPtr->type = PKCS15_SUBTYPE_DATA;
pkcs15infoPtr->dataType = pkcs15objectInfo.dataType;
pkcs15infoPtr->dataData = objectData;
pkcs15infoPtr->dataDataSize = objectLength;
pkcs15infoPtr->dataOffset = pkcs15objectInfo.dataOffset;
break;
}
}
}
return( status );
}
/****************************************************************************
* *
* Read a Key *
* *
****************************************************************************/
/* Set any optional attributes that may be associated with a key */
static int setKeyAttributes( const CRYPT_HANDLE iCryptHandle,
const PKCS15_INFO *pkcs15infoPtr,
const int actionFlags )
{
RESOURCE_DATA msgData;
int status = CRYPT_OK;
if( actionFlags != CRYPT_UNUSED )
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,
( void * ) &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( cryptStatusOK( status ) && pkcs15infoPtr->openPGPKeyIDlength )
{
setMessageData( &msgData, ( void * ) pkcs15infoPtr->openPGPKeyID,
pkcs15infoPtr->openPGPKeyIDlength );
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
}
if( cryptStatusOK( status ) && pkcs15infoPtr->validFrom )
{
setMessageData( &msgData, ( void * ) &pkcs15infoPtr->validFrom,
sizeof( time_t ) );
status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_PGPVALIDITY );
}
return( status );
}
/* Read the decryption information for the encrypted private key and use it
to import the encrypted private components into an existing PKC context */
static int readEncryptedKey( STREAM *stream,
const CRYPT_CONTEXT iPrivateKey,
const char *password, const int passwordLength )
{
CRYPT_CONTEXT iSessionKey;
MESSAGE_CREATEOBJECT_INFO createInfo;
MECHANISM_WRAP_INFO mechanismInfo;
RESOURCE_DATA msgData;
QUERY_INFO queryInfo, contentQueryInfo;
void *encryptedKey;
int status;
/* Skip the version number and header for the SET OF EncryptionInfo and
query the exported key information to determine the parameters
required to reconstruct the decryption key */
readShortInteger( stream, NULL );
readSet( stream, NULL );
status = queryAsn1Object( stream, &queryInfo );
if( cryptStatusError( status ) )
return( status );
if( queryInfo.type != CRYPT_OBJECT_ENCRYPTED_KEY )
return( CRYPT_ERROR_BADDATA );
encryptedKey = sMemBufPtr( stream );
readUniversal( stream ); /* Skip the exported key */
/* Read the session key information into a context */
status = readCMSencrHeader( stream, dataOIDinfo, &iSessionKey,
&contentQueryInfo );
if( cryptStatusError( status ) )
return( status );
if( contentQueryInfo.size > sMemDataLeft( stream ) )
return( CRYPT_ERROR_UNDERFLOW );
/* Create an encryption context and derive the user password into it
using the given parameters, and import the session key. If there's
an error in the parameters stored with the exported key we'll get an
arg or attribute error when we try to set the attribute so we
translate it into an error code which is appropriate for the
situation */
setMessageCreateObjectInfo( &createInfo, queryInfo.cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE, &queryInfo.cryptMode,
CRYPT_CTXINFO_MODE );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE,
&queryInfo.keySetupAlgo,
CRYPT_CTXINFO_KEYING_ALGO );
if( cryptStatusOK( status ) )
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE,
&queryInfo.keySetupIterations,
CRYPT_CTXINFO_KEYING_ITERATIONS );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, queryInfo.salt, queryInfo.saltLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT );
}
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, ( void * ) password, passwordLength );
status = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_VALUE );
}
if( cryptStatusOK( status ) )
status = iCryptImportKeyEx( encryptedKey, queryInfo.size,
CRYPT_FORMAT_CRYPTLIB,
createInfo.cryptHandle, iSessionKey,
NULL );
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
}
memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
}
/* Import the encrypted key into the PKC context */
setMechanismWrapInfo( &mechanismInfo, sMemBufPtr( stream ),
contentQueryInfo.size, NULL, 0, iPrivateKey,
iSessionKey, CRYPT_UNUSED );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,
&mechanismInfo, MECHANISM_PRIVATEKEYWRAP );
clearMechanismInfo( &mechanismInfo );
krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Return an encoded configuration item */
static int getConfigItem( KEYSET_INFO *keysetInfo,
const CRYPT_ATTRIBUTE_TYPE dataType,
void *data, int *dataLength )
{
const PKCS15_INFO *pkcs15infoPtr = keysetInfo->keyData;
static int trustedCertIndex;
assert( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
dataType == CRYPT_IATTRIBUTE_USERINDEX || \
dataType == CRYPT_IATTRIBUTE_USERINFO || \
dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT || \
dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );
/* If we're being asked for pre-encoded data, return it to the caller */
if( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
dataType == CRYPT_IATTRIBUTE_USERINDEX || \
dataType == CRYPT_IATTRIBUTE_USERINFO )
{
int length, i;
/* Find the particular data type we're looking for */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -