-
Notifications
You must be signed in to change notification settings - Fork 789
/
dif_hmac.h
234 lines (212 loc) · 8.16 KB
/
dif_hmac.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_HMAC_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_HMAC_H_
/**
* @file
* @brief <a href="/hw/ip/hmac/doc/">HMAC</a> Device Interface Functions
*/
#include <stddef.h>
#include <stdint.h>
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/autogen/dif_hmac_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* Supported HMAC modes of operation.
*/
typedef enum dif_hmac_mode {
/** The HMAC mode. */
kDifHmacModeHmac = 0,
/** The SHA256-only mode. */
kDifHmacModeSha256,
} dif_hmac_mode_t;
/**
* Supported byte endienness options.
*/
typedef enum dif_hmac_endianness {
/** Big endian byte ordering. */
kDifHmacEndiannessBig = 0,
/** Little endian byte ordering. */
kDifHmacEndiannessLittle,
} dif_hmac_endianness_t;
/**
* HMAC key length in bits.
*/
typedef enum dif_hmac_key_length {
kDifHMACKey128 = 1,
kDifHMACKey256 = (1 << 1),
kDifHMACKey384 = (1 << 2),
kDifHMACKey512 = (1 << 3),
kDifHMACKey1024 = (1 << 4),
} dif_hmac_key_length_t;
/**
* SHA-2 digest size
*/
typedef enum dif_sha2_digest_size {
kDifSHA256 = (1 << 1),
kDifSHA384 = (1 << 2),
kDifSHA512 = (1 << 3),
} dif_sha2_digest_size_t;
/**
* Configuration for a single HMAC Transaction
*/
typedef struct dif_hmac_transaction {
/** Byte endianness for writes to the FIFO. */
dif_hmac_endianness_t message_endianness;
/** Byte endianness for reads from the digest. */
dif_hmac_endianness_t digest_endianness;
/** SHA-2 digest size. */
dif_sha2_digest_size_t digest_size;
/** HMAC key length. */
dif_hmac_key_length_t key_length;
} dif_hmac_transaction_t;
/**
* A typed representation of the HMAC digest.
*/
typedef struct dif_hmac_digest {
uint32_t digest[8];
} dif_hmac_digest_t;
/**
* Resets the HMAC engine and readies it to receive a new message to process an
* HMAC digest.
*
* This function causes the HMAC engine to start its operation. After a
* successful call to this function, |dif_hmac_fifo_push()| can be called to
* write the message for HMAC processing.
*
* This function should be called with a valid `key` that references a 32-byte,
* contiguous, readable region where the key may be copied from. Passing a
* `NULL` `key` reference will skip loading of the key. This is only expected to
* be used to test scenarios where the key is not loaded.
*
* @param hmac The HMAC device to start HMAC operation for.
* @param key The 256-bit HMAC key.
* @param config The per-transaction configuration.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_mode_hmac_start(const dif_hmac_t *hmac,
const uint8_t *key,
const dif_hmac_transaction_t config);
/**
* Resets the HMAC engine and readies it to receive a new message to process a
* SHA256 digest.
*
* This function causes the HMAC engine to start its operation. After a
* successful call to this function, |dif_hmac_fifo_push()| can be called to
* write the message for SHA256 processing.
*
* @param hmac The HMAC device to start SHA256 operation for.
* @param config The per-transaction configuration.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_mode_sha256_start(const dif_hmac_t *hmac,
const dif_hmac_transaction_t config);
/**
* Attempts to send `len` bytes from the buffer pointed to by `data` to the
* device described by `hmac`. This function will send to the message FIFO until
* the FIFO fills up or `len` bytes have been sent.
*
* In the event that the FIFO fills up before `len` bytes have been sent this
* function will return a `kDifHmacFifoFull` error. In this case it is valid
* to call this function again by advancing `data` by `len` - |*bytes_sent|
* bytes. It may be desirable to wait for space to free up on the FIFO before
* issuing subsequent calls to this function, but it is not strictly
* necessary. The number of entries in the FIFO can be queried with
* `dif_hmac_fifo_count_entries()`.
*
* `data` *must* point to an allocated buffer of at least length `len`.
*
* @param hmac The HMAC device to send to.
* @param data A contiguous buffer to copy from.
* @param len The length of the buffer to copy from.
* @param[out] bytes_sent The number of bytes sent to the FIFO (optional).
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_fifo_push(const dif_hmac_t *hmac, const void *data,
size_t len, size_t *bytes_sent);
/**
* Retrieves the number of entries in the HMAC FIFO. These entries may be
* semi-arbitrary in length; this function should not be used to calculate
* message length.
*
* @param hmac The HMAC device to get the FIFO depth for.
* @param[out] num_entries The number of entries in the FIFO.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_fifo_count_entries(const dif_hmac_t *hmac,
uint32_t *num_entries);
/**
* Retrieves the number of bits in the loaded HMAC device.
* `dif_hmac_fifo_count_entries()` should be called before this function to
* ensure the FIFO is empty, as any bits in the FIFO are not counted in
* `msg_len`.
*
* @param hmac The HMAC device to get the message length for.
* @param[out] msg_len The number of bits in the HMAC message.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_get_message_length(const dif_hmac_t *hmac,
uint64_t *msg_len);
/**
* Attempts to run HMAC or SHA256 depending on the mode `hmac` was initialized
* in. Calls to this function always succeed and return without blocking. The
* caller can use `dif_hmac_check_state()` to check for errors and for the
* `DIF_HMAC_DONE` status before reading the digest with
* `dif_hmac_digest_read()`.
*
* @param hmac The HMAC device to initiate the run on.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_process(const dif_hmac_t *hmac);
/**
* Attempts to finish a transaction started with `dif_hmac_mode_*_start`, and
* reads the final digest in the buffer referenced by `digest`.
*
* This queries the `INTR_STATE` register to check if the HMAC is finished, and
* will acknowledge a `hmac_done` interrupt. If that register is not pending,
* then this function assumes HMAC is still processing and will return
* `kDifHmacErrorDigestProcessing`.
*
* `digest` must reference an allocated, contiguous, 32-byte buffer. This buffer
* shall also be 4-byte aligned. This is all consistent with the platform
* requirements for size and alignment requirements of `dif_hmac_digest_t`.
*
* @param hmac The HMAC device to read the digest from.
* @param disable_after_done If true, the HMAC and SHA256 datapaths will be
* disabled after the digest is read, clearing the digest registers.
* @param[out] digest A contiguous 32-byte, 4-byte aligned buffer for the
* digest.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_finish(const dif_hmac_t *hmac, bool disable_after_done,
dif_hmac_digest_t *digest);
/**
* Randomizes internal secret registers on the HMAC device. This includes the
* key, hash value, and internal state machine. The value of `entropy` will be
* used to "randomize" the internal state of the HMAC device. See the HMAC IP
* documentation for more information: hw/ip/hmac/doc.
*
* @param hmac The HMAC device to clobber state on.
* @param entropy A source of randomness to write to the HMAC internal state.
* @param[out] digest The resulting digest from the wipe operation.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_hmac_wipe_secret(const dif_hmac_t *hmac, uint32_t entropy,
dif_hmac_digest_t *digest);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_HMAC_H_