c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/*
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Implementation of DES encryption for NTLM
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Copyright 1997-2005 Simon Tatham.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * This software is released under the MIT license.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
da5e38870126e6fefdc8777c751affe77a042c01Timo Sirainen#include "lib.h"
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#include "ntlm-des.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/*
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Description of DES
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * ------------------
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Unlike the description in FIPS 46, I'm going to use _sensible_ indices:
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits in an n-bit word are numbered from 0 at the LSB to n-1 at the MSB.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * And S-boxes are indexed by six consecutive bits, not by the outer two
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * followed by the middle four.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The DES encryption routine requires a 64-bit input, and a key schedule K
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * containing 16 48-bit elements.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * First the input is permuted by the initial permutation IP.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Then the input is split into 32-bit words L and R. (L is the MSW.)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Next, 16 rounds. In each round:
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * (L, R) <- (R, L xor f(R, K[i]))
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Then the pre-output words L and R are swapped.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Then L and R are glued back together into a 64-bit word. (L is the MSW,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * again, but since we just swapped them, the MSW is the R that came out
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * of the last round.)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The 64-bit output block is permuted by the inverse of IP and returned.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Decryption is identical except that the elements of K are used in the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * opposite order. (This wouldn't work if that word swap didn't happen.)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The function f, used in each round, accepts a 32-bit word R and a
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 48-bit key block K. It produces a 32-bit output.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * First R is expanded to 48 bits using the bit-selection function E.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The resulting 48-bit block is XORed with the key block K to produce
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * a 48-bit block X.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * This block X is split into eight groups of 6 bits. Each group of 6
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits is then looked up in one of the eight S-boxes to convert
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * it to 4 bits. These eight groups of 4 bits are glued back
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * together to produce a 32-bit preoutput block.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The preoutput block is permuted using the permutation P and returned.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Key setup maps a 64-bit key word into a 16x48-bit key schedule. Although
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the approved input format for the key is a 64-bit word, eight of the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits are discarded, so the actual quantity of key used is 56 bits.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * First the input key is converted to two 28-bit words C and D using
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the bit-selection function PC1.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Then 16 rounds of key setup occur. In each round, C and D are each
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * rotated left by either 1 or 2 bits (depending on which round), and
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * then converted into a key schedule element using the bit-selection
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * function PC2.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * That's the actual algorithm. Now for the tedious details: all those
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * painful permutations and lookup tables.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * IP is a 64-to-64 bit permutation. Its output contains the following
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits of its input (listed in order MSB to LSB of output).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 6 14 22 30 38 46 54 62 4 12 20 28 36 44 52 60
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 2 10 18 26 34 42 50 58 0 8 16 24 32 40 48 56
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 7 15 23 31 39 47 55 63 5 13 21 29 37 45 53 61
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 3 11 19 27 35 43 51 59 1 9 17 25 33 41 49 57
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * E is a 32-to-48 bit selection function. Its output contains the following
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits of its input (listed in order MSB to LSB of output).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 0 31 30 29 28 27 28 27 26 25 24 23 24 23 22 21 20 19 20 19 18 17 16 15
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 16 15 14 13 12 11 12 11 10 9 8 7 8 7 6 5 4 3 4 3 2 1 0 31
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The S-boxes are arbitrary table-lookups each mapping a 6-bit input to a
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 4-bit output. In other words, each S-box is an array[64] of 4-bit numbers.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The S-boxes are listed below. The first S-box listed is applied to the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * most significant six bits of the block X; the last one is applied to the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * least significant.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 14 0 4 15 13 7 1 4 2 14 15 2 11 13 8 1
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 3 10 10 6 6 12 12 11 5 9 9 5 0 3 7 8
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 4 15 1 12 14 8 8 2 13 4 6 9 2 1 11 7
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 15 5 12 11 9 3 7 14 3 10 10 0 5 6 0 13
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 15 3 1 13 8 4 14 7 6 15 11 2 3 8 4 14
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 9 12 7 0 2 1 13 10 12 6 0 9 5 11 10 5
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 0 13 14 8 7 10 11 1 10 3 4 15 13 4 1 2
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 5 11 8 6 12 7 6 12 9 0 3 5 2 14 15 9
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 10 13 0 7 9 0 14 9 6 3 3 4 15 6 5 10
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 1 2 13 8 12 5 7 14 11 12 4 11 2 15 8 1
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 13 1 6 10 4 13 9 0 8 6 15 9 3 8 0 7
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 11 4 1 15 2 14 12 3 5 11 10 5 14 2 7 12
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 7 13 13 8 14 11 3 5 0 6 6 15 9 0 10 3
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 1 4 2 7 8 2 5 12 11 1 12 10 4 14 15 9
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 10 3 6 15 9 0 0 6 12 10 11 1 7 13 13 8
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 15 9 1 4 3 5 14 11 5 12 2 7 8 2 4 14
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 2 14 12 11 4 2 1 12 7 4 10 7 11 13 6 1
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 8 5 5 0 3 15 15 10 13 3 0 9 14 8 9 6
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 4 11 2 8 1 12 11 7 10 1 13 14 7 2 8 13
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 15 6 9 15 12 0 5 9 6 10 3 4 0 5 14 3
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 12 10 1 15 10 4 15 2 9 7 2 12 6 9 8 5
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 0 6 13 1 3 13 4 14 14 0 7 11 5 3 11 8
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 9 4 14 3 15 2 5 12 2 9 8 5 12 15 3 10
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 7 11 0 14 4 1 10 7 1 6 13 0 11 8 6 13
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 4 13 11 0 2 11 14 7 15 4 0 9 8 1 13 10
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 3 14 12 3 9 5 7 12 5 2 10 15 6 8 1 6
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 1 6 4 11 11 13 13 8 12 1 3 4 7 10 14 7
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 10 9 15 5 6 0 8 15 0 14 5 2 9 3 2 12
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 13 1 2 15 8 13 4 8 6 10 15 3 11 7 1 4
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 10 12 9 5 3 6 14 11 5 0 0 14 12 9 7 2
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 7 2 11 1 4 14 1 7 9 4 12 10 14 8 2 13
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 0 15 6 12 10 9 13 0 15 3 3 5 5 6 8 11
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * P is a 32-to-32 bit permutation. Its output contains the following
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits of its input (listed in order MSB to LSB of output).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 16 25 12 11 3 20 4 15 31 17 9 6 27 14 1 22
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 30 24 8 18 0 5 29 23 13 19 2 26 10 21 28 7
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * PC1 is a 64-to-56 bit selection function. Its output is in two words,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * C and D. The word C contains the following bits of its input (listed
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * in order MSB to LSB of output).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 7 15 23 31 39 47 55 63 6 14 22 30 38 46
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 54 62 5 13 21 29 37 45 53 61 4 12 20 28
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * And the word D contains these bits.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 1 9 17 25 33 41 49 57 2 10 18 26 34 42
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 50 58 3 11 19 27 35 43 51 59 36 44 52 60
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * PC2 is a 56-to-48 bit selection function. Its input is in two words,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * C and D. These are treated as one 56-bit word (with C more significant,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * so that bits 55 to 28 of the word are bits 27 to 0 of C, and bits 27 to
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 0 of the word are bits 27 to 0 of D). The output contains the following
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits of this 56-bit input word (listed in order MSB to LSB of output).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 42 39 45 32 55 51 53 28 41 50 35 46 33 37 44 52 30 48 40 49 29 36 43 54
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 15 4 25 19 9 1 26 16 5 11 23 8 12 7 17 0 22 3 10 14 6 20 27 24
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/*
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Implementation details
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * ----------------------
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * If you look at the code in this module, you'll find it looks
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * nothing _like_ the above algorithm. Here I explain the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * differences...
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Key setup has not been heavily optimised here. We are not
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * concerned with key agility: we aren't codebreakers. We don't
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * mind a little delay (and it really is a little one; it may be a
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * factor of five or so slower than it could be but it's still not
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * an appreciable length of time) while setting up. The only tweaks
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * in the key setup are ones which change the format of the key
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * schedule to speed up the actual encryption. I'll describe those
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * below.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi * The first and most obvious optimization is the S-boxes. Since
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * each S-box always targets the same four bits in the final 32-bit
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * word, so the output from (for example) S-box 0 must always be
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * shifted left 28 bits, we can store the already-shifted outputs
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * in the lookup tables. This reduces lookup-and-shift to lookup,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * so the S-box step is now just a question of ORing together eight
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * table lookups.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The permutation P is just a bit order change; it's invariant
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * with respect to OR, in that P(x)|P(y) = P(x|y). Therefore, we
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * can apply P to every entry of the S-box tables and then we don't
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * have to do it in the code of f(). This yields a set of tables
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * which might be called SP-boxes.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The bit-selection function E is our next target. Note that E is
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * immediately followed by the operation of splitting into 6-bit
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * chunks. Examining the 6-bit chunks coming out of E we notice
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * they're all contiguous within the word (speaking cyclically -
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the end two wrap round); so we can extract those bit strings
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * individually rather than explicitly running E. This would yield
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * code such as
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * y |= SPboxes[0][ (rotl(R, 5) ^ top6bitsofK) & 0x3F ];
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * t |= SPboxes[1][ (rotl(R,11) ^ next6bitsofK) & 0x3F ];
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * and so on; and the key schedule preparation would have to
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * provide each 6-bit chunk separately.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Really we'd like to XOR in the key schedule element before
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * looking up bit strings in R. This we can't do, naively, because
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the 6-bit strings we want overlap. But look at the strings:
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 3322222222221111111111
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bit 10987654321098765432109876543210
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box0 XXXXX X
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box1 XXXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box2 XXXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box3 XXXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box4 XXXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box5 XXXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box6 XXXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * box7 X XXXXX
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The bit strings we need to XOR in for boxes 0, 2, 4 and 6 don't
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * overlap with each other. Neither do the ones for boxes 1, 3, 5
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * and 7. So we could provide the key schedule in the form of two
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * words that we can separately XOR into R, and then every S-box
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * index is available as a (cyclically) contiguous 6-bit substring
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * of one or the other of the results.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The comments in Eric Young's libdes implementation point out
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * that two of these bit strings require a rotation (rather than a
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * simple shift) to extract. It's unavoidable that at least _one_
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * must do; but we can actually run the whole inner algorithm (all
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 16 rounds) rotated one bit to the left, so that what the `real'
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * DES description sees as L=0x80000001 we see as L=0x00000003.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * This requires rotating all our SP-box entries one bit to the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * left, and rotating each word of the key schedule elements one to
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the left, and rotating L and R one bit left just after IP and
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * one bit right again just before FP. And in each round we convert
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * a rotate into a shift, so we've saved a few per cent.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * That's about it for the inner loop; the SP-box tables as listed
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * below are what I've described here (the original S value,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * shifted to its final place in the input to P, run through P, and
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * then rotated one bit left). All that remains is to optimise the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * initial permutation IP.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * IP is not an arbitrary permutation. It has the nice property
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * that if you take any bit number, write it in binary (6 bits),
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * permute those 6 bits and invert some of them, you get the final
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * position of that bit. Specifically, the bit whose initial
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * position is given (in binary) as fedcba ends up in position
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * AcbFED (where a capital letter denotes the inverse of a bit).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * We have the 64-bit data in two 32-bit words L and R, where bits
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * in L are those with f=1 and bits in R are those with f=0. We
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * note that we can do a simple transformation: suppose we exchange
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the bits with f=1,c=0 and the bits with f=0,c=1. This will cause
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the bit fedcba to be in position cedfba - we've `swapped' bits c
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * and f in the position of each bit!
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Better still, this transformation is easy. In the example above,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bits in L with c=0 are bits 0x0F0F0F0F, and those in R with c=1
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * are 0xF0F0F0F0. So we can do
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * difference = ((R >> 4) ^ L) & 0x0F0F0F0F
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * R ^= (difference << 4)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * L ^= difference
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * to perform the swap. Let's denote this by bitswap(4,0x0F0F0F0F).
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Also, we can invert the bit at the top just by exchanging L and
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * R. So in a few swaps and a few of these bit operations we can
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * do:
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Initially the position of bit fedcba is fedcba
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Swap L with R to make it Fedcba
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Perform bitswap( 4,0x0F0F0F0F) to make it cedFba
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Perform bitswap(16,0x0000FFFF) to make it ecdFba
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Swap L with R to make it EcdFba
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Perform bitswap( 2,0x33333333) to make it bcdFEa
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Perform bitswap( 8,0x00FF00FF) to make it dcbFEa
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Swap L with R to make it DcbFEa
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Perform bitswap( 1,0x55555555) to make it acbFED
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * Swap L with R to make it AcbFED
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * (In the actual code the four swaps are implicit: R and L are
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * simply used the other way round in the first, second and last
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bitswap operations.)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen *
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The final permutation is just the inverse of IP, so it can be
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * performed by a similar set of operations.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainenstruct des_context {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen uint32_t k0246[16], k1357[16];
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen};
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define rotl(x, c) ( (x << c) | (x >> (32-c)) )
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define rotl28(x, c) ( ( (x << c) | (x >> (28-c)) ) & 0x0FFFFFFF)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainenstatic uint32_t bitsel(uint32_t * input, const int *bitnums, int size)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen{
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen uint32_t ret = 0;
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen while (size-- > 0) {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen int bitpos = *bitnums++;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen ret <<= 1;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen if (bitpos >= 0)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen ret |= 1 & (input[bitpos / 32] >> (bitpos % 32));
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen }
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen return ret;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainenstatic inline void des_key_setup(uint32_t key_msw, uint32_t key_lsw,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen struct des_context *sched)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen /* Tables are modified to work with 56-bit key */
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen static const int PC1_Cbits[] = {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 6, 13, 20, 27, 34, 41, 48, 55, 5, 12, 19, 26, 33, 40,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 47, 54, 4, 11, 18, 25, 32, 39, 46, 53, 3, 10, 17, 24
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen };
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen static const int PC1_Dbits[] = {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0, 7, 14, 21, 28, 35, 42, 49, 1, 8, 15, 22, 29, 36,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 43, 50, 2, 9, 16, 23, 30, 37, 44, 51, 31, 38, 45, 52
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen };
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen /*
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * The bit numbers in the two lists below don't correspond to
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * the ones in the above description of PC2, because in the
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * above description C and D are concatenated so `bit 28' means
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * bit 0 of C. In this implementation we're using the standard
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * `bitsel' function above and C is in the second word, so bit
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen * 0 of C is addressed by writing `32' here.
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen */
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen static const int PC2_0246[] = {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 49, 36, 59, 55, -1, -1, 37, 41, 48, 56, 34, 52, -1, -1, 15, 4,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 25, 19, 9, 1, -1, -1, 12, 7, 17, 0, 22, 3, -1, -1, 46, 43
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen };
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen static const int PC2_1357[] = {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen -1, -1, 57, 32, 45, 54, 39, 50, -1, -1, 44, 53, 33, 40, 47, 58,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen -1, -1, 26, 16, 5, 11, 23, 8, -1, -1, 10, 14, 6, 20, 27, 24
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen };
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen static const int leftshifts[] = {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen };
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen uint32_t C, D;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen uint32_t buf[2];
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen int i;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen buf[0] = key_lsw;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen buf[1] = key_msw;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen C = bitsel(buf, PC1_Cbits, 28);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen D = bitsel(buf, PC1_Dbits, 28);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen for (i = 0; i < 16; i++) {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen C = rotl28(C, leftshifts[i]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen D = rotl28(D, leftshifts[i]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen buf[0] = D;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen buf[1] = C;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen sched->k0246[i] = bitsel(buf, PC2_0246, 32);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen sched->k1357[i] = bitsel(buf, PC2_1357, 32);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen }
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainenstatic const uint32_t SPboxes[8][64] = {
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x01010400, 0x00000000, 0x00010000, 0x01010404,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x01010004, 0x00010404, 0x00000004, 0x00010000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000400, 0x01010400, 0x01010404, 0x00000400,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x01000404, 0x01010004, 0x01000000, 0x00000004,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000404, 0x01000400, 0x01000400, 0x00010400,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00010400, 0x01010000, 0x01010000, 0x01000404,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00010004, 0x01000004, 0x01000004, 0x00010004,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x00000404, 0x00010404, 0x01000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00010000, 0x01010404, 0x00000004, 0x01010000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x01010400, 0x01000000, 0x01000000, 0x00000400,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x01010004, 0x00010000, 0x00010400, 0x01000004,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000400, 0x00000004, 0x01000404, 0x00010404,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x01010404, 0x00010004, 0x01010000, 0x01000404,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x01000004, 0x00000404, 0x00010404, 0x01010400,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000404, 0x01000400, 0x01000400, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00010004, 0x00010400, 0x00000000, 0x01010004},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x80108020, 0x80008000, 0x00008000, 0x00108020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00100000, 0x00000020, 0x80100020, 0x80008020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x80000020, 0x80108020, 0x80108000, 0x80000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x80008000, 0x00100000, 0x00000020, 0x80100020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00108000, 0x00100020, 0x80008020, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x80000000, 0x00008000, 0x00108020, 0x80100000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00100020, 0x80000020, 0x00000000, 0x00108000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00008020, 0x80108000, 0x80100000, 0x00008020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x00108020, 0x80100020, 0x00100000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x80008020, 0x80100000, 0x80108000, 0x00008000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x80100000, 0x80008000, 0x00000020, 0x80108020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00108020, 0x00000020, 0x00008000, 0x80000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00008020, 0x80108000, 0x00100000, 0x80000020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00100020, 0x80008020, 0x80000020, 0x00100020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00108000, 0x00000000, 0x80008000, 0x00008020,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x80000000, 0x80100020, 0x80108020, 0x00108000},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x00000208, 0x08020200, 0x00000000, 0x08020008,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08000200, 0x00000000, 0x00020208, 0x08000200,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00020008, 0x08000008, 0x08000008, 0x00020000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08020208, 0x00020008, 0x08020000, 0x00000208,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08000000, 0x00000008, 0x08020200, 0x00000200,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00020200, 0x08020000, 0x08020008, 0x00020208,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08000208, 0x00020200, 0x00020000, 0x08000208,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000008, 0x08020208, 0x00000200, 0x08000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08020200, 0x08000000, 0x00020008, 0x00000208,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00020000, 0x08020200, 0x08000200, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000200, 0x00020008, 0x08020208, 0x08000200,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08000008, 0x00000200, 0x00000000, 0x08020008,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08000208, 0x00020000, 0x08000000, 0x08020208,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000008, 0x00020208, 0x00020200, 0x08000008,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x08020000, 0x08000208, 0x00000208, 0x08020000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00020208, 0x00000008, 0x08020008, 0x00020200},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x00802001, 0x00002081, 0x00002081, 0x00000080,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00802080, 0x00800081, 0x00800001, 0x00002001,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x00802000, 0x00802000, 0x00802081,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000081, 0x00000000, 0x00800080, 0x00800001,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000001, 0x00002000, 0x00800000, 0x00802001,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000080, 0x00800000, 0x00002001, 0x00002080,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00800081, 0x00000001, 0x00002080, 0x00800080,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00002000, 0x00802080, 0x00802081, 0x00000081,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00800080, 0x00800001, 0x00802000, 0x00802081,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000081, 0x00000000, 0x00000000, 0x00802000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00002080, 0x00800080, 0x00800081, 0x00000001,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00802001, 0x00002081, 0x00002081, 0x00000080,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00802081, 0x00000081, 0x00000001, 0x00002000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00800001, 0x00002001, 0x00802080, 0x00800081,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00002001, 0x00002080, 0x00800000, 0x00802001,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000080, 0x00800000, 0x00002000, 0x00802080},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x00000100, 0x02080100, 0x02080000, 0x42000100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00080000, 0x00000100, 0x40000000, 0x02080000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x40080100, 0x00080000, 0x02000100, 0x40080100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x42000100, 0x42080000, 0x00080100, 0x40000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x02000000, 0x40080000, 0x40080000, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x40000100, 0x42080100, 0x42080100, 0x02000100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x42080000, 0x40000100, 0x00000000, 0x42000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x02080100, 0x02000000, 0x42000000, 0x00080100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00080000, 0x42000100, 0x00000100, 0x02000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x40000000, 0x02080000, 0x42000100, 0x40080100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x02000100, 0x40000000, 0x42080000, 0x02080100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x40080100, 0x00000100, 0x02000000, 0x42080000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x42080100, 0x00080100, 0x42000000, 0x42080100,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x02080000, 0x00000000, 0x40080000, 0x42000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00080100, 0x02000100, 0x40000100, 0x00080000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x40080000, 0x02080100, 0x40000100},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x20000010, 0x20400000, 0x00004000, 0x20404010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20400000, 0x00000010, 0x20404010, 0x00400000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20004000, 0x00404010, 0x00400000, 0x20000010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00400010, 0x20004000, 0x20000000, 0x00004010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x00400010, 0x20004010, 0x00004000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00404000, 0x20004010, 0x00000010, 0x20400010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20400010, 0x00000000, 0x00404010, 0x20404000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00004010, 0x00404000, 0x20404000, 0x20000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20004000, 0x00000010, 0x20400010, 0x00404000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20404010, 0x00400000, 0x00004010, 0x20000010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00400000, 0x20004000, 0x20000000, 0x00004010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20000010, 0x20404010, 0x00404000, 0x20400000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00404010, 0x20404000, 0x00000000, 0x20400010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000010, 0x00004000, 0x20400000, 0x00404010,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00004000, 0x00400010, 0x20004010, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x20404000, 0x20000000, 0x00400010, 0x20004010},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x00200000, 0x04200002, 0x04000802, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000800, 0x04000802, 0x00200802, 0x04200800,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04200802, 0x00200000, 0x00000000, 0x04000002,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000002, 0x04000000, 0x04200002, 0x00000802,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04000800, 0x00200802, 0x00200002, 0x04000800,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04000002, 0x04200000, 0x04200800, 0x00200002,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04200000, 0x00000800, 0x00000802, 0x04200802,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00200800, 0x00000002, 0x04000000, 0x00200800,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04000000, 0x00200800, 0x00200000, 0x04000802,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04000802, 0x04200002, 0x04200002, 0x00000002,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00200002, 0x04000000, 0x04000800, 0x00200000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04200800, 0x00000802, 0x00200802, 0x04200800,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000802, 0x04000002, 0x04200802, 0x04200000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00200800, 0x00000000, 0x00000002, 0x04200802,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x00200802, 0x04200000, 0x00000800,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x04000002, 0x04000800, 0x00000800, 0x00200002},
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen {0x10001040, 0x00001000, 0x00040000, 0x10041040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10000000, 0x10001040, 0x00000040, 0x10000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00040040, 0x10040000, 0x10041040, 0x00041000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10041000, 0x00041040, 0x00001000, 0x00000040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10040000, 0x10000040, 0x10001000, 0x00001040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00041000, 0x00040040, 0x10040040, 0x10041000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00001040, 0x00000000, 0x00000000, 0x10040040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10000040, 0x10001000, 0x00041040, 0x00040000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00041040, 0x00040000, 0x10041000, 0x00001000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000040, 0x10040040, 0x00001000, 0x00041040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10001000, 0x00000040, 0x10000040, 0x10040000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10040040, 0x10000000, 0x00040000, 0x10001040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00000000, 0x10041040, 0x00040040, 0x10000040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10040000, 0x10001000, 0x10001040, 0x00000000,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x10041040, 0x00041000, 0x00041000, 0x00001040,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen 0x00001040, 0x00040040, 0x10000000, 0x10041000}
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen};
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define f(R, K0246, K1357) (\
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen s0246 = R ^ K0246, \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen s1357 = R ^ K1357, \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen s0246 = rotl(s0246, 28), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[0] [(s0246 >> 24) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[1] [(s1357 >> 24) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[2] [(s0246 >> 16) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[3] [(s1357 >> 16) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[4] [(s0246 >> 8) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[5] [(s1357 >> 8) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[6] [(s0246 ) & 0x3F] | \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen SPboxes[7] [(s1357 ) & 0x3F])
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define bitswap(L, R, n, mask) (\
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen swap = mask & ( (R >> n) ^ L ), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= swap << n, \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= swap)
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen/* Initial permutation */
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define IP(L, R) (\
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(R, L, 4, 0x0F0F0F0F), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(R, L, 16, 0x0000FFFF), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(L, R, 2, 0x33333333), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(L, R, 8, 0x00FF00FF), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(R, L, 1, 0x55555555))
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen/* Final permutation */
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define FP(L, R) (\
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(R, L, 1, 0x55555555), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(L, R, 8, 0x00FF00FF), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(L, R, 2, 0x33333333), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(R, L, 16, 0x0000FFFF), \
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen bitswap(R, L, 4, 0x0F0F0F0F))
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic void
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainendes_encipher(uint32_t *output, uint32_t L, uint32_t R,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen struct des_context *sched)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen uint32_t swap, s0246, s1357;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen IP(L, R);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L = rotl(L, 1);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R = rotl(R, 1);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[0], sched->k1357[0]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[1], sched->k1357[1]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[2], sched->k1357[2]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[3], sched->k1357[3]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[4], sched->k1357[4]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[5], sched->k1357[5]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[6], sched->k1357[6]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[7], sched->k1357[7]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[8], sched->k1357[8]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[9], sched->k1357[9]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[10], sched->k1357[10]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[11], sched->k1357[11]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[12], sched->k1357[12]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[13], sched->k1357[13]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L ^= f(R, sched->k0246[14], sched->k1357[14]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R ^= f(L, sched->k0246[15], sched->k1357[15]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L = rotl(L, 31);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R = rotl(R, 31);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen swap = L;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L = R;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R = swap;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen FP(L, R);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen output[0] = L;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen output[1] = R;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen#define GET_32BIT_MSB_FIRST(cp) \
b9e830a81455faf3c0dadfc9dbf0c7dc8aca955cJosef 'Jeff' Sipek ((unsigned long) be32_to_cpu_unaligned(cp))
b9e830a81455faf3c0dadfc9dbf0c7dc8aca955cJosef 'Jeff' Sipek
b9e830a81455faf3c0dadfc9dbf0c7dc8aca955cJosef 'Jeff' Sipek#define PUT_32BIT_MSB_FIRST(cp, value) \
b9e830a81455faf3c0dadfc9dbf0c7dc8aca955cJosef 'Jeff' Sipek cpu32_to_be_unaligned((value), (cp))
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainenstatic inline void
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainendes_cbc_encrypt(unsigned char *dest, const unsigned char *src,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen struct des_context *sched)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen uint32_t out[2], L, R;
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen L = GET_32BIT_MSB_FIRST(src);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen R = GET_32BIT_MSB_FIRST(src + 4);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen des_encipher(out, L, R, sched);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen PUT_32BIT_MSB_FIRST(dest, out[0]);
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen PUT_32BIT_MSB_FIRST(dest + 4, out[1]);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainenvoid deshash(unsigned char *dst, const unsigned char *key,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen const unsigned char *src)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen struct des_context ctx;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen des_key_setup(GET_32BIT_MSB_FIRST(key) >> 8,
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen GET_32BIT_MSB_FIRST(key + 3), &ctx);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
a20c287027db23b665bd57f99844c39af81febc3Timo Sirainen des_cbc_encrypt(dst, src, &ctx);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}