6 static inline void puthash(TF_BYTE_TYPE *dst, const TF_UNIT_TYPE *src, size_t l)
9 for (n = 0; n < l; n++) dst[n] = (TF_BYTE_TYPE)(src[n>>3] >> (TF_SIZE_UNIT*(n&7)));
12 static void skein_process_blk(struct skein *sk, const TF_BYTE_TYPE *in, size_t szin, size_t l)
14 TF_UNIT_TYPE x[TF_NR_BLOCK_UNITS], y[TF_NR_BLOCK_UNITS];
18 sk->key[TF_TWEAK_WORD1] += l;
20 memcpy(x, in, TF_BLOCK_SIZE);
21 data_to_words(x, TF_BLOCK_SIZE);
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];
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];
32 sk->key[TF_TWEAK_WORD2] &= ~SKEIN_FLAG_FIRST;
36 void skein_init_key(struct skein *sk, const void *ukey, size_t bits)
38 TF_UNIT_TYPE cfg[TF_NR_BLOCK_UNITS];
40 memset(sk, 0, sizeof(struct skein));
43 memcpy(sk->key, ukey, TF_FROM_BITS(TF_MAX_BITS));
44 data_to_words(sk->key, TF_FROM_BITS(TF_MAX_BITS));
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);
54 sk->key[TF_TWEAK_WORD1] = 0;
55 sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_CFG | SKEIN_FLAG_FIRST | SKEIN_FLAG_LAST;
57 skein_process_blk(sk, (TF_BYTE_TYPE *)cfg, 1, 32);
59 sk->key[TF_TWEAK_WORD1] = 0;
60 sk->key[TF_TWEAK_WORD2] = SKEIN_BLOCK_MSG | SKEIN_FLAG_FIRST;
63 void skein_init(struct skein *sk, size_t bits)
65 skein_init_key(sk, NULL, bits);
68 void skein_update(struct skein *sk, const void *msg, size_t msgsz)
70 const TF_BYTE_TYPE *umsg = msg;
73 if (msgsz + sk->carry_bytes > TF_BLOCK_SIZE) {
74 if (sk->carry_bytes) {
75 n = TF_BLOCK_SIZE - sk->carry_bytes;
77 memcpy(&sk->carry_block[sk->carry_bytes], umsg, n);
82 skein_process_blk(sk, sk->carry_block, 1, TF_BLOCK_SIZE);
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;
95 memcpy(&sk->carry_block[sk->carry_bytes], umsg, msgsz);
96 sk->carry_bytes += msgsz;
100 void skein_final(void *result, struct skein *sk)
102 TF_BYTE_TYPE *uresult = result;
103 TF_UNIT_TYPE key[TF_NR_BLOCK_UNITS], *X;
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);
111 b = (sk->bits + 7) / 8;
113 memset(sk->carry_block, 0, sizeof(sk->carry_block));
114 memcpy(key, sk->key, sizeof(key));
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;
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);
130 memset(sk, 0, sizeof(struct skein));