envelope.h

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C头文件 代码 · 共 615 行 · 第 1/2 页

H
615
字号
/****************************************************************************
*																			*
*						 Enveloping Routines Header File					*
*						Copyright Peter Gutmann 1996-2002					*
*																			*
****************************************************************************/

#ifndef _ENV_DEFINED

#define _ENV_DEFINED

#ifndef _STREAM_DEFINED
  #if defined( INC_ALL )
	#include "stream.h"
  #elif defined INC_CHILD
	#include "../keymgmt/stream.h"
  #else
	#include "keymgmt/stream.h"
  #endif /* Compiler-specific includes */
#endif /* _STREAM_DEFINED */
#ifndef NO_COMPRESSION
  #if defined( INC_ALL )
	#include "zlib.h"
  #elif defined( INC_CHILD )
	#include "../zlib/zlib.h"
  #else
	#include "zlib/zlib.h"
  #endif /* Compiler-specific includes */
#endif /* NO_COMPRESSION */

/* Types of actions which can be performed on a piece of data.  The two key
   exchange actions are handled identically, but are given different tags
   because we place PKC-based key exchange actions (which may be handled
   automatically) before conventional key exchange actions (which usually
   require manual intervention for passphrases).  For this reason the actions
   are given in their sort order (ie ACTION_KEYEXCHANGE_PKC precedes
   ACTION_KEYEXCHANGE in the action list) */

typedef enum {
	ACTION_NONE,					/* Non-action */

	/* Pre-actions */
	ACTION_KEYEXCHANGE_PKC,			/* Generate/read PKC exchange information */
	ACTION_KEYEXCHANGE,				/* Generate/read key exchange information */

	/* Actions */
	ACTION_COMPRESS,				/* Compress */
	ACTION_HASH,					/* Hash */
	ACTION_MAC,						/* MAC */
	ACTION_CRYPT,					/* En/decrypt */

	/* Post-actions */
	ACTION_SIGN						/* Generate/check signature */
	} ACTION_TYPE;

/* An 'action list' which defines what we need to do to the content when
   enveloping data.  There are three action lists, one for actions to perform
   before enveloping data, one to perform during enveloping (which is 
   actually just a single action rather than a list), and one to perform 
   after enveloping.  ACTION_KEYEXCHANGE and ACTION_KEYEXCHANGE_PKC are found 
   in the pre-enveloping list, ACTION_SIGN in the post-enveloping list, and 
   everything else in the during-enveloping list.  A collection of similar 
   actions is called an action group.

   Some actions are many-to-one, in which a number of controlling actions in
   one list may act on a single subject action in another list (for example a
   number of signature actions may sign the output from a single hash
   action).  This is handled by having the controlling actions maintain
   pointers to the subject action, for example a number of key export actions
   would point to one session encryption action (the export action exports
   the session key) */

typedef struct AI {
	/* Type of list item and link information */
	ACTION_TYPE action;				/* Type of action to perform */
	struct AI *next;				/* Next item in the list */

	/* Variables to handle controlling/subject actions.  The associated
	   action points to the subject action associated with a controlling
	   action if this is a controlling action.  The needsController flag
	   records whether this is a subject action which still requires a
	   controlling action.  This allows us to identify unused subject actions
	   more easily than by scanning all controller->subject relationships.
	   The addedAutomatically flag records whether the action was added
	   automatically and invisibly to the caller as a result of adding a
	   different action.  This is to ensure we don't return an error the
	   first time the caller adds an action which is identical to an
	   automatically added action */
	struct AI *associatedAction;	/* Associated action */
	BOOLEAN needsController;		/* Whether it needs a controlling action */
	BOOLEAN addedAutomatically;		/* Whether action added automatically */

	/* Information related to the action.  These fields contain various
	   pieces of information required as part of the action.  The crypt
	   handle usually contains the internal encryption context needed to
	   perform the action (eg encryption, hashing, signing), but may also
	   contain a certificate when we envelope data in CMS format.  If we're
	   generating CMS signatures, there may be extra attribute data present 
	   which is included in the signature, and we may also have 
	   countersignature information present, typically a timestamping session
	   object.  Finally, there may also be auxiliary information present 
	   which is required for special processing */
	CRYPT_CONTEXT iCryptHandle;		/* Encryption handle for action */
	CRYPT_CERTIFICATE iExtraData;	/* Extra attribute data for CMS sigs.*/
	CRYPT_SESSION iTspSession;		/* Timestamping session object */
	int encodedSize;				/* The encoded size of the action */
	} ACTION_LIST;

/* A 'content list' which is used to store objects found in the non-data
   portion of the envelope until we can do something with them when de-
   enveloping data.  If the envelope contains encrypted data this list
   contains the key exchange information until we get a key exchange key to
   recover the session key.  If the envelope contains signed data this list
   contains the signature(s) until we get signature keys to check them.  The
   same list is used for two purposes at different times */

typedef struct CL {
	/* Link information */
	struct CL *next;				/* Next item in the list */

	/* The object contained in this list element */
	void *object;					/* The object data */
	int objectSize;					/* Size of the object */

	/* Details on the object.  Here we store whatever is required to process
	   the object without having to call queryObject() for the details */
	CRYPT_ATTRIBUTE_TYPE envInfo;	/* Env.info required to continue */
	CRYPT_FORMAT_TYPE formatType;	/* Data format */
	BYTE keyID[ CRYPT_MAX_HASHSIZE ];/* cryptlib key ID */
	int keyIDsize;
	void *issuerAndSerialNumber;	/* CMS key ID */
	int issuerAndSerialNumberSize;
	void *payload;					/* Payload data (eg encr.key) */
	int payloadSize;
	CRYPT_ALGO cryptAlgo;			/* Encryption algo.for this object */
	CRYPT_MODE cryptMode;			/* Encrytion mode for this object */
	BYTE saltOrIV[ CRYPT_MAX_HASHSIZE ];/* Salt for password-derived key or */
	int saltOrIVsize;				/*	   IV for session encr.context */
	int keySetupIterations;			/* Iterations for pw-derived key */
	CRYPT_ALGO hashAlgo;			/* Hash algo.for signed data */

	/* Additional information obtained when processing the content */
	CRYPT_HANDLE iSigCheckKey;		/* Signature check key */
	CRYPT_CERTIFICATE iExtraData;	/* Extra data in CMS signatures */
	void *extraData;				/* Extrat data in PGP signatures */
	int extraDataLength;

	/* We only need to process an object once, once we've done this we store
	   the processing result so that any further attempts to process the
	   object will return the previously obtained result (an object can be
	   processed multiple times if the user wanders up and down the content
	   list using the cursor management capabilities) */
	BOOLEAN processed;				/* Whether object has been processed */
	int processingResult;			/* Result of processing */
	} CONTENT_LIST;

/* The current state of the (de)enveloping.  The states are the predata state
   (when we're performing final setup steps and handling header information
   in the envelope), the data state (when we're enveloping data), the
   postdata state (when we're handling trailer information), and the
   extradata state (when we're processing out-of-band data such as the data
   associated with detached signatures) */

typedef enum {
	STATE_PREDATA,					/* Emitting header information */
	STATE_DATA,						/* During (de)enveloping of data */
	STATE_POSTDATA,					/* After (de)enveloping of data */
	STATE_EXTRADATA,				/* Additional out-of-band data */
	STATE_FINISHED					/* Finished processing */
	} ENVELOPE_STATE;

/* The current state of the processing of headers which contain non-data
   during the enveloping process.  Before the enveloping of data begins, the
   user pushes in a variety of enveloping information (which in turn might
   trigger the creation of more internal information objects).  Once the
   enveloping begins, this enveloping information is encoded as ASN.1
   structures and written into the envelope buffer.  This encoding process
   can be interrupted at any point when the envelope buffer fills up, so we
   break it down into a series of atomic states between which the enveloping
   process can be interrupted by the caller removing data from the envelope.

   There are two sets of states, the first set which covers the encoding of
   the header information at the start of the envelope (only key exchange
   information requires this), and the second which covers the information at
   the end of the envelope (only signatures require this) */

typedef enum {
	ENVSTATE_NONE,					/* No header processing/before header */

	/* Header state information */
	ENVSTATE_HEADER,				/* Emitting header */
	ENVSTATE_KEYINFO,				/* Emitting key exchange information */
	ENVSTATE_ENCRINFO,				/* Emitting EncrContentInfo information */

	/* Trailer state information */
	ENVSTATE_SIGNATURE,				/* Emitting signatures */
	ENVSTATE_EOC,					/* Emitting EOC octets */

	ENVSTATE_DONE					/* Finished processing header/trailer */
	} ENV_STATE;

/* The current state of the processing of headers which contain non-data
   in the envelope during the de-enveloping process.  This is implemented as
   a somewhat complex FSM because the enveloping routines give the user the
   ability to push in arbitrary amounts of data corresponding to ASN.1
   structures and simultaneously pop out data/information based on decoding
   them.  A typical complex enveloped type might contain a number of headers,
   a session key encrypted with 18 different public keys, five varieties of
   signature type, and God knows what else, of which the caller might feed us
   500 bytes - a small fraction of the total data - and then ask for
   information on what they've just fed us.  We have to remember how far we
   got (halfway through an RSA-encrypted DES key fifteen levels of nesting
   down in an ASN.1 structure), process everything we can, and then get back
   to them on what we found.  Then they feed us another few hundred bytes and
   the whole thing starts anew.

   The state machine works by processing one complete object or part of an
   object at a time and then moving on to the next state which corresponds to
   handling another part of the object or another object.  If there isn't
   enough data present to process a part or subpart, we return an underflow
   error and try again when more data is added */

typedef enum {
	DEENVSTATE_NONE,				/* No header processing/before header */

	/* Header state information */
	DEENVSTATE_SET_ENCR,			/* Processing start of SET OF EncrKeyInfo */
	DEENVSTATE_ENCR,				/* Processing EncrKeyInfo records */
	DEENVSTATE_ENCRCONTENT,			/* Processing EncrContentInfo */

	DEENVSTATE_SET_HASH,			/* Processing start of SET OF DigestAlgoID */
	DEENVSTATE_HASH,				/* Processing DigestAlgoID records */
	DEENVSTATE_CONTENT,				/* Processing ContentInfo */

	DEENVSTATE_DATA,				/* Processing data payload */

	/* Trailer state information */
	DEENVSTATE_CERTSET,				/* Processing optional cert chain */
	DEENVSTATE_SET_SIG,				/* Processing start of SET OF Signature */
	DEENVSTATE_SIG,					/* Processing Signature records */
	DEENVSTATE_EOC,					/* Processing end-of-contents octets */

	DEENVSTATE_DONE					/* Finished processing header/trailer */
	} DEENV_STATE;

/* The current state of processing of headers for PGP messages.  These are
   somewhat different to the ASN.1-encoded objects used by cryptlib in that
   many of the objects are emitted as discrete packets rather than the nested
   objects used in ASN.1 objects.  This makes some parts of the processing
   much easier (less length information to track) and some parts much harder
   (since just about anything could appear next, you need to maintain a
   lookahead to figure out what to do next, but you may run out of data
   before you can determine which state is next).  The handling of content
   inside encrypted data is particularly messy since there's a plain-data
   header which has to be removed in a manner which is transparent to the
   user.
   
   The two deenveloping encrypted-data states are almost identical except for
   the fact that one performs PGP's odd IV resync while the other doesn't, a
   requirement buried in the depths of two otherwise identical text blocks in 
   the RFC */

typedef enum {
	PGP_ENVSTATE_NONE,				/* No message processing/before message */

	/* Header state information */
	PGP_ENVSTATE_HEADER,			/* Emitting header */
	PGP_ENVSTATE_KEYINFO,			/* Emitting key exchange information */
	PGP_ENVSTATE_ENCRINFO,			/* Emitting secret-key encryption information */
	PGP_ENVSTATE_DATA,				/* Emitting data payload header */

	/* Trailer state information */
	PGP_ENVSTATE_SIGNATURE,			/* Emitting signatures */

	PGP_ENVSTATE_DONE				/* Finished processing message */
	} PGP_ENV_STATE;

typedef enum {
	PGP_DEENVSTATE_NONE,			/* No message processing/before message */

	/* Header state information */
	PGP_DEENVSTATE_ENCR,			/* Encrypted data packet */
	PGP_DEENVSTATE_ENCR_MDC,		/* Encrypted data with MDC */

	PGP_DEENVSTATE_DATA,			/* Data */
	PGP_DEENVSTATE_DATA_HEADER,		/* Out-of-band data inside compressed data */

	PGP_DEENVSTATE_DONE				/* Finished processing message */
	} PGP_DEENV_STATE;

/* The current state of processing of headers for data segments nested inside
   the OCTET STRING which contains the envelopes content.  Since we can run
   out of data at any point, we have to preserve the current state so we can
   continue when we get more data */

typedef enum {
	SEGHDRSTATE_NONE,				/* No header processing/before header */
	SEGHDRSTATE_LEN_OF_LEN,			/* Expecting OCTET STRING len-of-len */
	SEGHDRSTATE_LEN,				/* Processing OCTET STRING length */
	SEGHDRSTATE_END,				/* Expecting second end-of-contents oct.*/
	SEGHDRSTATE_DONE				/* Parsed entire header */
	} SEGHDR_STATE;

/* Envelope information flags */

#define ENVELOPE_ISDEENVELOPE	0x01	/* De-enveloping envelope */
#define ENVELOPE_NOSEGMENT		0x02	/* Don't segment payload data */
#define ENVELOPE_DETACHED_SIG	0x04	/* Generate detached signature */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?