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
13extern "C" {
14#endif
15
16enum {
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 * Size of a HMAC-SHA-256 key in bytes.
27 */
28 kHmacKeyNumBytes = kHmacDigestNumBytes,
29 /**
30 * Size of a HMAC-SHA-256 key in 32-bit words.
31 */
32 kHmacKeyNumWords = kHmacDigestNumWords,
33};
34
35/**
36 * A typed representation of the HMAC digest.
37 */
38typedef struct hmac_digest {
39 uint32_t digest[kHmacDigestNumWords];
40} hmac_digest_t;
41
42/**
43 * A typed representation of the HMAC secret key (for HMAC-SHA256 mode).
44 */
45typedef struct hmac_key {
46 uint32_t key[kHmacDigestNumWords];
47} hmac_key_t;
48
49/**
50 * Stored SHA256 operation state.
51 *
52 * Does not store the configuration of the block, so it is important that
53 * configuration parameters such as digest endianness match up when the
54 * operation is restarted.
55 */
56typedef struct hmac_context {
57 uint32_t msg_len_upper;
58 uint32_t msg_len_lower;
59 uint32_t digest[kHmacDigestNumWords];
60} hmac_context_t;
61
62/**
63 * Configure the HMAC block in HMAC-SHA256 mode.
64 *
65 * This function resets the HMAC module to clear the digest register.
66 * It then configures the HMAC block in HMAC mode with digest output
67 * in the requested endianness.
68 *
69 * @param big_endian Whether or not to initialize the peripheral for big-endian
70 * results.
71 */
72void sc_hmac_hmac_sha256_configure(bool big_endian_digest, hmac_key_t key);
73
74/**
75 * Convenience single-shot function for computing the HMAC-SHA-256 keyed-digest
76 * of a contiguous buffer.
77 *
78 * @param data Buffer to copy data from.
79 * @param len Size of the `data` buffer in bytes.
80 * @param key Secret key to use.
81 * @param big_endian_digest Whether to configure the hardware to produce a
82 * big-endian digest.
83 * @param[out] digest Buffer to copy digest to.
84 */
85void sc_hmac_hmac_sha256(const void *data, size_t len, hmac_key_t key,
86 bool big_endian_digest, hmac_digest_t *digest);
87
88/**
89 * Configure the HMAC block in SHA256 mode.
90 *
91 * This function resets the HMAC module to clear the digest register.
92 * It then configures the HMAC block in SHA256 mode with digest output
93 * in the requested endianness.
94 *
95 * @param big_endian Whether or not to initialize the peripheral for big-endian
96 * results.
97 */
98void hmac_sha256_configure(bool big_endian_digest);
99
100/**
101 * Starts a new operation on the pre-configured HMAC block.
102 *
103 * Call `hmac_sha256_configure` first.
104 */
105void hmac_sha256_start(void);
106
107/**
108 * Configures and starts HMAC in SHA256 mode with little-endian output.
109 */
110#if defined(OT_PLATFORM_RV32) || defined(HMAC_UNIT_TEST_)
111inline void hmac_sha256_init(void) {
112 hmac_sha256_configure(false);
113 hmac_sha256_start();
114}
115#else
116void hmac_sha256_init(void);
117#endif
118
119/**
120 * Configures and starts HMAC in HMAC mode with little-endian output.
121 */
122inline void sc_hmac_hmac_sha256_init(hmac_key_t key, bool big_endian_digest) {
123 sc_hmac_hmac_sha256_configure(big_endian_digest, key);
124 hmac_sha256_start();
125}
126
127/**
128 * Sends `len` bytes from `data` to the SHA2-256 function.
129 *
130 * This function does not check for the size of the available HMAC
131 * FIFO. Since the this function is meant to run in blocking mode,
132 * polling for FIFO status is equivalent to stalling on FIFO write.
133 *
134 * @param data Buffer to copy data from.
135 * @param len Size of the `data` buffer in bytes.
136 */
137void hmac_sha256_update(const void *data, size_t len);
138
139/**
140 * Sends `len` 32-bit words from `data` to the SHA2-256 function.
141 *
142 * This function does not check for the size of the available HMAC
143 * FIFO. Since the this function is meant to run in blocking mode,
144 * polling for FIFO status is equivalent to stalling on FIFO write.
145 *
146 * @param data Buffer to copy data from.
147 * @param len Size of the `data` buffer in words.
148 */
149void hmac_sha256_update_words(const uint32_t *data, size_t len);
150
151/**
152 * Begin processing the final digest for HMAC.
153 */
154void hmac_sha256_process(void);
155
156/**
157 * Finalizes SHA256 operation and copies truncated output.
158 *
159 * Copies only the first `len` 32-bit words of the digest. The caller must
160 * ensure enough space is available in the buffer.
161 *
162 * Note: the caller must call `hmac_sha256_process()` before calling this.
163 *
164 * @param[out] digest Buffer to copy digest to.
165 * @param[out] len Requested word-length.
166 */
167void hmac_sha256_final_truncated(uint32_t *digest, size_t len);
168
169/**
170 * Finalizes SHA256 operation and writes `digest` buffer.
171 *
172 * Note: the caller must call `hmac_sha256_process()` before calling this.
173 *
174 * @param[out] digest Buffer to copy digest to.
175 */
176#if defined(OT_PLATFORM_RV32) || defined(HMAC_UNIT_TEST_)
177inline void hmac_sha256_final(hmac_digest_t *digest) {
178 hmac_sha256_final_truncated(digest->digest, ARRAYSIZE(digest->digest));
179}
180#else
181void hmac_sha256_final(hmac_digest_t *digest);
182#endif
183
184/**
185 * Convenience single-shot function for computing the SHA-256 digest of a
186 * contiguous buffer.
187 *
188 * @param data Buffer to copy data from.
189 * @param len Size of the `data` buffer in bytes.
190 * @param[out] digest Buffer to copy digest to.
191 */
192void hmac_sha256(const void *data, size_t len, hmac_digest_t *digest);
193
194/**
195 * Save an operation's working state for later.
196 *
197 * This function issues the `stop` command and then waits for HMAC's `done`
198 * interrupt.
199 *
200 * IMPORTANT: the caller must ensure that the amount of message input written
201 * between `start` or `restore` and this function is a *nonzero* number of full
202 * message blocks (512 bits for SHA256). Otherwise, the hardware will wait for
203 * more input before issuing the `done` interrupt, and the computation will
204 * spin forever.
205 *
206 * @param[out] ctx Saved operation state.
207 */
208void hmac_sha256_save(hmac_context_t *ctx);
209
210/**
211 * Restore an operation's working state.
212 *
213 * Issues the `continue` command after restoring the state. Call
214 * `hmac_sha256_configure()` to set the HMAC configuration before calling this
215 * function.
216 *
217 * @param ctx Saved operation state.
218 */
219void hmac_sha256_restore(const hmac_context_t *ctx);
220
221#ifdef __cplusplus
222}
223#endif
224
225#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_HMAC_H_