2N/A/* This file was automatically imported with
2N/A import_gcry.py. Please don't modify it */
2N/A#include <grub/dl.h>
2N/AGRUB_MOD_LICENSE ("GPLv3+");
2N/A/* serpent.c - Implementation of the Serpent encryption algorithm.
2N/A * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
2N/A *
2N/A * This file is part of Libgcrypt.
2N/A *
2N/A * Libgcrypt is free software; you can redistribute it and/or modify
2N/A * it under the terms of the GNU Lesser general Public License as
2N/A * published by the Free Software Foundation; either version 2.1 of
2N/A * the License, or (at your option) any later version.
2N/A *
2N/A * Libgcrypt is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU Lesser General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU Lesser General Public
2N/A * License along with this program; if not, write to the Free Software
2N/A * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
2N/A * 02111-1307, USA.
2N/A */
2N/A
2N/A
2N/A
2N/A#include "types.h"
2N/A#include "g10lib.h"
2N/A#include "cipher.h"
2N/A#include "bithelp.h"
2N/A
2N/A/* Number of rounds per Serpent encrypt/decrypt operation. */
2N/A#define ROUNDS 32
2N/A
2N/A/* Magic number, used during generating of the subkeys. */
2N/A#define PHI 0x9E3779B9
2N/A
2N/A/* Serpent works on 128 bit blocks. */
2N/Atypedef u32 serpent_block_t[4];
2N/A
2N/A/* Serpent key, provided by the user. If the original key is shorter
2N/A than 256 bits, it is padded. */
2N/Atypedef u32 serpent_key_t[8];
2N/A
2N/A/* The key schedule consists of 33 128 bit subkeys. */
2N/Atypedef u32 serpent_subkeys_t[ROUNDS + 1][4];
2N/A
2N/A/* A Serpent context. */
2N/Atypedef struct serpent_context
2N/A{
2N/A serpent_subkeys_t keys; /* Generated subkeys. */
2N/A} serpent_context_t;
2N/A
2N/A
2N/A/* A prototype. */
2N/Astatic const char *serpent_test (void);
2N/A
2N/A
2N/A#define byte_swap_32(x) \
2N/A (0 \
2N/A | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
2N/A | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
2N/A
2N/A/* These are the S-Boxes of Serpent. They are copied from Serpents
2N/A reference implementation (the optimized one, contained in
2N/A `floppy2') and are therefore:
2N/A
2N/A Copyright (C) 1998 Ross Anderson, Eli Biham, Lars Knudsen.
2N/A
2N/A To quote the Serpent homepage
2N/A (http://www.cl.cam.ac.uk/~rja14/serpent.html):
2N/A
2N/A "Serpent is now completely in the public domain, and we impose no
2N/A restrictions on its use. This was announced on the 21st August at
2N/A the First AES Candidate Conference. The optimised implementations
2N/A in the submission package are now under the GNU PUBLIC LICENSE
2N/A (GPL), although some comments in the code still say otherwise. You
2N/A are welcome to use Serpent for any application." */
2N/A
2N/A#define SBOX0(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t05, t06, t07, t08, t09; \
2N/A u32 t11, t12, t13, t14, t15, t17, t01; \
2N/A t01 = b ^ c ; \
2N/A t02 = a | d ; \
2N/A t03 = a ^ b ; \
2N/A z = t02 ^ t01; \
2N/A t05 = c | z ; \
2N/A t06 = a ^ d ; \
2N/A t07 = b | c ; \
2N/A t08 = d & t05; \
2N/A t09 = t03 & t07; \
2N/A y = t09 ^ t08; \
2N/A t11 = t09 & y ; \
2N/A t12 = c ^ d ; \
2N/A t13 = t07 ^ t11; \
2N/A t14 = b & t06; \
2N/A t15 = t06 ^ t13; \
2N/A w = ~ t15; \
2N/A t17 = w ^ t14; \
2N/A x = t12 ^ t17; \
2N/A }
2N/A
2N/A#define SBOX0_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t08, t09, t10; \
2N/A u32 t12, t13, t14, t15, t17, t18, t01; \
2N/A t01 = c ^ d ; \
2N/A t02 = a | b ; \
2N/A t03 = b | c ; \
2N/A t04 = c & t01; \
2N/A t05 = t02 ^ t01; \
2N/A t06 = a | t04; \
2N/A y = ~ t05; \
2N/A t08 = b ^ d ; \
2N/A t09 = t03 & t08; \
2N/A t10 = d | y ; \
2N/A x = t09 ^ t06; \
2N/A t12 = a | t05; \
2N/A t13 = x ^ t12; \
2N/A t14 = t03 ^ t10; \
2N/A t15 = a ^ c ; \
2N/A z = t14 ^ t13; \
2N/A t17 = t05 & t13; \
2N/A t18 = t14 | t17; \
2N/A w = t15 ^ t18; \
2N/A }
2N/A
2N/A#define SBOX1(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t07, t08; \
2N/A u32 t10, t11, t12, t13, t16, t17, t01; \
2N/A t01 = a | d ; \
2N/A t02 = c ^ d ; \
2N/A t03 = ~ b ; \
2N/A t04 = a ^ c ; \
2N/A t05 = a | t03; \
2N/A t06 = d & t04; \
2N/A t07 = t01 & t02; \
2N/A t08 = b | t06; \
2N/A y = t02 ^ t05; \
2N/A t10 = t07 ^ t08; \
2N/A t11 = t01 ^ t10; \
2N/A t12 = y ^ t11; \
2N/A t13 = b & d ; \
2N/A z = ~ t10; \
2N/A x = t13 ^ t12; \
2N/A t16 = t10 | x ; \
2N/A t17 = t05 & t16; \
2N/A w = c ^ t17; \
2N/A }
2N/A
2N/A#define SBOX1_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t07, t08; \
2N/A u32 t09, t10, t11, t14, t15, t17, t01; \
2N/A t01 = a ^ b ; \
2N/A t02 = b | d ; \
2N/A t03 = a & c ; \
2N/A t04 = c ^ t02; \
2N/A t05 = a | t04; \
2N/A t06 = t01 & t05; \
2N/A t07 = d | t03; \
2N/A t08 = b ^ t06; \
2N/A t09 = t07 ^ t06; \
2N/A t10 = t04 | t03; \
2N/A t11 = d & t08; \
2N/A y = ~ t09; \
2N/A x = t10 ^ t11; \
2N/A t14 = a | y ; \
2N/A t15 = t06 ^ x ; \
2N/A z = t01 ^ t04; \
2N/A t17 = c ^ t15; \
2N/A w = t14 ^ t17; \
2N/A }
2N/A
2N/A#define SBOX2(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t05, t06, t07, t08; \
2N/A u32 t09, t10, t12, t13, t14, t01; \
2N/A t01 = a | c ; \
2N/A t02 = a ^ b ; \
2N/A t03 = d ^ t01; \
2N/A w = t02 ^ t03; \
2N/A t05 = c ^ w ; \
2N/A t06 = b ^ t05; \
2N/A t07 = b | t05; \
2N/A t08 = t01 & t06; \
2N/A t09 = t03 ^ t07; \
2N/A t10 = t02 | t09; \
2N/A x = t10 ^ t08; \
2N/A t12 = a | d ; \
2N/A t13 = t09 ^ x ; \
2N/A t14 = b ^ t13; \
2N/A z = ~ t09; \
2N/A y = t12 ^ t14; \
2N/A }
2N/A
2N/A#define SBOX2_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t06, t07, t08, t09; \
2N/A u32 t10, t11, t12, t15, t16, t17, t01; \
2N/A t01 = a ^ d ; \
2N/A t02 = c ^ d ; \
2N/A t03 = a & c ; \
2N/A t04 = b | t02; \
2N/A w = t01 ^ t04; \
2N/A t06 = a | c ; \
2N/A t07 = d | w ; \
2N/A t08 = ~ d ; \
2N/A t09 = b & t06; \
2N/A t10 = t08 | t03; \
2N/A t11 = b & t07; \
2N/A t12 = t06 & t02; \
2N/A z = t09 ^ t10; \
2N/A x = t12 ^ t11; \
2N/A t15 = c & z ; \
2N/A t16 = w ^ x ; \
2N/A t17 = t10 ^ t15; \
2N/A y = t16 ^ t17; \
2N/A }
2N/A
2N/A#define SBOX3(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t07, t08; \
2N/A u32 t09, t10, t11, t13, t14, t15, t01; \
2N/A t01 = a ^ c ; \
2N/A t02 = a | d ; \
2N/A t03 = a & d ; \
2N/A t04 = t01 & t02; \
2N/A t05 = b | t03; \
2N/A t06 = a & b ; \
2N/A t07 = d ^ t04; \
2N/A t08 = c | t06; \
2N/A t09 = b ^ t07; \
2N/A t10 = d & t05; \
2N/A t11 = t02 ^ t10; \
2N/A z = t08 ^ t09; \
2N/A t13 = d | z ; \
2N/A t14 = a | t07; \
2N/A t15 = b & t13; \
2N/A y = t08 ^ t11; \
2N/A w = t14 ^ t15; \
2N/A x = t05 ^ t04; \
2N/A }
2N/A
2N/A#define SBOX3_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t07, t09; \
2N/A u32 t11, t12, t13, t14, t16, t01; \
2N/A t01 = c | d ; \
2N/A t02 = a | d ; \
2N/A t03 = c ^ t02; \
2N/A t04 = b ^ t02; \
2N/A t05 = a ^ d ; \
2N/A t06 = t04 & t03; \
2N/A t07 = b & t01; \
2N/A y = t05 ^ t06; \
2N/A t09 = a ^ t03; \
2N/A w = t07 ^ t03; \
2N/A t11 = w | t05; \
2N/A t12 = t09 & t11; \
2N/A t13 = a & y ; \
2N/A t14 = t01 ^ t05; \
2N/A x = b ^ t12; \
2N/A t16 = b | t13; \
2N/A z = t14 ^ t16; \
2N/A }
2N/A
2N/A#define SBOX4(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t08, t09; \
2N/A u32 t10, t11, t12, t13, t14, t15, t16, t01; \
2N/A t01 = a | b ; \
2N/A t02 = b | c ; \
2N/A t03 = a ^ t02; \
2N/A t04 = b ^ d ; \
2N/A t05 = d | t03; \
2N/A t06 = d & t01; \
2N/A z = t03 ^ t06; \
2N/A t08 = z & t04; \
2N/A t09 = t04 & t05; \
2N/A t10 = c ^ t06; \
2N/A t11 = b & c ; \
2N/A t12 = t04 ^ t08; \
2N/A t13 = t11 | t03; \
2N/A t14 = t10 ^ t09; \
2N/A t15 = a & t05; \
2N/A t16 = t11 | t12; \
2N/A y = t13 ^ t08; \
2N/A x = t15 ^ t16; \
2N/A w = ~ t14; \
2N/A }
2N/A
2N/A#define SBOX4_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t07, t09; \
2N/A u32 t10, t11, t12, t13, t15, t01; \
2N/A t01 = b | d ; \
2N/A t02 = c | d ; \
2N/A t03 = a & t01; \
2N/A t04 = b ^ t02; \
2N/A t05 = c ^ d ; \
2N/A t06 = ~ t03; \
2N/A t07 = a & t04; \
2N/A x = t05 ^ t07; \
2N/A t09 = x | t06; \
2N/A t10 = a ^ t07; \
2N/A t11 = t01 ^ t09; \
2N/A t12 = d ^ t04; \
2N/A t13 = c | t10; \
2N/A z = t03 ^ t12; \
2N/A t15 = a ^ t04; \
2N/A y = t11 ^ t13; \
2N/A w = t15 ^ t09; \
2N/A }
2N/A
2N/A#define SBOX5(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t07, t08, t09; \
2N/A u32 t10, t11, t12, t13, t14, t01; \
2N/A t01 = b ^ d ; \
2N/A t02 = b | d ; \
2N/A t03 = a & t01; \
2N/A t04 = c ^ t02; \
2N/A t05 = t03 ^ t04; \
2N/A w = ~ t05; \
2N/A t07 = a ^ t01; \
2N/A t08 = d | w ; \
2N/A t09 = b | t05; \
2N/A t10 = d ^ t08; \
2N/A t11 = b | t07; \
2N/A t12 = t03 | w ; \
2N/A t13 = t07 | t10; \
2N/A t14 = t01 ^ t11; \
2N/A y = t09 ^ t13; \
2N/A x = t07 ^ t08; \
2N/A z = t12 ^ t14; \
2N/A }
2N/A
2N/A#define SBOX5_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t07, t08, t09; \
2N/A u32 t10, t12, t13, t15, t16, t01; \
2N/A t01 = a & d ; \
2N/A t02 = c ^ t01; \
2N/A t03 = a ^ d ; \
2N/A t04 = b & t02; \
2N/A t05 = a & c ; \
2N/A w = t03 ^ t04; \
2N/A t07 = a & w ; \
2N/A t08 = t01 ^ w ; \
2N/A t09 = b | t05; \
2N/A t10 = ~ b ; \
2N/A x = t08 ^ t09; \
2N/A t12 = t10 | t07; \
2N/A t13 = w | x ; \
2N/A z = t02 ^ t12; \
2N/A t15 = t02 ^ t13; \
2N/A t16 = b ^ d ; \
2N/A y = t16 ^ t15; \
2N/A }
2N/A
2N/A#define SBOX6(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t07, t08, t09, t10; \
2N/A u32 t11, t12, t13, t15, t17, t18, t01; \
2N/A t01 = a & d ; \
2N/A t02 = b ^ c ; \
2N/A t03 = a ^ d ; \
2N/A t04 = t01 ^ t02; \
2N/A t05 = b | c ; \
2N/A x = ~ t04; \
2N/A t07 = t03 & t05; \
2N/A t08 = b & x ; \
2N/A t09 = a | c ; \
2N/A t10 = t07 ^ t08; \
2N/A t11 = b | d ; \
2N/A t12 = c ^ t11; \
2N/A t13 = t09 ^ t10; \
2N/A y = ~ t13; \
2N/A t15 = x & t03; \
2N/A z = t12 ^ t07; \
2N/A t17 = a ^ b ; \
2N/A t18 = y ^ t15; \
2N/A w = t17 ^ t18; \
2N/A }
2N/A
2N/A#define SBOX6_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t07, t08, t09; \
2N/A u32 t12, t13, t14, t15, t16, t17, t01; \
2N/A t01 = a ^ c ; \
2N/A t02 = ~ c ; \
2N/A t03 = b & t01; \
2N/A t04 = b | t02; \
2N/A t05 = d | t03; \
2N/A t06 = b ^ d ; \
2N/A t07 = a & t04; \
2N/A t08 = a | t02; \
2N/A t09 = t07 ^ t05; \
2N/A x = t06 ^ t08; \
2N/A w = ~ t09; \
2N/A t12 = b & w ; \
2N/A t13 = t01 & t05; \
2N/A t14 = t01 ^ t12; \
2N/A t15 = t07 ^ t13; \
2N/A t16 = d | t02; \
2N/A t17 = a ^ x ; \
2N/A z = t17 ^ t15; \
2N/A y = t16 ^ t14; \
2N/A }
2N/A
2N/A#define SBOX7(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t05, t06, t08, t09, t10; \
2N/A u32 t11, t13, t14, t15, t16, t17, t01; \
2N/A t01 = a & c ; \
2N/A t02 = ~ d ; \
2N/A t03 = a & t02; \
2N/A t04 = b | t01; \
2N/A t05 = a & b ; \
2N/A t06 = c ^ t04; \
2N/A z = t03 ^ t06; \
2N/A t08 = c | z ; \
2N/A t09 = d | t05; \
2N/A t10 = a ^ t08; \
2N/A t11 = t04 & z ; \
2N/A x = t09 ^ t10; \
2N/A t13 = b ^ x ; \
2N/A t14 = t01 ^ x ; \
2N/A t15 = c ^ t05; \
2N/A t16 = t11 | t13; \
2N/A t17 = t02 | t14; \
2N/A w = t15 ^ t17; \
2N/A y = a ^ t16; \
2N/A }
2N/A
2N/A#define SBOX7_INVERSE(a, b, c, d, w, x, y, z) \
2N/A { \
2N/A u32 t02, t03, t04, t06, t07, t08, t09; \
2N/A u32 t10, t11, t13, t14, t15, t16, t01; \
2N/A t01 = a & b ; \
2N/A t02 = a | b ; \
2N/A t03 = c | t01; \
2N/A t04 = d & t02; \
2N/A z = t03 ^ t04; \
2N/A t06 = b ^ t04; \
2N/A t07 = d ^ z ; \
2N/A t08 = ~ t07; \
2N/A t09 = t06 | t08; \
2N/A t10 = b ^ d ; \
2N/A t11 = a | d ; \
2N/A x = a ^ t09; \
2N/A t13 = c ^ t06; \
2N/A t14 = c & t11; \
2N/A t15 = d | x ; \
2N/A t16 = t01 | t10; \
2N/A w = t13 ^ t15; \
2N/A y = t14 ^ t16; \
2N/A }
2N/A
2N/A/* XOR BLOCK1 into BLOCK0. */
2N/A#define BLOCK_XOR(block0, block1) \
2N/A { \
2N/A block0[0] ^= block1[0]; \
2N/A block0[1] ^= block1[1]; \
2N/A block0[2] ^= block1[2]; \
2N/A block0[3] ^= block1[3]; \
2N/A }
2N/A
2N/A/* Copy BLOCK_SRC to BLOCK_DST. */
2N/A#define BLOCK_COPY(block_dst, block_src) \
2N/A { \
2N/A block_dst[0] = block_src[0]; \
2N/A block_dst[1] = block_src[1]; \
2N/A block_dst[2] = block_src[2]; \
2N/A block_dst[3] = block_src[3]; \
2N/A }
2N/A
2N/A/* Apply SBOX number WHICH to to the block found in ARRAY0 at index
2N/A INDEX, writing the output to the block found in ARRAY1 at index
2N/A INDEX. */
2N/A#define SBOX(which, array0, array1, index) \
2N/A SBOX##which (array0[index + 0], array0[index + 1], \
2N/A array0[index + 2], array0[index + 3], \
2N/A array1[index + 0], array1[index + 1], \
2N/A array1[index + 2], array1[index + 3]);
2N/A
2N/A/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at
2N/A index INDEX, writing the output to the block found in ARRAY1 at
2N/A index INDEX. */
2N/A#define SBOX_INVERSE(which, array0, array1, index) \
2N/A SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \
2N/A array0[index + 2], array0[index + 3], \
2N/A array1[index + 0], array1[index + 1], \
2N/A array1[index + 2], array1[index + 3]);
2N/A
2N/A/* Apply the linear transformation to BLOCK. */
2N/A#define LINEAR_TRANSFORMATION(block) \
2N/A { \
2N/A block[0] = rol (block[0], 13); \
2N/A block[2] = rol (block[2], 3); \
2N/A block[1] = block[1] ^ block[0] ^ block[2]; \
2N/A block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
2N/A block[1] = rol (block[1], 1); \
2N/A block[3] = rol (block[3], 7); \
2N/A block[0] = block[0] ^ block[1] ^ block[3]; \
2N/A block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
2N/A block[0] = rol (block[0], 5); \
2N/A block[2] = rol (block[2], 22); \
2N/A }
2N/A
2N/A/* Apply the inverse linear transformation to BLOCK. */
2N/A#define LINEAR_TRANSFORMATION_INVERSE(block) \
2N/A { \
2N/A block[2] = ror (block[2], 22); \
2N/A block[0] = ror (block[0] , 5); \
2N/A block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
2N/A block[0] = block[0] ^ block[1] ^ block[3]; \
2N/A block[3] = ror (block[3], 7); \
2N/A block[1] = ror (block[1], 1); \
2N/A block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
2N/A block[1] = block[1] ^ block[0] ^ block[2]; \
2N/A block[2] = ror (block[2], 3); \
2N/A block[0] = ror (block[0], 13); \
2N/A }
2N/A
2N/A/* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the
2N/A subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage.
2N/A This macro increments `round'. */
2N/A#define ROUND(which, subkeys, block, block_tmp) \
2N/A { \
2N/A BLOCK_XOR (block, subkeys[round]); \
2N/A round++; \
2N/A SBOX (which, block, block_tmp, 0); \
2N/A LINEAR_TRANSFORMATION (block_tmp); \
2N/A BLOCK_COPY (block, block_tmp); \
2N/A }
2N/A
2N/A/* Apply the last Serpent round to BLOCK, using the SBOX number WHICH
2N/A and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
2N/A storage. The result will be stored in BLOCK_TMP. This macro
2N/A increments `round'. */
2N/A#define ROUND_LAST(which, subkeys, block, block_tmp) \
2N/A { \
2N/A BLOCK_XOR (block, subkeys[round]); \
2N/A round++; \
2N/A SBOX (which, block, block_tmp, 0); \
2N/A BLOCK_XOR (block_tmp, subkeys[round]); \
2N/A round++; \
2N/A }
2N/A
2N/A/* Apply an inverse Serpent round to BLOCK, using the SBOX number
2N/A WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as
2N/A temporary storage. This macro increments `round'. */
2N/A#define ROUND_INVERSE(which, subkey, block, block_tmp) \
2N/A { \
2N/A LINEAR_TRANSFORMATION_INVERSE (block); \
2N/A SBOX_INVERSE (which, block, block_tmp, 0); \
2N/A BLOCK_XOR (block_tmp, subkey[round]); \
2N/A round--; \
2N/A BLOCK_COPY (block, block_tmp); \
2N/A }
2N/A
2N/A/* Apply the first Serpent round to BLOCK, using the SBOX number WHICH
2N/A and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary
2N/A storage. The result will be stored in BLOCK_TMP. This macro
2N/A increments `round'. */
2N/A#define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
2N/A { \
2N/A BLOCK_XOR (block, subkeys[round]); \
2N/A round--; \
2N/A SBOX_INVERSE (which, block, block_tmp, 0); \
2N/A BLOCK_XOR (block_tmp, subkeys[round]); \
2N/A round--; \
2N/A }
2N/A
2N/A/* Convert the user provided key KEY of KEY_LENGTH bytes into the
2N/A internally used format. */
2N/Astatic void
2N/Aserpent_key_prepare (const byte *key, unsigned int key_length,
2N/A serpent_key_t key_prepared)
2N/A{
2N/A int i;
2N/A
2N/A /* Copy key. */
2N/A memcpy (key_prepared, key, key_length);
2N/A#ifdef WORDS_BIGENDIAN
2N/A for (i = 0; i < key_length / 4; i++)
2N/A key_prepared[i] = byte_swap_32 (key_prepared[i]);
2N/A#endif
2N/A
2N/A if (key_length < 32)
2N/A {
2N/A /* Key must be padded according to the Serpent
2N/A specification. */
2N/A key_prepared[key_length / 4] = 0x00000001;
2N/A
2N/A for (i = key_length / 4 + 1; i < 8; i++)
2N/A key_prepared[i] = 0;
2N/A }
2N/A}
2N/A
2N/A/* Derive the 33 subkeys from KEY and store them in SUBKEYS. */
2N/Astatic void
2N/Aserpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys)
2N/A{
2N/A u32 w_real[140]; /* The `prekey'. */
2N/A u32 k[132];
2N/A u32 *w = &w_real[8];
2N/A int i, j;
2N/A
2N/A /* Initialize with key values. */
2N/A for (i = 0; i < 8; i++)
2N/A w[i - 8] = key[i];
2N/A
2N/A /* Expand to intermediate key using the affine recurrence. */
2N/A for (i = 0; i < 132; i++)
2N/A w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
2N/A
2N/A /* Calculate subkeys via S-Boxes, in bitslice mode. */
2N/A SBOX (3, w, k, 0);
2N/A SBOX (2, w, k, 4);
2N/A SBOX (1, w, k, 8);
2N/A SBOX (0, w, k, 12);
2N/A SBOX (7, w, k, 16);
2N/A SBOX (6, w, k, 20);
2N/A SBOX (5, w, k, 24);
2N/A SBOX (4, w, k, 28);
2N/A SBOX (3, w, k, 32);
2N/A SBOX (2, w, k, 36);
2N/A SBOX (1, w, k, 40);
2N/A SBOX (0, w, k, 44);
2N/A SBOX (7, w, k, 48);
2N/A SBOX (6, w, k, 52);
2N/A SBOX (5, w, k, 56);
2N/A SBOX (4, w, k, 60);
2N/A SBOX (3, w, k, 64);
2N/A SBOX (2, w, k, 68);
2N/A SBOX (1, w, k, 72);
2N/A SBOX (0, w, k, 76);
2N/A SBOX (7, w, k, 80);
2N/A SBOX (6, w, k, 84);
2N/A SBOX (5, w, k, 88);
2N/A SBOX (4, w, k, 92);
2N/A SBOX (3, w, k, 96);
2N/A SBOX (2, w, k, 100);
2N/A SBOX (1, w, k, 104);
2N/A SBOX (0, w, k, 108);
2N/A SBOX (7, w, k, 112);
2N/A SBOX (6, w, k, 116);
2N/A SBOX (5, w, k, 120);
2N/A SBOX (4, w, k, 124);
2N/A SBOX (3, w, k, 128);
2N/A
2N/A /* Renumber subkeys. */
2N/A for (i = 0; i < ROUNDS + 1; i++)
2N/A for (j = 0; j < 4; j++)
2N/A subkeys[i][j] = k[4 * i + j];
2N/A}
2N/A
2N/A/* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */
2N/Astatic void
2N/Aserpent_setkey_internal (serpent_context_t *context,
2N/A const byte *key, unsigned int key_length)
2N/A{
2N/A serpent_key_t key_prepared;
2N/A
2N/A serpent_key_prepare (key, key_length, key_prepared);
2N/A serpent_subkeys_generate (key_prepared, context->keys);
2N/A _gcry_burn_stack (272 * sizeof (u32));
2N/A}
2N/A
2N/A/* Initialize CTX with the key KEY of KEY_LENGTH bytes. */
2N/Astatic gcry_err_code_t
2N/Aserpent_setkey (void *ctx,
2N/A const byte *key, unsigned int key_length)
2N/A{
2N/A serpent_context_t *context = ctx;
2N/A static const char *serpent_test_ret;
2N/A static int serpent_init_done;
2N/A gcry_err_code_t ret = GPG_ERR_NO_ERROR;
2N/A
2N/A if (! serpent_init_done)
2N/A {
2N/A /* Execute a self-test the first time, Serpent is used. */
2N/A serpent_test_ret = serpent_test ();
2N/A if (serpent_test_ret)
2N/A log_error ("Serpent test failure: %s\n", serpent_test_ret);
2N/A serpent_init_done = 1;
2N/A }
2N/A
2N/A if (serpent_test_ret)
2N/A ret = GPG_ERR_SELFTEST_FAILED;
2N/A else
2N/A {
2N/A serpent_setkey_internal (context, key, key_length);
2N/A _gcry_burn_stack (sizeof (serpent_key_t));
2N/A }
2N/A
2N/A return ret;
2N/A}
2N/A
2N/Astatic void
2N/Aserpent_encrypt_internal (serpent_context_t *context,
2N/A const byte *input, byte *output)
2N/A{
2N/A serpent_block_t b, b_next;
2N/A int round = 0;
2N/A
2N/A memcpy (b, input, sizeof (b));
2N/A#ifdef WORDS_BIGENDIAN
2N/A b[0] = byte_swap_32 (b[0]);
2N/A b[1] = byte_swap_32 (b[1]);
2N/A b[2] = byte_swap_32 (b[2]);
2N/A b[3] = byte_swap_32 (b[3]);
2N/A#endif
2N/A
2N/A ROUND (0, context->keys, b, b_next);
2N/A ROUND (1, context->keys, b, b_next);
2N/A ROUND (2, context->keys, b, b_next);
2N/A ROUND (3, context->keys, b, b_next);
2N/A ROUND (4, context->keys, b, b_next);
2N/A ROUND (5, context->keys, b, b_next);
2N/A ROUND (6, context->keys, b, b_next);
2N/A ROUND (7, context->keys, b, b_next);
2N/A ROUND (0, context->keys, b, b_next);
2N/A ROUND (1, context->keys, b, b_next);
2N/A ROUND (2, context->keys, b, b_next);
2N/A ROUND (3, context->keys, b, b_next);
2N/A ROUND (4, context->keys, b, b_next);
2N/A ROUND (5, context->keys, b, b_next);
2N/A ROUND (6, context->keys, b, b_next);
2N/A ROUND (7, context->keys, b, b_next);
2N/A ROUND (0, context->keys, b, b_next);
2N/A ROUND (1, context->keys, b, b_next);
2N/A ROUND (2, context->keys, b, b_next);
2N/A ROUND (3, context->keys, b, b_next);
2N/A ROUND (4, context->keys, b, b_next);
2N/A ROUND (5, context->keys, b, b_next);
2N/A ROUND (6, context->keys, b, b_next);
2N/A ROUND (7, context->keys, b, b_next);
2N/A ROUND (0, context->keys, b, b_next);
2N/A ROUND (1, context->keys, b, b_next);
2N/A ROUND (2, context->keys, b, b_next);
2N/A ROUND (3, context->keys, b, b_next);
2N/A ROUND (4, context->keys, b, b_next);
2N/A ROUND (5, context->keys, b, b_next);
2N/A ROUND (6, context->keys, b, b_next);
2N/A
2N/A ROUND_LAST (7, context->keys, b, b_next);
2N/A
2N/A#ifdef WORDS_BIGENDIAN
2N/A b_next[0] = byte_swap_32 (b_next[0]);
2N/A b_next[1] = byte_swap_32 (b_next[1]);
2N/A b_next[2] = byte_swap_32 (b_next[2]);
2N/A b_next[3] = byte_swap_32 (b_next[3]);
2N/A#endif
2N/A memcpy (output, b_next, sizeof (b_next));
2N/A}
2N/A
2N/Astatic void
2N/Aserpent_decrypt_internal (serpent_context_t *context,
2N/A const byte *input, byte *output)
2N/A{
2N/A serpent_block_t b, b_next;
2N/A int round = ROUNDS;
2N/A
2N/A memcpy (b, input, sizeof (b));
2N/A#ifdef WORDS_BIGENDIAN
2N/A b[0] = byte_swap_32 (b[0]);
2N/A b[1] = byte_swap_32 (b[1]);
2N/A b[2] = byte_swap_32 (b[2]);
2N/A b[3] = byte_swap_32 (b[3]);
2N/A#endif
2N/A
2N/A ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
2N/A
2N/A ROUND_INVERSE (6, context->keys, b, b_next);
2N/A ROUND_INVERSE (5, context->keys, b, b_next);
2N/A ROUND_INVERSE (4, context->keys, b, b_next);
2N/A ROUND_INVERSE (3, context->keys, b, b_next);
2N/A ROUND_INVERSE (2, context->keys, b, b_next);
2N/A ROUND_INVERSE (1, context->keys, b, b_next);
2N/A ROUND_INVERSE (0, context->keys, b, b_next);
2N/A ROUND_INVERSE (7, context->keys, b, b_next);
2N/A ROUND_INVERSE (6, context->keys, b, b_next);
2N/A ROUND_INVERSE (5, context->keys, b, b_next);
2N/A ROUND_INVERSE (4, context->keys, b, b_next);
2N/A ROUND_INVERSE (3, context->keys, b, b_next);
2N/A ROUND_INVERSE (2, context->keys, b, b_next);
2N/A ROUND_INVERSE (1, context->keys, b, b_next);
2N/A ROUND_INVERSE (0, context->keys, b, b_next);
2N/A ROUND_INVERSE (7, context->keys, b, b_next);
2N/A ROUND_INVERSE (6, context->keys, b, b_next);
2N/A ROUND_INVERSE (5, context->keys, b, b_next);
2N/A ROUND_INVERSE (4, context->keys, b, b_next);
2N/A ROUND_INVERSE (3, context->keys, b, b_next);
2N/A ROUND_INVERSE (2, context->keys, b, b_next);
2N/A ROUND_INVERSE (1, context->keys, b, b_next);
2N/A ROUND_INVERSE (0, context->keys, b, b_next);
2N/A ROUND_INVERSE (7, context->keys, b, b_next);
2N/A ROUND_INVERSE (6, context->keys, b, b_next);
2N/A ROUND_INVERSE (5, context->keys, b, b_next);
2N/A ROUND_INVERSE (4, context->keys, b, b_next);
2N/A ROUND_INVERSE (3, context->keys, b, b_next);
2N/A ROUND_INVERSE (2, context->keys, b, b_next);
2N/A ROUND_INVERSE (1, context->keys, b, b_next);
2N/A ROUND_INVERSE (0, context->keys, b, b_next);
2N/A
2N/A#ifdef WORDS_BIGENDIAN
2N/A b_next[0] = byte_swap_32 (b_next[0]);
2N/A b_next[1] = byte_swap_32 (b_next[1]);
2N/A b_next[2] = byte_swap_32 (b_next[2]);
2N/A b_next[3] = byte_swap_32 (b_next[3]);
2N/A#endif
2N/A memcpy (output, b_next, sizeof (b_next));
2N/A}
2N/A
2N/Astatic void
2N/Aserpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
2N/A{
2N/A serpent_context_t *context = ctx;
2N/A
2N/A serpent_encrypt_internal (context, buffer_in, buffer_out);
2N/A _gcry_burn_stack (2 * sizeof (serpent_block_t));
2N/A}
2N/A
2N/Astatic void
2N/Aserpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
2N/A{
2N/A serpent_context_t *context = ctx;
2N/A
2N/A serpent_decrypt_internal (context, buffer_in, buffer_out);
2N/A _gcry_burn_stack (2 * sizeof (serpent_block_t));
2N/A}
2N/A
2N/A
2N/A
2N/A/* Serpent test. */
2N/A
2N/Astatic const char *serpent_test (void) { return 0; }
2N/A
2N/A
2N/A
2N/A/* "SERPENT" is an alias for "SERPENT128". */
2N/Astatic const char *cipher_spec_serpent128_aliases[] =
2N/A {
2N/A "SERPENT",
2N/A NULL
2N/A };
2N/A
2N/Agcry_cipher_spec_t _gcry_cipher_spec_serpent128 =
2N/A {
2N/A "SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128,
2N/A sizeof (serpent_context_t),
2N/A serpent_setkey, serpent_encrypt, serpent_decrypt
2N/A ,
2N/A#ifdef GRUB_UTIL
2N/A .modname = "gcry_serpent",
2N/A#endif
2N/A };
2N/A
2N/Agcry_cipher_spec_t _gcry_cipher_spec_serpent192 =
2N/A {
2N/A "SERPENT192", NULL, NULL, 16, 192,
2N/A sizeof (serpent_context_t),
2N/A serpent_setkey, serpent_encrypt, serpent_decrypt
2N/A ,
2N/A#ifdef GRUB_UTIL
2N/A .modname = "gcry_serpent",
2N/A#endif
2N/A };
2N/A
2N/Agcry_cipher_spec_t _gcry_cipher_spec_serpent256 =
2N/A {
2N/A "SERPENT256", NULL, NULL, 16, 256,
2N/A sizeof (serpent_context_t),
2N/A serpent_setkey, serpent_encrypt, serpent_decrypt
2N/A ,
2N/A#ifdef GRUB_UTIL
2N/A .modname = "gcry_serpent",
2N/A#endif
2N/A };
2N/A
2N/A
2N/AGRUB_MOD_INIT(gcry_serpent)
2N/A{
2N/A grub_cipher_register (&_gcry_cipher_spec_serpent128);
2N/A grub_cipher_register (&_gcry_cipher_spec_serpent192);
2N/A grub_cipher_register (&_gcry_cipher_spec_serpent256);
2N/A}
2N/A
2N/AGRUB_MOD_FINI(gcry_serpent)
2N/A{
2N/A grub_cipher_unregister (&_gcry_cipher_spec_serpent128);
2N/A grub_cipher_unregister (&_gcry_cipher_spec_serpent192);
2N/A grub_cipher_unregister (&_gcry_cipher_spec_serpent256);
2N/A}