summaryrefslogtreecommitdiff
path: root/libavutil/twofish.c (plain)
blob: d84fa4f363a09327b89d22b9cd9ab2a76b2430f6
1/*
2 * An implementation of the TwoFish algorithm
3 * Copyright (c) 2015 Supraja Meedinti
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include "twofish.h"
22#include "common.h"
23#include "intreadwrite.h"
24#include "attributes.h"
25
26#define LR(x, n) ((x) << (n) | (x) >> (32 - (n)))
27#define RR(x, n) ((x) >> (n) | (x) << (32 - (n)))
28
29typedef struct AVTWOFISH {
30 uint32_t K[40];
31 uint32_t S[4];
32 int ksize;
33 uint32_t MDS1[256];
34 uint32_t MDS2[256];
35 uint32_t MDS3[256];
36 uint32_t MDS4[256];
37} AVTWOFISH;
38
39static const uint8_t MD1[256] = {
40 0x00, 0x5b, 0xb6, 0xed, 0x05, 0x5e, 0xb3, 0xe8, 0x0a, 0x51, 0xbc, 0xe7, 0x0f, 0x54, 0xb9, 0xe2,
41 0x14, 0x4f, 0xa2, 0xf9, 0x11, 0x4a, 0xa7, 0xfc, 0x1e, 0x45, 0xa8, 0xf3, 0x1b, 0x40, 0xad, 0xf6,
42 0x28, 0x73, 0x9e, 0xc5, 0x2d, 0x76, 0x9b, 0xc0, 0x22, 0x79, 0x94, 0xcf, 0x27, 0x7c, 0x91, 0xca,
43 0x3c, 0x67, 0x8a, 0xd1, 0x39, 0x62, 0x8f, 0xd4, 0x36, 0x6d, 0x80, 0xdb, 0x33, 0x68, 0x85, 0xde,
44 0x50, 0x0b, 0xe6, 0xbd, 0x55, 0x0e, 0xe3, 0xb8, 0x5a, 0x01, 0xec, 0xb7, 0x5f, 0x04, 0xe9, 0xb2,
45 0x44, 0x1f, 0xf2, 0xa9, 0x41, 0x1a, 0xf7, 0xac, 0x4e, 0x15, 0xf8, 0xa3, 0x4b, 0x10, 0xfd, 0xa6,
46 0x78, 0x23, 0xce, 0x95, 0x7d, 0x26, 0xcb, 0x90, 0x72, 0x29, 0xc4, 0x9f, 0x77, 0x2c, 0xc1, 0x9a,
47 0x6c, 0x37, 0xda, 0x81, 0x69, 0x32, 0xdf, 0x84, 0x66, 0x3d, 0xd0, 0x8b, 0x63, 0x38, 0xd5, 0x8e,
48 0xa0, 0xfb, 0x16, 0x4d, 0xa5, 0xfe, 0x13, 0x48, 0xaa, 0xf1, 0x1c, 0x47, 0xaf, 0xf4, 0x19, 0x42,
49 0xb4, 0xef, 0x02, 0x59, 0xb1, 0xea, 0x07, 0x5c, 0xbe, 0xe5, 0x08, 0x53, 0xbb, 0xe0, 0x0d, 0x56,
50 0x88, 0xd3, 0x3e, 0x65, 0x8d, 0xd6, 0x3b, 0x60, 0x82, 0xd9, 0x34, 0x6f, 0x87, 0xdc, 0x31, 0x6a,
51 0x9c, 0xc7, 0x2a, 0x71, 0x99, 0xc2, 0x2f, 0x74, 0x96, 0xcd, 0x20, 0x7b, 0x93, 0xc8, 0x25, 0x7e,
52 0xf0, 0xab, 0x46, 0x1d, 0xf5, 0xae, 0x43, 0x18, 0xfa, 0xa1, 0x4c, 0x17, 0xff, 0xa4, 0x49, 0x12,
53 0xe4, 0xbf, 0x52, 0x09, 0xe1, 0xba, 0x57, 0x0c, 0xee, 0xb5, 0x58, 0x03, 0xeb, 0xb0, 0x5d, 0x06,
54 0xd8, 0x83, 0x6e, 0x35, 0xdd, 0x86, 0x6b, 0x30, 0xd2, 0x89, 0x64, 0x3f, 0xd7, 0x8c, 0x61, 0x3a,
55 0xcc, 0x97, 0x7a, 0x21, 0xc9, 0x92, 0x7f, 0x24, 0xc6, 0x9d, 0x70, 0x2b, 0xc3, 0x98, 0x75, 0x2e
56};
57
58static const uint8_t MD2[256] = {
59 0x00, 0xef, 0xb7, 0x58, 0x07, 0xe8, 0xb0, 0x5f, 0x0e, 0xe1, 0xb9, 0x56, 0x09, 0xe6, 0xbe, 0x51,
60 0x1c, 0xf3, 0xab, 0x44, 0x1b, 0xf4, 0xac, 0x43, 0x12, 0xfd, 0xa5, 0x4a, 0x15, 0xfa, 0xa2, 0x4d,
61 0x38, 0xd7, 0x8f, 0x60, 0x3f, 0xd0, 0x88, 0x67, 0x36, 0xd9, 0x81, 0x6e, 0x31, 0xde, 0x86, 0x69,
62 0x24, 0xcb, 0x93, 0x7c, 0x23, 0xcc, 0x94, 0x7b, 0x2a, 0xc5, 0x9d, 0x72, 0x2d, 0xc2, 0x9a, 0x75,
63 0x70, 0x9f, 0xc7, 0x28, 0x77, 0x98, 0xc0, 0x2f, 0x7e, 0x91, 0xc9, 0x26, 0x79, 0x96, 0xce, 0x21,
64 0x6c, 0x83, 0xdb, 0x34, 0x6b, 0x84, 0xdc, 0x33, 0x62, 0x8d, 0xd5, 0x3a, 0x65, 0x8a, 0xd2, 0x3d,
65 0x48, 0xa7, 0xff, 0x10, 0x4f, 0xa0, 0xf8, 0x17, 0x46, 0xa9, 0xf1, 0x1e, 0x41, 0xae, 0xf6, 0x19,
66 0x54, 0xbb, 0xe3, 0x0c, 0x53, 0xbc, 0xe4, 0x0b, 0x5a, 0xb5, 0xed, 0x02, 0x5d, 0xb2, 0xea, 0x05,
67 0xe0, 0x0f, 0x57, 0xb8, 0xe7, 0x08, 0x50, 0xbf, 0xee, 0x01, 0x59, 0xb6, 0xe9, 0x06, 0x5e, 0xb1,
68 0xfc, 0x13, 0x4b, 0xa4, 0xfb, 0x14, 0x4c, 0xa3, 0xf2, 0x1d, 0x45, 0xaa, 0xf5, 0x1a, 0x42, 0xad,
69 0xd8, 0x37, 0x6f, 0x80, 0xdf, 0x30, 0x68, 0x87, 0xd6, 0x39, 0x61, 0x8e, 0xd1, 0x3e, 0x66, 0x89,
70 0xc4, 0x2b, 0x73, 0x9c, 0xc3, 0x2c, 0x74, 0x9b, 0xca, 0x25, 0x7d, 0x92, 0xcd, 0x22, 0x7a, 0x95,
71 0x90, 0x7f, 0x27, 0xc8, 0x97, 0x78, 0x20, 0xcf, 0x9e, 0x71, 0x29, 0xc6, 0x99, 0x76, 0x2e, 0xc1,
72 0x8c, 0x63, 0x3b, 0xd4, 0x8b, 0x64, 0x3c, 0xd3, 0x82, 0x6d, 0x35, 0xda, 0x85, 0x6a, 0x32, 0xdd,
73 0xa8, 0x47, 0x1f, 0xf0, 0xaf, 0x40, 0x18, 0xf7, 0xa6, 0x49, 0x11, 0xfe, 0xa1, 0x4e, 0x16, 0xf9,
74 0xb4, 0x5b, 0x03, 0xec, 0xb3, 0x5c, 0x04, 0xeb, 0xba, 0x55, 0x0d, 0xe2, 0xbd, 0x52, 0x0a, 0xe5
75};
76
77static const uint8_t q0[256] = {
78 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38,
79 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48,
80 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82,
81 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61,
82 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
83 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7,
84 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71,
85 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7,
86 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90,
87 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
88 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64,
89 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a,
90 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d,
91 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
92 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
93 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0
94};
95
96static const uint8_t q1[256] = {
97 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b,
98 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f,
99 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5,
100 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51,
101 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
102 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8,
103 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2,
104 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17,
105 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e,
106 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
107 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48,
108 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64,
109 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69,
110 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc,
111 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
112 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91
113};
114
115struct AVTWOFISH *av_twofish_alloc(void)
116{
117 return av_mallocz(sizeof(struct AVTWOFISH));
118}
119
120const int av_twofish_size = sizeof(AVTWOFISH);
121
122static uint8_t gfmul(uint8_t a, uint8_t b)
123{
124 uint8_t r = 0, t;
125 while (a && b) {
126 if (a & 1)
127 r = r ^ b;
128 t = b & 0x80;
129 b = b << 1;
130 if (t)
131 b = b ^ 0x4d;
132 a = a >> 1;
133 }
134 return r;
135}
136
137static uint32_t tf_RS(uint32_t k0, uint32_t k1)
138{
139 uint8_t s[4], m[8];
140 AV_WL32(m, k0);
141 AV_WL32(m + 4, k1);
142 s[0] = gfmul(0x01, m[0]) ^ gfmul(0xa4, m[1]) ^ gfmul(0x55, m[2]) ^ gfmul(0x87, m[3]) ^ gfmul(0x5a, m[4]) ^ gfmul(0x58, m[5]) ^ gfmul(0xdb, m[6]) ^ gfmul(0x9e, m[7]);
143 s[1] = gfmul(0xa4, m[0]) ^ gfmul(0x56, m[1]) ^ gfmul(0x82, m[2]) ^ gfmul(0xf3, m[3]) ^ gfmul(0x1e, m[4]) ^ gfmul(0xc6, m[5]) ^ gfmul(0x68, m[6]) ^ gfmul(0xe5, m[7]);
144 s[2] = gfmul(0x02, m[0]) ^ gfmul(0xa1, m[1]) ^ gfmul(0xfc, m[2]) ^ gfmul(0xc1, m[3]) ^ gfmul(0x47, m[4]) ^ gfmul(0xae, m[5]) ^ gfmul(0x3d, m[6]) ^ gfmul(0x19, m[7]);
145 s[3] = gfmul(0xa4, m[0]) ^ gfmul(0x55, m[1]) ^ gfmul(0x87, m[2]) ^ gfmul(0x5a, m[3]) ^ gfmul(0x58, m[4]) ^ gfmul(0xdb, m[5]) ^ gfmul(0x9e, m[6]) ^ gfmul(0x03, m[7]);
146 return AV_RL32(s);
147}
148
149static void tf_h0(uint8_t y[4], uint32_t L[4], int k)
150{
151 uint8_t l[4];
152 if (k == 4) {
153 AV_WL32(l, L[3]);
154 y[0] = q1[y[0]] ^ l[0];
155 y[1] = q0[y[1]] ^ l[1];
156 y[2] = q0[y[2]] ^ l[2];
157 y[3] = q1[y[3]] ^ l[3];
158 }
159 if (k >= 3) {
160 AV_WL32(l, L[2]);
161 y[0] = q1[y[0]] ^ l[0];
162 y[1] = q1[y[1]] ^ l[1];
163 y[2] = q0[y[2]] ^ l[2];
164 y[3] = q0[y[3]] ^ l[3];
165 }
166 AV_WL32(l, L[1]);
167 y[0] = q1[q0[q0[y[0]] ^ l[0]] ^ (L[0] & 0xff)];
168 y[1] = q0[q0[q1[y[1]] ^ l[1]] ^ ((L[0] >> 8) & 0xff)];
169 y[2] = q1[q1[q0[y[2]] ^ l[2]] ^ ((L[0] >> 16) & 0xff)];
170 y[3] = q0[q1[q1[y[3]] ^ l[3]] ^ (L[0] >> 24)];
171}
172
173static uint32_t tf_h(uint32_t X, uint32_t L[4], int k)
174{
175 uint8_t y[4], l[4];
176 AV_WL32(y, X);
177 tf_h0(y, L, k);
178
179 l[0] = y[0] ^ MD2[y[1]] ^ MD1[y[2]] ^ MD1[y[3]];
180 l[1] = MD1[y[0]] ^ MD2[y[1]] ^ MD2[y[2]] ^ y[3];
181 l[2] = MD2[y[0]] ^ MD1[y[1]] ^ y[2] ^ MD2[y[3]];
182 l[3] = MD2[y[0]] ^ y[1] ^ MD2[y[2]] ^ MD1[y[3]];
183
184 return AV_RL32(l);
185}
186
187static uint32_t MDS_mul(AVTWOFISH *cs, uint32_t X)
188{
189 return cs->MDS1[(X) & 0xff] ^ cs->MDS2[((X) >> 8) & 0xff] ^ cs->MDS3[((X) >> 16) & 0xff] ^ cs->MDS4[(X) >> 24];
190}
191
192static void precomputeMDS(AVTWOFISH *cs)
193{
194 uint8_t y[4];
195 int i;
196 for (i = 0; i < 256; i++) {
197 y[0] = y[1] = y[2] = y[3] = i;
198 tf_h0(y, cs->S, cs->ksize);
199 cs->MDS1[i] = ((uint32_t)y[0]) ^ ((uint32_t)MD1[y[0]] << 8) ^ ((uint32_t)MD2[y[0]] << 16) ^ ((uint32_t)MD2[y[0]] << 24);
200 cs->MDS2[i] = ((uint32_t)MD2[y[1]]) ^ ((uint32_t)MD2[y[1]] << 8) ^ ((uint32_t)MD1[y[1]] << 16) ^ ((uint32_t)y[1] << 24);
201 cs->MDS3[i] = ((uint32_t)MD1[y[2]]) ^ ((uint32_t)MD2[y[2]] << 8) ^ ((uint32_t)y[2] << 16) ^ ((uint32_t)MD2[y[2]] << 24);
202 cs->MDS4[i] = ((uint32_t)MD1[y[3]]) ^ ((uint32_t)y[3] << 8) ^ ((uint32_t)MD2[y[3]] << 16) ^ ((uint32_t)MD1[y[3]] << 24);
203 }
204}
205
206static void twofish_encrypt(AVTWOFISH *cs, uint8_t *dst, const uint8_t *src)
207{
208 uint32_t P[4], t0, t1;
209 int i;
210 P[0] = AV_RL32(src) ^ cs->K[0];
211 P[1] = AV_RL32(src + 4) ^ cs->K[1];
212 P[2] = AV_RL32(src + 8) ^ cs->K[2];
213 P[3] = AV_RL32(src + 12) ^ cs->K[3];
214 for (i = 0; i < 16; i += 2) {
215 t0 = MDS_mul(cs, P[0]);
216 t1 = MDS_mul(cs, LR(P[1], 8));
217 P[2] = RR(P[2] ^ (t0 + t1 + cs->K[2 * i + 8]), 1);
218 P[3] = LR(P[3], 1) ^ (t0 + 2 * t1 + cs->K[2 * i + 9]);
219 t0 = MDS_mul(cs, P[2]);
220 t1 = MDS_mul(cs, LR(P[3], 8));
221 P[0] = RR(P[0] ^ (t0 + t1 + cs->K[2 * i + 10]), 1);
222 P[1] = LR(P[1], 1) ^ (t0 + 2 * t1 + cs->K[2 * i + 11]);
223 }
224 P[2] ^= cs->K[4];
225 P[3] ^= cs->K[5];
226 P[0] ^= cs->K[6];
227 P[1] ^= cs->K[7];
228 AV_WL32(dst, P[2]);
229 AV_WL32(dst + 4, P[3]);
230 AV_WL32(dst + 8, P[0]);
231 AV_WL32(dst + 12, P[1]);
232}
233
234static void twofish_decrypt(AVTWOFISH *cs, uint8_t *dst, const uint8_t *src, uint8_t *iv)
235{
236 uint32_t P[4], t0, t1;
237 int i;
238 P[2] = AV_RL32(src) ^ cs->K[4];
239 P[3] = AV_RL32(src + 4) ^ cs->K[5];
240 P[0] = AV_RL32(src + 8) ^ cs->K[6];
241 P[1] = AV_RL32(src + 12) ^ cs->K[7];
242 for (i = 15; i >= 0; i -= 2) {
243 t0 = MDS_mul(cs, P[2]);
244 t1 = MDS_mul(cs, LR(P[3], 8));
245 P[0] = LR(P[0], 1) ^ (t0 + t1 + cs->K[2 * i + 8]);
246 P[1] = RR(P[1] ^ (t0 + 2 * t1 + cs->K[2 * i + 9]), 1);
247 t0 = MDS_mul(cs, P[0]);
248 t1 = MDS_mul(cs, LR(P[1], 8));
249 P[2] = LR(P[2], 1) ^ (t0 + t1 + cs->K[2 * i + 6]);
250 P[3] = RR(P[3] ^ (t0 + 2 * t1 + cs->K[2 * i + 7]), 1);
251 }
252 P[0] ^= cs->K[0];
253 P[1] ^= cs->K[1];
254 P[2] ^= cs->K[2];
255 P[3] ^= cs->K[3];
256 if (iv) {
257 P[0] ^= AV_RL32(iv);
258 P[1] ^= AV_RL32(iv + 4);
259 P[2] ^= AV_RL32(iv + 8);
260 P[3] ^= AV_RL32(iv + 12);
261 memcpy(iv, src, 16);
262 }
263 AV_WL32(dst, P[2]);
264 AV_WL32(dst + 4, P[3]);
265 AV_WL32(dst + 8, P[0]);
266 AV_WL32(dst + 12, P[1]);
267}
268
269av_cold int av_twofish_init(AVTWOFISH *cs, const uint8_t *key, int key_bits)
270{
271 int i;
272 uint8_t keypad[32];
273 uint32_t Key[8], Me[4], Mo[4], A, B;
274 const uint32_t rho = 0x01010101;
275 if (key_bits < 0)
276 return AVERROR(EINVAL);
277 if (key_bits <= 128) {
278 cs->ksize = 2;
279 } else if (key_bits <= 192) {
280 cs->ksize = 3;
281 } else {
282 cs->ksize = 4;
283 }
284 memset(keypad, 0, sizeof(keypad));
285 if (key_bits <= 256) {
286 memcpy(keypad, key, key_bits >> 3);
287 } else {
288 memcpy(keypad, key, 32);
289 }
290 for (i = 0; i < 2 * cs->ksize ; i++)
291 Key[i] = AV_RL32(keypad + 4 * i);
292 for (i = 0; i < cs->ksize; i++) {
293 Me[i] = Key[2 * i];
294 Mo[i] = Key[2 * i + 1];
295 cs->S[cs->ksize - i - 1] = tf_RS(Me[i], Mo[i]);
296 }
297 precomputeMDS(cs);
298 for (i = 0; i < 20; i++) {
299 A = tf_h((2 * i) * rho, Me, cs->ksize);
300 B = tf_h((2 * i + 1) * rho, Mo, cs->ksize);
301 B = LR(B, 8);
302 cs->K[2 * i] = A + B;
303 cs->K[2 * i + 1] = LR((A + (2 * B)), 9);
304 }
305 if (cs->ksize << 6 != key_bits) {
306 return 1;
307 } else {
308 return 0;
309 }
310}
311
312void av_twofish_crypt(AVTWOFISH *cs, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt)
313{
314 int i;
315 while (count--) {
316 if (decrypt) {
317 twofish_decrypt(cs, dst, src, iv);
318 } else {
319 if (iv) {
320 for (i = 0; i < 16; i++)
321 dst[i] = src[i] ^ iv[i];
322 twofish_encrypt(cs, dst, dst);
323 memcpy(iv, dst, 16);
324 } else {
325 twofish_encrypt(cs, dst, src);
326 }
327 }
328 src = src + 16;
329 dst = dst + 16;
330 }
331}
332