ascon_aead128.c
Go to the documentation of this file.
1 /**
2  * @file ascon_aead128.c
3  * @brief Ascon-AEAD128
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * Ascon-AEAD128 is a nonce-based authenticated encryption with associated data
30  * that provides 128-bit security strength
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.5.0
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "lwc/ascon_aead128.h"
42 #include "debug.h"
43 
44 //Check crypto library configuration
45 #if (ASCON_AEAD128_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Authenticated encryption using Ascon-AEAD128
50  * @param[in] k key
51  * @param[in] kLen Length of the key
52  * @param[in] n Nonce
53  * @param[in] nLen Length of the nonce
54  * @param[in] a Additional authenticated data
55  * @param[in] aLen Length of the additional data
56  * @param[in] p Plaintext to be encrypted
57  * @param[out] c Ciphertext resulting from the encryption
58  * @param[in] length Total number of data bytes to be encrypted
59  * @param[out] t MAC resulting from the encryption process
60  * @param[in] tLen Length of the MAC
61  * @return Error code
62  **/
63 
64 error_t asconAead128Encrypt(const uint8_t *k, size_t kLen, const uint8_t *n,
65  size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c,
66  size_t length, uint8_t *t, size_t tLen)
67 {
68  uint8_t buffer[16];
69  AsconState state;
70 
71  //Check parameters
72  if(k == NULL || n == NULL || t == NULL)
74 
75  //Ascon-AEAD128.enc takes a 128-bit secret key and a 128-bit nonce as input
76  //and outputs a 128-bit authentication tag
77  if(kLen != 16 || nLen != 16 || tLen != 16)
78  return ERROR_INVALID_LENGTH;
79 
80  //Given 128-bit K and 128-bit N, the 320-bit internal state S is initialized
81  //as S = IV | K | N
82  state.x[0] = 0x808C0001;
83  state.x[1] = 0x00001000;
84  state.x[2] = LOAD32LE(k);
85  state.x[3] = LOAD32LE(k + 4);
86  state.x[4] = LOAD32LE(k + 8);
87  state.x[5] = LOAD32LE(k + 12);
88  state.x[6] = LOAD32LE(n);
89  state.x[7] = LOAD32LE(n + 4);
90  state.x[8] = LOAD32LE(n + 8);
91  state.x[9] = LOAD32LE(n + 12);
92 
93  //Next, S is updated using the permutation Ascon-p[12]
94  asconP(&state, 12);
95 
96  //XOR the secret key K into the last 128 bits of internal state
97  state.x[6] ^= LOAD32LE(k);
98  state.x[7] ^= LOAD32LE(k + 4);
99  state.x[8] ^= LOAD32LE(k + 8);
100  state.x[9] ^= LOAD32LE(k + 12);
101 
102  //Any associated data?
103  if(aLen > 0)
104  {
105  //When associated data is non-empty, it is parsed into blocks
106  while(aLen >= 16)
107  {
108  //Each associated data block Ai is absorbed into the first 128 bits
109  //of state
110  state.x[0] ^= LOAD32LE(a);
111  state.x[1] ^= LOAD32LE(a + 4);
112  state.x[2] ^= LOAD32LE(a + 8);
113  state.x[3] ^= LOAD32LE(a + 12);
114 
115  //And the permutation Ascon-p[8] is applied to the state
116  asconP(&state, 8);
117 
118  //Number of remaining data bytes
119  aLen -= 16;
120  a += 16;
121  }
122 
123  //The final block Am~ can be empty. It is padded so that |Am| = 128
124  osMemset(buffer, 0, 16);
125  osMemcpy(buffer, a, aLen);
126  buffer[aLen] = 0x01;
127 
128  //Absorb the final block Am
129  state.x[0] ^= LOAD32LE(buffer);
130  state.x[1] ^= LOAD32LE(buffer + 4);
131  state.x[2] ^= LOAD32LE(buffer + 8);
132  state.x[3] ^= LOAD32LE(buffer + 12);
133 
134  //The permutation Ascon-p[8] is applied to the state
135  asconP(&state, 8);
136  }
137 
138  //The final step of processing associated data is to update the state with
139  //a constant
140  state.x[9] ^= 0x80000000;
141 
142  //Plaintext P is parsed into blocks
143  while(length >= 16)
144  {
145  //For each Pi, the state S is updated
146  state.x[0] ^= LOAD32LE(p);
147  state.x[1] ^= LOAD32LE(p + 4);
148  state.x[2] ^= LOAD32LE(p + 8);
149  state.x[3] ^= LOAD32LE(p + 12);
150 
151  //Generate the corresponding ciphertext block Ci
152  STORE32LE(state.x[0], c);
153  STORE32LE(state.x[1], c + 4);
154  STORE32LE(state.x[2], c + 8);
155  STORE32LE(state.x[3], c + 12);
156 
157  //The permutation Ascon-p[8] is applied to the state
158  asconP(&state, 8);
159 
160  //Next block
161  length -= 16;
162  p += 16;
163  c += 16;
164  }
165 
166  //The final block Pn~ can be empty. It is padded so that |Pn| = 128
167  osMemset(buffer, 0, 16);
168  osMemcpy(buffer, p, length);
169  buffer[length] = 0x01;
170 
171  //Update the state for the last block Pn
172  state.x[0] ^= LOAD32LE(buffer);
173  state.x[1] ^= LOAD32LE(buffer + 4);
174  state.x[2] ^= LOAD32LE(buffer + 8);
175  state.x[3] ^= LOAD32LE(buffer + 12);
176 
177  //Generate the corresponding ciphertext block Cn
178  STORE32LE(state.x[0], buffer);
179  STORE32LE(state.x[1], buffer + 4);
180  STORE32LE(state.x[2], buffer + 8);
181  STORE32LE(state.x[3], buffer + 12);
182 
183  //The last ciphertext block Cn~ is obtained as Cn~ = S[0:l-1]
184  osMemcpy(c, buffer, length);
185 
186  //During finalization, the key is first loaded to the state S
187  state.x[4] ^= LOAD32LE(k);
188  state.x[5] ^= LOAD32LE(k + 4);
189  state.x[6] ^= LOAD32LE(k + 8);
190  state.x[7] ^= LOAD32LE(k + 12);
191 
192  //And the state S is then updated using the permutation Ascon-p[12]
193  asconP(&state, 12);
194 
195  //Finally, the tag T is generated by XORing the key with the last 128 bits
196  //of the state
197  state.x[6] ^= LOAD32LE(k);
198  STORE32LE(state.x[6], t);
199  state.x[7] ^= LOAD32LE(k + 4);
200  STORE32LE(state.x[7], t + 4);
201  state.x[8] ^= LOAD32LE(k + 8);
202  STORE32LE(state.x[8], t + 8);
203  state.x[9] ^= LOAD32LE(k + 12);
204  STORE32LE(state.x[9], t + 12);
205 
206  //Sucessful processing
207  return NO_ERROR;
208 }
209 
210 
211 /**
212  * @brief Authenticated decryption using Ascon-AEAD128
213  * @param[in] k key
214  * @param[in] kLen Length of the key
215  * @param[in] n Nonce
216  * @param[in] nLen Length of the nonce
217  * @param[in] a Additional authenticated data
218  * @param[in] aLen Length of the additional data
219  * @param[in] c Ciphertext to be decrypted
220  * @param[out] p Plaintext resulting from the decryption
221  * @param[in] length Total number of data bytes to be decrypted
222  * @param[in] t MAC to be verified
223  * @param[in] tLen Length of the MAC
224  * @return Error code
225  **/
226 
227 error_t asconAead128Decrypt(const uint8_t *k, size_t kLen, const uint8_t *n,
228  size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p,
229  size_t length, const uint8_t *t, size_t tLen)
230 {
231  size_t i;
232  uint8_t mask;
233  uint32_t temp1;
234  uint32_t temp2;
235  uint8_t buffer[16];
236  AsconState state;
237 
238  //Check parameters
239  if(k == NULL || n == NULL || t == NULL)
241 
242  //Ascon-AEAD128.dec takes a 128-bit secret key, a 128-bit nonce and a
243  //128-bit authentication tag as input
244  if(kLen != 16 || nLen != 16 || tLen != 16)
245  return ERROR_INVALID_LENGTH;
246 
247  //Given 128-bit K and 128-bit N, the 320-bit internal state S is initialized
248  //as S = IV | K | N
249  state.x[0] = 0x808C0001;
250  state.x[1] = 0x00001000;
251  state.x[2] = LOAD32LE(k);
252  state.x[3] = LOAD32LE(k + 4);
253  state.x[4] = LOAD32LE(k + 8);
254  state.x[5] = LOAD32LE(k + 12);
255  state.x[6] = LOAD32LE(n);
256  state.x[7] = LOAD32LE(n + 4);
257  state.x[8] = LOAD32LE(n + 8);
258  state.x[9] = LOAD32LE(n + 12);
259 
260  //Next, S is updated using the permutation Ascon-p[12]
261  asconP(&state, 12);
262 
263  //XOR the secret key K into the last 128 bits of internal state
264  state.x[6] ^= LOAD32LE(k);
265  state.x[7] ^= LOAD32LE(k + 4);
266  state.x[8] ^= LOAD32LE(k + 8);
267  state.x[9] ^= LOAD32LE(k + 12);
268 
269  //Any associated data?
270  if(aLen > 0)
271  {
272  //When associated data is non-empty, it is parsed into blocks
273  while(aLen >= 16)
274  {
275  //Each associated data block Ai is absorbed into the first 128 bits
276  //of state
277  state.x[0] ^= LOAD32LE(a);
278  state.x[1] ^= LOAD32LE(a + 4);
279  state.x[2] ^= LOAD32LE(a + 8);
280  state.x[3] ^= LOAD32LE(a + 12);
281 
282  //And the permutation Ascon-p[8] is applied to the state
283  asconP(&state, 8);
284 
285  //Number of remaining data bytes
286  aLen -= 16;
287  a += 16;
288  }
289 
290  //The final block Am~ can be empty. It is padded so that |Am| = 128
291  osMemset(buffer, 0, 16);
292  osMemcpy(buffer, a, aLen);
293  buffer[aLen] = 0x01;
294 
295  //Absorb the final block Am
296  state.x[0] ^= LOAD32LE(buffer);
297  state.x[1] ^= LOAD32LE(buffer + 4);
298  state.x[2] ^= LOAD32LE(buffer + 8);
299  state.x[3] ^= LOAD32LE(buffer + 12);
300 
301  //The permutation Ascon-p[8] is applied to the state
302  asconP(&state, 8);
303  }
304 
305  //The final step of processing associated data is to update the state with
306  //a constant
307  state.x[9] ^= 0x80000000;
308 
309  //Ciphertext C is parsed into blocks
310  while(length >= 16)
311  {
312  //The plaintext block Pi is obtained as Pi = S[0:127] + Ci
313  temp1 = state.x[0] ^ LOAD32LE(c);
314  STORE32LE(temp1, p);
315  temp1 = state.x[1] ^ LOAD32LE(c + 4);
316  STORE32LE(temp1, p + 4);
317  temp1 = state.x[2] ^ LOAD32LE(c + 8);
318  STORE32LE(temp1, p + 8);
319  temp1 = state.x[3] ^ LOAD32LE(c + 12);
320  STORE32LE(temp1, p + 12);
321 
322  //Update the state S with Ci
323  state.x[0] = LOAD32LE(c);
324  state.x[1] = LOAD32LE(c + 4);
325  state.x[2] = LOAD32LE(c + 8);
326  state.x[3] = LOAD32LE(c + 12);
327 
328  //The permutation Ascon-p[8] is applied to the state
329  asconP(&state, 8);
330 
331  //Next block
332  length -= 16;
333  c += 16;
334  p += 16;
335  }
336 
337  //Copy S[0:127]
338  STORE32LE(state.x[0], buffer);
339  STORE32LE(state.x[1], buffer + 4);
340  STORE32LE(state.x[2], buffer + 8);
341  STORE32LE(state.x[3], buffer + 12);
342 
343  //The final block Cn~ can be empty
344  osMemcpy(buffer, c, length);
345  buffer[length] ^= 0x01;
346 
347  //For the last block of the ciphertext Cn~, the following steps are applied
348  temp1 = LOAD32LE(buffer);
349  temp2 = temp1 ^ state.x[0];
350  STORE32LE(temp2, buffer);
351  state.x[0] = temp1;
352  temp1 = LOAD32LE(buffer + 4);
353  temp2 = temp1 ^ state.x[1];
354  STORE32LE(temp2, buffer + 4);
355  state.x[1] = temp1;
356  temp1 = LOAD32LE(buffer + 8);
357  temp2 = temp1 ^ state.x[2];
358  STORE32LE(temp2, buffer + 8);
359  state.x[2] = temp1;
360  temp1 = LOAD32LE(buffer + 12);
361  temp2 = temp1 ^ state.x[3];
362  STORE32LE(temp2, buffer + 12);
363  state.x[3] = temp1;
364 
365  //Copy the last plaintext block Pn~
366  osMemcpy(p, buffer, length);
367 
368  //During finalization, the key is first loaded to the state S
369  state.x[4] ^= LOAD32LE(k);
370  state.x[5] ^= LOAD32LE(k + 4);
371  state.x[6] ^= LOAD32LE(k + 8);
372  state.x[7] ^= LOAD32LE(k + 12);
373 
374  //And the state S is then updated using the permutation Ascon-p[12]
375  asconP(&state, 12);
376 
377  //Finally, the tag T' is generated by XORing the key with the last 128 bits
378  //of the state
379  state.x[6] ^= LOAD32LE(k);
380  STORE32LE(state.x[6], buffer);
381  state.x[7] ^= LOAD32LE(k + 4);
382  STORE32LE(state.x[7], buffer + 4);
383  state.x[8] ^= LOAD32LE(k + 8);
384  STORE32LE(state.x[8], buffer + 8);
385  state.x[9] ^= LOAD32LE(k + 12);
386  STORE32LE(state.x[9], buffer + 12);
387 
388  //As the last step, the computed T' is compared with the input T
389  for(mask = 0, i = 0; i < 16; i++)
390  {
391  mask |= buffer[i] ^ t[i];
392  }
393 
394  //Return status code
395  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
396 }
397 
398 #endif
uint8_t a
Definition: ndp.h:411
uint8_t p
Definition: ndp.h:300
uint8_t t
Definition: lldp_ext_med.h:212
Ascon state.
Definition: ascon.h:48
#define STORE32LE(a, p)
Definition: cpu_endian.h:279
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
uint32_t x[10]
Definition: ascon.h:49
Ascon-AEAD128.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_LENGTH
Definition: error.h:111
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:319
uint8_t length
Definition: tcp.h:375
error_t asconAead128Encrypt(const uint8_t *k, size_t kLen, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using Ascon-AEAD128.
Definition: ascon_aead128.c:64
uint8_t n
#define LOAD32LE(p)
Definition: cpu_endian.h:203
#define osMemset(p, value, length)
Definition: os_port.h:138
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
void asconP(AsconState *s, uint_t nr)
Ascon-p[rnd] permutation.
Definition: ascon.c:63
error_t asconAead128Decrypt(const uint8_t *k, size_t kLen, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using Ascon-AEAD128.