From 51effd04531790e303aaa87678d37a8b4ec3d9d8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 18 Jan 2026 03:56:57 +0100 Subject: [PATCH] MDS v2 structures and decode/crypto utilities from Marisa-Chan's repository in preparation for MDS v2/MDX support implementation. --- src/cdrom/cdrom_image.c | 66 +- src/utils/CMakeLists.txt | 36 + src/utils/common/crc.c | 133 +++ src/utils/common/crc.h | 37 + src/utils/common/crypto.c | 1653 +++++++++++++++++++++++++++++ src/utils/common/crypto.h | 304 ++++++ src/utils/common/endian.c | 57 + src/utils/common/endian.h | 138 +++ src/utils/common/gfmul.c | 893 ++++++++++++++++ src/utils/common/gfmul.h | 78 ++ src/utils/common/password.h | 39 + src/utils/common/pkcs5.c | 631 +++++++++++ src/utils/common/pkcs5.h | 41 + src/utils/common/tcdefs.h | 167 +++ src/utils/common/xts.c | 627 +++++++++++ src/utils/common/xts.h | 79 ++ src/utils/crypto/aes.h | 215 ++++ src/utils/crypto/aes_x64.asm | 904 ++++++++++++++++ src/utils/crypto/aes_x86.asm | 644 +++++++++++ src/utils/crypto/aescrypt.c | 311 ++++++ src/utils/crypto/aeskey.c | 577 ++++++++++ src/utils/crypto/aesopt.h | 731 +++++++++++++ src/utils/crypto/aessmall.c | 921 ++++++++++++++++ src/utils/crypto/aessmall.h | 169 +++ src/utils/crypto/aessmall_x86.asm | 1444 +++++++++++++++++++++++++ src/utils/crypto/aestab.c | 427 ++++++++ src/utils/crypto/aestab.h | 174 +++ src/utils/crypto/bf_ecb.c | 113 ++ src/utils/crypto/bf_enc.c | 235 ++++ src/utils/crypto/bf_locl.h | 246 +++++ src/utils/crypto/bf_pi.h | 327 ++++++ src/utils/crypto/bf_skey.c | 118 ++ src/utils/crypto/blowfish.h | 120 +++ src/utils/crypto/c_ecb.c | 80 ++ src/utils/crypto/c_enc.c | 201 ++++ src/utils/crypto/c_skey.c | 164 +++ src/utils/crypto/cast.h | 113 ++ src/utils/crypto/cast_lcl.h | 225 ++++ src/utils/crypto/cast_s.h | 530 +++++++++ src/utils/crypto/des.c | 4 + src/utils/crypto/des.h | 292 +++++ src/utils/crypto/des_enc.c | 479 +++++++++ src/utils/crypto/des_locl.h | 518 +++++++++ src/utils/crypto/ecb3_enc.c | 84 ++ src/utils/crypto/podd.h | 77 ++ src/utils/crypto/rmd160.c | 510 +++++++++ src/utils/crypto/rmd160.h | 63 ++ src/utils/crypto/serpent.c | 940 ++++++++++++++++ src/utils/crypto/serpent.h | 19 + src/utils/crypto/set_key.c | 233 ++++ src/utils/crypto/set_key.h | 6 + src/utils/crypto/sha1.c | 280 +++++ src/utils/crypto/sha1.h | 80 ++ src/utils/crypto/sha2.c | 770 ++++++++++++++ src/utils/crypto/sha2.h | 155 +++ src/utils/crypto/sk.h | 206 ++++ src/utils/crypto/spr.h | 206 ++++ src/utils/crypto/twofish.c | 548 ++++++++++ src/utils/crypto/twofish.h | 56 + src/utils/crypto/whirlpool.c | 1058 ++++++++++++++++++ src/utils/crypto/whirlpool.h | 150 +++ src/utils/decode.c | 462 ++++++++ src/utils/defines.h | 13 + src/utils/edc.c | 78 ++ src/utils/edc.h | 8 + src/utils/mds.h | 188 ++++ src/utils/utils.c | 27 + 67 files changed, 21470 insertions(+), 8 deletions(-) create mode 100644 src/utils/common/crc.c create mode 100644 src/utils/common/crc.h create mode 100644 src/utils/common/crypto.c create mode 100644 src/utils/common/crypto.h create mode 100644 src/utils/common/endian.c create mode 100644 src/utils/common/endian.h create mode 100644 src/utils/common/gfmul.c create mode 100644 src/utils/common/gfmul.h create mode 100644 src/utils/common/password.h create mode 100644 src/utils/common/pkcs5.c create mode 100644 src/utils/common/pkcs5.h create mode 100644 src/utils/common/tcdefs.h create mode 100644 src/utils/common/xts.c create mode 100644 src/utils/common/xts.h create mode 100644 src/utils/crypto/aes.h create mode 100644 src/utils/crypto/aes_x64.asm create mode 100644 src/utils/crypto/aes_x86.asm create mode 100644 src/utils/crypto/aescrypt.c create mode 100644 src/utils/crypto/aeskey.c create mode 100644 src/utils/crypto/aesopt.h create mode 100644 src/utils/crypto/aessmall.c create mode 100644 src/utils/crypto/aessmall.h create mode 100644 src/utils/crypto/aessmall_x86.asm create mode 100644 src/utils/crypto/aestab.c create mode 100644 src/utils/crypto/aestab.h create mode 100644 src/utils/crypto/bf_ecb.c create mode 100644 src/utils/crypto/bf_enc.c create mode 100644 src/utils/crypto/bf_locl.h create mode 100644 src/utils/crypto/bf_pi.h create mode 100644 src/utils/crypto/bf_skey.c create mode 100644 src/utils/crypto/blowfish.h create mode 100644 src/utils/crypto/c_ecb.c create mode 100644 src/utils/crypto/c_enc.c create mode 100644 src/utils/crypto/c_skey.c create mode 100644 src/utils/crypto/cast.h create mode 100644 src/utils/crypto/cast_lcl.h create mode 100644 src/utils/crypto/cast_s.h create mode 100644 src/utils/crypto/des.c create mode 100644 src/utils/crypto/des.h create mode 100644 src/utils/crypto/des_enc.c create mode 100644 src/utils/crypto/des_locl.h create mode 100644 src/utils/crypto/ecb3_enc.c create mode 100644 src/utils/crypto/podd.h create mode 100644 src/utils/crypto/rmd160.c create mode 100644 src/utils/crypto/rmd160.h create mode 100644 src/utils/crypto/serpent.c create mode 100644 src/utils/crypto/serpent.h create mode 100644 src/utils/crypto/set_key.c create mode 100644 src/utils/crypto/set_key.h create mode 100644 src/utils/crypto/sha1.c create mode 100644 src/utils/crypto/sha1.h create mode 100644 src/utils/crypto/sha2.c create mode 100644 src/utils/crypto/sha2.h create mode 100644 src/utils/crypto/sk.h create mode 100644 src/utils/crypto/spr.h create mode 100644 src/utils/crypto/twofish.c create mode 100644 src/utils/crypto/twofish.h create mode 100644 src/utils/crypto/whirlpool.c create mode 100644 src/utils/crypto/whirlpool.h create mode 100644 src/utils/decode.c create mode 100644 src/utils/defines.h create mode 100644 src/utils/edc.c create mode 100644 src/utils/edc.h create mode 100644 src/utils/mds.h create mode 100644 src/utils/utils.c diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 6452868ab..6712912ad 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -175,6 +175,20 @@ typedef struct uint32_t trk_blocks_offs; } mds_sess_block_t; /* 24 bytes */ +/* MDF v2.01 session block. */ +typedef struct +{ + int64_t sess_start; + uint16_t sess_id; + uint8_t all_blocks_num; + uint8_t non_track_blocks_num; + uint16_t first_trk; + uint16_t last_trk; + uint32_t pad; + uint32_t trk_blocks_offs; + int64_t sess_end; +} mds_v2_sess_block_t; /* 24 bytes */ + typedef struct { uint8_t trk_mode; @@ -220,6 +234,17 @@ typedef struct uint32_t pad0; } mds_footer_t; /* 16 bytes */ +/* MDF v2.01 track footer block. */ +typedef struct +{ + uint32_t fn_offs; + uint32_t pad; /* Always wide */ + uint32_t pad0; + uint32_t pad1; + uint64_t trk_sectors; + uint64_t pad2; +} mds_v2_footer_t; /* 16 bytes */ + typedef struct { uint32_t type; @@ -1949,6 +1974,7 @@ image_load_mds(cd_image_t *img, const char *mdsfile) track_index_t *ci = NULL; track_file_t *tf = NULL; int is_viso = 0; + int version = 1; int last_t = -1; int error; char pathname[MAX_FILENAME_LENGTH]; @@ -1956,9 +1982,11 @@ image_load_mds(cd_image_t *img, const char *mdsfile) mds_hdr_t mds_hdr = { 0 }; mds_sess_block_t mds_sess_block = { 0 }; + mds_v2_sess_block_t mds_v2_sess_block = { 0 }; mds_trk_block_t mds_trk_block = { 0 }; mds_trk_ex_block_t mds_trk_ex_block = { 0 }; mds_footer_t mds_footer = { 0 }; + mds_v2_footer_t mds_v2_footer = { 0 }; mds_dpm_block_t mds_dpm_block = { 0 }; uint32_t mds_dpm_blocks_num = 0x00000000; uint32_t mds_dpm_block_offs = 0x00000000; @@ -2006,6 +2034,7 @@ image_load_mds(cd_image_t *img, const char *mdsfile) #else warning("\"%s\" is a Daemon Tools encrypted MDS which is not supported\n", mdsfile); #endif + version = 2; fclose(fp); return 0; } @@ -2083,9 +2112,18 @@ image_load_mds(cd_image_t *img, const char *mdsfile) } for (int s = 0; s < mds_hdr.sess_num; s++) { - fseek(fp, mds_hdr.sess_blocks_offs + (s * sizeof(mds_sess_block_t)), SEEK_SET); - if (fread(&mds_sess_block, 1, sizeof(mds_sess_block_t), fp) != sizeof(mds_sess_block_t)) - return 0; + if (version == 2) { + fseek(fp, mds_hdr.sess_blocks_offs + (s * sizeof(mds_v2_sess_block_t)), SEEK_SET); + if (fread(&mds_v2_sess_block, 1, sizeof(mds_v2_sess_block_t), fp) != sizeof(mds_v2_sess_block_t)) + return 0; + memcpy(&mds_sess_block, &mds_v2_sess_block, sizeof(mds_sess_block_t)); + mds_sess_block.sess_start = (int32_t) mds_v2_sess_block.sess_start; + mds_sess_block.sess_end = (int32_t) mds_v2_sess_block.sess_end; + } else { + fseek(fp, mds_hdr.sess_blocks_offs + (s * sizeof(mds_sess_block_t)), SEEK_SET); + if (fread(&mds_sess_block, 1, sizeof(mds_sess_block_t), fp) != sizeof(mds_sess_block_t)) + return 0; + } for (int t = 0; t < mds_sess_block.all_blocks_num; t++) { fseek(fp, mds_sess_block.trk_blocks_offs + (t * sizeof(mds_trk_block_t)), SEEK_SET); @@ -2127,9 +2165,17 @@ image_load_mds(cd_image_t *img, const char *mdsfile) uint32_t astart2 = mds_trk_block.start_sect + mds_trk_ex_block.trk_sectors; if (mds_trk_block.footer_offs != 0ULL) for (uint32_t ff = 0; ff < mds_trk_block.files_num; ff++) { - fseek(fp, mds_trk_block.footer_offs + (ff * sizeof(mds_footer_t)), SEEK_SET); - if (fread(&mds_footer, 1, sizeof(mds_footer_t), fp) != sizeof(mds_footer_t)) - return 0; + if (version == 2) { + fseek(fp, mds_trk_block.footer_offs + (ff * sizeof(mds_v2_footer_t)), SEEK_SET); + if (fread(&mds_v2_footer, 1, sizeof(mds_v2_footer_t), fp) != sizeof(mds_v2_footer_t)) + return 0; + memcpy(&mds_footer, &mds_v2_footer, sizeof(mds_footer)); + mds_footer.fn_is_wide = 1; + } else { + fseek(fp, mds_trk_block.footer_offs + (ff * sizeof(mds_footer_t)), SEEK_SET); + if (fread(&mds_footer, 1, sizeof(mds_footer_t), fp) != sizeof(mds_footer_t)) + return 0; + } uint16_t wfn[2048] = { 0 }; char fn[2048] = { 0 }; @@ -2149,7 +2195,10 @@ image_load_mds(cd_image_t *img, const char *mdsfile) break; } - if (!stricmp(fn, "*.mdf")) { + if (strlen(fn) == 0) + /* This is in MDX files - the file name string is empty. */ + strcpy(fn, mdsfile); + else if (!stricmp(fn, "*.mdf")) { strcpy(fn, mdsfile); fn[strlen(mdsfile) - 3] = 'm'; fn[strlen(mdsfile) - 2] = 'd'; @@ -2681,7 +2730,8 @@ image_open(cdrom_t *dev, const char *path) if (img != NULL) { int ret; const int is_cue = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "CUE")); - const int is_mds = ((ext == 4) && !stricmp(path + strlen(path) - ext + 1, "MDS")); + const int is_mds = ((ext == 4) && (!stricmp(path + strlen(path) - ext + 1, "MDS") || + !stricmp(path + strlen(path) - ext + 1, "MDX"))); char n[1024] = { 0 }; sprintf(n, "CD-ROM %i Image", dev->id + 1); diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index bcbc7aafd..55525752b 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -16,12 +16,48 @@ # add_library(utils OBJECT + + # Core cJSON.c crc.c crc32.c + decode.c + edc.c fifo.c fifo8.c ini.c log.c random.c + utils.c + + # Common + common/crc.c + common/crypto.c + common/endian.c + common/gfmul.c + common/pkcs5.c + common/xts.c + + # Crypto + crypto/aescrypt.c + crypto/aeskey.c + crypto/aessmall.c + crypto/aestab.c + crypto/bf_ecb.c + crypto/bf_enc.c + crypto/bf_skey.c + crypto/c_ecb.c + crypto/c_enc.c + crypto/c_skey.c + crypto/des.c + crypto/des_enc.c + crypto/ecb3_enc.c + crypto/rmd160.c + crypto/serpent.c + crypto/set_key.c + crypto/sha1.c + crypto/sha2.c + crypto/twofish.c + crypto/whirlpool.c + ) diff --git a/src/utils/common/crc.c b/src/utils/common/crc.c new file mode 100644 index 000000000..7e06b95b5 --- /dev/null +++ b/src/utils/common/crc.c @@ -0,0 +1,133 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "tcdefs.h" +#include "crc.h" +#include "../common/endian.h" + +#ifndef TC_MINIMIZE_CODE_SIZE + +/* CRC polynomial 0x04c11db7 */ +uint32_t crc_32_tab[]= +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t GetCrc32 (unsigned char *data, int length) +{ + uint32_t CRC = 0xffffffff; + + while (length--) + { + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *data++) & 0xFF ]; + } + + return CRC ^ 0xffffffff; +} + +uint32_t crc32int (uint32_t *data) +{ + unsigned char *d = (unsigned char *) data; + uint32_t CRC = 0xffffffff; + + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; + CRC = (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d++) & 0xFF ]; + return (CRC >> 8) ^ crc_32_tab[ (CRC ^ *d) & 0xFF ] ^ 0xffffffff; +} + +#if BYTE_ORDER == LITTLE_ENDIAN +# define CRC_SELFTEST 0x6fcf9e13 +#else +# define CRC_SELFTEST 0xca87914d +#endif + +int crc32_selftests (void) +{ + int i; + uint32_t crc = 0xffffffff; + int bSuccess = 0; + + for (i = 0; i < (int)sizeof(crc_32_tab); i++) + crc = UPDC32 (((unsigned char *) crc_32_tab)[i], crc); + + bSuccess = CRC_SELFTEST == (crc ^ 0xffffffff); + + bSuccess &= GetCrc32 ((unsigned char *)crc_32_tab, sizeof crc_32_tab) == CRC_SELFTEST; + + return bSuccess; +} + +#else // TC_MINIMIZE_CODE_SIZE + +uint32_t GetCrc32 (unsigned char *data, int length) +{ + uint32_t r = 0xFFFFFFFFUL; + int i, b; + + for (i = 0; i < length; ++i) + { + r ^= data[i]; + for (b = 0; b < 8; ++b) + { + if ((unsigned __int8) r & 1) + r = (r >> 1) ^ 0xEDB88320UL; + else + r >>= 1; + } + } + + return r ^ 0xFFFFFFFFUL; +} + +int crc32_selftests () +{ + unsigned __int8 testData[32]; + unsigned __int8 i; + + for (i = 0; i < sizeof (testData); ++i) + testData[i] = i; + + return GetCrc32 (testData, sizeof (testData)) == 0x91267E8AUL; +} + +#endif // TC_MINIMIZE_CODE_SIZE diff --git a/src/utils/common/crc.h b/src/utils/common/crc.h new file mode 100644 index 000000000..0fef2a311 --- /dev/null +++ b/src/utils/common/crc.h @@ -0,0 +1,37 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_CRC +#define TC_HEADER_CRC + +#include + +#include "tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define UPDC32(octet, crc)\ + (uint32_t)((crc_32_tab[(((uint32_t)(crc)) ^ ((unsigned char)(octet))) & 0xff] ^ (((uint32_t)(crc)) >> 8))) + +uint32_t GetCrc32 (unsigned char *data, int length); +uint32_t crc32int (uint32_t *data); +int crc32_selftests (void); + +extern uint32_t crc_32_tab[]; + +#if defined(__cplusplus) +} +#endif + +#endif // TC_HEADER_CRC diff --git a/src/utils/common/crypto.c b/src/utils/common/crypto.c new file mode 100644 index 000000000..8edef29bb --- /dev/null +++ b/src/utils/common/crypto.c @@ -0,0 +1,1653 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "tcdefs.h" +#include "crypto.h" +#include "xts.h" +#include "crc.h" +#include "../common/endian.h" +#include + +/* Update the following when adding a new cipher or EA: + + Crypto.h: + ID #define + MAX_EXPANDED_KEY #define + + Crypto.c: + Ciphers[] + EncryptionAlgorithms[] + CipherInit() + EncipherBlock() + DecipherBlock() + +*/ + +// Cipher configuration +static Cipher Ciphers[] = +{ +// Block Size Key Size Key Schedule Size +// ID Name (Bytes) (Bytes) (Bytes) + { AES256, "AES256", 16, 32, AES_KS }, + { AES192, "AES192", 16, 24, AES_KS }, + { AES128, "AES128", 16, 16, AES_KS }, + { BLOWFISH, "Blowfish", 8, 56, 4168 }, // Deprecated/legacy + { CAST, "CAST5", 8, 16, 128 }, // Deprecated/legacy + { DES56, "DES", 8, 7, 128 }, // Deprecated/legacy + { SERPENT, "Serpent", 16, 32, 140*4 }, + { TRIPLEDES,"Triple DES", 8, 8*3, 128*3 }, // Deprecated/legacy + { TWOFISH, "Twofish", 16, 32, TWOFISH_KS }, + { 0, 0, 0, 0, 0 } +}; + + +// Encryption algorithm configuration +// The following modes have been deprecated (legacy): LRW, CBC, INNER_CBC, OUTER_CBC +static EncryptionAlgorithm EncryptionAlgorithms[] = +{ + // Cipher(s) Modes FormatEnabled + + { { 0, 0 }, { 0, 0, 0, 0 }, 0 }, // Must be all-zero + { { AES256, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { AES192, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { AES128, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { BLOWFISH, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { CAST, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { SERPENT, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { TRIPLEDES, 0 }, { LRW, CBC, 0, 0 }, 0 }, // Deprecated/legacy + { { TWOFISH, 0 }, { XTS, LRW, CBC, 0 }, 1 }, + { { TWOFISH, AES256, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, AES256, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { AES256, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { AES256, TWOFISH, SERPENT, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { SERPENT, TWOFISH, 0 }, { XTS, LRW, OUTER_CBC, 0 }, 1 }, + { { BLOWFISH, AES256, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy + { { SERPENT, BLOWFISH, AES256, 0 }, { INNER_CBC, 0, 0, 0 }, 0 }, // Deprecated/legacy + { { 0, 0 }, { 0, 0, 0, 0 }, 0 } // Must be all-zero + +}; + + + +// Hash algorithms +static Hash Hashes[] = +{ // ID Name Deprecated System Encryption + { RIPEMD160, "RIPEMD-160", 0, 1 }, + { SHA512, "SHA-512", 0, 0 }, + { WHIRLPOOL, "Whirlpool", 0, 0 }, + { SHA1, "SHA-1", 1, 0 }, // Deprecated/legacy + { 0, 0, 0 } +}; + +/* Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) */ +int CipherInit (int cipher, unsigned char *key, uint8_t *ks) +{ + int retVal = ERR_SUCCESS; + + switch (cipher) + { + case AES256: + if (aes_encrypt_key256 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + + if (aes_decrypt_key256 (key, (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + break; + + case AES192: + if (aes_encrypt_key192 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + + if (aes_decrypt_key192 (key, (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + break; + + case AES128: + if (aes_encrypt_key128 (key, (aes_encrypt_ctx *) ks) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + + if (aes_decrypt_key128 (key, (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx))) != EXIT_SUCCESS) + return ERR_CIPHER_INIT_FAILURE; + break; + + case SERPENT: + serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks); + break; + + case TWOFISH: + twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, CipherGetKeySize(TWOFISH) * 8); + break; + + case BLOWFISH: + /* Deprecated/legacy */ + BF_set_key ((BF_KEY *)ks, CipherGetKeySize(BLOWFISH), key); + break; + + case DES56: + /* Deprecated/legacy */ + switch (des_key_sched ((des_cblock *) key, (struct des_ks_struct *) ks)) + { + case -1: + return ERR_CIPHER_INIT_FAILURE; + case -2: + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; + } + break; + + case CAST: + /* Deprecated/legacy */ + CAST_set_key((CAST_KEY *) ks, CipherGetKeySize(CAST), key); + break; + + case TRIPLEDES: + /* Deprecated/legacy */ + switch (des_key_sched ((des_cblock *) key, (struct des_ks_struct *) ks)) + { + case -1: + return ERR_CIPHER_INIT_FAILURE; + case -2: + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; + } + switch (des_key_sched ((des_cblock *) ((char*)(key)+8), (struct des_ks_struct *) (ks + CipherGetKeyScheduleSize (DES56)))) + { + case -1: + return ERR_CIPHER_INIT_FAILURE; + case -2: + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; + } + switch (des_key_sched ((des_cblock *) ((char*)(key)+16), (struct des_ks_struct *) (ks + CipherGetKeyScheduleSize (DES56) * 2))) + { + case -1: + return ERR_CIPHER_INIT_FAILURE; + case -2: + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; + } + + // Verify whether all three DES keys are mutually different + if (((*((int64_t *) key) ^ *((int64_t *) key+1)) & 0xFEFEFEFEFEFEFEFEULL) == 0 + || ((*((int64_t *) key+1) ^ *((int64_t *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0 + || ((*((int64_t *) key) ^ *((int64_t *) key+2)) & 0xFEFEFEFEFEFEFEFEULL) == 0) + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + + break; + + default: + // Unknown/wrong cipher ID + return ERR_CIPHER_INIT_FAILURE; + } + + return retVal; +} + +void EncipherBlock(int cipher, void *data, void *ks) +{ + switch (cipher) + { + case AES256: + case AES192: + case AES128: + aes_encrypt (data, data, ks); break; + case TWOFISH: twofish_encrypt (ks, data, data); break; + case SERPENT: serpent_encrypt (data, data, ks); break; + case BLOWFISH: BF_ecb_le_encrypt (data, data, ks, 1); break; // Deprecated/legacy + case DES56: des_encrypt (data, ks, 1); break; // Deprecated/legacy + case CAST: CAST_ecb_encrypt (data, data, ks, 1); break; // Deprecated/legacy + case TRIPLEDES: des_ecb3_encrypt (data, data, ks, // Deprecated/legacy + (void*)((char*) ks + CipherGetKeyScheduleSize (DES56)), (void*)((char*) ks + CipherGetKeyScheduleSize (DES56) * 2), 1); break; + default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID + } +} + +void DecipherBlock(int cipher, void *data, void *ks) +{ + switch (cipher) + { + case SERPENT: serpent_decrypt (data, data, ks); break; + case TWOFISH: twofish_decrypt (ks, data, data); break; + case AES256: + case AES192: + case AES128: + aes_decrypt (data, data, (void *) ((char *) ks + sizeof(aes_encrypt_ctx))); break; + case BLOWFISH: BF_ecb_le_encrypt (data, data, ks, 0); break; // Deprecated/legacy + case DES56: des_encrypt (data, ks, 0); break; // Deprecated/legacy + case CAST: CAST_ecb_encrypt (data, data, ks,0); break; // Deprecated/legacy + case TRIPLEDES: des_ecb3_encrypt (data, data, ks, // Deprecated/legacy + (void*)((char*) ks + CipherGetKeyScheduleSize (DES56)), + (void*)((char*) ks + CipherGetKeyScheduleSize (DES56) * 2), 0); break; + default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID + } +} + +// Ciphers support + +Cipher *CipherGet (int id) +{ + int i; + for (i = 0; Ciphers[i].Id != 0; i++) + if (Ciphers[i].Id == id) + return &Ciphers[i]; + + return NULL; +} + +char *CipherGetName (int cipherId) +{ + return CipherGet (cipherId) -> Name; +} + +int CipherGetBlockSize (int cipherId) +{ + return CipherGet (cipherId) -> BlockSize; +} + +int CipherGetKeySize (int cipherId) +{ + return CipherGet (cipherId) -> KeySize; +} + +int CipherGetKeyScheduleSize (int cipherId) +{ + return CipherGet (cipherId) -> KeyScheduleSize; +} + + +// Encryption algorithms support + +int EAGetFirst (void) +{ + return 1; +} + +// Returns number of EAs +int EAGetCount (void) +{ + int ea, count = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + count++; + } + return count; +} + +int EAGetNext (int previousEA) +{ + int id = previousEA + 1; + if (EncryptionAlgorithms[id].Ciphers[0] != 0) return id; + return 0; +} + + +// Return values: 0 = success, ERR_CIPHER_INIT_FAILURE (fatal), ERR_CIPHER_INIT_WEAK_KEY (non-fatal) +int EAInit (int ea, unsigned char *key, uint8_t *ks) +{ + int c, retVal = ERR_SUCCESS; + + if (ea == 0) + return ERR_CIPHER_INIT_FAILURE; + + for (c = EAGetFirstCipher (ea); c != 0; c = EAGetNextCipher (ea, c)) + { + switch (CipherInit (c, key, ks)) + { + case ERR_CIPHER_INIT_FAILURE: + return ERR_CIPHER_INIT_FAILURE; + + case ERR_CIPHER_INIT_WEAK_KEY: + retVal = ERR_CIPHER_INIT_WEAK_KEY; // Non-fatal error + break; + } + + key += CipherGetKeySize (c); + ks += CipherGetKeyScheduleSize (c); + } + return retVal; +} + + +int EAInitMode (PCRYPTO_INFO ci) +{ + switch (ci->mode) + { + case XTS: + // Secondary key schedule + if (EAInit (ci->ea, ci->k2, ci->ks2) != ERR_SUCCESS) + return 0; + + /* Note: XTS mode could potentially be initialized with a weak key causing all blocks in one data unit + on the volume to be tweaked with zero tweaks (i.e. 512 bytes of the volume would be encrypted in ECB + mode). However, to create a TrueCrypt volume with such a weak key, each human being on Earth would have + to create approximately 11,378,125,361,078,862 (about eleven quadrillion) TrueCrypt volumes (provided + that the size of each of the volumes is 1024 terabytes). */ + break; + + case LRW: + switch (CipherGetBlockSize (EAGetFirstCipher (ci->ea))) + { + case 8: + /* Deprecated/legacy */ + return Gf64TabInit (ci->k2, &ci->gf_ctx); + + case 16: + return Gf128Tab64Init (ci->k2, &ci->gf_ctx); + + default: + TC_THROW_FATAL_EXCEPTION; + } + + break; + + case CBC: + case INNER_CBC: + case OUTER_CBC: + // The mode does not need to be initialized or is initialized elsewhere + return 1; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + return 1; +} + + +// Returns name of EA, cascaded cipher names are separated by hyphens +char *EAGetName (char *buf, int ea) +{ + int i = EAGetLastCipher(ea); + strcpy (buf, (i != 0) ? CipherGetName (i) : "?"); + + while ((i = EAGetPreviousCipher(ea, i))) + { + strcat (buf, "-"); + strcat (buf, CipherGetName (i)); + } + + return buf; +} + + +int EAGetByName (char *name) +{ + int ea = EAGetFirst (); + char n[128]; + + do + { + EAGetName (n, ea); + if (strcmp (n, name) == 0) + return ea; + } + while ((ea = EAGetNext (ea))); + + return 0; +} + +// Returns sum of key sizes of all ciphers of the EA (in bytes) +int EAGetKeySize (int ea) +{ + int i = EAGetFirstCipher (ea); + int size = CipherGetKeySize (i); + + while ((i = EAGetNextCipher (ea, i))) + { + size += CipherGetKeySize (i); + } + + return size; +} + + +// Returns the first mode of operation of EA +int EAGetFirstMode (int ea) +{ + return (EncryptionAlgorithms[ea].Modes[0]); +} + + +int EAGetNextMode (int ea, int previousModeId) +{ + int c, i = 0; + while ((c = EncryptionAlgorithms[ea].Modes[i++])) + { + if (c == previousModeId) + return EncryptionAlgorithms[ea].Modes[i]; + } + + return 0; +} + + +// Returns the name of the mode of operation of the whole EA +char *EAGetModeName (int ea, int mode, int capitalLetters) +{ + switch (mode) + { + case XTS: + + return "XTS"; + + case LRW: + + /* Deprecated/legacy */ + + return "LRW"; + + case CBC: + { + /* Deprecated/legacy */ + + char eaName[100]; + EAGetName (eaName, ea); + + if (strcmp (eaName, "Triple DES") == 0) + return capitalLetters ? "Outer-CBC" : "outer-CBC"; + + return "CBC"; + } + + case OUTER_CBC: + + /* Deprecated/legacy */ + + return capitalLetters ? "Outer-CBC" : "outer-CBC"; + + case INNER_CBC: + + /* Deprecated/legacy */ + + return capitalLetters ? "Inner-CBC" : "inner-CBC"; + + } + return "[unknown]"; +} + + + +// Returns sum of key schedule sizes of all ciphers of the EA +int EAGetKeyScheduleSize (int ea) +{ + int i = EAGetFirstCipher(ea); + int size = CipherGetKeyScheduleSize (i); + + while ((i = EAGetNextCipher(ea, i))) + { + size += CipherGetKeyScheduleSize (i); + } + + return size; +} + + +// Returns the largest key size needed by an EA for the specified mode of operation +int EAGetLargestKeyForMode (int mode) +{ + int ea, key = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (!EAIsModeSupported (ea, mode)) + continue; + + if (EAGetKeySize (ea) >= key) + key = EAGetKeySize (ea); + } + return key; +} + + +// Returns the largest key needed by any EA for any mode +int EAGetLargestKey (void) +{ + int ea, key = 0; + + for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) + { + if (EAGetKeySize (ea) >= key) + key = EAGetKeySize (ea); + } + + return key; +} + + +// Returns number of ciphers in EA +int EAGetCipherCount (int ea) +{ + int i = 0; + while (EncryptionAlgorithms[ea].Ciphers[i++]); + + return i - 1; +} + + +int EAGetFirstCipher (int ea) +{ + return EncryptionAlgorithms[ea].Ciphers[0]; +} + + +int EAGetLastCipher (int ea) +{ + int c, i = 0; + while ((c = EncryptionAlgorithms[ea].Ciphers[i++])); + + return EncryptionAlgorithms[ea].Ciphers[i - 2]; +} + + +int EAGetNextCipher (int ea, int previousCipherId) +{ + int c, i = 0; + while ((c = EncryptionAlgorithms[ea].Ciphers[i++])) + { + if (c == previousCipherId) + return EncryptionAlgorithms[ea].Ciphers[i]; + } + + return 0; +} + + +int EAGetPreviousCipher (int ea, int previousCipherId) +{ + int c, i = 0; + + if (EncryptionAlgorithms[ea].Ciphers[i++] == previousCipherId) + return 0; + + while ((c = EncryptionAlgorithms[ea].Ciphers[i++])) + { + if (c == previousCipherId) + return EncryptionAlgorithms[ea].Ciphers[i - 2]; + } + + return 0; +} + + +int EAIsFormatEnabled (int ea) +{ + return EncryptionAlgorithms[ea].FormatEnabled; +} + + +// Returns TRUE if the mode of operation is supported for the encryption algorithm +int EAIsModeSupported (int ea, int testedMode) +{ + int mode; + + for (mode = EAGetFirstMode (ea); mode != 0; mode = EAGetNextMode (ea, mode)) + { + if (mode == testedMode) + return 1; + } + return 0; +} + + +Hash *HashGet (int id) +{ + int i; + for (i = 0; Hashes[i].Id != 0; i++) + if (Hashes[i].Id == id) + return &Hashes[i]; + + return 0; +} + + +int HashGetIdByName (char *name) +{ + int i; + for (i = 0; Hashes[i].Id != 0; i++) + if (strcmp (Hashes[i].Name, name) == 0) + return Hashes[i].Id; + + return 0; +} + + +char *HashGetName (int hashId) +{ + return HashGet (hashId) -> Name; +} + + +int HashIsDeprecated (int hashId) +{ + return HashGet (hashId) -> Deprecated; +} + + +PCRYPTO_INFO crypto_open (void) +{ + /* Do the crt allocation */ + PCRYPTO_INFO cryptoInfo = (PCRYPTO_INFO) TCalloc (sizeof (CRYPTO_INFO)); + memset (cryptoInfo, 0, sizeof (CRYPTO_INFO)); + + if (cryptoInfo == NULL) + return NULL; + + cryptoInfo->ea = -1; + return cryptoInfo; +} + +void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen) +{ + keyInfo->keyLength = nUserKeyLen; + burn (keyInfo->userKey, sizeof (keyInfo->userKey)); + memcpy (keyInfo->userKey, lpszUserKey, nUserKeyLen); +} + +void crypto_close (PCRYPTO_INFO cryptoInfo) +{ + if (cryptoInfo != NULL) + { + burn (cryptoInfo, sizeof (CRYPTO_INFO)); + TCfree (cryptoInfo); + } +} + + +#ifndef TC_NO_COMPILER_INT64 +void Xor128 (uint64_t *a, uint64_t *b) +{ + *a++ ^= *b++; + *a ^= *b; +} + + +void Xor64 (uint64_t *a, uint64_t *b) +{ + *a ^= *b; +} + + +void EncryptBufferLRW128 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + uint8_t *p = buffer; + uint8_t *ks = cryptoInfo->ks; + uint8_t i[8]; + uint8_t t[16]; + uint64_t b; + + *(uint64_t *)i = BE64(blockIndex); + + if (length % 16) + TC_THROW_FATAL_EXCEPTION; + + // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); + Xor128 ((uint64_t *)p, (uint64_t *)t); + + if (cipherCount > 1) + { + // Cipher cascade + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncipherBlock (cipher, p, ks); + ks += CipherGetKeyScheduleSize (cipher); + } + ks = cryptoInfo->ks; + } + else + { + EncipherBlock (cipher, p, ks); + } + + Xor128 ((uint64_t *)p, (uint64_t *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(uint64_t *)i = BE64 ( BE64(*(uint64_t *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +void EncryptBufferLRW64 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + uint8_t *p = buffer; + uint8_t *ks = cryptoInfo->ks; + uint8_t i[8]; + uint8_t t[8]; + uint64_t b; + + *(uint64_t *)i = BE64(blockIndex); + + if (length % 8) + TC_THROW_FATAL_EXCEPTION; + + for (b = 0; b < length >> 3; b++) + { + Gf64MulTab (i, t, &cryptoInfo->gf_ctx); + Xor64 ((uint64_t *)p, (uint64_t *)t); + + EncipherBlock (cipher, p, ks); + + Xor64 ((uint64_t *)p, (uint64_t *)t); + + p += 8; + + if (i[7] != 0xff) + i[7]++; + else + *(uint64_t *)i = BE64 ( BE64(*(uint64_t *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +void DecryptBufferLRW128 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + int cipherCount = EAGetCipherCount (cryptoInfo->ea); + uint8_t *p = buffer; + uint8_t *ks = cryptoInfo->ks; + uint8_t i[8]; + uint8_t t[16]; + uint64_t b; + + *(uint64_t *)i = BE64(blockIndex); + + if (length % 16) + TC_THROW_FATAL_EXCEPTION; + + // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); + Xor128 ((uint64_t *)p, (uint64_t *)t); + + if (cipherCount > 1) + { + // Cipher cascade + ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + DecipherBlock (cipher, p, ks); + } + } + else + { + DecipherBlock (cipher, p, ks); + } + + Xor128 ((uint64_t *)p, (uint64_t *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(uint64_t *)i = BE64 ( BE64(*(uint64_t *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + + +void DecryptBufferLRW64 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo) +{ + /* Deprecated/legacy */ + + int cipher = EAGetFirstCipher (cryptoInfo->ea); + uint8_t *p = buffer; + uint8_t *ks = cryptoInfo->ks; + uint8_t i[8]; + uint8_t t[8]; + uint64_t b; + + *(uint64_t *)i = BE64(blockIndex); + + if (length % 8) + TC_THROW_FATAL_EXCEPTION; + + for (b = 0; b < length >> 3; b++) + { + Gf64MulTab (i, t, &cryptoInfo->gf_ctx); + Xor64 ((uint64_t *)p, (uint64_t *)t); + + DecipherBlock (cipher, p, ks); + + Xor64 ((uint64_t *)p, (uint64_t *)t); + + p += 8; + + if (i[7] != 0xff) + i[7]++; + else + *(uint64_t *)i = BE64 ( BE64(*(uint64_t *)i) + 1 ); + } + + FAST_ERASE64 (t, sizeof(t)); +} + + +// Initializes IV and whitening values for sector encryption/decryption in CBC mode. +// IMPORTANT: This function has been deprecated (legacy). +void +InitSectorIVAndWhitening (uint64_t unitNo, + int blockSize, + uint32_t *iv, + uint64_t *ivSeed, + uint32_t *whitening) +{ + + /* IMPORTANT: This function has been deprecated (legacy) */ + + uint64_t iv64[4]; + uint32_t *iv32 = (uint32_t *) iv64; + + iv64[0] = ivSeed[0] ^ LE64(unitNo); + iv64[1] = ivSeed[1] ^ LE64(unitNo); + iv64[2] = ivSeed[2] ^ LE64(unitNo); + if (blockSize == 16) + { + iv64[3] = ivSeed[3] ^ LE64(unitNo); + } + + iv[0] = iv32[0]; + iv[1] = iv32[1]; + + switch (blockSize) + { + case 16: + + // 128-bit block + + iv[2] = iv32[2]; + iv[3] = iv32[3]; + + whitening[0] = LE32( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) ); + whitening[1] = LE32( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) ); + break; + + case 8: + + // 64-bit block + + whitening[0] = LE32( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) ); + whitening[1] = LE32( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) ); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } +} + + +// EncryptBufferCBC (deprecated/legacy) +// +// data: data to be encrypted +// len: number of bytes to encrypt (must be divisible by the largest cipher block size) +// ks: scheduled key +// iv: IV +// whitening: whitening constants +// ea: outer-CBC cascade ID (0 = CBC/inner-CBC) +// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC) + +static void +EncryptBufferCBC (uint32_t *data, + unsigned int len, + uint8_t *ks, + uint32_t *iv, + uint32_t *whitening, + int ea, + int cipher) +{ + /* IMPORTANT: This function has been deprecated (legacy) */ + + uint32_t bufIV[4] = { 0 }; + uint64_t i; + int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); + + if (len % blockSize) + TC_THROW_FATAL_EXCEPTION; + + // IV + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + // Encrypt each block + for (i = 0; i < len/blockSize; i++) + { + // CBC + data[0] ^= bufIV[0]; + data[1] ^= bufIV[1]; + if (blockSize == 16) + { + data[2] ^= bufIV[2]; + data[3] ^= bufIV[3]; + } + + if (ea != 0) + { + // Outer-CBC + for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) + { + EncipherBlock (cipher, data, ks); + ks += CipherGetKeyScheduleSize (cipher); + } + ks -= EAGetKeyScheduleSize (ea); + } + else + { + // CBC/inner-CBC + EncipherBlock (cipher, data, ks); + } + + // CBC + bufIV[0] = data[0]; + bufIV[1] = data[1]; + if (blockSize == 16) + { + bufIV[2] = data[2]; + bufIV[3] = data[3]; + } + + // Whitening + data[0] ^= whitening[0]; + data[1] ^= whitening[1]; + if (blockSize == 16) + { + data[2] ^= whitening[0]; + data[3] ^= whitening[1]; + } + + data += blockSize / sizeof(*data); + } +} + + +// DecryptBufferCBC (deprecated/legacy) +// +// data: data to be decrypted +// len: number of bytes to decrypt (must be divisible by the largest cipher block size) +// ks: scheduled key +// iv: IV +// whitening: whitening constants +// ea: outer-CBC cascade ID (0 = CBC/inner-CBC) +// cipher: CBC/inner-CBC cipher ID (0 = outer-CBC) + +static void +DecryptBufferCBC (uint32_t *data, + unsigned int len, + uint8_t *ks, + uint32_t *iv, + uint32_t *whitening, + int ea, + int cipher) +{ + + /* IMPORTANT: This function has been deprecated (legacy) */ + + uint32_t bufIV[4] = { 0 }; + uint64_t i; + uint32_t ct[4]; + int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); + + if (len % blockSize) + TC_THROW_FATAL_EXCEPTION; + + // IV + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + if (blockSize == 16) + { + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + } + + // Decrypt each block + for (i = 0; i < len/blockSize; i++) + { + // Dewhitening + if (whitening) + { + data[0] ^= whitening[0]; + data[1] ^= whitening[1]; + if (blockSize == 16) + { + data[2] ^= whitening[0]; + data[3] ^= whitening[1]; + } + + // CBC + ct[0] = data[0]; + ct[1] = data[1]; + if (blockSize == 16) + { + ct[2] = data[2]; + ct[3] = data[3]; + } + } + + if (ea != 0) + { + // Outer-CBC + ks += EAGetKeyScheduleSize (ea); + for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + DecipherBlock (cipher, data, ks); + } + } + else + { + // CBC/inner-CBC + DecipherBlock (cipher, data, ks); + } + + // CBC + data[0] ^= bufIV[0]; + data[1] ^= bufIV[1]; + if (whitening) + { + bufIV[0] = ct[0]; + bufIV[1] = ct[1]; + } + if (blockSize == 16) + { + data[2] ^= bufIV[2]; + data[3] ^= bufIV[3]; + if (whitening) + { + bufIV[2] = ct[2]; + bufIV[3] = ct[3]; + } + } + + data += blockSize / sizeof(*data); + } +} +#endif // #ifndef TC_NO_COMPILER_INT64 + + +// EncryptBuffer +// +// buf: data to be encrypted +// len: number of bytes to encrypt; must be divisible by the block size (for cascaded +// ciphers divisible by the largest block size used within the cascade) +void EncryptBuffer (uint8_t *buf, + TC_LARGEST_COMPILER_UINT len, + PCRYPTO_INFO cryptoInfo) +{ + switch (cryptoInfo->mode) + { + case XTS: + { + uint8_t *ks = cryptoInfo->ks; + uint8_t *ks2 = cryptoInfo->ks2; + UINT64_STRUCT dataUnitNo; + int cipher; + + // When encrypting/decrypting a buffer (typically a volume header) the sequential number + // of the first XTS data unit in the buffer is always 0 and the start of the buffer is + // always considered aligned with the start of a data unit. + dataUnitNo.LowPart = 0; + dataUnitNo.HighPart = 0; + + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); + + ks += CipherGetKeyScheduleSize (cipher); + ks2 += CipherGetKeyScheduleSize (cipher); + } + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + + /* Deprecated/legacy */ + + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + EncryptBufferLRW64 ((uint8_t *)buf, (uint64_t) len, 1, cryptoInfo); + break; + + case 16: + EncryptBufferLRW128 ((uint8_t *)buf, (uint64_t) len, 1, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + + case CBC: + case INNER_CBC: + { + /* Deprecated/legacy */ + + uint8_t *ks = cryptoInfo->ks; + int cipher; + + for (cipher = EAGetFirstCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetNextCipher (cryptoInfo->ea, cipher)) + { + EncryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + ks, + (uint32_t *) cryptoInfo->k2, + (uint32_t *) &cryptoInfo->k2[8], + 0, + cipher); + + ks += CipherGetKeyScheduleSize (cipher); + } + } + break; + + case OUTER_CBC: + + /* Deprecated/legacy */ + + EncryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + cryptoInfo->ks, + (uint32_t *) cryptoInfo->k2, + (uint32_t *) &cryptoInfo->k2[8], + cryptoInfo->ea, + 0); + + break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } +} + +// #ifndef TC_NO_COMPILER_INT64 +// // Converts a data unit number to the index of the first LRW block in the data unit. +// // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). +// uint64_t DataUnit2LRWIndex (uint64_t dataUnit, int blockSize, PCRYPTO_INFO ci) +// { +// /* Deprecated/legacy */ + +// if (ci->hiddenVolume) +// dataUnit -= ci->hiddenVolumeOffset / ENCRYPTION_DATA_UNIT_SIZE; +// else +// dataUnit -= HEADER_SIZE / ENCRYPTION_DATA_UNIT_SIZE; // Compensate for the volume header size + +// switch (blockSize) +// { +// case 8: +// return (dataUnit << 6) | 1; + +// case 16: +// return (dataUnit << 5) | 1; + +// default: +// TC_THROW_FATAL_EXCEPTION; +// } + +// return 0; +// } +// #endif // #ifndef TC_NO_COMPILER_INT64 + + +// // buf: data to be encrypted +// // unitNo: sequential number of the data unit with which the buffer starts +// // nbrUnits: number of data units in the buffer +// void EncryptDataUnits (uint8_t *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +// { +// int ea = ci->ea; +// uint8_t *ks = ci->ks; +// uint8_t *ks2 = ci->ks2; +// int cipher; + +// #ifndef TC_NO_COMPILER_INT64 +// void *iv = ci->k2; // Deprecated/legacy +// uint64_t unitNo = structUnitNo->Value; +// uint64_t *iv64 = (uint64_t *) iv; // Deprecated/legacy +// uint32_t sectorIV[4]; // Deprecated/legacy +// uint32_t secWhitening[2]; // Deprecated/legacy +// #endif + +// switch (ci->mode) +// { +// case XTS: +// for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) +// { +// EncryptBufferXTS (buf, +// nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, +// structUnitNo, +// 0, +// ks, +// ks2, +// cipher); + +// ks += CipherGetKeyScheduleSize (cipher); +// ks2 += CipherGetKeyScheduleSize (cipher); +// } +// break; + +// #ifndef TC_NO_COMPILER_INT64 +// case LRW: + +// /* Deprecated/legacy */ + +// switch (CipherGetBlockSize (EAGetFirstCipher (ea))) +// { +// case 8: +// EncryptBufferLRW64 (buf, +// (uint64_t) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, +// DataUnit2LRWIndex (unitNo, 8, ci), +// ci); +// break; + +// case 16: +// EncryptBufferLRW128 (buf, +// (uint64_t) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, +// DataUnit2LRWIndex (unitNo, 16, ci), +// ci); +// break; + +// default: +// TC_THROW_FATAL_EXCEPTION; +// } +// break; + +// case CBC: +// case INNER_CBC: + +// /* Deprecated/legacy */ + +// while (nbrUnits--) +// { +// for (cipher = EAGetFirstCipher (ea); cipher != 0; cipher = EAGetNextCipher (ea, cipher)) +// { +// InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + +// EncryptBufferCBC ((uint32_t *) buf, +// ENCRYPTION_DATA_UNIT_SIZE, +// ks, +// sectorIV, +// secWhitening, +// 0, +// cipher); + +// ks += CipherGetKeyScheduleSize (cipher); +// } +// ks -= EAGetKeyScheduleSize (ea); +// buf += ENCRYPTION_DATA_UNIT_SIZE; +// unitNo++; +// } +// break; + +// case OUTER_CBC: + +// /* Deprecated/legacy */ + +// while (nbrUnits--) +// { +// InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); + +// EncryptBufferCBC ((uint32_t *) buf, +// ENCRYPTION_DATA_UNIT_SIZE, +// ks, +// sectorIV, +// secWhitening, +// ea, +// 0); + +// buf += ENCRYPTION_DATA_UNIT_SIZE; +// unitNo++; +// } +// break; +// #endif // #ifndef TC_NO_COMPILER_INT64 + +// default: +// // Unknown/wrong ID +// TC_THROW_FATAL_EXCEPTION; +// } +// } + +// DecryptBuffer +// +// buf: data to be decrypted +// len: number of bytes to decrypt; must be divisible by the block size (for cascaded +// ciphers divisible by the largest block size used within the cascade) +void DecryptBuffer (uint8_t *buf, + TC_LARGEST_COMPILER_UINT len, + uint32_t secSz, + uint64_t secN, + uint8_t flags, + PCRYPTO_INFO cryptoInfo) +{ + + void *iv = cryptoInfo->k2; + uint32_t sectorIV[4]; + uint32_t secWhitening[2]; + uint64_t *iv64 = (uint64_t *) iv; + + switch (cryptoInfo->mode) + { + case XTS: + { + uint8_t *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + uint8_t *ks2 = cryptoInfo->ks2 + EAGetKeyScheduleSize (cryptoInfo->ea); + UINT64_STRUCT dataUnitNo; + int cipher; + + // When encrypting/decrypting a buffer (typically a volume header) the sequential number + // of the first XTS data unit in the buffer is always 0 and the start of the buffer is + // always considered aligned with the start of the data unit 0. + dataUnitNo.Value = secN; + + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + ks2 -= CipherGetKeyScheduleSize (cipher); + DecryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); + } + } + break; + +#ifndef TC_NO_COMPILER_INT64 + case LRW: + { + uint32_t n = 0; + if (flags & 2) + n = secN; + + switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) + { + case 8: + DecryptBufferLRW64 (buf, (uint64_t) len, 1 + (secSz / 8) * n, cryptoInfo); + break; + + case 16: + DecryptBufferLRW128 (buf, (uint64_t) len, 1 + (secSz / 16) * n, cryptoInfo); + break; + + default: + TC_THROW_FATAL_EXCEPTION; + } + break; + } + + case CBC: + case INNER_CBC: + { + /* Deprecated/legacy */ + + uint8_t *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); + int cipher; + for (cipher = EAGetLastCipher (cryptoInfo->ea); + cipher != 0; + cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) + { + ks -= CipherGetKeyScheduleSize (cipher); + + if (flags & 1) + { + DecryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + ks, + (uint32_t *) cryptoInfo->k2, + NULL, + 0, + cipher); + } + else if (flags & 2) + { + InitSectorIVAndWhitening (secN, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + DecryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + cryptoInfo->ks, + sectorIV, + secWhitening, + 0, + cipher); + } + else + { + DecryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + ks, + (uint32_t *) cryptoInfo->k2, + (uint32_t *) &cryptoInfo->k2[8], + 0, + cipher); + } + } + } + break; + + case OUTER_CBC: + if (flags & 1) + { + DecryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + cryptoInfo->ks, + (uint32_t *) cryptoInfo->k2, + NULL, + cryptoInfo->ea, + 0); + } + else if (flags & 2) + { + InitSectorIVAndWhitening (secN, CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea)), sectorIV, iv64, secWhitening); + DecryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + cryptoInfo->ks, + sectorIV, + secWhitening, + cryptoInfo->ea, + 0); + } + else + { + DecryptBufferCBC ((uint32_t *) buf, + (unsigned int) len, + cryptoInfo->ks, + (uint32_t *) cryptoInfo->k2, + (uint32_t *) &cryptoInfo->k2[8], + cryptoInfo->ea, + 0); + } + + break; +#endif // #ifndef TC_NO_COMPILER_INT64 + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } +} + +// // buf: data to be decrypted +// // unitNo: sequential number of the data unit with which the buffer starts +// // nbrUnits: number of data units in the buffer +// void DecryptDataUnits (uint8_t *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) +// { +// int ea = ci->ea; +// uint8_t *ks = ci->ks; +// uint8_t *ks2 = ci->ks2; +// int cipher; + +// #ifndef TC_NO_COMPILER_INT64 +// void *iv = ci->k2; // Deprecated/legacy +// uint64_t unitNo = structUnitNo->Value; +// uint64_t *iv64 = (uint64_t *) iv; // Deprecated/legacy +// uint32_t sectorIV[4]; // Deprecated/legacy +// uint32_t secWhitening[2]; // Deprecated/legacy +// #endif // #ifndef TC_NO_COMPILER_INT64 + + +// switch (ci->mode) +// { +// case XTS: +// ks += EAGetKeyScheduleSize (ea); +// ks2 += EAGetKeyScheduleSize (ea); + +// for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) +// { +// ks -= CipherGetKeyScheduleSize (cipher); +// ks2 -= CipherGetKeyScheduleSize (cipher); + +// DecryptBufferXTS (buf, +// nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, +// structUnitNo, +// 0, +// ks, +// ks2, +// cipher); +// } +// break; + +// #ifndef TC_NO_COMPILER_INT64 +// case LRW: + +// /* Deprecated/legacy */ + +// switch (CipherGetBlockSize (EAGetFirstCipher (ea))) +// { +// case 8: +// DecryptBufferLRW64 (buf, +// (uint64_t) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, +// DataUnit2LRWIndex (unitNo, 8, ci), +// ci); +// break; + +// case 16: +// DecryptBufferLRW128 (buf, +// (uint64_t) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, +// DataUnit2LRWIndex (unitNo, 16, ci), +// ci); +// break; + +// default: +// TC_THROW_FATAL_EXCEPTION; +// } +// break; + +// case CBC: +// case INNER_CBC: + +// /* Deprecated/legacy */ + +// while (nbrUnits--) +// { +// ks += EAGetKeyScheduleSize (ea); +// for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) +// { +// InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); + +// ks -= CipherGetKeyScheduleSize (cipher); + +// DecryptBufferCBC ((uint32_t *) buf, +// ENCRYPTION_DATA_UNIT_SIZE, +// ks, +// sectorIV, +// secWhitening, +// 0, +// cipher); +// } +// buf += ENCRYPTION_DATA_UNIT_SIZE; +// unitNo++; +// } +// break; + +// case OUTER_CBC: + +// /* Deprecated/legacy */ + +// while (nbrUnits--) +// { +// InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); + +// DecryptBufferCBC ((uint32_t *) buf, +// ENCRYPTION_DATA_UNIT_SIZE, +// ks, +// sectorIV, +// secWhitening, +// ea, +// 0); + +// buf += ENCRYPTION_DATA_UNIT_SIZE; +// unitNo++; +// } +// break; +// #endif // #ifndef TC_NO_COMPILER_INT64 + +// default: +// // Unknown/wrong ID +// TC_THROW_FATAL_EXCEPTION; +// } +// } + + +// Returns the maximum number of bytes necessary to be generated by the PBKDF2 (PKCS #5) +int GetMaxPkcs5OutSize (void) +{ + int size = 32; + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + + size = max (size, EAGetLargestKeyForMode (XTS) * 2); // Sizes of primary + secondary keys + + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (LRW)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (CBC)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (OUTER_CBC)); // Deprecated/legacy + size = max (size, LEGACY_VOL_IV_SIZE + EAGetLargestKeyForMode (INNER_CBC)); // Deprecated/legacy + + return size; +} diff --git a/src/utils/common/crypto.h b/src/utils/common/crypto.h new file mode 100644 index 000000000..8c3960e08 --- /dev/null +++ b/src/utils/common/crypto.h @@ -0,0 +1,304 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +/* Update the following when adding a new cipher or EA: + + Crypto.h: + ID #define + MAX_EXPANDED_KEY #define + + Crypto.c: + Ciphers[] + EncryptionAlgorithms[] + CipherInit() + EncipherBlock() + DecipherBlock() + +*/ + +#ifndef CRYPTO_H +#define CRYPTO_H + +#include +#include "tcdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Encryption data unit size, which may differ from the sector size and must always be 512 +#define ENCRYPTION_DATA_UNIT_SIZE 512 + +// Size of the salt (in bytes) +#define PKCS5_SALT_SIZE 64 + +// Size of the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode) +#define MASTER_KEYDATA_SIZE 256 + +// Size of the deprecated volume header item containing either an IV seed (CBC mode) or tweak key (LRW mode) +#define LEGACY_VOL_IV_SIZE 32 + +// Volume header byte offsets +#define HEADER_SALT_OFFSET 0 +#define HEADER_ENCRYPTED_DATA_OFFSET PKCS5_SALT_SIZE +#define HEADER_MASTER_KEYDATA_OFFSET 256 + +// Volume header sizes +#define HEADER_SIZE 512 +#define HEADER_ENCRYPTED_DATA_SIZE (HEADER_SIZE - HEADER_ENCRYPTED_DATA_OFFSET) + +/* The offset, in bytes, of the hidden volume header position from the end of the file (a positive value). + The extra offset (SECTOR_SIZE * 2) was added because FAT file system fills the last sector with zeroes + (marked as free; observed when quick format was performed using the OS format tool). One extra sector was + added to the offset for future expandability (should the header size increase, or should header backup be + introduced). */ +#define HIDDEN_VOL_HEADER_OFFSET (HEADER_SIZE + SECTOR_SIZE * 2) + + +// The first PRF to try when mounting +#define FIRST_PRF_ID 1 + +// Hash algorithms (pseudorandom functions). +enum +{ + RIPEMD160 = FIRST_PRF_ID, + SHA1, + WHIRLPOOL, + SHA512, + HASH_ENUM_END_ID +}; + +// The last PRF to try when mounting and also the number of implemented PRFs +#define LAST_PRF_ID (HASH_ENUM_END_ID - 1) + +#define RIPEMD160_BLOCKSIZE 64 +#define RIPEMD160_DIGESTSIZE 20 + +#define SHA1_BLOCKSIZE 64 +#define SHA1_DIGESTSIZE 20 + +#define SHA512_BLOCKSIZE 128 +#define SHA512_DIGESTSIZE 64 + +#define WHIRLPOOL_BLOCKSIZE 64 +#define WHIRLPOOL_DIGESTSIZE 64 + +#define MAX_DIGESTSIZE WHIRLPOOL_DIGESTSIZE + +#define DEFAULT_HASH_ALGORITHM FIRST_PRF_ID +#define DEFAULT_HASH_ALGORITHM_BOOT RIPEMD160 + +// The mode of operation used for newly created volumes and first to try when mounting +#define FIRST_MODE_OF_OPERATION_ID 1 + +// Modes of operation +enum +{ + /* If you add/remove a mode, update the following: GetMaxPkcs5OutSize(), EAInitMode() */ + + XTS = FIRST_MODE_OF_OPERATION_ID, + LRW, // Deprecated/legacy + CBC, // Deprecated/legacy + OUTER_CBC, // Deprecated/legacy + INNER_CBC, // Deprecated/legacy + MODE_ENUM_END_ID +}; + + +// The last mode of operation to try when mounting and also the number of implemented modes +#define LAST_MODE_OF_OPERATION (MODE_ENUM_END_ID - 1) + +// Ciphertext/plaintext block size for XTS mode (in bytes) +#define BYTES_PER_XTS_BLOCK 16 + +// Number of ciphertext/plaintext blocks per XTS data unit +#define BLOCKS_PER_XTS_DATA_UNIT (ENCRYPTION_DATA_UNIT_SIZE / BYTES_PER_XTS_BLOCK) + + +// Cipher IDs +enum +{ + NONE = 0, + AES256, + AES192, + AES128, + BLOWFISH, // Deprecated/legacy + CAST, // Deprecated/legacy + SERPENT, + TRIPLEDES, // Deprecated/legacy + TWOFISH, + DES56 // Deprecated/legacy (used only by Triple DES) +}; + +typedef struct +{ + int Id; // Cipher ID + char *Name; // Name + int BlockSize; // Block size (bytes) + int KeySize; // Key size (bytes) + int KeyScheduleSize; // Scheduled key size (bytes) +} Cipher; + +typedef struct +{ + int Ciphers[4]; // Null terminated array of ciphers used by encryption algorithm + int Modes[LAST_MODE_OF_OPERATION + 1]; // Null terminated array of modes of operation + int FormatEnabled; +} EncryptionAlgorithm; + +typedef struct +{ + int Id; // Hash ID + char *Name; // Name + int Deprecated; + int SystemEncryption; // Available for system encryption +} Hash; + +// Maxium length of scheduled key +#define AES_KS (sizeof(aes_encrypt_ctx) + sizeof(aes_decrypt_ctx)) + +#define SERPENT_KS (140 * 4) + +#define MAX_EXPANDED_KEY (AES_KS + SERPENT_KS + TWOFISH_KS) + +#define PRAND_DISK_WIPE_PASSES 200 + +#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_AES) +# include "../crypto/aes.h" +#else +# include "../crypto/aesSmall.h" +#endif + +#include "../crypto/blowfish.h" +#include "../crypto/cast.h" +#include "../crypto/des.h" +#include "../crypto/serpent.h" +#include "../crypto/twofish.h" + +#include "../crypto/rmd160.h" +# include "../crypto/sha1.h" +# include "../crypto/sha2.h" +# include "../crypto/whirlpool.h" + +#include "gfmul.h" +#include "password.h" + +typedef struct keyInfo_t +{ + int noIterations; /* Number of times to iterate (PKCS-5) */ + int keyLength; /* Length of the key */ + int8_t userKey[MAX_PASSWORD]; /* Password (to which keyfiles may have been applied). WITHOUT +1 for the null terminator. */ + int8_t salt[PKCS5_SALT_SIZE]; /* PKCS-5 salt */ + int8_t master_keydata[MASTER_KEYDATA_SIZE]; /* Concatenated master primary and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */ +} KEY_INFO, *PKEY_INFO; + +typedef struct CRYPTO_INFO_t +{ + int ea; /* Encryption algorithm ID */ + int mode; /* Mode of operation (e.g., XTS) */ + uint8_t ks[MAX_EXPANDED_KEY]; /* Primary key schedule (if it is a cascade, it conatins multiple concatenated keys) */ + uint8_t ks2[MAX_EXPANDED_KEY]; /* Secondary key schedule (if cascade, multiple concatenated) for XTS mode. */ + + GfCtx gf_ctx; + + uint8_t master_keydata[MASTER_KEYDATA_SIZE]; /* This holds the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */ + uint8_t k2[MASTER_KEYDATA_SIZE]; /* For XTS, this contains the secondary key (if cascade, multiple concatenated). For LRW (deprecated/legacy), it contains the tweak key. For CBC (deprecated/legacy), it contains the IV seed. */ + uint8_t salt[PKCS5_SALT_SIZE]; + int noIterations; + int pkcs5; + + // uint64_t volume_creation_time; + // uint64_t header_creation_time; + + // // Hidden volume status & parameters + // int hiddenVolume; // Indicates whether the volume is mounted/mountable as hidden volume + // int bProtectHiddenVolume; // Indicates whether the volume contains a hidden volume to be protected against overwriting + // int bHiddenVolProtectionAction; // TRUE if a write operation has been denied by the driver in order to prevent the hidden volume from being overwritten (set to FALSE upon volume mount). + + // uint64_t hiddenVolumeSize; // Size of the hidden volume excluding the header (in bytes). Set to 0 for standard volumes. + // uint64_t hiddenVolumeOffset; // Absolute position, in bytes, of the first hidden volume data sector within the host volume (provided that there is a hidden volume within). This must be set for all hidden volumes; in case of a normal volume, this variable is only used when protecting a hidden volume within it. + // uint64_t volDataAreaOffset; // Absolute position, in bytes, of the first data sector of the volume. + + // int bPartitionInInactiveSysEncScope; // If TRUE, the volume is a partition located on an encrypted system drive and mounted without pre-boot authentication. + + // UINT64_STRUCT FirstDataUnitNo; // First data unit number of the volume. This is 0 for file-hosted and non-system partition-hosted volumes. For partitions within key scope of system encryption this reflects real physical offset within the device (this is used e.g. when such a partition is mounted as a regular volume without pre-boot authentication). + // UINT64_STRUCT VolumeSize; + + // UINT64_STRUCT EncryptedAreaStart; + // UINT64_STRUCT EncryptedAreaLength; + +} CRYPTO_INFO, *PCRYPTO_INFO; + +PCRYPTO_INFO crypto_open (void); +void crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen); +void crypto_close (PCRYPTO_INFO cryptoInfo); + +int CipherGetBlockSize (int cipher); +int CipherGetKeySize (int cipher); +int CipherGetKeyScheduleSize (int cipher); +char * CipherGetName (int cipher); + +int CipherInit (int cipher, unsigned char *key, unsigned char *ks); +int EAInit (int ea, unsigned char *key, unsigned char *ks); +int EAInitMode (PCRYPTO_INFO ci); +void EncipherBlock(int cipher, void *data, void *ks); +void DecipherBlock(int cipher, void *data, void *ks); + +int EAGetFirst (void); +int EAGetCount (void); +int EAGetNext (int previousEA); +char * EAGetName (char *buf, int ea); +int EAGetByName (char *name); +int EAGetKeySize (int ea); +int EAGetFirstMode (int ea); +int EAGetNextMode (int ea, int previousModeId); +char * EAGetModeName (int ea, int mode, int capitalLetters); +int EAGetKeyScheduleSize (int ea); +int EAGetLargestKey (void); +int EAGetLargestKeyForMode (int mode); + +int EAGetCipherCount (int ea); +int EAGetFirstCipher (int ea); +int EAGetLastCipher (int ea); +int EAGetNextCipher (int ea, int previousCipherId); +int EAGetPreviousCipher (int ea, int previousCipherId); +int EAIsFormatEnabled (int ea); +int EAIsModeSupported (int ea, int testedMode); + +char *HashGetName (int hash_algo_id); +int HashIsDeprecated (int hashId); + +int GetMaxPkcs5OutSize (void); + +//void EncryptDataUnits (uint8_t *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); +//void DecryptDataUnits (uint8_t *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci); +void EncryptBuffer (uint8_t *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo); +void DecryptBuffer (uint8_t *buf, TC_LARGEST_COMPILER_UINT len, uint32_t secSz, uint64_t secN, uint8_t flags, PCRYPTO_INFO cryptoInfo); + +#ifndef TC_NO_COMPILER_INT64 + +void Xor128 (uint64_t *a, uint64_t *b); +void Xor64 (uint64_t *a, uint64_t *b); + +void EncryptBufferLRW128 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo); +void DecryptBufferLRW128 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo); +void EncryptBufferLRW64 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo); +void DecryptBufferLRW64 (uint8_t *buffer, uint64_t length, uint64_t blockIndex, PCRYPTO_INFO cryptoInfo); + +void InitSectorIVAndWhitening (uint64_t unitNo, int blockSize, uint32_t *iv, uint64_t *ivSeed, uint32_t *whitening); +//uint64_t DataUnit2LRWIndex (uint64_t dataUnit, int blockSize, PCRYPTO_INFO ci); +#endif // #ifndef TC_NO_COMPILER_INT64 + +#ifdef __cplusplus +} +#endif + +#endif /* CRYPTO_H */ diff --git a/src/utils/common/endian.c b/src/utils/common/endian.c new file mode 100644 index 000000000..90d2115da --- /dev/null +++ b/src/utils/common/endian.c @@ -0,0 +1,57 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "tcdefs.h" +#include "../common/endian.h" + + +uint16_t MirrorBytes16 (uint16_t x) +{ + return (x << 8) | (x >> 8); +} + + +uint32_t MirrorBytes32 (uint32_t x) +{ + uint32_t n = (uint8_t) x; + n <<= 8; n |= (uint8_t) (x >> 8); + n <<= 8; n |= (uint8_t) (x >> 16); + return (n << 8) | (uint8_t) (x >> 24); +} + +#ifndef TC_NO_COMPILER_INT64 +uint64_t MirrorBytes64 (uint64_t x) +{ + uint64_t n = (uint8_t) x; + n <<= 8; n |= (uint8_t) (x >> 8); + n <<= 8; n |= (uint8_t) (x >> 16); + n <<= 8; n |= (uint8_t) (x >> 24); + n <<= 8; n |= (uint8_t) (x >> 32); + n <<= 8; n |= (uint8_t) (x >> 40); + n <<= 8; n |= (uint8_t) (x >> 48); + return (n << 8) | (uint8_t) (x >> 56); +} +#endif + +void +LongReverse (uint32_t *buffer, unsigned byteCount) +{ + uint32_t value; + + byteCount /= sizeof (uint32_t); + while (byteCount--) + { + value = *buffer; + value = ((value & 0xFF00FF00L) >> 8) | \ + ((value & 0x00FF00FFL) << 8); + *buffer++ = (value << 16) | (value >> 16); + } +} diff --git a/src/utils/common/endian.h b/src/utils/common/endian.h new file mode 100644 index 000000000..787c6fa21 --- /dev/null +++ b/src/utils/common/endian.h @@ -0,0 +1,138 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_ENDIAN_H +#define TC_ENDIAN_H + +#include + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifdef _WIN32 + +# ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1234 +# endif +# ifndef BYTE_ORDER +# define BYTE_ORDER LITTLE_ENDIAN +# endif + +#elif !defined(BYTE_ORDER) + +# ifdef TC_MACOSX +# include +# elif defined (TC_BSD) +# include +# else +# include +# endif + +# ifndef BYTE_ORDER +# ifndef __BYTE_ORDER +# error Byte order cannot be determined (BYTE_ORDER undefined) +# endif + +# define BYTE_ORDER __BYTE_ORDER +# endif + +# ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# endif + +# ifndef BIG_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# endif + +#endif // !BYTE_ORDER + +/* Macros to read and write 16, 32, and 64-bit quantities in a portable manner. + These functions are implemented as macros rather than true functions as + the need to adjust the memory pointers makes them somewhat painful to call + in user code */ + +#define mputInt64(memPtr,data) \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 56 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 48 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 40 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 32 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 24 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 16 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) + +#define mputLong(memPtr,data) \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 24 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 16 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) + +#define mputWord(memPtr,data) \ + *memPtr++ = ( unsigned char ) ( ( ( data ) >> 8 ) & 0xFF ), \ + *memPtr++ = ( unsigned char ) ( ( data ) & 0xFF ) + +#define mputByte(memPtr,data) \ + *memPtr++ = ( unsigned char ) data + +#define mputBytes(memPtr,data,len) \ + memcpy (memPtr,data,len); \ + memPtr += len; + +#define mgetInt64(memPtr) \ + ( memPtr += 8, ( ( unsigned __int64 ) memPtr[ -8 ] << 56 ) | ( ( unsigned __int64 ) memPtr[ -7 ] << 48 ) | \ + ( ( unsigned __int64 ) memPtr[ -6 ] << 40 ) | ( ( unsigned __int64 ) memPtr[ -5 ] << 32 ) | \ + ( ( unsigned __int64 ) memPtr[ -4 ] << 24 ) | ( ( unsigned __int64 ) memPtr[ -3 ] << 16 ) | \ + ( ( unsigned __int64 ) memPtr[ -2 ] << 8 ) | ( unsigned __int64 ) memPtr[ -1 ] ) + +#define mgetLong(memPtr) \ + ( memPtr += 4, ( ( unsigned __int32 ) memPtr[ -4 ] << 24 ) | ( ( unsigned __int32 ) memPtr[ -3 ] << 16 ) | \ + ( ( unsigned __int32 ) memPtr[ -2 ] << 8 ) | ( unsigned __int32 ) memPtr[ -1 ] ) + +#define mgetWord(memPtr) \ + ( memPtr += 2, ( unsigned short ) memPtr[ -2 ] << 8 ) | ( ( unsigned short ) memPtr[ -1 ] ) + +#define mgetByte(memPtr) \ + ( ( unsigned char ) *memPtr++ ) + +#if BYTE_ORDER == BIG_ENDIAN +# define LE16(x) MirrorBytes16(x) +# define LE32(x) MirrorBytes32(x) +# define LE64(x) MirrorBytes64(x) +#else +# define LE16(x) (x) +# define LE32(x) (x) +# define LE64(x) (x) +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +# define BE16(x) MirrorBytes16(x) +# define BE32(x) MirrorBytes32(x) +# define BE64(x) MirrorBytes64(x) +#else +# define BE16(x) (x) +# define BE32(x) (x) +# define BE64(x) (x) +#endif + +uint16_t MirrorBytes16 (uint16_t x); +uint32_t MirrorBytes32 (uint32_t x); +#ifndef TC_NO_COMPILER_INT64 +uint64_t MirrorBytes64 (uint64_t x); +#endif +void LongReverse ( uint32_t *buffer , unsigned byteCount ); + +#if defined(__cplusplus) +} +#endif + +#endif /* TC_ENDIAN_H */ diff --git a/src/utils/common/gfmul.c b/src/utils/common/gfmul.c new file mode 100644 index 000000000..9536d2ea9 --- /dev/null +++ b/src/utils/common/gfmul.c @@ -0,0 +1,893 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 31/01/2004 + + My thanks to John Viega and David McGrew for their support in developing + this code and to David for testing it on a big-endain system. +*/ + +/* + Portions Copyright (c) 2005 TrueCrypt Foundation + + TrueCrypt Foundation made the following changes: + + - Added multiplication in the finite field GF(2^128) optimized for + cases involving a 64-bit operand. + + - Added multiplication in the finite field GF(2^64). + + - Added MSB-first mode. + + - Added basic test algorithms. + + - Removed GCM. +*/ + +#include +#include +#include +#include "gfmul.h" +#include "tcdefs.h" +#include "../common/endian.h" + +/* BUFFER_ALIGN32 or BUFFER_ALIGN64 must be defined at this point to */ +/* enable faster operation by taking advantage of memory aligned values */ +/* NOTE: the BUFFER_ALIGN64 option has not been tested extensively */ + +#define BUFFER_ALIGN32 +#define UNROLL_LOOPS /* define to unroll some loops */ +#define IN_LINES /* define to use inline functions */ + /* in place of macros */ + +#define mode(x) GM_##x + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef uint32_t mode(32t); +typedef uint64_t mode(64t); + +#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN +#endif + +#ifdef _MSC_VER +#pragma intrinsic(memcpy) +#define in_line __inline +#else +#define in_line +#endif + +#if 0 && defined(_MSC_VER) +#define rotl32 _lrotl +#define rotr32 _lrotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if defined(SWAP_BYTES) + +#if defined ( IN_LINES ) + +in_line void bsw_32(void * p, unsigned int n) +{ unsigned int i = n; + while(i--) + ((mode(32t)*)p)[i] = bswap_32(((mode(32t)*)p)[i]); +} + +#else + +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((mode(32t)*)p)[_i] = bswap_32(((mode(32t)*)p)[_i]); } + +#endif + +#else +#define bsw_32(p,n) +#endif + +/* These values are used to detect long word alignment in order */ +/* to speed up some GCM buffer operations. This facility may */ +/* not work on some machines */ + +#define lp08(x) ((unsigned char*)(x)) +#define lp32(x) ((mode(32t)*)(x)) +#define lp64(x) ((mode(64t)*)(x)) + +#define A32_MASK 3 +#define A64_MASK 7 +#define aligned32(x) (!(((mode(32t))(x)) & A32_MASK)) +#define aligned64(x) (!(((mode(32t))(x)) & A64_MASK)) + +#if defined( BUFFER_ALIGN32 ) + +#define ADR_MASK A32_MASK +#define aligned aligned32 +#define lp lp32 +#define lp_inc 4 + +#if defined( IN_LINES ) + +in_line void move_block_aligned( void *p, const void *q) +{ + lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1], + lp32(p)[2] = lp32(q)[2], lp32(p)[3] = lp32(q)[3]; +} + +in_line void move_block_aligned64( void *p, const void *q) +{ + lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1]; +} + +in_line void xor_block_aligned( void *p, const void *q) +{ + lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1], + lp32(p)[2] ^= lp32(q)[2], lp32(p)[3] ^= lp32(q)[3]; +} + +in_line void xor_block_aligned64( void *p, const void *q) +{ + lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1]; +} + +#else + +#define move_block_aligned(p,q) \ + lp32(p)[0] = lp32(q)[0], lp32(p)[1] = lp32(q)[1], \ + lp32(p)[2] = lp32(q)[2], lp32(p)[3] = lp32(q)[3] + +#define xor_block_aligned(p,q) \ + lp32(p)[0] ^= lp32(q)[0], lp32(p)[1] ^= lp32(q)[1], \ + lp32(p)[2] ^= lp32(q)[2], lp32(p)[3] ^= lp32(q)[3] + +#endif + +#elif defined( BUFFER_ALIGN64 ) + +#define ADR_MASK A64_MASK +#define aligned aligned64 +#define lp lp64 +#define lp_inc 8 + +#define move_block_aligned(p,q) \ + lp64(p)[0] = lp64(q)[0], lp64(p)[1] = lp64(q)[1] + +#define xor_block_aligned(p,q) \ + lp64(p)[0] ^= lp64(q)[0], lp64(p)[1] ^= lp64(q)[1] + +#else +#define aligned(x) 0 +#endif + +#define move_block(p,q) memcpy((p), (q), BLOCK_LEN) + +#define xor_block(p,q) \ + lp08(p)[ 0] ^= lp08(q)[ 0], lp08(p)[ 1] ^= lp08(q)[ 1], \ + lp08(p)[ 2] ^= lp08(q)[ 2], lp08(p)[ 3] ^= lp08(q)[ 3], \ + lp08(p)[ 4] ^= lp08(q)[ 4], lp08(p)[ 5] ^= lp08(q)[ 5], \ + lp08(p)[ 6] ^= lp08(q)[ 6], lp08(p)[ 7] ^= lp08(q)[ 7], \ + lp08(p)[ 8] ^= lp08(q)[ 8], lp08(p)[ 9] ^= lp08(q)[ 9], \ + lp08(p)[10] ^= lp08(q)[10], lp08(p)[11] ^= lp08(q)[11], \ + lp08(p)[12] ^= lp08(q)[12], lp08(p)[13] ^= lp08(q)[13], \ + lp08(p)[14] ^= lp08(q)[14], lp08(p)[15] ^= lp08(q)[15] + + +#define gf_dat(q) {\ + q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\ + q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\ + q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\ + q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\ + q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\ + q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\ + q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\ + q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\ + q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\ + q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\ + q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\ + q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\ + q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\ + q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\ + q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\ + q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\ + q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\ + q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\ + q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\ + q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\ + q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\ + q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\ + q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\ + q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\ + q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\ + q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\ + q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\ + q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\ + q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\ + q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\ + q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\ + q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) } + +/* given the value i in 0..255 as the byte overflow when a a field */ +/* element in GHASH is multipled by x^8, this function will return */ +/* the values that are generated in the lo 16-bit word of the field */ +/* value by applying the modular polynomial. The values lo_byte and */ +/* hi_byte are returned via the macro xp_fun(lo_byte, hi_byte) so */ +/* that the values can be assembled into memory as required by a */ +/* suitable definition of this macro operating on the table above */ + +#define xp(i) xp_fun( \ + (i & 0x80 ? 0xe1 : 0) ^ (i & 0x40 ? 0x70 : 0) ^ \ + (i & 0x20 ? 0x38 : 0) ^ (i & 0x10 ? 0x1c : 0) ^ \ + (i & 0x08 ? 0x0e : 0) ^ (i & 0x04 ? 0x07 : 0) ^ \ + (i & 0x02 ? 0x03 : 0) ^ (i & 0x01 ? 0x01 : 0), \ + (i & 0x80 ? 0x00 : 0) ^ (i & 0x40 ? 0x80 : 0) ^ \ + (i & 0x20 ? 0x40 : 0) ^ (i & 0x10 ? 0x20 : 0) ^ \ + (i & 0x08 ? 0x10 : 0) ^ (i & 0x04 ? 0x08 : 0) ^ \ + (i & 0x02 ? 0x84 : 0) ^ (i & 0x01 ? 0xc2 : 0) ) + +#define xp64(i) xp_fun( \ + (i & 0x80 ? 0xd8 : 0) ^ (i & 0x40 ? 0x6c : 0) ^ \ + (i & 0x20 ? 0x36 : 0) ^ (i & 0x10 ? 0x1b : 0) ^ \ + (i & 0x08 ? 0x0d : 0) ^ (i & 0x04 ? 0x06 : 0) ^ \ + (i & 0x02 ? 0x03 : 0) ^ (i & 0x01 ? 0x01 : 0), \ + (i & 0x80 ? 0x00 : 0) ^ (i & 0x40 ? 0x00 : 0) ^ \ + (i & 0x20 ? 0x00 : 0) ^ (i & 0x10 ? 0x00 : 0) ^ \ + (i & 0x08 ? 0x80 : 0) ^ (i & 0x04 ? 0xc0 : 0) ^ \ + (i & 0x02 ? 0x60 : 0) ^ (i & 0x01 ? 0xb0 : 0) ) + +static mode(32t) gf_poly[2] = { 0, 0xe1000000 }; +static mode(32t) gf_poly64[2] = { 0, 0xd8000000 }; + +/* Multiply of a GF128 field element by x. The field element */ +/* is held in an array of bytes in which field bits 8n..8n + 7 */ +/* are held in byte[n], with lower indexed bits placed in the */ +/* more numerically significant bit positions in bytes. */ + +/* This function multiples a field element x, in the polynomial */ +/* field representation. It uses 32-bit word operations to gain */ +/* speed but compensates for machine endianess and hence works */ +/* correctly on both styles of machine */ + +in_line void mul_x(mode(32t) x[4]) +{ mode(32t) t; + + bsw_32(x, 4); + + /* at this point the filed element bits 0..127 are set out */ + /* as follows in 32-bit words (where the most significant */ + /* (ms) numeric bits are to the left) */ + /* */ + /* x[0] x[1] x[2] x[3] */ + /* ms ls ms ls ms ls ms ls */ + /* field: 0 ... 31 32 .. 63 64 .. 95 96 .. 127 */ + + t = gf_poly[x[3] & 1]; /* bit 127 of the element */ + x[3] = (x[3] >> 1) | (x[2] << 31); /* shift bits up by one */ + x[2] = (x[2] >> 1) | (x[1] << 31); /* position */ + x[1] = (x[1] >> 1) | (x[0] << 31); /* if bit 7 is 1 xor in */ + x[0] = (x[0] >> 1) ^ t; /* the field polynomial */ + bsw_32(x, 4); +} + +in_line void mul_x64(mode(32t) x[2]) +{ mode(32t) t; + + bsw_32(x, 2); + + /* at this point the filed element bits 0..127 are set out */ + /* as follows in 32-bit words (where the most significant */ + /* (ms) numeric bits are to the left) */ + /* */ + /* x[0] x[1] x[2] x[3] */ + /* ms ls ms ls ms ls ms ls */ + /* field: 0 ... 31 32 .. 63 64 .. 95 96 .. 127 */ + + t = gf_poly64[x[1] & 1]; /* bit 127 of the element */ + /* shift bits up by one */ + /* position */ + x[1] = (x[1] >> 1) | (x[0] << 31); /* if bit 7 is 1 xor in */ + x[0] = (x[0] >> 1) ^ t; /* the field polynomial */ + bsw_32(x, 2); +} + +/* Multiply of a GF128 field element by x^8 using 32-bit words */ +/* for speed - machine endianess matters here */ + +#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) + +#define xp_fun(x,y) ((mode(32t))(x)) | (((mode(32t))(y)) << 8) +static const uint16_t gft_le[256] = gf_dat(xp); +static const uint16_t gft_le64[256] = gf_dat(xp64); + +in_line void mul_lex8(mode(32t) x[4]) /* mutiply with long words */ +{ mode(32t) t = (x[3] >> 24); /* in little endian format */ + x[3] = (x[3] << 8) | (x[2] >> 24); + x[2] = (x[2] << 8) | (x[1] >> 24); + x[1] = (x[1] << 8) | (x[0] >> 24); + x[0] = (x[0] << 8) ^ gft_le[t]; +} + +in_line void mul_lex8_64(mode(32t) x[2]) /* mutiply with long words */ +{ mode(32t) t = (x[1] >> 24); /* in little endian format */ + x[1] = (x[1] << 8) | (x[0] >> 24); + x[0] = (x[0] << 8) ^ gft_le64[t]; +} + +#endif + +#if 1 || (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) + +#undef xp_fun +#define xp_fun(x,y) ((mode(32t))(y)) | (((mode(32t))(x)) << 8) +static const uint16_t gft_be[256] = gf_dat(xp); +static const uint16_t gft_be64[256] = gf_dat(xp64); + +in_line void mul_bex8(mode(32t) x[4]) /* mutiply with long words */ +{ mode(32t) t = (x[3] & 0xff); /* in big endian format */ + x[3] = (x[3] >> 8) | (x[2] << 24); + x[2] = (x[2] >> 8) | (x[1] << 24); + x[1] = (x[1] >> 8) | (x[0] << 24); + x[0] = (x[0] >> 8) ^ (((mode(32t))gft_be[t]) << 16); +} + +in_line void mul_bex8_64(mode(32t) x[2]) /* mutiply with long words */ +{ mode(32t) t = (x[1] & 0xff); /* in big endian format */ + x[1] = (x[1] >> 8) | (x[0] << 24); + x[0] = (x[0] >> 8) ^ (((mode(32t))gft_be64[t]) << 16); +} + +#endif + +/* hence choose the correct version for the machine endianess */ + +#if PLATFORM_BYTE_ORDER == BRG_BIG_ENDIAN +#define mul_x8 mul_bex8 +#define mul_x8_64 mul_bex8_64 +#else +#define mul_x8 mul_lex8 +#define mul_x8_64 mul_lex8_64 +#endif + +/* different versions of the general gf_mul function are provided */ +/* here. Sadly none are very fast :-( */ + +void GfMul128 (void *a, const void* b) +{ mode(32t) r[CBLK_LEN >> 2], p[8][CBLK_LEN >> 2]; + int i; + + move_block_aligned(p[0], b); + bsw_32(p[0], 4); + for(i = 0; i < 7; ++i) + { + p[i + 1][3] = (p[i][3] >> 1) | (p[i][2] << 31); + p[i + 1][2] = (p[i][2] >> 1) | (p[i][1] << 31); + p[i + 1][1] = (p[i][1] >> 1) | (p[i][0] << 31); + p[i + 1][0] = (p[i][0] >> 1) ^ gf_poly[p[i][3] & 1]; + } + + memset(r, 0, CBLK_LEN); + for(i = 0; i < 16; ++i) + { + if(i) mul_bex8(r); /* order is always big endian here */ + + if(((unsigned char*)a)[15 - i] & 0x80) + xor_block_aligned(r, p[0]); + if(((unsigned char*)a)[15 - i] & 0x40) + xor_block_aligned(r, p[1]); + if(((unsigned char*)a)[15 - i] & 0x20) + xor_block_aligned(r, p[2]); + if(((unsigned char*)a)[15 - i] & 0x10) + xor_block_aligned(r, p[3]); + if(((unsigned char*)a)[15 - i] & 0x08) + xor_block_aligned(r, p[4]); + if(((unsigned char*)a)[15 - i] & 0x04) + xor_block_aligned(r, p[5]); + if(((unsigned char*)a)[15 - i] & 0x02) + xor_block_aligned(r, p[6]); + if(((unsigned char*)a)[15 - i] & 0x01) + xor_block_aligned(r, p[7]); + } + bsw_32(r, 4); + move_block_aligned(a, r); +} + +#if defined( UNROLL_LOOPS ) + +#define xor_8k(i) \ + xor_block_aligned(r, ctx->gf_t8k[i + i][a[i] & 15]); \ + xor_block_aligned(r, ctx->gf_t8k[i + i + 1][a[i] >> 4]) + + +void GfMul128Tab (unsigned char a[CBLK_LEN], GfCtx8k *ctx) +{ uint32_t r[CBLK_LEN >> 2]; + + move_block_aligned(r, ctx->gf_t8k[0][a[0] & 15]); + xor_block_aligned(r, ctx->gf_t8k[1][a[0] >> 4]); + xor_8k( 1); xor_8k( 2); xor_8k( 3); + xor_8k( 4); xor_8k( 5); xor_8k( 6); xor_8k( 7); + xor_8k( 8); xor_8k( 9); xor_8k(10); xor_8k(11); + xor_8k(12); xor_8k(13); xor_8k(14); xor_8k(15); + move_block_aligned(a, r); +} + +#else + +void GfMul128Tab (unsigned char a[CBLK_LEN], GfCtx8k *ctx) +{ uint32_t r[CBLK_LEN >> 2], *p; + int i; + + p = ctx->gf_t8k[0][a[0] & 15]; + memcpy(r, p, CBLK_LEN); + p = ctx->gf_t8k[1][a[0] >> 4]; + xor_block_aligned(r, p); + for(i = 1; i < CBLK_LEN; ++i) + { + xor_block_aligned(r, ctx->gf_t8k[i + i][a[i] & 15]); + xor_block_aligned(r, ctx->gf_t8k[i + i + 1][a[i] >> 4]); + } + memcpy(a, r, CBLK_LEN); +} + +#endif + +void compile_8k_table(uint8_t *a, GfCtx8k *ctx) +{ int i, j, k; + + memset(ctx->gf_t8k, 0, 32 * 16 * 16); + for(i = 0; i < 2 * CBLK_LEN; ++i) + { + if(i == 0) + { + memcpy(ctx->gf_t8k[1][8], a, CBLK_LEN); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t8k[1][j], ctx->gf_t8k[1][j + j], CBLK_LEN); + mul_x(ctx->gf_t8k[1][j]); + } + memcpy(ctx->gf_t8k[0][8], ctx->gf_t8k[1][1], CBLK_LEN); + mul_x(ctx->gf_t8k[0][8]); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t8k[0][j], ctx->gf_t8k[0][j + j], CBLK_LEN); + mul_x(ctx->gf_t8k[0][j]); + } + } + else if(i > 1) + for(j = 8; j > 0; j >>= 1) + { + memcpy(ctx->gf_t8k[i][j], ctx->gf_t8k[i - 2][j], CBLK_LEN); + mul_x8(ctx->gf_t8k[i][j]); + } + + for(j = 2; j < 16; j += j) + { + mode(32t) *pj = ctx->gf_t8k[i][j]; + mode(32t) *pk = ctx->gf_t8k[i][1]; + mode(32t) *pl = ctx->gf_t8k[i][j + 1]; + + for(k = 1; k < j; ++k) + { + *pl++ = pj[0] ^ *pk++; + *pl++ = pj[1] ^ *pk++; + *pl++ = pj[2] ^ *pk++; + *pl++ = pj[3] ^ *pk++; + } + } + } +} + + +void compile_4k_table64(uint8_t *a, GfCtx4k64 *ctx) +{ int i, j, k; + + memset(ctx->gf_t4k, 0, sizeof(ctx->gf_t4k)); + for(i = 0; i < 2 * CBLK_LEN8; ++i) + { + if(i == 0) + { + memcpy(ctx->gf_t4k[1][8], a, CBLK_LEN8); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t4k[1][j], ctx->gf_t4k[1][j + j], CBLK_LEN8); + mul_x64(ctx->gf_t4k[1][j]); + } + memcpy(ctx->gf_t4k[0][8], ctx->gf_t4k[1][1], CBLK_LEN8); + mul_x64(ctx->gf_t4k[0][8]); + for(j = 4; j > 0; j >>= 1) + { + memcpy(ctx->gf_t4k[0][j], ctx->gf_t4k[0][j + j], CBLK_LEN8); + mul_x64(ctx->gf_t4k[0][j]); + } + } + else if(i > 1) + for(j = 8; j > 0; j >>= 1) + { + memcpy(ctx->gf_t4k[i][j], ctx->gf_t4k[i - 2][j], CBLK_LEN8); + mul_x8_64(ctx->gf_t4k[i][j]); + } + + for(j = 2; j < 16; j += j) + { + mode(32t) *pj = ctx->gf_t4k[i][j]; + mode(32t) *pk = ctx->gf_t4k[i][1]; + mode(32t) *pl = ctx->gf_t4k[i][j + 1]; + + for(k = 1; k < j; ++k) + { + *pl++ = pj[0] ^ *pk++; + *pl++ = pj[1] ^ *pk++; + *pl++ = pj[2] ^ *pk++; + *pl++ = pj[3] ^ *pk++; + } + } + } +} + +static int IsBitSet128 (unsigned int bit, uint8_t *a) +{ + return a[(127 - bit) / 8] & (0x80 >> ((127 - bit) % 8)); +} + +static int IsBitSet64 (unsigned int bit, uint8_t *a) +{ + return a[(63 - bit) / 8] & (0x80 >> ((63 - bit) % 8)); +} + +static void SetBit128 (unsigned int bit, uint8_t *a) +{ + a[(127 - bit) / 8] |= 0x80 >> ((127 - bit) % 8); +} + +static void SetBit64 (unsigned int bit, uint8_t *a) +{ + a[(63 - bit) / 8] |= 0x80 >> ((63 - bit) % 8); +} + +void MirrorBits128 (uint8_t *a) +{ + uint8_t t[128 / 8]; + int i; + memset (t,0,16); + for (i = 0; i < 128; i++) + { + if (IsBitSet128(i, a)) + SetBit128 (127 - i, t); + } + memcpy (a, t, sizeof (t)); + burn (t,sizeof (t)); +} + +void MirrorBits64 (uint8_t *a) +{ + uint8_t t[64 / 8]; + int i; + memset (t,0,8); + for (i = 0; i < 64; i++) + { + if (IsBitSet64(i, a)) + SetBit64 (63 - i, t); + } + memcpy (a, t, sizeof (t)); + burn (t,sizeof (t)); +} + +/* Allocate and initialize speed optimization table + for multiplication by 64-bit operand in MSB-first mode */ +int Gf128Tab64Init (uint8_t *a, GfCtx *ctx) +{ + GfCtx8k *ctx8k; + uint8_t am[16]; + int i, j; + + ctx8k = (GfCtx8k *) TCalloc (sizeof (GfCtx8k)); + if (!ctx8k) + return 0; + + memcpy (am, a, 16); + MirrorBits128 (am); + compile_8k_table (am, ctx8k); + + /* Convert 8k LSB-first table to 4k MSB-first */ + for (i = 16; i < 32; i++) + { + for (j = 0; j < 16; j++) + { + int jm = 0; + jm |= (j & 0x1) << 3; + jm |= (j & 0x2) << 1; + jm |= (j & 0x4) >> 1; + jm |= (j & 0x8) >> 3; + + memcpy (&ctx->gf_t128[i-16][jm], (unsigned char *)&ctx8k->gf_t8k[31-i][j], 16); + MirrorBits128 ((unsigned char *)&ctx->gf_t128[i-16][jm]); + } + } + + burn (ctx8k ,sizeof (*ctx8k)); + burn (am, sizeof (am)); + TCfree (ctx8k); + return 1; +} + +int Gf64TabInit (uint8_t *a, GfCtx *ctx) +{ + /* Deprecated/legacy */ + + GfCtx4k64 *ctx4k; + uint8_t am[8]; + int i, j; + + ctx4k = (GfCtx4k64 *) TCalloc (sizeof (GfCtx4k64)); + if (!ctx4k) + return 0; + + memcpy (am, a, 8); + MirrorBits64 (am); + compile_4k_table64 (am, ctx4k); + + /* Convert LSB-first table to MSB-first */ + for (i = 0; i < 16; i++) + { + for (j = 0; j < 16; j++) + { + int jm = 0; + jm |= (j & 0x1) << 3; + jm |= (j & 0x2) << 1; + jm |= (j & 0x4) >> 1; + jm |= (j & 0x8) >> 3; + + memcpy (&ctx->gf_t64[i][jm], (unsigned char *)&ctx4k->gf_t4k[15-i][j], 8); + MirrorBits64 ((unsigned char *)&ctx->gf_t64[i][jm]); + } + } + + burn (ctx4k,sizeof (*ctx4k)); + burn (am, sizeof (am)); + TCfree (ctx4k); + return 1; +} + +#define xor_8kt64(i) \ + xor_block_aligned(r, ctx->gf_t128[i + i][a[i] & 15]); \ + xor_block_aligned(r, ctx->gf_t128[i + i + 1][a[i] >> 4]) + +/* Multiply a 128-bit number by a 64-bit number in the finite field GF(2^128) */ +void Gf128MulBy64Tab (uint8_t a[8], uint8_t p[16], GfCtx *ctx) +{ + uint32_t r[CBLK_LEN >> 2]; + + move_block_aligned(r, ctx->gf_t128[7*2][a[7] & 15]); + xor_block_aligned(r, ctx->gf_t128[7*2+1][a[7] >> 4]); + + if (*(uint16_t *)a) + { + xor_8kt64(0); + xor_8kt64(1); + } + if (a[2]) + { + xor_8kt64(2); + } + xor_8kt64(3); + xor_8kt64(4); + xor_8kt64(5); + xor_8kt64(6); + + move_block_aligned(p, r); +} + +#define xor_8k64(i) \ + xor_block_aligned64(r, ctx->gf_t64[i + i][a[i] & 15]); \ + xor_block_aligned64(r, ctx->gf_t64[i + i + 1][a[i] >> 4]) + +/* Multiply two 64-bit numbers in the finite field GF(2^64) */ +void Gf64MulTab (unsigned char a[8], unsigned char p[8], GfCtx *ctx) +{ + /* Deprecated/legacy */ + + uint32_t r[CBLK_LEN8 >> 2]; + + move_block_aligned64(r, ctx->gf_t64[7*2][a[7] & 15]); + xor_block_aligned64(r, ctx->gf_t64[7*2+1][a[7] >> 4]); + + if (*(uint16_t *)a) + { + xor_8k64(0); + xor_8k64(1); + } + if (a[2]) + { + xor_8k64(2); + } + xor_8k64(3); + xor_8k64(4); + xor_8k64(5); + xor_8k64(6); + + move_block_aligned64(p, r); +} + + +/* Basic algorithms for testing of optimized algorithms */ + +static void xor128 (uint64_t *a, uint64_t *b) +{ + *a++ ^= *b++; + *a ^= *b; +} + +static void shl128 (uint8_t *a) +{ + int i, x = 0, xx; + for (i = 15; i >= 0; i--) + { + xx = (a[i] & 0x80) >> 7; + a[i] = (a[i] << 1) | x; + x = xx; + } +} + +static void GfMul128Basic (uint8_t *a, uint8_t *b, uint8_t *p) +{ + int i; + uint8_t la[16]; + memcpy (la, a, 16); + memset (p, 0, 16); + + for (i = 0; i < 128; i++) + { + if (IsBitSet128 (i, b)) + xor128 ((uint64_t *)p, (uint64_t *)la); + + if (la[0] & 0x80) + { + shl128 (la); + la[15] ^= 0x87; + } + else + { + shl128 (la); + } + } +} + +static void xor64 (uint64_t *a, uint64_t *b) +{ + *a ^= *b; +} + +static void shl64 (uint8_t *a) +{ + int i, x = 0, xx; + for (i = 7; i >= 0; i--) + { + xx = (a[i] & 0x80) >> 7; + a[i] = (a[i] << 1) | x; + x = xx; + } +} + +static void GfMul64Basic (uint8_t *a, uint8_t *b, uint8_t* p) +{ + /* Deprecated/legacy */ + + int i; + uint8_t la[8]; + memcpy (la, a, 8); + memset (p, 0, 8); + + for (i = 0; i < 64; i++) + { + if (IsBitSet64 (i, b)) + xor64 ((uint64_t *)p, (uint64_t *)la); + + if (la[0] & 0x80) + { + shl64 (la); + la[7] ^= 0x1b; + } + else + { + shl64 (la); + } + } +} + + +int GfMulSelfTest (void) +{ + int result = 1; + uint8_t a[16]; + uint8_t b[16]; + uint8_t p1[16]; + uint8_t p2[16]; + GfCtx *gfCtx = (GfCtx *) TCalloc (sizeof (GfCtx)); + int i, j; + + if (!gfCtx) + return 0; + + /* GF(2^64) - deprecated/legacy */ + for (i = 0; i < 0x100; i++) + { + for (j = 0; j < 8; j++) + { + a[j] = (uint8_t) i; + b[j] = a[j] ^ 0xff; + } + + GfMul64Basic (a, b, p1); + + Gf64TabInit (a, gfCtx); + Gf64MulTab (b, p2, gfCtx); + + if (memcmp (p1, p2, 8) != 0) + result = 0; + } + + /* GF(2^128) */ + for (i = 0; i < 0x100; i++) + { + for (j = 0; j < 16; j++) + { + a[j] = (uint8_t) i; + b[j] = j < 8 ? 0 : a[j] ^ 0xff; + } + + GfMul128Basic (a, b, p1); + + Gf128Tab64Init (a, gfCtx); + Gf128MulBy64Tab (b + 8, p2, gfCtx); + + if (memcmp (p1, p2, 16) != 0) + result = 0; + } + + TCfree (gfCtx); + return result; +} + +#if defined(__cplusplus) +} +#endif diff --git a/src/utils/common/gfmul.h b/src/utils/common/gfmul.h new file mode 100644 index 000000000..da411ed67 --- /dev/null +++ b/src/utils/common/gfmul.h @@ -0,0 +1,78 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 31/01/2004 +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#ifndef _GCM_H +#define _GCM_H + +#include + +#include "tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define CBLK_LEN 16 /* encryption block length */ +#define CBLK_LEN8 8 + +typedef struct +{ + uint32_t gf_t8k[CBLK_LEN * 2][16][CBLK_LEN / 4]; +} GfCtx8k; + +typedef struct +{ + uint32_t gf_t4k[CBLK_LEN8 * 2][16][CBLK_LEN / 4]; +} GfCtx4k64; + +typedef struct +{ + /* union not used to support faster mounting */ + uint32_t gf_t128[CBLK_LEN * 2 / 2][16][CBLK_LEN / 4]; + uint32_t gf_t64[CBLK_LEN8 * 2][16][CBLK_LEN8 / 4]; +} GfCtx; + +typedef int ret_type; + +void GfMul128 (void *a, const void* b); +void GfMul128Tab(unsigned char a[16], GfCtx8k *ctx); +int Gf128Tab64Init (uint8_t *a, GfCtx *ctx); +void Gf128MulBy64Tab (uint8_t a[8], uint8_t p[16], GfCtx *ctx); +int Gf64TabInit (uint8_t *a, GfCtx *ctx); +void Gf64MulTab (unsigned char a[8], unsigned char p[8], GfCtx *ctx); +void MirrorBits128 (uint8_t *a); +void MirrorBits64 (uint8_t *a); +int GfMulSelfTest (void); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/utils/common/password.h b/src/utils/common/password.h new file mode 100644 index 000000000..cbf4cc53b --- /dev/null +++ b/src/utils/common/password.h @@ -0,0 +1,39 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef PASSWORD_H +#define PASSWORD_H + +#include + +// User text input limits +#define MIN_PASSWORD 1 // Minimum password length +#define MAX_PASSWORD 64 // Maximum password length + +#define PASSWORD_LEN_WARNING 20 // Display a warning when a password is shorter than this + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + // Modifying this structure can introduce incompatibility with previous versions + int32_t Length; + unsigned char Text[MAX_PASSWORD + 1]; + char Pad[3]; // keep 64-bit alignment +} Password; + +#ifdef __cplusplus +} +#endif + +#endif // PASSWORD_H diff --git a/src/utils/common/pkcs5.c b/src/utils/common/pkcs5.c new file mode 100644 index 000000000..2e55472b2 --- /dev/null +++ b/src/utils/common/pkcs5.c @@ -0,0 +1,631 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#include "tcdefs.h" + +#include +#include "../crypto/rmd160.h" +#include "../crypto/sha1.h" +#include "../crypto/sha2.h" +#include "../crypto/whirlpool.h" +#include "pkcs5.h" +#include "crypto.h" + +void hmac_truncate + ( + char *d1, /* data to be truncated */ + char *d2, /* truncated data */ + int len /* length in bytes to keep */ +) +{ + int i; + for (i = 0; i < len; i++) + d2[i] = d1[i]; +} + + +void hmac_sha512 +( + char *k, /* secret key */ + int lk, /* length of the key in bytes */ + char *d, /* data */ + int ld, /* length of data in bytes */ + char *out, /* output buffer, at least "t" bytes */ + int t +) +{ + sha512_ctx ictx, octx; + char isha[SHA512_DIGESTSIZE], osha[SHA512_DIGESTSIZE]; + char key[SHA512_DIGESTSIZE]; + char buf[SHA512_BLOCKSIZE]; + int i; + + /* If the key is longer than the hash algorithm block size, + let key = sha512(key), as per HMAC specifications. */ + if (lk > SHA512_BLOCKSIZE) + { + sha512_ctx tctx; + + sha512_begin (&tctx); + sha512_hash ((unsigned char *) k, lk, &tctx); + sha512_end ((unsigned char *) key, &tctx); + + k = key; + lk = SHA512_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /**** Inner Digest ****/ + + sha512_begin (&ictx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x36); + for (i = lk; i < SHA512_BLOCKSIZE; ++i) + buf[i] = 0x36; + + sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, &ictx); + sha512_hash ((unsigned char *) d, ld, &ictx); + + sha512_end ((unsigned char *) isha, &ictx); + + /**** Outer Digest ****/ + + sha512_begin (&octx); + + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x5C); + for (i = lk; i < SHA512_BLOCKSIZE; ++i) + buf[i] = 0x5C; + + sha512_hash ((unsigned char *) buf, SHA512_BLOCKSIZE, &octx); + sha512_hash ((unsigned char *) isha, SHA512_DIGESTSIZE, &octx); + + sha512_end ((unsigned char *) osha, &octx); + + /* truncate and print the results */ + t = t > SHA512_DIGESTSIZE ? SHA512_DIGESTSIZE : t; + hmac_truncate (osha, out, t); + + /* Prevent leaks */ + burn (&ictx, sizeof(ictx)); + burn (&octx, sizeof(octx)); + burn (isha, sizeof(isha)); + burn (osha, sizeof(osha)); + burn (buf, sizeof(buf)); + burn (key, sizeof(key)); +} + + +void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) +{ + char j[SHA512_DIGESTSIZE], k[SHA512_DIGESTSIZE]; + char init[128]; + char counter[4]; + int c, i; + + /* iteration 1 */ + memset (counter, 0, 4); + counter[3] = (char) b; + memcpy (init, salt, salt_len); /* salt */ + memcpy (&init[salt_len], counter, 4); /* big-endian block number */ + hmac_sha512 (pwd, pwd_len, init, salt_len + 4, j, SHA512_DIGESTSIZE); + memcpy (u, j, SHA512_DIGESTSIZE); + + /* remaining iterations */ + for (c = 1; c < iterations; c++) + { + hmac_sha512 (pwd, pwd_len, j, SHA512_DIGESTSIZE, k, SHA512_DIGESTSIZE); + for (i = 0; i < SHA512_DIGESTSIZE; i++) + { + u[i] ^= k[i]; + j[i] = k[i]; + } + } + + /* Prevent possible leaks. */ + burn (j, sizeof(j)); + burn (k, sizeof(k)); +} + + +void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) +{ + char u[SHA512_DIGESTSIZE]; + int b, l, r; + + if (dklen % SHA512_DIGESTSIZE) + { + l = 1 + dklen / SHA512_DIGESTSIZE; + } + else + { + l = dklen / SHA512_DIGESTSIZE; + } + + r = dklen - (l - 1) * SHA512_DIGESTSIZE; + + /* first l - 1 blocks */ + for (b = 1; b < l; b++) + { + derive_u_sha512 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, SHA512_DIGESTSIZE); + dk += SHA512_DIGESTSIZE; + } + + /* last block */ + derive_u_sha512 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, r); + + + /* Prevent possible leaks. */ + burn (u, sizeof(u)); +} + + +/* Deprecated/legacy */ +void hmac_sha1 +( + char *k, /* secret key */ + int lk, /* length of the key in bytes */ + char *d, /* data */ + int ld, /* length of data in bytes */ + char *out, /* output buffer, at least "t" bytes */ + int t +) +{ + sha1_ctx ictx, octx; + char isha[SHA1_DIGESTSIZE], osha[SHA1_DIGESTSIZE]; + char key[SHA1_DIGESTSIZE]; + char buf[SHA1_BLOCKSIZE]; + int i; + + /* If the key is longer than the hash algorithm block size, + let key = sha1(key), as per HMAC specifications. */ + if (lk > SHA1_BLOCKSIZE) + { + sha1_ctx tctx; + + sha1_begin (&tctx); + sha1_hash ((unsigned char *) k, lk, &tctx); + sha1_end ((unsigned char *) key, &tctx); + + k = key; + lk = SHA1_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /**** Inner Digest ****/ + + sha1_begin (&ictx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x36); + for (i = lk; i < SHA1_BLOCKSIZE; ++i) + buf[i] = 0x36; + + sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &ictx); + sha1_hash ((unsigned char *) d, ld, &ictx); + + sha1_end ((unsigned char *) isha, &ictx); + + /**** Outer Digest ****/ + + sha1_begin (&octx); + + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x5C); + for (i = lk; i < SHA1_BLOCKSIZE; ++i) + buf[i] = 0x5C; + + sha1_hash ((unsigned char *) buf, SHA1_BLOCKSIZE, &octx); + sha1_hash ((unsigned char *) isha, SHA1_DIGESTSIZE, &octx); + + sha1_end ((unsigned char *) osha, &octx); + + /* truncate and print the results */ + t = t > SHA1_DIGESTSIZE ? SHA1_DIGESTSIZE : t; + hmac_truncate (osha, out, t); + + /* Prevent leaks */ + burn (&ictx, sizeof(ictx)); + burn (&octx, sizeof(octx)); + burn (isha, sizeof(isha)); + burn (osha, sizeof(osha)); + burn (buf, sizeof(buf)); + burn (key, sizeof(key)); +} + + +/* Deprecated/legacy */ +void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) +{ + char j[SHA1_DIGESTSIZE], k[SHA1_DIGESTSIZE]; + char init[128]; + char counter[4]; + int c, i; + + /* iteration 1 */ + memset (counter, 0, 4); + counter[3] = (char) b; + memcpy (init, salt, salt_len); /* salt */ + memcpy (&init[salt_len], counter, 4); /* big-endian block number */ + hmac_sha1 (pwd, pwd_len, init, salt_len + 4, j, SHA1_DIGESTSIZE); + memcpy (u, j, SHA1_DIGESTSIZE); + + /* remaining iterations */ + for (c = 1; c < iterations; c++) + { + hmac_sha1 (pwd, pwd_len, j, SHA1_DIGESTSIZE, k, SHA1_DIGESTSIZE); + for (i = 0; i < SHA1_DIGESTSIZE; i++) + { + u[i] ^= k[i]; + j[i] = k[i]; + } + } + + /* Prevent possible leaks. */ + burn (j, sizeof(j)); + burn (k, sizeof(k)); +} + + +/* Deprecated/legacy */ +void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) +{ + char u[SHA1_DIGESTSIZE]; + int b, l, r; + + if (dklen % SHA1_DIGESTSIZE) + { + l = 1 + dklen / SHA1_DIGESTSIZE; + } + else + { + l = dklen / SHA1_DIGESTSIZE; + } + + r = dklen - (l - 1) * SHA1_DIGESTSIZE; + + /* first l - 1 blocks */ + for (b = 1; b < l; b++) + { + derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, SHA1_DIGESTSIZE); + dk += SHA1_DIGESTSIZE; + } + + /* last block */ + derive_u_sha1 (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, r); + + + /* Prevent possible leaks. */ + burn (u, sizeof(u)); +} + + +void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest) +{ + RMD160_CTX context; + unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ + unsigned char k_opad[65]; /* outer padding - key XORd with opad */ + unsigned char tk[RIPEMD160_DIGESTSIZE]; + int i; + + /* If the key is longer than the hash algorithm block size, + let key = ripemd160(key), as per HMAC specifications. */ + if (keylen > RIPEMD160_BLOCKSIZE) + { + RMD160_CTX tctx; + + RMD160Init(&tctx); + RMD160Update(&tctx, (const uint8_t *) key, keylen); + RMD160Final(tk, &tctx); + + key = (char *) tk; + keylen = RIPEMD160_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /* + + RMD160(K XOR opad, RMD160(K XOR ipad, text)) + + where K is an n byte key + ipad is the byte 0x36 repeated RIPEMD160_BLOCKSIZE times + opad is the byte 0x5c repeated RIPEMD160_BLOCKSIZE times + and text is the data being protected */ + + + /* start out by storing key in pads */ + memset(k_ipad, 0x36, sizeof(k_ipad)); + memset(k_opad, 0x5c, sizeof(k_opad)); + + /* XOR key with ipad and opad values */ + for (i=0; i WHIRLPOOL_BLOCKSIZE) + { + WHIRLPOOL_CTX tctx; + + WHIRLPOOL_init (&tctx); + WHIRLPOOL_add ((unsigned char *) k, lk * 8, &tctx); + WHIRLPOOL_finalize (&tctx, (unsigned char *) key); + + k = key; + lk = WHIRLPOOL_DIGESTSIZE; + + burn (&tctx, sizeof(tctx)); // Prevent leaks + } + + /**** Inner Digest ****/ + + WHIRLPOOL_init (&ictx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x36); + for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) + buf[i] = 0x36; + + WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &ictx); + WHIRLPOOL_add ((unsigned char *) d, ld * 8, &ictx); + + WHIRLPOOL_finalize (&ictx, (unsigned char *) iwhi); + + /**** Outer Digest ****/ + + WHIRLPOOL_init (&octx); + + for (i = 0; i < lk; ++i) + buf[i] = (char) (k[i] ^ 0x5C); + for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) + buf[i] = 0x5C; + + WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &octx); + WHIRLPOOL_add ((unsigned char *) iwhi, WHIRLPOOL_DIGESTSIZE * 8, &octx); + + WHIRLPOOL_finalize (&octx, (unsigned char *) owhi); + + /* truncate and print the results */ + t = t > WHIRLPOOL_DIGESTSIZE ? WHIRLPOOL_DIGESTSIZE : t; + hmac_truncate (owhi, out, t); + + /* Prevent possible leaks. */ + burn (&ictx, sizeof(ictx)); + burn (&octx, sizeof(octx)); + burn (owhi, sizeof(owhi)); + burn (iwhi, sizeof(iwhi)); + burn (buf, sizeof(buf)); + burn (key, sizeof(key)); +} + +void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b) +{ + char j[WHIRLPOOL_DIGESTSIZE], k[WHIRLPOOL_DIGESTSIZE]; + char init[128]; + char counter[4]; + int c, i; + + /* iteration 1 */ + memset (counter, 0, 4); + counter[3] = (char) b; + memcpy (init, salt, salt_len); /* salt */ + memcpy (&init[salt_len], counter, 4); /* big-endian block number */ + hmac_whirlpool (pwd, pwd_len, init, salt_len + 4, j, WHIRLPOOL_DIGESTSIZE); + memcpy (u, j, WHIRLPOOL_DIGESTSIZE); + + /* remaining iterations */ + for (c = 1; c < iterations; c++) + { + hmac_whirlpool (pwd, pwd_len, j, WHIRLPOOL_DIGESTSIZE, k, WHIRLPOOL_DIGESTSIZE); + for (i = 0; i < WHIRLPOOL_DIGESTSIZE; i++) + { + u[i] ^= k[i]; + j[i] = k[i]; + } + } + + /* Prevent possible leaks. */ + burn (j, sizeof(j)); + burn (k, sizeof(k)); +} + +void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen) +{ + char u[WHIRLPOOL_DIGESTSIZE]; + int b, l, r; + + if (dklen % WHIRLPOOL_DIGESTSIZE) + { + l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; + } + else + { + l = dklen / WHIRLPOOL_DIGESTSIZE; + } + + r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; + + /* first l - 1 blocks */ + for (b = 1; b < l; b++) + { + derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, WHIRLPOOL_DIGESTSIZE); + dk += WHIRLPOOL_DIGESTSIZE; + } + + /* last block */ + derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, u, b); + memcpy (dk, u, r); + + + /* Prevent possible leaks. */ + burn (u, sizeof(u)); +} + + +char *get_pkcs5_prf_name (int pkcs5_prf_id) +{ + switch (pkcs5_prf_id) + { + case SHA512: + return "HMAC-SHA-512"; + + case SHA1: // Deprecated/legacy + return "HMAC-SHA-1"; + + case RIPEMD160: + return "HMAC-RIPEMD-160"; + + case WHIRLPOOL: + return "HMAC-Whirlpool"; + + default: + return "(Unknown)"; + } +} + + +int get_pkcs5_iteration_count (int pkcs5_prf_id, int bBoot) +{ + switch (pkcs5_prf_id) + { + case RIPEMD160: + return (bBoot ? 1000 : 2000); + + case SHA512: + return 1000; + + case SHA1: // Deprecated/legacy + return 2000; + + case WHIRLPOOL: + return 1000; + + default: + TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID + } + return 0; +} diff --git a/src/utils/common/pkcs5.h b/src/utils/common/pkcs5.h new file mode 100644 index 000000000..efd2cc9ed --- /dev/null +++ b/src/utils/common/pkcs5.h @@ -0,0 +1,41 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TC_HEADER_PKCS5 +#define TC_HEADER_PKCS5 + +#include "tcdefs.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void hmac_sha512 (char *k, int lk, char *d, int ld, char *out, int t); +void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +void hmac_sha1 (char *k, int lk, char *d, int ld, char *out, int t); +void derive_u_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_sha1 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest); +void derive_u_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +void hmac_whirlpool (char *k, int lk, char *d, int ld, char *out, int t); +void derive_u_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b); +void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen); +int get_pkcs5_iteration_count (int pkcs5_prf_id, int bBoot); +char *get_pkcs5_prf_name (int pkcs5_prf_id); + +#if defined(__cplusplus) +} +#endif + +#endif // TC_HEADER_PKCS5 diff --git a/src/utils/common/tcdefs.h b/src/utils/common/tcdefs.h new file mode 100644 index 000000000..49dc6bde2 --- /dev/null +++ b/src/utils/common/tcdefs.h @@ -0,0 +1,167 @@ +/* + Legal Notice: Some portions of the source code contained in this file were + derived from the source code of Encryption for the Masses 2.02a, which is + Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License + Agreement for Encryption for the Masses'. Modifications and additions to + the original source code (contained in this file) and all other portions of + this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed + by the TrueCrypt License 2.4 the full text of which is contained in the + file License.txt included in TrueCrypt binary and source code distribution + packages. */ + +#ifndef TCDEFS_H +#define TCDEFS_H + +#include +#include + +#define TC_APP_NAME "TrueCrypt" + +// Version displayed to user +#define VERSION_STRING "5.1a" + +// Version number to compare against driver +#define VERSION_NUM 0x051a + +// Version number written to volume header during format, +// specifies the minimum program version required to mount the volume +#define VOL_REQ_PROG_VERSION 0x0500 + +// Volume header version +#define VOLUME_HEADER_VERSION 0x0003 + +// Sector size of encrypted filesystem, which may differ from sector size +// of host filesystem/device (this is fully supported since v4.3). +#define SECTOR_SIZE 512 + +#define BYTES_PER_KB 1024LL +#define BYTES_PER_MB 1048576LL +#define BYTES_PER_GB 1073741824LL +#define BYTES_PER_TB 1099511627776LL +#define BYTES_PER_PB 1125899906842624LL + +/* GUI/driver errors */ + +#define MAX_128BIT_BLOCK_VOLUME_SIZE BYTES_PER_PB // Security bound (128-bit block XTS mode) +#define MAX_VOLUME_SIZE_GENERAL 0x7fffFFFFffffFFFFLL // Signed 64-bit integer file offset values +#define MAX_VOLUME_SIZE MAX_128BIT_BLOCK_VOLUME_SIZE +#define MIN_FAT_VOLUME_SIZE 19456 +#define MAX_FAT_VOLUME_SIZE 0x20000000000LL +#define MIN_NTFS_VOLUME_SIZE 2634752 +#define OPTIMAL_MIN_NTFS_VOLUME_SIZE (4 * BYTES_PER_GB) +#define MAX_NTFS_VOLUME_SIZE (128LL * BYTES_PER_TB) // NTFS volume can theoretically be up to 16 exabytes, but Windows XP and 2003 limit the size to that addressable with 32-bit clusters, i.e. max size is 128 TB (if 64-KB clusters are used). +#define MAX_HIDDEN_VOLUME_HOST_SIZE MAX_NTFS_VOLUME_SIZE +#define MAX_HIDDEN_VOLUME_SIZE ( MAX_HIDDEN_VOLUME_HOST_SIZE - HIDDEN_VOL_HEADER_OFFSET - HEADER_SIZE ) +#define MIN_VOLUME_SIZE MIN_FAT_VOLUME_SIZE +#define MIN_HIDDEN_VOLUME_HOST_SIZE ( MIN_VOLUME_SIZE * 2 + HIDDEN_VOL_HEADER_OFFSET + HEADER_SIZE ) + +#ifndef TC_NO_COMPILER_INT64 +#if MAX_VOLUME_SIZE > MAX_VOLUME_SIZE_GENERAL +#error MAX_VOLUME_SIZE must be less than or equal to MAX_VOLUME_SIZE_GENERAL +#endif +#endif + +#define TCalloc(X) calloc(1, X) +#define TCfree free + +#define WIDE(x) (LPWSTR)L##x + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef uint8_t byte; +typedef uint16_t uint16; +typedef uint32_t uint32; + +#ifdef TC_NO_COMPILER_INT64 +typedef uint32_t TC_LARGEST_COMPILER_UINT; +#else +typedef uint64_t TC_LARGEST_COMPILER_UINT; +typedef int64_t int64; +typedef uint64_t uint64; +#endif + +// Needed by Cryptolib +typedef uint8_t uint_8t; +typedef uint16_t uint_16t; +typedef uint32_t uint_32t; +#ifndef TC_NO_COMPILER_INT64 +typedef uint64_t uint_64t; +#endif + +typedef union +{ + struct + { + uint32_t LowPart; + uint32_t HighPart; + }; +#ifndef TC_NO_COMPILER_INT64 + uint64_t Value; +#endif + +} UINT64_STRUCT; + + +#define TC_THROW_FATAL_EXCEPTION *(char *) 0 = 0 + +#define burn(mem,size) do { volatile char *burnm = (volatile char *)(mem); int burnc = size; while (burnc--) *burnm++ = 0; } while (0) + +// The size of the memory area to wipe is in bytes amd it must be a multiple of 8. +#ifndef TC_NO_COMPILER_INT64 +# define FAST_ERASE64(mem,size) do { volatile uint64_t *burnm = (volatile uint64_t *)(mem); int burnc = size >> 3; while (burnc--) *burnm++ = 0; } while (0) +#else +# define FAST_ERASE64(mem,size) do { volatile uint32_t *burnm = (volatile uint32_t *)(mem); int burnc = size >> 2; while (burnc--) *burnm++ = 0; } while (0) +#endif + + +#ifdef MAX_PATH +#define TC_MAX_PATH MAX_PATH +#else +#define TC_MAX_PATH 260 /* Includes the null terminator */ +#endif + +#define MAX_URL_LENGTH 2084 /* Internet Explorer limit. Includes the terminating null character. */ + + +enum +{ + /* WARNING: Add any new codes at the end (do NOT insert them between existing). Do NOT delete any + existing codes. Changing these values or their meanings may cause incompatibility with other + versions (for example, if a new version of the TrueCrypt installer receives an error code from + an installed driver whose version is lower, it will interpret the error incorrectly). */ + + ERR_SUCCESS = 0, + ERR_OS_ERROR = 1, + ERR_OUTOFMEMORY, + ERR_PASSWORD_WRONG, + ERR_VOL_FORMAT_BAD, + ERR_DRIVE_NOT_FOUND, + ERR_FILES_OPEN, + ERR_VOL_SIZE_WRONG, + ERR_COMPRESSION_NOT_SUPPORTED, + ERR_PASSWORD_CHANGE_VOL_TYPE, + ERR_PASSWORD_CHANGE_VOL_VERSION, + ERR_VOL_SEEKING, + ERR_VOL_WRITING, + ERR_FILES_OPEN_LOCK, + ERR_VOL_READING, + ERR_DRIVER_VERSION, + ERR_NEW_VERSION_REQUIRED, + ERR_CIPHER_INIT_FAILURE, + ERR_CIPHER_INIT_WEAK_KEY, + ERR_SELF_TESTS_FAILED, + ERR_SECTOR_SIZE_INCOMPATIBLE, + ERR_VOL_ALREADY_MOUNTED, + ERR_NO_FREE_DRIVES, + ERR_FILE_OPEN_FAILED, + ERR_VOL_MOUNT_FAILED, + ERR_INVALID_DEVICE, + ERR_ACCESS_DENIED, + ERR_MODE_INIT_FAILED, + ERR_DONT_REPORT, + ERR_ENCRYPTION_NOT_COMPLETED, + ERR_PARAMETER_INCORRECT +}; + +#endif // #ifndef TCDEFS_H diff --git a/src/utils/common/xts.c b/src/utils/common/xts.c new file mode 100644 index 000000000..47fcc2f90 --- /dev/null +++ b/src/utils/common/xts.c @@ -0,0 +1,627 @@ +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.4 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +/* For low-memory environments, define XTS_LOW_RESOURCE_VERSION, which will save +0.5 KB of RAM, but the speed will be 15-20% lower. However, on multi-core CPUs, +the XTS_LOW_RESOURCE_VERSION code might eventually be faster when parallelized, +because it processes the buffer continuously as a whole -- it does not divide the +buffer into data units (nevertheless, note that GenerateWhiteningValues supports +more than one data unit). + +Note that when TC_NO_COMPILER_INT64 is defined, XTS_LOW_RESOURCE_VERSION is implicitly +defined as well (because the non-low-resource version needs 64-bit types). + +For big-endian platforms (PowerPC, SPARC, etc.) define BYTE_ORDER as BIG_ENDIAN. */ + + +#ifdef TC_MINIMIZE_CODE_SIZE +# define XTS_LOW_RESOURCE_VERSION +# pragma optimize ("tl", on) +#endif + +#ifdef TC_NO_COMPILER_INT64 +# ifndef XTS_LOW_RESOURCE_VERSION +# define XTS_LOW_RESOURCE_VERSION +# endif +#endif + + +#include "xts.h" + + +#ifndef XTS_LOW_RESOURCE_VERSION + +// length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size +// ks: the primary key schedule +// ks2: the secondary key schedule +// startDataUnitNo: The sequential number of the data unit with which the buffer starts. +// startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit startDataUnitNo. +// When encrypting the data unit from its first block, startCipherBlockNo is 0. +// The startCipherBlockNo value applies only to the first data unit in the buffer; each successive +// data unit is encrypted from its first block. The start of the buffer does not have to be +// aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it +// is not aligned, startCipherBlockNo must reflect the misalignment accordingly. +void EncryptBufferXTS (uint8_t *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startCipherBlockNo, + uint8_t *ks, + uint8_t *ks2, + int cipher) +{ + uint8_t finalCarry; + uint8_t whiteningValues [ENCRYPTION_DATA_UNIT_SIZE]; + uint8_t whiteningValue [BYTES_PER_XTS_BLOCK]; + uint8_t byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + uint64_t *whiteningValuesPtr64 = (uint64_t *) whiteningValues; + uint64_t *whiteningValuePtr64 = (uint64_t *) whiteningValue; + uint64_t *bufPtr = (uint64_t *) buffer; + unsigned int startBlock = startCipherBlockNo, endBlock, block; + uint64_t *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1; + TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; + + /* The encrypted data unit number (i.e. the resultant ciphertext block) is to be multiplied in the + finite field GF(2^128) by j-th power of n, where j is the sequential plaintext/ciphertext block + number and n is 2, a primitive element of GF(2^128). This can be (and is) simplified and implemented + as a left shift of the preceding whitening value by one bit (with carry propagating). In addition, if + the shift of the highest byte results in a carry, 135 is XORed into the lowest byte. The value 135 is + derived from the modulus of the Galois Field (x^128+x^7+x^2+x+1). */ + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + dataUnitNo = startDataUnitNo->Value; + *((uint64_t *) byteBufUnitNo) = LE64 (dataUnitNo); + *((uint64_t *) byteBufUnitNo + 1) = 0; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Process all blocks in the buffer + // When length > ENCRYPTION_DATA_UNIT_SIZE, this can be parallelized (one data unit per core) + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; + whiteningValuePtr64 = (uint64_t *) whiteningValue; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + *whiteningValuePtr64 = *((uint64_t *) byteBufUnitNo); + *(whiteningValuePtr64 + 1) = 0; + EncipherBlock (cipher, whiteningValue, ks2); + + // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit + // whitening values are stored in memory as a sequence of 64-bit integers in reverse order. + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + *whiteningValuesPtr64-- = *whiteningValuePtr64++; + *whiteningValuesPtr64-- = *whiteningValuePtr64; + } + else + whiteningValuePtr64++; + + // Derive the next whitening value + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms (Intel, AMD, etc.) + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; + +#else + // Big-endian platforms (PowerPC, Motorola, etc.) + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; + + // Encrypt all blocks in this data unit + // TO DO: This should be parallelized (one block per core) + for (block = startBlock; block < endBlock; block++) + { + // Pre-whitening + *bufPtr++ ^= *whiteningValuesPtr64--; + *bufPtr-- ^= *whiteningValuesPtr64++; + + // Actual encryption + EncipherBlock (cipher, bufPtr, ks); + + // Post-whitening + *bufPtr++ ^= *whiteningValuesPtr64--; + *bufPtr++ ^= *whiteningValuesPtr64--; + + blockCount--; + } + + startBlock = 0; + + dataUnitNo++; + + *((uint64_t *) byteBufUnitNo) = LE64 (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof(whiteningValue)); + FAST_ERASE64 (whiteningValues, sizeof(whiteningValues)); +} + + +// For descriptions of the input parameters, see EncryptBufferXTS(). +void DecryptBufferXTS (uint8_t *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startCipherBlockNo, + uint8_t *ks, + uint8_t *ks2, + int cipher) +{ + uint8_t finalCarry; + uint8_t whiteningValues [ENCRYPTION_DATA_UNIT_SIZE]; + uint8_t whiteningValue [BYTES_PER_XTS_BLOCK]; + uint8_t byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + uint64_t *whiteningValuesPtr64 = (uint64_t *) whiteningValues; + uint64_t *whiteningValuePtr64 = (uint64_t *) whiteningValue; + uint64_t *bufPtr = (uint64_t *) buffer; + unsigned int startBlock = startCipherBlockNo, endBlock, block; + uint64_t *const finalInt64WhiteningValuesPtr = whiteningValuesPtr64 + sizeof (whiteningValues) / sizeof (*whiteningValuesPtr64) - 1; + TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + dataUnitNo = startDataUnitNo->Value; + *((uint64_t *) byteBufUnitNo) = LE64 (dataUnitNo); + *((uint64_t *) byteBufUnitNo + 1) = 0; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Process all blocks in the buffer + // When length > ENCRYPTION_DATA_UNIT_SIZE, this can be parallelized (one data unit per core) + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; + whiteningValuePtr64 = (uint64_t *) whiteningValue; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + *whiteningValuePtr64 = *((uint64_t *) byteBufUnitNo); + *(whiteningValuePtr64 + 1) = 0; + EncipherBlock (cipher, whiteningValue, ks2); + + // Generate subsequent whitening values for blocks in this data unit. Note that all generated 128-bit + // whitening values are stored in memory as a sequence of 64-bit integers in reverse order. + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + *whiteningValuesPtr64-- = *whiteningValuePtr64++; + *whiteningValuesPtr64-- = *whiteningValuePtr64; + } + else + whiteningValuePtr64++; + + // Derive the next whitening value + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms (Intel, AMD, etc.) + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; + +#else + // Big-endian platforms (PowerPC, Motorola, etc.) + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + whiteningValuesPtr64 = finalInt64WhiteningValuesPtr; + + // Decrypt blocks in this data unit + // TO DO: This should be parallelized (one block per core) + for (block = startBlock; block < endBlock; block++) + { + *bufPtr++ ^= *whiteningValuesPtr64--; + *bufPtr-- ^= *whiteningValuesPtr64++; + + DecipherBlock (cipher, bufPtr, ks); + + *bufPtr++ ^= *whiteningValuesPtr64--; + *bufPtr++ ^= *whiteningValuesPtr64--; + + blockCount--; + } + + startBlock = 0; + + dataUnitNo++; + + *((uint64_t *) byteBufUnitNo) = LE64 (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof(whiteningValue)); + FAST_ERASE64 (whiteningValues, sizeof(whiteningValues)); +} + + +#if 0 // The following function is currently unused but may be useful in future + +// Generates XTS whitening values. Use this function if you need to generate whitening values for more than +// one data unit in one pass (the value 'length' may be greater than the data unit size). 'buffer' must point +// to the LAST 8 bytes of the buffer for the whitening values. Note that the generated 128-bit whitening values +// are stored in memory as a sequence of 64-bit integers in reverse order. For descriptions of the input +// parameters, see EncryptBufferXTS(). +static void GenerateWhiteningValues (uint64_t *bufPtr64, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startBlock, + uint8_t *ks2, + int cipher) +{ + unsigned int block; + unsigned int endBlock; + uint8_t byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + uint8_t whiteningValue [BYTES_PER_XTS_BLOCK]; + uint64_t *whiteningValuePtr64 = (uint64_t *) whiteningValue; + uint8_t finalCarry; + uint64_t *const finalInt64WhiteningValuePtr = whiteningValuePtr64 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr64) - 1; + TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo; + + dataUnitNo = startDataUnitNo->Value; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes. + *((uint64_t *) byteBufUnitNo) = LE64 (dataUnitNo); + *((uint64_t *) byteBufUnitNo + 1) = 0; + + // Generate the whitening values. + // When length > ENCRYPTION_DATA_UNIT_SIZE, this can be parallelized (one data unit per core) + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK); + EncipherBlock (cipher, whiteningValue, ks2); + + // Process all blocks in this data unit + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + whiteningValuePtr64 = (uint64_t *) whiteningValue; + + *bufPtr64-- = *whiteningValuePtr64++; + *bufPtr64-- = *whiteningValuePtr64; + + blockCount--; + } + + // Derive the next whitening value + + whiteningValuePtr64 = finalInt64WhiteningValuePtr; + +#if BYTE_ORDER == LITTLE_ENDIAN + + // Little-endian platforms (Intel, AMD, etc.) + + finalCarry = + (*whiteningValuePtr64 & 0x8000000000000000) ? + 135 : 0; + + *whiteningValuePtr64-- <<= 1; + + if (*whiteningValuePtr64 & 0x8000000000000000) + *(whiteningValuePtr64 + 1) |= 1; + + *whiteningValuePtr64 <<= 1; + +#else + // Big-endian platforms (PowerPC, Motorola, etc.) + + finalCarry = + (*whiteningValuePtr64 & 0x80) ? + 135 : 0; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); + + whiteningValuePtr64--; + + if (*whiteningValuePtr64 & 0x80) + *(whiteningValuePtr64 + 1) |= 0x0100000000000000; + + *whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1); +#endif + + whiteningValue[0] ^= finalCarry; + } + + startBlock = 0; + + dataUnitNo++; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + *((uint64_t *) byteBufUnitNo) = LE64 (dataUnitNo); + } + + FAST_ERASE64 (whiteningValue, sizeof(whiteningValue)); +} +#endif // #if 0 + + +#else // XTS_LOW_RESOURCE_VERSION + + +#if BYTE_ORDER == BIG_ENDIAN +#error XTS_LOW_RESOURCE_VERSION is not compatible with big-endian platforms +#endif + + +// Increases a 64-bit value by one in a way compatible with non-64-bit environments/platforms +static void IncUint64Struct (UINT64_STRUCT *uint64Struct) +{ +#ifdef TC_NO_COMPILER_INT64 + if (!++uint64Struct->LowPart) + { + uint64Struct->HighPart++; + } +#else + uint64Struct->Value++; +#endif +} + + +// Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit +// environments/platforms) into a little-endian 16-byte array. +static void Uint64ToLE16ByteArray (uint8_t *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32) +{ + unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf; + + *bufPtr32++ = lowInt32; + *bufPtr32++ = highInt32; + + // We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes + *bufPtr32++ = 0; + *bufPtr32 = 0; +} + + +// Generates and XORs XTS whitening values into blocks in the buffer. +// For descriptions of the input parameters, see EncryptBufferXTS(). +static void WhiteningPass (uint8_t *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *startDataUnitNo, + unsigned int startBlock, + uint8_t *ks2, + int cipher) +{ + TC_LARGEST_COMPILER_UINT blockCount; + UINT64_STRUCT dataUnitNo; + unsigned int block; + unsigned int endBlock; + uint8_t byteBufUnitNo [BYTES_PER_XTS_BLOCK]; + uint8_t whiteningValue [BYTES_PER_XTS_BLOCK]; + unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer; + unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; + uint8_t finalCarry; + unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1; + + // Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms + dataUnitNo.HighPart = startDataUnitNo->HighPart; + dataUnitNo.LowPart = startDataUnitNo->LowPart; + + blockCount = length / BYTES_PER_XTS_BLOCK; + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + // (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.) + Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); + + // Generate whitening values for all blocks in the buffer + while (blockCount > 0) + { + if (blockCount < BLOCKS_PER_XTS_DATA_UNIT) + endBlock = startBlock + (unsigned int) blockCount; + else + endBlock = BLOCKS_PER_XTS_DATA_UNIT; + + // Encrypt the data unit number using the secondary key (in order to generate the first + // whitening value for this data unit) + memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK); + EncipherBlock (cipher, whiteningValue, ks2); + + // Generate subsequent whitening values and XOR each whitening value into corresponding + // ciphertext/plaintext block + + for (block = 0; block < endBlock; block++) + { + if (block >= startBlock) + { + whiteningValuePtr32 = (unsigned __int32 *) whiteningValue; + + // XOR the whitening value into this ciphertext/plaintext block + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32++; + *bufPtr32++ ^= *whiteningValuePtr32; + + blockCount--; + } + + // Derive the next whitening value + + finalCarry = 0; + + for (whiteningValuePtr32 = finalDwordWhiteningValuePtr; + whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue; + whiteningValuePtr32--) + { + if (*whiteningValuePtr32 & 0x80000000) // If the following shift results in a carry + { + if (whiteningValuePtr32 != finalDwordWhiteningValuePtr) // If not processing the highest double word + { + // A regular carry + *(whiteningValuePtr32 + 1) |= 1; + } + else + { + // The highest byte shift will result in a carry + finalCarry = 135; + } + } + + *whiteningValuePtr32 <<= 1; + } + + whiteningValue[0] ^= finalCarry; + } + + startBlock = 0; + + // Increase the data unit number by one + IncUint64Struct (&dataUnitNo); + + // Convert the 64-bit data unit number into a little-endian 16-byte array. + Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart); + } + + FAST_ERASE64 (whiteningValue, sizeof(whiteningValue)); +} + + +// length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size +// ks: the primary key schedule +// ks2: the secondary key schedule +// dataUnitNo: The sequential number of the data unit with which the buffer starts. +// startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit dataUnitNo. +// When encrypting the data unit from its first block, startCipherBlockNo is 0. +// The startCipherBlockNo value applies only to the first data unit in the buffer; each successive +// data unit is encrypted from its first block. The start of the buffer does not have to be +// aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it +// is not aligned, startCipherBlockNo must reflect the misalignment accordingly. +void EncryptBufferXTS (uint8_t *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *dataUnitNo, + unsigned int startCipherBlockNo, + uint8_t *ks, + uint8_t *ks2, + int cipher) +{ + TC_LARGEST_COMPILER_UINT blockCount; + uint8_t *bufPtr = buffer; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + // Pre-whitening (all plaintext blocks in the buffer) + WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher); + + // Encrypt all plaintext blocks in the buffer + for (blockCount = 0; blockCount < length / BYTES_PER_XTS_BLOCK; blockCount++) + { + EncipherBlock (cipher, bufPtr, ks); + bufPtr += BYTES_PER_XTS_BLOCK; + } + + // Post-whitening (all ciphertext blocks in the buffer) + WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher); +} + + +// For descriptions of the input parameters, see EncryptBufferXTS(). +void DecryptBufferXTS (uint8_t *buffer, + TC_LARGEST_COMPILER_UINT length, + const UINT64_STRUCT *dataUnitNo, + unsigned int startCipherBlockNo, + uint8_t *ks, + uint8_t *ks2, + int cipher) +{ + TC_LARGEST_COMPILER_UINT blockCount; + uint8_t *bufPtr = buffer; + + if (length % BYTES_PER_XTS_BLOCK) + TC_THROW_FATAL_EXCEPTION; + + WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher); + + for (blockCount = 0; blockCount < length / BYTES_PER_XTS_BLOCK; blockCount++) + { + DecipherBlock (cipher, bufPtr, ks); + bufPtr += BYTES_PER_XTS_BLOCK; + } + + WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher); +} + +#endif // XTS_LOW_RESOURCE_VERSION diff --git a/src/utils/common/xts.h b/src/utils/common/xts.h new file mode 100644 index 000000000..cce7877b8 --- /dev/null +++ b/src/utils/common/xts.h @@ -0,0 +1,79 @@ +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.4 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#ifndef XTS_H +#define XTS_H + +// Header files (optional) + +#include + +#include "tcdefs.h" +#include "../common/endian.h" +#include "crypto.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// Macros + +#ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1 +#endif + +#ifndef BIG_ENDIAN +# define BIG_ENDIAN 2 +#endif + +#ifndef BYTE_ORDER +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#ifndef LE64 +# if BYTE_ORDER == LITTLE_ENDIAN +# define LE64(x) (x) +# endif +#endif + +// Custom data types + +#ifndef TC_LARGEST_COMPILER_UINT +# ifdef TC_NO_COMPILER_INT64 + typedef uint32_t TC_LARGEST_COMPILER_UINT; +# else + typedef uint64_t TC_LARGEST_COMPILER_UINT; +# endif +#endif + +#ifndef TCDEFS_H +typedef union +{ + struct + { + uint32_t LowPart; + uint32_t HighPart; + }; +# ifndef TC_NO_COMPILER_INT64 + uint64_t Value; +# endif + +} UINT64_STRUCT; +#endif + +// Public function prototypes + +void EncryptBufferXTS (uint8_t *buffer, TC_LARGEST_COMPILER_UINT length, const UINT64_STRUCT *startDataUnitNo, unsigned int startCipherBlockNo, uint8_t *ks, uint8_t *ks2, int cipher); +void DecryptBufferXTS (uint8_t *buffer, TC_LARGEST_COMPILER_UINT length, const UINT64_STRUCT *startDataUnitNo, unsigned int startCipherBlockNo, uint8_t *ks, uint8_t *ks2, int cipher); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef XTS_H diff --git a/src/utils/crypto/aes.h b/src/utils/crypto/aes.h new file mode 100644 index 000000000..e8ae33e9d --- /dev/null +++ b/src/utils/crypto/aes.h @@ -0,0 +1,215 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + + This file contains the definitions required to use AES in C. See aesopt.h + for optimisation details. +*/ + +/* Adapted by the TrueCrypt Foundation */ + +#ifndef _AES_H +#define _AES_H + +#include "../common/tcdefs.h" + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#endif +#define INT_RETURN int + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define AES_128 /* define if AES with 128 bit keys is needed */ +#define AES_192 /* define if AES with 192 bit keys is needed */ +#define AES_256 /* define if AES with 256 bit keys is needed */ +#define AES_VAR /* define if a variable key size is needed */ +// #define AES_MODES /* define if support is needed for modes */ + +/* The following must also be set in assembler files if being used */ + +#define AES_ENCRYPT /* if support for encryption is needed */ +#define AES_DECRYPT /* if support for decryption is needed */ +#define AES_ERR_CHK /* for parameter checks & error return codes */ +#define AES_REV_DKS /* define to reverse decryption key schedule */ + +#define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ +#define N_COLS 4 /* the number of columns in the state */ + +/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ +/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ +/* or 44, 52 or 60 32-bit words. */ + +#if defined( AES_VAR ) || defined( AES_256 ) +#define KS_LENGTH 60 +#elif defined( AES_192 ) +#define KS_LENGTH 52 +#else +#define KS_LENGTH 44 +#endif + +#if defined( AES_ERR_CHK ) +#define AES_RETURN INT_RETURN +#else +#define AES_RETURN VOID_RETURN +#endif + +/* the character array 'inf' in the following structures is used */ +/* to hold AES context information. This AES code uses cx->inf.b[0] */ +/* to hold the number of rounds multiplied by 16. The other three */ +/* elements can be used by code that implements additional modes */ + +typedef union +{ uint_32t l; + uint_8t b[4]; +} aes_inf; + +typedef struct +{ uint_32t ks[KS_LENGTH]; + aes_inf inf; +} aes_encrypt_ctx; + +typedef struct +{ uint_32t ks[KS_LENGTH]; + aes_inf inf; +} aes_decrypt_ctx; + +/* This routine must be called before first use if non-static */ +/* tables are being used */ + +AES_RETURN aes_init(void); + +/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ +/* those in the range 128 <= key_len <= 256 are given in bits */ + +#if defined( AES_ENCRYPT ) + +#if defined(AES_128) || defined(AES_VAR) +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined(AES_192) || defined(AES_VAR) +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined(AES_256) || defined(AES_VAR) +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined(AES_VAR) +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); + +#endif + +#if defined( AES_DECRYPT ) + +#if defined(AES_128) || defined(AES_VAR) +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined(AES_192) || defined(AES_VAR) +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined(AES_256) || defined(AES_VAR) +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined(AES_VAR) +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); + +#endif + +#if defined(AES_MODES) + +/* Multiple calls to the following subroutines for multiple block */ +/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ +/* long messages incremantally provided that the context AND the iv */ +/* are preserved between all such calls. For the ECB and CBC modes */ +/* each individual call within a series of incremental calls must */ +/* process only full blocks (i.e. len must be a multiple of 16) but */ +/* the CFB, OFB and CTR mode calls can handle multiple incremental */ +/* calls of any length. Each mode is reset when a new AES key is */ +/* set but ECB and CBC operations can be reset without setting a */ +/* new key by setting a new IV value. To reset CFB, OFB and CTR */ +/* without setting the key, aes_mode_reset() must be called and the */ +/* IV must be set. NOTE: All these calls update the IV on exit so */ +/* this has to be reset if a new operation with the same IV as the */ +/* previous one is required (or decryption follows encryption with */ +/* the same IV array). */ + +AES_RETURN aes_test_alignment_detection(unsigned int n); + +AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +#define aes_ofb_encrypt aes_ofb_crypt +#define aes_ofb_decrypt aes_ofb_crypt + +AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +typedef void cbuf_inc(unsigned char *cbuf); + +#define aes_ctr_encrypt aes_ctr_crypt +#define aes_ctr_decrypt aes_ctr_crypt + +AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/utils/crypto/aes_x64.asm b/src/utils/crypto/aes_x64.asm new file mode 100644 index 000000000..f86afcf4d --- /dev/null +++ b/src/utils/crypto/aes_x64.asm @@ -0,0 +1,904 @@ + +; --------------------------------------------------------------------------- +; Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. +; +; LICENSE TERMS +; +; The free distribution and use of this software is allowed (with or without +; changes) provided that: +; +; 1. source code distributions include the above copyright notice, this +; list of conditions and the following disclaimer; +; +; 2. binary distributions include the above copyright notice, this list +; of conditions and the following disclaimer in their documentation; +; +; 3. the name of the copyright holder is not used to endorse products +; built using this software without specific written permission. +; +; DISCLAIMER +; +; This software is provided 'as is' with no explicit or implied warranties +; in respect of its properties, including, but not limited to, correctness +; and/or fitness for purpose. +; --------------------------------------------------------------------------- +; Issue 20/12/2007 +; +; I am grateful to Dag Arne Osvik for many discussions of the techniques that +; can be used to optimise AES assembler code on AMD64/EM64T architectures. +; Some of the techniques used in this implementation are the result of +; suggestions made by him for which I am most grateful. + +; An AES implementation for AMD64 processors using the YASM assembler. This +; implemetation provides only encryption, decryption and hence requires key +; scheduling support in C. It uses 8k bytes of tables but its encryption and +; decryption performance is very close to that obtained using large tables. +; It can use either Windows or Gnu/Linux calling conventions, which are as +; follows: +; windows gnu/linux +; +; in_blk rcx rdi +; out_blk rdx rsi +; context (cx) r8 rdx +; +; preserved rsi - + rbx, rbp, rsp, r12, r13, r14 & r15 +; registers rdi - on both +; +; destroyed - rsi + rax, rcx, rdx, r8, r9, r10 & r11 +; registers - rdi on both +; +; The default convention is that for windows, the gnu/linux convention being +; used if __GNUC__ is defined. +; +; Define _SEH_ to include support for Win64 structured exception handling +; (this requires YASM version 0.6 or later). +; +; This code provides the standard AES block size (128 bits, 16 bytes) and the +; three standard AES key sizes (128, 192 and 256 bits). It has the same call +; interface as my C implementation. It uses the Microsoft C AMD64 calling +; conventions in which the three parameters are placed in rcx, rdx and r8 +; respectively. The rbx, rsi, rdi, rbp and r12..r15 registers are preserved. +; +; AES_RETURN aes_encrypt(const unsigned char in_blk[], +; unsigned char out_blk[], const aes_encrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt(const unsigned char in_blk[], +; unsigned char out_blk[], const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_encrypt_key(const unsigned char key[], +; const aes_encrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt_key(const unsigned char key[], +; const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_encrypt_key(const unsigned char key[], +; unsigned int len, const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt_key(const unsigned char key[], +; unsigned int len, const aes_decrypt_ctx cx[1]); +; +; where is 128, 102 or 256. In the last two calls the length can be in +; either bits or bytes. +; +; Comment in/out the following lines to obtain the desired subroutines. These +; selections MUST match those in the C header file aes.h + +; %define AES_128 ; define if AES with 128 bit keys is needed +; %define AES_192 ; define if AES with 192 bit keys is needed +%define AES_256 ; define if AES with 256 bit keys is needed +; %define AES_VAR ; define if a variable key size is needed +%define ENCRYPTION ; define if encryption is needed +%define DECRYPTION ; define if decryption is needed +%define AES_REV_DKS ; define if key decryption schedule is reversed +%define LAST_ROUND_TABLES ; define for the faster version using extra tables + +; The encryption key schedule has the following in memory layout where N is the +; number of rounds (10, 12 or 14): +; +; lo: | input key (round 0) | ; each round is four 32-bit words +; | encryption round 1 | +; | encryption round 2 | +; .... +; | encryption round N-1 | +; hi: | encryption round N | +; +; The decryption key schedule is normally set up so that it has the same +; layout as above by actually reversing the order of the encryption key +; schedule in memory (this happens when AES_REV_DKS is set): +; +; lo: | decryption round 0 | = | encryption round N | +; | decryption round 1 | = INV_MIX_COL[ | encryption round N-1 | ] +; | decryption round 2 | = INV_MIX_COL[ | encryption round N-2 | ] +; .... .... +; | decryption round N-1 | = INV_MIX_COL[ | encryption round 1 | ] +; hi: | decryption round N | = | input key (round 0) | +; +; with rounds except the first and last modified using inv_mix_column() +; But if AES_REV_DKS is NOT set the order of keys is left as it is for +; encryption so that it has to be accessed in reverse when used for +; decryption (although the inverse mix column modifications are done) +; +; lo: | decryption round 0 | = | input key (round 0) | +; | decryption round 1 | = INV_MIX_COL[ | encryption round 1 | ] +; | decryption round 2 | = INV_MIX_COL[ | encryption round 2 | ] +; .... .... +; | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ] +; hi: | decryption round N | = | encryption round N | +; +; This layout is faster when the assembler key scheduling provided here +; is used. +; +; The DLL interface must use the _stdcall convention in which the number +; of bytes of parameter space is added after an @ to the sutine's name. +; We must also remove our parameters from the stack before return (see +; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version. + +;%define DLL_EXPORT + +; End of user defines + +%ifdef AES_VAR +%ifndef AES_128 +%define AES_128 +%endif +%ifndef AES_192 +%define AES_192 +%endif +%ifndef AES_256 +%define AES_256 +%endif +%endif + +%ifdef AES_VAR +%define KS_LENGTH 60 +%elifdef AES_256 +%define KS_LENGTH 60 +%elifdef AES_192 +%define KS_LENGTH 52 +%else +%define KS_LENGTH 44 +%endif + +%define r0 rax +%define r1 rdx +%define r2 rcx +%define r3 rbx +%define r4 rsi +%define r5 rdi +%define r6 rbp +%define r7 rsp + +%define raxd eax +%define rdxd edx +%define rcxd ecx +%define rbxd ebx +%define rsid esi +%define rdid edi +%define rbpd ebp +%define rspd esp + +%define raxb al +%define rdxb dl +%define rcxb cl +%define rbxb bl +%define rsib sil +%define rdib dil +%define rbpb bpl +%define rspb spl + +%define r0h ah +%define r1h dh +%define r2h ch +%define r3h bh + +%define r0d eax +%define r1d edx +%define r2d ecx +%define r3d ebx + +; finite field multiplies by {02}, {04} and {08} + +%define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) +%define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) +%define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) + +; finite field multiplies required in table generation + +%define f3(x) (f2(x) ^ x) +%define f9(x) (f8(x) ^ x) +%define fb(x) (f8(x) ^ f2(x) ^ x) +%define fd(x) (f8(x) ^ f4(x) ^ x) +%define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +; macro for expanding S-box data + +%macro enc_vals 1 + db %1(0x63),%1(0x7c),%1(0x77),%1(0x7b),%1(0xf2),%1(0x6b),%1(0x6f),%1(0xc5) + db %1(0x30),%1(0x01),%1(0x67),%1(0x2b),%1(0xfe),%1(0xd7),%1(0xab),%1(0x76) + db %1(0xca),%1(0x82),%1(0xc9),%1(0x7d),%1(0xfa),%1(0x59),%1(0x47),%1(0xf0) + db %1(0xad),%1(0xd4),%1(0xa2),%1(0xaf),%1(0x9c),%1(0xa4),%1(0x72),%1(0xc0) + db %1(0xb7),%1(0xfd),%1(0x93),%1(0x26),%1(0x36),%1(0x3f),%1(0xf7),%1(0xcc) + db %1(0x34),%1(0xa5),%1(0xe5),%1(0xf1),%1(0x71),%1(0xd8),%1(0x31),%1(0x15) + db %1(0x04),%1(0xc7),%1(0x23),%1(0xc3),%1(0x18),%1(0x96),%1(0x05),%1(0x9a) + db %1(0x07),%1(0x12),%1(0x80),%1(0xe2),%1(0xeb),%1(0x27),%1(0xb2),%1(0x75) + db %1(0x09),%1(0x83),%1(0x2c),%1(0x1a),%1(0x1b),%1(0x6e),%1(0x5a),%1(0xa0) + db %1(0x52),%1(0x3b),%1(0xd6),%1(0xb3),%1(0x29),%1(0xe3),%1(0x2f),%1(0x84) + db %1(0x53),%1(0xd1),%1(0x00),%1(0xed),%1(0x20),%1(0xfc),%1(0xb1),%1(0x5b) + db %1(0x6a),%1(0xcb),%1(0xbe),%1(0x39),%1(0x4a),%1(0x4c),%1(0x58),%1(0xcf) + db %1(0xd0),%1(0xef),%1(0xaa),%1(0xfb),%1(0x43),%1(0x4d),%1(0x33),%1(0x85) + db %1(0x45),%1(0xf9),%1(0x02),%1(0x7f),%1(0x50),%1(0x3c),%1(0x9f),%1(0xa8) + db %1(0x51),%1(0xa3),%1(0x40),%1(0x8f),%1(0x92),%1(0x9d),%1(0x38),%1(0xf5) + db %1(0xbc),%1(0xb6),%1(0xda),%1(0x21),%1(0x10),%1(0xff),%1(0xf3),%1(0xd2) + db %1(0xcd),%1(0x0c),%1(0x13),%1(0xec),%1(0x5f),%1(0x97),%1(0x44),%1(0x17) + db %1(0xc4),%1(0xa7),%1(0x7e),%1(0x3d),%1(0x64),%1(0x5d),%1(0x19),%1(0x73) + db %1(0x60),%1(0x81),%1(0x4f),%1(0xdc),%1(0x22),%1(0x2a),%1(0x90),%1(0x88) + db %1(0x46),%1(0xee),%1(0xb8),%1(0x14),%1(0xde),%1(0x5e),%1(0x0b),%1(0xdb) + db %1(0xe0),%1(0x32),%1(0x3a),%1(0x0a),%1(0x49),%1(0x06),%1(0x24),%1(0x5c) + db %1(0xc2),%1(0xd3),%1(0xac),%1(0x62),%1(0x91),%1(0x95),%1(0xe4),%1(0x79) + db %1(0xe7),%1(0xc8),%1(0x37),%1(0x6d),%1(0x8d),%1(0xd5),%1(0x4e),%1(0xa9) + db %1(0x6c),%1(0x56),%1(0xf4),%1(0xea),%1(0x65),%1(0x7a),%1(0xae),%1(0x08) + db %1(0xba),%1(0x78),%1(0x25),%1(0x2e),%1(0x1c),%1(0xa6),%1(0xb4),%1(0xc6) + db %1(0xe8),%1(0xdd),%1(0x74),%1(0x1f),%1(0x4b),%1(0xbd),%1(0x8b),%1(0x8a) + db %1(0x70),%1(0x3e),%1(0xb5),%1(0x66),%1(0x48),%1(0x03),%1(0xf6),%1(0x0e) + db %1(0x61),%1(0x35),%1(0x57),%1(0xb9),%1(0x86),%1(0xc1),%1(0x1d),%1(0x9e) + db %1(0xe1),%1(0xf8),%1(0x98),%1(0x11),%1(0x69),%1(0xd9),%1(0x8e),%1(0x94) + db %1(0x9b),%1(0x1e),%1(0x87),%1(0xe9),%1(0xce),%1(0x55),%1(0x28),%1(0xdf) + db %1(0x8c),%1(0xa1),%1(0x89),%1(0x0d),%1(0xbf),%1(0xe6),%1(0x42),%1(0x68) + db %1(0x41),%1(0x99),%1(0x2d),%1(0x0f),%1(0xb0),%1(0x54),%1(0xbb),%1(0x16) +%endmacro + +%macro dec_vals 1 + db %1(0x52),%1(0x09),%1(0x6a),%1(0xd5),%1(0x30),%1(0x36),%1(0xa5),%1(0x38) + db %1(0xbf),%1(0x40),%1(0xa3),%1(0x9e),%1(0x81),%1(0xf3),%1(0xd7),%1(0xfb) + db %1(0x7c),%1(0xe3),%1(0x39),%1(0x82),%1(0x9b),%1(0x2f),%1(0xff),%1(0x87) + db %1(0x34),%1(0x8e),%1(0x43),%1(0x44),%1(0xc4),%1(0xde),%1(0xe9),%1(0xcb) + db %1(0x54),%1(0x7b),%1(0x94),%1(0x32),%1(0xa6),%1(0xc2),%1(0x23),%1(0x3d) + db %1(0xee),%1(0x4c),%1(0x95),%1(0x0b),%1(0x42),%1(0xfa),%1(0xc3),%1(0x4e) + db %1(0x08),%1(0x2e),%1(0xa1),%1(0x66),%1(0x28),%1(0xd9),%1(0x24),%1(0xb2) + db %1(0x76),%1(0x5b),%1(0xa2),%1(0x49),%1(0x6d),%1(0x8b),%1(0xd1),%1(0x25) + db %1(0x72),%1(0xf8),%1(0xf6),%1(0x64),%1(0x86),%1(0x68),%1(0x98),%1(0x16) + db %1(0xd4),%1(0xa4),%1(0x5c),%1(0xcc),%1(0x5d),%1(0x65),%1(0xb6),%1(0x92) + db %1(0x6c),%1(0x70),%1(0x48),%1(0x50),%1(0xfd),%1(0xed),%1(0xb9),%1(0xda) + db %1(0x5e),%1(0x15),%1(0x46),%1(0x57),%1(0xa7),%1(0x8d),%1(0x9d),%1(0x84) + db %1(0x90),%1(0xd8),%1(0xab),%1(0x00),%1(0x8c),%1(0xbc),%1(0xd3),%1(0x0a) + db %1(0xf7),%1(0xe4),%1(0x58),%1(0x05),%1(0xb8),%1(0xb3),%1(0x45),%1(0x06) + db %1(0xd0),%1(0x2c),%1(0x1e),%1(0x8f),%1(0xca),%1(0x3f),%1(0x0f),%1(0x02) + db %1(0xc1),%1(0xaf),%1(0xbd),%1(0x03),%1(0x01),%1(0x13),%1(0x8a),%1(0x6b) + db %1(0x3a),%1(0x91),%1(0x11),%1(0x41),%1(0x4f),%1(0x67),%1(0xdc),%1(0xea) + db %1(0x97),%1(0xf2),%1(0xcf),%1(0xce),%1(0xf0),%1(0xb4),%1(0xe6),%1(0x73) + db %1(0x96),%1(0xac),%1(0x74),%1(0x22),%1(0xe7),%1(0xad),%1(0x35),%1(0x85) + db %1(0xe2),%1(0xf9),%1(0x37),%1(0xe8),%1(0x1c),%1(0x75),%1(0xdf),%1(0x6e) + db %1(0x47),%1(0xf1),%1(0x1a),%1(0x71),%1(0x1d),%1(0x29),%1(0xc5),%1(0x89) + db %1(0x6f),%1(0xb7),%1(0x62),%1(0x0e),%1(0xaa),%1(0x18),%1(0xbe),%1(0x1b) + db %1(0xfc),%1(0x56),%1(0x3e),%1(0x4b),%1(0xc6),%1(0xd2),%1(0x79),%1(0x20) + db %1(0x9a),%1(0xdb),%1(0xc0),%1(0xfe),%1(0x78),%1(0xcd),%1(0x5a),%1(0xf4) + db %1(0x1f),%1(0xdd),%1(0xa8),%1(0x33),%1(0x88),%1(0x07),%1(0xc7),%1(0x31) + db %1(0xb1),%1(0x12),%1(0x10),%1(0x59),%1(0x27),%1(0x80),%1(0xec),%1(0x5f) + db %1(0x60),%1(0x51),%1(0x7f),%1(0xa9),%1(0x19),%1(0xb5),%1(0x4a),%1(0x0d) + db %1(0x2d),%1(0xe5),%1(0x7a),%1(0x9f),%1(0x93),%1(0xc9),%1(0x9c),%1(0xef) + db %1(0xa0),%1(0xe0),%1(0x3b),%1(0x4d),%1(0xae),%1(0x2a),%1(0xf5),%1(0xb0) + db %1(0xc8),%1(0xeb),%1(0xbb),%1(0x3c),%1(0x83),%1(0x53),%1(0x99),%1(0x61) + db %1(0x17),%1(0x2b),%1(0x04),%1(0x7e),%1(0xba),%1(0x77),%1(0xd6),%1(0x26) + db %1(0xe1),%1(0x69),%1(0x14),%1(0x63),%1(0x55),%1(0x21),%1(0x0c),%1(0x7d) +%endmacro + +%define u8(x) f2(x), x, x, f3(x), f2(x), x, x, f3(x) +%define v8(x) fe(x), f9(x), fd(x), fb(x), fe(x), f9(x), fd(x), x +%define w8(x) x, 0, 0, 0, x, 0, 0, 0 + +%define tptr rbp ; table pointer +%define kptr r8 ; key schedule pointer +%define fofs 128 ; adjust offset in key schedule to keep |disp| < 128 +%define fk_ref(x,y) [kptr-16*x+fofs+4*y] +%ifdef AES_REV_DKS +%define rofs 128 +%define ik_ref(x,y) [kptr-16*x+rofs+4*y] +%else +%define rofs -128 +%define ik_ref(x,y) [kptr+16*x+rofs+4*y] +%endif + +%define tab_0(x) [tptr+8*x] +%define tab_1(x) [tptr+8*x+3] +%define tab_2(x) [tptr+8*x+2] +%define tab_3(x) [tptr+8*x+1] +%define tab_f(x) byte [tptr+8*x+1] +%define tab_i(x) byte [tptr+8*x+7] +%define t_ref(x,r) tab_ %+ x(r) + +%macro ff_rnd 5 ; normal forward round + mov %1d, fk_ref(%5,0) + mov %2d, fk_ref(%5,1) + mov %3d, fk_ref(%5,2) + mov %4d, fk_ref(%5,3) + + movzx esi, al + movzx edi, ah + shr eax, 16 + xor %1d, t_ref(0,rsi) + xor %4d, t_ref(1,rdi) + movzx esi, al + movzx edi, ah + xor %3d, t_ref(2,rsi) + xor %2d, t_ref(3,rdi) + + movzx esi, bl + movzx edi, bh + shr ebx, 16 + xor %2d, t_ref(0,rsi) + xor %1d, t_ref(1,rdi) + movzx esi, bl + movzx edi, bh + xor %4d, t_ref(2,rsi) + xor %3d, t_ref(3,rdi) + + movzx esi, cl + movzx edi, ch + shr ecx, 16 + xor %3d, t_ref(0,rsi) + xor %2d, t_ref(1,rdi) + movzx esi, cl + movzx edi, ch + xor %1d, t_ref(2,rsi) + xor %4d, t_ref(3,rdi) + + movzx esi, dl + movzx edi, dh + shr edx, 16 + xor %4d, t_ref(0,rsi) + xor %3d, t_ref(1,rdi) + movzx esi, dl + movzx edi, dh + xor %2d, t_ref(2,rsi) + xor %1d, t_ref(3,rdi) + + mov eax,%1d + mov ebx,%2d + mov ecx,%3d + mov edx,%4d +%endmacro + +%ifdef LAST_ROUND_TABLES + +%macro fl_rnd 5 ; last forward round + add tptr, 2048 + mov %1d, fk_ref(%5,0) + mov %2d, fk_ref(%5,1) + mov %3d, fk_ref(%5,2) + mov %4d, fk_ref(%5,3) + + movzx esi, al + movzx edi, ah + shr eax, 16 + xor %1d, t_ref(0,rsi) + xor %4d, t_ref(1,rdi) + movzx esi, al + movzx edi, ah + xor %3d, t_ref(2,rsi) + xor %2d, t_ref(3,rdi) + + movzx esi, bl + movzx edi, bh + shr ebx, 16 + xor %2d, t_ref(0,rsi) + xor %1d, t_ref(1,rdi) + movzx esi, bl + movzx edi, bh + xor %4d, t_ref(2,rsi) + xor %3d, t_ref(3,rdi) + + movzx esi, cl + movzx edi, ch + shr ecx, 16 + xor %3d, t_ref(0,rsi) + xor %2d, t_ref(1,rdi) + movzx esi, cl + movzx edi, ch + xor %1d, t_ref(2,rsi) + xor %4d, t_ref(3,rdi) + + movzx esi, dl + movzx edi, dh + shr edx, 16 + xor %4d, t_ref(0,rsi) + xor %3d, t_ref(1,rdi) + movzx esi, dl + movzx edi, dh + xor %2d, t_ref(2,rsi) + xor %1d, t_ref(3,rdi) +%endmacro + +%else + +%macro fl_rnd 5 ; last forward round + mov %1d, fk_ref(%5,0) + mov %2d, fk_ref(%5,1) + mov %3d, fk_ref(%5,2) + mov %4d, fk_ref(%5,3) + + movzx esi, al + movzx edi, ah + shr eax, 16 + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + xor %1d, esi + rol edi, 8 + xor %4d, edi + movzx esi, al + movzx edi, ah + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + rol esi, 16 + rol edi, 24 + xor %3d, esi + xor %2d, edi + + movzx esi, bl + movzx edi, bh + shr ebx, 16 + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + xor %2d, esi + rol edi, 8 + xor %1d, edi + movzx esi, bl + movzx edi, bh + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + rol esi, 16 + rol edi, 24 + xor %4d, esi + xor %3d, edi + + movzx esi, cl + movzx edi, ch + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + shr ecx, 16 + xor %3d, esi + rol edi, 8 + xor %2d, edi + movzx esi, cl + movzx edi, ch + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + rol esi, 16 + rol edi, 24 + xor %1d, esi + xor %4d, edi + + movzx esi, dl + movzx edi, dh + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + shr edx, 16 + xor %4d, esi + rol edi, 8 + xor %3d, edi + movzx esi, dl + movzx edi, dh + movzx esi, t_ref(f,rsi) + movzx edi, t_ref(f,rdi) + rol esi, 16 + rol edi, 24 + xor %2d, esi + xor %1d, edi +%endmacro + +%endif + +%macro ii_rnd 5 ; normal inverse round + mov %1d, ik_ref(%5,0) + mov %2d, ik_ref(%5,1) + mov %3d, ik_ref(%5,2) + mov %4d, ik_ref(%5,3) + + movzx esi, al + movzx edi, ah + shr eax, 16 + xor %1d, t_ref(0,rsi) + xor %2d, t_ref(1,rdi) + movzx esi, al + movzx edi, ah + xor %3d, t_ref(2,rsi) + xor %4d, t_ref(3,rdi) + + movzx esi, bl + movzx edi, bh + shr ebx, 16 + xor %2d, t_ref(0,rsi) + xor %3d, t_ref(1,rdi) + movzx esi, bl + movzx edi, bh + xor %4d, t_ref(2,rsi) + xor %1d, t_ref(3,rdi) + + movzx esi, cl + movzx edi, ch + shr ecx, 16 + xor %3d, t_ref(0,rsi) + xor %4d, t_ref(1,rdi) + movzx esi, cl + movzx edi, ch + xor %1d, t_ref(2,rsi) + xor %2d, t_ref(3,rdi) + + movzx esi, dl + movzx edi, dh + shr edx, 16 + xor %4d, t_ref(0,rsi) + xor %1d, t_ref(1,rdi) + movzx esi, dl + movzx edi, dh + xor %2d, t_ref(2,rsi) + xor %3d, t_ref(3,rdi) + + mov eax,%1d + mov ebx,%2d + mov ecx,%3d + mov edx,%4d +%endmacro + +%ifdef LAST_ROUND_TABLES + +%macro il_rnd 5 ; last inverse round + add tptr, 2048 + mov %1d, ik_ref(%5,0) + mov %2d, ik_ref(%5,1) + mov %3d, ik_ref(%5,2) + mov %4d, ik_ref(%5,3) + + movzx esi, al + movzx edi, ah + shr eax, 16 + xor %1d, t_ref(0,rsi) + xor %2d, t_ref(1,rdi) + movzx esi, al + movzx edi, ah + xor %3d, t_ref(2,rsi) + xor %4d, t_ref(3,rdi) + + movzx esi, bl + movzx edi, bh + shr ebx, 16 + xor %2d, t_ref(0,rsi) + xor %3d, t_ref(1,rdi) + movzx esi, bl + movzx edi, bh + xor %4d, t_ref(2,rsi) + xor %1d, t_ref(3,rdi) + + movzx esi, cl + movzx edi, ch + shr ecx, 16 + xor %3d, t_ref(0,rsi) + xor %4d, t_ref(1,rdi) + movzx esi, cl + movzx edi, ch + xor %1d, t_ref(2,rsi) + xor %2d, t_ref(3,rdi) + + movzx esi, dl + movzx edi, dh + shr edx, 16 + xor %4d, t_ref(0,rsi) + xor %1d, t_ref(1,rdi) + movzx esi, dl + movzx edi, dh + xor %2d, t_ref(2,rsi) + xor %3d, t_ref(3,rdi) +%endmacro + +%else + +%macro il_rnd 5 ; last inverse round + mov %1d, ik_ref(%5,0) + mov %2d, ik_ref(%5,1) + mov %3d, ik_ref(%5,2) + mov %4d, ik_ref(%5,3) + + movzx esi, al + movzx edi, ah + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + shr eax, 16 + xor %1d, esi + rol edi, 8 + xor %2d, edi + movzx esi, al + movzx edi, ah + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + rol esi, 16 + rol edi, 24 + xor %3d, esi + xor %4d, edi + + movzx esi, bl + movzx edi, bh + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + shr ebx, 16 + xor %2d, esi + rol edi, 8 + xor %3d, edi + movzx esi, bl + movzx edi, bh + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + rol esi, 16 + rol edi, 24 + xor %4d, esi + xor %1d, edi + + movzx esi, cl + movzx edi, ch + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + shr ecx, 16 + xor %3d, esi + rol edi, 8 + xor %4d, edi + movzx esi, cl + movzx edi, ch + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + rol esi, 16 + rol edi, 24 + xor %1d, esi + xor %2d, edi + + movzx esi, dl + movzx edi, dh + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + shr edx, 16 + xor %4d, esi + rol edi, 8 + xor %1d, edi + movzx esi, dl + movzx edi, dh + movzx esi, t_ref(i,rsi) + movzx edi, t_ref(i,rdi) + rol esi, 16 + rol edi, 24 + xor %2d, esi + xor %3d, edi +%endmacro + +%endif + +%ifdef ENCRYPTION + + global aes_encrypt +%ifdef DLL_EXPORT + export aes_encrypt +%endif + + section .data align=64 + align 64 +enc_tab: + enc_vals u8 +%ifdef LAST_ROUND_TABLES + enc_vals w8 +%endif + + section .text align=16 + align 16 + +%ifdef _SEH_ +proc_frame aes_encrypt + alloc_stack 7*8 ; 7 to align stack to 16 bytes + save_reg rsi,4*8 + save_reg rdi,5*8 + save_reg rbx,1*8 + save_reg rbp,2*8 + save_reg r12,3*8 +end_prologue + mov rdi, rcx ; input pointer + mov [rsp+0*8], rdx ; output pointer +%else + aes_encrypt: + %ifdef __GNUC__ + sub rsp, 4*8 ; gnu/linux binary interface + mov [rsp+0*8], rsi ; output pointer + mov r8, rdx ; context + %else + sub rsp, 6*8 ; windows binary interface + mov [rsp+4*8], rsi + mov [rsp+5*8], rdi + mov rdi, rcx ; input pointer + mov [rsp+0*8], rdx ; output pointer + %endif + mov [rsp+1*8], rbx ; input pointer in rdi + mov [rsp+2*8], rbp ; output pointer in [rsp] + mov [rsp+3*8], r12 ; context in r8 +%endif + + movzx esi, byte [kptr+4*KS_LENGTH] + lea tptr,[enc_tab wrt rip] + sub kptr, fofs + + mov eax, [rdi+0*4] + mov ebx, [rdi+1*4] + mov ecx, [rdi+2*4] + mov edx, [rdi+3*4] + + xor eax, [kptr+fofs] + xor ebx, [kptr+fofs+4] + xor ecx, [kptr+fofs+8] + xor edx, [kptr+fofs+12] + + lea kptr,[kptr+rsi] + cmp esi, 10*16 + je .3 + cmp esi, 12*16 + je .2 + cmp esi, 14*16 + je .1 + mov rax, -1 + jmp .4 + +.1: ff_rnd r9, r10, r11, r12, 13 + ff_rnd r9, r10, r11, r12, 12 +.2: ff_rnd r9, r10, r11, r12, 11 + ff_rnd r9, r10, r11, r12, 10 +.3: ff_rnd r9, r10, r11, r12, 9 + ff_rnd r9, r10, r11, r12, 8 + ff_rnd r9, r10, r11, r12, 7 + ff_rnd r9, r10, r11, r12, 6 + ff_rnd r9, r10, r11, r12, 5 + ff_rnd r9, r10, r11, r12, 4 + ff_rnd r9, r10, r11, r12, 3 + ff_rnd r9, r10, r11, r12, 2 + ff_rnd r9, r10, r11, r12, 1 + fl_rnd r9, r10, r11, r12, 0 + + mov rbx, [rsp] + mov [rbx], r9d + mov [rbx+4], r10d + mov [rbx+8], r11d + mov [rbx+12], r12d + xor rax, rax +.4: + mov rbx, [rsp+1*8] + mov rbp, [rsp+2*8] + mov r12, [rsp+3*8] +%ifdef __GNUC__ + add rsp, 4*8 + ret +%else + mov rsi, [rsp+4*8] + mov rdi, [rsp+5*8] + %ifdef _SEH_ + add rsp, 7*8 + ret + endproc_frame + %else + add rsp, 6*8 + ret + %endif +%endif + +%endif + +%ifdef DECRYPTION + + global aes_decrypt +%ifdef DLL_EXPORT + export aes_decrypt +%endif + + section .data + align 64 +dec_tab: + dec_vals v8 +%ifdef LAST_ROUND_TABLES + dec_vals w8 +%endif + + section .text + align 16 + +%ifdef _SEH_ +proc_frame aes_decrypt + alloc_stack 7*8 ; 7 to align stack to 16 bytes + save_reg rsi,4*8 + save_reg rdi,5*8 + save_reg rbx,1*8 + save_reg rbp,2*8 + save_reg r12,3*8 +end_prologue + mov rdi, rcx ; input pointer + mov [rsp+0*8], rdx ; output pointer +%else + aes_decrypt: + %ifdef __GNUC__ + sub rsp, 4*8 ; gnu/linux binary interface + mov [rsp+0*8], rsi ; output pointer + mov r8, rdx ; context + %else + sub rsp, 6*8 ; windows binary interface + mov [rsp+4*8], rsi + mov [rsp+5*8], rdi + mov rdi, rcx ; input pointer + mov [rsp+0*8], rdx ; output pointer + %endif + mov [rsp+1*8], rbx ; input pointer in rdi + mov [rsp+2*8], rbp ; output pointer in [rsp] + mov [rsp+3*8], r12 ; context in r8 +%endif + + movzx esi,byte[kptr+4*KS_LENGTH] + lea tptr,[dec_tab wrt rip] + sub kptr, rofs + + mov eax, [rdi+0*4] + mov ebx, [rdi+1*4] + mov ecx, [rdi+2*4] + mov edx, [rdi+3*4] + +%ifdef AES_REV_DKS + mov rdi, kptr + lea kptr,[kptr+rsi] +%else + lea rdi,[kptr+rsi] +%endif + + xor eax, [rdi+rofs] + xor ebx, [rdi+rofs+4] + xor ecx, [rdi+rofs+8] + xor edx, [rdi+rofs+12] + + cmp esi, 10*16 + je .3 + cmp esi, 12*16 + je .2 + cmp esi, 14*16 + je .1 + mov rax, -1 + jmp .4 + +.1: ii_rnd r9, r10, r11, r12, 13 + ii_rnd r9, r10, r11, r12, 12 +.2: ii_rnd r9, r10, r11, r12, 11 + ii_rnd r9, r10, r11, r12, 10 +.3: ii_rnd r9, r10, r11, r12, 9 + ii_rnd r9, r10, r11, r12, 8 + ii_rnd r9, r10, r11, r12, 7 + ii_rnd r9, r10, r11, r12, 6 + ii_rnd r9, r10, r11, r12, 5 + ii_rnd r9, r10, r11, r12, 4 + ii_rnd r9, r10, r11, r12, 3 + ii_rnd r9, r10, r11, r12, 2 + ii_rnd r9, r10, r11, r12, 1 + il_rnd r9, r10, r11, r12, 0 + + mov rbx, [rsp] + mov [rbx], r9d + mov [rbx+4], r10d + mov [rbx+8], r11d + mov [rbx+12], r12d + xor rax, rax +.4: mov rbx, [rsp+1*8] + mov rbp, [rsp+2*8] + mov r12, [rsp+3*8] +%ifdef __GNUC__ + add rsp, 4*8 + ret +%else + mov rsi, [rsp+4*8] + mov rdi, [rsp+5*8] + %ifdef _SEH_ + add rsp, 7*8 + ret + endproc_frame + %else + add rsp, 6*8 + ret + %endif +%endif + +%endif + + end diff --git a/src/utils/crypto/aes_x86.asm b/src/utils/crypto/aes_x86.asm new file mode 100644 index 000000000..7fc9093ec --- /dev/null +++ b/src/utils/crypto/aes_x86.asm @@ -0,0 +1,644 @@ + +; --------------------------------------------------------------------------- +; Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. +; +; LICENSE TERMS +; +; The free distribution and use of this software is allowed (with or without +; changes) provided that: +; +; 1. source code distributions include the above copyright notice, this +; list of conditions and the following disclaimer; +; +; 2. binary distributions include the above copyright notice, this list +; of conditions and the following disclaimer in their documentation; +; +; 3. the name of the copyright holder is not used to endorse products +; built using this software without specific written permission. +; +; DISCLAIMER +; +; This software is provided 'as is' with no explicit or implied warranties +; in respect of its properties, including, but not limited to, correctness +; and/or fitness for purpose. +; --------------------------------------------------------------------------- +; Issue 20/12/2007 +; +; This code requires ASM_X86_V1C to be set in aesopt.h. It requires the C files +; aeskey.c and aestab.c for support. + +; An AES implementation for x86 processors using the YASM (or NASM) assembler. +; This is an assembler implementation that covers encryption and decryption +; only and is intended as a replacement of the C file aescrypt.c. It hence +; requires the file aeskey.c for keying and aestab.c for the AES tables. It +; employs full tables rather than compressed tables. + +; This code provides the standard AES block size (128 bits, 16 bytes) and the +; three standard AES key sizes (128, 192 and 256 bits). It has the same call +; interface as my C implementation. The ebx, esi, edi and ebp registers are +; preserved across calls but eax, ecx and edx and the artihmetic status flags +; are not. It is also important that the defines below match those used in the +; C code. This code uses the VC++ register saving conentions; if it is used +; with another compiler, conventions for using and saving registers may need to +; be checked (and calling conventions). The YASM command line for the VC++ +; custom build step is: +; +; yasm -Xvc -f win32 -o "$(TargetDir)\$(InputName).obj" "$(InputPath)" +; +; The calling intefaces are: +; +; AES_RETURN aes_encrypt(const unsigned char in_blk[], +; unsigned char out_blk[], const aes_encrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt(const unsigned char in_blk[], +; unsigned char out_blk[], const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_encrypt_key(const unsigned char key[], +; const aes_encrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt_key(const unsigned char key[], +; const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_encrypt_key(const unsigned char key[], +; unsigned int len, const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt_key(const unsigned char key[], +; unsigned int len, const aes_decrypt_ctx cx[1]); +; +; where is 128, 102 or 256. In the last two calls the length can be in +; either bits or bytes. +; +; Comment in/out the following lines to obtain the desired subroutines. These +; selections MUST match those in the C header file aes.h + +; %define AES_128 ; define if AES with 128 bit keys is needed +; %define AES_192 ; define if AES with 192 bit keys is needed +%define AES_256 ; define if AES with 256 bit keys is needed +; %define AES_VAR ; define if a variable key size is needed +%define ENCRYPTION ; define if encryption is needed +%define DECRYPTION ; define if decryption is needed +%define AES_REV_DKS ; define if key decryption schedule is reversed +%define LAST_ROUND_TABLES ; define if tables are to be used for last round + +; offsets to parameters + +in_blk equ 4 ; input byte array address parameter +out_blk equ 8 ; output byte array address parameter +ctx equ 12 ; AES context structure +stk_spc equ 20 ; stack space +%define parms 12 ; parameter space on stack + +; The encryption key schedule has the following in memory layout where N is the +; number of rounds (10, 12 or 14): +; +; lo: | input key (round 0) | ; each round is four 32-bit words +; | encryption round 1 | +; | encryption round 2 | +; .... +; | encryption round N-1 | +; hi: | encryption round N | +; +; The decryption key schedule is normally set up so that it has the same +; layout as above by actually reversing the order of the encryption key +; schedule in memory (this happens when AES_REV_DKS is set): +; +; lo: | decryption round 0 | = | encryption round N | +; | decryption round 1 | = INV_MIX_COL[ | encryption round N-1 | ] +; | decryption round 2 | = INV_MIX_COL[ | encryption round N-2 | ] +; .... .... +; | decryption round N-1 | = INV_MIX_COL[ | encryption round 1 | ] +; hi: | decryption round N | = | input key (round 0) | +; +; with rounds except the first and last modified using inv_mix_column() +; But if AES_REV_DKS is NOT set the order of keys is left as it is for +; encryption so that it has to be accessed in reverse when used for +; decryption (although the inverse mix column modifications are done) +; +; lo: | decryption round 0 | = | input key (round 0) | +; | decryption round 1 | = INV_MIX_COL[ | encryption round 1 | ] +; | decryption round 2 | = INV_MIX_COL[ | encryption round 2 | ] +; .... .... +; | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ] +; hi: | decryption round N | = | encryption round N | +; +; This layout is faster when the assembler key scheduling provided here +; is used. +; +; The DLL interface must use the _stdcall convention in which the number +; of bytes of parameter space is added after an @ to the sutine's name. +; We must also remove our parameters from the stack before return (see +; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version. + +;%define DLL_EXPORT + +; End of user defines + +%ifdef AES_VAR +%ifndef AES_128 +%define AES_128 +%endif +%ifndef AES_192 +%define AES_192 +%endif +%ifndef AES_256 +%define AES_256 +%endif +%endif + +%ifdef AES_VAR +%define KS_LENGTH 60 +%elifdef AES_256 +%define KS_LENGTH 60 +%elifdef AES_192 +%define KS_LENGTH 52 +%else +%define KS_LENGTH 44 +%endif + +; These macros implement stack based local variables + +%macro save 2 + mov [esp+4*%1],%2 +%endmacro + +%macro restore 2 + mov %1,[esp+4*%2] +%endmacro + +; the DLL has to implement the _stdcall calling interface on return +; In this case we have to take our parameters (3 4-byte pointers) +; off the stack + +%macro do_name 1-2 parms +%ifndef DLL_EXPORT + align 32 + global %1 +%1: +%else + align 32 + global %1@%2 + export %1@%2 +%1@%2: +%endif +%endmacro + +%macro do_call 1-2 parms +%ifndef DLL_EXPORT + call %1 + add esp,%2 +%else + call %1@%2 +%endif +%endmacro + +%macro do_exit 0-1 parms +%ifdef DLL_EXPORT + ret %1 +%else + ret +%endif +%endmacro + +%ifdef ENCRYPTION + + extern _t_fn + +%define etab_0(x) [_t_fn+4*x] +%define etab_1(x) [_t_fn+1024+4*x] +%define etab_2(x) [_t_fn+2048+4*x] +%define etab_3(x) [_t_fn+3072+4*x] + +%ifdef LAST_ROUND_TABLES + + extern _t_fl + +%define eltab_0(x) [_t_fl+4*x] +%define eltab_1(x) [_t_fl+1024+4*x] +%define eltab_2(x) [_t_fl+2048+4*x] +%define eltab_3(x) [_t_fl+3072+4*x] + +%else + +%define etab_b(x) byte [_t_fn+3072+4*x] + +%endif + +; ROUND FUNCTION. Build column[2] on ESI and column[3] on EDI that have the +; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX. +; +; Input: +; +; EAX column[0] +; EBX column[1] +; ECX column[2] +; EDX column[3] +; ESI column key[round][2] +; EDI column key[round][3] +; EBP scratch +; +; Output: +; +; EBP column[0] unkeyed +; EBX column[1] unkeyed +; ESI column[2] keyed +; EDI column[3] keyed +; EAX scratch +; ECX scratch +; EDX scratch + +%macro rnd_fun 2 + + rol ebx,16 + %1 esi, cl, 0, ebp + %1 esi, dh, 1, ebp + %1 esi, bh, 3, ebp + %1 edi, dl, 0, ebp + %1 edi, ah, 1, ebp + %1 edi, bl, 2, ebp + %2 ebp, al, 0, ebp + shr ebx,16 + and eax,0xffff0000 + or eax,ebx + shr edx,16 + %1 ebp, ah, 1, ebx + %1 ebp, dh, 3, ebx + %2 ebx, dl, 2, ebx + %1 ebx, ch, 1, edx + %1 ebx, al, 0, edx + shr eax,16 + shr ecx,16 + %1 ebp, cl, 2, edx + %1 edi, ch, 3, edx + %1 esi, al, 2, edx + %1 ebx, ah, 3, edx + +%endmacro + +; Basic MOV and XOR Operations for normal rounds + +%macro nr_xor 4 + movzx %4,%2 + xor %1,etab_%3(%4) +%endmacro + +%macro nr_mov 4 + movzx %4,%2 + mov %1,etab_%3(%4) +%endmacro + +; Basic MOV and XOR Operations for last round + +%ifdef LAST_ROUND_TABLES + + %macro lr_xor 4 + movzx %4,%2 + xor %1,eltab_%3(%4) + %endmacro + + %macro lr_mov 4 + movzx %4,%2 + mov %1,eltab_%3(%4) + %endmacro + +%else + + %macro lr_xor 4 + movzx %4,%2 + movzx %4,etab_b(%4) + %if %3 != 0 + shl %4,8*%3 + %endif + xor %1,%4 + %endmacro + + %macro lr_mov 4 + movzx %4,%2 + movzx %1,etab_b(%4) + %if %3 != 0 + shl %1,8*%3 + %endif + %endmacro + +%endif + +%macro enc_round 0 + + add ebp,16 + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + rnd_fun nr_xor, nr_mov + + mov eax,ebp + mov ecx,esi + mov edx,edi + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + +%macro enc_last_round 0 + + add ebp,16 + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + rnd_fun lr_xor, lr_mov + + mov eax,ebp + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + + section .text align=32 + +; AES Encryption Subroutine + + do_name _aes_encrypt + + sub esp,stk_spc + mov [esp+16],ebp + mov [esp+12],ebx + mov [esp+ 8],esi + mov [esp+ 4],edi + + mov esi,[esp+in_blk+stk_spc] ; input pointer + mov eax,[esi ] + mov ebx,[esi+ 4] + mov ecx,[esi+ 8] + mov edx,[esi+12] + + mov ebp,[esp+ctx+stk_spc] ; key pointer + movzx edi,byte [ebp+4*KS_LENGTH] + xor eax,[ebp ] + xor ebx,[ebp+ 4] + xor ecx,[ebp+ 8] + xor edx,[ebp+12] + +; determine the number of rounds + + cmp edi,10*16 + je .3 + cmp edi,12*16 + je .2 + cmp edi,14*16 + je .1 + mov eax,-1 + jmp .5 + +.1: enc_round + enc_round +.2: enc_round + enc_round +.3: enc_round + enc_round + enc_round + enc_round + enc_round + enc_round + enc_round + enc_round + enc_round + enc_last_round + + mov edx,[esp+out_blk+stk_spc] + mov [edx],eax + mov [edx+4],ebx + mov [edx+8],esi + mov [edx+12],edi + xor eax,eax + +.5: mov ebp,[esp+16] + mov ebx,[esp+12] + mov esi,[esp+ 8] + mov edi,[esp+ 4] + add esp,stk_spc + do_exit + +%endif + +%ifdef DECRYPTION + + extern _t_in + +%define dtab_0(x) [_t_in+4*x] +%define dtab_1(x) [_t_in+1024+4*x] +%define dtab_2(x) [_t_in+2048+4*x] +%define dtab_3(x) [_t_in+3072+4*x] + +%ifdef LAST_ROUND_TABLES + + extern _t_il + +%define dltab_0(x) [_t_il+4*x] +%define dltab_1(x) [_t_il+1024+4*x] +%define dltab_2(x) [_t_il+2048+4*x] +%define dltab_3(x) [_t_il+3072+4*x] + +%else + + extern _t_ibox + +%define dtab_x(x) byte [_t_ibox+x] + +%endif + +%macro irn_fun 2 + + rol eax,16 + %1 esi, cl, 0, ebp + %1 esi, bh, 1, ebp + %1 esi, al, 2, ebp + %1 edi, dl, 0, ebp + %1 edi, ch, 1, ebp + %1 edi, ah, 3, ebp + %2 ebp, bl, 0, ebp + shr eax,16 + and ebx,0xffff0000 + or ebx,eax + shr ecx,16 + %1 ebp, bh, 1, eax + %1 ebp, ch, 3, eax + %2 eax, cl, 2, ecx + %1 eax, bl, 0, ecx + %1 eax, dh, 1, ecx + shr ebx,16 + shr edx,16 + %1 esi, dh, 3, ecx + %1 ebp, dl, 2, ecx + %1 eax, bh, 3, ecx + %1 edi, bl, 2, ecx + +%endmacro + +; Basic MOV and XOR Operations for normal rounds + +%macro ni_xor 4 + movzx %4,%2 + xor %1,dtab_%3(%4) +%endmacro + +%macro ni_mov 4 + movzx %4,%2 + mov %1,dtab_%3(%4) +%endmacro + +; Basic MOV and XOR Operations for last round + +%ifdef LAST_ROUND_TABLES + +%macro li_xor 4 + movzx %4,%2 + xor %1,dltab_%3(%4) +%endmacro + +%macro li_mov 4 + movzx %4,%2 + mov %1,dltab_%3(%4) +%endmacro + +%else + + %macro li_xor 4 + movzx %4,%2 + movzx %4,dtab_x(%4) + %if %3 != 0 + shl %4,8*%3 + %endif + xor %1,%4 + %endmacro + + %macro li_mov 4 + movzx %4,%2 + movzx %1,dtab_x(%4) + %if %3 != 0 + shl %1,8*%3 + %endif + %endmacro + +%endif + +%macro dec_round 0 + +%ifdef AES_REV_DKS + add ebp,16 +%else + sub ebp,16 +%endif + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + irn_fun ni_xor, ni_mov + + mov ebx,ebp + mov ecx,esi + mov edx,edi + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + +%macro dec_last_round 0 + +%ifdef AES_REV_DKS + add ebp,16 +%else + sub ebp,16 +%endif + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + irn_fun li_xor, li_mov + + mov ebx,ebp + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + + section .text + +; AES Decryption Subroutine + + do_name _aes_decrypt + + sub esp,stk_spc + mov [esp+16],ebp + mov [esp+12],ebx + mov [esp+ 8],esi + mov [esp+ 4],edi + +; input four columns and xor in first round key + + mov esi,[esp+in_blk+stk_spc] ; input pointer + mov eax,[esi ] + mov ebx,[esi+ 4] + mov ecx,[esi+ 8] + mov edx,[esi+12] + lea esi,[esi+16] + + mov ebp,[esp+ctx+stk_spc] ; key pointer + movzx edi,byte[ebp+4*KS_LENGTH] +%ifndef AES_REV_DKS ; if decryption key schedule is not reversed + lea ebp,[ebp+edi] ; we have to access it from the top down +%endif + xor eax,[ebp ] ; key schedule + xor ebx,[ebp+ 4] + xor ecx,[ebp+ 8] + xor edx,[ebp+12] + +; determine the number of rounds + + cmp edi,10*16 + je .3 + cmp edi,12*16 + je .2 + cmp edi,14*16 + je .1 + mov eax,-1 + jmp .5 + +.1: dec_round + dec_round +.2: dec_round + dec_round +.3: dec_round + dec_round + dec_round + dec_round + dec_round + dec_round + dec_round + dec_round + dec_round + dec_last_round + +; move final values to the output array. + + mov ebp,[esp+out_blk+stk_spc] + mov [ebp],eax + mov [ebp+4],ebx + mov [ebp+8],esi + mov [ebp+12],edi + xor eax,eax + +.5: mov ebp,[esp+16] + mov ebx,[esp+12] + mov esi,[esp+ 8] + mov edi,[esp+ 4] + add esp,stk_spc + do_exit + +%endif + + end + diff --git a/src/utils/crypto/aescrypt.c b/src/utils/crypto/aescrypt.c new file mode 100644 index 000000000..7724431dd --- /dev/null +++ b/src/utils/crypto/aescrypt.c @@ -0,0 +1,311 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 +*/ + +#include "aesopt.h" +#include "aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) +#define so(y,x,c) word_out(y, c, s(x,c)) + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 +#endif + +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimiation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) +#pragma optimize( "s", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define fwd_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) +#elif defined(FT1_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) +#else +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) +#else +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) +{ uint_32t locals(b0, b1); + const uint_32t *kp; +#if defined( dec_fmvars ) + dec_fmvars; /* declare variables for fwd_mcol() if needed */ +#endif + +#if defined( AES_ERR_CHK ) + if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) + return EXIT_FAILURE; +#endif + + kp = cx->ks; + state_in(b0, in, kp); + +#if (ENC_UNROLL == FULL) + + switch(cx->inf.b[0]) + { + case 14 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 12 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 10 * 16: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + round(fwd_rnd, b1, b0, kp + 3 * N_COLS); + round(fwd_rnd, b0, b1, kp + 4 * N_COLS); + round(fwd_rnd, b1, b0, kp + 5 * N_COLS); + round(fwd_rnd, b0, b1, kp + 6 * N_COLS); + round(fwd_rnd, b1, b0, kp + 7 * N_COLS); + round(fwd_rnd, b0, b1, kp + 8 * N_COLS); + round(fwd_rnd, b1, b0, kp + 9 * N_COLS); + round(fwd_lrnd, b0, b1, kp +10 * N_COLS); + } + +#else + +#if (ENC_UNROLL == PARTIAL) + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + kp += N_COLS; + round(fwd_rnd, b0, b1, kp); + } + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); +#else + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp += N_COLS; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimiation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) +#pragma optimize( "t", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define inv_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) + +#if defined(IT4_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) +#elif defined(IT1_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) +#else +#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) +#else +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) +#endif + +/* This code can work with the decryption key schedule in the */ +/* order that is used for encrytpion (where the 1st decryption */ +/* round key is at the high end ot the schedule) or with a key */ +/* schedule that has been reversed to put the 1st decryption */ +/* round key at the low end of the schedule in memory (when */ +/* AES_REV_DKS is defined) */ + +#ifdef AES_REV_DKS +#define key_ofs 0 +#define rnd_key(n) (kp + n * N_COLS) +#else +#define key_ofs 1 +#define rnd_key(n) (kp - n * N_COLS) +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) +{ uint_32t locals(b0, b1); +#if defined( dec_imvars ) + dec_imvars; /* declare variables for inv_mcol() if needed */ +#endif + const uint_32t *kp; + +#if defined( AES_ERR_CHK ) + if( cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16 ) + return EXIT_FAILURE; +#endif + + kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); + state_in(b0, in, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); + switch(cx->inf.b[0]) + { + case 14 * 16: + round(inv_rnd, b1, b0, rnd_key(-13)); + round(inv_rnd, b0, b1, rnd_key(-12)); + case 12 * 16: + round(inv_rnd, b1, b0, rnd_key(-11)); + round(inv_rnd, b0, b1, rnd_key(-10)); + case 10 * 16: + round(inv_rnd, b1, b0, rnd_key(-9)); + round(inv_rnd, b0, b1, rnd_key(-8)); + round(inv_rnd, b1, b0, rnd_key(-7)); + round(inv_rnd, b0, b1, rnd_key(-6)); + round(inv_rnd, b1, b0, rnd_key(-5)); + round(inv_rnd, b0, b1, rnd_key(-4)); + round(inv_rnd, b1, b0, rnd_key(-3)); + round(inv_rnd, b0, b1, rnd_key(-2)); + round(inv_rnd, b1, b0, rnd_key(-1)); + round(inv_lrnd, b0, b1, rnd_key( 0)); + } + +#else + +#if (DEC_UNROLL == PARTIAL) + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + kp = rnd_key(1); + round(inv_rnd, b0, b1, kp); + } + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); +#else + { uint_32t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp = rnd_key(1); + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/src/utils/crypto/aeskey.c b/src/utils/crypto/aeskey.c new file mode 100644 index 000000000..8e6264f93 --- /dev/null +++ b/src/utils/crypto/aeskey.c @@ -0,0 +1,577 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 +*/ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsequence-point" + +#include "aesopt.h" +#include "aestab.h" + +#ifdef USE_VIA_ACE_IF_PRESENT +# include "aes_via_ace.h" +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Initialise the key schedule from the user supplied key. The key + length can be specified in bytes, with legal values of 16, 24 + and 32, or in bits, with legal values of 128, 192 and 256. These + values correspond with Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_col and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_col = 4 10 9 8 7 7 + cx->n_col = 5 14 11 10 9 9 + cx->n_col = 6 19 15 12 11 11 + cx->n_col = 7 21 19 16 13 14 + cx->n_col = 8 29 23 19 17 14 +*/ + +#if (FUNCS_IN_C & ENC_KEYING_IN_C) + +#if defined(AES_128) || defined(AES_VAR) + +#define ke4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; \ + k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[4]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + +#if ENC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 9; ++i) + ke4(cx->ks, i); + } +#else + ke4(cx->ks, 0); ke4(cx->ks, 1); + ke4(cx->ks, 2); ke4(cx->ks, 3); + ke4(cx->ks, 4); ke4(cx->ks, 5); + ke4(cx->ks, 6); ke4(cx->ks, 7); + ke4(cx->ks, 8); +#endif + ke4(cx->ks, 9); + cx->inf.l = 0; + cx->inf.b[0] = 10 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_192) || defined(AES_VAR) + +#define kef6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; \ + k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ kef6(k,i); \ + k[6*(i)+10] = ss[4] ^= ss[3]; \ + k[6*(i)+11] = ss[5] ^= ss[4]; \ +} + +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[6]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + +#if ENC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 7; ++i) + ke6(cx->ks, i); + } +#else + ke6(cx->ks, 0); ke6(cx->ks, 1); + ke6(cx->ks, 2); ke6(cx->ks, 3); + ke6(cx->ks, 4); ke6(cx->ks, 5); + ke6(cx->ks, 6); +#endif + kef6(cx->ks, 7); + cx->inf.l = 0; + cx->inf.b[0] = 12 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_256) || defined(AES_VAR) + +#define kef8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; \ + k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ kef8(k,i); \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ + k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; \ + k[8*(i)+15] = ss[7] ^= ss[6]; \ +} + +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint_32t ss[8]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + cx->ks[6] = ss[6] = word_in(key, 6); + cx->ks[7] = ss[7] = word_in(key, 7); + +#if ENC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 6; ++i) + ke8(cx->ks, i); + } +#else + ke8(cx->ks, 0); ke8(cx->ks, 1); + ke8(cx->ks, 2); ke8(cx->ks, 3); + ke8(cx->ks, 4); ke8(cx->ks, 5); +#endif + kef8(cx->ks, 6); + cx->inf.l = 0; + cx->inf.b[0] = 14 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_VAR) + +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) +{ + switch(key_len) + { +#if defined( AES_ERR_CHK ) + case 16: case 128: return aes_encrypt_key128(key, cx); + case 24: case 192: return aes_encrypt_key192(key, cx); + case 32: case 256: return aes_encrypt_key256(key, cx); + default: return EXIT_FAILURE; +#else + case 16: case 128: aes_encrypt_key128(key, cx); return; + case 24: case 192: aes_encrypt_key192(key, cx); return; + case 32: case 256: aes_encrypt_key256(key, cx); return; +#endif + } +} + +#endif + +#endif + +#if (FUNCS_IN_C & DEC_KEYING_IN_C) + +/* this is used to store the decryption round keys */ +/* in forward or reverse order */ + +#ifdef AES_REV_DKS +#define v(n,i) ((n) - (i) + 2 * ((i) & 3)) +#else +#define v(n,i) (i) +#endif + +#if DEC_ROUND == NO_TABLES +#define ff(x) (x) +#else +#define ff(x) inv_mcol(x) +#if defined( dec_imvars ) +#define d_vars dec_imvars +#endif +#endif + +#if defined(AES_128) || defined(AES_VAR) + +#define k4e(k,i) \ +{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ + k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ + k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ +} + +#if 1 + +#define kdf4(k,i) \ +{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ + ss[1] = ss[1] ^ ss[3]; \ + ss[2] = ss[2] ^ ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ + k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ + k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ +} + +#define kdl4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ + k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ + k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ + k[v(40,(4*(i))+6)] = ss[0]; \ + k[v(40,(4*(i))+7)] = ss[1]; \ +} + +#else + +#define kdf4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ +} + +#define kdl4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ +} + +#endif + +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[5]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); + +#if DEC_UNROLL == NONE + { uint_32t i; + for(i = 0; i < 10; ++i) + k4e(cx->ks, i); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 10 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#else + kdf4(cx->ks, 0); kd4(cx->ks, 1); + kd4(cx->ks, 2); kd4(cx->ks, 3); + kd4(cx->ks, 4); kd4(cx->ks, 5); + kd4(cx->ks, 6); kd4(cx->ks, 7); + kd4(cx->ks, 8); kdl4(cx->ks, 9); +#endif + cx->inf.l = 0; + cx->inf.b[0] = 10 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_192) || defined(AES_VAR) + +#define k6ef(k,i) \ +{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ + k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ + k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ +} + +#define k6e(k,i) \ +{ k6ef(k,i); \ + k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ + k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ +} + +#define kdf6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ +} + +#define kd6(k,i) \ +{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ +} + +#define kdl6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ +} + +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[7]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); + +#if DEC_UNROLL == NONE + cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); + { uint_32t i; + + for(i = 0; i < 7; ++i) + k6e(cx->ks, i); + k6ef(cx->ks, 7); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 12 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#else + cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4)); + cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5)); + kdf6(cx->ks, 0); kd6(cx->ks, 1); + kd6(cx->ks, 2); kd6(cx->ks, 3); + kd6(cx->ks, 4); kd6(cx->ks, 5); + kd6(cx->ks, 6); kdl6(cx->ks, 7); +#endif + cx->inf.l = 0; + cx->inf.b[0] = 12 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_256) || defined(AES_VAR) + +#define k8ef(k,i) \ +{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ + k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ + k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ +} + +#define k8e(k,i) \ +{ k8ef(k,i); \ + k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ + k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ + k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ + k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ +} + +#define kdf8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ +} + +#define kd8(k,i) \ +{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ + ss[8] = ls_box(ss[3],0); \ + ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ +} + +#define kdl8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ +} + +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint_32t ss[9]; +#if defined( d_vars ) + d_vars; +#endif + cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); + +#if DEC_UNROLL == NONE + cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); + cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); + cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); + { uint_32t i; + + for(i = 0; i < 6; ++i) + k8e(cx->ks, i); + k8ef(cx->ks, 6); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 14 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); + +#endif + } +#else + cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4)); + cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5)); + cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6)); + cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7)); + kdf8(cx->ks, 0); kd8(cx->ks, 1); + kd8(cx->ks, 2); kd8(cx->ks, 3); + kd8(cx->ks, 4); kd8(cx->ks, 5); + kdl8(cx->ks, 6); +#endif + cx->inf.l = 0; + cx->inf.b[0] = 14 * 16; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + +#if defined( AES_ERR_CHK ) + return EXIT_SUCCESS; +#endif +} + +#endif + +#if defined(AES_VAR) + +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) +{ + switch(key_len) + { +#if defined( AES_ERR_CHK ) + case 16: case 128: return aes_decrypt_key128(key, cx); + case 24: case 192: return aes_decrypt_key192(key, cx); + case 32: case 256: return aes_decrypt_key256(key, cx); + default: return EXIT_FAILURE; +#else + case 16: case 128: aes_decrypt_key128(key, cx); return; + case 24: case 192: aes_decrypt_key192(key, cx); return; + case 32: case 256: aes_decrypt_key256(key, cx); return; +#endif + } +} + +#endif + +#endif + +#if defined(__cplusplus) +} +#endif + +#pragma GCC diagnostic pop diff --git a/src/utils/crypto/aesopt.h b/src/utils/crypto/aesopt.h new file mode 100644 index 000000000..1a9778222 --- /dev/null +++ b/src/utils/crypto/aesopt.h @@ -0,0 +1,731 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + + This file contains the compilation options for AES (Rijndael) and code + that is common across encryption, key scheduling and table generation. + + OPERATION + + These source code files implement the AES algorithm Rijndael designed by + Joan Daemen and Vincent Rijmen. This version is designed for the standard + block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 + and 32 bytes). + + This version is designed for flexibility and speed using operations on + 32-bit words rather than operations on bytes. It can be compiled with + either big or little endian internal byte order but is faster when the + native byte order for the processor is used. + + THE CIPHER INTERFACE + + The cipher interface is implemented as an array of bytes in which lower + AES bit sequence indexes map to higher numeric significance within bytes. + + uint_8t (an unsigned 8-bit type) + uint_32t (an unsigned 32-bit type) + struct aes_encrypt_ctx (structure for the cipher encryption context) + struct aes_decrypt_ctx (structure for the cipher decryption context) + AES_RETURN the function return type + + C subroutine calls: + + AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, + const aes_encrypt_ctx cx[1]); + + AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, + const aes_decrypt_ctx cx[1]); + + IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that + you call aes_init() before AES is used so that the tables are initialised. + + C++ aes class subroutines: + + Class AESencrypt for encryption + + Construtors: + AESencrypt(void) + AESencrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const + + Class AESdecrypt for encryption + Construtors: + AESdecrypt(void) + AESdecrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#if !defined( _AESOPT_H ) +#define _AESOPT_H + + +#if defined( __cplusplus ) +#include "aescpp.h" +#else +#include "aes.h" +#endif + + +#include "../common/endian.h" +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#endif + + +/* CONFIGURATION - THE USE OF DEFINES + + Later in this section there are a number of defines that control the + operation of the code. In each section, the purpose of each define is + explained so that the relevant form can be included or excluded by + setting either 1's or 0's respectively on the branches of the related + #if clauses. The following local defines should not be changed. +*/ + +#define ENCRYPTION_IN_C 1 +#define DECRYPTION_IN_C 2 +#define ENC_KEYING_IN_C 4 +#define DEC_KEYING_IN_C 8 + +#define NO_TABLES 0 +#define ONE_TABLE 1 +#define FOUR_TABLES 4 +#define NONE 0 +#define PARTIAL 1 +#define FULL 2 + +/* --- START OF USER CONFIGURED OPTIONS --- */ + +/* 1. BYTE ORDER WITHIN 32 BIT WORDS + + The fundamental data processing units in Rijndael are 8-bit bytes. The + input, output and key input are all enumerated arrays of bytes in which + bytes are numbered starting at zero and increasing to one less than the + number of bytes in the array in question. This enumeration is only used + for naming bytes and does not imply any adjacency or order relationship + from one byte to another. When these inputs and outputs are considered + as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + In this implementation bits are numbered from 0 to 7 starting at the + numerically least significant end of each byte (bit n represents 2^n). + + However, Rijndael can be implemented more efficiently using 32-bit + words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + into word[n]. While in principle these bytes can be assembled into words + in any positions, this implementation only supports the two formats in + which bytes in adjacent positions within words also have adjacent byte + numbers. This order is called big-endian if the lowest numbered bytes + in words have the highest numeric significance and little-endian if the + opposite applies. + + This code can work in either order irrespective of the order used by the + machine on which it runs. Normally the internal byte order will be set + to the order of the processor on which the code is to be run but this + define can be used to reverse this in special situations + + WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. + This define will hence be redefined later (in section 4) if necessary +*/ + +#if 1 +#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif 0 +#define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 +#define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN +#else +#error The algorithm byte order is not defined +#endif + +/* 2. VIA ACE SUPPORT + + Define this option if support for the VIA ACE is required. This uses + inline assembler instructions and is only implemented for the Microsoft, + Intel and GCC compilers. If VIA ACE is known to be present, then defining + ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption + code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if + it is detected (both present and enabled) but the normal AES code will + also be present. + + When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte + aligned; other input/output buffers do not need to be 16 byte aligned + but there are very large performance gains if this can be arranged. + VIA ACE also requires the decryption key schedule to be in reverse + order (which later checks below ensure). +*/ + +#if 0 && !defined( USE_VIA_ACE_IF_PRESENT ) +# define USE_VIA_ACE_IF_PRESENT +#endif + +#if 0 && !defined( ASSUME_VIA_ACE_PRESENT ) +# define ASSUME_VIA_ACE_PRESENT +# endif + +#if defined ( _WIN64 ) || defined( _WIN32_WCE ) || \ + defined( _MSC_VER ) && ( _MSC_VER <= 800 ) +# if defined( USE_VIA_ACE_IF_PRESENT ) +# undef USE_VIA_ACE_IF_PRESENT +# endif +# if defined( ASSUME_VIA_ACE_PRESENT ) +# undef ASSUME_VIA_ACE_PRESENT +# endif +#endif + +/* 3. ASSEMBLER SUPPORT + + This define (which can be on the command line) enables the use of the + assembler code routines for encryption, decryption and key scheduling + as follows: + + ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for + encryption and decryption and but with key scheduling in C + ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for + encryption, decryption and key scheduling + ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + + Change one 'if 0' below to 'if 1' to select the version or define + as a compilation option. +*/ + +#if 0 && !defined( ASM_X86_V1C ) +# define ASM_X86_V1C +#elif 0 && !defined( ASM_X86_V2 ) +# define ASM_X86_V2 +#elif 0 && !defined( ASM_X86_V2C ) +# define ASM_X86_V2C +#elif 0 && !defined( ASM_AMD64_C ) +# define ASM_AMD64_C +#endif + +#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ + && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 ) +//# error Assembler code is only available for x86 and AMD64 systems +#endif + +/* 4. FAST INPUT/OUTPUT OPERATIONS. + + On some machines it is possible to improve speed by transferring the + bytes in the input and output arrays to and from the internal 32-bit + variables by addressing these arrays as if they are arrays of 32-bit + words. On some machines this will always be possible but there may + be a large performance penalty if the byte arrays are not aligned on + the normal word boundaries. On other machines this technique will + lead to memory access errors when such 32-bit word accesses are not + properly aligned. The option SAFE_IO avoids such problems but will + often be slower on those machines that support misaligned access + (especially so if care is taken to align the input and output byte + arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + assumed that access to byte arrays as if they are arrays of 32-bit + words will not cause problems when such accesses are misaligned. +*/ +#if 1 && !defined( _MSC_VER ) +#define SAFE_IO +#endif + +/* 5. LOOP UNROLLING + + The code for encryption and decrytpion cycles through a number of rounds + that can be implemented either in a loop or by expanding the code into a + long sequence of instructions, the latter producing a larger program but + one that will often be much faster. The latter is called loop unrolling. + There are also potential speed advantages in expanding two iterations in + a loop with half the number of iterations, which is called partial loop + unrolling. The following options allow partial or full loop unrolling + to be set independently for encryption and decryption +*/ +#if 1 +#define ENC_UNROLL FULL +#elif 0 +#define ENC_UNROLL PARTIAL +#else +#define ENC_UNROLL NONE +#endif + +#if 1 +#define DEC_UNROLL FULL +#elif 0 +#define DEC_UNROLL PARTIAL +#else +#define DEC_UNROLL NONE +#endif + +/* 6. FAST FINITE FIELD OPERATIONS + + If this section is included, tables are used to provide faster finite + field arithmetic (this has no effect if FIXED_TABLES is defined). +*/ +#if !defined (TC_WINDOWS_BOOT) +#define FF_TABLES +#endif + +/* 7. INTERNAL STATE VARIABLE FORMAT + + The internal state of Rijndael is stored in a number of local 32-bit + word varaibles which can be defined either as an array or as individual + names variables. Include this section if you want to store these local + varaibles in arrays. Otherwise individual local variables will be used. +*/ +#if 1 +#define ARRAYS +#endif + +/* 8. FIXED OR DYNAMIC TABLES + + When this section is included the tables used by the code are compiled + statically into the binary file. Otherwise the subroutine aes_init() + must be called to compute them before the code is first used. +*/ +#if !defined (TC_WINDOWS_BOOT) && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) +#define FIXED_TABLES +#endif + +/* 9. TABLE ALIGNMENT + + On some sytsems speed will be improved by aligning the AES large lookup + tables on particular boundaries. This define should be set to a power of + two giving the desired alignment. It can be left undefined if alignment + is not needed. This option is specific to the Microsft VC++ compiler - + it seems to sometimes cause trouble for the VC++ version 6 compiler. +*/ + +#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +#define TABLE_ALIGN 32 +#endif + +/* 10. TABLE OPTIONS + + This cipher proceeds by repeating in a number of cycles known as 'rounds' + which are implemented by a round function which can optionally be speeded + up using tables. The basic tables are each 256 32-bit words, with either + one or four tables being required for each round function depending on + how much speed is required. The encryption and decryption round functions + are different and the last encryption and decrytpion round functions are + different again making four different round functions in all. + + This means that: + 1. Normal encryption and decryption rounds can each use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + 2. The last encryption and decryption rounds can also use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + + Include or exclude the appropriate definitions below to set the number + of tables used by this implementation. +*/ + +#if 1 /* set tables for the normal encryption round */ +#define ENC_ROUND FOUR_TABLES +#elif 0 +#define ENC_ROUND ONE_TABLE +#else +#define ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last encryption round */ +#define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +#define LAST_ENC_ROUND ONE_TABLE +#else +#define LAST_ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the normal decryption round */ +#define DEC_ROUND FOUR_TABLES +#elif 0 +#define DEC_ROUND ONE_TABLE +#else +#define DEC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last decryption round */ +#define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +#define LAST_DEC_ROUND ONE_TABLE +#else +#define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + way that the round functions can. Include or exclude the following + defines to set this requirement. +*/ +#if 1 +#define KEY_SCHED FOUR_TABLES +#elif 0 +#define KEY_SCHED ONE_TABLE +#else +#define KEY_SCHED NO_TABLES +#endif + +/* ---- END OF USER CONFIGURED OPTIONS ---- */ + +/* VIA ACE support is only available for VC++ and GCC */ + +#if !defined( _MSC_VER ) && !defined( __GNUC__ ) +# if defined( ASSUME_VIA_ACE_PRESENT ) +# undef ASSUME_VIA_ACE_PRESENT +# endif +# if defined( USE_VIA_ACE_IF_PRESENT ) +# undef USE_VIA_ACE_IF_PRESENT +# endif +#endif + +#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) +#define USE_VIA_ACE_IF_PRESENT +#endif + +#if defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) +#define AES_REV_DKS +#endif + +/* Assembler support requires the use of platform byte order */ + +#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ + && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) +#undef ALGORITHM_BYTE_ORDER +#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#endif + +/* In this implementation the columns of the state array are each held in + 32-bit words. The state array can be held in various ways: in an array + of words, in a number of individual word variables or in a number of + processor registers. The following define maps a variable name x and + a column number c to the way the state array variable is to be held. + The first define below maps the state into an array x[c] whereas the + second form maps the state into a number of individual variables x0, + x1, etc. Another form could map individual state colums to machine + register names. +*/ + +#if defined( ARRAYS ) +#define s(x,c) x[c] +#else +#define s(x,c) x##c +#endif + +/* This implementation provides subroutines for encryption, decryption + and for setting the three key lengths (separately) for encryption + and decryption. Since not all functions are needed, masks are set + up here to determine which will be implemented in C +*/ + +#if !defined( AES_ENCRYPT ) +# define EFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define EFUNCS_IN_C ENC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) +#else +# define EFUNCS_IN_C 0 +#endif + +#if !defined( AES_DECRYPT ) +# define DFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define DFUNCS_IN_C DEC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) +#else +# define DFUNCS_IN_C 0 +#endif + +#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) + +/* END OF CONFIGURATION OPTIONS */ + +#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) + +/* Disable or report errors on some combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +#undef ENC_UNROLL +#define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +#undef DEC_UNROLL +#define DEC_UNROLL NONE +#endif + +#if defined( bswap32 ) +#define aes_sw32 bswap32 +#elif defined( bswap_32 ) +#define aes_sw32 bswap_32 +#else +#define brot(x,n) (((uint_32t)(x) << n) | ((uint_32t)(x) >> (32 - n))) +#define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) +#endif + +/* upr(x,n): rotates bytes within words by n positions, moving bytes to + higher index positions with wrap around into low positions + ups(x,n): moves bytes by n positions to higher index positions in + words but without wrap around + bval(x,n): extracts a byte from a word + + WARNING: The definitions given here are intended only for use with + unsigned variables and with shift counts that are compile + time constants +*/ + +#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) +#define upr(x,n) (((uint_32t)(x) << (8 * (n))) | ((uint_32t)(x) >> (32 - 8 * (n)))) +#define ups(x,n) ((uint_32t) (x) << (8 * (n))) +#define bval(x,n) ((uint_8t)((x) >> (8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((uint_32t)(b3) << 24) | ((uint_32t)(b2) << 16) | ((uint_32t)(b1) << 8) | (b0)) +#endif + +#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) +#define upr(x,n) (((uint_32t)(x) >> (8 * (n))) | ((uint_32t)(x) << (32 - 8 * (n)))) +#define ups(x,n) ((uint_32t) (x) >> (8 * (n))) +#define bval(x,n) ((uint_8t)((x) >> (24 - 8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((uint_32t)(b0) << 24) | ((uint_32t)(b1) << 16) | ((uint_32t)(b2) << 8) | (b3)) +#endif + +#if defined( SAFE_IO ) + +#define word_in(x,c) bytes2word(((const uint_8t*)(x)+4*c)[0], ((const uint_8t*)(x)+4*c)[1], \ + ((const uint_8t*)(x)+4*c)[2], ((const uint_8t*)(x)+4*c)[3]) +#define word_out(x,c,v) { ((uint_8t*)(x)+4*c)[0] = bval(v,0); ((uint_8t*)(x)+4*c)[1] = bval(v,1); \ + ((uint_8t*)(x)+4*c)[2] = bval(v,2); ((uint_8t*)(x)+4*c)[3] = bval(v,3); } + +#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) + +#define word_in(x,c) (*((uint_32t*)(x)+(c))) +#define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = (v)) + +#else + +#define word_in(x,c) aes_sw32(*((uint_32t*)(x)+(c))) +#define word_out(x,c,v) (*((uint_32t*)(x)+(c)) = aes_sw32(v)) + +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define m1 0x80808080 +#define m2 0x7f7f7f7f +#define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of gf_mulx that might + give improved performance if a fast 32-bit multiply is not available. Note + that a temporary variable u needs to be defined where gf_mulx is used. + +#define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) +#define m4 (0x01010101 * BPOLY) +#define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) +*/ + +/* Work out which tables are needed for the different options */ + +#if defined( ASM_X86_V1C ) +#if defined( ENC_ROUND ) +#undef ENC_ROUND +#endif +#define ENC_ROUND FOUR_TABLES +#if defined( LAST_ENC_ROUND ) +#undef LAST_ENC_ROUND +#endif +#define LAST_ENC_ROUND FOUR_TABLES +#if defined( DEC_ROUND ) +#undef DEC_ROUND +#endif +#define DEC_ROUND FOUR_TABLES +#if defined( LAST_DEC_ROUND ) +#undef LAST_DEC_ROUND +#endif +#define LAST_DEC_ROUND FOUR_TABLES +#if defined( KEY_SCHED ) +#undef KEY_SCHED +#define KEY_SCHED FOUR_TABLES +#endif +#endif + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) +#if ENC_ROUND == ONE_TABLE +#define FT1_SET +#elif ENC_ROUND == FOUR_TABLES +#define FT4_SET +#else +#define SBX_SET +#endif +#if LAST_ENC_ROUND == ONE_TABLE +#define FL1_SET +#elif LAST_ENC_ROUND == FOUR_TABLES +#define FL4_SET +#elif !defined( SBX_SET ) +#define SBX_SET +#endif +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) +#if DEC_ROUND == ONE_TABLE +#define IT1_SET +#elif DEC_ROUND == FOUR_TABLES +#define IT4_SET +#else +#define ISB_SET +#endif +#if LAST_DEC_ROUND == ONE_TABLE +#define IL1_SET +#elif LAST_DEC_ROUND == FOUR_TABLES +#define IL4_SET +#elif !defined(ISB_SET) +#define ISB_SET +#endif +#endif + +#if (FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C) +#if KEY_SCHED == ONE_TABLE +#define LS1_SET +#elif KEY_SCHED == FOUR_TABLES +#define LS4_SET +#elif !defined( SBX_SET ) +#define SBX_SET +#endif +#endif + +#if (FUNCS_IN_C & DEC_KEYING_IN_C) +#if KEY_SCHED == ONE_TABLE +#define IM1_SET +#elif KEY_SCHED == FOUR_TABLES +#define IM4_SET +#elif !defined( SBX_SET ) +#define SBX_SET +#endif +#endif + +/* generic definitions of Rijndael macros that use tables */ + +#define no_table(x,box,vf,rf,c) bytes2word( \ + box[bval(vf(x,0,c),rf(0,c))], \ + box[bval(vf(x,1,c),rf(1,c))], \ + box[bval(vf(x,2,c),rf(2,c))], \ + box[bval(vf(x,3,c),rf(3,c))]) + +#define one_table(x,op,tab,vf,rf,c) \ + ( tab[bval(vf(x,0,c),rf(0,c))] \ + ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ + ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ + ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) + +#define four_tables(x,tab,vf,rf,c) \ + ( tab[0][bval(vf(x,0,c),rf(0,c))] \ + ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ + ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ + ^ tab[3][bval(vf(x,3,c),rf(3,c))]) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((8+r-c)&3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#if defined( FM4_SET ) /* not currently used */ +#define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) +#elif defined( FM1_SET ) /* not currently used */ +#define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) +#else +#define dec_fmvars uint_32t g2 +#define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) +#endif + +#if defined( IM4_SET ) +#define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) +#elif defined( IM1_SET ) +#define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) +#else +#define dec_imvars uint_32t g2, g4, g9 +#define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ + (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) +#endif + +#if defined( FL4_SET ) +#define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) +#elif defined( LS4_SET ) +#define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) +#elif defined( FL1_SET ) +#define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) +#elif defined( LS1_SET ) +#define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) +#else +#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) +#endif + +#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) +#define ISB_SET +#endif + +#endif diff --git a/src/utils/crypto/aessmall.c b/src/utils/crypto/aessmall.c new file mode 100644 index 000000000..3296f1391 --- /dev/null +++ b/src/utils/crypto/aessmall.c @@ -0,0 +1,921 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state (there are options to use 32-bit types if available). + + The combination of mix columns and byte substitution used here is based on + that developed by Karl Malbrain. His contribution is acknowledged. + */ + +/* Adapted by TrueCrypt Foundation: + - Macro-generated tables were replaced with static data to enable compiling + with MSVC++ 1.5 which runs out of resources when expanding large macros. +*/ + +// #pragma optimize ("t", on) + +/* define if you have a fast memcpy function on your system */ +#if 1 +# define HAVE_MEMCPY +# include +# if defined( _MSC_VER ) +# ifndef DEBUG +# pragma intrinsic( memcpy ) +# endif +# endif +#endif + +/* define if you have fast 32-bit types on your system */ +#if 1 +# define HAVE_UINT_32T +#endif + +/* alternative versions (test for performance on your system) */ +#if 0 +# define VERSION_1 +#endif + +#include +#include "aessmall.h" + +#define WPOLY 0x011b +#define DPOLY 0x008d +#define f1(x) (x) +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +static const uint_8t s_box[256] = { + 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, + 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, + 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, + 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, + 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, + 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, + 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, + 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, + 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, + 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, + 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, + 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, + 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, + 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, + 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, + 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, + 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 +}; + +static const uint_8t inv_s_box[256] = { + 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38, + 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, + 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87, + 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, + 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d, + 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, + 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2, + 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, + 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16, + 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, + 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda, + 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, + 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a, + 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, + 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02, + 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, + 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea, + 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, + 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85, + 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, + 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89, + 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, + 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20, + 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, + 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31, + 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, + 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d, + 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, + 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0, + 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, + 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26, + 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d +}; + +static const uint_8t gfm2_s_box[256] = { + 0xc6,0xf8,0xee,0xf6,0xff,0xd6,0xde,0x91, + 0x60,0x02,0xce,0x56,0xe7,0xb5,0x4d,0xec, + 0x8f,0x1f,0x89,0xfa,0xef,0xb2,0x8e,0xfb, + 0x41,0xb3,0x5f,0x45,0x23,0x53,0xe4,0x9b, + 0x75,0xe1,0x3d,0x4c,0x6c,0x7e,0xf5,0x83, + 0x68,0x51,0xd1,0xf9,0xe2,0xab,0x62,0x2a, + 0x08,0x95,0x46,0x9d,0x30,0x37,0x0a,0x2f, + 0x0e,0x24,0x1b,0xdf,0xcd,0x4e,0x7f,0xea, + 0x12,0x1d,0x58,0x34,0x36,0xdc,0xb4,0x5b, + 0xa4,0x76,0xb7,0x7d,0x52,0xdd,0x5e,0x13, + 0xa6,0xb9,0x00,0xc1,0x40,0xe3,0x79,0xb6, + 0xd4,0x8d,0x67,0x72,0x94,0x98,0xb0,0x85, + 0xbb,0xc5,0x4f,0xed,0x86,0x9a,0x66,0x11, + 0x8a,0xe9,0x04,0xfe,0xa0,0x78,0x25,0x4b, + 0xa2,0x5d,0x80,0x05,0x3f,0x21,0x70,0xf1, + 0x63,0x77,0xaf,0x42,0x20,0xe5,0xfd,0xbf, + 0x81,0x18,0x26,0xc3,0xbe,0x35,0x88,0x2e, + 0x93,0x55,0xfc,0x7a,0xc8,0xba,0x32,0xe6, + 0xc0,0x19,0x9e,0xa3,0x44,0x54,0x3b,0x0b, + 0x8c,0xc7,0x6b,0x28,0xa7,0xbc,0x16,0xad, + 0xdb,0x64,0x74,0x14,0x92,0x0c,0x48,0xb8, + 0x9f,0xbd,0x43,0xc4,0x39,0x31,0xd3,0xf2, + 0xd5,0x8b,0x6e,0xda,0x01,0xb1,0x9c,0x49, + 0xd8,0xac,0xf3,0xcf,0xca,0xf4,0x47,0x10, + 0x6f,0xf0,0x4a,0x5c,0x38,0x57,0x73,0x97, + 0xcb,0xa1,0xe8,0x3e,0x96,0x61,0x0d,0x0f, + 0xe0,0x7c,0x71,0xcc,0x90,0x06,0xf7,0x1c, + 0xc2,0x6a,0xae,0x69,0x17,0x99,0x3a,0x27, + 0xd9,0xeb,0x2b,0x22,0xd2,0xa9,0x07,0x33, + 0x2d,0x3c,0x15,0xc9,0x87,0xaa,0x50,0xa5, + 0x03,0x59,0x09,0x1a,0x65,0xd7,0x84,0xd0, + 0x82,0x29,0x5a,0x1e,0x7b,0xa8,0x6d,0x2c +}; + +static const uint_8t gfm3_s_box[256] = { + 0xa5,0x84,0x99,0x8d,0x0d,0xbd,0xb1,0x54, + 0x50,0x03,0xa9,0x7d,0x19,0x62,0xe6,0x9a, + 0x45,0x9d,0x40,0x87,0x15,0xeb,0xc9,0x0b, + 0xec,0x67,0xfd,0xea,0xbf,0xf7,0x96,0x5b, + 0xc2,0x1c,0xae,0x6a,0x5a,0x41,0x02,0x4f, + 0x5c,0xf4,0x34,0x08,0x93,0x73,0x53,0x3f, + 0x0c,0x52,0x65,0x5e,0x28,0xa1,0x0f,0xb5, + 0x09,0x36,0x9b,0x3d,0x26,0x69,0xcd,0x9f, + 0x1b,0x9e,0x74,0x2e,0x2d,0xb2,0xee,0xfb, + 0xf6,0x4d,0x61,0xce,0x7b,0x3e,0x71,0x97, + 0xf5,0x68,0x00,0x2c,0x60,0x1f,0xc8,0xed, + 0xbe,0x46,0xd9,0x4b,0xde,0xd4,0xe8,0x4a, + 0x6b,0x2a,0xe5,0x16,0xc5,0xd7,0x55,0x94, + 0xcf,0x10,0x06,0x81,0xf0,0x44,0xba,0xe3, + 0xf3,0xfe,0xc0,0x8a,0xad,0xbc,0x48,0x04, + 0xdf,0xc1,0x75,0x63,0x30,0x1a,0x0e,0x6d, + 0x4c,0x14,0x35,0x2f,0xe1,0xa2,0xcc,0x39, + 0x57,0xf2,0x82,0x47,0xac,0xe7,0x2b,0x95, + 0xa0,0x98,0xd1,0x7f,0x66,0x7e,0xab,0x83, + 0xca,0x29,0xd3,0x3c,0x79,0xe2,0x1d,0x76, + 0x3b,0x56,0x4e,0x1e,0xdb,0x0a,0x6c,0xe4, + 0x5d,0x6e,0xef,0xa6,0xa8,0xa4,0x37,0x8b, + 0x32,0x43,0x59,0xb7,0x8c,0x64,0xd2,0xe0, + 0xb4,0xfa,0x07,0x25,0xaf,0x8e,0xe9,0x18, + 0xd5,0x88,0x6f,0x72,0x24,0xf1,0xc7,0x51, + 0x23,0x7c,0x9c,0x21,0xdd,0xdc,0x86,0x85, + 0x90,0x42,0xc4,0xaa,0xd8,0x05,0x01,0x12, + 0xa3,0x5f,0xf9,0xd0,0x91,0x58,0x27,0xb9, + 0x38,0x13,0xb3,0x33,0xbb,0x70,0x89,0xa7, + 0xb6,0x22,0x92,0x20,0x49,0xff,0x78,0x7a, + 0x8f,0xf8,0x80,0x17,0xda,0x31,0xc6,0xb8, + 0xc3,0xb0,0x77,0x11,0xcb,0xfc,0xd6,0x3a +}; + +static const uint_8t gfmul_9[256] = { + 0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f, + 0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77, + 0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf, + 0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7, + 0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04, + 0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c, + 0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94, + 0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc, + 0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49, + 0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01, + 0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9, + 0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91, + 0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72, + 0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a, + 0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2, + 0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa, + 0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3, + 0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b, + 0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43, + 0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b, + 0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8, + 0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0, + 0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78, + 0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30, + 0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5, + 0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed, + 0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35, + 0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d, + 0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e, + 0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6, + 0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e, + 0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46 +}; + +static const uint_8t gfmul_b[256] = { + 0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31, + 0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69, + 0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81, + 0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9, + 0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a, + 0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12, + 0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa, + 0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2, + 0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7, + 0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f, + 0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77, + 0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f, + 0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc, + 0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4, + 0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c, + 0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54, + 0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6, + 0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e, + 0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76, + 0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e, + 0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd, + 0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5, + 0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d, + 0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55, + 0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30, + 0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68, + 0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80, + 0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8, + 0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b, + 0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13, + 0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb, + 0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3 +}; + +static const uint_8t gfmul_d[256] = { + 0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23, + 0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b, + 0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3, + 0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b, + 0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98, + 0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0, + 0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48, + 0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20, + 0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e, + 0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26, + 0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e, + 0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6, + 0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5, + 0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d, + 0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25, + 0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d, + 0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9, + 0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91, + 0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29, + 0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41, + 0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42, + 0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a, + 0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92, + 0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa, + 0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94, + 0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc, + 0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44, + 0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c, + 0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f, + 0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47, + 0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff, + 0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97 +}; + +static const uint_8t gfmul_e[256] = { + 0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a, + 0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a, + 0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca, + 0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba, + 0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1, + 0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81, + 0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11, + 0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61, + 0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87, + 0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7, + 0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67, + 0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17, + 0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c, + 0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c, + 0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc, + 0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc, + 0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b, + 0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b, + 0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b, + 0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb, + 0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0, + 0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0, + 0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50, + 0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20, + 0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6, + 0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6, + 0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26, + 0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56, + 0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d, + 0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d, + 0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd, + 0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d +}; + +#if defined( HAVE_UINT_32T ) + typedef unsigned long uint_32t; +#endif + +#if defined( HAVE_MEMCPY ) +# define block_copy(d, s, l) memcpy(d, s, l) +# define block16_copy(d, s) memcpy(d, s, N_BLOCK) +#else +# define block_copy(d, s, l) copy_block(d, s, l) +# define block16_copy(d, s) copy_block16(d, s) + +/* block size 'nn' must be a multiple of four */ + +static void copy_block16( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0]; + ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1]; + ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2]; + ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3]; +#else + ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0]; + ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1]; + ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2]; + ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3]; + ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4]; + ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5]; + ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6]; + ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7]; + ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8]; + ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9]; + ((uint_8t*)d)[10] = ((uint_8t*)s)[10]; + ((uint_8t*)d)[11] = ((uint_8t*)s)[11]; + ((uint_8t*)d)[12] = ((uint_8t*)s)[12]; + ((uint_8t*)d)[13] = ((uint_8t*)s)[13]; + ((uint_8t*)d)[14] = ((uint_8t*)s)[14]; + ((uint_8t*)d)[15] = ((uint_8t*)s)[15]; +#endif +} + +static void copy_block( void * d, void *s, uint_8t nn ) +{ + while( nn-- ) + *((uint8_t*)d)++ = *((uint8_t*)s)++; +} +#endif + +static void copy_and_key( void *d, const void *s, const void *k ) +{ +#if defined( HAVE_UINT_32T ) + ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0] ^ ((uint_32t*)k)[ 0]; + ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1] ^ ((uint_32t*)k)[ 1]; + ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2] ^ ((uint_32t*)k)[ 2]; + ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3] ^ ((uint_32t*)k)[ 3]; +#elif 1 + ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0] ^ ((uint_8t*)k)[ 0]; + ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1] ^ ((uint_8t*)k)[ 1]; + ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2] ^ ((uint_8t*)k)[ 2]; + ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3] ^ ((uint_8t*)k)[ 3]; + ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4] ^ ((uint_8t*)k)[ 4]; + ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5] ^ ((uint_8t*)k)[ 5]; + ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6] ^ ((uint_8t*)k)[ 6]; + ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7] ^ ((uint_8t*)k)[ 7]; + ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8] ^ ((uint_8t*)k)[ 8]; + ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9] ^ ((uint_8t*)k)[ 9]; + ((uint_8t*)d)[10] = ((uint_8t*)s)[10] ^ ((uint_8t*)k)[10]; + ((uint_8t*)d)[11] = ((uint_8t*)s)[11] ^ ((uint_8t*)k)[11]; + ((uint_8t*)d)[12] = ((uint_8t*)s)[12] ^ ((uint_8t*)k)[12]; + ((uint_8t*)d)[13] = ((uint_8t*)s)[13] ^ ((uint_8t*)k)[13]; + ((uint_8t*)d)[14] = ((uint_8t*)s)[14] ^ ((uint_8t*)k)[14]; + ((uint_8t*)d)[15] = ((uint_8t*)s)[15] ^ ((uint_8t*)k)[15]; +#else + block16_copy(d, s); + xor_block(d, k); +#endif +} + +static void shift_sub_rows( uint_8t st[N_BLOCK] ) +{ uint_8t tt; + + st[ 0] = s_box[st[ 0]]; st[ 4] = s_box[st[ 4]]; + st[ 8] = s_box[st[ 8]]; st[12] = s_box[st[12]]; + + tt = st[1]; st[ 1] = s_box[st[ 5]]; st[ 5] = s_box[st[ 9]]; + st[ 9] = s_box[st[13]]; st[13] = s_box[ tt ]; + + tt = st[2]; st[ 2] = s_box[st[10]]; st[10] = s_box[ tt ]; + tt = st[6]; st[ 6] = s_box[st[14]]; st[14] = s_box[ tt ]; + + tt = st[15]; st[15] = s_box[st[11]]; st[11] = s_box[st[ 7]]; + st[ 7] = s_box[st[ 3]]; st[ 3] = s_box[ tt ]; +} + +static void inv_shift_sub_rows( uint_8t st[N_BLOCK] ) +{ uint_8t tt; + + st[ 0] = inv_s_box[st[ 0]]; st[ 4] = inv_s_box[st[ 4]]; + st[ 8] = inv_s_box[st[ 8]]; st[12] = inv_s_box[st[12]]; + + tt = st[13]; st[13] = inv_s_box[st[9]]; st[ 9] = inv_s_box[st[5]]; + st[ 5] = inv_s_box[st[1]]; st[ 1] = inv_s_box[ tt ]; + + tt = st[2]; st[ 2] = inv_s_box[st[10]]; st[10] = inv_s_box[ tt ]; + tt = st[6]; st[ 6] = inv_s_box[st[14]]; st[14] = inv_s_box[ tt ]; + + tt = st[3]; st[ 3] = inv_s_box[st[ 7]]; st[ 7] = inv_s_box[st[11]]; + st[11] = inv_s_box[st[15]]; st[15] = inv_s_box[ tt ]; +} + +#if defined( VERSION_1 ) + static void mix_sub_columns( uint_8t dt[N_BLOCK] ) + { uint_8t st[N_BLOCK]; + block16_copy(st, dt); +#else + static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] ) + { +#endif + dt[ 0] = gfm2_s_box[st[0]] ^ gfm3_s_box[st[5]] ^ s_box[st[10]] ^ s_box[st[15]]; + dt[ 1] = s_box[st[0]] ^ gfm2_s_box[st[5]] ^ gfm3_s_box[st[10]] ^ s_box[st[15]]; + dt[ 2] = s_box[st[0]] ^ s_box[st[5]] ^ gfm2_s_box[st[10]] ^ gfm3_s_box[st[15]]; + dt[ 3] = gfm3_s_box[st[0]] ^ s_box[st[5]] ^ s_box[st[10]] ^ gfm2_s_box[st[15]]; + + dt[ 4] = gfm2_s_box[st[4]] ^ gfm3_s_box[st[9]] ^ s_box[st[14]] ^ s_box[st[3]]; + dt[ 5] = s_box[st[4]] ^ gfm2_s_box[st[9]] ^ gfm3_s_box[st[14]] ^ s_box[st[3]]; + dt[ 6] = s_box[st[4]] ^ s_box[st[9]] ^ gfm2_s_box[st[14]] ^ gfm3_s_box[st[3]]; + dt[ 7] = gfm3_s_box[st[4]] ^ s_box[st[9]] ^ s_box[st[14]] ^ gfm2_s_box[st[3]]; + + dt[ 8] = gfm2_s_box[st[8]] ^ gfm3_s_box[st[13]] ^ s_box[st[2]] ^ s_box[st[7]]; + dt[ 9] = s_box[st[8]] ^ gfm2_s_box[st[13]] ^ gfm3_s_box[st[2]] ^ s_box[st[7]]; + dt[10] = s_box[st[8]] ^ s_box[st[13]] ^ gfm2_s_box[st[2]] ^ gfm3_s_box[st[7]]; + dt[11] = gfm3_s_box[st[8]] ^ s_box[st[13]] ^ s_box[st[2]] ^ gfm2_s_box[st[7]]; + + dt[12] = gfm2_s_box[st[12]] ^ gfm3_s_box[st[1]] ^ s_box[st[6]] ^ s_box[st[11]]; + dt[13] = s_box[st[12]] ^ gfm2_s_box[st[1]] ^ gfm3_s_box[st[6]] ^ s_box[st[11]]; + dt[14] = s_box[st[12]] ^ s_box[st[1]] ^ gfm2_s_box[st[6]] ^ gfm3_s_box[st[11]]; + dt[15] = gfm3_s_box[st[12]] ^ s_box[st[1]] ^ s_box[st[6]] ^ gfm2_s_box[st[11]]; + } + +#if defined( VERSION_1 ) + static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] ) + { uint_8t st[N_BLOCK]; + block16_copy(st, dt); +#else + static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] ) + { +#endif + dt[ 0] = inv_s_box[gfmul_e[st[ 0]] ^ gfmul_b[st[ 1]] ^ gfmul_d[st[ 2]] ^ gfmul_9[st[ 3]]]; + dt[ 5] = inv_s_box[gfmul_9[st[ 0]] ^ gfmul_e[st[ 1]] ^ gfmul_b[st[ 2]] ^ gfmul_d[st[ 3]]]; + dt[10] = inv_s_box[gfmul_d[st[ 0]] ^ gfmul_9[st[ 1]] ^ gfmul_e[st[ 2]] ^ gfmul_b[st[ 3]]]; + dt[15] = inv_s_box[gfmul_b[st[ 0]] ^ gfmul_d[st[ 1]] ^ gfmul_9[st[ 2]] ^ gfmul_e[st[ 3]]]; + + dt[ 4] = inv_s_box[gfmul_e[st[ 4]] ^ gfmul_b[st[ 5]] ^ gfmul_d[st[ 6]] ^ gfmul_9[st[ 7]]]; + dt[ 9] = inv_s_box[gfmul_9[st[ 4]] ^ gfmul_e[st[ 5]] ^ gfmul_b[st[ 6]] ^ gfmul_d[st[ 7]]]; + dt[14] = inv_s_box[gfmul_d[st[ 4]] ^ gfmul_9[st[ 5]] ^ gfmul_e[st[ 6]] ^ gfmul_b[st[ 7]]]; + dt[ 3] = inv_s_box[gfmul_b[st[ 4]] ^ gfmul_d[st[ 5]] ^ gfmul_9[st[ 6]] ^ gfmul_e[st[ 7]]]; + + dt[ 8] = inv_s_box[gfmul_e[st[ 8]] ^ gfmul_b[st[ 9]] ^ gfmul_d[st[10]] ^ gfmul_9[st[11]]]; + dt[13] = inv_s_box[gfmul_9[st[ 8]] ^ gfmul_e[st[ 9]] ^ gfmul_b[st[10]] ^ gfmul_d[st[11]]]; + dt[ 2] = inv_s_box[gfmul_d[st[ 8]] ^ gfmul_9[st[ 9]] ^ gfmul_e[st[10]] ^ gfmul_b[st[11]]]; + dt[ 7] = inv_s_box[gfmul_b[st[ 8]] ^ gfmul_d[st[ 9]] ^ gfmul_9[st[10]] ^ gfmul_e[st[11]]]; + + dt[12] = inv_s_box[gfmul_e[st[12]] ^ gfmul_b[st[13]] ^ gfmul_d[st[14]] ^ gfmul_9[st[15]]]; + dt[ 1] = inv_s_box[gfmul_9[st[12]] ^ gfmul_e[st[13]] ^ gfmul_b[st[14]] ^ gfmul_d[st[15]]]; + dt[ 6] = inv_s_box[gfmul_d[st[12]] ^ gfmul_9[st[13]] ^ gfmul_e[st[14]] ^ gfmul_b[st[15]]]; + dt[11] = inv_s_box[gfmul_b[st[12]] ^ gfmul_d[st[13]] ^ gfmul_9[st[14]] ^ gfmul_e[st[15]]]; + } + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +/* Set the cipher key for the pre-keyed version */ + +return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] ) +{ + uint_8t cc, rc, hi; + + switch( keylen ) + { + case 16: + case 128: + keylen = 16; + break; + case 24: + case 192: + keylen = 24; + break; + case 32: + keylen = 32; + break; + default: + ctx->rnd = 0; + return -1; + } + block_copy(ctx->ksch, key, keylen); + hi = (keylen + 28) << 2; + ctx->rnd = (hi >> 4) - 1; + for( cc = keylen, rc = 1; cc < hi; cc += 4 ) + { uint_8t tt, t0, t1, t2, t3; + + t0 = ctx->ksch[cc - 4]; + t1 = ctx->ksch[cc - 3]; + t2 = ctx->ksch[cc - 2]; + t3 = ctx->ksch[cc - 1]; + if( cc % keylen == 0 ) + { + tt = t0; + t0 = s_box[t1] ^ rc; + t1 = s_box[t2]; + t2 = s_box[t3]; + t3 = s_box[tt]; + rc = f2(rc); + } + else if( keylen > 24 && cc % keylen == 16 ) + { + t0 = s_box[t0]; + t1 = s_box[t1]; + t2 = s_box[t2]; + t3 = s_box[t3]; + } + tt = cc - keylen; + ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; + ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; + ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; + ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; + } + return 0; +} + +#endif + +#if defined( AES_ENC_PREKEYED ) + +/* Encrypt a single block of 16 bytes */ + +return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint_8t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch ); + + for( r = 1 ; r < ctx->rnd ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + add_round_key( s1, ctx->ksch + r * N_BLOCK); + } +#else + { uint_8t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); + } +#endif + shift_sub_rows( s1 ); + copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); + } + else + return -1; + return 0; +} + +#endif + +#if defined( AES_DEC_PREKEYED ) + +/* Decrypt a single block of 16 bytes */ + +return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint_8t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); + inv_shift_sub_rows( s1 ); + + for( r = ctx->rnd ; --r ; ) +#if defined( VERSION_1 ) + { + add_round_key( s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1 ); + } +#else + { uint_8t s2[N_BLOCK]; + copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, ctx->ksch ); + } + else + return -1; + return 0; +} + +#endif + +#if defined( AES_ENC_128_OTFK ) + +/* The 'on the fly' encryption key update for for 128 bit keys */ + +static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + k[0] ^= s_box[k[13]] ^ *rc; + k[1] ^= s_box[k[14]]; + k[2] ^= s_box[k[15]]; + k[3] ^= s_box[k[12]]; + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) +{ uint_8t s1[N_BLOCK], r, rc = 1; + + if(o_key != key) + block16_copy( o_key, key ); + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 10 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + update_encrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + } +#else + { uint_8t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_128_OTFK ) + +/* The 'on the fly' decryption key update for for 128 bit keys */ + +static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + for( cc = 12; cc > 0; cc -= 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + *rc = d2(*rc); + k[0] ^= s_box[k[13]] ^ *rc; + k[1] ^= s_box[k[14]]; + k[2] ^= s_box[k[15]]; + k[3] ^= s_box[k[12]]; +} + +/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] ) +{ + uint_8t s1[N_BLOCK], r, rc = 0x6c; + if(o_key != key) + block16_copy( o_key, key ); + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 10 ; --r ; ) +#if defined( VERSION_1 ) + { + update_decrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint_8t s2[N_BLOCK]; + update_decrypt_key_128( o_key, &rc ); + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + update_decrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_ENC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + k[0] ^= s_box[k[29]] ^ *rc; + k[1] ^= s_box[k[30]]; + k[2] ^= s_box[k[31]]; + k[3] ^= s_box[k[28]]; + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box[k[12]]; + k[17] ^= s_box[k[13]]; + k[18] ^= s_box[k[14]]; + k[19] ^= s_box[k[15]]; + + for( cc = 20; cc < 32; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ + +void aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) +{ + uint_8t s1[N_BLOCK], r, rc = 1; + if(o_key != key) + { + block16_copy( o_key, key ); + block16_copy( o_key + 16, key + 16 ); + } + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 14 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns(s1); + if( r & 1 ) + add_round_key( s1, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key ); + } + } +#else + { uint_8t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + if( r & 1 ) + copy_and_key( s1, s2, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_256( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc ) +{ uint_8t cc; + + for(cc = 28; cc > 16; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box[k[12]]; + k[17] ^= s_box[k[13]]; + k[18] ^= s_box[k[14]]; + k[19] ^= s_box[k[15]]; + + for(cc = 12; cc > 0; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + *rc = d2(*rc); + k[0] ^= s_box[k[29]] ^ *rc; + k[1] ^= s_box[k[30]]; + k[2] ^= s_box[k[31]]; + k[3] ^= s_box[k[28]]; +} + +/* Decrypt a single block of 16 bytes with 'on the fly' + 256 bit keying +*/ +void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] ) +{ + uint_8t s1[N_BLOCK], r, rc = 0x80; + + if(o_key != key) + { + block16_copy( o_key, key ); + block16_copy( o_key + 16, key + 16 ); + } + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 14 ; --r ; ) +#if defined( VERSION_1 ) + { + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key + 16 ); + } + else + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint_8t s2[N_BLOCK]; + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + copy_and_key( s2, s1, o_key + 16 ); + } + else + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, o_key ); +} + +#endif diff --git a/src/utils/crypto/aessmall.h b/src/utils/crypto/aessmall.h new file mode 100644 index 000000000..ebeb24efd --- /dev/null +++ b/src/utils/crypto/aessmall.h @@ -0,0 +1,169 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state. + */ + +#ifndef AES_H +#define AES_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* This provides speed optimisation opportunities if 32-bit word + operations are available +*/ +#if 1 +# define HAVE_UINT_32T +#endif + +#if 1 +# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ +#endif +#if 1 +# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ +#endif +#if 0 +# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ +#endif +#if 0 +# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ +#endif + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 + +typedef unsigned char uint_8t; + +typedef uint_8t return_type; +typedef uint_8t length_type; +typedef uint_8t uint_type; + +typedef unsigned char uint_8t; + +typedef struct +{ uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; + uint_8t rnd; +} aes_context; + +/* The following calls are for a precomputed key schedule + + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). +*/ + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +return_type aes_set_key( const unsigned char key[], + length_type keylen, + aes_context ctx[1] ); +#endif + +#if defined( AES_ENC_PREKEYED ) + +return_type aes_encrypt( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const aes_context ctx[1] ); +#endif + +#if defined( AES_DEC_PREKEYED ) + +return_type aes_decrypt( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const aes_context ctx[1] ); +#endif + +/* The following calls are for 'on the fly' keying. In this case the + encryption and decryption keys are different. + + The encryption subroutines take a key in an array of bytes in + key[L] where L is 16, 24 or 32 bytes for key lengths of 128, + 192, and 256 bits respectively. They then encrypts the input + data, in[] with this key and put the reult in the output array + out[]. In addition, the second key array, o_key[L], is used + to output the key that is needed by the decryption subroutine + to reverse the encryption operation. The two key arrays can + be the same array but in this case the original key will be + overwritten. + + In the same way, the decryption subroutines output keys that + can be used to reverse their effect when used for encryption. + + Only 128 and 256 bit keys are supported in these 'on the fly' + modes. +*/ + +#if defined( AES_ENC_128_OTFK ) +void aes_encrypt_128( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], + uint_8t o_key[N_BLOCK] ); +#endif + +#if defined( AES_DEC_128_OTFK ) +void aes_decrypt_128( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[N_BLOCK], + unsigned char o_key[N_BLOCK] ); +#endif + +#if defined( AES_ENC_256_OTFK ) +void aes_encrypt_256( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], + unsigned char o_key[2 * N_BLOCK] ); +#endif + +#if defined( AES_DEC_256_OTFK ) +void aes_decrypt_256( const unsigned char in[N_BLOCK], + unsigned char out[N_BLOCK], + const unsigned char key[2 * N_BLOCK], + unsigned char o_key[2 * N_BLOCK] ); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/utils/crypto/aessmall_x86.asm b/src/utils/crypto/aessmall_x86.asm new file mode 100644 index 000000000..9356a65c0 --- /dev/null +++ b/src/utils/crypto/aessmall_x86.asm @@ -0,0 +1,1444 @@ + +; --------------------------------------------------------------------------- +; Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. +; +; LICENSE TERMS +; +; The free distribution and use of this software is allowed (with or without +; changes) provided that: +; +; 1. source code distributions include the above copyright notice, this +; list of conditions and the following disclaimer; +; +; 2. binary distributions include the above copyright notice, this list +; of conditions and the following disclaimer in their documentation; +; +; 3. the name of the copyright holder is not used to endorse products +; built using this software without specific written permission. +; +; DISCLAIMER +; +; This software is provided 'as is' with no explicit or implied warranties +; in respect of its properties, including, but not limited to, correctness +; and/or fitness for purpose. +; --------------------------------------------------------------------------- +; Issue 20/12/2007 +; +; This code requires either ASM_X86_V2 or ASM_X86_V2C to be set in aesopt.h +; and the same define to be set here as well. If AES_V2C is set this file +; requires the C files aeskey.c and aestab.c for support. + +; An AES implementation for x86 processors using the YASM (or NASM) assembler. +; This is a full assembler implementation covering encryption, decryption and +; key scheduling. It uses 2k bytes of tables but its encryption and decryption +; performance is very close to that obtained using large tables. Key schedule +; expansion is slower for both encryption and decryption but this is likely to +; be offset by the much smaller load that this version places on the processor +; cache. I acknowledge the contribution made by Daniel Bernstein to aspects of +; the design of the AES round function used here. +; +; This code provides the standard AES block size (128 bits, 16 bytes) and the +; three standard AES key sizes (128, 192 and 256 bits). It has the same call +; interface as my C implementation. The ebx, esi, edi and ebp registers are +; preserved across calls but eax, ecx and edx and the artihmetic status flags +; are not. Although this is a full assembler implementation, it can be used +; in conjunction with my C code which provides faster key scheduling using +; large tables. In this case aeskey.c should be compiled with ASM_X86_V2C +; defined. It is also important that the defines below match those used in the +; C code. This code uses the VC++ register saving conentions; if it is used +; with another compiler, conventions for using and saving registers may need +; to be checked (and calling conventions). The YASM command line for the VC++ +; custom build step is: +; +; yasm -Xvc -f win32 -D -o "$(TargetDir)\$(InputName).obj" "$(InputPath)" +; +; For the cryptlib build this is (pcg): +; +; yasm -Xvc -f win32 -D ASM_X86_V2C -o aescrypt2.obj aes_x86_v2.asm +; +; where is ASM_X86_V2 or ASM_X86_V2C. The calling intefaces are: +; +; AES_RETURN aes_encrypt(const unsigned char in_blk[], +; unsigned char out_blk[], const aes_encrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt(const unsigned char in_blk[], +; unsigned char out_blk[], const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_encrypt_key(const unsigned char key[], +; const aes_encrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt_key(const unsigned char key[], +; const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_encrypt_key(const unsigned char key[], +; unsigned int len, const aes_decrypt_ctx cx[1]); +; +; AES_RETURN aes_decrypt_key(const unsigned char key[], +; unsigned int len, const aes_decrypt_ctx cx[1]); +; +; where is 128, 102 or 256. In the last two calls the length can be in +; either bits or bytes. + +; The DLL interface must use the _stdcall convention in which the number +; of bytes of parameter space is added after an @ to the sutine's name. +; We must also remove our parameters from the stack before return (see +; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version. + +; +; Adapted for TrueCrypt by the TrueCrypt Foundation: +; - All tables generated at run-time +; - Adapted for 16-bit environment +; + +CPU 386 +USE16 +SEGMENT _TEXT PUBLIC CLASS=CODE USE16 +SEGMENT _DATA PUBLIC CLASS=DATA USE16 + +GROUP DGROUP _TEXT _DATA + +extern _aes_dec_tab ; Aestab.c +extern _aes_enc_tab + +; %define DLL_EXPORT + +; The size of the code can be reduced by using functions for the encryption +; and decryption rounds in place of macro expansion + +%define REDUCE_CODE_SIZE + +; Comment in/out the following lines to obtain the desired subroutines. These +; selections MUST match those in the C header file aes.h + +; %define AES_128 ; define if AES with 128 bit keys is needed +; %define AES_192 ; define if AES with 192 bit keys is needed +%define AES_256 ; define if AES with 256 bit keys is needed +; %define AES_VAR ; define if a variable key size is needed +%define ENCRYPTION ; define if encryption is needed +%define DECRYPTION ; define if decryption is needed +; %define AES_REV_DKS ; define if key decryption schedule is reversed + +%ifndef ASM_X86_V2C +%define ENCRYPTION_KEY_SCHEDULE ; define if encryption key expansion is needed +%define DECRYPTION_KEY_SCHEDULE ; define if decryption key expansion is needed +%endif + +; The encryption key schedule has the following in memory layout where N is the +; number of rounds (10, 12 or 14): +; +; lo: | input key (round 0) | ; each round is four 32-bit words +; | encryption round 1 | +; | encryption round 2 | +; .... +; | encryption round N-1 | +; hi: | encryption round N | +; +; The decryption key schedule is normally set up so that it has the same +; layout as above by actually reversing the order of the encryption key +; schedule in memory (this happens when AES_REV_DKS is set): +; +; lo: | decryption round 0 | = | encryption round N | +; | decryption round 1 | = INV_MIX_COL[ | encryption round N-1 | ] +; | decryption round 2 | = INV_MIX_COL[ | encryption round N-2 | ] +; .... .... +; | decryption round N-1 | = INV_MIX_COL[ | encryption round 1 | ] +; hi: | decryption round N | = | input key (round 0) | +; +; with rounds except the first and last modified using inv_mix_column() +; But if AES_REV_DKS is NOT set the order of keys is left as it is for +; encryption so that it has to be accessed in reverse when used for +; decryption (although the inverse mix column modifications are done) +; +; lo: | decryption round 0 | = | input key (round 0) | +; | decryption round 1 | = INV_MIX_COL[ | encryption round 1 | ] +; | decryption round 2 | = INV_MIX_COL[ | encryption round 2 | ] +; .... .... +; | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ] +; hi: | decryption round N | = | encryption round N | +; +; This layout is faster when the assembler key scheduling provided here +; is used. +; +; End of user defines + +%ifdef AES_VAR +%ifndef AES_128 +%define AES_128 +%endif +%ifndef AES_192 +%define AES_192 +%endif +%ifndef AES_256 +%define AES_256 +%endif +%endif + +%ifdef AES_VAR +%define KS_LENGTH 60 +%elifdef AES_256 +%define KS_LENGTH 60 +%elifdef AES_192 +%define KS_LENGTH 52 +%else +%define KS_LENGTH 44 +%endif + +; These macros implement stack based local variables + +%macro save 2 + mov [esp+4*%1],%2 +%endmacro + +%macro restore 2 + mov %1,[esp+4*%2] +%endmacro + +%ifdef REDUCE_CODE_SIZE + %macro mf_call 1 + call %1 + %endmacro +%else + %macro mf_call 1 + %1 + %endmacro +%endif + +; the DLL has to implement the _stdcall calling interface on return +; In this case we have to take our parameters (3 4-byte pointers) +; off the stack + +%define parms 12 + +%macro do_name 1-2 parms +%ifndef DLL_EXPORT + global %1 +%1: +%else + global %1@%2 + export %1@%2 +%1@%2: +%endif +%endmacro + +%macro do_call 1-2 parms +%ifndef DLL_EXPORT + call %1 + add esp,%2 +%else + call %1@%2 +%endif +%endmacro + +%macro do_exit 0-1 parms +%ifdef DLL_EXPORT + ret %1 +%else + ret +%endif +%endmacro + +; finite field multiplies by {02}, {04} and {08} + +%define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) +%define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) +%define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) + +; finite field multiplies required in table generation + +%define f3(x) (f2(x) ^ x) +%define f9(x) (f8(x) ^ x) +%define fb(x) (f8(x) ^ f2(x) ^ x) +%define fd(x) (f8(x) ^ f4(x) ^ x) +%define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +%define etab_0(x) [_aes_enc_tab+4+8*x] +%define etab_1(x) [_aes_enc_tab+3+8*x] +%define etab_2(x) [_aes_enc_tab+2+8*x] +%define etab_3(x) [_aes_enc_tab+1+8*x] +%define etab_b(x) byte [_aes_enc_tab+1+8*x] ; used with movzx for 0x000000xx +%define etab_w(x) word [_aes_enc_tab+8*x] ; used with movzx for 0x0000xx00 + +%define btab_0(x) [_aes_enc_tab+6+8*x] +%define btab_1(x) [_aes_enc_tab+5+8*x] +%define btab_2(x) [_aes_enc_tab+4+8*x] +%define btab_3(x) [_aes_enc_tab+3+8*x] + +; ROUND FUNCTION. Build column[2] on ESI and column[3] on EDI that have the +; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX. +; +; Input: +; +; EAX column[0] +; EBX column[1] +; ECX column[2] +; EDX column[3] +; ESI column key[round][2] +; EDI column key[round][3] +; EBP scratch +; +; Output: +; +; EBP column[0] unkeyed +; EBX column[1] unkeyed +; ESI column[2] keyed +; EDI column[3] keyed +; EAX scratch +; ECX scratch +; EDX scratch + +%macro rnd_fun 2 + + rol ebx,16 + %1 esi, cl, 0, ebp + %1 esi, dh, 1, ebp + %1 esi, bh, 3, ebp + %1 edi, dl, 0, ebp + %1 edi, ah, 1, ebp + %1 edi, bl, 2, ebp + %2 ebp, al, 0, ebp + shr ebx,16 + and eax,0xffff0000 + or eax,ebx + shr edx,16 + %1 ebp, ah, 1, ebx + %1 ebp, dh, 3, ebx + %2 ebx, dl, 2, ebx + %1 ebx, ch, 1, edx + %1 ebx, al, 0, edx + shr eax,16 + shr ecx,16 + %1 ebp, cl, 2, edx + %1 edi, ch, 3, edx + %1 esi, al, 2, edx + %1 ebx, ah, 3, edx + +%endmacro + +; Basic MOV and XOR Operations for normal rounds + +%macro nr_xor 4 + movzx %4,%2 + xor %1,etab_%3(%4) +%endmacro + +%macro nr_mov 4 + movzx %4,%2 + mov %1,etab_%3(%4) +%endmacro + +; Basic MOV and XOR Operations for last round + +%if 1 + + %macro lr_xor 4 + movzx %4,%2 + movzx %4,etab_b(%4) + %if %3 != 0 + shl %4,8*%3 + %endif + xor %1,%4 + %endmacro + + %macro lr_mov 4 + movzx %4,%2 + movzx %1,etab_b(%4) + %if %3 != 0 + shl %1,8*%3 + %endif + %endmacro + +%else ; less effective but worth leaving as an option + + %macro lr_xor 4 + movzx %4,%2 + mov %4,btab_%3(%4) + and %4,0x000000ff << 8 * %3 + xor %1,%4 + %endmacro + + %macro lr_mov 4 + movzx %4,%2 + mov %1,btab_%3(%4) + and %1,0x000000ff << 8 * %3 + %endmacro + +%endif + +; Apply S-Box to the 4 bytes in a 32-bit word and rotate byte positions + +%ifdef REDUCE_CODE_SIZE + +l3s_col: + movzx ecx,al ; in eax + movzx ecx, etab_b(ecx) ; out eax + xor edx,ecx ; scratch ecx,edx + movzx ecx,ah + movzx ecx, etab_b(ecx) + shl ecx,8 + xor edx,ecx + shr eax,16 + movzx ecx,al + movzx ecx, etab_b(ecx) + shl ecx,16 + xor edx,ecx + movzx ecx,ah + movzx ecx, etab_b(ecx) + shl ecx,24 + xor edx,ecx + mov eax,edx + ret + +%else + +%macro l3s_col 0 + + movzx ecx,al ; in eax + movzx ecx, etab_b(ecx) ; out eax + xor edx,ecx ; scratch ecx,edx + movzx ecx,ah + movzx ecx, etab_b(ecx) + shl ecx,8 + xor edx,ecx + shr eax,16 + movzx ecx,al + movzx ecx, etab_b(ecx) + shl ecx,16 + xor edx,ecx + movzx ecx,ah + movzx ecx, etab_b(ecx) + shl ecx,24 + xor edx,ecx + mov eax,edx + +%endmacro + +%endif + +; offsets to parameters + +in_blk equ 2 ; input byte array address parameter +out_blk equ 4 ; output byte array address parameter +ctx equ 6 ; AES context structure +stk_spc equ 20 ; stack space + +%ifdef ENCRYPTION + +; %define ENCRYPTION_TABLE + +%ifdef REDUCE_CODE_SIZE + +enc_round: + sub sp, 2 + add ebp,16 + save 1,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + rnd_fun nr_xor, nr_mov + + mov eax,ebp + mov ecx,esi + mov edx,edi + restore ebp,1 + xor eax,[ebp] + xor ebx,[ebp+4] + add sp, 2 + ret + +%else + +%macro enc_round 0 + + add ebp,16 + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + rnd_fun nr_xor, nr_mov + + mov eax,ebp + mov ecx,esi + mov edx,edi + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + +%endif + +%macro enc_last_round 0 + + add ebp,16 + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + rnd_fun lr_xor, lr_mov + + mov eax,ebp + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + + section _TEXT + +; AES Encryption Subroutine + + do_name _aes_encrypt,12 + + mov ax, sp + movzx esp, ax + + sub esp,stk_spc + mov [esp+16],ebp + mov [esp+12],ebx + mov [esp+ 8],esi + mov [esp+ 4],edi + + movzx esi,word [esp+in_blk+stk_spc] ; input pointer + mov eax,[esi ] + mov ebx,[esi+ 4] + mov ecx,[esi+ 8] + mov edx,[esi+12] + + movzx ebp,word [esp+ctx+stk_spc] ; key pointer + movzx edi,byte [ebp+4*KS_LENGTH] + xor eax,[ebp ] + xor ebx,[ebp+ 4] + xor ecx,[ebp+ 8] + xor edx,[ebp+12] + +; determine the number of rounds + +%ifndef AES_256 + cmp edi,10*16 + je .3 + cmp edi,12*16 + je .2 + cmp edi,14*16 + je .1 + mov eax,-1 + jmp .5 +%endif + +.1: mf_call enc_round + mf_call enc_round +.2: mf_call enc_round + mf_call enc_round +.3: mf_call enc_round + mf_call enc_round + mf_call enc_round + mf_call enc_round + mf_call enc_round + mf_call enc_round + mf_call enc_round + mf_call enc_round + mf_call enc_round + enc_last_round + + movzx edx,word [esp+out_blk+stk_spc] + mov [edx],eax + mov [edx+4],ebx + mov [edx+8],esi + mov [edx+12],edi + xor eax,eax + +.5: mov ebp,[esp+16] + mov ebx,[esp+12] + mov esi,[esp+ 8] + mov edi,[esp+ 4] + add esp,stk_spc + do_exit 12 + +%endif + +%macro f_key 2 + + push ecx + push edx + mov edx,esi + ror eax,8 + mf_call l3s_col + mov esi,eax + pop edx + pop ecx + xor esi,rc_val + + mov [ebp+%1*%2],esi + xor edi,esi + mov [ebp+%1*%2+4],edi + xor ecx,edi + mov [ebp+%1*%2+8],ecx + xor edx,ecx + mov [ebp+%1*%2+12],edx + mov eax,edx + +%if %2 == 24 + +%if %1 < 7 + xor eax,[ebp+%1*%2+16-%2] + mov [ebp+%1*%2+16],eax + xor eax,[ebp+%1*%2+20-%2] + mov [ebp+%1*%2+20],eax +%endif + +%elif %2 == 32 + +%if %1 < 6 + push ecx + push edx + mov edx,[ebp+%1*%2+16-%2] + mf_call l3s_col + pop edx + pop ecx + mov [ebp+%1*%2+16],eax + xor eax,[ebp+%1*%2+20-%2] + mov [ebp+%1*%2+20],eax + xor eax,[ebp+%1*%2+24-%2] + mov [ebp+%1*%2+24],eax + xor eax,[ebp+%1*%2+28-%2] + mov [ebp+%1*%2+28],eax +%endif + +%endif + +%assign rc_val f2(rc_val) + +%endmacro + +%ifdef ENCRYPTION_KEY_SCHEDULE + +%ifdef AES_128 + +%ifndef ENCRYPTION_TABLE +; %define ENCRYPTION_TABLE +%endif + +%assign rc_val 1 + + do_name _aes_encrypt_key128,8 + + push ebp + push ebx + push esi + push edi + + mov ebp,[esp+24] + mov [ebp+4*KS_LENGTH],dword 10*16 + mov ebx,[esp+20] + + mov esi,[ebx] + mov [ebp],esi + mov edi,[ebx+4] + mov [ebp+4],edi + mov ecx,[ebx+8] + mov [ebp+8],ecx + mov edx,[ebx+12] + mov [ebp+12],edx + add ebp,16 + mov eax,edx + + f_key 0,16 ; 11 * 4 = 44 unsigned longs + f_key 1,16 ; 4 + 4 * 10 generated = 44 + f_key 2,16 + f_key 3,16 + f_key 4,16 + f_key 5,16 + f_key 6,16 + f_key 7,16 + f_key 8,16 + f_key 9,16 + + pop edi + pop esi + pop ebx + pop ebp + xor eax,eax + do_exit 8 + +%endif + +%ifdef AES_192 + +%ifndef ENCRYPTION_TABLE +; %define ENCRYPTION_TABLE +%endif + +%assign rc_val 1 + + do_name _aes_encrypt_key192,8 + + push ebp + push ebx + push esi + push edi + + mov ebp,[esp+24] + mov [ebp+4*KS_LENGTH],dword 12 * 16 + mov ebx,[esp+20] + + mov esi,[ebx] + mov [ebp],esi + mov edi,[ebx+4] + mov [ebp+4],edi + mov ecx,[ebx+8] + mov [ebp+8],ecx + mov edx,[ebx+12] + mov [ebp+12],edx + mov eax,[ebx+16] + mov [ebp+16],eax + mov eax,[ebx+20] + mov [ebp+20],eax + add ebp,24 + + f_key 0,24 ; 13 * 4 = 52 unsigned longs + f_key 1,24 ; 6 + 6 * 8 generated = 54 + f_key 2,24 + f_key 3,24 + f_key 4,24 + f_key 5,24 + f_key 6,24 + f_key 7,24 + + pop edi + pop esi + pop ebx + pop ebp + xor eax,eax + do_exit 8 + +%endif + +%ifdef AES_256 + +%ifndef ENCRYPTION_TABLE +; %define ENCRYPTION_TABLE +%endif + +%assign rc_val 1 + + do_name _aes_encrypt_key256,8 + + mov ax, sp + movzx esp, ax + + push ebp + push ebx + push esi + push edi + + movzx ebp, word [esp+20] ; ks + mov [ebp+4*KS_LENGTH],dword 14 * 16 + movzx ebx, word [esp+18] ; key + + mov esi,[ebx] + mov [ebp],esi + mov edi,[ebx+4] + mov [ebp+4],edi + mov ecx,[ebx+8] + mov [ebp+8],ecx + mov edx,[ebx+12] + mov [ebp+12],edx + mov eax,[ebx+16] + mov [ebp+16],eax + mov eax,[ebx+20] + mov [ebp+20],eax + mov eax,[ebx+24] + mov [ebp+24],eax + mov eax,[ebx+28] + mov [ebp+28],eax + add ebp,32 + + f_key 0,32 ; 15 * 4 = 60 unsigned longs + f_key 1,32 ; 8 + 8 * 7 generated = 64 + f_key 2,32 + f_key 3,32 + f_key 4,32 + f_key 5,32 + f_key 6,32 + + pop edi + pop esi + pop ebx + pop ebp + xor eax,eax + do_exit 8 + +%endif + +%ifdef AES_VAR + +%ifndef ENCRYPTION_TABLE +; %define ENCRYPTION_TABLE +%endif + + do_name _aes_encrypt_key,12 + + mov ecx,[esp+4] + mov eax,[esp+8] + mov edx,[esp+12] + push edx + push ecx + + cmp eax,16 + je .1 + cmp eax,128 + je .1 + + cmp eax,24 + je .2 + cmp eax,192 + je .2 + + cmp eax,32 + je .3 + cmp eax,256 + je .3 + mov eax,-1 + add esp,8 + do_exit 12 + +.1: do_call _aes_encrypt_key128,8 + do_exit 12 +.2: do_call _aes_encrypt_key192,8 + do_exit 12 +.3: do_call _aes_encrypt_key256,8 + do_exit 12 + +%endif + +%endif + +%ifdef ENCRYPTION_TABLE + +; S-box data - 256 entries + + section _DATA + +%define u8(x) 0, x, x, f3(x), f2(x), x, x, f3(x) + +_aes_enc_tab: + db u8(0x63),u8(0x7c),u8(0x77),u8(0x7b),u8(0xf2),u8(0x6b),u8(0x6f),u8(0xc5) + db u8(0x30),u8(0x01),u8(0x67),u8(0x2b),u8(0xfe),u8(0xd7),u8(0xab),u8(0x76) + db u8(0xca),u8(0x82),u8(0xc9),u8(0x7d),u8(0xfa),u8(0x59),u8(0x47),u8(0xf0) + db u8(0xad),u8(0xd4),u8(0xa2),u8(0xaf),u8(0x9c),u8(0xa4),u8(0x72),u8(0xc0) + db u8(0xb7),u8(0xfd),u8(0x93),u8(0x26),u8(0x36),u8(0x3f),u8(0xf7),u8(0xcc) + db u8(0x34),u8(0xa5),u8(0xe5),u8(0xf1),u8(0x71),u8(0xd8),u8(0x31),u8(0x15) + db u8(0x04),u8(0xc7),u8(0x23),u8(0xc3),u8(0x18),u8(0x96),u8(0x05),u8(0x9a) + db u8(0x07),u8(0x12),u8(0x80),u8(0xe2),u8(0xeb),u8(0x27),u8(0xb2),u8(0x75) + db u8(0x09),u8(0x83),u8(0x2c),u8(0x1a),u8(0x1b),u8(0x6e),u8(0x5a),u8(0xa0) + db u8(0x52),u8(0x3b),u8(0xd6),u8(0xb3),u8(0x29),u8(0xe3),u8(0x2f),u8(0x84) + db u8(0x53),u8(0xd1),u8(0x00),u8(0xed),u8(0x20),u8(0xfc),u8(0xb1),u8(0x5b) + db u8(0x6a),u8(0xcb),u8(0xbe),u8(0x39),u8(0x4a),u8(0x4c),u8(0x58),u8(0xcf) + db u8(0xd0),u8(0xef),u8(0xaa),u8(0xfb),u8(0x43),u8(0x4d),u8(0x33),u8(0x85) + db u8(0x45),u8(0xf9),u8(0x02),u8(0x7f),u8(0x50),u8(0x3c),u8(0x9f),u8(0xa8) + db u8(0x51),u8(0xa3),u8(0x40),u8(0x8f),u8(0x92),u8(0x9d),u8(0x38),u8(0xf5) + db u8(0xbc),u8(0xb6),u8(0xda),u8(0x21),u8(0x10),u8(0xff),u8(0xf3),u8(0xd2) + db u8(0xcd),u8(0x0c),u8(0x13),u8(0xec),u8(0x5f),u8(0x97),u8(0x44),u8(0x17) + db u8(0xc4),u8(0xa7),u8(0x7e),u8(0x3d),u8(0x64),u8(0x5d),u8(0x19),u8(0x73) + db u8(0x60),u8(0x81),u8(0x4f),u8(0xdc),u8(0x22),u8(0x2a),u8(0x90),u8(0x88) + db u8(0x46),u8(0xee),u8(0xb8),u8(0x14),u8(0xde),u8(0x5e),u8(0x0b),u8(0xdb) + db u8(0xe0),u8(0x32),u8(0x3a),u8(0x0a),u8(0x49),u8(0x06),u8(0x24),u8(0x5c) + db u8(0xc2),u8(0xd3),u8(0xac),u8(0x62),u8(0x91),u8(0x95),u8(0xe4),u8(0x79) + db u8(0xe7),u8(0xc8),u8(0x37),u8(0x6d),u8(0x8d),u8(0xd5),u8(0x4e),u8(0xa9) + db u8(0x6c),u8(0x56),u8(0xf4),u8(0xea),u8(0x65),u8(0x7a),u8(0xae),u8(0x08) + db u8(0xba),u8(0x78),u8(0x25),u8(0x2e),u8(0x1c),u8(0xa6),u8(0xb4),u8(0xc6) + db u8(0xe8),u8(0xdd),u8(0x74),u8(0x1f),u8(0x4b),u8(0xbd),u8(0x8b),u8(0x8a) + db u8(0x70),u8(0x3e),u8(0xb5),u8(0x66),u8(0x48),u8(0x03),u8(0xf6),u8(0x0e) + db u8(0x61),u8(0x35),u8(0x57),u8(0xb9),u8(0x86),u8(0xc1),u8(0x1d),u8(0x9e) + db u8(0xe1),u8(0xf8),u8(0x98),u8(0x11),u8(0x69),u8(0xd9),u8(0x8e),u8(0x94) + db u8(0x9b),u8(0x1e),u8(0x87),u8(0xe9),u8(0xce),u8(0x55),u8(0x28),u8(0xdf) + db u8(0x8c),u8(0xa1),u8(0x89),u8(0x0d),u8(0xbf),u8(0xe6),u8(0x42),u8(0x68) + db u8(0x41),u8(0x99),u8(0x2d),u8(0x0f),u8(0xb0),u8(0x54),u8(0xbb),u8(0x16) + +%endif + +%ifdef DECRYPTION + +; %define DECRYPTION_TABLE + +%define dtab_0(x) [_aes_dec_tab+ 8*x] +%define dtab_1(x) [_aes_dec_tab+3+8*x] +%define dtab_2(x) [_aes_dec_tab+2+8*x] +%define dtab_3(x) [_aes_dec_tab+1+8*x] +%define dtab_x(x) byte [_aes_dec_tab+7+8*x] + +%macro irn_fun 2 + + rol eax,16 + %1 esi, cl, 0, ebp + %1 esi, bh, 1, ebp + %1 esi, al, 2, ebp + %1 edi, dl, 0, ebp + %1 edi, ch, 1, ebp + %1 edi, ah, 3, ebp + %2 ebp, bl, 0, ebp + shr eax,16 + and ebx,0xffff0000 + or ebx,eax + shr ecx,16 + %1 ebp, bh, 1, eax + %1 ebp, ch, 3, eax + %2 eax, cl, 2, ecx + %1 eax, bl, 0, ecx + %1 eax, dh, 1, ecx + shr ebx,16 + shr edx,16 + %1 esi, dh, 3, ecx + %1 ebp, dl, 2, ecx + %1 eax, bh, 3, ecx + %1 edi, bl, 2, ecx + +%endmacro + +; Basic MOV and XOR Operations for normal rounds + +%macro ni_xor 4 + movzx %4,%2 + xor %1,dtab_%3(%4) +%endmacro + +%macro ni_mov 4 + movzx %4,%2 + mov %1,dtab_%3(%4) +%endmacro + +; Basic MOV and XOR Operations for last round + +%macro li_xor 4 + movzx %4,%2 + movzx %4,dtab_x(%4) +%if %3 != 0 + shl %4,8*%3 +%endif + xor %1,%4 +%endmacro + +%macro li_mov 4 + movzx %4,%2 + movzx %1,dtab_x(%4) +%if %3 != 0 + shl %1,8*%3 +%endif +%endmacro + +%ifdef REDUCE_CODE_SIZE + +dec_round: + sub sp, 2 +%ifdef AES_REV_DKS + add ebp,16 +%else + sub ebp,16 +%endif + save 1,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + irn_fun ni_xor, ni_mov + + mov ebx,ebp + mov ecx,esi + mov edx,edi + restore ebp,1 + xor eax,[ebp] + xor ebx,[ebp+4] + add sp, 2 + ret + +%else + +%macro dec_round 0 + +%ifdef AES_REV_DKS + add ebp,16 +%else + sub ebp,16 +%endif + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + irn_fun ni_xor, ni_mov + + mov ebx,ebp + mov ecx,esi + mov edx,edi + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + +%endif + +%macro dec_last_round 0 + +%ifdef AES_REV_DKS + add ebp,16 +%else + sub ebp,16 +%endif + save 0,ebp + mov esi,[ebp+8] + mov edi,[ebp+12] + + irn_fun li_xor, li_mov + + mov ebx,ebp + restore ebp,0 + xor eax,[ebp] + xor ebx,[ebp+4] + +%endmacro + + section _TEXT + +; AES Decryption Subroutine + + do_name _aes_decrypt,12 + + mov ax, sp + movzx esp, ax + + sub esp,stk_spc + mov [esp+16],ebp + mov [esp+12],ebx + mov [esp+ 8],esi + mov [esp+ 4],edi + +; input four columns and xor in first round key + + movzx esi,word [esp+in_blk+stk_spc] ; input pointer + mov eax,[esi ] + mov ebx,[esi+ 4] + mov ecx,[esi+ 8] + mov edx,[esi+12] + lea esi,[esi+16] + + movzx ebp, word [esp+ctx+stk_spc] ; key pointer + movzx edi,byte[ebp+4*KS_LENGTH] +%ifndef AES_REV_DKS ; if decryption key schedule is not reversed + lea ebp,[ebp+edi] ; we have to access it from the top down +%endif + xor eax,[ebp ] ; key schedule + xor ebx,[ebp+ 4] + xor ecx,[ebp+ 8] + xor edx,[ebp+12] + +; determine the number of rounds + +%ifndef AES_256 + cmp edi,10*16 + je .3 + cmp edi,12*16 + je .2 + cmp edi,14*16 + je .1 + mov eax,-1 + jmp .5 +%endif + +.1: mf_call dec_round + mf_call dec_round +.2: mf_call dec_round + mf_call dec_round +.3: mf_call dec_round + mf_call dec_round + mf_call dec_round + mf_call dec_round + mf_call dec_round + mf_call dec_round + mf_call dec_round + mf_call dec_round + mf_call dec_round + dec_last_round + +; move final values to the output array. + + movzx ebp,word [esp+out_blk+stk_spc] + mov [ebp],eax + mov [ebp+4],ebx + mov [ebp+8],esi + mov [ebp+12],edi + xor eax,eax + +.5: mov ebp,[esp+16] + mov ebx,[esp+12] + mov esi,[esp+ 8] + mov edi,[esp+ 4] + add esp,stk_spc + do_exit 12 + +%endif + +%ifdef REDUCE_CODE_SIZE + +inv_mix_col: + movzx ecx,dl ; input eax, edx + movzx ecx,etab_b(ecx) ; output eax + mov eax,dtab_0(ecx) ; used ecx + movzx ecx,dh + shr edx,16 + movzx ecx,etab_b(ecx) + xor eax,dtab_1(ecx) + movzx ecx,dl + movzx ecx,etab_b(ecx) + xor eax,dtab_2(ecx) + movzx ecx,dh + movzx ecx,etab_b(ecx) + xor eax,dtab_3(ecx) + ret + +%else + +%macro inv_mix_col 0 + + movzx ecx,dl ; input eax, edx + movzx ecx,etab_b(ecx) ; output eax + mov eax,dtab_0(ecx) ; used ecx + movzx ecx,dh + shr edx,16 + movzx ecx,etab_b(ecx) + xor eax,dtab_1(ecx) + movzx ecx,dl + movzx ecx,etab_b(ecx) + xor eax,dtab_2(ecx) + movzx ecx,dh + movzx ecx,etab_b(ecx) + xor eax,dtab_3(ecx) + +%endmacro + +%endif + +%ifdef DECRYPTION_KEY_SCHEDULE + +%ifdef AES_128 + +%ifndef DECRYPTION_TABLE +; %define DECRYPTION_TABLE +%endif + + do_name _aes_decrypt_key128,8 + + push ebp + push ebx + push esi + push edi + mov eax,[esp+24] ; context + mov edx,[esp+20] ; key + push eax + push edx + do_call _aes_encrypt_key128,8 ; generate expanded encryption key + mov eax,10*16 + mov esi,[esp+24] ; pointer to first round key + lea edi,[esi+eax] ; pointer to last round key + add esi,32 + ; the inverse mix column transformation + mov edx,[esi-16] ; needs to be applied to all round keys + mf_call inv_mix_col ; except first and last. Hence start by + mov [esi-16],eax ; transforming the four sub-keys in the + mov edx,[esi-12] ; second round key + mf_call inv_mix_col + mov [esi-12],eax ; transformations for subsequent rounds + mov edx,[esi-8] ; can then be made more efficient by + mf_call inv_mix_col ; noting that for three of the four sub-keys + mov [esi-8],eax ; in the encryption round key ek[r]: + mov edx,[esi-4] ; + mf_call inv_mix_col ; ek[r][n] = ek[r][n-1] ^ ek[r-1][n] + mov [esi-4],eax ; + ; where n is 1..3. Hence the corresponding +.0: mov edx,[esi] ; subkeys in the decryption round key dk[r] + mf_call inv_mix_col ; also obey since inv_mix_col is linear in + mov [esi],eax ; GF(256): + xor eax,[esi-12] ; + mov [esi+4],eax ; dk[r][n] = dk[r][n-1] ^ dk[r-1][n] + xor eax,[esi-8] ; + mov [esi+8],eax ; So we only need one inverse mix column + xor eax,[esi-4] ; operation (n = 0) for each four word cycle + mov [esi+12],eax ; in the expanded key. + add esi,16 + cmp edi,esi + jg .0 + jmp dec_end + +%endif + +%ifdef AES_192 + +%ifndef DECRYPTION_TABLE +; %define DECRYPTION_TABLE +%endif + + do_name _aes_decrypt_key192,8 + + push ebp + push ebx + push esi + push edi + mov eax,[esp+24] ; context + mov edx,[esp+20] ; key + push eax + push edx + do_call _aes_encrypt_key192,8 ; generate expanded encryption key + mov eax,12*16 + mov esi,[esp+24] ; first round key + lea edi,[esi+eax] ; last round key + add esi,48 ; the first 6 words are the key, of + ; which the top 2 words are part of + mov edx,[esi-32] ; the second round key and hence + mf_call inv_mix_col ; need to be modified. After this we + mov [esi-32],eax ; need to do a further six values prior + mov edx,[esi-28] ; to using a more efficient technique + mf_call inv_mix_col ; based on: + mov [esi-28],eax ; + ; dk[r][n] = dk[r][n-1] ^ dk[r-1][n] + mov edx,[esi-24] ; + mf_call inv_mix_col ; for n = 1 .. 5 where the key expansion + mov [esi-24],eax ; cycle is now 6 words long + mov edx,[esi-20] + mf_call inv_mix_col + mov [esi-20],eax + mov edx,[esi-16] + mf_call inv_mix_col + mov [esi-16],eax + mov edx,[esi-12] + mf_call inv_mix_col + mov [esi-12],eax + mov edx,[esi-8] + mf_call inv_mix_col + mov [esi-8],eax + mov edx,[esi-4] + mf_call inv_mix_col + mov [esi-4],eax + +.0: mov edx,[esi] ; the expanded key is 13 * 4 = 44 32-bit words + mf_call inv_mix_col ; of which 11 * 4 = 44 have to be modified + mov [esi],eax ; using inv_mix_col. We have already done 8 + xor eax,[esi-20] ; of these so 36 are left - hence we need + mov [esi+4],eax ; exactly 6 loops of six here + xor eax,[esi-16] + mov [esi+8],eax + xor eax,[esi-12] + mov [esi+12],eax + xor eax,[esi-8] + mov [esi+16],eax + xor eax,[esi-4] + mov [esi+20],eax + add esi,24 + cmp edi,esi + jg .0 + jmp dec_end + +%endif + +%ifdef AES_256 + +%ifndef DECRYPTION_TABLE +; %define DECRYPTION_TABLE +%endif + + do_name _aes_decrypt_key256,8 + + mov ax, sp + movzx esp, ax + push ebp + push ebx + push esi + push edi + + movzx eax, word [esp+20] ; ks + movzx edx, word [esp+18] ; key + push ax + push dx + do_call _aes_encrypt_key256,4 ; generate expanded encryption key + mov eax,14*16 + movzx esi, word [esp+20] ; ks + lea edi,[esi+eax] + add esi,64 + + mov edx,[esi-48] ; the primary key is 8 words, of which + mf_call inv_mix_col ; the top four require modification + mov [esi-48],eax + mov edx,[esi-44] + mf_call inv_mix_col + mov [esi-44],eax + mov edx,[esi-40] + mf_call inv_mix_col + mov [esi-40],eax + mov edx,[esi-36] + mf_call inv_mix_col + mov [esi-36],eax + + mov edx,[esi-32] ; the encryption key expansion cycle is + mf_call inv_mix_col ; now eight words long so we need to + mov [esi-32],eax ; start by doing one complete block + mov edx,[esi-28] + mf_call inv_mix_col + mov [esi-28],eax + mov edx,[esi-24] + mf_call inv_mix_col + mov [esi-24],eax + mov edx,[esi-20] + mf_call inv_mix_col + mov [esi-20],eax + mov edx,[esi-16] + mf_call inv_mix_col + mov [esi-16],eax + mov edx,[esi-12] + mf_call inv_mix_col + mov [esi-12],eax + mov edx,[esi-8] + mf_call inv_mix_col + mov [esi-8],eax + mov edx,[esi-4] + mf_call inv_mix_col + mov [esi-4],eax + +.0: mov edx,[esi] ; we can now speed up the remaining + mf_call inv_mix_col ; rounds by using the technique + mov [esi],eax ; outlined earlier. But note that + xor eax,[esi-28] ; there is one extra inverse mix + mov [esi+4],eax ; column operation as the 256 bit + xor eax,[esi-24] ; key has an extra non-linear step + mov [esi+8],eax ; for the midway element. + xor eax,[esi-20] + mov [esi+12],eax ; the expanded key is 15 * 4 = 60 + mov edx,[esi+16] ; 32-bit words of which 52 need to + mf_call inv_mix_col ; be modified. We have already done + mov [esi+16],eax ; 12 so 40 are left - which means + xor eax,[esi-12] ; that we need exactly 5 loops of 8 + mov [esi+20],eax + xor eax,[esi-8] + mov [esi+24],eax + xor eax,[esi-4] + mov [esi+28],eax + add esi,32 + cmp edi,esi + jg .0 + +%endif + +dec_end: + +%ifdef AES_REV_DKS + + movzx esi,word [esp+20] ; this reverses the order of the +.1: mov eax,[esi] ; round keys if required + mov ebx,[esi+4] + mov ebp,[edi] + mov edx,[edi+4] + mov [esi],ebp + mov [esi+4],edx + mov [edi],eax + mov [edi+4],ebx + + mov eax,[esi+8] + mov ebx,[esi+12] + mov ebp,[edi+8] + mov edx,[edi+12] + mov [esi+8],ebp + mov [esi+12],edx + mov [edi+8],eax + mov [edi+12],ebx + + add esi,16 + sub edi,16 + cmp edi,esi + jg .1 + +%endif + + pop edi + pop esi + pop ebx + pop ebp + xor eax,eax + do_exit 8 + +%ifdef AES_VAR + + do_name _aes_decrypt_key,12 + + mov ecx,[esp+4] + mov eax,[esp+8] + mov edx,[esp+12] + push edx + push ecx + + cmp eax,16 + je .1 + cmp eax,128 + je .1 + + cmp eax,24 + je .2 + cmp eax,192 + je .2 + + cmp eax,32 + je .3 + cmp eax,256 + je .3 + mov eax,-1 + add esp,8 + do_exit 12 + +.1: do_call _aes_decrypt_key128,8 + do_exit 12 +.2: do_call _aes_decrypt_key192,8 + do_exit 12 +.3: do_call _aes_decrypt_key256,8 + do_exit 12 + +%endif + +%endif + +%ifdef DECRYPTION_TABLE + +; Inverse S-box data - 256 entries + + section _DATA + +%define v8(x) fe(x), f9(x), fd(x), fb(x), fe(x), f9(x), fd(x), x + +_aes_dec_tab: + db v8(0x52),v8(0x09),v8(0x6a),v8(0xd5),v8(0x30),v8(0x36),v8(0xa5),v8(0x38) + db v8(0xbf),v8(0x40),v8(0xa3),v8(0x9e),v8(0x81),v8(0xf3),v8(0xd7),v8(0xfb) + db v8(0x7c),v8(0xe3),v8(0x39),v8(0x82),v8(0x9b),v8(0x2f),v8(0xff),v8(0x87) + db v8(0x34),v8(0x8e),v8(0x43),v8(0x44),v8(0xc4),v8(0xde),v8(0xe9),v8(0xcb) + db v8(0x54),v8(0x7b),v8(0x94),v8(0x32),v8(0xa6),v8(0xc2),v8(0x23),v8(0x3d) + db v8(0xee),v8(0x4c),v8(0x95),v8(0x0b),v8(0x42),v8(0xfa),v8(0xc3),v8(0x4e) + db v8(0x08),v8(0x2e),v8(0xa1),v8(0x66),v8(0x28),v8(0xd9),v8(0x24),v8(0xb2) + db v8(0x76),v8(0x5b),v8(0xa2),v8(0x49),v8(0x6d),v8(0x8b),v8(0xd1),v8(0x25) + db v8(0x72),v8(0xf8),v8(0xf6),v8(0x64),v8(0x86),v8(0x68),v8(0x98),v8(0x16) + db v8(0xd4),v8(0xa4),v8(0x5c),v8(0xcc),v8(0x5d),v8(0x65),v8(0xb6),v8(0x92) + db v8(0x6c),v8(0x70),v8(0x48),v8(0x50),v8(0xfd),v8(0xed),v8(0xb9),v8(0xda) + db v8(0x5e),v8(0x15),v8(0x46),v8(0x57),v8(0xa7),v8(0x8d),v8(0x9d),v8(0x84) + db v8(0x90),v8(0xd8),v8(0xab),v8(0x00),v8(0x8c),v8(0xbc),v8(0xd3),v8(0x0a) + db v8(0xf7),v8(0xe4),v8(0x58),v8(0x05),v8(0xb8),v8(0xb3),v8(0x45),v8(0x06) + db v8(0xd0),v8(0x2c),v8(0x1e),v8(0x8f),v8(0xca),v8(0x3f),v8(0x0f),v8(0x02) + db v8(0xc1),v8(0xaf),v8(0xbd),v8(0x03),v8(0x01),v8(0x13),v8(0x8a),v8(0x6b) + db v8(0x3a),v8(0x91),v8(0x11),v8(0x41),v8(0x4f),v8(0x67),v8(0xdc),v8(0xea) + db v8(0x97),v8(0xf2),v8(0xcf),v8(0xce),v8(0xf0),v8(0xb4),v8(0xe6),v8(0x73) + db v8(0x96),v8(0xac),v8(0x74),v8(0x22),v8(0xe7),v8(0xad),v8(0x35),v8(0x85) + db v8(0xe2),v8(0xf9),v8(0x37),v8(0xe8),v8(0x1c),v8(0x75),v8(0xdf),v8(0x6e) + db v8(0x47),v8(0xf1),v8(0x1a),v8(0x71),v8(0x1d),v8(0x29),v8(0xc5),v8(0x89) + db v8(0x6f),v8(0xb7),v8(0x62),v8(0x0e),v8(0xaa),v8(0x18),v8(0xbe),v8(0x1b) + db v8(0xfc),v8(0x56),v8(0x3e),v8(0x4b),v8(0xc6),v8(0xd2),v8(0x79),v8(0x20) + db v8(0x9a),v8(0xdb),v8(0xc0),v8(0xfe),v8(0x78),v8(0xcd),v8(0x5a),v8(0xf4) + db v8(0x1f),v8(0xdd),v8(0xa8),v8(0x33),v8(0x88),v8(0x07),v8(0xc7),v8(0x31) + db v8(0xb1),v8(0x12),v8(0x10),v8(0x59),v8(0x27),v8(0x80),v8(0xec),v8(0x5f) + db v8(0x60),v8(0x51),v8(0x7f),v8(0xa9),v8(0x19),v8(0xb5),v8(0x4a),v8(0x0d) + db v8(0x2d),v8(0xe5),v8(0x7a),v8(0x9f),v8(0x93),v8(0xc9),v8(0x9c),v8(0xef) + db v8(0xa0),v8(0xe0),v8(0x3b),v8(0x4d),v8(0xae),v8(0x2a),v8(0xf5),v8(0xb0) + db v8(0xc8),v8(0xeb),v8(0xbb),v8(0x3c),v8(0x83),v8(0x53),v8(0x99),v8(0x61) + db v8(0x17),v8(0x2b),v8(0x04),v8(0x7e),v8(0xba),v8(0x77),v8(0xd6),v8(0x26) + db v8(0xe1),v8(0x69),v8(0x14),v8(0x63),v8(0x55),v8(0x21),v8(0x0c),v8(0x7d) + +%endif diff --git a/src/utils/crypto/aestab.c b/src/utils/crypto/aestab.c new file mode 100644 index 000000000..07102a978 --- /dev/null +++ b/src/utils/crypto/aestab.c @@ -0,0 +1,427 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation: + - Added run-time table generator for Aes_x86_v2.asm +*/ + +#define DO_TABLES + +#include "aes.h" +#include "aesopt.h" + +#if defined(FIXED_TABLES) + +#define sb_data(w) {\ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) {\ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) {\ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + +#define rc_data(w) {\ + w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ + w(0x1b), w(0x36) } + +#define h0(x) (x) + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +#endif + +#if defined(FIXED_TABLES) || !defined(FF_TABLES) + +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#else + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) +#define fi(x) ((x) ? pow[ 255 - log[x]] : 0) + +#endif + +#include "aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(FIXED_TABLES) + +/* implemented in case of wrong call for fixed tables */ + +AES_RETURN aes_init(void) +{ + return EXIT_SUCCESS; +} + +#else /* dynamic table generation */ + +#if !defined(FF_TABLES) + +/* Generate the tables for the dynamic table option + + It will generally be sensible to use tables to compute finite + field multiplies and inverses but where memory is scarse this + code might sometimes be better. But it only has effect during + initialisation so its pretty unimportant in overall terms. +*/ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + set in x with x in the range 1 < x < 0x00000200. This form is + used so that locals within fi can be bytes rather than words +*/ + +static uint_8t hibit(const uint_32t x) +{ uint_8t r = (uint_8t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint_8t fi(const uint_8t x) +{ uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) return x; + + for(;;) + { + if(!n1) return v1; + + while(n2 >= n1) + { + n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); + } + + if(!n2) return v2; + + while(n1 >= n2) + { + n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); + } + } +} + +#endif + +/* The forward and inverse affine transformations used in the S-box */ + +#define fwd_affine(x) \ + (w = (uint_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(uint_8t)(w^(w>>8))) + +#define inv_affine(x) \ + (w = (uint_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(uint_8t)(w^(w>>8))) + +static int init = 0; + +#ifdef TC_WINDOWS_BOOT + +#pragma optimize ("l", on) +uint_8t aes_enc_tab[256][8]; +uint_8t aes_dec_tab[256][8]; + +#endif + +AES_RETURN aes_init(void) +{ uint_32t i, w; + +#ifdef TC_WINDOWS_BOOT + + if (init) + return EXIT_SUCCESS; + + for (i = 0; i < 256; ++i) + { + uint_8t x = fwd_affine(fi((uint_8t)i)); + aes_enc_tab[i][0] = 0; + aes_enc_tab[i][1] = x; + aes_enc_tab[i][2] = x; + aes_enc_tab[i][3] = f3(x); + aes_enc_tab[i][4] = f2(x); + aes_enc_tab[i][5] = x; + aes_enc_tab[i][6] = x; + aes_enc_tab[i][7] = f3(x); + + x = fi((uint_8t)inv_affine((uint_8t)i)); + aes_dec_tab[i][0] = fe(x); + aes_dec_tab[i][1] = f9(x); + aes_dec_tab[i][2] = fd(x); + aes_dec_tab[i][3] = fb(x); + aes_dec_tab[i][4] = fe(x); + aes_dec_tab[i][5] = f9(x); + aes_dec_tab[i][6] = fd(x); + aes_dec_tab[i][7] = x; + } + +#else // TC_WINDOWS_BOOT + +#if defined(FF_TABLES) + + uint_8t pow[512], log[256]; + + if(init) + return EXIT_SUCCESS; + /* log and power tables for GF(2^8) finite field with + WPOLY as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables + */ + + i = 0; w = 1; + do + { + pow[i] = (uint_8t)w; + pow[i + 255] = (uint_8t)w; + log[w] = (uint_8t)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } + while (w != 1); + +#else + if(init) + return EXIT_SUCCESS; +#endif + + for(i = 0, w = 1; i < RC_LENGTH; ++i) + { + t_set(r,c)[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) + { uint_8t b; + + b = fwd_affine(fi((uint_8t)i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#if defined( SBX_SET ) + t_set(s,box)[i] = b; +#endif + +#if defined( FT1_SET ) /* tables for a normal encryption round */ + t_set(f,n)[i] = w; +#endif +#if defined( FT4_SET ) + t_set(f,n)[0][i] = w; + t_set(f,n)[1][i] = upr(w,1); + t_set(f,n)[2][i] = upr(w,2); + t_set(f,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); + +#if defined( FL1_SET ) /* tables for last encryption round (may also */ + t_set(f,l)[i] = w; /* be used in the key schedule) */ +#endif +#if defined( FL4_SET ) + t_set(f,l)[0][i] = w; + t_set(f,l)[1][i] = upr(w,1); + t_set(f,l)[2][i] = upr(w,2); + t_set(f,l)[3][i] = upr(w,3); +#endif + +#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ + t_set(l,s)[i] = w; /* not of the required form */ +#endif +#if defined( LS4_SET ) + t_set(l,s)[0][i] = w; + t_set(l,s)[1][i] = upr(w,1); + t_set(l,s)[2][i] = upr(w,2); + t_set(l,s)[3][i] = upr(w,3); +#endif + + b = fi(inv_affine((uint_8t)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#if defined( IM1_SET ) /* tables for the inverse mix column operation */ + t_set(i,m)[b] = w; +#endif +#if defined( IM4_SET ) + t_set(i,m)[0][b] = w; + t_set(i,m)[1][b] = upr(w,1); + t_set(i,m)[2][b] = upr(w,2); + t_set(i,m)[3][b] = upr(w,3); +#endif + +#if defined( ISB_SET ) + t_set(i,box)[i] = b; +#endif +#if defined( IT1_SET ) /* tables for a normal decryption round */ + t_set(i,n)[i] = w; +#endif +#if defined( IT4_SET ) + t_set(i,n)[0][i] = w; + t_set(i,n)[1][i] = upr(w,1); + t_set(i,n)[2][i] = upr(w,2); + t_set(i,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); +#if defined( IL1_SET ) /* tables for last decryption round */ + t_set(i,l)[i] = w; +#endif +#if defined( IL4_SET ) + t_set(i,l)[0][i] = w; + t_set(i,l)[1][i] = upr(w,1); + t_set(i,l)[2][i] = upr(w,2); + t_set(i,l)[3][i] = upr(w,3); +#endif + } + +#endif // TC_WINDOWS_BOOT + + init = 1; + return EXIT_SUCCESS; +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/src/utils/crypto/aestab.h b/src/utils/crypto/aestab.h new file mode 100644 index 000000000..e52e0057d --- /dev/null +++ b/src/utils/crypto/aestab.h @@ -0,0 +1,174 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + + This file contains the code for declaring the tables needed to implement + AES. The file aesopt.h is assumed to be included before this header file. + If there are no global variables, the definitions here can be used to put + the AES tables in a structure so that a pointer can then be added to the + AES context to pass them to the AES routines that need them. If this + facility is used, the calling program has to ensure that this pointer is + managed appropriately. In particular, the value of the t_dec(in,it) item + in the table structure must be set to zero in order to ensure that the + tables are initialised. In practice the three code sequences in aeskey.c + that control the calls to aes_init() and the aes_init() routine itself will + have to be changed for a specific implementation. If global variables are + available it will generally be preferable to use them with the precomputed + FIXED_TABLES option that uses static global tables. + + The following defines can be used to control the way the tables + are defined, initialised and used in embedded environments that + require special features for these purposes + + the 't_dec' construction is used to declare fixed table arrays + the 't_set' construction is used to set fixed table values + the 't_use' construction is used to access fixed table values + + 256 byte tables: + + t_xxx(s,box) => forward S box + t_xxx(i,box) => inverse S box + + 256 32-bit word OR 4 x 256 32-bit word tables: + + t_xxx(f,n) => forward normal round + t_xxx(f,l) => forward last round + t_xxx(i,n) => inverse normal round + t_xxx(i,l) => inverse last round + t_xxx(l,s) => key schedule table + t_xxx(i,m) => key schedule table + + Other variables and tables: + + t_xxx(r,c) => the rcon table +*/ + +#if !defined( _AESTAB_H ) +#define _AESTAB_H + +#define t_dec(m,n) t_##m##n +#define t_set(m,n) t_##m##n +#define t_use(m,n) t_##m##n + +#if defined(FIXED_TABLES) +# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) +/* make tables far data to avoid using too much DGROUP space (PG) */ +# define CONST const far +# else +# define CONST const +# endif +#else +# define CONST +#endif + +#if defined(__cplusplus) +# define EXTERN extern "C" +#elif defined(DO_TABLES) +# define EXTERN +#else +# define EXTERN extern +#endif + +#if defined(_MSC_VER) && defined(TABLE_ALIGN) +#define ALIGN __declspec(align(TABLE_ALIGN)) +#else +#define ALIGN +#endif + +#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) +# define XP_DIR __cdecl +#else +# define XP_DIR +#endif + +#if defined(DO_TABLES) && defined(FIXED_TABLES) +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } +EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH] = rc_data(w0); +#else +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] +EXTERN ALIGN CONST uint_32t t_dec(r,c)[RC_LENGTH]; +#endif + +#if defined( SBX_SET ) + d_1(uint_8t, t_dec(s,box), sb_data, h0); +#endif +#if defined( ISB_SET ) + d_1(uint_8t, t_dec(i,box), isb_data, h0); +#endif + +#if defined( FT1_SET ) + d_1(uint_32t, t_dec(f,n), sb_data, u0); +#endif +#if defined( FT4_SET ) + d_4(uint_32t, t_dec(f,n), sb_data, u0, u1, u2, u3); +#endif + +#if defined( FL1_SET ) + d_1(uint_32t, t_dec(f,l), sb_data, w0); +#endif +#if defined( FL4_SET ) + d_4(uint_32t, t_dec(f,l), sb_data, w0, w1, w2, w3); +#endif + +#if defined( IT1_SET ) + d_1(uint_32t, t_dec(i,n), isb_data, v0); +#endif +#if defined( IT4_SET ) + d_4(uint_32t, t_dec(i,n), isb_data, v0, v1, v2, v3); +#endif + +#if defined( IL1_SET ) + d_1(uint_32t, t_dec(i,l), isb_data, w0); +#endif +#if defined( IL4_SET ) + d_4(uint_32t, t_dec(i,l), isb_data, w0, w1, w2, w3); +#endif + +#if defined( LS1_SET ) +#if defined( FL1_SET ) +#undef LS1_SET +#else + d_1(uint_32t, t_dec(l,s), sb_data, w0); +#endif +#endif + +#if defined( LS4_SET ) +#if defined( FL4_SET ) +#undef LS4_SET +#else + d_4(uint_32t, t_dec(l,s), sb_data, w0, w1, w2, w3); +#endif +#endif + +#if defined( IM1_SET ) + d_1(uint_32t, t_dec(i,m), mm_data, v0); +#endif +#if defined( IM4_SET ) + d_4(uint_32t, t_dec(i,m), mm_data, v0, v1, v2, v3); +#endif + +#endif diff --git a/src/utils/crypto/bf_ecb.c b/src/utils/crypto/bf_ecb.c new file mode 100644 index 000000000..8fd65d213 --- /dev/null +++ b/src/utils/crypto/bf_ecb.c @@ -0,0 +1,113 @@ +/* Deprecated/legacy */ + +/* crypto/bf/bf_ecb.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#include "blowfish.h" +#include "bf_locl.h" +#include "../common/endian.h" + +/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' + * (From LECTURE NOTES IN COIMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +char *BF_version="BlowFish part of SSLeay 0.8.2b 08-Jan-1998"; + +char *BF_options(void) + { +#ifdef BF_PTR + return("blowfish(ptr)"); +#elif defined(BF_PTR2) + return("blowfish(ptr2)"); +#else + return("blowfish(idx)"); +#endif + } + +void BF_ecb_encrypt(unsigned char *in, unsigned char *out, BF_KEY *ks, int encrypt) + { + BF_LONG l,d[2]; + + n2l(in,l); d[0]=l; + n2l(in,l); d[1]=l; + if (encrypt) + BF_encrypt(d,ks); + else + BF_decrypt(d,ks); + l=d[0]; l2n(l,out); + l=d[1]; l2n(l,out); + l=d[0]=d[1]=0; + } + +void BF_ecb_le_encrypt(unsigned char *in, unsigned char *out, BF_KEY *ks, int encrypt) +{ + BF_LONG d[2]; + + d[0] = LE32(((BF_LONG *)in)[0]); + d[1] = LE32(((BF_LONG *)in)[1]); + if (encrypt) + BF_encrypt(d,ks); + else + BF_decrypt(d,ks); + ((BF_LONG *)out)[0] = LE32(d[0]); + ((BF_LONG *)out)[1] = LE32(d[1]); + d[0]=d[1]=0; +} diff --git a/src/utils/crypto/bf_enc.c b/src/utils/crypto/bf_enc.c new file mode 100644 index 000000000..2323c648f --- /dev/null +++ b/src/utils/crypto/bf_enc.c @@ -0,0 +1,235 @@ +/* Deprecated/legacy */ + +/* crypto/bf/bf_enc.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + + +#include "blowfish.h" +#include "bf_locl.h" + +/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper' + * (From LECTURE NOTES IN COIMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION, + * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993) + */ + +#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20) +If you set BF_ROUNDS to some value other than 16 or 20, you will have +to modify the code. +#endif + +void BF_encrypt(BF_LONG *data, BF_KEY *key) + { + register BF_LONG l,r,*p,*s; + + p=key->P; + s= &(key->S[0]); + l=data[0]; + r=data[1]; + + l^=p[0]; + BF_ENC(r,l,s,p[ 1]); + BF_ENC(l,r,s,p[ 2]); + BF_ENC(r,l,s,p[ 3]); + BF_ENC(l,r,s,p[ 4]); + BF_ENC(r,l,s,p[ 5]); + BF_ENC(l,r,s,p[ 6]); + BF_ENC(r,l,s,p[ 7]); + BF_ENC(l,r,s,p[ 8]); + BF_ENC(r,l,s,p[ 9]); + BF_ENC(l,r,s,p[10]); + BF_ENC(r,l,s,p[11]); + BF_ENC(l,r,s,p[12]); + BF_ENC(r,l,s,p[13]); + BF_ENC(l,r,s,p[14]); + BF_ENC(r,l,s,p[15]); + BF_ENC(l,r,s,p[16]); +#if BF_ROUNDS == 20 + BF_ENC(r,l,s,p[17]); + BF_ENC(l,r,s,p[18]); + BF_ENC(r,l,s,p[19]); + BF_ENC(l,r,s,p[20]); +#endif + r^=p[BF_ROUNDS+1]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; + } + +#ifndef BF_DEFAULT_OPTIONS + +void BF_decrypt(BF_LONG *data, BF_KEY *key) + { + register BF_LONG l,r,*p,*s; + + p=key->P; + s= &(key->S[0]); + l=data[0]; + r=data[1]; + + l^=p[BF_ROUNDS+1]; +#if BF_ROUNDS == 20 + BF_ENC(r,l,s,p[20]); + BF_ENC(l,r,s,p[19]); + BF_ENC(r,l,s,p[18]); + BF_ENC(l,r,s,p[17]); +#endif + BF_ENC(r,l,s,p[16]); + BF_ENC(l,r,s,p[15]); + BF_ENC(r,l,s,p[14]); + BF_ENC(l,r,s,p[13]); + BF_ENC(r,l,s,p[12]); + BF_ENC(l,r,s,p[11]); + BF_ENC(r,l,s,p[10]); + BF_ENC(l,r,s,p[ 9]); + BF_ENC(r,l,s,p[ 8]); + BF_ENC(l,r,s,p[ 7]); + BF_ENC(r,l,s,p[ 6]); + BF_ENC(l,r,s,p[ 5]); + BF_ENC(r,l,s,p[ 4]); + BF_ENC(l,r,s,p[ 3]); + BF_ENC(r,l,s,p[ 2]); + BF_ENC(l,r,s,p[ 1]); + r^=p[0]; + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; + } + +void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length, BF_KEY *ks, unsigned char *iv, int encrypt) + { + register BF_LONG tin0,tin1; + register BF_LONG tout0,tout1,xor0,xor1; + register long l=length; + BF_LONG tin[2]; + + if (encrypt) + { + n2l(iv,tout0); + n2l(iv,tout1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + BF_encrypt(tin,ks); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + if (l != -8) + { + n2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + BF_encrypt(tin,ks); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + l2n(tout0,iv); + l2n(tout1,iv); + } + else + { + n2l(iv,xor0); + n2l(iv,xor1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + BF_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2n(tout0,out); + l2n(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + BF_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2nn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + l2n(xor0,iv); + l2n(xor1,iv); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +#endif diff --git a/src/utils/crypto/bf_locl.h b/src/utils/crypto/bf_locl.h new file mode 100644 index 000000000..36dc05048 --- /dev/null +++ b/src/utils/crypto/bf_locl.h @@ -0,0 +1,246 @@ +/* Deprecated/legacy */ + +/* crypto/bf/bf_locl.org */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * + * Always modify bf_locl.org since bf_locl.h is automatically generated from + * it during SSLeay configuration. + * + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + */ + +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define BF_PTR +#elif defined( __ultrix ) /* Older MIPS */ +# define BF_PTR +#elif defined( __osf1__ ) /* Alpha */ + /* None */ +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* None */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ + /* Unknown */ +#elif defined( __sgi ) /* Newer MIPS */ +# define BF_PTR +#elif defined( i386 ) /* x86 boxes, should be gcc */ +# define BF_PTR2 +#elif defined( _MSC_VER ) /* x86 boxes, Visual C */ +# define BF_PTR2 +#endif /* Systems-specific speed defines */ + +#undef c2l +#define c2l(c,l) (l =((uint32_t)(*((c)++))) , \ + l|=((uint32_t)(*((c)++)))<< 8L, \ + l|=((uint32_t)(*((c)++)))<<16L, \ + l|=((uint32_t)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((uint32_t)(*(--(c))))<<24L; \ + case 7: l2|=((uint32_t)(*(--(c))))<<16L; \ + case 6: l2|=((uint32_t)(*(--(c))))<< 8L; \ + case 5: l2|=((uint32_t)(*(--(c)))); \ + case 4: l1 =((uint32_t)(*(--(c))))<<24L; \ + case 3: l1|=((uint32_t)(*(--(c))))<<16L; \ + case 2: l1|=((uint32_t)(*(--(c))))<< 8L; \ + case 1: l1|=((uint32_t)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((uint32_t)(*(--(c)))) ; \ + case 7: l2|=((uint32_t)(*(--(c))))<< 8; \ + case 6: l2|=((uint32_t)(*(--(c))))<<16; \ + case 5: l2|=((uint32_t)(*(--(c))))<<24; \ + case 4: l1 =((uint32_t)(*(--(c)))) ; \ + case 3: l1|=((uint32_t)(*(--(c))))<< 8; \ + case 2: l1|=((uint32_t)(*(--(c))))<<16; \ + case 1: l1|=((uint32_t)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((uint32_t)(*((c)++)))<<24L, \ + l|=((uint32_t)(*((c)++)))<<16L, \ + l|=((uint32_t)(*((c)++)))<< 8L, \ + l|=((uint32_t)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* This is actually a big endian algorithm, the most significate byte + * is used to lookup array 0 */ + +/* use BF_PTR2 for intel boxes, + * BF_PTR for sparc and MIPS/SGI + * use nothing for Alpha and HP. + */ +#if !defined(BF_PTR) && !defined(BF_PTR2) +#define BF_PTR2 +#endif + +#define BF_M 0x3fc +#define BF_0 22L +#define BF_1 14L +#define BF_2 6L +#define BF_3 2L /* left shift */ + +#if defined(BF_PTR2) + +/* This is basically a special pentium verson */ +#define BF_ENC(LL,R,S,P) \ + { \ + BF_LONG t,u,v; \ + u=R>>BF_0; \ + v=R>>BF_1; \ + u&=BF_M; \ + v&=BF_M; \ + t= *(BF_LONG *)((unsigned char *)&(S[ 0])+u); \ + u=R>>BF_2; \ + t+= *(BF_LONG *)((unsigned char *)&(S[256])+v); \ + v=R<>BF_0)&BF_M))+ \ + *(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \ + *(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \ + *(BF_LONG *)((unsigned char *)&(S[768])+((R<>24L) ] + \ + S[0x0100+((int)(R>>16L)&0xff)])^ \ + S[0x0200+((int)(R>> 8L)&0xff)])+ \ + S[0x0300+((int)(R )&0xff)])&0xffffffffL; +#endif diff --git a/src/utils/crypto/bf_pi.h b/src/utils/crypto/bf_pi.h new file mode 100644 index 000000000..9a3933ed1 --- /dev/null +++ b/src/utils/crypto/bf_pi.h @@ -0,0 +1,327 @@ +/* Deprecated/legacy */ + +/* crypto/bf/bf_pi.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +static BF_KEY bf_init= { + { + 0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L, + 0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L, + 0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL, + 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L, + 0x9216d5d9L, 0x8979fb1b + },{ + 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L, + 0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L, + 0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L, + 0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL, + 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL, + 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L, + 0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL, + 0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL, + 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L, + 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L, + 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL, + 0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL, + 0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL, + 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L, + 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L, + 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L, + 0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L, + 0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L, + 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL, + 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L, + 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L, + 0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L, + 0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L, + 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL, + 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L, + 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL, + 0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL, + 0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L, + 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL, + 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L, + 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL, + 0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L, + 0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L, + 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL, + 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L, + 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L, + 0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL, + 0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L, + 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL, + 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L, + 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L, + 0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL, + 0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L, + 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L, + 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L, + 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L, + 0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L, + 0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL, + 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL, + 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L, + 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L, + 0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L, + 0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L, + 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL, + 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L, + 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL, + 0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL, + 0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L, + 0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L, + 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L, + 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L, + 0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L, + 0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L, + 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL, + 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L, + 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L, + 0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L, + 0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL, + 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L, + 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L, + 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL, + 0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L, + 0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L, + 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L, + 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL, + 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL, + 0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L, + 0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L, + 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L, + 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L, + 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL, + 0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL, + 0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL, + 0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L, + 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL, + 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L, + 0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L, + 0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL, + 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL, + 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L, + 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL, + 0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L, + 0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL, + 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL, + 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L, + 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L, + 0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L, + 0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L, + 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L, + 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L, + 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L, + 0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL, + 0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L, + 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL, + 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L, + 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L, + 0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L, + 0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L, + 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L, + 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L, + 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L, + 0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L, + 0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L, + 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L, + 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L, + 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L, + 0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L, + 0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L, + 0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L, + 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L, + 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL, + 0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL, + 0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L, + 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL, + 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L, + 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L, + 0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L, + 0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L, + 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L, + 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L, + 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL, + 0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L, + 0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L, + 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L, + 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL, + 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL, + 0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL, + 0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L, + 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L, + 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL, + 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L, + 0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL, + 0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L, + 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL, + 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L, + 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL, + 0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L, + 0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL, + 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L, + 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L, + 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL, + 0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L, + 0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L, + 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L, + 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L, + 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL, + 0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L, + 0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL, + 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L, + 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL, + 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L, + 0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL, + 0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL, + 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL, + 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L, + 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L, + 0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL, + 0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL, + 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL, + 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL, + 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL, + 0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L, + 0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L, + 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L, + 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L, + 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL, + 0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL, + 0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L, + 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L, + 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L, + 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L, + 0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L, + 0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L, + 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L, + 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L, + 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L, + 0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L, + 0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL, + 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L, + 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL, + 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L, + 0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L, + 0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL, + 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL, + 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL, + 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L, + 0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L, + 0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L, + 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L, + 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L, + 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L, + 0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L, + 0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L, + 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L, + 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L, + 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L, + 0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L, + 0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL, + 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL, + 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L, + 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL, + 0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL, + 0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL, + 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L, + 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL, + 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL, + 0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L, + 0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L, + 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L, + 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L, + 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL, + 0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL, + 0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L, + 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L, + 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L, + 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL, + 0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L, + 0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L, + 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L, + 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL, + 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L, + 0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L, + 0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L, + 0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL, + 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL, + 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L, + 0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L, + 0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L, + 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L, + 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL, + 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L, + 0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL, + 0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL, + 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L, + 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L, + 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL, + 0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L, + 0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL, + 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L, + 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL, + 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L, + 0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L, + 0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL, + 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L, + 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL, + 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L, + } + }; + diff --git a/src/utils/crypto/bf_skey.c b/src/utils/crypto/bf_skey.c new file mode 100644 index 000000000..5926293aa --- /dev/null +++ b/src/utils/crypto/bf_skey.c @@ -0,0 +1,118 @@ +/* Deprecated/legacy */ + +/* crypto/bf/bf_skey.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include "blowfish.h" +#include "bf_locl.h" +#include "bf_pi.h" + +void BF_set_key(BF_KEY *key, int len, unsigned char *data) + { + int i; + BF_LONG *p,ri,in[2]; + unsigned char *d,*end; + + + memcpy((char *)key,(char *)&bf_init,sizeof(BF_KEY)); + p=key->P; + + if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4; + + d=data; + end= &(data[len]); + for (i=0; i<(BF_ROUNDS+2); i++) + { + ri= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + ri<<=8; + ri|= *(d++); + if (d >= end) d=data; + + p[i]^=ri; + } + + in[0]=0L; + in[1]=0L; + for (i=0; i<(BF_ROUNDS+2); i+=2) + { + BF_encrypt(in,key); + p[i ]=in[0]; + p[i+1]=in[1]; + } + + p=key->S; + for (i=0; i<4*256; i+=2) + { + BF_encrypt(in,key); + p[i ]=in[0]; + p[i+1]=in[1]; + } + } diff --git a/src/utils/crypto/blowfish.h b/src/utils/crypto/blowfish.h new file mode 100644 index 000000000..e54bfefcc --- /dev/null +++ b/src/utils/crypto/blowfish.h @@ -0,0 +1,120 @@ +/* Deprecated/legacy */ + +/* crypto/bf/blowfish.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BLOWFISH_H +#define HEADER_BLOWFISH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BF_ENCRYPT 1 +#define BF_DECRYPT 0 + +/* If you make this 'unsigned int' the pointer variants will work on + * the Alpha, otherwise they will not. Strangly using the '8 byte' + * BF_LONG and the default 'non-pointer' inner loop is the best configuration + * for the Alpha */ +#define BF_LONG uint32_t + +#define BF_ROUNDS 16 +#define BF_BLOCK 8 + +typedef struct bf_key_st + { + BF_LONG P[BF_ROUNDS+2]; + BF_LONG S[4*256]; + } BF_KEY; + +#ifndef NOPROTO + +void BF_set_key(BF_KEY *key, int len, unsigned char *data); +void BF_ecb_encrypt(unsigned char *in,unsigned char *out,BF_KEY *key, int enc); +void BF_ecb_le_encrypt(unsigned char *in, unsigned char *out, BF_KEY *ks, int encrypt); +void BF_encrypt(BF_LONG *data,BF_KEY *key); +void BF_decrypt(BF_LONG *data,BF_KEY *key); +void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length, + BF_KEY *ks, unsigned char *iv, int enc); +void BF_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + BF_KEY *schedule, unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, + BF_KEY *schedule, unsigned char *ivec, int *num); +char *BF_options(void); + +#else + +void BF_set_key(); +void BF_ecb_encrypt(); +void BF_encrypt(); +void BF_decrypt(); +void BF_cbc_encrypt(); +void BF_cfb64_encrypt(); +void BF_ofb64_encrypt(); +char *BF_options(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/crypto/c_ecb.c b/src/utils/crypto/c_ecb.c new file mode 100644 index 000000000..1beb79107 --- /dev/null +++ b/src/utils/crypto/c_ecb.c @@ -0,0 +1,80 @@ +/* Deprecated/legacy */ + +/* crypto/cast/cast_ecb.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "cast.h" +#include "cast_lcl.h" + + +char *CAST_version="CAST part of SSLeay 0.8.2b 08-Jan-1998"; + +void CAST_ecb_encrypt(unsigned char *in, unsigned char *out, CAST_KEY *ks, int encrypt) + { + CAST_LONG l,d[2]; + + n2l(in,l); d[0]=l; + n2l(in,l); d[1]=l; + if (encrypt) + CAST_encrypt(d,ks); + else + CAST_decrypt(d,ks); + l=d[0]; l2n(l,out); + l=d[1]; l2n(l,out); + l=d[0]=d[1]=0; + } diff --git a/src/utils/crypto/c_enc.c b/src/utils/crypto/c_enc.c new file mode 100644 index 000000000..258bfa92c --- /dev/null +++ b/src/utils/crypto/c_enc.c @@ -0,0 +1,201 @@ +/* Deprecated/legacy */ + +/* crypto/cast/c_enc.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "cast.h" +#include "cast_lcl.h" + +void CAST_encrypt(CAST_LONG *data, CAST_KEY *key) + { + register CAST_LONG l,r,*k,t; + + k= &(key->data[0]); + l=data[0]; + r=data[1]; + + E_CAST( 0,k,l,r,+,^,-); + E_CAST( 1,k,r,l,^,-,+); + E_CAST( 2,k,l,r,-,+,^); + E_CAST( 3,k,r,l,+,^,-); + E_CAST( 4,k,l,r,^,-,+); + E_CAST( 5,k,r,l,-,+,^); + E_CAST( 6,k,l,r,+,^,-); + E_CAST( 7,k,r,l,^,-,+); + E_CAST( 8,k,l,r,-,+,^); + E_CAST( 9,k,r,l,+,^,-); + E_CAST(10,k,l,r,^,-,+); + E_CAST(11,k,r,l,-,+,^); + E_CAST(12,k,l,r,+,^,-); + E_CAST(13,k,r,l,^,-,+); + E_CAST(14,k,l,r,-,+,^); + E_CAST(15,k,r,l,+,^,-); + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; + } + +void CAST_decrypt(CAST_LONG *data, CAST_KEY *key) + { + register CAST_LONG l,r,*k,t; + + k= &(key->data[0]); + l=data[0]; + r=data[1]; + + E_CAST(15,k,l,r,+,^,-); + E_CAST(14,k,r,l,-,+,^); + E_CAST(13,k,l,r,^,-,+); + E_CAST(12,k,r,l,+,^,-); + E_CAST(11,k,l,r,-,+,^); + E_CAST(10,k,r,l,^,-,+); + E_CAST( 9,k,l,r,+,^,-); + E_CAST( 8,k,r,l,-,+,^); + E_CAST( 7,k,l,r,^,-,+); + E_CAST( 6,k,r,l,+,^,-); + E_CAST( 5,k,l,r,-,+,^); + E_CAST( 4,k,r,l,^,-,+); + E_CAST( 3,k,l,r,+,^,-); + E_CAST( 2,k,r,l,-,+,^); + E_CAST( 1,k,l,r,^,-,+); + E_CAST( 0,k,r,l,+,^,-); + + data[1]=l&0xffffffffL; + data[0]=r&0xffffffffL; + } + +void CAST_cbc_encrypt(unsigned char *in, unsigned char *out, long length, CAST_KEY *ks, unsigned char *iv, int encrypt) + { + register CAST_LONG tin0,tin1; + register CAST_LONG tout0,tout1,xor0,xor1; + register long l=length; + CAST_LONG tin[2]; + + if (encrypt) + { + n2l(iv,tout0); + n2l(iv,tout1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + CAST_encrypt(tin,ks); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + if (l != -8) + { + n2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + tin[0]=tin0; + tin[1]=tin1; + CAST_encrypt(tin,ks); + tout0=tin[0]; + tout1=tin[1]; + l2n(tout0,out); + l2n(tout1,out); + } + l2n(tout0,iv); + l2n(tout1,iv); + } + else + { + n2l(iv,xor0); + n2l(iv,xor1); + iv-=8; + for (l-=8; l>=0; l-=8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + CAST_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2n(tout0,out); + l2n(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + n2l(in,tin0); + n2l(in,tin1); + tin[0]=tin0; + tin[1]=tin1; + CAST_decrypt(tin,ks); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2nn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + l2n(xor0,iv); + l2n(xor1,iv); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } diff --git a/src/utils/crypto/c_skey.c b/src/utils/crypto/c_skey.c new file mode 100644 index 000000000..498a68b35 --- /dev/null +++ b/src/utils/crypto/c_skey.c @@ -0,0 +1,164 @@ +/* Deprecated/legacy */ + +/* crypto/cast/c_skey.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + + +#include "cast.h" +#include "cast_lcl.h" +#include "cast_s.h" + +#define CAST_exp(l,A,a,n) \ + A[n/4]=l; \ + a[n+3]=(l )&0xff; \ + a[n+2]=(l>> 8)&0xff; \ + a[n+1]=(l>>16)&0xff; \ + a[n+0]=(l>>24); + +#define S4 CAST_S_table4 +#define S5 CAST_S_table5 +#define S6 CAST_S_table6 +#define S7 CAST_S_table7 + +void CAST_set_key(CAST_KEY *key, int len, unsigned char *data) + { + CAST_LONG x[16]; + CAST_LONG z[16]; + CAST_LONG k[32]; + CAST_LONG X[4],Z[4]; + CAST_LONG l,*K; + int i; + + for (i=0; i<16; i++) x[i]=0; + if (len > 16) len=16; + for (i=0; idata[i*2]=k[i]; + key->data[i*2+1]=((k[i+16])+16)&0x1f; + } + } diff --git a/src/utils/crypto/cast.h b/src/utils/crypto/cast.h new file mode 100644 index 000000000..b1008fb9d --- /dev/null +++ b/src/utils/crypto/cast.h @@ -0,0 +1,113 @@ +/* Deprecated/legacy */ + +/* crypto/cast/cast.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CAST_H +#define HEADER_CAST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CAST_ENCRYPT 1 +#define CAST_DECRYPT 0 + +#define CAST_LONG uint32_t + +#define CAST_BLOCK 8 +#define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st + { + CAST_LONG data[32]; + } CAST_KEY; + +#ifndef NOPROTO + +void CAST_set_key(CAST_KEY *key, int len, unsigned char *data); +void CAST_ecb_encrypt(unsigned char *in,unsigned char *out,CAST_KEY *key, + int enc); +void CAST_encrypt(CAST_LONG *data,CAST_KEY *key); +void CAST_decrypt(CAST_LONG *data,CAST_KEY *key); +void CAST_cbc_encrypt(unsigned char *in, unsigned char *out, long length, + CAST_KEY *ks, unsigned char *iv, int enc); +void CAST_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + CAST_KEY *schedule, unsigned char *ivec, int *num, int enc); +void CAST_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, + CAST_KEY *schedule, unsigned char *ivec, int *num); + +#else + +void CAST_set_key(); +void CAST_ecb_encrypt(); +void CAST_encrypt(); +void CAST_decrypt(); +void CAST_cbc_encrypt(); +void CAST_cfb64_encrypt(); +void CAST_ofb64_encrypt(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/crypto/cast_lcl.h b/src/utils/crypto/cast_lcl.h new file mode 100644 index 000000000..e757c21ef --- /dev/null +++ b/src/utils/crypto/cast_lcl.h @@ -0,0 +1,225 @@ +/* Deprecated/legacy */ + +/* crypto/rc2/rc2_locl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifdef WIN32 +#include +#endif + +#undef c2l +#define c2l(c,l) (l =((uint32_t)(*((c)++))) , \ + l|=((uint32_t)(*((c)++)))<< 8L, \ + l|=((uint32_t)(*((c)++)))<<16L, \ + l|=((uint32_t)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#undef c2ln +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((uint32_t)(*(--(c))))<<24L; \ + case 7: l2|=((uint32_t)(*(--(c))))<<16L; \ + case 6: l2|=((uint32_t)(*(--(c))))<< 8L; \ + case 5: l2|=((uint32_t)(*(--(c)))); \ + case 4: l1 =((uint32_t)(*(--(c))))<<24L; \ + case 3: l1|=((uint32_t)(*(--(c))))<<16L; \ + case 2: l1|=((uint32_t)(*(--(c))))<< 8L; \ + case 1: l1|=((uint32_t)(*(--(c)))); \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#undef l2cn +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +/* NOTE - c is not incremented as per n2l */ +#define n2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((uint32_t)(*(--(c)))) ; \ + case 7: l2|=((uint32_t)(*(--(c))))<< 8; \ + case 6: l2|=((uint32_t)(*(--(c))))<<16; \ + case 5: l2|=((uint32_t)(*(--(c))))<<24; \ + case 4: l1 =((uint32_t)(*(--(c)))) ; \ + case 3: l1|=((uint32_t)(*(--(c))))<< 8; \ + case 2: l1|=((uint32_t)(*(--(c))))<<16; \ + case 1: l1|=((uint32_t)(*(--(c))))<<24; \ + } \ + } + +/* NOTE - c is not incremented as per l2n */ +#define l2nn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ + } \ + } + +#undef n2l +#define n2l(c,l) (l =((uint32_t)(*((c)++)))<<24L, \ + l|=((uint32_t)(*((c)++)))<<16L, \ + l|=((uint32_t)(*((c)++)))<< 8L, \ + l|=((uint32_t)(*((c)++)))) + +#undef l2n +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +//#if defined(WIN32) +//#define ROTL(a,n) (_lrotl(a,n)) +//#else +#define ROTL(a,n) (((a)<<(n))|((a)>>(32-(n)))) +//#endif + +#define C_M 0x3fc +#define C_0 22L +#define C_1 14L +#define C_2 6L +#define C_3 2L /* left shift */ + +/* The rotate has an extra 16 added to it to help the x86 asm */ +#if defined(CAST_PTR) +#define E_CAST(n,key,L,R,OP1,OP2,OP3) \ + { \ + int i; \ + t=key[n*2] OP1 R; \ + i=key[n*2+1]; \ + t=ROTL(t,i); \ + L^= ((( *(CAST_LONG *)((unsigned char *) \ + CAST_S_table0+((t>>C_2)&C_M)) OP2 \ + *(CAST_LONG *)((unsigned char *) \ + CAST_S_table1+((t<>C_0)&C_M))) OP1 \ + *(CAST_LONG *)((unsigned char *) \ + CAST_S_table3+((t>>C_1)&C_M))); \ + } +#elif defined(CAST_PTR2) +#define E_CAST(n,key,L,R,OP1,OP2,OP3) \ + { \ + int i; \ + CAST_LONG u,v,w; \ + w=key[n*2] OP1 R; \ + i=key[n*2+1]; \ + w=ROTL(w,i); \ + u=w>>C_2; \ + v=w<>C_0; \ + t=t OP2 *(CAST_LONG *)((unsigned char *)CAST_S_table1+v); \ + v=w>>C_1; \ + u&=C_M; \ + v&=C_M; \ + t=t OP3 *(CAST_LONG *)((unsigned char *)CAST_S_table2+u); \ + t=t OP1 *(CAST_LONG *)((unsigned char *)CAST_S_table3+v); \ + L^=t; \ + } +#else +#define E_CAST(n,key,L,R,OP1,OP2,OP3) \ + { \ + CAST_LONG a,b,c,d; \ + t=key[n*2] OP1 R; \ + t=ROTL(t,(key[n*2+1])); \ + a=CAST_S_table0[(t>> 8)&0xff]; \ + b=CAST_S_table1[(t )&0xff]; \ + c=CAST_S_table2[(t>>24)&0xff]; \ + d=CAST_S_table3[(t>>16)&0xff]; \ + L^=(((a OP2 b) OP3 c) OP1 d); \ + } +#endif + +extern CAST_LONG CAST_S_table0[256]; +extern CAST_LONG CAST_S_table1[256]; +extern CAST_LONG CAST_S_table2[256]; +extern CAST_LONG CAST_S_table3[256]; +extern CAST_LONG CAST_S_table4[256]; +extern CAST_LONG CAST_S_table5[256]; +extern CAST_LONG CAST_S_table6[256]; +extern CAST_LONG CAST_S_table7[256]; diff --git a/src/utils/crypto/cast_s.h b/src/utils/crypto/cast_s.h new file mode 100644 index 000000000..5841ee134 --- /dev/null +++ b/src/utils/crypto/cast_s.h @@ -0,0 +1,530 @@ +/* Deprecated/legacy */ + +CAST_LONG CAST_S_table0[256]={ + 0x30fb40d4,0x9fa0ff0b,0x6beccd2f,0x3f258c7a, + 0x1e213f2f,0x9c004dd3,0x6003e540,0xcf9fc949, + 0xbfd4af27,0x88bbbdb5,0xe2034090,0x98d09675, + 0x6e63a0e0,0x15c361d2,0xc2e7661d,0x22d4ff8e, + 0x28683b6f,0xc07fd059,0xff2379c8,0x775f50e2, + 0x43c340d3,0xdf2f8656,0x887ca41a,0xa2d2bd2d, + 0xa1c9e0d6,0x346c4819,0x61b76d87,0x22540f2f, + 0x2abe32e1,0xaa54166b,0x22568e3a,0xa2d341d0, + 0x66db40c8,0xa784392f,0x004dff2f,0x2db9d2de, + 0x97943fac,0x4a97c1d8,0x527644b7,0xb5f437a7, + 0xb82cbaef,0xd751d159,0x6ff7f0ed,0x5a097a1f, + 0x827b68d0,0x90ecf52e,0x22b0c054,0xbc8e5935, + 0x4b6d2f7f,0x50bb64a2,0xd2664910,0xbee5812d, + 0xb7332290,0xe93b159f,0xb48ee411,0x4bff345d, + 0xfd45c240,0xad31973f,0xc4f6d02e,0x55fc8165, + 0xd5b1caad,0xa1ac2dae,0xa2d4b76d,0xc19b0c50, + 0x882240f2,0x0c6e4f38,0xa4e4bfd7,0x4f5ba272, + 0x564c1d2f,0xc59c5319,0xb949e354,0xb04669fe, + 0xb1b6ab8a,0xc71358dd,0x6385c545,0x110f935d, + 0x57538ad5,0x6a390493,0xe63d37e0,0x2a54f6b3, + 0x3a787d5f,0x6276a0b5,0x19a6fcdf,0x7a42206a, + 0x29f9d4d5,0xf61b1891,0xbb72275e,0xaa508167, + 0x38901091,0xc6b505eb,0x84c7cb8c,0x2ad75a0f, + 0x874a1427,0xa2d1936b,0x2ad286af,0xaa56d291, + 0xd7894360,0x425c750d,0x93b39e26,0x187184c9, + 0x6c00b32d,0x73e2bb14,0xa0bebc3c,0x54623779, + 0x64459eab,0x3f328b82,0x7718cf82,0x59a2cea6, + 0x04ee002e,0x89fe78e6,0x3fab0950,0x325ff6c2, + 0x81383f05,0x6963c5c8,0x76cb5ad6,0xd49974c9, + 0xca180dcf,0x380782d5,0xc7fa5cf6,0x8ac31511, + 0x35e79e13,0x47da91d0,0xf40f9086,0xa7e2419e, + 0x31366241,0x051ef495,0xaa573b04,0x4a805d8d, + 0x548300d0,0x00322a3c,0xbf64cddf,0xba57a68e, + 0x75c6372b,0x50afd341,0xa7c13275,0x915a0bf5, + 0x6b54bfab,0x2b0b1426,0xab4cc9d7,0x449ccd82, + 0xf7fbf265,0xab85c5f3,0x1b55db94,0xaad4e324, + 0xcfa4bd3f,0x2deaa3e2,0x9e204d02,0xc8bd25ac, + 0xeadf55b3,0xd5bd9e98,0xe31231b2,0x2ad5ad6c, + 0x954329de,0xadbe4528,0xd8710f69,0xaa51c90f, + 0xaa786bf6,0x22513f1e,0xaa51a79b,0x2ad344cc, + 0x7b5a41f0,0xd37cfbad,0x1b069505,0x41ece491, + 0xb4c332e6,0x032268d4,0xc9600acc,0xce387e6d, + 0xbf6bb16c,0x6a70fb78,0x0d03d9c9,0xd4df39de, + 0xe01063da,0x4736f464,0x5ad328d8,0xb347cc96, + 0x75bb0fc3,0x98511bfb,0x4ffbcc35,0xb58bcf6a, + 0xe11f0abc,0xbfc5fe4a,0xa70aec10,0xac39570a, + 0x3f04442f,0x6188b153,0xe0397a2e,0x5727cb79, + 0x9ceb418f,0x1cacd68d,0x2ad37c96,0x0175cb9d, + 0xc69dff09,0xc75b65f0,0xd9db40d8,0xec0e7779, + 0x4744ead4,0xb11c3274,0xdd24cb9e,0x7e1c54bd, + 0xf01144f9,0xd2240eb1,0x9675b3fd,0xa3ac3755, + 0xd47c27af,0x51c85f4d,0x56907596,0xa5bb15e6, + 0x580304f0,0xca042cf1,0x011a37ea,0x8dbfaadb, + 0x35ba3e4a,0x3526ffa0,0xc37b4d09,0xbc306ed9, + 0x98a52666,0x5648f725,0xff5e569d,0x0ced63d0, + 0x7c63b2cf,0x700b45e1,0xd5ea50f1,0x85a92872, + 0xaf1fbda7,0xd4234870,0xa7870bf3,0x2d3b4d79, + 0x42e04198,0x0cd0ede7,0x26470db8,0xf881814c, + 0x474d6ad7,0x7c0c5e5c,0xd1231959,0x381b7298, + 0xf5d2f4db,0xab838653,0x6e2f1e23,0x83719c9e, + 0xbd91e046,0x9a56456e,0xdc39200c,0x20c8c571, + 0x962bda1c,0xe1e696ff,0xb141ab08,0x7cca89b9, + 0x1a69e783,0x02cc4843,0xa2f7c579,0x429ef47d, + 0x427b169c,0x5ac9f049,0xdd8f0f00,0x5c8165bf, + }; +CAST_LONG CAST_S_table1[256]={ + 0x1f201094,0xef0ba75b,0x69e3cf7e,0x393f4380, + 0xfe61cf7a,0xeec5207a,0x55889c94,0x72fc0651, + 0xada7ef79,0x4e1d7235,0xd55a63ce,0xde0436ba, + 0x99c430ef,0x5f0c0794,0x18dcdb7d,0xa1d6eff3, + 0xa0b52f7b,0x59e83605,0xee15b094,0xe9ffd909, + 0xdc440086,0xef944459,0xba83ccb3,0xe0c3cdfb, + 0xd1da4181,0x3b092ab1,0xf997f1c1,0xa5e6cf7b, + 0x01420ddb,0xe4e7ef5b,0x25a1ff41,0xe180f806, + 0x1fc41080,0x179bee7a,0xd37ac6a9,0xfe5830a4, + 0x98de8b7f,0x77e83f4e,0x79929269,0x24fa9f7b, + 0xe113c85b,0xacc40083,0xd7503525,0xf7ea615f, + 0x62143154,0x0d554b63,0x5d681121,0xc866c359, + 0x3d63cf73,0xcee234c0,0xd4d87e87,0x5c672b21, + 0x071f6181,0x39f7627f,0x361e3084,0xe4eb573b, + 0x602f64a4,0xd63acd9c,0x1bbc4635,0x9e81032d, + 0x2701f50c,0x99847ab4,0xa0e3df79,0xba6cf38c, + 0x10843094,0x2537a95e,0xf46f6ffe,0xa1ff3b1f, + 0x208cfb6a,0x8f458c74,0xd9e0a227,0x4ec73a34, + 0xfc884f69,0x3e4de8df,0xef0e0088,0x3559648d, + 0x8a45388c,0x1d804366,0x721d9bfd,0xa58684bb, + 0xe8256333,0x844e8212,0x128d8098,0xfed33fb4, + 0xce280ae1,0x27e19ba5,0xd5a6c252,0xe49754bd, + 0xc5d655dd,0xeb667064,0x77840b4d,0xa1b6a801, + 0x84db26a9,0xe0b56714,0x21f043b7,0xe5d05860, + 0x54f03084,0x066ff472,0xa31aa153,0xdadc4755, + 0xb5625dbf,0x68561be6,0x83ca6b94,0x2d6ed23b, + 0xeccf01db,0xa6d3d0ba,0xb6803d5c,0xaf77a709, + 0x33b4a34c,0x397bc8d6,0x5ee22b95,0x5f0e5304, + 0x81ed6f61,0x20e74364,0xb45e1378,0xde18639b, + 0x881ca122,0xb96726d1,0x8049a7e8,0x22b7da7b, + 0x5e552d25,0x5272d237,0x79d2951c,0xc60d894c, + 0x488cb402,0x1ba4fe5b,0xa4b09f6b,0x1ca815cf, + 0xa20c3005,0x8871df63,0xb9de2fcb,0x0cc6c9e9, + 0x0beeff53,0xe3214517,0xb4542835,0x9f63293c, + 0xee41e729,0x6e1d2d7c,0x50045286,0x1e6685f3, + 0xf33401c6,0x30a22c95,0x31a70850,0x60930f13, + 0x73f98417,0xa1269859,0xec645c44,0x52c877a9, + 0xcdff33a6,0xa02b1741,0x7cbad9a2,0x2180036f, + 0x50d99c08,0xcb3f4861,0xc26bd765,0x64a3f6ab, + 0x80342676,0x25a75e7b,0xe4e6d1fc,0x20c710e6, + 0xcdf0b680,0x17844d3b,0x31eef84d,0x7e0824e4, + 0x2ccb49eb,0x846a3bae,0x8ff77888,0xee5d60f6, + 0x7af75673,0x2fdd5cdb,0xa11631c1,0x30f66f43, + 0xb3faec54,0x157fd7fa,0xef8579cc,0xd152de58, + 0xdb2ffd5e,0x8f32ce19,0x306af97a,0x02f03ef8, + 0x99319ad5,0xc242fa0f,0xa7e3ebb0,0xc68e4906, + 0xb8da230c,0x80823028,0xdcdef3c8,0xd35fb171, + 0x088a1bc8,0xbec0c560,0x61a3c9e8,0xbca8f54d, + 0xc72feffa,0x22822e99,0x82c570b4,0xd8d94e89, + 0x8b1c34bc,0x301e16e6,0x273be979,0xb0ffeaa6, + 0x61d9b8c6,0x00b24869,0xb7ffce3f,0x08dc283b, + 0x43daf65a,0xf7e19798,0x7619b72f,0x8f1c9ba4, + 0xdc8637a0,0x16a7d3b1,0x9fc393b7,0xa7136eeb, + 0xc6bcc63e,0x1a513742,0xef6828bc,0x520365d6, + 0x2d6a77ab,0x3527ed4b,0x821fd216,0x095c6e2e, + 0xdb92f2fb,0x5eea29cb,0x145892f5,0x91584f7f, + 0x5483697b,0x2667a8cc,0x85196048,0x8c4bacea, + 0x833860d4,0x0d23e0f9,0x6c387e8a,0x0ae6d249, + 0xb284600c,0xd835731d,0xdcb1c647,0xac4c56ea, + 0x3ebd81b3,0x230eabb0,0x6438bc87,0xf0b5b1fa, + 0x8f5ea2b3,0xfc184642,0x0a036b7a,0x4fb089bd, + 0x649da589,0xa345415e,0x5c038323,0x3e5d3bb9, + 0x43d79572,0x7e6dd07c,0x06dfdf1e,0x6c6cc4ef, + 0x7160a539,0x73bfbe70,0x83877605,0x4523ecf1, + }; +CAST_LONG CAST_S_table2[256]={ + 0x8defc240,0x25fa5d9f,0xeb903dbf,0xe810c907, + 0x47607fff,0x369fe44b,0x8c1fc644,0xaececa90, + 0xbeb1f9bf,0xeefbcaea,0xe8cf1950,0x51df07ae, + 0x920e8806,0xf0ad0548,0xe13c8d83,0x927010d5, + 0x11107d9f,0x07647db9,0xb2e3e4d4,0x3d4f285e, + 0xb9afa820,0xfade82e0,0xa067268b,0x8272792e, + 0x553fb2c0,0x489ae22b,0xd4ef9794,0x125e3fbc, + 0x21fffcee,0x825b1bfd,0x9255c5ed,0x1257a240, + 0x4e1a8302,0xbae07fff,0x528246e7,0x8e57140e, + 0x3373f7bf,0x8c9f8188,0xa6fc4ee8,0xc982b5a5, + 0xa8c01db7,0x579fc264,0x67094f31,0xf2bd3f5f, + 0x40fff7c1,0x1fb78dfc,0x8e6bd2c1,0x437be59b, + 0x99b03dbf,0xb5dbc64b,0x638dc0e6,0x55819d99, + 0xa197c81c,0x4a012d6e,0xc5884a28,0xccc36f71, + 0xb843c213,0x6c0743f1,0x8309893c,0x0feddd5f, + 0x2f7fe850,0xd7c07f7e,0x02507fbf,0x5afb9a04, + 0xa747d2d0,0x1651192e,0xaf70bf3e,0x58c31380, + 0x5f98302e,0x727cc3c4,0x0a0fb402,0x0f7fef82, + 0x8c96fdad,0x5d2c2aae,0x8ee99a49,0x50da88b8, + 0x8427f4a0,0x1eac5790,0x796fb449,0x8252dc15, + 0xefbd7d9b,0xa672597d,0xada840d8,0x45f54504, + 0xfa5d7403,0xe83ec305,0x4f91751a,0x925669c2, + 0x23efe941,0xa903f12e,0x60270df2,0x0276e4b6, + 0x94fd6574,0x927985b2,0x8276dbcb,0x02778176, + 0xf8af918d,0x4e48f79e,0x8f616ddf,0xe29d840e, + 0x842f7d83,0x340ce5c8,0x96bbb682,0x93b4b148, + 0xef303cab,0x984faf28,0x779faf9b,0x92dc560d, + 0x224d1e20,0x8437aa88,0x7d29dc96,0x2756d3dc, + 0x8b907cee,0xb51fd240,0xe7c07ce3,0xe566b4a1, + 0xc3e9615e,0x3cf8209d,0x6094d1e3,0xcd9ca341, + 0x5c76460e,0x00ea983b,0xd4d67881,0xfd47572c, + 0xf76cedd9,0xbda8229c,0x127dadaa,0x438a074e, + 0x1f97c090,0x081bdb8a,0x93a07ebe,0xb938ca15, + 0x97b03cff,0x3dc2c0f8,0x8d1ab2ec,0x64380e51, + 0x68cc7bfb,0xd90f2788,0x12490181,0x5de5ffd4, + 0xdd7ef86a,0x76a2e214,0xb9a40368,0x925d958f, + 0x4b39fffa,0xba39aee9,0xa4ffd30b,0xfaf7933b, + 0x6d498623,0x193cbcfa,0x27627545,0x825cf47a, + 0x61bd8ba0,0xd11e42d1,0xcead04f4,0x127ea392, + 0x10428db7,0x8272a972,0x9270c4a8,0x127de50b, + 0x285ba1c8,0x3c62f44f,0x35c0eaa5,0xe805d231, + 0x428929fb,0xb4fcdf82,0x4fb66a53,0x0e7dc15b, + 0x1f081fab,0x108618ae,0xfcfd086d,0xf9ff2889, + 0x694bcc11,0x236a5cae,0x12deca4d,0x2c3f8cc5, + 0xd2d02dfe,0xf8ef5896,0xe4cf52da,0x95155b67, + 0x494a488c,0xb9b6a80c,0x5c8f82bc,0x89d36b45, + 0x3a609437,0xec00c9a9,0x44715253,0x0a874b49, + 0xd773bc40,0x7c34671c,0x02717ef6,0x4feb5536, + 0xa2d02fff,0xd2bf60c4,0xd43f03c0,0x50b4ef6d, + 0x07478cd1,0x006e1888,0xa2e53f55,0xb9e6d4bc, + 0xa2048016,0x97573833,0xd7207d67,0xde0f8f3d, + 0x72f87b33,0xabcc4f33,0x7688c55d,0x7b00a6b0, + 0x947b0001,0x570075d2,0xf9bb88f8,0x8942019e, + 0x4264a5ff,0x856302e0,0x72dbd92b,0xee971b69, + 0x6ea22fde,0x5f08ae2b,0xaf7a616d,0xe5c98767, + 0xcf1febd2,0x61efc8c2,0xf1ac2571,0xcc8239c2, + 0x67214cb8,0xb1e583d1,0xb7dc3e62,0x7f10bdce, + 0xf90a5c38,0x0ff0443d,0x606e6dc6,0x60543a49, + 0x5727c148,0x2be98a1d,0x8ab41738,0x20e1be24, + 0xaf96da0f,0x68458425,0x99833be5,0x600d457d, + 0x282f9350,0x8334b362,0xd91d1120,0x2b6d8da0, + 0x642b1e31,0x9c305a00,0x52bce688,0x1b03588a, + 0xf7baefd5,0x4142ed9c,0xa4315c11,0x83323ec5, + 0xdfef4636,0xa133c501,0xe9d3531c,0xee353783, + }; +CAST_LONG CAST_S_table3[256]={ + 0x9db30420,0x1fb6e9de,0xa7be7bef,0xd273a298, + 0x4a4f7bdb,0x64ad8c57,0x85510443,0xfa020ed1, + 0x7e287aff,0xe60fb663,0x095f35a1,0x79ebf120, + 0xfd059d43,0x6497b7b1,0xf3641f63,0x241e4adf, + 0x28147f5f,0x4fa2b8cd,0xc9430040,0x0cc32220, + 0xfdd30b30,0xc0a5374f,0x1d2d00d9,0x24147b15, + 0xee4d111a,0x0fca5167,0x71ff904c,0x2d195ffe, + 0x1a05645f,0x0c13fefe,0x081b08ca,0x05170121, + 0x80530100,0xe83e5efe,0xac9af4f8,0x7fe72701, + 0xd2b8ee5f,0x06df4261,0xbb9e9b8a,0x7293ea25, + 0xce84ffdf,0xf5718801,0x3dd64b04,0xa26f263b, + 0x7ed48400,0x547eebe6,0x446d4ca0,0x6cf3d6f5, + 0x2649abdf,0xaea0c7f5,0x36338cc1,0x503f7e93, + 0xd3772061,0x11b638e1,0x72500e03,0xf80eb2bb, + 0xabe0502e,0xec8d77de,0x57971e81,0xe14f6746, + 0xc9335400,0x6920318f,0x081dbb99,0xffc304a5, + 0x4d351805,0x7f3d5ce3,0xa6c866c6,0x5d5bcca9, + 0xdaec6fea,0x9f926f91,0x9f46222f,0x3991467d, + 0xa5bf6d8e,0x1143c44f,0x43958302,0xd0214eeb, + 0x022083b8,0x3fb6180c,0x18f8931e,0x281658e6, + 0x26486e3e,0x8bd78a70,0x7477e4c1,0xb506e07c, + 0xf32d0a25,0x79098b02,0xe4eabb81,0x28123b23, + 0x69dead38,0x1574ca16,0xdf871b62,0x211c40b7, + 0xa51a9ef9,0x0014377b,0x041e8ac8,0x09114003, + 0xbd59e4d2,0xe3d156d5,0x4fe876d5,0x2f91a340, + 0x557be8de,0x00eae4a7,0x0ce5c2ec,0x4db4bba6, + 0xe756bdff,0xdd3369ac,0xec17b035,0x06572327, + 0x99afc8b0,0x56c8c391,0x6b65811c,0x5e146119, + 0x6e85cb75,0xbe07c002,0xc2325577,0x893ff4ec, + 0x5bbfc92d,0xd0ec3b25,0xb7801ab7,0x8d6d3b24, + 0x20c763ef,0xc366a5fc,0x9c382880,0x0ace3205, + 0xaac9548a,0xeca1d7c7,0x041afa32,0x1d16625a, + 0x6701902c,0x9b757a54,0x31d477f7,0x9126b031, + 0x36cc6fdb,0xc70b8b46,0xd9e66a48,0x56e55a79, + 0x026a4ceb,0x52437eff,0x2f8f76b4,0x0df980a5, + 0x8674cde3,0xedda04eb,0x17a9be04,0x2c18f4df, + 0xb7747f9d,0xab2af7b4,0xefc34d20,0x2e096b7c, + 0x1741a254,0xe5b6a035,0x213d42f6,0x2c1c7c26, + 0x61c2f50f,0x6552daf9,0xd2c231f8,0x25130f69, + 0xd8167fa2,0x0418f2c8,0x001a96a6,0x0d1526ab, + 0x63315c21,0x5e0a72ec,0x49bafefd,0x187908d9, + 0x8d0dbd86,0x311170a7,0x3e9b640c,0xcc3e10d7, + 0xd5cad3b6,0x0caec388,0xf73001e1,0x6c728aff, + 0x71eae2a1,0x1f9af36e,0xcfcbd12f,0xc1de8417, + 0xac07be6b,0xcb44a1d8,0x8b9b0f56,0x013988c3, + 0xb1c52fca,0xb4be31cd,0xd8782806,0x12a3a4e2, + 0x6f7de532,0x58fd7eb6,0xd01ee900,0x24adffc2, + 0xf4990fc5,0x9711aac5,0x001d7b95,0x82e5e7d2, + 0x109873f6,0x00613096,0xc32d9521,0xada121ff, + 0x29908415,0x7fbb977f,0xaf9eb3db,0x29c9ed2a, + 0x5ce2a465,0xa730f32c,0xd0aa3fe8,0x8a5cc091, + 0xd49e2ce7,0x0ce454a9,0xd60acd86,0x015f1919, + 0x77079103,0xdea03af6,0x78a8565e,0xdee356df, + 0x21f05cbe,0x8b75e387,0xb3c50651,0xb8a5c3ef, + 0xd8eeb6d2,0xe523be77,0xc2154529,0x2f69efdf, + 0xafe67afb,0xf470c4b2,0xf3e0eb5b,0xd6cc9876, + 0x39e4460c,0x1fda8538,0x1987832f,0xca007367, + 0xa99144f8,0x296b299e,0x492fc295,0x9266beab, + 0xb5676e69,0x9bd3ddda,0xdf7e052f,0xdb25701c, + 0x1b5e51ee,0xf65324e6,0x6afce36c,0x0316cc04, + 0x8644213e,0xb7dc59d0,0x7965291f,0xccd6fd43, + 0x41823979,0x932bcdf6,0xb657c34d,0x4edfd282, + 0x7ae5290c,0x3cb9536b,0x851e20fe,0x9833557e, + 0x13ecf0b0,0xd3ffb372,0x3f85c5c1,0x0aef7ed2, + }; +CAST_LONG CAST_S_table4[256]={ + 0x7ec90c04,0x2c6e74b9,0x9b0e66df,0xa6337911, + 0xb86a7fff,0x1dd358f5,0x44dd9d44,0x1731167f, + 0x08fbf1fa,0xe7f511cc,0xd2051b00,0x735aba00, + 0x2ab722d8,0x386381cb,0xacf6243a,0x69befd7a, + 0xe6a2e77f,0xf0c720cd,0xc4494816,0xccf5c180, + 0x38851640,0x15b0a848,0xe68b18cb,0x4caadeff, + 0x5f480a01,0x0412b2aa,0x259814fc,0x41d0efe2, + 0x4e40b48d,0x248eb6fb,0x8dba1cfe,0x41a99b02, + 0x1a550a04,0xba8f65cb,0x7251f4e7,0x95a51725, + 0xc106ecd7,0x97a5980a,0xc539b9aa,0x4d79fe6a, + 0xf2f3f763,0x68af8040,0xed0c9e56,0x11b4958b, + 0xe1eb5a88,0x8709e6b0,0xd7e07156,0x4e29fea7, + 0x6366e52d,0x02d1c000,0xc4ac8e05,0x9377f571, + 0x0c05372a,0x578535f2,0x2261be02,0xd642a0c9, + 0xdf13a280,0x74b55bd2,0x682199c0,0xd421e5ec, + 0x53fb3ce8,0xc8adedb3,0x28a87fc9,0x3d959981, + 0x5c1ff900,0xfe38d399,0x0c4eff0b,0x062407ea, + 0xaa2f4fb1,0x4fb96976,0x90c79505,0xb0a8a774, + 0xef55a1ff,0xe59ca2c2,0xa6b62d27,0xe66a4263, + 0xdf65001f,0x0ec50966,0xdfdd55bc,0x29de0655, + 0x911e739a,0x17af8975,0x32c7911c,0x89f89468, + 0x0d01e980,0x524755f4,0x03b63cc9,0x0cc844b2, + 0xbcf3f0aa,0x87ac36e9,0xe53a7426,0x01b3d82b, + 0x1a9e7449,0x64ee2d7e,0xcddbb1da,0x01c94910, + 0xb868bf80,0x0d26f3fd,0x9342ede7,0x04a5c284, + 0x636737b6,0x50f5b616,0xf24766e3,0x8eca36c1, + 0x136e05db,0xfef18391,0xfb887a37,0xd6e7f7d4, + 0xc7fb7dc9,0x3063fcdf,0xb6f589de,0xec2941da, + 0x26e46695,0xb7566419,0xf654efc5,0xd08d58b7, + 0x48925401,0xc1bacb7f,0xe5ff550f,0xb6083049, + 0x5bb5d0e8,0x87d72e5a,0xab6a6ee1,0x223a66ce, + 0xc62bf3cd,0x9e0885f9,0x68cb3e47,0x086c010f, + 0xa21de820,0xd18b69de,0xf3f65777,0xfa02c3f6, + 0x407edac3,0xcbb3d550,0x1793084d,0xb0d70eba, + 0x0ab378d5,0xd951fb0c,0xded7da56,0x4124bbe4, + 0x94ca0b56,0x0f5755d1,0xe0e1e56e,0x6184b5be, + 0x580a249f,0x94f74bc0,0xe327888e,0x9f7b5561, + 0xc3dc0280,0x05687715,0x646c6bd7,0x44904db3, + 0x66b4f0a3,0xc0f1648a,0x697ed5af,0x49e92ff6, + 0x309e374f,0x2cb6356a,0x85808573,0x4991f840, + 0x76f0ae02,0x083be84d,0x28421c9a,0x44489406, + 0x736e4cb8,0xc1092910,0x8bc95fc6,0x7d869cf4, + 0x134f616f,0x2e77118d,0xb31b2be1,0xaa90b472, + 0x3ca5d717,0x7d161bba,0x9cad9010,0xaf462ba2, + 0x9fe459d2,0x45d34559,0xd9f2da13,0xdbc65487, + 0xf3e4f94e,0x176d486f,0x097c13ea,0x631da5c7, + 0x445f7382,0x175683f4,0xcdc66a97,0x70be0288, + 0xb3cdcf72,0x6e5dd2f3,0x20936079,0x459b80a5, + 0xbe60e2db,0xa9c23101,0xeba5315c,0x224e42f2, + 0x1c5c1572,0xf6721b2c,0x1ad2fff3,0x8c25404e, + 0x324ed72f,0x4067b7fd,0x0523138e,0x5ca3bc78, + 0xdc0fd66e,0x75922283,0x784d6b17,0x58ebb16e, + 0x44094f85,0x3f481d87,0xfcfeae7b,0x77b5ff76, + 0x8c2302bf,0xaaf47556,0x5f46b02a,0x2b092801, + 0x3d38f5f7,0x0ca81f36,0x52af4a8a,0x66d5e7c0, + 0xdf3b0874,0x95055110,0x1b5ad7a8,0xf61ed5ad, + 0x6cf6e479,0x20758184,0xd0cefa65,0x88f7be58, + 0x4a046826,0x0ff6f8f3,0xa09c7f70,0x5346aba0, + 0x5ce96c28,0xe176eda3,0x6bac307f,0x376829d2, + 0x85360fa9,0x17e3fe2a,0x24b79767,0xf5a96b20, + 0xd6cd2595,0x68ff1ebf,0x7555442c,0xf19f06be, + 0xf9e0659a,0xeeb9491d,0x34010718,0xbb30cab8, + 0xe822fe15,0x88570983,0x750e6249,0xda627e55, + 0x5e76ffa8,0xb1534546,0x6d47de08,0xefe9e7d4, + }; +CAST_LONG CAST_S_table5[256]={ + 0xf6fa8f9d,0x2cac6ce1,0x4ca34867,0xe2337f7c, + 0x95db08e7,0x016843b4,0xeced5cbc,0x325553ac, + 0xbf9f0960,0xdfa1e2ed,0x83f0579d,0x63ed86b9, + 0x1ab6a6b8,0xde5ebe39,0xf38ff732,0x8989b138, + 0x33f14961,0xc01937bd,0xf506c6da,0xe4625e7e, + 0xa308ea99,0x4e23e33c,0x79cbd7cc,0x48a14367, + 0xa3149619,0xfec94bd5,0xa114174a,0xeaa01866, + 0xa084db2d,0x09a8486f,0xa888614a,0x2900af98, + 0x01665991,0xe1992863,0xc8f30c60,0x2e78ef3c, + 0xd0d51932,0xcf0fec14,0xf7ca07d2,0xd0a82072, + 0xfd41197e,0x9305a6b0,0xe86be3da,0x74bed3cd, + 0x372da53c,0x4c7f4448,0xdab5d440,0x6dba0ec3, + 0x083919a7,0x9fbaeed9,0x49dbcfb0,0x4e670c53, + 0x5c3d9c01,0x64bdb941,0x2c0e636a,0xba7dd9cd, + 0xea6f7388,0xe70bc762,0x35f29adb,0x5c4cdd8d, + 0xf0d48d8c,0xb88153e2,0x08a19866,0x1ae2eac8, + 0x284caf89,0xaa928223,0x9334be53,0x3b3a21bf, + 0x16434be3,0x9aea3906,0xefe8c36e,0xf890cdd9, + 0x80226dae,0xc340a4a3,0xdf7e9c09,0xa694a807, + 0x5b7c5ecc,0x221db3a6,0x9a69a02f,0x68818a54, + 0xceb2296f,0x53c0843a,0xfe893655,0x25bfe68a, + 0xb4628abc,0xcf222ebf,0x25ac6f48,0xa9a99387, + 0x53bddb65,0xe76ffbe7,0xe967fd78,0x0ba93563, + 0x8e342bc1,0xe8a11be9,0x4980740d,0xc8087dfc, + 0x8de4bf99,0xa11101a0,0x7fd37975,0xda5a26c0, + 0xe81f994f,0x9528cd89,0xfd339fed,0xb87834bf, + 0x5f04456d,0x22258698,0xc9c4c83b,0x2dc156be, + 0x4f628daa,0x57f55ec5,0xe2220abe,0xd2916ebf, + 0x4ec75b95,0x24f2c3c0,0x42d15d99,0xcd0d7fa0, + 0x7b6e27ff,0xa8dc8af0,0x7345c106,0xf41e232f, + 0x35162386,0xe6ea8926,0x3333b094,0x157ec6f2, + 0x372b74af,0x692573e4,0xe9a9d848,0xf3160289, + 0x3a62ef1d,0xa787e238,0xf3a5f676,0x74364853, + 0x20951063,0x4576698d,0xb6fad407,0x592af950, + 0x36f73523,0x4cfb6e87,0x7da4cec0,0x6c152daa, + 0xcb0396a8,0xc50dfe5d,0xfcd707ab,0x0921c42f, + 0x89dff0bb,0x5fe2be78,0x448f4f33,0x754613c9, + 0x2b05d08d,0x48b9d585,0xdc049441,0xc8098f9b, + 0x7dede786,0xc39a3373,0x42410005,0x6a091751, + 0x0ef3c8a6,0x890072d6,0x28207682,0xa9a9f7be, + 0xbf32679d,0xd45b5b75,0xb353fd00,0xcbb0e358, + 0x830f220a,0x1f8fb214,0xd372cf08,0xcc3c4a13, + 0x8cf63166,0x061c87be,0x88c98f88,0x6062e397, + 0x47cf8e7a,0xb6c85283,0x3cc2acfb,0x3fc06976, + 0x4e8f0252,0x64d8314d,0xda3870e3,0x1e665459, + 0xc10908f0,0x513021a5,0x6c5b68b7,0x822f8aa0, + 0x3007cd3e,0x74719eef,0xdc872681,0x073340d4, + 0x7e432fd9,0x0c5ec241,0x8809286c,0xf592d891, + 0x08a930f6,0x957ef305,0xb7fbffbd,0xc266e96f, + 0x6fe4ac98,0xb173ecc0,0xbc60b42a,0x953498da, + 0xfba1ae12,0x2d4bd736,0x0f25faab,0xa4f3fceb, + 0xe2969123,0x257f0c3d,0x9348af49,0x361400bc, + 0xe8816f4a,0x3814f200,0xa3f94043,0x9c7a54c2, + 0xbc704f57,0xda41e7f9,0xc25ad33a,0x54f4a084, + 0xb17f5505,0x59357cbe,0xedbd15c8,0x7f97c5ab, + 0xba5ac7b5,0xb6f6deaf,0x3a479c3a,0x5302da25, + 0x653d7e6a,0x54268d49,0x51a477ea,0x5017d55b, + 0xd7d25d88,0x44136c76,0x0404a8c8,0xb8e5a121, + 0xb81a928a,0x60ed5869,0x97c55b96,0xeaec991b, + 0x29935913,0x01fdb7f1,0x088e8dfa,0x9ab6f6f5, + 0x3b4cbf9f,0x4a5de3ab,0xe6051d35,0xa0e1d855, + 0xd36b4cf1,0xf544edeb,0xb0e93524,0xbebb8fbd, + 0xa2d762cf,0x49c92f54,0x38b5f331,0x7128a454, + 0x48392905,0xa65b1db8,0x851c97bd,0xd675cf2f, + }; +CAST_LONG CAST_S_table6[256]={ + 0x85e04019,0x332bf567,0x662dbfff,0xcfc65693, + 0x2a8d7f6f,0xab9bc912,0xde6008a1,0x2028da1f, + 0x0227bce7,0x4d642916,0x18fac300,0x50f18b82, + 0x2cb2cb11,0xb232e75c,0x4b3695f2,0xb28707de, + 0xa05fbcf6,0xcd4181e9,0xe150210c,0xe24ef1bd, + 0xb168c381,0xfde4e789,0x5c79b0d8,0x1e8bfd43, + 0x4d495001,0x38be4341,0x913cee1d,0x92a79c3f, + 0x089766be,0xbaeeadf4,0x1286becf,0xb6eacb19, + 0x2660c200,0x7565bde4,0x64241f7a,0x8248dca9, + 0xc3b3ad66,0x28136086,0x0bd8dfa8,0x356d1cf2, + 0x107789be,0xb3b2e9ce,0x0502aa8f,0x0bc0351e, + 0x166bf52a,0xeb12ff82,0xe3486911,0xd34d7516, + 0x4e7b3aff,0x5f43671b,0x9cf6e037,0x4981ac83, + 0x334266ce,0x8c9341b7,0xd0d854c0,0xcb3a6c88, + 0x47bc2829,0x4725ba37,0xa66ad22b,0x7ad61f1e, + 0x0c5cbafa,0x4437f107,0xb6e79962,0x42d2d816, + 0x0a961288,0xe1a5c06e,0x13749e67,0x72fc081a, + 0xb1d139f7,0xf9583745,0xcf19df58,0xbec3f756, + 0xc06eba30,0x07211b24,0x45c28829,0xc95e317f, + 0xbc8ec511,0x38bc46e9,0xc6e6fa14,0xbae8584a, + 0xad4ebc46,0x468f508b,0x7829435f,0xf124183b, + 0x821dba9f,0xaff60ff4,0xea2c4e6d,0x16e39264, + 0x92544a8b,0x009b4fc3,0xaba68ced,0x9ac96f78, + 0x06a5b79a,0xb2856e6e,0x1aec3ca9,0xbe838688, + 0x0e0804e9,0x55f1be56,0xe7e5363b,0xb3a1f25d, + 0xf7debb85,0x61fe033c,0x16746233,0x3c034c28, + 0xda6d0c74,0x79aac56c,0x3ce4e1ad,0x51f0c802, + 0x98f8f35a,0x1626a49f,0xeed82b29,0x1d382fe3, + 0x0c4fb99a,0xbb325778,0x3ec6d97b,0x6e77a6a9, + 0xcb658b5c,0xd45230c7,0x2bd1408b,0x60c03eb7, + 0xb9068d78,0xa33754f4,0xf430c87d,0xc8a71302, + 0xb96d8c32,0xebd4e7be,0xbe8b9d2d,0x7979fb06, + 0xe7225308,0x8b75cf77,0x11ef8da4,0xe083c858, + 0x8d6b786f,0x5a6317a6,0xfa5cf7a0,0x5dda0033, + 0xf28ebfb0,0xf5b9c310,0xa0eac280,0x08b9767a, + 0xa3d9d2b0,0x79d34217,0x021a718d,0x9ac6336a, + 0x2711fd60,0x438050e3,0x069908a8,0x3d7fedc4, + 0x826d2bef,0x4eeb8476,0x488dcf25,0x36c9d566, + 0x28e74e41,0xc2610aca,0x3d49a9cf,0xbae3b9df, + 0xb65f8de6,0x92aeaf64,0x3ac7d5e6,0x9ea80509, + 0xf22b017d,0xa4173f70,0xdd1e16c3,0x15e0d7f9, + 0x50b1b887,0x2b9f4fd5,0x625aba82,0x6a017962, + 0x2ec01b9c,0x15488aa9,0xd716e740,0x40055a2c, + 0x93d29a22,0xe32dbf9a,0x058745b9,0x3453dc1e, + 0xd699296e,0x496cff6f,0x1c9f4986,0xdfe2ed07, + 0xb87242d1,0x19de7eae,0x053e561a,0x15ad6f8c, + 0x66626c1c,0x7154c24c,0xea082b2a,0x93eb2939, + 0x17dcb0f0,0x58d4f2ae,0x9ea294fb,0x52cf564c, + 0x9883fe66,0x2ec40581,0x763953c3,0x01d6692e, + 0xd3a0c108,0xa1e7160e,0xe4f2dfa6,0x693ed285, + 0x74904698,0x4c2b0edd,0x4f757656,0x5d393378, + 0xa132234f,0x3d321c5d,0xc3f5e194,0x4b269301, + 0xc79f022f,0x3c997e7e,0x5e4f9504,0x3ffafbbd, + 0x76f7ad0e,0x296693f4,0x3d1fce6f,0xc61e45be, + 0xd3b5ab34,0xf72bf9b7,0x1b0434c0,0x4e72b567, + 0x5592a33d,0xb5229301,0xcfd2a87f,0x60aeb767, + 0x1814386b,0x30bcc33d,0x38a0c07d,0xfd1606f2, + 0xc363519b,0x589dd390,0x5479f8e6,0x1cb8d647, + 0x97fd61a9,0xea7759f4,0x2d57539d,0x569a58cf, + 0xe84e63ad,0x462e1b78,0x6580f87e,0xf3817914, + 0x91da55f4,0x40a230f3,0xd1988f35,0xb6e318d2, + 0x3ffa50bc,0x3d40f021,0xc3c0bdae,0x4958c24c, + 0x518f36b2,0x84b1d370,0x0fedce83,0x878ddada, + 0xf2a279c7,0x94e01be8,0x90716f4b,0x954b8aa3, + }; +CAST_LONG CAST_S_table7[256]={ + 0xe216300d,0xbbddfffc,0xa7ebdabd,0x35648095, + 0x7789f8b7,0xe6c1121b,0x0e241600,0x052ce8b5, + 0x11a9cfb0,0xe5952f11,0xece7990a,0x9386d174, + 0x2a42931c,0x76e38111,0xb12def3a,0x37ddddfc, + 0xde9adeb1,0x0a0cc32c,0xbe197029,0x84a00940, + 0xbb243a0f,0xb4d137cf,0xb44e79f0,0x049eedfd, + 0x0b15a15d,0x480d3168,0x8bbbde5a,0x669ded42, + 0xc7ece831,0x3f8f95e7,0x72df191b,0x7580330d, + 0x94074251,0x5c7dcdfa,0xabbe6d63,0xaa402164, + 0xb301d40a,0x02e7d1ca,0x53571dae,0x7a3182a2, + 0x12a8ddec,0xfdaa335d,0x176f43e8,0x71fb46d4, + 0x38129022,0xce949ad4,0xb84769ad,0x965bd862, + 0x82f3d055,0x66fb9767,0x15b80b4e,0x1d5b47a0, + 0x4cfde06f,0xc28ec4b8,0x57e8726e,0x647a78fc, + 0x99865d44,0x608bd593,0x6c200e03,0x39dc5ff6, + 0x5d0b00a3,0xae63aff2,0x7e8bd632,0x70108c0c, + 0xbbd35049,0x2998df04,0x980cf42a,0x9b6df491, + 0x9e7edd53,0x06918548,0x58cb7e07,0x3b74ef2e, + 0x522fffb1,0xd24708cc,0x1c7e27cd,0xa4eb215b, + 0x3cf1d2e2,0x19b47a38,0x424f7618,0x35856039, + 0x9d17dee7,0x27eb35e6,0xc9aff67b,0x36baf5b8, + 0x09c467cd,0xc18910b1,0xe11dbf7b,0x06cd1af8, + 0x7170c608,0x2d5e3354,0xd4de495a,0x64c6d006, + 0xbcc0c62c,0x3dd00db3,0x708f8f34,0x77d51b42, + 0x264f620f,0x24b8d2bf,0x15c1b79e,0x46a52564, + 0xf8d7e54e,0x3e378160,0x7895cda5,0x859c15a5, + 0xe6459788,0xc37bc75f,0xdb07ba0c,0x0676a3ab, + 0x7f229b1e,0x31842e7b,0x24259fd7,0xf8bef472, + 0x835ffcb8,0x6df4c1f2,0x96f5b195,0xfd0af0fc, + 0xb0fe134c,0xe2506d3d,0x4f9b12ea,0xf215f225, + 0xa223736f,0x9fb4c428,0x25d04979,0x34c713f8, + 0xc4618187,0xea7a6e98,0x7cd16efc,0x1436876c, + 0xf1544107,0xbedeee14,0x56e9af27,0xa04aa441, + 0x3cf7c899,0x92ecbae6,0xdd67016d,0x151682eb, + 0xa842eedf,0xfdba60b4,0xf1907b75,0x20e3030f, + 0x24d8c29e,0xe139673b,0xefa63fb8,0x71873054, + 0xb6f2cf3b,0x9f326442,0xcb15a4cc,0xb01a4504, + 0xf1e47d8d,0x844a1be5,0xbae7dfdc,0x42cbda70, + 0xcd7dae0a,0x57e85b7a,0xd53f5af6,0x20cf4d8c, + 0xcea4d428,0x79d130a4,0x3486ebfb,0x33d3cddc, + 0x77853b53,0x37effcb5,0xc5068778,0xe580b3e6, + 0x4e68b8f4,0xc5c8b37e,0x0d809ea2,0x398feb7c, + 0x132a4f94,0x43b7950e,0x2fee7d1c,0x223613bd, + 0xdd06caa2,0x37df932b,0xc4248289,0xacf3ebc3, + 0x5715f6b7,0xef3478dd,0xf267616f,0xc148cbe4, + 0x9052815e,0x5e410fab,0xb48a2465,0x2eda7fa4, + 0xe87b40e4,0xe98ea084,0x5889e9e1,0xefd390fc, + 0xdd07d35b,0xdb485694,0x38d7e5b2,0x57720101, + 0x730edebc,0x5b643113,0x94917e4f,0x503c2fba, + 0x646f1282,0x7523d24a,0xe0779695,0xf9c17a8f, + 0x7a5b2121,0xd187b896,0x29263a4d,0xba510cdf, + 0x81f47c9f,0xad1163ed,0xea7b5965,0x1a00726e, + 0x11403092,0x00da6d77,0x4a0cdd61,0xad1f4603, + 0x605bdfb0,0x9eedc364,0x22ebe6a8,0xcee7d28a, + 0xa0e736a0,0x5564a6b9,0x10853209,0xc7eb8f37, + 0x2de705ca,0x8951570f,0xdf09822b,0xbd691a6c, + 0xaa12e4f2,0x87451c0f,0xe0f6a27a,0x3ada4819, + 0x4cf1764f,0x0d771c2b,0x67cdb156,0x350d8384, + 0x5938fa0f,0x42399ef3,0x36997b07,0x0e84093d, + 0x4aa93e61,0x8360d87b,0x1fa98b0c,0x1149382c, + 0xe97625a5,0x0614d1b7,0x0e25244b,0x0c768347, + 0x589e8d82,0x0d2059d1,0xa466bb1e,0xf8da0a82, + 0x04f19130,0xba6e4ec0,0x99265164,0x1ee7230d, + 0x50b2ad80,0xeaee6801,0x8db2a283,0xea8bf59e, + }; diff --git a/src/utils/crypto/des.c b/src/utils/crypto/des.c new file mode 100644 index 000000000..897cbdd52 --- /dev/null +++ b/src/utils/crypto/des.c @@ -0,0 +1,4 @@ +/* Deprecated/legacy */ + +#include "des.h" +#include "spr.h" diff --git a/src/utils/crypto/des.h b/src/utils/crypto/des.h new file mode 100644 index 000000000..625c3f9dc --- /dev/null +++ b/src/utils/crypto/des.h @@ -0,0 +1,292 @@ +/* Deprecated/legacy */ + +/* crypto/des/des.org */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * + * Always modify des.org since des.h is automatically generated from + * it during SSLeay configuration. + * + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + */ + +#ifndef HEADER_DES_H +#define HEADER_DES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG uint32_t +#endif + +typedef unsigned char des_cblock[8]; +typedef struct des_ks_struct + { + union { + des_cblock _; + /* make sure things are correct size on machines with + * 8 byte longs */ + DES_LONG pad[2]; + } ks; + } des_key_schedule[16]; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +#define des_ecb2_encrypt(i,o,k1,k2,e) \ + des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +#define C_Block des_cblock +#define Key_schedule des_key_schedule +#ifdef KERBEROS +#define ENCRYPT DES_ENCRYPT +#define DECRYPT DES_DECRYPT +#endif +#define KEY_SZ DES_KEY_SZ +#define string_to_key des_string_to_key +#define read_pw_string des_read_pw_string +#define random_key des_random_key +#define pcbc_encrypt des_pcbc_encrypt +#define set_key des_set_key +#define key_sched des_key_sched +#define ecb_encrypt des_ecb_encrypt +#define cbc_encrypt des_cbc_encrypt +#define ncbc_encrypt des_ncbc_encrypt +#define xcbc_encrypt des_xcbc_encrypt +#define cbc_cksum des_cbc_cksum +#define quad_cksum des_quad_cksum + +/* For compatibility with the MIT lib - eay 20/05/92 */ +typedef des_key_schedule bit_64; +#define des_fixup_key_parity des_set_odd_parity +#define des_check_key_parity check_parity + +extern int des_check_key; /* defaults to false */ +extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ + +/* The next line is used to disable full ANSI prototypes, if your + * compiler has problems with the prototypes, make sure this line always + * evaluates to true :-) */ +#if defined(MSDOS) || defined(__STDC__) +#undef NOPROTO +#endif +#ifndef NOPROTO +char *des_options(void); +void des_ecb3_encrypt(des_cblock *input,des_cblock *output, + des_key_schedule ks1,des_key_schedule ks2, + des_key_schedule ks3, int enc); +DES_LONG des_cbc_cksum(des_cblock *input,des_cblock *output, + long length,des_key_schedule schedule,des_cblock *ivec); +void des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec,int enc); +void des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec,int enc); +void des_xcbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec, + des_cblock *inw,des_cblock *outw,int enc); +void des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, + long length,des_key_schedule schedule,des_cblock *ivec,int enc); +void des_ecb_encrypt(des_cblock *input,des_cblock *output, + des_key_schedule ks,int enc); +void des_encrypt(DES_LONG *data,des_key_schedule ks, int enc); +void des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc); +void des_encrypt3(DES_LONG *data, des_key_schedule ks1, + des_key_schedule ks2, des_key_schedule ks3); +void des_decrypt3(DES_LONG *data, des_key_schedule ks1, + des_key_schedule ks2, des_key_schedule ks3); +void des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, + long length, des_key_schedule ks1, des_key_schedule ks2, + des_key_schedule ks3, des_cblock *ivec, int enc); +void des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, + long length, des_key_schedule ks1, des_key_schedule ks2, + des_key_schedule ks3, des_cblock *ivec, int *num, int enc); +void des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, + long length, des_key_schedule ks1, des_key_schedule ks2, + des_key_schedule ks3, des_cblock *ivec, int *num); + +void des_xwhite_in2out(des_cblock (*des_key), des_cblock (*in_white), + des_cblock (*out_white)); + +int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, + des_cblock *iv); +int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, + des_cblock *iv); +char *des_fcrypt(const char *buf,const char *salt, char *ret); +char *des_crypt(const char *buf,const char *salt); +void des_ofb_encrypt(unsigned char *in,unsigned char *out, + int numbits,long length,des_key_schedule schedule,des_cblock *ivec); +void des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec,int enc); +DES_LONG des_quad_cksum(des_cblock *input,des_cblock *output, + long length,int out_count,des_cblock *seed); +void des_random_seed(des_cblock key); +void des_random_key(des_cblock ret); +int des_read_password(des_cblock *key,char *prompt,int verify); +int des_read_2passwords(des_cblock *key1,des_cblock *key2, + char *prompt,int verify); +int des_read_pw_string(char *buf,int length,char *prompt,int verify); +void des_set_odd_parity(des_cblock *key); +int des_is_weak_key(des_cblock *key); +int des_set_key(des_cblock *key,des_key_schedule schedule); +int des_key_sched(des_cblock *key,des_key_schedule schedule); +void des_string_to_key(char *str,des_cblock *key); +void des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); +void des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + des_key_schedule schedule, des_cblock *ivec, int *num, int enc); +void des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, + des_key_schedule schedule, des_cblock *ivec, int *num); +int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify); + +/* Extra functions from Mark Murray */ +void des_cblock_print_file(des_cblock *cb, FILE *fp); +/* The following functions are not in the normal unix build or the + * SSLeay build. When using the SSLeay build, use RAND_seed() + * and RAND_bytes() instead. */ +int des_new_random_key(des_cblock *key); +void des_init_random_number_generator(des_cblock *key); +void des_set_random_generator_seed(des_cblock *key); +void des_set_sequence_number(des_cblock new_sequence_number); +void des_generate_random_block(des_cblock *block); + +#else + +char *des_options(); +void des_ecb3_encrypt(); +DES_LONG des_cbc_cksum(); +void des_cbc_encrypt(); +void des_ncbc_encrypt(); +void des_xcbc_encrypt(); +void des_cfb_encrypt(); +void des_ede3_cfb64_encrypt(); +void des_ede3_ofb64_encrypt(); +void des_ecb_encrypt(); +void des_encrypt(); +void des_encrypt2(); +void des_encrypt3(); +void des_decrypt3(); +void des_ede3_cbc_encrypt(); +int des_enc_read(); +int des_enc_write(); +char *des_fcrypt(); +#ifdef PERL5 +char *des_crypt(); +#else +char *crypt(); +#endif +void des_ofb_encrypt(); +void des_pcbc_encrypt(); +DES_LONG des_quad_cksum(); +void des_random_seed(); +void des_random_key(); +int des_read_password(); +int des_read_2passwords(); +int des_read_pw_string(); +void des_set_odd_parity(); +int des_is_weak_key(); +int des_set_key(); +int des_key_sched(); +void des_string_to_key(); +void des_string_to_2keys(); +void des_cfb64_encrypt(); +void des_ofb64_encrypt(); +int des_read_pw(); +void des_xwhite_in2out(); + +/* Extra functions from Mark Murray */ +void des_cblock_print_file(); +/* The following functions are not in the normal unix build or the + * SSLeay build. When using the SSLeay build, use RAND_seed() + * and RAND_bytes() instead. */ +#ifdef FreeBSD +int des_new_random_key(); +void des_init_random_number_generator(); +void des_set_random_generator_seed(); +void des_set_sequence_number(); +void des_generate_random_block(); +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/utils/crypto/des_enc.c b/src/utils/crypto/des_enc.c new file mode 100644 index 000000000..bb822afcd --- /dev/null +++ b/src/utils/crypto/des_enc.c @@ -0,0 +1,479 @@ +/* Deprecated/legacy */ + +/* crypto/des/des_enc.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#include "des_locl.h" +#include "../common/endian.h" + +void des_encrypt(DES_LONG *data, des_key_schedule ks, int enc) + { + register DES_LONG l,r,t,u; +#ifdef DES_PTR + register unsigned char *des_SP=(unsigned char *)des_SPtrans; +#endif +#ifndef DES_UNROLL + register int i; +#endif + register DES_LONG *s; + + r=LE32(data[0]); + l=LE32(data[1]); + + IP(r,l); + /* Things have been modified so that the initial rotate is + * done outside the loop. This required the + * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * One perl script later and things have a 5% speed up on a sparc2. + * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> + * for pointing this out. */ + /* clear the top bits on machines with 8byte longs */ + /* shift left by 2 */ + r=ROTATE(r,29)&0xffffffffL; + l=ROTATE(l,29)&0xffffffffL; + + s=(DES_LONG *)ks; + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (enc) + { +#ifdef DES_UNROLL + D_ENCRYPT(l,r, 0); /* 1 */ + D_ENCRYPT(r,l, 2); /* 2 */ + D_ENCRYPT(l,r, 4); /* 3 */ + D_ENCRYPT(r,l, 6); /* 4 */ + D_ENCRYPT(l,r, 8); /* 5 */ + D_ENCRYPT(r,l,10); /* 6 */ + D_ENCRYPT(l,r,12); /* 7 */ + D_ENCRYPT(r,l,14); /* 8 */ + D_ENCRYPT(l,r,16); /* 9 */ + D_ENCRYPT(r,l,18); /* 10 */ + D_ENCRYPT(l,r,20); /* 11 */ + D_ENCRYPT(r,l,22); /* 12 */ + D_ENCRYPT(l,r,24); /* 13 */ + D_ENCRYPT(r,l,26); /* 14 */ + D_ENCRYPT(l,r,28); /* 15 */ + D_ENCRYPT(r,l,30); /* 16 */ +#else + for (i=0; i<32; i+=8) + { + D_ENCRYPT(l,r,i+0); /* 1 */ + D_ENCRYPT(r,l,i+2); /* 2 */ + D_ENCRYPT(l,r,i+4); /* 3 */ + D_ENCRYPT(r,l,i+6); /* 4 */ + } +#endif + } + else + { +#ifdef DES_UNROLL + D_ENCRYPT(l,r,30); /* 16 */ + D_ENCRYPT(r,l,28); /* 15 */ + D_ENCRYPT(l,r,26); /* 14 */ + D_ENCRYPT(r,l,24); /* 13 */ + D_ENCRYPT(l,r,22); /* 12 */ + D_ENCRYPT(r,l,20); /* 11 */ + D_ENCRYPT(l,r,18); /* 10 */ + D_ENCRYPT(r,l,16); /* 9 */ + D_ENCRYPT(l,r,14); /* 8 */ + D_ENCRYPT(r,l,12); /* 7 */ + D_ENCRYPT(l,r,10); /* 6 */ + D_ENCRYPT(r,l, 8); /* 5 */ + D_ENCRYPT(l,r, 6); /* 4 */ + D_ENCRYPT(r,l, 4); /* 3 */ + D_ENCRYPT(l,r, 2); /* 2 */ + D_ENCRYPT(r,l, 0); /* 1 */ +#else + for (i=30; i>0; i-=8) + { + D_ENCRYPT(l,r,i-0); /* 16 */ + D_ENCRYPT(r,l,i-2); /* 15 */ + D_ENCRYPT(l,r,i-4); /* 14 */ + D_ENCRYPT(r,l,i-6); /* 13 */ + } +#endif + } + + /* rotate and clear the top bits on machines with 8byte longs */ + l=ROTATE(l,3)&0xffffffffL; + r=ROTATE(r,3)&0xffffffffL; + + FP(r,l); + data[0]=LE32(l); + data[1]=LE32(r); + l=r=t=u=0; + } + +void des_encrypt2(DES_LONG *data, des_key_schedule ks, int enc) + { + register DES_LONG l,r,t,u; +#ifdef DES_PTR + register unsigned char *des_SP=(unsigned char *)des_SPtrans; +#endif +#ifndef DES_UNROLL + register int i; +#endif + register DES_LONG *s; + + r=data[0]; + l=data[1]; + + /* Things have been modified so that the initial rotate is + * done outside the loop. This required the + * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * One perl script later and things have a 5% speed up on a sparc2. + * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> + * for pointing this out. */ + /* clear the top bits on machines with 8byte longs */ + r=ROTATE(r,29)&0xffffffffL; + l=ROTATE(l,29)&0xffffffffL; + + s=(DES_LONG *)ks; + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (enc) + { +#ifdef DES_UNROLL + D_ENCRYPT(l,r, 0); /* 1 */ + D_ENCRYPT(r,l, 2); /* 2 */ + D_ENCRYPT(l,r, 4); /* 3 */ + D_ENCRYPT(r,l, 6); /* 4 */ + D_ENCRYPT(l,r, 8); /* 5 */ + D_ENCRYPT(r,l,10); /* 6 */ + D_ENCRYPT(l,r,12); /* 7 */ + D_ENCRYPT(r,l,14); /* 8 */ + D_ENCRYPT(l,r,16); /* 9 */ + D_ENCRYPT(r,l,18); /* 10 */ + D_ENCRYPT(l,r,20); /* 11 */ + D_ENCRYPT(r,l,22); /* 12 */ + D_ENCRYPT(l,r,24); /* 13 */ + D_ENCRYPT(r,l,26); /* 14 */ + D_ENCRYPT(l,r,28); /* 15 */ + D_ENCRYPT(r,l,30); /* 16 */ +#else + for (i=0; i<32; i+=8) + { + D_ENCRYPT(l,r,i+0); /* 1 */ + D_ENCRYPT(r,l,i+2); /* 2 */ + D_ENCRYPT(l,r,i+4); /* 3 */ + D_ENCRYPT(r,l,i+6); /* 4 */ + } +#endif + } + else + { +#ifdef DES_UNROLL + D_ENCRYPT(l,r,30); /* 16 */ + D_ENCRYPT(r,l,28); /* 15 */ + D_ENCRYPT(l,r,26); /* 14 */ + D_ENCRYPT(r,l,24); /* 13 */ + D_ENCRYPT(l,r,22); /* 12 */ + D_ENCRYPT(r,l,20); /* 11 */ + D_ENCRYPT(l,r,18); /* 10 */ + D_ENCRYPT(r,l,16); /* 9 */ + D_ENCRYPT(l,r,14); /* 8 */ + D_ENCRYPT(r,l,12); /* 7 */ + D_ENCRYPT(l,r,10); /* 6 */ + D_ENCRYPT(r,l, 8); /* 5 */ + D_ENCRYPT(l,r, 6); /* 4 */ + D_ENCRYPT(r,l, 4); /* 3 */ + D_ENCRYPT(l,r, 2); /* 2 */ + D_ENCRYPT(r,l, 0); /* 1 */ +#else + for (i=30; i>0; i-=8) + { + D_ENCRYPT(l,r,i-0); /* 16 */ + D_ENCRYPT(r,l,i-2); /* 15 */ + D_ENCRYPT(l,r,i-4); /* 14 */ + D_ENCRYPT(r,l,i-6); /* 13 */ + } +#endif + } + /* rotate and clear the top bits on machines with 8byte longs */ + data[0]=ROTATE(l,3)&0xffffffffL; + data[1]=ROTATE(r,3)&0xffffffffL; + l=r=t=u=0; + } + +void des_encrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3) + { + register DES_LONG l,r; + + l=data[0]; + r=data[1]; + IP(l,r); + data[0]=l; + data[1]=r; + des_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT); + des_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT); + des_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT); + l=data[0]; + r=data[1]; + FP(r,l); + data[0]=l; + data[1]=r; + } + +void des_decrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3) + { + register DES_LONG l,r; + + l=data[0]; + r=data[1]; + IP(l,r); + data[0]=l; + data[1]=r; + des_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT); + des_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT); + des_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT); + l=data[0]; + r=data[1]; + FP(r,l); + data[0]=l; + data[1]=r; + } + +#ifndef DES_DEFAULT_OPTIONS + +void des_ncbc_encrypt(des_cblock (*input), des_cblock (*output), long length, des_key_schedule schedule, des_cblock (*ivec), int enc) + { + register DES_LONG tin0,tin1; + register DES_LONG tout0,tout1,xor0,xor1; + register unsigned char *in,*out; + register long l=length; + DES_LONG tin[2]; + unsigned char *iv; + + in=(unsigned char *)input; + out=(unsigned char *)output; + iv=(unsigned char *)ivec; + + if (enc) + { + c2l(iv,tout0); + c2l(iv,tout1); + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); + c2l(in,tin1); + tin0^=tout0; tin[0]=tin0; + tin1^=tout1; tin[1]=tin1; + des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + tout0=tin[0]; l2c(tout0,out); + tout1=tin[1]; l2c(tout1,out); + } + if (l != -8) + { + c2ln(in,tin0,tin1,l+8); + tin0^=tout0; tin[0]=tin0; + tin1^=tout1; tin[1]=tin1; + des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT); + tout0=tin[0]; l2c(tout0,out); + tout1=tin[1]; l2c(tout1,out); + } + iv=(unsigned char *)ivec; + l2c(tout0,iv); + l2c(tout1,iv); + } + else + { + c2l(iv,xor0); + c2l(iv,xor1); + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2c(tout0,out); + l2c(tout1,out); + xor0=tin0; + xor1=tin1; + } + if (l != -8) + { + c2l(in,tin0); tin[0]=tin0; + c2l(in,tin1); tin[1]=tin1; + des_encrypt((DES_LONG *)tin,schedule,DES_DECRYPT); + tout0=tin[0]^xor0; + tout1=tin[1]^xor1; + l2cn(tout0,tout1,out,l+8); + xor0=tin0; + xor1=tin1; + } + + iv=(unsigned char *)ivec; + l2c(xor0,iv); + l2c(xor1,iv); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +void des_ede3_cbc_encrypt(des_cblock (*input), des_cblock (*output), long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock (*ivec), int enc) + { + register DES_LONG tin0,tin1; + register DES_LONG tout0,tout1,xor0,xor1; + register unsigned char *in,*out; + register long l=length; + DES_LONG tin[2]; + unsigned char *iv; + + in=(unsigned char *)input; + out=(unsigned char *)output; + iv=(unsigned char *)ivec; + + if (enc) + { + c2l(iv,tout0); + c2l(iv,tout1); + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); + c2l(in,tin1); + tin0^=tout0; + tin1^=tout1; + + tin[0]=tin0; + tin[1]=tin1; + des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); + tout0=tin[0]; + tout1=tin[1]; + + l2c(tout0,out); + l2c(tout1,out); + } + if (l != -8) + { + c2ln(in,tin0,tin1,l+8); + tin0^=tout0; + tin1^=tout1; + + tin[0]=tin0; + tin[1]=tin1; + des_encrypt3((DES_LONG *)tin,ks1,ks2,ks3); + tout0=tin[0]; + tout1=tin[1]; + + l2c(tout0,out); + l2c(tout1,out); + } + iv=(unsigned char *)ivec; + l2c(tout0,iv); + l2c(tout1,iv); + } + else + { + register DES_LONG t0,t1; + + c2l(iv,xor0); + c2l(iv,xor1); + for (l-=8; l>=0; l-=8) + { + c2l(in,tin0); + c2l(in,tin1); + + t0=tin0; + t1=tin1; + + tin[0]=tin0; + tin[1]=tin1; + des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); + tout0=tin[0]; + tout1=tin[1]; + + tout0^=xor0; + tout1^=xor1; + l2c(tout0,out); + l2c(tout1,out); + xor0=t0; + xor1=t1; + } + if (l != -8) + { + c2l(in,tin0); + c2l(in,tin1); + + t0=tin0; + t1=tin1; + + tin[0]=tin0; + tin[1]=tin1; + des_decrypt3((DES_LONG *)tin,ks1,ks2,ks3); + tout0=tin[0]; + tout1=tin[1]; + + tout0^=xor0; + tout1^=xor1; + l2cn(tout0,tout1,out,l+8); + xor0=t0; + xor1=t1; + } + + iv=(unsigned char *)ivec; + l2c(xor0,iv); + l2c(xor1,iv); + } + tin0=tin1=tout0=tout1=xor0=xor1=0; + tin[0]=tin[1]=0; + } + +#endif /* DES_DEFAULT_OPTIONS */ diff --git a/src/utils/crypto/des_locl.h b/src/utils/crypto/des_locl.h new file mode 100644 index 000000000..116b41d95 --- /dev/null +++ b/src/utils/crypto/des_locl.h @@ -0,0 +1,518 @@ +/* Deprecated/legacy */ + +/* crypto/des/des_locl.org */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * + * Always modify des_locl.org since des_locl.h is automatically generated from + * it during SSLeay configuration. + * + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + */ + +#ifndef HEADER_DES_LOCL_H +#define HEADER_DES_LOCL_H + +#if defined(WIN32) || defined(WIN16) +#ifndef MSDOS +#define MSDOS +#endif +#endif + +#include +#include +#ifndef MSDOS +#include +#endif +#include "des.h" + +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#define DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependancies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#define DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very mucy CPU dependant */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ + #define DES_PTR + #define DES_RISC1 + #define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ + #define DES_PTR + #define DES_RISC2 + #define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ + #define DES_PTR + #define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ + #define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ + #define DES_PTR + #define DES_RISC2 + #define DES_UNROLL +#elif defined( i386 ) /* x86 boxes, should be gcc */ + #define DES_PTR + #define DES_RISC1 + #define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ + +#ifdef MSDOS /* Visual C++ 2.1 (Windows NT/95) */ +#include +#include +#include +#include +#ifndef RAND +#define RAND +#endif +#undef NOPROTO +#endif + +#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS) +#include +#endif + +#ifndef RAND +#define RAND +#endif + +#ifdef linux +#undef RAND +#endif + +#ifdef MSDOS +#define getpid() 2 +#define RAND +#undef NOPROTO +#endif + +#if defined(NOCONST) +#define const +#endif + +#ifdef __STDC__ +#undef NOPROTO +#endif + +#ifdef RAND +#define srandom(s) srand(s) +#define random rand +#endif + +#define ITERATIONS 16 +#define HALF_ITERATIONS 8 + +/* used in des_read and des_write */ +#define MAXWRITE (1024*16) +#define BSIZE (MAXWRITE+4) + +#define c2l(c,l) (l =((DES_LONG)(*((c)++))) , \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<<24L) + +/* NOTE - c is not incremented as per c2l */ +#define c2ln(c,l1,l2,n) { \ + c+=n; \ + l1=l2=0; \ + switch (n) { \ + case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ + case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ + case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ + case 5: l2|=((DES_LONG)(*(--(c)))); \ + case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ + case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ + case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ + case 1: l1|=((DES_LONG)(*(--(c)))); \ + } \ + } + +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24L)&0xff)) + +/* replacements for htonl and ntohl since I have no idea what to do + * when faced with machines with 8 byte longs. */ +#define HDRSIZE 4 + +#define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ + l|=((DES_LONG)(*((c)++)))<<16L, \ + l|=((DES_LONG)(*((c)++)))<< 8L, \ + l|=((DES_LONG)(*((c)++)))) + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* NOTE - c is not incremented as per l2c */ +#define l2cn(l1,l2,c,n) { \ + c+=n; \ + switch (n) { \ + case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ + case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ + case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ + case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ + case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ + case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ + case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ + case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ + } \ + } + +//#if defined(WIN32) +//#define ROTATE(a,n) (_lrotr(a,n)) +//#else +#define ROTATE(a,n) (((a)>>(n))+((a)<<(32-(n)))) +//#endif + +/* Don't worry about the LOAD_DATA() stuff, that is used by + * fcrypt() to add it's little bit to the front */ + +#ifdef DES_FCRYPT + +#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \ + { DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); } + +#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + t=R^(R>>16L); \ + u=t&E0; t&=E1; \ + tmp=(u<<16); u^=R^s[S ]; u^=tmp; \ + tmp=(t<<16); t^=R^s[S+1]; t^=tmp +#else +#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g) +#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \ + u=R^s[S ]; \ + t=R^s[S+1] +#endif + +/* The changes to this macro may help or hinder, depending on the + * compiler and the achitecture. gcc2 always seems to do well :-). + * Inspired by Dana How + * DO NOT use the alternative version on machines with 8 byte longs. + * It does not seem to work on the Alpha, even when DES_LONG is 4 + * bytes, probably an issue of accessing non-word aligned objects :-( */ +#ifdef DES_PTR + +/* It recently occured to me that 0^0^0^0^0^0^0 == 0, so there + * is no reason to not xor all the sub items together. This potentially + * saves a register since things can be xored directly into L */ + +#if defined(DES_RISC1) || defined(DES_RISC2) +#ifdef DES_RISC1 +#define D_ENCRYPT(LL,R,S) { \ + unsigned int u1,u2,u3; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u2=(int)u>>8L; \ + u1=(int)u&0xfc; \ + u2&=0xfc; \ + t=ROTATE(t,4); \ + u>>=16L; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ + u3=(int)(u>>8L); \ + u1=(int)u&0xfc; \ + u3&=0xfc; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+u1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+u3); \ + u2=(int)t>>8L; \ + u1=(int)t&0xfc; \ + u2&=0xfc; \ + t>>=16L; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ + u3=(int)t>>8L; \ + u1=(int)t&0xfc; \ + u3&=0xfc; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+u1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+u3); } +#endif +#ifdef DES_RISC2 +#define D_ENCRYPT(LL,R,S) { \ + unsigned int u1,u2,s1,s2; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u2=(int)u>>8L; \ + u1=(int)u&0xfc; \ + u2&=0xfc; \ + t=ROTATE(t,4); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP +u1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x200+u2); \ + s1=(int)(u>>16L); \ + s2=(int)(u>>24L); \ + s1&=0xfc; \ + s2&=0xfc; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x400+s1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x600+s2); \ + u2=(int)t>>8L; \ + u1=(int)t&0xfc; \ + u2&=0xfc; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x100+u1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x300+u2); \ + s1=(int)(t>>16L); \ + s2=(int)(t>>24L); \ + s1&=0xfc; \ + s2&=0xfc; \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x500+s1); \ + LL^= *(DES_LONG *)((unsigned char *)des_SP+0x700+s2); } +#endif +#else +#define D_ENCRYPT(LL,R,S) { \ + LOAD_DATA_tmp(R,S,u,t,E0,E1); \ + t=ROTATE(t,4); \ + LL^= \ + *(DES_LONG *)((unsigned char *)des_SP +((u )&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x200+((u>> 8L)&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x400+((u>>16L)&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x600+((u>>24L)&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x100+((t )&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x300+((t>> 8L)&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x500+((t>>16L)&0xfc))^ \ + *(DES_LONG *)((unsigned char *)des_SP+0x700+((t>>24L)&0xfc)); } +#endif + +#else /* original version */ + +#if defined(DES_RISC1) || defined(DES_RISC2) +#ifdef DES_RISC1 +#define D_ENCRYPT(LL,R,S) {\ + unsigned int u1,u2,u3; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u>>=2L; \ + t=ROTATE(t,6); \ + u2=(int)u>>8L; \ + u1=(int)u&0x3f; \ + u2&=0x3f; \ + u>>=16L; \ + LL^=des_SPtrans[0][u1]; \ + LL^=des_SPtrans[2][u2]; \ + u3=(int)u>>8L; \ + u1=(int)u&0x3f; \ + u3&=0x3f; \ + LL^=des_SPtrans[4][u1]; \ + LL^=des_SPtrans[6][u3]; \ + u2=(int)t>>8L; \ + u1=(int)t&0x3f; \ + u2&=0x3f; \ + t>>=16L; \ + LL^=des_SPtrans[1][u1]; \ + LL^=des_SPtrans[3][u2]; \ + u3=(int)t>>8L; \ + u1=(int)t&0x3f; \ + u3&=0x3f; \ + LL^=des_SPtrans[5][u1]; \ + LL^=des_SPtrans[7][u3]; } +#endif +#ifdef DES_RISC2 +#define D_ENCRYPT(LL,R,S) {\ + unsigned int u1,u2,s1,s2; \ + LOAD_DATA(R,S,u,t,E0,E1,u1); \ + u>>=2L; \ + t=ROTATE(t,6); \ + u2=(int)u>>8L; \ + u1=(int)u&0x3f; \ + u2&=0x3f; \ + LL^=des_SPtrans[0][u1]; \ + LL^=des_SPtrans[2][u2]; \ + s1=(int)u>>16L; \ + s2=(int)u>>24L; \ + s1&=0x3f; \ + s2&=0x3f; \ + LL^=des_SPtrans[4][s1]; \ + LL^=des_SPtrans[6][s2]; \ + u2=(int)t>>8L; \ + u1=(int)t&0x3f; \ + u2&=0x3f; \ + LL^=des_SPtrans[1][u1]; \ + LL^=des_SPtrans[3][u2]; \ + s1=(int)t>>16; \ + s2=(int)t>>24L; \ + s1&=0x3f; \ + s2&=0x3f; \ + LL^=des_SPtrans[5][s1]; \ + LL^=des_SPtrans[7][s2]; } +#endif + +#else + +#define D_ENCRYPT(LL,R,S) {\ + LOAD_DATA_tmp(R,S,u,t,E0,E1); \ + t=ROTATE(t,4); \ + LL^=\ + des_SPtrans[0][(u>> 2L)&0x3f]^ \ + des_SPtrans[2][(u>>10L)&0x3f]^ \ + des_SPtrans[4][(u>>18L)&0x3f]^ \ + des_SPtrans[6][(u>>26L)&0x3f]^ \ + des_SPtrans[1][(t>> 2L)&0x3f]^ \ + des_SPtrans[3][(t>>10L)&0x3f]^ \ + des_SPtrans[5][(t>>18L)&0x3f]^ \ + des_SPtrans[7][(t>>26L)&0x3f]; } +#endif +#endif + + /* IP and FP + * The problem is more of a geometric problem that random bit fiddling. + 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + + 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + + The output has been subject to swaps of the form + 0 1 -> 3 1 but the odd and even bits have been put into + 2 3 2 0 + different words. The main trick is to remember that + t=((l>>size)^r)&(mask); + r^=t; + l^=(t<>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +#define IP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(r,l,tt, 4,0x0f0f0f0fL); \ + PERM_OP(l,r,tt,16,0x0000ffffL); \ + PERM_OP(r,l,tt, 2,0x33333333L); \ + PERM_OP(l,r,tt, 8,0x00ff00ffL); \ + PERM_OP(r,l,tt, 1,0x55555555L); \ + } + +#define FP(l,r) \ + { \ + register DES_LONG tt; \ + PERM_OP(l,r,tt, 1,0x55555555L); \ + PERM_OP(r,l,tt, 8,0x00ff00ffL); \ + PERM_OP(l,r,tt, 2,0x33333333L); \ + PERM_OP(r,l,tt,16,0x0000ffffL); \ + PERM_OP(l,r,tt, 4,0x0f0f0f0fL); \ + } + +extern const DES_LONG des_SPtrans[8][64]; + +#ifndef NOPROTO +void fcrypt_body(DES_LONG *out,des_key_schedule ks, + DES_LONG Eswap0, DES_LONG Eswap1); +#else +void fcrypt_body(); +#endif + +#endif diff --git a/src/utils/crypto/ecb3_enc.c b/src/utils/crypto/ecb3_enc.c new file mode 100644 index 000000000..ff4661f64 --- /dev/null +++ b/src/utils/crypto/ecb3_enc.c @@ -0,0 +1,84 @@ +/* Deprecated/legacy */ + +/* crypto/des/ecb3_enc.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "des_locl.h" + + +void des_ecb3_encrypt(des_cblock (*input), des_cblock (*output), des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, int enc) + { + register DES_LONG l0,l1; + register unsigned char *in,*out; + DES_LONG ll[2]; + + in=(unsigned char *)input; + out=(unsigned char *)output; + c2l(in,l0); + c2l(in,l1); + ll[0]=l0; + ll[1]=l1; + if (enc) + des_encrypt3(ll,ks1,ks2,ks3); + else + des_decrypt3(ll,ks1,ks2,ks3); + l0=ll[0]; + l1=ll[1]; + l2c(l0,out); + l2c(l1,out); + } diff --git a/src/utils/crypto/podd.h b/src/utils/crypto/podd.h new file mode 100644 index 000000000..d4083b428 --- /dev/null +++ b/src/utils/crypto/podd.h @@ -0,0 +1,77 @@ +/* Deprecated/legacy */ + +/* crypto/des/podd.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +static const unsigned char odd_parity[256]={ + 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, + 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, + 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, + 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, + 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, + 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, + 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, +112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, +128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, +145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, +161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, +176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, +193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, +208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, +224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, +241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; diff --git a/src/utils/crypto/rmd160.c b/src/utils/crypto/rmd160.c new file mode 100644 index 000000000..7a273022f --- /dev/null +++ b/src/utils/crypto/rmd160.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160", + * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997, + * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf + */ + +/* Adapted by TrueCrypt Foundation */ + +#include "rmd160.h" +#include "../common/endian.h" +#include + +#define PUT_64BIT_LE(cp, value) do { \ + (cp)[7] = (unsigned char)((value) >> 56); \ + (cp)[6] = (unsigned char)((value) >> 48); \ + (cp)[5] = (unsigned char)((value) >> 40); \ + (cp)[4] = (unsigned char)((value) >> 32); \ + (cp)[3] = (unsigned char)((value) >> 24); \ + (cp)[2] = (unsigned char)((value) >> 16); \ + (cp)[1] = (unsigned char)((value) >> 8); \ + (cp)[0] = (unsigned char)(value); } while (0) + +#define PUT_32BIT_LE(cp, value) do { \ + (cp)[3] = (unsigned char)((value) >> 24); \ + (cp)[2] = (unsigned char)((value) >> 16); \ + (cp)[1] = (unsigned char)((value) >> 8); \ + (cp)[0] = (unsigned char)(value); } while (0) + +#define H0 0x67452301U +#define H1 0xEFCDAB89U +#define H2 0x98BADCFEU +#define H3 0x10325476U +#define H4 0xC3D2E1F0U + +#define K0 0x00000000U +#define K1 0x5A827999U +#define K2 0x6ED9EBA1U +#define K3 0x8F1BBCDCU +#define K4 0xA953FD4EU + +#define KK0 0x50A28BE6U +#define KK1 0x5C4DD124U +#define KK2 0x6D703EF3U +#define KK3 0x7A6D76E9U +#define KK4 0x00000000U + +/* rotate x left n bits. */ + +#if defined (_MSC_VER) && !defined (_DEBUG) +#include +# pragma intrinsic (_lrotl) +# define ROL(n, x) (_lrotl (x, n)) +#else +# define ROL(n, x) (((x) << (n)) | ((x) >> (32-(n)))) +#endif + +#define F0(x, y, z) ((x) ^ (y) ^ (z)) +#define F1(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define F2(x, y, z) (((x) | (~y)) ^ (z)) +#define F3(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define F4(x, y, z) ((x) ^ ((y) | (~z))) + +#define R(a, b, c, d, e, Fj, Kj, sj, rj) \ + do { \ + a = ROL(sj, a + Fj(b,c,d) + X(rj) + Kj) + e; \ + c = ROL(10, c); \ + } while(0) + +#define X(i) x[i] + +#ifndef TC_MINIMIZE_CODE_SIZE + +static u_char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#else + +static u_char PADDING[64]; + +#endif + +void +RMD160Init(RMD160_CTX *ctx) +{ + ctx->count = 0; + ctx->state[0] = H0; + ctx->state[1] = H1; + ctx->state[2] = H2; + ctx->state[3] = H3; + ctx->state[4] = H4; + + PADDING[0] = 0x80; +} + +void +RMD160Update(RMD160_CTX *ctx, const u_char *input, u_int32_t len) +{ + u_int32_t have, off, need; + u_char buf[64] = { 0 }; + + have = (uint32_t)((ctx->count/8) % 64); + need = 64 - have; + ctx->count += 8 * len; + off = 0; + + if (len >= need) { + if (have) { + memcpy(ctx->buffer + have, input, (size_t) need); + RMD160Transform(ctx->state, ctx->buffer); + off = need; + have = 0; + } + /* now the buffer is empty */ + while (off + 64 <= len) { + if ((len - off) < 64) { + memset(buf, 0x00, 64); + memcpy(buf, input + off, len - off); + RMD160Transform(ctx->state, buf); + } else + RMD160Transform(ctx->state, input + off); + off += 64; + } + } + if (off < len) + memcpy(ctx->buffer + have, input+off, (size_t) (len-off)); +} + +void RMD160Final(u_char digest[20], RMD160_CTX *ctx) +{ + int i; + u_char size[8]; + u_int32_t padlen; + +#ifndef TC_NO_COMPILER_INT64 + PUT_64BIT_LE(size, ctx->count); +#else + *(uint32_t *) (size + 4) = 0; + PUT_32BIT_LE(size, ctx->count); +#endif + /* + * pad to 64 byte blocks, at least one byte from PADDING plus 8 bytes + * for the size + */ + padlen = (uint32_t)(64 - ((ctx->count/8) % 64)); + if (padlen < 1 + 8) + padlen += 64; + RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ + RMD160Update(ctx, size, 8); + + if (digest != 0) + for (i = 0; i < 5; i++) + PUT_32BIT_LE(digest + i*4, ctx->state[i]); + + memset(ctx, 0, sizeof (*ctx)); +} + +#ifndef TC_MINIMIZE_CODE_SIZE + +void +RMD160Transform(u_int32_t state[5], const u_char block[64]) +{ + u_int32_t a, b, c, d, e, aa, bb, cc, dd, ee, t, x[16]; + +#if BYTE_ORDER == LITTLE_ENDIAN + memcpy(x, block, 64); +#else + int i; + + for (i = 0; i < 16; i++) + x[i] = (u_int32_t)( + (u_int32_t)(block[i*4 + 0]) | + (u_int32_t)(block[i*4 + 1]) << 8 | + (u_int32_t)(block[i*4 + 2]) << 16 | + (u_int32_t)(block[i*4 + 3]) << 24); +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* Round 1 */ + R(a, b, c, d, e, F0, K0, 11, 0); + R(e, a, b, c, d, F0, K0, 14, 1); + R(d, e, a, b, c, F0, K0, 15, 2); + R(c, d, e, a, b, F0, K0, 12, 3); + R(b, c, d, e, a, F0, K0, 5, 4); + R(a, b, c, d, e, F0, K0, 8, 5); + R(e, a, b, c, d, F0, K0, 7, 6); + R(d, e, a, b, c, F0, K0, 9, 7); + R(c, d, e, a, b, F0, K0, 11, 8); + R(b, c, d, e, a, F0, K0, 13, 9); + R(a, b, c, d, e, F0, K0, 14, 10); + R(e, a, b, c, d, F0, K0, 15, 11); + R(d, e, a, b, c, F0, K0, 6, 12); + R(c, d, e, a, b, F0, K0, 7, 13); + R(b, c, d, e, a, F0, K0, 9, 14); + R(a, b, c, d, e, F0, K0, 8, 15); /* #15 */ + /* Round 2 */ + R(e, a, b, c, d, F1, K1, 7, 7); + R(d, e, a, b, c, F1, K1, 6, 4); + R(c, d, e, a, b, F1, K1, 8, 13); + R(b, c, d, e, a, F1, K1, 13, 1); + R(a, b, c, d, e, F1, K1, 11, 10); + R(e, a, b, c, d, F1, K1, 9, 6); + R(d, e, a, b, c, F1, K1, 7, 15); + R(c, d, e, a, b, F1, K1, 15, 3); + R(b, c, d, e, a, F1, K1, 7, 12); + R(a, b, c, d, e, F1, K1, 12, 0); + R(e, a, b, c, d, F1, K1, 15, 9); + R(d, e, a, b, c, F1, K1, 9, 5); + R(c, d, e, a, b, F1, K1, 11, 2); + R(b, c, d, e, a, F1, K1, 7, 14); + R(a, b, c, d, e, F1, K1, 13, 11); + R(e, a, b, c, d, F1, K1, 12, 8); /* #31 */ + /* Round 3 */ + R(d, e, a, b, c, F2, K2, 11, 3); + R(c, d, e, a, b, F2, K2, 13, 10); + R(b, c, d, e, a, F2, K2, 6, 14); + R(a, b, c, d, e, F2, K2, 7, 4); + R(e, a, b, c, d, F2, K2, 14, 9); + R(d, e, a, b, c, F2, K2, 9, 15); + R(c, d, e, a, b, F2, K2, 13, 8); + R(b, c, d, e, a, F2, K2, 15, 1); + R(a, b, c, d, e, F2, K2, 14, 2); + R(e, a, b, c, d, F2, K2, 8, 7); + R(d, e, a, b, c, F2, K2, 13, 0); + R(c, d, e, a, b, F2, K2, 6, 6); + R(b, c, d, e, a, F2, K2, 5, 13); + R(a, b, c, d, e, F2, K2, 12, 11); + R(e, a, b, c, d, F2, K2, 7, 5); + R(d, e, a, b, c, F2, K2, 5, 12); /* #47 */ + /* Round 4 */ + R(c, d, e, a, b, F3, K3, 11, 1); + R(b, c, d, e, a, F3, K3, 12, 9); + R(a, b, c, d, e, F3, K3, 14, 11); + R(e, a, b, c, d, F3, K3, 15, 10); + R(d, e, a, b, c, F3, K3, 14, 0); + R(c, d, e, a, b, F3, K3, 15, 8); + R(b, c, d, e, a, F3, K3, 9, 12); + R(a, b, c, d, e, F3, K3, 8, 4); + R(e, a, b, c, d, F3, K3, 9, 13); + R(d, e, a, b, c, F3, K3, 14, 3); + R(c, d, e, a, b, F3, K3, 5, 7); + R(b, c, d, e, a, F3, K3, 6, 15); + R(a, b, c, d, e, F3, K3, 8, 14); + R(e, a, b, c, d, F3, K3, 6, 5); + R(d, e, a, b, c, F3, K3, 5, 6); + R(c, d, e, a, b, F3, K3, 12, 2); /* #63 */ + /* Round 5 */ + R(b, c, d, e, a, F4, K4, 9, 4); + R(a, b, c, d, e, F4, K4, 15, 0); + R(e, a, b, c, d, F4, K4, 5, 5); + R(d, e, a, b, c, F4, K4, 11, 9); + R(c, d, e, a, b, F4, K4, 6, 7); + R(b, c, d, e, a, F4, K4, 8, 12); + R(a, b, c, d, e, F4, K4, 13, 2); + R(e, a, b, c, d, F4, K4, 12, 10); + R(d, e, a, b, c, F4, K4, 5, 14); + R(c, d, e, a, b, F4, K4, 12, 1); + R(b, c, d, e, a, F4, K4, 13, 3); + R(a, b, c, d, e, F4, K4, 14, 8); + R(e, a, b, c, d, F4, K4, 11, 11); + R(d, e, a, b, c, F4, K4, 8, 6); + R(c, d, e, a, b, F4, K4, 5, 15); + R(b, c, d, e, a, F4, K4, 6, 13); /* #79 */ + + aa = a ; bb = b; cc = c; dd = d; ee = e; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* Parallel round 1 */ + R(a, b, c, d, e, F4, KK0, 8, 5); + R(e, a, b, c, d, F4, KK0, 9, 14); + R(d, e, a, b, c, F4, KK0, 9, 7); + R(c, d, e, a, b, F4, KK0, 11, 0); + R(b, c, d, e, a, F4, KK0, 13, 9); + R(a, b, c, d, e, F4, KK0, 15, 2); + R(e, a, b, c, d, F4, KK0, 15, 11); + R(d, e, a, b, c, F4, KK0, 5, 4); + R(c, d, e, a, b, F4, KK0, 7, 13); + R(b, c, d, e, a, F4, KK0, 7, 6); + R(a, b, c, d, e, F4, KK0, 8, 15); + R(e, a, b, c, d, F4, KK0, 11, 8); + R(d, e, a, b, c, F4, KK0, 14, 1); + R(c, d, e, a, b, F4, KK0, 14, 10); + R(b, c, d, e, a, F4, KK0, 12, 3); + R(a, b, c, d, e, F4, KK0, 6, 12); /* #15 */ + /* Parallel round 2 */ + R(e, a, b, c, d, F3, KK1, 9, 6); + R(d, e, a, b, c, F3, KK1, 13, 11); + R(c, d, e, a, b, F3, KK1, 15, 3); + R(b, c, d, e, a, F3, KK1, 7, 7); + R(a, b, c, d, e, F3, KK1, 12, 0); + R(e, a, b, c, d, F3, KK1, 8, 13); + R(d, e, a, b, c, F3, KK1, 9, 5); + R(c, d, e, a, b, F3, KK1, 11, 10); + R(b, c, d, e, a, F3, KK1, 7, 14); + R(a, b, c, d, e, F3, KK1, 7, 15); + R(e, a, b, c, d, F3, KK1, 12, 8); + R(d, e, a, b, c, F3, KK1, 7, 12); + R(c, d, e, a, b, F3, KK1, 6, 4); + R(b, c, d, e, a, F3, KK1, 15, 9); + R(a, b, c, d, e, F3, KK1, 13, 1); + R(e, a, b, c, d, F3, KK1, 11, 2); /* #31 */ + /* Parallel round 3 */ + R(d, e, a, b, c, F2, KK2, 9, 15); + R(c, d, e, a, b, F2, KK2, 7, 5); + R(b, c, d, e, a, F2, KK2, 15, 1); + R(a, b, c, d, e, F2, KK2, 11, 3); + R(e, a, b, c, d, F2, KK2, 8, 7); + R(d, e, a, b, c, F2, KK2, 6, 14); + R(c, d, e, a, b, F2, KK2, 6, 6); + R(b, c, d, e, a, F2, KK2, 14, 9); + R(a, b, c, d, e, F2, KK2, 12, 11); + R(e, a, b, c, d, F2, KK2, 13, 8); + R(d, e, a, b, c, F2, KK2, 5, 12); + R(c, d, e, a, b, F2, KK2, 14, 2); + R(b, c, d, e, a, F2, KK2, 13, 10); + R(a, b, c, d, e, F2, KK2, 13, 0); + R(e, a, b, c, d, F2, KK2, 7, 4); + R(d, e, a, b, c, F2, KK2, 5, 13); /* #47 */ + /* Parallel round 4 */ + R(c, d, e, a, b, F1, KK3, 15, 8); + R(b, c, d, e, a, F1, KK3, 5, 6); + R(a, b, c, d, e, F1, KK3, 8, 4); + R(e, a, b, c, d, F1, KK3, 11, 1); + R(d, e, a, b, c, F1, KK3, 14, 3); + R(c, d, e, a, b, F1, KK3, 14, 11); + R(b, c, d, e, a, F1, KK3, 6, 15); + R(a, b, c, d, e, F1, KK3, 14, 0); + R(e, a, b, c, d, F1, KK3, 6, 5); + R(d, e, a, b, c, F1, KK3, 9, 12); + R(c, d, e, a, b, F1, KK3, 12, 2); + R(b, c, d, e, a, F1, KK3, 9, 13); + R(a, b, c, d, e, F1, KK3, 12, 9); + R(e, a, b, c, d, F1, KK3, 5, 7); + R(d, e, a, b, c, F1, KK3, 15, 10); + R(c, d, e, a, b, F1, KK3, 8, 14); /* #63 */ + /* Parallel round 5 */ + R(b, c, d, e, a, F0, KK4, 8, 12); + R(a, b, c, d, e, F0, KK4, 5, 15); + R(e, a, b, c, d, F0, KK4, 12, 10); + R(d, e, a, b, c, F0, KK4, 9, 4); + R(c, d, e, a, b, F0, KK4, 12, 1); + R(b, c, d, e, a, F0, KK4, 5, 5); + R(a, b, c, d, e, F0, KK4, 14, 8); + R(e, a, b, c, d, F0, KK4, 6, 7); + R(d, e, a, b, c, F0, KK4, 8, 6); + R(c, d, e, a, b, F0, KK4, 13, 2); + R(b, c, d, e, a, F0, KK4, 6, 13); + R(a, b, c, d, e, F0, KK4, 5, 14); + R(e, a, b, c, d, F0, KK4, 15, 0); + R(d, e, a, b, c, F0, KK4, 13, 3); + R(c, d, e, a, b, F0, KK4, 11, 9); + R(b, c, d, e, a, F0, KK4, 11, 11); /* #79 */ + + t = state[1] + cc + d; + state[1] = state[2] + dd + e; + state[2] = state[3] + ee + a; + state[3] = state[4] + aa + b; + state[4] = state[0] + bb + c; + state[0] = t; +} + +#else // TC_MINIMIZE_CODE_SIZE + +/* + Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + + Governed by the TrueCrypt License 2.4 the full text of which is contained + in the file License.txt included in TrueCrypt binary and source code + distribution packages. +*/ + +#pragma optimize ("tl", on) + +typedef uint32_t uint32; +typedef unsigned __int8 byte; + +static const byte OrderTab[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +}; + +static const byte RolTab[] = { + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6, + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +}; + +static const uint32 KTab[] = { + 0x00000000UL, + 0x5A827999UL, + 0x6ED9EBA1UL, + 0x8F1BBCDCUL, + 0xA953FD4EUL, + 0x50A28BE6UL, + 0x5C4DD124UL, + 0x6D703EF3UL, + 0x7A6D76E9UL, + 0x00000000UL +}; + + +void RMD160Transform (u_int32_t state[5], const u_char block[64]) +{ + uint32 a, b, c, d, e; + uint32 a2, b2, c2, d2, e2; + uint32 *data = (uint32 *) block; + byte pos; + uint32 tmp; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + for (pos = 0; pos < 160; ++pos) + { + tmp = a + data[OrderTab[pos]] + KTab[pos >> 4]; + + switch (pos >> 4) + { + case 0: case 9: tmp += F0 (b, c, d); break; + case 1: case 8: tmp += F1 (b, c, d); break; + case 2: case 7: tmp += F2 (b, c, d); break; + case 3: case 6: tmp += F3 (b, c, d); break; + case 4: case 5: tmp += F4 (b, c, d); break; + } + + tmp = ROL (RolTab[pos], tmp) + e; + a = e; + e = d; + d = ROL (10, c); + c = b; + b = tmp; + + if (pos == 79) + { + a2 = a; + b2 = b; + c2 = c; + d2 = d; + e2 = e; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + } + } + + tmp = state[1] + c2 + d; + state[1] = state[2] + d2 + e; + state[2] = state[3] + e2 + a; + state[3] = state[4] + a2 + b; + state[4] = state[0] + b2 + c; + state[0] = tmp; +} + +#endif // TC_MINIMIZE_CODE_SIZE diff --git a/src/utils/crypto/rmd160.h b/src/utils/crypto/rmd160.h new file mode 100644 index 000000000..c97f65439 --- /dev/null +++ b/src/utils/crypto/rmd160.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Adapted by TrueCrypt Foundation */ + +#ifndef _RMD160_H +#define _RMD160_H + +#include + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifndef u_int32_t +#define u_int32_t uint32_t +#define u_int64_t uint64_t +#define u_char uint8_t +#endif + +/* RMD160 context. */ +typedef struct RMD160Context { + u_int32_t state[5]; /* state */ +#ifndef TC_NO_COMPILER_INT64 + u_int64_t count; /* number of bits, modulo 2^64 */ +#else + u_int32_t count; +#endif + u_char buffer[64]; /* input buffer */ +} RMD160_CTX; + +void RMD160Init(RMD160_CTX *); +void RMD160Transform(u_int32_t [5], const u_char [64]); +void RMD160Update(RMD160_CTX *, const u_char *, u_int32_t); +void RMD160Final(u_char [20], RMD160_CTX *); + +#if defined(__cplusplus) +} +#endif + +#endif /* _RMD160_H */ diff --git a/src/utils/crypto/serpent.c b/src/utils/crypto/serpent.c new file mode 100644 index 000000000..5edf17c3d --- /dev/null +++ b/src/utils/crypto/serpent.c @@ -0,0 +1,940 @@ +// serpent.cpp - written and placed in the public domain by Wei Dai + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + + +#include "serpent.h" +#include "../common/endian.h" + +#include + +#if defined(_WIN32) && !defined(_DEBUG) +#include +#define rotlFixed _rotl +#define rotrFixed _rotr +#else +#define rotlFixed(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) +#endif + +// linear transformation +#define LT(i,a,b,c,d,e) {\ + a = rotlFixed(a, 13); \ + c = rotlFixed(c, 3); \ + d = rotlFixed(d ^ c ^ (a << 3), 7); \ + b = rotlFixed(b ^ a ^ c, 1); \ + a = rotlFixed(a ^ b ^ d, 5); \ + c = rotlFixed(c ^ d ^ (b << 7), 22);} + +// inverse linear transformation +#define ILT(i,a,b,c,d,e) {\ + c = rotrFixed(c, 22); \ + a = rotrFixed(a, 5); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + b = rotrFixed(b, 1); \ + d = rotrFixed(d, 7) ^ c ^ (a << 3); \ + b ^= a ^ c; \ + c = rotrFixed(c, 3); \ + a = rotrFixed(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];} + + +#ifdef TC_MINIMIZE_CODE_SIZE + +static void S0f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S1f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S2f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S3f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S4f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S5f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S6f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void S7f (uint32_t *r0, uint32_t *r1, uint32_t *r2, uint32_t *r3, uint32_t *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; +} + +static void KXf (const uint32_t *k, unsigned int r, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ + *a ^= k[r]; + *b ^= k[r + 1]; + *c ^= k[r + 2]; + *d ^= k[r + 3]; +} + +#endif // TC_MINIMIZE_CODE_SIZE + +#ifndef TC_MINIMIZE_CODE_SIZE + +void serpent_set_key(const uint8_t userKey[], int keylen, uint8_t *ks) +{ + uint32_t a,b,c,d,e; + uint32_t *k = (uint32_t *)ks; + uint32_t t; + int i; + + for (i = 0; i < keylen / (int)sizeof(int32_t); i++) + k[i] = LE32(((uint32_t*)userKey)[i]); + + if (keylen < 32) + k[keylen/4] |= (uint32_t)1 << ((keylen%4)*8); + + k += 8; + t = k[-1]; + for (i = 0; i < 132; ++i) + k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + k -= 20; + +#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;} \ + + for (i=0; i<4; 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); +} + +#else // TC_MINIMIZE_CODE_SIZE + +static void LKf (uint32_t *k, unsigned int r, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ + *a = k[r]; + *b = k[r + 1]; + *c = k[r + 2]; + *d = k[r + 3]; +} + +static void SKf (uint32_t *k, unsigned int r, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ + k[r + 4] = *a; + k[r + 5] = *b; + k[r + 6] = *c; + k[r + 7] = *d; +} + +void serpent_set_key(const uint8_t userKey[], int keylen, uint8_t *ks) +{ + uint32_t a,b,c,d,e; + uint32_t *k = (uint32_t *)ks; + uint32_t t; + int i; + + for (i = 0; i < keylen / (int)sizeof(__int32); i++) + k[i] = LE32(((uint32_t*)userKey)[i]); + + if (keylen < 32) + k[keylen/4] |= (uint32_t)1 << ((keylen%4)*8); + + k += 8; + t = k[-1]; + for (i = 0; i < 132; ++i) + k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + k -= 20; + + for (i=0; i<4; i++) + { + LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); + LKf (k, 24, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); SKf (k, 20, &a, &e, &b, &d); + LKf (k, 28, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); SKf (k, 24, &c, &b, &a, &e); + LKf (k, 32, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); SKf (k, 28, &b, &e, &c, &a); + k += 8*4; + LKf (k, 4, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); SKf (k, 0, &d, &e, &b, &a); + LKf (k, 8, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); SKf (k, 4, &a, &c, &d, &b); + LKf (k, 12, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); SKf (k, 8, &a, &c, &b, &e); + LKf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); SKf (k, 12, &b, &a, &e, &c); + } + LKf (k, 20, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); SKf (k, 16, &e, &b, &d, &c); +} + +#endif // TC_MINIMIZE_CODE_SIZE + + +#ifndef TC_MINIMIZE_CODE_SIZE + +void serpent_encrypt(const uint8_t *inBlock, uint8_t *outBlock, uint8_t *ks) +{ + uint32_t a, b, c, d, e; + unsigned int i=1; + const uint32_t *k = (uint32_t *)ks + 8; + uint32_t *in = (uint32_t *) inBlock; + uint32_t *out = (uint32_t *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + 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); + + out[0] = LE32(d); + out[1] = LE32(e); + out[2] = LE32(b); + out[3] = LE32(a); +} + +#else // TC_MINIMIZE_CODE_SIZE + +typedef uint32_t uint32; + +static void LTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) +{ + *a = rotlFixed(*a, 13); + *c = rotlFixed(*c, 3); + *d = rotlFixed(*d ^ *c ^ (*a << 3), 7); + *b = rotlFixed(*b ^ *a ^ *c, 1); + *a = rotlFixed(*a ^ *b ^ *d, 5); + *c = rotlFixed(*c ^ *d ^ (*b << 7), 22); +} + +void serpent_encrypt(const uint8_t *inBlock, uint8_t *outBlock, uint8_t *ks) +{ + uint32_t a, b, c, d, e; + unsigned int i=1; + const uint32_t *k = (uint32_t *)ks + 8; + uint32_t *in = (uint32_t *) inBlock; + uint32_t *out = (uint32_t *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + do + { + KXf (k, 0, &a, &b, &c, &d); S0f (&a, &b, &c, &d, &e); LTf (&b, &e, &c, &a); + KXf (k, 4, &b, &e, &c, &a); S1f (&b, &e, &c, &a, &d); LTf (&c, &b, &a, &e); + KXf (k, 8, &c, &b, &a, &e); S2f (&c, &b, &a, &e, &d); LTf (&a, &e, &b, &d); + KXf (k, 12, &a, &e, &b, &d); S3f (&a, &e, &b, &d, &c); LTf (&e, &b, &d, &c); + KXf (k, 16, &e, &b, &d, &c); S4f (&e, &b, &d, &c, &a); LTf (&b, &a, &e, &c); + KXf (k, 20, &b, &a, &e, &c); S5f (&b, &a, &e, &c, &d); LTf (&a, &c, &b, &e); + KXf (k, 24, &a, &c, &b, &e); S6f (&a, &c, &b, &e, &d); LTf (&a, &c, &d, &b); + KXf (k, 28, &a, &c, &d, &b); S7f (&a, &c, &d, &b, &e); + + if (i == 4) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + LTf (&a,&b,&c,&d); + } + while (1); + + KXf (k, 32, &d, &e, &b, &a); + + out[0] = LE32(d); + out[1] = LE32(e); + out[2] = LE32(b); + out[3] = LE32(a); +} + +#endif // TC_MINIMIZE_CODE_SIZE + +#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_SERPENT) + +void serpent_decrypt(const uint8_t *inBlock, uint8_t *outBlock, uint8_t *ks) +{ + uint32_t a, b, c, d, e; + const uint32_t *k = (uint32_t *)ks + 104; + unsigned int i=4; + uint32_t *in = (uint32_t *) inBlock; + uint32_t *out = (uint32_t *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + 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); + + out[0] = LE32(a); + out[1] = LE32(d); + out[2] = LE32(b); + out[3] = LE32(e); +} + +#else // TC_MINIMIZE_CODE_SIZE && !TC_WINDOWS_BOOT_SERPENT + +static void ILTf (uint32 *a, uint32 *b, uint32 *c, uint32 *d) +{ + *c = rotrFixed(*c, 22); + *a = rotrFixed(*a, 5); + *c ^= *d ^ (*b << 7); + *a ^= *b ^ *d; + *b = rotrFixed(*b, 1); + *d = rotrFixed(*d, 7) ^ *c ^ (*a << 3); + *b ^= *a ^ *c; + *c = rotrFixed(*c, 3); + *a = rotrFixed(*a, 13); +} + +void serpent_decrypt(const uint8_t *inBlock, uint8_t *outBlock, uint8_t *ks) +{ + uint32_t a, b, c, d, e; + const uint32_t *k = (uint32_t *)ks + 104; + unsigned int i=4; + uint32_t *in = (uint32_t *) inBlock; + uint32_t *out = (uint32_t *) outBlock; + + a = LE32(in[0]); + b = LE32(in[1]); + c = LE32(in[2]); + d = LE32(in[3]); + + KXf (k, 32, &a, &b, &c, &d); + goto start; + + do + { + c = b; + b = d; + d = e; + k -= 32; + beforeI7(ILT); +start: + beforeI7(I7); KXf (k, 28, &d, &a, &b, &e); + ILTf (&d, &a, &b, &e); afterI7(I6); KXf (k, 24, &a, &b, &c, &e); + ILTf (&a, &b, &c, &e); afterI6(I5); KXf (k, 20, &b, &d, &e, &c); + ILTf (&b, &d, &e, &c); afterI5(I4); KXf (k, 16, &b, &c, &e, &a); + ILTf (&b, &c, &e, &a); afterI4(I3); KXf (k, 12, &a, &b, &e, &c); + ILTf (&a, &b, &e, &c); afterI3(I2); KXf (k, 8, &b, &d, &e, &c); + ILTf (&b, &d, &e, &c); afterI2(I1); KXf (k, 4, &a, &b, &c, &e); + ILTf (&a, &b, &c, &e); afterI1(I0); KXf (k, 0, &a, &d, &b, &e); + } + while (--i != 0); + + out[0] = LE32(a); + out[1] = LE32(d); + out[2] = LE32(b); + out[3] = LE32(e); +} + +#endif // TC_MINIMIZE_CODE_SIZE && !TC_WINDOWS_BOOT_SERPENT diff --git a/src/utils/crypto/serpent.h b/src/utils/crypto/serpent.h new file mode 100644 index 000000000..484e949f4 --- /dev/null +++ b/src/utils/crypto/serpent.h @@ -0,0 +1,19 @@ +#ifndef HEADER_Crypto_Serpent +#define HEADER_Crypto_Serpent + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void serpent_set_key(const uint8_t userKey[], int keylen, uint8_t *ks); +void serpent_encrypt(const uint8_t *inBlock, uint8_t *outBlock, uint8_t *ks); +void serpent_decrypt(const uint8_t *inBlock, uint8_t *outBlock, uint8_t *ks); + +#ifdef __cplusplus +} +#endif + +#endif // HEADER_Crypto_Serpent diff --git a/src/utils/crypto/set_key.c b/src/utils/crypto/set_key.c new file mode 100644 index 000000000..fe0026dc1 --- /dev/null +++ b/src/utils/crypto/set_key.c @@ -0,0 +1,233 @@ +/* Deprecated/legacy */ + +/* crypto/des/set_key.c */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* set_key.c v 1.4 eay 24/9/91 + * 1.4 Speed up by 400% :-) + * 1.3 added register declarations. + * 1.2 unrolled make_key_sched a bit more + * 1.1 added norm_expand_bits + * 1.0 First working version + */ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + +#include "des_locl.h" +#include "podd.h" +#include "sk.h" + +int des_check_key=1; + +void des_set_odd_parity(des_cblock (*key)) + { + int i; + + for (i=0; i<(int)DES_KEY_SZ; i++) + (*key)[i]=odd_parity[(*key)[i]]; + } + +/* Weak and semi week keys as take from + * %A D.W. Davies + * %A W.L. Price + * %T Security for Computer Networks + * %I John Wiley & Sons + * %D 1984 + * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference + * (and actual cblock values). + */ +#define NUM_WEAK_KEY 18 +static des_cblock weak_keys[NUM_WEAK_KEY]={ + /* weak keys */ + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE}, + {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, + {0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1}, + {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}, + {0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0}, + /* semi-weak keys */ + {0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE}, + {0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01}, + {0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1}, + {0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E}, + {0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1}, + {0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01}, + {0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE}, + {0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E}, + {0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E}, + {0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01}, + {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, + {0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}}; + +int des_is_weak_key(des_cblock (*key)) +{ + int i; + + for (i=0; i>(n))^(b))&(m)),\ + * (b)^=(t),\ + * (a)=((a)^((t)<<(n)))) + */ + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + +/* return 0 if key parity is odd (correct), + * return -1 if key parity error, + * return -2 if illegal weak key. + */ +int des_set_key(des_cblock (*key), des_key_schedule schedule) + { + static int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; + register DES_LONG c,d,t,s,t2; + register unsigned char *in; + register DES_LONG *k; + register int i; + + k=(DES_LONG *)schedule; + in=(unsigned char *)key; + + c2l(in,c); + c2l(in,d); + + /* do PC1 in 60 simple operations */ +/* PERM_OP(d,c,t,4,0x0f0f0f0fL); + HPERM_OP(c,t,-2, 0xcccc0000L); + HPERM_OP(c,t,-1, 0xaaaa0000L); + HPERM_OP(c,t, 8, 0x00ff0000L); + HPERM_OP(c,t,-1, 0xaaaa0000L); + HPERM_OP(d,t,-8, 0xff000000L); + HPERM_OP(d,t, 8, 0x00ff0000L); + HPERM_OP(d,t, 2, 0x33330000L); + d=((d&0x00aa00aaL)<<7L)|((d&0x55005500L)>>7L)|(d&0xaa55aa55L); + d=(d>>8)|((c&0xf0000000L)>>4); + c&=0x0fffffffL; */ + + /* I now do it in 47 simple operations :-) + * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) + * for the inspiration. :-) */ + PERM_OP (d,c,t,4,0x0f0f0f0fL); + HPERM_OP(c,t,-2,0xcccc0000L); + HPERM_OP(d,t,-2,0xcccc0000L); + PERM_OP (d,c,t,1,0x55555555L); + PERM_OP (c,d,t,8,0x00ff00ffL); + PERM_OP (d,c,t,1,0x55555555L); + d= (((d&0x000000ffL)<<16L)| (d&0x0000ff00L) | + ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L)); + c&=0x0fffffffL; + + for (i=0; i>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); } + else + { c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); } + c&=0x0fffffffL; + d&=0x0fffffffL; + /* could be a few less shifts but I am to lazy at this + * point in time to investigate */ + s= des_skb[0][ (c )&0x3f ]| + des_skb[1][((c>> 6)&0x03)|((c>> 7L)&0x3c)]| + des_skb[2][((c>>13)&0x0f)|((c>>14L)&0x30)]| + des_skb[3][((c>>20)&0x01)|((c>>21L)&0x06) | + ((c>>22L)&0x38)]; + t= des_skb[4][ (d )&0x3f ]| + des_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]| + des_skb[6][ (d>>15L)&0x3f ]| + des_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)]; + + /* table contained 0213 4657 */ + t2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL; + *(k++)=ROTATE(t2,30)&0xffffffffL; + + t2=((s>>16L)|(t&0xffff0000L)); + *(k++)=ROTATE(t2,26)&0xffffffffL; + } + + if (des_check_key) + { + //if (!check_parity(key)) + // return(-1); + + if (des_is_weak_key(key)) + return(-2); + } + + return(0); + } + +int des_key_sched(des_cblock (*key), des_key_schedule schedule) + { + return(des_set_key(key,schedule)); + } diff --git a/src/utils/crypto/set_key.h b/src/utils/crypto/set_key.h new file mode 100644 index 000000000..a3f1c689c --- /dev/null +++ b/src/utils/crypto/set_key.h @@ -0,0 +1,6 @@ +/* Deprecated/legacy */ + +void des_set_odd_parity ( des_cblock (*key )); +int des_is_weak_key ( des_cblock (*key )); +int des_set_key ( des_cblock (*key ), des_key_schedule schedule ); +int des_key_sched ( des_cblock (*key ), des_key_schedule schedule ); diff --git a/src/utils/crypto/sha1.c b/src/utils/crypto/sha1.c new file mode 100644 index 000000000..370479ec8 --- /dev/null +++ b/src/utils/crypto/sha1.c @@ -0,0 +1,280 @@ +/* Deprecated/legacy */ + +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 18/06/2004 + + This is a byte oriented version of SHA1 that operates on arrays of bytes + stored in memory. +*/ + +#include /* for memcpy() etc. */ +#include /* for _lrotl with VC++ */ + +#include "sha1.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* + To obtain the highest speed on processors with 32-bit words, this code + needs to determine the order in which bytes are packed into such words. + The following block of code is an attempt to capture the most obvious + ways in which various environemnts specify their endian definitions. + It may well fail, in which case the definitions will need to be set by + editing at the points marked **** EDIT HERE IF NECESSARY **** below. +*/ + +/* PLATFORM SPECIFIC INCLUDES */ + +/* Original byte order detection removed */ +#include "../common/endian.h" + +#define BRG_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define BRG_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_LITTLE_ENDIAN +#endif + +#if BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER BRG_BIG_ENDIAN +#endif + +#ifdef _MSC_VER +#pragma intrinsic(memcpy) +#endif + +#if 1 && defined(_MSC_VER) && !defined(_DEBUG) +#define rotl32 _rotl +#define rotr32 _rotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == BRG_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if defined(SWAP_BYTES) +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((sha1_32t*)p)[_i] = bswap_32(((sha1_32t*)p)[_i]); } +#else +#define bsw_32(p,n) +#endif + +#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) + +#if 0 + +#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#else /* Discovered by Rich Schroeppel and Colin Plumb */ + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + +#endif + +/* Compile 64 bytes of hash data into SHA1 context. Note */ +/* that this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is in such an order that low */ +/* address bytes in the ORIGINAL byte stream will go in */ +/* this buffer to the high end of 32-bit words on BOTH big */ +/* and little endian systems */ + +#ifdef ARRAY +#define q(v,n) v[n] +#else +#define q(v,n) v##n +#endif + +#define one_cycle(v,a,b,c,d,e,f,k,h) \ + q(v,e) += rotr32(q(v,a),27) + \ + f(q(v,b),q(v,c),q(v,d)) + k + h; \ + q(v,b) = rotr32(q(v,b), 2) + +#define five_cycle(v,f,k,i) \ + one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \ + one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \ + one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \ + one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \ + one_cycle(v, 1,2,3,4,0, f,k,hf(i+4)) + +void sha1_compile(sha1_ctx ctx[1]) +{ sha1_32t *w = ctx->wbuf; + +#ifdef ARRAY + sha1_32t v[5]; + memcpy(v, ctx->hash, 5 * sizeof(sha1_32t)); +#else + sha1_32t v0, v1, v2, v3, v4; + v0 = ctx->hash[0]; v1 = ctx->hash[1]; + v2 = ctx->hash[2]; v3 = ctx->hash[3]; + v4 = ctx->hash[4]; +#endif + +#define hf(i) w[i] + + five_cycle(v, ch, 0x5a827999, 0); + five_cycle(v, ch, 0x5a827999, 5); + five_cycle(v, ch, 0x5a827999, 10); + one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \ + +#undef hf +#define hf(i) (w[(i) & 15] = rotl32( \ + w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \ + ^ w[((i) + 2) & 15] ^ w[(i) & 15], 1)) + + one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16)); + one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17)); + one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18)); + one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19)); + + five_cycle(v, parity, 0x6ed9eba1, 20); + five_cycle(v, parity, 0x6ed9eba1, 25); + five_cycle(v, parity, 0x6ed9eba1, 30); + five_cycle(v, parity, 0x6ed9eba1, 35); + + five_cycle(v, maj, 0x8f1bbcdc, 40); + five_cycle(v, maj, 0x8f1bbcdc, 45); + five_cycle(v, maj, 0x8f1bbcdc, 50); + five_cycle(v, maj, 0x8f1bbcdc, 55); + + five_cycle(v, parity, 0xca62c1d6, 60); + five_cycle(v, parity, 0xca62c1d6, 65); + five_cycle(v, parity, 0xca62c1d6, 70); + five_cycle(v, parity, 0xca62c1d6, 75); + +#ifdef ARRAY + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; +#else + ctx->hash[0] += v0; ctx->hash[1] += v1; + ctx->hash[2] += v2; ctx->hash[3] += v3; + ctx->hash[4] += v4; +#endif +} + +void sha1_begin(sha1_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; +} + +/* SHA1 hash data in an array of bytes into hash buffer and */ +/* call the hash_compile function as required. */ + +void sha1_hash(const unsigned char data[], uint32_t len, sha1_ctx ctx[1]) +{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK), + space = SHA1_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks if possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; + bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2); + sha1_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA1 final padding and digest calculation */ + +void sha1_end(unsigned char hval[], sha1_ctx ctx[1]) +{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_32(ctx->wbuf, (i + 3) >> 2); + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); + ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space, pad and empty the buffer */ + if(i > SHA1_BLOCK_SIZE - 9) + { + if(i < 60) ctx->wbuf[15] = 0; + sha1_compile(ctx); + i = 0; + } + else /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + + while(i < 14) /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + + /* the following 32-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 32-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); + ctx->wbuf[15] = ctx->count[0] << 3; + sha1_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* misaligned for 32-bit words */ + for(i = 0; i < SHA1_DIGEST_SIZE; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); +} + +void sha1(unsigned char hval[], const unsigned char data[], uint32_t len) +{ sha1_ctx cx[1]; + + sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); +} + +#if defined(__cplusplus) +} +#endif diff --git a/src/utils/crypto/sha1.h b/src/utils/crypto/sha1.h new file mode 100644 index 000000000..d622f9839 --- /dev/null +++ b/src/utils/crypto/sha1.h @@ -0,0 +1,80 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 26/08/2003 +*/ + +#ifndef _SHA1_H +#define _SHA1_H + +#include +#include + +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DIGEST_SIZE 20 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* define an unsigned 32-bit type */ + +#if defined(_MSC_VER) + typedef uint32_t sha1_32t; +#elif defined(ULONG_MAX) && ULONG_MAX == 0xfffffffful + typedef uint32_t sha1_32t; +#elif defined(UINT_MAX) && UINT_MAX == 0xffffffff + typedef uint32_t sha1_32t; +#else +# error Please define sha1_32t as an unsigned 32 bit type in sha1.h +#endif + +/* type to hold the SHA256 context */ + +typedef struct +{ sha1_32t count[2]; + sha1_32t hash[5]; + sha1_32t wbuf[16]; +} sha1_ctx; + +/* Note that these prototypes are the same for both bit and */ +/* byte oriented implementations. However the length fields */ +/* are in bytes or bits as appropriate for the version used */ +/* and bit sequences are input as arrays of bytes in which */ +/* bit sequences run from the most to the least significant */ +/* end of each byte */ + +void sha1_compile(sha1_ctx ctx[1]); + +void sha1_begin(sha1_ctx ctx[1]); +void sha1_hash(const uint8_t data[], uint32_t len, sha1_ctx ctx[1]); +void sha1_end(uint8_t hval[], sha1_ctx ctx[1]); +void sha1(uint8_t hval[], const uint8_t data[], uint32_t len); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/utils/crypto/sha2.c b/src/utils/crypto/sha2.c new file mode 100644 index 000000000..cc528d941 --- /dev/null +++ b/src/utils/crypto/sha2.c @@ -0,0 +1,770 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 + + This is a byte oriented version of SHA2 that operates on arrays of bytes + stored in memory. This code implements sha256, sha384 and sha512 but the + latter two functions rely on efficient 64-bit integer operations that + may not be very efficient on 32-bit machines + + The sha256 functions use a type 'sha256_ctx' to hold details of the + current hash state and uses the following three calls: + + void sha256_begin(sha256_ctx ctx[1]) + void sha256_hash(const unsigned char data[], + unsigned long len, sha256_ctx ctx[1]) + void sha_end1(unsigned char hval[], sha256_ctx ctx[1]) + + The first subroutine initialises a hash computation by setting up the + context in the sha256_ctx context. The second subroutine hashes 8-bit + bytes from array data[] into the hash state withinh sha256_ctx context, + the number of bytes to be hashed being given by the the unsigned long + integer len. The third subroutine completes the hash calculation and + places the resulting digest value in the array of 8-bit bytes hval[]. + + The sha384 and sha512 functions are similar and use the interfaces: + + void sha384_begin(sha384_ctx ctx[1]); + void sha384_hash(const unsigned char data[], + unsigned long len, sha384_ctx ctx[1]); + void sha384_end(unsigned char hval[], sha384_ctx ctx[1]); + + void sha512_begin(sha512_ctx ctx[1]); + void sha512_hash(const unsigned char data[], + unsigned long len, sha512_ctx ctx[1]); + void sha512_end(unsigned char hval[], sha512_ctx ctx[1]); + + In addition there is a function sha2 that can be used to call all these + functions using a call with a hash length parameter as follows: + + int sha2_begin(unsigned long len, sha2_ctx ctx[1]); + void sha2_hash(const unsigned char data[], + unsigned long len, sha2_ctx ctx[1]); + void sha2_end(unsigned char hval[], sha2_ctx ctx[1]); + + My thanks to Erik Andersen for testing this code + on big-endian systems and for his assistance with corrections +*/ + +#include "../common/endian.h" +#define PLATFORM_BYTE_ORDER BYTE_ORDER +#define IS_LITTLE_ENDIAN LITTLE_ENDIAN + +#if 0 +#define UNROLL_SHA2 /* for SHA2 loop unroll */ +#endif + +#include /* for memcpy() etc. */ + +#include "sha2.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) +#pragma intrinsic(memcpy) +#endif + +#if 0 && defined(_MSC_VER) +#define rotl32 _lrotl +#define rotr32 _lrotr +#else +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) +#endif + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#if 0 + +#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#else /* Thanks to Rich Schroeppel and Colin Plumb for the following */ + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + +#endif + +/* round transforms for SHA256 and SHA512 compression functions */ + +#define vf(n,i) v[(n - i) & 7] + +#define hf(i) (p[i & 15] += \ + g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) + +#define v_cycle(i,j) \ + vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \ + + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \ + vf(3,i) += vf(7,i); \ + vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i)) + +#if defined(SHA_224) || defined(SHA_256) + +#define SHA256_MASK (SHA256_BLOCK_SIZE - 1) + +#if defined(SWAP_BYTES) +#define bsw_32(p,n) \ + { int _i = (n); while(_i--) ((uint_32t*)p)[_i] = bswap_32(((uint_32t*)p)[_i]); } +#else +#define bsw_32(p,n) +#endif + +#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) +#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) +#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) +#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) +#define k_0 k256 + +/* rotated SHA256 round definition. Rather than swapping variables as in */ +/* FIPS-180, different variables are 'rotated' on each round, returning */ +/* to their starting positions every eight rounds */ + +#define q(n) v##n + +#define one_cycle(a,b,c,d,e,f,g,h,k,w) \ + q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \ + q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c)) + +/* SHA256 mixing data */ + +const uint_32t k256[64] = +{ 0x428a2f98ul, 0x71374491ul, 0xb5c0fbcful, 0xe9b5dba5ul, + 0x3956c25bul, 0x59f111f1ul, 0x923f82a4ul, 0xab1c5ed5ul, + 0xd807aa98ul, 0x12835b01ul, 0x243185beul, 0x550c7dc3ul, + 0x72be5d74ul, 0x80deb1feul, 0x9bdc06a7ul, 0xc19bf174ul, + 0xe49b69c1ul, 0xefbe4786ul, 0x0fc19dc6ul, 0x240ca1ccul, + 0x2de92c6ful, 0x4a7484aaul, 0x5cb0a9dcul, 0x76f988daul, + 0x983e5152ul, 0xa831c66dul, 0xb00327c8ul, 0xbf597fc7ul, + 0xc6e00bf3ul, 0xd5a79147ul, 0x06ca6351ul, 0x14292967ul, + 0x27b70a85ul, 0x2e1b2138ul, 0x4d2c6dfcul, 0x53380d13ul, + 0x650a7354ul, 0x766a0abbul, 0x81c2c92eul, 0x92722c85ul, + 0xa2bfe8a1ul, 0xa81a664bul, 0xc24b8b70ul, 0xc76c51a3ul, + 0xd192e819ul, 0xd6990624ul, 0xf40e3585ul, 0x106aa070ul, + 0x19a4c116ul, 0x1e376c08ul, 0x2748774cul, 0x34b0bcb5ul, + 0x391c0cb3ul, 0x4ed8aa4aul, 0x5b9cca4ful, 0x682e6ff3ul, + 0x748f82eeul, 0x78a5636ful, 0x84c87814ul, 0x8cc70208ul, + 0x90befffaul, 0xa4506cebul, 0xbef9a3f7ul, 0xc67178f2ul, +}; + +/* Compile 64 bytes of hash data into SHA256 digest value */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is such that low address bytes */ +/* in the ORIGINAL byte stream will go into the high end of */ +/* words on BOTH big and little endian systems */ + +VOID_RETURN sha256_compile(sha256_ctx ctx[1]) +{ +#if !defined(UNROLL_SHA2) + + uint_32t j, *p = ctx->wbuf, v[8]; + + memcpy(v, ctx->hash, 8 * sizeof(uint_32t)); + + for(j = 0; j < 64; j += 16) + { + v_cycle( 0, j); v_cycle( 1, j); + v_cycle( 2, j); v_cycle( 3, j); + v_cycle( 4, j); v_cycle( 5, j); + v_cycle( 6, j); v_cycle( 7, j); + v_cycle( 8, j); v_cycle( 9, j); + v_cycle(10, j); v_cycle(11, j); + v_cycle(12, j); v_cycle(13, j); + v_cycle(14, j); v_cycle(15, j); + } + + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; + ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; + +#else + + uint_32t *p = ctx->wbuf,v0,v1,v2,v3,v4,v5,v6,v7; + + v0 = ctx->hash[0]; v1 = ctx->hash[1]; + v2 = ctx->hash[2]; v3 = ctx->hash[3]; + v4 = ctx->hash[4]; v5 = ctx->hash[5]; + v6 = ctx->hash[6]; v7 = ctx->hash[7]; + + one_cycle(0,1,2,3,4,5,6,7,k256[ 0],p[ 0]); + one_cycle(7,0,1,2,3,4,5,6,k256[ 1],p[ 1]); + one_cycle(6,7,0,1,2,3,4,5,k256[ 2],p[ 2]); + one_cycle(5,6,7,0,1,2,3,4,k256[ 3],p[ 3]); + one_cycle(4,5,6,7,0,1,2,3,k256[ 4],p[ 4]); + one_cycle(3,4,5,6,7,0,1,2,k256[ 5],p[ 5]); + one_cycle(2,3,4,5,6,7,0,1,k256[ 6],p[ 6]); + one_cycle(1,2,3,4,5,6,7,0,k256[ 7],p[ 7]); + one_cycle(0,1,2,3,4,5,6,7,k256[ 8],p[ 8]); + one_cycle(7,0,1,2,3,4,5,6,k256[ 9],p[ 9]); + one_cycle(6,7,0,1,2,3,4,5,k256[10],p[10]); + one_cycle(5,6,7,0,1,2,3,4,k256[11],p[11]); + one_cycle(4,5,6,7,0,1,2,3,k256[12],p[12]); + one_cycle(3,4,5,6,7,0,1,2,k256[13],p[13]); + one_cycle(2,3,4,5,6,7,0,1,k256[14],p[14]); + one_cycle(1,2,3,4,5,6,7,0,k256[15],p[15]); + + one_cycle(0,1,2,3,4,5,6,7,k256[16],hf( 0)); + one_cycle(7,0,1,2,3,4,5,6,k256[17],hf( 1)); + one_cycle(6,7,0,1,2,3,4,5,k256[18],hf( 2)); + one_cycle(5,6,7,0,1,2,3,4,k256[19],hf( 3)); + one_cycle(4,5,6,7,0,1,2,3,k256[20],hf( 4)); + one_cycle(3,4,5,6,7,0,1,2,k256[21],hf( 5)); + one_cycle(2,3,4,5,6,7,0,1,k256[22],hf( 6)); + one_cycle(1,2,3,4,5,6,7,0,k256[23],hf( 7)); + one_cycle(0,1,2,3,4,5,6,7,k256[24],hf( 8)); + one_cycle(7,0,1,2,3,4,5,6,k256[25],hf( 9)); + one_cycle(6,7,0,1,2,3,4,5,k256[26],hf(10)); + one_cycle(5,6,7,0,1,2,3,4,k256[27],hf(11)); + one_cycle(4,5,6,7,0,1,2,3,k256[28],hf(12)); + one_cycle(3,4,5,6,7,0,1,2,k256[29],hf(13)); + one_cycle(2,3,4,5,6,7,0,1,k256[30],hf(14)); + one_cycle(1,2,3,4,5,6,7,0,k256[31],hf(15)); + + one_cycle(0,1,2,3,4,5,6,7,k256[32],hf( 0)); + one_cycle(7,0,1,2,3,4,5,6,k256[33],hf( 1)); + one_cycle(6,7,0,1,2,3,4,5,k256[34],hf( 2)); + one_cycle(5,6,7,0,1,2,3,4,k256[35],hf( 3)); + one_cycle(4,5,6,7,0,1,2,3,k256[36],hf( 4)); + one_cycle(3,4,5,6,7,0,1,2,k256[37],hf( 5)); + one_cycle(2,3,4,5,6,7,0,1,k256[38],hf( 6)); + one_cycle(1,2,3,4,5,6,7,0,k256[39],hf( 7)); + one_cycle(0,1,2,3,4,5,6,7,k256[40],hf( 8)); + one_cycle(7,0,1,2,3,4,5,6,k256[41],hf( 9)); + one_cycle(6,7,0,1,2,3,4,5,k256[42],hf(10)); + one_cycle(5,6,7,0,1,2,3,4,k256[43],hf(11)); + one_cycle(4,5,6,7,0,1,2,3,k256[44],hf(12)); + one_cycle(3,4,5,6,7,0,1,2,k256[45],hf(13)); + one_cycle(2,3,4,5,6,7,0,1,k256[46],hf(14)); + one_cycle(1,2,3,4,5,6,7,0,k256[47],hf(15)); + + one_cycle(0,1,2,3,4,5,6,7,k256[48],hf( 0)); + one_cycle(7,0,1,2,3,4,5,6,k256[49],hf( 1)); + one_cycle(6,7,0,1,2,3,4,5,k256[50],hf( 2)); + one_cycle(5,6,7,0,1,2,3,4,k256[51],hf( 3)); + one_cycle(4,5,6,7,0,1,2,3,k256[52],hf( 4)); + one_cycle(3,4,5,6,7,0,1,2,k256[53],hf( 5)); + one_cycle(2,3,4,5,6,7,0,1,k256[54],hf( 6)); + one_cycle(1,2,3,4,5,6,7,0,k256[55],hf( 7)); + one_cycle(0,1,2,3,4,5,6,7,k256[56],hf( 8)); + one_cycle(7,0,1,2,3,4,5,6,k256[57],hf( 9)); + one_cycle(6,7,0,1,2,3,4,5,k256[58],hf(10)); + one_cycle(5,6,7,0,1,2,3,4,k256[59],hf(11)); + one_cycle(4,5,6,7,0,1,2,3,k256[60],hf(12)); + one_cycle(3,4,5,6,7,0,1,2,k256[61],hf(13)); + one_cycle(2,3,4,5,6,7,0,1,k256[62],hf(14)); + one_cycle(1,2,3,4,5,6,7,0,k256[63],hf(15)); + + ctx->hash[0] += v0; ctx->hash[1] += v1; + ctx->hash[2] += v2; ctx->hash[3] += v3; + ctx->hash[4] += v4; ctx->hash[5] += v5; + ctx->hash[6] += v6; ctx->hash[7] += v7; +#endif +} + +/* SHA256 hash data in an array of bytes into hash buffer */ +/* and call the hash_compile function as required. */ + +VOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]) +{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA256_MASK), + space = SHA256_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks while possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0; + bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2) + sha256_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA256 Final padding and digest calculation */ + +static void sha_end1(unsigned char hval[], sha256_ctx ctx[1], const unsigned int hlen) +{ uint_32t i = (uint_32t)(ctx->count[0] & SHA256_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_32(ctx->wbuf, (i + 3) >> 2) + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3); + ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3); + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space pad and empty the buffer */ + if(i > SHA256_BLOCK_SIZE - 9) + { + if(i < 60) ctx->wbuf[15] = 0; + sha256_compile(ctx); + i = 0; + } + else /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + + while(i < 14) /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + + /* the following 32-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 32-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); + ctx->wbuf[15] = ctx->count[0] << 3; + sha256_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* mislaigned for 32-bit words */ + for(i = 0; i < hlen; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); +} + +#endif + +#if defined(SHA_224) + +const uint_32t i224[8] = +{ + 0xc1059ed8ul, 0x367cd507ul, 0x3070dd17ul, 0xf70e5939ul, + 0xffc00b31ul, 0x68581511ul, 0x64f98fa7ul, 0xbefa4fa4ul +}; + +VOID_RETURN sha224_begin(sha224_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i224, 8 * sizeof(uint_32t)); +} + +VOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]) +{ + sha_end1(hval, ctx, SHA224_DIGEST_SIZE); +} + +VOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha224_ctx cx[1]; + + sha224_begin(cx); + sha224_hash(data, len, cx); + sha_end1(hval, cx, SHA224_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_256) + +const uint_32t i256[8] = +{ + 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, + 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul +}; + +VOID_RETURN sha256_begin(sha256_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i256, 8 * sizeof(uint_32t)); +} + +VOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]) +{ + sha_end1(hval, ctx, SHA256_DIGEST_SIZE); +} + +VOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha256_ctx cx[1]; + + sha256_begin(cx); + sha256_hash(data, len, cx); + sha_end1(hval, cx, SHA256_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_384) || defined(SHA_512) + +#define SHA512_MASK (SHA512_BLOCK_SIZE - 1) + +#define rotr64(x,n) (((x) >> n) | ((x) << (64 - n))) + +#if !defined(bswap_64) +#define bswap_64(x) (((uint_64t)(bswap_32((uint_32t)(x)))) << 32 | bswap_32((uint_32t)((x) >> 32))) +#endif + +#if defined(SWAP_BYTES) +#define bsw_64(p,n) \ + { int _i = (n); while(_i--) ((uint_64t*)p)[_i] = bswap_64(((uint_64t*)p)[_i]); } +#else +#define bsw_64(p,n) +#endif + +/* SHA512 mixing function definitions */ + +#ifdef s_0 +# undef s_0 +# undef s_1 +# undef g_0 +# undef g_1 +# undef k_0 +#endif + +#define s_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39)) +#define s_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41)) +#define g_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7)) +#define g_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6)) +#define k_0 k512 + +/* SHA384/SHA512 mixing data */ + +const uint_64t k512[80] = +{ + li_64(428a2f98d728ae22), li_64(7137449123ef65cd), + li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc), + li_64(3956c25bf348b538), li_64(59f111f1b605d019), + li_64(923f82a4af194f9b), li_64(ab1c5ed5da6d8118), + li_64(d807aa98a3030242), li_64(12835b0145706fbe), + li_64(243185be4ee4b28c), li_64(550c7dc3d5ffb4e2), + li_64(72be5d74f27b896f), li_64(80deb1fe3b1696b1), + li_64(9bdc06a725c71235), li_64(c19bf174cf692694), + li_64(e49b69c19ef14ad2), li_64(efbe4786384f25e3), + li_64(0fc19dc68b8cd5b5), li_64(240ca1cc77ac9c65), + li_64(2de92c6f592b0275), li_64(4a7484aa6ea6e483), + li_64(5cb0a9dcbd41fbd4), li_64(76f988da831153b5), + li_64(983e5152ee66dfab), li_64(a831c66d2db43210), + li_64(b00327c898fb213f), li_64(bf597fc7beef0ee4), + li_64(c6e00bf33da88fc2), li_64(d5a79147930aa725), + li_64(06ca6351e003826f), li_64(142929670a0e6e70), + li_64(27b70a8546d22ffc), li_64(2e1b21385c26c926), + li_64(4d2c6dfc5ac42aed), li_64(53380d139d95b3df), + li_64(650a73548baf63de), li_64(766a0abb3c77b2a8), + li_64(81c2c92e47edaee6), li_64(92722c851482353b), + li_64(a2bfe8a14cf10364), li_64(a81a664bbc423001), + li_64(c24b8b70d0f89791), li_64(c76c51a30654be30), + li_64(d192e819d6ef5218), li_64(d69906245565a910), + li_64(f40e35855771202a), li_64(106aa07032bbd1b8), + li_64(19a4c116b8d2d0c8), li_64(1e376c085141ab53), + li_64(2748774cdf8eeb99), li_64(34b0bcb5e19b48a8), + li_64(391c0cb3c5c95a63), li_64(4ed8aa4ae3418acb), + li_64(5b9cca4f7763e373), li_64(682e6ff3d6b2b8a3), + li_64(748f82ee5defb2fc), li_64(78a5636f43172f60), + li_64(84c87814a1f0ab72), li_64(8cc702081a6439ec), + li_64(90befffa23631e28), li_64(a4506cebde82bde9), + li_64(bef9a3f7b2c67915), li_64(c67178f2e372532b), + li_64(ca273eceea26619c), li_64(d186b8c721c0c207), + li_64(eada7dd6cde0eb1e), li_64(f57d4f7fee6ed178), + li_64(06f067aa72176fba), li_64(0a637dc5a2c898a6), + li_64(113f9804bef90dae), li_64(1b710b35131c471b), + li_64(28db77f523047d84), li_64(32caab7b40c72493), + li_64(3c9ebe0a15c9bebc), li_64(431d67c49c100d4c), + li_64(4cc5d4becb3e42b6), li_64(597f299cfc657e2a), + li_64(5fcb6fab3ad6faec), li_64(6c44198c4a475817) +}; + +/* Compile 128 bytes of hash data into SHA384/512 digest */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is such that low address bytes */ +/* in the ORIGINAL byte stream will go into the high end of */ +/* words on BOTH big and little endian systems */ + +VOID_RETURN sha512_compile(sha512_ctx ctx[1]) +{ uint_64t v[8], *p = ctx->wbuf; + uint_32t j; + + memcpy(v, ctx->hash, 8 * sizeof(uint_64t)); + + for(j = 0; j < 80; j += 16) + { + v_cycle( 0, j); v_cycle( 1, j); + v_cycle( 2, j); v_cycle( 3, j); + v_cycle( 4, j); v_cycle( 5, j); + v_cycle( 6, j); v_cycle( 7, j); + v_cycle( 8, j); v_cycle( 9, j); + v_cycle(10, j); v_cycle(11, j); + v_cycle(12, j); v_cycle(13, j); + v_cycle(14, j); v_cycle(15, j); + } + + ctx->hash[0] += v[0]; ctx->hash[1] += v[1]; + ctx->hash[2] += v[2]; ctx->hash[3] += v[3]; + ctx->hash[4] += v[4]; ctx->hash[5] += v[5]; + ctx->hash[6] += v[6]; ctx->hash[7] += v[7]; +} + +/* Compile 128 bytes of hash data into SHA256 digest value */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is in such an order that low */ +/* address bytes in the ORIGINAL byte stream placed in this */ +/* buffer will now go to the high end of words on BOTH big */ +/* and little endian systems */ + +VOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]) +{ uint_32t pos = (uint_32t)(ctx->count[0] & SHA512_MASK), + space = SHA512_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks while possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0; + bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3); + sha512_compile(ctx); + } + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA384/512 Final padding and digest calculation */ + +static void sha_end2(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen) +{ uint_32t i = (uint_32t)(ctx->count[0] & SHA512_MASK); + + /* put bytes in the buffer in an order in which references to */ + /* 32-bit words will put bytes with lower addresses into the */ + /* top of 32 bit words on BOTH big and little endian machines */ + bsw_64(ctx->wbuf, (i + 7) >> 3); + + /* we now need to mask valid bytes and add the padding which is */ + /* a single 1 bit and as many zero bits as necessary. Note that */ + /* we can always add the first padding byte here because the */ + /* buffer always has at least one empty slot */ + ctx->wbuf[i >> 3] &= li_64(ffffffffffffff00) << 8 * (~i & 7); + ctx->wbuf[i >> 3] |= li_64(0000000000000080) << 8 * (~i & 7); + + /* we need 17 or more empty byte positions, one for the padding */ + /* byte (above) and sixteen for the length count. If there is */ + /* not enough space pad and empty the buffer */ + if(i > SHA512_BLOCK_SIZE - 17) + { + if(i < 120) ctx->wbuf[15] = 0; + sha512_compile(ctx); + i = 0; + } + else + i = (i >> 3) + 1; + + while(i < 14) + ctx->wbuf[i++] = 0; + + /* the following 64-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 64-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61); + ctx->wbuf[15] = ctx->count[0] << 3; + sha512_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* misaligned for 32-bit words */ + for(i = 0; i < hlen; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 3] >> (8 * (~i & 7))); +} + +#endif + +#if defined(SHA_384) + +/* SHA384 initialisation data */ + +const uint_64t i384[80] = +{ + li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507), + li_64(9159015a3070dd17), li_64(152fecd8f70e5939), + li_64(67332667ffc00b31), li_64(8eb44a8768581511), + li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4) +}; + +VOID_RETURN sha384_begin(sha384_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i384, 8 * sizeof(uint_64t)); +} + +VOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]) +{ + sha_end2(hval, ctx, SHA384_DIGEST_SIZE); +} + +VOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha384_ctx cx[1]; + + sha384_begin(cx); + sha384_hash(data, len, cx); + sha_end2(hval, cx, SHA384_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_512) + +/* SHA512 initialisation data */ + +const uint_64t i512[80] = +{ + li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b), + li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1), + li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f), + li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179) +}; + +VOID_RETURN sha512_begin(sha512_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + memcpy(ctx->hash, i512, 8 * sizeof(uint_64t)); +} + +VOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]) +{ + sha_end2(hval, ctx, SHA512_DIGEST_SIZE); +} + +VOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len) +{ sha512_ctx cx[1]; + + sha512_begin(cx); + sha512_hash(data, len, cx); + sha_end2(hval, cx, SHA512_DIGEST_SIZE); +} + +#endif + +#if defined(SHA_2) + +#define CTX_224(x) ((x)->uu->ctx256) +#define CTX_256(x) ((x)->uu->ctx256) +#define CTX_384(x) ((x)->uu->ctx512) +#define CTX_512(x) ((x)->uu->ctx512) + +/* SHA2 initialisation */ + +INT_RETURN sha2_begin(unsigned long len, sha2_ctx ctx[1]) +{ + switch(len) + { +#if defined(SHA_224) + case 224: + case 28: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; + memcpy(CTX_256(ctx)->hash, i224, 32); + ctx->sha2_len = 28; return EXIT_SUCCESS; +#endif +#if defined(SHA_256) + case 256: + case 32: CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0; + memcpy(CTX_256(ctx)->hash, i256, 32); + ctx->sha2_len = 32; return EXIT_SUCCESS; +#endif +#if defined(SHA_384) + case 384: + case 48: CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0; + memcpy(CTX_384(ctx)->hash, i384, 64); + ctx->sha2_len = 48; return EXIT_SUCCESS; +#endif +#if defined(SHA_512) + case 512: + case 64: CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0; + memcpy(CTX_512(ctx)->hash, i512, 64); + ctx->sha2_len = 64; return EXIT_SUCCESS; +#endif + default: return EXIT_FAILURE; + } +} + +VOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]) +{ + switch(ctx->sha2_len) + { +#if defined(SHA_224) + case 28: sha224_hash(data, len, CTX_224(ctx)); return; +#endif +#if defined(SHA_256) + case 32: sha256_hash(data, len, CTX_256(ctx)); return; +#endif +#if defined(SHA_384) + case 48: sha384_hash(data, len, CTX_384(ctx)); return; +#endif +#if defined(SHA_512) + case 64: sha512_hash(data, len, CTX_512(ctx)); return; +#endif + } +} + +VOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]) +{ + switch(ctx->sha2_len) + { +#if defined(SHA_224) + case 28: sha_end1(hval, CTX_224(ctx), SHA224_DIGEST_SIZE); return; +#endif +#if defined(SHA_256) + case 32: sha_end1(hval, CTX_256(ctx), SHA256_DIGEST_SIZE); return; +#endif +#if defined(SHA_384) + case 48: sha_end2(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return; +#endif +#if defined(SHA_512) + case 64: sha_end2(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return; +#endif + } +} + +INT_RETURN sha2(unsigned char hval[], unsigned long size, + const unsigned char data[], unsigned long len) +{ sha2_ctx cx[1]; + + if(sha2_begin(size, cx) == EXIT_SUCCESS) + { + sha2_hash(data, len, cx); sha2_end(hval, cx); return EXIT_SUCCESS; + } + else + return EXIT_FAILURE; +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/src/utils/crypto/sha2.h b/src/utils/crypto/sha2.h new file mode 100644 index 000000000..3ebf66710 --- /dev/null +++ b/src/utils/crypto/sha2.h @@ -0,0 +1,155 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 01/08/2005 +*/ + +#ifndef _SHA2_H +#define _SHA2_H + +#include "../common/tcdefs.h" +#include "../common/endian.h" + +#define SHA_64BIT + +/* define the hash functions that you need */ +#define SHA_2 /* for dynamic hash length */ +#define SHA_224 +#define SHA_256 +#ifdef SHA_64BIT +# define SHA_384 +# define SHA_512 +# define NEED_UINT_64T +#endif + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#endif + +#define li_64(h) 0x##h##ull + +#define VOID_RETURN void +#define INT_RETURN int + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Note that the following function prototypes are the same */ +/* for both the bit and byte oriented implementations. But */ +/* the length fields are in bytes or bits as is appropriate */ +/* for the version used. Bit sequences are arrays of bytes */ +/* in which bit sequence indexes increase from the most to */ +/* the least significant end of each byte */ + +#define SHA224_DIGEST_SIZE 28 +#define SHA224_BLOCK_SIZE 64 +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +/* type to hold the SHA256 (and SHA224) context */ + +typedef struct +{ uint_32t count[2]; + uint_32t hash[8]; + uint_32t wbuf[16]; +} sha256_ctx; + +typedef sha256_ctx sha224_ctx; + +VOID_RETURN sha256_compile(sha256_ctx ctx[1]); + +VOID_RETURN sha224_begin(sha224_ctx ctx[1]); +#define sha224_hash sha256_hash +VOID_RETURN sha224_end(uint8_t hval[], sha224_ctx ctx[1]); +VOID_RETURN sha224(uint8_t hval[], const uint8_t data[], unsigned long len); + +VOID_RETURN sha256_begin(sha256_ctx ctx[1]); +VOID_RETURN sha256_hash(const uint8_t data[], unsigned long len, sha256_ctx ctx[1]); +VOID_RETURN sha256_end(uint8_t hval[], sha256_ctx ctx[1]); +VOID_RETURN sha256(uint8_t hval[], const uint8_t data[], unsigned long len); + +#ifndef SHA_64BIT + +typedef struct +{ union + { sha256_ctx ctx256[1]; + } uu[1]; + uint_32t sha2_len; +} sha2_ctx; + +#define SHA2_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE + +#else + +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 +#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + +/* type to hold the SHA384 (and SHA512) context */ + +typedef struct +{ uint_64t count[2]; + uint_64t hash[8]; + uint_64t wbuf[16]; +} sha512_ctx; + +typedef sha512_ctx sha384_ctx; + +typedef struct +{ union + { sha256_ctx ctx256[1]; + sha512_ctx ctx512[1]; + } uu[1]; + uint_32t sha2_len; +} sha2_ctx; + +VOID_RETURN sha512_compile(sha512_ctx ctx[1]); + +VOID_RETURN sha384_begin(sha384_ctx ctx[1]); +#define sha384_hash sha512_hash +VOID_RETURN sha384_end(uint8_t hval[], sha384_ctx ctx[1]); +VOID_RETURN sha384(uint8_t hval[], const uint8_t data[], unsigned long len); + +VOID_RETURN sha512_begin(sha512_ctx ctx[1]); +VOID_RETURN sha512_hash(const uint8_t data[], unsigned long len, sha512_ctx ctx[1]); +VOID_RETURN sha512_end(uint8_t hval[], sha512_ctx ctx[1]); +VOID_RETURN sha512(uint8_t hval[], const uint8_t data[], unsigned long len); + +INT_RETURN sha2_begin(unsigned long size, sha2_ctx ctx[1]); +VOID_RETURN sha2_hash(const uint8_t data[], unsigned long len, sha2_ctx ctx[1]); +VOID_RETURN sha2_end(uint8_t hval[], sha2_ctx ctx[1]); +INT_RETURN sha2(uint8_t hval[], unsigned long size, const uint8_t data[], unsigned long len); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/src/utils/crypto/sk.h b/src/utils/crypto/sk.h new file mode 100644 index 000000000..ea55bc6ff --- /dev/null +++ b/src/utils/crypto/sk.h @@ -0,0 +1,206 @@ +/* Deprecated/legacy */ + +/* crypto/des/sk.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +static const DES_LONG des_skb[8][64]={ +{ +/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ +0x00000000L,0x00000010L,0x20000000L,0x20000010L, +0x00010000L,0x00010010L,0x20010000L,0x20010010L, +0x00000800L,0x00000810L,0x20000800L,0x20000810L, +0x00010800L,0x00010810L,0x20010800L,0x20010810L, +0x00000020L,0x00000030L,0x20000020L,0x20000030L, +0x00010020L,0x00010030L,0x20010020L,0x20010030L, +0x00000820L,0x00000830L,0x20000820L,0x20000830L, +0x00010820L,0x00010830L,0x20010820L,0x20010830L, +0x00080000L,0x00080010L,0x20080000L,0x20080010L, +0x00090000L,0x00090010L,0x20090000L,0x20090010L, +0x00080800L,0x00080810L,0x20080800L,0x20080810L, +0x00090800L,0x00090810L,0x20090800L,0x20090810L, +0x00080020L,0x00080030L,0x20080020L,0x20080030L, +0x00090020L,0x00090030L,0x20090020L,0x20090030L, +0x00080820L,0x00080830L,0x20080820L,0x20080830L, +0x00090820L,0x00090830L,0x20090820L,0x20090830L, +},{ +/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ +0x00000000L,0x02000000L,0x00002000L,0x02002000L, +0x00200000L,0x02200000L,0x00202000L,0x02202000L, +0x00000004L,0x02000004L,0x00002004L,0x02002004L, +0x00200004L,0x02200004L,0x00202004L,0x02202004L, +0x00000400L,0x02000400L,0x00002400L,0x02002400L, +0x00200400L,0x02200400L,0x00202400L,0x02202400L, +0x00000404L,0x02000404L,0x00002404L,0x02002404L, +0x00200404L,0x02200404L,0x00202404L,0x02202404L, +0x10000000L,0x12000000L,0x10002000L,0x12002000L, +0x10200000L,0x12200000L,0x10202000L,0x12202000L, +0x10000004L,0x12000004L,0x10002004L,0x12002004L, +0x10200004L,0x12200004L,0x10202004L,0x12202004L, +0x10000400L,0x12000400L,0x10002400L,0x12002400L, +0x10200400L,0x12200400L,0x10202400L,0x12202400L, +0x10000404L,0x12000404L,0x10002404L,0x12002404L, +0x10200404L,0x12200404L,0x10202404L,0x12202404L, +},{ +/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ +0x00000000L,0x00000001L,0x00040000L,0x00040001L, +0x01000000L,0x01000001L,0x01040000L,0x01040001L, +0x00000002L,0x00000003L,0x00040002L,0x00040003L, +0x01000002L,0x01000003L,0x01040002L,0x01040003L, +0x00000200L,0x00000201L,0x00040200L,0x00040201L, +0x01000200L,0x01000201L,0x01040200L,0x01040201L, +0x00000202L,0x00000203L,0x00040202L,0x00040203L, +0x01000202L,0x01000203L,0x01040202L,0x01040203L, +0x08000000L,0x08000001L,0x08040000L,0x08040001L, +0x09000000L,0x09000001L,0x09040000L,0x09040001L, +0x08000002L,0x08000003L,0x08040002L,0x08040003L, +0x09000002L,0x09000003L,0x09040002L,0x09040003L, +0x08000200L,0x08000201L,0x08040200L,0x08040201L, +0x09000200L,0x09000201L,0x09040200L,0x09040201L, +0x08000202L,0x08000203L,0x08040202L,0x08040203L, +0x09000202L,0x09000203L,0x09040202L,0x09040203L, +},{ +/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ +0x00000000L,0x00100000L,0x00000100L,0x00100100L, +0x00000008L,0x00100008L,0x00000108L,0x00100108L, +0x00001000L,0x00101000L,0x00001100L,0x00101100L, +0x00001008L,0x00101008L,0x00001108L,0x00101108L, +0x04000000L,0x04100000L,0x04000100L,0x04100100L, +0x04000008L,0x04100008L,0x04000108L,0x04100108L, +0x04001000L,0x04101000L,0x04001100L,0x04101100L, +0x04001008L,0x04101008L,0x04001108L,0x04101108L, +0x00020000L,0x00120000L,0x00020100L,0x00120100L, +0x00020008L,0x00120008L,0x00020108L,0x00120108L, +0x00021000L,0x00121000L,0x00021100L,0x00121100L, +0x00021008L,0x00121008L,0x00021108L,0x00121108L, +0x04020000L,0x04120000L,0x04020100L,0x04120100L, +0x04020008L,0x04120008L,0x04020108L,0x04120108L, +0x04021000L,0x04121000L,0x04021100L,0x04121100L, +0x04021008L,0x04121008L,0x04021108L,0x04121108L, +},{ +/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ +0x00000000L,0x10000000L,0x00010000L,0x10010000L, +0x00000004L,0x10000004L,0x00010004L,0x10010004L, +0x20000000L,0x30000000L,0x20010000L,0x30010000L, +0x20000004L,0x30000004L,0x20010004L,0x30010004L, +0x00100000L,0x10100000L,0x00110000L,0x10110000L, +0x00100004L,0x10100004L,0x00110004L,0x10110004L, +0x20100000L,0x30100000L,0x20110000L,0x30110000L, +0x20100004L,0x30100004L,0x20110004L,0x30110004L, +0x00001000L,0x10001000L,0x00011000L,0x10011000L, +0x00001004L,0x10001004L,0x00011004L,0x10011004L, +0x20001000L,0x30001000L,0x20011000L,0x30011000L, +0x20001004L,0x30001004L,0x20011004L,0x30011004L, +0x00101000L,0x10101000L,0x00111000L,0x10111000L, +0x00101004L,0x10101004L,0x00111004L,0x10111004L, +0x20101000L,0x30101000L,0x20111000L,0x30111000L, +0x20101004L,0x30101004L,0x20111004L,0x30111004L, +},{ +/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ +0x00000000L,0x08000000L,0x00000008L,0x08000008L, +0x00000400L,0x08000400L,0x00000408L,0x08000408L, +0x00020000L,0x08020000L,0x00020008L,0x08020008L, +0x00020400L,0x08020400L,0x00020408L,0x08020408L, +0x00000001L,0x08000001L,0x00000009L,0x08000009L, +0x00000401L,0x08000401L,0x00000409L,0x08000409L, +0x00020001L,0x08020001L,0x00020009L,0x08020009L, +0x00020401L,0x08020401L,0x00020409L,0x08020409L, +0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, +0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, +0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, +0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, +0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, +0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, +0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, +0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, +},{ +/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ +0x00000000L,0x00000100L,0x00080000L,0x00080100L, +0x01000000L,0x01000100L,0x01080000L,0x01080100L, +0x00000010L,0x00000110L,0x00080010L,0x00080110L, +0x01000010L,0x01000110L,0x01080010L,0x01080110L, +0x00200000L,0x00200100L,0x00280000L,0x00280100L, +0x01200000L,0x01200100L,0x01280000L,0x01280100L, +0x00200010L,0x00200110L,0x00280010L,0x00280110L, +0x01200010L,0x01200110L,0x01280010L,0x01280110L, +0x00000200L,0x00000300L,0x00080200L,0x00080300L, +0x01000200L,0x01000300L,0x01080200L,0x01080300L, +0x00000210L,0x00000310L,0x00080210L,0x00080310L, +0x01000210L,0x01000310L,0x01080210L,0x01080310L, +0x00200200L,0x00200300L,0x00280200L,0x00280300L, +0x01200200L,0x01200300L,0x01280200L,0x01280300L, +0x00200210L,0x00200310L,0x00280210L,0x00280310L, +0x01200210L,0x01200310L,0x01280210L,0x01280310L, +},{ +/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ +0x00000000L,0x04000000L,0x00040000L,0x04040000L, +0x00000002L,0x04000002L,0x00040002L,0x04040002L, +0x00002000L,0x04002000L,0x00042000L,0x04042000L, +0x00002002L,0x04002002L,0x00042002L,0x04042002L, +0x00000020L,0x04000020L,0x00040020L,0x04040020L, +0x00000022L,0x04000022L,0x00040022L,0x04040022L, +0x00002020L,0x04002020L,0x00042020L,0x04042020L, +0x00002022L,0x04002022L,0x00042022L,0x04042022L, +0x00000800L,0x04000800L,0x00040800L,0x04040800L, +0x00000802L,0x04000802L,0x00040802L,0x04040802L, +0x00002800L,0x04002800L,0x00042800L,0x04042800L, +0x00002802L,0x04002802L,0x00042802L,0x04042802L, +0x00000820L,0x04000820L,0x00040820L,0x04040820L, +0x00000822L,0x04000822L,0x00040822L,0x04040822L, +0x00002820L,0x04002820L,0x00042820L,0x04042820L, +0x00002822L,0x04002822L,0x00042822L,0x04042822L, +}}; diff --git a/src/utils/crypto/spr.h b/src/utils/crypto/spr.h new file mode 100644 index 000000000..ef72408c4 --- /dev/null +++ b/src/utils/crypto/spr.h @@ -0,0 +1,206 @@ +/* Deprecated/legacy */ + +/* crypto/des/spr.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +const DES_LONG des_SPtrans[8][64]={ +{ +/* nibble 0 */ +0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L, +0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L, +0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L, +0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L, +0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L, +0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L, +0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L, +0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L, +0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L, +0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L, +0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L, +0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L, +0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L, +0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L, +0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L, +0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L, +},{ +/* nibble 1 */ +0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L, +0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L, +0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L, +0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L, +0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L, +0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L, +0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L, +0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L, +0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L, +0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L, +0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L, +0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L, +0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L, +0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L, +0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L, +0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L, +},{ +/* nibble 2 */ +0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L, +0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L, +0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L, +0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L, +0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L, +0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L, +0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L, +0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L, +0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L, +0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L, +0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L, +0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L, +0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L, +0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L, +0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L, +0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L, +},{ +/* nibble 3 */ +0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L, +0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L, +0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L, +0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L, +0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L, +0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L, +0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L, +0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L, +0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L, +0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L, +0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L, +0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L, +0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L, +0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L, +0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L, +0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L, +},{ +/* nibble 4 */ +0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L, +0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L, +0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L, +0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L, +0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L, +0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L, +0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L, +0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L, +0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L, +0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L, +0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L, +0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L, +0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L, +0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L, +0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L, +0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L, +},{ +/* nibble 5 */ +0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L, +0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L, +0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L, +0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L, +0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L, +0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L, +0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L, +0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L, +0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L, +0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L, +0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L, +0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L, +0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L, +0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L, +0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L, +0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L, +},{ +/* nibble 6 */ +0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L, +0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L, +0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L, +0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L, +0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L, +0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L, +0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L, +0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L, +0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L, +0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L, +0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L, +0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L, +0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L, +0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L, +0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L, +0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L, +},{ +/* nibble 7 */ +0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L, +0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L, +0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L, +0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L, +0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L, +0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L, +0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L, +0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L, +0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L, +0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L, +0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L, +0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L, +0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L, +0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L, +0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L, +0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L, +}}; diff --git a/src/utils/crypto/twofish.c b/src/utils/crypto/twofish.c new file mode 100644 index 000000000..981acdba8 --- /dev/null +++ b/src/utils/crypto/twofish.c @@ -0,0 +1,548 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1999, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software is allowed (with or without + changes) provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + + My thanks to Doug Whiting and Niels Ferguson for comments that led + to improvements in this implementation. + + Issue Date: 14th January 1999 +*/ + +/* Adapted for TrueCrypt by the TrueCrypt Foundation */ + + +#ifdef TC_WINDOWS_BOOT +#pragma optimize ("tl", on) +#endif + +#include "twofish.h" +#include "../common/endian.h" + +#define Q_TABLES +#define M_TABLE + +#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_TWOFISH) +# define MK_TABLE +# define ONE_STEP +#endif + +/* finite field arithmetic for GF(2**8) with the modular */ +/* polynomial x^8 + x^6 + x^5 + x^3 + 1 (0x169) */ + +#define G_M 0x0169 + +static u1byte tab_5b[4] = { 0, G_M >> 2, G_M >> 1, (G_M >> 1) ^ (G_M >> 2) }; +static u1byte tab_ef[4] = { 0, (G_M >> 1) ^ (G_M >> 2), G_M >> 1, G_M >> 2 }; + +#define ffm_01(x) (x) +#define ffm_5b(x) ((x) ^ ((x) >> 2) ^ tab_5b[(x) & 3]) +#define ffm_ef(x) ((x) ^ ((x) >> 1) ^ ((x) >> 2) ^ tab_ef[(x) & 3]) + +static u1byte ror4[16] = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; +static u1byte ashx[16] = { 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 }; + +static u1byte qt0[2][16] = +{ { 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 }, + { 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 } +}; + +static u1byte qt1[2][16] = +{ { 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 }, + { 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 } +}; + +static u1byte qt2[2][16] = +{ { 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 }, + { 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 } +}; + +static u1byte qt3[2][16] = +{ { 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 }, + { 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 } +}; + +static u1byte qp(const u4byte n, const u1byte x) +{ u1byte a0, a1, a2, a3, a4, b0, b1, b2, b3, b4; + + a0 = x >> 4; b0 = x & 15; + a1 = a0 ^ b0; b1 = ror4[b0] ^ ashx[a0]; + a2 = qt0[n][a1]; b2 = qt1[n][b1]; + a3 = a2 ^ b2; b3 = ror4[b2] ^ ashx[a2]; + a4 = qt2[n][a3]; b4 = qt3[n][b3]; + return (b4 << 4) | a4; +}; + +#ifdef Q_TABLES + +static u4byte qt_gen = 0; +static u1byte q_tab[2][256]; + +#define q(n,x) q_tab[n][x] + +static void gen_qtab(void) +{ u4byte i; + + for(i = 0; i < 256; ++i) + { + q(0,i) = qp(0, (u1byte)i); + q(1,i) = qp(1, (u1byte)i); + } +}; + +#else + +#define q(n,x) qp(n, x) + +#endif + +#ifdef M_TABLE + +static u4byte mt_gen = 0; +static u4byte m_tab[4][256]; + +static void gen_mtab(void) +{ u4byte i, f01, f5b, fef; + + for(i = 0; i < 256; ++i) + { + f01 = q(1,i); f5b = ffm_5b(f01); fef = ffm_ef(f01); + m_tab[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24); + m_tab[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24); + + f01 = q(0,i); f5b = ffm_5b(f01); fef = ffm_ef(f01); + m_tab[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24); + m_tab[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24); + } +}; + +#define mds(n,x) m_tab[n][x] + +#else + +#define fm_00 ffm_01 +#define fm_10 ffm_5b +#define fm_20 ffm_ef +#define fm_30 ffm_ef +#define q_0(x) q(1,x) + +#define fm_01 ffm_ef +#define fm_11 ffm_ef +#define fm_21 ffm_5b +#define fm_31 ffm_01 +#define q_1(x) q(0,x) + +#define fm_02 ffm_5b +#define fm_12 ffm_ef +#define fm_22 ffm_01 +#define fm_32 ffm_ef +#define q_2(x) q(1,x) + +#define fm_03 ffm_5b +#define fm_13 ffm_01 +#define fm_23 ffm_ef +#define fm_33 ffm_5b +#define q_3(x) q(0,x) + +#define f_0(n,x) ((u4byte)fm_0##n(x)) +#define f_1(n,x) ((u4byte)fm_1##n(x) << 8) +#define f_2(n,x) ((u4byte)fm_2##n(x) << 16) +#define f_3(n,x) ((u4byte)fm_3##n(x) << 24) + +#define mds(n,x) f_0(n,q_##n(x)) ^ f_1(n,q_##n(x)) ^ f_2(n,q_##n(x)) ^ f_3(n,q_##n(x)) + +#endif + +static u4byte h_fun(TwofishInstance *instance, const u4byte x, const u4byte key[]) +{ u4byte b0, b1, b2, b3; + +#ifndef M_TABLE + u4byte m5b_b0, m5b_b1, m5b_b2, m5b_b3; + u4byte mef_b0, mef_b1, mef_b2, mef_b3; +#endif + + b0 = extract_byte(x, 0); b1 = extract_byte(x, 1); b2 = extract_byte(x, 2); b3 = extract_byte(x, 3); + + switch(instance->k_len) + { + case 4: b0 = q(1, (u1byte) b0) ^ extract_byte(key[3],0); + b1 = q(0, (u1byte) b1) ^ extract_byte(key[3],1); + b2 = q(0, (u1byte) b2) ^ extract_byte(key[3],2); + b3 = q(1, (u1byte) b3) ^ extract_byte(key[3],3); + case 3: b0 = q(1, (u1byte) b0) ^ extract_byte(key[2],0); + b1 = q(1, (u1byte) b1) ^ extract_byte(key[2],1); + b2 = q(0, (u1byte) b2) ^ extract_byte(key[2],2); + b3 = q(0, (u1byte) b3) ^ extract_byte(key[2],3); + case 2: b0 = q(0, (u1byte) (q(0, (u1byte) b0) ^ extract_byte(key[1],0))) ^ extract_byte(key[0],0); + b1 = q(0, (u1byte) (q(1, (u1byte) b1) ^ extract_byte(key[1],1))) ^ extract_byte(key[0],1); + b2 = q(1, (u1byte) (q(0, (u1byte) b2) ^ extract_byte(key[1],2))) ^ extract_byte(key[0],2); + b3 = q(1, (u1byte) (q(1, (u1byte) b3) ^ extract_byte(key[1],3))) ^ extract_byte(key[0],3); + } +#ifdef M_TABLE + + return mds(0, b0) ^ mds(1, b1) ^ mds(2, b2) ^ mds(3, b3); + +#else + + b0 = q(1, (u1byte) b0); b1 = q(0, (u1byte) b1); b2 = q(1, (u1byte) b2); b3 = q(0, (u1byte) b3); + m5b_b0 = ffm_5b(b0); m5b_b1 = ffm_5b(b1); m5b_b2 = ffm_5b(b2); m5b_b3 = ffm_5b(b3); + mef_b0 = ffm_ef(b0); mef_b1 = ffm_ef(b1); mef_b2 = ffm_ef(b2); mef_b3 = ffm_ef(b3); + b0 ^= mef_b1 ^ m5b_b2 ^ m5b_b3; b3 ^= m5b_b0 ^ mef_b1 ^ mef_b2; + b2 ^= mef_b0 ^ m5b_b1 ^ mef_b3; b1 ^= mef_b0 ^ mef_b2 ^ m5b_b3; + + return b0 | (b3 << 8) | (b2 << 16) | (b1 << 24); + +#endif +}; + +#ifdef MK_TABLE + +#ifdef ONE_STEP +//u4byte mk_tab[4][256]; +#else +static u1byte sb[4][256]; +#endif + +#define q20(x) q(0,q(0,x) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) +#define q21(x) q(0,q(1,x) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) +#define q22(x) q(1,q(0,x) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) +#define q23(x) q(1,q(1,x) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) + +#define q30(x) q(0,q(0,q(1, x) ^ extract_byte(key[2],0)) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) +#define q31(x) q(0,q(1,q(1, x) ^ extract_byte(key[2],1)) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) +#define q32(x) q(1,q(0,q(0, x) ^ extract_byte(key[2],2)) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) +#define q33(x) q(1,q(1,q(0, x) ^ extract_byte(key[2],3)) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) + +#define q40(x) q(0,q(0,q(1, q(1, x) ^ extract_byte(key[3],0)) ^ extract_byte(key[2],0)) ^ extract_byte(key[1],0)) ^ extract_byte(key[0],0) +#define q41(x) q(0,q(1,q(1, q(0, x) ^ extract_byte(key[3],1)) ^ extract_byte(key[2],1)) ^ extract_byte(key[1],1)) ^ extract_byte(key[0],1) +#define q42(x) q(1,q(0,q(0, q(0, x) ^ extract_byte(key[3],2)) ^ extract_byte(key[2],2)) ^ extract_byte(key[1],2)) ^ extract_byte(key[0],2) +#define q43(x) q(1,q(1,q(0, q(1, x) ^ extract_byte(key[3],3)) ^ extract_byte(key[2],3)) ^ extract_byte(key[1],3)) ^ extract_byte(key[0],3) + +static void gen_mk_tab(TwofishInstance *instance, u4byte key[]) +{ u4byte i; + u1byte by; + + u4byte *mk_tab = instance->mk_tab; + + switch(instance->k_len) + { + case 2: for(i = 0; i < 256; ++i) + { + by = (u1byte)i; +#ifdef ONE_STEP + mk_tab[0 + 4*i] = mds(0, q20(by)); mk_tab[1 + 4*i] = mds(1, q21(by)); + mk_tab[2 + 4*i] = mds(2, q22(by)); mk_tab[3 + 4*i] = mds(3, q23(by)); +#else + sb[0][i] = q20(by); sb[1][i] = q21(by); + sb[2][i] = q22(by); sb[3][i] = q23(by); +#endif + } + break; + + case 3: for(i = 0; i < 256; ++i) + { + by = (u1byte)i; +#ifdef ONE_STEP + mk_tab[0 + 4*i] = mds(0, q30(by)); mk_tab[1 + 4*i] = mds(1, q31(by)); + mk_tab[2 + 4*i] = mds(2, q32(by)); mk_tab[3 + 4*i] = mds(3, q33(by)); +#else + sb[0][i] = q30(by); sb[1][i] = q31(by); + sb[2][i] = q32(by); sb[3][i] = q33(by); +#endif + } + break; + + case 4: for(i = 0; i < 256; ++i) + { + by = (u1byte)i; +#ifdef ONE_STEP + mk_tab[0 + 4*i] = mds(0, q40(by)); mk_tab[1 + 4*i] = mds(1, q41(by)); + mk_tab[2 + 4*i] = mds(2, q42(by)); mk_tab[3 + 4*i] = mds(3, q43(by)); +#else + sb[0][i] = q40(by); sb[1][i] = q41(by); + sb[2][i] = q42(by); sb[3][i] = q43(by); +#endif + } + } +}; + +# ifdef ONE_STEP +# define g0_fun(x) ( mk_tab[0 + 4*extract_byte(x,0)] ^ mk_tab[1 + 4*extract_byte(x,1)] \ + ^ mk_tab[2 + 4*extract_byte(x,2)] ^ mk_tab[3 + 4*extract_byte(x,3)] ) +# define g1_fun(x) ( mk_tab[0 + 4*extract_byte(x,3)] ^ mk_tab[1 + 4*extract_byte(x,0)] \ + ^ mk_tab[2 + 4*extract_byte(x,1)] ^ mk_tab[3 + 4*extract_byte(x,2)] ) + + +# else +# define g0_fun(x) ( mds(0, sb[0][extract_byte(x,0)]) ^ mds(1, sb[1][extract_byte(x,1)]) \ + ^ mds(2, sb[2][extract_byte(x,2)]) ^ mds(3, sb[3][extract_byte(x,3)]) ) +# define g1_fun(x) ( mds(0, sb[0][extract_byte(x,3)]) ^ mds(1, sb[1][extract_byte(x,0)]) \ + ^ mds(2, sb[2][extract_byte(x,1)]) ^ mds(3, sb[3][extract_byte(x,2)]) ) +# endif + +#else + +#define g0_fun(x) h_fun(instance, x, instance->s_key) +#define g1_fun(x) h_fun(instance, rotl(x,8), instance->s_key) + +#endif + +/* The (12,8) Reed Soloman code has the generator polynomial + + g(x) = x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1 + +where the coefficients are in the finite field GF(2^8) with a +modular polynomial a^8 + a^6 + a^3 + a^2 + 1. To generate the +remainder we have to start with a 12th order polynomial with our +eight input bytes as the coefficients of the 4th to 11th terms. +That is: + + m[7] * x^11 + m[6] * x^10 ... + m[0] * x^4 + 0 * x^3 +... + 0 + +We then multiply the generator polynomial by m[7] * x^7 and subtract +it - xor in GF(2^8) - from the above to eliminate the x^7 term (the +artihmetic on the coefficients is done in GF(2^8). We then multiply +the generator polynomial by x^6 * coeff(x^10) and use this to remove +the x^10 term. We carry on in this way until the x^4 term is removed +so that we are left with: + + r[3] * x^3 + r[2] * x^2 + r[1] 8 x^1 + r[0] + +which give the resulting 4 bytes of the remainder. This is equivalent +to the matrix multiplication in the Twofish description but much faster +to implement. + +*/ + +#define G_MOD 0x0000014d + +static u4byte mds_rem(u4byte p0, u4byte p1) +{ u4byte i, t, u; + + for(i = 0; i < 8; ++i) + { + t = p1 >> 24; // get most significant coefficient + + p1 = (p1 << 8) | (p0 >> 24); p0 <<= 8; // shift others up + + // multiply t by a (the primitive element - i.e. left shift) + + u = (t << 1); + + if(t & 0x80) // subtract modular polynomial on overflow + + u ^= G_MOD; + + p1 ^= t ^ (u << 16); // remove t * (a * x^2 + 1) + + u ^= (t >> 1); // form u = a * t + t / a = t * (a + 1 / a); + + if(t & 0x01) // add the modular polynomial on underflow + + u ^= G_MOD >> 1; + + p1 ^= (u << 24) | (u << 8); // remove t * (a + 1/a) * (x^3 + x) + } + + return p1; +}; + +/* initialise the key schedule from the user supplied key */ + +u4byte *twofish_set_key(TwofishInstance *instance, const u4byte in_key[], const u4byte key_len) +{ u4byte i, a, b, me_key[4], mo_key[4]; + u4byte *l_key, *s_key; + + l_key = instance->l_key; + s_key = instance->s_key; + +#ifdef Q_TABLES + if(!qt_gen) + { + gen_qtab(); qt_gen = 1; + } +#endif + +#ifdef M_TABLE + if(!mt_gen) + { + gen_mtab(); mt_gen = 1; + } +#endif + + instance->k_len = key_len / 64; /* 2, 3 or 4 */ + + for(i = 0; i < instance->k_len; ++i) + { + a = LE32(in_key[i + i]); me_key[i] = a; + b = LE32(in_key[i + i + 1]); mo_key[i] = b; + s_key[instance->k_len - i - 1] = mds_rem(a, b); + } + + for(i = 0; i < 40; i += 2) + { + a = 0x01010101 * i; b = a + 0x01010101; + a = h_fun(instance, a, me_key); + b = rotl(h_fun(instance, b, mo_key), 8); + l_key[i] = a + b; + l_key[i + 1] = rotl(a + 2 * b, 9); + } + +#ifdef MK_TABLE + gen_mk_tab(instance, s_key); +#endif + + return l_key; +}; + +/* encrypt a block of text */ + +#ifndef TC_MINIMIZE_CODE_SIZE + +#define f_rnd(i) \ + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); \ + blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1); \ + blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]); \ + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); \ + blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1); \ + blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]) + +void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; + u4byte *mk_tab = instance->mk_tab; + + blk[0] = LE32(in_blk[0]) ^ l_key[0]; + blk[1] = LE32(in_blk[1]) ^ l_key[1]; + blk[2] = LE32(in_blk[2]) ^ l_key[2]; + blk[3] = LE32(in_blk[3]) ^ l_key[3]; + + f_rnd(0); f_rnd(1); f_rnd(2); f_rnd(3); + f_rnd(4); f_rnd(5); f_rnd(6); f_rnd(7); + + out_blk[0] = LE32(blk[2] ^ l_key[4]); + out_blk[1] = LE32(blk[3] ^ l_key[5]); + out_blk[2] = LE32(blk[0] ^ l_key[6]); + out_blk[3] = LE32(blk[1] ^ l_key[7]); +}; + +#else // TC_MINIMIZE_CODE_SIZE + +void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; +#ifdef TC_WINDOWS_BOOT_TWOFISH + u4byte *mk_tab = instance->mk_tab; +#endif + int i; + + blk[0] = LE32(in_blk[0]) ^ l_key[0]; + blk[1] = LE32(in_blk[1]) ^ l_key[1]; + blk[2] = LE32(in_blk[2]) ^ l_key[2]; + blk[3] = LE32(in_blk[3]) ^ l_key[3]; + + for (i = 0; i <= 7; ++i) + { + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); + blk[2] = rotr(blk[2] ^ (t0 + t1 + l_key[4 * (i) + 8]), 1); + blk[3] = rotl(blk[3], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]); + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); + blk[0] = rotr(blk[0] ^ (t0 + t1 + l_key[4 * (i) + 10]), 1); + blk[1] = rotl(blk[1], 1) ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]); + } + + out_blk[0] = LE32(blk[2] ^ l_key[4]); + out_blk[1] = LE32(blk[3] ^ l_key[5]); + out_blk[2] = LE32(blk[0] ^ l_key[6]); + out_blk[3] = LE32(blk[1] ^ l_key[7]); +}; + +#endif // TC_MINIMIZE_CODE_SIZE + +/* decrypt a block of text */ + +#ifndef TC_MINIMIZE_CODE_SIZE + +#define i_rnd(i) \ + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); \ + blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]); \ + blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); \ + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); \ + blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) + 8]); \ + blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]), 1) + +void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; + u4byte *mk_tab = instance->mk_tab; + + blk[0] = LE32(in_blk[0]) ^ l_key[4]; + blk[1] = LE32(in_blk[1]) ^ l_key[5]; + blk[2] = LE32(in_blk[2]) ^ l_key[6]; + blk[3] = LE32(in_blk[3]) ^ l_key[7]; + + i_rnd(7); i_rnd(6); i_rnd(5); i_rnd(4); + i_rnd(3); i_rnd(2); i_rnd(1); i_rnd(0); + + out_blk[0] = LE32(blk[2] ^ l_key[0]); + out_blk[1] = LE32(blk[3] ^ l_key[1]); + out_blk[2] = LE32(blk[0] ^ l_key[2]); + out_blk[3] = LE32(blk[1] ^ l_key[3]); +}; + +#else // TC_MINIMIZE_CODE_SIZE + +void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]) +{ u4byte t0, t1, blk[4]; + + u4byte *l_key = instance->l_key; +#ifdef TC_WINDOWS_BOOT_TWOFISH + u4byte *mk_tab = instance->mk_tab; +#endif + int i; + + blk[0] = LE32(in_blk[0]) ^ l_key[4]; + blk[1] = LE32(in_blk[1]) ^ l_key[5]; + blk[2] = LE32(in_blk[2]) ^ l_key[6]; + blk[3] = LE32(in_blk[3]) ^ l_key[7]; + + for (i = 7; i >= 0; --i) + { + t1 = g1_fun(blk[1]); t0 = g0_fun(blk[0]); + blk[2] = rotl(blk[2], 1) ^ (t0 + t1 + l_key[4 * (i) + 10]); + blk[3] = rotr(blk[3] ^ (t0 + 2 * t1 + l_key[4 * (i) + 11]), 1); + t1 = g1_fun(blk[3]); t0 = g0_fun(blk[2]); + blk[0] = rotl(blk[0], 1) ^ (t0 + t1 + l_key[4 * (i) + 8]); + blk[1] = rotr(blk[1] ^ (t0 + 2 * t1 + l_key[4 * (i) + 9]), 1); + } + + out_blk[0] = LE32(blk[2] ^ l_key[0]); + out_blk[1] = LE32(blk[3] ^ l_key[1]); + out_blk[2] = LE32(blk[0] ^ l_key[2]); + out_blk[3] = LE32(blk[1] ^ l_key[3]); +}; + +#endif // TC_MINIMIZE_CODE_SIZE diff --git a/src/utils/crypto/twofish.h b/src/utils/crypto/twofish.h new file mode 100644 index 000000000..b63ae69cd --- /dev/null +++ b/src/utils/crypto/twofish.h @@ -0,0 +1,56 @@ +#ifndef TWOFISH_H +#define TWOFISH_H + +#include + + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifndef u4byte +#define u4byte uint32_t +#endif +#ifndef u1byte +#define u1byte uint8_t +#endif + +#ifndef extract_byte +#define extract_byte(x,n) ((u1byte)((x) >> (8 * n))) +#endif + +#ifndef rotl + +#ifdef _WIN32 +#include +// #pragma intrinsic(_lrotr,_lrotl) +#define rotr(x,n) _lrotr(x,n) +#define rotl(x,n) _lrotl(x,n) +#else +#define rotr(x,n) (((x)>>(n))|((x)<<(32-(n)))) +#define rotl(x,n) (((x)<<(n))|((x)>>(32-(n)))) +#endif + +#endif +typedef struct +{ + u4byte l_key[40]; + u4byte s_key[4]; +#if !defined (TC_MINIMIZE_CODE_SIZE) || defined (TC_WINDOWS_BOOT_TWOFISH) + u4byte mk_tab[4 * 256]; +#endif + u4byte k_len; +} TwofishInstance; + +#define TWOFISH_KS sizeof(TwofishInstance) + +u4byte * twofish_set_key(TwofishInstance *instance, const u4byte in_key[], const u4byte key_len); +void twofish_encrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[]); +void twofish_decrypt(TwofishInstance *instance, const u4byte in_blk[4], u4byte out_blk[4]); + +#if defined(__cplusplus) +} +#endif + +#endif // TWOFISH_H diff --git a/src/utils/crypto/whirlpool.c b/src/utils/crypto/whirlpool.c new file mode 100644 index 000000000..baaedb5d0 --- /dev/null +++ b/src/utils/crypto/whirlpool.c @@ -0,0 +1,1058 @@ +/** + * The Whirlpool hashing function. + * + *

+ * References + * + *

+ * The Whirlpool algorithm was developed by + * Paulo S. L. M. Barreto and + * Vincent Rijmen. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * @author Paulo S.L.M. Barreto + * @author Vincent Rijmen. + * Minor modifications by TrueCrypt Foundation. + * + * @version 3.0 (2003.03.12) + * + * ============================================================================= + * + * Differences from version 2.1: + * + * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9). + * + * ============================================================================= + * + * Differences from version 2.0: + * + * - Generation of ISO/IEC 10118-3 test vectors. + * - Bug fix: nonzero carry was ignored when tallying the data length + * (this bug apparently only manifested itself when feeding data + * in pieces rather than in a single chunk at once). + * - Support for MS Visual C++ 64-bit integer arithmetic. + * + * Differences from version 1.0: + * + * - Original S-box replaced by the tweaked, hardware-efficient version. + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + /* The code contained in this file (Whirlpool.c) is in the public domain. */ + +#include +#include +#include +#include + +#include "whirlpool.h" + +/* #define TRACE_INTERMEDIATE_VALUES */ + +/* + * The number of rounds of the internal dedicated block cipher. + */ +#define R 10 + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +static const u64 C0[256] = { + LL(0x18186018c07830d8), LL(0x23238c2305af4626), LL(0xc6c63fc67ef991b8), LL(0xe8e887e8136fcdfb), + LL(0x878726874ca113cb), LL(0xb8b8dab8a9626d11), LL(0x0101040108050209), LL(0x4f4f214f426e9e0d), + LL(0x3636d836adee6c9b), LL(0xa6a6a2a6590451ff), LL(0xd2d26fd2debdb90c), LL(0xf5f5f3f5fb06f70e), + LL(0x7979f979ef80f296), LL(0x6f6fa16f5fcede30), LL(0x91917e91fcef3f6d), LL(0x52525552aa07a4f8), + LL(0x60609d6027fdc047), LL(0xbcbccabc89766535), LL(0x9b9b569baccd2b37), LL(0x8e8e028e048c018a), + LL(0xa3a3b6a371155bd2), LL(0x0c0c300c603c186c), LL(0x7b7bf17bff8af684), LL(0x3535d435b5e16a80), + LL(0x1d1d741de8693af5), LL(0xe0e0a7e05347ddb3), LL(0xd7d77bd7f6acb321), LL(0xc2c22fc25eed999c), + LL(0x2e2eb82e6d965c43), LL(0x4b4b314b627a9629), LL(0xfefedffea321e15d), LL(0x575741578216aed5), + LL(0x15155415a8412abd), LL(0x7777c1779fb6eee8), LL(0x3737dc37a5eb6e92), LL(0xe5e5b3e57b56d79e), + LL(0x9f9f469f8cd92313), LL(0xf0f0e7f0d317fd23), LL(0x4a4a354a6a7f9420), LL(0xdada4fda9e95a944), + LL(0x58587d58fa25b0a2), LL(0xc9c903c906ca8fcf), LL(0x2929a429558d527c), LL(0x0a0a280a5022145a), + LL(0xb1b1feb1e14f7f50), LL(0xa0a0baa0691a5dc9), LL(0x6b6bb16b7fdad614), LL(0x85852e855cab17d9), + LL(0xbdbdcebd8173673c), LL(0x5d5d695dd234ba8f), LL(0x1010401080502090), LL(0xf4f4f7f4f303f507), + LL(0xcbcb0bcb16c08bdd), LL(0x3e3ef83eedc67cd3), LL(0x0505140528110a2d), LL(0x676781671fe6ce78), + LL(0xe4e4b7e47353d597), LL(0x27279c2725bb4e02), LL(0x4141194132588273), LL(0x8b8b168b2c9d0ba7), + LL(0xa7a7a6a7510153f6), LL(0x7d7de97dcf94fab2), LL(0x95956e95dcfb3749), LL(0xd8d847d88e9fad56), + LL(0xfbfbcbfb8b30eb70), LL(0xeeee9fee2371c1cd), LL(0x7c7ced7cc791f8bb), LL(0x6666856617e3cc71), + LL(0xdddd53dda68ea77b), LL(0x17175c17b84b2eaf), LL(0x4747014702468e45), LL(0x9e9e429e84dc211a), + LL(0xcaca0fca1ec589d4), LL(0x2d2db42d75995a58), LL(0xbfbfc6bf9179632e), LL(0x07071c07381b0e3f), + LL(0xadad8ead012347ac), LL(0x5a5a755aea2fb4b0), LL(0x838336836cb51bef), LL(0x3333cc3385ff66b6), + LL(0x636391633ff2c65c), LL(0x02020802100a0412), LL(0xaaaa92aa39384993), LL(0x7171d971afa8e2de), + LL(0xc8c807c80ecf8dc6), LL(0x19196419c87d32d1), LL(0x494939497270923b), LL(0xd9d943d9869aaf5f), + LL(0xf2f2eff2c31df931), LL(0xe3e3abe34b48dba8), LL(0x5b5b715be22ab6b9), LL(0x88881a8834920dbc), + LL(0x9a9a529aa4c8293e), LL(0x262698262dbe4c0b), LL(0x3232c8328dfa64bf), LL(0xb0b0fab0e94a7d59), + LL(0xe9e983e91b6acff2), LL(0x0f0f3c0f78331e77), LL(0xd5d573d5e6a6b733), LL(0x80803a8074ba1df4), + LL(0xbebec2be997c6127), LL(0xcdcd13cd26de87eb), LL(0x3434d034bde46889), LL(0x48483d487a759032), + LL(0xffffdbffab24e354), LL(0x7a7af57af78ff48d), LL(0x90907a90f4ea3d64), LL(0x5f5f615fc23ebe9d), + LL(0x202080201da0403d), LL(0x6868bd6867d5d00f), LL(0x1a1a681ad07234ca), LL(0xaeae82ae192c41b7), + LL(0xb4b4eab4c95e757d), LL(0x54544d549a19a8ce), LL(0x93937693ece53b7f), LL(0x222288220daa442f), + LL(0x64648d6407e9c863), LL(0xf1f1e3f1db12ff2a), LL(0x7373d173bfa2e6cc), LL(0x12124812905a2482), + LL(0x40401d403a5d807a), LL(0x0808200840281048), LL(0xc3c32bc356e89b95), LL(0xecec97ec337bc5df), + LL(0xdbdb4bdb9690ab4d), LL(0xa1a1bea1611f5fc0), LL(0x8d8d0e8d1c830791), LL(0x3d3df43df5c97ac8), + LL(0x97976697ccf1335b), LL(0x0000000000000000), LL(0xcfcf1bcf36d483f9), LL(0x2b2bac2b4587566e), + LL(0x7676c57697b3ece1), LL(0x8282328264b019e6), LL(0xd6d67fd6fea9b128), LL(0x1b1b6c1bd87736c3), + LL(0xb5b5eeb5c15b7774), LL(0xafaf86af112943be), LL(0x6a6ab56a77dfd41d), LL(0x50505d50ba0da0ea), + LL(0x45450945124c8a57), LL(0xf3f3ebf3cb18fb38), LL(0x3030c0309df060ad), LL(0xefef9bef2b74c3c4), + LL(0x3f3ffc3fe5c37eda), LL(0x55554955921caac7), LL(0xa2a2b2a2791059db), LL(0xeaea8fea0365c9e9), + LL(0x656589650fecca6a), LL(0xbabad2bab9686903), LL(0x2f2fbc2f65935e4a), LL(0xc0c027c04ee79d8e), + LL(0xdede5fdebe81a160), LL(0x1c1c701ce06c38fc), LL(0xfdfdd3fdbb2ee746), LL(0x4d4d294d52649a1f), + LL(0x92927292e4e03976), LL(0x7575c9758fbceafa), LL(0x06061806301e0c36), LL(0x8a8a128a249809ae), + LL(0xb2b2f2b2f940794b), LL(0xe6e6bfe66359d185), LL(0x0e0e380e70361c7e), LL(0x1f1f7c1ff8633ee7), + LL(0x6262956237f7c455), LL(0xd4d477d4eea3b53a), LL(0xa8a89aa829324d81), LL(0x96966296c4f43152), + LL(0xf9f9c3f99b3aef62), LL(0xc5c533c566f697a3), LL(0x2525942535b14a10), LL(0x59597959f220b2ab), + LL(0x84842a8454ae15d0), LL(0x7272d572b7a7e4c5), LL(0x3939e439d5dd72ec), LL(0x4c4c2d4c5a619816), + LL(0x5e5e655eca3bbc94), LL(0x7878fd78e785f09f), LL(0x3838e038ddd870e5), LL(0x8c8c0a8c14860598), + LL(0xd1d163d1c6b2bf17), LL(0xa5a5aea5410b57e4), LL(0xe2e2afe2434dd9a1), LL(0x616199612ff8c24e), + LL(0xb3b3f6b3f1457b42), LL(0x2121842115a54234), LL(0x9c9c4a9c94d62508), LL(0x1e1e781ef0663cee), + LL(0x4343114322528661), LL(0xc7c73bc776fc93b1), LL(0xfcfcd7fcb32be54f), LL(0x0404100420140824), + LL(0x51515951b208a2e3), LL(0x99995e99bcc72f25), LL(0x6d6da96d4fc4da22), LL(0x0d0d340d68391a65), + LL(0xfafacffa8335e979), LL(0xdfdf5bdfb684a369), LL(0x7e7ee57ed79bfca9), LL(0x242490243db44819), + LL(0x3b3bec3bc5d776fe), LL(0xabab96ab313d4b9a), LL(0xcece1fce3ed181f0), LL(0x1111441188552299), + LL(0x8f8f068f0c890383), LL(0x4e4e254e4a6b9c04), LL(0xb7b7e6b7d1517366), LL(0xebeb8beb0b60cbe0), + LL(0x3c3cf03cfdcc78c1), LL(0x81813e817cbf1ffd), LL(0x94946a94d4fe3540), LL(0xf7f7fbf7eb0cf31c), + LL(0xb9b9deb9a1676f18), LL(0x13134c13985f268b), LL(0x2c2cb02c7d9c5851), LL(0xd3d36bd3d6b8bb05), + LL(0xe7e7bbe76b5cd38c), LL(0x6e6ea56e57cbdc39), LL(0xc4c437c46ef395aa), LL(0x03030c03180f061b), + LL(0x565645568a13acdc), LL(0x44440d441a49885e), LL(0x7f7fe17fdf9efea0), LL(0xa9a99ea921374f88), + LL(0x2a2aa82a4d825467), LL(0xbbbbd6bbb16d6b0a), LL(0xc1c123c146e29f87), LL(0x53535153a202a6f1), + LL(0xdcdc57dcae8ba572), LL(0x0b0b2c0b58271653), LL(0x9d9d4e9d9cd32701), LL(0x6c6cad6c47c1d82b), + LL(0x3131c43195f562a4), LL(0x7474cd7487b9e8f3), LL(0xf6f6fff6e309f115), LL(0x464605460a438c4c), + LL(0xacac8aac092645a5), LL(0x89891e893c970fb5), LL(0x14145014a04428b4), LL(0xe1e1a3e15b42dfba), + LL(0x16165816b04e2ca6), LL(0x3a3ae83acdd274f7), LL(0x6969b9696fd0d206), LL(0x09092409482d1241), + LL(0x7070dd70a7ade0d7), LL(0xb6b6e2b6d954716f), LL(0xd0d067d0ceb7bd1e), LL(0xeded93ed3b7ec7d6), + LL(0xcccc17cc2edb85e2), LL(0x424215422a578468), LL(0x98985a98b4c22d2c), LL(0xa4a4aaa4490e55ed), + LL(0x2828a0285d885075), LL(0x5c5c6d5cda31b886), LL(0xf8f8c7f8933fed6b), LL(0x8686228644a411c2), +}; + +static const u64 C1[256] = { + LL(0xd818186018c07830), LL(0x2623238c2305af46), LL(0xb8c6c63fc67ef991), LL(0xfbe8e887e8136fcd), + LL(0xcb878726874ca113), LL(0x11b8b8dab8a9626d), LL(0x0901010401080502), LL(0x0d4f4f214f426e9e), + LL(0x9b3636d836adee6c), LL(0xffa6a6a2a6590451), LL(0x0cd2d26fd2debdb9), LL(0x0ef5f5f3f5fb06f7), + LL(0x967979f979ef80f2), LL(0x306f6fa16f5fcede), LL(0x6d91917e91fcef3f), LL(0xf852525552aa07a4), + LL(0x4760609d6027fdc0), LL(0x35bcbccabc897665), LL(0x379b9b569baccd2b), LL(0x8a8e8e028e048c01), + LL(0xd2a3a3b6a371155b), LL(0x6c0c0c300c603c18), LL(0x847b7bf17bff8af6), LL(0x803535d435b5e16a), + LL(0xf51d1d741de8693a), LL(0xb3e0e0a7e05347dd), LL(0x21d7d77bd7f6acb3), LL(0x9cc2c22fc25eed99), + LL(0x432e2eb82e6d965c), LL(0x294b4b314b627a96), LL(0x5dfefedffea321e1), LL(0xd5575741578216ae), + LL(0xbd15155415a8412a), LL(0xe87777c1779fb6ee), LL(0x923737dc37a5eb6e), LL(0x9ee5e5b3e57b56d7), + LL(0x139f9f469f8cd923), LL(0x23f0f0e7f0d317fd), LL(0x204a4a354a6a7f94), LL(0x44dada4fda9e95a9), + LL(0xa258587d58fa25b0), LL(0xcfc9c903c906ca8f), LL(0x7c2929a429558d52), LL(0x5a0a0a280a502214), + LL(0x50b1b1feb1e14f7f), LL(0xc9a0a0baa0691a5d), LL(0x146b6bb16b7fdad6), LL(0xd985852e855cab17), + LL(0x3cbdbdcebd817367), LL(0x8f5d5d695dd234ba), LL(0x9010104010805020), LL(0x07f4f4f7f4f303f5), + LL(0xddcbcb0bcb16c08b), LL(0xd33e3ef83eedc67c), LL(0x2d0505140528110a), LL(0x78676781671fe6ce), + LL(0x97e4e4b7e47353d5), LL(0x0227279c2725bb4e), LL(0x7341411941325882), LL(0xa78b8b168b2c9d0b), + LL(0xf6a7a7a6a7510153), LL(0xb27d7de97dcf94fa), LL(0x4995956e95dcfb37), LL(0x56d8d847d88e9fad), + LL(0x70fbfbcbfb8b30eb), LL(0xcdeeee9fee2371c1), LL(0xbb7c7ced7cc791f8), LL(0x716666856617e3cc), + LL(0x7bdddd53dda68ea7), LL(0xaf17175c17b84b2e), LL(0x454747014702468e), LL(0x1a9e9e429e84dc21), + LL(0xd4caca0fca1ec589), LL(0x582d2db42d75995a), LL(0x2ebfbfc6bf917963), LL(0x3f07071c07381b0e), + LL(0xacadad8ead012347), LL(0xb05a5a755aea2fb4), LL(0xef838336836cb51b), LL(0xb63333cc3385ff66), + LL(0x5c636391633ff2c6), LL(0x1202020802100a04), LL(0x93aaaa92aa393849), LL(0xde7171d971afa8e2), + LL(0xc6c8c807c80ecf8d), LL(0xd119196419c87d32), LL(0x3b49493949727092), LL(0x5fd9d943d9869aaf), + LL(0x31f2f2eff2c31df9), LL(0xa8e3e3abe34b48db), LL(0xb95b5b715be22ab6), LL(0xbc88881a8834920d), + LL(0x3e9a9a529aa4c829), LL(0x0b262698262dbe4c), LL(0xbf3232c8328dfa64), LL(0x59b0b0fab0e94a7d), + LL(0xf2e9e983e91b6acf), LL(0x770f0f3c0f78331e), LL(0x33d5d573d5e6a6b7), LL(0xf480803a8074ba1d), + LL(0x27bebec2be997c61), LL(0xebcdcd13cd26de87), LL(0x893434d034bde468), LL(0x3248483d487a7590), + LL(0x54ffffdbffab24e3), LL(0x8d7a7af57af78ff4), LL(0x6490907a90f4ea3d), LL(0x9d5f5f615fc23ebe), + LL(0x3d202080201da040), LL(0x0f6868bd6867d5d0), LL(0xca1a1a681ad07234), LL(0xb7aeae82ae192c41), + LL(0x7db4b4eab4c95e75), LL(0xce54544d549a19a8), LL(0x7f93937693ece53b), LL(0x2f222288220daa44), + LL(0x6364648d6407e9c8), LL(0x2af1f1e3f1db12ff), LL(0xcc7373d173bfa2e6), LL(0x8212124812905a24), + LL(0x7a40401d403a5d80), LL(0x4808082008402810), LL(0x95c3c32bc356e89b), LL(0xdfecec97ec337bc5), + LL(0x4ddbdb4bdb9690ab), LL(0xc0a1a1bea1611f5f), LL(0x918d8d0e8d1c8307), LL(0xc83d3df43df5c97a), + LL(0x5b97976697ccf133), LL(0x0000000000000000), LL(0xf9cfcf1bcf36d483), LL(0x6e2b2bac2b458756), + LL(0xe17676c57697b3ec), LL(0xe68282328264b019), LL(0x28d6d67fd6fea9b1), LL(0xc31b1b6c1bd87736), + LL(0x74b5b5eeb5c15b77), LL(0xbeafaf86af112943), LL(0x1d6a6ab56a77dfd4), LL(0xea50505d50ba0da0), + LL(0x5745450945124c8a), LL(0x38f3f3ebf3cb18fb), LL(0xad3030c0309df060), LL(0xc4efef9bef2b74c3), + LL(0xda3f3ffc3fe5c37e), LL(0xc755554955921caa), LL(0xdba2a2b2a2791059), LL(0xe9eaea8fea0365c9), + LL(0x6a656589650fecca), LL(0x03babad2bab96869), LL(0x4a2f2fbc2f65935e), LL(0x8ec0c027c04ee79d), + LL(0x60dede5fdebe81a1), LL(0xfc1c1c701ce06c38), LL(0x46fdfdd3fdbb2ee7), LL(0x1f4d4d294d52649a), + LL(0x7692927292e4e039), LL(0xfa7575c9758fbcea), LL(0x3606061806301e0c), LL(0xae8a8a128a249809), + LL(0x4bb2b2f2b2f94079), LL(0x85e6e6bfe66359d1), LL(0x7e0e0e380e70361c), LL(0xe71f1f7c1ff8633e), + LL(0x556262956237f7c4), LL(0x3ad4d477d4eea3b5), LL(0x81a8a89aa829324d), LL(0x5296966296c4f431), + LL(0x62f9f9c3f99b3aef), LL(0xa3c5c533c566f697), LL(0x102525942535b14a), LL(0xab59597959f220b2), + LL(0xd084842a8454ae15), LL(0xc57272d572b7a7e4), LL(0xec3939e439d5dd72), LL(0x164c4c2d4c5a6198), + LL(0x945e5e655eca3bbc), LL(0x9f7878fd78e785f0), LL(0xe53838e038ddd870), LL(0x988c8c0a8c148605), + LL(0x17d1d163d1c6b2bf), LL(0xe4a5a5aea5410b57), LL(0xa1e2e2afe2434dd9), LL(0x4e616199612ff8c2), + LL(0x42b3b3f6b3f1457b), LL(0x342121842115a542), LL(0x089c9c4a9c94d625), LL(0xee1e1e781ef0663c), + LL(0x6143431143225286), LL(0xb1c7c73bc776fc93), LL(0x4ffcfcd7fcb32be5), LL(0x2404041004201408), + LL(0xe351515951b208a2), LL(0x2599995e99bcc72f), LL(0x226d6da96d4fc4da), LL(0x650d0d340d68391a), + LL(0x79fafacffa8335e9), LL(0x69dfdf5bdfb684a3), LL(0xa97e7ee57ed79bfc), LL(0x19242490243db448), + LL(0xfe3b3bec3bc5d776), LL(0x9aabab96ab313d4b), LL(0xf0cece1fce3ed181), LL(0x9911114411885522), + LL(0x838f8f068f0c8903), LL(0x044e4e254e4a6b9c), LL(0x66b7b7e6b7d15173), LL(0xe0ebeb8beb0b60cb), + LL(0xc13c3cf03cfdcc78), LL(0xfd81813e817cbf1f), LL(0x4094946a94d4fe35), LL(0x1cf7f7fbf7eb0cf3), + LL(0x18b9b9deb9a1676f), LL(0x8b13134c13985f26), LL(0x512c2cb02c7d9c58), LL(0x05d3d36bd3d6b8bb), + LL(0x8ce7e7bbe76b5cd3), LL(0x396e6ea56e57cbdc), LL(0xaac4c437c46ef395), LL(0x1b03030c03180f06), + LL(0xdc565645568a13ac), LL(0x5e44440d441a4988), LL(0xa07f7fe17fdf9efe), LL(0x88a9a99ea921374f), + LL(0x672a2aa82a4d8254), LL(0x0abbbbd6bbb16d6b), LL(0x87c1c123c146e29f), LL(0xf153535153a202a6), + LL(0x72dcdc57dcae8ba5), LL(0x530b0b2c0b582716), LL(0x019d9d4e9d9cd327), LL(0x2b6c6cad6c47c1d8), + LL(0xa43131c43195f562), LL(0xf37474cd7487b9e8), LL(0x15f6f6fff6e309f1), LL(0x4c464605460a438c), + LL(0xa5acac8aac092645), LL(0xb589891e893c970f), LL(0xb414145014a04428), LL(0xbae1e1a3e15b42df), + LL(0xa616165816b04e2c), LL(0xf73a3ae83acdd274), LL(0x066969b9696fd0d2), LL(0x4109092409482d12), + LL(0xd77070dd70a7ade0), LL(0x6fb6b6e2b6d95471), LL(0x1ed0d067d0ceb7bd), LL(0xd6eded93ed3b7ec7), + LL(0xe2cccc17cc2edb85), LL(0x68424215422a5784), LL(0x2c98985a98b4c22d), LL(0xeda4a4aaa4490e55), + LL(0x752828a0285d8850), LL(0x865c5c6d5cda31b8), LL(0x6bf8f8c7f8933fed), LL(0xc28686228644a411), +}; + +static const u64 C2[256] = { + LL(0x30d818186018c078), LL(0x462623238c2305af), LL(0x91b8c6c63fc67ef9), LL(0xcdfbe8e887e8136f), + LL(0x13cb878726874ca1), LL(0x6d11b8b8dab8a962), LL(0x0209010104010805), LL(0x9e0d4f4f214f426e), + LL(0x6c9b3636d836adee), LL(0x51ffa6a6a2a65904), LL(0xb90cd2d26fd2debd), LL(0xf70ef5f5f3f5fb06), + LL(0xf2967979f979ef80), LL(0xde306f6fa16f5fce), LL(0x3f6d91917e91fcef), LL(0xa4f852525552aa07), + LL(0xc04760609d6027fd), LL(0x6535bcbccabc8976), LL(0x2b379b9b569baccd), LL(0x018a8e8e028e048c), + LL(0x5bd2a3a3b6a37115), LL(0x186c0c0c300c603c), LL(0xf6847b7bf17bff8a), LL(0x6a803535d435b5e1), + LL(0x3af51d1d741de869), LL(0xddb3e0e0a7e05347), LL(0xb321d7d77bd7f6ac), LL(0x999cc2c22fc25eed), + LL(0x5c432e2eb82e6d96), LL(0x96294b4b314b627a), LL(0xe15dfefedffea321), LL(0xaed5575741578216), + LL(0x2abd15155415a841), LL(0xeee87777c1779fb6), LL(0x6e923737dc37a5eb), LL(0xd79ee5e5b3e57b56), + LL(0x23139f9f469f8cd9), LL(0xfd23f0f0e7f0d317), LL(0x94204a4a354a6a7f), LL(0xa944dada4fda9e95), + LL(0xb0a258587d58fa25), LL(0x8fcfc9c903c906ca), LL(0x527c2929a429558d), LL(0x145a0a0a280a5022), + LL(0x7f50b1b1feb1e14f), LL(0x5dc9a0a0baa0691a), LL(0xd6146b6bb16b7fda), LL(0x17d985852e855cab), + LL(0x673cbdbdcebd8173), LL(0xba8f5d5d695dd234), LL(0x2090101040108050), LL(0xf507f4f4f7f4f303), + LL(0x8bddcbcb0bcb16c0), LL(0x7cd33e3ef83eedc6), LL(0x0a2d050514052811), LL(0xce78676781671fe6), + LL(0xd597e4e4b7e47353), LL(0x4e0227279c2725bb), LL(0x8273414119413258), LL(0x0ba78b8b168b2c9d), + LL(0x53f6a7a7a6a75101), LL(0xfab27d7de97dcf94), LL(0x374995956e95dcfb), LL(0xad56d8d847d88e9f), + LL(0xeb70fbfbcbfb8b30), LL(0xc1cdeeee9fee2371), LL(0xf8bb7c7ced7cc791), LL(0xcc716666856617e3), + LL(0xa77bdddd53dda68e), LL(0x2eaf17175c17b84b), LL(0x8e45474701470246), LL(0x211a9e9e429e84dc), + LL(0x89d4caca0fca1ec5), LL(0x5a582d2db42d7599), LL(0x632ebfbfc6bf9179), LL(0x0e3f07071c07381b), + LL(0x47acadad8ead0123), LL(0xb4b05a5a755aea2f), LL(0x1bef838336836cb5), LL(0x66b63333cc3385ff), + LL(0xc65c636391633ff2), LL(0x041202020802100a), LL(0x4993aaaa92aa3938), LL(0xe2de7171d971afa8), + LL(0x8dc6c8c807c80ecf), LL(0x32d119196419c87d), LL(0x923b494939497270), LL(0xaf5fd9d943d9869a), + LL(0xf931f2f2eff2c31d), LL(0xdba8e3e3abe34b48), LL(0xb6b95b5b715be22a), LL(0x0dbc88881a883492), + LL(0x293e9a9a529aa4c8), LL(0x4c0b262698262dbe), LL(0x64bf3232c8328dfa), LL(0x7d59b0b0fab0e94a), + LL(0xcff2e9e983e91b6a), LL(0x1e770f0f3c0f7833), LL(0xb733d5d573d5e6a6), LL(0x1df480803a8074ba), + LL(0x6127bebec2be997c), LL(0x87ebcdcd13cd26de), LL(0x68893434d034bde4), LL(0x903248483d487a75), + LL(0xe354ffffdbffab24), LL(0xf48d7a7af57af78f), LL(0x3d6490907a90f4ea), LL(0xbe9d5f5f615fc23e), + LL(0x403d202080201da0), LL(0xd00f6868bd6867d5), LL(0x34ca1a1a681ad072), LL(0x41b7aeae82ae192c), + LL(0x757db4b4eab4c95e), LL(0xa8ce54544d549a19), LL(0x3b7f93937693ece5), LL(0x442f222288220daa), + LL(0xc86364648d6407e9), LL(0xff2af1f1e3f1db12), LL(0xe6cc7373d173bfa2), LL(0x248212124812905a), + LL(0x807a40401d403a5d), LL(0x1048080820084028), LL(0x9b95c3c32bc356e8), LL(0xc5dfecec97ec337b), + LL(0xab4ddbdb4bdb9690), LL(0x5fc0a1a1bea1611f), LL(0x07918d8d0e8d1c83), LL(0x7ac83d3df43df5c9), + LL(0x335b97976697ccf1), LL(0x0000000000000000), LL(0x83f9cfcf1bcf36d4), LL(0x566e2b2bac2b4587), + LL(0xece17676c57697b3), LL(0x19e68282328264b0), LL(0xb128d6d67fd6fea9), LL(0x36c31b1b6c1bd877), + LL(0x7774b5b5eeb5c15b), LL(0x43beafaf86af1129), LL(0xd41d6a6ab56a77df), LL(0xa0ea50505d50ba0d), + LL(0x8a5745450945124c), LL(0xfb38f3f3ebf3cb18), LL(0x60ad3030c0309df0), LL(0xc3c4efef9bef2b74), + LL(0x7eda3f3ffc3fe5c3), LL(0xaac755554955921c), LL(0x59dba2a2b2a27910), LL(0xc9e9eaea8fea0365), + LL(0xca6a656589650fec), LL(0x6903babad2bab968), LL(0x5e4a2f2fbc2f6593), LL(0x9d8ec0c027c04ee7), + LL(0xa160dede5fdebe81), LL(0x38fc1c1c701ce06c), LL(0xe746fdfdd3fdbb2e), LL(0x9a1f4d4d294d5264), + LL(0x397692927292e4e0), LL(0xeafa7575c9758fbc), LL(0x0c3606061806301e), LL(0x09ae8a8a128a2498), + LL(0x794bb2b2f2b2f940), LL(0xd185e6e6bfe66359), LL(0x1c7e0e0e380e7036), LL(0x3ee71f1f7c1ff863), + LL(0xc4556262956237f7), LL(0xb53ad4d477d4eea3), LL(0x4d81a8a89aa82932), LL(0x315296966296c4f4), + LL(0xef62f9f9c3f99b3a), LL(0x97a3c5c533c566f6), LL(0x4a102525942535b1), LL(0xb2ab59597959f220), + LL(0x15d084842a8454ae), LL(0xe4c57272d572b7a7), LL(0x72ec3939e439d5dd), LL(0x98164c4c2d4c5a61), + LL(0xbc945e5e655eca3b), LL(0xf09f7878fd78e785), LL(0x70e53838e038ddd8), LL(0x05988c8c0a8c1486), + LL(0xbf17d1d163d1c6b2), LL(0x57e4a5a5aea5410b), LL(0xd9a1e2e2afe2434d), LL(0xc24e616199612ff8), + LL(0x7b42b3b3f6b3f145), LL(0x42342121842115a5), LL(0x25089c9c4a9c94d6), LL(0x3cee1e1e781ef066), + LL(0x8661434311432252), LL(0x93b1c7c73bc776fc), LL(0xe54ffcfcd7fcb32b), LL(0x0824040410042014), + LL(0xa2e351515951b208), LL(0x2f2599995e99bcc7), LL(0xda226d6da96d4fc4), LL(0x1a650d0d340d6839), + LL(0xe979fafacffa8335), LL(0xa369dfdf5bdfb684), LL(0xfca97e7ee57ed79b), LL(0x4819242490243db4), + LL(0x76fe3b3bec3bc5d7), LL(0x4b9aabab96ab313d), LL(0x81f0cece1fce3ed1), LL(0x2299111144118855), + LL(0x03838f8f068f0c89), LL(0x9c044e4e254e4a6b), LL(0x7366b7b7e6b7d151), LL(0xcbe0ebeb8beb0b60), + LL(0x78c13c3cf03cfdcc), LL(0x1ffd81813e817cbf), LL(0x354094946a94d4fe), LL(0xf31cf7f7fbf7eb0c), + LL(0x6f18b9b9deb9a167), LL(0x268b13134c13985f), LL(0x58512c2cb02c7d9c), LL(0xbb05d3d36bd3d6b8), + LL(0xd38ce7e7bbe76b5c), LL(0xdc396e6ea56e57cb), LL(0x95aac4c437c46ef3), LL(0x061b03030c03180f), + LL(0xacdc565645568a13), LL(0x885e44440d441a49), LL(0xfea07f7fe17fdf9e), LL(0x4f88a9a99ea92137), + LL(0x54672a2aa82a4d82), LL(0x6b0abbbbd6bbb16d), LL(0x9f87c1c123c146e2), LL(0xa6f153535153a202), + LL(0xa572dcdc57dcae8b), LL(0x16530b0b2c0b5827), LL(0x27019d9d4e9d9cd3), LL(0xd82b6c6cad6c47c1), + LL(0x62a43131c43195f5), LL(0xe8f37474cd7487b9), LL(0xf115f6f6fff6e309), LL(0x8c4c464605460a43), + LL(0x45a5acac8aac0926), LL(0x0fb589891e893c97), LL(0x28b414145014a044), LL(0xdfbae1e1a3e15b42), + LL(0x2ca616165816b04e), LL(0x74f73a3ae83acdd2), LL(0xd2066969b9696fd0), LL(0x124109092409482d), + LL(0xe0d77070dd70a7ad), LL(0x716fb6b6e2b6d954), LL(0xbd1ed0d067d0ceb7), LL(0xc7d6eded93ed3b7e), + LL(0x85e2cccc17cc2edb), LL(0x8468424215422a57), LL(0x2d2c98985a98b4c2), LL(0x55eda4a4aaa4490e), + LL(0x50752828a0285d88), LL(0xb8865c5c6d5cda31), LL(0xed6bf8f8c7f8933f), LL(0x11c28686228644a4), +}; + +static const u64 C3[256] = { + LL(0x7830d818186018c0), LL(0xaf462623238c2305), LL(0xf991b8c6c63fc67e), LL(0x6fcdfbe8e887e813), + LL(0xa113cb878726874c), LL(0x626d11b8b8dab8a9), LL(0x0502090101040108), LL(0x6e9e0d4f4f214f42), + LL(0xee6c9b3636d836ad), LL(0x0451ffa6a6a2a659), LL(0xbdb90cd2d26fd2de), LL(0x06f70ef5f5f3f5fb), + LL(0x80f2967979f979ef), LL(0xcede306f6fa16f5f), LL(0xef3f6d91917e91fc), LL(0x07a4f852525552aa), + LL(0xfdc04760609d6027), LL(0x766535bcbccabc89), LL(0xcd2b379b9b569bac), LL(0x8c018a8e8e028e04), + LL(0x155bd2a3a3b6a371), LL(0x3c186c0c0c300c60), LL(0x8af6847b7bf17bff), LL(0xe16a803535d435b5), + LL(0x693af51d1d741de8), LL(0x47ddb3e0e0a7e053), LL(0xacb321d7d77bd7f6), LL(0xed999cc2c22fc25e), + LL(0x965c432e2eb82e6d), LL(0x7a96294b4b314b62), LL(0x21e15dfefedffea3), LL(0x16aed55757415782), + LL(0x412abd15155415a8), LL(0xb6eee87777c1779f), LL(0xeb6e923737dc37a5), LL(0x56d79ee5e5b3e57b), + LL(0xd923139f9f469f8c), LL(0x17fd23f0f0e7f0d3), LL(0x7f94204a4a354a6a), LL(0x95a944dada4fda9e), + LL(0x25b0a258587d58fa), LL(0xca8fcfc9c903c906), LL(0x8d527c2929a42955), LL(0x22145a0a0a280a50), + LL(0x4f7f50b1b1feb1e1), LL(0x1a5dc9a0a0baa069), LL(0xdad6146b6bb16b7f), LL(0xab17d985852e855c), + LL(0x73673cbdbdcebd81), LL(0x34ba8f5d5d695dd2), LL(0x5020901010401080), LL(0x03f507f4f4f7f4f3), + LL(0xc08bddcbcb0bcb16), LL(0xc67cd33e3ef83eed), LL(0x110a2d0505140528), LL(0xe6ce78676781671f), + LL(0x53d597e4e4b7e473), LL(0xbb4e0227279c2725), LL(0x5882734141194132), LL(0x9d0ba78b8b168b2c), + LL(0x0153f6a7a7a6a751), LL(0x94fab27d7de97dcf), LL(0xfb374995956e95dc), LL(0x9fad56d8d847d88e), + LL(0x30eb70fbfbcbfb8b), LL(0x71c1cdeeee9fee23), LL(0x91f8bb7c7ced7cc7), LL(0xe3cc716666856617), + LL(0x8ea77bdddd53dda6), LL(0x4b2eaf17175c17b8), LL(0x468e454747014702), LL(0xdc211a9e9e429e84), + LL(0xc589d4caca0fca1e), LL(0x995a582d2db42d75), LL(0x79632ebfbfc6bf91), LL(0x1b0e3f07071c0738), + LL(0x2347acadad8ead01), LL(0x2fb4b05a5a755aea), LL(0xb51bef838336836c), LL(0xff66b63333cc3385), + LL(0xf2c65c636391633f), LL(0x0a04120202080210), LL(0x384993aaaa92aa39), LL(0xa8e2de7171d971af), + LL(0xcf8dc6c8c807c80e), LL(0x7d32d119196419c8), LL(0x70923b4949394972), LL(0x9aaf5fd9d943d986), + LL(0x1df931f2f2eff2c3), LL(0x48dba8e3e3abe34b), LL(0x2ab6b95b5b715be2), LL(0x920dbc88881a8834), + LL(0xc8293e9a9a529aa4), LL(0xbe4c0b262698262d), LL(0xfa64bf3232c8328d), LL(0x4a7d59b0b0fab0e9), + LL(0x6acff2e9e983e91b), LL(0x331e770f0f3c0f78), LL(0xa6b733d5d573d5e6), LL(0xba1df480803a8074), + LL(0x7c6127bebec2be99), LL(0xde87ebcdcd13cd26), LL(0xe468893434d034bd), LL(0x75903248483d487a), + LL(0x24e354ffffdbffab), LL(0x8ff48d7a7af57af7), LL(0xea3d6490907a90f4), LL(0x3ebe9d5f5f615fc2), + LL(0xa0403d202080201d), LL(0xd5d00f6868bd6867), LL(0x7234ca1a1a681ad0), LL(0x2c41b7aeae82ae19), + LL(0x5e757db4b4eab4c9), LL(0x19a8ce54544d549a), LL(0xe53b7f93937693ec), LL(0xaa442f222288220d), + LL(0xe9c86364648d6407), LL(0x12ff2af1f1e3f1db), LL(0xa2e6cc7373d173bf), LL(0x5a24821212481290), + LL(0x5d807a40401d403a), LL(0x2810480808200840), LL(0xe89b95c3c32bc356), LL(0x7bc5dfecec97ec33), + LL(0x90ab4ddbdb4bdb96), LL(0x1f5fc0a1a1bea161), LL(0x8307918d8d0e8d1c), LL(0xc97ac83d3df43df5), + LL(0xf1335b97976697cc), LL(0x0000000000000000), LL(0xd483f9cfcf1bcf36), LL(0x87566e2b2bac2b45), + LL(0xb3ece17676c57697), LL(0xb019e68282328264), LL(0xa9b128d6d67fd6fe), LL(0x7736c31b1b6c1bd8), + LL(0x5b7774b5b5eeb5c1), LL(0x2943beafaf86af11), LL(0xdfd41d6a6ab56a77), LL(0x0da0ea50505d50ba), + LL(0x4c8a574545094512), LL(0x18fb38f3f3ebf3cb), LL(0xf060ad3030c0309d), LL(0x74c3c4efef9bef2b), + LL(0xc37eda3f3ffc3fe5), LL(0x1caac75555495592), LL(0x1059dba2a2b2a279), LL(0x65c9e9eaea8fea03), + LL(0xecca6a656589650f), LL(0x686903babad2bab9), LL(0x935e4a2f2fbc2f65), LL(0xe79d8ec0c027c04e), + LL(0x81a160dede5fdebe), LL(0x6c38fc1c1c701ce0), LL(0x2ee746fdfdd3fdbb), LL(0x649a1f4d4d294d52), + LL(0xe0397692927292e4), LL(0xbceafa7575c9758f), LL(0x1e0c360606180630), LL(0x9809ae8a8a128a24), + LL(0x40794bb2b2f2b2f9), LL(0x59d185e6e6bfe663), LL(0x361c7e0e0e380e70), LL(0x633ee71f1f7c1ff8), + LL(0xf7c4556262956237), LL(0xa3b53ad4d477d4ee), LL(0x324d81a8a89aa829), LL(0xf4315296966296c4), + LL(0x3aef62f9f9c3f99b), LL(0xf697a3c5c533c566), LL(0xb14a102525942535), LL(0x20b2ab59597959f2), + LL(0xae15d084842a8454), LL(0xa7e4c57272d572b7), LL(0xdd72ec3939e439d5), LL(0x6198164c4c2d4c5a), + LL(0x3bbc945e5e655eca), LL(0x85f09f7878fd78e7), LL(0xd870e53838e038dd), LL(0x8605988c8c0a8c14), + LL(0xb2bf17d1d163d1c6), LL(0x0b57e4a5a5aea541), LL(0x4dd9a1e2e2afe243), LL(0xf8c24e616199612f), + LL(0x457b42b3b3f6b3f1), LL(0xa542342121842115), LL(0xd625089c9c4a9c94), LL(0x663cee1e1e781ef0), + LL(0x5286614343114322), LL(0xfc93b1c7c73bc776), LL(0x2be54ffcfcd7fcb3), LL(0x1408240404100420), + LL(0x08a2e351515951b2), LL(0xc72f2599995e99bc), LL(0xc4da226d6da96d4f), LL(0x391a650d0d340d68), + LL(0x35e979fafacffa83), LL(0x84a369dfdf5bdfb6), LL(0x9bfca97e7ee57ed7), LL(0xb44819242490243d), + LL(0xd776fe3b3bec3bc5), LL(0x3d4b9aabab96ab31), LL(0xd181f0cece1fce3e), LL(0x5522991111441188), + LL(0x8903838f8f068f0c), LL(0x6b9c044e4e254e4a), LL(0x517366b7b7e6b7d1), LL(0x60cbe0ebeb8beb0b), + LL(0xcc78c13c3cf03cfd), LL(0xbf1ffd81813e817c), LL(0xfe354094946a94d4), LL(0x0cf31cf7f7fbf7eb), + LL(0x676f18b9b9deb9a1), LL(0x5f268b13134c1398), LL(0x9c58512c2cb02c7d), LL(0xb8bb05d3d36bd3d6), + LL(0x5cd38ce7e7bbe76b), LL(0xcbdc396e6ea56e57), LL(0xf395aac4c437c46e), LL(0x0f061b03030c0318), + LL(0x13acdc565645568a), LL(0x49885e44440d441a), LL(0x9efea07f7fe17fdf), LL(0x374f88a9a99ea921), + LL(0x8254672a2aa82a4d), LL(0x6d6b0abbbbd6bbb1), LL(0xe29f87c1c123c146), LL(0x02a6f153535153a2), + LL(0x8ba572dcdc57dcae), LL(0x2716530b0b2c0b58), LL(0xd327019d9d4e9d9c), LL(0xc1d82b6c6cad6c47), + LL(0xf562a43131c43195), LL(0xb9e8f37474cd7487), LL(0x09f115f6f6fff6e3), LL(0x438c4c464605460a), + LL(0x2645a5acac8aac09), LL(0x970fb589891e893c), LL(0x4428b414145014a0), LL(0x42dfbae1e1a3e15b), + LL(0x4e2ca616165816b0), LL(0xd274f73a3ae83acd), LL(0xd0d2066969b9696f), LL(0x2d12410909240948), + LL(0xade0d77070dd70a7), LL(0x54716fb6b6e2b6d9), LL(0xb7bd1ed0d067d0ce), LL(0x7ec7d6eded93ed3b), + LL(0xdb85e2cccc17cc2e), LL(0x578468424215422a), LL(0xc22d2c98985a98b4), LL(0x0e55eda4a4aaa449), + LL(0x8850752828a0285d), LL(0x31b8865c5c6d5cda), LL(0x3fed6bf8f8c7f893), LL(0xa411c28686228644), +}; + +static const u64 C4[256] = { + LL(0xc07830d818186018), LL(0x05af462623238c23), LL(0x7ef991b8c6c63fc6), LL(0x136fcdfbe8e887e8), + LL(0x4ca113cb87872687), LL(0xa9626d11b8b8dab8), LL(0x0805020901010401), LL(0x426e9e0d4f4f214f), + LL(0xadee6c9b3636d836), LL(0x590451ffa6a6a2a6), LL(0xdebdb90cd2d26fd2), LL(0xfb06f70ef5f5f3f5), + LL(0xef80f2967979f979), LL(0x5fcede306f6fa16f), LL(0xfcef3f6d91917e91), LL(0xaa07a4f852525552), + LL(0x27fdc04760609d60), LL(0x89766535bcbccabc), LL(0xaccd2b379b9b569b), LL(0x048c018a8e8e028e), + LL(0x71155bd2a3a3b6a3), LL(0x603c186c0c0c300c), LL(0xff8af6847b7bf17b), LL(0xb5e16a803535d435), + LL(0xe8693af51d1d741d), LL(0x5347ddb3e0e0a7e0), LL(0xf6acb321d7d77bd7), LL(0x5eed999cc2c22fc2), + LL(0x6d965c432e2eb82e), LL(0x627a96294b4b314b), LL(0xa321e15dfefedffe), LL(0x8216aed557574157), + LL(0xa8412abd15155415), LL(0x9fb6eee87777c177), LL(0xa5eb6e923737dc37), LL(0x7b56d79ee5e5b3e5), + LL(0x8cd923139f9f469f), LL(0xd317fd23f0f0e7f0), LL(0x6a7f94204a4a354a), LL(0x9e95a944dada4fda), + LL(0xfa25b0a258587d58), LL(0x06ca8fcfc9c903c9), LL(0x558d527c2929a429), LL(0x5022145a0a0a280a), + LL(0xe14f7f50b1b1feb1), LL(0x691a5dc9a0a0baa0), LL(0x7fdad6146b6bb16b), LL(0x5cab17d985852e85), + LL(0x8173673cbdbdcebd), LL(0xd234ba8f5d5d695d), LL(0x8050209010104010), LL(0xf303f507f4f4f7f4), + LL(0x16c08bddcbcb0bcb), LL(0xedc67cd33e3ef83e), LL(0x28110a2d05051405), LL(0x1fe6ce7867678167), + LL(0x7353d597e4e4b7e4), LL(0x25bb4e0227279c27), LL(0x3258827341411941), LL(0x2c9d0ba78b8b168b), + LL(0x510153f6a7a7a6a7), LL(0xcf94fab27d7de97d), LL(0xdcfb374995956e95), LL(0x8e9fad56d8d847d8), + LL(0x8b30eb70fbfbcbfb), LL(0x2371c1cdeeee9fee), LL(0xc791f8bb7c7ced7c), LL(0x17e3cc7166668566), + LL(0xa68ea77bdddd53dd), LL(0xb84b2eaf17175c17), LL(0x02468e4547470147), LL(0x84dc211a9e9e429e), + LL(0x1ec589d4caca0fca), LL(0x75995a582d2db42d), LL(0x9179632ebfbfc6bf), LL(0x381b0e3f07071c07), + LL(0x012347acadad8ead), LL(0xea2fb4b05a5a755a), LL(0x6cb51bef83833683), LL(0x85ff66b63333cc33), + LL(0x3ff2c65c63639163), LL(0x100a041202020802), LL(0x39384993aaaa92aa), LL(0xafa8e2de7171d971), + LL(0x0ecf8dc6c8c807c8), LL(0xc87d32d119196419), LL(0x7270923b49493949), LL(0x869aaf5fd9d943d9), + LL(0xc31df931f2f2eff2), LL(0x4b48dba8e3e3abe3), LL(0xe22ab6b95b5b715b), LL(0x34920dbc88881a88), + LL(0xa4c8293e9a9a529a), LL(0x2dbe4c0b26269826), LL(0x8dfa64bf3232c832), LL(0xe94a7d59b0b0fab0), + LL(0x1b6acff2e9e983e9), LL(0x78331e770f0f3c0f), LL(0xe6a6b733d5d573d5), LL(0x74ba1df480803a80), + LL(0x997c6127bebec2be), LL(0x26de87ebcdcd13cd), LL(0xbde468893434d034), LL(0x7a75903248483d48), + LL(0xab24e354ffffdbff), LL(0xf78ff48d7a7af57a), LL(0xf4ea3d6490907a90), LL(0xc23ebe9d5f5f615f), + LL(0x1da0403d20208020), LL(0x67d5d00f6868bd68), LL(0xd07234ca1a1a681a), LL(0x192c41b7aeae82ae), + LL(0xc95e757db4b4eab4), LL(0x9a19a8ce54544d54), LL(0xece53b7f93937693), LL(0x0daa442f22228822), + LL(0x07e9c86364648d64), LL(0xdb12ff2af1f1e3f1), LL(0xbfa2e6cc7373d173), LL(0x905a248212124812), + LL(0x3a5d807a40401d40), LL(0x4028104808082008), LL(0x56e89b95c3c32bc3), LL(0x337bc5dfecec97ec), + LL(0x9690ab4ddbdb4bdb), LL(0x611f5fc0a1a1bea1), LL(0x1c8307918d8d0e8d), LL(0xf5c97ac83d3df43d), + LL(0xccf1335b97976697), LL(0x0000000000000000), LL(0x36d483f9cfcf1bcf), LL(0x4587566e2b2bac2b), + LL(0x97b3ece17676c576), LL(0x64b019e682823282), LL(0xfea9b128d6d67fd6), LL(0xd87736c31b1b6c1b), + LL(0xc15b7774b5b5eeb5), LL(0x112943beafaf86af), LL(0x77dfd41d6a6ab56a), LL(0xba0da0ea50505d50), + LL(0x124c8a5745450945), LL(0xcb18fb38f3f3ebf3), LL(0x9df060ad3030c030), LL(0x2b74c3c4efef9bef), + LL(0xe5c37eda3f3ffc3f), LL(0x921caac755554955), LL(0x791059dba2a2b2a2), LL(0x0365c9e9eaea8fea), + LL(0x0fecca6a65658965), LL(0xb9686903babad2ba), LL(0x65935e4a2f2fbc2f), LL(0x4ee79d8ec0c027c0), + LL(0xbe81a160dede5fde), LL(0xe06c38fc1c1c701c), LL(0xbb2ee746fdfdd3fd), LL(0x52649a1f4d4d294d), + LL(0xe4e0397692927292), LL(0x8fbceafa7575c975), LL(0x301e0c3606061806), LL(0x249809ae8a8a128a), + LL(0xf940794bb2b2f2b2), LL(0x6359d185e6e6bfe6), LL(0x70361c7e0e0e380e), LL(0xf8633ee71f1f7c1f), + LL(0x37f7c45562629562), LL(0xeea3b53ad4d477d4), LL(0x29324d81a8a89aa8), LL(0xc4f4315296966296), + LL(0x9b3aef62f9f9c3f9), LL(0x66f697a3c5c533c5), LL(0x35b14a1025259425), LL(0xf220b2ab59597959), + LL(0x54ae15d084842a84), LL(0xb7a7e4c57272d572), LL(0xd5dd72ec3939e439), LL(0x5a6198164c4c2d4c), + LL(0xca3bbc945e5e655e), LL(0xe785f09f7878fd78), LL(0xddd870e53838e038), LL(0x148605988c8c0a8c), + LL(0xc6b2bf17d1d163d1), LL(0x410b57e4a5a5aea5), LL(0x434dd9a1e2e2afe2), LL(0x2ff8c24e61619961), + LL(0xf1457b42b3b3f6b3), LL(0x15a5423421218421), LL(0x94d625089c9c4a9c), LL(0xf0663cee1e1e781e), + LL(0x2252866143431143), LL(0x76fc93b1c7c73bc7), LL(0xb32be54ffcfcd7fc), LL(0x2014082404041004), + LL(0xb208a2e351515951), LL(0xbcc72f2599995e99), LL(0x4fc4da226d6da96d), LL(0x68391a650d0d340d), + LL(0x8335e979fafacffa), LL(0xb684a369dfdf5bdf), LL(0xd79bfca97e7ee57e), LL(0x3db4481924249024), + LL(0xc5d776fe3b3bec3b), LL(0x313d4b9aabab96ab), LL(0x3ed181f0cece1fce), LL(0x8855229911114411), + LL(0x0c8903838f8f068f), LL(0x4a6b9c044e4e254e), LL(0xd1517366b7b7e6b7), LL(0x0b60cbe0ebeb8beb), + LL(0xfdcc78c13c3cf03c), LL(0x7cbf1ffd81813e81), LL(0xd4fe354094946a94), LL(0xeb0cf31cf7f7fbf7), + LL(0xa1676f18b9b9deb9), LL(0x985f268b13134c13), LL(0x7d9c58512c2cb02c), LL(0xd6b8bb05d3d36bd3), + LL(0x6b5cd38ce7e7bbe7), LL(0x57cbdc396e6ea56e), LL(0x6ef395aac4c437c4), LL(0x180f061b03030c03), + LL(0x8a13acdc56564556), LL(0x1a49885e44440d44), LL(0xdf9efea07f7fe17f), LL(0x21374f88a9a99ea9), + LL(0x4d8254672a2aa82a), LL(0xb16d6b0abbbbd6bb), LL(0x46e29f87c1c123c1), LL(0xa202a6f153535153), + LL(0xae8ba572dcdc57dc), LL(0x582716530b0b2c0b), LL(0x9cd327019d9d4e9d), LL(0x47c1d82b6c6cad6c), + LL(0x95f562a43131c431), LL(0x87b9e8f37474cd74), LL(0xe309f115f6f6fff6), LL(0x0a438c4c46460546), + LL(0x092645a5acac8aac), LL(0x3c970fb589891e89), LL(0xa04428b414145014), LL(0x5b42dfbae1e1a3e1), + LL(0xb04e2ca616165816), LL(0xcdd274f73a3ae83a), LL(0x6fd0d2066969b969), LL(0x482d124109092409), + LL(0xa7ade0d77070dd70), LL(0xd954716fb6b6e2b6), LL(0xceb7bd1ed0d067d0), LL(0x3b7ec7d6eded93ed), + LL(0x2edb85e2cccc17cc), LL(0x2a57846842421542), LL(0xb4c22d2c98985a98), LL(0x490e55eda4a4aaa4), + LL(0x5d8850752828a028), LL(0xda31b8865c5c6d5c), LL(0x933fed6bf8f8c7f8), LL(0x44a411c286862286), +}; + +static const u64 C5[256] = { + LL(0x18c07830d8181860), LL(0x2305af462623238c), LL(0xc67ef991b8c6c63f), LL(0xe8136fcdfbe8e887), + LL(0x874ca113cb878726), LL(0xb8a9626d11b8b8da), LL(0x0108050209010104), LL(0x4f426e9e0d4f4f21), + LL(0x36adee6c9b3636d8), LL(0xa6590451ffa6a6a2), LL(0xd2debdb90cd2d26f), LL(0xf5fb06f70ef5f5f3), + LL(0x79ef80f2967979f9), LL(0x6f5fcede306f6fa1), LL(0x91fcef3f6d91917e), LL(0x52aa07a4f8525255), + LL(0x6027fdc04760609d), LL(0xbc89766535bcbcca), LL(0x9baccd2b379b9b56), LL(0x8e048c018a8e8e02), + LL(0xa371155bd2a3a3b6), LL(0x0c603c186c0c0c30), LL(0x7bff8af6847b7bf1), LL(0x35b5e16a803535d4), + LL(0x1de8693af51d1d74), LL(0xe05347ddb3e0e0a7), LL(0xd7f6acb321d7d77b), LL(0xc25eed999cc2c22f), + LL(0x2e6d965c432e2eb8), LL(0x4b627a96294b4b31), LL(0xfea321e15dfefedf), LL(0x578216aed5575741), + LL(0x15a8412abd151554), LL(0x779fb6eee87777c1), LL(0x37a5eb6e923737dc), LL(0xe57b56d79ee5e5b3), + LL(0x9f8cd923139f9f46), LL(0xf0d317fd23f0f0e7), LL(0x4a6a7f94204a4a35), LL(0xda9e95a944dada4f), + LL(0x58fa25b0a258587d), LL(0xc906ca8fcfc9c903), LL(0x29558d527c2929a4), LL(0x0a5022145a0a0a28), + LL(0xb1e14f7f50b1b1fe), LL(0xa0691a5dc9a0a0ba), LL(0x6b7fdad6146b6bb1), LL(0x855cab17d985852e), + LL(0xbd8173673cbdbdce), LL(0x5dd234ba8f5d5d69), LL(0x1080502090101040), LL(0xf4f303f507f4f4f7), + LL(0xcb16c08bddcbcb0b), LL(0x3eedc67cd33e3ef8), LL(0x0528110a2d050514), LL(0x671fe6ce78676781), + LL(0xe47353d597e4e4b7), LL(0x2725bb4e0227279c), LL(0x4132588273414119), LL(0x8b2c9d0ba78b8b16), + LL(0xa7510153f6a7a7a6), LL(0x7dcf94fab27d7de9), LL(0x95dcfb374995956e), LL(0xd88e9fad56d8d847), + LL(0xfb8b30eb70fbfbcb), LL(0xee2371c1cdeeee9f), LL(0x7cc791f8bb7c7ced), LL(0x6617e3cc71666685), + LL(0xdda68ea77bdddd53), LL(0x17b84b2eaf17175c), LL(0x4702468e45474701), LL(0x9e84dc211a9e9e42), + LL(0xca1ec589d4caca0f), LL(0x2d75995a582d2db4), LL(0xbf9179632ebfbfc6), LL(0x07381b0e3f07071c), + LL(0xad012347acadad8e), LL(0x5aea2fb4b05a5a75), LL(0x836cb51bef838336), LL(0x3385ff66b63333cc), + LL(0x633ff2c65c636391), LL(0x02100a0412020208), LL(0xaa39384993aaaa92), LL(0x71afa8e2de7171d9), + LL(0xc80ecf8dc6c8c807), LL(0x19c87d32d1191964), LL(0x497270923b494939), LL(0xd9869aaf5fd9d943), + LL(0xf2c31df931f2f2ef), LL(0xe34b48dba8e3e3ab), LL(0x5be22ab6b95b5b71), LL(0x8834920dbc88881a), + LL(0x9aa4c8293e9a9a52), LL(0x262dbe4c0b262698), LL(0x328dfa64bf3232c8), LL(0xb0e94a7d59b0b0fa), + LL(0xe91b6acff2e9e983), LL(0x0f78331e770f0f3c), LL(0xd5e6a6b733d5d573), LL(0x8074ba1df480803a), + LL(0xbe997c6127bebec2), LL(0xcd26de87ebcdcd13), LL(0x34bde468893434d0), LL(0x487a75903248483d), + LL(0xffab24e354ffffdb), LL(0x7af78ff48d7a7af5), LL(0x90f4ea3d6490907a), LL(0x5fc23ebe9d5f5f61), + LL(0x201da0403d202080), LL(0x6867d5d00f6868bd), LL(0x1ad07234ca1a1a68), LL(0xae192c41b7aeae82), + LL(0xb4c95e757db4b4ea), LL(0x549a19a8ce54544d), LL(0x93ece53b7f939376), LL(0x220daa442f222288), + LL(0x6407e9c86364648d), LL(0xf1db12ff2af1f1e3), LL(0x73bfa2e6cc7373d1), LL(0x12905a2482121248), + LL(0x403a5d807a40401d), LL(0x0840281048080820), LL(0xc356e89b95c3c32b), LL(0xec337bc5dfecec97), + LL(0xdb9690ab4ddbdb4b), LL(0xa1611f5fc0a1a1be), LL(0x8d1c8307918d8d0e), LL(0x3df5c97ac83d3df4), + LL(0x97ccf1335b979766), LL(0x0000000000000000), LL(0xcf36d483f9cfcf1b), LL(0x2b4587566e2b2bac), + LL(0x7697b3ece17676c5), LL(0x8264b019e6828232), LL(0xd6fea9b128d6d67f), LL(0x1bd87736c31b1b6c), + LL(0xb5c15b7774b5b5ee), LL(0xaf112943beafaf86), LL(0x6a77dfd41d6a6ab5), LL(0x50ba0da0ea50505d), + LL(0x45124c8a57454509), LL(0xf3cb18fb38f3f3eb), LL(0x309df060ad3030c0), LL(0xef2b74c3c4efef9b), + LL(0x3fe5c37eda3f3ffc), LL(0x55921caac7555549), LL(0xa2791059dba2a2b2), LL(0xea0365c9e9eaea8f), + LL(0x650fecca6a656589), LL(0xbab9686903babad2), LL(0x2f65935e4a2f2fbc), LL(0xc04ee79d8ec0c027), + LL(0xdebe81a160dede5f), LL(0x1ce06c38fc1c1c70), LL(0xfdbb2ee746fdfdd3), LL(0x4d52649a1f4d4d29), + LL(0x92e4e03976929272), LL(0x758fbceafa7575c9), LL(0x06301e0c36060618), LL(0x8a249809ae8a8a12), + LL(0xb2f940794bb2b2f2), LL(0xe66359d185e6e6bf), LL(0x0e70361c7e0e0e38), LL(0x1ff8633ee71f1f7c), + LL(0x6237f7c455626295), LL(0xd4eea3b53ad4d477), LL(0xa829324d81a8a89a), LL(0x96c4f43152969662), + LL(0xf99b3aef62f9f9c3), LL(0xc566f697a3c5c533), LL(0x2535b14a10252594), LL(0x59f220b2ab595979), + LL(0x8454ae15d084842a), LL(0x72b7a7e4c57272d5), LL(0x39d5dd72ec3939e4), LL(0x4c5a6198164c4c2d), + LL(0x5eca3bbc945e5e65), LL(0x78e785f09f7878fd), LL(0x38ddd870e53838e0), LL(0x8c148605988c8c0a), + LL(0xd1c6b2bf17d1d163), LL(0xa5410b57e4a5a5ae), LL(0xe2434dd9a1e2e2af), LL(0x612ff8c24e616199), + LL(0xb3f1457b42b3b3f6), LL(0x2115a54234212184), LL(0x9c94d625089c9c4a), LL(0x1ef0663cee1e1e78), + LL(0x4322528661434311), LL(0xc776fc93b1c7c73b), LL(0xfcb32be54ffcfcd7), LL(0x0420140824040410), + LL(0x51b208a2e3515159), LL(0x99bcc72f2599995e), LL(0x6d4fc4da226d6da9), LL(0x0d68391a650d0d34), + LL(0xfa8335e979fafacf), LL(0xdfb684a369dfdf5b), LL(0x7ed79bfca97e7ee5), LL(0x243db44819242490), + LL(0x3bc5d776fe3b3bec), LL(0xab313d4b9aabab96), LL(0xce3ed181f0cece1f), LL(0x1188552299111144), + LL(0x8f0c8903838f8f06), LL(0x4e4a6b9c044e4e25), LL(0xb7d1517366b7b7e6), LL(0xeb0b60cbe0ebeb8b), + LL(0x3cfdcc78c13c3cf0), LL(0x817cbf1ffd81813e), LL(0x94d4fe354094946a), LL(0xf7eb0cf31cf7f7fb), + LL(0xb9a1676f18b9b9de), LL(0x13985f268b13134c), LL(0x2c7d9c58512c2cb0), LL(0xd3d6b8bb05d3d36b), + LL(0xe76b5cd38ce7e7bb), LL(0x6e57cbdc396e6ea5), LL(0xc46ef395aac4c437), LL(0x03180f061b03030c), + LL(0x568a13acdc565645), LL(0x441a49885e44440d), LL(0x7fdf9efea07f7fe1), LL(0xa921374f88a9a99e), + LL(0x2a4d8254672a2aa8), LL(0xbbb16d6b0abbbbd6), LL(0xc146e29f87c1c123), LL(0x53a202a6f1535351), + LL(0xdcae8ba572dcdc57), LL(0x0b582716530b0b2c), LL(0x9d9cd327019d9d4e), LL(0x6c47c1d82b6c6cad), + LL(0x3195f562a43131c4), LL(0x7487b9e8f37474cd), LL(0xf6e309f115f6f6ff), LL(0x460a438c4c464605), + LL(0xac092645a5acac8a), LL(0x893c970fb589891e), LL(0x14a04428b4141450), LL(0xe15b42dfbae1e1a3), + LL(0x16b04e2ca6161658), LL(0x3acdd274f73a3ae8), LL(0x696fd0d2066969b9), LL(0x09482d1241090924), + LL(0x70a7ade0d77070dd), LL(0xb6d954716fb6b6e2), LL(0xd0ceb7bd1ed0d067), LL(0xed3b7ec7d6eded93), + LL(0xcc2edb85e2cccc17), LL(0x422a578468424215), LL(0x98b4c22d2c98985a), LL(0xa4490e55eda4a4aa), + LL(0x285d8850752828a0), LL(0x5cda31b8865c5c6d), LL(0xf8933fed6bf8f8c7), LL(0x8644a411c2868622), +}; + +static const u64 C6[256] = { + LL(0x6018c07830d81818), LL(0x8c2305af46262323), LL(0x3fc67ef991b8c6c6), LL(0x87e8136fcdfbe8e8), + LL(0x26874ca113cb8787), LL(0xdab8a9626d11b8b8), LL(0x0401080502090101), LL(0x214f426e9e0d4f4f), + LL(0xd836adee6c9b3636), LL(0xa2a6590451ffa6a6), LL(0x6fd2debdb90cd2d2), LL(0xf3f5fb06f70ef5f5), + LL(0xf979ef80f2967979), LL(0xa16f5fcede306f6f), LL(0x7e91fcef3f6d9191), LL(0x5552aa07a4f85252), + LL(0x9d6027fdc0476060), LL(0xcabc89766535bcbc), LL(0x569baccd2b379b9b), LL(0x028e048c018a8e8e), + LL(0xb6a371155bd2a3a3), LL(0x300c603c186c0c0c), LL(0xf17bff8af6847b7b), LL(0xd435b5e16a803535), + LL(0x741de8693af51d1d), LL(0xa7e05347ddb3e0e0), LL(0x7bd7f6acb321d7d7), LL(0x2fc25eed999cc2c2), + LL(0xb82e6d965c432e2e), LL(0x314b627a96294b4b), LL(0xdffea321e15dfefe), LL(0x41578216aed55757), + LL(0x5415a8412abd1515), LL(0xc1779fb6eee87777), LL(0xdc37a5eb6e923737), LL(0xb3e57b56d79ee5e5), + LL(0x469f8cd923139f9f), LL(0xe7f0d317fd23f0f0), LL(0x354a6a7f94204a4a), LL(0x4fda9e95a944dada), + LL(0x7d58fa25b0a25858), LL(0x03c906ca8fcfc9c9), LL(0xa429558d527c2929), LL(0x280a5022145a0a0a), + LL(0xfeb1e14f7f50b1b1), LL(0xbaa0691a5dc9a0a0), LL(0xb16b7fdad6146b6b), LL(0x2e855cab17d98585), + LL(0xcebd8173673cbdbd), LL(0x695dd234ba8f5d5d), LL(0x4010805020901010), LL(0xf7f4f303f507f4f4), + LL(0x0bcb16c08bddcbcb), LL(0xf83eedc67cd33e3e), LL(0x140528110a2d0505), LL(0x81671fe6ce786767), + LL(0xb7e47353d597e4e4), LL(0x9c2725bb4e022727), LL(0x1941325882734141), LL(0x168b2c9d0ba78b8b), + LL(0xa6a7510153f6a7a7), LL(0xe97dcf94fab27d7d), LL(0x6e95dcfb37499595), LL(0x47d88e9fad56d8d8), + LL(0xcbfb8b30eb70fbfb), LL(0x9fee2371c1cdeeee), LL(0xed7cc791f8bb7c7c), LL(0x856617e3cc716666), + LL(0x53dda68ea77bdddd), LL(0x5c17b84b2eaf1717), LL(0x014702468e454747), LL(0x429e84dc211a9e9e), + LL(0x0fca1ec589d4caca), LL(0xb42d75995a582d2d), LL(0xc6bf9179632ebfbf), LL(0x1c07381b0e3f0707), + LL(0x8ead012347acadad), LL(0x755aea2fb4b05a5a), LL(0x36836cb51bef8383), LL(0xcc3385ff66b63333), + LL(0x91633ff2c65c6363), LL(0x0802100a04120202), LL(0x92aa39384993aaaa), LL(0xd971afa8e2de7171), + LL(0x07c80ecf8dc6c8c8), LL(0x6419c87d32d11919), LL(0x39497270923b4949), LL(0x43d9869aaf5fd9d9), + LL(0xeff2c31df931f2f2), LL(0xabe34b48dba8e3e3), LL(0x715be22ab6b95b5b), LL(0x1a8834920dbc8888), + LL(0x529aa4c8293e9a9a), LL(0x98262dbe4c0b2626), LL(0xc8328dfa64bf3232), LL(0xfab0e94a7d59b0b0), + LL(0x83e91b6acff2e9e9), LL(0x3c0f78331e770f0f), LL(0x73d5e6a6b733d5d5), LL(0x3a8074ba1df48080), + LL(0xc2be997c6127bebe), LL(0x13cd26de87ebcdcd), LL(0xd034bde468893434), LL(0x3d487a7590324848), + LL(0xdbffab24e354ffff), LL(0xf57af78ff48d7a7a), LL(0x7a90f4ea3d649090), LL(0x615fc23ebe9d5f5f), + LL(0x80201da0403d2020), LL(0xbd6867d5d00f6868), LL(0x681ad07234ca1a1a), LL(0x82ae192c41b7aeae), + LL(0xeab4c95e757db4b4), LL(0x4d549a19a8ce5454), LL(0x7693ece53b7f9393), LL(0x88220daa442f2222), + LL(0x8d6407e9c8636464), LL(0xe3f1db12ff2af1f1), LL(0xd173bfa2e6cc7373), LL(0x4812905a24821212), + LL(0x1d403a5d807a4040), LL(0x2008402810480808), LL(0x2bc356e89b95c3c3), LL(0x97ec337bc5dfecec), + LL(0x4bdb9690ab4ddbdb), LL(0xbea1611f5fc0a1a1), LL(0x0e8d1c8307918d8d), LL(0xf43df5c97ac83d3d), + LL(0x6697ccf1335b9797), LL(0x0000000000000000), LL(0x1bcf36d483f9cfcf), LL(0xac2b4587566e2b2b), + LL(0xc57697b3ece17676), LL(0x328264b019e68282), LL(0x7fd6fea9b128d6d6), LL(0x6c1bd87736c31b1b), + LL(0xeeb5c15b7774b5b5), LL(0x86af112943beafaf), LL(0xb56a77dfd41d6a6a), LL(0x5d50ba0da0ea5050), + LL(0x0945124c8a574545), LL(0xebf3cb18fb38f3f3), LL(0xc0309df060ad3030), LL(0x9bef2b74c3c4efef), + LL(0xfc3fe5c37eda3f3f), LL(0x4955921caac75555), LL(0xb2a2791059dba2a2), LL(0x8fea0365c9e9eaea), + LL(0x89650fecca6a6565), LL(0xd2bab9686903baba), LL(0xbc2f65935e4a2f2f), LL(0x27c04ee79d8ec0c0), + LL(0x5fdebe81a160dede), LL(0x701ce06c38fc1c1c), LL(0xd3fdbb2ee746fdfd), LL(0x294d52649a1f4d4d), + LL(0x7292e4e039769292), LL(0xc9758fbceafa7575), LL(0x1806301e0c360606), LL(0x128a249809ae8a8a), + LL(0xf2b2f940794bb2b2), LL(0xbfe66359d185e6e6), LL(0x380e70361c7e0e0e), LL(0x7c1ff8633ee71f1f), + LL(0x956237f7c4556262), LL(0x77d4eea3b53ad4d4), LL(0x9aa829324d81a8a8), LL(0x6296c4f431529696), + LL(0xc3f99b3aef62f9f9), LL(0x33c566f697a3c5c5), LL(0x942535b14a102525), LL(0x7959f220b2ab5959), + LL(0x2a8454ae15d08484), LL(0xd572b7a7e4c57272), LL(0xe439d5dd72ec3939), LL(0x2d4c5a6198164c4c), + LL(0x655eca3bbc945e5e), LL(0xfd78e785f09f7878), LL(0xe038ddd870e53838), LL(0x0a8c148605988c8c), + LL(0x63d1c6b2bf17d1d1), LL(0xaea5410b57e4a5a5), LL(0xafe2434dd9a1e2e2), LL(0x99612ff8c24e6161), + LL(0xf6b3f1457b42b3b3), LL(0x842115a542342121), LL(0x4a9c94d625089c9c), LL(0x781ef0663cee1e1e), + LL(0x1143225286614343), LL(0x3bc776fc93b1c7c7), LL(0xd7fcb32be54ffcfc), LL(0x1004201408240404), + LL(0x5951b208a2e35151), LL(0x5e99bcc72f259999), LL(0xa96d4fc4da226d6d), LL(0x340d68391a650d0d), + LL(0xcffa8335e979fafa), LL(0x5bdfb684a369dfdf), LL(0xe57ed79bfca97e7e), LL(0x90243db448192424), + LL(0xec3bc5d776fe3b3b), LL(0x96ab313d4b9aabab), LL(0x1fce3ed181f0cece), LL(0x4411885522991111), + LL(0x068f0c8903838f8f), LL(0x254e4a6b9c044e4e), LL(0xe6b7d1517366b7b7), LL(0x8beb0b60cbe0ebeb), + LL(0xf03cfdcc78c13c3c), LL(0x3e817cbf1ffd8181), LL(0x6a94d4fe35409494), LL(0xfbf7eb0cf31cf7f7), + LL(0xdeb9a1676f18b9b9), LL(0x4c13985f268b1313), LL(0xb02c7d9c58512c2c), LL(0x6bd3d6b8bb05d3d3), + LL(0xbbe76b5cd38ce7e7), LL(0xa56e57cbdc396e6e), LL(0x37c46ef395aac4c4), LL(0x0c03180f061b0303), + LL(0x45568a13acdc5656), LL(0x0d441a49885e4444), LL(0xe17fdf9efea07f7f), LL(0x9ea921374f88a9a9), + LL(0xa82a4d8254672a2a), LL(0xd6bbb16d6b0abbbb), LL(0x23c146e29f87c1c1), LL(0x5153a202a6f15353), + LL(0x57dcae8ba572dcdc), LL(0x2c0b582716530b0b), LL(0x4e9d9cd327019d9d), LL(0xad6c47c1d82b6c6c), + LL(0xc43195f562a43131), LL(0xcd7487b9e8f37474), LL(0xfff6e309f115f6f6), LL(0x05460a438c4c4646), + LL(0x8aac092645a5acac), LL(0x1e893c970fb58989), LL(0x5014a04428b41414), LL(0xa3e15b42dfbae1e1), + LL(0x5816b04e2ca61616), LL(0xe83acdd274f73a3a), LL(0xb9696fd0d2066969), LL(0x2409482d12410909), + LL(0xdd70a7ade0d77070), LL(0xe2b6d954716fb6b6), LL(0x67d0ceb7bd1ed0d0), LL(0x93ed3b7ec7d6eded), + LL(0x17cc2edb85e2cccc), LL(0x15422a5784684242), LL(0x5a98b4c22d2c9898), LL(0xaaa4490e55eda4a4), + LL(0xa0285d8850752828), LL(0x6d5cda31b8865c5c), LL(0xc7f8933fed6bf8f8), LL(0x228644a411c28686), +}; + +static const u64 C7[256] = { + LL(0x186018c07830d818), LL(0x238c2305af462623), LL(0xc63fc67ef991b8c6), LL(0xe887e8136fcdfbe8), + LL(0x8726874ca113cb87), LL(0xb8dab8a9626d11b8), LL(0x0104010805020901), LL(0x4f214f426e9e0d4f), + LL(0x36d836adee6c9b36), LL(0xa6a2a6590451ffa6), LL(0xd26fd2debdb90cd2), LL(0xf5f3f5fb06f70ef5), + LL(0x79f979ef80f29679), LL(0x6fa16f5fcede306f), LL(0x917e91fcef3f6d91), LL(0x525552aa07a4f852), + LL(0x609d6027fdc04760), LL(0xbccabc89766535bc), LL(0x9b569baccd2b379b), LL(0x8e028e048c018a8e), + LL(0xa3b6a371155bd2a3), LL(0x0c300c603c186c0c), LL(0x7bf17bff8af6847b), LL(0x35d435b5e16a8035), + LL(0x1d741de8693af51d), LL(0xe0a7e05347ddb3e0), LL(0xd77bd7f6acb321d7), LL(0xc22fc25eed999cc2), + LL(0x2eb82e6d965c432e), LL(0x4b314b627a96294b), LL(0xfedffea321e15dfe), LL(0x5741578216aed557), + LL(0x155415a8412abd15), LL(0x77c1779fb6eee877), LL(0x37dc37a5eb6e9237), LL(0xe5b3e57b56d79ee5), + LL(0x9f469f8cd923139f), LL(0xf0e7f0d317fd23f0), LL(0x4a354a6a7f94204a), LL(0xda4fda9e95a944da), + LL(0x587d58fa25b0a258), LL(0xc903c906ca8fcfc9), LL(0x29a429558d527c29), LL(0x0a280a5022145a0a), + LL(0xb1feb1e14f7f50b1), LL(0xa0baa0691a5dc9a0), LL(0x6bb16b7fdad6146b), LL(0x852e855cab17d985), + LL(0xbdcebd8173673cbd), LL(0x5d695dd234ba8f5d), LL(0x1040108050209010), LL(0xf4f7f4f303f507f4), + LL(0xcb0bcb16c08bddcb), LL(0x3ef83eedc67cd33e), LL(0x05140528110a2d05), LL(0x6781671fe6ce7867), + LL(0xe4b7e47353d597e4), LL(0x279c2725bb4e0227), LL(0x4119413258827341), LL(0x8b168b2c9d0ba78b), + LL(0xa7a6a7510153f6a7), LL(0x7de97dcf94fab27d), LL(0x956e95dcfb374995), LL(0xd847d88e9fad56d8), + LL(0xfbcbfb8b30eb70fb), LL(0xee9fee2371c1cdee), LL(0x7ced7cc791f8bb7c), LL(0x66856617e3cc7166), + LL(0xdd53dda68ea77bdd), LL(0x175c17b84b2eaf17), LL(0x47014702468e4547), LL(0x9e429e84dc211a9e), + LL(0xca0fca1ec589d4ca), LL(0x2db42d75995a582d), LL(0xbfc6bf9179632ebf), LL(0x071c07381b0e3f07), + LL(0xad8ead012347acad), LL(0x5a755aea2fb4b05a), LL(0x8336836cb51bef83), LL(0x33cc3385ff66b633), + LL(0x6391633ff2c65c63), LL(0x020802100a041202), LL(0xaa92aa39384993aa), LL(0x71d971afa8e2de71), + LL(0xc807c80ecf8dc6c8), LL(0x196419c87d32d119), LL(0x4939497270923b49), LL(0xd943d9869aaf5fd9), + LL(0xf2eff2c31df931f2), LL(0xe3abe34b48dba8e3), LL(0x5b715be22ab6b95b), LL(0x881a8834920dbc88), + LL(0x9a529aa4c8293e9a), LL(0x2698262dbe4c0b26), LL(0x32c8328dfa64bf32), LL(0xb0fab0e94a7d59b0), + LL(0xe983e91b6acff2e9), LL(0x0f3c0f78331e770f), LL(0xd573d5e6a6b733d5), LL(0x803a8074ba1df480), + LL(0xbec2be997c6127be), LL(0xcd13cd26de87ebcd), LL(0x34d034bde4688934), LL(0x483d487a75903248), + LL(0xffdbffab24e354ff), LL(0x7af57af78ff48d7a), LL(0x907a90f4ea3d6490), LL(0x5f615fc23ebe9d5f), + LL(0x2080201da0403d20), LL(0x68bd6867d5d00f68), LL(0x1a681ad07234ca1a), LL(0xae82ae192c41b7ae), + LL(0xb4eab4c95e757db4), LL(0x544d549a19a8ce54), LL(0x937693ece53b7f93), LL(0x2288220daa442f22), + LL(0x648d6407e9c86364), LL(0xf1e3f1db12ff2af1), LL(0x73d173bfa2e6cc73), LL(0x124812905a248212), + LL(0x401d403a5d807a40), LL(0x0820084028104808), LL(0xc32bc356e89b95c3), LL(0xec97ec337bc5dfec), + LL(0xdb4bdb9690ab4ddb), LL(0xa1bea1611f5fc0a1), LL(0x8d0e8d1c8307918d), LL(0x3df43df5c97ac83d), + LL(0x976697ccf1335b97), LL(0x0000000000000000), LL(0xcf1bcf36d483f9cf), LL(0x2bac2b4587566e2b), + LL(0x76c57697b3ece176), LL(0x82328264b019e682), LL(0xd67fd6fea9b128d6), LL(0x1b6c1bd87736c31b), + LL(0xb5eeb5c15b7774b5), LL(0xaf86af112943beaf), LL(0x6ab56a77dfd41d6a), LL(0x505d50ba0da0ea50), + LL(0x450945124c8a5745), LL(0xf3ebf3cb18fb38f3), LL(0x30c0309df060ad30), LL(0xef9bef2b74c3c4ef), + LL(0x3ffc3fe5c37eda3f), LL(0x554955921caac755), LL(0xa2b2a2791059dba2), LL(0xea8fea0365c9e9ea), + LL(0x6589650fecca6a65), LL(0xbad2bab9686903ba), LL(0x2fbc2f65935e4a2f), LL(0xc027c04ee79d8ec0), + LL(0xde5fdebe81a160de), LL(0x1c701ce06c38fc1c), LL(0xfdd3fdbb2ee746fd), LL(0x4d294d52649a1f4d), + LL(0x927292e4e0397692), LL(0x75c9758fbceafa75), LL(0x061806301e0c3606), LL(0x8a128a249809ae8a), + LL(0xb2f2b2f940794bb2), LL(0xe6bfe66359d185e6), LL(0x0e380e70361c7e0e), LL(0x1f7c1ff8633ee71f), + LL(0x62956237f7c45562), LL(0xd477d4eea3b53ad4), LL(0xa89aa829324d81a8), LL(0x966296c4f4315296), + LL(0xf9c3f99b3aef62f9), LL(0xc533c566f697a3c5), LL(0x25942535b14a1025), LL(0x597959f220b2ab59), + LL(0x842a8454ae15d084), LL(0x72d572b7a7e4c572), LL(0x39e439d5dd72ec39), LL(0x4c2d4c5a6198164c), + LL(0x5e655eca3bbc945e), LL(0x78fd78e785f09f78), LL(0x38e038ddd870e538), LL(0x8c0a8c148605988c), + LL(0xd163d1c6b2bf17d1), LL(0xa5aea5410b57e4a5), LL(0xe2afe2434dd9a1e2), LL(0x6199612ff8c24e61), + LL(0xb3f6b3f1457b42b3), LL(0x21842115a5423421), LL(0x9c4a9c94d625089c), LL(0x1e781ef0663cee1e), + LL(0x4311432252866143), LL(0xc73bc776fc93b1c7), LL(0xfcd7fcb32be54ffc), LL(0x0410042014082404), + LL(0x515951b208a2e351), LL(0x995e99bcc72f2599), LL(0x6da96d4fc4da226d), LL(0x0d340d68391a650d), + LL(0xfacffa8335e979fa), LL(0xdf5bdfb684a369df), LL(0x7ee57ed79bfca97e), LL(0x2490243db4481924), + LL(0x3bec3bc5d776fe3b), LL(0xab96ab313d4b9aab), LL(0xce1fce3ed181f0ce), LL(0x1144118855229911), + LL(0x8f068f0c8903838f), LL(0x4e254e4a6b9c044e), LL(0xb7e6b7d1517366b7), LL(0xeb8beb0b60cbe0eb), + LL(0x3cf03cfdcc78c13c), LL(0x813e817cbf1ffd81), LL(0x946a94d4fe354094), LL(0xf7fbf7eb0cf31cf7), + LL(0xb9deb9a1676f18b9), LL(0x134c13985f268b13), LL(0x2cb02c7d9c58512c), LL(0xd36bd3d6b8bb05d3), + LL(0xe7bbe76b5cd38ce7), LL(0x6ea56e57cbdc396e), LL(0xc437c46ef395aac4), LL(0x030c03180f061b03), + LL(0x5645568a13acdc56), LL(0x440d441a49885e44), LL(0x7fe17fdf9efea07f), LL(0xa99ea921374f88a9), + LL(0x2aa82a4d8254672a), LL(0xbbd6bbb16d6b0abb), LL(0xc123c146e29f87c1), LL(0x535153a202a6f153), + LL(0xdc57dcae8ba572dc), LL(0x0b2c0b582716530b), LL(0x9d4e9d9cd327019d), LL(0x6cad6c47c1d82b6c), + LL(0x31c43195f562a431), LL(0x74cd7487b9e8f374), LL(0xf6fff6e309f115f6), LL(0x4605460a438c4c46), + LL(0xac8aac092645a5ac), LL(0x891e893c970fb589), LL(0x145014a04428b414), LL(0xe1a3e15b42dfbae1), + LL(0x165816b04e2ca616), LL(0x3ae83acdd274f73a), LL(0x69b9696fd0d20669), LL(0x092409482d124109), + LL(0x70dd70a7ade0d770), LL(0xb6e2b6d954716fb6), LL(0xd067d0ceb7bd1ed0), LL(0xed93ed3b7ec7d6ed), + LL(0xcc17cc2edb85e2cc), LL(0x4215422a57846842), LL(0x985a98b4c22d2c98), LL(0xa4aaa4490e55eda4), + LL(0x28a0285d88507528), LL(0x5c6d5cda31b8865c), LL(0xf8c7f8933fed6bf8), LL(0x86228644a411c286), +}; + +static const u64 rc[R + 1] = { + LL(0x0000000000000000), + LL(0x1823c6e887b8014f), + LL(0x36a6d2f5796f9152), + LL(0x60bc9b8ea30c7b35), + LL(0x1de0d7c22e4bfe57), + LL(0x157737e59ff04ada), + LL(0x58c9290ab1a06b85), + LL(0xbd5d10f4cb3e0567), + LL(0xe427418ba77d95d8), + LL(0xfbee7c66dd17479e), + LL(0xca2dbf07ad5a8333), +}; + +/** + * The core Whirlpool transform. + */ +static void processBuffer(struct NESSIEstruct * const structpointer) { + int i, r; + u64 K[8]; /* the round key */ + u64 block[8]; /* mu(buffer) */ + u64 state[8]; /* the cipher state */ + u64 L[8]; + u8 *buffer = structpointer->buffer; + /* + * map the buffer to a block: + */ + for (i = 0; i < 8; i++, buffer += 8) { + block[i] = + (((u64)buffer[0] ) << 56) ^ + (((u64)buffer[1] & 0xffL) << 48) ^ + (((u64)buffer[2] & 0xffL) << 40) ^ + (((u64)buffer[3] & 0xffL) << 32) ^ + (((u64)buffer[4] & 0xffL) << 24) ^ + (((u64)buffer[5] & 0xffL) << 16) ^ + (((u64)buffer[6] & 0xffL) << 8) ^ + (((u64)buffer[7] & 0xffL) ); + } + /* + * compute and apply K^0 to the cipher state: + */ + state[0] = block[0] ^ (K[0] = structpointer->hash[0]); + state[1] = block[1] ^ (K[1] = structpointer->hash[1]); + state[2] = block[2] ^ (K[2] = structpointer->hash[2]); + state[3] = block[3] ^ (K[3] = structpointer->hash[3]); + state[4] = block[4] ^ (K[4] = structpointer->hash[4]); + state[5] = block[5] ^ (K[5] = structpointer->hash[5]); + state[6] = block[6] ^ (K[6] = structpointer->hash[6]); + state[7] = block[7] ^ (K[7] = structpointer->hash[7]); + /* + * iterate over all rounds: + */ + for (r = 1; r <= R; r++) { + /* + * compute K^r from K^{r-1}: + */ + L[0] = + C0[(int)(K[0] >> 56) ] ^ + C1[(int)(K[7] >> 48) & 0xff] ^ + C2[(int)(K[6] >> 40) & 0xff] ^ + C3[(int)(K[5] >> 32) & 0xff] ^ + C4[(int)(K[4] >> 24) & 0xff] ^ + C5[(int)(K[3] >> 16) & 0xff] ^ + C6[(int)(K[2] >> 8) & 0xff] ^ + C7[(int)(K[1] ) & 0xff] ^ + rc[r]; + L[1] = + C0[(int)(K[1] >> 56) ] ^ + C1[(int)(K[0] >> 48) & 0xff] ^ + C2[(int)(K[7] >> 40) & 0xff] ^ + C3[(int)(K[6] >> 32) & 0xff] ^ + C4[(int)(K[5] >> 24) & 0xff] ^ + C5[(int)(K[4] >> 16) & 0xff] ^ + C6[(int)(K[3] >> 8) & 0xff] ^ + C7[(int)(K[2] ) & 0xff]; + L[2] = + C0[(int)(K[2] >> 56) ] ^ + C1[(int)(K[1] >> 48) & 0xff] ^ + C2[(int)(K[0] >> 40) & 0xff] ^ + C3[(int)(K[7] >> 32) & 0xff] ^ + C4[(int)(K[6] >> 24) & 0xff] ^ + C5[(int)(K[5] >> 16) & 0xff] ^ + C6[(int)(K[4] >> 8) & 0xff] ^ + C7[(int)(K[3] ) & 0xff]; + L[3] = + C0[(int)(K[3] >> 56) ] ^ + C1[(int)(K[2] >> 48) & 0xff] ^ + C2[(int)(K[1] >> 40) & 0xff] ^ + C3[(int)(K[0] >> 32) & 0xff] ^ + C4[(int)(K[7] >> 24) & 0xff] ^ + C5[(int)(K[6] >> 16) & 0xff] ^ + C6[(int)(K[5] >> 8) & 0xff] ^ + C7[(int)(K[4] ) & 0xff]; + L[4] = + C0[(int)(K[4] >> 56) ] ^ + C1[(int)(K[3] >> 48) & 0xff] ^ + C2[(int)(K[2] >> 40) & 0xff] ^ + C3[(int)(K[1] >> 32) & 0xff] ^ + C4[(int)(K[0] >> 24) & 0xff] ^ + C5[(int)(K[7] >> 16) & 0xff] ^ + C6[(int)(K[6] >> 8) & 0xff] ^ + C7[(int)(K[5] ) & 0xff]; + L[5] = + C0[(int)(K[5] >> 56) ] ^ + C1[(int)(K[4] >> 48) & 0xff] ^ + C2[(int)(K[3] >> 40) & 0xff] ^ + C3[(int)(K[2] >> 32) & 0xff] ^ + C4[(int)(K[1] >> 24) & 0xff] ^ + C5[(int)(K[0] >> 16) & 0xff] ^ + C6[(int)(K[7] >> 8) & 0xff] ^ + C7[(int)(K[6] ) & 0xff]; + L[6] = + C0[(int)(K[6] >> 56) ] ^ + C1[(int)(K[5] >> 48) & 0xff] ^ + C2[(int)(K[4] >> 40) & 0xff] ^ + C3[(int)(K[3] >> 32) & 0xff] ^ + C4[(int)(K[2] >> 24) & 0xff] ^ + C5[(int)(K[1] >> 16) & 0xff] ^ + C6[(int)(K[0] >> 8) & 0xff] ^ + C7[(int)(K[7] ) & 0xff]; + L[7] = + C0[(int)(K[7] >> 56) ] ^ + C1[(int)(K[6] >> 48) & 0xff] ^ + C2[(int)(K[5] >> 40) & 0xff] ^ + C3[(int)(K[4] >> 32) & 0xff] ^ + C4[(int)(K[3] >> 24) & 0xff] ^ + C5[(int)(K[2] >> 16) & 0xff] ^ + C6[(int)(K[1] >> 8) & 0xff] ^ + C7[(int)(K[0] ) & 0xff]; + K[0] = L[0]; + K[1] = L[1]; + K[2] = L[2]; + K[3] = L[3]; + K[4] = L[4]; + K[5] = L[5]; + K[6] = L[6]; + K[7] = L[7]; + /* + * apply the r-th round transformation: + */ + L[0] = + C0[(int)(state[0] >> 56) ] ^ + C1[(int)(state[7] >> 48) & 0xff] ^ + C2[(int)(state[6] >> 40) & 0xff] ^ + C3[(int)(state[5] >> 32) & 0xff] ^ + C4[(int)(state[4] >> 24) & 0xff] ^ + C5[(int)(state[3] >> 16) & 0xff] ^ + C6[(int)(state[2] >> 8) & 0xff] ^ + C7[(int)(state[1] ) & 0xff] ^ + K[0]; + L[1] = + C0[(int)(state[1] >> 56) ] ^ + C1[(int)(state[0] >> 48) & 0xff] ^ + C2[(int)(state[7] >> 40) & 0xff] ^ + C3[(int)(state[6] >> 32) & 0xff] ^ + C4[(int)(state[5] >> 24) & 0xff] ^ + C5[(int)(state[4] >> 16) & 0xff] ^ + C6[(int)(state[3] >> 8) & 0xff] ^ + C7[(int)(state[2] ) & 0xff] ^ + K[1]; + L[2] = + C0[(int)(state[2] >> 56) ] ^ + C1[(int)(state[1] >> 48) & 0xff] ^ + C2[(int)(state[0] >> 40) & 0xff] ^ + C3[(int)(state[7] >> 32) & 0xff] ^ + C4[(int)(state[6] >> 24) & 0xff] ^ + C5[(int)(state[5] >> 16) & 0xff] ^ + C6[(int)(state[4] >> 8) & 0xff] ^ + C7[(int)(state[3] ) & 0xff] ^ + K[2]; + L[3] = + C0[(int)(state[3] >> 56) ] ^ + C1[(int)(state[2] >> 48) & 0xff] ^ + C2[(int)(state[1] >> 40) & 0xff] ^ + C3[(int)(state[0] >> 32) & 0xff] ^ + C4[(int)(state[7] >> 24) & 0xff] ^ + C5[(int)(state[6] >> 16) & 0xff] ^ + C6[(int)(state[5] >> 8) & 0xff] ^ + C7[(int)(state[4] ) & 0xff] ^ + K[3]; + L[4] = + C0[(int)(state[4] >> 56) ] ^ + C1[(int)(state[3] >> 48) & 0xff] ^ + C2[(int)(state[2] >> 40) & 0xff] ^ + C3[(int)(state[1] >> 32) & 0xff] ^ + C4[(int)(state[0] >> 24) & 0xff] ^ + C5[(int)(state[7] >> 16) & 0xff] ^ + C6[(int)(state[6] >> 8) & 0xff] ^ + C7[(int)(state[5] ) & 0xff] ^ + K[4]; + L[5] = + C0[(int)(state[5] >> 56) ] ^ + C1[(int)(state[4] >> 48) & 0xff] ^ + C2[(int)(state[3] >> 40) & 0xff] ^ + C3[(int)(state[2] >> 32) & 0xff] ^ + C4[(int)(state[1] >> 24) & 0xff] ^ + C5[(int)(state[0] >> 16) & 0xff] ^ + C6[(int)(state[7] >> 8) & 0xff] ^ + C7[(int)(state[6] ) & 0xff] ^ + K[5]; + L[6] = + C0[(int)(state[6] >> 56) ] ^ + C1[(int)(state[5] >> 48) & 0xff] ^ + C2[(int)(state[4] >> 40) & 0xff] ^ + C3[(int)(state[3] >> 32) & 0xff] ^ + C4[(int)(state[2] >> 24) & 0xff] ^ + C5[(int)(state[1] >> 16) & 0xff] ^ + C6[(int)(state[0] >> 8) & 0xff] ^ + C7[(int)(state[7] ) & 0xff] ^ + K[6]; + L[7] = + C0[(int)(state[7] >> 56) ] ^ + C1[(int)(state[6] >> 48) & 0xff] ^ + C2[(int)(state[5] >> 40) & 0xff] ^ + C3[(int)(state[4] >> 32) & 0xff] ^ + C4[(int)(state[3] >> 24) & 0xff] ^ + C5[(int)(state[2] >> 16) & 0xff] ^ + C6[(int)(state[1] >> 8) & 0xff] ^ + C7[(int)(state[0] ) & 0xff] ^ + K[7]; + state[0] = L[0]; + state[1] = L[1]; + state[2] = L[2]; + state[3] = L[3]; + state[4] = L[4]; + state[5] = L[5]; + state[6] = L[6]; + state[7] = L[7]; + } + /* + * apply the Miyaguchi-Preneel compression function: + */ + structpointer->hash[0] ^= state[0] ^ block[0]; + structpointer->hash[1] ^= state[1] ^ block[1]; + structpointer->hash[2] ^= state[2] ^ block[2]; + structpointer->hash[3] ^= state[3] ^ block[3]; + structpointer->hash[4] ^= state[4] ^ block[4]; + structpointer->hash[5] ^= state[5] ^ block[5]; + structpointer->hash[6] ^= state[6] ^ block[6]; + structpointer->hash[7] ^= state[7] ^ block[7]; +} + +/** + * Initialize the hashing state. + */ +void WHIRLPOOL_init(struct NESSIEstruct * const structpointer) { + int i; + + memset(structpointer->bitLength, 0, 32); + structpointer->bufferBits = structpointer->bufferPos = 0; + structpointer->buffer[0] = 0; /* it's only necessary to cleanup buffer[bufferPos] */ + for (i = 0; i < 8; i++) { + structpointer->hash[i] = 0L; /* initial value */ + } +} + +/** + * Delivers input data to the hashing algorithm. + * + * @param source plaintext data to hash. + * @param sourceBits how many bits of plaintext to process. + * + * This method maintains the invariant: bufferBits < DIGESTBITS + */ +void WHIRLPOOL_add(const unsigned char * const source, + uint32_t sourceBits, + struct NESSIEstruct * const structpointer) { + /* + sourcePos + | + +-------+-------+------- + ||||||||||||||||||||| source + +-------+-------+------- + +-------+-------+-------+-------+-------+------- + |||||||||||||||||||||| buffer + +-------+-------+-------+-------+-------+------- + | + bufferPos + */ + int sourcePos = 0; /* index of leftmost source u8 containing data (1 to 8 bits). */ + int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */ + int bufferRem = structpointer->bufferBits & 7; /* occupied bits on buffer[bufferPos]. */ + int i; + u32 b, carry; + u8 *buffer = structpointer->buffer; + u8 *bitLength = structpointer->bitLength; + int bufferBits = structpointer->bufferBits; + int bufferPos = structpointer->bufferPos; + + /* + * tally the length of the added data: + */ + u64 value = sourceBits; + for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != LL(0)); i--) { + carry += bitLength[i] + ((u32)value & 0xff); + bitLength[i] = (u8)carry; + carry >>= 8; + value >>= 8; + } + /* + * process data in chunks of 8 bits (a more efficient approach would be to take whole-word chunks): + */ + while (sourceBits > 8) { + /* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */ + /* + * take a byte from the source: + */ + b = ((source[sourcePos] << sourceGap) & 0xff) | + ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); + /* + * process this byte: + */ + buffer[bufferPos++] |= (u8)(b >> bufferRem); + bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ + if (bufferBits == DIGESTBITS) { + /* + * process data block: + */ + processBuffer(structpointer); + /* + * reset buffer: + */ + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = (u8) (b << (8 - bufferRem)); + bufferBits += bufferRem; + /* + * proceed to remaining data: + */ + sourceBits -= 8; + sourcePos++; + } + /* now 0 <= sourceBits <= 8; + * furthermore, all data (if any is left) is in source[sourcePos]. + */ + if (sourceBits > 0) { + b = (source[sourcePos] << sourceGap) & 0xff; /* bits are left-justified on b. */ + /* + * process the remaining bits: + */ + buffer[bufferPos] |= b >> bufferRem; + } else { + b = 0; + } + if (bufferRem + sourceBits < 8) { + /* + * all remaining data fits on buffer[bufferPos], + * and there still remains some space. + */ + bufferBits += sourceBits; + } else { + /* + * buffer[bufferPos] is full: + */ + bufferPos++; + bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ + sourceBits -= 8 - bufferRem; + /* now 0 <= sourceBits < 8; + * furthermore, all data (if any is left) is in source[sourcePos]. + */ + if (bufferBits == DIGESTBITS) { + /* + * process data block: + */ + processBuffer(structpointer); + /* + * reset buffer: + */ + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = (u8) (b << (8 - bufferRem)); + bufferBits += (int)sourceBits; + } + structpointer->bufferBits = bufferBits; + structpointer->bufferPos = bufferPos; +} + +/** + * Get the hash value from the hashing state. + * + * This method uses the invariant: bufferBits < DIGESTBITS + */ +void WHIRLPOOL_finalize(struct NESSIEstruct * const structpointer, + unsigned char * const result) { + int i; + u8 *buffer = structpointer->buffer; + u8 *bitLength = structpointer->bitLength; + int bufferBits = structpointer->bufferBits; + int bufferPos = structpointer->bufferPos; + u8 *digest = result; + + /* + * append a '1'-bit: + */ + buffer[bufferPos] |= 0x80U >> (bufferBits & 7); + bufferPos++; /* all remaining bits on the current u8 are set to zero. */ + /* + * pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits: + */ + if (bufferPos > WBLOCKBYTES - LENGTHBYTES) { + if (bufferPos < WBLOCKBYTES) { + memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos); + } + /* + * process data block: + */ + processBuffer(structpointer); + /* + * reset buffer: + */ + bufferPos = 0; + } + if (bufferPos < WBLOCKBYTES - LENGTHBYTES) { + memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos); + } + bufferPos = WBLOCKBYTES - LENGTHBYTES; + /* + * append bit length of hashed data: + */ + memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES); + /* + * process data block: + */ + processBuffer(structpointer); + /* + * return the completed message digest: + */ + for (i = 0; i < DIGESTBYTES/8; i++) { + digest[0] = (u8)(structpointer->hash[i] >> 56); + digest[1] = (u8)(structpointer->hash[i] >> 48); + digest[2] = (u8)(structpointer->hash[i] >> 40); + digest[3] = (u8)(structpointer->hash[i] >> 32); + digest[4] = (u8)(structpointer->hash[i] >> 24); + digest[5] = (u8)(structpointer->hash[i] >> 16); + digest[6] = (u8)(structpointer->hash[i] >> 8); + digest[7] = (u8)(structpointer->hash[i] ); + digest += 8; + } + structpointer->bufferBits = bufferBits; + structpointer->bufferPos = bufferPos; +} diff --git a/src/utils/crypto/whirlpool.h b/src/utils/crypto/whirlpool.h new file mode 100644 index 000000000..3a88006de --- /dev/null +++ b/src/utils/crypto/whirlpool.h @@ -0,0 +1,150 @@ +#ifndef WHIRLPOOL_H +#define WHIRLPOOL_H 1 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifndef PORTABLE_C__ +#define PORTABLE_C__ + +#include +#include + +/* Definition of minimum-width integer types + * + * u8 -> unsigned integer type, at least 8 bits, equivalent to unsigned char + * u16 -> unsigned integer type, at least 16 bits + * u32 -> unsigned integer type, at least 32 bits + * + * s8, s16, s32 -> signed counterparts of u8, u16, u32 + * + * Always use macro's T8(), T16() or T32() to obtain exact-width results, + * i.e., to specify the size of the result of each expression. + */ + +typedef int8_t s8; +typedef uint8_t u8; + +#if UINT_MAX >= 4294967295UL + +typedef int16_t s16; +typedef int32_t s32; +typedef uint16_t u16; +typedef uint32_t u32; + +#define ONE32 0xffffffffU + +#else + +typedef int16_t s16; +typedef int32_t s32; +typedef uint16_t u16; +typedef uint32_t u32; + +#define ONE32 0xffffffffUL + +#endif + +#define ONE8 0xffU +#define ONE16 0xffffU + +#define T8(x) ((x) & ONE8) +#define T16(x) ((x) & ONE16) +#define T32(x) ((x) & ONE32) + +#ifdef _MSC_VER +typedef uint64_t u64; +typedef int64_t s64; +#define LL(v) (v##i64) +#define ONE64 LL(0xffffffffffffffff) +#else /* !_MSC_VER */ +typedef uint64_t u64; +typedef int64_t s64; +#define LL(v) (v##ULL) +#define ONE64 LL(0xffffffffffffffff) +#endif /* ?_MSC_VER */ +#define T64(x) ((x) & ONE64) +#define ROTR64(v, n) (((v) >> (n)) | T64((v) << (64 - (n)))) +/* + * Note: the test is used to detect native 64-bit architectures; + * if the unsigned long is strictly greater than 32-bit, it is + * assumed to be at least 64-bit. This will not work correctly + * on (old) 36-bit architectures (PDP-11 for instance). + * + * On non-64-bit architectures, "long long" is used. + */ + +/* + * U8TO32_BIG(c) returns the 32-bit value stored in big-endian convention + * in the unsigned char array pointed to by c. + */ +#define U8TO32_BIG(c) (((u32)T8(*(c)) << 24) | ((u32)T8(*((c) + 1)) << 16) | ((u32)T8(*((c) + 2)) << 8) | ((u32)T8(*((c) + 3)))) + +/* + * U8TO32_LITTLE(c) returns the 32-bit value stored in little-endian convention + * in the unsigned char array pointed to by c. + */ +#define U8TO32_LITTLE(c) (((u32)T8(*(c))) | ((u32)T8(*((c) + 1)) << 8) | (u32)T8(*((c) + 2)) << 16) | ((u32)T8(*((c) + 3)) << 24)) + +/* + * U8TO32_BIG(c, v) stores the 32-bit-value v in big-endian convention + * into the unsigned char array pointed to by c. + */ +#define U32TO8_BIG(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x >> 24); d[1] = T8(x >> 16); d[2] = T8(x >> 8); d[3] = T8(x); } while (0) + +/* + * U8TO32_LITTLE(c, v) stores the 32-bit-value v in little-endian convention + * into the unsigned char array pointed to by c. + */ +#define U32TO8_LITTLE(c, v) do { u32 x = (v); u8 *d = (c); d[0] = T8(x); d[1] = T8(x >> 8); d[2] = T8(x >> 16); d[3] = T8(x >> 24); } while (0) + +/* + * ROTL32(v, n) returns the value of the 32-bit unsigned value v after + * a rotation of n bits to the left. It might be replaced by the appropriate + * architecture-specific macro. + * + * It evaluates v and n twice. + * + * The compiler might emit a warning if n is the constant 0. The result + * is undefined if n is greater than 31. + */ +#define ROTL32(v, n) (T32((v) << (n)) | ((v) >> (32 - (n)))) + +/* + * Whirlpool-specific definitions. + */ + +#define DIGESTBYTES 64 +#define DIGESTBITS (8*DIGESTBYTES) /* 512 */ + +#define WBLOCKBYTES 64 +#define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */ + +#define LENGTHBYTES 32 +#define LENGTHBITS (8*LENGTHBYTES) /* 256 */ + +typedef struct NESSIEstruct { + u8 bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit counter) */ + u8 buffer[WBLOCKBYTES]; /* buffer of data to hash */ + int bufferBits; /* current number of bits on the buffer */ + int bufferPos; /* current (possibly incomplete) byte slot on the buffer */ + u64 hash[DIGESTBYTES/8]; /* the hashing state */ +} NESSIEstruct; + +#endif /* PORTABLE_C__ */ + +// ------------- + +typedef NESSIEstruct WHIRLPOOL_CTX; + +void WHIRLPOOL_add(const uint8_t * const source, uint32_t sourceBits, struct NESSIEstruct * const structpointer); +void WHIRLPOOL_finalize(struct NESSIEstruct * const structpointer, uint8_t * const result); +void WHIRLPOOL_init(struct NESSIEstruct * const structpointer); + +#if defined(__cplusplus) +} +#endif + +#endif /* WHIRLPOOL_H */ diff --git a/src/utils/decode.c b/src/utils/decode.c new file mode 100644 index 000000000..8221428ba --- /dev/null +++ b/src/utils/decode.c @@ -0,0 +1,462 @@ +#include "mds.h" +#include "edc.h" + + +#include "common/tcdefs.h" +#include "common/crypto.h" +#include "common/endian.h" +#include "common/pkcs5.h" +#include "common/crc.h" + +#include + + + +void unshuffle1(u8 *data) +{ + u32 val = getEDC(data, 0x40) ^ 0x567372ff; + for(int i = 0; i < 0x40; i += 4) + { + val = (val * 0x35e85a6d) + 0x1548dce9; + u32 ud = getU32(data + i); + setU32(data + i, ud ^ val ^ 0xec564717); + + if (data[i] == 0) + data[i] = 0x5f; + if (data[i+1] == 0) + data[i+1] = 0x5f; + if (data[i+2] == 0) + data[i+2] = 0x5f; + if (data[i+3] == 0) + data[i+3] = 0x5f; + } +} + +void DecryptBlock(u8 *buf, + TC_LARGEST_COMPILER_UINT len, + u32 secSz, + u64 secN, + u8 flags, + PCRYPTO_INFO cryptoInfo) +{ + const int blockSize = CipherGetBlockSize( EAGetFirstCipher(cryptoInfo->ea) ); + + u64 blk = 0x200; + if (blockSize <= secSz) + blk = secSz; + + const u64 asz = blk - (blk % blockSize); + if ((flags & 4) == 0) + { + const u32 c = len / blk; + for (int i = 0; i < c; i++) + { + DecryptBuffer(buf + i * blk, asz, asz, secN + i, flags, cryptoInfo); + } + } + else + { + u32 adsz = len - (len % blockSize); + u64 pos = 0; + int i = 0; + while(adsz > 0) + { + u32 bsz = asz; + if (adsz <= asz) + bsz = adsz; + + DecryptBuffer(buf + pos, bsz, adsz, secN + i, flags, cryptoInfo); + + pos += bsz; + adsz -= bsz; + i++; + } + } +} + + + +// From volumes.c + modifies + +#define HEADER_OFFSET_CRC 64 +#define HEADER_OFFSET_MAGIC 68 +#define HEADER_OFFSET_DATA 80 +#define HEADER_DATA_SIZE 0x100 +#define HEADER_OFFSET_DATASZ 74 + + +uint16 GetHeaderField16 (byte *header, size_t offset) +{ + /* modify BE->LE */ + return LE16 (*(uint16 *) (header + offset)); +} + + +uint32 GetHeaderField32 (byte *header, size_t offset) +{ + /* modify BE->LE */ + return LE32 (*(uint32 *) (header + offset)); +} + + +UINT64_STRUCT GetHeaderField64 (byte *header, size_t offset) +{ + /* modify BE->LE */ + UINT64_STRUCT uint64Struct; + +#ifndef TC_NO_COMPILER_INT64 + uint64Struct.Value = LE64 (*(uint64 *) (header + offset)); +#else + uint64Struct.HighPart = LE32 (*(uint32 *) (header + offset)); + uint64Struct.LowPart = LE32 (*(uint32 *) (header + offset + 4)); +#endif + return uint64Struct; +} + + +int ReadHeader (int bBoot, char *encryptedHeader, Password *password, PCRYPTO_INFO *retInfo, CRYPTO_INFO *retHeaderCryptoInfo) +{ + char header[HEADER_SIZE]; + KEY_INFO keyInfo; + PCRYPTO_INFO cryptoInfo; + char dk[MASTER_KEYDATA_SIZE]; + int pkcs5_prf; + int status; + int primaryKeyOffset; + + + if (retHeaderCryptoInfo != NULL) + { + cryptoInfo = retHeaderCryptoInfo; + } + else + { + cryptoInfo = *retInfo = crypto_open (); + if (cryptoInfo == NULL) + return ERR_OUTOFMEMORY; + } + + crypto_loadkey (&keyInfo, (char *) password->Text, (int) password->Length); + + // PKCS5 is used to derive the primary header key(s) and secondary header key(s) (XTS mode) from the password + memcpy (keyInfo.salt, encryptedHeader + HEADER_SALT_OFFSET, PKCS5_SALT_SIZE); + + memset(dk, 0, sizeof(dk)); + + // Use this legacy incorrect(for XTS) size, because Daemon Tools use it in this way + // seems DTools manual upgrade their pre-TrueCrypt5.0 sources + int keysize = EAGetLargestKey() + LEGACY_VOL_IV_SIZE; + + // Test only rp160/sha1/whirlpool only + for (pkcs5_prf = FIRST_PRF_ID; pkcs5_prf <= WHIRLPOOL; pkcs5_prf++) + { + int lrw64InitDone = 0; // Deprecated/legacy + int lrw128InitDone = 0; // Deprecated/legacy + + keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, bBoot); + + switch (pkcs5_prf) + { + case RIPEMD160: + derive_key_ripemd160 ((char *) keyInfo.userKey, keyInfo.keyLength, (char *) keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, keysize); + break; + + case SHA1: + // Deprecated/legacy + derive_key_sha1 ((char *) keyInfo.userKey, keyInfo.keyLength, (char *) keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, keysize); + break; + + case WHIRLPOOL: + derive_key_whirlpool ((char *) keyInfo.userKey, keyInfo.keyLength, (char *) keyInfo.salt, + PKCS5_SALT_SIZE, keyInfo.noIterations, dk, keysize); + break; + + default: + // Unknown/wrong ID + TC_THROW_FATAL_EXCEPTION; + } + + // Test all available modes of operation + for (cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID; + cryptoInfo->mode <= LAST_MODE_OF_OPERATION; + cryptoInfo->mode++) + { + switch (cryptoInfo->mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // For LRW (deprecated/legacy), copy the tweak key + // For CBC (deprecated/legacy), copy the IV/whitening seed + memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE); + primaryKeyOffset = LEGACY_VOL_IV_SIZE; + break; + + default: + primaryKeyOffset = 0; + } + + // Test all available encryption algorithms + for (cryptoInfo->ea = EAGetFirst (); + cryptoInfo->ea != 0; + cryptoInfo->ea = EAGetNext (cryptoInfo->ea)) + { + int blockSize; + + if (!EAIsModeSupported (cryptoInfo->ea, cryptoInfo->mode)) + continue; // This encryption algorithm has never been available with this mode of operation + + blockSize = CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea)); + + status = EAInit (cryptoInfo->ea, (unsigned char *) (dk + primaryKeyOffset), cryptoInfo->ks); + if (status == ERR_CIPHER_INIT_FAILURE) + goto err; + + // Init objects related to the mode of operation + + if (cryptoInfo->mode == XTS) + { + // Copy the secondary key (if cascade, multiple concatenated) + memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); + + // Secondary key schedule + if (!EAInitMode (cryptoInfo)) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + } + else if (cryptoInfo->mode == LRW + && ((blockSize == 8 && !lrw64InitDone) || (blockSize == 16 && !lrw128InitDone))) + { + // Deprecated/legacy + + if (!EAInitMode (cryptoInfo)) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + + if (blockSize == 8) + lrw64InitDone = 1; + else if (blockSize == 16) + lrw128InitDone = 1; + } + + // Copy the header for decryption + memcpy (header, encryptedHeader, HEADER_SIZE); + + // Try to decrypt header + DecryptBlock((unsigned char *) (header + HEADER_ENCRYPTED_DATA_OFFSET), HEADER_ENCRYPTED_DATA_SIZE, HEADER_SIZE, 0, 4, cryptoInfo); + + // Magic 'TRUE' + if (GetHeaderField32 ((unsigned char *) header, HEADER_OFFSET_MAGIC) != 0x54525545) + continue; + + uint32_t crc = GetHeaderField32 ((unsigned char *) header, HEADER_OFFSET_CRC); + if (crc != GetCrc32 ((unsigned char *) ((unsigned char *) (header + HEADER_OFFSET_DATA)), HEADER_DATA_SIZE) ) + continue; + + if ( GetHeaderField16((unsigned char *) header, HEADER_OFFSET_DATASZ) > 0x100 ) + continue; + + + memcpy(dk, header + HEADER_OFFSET_DATA, HEADER_DATA_SIZE); + + memcpy(encryptedHeader, header, 0x200); + + switch (cryptoInfo->mode) + { + case LRW: + case CBC: + case INNER_CBC: + case OUTER_CBC: + + // For LRW (deprecated/legacy), copy the tweak key + // For CBC (deprecated/legacy), copy the IV/whitening seed + memcpy (cryptoInfo->k2, dk, LEGACY_VOL_IV_SIZE); + primaryKeyOffset = LEGACY_VOL_IV_SIZE; + break; + + default: + primaryKeyOffset = 0; + } + + if (EAInit (cryptoInfo->ea, (unsigned char *) (dk + primaryKeyOffset), cryptoInfo->ks) != 0 ) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + + if (cryptoInfo->mode == XTS) + memcpy (cryptoInfo->k2, dk + EAGetKeySize (cryptoInfo->ea), EAGetKeySize (cryptoInfo->ea)); + + if (!EAInitMode (cryptoInfo)) + { + status = ERR_MODE_INIT_FAILED; + goto err; + } + + // Clear out the temporary key buffers +// ret: + burn (dk, sizeof(dk)); + burn (&keyInfo, sizeof (keyInfo)); + + return 0; + } + } + } + status = ERR_PASSWORD_WRONG; + +err: + if (cryptoInfo != retHeaderCryptoInfo) + { + crypto_close(cryptoInfo); + *retInfo = NULL; + } + + burn (&keyInfo, sizeof (keyInfo)); + burn (dk, sizeof(dk)); + return status; +} + + + +int decode1(u8 *data, const char *pass, PCRYPTO_INFO *ci) +{ + u32 passlen = 0; + u8 unsh[0x101]; + memset(unsh, 0, 0x101); + if (!pass) + { + memcpy(unsh, data, 0x40); + unshuffle1(unsh); + passlen = 0x40; + } + else + { + passlen = strlen(pass); + if (passlen > 0x40) + passlen = 0x40; + memcpy(unsh, pass, passlen); + } + + Password pwd; + pwd.Length = passlen; + memcpy(pwd.Text, unsh, passlen); + + return ReadHeader(0, (char *) data, &pwd, ci, NULL); +} + + + +void decryptMode2(Decoder *ctx, u8 *buffer, u32 length, u64 blockIndex) +{ + u8 *p = buffer; + u8 i[8]; + u8 t[16]; + u64 b; + + *(u64 *)i = BE64(blockIndex); + + for (b = 0; b < length >> 4; b++) + { + Gf128MulBy64Tab (i, t, &ctx->gf_ctx); + Xor128 ((u64 *)p, (u64 *)t); + + aes_decrypt (p, p, &ctx->decr); + + Xor128 ((u64 *)p, (u64 *)t); + + p += 16; + + if (i[7] != 0xff) + i[7]++; + else + *(u64 *)i = BE64 ( BE64(*(u64 *)i) + 1 ); + } +} + + +void MdxDecryptBufferCBC (Decoder *ctx, u32 *data, unsigned int len, u32 *iv, u32 *whitening) +{ + u32 bufIV[4]; + u64 i; + u32 ct[4]; + + // IV + bufIV[0] = iv[0]; + bufIV[1] = iv[1]; + bufIV[2] = iv[2]; + bufIV[3] = iv[3]; + + // Decrypt each block + for (i = 0; i < len/16; i++) + { + // Dewhitening + if (whitening) + { + data[0] ^= whitening[0]; + data[1] ^= whitening[1]; + data[2] ^= whitening[0]; + data[3] ^= whitening[1]; + + //CBC + ct[0] = data[0]; + ct[1] = data[1]; + ct[2] = data[2]; + ct[3] = data[3]; + } + + aes_decrypt((u8 *)data, (u8 *)data, &ctx->decr); + + // CBC + data[0] ^= bufIV[0]; + data[1] ^= bufIV[1]; + data[2] ^= bufIV[2]; + data[3] ^= bufIV[3]; + + if (whitening) + { + bufIV[0] = ct[0]; + bufIV[1] = ct[1]; + bufIV[2] = ct[2]; + bufIV[3] = ct[3]; + } + + data += 4; + } +} + +void decryptMdxData(Decoder *ctx, u8 *buffer, u32 length, u64 blockSize, u64 blockIndex) +{ + if (ctx->mode == 1) + { + if (ctx->ctr) + { + u32 sectorIV[4]; + u32 secWhitening[4]; + InitSectorIVAndWhitening (blockIndex, 16, sectorIV, (u64 *)(ctx->dg + 16), secWhitening); + MdxDecryptBufferCBC (ctx, (u32 *)buffer, length, sectorIV, secWhitening); + } + else + { + MdxDecryptBufferCBC (ctx, (u32 *)buffer, length, (u32 *)ctx->dg, (u32 *)(ctx->dg + 8)); + } + } + else if (ctx->mode == 2) + { + if (ctx->ctr) + decryptMode2(ctx, buffer, length, 1 + (blockSize / 16) * blockIndex); + else + decryptMode2(ctx, buffer, length, 1); + } + else + { + MdxDecryptBufferCBC (ctx, (u32 *)buffer, length, (u32 *)ctx->dg, NULL); + } +} diff --git a/src/utils/defines.h b/src/utils/defines.h new file mode 100644 index 000000000..fb8f5c79c --- /dev/null +++ b/src/utils/defines.h @@ -0,0 +1,13 @@ +#ifndef DEFINES_H +#define DEFINES_H + +#include + +typedef uint64_t u64; +typedef int64_t s64; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint8_t u8; +typedef int BOOL; + +#endif diff --git a/src/utils/edc.c b/src/utils/edc.c new file mode 100644 index 000000000..c21ef9e22 --- /dev/null +++ b/src/utils/edc.c @@ -0,0 +1,78 @@ +#include "defines.h" + +u32 EDC_crctable[256] = { + 0x0, 0x90910101, 0x91210201, 0x1B00300, +0x92410401, 0x2D00500, 0x3600600, 0x93F10701, +0x94810801, 0x4100900, 0x5A00A00, 0x95310B01, +0x6C00C00, 0x96510D01, 0x97E10E01, 0x7700F00, +0x99011001, 0x9901100, 0x8201200, 0x98B11301, +0xB401400, 0x9BD11501, 0x9A611601, 0xAF01700, +0xD801800, 0x9D111901, 0x9CA11A01, 0xC301B00, +0x9FC11C01, 0xF501D00, 0xEE01E00, 0x9E711F01, +0x82012001, 0x12902100, 0x13202200, 0x83B12301, +0x10402400, 0x80D12501, 0x81612601, 0x11F02700, +0x16802800, 0x86112901, 0x87A12A01, 0x17302B00, +0x84C12C01, 0x14502D00, 0x15E02E00, 0x85712F01, +0x1B003000, 0x8B913101, 0x8A213201, 0x1AB03300, +0x89413401, 0x19D03500, 0x18603600, 0x88F13701, +0x8F813801, 0x1F103900, 0x1EA03A00, 0x8E313B01, +0x1DC03C00, 0x8D513D01, 0x8CE13E01, 0x1C703F00, +0xB4014001, 0x24904100, 0x25204200, 0xB5B14301, +0x26404400, 0xB6D14501, 0xB7614601, 0x27F04700, +0x20804800, 0xB0114901, 0xB1A14A01, 0x21304B00, +0xB2C14C01, 0x22504D00, 0x23E04E00, 0xB3714F01, +0x2D005000, 0xBD915101, 0xBC215201, 0x2CB05300, +0xBF415401, 0x2FD05500, 0x2E605600, 0xBEF15701, +0xB9815801, 0x29105900, 0x28A05A00, 0xB8315B01, +0x2BC05C00, 0xBB515D01, 0xBAE15E01, 0x2A705F00, +0x36006000, 0xA6916101, 0xA7216201, 0x37B06300, +0xA4416401, 0x34D06500, 0x35606600, 0xA5F16701, +0xA2816801, 0x32106900, 0x33A06A00, 0xA3316B01, +0x30C06C00, 0xA0516D01, 0xA1E16E01, 0x31706F00, +0xAF017001, 0x3F907100, 0x3E207200, 0xAEB17301, +0x3D407400, 0xADD17501, 0xAC617601, 0x3CF07700, +0x3B807800, 0xAB117901, 0xAAA17A01, 0x3A307B00, +0xA9C17C01, 0x39507D00, 0x38E07E00, 0xA8717F01, +0xD8018001, 0x48908100, 0x49208200, 0xD9B18301, +0x4A408400, 0xDAD18501, 0xDB618601, 0x4BF08700, +0x4C808800, 0xDC118901, 0xDDA18A01, 0x4D308B00, +0xDEC18C01, 0x4E508D00, 0x4FE08E00, 0xDF718F01, +0x41009000, 0xD1919101, 0xD0219201, 0x40B09300, +0xD3419401, 0x43D09500, 0x42609600, 0xD2F19701, +0xD5819801, 0x45109900, 0x44A09A00, 0xD4319B01, +0x47C09C00, 0xD7519D01, 0xD6E19E01, 0x46709F00, +0x5A00A000, 0xCA91A101, 0xCB21A201, 0x5BB0A300, +0xC841A401, 0x58D0A500, 0x5960A600, 0xC9F1A701, +0xCE81A801, 0x5E10A900, 0x5FA0AA00, 0xCF31AB01, +0x5CC0AC00, 0xCC51AD01, 0xCDE1AE01, 0x5D70AF00, +0xC301B001, 0x5390B100, 0x5220B200, 0xC2B1B301, +0x5140B400, 0xC1D1B501, 0xC061B601, 0x50F0B700, +0x5780B800, 0xC711B901, 0xC6A1BA01, 0x5630BB00, +0xC5C1BC01, 0x5550BD00, 0x54E0BE00, 0xC471BF01, +0x6C00C000, 0xFC91C101, 0xFD21C201, 0x6DB0C300, +0xFE41C401, 0x6ED0C500, 0x6F60C600, 0xFFF1C701, +0xF881C801, 0x6810C900, 0x69A0CA00, 0xF931CB01, +0x6AC0CC00, 0xFA51CD01, 0xFBE1CE01, 0x6B70CF00, +0xF501D001, 0x6590D100, 0x6420D200, 0xF4B1D301, +0x6740D400, 0xF7D1D501, 0xF661D601, 0x66F0D700, +0x6180D800, 0xF111D901, 0xF0A1DA01, 0x6030DB00, +0xF3C1DC01, 0x6350DD00, 0x62E0DE00, 0xF271DF01, +0xEE01E001, 0x7E90E100, 0x7F20E200, 0xEFB1E301, +0x7C40E400, 0xECD1E501, 0xED61E601, 0x7DF0E700, +0x7A80E800, 0xEA11E901, 0xEBA1EA01, 0x7B30EB00, +0xE8C1EC01, 0x7850ED00, 0x79E0EE00, 0xE971EF01, +0x7700F000, 0xE791F101, 0xE621F201, 0x76B0F300, +0xE541F401, 0x75D0F500, 0x7460F600, 0xE4F1F701, +0xE381F801, 0x7310F900, 0x72A0FA00, 0xE231FB01, +0x71C0FC00, 0xE151FD01, 0xE0E1FE01, 0x7070FF00 }; + + +u32 getEDC(void *data, u32 num) +{ + u8 *d = (u8 *)data; + u32 result = 0; + for(u32 i = 0; i < num; i++) { + result = EDC_crctable[ (result ^ d[i]) & 0xff ] ^ (result >> 8); + } + return result; +} diff --git a/src/utils/edc.h b/src/utils/edc.h new file mode 100644 index 000000000..dd6639bc8 --- /dev/null +++ b/src/utils/edc.h @@ -0,0 +1,8 @@ +#ifndef EDC_H +#define EDC_H + +#include "defines.h" + +u32 getEDC(void *data, u32 num); + +#endif diff --git a/src/utils/mds.h b/src/utils/mds.h new file mode 100644 index 000000000..d080b0e42 --- /dev/null +++ b/src/utils/mds.h @@ -0,0 +1,188 @@ +#ifndef MDS_H +#define MDS_H + +#include +#include +#include + +#include "defines.h" +#include "common/crypto.h" + +typedef struct Decoder_t +{ + u8 dg[32]; + GfCtx gf_ctx; + aes_encrypt_ctx encr; + aes_decrypt_ctx decr; + u8 bsize; + + int mode; + int ctr; +} Decoder; + + + +enum TRACK_TYPE +{ + TRK_T_MAINTENANCE = 0, + TRK_T_AUDIO = 1, + TRK_T_MODE1 = 2, + TRK_T_MODE2 = 3, + TRK_T_MODE2_FORM1 = 4, + TRK_T_MODE2_FORM2 = 5 +}; + +enum TRACK_FLAG +{ + TRK_F_TYPE_MASK = 7, + TRK_F_EDC = 8, + TRK_F_10 = 0x10, + TRK_F_HEADER = 0x20, + TRK_F_SUBHEADER = 0x40, + TRK_F_SYNC = 0x80 +}; + + +typedef struct __attribute__((packed)) +{ + u32 f0; + u32 f1; + u64 f3; //or two u32? +} UNK4; + +typedef struct __attribute__((packed)) +{ + char signature[16]; + u8 major; // 0x10 + u8 minor; + u16 medium_type; // 0x12 + u16 num_sessions; // 0x14 + u16 _unk1_; + u16 _unk2_size_; // 0x18 + u16 bca_len; + u16 _unk3_size_; // 0x1c + u16 _unk4_size_; // 0x1e + u32 _unk2_offset_; // 0x20 + u32 bca_data_offset; // 0x24 + u32 _unk3_offset_; // 0x28 + u32 _unk4_offset_; // 0x2c 0x10 byte elements UNK4 + u8 _unk5_; // 0x30 + u32 _unk6_; // 0x31 + u8 _unk7_; // 0x35 + u64 _unk8_; // 0x36 + u16 _unk9_; // 0x3e + u32 disc_structures_offset; // 0x40 + u32 _unk10_offset_; // 0x44 + u16 _unk10_size_; // 0x48 + u8 _dummy1_[6]; // 0x4a not used by DT + u32 sessions_blocks_offset; // 0x50 + u32 dpm_blocks_offset; // 0x54 + u32 encryption_block_offset; // 0x58 + u8 _dummy2_[4]; // 0x5c +} MDX_Header; // 0x60 + +typedef struct __attribute__((packed)) +{ + u64 session_start; + u16 session_number; // 0x8 + u8 num_all_blocks; // 0xa + u8 num_nontrack_blocks; // 0xb + u16 first_track; // 0xc + u16 last_track; // 0xe + u32 _dummy_; // 0x10 + u32 tracks_blocks_offset; // 0x14 + u64 session_end; // 0x18 +} MDX_SessionBlock; // 0x20 + +typedef struct __attribute__((packed)) +{ + u8 mode; + u8 subchannel; + u8 adr_ctl; + u8 tno; + u8 point; // 4 + u8 min; + u8 sec; + u8 frame; + u8 zero; // 8 + u8 pmin; + u8 psec; + u8 pframe; + u32 extra_offset; // 0xc + u16 file_block_size; // 0x10 original name. represent full size of data and additional data per sector + u8 _unk1_; // 0x12 + u8 _dummy1_[5]; // 0x13 + u32 _unk2_; // 0x18; + u32 _unk3_; // 0x1c; + u32 _unk4_; // 0x20; + u32 start_sector; // 0x24 + u64 start_offset; // 0x28 + u32 footer_count; // 0x30 + u32 footer_offset; // 0x34 + u64 start_sector64; // 0x38 major >= 2 + u64 track_size64; // 0x40 major >= 2 + u8 _dummy2_[8]; // 0x48 +} MDX_TrackBlock; // 0x50 + +typedef struct __attribute__((packed)) +{ + u32 filename_offset; + u8 flags; // 4 + u8 _dummy1_; // 5 + u16 _unk1_size_; // 6 + u32 _unk2_size_; // 8 + u32 blocks_in_compression_group; // c major >= 2 + u64 track_data_length; // 10 major >= 2 + u64 compress_table_offset; // 18 +} MDX_Footer; // 0x20 + + + + +// decode.c +void DecryptBlock(u8 *buf, TC_LARGEST_COMPILER_UINT len, u32 secSz, u64 secN, u8 flags, PCRYPTO_INFO cryptoInfo); + +int decode1(u8 *data, const char *pass, PCRYPTO_INFO *ci); + +void decryptMdxData(Decoder *ctx, u8 *buffer, u32 length, u64 blockSize, u64 blockIndex); + + +// utils.c +inline static u64 getU64(const void *mem) +{ + const u8 *mem8 = (const u8 *)mem; + return ((u64)mem8[0] | ((u64)mem8[1] << 8) | ((u64)mem8[2] << 16) | ((u64)mem8[3] << 24) | ((u64)mem8[4] << 32) | ((u64)mem8[5] << 40) | ((u64)mem8[6] << 48) | ((u64)mem8[7] << 56)); +} + +inline static u32 getU32(const void *mem) +{ + const u8 *mem8 = (const u8 *)mem; + return ((u32)mem8[0] | ((u32)mem8[1] << 8) | ((u32)mem8[2] << 16) | ((u32)mem8[3] << 24)); +} + +inline static u16 getU16(const void *mem) +{ + const u8 *mem8 = (const u8 *)mem; + return ((u16)mem8[0] | ((u16)mem8[1] << 8)); +} + +inline static u8 getU8(const void *mem) +{ + const u8 *mem8 = (const u8 *)mem; + return (u8)mem8[0]; +} + +inline static void setU32(void *mem, u32 val) +{ + u8 *mem8 = (u8 *)mem; + mem8[0] = val & 0xff; + mem8[1] = (val >> 8) & 0xff; + mem8[2] = (val >> 16) & 0xff; + mem8[3] = (val >> 24) & 0xff; +} + +u32 freadU32(FILE *f); +u64 freadU64(FILE *f); +void printHex(void *data, int num); + +#endif diff --git a/src/utils/utils.c b/src/utils/utils.c new file mode 100644 index 000000000..e2bc66473 --- /dev/null +++ b/src/utils/utils.c @@ -0,0 +1,27 @@ +#include "mds.h" + +u32 freadU32(FILE *f) +{ + u8 val[4] = {0, 0, 0, 0}; + fread(val, 4, 1, f); + return getU32(val); +} + +u64 freadU64(FILE *f) +{ + u8 val[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + fread(val, 8, 1, f); + return getU64(val); +} + +void printHex(void *data, int num) +{ + u8 *m = (u8 *)data; + while(num > 0) + { + printf("%02x", *m); + m++; + num--; + } + printf("\n"); +}