1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-07-06 07:44:57 +03:00

Revamp digest functions

- Hash() has been removed because it was ambiguous, Md5() and Sha0() are proper replacements.
- HMacMd5() and HMacSha1() now share a common implementation handled by the new Internal_HMac() function.
- NewMd() and MdProcess() now support plain hashing (without the key).
- NewMd(), SetMdKey() and MdProcess() now check the OpenSSL functions' return value and in case of failure a debug message is printed along with the error string, if available.
- SetMdKey()'s return value has been changed from void to bool, so that it's possible to know whether the function succeeded or not.
- MdProcess()' return value has been changed from void to UINT (unsigned int) and the function now returns the number of bytes written by HMAC_Final() or EVP_DigestFinal_ex().
This commit is contained in:
Davide Beatrici
2018-09-22 06:35:30 +02:00
parent 69b35f875a
commit 3f5f716357
41 changed files with 329 additions and 371 deletions

View File

@ -170,7 +170,8 @@ LOCK **ssl_lock_obj = NULL;
UINT ssl_lock_num;
static bool openssl_inited = false;
static unsigned char *Internal_SHA0(const unsigned char *d, size_t n, unsigned char *md);
static UINT Internal_HMac(const EVP_MD *md, void *dest, void *key, UINT key_size, const void *src, const UINT src_size);
static void Internal_Sha0(unsigned char *dest, const unsigned char *src, const UINT size);
// For the callback function
typedef struct CB_PARAM
@ -268,185 +269,86 @@ void Enc_tls1_PRF(unsigned char *label, int label_len, const unsigned char *sec,
}
// Calculation of HMAC (MD5)
void HMacMd5(void *dst, void *key, UINT key_size, void *data, UINT data_size)
UINT HMacMd5(void *dst, void *key, UINT key_size, void *src, UINT src_size)
{
UCHAR k[HMAC_BLOCK_SIZE];
UCHAR hash1[MD5_SIZE];
UCHAR data2[HMAC_BLOCK_SIZE];
MD5_CTX md5_ctx1;
UCHAR pad1[HMAC_BLOCK_SIZE];
UINT i;
// Validate arguments
if (dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
{
return;
}
// Creating a K
if (key_size <= HMAC_BLOCK_SIZE)
{
for (i = 0;i < key_size;i++)
{
pad1[i] = ((UCHAR *)key)[i] ^ 0x36;
}
for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
{
pad1[i] = 0 ^ 0x36;
}
}
else
{
Zero(k, sizeof(k));
Hash(k, key, key_size, false);
for (i = 0;i < HMAC_BLOCK_SIZE;i++)
{
pad1[i] = k[i] ^ 0x36;
}
}
MD5_Init(&md5_ctx1);
MD5_Update(&md5_ctx1, pad1, sizeof(pad1));
MD5_Update(&md5_ctx1, data, data_size);
MD5_Final(hash1, &md5_ctx1);
// Generation of data 2
if (key_size <= HMAC_BLOCK_SIZE)
{
for (i = 0;i < key_size;i++)
{
data2[i] = ((UCHAR *)key)[i] ^ 0x5c;
}
for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
{
data2[i] = 0 ^ 0x5c;
}
}
else
{
for (i = 0;i < HMAC_BLOCK_SIZE;i++)
{
data2[i] = k[i] ^ 0x5c;
}
}
MD5_Init(&md5_ctx1);
MD5_Update(&md5_ctx1, data2, HMAC_BLOCK_SIZE);
MD5_Update(&md5_ctx1, hash1, MD5_SIZE);
MD5_Final(dst, &md5_ctx1);
return Internal_HMac(EVP_md5(), dst, key, key_size, src, src_size);
}
// Calculation of HMAC (SHA-1)
void HMacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size)
UINT HMacSha1(void *dst, void *key, UINT key_size, void *src, UINT src_size)
{
UCHAR k[HMAC_BLOCK_SIZE];
UCHAR hash1[SHA1_SIZE];
UCHAR data2[HMAC_BLOCK_SIZE];
SHA_CTX sha_ctx1;
UCHAR pad1[HMAC_BLOCK_SIZE];
UINT i;
// Validate arguments
if (dst == NULL || (key == NULL && key_size != 0) || (data == NULL && data_size != 0))
{
return;
}
// Creating a K
if (key_size <= HMAC_BLOCK_SIZE)
{
for (i = 0;i < key_size;i++)
{
pad1[i] = ((UCHAR *)key)[i] ^ 0x36;
}
for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
{
pad1[i] = 0 ^ 0x36;
}
}
else
{
Zero(k, sizeof(k));
HashSha1(k, key, key_size);
for (i = 0;i < HMAC_BLOCK_SIZE;i++)
{
pad1[i] = k[i] ^ 0x36;
}
}
SHA1_Init(&sha_ctx1);
SHA1_Update(&sha_ctx1, pad1, sizeof(pad1));
SHA1_Update(&sha_ctx1, data, data_size);
SHA1_Final(hash1, &sha_ctx1);
// Generation of data 2
if (key_size <= HMAC_BLOCK_SIZE)
{
for (i = 0;i < key_size;i++)
{
data2[i] = ((UCHAR *)key)[i] ^ 0x5c;
}
for (i = key_size;i < HMAC_BLOCK_SIZE;i++)
{
data2[i] = 0 ^ 0x5c;
}
}
else
{
for (i = 0;i < HMAC_BLOCK_SIZE;i++)
{
data2[i] = k[i] ^ 0x5c;
}
}
SHA1_Init(&sha_ctx1);
SHA1_Update(&sha_ctx1, data2, HMAC_BLOCK_SIZE);
SHA1_Update(&sha_ctx1, hash1, SHA1_SIZE);
SHA1_Final(dst, &sha_ctx1);
return Internal_HMac(EVP_sha1(), dst, key, key_size, src, src_size);
}
// Calculate the HMAC
void MdProcess(MD *md, void *dest, void *src, UINT size)
// Calculate the hash/HMAC
UINT MdProcess(MD *md, void *dest, void *src, UINT size)
{
int r = 0;
if (md != NULL && md->isNullMd)
{
if (dest != src)
{
Copy(dest, src, size);
}
return;
}
UINT len = 0;
// Validate arguments
if (md == NULL || dest == NULL || (src != NULL && size == 0))
if (md == NULL || md->IsNullMd || dest == NULL || (src == NULL && size != 0))
{
return;
return 0;
}
HMAC_Init_ex(md->Ctx, NULL, 0, NULL, NULL);
HMAC_Update(md->Ctx, src, size);
HMAC_Final(md->Ctx, dest, &r);
if (md->IsHMac)
{
if (HMAC_Update(md->Ctx, src, size) == false)
{
Debug("MdProcess(): HMAC_Update() failed with error: %s\n", OpenSSL_Error());
return 0;
}
if (HMAC_Final(md->Ctx, dest, &len) == false)
{
Debug("MdProcess(): HMAC_Final() failed with error: %s\n", OpenSSL_Error());
}
}
else
{
if (EVP_DigestUpdate(md->Ctx, src, size) == false)
{
Debug("MdProcess(): EVP_DigestUpdate() failed with error: %s\n", OpenSSL_Error());
return 0;
}
if (EVP_DigestFinal_ex(md->Ctx, dest, &len) == false)
{
Debug("MdProcess(): EVP_DigestFinal_ex() failed with error: %s\n", OpenSSL_Error());
}
}
return len;
}
// Set the key to the message digest object
void SetMdKey(MD *md, void *key, UINT key_size)
bool SetMdKey(MD *md, void *key, UINT key_size)
{
// Validate arguments
if (md == NULL || (key != NULL && key_size == 0))
if (md == NULL || md->IsHMac == false || key == NULL || key_size == 0)
{
return;
return false;
}
HMAC_Init_ex(md->Ctx, key, key_size, (const EVP_MD *)md->Md, NULL);
if (HMAC_Init_ex(md->Ctx, key, key_size, (const EVP_MD *)md->Md, NULL) == false)
{
Debug("SetMdKey(): HMAC_Init_ex() failed with error: %s\n", OpenSSL_Error());
return false;
}
return true;
}
// Creating a message digest object
MD *NewMd(char *name)
{
return NewMdEx(name, true);
}
MD *NewMdEx(char *name, bool hmac)
{
MD *m;
// Validate arguments
if (name == NULL)
{
@ -461,25 +363,43 @@ MD *NewMd(char *name)
StrCmpi(name, "NULL") == 0 ||
IsEmptyStr(name))
{
m->isNullMd = true;
m->IsNullMd = true;
return m;
}
m->Md = (const struct evp_md_st *)EVP_get_digestbyname(name);
if (m->Md == NULL)
{
Debug("NewMdEx(): Algorithm %s not found by EVP_get_digestbyname().\n", m->Name);
FreeMd(m);
return NULL;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
m->Ctx = HMAC_CTX_new();
#else
m->Ctx = ZeroMalloc(sizeof(struct hmac_ctx_st));
HMAC_CTX_init(m->Ctx);
#endif
m->Size = EVP_MD_size((const EVP_MD *)m->Md);
m->IsHMac = hmac;
if (hmac)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
m->Ctx = HMAC_CTX_new();
#else
m->Ctx = ZeroMalloc(sizeof(struct hmac_ctx_st));
HMAC_CTX_init(m->Ctx);
#endif
}
else
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
m->Ctx = EVP_MD_CTX_new();
#else
m->Ctx = EVP_MD_CTX_create();
#endif
if (EVP_DigestInit_ex(m->Ctx, m->Md, NULL) == false)
{
Debug("NewMdEx(): EVP_DigestInit_ex() failed with error: %s\n", OpenSSL_Error());
FreeMd(m);
}
}
return m;
}
@ -495,12 +415,23 @@ void FreeMd(MD *md)
if (md->Ctx != NULL)
{
if (md->IsHMac)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
HMAC_CTX_free(md->Ctx);
HMAC_CTX_free(md->Ctx);
#else
HMAC_CTX_cleanup(md->Ctx);
Free(md->Ctx);
HMAC_CTX_cleanup(md->Ctx);
Free(md->Ctx);
#endif
}
else
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_MD_CTX_free(md->Ctx);
#else
EVP_MD_CTX_destroy(md->Ctx);
#endif
}
}
Free(md);
@ -704,7 +635,7 @@ UINT HashPtrToUINT(void *p)
return 0;
}
Hash(hash_data, &p, sizeof(p), false);
Md5(hash_data, &p, sizeof(p));
Copy(&ret, hash_data, sizeof(ret));
@ -822,6 +753,11 @@ unsigned long OpenSSL_Id(void)
return (unsigned long)ThreadId();
}
char *OpenSSL_Error()
{
return ERR_error_string(ERR_get_error(), NULL);
}
// Get the display name of the certificate
void GetPrintNameFromX(wchar_t *str, UINT size, X *x)
{
@ -2287,7 +2223,7 @@ bool HashForSign(void *dst, UINT dst_size, void *src, UINT src_size)
Copy(buf, sign_data, sizeof(sign_data));
// Hash
HashSha1(HASHED_DATA(buf), src, src_size);
Sha1(HASHED_DATA(buf), src, src_size);
return true;
}
@ -3781,8 +3717,8 @@ void InitCryptLibrary()
openssl_inited = true;
}
// Hash function
void Hash(void *dst, void *src, UINT size, bool sha)
// MD4 specific hash function
void HashMd4(void *dst, void *src, UINT size)
{
// Validate arguments
if (dst == NULL || (src == NULL && size != 0))
@ -3790,26 +3726,6 @@ void Hash(void *dst, void *src, UINT size, bool sha)
return;
}
if (sha == false)
{
// MD5 hash
MD5(src, size, dst);
}
else
{
// SHA hash
Internal_SHA0(src, size, dst);
}
}
// MD4 specific hash function
void HashMd4(void *dst, void *src, UINT size)
{
// Validate arguments
if (dst == NULL || (size != 0 && src == NULL))
{
return;
}
MD4(src, size, dst);
}
@ -3824,7 +3740,7 @@ UINT HashToUINT(void *data, UINT size)
return 0;
}
HashSha1(hash, data, size);
Sha1(hash, data, size);
Copy(&u, hash, sizeof(UINT));
@ -3836,12 +3752,7 @@ UINT HashToUINT(void *data, UINT size)
// SHA-1 specific hash function
void HashSha1(void *dst, void *src, UINT size)
{
// Validate arguments
if (dst == NULL || (size != 0 && src == NULL))
{
return;
}
SHA1(src, size, dst);
Sha1(dst, src, size);
}
// Creating a new CRYPT object
@ -3876,11 +3787,11 @@ void Encrypt(CRYPT *c, void *dst, void *src, UINT size)
RC4(c->Rc4Key, size, src, dst);
}
// SHA-1 hash
// SHA hash
void Sha(UINT sha_type, void *dst, void *src, UINT size)
{
// Validate arguments
if (dst == NULL || src == NULL)
if (dst == NULL || (src == NULL && size != 0))
{
return;
}
@ -3899,29 +3810,36 @@ void Sha(UINT sha_type, void *dst, void *src, UINT size)
SHA512(src, size, dst);
break;
}
}
// SHA-1 hash
void Sha1(void *dst, void *src, UINT size)
void Sha0(void *dst, void *src, UINT size)
{
// Validate arguments
if (dst == NULL || src == NULL)
if (dst == NULL || (src == NULL && size != 0))
{
return;
}
SHA1(src, size, dst);
Internal_Sha0(dst, src, size);
}
void Sha2_256(void *dst, void *src, UINT size) {
void Sha1(void *dst, void *src, UINT size)
{
Sha(SHA1_160, dst, src, size);
}
void Sha2_256(void *dst, void *src, UINT size)
{
Sha(SHA2_256, dst, src, size);
}
void Sha2_384(void *dst, void *src, UINT size) {
void Sha2_384(void *dst, void *src, UINT size)
{
Sha(SHA2_384, dst, src, size);
}
void Sha2_512(void *dst, void *src, UINT size) {
void Sha2_512(void *dst, void *src, UINT size)
{
Sha(SHA2_512, dst, src, size);
}
@ -3929,7 +3847,7 @@ void Sha2_512(void *dst, void *src, UINT size) {
void Md5(void *dst, void *src, UINT size)
{
// Validate arguments
if (dst == NULL || src == NULL)
if (dst == NULL || (src == NULL && size != 0))
{
return;
}
@ -4468,6 +4386,50 @@ void DhFree(DH_CTX *dh)
Free(dh);
}
int GetSslClientCertIndex()
{
return ssl_clientcert_index;
}
// Internal functions
static UINT Internal_HMac(const EVP_MD *md, void *dest, void *key, UINT key_size, const void *src, const UINT src_size)
{
MD *m;
UINT len = 0;
// Validate arguments
if (md == NULL || dest == NULL || key == NULL || key_size == 0 || (src == NULL && src_size != 0))
{
return 0;
}
m = ZeroMalloc(sizeof(MD));
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
m->Ctx = HMAC_CTX_new();
#else
m->Ctx = ZeroMalloc(sizeof(HMAC_CTX));
HMAC_CTX_init(m->Ctx);
#endif
m->Md = md;
m->IsHMac = true;
if (SetMdKey(m, key, key_size) == false)
{
Debug("Internal_HMac(): SetMdKey() failed!\n");
goto final;
}
len = MdProcess(m, dest, src, src_size);
if (len == 0)
{
Debug("Internal_HMac(): MdProcess() returned 0!\n");
}
final:
FreeMd(m);
return len;
}
/////////////////////////
// SHA0 implementation //
/////////////////////////
@ -4767,24 +4729,12 @@ static void ampheck_sha0_finish(const struct ampheck_sha0 *ctx, UCHAR *digest)
UNPACK_32_BE(tmp.h[3], &digest[12]);
UNPACK_32_BE(tmp.h[4], &digest[16]);
}
static unsigned char *Internal_SHA0(const unsigned char *d, size_t n, unsigned char *md)
static void Internal_Sha0(unsigned char *dest, const unsigned char *src, const UINT size)
{
struct ampheck_sha0 c;
static unsigned char m[SHA_DIGEST_LENGTH];
if (md == NULL) md=m;
ampheck_sha0_init(&c);
ampheck_sha0_update(&c, d, (UINT)n);
ampheck_sha0_finish(&c, md);
return md;
ampheck_sha0_update(&c, src, size);
ampheck_sha0_finish(&c, dest);
}
int GetSslClientCertIndex()
{
return ssl_clientcert_index;
}