📄 crypt.h
字号:
mget/putLong():
CMP "TCP" protocol, also used in TSP (disabled by default in both).
SSHv1 (disabled by default).
Sampling data from the crypto RNG to detect stuck-at faults.
Debug version of clAlloc() */
#if defined( USE_CMP_TRANSPORT ) || defined( USE_SSH1 )
#define mgetWord( memPtr ) \
( ( ( unsigned int ) memPtr[ 0 ] << 8 ) | \
( unsigned int ) memPtr[ 1 ] ); \
memPtr += 2
#define mputWord( memPtr, data ) \
memPtr[ 0 ] = ( BYTE ) ( ( ( data ) >> 8 ) & 0xFF ); \
memPtr[ 1 ] = ( BYTE ) ( ( data ) & 0xFF ); \
memPtr += 2
#endif /* USE_CMP_TRANSPORT || USE_SSH1 */
#define mgetLong( memPtr ) \
( ( ( unsigned long ) memPtr[ 0 ] << 24 ) | \
( ( unsigned long ) memPtr[ 1 ] << 16 ) | \
( ( unsigned long ) memPtr[ 2 ] << 8 ) | \
( unsigned long ) memPtr[ 3 ] ); \
memPtr += 4
#define mputLong( memPtr, data ) \
memPtr[ 0 ] = ( BYTE ) ( ( ( data ) >> 24 ) & 0xFF ); \
memPtr[ 1 ] = ( BYTE ) ( ( ( data ) >> 16 ) & 0xFF ); \
memPtr[ 2 ] = ( BYTE ) ( ( ( data ) >> 8 ) & 0xFF ); \
memPtr[ 3 ] = ( BYTE ) ( ( data ) & 0xFF ); \
memPtr += 4
/****************************************************************************
* *
* Data Size and Crypto-related Constants *
* *
****************************************************************************/
/* Pull in the data-size and crypt-related constants */
#if defined( INC_ALL )
#include "consts.h"
#else
#include "misc/consts.h"
#endif /* Compiler-specific includes */
/****************************************************************************
* *
* Data Structures *
* *
****************************************************************************/
/* Information on exported key/signature data. This is an extended version
of the data returned by the externally-visible cryptQueryObject() routine */
typedef struct {
/* Object format and status information */
CRYPT_FORMAT_TYPE formatType; /* Object format type */
CRYPT_OBJECT_TYPE type; /* Object type */
long size; /* Object size */
int version; /* Object format version */
/* The encryption algorithm and mode */
CRYPT_ALGO_TYPE cryptAlgo; /* The encryption algorithm */
CRYPT_MODE_TYPE cryptMode; /* The encryption mode */
/* The key ID for public key objects */
BUFFER( CRYPT_MAX_HASHSIZE, keyIDlength ) \
BYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];/* PKC key ID */
int keyIDlength;
/* The IV for conventionally encrypted data */
BUFFER( CRYPT_MAX_IVSIZE, ivLength ) \
BYTE iv[ CRYPT_MAX_IVSIZE + 8 ];/* IV */
int ivLength;
/* The key derivation algorithm and iteration count for conventionally
encrypted keys */
CRYPT_ALGO_TYPE keySetupAlgo; /* Key setup algorithm */
int keySetupIterations; /* Key setup iteration count */
BUFFER( CRYPT_MAX_HASHSIZE, saltLength ) \
BYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];/* Key setup salt */
int saltLength;
/* The hash algorithm for signatures */
CRYPT_ALGO_TYPE hashAlgo; /* Hash algorithm */
/* The start and length of the payload data, either the encrypted key or
the signature data */
int dataStart, dataLength;
/* The start and length of the issuerAndSerialNumber, authenticated
attributes, and unauthenticated attributes for CMS objects */
int iAndSStart, iAndSLength;
int attributeStart, attributeLength;
int unauthAttributeStart, unauthAttributeLength;
} QUERY_INFO;
/* DLP algorithms require composite parameters when en/decrypting and
signing/sig checking, so we can't just pass in a single buffer full of
data as we can with RSA. In addition the data length changes, for
example for a DSA sig we pass in a 20-byte hash and get back a ~50-byte
sig, for sig.checking we pass in a 20-byte hash and ~50-byte sig and get
back nothing. Because of this we have to use the following structure to
pass data to the DLP-based PKCs */
typedef struct {
BUFFER_FIXED( inLen1 ) \
const BYTE *inParam1;
BUFFER_OPT_FIXED( inLen2 ) \
const BYTE *inParam2; /* Input parameters */
BUFFER_FIXED( outLen ) \
BYTE *outParam; /* Output parameter */
int inLen1, inLen2, outLen; /* Parameter lengths */
CRYPT_FORMAT_TYPE formatType; /* Paramter format type */
} DLP_PARAMS;
#define setDLPParams( dlpDataPtr, dataIn, dataInLen, dataOut, dataOutLen ) \
{ \
memset( ( dlpDataPtr ), 0, sizeof( DLP_PARAMS ) ); \
( dlpDataPtr )->formatType = CRYPT_FORMAT_CRYPTLIB; \
( dlpDataPtr )->inParam1 = ( dataIn ); \
( dlpDataPtr )->inLen1 = ( dataInLen ); \
( dlpDataPtr )->outParam = ( dataOut ); \
( dlpDataPtr )->outLen = ( dataOutLen ); \
}
/* When calling key agreement functions we have to pass a mass of cruft
around instead of the usual flat data (even more than the generic DLP
parameter information) for which we use the following structure. The
public value is the public key value used for the agreement process,
typically y = g^x mod p for DH-like mechanisms. The ukm is the user
keying material, typically something which is mixed into the DH process
to make the new key unique. The wrapped key is the output (originator)/
input(recipient) to the keyagreement process. The session key context
contains a context into which the derived key is loaded. Typical
examples of use are:
PKCS #3: publicValue = y
Fortezza: publicValue = y, ukm = Ra, wrappedKey = TEK-wrapped MEK
S/MIME: publicValue = y, ukm = 512-bit nonce, wrappedKey = g^x mod p
SSH, SSL: publicValue = y, wrappedKey = x */
typedef struct {
BUFFER( CRYPT_MAX_PKCSIZE, publicValueLen ) \
BYTE publicValue[ CRYPT_MAX_PKCSIZE + 8 ];
int publicValueLen; /* Public key value */
#ifdef USE_FORTEZZA
BUFFER( CRYPT_MAX_PKCSIZE, ukmLen ) \
BYTE ukm[ CRYPT_MAX_PKCSIZE + 8 ];
int ukmLen; /* User keying material */
CRYPT_CONTEXT sessionKeyContext;/* Context for derived key */
#endif /* USE_FORTEZZA */
BUFFER( CRYPT_MAX_PKCSIZE, wrappedKeyLen ) \
BYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];
int wrappedKeyLen; /* Wrapped key */
} KEYAGREE_PARAMS;
/****************************************************************************
* *
* Useful General Macros *
* *
****************************************************************************/
/* Reasonably reliable way to get rid of unused argument warnings in a
compiler-independant manner */
#define UNUSED_ARG( arg ) ( ( arg ) = ( arg ) )
/* Although min() and max() aren't in the ANSI standard, most compilers have
them in one form or another, but just enough don't that we need to define
them ourselves in some cases */
#if !defined( min )
#ifdef MIN
#define min MIN
#define max MAX
#else
#define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
#define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
#endif /* Various min/max macros */
#endif /* !min/max */
/* Macros to convert to and from the bit counts used for some encryption
parameters */
#define bitsToBytes( bits ) ( ( ( bits ) + 7 ) >> 3 )
#define bytesToBits( bytes ) ( ( bytes ) << 3 )
/* Macro to round a value up to the nearest multiple of a second value,
with the second value being a power of 2 */
#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 set to 0 all the time,
and makes it obvious where sensitive data is being erased. In addition
some systems, recognising the problem, have distinct memory zeroisation
support, so if available we use that */
#if defined( _MSC_VER ) && VC_GE_2005( _MSC_VER )
/* This isn't terribly spectacular, just a mapping to
RtlSecureZeroMemory() which is implemented as inline code implementing
a loop on a pointer declared volatile, but there's an implied contract
that future versions will always zeroise memory even in the face of
compiler changes that would otherwise optimise away the access */
#define zeroise( memory, size ) SecureZeroMemory( memory, size )
#else
#define zeroise( memory, size ) memset( memory, 0, size )
#endif /* Systems with distinct zeroise functions */
/* 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. The full function isValidHandle() used
in the kernel does check that the handle refers to a valid object, being
more than just a range check */
#define isHandleRangeValid( 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 just 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 that normally use the default algorithm set in the configuration
database if nothing else is explicitly specified, but that 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_ECDSA )
#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 )
#define isEccAlgo( algorithm ) \
( ( algorithm ) == CRYPT_ALGO_ECDSA )
/* A macro to check whether a public key is too short to be secure. This
is a bit more complex than just a range check because any length below
about 512 bits is probably a bad data error, while lengths from about
512 bits to MIN_PKCSIZE are too-short key errors */
#define isShortPKCKey( keySize ) \
( ( keySize ) >= bitsToBytes( 504 ) && ( keySize ) < MIN_PKCSIZE )
/* Perform a range check on a block of memory, checking that
{ start, length } falls within { 0, totalLength }. The lower bound on
the length is set by PGP attributes, which can consist of nothing but a
16-bit length */
#define rangeCheck( start, length, totalLength ) \
( ( start ) <= 0 || ( length ) < 2 || \
( start ) + ( length ) > ( totalLength ) ) ? FALSE : TRUE
/* Check the validity of a pointer passed to a cryptlib function. Usually
the best that we can do is check that it's not null, but some OSes allow
for better checking than this, for example that it points to a block of
readable or writeable memory. Under Windows IsBadReadPtr() will always
succeed if the size is 0, so we have to add a separate check to make sure
that it's non-NULL.
There are additional caveats with the use of the Windows memory-checking
functions. In theory these would be implemented via VirtualQuery(),
however this is quite slow, requiring a kernel transition and poking
around with the page protection mechanisms. Instead, they try and read
or write the memory, with an exception handler wrapped around the access.
If the exception is thrown, they fail. The problem with this way of
doing things is that if the memory address is a stack guard page used to
grow the stack (when the system-level exception handler sees an access to
the bottom-of-stack guard page, it knows that it has to grow the stack)
*and* the guard page is owned by another thread, IsBadXxxPtr() will catch
the exception and the system will never see it, so it can't grow the
stack past the current limit (note that this only occurs if the guard
page that we hit is owned by a different thread; if we own in then the
kernel will catch the STATUS_GUARD_PAGE_VIOLATION exception and grow the
stack as required). In addition if it's the last guard page then instead
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -