Notation and Conventions

This section is normative: every formula is read under these conventions, and no Machine description may introduce a different one.

Values, Bits, and Byte Strings

A value is a bit string whose length its context fixes. For an n-bit value V, V[i] is its i-th bit, bit 0 being the least significant, and V[j:i], with 0 ≤ i ≤ j < n, the slice from bit i to bit j, both inclusive.

A referenced standard may specify an input, output, key, state field, or constant as a byte string M = M0, M1, …, Mn-1, M0 being the first (leftmost, lowest-addressed) byte. This specification represents it by the 8n-bit value V with V[8i+7 : 8i] = Mi for 0 ≤ i < n, and by no other mapping. The mapping is little-endian, like RISC-V: for a KLE memory operation with effective address A, the byte at A + i is V[8i+7 : 8i]; a vector register (group) that supplies INPUT or receives OUTPUT holds what a unit-stride byte load (vle8.v) of that memory gives, and a unit-stride byte store (vse8.v) reproduces the memory. The mapping does not depend on SEW and VL, of which KLE uses only the product (Notation in the Machine Descriptions), and KLE memory instructions ignore the data endianness of the hart (Endianness).

Operators and Control Constructs

  • x ← y, also in listings (x ← y in inline code): assignment of y to x.

  • x = y, x ≠ y (x != y in listings), <, ≤, >, ≥: equality, inequality and the usual integer comparisons.

  • +, -, ×: integer addition, subtraction and multiplication; a / b: exact division, used only where b divides a, or inside ceil or floor as the real quotient; a mod b, for b > 0: the remainder of a divided by b, from 0 to b-1.

  • [k]P: the elliptic-curve point P added to itself k times by the group law of its curve.

  • V xor W, V and W, V or W: bitwise operations on values of equal length.

  • V << k, V >> k: logical shifts of V by k bits within its declared width, shifting in zeros; a left shift moves data toward the later bytes of the string.

  • A @ B, for values A of p bits and B of q bits: their concatenation, the (p+q)-bit value C with C[q-1:0] = B and C[p+q-1:q] = A; the left operand of @ occupies the more significant bits.

  • X ‖ Y, for byte strings or arrays of blocks: X followed by Y, X at the lower offsets or indices. This specification uses ‖ only in this little-endian sense, into which it transcribes a standard’s formula (Transcribing a Formula from a Standard); a standard’s own ‖ appears only in those examples and in Conventions of the Referenced Standards.

  • foreach(i from a to b) do: executes the indented body that follows for each integer i from a to b, both included, in increasing order, and not at all if a > b; foreach(i from a to b by s) steps i by s > 0.

  • if (c) then: performs the indented lines that follow only if c holds, and a following else: its own lines otherwise; while (c) do: performs its indented lines while c holds, testing c before each pass.

  • xk (x**k in listing blocks): x to the power k; in a field, x may be the polynomial variable and · the field product, with x-128 the inverse of x128. As an operand of @ or ‖, 0k and 1k are instead zeros(k) and ones(k), empty for k = 0.

  • local x : T, local a, b : T: pseudocode variables, outside any architectural state; a variable first assigned in a listing without local is also local to its function.

  • function f(a : T, …) → T' = { … }, struct { … }, array [i..j] of T, return: function definition, record, array type, and result. struct { f = v, … } builds a record and r.f selects its field f; A[] is a whole array of unspecified bounds and A[i] its element i, which may be sliced (A[i][j:k]) and assigned to as a slice.

  • x ∈ {a, b}: set membership.

  • Where a bit string is expected, binary digits, with or without the prefix 0b, are a bit string, the most significant first, as in the RISC-V ISA manual: 10 is the 2-bit V with V[1] = 1 and V[0] = 0, and a bare 0 or 1 is one bit. Where an n-bit value is expected, a hexadecimal numeral 0x… of value v stands for bin(v, n). Every other numeral is an integer.

  • (a, b) after return, and x, y ← f(…): a result with several components and its component-wise assignment, in declaration order; a result type written {x : T, …} is such a tuple.

  • bool, true, false: the Boolean type and its values; int: the integer type; bits(n): the type of an n-bit value.

  • X[r]: GPR number r, as in the RISC-V ISA manual (X[rs1] is the GPR that field rs1 names); X[s+1] @ X[s] is the GPR pair that holds a 64-bit value on RV32.

  • sext(x): x sign-extended to XLEN bits.

Functions

  • bin(n,m): the m least significant bits of the unsigned integer n, zero-extended if needed, bit i being the coefficient of 2i: bin(int(V), m) = V for an m-bit V, and int(bin(n, m)) = n mod 2m.

  • bswap(m): the byte string m in reverse byte order; for an 8n-bit value V, byte i of the result is byte n-1-i of V. bswap(m, n) = bswap(m[8n-1:0]).

  • brev8(V): for an 8n-bit value V, the value with the bits of each byte reversed, brev8(V)[8i+j] = V[8i+7-j] for 0 ≤ i < n and 0 ≤ j < 8, as the Zbkb instruction brev8 computes.

  • ceil(x), also ⌈x⌉: the smallest integer at least x; floor(x), also ⌊x⌋: the largest integer at most x.

  • double(S): doubling in GF(2b), as CMAC Functions defines it; OCB Mode uses it with b = 128.

  • Galoismul(a, b): multiplication in the GHASH field (GCM Mode).

  • int(V): V read as a little-endian unsigned binary number, bit V[i] being the coefficient of 2i.

  • lcm(a, b): the least common multiple of the positive integers a and b.

  • len_in_bits(M): the length of the value or string M in bits; len_in_bytes(M) = len_in_bits(M) / 8, defined only when len_in_bits(M) is a multiple of 8.

  • log2(x): the base-2 logarithm of the real number x > 0.

  • lsb(x), msb(x): the least, resp. most, significant bit of x; lsbc(x), msbc(x): its c least, resp. most, significant bits.

  • m[i .. j]: bytes i to j of the byte array m, both inclusive; bits are indexed as in Values, Bits, and Byte Strings.

  • min(x, y, …), max(x, y, …): the smallest, resp. largest, argument.

  • Montmul(a, b): the POLYVAL field operation (POLYVAL Hashing Function).

  • ones(i), zeros(i): i ones, resp. zeros.

  • update_mask(M): the XEX/XTS mask update (XEX/XTS Modes); a Machine that uses it names the one it means.

Transcribing a Formula from a Standard

Referenced standards often use the big-endian notation of communication protocols; this specification is little-endian. A formula from a standard is transcribed in two steps, in this order:

  1. Reverse the concatenation: A0 ‖ A1 ‖ … ‖ Am-1 becomes Am-1 @ … @ A1 @ A0, where each Ai is a whole field of the standard, such as a byte string or an encoded integer, never a part of one. A wrong ordering is the most common transcription error. Long messages formed by concatenation keep “‖”, in the little-endian sense of Operators and Control Constructs, since the standard’s own “‖” may be ambiguous.

  2. Encode each integer explicitly: a field that the standard specifies as a big-endian integer becomes bswap(bin(n, m)), and a little-endian one bin(n, m); neither is a bare numeral.

Two examples:

  • cite:[RFC8452] §4 builds each key-derivation input as the four-byte little-endian counter followed by the twelve-byte nonce, LE32(i) ‖ N: step 1 gives N @ LE32(i), and step 2 N @ bin(i,32).

  • cite:[nist-SP-800-38D] §7.1 builds, for a 96-bit IV, J0 = IV ‖ 031 ‖ 1, whose last four bytes encode the integer 1 big-endian: step 1 gives (031 ‖ 1) @ IV, the 32-bit counter counting as one field, and step 2 J0 ← bswap(bin(1,32)) @ IV. The left-to-right transcription IV @ zeros(31) @ 1 would put the IV in J0[127:32] and the counter in J0[31:0], the reverse of what cite:[nist-SP-800-38D] requires.

Conventions of the Referenced Standards

In a standard, A0 ‖ A1 ‖ … ‖ Am-1 may make A0 the most significant element, or the least. The table records, for each standard whose algorithms this specification reproduces, its convention and the resulting obligation. It is informative: where it differs from a Machine description or a Rule, these prevail, and an algorithm description must still be explicit.

Standard Convention used by the standard Obligation in this specification

SP 800-38A/B/E (ECB, CBC, CFB, OFB, CTR, CMAC, XTS)

byte strings; SP 800-38A, Appendix B, permits different counter constructions that ensure uniqueness; the CMAC subkey shift is over the big-endian string; the XTS tweak and mask are little-endian.

Direct mapping for ECB and the XTS data path, with the update_mask of XEX/XTS Modes. KLE selects a 32-bit big-endian counter in the trailing bytes of the CTR counter block, assembled via bswap (CTR/XCTR Keystream Generation), and the CMAC subkeys via the big-endian double (CMAC Functions). CFB with a segment of u bits takes the first bit of a byte string as the most significant bit of its first byte, and the first u bits as its first segment: KLE applies brev8 to the operands and takes the segments from the least significant bits (Chaining/Feedback Modes (CBC, CFB, and OFB)), which is direct when u is a multiple of 8.

GB/T 17964-2021 (XTS with SM4)

byte strings; the multiplication that updates the mask takes the bits of each byte in the reverse order of SP 800-38E.

The update_mask of SM4_XEX in XEX/XTS Modes.

HCTR2 (XCTR)

byte strings; the block counter is a little-endian integer, XORed into the IV.

Direct mapping: the input block is IV xor (zeros(b - j) @ ctr), with no bswap (CTR/XCTR Keystream Generation).

SP 800-38D (GCM)

byte strings; GHASH field bit-reflected within bytes; counters big-endian.

The Galoismul of GCM Mode; every counter and length field via bswap.

RFC 8452 (AES-GCM-SIV)

byte strings; POLYVAL field fully little-endian; block counter little-endian.

The Montmul of POLYVAL Hashing Function; counters and length blocks via bin.

RFC 7253 (OCB3)

bit strings, first bit most significant; double and the Stretch window are big-endian.

The double of OCB Mode; explicit bswap wherever the algorithm operates on the big-endian view.

FIPS 202 (SHA-3, SHAKE)

bit strings mapped to the state by §3.1; lanes little-endian.

Direct mapping of the absorbed string, with the lane indexing of FIPS 202 §3.1 unchanged; a final piece of any bit length maps directly, its last bits in the least significant positions (SHA-3 Family Specific Rules).

SP 800-185 (cSHAKE, KMAC)

bit strings as in FIPS 202; left_encode and right_encode write an integer big-endian, most significant byte first.

As FIPS 202; the right_encode of KMAC128, KMAC256, KMACXOF128, and KMACXOF256. The cshake_block and key_block use the same order whether the provisioner forms them or, for a system key or a random key (KeyType = 1 or 2), the KLE unit.

RFC 7693 (BLAKE2)

byte strings; words, counter and parameter block little-endian.

Direct mapping: words and counter via bin, no bswap; a final piece is a whole number of bytes (BLAKE2 Specific Rules).

FIPS 180-4 (SHA-2), GB/T 32905 (SM3)

bit strings, first bit most significant within a byte; big-endian words and length encoding.

Message schedule words, chaining variables (hence the digest) and the appended length via bswap; a final piece whose length is not a multiple of 8 carries its last bits in the most significant positions of its last byte (SHA-2 Family Specific Rules; Rule MR11, second bullet).

SP 800-232 (Ascon)

Little-endian throughout, including ‖.

Direct mapping, also within the last byte of a final block of any bit length (Enc_Last_Block and Dec_Last_Block in Ascon-AEAD128, the final piece of Ascon-Hash256 and the Z of Ascon-CXOF128; Rule MR11).

FIPS 186-5, SP 800-56A, SP 800-186, RFC 5639, GM/T 0003 (ECDSA, ECDH, SM2)

integers and coordinates as big-endian octet strings.

Every value little-endian via bin, converted by the caller (Elliptic Curve Cryptography); Hash holds bin(e, h) of the big-endian digest integer e; the shared secret that Output emits keeps the big-endian order of its standard, via bswap.

RFC 7748, RFC 8032 (X25519, X448, EdDSA)

little-endian integers, u-coordinates and point encodings.

Direct mapping via bin, including the shared secret K and the encoded points and signatures (X25519- and X448-Specific Rules, EdDSA-Specific Rules).

FIPS 198-1 (HMAC)

bit strings, as in its hash function; ipad and opad repeat a single byte.

Direct mapping; a final piece in the bit order of H (HMAC).

FIPS 203 / FIPS 204 (ML-KEM, ML-DSA)

byte strings produced by the standard’s own encoding routines.

Direct mapping of the encoded byte strings; no re-encoding.