diff options
-rw-r--r-- | src/crypto/des.c | 695 | ||||
-rw-r--r-- | src/include/ipxe/des.h | 91 | ||||
-rw-r--r-- | src/include/ipxe/errfile.h | 1 | ||||
-rw-r--r-- | src/tests/des_test.c | 898 |
4 files changed, 1685 insertions, 0 deletions
diff --git a/src/crypto/des.c b/src/crypto/des.c new file mode 100644 index 000000000..6918bec3e --- /dev/null +++ b/src/crypto/des.c @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * DES algorithm + * + * DES was not designed to be implemented in software, and therefore + * contains a large number of bit permutation operations that are + * essentially free in hardware (requiring only wires, no gates) but + * expensive in software. + * + * Since DES is no longer used as a practical block cipher for large + * volumes of data, we optimise for code size, and do not attempt to + * obtain fast throughput. + * + * The algorithm is specified in NIST SP 800-67, downloadable from + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-67r2.pdf + */ + +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <byteswap.h> +#include <ipxe/rotate.h> +#include <ipxe/crypto.h> +#include <ipxe/ecb.h> +#include <ipxe/cbc.h> +#include <ipxe/init.h> +#include <ipxe/des.h> + +/** + * DES shift schedule + * + * The DES shift schedule (ordered from round 16 down to round 1) is + * {1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,1}. In binary, this may be + * represented as {1,10,10,10,10,10,10,1,10,10,10,10,10,10,1,1} and + * concatenated (without padding) to produce a single binary integer + * 1101010101010110101010101011 (equal to 0x0d556aab in hexadecimal). + * + * This integer may then be consumed LSB-first, where a 1 bit + * indicates a shift and the generation of a round key, and a 0 bit + * indicates a shift without the generation of a round key. + */ +#define DES_SCHEDULE 0x0d556aab + +/** + * Define an element pair in a DES S-box + * + * @v x Upper element of element pair + * @v y Lower element of element pair + * + * DES S-box elements are 4-bit values. We encode two values per + * byte, ordering the elements so that the six-bit input value may be + * used directly as a lookup index. + * + * Specifically, if the input value is {r1,c3,c2,c1,c0,r0}, where + * {r1,r0} is the table row index and {c3,c2,c1,c0} is the table + * column index (as used in the DES specification), then: + * + * - {r1,c3,c2,c1,c0} is the byte index into the table + * + * - (4*r0) is the required bit shift to extract the 4-bit value + */ +#define SBYTE( x, y ) ( ( (y) << 4 ) | (x) ) + +/** + * Define a row pair in a DES S-box + * + * @v x0..xf Upper row of row pair + * @v y0..yf Lower row of row pair + */ +#define SBOX( x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf, \ + y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, ya, yb, yc, yd, ye, yf ) \ + SBYTE ( x0, y0 ), SBYTE ( x1, y1 ), SBYTE ( x2, y2 ), SBYTE ( x3, y3 ),\ + SBYTE ( x4, y4 ), SBYTE ( x5, y5 ), SBYTE ( x6, y6 ), SBYTE ( x7, y7 ),\ + SBYTE ( x8, y8 ), SBYTE ( x9, y9 ), SBYTE ( xa, ya ), SBYTE ( xb, yb ),\ + SBYTE ( xc, yc ), SBYTE ( xd, yd ), SBYTE ( xe, ye ), SBYTE ( xf, yf ) + +/** DES S-boxes S1..S8 */ +static const uint8_t des_s[8][32] = { { + /* S1 */ + SBOX ( 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 ), + SBOX ( 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 ) +}, { + /* S2 */ + SBOX ( 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 ), + SBOX ( 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 ) +}, { + /* S3 */ + SBOX ( 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 ), + SBOX ( 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 ) +}, { + /* S4 */ + SBOX ( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 ), + SBOX ( 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 ) +}, { + /* S5 */ + SBOX ( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 ), + SBOX ( 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 ) +}, { + /* S6 */ + SBOX ( 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 ), + SBOX ( 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 ) +}, { + /* S7 */ + SBOX ( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 ), + SBOX ( 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 ) +}, { + /* S8 */ + SBOX ( 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 ), + SBOX ( 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 ) +} }; + +/** + * Define a bit index within permuted choice 2 (PC2) + * + * @v bit Bit index + * + * Permuted choice 2 (PC2) is used to select bits from a concatenated + * pair of 28-bit registers ("C" and "D") as part of the key schedule. + * We store these as 32-bit registers and so must add 4 to indexes + * above 28. + */ +#define DES_PC2( x ) ( (x) + ( ( (x) > 28 ) ? 4 : 0 ) ) + +/** + * Define six bits of permuted choice 2 (PC2) + * + * @v r1:r0 Bits corresponding to S-box row index + * @v c3:c0 Bits corresponding to S-box column index + * + * There are 8 steps within a DES round (one step per S-box). Each + * step requires six bits of the round key, corresponding to the S-box + * input value {r1,c3,c2,c1,c0,r0}, where {r1,r0} is the table row + * index and {c3,c2,c1,c0} is the table column index. + * + * As an optimisation, we store the least significant of the 6 bits in + * the sign bit of a signed 8-bit value, and the remaining 5 bits in + * the least significant 5 bits of the 8-bit value. See the comments + * in des_sbox() for further details. + */ +#define DES_PC2R( r1, c3, c2, c1, c0, r0 ) \ + DES_PC2 ( r0 ), /* LSB stored in sign bit */ \ + DES_PC2 ( r0 ), /* Unused bit */ \ + DES_PC2 ( r0 ), /* Unused bit */ \ + DES_PC2 ( r1 ), /* Remaining 5 bits */ \ + DES_PC2 ( c3 ), /* ... */ \ + DES_PC2 ( c2 ), /* ... */ \ + DES_PC2 ( c1 ), /* ... */ \ + DES_PC2 ( c0 ) /* ... */ + +/** + * A DES systematic permutation generator + * + * Many of the permutations used in DES comprise systematic bit + * patterns. We generate these permutations at runtime to save on + * code size. + */ +struct des_generator { + /** Permutation */ + uint8_t *permutation; + /** Seed value */ + uint32_t seed; +}; + +/** + * Define a DES permutation generator + * + * @v PERMUTATION Permutation + * @v OFFSET Fixed input bit offset (0 or 1) + * @v INV<n> Input bit index bit <n> should be inverted + * @v BIT<n> Source bit for input bit index bit <n> + * @ret generator Permutation generator + */ +#define DES_GENERATOR( PERMUTATION, OFFSET, INV5, BIT5, INV4, BIT4, \ + INV3, BIT3, INV2, BIT2, INV1, BIT1, INV0, BIT0 ) \ + { \ + .permutation = (PERMUTATION), \ + .seed = ( ( (INV0) << 31 ) | ( (BIT0) << 28 ) | \ + ( (INV1) << 27 ) | ( (BIT1) << 24 ) | \ + ( (INV2) << 23 ) | ( (BIT2) << 20 ) | \ + ( (INV3) << 19 ) | ( (BIT3) << 16 ) | \ + ( (INV4) << 15 ) | ( (BIT4) << 12 ) | \ + ( (INV5) << 11 ) | ( (BIT5) << 8 ) | \ + ( ( uint32_t ) sizeof (PERMUTATION) - 1 ) | \ + (OFFSET) ), \ + } + +/** DES permuted choice 1 (PC1) "C" register */ +static uint8_t des_pc1c[29]; + +/** DES permuted choice 1 (PC1) "D" register */ +static uint8_t des_pc1d[33]; + +/** DES permuted choice 2 (PC2) */ +static const uint8_t des_pc2[65] = { + DES_PC2R ( 14, 17, 11, 24, 1, 5 ), + DES_PC2R ( 3, 28, 15, 6, 21, 10 ), + DES_PC2R ( 23, 19, 12, 4, 26, 8 ), + DES_PC2R ( 16, 7, 27, 20, 13, 2 ), + DES_PC2R ( 41, 52, 31, 37, 47, 55 ), + DES_PC2R ( 30, 40, 51, 45, 33, 48 ), + DES_PC2R ( 44, 49, 39, 56, 34, 53 ), + DES_PC2R ( 46, 42, 50, 36, 29, 32 ), + 0 /* terminator */ +}; + +/** DES initial permutation (IP) */ +static uint8_t des_ip[65]; + +/** DES data permutation (P) */ +static const uint8_t des_p[33] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, + 0 /* terminator */ +}; + +/** DES final / inverse initial permutation (FP / IP^-1) */ +static uint8_t des_fp[65]; + +/** DES permutation generators */ +static struct des_generator des_generators[] = { + + /* The DES initial permutation transforms the bit index + * {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,x4,x3,~x5}+1 + */ + DES_GENERATOR ( des_ip, 1, 1, 2, 1, 1, 1, 0, 0, 4, 0, 3, 1, 5 ), + + /* The DES final permutation transforms the bit index + * {x5,x4,x3,x2,x1,x0}+1 into {~x0,x2,x1,~x5,~x4,~x3}+1 + * + * There is an asymmetry in the DES block diagram for the last + * of the 16 rounds, which is functionally equivalent to + * performing 16 identical rounds and then swapping the left + * and right halves before applying the final permutation. We + * may therefore account for this asymmetry by inverting the + * MSB in each bit index, to point to the corresponding bit in + * the other half. + * + * This is equivalent to using a permutation that transforms + * {x5,x4,x3,x2,x1,x0}+1 into {x0,x2,x1,~x5,~x4,~x3}+1 + */ + DES_GENERATOR ( des_fp, 1, 0, 0, 0, 2, 0, 1, 1, 5, 1, 4, 1, 3 ), + + /* The "C" half of DES permuted choice 1 (PC1) transforms the + * bit index {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,x5,x4,x3}+1 + */ + DES_GENERATOR ( des_pc1c, 1, 1, 2, 1, 1, 1, 0, 0, 5, 0, 4, 0, 3 ), + + /* The "D" half of DES permuted choice 1 (PC1) transforms the + * bit index {x5,x4,x3,x2,x1,x0}+1 into {~x2,~x1,~x0,~x5,~x4,~x3}+0 + * + * Due to the idosyncratic design choice of using 28-bit + * registers in the DES key expansion schedule, the final four + * permutation values appear at indices [28:31] instead of + * [24:27]. This is adjusted for in @c des_setkey(). + */ + DES_GENERATOR ( des_pc1d, 0, 1, 2, 1, 1, 1, 0, 1, 5, 1, 4, 1, 3 ), +}; + +/** + * Generate DES permutation + * + * @v generator Generator + */ +static __attribute__ (( noinline )) void +des_generate ( struct des_generator *generator ) { + uint8_t *permutation = generator->permutation; + uint32_t seed = generator->seed; + unsigned int index = 0; + uint8_t accum; + uint8_t bit; + + /* Generate permutations + * + * This loop is optimised for code size on a + * register-constrained architecture such as i386. + */ + do { + /* Rotate seed to access MSB's bit descriptor */ + seed = ror32 ( seed, 8 ); + + /* Initialise accumulator with six flag bits */ + accum = 0xfc; + + /* Accumulate bits until all six flag bits are cleared */ + do { + /* Extract specified bit from index. Use a + * rotation instead of a shift, since this + * will allow the mask to be elided. + */ + bit = ror8 ( index, ( seed & 0x07 ) ); + seed = ror32 ( seed, 3 ); + + /* Toggle bit if applicable */ + bit ^= seed; + seed = ror32 ( seed, 1 ); + + /* Add bit to accumulator and clear one flag bit */ + accum <<= 1; + accum |= ( bit & 0x01 ); + + } while ( accum & 0x80 ); + + /* Add constant offset if applicable */ + accum += ( seed & 0x01 ); + + /* Store permutation */ + permutation[index] = accum; + + /* Loop until reaching length (which is always even) */ + } while ( ++index < ( seed & 0xfe ) ); + DBGC2 ( permutation, "DES generated permutation %p:\n", permutation ); + DBGC2_HDA ( permutation, 0, permutation, + ( ( seed & 0xfe ) + 1 /* zero terminator */ ) ); +} + +/** + * Initialise permutations + */ +static void des_init ( void ) { + unsigned int i; + + /* Generate all generated permutations */ + for ( i = 0 ; i < ( sizeof ( des_generators ) / + sizeof ( des_generators[0] ) ) ; i++ ) { + des_generate ( &des_generators[i] ); + } +} + +/** Initialisation function */ +struct init_fn des_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = des_init, +}; + +/** + * Perform bit permutation + * + * @v permutation Bit permutation (zero-terminated) + * @v in Input value + * @v out Output value + */ +static void des_permute ( const uint8_t *permutation, const uint8_t *in, + uint8_t *out ) { + uint8_t mask = 0x80; + uint8_t accum = 0; + unsigned int bit; + + /* Extract individual input bits to construct output value */ + while ( ( bit = *(permutation++) ) ) { + bit--; + if ( in[ bit / 8 ] & ( 0x80 >> ( bit % 8 ) ) ) + accum |= mask; + *out = accum; + mask = ror8 ( mask, 1 ); + if ( mask == 0x80 ) { + out++; + accum = 0; + } + } +} + +/** + * Perform DES S-box substitution + * + * @v in 32-bit input value (native endian) + * @v rkey 48-bit round key + * @ret out 32-bit output value (native endian) + */ +static uint32_t des_sbox ( uint32_t in, const union des_round_key *rkey ) { + uint32_t out = 0; + uint32_t lookup; + int32_t key; + uint8_t sub; + unsigned int i; + + /* Perform input expansion, key addition, and S-box substitution */ + for ( i = 0 ; i < 8 ; i++ ) { + + /* Rotate input and output */ + out = rol32 ( out, 4 ); + in = rol32 ( in, 4 ); + + /* Extract step key from relevant 6 bits of round key + * + * The least significant of the 6 bits (corresponding + * to bit r0 in the S-box lookup index) is stored in + * the sign bit of the step key byte. It will + * therefore be propagated via sign extension to the + * MSB of the 32-bit step key. + * + * The remaining 5 of the 6 bits (corresponding to + * bits {r1,c3,c2,c1,c0} in the S-box lookup index) + * are stored in the least significant 5 bits of the + * step key byte and will end up in the least + * significant 5 bits of the 32-bit step key. + */ + key = rkey->step[i]; + + /* Add step key to input to produce S-box lookup index + * + * We do not ever perform an explicit expansion of the + * input value from 32 to 48 bits. Instead, we rotate + * the 32-bit input value by 4 bits on each step, and + * extract the relevant 6 bits. + * + * The least significant of the 6 bits (corresponding + * to bit r0 in the S-box lookup index) is currently + * in the MSB of the 32-bit (rotated) input value. + * + * The remaining 5 of the 6 bits (corresponding to + * bits {r1,c3,c2,c1,c0} in the S-box lookup index) + * are currently in the least significant 5 bits of + * the 32-bit (rotated) input value. + * + * This aligns with the placement of the bits in the + * step key (see above), and we can therefore perform + * a single XOR to add the 6-bit step key to the + * relevant 6 bits of the input value. + */ + lookup = ( in ^ key ); + + /* Look up S[i][in ^ key] from S-box + * + * We have bits {r1,c3,c2,c1,c0} in the least + * significant 5 bits of the lookup index, and so can + * use the masked lookup index directly as a byte + * index into the relevant S-box to extract the byte + * containing both {r1,c3,c2,c1,c0,'0'} and + * {r1,c3,c2,c1,c0,'1'}. + * + * We then use the MSB of the 32-bit lookup index to + * extract the relevant nibble for the full lookup + * index {r1,c3,c2,c1,c0,r0}. + */ + sub = des_s[i][ lookup & 0x1f ]; + sub >>= ( ( lookup >> 29 ) & 4 ); + sub &= 0x0f; + + /* Substitute S[i][input ^ key] into output */ + out |= sub; + } + + return out; +} + +/** + * Perform a single DES round + * + * @v block DES block + * @v rkey 48-bit round key + */ +static void des_round ( union des_block *block, + const union des_round_key *rkey ) { + union des_dword sbox; + uint32_t left; + uint32_t right; + + /* Extract left and right halves L[n-1] and R[n-1] */ + left = block->left.dword; + right = block->right.dword; + DBGC2 ( block, "DES L=%08x R=%08x K=%08x%08x", be32_to_cpu ( left ), + be32_to_cpu ( right ), be32_to_cpu ( rkey->dword[0] ), + be32_to_cpu ( rkey->dword[1] ) ); + + /* L[n] = R[n-1] */ + block->left.dword = right; + + /* Calculate Feistel function f(R[n-1], K[n]) */ + sbox.dword = cpu_to_be32 ( des_sbox ( be32_to_cpu ( right ), rkey ) ); + des_permute ( des_p, sbox.byte, block->right.byte ); + + /* R[n] = L[n-1] + f(R[n-1], K[n]) */ + block->right.dword ^= left; + DBGC2 ( block, " => L=%08x R=%08x\n", + be32_to_cpu ( block->left.dword ), + be32_to_cpu ( block->right.dword ) ); +} + +/** + * Perform all DES rounds + * + * @v in Input DES block + * @v out Output DES block + * @v rkey Starting 48-bit round key + * @v offset Byte offset between round keys + */ +static void des_rounds ( const union des_block *in, union des_block *out, + const union des_round_key *rkey, + ssize_t offset ) { + union des_block tmp; + unsigned int i; + + /* Apply initial permutation */ + des_permute ( des_ip, in->byte, tmp.byte ); + + /* Perform all DES rounds, consuming keys in the specified order */ + for ( i = 0 ; i < DES_ROUNDS ; i++ ) { + des_round ( &tmp, rkey ); + rkey = ( ( ( void * ) rkey ) + offset ); + } + + /* Apply final permutation */ + DBGC ( &tmp, "DES %scrypted %08x%08x => ", + ( ( offset > 0 ) ? "en" : "de" ), be32_to_cpu ( in->dword[0] ), + be32_to_cpu ( in->dword[1] ) ); + des_permute ( des_fp, tmp.byte, out->byte ); + DBGC ( &tmp, "%08x%08x\n", be32_to_cpu ( out->dword[0] ), + be32_to_cpu ( out->dword[1] ) ); +} + +/** + * Rotate 28-bit word + * + * @v dword 28-bit dword value + * @ret dword Rotated 28-bit dword value + */ +static uint32_t des_rol28 ( uint32_t dword ) { + int32_t sdword; + + /* Convert to native-endian */ + sdword = be32_to_cpu ( dword ); + + /* Signed shift right by 4 places to copy bit 31 to bits 27:31 */ + sdword >>= 4; + + /* Rotate left */ + sdword = rol32 ( sdword, 1 ); + + /* Shift left by 4 places to restore bit positions */ + sdword <<= 4; + + /* Convert back to big-endian */ + dword = cpu_to_be32 ( sdword ); + + return dword; +} + +/** + * Set key + * + * @v ctx Context + * @v key Key + * @v keylen Key length + * @ret rc Return status code + */ +static int des_setkey ( void *ctx, const void *key, size_t keylen ) { + struct des_context *des = ctx; + union des_round_key *rkey = des->rkey; + union des_block reg; + uint32_t schedule; + + /* Validate key length */ + if ( keylen != DES_BLOCKSIZE ) + return -EINVAL; + DBGC ( des, "DES %p new key:\n", des ); + DBGC_HDA ( des, 0, key, keylen ); + + /* Apply permuted choice 1 */ + des_permute ( des_pc1c, key, reg.c.byte ); + des_permute ( des_pc1d, key, reg.d.byte ); + reg.d.byte[3] <<= 4; /* see comment for @c des_pc1d */ + DBGC2 ( des, "DES %p C[ 0]=%07x D[ 0]=%07x\n", + des, ( be32_to_cpu ( reg.c.dword ) >> 4 ), + ( be32_to_cpu ( reg.d.dword ) >> 4 ) ); + + /* Generate round keys */ + for ( schedule = DES_SCHEDULE ; schedule ; schedule >>= 1 ) { + + /* Shift 28-bit words */ + reg.c.dword = des_rol28 ( reg.c.dword ); + reg.d.dword = des_rol28 ( reg.d.dword ); + + /* Skip rounds according to shift schedule */ + if ( ! ( schedule & 1 ) ) + continue; + + /* Apply permuted choice 2 */ + des_permute ( des_pc2, reg.byte, rkey->byte ); + DBGC2 ( des, "DES %p C[%2zd]=%07x D[%2zd]=%07x K[%2zd]=" + "%08x%08x\n", des, ( ( rkey - des->rkey ) + 1 ), + ( be32_to_cpu ( reg.c.dword ) >> 4 ), + ( ( rkey - des->rkey ) + 1 ), + ( be32_to_cpu ( reg.d.dword ) >> 4 ), + ( ( rkey - des->rkey ) + 1 ), + be32_to_cpu ( rkey->dword[0] ), + be32_to_cpu ( rkey->dword[1] ) ); + + /* Move to next key */ + rkey++; + } + + /* Sanity check */ + assert ( rkey == &des->rkey[DES_ROUNDS] ); + + return 0; +} + +/** + * Encrypt data + * + * @v ctx Context + * @v src Data to encrypt + * @v dst Buffer for encrypted data + * @v len Length of data + */ +static void des_encrypt ( void *ctx, const void *src, void *dst, size_t len ) { + struct des_context *des = ctx; + + /* Sanity check */ + assert ( len == DES_BLOCKSIZE ); + + /* Cipher using keys in forward direction */ + des_rounds ( src, dst, &des->rkey[0], sizeof ( des->rkey[0] ) ); +} + +/** + * Decrypt data + * + * @v ctx Context + * @v src Data to decrypt + * @v dst Buffer for decrypted data + * @v len Length of data + */ +static void des_decrypt ( void *ctx, const void *src, void *dst, size_t len ) { + struct des_context *des = ctx; + + /* Sanity check */ + assert ( len == DES_BLOCKSIZE ); + + /* Cipher using keys in reverse direction */ + des_rounds ( src, dst, &des->rkey[ DES_ROUNDS - 1 ], + -sizeof ( des->rkey[0] ) ); +} + +/** Basic DES algorithm */ +struct cipher_algorithm des_algorithm = { + .name = "des", + .ctxsize = sizeof ( struct des_context ), + .blocksize = DES_BLOCKSIZE, + .alignsize = 0, + .authsize = 0, + .setkey = des_setkey, + .setiv = cipher_null_setiv, + .encrypt = des_encrypt, + .decrypt = des_decrypt, + .auth = cipher_null_auth, +}; + +/* DES in Electronic Codebook mode */ +ECB_CIPHER ( des_ecb, des_ecb_algorithm, + des_algorithm, struct des_context, DES_BLOCKSIZE ); + +/* DES in Cipher Block Chaining mode */ +CBC_CIPHER ( des_cbc, des_cbc_algorithm, + des_algorithm, struct des_context, DES_BLOCKSIZE ); diff --git a/src/include/ipxe/des.h b/src/include/ipxe/des.h new file mode 100644 index 000000000..755a90ea0 --- /dev/null +++ b/src/include/ipxe/des.h @@ -0,0 +1,91 @@ +#ifndef _IPXE_DES_H +#define _IPXE_DES_H + +/** @file + * + * DES algorithm + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <ipxe/crypto.h> + +/** A DES 32-bit dword value + * + * DES views data as 64-bit big-endian values, typically handled as a + * most-significant "left" half and a least-significant "right" half. + */ +union des_dword { + /** Raw bytes */ + uint8_t byte[4]; + /** 32-bit big-endian dword */ + uint32_t dword; +}; + +/** A DES 64-bit block */ +union des_block { + /** Raw bytes */ + uint8_t byte[8]; + /** 32-bit big-endian dwords */ + uint32_t dword[2]; + /** Named left and right halves */ + struct { + /** Left (most significant) half */ + union des_dword left; + /** Right (least significant) half */ + union des_dword right; + }; + /** Named "C" and "D" halves */ + struct { + /** "C" (most significant) half */ + union des_dword c; + /** "D" (least significant) half */ + union des_dword d; + }; +}; + +/** DES blocksize */ +#define DES_BLOCKSIZE sizeof ( union des_block ) + +/** A DES round key + * + * A DES round key is a 48-bit value, consumed as 8 groups of 6 bits. + * We store these as 8 separate bytes, for simplicity of consumption. + */ +union des_round_key { + /** Raw bytes */ + uint8_t byte[8]; + /** 32-bit big-endian dwords */ + uint32_t dword[2]; + /** 6-bit step key byte + * + * There are 8 steps within a DES round (one step per S-box). + * Each step requires six bits of the round key. + * + * As an optimisation, we store the least significant of the 6 + * bits in the sign bit of a signed 8-bit value, and the + * remaining 5 bits in the least significant 5 bits of the + * 8-bit value. See the comments in des_sbox() for further + * details. + */ + int8_t step[8]; +}; + +/** Number of DES rounds */ +#define DES_ROUNDS 16 + +/** DES context */ +struct des_context { + /** Round keys */ + union des_round_key rkey[DES_ROUNDS]; +}; + +/** DES context size */ +#define DES_CTX_SIZE sizeof ( struct des_context ) + +extern struct cipher_algorithm des_algorithm; +extern struct cipher_algorithm des_ecb_algorithm; +extern struct cipher_algorithm des_cbc_algorithm; + +#endif /* _IPXE_DES_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 060a42a33..f7a00dbe7 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -408,6 +408,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_efi_shim ( ERRFILE_OTHER | 0x005d0000 ) #define ERRFILE_efi_settings ( ERRFILE_OTHER | 0x005e0000 ) #define ERRFILE_x25519 ( ERRFILE_OTHER | 0x005f0000 ) +#define ERRFILE_des ( ERRFILE_OTHER | 0x00600000 ) /** @} */ diff --git a/src/tests/des_test.c b/src/tests/des_test.c new file mode 100644 index 000000000..ffafbd810 --- /dev/null +++ b/src/tests/des_test.c @@ -0,0 +1,898 @@ +/* + * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * DES tests + * + * These test vectors are originally provided by NBS (the precursor of + * NIST) in SP 500-20, downloadable as a scan of the typewritten + * original from: + * + * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nbsspecialpublication500-20e1980.pdf + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include <assert.h> +#include <ipxe/des.h> +#include <ipxe/test.h> +#include "cipher_test.h" + +/** Define a DES 64-bit test value */ +#define DES_VALUE(value) { \ + ( ( ( ( uint64_t ) (value) ) >> 56 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 48 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 40 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 32 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 24 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 16 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 8 ) & 0xff ), \ + ( ( ( ( uint64_t ) (value) ) >> 0 ) & 0xff ) \ + } + +/** Define a DES test */ +#define DES_TEST( name, key, plaintext, ciphertext ) \ + CIPHER_TEST ( name, &des_ecb_algorithm, DES_VALUE ( key ), \ + IV(), ADDITIONAL(), DES_VALUE ( plaintext ), \ + DES_VALUE ( ciphertext ), AUTH() ) + +/* Sample round outputs (page 9) */ +DES_TEST ( des_round_sample, + 0x10316e028c8f3b4a, 0x0000000000000000, 0x82dcbafbdeab6602 ); + +/* Test 1: Initial permutation and expansion tests + * + * "Set Key=0 and encrypt the 64-bit data vectors e[i]: i=1,...,64" + * + * Appendix B, page 28 ("IP and E test") + */ +DES_TEST ( des_test1_1, + 0x0101010101010101, 0x8000000000000000, 0x95f8a5e5dd31d900 ); +DES_TEST ( des_test1_2, + 0x0101010101010101, 0x4000000000000000, 0xdd7f121ca5015619 ); +DES_TEST ( des_test1_3, + 0x0101010101010101, 0x2000000000000000, 0x2e8653104f3834ea ); +DES_TEST ( des_test1_4, + 0x0101010101010101, 0x1000000000000000, 0x4bd388ff6cd81d4f ); +DES_TEST ( des_test1_5, + 0x0101010101010101, 0x0800000000000000, 0x20b9e767b2fb1456 ); +DES_TEST ( des_test1_6, + 0x0101010101010101, 0x0400000000000000, 0x55579380d77138ef ); +DES_TEST ( des_test1_7, + 0x0101010101010101, 0x0200000000000000, 0x6cc5defaaf04512f ); +DES_TEST ( des_test1_8, + 0x0101010101010101, 0x0100000000000000, 0x0d9f279ba5d87260 ); +DES_TEST ( des_test1_9, + 0x0101010101010101, 0x0080000000000000, 0xd9031b0271bd5a0a ); +DES_TEST ( des_test1_10, + 0x0101010101010101, 0x0040000000000000, 0x424250b37c3dd951 ); +DES_TEST ( des_test1_11, + 0x0101010101010101, 0x0020000000000000, 0xb8061b7ecd9a21e5 ); +DES_TEST ( des_test1_12, + 0x0101010101010101, 0x0010000000000000, 0xf15d0f286b65bd28 ); +DES_TEST ( des_test1_13, + 0x0101010101010101, 0x0008000000000000, 0xadd0cc8d6e5deba1 ); +DES_TEST ( des_test1_14, + 0x0101010101010101, 0x0004000000000000, 0xe6d5f82752ad63d1 ); +DES_TEST ( des_test1_15, + 0x0101010101010101, 0x0002000000000000, 0xecbfe3bd3f591a5e ); +DES_TEST ( des_test1_16, + 0x0101010101010101, 0x0001000000000000, 0xf356834379d165cd ); +DES_TEST ( des_test1_17, + 0x0101010101010101, 0x0000800000000000, 0x2b9f982f20037fa9 ); +DES_TEST ( des_test1_18, + 0x0101010101010101, 0x0000400000000000, 0x889de068a16f0be6 ); +DES_TEST ( des_test1_19, + 0x0101010101010101, 0x0000200000000000, 0xe19e275d846a1298 ); +DES_TEST ( des_test1_20, + 0x0101010101010101, 0x0000100000000000, 0x329a8ed523d71aec ); +DES_TEST ( des_test1_21, + 0x0101010101010101, 0x0000080000000000, 0xe7fce22557d23c97 ); +DES_TEST ( des_test1_22, + 0x0101010101010101, 0x0000040000000000, 0x12a9f5817ff2d65d ); +DES_TEST ( des_test1_23, + 0x0101010101010101, 0x0000020000000000, 0xa484c3ad38dc9c19 ); +DES_TEST ( des_test1_24, + 0x0101010101010101, 0x0000010000000000, 0xfbe00a8a1ef8ad72 ); +DES_TEST ( des_test1_25, + 0x0101010101010101, 0x0000008000000000, 0x750d079407521363 ); +DES_TEST ( des_test1_26, + 0x0101010101010101, 0x0000004000000000, 0x64feed9c724c2faf ); +DES_TEST ( des_test1_27, + 0x0101010101010101, 0x0000002000000000, 0xf02b263b328e2b60 ); +DES_TEST ( des_test1_28, + 0x0101010101010101, 0x0000001000000000, 0x9d64555a9a10b852 ); +DES_TEST ( des_test1_29, + 0x0101010101010101, 0x0000000800000000, 0xd106ff0bed5255d7 ); +DES_TEST ( des_test1_30, + 0x0101010101010101, 0x0000000400000000, 0xe1652c6b138c64a5 ); +DES_TEST ( des_test1_31, + 0x0101010101010101, 0x0000000200000000, 0xe428581186ec8f46 ); +DES_TEST ( des_test1_32, + 0x0101010101010101, 0x0000000100000000, 0xaeb5f5ede22d1a36 ); +DES_TEST ( des_test1_33, + 0x0101010101010101, 0x0000000080000000, 0xe943d7568aec0c5c ); +DES_TEST ( des_test1_34, + 0x0101010101010101, 0x0000000040000000, 0xdf98c8276f54b04b ); +DES_TEST ( des_test1_35, + 0x0101010101010101, 0x0000000020000000, 0xb160e4680f6c696f ); +DES_TEST ( des_test1_36, + 0x0101010101010101, 0x0000000010000000, 0xfa0752b07d9c4ab8 ); +DES_TEST ( des_test1_37, + 0x0101010101010101, 0x0000000008000000, 0xca3a2b036dbc8502 ); +DES_TEST ( des_test1_38, + 0x0101010101010101, 0x0000000004000000, 0x5e0905517bb59bcf ); +DES_TEST ( des_test1_39, + 0x0101010101010101, 0x0000000002000000, 0x814eeb3b91d90726 ); +DES_TEST ( des_test1_40, + 0x0101010101010101, 0x0000000001000000, 0x4d49db1532919c9f ); +DES_TEST ( des_test1_41, + 0x0101010101010101, 0x0000000000800000, 0x25eb5fc3f8cf0621 ); +DES_TEST ( des_test1_42, + 0x0101010101010101, 0x0000000000400000, 0xab6a20c0620d1c6f ); +DES_TEST ( des_test1_43, + 0x0101010101010101, 0x0000000000200000, 0x79e90dbc98f92cca ); +DES_TEST ( des_test1_44, + 0x0101010101010101, 0x0000000000100000, 0x866ecedd8072bb0e ); +DES_TEST ( des_test1_45, + 0x0101010101010101, 0x0000000000080000, 0x8b54536f2f3e64a8 ); +DES_TEST ( des_test1_46, + 0x0101010101010101, 0x0000000000040000, 0xea51d3975595b86b ); +DES_TEST ( des_test1_47, + 0x0101010101010101, 0x0000000000020000, 0xcaffc6ac4542de31 ); +DES_TEST ( des_test1_48, + 0x0101010101010101, 0x0000000000010000, 0x8dd45a2ddf90796c ); +DES_TEST ( des_test1_49, + 0x0101010101010101, 0x0000000000008000, 0x1029d55e880ec2d0 ); +DES_TEST ( des_test1_50, + 0x0101010101010101, 0x0000000000004000, 0x5d86cb23639dbea9 ); +DES_TEST ( des_test1_51, + 0x0101010101010101, 0x0000000000002000, 0x1d1ca853ae7c0c5f ); +DES_TEST ( des_test1_52, + 0x0101010101010101, 0x0000000000001000, 0xce332329248f3228 ); +DES_TEST ( des_test1_53, + 0x0101010101010101, 0x0000000000000800, 0x8405d1abe24fb942 ); +DES_TEST ( des_test1_54, + 0x0101010101010101, 0x0000000000000400, 0xe643d78090ca4207 ); +DES_TEST ( des_test1_55, + 0x0101010101010101, 0x0000000000000200, 0x48221b9937748a23 ); +DES_TEST ( des_test1_56, + 0x0101010101010101, 0x0000000000000100, 0xdd7c0bbd61fafd54 ); +DES_TEST ( des_test1_57, + 0x0101010101010101, 0x0000000000000080, 0x2fbc291a570db5c4 ); +DES_TEST ( des_test1_58, + 0x0101010101010101, 0x0000000000000040, 0xe07c30d7e4e26e12 ); +DES_TEST ( des_test1_59, + 0x0101010101010101, 0x0000000000000020, 0x0953e2258e8e90a1 ); +DES_TEST ( des_test1_60, + 0x0101010101010101, 0x0000000000000010, 0x5b711bc4ceebf2ee ); +DES_TEST ( des_test1_61, + 0x0101010101010101, 0x0000000000000008, 0xcc083f1e6d9e85f6 ); +DES_TEST ( des_test1_62, + 0x0101010101010101, 0x0000000000000004, 0xd2fd8867d50d2dfe ); +DES_TEST ( des_test1_63, + 0x0101010101010101, 0x0000000000000002, 0x06e7ea22ce92708f ); +DES_TEST ( des_test1_64, + 0x0101010101010101, 0x0000000000000001, 0x166b40b44aba4bd6 ); + +/* Test 2: Inverse permutation and expansion tests + * + * "Set Key=0 and encrypt the results c[i] obtained in Test 1" + * + * Appendix B, page 28 ("IP and E test") + */ +DES_TEST ( des_test2_1, + 0x0101010101010101, 0x95f8a5e5dd31d900, 0x8000000000000000 ); +DES_TEST ( des_test2_2, + 0x0101010101010101, 0xdd7f121ca5015619, 0x4000000000000000 ); +DES_TEST ( des_test2_3, + 0x0101010101010101, 0x2e8653104f3834ea, 0x2000000000000000 ); +DES_TEST ( des_test2_4, + 0x0101010101010101, 0x4bd388ff6cd81d4f, 0x1000000000000000 ); +DES_TEST ( des_test2_5, + 0x0101010101010101, 0x20b9e767b2fb1456, 0x0800000000000000 ); +DES_TEST ( des_test2_6, + 0x0101010101010101, 0x55579380d77138ef, 0x0400000000000000 ); +DES_TEST ( des_test2_7, + 0x0101010101010101, 0x6cc5defaaf04512f, 0x0200000000000000 ); +DES_TEST ( des_test2_8, + 0x0101010101010101, 0x0d9f279ba5d87260, 0x0100000000000000 ); +DES_TEST ( des_test2_9, + 0x0101010101010101, 0xd9031b0271bd5a0a, 0x0080000000000000 ); +DES_TEST ( des_test2_10, + 0x0101010101010101, 0x424250b37c3dd951, 0x0040000000000000 ); +DES_TEST ( des_test2_11, + 0x0101010101010101, 0xb8061b7ecd9a21e5, 0x0020000000000000 ); +DES_TEST ( des_test2_12, + 0x0101010101010101, 0xf15d0f286b65bd28, 0x0010000000000000 ); +DES_TEST ( des_test2_13, + 0x0101010101010101, 0xadd0cc8d6e5deba1, 0x0008000000000000 ); +DES_TEST ( des_test2_14, + 0x0101010101010101, 0xe6d5f82752ad63d1, 0x0004000000000000 ); +DES_TEST ( des_test2_15, + 0x0101010101010101, 0xecbfe3bd3f591a5e, 0x0002000000000000 ); +DES_TEST ( des_test2_16, + 0x0101010101010101, 0xf356834379d165cd, 0x0001000000000000 ); +DES_TEST ( des_test2_17, + 0x0101010101010101, 0x2b9f982f20037fa9, 0x0000800000000000 ); +DES_TEST ( des_test2_18, + 0x0101010101010101, 0x889de068a16f0be6, 0x0000400000000000 ); +DES_TEST ( des_test2_19, + 0x0101010101010101, 0xe19e275d846a1298, 0x0000200000000000 ); +DES_TEST ( des_test2_20, + 0x0101010101010101, 0x329a8ed523d71aec, 0x0000100000000000 ); +DES_TEST ( des_test2_21, + 0x0101010101010101, 0xe7fce22557d23c97, 0x0000080000000000 ); +DES_TEST ( des_test2_22, + 0x0101010101010101, 0x12a9f5817ff2d65d, 0x0000040000000000 ); +DES_TEST ( des_test2_23, + 0x0101010101010101, 0xa484c3ad38dc9c19, 0x0000020000000000 ); +DES_TEST ( des_test2_24, + 0x0101010101010101, 0xfbe00a8a1ef8ad72, 0x0000010000000000 ); +DES_TEST ( des_test2_25, + 0x0101010101010101, 0x750d079407521363, 0x0000008000000000 ); +DES_TEST ( des_test2_26, + 0x0101010101010101, 0x64feed9c724c2faf, 0x0000004000000000 ); +DES_TEST ( des_test2_27, + 0x0101010101010101, 0xf02b263b328e2b60, 0x0000002000000000 ); +DES_TEST ( des_test2_28, + 0x0101010101010101, 0x9d64555a9a10b852, 0x0000001000000000 ); +DES_TEST ( des_test2_29, + 0x0101010101010101, 0xd106ff0bed5255d7, 0x0000000800000000 ); +DES_TEST ( des_test2_30, + 0x0101010101010101, 0xe1652c6b138c64a5, 0x0000000400000000 ); +DES_TEST ( des_test2_31, + 0x0101010101010101, 0xe428581186ec8f46, 0x0000000200000000 ); +DES_TEST ( des_test2_32, + 0x0101010101010101, 0xaeb5f5ede22d1a36, 0x0000000100000000 ); +DES_TEST ( des_test2_33, + 0x0101010101010101, 0xe943d7568aec0c5c, 0x0000000080000000 ); +DES_TEST ( des_test2_34, + 0x0101010101010101, 0xdf98c8276f54b04b, 0x0000000040000000 ); +DES_TEST ( des_test2_35, + 0x0101010101010101, 0xb160e4680f6c696f, 0x0000000020000000 ); +DES_TEST ( des_test2_36, + 0x0101010101010101, 0xfa0752b07d9c4ab8, 0x0000000010000000 ); +DES_TEST ( des_test2_37, + 0x0101010101010101, 0xca3a2b036dbc8502, 0x0000000008000000 ); +DES_TEST ( des_test2_38, + 0x0101010101010101, 0x5e0905517bb59bcf, 0x0000000004000000 ); +DES_TEST ( des_test2_39, + 0x0101010101010101, 0x814eeb3b91d90726, 0x0000000002000000 ); +DES_TEST ( des_test2_40, + 0x0101010101010101, 0x4d49db1532919c9f, 0x0000000001000000 ); +DES_TEST ( des_test2_41, + 0x0101010101010101, 0x25eb5fc3f8cf0621, 0x0000000000800000 ); +DES_TEST ( des_test2_42, + 0x0101010101010101, 0xab6a20c0620d1c6f, 0x0000000000400000 ); +DES_TEST ( des_test2_43, + 0x0101010101010101, 0x79e90dbc98f92cca, 0x0000000000200000 ); +DES_TEST ( des_test2_44, + 0x0101010101010101, 0x866ecedd8072bb0e, 0x0000000000100000 ); +DES_TEST ( des_test2_45, + 0x0101010101010101, 0x8b54536f2f3e64a8, 0x0000000000080000 ); +DES_TEST ( des_test2_46, + 0x0101010101010101, 0xea51d3975595b86b, 0x0000000000040000 ); +DES_TEST ( des_test2_47, + 0x0101010101010101, 0xcaffc6ac4542de31, 0x0000000000020000 ); +DES_TEST ( des_test2_48, + 0x0101010101010101, 0x8dd45a2ddf90796c, 0x0000000000010000 ); +DES_TEST ( des_test2_49, + 0x0101010101010101, 0x1029d55e880ec2d0, 0x0000000000008000 ); +DES_TEST ( des_test2_50, + 0x0101010101010101, 0x5d86cb23639dbea9, 0x0000000000004000 ); +DES_TEST ( des_test2_51, + 0x0101010101010101, 0x1d1ca853ae7c0c5f, 0x0000000000002000 ); +DES_TEST ( des_test2_52, + 0x0101010101010101, 0xce332329248f3228, 0x0000000000001000 ); +DES_TEST ( des_test2_53, + 0x0101010101010101, 0x8405d1abe24fb942, 0x0000000000000800 ); +DES_TEST ( des_test2_54, + 0x0101010101010101, 0xe643d78090ca4207, 0x0000000000000400 ); +DES_TEST ( des_test2_55, + 0x0101010101010101, 0x48221b9937748a23, 0x0000000000000200 ); +DES_TEST ( des_test2_56, + 0x0101010101010101, 0xdd7c0bbd61fafd54, 0x0000000000000100 ); +DES_TEST ( des_test2_57, + 0x0101010101010101, 0x2fbc291a570db5c4, 0x0000000000000080 ); +DES_TEST ( des_test2_58, + 0x0101010101010101, 0xe07c30d7e4e26e12, 0x0000000000000040 ); +DES_TEST ( des_test2_59, + 0x0101010101010101, 0x0953e2258e8e90a1, 0x0000000000000020 ); +DES_TEST ( des_test2_60, + 0x0101010101010101, 0x5b711bc4ceebf2ee, 0x0000000000000010 ); +DES_TEST ( des_test2_61, + 0x0101010101010101, 0xcc083f1e6d9e85f6, 0x0000000000000008 ); +DES_TEST ( des_test2_62, + 0x0101010101010101, 0xd2fd8867d50d2dfe, 0x0000000000000004 ); +DES_TEST ( des_test2_63, + 0x0101010101010101, 0x06e7ea22ce92708f, 0x0000000000000002 ); +DES_TEST ( des_test2_64, + 0x0101010101010101, 0x166b40b44aba4bd6, 0x0000000000000001 ); + +/* Test 3: Data permutation tests + * + * "Set the plaintext to zero and process the 32 keys in PTEST" + * + * Appendix B, page 32 ("PTEST") + */ +DES_TEST ( des_test3_1, + 0x1046913489980131, 0x0000000000000000, 0x88d55e54f54c97b4 ); +DES_TEST ( des_test3_2, + 0x1007103489988020, 0x0000000000000000, 0x0c0cc00c83ea48fd ); +DES_TEST ( des_test3_3, + 0x10071034c8980120, 0x0000000000000000, 0x83bc8ef3a6570183 ); +DES_TEST ( des_test3_4, + 0x1046103489988020, 0x0000000000000000, 0xdf725dcad94ea2e9 ); +DES_TEST ( des_test3_5, + 0x1086911519190101, 0x0000000000000000, 0xe652b53b550be8b0 ); +DES_TEST ( des_test3_6, + 0x1086911519580101, 0x0000000000000000, 0xaf527120c485cbb0 ); +DES_TEST ( des_test3_7, + 0x5107b01519580101, 0x0000000000000000, 0x0f04ce393db926d5 ); +DES_TEST ( des_test3_8, + 0x1007b01519190101, 0x0000000000000000, 0xc9f00ffc74079067 ); +DES_TEST ( des_test3_9, + 0x3107915498080101, 0x0000000000000000, 0x7cfd82a593252b4e ); +DES_TEST ( des_test3_10, + 0x3107919498080101, 0x0000000000000000, 0xcb49a2f9e91363e3 ); +DES_TEST ( des_test3_11, + 0x10079115b9080140, 0x0000000000000000, 0x00b588be70d23f56 ); +DES_TEST ( des_test3_12, + 0x3107911598080140, 0x0000000000000000, 0x406a9a6ab43399ae ); +DES_TEST ( des_test3_13, + 0x1007d01589980101, 0x0000000000000000, 0x6cb773611dca9ada ); +DES_TEST ( des_test3_14, + 0x9107911589980101, 0x0000000000000000, 0x67fd21c17dbb5d70 ); +DES_TEST ( des_test3_15, + 0x9107d01589190101, 0x0000000000000000, 0x9592cb4110430787 ); +DES_TEST ( des_test3_16, + 0x1007d01598980120, 0x0000000000000000, 0xa6b7ff68a318ddd3 ); +DES_TEST ( des_test3_17, + 0x1007940498190101, 0x0000000000000000, 0x4d102196c914ca16 ); +DES_TEST ( des_test3_18, + 0x0107910491190401, 0x0000000000000000, 0x2dfa9f4573594965 ); +DES_TEST ( des_test3_19, + 0x0107910491190101, 0x0000000000000000, 0xb46604816c0e0774 ); +DES_TEST ( des_test3_20, + 0x0107940491190401, 0x0000000000000000, 0x6e7e6221a4f34e87 ); +DES_TEST ( des_test3_21, + 0x19079210981a0101, 0x0000000000000000, 0xaa85e74643233199 ); +DES_TEST ( des_test3_22, + 0x1007911998190801, 0x0000000000000000, 0x2e5a19db4d1962d6 ); +DES_TEST ( des_test3_23, + 0x10079119981a0801, 0x0000000000000000, 0x23a866a809d30894 ); +DES_TEST ( des_test3_24, + 0x1007921098190101, 0x0000000000000000, 0xd812d961f017d320 ); +DES_TEST ( des_test3_25, + 0x100791159819010b, 0x0000000000000000, 0x055605816e58608f ); +DES_TEST ( des_test3_26, + 0x1004801598190101, 0x0000000000000000, 0xabd88e8b1b7716f1 ); +DES_TEST ( des_test3_27, + 0x1004801598190102, 0x0000000000000000, 0x537ac95be69da1e1 ); +DES_TEST ( des_test3_28, + 0x1004801598190108, 0x0000000000000000, 0xaed0f6ae3c25cdd8 ); +DES_TEST ( des_test3_29, + 0x1002911498100104, 0x0000000000000000, 0xb3e35a5ee53e7b8d ); +DES_TEST ( des_test3_30, + 0x1002911598190104, 0x0000000000000000, 0x61c79c71921a2ef8 ); +DES_TEST ( des_test3_31, + 0x1002911598100201, 0x0000000000000000, 0xe2f5728f0995013c ); +DES_TEST ( des_test3_32, + 0x1002911698100101, 0x0000000000000000, 0x1aeac39a61f0a464 ); + +/* Test 4: Key permutation tests + * + * "Set Data=0 and use the keys e[i]: i=1,...,64 ignoring i=8,16,...,64" + * + * Test 4 part 1 is the forward direction as described above. Test 4 + * part 2 ("set data=c[i] from part 1 ... then decipher") is carried + * out for us automatically, since CIPHER_TEST() performs both + * encryption and decryption tests. + * + * Appendix B, page 30 ("PC1 and PC2 test") + */ +DES_TEST ( des_test4_1, + 0x8001010101010101, 0x0000000000000000, 0x95a8d72813daa94d ); +DES_TEST ( des_test4_2, + 0x4001010101010101, 0x0000000000000000, 0x0eec1487dd8c26d5 ); +DES_TEST ( des_test4_3, + 0x2001010101010101, 0x0000000000000000, 0x7ad16ffb79c45926 ); +DES_TEST ( des_test4_4, + 0x1001010101010101, 0x0000000000000000, 0xd3746294ca6a6cf3 ); +DES_TEST ( des_test4_5, + 0x0801010101010101, 0x0000000000000000, 0x809f5f873c1fd761 ); +DES_TEST ( des_test4_6, + 0x0401010101010101, 0x0000000000000000, 0xc02faffec989d1fc ); +DES_TEST ( des_test4_7, + 0x0201010101010101, 0x0000000000000000, 0x4615aa1d33e72f10 ); +DES_TEST ( des_test4_8, + 0x0180010101010101, 0x0000000000000000, 0x2055123350c00858 ); +DES_TEST ( des_test4_9, + 0x0140010101010101, 0x0000000000000000, 0xdf3b99d6577397c8 ); +DES_TEST ( des_test4_10, + 0x0120010101010101, 0x0000000000000000, 0x31fe17369b5288c9 ); +DES_TEST ( des_test4_11, + 0x0110010101010101, 0x0000000000000000, 0xdfdd3cc64dae1642 ); +DES_TEST ( des_test4_12, + 0x0108010101010101, 0x0000000000000000, 0x178c83ce2b399d94 ); +DES_TEST ( des_test4_13, + 0x0104010101010101, 0x0000000000000000, 0x50f636324a9b7f80 ); +DES_TEST ( des_test4_14, + 0x0102010101010101, 0x0000000000000000, 0xa8468ee3bc18f06d ); +DES_TEST ( des_test4_15, + 0x0101800101010101, 0x0000000000000000, 0xa2dc9e92fd3cde92 ); +DES_TEST ( des_test4_16, + 0x0101400101010101, 0x0000000000000000, 0xcac09f797d031287 ); +DES_TEST ( des_test4_17, + 0x0101200101010101, 0x0000000000000000, 0x90ba680b22aeb525 ); +DES_TEST ( des_test4_18, + 0x0101100101010101, 0x0000000000000000, 0xce7a24f350e280b6 ); +DES_TEST ( des_test4_19, + 0x0101080101010101, 0x0000000000000000, 0x882bff0aa01a0b87 ); +DES_TEST ( des_test4_20, + 0x0101040101010101, 0x0000000000000000, 0x25610288924511c2 ); +DES_TEST ( des_test4_21, + 0x0101020101010101, 0x0000000000000000, 0xc71516c29c75d170 ); +DES_TEST ( des_test4_22, + 0x0101018001010101, 0x0000000000000000, 0x5199c29a52c9f059 ); +DES_TEST ( des_test4_23, + 0x0101014001010101, 0x0000000000000000, 0xc22f0a294a71f29f ); +DES_TEST ( des_test4_24, + 0x0101012001010101, 0x0000000000000000, 0xee371483714c02ea ); +DES_TEST ( des_test4_25, + 0x0101011001010101, 0x0000000000000000, 0xa81fbd448f9e522f ); +DES_TEST ( des_test4_26, + 0x0101010801010101, 0x0000000000000000, 0x4f644c92e192dfed ); +DES_TEST ( des_test4_27, + 0x0101010401010101, 0x0000000000000000, 0x1afa9a66a6df92ae ); +DES_TEST ( des_test4_28, + 0x0101010201010101, 0x0000000000000000, 0xb3c1cc715cb879d8 ); +DES_TEST ( des_test4_29, + 0x0101010180010101, 0x0000000000000000, 0x19d032e64ab0bd8b ); +DES_TEST ( des_test4_30, + 0x0101010140010101, 0x0000000000000000, 0x3cfaa7a7dc8720dc ); +DES_TEST ( des_test4_31, + 0x0101010120010101, 0x0000000000000000, 0xb7265f7f447ac6f3 ); +DES_TEST ( des_test4_32, + 0x0101010110010101, 0x0000000000000000, 0x9db73b3c0d163f54 ); +DES_TEST ( des_test4_33, + 0x0101010108010101, 0x0000000000000000, 0x8181b65babf4a975 ); +DES_TEST ( des_test4_34, + 0x0101010104010101, 0x0000000000000000, 0x93c9b64042eaa240 ); +DES_TEST ( des_test4_35, + 0x0101010102010101, 0x0000000000000000, 0x5570530829705592 ); +DES_TEST ( des_test4_36, + 0x0101010101800101, 0x0000000000000000, 0x8638809e878787a0 ); +DES_TEST ( des_test4_37, + 0x0101010101400101, 0x0000000000000000, 0x41b9a79af79ac208 ); +DES_TEST ( des_test4_38, + 0x0101010101200101, 0x0000000000000000, 0x7a9be42f2009a892 ); +DES_TEST ( des_test4_39, + 0x0101010101100101, 0x0000000000000000, 0x29038d56ba6d2745 ); +DES_TEST ( des_test4_40, + 0x0101010101080101, 0x0000000000000000, 0x5495c6abf1e5df51 ); +DES_TEST ( des_test4_41, + 0x0101010101040101, 0x0000000000000000, 0xae13dbd561488933 ); +DES_TEST ( des_test4_42, + 0x0101010101020101, 0x0000000000000000, 0x024d1ffa8904e389 ); +DES_TEST ( des_test4_43, + 0x0101010101018001, 0x0000000000000000, 0xd1399712f99bf02e ); +DES_TEST ( des_test4_44, + 0x0101010101014001, 0x0000000000000000, 0x14c1d7c1cffec79e ); +DES_TEST ( des_test4_45, + 0x0101010101012001, 0x0000000000000000, 0x1de5279dae3bed6f ); +DES_TEST ( des_test4_46, + 0x0101010101011001, 0x0000000000000000, 0xe941a33f85501303 ); +DES_TEST ( des_test4_47, + 0x0101010101010801, 0x0000000000000000, 0xda99dbbc9a03f379 ); +DES_TEST ( des_test4_48, + 0x0101010101010401, 0x0000000000000000, 0xb7fc92f91d8e92e9 ); +DES_TEST ( des_test4_49, + 0x0101010101010201, 0x0000000000000000, 0xae8e5caa3ca04e85 ); +DES_TEST ( des_test4_50, + 0x0101010101010180, 0x0000000000000000, 0x9cc62df43b6eed74 ); +DES_TEST ( des_test4_51, + 0x0101010101010140, 0x0000000000000000, 0xd863dbb5c59a91a0 ); +DES_TEST ( des_test4_52, + 0x0101010101010120, 0x0000000000000000, 0xa1ab2190545b91d7 ); +DES_TEST ( des_test4_53, + 0x0101010101010110, 0x0000000000000000, 0x0875041e64c570f7 ); +DES_TEST ( des_test4_54, + 0x0101010101010108, 0x0000000000000000, 0x5a594528bebef1cc ); +DES_TEST ( des_test4_55, + 0x0101010101010104, 0x0000000000000000, 0xfcdb3291de21f0c0 ); +DES_TEST ( des_test4_56, + 0x0101010101010102, 0x0000000000000000, 0x869efd7f9f265a09 ); + +/* Test 5: S-box tests + * + * "Set Data and Key equal to the inputs defined in the Substitution + * Table test" + * + * Appendix B, page 33 ("19 key data pairs which exercise every S-box entry") + */ +DES_TEST ( des_test5_1, + 0x7ca110454a1a6e57, 0x01a1d6d039776742, 0x690f5b0d9a26939b ); +DES_TEST ( des_test5_2, + 0x0131d9619dc1376e, 0x5cd54ca83def57da, 0x7a389d10354bd271 ); +DES_TEST ( des_test5_3, + 0x07a1133e4a0b2686, 0x0248d43806f67172, 0x868ebb51cab4599a ); +DES_TEST ( des_test5_4, + 0x3849674c2602319e, 0x51454b582ddf440a, 0x7178876e01f19b2a ); +DES_TEST ( des_test5_5, + 0x04b915ba43feb5b6, 0x42fd443059577fa2, 0xaf37fb421f8c4095 ); +DES_TEST ( des_test5_6, + 0x0113b970fd34f2ce, 0x059b5e0851cf143a, 0x86a560f10ec6d85b ); +DES_TEST ( des_test5_7, + 0x0170f175468fb5e6, 0x0756d8e0774761d2, 0x0cd3da020021dc09 ); +DES_TEST ( des_test5_8, + 0x43297fad38e373fe, 0x762514b829bf486a, 0xea676b2cb7db2b7a ); +DES_TEST ( des_test5_9, + 0x07a7137045da2a16, 0x3bdd119049372802, 0xdfd64a815caf1a0f ); +DES_TEST ( des_test5_10, + 0x04689104c2fd3b2f, 0x26955f6835af609a, 0x5c513c9c4886c088 ); +DES_TEST ( des_test5_11, + 0x37d06bb516cb7546, 0x164d5e404f275232, 0x0a2aeeae3ff4ab77 ); +DES_TEST ( des_test5_12, + 0x1f08260d1ac2465e, 0x6b056e18759f5cca, 0xef1bf03e5dfa575a ); +DES_TEST ( des_test5_13, + 0x584023641aba6176, 0x004bd6ef09176062, 0x88bf0db6d70dee56 ); +DES_TEST ( des_test5_14, + 0x025816164629b007, 0x480d39006ee762f2, 0xa1f9915541020b56 ); +DES_TEST ( des_test5_15, + 0x49793ebc79b3258f, 0x437540c8698f3cfa, 0x6fbf1cafcffd0556 ); +DES_TEST ( des_test5_16, + 0x4fb05e1515ab73a7, 0x072d43a077075292, 0x2f22e49bab7ca1ac ); +DES_TEST ( des_test5_17, + 0x49e95d6d4ca229bf, 0x02fe55778117f12a, 0x5a6b612cc26cce4a ); +DES_TEST ( des_test5_18, + 0x018310dc409b26d6, 0x1d9d5c5018f728c2, 0x5f4c038ed12b2e41 ); +DES_TEST ( des_test5_19, + 0x1c587f1c13924fef, 0x305532286d6f295a, 0x63fac0d034d9f793 ); + +/* Unofficial tests + * + * The official tests are all exactly one block in length. Add some + * multi-block tests (generated in Python). + */ +CIPHER_TEST ( des_unofficial_ecb, &des_ecb_algorithm, + KEY ( 0x6e, 0x6f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79 ), + IV(), ADDITIONAL(), + PLAINTEXT ( 0x53, 0x6f, 0x20, 0x63, 0x75, 0x74, 0x65, 0x20, + 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x61, + 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, + 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x6f, + 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x74, + 0x75, 0x61, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x21, 0x21 ), + CIPHERTEXT ( 0x1a, 0x02, 0x17, 0xcb, 0x93, 0xa3, 0xd2, 0xf2, + 0xf9, 0x45, 0x71, 0x1c, 0x33, 0xb1, 0x5c, 0xa4, + 0x8b, 0x6b, 0x11, 0x7a, 0x7c, 0x86, 0x7c, 0x7f, + 0x9f, 0x56, 0x61, 0x46, 0x7f, 0xa6, 0xae, 0xf1, + 0x49, 0xf7, 0x53, 0xe0, 0xbc, 0x15, 0x6a, 0x30, + 0xe7, 0xf8, 0xf3, 0x29, 0x11, 0xd8, 0x7d, 0x04, + 0x62, 0x5a, 0xaa, 0xa1, 0x89, 0x61, 0x4c, 0xf6, + 0x5a, 0x47, 0x3b, 0xc6, 0x04, 0x15, 0xce, 0xf6 ), + AUTH() ); +CIPHER_TEST ( des_unofficial_cbc, &des_cbc_algorithm, + KEY ( 0x6e, 0x6f, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79 ), + IV ( 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ), + ADDITIONAL(), + PLAINTEXT ( 0x53, 0x6f, 0x20, 0x63, 0x75, 0x74, 0x65, 0x20, + 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x61, + 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, + 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x6f, + 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x74, + 0x75, 0x61, 0x6c, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x72, 0x21, 0x21 ), + CIPHERTEXT ( 0x4c, 0x5f, 0x62, 0xfc, 0xf4, 0x93, 0x09, 0xb5, + 0x1d, 0x52, 0x25, 0xec, 0xc7, 0x42, 0x3c, 0x29, + 0x33, 0x67, 0xf5, 0xe9, 0xd6, 0x3c, 0x27, 0x5b, + 0x49, 0x69, 0xc5, 0xa9, 0x08, 0xa3, 0x14, 0x66, + 0x3c, 0x95, 0x33, 0x30, 0xcf, 0x3c, 0x7c, 0xaf, + 0xa3, 0xe4, 0xf8, 0x2e, 0xc3, 0x55, 0x57, 0x81, + 0x33, 0xd9, 0x90, 0xe2, 0x99, 0xdc, 0x32, 0x10, + 0x13, 0x21, 0xb6, 0xc1, 0x6b, 0x0f, 0x22, 0xa9 ), + AUTH() ); + +/** + * Perform DES self-test + * + */ +static void des_test_exec ( void ) { + + /* Sample round outputs (page 9) */ + cipher_ok ( &des_round_sample ); + + /* Test 1: Initial permutation and expansion tests */ + cipher_ok ( &des_test1_1 ); + cipher_ok ( &des_test1_2 ); + cipher_ok ( &des_test1_3 ); + cipher_ok ( &des_test1_4 ); + cipher_ok ( &des_test1_5 ); + cipher_ok ( &des_test1_6 ); + cipher_ok ( &des_test1_7 ); + cipher_ok ( &des_test1_8 ); + cipher_ok ( &des_test1_9 ); + cipher_ok ( &des_test1_10 ); + cipher_ok ( &des_test1_11 ); + cipher_ok ( &des_test1_12 ); + cipher_ok ( &des_test1_13 ); + cipher_ok ( &des_test1_14 ); + cipher_ok ( &des_test1_15 ); + cipher_ok ( &des_test1_16 ); + cipher_ok ( &des_test1_17 ); + cipher_ok ( &des_test1_18 ); + cipher_ok ( &des_test1_19 ); + cipher_ok ( &des_test1_20 ); + cipher_ok ( &des_test1_21 ); + cipher_ok ( &des_test1_22 ); + cipher_ok ( &des_test1_23 ); + cipher_ok ( &des_test1_24 ); + cipher_ok ( &des_test1_25 ); + cipher_ok ( &des_test1_26 ); + cipher_ok ( &des_test1_27 ); + cipher_ok ( &des_test1_28 ); + cipher_ok ( &des_test1_29 ); + cipher_ok ( &des_test1_30 ); + cipher_ok ( &des_test1_31 ); + cipher_ok ( &des_test1_32 ); + cipher_ok ( &des_test1_33 ); + cipher_ok ( &des_test1_34 ); + cipher_ok ( &des_test1_35 ); + cipher_ok ( &des_test1_36 ); + cipher_ok ( &des_test1_37 ); + cipher_ok ( &des_test1_38 ); + cipher_ok ( &des_test1_39 ); + cipher_ok ( &des_test1_40 ); + cipher_ok ( &des_test1_41 ); + cipher_ok ( &des_test1_42 ); + cipher_ok ( &des_test1_43 ); + cipher_ok ( &des_test1_44 ); + cipher_ok ( &des_test1_45 ); + cipher_ok ( &des_test1_46 ); + cipher_ok ( &des_test1_47 ); + cipher_ok ( &des_test1_48 ); + cipher_ok ( &des_test1_49 ); + cipher_ok ( &des_test1_50 ); + cipher_ok ( &des_test1_51 ); + cipher_ok ( &des_test1_52 ); + cipher_ok ( &des_test1_53 ); + cipher_ok ( &des_test1_54 ); + cipher_ok ( &des_test1_55 ); + cipher_ok ( &des_test1_56 ); + cipher_ok ( &des_test1_57 ); + cipher_ok ( &des_test1_58 ); + cipher_ok ( &des_test1_59 ); + cipher_ok ( &des_test1_60 ); + cipher_ok ( &des_test1_61 ); + cipher_ok ( &des_test1_62 ); + cipher_ok ( &des_test1_63 ); + cipher_ok ( &des_test1_64 ); + + /* Test 2: Inverse permutation and expansion tests */ + cipher_ok ( &des_test2_1 ); + cipher_ok ( &des_test2_2 ); + cipher_ok ( &des_test2_3 ); + cipher_ok ( &des_test2_4 ); + cipher_ok ( &des_test2_5 ); + cipher_ok ( &des_test2_6 ); + cipher_ok ( &des_test2_7 ); + cipher_ok ( &des_test2_8 ); + cipher_ok ( &des_test2_9 ); + cipher_ok ( &des_test2_10 ); + cipher_ok ( &des_test2_11 ); + cipher_ok ( &des_test2_12 ); + cipher_ok ( &des_test2_13 ); + cipher_ok ( &des_test2_14 ); + cipher_ok ( &des_test2_15 ); + cipher_ok ( &des_test2_16 ); + cipher_ok ( &des_test2_17 ); + cipher_ok ( &des_test2_18 ); + cipher_ok ( &des_test2_19 ); + cipher_ok ( &des_test2_20 ); + cipher_ok ( &des_test2_21 ); + cipher_ok ( &des_test2_22 ); + cipher_ok ( &des_test2_23 ); + cipher_ok ( &des_test2_24 ); + cipher_ok ( &des_test2_25 ); + cipher_ok ( &des_test2_26 ); + cipher_ok ( &des_test2_27 ); + cipher_ok ( &des_test2_28 ); + cipher_ok ( &des_test2_29 ); + cipher_ok ( &des_test2_30 ); + cipher_ok ( &des_test2_31 ); + cipher_ok ( &des_test2_32 ); + cipher_ok ( &des_test2_33 ); + cipher_ok ( &des_test2_34 ); + cipher_ok ( &des_test2_35 ); + cipher_ok ( &des_test2_36 ); + cipher_ok ( &des_test2_37 ); + cipher_ok ( &des_test2_38 ); + cipher_ok ( &des_test2_39 ); + cipher_ok ( &des_test2_40 ); + cipher_ok ( &des_test2_41 ); + cipher_ok ( &des_test2_42 ); + cipher_ok ( &des_test2_43 ); + cipher_ok ( &des_test2_44 ); + cipher_ok ( &des_test2_45 ); + cipher_ok ( &des_test2_46 ); + cipher_ok ( &des_test2_47 ); + cipher_ok ( &des_test2_48 ); + cipher_ok ( &des_test2_49 ); + cipher_ok ( &des_test2_50 ); + cipher_ok ( &des_test2_51 ); + cipher_ok ( &des_test2_52 ); + cipher_ok ( &des_test2_53 ); + cipher_ok ( &des_test2_54 ); + cipher_ok ( &des_test2_55 ); + cipher_ok ( &des_test2_56 ); + cipher_ok ( &des_test2_57 ); + cipher_ok ( &des_test2_58 ); + cipher_ok ( &des_test2_59 ); + cipher_ok ( &des_test2_60 ); + cipher_ok ( &des_test2_61 ); + cipher_ok ( &des_test2_62 ); + cipher_ok ( &des_test2_63 ); + cipher_ok ( &des_test2_64 ); + + /* Test 3: Data permutation tests */ + cipher_ok ( &des_test3_1 ); + cipher_ok ( &des_test3_2 ); + cipher_ok ( &des_test3_3 ); + cipher_ok ( &des_test3_4 ); + cipher_ok ( &des_test3_5 ); + cipher_ok ( &des_test3_6 ); + cipher_ok ( &des_test3_7 ); + cipher_ok ( &des_test3_8 ); + cipher_ok ( &des_test3_9 ); + cipher_ok ( &des_test3_10 ); + cipher_ok ( &des_test3_11 ); + cipher_ok ( &des_test3_12 ); + cipher_ok ( &des_test3_13 ); + cipher_ok ( &des_test3_14 ); + cipher_ok ( &des_test3_15 ); + cipher_ok ( &des_test3_16 ); + cipher_ok ( &des_test3_17 ); + cipher_ok ( &des_test3_18 ); + cipher_ok ( &des_test3_19 ); + cipher_ok ( &des_test3_20 ); + cipher_ok ( &des_test3_21 ); + cipher_ok ( &des_test3_22 ); + cipher_ok ( &des_test3_23 ); + cipher_ok ( &des_test3_24 ); + cipher_ok ( &des_test3_25 ); + cipher_ok ( &des_test3_26 ); + cipher_ok ( &des_test3_27 ); + cipher_ok ( &des_test3_28 ); + cipher_ok ( &des_test3_29 ); + cipher_ok ( &des_test3_30 ); + cipher_ok ( &des_test3_31 ); + cipher_ok ( &des_test3_32 ); + + /* Test 4: Key permutation tests */ + cipher_ok ( &des_test4_1 ); + cipher_ok ( &des_test4_2 ); + cipher_ok ( &des_test4_3 ); + cipher_ok ( &des_test4_4 ); + cipher_ok ( &des_test4_5 ); + cipher_ok ( &des_test4_6 ); + cipher_ok ( &des_test4_7 ); + cipher_ok ( &des_test4_8 ); + cipher_ok ( &des_test4_9 ); + cipher_ok ( &des_test4_10 ); + cipher_ok ( &des_test4_11 ); + cipher_ok ( &des_test4_12 ); + cipher_ok ( &des_test4_13 ); + cipher_ok ( &des_test4_14 ); + cipher_ok ( &des_test4_15 ); + cipher_ok ( &des_test4_16 ); + cipher_ok ( &des_test4_17 ); + cipher_ok ( &des_test4_18 ); + cipher_ok ( &des_test4_19 ); + cipher_ok ( &des_test4_20 ); + cipher_ok ( &des_test4_21 ); + cipher_ok ( &des_test4_22 ); + cipher_ok ( &des_test4_23 ); + cipher_ok ( &des_test4_24 ); + cipher_ok ( &des_test4_25 ); + cipher_ok ( &des_test4_26 ); + cipher_ok ( &des_test4_27 ); + cipher_ok ( &des_test4_28 ); + cipher_ok ( &des_test4_29 ); + cipher_ok ( &des_test4_30 ); + cipher_ok ( &des_test4_31 ); + cipher_ok ( &des_test4_32 ); + cipher_ok ( &des_test4_33 ); + cipher_ok ( &des_test4_34 ); + cipher_ok ( &des_test4_35 ); + cipher_ok ( &des_test4_36 ); + cipher_ok ( &des_test4_37 ); + cipher_ok ( &des_test4_38 ); + cipher_ok ( &des_test4_39 ); + cipher_ok ( &des_test4_40 ); + cipher_ok ( &des_test4_41 ); + cipher_ok ( &des_test4_42 ); + cipher_ok ( &des_test4_43 ); + cipher_ok ( &des_test4_44 ); + cipher_ok ( &des_test4_45 ); + cipher_ok ( &des_test4_46 ); + cipher_ok ( &des_test4_47 ); + cipher_ok ( &des_test4_48 ); + cipher_ok ( &des_test4_49 ); + cipher_ok ( &des_test4_50 ); + cipher_ok ( &des_test4_51 ); + cipher_ok ( &des_test4_52 ); + cipher_ok ( &des_test4_53 ); + cipher_ok ( &des_test4_54 ); + cipher_ok ( &des_test4_55 ); + cipher_ok ( &des_test4_56 ); + + /* Test 5: S-box tests */ + cipher_ok ( &des_test5_1 ); + cipher_ok ( &des_test5_2 ); + cipher_ok ( &des_test5_3 ); + cipher_ok ( &des_test5_4 ); + cipher_ok ( &des_test5_5 ); + cipher_ok ( &des_test5_6 ); + cipher_ok ( &des_test5_7 ); + cipher_ok ( &des_test5_8 ); + cipher_ok ( &des_test5_9 ); + cipher_ok ( &des_test5_10 ); + cipher_ok ( &des_test5_11 ); + cipher_ok ( &des_test5_12 ); + cipher_ok ( &des_test5_13 ); + cipher_ok ( &des_test5_14 ); + cipher_ok ( &des_test5_15 ); + cipher_ok ( &des_test5_16 ); + cipher_ok ( &des_test5_17 ); + cipher_ok ( &des_test5_18 ); + cipher_ok ( &des_test5_19 ); + + /* Multi-block tests */ + cipher_ok ( &des_unofficial_ecb ); + cipher_ok ( &des_unofficial_cbc ); + + /* Speed tests */ + DBG ( "DES-ECB encryption required %ld cycles per byte\n", + cipher_cost_encrypt ( &des_ecb_algorithm, 8 ) ); + DBG ( "DES-ECB decryption required %ld cycles per byte\n", + cipher_cost_decrypt ( &des_ecb_algorithm, 8 ) ); + DBG ( "DES-CBC encryption required %ld cycles per byte\n", + cipher_cost_encrypt ( &des_cbc_algorithm, 8 ) ); + DBG ( "DES-CBC decryption required %ld cycles per byte\n", + cipher_cost_decrypt ( &des_cbc_algorithm, 8 ) ); +} + +/** DES self-test */ +struct self_test des_test __self_test = { + .name = "des", + .exec = des_test_exec, +}; |