[sw] Add C wrappers for RSA-3072 operations.
Signed-off-by: Jade Philipoom <jadep@google.com>
diff --git a/sw/device/silicon_creator/lib/crypto/rsa_3072/meson.build b/sw/device/silicon_creator/lib/crypto/rsa_3072/meson.build
index 9674ac4..eddb1cf 100644
--- a/sw/device/silicon_creator/lib/crypto/rsa_3072/meson.build
+++ b/sw/device/silicon_creator/lib/crypto/rsa_3072/meson.build
@@ -4,7 +4,8 @@
# Create otbn sources dictionary
sw_lib_crypto_rsa_3072_otbn_sources = {
- 'rsa_3072': files(
+ 'rsa_3072_verify': files(
+ 'rsa_3072_verify.s',
'rsa_3072.s',
),
}
@@ -59,3 +60,17 @@
)
endforeach
+
+# C wrapper for RSA-3072 verify
+sw_silicon_creator_lib_crypto_rsa_3072_verify = declare_dependency(
+ link_with: static_library(
+ 'sw_silicon_creator_lib_crypto_rsa_3072_verify',
+ sources: [
+ 'rsa_3072_verify.c',
+ ],
+ dependencies: [
+ sw_silicon_creator_lib_otbn_util,
+ sw_lib_crypto_rsa_3072_otbn['rsa_3072_verify']['rv32embed_dependency'],
+ ],
+ ),
+)
diff --git a/sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.c b/sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.c
new file mode 100644
index 0000000..bada38a
--- /dev/null
+++ b/sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.c
@@ -0,0 +1,165 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.h"
+
+#include "sw/device/lib/base/hardened.h"
+#include "sw/device/silicon_creator/lib/error.h"
+#include "sw/device/silicon_creator/lib/otbn_util.h"
+
+#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
+
+OTBN_DECLARE_APP_SYMBOLS(rsa_3072_verify); // The OTBN RSA-3072 verify app.
+OTBN_DECLARE_PTR_SYMBOL(rsa_3072_verify, mode); // Mode (precomp or verify).
+OTBN_DECLARE_PTR_SYMBOL(rsa_3072_verify, out_buf); // Output buffer (message).
+OTBN_DECLARE_PTR_SYMBOL(rsa_3072_verify, in_mod); // The RSA modulus (n).
+OTBN_DECLARE_PTR_SYMBOL(rsa_3072_verify, in_buf); // The signature (s).
+OTBN_DECLARE_PTR_SYMBOL(rsa_3072_verify,
+ in_rr); // The Montgomery constant R^2.
+OTBN_DECLARE_PTR_SYMBOL(rsa_3072_verify,
+ in_m0inv); // The Montgomery constant m0_inv.
+
+static const otbn_app_t kOtbnAppRsa = OTBN_APP_T_INIT(rsa_3072_verify);
+static const otbn_ptr_t kOtbnVarRsaMode =
+ OTBN_PTR_T_INIT(rsa_3072_verify, mode);
+static const otbn_ptr_t kOtbnVarRsaOutBuf =
+ OTBN_PTR_T_INIT(rsa_3072_verify, out_buf);
+static const otbn_ptr_t kOtbnVarRsaInMod =
+ OTBN_PTR_T_INIT(rsa_3072_verify, in_mod);
+static const otbn_ptr_t kOtbnVarRsaInBuf =
+ OTBN_PTR_T_INIT(rsa_3072_verify, in_buf);
+static const otbn_ptr_t kOtbnVarRsaInRR =
+ OTBN_PTR_T_INIT(rsa_3072_verify, in_rr);
+static const otbn_ptr_t kOtbnVarRsaInM0Inv =
+ OTBN_PTR_T_INIT(rsa_3072_verify, in_m0inv);
+
+/* Mode is represented by a single word, 1 for precomputation and 2 for verify
+ */
+static const uint32_t kOtbnRsaModeNumWords = 1;
+static const uint32_t kOtbnRsaModePrecomp = 1;
+static const uint32_t kOtbnRsaModeVerify = 2;
+
+/**
+ * Copies a 3072-bit number from the CPU memory to OTBN data memory.
+ *
+ * @param otbn The OTBN context object.
+ * @param src Source of the data to copy.
+ * @param dst Pointer to the destination in OTBN's data memory.
+ * @return The result of the operation.
+ */
+rom_error_t write_rsa_3072_int_to_otbn(otbn_t *otbn, const rsa_3072_int_t *src,
+ otbn_ptr_t dst) {
+ return otbn_copy_data_to_otbn(otbn, kRsa3072NumWords, src->data, dst);
+}
+
+/**
+ * Copies a 3072-bit number from OTBN data memory to CPU memory.
+ *
+ * @param otbn The OTBN context object.
+ * @param src The pointer in OTBN data memory to copy from.
+ * @param dst The destination of the copied data in main memory (preallocated).
+ * @return The result of the operation.
+ */
+rom_error_t read_rsa_3072_int_from_otbn(otbn_t *otbn, const otbn_ptr_t src,
+ rsa_3072_int_t *dst) {
+ return otbn_copy_data_from_otbn(otbn, kRsa3072NumWords, src, dst->data);
+}
+
+// TODO: This implementation waits while OTBN is processing; it should be
+// modified to be non-blocking.
+rom_error_t rsa_3072_precomp(const rsa_3072_public_key_t *public_key,
+ rsa_3072_constants_t *result) {
+ otbn_t otbn;
+
+ // Initialize OTBN and load the RSA app.
+ otbn_init(&otbn);
+ RETURN_IF_ERROR(otbn_load_app(&otbn, kOtbnAppRsa));
+
+ // Set mode to perform precomputation.
+ RETURN_IF_ERROR(otbn_copy_data_to_otbn(
+ &otbn, kOtbnRsaModeNumWords, &kOtbnRsaModePrecomp, kOtbnVarRsaMode));
+
+ // Set the modulus (n).
+ RETURN_IF_ERROR(
+ write_rsa_3072_int_to_otbn(&otbn, &public_key->n, kOtbnVarRsaInMod));
+
+ // Start the OTBN routine.
+ RETURN_IF_ERROR(otbn_execute_app(&otbn));
+
+ // Spin here waiting for OTBN to complete.
+ RETURN_IF_ERROR(otbn_busy_wait_for_done(&otbn));
+
+ // Read precomputed constant rr out of DMEM.
+ RETURN_IF_ERROR(
+ read_rsa_3072_int_from_otbn(&otbn, kOtbnVarRsaInRR, &result->rr));
+
+ // Read precomputed constant m0_inv out of DMEM.
+ RETURN_IF_ERROR(otbn_copy_data_from_otbn(&otbn, kOtbnWideWordNumWords,
+ kOtbnVarRsaInM0Inv, result->m0_inv));
+
+ return kErrorOk;
+}
+
+// TODO: This implementation waits while OTBN is processing; it should be
+// modified to be non-blocking.
+rom_error_t rsa_3072_verify(const rsa_3072_int_t *signature,
+ const rsa_3072_int_t *message,
+ const rsa_3072_public_key_t *public_key,
+ const rsa_3072_constants_t *constants,
+ hardened_bool_t *result) {
+ otbn_t otbn;
+ rsa_3072_int_t recoveredMessage;
+
+ // For now, only the F4 modulus is supported.
+ if (public_key->e != 65537) {
+ return kErrorOtbnInvalidArgument;
+ }
+
+ // TODO: Check that s < n, reject signature otherwise
+
+ // Initialize OTBN and load the RSA app.
+ otbn_init(&otbn);
+ RETURN_IF_ERROR(otbn_load_app(&otbn, kOtbnAppRsa));
+
+ // Set mode to perform verification.
+ RETURN_IF_ERROR(otbn_copy_data_to_otbn(&otbn, kOtbnRsaModeNumWords,
+ &kOtbnRsaModeVerify, kOtbnVarRsaMode));
+
+ // Set the modulus (n).
+ RETURN_IF_ERROR(
+ write_rsa_3072_int_to_otbn(&otbn, &public_key->n, kOtbnVarRsaInMod));
+
+ // Set the signature.
+ RETURN_IF_ERROR(
+ write_rsa_3072_int_to_otbn(&otbn, signature, kOtbnVarRsaInBuf));
+
+ // Set the precomputed constant R^2.
+ RETURN_IF_ERROR(
+ write_rsa_3072_int_to_otbn(&otbn, &constants->rr, kOtbnVarRsaInRR));
+
+ // Set the precomputed constant m0_inv.
+ RETURN_IF_ERROR(otbn_copy_data_to_otbn(
+ &otbn, kOtbnWideWordNumWords, constants->m0_inv, kOtbnVarRsaInM0Inv));
+
+ // Start the OTBN routine.
+ RETURN_IF_ERROR(otbn_execute_app(&otbn));
+
+ // Spin here waiting for OTBN to complete.
+ RETURN_IF_ERROR(otbn_busy_wait_for_done(&otbn));
+
+ // Read recovered message out of OTBN dmem.
+ RETURN_IF_ERROR(
+ read_rsa_3072_int_from_otbn(&otbn, kOtbnVarRsaOutBuf, &recoveredMessage));
+
+ // TODO: harden this memory comparison
+ // Check if recovered message matches expectation
+ *result = kHardenedBoolTrue;
+ for (int i = 0; i < kRsa3072NumWords; i++) {
+ if (recoveredMessage.data[i] != message->data[i]) {
+ *result = kHardenedBoolFalse;
+ }
+ }
+
+ return kErrorOk;
+}
diff --git a/sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.h b/sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.h
new file mode 100644
index 0000000..456b4a2
--- /dev/null
+++ b/sw/device/silicon_creator/lib/crypto/rsa_3072/rsa_3072_verify.h
@@ -0,0 +1,89 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_CRYPTO_RSA_3072_RSA_3072_VERIFY_H_
+#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_CRYPTO_RSA_3072_RSA_3072_VERIFY_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "sw/device/lib/base/hardened.h"
+#include "sw/device/silicon_creator/lib/error.h"
+#include "sw/device/silicon_creator/lib/otbn_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+enum {
+ /* Length of the RSA-3072 modulus is 3072 bits */
+ kRsa3072NumBits = 3072,
+ /* Length of the RSA-3072 modulus in words */
+ kRsa3072NumWords = kRsa3072NumBits / (sizeof(uint32_t) * 8),
+};
+
+/**
+ * A type that holds an element of the RSA-3072 finite field (i.e. a 3072-bit
+ * number).
+ *
+ * This type can be used for RSA-3072 signatures, keys, and intermediate values
+ * during modular exponentiation.
+ */
+typedef struct rsa_3072_int_t {
+ uint32_t data[kRsa3072NumWords];
+} rsa_3072_int_t;
+
+/**
+ * A type that holds an RSA-3072 public key.
+ *
+ * The public key consists of a 3072-bit modulus n and a public exponent e.
+ */
+typedef struct rsa_3072_public_key_t {
+ rsa_3072_int_t n;
+ uint32_t e;
+} rsa_3072_public_key_t;
+
+/**
+ * A type that holds precomputed Montgomery constants for a RSA-3072 public
+ * key.
+ *
+ * The constants are:
+ * rr : (2^3072)^2 mod n
+ * m0_inv : (-(n^(-1))) mod 2^256
+ */
+typedef struct rsa_3072_constants_t {
+ rsa_3072_int_t rr;
+ uint32_t m0_inv[kOtbnWideWordNumWords];
+} rsa_3072_constants_t;
+
+/**
+ * Precomputes Montgomery constants for an RSA-3072 public key.
+ *
+ * @param public_key Key for which to compute constants.
+ * @param result Buffer in which to store output
+ * @return Result of the operation (OK or error).
+ */
+rom_error_t rsa_3072_precomp(const rsa_3072_public_key_t *public_key,
+ rsa_3072_constants_t *result);
+
+/**
+ * Verifies an RSA-3072 signature.
+ *
+ * @param signature Signature to be verified.
+ * @param message Digest of the message to check the signature against.
+ * @param public_key Key to check the signature against.
+ * @param result Buffer in which to store output (true iff signature is valid)
+ * @return Result of the operation (OK or error).
+ */
+rom_error_t rsa_3072_verify(const rsa_3072_int_t *signature,
+ const rsa_3072_int_t *message,
+ const rsa_3072_public_key_t *public_key,
+ const rsa_3072_constants_t *constants,
+ hardened_bool_t *result);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_CRYPTO_RSA_3072_RSA_3072_VERIFY_H_
diff --git a/sw/device/silicon_creator/lib/otbn_util.h b/sw/device/silicon_creator/lib/otbn_util.h
index fddff0a..efb3822 100644
--- a/sw/device/silicon_creator/lib/otbn_util.h
+++ b/sw/device/silicon_creator/lib/otbn_util.h
@@ -16,6 +16,16 @@
#endif
/**
+ * Constants related to OTBN wide words
+ */
+enum {
+ /* Length of an OTBN wide word in bits */
+ kOtbnWideWordNumBits = 256,
+ /* Length of an OTBN wide word in words */
+ kOtbnWideWordNumWords = kOtbnWideWordNumBits / (sizeof(uint32_t) * 8),
+};
+
+/**
* Information about an embedded OTBN application image.
*
* All pointers reference data in the normal CPU address space.