dbxpk15.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,715 行 · 第 1/5 页
C
1,715 行
/****************************************************************************
* *
* cryptlib PKCS #15 Routines *
* Copyright Peter Gutmann 1996-2002 *
* *
****************************************************************************/
/* The format used to protect the private key components is a standard
cryptlib envelope, however for various reasons the required enveloping
functionality is duplicated here:
1. It's somewhat inelegant to use the heavyweight enveloping routines to
wrap up 100 bytes of data.
2. The enveloping code is enormous and complex, especially when extra
sections like zlib and PGP and S/MIME support are factored in. This
makes it difficult to compile a stripped-down version of cryptlib,
since private key storage will require all the enveloping code to be
included.
3. Since the enveloping code is general-purpose, it doesn't allow very
precise control over the data being processed. Specifically, it's
necessary to write the private key components to a buffer in plaintext
form, which isn't permitted by the cryptlib kernel.
For these reasons this module includes the code to process minimal
(password-encrypted data) envelopes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
#include "crypt.h"
#include "keyset.h"
#include "asn1.h"
#include "asn1objs.h"
#include "asn1oid.h"
#elif defined( INC_CHILD )
#include "../crypt.h"
#include "keyset.h"
#include "../keymgmt/asn1.h"
#include "../keymgmt/asn1objs.h"
#include "../keymgmt/asn1oid.h"
#else
#include "crypt.h"
#include "misc/keyset.h"
#include "keymgmt/asn1.h"
#include "keymgmt/asn1objs.h"
#include "keymgmt/asn1oid.h"
#endif /* Compiler-specific includes */
/* A PKCS #15 file can contain multiple key and cert objects, before we do
anything with the file we scan it and build an in-memory index of what's
present. When we perform an update we just flush the in-memory
information to disk.
Each file can contain information for multiple personalities (although
it's extremely unlikely to contain more than one or two), we allow a
maximum of MAX_PKCS15_OBJECTS per file in order to discourage them from
being used as general-purpose public-key keysets, which they're not really
intended for. A setting of 32 objects consumes ~4K of memory (32 x ~128),
so we choose that as the limit */
#define MAX_PKCS15_OBJECTS 32
/* Usually a PKCS #15 personality consists of a collection of related PKCS
#15 objects (typically a public and private key and a cert), but sometimes
we have personalities which consist only of a cert and little other
information (for example a trusted CA root cert, which contains no user-
supplied information such as a label). The following types of personality
are handled for PKCS #15 files */
typedef enum {
PKCS15_SUBTYPE_NONE, /* Non-personality */
PKCS15_SUBTYPE_NORMAL, /* Standard personality, keys+optional cert */
PKCS15_SUBTYPE_CERT, /* Standalone cert */
PKCS15_SUBTYPE_SECRETKEY, /* Secret key */
PKCS15_SUBTYPE_DATA, /* Pre-encoded cryptlib-specific data */
PKCS15_SUBTYPE_LAST
} PKCS15_SUBTYPE;
/* The following structure contains the the information for one personality,
which covers one or more of a private key, public key, and cert */
typedef struct {
/* General information on the personality: The subtype, a local unique
identifier which is easier to manage than the iD, the PKCS #15
object label, and the PKCS #15 object ID and key ID (which is usually
the same as the object ID) */
PKCS15_SUBTYPE type; /* Personality subtype */
int index; /* Unique value for this personality */
char label[ CRYPT_MAX_TEXTSIZE ];/* PKCS #15 object label */
int labelLength;
BYTE iD[ CRYPT_MAX_HASHSIZE ], keyID[ CRYPT_MAX_HASHSIZE ];
int iDlength, keyIDlength; /* PKCS #15 object ID and key ID */
/* Certificate-related ID information: Hash of the issuer name, subject
name, and issuerAndSerialNumber, and PGP key IDs */
BYTE iAndSID[ KEYID_SIZE ], subjectNameID[ KEYID_SIZE ];
BYTE issuerNameID[ KEYID_SIZE ];
BYTE pgp2KeyID[ PGP_KEYID_SIZE ], openPGPKeyID[ PGP_KEYID_SIZE ];
int iAndSIDlength, subjectNameIDlength, issuerNameIDlength;
int pgp2KeyIDlength, openPGPKeyIDlength;
/* Key/cert object data */
void *pubKeyData, *privKeyData, *certData; /* Encoded object data */
int pubKeyDataSize, privKeyDataSize, certDataSize;
int pubKeyOffset, privKeyOffset, certOffset;
/* Offset of payload in data */
int pubKeyUsage, privKeyUsage; /* Permitted usage for the key */
int trustedUsage; /* Usage which key is trusted for */
BOOLEAN implicitTrust; /* Whether cert is implicitly trusted */
time_t validFrom, validTo; /* Cert validity information */
/* Data object data */
CRYPT_ATTRIBUTE_TYPE dataType; /* Type of the encoded object data */
void *dataData; /* Encoded object data */
int dataDataSize, dataOffset;
} PKCS15_INFO;
/* The types of object we can find in a PKCS #15 file. These are also used
as context-specific object tags */
typedef enum { PKCS15_OBJECT_PRIVKEY, PKCS15_OBJECT_PUBKEY,
PKCS15_OBJECT_TRUSTEDPUBKEY, PKCS15_OBJECT_SECRETKEY,
PKCS15_OBJECT_CERT, PKCS15_OBJECT_TRUSTEDCERT,
PKCS15_OBJECT_USEFULCERT, PKCS15_OBJECT_DATA,
PKCS15_OBJECT_AUTH, PKCS15_OBJECT_LAST } PKCS15_OBJECT_TYPE;
/* The types of key identifiers we can find attached to an object */
enum { PKCS15_KEYID_NONE, PKCS15_KEYID_ISSUERANDSERIALNUMBER,
PKCS15_KEYID_SUBJECTKEYIDENTIFIER, PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH,
PKCS15_KEYID_SUBJECTKEYHASH, PKCS15_KEYID_ISSUERKEYHASH,
PKCS15_KEYID_ISSUERNAMEHASH, PKCS15_KEYID_SUBJECTNAMEHASH,
PKCS15_KEYID_PGP2, PKCS15_KEYID_OPENPGP };
/* PKCS #15 key usage flags, a complex mixture of PKCS #11 and some bits of
X.509 */
#define PKCS15_USAGE_ENCRYPT 0x0001
#define PKCS15_USAGE_DECRYPT 0x0002
#define PKCS15_USAGE_SIGN 0x0004
#define PKCS15_USAGE_SIGNRECOVER 0x0008
#define PKCS15_USAGE_WRAP 0x0010
#define PKCS15_USAGE_UNWRAP 0x0020
#define PKCS15_USAGE_VERIFY 0x0040
#define PKCS15_USAGE_VERIFYRECOVER 0x0080
#define PKCS15_USAGE_DERIVE 0x0100
#define PKCS15_USAGE_NONREPUDIATION 0x0200
/* PKCS #15 flags which can't be set for public keys. We use this as a mask
to derive public-key flags from private key ones */
#define PUBKEY_USAGE_MASK ~( PKCS15_USAGE_DECRYPT | PKCS15_USAGE_SIGN | \
PKCS15_USAGE_SIGNRECOVER | PKCS15_USAGE_UNWRAP )
/* PKCS #15 usage types for encryption and signature keys. We use these when
looking specifically for signing or encryption keys */
#define ENCR_USAGE_MASK ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_DECRYPT | \
PKCS15_USAGE_WRAP | PKCS15_USAGE_UNWRAP )
#define SIGN_USAGE_MASK ( PKCS15_USAGE_SIGN | PKCS15_USAGE_SIGNRECOVER | \
PKCS15_USAGE_VERIFY | PKCS15_USAGE_VERIFYRECOVER | \
PKCS15_USAGE_NONREPUDIATION )
/* The access flags for various types of key objects. For a public key we
set 'extractable', for a private key we set 'sensitive',
'alwaysSensitive', and 'neverExtractable' */
#define KEYATTR_ACCESS_PUBLIC 0x02 /* 00010b */
#define KEYATTR_ACCESS_PRIVATE 0x0D /* 01101b */
/* Context-specific tags for the PublicKeyInfo record */
enum { CTAG_PK_CERTIFICATE, CTAG_PK_CERTCHAIN };
/* Context-specific tag for the EncryptedData record (this is normally
defined in env_asn1.c) */
#define CTAG_CI_ENCRYPTED 1
/* Context-specific tags for the PKCS #15 object record */
enum { CTAG_OB_SUBCLASSATTR, CTAG_OB_TYPEATTR };
/* Context-specific tags for the PKCS #15 object value record */
enum { CTAG_OV_DIRECT, CTAG_OV_DUMMY, CTAG_OV_DIRECTPROTECTED };
/* Context-specific tags for the PKCS #15 class attributes record */
enum { CTAG_CA_DUMMY, CTAG_CA_TRUSTED_USAGE, CTAG_CA_IDENTIFIERS,
CTAG_CA_TRUSTED_IMPLICIT, CTAG_CA_VALIDTO };
/* Context-specific tags for the PKCS #15 data objects record */
enum { CTAG_DO_EXTERNALDO, CTAG_DO_OIDDO };
/* OID information used to read a PKCS #15 file */
static const OID_SELECTION keyFileOIDselection[] = {
{ OID_PKCS15_CONTENTTYPE, 0, 0, CRYPT_OK },
{ NULL, 0, 0, 0 }
};
static const OID_SELECTION dataOIDselection[] = {
{ OID_CMS_DATA, CRYPT_UNUSED, CRYPT_UNUSED, CRYPT_OK },
{ NULL, 0, 0, 0 }
};
static const OID_SELECTION cryptlibDataOIDselection[] = {
{ OID_CRYPTLIB_CONFIGDATA, CRYPT_UNUSED, CRYPT_UNUSED,
CRYPT_IATTRIBUTE_CONFIGDATA },
{ OID_CRYPTLIB_USERINDEX, CRYPT_UNUSED, CRYPT_UNUSED,
CRYPT_IATTRIBUTE_USERINDEX },
{ OID_CRYPTLIB_USERINFO, CRYPT_UNUSED, CRYPT_UNUSED,
CRYPT_IATTRIBUTE_USERINFO },
{ NULL, 0, 0, 0 }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Locate an object based on an ID. Since PKCS #15 uses more key ID types
than are used by the rest of cryptlib, we extend the standard range with
PKCS15-only types */
#define CRYPT_KEYIDEX_SUBJECTNAMEID CRYPT_KEYID_LAST
static PKCS15_INFO *findEntry( const PKCS15_INFO *pkcs15info,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const int requestedUsage )
{
const int compositeUsage = pkcs15info->pubKeyUsage | \
pkcs15info->privKeyUsage;
int i;
assert( keyID != NULL );
assert( keyIDlength >= 0 );
assert( ( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS ) != \
KEYMGMT_MASK_USAGEOPTIONS );
/* If there's no ID to search on, don't try and do anything (this can
occur when we're trying to build a chain and the necessary chaining
data isn't present) */
if( keyIDlength == 0 )
return( NULL );
/* Try and locate the appropriate object in the PKCS #15 collection */
for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
{
/* If there's an explicit usage requested, make sure the key usage
matches this. This can get slightly complex since the advertised
usage isn't necessarily the same as the usage permitted by the
associated cert (PKCS #11 apps are particularly good at setting
bogus usage types) and the overall result can be further
influenced by trusted usage settings, all we check for here is
an indicated usage for the key matching the requested usage */
if( ( requestedUsage & KEYMGMT_FLAG_USAGE_CRYPT ) && \
!( compositeUsage & ENCR_USAGE_MASK ) )
continue;
if( ( requestedUsage & KEYMGMT_FLAG_USAGE_SIGN ) && \
!( compositeUsage & SIGN_USAGE_MASK ) )
continue;
/* Check for a match based on the ID type */
switch( keyIDtype )
{
case CRYPT_KEYID_NAME:
case CRYPT_KEYID_EMAIL:
if( pkcs15info[ i ].labelLength && \
keyIDlength == pkcs15info[ i ].labelLength && \
!strnicmp( pkcs15info[ i ].label, keyID, keyIDlength ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
break;
case CRYPT_IKEYID_ID:
if( keyIDlength == pkcs15info[ i ].iDlength && \
!memcmp( keyID, pkcs15info[ i ].iD, keyIDlength ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
break;
case CRYPT_IKEYID_KEYID:
if( keyIDlength == pkcs15info[ i ].keyIDlength && \
!memcmp( keyID, pkcs15info[ i ].keyID, keyIDlength ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
break;
case CRYPT_IKEYID_PGPKEYID:
if( keyIDlength == pkcs15info[ i ].pgp2KeyIDlength && \
!memcmp( keyID, pkcs15info[ i ].pgp2KeyID, keyIDlength ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
break;
case CRYPT_IKEYID_ISSUERID:
if( keyIDlength == pkcs15info[ i ].iAndSIDlength && \
!memcmp( keyID, pkcs15info[ i ].iAndSID, keyIDlength ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
break;
case CRYPT_KEYIDEX_SUBJECTNAMEID:
if( keyIDlength == pkcs15info[ i ].subjectNameIDlength && \
!memcmp( keyID, pkcs15info[ i ].subjectNameID, keyIDlength ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
break;
default:
assert( NOTREACHED );
}
}
/* If we're trying to match on the PGP key ID and didn't find anything,
retry it using the first PGP_KEYID_SIZE bytes of the object ID. This
is necessary because calculation of the OpenPGP ID requires the
presence of data which isn't present in non-PGP keys, so we can't
calculate a real OpenPGP ID but have to use the next-best thing */
if( keyIDtype == CRYPT_IKEYID_PGPKEYID )
for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
if( pkcs15info[ i ].iDlength >= PGP_KEYID_SIZE && \
!memcmp( keyID, pkcs15info[ i ].iD, PGP_KEYID_SIZE ) )
return( ( PKCS15_INFO * ) &pkcs15info[ i ] );
return( NULL );
}
/* Free object entries */
static void pkcs15freeEntry( PKCS15_INFO *pkcs15info )
{
if( pkcs15info->pubKeyData != NULL )
{
zeroise( pkcs15info->pubKeyData, pkcs15info->pubKeyDataSize );
free( pkcs15info->pubKeyData );
}
if( pkcs15info->privKeyData != NULL )
{
zeroise( pkcs15info->privKeyData, pkcs15info->privKeyDataSize );
free( pkcs15info->privKeyData );
}
if( pkcs15info->certData != NULL )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?