Software APIs
hmac_sha256_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 
5 #include "sw/device/lib/crypto/drivers/entropy.h"
6 #include "sw/device/lib/crypto/impl/integrity.h"
7 #include "sw/device/lib/crypto/impl/keyblob.h"
11 #include "sw/device/lib/testing/test_framework/check.h"
13 
14 enum {
15  /**
16  * HMAC-SHA256 tag length (256 bits) in words.
17  */
18  kTagLenWords = 256 / 32,
19 };
20 
21 // 256-bit test key (big endian) =
22 // 0x1bff10eaa5b9b204d6f3232a573e8e51a27b68c319366deaf26b91b0712f7a34
23 static const uint32_t kBasicTestKey[] = {
24  0xea10ff1b, 0x04b2b9a5, 0x2a23f3d6, 0x518e3e57,
25  0xc3687ba2, 0xea6d3619, 0xb0916bf2, 0x347a2f71,
26 };
27 
28 // Long test key, 544 bits (big endian) =
29 // 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243
30 static const uint32_t kLongTestKey[] = {
31  0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514,
32  0x1b1a1918, 0x1f1e1d1c, 0x23222120, 0x27262524, 0x2b2a2928, 0x2f2e2d2c,
33  0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, 0x43424140,
34 };
35 
36 // Random value for masking, as large as the longest test key. This value
37 // should not affect the result.
38 static const uint32_t kTestMask[ARRAYSIZE(kLongTestKey)] = {
39  0x8cb847c3, 0xc6d34f36, 0x72edbf7b, 0x9bc0317f, 0x8f003c7f, 0x1d7ba049,
40  0xfd463b63, 0xbb720c44, 0x784c215e, 0xeb101d65, 0x35beb911, 0xab481345,
41  0xa7ebc3e3, 0x04b2a1b9, 0x764a9630, 0x78b8f9c5, 0x3f2a1d8e,
42 };
43 
44 /**
45  * Call the `otcrypto_mac` API and check the resulting tag.
46  *
47  * @param key Key material.
48  * @param key_num_words Key length in bytes.
49  * @param msg Input message.
50  * @param exp_tag Expected tag (256 bits).
51  * @return Result (OK or error).
52  */
53 static status_t run_test(const uint32_t *key, size_t key_len,
55  const uint32_t *exp_tag) {
56  // Construct blinded key.
57  otcrypto_key_config_t config = {
58  .version = kOtcryptoLibVersion1,
59  .key_mode = kOtcryptoKeyModeHmacSha256,
60  .key_length = key_len,
61  .hw_backed = kHardenedBoolFalse,
62  .exportable = kHardenedBoolFalse,
63  .security_level = kOtcryptoKeySecurityLevelLow,
64  };
65 
66  uint32_t keyblob[keyblob_num_words(config)];
67  TRY(keyblob_from_key_and_mask(key, kTestMask, config, keyblob));
68  otcrypto_blinded_key_t blinded_key = {
69  .config = config,
70  .keyblob = keyblob,
71  .keyblob_length = sizeof(keyblob),
72  .checksum = 0,
73  };
74  blinded_key.checksum = integrity_blinded_checksum(&blinded_key);
75 
76  uint32_t act_tag[kTagLenWords];
77  otcrypto_word32_buf_t tag_buf = {
78  .data = act_tag,
79  .len = ARRAYSIZE(act_tag),
80  };
81 
82  TRY(otcrypto_hmac(&blinded_key, msg, tag_buf));
83  TRY_CHECK_ARRAYS_EQ(act_tag, exp_tag, kTagLenWords);
84  return OK_STATUS();
85 }
86 
87 /**
88  * Simple test with a short message.
89  *
90  * HMAC-SHA256(kBasicTestKey, 'Test message.')
91  * = 0xb4595b02be2a1638893166366656ece12b749b95a2815e52d687535309f3126f
92  */
93 static status_t simple_test(void) {
94  const char plaintext[] = "Test message.";
95  otcrypto_const_byte_buf_t msg_buf = {
96  .data = (unsigned char *)plaintext,
97  .len = sizeof(plaintext) - 1,
98  };
99  const uint32_t exp_tag[] = {
100  0x025b59b4, 0x38162abe, 0x36663189, 0xe1ec5666,
101  0x959b742b, 0x525e81a2, 0x535387d6, 0x6f12f309,
102  };
103  return run_test(kBasicTestKey, sizeof(kBasicTestKey), msg_buf, exp_tag);
104 }
105 
106 /**
107  * Test with an empty message.
108  *
109  * HMAC-SHA256(kBasicTestKey, '')
110  * = 0xa9425cbb40d13a0e07916761c06c4aa37969305361508afae62e8bbca5c099a4
111  */
112 static status_t empty_test(void) {
113  const uint32_t exp_tag[] = {
114  0xbb5c42a9, 0x0e3ad140, 0x61679107, 0xa34a6cc0,
115  0x53306979, 0xfa8a5061, 0xbc8b2ee6, 0xa499c0a5,
116  };
117  otcrypto_const_byte_buf_t msg_buf = {
118  .data = NULL,
119  .len = 0,
120  };
121  return run_test(kBasicTestKey, sizeof(kBasicTestKey), msg_buf, exp_tag);
122 }
123 
124 /**
125  * Test using a long key.
126  *
127  * HMAC-SHA256(kLongTestKey, 'Test message.')
128  * = 0x6fab77a49de1fa73dfa97f4f36b956d552afd11d77f584cd8c5c8332d32a6836
129  */
130 static status_t long_key_test(void) {
131  const char plaintext[] = "Test message.";
132  otcrypto_const_byte_buf_t msg_buf = {
133  .data = (unsigned char *)plaintext,
134  .len = sizeof(plaintext) - 1,
135  };
136  const uint32_t exp_tag[] = {
137  0xa477ab6f, 0x73fae19d, 0x4f7fa9df, 0xd556b936,
138  0x1dd1af52, 0xcd84f577, 0x32835c8c, 0x36682ad3,
139  };
140  return run_test(kLongTestKey, sizeof(kLongTestKey), msg_buf, exp_tag);
141 }
142 
143 OTTF_DEFINE_TEST_CONFIG();
144 
145 // Holds the test result.
146 static volatile status_t test_result;
147 
148 bool test_main(void) {
149  test_result = OK_STATUS();
150  CHECK_STATUS_OK(entropy_complex_init());
151  EXECUTE_TEST(test_result, simple_test);
152  EXECUTE_TEST(test_result, empty_test);
153  EXECUTE_TEST(test_result, long_key_test);
154  return status_ok(test_result);
155 }