Update copyright headers for dual licensing.
[gd/nettle] / serpent-decrypt.c
1 /* serpent-decrypt.c
2
3    The serpent block cipher.
4
5    For more details on this algorithm, see the Serpent website at
6    http://www.cl.cam.ac.uk/~rja14/serpent.html
7
8    Copyright (C) 2011  Niels Möller
9    Copyright (C) 2010, 2011  Simon Josefsson
10    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
11
12    This file is part of GNU Nettle.
13
14    GNU Nettle is free software: you can redistribute it and/or
15    modify it under the terms of either:
16
17      * the GNU Lesser General Public License as published by the Free
18        Software Foundation; either version 3 of the License, or (at your
19        option) any later version.
20
21    or
22
23      * the GNU General Public License as published by the Free
24        Software Foundation; either version 2 of the License, or (at your
25        option) any later version.
26
27    or both in parallel, as here.
28
29    GNU Nettle is distributed in the hope that it will be useful,
30    but WITHOUT ANY WARRANTY; without even the implied warranty of
31    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32    General Public License for more details.
33
34    You should have received copies of the GNU General Public License and
35    the GNU Lesser General Public License along with this program.  If
36    not, see http://www.gnu.org/licenses/.
37 */
38
39 /* This file is derived from cipher/serpent.c in Libgcrypt v1.4.6.
40    The adaption to Nettle was made by Simon Josefsson on 2010-12-07
41    with final touches on 2011-05-30.  Changes include replacing
42    libgcrypt with nettle in the license template, renaming
43    serpent_context to serpent_ctx, renaming u32 to uint32_t, removing
44    libgcrypt stubs and selftests, modifying entry function prototypes,
45    using FOR_BLOCKS to iterate through data in encrypt/decrypt, using
46    LE_READ_UINT32 and LE_WRITE_UINT32 to access data in
47    encrypt/decrypt, and running indent on the code. */
48
49 #if HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <assert.h>
54 #include <limits.h>
55
56 #include "serpent.h"
57
58 #include "macros.h"
59 #include "serpent-internal.h"
60
61 /* These are the S-Boxes of Serpent.  They are copied from Serpents
62    reference implementation (the optimized one, contained in
63    `floppy2') and are therefore:
64
65      Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen.
66
67   To quote the Serpent homepage
68   (http://www.cl.cam.ac.uk/~rja14/serpent.html):
69
70   "Serpent is now completely in the public domain, and we impose no
71    restrictions on its use.  This was announced on the 21st August at
72    the First AES Candidate Conference. The optimised implementations
73    in the submission package are now under the GNU PUBLIC LICENSE
74    (GPL), although some comments in the code still say otherwise. You
75    are welcome to use Serpent for any application."  */
76
77 /* S0 inverse:  13  3 11  0 10  6  5 12  1 14  4  7 15  9  8  2 */
78 /* Original single-assignment form:
79
80      t01 = x2  ^ x3;
81      t02 = x0  | x1;
82      t03 = x1  | x2;
83      t04 = x2  & t01;
84      t05 = t02 ^ t01;
85      t06 = x0  | t04;
86      y2  =     ~ t05;
87      t08 = x1  ^ x3;
88      t09 = t03 & t08;
89      t10 = x3  | y2;
90      y1  = t09 ^ t06;
91      t12 = x0  | t05;
92      t13 = y1  ^ t12;
93      t14 = t03 ^ t10;
94      t15 = x0  ^ x2;
95      y3  = t14 ^ t13;
96      t17 = t05 & t13;
97      t18 = t14 | t17;
98      y0  = t15 ^ t18;
99 */
100 #define SBOX0_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)           \
101   do {                                                          \
102     y0  = x0 ^ x2;                                              \
103     y2  = x0 | x1;                                              \
104     y1  = x2 ^ x3;                                              \
105     y2 ^= y1;                                                   \
106     y1 &= x2;                                                   \
107     x2 |= x1;                                                   \
108     x1 ^= x3;                                                   \
109     y1 |= x0;                                                   \
110     x1 &= x2;                                                   \
111     y1 ^= x1;                                                   \
112     x0 |= y2;                                                   \
113     x0 ^= y1;                                                   \
114     x1  = y2 & x0;                                              \
115     y2  = ~ y2;                                                 \
116     x3 |= y2;                                                   \
117     x3 ^= x2;                                                   \
118     y3  = x3 ^ x0;                                              \
119     x1 |= x3;                                                   \
120     y0 ^= x1;                                                   \
121   } while (0)
122
123 /* S1 inverse:   5  8  2 14 15  6 12  3 11  4  7  9  1 13 10  0 */
124 /* Original single-assignment form:
125      t01 = x0  ^ x1;
126      t02 = x1  | x3;
127      t03 = x0  & x2;
128      t04 = x2  ^ t02;
129      t05 = x0  | t04;
130      t06 = t01 & t05;
131      t07 = x3  | t03;
132      t08 = x1  ^ t06;
133      t09 = t07 ^ t06;
134      t10 = t04 | t03;
135      t11 = x3  & t08;
136      y2  =     ~ t09;
137      y1  = t10 ^ t11;
138      t14 = x0  | y2;
139      t15 = t06 ^ y1;
140      y3  = t01 ^ t04;
141      t17 = x2  ^ t15;
142      y0  = t14 ^ t17;
143 */
144 #define SBOX1_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)       \
145   do {                                                      \
146     y1  = x1 | x3;                                          \
147     y1 ^= x2;                                               \
148     y3  = x0 ^ x1;                                          \
149     y0  = x0 | y1;                                          \
150     y0 &= y3;                                               \
151     x1 ^= y0;                                               \
152     y3 ^= y1;                                               \
153     x1 &= x3;                                               \
154     y2  = x0 & x2;                                          \
155     y1 |= y2;                                               \
156     y2 |= x3;                                               \
157     y2 ^= y0;                                               \
158     y2  = ~ y2;                                             \
159     y1 ^= x1;                                               \
160     y0 ^= y1;                                               \
161     y0 ^= x2;                                               \
162     x0 |= y2;                                               \
163     y0 ^= x0;                                               \
164   } while (0)
165
166 /* S2 inverse:  12  9 15  4 11 14  1  2  0  3  6 13  5  8 10  7 */
167 /* Original single-assignment form:
168      t01 = x0  ^ x3;
169      t02 = x2  ^ x3;
170      t03 = x0  & x2;
171      t04 = x1  | t02;
172      y0  = t01 ^ t04;
173      t06 = x0  | x2;
174      t07 = x3  | y0;
175      t08 =     ~ x3;
176      t09 = x1  & t06;
177      t10 = t08 | t03;
178      t11 = x1  & t07;
179      t12 = t06 & t02;
180      y3  = t09 ^ t10;
181      y1  = t12 ^ t11;
182      t15 = x2  & y3;
183      t16 = y0  ^ y1;
184      t17 = t10 ^ t15;
185      y2  = t16 ^ t17;
186 */
187 #define SBOX2_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)           \
188   do {                                                          \
189     y0  = x0 ^ x3;                                              \
190     y2  = x2 ^ x3;                                              \
191     y1  = x1 | y2;                                              \
192     y0 ^= y1;                                                   \
193     y1  = x3 | y0;                                              \
194     y1 &= x1;                                                   \
195     x3  = ~ x3;                                                 \
196     y3  = x0 | x2;                                              \
197     y2 &= y3;                                                   \
198     y1 ^= y2;                                                   \
199     y3 &= x1;                                                   \
200     x0 &= x2;                                                   \
201     x0 |= x3;                                                   \
202     y3 ^= x0;                                                   \
203     x2 &= y3;                                                   \
204     x2 ^= x0;                                                   \
205     y2  = y0 ^ y1;                                              \
206     y2 ^= x2;                                                   \
207   } while (0)
208
209 /* S3 inverse:   0  9 10  7 11 14  6 13  3  5 12  2  4  8 15  1 */
210 /* Original single-assignment form:
211      t01 = x2  | x3;
212      t02 = x0  | x3;
213      t03 = x2  ^ t02;
214      t04 = x1  ^ t02;
215      t05 = x0  ^ x3;
216      t06 = t04 & t03;
217      t07 = x1  & t01;
218      y2  = t05 ^ t06;
219      t09 = x0  ^ t03;
220      y0  = t07 ^ t03;
221      t11 = y0  | t05;
222      t12 = t09 & t11;
223      t13 = x0  & y2;
224      t14 = t01 ^ t05;
225      y1  = x1  ^ t12;
226      t16 = x1  | t13;
227      y3  = t14 ^ t16;
228 */
229 #define SBOX3_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)       \
230   do {                                                      \
231     y3  = x2 | x3;                                          \
232     y0  = x1 & y3;                                          \
233     y2  = x0 | x3;                                          \
234     y1  = x2 ^ y2;                                          \
235     y0 ^= y1;                                               \
236     x3 ^= x0;                                               \
237     y3 ^= x3;                                               \
238     y2 ^= x1;                                               \
239     y2 &= y1;                                               \
240     y2 ^= x3;                                               \
241     y1 ^= x0;                                               \
242     x3 |= y0;                                               \
243     y1 &= x3;                                               \
244     y1 ^= x1;                                               \
245     x0 &= y2;                                               \
246     x0 |= x1;                                               \
247     y3 ^= x0;                                               \
248   } while (0)
249
250 /* S4 inverse:   5  0  8  3 10  9  7 14  2 12 11  6  4 15 13  1 */
251 /* Original single-assignment form:
252      t01 = x1  | x3;
253      t02 = x2  | x3;
254      t03 = x0  & t01;
255      t04 = x1  ^ t02;
256      t05 = x2  ^ x3;
257      t06 =     ~ t03;
258      t07 = x0  & t04;
259      y1  = t05 ^ t07;
260      t09 = y1  | t06;
261      t10 = x0  ^ t07;
262      t11 = t01 ^ t09;
263      t12 = x3  ^ t04;
264      t13 = x2  | t10;
265      y3  = t03 ^ t12;
266      t15 = x0  ^ t04;
267      y2  = t11 ^ t13;
268      y0  = t15 ^ t09;
269 */
270 #define SBOX4_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)       \
271   do {                                                      \
272     y1  = x2 ^ x3;                                          \
273     y2  = x2 | x3;                                          \
274     y2 ^= x1;                                               \
275     x1 |= x3;                                               \
276     y0  = x0 ^ y2;                                          \
277     x3 ^= y2;                                               \
278     y2 &= x0;                                               \
279     y1 ^= y2;                                               \
280     y2 ^= x0;                                               \
281     y2 |= x2;                                               \
282     x0 &=  x1;                                              \
283     y3  = x0 ^ x3;                                          \
284     x0  = ~ x0;                                             \
285     x0 |= y1;                                               \
286     y0 ^= x0;                                               \
287     x0 ^= x1;                                               \
288     y2 ^= x0;                                               \
289   } while (0)
290
291 /* S5 inverse:   8 15  2  9  4  1 13 14 11  6  5  3  7 12 10  0 */
292 /* Original single-assignment form:
293      t01 = x0  & x3;
294      t02 = x2  ^ t01;
295      t03 = x0  ^ x3;
296      t04 = x1  & t02;
297      t05 = x0  & x2;
298      y0  = t03 ^ t04;
299      t07 = x0  & y0;
300      t08 = t01 ^ y0;
301      t09 = x1  | t05;
302      t10 =     ~ x1;
303      y1  = t08 ^ t09;
304      t12 = t10 | t07;
305      t13 = y0  | y1;
306      y3  = t02 ^ t12;
307      t15 = t02 ^ t13;
308      t16 = x1  ^ x3;
309      y2  = t16 ^ t15;
310 */
311 #define SBOX5_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)       \
312   do {                                                      \
313     y1  = x0 & x3;                                          \
314     y3  = x2 ^ y1;                                          \
315     y0  = x1 & y3;                                          \
316     y2  = x0 ^ x3;                                          \
317     x3 ^= x1;                                               \
318     y0 ^= y2;                                               \
319     x2 &= x0;                                               \
320     x0 &= y0;                                               \
321     x2 |= x1;                                               \
322     y1 ^= y0;                                               \
323     y1 ^= x2;                                               \
324     y2  = y0 | y1;                                          \
325     y2 ^= y3;                                               \
326     y2 ^= x3;                                               \
327     x1  = ~ x1;                                             \
328     x1 |= x0;                                               \
329     y3 ^= x1;                                               \
330   } while (0)
331
332 /* S6 inverse:  15 10  1 13  5  3  6  0  4  9 14  7  2 12  8 11 */
333 /* Original single-assignment form:
334      t01 = x0  ^ x2;
335      t02 =     ~ x2;
336      t03 = x1  & t01;
337      t04 = x1  | t02;
338      t05 = x3  | t03;
339      t06 = x1  ^ x3;
340      t07 = x0  & t04;
341      t08 = x0  | t02;
342      t09 = t07 ^ t05;
343      y1  = t06 ^ t08;
344      y0  =     ~ t09;
345      t12 = x1  & y0;
346      t13 = t01 & t05;
347      t14 = t01 ^ t12;
348      t15 = t07 ^ t13;
349      t16 = x3  | t02;
350      t17 = x0  ^ y1;
351      y3  = t17 ^ t15;
352      y2  = t16 ^ t14;
353  */
354 #define SBOX6_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)       \
355   do {                                                      \
356     y2  = x0 ^ x2;                                          \
357     x2  = ~ x2;                                             \
358     y0  = x1 ^ x3;                                          \
359     y1  = x0 | x2;                                          \
360     y1 ^= y0;                                               \
361     y3  = x1 & y2;                                          \
362     y3 |= x3;                                               \
363     x3 |= x2;                                               \
364     x2 |= x1;                                               \
365     x2 &= x0;                                               \
366     y0  = x2 ^ y3;                                          \
367     y0  = ~ y0;                                             \
368     y3 &= y2;                                               \
369     y3 ^= x2;                                               \
370     x0 ^= y1;                                               \
371     y3 ^= x0;                                               \
372     x1 &= y0;                                               \
373     y2 ^= x1;                                               \
374     y2 ^= x3;                                               \
375   } while (0)
376
377 /* S7 inverse:   3  0  6 13  9 14 15  8  5 12 11  7 10  1  4  2 */
378 /* Original single-assignment form:
379      t01 = x0  & x1;
380      t02 = x0  | x1;
381      t03 = x2  | t01;
382      t04 = x3  & t02;
383      y3  = t03 ^ t04;
384      t06 = x1  ^ t04;
385      t07 = x3  ^ y3;
386      t08 =     ~ t07;
387      t09 = t06 | t08;
388      t10 = x1  ^ x3;
389      t11 = x0  | x3;
390      y1  = x0  ^ t09;
391      t13 = x2  ^ t06;
392      t14 = x2  & t11;
393      t15 = x3  | y1;
394      t16 = t01 | t10;
395      y0  = t13 ^ t15;
396      y2  = t14 ^ t16;
397 */
398 #define SBOX7_INVERSE(x0, x1, x2, x3, y0, y1, y2, y3)       \
399   do {                                                      \
400     y3  = x0 & x1;                                          \
401     y2  = x1 ^ x3;                                          \
402     y2 |= y3;                                               \
403     y1  = x0 | x3;                                          \
404     y1 &= x2;                                               \
405     y2 ^= y1;                                               \
406     y3 |= x2;                                               \
407     y0  = x0 | x1;                                          \
408     y0 &= x3;                                               \
409     y3 ^= y0;                                               \
410     y0 ^= x1;                                               \
411     y1  = x3 ^ y3;                                          \
412     y1  = ~ y1;                                             \
413     y1 |= y0;                                               \
414     y0 ^= x2;                                               \
415     y1 ^= x0;                                               \
416     x3 |= y1;                                               \
417     y0 ^= x3;                                               \
418   } while (0)
419
420 /* In-place inverse linear transformation.  */
421 #define LINEAR_TRANSFORMATION_INVERSE(x0,x1,x2,x3)       \
422   do {                                                   \
423     x2 = ROTL32 (10, x2);                    \
424     x0 = ROTL32 (27, x0);                    \
425     x2 = x2 ^ x3 ^ (x1 << 7); \
426     x0 = x0 ^ x1 ^ x3;        \
427     x3 = ROTL32 (25, x3);                     \
428     x1 = ROTL32 (31, x1);                     \
429     x3 = x3 ^ x2 ^ (x0 << 3); \
430     x1 = x1 ^ x0 ^ x2;        \
431     x2 = ROTL32 (29, x2);                     \
432     x0 = ROTL32 (19, x0);                    \
433   } while (0)
434
435 /* Round inputs are x0,x1,x2,x3 (destroyed), and round outputs are
436    y0,y1,y2,y3. */
437 #define ROUND_INVERSE(which, subkey, x0,x1,x2,x3, y0,y1,y2,y3) \
438   do {                                                         \
439     LINEAR_TRANSFORMATION_INVERSE (x0,x1,x2,x3);               \
440     SBOX##which##_INVERSE(x0,x1,x2,x3, y0,y1,y2,y3);           \
441     KEYXOR(y0,y1,y2,y3, subkey);                               \
442   } while (0)
443
444 #if HAVE_NATIVE_64_BIT
445
446 /* In-place inverse linear transformation.  */
447 #define LINEAR_TRANSFORMATION64_INVERSE(x0,x1,x2,x3)     \
448   do {                                                   \
449     x2 = DROTL32 (10, x2);                    \
450     x0 = DROTL32 (27, x0);                    \
451     x2 = x2 ^ x3 ^ DRSHIFT32(7, x1); \
452     x0 = x0 ^ x1 ^ x3;        \
453     x3 = DROTL32 (25, x3);                     \
454     x1 = DROTL32 (31, x1);                     \
455     x3 = x3 ^ x2 ^ DRSHIFT32(3, x0); \
456     x1 = x1 ^ x0 ^ x2;        \
457     x2 = DROTL32 (29, x2);                     \
458     x0 = DROTL32 (19, x0);                    \
459   } while (0)
460
461 #define ROUND64_INVERSE(which, subkey, x0,x1,x2,x3, y0,y1,y2,y3) \
462   do {                                                         \
463     LINEAR_TRANSFORMATION64_INVERSE (x0,x1,x2,x3);             \
464     SBOX##which##_INVERSE(x0,x1,x2,x3, y0,y1,y2,y3);           \
465     KEYXOR64(y0,y1,y2,y3, subkey);                             \
466   } while (0)
467
468 #endif /* HAVE_NATIVE_64_BIT */
469
470 void
471 serpent_decrypt (const struct serpent_ctx *ctx,
472                  size_t length, uint8_t * dst, const uint8_t * src)
473 {
474   assert( !(length % SERPENT_BLOCK_SIZE));
475
476 #if HAVE_NATIVE_64_BIT
477   if (length & SERPENT_BLOCK_SIZE)
478 #else
479   while (length >= SERPENT_BLOCK_SIZE)
480 #endif
481     {
482       uint32_t x0,x1,x2,x3, y0,y1,y2,y3;
483       unsigned k;
484
485       x0 = LE_READ_UINT32 (src);
486       x1 = LE_READ_UINT32 (src + 4);
487       x2 = LE_READ_UINT32 (src + 8);
488       x3 = LE_READ_UINT32 (src + 12);
489
490       /* Inverse of special round */
491       KEYXOR (x0,x1,x2,x3, ctx->keys[32]);
492       SBOX7_INVERSE (x0,x1,x2,x3, y0,y1,y2,y3);
493       KEYXOR (y0,y1,y2,y3, ctx->keys[31]);
494
495       k = 24;
496       goto start32;
497       while (k > 0)
498         {
499           k -= 8;
500           ROUND_INVERSE (7, ctx->keys[k+7], x0,x1,x2,x3, y0,y1,y2,y3);
501         start32:
502           ROUND_INVERSE (6, ctx->keys[k+6], y0,y1,y2,y3, x0,x1,x2,x3);
503           ROUND_INVERSE (5, ctx->keys[k+5], x0,x1,x2,x3, y0,y1,y2,y3);
504           ROUND_INVERSE (4, ctx->keys[k+4], y0,y1,y2,y3, x0,x1,x2,x3);
505           ROUND_INVERSE (3, ctx->keys[k+3], x0,x1,x2,x3, y0,y1,y2,y3);
506           ROUND_INVERSE (2, ctx->keys[k+2], y0,y1,y2,y3, x0,x1,x2,x3);
507           ROUND_INVERSE (1, ctx->keys[k+1], x0,x1,x2,x3, y0,y1,y2,y3);
508           ROUND_INVERSE (0, ctx->keys[k], y0,y1,y2,y3, x0,x1,x2,x3);
509         }
510       
511       LE_WRITE_UINT32 (dst, x0);
512       LE_WRITE_UINT32 (dst + 4, x1);
513       LE_WRITE_UINT32 (dst + 8, x2);
514       LE_WRITE_UINT32 (dst + 12, x3);
515
516       src += SERPENT_BLOCK_SIZE;
517       dst += SERPENT_BLOCK_SIZE;
518       length -= SERPENT_BLOCK_SIZE;
519     }
520 #if HAVE_NATIVE_64_BIT
521   FOR_BLOCKS(length, dst, src, 2*SERPENT_BLOCK_SIZE)
522     {
523       uint64_t x0,x1,x2,x3, y0,y1,y2,y3;
524       unsigned k;
525
526       x0 = LE_READ_UINT32 (src);
527       x1 = LE_READ_UINT32 (src + 4);
528       x2 = LE_READ_UINT32 (src + 8);
529       x3 = LE_READ_UINT32 (src + 12);
530
531       x0 <<= 32; x0 |= LE_READ_UINT32 (src + 16);
532       x1 <<= 32; x1 |= LE_READ_UINT32 (src + 20);
533       x2 <<= 32; x2 |= LE_READ_UINT32 (src + 24);
534       x3 <<= 32; x3 |= LE_READ_UINT32 (src + 28);
535
536       /* Inverse of special round */
537       KEYXOR64 (x0,x1,x2,x3, ctx->keys[32]);
538       SBOX7_INVERSE (x0,x1,x2,x3, y0,y1,y2,y3);
539       KEYXOR64 (y0,y1,y2,y3, ctx->keys[31]);
540
541       k = 24;
542       goto start64;
543       while (k > 0)
544         {
545           k -= 8;
546           ROUND64_INVERSE (7, ctx->keys[k+7], x0,x1,x2,x3, y0,y1,y2,y3);
547         start64:
548           ROUND64_INVERSE (6, ctx->keys[k+6], y0,y1,y2,y3, x0,x1,x2,x3);
549           ROUND64_INVERSE (5, ctx->keys[k+5], x0,x1,x2,x3, y0,y1,y2,y3);
550           ROUND64_INVERSE (4, ctx->keys[k+4], y0,y1,y2,y3, x0,x1,x2,x3);
551           ROUND64_INVERSE (3, ctx->keys[k+3], x0,x1,x2,x3, y0,y1,y2,y3);
552           ROUND64_INVERSE (2, ctx->keys[k+2], y0,y1,y2,y3, x0,x1,x2,x3);
553           ROUND64_INVERSE (1, ctx->keys[k+1], x0,x1,x2,x3, y0,y1,y2,y3);
554           ROUND64_INVERSE (0, ctx->keys[k], y0,y1,y2,y3, x0,x1,x2,x3);
555         }
556     
557       LE_WRITE_UINT32 (dst + 16, x0);
558       LE_WRITE_UINT32 (dst + 20, x1);
559       LE_WRITE_UINT32 (dst + 24, x2);
560       LE_WRITE_UINT32 (dst + 28, x3);
561       x0 >>= 32; LE_WRITE_UINT32 (dst, x0);
562       x1 >>= 32; LE_WRITE_UINT32 (dst + 4, x1);
563       x2 >>= 32; LE_WRITE_UINT32 (dst + 8, x2);
564       x3 >>= 32; LE_WRITE_UINT32 (dst + 12, x3);
565     }
566 #endif /* HAVE_NATIVE_64_BIT */  
567 }