1 /*
2 * Copyright (c) 2023, The TrustedFirmware-M Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include <assert.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include "cc3xx_stdlib.h"
11 #include "cc3xx_hmac.h"
12 #include "cc3xx_drbg_hmac.h"
13
14 #define BITS_TO_BYTES(x) (((x) + 7)/8)
15 #define BYTES_TO_BITS(x) ((x)*8)
16
17 /**
18 * @brief Update the state (K,V)
19 *
20 * @param hmac_inputs_num Number of inputs for the update operation, it can be zero
21 * @param state A pointer to a state structure
22 * @param hmac_inputs Inputs for the update operation, passed as an array of hmac_inputs_num pointers
23 * @param hmac_inputs_len Lengths for the update operation, passed as an array of hmac_inputs_num values
24 * @return cc3xx_err_t
25 */
hmac_update(size_t hmac_inputs_num,struct cc3xx_drbg_hmac_state_t * state,const uint8_t ** hmac_inputs,const size_t * hmac_inputs_len)26 static cc3xx_err_t hmac_update(
27 size_t hmac_inputs_num,
28 struct cc3xx_drbg_hmac_state_t *state,
29 const uint8_t **hmac_inputs, const size_t *hmac_inputs_len)
30 {
31 const uint8_t byte0 = 0x00; const uint8_t byte1 = 0x01;
32 cc3xx_err_t err;
33 size_t idx;
34 const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
35
36 /* 1. K = HMAC(K, V || 0x00 || provided_data) */
37 err = cc3xx_lowlevel_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
38 if (err != CC3XX_ERR_SUCCESS) {
39 return err;
40 }
41 err = cc3xx_lowlevel_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
42 if (err != CC3XX_ERR_SUCCESS) {
43 return err;
44 }
45 err = cc3xx_lowlevel_hmac_update(&state->h, &byte0, sizeof(byte0));
46 if (err != CC3XX_ERR_SUCCESS) {
47 return err;
48 }
49 /* provided_data can be given into up to 3 chunks, starting from 0 index */
50 for (idx = 0; idx < hmac_inputs_num && hmac_inputs_len[idx] != 0; idx++) {
51 err = cc3xx_lowlevel_hmac_update(&state->h, hmac_inputs[idx], hmac_inputs_len[idx]);
52 if (err != CC3XX_ERR_SUCCESS) {
53 return err;
54 }
55 }
56
57 err = cc3xx_lowlevel_hmac_finish(&state->h, state->key_k, sizeof(state->key_k), NULL);
58 if (err != CC3XX_ERR_SUCCESS) {
59 return err;
60 }
61
62 /* 2. V = HMAC(K, V) */
63 err = cc3xx_lowlevel_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
64 if (err != CC3XX_ERR_SUCCESS) {
65 return err;
66 }
67 err = cc3xx_lowlevel_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
68 if (err != CC3XX_ERR_SUCCESS) {
69 return err;
70 }
71 err = cc3xx_lowlevel_hmac_finish(&state->h, state->block_v, sizeof(state->block_v), NULL);
72 if (err != CC3XX_ERR_SUCCESS) {
73 return err;
74 }
75
76 /* 3. If no provided_data has been passed, just return here */
77 if (hmac_inputs_num == 0) {
78 return err;
79 }
80
81 /* 4. K = HMAC(K, V || 0x01 || provided_data) */
82 err = cc3xx_lowlevel_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
83 if (err != CC3XX_ERR_SUCCESS) {
84 return err;
85 }
86 err = cc3xx_lowlevel_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
87 if (err != CC3XX_ERR_SUCCESS) {
88 return err;
89 }
90 err = cc3xx_lowlevel_hmac_update(&state->h, &byte1, sizeof(byte1));
91 if (err != CC3XX_ERR_SUCCESS) {
92 return err;
93 }
94 for (idx = 0; idx < hmac_inputs_num && hmac_inputs_len[idx] != 0; idx++) {
95 err = cc3xx_lowlevel_hmac_update(&state->h, hmac_inputs[idx], hmac_inputs_len[idx]);
96 if (err != CC3XX_ERR_SUCCESS) {
97 return err;
98 }
99 }
100
101 err = cc3xx_lowlevel_hmac_finish(&state->h, state->key_k, sizeof(state->key_k), NULL);
102 if (err != CC3XX_ERR_SUCCESS) {
103 return err;
104 }
105
106 /* 5. V = HMAC(K, V) */
107 err = cc3xx_lowlevel_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k), alg);
108 if (err != CC3XX_ERR_SUCCESS) {
109 return err;
110 }
111 err = cc3xx_lowlevel_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
112 if (err != CC3XX_ERR_SUCCESS) {
113 return err;
114 }
115 err = cc3xx_lowlevel_hmac_finish(&state->h, state->block_v, sizeof(state->block_v), NULL);
116
117 /* return updated (K, V) state */
118 return err;
119 }
120
cc3xx_lowlevel_drbg_hmac_instantiate(struct cc3xx_drbg_hmac_state_t * state,const uint8_t * entropy,size_t entropy_len,const uint8_t * nonce,size_t nonce_len,const uint8_t * personalization,size_t personalization_len)121 cc3xx_err_t cc3xx_lowlevel_drbg_hmac_instantiate(
122 struct cc3xx_drbg_hmac_state_t *state,
123 const uint8_t *entropy, size_t entropy_len,
124 const uint8_t *nonce, size_t nonce_len,
125 const uint8_t *personalization, size_t personalization_len)
126 {
127 cc3xx_err_t err;
128
129 /* Initialize the state */
130 memset(state->block_v, 0x01, sizeof(state->block_v));
131 memset(state->key_k, 0x00, sizeof(state->key_k));
132
133 /* Prepare the seed material to be passed to update() */
134 const uint8_t *seed[3] = {entropy, nonce, personalization};
135 const size_t seed_len[3] = {entropy_len, nonce_len, personalization_len};
136
137 err = hmac_update(3, state, seed, seed_len);
138
139 state->reseed_counter = 1;
140
141 return err;
142 }
143
cc3xx_lowlevel_drbg_hmac_generate(struct cc3xx_drbg_hmac_state_t * state,size_t len_bits,uint8_t * returned_bits,const uint8_t * additional_input,size_t additional_input_len)144 cc3xx_err_t cc3xx_lowlevel_drbg_hmac_generate(
145 struct cc3xx_drbg_hmac_state_t *state,
146 size_t len_bits, uint8_t *returned_bits,
147 const uint8_t *additional_input, size_t additional_input_len)
148 {
149 cc3xx_err_t err;
150 size_t generated_bits = 0;
151 const uint8_t *data[3] = {NULL};
152 size_t data_len[3] = {0};
153 size_t idx;
154 size_t last_hmac_update_num = 0;
155 const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
156
157 if (state->reseed_counter == UINT32_MAX) {
158 /* When we reach 2^32 invocations we must reseed */
159 return CC3XX_ERR_DRBG_RESEED_REQUIRED;
160 }
161
162 if (additional_input_len && additional_input != NULL) {
163 data[0] = additional_input;
164 data_len[0] = additional_input_len;
165 err = hmac_update(1, state, data, data_len);
166 if (err != CC3XX_ERR_SUCCESS) {
167 return err;
168 }
169 }
170
171 /* While len(temp) < requested_number_of_bits, as per spec */
172 while (generated_bits < len_bits) {
173 uint32_t temp[CC3XX_DRBG_HMAC_OUTLEN/4];
174 size_t bytes_to_copy;
175 /* V = HMAC(K, V) */
176 err = cc3xx_lowlevel_hmac_set_key(&state->h,
177 (const uint8_t *)state->key_k,
178 sizeof(state->key_k),
179 alg);
180 if (err != CC3XX_ERR_SUCCESS) {
181 return err;
182 }
183 err = cc3xx_lowlevel_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
184 if (err != CC3XX_ERR_SUCCESS) {
185 return err;
186 }
187 err = cc3xx_lowlevel_hmac_finish(&state->h, temp, CC3XX_DRBG_HMAC_OUTLEN, NULL);
188 if (err != CC3XX_ERR_SUCCESS) {
189 return err;
190 }
191
192 bytes_to_copy = len_bits - generated_bits < BYTES_TO_BITS(CC3XX_DRBG_HMAC_OUTLEN) ?
193 BITS_TO_BYTES(len_bits - generated_bits) : CC3XX_DRBG_HMAC_OUTLEN;
194 memcpy(&returned_bits[BITS_TO_BYTES(generated_bits)], temp, bytes_to_copy);
195
196 generated_bits += BYTES_TO_BITS(CC3XX_DRBG_HMAC_OUTLEN);
197
198 memcpy(state->block_v, temp, CC3XX_DRBG_HMAC_OUTLEN);
199 }
200
201 /* We need to mask the last byte in case len_bits % 8 is different than 0 */
202 if (len_bits % 8) {
203 uint8_t mask = 0UL;
204 for (idx = 0; idx < len_bits % 8; idx++) {
205 mask |= 1UL << (8 - idx - 1);
206 }
207
208 returned_bits[BITS_TO_BYTES(len_bits) - 1] &= mask;
209 }
210
211 /* The update is done with no additional_input to update() */
212 if (additional_input != NULL && additional_input_len != 0) {
213 data[0] = additional_input;
214 data_len[0] = additional_input_len;
215 last_hmac_update_num = 1;
216 }
217
218 err = hmac_update(last_hmac_update_num, state, data, data_len);
219
220 state->reseed_counter++;
221
222 return err;
223 }
224
cc3xx_lowlevel_drbg_hmac_reseed(struct cc3xx_drbg_hmac_state_t * state,const uint8_t * entropy,size_t entropy_len,const uint8_t * additional_input,size_t additional_input_len)225 cc3xx_err_t cc3xx_lowlevel_drbg_hmac_reseed(
226 struct cc3xx_drbg_hmac_state_t *state,
227 const uint8_t *entropy, size_t entropy_len,
228 const uint8_t *additional_input, size_t additional_input_len)
229 {
230 cc3xx_err_t err;
231
232 /* The update is done with no personalization string update() */
233 const uint8_t *data[3] = {entropy, additional_input, NULL};
234 const size_t data_len[3] = {entropy_len, additional_input_len, 0};
235
236 err = hmac_update(2, state, data, data_len);
237 if (err != CC3XX_ERR_SUCCESS) {
238 return err;
239 }
240
241 state->reseed_counter = 1;
242
243 return err;
244 }
245
cc3xx_lowlevel_drbg_hmac_uninit(struct cc3xx_drbg_hmac_state_t * state)246 cc3xx_err_t cc3xx_lowlevel_drbg_hmac_uninit(struct cc3xx_drbg_hmac_state_t *state)
247 {
248 cc3xx_secure_erase_buffer((uint32_t *)state, sizeof(struct cc3xx_drbg_hmac_state_t)/4);
249 return CC3XX_ERR_SUCCESS;
250 }
251