Unprivileged Architecture: Machines

This chapter is normative.

All values, bit slices, concatenations, and finite-field operations in this chapter follow the conventions of Notation and Conventions. Specifically, the byte at the lowest address occupies the least significant bits, and the @ operator places its left operand in the more significant bits, opposite to ‖, which places its left operand at the lower offsets (Operators and Control Constructs). No Machine may deviate from these conventions.

This chapter specifies KLE instruction behavior for supported Machines. Some Machines are defined generically for primitives meeting certain properties (e.g., GCM works with AES or SM4), while others are tied to specific primitives (e.g., Ascon).

Table 1 gives the encoding of each Machine of this specification in the MDH field Machine, which has two sub-fields: Type in bits [11:4] and Mode in bits [3:0]. For some classes of Machines, Mode specifies a subtype; other groups of Machines may subdivide Machine differently.

Table 1. Machine Type and Mode Encodings, corresponding Extensions
Type Mode Machine name Extension

0

0

AES128_ECB

Zklaes128p

0

1

AES128_CBC

Zklaes128pcbcm

0

2

AES128_CFB

Zklaes128pcfbm

0

3

AES128_OFB

Zklaes128pofbm

0

4

AES128_CTR

Zklaes128pctrm

0

5

AES128_XCTR

Zklaes128pxctrm

0

6

AES128_XEX

Zklaes128pxexm

0

7

AES128_GCM

Zklaes128pgcmm

0

8

AES128_GCM_IV

Zklaes128pgcmm

0

9

AES128_GCM_SIV

Zklaes128pgcmsivm

0

10

AES128_CMAC

Zklaes128pcmacm

0

11

AES128_OCB

Zklaes128pocbm

0

12

AES128_OCB_NONCE

Zklaes128pocbm

1

0

AES192_ECB

Zklaes192p

1

1—​5, 7—​8, 10—​12

Analogous to the corresponding Modes for AES128, but with 192 replacing 128. There is no Mode 6: cite:[IEEE-1619-2018] defines XTS-AES only for 128-bit and 256-bit keys; and no Mode 9: cite:[RFC8452] defines AES-GCM-SIV only for 128-bit and 256-bit keys.

2

0

AES256_ECB

Zklaes256p

2

1—​12

Analogous to Modes 1—​12 for AES128, but with 256 replacing 128.

3

0

SM4_ECB

Zklsm4p

3

1—​4, 6—​8, 10

Analogous to the corresponding Modes for AES128, but with SM4 and sm4 replacing AES128 and aes128; Mode 6, SM4_XEX, multiplies the mask as GB/T 17964-2021 does (XEX/XTS Modes). There are no Modes 5, 9, 11 and 12: none of SM4-XCTR, SM4-GCM-SIV and SM4-OCB is standardized.

4

0

SHA2-224

Zklesha2h

4

1

SHA2-256

Zklesha2h

4

2

SHA2-384

Zklesha2h

4

3

SHA2-512

Zklesha2h

4

4

SHA2-512/224

Zklesha2h

4

5

SHA2-512/256

Zklesha2h

4/5

6

SHA2-224_HMAC (No Initial Key/Key In PI)

Zklesha2hhmacm

4/5

7

SHA2-256_HMAC (No Initial Key/Key In PI)

Zklesha2hhmacm

4/5

8

SHA2-384_HMAC (No Initial Key/Key In PI)

Zklesha2hhmacm

4/5

9

SHA2-512_HMAC (No Initial Key/Key In PI)

Zklesha2hhmacm

4/5

10

SHA2-512/224_HMAC (No Initial Key/Key In PI)

Zklesha2hhmacm

4/5

11

SHA2-512/256_HMAC (No Initial Key/Key In PI)

Zklesha2hhmacm

6

0

SHA3-224

Zklesha3h

6

1

SHA3-256

Zklesha3h

6

2

SHA3-384

Zklesha3h

6

3

SHA3-512

Zklesha3h

6

4

SHAKE128

Zklesha3h

6

5

SHAKE256

Zklesha3h

6/7

6

SHA3-224_HMAC (No Initial Key/Key In PI)

Zklesha3hhmacm

6/7

7

SHA3-256_HMAC (No Initial Key/Key In PI)

Zklesha3hhmacm

6/7

8

SHA3-384_HMAC (No Initial Key/Key In PI)

Zklesha3hhmacm

6/7

9

SHA3-512_HMAC (No Initial Key/Key In PI)

Zklesha3hhmacm

6

10

KMAC128

Zklesha3hkmacm

6

11

KMACXOF128

Zklesha3hkmacm

6

12

KMAC256

Zklesha3hkmacm

6

13

KMACXOF256

Zklesha3hkmacm

7

0

BLAKE2b, unkeyed or keyed

Zklblake2h

7

1

BLAKE2s, unkeyed or keyed

Zklblake2h

8

0

Ascon-AEAD128

Zklascon

8

1

Ascon-AEAD128_Nonce

Zklascon

8

2

Ascon-AEAD128_Nonce_Mask

Zklascon

8

3

Ascon-Hash256

Zklascon

8

4

Ascon-XOF128

Zklascon

8

5

Ascon-CXOF128

Zklascon

9

0

SM3

Zklsm3h

9

1

SM3_HMAC (No Initial Key)

Zklsm3hhmacm

9

2

SM3_HMAC (Key In PI)

Zklsm3hhmacm

10

0

Elliptic Curve Cryptography: secp256r1 (NIST P-256)

Zklsecp256r1c

10

1

ECC: secp384r1 (NIST P-384)

Zklsecp384r1c

10

2

ECC: secp521r1 (NIST P-521)

Zklsecp521r1c

10

3

ECC: x25519

Zklx25519c

10

4

ECC: x448

Zklx448c

10

5

ECC: ed25519

Zkled25519c

10

6

ECC: ed448

Zkled448c

10

7

ECC: brainpoolP256r1

Zklbpp256r1c

10

8

ECC: brainpoolP384r1

Zklbpp384r1c

10

9

ECC: brainpoolP512r1

Zklbpp512r1c

10

10

ECC: SM2

Zklsm2c

11

0

Post-Quantum Cryptography (PQC): ML-KEM-512

Zklmlkem512k

11

1

PQC: ML-KEM-768

Zklmlkem768k

11

2

PQC: ML-KEM-1024

Zklmlkem1024k

11

3

PQC: ML-DSA-44 and HashML-DSA-44

Zklmldsa44s

11

4

PQC: ML-DSA-65 and HashML-DSA-65

Zklmldsa65s

11

5

PQC: ML-DSA-87 and HashML-DSA-87

Zklmldsa87s

Note on the HMAC variants. In the SHA-2 and SHA-3 HMAC Machines, the lower Type (4 or 6) selects the “No Initial Key” (NIK) variant and the higher Type (5 or 7) the “Key In PI” (KIP) variant (HMAC); for SM3_HMAC, Mode 1 selects NIK and Mode 2 KIP. A NIK variant must have KeyType = 0 in its MDH; any other KeyType is invalid Metadata.

Definition of a Machine in KLE

The following information fully defines a Machine:

Parameters

These include:

  • the block size b, the bit length of the basic unit the Machine processes, usually the block size of its main underlying primitive;

  • the key size k, in bits, for Machines that hold a key;

  • the granularity, usually equal to b. “Last blocks”, such as those of the AD or of the plaintext or ciphertext, may be shorter than b. Where the length of such a block is set explicitly, a longer input that carries it is truncated: its excess most significant bits are ignored; and

  • any other parameter needed to instantiate the Machine with compatible primitives.

Data Structures

These include:

  1. Provisioning Input: its fields, in the order in which they appear in the PI, each with its length. Every table ends with a zero Padding to a multiple of 128 bits, of a size pad as defined for the Serialized Content; provisioning ignores the padding bits.

    Every PI starts with the MDH, at position i. The Provisioning Input tables of the Machines omit it and start at position ii:

    Pos. Size (Bits) Field

    i

    128

    MDH

  2. Internal State: the information kept in the internal state of a CC, needed to define the Machine and its semantics. It must exist internally, but its representation and format are not prescribed. The Internal State always contains the MDH. A key field of the Internal State holds the key itself, even when the PI or the SCC carries a System Key Identifier in its place (System Keys).

  3. Serialized Content: the plaintext of the Content1 of the SCC: its fields, in the order in which they appear in an SCC, each with its length. It does not include the MDH, and ends with a zero Padding to a multiple of 128 bits; a size pad is (−s) mod 128 bits, s being the total size of the Positions before it, with the sizes in effect. In the formulas for pad, kf is the size of the key field: k, or 64 when it holds a System Key Identifier. The Machine may designate public fields, which it places first and an SCC carries in clear; their number of whole 128-bit blocks is SCC_ClearLen1 (Rule GR9), zero where the Machine designates none.

Machine-Specific Functions

Any other function specific to the Machine.

State Machine

The state machine is defined by:

  1. the list of States the Machine may assume, each with its representation as State and StateExtension Fields specifies;

  2. the complete list of allowed state transitions, with the prerequisites of each, the native kl.setst Form and the meaning of any auxiliary parameter to it, and any other condition that triggers a transition without a kl.setst; and

  3. the allowed or expected instructions in each State, and their semantics. Besides configuration and export sequences, a State typically permits only certain Forms of kl.exec and kl.setst, and may be an endpoint of kl.derive (Derivation Endpoints of the Machines). With Zklio, a substitution may replace any native Form of kl.exec, however the Machine words it (Zklio, Rule GR10): a Form D kl.exec replaces a Form A, B or C kl.exec. A kl.setst into a State for which the Machine names no Form is of Form A. Where a State expects a Form B or D kl.setst, a Form A one is admitted too, with a zero operand; where it expects Form C with an INPUT of at most 128 bits, a Form A or D one is admitted (Rule MR5), and a Form B one where the State says so. A substitution issued without the required KLIOBUF setup fails as Rules GR11 and GR10.2 state. A Form that is neither a native Form of the State nor, with Zklio, its substitution is a wrong Form (Rule GR19.1). kl.input and kl.output access no locker, so the state machine does not restrict them. Rule GR13.5 states the behavior precisely.

The non-normative code examples in Appendix: Writing Software for KLE illustrate how software uses the Machines through the KLE ISA; the examples use the vector Forms of the instructions.

Notation in the Machine Descriptions

The following nomenclature is specific to the Machine specifications:

  • INPUT is the input data of kl.exec or kl.setst: the input vector register, the 128-bit GPR operand of a Form D kl.setst, the Xs of a Form B kl.setst that a State admits in place of Form C, zero-extended to 128 bits, or the KLIOBUF (Zklio).

  • OUTPUT is the output data of kl.exec: the output vector register, or the KLIOBUF (Zklio).

  • Xs is the auxiliary operand of a Form B kl.setst: a 64-bit value, in one GPR on RV64 and in the pair X[s+1] @ X[s] on RV32 (Rule GR2). A Form A kl.setst is a Form B one with Xs = 0.

  • KLLEN is the operand length in bits: vl × SEW for a vector operand, and kliobuftop × 8 for a KLIOBUF operand, and 128 for the GPR operand of a Form D kl.setst, or for the zero-extended Xs of a Form B one. kliobuftop, like every other KLIOBUF CSR and klstart, is a number of bytes. For a KLIOBUF operand, kliobuftop plays the role of VL, and the transfer window is bytes [0, kliobuftop-1] (kliobuftop). For either operand of kl.exec, klstart plays the role of vstart: it is the byte position within the transfer window at which processing starts or resumes (klstart). kl.setst does not honor klstart: it reads its whole operand.

  • enc_blk(K, p) → c and dec_blk(K, c) → p: the encryption of block p, resp. the decryption of block c, under key K by the block cipher of the Machine.

  • trunc(V, n), for 0 ≤ n ≤ b and a value V of at least n bits: the b-bit value zeros(b-n) @ V[n-1:0], which keeps the n least significant bits of V and ignores the others; trunc(V, b) = V for a b-bit V.

  • pad10(X, n): for n a multiple of 8 with 0 ≤ n < b, the b-bit value holding the n-bit partial block X[n-1:0] followed, in string order, by a single 1 bit and then zeros, zeros(b-8-n) @ 0b10000000 @ X[n-1:0]. The terminating 1 is the most significant bit of byte n/8, not bit n of the value: within a byte, the first bit of the string is the most significant (Notation and Conventions). It is the padding of cite:[RFC7253] §4.2 and cite:[nist-SP-800-38B] §6.2.

General Rules for Machines

Besides the General Rules (GR) of Unprivileged Architecture: Instructions and Architectural States, in particular those governing the State field and its transitions (Rules Governing the State and StateExtension Fields and their Transitions), the following Machine Rules (MR) apply to all Machines, unless stated otherwise.

Machine Definition and Checks

MR1

Policy gate and entry conditions.

Each Machine states, for each of its States:

  • the bit of MachinePolicy (Machine and MachinePolicy Fields), if any, that enables its operation; “if encryption is allowed” refers to MachinePolicy[0] and “if decryption is allowed” to MachinePolicy[1]. A bit gates the States of its operation and every State that follows uniquely from them, its Gated States:

    • encryption: Encrypt, Enc_Last_Block, Enc_Tag_Finalize and, where it emits the tag of the encryption, Hash_Output;

    • decryption: Decrypt, Dec_Last_Block, Dec_Tag_Finalize and, in GCM Mode, OCB Mode and Ascon-AEAD128, Hash_Verify;

    • signature generation: Sign_Generate, Output with a signature, and Sign_Output;

    • signature verification: Sign_Input and Sign_Verify;

    • MAC generation: Hash_Output and Hash_Output_Bits; MAC verification: Hash_Verify; and

  • its entry conditions: what the State requires, such as the Has flags, the mode, and the other configuration of the CC that it uses.

Unless the Machine states otherwise, a zero MachinePolicy is invalid Metadata (Validity of Metadata) for a Machine that encrypts and decrypts, or that generates and verifies MACs, and valid for one that generates and verifies signatures: it then disables these operations and leaves the others, if any, available.

GCM with Preset IV, OCB with Preset Nonce and Ascon-AEAD128 with Preset Nonce, which carry their IV or nonce in the PI, admit only MachinePolicy = 0b10: they only decrypt. Any other value is invalid Metadata (Validity of Metadata), and a narrowing to it transitions the locker to Error State Invalid (Rule GR20).

A kl.exec, kl.derive, or kl.setst that is a usage instruction (State modification and usage control, per instruction) is checked:

  1. At issue, against MachinePolicy. The locker transitions to Error State Invalid, and the instruction performs no operation, if the instruction:

    1. is issued in a State whose operation MachinePolicy disables, or from which every operation that the Machine can complete is disabled, unless Rule GR19.3 admits it or it is a kl.setst naming a State that still leads to an enabled operation; or

    2. would enter a State whose operation MachinePolicy disables, by naming it or on its completion (Rule MR18).

  2. After it acts, against the entry conditions of the State that it enters. They are checked after the operations of leaving the current State, on the content that these and the instruction produce (such as the last part of the IV that the completing kl.exec of GCM Mode writes); if they fail, the locker transitions to Error State Invalid instead of entering the State.

Within a State, an instruction checks a condition only if it can change in that State or the check is one of Rule MR3. The Machine states the check with the instruction; a failed check transitions the locker to Invalid unless it detects a data error (Rule MR2).

MR2

Configuration errors and data errors. Each Machine states which of its checks detect a configuration error, and which a data error:

  • A configuration error transitions the locker to Error State Invalid. It is either:

    • a field that sets a parameter or a key of the CC, not the data of an operation, with a value that the referenced standard rejects, such as a malformed private key; or

    • a field (a peer point or a signature included) whose encoding violates a constraint that is checked when the field is written, such as the zero most significant bits of secp521r1 (Elliptic Curve Cryptography). A Machine may classify such a check as a data error instead, as ML-KEM does for the input checks of cite:[nist-fips-203] on encapsk and ciphertext. A constraint that the standard checks only when an operation decodes the value, such as the hint encoding of an ML-DSA signature (cite:[nist-fips-204] Algorithm 21), is a data error detected by that operation.

  • A data error transitions the locker to Failure, a Valid State. It is either:

    • a ciphertext, tag, signature, message representative or public key that is malformed, does not verify, or fails an input check that the Machine classifies as a data error, such as the check of an ML-KEM encapsulation key; or

    • a point an operation uses, such as a peer’s point, a public key or a generator, that is not a valid point of the curve.

MR3

Checks of a field. A check that the Machine attaches to a field and that depends on that field alone is made whenever the field is written: at the completion of its load (Rule MR14), of a kl.derive into it, of the provisioning that carries it, and of an import that restores it. Examples are the zero most significant bits of secp521r1, the well-formedness of an ML-DSA privkey, and the input checks of cite:[nist-fips-203] on an ML-KEM key. The check need not be repeated when the field is read, since the KLF guarantees the integrity of the locker (The Cryptographic Locker File and Authentication Information); a Machine may repeat it on a value that an interrupted operation resumes with, as secp521r1 does (Elliptic Curve Cryptography), and a repeated check that fails transitions the locker to Error State Invalid.

A check that depends on the operation or on more than one field is made by the operation that reads the field, before it changes any state. Examples are the validity of a point in the role that the operation gives it, the range of Scalar against the group order, and the consistency of a public key with a private key. Rule MR2 classifies the failure of any check other than a repeated one.

MR4

System-specific import. A system-specific import never circumvents the referenced standard of the Machine (Rule GR49). The converted Content undergoes the checks of Rule MR3, and a field that the Machine derives from another is derived from the converted Content, or checked against it, never taken from the format unchecked. A Machine whose Provisioning Input does not carry a field that a format may configure states how the import checks and marks that field, as ML-KEM and ML-DSA do.

Operands, Outputs and Fields

MR5

Form of a kl.setst with a short INPUT. Where a State expects a Form C kl.setst whose INPUT is at most 128 bits, a Form D one is admitted too, as is a Form A one, whose INPUT is a 128-bit zero. A Form B one is admitted only where the State says so, for an integer INPUT of at most 64 bits.

MR6

If KLLEN violates the granularity constraints of the Machine in its current State, the instruction performs no operation and the locker transitions to Error State Invalid, with its output window zeroed (Rule GR14). The granularity constrains the transfers of whole blocks, for instance to a multiple of the block size; for a final block or piece of last_block_len bits it is KLLEN ≥ last_block_len. A fixed-width input follows Rule MR8; the Machine defines the constraint on a tag that it admits truncated.

MR7

A field that a Machine can derive inexpensively from other fields of the same CC may be omitted from the Serialized Content. It is then recomputed when an import completes, by the kl.mgmt with #kl_cfg_management_end, whatever the format (a system-specific one included, Rule GR51), and whenever a field it depends on is modified, for instance by a kl.derive into a key field or an explicit operation of the Machine. The Machine states only the derivation, and marks the field “(derived)” in its Internal State.

MR8

Where a State consumes from INPUT a single value of fixed width, that of the field it assigns or of the operand it is defined over, the width need not be the block size b. If KLLEN exceeds that width, only that many least significant bits of INPUT are used and the rest are ignored; a smaller KLLEN violates the granularity (Rule MR6).

MR9

A State writes OUTPUT only within its output window, bits [8 × klstart, KLLEN − 1] (Rule GR14). An output longer than KLLEN is truncated to its KLLEN least significant bits, unless it is emitted over several kl.exec, as a long field (Rule MR14) or a digest or XOF output is; a KLLEN below a minimum that the Machine sets violates the granularity (Rule MR6). A State that writes fewer bits than the window holds clears the rest of the window. This concerns the bits within the operand; the tail-agnostic policy of RVV/KLV governs the elements beyond VL.

MR10

Final fractional block. A Machine whose input ends in a fractional block processes it in a State of its own, such as Enc_Last_Block, Dec_Last_Block or Hash_Absorb_Last_Block, the final-block State, as follows, unless the Machine defines otherwise; a kl.exec in it is checked first against the State (Rule GR13.5), then against its transfer window (Rule GR18), then by the Machine:

  1. The caller determines the bit length n of the final block (Rule MR11) and tests whether it is zero.

  2. If n = 0, no kl.exec is needed: a kl.setst into the final-block State with n = 0 (Xs = 0, or Form A) records last_block_len = 0 and performs the operations of the final block on empty input; where the Machine has a single successor of the final-block State, the locker enters it at once (item 3), unless the Machine defines otherwise. A kl.setst from the State preceding the final-block State to its successor, bypassing the final-block State, is equivalent to this and must be of Form A, unless the Machine names another Form, as GCM Mode does; where n is determined by the Machine (max_len != 0 in Macro: Processing Variable Length Inputs into a Fixed Length Output) and is not zero, the bypass transitions the locker to Error State Invalid.

  3. If n != 0, a kl.setst into the final-block State records last_block_len = n, and a single kl.exec (Rule MR13) processes the n least significant bits of its INPUT and ignores the other bits (Rule MR8); a KLLEN smaller than n is not zero-padded but violates the granularity (Rule MR6), and an empty transfer window does not reach the Machine (Rule GR18). Once the final block is processed, the locker transitions to the successor of the final-block State that the Machine names, and no kl.setst is needed to leave the final-block State.

  4. Where software chooses among several successors, as for the digest of a hash function (Hash_Output, Hash_Output_Bits or Hash_Verify, which may be gated separately by Rule MR1), or the entry of the successor takes an operand that the final-block State cannot supply, as the length block of Enc_Tag_Finalize and Dec_Tag_Finalize in GCM Mode, the Machine names no successor: the locker stays in the final-block State once the block is processed, or on entering it with n = 0, and software selects the successor with a kl.setst. A State whose final block is empty or already processed (last_block_len = 0) admits no kl.exec of Forms A to C, whatever its transfer window, even an empty one: one transitions the locker to Error State Invalid.

  5. A kl.setst, other than one naming Ready (Rule GR19.3), leaving the final-block State with n != 0 before its kl.exec transitions the locker to Error State Invalid, unless the Machine defines otherwise.

A Machine may require a native Form D kl.exec, which has no transfer window, as Enc_Last_Block and Dec_Last_Block of OCB Mode do: with n = 0 the locker stays in the State until that kl.exec, and item 2 does not apply. The designer of a new Machine follows this Rule, with OCB Mode and Ascon-AEAD128 as examples of a single successor, and Hash and MAC Functions, and XOFs of a choice of successors.

A second final block is not a continuation of the input but an attempt to manipulate the internal state of the Machine.
MR11

A last_block_len, or any other parameter giving the bit length of a final input piece, is a multiple of 8, unless the Machine either:

  • states that its referenced standard orders the bits within a byte as Notation and Conventions does, so that a truncation of the last byte to its least significant bits is the bit string that the standard defines (as for Ascon-AEAD128); or

  • defines which bits of the partial final byte carry the piece (as for the nonce of OCB Mode).

A value that the Machine does not admit transitions the locker to Error State Invalid. Whether zero is admissible depends on the Machine.

MR12

Verification of a tag. A Machine that verifies a tag or a MAC without disclosing the value it computes does so in constant time, and transitions to Success if the verification succeeds and to Failure otherwise (Rule MR2). The instruction that provides the tag or MAC to verify performs the verification. It is:

  • by default, a single Form B kl.exec in Hash_Verify, which supplies the expected value and compares the number of bits that the Machine holds in tag_len;

  • where the expected value is supplied first, as the SIV of GCM-SIV is (GCM-SIV Mode), the kl.exec that completes the internal tag computation.

CMAC Functions, GCM Mode, GCM with Preset IV, HMAC, Ascon-AEAD128, Ascon-AEAD128 with Preset Nonce and Ascon-AEAD128 with Nonce Masking compare a prefix of the tag or MAC. Every verification of a locker of these Machines compares the same number of bits, tag_len_p, which the AuxInfo field of its MDH holds (MachineUse and AuxInfo Fields):

  • tag_len_p is one of the tag lengths that the Machine admits, and the full length if KeyType = 1: 128 for GCM and Ascon-AEAD128, b for CMAC and t for HMAC. A provisioning or import whose AuxInfo holds another value completes into Error State Invalid (Rule MR3).

  • Provisioning keeps the AuxInfo of the PI, and entering Ready leaves it unchanged; these Machines define all its bits, so kl.clearads and an import without ADS leave it unchanged too.

  • A locker whose tag_len_p is shorter than the full length is not a kl.derive destination (Derivation Endpoints of the Machines).

  • A kl.setst naming Hash_Verify whose resulting tag_len differs from tag_len_p transitions the locker to Error State Invalid.

  • In Ascon-AEAD128 and its variants, entering Ready sets tag_len ← tag_len_p, and the Set_Aux_Value operation transitions the locker to Error State Invalid if its Xs differs from tag_len_p.

  • The tag or MAC that a locker of GCM or CMAC outputs has tag_len_p bits: a smaller KLLEN violates the granularity of the State (Rule MR6), and a larger one receives the tag with the bits beyond tag_len_p cleared (Rule MR9); Ascon-AEAD128 and its variants output tag_len = tag_len_p bits. HMAC, which also serves as a pseudorandom function, outputs as many bits as the caller chooses for each message; a caller that uses them as MACs keeps one length per key (Rule MR15).

Multi-block Operations

MR13

Single- and Multi-block kl.exec. In a State that processes whole blocks of b bits, one kl.exec applies the per-block operation of the State KLLEN/b times, for i = 0, b, 2b, …, KLLEN − b in that order, consuming INPUT[i+b-1:i] if the State takes an input and producing OUTPUT[i+b-1:i] if it produces an output. Blocks are taken and produced from the least significant position upward, here and throughout this specification. A resumed kl.exec performs only the iterations from i = 8 × klstart onwards (klstart).

A State that the Machine describes as processing a single block, such as a last-block, tag-finalize or verify State, or XEX Decrypt during ciphertext stealing (XEX/XTS Modes), processes exactly one block whatever KLLEN is, unless its transfer window is invalid (Rule MR6) or empty (Rule GR18). Rule MR10 governs a further kl.exec in a last-block State. The last_block_state of Macro: Processing Variable Length Inputs into a Fixed Length Output instead processes exactly its final piece, which may first complete the current block. The only interruption point of a kl.exec in such a State, or of one that processes a final piece, is 0 (Rule GR33.2).

MR14

Long fields transferred by several kl.exec. A State X that loads a long field from INPUT, or emits one to OUTPUT, over several kl.exec names a state field W that records the amount transferred so far, in bits or bytes. Where W is a field of the MDH, such as MachineUse, kl.rstr* cannot write it (kl.rstrl, kl.rstrh, and kl.rstrv). A digest or XOF output that a State emits from its internal state is not a long field: its Machine defines the progress and the outcome of an excess KLLEN, as Hash and MAC Functions, and XOFs does.

  1. Entry. Entering X zeroes W; entering a loading State also zeroes the field.

  2. Progress. W rises by the amount transferred: for a kl.exec that completes, by KLLEN − 8 × klstart bits or KLLEN/8 − klstart bytes, up to the size of the field; for one that halts, by its committed prefix (Rule GR33), so that its resumption adds only the remainder.

  3. Completion. The transfer is complete once W reaches the size of the field. Completion does not reset W; a transition that the Machine then makes zeroes it. Unless the Machine defines another transition, an emitting State transitions to Success, and a loading State admits no further kl.exec (Rule GR13.5).

  4. Excess. Excess data in the final load is ignored; an emitting kl.exec that would carry W past the field size transitions the locker to Error State Invalid.

  5. Incomplete load. A kl.setst that leaves a loading State X before the load is complete leaves the field unconfigured: it zeroes the field and any length of it set on entering X, and leaves its flag, if any, clear. A same-State kl.setst (Rule GR19.2) or kl.clearads restarts the load: as on entering X, it zeroes W and the field, and clears its flag, if any. A Machine whose next State needs the field states this as an entry condition (Rule MR1).

  6. Flags. A Machine may keep in StateExtension a flag per loaded field that records a configured value, such as the Has flags of the ECC, ML-KEM and ML-DSA Machines and the HasKey flag of HMAC. Unless the Machine states otherwise, entering the loading State clears the flag, and a load that completes and passes the checks of Rule MR3, or an operation of the Machine that computes the field, sets it; kl.getstx reads it. Each Machine lists its flags, their bit positions and any departure from this pattern.

  7. PROCESS_VLI. A load by PROCESS_VLI (Macro: Processing Variable Length Inputs into a Fixed Length Output) passes max_len = the size of the field and cumul_len = W. A field stored as loaded also passes block = state, b = n = its size, mode = assign and process_block = finalize = None; a field processed as loaded, such as the IV of GCM Mode, passes the functions and mode that its Machine states.

MR15

A Machine enforces only the per-message limits that its correctness needs at practical lengths and that it can track from its own state, such as the 32-bit counters of GCM Mode and GCM-SIV Mode and the bound on the L[i] array of OCB Mode. A Machine also fixes the verification length of each locker (Rule MR12). The caller keeps every other limit; no Machine counts or enforces it:

  • the length of a message is limited by the referenced standard, such as the 220 blocks of a data unit of cite:[nist-SP-800-38E], and by the width of a field that records it, such as the 64 bits of cumul_len, a width that no message reaches in practice; beyond the latter limit, the digest or tag is unspecified, but computed from the Content and the message alone and not otherwise secret Content (Rule GR8);

  • the use of a key across messages is limited as the referenced standard states, for instance in the total data processed, the number of failed verifications, or a parameter fixed for the lifespan of the key; the limit applies across every locker and SCC that holds the key, including its copies by kl.clone and its re-imports;

  • the uniqueness of a nonce, IV, counter or tag mask, as the referenced standard requires: no Machine prevents its reuse, whether by re-importing an earlier SCC, by kl.clone or by returning to Ready; a Machine that carries its IV or nonce in the PI only decrypts (Rule MR1).

Operations and Transitions

MR16

A Machine may declare a kl.setst an operation if it names a constant of Table 2 or a Machine-defined immediate, 66–127 (kl.setst and kl.setstq). An operation performs the stated action and leaves State unchanged; it changes StateExtension only where the Machine states so. It is not a transition: it performs none of the operations of leaving or entering a State (Rule MR17), and Rules GR19.2, GR38 and MR14 do not treat it as one. The Machine states the States in which the operation is allowed, and its Form; in any other State, a constant of Table 2 names a State, and a Machine-defined immediate is not admitted (Rule GR19.4). No Machine declares an operation in a State of Rule GR38. Set_Aux_Value, for instance, is an operation in CTR/XCTR Keystream Generation, Generic Tweakable Block Ciphers and Ascon-AEAD128, and a State in GCM Mode, GCM-SIV Mode and OCB Mode; kl_xex_state_steal is an operation in Decrypt of XEX/XTS Modes.

MR17

The operations that a Machine performs on entering or leaving a State, or on a change of State, apply only to the transitions between its Valid States that usage instructions make. A kl.setst naming Ready issued in Ready is such a transition: it performs the operations of entering Ready. A management operation’s moves into and out of a Configuration State perform none of them, and neither does the restoring of the saved State when an export or an import completes. Two events other than such a transition also perform the operations of entering Ready:

  • the completion of a provisioning, or of a system-specific import unless its format defines other initialization operations in their place (Rule GR51); and

  • a kl.derive that writes a key in Ready (Rule GR29 item 6).

MR18

Transitions that a Machine makes. A Machine may make a transition by itself: on completing a kl.exec, or the part of a kl.derive that acts at an endpoint as that kl.exec would (Rule GR28), or within a kl.setst that names another State. Such a transition is made only that way: no source State allows a kl.setst naming its destination (Rule GR19.4), unless the destination is Ready (Rule GR19.3) or the Machine lists that kl.setst.

Randomness

MR19

A Machine operation that needs random bits from an RBG or DRBG, such as the generation of a nonce, an ephemeral scalar or a signature into the locker, is an instruction of its own. That instruction works only on the locker and on scalar operands captured at issue, transfers no data to or from memory, vector registers, the KLIOBUF or another locker, and may be long-running (Long-Running Operation). If the RBG or DRBG cannot supply the bits, Rule GR45 applies.

An instruction that transfers data never waits or fails for lack of random bits, even when resumed, restored or restarted; further randomness that its Machine needs comes from another instruction.

Randomness that the implementation needs, such as masks, is supplied in advance, without weakening the required protection.

An internal algorithmic random value, such as a signing nonce or an ephemeral scalar, serves only the one instance of the scheme that requires it, and no other instance or purpose. It is never reused, not even when an interrupted operation restarts (Rule GR38). Resuming copies of one interrupted operation, restored from one image, completes that one instance on the same inputs and is not a reuse.

Input and Output Padding, Truncation, Byte Granularity

Unless the Machine specifies otherwise and pads internally, the caller must pad an input whose length the granularity of the State does not admit to a KLLEN that the Machine admits, and pass its actual length to the Machine, typically through kl.setst.

Cryptographic inputs are normally supplied through vector registers or the KLIOBUF, in whole bytes. For a standard that permits arbitrary bit lengths, the caller specifies the bit length of the final input piece, usually as a kl.setst parameter, and the Machine truncates that input to it. The Machine clears the output bits beyond the final piece, also within its last byte (Rule MR9).

This occurs, for instance, with the last_block_len parameters in GCM Mode, GCM-SIV Mode, OCB Mode, Ascon-AEAD128, and Hash and MAC Functions, and XOFs. Such a parameter gives the length to which the Machine truncates the passed input, not the length KLLEN of that input. Macro PROCESS_VLI receives field lengths in bits, but kl.exec always transfers whole bytes, and the last input may be truncated internally.

Where a standard’s formula requires the bit count of data that the Machine receives in whole bytes, it is the byte count multiplied by 8, as with the length block of GHASH in GCM Mode.

Symmetric Cryptography

This table, with Global CC State Numbers: Inert State, Global CC State Numbers: Valid States and Global StateExtension Codes at State 0: Unconfigured and Error States, defines the States of the symmetric Machines. A Machine may override these values and says so where it does; the public-key Machines define their own mnemonics.

Table 2. Common Constants defining CC states for Symmetric Machines
Value Mnemonic for the Constant State Name Description

2

kl_state_operate

Operate

Generic operational state.

kl_state_hash_absorb

Hash_Absorb

(Same value as Operate, with a mnemonic more intuitive for hash functions.) Absorb data: the message of a hash function, MAC or XOF, or the associated data of an AEAD scheme; on the encryption path of GCM-SIV Mode, also the plaintext. On entering the State, the Machine may initialize its tag or MAC computation.

3

kl_state_hash_last_block

Hash_Absorb_Last_Block

Absorb a final input piece whose length the kl.setst sets, such as the last partial block of the associated data or of a MAC input, or the final piece of a hashed message, of any bit length that the standard admits.

4

kl_state_hash_finalize

Hash_Finalize

Finalize the internal state of a hash/tag function.

5

kl_state_hash_verify

Hash_Verify

Compare the internal hash/tag value to the provided one.

6

kl_state_hash_output

Hash_Output

Enter the hash output phase of a hash/tag function.

7

kl_state_encrypt

Encrypt

Perform encryption, and any associated tag computation.

8

kl_state_decrypt

Decrypt

Perform decryption, and any associated tag computation.

9

kl_state_enc_last_block

Enc_Last_Block

Process the last block separately, on the encryption path of an authenticated encryption mode.

10

kl_state_dec_last_block

Dec_Last_Block

Process the last block separately, on the decryption path of an authenticated encryption mode.

11

kl_state_enc_tag_finalize

Enc_Tag_Finalize

Finalize the tag computation for AE mode encryption.

12

kl_state_dec_tag_finalize

Dec_Tag_Finalize

Finalize the internal tag computation for AE mode decryption; where the expected tag was supplied first, as in GCM-SIV Mode, also verify it (Rule MR12).

13

kl_state_set_aux_value

Set_Aux_Value

Set a public/auxiliary value in a cryptographic scheme implemented by the Machine.

14

kl_state_set_aux_value_2

Set_Aux_Value_2

Set a second public/auxiliary value in a cryptographic scheme implemented by the Machine.

15

kl_state_set_key

Set_Key

Reconfigure a key field.

16

kl_state_hash_output_bits

Hash_Output_Bits

Output the hash a set number of bits at a time.

Rule MR16 applies to the Machines that use Table 2 and to every Machine-defined immediate; Rules MR17 to MR18 apply to every Machine.

Electronic Codebook Mode

ECB mode cite:[nist-SP-800-38A-1] is the simplest way to use a block cipher.

Parameters
  • b = bit length of a block (b a multiple of 8), with b ≥ 64.

  • k = bit length of a key (k a multiple of 8).

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    pad

    Padding: (−kf) mod 128.

Machine-Specific Functions

enc_blk and dec_blk (Notation in the Machine Descriptions).

State Machine
  • States:

    • Ready: The CC is ready.

    • Encrypt: Encrypting blocks of input.

    • Decrypt: Decrypting blocks of input.

  • Allowed State Transitions:

    • Ready, Encrypt or Decrypt → Encrypt, if encryption is allowed (Rule MR1).

    • Ready, Encrypt or Decrypt → Decrypt, if decryption is allowed (Rule MR1).

    • Encrypt or Decrypt → Ready (Rule GR19.3).

  • Behavior:

    • The Machine allows a same-State kl.setst into Encrypt or Decrypt (Rule GR19.2), which changes nothing.

    • In Encrypt and Decrypt, (multi-block) Form A kl.exec instructions are expected. For each block, OUTPUT ← enc_blk(key, INPUT) in Encrypt, and OUTPUT ← dec_blk(key, INPUT) in Decrypt.

Chaining/Feedback Modes (CBC, CFB, and OFB)

Cipher Block Chaining (CBC), Cipher Feedback (CFB) and Output Feedback (OFB) cite:[nist-SP-800-38A-1] are defined here for a block cipher of block size b. CFB has a segment of u bits. CBC takes no padding or ciphertext stealing: the caller supplies whole blocks. CBC and CFB process data; OFB, like CTR (CTR/XCTR Keystream Generation), generates a keystream.

Parameters
  • b = block size (b a multiple of 8), with 64 ≤ b ≤ 128.

  • k = key size (k a multiple of 8).

  • u = segment size in bits (CFB only), with 0 < u ≤ b, a parameter of the CC held in AuxInfo (see the Behavior below).

  • Granularity: b bits in CBC and OFB; 8 bits in CFB, where a KLLEN below u violates it (Rule MR6).

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • IV: b bits, the chaining value: the initialization vector at first; then the last ciphertext block in CBC, the brev8 of the shift register of cite:[nist-SP-800-38A-1] in CFB (the last bits of the initialization vector followed by the ciphertext segments), and the last keystream block in OFB.

    • u: 8 bits (CFB only), held in AuxInfo[7:0] of the MDH, not serialized.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    b

    IV

    iii

    pad

    Padding: (−(kf + b)) mod 128.

Machine-Specific Functions

enc_blk and dec_blk (Notation in the Machine Descriptions).

State Machine
  • States:

    • Ready: The CC is ready.

    • Encrypt and Decrypt (CBC and CFB): Encrypting, resp. decrypting, blocks (CBC) or segments (CFB) of input.

    • Operate (OFB): The CC produces a keystream.

  • Allowed State Transitions:

    • CBC and CFB: Ready, Encrypt or Decrypt → Encrypt, if encryption is allowed, and → Decrypt, if decryption is allowed (Rule MR1).

    • OFB: Ready or Operate → Operate, if encryption or decryption is allowed (Rule MR1).

    • Encrypt, Decrypt or Operate → Ready (Rule GR19.3).

  • Behavior:

    • When entering Ready, IV ← 0.

    • In CFB, the segment size is fixed at provisioning: u = AuxInfo[7:0] (MachineUse and AuxInfo Fields), and AuxInfo[15:8] is zero. A provisioning or import whose AuxInfo violates this, or has u outside 0 < u ≤ b, completes into Error State Invalid (Rule MR3). Provisioning keeps the AuxInfo of the PI, and no operation changes it: CFB defines all its bits, so entering Ready, kl.clearads and an import without ADS leave it unchanged. With u = b the Machine is the full-block CFB.

    • When entering Encrypt, Decrypt or Operate, LOAD_FIXED_FIELD(IV, b) (LOAD_FIXED_FIELD(field, w)) loads the initialization vector. The Machine allows a same-State kl.setst into these States (Rule GR19.2), which replaces IV and keeps key.

    • In Encrypt and Decrypt, (multi-block) Form A kl.exec instructions are expected. In CBC, for each block, with INPUT the block of input:

      Mode Operation Semantics

      CBC

      Encrypt

      OUTPUT ← enc_blk(key, INPUT xor IV), IV ← OUTPUT

      Decrypt

      OUTPUT ← dec_blk(key, INPUT) xor IV, IV ← INPUT

      In CFB, INPUT is processed in n = ⌊`KLLEN`/u⌋ segments of u bits; the other bits are ignored, and software shifts them into the next kl.exec. The standard cite:[nist-SP-800-38A-1] numbers bits from the most significant bit of a byte. For each j from 0 to n-1, in increasing order, with Cj the ciphertext segment, Yj in Encrypt and Xj in Decrypt:

      1. W ← brev8(IV);

      2. Q ← brev8(enc_blk(key, IV))[u-1:0];

      3. Xj ← brev8(INPUT)[(j+1)u-1:ju];

      4. Yj ← Xj xor Q;

      5. IV ← brev8(Cj @ W[b-1:u]), with W[b-1:u] empty if u = b; and

      6. OUTPUT = brev8(Y), where Y has Yj in bits [(j+1)u-1:ju] and 0 above bit nu-1.

      The iterations of Rule MR13 are over the segments; the interruption points (Rule GR33.2) are the multiples of lcm(8, u)/8 bytes. For u a multiple of 8 the brev8 cancel: for each segment, Q = enc_blk(key, IV)[u-1:0] with the current IV, and IV ← Cj @ IV[b-1:u], with Cj the bytes of the segment in OUTPUT or INPUT.

      For each block or segment, INPUT is read before OUTPUT is written, so OUTPUT may be computed in place.

    • In Operate (OFB), (multi-block) Form C kl.exec instructions are expected. For each block, IV ← enc_blk(key, IV) and OUTPUT ← IV. As a kl.derive source (Derivation Endpoints of the Machines), Operate supplies the keystream of whole-block Form C kl.exec instructions, discarding the unused bytes of the last block.

The decryption of CFB uses enc_blk only. With u = b it is the full-block CFB; u = 8 and u = 1 are CFB8 and CFB1 of cite:[nist-SP-800-38A-1]. The caller ensures the uniqueness and unpredictability of the IV that the standard requires (Rule MR15); a Form A kl.setst sets it to zero.

CTR/XCTR Keystream Generation

In CTR mode, the IV and the counter are concatenated to form the input block of the underlying keyed PRP or PRF, so their lengths sum to its block size.

In XCTR mode, the IV has the block size; the counter is zero-extended to the block size, and its XOR with the IV forms the input block.

Parameters
  • b = block size (b a multiple of 8), with b ≥ 64.

  • k = key size (k a multiple of 8).

  • j = counter size: 32 in CTR mode, 64 in XCTR mode.

  • n = IV size (n a multiple of 8).

  • In CTR mode, b = n + j; in XCTR mode, b = n.

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • IV: n bits.

    • ctr: j bits.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    n

    IV

    iii

    j

    ctr

    iv

    pad

    Padding: (−(kf + n + j)) mod 128.

Machine-Specific Functions
State Machine
  • States:

    • Ready: The CC is ready.

    • Operate: The CC produces a keystream.

  • Allowed State Transitions:

    • Ready or Operate → Operate, if encryption or decryption is allowed (Rule MR1).

    • Operate → Ready (Rule GR19.3).

  • Behavior:

    • When entering Ready, IV ← 0, and ctr ← 0 in CTR mode and 1 in XCTR mode (as in the XCTR of HCTR2 cite:[cryptoeprint-2021-1441]).

    • When entering Operate, the kl.setst with immediate kl_state_operate invokes LOAD_FIXED_FIELD(IV, n, B) (LOAD_FIXED_FIELD(field, w)), which loads IV and leaves ctr unchanged. The Machine allows a same-State kl.setst into Operate (Rule GR19.2), which does the same.

    • In State Operate, (multi-block) Form C kl.exec instructions are expected. For each block, they perform:

      1. In CTR mode, tmp ← keystream_block(bswap(ctr) @ IV); in XCTR mode, tmp ← keystream_block(IV xor (zeros(b - j) @ ctr)).

      2. tick_ctr().

      3. OUTPUT ← tmp.

      As a kl.derive source (Derivation Endpoints of the Machines), Operate supplies the keystream of whole-block Form C kl.exec instructions, discarding the unused bytes of the last block.

    • In States Ready and Operate, the Form B kl.setst with immediate kl_state_set_aux_value and auxiliary operand Xs sets the counter: ctr ← bin(Xs, j). It is an operation, not a State (Rule MR16).

Setting the counter gives random access into a keystream, for example to resume an interrupted stream. ctr wraps modulo 2j and never carries into IV, so one IV yields at most 2j distinct counter blocks (in CTR mode, the incrementing function of cite:[nist-SP-800-38A-1] Appendix B.1 with m = j). No check detects the wrap (Rule MR15), since the Machine does not know where a message starts. In CTR mode, software that follows a protocol incrementing the whole counter block splits the kl.exec at the wrap, then sets the incremented IV and ctr = 0.

Code examples (b = 128): Encrypt with Keystream Generation.

XEX/XTS Modes

XEX cite:[DBLP-conf-asiacrypt-Rogaway04] turns a block cipher into a Tweakable Block Cipher (TBC) cite:[DBLP-conf-crypto-LiskovRW02], whose key and tweak together select the permutation that the cipher computes. Its two-key form builds a TBC Ẽ from a block cipher E, with keys K1 and K2, tweak T, and plaintext P:

       Ẽ(K1, K2, T, P) = E(K1, P xor M) xor M    where    M = E(K2, T)    is called a mask.

The single-key XEX of cite:[DBLP-conf-asiacrypt-Rogaway04], whose mask is x · E(K, T), is not architected. The Machine computes the mask once per tweak, by the kl.setst that sets the tweak; each block uses the current mask and then updates it by a multiplication in GF(2b). key1 is K1, which encrypts the data, and key2 is K2, which encrypts the tweak.

XTS cite:[DBLP-journals-ieeesp-Martin10], designed for storage confidentiality and a NIST Recommendation since 2010, adds two things to XEX: the tweak identifies the data unit, and a data unit whose length is not a multiple of b is completed by ciphertext stealing. Software obtains both from the XEX CC (XTS ciphertext stealing). The variants differ:

  • AES128_XEX and AES256_XEX follow cite:[nist-SP-800-38E] and cite:[IEEE-1619-2018]:

    • update_mask takes V[i] as the coefficient of xi;

    • the tweak, the INPUT of the kl.setst into Encrypt or Decrypt, is bin(i, b) (Notation and Conventions), the data unit sequence number i as a b-bit little-endian value;

    • a data unit has at most 220 blocks (Rule MR15).

  • SM4_XEX follows cite:[GBT-17964-2021]:

    • update_mask takes the bits of each byte in the reverse order;

    • the tweak is the 128-bit tweak of cite:[GBT-17964-2021], its first byte in byte 0.

The Machine cannot check that the two keys are independent: the provisioner must supply two independently generated keys, a System Key Identifier must resolve to two independently generated keys in the SKS, and software that derives key1 ‖ key2 (Derivation Endpoints of the Machines) must take it from a source whose two halves are independent, such as a keystream.

Parameters
  • b = 128 = block size.

  • k = key size (k a multiple of 8).

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key1 or System Key Identifier

    iii

    k or 0

    key2, or empty if KeyType = 1 (a single SKID retrieves both keys, Rule GR55.1)

    iv

    pad

    Padding: (−2k) mod 128, or 64 with a System Key Identifier.

  • Internal State:

    • key1: k bits.

    • key2: k bits. key2 = key1 is a configuration error (Rule MR2). It is checked whenever the keys are written: by a provisioning, by an import, and by a kl.derive into key1 ‖ key2. A provisioning checks them whether the PI gives them by value or by a System Key Identifier, or the provisioning generates them (KeyType = 2).

    • mask: b bits.

    • StealSkip and StealBack: bits 0 and 1 of StateExtension respectively, which record the two steps of ciphertext stealing in Decrypt (XTS ciphertext stealing). At most one of them is set, and only in Decrypt; the Machine supports no other StateExtension @ State.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key1 or System Key Identifier

    ii

    k or 0

    key2, or empty if KeyType = 1 (a single SKID retrieves both keys, Rule GR55.1)

    iii

    b

    mask

    iv

    pad

    Padding: (−2k) mod 128, or 64 with a System Key Identifier.

Machine-Specific Functions
  • update_mask(mask) multiplies mask by a generator of GF(2128): it is the multiplication by x modulo x128 + x7 + x2 + x + 1. For AES128_XEX and AES256_XEX (cite:[IEEE-1619-2018] §5.2),

           update_mask(V) = V << 1     if V[127] = 0

    and

           update_mask(V) = (V << 1) xor (zeros(120) @ 0b10000111)    otherwise.

    For SM4_XEX, with Bj = V[8j+7:8j], byte j of V, update_mask(V) = B'15 @ … @ B'0, where

           B'j = Bj-1[0] @ Bj[7:1]    for 0 < j < 16,

           B'0 = B0 >> 1     if B15[0] = 0,    and B'0 = (B0 >> 1) xor 0xE1    otherwise.

  • mask ← update_mask_inv(mask) where update_mask_inv inverts update_mask, dividing by x.
    For AES128_XEX and AES256_XEX,

           update_mask_inv(V) = V >> 1     if V[0] = 0

    and

           update_mask_inv(V) = ((V xor (zeros(120) @ 0b10000111)) >> 1)
                 xor (0b1 @ zeros(127))    otherwise.

    For SM4_XEX, with Bj byte j of V as above, c = B0[7], and A = B0 if c = 0 and A = B0 xor 0xE1 otherwise, update_mask_inv(V) = B'15 @ … @ B'0, where

           B'j = Bj[6:0] @ Bj+1[7]    for 0 < j < 15,

           B'0 = A[6:0] @ B1[7]    and    B'15 = B15[6:0] @ c.

State Machine
  • States: Ready, Encrypt, and Decrypt (defined as before, cf. Electronic Codebook Mode), and Success.

  • Allowed State Transitions:

    • Ready, Encrypt or Decrypt → Encrypt, if encryption is allowed (Rule MR1).

    • Ready, Encrypt or Decrypt → Decrypt, if decryption is allowed (Rule MR1).

    • Decrypt with StealBack set → Success, by the Form A kl.exec that ends ciphertext stealing.

    • Encrypt, Decrypt or Success → Ready (Rule GR19.3).

  • Behavior:

    • Every transition, same-State kl.setst included, clears StealSkip and StealBack.

    • When entering Ready, mask ← 0.

    • When entering Encrypt or Decrypt, LOAD_FIXED_FIELD(mask, b, B) (LOAD_FIXED_FIELD(field, w)) loads the tweak into mask, and then mask ← enc_blk(key2, mask) computes the initial mask. The Machine allows a same-State kl.setst into Encrypt or Decrypt (Rule GR19.2), which does the same: it takes a new tweak and performs both steps.

    • In States Encrypt and Decrypt, with StealSkip and StealBack clear, (multi-block) Form A kl.exec instructions are expected. For each block, they read the INPUT and determine the OUTPUT:

      1. In State Encrypt, OUTPUT ← mask xor enc_blk(key1, INPUT xor mask); in State Decrypt, OUTPUT ← mask xor dec_blk(key1, INPUT xor mask).

      2. mask ← update_mask(mask).

    • In State Decrypt, the Form A kl.setst with immediate kl_xex_state_steal (66) starts ciphertext stealing. It is an operation (Rule MR16). If StealSkip or StealBack is set, it transitions the locker to Error State Invalid; otherwise it:

      1. mask ← update_mask(mask);

      2. sets StealSkip.

    • In State Decrypt with StealSkip set, a Form A kl.exec processes a single block (Rule MR13):

      1. OUTPUT ← mask xor dec_blk(key1, INPUT xor mask);

      2. mask ← update_mask_inv(mask);

      3. it clears StealSkip and sets StealBack.

    • In State Decrypt with StealBack set, a Form A kl.exec processes a single block (Rule MR13):

      1. OUTPUT ← mask xor dec_blk(key1, INPUT xor mask);

      2. the locker transitions to Success.

Code examples, with ciphertext stealing: XEX Encryption, XEX Decryption.

Ciphertext stealing. A data unit of whole blocks is processed, in both directions, by the plain XEX sequence over its blocks. Otherwise, let it be m ≥ 1 full blocks P0 … Pm-1 followed by a partial block Pm of s bits, with 0 < s < b and s a multiple of 8. The locker is at mask index j when its mask is update_mask applied j times to enc_blk(key2, T), where T is the tweak. Blocks are processed in order (Rule MR13), so the j-th block after the tweak is set, counting from 0, uses mask index j. CP @ Pm and CP @ Cm place the partial block in the least significant bits, where the first s/8 bytes of a string are (Notation and Conventions).

Encryption consumes the mask indices in order:

  1. Issue kl.exec for P0 … Pm-2, obtaining C0 … Cm-2 (no instruction if m = 1).

  2. Issue kl.exec for Pm-1, obtaining CC at mask index m-1; Cm ← CC[s-1:0] and CP ← CC[b-1:s].

  3. Issue kl.exec for CP @ Pm, obtaining Cm-1 at mask index m.

  4. The ciphertext is C0 … Cm-1, Cm, with Cm the final s bits.

Decryption consumes mask index m before mask index m-1; the stealing steps of the Machine reorder the two:

  1. Issue kl.exec for C0 … Cm-2, obtaining P0 … Pm-2 (no instruction if m = 1); the mask is at index m-1.

  2. Issue the Form A kl.setst with immediate kl_xex_state_steal, which skips mask index m-1.

  3. Issue kl.exec for Cm-1, obtaining PP at mask index m; the mask returns to index m-1.

  4. Pm ← PP[s-1:0] and CP ← PP[b-1:s].

  5. Issue kl.exec for CP @ Cm, obtaining Pm-1 at mask index m-1; the locker transitions to Success.

Decryption with stealing adds the kl.setst with immediate kl_xex_state_steal to the data unit. The data unit ends in Success, so a kl.setst into Ready precedes the kl.setst that sets the next tweak.

Generic Tweakable Block Ciphers

The specification of a generic tweakable block cipher resembles that of a block cipher in ECB mode. Since kl.exec takes a single input, a separate instruction sets the tweak. A tweak longer than the block may need the vector length reconfigured between setting the tweak and processing blocks.

Some commonly used TBCs are Deoxys-BC cite:[Deoxys-141], SKINNY cite:[DBLP-conf-crypto-BeierleJKL0PSSS16], QARMA cite:[DBLP-journals-tosc-Avanzi17], and QARMAv2 cite:[DBLP-journals-tosc-AvanziBDEGNR23].

Parameters
  • b = block size (b a multiple of 8), with b ≥ 64.

  • k = key size (k a multiple of 8).

  • t = tweak size (t a multiple of 8).

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • tweak: t bits.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    t

    tweak

    iii

    pad

    Padding: (−(kf + t)) mod 128.

State Machine
  • States: Ready, Encrypt, and Decrypt (cf. Electronic Codebook Mode). Setting the tweak is an operation, not a State (Rule MR16).

  • Allowed State Transitions:

    • Ready, Encrypt or Decrypt → Encrypt, if encryption is allowed (Rule MR1).

    • Ready, Encrypt or Decrypt → Decrypt, if decryption is allowed (Rule MR1).

    • Encrypt or Decrypt → Ready (Rule GR19.3).

  • Behavior:

    • When entering Ready, the tweak field is cleared.

    • The Machine allows a same-State kl.setst into Encrypt or Decrypt (Rule GR19.2), which leaves tweak unchanged.

    • In States Ready, Encrypt and Decrypt, the Form C kl.setst with immediate kl_state_set_aux_value and auxiliary operand INPUT is the set-tweak operation: it invokes LOAD_FIXED_FIELD(tweak, t, B) (LOAD_FIXED_FIELD(field, w)), which loads tweak.

    • In Encrypt and Decrypt, (multi-block) Form A kl.exec instructions are expected. For each block, they encrypt, resp. decrypt, INPUT into OUTPUT under key and tweak. Every block uses the current tweak; the Machine never updates it by itself.

Macro: Processing Variable Length Inputs into a Fixed Length Output

Many Machines process variable-length inputs into fixed-length outputs, for instance to hash, or to derive an internal fixed-length IV from a variable-length external one. They do so in specific States, such as Hash_Absorb. This section describes the semantics of such a State, called Current_State here. PROCESS_VLI is a macro, not a subroutine: an invocation splices the behavior below into the State Machine of the calling Machine, with each parameter replaced by the variable or function that it names, and with any change to its steps that the invoking Machine states, such as the final piece of SHA-2 Family Specific Rules and the postponed step 3.g of BLAKE2 Specific Rules. The macro defines how the kl.exec instructions of Current_State and last_block_state consume their INPUT. A kl.setst passes the macro no data. A kl.exec that a State of the macro admits, with an empty transfer window (Rule GR18), does not reach the macro; the macro behaves as if the caller had made extra kl.exec calls that transfer nothing: it changes none of the variables, and the State is kept. The kl.setst that enters Current_State may set max_len (Form B), and the one that enters last_block_state may set last_block_len. Any other operand of a kl.setst is defined by the invoking Machine.

A Machine invokes it as:

PROCESS_VLI(max_len,
            block,           b,               state,           n,
            input_base,      block_base,      state_offset,    cumul_len,
            process_block(), finalize(),      mode,            granularity,
            last_block_state, process_last_block(),            last_block_len)

where each parameter is a reference to a variable or function of the calling Machine, or None where the calling Machine does not define it:

  1. max_len is the total length of the data to be absorbed, in bits. If neither software nor the Machine sets it (see State Machine Behavior below), max_len is zero.

  2. block contains the current block being filled internally before processing. Its size is b bits.

  3. state is the output buffer. It may be the same as block. Its size is n bits.

  4. input_base is the offset, within the INPUT of the kl.exec, of the next data to absorb.

  5. block_base is the offset, within the current block, of the next data to absorb: within block if mode is assign, and within state from state_offset if mode is xor_accumulate (steps 3.b and 3.c). Each time it reaches b, the block is processed (step 3.g).

  6. state_offset is the offset within state at which the input is XORed, for instance in sponge constructions.

  7. cumul_len is the cumulative length of the data absorbed so far by the macro, or None if not tracked.

  8. mode is either assign or xor_accumulate, and selects how incoming data is combined with the destination, as specified in steps 3.b and 3.c below. It is not inferred from whether block and state denote the same variable.

  9. last_block_state is the State in which a final piece of the input is absorbed, or None.

  10. last_block_len is the variable of the calling Machine that contains the bit length of the final piece still to be absorbed, or None if last_block_state is None.

input_base, block_base, cumul_len and last_block_len, the last two whenever they are given, must denote distinct storage locations. They are updated independently: input_base is set to 8 × klstart at the start of every kl.exec (step 2), whereas block_base and cumul_len persist across instructions. An invocation that binds two of them to the same location is malformed: the macro would update that location several times per iteration.

When max_len is not 0 or last_block_state is not None, cumul_len must not be None: the macro evaluates it unconditionally in those cases.

When mode is xor_accumulate, the caller must satisfy state_offset + b ≤ n. The destination of step 3.c ends at bit block_base + amount + state_offset − 1, and block_base + amount can reach b, so a larger state_offset would write past the end of state.

mode is an explicit parameter because the two combining rules are not interchangeable. Sponge constructions require xor_accumulate: they XOR the input directly into the rate portion of the state. A field loaded rather than absorbed, in particular key and key-like material, requires assign. Selecting xor_accumulate where assign is meant combines the incoming value with whatever the field already held. For a key field, this silently yields a key that neither party chose.

The macro does not initialize the persistent state variables block_base and cumul_len. The invoking Machine zeroes them where needed. A Machine that enters a State with mode = assign, and whose destination field must hold a defined value once loading completes, must zero that field on entry to the State.

The macro leaves block_base and cumul_len alone so that several invocations of it can concatenate their results.

Units. max_len, b, n, input_base, block_base, state_offset, cumul_len, last_block_len, and amount are all counted in bits, to support values of max_len that are not multiples of 8 bits. However, the macro only supports values of b and n that are multiples of 8 bits, and all kl.exec instructions transfer whole bytes and never a fraction of a byte. As a consequence, input_base and block_base are multiples of 8, with two exceptions: after the final transfer of an input whose max_len is not a multiple of 8, which ends the instruction (step 3.h), and after a final piece absorbed in last_block_state.

Finally, three parameters are functions of the calling Machine:

  • process_block()=process_block(block, state) processes the current block into state. It may be given as None, in which case no such call is made, and the macro uses state only in step 3.c.

  • finalize() finalizes the processing of the input data, completing the current block where the Machine’s rules require it. It may also be given as None, in which case no such call is made.

  • process_last_block()=process_last_block(block, state) processes the block that holds the final bit of a piece absorbed in last_block_state, in place of process_block(). It may be given as None, in which case that block is processed as any other.

The last three parameters may be omitted, and are passed as None: the steps for last_block_state below do not apply.

Passing None for both process_block() and finalize() reduces the macro to its accounting of partial progress across kl.exec instructions; a Machine needs this when it only has to fill a long field from memory and has no per-block processing to perform.

A Machine whose final piece needs a State of its own passes last_block_state. It also passes process_last_block() if the block that holds the final bit needs processing of its own.

The optional parameter granularity specifies the transfer unit for inputs.

  • Where max_len = 0, granularity constrains no KLLEN: every KLLEN that is a multiple of 8 is absorbed, and granularity only restricts the interruption points (step 3.i).

  • Where max_len != 0, a transfer violates the granularity of the State (Rule MR6) if its KLLEN is not a whole multiple of granularity and cumul_len + KLLEN < max_len. In this test, cumul_len is its value when the instruction is issued, whether the instruction starts or resumes.

  • Every other KLLEN meets the granularity of the State, so max_len need not be a multiple of granularity.

  • Where last_block_state is None, the data beyond max_len is ignored (step 3.h, Input and Output Padding, Truncation, Byte Granularity); otherwise step 1 requires each transfer to end before max_len. For example, with granularity = 128, a 96-bit IV is supplied in a single transfer, either as a 96-bit vector or as a 128-bit vector with excess bits truncated.

  • Since KLLEN counts the bytes that a non-zero klstart skips, a resumed transfer with a KLLEN that is not a whole multiple of granularity is also admitted and ends before max_len with a partial block.

Internal State Variables

Besides the variables that the parameters name, the Machine may define variables for process_block(), process_last_block() and finalize(). max_len keeps its value for the duration of the computation.

State Machine Behavior
  • When entering State Current_State:

    1. If software sets max_len, it passes it to a Form B kl.setst, which sets max_len to its auxiliary operand Xs.

    2. Otherwise, max_len is set by the Machine, and the kl.setst that enters the State is of Form A, or of Form B where the invoking Machine defines its Xs; such a kl.setst does not set max_len.

  • While in State Current_State, only kl.exec instructions of Form B are expected, each of which processes its INPUT.

    1. If max_len != 0, the locker transitions to Error State Invalid if either:

      1. cumul_len ≥ max_len; or

      2. last_block_state is not None and cumul_len + KLLEN − 8 × klstart ≥ max_len.

        An empty transfer window never reaches the macro (Rule GR18), so a kl.exec that transfers nothing is not Invalid here, even once cumul_len ≥ max_len: a State that still admits the kl.exec keeps its State, and one that admits none (Rule GR13.5) is Invalid before the macro.

    2. input_base ← 8 × klstart: 0 when the instruction starts, the point of progress when it resumes. Nothing else distinguishes a start from a resumption.

    3. while (input_base < KLLEN) do:

      1. If max_len != 0 then amount ← min(KLLEN - input_base, b - block_base, max_len - cumul_len), else amount ← min(KLLEN - input_base, b - block_base). amount is always strictly positive, so the loop terminates.

      2. if mode = assign then:

        1. block[block_base + amount - 1 : block_base] ← INPUT[input_base + amount - 1 : input_base].

      3. else, that is if mode = xor_accumulate:

        1. XOR INPUT[input_base + amount - 1 : input_base] to state[block_base + amount + state_offset - 1 : block_base + state_offset].

      4. input_base ← input_base + amount.

      5. block_base ← block_base + amount.

      6. If cumul_len is not None, then cumul_len ← cumul_len + amount.

      7. If (block_base = b) then:

        1. process_block(block, state), if process_block() is not None.

        2. block_base ← 0.

      8. If max_len != 0 and cumul_len = max_len then:

        1. finalize(), if finalize() is not None.

        2. The instruction is terminated, even if input_base < KLLEN.

      9. Here, and only here, the instruction may be interrupted while input_base < KLLEN, if the invocation gives no granularity or input_base is a whole multiple of it, with klstart ← input_base / 8.

    Architected state alone determines the interruption points of kl.exec in Current_State (Rule GR33.2). They are the byte offsets k for which 8 × k is a multiple of granularity, or every byte offset if the invocation gives no granularity. An instruction issued while the locker holds block_base ≠ 0 admits only klstart = 0: any other klstart transitions the locker to Error State Invalid, as in Rule GR18.

    Every pass but the last ends with a full block, so a halt leaves block_base = 0; the last pass may leave a partial block. A halted instruction is resumed with block_base = 0, whatever block_base it started with, and the klstart that its halt recorded is an interruption point of the resumed instruction. An instruction issued with a non-zero block_base can still halt where step 3.i allows it, once its first iteration has completed the block. At a halt, input_base is a whole number of bytes, so klstart never describes a position inside a byte, as is also the case on the output side of Hash_Output (Hash and MAC Functions, and XOFs).
  • Where last_block_state is not None:

    1. If max_len = 0, the invoking Machine sets last_block_len ← b on entering Current_State. Software then issues a kl.setst naming either last_block_state or another State that the invoking Machine admits from Current_State, such as Hash_Output in Hash and MAC Functions, and XOFs.

    2. If max_len != 0, Current_State absorbs fewer than max_len bits (step 1), and software enters last_block_state, which absorbs the rest.

  • When entering last_block_state from Current_State:

    1. If max_len = 0, a Form B kl.setst invokes FINAL_BLOCK_ENTRY(0, b, unit) (FINAL_BLOCK_ENTRY(lo, hi, unit)), with the unit that Rule MR11 admits; with Xs = 0, a kl.exec in last_block_state transitions the locker to Error State Invalid (step 1 below).

    2. If max_len != 0, the kl.setst is of Form A and sets last_block_len ← max_len − cumul_len.

      1. If this new last_block_len > b, the locker transitions to Error State Invalid.

    3. finalize() is not performed.

  • In last_block_state, a single Form B kl.exec absorbs INPUT[last_block_len-1:0] (Rule MR10, item 3), with the only interruption point 0 (Rule MR13), and performs:

    1. If last_block_len = 0, the locker transitions to Error State Invalid (Rule MR10).

    2. input_base ← 0.

    3. while (input_base < last_block_len) do:

      1. amount ← min(last_block_len - input_base, b - block_base).

      2. Steps 3.b to 3.f of the kl.exec in Current_State.

      3. If block_base = b and either input_base < last_block_len or process_last_block() is None, then:

        1. process_block(block, state), if process_block() is not None.

        2. block_base ← 0.

    4. If process_last_block() is not None, then:

      1. process_last_block(block, state),

      2. block_base ← 0.

    5. last_block_len ← 0.

  • A kl.setst that transitions the locker from Current_State or last_block_state to another State performs finalize() before the transition, if finalize() is not None and step 3.h has not performed it. This does not apply where the destination is:

    1. Ready or an Error State; or

    2. last_block_state, from Current_State.

  • The locker transitions to Error State Invalid on:

    1. leaving last_block_state, with last_block_len != 0, for a Valid State other than Ready;

    2. where max_len != 0 and last_block_state is not None, leaving Current_State for a Valid State other than Ready or last_block_state.

Common Operations

The operations of this section, like PROCESS_VLI (Macro: Processing Variable Length Inputs into a Fixed Length Output), are macros: an invocation splices the behavior stated here into the State or instruction that invokes it, with each parameter replaced by the variable, value or function that the Machine passes, and with any change that the Machine states. Each one applies the Machine Rules that it cites; a Machine that invokes it does not restate them. PRESET (PRESET(parent, field)) differs: a Machine invokes it to define itself as a variant of another Machine.

LOAD_FIXED_FIELD(field, w)

Invoked by the kl.setst that enters a State, or that performs an operation (Rule MR16), and takes a value of w bits as INPUT:

  1. Its native Form is C. Where w ≤ 128, Forms A and D are admitted too (Rule MR5); where the invocation passes B as a third parameter, Form B is admitted, whatever w.

  2. field ← INPUT[w-1:0]; the other bits of INPUT are ignored (Rule MR8).

  3. Where the macro is invoked on entering a State, a same-State kl.setst into that State that the Machine allows (Rule GR19.2) does the same: it replaces field and performs the steps that the Machine adds, and changes nothing else.

LOAD_LONG_FIELD(len, block, state, n, process_block(), finalize(), mode, g)

Defines a State X that loads a field of len bits over several Form B kl.exec (Rule MR14), with W = cumul_len, in bits:

  1. Entering X zeroes input_base, block_base and cumul_len, and the field where mode = assign, and clears its flag, if any. The Machine allows a same-State kl.setst (Rule GR19.2), which does the same and restarts the load, discarding the part loaded so far.

  2. Each kl.exec in X invokes
       PROCESS_VLI(len, block, b, state, n, input_base, block_base, 0, cumul_len,
          process_block(), finalize(), mode, g),
    with last_block_state = None (Macro: Processing Variable Length Inputs into a Fixed Length Output).

  3. The load is complete once cumul_len = len; a field stored as loaded then sets its flag, if any (Rule MR14).

  4. Leaving X before the load is complete leaves the field unconfigured (Rule MR14, item 5).

FINAL_BLOCK_ENTRY(lo, hi, unit)

Invoked by the Form B kl.setst with auxiliary operand Xs that enters a final-block State (Rule MR10):

  1. Xs must be a multiple of unit with lo ≤ Xs ≤ hi; unit is 8 unless Rule MR11 lets the Machine pass 1. Any other Xs transitions the locker to Error State Invalid (Rule MR11).

  2. last_block_len ← Xs, the bit length of the final block.

  3. If Xs = 0, which requires lo = 0, the kl.setst processes the empty final block as Rule MR10 item 2 states, unless the Machine states otherwise; with lo > 0, an empty final block takes the bypass of that item instead.

  4. Otherwise, a single kl.exec in the State processes INPUT[last_block_len-1:0] and sets last_block_len ← 0 (Rule MR10 item 3): a KLLEN smaller than last_block_len is not zero-padded but violates the granularity, and an empty transfer window does not reach the Machine.

SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)

SET_TAG_LEN(cap, lo) is invoked by the Form B kl.setst with immediate kl_state_hash_verify and auxiliary operand Xs that enters Hash_Verify (Rule MR12):

  1. Xs must be a multiple of 8 with Xs ≥ lo.

  2. tag_len ← min(Xs, cap), or Xs where cap is None, which must equal tag_len_p (Rule MR12).

  3. Any other Xs transitions the locker to Error State Invalid.

VERIFY_TAG(expected, len), with len = tag_len where the invocation omits it, is invoked by the single Form B kl.exec that verifies a tag or MAC (Rule MR12):

  1. It compares INPUT[len-1:0] with expected[len-1:0] in constant time; the other bits of INPUT are ignored (Rule MR8).

  2. If they match, the locker transitions to Success; otherwise, to Failure.

  3. A KLLEN smaller than len violates the granularity of the State (Rule MR6).

PRESET(parent, field)

Defines a Machine that is the Machine parent with field, the IV or nonce that parent takes from software for each message, carried in the Provisioning Input instead, as the Machine’s PI table shows:

  1. Provisioning sets field, or the Internal State that the Machine forms from it, from the PI, and an import from the Serialized Content; no instruction sets field. The step of parent that loads field from INPUT does not apply, and the Machine states what replaces it.

  2. Entering Ready keeps field, with any step that the Machine states for it, so a later message is decrypted under the same field; software that needs another field provisions another locker.

  3. The Machine only decrypts (Rule MR1): the party that provisions the locker encrypts under the key and field once, by other means (Rule MR15).

  4. The Machine is not a kl.derive destination (Derivation Endpoints of the Machines): its key and field are configured together, by provisioning or import.

Where parent is a block cipher mode, such as GCM Mode or OCB Mode, the Machine protects the confidentiality of field. Since it only decrypts, the uniqueness requirement on field of the standard of parent binds the party that encrypts, once, under the key and field. A key that software knows, derived into the key field while field is kept, would let it recover field. So would the same key in another locker that software can use, if that locker:

Software holds the same key in another locker when it can provision, by its SKID, a System Key that the SKS allows for that locker’s Machine.

GCM Mode

The GCM mode was designed by David McGrew and John Viega cite:[DBLP-conf-indocrypt-McGrewV04] and became a NIST Recommendation in 2007 cite:[nist-SP-800-38D]. cite:[nist-SP-800-38D] §5.1 defines GCM only for block ciphers whose block is 128 bits, such as AES and SM4 (Table 1).

Parameters
  • k = key size (k a multiple of 64).

  • b = 128 = block size in bits.

  • c = 32 = counter size in bits.

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • J0: 128 bits. The pre-counter block of cite:[nist-SP-800-38D] §7.1, a byte string (Notation and Conventions); its bytes 12 to 15, J0[127:96], hold the big-endian counter of the last counter block used, start_ctr before the first block.

    • auth_key (derived): 128 bits. Rule MR7 applies.

    • tag: 128 bits. In Set_Aux_Value, the IV absorbed so far: the running GHASH value over it, or, if len = 96, the IV itself. Then the running GHASH value over the AD and the ciphertext; once finalized, the tag.

    • start_ctr: an integer in the range 0 to 232-1, the counter of the pre-counter block J0 of cite:[nist-SP-800-38D] §7.1; the first block uses the initial counter block inc32(J0), of counter (start_ctr + 1) mod 232.

    • last_block_len: 0, or a multiple of 8 from 8 to 120. The bit length of the final, partial block of the plaintext or ciphertext.

    • tag_len: the number of bits that Hash_Verify compares, one of 128, 120, 112, 104, 96 and 64, or 0 before it is set; serialized on 16 bits.

    • tag_len_p: the length of every tag that the locker outputs, and the number of bits that every verification compares (Rule MR12): one of 128, 120, 112, 104, 96 and 64 (cite:[nist-SP-800-38D] §5.2.1.2), and 128 if KeyType = 1; held in AuxInfo, not serialized.

    • len, block_base, cumul_len, input_base: in Set_Aux_Value, the max_len, block_base, cumul_len and input_base of Macro: Processing Variable Length Inputs into a Fixed Length Output for the IV. input_base is not serialized.

    The variables len, input_base, block_base and cumul_len of the internal state may overlap with J0, or be separate fields, as may be necessary if the implementation of macro PROCESS_VLI (Macro: Processing Variable Length Inputs into a Fixed Length Output) works with integers of a different length. Where they overlap, they hold their values only until finalize() writes J0, and the transition to Hash_Absorb leaves J0 as finalize() wrote it.

  • Serialized Content:

    Pos. Size (Bits) Field Description

    i

    k or 64

    key

    Key value or System Key Identifier

    ii

    128

    J0

    The pre-counter block of cite:[nist-SP-800-38D] §7.1, a byte string; J0[127:96], its bytes 12 to 15, holds the big-endian counter of the last counter block used, start_ctr before the first block.

    iii

    128

    tag

    iv

    32

    start_ctr

    The counter of the pre-counter block J0 before the first block, serialized as bin(start_ctr,32).

    v

    16

    last_block_len

    vi

    16

    tag_len

    Zero, or one of 128, 120, 112, 104, 96 and 64, and nonzero exactly in State Hash_Verify; an import that violates this transitions the locker to Error State Invalid (Rule MR3).

    vii

    pad

    Padding

    Zero; (−(kf + 320)) mod 128 = (−(kf + 64)) mod 128 bits.

    While the locker is in State Set_Aux_Value, J0 is replaced by the following fields:

    Pos. Size (Bits) Field Description

    ii.a

    16

    len

    Total length of the IV, in bits.

    ii.b

    16

    Padding

    Zero.

    ii.c

    16

    block_base

    Amount of data, in bits, absorbed so far into the current block.

    ii.d

    48

    cumul_len

    Cumulative length, in bits, of the data absorbed so far.

    ii.e

    32

    Padding

    Zero.

There are no fields for the lengths of the AD and of the plaintext, as they are maintained by the calling software.
Machine-Specific Functions
  • absorb(data) absorbs data into the hash function by performing:

    1. tag ← tag xor data.

    2. tag ← Galoismul(tag, auth_key).

  • next_ks() → bits(b) steps the counter and returns the next keystream block:

    1. ctr ← (int(bswap(J0[127:96])) + 1) mod 232, with ctr a local integer.

    2. If ctr = (start_ctr - 1) mod 232 (at most 232 − 2 blocks), the locker transitions to Error State Invalid, and the calling kl.exec performs no further step.

    3. Otherwise, J0[127:96] ← bswap(bin(ctr,32)), the counter back in big-endian, and next_ks() returns enc_blk(key, J0).

  • close_tag(L) absorbs the length block L and masks the tag:

    1. absorb(L).

    2. tag ← tag xor enc_blk(key, bswap(bin(start_ctr,32)) @ J0[95:0]).

  • Galoismul(a, b) is multiplication in the GHASH field of cite:[nist-SP-800-38D] §6.3, in the representation of that section.

    The field is GF(2)[x] modulo x128 + x7 + x2 + x + 1. A 128-bit value V represents the element whose coefficient of x8i+j, for 0 ≤ i < 16 and 0 ≤ j ≤ 7, is V[8i + (7-j)].

    In other words, the byte order runs forward (“little endian”: the byte at offset 0 contains the coefficients of x0 through x7, the byte at offset 1 contains the coefficients of x8 through x15, and so on) while the bit order is reversed within each byte: in the byte at offset 0, bit 0, the least significant bit, is the coefficient of x7, bit 1 that of x6, and so on.

State Machine
  • States:

    Besides Ready, Success, and Failure, the GCM Mode Machines make use of the following States:

    • Set_Aux_Value: Absorb the IV; the kl.exec that completes it computes J0.

    • Hash_Absorb: Process Associated Data (AD) into the tag.

    • Encrypt: Encrypt the plaintext and absorb the ciphertext into the tag.

    • Enc_Last_Block: Encrypt the final, fractional block of the plaintext.

    • Enc_Tag_Finalize: Finalize the encryption tag, prepare to return its value.

    • Decrypt: Absorb the ciphertext into the tag and decrypt it.

    • Dec_Last_Block: Decrypt the final, fractional block of the ciphertext.

    • Dec_Tag_Finalize: Finalize the computation of the tag and keep it internally.

    • Hash_Verify: Compare the tag against a user-supplied value, without disclosing it.

    The Associated Data (AD) and the plaintext or ciphertext are absorbed into GHASH differently; this places two obligations on the caller:

    • For the AD, the caller must zero every bit of the final block beyond the actual end of the AD. No State processes a fractional last AD block separately.

    • For the plaintext and ciphertext, the caller must not pass a final block shorter than b, zero-padded, to Encrypt or Decrypt. Such a block goes through State Enc_Last_Block, resp. Dec_Last_Block.

    Such a padded block would be encrypted, emitting keystream, and absorbed, producing a tag that does not conform to cite:[nist-SP-800-38D]. GHASH absorbs the final AD block whole.
  • Allowed State Transitions:

    • Ready → Set_Aux_Value → Hash_Absorb; the kl.exec that completes the IV makes the second transition (Rule MR18).

    • Set_Aux_Value → Set_Aux_Value, which restarts the IV (see below).

    • Hash_Absorb → Encrypt, if encryption is allowed (Rule MR1).

    • Hash_Absorb → Decrypt, if decryption is allowed (Rule MR1).

    • Encrypt → { Enc_Last_Block → } Enc_Tag_Finalize → Success.

    • Decrypt → { Dec_Last_Block → } Dec_Tag_Finalize → Hash_Verify → Success or Failure.

  • Behavior:

    • When entering State Ready:

      1. auth_key ← enc_blk(key, zeros(b));

      2. tag ← zeros(b);

      3. tag_len ← 0;

      4. last_block_len ← 0.

    • When entering State Set_Aux_Value:

      1. A Form B kl.setst with immediate kl_state_set_aux_value and auxiliary operand Xs sets the IV length in bits: len ← Xs.

      2. Xs must be a multiple of 8 with 8 ≤ Xs ≤ 8192; any other Xs, 0 included, transitions the locker to Error State Invalid.

      3. tag ← zeros(b).

      4. A same-State Form B kl.setst repeats these operations, restarting the IV (LOAD_LONG_FIELD(len, block, state, n, process_block(), finalize(), mode, g)).

    • State Set_Aux_Value is LOAD_LONG_FIELD(len, tag, tag, b, process_block(), finalize(), xor_accumulate, b) (LOAD_LONG_FIELD(len, block, state, n, process_block(), finalize(), mode, g)): entering it also zeroes input_base, block_base and cumul_len, and each kl.exec absorbs the next part of the IV into tag, where:

      • process_block() performs tag ← Galoismul(tag, auth_key); a 96-bit IV never fills a block, so it is never multiplied;

      • finalize() is defined as:

        1. If len = 96, then:

          1. J0 ← bswap(bin(1,32)) @ tag[95:0].

            The value of J0 is that of cite:[nist-SP-800-38D] §7.1 for a 96-bit IV, the byte string IV ‖ bswap(bin(1,32)): the IV occupies bytes 0 to 11 (J0[95:0]), and the counter occupies bytes 12 to 15 as a big-endian integer.

        2. Otherwise, let s ← 128 × ceil(len/128) - len, and the computation of J0 ← GHASH(IV ‖ 0s+64 ‖ bswap(bin(len,64)), auth_key) is completed by performing:

          1. if block_base != 0, then tag ← Galoismul(tag, auth_key).

          2. tag ← tag xor (bswap(bin(len,64)) @ zeros(64)).

          3. tag ← Galoismul(tag, auth_key).

          4. J0 ← tag.

        3. start_ctr ← int(bswap(J0[127:96])).

        4. tag ← zeros(b).

        5. The locker transitions to State Hash_Absorb.

    • When leaving State Set_Aux_Value:

      1. the kl.exec that completes the IV performs finalize() (step 3.h of Macro: Processing Variable Length Inputs into a Fixed Length Output), which transitions the locker to Hash_Absorb;

      2. a kl.setst naming Ready discards the partial IV without finalize(), zeroing tag, J0, len, block_base and cumul_len (Rule MR14);

      3. a kl.setst naming Hash_Absorb transitions the locker to Error State Invalid: entering Hash_Absorb requires a complete IV (Rule MR1).

The IV is absorbed into tag, not into J0, and only the finished value is copied to J0. tag is free for this: entering Set_Aux_Value zeroes it, which is GHASH’s initial value. The slot of J0 in the Serialized Content instead carries len, block_base and cumul_len while this State is active. Accumulating into J0 would place the running hash and those counters in the same 128 bits, so a CC exported part-way through a non-96-bit IV could not resume.

  • In State Hash_Absorb, (multi-block) Form B kl.exec instructions absorb each data block into tag: absorb(INPUT).

  • In State Encrypt or Decrypt, (multi-block) Form A kl.exec instructions encrypt, resp. decrypt, INPUT into OUTPUT and absorb the ciphertext, OUTPUT, resp. INPUT, into tag, with tmp a local bits(b):

    1. tmp ← INPUT xor next_ks(), resp. tmp ← INPUT.

    2. absorb(tmp).

    3. OUTPUT ← tmp, resp. OUTPUT ← tmp xor next_ks().

  • When entering State Enc_Last_Block, resp. Dec_Last_Block, a Form B kl.setst with immediate kl_state_enc_last_block, resp. kl_state_dec_last_block, performs FINAL_BLOCK_ENTRY(8, 120, 8) (FINAL_BLOCK_ENTRY(lo, hi, unit)): last_block_len ← Xs, a multiple of 8 from 8 to 120; an empty final block takes the bypass below.

    cite:[nist-SP-800-38D] admits any bit length, but numbers the bits of a byte from the most significant, so a truncation to the least significant bits would not give its bit string (Rule MR11).
  • In State Enc_Last_Block or Dec_Last_Block, a single Form A kl.exec encrypts, resp. decrypts, its INPUT into its OUTPUT and absorbs the zero-padded final block of the ciphertext into tag, with tmp a local bits(b):

    1. In Enc_Last_Block:

      1. tmp ← trunc(INPUT, last_block_len) xor trunc(next_ks(), last_block_len).

      2. absorb(tmp).

      3. OUTPUT ← tmp.

    2. In Dec_Last_Block:

      1. tmp ← trunc(INPUT, last_block_len).

      2. OUTPUT ← tmp xor trunc(next_ks(), last_block_len).

      3. absorb(tmp).

  • Rule MR10 applies to Enc_Last_Block and Dec_Last_Block, which have no successor (item 4): Enc_Tag_Finalize, resp. Dec_Tag_Finalize, takes the length block as the operand of a Form C kl.setst, and that kl.setst leaves the final-block State after its kl.exec. For an empty final block, a Form C kl.setst from Encrypt into Enc_Tag_Finalize, resp. from Decrypt into Dec_Tag_Finalize, bypasses the final-block State: tag and J0 are unchanged, and the message ends with the blocks already processed.

  • When entering State Enc_Tag_Finalize, resp. Dec_Tag_Finalize:

    1. A Form C kl.setst with immediate kl_state_enc_tag_finalize, resp. kl_state_dec_tag_finalize, and auxiliary operand INPUT supplies the length block, which software computes:

      1. INPUT ← bswap(bin(len_in_bits(plaintext), 64)) @ bswap(bin(len_in_bits(AD), 64)), resp. INPUT ← bswap(bin(len_in_bits(ciphertext), 64)) @ bswap(bin(len_in_bits(AD), 64)).

      2. len_in_bits(plaintext) counts only the plaintext that Encrypt and Enc_Last_Block processed, resp. len_in_bits(ciphertext) only the ciphertext that Decrypt and Dec_Last_Block processed; a final block that a kl.setst omitted is not counted.

    2. close_tag(INPUT[127:0]) (Rule MR8) computes the tag and retains it internally.

  • In State Enc_Tag_Finalize, a single Form C kl.exec writes tag[tag_len_p-1:0], the truncated tag MSBtag_len_p(T) of cite:[nist-SP-800-38D] §7.1, to OUTPUT (Rule MR12), and the locker transitions to Success.

  • When entering State Hash_Verify, a Form B kl.setst with immediate kl_state_hash_verify performs SET_TAG_LEN(None, 0) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)): tag_len ← Xs, the number of tag bits to compare, which must equal tag_len_p.

  • In State Hash_Verify, a single Form B kl.exec performs VERIFY_TAG(tag) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)): it compares INPUT[tag_len-1:0] in constant time with tag[tag_len-1:0], the MSBt(T) of cite:[nist-SP-800-38D] §7.2 with t = tag_len, and the locker transitions to Success or Failure. In both cases tag_len ← 0.

    Truncated tags are prefixes of one another. The floor of 64 bits excludes the 32 bits that cite:[nist-SP-800-38D] admits for some applications. Every verification compares tag_len_p bits (Rule MR12), but a forgery attempt with a message of ℓ blocks succeeds with probability about ℓ × 2-tag_len_p, and each success reveals information about auth_key that makes the next attempt easier. For tag_len_p < 128, the caller applies the limits of cite:[nist-SP-800-38D] Appendix C on message length and on failed verifications per key (Rule MR15). Rule MR15 leaves to the caller a single t across lockers that hold the same key by value.
    Decrypt and Dec_Last_Block release the plaintext block by block, before Hash_Verify checks the tag, whereas cite:[nist-SP-800-38D] returns no plaintext when the check fails. The same holds for the other AEAD Machines: GCM with Preset IV, GCM-SIV Mode (whose Dec_Tag_Finalize verifies the tag), OCB Mode, OCB with Preset Nonce, Ascon-AEAD128, Ascon-AEAD128 with Preset Nonce and Ascon-AEAD128 with Nonce Masking. Rule SR18 forbids the caller to use this plaintext before the locker reaches Success, and requires it to discard the plaintext otherwise. In OCB, the released plaintext also enables a forgery (Accepted Risks). Only software that complies with Rule SR18 obtains the authenticated decryption of cite:[nist-SP-800-38D] and of the standards of the other AEAD Machines.
    Two messages that the caller encrypts under the same key and IV reveal auth_key, which then allows forgeries under every IV until the key is retired (Accepted Risks).

Code examples: GCM Encryption, GCM Decryption.

GCM with Preset IV

The mode of operation “GCM with a Preset IV” is a variant of GCM in which the initialization vector (IV) is provisioned with the key, rather than supplied by software for each message.

This Machine is PRESET(GCM, IV) (PRESET(parent, field), GCM Mode). Provisioning forms J0 from the 96-bit IV as cite:[nist-SP-800-38D] §7.1 does; J0 itself is never provisioned. The differences follow.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field Description

    ii

    k or 64

    key

    Key value or System Key Identifier

    iii

    96

    IV

    The IV of cite:[nist-SP-800-38D] §7.1. Only a 96-bit IV is supported.

    iv

    pad

    Padding

    Zero; (−(kf + 96)) mod 128 bits.

  • Internal State:

    Same as for GCM.

    Upon provisioning, before the operations of entering Ready (Rule MR17), J0 ← bswap(bin(1,32)) @ IV, the byte string IV ‖ bswap(bin(1,32)) of cite:[nist-SP-800-38D] §7.1, and start_ctr ← 1. start_ctr is 1 in every CC of this Machine: an import whose Serialized Content holds another value completes into Error State Invalid (Rule MR3).

  • Serialized Content:

    Same as for GCM.

State Machine
  • States and Allowed Transitions:

    Same as for GCM, with the following exceptions:

    • There is no State Set_Aux_Value, and nothing that GCM specifies for it applies. The transition is from Ready to Hash_Absorb.

  • State Machine Behavior:

    The differences with respect to GCM are:

    • Entering State Ready also restores the provisioned J0, by J0[127:96] ← bswap(bin(1,32)), which keeps the IV (PRESET(parent, field)).

The rationale of PRESET(parent, field) applies, with the uniqueness requirement of cite:[nist-SP-800-38D] §8 on the key and J0. A derived key would let software recover J0 from the keystream, and a locker that computes the inverse block cipher would let it recover the IV, and so J0, from a single keystream block.

A provisioned J0 would let software choose the counter blocks that the Machine encrypts: with J0 = 096 ‖ 0xFFFFFFFF, a decrypt-only locker would output E(K, 0), the GHASH key, and with J0 = N ‖ 032 the tag mask of IV N, so that software could forge tags under a key that it never sees.

GCM-SIV Mode

The GCM-SIV mode is described in cite:[DBLP-journals-iacr-GueronLL17] and cite:[RFC8452]. This specification defines GCM-SIV only for AES, whose block is 128 bits, as cite:[RFC8452] does (Table 1); the definition will be extended to other block ciphers if needed.

The decryption path of GCM-SIV resembles that of GCM; the encryption path differs:

  • Encryption: Hash_Absorb absorbs the whole associated data (AD) and plaintext. Enc_Tag_Finalize then absorbs the lengths and produces the SIV, which is also the tag. Encrypt then makes a second pass over the plaintext, with the SIV as its initialization vector.

  • Decryption: Hash_Absorb absorbs only the AD. Decrypt decrypts the ciphertext and absorbs the resulting plaintext. Dec_Tag_Finalize then absorbs the lengths, recomputes the SIV, and compares it internally with the SIV set in Set_Aux_Value_2.

Parameters
  • k = key size, either 128 or 256: cite:[RFC8452] defines AES-GCM-SIV only for these two.

  • b = 128 = block size.

  • c = 32 = counter size.

  • Granularity: b.

  • The authentication tag is b = 128 bits long.

  • A plaintext or ciphertext holds at most 232 blocks, the final partial block included: the P_MAX of cite:[RFC8452] §6. The caller must keep the AD within the A_MAX of cite:[RFC8452] §6, 236 bytes (Rule MR15).

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • enc_key (derived): k bits.

    • auth_key (derived): 128 bits. Rule MR7 applies to both.

    • nonce: 96 bits.

    • ctr: the number of plaintext or ciphertext blocks encrypted or decrypted, an integer in the range 0 to 232, held and serialized on 33 bits: bits [31:0] in field iii, bit 32 in field vi.

    • SIV: 128 bits.

    • tmp: 128 bits.

    • last_block_len: 7 bits, an integer in the range 0 to 127. The bit length of the final, partial block of the plaintext or ciphertext.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    96

    nonce

    iii

    32

    ctr[31:0]

    iv

    128

    SIV

    v

    128

    tmp

    vi

    16

    ctr[32] in bit 15, last_block_len in bits [6:0], the other bits zero

    vii

    pad

    Padding: (−(kf + 400)) mod 128 = (−(kf + 16)) mod 128.

Machine-Specific Functions
  • RFC8452_KeyDeriv(k, key, nonce) derives the per-nonce message-encryption and message-authentication keys of cite:[RFC8452] §4:

    AES-GCM-SIV Key Derivation
    function RFC8452_KeyDeriv(k : int, key : bits(k), nonce : bits(96))
        → struct{enc_key : bits(k), auth_key : bits(128)} =
    {
      local A : array [0..5] of bits(128);
      local E : bits(k);
      local i : int;
    
      foreach(i from 0 to k/64 + 1) do:
        A[i] ← enc_blk(key, nonce @ bin(i,32));
      foreach(i from 2 to k/64 + 1) do:
        E[64*i-65 : 64*i-128] ← A[i][63:0];
    
      return struct { enc_key = E, auth_key = A[1][63:0] @ A[0][63:0] };
    }

    The loop makes k/64 + 2 calls, four for k = 128 and six for k = 256, and keeps the low 64 bits of each: these are the “first eight bytes” of cite:[RFC8452] under Notation and Conventions.

  • absorb(data) absorbs data into the hash function by performing a step of POLYVAL:

    1. tmp ← tmp xor data.

    2. tmp ← Montmul(tmp, auth_key), with the Montmul of the POLYVAL of POLYVAL Hashing Function.

  • next_ks() → bits(b) returns the keystream block of the next counter and steps the counter:

    1. If ctr = 232, the locker transitions to Error State Invalid, and the calling kl.exec performs no further step: the block would be one more than a message may hold.

    2. Otherwise, ctr ← ctr + 1, and next_ks() returns enc_blk(enc_key, 1 @ SIV[126:32] @ bin((int(SIV[31:0]) + ctr - 1) mod 232, 32)), the block of the counter before the step.

  • synth_siv(L) absorbs the length block L and computes the SIV into tmp:

    1. absorb(L).

    2. tmp ← enc_blk(enc_key, 0 @ tmp[126:96] @ (tmp[95:0] xor nonce)).

State Machine
  • States:

    Besides Ready, Success, and Failure, the GCM-SIV Machine makes use of the following States:

    • Set_Aux_Value: Set the value of nonce.

    • Set_Aux_Value_2: Set the SIV.

    • Hash_Absorb: Absorb the AD and, on the encryption path, the plaintext into the partial tag tmp.

    • Encrypt: Encrypt the plaintext.

    • Enc_Last_Block: Encrypt the final, fractional block of the plaintext.

    • Enc_Tag_Finalize: Finalize the SIV with the AD and plaintext lengths, and return it.

    • Decrypt: Decrypt the ciphertext and absorb the resulting plaintext into the partial tag.

    • Dec_Last_Block: Decrypt the final, fractional block of the ciphertext.

    • Dec_Tag_Finalize: Finalize the tag with the AD and plaintext lengths, then compare it against the SIV.

  • Allowed State Transitions:

    • Ready → Set_Aux_Value.

    • Set_Aux_Value → Set_Aux_Value_2 or Hash_Absorb.

    • Set_Aux_Value_2 → Hash_Absorb.

    • For encryption: Hash_Absorb → Enc_Tag_Finalize → Encrypt { → Enc_Last_Block }. The path ends in Encrypt or Enc_Last_Block, not in Success; the next message starts with a return to Ready.

    • The kl.exec of Enc_Tag_Finalize synthesizes SIV and transitions the locker to Encrypt (Rule MR18).

    • For decryption: Hash_Absorb → Decrypt → { Dec_Last_Block → } Dec_Tag_Finalize → Success or Failure.

    • Rule MR10 applies: the kl.exec of Dec_Last_Block transitions the locker to Dec_Tag_Finalize, which a kl.setst from Decrypt enters directly for an empty final block (item 2); Enc_Last_Block has no successor.

    • A final plaintext or ciphertext block shorter than b goes through Enc_Last_Block, resp. Dec_Last_Block.

  • Behavior:

    • Upon entering State Ready:

      • The following initialization operations are performed:

        1. nonce ← 0, ctr ← 0, tmp ← 0, last_block_len ← 0 and SIV ← 0.

    • When entering State Set_Aux_Value:

      1. A Form C kl.setst with immediate kl_state_set_aux_value and auxiliary operand INPUT is expected.

      2. nonce ← INPUT[95:0] (Rule MR8).

      3. (enc_key, auth_key) ← RFC8452_KeyDeriv(k, key, nonce).

    • When entering State Set_Aux_Value_2:

      1. A Form C kl.setst with immediate kl_state_set_aux_value_2 and auxiliary operand INPUT is expected.

      2. SIV ← INPUT[127:0] (Rule MR8).

        This State is meant to serve the decryption path. Entering it during encryption is harmless: an externally set SIV never feeds the encryption keystream. The encryption path reaches Encrypt only through the Enc_Tag_Finalize kl.exec, which overwrites SIV with the synthetic value, and it reaches Enc_Last_Block only from Encrypt. Skipping it during decryption leaves SIV at the zero that entering Ready set.

    • In State Set_Aux_Value or Set_Aux_Value_2, a kl.setst naming that same State transitions the locker to Error State Invalid (Rule GR19.2):

      1. The kl.setst that enters the State sets the value.

      2. The State loads no field by kl.exec.

    • In State Hash_Absorb, each (multi-block) Form B kl.exec absorbs its data blocks into tmp: absorb(INPUT). The caller must zero-pad the following, each separately to a multiple of 16 bytes, as cite:[RFC8452] §4 specifies:

      1. The AD.

      2. On the encryption path, the plaintext.

      Every bit of the final partial block beyond the end of its data must be zero.

    • In State Enc_Tag_Finalize, a single Form A kl.exec is expected, whose INPUT the caller must set to bin(len_in_bits(plaintext), 64) @ bin(len_in_bits(AD), 64). It finalizes the SIV:

      1. synth_siv(INPUT[127:0]) (Rule MR8).

      2. SIV ← tmp and OUTPUT ← SIV.

      3. The locker transitions to Encrypt.

    • In State Encrypt or Decrypt, (multi-block) Form A kl.exec instructions are expected, encrypting, resp. decrypting, INPUT into OUTPUT:

      1. OUTPUT ← INPUT xor next_ks().

      2. In Decrypt only, absorb(OUTPUT), which absorbs the plaintext into tmp.

    • When entering State Enc_Last_Block, resp. Dec_Last_Block, a Form B kl.setst with immediate kl_state_enc_last_block, resp. kl_state_dec_last_block, performs FINAL_BLOCK_ENTRY(8, 120, 8) (FINAL_BLOCK_ENTRY(lo, hi, unit)): last_block_len ← Xs, a multiple of 8 from 8 to 120. An empty final block skips Enc_Last_Block: the message ends in Encrypt.

    • In State Enc_Last_Block or Dec_Last_Block, a single Form A kl.exec instruction is expected, encrypting, resp. decrypting, INPUT into OUTPUT as follows (Rule MR10):

      1. OUTPUT ← trunc(INPUT, last_block_len) xor trunc(next_ks(), last_block_len).

      2. In Dec_Last_Block only, absorb(OUTPUT), which absorbs the zero-padded plaintext into the partial tag.

      3. In Dec_Last_Block, the locker then transitions to Dec_Tag_Finalize; the Machine names no successor of Enc_Last_Block, so the locker stays in it.

    • In State Dec_Tag_Finalize, a single Form B kl.exec is expected, whose INPUT the caller must set to bin(len_in_bits(plaintext), 64) @ bin(len_in_bits(AD), 64); it compares the SIV itself (Rule MR12):

      1. synth_siv(INPUT[127:0]) (Rule MR8).

      2. If tmp = SIV, the locker transitions to Success; otherwise, it transitions to Failure.

Code examples: GCM-SIV Mode.

OCB Mode

Only OCB3 is architected, following RFC 7253 cite:[RFC7253] and cite:[DBLP-journals-joc-KrovetzR21], and only for AES, as in the AEAD algorithms of cite:[RFC7253] (Table 1). The state machine follows RFC 7253 except in notation. Bit positions count from 0 at the least significant bit (Notation and Conventions); RFC 7253 counts them from 1 at the most significant bit. A block is a little-endian byte string: its byte 0 is the first byte of the RFC 7253 string. A formula over RFC 7253 bit positions is computed on the bswap view of the block, either with an explicit bswap or in a function or variable whose name ends in _be. Block indices, index included, start from 1 as in RFC 7253.

Parameters
  • b = 128 = block size.

  • k = key size. It must be 128, 192, or 256.

  • MAX_BLOCKS = 248 = maximum number of blocks, a final partial block included, in the AD or in the plaintext. This specification sets this bound: cite:[RFC7253] places no limit on the length of a message. The caller keeps the uniqueness of the nonce and the recommendation of cite:[RFC7253] §5 that a key process at most 248 blocks in total, the associated data included (Rule MR15).

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • N: 120 bits.

    • N_len: 7 bits. Bit length of the nonce. It must not exceed 120.

    • HasN: bit 0 of StateExtension, set once N holds a loaded nonce (Rule MR14).

    • L*, offset, hash_A, checksum_P: 128 bits each.

    • L$ and L[i] (derived): 128 bits each, for 0 ≤ i ≤ ⌊log2(MAX_BLOCKS)⌋ = 48; L[i] is Li of cite:[RFC7253]. Rule MR7 applies to them.

    • tag_len: 8 bits. Bit length of the tag. The allowed values are 64, 96, and 128.

    • last_block_len: 7 bits, an integer in the range 0 to 127. The bit length of the final, partial block of the AD, the plaintext or the ciphertext; 0 for an empty final block.

    • index: 49 bits, corresponding to i in the loops in RFC 7253. It is 0 from the entry into Ready to the entry into Hash_Absorb, and then ranges from 1 to MAX_BLOCKS + 1 = 248 + 1.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    120

    N

    iii

    7

    N_len, the bit length of the nonce

    iv

    1

    Padding

    v

    128

    L*; the derived L$ and L[i] are not serialized (Rule MR7)

    vi

    128

    offset (current offset)

    vii

    128

    hash_A

    viii

    128

    checksum_P (used also for the final tag)

    ix

    49

    index

    x

    2

    tag_len, encoded as tag_len/32 − 2. The value 3 is not produced; an import that carries it transitions the locker to Error State Invalid (Rule MR3).

    xi

    7

    last_block_len

    xii

    pad

    Padding: (−(kf + 698)) mod 128 = (−(kf + 58)) mod 128.

Machine-Specific Functions
  • ntz(n) = the number of trailing zero bits in the base-2 representation of the positive integer n. Formally, ntz(n) is the largest integer x for which 2x divides n.

  • double(S): doubling in the OCB3 field of cite:[RFC7253], which is the double of CMAC Functions for b = 128.

  • next_offset() advances offset to the next full block:

    1. If index > MAX_BLOCKS, the locker transitions to Error State Invalid: the block would be one more than the AD, the plaintext or the ciphertext may hold.

    2. offset ← offset xor L[ntz(index)].

    3. index ← index + 1.

  • last_offset() advances offset to the final partial block:

    1. If index > MAX_BLOCKS, the locker transitions to Error State Invalid, as in next_offset().

    2. offset ← offset xor L*.

  • ocb_tag(X) computes into checksum_P the tag, before truncation, from the last checksum input X:

           checksum_P ← enc_blk(key, checksum_P xor X xor L$) xor hash_A.

  • nonce_be(N, n) = the big-endian view of the n-bit nonce bit string held in N. cite:[RFC7253] treats the nonce as a bit string whose first bit is the most significant, so when it is serialized into bytes the final, possibly partial byte is left-aligned: its r = n mod 8 most significant bits carry nonce and its remaining bits are padding. With q = ⌈n/8⌉ the number of bytes so occupied,

           nonce_be(N, n) = (bswap(N[8q-1:0], q) >> 8 - r) mod 8[n-1:0], an n-bit value.

    The first bit of the nonce string is nonce_be(N, n)[n-1] and the last is bit 0. For r = 0 this reduces to bswap(N[n-1:0]), so a nonce occupying a whole number of bytes is unaffected. bswap alone cannot express the general case, since it is defined only over byte strings.

State Machine
  • States: Besides Ready, Success, and Failure, the Machines implementing OCB Mode use the following States:

    • Set_Aux_Value: Set the length and the value of the nonce.

    • Hash_Absorb: Set the tag length, and process the AD.

    • Hash_Absorb_Last_Block: Set the bit length, possibly zero, of the final block of the AD, and process that block. Every message passes through this State.

    • Encrypt: Process the plaintext by absorbing it into the tag and encrypting it.

    • Enc_Last_Block: Provide the last block of the plaintext, then process it.

    • Enc_Tag_Finalize: Return the tag.

    • Decrypt: Process the ciphertext by decrypting it and absorbing the plaintext into the tag.

    • Dec_Last_Block: Provide the last block of the ciphertext, then process it.

    • Hash_Verify: Compare a user-provided value with the internally computed tag.

  • Allowed State Transitions:

    • Ready → Set_Aux_Value → Hash_Absorb → Hash_Absorb_Last_Block.

    • Set_Aux_Value → Set_Aux_Value, which restarts the nonce load (see below).

    • Hash_Absorb_Last_Block → Encrypt or Decrypt.

    • Encrypt → Enc_Last_Block → Enc_Tag_Finalize → Success.

    • Decrypt → Dec_Last_Block → Hash_Verify → Success or Failure.

    • The kl.exec of Enc_Last_Block, resp. Dec_Last_Block, makes the transition to Enc_Tag_Finalize, resp. Hash_Verify (Rule MR18).

    • Every message passes through Enc_Last_Block or Dec_Last_Block, with last_block_len zero if its last block is a full block, processed in Encrypt or Decrypt.

      These States are left by their kl.exec or, with last_block_len zero, by a Form A kl.setst to Enc_Tag_Finalize, resp. Hash_Verify (see below). Any other kl.setst, except one naming Ready (Rule GR19.3), transitions the locker to Error State Invalid.

    • Gated States: those that Rule MR1 lists for encryption and decryption.

  • Behavior:

    • Upon entering State Ready:

      • The following initialization operations are performed:

        1. N ← zeros(120).

        2. N_len ← 0.

        3. HasN is cleared.

        4. hash_A ← zeros(128).

        5. checksum_P ← zeros(128).

        6. index ← 0.

        7. last_block_len ← 0.

        8. tag_len ← 128.

    • When entering State Set_Aux_Value:

      1. A Form B kl.setst with immediate kl_state_set_aux_value and auxiliary operand Xs is expected, where Xs must satisfy 6 ≤ Xs ≤ 120; any other Xs transitions the locker to Error State Invalid. Every bit length in that range is admissible (Rule MR11): the nonce is a bit string and need not fill whole bytes.

      2. N_len ← Xs and N ← zeros(120), and HasN is cleared.

cite:[RFC7253] itself places no lower bound on the nonce length. KLE requires at least 6 bits because a shorter nonce leaves the bottom and Stretch derivation of cite:[RFC7253] §4.2 without enough entropy to remain sound, as analyzed in cite:[cryptoeprint-2023-326]. An implementation of this specification is therefore not a general RFC 7253 implementation for nonces shorter than 6 bits.

  • While in State Set_Aux_Value, a Form B kl.exec, which processes a single block (Rule MR13), loads N from INPUT[8q-1:0], with q = ⌈N_len/8⌉; the other bits of INPUT are ignored (Rule MR8):

    1. N ← zeros(120 - 8q) @ INPUT[8q-1:0], with the (8 - N_len) mod 8 least significant bits of byte q-1 cleared: they pad the final, partial byte of the nonce string, are not part of the nonce, and are ignored.

    2. HasN is set.

    A repeated kl.exec rewrites N.

    A kl.setst naming Set_Aux_Value in this State restarts the load (Rule GR19.2): it performs the operations of entering the State with its new Xs.

  • When entering State Hash_Absorb, which requires HasN (Rule MR1):

    1. A Form B kl.setst with immediate kl_state_hash_absorb and auxiliary operand Xs is expected, where Xs must be 64, 96 or 128; any other Xs transitions the locker to Error State Invalid.

    2. index ← 1 and tag_len ← Xs.

    3. offset ← zeros(b) – this is Offset0 in the RFC.

    4. L* ← enc_blk(key, zeros(b)) – this is L* in the RFC.

    5. L$ ← double(L*), L[0] ← double(L$), and L[i] ← double(L[i-1]) for all i with 0 < i ≤ 48, possibly lazily.

  • In State Hash_Absorb, (multi-block) kl.exec instructions are expected to be of Form B, absorbing a data block INPUT into hash_A:

    1. next_offset().

    2. hash_A ← hash_A xor enc_blk(key, INPUT xor offset).

  • When entering State Hash_Absorb_Last_Block, a Form B kl.setst with immediate kl_state_hash_last_block invokes FINAL_BLOCK_ENTRY(0, 120, 8) (FINAL_BLOCK_ENTRY(lo, hi, unit)), which sets last_block_len, the bit length of the final block of the AD. An empty final block needs no kl.exec: the message continues with the kl.setst into Encrypt or Decrypt.

  • In State Hash_Absorb_Last_Block, a single Form B kl.exec absorbs the last block of the AD into hash_A:

    1. last_offset().

    2. hash_A ← hash_A xor enc_blk(key, pad10(INPUT, last_block_len) xor offset).

    With last_block_len = 0, the final block is empty or already processed, and a kl.exec transitions the locker to Error State Invalid (Rule MR10). The AD has several successors, so Hash_Absorb_Last_Block stays after its kl.exec (Rule MR10).

  • On entering State Encrypt or Decrypt, the Machine computes the nonce-dependent variables of cite:[RFC7253] §4.2:

    • local Nonce_be : bits(128) – this is Nonce in the RFC, in the big-endian view.

    • local Ktop, Ktop_be : bits(128)

    • local Stretch_be : bits(192) – this is Stretch in the RFC, in the big-endian view.

    • local bottom : int

    1. Nonce_be ← bin(tag_len mod 128, 7) @ zeros(120 - N_len) @ 1 @ nonce_be(N, N_len).

    2. bottom ← int(Nonce_be[5:0]).

    3. Ktop ← enc_blk(key, bswap(Nonce_be[127:6] @ zeros(6))).

    4. Ktop_be ← bswap(Ktop).

    5. Stretch_be ← Ktop_be @ (Ktop_be[127:64] xor Ktop_be[119:56]).

    6. index ← 1.

    7. offset ← bswap(Stretch_be[191-bottom : 64-bottom]).

  • In State Encrypt, (multi-block) kl.exec instructions are expected to be of Form A, absorbing the plaintext INPUT into checksum_P and encrypting it into OUTPUT:

    1. next_offset().

    2. checksum_P ← checksum_P xor INPUT.

    3. OUTPUT ← offset xor enc_blk(key, INPUT xor offset).

  • In State Decrypt, (multi-block) kl.exec instructions are expected to be of Form A, decrypting INPUT into OUTPUT and absorbing the plaintext OUTPUT into checksum_P:

    • local tmp : bits(b)

    1. next_offset().

    2. tmp ← offset xor dec_blk(key, INPUT xor offset).

    3. checksum_P ← checksum_P xor tmp.

    4. OUTPUT ← tmp.

  • When entering State Enc_Last_Block, resp. Dec_Last_Block, a Form B kl.setst with immediate kl_state_enc_last_block, resp. kl_state_dec_last_block, invokes FINAL_BLOCK_ENTRY(0, 120, 8) (FINAL_BLOCK_ENTRY(lo, hi, unit)), which sets last_block_len, the bit length of the final block of the plaintext, resp. ciphertext. These States are the exception to item 2 of Rule MR10: with Xs = 0, the kl.setst neither processes the final block nor enters the successor, which the Form D kl.exec or the Form A kl.setst below enters.

  • In State Enc_Last_Block or Dec_Last_Block, if last_block_len is nonzero, a single Form A kl.exec is expected, which performs the following, where P, the final block of the plaintext, is INPUT in Enc_Last_Block and the OUTPUT of step 2 in Dec_Last_Block:

    1. last_offset().

    2. OUTPUT ← trunc(INPUT, last_block_len) xor trunc(enc_blk(key, offset), last_block_len). // enc_blk(key, offset) is Pad in RFC 7253

    3. ocb_tag(offset xor pad10(P, last_block_len)).

    If last_block_len is zero, a single Form D kl.exec is expected instead, which performs ocb_tag(offset).

    In both cases last_block_len ← 0 and the locker then transitions to Enc_Tag_Finalize, resp. Hash_Verify.

    With last_block_len zero, a Form A kl.setst with immediate kl_state_enc_tag_finalize, resp. kl_state_hash_verify, is also admitted: on entering Enc_Tag_Finalize, resp. Hash_Verify, it performs the operation of the Form D kl.exec, so that both routes leave the same checksum_P. With last_block_len nonzero, that kl.setst transitions the locker to Error State Invalid.

  • In State Enc_Tag_Finalize, a single Form C kl.exec is expected. It performs OUTPUT ← trunc(checksum_P, tag_len), and the locker transitions to Success. A KLLEN smaller than tag_len violates the granularity of the State (Rule MR6).

  • In State Hash_Verify, a single Form B kl.exec completes decryption: VERIFY_TAG(checksum_P) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)) compares the tag_len least significant bits of INPUT with those of checksum_P, with the tag_len set on entering Hash_Absorb.

Code examples: OCB Mode.

OCB with Preset Nonce

The mode of operation “OCB with Preset Nonce” is a variant of OCB (OCB Mode) in which the nonce is carried in the Provisioning Input, as the IV is in GCM with Preset IV. This Machine is PRESET(OCB, N) (PRESET(parent, field)), with N_len preset together with N, and is otherwise the same as OCB, its Parameters and Machine-Specific Functions included, except as follows.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field Description

    ii

    k or 64

    key

    Key value or System Key Identifier

    iii

    120

    N

    The nonce, in the format of the INPUT of the Set_Aux_Value kl.exec of OCB Mode.

    iv

    7

    N_len

    The bit length of the nonce.

    v

    1

    Padding

    vi

    0 or 64

    Padding

  • Internal State:

    Same as for OCB.

    Provisioning sets N_len from the PI, and sets N from the PI as the Set_Aux_Value kl.exec of OCB Mode sets it from its INPUT. An N_len outside [6, 120], in the PI or in an imported Serialized Content, causes the locker to transition to Error State Invalid (Rule MR3).

  • Serialized Content:

    Same as for OCB.

State Machine
  • States and Allowed Transitions:

    Same as for OCB, with the following exceptions:

    • There is no State Set_Aux_Value. The transition is from Ready to Hash_Absorb.

  • State Machine Behavior:

    The differences with respect to OCB are:

    • The Form B kl.setst that sets tag_len and transitions to State Hash_Absorb is issued in State Ready.

    • This Machine does not use HasN: bit 0 of StateExtension stays 0. Entering State Hash_Absorb requires no HasN: every provisioning and import supplies N and N_len.

    • Entering State Ready clears neither N nor N_len, which keeps the nonce (PRESET(parent, field)).

The rationale of PRESET(parent, field) applies, with the nonce uniqueness of cite:[RFC7253] on the key and N. A locker that computes the inverse block cipher would let software recover the nonce from the final partial blocks that this Machine decrypts, each of which reveals up to 120 bits of a Pad; a locker of OCB takes the nonce that software sets in Set_Aux_Value.

CMAC Functions

CMAC is a message authentication code built on a block cipher. Tetsu Iwata and Kaoru Kurosawa designed it, and it became a NIST Recommendation in May 2005 cite:[nist-SP-800-38B].

Parameters
  • b = 64 or 128, the block size of the underlying block cipher (cite:[nist-SP-800-38B] §5.2).

  • k = key size (k a multiple of 8).

  • Granularity: b.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    k or 64

    key or System Key Identifier

    iii

    pad

    Padding: (−kf) mod 128.

  • Internal State:

    • key: k bits.

    • hash: b bits.

    • last_block_len: an integer in the range 0 to b, serialized on 32 bits.

    • tag_len: the number of bits that Hash_Verify compares, an integer in the range 64 to b, or 0 before it is set; serialized on 32 bits.

    • tag_len_p: the length of every MAC that the locker outputs, and the number of bits that every verification compares (Rule MR12): a multiple of 8 from 64 to b, and b if KeyType = 1; held in AuxInfo, not serialized.

    • absorbed_any: a boolean, set once a block has been absorbed in Hash_Absorb.

    • absorbed_all: a boolean, set once the last block has been absorbed.

  • MDH: MachinePolicy: bit 0 permits generating a CMAC (Hash_Output), and bit 1 verifying one (Hash_Verify); at least one bit must be set (Validity of Metadata).

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    k or 64

    key or System Key Identifier

    ii

    b

    hash

    iii

    32

    last_block_len

    iv

    32

    tag_len

    v

    1 (boolean)

    absorbed_any

    vi

    1 (boolean)

    absorbed_all

    vii

    pad

    Padding: (−(kf + b + 66)) mod 128.

Machine-Specific Functions
  • double(S) = bswap(dbl(bswap(S))), the doubling of cite:[nist-SP-800-38B] §6.1, where

    • dbl(V) = V << 1 if V[b-1] = 0, else (V << 1) xor (zeros(b-8) @ Rb), with
      Rb the constant of §5.3: R128 = 0b10000111 (x128 + x7 + x2 + x + 1) for b = 128, and
      R64 = 0b00011011 (x64 + x4 + x3 + x + 1) for b = 64.

    • For every block cipher with b = 128, SM4 included, dbl is the update_mask of AES128_XEX (XEX/XTS Modes), and double is the OCB3 doubling of OCB Mode.

  • gen_subkeys(K) → (K1,K2) generates subkeys K1 and K2 from K as cite:[nist-SP-800-38B] §6.1 does:

    1. L ← enc_blk(K, zeros(b))

    2. K1 ← double(L)

    3. K2 ← double(K1)

    4. return (K1, K2).

State Machine
  • States:

    • Ready: The CC is ready.

    • Hash_Absorb: Absorb data into the CMAC function.

    • Hash_Absorb_Last_Block: Set the length of the last block to absorb, then absorb it.

    • Hash_Output: Output the CMAC.

    • Hash_Verify: Compare the CMAC with a value supplied by software, without disclosing it.

    • Success: The CC has completed the CMAC operation.

    • Failure: A CMAC verification has failed.

  • Allowed State Transitions:

    • Ready → Hash_Absorb → Hash_Absorb_Last_Block → Hash_Output → Success.

    • Hash_Absorb_Last_Block → Hash_Verify → Success or Failure.

    • From any valid state to State Ready (Rule GR19.3).

  • Behavior:

    • Entering State Ready:

      • last_block_len ← 0

      • tag_len ← 0

      • hash ← zeros(b)

      • absorbed_any ← false

      • absorbed_all ← false

    • In State Hash_Absorb, a Form B kl.exec, which may span several blocks, absorbs each b-bit block P of INPUT in turn (Rule MR13):

      1. hash ← enc_blk(key, hash xor P).

      2. absorbed_any ← true.

    • When entering State Hash_Absorb_Last_Block, a Form B kl.setst with immediate kl_state_hash_last_block invokes FINAL_BLOCK_ENTRY(0, b, 8) (FINAL_BLOCK_ENTRY(lo, hi, unit)), which sets last_block_len, the bit length of the last block, with these changes:

      1. Xs = 0 denotes the empty message: with absorbed_any = true, it transitions the locker to Error State Invalid.

      2. If Xs = 0, the empty final block is absorbed at once, without a kl.exec (Rule MR10):

        1. (K1, K2) ← gen_subkeys(key),

        2. hash ← enc_blk(key, hash xor pad10(zeros(b), 0) xor K2), and

        3. absorbed_all ← true.

      3. The kl.exec leaves last_block_len unchanged: absorbed_all records that the last block is absorbed.

    • In State Hash_Absorb_Last_Block, a single Form B kl.exec absorbs the last block:

      1. (K1, K2) ← gen_subkeys(key).

      2. if last_block_len = b, then:

        1. tmp ← hash xor INPUT[b-1:0] xor K1

      3. else, that is if 0 < last_block_len < b:

        1. tmp ← hash xor pad10(INPUT, last_block_len) xor K2

      4. hash ← enc_blk(key, tmp)

      5. absorbed_all ← true

      A kl.exec with absorbed_all = true transitions the locker to Error State Invalid.

    • A kl.setst with immediate kl_state_hash_output enters State Hash_Output; with absorbed_all = false, it transitions the locker to Error State Invalid instead.

    • In State Hash_Output, a single Form C kl.exec, which processes a single block (Rule MR13), outputs the CMAC:

      1. OUTPUT ← trunc(hash, tag_len_p), the first tag_len_p/8 bytes of hash and the truncated tag of cite:[nist-SP-800-38B] §6.2 when tag_len_p < b; a KLLEN smaller than tag_len_p violates the granularity of the State, and a larger one receives the MAC with the bits beyond tag_len_p cleared (Rule MR12).

      2. The CC transitions to State Success.

    • State Hash_Output, as a kl.derive source (Derivation Endpoints of the Machines), supplies the b/8 bytes of hash.

    • A Form B kl.setst with immediate kl_state_hash_verify and auxiliary operand Xs enters State Hash_Verify by invoking SET_TAG_LEN(b, 64) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)), which sets tag_len ← min(Xs, b) and requires it to equal tag_len_p. With absorbed_all = false, the kl.setst transitions the locker to Error State Invalid.

    • In State Hash_Verify, a single Form B kl.exec verifies the tag by invoking VERIFY_TAG(hash) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)), which compares INPUT[tag_len-1:0] with hash[tag_len-1:0], the first tag_len/8 bytes of the CMAC, MSBTlen of cite:[nist-SP-800-38B] §6.2.

Code examples: CMAC Functions.

Hash and MAC Functions, and XOFs

This section defines an interface for hash functions, MAC functions and XOFs. No interface fits every construction, but the one defined here covers the most common, such as SHA-2 cite:[nist-fips-180-4], SHA-3, and SHAKE cite:[nist-fips-202].

Every Machine that instantiates it pads the message as its referenced standard prescribes: the caller supplies the message alone, and the kl.setst that ends the message completes the padding and applies any length encoding of that standard. One instruction sequence serves all of them (Hash Functions, MACs and XOFs).

It is highly recommended that a new Machine for a hash function, MAC function or XOF work with the same instruction sequence, unless a reason prevents it.

Parameters
  • b = block size (b a multiple of 8): the size of an absorbed block, which may differ from the size of the internal state. For a sponge function, b is the rate.

  • t = output block length (t a multiple of 8): the size of the digest, or of each block that the output stage emits between two update(). This description assumes t ≤ b.

  • d = digest length (d a multiple of 8) of a fixed-output Machine: t, unless the Machine states otherwise, as Ascon-Hash256 does. An XOF has no d.

  • n = size of the internal state kept by the function (n a multiple of 8). For a sponge function, n-b is the capacity of the function.

  • k = key size (k a multiple of 8). Present only if keyed, i.e., a MAC.

  • state_offset = offset into the state at which the block is absorbed.

  • tag_offset = offset of the tag into the state, 0 unless the Machine states otherwise. A Machine must satisfy state_offset ≤ tag_offset and tag_offset + t ≤ state_offset + b for a sponge, so that every output bit comes from the rate, and tag_offset + t ≤ n otherwise.

  • g = granularity: 8 bits in Hash_Absorb and Hash_Output, for every instantiation; a State that loads a field, such as Set_Key of HMAC, uses it too unless the Machine states otherwise.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    If keyed: k or 64

    key or System Key Identifier

    If unkeyed: 0

    none: the Provisioning Input is the MDH only

    iii

    pad

    Padding: (−kf) mod 128 if keyed, 0 if unkeyed.

  • MDH: MachinePolicy: unless the instantiating Machine states otherwise, no State is gated by MachinePolicy (Rule MR1), and a non-zero value is unsupported Metadata (Validity of Metadata).

  • Internal State:

    • key: k bits. Present only if keyed, i.e., a MAC.

    • state: n bits.

    • last_block_len: int. Bit length of the final piece to be absorbed in Hash_Absorb_Last_Block. In Hash_Output_Bits, after the message has ended, the field is called read_len: the number of bits still to be read before the next kl.setst.

    • input_base/output_base (same field): int. Offset within the input or output at which to read or write.

    • block_base: int. Length of the data absorbed so far into the current block or, in Hash_Output and Hash_Output_Bits, emitted so far from the current t-bit output block.

    • out_len: int. In Hash_Output and Hash_Output_Bits, the number of output bits still to be emitted, or 0 for an XOF without bound; zero in every other State.

    • cumul_len: int. Cumulative length of the data absorbed so far.

    • block: b bits. Present only if a partial block is kept separately, for instance when inputs are not absorbed directly into state.

    • Sealed: Boolean, bit 1 of StateExtension, set when a sealed source (Rule GR31.3) enters the message input, and cleared only on entering Ready. A StateExtension @ State with Sealed set in a State other than Hash_Absorb, Hash_Absorb_Last_Block, Hash_Output and Success is not supported by the Machine: an SCC that carries it is invalid Metadata (Validity of Metadata).

  • Serialized Content:

    Pos. Size (Bits) Field Notes

    i

    If keyed: k or 64

    key or SKID

     — 

    If unkeyed: 0

    none

     — 

    ii

    n

    state

     — 

    iii

    16

    last_block_len

    The bit length of the final piece still to be absorbed, 0 once the message ends; in Hash_Output_Bits, read_len.

    iv

    16

    block_base

    Amount of data, in bits, stored so far into block or accumulated (usually XORed) into state; in Hash_Output and Hash_Output_Bits, the amount emitted from the current output block.

    v, vi

    32

    out_len

    Unless the Machine uses these bits otherwise, as BLAKE2 Specific Rules does.

    vii

    64

    cumul_len

    Cumulative length of the data absorbed so far; its width limits the length of a message (Rule MR15). Present only if the padding or another function of the Machine uses it, or under HMAC (HMAC).

    viii

    b

    block

    Only if the block is stored separately from the state.

    ix

    pad

    Padding

    Zero; (−(kf + n + 64 + c' + b')) mod 128 bits, where kf is 0 if unkeyed, c' is 64 if cumul_len is present and 0 otherwise, and b' is b if block is present and 0 otherwise.

    input_base/output_base is not serialized: it is set to 8 × klstart at the start of every kl.exec.

Machine-Specific Functions
  • process_block(): Process block into the hash or MAC.

  • finalize(): Apply to the absorbed message the padding, and any length encoding or final-block processing, of the referenced standard, and process state, in place, so that it holds the digest, or the first t bits of output, at tag_offset.

  • update(): Update state during the output stage. A fixed-output Machine with d ≤ t needs none: its output loop enters Success and returns before it reaches update().

State Machine
  • States: Ready, Hash_Absorb, Hash_Absorb_Last_Block, Hash_Output, Hash_Output_Bits and Success.

    • Ready: The CC is ready.

    • Hash_Absorb: Absorb the message into the hash function.

    • Hash_Absorb_Last_Block: Set the bit length of the final piece of the message, then absorb it.

    • Hash_Output: Output the hash.

    • Hash_Output_Bits: Output the hash a set number of bits at a time.

    • Success: The CC has completed the operation (an XOF reaches it only with a bounded output).

  • Allowed State Transitions:

    • Ready → Hash_Absorb → { Hash_Absorb_Last_Block → } Hash_Output → Success.

    • Hash_Absorb, or Hash_Absorb_Last_Block with last_block_len = 0, → Hash_Output_Bits; Hash_Output → Hash_Output_Bits → Success; and Hash_Output_Bits → Hash_Output_Bits.

    • The Machine makes no transition into Hash_Output, Hash_Output_Bits, or the Hash_Verify of a MAC, by itself: a kl.setst naming it from Hash_Absorb or Hash_Absorb_Last_Block ends the message.

    • From any valid state to State Ready (Rule GR19.3).

  • Behavior:

    • Upon entering State Ready:

      • last_block_len, block_base, cumul_len, out_len and block are set to zero, and Sealed is cleared.

      • state: the initial value is set as specified by the Machine.

    • The kl.setst that enters Hash_Absorb sets last_block_len ← b (Macro: Processing Variable Length Inputs into a Fixed Length Output).

    • State Hash_Absorb invokes macro PROCESS_VLI (Macro: Processing Variable Length Inputs into a Fixed Length Output) as:

         PROCESS_VLI(0, block, b, state, n, input_base, block_base,
             state_offset, cumul_len, process_block(), None, mode, 8,
             Hash_Absorb_Last_Block, None, last_block_len),

      where:

      • state_offset is Machine-defined;

      • cumul_len is None where neither the Machine nor HMAC uses it;

      • finalize() is None in this invocation: it is performed once, by the kl.setst that ends the message;

      • mode is:

        • assign for a construction that fills a separate block and then processes it into state through process_block(), and

        • xor_accumulate for one that absorbs the input directly into state, as a sponge does; each instantiation states which it uses.

      A kl.exec absorbs any whole number of bytes. Its interruption points are those of Macro: Processing Variable Length Inputs into a Fixed Length Output: 0 and, if the locker holds block_base = 0 when it is issued, every byte offset.

    • State Hash_Absorb_Last_Block, entered from Hash_Absorb:

      1. A Form B kl.setst with immediate kl_state_hash_last_block and auxiliary operand Xs, Xs = 0 for Form A, sets last_block_len ← Xs (Macro: Processing Variable Length Inputs into a Fixed Length Output). Xs must satisfy:

        1. 0 ≤ Xs ≤ b;

        2. Xs is a multiple of 8, unless the Machine admits other bit lengths as Rule MR11 permits.

      2. Any other Xs transitions the locker to Error State Invalid.

      3. If last_block_len = 0, nothing more happens: the final piece is empty, and the message is what Hash_Absorb absorbed. No kl.exec is needed; any kl.exec transitions the locker to Error State Invalid (Rules MR10 and GR13.5).

      4. If last_block_len ≠ 0, a single Form B kl.exec absorbs the final piece as Macro: Processing Variable Length Inputs into a Fixed Length Output specifies for last_block_state:

        1. unless the Machine states otherwise, the piece is the last_block_len least significant bits of INPUT;

        2. its only interruption point is 0 (Rule MR13).

    • From Hash_Absorb, or from Hash_Absorb_Last_Block with last_block_len = 0, the kl.setst naming Hash_Output ends the message:

      1. Issued from Hash_Absorb, it gives the result of an empty final piece followed by the same kl.setst.

      2. It is of Form A or of Form B, unless the Machine requires Form A.

      3. A non-zero auxiliary operand Xs is the output length in bits, and must:

        1. be at most d for a fixed-output Machine, and below 232 for an XOF;

        2. be a multiple of 8, unless the Machine states otherwise, as KMAC128, KMAC256, KMACXOF128, and KMACXOF256 does for KMAC128 and KMAC256;

        3. be at least the minimum that a MAC may set, as HMAC does with 64 bits and KMAC128, KMAC256, KMACXOF128, and KMACXOF256 with 32 bits for KMAC128 and KMAC256.

      Any other non-zero Xs transitions the locker to Error State Invalid, before finalize().

      In Hash_Absorb_Last_Block, last_block_len ≠ 0 means that the final piece is not yet absorbed: a kl.setst naming Hash_Output, Hash_Output_Bits, or the Hash_Verify of a MAC, then transitions the locker to Error State Invalid.

    • In State Hash_Output:

      • Upon entering the state, the following operations are first performed:

        1. finalize()

        2. block_base ← 0 and last_block_len ← 0

        3. out_len ← Xs for a Form B kl.setst with Xs ≠ 0; otherwise out_len ← d for a fixed-output Machine, and out_len ← 0 for an XOF.

      • For each Form C kl.exec instruction, the following operations are performed:

        • local amount : int,   amount of data to copy from state to OUTPUT

        1. output_base ← 8 × klstart // 0 when the instruction starts

        2. while (output_base < KLLEN) do:

          1. amount ← min(KLLEN - output_base, t - block_base), and, if out_len ≠ 0, amount ← min(amount, out_len)

          2. OUTPUT[output_base + amount - 1 : output_base] ←
               state[tag_offset + block_base + amount - 1 : tag_offset + block_base]

          3. output_base ← output_base + amount

          4. block_base ← block_base + amount

          5. if out_len ≠ 0 then:

            1. out_len ← out_len - amount

            2. if out_len = 0, any bits of OUTPUT beyond output_base are cleared, the locker transitions to Success, and the instruction returns.

          6. if (block_base = t) then:

            1. update()

            2. block_base ← 0

            3. Here, and only here, the instruction can be interrupted while output_base < KLLEN, with klstart ← output_base / 8. A halt here leaves block_base = 0.

        The output has as many bits as out_len holds on entering the State, or is unbounded for an XOF without bound, and is emitted in any whole number of bytes.

        The interruption points of kl.exec in Hash_Output (Rule GR33.2) are 0 and, if the locker holds block_base = 0 when the kl.exec is issued, any byte offset, whatever out_len.

    • In State Hash_Output_Bits:

      • A Form B kl.setst with immediate kl_state_hash_output_bits and auxiliary operand Xs, issued in Hash_Output or Hash_Output_Bits, enters or stays in the State and sets read_len ← Xs. It performs no finalize(), keeps block_base and out_len, and discards any bits that an earlier read_len left unread. Issued from Hash_Absorb, or from Hash_Absorb_Last_Block with last_block_len = 0, it ends the message: it gives the result of a Form A kl.setst naming Hash_Output followed by the same kl.setst. The output is then that of a Form A entry, unbounded for an XOF, and a Machine that requires Form B into Hash_Output, as KMAC128, KMAC256, KMACXOF128, and KMACXOF256 does for KMAC128 and KMAC256, transitions the locker to Error State Invalid. A Form A kl.setst, Xs = 0, or Xs ≥ 216 transitions the locker to Error State Invalid.

      • Each Form C kl.exec runs the loop of Hash_Output with these changes:

        1. amount is also at most read_len, and read_len ← read_len - amount follows block_base ← block_base + amount;

        2. after the block_base = t step, if read_len = 0, any bits of OUTPUT beyond output_base are cleared, and the instruction returns, the locker staying in Hash_Output_Bits;

        3. the instruction can be interrupted wherever output_base is a multiple of 8 and less than KLLEN and read_len ≠ 0, inside a block too, and nowhere else, with klstart ← output_base / 8.

          A Form C kl.exec issued with read_len = 0 transitions the locker to Error State Invalid. The interruption points of kl.exec in Hash_Output_Bits are 0 and any byte offset, whatever block_base. As a kl.derive source (Derivation Endpoints of the Machines), the locker supplies the output that follows block_base, as in Hash_Output, and keeps read_len.

    • A sealed locker, one with Sealed set or, in HMAC, KeySealed, admits no kl.exec in Hash_Output and no kl.setst naming Hash_Output_Bits or Hash_Verify: each transitions it to Error State Invalid. Its output in Hash_Output is a sealed source (Rule GR31.3).

The following are Machine-specific, and the code example of Hashing a Message uses none of them:

SHA-2 Family Specific Rules

The primitives of the SHA-2 family cite:[nist-fips-180-4] (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256) are instantiations of the algorithm specified in Hash and MAC Functions, and XOFs, and only the differences from the behavior described there are given here.

Parameters
  • The word size w, and b, n, and t, as given in Table 3; the internal state consists of the eight w-bit chaining variables of cite:[nist-fips-180-4].

Table 3. Parameters of the SHA-2 family and SM3
Function w b n t

SHA-224

32

512

256

224

SHA-256

32

512

256

256

SHA-384

64

1024

512

384

SHA-512

64

1024

512

512

SHA-512/224

64

1024

512

224

SHA-512/256

64

1024

512

256

SM3 (SM3 Specific Rules)

32

512

256

256

Data Structures
  • Provisioning Input: the MDH only (Hash and MAC Functions, and XOFs, unkeyed).

  • Internal State:

    • state: n bits, holding the eight chaining variables Hi big-endian: state[(i+1)w-1 : iw] = bswap(bin(Hi, w)), for 0 ≤ i < 8.

    • block (b bits).

    • block_base, last_block_len and out_len (Hash and MAC Functions, and XOFs).

    • cumul_len, the number of message bits absorbed.

  • Serialized Content: as prescribed by Hash and MAC Functions, and XOFs, with out_len in Positions v and vi, and cumul_len and block present.

Machine-Specific Functions
  • process_block(): applies the compression function of cite:[nist-fips-180-4] §6 for the selected function to absorb the current block into state, message word j being int(bswap(block[(j+1)w-1 : jw])), for 0 ≤ j < 16.

  • finalize(): absorbs the rest of the padding of cite:[nist-fips-180-4] §5.1.1 and §5.1.2 for a message of ℓ bits, by steps 3.a to 3.e and 3.g of Macro: Processing Variable Length Inputs into a Fixed Length Output, so that cumul_len does not count it. This rest is the byte 0x80 if cumul_len is a multiple of 8 (otherwise the final piece carries the bit 1 already), then zero bytes until block_base = b − 2`w`, then bswap(bin(ℓ, 2w)). ℓ is cumul_len, or, under HMAC, the length that HMAC states.

State Machine
  • States and Allowed State Transitions: those of Hash and MAC Functions, and XOFs.

  • Behavior:

    • Upon entering State Ready, state is set to the initial hash value of the selected function per cite:[nist-fips-180-4] §5.3.

    • In State Hash_Absorb, PROCESS_VLI is invoked as in Hash and MAC Functions, and XOFs, with mode = assign, state_offset = 0 and cumul_len tracked.

      mode is assign because the SHA-2 family fills a separate block and compresses it into state.
    • In State Hash_Absorb_Last_Block:

      1. The final piece is the ⌈last_block_len/8⌉ least significant bytes of INPUT; the other bits of INPUT are ignored.

      2. Let q = last_block_len mod 8. If q ≠ 0:

        1. the last of these bytes carries the final q bits of the piece in its q most significant positions, since cite:[nist-fips-180-4] orders the bits of a byte from the most significant (Rule MR11, second bullet);

        2. the Machine replaces the other 8 − q bits of that byte by the bit 1 that starts the padding, followed by zeros.

      3. The kl.exec of last_block_state (Macro: Processing Variable Length Inputs into a Fixed Length Output) absorbs these bytes: its step 3, with all sub-steps, uses 8 × ⌈last_block_len/8⌉ in place of last_block_len.

      4. In place of the increments of step 3.f of the kl.exec in Current_State, cumul_len advances once by last_block_len itself, before step 5 clears last_block_len.

    • In State Hash_Output, the bytes emitted are the chaining variables in the big-endian encoding, truncated to the number of bits that out_len holds on entering the State (Hash and MAC Functions, and XOFs).

SM3 Specific Rules

The ShangMi 3 hash function, standardized as GB/T 32905-2016 cite:[GBT-32905-2016], follows the rules of SHA-256 (SHA-2 Family Specific Rules), with the parameters of row SM3 of Table 3, except that its initial hash value and compression function are those of the SM3 standard.

BLAKE2 Specific Rules

BLAKE2b and BLAKE2s cite:[RFC7693], unkeyed or keyed, instantiate Hash and MAC Functions, and XOFs; only the differences are given here. nn and kk are the digest and key lengths in bytes.

Parameters
  • w, r (the rounds of F), b, n, nnmax, kkmax and the rotation constants of G, as in Table 4; t = 8 × nn.

Table 4. Parameters of BLAKE2
Function w r b n nnmax kkmax (R1, R2, R3, R4)

BLAKE2b

64

12

1024

512

64

64

(32, 24, 16, 63)

BLAKE2s

32

10

512

256

32

32

(16, 12, 8, 7)

Data Structures
  • Provisioning Input: the MDH only, or, with a system key (KeyType = 1):

    Pos. Size (Bits) Field

    ii

    64

    System Key Identifier

    iii

    64

    Padding

    kk is the length of the key that the SKS returns; a length outside 1 to kkmax transitions the locker to Error State Invalid (System Keys). When an import resolves the SKID again, a key whose length differs from the restored kk transitions the locker to Error State Invalid. KeyType = 2 is invalid: the Machine holds no key by value. A caller with its own key absorbs it (see below).

  • MDH: MachinePolicy: without a system key, as in Hash and MAC Functions, and XOFs. With a system key, the Machine is a MAC that only generates tags: bit 0 enables Hash_Output (Rule MR1); MachinePolicy = 0 is invalid Metadata, and any set bit other than bit 0 is unsupported Metadata (Validity of Metadata).

  • Internal State:

    • nn, with 1 ≤ nn ≤ nnmax, and kk, with kk ≤ kkmax; an import that writes a value outside these ranges transitions the locker to Error State Invalid (Rule MR3).

    • state: the words hi of cite:[RFC7693], little-endian: state[(i+1)w-1 : iw] = bin(hi, w), for 0 ≤ i < 8.

    • block, block_base, last_block_len, out_len, and cumul_len, which also counts a key block, so that cumul_len/8 is the counter of cite:[RFC7693] §3.2.

    • syskey: with a system key, the key that the SKID resolves to, zero-padded to b bits. It is not serialized: the SKID in Position i of the Serialized Content stands for it (Rule GR55.1).

  • Serialized Content: as in Hash and MAC Functions, and XOFs, with cumul_len and block present, and:

    • the SKID, if any, in Position i;

    • nn in Position v and kk in Position vi, 16 bits each, nn in the lower half;

    • in Hash_Output and Hash_Output_Bits, out_len in the lower 32 bits of Position vii, the upper 32 bits zero, in place of cumul_len, which finalize() has consumed.

Machine-Specific Functions
  • F(f): the compression function of cite:[RFC7693] §3.2 on state, with message words mj = int(block[(j+1)w-1 : jw]), the counter cumul_len/8, and the final-block flag f.

  • process_block(): F(false).

  • finalize() performs the first of the following that applies, then sets block_base ← 0:

    • with block_base > 0: zeroes block[b-1 : block_base] and performs F(true);

    • with block_base = 0, which only an empty message leaves, and a system key: block ← syskey, cumul_len ← b, F(true) and block ← zeros(b);

    • with block_base = 0, no system key and kk = 0: F(true) on the zero block;

    • with block_base = 0, no system key and kk ≠ 0: the locker transitions to Error State Invalid, since the caller’s key block is missing.

State Machine
  • States: Ready, Hash_Absorb, Hash_Absorb_Last_Block, Hash_Output, Hash_Output_Bits, and Success.

  • Allowed State Transitions:

  • Behavior, where it differs from Hash and MAC Functions, and XOFs:

    • At the completion of a provisioning, before the operations of entering Ready, nn ← nnmax and kk ← the length of the system key, or 0 without one. The completion of a system-specific import does the same for each of them that the converted Content does not configure (Rule GR51). Every other entry into Ready keeps nn and kk.

    • When entering State Ready, state is the IV of cite:[RFC7693] §2.6, with h0 XORed with bin(0x01010000 + kk × 256 + nn, w) (§2.5, §3.3).

    • In State Ready, setting the parameters is an operation, not a State (Rule MR16):

      1. a Form B kl.setst with immediate kl_state_set_aux_value and auxiliary operand Xs sets nn ← Xs[7:0] and, without a system key, kk ← Xs[15:8], and recomputes h0;

      2. Xs must satisfy 1 ≤ Xs[7:0] ≤ nnmax and Xs[15:8] ≤ kkmax, and its bits above bit 15 must be 0. With a system key, Xs[15:8] must be 0.

      Any other Xs transitions the locker to Error State Invalid.

    • With a system key, the instruction that absorbs the first byte of the message compresses the key block before it absorbs that byte: block ← syskey, cumul_len ← b, F(false), and block ← zeros(b). That instruction is a kl.exec or a kl.derive in Hash_Absorb, or the kl.exec of Hash_Absorb_Last_Block. cumul_len = 0 records that the key block is still pending; for the empty message, finalize() compresses it as the final block.

      syskey is in block only between two steps of one instruction, which cannot halt between them, so no Serialized Content holds it (Rule GR55.1).
    • A caller with its own key, and no system key:

      1. sets kk to the length of the key in bytes by the Set_Aux_Value operation;

      2. absorbs the key, zero-padded to b bits, as the first block of the message (cite:[RFC7693] §3.3);

      3. for an empty message, absorbs nothing more, and finalize() compresses the key block as the final block.

      The Machine does not tell the key block from the message: it checks neither that kk matches the length of the key nor that the key is padded with zeros, and a mismatch only yields a different hash.
    • In State Hash_Absorb, PROCESS_VLI is invoked with max_len = 0, state_offset = 0 and mode = assign, with these differences:

      1. Step 3.g is postponed: a block filled to block_base = b is kept.

      2. The iteration of step 3 that absorbs the next byte of the message first compresses that block by F(false) and sets block_base ← 0, before step 3.a, so that the counter cumul_len/8 does not yet count that byte.

      3. With a system key, the key block is compressed first, as stated above.

      4. The interruption points of kl.exec in Hash_Absorb are 0 and, if the locker holds block_base = 0 or block_base = b when the kl.exec is issued, any byte offset. A halt leaves the full block held, with block_base = b, so that its resumption meets that condition.

    • Hash_Absorb_Last_Block follows Hash and MAC Functions, and XOFs, with Xs a multiple of 8 (Rule MR11). In the kl.exec of last_block_state (Macro: Processing Variable Length Inputs into a Fixed Length Output), step 3.c is postponed in the same way:

      1. A full block, including one held from Hash_Absorb, is compressed by F(false), with block_base ← 0, at the start of the loop iteration that absorbs the next byte of the final piece, before its amount is computed.

      2. A final piece that fills its block is held for finalize().

HMAC

Hash function Machines suffice to compute HMACs, but an environment may want to hide the HMAC key. This section extends Hash and MAC Functions, and XOFs accordingly.

finalize() of H pads as in H; for SHA-2 (SHA-2 Family Specific Rules) and SM3 (SM3 Specific Rules) it encodes ℓ = b + cumul_len bits for the inner hash and b + t bits for the outer, since absorb(K0 xor ipad) and absorb(K0 xor opad) are not counted in cumul_len.

Parameters
  • H = the underlying hash function.

  • b = the input block size of H: its parameter b, which for SHA-3 is the rate (Table 5).

  • t = the digest size: the parameter t of H (Hash and MAC Functions, and XOFs).

  • Granularity: same as that of the underlying hash function.

The two padding constants of cite:[nist-fips-198-1] are:

  • ipad = the byte 0x36 repeated b/8 times, and

  • opad = the byte 0x5c repeated b/8 times,

both b bits long. All bytes of each constant are equal, so its representation does not depend on the byte order of Notation and Conventions.

Data Structures
  • Provisioning Input:

    Each HMAC Machine has two variants, which the Machine field distinguishes (Table 1): by Type for the SHA-2 and SHA-3 HMACs, and by Mode for SM3_HMAC.

    The PI of the “No Initial Key” (NIK) variant is the MDH alone.

    The PI of the “Key In PI” (KIP) variant has the following format:

    Pos. Size (Bits) Field

    ii

    b or 64

    K0, the key already reduced to b bits (see below), or a System Key Identifier.

    iii

    0 or 64

    Padding

    The key provisioned or held in a CC is the value K0 of cite:[nist-fips-198-1] §4, Steps 1 to 3: the key K padded with zeros to b bits, or, if K is longer than b bits, H(K) padded with zeros to b bits. Whoever provisions the key derives K0 from it. With KeyType = 1, the SKS returns K, and the KLE unit forms K0 from it by the same Steps. A system-specific import (Rule GR51) that configures the K0 of a NIK CC forms it by the same Steps from the key that the format carries, and sets HasKey, as a completed load of K0 does (Rule MR4).

  • Internal State:

    • hash_fn_state: the entire state of H, with the following fields:

      • state: n bits.

      • last_block_len, out_len: int (Hash and MAC Functions, and XOFs).

      • input_base: int. Offset within input/output to read from/write to.

      • block_base: int. Length of the data absorbed so far into the current block or, in Hash_Output and Hash_Output_Bits, emitted so far from the current t-bit output block (Hash and MAC Functions, and XOFs).

      • cumul_len: int. Cumulative length of data absorbed so far, tracked by every HMAC Machine (for the K0 load in Set_Key, and for the padding of SHA-2 and SM3).

      • block: b bits. Included only if a partial block is maintained, for instance when the inputs are not directly absorbed into state.

    • K0: b bits, the value K0 as per cite:[nist-fips-198-1] §4, Steps 1 to 3.

    • tag_len: the number of bits that Hash_Verify compares, 64 to t, or 0 before it is set.

    • tag_len_p: the number of bits that every verification compares (Rule MR12): a multiple of 8 from 64 to t, and t if KeyType = 1; held in AuxInfo, not serialized.

    • HasKey (NIK variant only): Boolean, bit 0 of StateExtension, recording that K0 holds a completely loaded key (Rule MR14).

    • KeySealed (NIK variant only): Boolean, bit 2 of StateExtension, set when a sealed source (Rule GR31.3) loads K0, and cleared on entering Set_Key. A StateExtension @ State with KeySealed set and HasKey clear, or set in Hash_Output_Bits, Hash_Verify or Failure, is not supported by the Machine: an SCC that carries it is invalid Metadata (Validity of Metadata). The KIP variant uses only Sealed (Hash and MAC Functions, and XOFs).

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    variable

    Serialized Content of the underlying hash function, in its entirety, including its Padding.

    ii

    b or 64

    K0, or a System Key Identifier.

    iii

    16

    tag_len

    iv

    pad

    Padding: (−(b + 16)) mod 128, or 48 with a System Key Identifier.

    If H is a SHA-3 function and KeyType = 1, the state of position i is masked as in KMAC128, KMAC256, KMACXOF128, and KMACXOF256 (Rule GR55.1).

State Machine

The NIK variant inserts State Set_Key between Ready and Hash_Absorb; both variants add States Hash_Verify and Failure.

The two variants differ only in how the key first reaches the CC.

In the KIP variant, K0 is carried in the Provisioning Input. The key is given by value (KeyType = 0), as an SKID (KeyType = 1), or as b random bits (KeyType = 2). A KIP CC cannot be re-keyed.

In the NIK variant, the Provisioning Input carries no key. K0 must be loaded in State Set_Key before Hash_Absorb can be entered: entering Hash_Absorb requires HasKey (Rule MR1), and leaving Set_Key before the load completes zeroes K0 (Rule MR14). A loaded key is kept across a return to Ready, so that one load of K0 serves any number of messages.

  • Allowed State Transitions:

    • For the NIK variant: Ready → Set_Key → Hash_Absorb, and Ready → Hash_Absorb once K0 is loaded (HasKey); then as in the underlying hash function.

    • For the NIK variant: Set_Key → Set_Key, which restarts the load (see below).

    • For the KIP variant: Ready → Hash_Absorb; then as in the underlying hash function.

    • Hash_Absorb, or Hash_Absorb_Last_Block with last_block_len = 0, → Hash_Verify → Success or Failure.

    • From any valid state to State Ready (Rule GR19.3).

    • MachinePolicy[0] gates MAC generation, and MachinePolicy[1] MAC verification (Rule MR1).

  • Behavior:

    • When entering Ready: tag_len ← 0.

    • State Set_Key is LOAD_LONG_FIELD(b, K0, K0, b, None, None, assign, g) (LOAD_LONG_FIELD(len, block, state, n, process_block(), finalize(), mode, g)), with g the granularity of H: Form B kl.exec instructions load the b-bit K0, and a completed load sets HasKey. Entering Set_Key, also by a same-State kl.setst, which restarts the load, also clears KeySealed. A kl.derive into K0 (Derivation Endpoints of the Machines) transfers a whole key K of eff_length ≤ b/8 bytes (Rule GR29 items 1 and 6):

      1. it requires klstart = 0 and a source of exactly eff_length bytes: a source field, or the remaining kl.exec output of the source;

      2. otherwise, the destination locker transitions to Error State Invalid, and the source is unchanged; a keystream of a keystream Machine (CTR/XCTR Keystream Generation, OFB of Chaining/Feedback Modes (CBC, CFB, and OFB)), or the output of an XOF without bound, has no length of its own and never meets the requirement of the previous step, so its kl.derive into K0 always has this outcome;

      3. it replaces all of K0, whatever a kl.exec loaded before it: K0 ← K zero-filled to b bits (cite:[nist-fips-198-1] §4, Step 3);

      4. it sets block_base ← 0 and cumul_len ← b, and sets HasKey, and KeySealed for a sealed source.

    • When entering Hash_Absorb:

      1. state is set to the initial value of the underlying hash function.

      2. block, block_base and cumul_len are set to zero, and last_block_len ← b, as in H.

      3. absorb(K0 xor ipad), not counted in cumul_len, where absorb(x) absorbs x as a kl.exec in Hash_Absorb of H does.

      4. If H keeps block apart from state (SHA-2, SM3), block ← zeros(b).

        K0 xor ipad is in block only between two steps of one instruction, so no Serialized Content holds it (Rule GR55.1).
    • While in Hash_Absorb and Hash_Absorb_Last_Block, the message is absorbed as in H, including the length and the bit order of the final piece (Rule MR11).

    • When entering State Hash_Output or Hash_Verify, the following steps replace the operations of H on entering Hash_Output:

      • local inner : bits(t)

      1. finalize() of H, which leaves the inner hash H((K0 xor ipad) ‖ message) in state[t+tag_offset-1 : tag_offset].

      2. inner ← state[t+tag_offset-1 : tag_offset].

      3. Reinitialize state to the initial value of the underlying hash function H, and set block, block_base and cumul_len to zero.

      4. absorb(K0 xor opad) as per H, not counted in cumul_len.

      5. absorb(inner) as per H, which leaves cumul_len = t, so that the outer hash digests (K0 xor opad) ‖ H((K0 xor ipad) ‖ message), as cite:[nist-fips-198-1] §4 requires.

      6. finalize() of H, block_base ← 0 and last_block_len ← 0. The t-bit HMAC value is then output in Hash_Output as by H, with out_len set as in Hash and MAC Functions, and XOFs, or verified in Hash_Verify.

      A non-zero Xs of a Form B kl.setst into Hash_Output is at least 64 (Hash and MAC Functions, and XOFs).

    • To verify an HMAC where MachinePolicy[1] is set (Rule MR1):

      1. the Form B kl.setst that enters State Hash_Verify invokes SET_TAG_LEN(t, 64) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)): tag_len ← min(Xs, t), which must equal tag_len_p;

      2. in State Hash_Verify, the single Form B kl.exec invokes VERIFY_TAG(state[tag_offset+t-1 : tag_offset]) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)): it compares INPUT[tag_len-1:0] with state[tag_offset+tag_len-1 : tag_offset], the first tag_len/8 bytes of the HMAC.

SHA-3 Family Specific Rules

The SHA-3 family comprises SHA3-224, SHA3-256, SHA3-384 and SHA3-512, written SHA3-N, and the XOFs SHAKE128 and SHAKE256. All are parameter choices of KECCAK cite:[DBLP-conf-eurocrypt-BertoniDPA13], standardized by NIST cite:[nist-fips-202]. They are instantiations of the Machine of Hash and MAC Functions, and XOFs; this section gives only the differences.

Parameters
  • n = 1600.

  • c = capacity, b = rate = 1600 - c, and t = the number of output bits taken from state per squeeze, all as given in Table 5.

Table 5. Parameters of the SHA-3 family
Function c b = 1600 - c t XOF? Suffix D

SHA3-224

448

1152

224

no

bin(2, 2)

SHA3-256

512

1088

256

no

bin(2, 2)

SHA3-384

768

832

384

no

bin(2, 2)

SHA3-512

1024

576

512

no

bin(2, 2)

SHAKE128

256

1344

1344

yes

bin(15, 4)

SHAKE256

512

1088

1088

yes

bin(15, 4)

bin(2, 2) and bin(15, 4) are the suffixes that cite:[nist-fips-202] writes as 01 and 1111, first bit leftmost: for SHA3-N, D[0] = 0 and D[1] = 1.

For the four fixed-output functions, t is the digest length, which is c/2, and a single squeeze suffices. For the two extendable-output functions, t is the full rate b, since a sponge makes exactly b bits available between successive applications of the permutation.

Data Structures
  • Provisioning Input: the MDH only.

  • Internal State:

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    1600

    state

    ii

    16

    block_base, in bits

    iii

    16

    last_block_len, in bits

    iv

    32

    out_len, in bits

    v

    64 or 0

    cumul_len, under HMAC (HMAC) only

    vi

    0, or 64 with cumul_len

    Padding

    This layout replaces that of Hash and MAC Functions, and XOFs, in which last_block_len precedes block_base.

Machine-Specific Functions

  • P(): computes KECCAK-p[1600, 24] on state, with result in place.

  • process_block(): there is no explicit operation to copy data into state, since the inputs are XORed directly into it; instead, process_block applies P() to the state.

  • update(): applies P() to the state during the digest output stage.

State Machine

  • States and Allowed State Transitions: those of Hash and MAC Functions, and XOFs.

  • Behavior:

    • Upon entering State Ready, state is zeroed.

    • In State Hash_Absorb, the input data is XORed directly into state: PROCESS_VLI is invoked as in Hash and MAC Functions, and XOFs, with block = state, mode = xor_accumulate, state_offset = 0, and cumul_len = None except under HMAC.

    • In State Hash_Absorb_Last_Block, a final piece of 0 to b bits is absorbed (Hash and MAC Functions, and XOFs), so that the message may have any bit length. cite:[nist-fips-202] orders the bits within a byte as Notation and Conventions does, so last_block_len need not be a multiple of 8 (Rule MR11).

    • Upon transitioning to State Hash_Output, finalize():

      1. forms the bit string S of cite:[nist-fips-202] §5.1 and §B.2:

        1. S[|D|-1:0] holds the suffix D of Table 5, with D[0] in S[0];

        2. pad10*1 follows: a 1 in S[|D|], zeros, and a 1 in S[|S|-1];

        3. |S| is the smallest length ≥ |D| + 2 that makes block_base + |S| a multiple of b;

      2. XORs S[b-block_base-1 : 0] into state[b-1 : block_base], and applies P();

      3. if |S| > b - block_base: XORs S[|S|-1 : b-block_base] into state[b-1 : 0], and then applies P();

      4. leaves the output in the first t bits of the rate.

        block_base is less than b, since it returns to 0 when it reaches b. When block_base is a multiple of 8, S fits in the current block: it is the byte pad_byte at state[block_base+7 : block_base], with pad_byte = 0x06 for SHA3-N and 0x1F for SHAKE128 and SHAKE256, XORed with the byte 0x80 at state[b-1 : b-8]. Else, after a final piece whose length is not a multiple of 8, S starts within a byte, and a second block is needed only when b - block_base < |D| + 2.
    • In State Hash_Output, output is extracted as in Hash and MAC Functions, and XOFs:

      1. SHA3-N: a digest of d bits, or of Xs bits after a non-zero Xs, at most t in either case, after which the locker transitions to Success;

      2. SHAKE128 and SHAKE256: output of unbounded length, or of Xs bits after a non-zero Xs, after which the locker transitions to Success.

The rest of the Machine follows Hash and MAC Functions, and XOFs.

KMAC128, KMAC256, KMACXOF128, and KMACXOF256

KMAC is the keyed MAC built on cSHAKE, standardized by NIST in cite:[nist-SP-800-185]. It is defined only over the KECCAK permutation of SHA-3, and this section gives only its differences from SHA-3 Family Specific Rules.

Parameters
  • n = 1600.

  • KMAC128 and KMACXOF128 use c = 256 and rate b = 1344 bits (168 bytes); KMAC256 and KMACXOF256 use c = 512 and rate b = 1088 bits (136 bytes).

  • t = b, as for the extendable-output functions of Table 5.

Data Structures

A CC does not hold the key K and the customization string S in their raw form. It holds the two rate-sized blocks that cite:[nist-SP-800-185] derives from them. Whoever provisions the CC prepares both, unless the KLE unit forms key_block from a System Key or a random K (see below):

       cshake_block = bytepad(encode_string("KMAC") ‖ encode_string(S), b/8), and
       key_block    = bytepad(encode_string(K), b/8),

where bytepad, encode_string and left_encode are as defined in cite:[nist-SP-800-185] §2.3:

Function rate b/8 maximum |K| maximum |S|

KMAC128/KMACXOF128

168 bytes

163 bytes

157 bytes

KMAC256/KMACXOF256

136 bytes

131 bytes

125 bytes

Only a K and an S within these maximums fit in one block each. The Machine does not check that a cshake_block or key_block carried by value is well formed.

cite:[nist-SP-800-185] admits a longer K or S, which bytepad spreads over more than one block, and unlike the key of HMAC, no shorter value computes the same function.

With KeyType = 1, the PI and the SCC carry a System Key Identifier in place of key_block (Rule GR55.1). The SKS returns the key K, and the KLE unit forms key_block from it as above. A K longer than the maximum in the table above transitions the locker to Error State Invalid (System Keys). With KeyType = 2 (KeyType Field), K is a random value of c/2 bits, from which key_block is formed in the same way. cshake_block is always carried by value. With KeyType = 1, the state field of the Serialized Content holds state xor state_mask in every State but Ready (Rule GR55.1); an import removes the mask after SKID resolution, when it converts the content into the internal format.

  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    b

    cshake_block

    iii

    b or 64

    key_block or System Key Identifier

    iv

    0

    Padding

  • Internal State: as for SHA-3 Family Specific Rules, with the addition of cshake_block and key_block, and with L in place of out_len:

    • cshake_block, key_block: b bits each; and

    • L: 32 bits, the output length or bound in bits, or 0 for an unbounded KMACXOF output; in Hash_Output and Hash_Output_Bits, the bits still to be emitted, as out_len (Hash and MAC Functions, and XOFs); from Hash_Verify on, the tag length in bits.

  • Serialized Content: as for SHA-3 Family Specific Rules, with L in Position iv in place of out_len, and cshake_block and key_block appended, followed by an empty Padding. Explicitly:

    Pos. Size (Bits) Field

    i

    1600

    state

    ii

    16

    block_base

    iii

    16

    last_block_len

    iv

    32

    L

    v

    b

    cshake_block

    vi

    b or 64

    key_block or System Key Identifier

    vii

    0

    Padding

Machine-Specific Functions
  • P(), process_block() and update() are as in SHA-3 Family Specific Rules.

  • right_encode(x), as in cite:[nist-SP-800-185] §2.3, is the value x written as an unsigned big-endian integer on the smallest possible positive number m of bytes, followed by a single byte holding m.

State Machine
  • States: Ready, Hash_Absorb, Hash_Absorb_Last_Block, Hash_Output, Hash_Output_Bits and Success, and, for KMAC128 and KMAC256 only, Hash_Verify and Failure.

  • Allowed State Transitions:

    • As in SHA-3 Family Specific Rules.

    • For KMAC128 and KMAC256: Hash_Absorb, or Hash_Absorb_Last_Block with last_block_len = 0, → Hash_Verify → Success or Failure.

    • For KMAC128 and KMAC256, MachinePolicy[0] gates MAC generation, and MachinePolicy[1] MAC verification (Rule MR1).

    • KMACXOF128 and KMACXOF256, which serve as key derivation functions, gate no State (Rule MR1), and a non-zero MachinePolicy is unsupported Metadata for them (Hash and MAC Functions, and XOFs); a kl.derive moves their output directly into a key (Derivation Endpoints of the Machines).

  • Behavior: as in SHA-3 Family Specific Rules, with the following differences.

    • When entering Ready: L ← 0.

    • When leaving Ready for Hash_Absorb, the kl.setst first:

      1. XORs cshake_block into the rate and applies P();

      2. XORs key_block into the rate and applies P().

        The key enters state only within that kl.setst, so that the Serialized Content of a CC in Ready is the same on every implementation and holds no key-dependent state. In Ready, state is zero, so masking it would output state_mask.
    • When entering Hash_Output or Hash_Verify from Hash_Absorb or Hash_Absorb_Last_Block, the kl.setst:

      1. checks Xs and sets L as follows; any other Xs transitions the locker to Error State Invalid:

        1. for KMAC128 and KMAC256, the kl.setst into Hash_Output is of Form B, and sets L ← Xs, the output length in bits, with 32 ≤ Xs < 232, the lower bound being that of cite:[nist-SP-800-185] §8.4.2;

        2. for KMACXOF128 and KMACXOF256, the kl.setst into Hash_Output is of Form A or of Form B: a non-zero Xs, a multiple of 8 below 232, sets L ← Xs, the output bound in bits; a Form A kl.setst, or Xs = 0, sets L ← 0, for an unbounded output;

        3. for KMAC128 and KMAC256, where MachinePolicy[1] is set, the kl.setst into Hash_Verify is of Form B, and sets L ← Xs, the tag length in bits, with Xs a multiple of 8 and 32 ≤ Xs ≤ b, the lower bound being that of cite:[nist-SP-800-185] §8.4.2;

      2. then performs finalize(), which:

        1. XORs right_encode(L), or right_encode(0) for KMACXOF128 and KMACXOF256, into state from bit block_base on, as PROCESS_VLI with mode = xor_accumulate absorbs data; the encoding directly follows the last bit of the message, even when block_base is not a multiple of 8;

        2. then applies the padding of SHA-3 Family Specific Rules with D = bin(0, 2), the suffix 00 of cSHAKE (pad_byte = 0x04 when block_base is a multiple of 8), in place of the bin(15, 4) of SHAKE;

      3. sets block_base ← 0 and last_block_len ← 0.

    • In State Hash_Output, L is the out_len of Hash and MAC Functions, and XOFs, whose output loop applies, with these properties:

      • for KMAC128 and KMAC256, L need not be a multiple of 8;

      • with L ≠ 0 on entering Hash_Output, the output consists of ⌈L/8⌉ bytes, which may span several t-bit blocks, and its last byte holds the final L mod 8 bits, if any, in its least significant bits;

      • with L = 0, KMACXOF128 and KMACXOF256 squeeze arbitrarily many bits and never transition to Success.

    • In State Hash_Verify, the single Form B kl.exec invokes VERIFY_TAG(state, L) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)): it compares INPUT[L-1:0] with state[L-1:0].

Ascon

Ascon is a public permutation cite:[DBLP-journals-joc-DobraunigEMS21] standardized by NIST cite:[nist-SP-800-232] together with various cryptographic algorithms designed around it.

Ascon conventions

The Ascon Machines share:

  • state[0 .. 4]: the five 64-bit words S0 to S4 of cite:[nist-SP-800-232], 320 bits, with state[0] in bits [63:0]. Each Machine states its rate, the low bits of state.

  • ASCON(p), which applies the permutation Ascon-p[p] of cite:[nist-SP-800-232], of p rounds, to the state.

  • pad(x,r), which appends the bit 1 to the bit string x, followed by the bit string 0j where j = (- |x| - 1) mod r: pad(x,r) = 0j @ 1 @ x.

Ascon-AEAD128

In Ascon-AEAD128, the caller applies pad( ·, 128) to non-empty associated data, so that the Machine in State Hash_Absorb absorbs a whole number of 128-bit blocks; empty associated data is not padded. The caller must not pad the final block of the plaintext or ciphertext, which holds 0 to 127 bits (cite:[nist-SP-800-232]) and is empty when the length is a multiple of 128. The caller gives the bit length of that block as the Xs of the Form B kl.setst into Enc_Last_Block, resp. Dec_Last_Block, and, if the block is non-empty, supplies it by the single kl.exec of that State; the Machine applies pad( ·, 128) to the final plaintext block internally. A caller that pads the final block in software and supplies it as a whole block in Encrypt, resp. Decrypt, obtains a ciphertext and a tag that differ from those of cite:[nist-SP-800-232].

Parameters
  • b = 128.

  • k = 128.

  • Granularity: 128 bits.

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    128 or 64

    key or System Key Identifier

    iii

    0 or 64

    Padding

  • Internal State:

    • key: 128 bits.

    • state[0 .. 4] (Ascon conventions), with the rate state[127:0].

    • tag_len: 8 bits as int.

    • tag_len_p: the number of bits that every verification compares (Rule MR12): a multiple of 8 from 64 to 128, and 128 if KeyType = 1; held in AuxInfo, not serialized.

    • last_block_len: 7 bits as int.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    128 or 64

    key or System Key Identifier

    ii

    64

    state[0]

    iii

    64

    state[1]

    iv

    64

    state[2]

    v

    64

    state[3]

    vi

    64

    state[4]

    vii

    16

    last_block_len

    viii

    16

    tag_len

    ix

    32, or 96 with a System Key Identifier

    Padding

Machine-Specific Functions
  • ASCON(p) and pad(x,r) (Ascon conventions).

  • absorb_rate(X) XORs the 128-bit X into the rate: state[0] ← state[0] xor X[63:0], then state[1] ← state[1] xor X[127:64].

  • ASCON_TAG() computes the 128-bit tag and returns state[4] @ state[3] after:

    1. state[2] ← state[2] xor key[63:0]

    2. state[3] ← state[3] xor key[127:64]

    3. ASCON(12)

    4. state[3] ← state[3] xor key[63:0]

    5. state[4] ← state[4] xor key[127:64]

State Machine
  • States:

    • Ready: The CC is ready.

    • Hash_Absorb: Set the nonce, and process the AD.

    • Encrypt: Encrypt the plaintext.

    • Enc_Last_Block: Encrypt the last block of the plaintext.

    • Hash_Output: Return the tag.

    • Decrypt: Decrypt the ciphertext.

    • Dec_Last_Block: Decrypt the last block of the ciphertext.

    • Hash_Verify: Compare a user-provided value with the internally computed tag.

    • Success: The Machine has completed its operation without errors.

    • Failure: The Machine has completed its operation with an authentication failure.

  • Allowed State Transitions:

    • Ready → Hash_Absorb → Encrypt or Decrypt.

    • Encrypt → { Enc_Last_Block → } Hash_Output → Success.

    • Decrypt → { Dec_Last_Block → } Hash_Verify → Success or Failure.

    • The Machine makes these transitions itself (Rule MR18):

      1. a kl.setst into Enc_Last_Block, resp. Dec_Last_Block, with Xs = 0 pads the empty final block and enters Hash_Output, resp. Hash_Verify, directly, as does the Form A bypass naming Hash_Output from Encrypt, resp. Hash_Verify from Decrypt (Rule MR10 item 2);

      2. the kl.exec of Enc_Last_Block, resp. Dec_Last_Block, enters Hash_Output, resp. Hash_Verify;

      3. the kl.exec of Hash_Output enters Success;

      4. the kl.exec of Hash_Verify enters Success or Failure (Rule MR12).

    • Gated States: those of Rule MR1, with Hash_Output under encryption and Hash_Verify under decryption.

  • Behavior:

    • Upon entering State Ready:

      1. state ← zeros(320)

      2. tag_len ← tag_len_p (Rule MR12)

      3. last_block_len ← 0

    • In State Ready, a Form B kl.setst with immediate kl_state_set_aux_value and auxiliary operand Xs is an operation, not a State (Rule MR16): it leaves tag_len unchanged, and an Xs other than tag_len_p transitions the locker to Error State Invalid (Rule MR12).

      A truncated tag is the leftmost tag_len bits of the 128-bit tag in the bit order of cite:[nist-SP-800-232] §4.2.1, which are the tag_len least significant bits of state[4] @ state[3]. Entering Ready restores tag_len to tag_len_p (Rule MR12), so every message of the locker uses the same length, and a verification oracle confirms the tag only after about 2tag_len_p trials. Rule MR15 leaves the bound on failed verifications of cite:[nist-SP-800-232] §4.3 R4–R5, and a single tag_len across lockers that hold the same key by value, to the caller.
    • The kl.setst into Hash_Absorb is of Form C. It takes the nonce from INPUT and performs:

      1. state[0] ← 0x00001000808c0001

      2. state[1] ← key[63:0]

      3. state[2] ← key[127:64]

      4. state[3] ← INPUT[63:0]

      5. state[4] ← INPUT[127:64]

      6. ASCON(12)

      7. state[3] ← state[3] xor key[63:0]

      8. state[4] ← state[4] xor key[127:64]

      Only INPUT[127:0] is used (Rule MR8).

      The key enters state only within this kl.setst and within ASCON_TAG(), each of which completes with the key permuted or masked by permutation output, so no Serialized Content holds it (Rule GR55.1).
    • In State Hash_Absorb, only (multi-block) kl.exec instructions of Form B are expected, absorbing a data block INPUT into the state as follows:

      1. absorb_rate(INPUT)

      2. ASCON(8)

      If the associated data is empty, the caller absorbs no block, not even a padding block, and no permutation is applied. No kl.exec is then needed in this State (Rule GR18).

    • Upon entering State Encrypt or Decrypt, the following domain separation operation is performed:

      1. state[4] ← state[4] xor (bin(1,64) << 63)

    • In State Encrypt, (multi-block) kl.exec instructions are expected to be of Form A, encrypting INPUT into OUTPUT as follows:

      1. absorb_rate(INPUT)

      2. OUTPUT ← state[1] @ state[0]

      3. ASCON(8)

    • When entering State Enc_Last_Block, resp. Dec_Last_Block, the Form B kl.setst with immediate kl_state_enc_last_block, resp. kl_state_dec_last_block, and auxiliary operand Xs invokes FINAL_BLOCK_ENTRY(0, 127, 1) (FINAL_BLOCK_ENTRY(lo, hi, unit)): it admits any bit length Xs of the final block from 0 to 127 and sets last_block_len ← Xs, which, unlike item 4 of the macro, the kl.exec leaves unchanged. Xs need not be a multiple of 8 (Rule MR11): cite:[nist-SP-800-232] orders the bits within a byte as Notation and Conventions does, so pad places the terminating 1 at bit position Xs for any Xs. If Xs = 0, the kl.setst pads the empty final block, state[0] ← state[0] xor bin(1,64) (this is pad(∅,128) = zeros(127) @ 1), and transitions the locker to Hash_Output, resp. Hash_Verify; otherwise, the State waits for its single Form A kl.exec, as described next.

    • In State Enc_Last_Block, exactly one Form A kl.exec is expected, to encrypt the last block. It performs:

      • local tmp : bits(128)

      1. tmp ← pad(INPUT[last_block_len-1:0], 128)

      2. absorb_rate(tmp)

      3. OUTPUT ← trunc(state[1] @ state[0], last_block_len)

      4. The state machine then transitions to State Hash_Output.

    • In State Hash_Output, only one kl.exec instruction of Form C is expected, computing the tag into OUTPUT as follows:

      1. OUTPUT ← trunc(ASCON_TAG(), tag_len)

      2. The state machine then transitions to State Success.

      State Hash_Output processes a single block (Rule MR13) and admits any KLLEN ≥ tag_len, a multiple of 128 or not; a smaller KLLEN violates the granularity of the State (Rule MR6).

    • In State Decrypt, (multi-block) kl.exec instructions are expected to be of Form A, decrypting INPUT into OUTPUT as follows:

      • local tmp : bits(128)

      1. tmp ← (state[1] xor INPUT[127:64]) @ (state[0] xor INPUT[63:0])

      2. state[0] ← INPUT[63:0]

      3. state[1] ← INPUT[127:64]

      4. ASCON(8)

      5. OUTPUT ← tmp

    • In State Dec_Last_Block, exactly one Form A kl.exec is expected, to decrypt the last block. It performs:

      • local S_r : bits(128) – the rate part of the state

      • local P : bits(128)

      1. S_r ← state[1] @ state[0]

      2. P ← zeros(128-last_block_len) @ (S_r[last_block_len-1:0] xor INPUT[last_block_len-1:0])

      3. OUTPUT ← P

      4. absorb_rate(pad(P[last_block_len-1:0], 128))

      5. The state machine then transitions to State Hash_Verify.

    • In State Hash_Verify, which the decryption path enters by itself (Rule MR12), a single Form B kl.exec performs VERIFY_TAG(ASCON_TAG()) (SET_TAG_LEN(cap, lo) and VERIFY_TAG(expected, len)): it compares INPUT[tag_len-1:0] with the computed tag in constant time, and transitions the locker to Success if they match and to Failure otherwise.

Ascon-AEAD128 with Preset Nonce

Like GCM with Preset IV (GCM with Preset IV), Ascon-AEAD128 has a variant with a preset nonce: this Machine is PRESET(Ascon-AEAD128, nonce) (PRESET(parent, field), Ascon-AEAD128).

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    128 or 64

    key or System Key Identifier

    iii

    128

    nonce

    iv

    0 or 64

    Padding

  • Internal State:

    Same as for Ascon-AEAD128, with in addition:

    • nonce: 128 bits.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    128 or 64

    key or System Key Identifier

    ii

    64

    state[0]

    iii

    64

    state[1]

    iv

    64

    state[2]

    v

    64

    state[3]

    vi

    64

    state[4]

    vii

    16

    last_block_len

    viii

    16

    tag_len

    ix

    128

    nonce

    x

    32, or 96 with a System Key Identifier

    Padding

    nonce is serialized because every transition into Hash_Absorb, also after an import, loads it into state.

State Machine
  • States and Allowed Transitions:

    Same as for Ascon-AEAD128.

  • State Machine Behavior:

    As for Ascon-AEAD128, except that:

    • The kl.setst into Hash_Absorb is of Form A. It performs the operations of the Form C nonce setup of Ascon-AEAD128, with nonce in place of INPUT.

Ascon-AEAD128 with Nonce Masking

cite:[nist-SP-800-232] also describes a version of Ascon-AEAD128 with Nonce Masking:

Data Structures
  • Provisioning Input:

    Pos. Size (Bits) Field

    ii

    128 or 64

    K1 or System Key Identifier

    iii

    128 or 0

    K2; absent when Pos. ii holds a System Key Identifier, which retrieves both K1 and K2 (Rule GR55.1)

    iv

    0, or 64 with a System Key Identifier

    Padding

  • Internal State:

    • K1: 128 bits.

    • K2: 128 bits.

    • state, tag_len, tag_len_p and last_block_len: as in Ascon-AEAD128, whose Enc_Last_Block and Dec_Last_Block states this Machine inherits.

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    128 or 64

    K1 or System Key Identifier

    ii

    128 or 0

    K2, or empty (a single SKID in Pos. i retrieves both keys)

    iii

    64

    state[0]

    iv

    64

    state[1]

    v

    64

    state[2]

    vi

    64

    state[3]

    vii

    64

    state[4]

    viii

    16

    last_block_len

    ix

    16

    tag_len

    x

    32, or 96 with a System Key Identifier

    Padding

The Machine has the Parameters, Machine-Specific Functions, States and behavior of Ascon-AEAD128, with K1 as the key key. The nonce setup of Ascon-AEAD128 uses INPUT[127:0] xor K2 in place of INPUT. K2 enters state only in the nonce setup, inside the masked nonce, before ASCON(12); K1 enters it wherever key does in Ascon-AEAD128.

Nonce masking with a set nonce needs no Machine of its own: the Machine of Ascon-AEAD128 with Preset Nonce is provisioned with K1 as the key key and N xor K2 as nonce, which software computes. This combination needs K2 outside the KLF. It cannot use a K1 and K2 that a System Key Identifier retrieves, since a System Key Identifier of Ascon-AEAD128 with Preset Nonce retrieves key alone (Rule GR55.1). All rules of Ascon-AEAD128 with Preset Nonce apply to this combination.

Ascon-Hash256

Ascon-Hash256 cite:[nist-SP-800-232] instantiates Hash and MAC Functions, and XOFs; only the differences are given here. The Machine applies pad(M, 64) of cite:[nist-SP-800-232] §5.1 when the message M ends.

Parameters
  • b = 64, n = 320, t = 64, d = 256, state_offset = 0, tag_offset = 0.

Data Structures

The Provisioning Input contains only the MDH.

  • Internal State:

  • Serialized Content:

    Pos. Size (Bits) Field

    i

    64

    state[0]

    ii

    64

    state[1]

    iii

    64

    state[2]

    iv

    64

    state[3]

    v

    64

    state[4]

    vi

    16

    block_base, in bits

    vii

    16

    last_block_len, in bits; read_len in Hash_Output_Bits

    viii

    32

    out_len in Hash_Output and Hash_Output_Bits; in Set_Aux_Value of Ascon-CXOF128, Z_len in bits [15:0] and cumul_len in bits [31:16]; zero otherwise

    ix

    0

    Padding

    This layout replaces that of Hash and MAC Functions, and XOFs.

Machine-Specific Functions
  • ASCON(p) (Ascon conventions).

  • process_block() and update(): ASCON(12).

  • finalize(): state[0] ← state[0] xor (bin(1,64) << block_base), then ASCON(12).

State Machine
  • States and Allowed State Transitions: those of Hash and MAC Functions, and XOFs.

  • Behavior:

    • Upon entering State Ready:

      1. state[0] ← 0x0000080100cc0002

      2. state[1] ← zeros(64)

      3. state[2] ← zeros(64)

      4. state[3] ← zeros(64)

      5. state[4] ← zeros(64)

      6. ASCON(12)

      7. block_base, last_block_len and Position viii (out_len, or the Z_len and cumul_len of Ascon-CXOF128) are set to zero.

    • In State Hash_Absorb, PROCESS_VLI is invoked as in Hash and MAC Functions, and XOFs, with block = state, mode = xor_accumulate and cumul_len = None.

    • In State Hash_Absorb_Last_Block, the final piece need not be a whole number of bytes (Rule MR11, first bullet): cite:[nist-SP-800-232] orders the bits within a byte as Notation and Conventions does, as for Ascon-AEAD128.

    • Hash_Output follows Hash and MAC Functions, and XOFs. The digest has 256 bits, or Xs bits after a Form B Xs ≠ 0, and is emitted in any whole number of bytes, with ASCON(12) between successive 64-bit words and none after the last.

A keyed version of this algorithm is not needed. A trusted entity can provide a CC that has already absorbed secret content, and reuse it for multiple invocations by keeping a copy of the original SCC.

Ascon-XOF128

The Machine is the same as Ascon-Hash256 (Ascon-Hash256) with the following differences:

  1. The IV written to state[0] in State Ready is 0x0000080000cc0003.

  2. It is an XOF (Hash and MAC Functions, and XOFs): it has no d, and Hash_Output emits output of unbounded length, or of Xs bits after a Form B Xs ≠ 0. The first output word follows the ASCON(12) of finalize(), the first squeezing permutation of cite:[nist-SP-800-232] Algorithm 6.

Ascon-CXOF128

Ascon-CXOF128 differs from Ascon-XOF128 in its IV, 0x0000080000cc0004, and in the customization string Z of cite:[nist-SP-800-232] §5.3, which precedes the message as the blocks Z0 = bin(len_in_bits(Z), 64) and pad(Z, 64), each 64-bit block followed by ASCON(12). The Machine absorbs them:

  • A Form A kl.setst from Ready into Hash_Absorb selects the empty Z: it absorbs Z0 = zeros(64) and pad(Z, 64) = bin(1, 64).

  • A Form B kl.setst with immediate kl_state_set_aux_value and auxiliary operand Xs, from Ready or from Set_Aux_Value, enters State Set_Aux_Value for a Z of Xs bits. The State is LOAD_LONG_FIELD(Z_len, state, state, n, process_block(), None, xor_accumulate, 8) (LOAD_LONG_FIELD(len, block, state, n, process_block(), finalize(), mode, g)): Form B kl.exec instructions load Z as a long field, with W = cumul_len, in bits, absorbing it into the rate as it is loaded, and a same-State kl.setst restarts the load. With mode xor_accumulate, the macro does not zero state. The Machine adds:

    1. Xs must satisfy 0 ≤ Xs ≤ 2048; any other Xs transitions the locker to Error State Invalid.

    2. Entering the State sets state to its value in Ready and Z_len ← Xs, and the kl.setst then absorbs Z0 = bin(Xs, 64).

    3. Z_len need not be a multiple of 8 (Rule MR11), as for the message: the last transfer is truncated to Z_len − cumul_len bits (Macro: Processing Variable Length Inputs into a Fixed Length Output).

    4. With Z_len = 0, the load is complete on entry, and any kl.exec transitions the locker to Error State Invalid.

    5. With Z_len > 0 and the load complete, a kl.exec with an empty transfer window does not reach the Machine and the State is kept (Rule GR18); any other kl.exec transitions the locker to Error State Invalid.

  • A Form A kl.setst from Set_Aux_Value into Hash_Absorb:

    1. requires cumul_len = Z_len; otherwise, it transitions the locker to Error State Invalid, performing no operation;

    2. applies pad(Z, 64): state[0] ← state[0] xor (bin(1,64) << block_base) and ASCON(12);

    3. sets block_base, Z_len and cumul_len ← 0;

    4. then performs the operations of entering Hash_Absorb.

The States add Set_Aux_Value, which absorbs Z, and the Allowed State Transitions add Ready → Set_Aux_Value → Hash_Absorb. The Internal State adds Z_len, the bit length of Z, and cumul_len, the number of bits of Z absorbed so far, both serialized in Position viii (Ascon-Hash256). In Ascon-Hash256 and Ascon-XOF128, a kl.setst naming Set_Aux_Value transitions the locker to Error State Invalid (Rule GR19.4).

Accepted Risks

This section is informative.

MachinePolicy gates States (Rule MR1): a locker cannot enter a State of a direction that its policy disables. The policy does not prevent the abuse of a mode of operation. In the modes below, the enabled direction computes the disabled one under the IV or nonce of a message, which the caller sets or the PI fixes, since both directions use the same keystream or the same direction of the block cipher. In CBC, decryption computes encryption only under an IV that the computation determines. Preventing this would remove the one-direction policies of these Machines, or require the locker to generate every IV and nonce, so the KLE accepts these risks. Privileged code that narrows MachinePolicy to give a process a one-direction copy of a CC (kl.rstrl, kl.rstrh, and kl.rstrv) obtains separate directions only in the other Machines, such as ECB and XEX/XTS, and in CBC only for an encrypt-only copy.

Machines Machine
Policy
What the locker still computes

CBC (Chaining/Feedback Modes (CBC, CFB, and OFB))

0b10

Encryption under an IV that the output determines: software picks the last ciphertext block, decrypts it alone under IV zeros(b), XORs the plaintext block into the output to obtain the previous ciphertext block, and repeats; the last step yields the IV.

CFB (Chaining/Feedback Modes (CBC, CFB, and OFB))

0b01

Decryption. For each segment, software computes the input block from the IV and the earlier ciphertext, sets it as IV by a same-State kl.setst into Encrypt, encrypts a zero segment, and XORs the output with the ciphertext segment.

CFB (Chaining/Feedback Modes (CBC, CFB, and OFB))

0b10

Encryption: decrypting a zero segment outputs the keystream segment of the IV that software sets on entering Decrypt.

OFB (Chaining/Feedback Modes (CBC, CFB, and OFB)), CTR and XCTR (CTR/XCTR Keystream Generation)

0b01 or 0b10

Both directions: either bit allows Operate, which computes both.

GCM (GCM Mode)

0b01

Decryption without verification: encrypting a ciphertext under the IV of its message outputs the plaintext, since both directions XOR the same counter keystream.

GCM (GCM Mode, GCM with Preset IV), GCM-SIV (GCM-SIV Mode)

0b10

Ciphertext without a tag that verifies: decrypting a plaintext outputs its encryption under the IV, or in GCM-SIV the tag, of the decryption.

OCB (OCB Mode)

0b01

The final partial block P of a message: Enc_Last_Block XORs its input with Pad, so the input C outputs P*.

OCB (OCB Mode, OCB with Preset Nonce)

0b10

Ciphertexts that verify, as described below.

Ascon-AEAD128 (Ascon-AEAD128, Ascon-AEAD128 with Nonce Masking)

0b01

Decryption without verification, at a cost linear in the length of the message, with a kl.clone of the locker before each block (quadratic without it). Under the nonce and associated data of the message, software encrypts the known prefix of the plaintext and then a zero block; the last output block XORed with the next ciphertext block gives the next plaintext block.

Ascon-AEAD128 (Ascon-AEAD128, Ascon-AEAD128 with Preset Nonce, Ascon-AEAD128 with Nonce Masking)

0b10

Ciphertext without a tag that verifies, at a cost linear in the length of the message, with a kl.clone of the locker before each block (quadratic without it). Software decrypts the ciphertext computed so far and then a zero block; the last output block XORed with the next plaintext block gives the next ciphertext block.

A locker of OCB Mode or OCB with Preset Nonce with MachinePolicy = 0b10 lets software forge. Decrypt outputs each plaintext block before Hash_Verify checks the tag, and for a fixed nonce and block index i, the map from a ciphertext block to its plaintext block is a fixed permutation fi. Given a valid message (N, A, C, T) of m full blocks and an optional final partial block, software decrypts chosen m-block ciphertexts under N and A, which no Machine prevents (Rule MR15). It searches for C' ≠ C such that f1(C'1) xor … xor fm(C'm) equals the checksum of the valid message. Since the tag depends on the ciphertext only through the checksum, (N, A, C', T) verifies. Wagner’s generalized birthday algorithm (CRYPTO 2002) finds such a C' with about 223 block decryptions for m ≥ 128, 245 for m = 4 and 264 for m = 2; for m = 1, no such C' exists. If the final block holds l > 0 bits, software also chooses C' freely, since the checksum depends on P' only in l of its bits: the search then concerns 128 − l bits, about 2128−l decryptions for m = 1 (28 for a 15-byte final block), and fewer for larger m.

A repeated IV or nonce, which Rule MR15 leaves to the caller, can reveal locker state derived from the key. In GCM Mode, two messages encrypted under one key and one IV give, with their tags, a polynomial in auth_key whose roots software computes, leaving few candidates (the "forbidden attack" of Joux, 2006). With auth_key, every valid message gives the tag mask of its IV, so software forges under that IV outside the locker. Since the Machine also accepts IVs of lengths other than 96 bits, whose J0 is a GHASH under auth_key, software can compute an IV whose J0 is the J0 of any chosen IV with its 32-bit counter decremented by one; encrypting or decrypting a zero block under it, in any locker of GCM Mode that holds the key, outputs the tag mask of the chosen IV. One repeated IV thus allows forgeries under every IV. Narrowing MachinePolicy, an ExpirationDate and clearing the locker do not revoke them; only retiring the key, in every locker and SCC that holds it, ends them. GCM-SIV Mode limits the damage of a repeated nonce to revealing whether two messages are equal.

Two Rules limit the remaining risks:

  • Rule MR12 fixes, for the Machines that it lists, the number of bits that every verification of a locker compares, so such a locker that verifies but does not generate confirms a tag only after about 2tag_len_p trials; for GCM the bound depends on the message length (GCM Mode).

  • Rule SR18 forbids software to use the plaintext that an AEAD Machine outputs before the locker reaches Success, since that plaintext is unauthenticated until then.

Elliptic Curve Cryptography

The Elliptic Curve Machines provide:

  1. Scalar multiplication with known and unknown base point.

  2. ECDSA, SM2 and EdDSA signature generation and verification.

The x25519 and x448 Machines (X25519- and X448-Specific Rules) provide only the former.

KDFs, hash functions and formats vary too much for general KEM or PKE support; among the elliptic curve standards, only SM2 fully specifies an integrated encryption scheme cite:[GMT-0003-4-2012]. Software builds such schemes on scalar multiplication, and kl.derive moves the shared secret into the hash function of the KDF, and the KDF output into the key of a symmetric Machine, without exposing them. A key that is exposed anyway should be provisioned into a locker, and its exposed copy erased at once.

Provisioning sets the Generator field to the default base point (“generator”) that the standards listed below define for the curve. Software may overwrite the field; a Form A kl.setst to Set_Generator, or one of Form B with zero in the GPR, restores the default, as does a Form B kl.setst to Ready with bit 0 of Xs set.

With MachineExtension = 1, the public-points variant, Generator and SecondPt are public fields, which an SCC carries in clear (Rule GR9): Generator always holds the default generator of the curve, so that Point_Mul computes only a public key, and a scalar multiplication of SecondPt, which would make a shared secret, transitions the locker to Error State Invalid (Point_Mul below). In this variant and the sealed one, a Form B kl.setst to Set_Generator with a non-zero operand, or to Ready with bit 5 of Xs set while HasSecondPt is set, transitions the locker to Error State Invalid, and a provisioning or import whose Generator is not the default completes into Error State Invalid (Rule MR3). The variant suits signature generation and verification, and key-pair generation; software uses MachineExtension = 0 for a key exchange and for a custom generator. It is defined for every Elliptic Curve Machine, and is unsupported Metadata where not implemented (Validity of Metadata).

With MachineExtension = 2, the sealed variant, Generator always holds the default generator, as in the public-points variant, but both points are private, Point_Mul may multiply SecondPt, and the shared secret is a sealed source (Rule GR31.3) that no kl.exec emits (Output below). It suits a key exchange whose key derivation runs in lockers. It is defined for every Elliptic Curve Machine except those of EdDSA-Specific Rules, and is unsupported Metadata where not implemented.

All values (integers, coordinates, etc.) are in little-endian format, except the shared secret of the Weierstrass curves that Output emits, which follows the byte order of its standard (see Output below).

Parameters

The parameters used in this section are:

  1. The bit length b of the main fields, such as coordinates, signature R and S fields, scalars;

  2. The bit length h of the hash used in the signature scheme. The Hash field holds:

    1. for the ECDSA curves, bin(e, h), where e is the leftmost min(N, outlen) bits of the message digest, read as a big-endian integer, as cite:[nist-fips-186-5] §6.4 and §6.4.1, step 2, prescribe:

      1. N is the bit length of the group order n, and outlen that of the digest;

      2. the digest is truncated, not reduced modulo n;

      3. the caller performs this truncation and chooses an approved hash function;

    2. for SM2, bin(e, 256), with e the big-endian integer of SM3(ZA ‖ M) of cite:[GMT-0003-2-2012], where ZA = SM3(bswap(bin(entlenA, 16)) ‖ IDA ‖ bswap(bin(a, 256)) ‖ bswap(bin(b, 256)) ‖ bswap(bin(xG, 256)) ‖ bswap(bin(yG, 256)) ‖ bswap(bin(xA, 256)) ‖ bswap(bin(yA, 256))):

      1. entlenA is the bit length of the identity IDA, a and b are the curve coefficients, not the parameter b, and (xA, yA) is the public key;

      2. the caller computes ZA and e, since every input to ZA is public; the KLE unit computes neither;

    3. for the Edwards curves, the 64-byte PH(M), used only in pre-hash mode; see EdDSA-Specific Rules;

  3. The bit length j of the random number used as nonce in signature generation;

  4. The number u of coordinates used to represent a point (u is 1 or 2); and

  5. The number v of elements used to represent a signature (v is 0, 1 or 2, where v = 0 denotes a curve for which no signature scheme is provided).

The granularity of every Elliptic Curve Machine, X25519, X448 and EdDSA included, is 8 bits: a field can be transferred with any SEW from 8 to 64 bits that divides its size, or through the KLIOBUF in any number of bytes.

The parameters for the defined curves are:

  • NIST curves cite:[NIST-SP-800-186,nist-fips-186-5]:

    • secp256r1 (NIST P-256): b = h = j = 256, u = v = 2.

    • secp384r1 (NIST P-384): b = h = j = 384, u = v = 2.

    • secp521r1 (NIST P-521): b = 576 (55 msbs set to zero), h = j = 576 (55 msbs set to zero), u = v = 2.

  • Edwards curves for signatures cite:[RFC8032,nist-fips-186-5]:

    • ed25519: b = 256, h = 512; u = 1, v = 2.

    • ed448: b = 456, h = 512; u = 1, v = 2.

  • Montgomery curves, for key exchange only cite:[RFC7748]:

    • x25519 (curve25519): b = 256; u = 1, v = 0.

    • x448 (curve448): b = 448; u = 1, v = 0.

  • Brainpool cite:[RFC5639,RFC8734]:

    • brainpoolP256r1: b = h = j = 256; u = v = 2.

    • brainpoolP384r1: b = h = j = 384; u = v = 2.

    • brainpoolP512r1: b = h = j = 512; u = v = 2.

  • SM2 cite:[GMT-0003-1-2012,GMT-0003-2-2012,GMT-0003-3-2012,GMT-0003-4-2012]: b = h = j = 256; u = v = 2.

For the Edwards curves, a point is the compressed b-bit string of cite:[RFC8032] §5 (u = 1), and a signature is the pair (R, S) of such strings (v = 2). So b = 456 for ed448, whose strings are 57 bytes. h = 512 because, in pre-hash mode, Hash holds the 64-byte PH(M). j = 0, since EdDSA uses no RndNum (EdDSA-Specific Rules).

For the Montgomery curves, a point is its u-coordinate alone (cite:[RFC7748] §5, u = 1). Their Machines provide key exchange only (X25519- and X448-Specific Rules), so v = 0, and h and j are not defined. They are listed apart from the Edwards curves because their points differ, and so does b for x448.

All curves here are defined over prime fields. For secp521r1, the 55 most significant bits of Scalar, Hash and RndNum, of each coordinate of Generator and SecondPt, and of each component of Signature must be zero. The locker transitions to Error State Invalid if a write sets one of them, or if Point_Mul, Sign_Generate or Sign_Verify finds one set in a value it uses, a resumed RndNum included (Rule MR3).

A point is valid if:

  • each of its coordinates is less than p;

  • it satisfies the curve equation;

  • it is not the neutral element: the point at infinity of a Weierstrass curve, resp. (0, 1) of an Edwards curve;

  • where the cofactor is not 1, it lies in the prime-order subgroup; and

  • on an Edwards curve, it decodes as cite:[RFC8032] §5.1.3, resp. §5.2.3, prescribes.

Point_Mul, Sign_Generate and Sign_Verify check the validity of Generator and SecondPt when they read them (Rule MR3). For the Edwards curves, only Point_Mul uses Generator, and Sign_Verify checks SecondPt only as EdDSA-Specific Rules states. An invalid point that an operation checks, and whose encoding satisfies the representation of the curve, is a data error and leads to Failure (Rule MR2), a coordinate not less than p included. A violated representation, such as a set msb of secp521r1, is a configuration error, as stated above. For the Montgomery curves, the check of X25519- and X448-Specific Rules replaces this one.

Data Structures
  • MDH:

    The Elliptic Curve Machines use the StateExtension field as follows:

    Table 6. StateExtension bits used by the Elliptic Curve Machines
    Bit Name Description

    0

    HasSecondPt

    A second point has been set.

    1

    HasSignature

    A signature has been set.

    2

    HasHash

    A hash has been set.

    3

    HasRndNum

    A random number has been set. For the EdDSA Machines this bit is HasHashState instead (EdDSA-Specific Rules).

    The Elliptic Curve Machines use the MachineUse field as follows:

    Table 7. MachineUse bits used by the Elliptic Curve Machines
    Bits Name Description

    [1:0]

    OutputType

    Determines what Output emits: 0, a point, the product of Generator, such as a public key; 1, a signature, from Signature; 2, a shared secret, the product of SecondPt, which Point_Mul multiplies whenever HasSecondPt is set, whether the point was loaded or copied. Points and shared secrets are emitted from SecondPt. The value 3 is reserved: a kl.exec or kl.derive in Output with that value transitions the locker to Error State Invalid.

    [13:2]

    Progress

    Tracks, in an implementation-defined and non-portable unit, the progress of long-running operations such as scalar multiplications. Whenever it is non-zero, the SCC must include an ADS (Rule GR38).

    Except in the sealed variant, Output explicitly allows the export of a shared secret through kl.exec, like any other output, so the caller can read it. Too many protocols process the ECDH shared secret themselves to list them as kl.derive destinations. Its kl.derive transfers are therefore unrestricted (Rule GR31.1), and the exclusion of K1 ‖ K2 of nonce masking as a destination (Derivation Endpoints of the Machines) applies only to a secret that kl.exec cannot read, such as the ML-KEM sharedkey or a sealed shared secret.

    For ECC Machines, MachinePolicy[0] gates signature generation and MachinePolicy[1] signature verification, with their Gated States (Rule MR1), and MachinePolicy ≠ 0 gates Set_Hash, since its field Hash exists only then. All four combinations are admissible, except as X25519- and X448-Specific Rules and EdDSA-Specific Rules restrict them.

The Provisioning Input contains only the MDH. A system-specific import (Rule GR51) checks every Generator, Scalar, SecondPt, Hash and Signature that it converts, with the checks and outcomes of a completed load of that field. It sets HasSecondPt, HasHash, resp. HasSignature for a converted SecondPt, Hash or Signature (Rule MR4).

  • Internal State:

    • OutputType: 2 bits, held in bits [1:0] of the MDH field MachineUse.

    • Progress: integer, held in bits [13:2] of the MDH field MachineUse (Table 7): the implementation-defined progress of a long-running operation.

    • block_base: 8 bits, held in bits [15:8] of the MDH field AuxInfo. The field W of Rule MR14, in bytes, of the “set” and “output” operations; it is public, since the instructions that the transfer issues determine it. Provisioning and a system-specific import zero it, and every kl.setst zeroes it; an immediate assignment of Set_Generator or Set_Scalar then sets it to the field size. It is distinct from the counters H.block_base and H'.block_base of the hash instances of EdDSA-Specific Rules.

    • Generator (X, {Y}): one or two b-bit strings representing the X {and Y} coordinate{s}.

    • SecondPt (X, {Y}): one or two b-bit strings representing the X {and Y} coordinate{s}. For signature verification and for multiplication by an unknown point, SecondPt holds the public key, resp. the peer’s point.

    • Scalar: b-bit string.

    • If signature generation or verification is allowed:

      • Signature (R,S): two b-bit strings representing the R and S components.

      • Hash: an h-bit string representing the hash.

    • If signature generation is allowed:

      • RndNum: a j-bit string representing the random number.

    • Additional data, for instance precomputed multiples of the Generator.

    A kl.rstrl or kl.rstrv that leaves both bits of MachinePolicy clear (kl.rstrl, kl.rstrh, and kl.rstrv) erases Signature and Hash and clears HasSignature and HasHash, since these fields then no longer exist. One that clears MachinePolicy[0] likewise destroys RndNum and clears HasRndNum.

  • Serialized Content:

    The public fields (Rule GR9) come first: Signature and, with MachineExtension = 1, Generator and SecondPt. Positions i, i.a, v and vi are present only for the values of MachinePolicy given:

    Pos. Type Size (Bits) Field

    i

    Public

    If MachinePolicy ≠ 0: vb, else: 0

    Signature, R value, followed by S value if v=2.

    i.a

    Public

    If MachinePolicy ≠ 0: p1, else: 0

    Padding

    ii

    Public if MachineExtension = 1, else Private

    ub

    Generator, X coordinate, followed by Y coordinate if u=2.

    iii

    Public if MachineExtension = 1, else Private

    ub

    SecondPt, X coordinate, followed by Y coordinate if u=2. Can be the Public Key.

    iii.a

    Public if MachineExtension = 1, else Private

    p3

    Padding

    iv

    Private

    b

    Scalar: b-bit string. Can be the Private Key.

    v

    Private

    If MachinePolicy ≠ 0: h, else: 0

    Hash: an h-bit string representing the hash.

    vi

    Private

    If MachinePolicy[0] = 1: j, else: 0

    RndNum. Its width is j, the nonce length, both here and in the Internal State.

    vi.a

    Private

    p6

    Padding

    The padding p1 = (−vb) mod 128 and p3 = (−2 × ub) mod 128 ends Signature, resp. Generator ‖ SecondPt, at a 128-bit boundary; it is 112 for ed448 and 0 for the other curves. The final Padding p6 = (−(b + (MachinePolicy ≠ 0) × h + MachinePolicy[0] × j)) mod 128 ends Content1. The transfer counter block_base is not serialized: it is held in the MDH (AuxInfo[15:8]). SCC_ClearLen1 is (MachinePolicy ≠ 0) × ⌈vb / 128⌉ with MachineExtension ≠ 1, and (MachinePolicy ≠ 0) × ⌈vb / 128⌉ + ⌈2 × ub / 128⌉ with MachineExtension = 1. Signature holds only a signature loaded for verification, or one that Sign_Generate has completed, or its R as EdDSA-Specific Rules states, or zero.

    Which fields are serialized depends only on MachinePolicy, never on State or StateExtension (Length of External Formats and KLF Capacity Usage of a Locker): a field is serialized with whatever it holds, a partial load or an intermediate value included, and its Has flag governs only its use.

    RndNum holds a value only while a signature generation is under way, with HasRndNum set, and is zero otherwise. A StateExtension @ State with HasRndNum set in a State other than Sign_Generate is not supported by the Machine: an SCC that carries it is invalid Metadata (Validity of Metadata).

    The size in bytes of the Positions other than ii, iv and vi.a is:

           varlen ← (ub + p3)/8 + (MachinePolicy != 0) × (vb + p1 + h)/8 + MachinePolicy[0] × j/8.

    If AuxDataLen ≥ 2, the SCC also carries the ADS: IMPQUAL and SIV2 precede Content1, and Content2 follows it (Plaintext of the Sealed Cryptographic Context (SCC) Format, all Sections in Order).

    For ed25519 and ed448 the fields of EdDSA-Specific Rules follow Position vi.a.

State Machine

  • States: Besides Ready (1), Success (54), Failure (55), ECC Machines define:

    • Set_Generator (2)

    • Set_Scalar (3)

    • Point_Mul (4)

    • Sign_Generate (5)

    • Sign_Verify (6)

    • Set_Hash (7)

    • Set_SecondPt (8)

    • Sign_Input (9)

    • Output (10)

  • Allowed State Transitions:

    The Set states are Set_Generator, Set_Scalar, Set_Hash, Set_SecondPt and Sign_Input.

    • Ready → any Set state.

    • Any Set state → any Set state, itself included.

    • Ready or any Set state → one of the following, with these entry conditions (Rule MR1):

      • Point_Mul: 1 ≤ int(Scalar) < n, where n is the order of the group;

      • Sign_Generate: HasHash and 1 ≤ int(Scalar) < n; for SM2, HasHash and 1 ≤ int(Scalar) ≤ n − 2 (cite:[GMT-0003-2-2012]);

      • Sign_Verify: HasSecondPt, HasHash and HasSignature.

      • X25519- and X448-Specific Rules replaces the condition of Point_Mul on Scalar, and EdDSA-Specific Rules replaces the conditions of all three States.

    • Point_Mul or Sign_Generate → Output, made only by the Form D kl.exec of the State (Rule MR18), or → Failure when a point that the operation uses is not valid (Rule MR2).

    • Output → Success, when the output is complete (Rule MR14), or on the first committed unit of a kl.derive of the shared secret.

    • Sign_Verify → Success or Failure.

    • A kl.setst into Set_Generator, Set_Scalar or Ready is of Form A or B, as the Behavior states, and one into Set_Ctx or Msg_Absorb of EdDSA-Specific Rules of Form B (Rule GR19.1).

    • Set_Generator sets a group generator, or the default one; Set_Scalar sets a scalar for scalar multiplication, or a private key.

    • HasSecondPt, HasSignature and HasHash follow Rule MR14, and are held in StateExtension (Table 6). HasRndNum, also held there, is set only while a signature operation holds RndNum, which is drawn, never loaded (Rule GR38).

    • Generator and Scalar have no flag. A load of either that is left incomplete zeroes the field (Rule MR14): a zero Generator is not a valid point, and a zero Scalar not a configured private key.

  • Behavior:

    • Provisioning sets Generator to the default of the curve, and Scalar to zero.

    • The Set states and Output follow Rule MR14, with the progress recorded in block_base, in bytes.

    • Entering Set_Generator:

      1. by a Form B kl.setst whose operand is zero, Form A included, sets the default generator of the curve, and block_base ← ub/8, which completes the load;

      2. by a Form B kl.setst whose operand is non-zero, erases Generator and starts a load: Form B kl.exec instructions then load the ub/8 bytes of Generator; with MachineExtension ≠ 0, it transitions the locker to Error State Invalid instead.

    • Entering Set_Scalar, Set_Hash, Set_SecondPt or Sign_Input by a Form A kl.setst starts a load of the field X that the State sets by Form B kl.exec instructions (Rule MR14): it erases X, Scalar becoming zero, and clears HasX where that flag exists.

    • A Form B kl.setst into Set_Scalar:

      1. whose operand is zero, Form A included, acts as the Form A kl.setst above;

      2. whose operand is non-zero sets Scalar to a random private key, and block_base ← b/8, which completes the load; no kl.exec follows. Rule GR45 applies if the RBG fails. The key is:

        1. for the NIST and Brainpool curves, an integer d with 1 ≤ d < n, generated as cite:[nist-fips-186-5] Appendix A.2.1 or A.2.2 prescribes;

        2. for SM2, one with 1 ≤ d ≤ n − 2 (cite:[GMT-0003-1-2012]), from an RBG of security strength at least 128 bits;

        3. for the Edwards curves, a b-bit string obtained as cite:[nist-fips-186-5] Appendix A.2.3, step 1, prescribes, from an RBG of security strength at least 128 bits for ed25519 and 224 bits for ed448;

        4. for the Montgomery curves, a uniformly random b-bit string, from an RBG of security strength at least 128 bits for x25519 and 224 bits for x448.

          The bits of Scalar beyond the key are zero.

    • Retry rules of signature generation:

      1. for the NIST and Brainpool curves, the signature is recomputed with a fresh k whenever r = 0 or s = 0 (cite:[nist-fips-186-5] §6.4.1);

      2. for SM2, whenever r = 0, r + k = n, or s = 0 (cite:[GMT-0003-2-2012]);

      3. the Edwards curves use no random secret, and have no retry rules.

      4. each retry draws k as Sign_Generate does and sets RndNum ← bin(k, j) before it records any further progress.

    • In State Point_Mul, a single Form D kl.exec performs a scalar multiplication:

      1. The base point P is SecondPt if HasSecondPt is set, and Generator otherwise.

      2. If P is SecondPt and MachineExtension = 1, the locker transitions to Error State Invalid.

      3. If P is not a valid point, the state machine transitions to Failure.

      4. SecondPt ← [int(Scalar)]P, encoded as in Elliptic Curve Cryptography, and HasSecondPt is set.

      5. OutputType ← shared secret if P is SecondPt, and point otherwise, and the locker transitions to Output.

    • In State Sign_Generate, a single Form D kl.exec signs, over the base point Generator, with private key d = int(Scalar) and message value e = int(Hash):

      1. If Generator is not a valid point, the locker transitions to Failure.

      2. If Progress is zero, the per-signature secret k, uniformly distributed in [1, n − 1], is generated from the RBG (Prerequisites, Rule GR45) as cite:[nist-fips-186-5] Appendix A.3.1 or A.3.2 prescribes, also for SM2; RndNum ← bin(k, j), and HasRndNum is set.

      3. If Progress is non-zero, the interrupted operation is resumed with the RndNum held, or restarted (Rule GR38).

      4. The signature (r, s) is computed as cite:[nist-fips-186-5] §6.4.1 specifies for the NIST and Brainpool curves, and as cite:[GMT-0003-2-2012] specifies for SM2, with the retry rules above.

      5. Signature ← (r, s), and HasSignature is set; RndNum is destroyed and HasRndNum cleared.

      6. OutputType ← signature, and the locker transitions to Output.

    • In State Sign_Verify, a single Form D kl.exec verifies Signature against the public key held in SecondPt and the message value e = int(Hash), as cite:[nist-fips-186-5] §6.4.2 specifies for the NIST and Brainpool curves, and as cite:[GMT-0003-2-2012] specifies for SM2:

      1. it performs every check those specifications require, the ranges of r and s included, and checks that SecondPt and Generator are valid points;

      2. if a check fails, or the signature equation does not hold, the state machine transitions to Failure, else to Success.

    • In State Output, OutputType determines the output and its length:

      • point: SecondPt, ub bits;

      • signature: Signature, vb bits;

      • shared secret: the byte string that the standard of the curve defines as the shared secret, in the byte order of that standard, which for the Weierstrass curves is the one exception to the little-endian encoding. It is:

        • for the NIST and Brainpool curves, Z of cite:[NIST-SP-800-56Ar3] §5.7.1.2: the X coordinate x as a big-endian string of m = ⌈log2(p)/8⌉ bytes (its Appendix C.2), that is bswap(bin(x, 8m)), 8m bits (66 bytes for secp521r1);

        • for SM2, x2 ‖ y2 of cite:[GMT-0003-4-2012], each coordinate a big-endian string of 32 bytes, that is bswap(bin(y, 256)) @ bswap(bin(x, 256)), x2 in the 32 least significant bytes, emitted first, 512 bits;

        • for the Montgomery curves, the whole b-bit string K of cite:[RFC7748] §6, little-endian as that standard defines it;

        • for the Edwards curves, whose standard defines no shared secret, the encoded point (cite:[RFC8032] §5.1.2, resp. §5.2.2).

    • In State Output, Form C kl.exec instructions emit the output, ending in Success (Rule MR14), in which no kl.derive is admitted.

      • This State allows the export of the shared secret through kl.exec, except in the sealed variant, where a Form C kl.exec with OutputType = shared secret transitions the locker to Error State Invalid. The shared secret is also a kl.derive source, unrestricted, or sealed in the sealed variant (Rule GR31.3), as a field (Rule GR31.1), of one kl.derive, and only while block_base = 0, before a Form C kl.exec has emitted any of it: that kl.derive transitions the locker to Success (Rule GR28), and one made once block_base ≠ 0 transitions it to Error State Invalid (Rule GR29 item 2). The transfer reads it from its first byte (Rule GR28): for X25519 and X448, a key field receives the first eff_length bytes of the shared secret; for the other curves, a key field is not a destination (Derivation Endpoints of the Machines); a message input receives the whole shared secret, with length equal to the length of the shared secret (Rules GR29 item 6 and GR31.1).

    • Entering Ready by a Form B kl.setst: bits 0 to 6 of Xs select the fields Generator, Scalar, SecondPt, Hash and Signature to copy, reset, erase or keep; a non-zero bit 7 or above transitions the locker to Error State Invalid.

      1. First the copies are made, both from the values held before the instruction, so that bits 4 and 5 together exchange the two points:

        1. bit 4: Generator is copied onto SecondPt, and HasSecondPt is set;

        2. bit 5: if HasSecondPt was set, SecondPt is copied onto Generator, or, with MachineExtension ≠ 0, the locker transitions to Error State Invalid; otherwise bit 5 has no effect.

      2. Then the fields are reset or erased:

        1. bit 0: Generator is reset to the default value;

        2. bit 1: SecondPt is erased and HasSecondPt is cleared;

        3. bit 2: Scalar is erased;

        4. bit 3: Hash is erased and HasHash is cleared;

        5. bit 6: Signature is erased and HasSignature is cleared.

      3. Every field whose bit is clear is kept. A Form A kl.setst sets no bit, and keeps all five fields.

    • Progress, bits [13:2] of MachineUse, is the field P of Rule GR38 for Point_Mul, Sign_Generate and Sign_Verify, and, in the EdDSA Machines (EdDSA-Specific Rules), for a kl.setst that enters or leaves Msg_Absorb (Rule GR37). Its material is RndNum, where the Machine uses it, and the intermediate values that the operation keeps in the ADS; for a kl.setst that enters or leaves Msg_Absorb, these include the expanded seed, the hash states being finalized, and r, R, k' and A before the operation completes. Each event of that Rule that zeroes Progress also destroys the material and, where the Machine has it, clears HasRndNum.

X25519- and X448-Specific Rules

The x25519 and x448 Machines implement the functions X25519 and X448 of cite:[RFC7748] §5, and with them the Diffie-Hellman key exchange of cite:[RFC7748] §6. Of the operations of Elliptic Curve Cryptography they provide only scalar multiplication. They differ from the other curves in three respects: a point is a single coordinate, the scalar is an arbitrary b-bit string, and the input point is not checked for validity, only the result. This subsection states the consequences; everything not restated here follows Elliptic Curve Cryptography.

Parameters
  • The curves are the Montgomery curves v2 = u3 + A · u2 + u of cite:[RFC7748] §4: curve25519 for x25519, with p = 2255 - 19 and A = 486662, and curve448 for x448, with p = 2448 - 2224 - 1 and A = 156326. curve25519 is birationally equivalent to the Edwards curve of ed25519; curve448 is related to that of ed448 by an isogeny of degree 4. The Machines are nevertheless distinct, and points and private keys are not interchangeable between them.

  • A point is represented in compressed form, by its u-coordinate alone, so the parameter u = 1. The u-coordinate is held as the X coordinate of Generator and SecondPt of Elliptic Curve Cryptography. A public key and a shared secret are 32 bytes for x25519 and 56 bytes for x448.

  • There is no signature scheme: v = 0, and h and j are not defined.

  • X25519(k, u) and X448(k, u) map a scalar and a u-coordinate, both b-bit strings, to a b-bit string, decoding their inputs as cite:[RFC7748] §5 prescribes:

    • the scalar is clamped: for x25519, bits 0, 1, 2 and 255 are cleared and bit 254 is set; for x448, bits 0 and 1 are cleared and bit 447 is set;

    • for x25519, bit 255 of the u-coordinate is ignored; and

    • a u-coordinate not smaller than p is reduced modulo p.

  • The private key is the unclamped b-bit string held in Scalar, which holds a configured private key when it is non-zero. It is not compared with the order of the group.

Data Structures

Those of Elliptic Curve Cryptography, with the following changes:

  • MDH:

    • MachinePolicy is not used and must be zero; a non-zero value is unsupported Metadata (Validity of Metadata), and a kl.rstrl or kl.rstrv leaves it zero (kl.rstrl, kl.rstrh, and kl.rstrv).

    • Of the StateExtension bits (Table 6) only HasSecondPt is used: an SCC with any of the bits 1 to 3 set is invalid Metadata (Validity of Metadata).

    • OutputType (Table 7) is never signature: a multiplication of Generator outputs a point, the public key, and one of SecondPt a shared secret, K; both are a single b-bit string.

  • Internal State: Generator and SecondPt are each a single b-bit string, a u-coordinate. SecondPt holds the peer’s public key and, after a scalar multiplication, the public key of the locker or the shared secret. Signature, Hash and RndNum do not exist.

  • Serialized Content: Positions ii to iv and vi.a of Elliptic Curve Cryptography, with u = 1; Positions i, i.a, v and vi are always empty. varlen ← b/8.

State Machine
  • States: besides Ready (1), Success (54) and Failure (55), only the following States of Elliptic Curve Cryptography:

    • Set_Generator (2)

    • Set_Scalar (3)

    • Point_Mul (4)

    • Set_SecondPt (8)

    • Output (10)

Sign_Generate, Sign_Verify, Set_Hash and Sign_Input are not defined: a kl.setst that names one of them transitions the locker to Error State Invalid (Rule GR19.4).

  • Allowed State Transitions: the Set states are Set_Generator, Set_Scalar and Set_SecondPt.

    • Ready or any Set state → any Set state, itself included, or → Point_Mul, which requires Scalar to hold a configured private key (Rule MR1).

    • Point_Mul → Output, or → Failure when the result is the all-zero string (Rule MR2); Output → Success, as in Elliptic Curve Cryptography.

  • Behavior:

    • Provisioning sets Generator to the base point of cite:[RFC7748] §4.1, resp. §4.2, that is, to the u-coordinate 9 for x25519 and 5 for x448, and Scalar to zero.

    • Generator, SecondPt and Scalar accept every b-bit string: no check is made when they are written (Rule MR3).

    • In State Point_Mul, a single Form D kl.exec performs a scalar multiplication, in the following steps, which replace those of Elliptic Curve Cryptography:

      1. The base point P is SecondPt if HasSecondPt is set, and Generator otherwise. P is not checked for validity: X25519 and X448 are defined for every b-bit string.

      2. R ← X25519(Scalar, P), resp. X448(Scalar, P).

      3. If R is the all-zero string, the locker transitions to Failure, and SecondPt and HasSecondPt are left unchanged. The check is made in constant time; cite:[RFC7748] §6 makes it optional.

      4. Otherwise SecondPt ← R, HasSecondPt is set, OutputType ← shared secret if P is SecondPt, and point otherwise, and the locker transitions to Output.

    • Entering Ready by a Form B kl.setst, bits 3 and 6 of Xs have no effect: Hash and Signature do not exist.

    • Rule GR38 applies to Point_Mul, with no RndNum to destroy.

A key exchange is two scalar multiplications with the same Scalar: with HasSecondPt clear and the default Generator, it yields the public key; after the peer’s public key is loaded in Set_SecondPt, it yields the shared secret K. cite:[RFC7748] §6 uses K as the input of a key derivation function, together with the two public keys; as a kl.derive source in Output (Derivation Endpoints of the Machines), K reaches that function without leaving the unit. A small-order P yields the all-zero R.

EdDSA-Specific Rules

EdDSA, standardized in cite:[RFC8032] and cite:[nist-fips-186-5], does not fit the division of labor used by the other curves of Elliptic Curve Cryptography, under which the caller hashes the message and the KLE unit performs only the group arithmetic. Both of its hash invocations take material the caller does not hold:

       r  = int(H(dom ‖ prefix ‖ M)) mod L, where prefix is secret, and
       k' = int(H(dom ‖ R ‖ A ‖ M)) mod L, where R = [r]B is computed inside.

The Machine must perform the hashing itself. This subsection states the consequences; everything not restated here follows Elliptic Curve Cryptography.

Parameters
  • H is SHA-512 for ed25519 and SHAKE256, with a 114-byte output, for ed448.

  • The private key, or seed, is the b-bit string held in Scalar; Scalar holds a configured seed when it is non-zero.

  • dom is dom2(x, ctx) for ed25519 and dom4(x, ctx) for ed448, as defined in cite:[RFC8032] §5.1 and §5.2, with x = 0 in pure mode and 1 in pre-hash mode. For ed25519 in pure mode with an empty context, dom is the empty string.

Pure and pre-hash modes

In pure mode the unit hashes the message itself; in pre-hash mode the caller supplies PH(M), 64 bytes for both curves, in the Hash field. Which modes an implementation offers depends on the hash extensions it provides:

Curve extension Also implements Modes available

Zkled25519c

 — 

Ed25519ph only

Zkled25519c

Zklesha2h

Ed25519, Ed25519ctx and Ed25519ph

Zkled448c

 — 

Ed448ph only

Zkled448c

Zklesha3h

Ed448 and Ed448ph

The curve extension alone must provide enough of H to hash the fixed-size inputs above, which are a few hundred bytes at most. Absorbing a message of arbitrary length requires the general hashing machinery, and so requires Zklesha2h or Zklesha3h, respectively.

The AuxInfo field of the MDH (MachineUse and AuxInfo Fields) is used as follows: bit 0 records the modes that a CC may use: pre-hash mode only if it is 0, and pure mode as well if it is 1; bits [2:1] hold msg_pass (see the State Machine below); bits [7:3] are reserved; and bits [15:8] hold block_base (Elliptic Curve Cryptography). At provisioning and at import, two cases are unsupported Metadata and raise a KLE unsupported-Metadata exception (Validity of Metadata): bit 0 = 1 on an implementation that does not offer pure mode for the curve, and a non-zero reserved bit. This allows an M-mode handler to emulate pure mode where the hardware does not offer it (Error Handling Architecture); a handler that cannot resolve the exception, including for a reserved value, transitions the locker to Error State Unsupported. Provisioning keeps bit 0 of the PI, and a transition to Ready leaves it unchanged. Provisioning ignores and zeroes bits [2:1] of the PI, and entering State Ready zeroes them.

Data Structures

In addition to the fields of Elliptic Curve Cryptography:

  • ctx: 255 bytes, and ctxlen: 8 bits, the context string of cite:[RFC8032]. It is optional for ed25519 and mandatory, though possibly empty, for ed448. Both are zero upon provisioning and upon entering State Ready, and are set in State Set_Ctx.

  • msg_pass: 2 bits, held in bits [2:1] of AuxInfo. In State Msg_Absorb it identifies the open pass: 0 for signing pass 1, 1 for signing pass 2, and 3 for the verification pass. In any other State it records the last completed pass: 0 for none (also once Sign_Generate has used the passes), 1 for signing pass 1, 2 for signing pass 2, and 3 for the verification pass.

  • k': b bits, bin(int(H(dom ‖ R ‖ A ‖ M)) mod L, b), the whole hash read as a little-endian integer and reduced modulo L, computed by signing pass 2 or by the verification pass, and zero otherwise; it is always below L. It is not secret: anyone holding R, A and M can compute it.

  • r: b bits, the secret scalar produced by the first signing pass, reduced modulo the group order L.

There is no stored pre-hash mode selector: the mode is inferred from the path taken, as described below.

RndNum is not used: the EdDSA nonce is deterministic by construction, being derived from prefix and the message. Its absence is deliberate; j = 0, so Position vi of Elliptic Curve Cryptography is always empty. Bit 3 of StateExtension, HasRndNum in the other ECC Machines, is instead HasHashState (Table 6): it is set on entering State Msg_Absorb and cleared on leaving it, so that it is set exactly while a pass is open, including across the same-State re-entry that ends one pass and opens the next. A StateExtension @ State with HasHashState set in a State other than Msg_Absorb, or clear in Msg_Absorb, is not supported by the Machine: an SCC that carries it is invalid Metadata (Validity of Metadata). It does not follow the pattern of Rule MR14, since it records no loaded field.

The clamped scalar s and the 32-byte or 57-byte prefix, respectively, are derived from the seed by hashing it with H, as cite:[RFC8032] §5.1.5 and §5.2.5 prescribe. An implementation may recompute them on each use or cache them in the ADS. The public key A is likewise derived from the seed, or cached in the ADS.

  • Serialized Content: the serialized content of Elliptic Curve Cryptography, with the following fields appended.

    Pos. Type Size (Bits) Field

    vii

    Private

    8

    ctxlen

    viii

    Private

    2040

    ctx

    ix

    Private

    b

    r

    x

    Private

    b

    k'

    xi

    Private

    hs

    The state of H, zero while no pass is open

    xii

    Private

    If MachinePolicy[0] = 1: hs, else: 0

    The state of H', zero except in signing pass 2

    xiii

    Private

    0 for ed25519, 112 for ed448

    Padding

hs is the length of the Serialized Content of the hash Machine of H, without a key or MDH and with cumul_len present: for ed25519 that of SHA-512 (SHA-2 Family Specific Rules), 1664 bits, and for ed448 that of SHAKE256 (SHA-3 Family Specific Rules), 1792 bits with its padding to a multiple of 128 bits. Positions xi and xii hold the state of H, resp. H', in that layout, with last_block_len and out_len zero. The state of H is always present, MachinePolicy being never 0 for EdDSA, and that of H' whenever MachinePolicy[0] is set, so that the length of Content1 depends only on MachinePolicy (Length of External Formats and KLF Capacity Usage of a Locker). A kl.rstrl or kl.rstrv that clears MachinePolicy[0] (kl.rstrl, kl.rstrh, and kl.rstrv) destroys the state of H', and leaves HasHashState unchanged.

r and k' are present unconditionally, and hold zero whenever no signing operation, resp. no signing or verification operation, is in progress.

The state of an open pass is architected: msg_pass identifies the pass, and Content1 carries r, k' and the hash states, so that an export and import, also to a different implementation, resumes the pass where it stopped. Making the presence of r and k' conditional on msg_pass would only complicate the Machine; r, 256 bits for ed25519 and 456 for ed448, adds little to an SCC of this size, and stays confidential in the encrypted part of Content1.
State Machine
  • States: those of Elliptic Curve Cryptography, and in addition

    • Msg_Absorb (11), in which message data is absorbed.

    • Set_Ctx (12), in which the context string is set.

  • Allowed State Transitions: those of Elliptic Curve Cryptography, with the following changes:

    • Set_Ctx is a Set state: the transitions of Elliptic Curve Cryptography into and out of the Set states apply to it.

    • Msg_Absorb:

      • is entered, by the Form B kl.setst described below, from Ready, any Set state, Set_Ctx included, or Msg_Absorb itself; the Machine allows this same-State kl.setst (Rule GR19.2), which marks a pass boundary;

      • is left only for Msg_Absorb, Sign_Generate, Sign_Verify, Ready or an Error State; a kl.setst naming any other State transitions the locker to Error State Invalid.

    • If, in Msg_Absorb, a kl.rstrl or kl.rstrv (kl.rstrl, kl.rstrh, and kl.rstrv) clears MachinePolicy[0] during signing pass 1 or 2, or MachinePolicy[1] during the verification pass (Rule GR20):

      • a kl.setst that ends a signing pass is admitted only if it names Ready, which abandons the pass; otherwise Rule MR1 applies.

    • MachinePolicy = 0 is invalid for EdDSA (Validity of Metadata), at provisioning and as the result of a kl.rstr*.

    • These entry conditions (Rule MR1) replace those of Elliptic Curve Cryptography, in addition to the gating by MachinePolicy:

      • Point_Mul: Scalar holds a configured seed.

      • Sign_Generate: Scalar holds a configured seed, and either msg_pass = 2 (pure mode) or msg_pass = 0 and HasHash (pre-hash mode).

      • Sign_Verify: HasSecondPt and HasSignature, and either msg_pass = 3 (pure mode) or msg_pass = 0 and HasHash (pre-hash mode).

  • Behavior:

    • In State Point_Mul, the Behavior of Elliptic Curve Cryptography applies, except that the multiplier is the secret scalar s derived from the seed (cite:[RFC8032] §5.1.5, resp. §5.2.5, steps 1 to 3): SecondPt ← [s]P.

    • Signature generation and verification use the base point B of cite:[RFC8032] §5.1, resp. §5.2, whatever Generator holds:

      1. R ← [r]B;

      2. the public key A derived from the seed is [s]B;

      3. verification checks its equation over B;

      4. the validity check of Generator (Elliptic Curve Cryptography) applies only to Point_Mul.

    • In pure mode, signature generation takes two passes over the message, and verification one (Msg_Absorb below); for these passes:

      1. entering Ready clears msg_pass, r and k';

      2. r, k' and Signature, which the passes compute, are not material of Sign_Generate or Sign_Verify under Rule GR38: a restarted operation uses them as held.

    • Entering Set_Ctx:

      1. A Form B kl.setst is used, whose Xs sets ctxlen; a value greater than 255 transitions the locker to Error State Invalid.

      2. If ctxlen ≠ 0, Form B kl.exec instructions then load the ctxlen bytes of ctx, whose other bytes stay zero, following Rule MR14 as the Set states of Elliptic Curve Cryptography do, with the progress recorded in block_base; a load left incomplete zeroes ctx and ctxlen (Rule MR14).

    • Entering Msg_Absorb (pure mode only) is done by a Form B kl.setst whose Xs selects the pass:

      1. The kl.setst requires bit 0 of AuxInfo to be 1 (Rule MR1).

      2. Xs is not the max_len of Macro: Processing Variable Length Inputs into a Fixed Length Output, which is 0.

      3. Each pass has its own entry conditions (Rule MR1) and entry operations:

        1. Xs = 0, signing pass 1:

          1. requires that signature generation be allowed and that Scalar hold a configured seed;

          2. sets msg_pass ← 0 and k' ← 0;

          3. initializes H with dom ‖ prefix.

        2. Xs = 1, signing pass 2:

          1. requires msg_pass = 1;

          2. initializes H with dom ‖ R ‖ A, with R from Signature and A derived from the seed;

          3. initializes a second instance H' with dom ‖ prefix, as in pass 1; H' absorbs the same message bytes and recomputes r, which finalization compares with the r of pass 1.

        3. Xs = 2, verification pass:

          1. requires that signature verification be allowed and that HasSignature and HasSecondPt hold;

          2. sets msg_pass ← 3 and k' ← 0;

          3. initializes H with dom ‖ R ‖ A, with R from Signature and A = SecondPt.

        4. Any other value of Xs transitions the locker to Error State Invalid.

      Initializing H, or H', with a string x sets that instance as entering Ready of the hash Machine of H does (SHA-2 Family Specific Rules for ed25519, SHA-3 Family Specific Rules for ed448), with all its counters zero, last_block_len and out_len included, and then absorbs x as a kl.exec in Hash_Absorb of that Machine would, counting it in the cumul_len of that instance. At pass finalization, the finalize() of SHA-2 Family Specific Rules encodes for SHA-512 the length of the whole input of the instance, as cite:[nist-fips-180-4] §5.1.2 requires.

    • In State Msg_Absorb, Form B kl.exec instructions absorb message bytes into H, and in signing pass 2 also into H':

      1. Each kl.exec invokes macro PROCESS_VLI (Macro: Processing Variable Length Inputs into a Fixed Length Output) as
            PROCESS_VLI(max_len=0, H.block, H.b, H.state, H.n, input_base, H.block_base, 0, H.cumul_len, H.process_block(), None, mode, granularity=8).

      2. In signing pass 2, it also invokes it with H' in place of H; the two invocations share input_base and run in lock step:

        1. each byte is absorbed into H and into H' before the next one;

        2. step 3.i of Macro: Processing Variable Length Inputs into a Fixed Length Output, the interruption point, applies only to the invocation for H.

      3. In each invocation:

        • H.block, H.b, H.state, H.n, H.block_base and H.cumul_len are the buffer, block size, state, state size, and partial-block and cumulative-length counters, in bits, of the hash instance H, and likewise for H'; for SHAKE256, H.block is H.state (SHA-3 Family Specific Rules);

        • H.block_base is distinct from the byte counter block_base of Elliptic Curve Cryptography, which Msg_Absorb does not use;

        • H.process_block() applies the compression function, resp. the permutation, of H;

        • H.cumul_len is tracked, since the unit appends the padding, and for SHA-512 the length, at pass finalization;

        • mode is assign for ed25519, whose H is SHA-512 (SHA-2 Family Specific Rules), and xor_accumulate for ed448, whose H is SHAKE256.

      The interruption points of Msg_Absorb are those of the invocation for H (Macro: Processing Variable Length Inputs into a Fixed Length Output): 0 and, if H.block_base is 0 when the instruction is issued, every byte offset. In signing pass 2, H' may then hold a partial block, which is architected (Position xii).

    • Leaving Msg_Absorb for Msg_Absorb (the same-State re-entry above), Sign_Generate or Sign_Verify finalizes the current pass:

      1. after pass Xs = 0:

        1. r ← bin(int(H(dom ‖ prefix ‖ M)) mod L, b),

        2. Signature.R ← [r]B, and Signature.S ← 0,

        3. msg_pass ← 1, and

        4. HasSignature is cleared: Signature.R holds an intermediate value, and a signature loaded before is discarded; being part of the signature, R is public (Rule GR9), and reveals neither r nor the key;

      2. after pass Xs = 1:

        1. if int(H'(dom ‖ prefix ‖ M)) mod L ≠ int(r), the locker transitions to Error State Invalid;

        2. otherwise k' ← bin(int(H(dom ‖ R ‖ A ‖ M)) mod L, b) and msg_pass ← 2;

      3. after pass Xs = 2: k' as above, and msg_pass remains 3.

      Leaving it for Ready abandons the pass without finalizing it: no hash is completed and no binding check is made. A kl.setst that enters or leaves Msg_Absorb is long-running; whether it is resumable is implementation-defined (Rule GR36).

    • In State Sign_Generate, a single Form D kl.exec completes the signature per cite:[RFC8032] §5.1.6, resp. §5.2.6:

      1. In pure mode (msg_pass = 2):

        1. R is Signature.R, which signing pass 1 set;

        2. S ← (r + k' × s) mod L.

      2. In pre-hash mode (msg_pass = 0), with Hash holding PH(M):

        1. r ← int(H(dom ‖ prefix ‖ Hash)) mod L;

        2. R ← [r]B;

        3. k' ← int(H(dom ‖ R ‖ A ‖ Hash)) mod L;

        4. S ← (r + k' × s) mod L;

        5. these r, R and k' are intermediate results of the operation (Rule GR37): the fields r and k' stay zero.

      3. In both modes:

        1. Signature ← (R, S), and HasSignature is set;

        2. r and k' are destroyed, and msg_pass ← 0;

        3. OutputType ← signature, and the locker transitions to Output.

    • In State Sign_Verify, a single Form D kl.exec verifies Signature per cite:[RFC8032] §5.1.7, resp. §5.2.7:

      1. in pure mode if msg_pass = 3, with the k' of the verification pass; in pre-hash mode if msg_pass = 0, with k' computed internally, Hash (holding PH(M)) standing in for the message;

      2. the checks of step 1 of those sections are performed: S < L, and R and A decode; A need not lie in the subgroup of order L;

      3. the equation checked is the cofactored one, [2c][S]B = [2c]R + [2c][k']A, with c = 3 for ed25519 and 2 for ed448 (cite:[nist-fips-186-5] §7.7, step 3, and, in pre-hash mode, §7.8.2, step 4);

      4. if a check fails, or the equation does not hold, the locker transitions to Failure, else to Success; in either case k' is zeroed.

  • Pass 2 recomputes r from its own message and invalidates the locker on a mismatch: two signatures sharing R over different messages reveal the private scalar s.

  • Since Msg_Absorb is never left for a Set state, Scalar, ctx, Signature and SecondPt stay fixed between the passes, and between the verification pass and Sign_Verify. This prevents two attacks:

    • a different R with the same r: two signatures with the same r and different k' reveal s;

    • a Signature substituted after the verification pass, to forge against the k' already computed.

  • The verification pass records 3, open or completed:

    • while open, 3 tells it from signing pass 1, so that the finalization, also after an export and import, is that of the open pass;

    • once completed, 3 differs from the 2 of signing pass 2; otherwise Sign_Generate would compute S from the public k' of the verification pass and the zero r that entering Ready leaves, and reveal s.

  • A completed signing pass 1 records 1, so that neither Sign_Generate nor Sign_Verify uses a k' never computed.

  • In pre-hash mode msg_pass plays no role: PH(M) in the Hash field feeds both hashes.

Post-Quantum Public-Key Cryptography

ML-KEM

NIST announced the Module-Lattice-Based Key-Encapsulation Mechanism Standard in August 2024 cite:[nist-fips-203]. The standard defines several procedures, including:

  • ML-KEM.KeyGen: Generates an encapsulation key encapsk and a corresponding decapsulation key decapsk.

  • ML-KEM.Encaps: Uses the encapsulation key encapsk to generate a shared secret key sharedkey and an associated ciphertext.

  • ML-KEM.Decaps: Uses the decapsulation key decapsk to produce a shared secret key sharedkey from a ciphertext.

ML-KEM comes in three versions, ML-KEM-512, ML-KEM-768, and ML-KEM-1024, with increasing cryptographic strength. They require RBGs of security strength at least 128, 192, and 256 bits, respectively (cite:[nist-fips-203]). The sizes of keys and ciphertexts of the three subtypes of ML-KEM are summarized in Table 8.

Table 8. Sizes (in bytes) of keys and ciphertexts of ML-KEM
Subtype encapsk decapsk ciphertext sharedkey

ML-KEM-512

800

1632

768

32

ML-KEM-768

1184

2400

1088

32

ML-KEM-1024

1568

3168

1568

32

The granularity of the ML-KEM Machines is 8 bits: a field can be transferred with any SEW from 8 to 64 bits that divides its size, or through the KLIOBUF in any number of bytes.

In State sharedkey_Output, one kl.derive (kl.derive) moves the sharedkey that Encapsulate or Decapsulate produced into a second, already provisioned locker. The destination is a key field of a symmetric Machine, or the kl.exec input of a hash function, MAC or XOF, that Derivation Endpoints of the Machines lists as a destination (Rule GR31.1). With MachineExtension = 1, the sealed variant, sharedkey is moreover a sealed source (Rule GR31.3); the variant is unsupported Metadata where not implemented (Validity of Metadata).

Data Structures
  • The Provisioning Input contains only the MDH.

  • MachinePolicy is not used and must be zero; a non-zero value is unsupported Metadata (Validity of Metadata). No State is gated by it (Rule MR1), and a kl.rstrl or kl.rstrv leaves it zero (kl.rstrl, kl.rstrh, and kl.rstrv).

  • Internal State:

    • decapsk: 13056 / 19200 / 25344 bits (1632 / 2400 / 3168 bytes), the string dk_PKE ‖ ek ‖ H(ek) ‖ z of cite:[nist-fips-203] Algorithm 16, where dk_PKE has 384·k bytes, ek has 384·k + 32 bytes, and H(ek) and z have 32 bytes each (k = 2, 3, 4).

    • encapsk: 6400 / 9472 / 12544 bits (800 / 1184 / 1568 bytes). It is not stored separately: it is the ek sub-field of decapsk, at byte offset 384·k (768 / 1152 / 1536). When only an encapsulation key is held, the other bytes of decapsk are zero.

    • HasEncapsk, HasDecapsk: Booleans, recording whether encapsk, resp. a complete decapsk, holds a configured value. They are bits 0 and 1 of StateExtension, resp., and follow the pattern of Rule MR14, with the departures stated below.

    • HasCiphertext: Boolean, bit 2 of StateExtension, recording whether ciphertext holds a complete value, loaded and checked, or computed by Encapsulate. It follows the pattern of Rule MR14.

    • HasSharedKey: Boolean, bit 3 of StateExtension, recording whether sharedkey holds the key that Encapsulate or Decapsulate produced, whatever its value, zero included. It is set when that operation completes, and cleared whenever sharedkey is zeroed. A StateExtension @ State with sharedkey_Output and HasSharedKey clear is not supported by the Machine: an SCC that carries it is invalid Metadata (Validity of Metadata).

    • ciphertext: 6144 / 8704 / 12544 bits (768 / 1088 / 1568 bytes).

    • sharedkey: 256 bits.

    encapsk, decapsk, resp. sharedkey correspond to ek, dk, resp. K in cite:[nist-fips-203].

    In the States that load a long field (encapsk_Input, decapsk_Input and ciphertext_Input) or emit one (encapsk_Output and ciphertext_Output), MachineUse records the number of bytes transferred so far. It is the transfer counter W of Rule MR14, which the ECC Machines keep in block_base instead (Elliptic Curve Cryptography).

  • Serialized Content:

    Pos. Type Size (Bits)
    for ML-KEM-512/768/1024
    Field

    i

    Public

    6400 / 9472 / 12544

    The ek sub-field of decapsk, that is encapsk.

    ii

    Public

    256

    The H(ek) sub-field of decapsk.

    iii

    Public

    6144 / 8704 / 12544

    ciphertext

    iii.a

    Public

    0 / 0 / 0

    Padding

    iv

    Private

    6144 / 9216 / 12288

    The dk_PKE sub-field of decapsk.

    iv.a

    Private

    0 / 0 / 0

    Padding

    v

    Private

    256

    The z sub-field of decapsk.

    vi

    Private

    256

    sharedkey

    vi.a

    Private

    0 / 0 / 0

    Padding

    Positions i to iii.a are the public fields and their padding (Rule GR9), and SCC_ClearLen1 is 100, 144 and 198 for ML-KEM-512, ML-KEM-768 and ML-KEM-1024. With only encapsk held, Positions ii, iv and v are zero. The ek and H(ek) sub-fields hold only a value loaded or computed for them, a partial load included, or zero, and ciphertext only a ciphertext loaded or computed by Encapsulate: Decapsulate never writes the re-encryption of cite:[nist-fips-203] Algorithm 18 into a field.

    These contexts are large: for ML-KEM-512, ML-KEM-768 and ML-KEM-1024 the serialized content is 2432, 3520 and 4768 bytes, that is 152, 220 and 298 blocks of 128 bits; encapsk takes no space of its own, since it is held in the ek sub-field of decapsk, which the Serialized Content splits into its sub-fields.

Machine-Specific Functions

The procedures implemented by ML-KEM are taken directly from cite:[nist-fips-203]:

  • ML-KEM.KeyGen() (cite:[nist-fips-203] Algorithm 19) draws the random seeds d, z and computes the encapsulation key encapsk and the decapsulation key decapsk as (encapsk, decapsk) = ML-KEM.KeyGen_internal(d, z) (Algorithm 16).

  • ML-KEM.Encaps(encapsk) (cite:[nist-fips-203] Algorithm 20) draws the randomness m and computes the shared key sharedkey and the ciphertext ciphertext as (sharedkey, ciphertext) = ML-KEM.Encaps_internal(encapsk, m) (Algorithm 17).

  • ML-KEM.Decaps(decapsk, ciphertext) computes the shared key sharedkey from the decapsulation key decapsk and the ciphertext ciphertext (cite:[nist-fips-203] Algorithm 21).

The loop of SampleNTT (cite:[nist-fips-203] Algorithm 7) iterates an indeterminate number of times (cite:[nist-fips-203] Appendix B). An implementation bounds it by an implementation-defined limit of at least 280 iterations (cite:[nist-fips-203] Appendix B, Table 4), which a correct execution reaches with a probability of at most 2-261. As in cite:[nist-fips-203], the execution time need not be independent of the number of iterations (SCProtection Field). When the limit is reached, the operation ends without output: it destroys its intermediate values and any value drawn for it, and zeroes MachineUse. The state machine then transitions to Failure.

cite:[nist-fips-203] Appendix B recommends not bounding the loop; KLE requires a bound, as for ML-DSA, so that every operation ends in bounded time.
State Machine
  • States: Besides Ready (1) and Failure (55), ML-KEM Machines define the following States:

    • GenerateKeyPair (2)

    • Encapsulate (3)

    • Decapsulate (4)

    • encapsk_Input (5)

    • decapsk_Input (6)

    • encapsk_Output (7)

    • ciphertext_Input (8)

    • ciphertext_Output (9)

    • sharedkey_Output (10)

  • Allowed State Transitions:

    • By kl.setst, under the entry conditions given below:

      1. from Ready or any other State listed above except Failure, to another of Ready, GenerateKeyPair, Encapsulate, Decapsulate, encapsk_Input, decapsk_Input, ciphertext_Input, encapsk_Output or ciphertext_Output;

      2. from Failure, only as Rule GR19.3 allows;

      3. in encapsk_Input, decapsk_Input and ciphertext_Input, to the same State, which restarts the load (Rule GR19.2).

    • On completion of its kl.exec: GenerateKeyPair → encapsk_Output; Encapsulate → ciphertext_Output; Decapsulate → sharedkey_Output.

    • When a SampleNTT limit is reached (see above): GenerateKeyPair, Encapsulate or Decapsulate → Failure.

    • Once its field has been completely emitted: encapsk_Output → Ready; ciphertext_Output → sharedkey_Output if HasSharedKey is set, as after Encapsulate, and → Ready otherwise.

    • On the first committed unit of a kl.derive of sharedkey: sharedkey_Output → Ready.

    • Once its field has been completely loaded: ciphertext_Input → Ready, or → Failure if the ciphertext type check fails; encapsk_Input → Failure if the encapsulation key check fails.

    • When an import restores an encapsk that HasEncapsk marks and that fails the encapsulation key check: → Failure.

    • sharedkey_Output is entered only by these transitions (Rule MR18).

    • ML-KEM Machines never enter Success.

  • Behavior:

    • Provisioning:

      1. clears decapsk (and with it encapsk), ciphertext and sharedkey;

      2. clears HasEncapsk, HasDecapsk, HasCiphertext and HasSharedKey;

      3. zeroes MachineUse.

    • Entering Ready:

      1. zeroes sharedkey and MachineUse;

      2. keeps decapsk (and with it encapsk), ciphertext, HasEncapsk, HasDecapsk and HasCiphertext.

    • Leaving:

      1. sharedkey_Output zeroes sharedkey;

      2. ciphertext_Output for a State other than sharedkey_Output also zeroes sharedkey.

    • Entering:

      1. encapsk_Input zeroes the whole decapsk field and clears HasEncapsk and HasDecapsk; the load writes the encapsk sub-field, so that the locker then holds an encapsulation key only;

      2. decapsk_Input zeroes the whole decapsk field, with its encapsk sub-field, and clears HasEncapsk and HasDecapsk;

      3. ciphertext_Input zeroes ciphertext and sharedkey, and clears HasCiphertext;

      4. Encapsulate or Decapsulate zeroes sharedkey.

    • No kl.setst of this Machine takes an auxiliary parameter.

    • The input checks of cite:[nist-fips-203] §7.2 and §7.3 are performed when a field is written (Rule MR3):

      1. a field is written when its load completes, and when an import restores a key that HasEncapsk or HasDecapsk marks as configured;

      2. a system-specific import (Rule GR51) checks a converted decapsk, encapsk or ciphertext as a completed load of that field does, with the same outcomes, and sets HasEncapsk, HasDecapsk and HasCiphertext as that load sets them (Rule MR4);

      3. a kl.setst that leaves encapsk_Input, decapsk_Input or ciphertext_Input before the field is complete zeroes the field (the whole decapsk for decapsk_Input; Rule MR14): HasEncapsk and HasDecapsk, resp. HasCiphertext, stay clear;

      4. departing from Rule MR14, excess data in the final loading transfer of encapsk, decapsk or ciphertext fails the type check;

      5. the checks and their outcomes are, for each field:

        1. encapsk: the encapsulation key check of cite:[nist-fips-203] §7.2:

          1. it is the type check (encapsk has the length required by the parameter set) and the modulus check (encapsk re-encodes to itself, that is, every coefficient is reduced modulo q);

          2. a failure is a data error (Rule MR2) when the encapsk was loaded in encapsk_Input, or imported with HasEncapsk set: the whole decapsk field is zeroed, HasEncapsk and HasDecapsk are cleared, and the state machine transitions to Failure.

        2. decapsk: the decapsulation key check of cite:[nist-fips-203] §7.3:

          1. it is the type check and the hash check (the copy of H(encapsk) embedded in decapsk matches the embedded encapsk);

          2. a failure is a configuration error: the locker transitions to Error State Invalid;

          3. when the load completes, the encapsulation key check is also performed on the embedded encapsk;

          4. a completed load that passes the decapsulation key check sets HasDecapsk, and also HasEncapsk if the embedded encapsk passes the encapsulation key check; a failure of that check only leaves HasEncapsk clear.

        3. ciphertext: when the load completes, the ciphertext type check of cite:[nist-fips-203] §7.3:

          1. a ciphertext loaded without excess data passes it: HasCiphertext is set, and the state machine transitions to Ready;

          2. a failure is a data error: ciphertext is zeroed, HasCiphertext stays clear, and the state machine transitions to Failure.

      These checks do not affect the implicit rejection of ML-KEM.Decaps: a ciphertext that passes the type check but does not decapsulate correctly still yields the z-derived shared key, and the state machine still transitions to sharedkey_Output.
    • In States GenerateKeyPair, Encapsulate and Decapsulate the operation is long-running:

      1. MachineUse is the field P of Rule GR38, and, when it is non-zero, the interrupted operation is resumed or restarted as per that Rule;

      2. its random values and intermediate values are kept in the ADS (Rule GR37);

      3. on completion, the operation destroys the values drawn for it and its intermediate values, except those that its result holds, such as z in decapsk;

      4. values computed from encapsk or decapsk alone, in any representation, masked shares included, may be kept in the ADS until that field is replaced or erased (AuxDataLen and ADSDropped Fields); KLE treats them as a representation of that key and protects them as the key itself, although cite:[nist-fips-203] §3.3 names only the seed and the matrix  as values that may be kept.

    • In State GenerateKeyPair, a Form D kl.exec generates a new key pair with ML-KEM.KeyGen of cite:[nist-fips-203] (Algorithm 19):

      1. besides a SampleNTT limit (see above), only the RBG can make it fail: Rule GR45 applies if the RBG fails;

      2. otherwise decapsk (and with it encapsk) receives the new key pair, HasEncapsk and HasDecapsk are set, and the state machine transitions to encapsk_Output, to emit the public key;

      3. leaving encapsk_Output keeps the key pair, whatever State follows; entering encapsk_Input or decapsk_Input discards it (see above).

    • Entering Encapsulate requires HasEncapsk (Rule MR1). In it, a Form D kl.exec applies ML-KEM.Encaps of cite:[nist-fips-203] (Algorithm 20) to encapsk:

      1. it draws one random value, from which it derives both the shared key and the ciphertext;

      2. besides a SampleNTT limit, only the RBG can make it fail: Rule GR45 applies if the RBG fails;

      3. otherwise it stores the two values in sharedkey and ciphertext, HasSharedKey and HasCiphertext are set, and the state machine transitions to ciphertext_Output.

    • Entering Decapsulate requires HasDecapsk and HasCiphertext (Rule MR1). In it, a Form D kl.exec applies ML-KEM.Decaps of cite:[nist-fips-203] (Algorithm 21):

      1. it runs for any ciphertext, and fails only on a SampleNTT limit;

      2. it places in sharedkey the shared key derived from the ciphertext or, by implicit rejection, the one derived from z, sets HasSharedKey, and the state machine transitions to sharedkey_Output;

      3. nothing but the value of sharedkey may depend on which of the two keys it placed:

        1. not the execution time;

        2. not any field of the locker, MachineUse included;

        3. not the AuxDataLen of an SCC exported while the operation is under way;

      4. the SCProtection level of the locker (SCProtection Field) governs the other physical leakage of the operation.

        A side channel of the decryption or of the re-encryption within Decapsulate, such as one that shows whether the decrypted message equals a value the caller chose, is a plaintext-checking oracle. With a few thousand chosen ciphertexts, it lets a caller recover dk_PKE, and with it the use of decapsk. The SCProtection level of the locker sets how far Decapsulate resists it. The value of sharedkey itself, which a caller can test through kl.derive, is no such oracle: cite:[nist-fips-203] ML-KEM.Decaps returns it to its caller, and ML-KEM is IND-CCA2 secure under that interface.
    • In States encapsk_Input, decapsk_Input and ciphertext_Input, Form B kl.exec instructions load encapsk, decapsk and ciphertext:

      1. following Rule MR14, with the progress recorded in MachineUse;

      2. the parameter set and the State fix the size of each field (Table 8).

    • In States encapsk_Output and ciphertext_Output:

      1. Form C kl.exec instructions emit encapsk and ciphertext, following Rule MR14, with the progress recorded in MachineUse;

      2. entering encapsk_Output requires HasEncapsk, and entering ciphertext_Output requires HasCiphertext (Rule MR1).

    • No kl.exec emits sharedkey:

      1. besides the instructions that move or copy the whole CC, an export and import, kl.clone, kl.rename and kl.swap, only kl.derive (kl.derive) moves it, as a field source (Rule GR31.1), and only in State sharedkey_Output (Derivation Endpoints of the Machines);

      2. that State admits no kl.exec, and one kl.derive, which transitions the locker to Ready (Rule GR28);

      3. the kl.derive reads the field from its first byte: a key field receives its first eff_length bytes, and a message input the whole field, with length = 32 (Rules GR28, GR29 item 6 and GR31.1).

ML-DSA

NIST announced the Module-Lattice-Based Digital Signature Standard in August 2024 cite:[nist-fips-204]; it has three variants: ML-DSA-44, ML-DSA-65, and ML-DSA-87.

Table 9. Sizes (in bytes) of keys and signatures of ML-DSA
Subtype Private Key Public Key Signature Size

ML-DSA-44

2560

1312

2420

ML-DSA-65

4032

1952

3309

ML-DSA-87

4896

2592

4627

They require RBGs of security strength at least 128 (192 recommended), 192, and 256 bits, respectively, for xi (cite:[nist-fips-204] §3.6.1); an ML-DSA-44 CC with a 128-bit RBG has security category 1.

The granularity of the ML-DSA Machines is 8 bits: a field can be transferred with any SEW from 8 to 64 bits that divides its size, or through the KLIOBUF in any number of bytes.

The principal functions offered by ML-DSA are:

  • ML-DSA.KeyGen: Generates a public-private key pair.

  • ML-DSA.Sign: Generates a digital signature for a given message.

  • ML-DSA.Verify: Verifies a digital signature for a given message.

  • HashML-DSA.Sign: Generates a digital signature for a given pre-hashed message.

  • HashML-DSA.Verify: Verifies a digital signature for a given pre-hashed message.

The KLE ML-DSA Machines execute the core lattice operations of signing and verification, specifically ML-DSA.Sign_internal and ML-DSA.Verify_internal as defined in cite:[nist-fips-204] (Algorithms 7 and 8), with an external message representative μ: the caller supplies μ in State mu_Input, and the steps of these algorithms that compute μ from tr and the formatted message M' are not performed. Consequently the Machine never receives the message or the context string ctx, and holds tr only within privkey.

Message hashing and domain formatting (cite:[nist-fips-204] §5) are structured as follows, with ctx a context string of at most 255 bytes, chosen by the protocol, |ctx| its length in bytes, and OID(PH) the DER encoding of the object identifier of PH (cite:[nist-fips-204] §5.4):

  • Pure ML-DSA: The caller formats the domain-separated message string M' = 0x00 ‖ bin(|ctx|, 8) ‖ ctx ‖ M and computes the 64-byte message representative mu = SHAKE256(tr ‖ M', 64), which is supplied to the KLE unit via State mu_Input.

  • HashML-DSA (Pre-Hash): The caller pre-hashes message M with the hash function PH specified in the AuxInfo field of the MDH, constructs M' = 0x01 ‖ bin(|ctx|, 8) ‖ ctx ‖ OID(PH) ‖ PH(M), and computes mu = SHAKE256(tr ‖ M', 64) to be loaded into State mu_Input. For FIPS conformance, cite:[nist-fips-204] (§5.4 and §5.4.1) requires PH(M) to be computed within a FIPS 140-validated cryptographic module. That module may be the KLE unit itself, if the unit is FIPS 140-validated.

  • Public Key Hash (tr): tr = SHAKE256(pubkey, 64). It is embedded in privkey (cite:[nist-fips-204] Algorithm 24), where ML-DSA.KeyGen places it; the caller computes it from the public key.

The caller’s duties in forming μ. The message representative μ and the string M' are formed as stated above, following cite:[nist-fips-204] §5.2 to 5.4 and Algorithms 2 to 5, 7 and 8, with PH the function that AuxInfo records. The caller is expected to:

  1. obtain the public key pk of the CC: the key it loaded in State pubkey_Input or, for a CC that holds a private key, the key emitted in State pubkey_Output after GenerateKeyPair or compute_pubKey, or a copy of it from an authenticated source, such as a certificate;

  2. compute tr from pk once, and keep it with the CC;

  3. for each message, choose the mode that AuxInfo selects (pure if AuxInfo = 0), form M' with the context string that the protocol prescribes, compute μ, and load it in State mu_Input, before entering Sign_Generate or Sign_Verify;

  4. use, when verifying, the same ctx and mode as the signer; and

  5. compute PH(M) for HashML-DSA within a cryptographic module of the required validation level (see above).

The Machine cannot check these steps: a μ formed with a wrong tr, ctx or mode yields a signature that the verifier rejects, but it never discloses or weakens the private key.

Data Structures
  • The Provisioning Input consists only of the MDH.

  • MachinePolicy[0] gates signature generation and MachinePolicy[1] signature verification, with their Gated States (Rule MR1).

  • The AuxInfo field is zero for pure ML-DSA. For HashML-DSA it records the pre-hash function PH, in the format of bits [15:0] of the MDH (Machine, MachinePolicy and MachineExtension), which the caller chooses among the hash functions and XOFs that cite:[nist-fips-204] §5.4 admits for the parameter set. The Machine never reads AuxInfo: it neither computes PH nor checks or enforces its use. It keeps the field unchanged, also through provisioning and transitions to Ready, so that the MDH, in the clear, informs the recipients of the CC, which need not implement PH. The caller always computes μ with SHAKE256, whatever PH is (cite:[nist-fips-204] Algorithm 7).

  • Internal State:

    • MachineUse, in the MDH, is the transfer counter W of Rule MR14, in bytes, in the States that load or emit a long field. In States GenerateKeyPair, compute_pubKey, Sign_Generate and Sign_Verify, it is the field P of Rule GR38 for their long-running operations, and encodes their progress in an implementation-defined way.

    • HasPrivKey, HasPubKey: Booleans, recording whether privkey, resp. pubkey, holds a configured value. They are bits 0 and 1 of StateExtension, resp., and follow the pattern of Rule MR14, with the departures stated below.

    • Hedged: Boolean, bit 2 of StateExtension, recording the signing mode selected on entering Sign_Generate.

    • HasMu: Boolean, bit 3 of StateExtension, recording that mu holds a completely loaded μ. It follows the pattern of Rule MR14.

    • privkey: 2560/4032/4896 bytes (20480/32256/39168 bits) for ML-DSA-44/65/87, resp.

    • pubkey: 1312/1952/2592 bytes (10496/15616/20736 bits) for ML-DSA-44/65/87, resp.

    • signature: 2420/3309/4627 bytes (19360/26472/37016 bits) for ML-DSA-44/65/87, resp.

    • mu: 64 bytes (512 bits), the external message representative μ

    • rnd: 32 bytes (256 bits), the random value of hedged signing; it is non-zero only while a hedged signing operation is interrupted (Rule GR38), and zero otherwise, including for deterministic signing.

  • Besides rnd, the internal state may contain several additional variables, for instance intermediate values of the computation of the NTT. Their definition and their size are implementation-dependent. An interrupted operation keeps them in the ADS, never in the Serialized Content (Rule GR37), so that it can resume on the same implementation; without them, it restarts (Rule GR38). When an operation completes, it destroys the values drawn for it, xi and rnd included, and its intermediate values; values computed from privkey or pubkey alone, in any representation, masked shares included, may be kept in the ADS until that field is replaced or erased (AuxDataLen and ADSDropped Fields); KLE treats them as a representation of that key and protects them as the key itself, although cite:[nist-fips-204] §3.6.3 names only the seed and the matrix  as values that may be kept.

  • Serialized Content:

    Pos. Type Size (Bits)
    for ML-DSA-44/65/87
    Field

    i

    Public

    10496 / 15616 / 20736

    pubkey

    ii

    Public

    19360 / 26472 / 37016

    signature

    ii.a

    Public

    96 / 24 / 104

    Padding

    iii

    Private

    20480 / 32256 / 39168

    privkey (contains tr)

    iii.a

    Private

    0 / 0 / 0

    Padding

    iv

    Private

    512

    mu

    v

    Private

    256

    rnd

    v.a

    Private

    0 / 0 / 0

    Padding

    Positions i to ii.a are the public fields and their padding (Rule GR9), and SCC_ClearLen1 is 234, 329 and 452 for ML-DSA-44, ML-DSA-65 and ML-DSA-87. pubkey holds only a public key loaded or computed, a partial load included, or zero, and signature only a signature loaded or completed, or zero: a rejected iteration of ML-DSA.Sign_internal writes no field.

    These contexts are large: for ML-DSA-44, ML-DSA-65 and ML-DSA-87 the serialized content is 6400, 9392 and 12224 bytes, that is 400, 587 and 764 blocks of 128 bits, padding included.

    Only HasPrivKey, HasPubKey, Hedged and HasMu, in StateExtension, record state: nothing records whether signature holds a value.

Machine-Specific Functions

The procedures implemented by ML-DSA are taken directly from cite:[nist-fips-204]:

  • ML-DSA.KeyGen() (cite:[nist-fips-204] Algorithm 1) draws the random seed xi and computes the public key pubkey and the private key privkey as (pubkey, privkey) = ML-DSA.KeyGen_internal(xi) (Algorithm 6).

  • ML-DSA.Sign_internal(privkey, mu, rnd) generates the digital signature signature from private key privkey, message representative mu, and randomness rnd (cite:[nist-fips-204] Algorithm 7).

  • ML-DSA.Verify_internal(pubkey, mu, signature) verifies the signature signature against public key pubkey and message representative mu (cite:[nist-fips-204] Algorithm 8).

The loops of ML-DSA.Sign_internal, RejBoundedPoly, RejNTTPoly and SampleInBall iterate an indeterminate number of times (cite:[nist-fips-204] Appendix C). An implementation bounds each by an implementation-defined limit of at least that of cite:[nist-fips-204] Table 3: 814 iterations of the loop of ML-DSA.Sign_internal; 481 iterations, or 481 bytes of XOF output, for RejBoundedPoly; 298 iterations, or 894 bytes of XOF output, for RejNTTPoly; and, for SampleInBall, 121 iterations of the while loop of its step 8 within one iteration of its for loop, or 221 bytes of XOF output for the whole call. A correct execution reaches these limits with probability of about 2-256 or less (cite:[nist-fips-204] Appendix C). As in cite:[nist-fips-204], the execution time need not be independent of the number of iterations (SCProtection Field). A limit reached ends the operation in Failure, without output: its intermediate values and the values drawn for it, xi and rnd included, are destroyed, and MachineUse is zeroed.

cite:[nist-fips-204] Appendix C recommends not bounding these loops; KLE requires the bound, so that every operation ends in bounded time, and the limits of Table 3 are reached by a correct execution with negligible probability.
State Machine

  • States: Besides Ready (1), Success (54), Failure (55), ML-DSA Machines define:

    • GenerateKeyPair (2)

    • pubkey_Output (3)

    • pubkey_Input (4)

    • mu_Input (6)

    • Sign_Generate (8)

    • Sign_Output (9)

    • Sign_Verify (10)

    • Sign_Input (11)

    • privkey_Input (12)

    • compute_pubKey (13)

  • Allowed State Transitions:

    • By kl.setst, subject to Rules GR19.3, GR19.2 and GR19.5 and to the entry conditions below: between any two different States listed above, and, in privkey_Input, pubkey_Input, mu_Input and Sign_Input, to the same State, which restarts the load. Sign_Output is entered only on completion of Sign_Generate (Rule MR18).

    • On completion of its kl.exec: GenerateKeyPair → pubkey_Output; compute_pubKey → Ready; Sign_Generate → Sign_Output; Sign_Verify → Success or Failure.

    • Once its field has been completely emitted: pubkey_Output → Success; Sign_Output → Success.

    • Once its field has been completely loaded, with excess data in the final transfer: pubkey_Input or Sign_Input → Failure.

    • When an implementation-defined loop limit is reached (see above): → Failure.

  • Behavior:

    • Provisioning:

      1. clears privkey and pubkey, and clears HasPrivKey and HasPubKey;

      2. zeroes MachineUse;

      3. leaves the locker in Ready.

    • Entering Ready:

      1. clears signature, mu, rnd and HasMu, and zeroes MachineUse;

      2. keeps privkey, pubkey, HasPrivKey and HasPubKey.

    • In State GenerateKeyPair, a Form D kl.exec generates a new key pair with ML-DSA.KeyGen of cite:[nist-fips-204] (Algorithm 1), from a seed xi drawn from the RBG (Rule GR45):

      1. the key pair replaces privkey (which embeds tr) and pubkey, and HasPrivKey and HasPubKey are set;

      2. the state machine transitions to pubkey_Output, with MachineUse zeroed; leaving it keeps the key pair.

    • Loading privkey, and system-specific imports:

      1. entering privkey_Input clears HasPrivKey and HasPubKey and erases pubkey;

      2. a system-specific import (Rule GR51) that converts a privkey checks it as a completed load does, with the same outcomes, and sets HasPrivKey;

      3. such an import drops any pubkey that the format carries: pubkey stays zero and HasPubKey clear, as entering privkey_Input leaves them, and compute_pubKey then derives pubkey;

      4. a system-specific import that converts a pubkey without a privkey sets HasPubKey, as a completed load does (Rule MR4).

    • Entering pubkey_Input:

      1. requires HasPrivKey to be clear (Rule MR1), and clears HasPubKey;

      2. when the load completes without excess data, HasPubKey is set.

    • In States privkey_Input, pubkey_Input, mu_Input and Sign_Input, Form B kl.exec instructions load privkey, pubkey, mu and signature, respectively, following Rule MR14, with the progress recorded in MachineUse, in bytes.

    • The checks of the loaded fields:

      1. a privkey with a coefficient of s1 or s2 outside [−η, η] (cite:[nist-fips-204] Algorithm 25) is a configuration error: the locker transitions to Error State Invalid when privkey is written, by a completed load or by an import with HasPrivKey set (Rule MR3);

      2. every pubkey of the correct length is well formed (cite:[nist-fips-204] Algorithm 23);

      3. departing from Rule MR14, excess data in the final loading transfer of pubkey or signature is a data error (cite:[nist-fips-204] §3.6.2): the field is zeroed, HasPubKey stays clear for a pubkey, and the state machine transitions to Failure (Rule MR2);

      4. a signature is not checked when it is loaded: as in cite:[nist-fips-204] Algorithm 8, ML-DSA.Verify_internal decodes it (Algorithm 27), and rejects a malformed signature, for which the decoding returns ⊥, as one that does not verify (Rule MR2).

    • Entering compute_pubKey requires HasPrivKey (Rule MR1). In it, a Form D kl.exec:

      1. derives pubkey from privkey: it decodes it with skDecode (cite:[nist-fips-204] Algorithm 25) and applies steps 3, 5, 6 and 8 of Algorithm 6;

      2. checks that the public key hashes to tr, embedded in privkey; if not, the locker transitions to Error State Invalid;

      3. writes the derived public key into pubkey and sets HasPubKey;

      4. transitions to Ready, which keeps the key pair.

    • When entering Sign_Generate, by a Form B kl.setst whose Xs selects the signing mode of cite:[nist-fips-204] §3.4:

      1. the State requires HasPrivKey and HasMu (Rule MR1);

      2. Xs = 0, for instance with Xs = X0, selects hedged signing and sets Hedged;

      3. any other Xs selects deterministic signing and clears Hedged;

      4. the kl.setst zeroes MachineUse, so that its progress is counted from entry and tracks the current operation, not the transfer that preceded it.

    • In State Sign_Generate, a Form D kl.exec signs with ML-DSA.Sign_internal of cite:[nist-fips-204] (Algorithm 7):

      1. the operation is long-running, and MachineUse is its field P (Rule GR38);

      2. MachineUse reveals at most the number of completed iterations of the signing loop; the challenge, the response and the failed check of a rejected iteration must not be observable, through MachineUse or otherwise;

      3. if MachineUse is zero, the operation starts, with rnd drawn from an approved RBG (Rule GR45) if Hedged is set, and rnd = zeros(256) otherwise;

      4. if MachineUse is non-zero, the interrupted operation is resumed with the rnd held, or restarted (Rule GR38);

      5. on completion, the output of ML-DSA.Sign_internal is written in signature, and the locker transitions to Sign_Output.

    • Entering Sign_Verify requires HasPubKey and HasMu (Rule MR1). In it, a Form D kl.exec verifies signature with ML-DSA.Verify_internal of cite:[nist-fips-204] (Algorithm 8):

      1. if it returns true, the state machine transitions to Success, otherwise to Failure;

      2. nothing is written to signature;

      3. departing from Rule MR14, Sign_Verify has no entry condition on signature; it verifies the value that signature holds:

        1. the signature last loaded in Sign_Input or computed by Sign_Generate since Ready was last entered;

        2. zero, if there is none or if the last load was left incomplete.

    • In pubkey_Output and Sign_Output:

      1. Form C kl.exec instructions emit pubkey, resp. signature, recording the progress in MachineUse, in bytes, and end in Success (Rule MR14);

      2. entering pubkey_Output requires HasPubKey (Rule MR1).

    • MachinePolicy may be narrowed using kl.rstrl or kl.rstrv (Rule GR20).

Derivation Endpoints of the Machines

Table 10 lists the architected kl.derive endpoints of the Machines of this Chapter.

Table 10. Derivation Endpoints of the Architected Machines
Machine(s) Field/Operation Role State

ECB mode, Chaining/feedback modes, Keystream generation, GCM mode, GCM-SIV mode, CMAC mode, OCB mode, Ascon-AEAD128

key

destination

Ready

XEX/XTS modes

key1 ‖ key2

destination

Ready

Ascon-AEAD128 with Nonce Masking

K1 ‖ K2, except of a shared secret that Rule GR31.1 restricts

destination

Ready

HMAC, NIK variant

K0

destination

Set_Key

Exactly these hash functions, MACs and XOFs: SHA-2, SM3, BLAKE2, SHA-3 and SHAKE, HMAC on SHA-2, SHA-3 and SM3, KMAC and KMACXOF, Ascon-Hash256, Ascon-XOF128 and Ascon-CXOF128

kl.exec input, of a shared secret only (Rule GR31.1)

destination

Hash_Absorb

Elliptic Curve

the shared secret as Output emits it, formed from SecondPt

source

Output with OutputType = shared secret and block_base = 0

ML-KEM

sharedkey

source

sharedkey_Output

Keystream generation, OFB

the keystream (Rule GR31.2)

source

Operate

CMAC, and the hash functions, MACs and XOFs listed above as destinations

the kl.exec output (Rule GR31.2)

source

Hash_Output, and Hash_Output_Bits where the Machine has it

A source and a destination form a pair only as Rules GR31.1–GR31.2 and GR31.3 admit. For now, the admissible pairs move:

  • an ML-KEM sharedkey, or the shared secret of an x25519 or x448 Machine (X25519- and X448-Specific Rules), into a listed key of a symmetric Machine; a restricted shared secret does not go into K1 ‖ K2 of nonce masking;

  • a shared secret of any ECC or ML-KEM Machine into the input of a listed hash function, HMAC, KMAC or XOF, as the input of a key-derivation method of cite:[NIST-SP-800-56Cr2]; for the other ECC Machines, whose shared secret is not a uniform string, this is the only destination, as cite:[NIST-SP-800-56Ar3] §5.8 requires for Z;

  • the keystream of a keystream Machine, or the output of a CMAC, hash function, MAC or XOF Machine, into a listed key of a symmetric Machine, as the key-derivation methods of cite:[NIST-SP-800-56Cr2] and cite:[nist-SP-800-108-r1] produce it;

  • a sealed source (Rule GR31.3) as above, but never into the key of keystream generation, OFB or CMAC, whose outputs are sources, nor into K1 ‖ K2; a hash, MAC or XOF input, or an HMAC K0, that receives it makes its locker sealed.

A destination key field still sets its own length conditions (Rule GR29 item 6): the K0 of HMAC takes only a source of exactly eff_length bytes, which a keystream or the output of an XOF without bound is not, so either one into K0 invalidates the destination alone. A locker of a Machine that Rule MR12 lists, whose tag_len_p is shorter than the full length, is not a destination. Every such kl.derive is uninterruptible (Rule GR32).