📄 cryptcfg.c
字号:
/****************************************************************************
* *
* cryptlib Configuration Routines *
* Copyright Peter Gutmann 1994-2005 *
* *
****************************************************************************/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
#ifdef INC_ALL
#include "asn1.h"
#else
#include "misc/asn1.h"
#endif /* Compiler-specific includes */
/* Prototypes for cert trust management functions */
int addTrustEntry( void *trustInfoPtr, const CRYPT_CERTIFICATE cryptCert,
const void *certObject, const int certObjectLength );
int enumTrustedCerts( void *trustInfoPtr, const CRYPT_CERTIFICATE iCryptCtl,
const CRYPT_KEYSET iCryptKeyset );
/****************************************************************************
* *
* Configuration Options *
* *
****************************************************************************/
/* Configuration option types */
typedef enum {
OPTION_NONE, /* Non-option */
OPTION_STRING, /* Literal string */
OPTION_NUMERIC, /* Numeric value */
OPTION_BOOLEAN /* Boolean flag */
} OPTION_TYPE;
/* The configuration options. These are broken up into two parts, the fixed
default values that are shared across all cryptlib operations and the
variable values that are variable for each user object.
Alongside the CRYPT_ATTRIBUTE_TYPE we store a persistant index value for
the option that always stays the same even if the attribute type changes.
This avoids the need to change the config file every time an attribute is
added or deleted. Some options can't be made persistent, for these the
index value is set to CRYPT_UNUSED */
typedef struct {
const CRYPT_ATTRIBUTE_TYPE option;/* Attribute ID */
const OPTION_TYPE type; /* Option type */
const int index; /* Index value for this option */
const char FAR_BSS *strDefault; /* Default if it's a string option */
const int intDefault; /* Default if it's a numeric/boolean */
} FIXED_OPTION_INFO;
typedef struct {
char *strValue; /* Value if it's a string option */
int intValue; /* Value if it's a numeric/boolean */
BOOLEAN dirty; /* Whether option has been changed */
} OPTION_INFO;
#define MK_OPTION( option, value, index ) \
{ option, OPTION_NUMERIC, index, NULL, value }
#define MK_OPTION_B( option, value, index ) \
{ option, OPTION_BOOLEAN, index, NULL, value }
#define MK_OPTION_S( option, value, index ) \
{ option, OPTION_STRING, index, value, 0 }
#define MK_OPTION_NONE() \
{ CRYPT_ATTRIBUTE_NONE, OPTION_NONE, CRYPT_UNUSED, NULL, 0 }
static const FAR_BSS FIXED_OPTION_INFO fixedOptionInfo[] = {
/* Dummy entry for CRYPT_ATTRIBUTE_NONE */
MK_OPTION_NONE(),
/* cryptlib information (read-only) */
MK_OPTION_S( CRYPT_OPTION_INFO_DESCRIPTION, "cryptlib security toolkit", CRYPT_UNUSED ),
MK_OPTION_S( CRYPT_OPTION_INFO_COPYRIGHT, "Copyright Peter Gutmann, Eric Young, OpenSSL, 1994-2005", CRYPT_UNUSED ),
MK_OPTION( CRYPT_OPTION_INFO_MAJORVERSION, 3, CRYPT_UNUSED ),
MK_OPTION( CRYPT_OPTION_INFO_MINORVERSION, 2, CRYPT_UNUSED ),
MK_OPTION( CRYPT_OPTION_INFO_STEPPING, 2, CRYPT_UNUSED ),
/* Context options, base = 0 */
/* Algorithm = Conventional encryption/hash/MAC options */
MK_OPTION( CRYPT_OPTION_ENCR_ALGO, CRYPT_ALGO_3DES, 0 ),
MK_OPTION( CRYPT_OPTION_ENCR_HASH, CRYPT_ALGO_SHA, 1 ),
MK_OPTION( CRYPT_OPTION_ENCR_MAC, CRYPT_ALGO_HMAC_SHA, 2 ),
/* Algorithm = PKC options */
MK_OPTION( CRYPT_OPTION_PKC_ALGO, CRYPT_ALGO_RSA, 3 ),
MK_OPTION( CRYPT_OPTION_PKC_KEYSIZE, bitsToBytes( 1024 ), 4 ),
/* Algorithm = Signature options */
MK_OPTION( CRYPT_OPTION_SIG_ALGO, CRYPT_ALGO_RSA, 5 ),
MK_OPTION( CRYPT_OPTION_SIG_KEYSIZE, bitsToBytes( 1024 ), 6 ),
/* Algorithm = Key derivation options */
MK_OPTION( CRYPT_OPTION_KEYING_ALGO, CRYPT_ALGO_SHA, 7 ),
MK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, 500, 8 ),
/* Certificate options, base = 100 */
MK_OPTION_B( CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, FALSE, 100 ),
MK_OPTION( CRYPT_OPTION_CERT_VALIDITY, 365, 101 ),
MK_OPTION( CRYPT_OPTION_CERT_UPDATEINTERVAL, 90, 102 ),
MK_OPTION( CRYPT_OPTION_CERT_COMPLIANCELEVEL, CRYPT_COMPLIANCELEVEL_STANDARD, 103 ),
MK_OPTION_B( CRYPT_OPTION_CERT_REQUIREPOLICY, TRUE, 104 ),
/* CMS options */
MK_OPTION_B( CRYPT_OPTION_CMS_DEFAULTATTRIBUTES, TRUE, 105 ),
/* Keyset options, base = 200 */
/* Keyset = LDAP options */
MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS, "inetOrgPerson", 200 ),
MK_OPTION( CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE, CRYPT_CERTTYPE_NONE, 201 ),
MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_FILTER, "(objectclass=*)", 202 ),
MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CACERTNAME, "cACertificate;binary", 203 ),
MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CERTNAME, "userCertificate;binary", 204 ),
MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CRLNAME, "certificateRevocationList;binary", 205 ),
MK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_EMAILNAME, "mail", 206 ),
/* Device options, base = 300 */
/* Device = PKCS #11 token options */
MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR01, NULL, 300 ),
MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR02, NULL, 301 ),
MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR03, NULL, 302 ),
MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR04, NULL, 303 ),
MK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR05, NULL, 304 ),
MK_OPTION_B( CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY, FALSE, 305 ),
/* Session options, base = 400 */
/* Miscellaneous options, base = 500. The network options are mostly
used by sessions, but also apply to other object types like network
keysets, so they're classed as miscellaneous options */
MK_OPTION_S( CRYPT_OPTION_NET_SOCKS_SERVER, NULL, 500 ),
MK_OPTION_S( CRYPT_OPTION_NET_SOCKS_USERNAME, NULL, 501 ),
MK_OPTION_S( CRYPT_OPTION_NET_HTTP_PROXY, NULL, 502 ),
MK_OPTION( CRYPT_OPTION_NET_CONNECTTIMEOUT, 30, 503 ),
MK_OPTION( CRYPT_OPTION_NET_READTIMEOUT, 0, 504 ),
MK_OPTION( CRYPT_OPTION_NET_WRITETIMEOUT, 2, 505 ),
MK_OPTION_B( CRYPT_OPTION_MISC_ASYNCINIT, TRUE, 506 ),
MK_OPTION_B( CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, FALSE, 507 ),
/* All options beyond this point are ephemeral and aren't stored to disk.
Remember to update the LAST_STORED_OPTION define below when adding
new options here */
/* cryptlib state information. These are special-case options that
record state information rather than a static config value. The
config-option-changed status value is updated dynamically, being set
to TRUE if any config option is changed. Writing it to FALSE commits
the changes to disk. The self-test status value is initially set to
FALSE, writing it to TRUE triggers a self-test for which the value
remains at TRUE if the test succeeds. Writing it to a particular
algorithm value tests only that algorithm */
MK_OPTION_B( CRYPT_OPTION_CONFIGCHANGED, FALSE, CRYPT_UNUSED ),
MK_OPTION( CRYPT_OPTION_SELFTESTOK, FALSE, CRYPT_UNUSED ),
/* End-of-list marker */
MK_OPTION_NONE()
};
/* The last option that's written to disk. Further options beyond this one
are ephemeral and are never written to disk */
#define LAST_STORED_OPTION CRYPT_OPTION_MISC_SIDECHANNELPROTECTION
/* The size of the variable-length config data */
#define OPTION_INFO_SIZE ( sizeof( OPTION_INFO ) * \
CRYPT_OPTION_CONFIGCHANGED - CRYPT_OPTION_FIRST )
/****************************************************************************
* *
* Set/Query Library-wide Config Options *
* *
****************************************************************************/
/* Set the value of a numeric or string option */
int setOption( OPTION_INFO *optionList, const CRYPT_ATTRIBUTE_TYPE option,
const int value )
{
const FIXED_OPTION_INFO *fixedOptionInfoPtr;
OPTION_INFO *optionInfoPtr;
/* The update of the selt-test status is performed in two phases, when we
begin the self-test it's set to an undefined value, once the self-test
completes it's set to the test result. Since there's no direct way to
differentiate an internal status update from an external attempt to do
the same thing, we disallow any attempt to update the value when it's
in the undefined state (see the comment for CRYPT_OPTION_SELFTESTOK
below), and use a write of CRYPT_OPTION_LAST to indicate an update of
the self-test status */
if( option == CRYPT_OPTION_LAST )
{
assert( optionList[ CRYPT_OPTION_SELFTESTOK - \
CRYPT_OPTION_FIRST ].intValue == CRYPT_ERROR );
optionList[ CRYPT_OPTION_SELFTESTOK - \
CRYPT_OPTION_FIRST ].intValue = value;
return( CRYPT_OK );
}
/* Get a pointer to the option information and make sure that everything
is OK */
assert( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );
optionInfoPtr = &optionList[ option - CRYPT_OPTION_FIRST ];
fixedOptionInfoPtr = &fixedOptionInfo[ option - CRYPT_OPTION_FIRST ];
assert( fixedOptionInfoPtr->type == OPTION_NUMERIC || \
fixedOptionInfoPtr->type == OPTION_BOOLEAN );
/* If the value is the same as the current one, there's nothing to do */
if( optionInfoPtr->intValue == value )
return( CRYPT_OK );
/* If we're forcing a commit by returning the config.changed flag to its
ground state, write any changed options to backing store */
if( option == CRYPT_OPTION_CONFIGCHANGED )
{
/* When a non-config option (for example a cert trust option) is
changed, then we need to write the updated config data to backing
store, but there's no way to tell that this is required because
the config options are unchanged. To allow the caller to signal
this change, they can explicitly set the config-changed setting
to TRUE (normally this is done implicitly by when another config
setting is changed). This explicit setting can only be done by
the higher-level config-update code, because the kernel blocks
any attempts to set it to a value other than FALSE */
if( value )
{
optionInfoPtr->intValue = TRUE;
return( CRYPT_OK );
}
/* Make sure that there's something to write. We do this to avoid
problems with programs that always try to update the config
(whether it's necessary or not), which can cause problems with
media with limited writeability */
if( !optionInfoPtr->intValue )
return( CRYPT_OK );
/* We don't do anything to write the config data at this level since
we currently have the user object locked and don't want to stall
all operations that depend on it while we're updating the config
data, so all we do is tell the user object to perform the
necessary operations */
return( OK_SPECIAL );
}
/* If we're forcing a self-test by changing the value of the self-test
status, perform an algorithm test */
if( option == CRYPT_OPTION_SELFTESTOK )
{
/* The self-test can take some time to complete. While it's running
we don't want to leave the user object locked since this will
block most other threads, which all eventually read some sort of
config option. To get around this problem we set the result
value to an undefined status and unlock the user object around the
call, then re-lock it and set its actual value via an update of
the pseudo-option CRYPT_OPTION_LAST once the self-test is done */
if( optionInfoPtr->intValue == CRYPT_ERROR )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -