ASCON Suite
ascon-isap-common.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 /* We expect a number of macros to be defined before this file
24  * is included to configure the underlying ISAP variant.
25  *
26  * ISAP_ALG_NAME Name of the ISAP algorithm; e.g. isap_keccak_128
27  * ISAP_KEY_STATE Type for the pre-computed key state
28  * ISAP_KEY_SIZE Size of the key in bytes.
29  * ISAP_NONCE_SIZE Size of the nonce in bytes.
30  * ISAP_TAG_SIZE Size of the authentication tag in bytes.
31  * ISAP_STATE_SIZE Size of the permutation state in bytes.
32  * ISAP_RATE Number of bytes in the rate for hashing and encryption.
33  * ISAP_sH Number of rounds for hashing.
34  * ISAP_sE Number of rounds for encryption.
35  * ISAP_sB Number of rounds for key bit absorption.
36  * ISAP_sK Number of rounds for keying.
37  */
38 #if defined(ISAP_ALG_NAME)
39 
40 #define ISAP_CONCAT_INNER(name,suffix) name##suffix
41 #define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix)
42 
43 #if defined(ASCON_BACKEND_DIRECT_XOR)
44 
45 #define ISAP_ADD_BIT(state, value, bit) \
46  do { \
47  (state)->B[0] ^= ((value) << (bit)) & 0x80; \
48  } while (0)
49 
50 #elif defined(ASCON_BACKEND_SLICED32)
51 
52 #define ISAP_ADD_BIT(state, value, bit) \
53  do { \
54  (state)->W[1] ^= (((uint32_t)(value)) << (24 + (bit))) & 0x80000000U; \
55  } while (0)
56 
57 #elif defined(ASCON_BACKEND_SLICED64)
58 
59 #define ISAP_ADD_BIT(state, value, bit) \
60  do { \
61  (state)->S[0] ^= (((uint64_t)(value)) << (56 + (bit))) & 0x8000000000000000ULL; \
62  } while (0)
63 
64 #else
65 
66 #define ISAP_ADD_BIT(state, value, bit) \
67  do { \
68  uint8_t absorb = (uint8_t)(((value) << (bit)) & 0x80); \
69  ascon_add_bytes((state), &absorb, 0, 1); \
70  } while (0)
71 
72 #endif
73 
74 /* IV string for initialising the associated data */
75 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_A)
77  0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
79 };
80 
81 /* IV string for authenticating associated data */
82 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA)
84  0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
86 };
87 
88 /* IV string for encrypting payload data */
89 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE)
91  0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
93 };
94 
105 static void ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
106  (ascon_state_t *state, const ascon_state_t *pk,
107  const unsigned char *data, unsigned data_len)
108 {
109  unsigned bit, num_bits;
110 
111  /* Initialize the state with the key and IV from "pk" */
112  ascon_copy(state, pk);
113 
114  /* Absorb all of the bits of the data buffer one by one */
115  num_bits = data_len * 8 - 1;
116  for (bit = 0; bit < num_bits; ++bit) {
117  ISAP_ADD_BIT(state, data[bit / 8], bit % 8);
118  ascon_permute(state, 12 - ISAP_sB);
119  }
120  ISAP_ADD_BIT(state, data[bit / 8], bit % 8);
121  ascon_permute(state, 12 - ISAP_sK);
122 }
123 
134 static void ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)
135  (ascon_state_t *state, const ISAP_KEY_STATE *pk, const unsigned char *npub,
136  unsigned char *c, const unsigned char *m, size_t mlen)
137 {
138  /* Set up the re-keyed encryption key and nonce in the state */
139  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
140  (state, &(pk->ke), npub, ISAP_NONCE_SIZE);
143 
144  /* Encrypt the plaintext to produce the ciphertext */
145  while (mlen >= ISAP_RATE) {
146  ascon_permute(state, 12 - ISAP_sE);
148  c += ISAP_RATE;
149  m += ISAP_RATE;
150  mlen -= ISAP_RATE;
151  }
152  if (mlen > 0) {
153  ascon_permute(state, 12 - ISAP_sE);
154  ascon_extract_and_add_bytes(state, m, c, 0, (unsigned)mlen);
155  }
156 }
157 
169 static void ISAP_CONCAT(ISAP_ALG_NAME,_mac)
170  (ascon_state_t *state, const ISAP_KEY_STATE *pk,
171  const unsigned char *npub,
172  const unsigned char *ad, size_t adlen,
173  const unsigned char *c, size_t clen,
174  unsigned char *tag)
175 {
176  unsigned char preserve[ISAP_STATE_SIZE - ISAP_KEY_SIZE];
177 #if ISAP_KEY_SIZE != ISAP_TAG_SIZE
178  unsigned char k[ISAP_KEY_SIZE];
179 #endif
180  unsigned temp;
181 
182  /* Absorb the associated data */
185  (state, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A), ISAP_NONCE_SIZE,
186  sizeof(ISAP_CONCAT(ISAP_ALG_NAME,_IV_A)));
187  ascon_permute(state, 12 - ISAP_sH);
188  while (adlen >= ISAP_RATE) {
190  ascon_permute(state, 12 - ISAP_sH);
191  ad += ISAP_RATE;
192  adlen -= ISAP_RATE;
193  }
194  temp = (unsigned)adlen;
195  if (temp)
196  ascon_add_bytes(state, ad, 0, temp);
197  ascon_pad(state, temp);
198  ascon_permute(state, 12 - ISAP_sH);
200 
201  /* Absorb the ciphertext */
202  while (clen >= ISAP_RATE) {
204  ascon_permute(state, 12 - ISAP_sH);
205  c += ISAP_RATE;
206  clen -= ISAP_RATE;
207  }
208  temp = (unsigned)clen;
209  if (temp)
210  ascon_add_bytes(state, c, 0, temp);
211  ascon_pad(state, temp);
212  ascon_permute(state, 12 - ISAP_sH);
213 
214  /* Re-key the state and generate the authentication tag */
215 #if ISAP_KEY_SIZE == ISAP_TAG_SIZE
217  ascon_extract_bytes(state, preserve, ISAP_KEY_SIZE, sizeof(preserve));
218  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
219  (state, &(pk->ka), tag, ISAP_TAG_SIZE);
220 #else
222  ascon_extract_bytes(state, preserve, ISAP_KEY_SIZE, sizeof(preserve));
223  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
224  (state, &(pk->ka), k, ISAP_KEY_SIZE);
225 #endif
226  ascon_overwrite_bytes(state, preserve, ISAP_KEY_SIZE, sizeof(preserve));
227  ascon_permute(state, 12 - ISAP_sH);
229  ascon_clean(preserve, sizeof(preserve));
230 #if ISAP_KEY_SIZE != ISAP_TAG_SIZE
231  ascon_clean(k, sizeof(k));
232 #endif
233 }
234 
235 void ISAP_CONCAT(ISAP_ALG_NAME,_aead_init)
236  (ISAP_KEY_STATE *pk, const unsigned char *k)
237 {
238  /* Expand the encryption key */
239  ascon_init(&(pk->ke));
240  ascon_overwrite_bytes(&(pk->ke), k, 0, ISAP_KEY_SIZE);
242  (&(pk->ke), ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), ISAP_KEY_SIZE,
243  sizeof(ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE)));
244  ascon_permute(&(pk->ke), 12 - ISAP_sK);
245  ascon_release(&(pk->ke));
246 
247  /* Expand the authentication key */
248  ascon_init(&(pk->ka));
249  ascon_overwrite_bytes(&(pk->ka), k, 0, ISAP_KEY_SIZE);
251  (&(pk->ka), ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), ISAP_KEY_SIZE,
252  sizeof(ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA)));
253  ascon_permute(&(pk->ka), 12 - ISAP_sK);
254  ascon_release(&(pk->ka));
255 }
256 
257 void ISAP_CONCAT(ISAP_ALG_NAME,_aead_load_key)
258  (ISAP_KEY_STATE *pk,
259  const unsigned char k[ASCON_ISAP_SAVED_KEY_SIZE])
260 {
261  /* Load the ke and ka values directly into the permutation states */
262  ascon_init(&(pk->ke));
263  ascon_overwrite_bytes(&(pk->ke), k, 0, ISAP_STATE_SIZE);
264  ascon_release(&(pk->ke));
265  ascon_init(&(pk->ka));
267  ascon_release(&(pk->ka));
268 }
269 
270 void ISAP_CONCAT(ISAP_ALG_NAME,_aead_save_key)
271  (ISAP_KEY_STATE *pk,
272  unsigned char k[ASCON_ISAP_SAVED_KEY_SIZE])
273 {
274  /* Extract the ASCON state for ke and ka into the buffer */
275  ascon_acquire(&(pk->ke));
276  ascon_extract_bytes(&(pk->ke), k, 0, ISAP_STATE_SIZE);
277  ascon_release(&(pk->ke));
278  ascon_acquire(&(pk->ka));
280  ascon_release(&(pk->ka));
281 }
282 
283 void ISAP_CONCAT(ISAP_ALG_NAME,_aead_free)(ISAP_KEY_STATE *pk)
284 {
285  if (pk) {
286  ascon_acquire(&(pk->ke));
287  ascon_free(&(pk->ke));
288  ascon_acquire(&(pk->ka));
289  ascon_free(&(pk->ka));
290  }
291 }
292 
293 void ISAP_CONCAT(ISAP_ALG_NAME,_aead_encrypt)
294  (unsigned char *c, size_t *clen,
295  const unsigned char *m, size_t mlen,
296  const unsigned char *ad, size_t adlen,
297  const unsigned char *npub,
298  const ISAP_KEY_STATE *pk)
299 {
301 
302  /* Set the length of the returned ciphertext */
303  *clen = mlen + ISAP_TAG_SIZE;
304 
305  /* Encrypt the plaintext to produce the ciphertext */
306  ascon_init(&state);
307  ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, pk, npub, c, m, mlen);
308 
309  /* Authenticate the associated data and ciphertext to generate the tag */
310  ISAP_CONCAT(ISAP_ALG_NAME,_mac)
311  (&state, pk, npub, ad, adlen, c, mlen, c + mlen);
312  ascon_free(&state);
313 }
314 
315 int ISAP_CONCAT(ISAP_ALG_NAME,_aead_decrypt)
316  (unsigned char *m, size_t *mlen,
317  const unsigned char *c, size_t clen,
318  const unsigned char *ad, size_t adlen,
319  const unsigned char *npub,
320  const ISAP_KEY_STATE *pk)
321 {
323  unsigned char tag[ISAP_TAG_SIZE];
324  int result;
325 
326  /* Validate the ciphertext length and set the return "mlen" value */
327  if (clen < ISAP_TAG_SIZE)
328  return -1;
329  *mlen = clen - ISAP_TAG_SIZE;
330 
331  /* Authenticate the associated data and ciphertext to generate the tag */
332  ascon_init(&state);
333  ISAP_CONCAT(ISAP_ALG_NAME,_mac)
334  (&state, pk, npub, ad, adlen, c, *mlen, tag);
335 
336  /* Decrypt the ciphertext to produce the plaintext */
337  ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, pk, npub, m, c, *mlen);
338 
339  /* Check the authentication tag */
340  result = ascon_aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE);
341  ascon_clean(tag, sizeof(tag));
342  ascon_free(&state);
343  return result;
344 }
345 
346 #endif /* ISAP_ALG_NAME */
347 
348 /* Now undefine everything so that we can include this file again for
349  * another variant on the ISAP algorithm */
350 #undef ISAP_ALG_NAME
351 #undef ISAP_KEY_STATE
352 #undef ISAP_KEY_SIZE
353 #undef ISAP_NONCE_SIZE
354 #undef ISAP_TAG_SIZE
355 #undef ISAP_RATE
356 #undef ISAP_sH
357 #undef ISAP_sE
358 #undef ISAP_sB
359 #undef ISAP_sK
360 #undef ISAP_STATE_SIZE
361 #undef ISAP_CONCAT_INNER
362 #undef ISAP_CONCAT
363 #undef ISAP_ADD_BIT
int ascon_aead_check_tag(unsigned char *plaintext, size_t plaintext_len, const unsigned char *tag1, const unsigned char *tag2, size_t size)
Check an authentication tag in constant time.
#define ISAP_sH
#define ISAP_RATE
#define ISAP_KEY_STATE
#define ISAP_sK
#define ISAP_NONCE_SIZE
#define ISAP_TAG_SIZE
#define ISAP_STATE_SIZE
#define ISAP_sE
#define ISAP_KEY_SIZE
#define ISAP_sB
#define ISAP_ALG_NAME
#define ascon_pad(state, offset)
#define ascon_separator(state)
#define ASCON_ISAP_SAVED_KEY_SIZE
Size of a pre-computed key in its save format.
Definition: isap.h:83
void ascon_free(ascon_state_t *state)
Frees an ASCON permutation state and attempts to destroy any sensitive material.
void ascon_release(ascon_state_t *state)
Temporarily releases access to any shared hardware resources that a permutation state was using.
void ascon_overwrite_bytes(ascon_state_t *state, const uint8_t *data, unsigned offset, unsigned size)
Overwrites existing bytes in the ASCON state.
void ascon_copy(ascon_state_t *dest, const ascon_state_t *src)
Copies the entire ASCON permutation state from a source to a destination.
void ascon_extract_bytes(const ascon_state_t *state, uint8_t *data, unsigned offset, unsigned size)
Extracts bytes from the ASCON state.
void ascon_add_bytes(ascon_state_t *state, const uint8_t *data, unsigned offset, unsigned size)
Adds bytes to the ASCON state by XOR'ing them with existing bytes.
void ascon_extract_and_add_bytes(const ascon_state_t *state, const uint8_t *input, uint8_t *output, unsigned offset, unsigned size)
Extracts bytes from the ASCON state and XOR's them with input bytes to produce output bytes.
void ascon_permute(ascon_state_t *state, uint8_t first_round)
Permutes the ASCON state with a specified number of rounds.
Definition: ascon-c32.c:36
void ascon_acquire(ascon_state_t *state)
Re-acquires access to any shared hardware resources that a permutation state was using.
void ascon_init(ascon_state_t *state)
Initializes the words of the ASCON permutation state to zero.
ascon_state_t state
[snippet_key]
Definition: snippets.c:2
unsigned char data[8]
[snippet_key]
Definition: snippets.c:14
Structure of the internal state of the ASCON permutation.
Definition: permutation.h:63
void ascon_clean(void *buf, unsigned size)
Cleans a buffer that contains sensitive material.
Definition: ascon-clean.c:38