]> git.ipfire.org Git - thirdparty/nettle.git/blame - serpent-encrypt.c
Use NETTLE_OCTET_SIZE_TO_LIMB_SIZE macro.
[thirdparty/nettle.git] / serpent-encrypt.c
CommitLineData
00a6c2d1 1/* serpent-encrypt.c
90112edb
NM
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*/
00a6c2d1
NM
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
00a6c2d1 77/* S0: 3 8 15 1 10 6 5 11 14 13 4 2 7 0 9 12 */
66b7bda5 78/* Could easily let y0, y1 overlap with x0, x1, and possibly also x2 and y2 */
3c5e8649 79#define SBOX0(x0, x1, x2, x3, y0, y1, y2, y3) \
66b7bda5
NM
80 do { \
81 y3 = x1 ^ x2; \
82 y0 = x0 | x3; \
83 y1 = x0 ^ x1; \
84 y3 ^= y0; \
85 y2 = x2 | y3; \
86 x0 ^= x3; \
87 y2 &= x3; \
88 x3 ^= x2; \
89 x2 |= x1; \
90 y0 = y1 & x2; \
91 y2 ^= y0; \
92 y0 &= y2; \
93 y0 ^= x2; \
94 x1 &= x0; \
95 y0 ^= x0; \
96 y0 = ~ y0; \
97 y1 = y0 ^ x1; \
98 y1 ^= x3; \
00a6c2d1
NM
99 } while (0)
100
2c32cfc7 101/* FIXME: Arrange for some overlap between inputs and outputs? */
00a6c2d1 102/* S1: 15 12 2 7 9 0 5 10 1 11 14 8 6 13 3 4 */
d9a172fd
NM
103/* Original single-assignment form:
104
fe7695d1
NM
105 t01 = x0 | x3;
106 t02 = x2 ^ x3;
107 t03 = ~ x1;
108 t04 = x0 ^ x2;
109 t05 = x0 | t03;
110 t06 = x3 & t04;
111 t07 = t01 & t02;
112 t08 = x1 | t06;
113 y2 = t02 ^ t05;
114 t10 = t07 ^ t08;
115 t11 = t01 ^ t10;
116 t12 = y2 ^ t11;
117 t13 = x1 & x3;
d9a172fd 118 y3 = ~ t10;
fe7695d1
NM
119 y1 = t13 ^ t12;
120 t16 = t10 | y1;
121 t17 = t05 & t16;
122 y0 = x2 ^ t17;
d9a172fd
NM
123*/
124#define SBOX1(x0, x1, x2, x3, y0, y1, y2, y3) \
dae705f5
NM
125 do { \
126 y1 = x0 | x3; \
127 y2 = x2 ^ x3; \
128 y0 = ~ x1; \
61c1cfc3 129 y3 = x0 ^ x2; \
dae705f5
NM
130 y0 |= x0; \
131 y3 &= x3; \
132 x0 = y1 & y2; \
133 y3 |= x1; \
134 y2 ^= y0; \
135 y3 ^= x0; \
136 x0 = y1 ^ y3; \
137 x0 ^= y2; \
61c1cfc3 138 y1 = x1 & x3; \
dae705f5 139 y1 ^= x0; \
d9a172fd 140 x3 = y1 | y3; \
dae705f5
NM
141 y3 = ~ y3; \
142 y0 &= x3; \
143 y0 ^= x2; \
00a6c2d1
NM
144 } while (0)
145
2c32cfc7 146/* FIXME: Arrange for some overlap between inputs and outputs? */
00a6c2d1 147/* S2: 8 6 7 9 3 12 10 15 13 1 14 4 0 11 5 2 */
3c5e8649 148#define SBOX2(x0, x1, x2, x3, y0, y1, y2, y3) \
2c32cfc7
NM
149 do { \
150 y2 = x0 | x2; \
151 y1 = x0 ^ x1; \
152 y3 = x3 ^ y2; \
153 y0 = y1 ^ y3; \
154 x3 |= x0; \
155 x2 ^= y0; \
156 x0 = x1 ^ x2; \
157 x2 |= x1; \
158 x0 &= y2; \
159 y3 ^= x2; \
160 y1 |= y3; \
161 y1 ^= x0; \
162 y2 = y3 ^ y1; \
163 y2 ^= x1; \
164 y3 = ~ y3; \
165 y2 ^= x3; \
00a6c2d1
NM
166 } while (0)
167
168/* S3: 0 15 11 8 12 9 6 3 13 1 2 4 10 7 5 14 */
2b39cfeb
NM
169/* Original single-assignment form:
170
171 t01 = x0 ^ x2;
172 t02 = x0 | x3;
173 t03 = x0 & x3;
174 t04 = t01 & t02;
175 t05 = x1 | t03;
176 t06 = x0 & x1;
177 t07 = x3 ^ t04;
178 t08 = x2 | t06;
179 t09 = x1 ^ t07;
180 t10 = x3 & t05;
181 t11 = t02 ^ t10;
182 y3 = t08 ^ t09;
183 t13 = x3 | y3;
184 t14 = x0 | t07;
185 t15 = x1 & t13;
186 y2 = t08 ^ t11;
187 y0 = t14 ^ t15;
188 y1 = t05 ^ t04;
189*/
3c5e8649 190#define SBOX3(x0, x1, x2, x3, y0, y1, y2, y3) \
d778b2da 191 do { \
61c1cfc3 192 y1 = x0 ^ x2; \
d778b2da
NM
193 y0 = x0 | x3; \
194 y3 = x0 & x3; \
61c1cfc3 195 y1 &= y0; \
d778b2da 196 y3 |= x1; \
61c1cfc3 197 y2 = x0 & x1; \
d778b2da 198 y2 |= x2; \
61c1cfc3 199 x2 = x3 ^ y1; \
d778b2da
NM
200 y1 ^= y3; \
201 x0 |= x2; \
202 x2 ^= x1; \
203 y3 &= x3; \
204 y0 ^= y3; \
205 y3 = y2 ^ x2; \
206 y2 ^= y0; \
207 x3 |= y3; \
208 x1 &= x3; \
209 y0 = x0 ^ x1; \
00a6c2d1
NM
210 } while (0)
211
2b39cfeb 212
00a6c2d1 213/* S4: 1 15 8 3 12 0 11 6 2 5 4 10 9 14 7 13 */
2b39cfeb
NM
214/* Original single-assignment form:
215 t01 = x0 | x1;
216 t02 = x1 | x2;
217 t03 = x0 ^ t02;
218 t04 = x1 ^ x3;
219 t05 = x3 | t03;
220 t06 = x3 & t01;
221 y3 = t03 ^ t06;
222 t08 = y3 & t04;
223 t09 = t04 & t05;
224 t10 = x2 ^ t06;
225 t11 = x1 & x2;
226 t12 = t04 ^ t08;
227 t13 = t11 | t03;
228 t14 = t10 ^ t09;
229 t15 = x0 & t05;
230 t16 = t11 | t12;
231 y2 = t13 ^ t08;
232 y1 = t15 ^ t16;
233 y0 = ~ t14;
234*/
3c5e8649 235#define SBOX4(x0, x1, x2, x3, y0, y1, y2, y3) \
b44a75d0
NM
236 do { \
237 y3 = x0 | x1; \
238 y2 = x1 | x2; \
61c1cfc3 239 y2 ^= x0; \
b44a75d0
NM
240 y3 &= x3; \
241 y0 = x1 ^ x3; \
242 x3 |= y2; \
243 x0 &= x3; \
244 x1 &= x2; \
245 x2 ^= y3; \
246 y3 ^= y2; \
247 y2 |= x1; \
248 y1 = y3 & y0; \
249 y2 ^= y1; \
250 y1 ^= y0; \
251 y1 |= x1; \
252 y1 ^= x0; \
253 y0 &= x3; \
254 y0 ^= x2; \
255 y0 = ~y0; \
00a6c2d1
NM
256 } while (0)
257
258/* S5: 15 5 2 11 4 10 9 12 0 3 14 8 13 6 7 1 */
9474fe42
NM
259/* Original single-assignment form:
260 t01 = x1 ^ x3;
261 t02 = x1 | x3;
262 t03 = x0 & t01;
263 t04 = x2 ^ t02;
264 t05 = t03 ^ t04;
265 y0 = ~ t05;
266 t07 = x0 ^ t01;
267 t08 = x3 | y0;
268 t09 = x1 | t05;
269 t10 = x3 ^ t08;
270 t11 = x1 | t07;
271 t12 = t03 | y0;
272 t13 = t07 | t10;
273 t14 = t01 ^ t11;
274 y2 = t09 ^ t13;
275 y1 = t07 ^ t08;
276 y3 = t12 ^ t14;
277*/
3c5e8649 278#define SBOX5(x0, x1, x2, x3, y0, y1, y2, y3) \
9474fe42
NM
279 do { \
280 y0 = x1 | x3; \
281 y0 ^= x2; \
282 x2 = x1 ^ x3; \
283 y2 = x0 ^ x2; \
284 x0 &= x2; \
285 y0 ^= x0; \
286 y3 = x1 | y2; \
287 x1 |= y0; \
288 y0 = ~y0; \
289 x0 |= y0; \
290 y3 ^= x2; \
291 y3 ^= x0; \
292 y1 = x3 | y0; \
293 x3 ^= y1; \
294 y1 ^= y2; \
295 y2 |= x3; \
296 y2 ^= x1; \
00a6c2d1
NM
297 } while (0)
298
299/* S6: 7 2 12 5 8 4 6 11 14 9 1 15 13 3 10 0 */
3c5e8649
NM
300/* Original single-assignment form:
301 t01 = x0 & x3;
302 t02 = x1 ^ x2;
303 t03 = x0 ^ x3;
304 t04 = t01 ^ t02;
305 t05 = x1 | x2;
306 y1 = ~ t04;
307 t07 = t03 & t05;
308 t08 = x1 & y1;
309 t09 = x0 | x2;
310 t10 = t07 ^ t08;
311 t11 = x1 | x3;
312 t12 = x2 ^ t11;
313 t13 = t09 ^ t10;
314 y2 = ~ t13;
315 t15 = y1 & t03;
316 y3 = t12 ^ t07;
317 t17 = x0 ^ x1;
318 t18 = y2 ^ t15;
319 y0 = t17 ^ t18;
320*/
321#define SBOX6(x0, x1, x2, x3, y0, y1, y2, y3) \
322 do { \
323 y0 = x0 ^ x3; \
324 y1 = x0 & x3; \
325 y2 = x0 | x2; \
326 x3 |= x1; \
327 x3 ^= x2; \
328 x0 ^= x1; \
329 y3 = x1 | x2; \
330 x2 ^= x1; \
331 y3 &= y0; \
332 y1 ^= x2; \
333 y1 = ~y1; \
334 y0 &= y1; \
335 x1 &= y1; \
336 x1 ^= y3; \
337 y3 ^= x3; \
338 y2 ^= x1; \
339 y2 = ~y2; \
340 y0 ^= y2; \
341 y0 ^= x0; \
00a6c2d1
NM
342 } while (0)
343
344/* S7: 1 13 15 0 14 8 2 11 7 4 12 10 9 3 5 6 */
3c5e8649
NM
345/* Original single-assignment form:
346 t01 = x0 & x2;
347 t02 = ~ x3;
348 t03 = x0 & t02;
349 t04 = x1 | t01;
350 t05 = x0 & x1;
351 t06 = x2 ^ t04;
352 y3 = t03 ^ t06;
353 t08 = x2 | y3;
354 t09 = x3 | t05;
355 t10 = x0 ^ t08;
356 t11 = t04 & y3;
357 y1 = t09 ^ t10;
358 t13 = x1 ^ y1;
359 t14 = t01 ^ y1;
360 t15 = x2 ^ t05;
361 t16 = t11 | t13;
362 t17 = t02 | t14;
363 y0 = t15 ^ t17;
364 y2 = x0 ^ t16;
365*/
366/* It appears impossible to do this with only 8 registers. We
367 recompute t02, and t04 (if we have spare registers, hopefully the
9946d3df 368 compiler can recognize them as common subexpressions). */
3c5e8649
NM
369#define SBOX7(x0, x1, x2, x3, y0, y1, y2, y3) \
370 do { \
371 y0 = x0 & x2; \
372 y3 = x1 | y0; /* t04 */ \
373 y3 ^= x2; \
374 y1 = ~x3; /* t02 */ \
375 y1 &= x0; \
376 y3 ^= y1; \
377 y1 = x2 | y3; \
378 y1 ^= x0; \
379 y2 = x0 & x1; \
380 x2 ^= y2; \
381 y2 |= x3; \
382 y1 ^= y2; \
383 y2 = x1 | y0; /* t04 */ \
384 y2 &= y3; \
385 x1 ^= y1; \
386 y2 |= x1; \
387 y2 ^= x0; \
388 y0 ^= y1; \
389 x3 = ~x3; /* t02 */ \
390 y0 |= x3; \
391 y0 ^= x2; \
00a6c2d1
NM
392 } while (0)
393
394/* In-place linear transformation. */
395#define LINEAR_TRANSFORMATION(x0,x1,x2,x3) \
396 do { \
8a56233b
NM
397 x0 = ROTL32 (13, x0); \
398 x2 = ROTL32 (3, x2); \
00a6c2d1
NM
399 x1 = x1 ^ x0 ^ x2; \
400 x3 = x3 ^ x2 ^ (x0 << 3); \
8a56233b
NM
401 x1 = ROTL32 (1, x1); \
402 x3 = ROTL32 (7, x3); \
00a6c2d1
NM
403 x0 = x0 ^ x1 ^ x3; \
404 x2 = x2 ^ x3 ^ (x1 << 7); \
8a56233b
NM
405 x0 = ROTL32 (5, x0); \
406 x2 = ROTL32 (22, x2); \
00a6c2d1
NM
407 } while (0)
408
409/* Round inputs are x0,x1,x2,x3 (destroyed), and round outputs are
410 y0,y1,y2,y3. */
411#define ROUND(which, subkey, x0,x1,x2,x3, y0,y1,y2,y3) \
412 do { \
413 KEYXOR(x0,x1,x2,x3, subkey); \
3c5e8649 414 SBOX##which(x0,x1,x2,x3, y0,y1,y2,y3); \
00a6c2d1
NM
415 LINEAR_TRANSFORMATION(y0,y1,y2,y3); \
416 } while (0)
417
418#if HAVE_NATIVE_64_BIT
419
420#define LINEAR_TRANSFORMATION64(x0,x1,x2,x3) \
421 do { \
d20990fd
NM
422 x0 = DROTL32 (13, x0); \
423 x2 = DROTL32 (3, x2); \
00a6c2d1 424 x1 = x1 ^ x0 ^ x2; \
d20990fd
NM
425 x3 = x3 ^ x2 ^ DRSHIFT32(3, x0); \
426 x1 = DROTL32 (1, x1); \
427 x3 = DROTL32 (7, x3); \
00a6c2d1 428 x0 = x0 ^ x1 ^ x3; \
d20990fd
NM
429 x2 = x2 ^ x3 ^ DRSHIFT32(7, x1); \
430 x0 = DROTL32 (5, x0); \
431 x2 = DROTL32 (22, x2); \
00a6c2d1
NM
432 } while (0)
433
434#define ROUND64(which, subkey, x0,x1,x2,x3, y0,y1,y2,y3) \
435 do { \
436 KEYXOR64(x0,x1,x2,x3, subkey); \
3c5e8649 437 SBOX##which(x0,x1,x2,x3, y0,y1,y2,y3); \
00a6c2d1
NM
438 LINEAR_TRANSFORMATION64(y0,y1,y2,y3); \
439 } while (0)
440
441#endif /* HAVE_NATIVE_64_BIT */
442
443void
444serpent_encrypt (const struct serpent_ctx *ctx,
3eb603d0 445 size_t length, uint8_t * dst, const uint8_t * src)
00a6c2d1
NM
446{
447 assert( !(length % SERPENT_BLOCK_SIZE));
448
449#if HAVE_NATIVE_64_BIT
450 if (length & SERPENT_BLOCK_SIZE)
451#else
452 while (length >= SERPENT_BLOCK_SIZE)
453#endif
454 {
455 uint32_t x0,x1,x2,x3, y0,y1,y2,y3;
456 unsigned k;
457
458 x0 = LE_READ_UINT32 (src);
459 x1 = LE_READ_UINT32 (src + 4);
460 x2 = LE_READ_UINT32 (src + 8);
461 x3 = LE_READ_UINT32 (src + 12);
462
463 for (k = 0; ; k += 8)
464 {
465 ROUND (0, ctx->keys[k+0], x0,x1,x2,x3, y0,y1,y2,y3);
466 ROUND (1, ctx->keys[k+1], y0,y1,y2,y3, x0,x1,x2,x3);
467 ROUND (2, ctx->keys[k+2], x0,x1,x2,x3, y0,y1,y2,y3);
468 ROUND (3, ctx->keys[k+3], y0,y1,y2,y3, x0,x1,x2,x3);
469 ROUND (4, ctx->keys[k+4], x0,x1,x2,x3, y0,y1,y2,y3);
470 ROUND (5, ctx->keys[k+5], y0,y1,y2,y3, x0,x1,x2,x3);
471 ROUND (6, ctx->keys[k+6], x0,x1,x2,x3, y0,y1,y2,y3);
472 if (k == 24)
473 break;
474 ROUND (7, ctx->keys[k+7], y0,y1,y2,y3, x0,x1,x2,x3);
475 }
476
477 /* Special final round, using two subkeys. */
478 KEYXOR (y0,y1,y2,y3, ctx->keys[31]);
3c5e8649 479 SBOX7 (y0,y1,y2,y3, x0,x1,x2,x3);
00a6c2d1
NM
480 KEYXOR (x0,x1,x2,x3, ctx->keys[32]);
481
482 LE_WRITE_UINT32 (dst, x0);
483 LE_WRITE_UINT32 (dst + 4, x1);
484 LE_WRITE_UINT32 (dst + 8, x2);
485 LE_WRITE_UINT32 (dst + 12, x3);
486
487 src += SERPENT_BLOCK_SIZE;
488 dst += SERPENT_BLOCK_SIZE;
489 length -= SERPENT_BLOCK_SIZE;
490 }
491#if HAVE_NATIVE_64_BIT
492 FOR_BLOCKS(length, dst, src, 2*SERPENT_BLOCK_SIZE)
493 {
494 uint64_t x0,x1,x2,x3, y0,y1,y2,y3;
495 unsigned k;
496
497 x0 = LE_READ_UINT32 (src);
498 x1 = LE_READ_UINT32 (src + 4);
499 x2 = LE_READ_UINT32 (src + 8);
500 x3 = LE_READ_UINT32 (src + 12);
501
502 x0 <<= 32; x0 |= LE_READ_UINT32 (src + 16);
503 x1 <<= 32; x1 |= LE_READ_UINT32 (src + 20);
504 x2 <<= 32; x2 |= LE_READ_UINT32 (src + 24);
505 x3 <<= 32; x3 |= LE_READ_UINT32 (src + 28);
506
507 for (k = 0; ; k += 8)
508 {
509 ROUND64 (0, ctx->keys[k+0], x0,x1,x2,x3, y0,y1,y2,y3);
510 ROUND64 (1, ctx->keys[k+1], y0,y1,y2,y3, x0,x1,x2,x3);
511 ROUND64 (2, ctx->keys[k+2], x0,x1,x2,x3, y0,y1,y2,y3);
512 ROUND64 (3, ctx->keys[k+3], y0,y1,y2,y3, x0,x1,x2,x3);
513 ROUND64 (4, ctx->keys[k+4], x0,x1,x2,x3, y0,y1,y2,y3);
514 ROUND64 (5, ctx->keys[k+5], y0,y1,y2,y3, x0,x1,x2,x3);
515 ROUND64 (6, ctx->keys[k+6], x0,x1,x2,x3, y0,y1,y2,y3);
516 if (k == 24)
517 break;
518 ROUND64 (7, ctx->keys[k+7], y0,y1,y2,y3, x0,x1,x2,x3);
519 }
520
521 /* Special final round, using two subkeys. */
522 KEYXOR64 (y0,y1,y2,y3, ctx->keys[31]);
3c5e8649 523 SBOX7 (y0,y1,y2,y3, x0,x1,x2,x3);
00a6c2d1
NM
524 KEYXOR64 (x0,x1,x2,x3, ctx->keys[32]);
525
526 LE_WRITE_UINT32 (dst + 16, x0);
527 LE_WRITE_UINT32 (dst + 20, x1);
528 LE_WRITE_UINT32 (dst + 24, x2);
529 LE_WRITE_UINT32 (dst + 28, x3);
530 x0 >>= 32; LE_WRITE_UINT32 (dst, x0);
531 x1 >>= 32; LE_WRITE_UINT32 (dst + 4, x1);
532 x2 >>= 32; LE_WRITE_UINT32 (dst + 8, x2);
533 x3 >>= 32; LE_WRITE_UINT32 (dst + 12, x3);
534 }
535#endif /* HAVE_NATIVE_64_BIT */
536}