mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-10 23:08:05 -05:00
Import code from previous AssetBuilder version
This commit is contained in:
495
thirdparty/libtomcrypt/ciphers/safer/safer.c
vendored
Normal file
495
thirdparty/libtomcrypt/ciphers/safer/safer.c
vendored
Normal file
@ -0,0 +1,495 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FILE: safer.c
|
||||
*
|
||||
* LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption
|
||||
* Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128,
|
||||
* LTC_SAFER SK-64 and LTC_SAFER SK-128.
|
||||
*
|
||||
* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch)
|
||||
* Signal and Information Processing Laboratory
|
||||
* Swiss Federal Institute of Technology
|
||||
* CH-8092 Zuerich, Switzerland
|
||||
*
|
||||
* DATE: September 9, 1995
|
||||
*
|
||||
* CHANGE HISTORY:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_SAFER
|
||||
|
||||
#define __LTC_SAFER_TAB_C__
|
||||
#include "safer_tab.c"
|
||||
|
||||
const struct ltc_cipher_descriptor safer_k64_desc = {
|
||||
"safer-k64",
|
||||
8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS,
|
||||
&safer_k64_setup,
|
||||
&safer_ecb_encrypt,
|
||||
&safer_ecb_decrypt,
|
||||
&safer_k64_test,
|
||||
&safer_done,
|
||||
&safer_64_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
},
|
||||
|
||||
safer_sk64_desc = {
|
||||
"safer-sk64",
|
||||
9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS,
|
||||
&safer_sk64_setup,
|
||||
&safer_ecb_encrypt,
|
||||
&safer_ecb_decrypt,
|
||||
&safer_sk64_test,
|
||||
&safer_done,
|
||||
&safer_64_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
},
|
||||
|
||||
safer_k128_desc = {
|
||||
"safer-k128",
|
||||
10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS,
|
||||
&safer_k128_setup,
|
||||
&safer_ecb_encrypt,
|
||||
&safer_ecb_decrypt,
|
||||
&safer_sk128_test,
|
||||
&safer_done,
|
||||
&safer_128_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
},
|
||||
|
||||
safer_sk128_desc = {
|
||||
"safer-sk128",
|
||||
11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS,
|
||||
&safer_sk128_setup,
|
||||
&safer_ecb_encrypt,
|
||||
&safer_ecb_decrypt,
|
||||
&safer_sk128_test,
|
||||
&safer_done,
|
||||
&safer_128_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/******************* Constants ************************************************/
|
||||
/* #define TAB_LEN 256 */
|
||||
|
||||
/******************* Assertions ***********************************************/
|
||||
|
||||
/******************* Macros ***************************************************/
|
||||
#define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\
|
||||
|(unsigned int)((x) & 0xFF) >> (8 - (n))))
|
||||
#define EXP(x) safer_ebox[(x) & 0xFF]
|
||||
#define LOG(x) safer_lbox[(x) & 0xFF]
|
||||
#define PHT(x, y) { y += x; x += y; }
|
||||
#define IPHT(x, y) { x -= y; y -= x; }
|
||||
|
||||
/******************* Types ****************************************************/
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static void _Safer_Expand_Userkey(const unsigned char *userkey_1,
|
||||
const unsigned char *userkey_2,
|
||||
unsigned int nof_rounds,
|
||||
int strengthened,
|
||||
safer_key_t key)
|
||||
#else
|
||||
static void Safer_Expand_Userkey(const unsigned char *userkey_1,
|
||||
const unsigned char *userkey_2,
|
||||
unsigned int nof_rounds,
|
||||
int strengthened,
|
||||
safer_key_t key)
|
||||
#endif
|
||||
{ unsigned int i, j, k;
|
||||
unsigned char ka[LTC_SAFER_BLOCK_LEN + 1];
|
||||
unsigned char kb[LTC_SAFER_BLOCK_LEN + 1];
|
||||
|
||||
if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds)
|
||||
nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS;
|
||||
*key++ = (unsigned char)nof_rounds;
|
||||
ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0;
|
||||
kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0;
|
||||
k = 0;
|
||||
for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
|
||||
ka[j] = ROL8(userkey_1[j], 5);
|
||||
ka[LTC_SAFER_BLOCK_LEN] ^= ka[j];
|
||||
kb[j] = *key++ = userkey_2[j];
|
||||
kb[LTC_SAFER_BLOCK_LEN] ^= kb[j];
|
||||
}
|
||||
for (i = 1; i <= nof_rounds; i++) {
|
||||
for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) {
|
||||
ka[j] = ROL8(ka[j], 6);
|
||||
kb[j] = ROL8(kb[j], 6);
|
||||
}
|
||||
if (strengthened) {
|
||||
k = 2 * i - 1;
|
||||
while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; }
|
||||
}
|
||||
for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
|
||||
if (strengthened) {
|
||||
*key++ = (ka[k]
|
||||
+ safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
|
||||
if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; }
|
||||
} else {
|
||||
*key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
|
||||
}
|
||||
}
|
||||
if (strengthened) {
|
||||
k = 2 * i;
|
||||
while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; }
|
||||
}
|
||||
for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
|
||||
if (strengthened) {
|
||||
*key++ = (kb[k]
|
||||
+ safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
|
||||
if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; }
|
||||
} else {
|
||||
*key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(ka, sizeof(ka));
|
||||
zeromem(kb, sizeof(kb));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static void Safer_Expand_Userkey(const unsigned char *userkey_1,
|
||||
const unsigned char *userkey_2,
|
||||
unsigned int nof_rounds,
|
||||
int strengthened,
|
||||
safer_key_t key)
|
||||
{
|
||||
_Safer_Expand_Userkey(userkey_1, userkey_2, nof_rounds, strengthened, key);
|
||||
burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2);
|
||||
}
|
||||
#endif
|
||||
|
||||
int safer_k64_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
|
||||
{
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
if (numrounds != 0 && (numrounds < 6 || numrounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
|
||||
return CRYPT_INVALID_ROUNDS;
|
||||
}
|
||||
|
||||
if (keylen != 8) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
|
||||
Safer_Expand_Userkey(key, key, (unsigned int)(numrounds != 0 ?numrounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int safer_sk64_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
|
||||
{
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
if (numrounds != 0 && (numrounds < 6 || numrounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
|
||||
return CRYPT_INVALID_ROUNDS;
|
||||
}
|
||||
|
||||
if (keylen != 8) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
|
||||
Safer_Expand_Userkey(key, key, (unsigned int)(numrounds != 0 ?numrounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int safer_k128_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
|
||||
{
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
if (numrounds != 0 && (numrounds < 6 || numrounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
|
||||
return CRYPT_INVALID_ROUNDS;
|
||||
}
|
||||
|
||||
if (keylen != 16) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
|
||||
Safer_Expand_Userkey(key, key+8, (unsigned int)(numrounds != 0 ?numrounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
int safer_sk128_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
|
||||
{
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
if (numrounds != 0 && (numrounds < 6 || numrounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
|
||||
return CRYPT_INVALID_ROUNDS;
|
||||
}
|
||||
|
||||
if (keylen != 16) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
|
||||
Safer_Expand_Userkey(key, key+8, (unsigned int)(numrounds != 0?numrounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _safer_ecb_encrypt(const unsigned char *block_in,
|
||||
unsigned char *block_out,
|
||||
symmetric_key *skey)
|
||||
#else
|
||||
int safer_ecb_encrypt(const unsigned char *block_in,
|
||||
unsigned char *block_out,
|
||||
symmetric_key *skey)
|
||||
#endif
|
||||
{ unsigned char a, b, c, d, e, f, g, h, t;
|
||||
unsigned int round;
|
||||
unsigned char *key;
|
||||
|
||||
LTC_ARGCHK(block_in != NULL);
|
||||
LTC_ARGCHK(block_out != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
key = skey->safer.key;
|
||||
a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3];
|
||||
e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7];
|
||||
if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS;
|
||||
while(round-- > 0)
|
||||
{
|
||||
a ^= *++key; b += *++key; c += *++key; d ^= *++key;
|
||||
e ^= *++key; f += *++key; g += *++key; h ^= *++key;
|
||||
a = EXP(a) + *++key; b = LOG(b) ^ *++key;
|
||||
c = LOG(c) ^ *++key; d = EXP(d) + *++key;
|
||||
e = EXP(e) + *++key; f = LOG(f) ^ *++key;
|
||||
g = LOG(g) ^ *++key; h = EXP(h) + *++key;
|
||||
PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
|
||||
PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
|
||||
PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
|
||||
t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
|
||||
}
|
||||
a ^= *++key; b += *++key; c += *++key; d ^= *++key;
|
||||
e ^= *++key; f += *++key; g += *++key; h ^= *++key;
|
||||
block_out[0] = a & 0xFF; block_out[1] = b & 0xFF;
|
||||
block_out[2] = c & 0xFF; block_out[3] = d & 0xFF;
|
||||
block_out[4] = e & 0xFF; block_out[5] = f & 0xFF;
|
||||
block_out[6] = g & 0xFF; block_out[7] = h & 0xFF;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
int safer_ecb_encrypt(const unsigned char *block_in,
|
||||
unsigned char *block_out,
|
||||
symmetric_key *skey)
|
||||
{
|
||||
int err = _safer_ecb_encrypt(block_in, block_out, skey);
|
||||
burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
static int _safer_ecb_decrypt(const unsigned char *block_in,
|
||||
unsigned char *block_out,
|
||||
symmetric_key *skey)
|
||||
#else
|
||||
int safer_ecb_decrypt(const unsigned char *block_in,
|
||||
unsigned char *block_out,
|
||||
symmetric_key *skey)
|
||||
#endif
|
||||
{ unsigned char a, b, c, d, e, f, g, h, t;
|
||||
unsigned int round;
|
||||
unsigned char *key;
|
||||
|
||||
LTC_ARGCHK(block_in != NULL);
|
||||
LTC_ARGCHK(block_out != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
key = skey->safer.key;
|
||||
a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3];
|
||||
e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7];
|
||||
if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS;
|
||||
key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round);
|
||||
h ^= *key; g -= *--key; f -= *--key; e ^= *--key;
|
||||
d ^= *--key; c -= *--key; b -= *--key; a ^= *--key;
|
||||
while (round--)
|
||||
{
|
||||
t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
|
||||
IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
|
||||
IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
|
||||
IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
|
||||
h -= *--key; g ^= *--key; f ^= *--key; e -= *--key;
|
||||
d -= *--key; c ^= *--key; b ^= *--key; a -= *--key;
|
||||
h = LOG(h) ^ *--key; g = EXP(g) - *--key;
|
||||
f = EXP(f) - *--key; e = LOG(e) ^ *--key;
|
||||
d = LOG(d) ^ *--key; c = EXP(c) - *--key;
|
||||
b = EXP(b) - *--key; a = LOG(a) ^ *--key;
|
||||
}
|
||||
block_out[0] = a & 0xFF; block_out[1] = b & 0xFF;
|
||||
block_out[2] = c & 0xFF; block_out[3] = d & 0xFF;
|
||||
block_out[4] = e & 0xFF; block_out[5] = f & 0xFF;
|
||||
block_out[6] = g & 0xFF; block_out[7] = h & 0xFF;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
int safer_ecb_decrypt(const unsigned char *block_in,
|
||||
unsigned char *block_out,
|
||||
symmetric_key *skey)
|
||||
{
|
||||
int err = _safer_ecb_decrypt(block_in, block_out, skey);
|
||||
burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
int safer_64_keysize(int *keysize)
|
||||
{
|
||||
LTC_ARGCHK(keysize != NULL);
|
||||
if (*keysize < 8) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
} else {
|
||||
*keysize = 8;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int safer_128_keysize(int *keysize)
|
||||
{
|
||||
LTC_ARGCHK(keysize != NULL);
|
||||
if (*keysize < 16) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
} else {
|
||||
*keysize = 16;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int safer_k64_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 },
|
||||
k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 };
|
||||
|
||||
symmetric_key skey;
|
||||
unsigned char buf[2][8];
|
||||
int err;
|
||||
|
||||
/* test K64 */
|
||||
if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
safer_ecb_encrypt(k64_pt, buf[0], &skey);
|
||||
safer_ecb_decrypt(buf[0], buf[1], &skey);
|
||||
|
||||
if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 ||
|
||||
compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int safer_sk64_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 };
|
||||
|
||||
symmetric_key skey;
|
||||
unsigned char buf[2][8];
|
||||
int err, y;
|
||||
|
||||
/* test SK64 */
|
||||
if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
safer_ecb_encrypt(sk64_pt, buf[0], &skey);
|
||||
safer_ecb_decrypt(buf[0], buf[1], &skey);
|
||||
|
||||
if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 ||
|
||||
compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
|
||||
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
|
||||
for (y = 0; y < 8; y++) buf[0][y] = 0;
|
||||
for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
|
||||
for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
|
||||
for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
|
||||
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Terminate the context
|
||||
@param skey The scheduled key
|
||||
*/
|
||||
void safer_done(symmetric_key *skey)
|
||||
{
|
||||
LTC_UNUSED_PARAM(skey);
|
||||
}
|
||||
|
||||
int safer_sk128_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 };
|
||||
|
||||
symmetric_key skey;
|
||||
unsigned char buf[2][8];
|
||||
int err, y;
|
||||
|
||||
/* test SK128 */
|
||||
if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
safer_ecb_encrypt(sk128_pt, buf[0], &skey);
|
||||
safer_ecb_decrypt(buf[0], buf[1], &skey);
|
||||
|
||||
if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 ||
|
||||
compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 0) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
|
||||
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
|
||||
for (y = 0; y < 8; y++) buf[0][y] = 0;
|
||||
for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
|
||||
for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
|
||||
for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
|
||||
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* ref: HEAD -> master, tag: v1.18.2 */
|
||||
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
|
||||
/* commit time: 2018-07-01 22:49:01 +0200 */
|
64
thirdparty/libtomcrypt/ciphers/safer/safer_tab.c
vendored
Normal file
64
thirdparty/libtomcrypt/ciphers/safer/safer_tab.c
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file safer_tab.c
|
||||
Tables for LTC_SAFER block ciphers
|
||||
*/
|
||||
|
||||
#ifdef __LTC_SAFER_TAB_C__
|
||||
|
||||
/* This is the box defined by ebox[x] = 45^x mod 257.
|
||||
* Its assumed that the value "256" corresponds to zero. */
|
||||
static const unsigned char safer_ebox[256] = {
|
||||
1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63,
|
||||
8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247,
|
||||
64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177,
|
||||
255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131,
|
||||
241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20,
|
||||
129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160,
|
||||
4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252,
|
||||
32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217,
|
||||
0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194,
|
||||
249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10,
|
||||
193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80,
|
||||
2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126,
|
||||
16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237,
|
||||
128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97,
|
||||
253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5,
|
||||
225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40
|
||||
};
|
||||
|
||||
/* This is the inverse of ebox or the base 45 logarithm */
|
||||
static const unsigned char safer_lbox[256] = {
|
||||
128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248,
|
||||
192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130,
|
||||
112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37,
|
||||
201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15,
|
||||
32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198,
|
||||
175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84,
|
||||
121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188,
|
||||
189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217,
|
||||
208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158,
|
||||
210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42,
|
||||
95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219,
|
||||
164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29,
|
||||
41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14,
|
||||
122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104,
|
||||
109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66,
|
||||
184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48
|
||||
};
|
||||
|
||||
#endif /* __LTC_SAFER_TAB_C__ */
|
||||
|
||||
|
||||
|
||||
/* ref: HEAD -> master, tag: v1.18.2 */
|
||||
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
|
||||
/* commit time: 2018-07-01 22:49:01 +0200 */
|
568
thirdparty/libtomcrypt/ciphers/safer/saferp.c
vendored
Normal file
568
thirdparty/libtomcrypt/ciphers/safer/saferp.c
vendored
Normal file
@ -0,0 +1,568 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
@file saferp.c
|
||||
LTC_SAFER+ Implementation by Tom St Denis
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_SAFERP
|
||||
|
||||
#define __LTC_SAFER_TAB_C__
|
||||
#include "safer_tab.c"
|
||||
|
||||
const struct ltc_cipher_descriptor saferp_desc =
|
||||
{
|
||||
"safer+",
|
||||
4,
|
||||
16, 32, 16, 8,
|
||||
&saferp_setup,
|
||||
&saferp_ecb_encrypt,
|
||||
&saferp_ecb_decrypt,
|
||||
&saferp_test,
|
||||
&saferp_done,
|
||||
&saferp_keysize,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/* ROUND(b,i)
|
||||
*
|
||||
* This is one forward key application. Note the basic form is
|
||||
* key addition, substitution, key addition. The safer_ebox and safer_lbox
|
||||
* are the exponentiation box and logarithm boxes respectively.
|
||||
* The value of 'i' is the current round number which allows this
|
||||
* function to be unrolled massively. Most of LTC_SAFER+'s speed
|
||||
* comes from not having to compute indirect accesses into the
|
||||
* array of 16 bytes b[0..15] which is the block of data
|
||||
*/
|
||||
|
||||
#define ROUND(b, i) do { \
|
||||
b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \
|
||||
b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \
|
||||
b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \
|
||||
b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \
|
||||
b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \
|
||||
b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \
|
||||
b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \
|
||||
b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \
|
||||
b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \
|
||||
b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \
|
||||
b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \
|
||||
b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \
|
||||
b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \
|
||||
b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \
|
||||
b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \
|
||||
b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; \
|
||||
} while (0)
|
||||
|
||||
/* This is one inverse key application */
|
||||
#define iROUND(b, i) do { \
|
||||
b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \
|
||||
b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \
|
||||
b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \
|
||||
b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \
|
||||
b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \
|
||||
b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \
|
||||
b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \
|
||||
b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \
|
||||
b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \
|
||||
b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \
|
||||
b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \
|
||||
b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \
|
||||
b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \
|
||||
b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \
|
||||
b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \
|
||||
b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; \
|
||||
} while (0)
|
||||
|
||||
/* This is a forward single layer PHT transform. */
|
||||
#define PHT(b) do { \
|
||||
b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \
|
||||
b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \
|
||||
b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \
|
||||
b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \
|
||||
b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \
|
||||
b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \
|
||||
b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \
|
||||
b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; \
|
||||
} while (0)
|
||||
|
||||
/* This is an inverse single layer PHT transform */
|
||||
#define iPHT(b) do { \
|
||||
b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \
|
||||
b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \
|
||||
b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \
|
||||
b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \
|
||||
b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \
|
||||
b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \
|
||||
b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \
|
||||
b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \
|
||||
} while (0)
|
||||
|
||||
/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */
|
||||
#define SHUF(b, b2) do { \
|
||||
b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \
|
||||
b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \
|
||||
b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \
|
||||
b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; \
|
||||
} while (0)
|
||||
|
||||
/* This is the inverse shuffle. It takes from b and gives to b2 */
|
||||
#define iSHUF(b, b2) do { \
|
||||
b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \
|
||||
b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \
|
||||
b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \
|
||||
b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; \
|
||||
} while (0)
|
||||
|
||||
/* The complete forward Linear Transform layer.
|
||||
* Note that alternating usage of b and b2.
|
||||
* Each round of LT starts in 'b' and ends in 'b2'.
|
||||
*/
|
||||
#define LT(b, b2) do { \
|
||||
PHT(b); SHUF(b, b2); \
|
||||
PHT(b2); SHUF(b2, b); \
|
||||
PHT(b); SHUF(b, b2); \
|
||||
PHT(b2); \
|
||||
} while (0)
|
||||
|
||||
/* This is the inverse linear transform layer. */
|
||||
#define iLT(b, b2) do { \
|
||||
iPHT(b); \
|
||||
iSHUF(b, b2); iPHT(b2); \
|
||||
iSHUF(b2, b); iPHT(b); \
|
||||
iSHUF(b, b2); iPHT(b2); \
|
||||
} while (0)
|
||||
|
||||
#ifdef LTC_SMALL_CODE
|
||||
|
||||
static void _round(unsigned char *b, int i, symmetric_key *skey)
|
||||
{
|
||||
ROUND(b, i);
|
||||
}
|
||||
|
||||
static void _iround(unsigned char *b, int i, symmetric_key *skey)
|
||||
{
|
||||
iROUND(b, i);
|
||||
}
|
||||
|
||||
static void _lt(unsigned char *b, unsigned char *b2)
|
||||
{
|
||||
LT(b, b2);
|
||||
}
|
||||
|
||||
static void _ilt(unsigned char *b, unsigned char *b2)
|
||||
{
|
||||
iLT(b, b2);
|
||||
}
|
||||
|
||||
#undef ROUND
|
||||
#define ROUND(b, i) _round(b, i, skey)
|
||||
|
||||
#undef iROUND
|
||||
#define iROUND(b, i) _iround(b, i, skey)
|
||||
|
||||
#undef LT
|
||||
#define LT(b, b2) _lt(b, b2)
|
||||
|
||||
#undef iLT
|
||||
#define iLT(b, b2) _ilt(b, b2)
|
||||
|
||||
#endif
|
||||
|
||||
/* These are the 33, 128-bit bias words for the key schedule */
|
||||
static const unsigned char safer_bias[33][16] = {
|
||||
{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100},
|
||||
{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61},
|
||||
{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160},
|
||||
{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148},
|
||||
{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143},
|
||||
{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202},
|
||||
{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44},
|
||||
{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51},
|
||||
{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56},
|
||||
{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215},
|
||||
{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210},
|
||||
{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53},
|
||||
{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244},
|
||||
{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131},
|
||||
{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241},
|
||||
{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172},
|
||||
{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239},
|
||||
{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202},
|
||||
{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246},
|
||||
{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152},
|
||||
{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236},
|
||||
{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150},
|
||||
{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30},
|
||||
{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6},
|
||||
{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104},
|
||||
{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175},
|
||||
{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35},
|
||||
{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7},
|
||||
{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207},
|
||||
{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247},
|
||||
{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255},
|
||||
{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}};
|
||||
|
||||
/**
|
||||
Initialize the LTC_SAFER+ block cipher
|
||||
@param key The symmetric key you wish to pass
|
||||
@param keylen The key length in bytes
|
||||
@param num_rounds The number of rounds desired (0 for default)
|
||||
@param skey The key in as scheduled by this function.
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
|
||||
{
|
||||
unsigned x, y, z;
|
||||
unsigned char t[33];
|
||||
static const int rounds[3] = { 8, 12, 16 };
|
||||
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
/* check arguments */
|
||||
if (keylen != 16 && keylen != 24 && keylen != 32) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
|
||||
/* Is the number of rounds valid? Either use zero for default or
|
||||
* 8,12,16 rounds for 16,24,32 byte keys
|
||||
*/
|
||||
if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) {
|
||||
return CRYPT_INVALID_ROUNDS;
|
||||
}
|
||||
|
||||
/* 128 bit key version */
|
||||
if (keylen == 16) {
|
||||
/* copy key into t */
|
||||
for (x = y = 0; x < 16; x++) {
|
||||
t[x] = key[x];
|
||||
y ^= key[x];
|
||||
}
|
||||
t[16] = y;
|
||||
|
||||
/* make round keys */
|
||||
for (x = 0; x < 16; x++) {
|
||||
skey->saferp.K[0][x] = t[x];
|
||||
}
|
||||
|
||||
/* make the 16 other keys as a transformation of the first key */
|
||||
for (x = 1; x < 17; x++) {
|
||||
/* rotate 3 bits each */
|
||||
for (y = 0; y < 17; y++) {
|
||||
t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
|
||||
}
|
||||
|
||||
/* select and add */
|
||||
z = x;
|
||||
for (y = 0; y < 16; y++) {
|
||||
skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
|
||||
if (++z == 17) { z = 0; }
|
||||
}
|
||||
}
|
||||
skey->saferp.rounds = 8;
|
||||
} else if (keylen == 24) {
|
||||
/* copy key into t */
|
||||
for (x = y = 0; x < 24; x++) {
|
||||
t[x] = key[x];
|
||||
y ^= key[x];
|
||||
}
|
||||
t[24] = y;
|
||||
|
||||
/* make round keys */
|
||||
for (x = 0; x < 16; x++) {
|
||||
skey->saferp.K[0][x] = t[x];
|
||||
}
|
||||
|
||||
for (x = 1; x < 25; x++) {
|
||||
/* rotate 3 bits each */
|
||||
for (y = 0; y < 25; y++) {
|
||||
t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
|
||||
}
|
||||
|
||||
/* select and add */
|
||||
z = x;
|
||||
for (y = 0; y < 16; y++) {
|
||||
skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
|
||||
if (++z == 25) { z = 0; }
|
||||
}
|
||||
}
|
||||
skey->saferp.rounds = 12;
|
||||
} else {
|
||||
/* copy key into t */
|
||||
for (x = y = 0; x < 32; x++) {
|
||||
t[x] = key[x];
|
||||
y ^= key[x];
|
||||
}
|
||||
t[32] = y;
|
||||
|
||||
/* make round keys */
|
||||
for (x = 0; x < 16; x++) {
|
||||
skey->saferp.K[0][x] = t[x];
|
||||
}
|
||||
|
||||
for (x = 1; x < 33; x++) {
|
||||
/* rotate 3 bits each */
|
||||
for (y = 0; y < 33; y++) {
|
||||
t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
|
||||
}
|
||||
|
||||
/* select and add */
|
||||
z = x;
|
||||
for (y = 0; y < 16; y++) {
|
||||
skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
|
||||
if (++z == 33) { z = 0; }
|
||||
}
|
||||
}
|
||||
skey->saferp.rounds = 16;
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(t, sizeof(t));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Encrypts a block of text with LTC_SAFER+
|
||||
@param pt The input plaintext (16 bytes)
|
||||
@param ct The output ciphertext (16 bytes)
|
||||
@param skey The key as scheduled
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
|
||||
{
|
||||
unsigned char b[16];
|
||||
int x;
|
||||
|
||||
LTC_ARGCHK(pt != NULL);
|
||||
LTC_ARGCHK(ct != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
/* do eight rounds */
|
||||
for (x = 0; x < 16; x++) {
|
||||
b[x] = pt[x];
|
||||
}
|
||||
ROUND(b, 0); LT(b, ct);
|
||||
ROUND(ct, 2); LT(ct, b);
|
||||
ROUND(b, 4); LT(b, ct);
|
||||
ROUND(ct, 6); LT(ct, b);
|
||||
ROUND(b, 8); LT(b, ct);
|
||||
ROUND(ct, 10); LT(ct, b);
|
||||
ROUND(b, 12); LT(b, ct);
|
||||
ROUND(ct, 14); LT(ct, b);
|
||||
/* 192-bit key? */
|
||||
if (skey->saferp.rounds > 8) {
|
||||
ROUND(b, 16); LT(b, ct);
|
||||
ROUND(ct, 18); LT(ct, b);
|
||||
ROUND(b, 20); LT(b, ct);
|
||||
ROUND(ct, 22); LT(ct, b);
|
||||
}
|
||||
/* 256-bit key? */
|
||||
if (skey->saferp.rounds > 12) {
|
||||
ROUND(b, 24); LT(b, ct);
|
||||
ROUND(ct, 26); LT(ct, b);
|
||||
ROUND(b, 28); LT(b, ct);
|
||||
ROUND(ct, 30); LT(ct, b);
|
||||
}
|
||||
ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
|
||||
ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
|
||||
ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
|
||||
ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
|
||||
ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
|
||||
ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
|
||||
ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
|
||||
ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
|
||||
ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
|
||||
ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
|
||||
ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
|
||||
ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
|
||||
ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
|
||||
ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
|
||||
ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
|
||||
ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(b, sizeof(b));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Decrypts a block of text with LTC_SAFER+
|
||||
@param ct The input ciphertext (16 bytes)
|
||||
@param pt The output plaintext (16 bytes)
|
||||
@param skey The key as scheduled
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
|
||||
{
|
||||
unsigned char b[16];
|
||||
int x;
|
||||
|
||||
LTC_ARGCHK(pt != NULL);
|
||||
LTC_ARGCHK(ct != NULL);
|
||||
LTC_ARGCHK(skey != NULL);
|
||||
|
||||
/* do eight rounds */
|
||||
b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
|
||||
b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
|
||||
b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
|
||||
b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
|
||||
b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
|
||||
b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
|
||||
b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
|
||||
b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
|
||||
b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
|
||||
b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
|
||||
b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
|
||||
b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
|
||||
b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
|
||||
b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
|
||||
b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
|
||||
b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
|
||||
/* 256-bit key? */
|
||||
if (skey->saferp.rounds > 12) {
|
||||
iLT(b, pt); iROUND(pt, 30);
|
||||
iLT(pt, b); iROUND(b, 28);
|
||||
iLT(b, pt); iROUND(pt, 26);
|
||||
iLT(pt, b); iROUND(b, 24);
|
||||
}
|
||||
/* 192-bit key? */
|
||||
if (skey->saferp.rounds > 8) {
|
||||
iLT(b, pt); iROUND(pt, 22);
|
||||
iLT(pt, b); iROUND(b, 20);
|
||||
iLT(b, pt); iROUND(pt, 18);
|
||||
iLT(pt, b); iROUND(b, 16);
|
||||
}
|
||||
iLT(b, pt); iROUND(pt, 14);
|
||||
iLT(pt, b); iROUND(b, 12);
|
||||
iLT(b, pt); iROUND(pt,10);
|
||||
iLT(pt, b); iROUND(b, 8);
|
||||
iLT(b, pt); iROUND(pt,6);
|
||||
iLT(pt, b); iROUND(b, 4);
|
||||
iLT(b, pt); iROUND(pt,2);
|
||||
iLT(pt, b); iROUND(b, 0);
|
||||
for (x = 0; x < 16; x++) {
|
||||
pt[x] = b[x];
|
||||
}
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(b, sizeof(b));
|
||||
#endif
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Performs a self-test of the LTC_SAFER+ block cipher
|
||||
@return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
|
||||
*/
|
||||
int saferp_test(void)
|
||||
{
|
||||
#ifndef LTC_TEST
|
||||
return CRYPT_NOP;
|
||||
#else
|
||||
static const struct {
|
||||
int keylen;
|
||||
unsigned char key[32], pt[16], ct[16];
|
||||
} tests[] = {
|
||||
{
|
||||
16,
|
||||
{ 41, 35, 190, 132, 225, 108, 214, 174,
|
||||
82, 144, 73, 241, 241, 187, 233, 235 },
|
||||
{ 179, 166, 219, 60, 135, 12, 62, 153,
|
||||
36, 94, 13, 28, 6, 183, 71, 222 },
|
||||
{ 224, 31, 182, 10, 12, 255, 84, 70,
|
||||
127, 13, 89, 249, 9, 57, 165, 220 }
|
||||
}, {
|
||||
24,
|
||||
{ 72, 211, 143, 117, 230, 217, 29, 42,
|
||||
229, 192, 247, 43, 120, 129, 135, 68,
|
||||
14, 95, 80, 0, 212, 97, 141, 190 },
|
||||
{ 123, 5, 21, 7, 59, 51, 130, 31,
|
||||
24, 112, 146, 218, 100, 84, 206, 177 },
|
||||
{ 92, 136, 4, 63, 57, 95, 100, 0,
|
||||
150, 130, 130, 16, 193, 111, 219, 133 }
|
||||
}, {
|
||||
32,
|
||||
{ 243, 168, 141, 254, 190, 242, 235, 113,
|
||||
255, 160, 208, 59, 117, 6, 140, 126,
|
||||
135, 120, 115, 77, 208, 190, 130, 190,
|
||||
219, 194, 70, 65, 43, 140, 250, 48 },
|
||||
{ 127, 112, 240, 167, 84, 134, 50, 149,
|
||||
170, 91, 104, 19, 11, 230, 252, 245 },
|
||||
{ 88, 11, 25, 36, 172, 229, 202, 213,
|
||||
170, 65, 105, 153, 220, 104, 153, 138 }
|
||||
}
|
||||
};
|
||||
|
||||
unsigned char tmp[2][16];
|
||||
symmetric_key skey;
|
||||
int err, i, y;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
|
||||
if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey);
|
||||
saferp_ecb_decrypt(tmp[0], tmp[1], &skey);
|
||||
|
||||
/* compare */
|
||||
if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Safer+ Encrypt", i) ||
|
||||
compare_testvector(tmp[1], 16, tests[i].pt, 16, "Safer+ Decrypt", i)) {
|
||||
return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
|
||||
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
|
||||
for (y = 0; y < 16; y++) tmp[0][y] = 0;
|
||||
for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey);
|
||||
for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey);
|
||||
for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Terminate the context
|
||||
@param skey The scheduled key
|
||||
*/
|
||||
void saferp_done(symmetric_key *skey)
|
||||
{
|
||||
LTC_UNUSED_PARAM(skey);
|
||||
}
|
||||
|
||||
/**
|
||||
Gets suitable key size
|
||||
@param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
|
||||
@return CRYPT_OK if the input key size is acceptable.
|
||||
*/
|
||||
int saferp_keysize(int *keysize)
|
||||
{
|
||||
LTC_ARGCHK(keysize != NULL);
|
||||
|
||||
if (*keysize < 16)
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
if (*keysize < 24) {
|
||||
*keysize = 16;
|
||||
} else if (*keysize < 32) {
|
||||
*keysize = 24;
|
||||
} else {
|
||||
*keysize = 32;
|
||||
}
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* ref: HEAD -> master, tag: v1.18.2 */
|
||||
/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
|
||||
/* commit time: 2018-07-01 22:49:01 +0200 */
|
Reference in New Issue
Block a user