Software APIs
hmac.h
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 #ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_HMAC_H_
5 #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_HMAC_H_
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include "sw/device/silicon_creator/lib/error.h"
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 enum {
17  /**
18  * Size of a SHA-256 digest in bytes.
19  */
20  kHmacDigestNumBytes = 32,
21  /**
22  * Size of a SHA-256 digest in 32-bit words.
23  */
24  kHmacDigestNumWords = kHmacDigestNumBytes / sizeof(uint32_t),
25 };
26 
27 /**
28  * A typed representation of the HMAC digest.
29  */
30 typedef struct hmac_digest {
31  uint32_t digest[kHmacDigestNumWords];
33 
34 /**
35  * Stored SHA256 operation state.
36  *
37  * Does not store the configuration of the block, so it is important that
38  * configuration parameters such as digest endianness match up when the
39  * operation is restarted.
40  */
41 typedef struct hmac_context {
42  uint32_t msg_len_upper;
43  uint32_t msg_len_lower;
44  uint32_t digest[kHmacDigestNumWords];
46 
47 /**
48  * Configure the HMAC block in SHA256 mode.
49  *
50  * This function resets the HMAC module to clear the digest register.
51  * It then configures the HMAC block in SHA256 mode with digest output
52  * in the requested endianness.
53  *
54  * @param big_endian Whether or not to initialize the peripheral for big-endian
55  * results.
56  */
57 void hmac_sha256_configure(bool big_endian_digest);
58 
59 /**
60  * Starts a new operation on the pre-configured HMAC block.
61  *
62  * Call `hmac_sha256_configure` first.
63  */
64 void hmac_sha256_start(void);
65 
66 /**
67  * Configures and starts HMAC in SHA256 mode with little-endian output.
68  */
69 inline void hmac_sha256_init(void) {
70  hmac_sha256_configure(false);
71  hmac_sha256_start();
72 }
73 
74 /**
75  * Sends `len` bytes from `data` to the SHA2-256 function.
76  *
77  * This function does not check for the size of the available HMAC
78  * FIFO. Since the this function is meant to run in blocking mode,
79  * polling for FIFO status is equivalent to stalling on FIFO write.
80  *
81  * @param data Buffer to copy data from.
82  * @param len Size of the `data` buffer in bytes.
83  */
84 void hmac_sha256_update(const void *data, size_t len);
85 
86 /**
87  * Sends `len` 32-bit words from `data` to the SHA2-256 function.
88  *
89  * This function does not check for the size of the available HMAC
90  * FIFO. Since the this function is meant to run in blocking mode,
91  * polling for FIFO status is equivalent to stalling on FIFO write.
92  *
93  * @param data Buffer to copy data from.
94  * @param len Size of the `data` buffer in words.
95  */
96 void hmac_sha256_update_words(const uint32_t *data, size_t len);
97 
98 /**
99  * Begin processing the final digest for HMAC.
100  */
101 void hmac_sha256_process(void);
102 
103 /**
104  * Finalizes SHA256 operation and copies truncated output.
105  *
106  * Copies only the first `len` 32-bit words of the digest. The caller must
107  * ensure enough space is available in the buffer.
108  *
109  * Note: the caller must call `hmac_sha256_process()` before calling this.
110  *
111  * @param[out] digest Buffer to copy digest to.
112  * @param[out] len Requested word-length.
113  */
114 void hmac_sha256_final_truncated(uint32_t *digest, size_t len);
115 
116 /**
117  * Finalizes SHA256 operation and writes `digest` buffer.
118  *
119  * Note: the caller must call `hmac_sha256_process()` before calling this.
120  *
121  * @param[out] digest Buffer to copy digest to.
122  */
123 inline void hmac_sha256_final(hmac_digest_t *digest) {
124  hmac_sha256_final_truncated(digest->digest, ARRAYSIZE(digest->digest));
125 }
126 
127 /**
128  * Convenience single-shot function for computing the SHA-256 digest of a
129  * contiguous buffer.
130  *
131  * @param data Buffer to copy data from.
132  * @param len Size of the `data` buffer in bytes.
133  * @param[out] digest Buffer to copy digest to.
134  */
135 void hmac_sha256(const void *data, size_t len, hmac_digest_t *digest);
136 
137 /**
138  * Save an operation's working state for later.
139  *
140  * This function issues the `stop` command and then waits for HMAC's `done`
141  * interrupt.
142  *
143  * IMPORTANT: the caller must ensure that the amount of message input written
144  * between `start` or `restore` and this function is a *nonzero* number of full
145  * message blocks (512 bits for SHA256). Otherwise, the hardware will wait for
146  * more input before issuing the `done` interrupt, and the computation will
147  * spin forever.
148  *
149  * @param[out] ctx Saved operation state.
150  */
151 void hmac_sha256_save(hmac_context_t *ctx);
152 
153 /**
154  * Restore an operation's working state.
155  *
156  * Issues the `continue` command after restoring the state. Call
157  * `hmac_sha256_configure()` to set the HMAC configuration before calling this
158  * function.
159  *
160  * @param ctx Saved operation state.
161  */
162 void hmac_sha256_restore(const hmac_context_t *ctx);
163 
164 #ifdef __cplusplus
165 }
166 #endif
167 
168 #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_HMAC_H_