chiark / gitweb /
math/gfx-sqr.c: Use bithacking rather than a table for squaring.
[catacomb] / symm / skipjack.c
1 /* -*-c-*-
2  *
3  * The Skipjack block cipher
4  *
5  * (c) 2000 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <mLib/bits.h>
31
32 #include "blkc.h"
33 #include "gcipher.h"
34 #include "skipjack.h"
35
36 /*----- Global variables --------------------------------------------------*/
37
38 const octet skipjack_keysz[] = { KSZ_SET, 10, 0 };
39
40 /*----- The Skipjack S-box ------------------------------------------------*/
41
42 extern const octet skipjack_s[256];
43
44 /*----- Main code ---------------------------------------------------------*/
45
46 /* --- @skipjack_init@ --- *
47  *
48  * Arguments:   @skipjack_ctx *k@ = pointer to key block
49  *              @const void *buf@ = pointer to key buffer
50  *              @size_t sz@ = size of key material
51  *
52  * Returns:     ---
53  *
54  * Use:         Initializes a Skipjack key buffer.  The key buffer must be
55  *              exactly 10 bytes long.
56  */
57
58 void skipjack_init(skipjack_ctx *k, const void *buf, size_t sz)
59 {
60   const octet *b = buf;
61   uint32 crud;
62   KSZ_ASSERT(skipjack, sz);
63   k->ka = LOAD32(b);
64   k->kb = LOAD32(b + 4);
65   crud = LOAD16(b + 8);
66   k->kc = U32((crud << 16) | (k->ka >> 16));
67   k->kd = U32((k->ka << 16) | (k->kb >> 16));
68   k->ke = U32((k->kb << 16) | crud);
69   crud = 0;
70 }
71
72 /* --- @skipjack_eblk@, @skipjack_dblk@ --- *
73  *
74  * Arguments:   @const skipjack_ctx *k@ = pointer to key block
75  *              @const uint32 s[2]@ = pointer to source block
76  *              @uint32 d[2]@ = pointer to skipjacktination block
77  *
78  * Returns:     ---
79  *
80  * Use:         Low-level block encryption and decryption.
81  */
82
83 #define G(x, k) do {                                                    \
84   octet _x = U8(x >> 8), _y = U8(x);                                    \
85   _x ^= skipjack_s[_y ^ U8(k >> 24)];                                   \
86   _y ^= skipjack_s[_x ^ U8(k >> 16)];                                   \
87   _x ^= skipjack_s[_y ^ U8(k >>  8)];                                   \
88   _y ^= skipjack_s[_x ^ U8(k >>  0)];                                   \
89   x = (_x << 8) | _y;                                                   \
90 } while (0)
91
92 #define RULE_A(w, x, y, z, n, k) do {                                   \
93   G(w, k); z ^= w ^ n++;                                                \
94 } while (0)
95
96 #define RULE_B(w, x, y, z, n, k) do {                                   \
97   x ^= w ^ n++; G(w, k);                                                \
98 } while (0)
99
100 void skipjack_eblk(const skipjack_ctx *k, const uint32 *s, uint32 *d)
101 {
102   unsigned n = 1;
103   uint16 w = U16(s[0] >> 16), x = U16(s[0]);
104   uint16 y = U16(s[1] >> 16), z = U16(s[1]);
105   uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke;
106
107   RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb);
108   RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd);
109   RULE_A(w, x, y, z, n, ke); RULE_A(z, w, x, y, n, ka);
110   RULE_A(y, z, w, x, n, kb); RULE_A(x, y, z, w, n, kc);
111   RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke);
112   RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb);
113   RULE_B(w, x, y, z, n, kc); RULE_B(z, w, x, y, n, kd);
114   RULE_B(y, z, w, x, n, ke); RULE_B(x, y, z, w, n, ka);
115   RULE_A(w, x, y, z, n, kb); RULE_A(z, w, x, y, n, kc);
116   RULE_A(y, z, w, x, n, kd); RULE_A(x, y, z, w, n, ke);
117   RULE_A(w, x, y, z, n, ka); RULE_A(z, w, x, y, n, kb);
118   RULE_A(y, z, w, x, n, kc); RULE_A(x, y, z, w, n, kd);
119   RULE_B(w, x, y, z, n, ke); RULE_B(z, w, x, y, n, ka);
120   RULE_B(y, z, w, x, n, kb); RULE_B(x, y, z, w, n, kc);
121   RULE_B(w, x, y, z, n, kd); RULE_B(z, w, x, y, n, ke);
122   RULE_B(y, z, w, x, n, ka); RULE_B(x, y, z, w, n, kb);
123
124   d[0] = ((uint32)w << 16) | (uint32)x;
125   d[1] = ((uint32)y << 16) | (uint32)z;
126 }
127
128 #define G_INV(x, k) do {                                                \
129   octet _x = U8(x >> 8), _y = U8(x);                                    \
130   _y ^= skipjack_s[_x ^ U8(k >>  0)];                                   \
131   _x ^= skipjack_s[_y ^ U8(k >>  8)];                                   \
132   _y ^= skipjack_s[_x ^ U8(k >> 16)];                                   \
133   _x ^= skipjack_s[_y ^ U8(k >> 24)];                                   \
134   x = (_x << 8) | _y;                                                   \
135 } while (0)
136
137 #define RULE_A_INV(w, x, y, z, n, i) do {                               \
138   w ^= x ^ --n; G_INV(x, i);                                            \
139 } while (0)
140
141 #define RULE_B_INV(w, x, y, z, n, i) do {                               \
142   G_INV(x, i); y ^= x ^ --n;                                            \
143 } while (0)
144
145 void skipjack_dblk(const skipjack_ctx *k, const uint32 *s, uint32 *d)
146 {
147   unsigned n = 33;
148   uint16 w = U16(s[0] >> 16), x = U16(s[0]);
149   uint16 y = U16(s[1] >> 16), z = U16(s[1]);
150   uint32 ka = k->ka, kb = k->kb, kc = k->kc, kd = k->kd, ke = k->ke;
151
152   RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka);
153   RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd);
154   RULE_B_INV(w, x, y, z, n, kc); RULE_B_INV(x, y, z, w, n, kb);
155   RULE_B_INV(y, z, w, x, n, ka); RULE_B_INV(z, w, x, y, n, ke);
156   RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc);
157   RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka);
158   RULE_A_INV(w, x, y, z, n, ke); RULE_A_INV(x, y, z, w, n, kd);
159   RULE_A_INV(y, z, w, x, n, kc); RULE_A_INV(z, w, x, y, n, kb);
160   RULE_B_INV(w, x, y, z, n, ka); RULE_B_INV(x, y, z, w, n, ke);
161   RULE_B_INV(y, z, w, x, n, kd); RULE_B_INV(z, w, x, y, n, kc);
162   RULE_B_INV(w, x, y, z, n, kb); RULE_B_INV(x, y, z, w, n, ka);
163   RULE_B_INV(y, z, w, x, n, ke); RULE_B_INV(z, w, x, y, n, kd);
164   RULE_A_INV(w, x, y, z, n, kc); RULE_A_INV(x, y, z, w, n, kb);
165   RULE_A_INV(y, z, w, x, n, ka); RULE_A_INV(z, w, x, y, n, ke);
166   RULE_A_INV(w, x, y, z, n, kd); RULE_A_INV(x, y, z, w, n, kc);
167   RULE_A_INV(y, z, w, x, n, kb); RULE_A_INV(z, w, x, y, n, ka);
168
169   d[0] = ((uint32)w << 16) | (uint32)x;
170   d[1] = ((uint32)y << 16) | (uint32)z;
171 }
172
173 BLKC_TEST(SKIPJACK, skipjack)
174
175 /*----- That's all, folks -------------------------------------------------*/