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_1024  AKMOS_THREEFISH_WORDS_1024
40 #define ROUNDS_1024 (80 / 8)
41 #define SKEYS_1024  ((ROUNDS_1024 * 2) + 1)
42 
akmos_threefish_1024_setkey(akmos_cipher_algo_t * uctx,const uint8_t * key,size_t len)43 void akmos_threefish_1024_setkey(akmos_cipher_algo_t *uctx,
44                                  const uint8_t *key,
45                                  size_t __attribute__((unused)) len)
46 {
47     akmos_threefish_1024_t *ctx;
48     uint64_t *k, *S;
49     size_t i, j;
50 
51     ctx = &uctx->tf_1024;
52 
53     k = ctx->k;
54 
55     for(i = 0; i < WORDS_1024; i++, key +=8)
56         k[i] = PACK64BE(key);
57 
58     k[WORDS_1024] = AKMOS_THREEFISH_C240;
59     for(i = 0; i < WORDS_1024; i++)
60         k[WORDS_1024] ^= k[i];
61 
62     for(i = 0, S = ctx->S; i < SKEYS_1024; i++, S += WORDS_1024) {
63         for(j = 0; j < WORDS_1024; j++)
64             S[j] = k[(i+j)%(WORDS_1024+1)];
65 
66         S[WORDS_1024-1] += i;
67     }
68 }
69 
akmos_threefish_1024_encrypt(akmos_cipher_algo_t * uctx,const uint8_t * in_blk,uint8_t * out_blk)70 void akmos_threefish_1024_encrypt(akmos_cipher_algo_t *uctx,
71                                   const uint8_t *in_blk,
72                                   uint8_t *out_blk)
73 {
74     akmos_threefish_1024_t *ctx;
75     uint64_t s[WORDS_1024], *S;
76     int i, j;
77 
78     ctx = &uctx->tf_1024;
79 
80     for(i = 0; i < WORDS_1024; i++, in_blk += 8)
81         s[i] = PACK64BE(in_blk);
82 
83     for(i = 0, S = ctx->S; i < ROUNDS_1024; i++, S += WORDS_1024) {
84         for(j = 0; j < WORDS_1024; j++)
85             s[j] += S[j];
86 
87         threefish_1024_emix1(s, 24, 13,  8, 47,  8, 17, 22, 37);
88         threefish_1024_emix2(s, 38, 19, 10, 55, 49, 18, 23, 52);
89         threefish_1024_emix3(s, 33,  4, 51, 13, 34, 41, 59, 17);
90         threefish_1024_emix4(s,  5, 20, 48, 41, 47, 28, 16, 25);
91 
92         for(j = 0, S += WORDS_1024; j < WORDS_1024; j++)
93             s[j] += S[j];
94 
95         threefish_1024_emix1(s, 41,  9, 37, 31, 12, 47, 44, 30);
96         threefish_1024_emix2(s, 16, 34, 56, 51,  4, 53, 42, 41);
97         threefish_1024_emix3(s, 31, 44, 47, 46, 19, 42, 44, 25);
98         threefish_1024_emix4(s,  9, 48, 35, 52, 23, 31, 37, 20);
99     }
100 
101     for(i = 0; i < WORDS_1024; i++, out_blk += 8)
102         UNPACK64BE(out_blk, s[i] + S[i]);
103 }
104 
akmos_threefish_1024_decrypt(akmos_cipher_algo_t * uctx,const uint8_t * in_blk,uint8_t * out_blk)105 void akmos_threefish_1024_decrypt(akmos_cipher_algo_t *uctx,
106                                   const uint8_t *in_blk,
107                                   uint8_t *out_blk)
108 {
109     akmos_threefish_1024_t *ctx;
110     uint64_t s[WORDS_1024], *S;
111     int i, j;
112 
113     ctx = &uctx->tf_1024;
114 
115     for(i = 0; i < WORDS_1024; i++, in_blk += 8)
116         s[i] = PACK64BE(in_blk);
117 
118     S = ctx->S + (WORDS_1024 * (SKEYS_1024 - 1));
119     for(i = 0; i < WORDS_1024; i++)
120         s[i] -= S[i];
121 
122     for(i = ROUNDS_1024; i > 0; i--) {
123         threefish_1024_dmix1(s, 20, 37, 31, 23, 52, 35, 48,  9);
124         threefish_1024_dmix2(s, 25, 44, 42, 19, 46, 47, 44, 31);
125         threefish_1024_dmix3(s, 41, 42, 53,  4, 51, 56, 34, 16);
126         threefish_1024_dmix4(s, 30, 44, 47, 12, 31, 37,  9, 41);
127 
128         for(j = 0, S -= WORDS_1024; j < WORDS_1024; j++)
129             s[j] -= S[j];
130 
131         threefish_1024_dmix1(s, 25, 16, 28, 47, 41, 48, 20,  5);
132         threefish_1024_dmix2(s, 17, 59, 41, 34, 13, 51,  4, 33);
133         threefish_1024_dmix3(s, 52, 23, 18, 49, 55, 10, 19, 38);
134         threefish_1024_dmix4(s, 37, 22, 17,  8, 47,  8, 13, 24);
135 
136         for(j = 0, S -= WORDS_1024; j < WORDS_1024; j++)
137             s[j] -= S[j];
138     }
139 
140     for(i = 0; i < WORDS_1024; i++, out_blk += 8)
141         UNPACK64BE(out_blk, s[i]);
142 }
143