chiark / gitweb /
math/gfx-sqr.c: Use bithacking rather than a table for squaring.
[catacomb] / symm / noekeon.c
1 /* -*-c-*-
2  *
3  * The Noekeon block cipher
4  *
5  * (c) 2001 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 <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  *
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";'
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);
77   k->k[0] = LOAD32(p +  0);
78   k->k[1] = LOAD32(p +  4);
79   k->k[2] = LOAD32(p +  8);
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)
109
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 -------------------------------------------------*/