ASCON Suite
ascon-x4-c32.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2022 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 #include "ascon-masked-state.h"
24 #include "ascon-masked-backend.h"
25 #include "core/ascon-util.h"
26 
27 #if defined(ASCON_MASKED_X4_BACKEND_C32) && ASCON_MASKED_MAX_SHARES >= 4
28 
37 #define and_not_xor(x, y, z, w) \
38  do { \
39  x##_a##w ^= (~(y##_a##w) & z##_a##w); \
40  x##_a##w ^= (ascon_mask32_unrotate_share1_0(y##_b##w) & z##_a##w); \
41  x##_a##w ^= (ascon_mask32_unrotate_share2_0(y##_c##w) & z##_a##w); \
42  x##_a##w ^= (ascon_mask32_unrotate_share3_0(y##_d##w) & z##_a##w); \
43  \
44  x##_b##w ^= (ascon_mask32_rotate_share1_0(~(y##_a##w)) & z##_b##w); \
45  x##_b##w ^= (y##_b##w & z##_b##w); \
46  x##_b##w ^= (ascon_mask32_unrotate_share2_1(y##_c##w) & z##_b##w); \
47  x##_b##w ^= (ascon_mask32_unrotate_share3_1(y##_d##w) & z##_b##w); \
48  \
49  x##_c##w ^= (ascon_mask32_rotate_share2_0(~(y##_a##w)) & z##_c##w); \
50  x##_c##w ^= (ascon_mask32_rotate_share2_1(y##_b##w) & z##_c##w); \
51  x##_c##w ^= (y##_c##w & z##_c##w); \
52  x##_c##w ^= (ascon_mask32_unrotate_share3_2(y##_d##w) & z##_c##w); \
53  \
54  x##_d##w ^= (ascon_mask32_rotate_share3_0(~(y##_a##w)) & z##_d##w); \
55  x##_d##w ^= (ascon_mask32_rotate_share3_1(y##_b##w) & z##_d##w); \
56  x##_d##w ^= (ascon_mask32_rotate_share3_2(y##_c##w) & z##_d##w); \
57  x##_d##w ^= (y##_d##w & z##_d##w); \
58  } while (0)
59 
65 #define linear(w) \
66  do { \
67  t0 = x0_##w##e ^ rightRotate4(x0_##w##o); \
68  t1 = x0_##w##o ^ rightRotate5(x0_##w##e); \
69  t2 = x1_##w##e ^ rightRotate11(x1_##w##e); \
70  t3 = x1_##w##o ^ rightRotate11(x1_##w##o); \
71  t4 = x2_##w##e ^ rightRotate2(x2_##w##o); \
72  t5 = x2_##w##o ^ rightRotate3(x2_##w##e); \
73  t6 = x3_##w##e ^ rightRotate3(x3_##w##o); \
74  t7 = x3_##w##o ^ rightRotate4(x3_##w##e); \
75  t8 = x4_##w##e ^ rightRotate17(x4_##w##e); \
76  t9 = x4_##w##o ^ rightRotate17(x4_##w##o); \
77  x0_##w##e ^= rightRotate9(t1); \
78  x0_##w##o ^= rightRotate10(t0); \
79  x1_##w##e ^= rightRotate19(t3); \
80  x1_##w##o ^= rightRotate20(t2); \
81  x2_##w##e ^= t5; \
82  x2_##w##o ^= rightRotate1(t4); \
83  x3_##w##e ^= rightRotate5(t6); \
84  x3_##w##o ^= rightRotate5(t7); \
85  x4_##w##e ^= rightRotate3(t9); \
86  x4_##w##o ^= rightRotate4(t8); \
87  } while (0)
88 
89 /* Generate a pair of pre-inverted round constants so that we can
90  * avoid NOT'ing x2 in the S-box during the rounds */
91 #define ROUND_CONSTANT_PAIR(rc1, rc2) \
92  (~((uint32_t)(rc1))), (~((uint32_t)(rc2)))
93 
95  (ascon_masked_state_t *state, uint8_t first_round, uint64_t *preserve)
96 {
97  static const uint32_t RC[12 * 2] = {
98  ROUND_CONSTANT_PAIR(12, 12),
99  ROUND_CONSTANT_PAIR( 9, 12),
100  ROUND_CONSTANT_PAIR(12, 9),
101  ROUND_CONSTANT_PAIR( 9, 9),
102  ROUND_CONSTANT_PAIR( 6, 12),
103  ROUND_CONSTANT_PAIR( 3, 12),
104  ROUND_CONSTANT_PAIR( 6, 9),
105  ROUND_CONSTANT_PAIR( 3, 9),
106  ROUND_CONSTANT_PAIR(12, 6),
107  ROUND_CONSTANT_PAIR( 9, 6),
108  ROUND_CONSTANT_PAIR(12, 3),
109  ROUND_CONSTANT_PAIR( 9, 3)
110  };
111  const uint32_t *rc = RC + first_round * 2;
112  uint32_t x0_ae, x1_ae, x2_ae, x3_ae, x4_ae;
113  uint32_t x0_ao, x1_ao, x2_ao, x3_ao, x4_ao;
114  uint32_t x0_be, x1_be, x2_be, x3_be, x4_be;
115  uint32_t x0_bo, x1_bo, x2_bo, x3_bo, x4_bo;
116  uint32_t x0_ce, x1_ce, x2_ce, x3_ce, x4_ce;
117  uint32_t x0_co, x1_co, x2_co, x3_co, x4_co;
118  uint32_t x0_de, x1_de, x2_de, x3_de, x4_de;
119  uint32_t x0_do, x1_do, x2_do, x3_do, x4_do;
120  uint32_t t0_ao, t0_bo, t0_co, t0_do, t1_ao, t1_bo, t1_co, t1_do;
121  uint32_t t0_ae, t0_be, t0_ce, t0_de, t1_ae, t1_be, t1_ce, t1_de;
122 
123  /* Start with the randomness that the caller provided */
124  t0_ae = ((uint32_t *)preserve)[0];
125  t0_ao = ((uint32_t *)preserve)[1];
126  t0_be = ((uint32_t *)preserve)[2];
127  t0_bo = ((uint32_t *)preserve)[3];
128  t0_ce = ((uint32_t *)preserve)[4];
129  t0_co = ((uint32_t *)preserve)[5];
130 
131  /* Load the state into local variables */
132  x0_ae = state->M[0].W[0];
133  x0_ao = state->M[0].W[1];
134  x0_be = state->M[0].W[2];
135  x0_bo = state->M[0].W[3];
136  x0_ce = state->M[0].W[4];
137  x0_co = state->M[0].W[5];
138  x0_de = state->M[0].W[6];
139  x0_do = state->M[0].W[7];
140  x1_ae = state->M[1].W[0];
141  x1_ao = state->M[1].W[1];
142  x1_be = state->M[1].W[2];
143  x1_bo = state->M[1].W[3];
144  x1_ce = state->M[1].W[4];
145  x1_co = state->M[1].W[5];
146  x1_de = state->M[1].W[6];
147  x1_do = state->M[1].W[7];
148  x2_ae = state->M[2].W[0];
149  x2_ao = state->M[2].W[1];
150  x2_be = state->M[2].W[2];
151  x2_bo = state->M[2].W[3];
152  x2_ce = state->M[2].W[4];
153  x2_co = state->M[2].W[5];
154  x2_de = state->M[2].W[6];
155  x2_do = state->M[2].W[7];
156  x3_ae = state->M[3].W[0];
157  x3_ao = state->M[3].W[1];
158  x3_be = state->M[3].W[2];
159  x3_bo = state->M[3].W[3];
160  x3_ce = state->M[3].W[4];
161  x3_co = state->M[3].W[5];
162  x3_de = state->M[3].W[6];
163  x3_do = state->M[3].W[7];
164  x4_ae = state->M[4].W[0];
165  x4_ao = state->M[4].W[1];
166  x4_be = state->M[4].W[2];
167  x4_bo = state->M[4].W[3];
168  x4_ce = state->M[4].W[4];
169  x4_co = state->M[4].W[5];
170  x4_de = state->M[4].W[6];
171  x4_do = state->M[4].W[7];
172 
173  /* The round constants invert x2 as part of the rounds so that we
174  * don't need an explicit "x2 = ~x2" step in the S-box. Pre-invert
175  * x2 before the first round to compensate. */
176  x2_ae = ~x2_ae;
177  x2_ao = ~x2_ao;
178 
179  /* Perform all encryption rounds */
180  while (first_round++ < 12) {
181  /* Substitution layer, even words */
182 
183  /* Add the inverted round constant to x2 */
184  x2_ae ^= *rc++;
185 
186  /* Start of the substitution layer, first share */
187  x0_ae ^= x4_ae;
188  x4_ae ^= x3_ae;
189  x2_ae ^= x1_ae;
190  t1_ae = x0_ae;
191 
192  /* Start of the substitution layer, second share */
193  x0_be ^= x4_be;
194  x4_be ^= x3_be;
195  x2_be ^= x1_be;
196  t1_be = x0_be;
197 
198  /* Start of the substitution layer, third share */
199  x0_ce ^= x4_ce;
200  x4_ce ^= x3_ce;
201  x2_ce ^= x1_ce;
202  t1_ce = x0_ce;
203 
204  /* Start of the substitution layer, fourth share */
205  x0_de ^= x4_de;
206  x4_de ^= x3_de;
207  x2_de ^= x1_de;
208  t1_de = x0_de;
209 
210  /* Middle part of the substitution layer, Chi5 */
211  t0_de = ascon_mask32_rotate_share3_0(t0_ae) ^ /* t0 = random shares */
214  and_not_xor(t0, x0, x1, e); /* t0 ^= (~x0) & x1; */
215  and_not_xor(x0, x1, x2, e); /* x0 ^= (~x1) & x2; */
216  and_not_xor(x1, x2, x3, e); /* x1 ^= (~x2) & x3; */
217  and_not_xor(x2, x3, x4, e); /* x2 ^= (~x3) & x4; */
218  and_not_xor(x3, x4, t1, e); /* x3 ^= (~x4) & t1; */
219  x4_ae ^= t0_ae; /* x4 ^= t0; */
220  x4_be ^= t0_be;
221  x4_ce ^= t0_ce;
222  x4_de ^= t0_de;
223 
224  /* End of the substitution layer */
225  x1_ae ^= x0_ae;
226  x0_ae ^= x4_ae;
227  x3_ae ^= x2_ae;
228  x1_be ^= x0_be;
229  x0_be ^= x4_be;
230  x3_be ^= x2_be;
231  x1_ce ^= x0_ce;
232  x0_ce ^= x4_ce;
233  x3_ce ^= x2_ce;
234  x1_de ^= x0_de;
235  x0_de ^= x4_de;
236  x3_de ^= x2_de;
237 
238  /* NOT'ing x2 is done as part of the next round constant */
239  /* x2_ae = ~x2_ae; */
240 
241  /* Substitution layer, odd words */
242 
243  /* Add the inverted round constant to x2 */
244  x2_ao ^= *rc++;
245 
246  /* Start of the substitution layer, first share */
247  x0_ao ^= x4_ao;
248  x4_ao ^= x3_ao;
249  x2_ao ^= x1_ao;
250  t1_ao = x0_ao;
251 
252  /* Start of the substitution layer, second share */
253  x0_bo ^= x4_bo;
254  x4_bo ^= x3_bo;
255  x2_bo ^= x1_bo;
256  t1_bo = x0_bo;
257 
258  /* Start of the substitution layer, third share */
259  x0_co ^= x4_co;
260  x4_co ^= x3_co;
261  x2_co ^= x1_co;
262  t1_co = x0_co;
263 
264  /* Start of the substitution layer, fourth share */
265  x0_do ^= x4_do;
266  x4_do ^= x3_do;
267  x2_do ^= x1_do;
268  t1_do = x0_do;
269 
270  /* Middle part of the substitution layer, Chi5 */
271  t0_do = ascon_mask32_rotate_share3_0(t0_ao) ^ /* t0 = random shares */
274  and_not_xor(t0, x0, x1, o); /* t0 ^= (~x0) & x1; */
275  and_not_xor(x0, x1, x2, o); /* x0 ^= (~x1) & x2; */
276  and_not_xor(x1, x2, x3, o); /* x1 ^= (~x2) & x3; */
277  and_not_xor(x2, x3, x4, o); /* x2 ^= (~x3) & x4; */
278  and_not_xor(x3, x4, t1, o); /* x3 ^= (~x4) & t1; */
279  x4_ao ^= t0_ao; /* x4 ^= t0; */
280  x4_bo ^= t0_bo;
281  x4_co ^= t0_co;
282  x4_do ^= t0_do;
283 
284  /* End of the substitution layer */
285  x1_ao ^= x0_ao;
286  x0_ao ^= x4_ao;
287  x3_ao ^= x2_ao;
288  x1_bo ^= x0_bo;
289  x0_bo ^= x4_bo;
290  x3_bo ^= x2_bo;
291  x1_co ^= x0_co;
292  x0_co ^= x4_co;
293  x3_co ^= x2_co;
294  x1_do ^= x0_do;
295  x0_do ^= x4_do;
296  x3_do ^= x2_do;
297 
298  /* NOT'ing x2 is done as part of the next round constant */
299  /* x2_ao = ~x2_ao; */
300 
301  /* Linear diffusion layer on each of the shares. Reuse some of
302  * the temporaries from substitution that we no longer require. */
303  #define t0 t0_de
304  #define t1 t0_do
305  #define t2 t1_ao
306  #define t3 t1_bo
307  #define t4 t1_co
308  #define t5 t1_do
309  #define t6 t1_ae
310  #define t7 t1_be
311  #define t8 t1_ce
312  #define t9 t1_de
313  linear(d);
314  linear(c);
315  linear(b);
316  linear(a);
317 
318  /* Rotate the randomness in t0 before the next round */
319  t0_ae = rightRotate7(t0_ae);
320  t0_ao = rightRotate7(t0_ao);
321  t0_be = rightRotate13(t0_be);
322  t0_bo = rightRotate13(t0_bo);
323  t0_ce = rightRotate29(t0_ce);
324  t0_co = rightRotate29(t0_co);
325  }
326 
327  /* Return the final randomness to the caller to preserve it */
328  ((uint32_t *)preserve)[0] = t0_ae;
329  ((uint32_t *)preserve)[1] = t0_ao;
330  ((uint32_t *)preserve)[2] = t0_be;
331  ((uint32_t *)preserve)[3] = t0_bo;
332  ((uint32_t *)preserve)[4] = t0_ce;
333  ((uint32_t *)preserve)[5] = t0_co;
334 
335  /* Store the local variables back to the state with a final invert of x2 */
336  state->M[0].W[0] = x0_ae;
337  state->M[0].W[1] = x0_ao;
338  state->M[0].W[2] = x0_be;
339  state->M[0].W[3] = x0_bo;
340  state->M[0].W[4] = x0_ce;
341  state->M[0].W[5] = x0_co;
342  state->M[0].W[6] = x0_de;
343  state->M[0].W[7] = x0_do;
344  state->M[1].W[0] = x1_ae;
345  state->M[1].W[1] = x1_ao;
346  state->M[1].W[2] = x1_be;
347  state->M[1].W[3] = x1_bo;
348  state->M[1].W[4] = x1_ce;
349  state->M[1].W[5] = x1_co;
350  state->M[1].W[6] = x1_de;
351  state->M[1].W[7] = x1_do;
352  state->M[2].W[0] = ~x2_ae;
353  state->M[2].W[1] = ~x2_ao;
354  state->M[2].W[2] = x2_be;
355  state->M[2].W[3] = x2_bo;
356  state->M[2].W[4] = x2_ce;
357  state->M[2].W[5] = x2_co;
358  state->M[2].W[6] = x2_de;
359  state->M[2].W[7] = x2_do;
360  state->M[3].W[0] = x3_ae;
361  state->M[3].W[1] = x3_ao;
362  state->M[3].W[2] = x3_be;
363  state->M[3].W[3] = x3_bo;
364  state->M[3].W[4] = x3_ce;
365  state->M[3].W[5] = x3_co;
366  state->M[3].W[6] = x3_de;
367  state->M[3].W[7] = x3_do;
368  state->M[4].W[0] = x4_ae;
369  state->M[4].W[1] = x4_ao;
370  state->M[4].W[2] = x4_be;
371  state->M[4].W[3] = x4_bo;
372  state->M[4].W[4] = x4_ce;
373  state->M[4].W[5] = x4_co;
374  state->M[4].W[6] = x4_de;
375  state->M[4].W[7] = x4_do;
376 }
377 
378 #endif /* ASCON_MASKED_X4_BACKEND_C32 */
#define ROUND_CONSTANT_PAIR(rc1, rc2)
Definition: ascon-c32.c:33
Utility functions for operating on masked ASCON states with between 2 and 4 shares.
void ascon_x4_permute(ascon_masked_state_t *state, uint8_t first_round, uint64_t *preserve)
Permutes the ASCON-x4 state with a specified number of rounds.
#define ascon_mask32_rotate_share3_2(x)
Rotates 32-bit masked share 3 with respect to share 2.
#define ascon_mask32_rotate_share3_1(x)
Rotates 32-bit masked share 3 with respect to share 1.
#define ascon_mask32_rotate_share3_0(x)
Rotates 32-bit masked share 3 with respect to share 0.
#define rightRotate13(a)
Definition: ascon-util.h:332
#define rightRotate7(a)
Definition: ascon-util.h:326
#define rightRotate29(a)
Definition: ascon-util.h:348
#define and_not_xor(x, y, z)
Computes x ^= (~y & z) with a 2-share masked representation.
Definition: ascon-x2-c64.c:36
ascon_state_t state
[snippet_key]
Definition: snippets.c:2
State of the ASCON permutation which has been masked with up to 4 shares.
uint32_t W[10]
Definition: permutation.h:65