xref: /third_party/ffmpeg/libavutil/twofish.c (revision cabdff1a)
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
33typedef 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
43static 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
62static 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
81static 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
100static 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
119struct AVTWOFISH *av_twofish_alloc(void)
120{
121    return av_mallocz(sizeof(struct AVTWOFISH));
122}
123
124const int av_twofish_size = sizeof(AVTWOFISH);
125
126static 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
141static 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
153static 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
177static 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
191static 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
196static 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
210static 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
238static 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
273av_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
316void 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