Skip to content

Commit

Permalink
[crypto] Factor out OTBN RSA testing utilities.
Browse files Browse the repository at this point in the history
Use the same testing library for otbn_rsa_test and
power_virus_systemtest. The testing library bypasses everything other
than the core OTBN operation, which is helpful for tests that may have
other blocks in different configurations than the cryptolib expects
(e.g. entropy or HMAC).

Signed-off-by: Jade Philipoom <[email protected]>
  • Loading branch information
jadephilipoom committed Jan 8, 2024
1 parent 87873f7 commit 5bcd7d0
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 136 deletions.
13 changes: 13 additions & 0 deletions sw/device/lib/testing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,19 @@ cc_library(
],
)

cc_library(
name = "otbn_testutils_rsa",
srcs = ["otbn_testutils_rsa.c"],
hdrs = ["otbn_testutils_rsa.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
":otbn_testutils",
"//sw/device/lib/base:status",
"//sw/device/lib/dif:otbn",
"//sw/otbn/crypto:rsa",
],
)

cc_library(
name = "otp_ctrl_testutils",
srcs = ["otp_ctrl_testutils.c"],
Expand Down
117 changes: 117 additions & 0 deletions sw/device/lib/testing/otbn_testutils_rsa.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/testing/otbn_testutils_rsa.h"

#include "sw/device/lib/base/status.h"
#include "sw/device/lib/dif/dif_otbn.h"
#include "sw/device/lib/testing/otbn_testutils.h"

OTBN_DECLARE_APP_SYMBOLS(rsa);
OTBN_DECLARE_SYMBOL_ADDR(rsa, mode);
OTBN_DECLARE_SYMBOL_ADDR(rsa, n_limbs);
OTBN_DECLARE_SYMBOL_ADDR(rsa, inout);
OTBN_DECLARE_SYMBOL_ADDR(rsa, modulus);
OTBN_DECLARE_SYMBOL_ADDR(rsa, exp);

static const otbn_app_t kOtbnAppRsa = OTBN_APP_T_INIT(rsa);
static const otbn_addr_t kOtbnVarRsaMode = OTBN_ADDR_T_INIT(rsa, mode);
static const otbn_addr_t kOtbnVarRsaNLimbs = OTBN_ADDR_T_INIT(rsa, n_limbs);
static const otbn_addr_t kOtbnVarRsaInOut = OTBN_ADDR_T_INIT(rsa, inout);
static const otbn_addr_t kOtbnVarRsaModulus = OTBN_ADDR_T_INIT(rsa, modulus);
static const otbn_addr_t kOtbnVarRsaExp = OTBN_ADDR_T_INIT(rsa, exp);

enum {
kOtbnWideWordBytes = 256 / 8,
kModeEncrypt = 1,
kModeDecrypt = 2,
};

status_t otbn_testutils_rsa_load(dif_otbn_t *otbn) {
if (otbn == NULL) {
return INVALID_ARGUMENT();
}
return otbn_testutils_load_app(otbn, kOtbnAppRsa);
}

status_t otbn_testutils_rsa_modexp_f4_start(dif_otbn_t *otbn,
const uint8_t *modulus,
const uint8_t *in,
size_t size_bytes) {
if (otbn == NULL || size_bytes % kOtbnWideWordBytes != 0) {
return INVALID_ARGUMENT();
}

uint32_t n_limbs = size_bytes / kOtbnWideWordBytes;
if (n_limbs == 0 || n_limbs > 16) {
return INVALID_ARGUMENT();
}

// Write input arguments.
uint32_t mode = kModeEncrypt;
TRY(otbn_testutils_write_data(otbn, sizeof(uint32_t), &mode,
kOtbnVarRsaMode));
TRY(otbn_testutils_write_data(otbn, sizeof(uint32_t), &n_limbs,
kOtbnVarRsaNLimbs));
TRY(otbn_testutils_write_data(otbn, size_bytes, modulus, kOtbnVarRsaModulus));
TRY(otbn_testutils_write_data(otbn, size_bytes, in, kOtbnVarRsaInOut));

// Call OTBN to start the operation.
return otbn_testutils_execute(otbn);
}

status_t otbn_testutils_rsa_modexp_consttime_start(
dif_otbn_t *otbn, const uint8_t *modulus, const uint8_t *private_exponent,
const uint8_t *in, size_t size_bytes) {
if (otbn == NULL || size_bytes % kOtbnWideWordBytes != 0) {
return INVALID_ARGUMENT();
}

uint32_t n_limbs = size_bytes / kOtbnWideWordBytes;
if (n_limbs == 0 || n_limbs > 16) {
return INVALID_ARGUMENT();
}

// Write input arguments.
uint32_t mode = kModeDecrypt;
TRY(otbn_testutils_write_data(otbn, sizeof(mode), &mode, kOtbnVarRsaMode));
TRY(otbn_testutils_write_data(otbn, sizeof(n_limbs), &n_limbs,
kOtbnVarRsaNLimbs));
TRY(otbn_testutils_write_data(otbn, size_bytes, modulus, kOtbnVarRsaModulus));
TRY(otbn_testutils_write_data(otbn, size_bytes, private_exponent,
kOtbnVarRsaExp));
TRY(otbn_testutils_write_data(otbn, size_bytes, in, kOtbnVarRsaInOut));

// Call OTBN to start the operation.
return otbn_testutils_execute(otbn);
}

static status_t modexp_finalize(dif_otbn_t *otbn, uint8_t *out,
size_t size_bytes) {
if (otbn == NULL || size_bytes % kOtbnWideWordBytes != 0) {
return INVALID_ARGUMENT();
}

uint32_t n_limbs = size_bytes / kOtbnWideWordBytes;
if (n_limbs == 0 || n_limbs > 16) {
return INVALID_ARGUMENT();
}

// Wait for OTBN to complete.
TRY(otbn_testutils_wait_for_done(otbn, kDifOtbnErrBitsNoError));

// Read back results.
return otbn_testutils_read_data(otbn, size_bytes, kOtbnVarRsaInOut, out);
}

status_t otbn_testutils_rsa_modexp_f4_finalize(dif_otbn_t *otbn, uint8_t *out,
size_t size_bytes) {
return modexp_finalize(otbn, out, size_bytes);
}

status_t otbn_testutils_rsa_modexp_consttime_finalize(dif_otbn_t *otbn,
uint8_t *out,
size_t size_bytes) {
return modexp_finalize(otbn, out, size_bytes);
}
100 changes: 100 additions & 0 deletions sw/device/lib/testing/otbn_testutils_rsa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// 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_LIB_TESTING_OTBN_TESTUTILS_RSA_H_
#define OPENTITAN_SW_DEVICE_LIB_TESTING_OTBN_TESTUTILS_RSA_H_

#include "sw/device/lib/base/status.h"
#include "sw/device/lib/dif/dif_otbn.h"

/**
* @file Run RSA on OTBN as a testing tool.
* @brief This library is based on the DIF instead of a full OTBN driver, and
* should be used for testing only. The library does not include message
* hashing or encoding.
*/

/**
* Load the RSA application into OTBN.
*
* @param otbn The OTBN context object.
*/
status_t otbn_testutils_rsa_load(dif_otbn_t *otbn);

/**
* Start running modular exponentiation with the exponent 65537.
*
* Computes (in^65537) mod n. This corresponds to the core step in encryption
* or signature verification, and is much faster than a general modular
* exponentiation. 65537 is also called "F4" because it is the 4th Fermat
* number (2^16 + 1).
*
* The RSA app should be loaded into OTBN with `otbn_testutils_rsa_load` before
* calling this function.
*
* @param otbn The OTBN context object.
* @param modulus The modulus (n).
* @param in The plaintext message.
* @param size_bytes The size of all buffers in bytes, i.e. the key/modulus
* length (i.e. 128 for RSA 1024). Valid range: 32..512 in
* 32 byte-steps (i.e. RSA 256 to RSA 4096).
*/
status_t otbn_testutils_rsa_modexp_f4_start(dif_otbn_t *otbn,
const uint8_t *modulus,
const uint8_t *in,
size_t size_bytes);

/**
* Finish modular exponentiation with the exponent 65537.
*
* Waits for OTBN to complete and reads back the result of modular
* exponentiation. Call only after `otbn_testutils_rsa_modexp_f4_start`.
*
* @param otbn The OTBN context object.
* @param out The encrypted message.
* @param size_bytes The size of all buffers in bytes, i.e. the key/modulus
* length (i.e. 128 for RSA 1024). Valid range: 32..512 in
* 32 byte-steps (i.e. RSA 256 to RSA 4096).
*/
status_t otbn_testutils_rsa_modexp_f4_finalize(dif_otbn_t *otbn, uint8_t *out,
size_t size_bytes);

/**
* Start a constant-time modular exponentiation.
*
* Computes (in^d) mod n. This corresponds to the core step in decryption or
* signature generation and can be very slow.
*
* The RSA app should be loaded into OTBN with `otbn_testutils_rsa_load` before
* calling this function.
*
* @param otbn The OTBN context object.
* @param modulus The modulus (n).
* @param private_exponent The private exponent (d).
* @param in The encrypted message.
* @param out The decrypted (plaintext) message.
* @param size_bytes The size of all buffers in bytes, i.e. the key/modulus
* length (i.e. 128 for RSA 1024). Valid range: 32..512 in
* 32 byte-steps (i.e. RSA 256 to RSA 4096).
*/
status_t otbn_testutils_rsa_modexp_consttime_start(
dif_otbn_t *otbn, const uint8_t *modulus, const uint8_t *private_exponent,
const uint8_t *in, size_t size_bytes);
/**
* Finish modular exponentiation with the exponent 65537.
*
* Waits for OTBN to complete and reads back the result of modular
* exponentiation. Call only after `otbn_testutils_rsa_modexp_consttime_start`.
*
* @param otbn The OTBN context object.
* @param out The encrypted message.
* @param size_bytes The size of all buffers in bytes, i.e. the key/modulus
* length (i.e. 128 for RSA 1024). Valid range: 32..512 in
* 32 byte-steps (i.e. RSA 256 to RSA 4096).
*/
status_t otbn_testutils_rsa_modexp_consttime_finalize(dif_otbn_t *otbn,
uint8_t *out,
size_t size_bytes);

#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_OTBN_TESTUTILS_RSA_H_
7 changes: 2 additions & 5 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2223,10 +2223,9 @@ opentitan_test(
"//sw/device/lib/runtime:ibex",
"//sw/device/lib/runtime:log",
"//sw/device/lib/testing:entropy_testutils",
"//sw/device/lib/testing:otbn_testutils",
"//sw/device/lib/testing:otbn_testutils_rsa",
"//sw/device/lib/testing:profile",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/otbn/crypto:rsa",
],
)

Expand Down Expand Up @@ -3714,8 +3713,6 @@ opentitan_test(
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/base:math",
"//sw/device/lib/base:multibits",
"//sw/device/lib/crypto/drivers:otbn",
"//sw/device/lib/crypto/impl/rsa:rsa_3072_verify",
"//sw/device/lib/dif:adc_ctrl",
"//sw/device/lib/dif:aes",
"//sw/device/lib/dif:csrng",
Expand All @@ -3740,11 +3737,11 @@ opentitan_test(
"//sw/device/lib/testing:entropy_testutils",
"//sw/device/lib/testing:hmac_testutils",
"//sw/device/lib/testing:i2c_testutils",
"//sw/device/lib/testing:otbn_testutils_rsa",
"//sw/device/lib/testing:pinmux_testutils",
"//sw/device/lib/testing:spi_device_testutils",
"//sw/device/lib/testing/test_framework:check",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/tests/crypto:rsa_3072_verify_testvectors_hardcoded_header",
],
)

Expand Down
Loading

0 comments on commit 5bcd7d0

Please sign in to comment.