5 #include "sw/device/lib/crypto/impl/aes_gcm/ghash.h"
11 #define MODULE_ID MAKE_MODULE_ID('g', 'h', 'a')
17 kGhashBlockLog2NumBytes = 4,
24 kNumWindows = kGhashBlockNumBytes << 1,
26 static_assert(kGhashBlockNumBytes == (1 << kGhashBlockLog2NumBytes),
27 "kGhashBlockLog2NumBytes does not match kGhashBlockNumBytes");
48 static const uint16_t kGFReduceTable[16] = {
49 0x0000, 0x201c, 0x4038, 0x6024, 0x8070, 0xa06c, 0xc048, 0xe054,
50 0x00e1, 0x20fd, 0x40d9, 0x60c5, 0x8091, 0xa08d, 0xc0a9, 0xe0b5};
64 for (
size_t i = 0; i < kGhashBlockNumWords; ++i) {
65 out->data[i] = x->data[i] ^ y->data[i];
79 static inline void block_shiftr(
ghash_block_t *block,
size_t nbits) {
85 for (
size_t i = 0; i < kGhashBlockNumWords; ++i) {
86 uint32_t rev = __builtin_bswap32(block->data[i]);
87 uint32_t next_carry = rev & ((1 << nbits) - 1);
89 rev |= carry << (32 - nbits);
91 block->data[i] = __builtin_bswap32(rev);
102 static inline uint8_t block_byte_get(
const ghash_block_t *block,
size_t index) {
103 return ((
char *)block->data)[index];
119 uint8_t p127 = block_byte_get(p, kGhashBlockNumBytes - 1) & 1;
121 memcpy(out->data, p->data, kGhashBlockNumBytes);
122 block_shiftr(out, 1);
125 uint32_t mask = 0 - p127;
126 out->data[0] ^= (0xe1 & mask);
135 static uint8_t reverse_bits(uint8_t
byte) {
139 for (
size_t i = 0; i < 4; ++i) {
141 out |= (
byte >> i) & 1;
146 void ghash_init_subkey(
const uint32_t *hash_subkey,
ghash_context_t *ctx) {
148 memset(ctx->
tbl[0].data, 0, kGhashBlockNumBytes);
150 memcpy(ctx->
tbl[0x8].data, hash_subkey, kGhashBlockNumBytes);
157 for (uint8_t i = 2; i < 16; i += 2) {
160 galois_mulx(&ctx->
tbl[reverse_bits(i >> 1)], &ctx->
tbl[reverse_bits(i)]);
163 block_xor(&ctx->
tbl[reverse_bits(i)], &ctx->
tbl[0x8],
164 &ctx->
tbl[reverse_bits(i + 1)]);
190 memset(result.data, 0, kGhashBlockNumBytes);
201 for (
size_t i = 0; i < kNumWindows; ++i) {
205 block_byte_get(&result, kGhashBlockNumBytes - 1) & 0x0f;
207 block_shiftr(&result, 4);
210 uint16_t reduce_term = kGFReduceTable[overflow];
214 result.data[0] ^= reduce_term;
220 uint8_t tbl_index = block_byte_get(&ctx->
state, (kNumWindows - 1 - i) >> 1);
230 block_xor(&result, &ctx->
tbl[tbl_index], &result);
233 memcpy(ctx->
state.data, result.data, kGhashBlockNumBytes);
246 galois_mul_state_key(ctx);
249 void ghash_process_full_blocks(
ghash_context_t *ctx,
size_t partial_len,
251 const uint8_t *input) {
252 if (input_len < kGhashBlockNumBytes - partial_len) {
254 unsigned char *partial_bytes = (
unsigned char *)partial->data;
255 memcpy(partial_bytes + partial_len, input, input_len);
258 unsigned char *partial_bytes = (
unsigned char *)partial->data;
259 memcpy(partial_bytes + partial_len, input,
260 kGhashBlockNumBytes - partial_len);
261 input += kGhashBlockNumBytes - partial_len;
262 input_len -= kGhashBlockNumBytes - partial_len;
265 ghash_process_block(ctx, partial);
268 while (input_len >= kGhashBlockNumBytes) {
269 memcpy(partial->data, input, kGhashBlockNumBytes);
270 ghash_process_block(ctx, partial);
271 input += kGhashBlockNumBytes;
272 input_len -= kGhashBlockNumBytes;
276 memcpy(partial->data, input, input_len);
281 const uint8_t *input) {
285 ghash_process_full_blocks(ctx, 0, &partial, input_len, input);
288 size_t partial_len = input_len % kGhashBlockNumBytes;
289 if (partial_len != 0) {
290 unsigned char *partial_bytes = (
unsigned char *)partial.data;
291 memset(partial_bytes + partial_len, 0, kGhashBlockNumBytes - partial_len);
292 ghash_process_block(ctx, &partial);
297 memcpy(result, ctx->
state.data, kGhashBlockNumBytes);