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