Software APIs
dif_kmac.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
6
7#include <assert.h>
8
12
13#include "kmac_regs.h" // Generated.
14
15enum {
16 /**
17 * The maximum amount of usable bits in the output state.
18 *
19 * This constant may be assumed to be a multiple of 32.
20 *
21 * The actual number of usable bits may be lower than the value defined
22 * depending on the mode in use. The intent is that this constant is useful
23 * for sizing fixed length buffers.
24 *
25 * Formula for the rate in bits is:
26 *
27 * r = 1600 - c
28 *
29 * Where c is the capacity (the security level in bits multiplied by two).
30 *
31 * The lowest security level is 128 (e.g. SHAKE128).
32 */
33 kDifKmacMaximumBitRate = 1600 - (2 * 128),
34};
35
36dif_result_t dif_kmac_customization_string_init(
37 const char *data, size_t len, dif_kmac_customization_string_t *out) {
38 if ((data == NULL && len != 0) || out == NULL) {
39 return kDifBadArg;
40 }
41
43 return kDifBadArg;
44 }
45
46 static_assert(kDifKmacMaxCustomizationStringLen <= UINT16_MAX / 8,
47 "length requires more than 3 bytes to left encode");
48 static_assert(ARRAYSIZE(out->buffer) >= kDifKmacMaxCustomizationStringLen + 3,
49 "buffer is not large enough");
50
51 // Left encode length in bits.
52 uint16_t bits = ((uint16_t)len) * 8;
53 char *buffer = out->buffer;
54 if (bits <= UINT8_MAX) {
55 out->length = len + 2;
56 *buffer++ = 1;
57 *buffer++ = (char)bits;
58 } else {
59 out->length = len + 3;
60 *buffer++ = 2;
61 // Most significant byte is first (i.e. big-endian).
62 *buffer++ = (char)(bits >> 8);
63 *buffer++ = (char)bits;
64 }
65
66 memcpy(buffer, data, len);
67
68 return kDifOk;
69}
70
71dif_result_t dif_kmac_function_name_init(const char *data, size_t len,
73 if ((data == NULL && len != 0) || out == NULL) {
74 return kDifBadArg;
75 }
76
78 return kDifBadArg;
79 }
80
81 static_assert(kDifKmacMaxFunctionNameLen <= UINT8_MAX / 8,
82 "length requires more than 2 bytes to left encode");
83 static_assert(ARRAYSIZE(out->buffer) >= kDifKmacMaxFunctionNameLen + 2,
84 "buffer is not large enough");
85
86 // Length of the data to be stored into buffer.
87 out->length = len + 2;
88
89 // Left encode length in bits.
90 out->buffer[0] = 1;
91 out->buffer[1] = (char)(len * 8);
92
93 memcpy(&out->buffer[2], data, len);
94
95 return kDifOk;
96}
97
98/**
99 * Report whether the hardware is currently idle.
100 *
101 * If the hardware is not idle then the `CFG` register is locked.
102 *
103 * @param kmac Handle.
104 * @returns Whether the hardware is currently idle or not.
105 */
106static bool is_state_idle(const dif_kmac_t *kmac) {
107 uint32_t reg = mmio_region_read32(kmac->base_addr, KMAC_STATUS_REG_OFFSET);
108 return bitfield_bit32_read(reg, KMAC_STATUS_SHA3_IDLE_BIT);
109}
110
111/**
112 * Report whether the hardware is currently in the absorb state and accepting
113 * writes to the message FIFO.
114 *
115 * Note that writes to the message FIFO may still block if it is full.
116 *
117 * @param kmac Handle.
118 * @returns Whether the hardware is currently absorbing or not.
119 */
120static bool is_state_absorb(const dif_kmac_t *kmac) {
121 uint32_t reg = mmio_region_read32(kmac->base_addr, KMAC_STATUS_REG_OFFSET);
122 return bitfield_bit32_read(reg, KMAC_STATUS_SHA3_ABSORB_BIT);
123}
124
125/**
126 * Report whether the hardware is currently in the squeeze state which means
127 * that the output state is valid and may be read by software.
128 *
129 * @param kmac Handle.
130 * @returns Whether the hardware is currently in the squeeze state or not.
131 */
132static bool is_state_squeeze(const dif_kmac_t *kmac) {
133 uint32_t reg = mmio_region_read32(kmac->base_addr, KMAC_STATUS_REG_OFFSET);
134 return bitfield_bit32_read(reg, KMAC_STATUS_SHA3_SQUEEZE_BIT);
135}
136
137dif_result_t dif_kmac_has_error_occurred(const dif_kmac_t *kmac, bool *error) {
138 if (kmac == NULL) {
139 return kDifBadArg;
140 }
141 uint32_t reg =
142 mmio_region_read32(kmac->base_addr, KMAC_INTR_STATE_REG_OFFSET);
143 *error = bitfield_bit32_read(reg, KMAC_INTR_STATE_KMAC_ERR_BIT);
144 return kDifOk;
145}
146
147dif_result_t dif_kmac_clear_err_irq(const dif_kmac_t *kmac) {
148 if (kmac == NULL) {
149 return kDifBadArg;
150 }
151 uint32_t reg = 0;
152 reg = bitfield_bit32_write(reg, KMAC_INTR_STATE_KMAC_ERR_BIT, true);
153 mmio_region_write32(kmac->base_addr, KMAC_INTR_STATE_REG_OFFSET, reg);
154 return kDifOk;
155}
156
157dif_result_t dif_kmac_poll_status(const dif_kmac_t *kmac, uint32_t flag) {
158 while (true) {
159 uint32_t reg = mmio_region_read32(kmac->base_addr, KMAC_STATUS_REG_OFFSET);
160 if (bitfield_bit32_read(reg, flag)) {
161 break;
162 }
163 bool error;
164 DIF_RETURN_IF_ERROR(dif_kmac_has_error_occurred(kmac, &error));
165 if (error) {
166 return kDifError;
167 }
168 }
169 return kDifOk;
170}
171
172dif_result_t dif_kmac_configure(dif_kmac_t *kmac, dif_kmac_config_t config) {
173 if (kmac == NULL) {
174 return kDifBadArg;
175 }
176
177 // Entropy mode.
178 uint32_t entropy_mode_value;
179 bool entropy_ready = false;
180 switch (config.entropy_mode) {
181 case kDifKmacEntropyModeIdle:
182 entropy_mode_value = KMAC_CFG_SHADOWED_ENTROPY_MODE_VALUE_IDLE_MODE;
183 break;
184 case kDifKmacEntropyModeEdn:
185 entropy_mode_value = KMAC_CFG_SHADOWED_ENTROPY_MODE_VALUE_EDN_MODE;
186 entropy_ready = true;
187 break;
188 case kDifKmacEntropyModeSoftware:
189 entropy_mode_value = KMAC_CFG_SHADOWED_ENTROPY_MODE_VALUE_SW_MODE;
190 entropy_ready = true;
191 break;
192 default:
193 return kDifBadArg;
194 }
195
196 // Check that the hardware is in an idle state.
197 if (!is_state_idle(kmac)) {
198 return kDifLocked;
199 }
200
201 // Write entropy period register.
202 uint32_t entropy_period_reg = 0;
203 entropy_period_reg = bitfield_field32_write(
204 entropy_period_reg, KMAC_ENTROPY_PERIOD_WAIT_TIMER_FIELD,
205 config.entropy_wait_timer);
206 entropy_period_reg = bitfield_field32_write(
207 entropy_period_reg, KMAC_ENTROPY_PERIOD_PRESCALER_FIELD,
208 config.entropy_prescaler);
209
210 mmio_region_write32(kmac->base_addr, KMAC_ENTROPY_PERIOD_REG_OFFSET,
211 entropy_period_reg);
212
213 // Write threshold register.
214 uint32_t entropy_threshold_reg =
215 KMAC_ENTROPY_REFRESH_THRESHOLD_SHADOWED_REG_RESVAL;
216 entropy_threshold_reg = bitfield_field32_write(
217 entropy_threshold_reg,
218 KMAC_ENTROPY_REFRESH_THRESHOLD_SHADOWED_THRESHOLD_FIELD,
220
221 mmio_region_write32_shadowed(
222 kmac->base_addr, KMAC_ENTROPY_REFRESH_THRESHOLD_SHADOWED_REG_OFFSET,
223 entropy_threshold_reg);
224
225 // Write configuration register.
226 uint32_t cfg_reg = 0;
227 cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_MSG_ENDIANNESS_BIT,
228 config.message_big_endian);
229 cfg_reg =
230 bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_STATE_ENDIANNESS_BIT,
231 config.output_big_endian);
232 cfg_reg = bitfield_field32_write(
233 cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_MODE_FIELD, entropy_mode_value);
234 cfg_reg =
235 bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_FAST_PROCESS_BIT,
236 config.entropy_fast_process);
237 cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_SIDELOAD_BIT,
238 config.sideload);
239 cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_READY_BIT,
240 entropy_ready);
241
242 cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_MSG_MASK_BIT,
243 config.msg_mask);
244
245 mmio_region_write32_shadowed(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
246 cfg_reg);
247
248 // Write entropy seed registers.
249 for (int i = 0; i < kDifKmacEntropySeedWords; ++i) {
250 mmio_region_write32(kmac->base_addr, KMAC_ENTROPY_SEED_REG_OFFSET,
251 config.entropy_seed[i]);
252 }
253
254 return kDifOk;
255}
256
257/**
258 * Calculate the rate (r) in bits from the given security level.
259 *
260 * @param security_level Security level in bits.
261 * @returns Rate in bits.
262 */
263static uint32_t calculate_rate_bits(uint32_t security_level) {
264 // Formula for the rate in bits is:
265 //
266 // r = 1600 - c
267 //
268 // Where c is the capacity (the security level in bits multiplied by two).
269 return 1600 - 2 * security_level;
270}
271
272dif_result_t dif_kmac_mode_sha3_start(
273 const dif_kmac_t *kmac, dif_kmac_operation_state_t *operation_state,
275 if (kmac == NULL || operation_state == NULL) {
276 return kDifBadArg;
277 }
278
279 // Set key strength and calculate rate (r) and digest length (d) in 32-bit
280 // words.
281 uint32_t kstrength;
282 switch (mode) {
284 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L224;
285 operation_state->offset = 0;
286 operation_state->r = calculate_rate_bits(224) / 32;
287 operation_state->d = 224 / 32;
288 break;
290 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256;
291 operation_state->offset = 0;
292 operation_state->r = calculate_rate_bits(256) / 32;
293 operation_state->d = 256 / 32;
294 break;
296 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L384;
297 operation_state->offset = 0;
298 operation_state->r = calculate_rate_bits(384) / 32;
299 operation_state->d = 384 / 32;
300 break;
302 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L512;
303 operation_state->offset = 0;
304 operation_state->r = calculate_rate_bits(512) / 32;
305 operation_state->d = 512 / 32;
306 break;
307 default:
308 return kDifBadArg;
309 }
310
311 // Hardware must be idle to start an operation.
312 if (!is_state_idle(kmac)) {
313 return kDifError;
314 }
315
316 operation_state->squeezing = false;
317 operation_state->append_d = false;
318
319 // Configure SHA-3 mode with the given strength.
320 uint32_t cfg_reg =
321 mmio_region_read32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
322 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
323 kstrength);
324 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
325 KMAC_CFG_SHADOWED_MODE_VALUE_SHA3);
326 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
327 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
328
329 // Issue start command.
330 uint32_t cmd_reg =
331 bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
332 mmio_region_write32(kmac->base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
333
334 // Poll until the status register is in the 'absorb' state.
335 return dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_ABSORB_BIT);
336}
337
338dif_result_t dif_kmac_mode_shake_start(
339 const dif_kmac_t *kmac, dif_kmac_operation_state_t *operation_state,
341 if (kmac == NULL || operation_state == NULL) {
342 return kDifBadArg;
343 }
344
345 // Set key strength and calculate rate (r).
346 uint32_t kstrength;
347 switch (mode) {
349 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128;
350 operation_state->r = calculate_rate_bits(128) / 32;
351 break;
353 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256;
354 operation_state->r = calculate_rate_bits(256) / 32;
355 break;
356 default:
357 return kDifBadArg;
358 }
359
360 // Hardware must be idle to start an operation.
361 if (!is_state_idle(kmac)) {
362 return kDifError;
363 }
364 operation_state->squeezing = false;
365 operation_state->append_d = false;
366 operation_state->d = 0; // Zero indicates variable digest length.
367 operation_state->offset = 0;
368
369 // Configure SHAKE mode with the given strength.
370 uint32_t cfg_reg =
371 mmio_region_read32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
372 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
373 kstrength);
374 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
375 KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE);
376 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
377 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
378
379 // Issue start command.
380 uint32_t cmd_reg =
381 bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
382 mmio_region_write32(kmac->base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
383
384 return dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_ABSORB_BIT);
385}
386
387dif_result_t dif_kmac_mode_cshake_start(
388 const dif_kmac_t *kmac, dif_kmac_operation_state_t *operation_state,
391 if (kmac == NULL || operation_state == NULL) {
392 return kDifBadArg;
393 }
394
395 // Use SHAKE if both N and S are empty strings.
396 bool n_is_empty = n == NULL || (n->buffer[0] == 1 && n->buffer[1] == 0);
397 bool s_is_empty = s == NULL || (s->buffer[0] == 1 && s->buffer[1] == 0);
398 if (n_is_empty && s_is_empty) {
399 switch (mode) {
401 return dif_kmac_mode_shake_start(kmac, operation_state,
404 return dif_kmac_mode_shake_start(kmac, operation_state,
406 default:
407 return kDifBadArg;
408 }
409 }
410
411 // Set key strength and calculate rate (r).
412 uint32_t kstrength;
413 switch (mode) {
415 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128;
416 operation_state->r = calculate_rate_bits(128) / 32;
417 break;
419 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256;
420 operation_state->r = calculate_rate_bits(256) / 32;
421 break;
422 default:
423 return kDifBadArg;
424 }
425
426 // Hardware must be idle to start an operation.
427 if (!is_state_idle(kmac)) {
428 return kDifError;
429 }
430 operation_state->squeezing = false;
431 operation_state->append_d = false;
432 operation_state->d = 0; // Zero indicates variable digest length.
433 operation_state->offset = 0;
434
435 // Configure cSHAKE mode with the given strength.
436 uint32_t cfg_reg =
437 mmio_region_read32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
438 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
439 kstrength);
440 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
441 KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
442 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
443 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
444
445 // Calculate PREFIX register values.
446 uint32_t prefix_regs[11] = {0};
447 uint8_t *prefix_data = (uint8_t *)prefix_regs;
448 if (n == NULL || n->length < 3) {
449 // Append left encoded empty string.
450 prefix_data[0] = 1;
451 prefix_data[1] = 0;
452 prefix_data += 2;
453 } else {
454 memcpy(prefix_data, n->buffer, n->length);
455 prefix_data += n->length;
456 }
457 if (s == NULL || s->length == 0) {
458 // Append left encoded empty string.
459 prefix_data[0] = 1;
460 prefix_data[1] = 0;
461 } else {
462 memcpy(prefix_data, s->buffer, s->length);
463 }
464
465 // Write PREFIX register values.
466 const mmio_region_t base = kmac->base_addr;
467 mmio_region_write32(base, KMAC_PREFIX_0_REG_OFFSET, prefix_regs[0]);
468 mmio_region_write32(base, KMAC_PREFIX_1_REG_OFFSET, prefix_regs[1]);
469 mmio_region_write32(base, KMAC_PREFIX_2_REG_OFFSET, prefix_regs[2]);
470 mmio_region_write32(base, KMAC_PREFIX_3_REG_OFFSET, prefix_regs[3]);
471 mmio_region_write32(base, KMAC_PREFIX_4_REG_OFFSET, prefix_regs[4]);
472 mmio_region_write32(base, KMAC_PREFIX_5_REG_OFFSET, prefix_regs[5]);
473 mmio_region_write32(base, KMAC_PREFIX_6_REG_OFFSET, prefix_regs[6]);
474 mmio_region_write32(base, KMAC_PREFIX_7_REG_OFFSET, prefix_regs[7]);
475 mmio_region_write32(base, KMAC_PREFIX_8_REG_OFFSET, prefix_regs[8]);
476 mmio_region_write32(base, KMAC_PREFIX_9_REG_OFFSET, prefix_regs[9]);
477 mmio_region_write32(base, KMAC_PREFIX_10_REG_OFFSET, prefix_regs[10]);
478
479 // Issue start command.
480 uint32_t cmd_reg =
481 bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
482 mmio_region_write32(kmac->base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
483
484 return dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_ABSORB_BIT);
485}
486
487dif_result_t dif_kmac_mode_kmac_start(
488 const dif_kmac_t *kmac, dif_kmac_operation_state_t *operation_state,
489 dif_kmac_mode_kmac_t mode, size_t l, const dif_kmac_key_t *k,
491 if (kmac == NULL || operation_state == NULL || k == NULL ||
493 return kDifBadArg;
494 }
495
496 // Set key strength and calculate rate (r).
497 uint32_t kstrength;
498 switch (mode) {
500 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128;
501 operation_state->r = calculate_rate_bits(128) / 32;
502 break;
504 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256;
505 operation_state->r = calculate_rate_bits(256) / 32;
506 break;
507 default:
508 return kDifBadArg;
509 }
510 operation_state->squeezing = false;
511 operation_state->offset = 0;
512 operation_state->d = l;
513 operation_state->append_d = true;
514
515 uint32_t key_len;
516 switch (k->length) {
518 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY128;
519 break;
521 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY192;
522 break;
524 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY256;
525 break;
527 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY384;
528 break;
530 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY512;
531 break;
532 default:
533 return kDifBadArg;
534 }
535
536 // Hardware must be idle to start an operation.
537 if (!is_state_idle(kmac)) {
538 return kDifError;
539 }
540 // Set key length and shares.
541 mmio_region_write32(kmac->base_addr, KMAC_KEY_LEN_REG_OFFSET, key_len);
542 for (int i = 0; i < ARRAYSIZE(k->share0); ++i) {
543 mmio_region_write32(kmac->base_addr,
544 KMAC_KEY_SHARE0_0_REG_OFFSET +
545 (ptrdiff_t)i * (ptrdiff_t)sizeof(uint32_t),
546 k->share0[i]);
547 mmio_region_write32(kmac->base_addr,
548 KMAC_KEY_SHARE1_0_REG_OFFSET +
549 (ptrdiff_t)i * (ptrdiff_t)sizeof(uint32_t),
550 k->share1[i]);
551 }
552
553 // Configure cSHAKE mode with the given strength and enable KMAC mode.
554 uint32_t cfg_reg =
555 mmio_region_read32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
556 cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, true);
557 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
558 kstrength);
559 cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
560 KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
561 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
562 mmio_region_write32(kmac->base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
563
564 // Initialize prefix registers with function name ("KMAC") and empty
565 // customization string. The empty customization string will be overwritten if
566 // a non-empty string is provided.
567 uint32_t prefix_regs[11] = {
568 0x4D4B2001, // 1 32 'K' 'M'
569 0x00014341, // 'A' 'C' 1 0
570 };
571
572 // Encoded customization string (s) must be at least 3 bytes long if it is not
573 // the empty string.
574 if (s != NULL && s->length >= 3) {
575 // First two bytes overwrite the pre-encoded empty customization string.
576 prefix_regs[1] &= 0xFFFF;
577 prefix_regs[1] |= (uint32_t)((uint8_t)s->buffer[0]) << 16;
578 prefix_regs[1] |= (uint32_t)((uint8_t)s->buffer[1]) << 24;
579 memcpy(&prefix_regs[2], &s->buffer[2], s->length - 2);
580 }
581
582 // Write PREFIX register values.
583 const mmio_region_t base = kmac->base_addr;
584 mmio_region_write32(base, KMAC_PREFIX_0_REG_OFFSET, prefix_regs[0]);
585 mmio_region_write32(base, KMAC_PREFIX_1_REG_OFFSET, prefix_regs[1]);
586 mmio_region_write32(base, KMAC_PREFIX_2_REG_OFFSET, prefix_regs[2]);
587 mmio_region_write32(base, KMAC_PREFIX_3_REG_OFFSET, prefix_regs[3]);
588 mmio_region_write32(base, KMAC_PREFIX_4_REG_OFFSET, prefix_regs[4]);
589 mmio_region_write32(base, KMAC_PREFIX_5_REG_OFFSET, prefix_regs[5]);
590 mmio_region_write32(base, KMAC_PREFIX_6_REG_OFFSET, prefix_regs[6]);
591 mmio_region_write32(base, KMAC_PREFIX_7_REG_OFFSET, prefix_regs[7]);
592 mmio_region_write32(base, KMAC_PREFIX_8_REG_OFFSET, prefix_regs[8]);
593 mmio_region_write32(base, KMAC_PREFIX_9_REG_OFFSET, prefix_regs[9]);
594 mmio_region_write32(base, KMAC_PREFIX_10_REG_OFFSET, prefix_regs[10]);
595
596 // Issue start command.
597 uint32_t cmd_reg =
598 bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
599 mmio_region_write32(kmac->base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
600
601 return dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_ABSORB_BIT);
602}
603
604static void msg_fifo_write(const dif_kmac_t *kmac, const unsigned char *data,
605 size_t len) {
606 // Copy message using aligned word sized loads and stores where possible to
607 // improve performance. Note: the parts of the message copied a byte at a time
608 // will not be byte swapped in big-endian mode.
609 for (; len != 0 && ((uintptr_t)data) % sizeof(uint32_t); --len) {
610 mmio_region_write8(kmac->base_addr, KMAC_MSG_FIFO_REG_OFFSET, *data++);
611 }
612 for (; len >= sizeof(uint32_t); len -= sizeof(uint32_t)) {
613 mmio_region_write32(kmac->base_addr, KMAC_MSG_FIFO_REG_OFFSET,
614 read_32(data));
615 data += sizeof(uint32_t);
616 }
617 for (; len != 0; --len) {
618 mmio_region_write8(kmac->base_addr, KMAC_MSG_FIFO_REG_OFFSET, *data++);
619 }
620}
621
622dif_result_t dif_kmac_absorb(const dif_kmac_t *kmac,
623 dif_kmac_operation_state_t *operation_state,
624 const void *msg, size_t len, size_t *processed) {
625 // Set the number of bytes processed to 0.
626 if (processed != NULL) {
627 *processed = 0;
628 }
629
630 if (kmac == NULL || operation_state == NULL || (msg == NULL && len != 0)) {
631 return kDifBadArg;
632 }
633
634 // Check that an operation has been started.
635 if (operation_state->r == 0) {
636 return kDifError;
637 }
638
639 // Poll until the status register is in the 'absorb' state.
640 if (!is_state_absorb(kmac)) {
641 return kDifError;
642 }
643
644 // Copy message using aligned word sized loads and stores where possible to
645 // improve performance. Note: the parts of the message copied a byte at a time
646 // will not be byte swapped in big-endian mode.
647 const unsigned char *data = (const unsigned char *)msg;
648 dif_kmac_status_t status;
649 while (len > 0) {
650 // Read the status register.
651 DIF_RETURN_IF_ERROR(dif_kmac_get_status(kmac, &status));
652
653 // Calculate the remaining space in the message FIFO based on the
654 // `FIFO_DEPTH` status field.
655 size_t free_entries = (KMAC_PARAM_NUM_ENTRIES_MSG_FIFO - status.fifo_depth);
656 size_t max_len = free_entries * KMAC_PARAM_NUM_BYTES_MSG_FIFO_ENTRY;
657 size_t write_len = (len < max_len) ? len : max_len;
658 msg_fifo_write(kmac, data, write_len);
659 data += write_len;
660 len -= write_len;
661
662 // If `processed` is non-null, do not continue after the first iteration;
663 // return the number of bytes written and `kDifKmacIncomplete`.
664 if (processed != NULL) {
665 *processed = write_len;
666 break;
667 }
668 }
669
670 return kDifOk;
671}
672
673dif_result_t dif_kmac_squeeze(const dif_kmac_t *kmac,
674 dif_kmac_operation_state_t *operation_state,
675 uint32_t *out, size_t len, size_t *processed,
676 uint32_t *capacity) {
677 if (kmac == NULL || operation_state == NULL || (out == NULL && len != 0)) {
678 return kDifBadArg;
679 }
680
681 // Set `processed` to 0 so we can return early without setting it again.
682 if (processed != NULL) {
683 *processed = 0;
684 }
685
686 const mmio_region_t base = kmac->base_addr;
687
688 // Move into squeezing state (if not already in it).
689 // Do this even if the length requested is 0 or too big.
690 if (!operation_state->squeezing) {
691 if (operation_state->append_d) {
692 // The KMAC operation requires that the output length (d) in bits be right
693 // encoded and appended to the end of the message.
694 // Note: kDifKmacMaxOutputLenWords could be reduced to make this code
695 // simpler. For example, a maximum of `(UINT16_MAX - 32) / 32` (just under
696 // 8 KiB) would mean that d is guaranteed to be less than 0xFFFF.
697 uint32_t d = operation_state->d * 32;
698 int len = 1 + (d > 0xFF) + (d > 0xFFFF) + (d > 0xFFFFFF);
699 int shift = (len - 1) * 8;
700 while (shift >= 8) {
701 mmio_region_write8(base, KMAC_MSG_FIFO_REG_OFFSET,
702 (uint8_t)(d >> shift));
703 shift -= 8;
704 }
705 mmio_region_write8(base, KMAC_MSG_FIFO_REG_OFFSET, (uint8_t)d);
706 mmio_region_write8(base, KMAC_MSG_FIFO_REG_OFFSET, (uint8_t)len);
707 }
708 operation_state->squeezing = true;
709
710 // Issue squeeze command.
711 uint32_t cmd_reg = bitfield_field32_write(0, KMAC_CMD_CMD_FIELD,
712 KMAC_CMD_CMD_VALUE_PROCESS);
713 mmio_region_write32(base, KMAC_CMD_REG_OFFSET, cmd_reg);
714 }
715
716 // If the operation has a fixed length output then the total number of bytes
717 // requested must not exceed that length.
718 if (operation_state->d != 0 &&
719 len > (operation_state->d - operation_state->offset)) {
720 return kDifError;
721 }
722
723 if (len == 0) {
724 return kDifOk;
725 }
726
727 while (len > 0) {
728 size_t n = len;
729 size_t remaining = operation_state->r - operation_state->offset;
730 if (operation_state->d != 0 && operation_state->d < operation_state->r) {
731 remaining = operation_state->d - operation_state->offset;
732 }
733 if (n > remaining) {
734 n = remaining;
735 }
736 if (n == 0) {
737 // Reduce the digest length to reflect consumed output state.
738 if (operation_state->d != 0) {
739 if (operation_state->d <= operation_state->r) {
740 return kDifError;
741 }
742 operation_state->d -= operation_state->r;
743 }
744
745 // Issue run command to generate more state.
746 uint32_t cmd_reg =
747 bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_RUN);
748 mmio_region_write32(base, KMAC_CMD_REG_OFFSET, cmd_reg);
749 operation_state->offset = 0;
750 continue;
751 }
752
753 // Poll the status register until in the 'squeeze' state.
755 dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_SQUEEZE_BIT));
756
757 ptrdiff_t offset =
758 KMAC_STATE_REG_OFFSET +
759 (ptrdiff_t)operation_state->offset * (ptrdiff_t)sizeof(uint32_t);
760 for (size_t i = 0; i < n; ++i) {
761 // Read both shares from state register and combine using XOR.
762 uint32_t share0 = mmio_region_read32(base, offset);
763 uint32_t share1 =
764 mmio_region_read32(base, offset + kDifKmacStateShareOffset);
765 *out++ = share0 ^ share1;
766 offset += sizeof(uint32_t);
767 }
768 operation_state->offset += n;
769 len -= n;
770 if (processed != NULL) {
771 *processed += n;
772 }
773 // Read also the capacity of the state, if non-NULL buffer is given.
774 // This is only useful for testing that capacity is not leaked during
775 // sideloaded KMAC operations.
776 if (capacity != NULL) {
777 ptrdiff_t capacity_offset =
778 KMAC_STATE_REG_OFFSET +
779 (ptrdiff_t)operation_state->r * (ptrdiff_t)sizeof(uint32_t);
780 for (int i = 0; i < kDifKmacStateWords - operation_state->r; ++i) {
781 uint32_t share0 = mmio_region_read32(base, capacity_offset);
782 uint32_t share1 = mmio_region_read32(
783 base, capacity_offset + kDifKmacStateShareOffset);
784 *capacity++ = share0 ^ share1;
785 capacity_offset += sizeof(uint32_t);
786 }
787 }
788 }
789 return kDifOk;
790}
791
792dif_result_t dif_kmac_end(const dif_kmac_t *kmac,
793 dif_kmac_operation_state_t *operation_state) {
794 if (kmac == NULL || operation_state == NULL) {
795 return kDifBadArg;
796 }
797
798 // The hardware should (must?) complete squeeze operation before the DONE
799 // command is issued.
800 if (!operation_state->squeezing) {
801 return kDifError;
802 }
803 while (true) {
804 if (is_state_squeeze(kmac)) {
805 break;
806 }
807 // TODO(#6248): check for error.
808 }
809
810 // Issue done command.
811 uint32_t cmd_reg =
812 bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_DONE);
813 mmio_region_write32(kmac->base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
814
815 // Reset operation state.
816 operation_state->squeezing = false;
817 operation_state->append_d = false;
818 operation_state->offset = 0;
819 operation_state->r = 0;
820 operation_state->d = 0;
821
822 return kDifOk;
823}
824
825dif_result_t dif_kmac_config_is_locked(const dif_kmac_t *kmac,
826 bool *is_locked) {
827 if (kmac == NULL || is_locked == NULL) {
828 return kDifBadArg;
829 }
830
831 uint32_t reg =
832 mmio_region_read32(kmac->base_addr, KMAC_CFG_REGWEN_REG_OFFSET);
833 *is_locked = !bitfield_bit32_read(reg, KMAC_CFG_REGWEN_EN_BIT);
834 return kDifOk;
835}
836
837dif_result_t dif_kmac_get_status(const dif_kmac_t *kmac,
838 dif_kmac_status_t *kmac_status) {
839 if (kmac == NULL || kmac_status == NULL) {
840 return kDifBadArg;
841 }
842
843 uint32_t reg = mmio_region_read32(kmac->base_addr, KMAC_STATUS_REG_OFFSET);
844
845 kmac_status->sha3_state = bitfield_field32_read(
846 reg,
847 (bitfield_field32_t){.mask = 0x07, .index = KMAC_STATUS_SHA3_IDLE_BIT});
848
849 kmac_status->fifo_depth =
850 bitfield_field32_read(reg, KMAC_STATUS_FIFO_DEPTH_FIELD);
851
852 kmac_status->fifo_state = bitfield_field32_read(
853 reg,
854 (bitfield_field32_t){.mask = 0x03, .index = KMAC_STATUS_FIFO_EMPTY_BIT});
855
856 kmac_status->faults = bitfield_field32_read(
857 reg, (bitfield_field32_t){.mask = 0x03,
858 .index = KMAC_STATUS_ALERT_FATAL_FAULT_BIT});
859
860 return kDifOk;
861}
862
863dif_result_t dif_kmac_get_hash_counter(const dif_kmac_t *kmac,
864 uint32_t *hash_ctr) {
865 if (kmac == NULL || hash_ctr == NULL) {
866 return kDifBadArg;
867 }
868
869 uint32_t reg = mmio_region_read32(kmac->base_addr,
870 KMAC_ENTROPY_REFRESH_HASH_CNT_REG_OFFSET);
871
872 *hash_ctr =
873 bitfield_field32_read(reg, KMAC_ENTROPY_REFRESH_HASH_CNT_HASH_CNT_FIELD);
874
875 return kDifOk;
876}
877
878dif_result_t dif_kmac_get_error(const dif_kmac_t *kmac, dif_kmac_error_t *error,
879 uint32_t *info) {
880 if (kmac == NULL || error == NULL || info == NULL) {
881 return kDifBadArg;
882 }
883
884 uint32_t reg = mmio_region_read32(kmac->base_addr, KMAC_ERR_CODE_REG_OFFSET);
885 *info = reg & 0xFFFFFF;
886 *error = (reg >> 24) & 0xFF;
887 return kDifOk;
888}
889
890dif_result_t dif_kmac_reset(const dif_kmac_t *kmac,
891 dif_kmac_operation_state_t *operation_state) {
892 if (kmac == NULL || operation_state == NULL) {
893 return kDifBadArg;
894 }
895 operation_state->d = 0;
896 operation_state->r = 0;
897 operation_state->offset = 0;
898 operation_state->squeezing = false;
899 DIF_RETURN_IF_ERROR(dif_kmac_err_processed(kmac));
900 return kDifOk;
901}
902
903dif_result_t dif_kmac_err_processed(const dif_kmac_t *kmac) {
904 if (kmac == NULL) {
905 return kDifBadArg;
906 }
907 uint32_t reg = 0;
908 reg = bitfield_bit32_write(reg, KMAC_CMD_ERR_PROCESSED_BIT, 1);
909 mmio_region_write32(kmac->base_addr, KMAC_CMD_REG_OFFSET, reg);
910 return kDifOk;
911}