Commit | Line | Data |
---|---|---|
0ba18b90 | 1 | /* -*-c-*- |
0ba18b90 | 2 | * |
3 | * The Noekeon block cipher | |
4 | * | |
5 | * (c) 2001 Straylight/Edgeware | |
6 | */ | |
7 | ||
45c0fd36 | 8 | /*----- Licensing notice --------------------------------------------------* |
0ba18b90 | 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. | |
45c0fd36 | 16 | * |
0ba18b90 | 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. | |
45c0fd36 | 21 | * |
0ba18b90 | 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 | */ | |
0ba18b90 | 27 | |
28 | /*----- Header files ------------------------------------------------------*/ | |
29 | ||
30 | #include <assert.h> | |
31 | #include <stdio.h> | |
32 | ||
33 | #include <mLib/bits.h> | |
34 | ||
35 | #include "blkc.h" | |
36 | #include "gcipher.h" | |
37 | #include "noekeon.h" | |
38 | ||
39 | /*----- Global variables --------------------------------------------------*/ | |
40 | ||
41 | const octet noekeon_keysz[] = { KSZ_SET, NOEKEON_KEYSZ, 0 }; | |
42 | ||
43 | /*----- Magic constants ---------------------------------------------------*/ | |
44 | ||
45 | /* --- To generate the magic --- * | |
46 | * | |
eaa515d8 | 47 | * perl -e'@@r=();$x=0x80;for(0..16){push(@@r,$x);$x<<=1;$x^=0x11b |
48 | * if$x&0x100;};print join(", ",map{sprintf"0x%02x",$_}@@r),"\n";' | |
0ba18b90 | 49 | */ |
50 | ||
51 | static const octet rcon[17] = { | |
52 | 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, | |
53 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, | |
54 | 0xd4 | |
55 | }; | |
56 | ||
57 | /*----- Main code ---------------------------------------------------------*/ | |
58 | ||
59 | /* --- @noekeon_init@--- * | |
60 | * | |
61 | * Arguments: @noekeon_ctx *k@ = pointer to key block to fill in | |
62 | * @const void *buf@ = pointer to buffer of key material | |
63 | * @size_t sz@ = size of key material | |
64 | * | |
65 | * Returns: --- | |
66 | * | |
67 | * Use: Initializes a Noekeon key buffer. Noekeon accepts a 128-bit | |
68 | * key. | |
69 | */ | |
70 | ||
71 | void noekeon_init(noekeon_ctx *k, const void *buf, size_t sz) | |
72 | { | |
73 | const octet *p = buf; | |
74 | static const noekeon_ctx nullkey = { { 0, 0, 0, 0 } }; | |
75 | ||
76 | KSZ_ASSERT(noekeon, sz); | |
45c0fd36 MW |
77 | k->k[0] = LOAD32(p + 0); |
78 | k->k[1] = LOAD32(p + 4); | |
79 | k->k[2] = LOAD32(p + 8); | |
0ba18b90 | 80 | k->k[3] = LOAD32(p + 12); |
81 | noekeon_eblk(&nullkey, k->k, k->k); | |
82 | } | |
83 | ||
84 | /* --- @noekeon_eblk@, @noekeon_dblk@ --- * | |
85 | * | |
86 | * Arguments: @const noekeon_ctx *k@ = pointer to key block | |
87 | * @const uint32 s[2]@ = pointer to source block | |
88 | * @uint32 d[2]@ = pointer to destination block | |
89 | * | |
90 | * Returns: --- | |
91 | * | |
92 | * Use: Low-level block encryption and decryption. | |
93 | */ | |
94 | ||
95 | #define GAMMA(a, b, c, d) do { \ | |
96 | uint32 _x; \ | |
97 | b ^= ~(c | d); a ^= b & c; \ | |
98 | _x = d; d = a; a = _x; \ | |
99 | c ^= a ^ b ^ d; \ | |
100 | b ^= ~(c | d); a ^= b & c; \ | |
101 | } while (0) | |
102 | ||
103 | #define THETA(ka, kb, kc, kd, a, b, c, d) do { \ | |
104 | uint32 _x; \ | |
105 | _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x; \ | |
106 | a ^= ka; b ^= kb; c ^= kc; d ^= kd; \ | |
107 | _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x; \ | |
108 | } while (0) | |
45c0fd36 | 109 | |
0ba18b90 | 110 | #define ITHETA(ka, kb, kc, kd, a, b, c, d) do { \ |
111 | uint32 _x; \ | |
112 | _x = b ^ d; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); a ^= _x; c ^= _x; \ | |
113 | a ^= ka; b ^= kb; c ^= kc; d ^= kd; \ | |
114 | _x = a ^ c; _x ^= ROR32(_x, 8) ^ ROL32(_x, 8); b ^= _x; d ^= _x; \ | |
115 | } while (0) | |
116 | ||
117 | #define PI1(a, b, c, d) do { \ | |
118 | b = ROL32(b, 1); c = ROL32(c, 5); d = ROL32(d, 2); \ | |
119 | } while (0) | |
120 | ||
121 | #define PI2(a, b, c, d) do { \ | |
122 | b = ROR32(b, 1); c = ROR32(c, 5); d = ROR32(d, 2); \ | |
123 | } while (0) | |
124 | ||
125 | #define ROUND(r, ka, kb, kc, kd, a, b, c, d) do { \ | |
126 | a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d); \ | |
127 | PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d); \ | |
128 | } while (0) | |
129 | ||
130 | #define IROUND(r, ka, kb, kc, kd, a, b, c, d) do { \ | |
131 | ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r; \ | |
132 | PI1(a, b, c, d); GAMMA(a, b, c, d); PI2(a, b, c, d); \ | |
133 | } while (0) | |
134 | ||
135 | void noekeon_eblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst) | |
136 | { | |
137 | uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3]; | |
138 | uint32 a = src[0], b = src[1], c = src[2], d = src[3]; | |
139 | const octet *r = rcon; | |
140 | ||
141 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
142 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
143 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
144 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
145 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
146 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
147 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
148 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
149 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
150 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
151 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
152 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
153 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
154 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
155 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
156 | ROUND(r, ka, kb, kc, kd, a, b, c, d); | |
157 | ||
158 | a ^= *r++; THETA(ka, kb, kc, kd, a, b, c, d); | |
159 | ||
160 | dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; | |
161 | } | |
162 | ||
163 | void noekeon_dblk(const noekeon_ctx *k, const uint32 *src, uint32 *dst) | |
164 | { | |
165 | uint32 ka = k->k[0], kb = k->k[1], kc = k->k[2], kd = k->k[3]; | |
166 | uint32 a = src[0], b = src[1], c = src[2], d = src[3]; | |
167 | const octet *r = rcon + sizeof(rcon); | |
168 | ||
169 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
170 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
171 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
172 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
173 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
174 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
175 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
176 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
177 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
178 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
179 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
180 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
181 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
182 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
183 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
184 | IROUND(r, ka, kb, kc, kd, a, b, c, d); | |
185 | ||
186 | ITHETA(ka, kb, kc, kd, a, b, c, d); a ^= *--r; | |
187 | ||
188 | dst[0] = a; dst[1] = b; dst[2] = c; dst[3] = d; | |
189 | } | |
190 | ||
191 | BLKC_TEST(NOEKEON, noekeon) | |
192 | ||
193 | /*----- That's all, folks -------------------------------------------------*/ |