mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
MDS v2 structures and decode/crypto utilities from Marisa-Chan's repository in preparation for MDS v2/MDX support implementation.
This commit is contained in:
133
src/utils/common/crc.c
Normal file
133
src/utils/common/crc.c
Normal file
@@ -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
|
||||
37
src/utils/common/crc.h
Normal file
37
src/utils/common/crc.h
Normal file
@@ -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 <inttypes.h>
|
||||
|
||||
#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
|
||||
1653
src/utils/common/crypto.c
Normal file
1653
src/utils/common/crypto.c
Normal file
File diff suppressed because it is too large
Load Diff
304
src/utils/common/crypto.h
Normal file
304
src/utils/common/crypto.h
Normal file
@@ -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 <inttypes.h>
|
||||
#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 */
|
||||
57
src/utils/common/endian.c
Normal file
57
src/utils/common/endian.c
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
138
src/utils/common/endian.h
Normal file
138
src/utils/common/endian.h
Normal file
@@ -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 <inttypes.h>
|
||||
|
||||
#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 <machine/endian.h>
|
||||
# elif defined (TC_BSD)
|
||||
# include <sys/endian.h>
|
||||
# else
|
||||
# include <endian.h>
|
||||
# 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 */
|
||||
893
src/utils/common/gfmul.c
Normal file
893
src/utils/common/gfmul.c
Normal file
@@ -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 <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#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
|
||||
78
src/utils/common/gfmul.h
Normal file
78
src/utils/common/gfmul.h
Normal file
@@ -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 <inttypes.h>
|
||||
|
||||
#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
|
||||
39
src/utils/common/password.h
Normal file
39
src/utils/common/password.h
Normal file
@@ -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 <inttypes.h>
|
||||
|
||||
// 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
|
||||
631
src/utils/common/pkcs5.c
Normal file
631
src/utils/common/pkcs5.c
Normal file
@@ -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 <memory.h>
|
||||
#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<keylen; i++)
|
||||
{
|
||||
k_ipad[i] ^= key[i];
|
||||
k_opad[i] ^= key[i];
|
||||
}
|
||||
|
||||
/* perform inner RIPEMD-160 */
|
||||
|
||||
RMD160Init(&context); /* init context for 1st pass */
|
||||
RMD160Update(&context, k_ipad, RIPEMD160_BLOCKSIZE); /* start with inner pad */
|
||||
RMD160Update(&context, (uint8_t *) input, len); /* then text of datagram */
|
||||
RMD160Final((uint8_t *) digest, &context); /* finish up 1st pass */
|
||||
|
||||
/* perform outer RIPEMD-160 */
|
||||
RMD160Init(&context); /* init context for 2nd pass */
|
||||
RMD160Update(&context, k_opad, RIPEMD160_BLOCKSIZE); /* start with outer pad */
|
||||
/* results of 1st hash */
|
||||
RMD160Update(&context, (uint8_t *) digest, RIPEMD160_DIGESTSIZE);
|
||||
RMD160Final((uint8_t *) digest, &context); /* finish up 2nd pass */
|
||||
|
||||
/* Prevent possible leaks. */
|
||||
burn (k_ipad, sizeof(k_ipad));
|
||||
burn (k_opad, sizeof(k_opad));
|
||||
burn (tk, sizeof(tk));
|
||||
burn (&context, sizeof(context));
|
||||
}
|
||||
|
||||
void derive_u_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b)
|
||||
{
|
||||
char j[RIPEMD160_DIGESTSIZE], k[RIPEMD160_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_ripemd160 (pwd, pwd_len, init, salt_len + 4, j);
|
||||
memcpy (u, j, RIPEMD160_DIGESTSIZE);
|
||||
|
||||
/* remaining iterations */
|
||||
for (c = 1; c < iterations; c++)
|
||||
{
|
||||
hmac_ripemd160 (pwd, pwd_len, j, RIPEMD160_DIGESTSIZE, k);
|
||||
for (i = 0; i < RIPEMD160_DIGESTSIZE; i++)
|
||||
{
|
||||
u[i] ^= k[i];
|
||||
j[i] = k[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent possible leaks. */
|
||||
burn (j, sizeof(j));
|
||||
burn (k, sizeof(k));
|
||||
}
|
||||
|
||||
void derive_key_ripemd160 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen)
|
||||
{
|
||||
char u[RIPEMD160_DIGESTSIZE];
|
||||
int b, l, r;
|
||||
|
||||
if (dklen % RIPEMD160_DIGESTSIZE)
|
||||
{
|
||||
l = 1 + dklen / RIPEMD160_DIGESTSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = dklen / RIPEMD160_DIGESTSIZE;
|
||||
}
|
||||
|
||||
r = dklen - (l - 1) * RIPEMD160_DIGESTSIZE;
|
||||
|
||||
/* first l - 1 blocks */
|
||||
for (b = 1; b < l; b++)
|
||||
{
|
||||
derive_u_ripemd160 (pwd, pwd_len, salt, salt_len, iterations, u, b);
|
||||
memcpy (dk, u, RIPEMD160_DIGESTSIZE);
|
||||
dk += RIPEMD160_DIGESTSIZE;
|
||||
}
|
||||
|
||||
/* last block */
|
||||
derive_u_ripemd160 (pwd, pwd_len, salt, salt_len, iterations, u, b);
|
||||
memcpy (dk, u, r);
|
||||
|
||||
|
||||
/* Prevent possible leaks. */
|
||||
burn (u, sizeof(u));
|
||||
}
|
||||
|
||||
void hmac_whirlpool
|
||||
(
|
||||
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
|
||||
)
|
||||
{
|
||||
WHIRLPOOL_CTX ictx, octx;
|
||||
char iwhi[WHIRLPOOL_DIGESTSIZE], owhi[WHIRLPOOL_DIGESTSIZE];
|
||||
char key[WHIRLPOOL_DIGESTSIZE];
|
||||
char buf[WHIRLPOOL_BLOCKSIZE];
|
||||
int i;
|
||||
|
||||
/* If the key is longer than the hash algorithm block size,
|
||||
let key = whirlpool(key), as per HMAC specifications. */
|
||||
if (lk > 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;
|
||||
}
|
||||
41
src/utils/common/pkcs5.h
Normal file
41
src/utils/common/pkcs5.h
Normal file
@@ -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
|
||||
167
src/utils/common/tcdefs.h
Normal file
167
src/utils/common/tcdefs.h
Normal file
@@ -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 <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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
|
||||
627
src/utils/common/xts.c
Normal file
627
src/utils/common/xts.c
Normal file
@@ -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
|
||||
79
src/utils/common/xts.h
Normal file
79
src/utils/common/xts.h
Normal file
@@ -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 <inttypes.h>
|
||||
|
||||
#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
|
||||
Reference in New Issue
Block a user