📄 envelope.h
字号:
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;
/* 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.
ENVELOPE_AUTHENC: Use authenticated encryption, which adds a MAC tag to
the encrypted data */
#define ENVELOPE_ISDEENVELOPE 0x0001 /* De-enveloping envelope */
#define ENVELOPE_DETACHED_SIG 0x0002 /* Generate detached signature */
#define ENVELOPE_NOSIGNINGCERTS 0x0004 /* Don't include signing certs */
#define ENVELOPE_ATTRONLY 0x0008 /* Env.contains only auth'd attrs.*/
#define ENVELOPE_ZSTREAMINITED 0x0010 /* Whether zlib stream has been inited */
#define ENVELOPE_AUTHENC 0x0020 /* Use authenticated encryption */
/* 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_NOLENGTHINFO: The payload uses neither a definite- nor
indefinite-length encoding but continues until the caller tells
us it's finished. This is used to handle PGP 2.x compressed
data, which just continues until EOF with no length information
provided.
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.
ENVDATA_HASATTACHEDOOB: The envelope has out-of-band additional data
attached to the payload data. This is used by OpenPGP to tack
an MDC packet onto the end of encrypted data.
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_NOLENGTHINFO 0x04 /* No length info for payload avail.*/
#define ENVDATA_NOSEGMENT 0x08 /* Don't segment payload data */
#define ENVDATA_SEGMENTCOMPLETE 0x10 /* Current segment has been completed */
#define ENVDATA_ENDOFCONTENTS 0x20 /* EOC reached */
#define ENVDATA_NEEDSPADDING 0x40 /* Whether to add PKCS #5 padding */
#define ENVDATA_HASATTACHEDOOB 0x80 /* Whether data has attached OOB extra */
/* Envelope data-copy flags. These are:
ENVCOPY_FLAG_NONE: Perform no special processing.
ENVCOPY_FLAG_OOBDATA: Data is out-of-band data that isn't part of the
normal data payload */
#define ENVCOPY_FLAG_NONE 0x00 /* No special action */
#define ENVCOPY_FLAG_OOBDATA 0x01 /* Data is OOB rather than payload data */
/* 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
there's no more data to be hashed it's cleared to prevent out-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 when the envelope is created (so that a later
change of the default value won't affect the enveloping process) but
can be changed explicitly on a per-envelope basis by setting the
options just for the envelope rather than for all of cryptlib */
CRYPT_ALGO_TYPE defaultHash; /* Default hash algorithm */
CRYPT_ALGO_TYPE defaultAlgo; /* Default encryption algorithm */
CRYPT_ALGO_TYPE defaultMAC; /* Default MAC algorithm */
#ifdef USE_COMPRESSION
/* zlib stream compression data structure used to hold the compression/
decompression state */
z_stream zStream; /* zlib state variable */
#endif /* USE_COMPRESSION */
/* Buffer information */
BUFFER( bufSize, bufPos ) \
BYTE *buffer; /* Data buffer */
int bufSize; /* Total buffer size */
int bufPos; /* Last data position in buffer */
/* Auxiliary buffer used as a staging area for holding signature data
that may not currently fit into the main buffer. These are generated
into the auxiliary buffer and then copied into the main buffer as
required */
BUFFER_OPT( auxBufSize, auxBufPos ) \
BYTE *auxBuffer; /* Buffer for sig.data */
int auxBufSize, auxBufPos; /* Current pos and total aux.buf.size */
/* When the caller knows in advance how large the payload will be, they
can advise the enveloping code of this, which allows a more efficient
encoding of the data. The following variable records the payload
size */
long payloadSize;
/* The current state of header processing. The cryptlib/CMS and PGP
processing states are kept separate (although they could actually be
merged into the same variable) because they are conceptually separate
and shouldn't really be treated as the same thing */
ENVELOPE_STATE state; /* Current state of processing */
ENV_STATE envState; /* Current state of env.non-data proc.*/
DEENV_STATE deenvState; /* Current state of de-env.non-data proc.*/
#ifdef USE_PGP
PGP_DEENV_STATE pgpDeenvState; /* Current state of PGP de-env.n-d proc.*/
#endif /* USE_PGP */
long hdrSetLength; /* Remaining bytes in SET OF EKeyInfo */
/* Some data formats place out-of-band data at the start of the payload
rather than putting it in the header, the data-left variable keeps
track of how many bytes of data still need to be removed before we
can return actual payload data to the caller. In some cases the
amount of data can't be specified as a simple byte count but involves
format-specific events (e.g. the presence of a flag or data count in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -