Lightweight Cryptography Primitives
 All Data Structures Files Functions Variables Typedefs Macros Pages
internal-isap.h
1 /*
2  * Copyright (C) 2021 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_RATE Number of bytes in the rate for hashing and encryption.
28  * ISAP_sH Number of rounds for hashing.
29  * ISAP_sE Number of rounds for encryption.
30  * ISAP_sB Number of rounds for key bit absorption.
31  * ISAP_sK Number of rounds for keying.
32  * ISAP_STATE Type for the permuation state; e.g. ascon_state_t
33  * ISAP_PERMUTE(s,r) Permutes the state "s" with number of rounds "r".
34  * ISAP_PERMUTE_SLICED(s,r) Defined if using the sliced version of ASCON.
35  */
36 #if defined(ISAP_ALG_NAME)
37 
38 #if !defined(ISAP_KEY_SIZE)
39 #define ISAP_KEY_SIZE 16
40 #define ISAP_NONCE_SIZE 16
41 #define ISAP_TAG_SIZE 16
42 #endif
43 
44 #define ISAP_CONCAT_INNER(name,suffix) name##suffix
45 #define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix)
46 
47 /* IV string for initialising the associated data */
48 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_A)
49  [sizeof(ISAP_STATE) - ISAP_NONCE_SIZE] = {
50  0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
51  ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK
52 };
53 
54 /* IV string for authenticating associated data */
55 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA)
56  [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = {
57  0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
58  ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK
59 };
60 
61 /* IV string for encrypting payload data */
62 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE)
63  [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = {
64  0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
65  ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK
66 };
67 
79 static void ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
80  (ISAP_STATE *state, const unsigned char *k, const unsigned char *iv,
81  const unsigned char *data, unsigned data_len)
82 {
83 #if defined(ISAP_PERMUTE_SLICED)
84  unsigned bit, num_bits;
85 
86  /* Initialize the state with the key and IV */
87  memcpy(state->B, k, ISAP_KEY_SIZE);
88  memcpy(state->B + ISAP_KEY_SIZE, iv, sizeof(state->B) - ISAP_KEY_SIZE);
89  ascon_to_sliced(state);
90  ISAP_PERMUTE_SLICED(state, ISAP_sK);
91 
92  /* Absorb all of the bits of the data buffer one by one */
93  num_bits = data_len * 8 - 1;
94  for (bit = 0; bit < num_bits; ++bit) {
95  state->W[1] ^=
96  (((uint32_t)(data[bit / 8])) << (24 + bit % 8)) & 0x80000000U;
97  ISAP_PERMUTE_SLICED(state, ISAP_sB);
98  }
99  state->W[1] ^=
100  (((uint32_t)(data[bit / 8])) << (24 + bit % 8)) & 0x80000000U;
101  ISAP_PERMUTE_SLICED(state, ISAP_sK);
102 #else
103  unsigned bit, num_bits;
104 
105  /* Initialize the state with the key and IV */
106  memcpy(state->B, k, ISAP_KEY_SIZE);
107  memcpy(state->B + ISAP_KEY_SIZE, iv, sizeof(state->B) - ISAP_KEY_SIZE);
108  ISAP_PERMUTE(state, ISAP_sK);
109 
110  /* Absorb all of the bits of the data buffer one by one */
111  num_bits = data_len * 8 - 1;
112  for (bit = 0; bit < num_bits; ++bit) {
113  state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80;
114  ISAP_PERMUTE(state, ISAP_sB);
115  }
116  state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80;
117  ISAP_PERMUTE(state, ISAP_sK);
118 #endif
119 }
120 
131 static void ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)
132  (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub,
133  unsigned char *c, const unsigned char *m, size_t mlen)
134 {
135 #if defined(ISAP_PERMUTE_SLICED)
136  unsigned char block[ISAP_RATE];
137 
138  /* Set up the re-keyed encryption key and nonce in the state */
139  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
140  (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), npub, ISAP_NONCE_SIZE);
141  ascon_set_sliced(state, npub, 3);
142  ascon_set_sliced(state, npub + 8, 4);
143 
144  /* Encrypt the plaintext to produce the ciphertext */
145  while (mlen >= ISAP_RATE) {
146  ISAP_PERMUTE_SLICED(state, ISAP_sE);
147  ascon_squeeze_sliced(state, block, 0);
148  lw_xor_block_2_src(c, block, m, ISAP_RATE);
149  c += ISAP_RATE;
150  m += ISAP_RATE;
151  mlen -= ISAP_RATE;
152  }
153  if (mlen > 0) {
154  ISAP_PERMUTE_SLICED(state, ISAP_sE);
155  ascon_squeeze_sliced(state, block, 0);
156  lw_xor_block_2_src(c, block, m, (unsigned)mlen);
157  }
158 #else
159  /* Set up the re-keyed encryption key and nonce in the state */
160  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
161  (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KE), npub, ISAP_NONCE_SIZE);
162  memcpy(state->B + sizeof(ISAP_STATE) - ISAP_NONCE_SIZE,
163  npub, ISAP_NONCE_SIZE);
164 
165  /* Encrypt the plaintext to produce the ciphertext */
166  while (mlen >= ISAP_RATE) {
167  ISAP_PERMUTE(state, ISAP_sE);
168  lw_xor_block_2_src(c, state->B, m, ISAP_RATE);
169  c += ISAP_RATE;
170  m += ISAP_RATE;
171  mlen -= ISAP_RATE;
172  }
173  if (mlen > 0) {
174  ISAP_PERMUTE(state, ISAP_sE);
175  lw_xor_block_2_src(c, state->B, m, (unsigned)mlen);
176  }
177 #endif
178 }
179 
191 static void ISAP_CONCAT(ISAP_ALG_NAME,_mac)
192  (ISAP_STATE *state, const unsigned char *k, const unsigned char *npub,
193  const unsigned char *ad, size_t adlen,
194  const unsigned char *c, size_t clen,
195  unsigned char *tag)
196 {
197 #if defined(ISAP_PERMUTE_SLICED)
198  unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE];
199  unsigned char padded[ISAP_RATE];
200  unsigned temp;
201 
202  /* Absorb the associated data */
203  memcpy(state->B, npub, ISAP_NONCE_SIZE);
204  memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A),
205  sizeof(state->B) - ISAP_NONCE_SIZE);
206  ascon_to_sliced(state);
207  ISAP_PERMUTE_SLICED(state, ISAP_sH);
208  while (adlen >= ISAP_RATE) {
209  ascon_absorb_sliced(state, ad, 0);
210  ISAP_PERMUTE_SLICED(state, ISAP_sH);
211  ad += ISAP_RATE;
212  adlen -= ISAP_RATE;
213  }
214  temp = (unsigned)adlen;
215  memcpy(padded, ad, temp);
216  padded[temp] = 0x80; /* padding */
217  memset(padded + temp + 1, 0, sizeof(padded) - (temp + 1));
218  ascon_absorb_sliced(state, padded, 0);
219  ISAP_PERMUTE_SLICED(state, ISAP_sH);
220  state->W[8] ^= 0x01; /* domain separation */
221 
222  /* Absorb the ciphertext */
223  while (clen >= ISAP_RATE) {
224  ascon_absorb_sliced(state, c, 0);
225  ISAP_PERMUTE_SLICED(state, ISAP_sH);
226  c += ISAP_RATE;
227  clen -= ISAP_RATE;
228  }
229  temp = (unsigned)clen;
230  memcpy(padded, c, temp);
231  padded[temp] = 0x80; /* padding */
232  memset(padded + temp + 1, 0, sizeof(padded) - (temp + 1));
233  ascon_absorb_sliced(state, padded, 0);
234  ISAP_PERMUTE_SLICED(state, ISAP_sH);
235 
236  /* Re-key the state and generate the authentication tag */
237  ascon_from_sliced(state);
238  memcpy(tag, state->B, ISAP_TAG_SIZE);
239  memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve));
240  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
241  (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), tag, ISAP_TAG_SIZE);
242  ascon_from_sliced(state);
243  memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve));
244  ascon_to_sliced(state);
245  ISAP_PERMUTE_SLICED(state, ISAP_sH);
246  ascon_squeeze_sliced(state, tag, 0);
247  ascon_squeeze_sliced(state, tag + 8, 1);
248 #else
249  unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE];
250  unsigned temp;
251 
252  /* Absorb the associated data */
253  memcpy(state->B, npub, ISAP_NONCE_SIZE);
254  memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_IV_A),
255  sizeof(state->B) - ISAP_NONCE_SIZE);
256  ISAP_PERMUTE(state, ISAP_sH);
257  while (adlen >= ISAP_RATE) {
258  lw_xor_block(state->B, ad, ISAP_RATE);
259  ISAP_PERMUTE(state, ISAP_sH);
260  ad += ISAP_RATE;
261  adlen -= ISAP_RATE;
262  }
263  temp = (unsigned)adlen;
264  lw_xor_block(state->B, ad, temp);
265  state->B[temp] ^= 0x80; /* padding */
266  ISAP_PERMUTE(state, ISAP_sH);
267  state->B[sizeof(state->B) - 1] ^= 0x01; /* domain separation */
268 
269  /* Absorb the ciphertext */
270  while (clen >= ISAP_RATE) {
271  lw_xor_block(state->B, c, ISAP_RATE);
272  ISAP_PERMUTE(state, ISAP_sH);
273  c += ISAP_RATE;
274  clen -= ISAP_RATE;
275  }
276  temp = (unsigned)clen;
277  lw_xor_block(state->B, c, temp);
278  state->B[temp] ^= 0x80; /* padding */
279  ISAP_PERMUTE(state, ISAP_sH);
280 
281  /* Re-key the state and generate the authentication tag */
282  memcpy(tag, state->B, ISAP_TAG_SIZE);
283  memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve));
284  ISAP_CONCAT(ISAP_ALG_NAME,_rekey)
285  (state, k, ISAP_CONCAT(ISAP_ALG_NAME,_IV_KA), tag, ISAP_TAG_SIZE);
286  memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve));
287  ISAP_PERMUTE(state, ISAP_sH);
288  memcpy(tag, state->B, ISAP_TAG_SIZE);
289 #endif
290 }
291 
292 int ISAP_CONCAT(ISAP_ALG_NAME,_aead_encrypt)
293  (unsigned char *c, size_t *clen,
294  const unsigned char *m, size_t mlen,
295  const unsigned char *ad, size_t adlen,
296  const unsigned char *npub,
297  const unsigned char *k)
298 {
299  ISAP_STATE state;
300 
301  /* Set the length of the returned ciphertext */
302  *clen = mlen + ISAP_TAG_SIZE;
303 
304  /* Encrypt the plaintext to produce the ciphertext */
305  ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, c, m, mlen);
306 
307  /* Authenticate the associated data and ciphertext to generate the tag */
308  ISAP_CONCAT(ISAP_ALG_NAME,_mac)
309  (&state, k, npub, ad, adlen, c, mlen, c + mlen);
310  return 0;
311 }
312 
313 int ISAP_CONCAT(ISAP_ALG_NAME,_aead_decrypt)
314  (unsigned char *m, size_t *mlen,
315  const unsigned char *c, size_t clen,
316  const unsigned char *ad, size_t adlen,
317  const unsigned char *npub,
318  const unsigned char *k)
319 {
320  ISAP_STATE state;
321  unsigned char tag[ISAP_TAG_SIZE];
322 
323  /* Validate the ciphertext length and set the return "mlen" value */
324  if (clen < ISAP_TAG_SIZE)
325  return -1;
326  *mlen = clen - ISAP_TAG_SIZE;
327 
328  /* Authenticate the associated data and ciphertext to generate the tag */
329  ISAP_CONCAT(ISAP_ALG_NAME,_mac)(&state, k, npub, ad, adlen, c, *mlen, tag);
330 
331  /* Decrypt the ciphertext to produce the plaintext */
332  ISAP_CONCAT(ISAP_ALG_NAME,_encrypt)(&state, k, npub, m, c, *mlen);
333 
334  /* Check the authentication tag */
335  return aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE);
336 }
337 
338 #endif /* ISAP_ALG_NAME */
339 
340 /* Now undefine everything so that we can include this file again for
341  * another variant on the ISAP algorithm */
342 #undef ISAP_ALG_NAME
343 #undef ISAP_RATE
344 #undef ISAP_sH
345 #undef ISAP_sE
346 #undef ISAP_sB
347 #undef ISAP_sK
348 #undef ISAP_STATE
349 #undef ISAP_PERMUTE
350 #undef ISAP_PERMUTE_SLICED
351 #undef ISAP_CONCAT_INNER
352 #undef ISAP_CONCAT
#define ascon_squeeze_sliced(state, data, offset)
Squeezes data from the ASCON state in sliced form.
Definition: internal-ascon.h:232
#define ascon_absorb_sliced(state, data, offset)
Absorbs data into the ASCON state in sliced form.
Definition: internal-ascon.h:175
void ascon_to_sliced(ascon_state_t *state)
Converts an ASCON state from byte form into sliced form.
Definition: internal-ascon.c:96
#define ascon_set_sliced(state, data, offset)
Sets data into the ASCON state in sliced form.
Definition: internal-ascon.h:156
void ascon_from_sliced(ascon_state_t *state)
Converts an ASCON state from sliced form into byte form.
Definition: internal-ascon.c:110