Files
2026-08-07 17:38:18 +09:00

395 lines
9.7 KiB
C

/*******************************************************************************
*
* FILE: safer.c
*
* DESCRIPTION: block-cipher algorithm SAFER (Secure And Fast Encryption
* Routine) in its four versions: SAFER K-64, SAFER K-128,
* SAFER SK-64 and 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:
*
*******************************************************************************/
/* modified in order to use the libmcrypt API by Nikos Mavroyanopoulos
* All modifications are placed under the license of libmcrypt.
*/
/* $Id: safer64.c,v 1.1 2007/07/19 06:11:48 pizon Exp $ */
/******************* External Headers *****************************************/
/******************* Local Headers ********************************************/
#include <libdefs.h>
#include <mcrypt_modules.h>
#include "safer.h"
#define _mcrypt_set_key safer_sk64_LTX__mcrypt_set_key
#define _mcrypt_encrypt safer_sk64_LTX__mcrypt_encrypt
#define _mcrypt_decrypt safer_sk64_LTX__mcrypt_decrypt
#define _mcrypt_get_size safer_sk64_LTX__mcrypt_get_size
#define _mcrypt_get_block_size safer_sk64_LTX__mcrypt_get_block_size
#define _is_block_algorithm safer_sk64_LTX__is_block_algorithm
#define _mcrypt_get_key_size safer_sk64_LTX__mcrypt_get_key_size
#define _mcrypt_get_supported_key_sizes safer_sk64_LTX__mcrypt_get_supported_key_sizes
#define _mcrypt_get_algorithms_name safer_sk64_LTX__mcrypt_get_algorithms_name
#define _mcrypt_self_test safer_sk64_LTX__mcrypt_self_test
#define _mcrypt_algorithm_version safer_sk64_LTX__mcrypt_algorithm_version
/******************* Constants ************************************************/
#define TAB_LEN 256
static int _safer64_init = 0;
/******************* Assertions ***********************************************/
/******************* Macros ***************************************************/
#define ROL(x, n) ((unsigned char)((unsigned int)(x) << (n)\
|(unsigned int)((x) & 0xFF) >> (8 - (n))))
#define EXP(x) exp_tab64[(x) & 0xFF]
#define LOG(x) log_tab64[(x) & 0xFF]
#define PHT(x, y) { y += x; x += y; }
#define IPHT(x, y) { x -= y; y -= x; }
/******************* Types ****************************************************/
static unsigned char exp_tab64[TAB_LEN];
static unsigned char log_tab64[TAB_LEN];
/******************* Module Data **********************************************/
/******************* Functions ************************************************/
/******************************************************************************/
static void _mcrypt_Safer_Init_Module(void)
{
unsigned int i, exp;
exp = 1;
for (i = 0; i < TAB_LEN; i++) {
exp_tab64[i] = (unsigned char) (exp & 0xFF);
log_tab64[exp_tab64[i]] = (unsigned char) i;
exp = exp * 45 % 257;
}
} /* Safer_Init_Module */
/******************************************************************************/
WIN32DLL_DEFINE
int _mcrypt_set_key(safer_key_t * key, safer_block_t * userkey,
int len)
{
unsigned int i, j;
unsigned char ka[SAFER_BLOCK_LEN + 1];
unsigned char kb[SAFER_BLOCK_LEN + 1];
int nof_rounds = SAFER_SK64_DEFAULT_NOF_ROUNDS;
int strengthened = 1;
if (_safer64_init == 0) {
_mcrypt_Safer_Init_Module();
_safer64_init = 1;
}
if (SAFER_MAX_NOF_ROUNDS < nof_rounds)
nof_rounds = SAFER_MAX_NOF_ROUNDS;
*key++ = (unsigned char) nof_rounds;
ka[SAFER_BLOCK_LEN] = 0;
kb[SAFER_BLOCK_LEN] = 0;
for (j = 0; j < SAFER_BLOCK_LEN; j++) {
ka[SAFER_BLOCK_LEN] ^= ka[j] = ROL(userkey[j], 5);
kb[SAFER_BLOCK_LEN] ^= kb[j] = *key++ = userkey[j];
}
for (i = 1; i <= nof_rounds; i++) {
for (j = 0; j < SAFER_BLOCK_LEN + 1; j++) {
ka[j] = ROL(ka[j], 6);
kb[j] = ROL(kb[j], 6);
}
for (j = 0; j < SAFER_BLOCK_LEN; j++)
if (strengthened)
*key++ =
(ka
[(j + 2 * i - 1) %
(SAFER_BLOCK_LEN + 1)] +
exp_tab64[exp_tab64[18 * i + j + 1]]) &
0xFF;
else
*key++ =
(ka[j] +
exp_tab64[exp_tab64[18 * i + j + 1]]) &
0xFF;
for (j = 0; j < SAFER_BLOCK_LEN; j++)
if (strengthened)
*key++ =
(kb
[(j + 2 * i) %
(SAFER_BLOCK_LEN + 1)] +
exp_tab64[exp_tab64[18 * i + j + 10]]) &
0xFF;
else
*key++ =
(kb[j] +
exp_tab64[exp_tab64[18 * i + j + 10]]) &
0xFF;
}
for (j = 0; j < SAFER_BLOCK_LEN + 1; j++)
ka[j] = kb[j] = 0;
return 0;
} /* Safer_Expand_Userkey */
/******************************************************************************/
WIN32DLL_DEFINE
void _mcrypt_encrypt(const safer_key_t * key, safer_block_t * block_in)
{
unsigned char a, b, c, d, e, f, g, h, t;
unsigned int round;
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 (SAFER_MAX_NOF_ROUNDS < (round = *key))
round = SAFER_MAX_NOF_ROUNDS;
while (round--) {
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_in[0] = a & 0xFF;
block_in[1] = b & 0xFF;
block_in[2] = c & 0xFF;
block_in[3] = d & 0xFF;
block_in[4] = e & 0xFF;
block_in[5] = f & 0xFF;
block_in[6] = g & 0xFF;
block_in[7] = h & 0xFF;
} /* Safer_Encrypt_Block */
/******************************************************************************/
WIN32DLL_DEFINE
void _mcrypt_decrypt(const safer_key_t * key, safer_block_t * block_in)
{
safer_block_t a, b, c, d, e, f, g, h, t;
unsigned int round;
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 (SAFER_MAX_NOF_ROUNDS < (round = *key))
round = SAFER_MAX_NOF_ROUNDS;
key += 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_in[0] = a & 0xFF;
block_in[1] = b & 0xFF;
block_in[2] = c & 0xFF;
block_in[3] = d & 0xFF;
block_in[4] = e & 0xFF;
block_in[5] = f & 0xFF;
block_in[6] = g & 0xFF;
block_in[7] = h & 0xFF;
} /* Safer_Decrypt_Block */
/******************************************************************************/
WIN32DLL_DEFINE int _mcrypt_get_size()
{
return (1 + SAFER_BLOCK_LEN * (1 + 2 * SAFER_MAX_NOF_ROUNDS));
}
WIN32DLL_DEFINE int _mcrypt_get_block_size()
{
return 8;
}
WIN32DLL_DEFINE int _is_block_algorithm()
{
return 1;
}
WIN32DLL_DEFINE int _mcrypt_get_key_size()
{
return 8;
}
static const int key_sizes[] = { 8 };
WIN32DLL_DEFINE const int *_mcrypt_get_supported_key_sizes(int *len)
{
*len = sizeof(key_sizes)/sizeof(int);
return key_sizes;
}
WIN32DLL_DEFINE char *_mcrypt_get_algorithms_name()
{
return "SAFER-SK64";
}
#define CIPHER "e490eebffd908f34"
WIN32DLL_DEFINE int _mcrypt_self_test()
{
char *keyword;
unsigned char plaintext[16];
unsigned char ciphertext[16];
int blocksize = _mcrypt_get_block_size(), j;
void *key;
unsigned char cipher_tmp[200];
keyword = calloc(1, _mcrypt_get_key_size());
if (keyword == NULL)
return -1;
for (j = 0; j < _mcrypt_get_key_size(); j++) {
keyword[j] = ((j * 2 + 10) % 256);
}
for (j = 0; j < blocksize; j++) {
plaintext[j] = j % 256;
}
key = malloc(_mcrypt_get_size());
if (key == NULL) {
free(keyword);
return -1;
}
memcpy(ciphertext, plaintext, blocksize);
_mcrypt_set_key(key, (void *) keyword, _mcrypt_get_key_size());
free(keyword);
_mcrypt_encrypt(key, (void *) ciphertext);
for (j = 0; j < blocksize; j++) {
sprintf(&((char *) cipher_tmp)[2 * j], "%.2x",
ciphertext[j]);
}
if (strcmp((char *) cipher_tmp, CIPHER) != 0) {
printf("failed compatibility\n");
printf("Expected: %s\nGot: %s\n", CIPHER,
(char *) cipher_tmp);
free(key);
return -1;
}
_mcrypt_decrypt(key, (void *) ciphertext);
free(key);
if (strcmp(ciphertext, plaintext) != 0) {
printf("failed internally\n");
return -1;
}
return 0;
}
WIN32DLL_DEFINE word32 _mcrypt_algorithm_version()
{
return 20010801;
}
#ifdef WIN32
# ifdef USE_LTDL
WIN32DLL_DEFINE int main (void)
{
/* empty main function to avoid linker error (see cygwin FAQ) */
}
# endif
#endif