1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes
9  ***********************************************************************************************************************/
10 
11 #include "bsp_api.h"
12 #include "hw_sce_aes_private.h"
13 #include "hw_sce_ra_private.h"
14 
15 /***********************************************************************************************************************
16  * Global variables and functions
17  ***********************************************************************************************************************/
18 
hw_gcm_calculation(uint8_t * input,uint8_t * output,uint32_t data_len,uint8_t * atag,uint8_t * initial_vector,uint32_t iv_len,uint8_t * aad,uint32_t aad_len)19 fsp_err_t hw_gcm_calculation (uint8_t * input,
20                               uint8_t * output,
21                               uint32_t  data_len,
22                               uint8_t * atag,
23                               uint8_t * initial_vector,
24                               uint32_t  iv_len,
25                               uint8_t * aad,
26                               uint32_t  aad_len)
27 {
28     uint32_t  len                             = 0;
29     uint32_t  temp_len                        = 0;
30     uint32_t  temp_value                      = 0;
31     uint8_t   first_block_null_aad            = 0;
32     uint8_t   Jn[16]                          = {0};
33     uint8_t   J0[16]                          = {0};
34     uint8_t   data[16]                        = {0};
35     uint8_t   local_in[SIZE_AES_BLOCK_BYTES]  = {0};
36     uint8_t   local_out[SIZE_AES_BLOCK_BYTES] = {0};
37     uint8_t * ptr;
38     uint8_t * ptr_out_temp;
39     uint8_t * ptr_out;
40     fsp_err_t status = FSP_SUCCESS;
41     uint8_t   temp_output[SIZE_AES_BLOCK_BYTES];
42     bool      src_unaligned = !HW_32BIT_ALIGNED((uint32_t) &input[0]);
43     bool      dst_unaligned = !HW_32BIT_ALIGNED((uint32_t) &output[0]);
44     uint8_t * buf_in        = input;
45     uint8_t * buf_out       = output;
46     uint8_t * p_in          = input;
47     uint8_t * p_out         = output;
48 
49     if (src_unaligned)
50     {
51         memset(local_in, 0, (size_t) sizeof(local_in));
52         p_in = &local_in[0];
53     }
54 
55     if (dst_unaligned)
56     {
57         p_out = &local_out[0];
58     }
59 
60     if ((uint8_t) iv_len == 12)
61     {
62         memcpy(&J0, initial_vector, 12);
63         J0[15] = 1;
64     }
65     else
66     {
67         ptr                = initial_vector;
68         temp_len           = iv_len;
69         R_AES_B->AESDCNTL |= R_AES_AESDCNTL_BIT_2 | R_AES_AESDCNTL_BIT_3;
70         do
71         {
72             len = 16;
73             if (temp_len < 16)
74             {
75                 len = temp_len;
76             }
77 
78             temp_len -= len;
79             hw_aes_start(ptr, &J0[0], 1);
80             ptr += len;
81         } while (temp_len > 0);
82 
83         for (int16_t iLoop = 0; iLoop < 8; iLoop++)
84         {
85             data[iLoop] = 0;
86         }
87 
88         for (int16_t iLoop = 0; iLoop < 8; iLoop++)
89         {
90             temp_len         = (uint32_t) ((uint8_t) iv_len * 8);
91             temp_len       >>= (8 * iLoop);
92             data[15 - iLoop] = (uint8_t) temp_len;
93         }
94 
95         hw_aes_start(&data[0], &J0[0], 1);
96     }
97 
98     /* Flow to Obtain J0 from IV End */
99     /* Flow to Obtain J1 from J0 */
100 
101     memcpy(Jn, J0, 16);
102 
103     for (int16_t iLoop = 0; iLoop < 4; iLoop++)
104     {
105         temp_value = Jn[15 - iLoop];
106         if (temp_value != 0xFF)        // NOLINT(readability-magic-numbers)
107         {
108             Jn[15 - iLoop] += 1;
109             break;
110         }
111 
112         Jn[15 - iLoop] = 0;
113     }
114 
115     hw_aes_set_iv(Jn);
116 
117     /* Athentication Tag Creation Start */
118     if (aad_len != 0)
119     {
120         /* Flow to Obtain AAD Hash Value Start */
121         ptr                = aad;
122         temp_len           = aad_len;
123         R_AES_B->AESDCNTL |= R_AES_AESDCNTL_BIT_2;
124 
125         do
126         {
127             len = 16;
128             if (temp_len < 16)
129             {
130                 len = temp_len;
131                 memset(data, 0, (size_t) sizeof(data));
132                 memcpy(data, ptr, (size_t) len);
133                 hw_aes_start(&data[0], &data[0], 1);
134             }
135             else
136             {
137                 hw_aes_start(ptr, &data[0], 1);
138             }
139 
140             ptr      += len;
141             temp_len -= len;
142         } while (temp_len > 0);
143 
144         /* Flow to Obtain AAD Hash Value End */
145     }
146     else
147     {
148         first_block_null_aad = 1;
149     }
150 
151     /* Encryption Flow Start */
152     if (data_len != 0)
153     {
154         ptr      = input;
155         ptr_out  = output;
156         temp_len = data_len;
157         do
158         {
159             if (src_unaligned)
160             {
161                 memcpy(&local_in[0], &buf_in[0], SIZE_AES_BLOCK_BYTES);
162             }
163 
164             ptr_out_temp = &temp_output[0];
165             temp_value   = 0;
166             len          = SIZE_AES_BLOCK_BYTES;
167             if (temp_len < SIZE_AES_BLOCK_BYTES)
168             {
169                 len          = temp_len;
170                 temp_value   = temp_len * 8;
171                 temp_value <<= 8;
172                 temp_value  |= R_AES_AESDCNTL_BIT_4;
173             }
174 
175             temp_len         -= len;
176             R_AES_B->AESDCNTL = ((uint16_t) temp_value | R_AES_AESDCNTL_BIT_5);
177             if (first_block_null_aad == 1)
178             {
179                 first_block_null_aad = 0;
180                 R_AES_B->AESDCNTL   |= R_AES_AESDCNTL_BIT_2;
181             }
182 
183             if ((src_unaligned || dst_unaligned) && (temp_len > 0)) // unaligned data in normal block
184             {
185                 hw_aes_start(p_in, p_out, 1);
186                 ptr_out += SIZE_AES_BLOCK_BYTES;
187                 if (dst_unaligned)
188                 {
189                     memcpy(&buf_out[0], &p_out[0], SIZE_AES_BLOCK_BYTES);
190                     buf_out += SIZE_AES_BLOCK_BYTES;
191                 }
192                 else
193                 {
194                     p_out += SIZE_AES_BLOCK_BYTES;
195                 }
196 
197                 if (src_unaligned)
198                 {
199                     buf_in += SIZE_AES_BLOCK_BYTES;
200                 }
201                 else
202                 {
203                     p_in += SIZE_AES_BLOCK_BYTES;
204                 }
205             }
206             else if (temp_len > 0)
207             {
208                 hw_aes_start(ptr, ptr_out, 1);
209                 ptr_out += SIZE_AES_BLOCK_BYTES;
210             }
211             else
212             {
213                 memset(data, 0, sizeof(data));
214                 memcpy(data, ptr, (size_t) len);
215                 hw_aes_start(&data[0], ptr_out_temp, 1);
216                 memcpy(ptr_out, &temp_output[0], (size_t) len);
217                 ptr_out_temp += SIZE_AES_BLOCK_BYTES;
218                 ptr_out      += SIZE_AES_BLOCK_BYTES;
219             }
220 
221             ptr += len;
222             for (int16_t iLoop = 0; iLoop < 4; iLoop++)
223             {
224                 temp_value = Jn[15 - iLoop];
225                 if (temp_value == 0xFF) // NOLINT(readability-magic-numbers)
226                 {
227                     Jn[15 - iLoop] = 0;
228                 }
229                 else
230                 {
231                     Jn[15 - iLoop] += 1;
232                     break;
233                 }
234             }
235 
236             hw_aes_set_iv(Jn);
237         } while (temp_len > 0);
238     }
239 
240     /* Encryption Flow End */
241 
242     hw_aes_set_iv(J0);
243     for (int16_t iLoop = 0; iLoop < 8; iLoop++)
244     {
245         temp_len       = aad_len * 8;
246         temp_len     >>= (8 * iLoop);
247         Jn[7 - iLoop]  = (uint8_t) temp_len;
248         temp_len       = data_len * 8;
249         temp_len     >>= (8 * iLoop);
250         Jn[15 - iLoop] = (uint8_t) temp_len;
251     }
252 
253     if (((uint8_t) iv_len == 12) && (aad_len == 0) && (data_len == 0))
254     {
255         R_AES_B->AESDCNTL = R_AES_AESDCNTL_BIT_2 | R_AES_AESDCNTL_BIT_3 | R_AES_AESDCNTL_BIT_6;
256     }
257     else if (((uint8_t) iv_len != 12) && (aad_len == 0) && (data_len == 0))
258     {
259         R_AES_B->AESDCNTL = R_AES_AESDCNTL_BIT_2 | R_AES_AESDCNTL_BIT_6;
260     }
261     else
262     {
263         R_AES_B->AESDCNTL = R_AES_AESDCNTL_BIT_6;
264     }
265 
266     hw_aes_start(&Jn[0], atag, 1);
267 
268     /* Athentication Tag Creation End*/
269     return status;
270 }
271