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
27/**
28 * A typed representation of the HMAC digest.
29 */
30typedef struct hmac_digest {
31 uint32_t digest[kHmacDigestNumWords];
32} hmac_digest_t;
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 */
41typedef struct hmac_context {
42 uint32_t msg_len_upper;
43 uint32_t msg_len_lower;
44 uint32_t digest[kHmacDigestNumWords];
45} hmac_context_t;
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 */
57void 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 */
64void hmac_sha256_start(void);
65
66/**
67 * Configures and starts HMAC in SHA256 mode with little-endian output.
68 */
69inline 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 */
84void 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 */
96void hmac_sha256_update_words(const uint32_t *data, size_t len);
97
98/**
99 * Begin processing the final digest for HMAC.
100 */
101void 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 */
114void 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 */
123inline 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 */
135void 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 */
151void 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 */
162void 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_