Bring stuff up2date and added own stuff
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
/* Based on idea.cpp - originally written and placed in the public domain by Wei Dai
|
||||
https://github.com/weidai11/cryptopp/blob/master/idea.cpp
|
||||
|
||||
Patents should be expired. On 2017-10-16 wikipedia says:
|
||||
https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
|
||||
|
||||
A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990,
|
||||
then an international patent application was filed under the Patent Cooperation Treaty on
|
||||
May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands,
|
||||
Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European
|
||||
patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011),
|
||||
the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012)
|
||||
and Japan (JP 3225440) (expired May 16, 2011).
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_IDEA
|
||||
|
||||
const struct ltc_cipher_descriptor idea_desc = {
|
||||
"idea",
|
||||
24, /* cipher_ID */
|
||||
16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */
|
||||
&idea_setup,
|
||||
&idea_ecb_encrypt,
|
||||
&idea_ecb_decrypt,
|
||||
&idea_test,
|
||||
&idea_done,
|
||||
&idea_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
typedef unsigned short int ushort16;
|
||||
|
||||
#define _LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */
|
||||
#define _HIGH16(x) ((x)>>16)
|
||||
#define _MUL(a,b) { \
|
||||
ulong32 p = (ulong32)_LOW16(a) * b; \
|
||||
if (p) { \
|
||||
p = _LOW16(p) - _HIGH16(p); \
|
||||
a = (ushort16)p - (ushort16)_HIGH16(p); \
|
||||
} \
|
||||
else \
|
||||
a = 1 - a - b; \
|
||||
}
|
||||
#define _STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); }
|
||||
#define _LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); }
|
||||
|
||||
static ushort16 _mul_inv(ushort16 x)
|
||||
{
|
||||
ushort16 y = x;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 15; i++) {
|
||||
_MUL(y, _LOW16(y));
|
||||
_MUL(y, x);
|
||||
}
|
||||
return _LOW16(y);
|
||||
}
|
||||
|
||||
static ushort16 _add_inv(ushort16 x)
|
||||
{
|
||||
return _LOW16(0 - x);
|
||||
}
|
||||
|
||||
static int _setup_key(const unsigned char *key, symmetric_key *skey)
|
||||
{
|
||||
int i, j;
|
||||
ushort16 *e_key = skey->idea.ek;
|
||||
ushort16 *d_key = skey->idea.dk;
|
||||
|
||||
/* prepare enc key */
|
||||
for (i = 0; i < 8; i++) {
|
||||
_LOAD16(e_key[i], key + 2 * i);
|
||||
}
|
||||
for (; i < LTC_IDEA_KEYLEN; i++) {
|
||||
j = (i - i % 8) - 8;
|
||||
e_key[i] = _LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7));
|
||||
}
|
||||
|
||||
/* prepare dec key */
|
||||
for (i = 0; i < LTC_IDEA_ROUNDS; i++) {
|
||||
d_key[i*6+0] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]);
|
||||
d_key[i*6+1] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]);
|
||||
d_key[i*6+2] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]);
|
||||
d_key[i*6+3] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]);
|
||||
d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4];
|
||||
d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5];
|
||||
}
|
||||
d_key[i*6+0] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]);
|
||||
d_key[i*6+1] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]);
|
||||
d_key[i*6+2] = _add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]);
|
||||
d_key[i*6+3] = _mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]);
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int _process_block(const unsigned char *in, unsigned char *out, ushort16 *m_key)
|
||||
{
|
||||
int i;
|
||||
ushort16 x0, x1, x2, x3, t0, t1;
|
||||
|
||||
_LOAD16(x0, in + 0);
|
||||
_LOAD16(x1, in + 2);
|
||||
_LOAD16(x2, in + 4);
|
||||
_LOAD16(x3, in + 6);
|
||||
|
||||
for (i = 0; i < LTC_IDEA_ROUNDS; i++) {
|
||||
_MUL(x0, m_key[i*6+0]);
|
||||
x1 += m_key[i*6+1];
|
||||
x2 += m_key[i*6+2];
|
||||
_MUL(x3, m_key[i*6+3]);
|
||||
t0 = x0^x2;
|
||||
_MUL(t0, m_key[i*6+4]);
|
||||
t1 = t0 + (x1^x3);
|
||||
_MUL(t1, m_key[i*6+5]);
|
||||
t0 += t1;
|
||||
x0 ^= t1;
|
||||
x3 ^= t0;
|
||||
t0 ^= x1;
|
||||
x1 = x2^t1;
|
||||
x2 = t0;
|
||||
}
|
||||
|
||||
_MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]);
|
||||
x2 += m_key[LTC_IDEA_ROUNDS*6+1];
|
||||
x1 += m_key[LTC_IDEA_ROUNDS*6+2];
|
||||
_MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]);
|
||||
|
||||
_STORE16(x0, out + 0);
|
||||
_STORE16(x2, out + 2);
|
||||
_STORE16(x1, out + 4);
|
||||
_STORE16(x3, out + 6);
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
|
||||
{
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
if (num_rounds != 0 && num_rounds != 8) return CRYPT_INVALID_ROUNDS;
|
||||
if (keylen != 16) return CRYPT_INVALID_KEYSIZE;
|
||||
|
||||
return _setup_key(key, skey);
|
||||
}
|
||||
|
||||
int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
|
||||
{
|
||||
int err = _process_block(pt, ct, skey->idea.ek);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
burn_stack(sizeof(ushort16) * 6 + sizeof(int));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
|
||||
{
|
||||
int err = _process_block(ct, pt, skey->idea.dk);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
burn_stack(sizeof(ushort16) * 6 + sizeof(int));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
void idea_done(symmetric_key *skey)
|
||||
{
|
||||
LTC_UNUSED_PARAM(skey);
|
||||
}
|
||||
|
||||
int idea_keysize(int *keysize)
|
||||
{
|
||||
LTC_ARGCHK(keysize != NULL);
|
||||
if (*keysize < 16) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
*keysize = 16;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int idea_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
unsigned char key[16], pt[8], ct[8];
|
||||
} tests[] = {
|
||||
{
|
||||
/* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F }
|
||||
},
|
||||
{
|
||||
/* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 }
|
||||
},
|
||||
{
|
||||
/* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 }
|
||||
},
|
||||
{
|
||||
/* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA }
|
||||
},
|
||||
{
|
||||
/* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
/* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C }
|
||||
},
|
||||
};
|
||||
|
||||
unsigned char buf[2][8];
|
||||
symmetric_key key;
|
||||
int err, x;
|
||||
|
||||
if (sizeof(ushort16) != 2) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
|
||||
for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
|
||||
if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,727 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
/* Based on serpent.cpp - originally written and placed in the public domain by Wei Dai
|
||||
https://github.com/weidai11/cryptopp/blob/master/serpent.cpp
|
||||
|
||||
On 2017-10-16 wikipedia says:
|
||||
"The Serpent cipher algorithm is in the public domain and has not been patented."
|
||||
https://en.wikipedia.org/wiki/Serpent_(cipher)
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_SERPENT
|
||||
|
||||
const struct ltc_cipher_descriptor serpent_desc = {
|
||||
"serpent",
|
||||
25, /* cipher_ID */
|
||||
16, 32, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */
|
||||
&serpent_setup,
|
||||
&serpent_ecb_encrypt,
|
||||
&serpent_ecb_decrypt,
|
||||
&serpent_test,
|
||||
&serpent_done,
|
||||
&serpent_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/* linear transformation */
|
||||
#define _LT(i,a,b,c,d,e) { \
|
||||
a = ROLc(a, 13); \
|
||||
c = ROLc(c, 3); \
|
||||
d = ROLc(d ^ c ^ (a << 3), 7); \
|
||||
b = ROLc(b ^ a ^ c, 1); \
|
||||
a = ROLc(a ^ b ^ d, 5); \
|
||||
c = ROLc(c ^ d ^ (b << 7), 22); \
|
||||
}
|
||||
|
||||
/* inverse linear transformation */
|
||||
#define _ILT(i,a,b,c,d,e) { \
|
||||
c = RORc(c, 22); \
|
||||
a = RORc(a, 5); \
|
||||
c ^= d ^ (b << 7); \
|
||||
a ^= b ^ d; \
|
||||
b = RORc(b, 1); \
|
||||
d = RORc(d, 7) ^ c ^ (a << 3); \
|
||||
b ^= a ^ c; \
|
||||
c = RORc(c, 3); \
|
||||
a = RORc(a, 13); \
|
||||
}
|
||||
|
||||
/* order of output from S-box functions */
|
||||
#define _beforeS0(f) f(0,a,b,c,d,e)
|
||||
#define _afterS0(f) f(1,b,e,c,a,d)
|
||||
#define _afterS1(f) f(2,c,b,a,e,d)
|
||||
#define _afterS2(f) f(3,a,e,b,d,c)
|
||||
#define _afterS3(f) f(4,e,b,d,c,a)
|
||||
#define _afterS4(f) f(5,b,a,e,c,d)
|
||||
#define _afterS5(f) f(6,a,c,b,e,d)
|
||||
#define _afterS6(f) f(7,a,c,d,b,e)
|
||||
#define _afterS7(f) f(8,d,e,b,a,c)
|
||||
|
||||
/* order of output from inverse S-box functions */
|
||||
#define _beforeI7(f) f(8,a,b,c,d,e)
|
||||
#define _afterI7(f) f(7,d,a,b,e,c)
|
||||
#define _afterI6(f) f(6,a,b,c,e,d)
|
||||
#define _afterI5(f) f(5,b,d,e,c,a)
|
||||
#define _afterI4(f) f(4,b,c,e,a,d)
|
||||
#define _afterI3(f) f(3,a,b,e,c,d)
|
||||
#define _afterI2(f) f(2,b,d,e,c,a)
|
||||
#define _afterI1(f) f(1,a,b,c,e,d)
|
||||
#define _afterI0(f) f(0,a,d,b,e,c)
|
||||
|
||||
/* The instruction sequences for the S-box functions
|
||||
* come from Dag Arne Osvik's paper "Speeding up Serpent".
|
||||
*/
|
||||
|
||||
#define _S0(i, r0, r1, r2, r3, r4) { \
|
||||
r3 ^= r0; \
|
||||
r4 = r1; \
|
||||
r1 &= r3; \
|
||||
r4 ^= r2; \
|
||||
r1 ^= r0; \
|
||||
r0 |= r3; \
|
||||
r0 ^= r4; \
|
||||
r4 ^= r3; \
|
||||
r3 ^= r2; \
|
||||
r2 |= r1; \
|
||||
r2 ^= r4; \
|
||||
r4 = ~r4; \
|
||||
r4 |= r1; \
|
||||
r1 ^= r3; \
|
||||
r1 ^= r4; \
|
||||
r3 |= r0; \
|
||||
r1 ^= r3; \
|
||||
r4 ^= r3; \
|
||||
}
|
||||
|
||||
#define _I0(i, r0, r1, r2, r3, r4) { \
|
||||
r2 = ~r2; \
|
||||
r4 = r1; \
|
||||
r1 |= r0; \
|
||||
r4 = ~r4; \
|
||||
r1 ^= r2; \
|
||||
r2 |= r4; \
|
||||
r1 ^= r3; \
|
||||
r0 ^= r4; \
|
||||
r2 ^= r0; \
|
||||
r0 &= r3; \
|
||||
r4 ^= r0; \
|
||||
r0 |= r1; \
|
||||
r0 ^= r2; \
|
||||
r3 ^= r4; \
|
||||
r2 ^= r1; \
|
||||
r3 ^= r0; \
|
||||
r3 ^= r1; \
|
||||
r2 &= r3; \
|
||||
r4 ^= r2; \
|
||||
}
|
||||
|
||||
#define _S1(i, r0, r1, r2, r3, r4) { \
|
||||
r0 = ~r0; \
|
||||
r2 = ~r2; \
|
||||
r4 = r0; \
|
||||
r0 &= r1; \
|
||||
r2 ^= r0; \
|
||||
r0 |= r3; \
|
||||
r3 ^= r2; \
|
||||
r1 ^= r0; \
|
||||
r0 ^= r4; \
|
||||
r4 |= r1; \
|
||||
r1 ^= r3; \
|
||||
r2 |= r0; \
|
||||
r2 &= r4; \
|
||||
r0 ^= r1; \
|
||||
r1 &= r2; \
|
||||
r1 ^= r0; \
|
||||
r0 &= r2; \
|
||||
r0 ^= r4; \
|
||||
}
|
||||
|
||||
#define _I1(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r1; \
|
||||
r1 ^= r3; \
|
||||
r3 &= r1; \
|
||||
r4 ^= r2; \
|
||||
r3 ^= r0; \
|
||||
r0 |= r1; \
|
||||
r2 ^= r3; \
|
||||
r0 ^= r4; \
|
||||
r0 |= r2; \
|
||||
r1 ^= r3; \
|
||||
r0 ^= r1; \
|
||||
r1 |= r3; \
|
||||
r1 ^= r0; \
|
||||
r4 = ~r4; \
|
||||
r4 ^= r1; \
|
||||
r1 |= r0; \
|
||||
r1 ^= r0; \
|
||||
r1 |= r4; \
|
||||
r3 ^= r1; \
|
||||
}
|
||||
|
||||
#define _S2(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r0; \
|
||||
r0 &= r2; \
|
||||
r0 ^= r3; \
|
||||
r2 ^= r1; \
|
||||
r2 ^= r0; \
|
||||
r3 |= r4; \
|
||||
r3 ^= r1; \
|
||||
r4 ^= r2; \
|
||||
r1 = r3; \
|
||||
r3 |= r4; \
|
||||
r3 ^= r0; \
|
||||
r0 &= r1; \
|
||||
r4 ^= r0; \
|
||||
r1 ^= r3; \
|
||||
r1 ^= r4; \
|
||||
r4 = ~r4; \
|
||||
}
|
||||
|
||||
#define _I2(i, r0, r1, r2, r3, r4) { \
|
||||
r2 ^= r3; \
|
||||
r3 ^= r0; \
|
||||
r4 = r3; \
|
||||
r3 &= r2; \
|
||||
r3 ^= r1; \
|
||||
r1 |= r2; \
|
||||
r1 ^= r4; \
|
||||
r4 &= r3; \
|
||||
r2 ^= r3; \
|
||||
r4 &= r0; \
|
||||
r4 ^= r2; \
|
||||
r2 &= r1; \
|
||||
r2 |= r0; \
|
||||
r3 = ~r3; \
|
||||
r2 ^= r3; \
|
||||
r0 ^= r3; \
|
||||
r0 &= r1; \
|
||||
r3 ^= r4; \
|
||||
r3 ^= r0; \
|
||||
}
|
||||
|
||||
#define _S3(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r0; \
|
||||
r0 |= r3; \
|
||||
r3 ^= r1; \
|
||||
r1 &= r4; \
|
||||
r4 ^= r2; \
|
||||
r2 ^= r3; \
|
||||
r3 &= r0; \
|
||||
r4 |= r1; \
|
||||
r3 ^= r4; \
|
||||
r0 ^= r1; \
|
||||
r4 &= r0; \
|
||||
r1 ^= r3; \
|
||||
r4 ^= r2; \
|
||||
r1 |= r0; \
|
||||
r1 ^= r2; \
|
||||
r0 ^= r3; \
|
||||
r2 = r1; \
|
||||
r1 |= r3; \
|
||||
r1 ^= r0; \
|
||||
}
|
||||
|
||||
#define _I3(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r2; \
|
||||
r2 ^= r1; \
|
||||
r1 &= r2; \
|
||||
r1 ^= r0; \
|
||||
r0 &= r4; \
|
||||
r4 ^= r3; \
|
||||
r3 |= r1; \
|
||||
r3 ^= r2; \
|
||||
r0 ^= r4; \
|
||||
r2 ^= r0; \
|
||||
r0 |= r3; \
|
||||
r0 ^= r1; \
|
||||
r4 ^= r2; \
|
||||
r2 &= r3; \
|
||||
r1 |= r3; \
|
||||
r1 ^= r2; \
|
||||
r4 ^= r0; \
|
||||
r2 ^= r4; \
|
||||
}
|
||||
|
||||
#define _S4(i, r0, r1, r2, r3, r4) { \
|
||||
r1 ^= r3; \
|
||||
r3 = ~r3; \
|
||||
r2 ^= r3; \
|
||||
r3 ^= r0; \
|
||||
r4 = r1; \
|
||||
r1 &= r3; \
|
||||
r1 ^= r2; \
|
||||
r4 ^= r3; \
|
||||
r0 ^= r4; \
|
||||
r2 &= r4; \
|
||||
r2 ^= r0; \
|
||||
r0 &= r1; \
|
||||
r3 ^= r0; \
|
||||
r4 |= r1; \
|
||||
r4 ^= r0; \
|
||||
r0 |= r3; \
|
||||
r0 ^= r2; \
|
||||
r2 &= r3; \
|
||||
r0 = ~r0; \
|
||||
r4 ^= r2; \
|
||||
}
|
||||
|
||||
#define _I4(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r2; \
|
||||
r2 &= r3; \
|
||||
r2 ^= r1; \
|
||||
r1 |= r3; \
|
||||
r1 &= r0; \
|
||||
r4 ^= r2; \
|
||||
r4 ^= r1; \
|
||||
r1 &= r2; \
|
||||
r0 = ~r0; \
|
||||
r3 ^= r4; \
|
||||
r1 ^= r3; \
|
||||
r3 &= r0; \
|
||||
r3 ^= r2; \
|
||||
r0 ^= r1; \
|
||||
r2 &= r0; \
|
||||
r3 ^= r0; \
|
||||
r2 ^= r4; \
|
||||
r2 |= r3; \
|
||||
r3 ^= r0; \
|
||||
r2 ^= r1; \
|
||||
}
|
||||
|
||||
#define _S5(i, r0, r1, r2, r3, r4) { \
|
||||
r0 ^= r1; \
|
||||
r1 ^= r3; \
|
||||
r3 = ~r3; \
|
||||
r4 = r1; \
|
||||
r1 &= r0; \
|
||||
r2 ^= r3; \
|
||||
r1 ^= r2; \
|
||||
r2 |= r4; \
|
||||
r4 ^= r3; \
|
||||
r3 &= r1; \
|
||||
r3 ^= r0; \
|
||||
r4 ^= r1; \
|
||||
r4 ^= r2; \
|
||||
r2 ^= r0; \
|
||||
r0 &= r3; \
|
||||
r2 = ~r2; \
|
||||
r0 ^= r4; \
|
||||
r4 |= r3; \
|
||||
r2 ^= r4; \
|
||||
}
|
||||
|
||||
#define _I5(i, r0, r1, r2, r3, r4) { \
|
||||
r1 = ~r1; \
|
||||
r4 = r3; \
|
||||
r2 ^= r1; \
|
||||
r3 |= r0; \
|
||||
r3 ^= r2; \
|
||||
r2 |= r1; \
|
||||
r2 &= r0; \
|
||||
r4 ^= r3; \
|
||||
r2 ^= r4; \
|
||||
r4 |= r0; \
|
||||
r4 ^= r1; \
|
||||
r1 &= r2; \
|
||||
r1 ^= r3; \
|
||||
r4 ^= r2; \
|
||||
r3 &= r4; \
|
||||
r4 ^= r1; \
|
||||
r3 ^= r0; \
|
||||
r3 ^= r4; \
|
||||
r4 = ~r4; \
|
||||
}
|
||||
|
||||
#define _S6(i, r0, r1, r2, r3, r4) { \
|
||||
r2 = ~r2; \
|
||||
r4 = r3; \
|
||||
r3 &= r0; \
|
||||
r0 ^= r4; \
|
||||
r3 ^= r2; \
|
||||
r2 |= r4; \
|
||||
r1 ^= r3; \
|
||||
r2 ^= r0; \
|
||||
r0 |= r1; \
|
||||
r2 ^= r1; \
|
||||
r4 ^= r0; \
|
||||
r0 |= r3; \
|
||||
r0 ^= r2; \
|
||||
r4 ^= r3; \
|
||||
r4 ^= r0; \
|
||||
r3 = ~r3; \
|
||||
r2 &= r4; \
|
||||
r2 ^= r3; \
|
||||
}
|
||||
|
||||
#define _I6(i, r0, r1, r2, r3, r4) { \
|
||||
r0 ^= r2; \
|
||||
r4 = r2; \
|
||||
r2 &= r0; \
|
||||
r4 ^= r3; \
|
||||
r2 = ~r2; \
|
||||
r3 ^= r1; \
|
||||
r2 ^= r3; \
|
||||
r4 |= r0; \
|
||||
r0 ^= r2; \
|
||||
r3 ^= r4; \
|
||||
r4 ^= r1; \
|
||||
r1 &= r3; \
|
||||
r1 ^= r0; \
|
||||
r0 ^= r3; \
|
||||
r0 |= r2; \
|
||||
r3 ^= r1; \
|
||||
r4 ^= r0; \
|
||||
}
|
||||
|
||||
#define _S7(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r2; \
|
||||
r2 &= r1; \
|
||||
r2 ^= r3; \
|
||||
r3 &= r1; \
|
||||
r4 ^= r2; \
|
||||
r2 ^= r1; \
|
||||
r1 ^= r0; \
|
||||
r0 |= r4; \
|
||||
r0 ^= r2; \
|
||||
r3 ^= r1; \
|
||||
r2 ^= r3; \
|
||||
r3 &= r0; \
|
||||
r3 ^= r4; \
|
||||
r4 ^= r2; \
|
||||
r2 &= r0; \
|
||||
r4 = ~r4; \
|
||||
r2 ^= r4; \
|
||||
r4 &= r0; \
|
||||
r1 ^= r3; \
|
||||
r4 ^= r1; \
|
||||
}
|
||||
|
||||
#define _I7(i, r0, r1, r2, r3, r4) { \
|
||||
r4 = r2; \
|
||||
r2 ^= r0; \
|
||||
r0 &= r3; \
|
||||
r2 = ~r2; \
|
||||
r4 |= r3; \
|
||||
r3 ^= r1; \
|
||||
r1 |= r0; \
|
||||
r0 ^= r2; \
|
||||
r2 &= r4; \
|
||||
r1 ^= r2; \
|
||||
r2 ^= r0; \
|
||||
r0 |= r2; \
|
||||
r3 &= r4; \
|
||||
r0 ^= r3; \
|
||||
r4 ^= r1; \
|
||||
r3 ^= r4; \
|
||||
r4 |= r0; \
|
||||
r3 ^= r2; \
|
||||
r4 ^= r2; \
|
||||
}
|
||||
|
||||
/* key xor */
|
||||
#define _KX(r, a, b, c, d, e) { \
|
||||
a ^= k[4 * r + 0]; \
|
||||
b ^= k[4 * r + 1]; \
|
||||
c ^= k[4 * r + 2]; \
|
||||
d ^= k[4 * r + 3]; \
|
||||
}
|
||||
|
||||
#define _LK(r, a, b, c, d, e) { \
|
||||
a = k[(8-r)*4 + 0]; \
|
||||
b = k[(8-r)*4 + 1]; \
|
||||
c = k[(8-r)*4 + 2]; \
|
||||
d = k[(8-r)*4 + 3]; \
|
||||
}
|
||||
|
||||
#define _SK(r, a, b, c, d, e) { \
|
||||
k[(8-r)*4 + 4] = a; \
|
||||
k[(8-r)*4 + 5] = b; \
|
||||
k[(8-r)*4 + 6] = c; \
|
||||
k[(8-r)*4 + 7] = d; \
|
||||
}
|
||||
|
||||
static int _setup_key(const unsigned char *key, int keylen, int rounds, ulong32 *k)
|
||||
{
|
||||
int i;
|
||||
ulong32 t;
|
||||
ulong32 k0[8] = { 0 }; /* zero-initialize */
|
||||
ulong32 a, b, c, d, e;
|
||||
|
||||
for (i = 0; i < 8 && i < keylen/4; ++i) {
|
||||
LOAD32L(k0[i], key + i * 4);
|
||||
}
|
||||
if (keylen < 32) {
|
||||
k0[keylen/4] |= (ulong32)1 << ((keylen%4)*8);
|
||||
}
|
||||
|
||||
t = k0[7];
|
||||
for (i = 0; i < 8; ++i) {
|
||||
k[i] = k0[i] = t = ROLc(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11);
|
||||
}
|
||||
for (i = 8; i < 4*(rounds+1); ++i) {
|
||||
k[i] = t = ROLc(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11);
|
||||
}
|
||||
k -= 20;
|
||||
|
||||
for (i = 0; i < rounds/8; i++) {
|
||||
_afterS2(_LK); _afterS2(_S3); _afterS3(_SK);
|
||||
_afterS1(_LK); _afterS1(_S2); _afterS2(_SK);
|
||||
_afterS0(_LK); _afterS0(_S1); _afterS1(_SK);
|
||||
_beforeS0(_LK); _beforeS0(_S0); _afterS0(_SK);
|
||||
k += 8*4;
|
||||
_afterS6(_LK); _afterS6(_S7); _afterS7(_SK);
|
||||
_afterS5(_LK); _afterS5(_S6); _afterS6(_SK);
|
||||
_afterS4(_LK); _afterS4(_S5); _afterS5(_SK);
|
||||
_afterS3(_LK); _afterS3(_S4); _afterS4(_SK);
|
||||
}
|
||||
_afterS2(_LK); _afterS2(_S3); _afterS3(_SK);
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int _enc_block(const unsigned char *in, unsigned char *out, ulong32 *k)
|
||||
{
|
||||
ulong32 a, b, c, d, e;
|
||||
unsigned int i = 1;
|
||||
|
||||
LOAD32L(a, in + 0);
|
||||
LOAD32L(b, in + 4);
|
||||
LOAD32L(c, in + 8);
|
||||
LOAD32L(d, in + 12);
|
||||
|
||||
do {
|
||||
_beforeS0(_KX); _beforeS0(_S0); _afterS0(_LT);
|
||||
_afterS0(_KX); _afterS0(_S1); _afterS1(_LT);
|
||||
_afterS1(_KX); _afterS1(_S2); _afterS2(_LT);
|
||||
_afterS2(_KX); _afterS2(_S3); _afterS3(_LT);
|
||||
_afterS3(_KX); _afterS3(_S4); _afterS4(_LT);
|
||||
_afterS4(_KX); _afterS4(_S5); _afterS5(_LT);
|
||||
_afterS5(_KX); _afterS5(_S6); _afterS6(_LT);
|
||||
_afterS6(_KX); _afterS6(_S7);
|
||||
|
||||
if (i == 4) break;
|
||||
|
||||
++i;
|
||||
c = b;
|
||||
b = e;
|
||||
e = d;
|
||||
d = a;
|
||||
a = e;
|
||||
k += 32;
|
||||
_beforeS0(_LT);
|
||||
} while (1);
|
||||
|
||||
_afterS7(_KX);
|
||||
|
||||
STORE32L(d, out + 0);
|
||||
STORE32L(e, out + 4);
|
||||
STORE32L(b, out + 8);
|
||||
STORE32L(a, out + 12);
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int _dec_block(const unsigned char *in, unsigned char *out, ulong32 *k)
|
||||
{
|
||||
ulong32 a, b, c, d, e;
|
||||
unsigned int i;
|
||||
|
||||
LOAD32L(a, in + 0);
|
||||
LOAD32L(b, in + 4);
|
||||
LOAD32L(c, in + 8);
|
||||
LOAD32L(d, in + 12);
|
||||
e = 0; LTC_UNUSED_PARAM(e); /* avoid scan-build warning */
|
||||
i = 4;
|
||||
k += 96;
|
||||
|
||||
_beforeI7(_KX);
|
||||
goto start;
|
||||
|
||||
do {
|
||||
c = b;
|
||||
b = d;
|
||||
d = e;
|
||||
k -= 32;
|
||||
_beforeI7(_ILT);
|
||||
start:
|
||||
_beforeI7(_I7); _afterI7(_KX);
|
||||
_afterI7(_ILT); _afterI7(_I6); _afterI6(_KX);
|
||||
_afterI6(_ILT); _afterI6(_I5); _afterI5(_KX);
|
||||
_afterI5(_ILT); _afterI5(_I4); _afterI4(_KX);
|
||||
_afterI4(_ILT); _afterI4(_I3); _afterI3(_KX);
|
||||
_afterI3(_ILT); _afterI3(_I2); _afterI2(_KX);
|
||||
_afterI2(_ILT); _afterI2(_I1); _afterI1(_KX);
|
||||
_afterI1(_ILT); _afterI1(_I0); _afterI0(_KX);
|
||||
} while (--i != 0);
|
||||
|
||||
STORE32L(a, out + 0);
|
||||
STORE32L(d, out + 4);
|
||||
STORE32L(b, out + 8);
|
||||
STORE32L(e, out + 12);
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
|
||||
{
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
if (num_rounds != 0 && num_rounds != 32) return CRYPT_INVALID_ROUNDS;
|
||||
if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE;
|
||||
|
||||
err = _setup_key(key, keylen, 32, skey->serpent.k);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
burn_stack(sizeof(ulong32) * 14 + sizeof(int));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
|
||||
{
|
||||
int err = _enc_block(pt, ct, skey->serpent.k);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
burn_stack(sizeof(ulong32) * 5 + sizeof(int));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
|
||||
{
|
||||
int err = _dec_block(ct, pt, skey->serpent.k);
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
burn_stack(sizeof(ulong32) * 5 + sizeof(int));
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
void serpent_done(symmetric_key *skey)
|
||||
{
|
||||
LTC_UNUSED_PARAM(skey);
|
||||
}
|
||||
|
||||
int serpent_keysize(int *keysize)
|
||||
{
|
||||
LTC_ARGCHK(keysize != NULL);
|
||||
|
||||
if (*keysize >= 32) { *keysize = 32; }
|
||||
else if (*keysize >= 24) { *keysize = 24; }
|
||||
else if (*keysize >= 16) { *keysize = 16; }
|
||||
else return CRYPT_INVALID_KEYSIZE;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int serpent_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
unsigned char key[32];
|
||||
int keylen;
|
||||
unsigned char pt[16], ct[16];
|
||||
} tests[] = {
|
||||
{
|
||||
/* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 32,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0xA2,0x23,0xAA,0x12,0x88,0x46,0x3C,0x0E,0x2B,0xE3,0x8E,0xBD,0x82,0x56,0x16,0xC0}
|
||||
},
|
||||
{
|
||||
/* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 32,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0xEA,0xE1,0xD4,0x05,0x57,0x01,0x74,0xDF,0x7D,0xF2,0xF9,0x96,0x6D,0x50,0x91,0x59}
|
||||
},
|
||||
{
|
||||
/* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 32,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0x65,0xF3,0x76,0x84,0x47,0x1E,0x92,0x1D,0xC8,0xA3,0x0F,0x45,0xB4,0x3C,0x44,0x99}
|
||||
},
|
||||
{
|
||||
/* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 24,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0x9E,0x27,0x4E,0xAD,0x9B,0x73,0x7B,0xB2,0x1E,0xFC,0xFC,0xA5,0x48,0x60,0x26,0x89}
|
||||
},
|
||||
{
|
||||
/* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 24,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0x92,0xFC,0x8E,0x51,0x03,0x99,0xE4,0x6A,0x04,0x1B,0xF3,0x65,0xE7,0xB3,0xAE,0x82}
|
||||
},
|
||||
{
|
||||
/* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 24,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0x5E,0x0D,0xA3,0x86,0xC4,0x6A,0xD4,0x93,0xDE,0xA2,0x03,0xFD,0xC6,0xF5,0x7D,0x70}
|
||||
},
|
||||
{
|
||||
/* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 16,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0x26,0x4E,0x54,0x81,0xEF,0xF4,0x2A,0x46,0x06,0xAB,0xDA,0x06,0xC0,0xBF,0xDA,0x3D}
|
||||
},
|
||||
{
|
||||
/* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 16,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0x4A,0x23,0x1B,0x3B,0xC7,0x27,0x99,0x34,0x07,0xAC,0x6E,0xC8,0x35,0x0E,0x85,0x24}
|
||||
},
|
||||
{
|
||||
/* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* keylen */ 16,
|
||||
/* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
/* ct */ {0xE0,0x32,0x69,0xF9,0xE9,0xFD,0x85,0x3C,0x7D,0x81,0x56,0xDF,0x14,0xB9,0x8D,0x56}
|
||||
}
|
||||
};
|
||||
|
||||
unsigned char buf[2][16];
|
||||
symmetric_key key;
|
||||
int err, x;
|
||||
|
||||
for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
|
||||
if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if ((err = serpent_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if (compare_testvector(buf[0], 16, tests[x].ct, 16, "SERPENT Encrypt", x)) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
if ((err = serpent_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if (compare_testvector(buf[1], 16, tests[x].pt, 16, "SERPENT Decrypt", x)) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
Reference in New Issue
Block a user