📄 crypt.h
字号:
compiler-independant manner */
#define UNUSED( arg ) ( ( arg ) = ( arg ) )
/* Although min() and max() aren't in the ANSI standard, most stdlib.h's have
them anyway for historical reasons. Just in case they're not defined
there by some pedantic compiler (some versions of Borland C do this), we
define them here */
#ifndef max
#define max( a, b ) ( ( ( a ) > ( b ) ) ? ( ( int ) a ) : ( ( int ) b ) )
#endif /* !max */
#ifndef min
#define min( a, b ) ( ( ( a ) < ( b ) ) ? ( ( int ) a ) : ( ( int ) b ) )
#endif /* !min */
/* Macro to round a value up to the nearest multiple of a second value */
#define roundUp( size, roundSize ) \
( ( ( size ) + ( ( roundSize ) - 1 ) ) & ~( ( roundSize ) - 1 ) )
/* A macro to clear sensitive data from memory. This is somewhat easier to
use than calling memset with the second parameter 0 all the time, and
makes it obvious where sensitive data is being erased */
#define zeroise( memory, size ) memset( memory, 0, size )
/* A macro to check that a value is a possibly valid handle. This doesn't
check that the handle refers to a valid object, merely that the value is
in the range for valid handles */
#define checkHandleRange( handle ) \
( ( handle ) > NO_SYSTEM_OBJECTS - 1 && ( handle ) < MAX_OBJECTS )
/* A macro to check whether an encryption mode needs an IV or not */
#define needsIV( mode ) ( ( mode ) == CRYPT_MODE_CBC || \
( mode ) == CRYPT_MODE_CFB || \
( mode ) == CRYPT_MODE_OFB )
/* A macro to check whether an algorithm is a pure stream cipher (that is,
a real stream cipher rather than a block cipher run in a stream mode) */
#define isStreamCipher( algorithm ) ( ( algorithm ) == CRYPT_ALGO_RC4 )
/* A macro to check whether an algorithm is regarded as being (relatively)
insecure or not. This is used by some of the higher-level internal
routines which normally use the default algorithm set in the configuration
database if nothing else is explicitly specified, but which specifically
check for the weaker algorithms and use something stronger instead if a
weak algorithm is specified. This is done both for luser-proofing and to
avoid possible problems from a trojan patching the configuration
database */
#define isWeakCryptAlgo( algorithm ) ( ( algorithm ) == CRYPT_ALGO_DES || \
( algorithm ) == CRYPT_ALGO_RC4 )
/* Macros to check whether a PKC algorithm is useful for a certain purpose or
requires special-case handling */
#define isSigAlgo( algorithm ) \
( ( algorithm ) == CRYPT_ALGO_RSA || ( algorithm ) == CRYPT_ALGO_DSA || \
( algorithm ) == CRYPT_ALGO_ELGAMAL )
#define isCryptAlgo( algorithm ) \
( ( algorithm ) == CRYPT_ALGO_RSA || ( algorithm ) == CRYPT_ALGO_ELGAMAL )
#define isKeyxAlgo( algorithm ) \
( ( algorithm ) == CRYPT_ALGO_DH || ( algorithm ) == CRYPT_ALGO_KEA )
#define isDlpAlgo( algorithm ) \
( ( algorithm ) == CRYPT_ALGO_DSA || ( algorithm ) == CRYPT_ALGO_ELGAMAL || \
( algorithm ) == CRYPT_ALGO_DH || ( algorithm ) == CRYPT_ALGO_KEA )
/* The EOL convention used when outputting text */
#if defined( __MSDOS16__ ) || defined( __MSDOS32__ ) || \
defined( __WINDOWS__ ) || defined( __OS2__ )
#define EOL "\r\n"
#define EOL_LEN 2
#elif defined( __UNIX__ ) || defined( __BEOS__ ) || defined( __AMIGA__ ) || \
defined( __IBM4758__ ) || defined( __TANDEM__ ) || defined( __VMCMS__ )
#define EOL "\n"
#define EOL_LEN 1
#elif defined( __MAC__ )
#define EOL "\r"
#define EOL_LEN 1
#else
#error You need to add the OS-specific define to enable end-of-line handling
#endif /* OS-specific EOL markers */
/* Clear/set object error information */
#define clearErrorInfo( objectInfoPtr ) \
{ \
objectInfoPtr->errorLocus = CRYPT_ATTRIBUTE_NONE; \
objectInfoPtr->errorType = CRYPT_OK; \
}
#define setErrorInfo( objectInfoPtr, locus, type ) \
{ \
objectInfoPtr->errorLocus = locus; \
objectInfoPtr->errorType = type; \
}
/****************************************************************************
* *
* Internal API Functions *
* *
****************************************************************************/
/* The data formats for recipient (key transport) and signature types. These
are an extension of the externally-visible cryptlib formats and are needed
for things like X.509 signatures and various secure session protocols
which wrap stuff other than straight keys up using a KEK. Note the non-
orthogonal handling of reading/writing CMS signatures, this is needed
because creating a CMS signature involves adding assorted additional data
like iAndS and signed attributes which present too much information to
pass into a basic writeSignature() call */
typedef enum {
RECIPIENT_NONE, /* No recipient type */
RECIPIENT_CRYPTLIB, /* keyID + algoID + OCTET STRING */
RECIPIENT_CMS /* iAndS + algoID + OCTET STRING */
} RECIPIENT_TYPE;
typedef enum {
SIGNATURE_NONE, /* No signature type */
SIGNATURE_RAW, /* Raw signature data */
SIGNATURE_PGP, /* Signature as PGP MPIs */
SIGNATURE_X509, /* algoID + BIT STRING */
SIGNATURE_CMS, /* sigAlgoID + OCTET STRING (write) */
/* iAndS + hAlgoID + sAlgoID + OCTET STRING (read) */
SIGNATURE_CRYPTLIB /* keyID + hashAlgoID + sigAlgoID + OCTET STRING */
} SIGNATURE_TYPE;
/* When importing certs for internal use we occasionally need to be able to
handle things which aren't normal certs. The following values tell the
cert import code to handle data formats which aren't quite the normal
certs or cert chains. CERTFORMAT_DATAONLY is a special-case value which
doesn't specifically contain a data format hint but indicates that the
certificate should be instantiated without creating a corresponding
context to contain the associated public key. This value is used by certs
contained in cert chains, where only the leaf cert actually needs to have
a context instantiated. Note that CERTFORMAT_NORMAL must be the first
value because it's the default setting (0) used when sending create
object messages */
typedef enum {
CERTFORMAT_NORMAL, /* Default format type */
CERTFORMAT_DATAONLY, /* Data-only cert */
CERTFORMAT_CERTSET, /* SET OF Certificate */
CERTFORMAT_SSLCHAIN, /* SSL cert chain */
CERTFORMAT_LAST /* Last cert format type */
} CERTFORMAT_TYPE;
/* Internal forms of various external functions. These work with internal
resources which are marked as being inaccessible to the corresponding
external functions, and return slightly different error codes in place of
parameter errors, since odd parameter errors coming from a deeply-buried
internal function won't make much sense to the caller.
Mid-level functions */
int iCryptCreateSignatureEx( void *signature, int *signatureLength,
const CRYPT_FORMAT_TYPE formatType,
const CRYPT_CONTEXT iSignContext,
const CRYPT_CONTEXT iHashContext,
const CRYPT_CERTIFICATE iExtraData,
const CRYPT_SESSION iTspSession );
int iCryptCheckSignatureEx( const void *signature, const int signatureLength,
const CRYPT_HANDLE iSigCheckKey,
const CRYPT_CONTEXT iHashContext,
CRYPT_HANDLE *iExtraData );
int iCryptImportKeyEx( const void *encryptedKey, const int encryptedKeyLength,
const CRYPT_CONTEXT iImportKey,
const CRYPT_CONTEXT iSessionKeyContext );
int iCryptExportKeyEx( void *encryptedKey, int *encryptedKeyLength,
const CRYPT_FORMAT_TYPE formatType,
const CRYPT_CONTEXT iSessionKeyContext,
const CRYPT_CONTEXT iExportKey,
const CRYPT_CONTEXT iAuxContext );
/* Special-case certificate functions. This works somewhat like the import
cert messages, but reads certs by sending get_next_cert messages to the
message source and provides extended control over the format of the
imported object. This isn't strictly speaking a certificate function since
the work is done by the caller (via callback messages), but the best place
to put it is with the cert-management code */
int iCryptImportCertIndirect( CRYPT_CERTIFICATE *iCertificate,
const CRYPT_HANDLE iCertSource,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength,
const int options );
/* Get a unique but not necessarily unpredictable nonce */
void getNonce( void *nonce, int nonceLength );
/* Copy a string attribute to external storage, with various range checks
to follow the cryptlib semantics */
int attributeCopy( RESOURCE_DATA *msgData, const void *attribute,
const int attributeLength );
int attributePtrCopy( void *dest, int *destLength, const void *attribute,
const int attributeLength );
/* Check whether a password is valid or not. Currently this just checks that
it contains at least one character, but stronger checking can be
substituted if required */
#define checkBadPassword( password ) \
( checkBadPtrRead( password, 1 ) || ( strlen( password ) < 1 ) )
/* Check whether a given algorithm is available for use. This is performed
frequently enough that we have a special function for it rather than
querying the system object */
BOOLEAN algoAvailable( const CRYPT_ALGO cryptAlgo );
/* When we encounter an internal consistency check failure, we usually want
to display some sort of message telling the user that something has gone
catastrophically wrong, however people probably don't want klaxons going
off when there's a problem in production code so we only enable it in
debug versions. The command-line makefiles by default build release
versions, so in practice the warn-the-user action is only taken under
Windows unless the user explicitly enables the user of assertions */
#include <assert.h>
#define NOTREACHED 0 /* Force an assertion failure via assert( NOTREACHED ) */
/* Compare two strings in a case-insensitive manner for those systems which
don't have this function.
[This line of comment is necessary to bypass a bug in the Borland C parser] */
#if !( defined( __WINDOWS__ ) || defined( __MSDOS__ ) || \
defined( __OS2__ ) || defined( __IBM4758__ ) || \
defined( __TANDEM__ ) ) || defined( NT_DRIVER )
int strnicmp( const char *src, const char *dest, const int length );
int stricmp( const char *src, const char *dest );
#endif /* !( __WINDOWS__ || __MSDOS__ || __OS2__ || __IBM4758__ ) || NT_DRIVER */
/* Hash state information. We can either call the hash function with
HASH_ALL to process an entire buffer at a time, or HASH_START/
HASH_CONTINUE/HASH_END to process it in parts */
typedef enum { HASH_START, HASH_CONTINUE, HASH_END, HASH_ALL } HASH_STATE;
/* The hash functions are used quite a bit by the library so we provide an
internal API for them to avoid the overhead of having to set up an
encryption context every time they're needed. These take a block of
input data and hash it, leaving the result in the output buffer. If the
hashState parameter is HASH_ALL the hashInfo parameter may be NULL, in
which case the function will use its own memory for the hashInfo */
#ifdef _BIG_WORDS
#define MAX_HASHINFO_SIZE 280 /* RIPEMD160: 24 * sizeof( long64 ) + 64 */
#else
#define MAX_HASHINFO_SIZE 100 /* RIPEMD160: 24 * sizeof( long ) */
#endif /* _BIG_WORDS */
typedef void ( *HASHFUNCTION )( void *hashInfo, BYTE *outBuffer, \
const BYTE *inBuffer, const int length, \
const HASH_STATE hashState );
void getHashParameters( const CRYPT_ALGO hashAlgorithm,
HASHFUNCTION *hashFunction, int *hashOutputSize );
/* In order to make it easier to add lots of arbitrary-sized values, we make
the following functions available to the polling code to implement a
clustered-write mechanism for small data quantities. These add an integer
or (short) string to a buffer and send it through to the randomness device
when the buffer is full. A call with a string of (NULL, 0) flushes any
remaining data through. The method of use is:
BYTE buffer[ bufSize ];
int bufIndex = 0;
addRandom( buffer, &bufIndex, bufSize, ... );
addRandomString( buffer, &bufIndex, bufSize, ... );
[...]
addRandomString( buffer, &bufIndex, bufSize, NULL, 0 );
Using the intermediate buffer ensures we don't have to send a message to
the device for every bit of data added */
#define addRandom( buffer, bufIndex, bufSize, value ) \
addRandomLong( buffer, bufIndex, bufSize, ( long ) value );
void addRandomLong( BYTE *buffer, int *bufIndex, const int bufSize,
const long value );
void addRandomString( BYTE *buffer, int *bufIndex, const int bufSize,
const void *value, const int valueLength );
/* base64 and S/MIME-en/decode routines */
int base64checkHeader( const char *data, const int dataLength );
int smimeCheckHeader( const char *data, const int dataLength );
int base64encodeLen( const int dataLength,
const CRYPT_CERTTYPE_TYPE certType );
int base64encode( char *outBuffer, const void *inBuffer, const int count,
const CRYPT_CERTTYPE_TYPE certType );
int base64decodeLen( const char *data, const int dataLength );
int base64decode( void *outBuffer, const char *inBuffer, const int count,
const CRYPT_CERTFORMAT_TYPE format );
/* User data en/decode routines */
BOOLEAN isUserValue( const char *encVal, const int encValueLength );
int adjustUserValue( BYTE *value, const int noCodeGroups );
int encodeUserValue( char *encVal, const BYTE *value,
const int noCodeGroups );
int decodeUserValue( BYTE *value, const char *encVal,
const int encValueLength );
#endif /* _CRYPT_DEFINED */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -