mirror of https://github.com/facebook/tac_plus
159 lines
4.8 KiB
C
159 lines
4.8 KiB
C
/*
|
|
* Copyright (c) 1991 David G. Koontz.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms are permitted
|
|
* provided that the above copyright notice and this paragraph are
|
|
* duplicated in all such forms. Inclusion in a product or release
|
|
* as part of a package for sale is not agreed to. Storing this
|
|
* software in a nonvolatile storage device characterized as an
|
|
* integrated circuit providing read only memory (ROM), either as
|
|
* source code or machine executeable instructions is similarly not
|
|
* agreed to. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE
|
|
*/
|
|
#ifndef lint
|
|
char Copyright[]=
|
|
"@(#) Copyright (c) 1991 David G. Koontz\n All rights reserved.\n";
|
|
#endif
|
|
/*
|
|
* fdes.c - faster implementation of DES algorithm.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "fdes.h"
|
|
#include "des_ip.h"
|
|
#include "des_iip.h"
|
|
#include "des_key.h"
|
|
#include "des_s_p.h"
|
|
|
|
/* Key Schedule permuted for S Box input: */
|
|
static union block_48 K_S[16];
|
|
static union block_48 *key_start;
|
|
static int des_mode;
|
|
|
|
#pragma weak tac_des
|
|
#pragma weak tac_des_loadkey
|
|
#pragma weak tac_set_des_mode
|
|
|
|
void
|
|
tac_set_des_mode(int encode)
|
|
{
|
|
if (encode) {
|
|
key_start = &K_S[0];
|
|
des_mode = SHIFT_FOR_ENCRYPT;
|
|
} else {
|
|
key_start = &K_S[15];
|
|
des_mode = SHIFT_FOR_DECRYPT;
|
|
}
|
|
}
|
|
|
|
void
|
|
tac_des_loadkey(unsigned char *key, int shift)
|
|
{
|
|
unsigned i,j;
|
|
union block_48 data;
|
|
|
|
if (!shift) /* key lookup table always shifts */
|
|
for (i = 0; i < 8; i++)
|
|
data.string[i] = key[i] >> 1;
|
|
else
|
|
for (i = 0; i < 8; i++)
|
|
data.string[i] = key[i];
|
|
|
|
for ( j = 0; j < 16; j++) /* key load must be re-entrant */
|
|
K_S[j].AB[0] = K_S[j].AB[1] = 0;
|
|
|
|
for (i = 0; i < 8; i++) { /* 8 bytes (56 bits) of key */
|
|
for(j = 0; j < 16;j++) { /* load K_S[0-16] byte at a time */
|
|
K_S[j].AB[0] |= KEY[i][data.string[i]][j][0];
|
|
K_S[j].AB[1] |= KEY[i][data.string[i]][j][1];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
no_ip_des(union LR_block *block)
|
|
{
|
|
unsigned int round;
|
|
int shift;
|
|
unsigned long temp_f;
|
|
union block_48 pre_S, *k_s;
|
|
|
|
k_s = key_start;
|
|
shift = des_mode;
|
|
|
|
for (round = 0; round < 8; round++) { /* f(R,K), 16 double rounds */
|
|
|
|
/* Expansion Permutation, E XOR K */
|
|
temp_f = block->LR[RR]; /* L/R reg. is R31,R0...R30 (D0-D31) format */
|
|
pre_S.AB[0] = temp_f & 0x3f3f3f3f ^ k_s->AB[0]; /* S1S3S5S7 */
|
|
pre_S.AB[1] = ((temp_f >> 4 | temp_f << 28) & 0x3f3f3f3f) ^ k_s->AB[1];
|
|
k_s += shift; /* S2S4S6S8 */
|
|
|
|
/* S Box and P lookup: temp_f = f(R,K) */
|
|
temp_f = S_P[0][pre_S.string[S1]] | S_P[1][pre_S.string[S2]]
|
|
| S_P[2][pre_S.string[S3]] | S_P[3][pre_S.string[S4]]
|
|
| S_P[4][pre_S.string[S5]] | S_P[5][pre_S.string[S6]]
|
|
| S_P[6][pre_S.string[S7]] | S_P[7][pre_S.string[S8]];
|
|
|
|
/* f(R,K) EXOR L */
|
|
temp_f ^= block->LR[LL]; /* temp_f is new R */
|
|
block->LR[LL] = temp_f; /* update L register */
|
|
|
|
/* Repeat round (temp_f carried through) */
|
|
pre_S.AB[0] = temp_f & 0x3f3f3f3f ^ k_s->AB[0];
|
|
pre_S.AB[1] = ((temp_f >> 4 | temp_f << 28) & 0x3f3f3f3f) ^ k_s->AB[1];
|
|
k_s += shift;
|
|
|
|
temp_f = S_P[0][pre_S.string[S1]] | S_P[1][pre_S.string[S2]]
|
|
| S_P[2][pre_S.string[S3]] | S_P[3][pre_S.string[S4]]
|
|
| S_P[4][pre_S.string[S5]] | S_P[5][pre_S.string[S6]]
|
|
| S_P[6][pre_S.string[S7]] | S_P[7][pre_S.string[S8]];
|
|
|
|
temp_f ^= block->LR[RR]; /* L is old R */
|
|
block->LR[RR] = temp_f; /* update R register */
|
|
}
|
|
/* had L/R swap here */
|
|
}
|
|
|
|
void
|
|
tac_des(union LR_block *block)
|
|
{
|
|
unsigned long temp;
|
|
union LR_block data;
|
|
|
|
data.LR[LL] = block->LR[LL];
|
|
data.LR[RR] = block->LR[RR];
|
|
|
|
temp = IP[ 0][data.string[0]] | IP[ 1][data.string[1]] |
|
|
IP[ 2][data.string[2]] | IP[ 3][data.string[3]] |
|
|
IP[ 4][data.string[4]] | IP[ 5][data.string[5]] |
|
|
IP[ 6][data.string[6]] | IP[ 7][data.string[7]];
|
|
|
|
data.LR[LL] =
|
|
IP[ 8][data.string[0]] | IP[ 9][data.string[1]] |
|
|
IP[10][data.string[2]] | IP[11][data.string[3]] |
|
|
IP[12][data.string[4]] | IP[13][data.string[5]] |
|
|
IP[14][data.string[6]] | IP[15][data.string[7]];
|
|
|
|
data.LR[RR] = temp;
|
|
|
|
no_ip_des(&data);
|
|
|
|
temp = IIP[ 0][data.string[0]] | IIP[ 1][data.string[1]] |
|
|
IIP[ 2][data.string[2]] | IIP[ 3][data.string[3]] |
|
|
IIP[ 4][data.string[4]] | IIP[ 5][data.string[5]] |
|
|
IIP[ 6][data.string[6]] | IIP[ 7][data.string[7]];
|
|
|
|
block->LR[AA] =
|
|
IIP[ 8][data.string[0]] | IIP[ 9][data.string[1]] |
|
|
IIP[10][data.string[2]] | IIP[11][data.string[3]] |
|
|
IIP[12][data.string[4]] | IIP[13][data.string[5]] |
|
|
IIP[14][data.string[6]] | IIP[15][data.string[7]];
|
|
|
|
block->LR[BB] = temp;
|
|
}
|