cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Loading...
Searching...
No Matches
keccak256.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
10
11/******************************************************************
12 * 1. Included files
13 ******************************************************************/
14
15#include "keccak256.h"
16#include <string.h>
17
18#include "CW_Utils.h" /* hardened memory primitives (CODING_RULES §1.4) */
19
20/******************************************************************
21 * 2. Constants
22 ******************************************************************/
23
24#define KECCAK_ROUNDS 24U
25#define KECCAK_RATE 136U /* 1088 / 8 bytes — rate for 256-bit output */
26#define KECCAK_STATE_LANE 25U /* 5×5 uint64_t lanes */
27
28static const uint64_t kRC[KECCAK_ROUNDS] = {
29 0x0000000000000001ULL, 0x0000000000008082ULL,
30 0x800000000000808AULL, 0x8000000080008000ULL,
31 0x000000000000808BULL, 0x0000000080000001ULL,
32 0x8000000080008081ULL, 0x8000000000008009ULL,
33 0x000000000000008AULL, 0x0000000000000088ULL,
34 0x0000000080008009ULL, 0x000000008000000AULL,
35 0x000000008000808BULL, 0x800000000000008BULL,
36 0x8000000000008089ULL, 0x8000000000008003ULL,
37 0x8000000000008002ULL, 0x8000000000000080ULL,
38 0x000000000000800AULL, 0x800000008000000AULL,
39 0x8000000080008081ULL, 0x8000000000008080ULL,
40 0x0000000080000001ULL, 0x8000000080008008ULL,
41};
42
43/* Rho rotation offsets for lane [x + 5*y], derived from the Keccak spec. */
44static const uint8_t kRHO[KECCAK_STATE_LANE] = {
45 0, 1, 62, 28, 27, /* y=0 */
46 36, 44, 6, 55, 20, /* y=1 */
47 3, 10, 43, 25, 39, /* y=2 */
48 41, 45, 15, 21, 8, /* y=3 */
49 18, 2, 61, 56, 14 /* y=4 */
50};
51
52/******************************************************************
53 * 3. Internal helpers
54 ******************************************************************/
55
63static uint64_t rot64(uint64_t x, uint8_t n)
64{
65 return (n == 0U) ? x : ((x << n) | (x >> (64U - n)));
66}
67
73static void keccak_f1600(uint64_t st[KECCAK_STATE_LANE])
74{
75 uint64_t C[5], D[5], B[KECCAK_STATE_LANE];
76 unsigned int round, x, y;
77
78 for (round = 0U; round < KECCAK_ROUNDS; round++) {
79 /* Theta */
80 for (x = 0U; x < 5U; x++) {
81 C[x] = st[x] ^ st[x + 5U] ^ st[x + 10U] ^ st[x + 15U] ^ st[x + 20U];
82 }
83 for (x = 0U; x < 5U; x++) {
84 D[x] = C[(x + 4U) % 5U] ^ rot64(C[(x + 1U) % 5U], 1U);
85 }
86 for (x = 0U; x < 5U; x++) {
87 for (y = 0U; y < 5U; y++) {
88 st[x + 5U * y] ^= D[x];
89 }
90 }
91
92 /* Rho + Pi: B[dst] = ROT(st[src], rho[src]) */
93 for (x = 0U; x < 5U; x++) {
94 for (y = 0U; y < 5U; y++) {
95 unsigned int src = x + 5U * y;
96 unsigned int dst_x = y;
97 unsigned int dst_y = (2U * x + 3U * y) % 5U;
98 B[dst_x + 5U * dst_y] = rot64(st[src], kRHO[src]);
99 }
100 }
101
102 /* Chi */
103 for (x = 0U; x < 5U; x++) {
104 for (y = 0U; y < 5U; y++) {
105 st[x + 5U * y] = B[x + 5U * y] ^
106 ((~B[(x + 1U) % 5U + 5U * y]) &
107 B[(x + 2U) % 5U + 5U * y]);
108 }
109 }
110
111 /* Iota */
112 st[0] ^= kRC[round];
113 }
114}
115
116/******************************************************************
117 * 4. Public API
118 ******************************************************************/
119
120void keccak256(const uint8_t *input, size_t length, uint8_t digest[32])
121{
122 uint64_t state[KECCAK_STATE_LANE];
123 uint8_t *sb = reinterpret_cast<uint8_t *>(state);
124 size_t offset = 0U;
125 size_t i;
126
127 CW_Utils::secure_wipe(sb, sizeof(state));
128
129 /* Absorb full blocks */
130 while ((length - offset) >= KECCAK_RATE) {
131 for (i = 0U; i < KECCAK_RATE; i++) {
132 sb[i] ^= input[offset + i];
133 }
134 keccak_f1600(state);
135 offset += KECCAK_RATE;
136 }
137
138 /* Absorb remaining bytes */
139 size_t rem = length - offset;
140 for (i = 0U; i < rem; i++) {
141 sb[i] ^= input[offset + i];
142 }
143
144 /* Pad: 0x01 for Ethereum Keccak (pre-NIST), 0x80 at end of rate block */
145 sb[rem] ^= 0x01U;
146 sb[KECCAK_RATE - 1U] ^= 0x80U;
147
148 keccak_f1600(state);
149
150 /* Squeeze first 32 bytes */
151 (void)CW_Utils::safe_memcpy(digest, 32U, sb, 32U);
152}
#define KECCAK_STATE_LANE
Definition keccak256.cpp:26
static void keccak_f1600(uint64_t st[KECCAK_STATE_LANE])
Apply the full 24-round Keccak-f[1600] permutation in place.
Definition keccak256.cpp:73
static const uint64_t kRC[KECCAK_ROUNDS]
Definition keccak256.cpp:28
static uint64_t rot64(uint64_t x, uint8_t n)
Rotate a 64-bit lane left by n bits.
Definition keccak256.cpp:63
static const uint8_t kRHO[KECCAK_STATE_LANE]
Definition keccak256.cpp:44
#define KECCAK_ROUNDS
Definition keccak256.cpp:24
void keccak256(const uint8_t *input, size_t length, uint8_t digest[32])
Compute the Keccak-256 digest of a buffer.
#define KECCAK_RATE
Definition keccak256.cpp:25
Original Keccak-256 digest as used by Ethereum.