📄 pkcs15_rd.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #15 Read Routines *
* Copyright Peter Gutmann 1996-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "pkcs15.h"
#include "asn1.h"
#include "asn1_ext.h"
#else
#include "crypt.h"
#include "keyset/keyset.h"
#include "keyset/pkcs15.h"
#include "misc/asn1.h"
#include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */
#ifdef USE_PKCS15
/* OID information used to read a PKCS #15 file */
static const OID_INFO FAR_BSS dataOIDinfo[] = {
{ OID_CMS_DATA, CRYPT_OK },
{ NULL, 0 }, { NULL, 0 }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Translate the PKCS #15 usage flags into cryptlib permitted actions. The
PKCS #11 use of the 'derive' flag to mean 'allow key agreement' is a bit
of a kludge, we map it to allowing keyagreement export and import if it's
a key-agreement algorithm, if there are further constraints they'll be
handled by the attached certificate. The PKCS #15 nonRepudiation flag
doesn't have any definition so we can't do anything with it, although we
may need to translate it to allowing signing and/or verification if
implementations appear that expect it to be used this way */
CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
static int getPermittedActions( IN_FLAGS( PKCS15_USAGE ) const int usageFlags,
IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,
OUT_FLAGS_Z( ACTION ) int *usage )
{
int actionFlags = ACTION_PERM_NONE_ALL;
REQUIRES( usageFlags >= PKSC15_USAGE_FLAG_NONE && \
usageFlags < PKCS15_USAGE_FLAG_MAX );
REQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
cryptAlgo <= CRYPT_ALGO_LAST_PKC );
/* Clear return value */
*usage = ACTION_PERM_NONE;
if( usageFlags & ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_WRAP ) )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
if( usageFlags & ( PKCS15_USAGE_DECRYPT | PKCS15_USAGE_UNWRAP ) )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
if( usageFlags & PKCS15_USAGE_SIGN )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
if( usageFlags & PKCS15_USAGE_VERIFY )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
if( isKeyxAlgo( cryptAlgo ) && ( usageFlags & PKCS15_USAGE_DERIVE ) )
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
if( cryptAlgo == CRYPT_ALGO_RSA )
{
/* If there are any restrictions on the key usage we have to make it
internal-only because of RSA's signature/encryption duality */
if( !( ( usageFlags & ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_WRAP | \
PKCS15_USAGE_DECRYPT | PKCS15_USAGE_UNWRAP ) ) && \
( usageFlags & ( PKCS15_USAGE_SIGN | PKCS15_USAGE_VERIFY ) ) ) )
actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
}
else
{
/* Because of the special-case data formatting requirements for DLP
algorithms we make the usage internal-only */
actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
}
if( actionFlags <= ACTION_PERM_NONE_ALL )
return( CRYPT_ERROR_PERMISSION );
*usage = actionFlags;
return( CRYPT_OK );
}
/* Copy any new object ID information that we've just read across to the
object information */
STDC_NONNULL_ARG( ( 1, 2 ) ) \
static void copyObjectIdInfo( INOUT PKCS15_INFO *pkcs15infoPtr,
const PKCS15_INFO *pkcs15objectInfo )
{
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );
/* 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( pkcs15objectInfo->keyIDlength > 0 && \
( 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 > 0 )
{
memcpy( pkcs15infoPtr->iAndSID, pkcs15objectInfo->iAndSID,
pkcs15objectInfo->iAndSIDlength );
pkcs15infoPtr->iAndSIDlength = pkcs15objectInfo->iAndSIDlength;
}
if( pkcs15objectInfo->subjectNameIDlength > 0 )
{
memcpy( pkcs15infoPtr->subjectNameID, pkcs15objectInfo->subjectNameID,
pkcs15objectInfo->subjectNameIDlength );
pkcs15infoPtr->subjectNameIDlength = pkcs15objectInfo->subjectNameIDlength;
}
if( pkcs15objectInfo->issuerNameIDlength > 0 )
{
memcpy( pkcs15infoPtr->issuerNameID, pkcs15objectInfo->issuerNameID,
pkcs15objectInfo->issuerNameIDlength );
pkcs15infoPtr->issuerNameIDlength = pkcs15objectInfo->issuerNameIDlength;
}
if( pkcs15objectInfo->pgp2KeyIDlength > 0 )
{
memcpy( pkcs15infoPtr->pgp2KeyID, pkcs15objectInfo->pgp2KeyID,
pkcs15objectInfo->pgp2KeyIDlength );
pkcs15infoPtr->pgp2KeyIDlength = pkcs15objectInfo->pgp2KeyIDlength;
}
if( pkcs15objectInfo->openPGPKeyIDlength > 0 )
{
memcpy( pkcs15infoPtr->openPGPKeyID, pkcs15objectInfo->openPGPKeyID,
pkcs15objectInfo->openPGPKeyIDlength );
pkcs15infoPtr->openPGPKeyIDlength = pkcs15objectInfo->openPGPKeyIDlength;
}
}
/* Copy any new object payload information that we've just read across to
the object information */
STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int copyObjectPayloadInfo( INOUT PKCS15_INFO *pkcs15infoPtr,
const PKCS15_INFO *pkcs15objectInfo,
IN_BUFFER( objectLength ) const void *object,
IN_LENGTH_SHORT const int objectLength,
IN_ENUM( PKCS15_OBJECT ) \
const PKCS15_OBJECT_TYPE type )
{
assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( object, objectLength ) );
REQUIRES( objectLength > 0 && objectLength < MAX_INTLENGTH_SHORT );
REQUIRES( type > PKCS15_OBJECT_NONE && type < PKCS15_OBJECT_LAST );
switch( type )
{
case PKCS15_OBJECT_PUBKEY:
pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
pkcs15infoPtr->pubKeyData = ( void * ) object;
pkcs15infoPtr->pubKeyDataSize = objectLength;
pkcs15infoPtr->pubKeyOffset = pkcs15objectInfo->pubKeyOffset;
pkcs15infoPtr->pubKeyUsage = pkcs15objectInfo->pubKeyUsage;
break;
case PKCS15_OBJECT_PRIVKEY:
pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
pkcs15infoPtr->privKeyData = ( void * ) object;
pkcs15infoPtr->privKeyDataSize = objectLength;
pkcs15infoPtr->privKeyOffset = pkcs15objectInfo->privKeyOffset;
pkcs15infoPtr->privKeyUsage = pkcs15objectInfo->privKeyUsage;
break;
case PKCS15_OBJECT_CERT:
if( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )
pkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;
pkcs15infoPtr->certData = ( void * ) object;
pkcs15infoPtr->certDataSize = objectLength;
pkcs15infoPtr->certOffset = pkcs15objectInfo->certOffset;
pkcs15infoPtr->trustedUsage = pkcs15objectInfo->trustedUsage;
pkcs15infoPtr->implicitTrust = pkcs15objectInfo->implicitTrust;
break;
case PKCS15_OBJECT_SECRETKEY:
/* We don't try and return an error for this, it's not something
that we can make use of but if it's ever reached it just ends
up as an empty (non-useful) object entry */
assert( DEBUG_WARN );
break;
case PKCS15_OBJECT_DATA:
pkcs15infoPtr->type = PKCS15_SUBTYPE_DATA;
pkcs15infoPtr->dataType = pkcs15objectInfo->dataType;
pkcs15infoPtr->dataData = ( void * ) object;
pkcs15infoPtr->dataDataSize = objectLength;
pkcs15infoPtr->dataOffset = pkcs15objectInfo->dataOffset;
break;
default:
/* We don't try and return an error for this, it's not something
that we can make use of but if it's ever reached it just ends
up as an empty (non-useful) object entry */
assert( DEBUG_WARN );
break;
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Read Public Key Components *
* *
****************************************************************************/
/* Read public-key components from a PKCS #15 object entry */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 7, 8, 9, 10, 11 ) ) \
int readPublicKeyComponents( const PKCS15_INFO *pkcs15infoPtr,
IN_HANDLE const CRYPT_KEYSET iCryptKeysetCallback,
IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,
IN_BUFFER( keyIDlength ) const void *keyID,
IN_LENGTH_KEYID const int keyIDlength,
const BOOLEAN publicComponentsOnly,
OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContextPtr,
OUT_HANDLE_OPT CRYPT_CERTIFICATE *iDataCertPtr,
OUT_FLAGS_Z( ACTION ) int *pubkeyActionFlags,
OUT_FLAGS_Z( ACTION ) int *privkeyActionFlags,
INOUT ERROR_INFO *errorInfo )
{
CRYPT_ALGO_TYPE cryptAlgo;
CRYPT_CONTEXT iCryptContext;
CRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;
STREAM stream;
int status;
assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
assert( isReadPtr( keyID, keyIDlength ) );
assert( isWritePtr( iCryptContextPtr, sizeof( CRYPT_CONTEXT ) ) );
assert( isWritePtr( iDataCertPtr, sizeof( CRYPT_CERTIFICATE ) ) );
assert( isWritePtr( pubkeyActionFlags, sizeof( int ) ) );
assert( isWritePtr( privkeyActionFlags, sizeof( int ) ) );
REQUIRES( isHandleRangeValid( iCryptKeysetCallback ) );
REQUIRES( keyIDtype == CRYPT_KEYID_NAME || \
keyIDtype == CRYPT_KEYID_URI || \
keyIDtype == CRYPT_IKEYID_KEYID || \
keyIDtype == CRYPT_IKEYID_PGPKEYID || \
keyIDtype == CRYPT_IKEYID_ISSUERID );
REQUIRES( keyIDlength >= MIN_NAME_LENGTH && \
keyIDlength < MAX_ATTRIBUTE_SIZE );
REQUIRES( errorInfo != NULL );
/* Clear return values */
*iCryptContextPtr = CRYPT_ERROR;
*iDataCertPtr = CRYPT_ERROR;
*pubkeyActionFlags = *privkeyActionFlags = ACTION_PERM_NONE;
/* If we're creating a public-key context we create the certificate or
PKC context normally, if we're creating a private-key context we
create a data-only certificate (if there's certificate information
present) and a partial PKC context ready to accept the private key
components. If there's a certificate present then we take all of the
information that we need from the certificate, otherwise we use the
public-key data */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -