📄 crypto.c
字号:
/* The source code contained in this file has been derived from the source code
of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and
additions to that source code contained in this file are Copyright (c) 2004-2005
TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation
release. Please see the file license.txt for full license details. */
#include "TCdefs.h"
#include "crypto.h"
#include "random.h"
#include "crc.h"
/* Update the following when adding a new cipher or EA:
Crypto.h:
ID #define
MAX_EXPANDED_KEY #define
Crypto.c:
Ciphers[]
EncryptionAlgorithms[]
CipherInit()
EncipherBlock()
DecipherBlock()
*/
// Cipher configuration
static Cipher Ciphers[] =
{
// ID Name Block size Key size Key schedule size
{ AES, "AES", 16, 32, sizeof(aes_encrypt_ctx)+sizeof(aes_decrypt_ctx) },
{ BLOWFISH, "Blowfish", 8, 56, 4168 },
{ CAST, "CAST5", 8, 16, 128 },
{ DES56, "DES", 8, 7, 128 },
{ SERPENT, "Serpent", 16, 32, 140*4 },
{ TRIPLEDES,"Triple DES", 8, 7*3, 128*3 },
{ TWOFISH, "Twofish", 16, 32, TWOFISH_KS },
{ 0, 0, 0, 0, 0 }
};
// Encryption algorithm configuration
static EncryptionAlgorithm EncryptionAlgorithms[] =
{
// Cipher(s) Mode
{ { 0, 0 } , 0 }, // (must be null)
{ { AES, 0 } , CBC }, // AES
{ { BLOWFISH, 0 } , CBC }, // Blowfish
{ { CAST, 0 } , CBC }, // CAST5
{ { SERPENT, 0 } , CBC }, // Serpent
{ { TRIPLEDES, 0 } , CBC }, // Triple DES
{ { TWOFISH, 0 } , CBC }, // Twofish
{ { BLOWFISH, AES, 0 } , INNER_CBC }, // AES-Blowfish
{ { SERPENT, BLOWFISH, AES, 0 } , INNER_CBC }, // AES-Blowfish-Serpent
{ { TWOFISH, AES, 0 } , OUTER_CBC }, // AES-Twofish
{ { SERPENT, TWOFISH, AES, 0 } , OUTER_CBC }, // AES-Twofish-Serpent
{ { AES, SERPENT, 0 } , OUTER_CBC }, // Serpent-AES
{ { AES, TWOFISH, SERPENT, 0 } , OUTER_CBC }, // Serpent-Twofish-AES
{ { SERPENT, TWOFISH, 0 } , OUTER_CBC }, // Twofish-Serpent
{ { 0, 0 } , 0 } // (must be null)
};
void CipherInit (int cipher, unsigned char *key, unsigned char *ks)
{
switch (cipher)
{
case BLOWFISH:
BF_set_key ((BF_KEY *)ks, CipherGetKeySize(BLOWFISH), key);
break;
case AES:
aes_encrypt_key(key, CipherGetKeySize(AES), (aes_encrypt_ctx *) ks);
aes_decrypt_key(key, CipherGetKeySize(AES), (aes_decrypt_ctx *) (ks + sizeof(aes_encrypt_ctx)));
break;
case DES56:
des_key_sched ((des_cblock *) key, (struct des_ks_struct *) ks);
break;
case CAST:
CAST_set_key((CAST_KEY *) ks, CipherGetKeySize(CAST), key);
break;
case SERPENT:
serpent_set_key (key, CipherGetKeySize(SERPENT) * 8, ks);
break;
case TRIPLEDES:
des_key_sched ((des_cblock *) key, (struct des_ks_struct *) ks);
des_key_sched ((des_cblock *) ((char*)(key)+8), (struct des_ks_struct *) (ks + CipherGetKeyScheduleSize (DES56)));
des_key_sched ((des_cblock *) ((char*)(key)+16), (struct des_ks_struct *) (ks + CipherGetKeyScheduleSize (DES56) * 2));
break;
case TWOFISH:
twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key, CipherGetKeySize(TWOFISH) * 8);
break;
}
}
void EncipherBlock(int cipher, void *data, void *ks)
{
switch (cipher)
{
case BLOWFISH: BF_encrypt (data, ks); break;
case AES: aes_encrypt (data, data, ks); break;
case DES56: des_encrypt (data, ks, 1); break;
case CAST: CAST_ecb_encrypt (data, data, ks, 1); break;
case SERPENT: serpent_encrypt (data, data, ks); break;
case TRIPLEDES: des_ecb3_encrypt (data, data, ks,
(void*)((char*) ks + CipherGetKeyScheduleSize (DES56)), (void*)((char*) ks + CipherGetKeyScheduleSize (DES56) * 2), 1); break;
case TWOFISH: twofish_encrypt (ks, data, data); break;
}
}
void DecipherBlock(int cipher, void *data, void *ks)
{
switch (cipher)
{
case BLOWFISH: BF_decrypt (data, ks); break;
case AES: aes_decrypt (data, data, (void *) ((char *) ks + sizeof(aes_encrypt_ctx))); break;
case DES56: des_encrypt (data, ks, 0); break;
case CAST: CAST_ecb_encrypt (data, data, ks,0); break;
case SERPENT: serpent_decrypt (data, data, ks); break;
case TRIPLEDES: des_ecb3_encrypt (data, data, ks,
(void*)((char*) ks + CipherGetKeyScheduleSize (DES56)),
(void*)((char*) ks + CipherGetKeyScheduleSize (DES56) * 2), 0); break;
case TWOFISH: twofish_decrypt (ks, data, data); break;
}
}
// Ciphers support
Cipher *CipherGet (int id)
{
int i;
for (i = 0; Ciphers[i].Id != 0; i++)
if (Ciphers[i].Id == id)
return &Ciphers[i];
return 0;
}
char *CipherGetName (int cipherId)
{
return CipherGet (cipherId) -> Name;
}
int CipherGetBlockSize (int cipherId)
{
return CipherGet (cipherId) -> BlockSize;
}
int CipherGetKeySize (int cipherId)
{
return CipherGet (cipherId) -> KeySize;
}
int CipherGetKeyScheduleSize (int cipherId)
{
return CipherGet (cipherId) -> KeyScheduleSize;
}
// Encryption algorithms support
int EAGetFirst ()
{
return 1;
}
// Returns number of EAs
int EAGetCount (void)
{
int ea, count = 0;
for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea))
{
count++;
}
return count;
}
int EAGetNext (int previousEA)
{
int id = previousEA + 1;
if (EncryptionAlgorithms[id].Ciphers[0] != 0) return id;
return 0;
}
void EAInit (int ea, unsigned char *key, unsigned char *ks)
{
int i = 0, c;
for (c = EAGetFirstCipher (ea); c != 0; c = EAGetNextCipher (ea, c))
{
CipherInit (c, key, ks);
key += CipherGetKeySize (c);
ks += CipherGetKeyScheduleSize (c);
}
}
// Returns name of EA, cascaded cipher names are separated by hyphens
char *EAGetName (char *buf, int ea)
{
int i = EAGetLastCipher(ea);
strcpy (buf, CipherGetName (i));
while (i = EAGetPreviousCipher(ea, i))
{
strcat (buf, "-");
strcat (buf, CipherGetName (i));
}
return buf;
}
// Returns sum of key sizes of all EA ciphers
int EAGetKeySize (int ea)
{
int i = EAGetFirstCipher(ea);
int size = CipherGetKeySize (i);
while (i = EAGetNextCipher(ea, i))
{
size += CipherGetKeySize (i);
}
return size;
}
// Returns the mode of operation of the whole EA
int EAGetMode (int ea)
{
return (EncryptionAlgorithms[ea].Mode);
}
// Returns the name of the mode of operation of the whole EA
char *EAGetModeName (char *name, int ea, BOOL capitalLetters)
{
char eaName[100];
switch (EncryptionAlgorithms[ea].Mode)
{
case CBC:
EAGetName (eaName, ea);
if (strcmp (eaName, "Triple DES") == 0)
sprintf (name, "%s", capitalLetters ? "Outer-CBC" : "outer-CBC");
else
sprintf (name, "%s", "CBC");
break;
case OUTER_CBC:
strcpy (name, capitalLetters ? "Outer-CBC" : "outer-CBC");
break;
case INNER_CBC:
strcpy (name, capitalLetters ? "Inner-CBC" : "inner-CBC");
break;
default:
strcpy (name, "[unknown]");
break;
}
return name;
}
// Returns sum of key schedule sizes of all EA ciphers
int EAGetKeyScheduleSize (int ea)
{
int i = EAGetFirstCipher(ea);
int size = CipherGetKeyScheduleSize (i);
while (i = EAGetNextCipher(ea, i))
{
size += CipherGetKeyScheduleSize (i);
}
return size;
}
// Returns largest key needed by all EAs
int EAGetLargestKey ()
{
int ea, key = 0;
for (ea = EAGetFirst (); ea != 0 ; ea = EAGetNext (ea))
{
if (EAGetKeySize (ea) >= key)
key = EAGetKeySize (ea);
}
return key;
}
// Returns number of ciphers in EA
int EAGetCipherCount (int ea)
{
int i = 0;
while (EncryptionAlgorithms[ea].Ciphers[i++]);
return i - 1;
}
int EAGetFirstCipher (int ea)
{
return EncryptionAlgorithms[ea].Ciphers[0];
}
int EAGetLastCipher (int ea)
{
int c, i = 0;
while (c = EncryptionAlgorithms[ea].Ciphers[i++]);
return EncryptionAlgorithms[ea].Ciphers[i - 2];
}
int EAGetNextCipher (int ea, int previousCipherId)
{
int c, i = 0;
while (c = EncryptionAlgorithms[ea].Ciphers[i++])
{
if (c == previousCipherId)
return EncryptionAlgorithms[ea].Ciphers[i];
}
return 0;
}
int EAGetPreviousCipher (int ea, int previousCipherId)
{
int c, i = 0;
if (EncryptionAlgorithms[ea].Ciphers[i++] == previousCipherId)
return 0;
while (c = EncryptionAlgorithms[ea].Ciphers[i++])
{
if (c == previousCipherId)
return EncryptionAlgorithms[ea].Ciphers[i - 2];
}
return 0;
}
// Hash support functions
char * get_hash_name (int pkcs5)
{
switch (pkcs5)
{
case SHA1: return "HMAC-SHA-1";
case RIPEMD160: return "HMAC-RIPEMD-160";
default: return "Unknown";
}
}
PCRYPTO_INFO
crypto_open ()
{
/* Do the crt allocation */
PCRYPTO_INFO cryptoInfo = TCalloc (sizeof (CRYPTO_INFO));
#ifndef DEVICE_DRIVER
VirtualLock (cryptoInfo, sizeof (CRYPTO_INFO));
#endif
if (cryptoInfo == NULL)
return NULL;
cryptoInfo->ea = -1;
return cryptoInfo;
}
void
crypto_loadkey (PKEY_INFO keyInfo, char *lpszUserKey, int nUserKeyLen)
{
keyInfo->keyLength = nUserKeyLen;
burn (keyInfo->userKey, sizeof (keyInfo->userKey));
memcpy (keyInfo->userKey, lpszUserKey, nUserKeyLen);
}
void
crypto_close (PCRYPTO_INFO cryptoInfo)
{
burn (cryptoInfo, sizeof (CRYPTO_INFO));
#ifndef DEVICE_DRIVER
VirtualUnlock (cryptoInfo, sizeof (CRYPTO_INFO));
#endif
TCfree (cryptoInfo);
}
// Initializes IV and whitening values for sector encryption/decryption
static void
InitSectorIVAndWhitening (unsigned __int64 secNo,
int blockSize,
unsigned long *iv,
unsigned __int64 *ivSeed,
unsigned long *whitening)
{
unsigned __int64 iv64[4];
unsigned long *iv32 = (unsigned long *) iv64;
iv64[0] = ivSeed[0] ^ secNo;
iv64[1] = ivSeed[1] ^ secNo;
iv64[2] = ivSeed[2] ^ secNo;
if (blockSize == 16)
{
iv64[3] = ivSeed[3] ^ secNo;
}
iv[0] = iv32[0];
iv[1] = iv32[1];
switch (blockSize)
{
case 16:
// 128-bit block
iv[2] = iv32[2];
iv[3] = iv32[3];
whitening[0] = crc32long ( &iv32[4] ) ^ crc32long ( &iv32[7] );
whitening[1] = crc32long ( &iv32[5] ) ^ crc32long ( &iv32[6] );
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -