Software APIs
rsa_3072_verify_functest.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 #include "sw/device/lib/crypto/drivers/entropy.h"
7 #include "sw/device/lib/crypto/drivers/otbn.h"
8 #include "sw/device/lib/crypto/impl/rsa/rsa_3072_verify.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
12 
13 // The autogen rule that creates this header creates it in a directory named
14 // after the rule, then manipulates the include path in the
15 // cc_compilation_context to include that directory, so the compiler will find
16 // the version of this file matching the Bazel rule under test.
17 #include "rsa_3072_verify_testvectors.h"
18 
19 status_t rsa_3072_verify_test(const rsa_3072_verify_test_vector_t *testvec) {
20  // Encode message
21  rsa_3072_int_t encodedMessage;
22  CHECK_STATUS_OK(
23  rsa_3072_encode_sha256(testvec->msg, testvec->msgLen, &encodedMessage));
24 
25  // Precompute Montgomery constants
26  rsa_3072_constants_t constants;
27  TRY(rsa_3072_compute_constants(&testvec->publicKey, &constants));
28 
29  // Attempt to verify signature
30  hardened_bool_t result;
31  status_t err = rsa_3072_verify(&testvec->signature, &encodedMessage,
32  &testvec->publicKey, &constants, &result);
33 
34  if (testvec->valid) {
35  // Return the error value if not OK.
36  TRY(err);
37  // Check result.
38  if (result != kHardenedBoolTrue) {
39  LOG_ERROR("Valid signature failed verification.");
40  return OTCRYPTO_RECOV_ERR;
41  }
42  } else {
43  // Signature is expected to be invalid.
44  if (result != kHardenedBoolFalse) {
45  LOG_ERROR("Invalid signature passed verification.");
46  return OTCRYPTO_RECOV_ERR;
47  }
48  // Error code may be OK or BAD_ARGS, but other errors indicate a problem.
49  if (!status_ok(err) && err.value != kOtcryptoStatusValueBadArgs) {
50  LOG_ERROR("Unexpected error on invalid signature: %r.", err);
51  return err;
52  }
53  }
54 
55  return OTCRYPTO_OK;
56 }
57 
58 OTTF_DEFINE_TEST_CONFIG();
59 
60 bool test_main(void) {
61  // Stays true only if all tests pass.
62  bool result = true;
63 
64  // Set entropy complex to auto mode.
65  CHECK_STATUS_OK(entropy_complex_init());
66 
67  // The definition of `RULE_NAME` comes from the autogen Bazel rule.
68  LOG_INFO("Starting rsa_3072_verify_test:%s", RULE_NAME);
69  for (uint32_t i = 0; i < RSA_3072_VERIFY_NUM_TESTS; i++) {
70  LOG_INFO("Starting rsa_3072_verify_test on test vector %d of %d...", i + 1,
71  RSA_3072_VERIFY_NUM_TESTS);
72 
73  // Extract test vector and check for unsupported exponents (e.g. 3); these
74  // signatures are expected to fail verification, so mark them invalid.
75  rsa_3072_verify_test_vector_t testvec = rsa_3072_verify_tests[i];
76  if (testvec.publicKey.e != 65537) {
77  testvec.valid = false;
78  }
79 
80  // Run test and print out result.
81  status_t err = rsa_3072_verify_test(&testvec);
82  if (status_ok(err)) {
83  LOG_INFO("Finished rsa_3072_verify_test on test vector %d : ok", i + 1);
84  } else {
85  LOG_ERROR("Finished rsa_3072_verify_test on test vector %d : error %r",
86  i + 1, err);
87  // For help with debugging, print the OTBN error bits, instruction
88  // count, and test vector notes.
89  LOG_INFO("OTBN error bits: 0x%08x", otbn_err_bits_get());
90  LOG_INFO("OTBN instruction count: 0x%08x", otbn_instruction_count_get());
91  LOG_INFO("Test notes: %s", testvec.comment);
92  result = false;
93  }
94  }
95  LOG_INFO("Finished rsa_3072_verify_test:%s", RULE_NAME);
96 
97  return result;
98 }