mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-14 03:03:14 +08:00
Added a lot of #ifndef , extern C, Move inside from ARMSRC -> THUMBS, which made the compiled image smaller.. I don't know if it broke anything. Moved MF_DBGLEVEL definitions into common.h Moved print_result from util.c into appmain.c Also split up some struct typedef into header files so they could be reused in other code places. ''' danger ''' this might have broken stuff...
437 lines
11 KiB
C
437 lines
11 KiB
C
/* des.c */
|
|
/*
|
|
This file is part of the ARM-Crypto-Lib.
|
|
Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
/**
|
|
* \file des.c
|
|
* \author Daniel Otte
|
|
* \email daniel.otte@rub.de
|
|
* \date 2007-06-16
|
|
* \brief DES and EDE-DES implementation
|
|
* \license GPLv3 or later
|
|
*
|
|
*/
|
|
|
|
#include "des.h"
|
|
|
|
const uint8_t sbox[256] = {
|
|
/* S-box 1 */
|
|
0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
|
|
0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
|
|
0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
|
|
0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
|
|
/* S-box 2 */
|
|
0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
|
|
0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
|
|
0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
|
|
0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
|
|
/* S-box 3 */
|
|
0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
|
|
0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
|
|
0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
|
|
0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
|
|
/* S-box 4 */
|
|
0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
|
|
0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
|
|
0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
|
|
0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
|
|
/* S-box 5 */
|
|
0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
|
|
0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
|
|
0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
|
|
0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
|
|
/* S-box 6 */
|
|
0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
|
|
0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
|
|
0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
|
|
0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
|
|
/* S-box 7 */
|
|
0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
|
|
0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
|
|
0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
|
|
0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
|
|
/* S-box 8 */
|
|
0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
|
|
0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
|
|
0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
|
|
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
|
|
};
|
|
|
|
const uint8_t e_permtab[] ={
|
|
4, 6, /* 4 bytes in 6 bytes out*/
|
|
32, 1, 2, 3, 4, 5,
|
|
4, 5, 6, 7, 8, 9,
|
|
8, 9, 10, 11, 12, 13,
|
|
12, 13, 14, 15, 16, 17,
|
|
16, 17, 18, 19, 20, 21,
|
|
20, 21, 22, 23, 24, 25,
|
|
24, 25, 26, 27, 28, 29,
|
|
28, 29, 30, 31, 32, 1
|
|
};
|
|
|
|
const uint8_t p_permtab[] ={
|
|
4, 4, /* 32 bit -> 32 bit */
|
|
16, 7, 20, 21,
|
|
29, 12, 28, 17,
|
|
1, 15, 23, 26,
|
|
5, 18, 31, 10,
|
|
2, 8, 24, 14,
|
|
32, 27, 3, 9,
|
|
19, 13, 30, 6,
|
|
22, 11, 4, 25
|
|
};
|
|
|
|
const uint8_t ip_permtab[] ={
|
|
8, 8, /* 64 bit -> 64 bit */
|
|
58, 50, 42, 34, 26, 18, 10, 2,
|
|
60, 52, 44, 36, 28, 20, 12, 4,
|
|
62, 54, 46, 38, 30, 22, 14, 6,
|
|
64, 56, 48, 40, 32, 24, 16, 8,
|
|
57, 49, 41, 33, 25, 17, 9, 1,
|
|
59, 51, 43, 35, 27, 19, 11, 3,
|
|
61, 53, 45, 37, 29, 21, 13, 5,
|
|
63, 55, 47, 39, 31, 23, 15, 7
|
|
};
|
|
|
|
const uint8_t inv_ip_permtab[] ={
|
|
8, 8, /* 64 bit -> 64 bit */
|
|
40, 8, 48, 16, 56, 24, 64, 32,
|
|
39, 7, 47, 15, 55, 23, 63, 31,
|
|
38, 6, 46, 14, 54, 22, 62, 30,
|
|
37, 5, 45, 13, 53, 21, 61, 29,
|
|
36, 4, 44, 12, 52, 20, 60, 28,
|
|
35, 3, 43, 11, 51, 19, 59, 27,
|
|
34, 2, 42, 10, 50, 18, 58, 26,
|
|
33, 1, 41, 9, 49, 17, 57, 25
|
|
};
|
|
|
|
const uint8_t pc1_permtab[] ={
|
|
8, 7, /* 64 bit -> 56 bit*/
|
|
57, 49, 41, 33, 25, 17, 9,
|
|
1, 58, 50, 42, 34, 26, 18,
|
|
10, 2, 59, 51, 43, 35, 27,
|
|
19, 11, 3, 60, 52, 44, 36,
|
|
63, 55, 47, 39, 31, 23, 15,
|
|
7, 62, 54, 46, 38, 30, 22,
|
|
14, 6, 61, 53, 45, 37, 29,
|
|
21, 13, 5, 28, 20, 12, 4
|
|
};
|
|
|
|
const uint8_t pc2_permtab[] ={
|
|
7, 6, /* 56 bit -> 48 bit */
|
|
14, 17, 11, 24, 1, 5,
|
|
3, 28, 15, 6, 21, 10,
|
|
23, 19, 12, 4, 26, 8,
|
|
16, 7, 27, 20, 13, 2,
|
|
41, 52, 31, 37, 47, 55,
|
|
30, 40, 51, 45, 33, 48,
|
|
44, 49, 39, 56, 34, 53,
|
|
46, 42, 50, 36, 29, 32
|
|
};
|
|
|
|
const uint8_t splitin6bitword_permtab[] = {
|
|
8, 8, /* 64 bit -> 64 bit */
|
|
64, 64, 1, 6, 2, 3, 4, 5,
|
|
64, 64, 7, 12, 8, 9, 10, 11,
|
|
64, 64, 13, 18, 14, 15, 16, 17,
|
|
64, 64, 19, 24, 20, 21, 22, 23,
|
|
64, 64, 25, 30, 26, 27, 28, 29,
|
|
64, 64, 31, 36, 32, 33, 34, 35,
|
|
64, 64, 37, 42, 38, 39, 40, 41,
|
|
64, 64, 43, 48, 44, 45, 46, 47
|
|
};
|
|
|
|
const uint8_t shiftkey_permtab[] = {
|
|
7, 7, /* 56 bit -> 56 bit */
|
|
2, 3, 4, 5, 6, 7, 8, 9,
|
|
10, 11, 12, 13, 14, 15, 16, 17,
|
|
18, 19, 20, 21, 22, 23, 24, 25,
|
|
26, 27, 28, 1,
|
|
30, 31, 32, 33, 34, 35, 36, 37,
|
|
38, 39, 40, 41, 42, 43, 44, 45,
|
|
46, 47, 48, 49, 50, 51, 52, 53,
|
|
54, 55, 56, 29
|
|
};
|
|
|
|
const uint8_t shiftkeyinv_permtab[] = {
|
|
7, 7,
|
|
28, 1, 2, 3, 4, 5, 6, 7,
|
|
8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23,
|
|
24, 25, 26, 27,
|
|
56, 29, 30, 31, 32, 33, 34, 35,
|
|
36, 37, 38, 39, 40, 41, 42, 43,
|
|
44, 45, 46, 47, 48, 49, 50, 51,
|
|
52, 53, 54, 55
|
|
};
|
|
|
|
/*
|
|
1 0
|
|
1 0
|
|
2 1
|
|
2 1
|
|
2 1
|
|
2 1
|
|
2 1
|
|
2 1
|
|
----
|
|
1 0
|
|
2 1
|
|
2 1
|
|
2 1
|
|
2 1
|
|
2 1
|
|
2 1
|
|
1 0
|
|
*/
|
|
#define ROTTABLE 0x7EFC
|
|
#define ROTTABLE_INV 0x3F7E
|
|
/******************************************************************************/
|
|
|
|
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
|
|
uint8_t ob; /* in-bytes and out-bytes */
|
|
uint8_t byte, bit; /* counter for bit and byte */
|
|
ob = ptable[1];
|
|
ptable = &(ptable[2]);
|
|
for(byte=0; byte<ob; ++byte){
|
|
uint8_t x,t=0;
|
|
for(bit=0; bit<8; ++bit){
|
|
x = *ptable++ - 1;
|
|
t<<=1;
|
|
if((in[x/8]) & (0x80>>(x%8)) ){
|
|
t|=0x01;
|
|
}
|
|
}
|
|
out[byte]=t;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void changeendian32(uint32_t * a){
|
|
*a = (*a & 0x000000FF) << 24 |
|
|
(*a & 0x0000FF00) << 8 |
|
|
(*a & 0x00FF0000) >> 8 |
|
|
(*a & 0xFF000000) >> 24;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
static inline
|
|
void shiftkey(uint8_t *key){
|
|
uint8_t k[7];
|
|
memcpy(k, key, 7);
|
|
permute((uint8_t*)shiftkey_permtab, k, key);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
static inline
|
|
void shiftkey_inv(uint8_t *key){
|
|
uint8_t k[7];
|
|
memcpy(k, key, 7);
|
|
permute((uint8_t*)shiftkeyinv_permtab, k, key);
|
|
|
|
}
|
|
|
|
/******************************************************************************/
|
|
static inline
|
|
uint64_t splitin6bitwords(uint64_t a){
|
|
uint64_t ret=0;
|
|
a &= 0x0000ffffffffffffLL;
|
|
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
static inline
|
|
uint8_t substitute(uint8_t a, uint8_t * sbp){
|
|
uint8_t x;
|
|
x = sbp[a>>1];
|
|
x = (a&1)?x&0x0F:x>>4;
|
|
return x;
|
|
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
uint32_t des_f(uint32_t r, uint8_t* kr){
|
|
uint8_t i;
|
|
uint32_t t=0,ret;
|
|
uint64_t data;
|
|
uint8_t *sbp; /* sboxpointer */
|
|
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
|
|
for(i=0; i<6; ++i)
|
|
((uint8_t*)&data)[i] ^= kr[i];
|
|
|
|
/* Sbox substitution */
|
|
data = splitin6bitwords(data);
|
|
sbp=(uint8_t*)sbox;
|
|
for(i=0; i<8; ++i){
|
|
uint8_t x;
|
|
x = substitute(((uint8_t*)&data)[i], sbp);
|
|
t<<=4;
|
|
t |= x;
|
|
sbp += 32;
|
|
}
|
|
changeendian32(&t);
|
|
|
|
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void des_enc(void* out, const void* in, const void* key){
|
|
#define R *((uint32_t*)&(data[4]))
|
|
#define L *((uint32_t*)&(data[0]))
|
|
|
|
uint8_t data[8],kr[6],k[7];
|
|
uint8_t i;
|
|
|
|
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
|
|
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
|
|
for(i=0; i<8; ++i){
|
|
shiftkey(k);
|
|
if(ROTTABLE&((1<<((i<<1)+0))) )
|
|
shiftkey(k);
|
|
permute((uint8_t*)pc2_permtab, k, kr);
|
|
L ^= des_f(R, kr);
|
|
|
|
shiftkey(k);
|
|
if(ROTTABLE&((1<<((i<<1)+1))) )
|
|
shiftkey(k);
|
|
permute((uint8_t*)pc2_permtab, k, kr);
|
|
R ^= des_f(L, kr);
|
|
|
|
}
|
|
/* L <-> R*/
|
|
R ^= L;
|
|
L ^= R;
|
|
R ^= L;
|
|
|
|
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void des_dec(void* out, const void* in, const uint8_t* key){
|
|
#define R *((uint32_t*)&(data[4]))
|
|
#define L *((uint32_t*)&(data[0]))
|
|
|
|
uint8_t data[8],kr[6],k[7];
|
|
int8_t i;
|
|
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
|
|
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
|
|
for(i=7; i>=0; --i){
|
|
|
|
permute((uint8_t*)pc2_permtab, k, kr);
|
|
L ^= des_f(R, kr);
|
|
shiftkey_inv(k);
|
|
if(ROTTABLE&((1<<((i<<1)+1))) ){
|
|
shiftkey_inv(k);
|
|
}
|
|
|
|
permute((uint8_t*)pc2_permtab, k, kr);
|
|
R ^= des_f(L, kr);
|
|
shiftkey_inv(k);
|
|
if(ROTTABLE&((1<<((i<<1)+0))) ){
|
|
shiftkey_inv(k);
|
|
}
|
|
|
|
}
|
|
/* L <-> R*/
|
|
R ^= L;
|
|
L ^= R;
|
|
R ^= L;
|
|
|
|
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void tdes_enc(void* out, void* in, const void* key){
|
|
des_enc(out, in, (uint8_t*)key + 0);
|
|
des_dec(out, out, (uint8_t*)key + 8);
|
|
des_enc(out, out, (uint8_t*)key +16);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
void tdes_dec(void* out, void* in, const uint8_t* key){
|
|
des_dec(out, in, (uint8_t*)key +16);
|
|
des_enc(out, out, (uint8_t*)key + 8);
|
|
des_dec(out, out, (uint8_t*)key + 0);
|
|
}
|
|
|
|
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
|
|
|
|
if( length % 8 ) return;
|
|
|
|
uint8_t i;
|
|
uint8_t* tin = (uint8_t*) in;
|
|
uint8_t* tout = (uint8_t*) out;
|
|
|
|
while( length > 0 )
|
|
{
|
|
for( i = 0; i < 8; i++ )
|
|
tout[i] = (unsigned char)( tin[i] ^ iv[i] );
|
|
|
|
des_enc(tout, tin, (uint8_t*)key + 0);
|
|
des_dec(tout, tout, (uint8_t*)key + 8);
|
|
des_enc(tout, tout, (uint8_t*)key + 0);
|
|
|
|
memcpy( iv, tout, 8 );
|
|
|
|
tin += 8;
|
|
tout += 8;
|
|
length -= 8;
|
|
}
|
|
}
|
|
|
|
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
|
|
|
|
if( length % 8 ) return;
|
|
|
|
uint8_t i;
|
|
unsigned char temp[8];
|
|
uint8_t* tin = (uint8_t*) in;
|
|
uint8_t* tout = (uint8_t*) out;
|
|
|
|
while( length > 0 )
|
|
{
|
|
memcpy( temp, tin, 8 );
|
|
|
|
des_dec(tout, tin, (uint8_t*)key + 0);
|
|
des_enc(tout, tout, (uint8_t*)key + 8);
|
|
des_dec(tout, tout, (uint8_t*)key + 0);
|
|
|
|
for( i = 0; i < 8; i++ )
|
|
tout[i] = (unsigned char)( tout[i] ^ iv[i] );
|
|
|
|
memcpy( iv, temp, 8 );
|
|
|
|
tin += 8;
|
|
tout += 8;
|
|
length -= 8;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|