Lightweight Cryptography Primitives
 All Data Structures Files Functions Variables Typedefs Macros Pages
internal-isap-pk.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_KEY_STATE Type for the pre-computed key state
28  * ISAP_RATE Number of bytes in the rate for hashing and encryption.
29  * ISAP_sH Number of rounds for hashing.
30  * ISAP_sE Number of rounds for encryption.
31  * ISAP_sB Number of rounds for key bit absorption.
32  * ISAP_sK Number of rounds for keying.
33  * ISAP_STATE Type for the permuation state; e.g. ascon_state_t
34  * ISAP_PERMUTE(s,r) Permutes the state "s" with number of rounds "r".
35  * ISAP_PERMUTE_SLICED(s,r) Defined if using the sliced version of ASCON.
36  */
37 #if defined(ISAP_ALG_NAME)
38 
39 #if !defined(ISAP_KEY_SIZE)
40 #define ISAP_KEY_SIZE 16
41 #define ISAP_NONCE_SIZE 16
42 #define ISAP_TAG_SIZE 16
43 #endif
44 
45 #define ISAP_CONCAT_INNER(name,suffix) name##suffix
46 #define ISAP_CONCAT(name,suffix) ISAP_CONCAT_INNER(name,suffix)
47 
48 /* IV string for initialising the associated data */
49 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_A)
50  [sizeof(ISAP_STATE) - ISAP_NONCE_SIZE] = {
51  0x01, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
52  ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK
53 };
54 
55 /* IV string for authenticating associated data */
56 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_KA)
57  [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = {
58  0x02, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
59  ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK
60 };
61 
62 /* IV string for encrypting payload data */
63 static unsigned char const ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_KE)
64  [sizeof(ISAP_STATE) - ISAP_KEY_SIZE] = {
65  0x03, ISAP_KEY_SIZE * 8, ISAP_RATE * 8, 1,
66  ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK
67 };
68 
79 static void ISAP_CONCAT(ISAP_ALG_NAME,_pk_rekey)
80  (ISAP_STATE *state, const unsigned char *pk,
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 (already pre-sliced) */
87  memcpy(state->B, pk, sizeof(state->B));
88 
89  /* Absorb all of the bits of the data buffer one by one */
90  num_bits = data_len * 8 - 1;
91  for (bit = 0; bit < num_bits; ++bit) {
92  state->W[1] ^=
93  (((uint32_t)(data[bit / 8])) << (24 + bit % 8)) & 0x80000000U;
94  ISAP_PERMUTE_SLICED(state, ISAP_sB);
95  }
96  state->W[1] ^=
97  (((uint32_t)(data[bit / 8])) << (24 + bit % 8)) & 0x80000000U;
98  ISAP_PERMUTE_SLICED(state, ISAP_sK);
99 #else
100  unsigned bit, num_bits;
101 
102  /* Initialize the state with the key and IV */
103  memcpy(state->B, pk, sizeof(state->B));
104 
105  /* Absorb all of the bits of the data buffer one by one */
106  num_bits = data_len * 8 - 1;
107  for (bit = 0; bit < num_bits; ++bit) {
108  state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80;
109  ISAP_PERMUTE(state, ISAP_sB);
110  }
111  state->B[0] ^= (data[bit / 8] << (bit % 8)) & 0x80;
112  ISAP_PERMUTE(state, ISAP_sK);
113 #endif
114 }
115 
126 static void ISAP_CONCAT(ISAP_ALG_NAME,_pk_encrypt)
127  (ISAP_STATE *state, const ISAP_KEY_STATE *pk, const unsigned char *npub,
128  unsigned char *c, const unsigned char *m, size_t mlen)
129 {
130 #if defined(ISAP_PERMUTE_SLICED)
131  unsigned char block[ISAP_RATE];
132 
133  /* Set up the re-keyed encryption key and nonce in the state */
134  ISAP_CONCAT(ISAP_ALG_NAME,_pk_rekey)(state, pk->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,_pk_rekey)(state, pk->ke, npub, ISAP_NONCE_SIZE);
155  memcpy(state->B + sizeof(ISAP_STATE) - ISAP_NONCE_SIZE,
156  npub, ISAP_NONCE_SIZE);
157 
158  /* Encrypt the plaintext to produce the ciphertext */
159  while (mlen >= ISAP_RATE) {
160  ISAP_PERMUTE(state, ISAP_sE);
161  lw_xor_block_2_src(c, state->B, m, ISAP_RATE);
162  c += ISAP_RATE;
163  m += ISAP_RATE;
164  mlen -= ISAP_RATE;
165  }
166  if (mlen > 0) {
167  ISAP_PERMUTE(state, ISAP_sE);
168  lw_xor_block_2_src(c, state->B, m, (unsigned)mlen);
169  }
170 #endif
171 }
172 
184 static void ISAP_CONCAT(ISAP_ALG_NAME,_pk_mac)
185  (ISAP_STATE *state, const ISAP_KEY_STATE *pk,
186  const unsigned char *npub,
187  const unsigned char *ad, size_t adlen,
188  const unsigned char *c, size_t 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,_pk_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,_pk_rekey)(state, pk->ka, tag, ISAP_TAG_SIZE);
235  ascon_from_sliced(state);
236  memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve));
237  ascon_to_sliced(state);
238  ISAP_PERMUTE_SLICED(state, ISAP_sH);
239  ascon_squeeze_sliced(state, tag, 0);
240  ascon_squeeze_sliced(state, tag + 8, 1);
241 #else
242  unsigned char preserve[sizeof(ISAP_STATE) - ISAP_TAG_SIZE];
243  unsigned temp;
244 
245  /* Absorb the associated data */
246  memcpy(state->B, npub, ISAP_NONCE_SIZE);
247  memcpy(state->B + ISAP_NONCE_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_A),
248  sizeof(state->B) - ISAP_NONCE_SIZE);
249  ISAP_PERMUTE(state, ISAP_sH);
250  while (adlen >= ISAP_RATE) {
251  lw_xor_block(state->B, ad, ISAP_RATE);
252  ISAP_PERMUTE(state, ISAP_sH);
253  ad += ISAP_RATE;
254  adlen -= ISAP_RATE;
255  }
256  temp = (unsigned)adlen;
257  lw_xor_block(state->B, ad, temp);
258  state->B[temp] ^= 0x80; /* padding */
259  ISAP_PERMUTE(state, ISAP_sH);
260  state->B[sizeof(state->B) - 1] ^= 0x01; /* domain separation */
261 
262  /* Absorb the ciphertext */
263  while (clen >= ISAP_RATE) {
264  lw_xor_block(state->B, c, ISAP_RATE);
265  ISAP_PERMUTE(state, ISAP_sH);
266  c += ISAP_RATE;
267  clen -= ISAP_RATE;
268  }
269  temp = (unsigned)clen;
270  lw_xor_block(state->B, c, temp);
271  state->B[temp] ^= 0x80; /* padding */
272  ISAP_PERMUTE(state, ISAP_sH);
273 
274  /* Re-key the state and generate the authentication tag */
275  memcpy(tag, state->B, ISAP_TAG_SIZE);
276  memcpy(preserve, state->B + ISAP_TAG_SIZE, sizeof(preserve));
277  ISAP_CONCAT(ISAP_ALG_NAME,_pk_rekey)(state, pk->ka, tag, ISAP_TAG_SIZE);
278  memcpy(state->B + ISAP_TAG_SIZE, preserve, sizeof(preserve));
279  ISAP_PERMUTE(state, ISAP_sH);
280  memcpy(tag, state->B, ISAP_TAG_SIZE);
281 #endif
282 }
283 
293 int ISAP_CONCAT(ISAP_ALG_NAME,_aead_pk_init)
294  (ISAP_KEY_STATE *pk, const unsigned char *k)
295 {
296 #if defined(ISAP_PERMUTE_SLICED)
297  ISAP_STATE state;
298 
299  /* Expand the encryption key */
300  memcpy(state.B, k, ISAP_KEY_SIZE);
301  memcpy(state.B + ISAP_KEY_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_KE),
302  sizeof(state.B) - ISAP_KEY_SIZE);
303  ascon_to_sliced(&state);
304  ISAP_PERMUTE_SLICED(&state, ISAP_sK);
305  memcpy(pk->ke, state.B, sizeof(state.B));
306 
307  /* Expand the authentication key */
308  memcpy(state.B, k, ISAP_KEY_SIZE);
309  memcpy(state.B + ISAP_KEY_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_KA),
310  sizeof(state.B) - ISAP_KEY_SIZE);
311  ascon_to_sliced(&state);
312  ISAP_PERMUTE_SLICED(&state, ISAP_sK);
313  memcpy(pk->ka, state.B, sizeof(state.B));
314 
315  return 0;
316 #else
317  ISAP_STATE state;
318 
319  /* Expand the encryption key */
320  memcpy(state.B, k, ISAP_KEY_SIZE);
321  memcpy(state.B + ISAP_KEY_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_KE),
322  sizeof(state.B) - ISAP_KEY_SIZE);
323  ISAP_PERMUTE(&state, ISAP_sK);
324  memcpy(pk->ke, state.B, sizeof(state.B));
325 
326  /* Expand the authentication key */
327  memcpy(state.B, k, ISAP_KEY_SIZE);
328  memcpy(state.B + ISAP_KEY_SIZE, ISAP_CONCAT(ISAP_ALG_NAME,_pk_IV_KA),
329  sizeof(state.B) - ISAP_KEY_SIZE);
330  ISAP_PERMUTE(&state, ISAP_sK);
331  memcpy(pk->ka, state.B, sizeof(state.B));
332 
333  return 0;
334 #endif
335 }
336 
337 int ISAP_CONCAT(ISAP_ALG_NAME,_aead_pk_encrypt)
338  (unsigned char *c, size_t *clen,
339  const unsigned char *m, size_t mlen,
340  const unsigned char *ad, size_t adlen,
341  const unsigned char *npub,
342  const ISAP_KEY_STATE *pk)
343 {
344  ISAP_STATE state;
345 
346  /* Set the length of the returned ciphertext */
347  *clen = mlen + ISAP_TAG_SIZE;
348 
349  /* Encrypt the plaintext to produce the ciphertext */
350  ISAP_CONCAT(ISAP_ALG_NAME,_pk_encrypt)(&state, pk, npub, c, m, mlen);
351 
352  /* Authenticate the associated data and ciphertext to generate the tag */
353  ISAP_CONCAT(ISAP_ALG_NAME,_pk_mac)
354  (&state, pk, npub, ad, adlen, c, mlen, c + mlen);
355  return 0;
356 }
357 
358 int ISAP_CONCAT(ISAP_ALG_NAME,_aead_pk_decrypt)
359  (unsigned char *m, size_t *mlen,
360  const unsigned char *c, size_t clen,
361  const unsigned char *ad, size_t adlen,
362  const unsigned char *npub,
363  const ISAP_KEY_STATE *pk)
364 {
365  ISAP_STATE state;
366  unsigned char tag[ISAP_TAG_SIZE];
367 
368  /* Validate the ciphertext length and set the return "mlen" value */
369  if (clen < ISAP_TAG_SIZE)
370  return -1;
371  *mlen = clen - ISAP_TAG_SIZE;
372 
373  /* Authenticate the associated data and ciphertext to generate the tag */
374  ISAP_CONCAT(ISAP_ALG_NAME,_pk_mac)
375  (&state, pk, npub, ad, adlen, c, *mlen, tag);
376 
377  /* Decrypt the ciphertext to produce the plaintext */
378  ISAP_CONCAT(ISAP_ALG_NAME,_pk_encrypt)(&state, pk, npub, m, c, *mlen);
379 
380  /* Check the authentication tag */
381  return aead_check_tag(m, *mlen, tag, c + *mlen, ISAP_TAG_SIZE);
382 }
383 
384 #endif /* ISAP_ALG_NAME */
385 
386 /* Now undefine everything so that we can include this file again for
387  * another variant on the ISAP algorithm */
388 #undef ISAP_ALG_NAME
389 #undef ISAP_KEY_STATE
390 #undef ISAP_RATE
391 #undef ISAP_sH
392 #undef ISAP_sE
393 #undef ISAP_sB
394 #undef ISAP_sK
395 #undef ISAP_STATE
396 #undef ISAP_PERMUTE
397 #undef ISAP_PERMUTE_SLICED
398 #undef ISAP_CONCAT_INNER
399 #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