Software APIs
hmac_sha512_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-SHA512 tag length (512 bits) in words.
17  */
18  kTagLenWords = 512 / 32,
19 };
20 
21 // Randomly generated 512-bit test key (big endian) =
22 // 0xba79877bb2027c689bef5c69567ca099977928d90a82c05c5d18c39967d4099f64b9f8d7dd192cd6e5902fb599fb601a6879ecb0fdb081bf1b75a4c1ed8865a4
23 static const uint32_t kBasicTestKey[] = {
24  0x7b8779ba, 0x687c02b2, 0x695cef9b, 0x99a07c56, 0xd9287997, 0x5cc0820a,
25  0x99c3185d, 0x9f09d467, 0xd7f8b964, 0xd62c19dd, 0xb52f90e5, 0x1a60fb99,
26  0xb0ec7968, 0xbf81b0fd, 0xc1a4751b, 0xa46588ed,
27 
28 };
29 
30 // Test key longer than the message block size, 1088 bits (big endian) =
31 // 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243
32 static const uint32_t kLongTestKey[] = {
33  0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514,
34  0x1b1a1918, 0x1f1e1d1c, 0x23222120, 0x27262524, 0x2b2a2928, 0x2f2e2d2c,
35  0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, 0x43424140, 0x03020100,
36  0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918,
37  0x1f1e1d1c, 0x23222120, 0x27262524, 0x2b2a2928, 0x2f2e2d2c, 0x33323130,
38  0x37363534, 0x3b3a3938, 0x3f3e3d3c, 0x43424140,
39 };
40 
41 // Random value for masking, as large as the longest test key. This value
42 // should not affect the result.
43 static const uint32_t kTestMask[ARRAYSIZE(kLongTestKey)] = {
44  0x8cb847c3, 0xc6d34f36, 0x72edbf7b, 0x9bc0317f, 0x8f003c7f, 0x1d7ba049,
45  0xfd463b63, 0xbb720c44, 0x784c215e, 0xeb101d65, 0x35beb911, 0xab481345,
46  0xa7ebc3e3, 0x04b2a1b9, 0x764a9630, 0x78b8f9c5, 0x3f2a1d8e, 0x8cb847c3,
47  0xc6d34f36, 0x72edbf7b, 0x9bc0317f, 0x8f003c7f, 0x1d7ba049, 0xfd463b63,
48  0xbb720c44, 0x784c215e, 0xeb101d65, 0x35beb911, 0xab481345, 0xa7ebc3e3,
49  0x04b2a1b9, 0x764a9630, 0x78b8f9c5, 0x3f2a1d8e,
50 };
51 
52 /**
53  * Call the `otcrypto_mac` API and check the resulting tag.
54  *
55  * @param key Key material.
56  * @param key_num_words Key length in bytes.
57  * @param msg Input message.
58  * @param exp_tag Expected tag.
59  * @return Result (OK or error).
60  */
61 static status_t run_test(const uint32_t *key, size_t key_len,
63  const uint32_t *exp_tag) {
64  // Construct blinded key.
65  otcrypto_key_config_t config = {
66  .version = kOtcryptoLibVersion1,
67  .key_mode = kOtcryptoKeyModeHmacSha512,
68  .key_length = key_len,
69  .hw_backed = kHardenedBoolFalse,
70  .exportable = kHardenedBoolFalse,
71  .security_level = kOtcryptoKeySecurityLevelLow,
72  };
73 
74  uint32_t keyblob[keyblob_num_words(config)];
75  TRY(keyblob_from_key_and_mask(key, kTestMask, config, keyblob));
76  otcrypto_blinded_key_t blinded_key = {
77  .config = config,
78  .keyblob = keyblob,
79  .keyblob_length = sizeof(keyblob),
80  .checksum = 0,
81  };
82  blinded_key.checksum = integrity_blinded_checksum(&blinded_key);
83 
84  uint32_t act_tag[kTagLenWords];
85  otcrypto_word32_buf_t tag_buf = {
86  .data = act_tag,
87  .len = ARRAYSIZE(act_tag),
88  };
89 
90  TRY(otcrypto_hmac(&blinded_key, msg, tag_buf));
91  TRY_CHECK_ARRAYS_EQ(act_tag, exp_tag, kTagLenWords);
92  return OK_STATUS();
93 }
94 
95 /**
96  * Simple test with a short message.
97  *
98  * HMAC-SHA512(kBasicTestKey, 'Test message.')
99  * =
100  * 0xa574367b4c84120c0bef3a2e0c5675b86fe0f21f980cc82cfe21b63442d3d12a2d33377a6471d9167eb9b3155543273bac2146e26208c95dc3490727417802ba
101  */
102 static status_t simple_test(void) {
103  const char plaintext[] = "Test message.";
104  otcrypto_const_byte_buf_t msg_buf = {
105  .data = (unsigned char *)plaintext,
106  .len = sizeof(plaintext) - 1,
107  };
108  const uint32_t exp_tag[] = {
109  0x7b3674a5, 0x0c12844c, 0x2e3aef0b, 0xb875560c, 0x1ff2e06f, 0x2cc80c98,
110  0x34b621fe, 0x2ad1d342, 0x7a37332d, 0x16d97164, 0x15b3b97e, 0x3b274355,
111  0xe24621ac, 0x5dc90862, 0x270749c3, 0xba027841,
112 
113  };
114  return run_test(kBasicTestKey, sizeof(kBasicTestKey), msg_buf, exp_tag);
115 }
116 
117 /**
118  * Test with an empty message.
119  *
120  * HMAC-SHA512(kBasicTestKey, '')
121  * =
122  * 0xef725f225b5c7e880aabfb5c3dd6d8d5f3027aaf1a532e502f65e48a1c9196cff712e44f3b2700d9c02321a363b7b9c51a598b9226a737704a6d19dff79c582d
123  */
124 static status_t empty_test(void) {
125  const uint32_t exp_tag[] = {
126  0x225f72ef, 0x887e5c5b, 0x5cfbab0a, 0xd5d8d63d, 0xaf7a02f3, 0x502e531a,
127  0x8ae4652f, 0xcf96911c, 0x4fe412f7, 0xd900273b, 0xa32123c0, 0xc5b9b763,
128  0x928b591a, 0x7037a726, 0xdf196d4a, 0x2d589cf7,
129 
130  };
131  otcrypto_const_byte_buf_t msg_buf = {
132  .data = NULL,
133  .len = 0,
134  };
135  return run_test(kBasicTestKey, sizeof(kBasicTestKey), msg_buf, exp_tag);
136 }
137 
138 /**
139  * Test using a long key.
140  *
141  * HMAC-SHA512(kLongTestKey, 'Test message.')
142  * =
143  * 0x6f18c6e54d2498dfd73bd6e04b38a85d2c94fcfc2ac7e54ea2eb5884a8e4ebb0a5e0954f7ec5fdc26b3c15aed8706620d72d97a3f0b986b631b2d550249c724d
144  */
145 static status_t long_key_test(void) {
146  const char plaintext[] = "Test message.";
147  otcrypto_const_byte_buf_t msg_buf = {
148  .data = (unsigned char *)plaintext,
149  .len = sizeof(plaintext) - 1,
150  };
151  const uint32_t exp_tag[] = {
152  0xe5c6186f, 0xdf98244d, 0xe0d63bd7, 0x5da8384b, 0xfcfc942c, 0x4ee5c72a,
153  0x8458eba2, 0xb0ebe4a8, 0x4f95e0a5, 0xc2fdc57e, 0xae153c6b, 0x206670d8,
154  0xa3972dd7, 0xb686b9f0, 0x50d5b231, 0x4d729c24,
155 
156  };
157  return run_test(kLongTestKey, sizeof(kLongTestKey), msg_buf, exp_tag);
158 }
159 
160 OTTF_DEFINE_TEST_CONFIG();
161 
162 // Holds the test result.
163 static volatile status_t test_result;
164 
165 bool test_main(void) {
166  test_result = OK_STATUS();
167  CHECK_STATUS_OK(entropy_complex_init());
168  EXECUTE_TEST(test_result, empty_test);
169  EXECUTE_TEST(test_result, simple_test);
170  EXECUTE_TEST(test_result, long_key_test);
171  return status_ok(test_result);
172 }