51 broke -E logic completely, rewise it
[tfcrypt.git] / skein.c
1 #include <string.h>
2 #include "tfdef.h"
3 #include "tfcore.h"
4 #include "skein.h"
5
6 static inline void puthash(TF_BYTE_TYPE *dst, const TF_UNIT_TYPE *src, size_t l)
7 {
8         size_t n;
9         for (n = 0; n < l; n++) dst[n] = (TF_BYTE_TYPE)(src[n>>3] >> (TF_SIZE_UNIT*(n&7)));
10 }
11
12 static void skein_process_blk(struct skein *sk, const TF_BYTE_TYPE *in, size_t szin, size_t l)
13 {
14         TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
15         size_t i;
16
17         do {
18                 sk->key[TF_TWEAK_WORD1] += l;
19
20                 memcpy(x, in, TF_BLOCK_SIZE);
21                 data_to_words(x, TF_BLOCK_SIZE);
22                 in += TF_BLOCK_SIZE;
23
24                 sk->key[TF_NR_KEY_UNITS-1-3] = THREEFISH_CONST;
25                 for (i = 0; i < TF_NR_KEY_UNITS-1-3; i++)
26                         sk->key[TF_NR_KEY_UNITS-1-3] ^= sk->key[i];
27                 sk->key[TF_TWEAK_WORD3] = sk->key[TF_TWEAK_WORD1] ^ sk->key[TF_TWEAK_WORD2];
28
29                 tf_encrypt_rawblk(y, x, sk->key);
30                 for (i = 0; i < TF_NR_BLOCK_UNITS; i++) sk->key[i] = y[i] ^ x[i];
31
32                 sk->key[TF_TWEAK_WORD2] &= ~SKEIN_FLAG_FIRST;
33         } while (--szin);
34 }
35
36 void skein_init_key(struct skein *sk, const void *ukey, size_t bits)
37 {
38         TF_UNIT_TYPE cfg[TF_NR_BLOCK_UNITS];
39
40         memset(sk, 0, sizeof(struct skein));
41
42         if (ukey) {
43                 memcpy(sk->key, ukey, TF_FROM_BITS(TF_MAX_BITS));
44                 data_to_words(sk->key, TF_FROM_BITS(TF_MAX_BITS));
45         }
46
47         sk->bits = bits;
48         sk->carry_bytes = 0;
49
50         memset(cfg, 0, sizeof(cfg));
51         cfg[0] = TF_SWAP_FUNC(((TF_UNIT_TYPE)SKEIN_VERSION << 32) + (TF_UNIT_TYPE)SKEIN_ID);
52         cfg[1] = TF_SWAP_FUNC(bits);
53
54         sk->key[TF_TWEAK_WORD1] = 0;
55         sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_CFG | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST;
56
57         skein_process_blk(sk, (TF_BYTE_TYPE *)cfg, 1, 32);
58
59         sk->key[TF_TWEAK_WORD1] = 0;
60         sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_MSG | SKEIN_FLAG_FIRST;
61 }
62
63 void skein_init(struct skein *sk, size_t bits)
64 {
65         skein_init_key(sk, NULL, bits);
66 }
67
68 void skein_update(struct skein *sk, const void *msg, size_t msgsz)
69 {
70         const TF_BYTE_TYPE *umsg = msg;
71         size_t n;
72
73         if (msgsz + sk->carry_bytes > TF_BLOCK_SIZE) {
74                 if (sk->carry_bytes) {
75                         n = TF_BLOCK_SIZE - sk->carry_bytes;
76                         if (n) {
77                                 memcpy(&sk->carry_block[sk->carry_bytes], umsg, n);
78                                 msgsz -= n;
79                                 umsg += n;
80                                 sk->carry_bytes += n;
81                         }
82                         skein_process_blk(sk, sk->carry_block, 1, TF_BLOCK_SIZE);
83                         sk->carry_bytes = 0;
84                 }
85
86                 if (msgsz > TF_BLOCK_SIZE) {
87                         n = (msgsz-1) / TF_BLOCK_SIZE;
88                         skein_process_blk(sk, umsg, n, TF_BLOCK_SIZE);
89                         msgsz -= n * TF_BLOCK_SIZE;
90                         umsg += n * TF_BLOCK_SIZE;
91                 }
92         }
93
94         if (msgsz) {
95                 memcpy(&sk->carry_block[sk->carry_bytes], umsg, msgsz);
96                 sk->carry_bytes += msgsz;
97         }
98 }
99
100 void skein_final(void *result, struct skein *sk)
101 {
102         TF_BYTE_TYPE *uresult = result;
103         TF_UNIT_TYPE key[TF_NR_BLOCK_UNITS], *X;
104         size_t i, b, n;
105
106         if (sk->carry_bytes < TF_BLOCK_SIZE)
107                 memset(sk->carry_block+sk->carry_bytes, 0, TF_BLOCK_SIZE-sk->carry_bytes);
108         sk->key[TF_TWEAK_WORD2] |= SKEIN_FLAG_LAST;
109         skein_process_blk(sk, sk->carry_block, 1, sk->carry_bytes);
110
111         b = (sk->bits + 7) / 8;
112
113         memset(sk->carry_block, 0, sizeof(sk->carry_block));
114         memcpy(key, sk->key, sizeof(key));
115
116         for (i = 0; (i * TF_BLOCK_SIZE) < b; i++) {
117                 X = (TF_UNIT_TYPE *)sk->carry_block;
118                 X[0] = TF_SWAP_FUNC((TF_UNIT_TYPE)i);
119                 sk->key[TF_TWEAK_WORD1] = 0;
120                 sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_OUT | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST;
121                 sk->carry_bytes = 0;
122
123                 skein_process_blk(sk, sk->carry_block, 1, TF_SIZE_UNIT);
124                 n = b-(i*TF_BLOCK_SIZE);
125                 if (n >= TF_BLOCK_SIZE) n = TF_BLOCK_SIZE;
126                 puthash(uresult+(i*TF_BLOCK_SIZE), sk->key, n);
127                 memcpy(sk->key, key, TF_BLOCK_SIZE);
128         }
129
130         memset(sk, 0, sizeof(struct skein));
131 }