⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 envelope.h

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 H
📖 第 1 页 / 共 3 页
字号:
   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 information is encoded as ASN.1 structures and 
   written into the envelope buffer.  The 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 that covers the encoding of
   the header information at the start of the envelope (only key exchange
   information requires this), and the second that 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 */

	ENVSTATE_DATA,					/* Emitting data payload information */

	/* Trailer state information */
	ENVSTATE_FLUSHED,				/* Data flushed through into buffer */
	ENVSTATE_SIGNATURE,				/* Emitting signatures */

	ENVSTATE_DONE,					/* Finished processing header/trailer */

	ENVSTATE_LAST					/* Last valid enveloping state */
	} ENV_STATE;

/* The current state of the processing of CMS headers that 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 various
   enveloping 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 that 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 that 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 */

	DEENVSTATE_LAST					/* Last valid de-enveloping state */
	} DEENV_STATE;

/* The current state of processing of PGP headers that contain non-data in 
   the envelope during the de-enveloping process.  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 that has to be removed in a manner which is transparent to the
   user.
   
   The two de-enveloping 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_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_DEENVSTATE_LAST				/* Last valid de-enveloping state */
	} PGP_DEENV_STATE;

/* The current state of processing of headers for data segments nested inside
   the OCTET STRING that contains the envelope's content.  Since we can run
   out of data at any point, we have to preserve the current state so that 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 */
	SEGHDRSTATE_LAST				/* Last valid header state */
	} SEGHDR_STATE;

/* Envelope information flags.  These are:

	ENVELOPE_ISDEENVELOPE: The envelope is a de-enveloping envelope.

	ENVELOPE_DETACHED_SIG: The (signed data) envelope should generate a
			standalone detached signature rather than signed enveloped data.

	ENVELOPE_NOSIGNINGCERTS: When generating a S/MIME signed data, don't
			include the signing certificates with the data.

	ENVELOPE_ATTRONLY: The (signed data) envelope only contains authenticated
			attributes, but not actual data.  This is required by SCEP.

	ENVELOPE_ZSTREAMINITED: Whether the zlib compression/decompression stream
			has been initialised */

#define ENVELOPE_ISDEENVELOPE	0x01	/* De-enveloping envelope */
#define ENVELOPE_DETACHED_SIG	0x02	/* Generate detached signature */
#define ENVELOPE_NOSIGNINGCERTS	0x04	/* Don't include signing certs */
#define ENVELOPE_ATTRONLY		0x08	/* Env.contains only auth'd attrs.*/
#define ENVELOPE_ZSTREAMINITED	0x10	/* Whether zlib stream has been inited */

/* Envelope data processing flags.  These are:

	ENVDATA_HASINDEFTRAILER: The (signed) envelope trailer has an indefinite
			length due to the use of signature algorithms that produce 
			variable-length output that can't be determined in advance.

	ENVDATA_HASHACTIONSACTIVE: The (signed) envelope is currently hashing
			payload data.

	ENVDATA_NOSEGMENT: The payload data shouldn't be segmented because a
			definite-length encoding is being used.

	ENVDATA_SEGMENTCOMPLETE: An indefinite-length segment has been completed
			an another one must be begun before more payload data can be
			emitted.

	ENVDATA_ENDOFCONTENTS: The EOC octets on indefinite payload data have 
			been reached.

	ENVDATA_NEEDSPADDING: Before (encrypted) enveloping can been completed 
			the payload data needs PKCS #5 padding added to it.

   The handling of several of these flags is quite complex, more details can 
   be found in encode/decode.c */

#define ENVDATA_HASINDEFTRAILER	0x01	/* Whether trailer size is indefinite */
#define ENVDATA_HASHACTIONSACTIVE 0x02	/* Payload hashing is active */
#define ENVDATA_NOSEGMENT		0x04	/* Don't segment payload data */
#define ENVDATA_SEGMENTCOMPLETE	0x08	/* Current segment has been completed */
#define ENVDATA_ENDOFCONTENTS	0x10	/* EOC reached */
#define ENVDATA_NEEDSPADDING	0x20	/* Whether to add PKCS #5 padding */

/* The size of the buffer used to handle read-ahead into out-of-band data at 
   the start of the payload */

#define OOB_BUFFER_SIZE			8

/* The structure that stores the information on an envelope */

typedef struct EI {
	/* Control and status information */
	CRYPT_FORMAT_TYPE type;			/* Envelope type */
	CRYPT_CONTENT_TYPE contentType;	/* Inner content type */
	ACTION_TYPE usage;				/* Usage (signing, encryption, etc) */
	int version;					/* Protocol version/subtype */
	int flags;						/* Envelope information flags */
	int dataFlags;					/* Envelope data processing flags */

	/* The list of actions to perform on the data.  There are three sets of
	   actions, the preActions (key exchange), the main actions (encryption 
	   or hashing), and the postActions (signing) */
	ACTION_LIST *preActionList;
	ACTION_LIST *actionList;
	ACTION_LIST *postActionList;

	/* Several action groups produce information which is prepended or
	   appended to the data.  The following variables record the encoded size
	   of this information.  In some cases the size of the appended
	   information isn't known when the enveloping is started so we have to
	   use an indefinite-length encoding for the outermost wrapper, if this
	   is the case then we set the ENVDATA_HASINDEFTRAILER flag to indicate 
	   that a definite-length encoding shouldn't be used even if the payload 
	   size is known */
	int cryptActionSize;			/* Size of key exchange actions */
	int signActionSize;				/* Size of signatures */
	int extraDataSize;				/* Size of any extra data */

	/* When prepending or appending header or trailer information to an
	   envelope we need to record the current position in the action list so
	   that we can continue later if we run out of room */
	ACTION_LIST *lastAction;

	/* When de-enveloping we may have objects present that can't be used
	   until user-supplied de-enveloping information is added to the
	   envelope.  We store these in a linked list in memory until the
	   information needed to work with them is present.  We also store a
	   pointer to the current position in the list, which is used when
	   traversing the list */
	CONTENT_LIST *contentList, *contentListCurrent;

	/* The public-key encryption/private-key decryption and signature-check
	   keysets that are used to look up any keys required during the 
	   enveloping/de-enveloping process */
	CRYPT_KEYSET iDecryptionKeyset;
	CRYPT_KEYSET iEncryptionKeyset;
	CRYPT_KEYSET iSigCheckKeyset;

	/* When we're encrypting/decrypting the envelope payload, the one action 
	   that we'll be performing constantly is encryption.  Similarly, when
	   we're signing/sig.checking, we'll be hashing the payload.  In order 
	   to make this process more efficientm, we record the encryption and 
	   hashing info here to save having to pull it out of the action list 
	   whenever it's needed.
	   
	   The encryption context, of which there's only one, is stored here.
	   Note that since there is a second reference held in the action list, 
	   there's no need to explicitly delete this when we destroy the 
	   envelope object since it's already been destroyed when the action 
	   list is destroyed.

	   For hashing, we may have multiple hash contexts active, so we still
	   use the action list for these.  However it's convenient to have 
	   direct confirmation that we have to hash the payload data to save 
	   having to check the action list each time, so we set the
	   ENVDATA_HASHACTIONSACTIVE flag to indicate that hashing is taking 
	   place.  This is only set while the hashing is taking place, once 

⌨️ 快捷键说明

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