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