[dif] Implement the AES OFB and CFB modes on the DIF API

Signed-off-by: Douglas Reis <doreis@lowrisc.org>
diff --git a/sw/device/lib/dif/dif_aes.c b/sw/device/lib/dif/dif_aes.c
index 7958a95..fc2b519 100644
--- a/sw/device/lib/dif/dif_aes.c
+++ b/sw/device/lib/dif/dif_aes.c
@@ -291,6 +291,60 @@
   return kDifOk;
 }
 
+dif_result_t dif_aes_start_ofb(const dif_aes_t *aes,
+                               const dif_aes_transaction_t *transaction,
+                               dif_aes_key_share_t key, dif_aes_iv_t iv) {
+  if (aes == NULL || transaction == NULL) {
+    return kDifBadArg;
+  }
+
+  if (!aes_idle(aes)) {
+    return kDifUnavailable;
+  }
+
+  dif_result_t result = configure(aes, transaction, kAesModeFieldValOfb);
+  if (result != kDifOk) {
+    return result;
+  }
+
+  aes_set_multireg(aes, &key.share0[0], AES_KEY_SHARE0_MULTIREG_COUNT,
+                   AES_KEY_SHARE0_0_REG_OFFSET);
+
+  aes_set_multireg(aes, &key.share1[0], AES_KEY_SHARE1_MULTIREG_COUNT,
+                   AES_KEY_SHARE1_0_REG_OFFSET);
+
+  aes_set_multireg(aes, &iv.iv[0], AES_IV_MULTIREG_COUNT, AES_IV_0_REG_OFFSET);
+
+  return kDifOk;
+}
+
+dif_result_t dif_aes_start_cfb(const dif_aes_t *aes,
+                               const dif_aes_transaction_t *transaction,
+                               dif_aes_key_share_t key, dif_aes_iv_t iv) {
+  if (aes == NULL || transaction == NULL) {
+    return kDifBadArg;
+  }
+
+  if (!aes_idle(aes)) {
+    return kDifUnavailable;
+  }
+
+  dif_result_t result = configure(aes, transaction, kAesModeFieldValCfb);
+  if (result != kDifOk) {
+    return result;
+  }
+
+  aes_set_multireg(aes, &key.share0[0], AES_KEY_SHARE0_MULTIREG_COUNT,
+                   AES_KEY_SHARE0_0_REG_OFFSET);
+
+  aes_set_multireg(aes, &key.share1[0], AES_KEY_SHARE1_MULTIREG_COUNT,
+                   AES_KEY_SHARE1_0_REG_OFFSET);
+
+  aes_set_multireg(aes, &iv.iv[0], AES_IV_MULTIREG_COUNT, AES_IV_0_REG_OFFSET);
+
+  return kDifOk;
+}
+
 dif_result_t dif_aes_end(const dif_aes_t *aes) {
   if (aes == NULL) {
     return kDifBadArg;
diff --git a/sw/device/lib/dif/dif_aes.h b/sw/device/lib/dif/dif_aes.h
index e1d4b0b..65e767c 100644
--- a/sw/device/lib/dif/dif_aes.h
+++ b/sw/device/lib/dif/dif_aes.h
@@ -245,6 +245,59 @@
                                dif_aes_key_share_t key, dif_aes_iv_t iv);
 
 /**
+ * Begins an AES transaction in OFB mode.
+ *
+ * In OFB cipher mode, the same key can be used for all messages, and the
+ * Initialization Vector (IV) need NOT be unpredictable. The following
+ * conditions must be true:
+ *     OFB mode requires a unique initialization vector for every message that
+ *     is ever encrypted under a given key, across all messages.
+ *
+ * With key length less than 256 bits, the excess portion of the `key` can be
+ * written with any data (preferably random).
+ *
+ * The peripheral must be in IDLE state for this operation to take effect, and
+ * will return `kDifAesStartBusy` if this condition is not met.
+ *
+ * @param aes AES state data.
+ * @param transaction Configuration data.
+ * @param key Masked AES key.
+ * @param iv AES Initialization vector.
+ * @return The result of the operation.
+ */
+OT_WARN_UNUSED_RESULT
+dif_result_t dif_aes_start_ofb(const dif_aes_t *aes,
+                               const dif_aes_transaction_t *transaction,
+                               dif_aes_key_share_t key, dif_aes_iv_t iv);
+
+/**
+ * Begins an AES transaction in CFB mode.
+ *
+ * In CFB cipher mode, the same key can be used for all messages, however
+ * new Initialisation Vector (IV) must be generated for any new message. The
+ * following condition must be true:
+ *     The IV must be unpredictable (it must not be possible to predict the IV
+ *     that will be associated to the plaintext in advance of the generation of
+ *     the IV).
+ *
+ * With key length less than 256 bits, the excess portion of the `key` can be
+ * written with any data (preferably random).
+ *
+ * The peripheral must be in IDLE state for this operation to take effect, and
+ * will return `kDifAesStartBusy` if this condition is not met.
+ *
+ * @param aes AES state data.
+ * @param transaction Configuration data.
+ * @param key Masked AES key.
+ * @param iv AES Initialization vector.
+ * @return The result of the operation.
+ */
+OT_WARN_UNUSED_RESULT
+dif_result_t dif_aes_start_cfb(const dif_aes_t *aes,
+                               const dif_aes_transaction_t *transaction,
+                               dif_aes_key_share_t key, dif_aes_iv_t iv);
+
+/**
  * Ends an AES transaction.
  *
  * This function must be called at the end of every `dif_aes_<mode>_start`