]>
jfr.im git - irc/quakenet/newserv.git/blob - lib/helix.c
1 /* Cleanroom reference implementation of Helix */
3 /* HEAVILY modified by Chris Porter to support contexts. */
5 /* See Ferguson et. al, Fast Software Encryption 2003, or
6 * http://www.macfergus.com/helix/helixPreproc.pdf
12 /* some useful macros -- little-endian */
13 #define B(x,i) ((UCHAR)(((x) >> (8*i)) & 0xFF))
14 #define BYTE2WORD(b) ( \
15 (((WORD)(b)[3] & 0xFF)<<24) | \
16 (((WORD)(b)[2] & 0xFF)<<16) | \
17 (((WORD)(b)[1] & 0xFF)<<8) | \
18 (((WORD)(b)[0] & 0xFF)) \
20 #define WORD2BYTE(w, b) { \
26 #define XORWORD(w, b) { \
32 #define ROTL(w,x) (((w) << (x))|((w) >> (32 - (x))))
34 /* 3.2, figure 2, block function */
36 h_block(struct helix_ctx
*ctx
, WORD X_i0
, WORD P_i
, WORD X_i1
)
40 r
= ctx
->A
; /* for returning later */
41 ctx
->A
+= ctx
->D
; ctx
->D
= ROTL(ctx
->D
, 15);
42 ctx
->B
+= ctx
->E
; ctx
->E
= ROTL(ctx
->E
, 25);
43 ctx
->C
^= ctx
->A
; ctx
->A
= ROTL(ctx
->A
, 9);
44 ctx
->D
^= ctx
->B
; ctx
->B
= ROTL(ctx
->B
, 10);
45 ctx
->E
+= ctx
->C
; ctx
->C
= ROTL(ctx
->C
, 17);
46 ctx
->A
^= ctx
->D
+ X_i0
; ctx
->D
= ROTL(ctx
->D
, 30);
47 ctx
->B
^= ctx
->E
; ctx
->E
= ROTL(ctx
->E
, 13);
48 ctx
->C
+= ctx
->A
; ctx
->A
= ROTL(ctx
->A
, 20);
49 ctx
->D
+= ctx
->B
; ctx
->B
= ROTL(ctx
->B
, 11);
50 ctx
->E
^= ctx
->C
; ctx
->C
= ROTL(ctx
->C
, 5);
51 ctx
->A
+= ctx
->D
^ P_i
; ctx
->D
= ROTL(ctx
->D
, 15);
52 ctx
->B
+= ctx
->E
; ctx
->E
= ROTL(ctx
->E
, 25);
53 ctx
->C
^= ctx
->A
; ctx
->A
= ROTL(ctx
->A
, 9);
54 ctx
->D
^= ctx
->B
; ctx
->B
= ROTL(ctx
->B
, 10);
55 ctx
->E
+= ctx
->C
; ctx
->C
= ROTL(ctx
->C
, 17);
56 ctx
->A
^= ctx
->D
+ X_i1
; ctx
->D
= ROTL(ctx
->D
, 30);
57 ctx
->B
^= ctx
->E
; ctx
->E
= ROTL(ctx
->E
, 13);
58 ctx
->C
+= ctx
->A
; ctx
->A
= ROTL(ctx
->A
, 20);
59 ctx
->D
+= ctx
->B
; ctx
->B
= ROTL(ctx
->B
, 11);
60 ctx
->E
^= ctx
->C
; ctx
->C
= ROTL(ctx
->C
, 5);
61 /* increment i in funny way */
62 if (++ctx
->h_iplus8
[0] == 0x80000000lu
) {
70 * Could do feistel in place, but this follows description in paper.
73 h_key(struct helix_ctx
*ctx
, unsigned char *U
, int U_len
)
75 WORD k
[40]; /* room for key schedule */
79 U_len
= 32; /* limit size of key */
80 memset((void *)k
, 0, sizeof k
);
81 memcpy((void *)&k
[32], U
, U_len
);
82 ctx
->h_iplus8
[0] = ctx
->h_iplus8
[1] = 0;
84 for (i
= 32; i
< 40; ++i
)
85 k
[i
] = BYTE2WORD(((unsigned char *)&k
[i
])); /* convert to words */
86 for (i
= 7; i
>= 0; --i
) {
92 (void)h_block(ctx
, 0, 0, 0);
93 k
[4*i
+0] = ctx
->A
^ k
[4*i
+8];
94 k
[4*i
+1] = ctx
->B
^ k
[4*i
+9];
95 k
[4*i
+2] = ctx
->C
^ k
[4*i
+10];
96 k
[4*i
+3] = ctx
->D
^ k
[4*i
+11];
99 for (i
= 0; i
< 8; ++i
)
101 /* remember length of key */
105 /* 3.3, nonce setup */
107 h_nonce(struct helix_ctx
*ctx
, UCHAR nonce
[16])
109 ctx
->N
[0] = BYTE2WORD(&nonce
[0]);
110 ctx
->N
[1] = BYTE2WORD(&nonce
[4]);
111 ctx
->N
[2] = BYTE2WORD(&nonce
[8]);
112 ctx
->N
[3] = BYTE2WORD(&nonce
[12]);
113 ctx
->N
[4] = 0 - ctx
->N
[0];
114 ctx
->N
[5] = 1 - ctx
->N
[1];
115 ctx
->N
[6] = 2 - ctx
->N
[2];
116 ctx
->N
[7] = 3 - ctx
->N
[3];
119 /* 3.3, X_i functions */
121 X(struct helix_ctx
*ctx
, int one
)
126 x
= ctx
->K
[(ctx
->h_iplus8
[0] + 4) & 0x07] + ctx
->N
[ctx
->h_iplus8
[0] & 0x07] + ctx
->h_iplus8
[0];
127 if ((ctx
->h_iplus8
[0] & 0x03) == 3)
128 x
+= ctx
->h_iplus8
[1];
129 else if ((ctx
->h_iplus8
[0] & 0x03) == 1)
133 x
= ctx
->K
[ctx
->h_iplus8
[0] & 0x07];
137 /* 3.4 initialisation */
139 h_init(struct helix_ctx
*ctx
)
143 ctx
->h_iplus8
[0] = ctx
->h_iplus8
[1] = 0;
144 ctx
->A
= ctx
->K
[3] ^ ctx
->N
[0];
145 ctx
->B
= ctx
->K
[4] ^ ctx
->N
[1];
146 ctx
->C
= ctx
->K
[5] ^ ctx
->N
[2];
147 ctx
->D
= ctx
->K
[6] ^ ctx
->N
[3];
149 for (i
= 0; i
< 8; ++i
)
150 (void) h_block(ctx
, X(ctx
, 0), 0, X(ctx
, 1));
153 /* 3.5 encryption, and 3.6 compute MAC */
155 h_encrypt(struct helix_ctx
*ctx
, UCHAR
*buf
, int n
, UCHAR macbuf
[16])
163 w
= h_block(ctx
, X(ctx
, 0), BYTE2WORD(buf
), X(ctx
, 1));
169 /* handle an odd bit at the end */
170 for (i
= 0; i
< n
; ++i
)
172 for (/*...*/; i
< 4; ++i
)
175 w
= h_block(ctx
, X(ctx
,0), w
, X(ctx
,1));
177 for (i
= 0; i
< n
; ++i
)
180 /* now compute MAC. Note that "n" is currently l(P) mod 4. */
181 ctx
->A
^= 0x912d94f1;
182 for (i
= 0; i
< 8; ++i
)
183 (void) h_block(ctx
, X(ctx
,0), n
, X(ctx
,1));
184 for (i
= 0; i
< 4; ++i
) {
185 w
= h_block(ctx
, X(ctx
,0), n
, X(ctx
,1));
186 WORD2BYTE(w
, &macbuf
[i
*4]);
190 /* 3.8 decryption, and 3.6 compute MAC */
192 h_decrypt(struct helix_ctx
*ctx
, UCHAR
*buf
, int n
, UCHAR macbuf
[16])
200 /* rather than muck with h_block, we use knowledge of A */
201 w
= BYTE2WORD(buf
) ^ ctx
->A
; /* plaintext */
202 w
= h_block(ctx
, X(ctx
,0), w
, X(ctx
,1));
208 /* handle an odd bit at the end */
209 for (i
= 0; i
< n
; ++i
)
212 for (/*...*/; i
< 4; ++i
)
215 (void) h_block(ctx
, X(ctx
,0), w
, X(ctx
,1)); /* note decryption already done */
216 for (i
= 0; i
< n
; ++i
)
219 /* now compute MAC. Note that "n" is currently l(P) mod 4. */
220 ctx
->A
^= 0x912d94f1;
221 for (i
= 0; i
< 8; ++i
)
222 (void) h_block(ctx
, X(ctx
,0), n
, X(ctx
,1));
223 for (i
= 0; i
< 4; ++i
) {
224 w
= h_block(ctx
, X(ctx
,0), n
, X(ctx
,1));
225 WORD2BYTE(w
, &macbuf
[i
*4]);
230 /*--------------------------------------------------------------------------*/
232 /*--------------------------------------------------------------------------*/
241 test_helix(int quick
)
244 UCHAR key
[32], nonce
[16], buf
[32], mac
[16];
245 struct helix_ctx ctx
;
248 printf("Test Vector set 1:\n");
249 hexprint("Initial Key", key
, 0);
250 memset((void *)nonce
, 0, 16);
251 hexprint("Nonce", nonce
, 16);
253 h_nonce(&ctx
, nonce
);
254 hexwprint("Working Key", ctx
.K
, 32);
255 hexwcheck(ctx
.K
, "a9 3b 6e 32 bc 23 4f 6c 32 6c 0f 82 74 ff a2 41"
256 "e3 da 57 7d ef 7c 1b 64 af 78 7c 38 dc ef e3 de", 32);
257 hexwprint("Working N", ctx
.N
, 32);
259 hexprint("Plaintext", buf
, 10);
260 h_encrypt(&ctx
, buf
, 10, mac
);
261 hexprint("Ciphertext", buf
, 10);
262 hexcheck(buf
, "70 44 c9 be 48 ae 89 22 66 e4", 10);
263 hexprint("MAC", mac
, 16);
264 hexcheck(mac
, "65 be 7a 60 fd 3b 8a 5e 31 61 80 80 56 32 d8 10", 16);
265 h_decrypt(&ctx
, buf
, 10, mac
);
266 hexprint("decrypted", buf
, 10);
267 hexprint("MAC", mac
, 16);
268 hexcheck(mac
, "65 be 7a 60 fd 3b 8a 5e 31 61 80 80 56 32 d8 10", 16);
271 printf("\nTest Vector set 2:\n");
272 hexread(key
, "00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00"
273 "04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00", 32);
274 hexprint("Initial Key", key
, 32);
275 hexread(nonce
, "00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00", 16);
276 hexprint("Nonce", nonce
, 16);
277 h_key(&ctx
, key
, 32);
278 h_nonce(&ctx
, nonce
);
279 hexwprint("Working Key", ctx
.K
, 32);
280 hexwcheck(ctx
.K
, "6e e9 a7 6c bd 0b f6 20 a6 d9 b7 59 49 d3 39 95"
281 "04 f8 4a d6 83 12 f9 06 ed d1 a6 98 9e c8 9d 45", 32);
282 hexread(buf
, "00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00"
283 "04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00", 32);
284 hexprint("Plaintext", buf
, 32);
285 h_encrypt(&ctx
, buf
, 32, mac
);
286 hexprint("Ciphertext", buf
, 32);
287 hexcheck(buf
, "7a 72 a7 5b 62 50 38 0b 69 75 1c d1 28 30 8d 9a"
288 "0c 74 46 a3 bf 3f 99 e6 65 56 b9 c1 18 ca 7d 87", 32);
289 hexprint("MAC", mac
, 16);
290 hexcheck(mac
, "e4 e5 49 01 c5 0b 34 e7 80 c0 9c 39 b1 09 a1 17", 16);
291 h_decrypt(&ctx
, buf
, 32, mac
);
292 hexprint("decrypted", buf
, 32);
293 hexprint("MAC", mac
, 16);
294 hexcheck(mac
, "e4 e5 49 01 c5 0b 34 e7 80 c0 9c 39 b1 09 a1 17", 16);
297 printf("\nTest Vector set 3:\n");
298 hexread(key
, "48 65 6c 69 78", 5);
299 hexprint("Initial Key", key
, 5);
300 hexread(nonce
, "30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66", 16);
301 hexprint("Nonce", nonce
, 16);
303 h_nonce(&ctx
, nonce
);
304 hexwprint("Working Key", ctx
.K
, 32);
305 hexwcheck(ctx
.K
, "6c 1e d7 7a cb a3 a1 d2 8f 1c d6 20 6d f1 15 da"
306 "f4 03 28 4a 73 9b b6 9f 35 7a 85 f5 51 32 11 39", 32);
307 hexread(buf
, "48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21", 13);
308 hexprint("Plaintext", buf
, 13);
309 h_encrypt(&ctx
, buf
, 13, mac
);
310 hexprint("Ciphertext", buf
, 13);
311 hexcheck(buf
, "6c 4c 27 b9 7a 82 a0 c5 80 2c 23 f2 0d", 13);
312 hexprint("MAC", mac
, 16);
313 hexcheck(mac
, "6c 82 d1 aa 3b 90 5f 12 f1 44 3f a7 f6 a1 01 d2", 16);
314 h_decrypt(&ctx
, buf
, 13, mac
);
315 hexprint("decrypted", buf
, 13);
316 hexprint("MAC", mac
, 16);
317 hexcheck(mac
, "6c 82 d1 aa 3b 90 5f 12 f1 44 3f a7 f6 a1 01 d2", 16);
320 #define BLOCKSIZE 1600 /* for MAC-style tests */
322 char *testkey
= "test key 128bits";
324 UCHAR testframe
[BLOCKSIZE
];
327 /* Perform various timing tests
329 UCHAR bigbuf
[1024*1024];
332 main(int ac
, char **av
)
336 UCHAR key
[32], IV
[32];
341 if (ac
== 2 && strcmp(av
[1], "-test") == 0) {
345 if (ac
>= 2 && strcmp(av
[1], "-verbose") == 0) {