1 /*
2 * Copyright (c) 2015-2018, Andrew Romanenko <melanhit@gmail.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <stdlib.h>
30 #include <stdint.h>
31
32 #include "../akmos.h"
33 #include "../bits.h"
34 #include "../cipher.h"
35
36 #include "threefish.h"
37 #include "threefish_mix.h"
38
39 #define WORDS_256 AKMOS_THREEFISH_WORDS_256
40 #define ROUNDS_256 (72 / 8)
41 #define SKEYS_256 ((ROUNDS_256 * 2) + 1)
42
akmos_threefish_256_setkey(akmos_cipher_algo_t * uctx,const uint8_t * key,size_t len)43 void akmos_threefish_256_setkey(akmos_cipher_algo_t *uctx,
44 const uint8_t *key,
45 size_t __attribute__((unused)) len)
46 {
47 akmos_threefish_256_t *ctx;
48 uint64_t *k, *S;
49 size_t i, j;
50
51 ctx = &uctx->tf_256;
52
53 k = ctx->k;
54
55 for(i = 0; i < WORDS_256; i++, key += 8)
56 k[i] = PACK64BE(key);
57
58 k[WORDS_256] = AKMOS_THREEFISH_C240;
59
60 for(i = 0; i < WORDS_256; i++)
61 k[WORDS_256] ^= k[i];
62
63 for(i = 0, S = ctx->S; i < SKEYS_256; i++, S += WORDS_256) {
64 for(j = 0; j < WORDS_256; j++)
65 S[j] = k[(i+j)%(WORDS_256+1)];
66
67 S[WORDS_256-1] += i;
68 }
69 }
70
akmos_threefish_256_encrypt(akmos_cipher_algo_t * uctx,const uint8_t * in_blk,uint8_t * out_blk)71 void akmos_threefish_256_encrypt(akmos_cipher_algo_t *uctx,
72 const uint8_t *in_blk,
73 uint8_t *out_blk)
74 {
75 akmos_threefish_256_t *ctx;
76 uint64_t s[WORDS_256], *S;
77 int i, j;
78
79 ctx = &uctx->tf_256;
80
81 for(i = 0; i < WORDS_256; i++, in_blk += 8)
82 s[i] = PACK64BE(in_blk);
83
84 for(i = 0, S = ctx->S; i < ROUNDS_256; i++, S += WORDS_256) {
85 for(j = 0; j < WORDS_256; j++)
86 s[j] += S[j];
87
88 threefish_256_emix(s, 14, 16, 52, 57);
89 threefish_256_emix(s, 23, 40, 5, 37);
90
91 for(j = 0, S += WORDS_256; j < WORDS_256; j++)
92 s[j] += S[j];
93
94 threefish_256_emix(s, 25, 33, 46, 12);
95 threefish_256_emix(s, 58, 22, 32, 32);
96 }
97
98 for(i = 0; i < WORDS_256; i++, out_blk += 8)
99 UNPACK64BE(out_blk, s[i] + S[i]);
100 }
101
akmos_threefish_256_decrypt(akmos_cipher_algo_t * uctx,const uint8_t * in_blk,uint8_t * out_blk)102 void akmos_threefish_256_decrypt(akmos_cipher_algo_t *uctx,
103 const uint8_t *in_blk,
104 uint8_t *out_blk)
105 {
106 akmos_threefish_256_t *ctx;
107 uint64_t s[WORDS_256], *S;
108 int i, j;
109
110 ctx = &uctx->tf_256;
111
112 for(i = 0; i < WORDS_256; i++, in_blk += 8)
113 s[i] = PACK64BE(in_blk);
114
115 S = ctx->S + (WORDS_256 * (SKEYS_256 - 1));
116 for(i = 0; i < WORDS_256; i++)
117 s[i] -= S[i];
118
119 for(i = ROUNDS_256; i > 0; i--) {
120 threefish_256_dmix(s, 32, 32, 58, 22);
121 threefish_256_dmix(s, 46, 12, 25, 33);
122
123 for(j = 0, S -= WORDS_256; j < WORDS_256; j++)
124 s[j] -= S[j];
125
126 threefish_256_dmix(s, 5, 37, 23, 40);
127 threefish_256_dmix(s, 52, 57, 14, 16);
128
129 for(j = 0, S -= WORDS_256; j < WORDS_256; j++)
130 s[j] -= S[j];
131 }
132
133 for(i = 0; i < WORDS_256; i++, out_blk += 8)
134 UNPACK64BE(out_blk, s[i]);
135 }
136