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