Software APIs
dif_aes.c
1 // Copyright lowRISC contributors.
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
6 
7 #include <stddef.h>
8 
11 
12 #include "aes_regs.h" // Generated.
13 
14 /*
15  * From: https://docs.opentitan.org/hw/ip/aes/doc/index.html#register-table,
16  * aes.CTRL.
17  */
18 
19 /*
20  * Field to select AES block cipher mode.
21  *
22  * Invalid input values, i.e., value with multiple bits set - are mapped to
23  * `kAesModeFieldValNone`.
24  */
25 typedef enum aes_mode_field_val {
26  kAesModeFieldValEcb = 0x01, /**< The Electronic Codebook Mode. */
27  kAesModeFieldValCbc = 0x02, /**< The Cipher Block Chaining Mode. */
28  kAesModeFieldValCfb = 0x04, /**< TODO */
29  kAesModeFieldValOfb = 0x08, /**< TODO */
30  kAesModeFieldValCtr = 0x10, /**< The Counter Mode. */
31  kAesModeFieldValNone = 0x20, /**< TODO */
32 } aes_mode_field_val_t;
33 
34 /*
35  * Field to select AES key length.
36  *
37  * Invalid input values, i.e., value with multiple bits set, value 3'b000, and
38  * value 3'b010 in case 192-bit keys are not supported (disabled at compile
39  * time) are mapped to `kAesKeyFieldVal256`.
40  */
41 typedef enum aes_key_field_val {
42  kAesKeyFieldValInvalid = 0x00,
43  kAesKeyFieldVal128 = 0x01,
44  kAesKeyFieldVal192 = 0x02,
45  kAesKeyFieldVal256 = 0x04,
46 } aes_key_field_val_t;
47 
48 static bool aes_idle(const dif_aes_t *aes) {
49  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
50  AES_STATUS_IDLE_BIT);
51 }
52 
53 static bool aes_stalled(const dif_aes_t *aes) {
54  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
55  AES_STATUS_STALL_BIT);
56 }
57 
58 static bool aes_output_lost(const dif_aes_t *aes) {
59  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
60  AES_STATUS_OUTPUT_LOST_BIT);
61 }
62 
63 static bool aes_output_valid(const dif_aes_t *aes) {
64  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
65  AES_STATUS_OUTPUT_VALID_BIT);
66 }
67 
68 static bool aes_input_ready(const dif_aes_t *aes) {
69  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
70  AES_STATUS_INPUT_READY_BIT);
71 }
72 
73 static bool aes_alert_fatal(const dif_aes_t *aes) {
74  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
75  AES_STATUS_ALERT_FATAL_FAULT_BIT);
76 }
77 
78 static bool aes_alert_recoverable(const dif_aes_t *aes) {
79  return mmio_region_get_bit32(aes->params.base_addr, AES_STATUS_REG_OFFSET,
80  AES_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_BIT);
81 }
82 
83 static void aes_shadowed_write(mmio_region_t base, ptrdiff_t offset,
84  uint32_t value) {
85  mmio_region_write32(base, offset, value);
86  mmio_region_write32(base, offset, value);
87 }
88 
89 static void aes_clear_internal_state(const dif_aes_t *aes) {
90  // Make sure AES is idle before clearing.
91  while (!aes_idle(aes)) {
92  }
93 
94  // It should be fine to clobber the Control register. Only
95  // `AES_CTRL_SHADOWED_MANUAL_OPERATION` bit must be set.
96  uint32_t ctrl_reg =
97  bitfield_bit32_write(0, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
98 
99  aes_shadowed_write(aes->params.base_addr, AES_CTRL_SHADOWED_REG_OFFSET,
100  ctrl_reg);
101 
102  uint32_t trigger_reg =
103  bitfield_bit32_write(0, AES_TRIGGER_KEY_IV_DATA_IN_CLEAR_BIT, true);
104 
105  trigger_reg =
106  bitfield_bit32_write(trigger_reg, AES_TRIGGER_DATA_OUT_CLEAR_BIT, true);
107 
108  mmio_region_write32(aes->params.base_addr, AES_TRIGGER_REG_OFFSET,
109  trigger_reg);
110 
111  // Make sure AES is cleared before proceeding (may take multiple cycles).
112  while (!aes_idle(aes)) {
113  }
114 }
115 
116 static aes_key_field_val_t key_to_field(dif_aes_key_length_t key) {
117  switch (key) {
118  case kDifAesKey128:
119  return kAesKeyFieldVal128;
120  case kDifAesKey192:
121  return kAesKeyFieldVal192;
122  case kDifAesKey256:
123  return kAesKeyFieldVal256;
124  default:
125  return kAesKeyFieldValInvalid;
126  }
127 }
128 
129 /**
130  * Configures AES. Is used by every `dif_aes_start_<mode>` function.
131  *
132  * @param aes AES state data.
133  * @param transaction Configuration data, common across all Cipher modes.
134  * @param cipher_mode_val Cipher Mode register write value.
135  * @return `dif_aes_start_result_t`.
136  */
137 static dif_aes_result_t configure(const dif_aes_t *aes,
138  const dif_aes_transaction_t *transaction,
139  aes_mode_field_val_t cipher_mode_val) {
140  aes_key_field_val_t key_len_val = key_to_field(transaction->key_len);
141  if (key_len_val == kAesKeyFieldValInvalid) {
142  return kDifAesError;
143  }
144 
145  uint32_t reg =
146  bitfield_field32_write(0, AES_CTRL_SHADOWED_KEY_LEN_FIELD, key_len_val);
147 
148  reg = bitfield_field32_write(reg, AES_CTRL_SHADOWED_MODE_FIELD,
149  cipher_mode_val);
150 
151  if (transaction->mode == kDifAesModeDecrypt) {
152  reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_OPERATION_BIT, true);
153  } else {
154  reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_OPERATION_BIT, false);
155  }
156 
157  if (transaction->operation == kDifAesOperationManual) {
158  reg =
159  bitfield_bit32_write(reg, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
160  } else {
161  reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT,
162  false);
163  }
164 
165  if (transaction->masking == kDifAesMaskingForceZero) {
166  reg =
167  bitfield_bit32_write(reg, AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT, true);
168  } else {
169  reg = bitfield_bit32_write(reg, AES_CTRL_SHADOWED_FORCE_ZERO_MASKS_BIT,
170  false);
171  }
172 
173  aes_shadowed_write(aes->params.base_addr, AES_CTRL_SHADOWED_REG_OFFSET, reg);
174 
175  return kDifAesOk;
176 }
177 
178 /**
179  * Sets all "sub-registers" of `aes.KEY`, `aes.IV` or `aes.DATA_IN` multiregs.
180  *
181  * @param aes AES state data.
182  * @param data Data to be written into multi-reg registers.
183  * @param regs_num Number of "sub-registers" in the multireg.
184  * @param reg0_offset Offset to the "sub-register 0" in the multireg.
185  */
186 static void aes_set_multireg(const dif_aes_t *aes, const uint32_t *data,
187  size_t regs_num, ptrdiff_t reg0_offset) {
188  for (int i = 0; i < regs_num; ++i) {
189  ptrdiff_t offset = reg0_offset + (i * sizeof(uint32_t));
190 
191  mmio_region_write32(aes->params.base_addr, offset, data[i]);
192  }
193 }
194 
196  if (aes == NULL) {
197  return kDifAesBadArg;
198  }
199 
200  aes->params = params;
201 
202  return kDifAesOk;
203 }
204 
206  if (aes == NULL) {
207  return kDifAesBadArg;
208  }
209 
210  aes_clear_internal_state(aes);
211 
212  uint32_t reg =
213  bitfield_bit32_write(0, AES_CTRL_SHADOWED_MANUAL_OPERATION_BIT, true);
214 
215  // Any values would do, illegal values chosen here.
216  reg = bitfield_field32_write(reg, AES_CTRL_SHADOWED_MODE_FIELD,
217  AES_CTRL_SHADOWED_MODE_VALUE_AES_NONE);
218 
219  reg =
220  bitfield_field32_write(reg, AES_CTRL_SHADOWED_KEY_LEN_FIELD, 0xffffffff);
221 
222  aes_shadowed_write(aes->params.base_addr, AES_CTRL_SHADOWED_REG_OFFSET, reg);
223 
224  return kDifAesOk;
225 }
226 
228  const dif_aes_transaction_t *transaction,
229  dif_aes_key_share_t key) {
230  if (aes == NULL || transaction == NULL) {
231  return kDifAesBadArg;
232  }
233 
234  if (!aes_idle(aes)) {
235  return kDifAesBusy;
236  }
237 
238  dif_aes_result_t result = configure(aes, transaction, kAesModeFieldValEcb);
239  if (result != kDifAesOk) {
240  return result;
241  }
242 
243  aes_set_multireg(aes, &key.share0[0], AES_KEY_SHARE0_MULTIREG_COUNT,
244  AES_KEY_SHARE0_0_REG_OFFSET);
245 
246  aes_set_multireg(aes, &key.share1[0], AES_KEY_SHARE1_MULTIREG_COUNT,
247  AES_KEY_SHARE1_0_REG_OFFSET);
248 
249  return kDifAesOk;
250 }
251 
253  const dif_aes_transaction_t *transaction,
255  if (aes == NULL || transaction == NULL) {
256  return kDifAesBadArg;
257  }
258 
259  if (!aes_idle(aes)) {
260  return kDifAesBusy;
261  }
262 
263  dif_aes_result_t result = configure(aes, transaction, kAesModeFieldValCbc);
264  if (result != kDifAesOk) {
265  return result;
266  }
267 
268  aes_set_multireg(aes, &key.share0[0], AES_KEY_SHARE0_MULTIREG_COUNT,
269  AES_KEY_SHARE0_0_REG_OFFSET);
270 
271  aes_set_multireg(aes, &key.share1[0], AES_KEY_SHARE1_MULTIREG_COUNT,
272  AES_KEY_SHARE1_0_REG_OFFSET);
273 
274  aes_set_multireg(aes, &iv.iv[0], AES_IV_MULTIREG_COUNT, AES_IV_0_REG_OFFSET);
275 
276  return kDifAesOk;
277 }
278 
280  const dif_aes_transaction_t *transaction,
282  if (aes == NULL || transaction == NULL) {
283  return kDifAesBadArg;
284  }
285 
286  if (!aes_idle(aes)) {
287  return kDifAesBusy;
288  }
289 
290  dif_aes_result_t result = configure(aes, transaction, kAesModeFieldValCtr);
291  if (result != kDifAesOk) {
292  return result;
293  }
294 
295  aes_set_multireg(aes, &key.share0[0], AES_KEY_SHARE0_MULTIREG_COUNT,
296  AES_KEY_SHARE0_0_REG_OFFSET);
297 
298  aes_set_multireg(aes, &key.share1[0], AES_KEY_SHARE1_MULTIREG_COUNT,
299  AES_KEY_SHARE1_0_REG_OFFSET);
300 
301  aes_set_multireg(aes, &iv.iv[0], AES_IV_MULTIREG_COUNT, AES_IV_0_REG_OFFSET);
302 
303  return kDifAesOk;
304 }
305 
307  if (aes == NULL) {
308  return kDifAesBadArg;
309  }
310 
311  if (!aes_idle(aes)) {
312  return kDifAesBusy;
313  }
314 
315  aes_clear_internal_state(aes);
316 
317  return kDifAesOk;
318 }
319 
321  const dif_aes_data_t data) {
322  if (aes == NULL) {
323  return kDifAesBadArg;
324  }
325 
326  if (!aes_input_ready(aes)) {
327  return kDifAesBusy;
328  }
329 
330  aes_set_multireg(aes, &data.data[0], AES_DATA_IN_MULTIREG_COUNT,
331  AES_DATA_IN_0_REG_OFFSET);
332 
333  return kDifAesOk;
334 }
335 
337  dif_aes_data_t *data) {
338  if (aes == NULL || data == NULL) {
339  return kDifAesBadArg;
340  }
341 
342  if (!aes_output_valid(aes)) {
343  return kDifAesOutputInvalid;
344  }
345 
346  for (int i = 0; i < AES_DATA_OUT_MULTIREG_COUNT; ++i) {
347  ptrdiff_t offset = AES_DATA_OUT_0_REG_OFFSET + (i * sizeof(uint32_t));
348 
349  data->data[i] = mmio_region_read32(aes->params.base_addr, offset);
350  }
351 
352  return kDifAesOk;
353 }
354 
356  dif_aes_trigger_t trigger) {
357  if (aes == NULL) {
358  return kDifAesBadArg;
359  }
360 
361  uint32_t reg;
362  switch (trigger) {
363  case kDifAesTriggerStart:
364  reg = bitfield_bit32_write(0, AES_TRIGGER_START_BIT, true);
365  break;
367  reg = bitfield_bit32_write(0, AES_TRIGGER_KEY_IV_DATA_IN_CLEAR_BIT, true);
368  break;
370  reg = bitfield_bit32_write(0, AES_TRIGGER_DATA_OUT_CLEAR_BIT, true);
371  break;
373  reg = bitfield_bit32_write(0, AES_TRIGGER_PRNG_RESEED_BIT, true);
374  break;
375  default:
376  return kDifAesError;
377  }
378 
379  mmio_region_write32(aes->params.base_addr, AES_TRIGGER_REG_OFFSET, reg);
380 
381  return kDifAesOk;
382 }
383 
385  bool *set) {
386  if (aes == NULL || set == NULL) {
387  return kDifAesBadArg;
388  }
389 
390  switch (flag) {
391  case kDifAesStatusIdle:
392  *set = aes_idle(aes);
393  break;
394  case kDifAesStatusStall:
395  *set = aes_stalled(aes);
396  break;
398  *set = aes_output_lost(aes);
399  break;
401  *set = aes_output_valid(aes);
402  break;
404  *set = aes_input_ready(aes);
405  break;
407  *set = aes_alert_fatal(aes);
408  break;
410  *set = aes_alert_recoverable(aes);
411  break;
412  default:
413  return kDifAesError;
414  }
415 
416  return kDifAesOk;
417 }
418 
421  dif_aes_alert_t alert) {
422  if (aes == NULL) {
423  return kDifAesBadArg;
424  }
425 
427  switch (alert) {
428  case kDifAlertFatalFault:
429  index = AES_ALERT_TEST_FATAL_FAULT_BIT;
430  break;
432  index = AES_ALERT_TEST_RECOV_CTRL_UPDATE_ERR_BIT;
433  break;
434  default:
435  return kDifAesError;
436  }
437 
438  uint32_t reg = bitfield_bit32_write(0, index, true);
439  mmio_region_write32(aes->params.base_addr, AES_ALERT_TEST_REG_OFFSET, reg);
440 
441  return kDifAesOk;
442 }