📄 pkcs15_rd.c
字号:
for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
if( ( pkcs15infoPtr[ i ].type == PKCS15_SUBTYPE_DATA && \
pkcs15infoPtr[ i ].dataType == dataType ) )
break;
if( i == MAX_PKCS15_OBJECTS )
return( CRYPT_ERROR_NOTFOUND );
pkcs15infoPtr = &pkcs15infoPtr[ i ];
/* Return it to the caller */
length = pkcs15infoPtr->dataDataSize - pkcs15infoPtr->dataOffset;
if( data != NULL )
{
if( *dataLength < length )
{
assert( NOTREACHED );
return( CRYPT_ERROR_OVERFLOW );
}
memcpy( data, ( BYTE * ) pkcs15infoPtr->dataData + \
pkcs15infoPtr->dataOffset, length );
}
*dataLength = length;
return( CRYPT_OK );
}
/* If this is the first cert, reset the index value. This is pretty
ugly since this sort of value should be stored with the caller,
however there's no way to pass this back and forth in a RESOURCE_DATA
without resorting to an even uglier hack and it's safe since this
attribute is only ever read for the config keyset */
if( dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT )
trustedCertIndex = 0;
/* If we're being asked for a trusted cert, find the first or next one */
while( trustedCertIndex < MAX_PKCS15_OBJECTS )
{
if( pkcs15infoPtr[ trustedCertIndex ].implicitTrust )
{
const int length =
pkcs15infoPtr[ trustedCertIndex ].certDataSize - \
pkcs15infoPtr[ trustedCertIndex ].certOffset;
int status = CRYPT_OK;
assert( isWritePtr( data, *dataLength ) );
if( *dataLength < length )
{
assert( NOTREACHED );
status = CRYPT_ERROR_OVERFLOW;
}
else
memcpy( data,
( BYTE * ) pkcs15infoPtr[ trustedCertIndex ].certData + \
pkcs15infoPtr[ trustedCertIndex ].certOffset,
length );
*dataLength = length;
trustedCertIndex++; /* Move on to the next cert */
return( status );
}
trustedCertIndex++;
}
return( CRYPT_ERROR_NOTFOUND );
}
/* Read key data from a PKCS #15 collection */
static int getItemFunction( KEYSET_INFO *keysetInfo,
CRYPT_HANDLE *iCryptHandle,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
void *auxInfo, int *auxInfoLength,
const int flags )
{
CRYPT_ALGO_TYPE cryptAlgo;
CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
CRYPT_CONTEXT iCryptContext;
const PKCS15_INFO *pkcs15infoPtr;
RESOURCE_DATA msgData;
STREAM stream;
const BOOLEAN publicComponentsOnly = \
( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? TRUE : FALSE;
int pubkeyActionFlags = 0, privkeyActionFlags = 0, status;
/* If we're being asked for encoded configuration information, return it
and exit. This is a bit odd, but more valid than defining a pile of
special-case KEYMGMT_ITEM types that only exist for PKCS #15 keysets,
since these are really attributes of the keyset rather than general
key types */
if( iCryptHandle == NULL )
{
assert( keyIDtype == CRYPT_KEYID_NONE );
assert( keyID == NULL ); assert( keyIDlength == 0 );
return( getConfigItem( keysetInfo, flags, auxInfo, auxInfoLength ) );
}
assert( iCryptHandle != NULL );
assert( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_URI || \
keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_PGPKEYID || \
keyIDtype == CRYPT_IKEYID_ISSUERID );
assert( keyID != NULL ); assert( keyIDlength >= 1 );
/* Clear the return values */
*iCryptHandle = CRYPT_ERROR;
/* Locate the appropriate object in the PKCS #15 collection and make sure
the components we need are present: Either a public key or a cert for
any read, and a private key as well for a private-key read */
pkcs15infoPtr = findEntry( keysetInfo->keyData, keyIDtype,
keyID, keyIDlength, flags );
if( pkcs15infoPtr == NULL || \
( pkcs15infoPtr->pubKeyData == NULL && \
pkcs15infoPtr->certData == NULL ) )
/* There's not enough information present to get a public key or the
public portions of a private key */
return( CRYPT_ERROR_NOTFOUND );
if( !publicComponentsOnly && pkcs15infoPtr->privKeyData == NULL )
/* There's not enough information present to get a private key */
return( CRYPT_ERROR_NOTFOUND );
/* If we're just checking whether an object exists, return now. If all
we want is the key label, copy it back to the caller and exit */
if( flags & KEYMGMT_FLAG_CHECK_ONLY )
return( CRYPT_OK );
if( flags & KEYMGMT_FLAG_LABEL_ONLY )
{
*auxInfoLength = pkcs15infoPtr->labelLength;
if( auxInfo != NULL )
memcpy( auxInfo, pkcs15infoPtr->label,
pkcs15infoPtr->labelLength );
return( CRYPT_OK );
}
/* If we're reading the private key, make sure that the user has
supplied a password. This is checked by the kernel, but we perform
another check here just to be safe*/
if( !publicComponentsOnly && auxInfo == NULL )
return( CRYPT_ERROR_WRONGKEY );
/* Read the public components. If we're creating a public-key context we
create the cert or PKC context normally, if we're creating a private-
key context we create a data-only cert (if there's cert information
present) and a partial PKC context ready to accept the private key
components. If there's a cert present we take all the info we need
from the cert, otherwise we use the public-key data */
if( pkcs15infoPtr->certData != NULL )
{
/* There's a certificate present, import it and reconstruct the
public-key info from it if we're creating a partial PKC context */
status = iCryptImportCertIndirect( &iCryptContext,
keysetInfo->objectHandle, keyIDtype, keyID,
keyIDlength, publicComponentsOnly ? \
KEYMGMT_FLAG_NONE : \
KEYMGMT_FLAG_DATAONLY_CERT );
if( cryptStatusOK( status ) && !publicComponentsOnly )
{
DYNBUF pubKeyDB;
iDataCert = iCryptContext; /* We got the cert, now get the context */
status = dynCreate( &pubKeyDB, iDataCert, CRYPT_IATTRIBUTE_SPKI );
if( cryptStatusError( status ) )
return( status );
sMemConnect( &stream, dynData( pubKeyDB ),
dynLength( pubKeyDB ) );
status = iCryptReadSubjectPublicKey( &stream, &iCryptContext,
TRUE );
sMemDisconnect( &stream );
dynDestroy( &pubKeyDB );
}
}
else
{
/* There's no certificate present, create the public-key context
directly */
sMemConnect( &stream, ( BYTE * ) pkcs15infoPtr->pubKeyData + \
pkcs15infoPtr->pubKeyOffset,
pkcs15infoPtr->pubKeyDataSize - \
pkcs15infoPtr->pubKeyOffset );
status = iCryptReadSubjectPublicKey( &stream, &iCryptContext,
!publicComponentsOnly );
sMemDisconnect( &stream );
}
if( cryptStatusOK( status ) )
status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( status );
/* Get the permitted usage flags for each object type that we'll be
instantiating. If there's a public key present we apply its usage
flags to whichever PKC context we create, even if it's done indirectly
via the cert import. Since the private key can also perform the
actions of the public key, we set its action flags to the union of the
two */
if( pkcs15infoPtr->pubKeyData != NULL )
{
pubkeyActionFlags = getPermittedActions( pkcs15infoPtr->pubKeyUsage,
cryptAlgo );
if( cryptStatusError( pubkeyActionFlags ) )
status = pubkeyActionFlags;
}
if( !publicComponentsOnly )
{
privkeyActionFlags = getPermittedActions( pkcs15infoPtr->privKeyUsage,
cryptAlgo );
if( cryptStatusError( privkeyActionFlags ) )
status = privkeyActionFlags;
privkeyActionFlags |= pubkeyActionFlags;
}
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
if( iDataCert != CRYPT_ERROR )
krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
}
/* If we're only interested in the public components, set the key
permissions and exit */
if( publicComponentsOnly )
{
status = setKeyAttributes( iCryptContext, pkcs15infoPtr,
( pkcs15infoPtr->pubKeyData != NULL ) ? \
pubkeyActionFlags : CRYPT_UNUSED );
if( cryptStatusOK( status ) )
*iCryptHandle = iCryptContext;
else
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
return( status );
}
assert( ( pkcs15infoPtr->pubKeyData != NULL || \
pkcs15infoPtr->certData != NULL ) && \
pkcs15infoPtr->privKeyData != NULL );
/* Set the key label. We have to do this before we load the key or the
key load will be blocked by the kernel */
setMessageData( &msgData, ( void * ) pkcs15infoPtr->label,
pkcs15infoPtr->labelLength );
krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_LABEL );
/* Read the private key header fields and import the private key */
sMemConnect( &stream,
( BYTE * ) pkcs15infoPtr->privKeyData + \
pkcs15infoPtr->privKeyOffset,
pkcs15infoPtr->privKeyDataSize - \
pkcs15infoPtr->privKeyOffset );
status = readConstructed( &stream, NULL, CTAG_OV_DIRECTPROTECTED );
if( cryptStatusOK( status ) )
status = readEncryptedKey( &stream, iCryptContext, auxInfo,
*auxInfoLength );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
if( iDataCert != CRYPT_ERROR )
krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
return( status );
}
/* Connect the data-only certificate object to the context if it exists.
This is an internal object used only by the context so we tell the
kernel to mark it as owned by the context only */
if( iDataCert != CRYPT_ERROR )
krnlSendMessage( iCryptContext, IMESSAGE_SETDEPENDENT, &iDataCert,
SETDEP_OPTION_NOINCREF );
/* Set the permitted action flags */
status = setKeyAttributes( iCryptContext, pkcs15infoPtr,
privkeyActionFlags );
if( cryptStatusError( status ) )
{
krnlSendNotifier( iCryptContext, MESSAGE_DECREFCOUNT );
return( status );
}
*iCryptHandle = iCryptContext;
return( CRYPT_OK );
}
/* Fetch a sequence of certs. These functions are called indirectly by the
certificate code to fetch the first and subsequent certs in a chain */
static int getItem( PKCS15_INFO *pkcs15info, CRYPT_CERTIFICATE *iCertificate,
int *stateInfo, const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const KEYMGMT_ITEM_TYPE itemType, const int options )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
const PKCS15_INFO *pkcs15infoPtr;
int status;
/* Find the appropriate entry based on the ID */
pkcs15infoPtr = findEntry( pkcs15info, keyIDtype, keyID, keyIDlength,
options );
if( pkcs15infoPtr == NULL )
{
*stateInfo = CRYPT_ERROR;
return( CRYPT_ERROR_NOTFOUND );
}
*stateInfo = pkcs15infoPtr->index;
/* Import the cert */
setMessageCreateObjectIndirectInfo( &createInfo,
( BYTE * ) pkcs15infoPtr->certData + pkcs15infoPtr->certOffset,
pkcs15infoPtr->certDataSize - pkcs15infoPtr->certOffset,
( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \
CERTFORMAT_DATAONLY : CRYPT_CERTTYPE_CERTIFICATE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT_INDIRECT, &createInfo,
OBJECT_TYPE_CERTIFICATE );
if( cryptStatusOK( status ) )
{
*iCertificate = createInfo.cryptHandle;
if( pkcs15infoPtr->validFrom == 0 )
/* Perform an opportunistic update of the validity info if
this hasn't already been set */
getValidityInfo( pkcs15info, createInfo.cryptHandle );
}
return( status );
}
static int getFirstItemFunction( KEYSET_INFO *keysetInfo,
CRYPT_CERTIFICATE *iCertificate,
int *stateInfo,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const KEYMGMT_ITEM_TYPE itemType,
const int options )
{
assert( stateInfo != NULL );
assert( keyIDtype != CRYPT_KEYID_NONE && keyID != NULL && \
keyIDlength > 0 );
assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
return( getItem( keysetInfo->keyData, iCertificate, stateInfo,
keyIDtype, keyID, keyIDlength, itemType, options ) );
}
static int getNextItemFunction( KEYSET_INFO *keysetInfo,
CRYPT_CERTIFICATE *iCertificate,
int *stateInfo, const int options )
{
PKCS15_INFO *pkcs15infoPtr = keysetInfo->keyData;
assert( stateInfo != NULL );
assert( ( *stateInfo >= 0 && *stateInfo < MAX_PKCS15_OBJECTS ) || \
*stateInfo == CRYPT_ERROR );
/* If the previous cert was the last one, there's nothing left to fetch */
if( *stateInfo == CRYPT_ERROR )
return( CRYPT_ERROR_NOTFOUND );
/* Find the cert for which the subjectNameID matches this cert's
issuerNameID */
return( getItem( pkcs15infoPtr, iCertificate, stateInfo,
CRYPT_KEYIDEX_SUBJECTNAMEID,
pkcs15infoPtr[ *stateInfo ].issuerNameID,
pkcs15infoPtr[ *stateInfo ].issuerNameIDlength,
KEYMGMT_ITEM_PUBLICKEY, options ) );
}
/****************************************************************************
* *
* Keyset Access Routines *
* *
****************************************************************************/
void initPKCS15read( KEYSET_INFO *keysetInfo )
{
keysetInfo->getItemFunction = getItemFunction;
keysetInfo->getFirstItemFunction = getFirstItemFunction;
keysetInfo->getNextItemFunction = getNextItemFunction;
}
#endif /* USE_PKCS15 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -