2015-12-04 15:47:52 +01:00
|
|
|
/* This is an independent implementation of the encryption algorithm: */
|
|
|
|
/* */
|
|
|
|
/* Twofish by Bruce Schneier and colleagues */
|
|
|
|
/* */
|
|
|
|
/* which is a candidate algorithm in the Advanced Encryption Standard */
|
|
|
|
/* programme of the US National Institute of Standards and Technology. */
|
|
|
|
/* */
|
|
|
|
/* Copyright in this implementation is held by Dr B R Gladman but I */
|
|
|
|
/* hereby give permission for its free direct or derivative use subject */
|
|
|
|
/* to acknowledgment of its origin and compliance with any conditions */
|
|
|
|
/* that the originators of t he algorithm place on its exploitation. */
|
|
|
|
/* */
|
|
|
|
/* My thanks to Doug Whiting and Niels Ferguson for comments that led */
|
|
|
|
/* to improvements in this implementation. */
|
|
|
|
/* */
|
|
|
|
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
|
|
|
|
/* */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* */
|
2016-05-10 19:07:07 +02:00
|
|
|
/* Cleaned and optimized for GPU use with hashcat by Jens Steube */
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2019-03-23 22:15:38 +01:00
|
|
|
#include "inc_vendor.h"
|
|
|
|
#include "inc_types.h"
|
|
|
|
#include "inc_common.h"
|
|
|
|
#include "inc_cipher_twofish.h"
|
2017-01-21 15:37:44 +01:00
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC u32 mds_rem (u32 p0, u32 p1)
|
2017-01-21 15:37:44 +01:00
|
|
|
{
|
|
|
|
#define G_MOD 0x14d
|
|
|
|
|
2019-03-16 21:11:02 +01:00
|
|
|
#define MDS_REM_ROUND() \
|
|
|
|
{ \
|
|
|
|
u32 t = p1 >> 24; \
|
|
|
|
p1 = (p1 << 8) | (p0 >> 24); \
|
|
|
|
p0 <<= 8; \
|
|
|
|
u32 u = (t << 1); \
|
|
|
|
if (t & 0x80) u ^= G_MOD; \
|
|
|
|
p1 ^= t ^ (u << 16); \
|
|
|
|
u ^= (t >> 1); \
|
|
|
|
if (t & 0x01) u ^= G_MOD >> 1; \
|
|
|
|
p1 ^= (u << 24) | (u << 8); \
|
|
|
|
}
|
2017-01-21 15:37:44 +01:00
|
|
|
|
2019-03-16 21:11:02 +01:00
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
|
|
|
MDS_REM_ROUND();
|
2017-01-21 15:37:44 +01:00
|
|
|
|
2019-03-16 21:11:02 +01:00
|
|
|
#undef MDS_REM_ROUND
|
2017-01-21 15:37:44 +01:00
|
|
|
|
|
|
|
return p1;
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC u32 h_fun128 (u32 *sk, u32 *lk, const u32 x, const u32 *key)
|
2015-12-04 15:47:52 +01:00
|
|
|
{
|
|
|
|
u32 b0, b1, b2, b3;
|
|
|
|
|
|
|
|
b0 = extract_byte (x, 0);
|
|
|
|
b1 = extract_byte (x, 1);
|
|
|
|
b2 = extract_byte (x, 2);
|
|
|
|
b3 = extract_byte (x, 3);
|
|
|
|
|
|
|
|
b0 = q (0, (q (0, b0) ^ extract_byte (key[1], 0))) ^ extract_byte (key[0], 0);
|
|
|
|
b1 = q (0, (q (1, b1) ^ extract_byte (key[1], 1))) ^ extract_byte (key[0], 1);
|
|
|
|
b2 = q (1, (q (0, b2) ^ extract_byte (key[1], 2))) ^ extract_byte (key[0], 2);
|
|
|
|
b3 = q (1, (q (1, b3) ^ extract_byte (key[1], 3))) ^ extract_byte (key[0], 3);
|
|
|
|
|
|
|
|
return mds (0, b0) ^ mds (1, b1) ^ mds (2, b2) ^ mds (3, b3);
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC void twofish128_set_key (u32 *sk, u32 *lk, const u32 *ukey)
|
2017-01-21 15:37:44 +01:00
|
|
|
{
|
|
|
|
u32 me_key[2];
|
|
|
|
|
|
|
|
me_key[0] = ukey[0];
|
|
|
|
me_key[1] = ukey[2];
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
u32 mo_key[2];
|
|
|
|
|
|
|
|
mo_key[0] = ukey[1];
|
|
|
|
mo_key[1] = ukey[3];
|
|
|
|
|
|
|
|
sk[1] = mds_rem (me_key[0], mo_key[0]);
|
|
|
|
sk[0] = mds_rem (me_key[1], mo_key[1]);
|
|
|
|
|
2019-03-03 12:12:01 +01:00
|
|
|
for (int i = 0; i < 40; i += 2)
|
2017-01-21 15:37:44 +01:00
|
|
|
{
|
|
|
|
u32 a = 0x01010101 * i;
|
|
|
|
u32 b = 0x01010101 + a;
|
|
|
|
|
|
|
|
a = h_fun128 (sk, lk, a, me_key);
|
|
|
|
b = h_fun128 (sk, lk, b, mo_key);
|
|
|
|
|
2019-03-23 22:15:38 +01:00
|
|
|
b = hc_rotl32_S (b, 8);
|
2017-01-21 15:37:44 +01:00
|
|
|
|
|
|
|
lk[i + 0] = a + b;
|
2019-03-23 22:15:38 +01:00
|
|
|
lk[i + 1] = hc_rotl32_S (a + 2 * b, 9);
|
2017-01-21 15:37:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC void twofish128_encrypt (const u32 *sk, const u32 *lk, const u32 *in, u32 *out)
|
2017-01-21 15:37:44 +01:00
|
|
|
{
|
|
|
|
u32 data[4];
|
|
|
|
|
|
|
|
data[0] = in[0] ^ lk[0];
|
|
|
|
data[1] = in[1] ^ lk[1];
|
|
|
|
data[2] = in[2] ^ lk[2];
|
|
|
|
data[3] = in[3] ^ lk[3];
|
|
|
|
|
|
|
|
f_rnd128 (0);
|
|
|
|
f_rnd128 (1);
|
|
|
|
f_rnd128 (2);
|
|
|
|
f_rnd128 (3);
|
|
|
|
f_rnd128 (4);
|
|
|
|
f_rnd128 (5);
|
|
|
|
f_rnd128 (6);
|
|
|
|
f_rnd128 (7);
|
|
|
|
|
|
|
|
out[0] = data[2] ^ lk[4];
|
|
|
|
out[1] = data[3] ^ lk[5];
|
|
|
|
out[2] = data[0] ^ lk[6];
|
|
|
|
out[3] = data[1] ^ lk[7];
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC void twofish128_decrypt (const u32 *sk, const u32 *lk, const u32 *in, u32 *out)
|
2017-01-21 15:37:44 +01:00
|
|
|
{
|
|
|
|
u32 data[4];
|
|
|
|
|
|
|
|
data[0] = in[0] ^ lk[4];
|
|
|
|
data[1] = in[1] ^ lk[5];
|
|
|
|
data[2] = in[2] ^ lk[6];
|
|
|
|
data[3] = in[3] ^ lk[7];
|
|
|
|
|
|
|
|
i_rnd128 (7);
|
|
|
|
i_rnd128 (6);
|
|
|
|
i_rnd128 (5);
|
|
|
|
i_rnd128 (4);
|
|
|
|
i_rnd128 (3);
|
|
|
|
i_rnd128 (2);
|
|
|
|
i_rnd128 (1);
|
|
|
|
i_rnd128 (0);
|
|
|
|
|
|
|
|
out[0] = data[2] ^ lk[0];
|
|
|
|
out[1] = data[3] ^ lk[1];
|
|
|
|
out[2] = data[0] ^ lk[2];
|
|
|
|
out[3] = data[1] ^ lk[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
// 256 bit key
|
|
|
|
|
|
|
|
#define g1_fun256(x) \
|
2015-12-04 15:47:52 +01:00
|
|
|
(mds (0, q40 (extract_byte (x, 3), sk)) ^ \
|
|
|
|
mds (1, q41 (extract_byte (x, 0), sk)) ^ \
|
|
|
|
mds (2, q42 (extract_byte (x, 1), sk)) ^ \
|
|
|
|
mds (3, q43 (extract_byte (x, 2), sk)))
|
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
#define g0_fun256(x) \
|
2015-12-04 15:47:52 +01:00
|
|
|
(mds (0, q40 (extract_byte (x, 0), sk)) ^ \
|
|
|
|
mds (1, q41 (extract_byte (x, 1), sk)) ^ \
|
|
|
|
mds (2, q42 (extract_byte (x, 2), sk)) ^ \
|
|
|
|
mds (3, q43 (extract_byte (x, 3), sk)))
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC u32 h_fun256 (u32 *sk, u32 *lk, const u32 x, const u32 *key)
|
2017-01-21 15:37:44 +01:00
|
|
|
{
|
|
|
|
u32 b0, b1, b2, b3;
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
b0 = extract_byte (x, 0);
|
|
|
|
b1 = extract_byte (x, 1);
|
|
|
|
b2 = extract_byte (x, 2);
|
|
|
|
b3 = extract_byte (x, 3);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
b0 = q (1, b0) ^ extract_byte (key[3], 0);
|
|
|
|
b1 = q (0, b1) ^ extract_byte (key[3], 1);
|
|
|
|
b2 = q (0, b2) ^ extract_byte (key[3], 2);
|
|
|
|
b3 = q (1, b3) ^ extract_byte (key[3], 3);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
b0 = q (1, b0) ^ extract_byte (key[2], 0);
|
|
|
|
b1 = q (1, b1) ^ extract_byte (key[2], 1);
|
|
|
|
b2 = q (0, b2) ^ extract_byte (key[2], 2);
|
|
|
|
b3 = q (0, b3) ^ extract_byte (key[2], 3);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
b0 = q (0, (q (0, b0) ^ extract_byte (key[1], 0))) ^ extract_byte (key[0], 0);
|
|
|
|
b1 = q (0, (q (1, b1) ^ extract_byte (key[1], 1))) ^ extract_byte (key[0], 1);
|
|
|
|
b2 = q (1, (q (0, b2) ^ extract_byte (key[1], 2))) ^ extract_byte (key[0], 2);
|
|
|
|
b3 = q (1, (q (1, b3) ^ extract_byte (key[1], 3))) ^ extract_byte (key[0], 3);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
return mds (0, b0) ^ mds (1, b1) ^ mds (2, b2) ^ mds (3, b3);
|
2015-12-04 15:47:52 +01:00
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC void twofish256_set_key (u32 *sk, u32 *lk, const u32 *ukey)
|
2015-12-04 15:47:52 +01:00
|
|
|
{
|
|
|
|
u32 me_key[4];
|
|
|
|
|
|
|
|
me_key[0] = ukey[0];
|
|
|
|
me_key[1] = ukey[2];
|
|
|
|
me_key[2] = ukey[4];
|
|
|
|
me_key[3] = ukey[6];
|
|
|
|
|
|
|
|
u32 mo_key[4];
|
|
|
|
|
|
|
|
mo_key[0] = ukey[1];
|
|
|
|
mo_key[1] = ukey[3];
|
|
|
|
mo_key[2] = ukey[5];
|
|
|
|
mo_key[3] = ukey[7];
|
|
|
|
|
|
|
|
sk[3] = mds_rem (me_key[0], mo_key[0]);
|
|
|
|
sk[2] = mds_rem (me_key[1], mo_key[1]);
|
|
|
|
sk[1] = mds_rem (me_key[2], mo_key[2]);
|
|
|
|
sk[0] = mds_rem (me_key[3], mo_key[3]);
|
|
|
|
|
2019-03-03 12:12:01 +01:00
|
|
|
for (int i = 0; i < 40; i += 2)
|
2015-12-04 15:47:52 +01:00
|
|
|
{
|
|
|
|
u32 a = 0x01010101 * i;
|
|
|
|
u32 b = 0x01010101 + a;
|
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
a = h_fun256 (sk, lk, a, me_key);
|
|
|
|
b = h_fun256 (sk, lk, b, mo_key);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
2019-03-23 22:15:38 +01:00
|
|
|
b = hc_rotl32_S (b, 8);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
|
|
|
lk[i + 0] = a + b;
|
2019-03-23 22:15:38 +01:00
|
|
|
lk[i + 1] = hc_rotl32_S (a + 2 * b, 9);
|
2015-12-04 15:47:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC void twofish256_encrypt (const u32 *sk, const u32 *lk, const u32 *in, u32 *out)
|
2015-12-04 15:47:52 +01:00
|
|
|
{
|
|
|
|
u32 data[4];
|
|
|
|
|
|
|
|
data[0] = in[0] ^ lk[0];
|
|
|
|
data[1] = in[1] ^ lk[1];
|
|
|
|
data[2] = in[2] ^ lk[2];
|
|
|
|
data[3] = in[3] ^ lk[3];
|
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
f_rnd256 (0);
|
|
|
|
f_rnd256 (1);
|
|
|
|
f_rnd256 (2);
|
|
|
|
f_rnd256 (3);
|
|
|
|
f_rnd256 (4);
|
|
|
|
f_rnd256 (5);
|
|
|
|
f_rnd256 (6);
|
|
|
|
f_rnd256 (7);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
|
|
|
out[0] = data[2] ^ lk[4];
|
|
|
|
out[1] = data[3] ^ lk[5];
|
|
|
|
out[2] = data[0] ^ lk[6];
|
|
|
|
out[3] = data[1] ^ lk[7];
|
|
|
|
}
|
|
|
|
|
2018-02-06 19:12:24 +01:00
|
|
|
DECLSPEC void twofish256_decrypt (const u32 *sk, const u32 *lk, const u32 *in, u32 *out)
|
2015-12-04 15:47:52 +01:00
|
|
|
{
|
|
|
|
u32 data[4];
|
|
|
|
|
|
|
|
data[0] = in[0] ^ lk[4];
|
|
|
|
data[1] = in[1] ^ lk[5];
|
|
|
|
data[2] = in[2] ^ lk[6];
|
|
|
|
data[3] = in[3] ^ lk[7];
|
|
|
|
|
2017-01-21 15:37:44 +01:00
|
|
|
i_rnd256 (7);
|
|
|
|
i_rnd256 (6);
|
|
|
|
i_rnd256 (5);
|
|
|
|
i_rnd256 (4);
|
|
|
|
i_rnd256 (3);
|
|
|
|
i_rnd256 (2);
|
|
|
|
i_rnd256 (1);
|
|
|
|
i_rnd256 (0);
|
2015-12-04 15:47:52 +01:00
|
|
|
|
|
|
|
out[0] = data[2] ^ lk[0];
|
|
|
|
out[1] = data[3] ^ lk[1];
|
|
|
|
out[2] = data[0] ^ lk[2];
|
|
|
|
out[3] = data[1] ^ lk[3];
|
|
|
|
}
|