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 */
110inline void hmac_sha256_init(void) {
111 hmac_sha256_configure(false);
112 hmac_sha256_start();
113}
114
115/**
116 * Configures and starts HMAC in HMAC mode with little-endian output.
117 */
118inline void sc_hmac_hmac_sha256_init(hmac_key_t key, bool big_endian_digest) {
119 sc_hmac_hmac_sha256_configure(big_endian_digest, key);
120 hmac_sha256_start();
121}
122
123/**
124 * Sends `len` bytes from `data` to the SHA2-256 function.
125 *
126 * This function does not check for the size of the available HMAC
127 * FIFO. Since the this function is meant to run in blocking mode,
128 * polling for FIFO status is equivalent to stalling on FIFO write.
129 *
130 * @param data Buffer to copy data from.
131 * @param len Size of the `data` buffer in bytes.
132 */
133void hmac_sha256_update(const void *data, size_t len);
134
135/**
136 * Sends `len` 32-bit words from `data` to the SHA2-256 function.
137 *
138 * This function does not check for the size of the available HMAC
139 * FIFO. Since the this function is meant to run in blocking mode,
140 * polling for FIFO status is equivalent to stalling on FIFO write.
141 *
142 * @param data Buffer to copy data from.
143 * @param len Size of the `data` buffer in words.
144 */
145void hmac_sha256_update_words(const uint32_t *data, size_t len);
146
147/**
148 * Begin processing the final digest for HMAC.
149 */
150void hmac_sha256_process(void);
151
152/**
153 * Finalizes SHA256 operation and copies truncated output.
154 *
155 * Copies only the first `len` 32-bit words of the digest. The caller must
156 * ensure enough space is available in the buffer.
157 *
158 * Note: the caller must call `hmac_sha256_process()` before calling this.
159 *
160 * @param[out] digest Buffer to copy digest to.
161 * @param[out] len Requested word-length.
162 */
163void hmac_sha256_final_truncated(uint32_t *digest, size_t len);
164
165/**
166 * Finalizes SHA256 operation and writes `digest` buffer.
167 *
168 * Note: the caller must call `hmac_sha256_process()` before calling this.
169 *
170 * @param[out] digest Buffer to copy digest to.
171 */
172inline void hmac_sha256_final(hmac_digest_t *digest) {
173 hmac_sha256_final_truncated(digest->digest, ARRAYSIZE(digest->digest));
174}
175
176/**
177 * Convenience single-shot function for computing the SHA-256 digest of a
178 * contiguous buffer.
179 *
180 * @param data Buffer to copy data from.
181 * @param len Size of the `data` buffer in bytes.
182 * @param[out] digest Buffer to copy digest to.
183 */
184void hmac_sha256(const void *data, size_t len, hmac_digest_t *digest);
185
186/**
187 * Save an operation's working state for later.
188 *
189 * This function issues the `stop` command and then waits for HMAC's `done`
190 * interrupt.
191 *
192 * IMPORTANT: the caller must ensure that the amount of message input written
193 * between `start` or `restore` and this function is a *nonzero* number of full
194 * message blocks (512 bits for SHA256). Otherwise, the hardware will wait for
195 * more input before issuing the `done` interrupt, and the computation will
196 * spin forever.
197 *
198 * @param[out] ctx Saved operation state.
199 */
200void hmac_sha256_save(hmac_context_t *ctx);
201
202/**
203 * Restore an operation's working state.
204 *
205 * Issues the `continue` command after restoring the state. Call
206 * `hmac_sha256_configure()` to set the HMAC configuration before calling this
207 * function.
208 *
209 * @param ctx Saved operation state.
210 */
211void hmac_sha256_restore(const hmac_context_t *ctx);
212
213#ifdef __cplusplus
214}
215#endif
216
217#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_DRIVERS_HMAC_H_