Software APIs
wots_test.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 
5 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/wots.h"
6 
7 #include <stdint.h>
8 
11 #include "sw/device/lib/testing/test_framework/check.h"
13 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/hash.h"
14 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/params.h"
15 #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/thash.h"
16 
17 OTTF_DEFINE_TEST_CONFIG();
18 
19 enum {
20  kSpxWotsMsgBytes = ((kSpxWotsLen1 * kSpxWotsLogW + 7) / 8),
21  kSpxWotsMsgWords =
22  (kSpxWotsMsgBytes + sizeof(uint32_t) - 1) / sizeof(uint32_t),
23 };
24 
25 // Test signature, message, and address. Populate before running test.
26 static uint32_t kTestSig[kSpxWotsWords] = {0};
27 static uint32_t kTestMsg[kSpxWotsMsgWords] = {0};
28 static spx_addr_t kTestAddr = {.addr = {0}};
29 
30 // Test context.
31 static spx_ctx_t kTestCtx = {
32  .pub_seed =
33  {
34  0xf3f2f1f0,
35  0xf7f6f5f4,
36  0xfbfaf9f8,
37  0xfffefdfc,
38  },
39 };
40 
41 // Test data generated with a third-party implementation of SPHINCS+.
42 static uint32_t kExpectedLeaf[kSpxNWords] = {0x14199738, 0x8d0ae722, 0x27ba271f,
43  0x94194a62};
44 
46 static rom_error_t pk_from_sig_test(void) {
47  RETURN_IF_ERROR(spx_hash_initialize(&kTestCtx));
48 
49  // Extract the public key from the signature.
50  uint32_t wots_pk[kSpxWotsPkWords];
51  wots_pk_from_sig(kTestSig, kTestMsg, &kTestCtx, &kTestAddr, wots_pk);
52 
53  // Compute the leaf node using `thash`. This is the next step in the
54  // verification procedure and FIPS 205 combines it into the same algorithm as
55  // `wots_pk_from_sig`; mostly this lets us have a shorter value to check.
56  spx_addr_t wots_pk_addr = {.addr = {0}};
57  spx_addr_type_set(&wots_pk_addr, kSpxAddrTypeWotsPk);
58  spx_addr_keypair_copy(&wots_pk_addr, &kTestAddr);
59  uint32_t actual_leaf[kSpxNWords];
60  thash(wots_pk, kSpxWotsLen, &kTestCtx, &wots_pk_addr, actual_leaf);
61 
62  // Check results.
63  CHECK_ARRAYS_EQ(actual_leaf, kExpectedLeaf, ARRAYSIZE(kExpectedLeaf));
64 
65  return kErrorOk;
66 }
67 
68 bool test_main(void) {
69  status_t result = OK_STATUS();
70 
71  // Populate signature with {0, 1, 2, 3, ... }.
72  unsigned char *test_sig_bytes = (unsigned char *)kTestSig;
73  for (size_t i = 0; i < kSpxWotsBytes; i++) {
74  test_sig_bytes[i] = i & 255;
75  }
76 
77  // Populate message with { ..., 3, 2, 1, 0}.
78  unsigned char *test_msg_bytes = (unsigned char *)kTestMsg;
79  for (size_t i = 0; i < kSpxWotsMsgBytes; i++) {
80  test_msg_bytes[i] = (kSpxWotsMsgBytes - i) & 255;
81  }
82 
83  // Populate address.
84  spx_addr_layer_set(&kTestAddr, 0xa3);
85  spx_addr_tree_set(&kTestAddr, 0xafaeadacabaaa9a8);
86  spx_addr_type_set(&kTestAddr, kSpxAddrTypeWots);
87  spx_addr_keypair_set(&kTestAddr, 0xb4b5b6b7);
88 
89  EXECUTE_TEST(result, pk_from_sig_test);
90 
91  return status_ok(result);
92 }