Software APIs
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/drivers/hmac.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
12 
13 /**
14  * Two-block test data.
15  *
16  * Test from:
17  * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA256.pdf
18  *
19  * SHA256('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
20  * = 0x248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1
21  */
22 static const unsigned char kTwoBlockMessage[] =
23  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
24 static const size_t kTwoBlockMessageLen = sizeof(kTwoBlockMessage) - 1;
25 static const uint8_t kTwoBlockExpDigest[] = {
26  0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
27  0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
28  0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1};
29 
30 /**
31  * Test that is exactly one block in length.
32  *
33  * SHA256(0x102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f)
34  * = 0xfdeab9acf3710362bd2658cdc9a29e8f9c757fcf9811603a8c447cd1d9151108
35  */
36 static const uint8_t kExactBlockMessage[] = {
37  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
38  0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
39  0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
40  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
41  0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
42  0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
43 };
44 static const size_t kExactBlockMessageLen = sizeof(kExactBlockMessage);
45 static const uint8_t kExactBlockExpDigest[] = {
46  0xfd, 0xea, 0xb9, 0xac, 0xf3, 0x71, 0x03, 0x62, 0xbd, 0x26, 0x58,
47  0xcd, 0xc9, 0xa2, 0x9e, 0x8f, 0x9c, 0x75, 0x7f, 0xcf, 0x98, 0x11,
48  0x60, 0x3a, 0x8c, 0x44, 0x7c, 0xd1, 0xd9, 0x15, 0x11, 0x08,
49 };
50 
51 /**
52  * Call the `otcrypto_hash` API and check the resulting digest.
53  *
54  * @param msg Input message.
55  * @param exp_digest Expected digest (256 bits).
56  */
57 static status_t run_test(otcrypto_const_byte_buf_t msg,
58  const uint32_t *exp_digest) {
59  uint32_t act_digest[kHmacSha256DigestWords];
60  otcrypto_hash_digest_t digest_buf = {
61  .data = act_digest,
62  .len = kHmacSha256DigestWords,
63  .mode = kOtcryptoHashModeSha256,
64  };
65  TRY(otcrypto_hash(msg, digest_buf));
66  TRY_CHECK_ARRAYS_EQ(act_digest, exp_digest, kHmacSha256DigestWords);
67  return OK_STATUS();
68 }
69 
70 /**
71  * Simple test with a short message.
72  *
73  * SHA256('Test message.')
74  * = 0xb2da997a966ee07c43e1f083807ce5884bc0a4cad13b02cadc72a11820b50917
75  */
76 static status_t simple_test(void) {
77  const char plaintext[] = "Test message.";
78  otcrypto_const_byte_buf_t msg_buf = {
79  .data = (unsigned char *)plaintext,
80  .len = sizeof(plaintext) - 1,
81  };
82  const uint32_t exp_digest[] = {
83  0x7a99dab2, 0x7ce06e96, 0x83f0e143, 0x88e57c80,
84  0xcaa4c04b, 0xca023bd1, 0x18a172dc, 0x1709b520,
85  };
86  return run_test(msg_buf, exp_digest);
87 }
88 
89 /**
90  * Test with an empty message.
91  *
92  * SHA256('')
93  * = 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
94  */
95 static status_t empty_test(void) {
96  const uint32_t exp_digest[] = {
97  0x42c4b0e3, 0x141cfc98, 0xc8f4fb9a, 0x24b96f99,
98  0xe441ae27, 0x4c939b64, 0x1b9995a4, 0x55b85278,
99  };
100  otcrypto_const_byte_buf_t msg_buf = {
101  .data = NULL,
102  .len = 0,
103  };
104  return run_test(msg_buf, exp_digest);
105 }
106 
107 /**
108  * Test streaming API with a one-block message in one update.
109  */
110 static status_t one_update_streaming_test(void) {
112  TRY(otcrypto_hash_init(&ctx, kOtcryptoHashModeSha256));
113 
114  otcrypto_const_byte_buf_t msg_buf = {
115  .data = kExactBlockMessage,
116  .len = kExactBlockMessageLen,
117  };
118  TRY(otcrypto_hash_update(&ctx, msg_buf));
119 
120  size_t digest_num_words =
121  (sizeof(kExactBlockExpDigest) + sizeof(uint32_t) - 1) / sizeof(uint32_t);
122  uint32_t act_digest[digest_num_words];
123  otcrypto_hash_digest_t digest_buf = {
124  .data = act_digest,
125  .len = digest_num_words,
126  .mode = kOtcryptoHashModeSha256,
127  };
128  TRY(otcrypto_hash_final(&ctx, digest_buf));
129  TRY_CHECK_ARRAYS_EQ((unsigned char *)act_digest, kExactBlockExpDigest,
130  sizeof(kExactBlockExpDigest));
131  return OK_STATUS();
132 }
133 
134 /**
135  * Test streaming API with a two-block message in multiple updates.
136  */
137 static status_t multiple_update_streaming_test(void) {
139  TRY(otcrypto_hash_init(&ctx, kOtcryptoHashModeSha256));
140 
141  // Send 0 bytes, then 1, then 2, etc. until message is done.
142  const unsigned char *next = kTwoBlockMessage;
143  size_t len = kTwoBlockMessageLen;
144  size_t update_size = 0;
145  while (len > 0) {
146  update_size = len <= update_size ? len : update_size;
147  otcrypto_const_byte_buf_t msg_buf = {
148  .data = next,
149  .len = update_size,
150  };
151  next += update_size;
152  len -= update_size;
153  update_size++;
154  TRY(otcrypto_hash_update(&ctx, msg_buf));
155  }
156  size_t digest_num_words =
157  (sizeof(kTwoBlockExpDigest) + sizeof(uint32_t) - 1) / sizeof(uint32_t);
158  uint32_t act_digest[digest_num_words];
159  otcrypto_hash_digest_t digest_buf = {
160  .data = act_digest,
161  .len = digest_num_words,
162  .mode = kOtcryptoHashModeSha256,
163  };
164  TRY(otcrypto_hash_final(&ctx, digest_buf));
165  TRY_CHECK_ARRAYS_EQ((unsigned char *)act_digest, kTwoBlockExpDigest,
166  sizeof(kTwoBlockExpDigest));
167  return OK_STATUS();
168 }
169 
170 OTTF_DEFINE_TEST_CONFIG();
171 
172 bool test_main(void) {
173  status_t test_result = OK_STATUS();
174  CHECK_STATUS_OK(entropy_complex_init());
175  EXECUTE_TEST(test_result, simple_test);
176  EXECUTE_TEST(test_result, empty_test);
177  EXECUTE_TEST(test_result, one_update_streaming_test);
178  EXECUTE_TEST(test_result, multiple_update_streaming_test);
179  return status_ok(test_result);
180 }