📄 envelope.h
字号:
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 */
} 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 */
} 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_DEENV_STATE;
/* The current state of processing of headers for data segments nested inside
the OCTET STRING that 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_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 */
#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
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
there's no more data to be hashed it's cleared to preventout-of-band
data from being hashed as well */
CRYPT_CONTEXT iCryptContext;
/* Some types of key management/signature require additional certs.
For encryption, there may be originator certs present for use with
key agreement algorithms; for signing, there may be a signing-cert
meta-object present to contain the union of multiple sets of signing
certs if multiple signatures are present. These are held in the
following certificate object */
CRYPT_CERTIFICATE iExtraCertChain;
/* The encryption/hashing/signature defaults for this envelope. These
are recorded here for two reasons. Firstly, we need to freeze the
defaults when the envelope is created so that a later change of the
default value won't affect the enveloping process. Secondly,
different envelope types have different defaults, and setting them
once at envelope creation is easier than checking the envelope type
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -