Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
50
third_party/FreeRDP/winpr/libwinpr/crypto/CMakeLists.txt
vendored
Normal file
50
third_party/FreeRDP/winpr/libwinpr/crypto/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# WinPR: Windows Portable Runtime
|
||||
# libwinpr-crypto cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(SRCS hash.c rand.c cipher.c cert.c crypto.c crypto.h)
|
||||
if(WITH_INTERNAL_RC4)
|
||||
list(APPEND SRCS rc4.c rc4.h)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNAL_MD4)
|
||||
list(APPEND SRCS md4.c md4.h)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNAL_MD5)
|
||||
list(APPEND SRCS md5.c md5.h)
|
||||
list(APPEND SRCS hmac_md5.c hmac_md5.h)
|
||||
endif()
|
||||
|
||||
winpr_module_add(${SRCS})
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
winpr_system_include_directory_add(${OPENSSL_INCLUDE_DIR})
|
||||
winpr_library_add_private(${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(MBEDTLS_FOUND)
|
||||
winpr_system_include_directory_add(${MBEDTLS_INCLUDE_DIR})
|
||||
winpr_library_add_private(${MBEDTLS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
winpr_library_add_public(crypt32)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
7
third_party/FreeRDP/winpr/libwinpr/crypto/ModuleOptions.cmake
vendored
Normal file
7
third_party/FreeRDP/winpr/libwinpr/crypto/ModuleOptions.cmake
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
set(MINWIN_LAYER "1")
|
||||
set(MINWIN_GROUP "core")
|
||||
set(MINWIN_MAJOR_VERSION "1")
|
||||
set(MINWIN_MINOR_VERSION "0")
|
||||
set(MINWIN_SHORT_NAME "crypto")
|
||||
set(MINWIN_LONG_NAME "Cryptography API (CryptoAPI)")
|
||||
set(MODULE_LIBRARY_NAME "crypt32")
|
||||
239
third_party/FreeRDP/winpr/libwinpr/crypto/cert.c
vendored
Normal file
239
third_party/FreeRDP/winpr/libwinpr/crypto/cert.c
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API (CryptoAPI)
|
||||
*
|
||||
* Copyright 2012-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
/**
|
||||
* CertOpenStore
|
||||
* CertCloseStore
|
||||
* CertControlStore
|
||||
* CertDuplicateStore
|
||||
* CertSaveStore
|
||||
* CertRegisterPhysicalStore
|
||||
* CertRegisterSystemStore
|
||||
* CertAddStoreToCollection
|
||||
* CertRemoveStoreFromCollection
|
||||
* CertOpenSystemStoreA
|
||||
* CertOpenSystemStoreW
|
||||
* CertEnumPhysicalStore
|
||||
* CertEnumSystemStore
|
||||
* CertEnumSystemStoreLocation
|
||||
* CertSetStoreProperty
|
||||
* CertUnregisterPhysicalStore
|
||||
* CertUnregisterSystemStore
|
||||
*
|
||||
* CertAddCertificateContextToStore
|
||||
* CertAddCertificateLinkToStore
|
||||
* CertAddCRLContextToStore
|
||||
* CertAddCRLLinkToStore
|
||||
* CertAddCTLContextToStore
|
||||
* CertAddCTLLinkToStore
|
||||
* CertAddEncodedCertificateToStore
|
||||
* CertAddEncodedCertificateToSystemStoreA
|
||||
* CertAddEncodedCertificateToSystemStoreW
|
||||
* CertAddEncodedCRLToStore
|
||||
* CertAddEncodedCTLToStore
|
||||
* CertAddSerializedElementToStore
|
||||
* CertDeleteCertificateFromStore
|
||||
* CertDeleteCRLFromStore
|
||||
* CertDeleteCTLFromStore
|
||||
* CertGetCRLFromStore
|
||||
* CertEnumCertificatesInStore
|
||||
* CertEnumCRLsInStore
|
||||
* CertEnumCTLsInStore
|
||||
* CertFindCertificateInStore
|
||||
* CertFindChainInStore
|
||||
* CertFindCRLInStore
|
||||
* CertFindCTLInStore
|
||||
* CertGetIssuerCertificateFromStore
|
||||
* CertGetStoreProperty
|
||||
* CertGetSubjectCertificateFromStore
|
||||
* CertSerializeCertificateStoreElement
|
||||
* CertSerializeCRLStoreElement
|
||||
* CertSerializeCTLStoreElement
|
||||
*
|
||||
* CertAddEnhancedKeyUsageIdentifier
|
||||
* CertAddRefServerOcspResponse
|
||||
* CertAddRefServerOcspResponseContext
|
||||
* CertAlgIdToOID
|
||||
* CertCloseServerOcspResponse
|
||||
* CertCompareCertificate
|
||||
* CertCompareCertificateName
|
||||
* CertCompareIntegerBlob
|
||||
* CertComparePublicKeyInfo
|
||||
* CertCreateCertificateChainEngine
|
||||
* CertCreateCertificateContext
|
||||
* CertCreateContext
|
||||
* CertCreateCRLContext
|
||||
* CertCreateCTLContext
|
||||
* CertCreateCTLEntryFromCertificateContextProperties
|
||||
* CertCreateSelfSignCertificate
|
||||
* CertDuplicateCertificateChain
|
||||
* CertDuplicateCertificateContext
|
||||
* CertDuplicateCRLContext
|
||||
* CertDuplicateCTLContext
|
||||
* CertEnumCertificateContextProperties
|
||||
* CertEnumCRLContextProperties
|
||||
* CertEnumCTLContextProperties
|
||||
* CertEnumSubjectInSortedCTL
|
||||
* CertFindAttribute
|
||||
* CertFindCertificateInCRL
|
||||
* CertFindExtension
|
||||
* CertFindRDNAttr
|
||||
* CertFindSubjectInCTL
|
||||
* CertFindSubjectInSortedCTL
|
||||
* CertFreeCertificateChain
|
||||
* CertFreeCertificateChainEngine
|
||||
* CertFreeCertificateChainList
|
||||
* CertFreeCertificateContext
|
||||
* CertFreeCRLContext
|
||||
* CertFreeCTLContext
|
||||
* CertFreeServerOcspResponseContext
|
||||
* CertGetCertificateChain
|
||||
* CertGetCertificateContextProperty
|
||||
* CertGetCRLContextProperty
|
||||
* CertGetCTLContextProperty
|
||||
* CertGetEnhancedKeyUsage
|
||||
* CertGetIntendedKeyUsage
|
||||
* CertGetNameStringA
|
||||
* CertGetNameStringW
|
||||
* CertGetPublicKeyLength
|
||||
* CertGetServerOcspResponseContext
|
||||
* CertGetValidUsages
|
||||
* CertIsRDNAttrsInCertificateName
|
||||
* CertIsStrongHashToSign
|
||||
* CertIsValidCRLForCertificate
|
||||
* CertNameToStrA
|
||||
* CertNameToStrW
|
||||
* CertOIDToAlgId
|
||||
* CertOpenServerOcspResponse
|
||||
* CertRDNValueToStrA
|
||||
* CertRDNValueToStrW
|
||||
* CertRemoveEnhancedKeyUsageIdentifier
|
||||
* CertResyncCertificateChainEngine
|
||||
* CertRetrieveLogoOrBiometricInfo
|
||||
* CertSelectCertificateChains
|
||||
* CertSetCertificateContextPropertiesFromCTLEntry
|
||||
* CertSetCertificateContextProperty
|
||||
* CertSetCRLContextProperty
|
||||
* CertSetCTLContextProperty
|
||||
* CertSetEnhancedKeyUsage
|
||||
* CertStrToNameA
|
||||
* CertStrToNameW
|
||||
* CertVerifyCertificateChainPolicy
|
||||
* CertVerifyCRLRevocation
|
||||
* CertVerifyCRLTimeValidity
|
||||
* CertVerifyCTLUsage
|
||||
* CertVerifyRevocation
|
||||
* CertVerifySubjectCertificateContext
|
||||
* CertVerifyTimeValidity
|
||||
* CertVerifyValidityNesting
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/wincrypt.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
HCERTSTORE CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType,
|
||||
WINPR_ATTR_UNUSED HCRYPTPROV_LEGACY hCryptProv,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED const void* pvPara)
|
||||
{
|
||||
WINPR_CERTSTORE* certstore = nullptr;
|
||||
|
||||
certstore = (WINPR_CERTSTORE*)calloc(1, sizeof(WINPR_CERTSTORE));
|
||||
|
||||
if (certstore)
|
||||
{
|
||||
certstore->lpszStoreProvider = lpszStoreProvider;
|
||||
certstore->dwMsgAndCertEncodingType = dwMsgAndCertEncodingType;
|
||||
}
|
||||
|
||||
return (HCERTSTORE)certstore;
|
||||
}
|
||||
|
||||
HCERTSTORE CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
|
||||
WINPR_ATTR_UNUSED LPCWSTR szSubsystemProtocol)
|
||||
{
|
||||
HCERTSTORE hCertStore = nullptr;
|
||||
|
||||
hCertStore = CertOpenStore(CERT_STORE_PROV_FILE, X509_ASN_ENCODING, hProv, 0, nullptr);
|
||||
|
||||
return hCertStore;
|
||||
}
|
||||
|
||||
HCERTSTORE CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
|
||||
WINPR_ATTR_UNUSED LPCSTR szSubsystemProtocol)
|
||||
{
|
||||
return CertOpenSystemStoreW(hProv, nullptr);
|
||||
}
|
||||
|
||||
BOOL CertCloseStore(HCERTSTORE hCertStore, WINPR_ATTR_UNUSED DWORD dwFlags)
|
||||
{
|
||||
WINPR_CERTSTORE* certstore = nullptr;
|
||||
|
||||
certstore = (WINPR_CERTSTORE*)hCertStore;
|
||||
|
||||
free(certstore);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PCCERT_CONTEXT CertFindCertificateInStore(WINPR_ATTR_UNUSED HCERTSTORE hCertStore,
|
||||
WINPR_ATTR_UNUSED DWORD dwCertEncodingType,
|
||||
WINPR_ATTR_UNUSED DWORD dwFindFlags,
|
||||
WINPR_ATTR_UNUSED DWORD dwFindType,
|
||||
WINPR_ATTR_UNUSED const void* pvFindPara,
|
||||
WINPR_ATTR_UNUSED PCCERT_CONTEXT pPrevCertContext)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return (PCCERT_CONTEXT)1;
|
||||
}
|
||||
|
||||
PCCERT_CONTEXT CertEnumCertificatesInStore(WINPR_ATTR_UNUSED HCERTSTORE hCertStore,
|
||||
WINPR_ATTR_UNUSED PCCERT_CONTEXT pPrevCertContext)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return (PCCERT_CONTEXT) nullptr;
|
||||
}
|
||||
|
||||
DWORD CertGetNameStringW(WINPR_ATTR_UNUSED PCCERT_CONTEXT pCertContext,
|
||||
WINPR_ATTR_UNUSED DWORD dwType, WINPR_ATTR_UNUSED DWORD dwFlags,
|
||||
WINPR_ATTR_UNUSED void* pvTypePara, WINPR_ATTR_UNUSED LPWSTR pszNameString,
|
||||
WINPR_ATTR_UNUSED DWORD cchNameString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD CertGetNameStringA(WINPR_ATTR_UNUSED PCCERT_CONTEXT pCertContext,
|
||||
WINPR_ATTR_UNUSED DWORD dwType, WINPR_ATTR_UNUSED DWORD dwFlags,
|
||||
WINPR_ATTR_UNUSED void* pvTypePara, WINPR_ATTR_UNUSED LPSTR pszNameString,
|
||||
WINPR_ATTR_UNUSED DWORD cchNameString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
881
third_party/FreeRDP/winpr/libwinpr/crypto/cipher.c
vendored
Normal file
881
third_party/FreeRDP/winpr/libwinpr/crypto/cipher.c
vendored
Normal file
@@ -0,0 +1,881 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
*
|
||||
* Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crypto.cipher")
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
#include "rc4.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rc4.h>
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/des.h>
|
||||
#include <mbedtls/cipher.h>
|
||||
#if MBEDTLS_VERSION_MAJOR < 3
|
||||
#define mbedtls_cipher_info_get_iv_size(_info) (_info->iv_size)
|
||||
#define mbedtls_cipher_info_get_key_bitlen(_info) (_info->key_bitlen)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct winpr_cipher_ctx_private_st
|
||||
{
|
||||
WINPR_CIPHER_TYPE cipher;
|
||||
WINPR_CRYPTO_OPERATION op;
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
EVP_CIPHER_CTX* ectx;
|
||||
#endif
|
||||
#ifdef WITH_MBEDTLS
|
||||
mbedtls_cipher_context_t* mctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* RC4
|
||||
*/
|
||||
|
||||
struct winpr_rc4_ctx_private_st
|
||||
{
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
winpr_int_RC4_CTX* ictx;
|
||||
#else
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX* ctx;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips)
|
||||
{
|
||||
if (!key || (keylen == 0))
|
||||
return nullptr;
|
||||
|
||||
WINPR_RC4_CTX* ctx = (WINPR_RC4_CTX*)calloc(1, sizeof(WINPR_RC4_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
WINPR_UNUSED(override_fips);
|
||||
ctx->ictx = winpr_int_rc4_new(key, keylen);
|
||||
if (!ctx->ictx)
|
||||
goto fail;
|
||||
#elif defined(WITH_OPENSSL)
|
||||
const EVP_CIPHER* evp = nullptr;
|
||||
|
||||
if (keylen > INT_MAX)
|
||||
goto fail;
|
||||
|
||||
ctx->ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx->ctx)
|
||||
goto fail;
|
||||
|
||||
evp = EVP_rc4();
|
||||
|
||||
if (!evp)
|
||||
goto fail;
|
||||
|
||||
EVP_CIPHER_CTX_reset(ctx->ctx);
|
||||
if (EVP_EncryptInit_ex(ctx->ctx, evp, nullptr, nullptr, nullptr) != 1)
|
||||
goto fail;
|
||||
|
||||
/* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
|
||||
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
|
||||
|
||||
if (override_fips == TRUE)
|
||||
EVP_CIPHER_CTX_set_flags(ctx->ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
|
||||
|
||||
#endif
|
||||
EVP_CIPHER_CTX_set_key_length(ctx->ctx, (int)keylen);
|
||||
if (EVP_EncryptInit_ex(ctx->ctx, nullptr, nullptr, key, nullptr) != 1)
|
||||
goto fail;
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
|
||||
winpr_RC4_Free(ctx);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const void* key, size_t keylen)
|
||||
{
|
||||
return winpr_RC4_New_Internal(key, keylen, TRUE);
|
||||
}
|
||||
|
||||
WINPR_RC4_CTX* winpr_RC4_New(const void* key, size_t keylen)
|
||||
{
|
||||
return winpr_RC4_New_Internal(key, keylen, FALSE);
|
||||
}
|
||||
|
||||
BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const void* input, void* output)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
return winpr_int_rc4_update(ctx->ictx, length, input, output);
|
||||
#elif defined(WITH_OPENSSL)
|
||||
WINPR_ASSERT(ctx->ctx);
|
||||
int outputLength = 0;
|
||||
if (length > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
WINPR_ASSERT(ctx);
|
||||
if (EVP_CipherUpdate(ctx->ctx, output, &outputLength, input, (int)length) != 1)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
winpr_int_rc4_free(ctx->ictx);
|
||||
#elif defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX_free(ctx->ctx);
|
||||
#endif
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic Cipher API
|
||||
*/
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
extern mbedtls_md_type_t winpr_mbedtls_get_md_type(int md);
|
||||
#endif
|
||||
|
||||
struct cipher_map
|
||||
{
|
||||
WINPR_CIPHER_TYPE md;
|
||||
const char* name;
|
||||
};
|
||||
static const struct cipher_map s_cipher_map[] = {
|
||||
{ WINPR_CIPHER_NONE, "none" },
|
||||
{ WINPR_CIPHER_NULL, "null" },
|
||||
{ WINPR_CIPHER_AES_128_ECB, "aes-128-ecb" },
|
||||
{ WINPR_CIPHER_AES_192_ECB, "aes-192-ecb" },
|
||||
{ WINPR_CIPHER_AES_256_ECB, "aes-256-ecb" },
|
||||
{ WINPR_CIPHER_AES_128_CBC, "aes-128-cbc" },
|
||||
{ WINPR_CIPHER_AES_192_CBC, "aes-192-cbc" },
|
||||
{ WINPR_CIPHER_AES_256_CBC, "aes-256-cbc" },
|
||||
{ WINPR_CIPHER_AES_128_CFB128, "aes-128-cfb128" },
|
||||
{ WINPR_CIPHER_AES_192_CFB128, "aes-192-cfb128" },
|
||||
{ WINPR_CIPHER_AES_256_CFB128, "aes-256-cfb128" },
|
||||
{ WINPR_CIPHER_AES_128_CTR, "aes-128-ctr" },
|
||||
{ WINPR_CIPHER_AES_192_CTR, "aes-192-ctr" },
|
||||
{ WINPR_CIPHER_AES_256_CTR, "aes-256-ctr" },
|
||||
{ WINPR_CIPHER_AES_128_GCM, "aes-128-gcm" },
|
||||
{ WINPR_CIPHER_AES_192_GCM, "aes-192-gcm" },
|
||||
{ WINPR_CIPHER_AES_256_GCM, "aes-256-gcm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_ECB, "camellia-128-ecb" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_ECB, "camellia-192-ecb" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_ECB, "camellia-256-ecb" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CBC, "camellia-128-cbc" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CBC, "camellia-192-cbc" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CBC, "camellia-256-cbc" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CFB128, "camellia-128-cfb128" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CFB128, "camellia-192-cfb128" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CFB128, "camellia-256-cfb128" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CTR, "camellia-128-ctr" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CTR, "camellia-192-ctr" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CTR, "camellia-256-ctr" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_GCM, "camellia-128-gcm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_GCM, "camellia-192-gcm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_GCM, "camellia-256-gcm" },
|
||||
{ WINPR_CIPHER_DES_ECB, "des-ecb" },
|
||||
{ WINPR_CIPHER_DES_CBC, "des-cbc" },
|
||||
{ WINPR_CIPHER_DES_EDE_ECB, "des-ede-ecb" },
|
||||
{ WINPR_CIPHER_DES_EDE_CBC, "des-ede-cbc" },
|
||||
{ WINPR_CIPHER_DES_EDE3_ECB, "des-ede3-ecb" },
|
||||
{ WINPR_CIPHER_DES_EDE3_CBC, "des-ede3-cbc" },
|
||||
{ WINPR_CIPHER_BLOWFISH_ECB, "blowfish-ecb" },
|
||||
{ WINPR_CIPHER_BLOWFISH_CBC, "blowfish-cbc" },
|
||||
{ WINPR_CIPHER_BLOWFISH_CFB64, "blowfish-cfb64" },
|
||||
{ WINPR_CIPHER_BLOWFISH_CTR, "blowfish-ctr" },
|
||||
{ WINPR_CIPHER_ARC4_128, "rc4" },
|
||||
{ WINPR_CIPHER_AES_128_CCM, "aes-128-ccm" },
|
||||
{ WINPR_CIPHER_AES_192_CCM, "aes-192-ccm" },
|
||||
{ WINPR_CIPHER_AES_256_CCM, "aes-256-ccm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_128_CCM, "camellia-128-ccm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_192_CCM, "camellia-192-ccm" },
|
||||
{ WINPR_CIPHER_CAMELLIA_256_CCM, "camellia-256-ccm" },
|
||||
};
|
||||
|
||||
static int cipher_compare(const void* a, const void* b)
|
||||
{
|
||||
const WINPR_CIPHER_TYPE* cipher = a;
|
||||
const struct cipher_map* map = b;
|
||||
if (*cipher == map->md)
|
||||
return 0;
|
||||
return *cipher > map->md ? 1 : -1;
|
||||
}
|
||||
|
||||
const char* winpr_cipher_type_to_string(WINPR_CIPHER_TYPE md)
|
||||
{
|
||||
WINPR_CIPHER_TYPE lc = md;
|
||||
const struct cipher_map* ret = bsearch(&lc, s_cipher_map, ARRAYSIZE(s_cipher_map),
|
||||
sizeof(struct cipher_map), cipher_compare);
|
||||
if (!ret)
|
||||
return "unknown";
|
||||
return ret->name;
|
||||
}
|
||||
|
||||
static int cipher_string_compare(const void* a, const void* b)
|
||||
{
|
||||
const char* cipher = a;
|
||||
const struct cipher_map* map = b;
|
||||
return strcmp(cipher, map->name);
|
||||
}
|
||||
|
||||
WINPR_CIPHER_TYPE winpr_cipher_type_from_string(const char* name)
|
||||
{
|
||||
const struct cipher_map* ret = bsearch(name, s_cipher_map, ARRAYSIZE(s_cipher_map),
|
||||
sizeof(struct cipher_map), cipher_string_compare);
|
||||
if (!ret)
|
||||
return WINPR_CIPHER_NONE;
|
||||
return ret->md;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
static const EVP_CIPHER* winpr_openssl_get_evp_cipher(WINPR_CIPHER_TYPE cipher)
|
||||
{
|
||||
const EVP_CIPHER* evp = nullptr;
|
||||
|
||||
switch (cipher)
|
||||
{
|
||||
case WINPR_CIPHER_NULL:
|
||||
evp = EVP_enc_null();
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_ECB:
|
||||
evp = EVP_get_cipherbyname("aes-128-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_ECB:
|
||||
evp = EVP_get_cipherbyname("aes-192-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_ECB:
|
||||
evp = EVP_get_cipherbyname("aes-256-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CBC:
|
||||
evp = EVP_get_cipherbyname("aes-128-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CBC:
|
||||
evp = EVP_get_cipherbyname("aes-192-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CBC:
|
||||
evp = EVP_get_cipherbyname("aes-256-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CFB128:
|
||||
evp = EVP_get_cipherbyname("aes-128-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CFB128:
|
||||
evp = EVP_get_cipherbyname("aes-192-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CFB128:
|
||||
evp = EVP_get_cipherbyname("aes-256-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CTR:
|
||||
evp = EVP_get_cipherbyname("aes-128-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CTR:
|
||||
evp = EVP_get_cipherbyname("aes-192-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CTR:
|
||||
evp = EVP_get_cipherbyname("aes-256-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_GCM:
|
||||
evp = EVP_get_cipherbyname("aes-128-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_GCM:
|
||||
evp = EVP_get_cipherbyname("aes-192-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_GCM:
|
||||
evp = EVP_get_cipherbyname("aes-256-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CCM:
|
||||
evp = EVP_get_cipherbyname("aes-128-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CCM:
|
||||
evp = EVP_get_cipherbyname("aes-192-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CCM:
|
||||
evp = EVP_get_cipherbyname("aes-256-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_ECB:
|
||||
evp = EVP_get_cipherbyname("camellia-128-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_ECB:
|
||||
evp = EVP_get_cipherbyname("camellia-192-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_ECB:
|
||||
evp = EVP_get_cipherbyname("camellia-256-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CBC:
|
||||
evp = EVP_get_cipherbyname("camellia-128-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CBC:
|
||||
evp = EVP_get_cipherbyname("camellia-192-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CBC:
|
||||
evp = EVP_get_cipherbyname("camellia-256-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CFB128:
|
||||
evp = EVP_get_cipherbyname("camellia-128-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CFB128:
|
||||
evp = EVP_get_cipherbyname("camellia-192-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CFB128:
|
||||
evp = EVP_get_cipherbyname("camellia-256-cfb128");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CTR:
|
||||
evp = EVP_get_cipherbyname("camellia-128-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CTR:
|
||||
evp = EVP_get_cipherbyname("camellia-192-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CTR:
|
||||
evp = EVP_get_cipherbyname("camellia-256-ctr");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_GCM:
|
||||
evp = EVP_get_cipherbyname("camellia-128-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_GCM:
|
||||
evp = EVP_get_cipherbyname("camellia-192-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_GCM:
|
||||
evp = EVP_get_cipherbyname("camellia-256-gcm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_128_CCM:
|
||||
evp = EVP_get_cipherbyname("camellia-128-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_192_CCM:
|
||||
evp = EVP_get_cipherbyname("camellia-192-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_CAMELLIA_256_CCM:
|
||||
evp = EVP_get_cipherbyname("camellia-256-ccm");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_ECB:
|
||||
evp = EVP_get_cipherbyname("des-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_CBC:
|
||||
evp = EVP_get_cipherbyname("des-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE_ECB:
|
||||
evp = EVP_get_cipherbyname("des-ede-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE_CBC:
|
||||
evp = EVP_get_cipherbyname("des-ede-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE3_ECB:
|
||||
evp = EVP_get_cipherbyname("des-ede3-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_DES_EDE3_CBC:
|
||||
evp = EVP_get_cipherbyname("des-ede3-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_ARC4_128:
|
||||
evp = EVP_get_cipherbyname("rc4");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_ECB:
|
||||
evp = EVP_get_cipherbyname("blowfish-ecb");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_CBC:
|
||||
evp = EVP_get_cipherbyname("blowfish-cbc");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_CFB64:
|
||||
evp = EVP_get_cipherbyname("blowfish-cfb64");
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_BLOWFISH_CTR:
|
||||
evp = EVP_get_cipherbyname("blowfish-ctr");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return evp;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher)
|
||||
{
|
||||
mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
|
||||
|
||||
switch (cipher)
|
||||
{
|
||||
case WINPR_CIPHER_NONE:
|
||||
type = MBEDTLS_CIPHER_NONE;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_NULL:
|
||||
type = MBEDTLS_CIPHER_NULL;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_ECB:
|
||||
type = MBEDTLS_CIPHER_AES_128_ECB;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_ECB:
|
||||
type = MBEDTLS_CIPHER_AES_192_ECB;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_ECB:
|
||||
type = MBEDTLS_CIPHER_AES_256_ECB;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CBC:
|
||||
type = MBEDTLS_CIPHER_AES_128_CBC;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CBC:
|
||||
type = MBEDTLS_CIPHER_AES_192_CBC;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CBC:
|
||||
type = MBEDTLS_CIPHER_AES_256_CBC;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CFB128:
|
||||
type = MBEDTLS_CIPHER_AES_128_CFB128;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CFB128:
|
||||
type = MBEDTLS_CIPHER_AES_192_CFB128;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CFB128:
|
||||
type = MBEDTLS_CIPHER_AES_256_CFB128;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CTR:
|
||||
type = MBEDTLS_CIPHER_AES_128_CTR;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CTR:
|
||||
type = MBEDTLS_CIPHER_AES_192_CTR;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CTR:
|
||||
type = MBEDTLS_CIPHER_AES_256_CTR;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_GCM:
|
||||
type = MBEDTLS_CIPHER_AES_128_GCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_GCM:
|
||||
type = MBEDTLS_CIPHER_AES_192_GCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_GCM:
|
||||
type = MBEDTLS_CIPHER_AES_256_GCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_128_CCM:
|
||||
type = MBEDTLS_CIPHER_AES_128_CCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_192_CCM:
|
||||
type = MBEDTLS_CIPHER_AES_192_CCM;
|
||||
break;
|
||||
|
||||
case WINPR_CIPHER_AES_256_CCM:
|
||||
type = MBEDTLS_CIPHER_AES_256_CCM;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
WINPR_CIPHER_CTX* winpr_Cipher_New(WINPR_CIPHER_TYPE cipher, WINPR_CRYPTO_OPERATION op,
|
||||
const void* key, const void* iv)
|
||||
{
|
||||
return winpr_Cipher_NewEx(cipher, op, key, 0, iv, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
WINPR_API WINPR_CIPHER_CTX* winpr_Cipher_NewEx(WINPR_CIPHER_TYPE cipher, WINPR_CRYPTO_OPERATION op,
|
||||
const void* key, WINPR_ATTR_UNUSED size_t keylen,
|
||||
const void* iv, WINPR_ATTR_UNUSED size_t ivlen)
|
||||
{
|
||||
if (cipher == WINPR_CIPHER_ARC4_128)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"WINPR_CIPHER_ARC4_128 (RC4) cipher not supported, use winpr_RC4_new instead");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WINPR_CIPHER_CTX* ctx = calloc(1, sizeof(WINPR_CIPHER_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
ctx->cipher = cipher;
|
||||
ctx->op = op;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_CIPHER* evp = winpr_openssl_get_evp_cipher(cipher);
|
||||
if (!evp)
|
||||
goto fail;
|
||||
|
||||
ctx->ectx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx->ectx)
|
||||
goto fail;
|
||||
|
||||
{
|
||||
const int operation = (op == WINPR_ENCRYPT) ? 1 : 0;
|
||||
if (EVP_CipherInit_ex(ctx->ectx, evp, nullptr, key, iv, operation) != 1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_set_padding(ctx->ectx, 0);
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_cipher_type_t cipher_type = winpr_mbedtls_get_cipher_type(cipher);
|
||||
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
||||
|
||||
if (!cipher_info)
|
||||
goto fail;
|
||||
|
||||
ctx->mctx = calloc(1, sizeof(mbedtls_cipher_context_t));
|
||||
if (!ctx->mctx)
|
||||
goto fail;
|
||||
|
||||
const mbedtls_operation_t operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
|
||||
mbedtls_cipher_init(ctx->mctx);
|
||||
|
||||
if (mbedtls_cipher_setup(ctx->mctx, cipher_info) != 0)
|
||||
goto fail;
|
||||
|
||||
const int key_bitlen = mbedtls_cipher_get_key_bitlen(ctx->mctx);
|
||||
|
||||
if (mbedtls_cipher_setkey(ctx->mctx, key, key_bitlen, operation) != 0)
|
||||
goto fail;
|
||||
|
||||
if (mbedtls_cipher_set_padding_mode(ctx->mctx, MBEDTLS_PADDING_NONE) != 0)
|
||||
goto fail;
|
||||
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
winpr_Cipher_Free(ctx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL winpr_Cipher_SetPadding(WINPR_CIPHER_CTX* ctx, BOOL enabled)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (!ctx->ectx)
|
||||
return FALSE;
|
||||
EVP_CIPHER_CTX_set_padding(ctx->ectx, enabled);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_cipher_padding_t option = enabled ? MBEDTLS_PADDING_PKCS7 : MBEDTLS_PADDING_NONE;
|
||||
if (mbedtls_cipher_set_padding_mode((mbedtls_cipher_context_t*)ctx, option) != 0)
|
||||
return FALSE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const void* input, size_t ilen, void* output,
|
||||
size_t* olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
WINPR_ASSERT(olen);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
int outl = (int)*olen;
|
||||
|
||||
if (ilen > INT_MAX)
|
||||
{
|
||||
WLog_ERR(TAG, "input length %" PRIuz " > %d, abort", ilen, INT_MAX);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(ctx->ectx);
|
||||
if (EVP_CipherUpdate(ctx->ectx, output, &outl, input, (int)ilen) == 1)
|
||||
{
|
||||
*olen = (size_t)outl;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
WINPR_ASSERT(ctx->mctx);
|
||||
if (mbedtls_cipher_update(ctx->mctx, input, ilen, output, olen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
|
||||
WLog_ERR(TAG, "Failed to update the data");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, void* output, size_t* olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
int outl = (int)*olen;
|
||||
|
||||
WINPR_ASSERT(ctx->ectx);
|
||||
if (EVP_CipherFinal_ex(ctx->ectx, output, &outl) == 1)
|
||||
{
|
||||
*olen = (size_t)outl;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
|
||||
WINPR_ASSERT(ctx->mctx);
|
||||
if (mbedtls_cipher_finish(ctx->mctx, output, olen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (ctx->ectx)
|
||||
EVP_CIPHER_CTX_free(ctx->ectx);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
if (ctx->mctx)
|
||||
{
|
||||
mbedtls_cipher_free(ctx->mctx);
|
||||
free(ctx->mctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Key Generation
|
||||
*/
|
||||
|
||||
int winpr_Cipher_BytesToKey(int cipher, WINPR_MD_TYPE md, const void* salt, const void* data,
|
||||
size_t datal, size_t count, void* key, void* iv)
|
||||
{
|
||||
/**
|
||||
* Key and IV generation compatible with OpenSSL EVP_BytesToKey():
|
||||
* https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
|
||||
*/
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_MD* evp_md = nullptr;
|
||||
const EVP_CIPHER* evp_cipher = nullptr;
|
||||
evp_md = winpr_openssl_get_evp_md(md);
|
||||
evp_cipher = winpr_openssl_get_evp_cipher(WINPR_ASSERTING_INT_CAST(WINPR_CIPHER_TYPE, cipher));
|
||||
WINPR_ASSERT(datal <= INT_MAX);
|
||||
WINPR_ASSERT(count <= INT_MAX);
|
||||
return EVP_BytesToKey(evp_cipher, evp_md, salt, data, (int)datal, (int)count, key, iv);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
int rv = 0;
|
||||
BYTE md_buf[64];
|
||||
int niv, nkey, addmd = 0;
|
||||
unsigned int mds = 0;
|
||||
mbedtls_md_context_t ctx;
|
||||
const mbedtls_md_info_t* md_info;
|
||||
mbedtls_cipher_type_t cipher_type;
|
||||
const mbedtls_cipher_info_t* cipher_info;
|
||||
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
|
||||
md_info = mbedtls_md_info_from_type(md_type);
|
||||
cipher_type = winpr_mbedtls_get_cipher_type(cipher);
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
||||
nkey = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
|
||||
niv = mbedtls_cipher_info_get_iv_size(cipher_info);
|
||||
|
||||
if ((nkey > 64) || (niv > 64))
|
||||
return 0;
|
||||
|
||||
if (!data)
|
||||
return nkey;
|
||||
|
||||
mbedtls_md_init(&ctx);
|
||||
|
||||
if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
|
||||
goto err;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (mbedtls_md_starts(&ctx) != 0)
|
||||
goto err;
|
||||
|
||||
if (addmd++)
|
||||
{
|
||||
if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mbedtls_md_update(&ctx, data, datal) != 0)
|
||||
goto err;
|
||||
|
||||
if (salt)
|
||||
{
|
||||
if (mbedtls_md_update(&ctx, salt, 8) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mbedtls_md_finish(&ctx, md_buf) != 0)
|
||||
goto err;
|
||||
|
||||
mds = mbedtls_md_get_size(md_info);
|
||||
|
||||
for (unsigned int i = 1; i < (unsigned int)count; i++)
|
||||
{
|
||||
if (mbedtls_md_starts(&ctx) != 0)
|
||||
goto err;
|
||||
|
||||
if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
|
||||
goto err;
|
||||
|
||||
if (mbedtls_md_finish(&ctx, md_buf) != 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
unsigned int i = 0;
|
||||
|
||||
if (nkey)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (nkey == 0)
|
||||
break;
|
||||
|
||||
if (i == mds)
|
||||
break;
|
||||
|
||||
if (key)
|
||||
*(BYTE*)(key++) = md_buf[i];
|
||||
|
||||
nkey--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (niv && (i != mds))
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (niv == 0)
|
||||
break;
|
||||
|
||||
if (i == mds)
|
||||
break;
|
||||
|
||||
if (iv)
|
||||
*(BYTE*)(iv++) = md_buf[i];
|
||||
|
||||
niv--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((nkey == 0) && (niv == 0))
|
||||
break;
|
||||
}
|
||||
|
||||
rv = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
|
||||
err:
|
||||
mbedtls_md_free(&ctx);
|
||||
SecureZeroMemory(md_buf, 64);
|
||||
return rv;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
324
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.c
vendored
Normal file
324
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.c
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API (CryptoAPI)
|
||||
*
|
||||
* Copyright 2012-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
/**
|
||||
* CryptAcquireCertificatePrivateKey
|
||||
* CryptBinaryToStringA
|
||||
* CryptBinaryToStringW
|
||||
* CryptCloseAsyncHandle
|
||||
* CryptCreateAsyncHandle
|
||||
* CryptCreateKeyIdentifierFromCSP
|
||||
* CryptDecodeMessage
|
||||
* CryptDecodeObject
|
||||
* CryptDecodeObjectEx
|
||||
* CryptDecryptAndVerifyMessageSignature
|
||||
* CryptDecryptMessage
|
||||
* CryptEncodeObject
|
||||
* CryptEncodeObjectEx
|
||||
* CryptEncryptMessage
|
||||
* CryptEnumKeyIdentifierProperties
|
||||
* CryptEnumOIDFunction
|
||||
* CryptEnumOIDInfo
|
||||
* CryptExportPKCS8
|
||||
* CryptExportPublicKeyInfo
|
||||
* CryptExportPublicKeyInfoEx
|
||||
* CryptExportPublicKeyInfoFromBCryptKeyHandle
|
||||
* CryptFindCertificateKeyProvInfo
|
||||
* CryptFindLocalizedName
|
||||
* CryptFindOIDInfo
|
||||
* CryptFormatObject
|
||||
* CryptFreeOIDFunctionAddress
|
||||
* CryptGetAsyncParam
|
||||
* CryptGetDefaultOIDDllList
|
||||
* CryptGetDefaultOIDFunctionAddress
|
||||
* CryptGetKeyIdentifierProperty
|
||||
* CryptGetMessageCertificates
|
||||
* CryptGetMessageSignerCount
|
||||
* CryptGetOIDFunctionAddress
|
||||
* CryptGetOIDFunctionValue
|
||||
* CryptHashCertificate
|
||||
* CryptHashCertificate2
|
||||
* CryptHashMessage
|
||||
* CryptHashPublicKeyInfo
|
||||
* CryptHashToBeSigned
|
||||
* CryptImportPKCS8
|
||||
* CryptImportPublicKeyInfo
|
||||
* CryptImportPublicKeyInfoEx
|
||||
* CryptImportPublicKeyInfoEx2
|
||||
* CryptInitOIDFunctionSet
|
||||
* CryptInstallDefaultContext
|
||||
* CryptInstallOIDFunctionAddress
|
||||
* CryptLoadSip
|
||||
* CryptMemAlloc
|
||||
* CryptMemFree
|
||||
* CryptMemRealloc
|
||||
* CryptMsgCalculateEncodedLength
|
||||
* CryptMsgClose
|
||||
* CryptMsgControl
|
||||
* CryptMsgCountersign
|
||||
* CryptMsgCountersignEncoded
|
||||
* CryptMsgDuplicate
|
||||
* CryptMsgEncodeAndSignCTL
|
||||
* CryptMsgGetAndVerifySigner
|
||||
* CryptMsgGetParam
|
||||
* CryptMsgOpenToDecode
|
||||
* CryptMsgOpenToEncode
|
||||
* CryptMsgSignCTL
|
||||
* CryptMsgUpdate
|
||||
* CryptMsgVerifyCountersignatureEncoded
|
||||
* CryptMsgVerifyCountersignatureEncodedEx
|
||||
* CryptQueryObject
|
||||
* CryptRegisterDefaultOIDFunction
|
||||
* CryptRegisterOIDFunction
|
||||
* CryptRegisterOIDInfo
|
||||
* CryptRetrieveTimeStamp
|
||||
* CryptSetAsyncParam
|
||||
* CryptSetKeyIdentifierProperty
|
||||
* CryptSetOIDFunctionValue
|
||||
* CryptSignAndEncodeCertificate
|
||||
* CryptSignAndEncryptMessage
|
||||
* CryptSignCertificate
|
||||
* CryptSignMessage
|
||||
* CryptSignMessageWithKey
|
||||
* CryptSIPAddProvider
|
||||
* CryptSIPCreateIndirectData
|
||||
* CryptSIPGetCaps
|
||||
* CryptSIPGetSignedDataMsg
|
||||
* CryptSIPLoad
|
||||
* CryptSIPPutSignedDataMsg
|
||||
* CryptSIPRemoveProvider
|
||||
* CryptSIPRemoveSignedDataMsg
|
||||
* CryptSIPRetrieveSubjectGuid
|
||||
* CryptSIPRetrieveSubjectGuidForCatalogFile
|
||||
* CryptSIPVerifyIndirectData
|
||||
* CryptUninstallDefaultContext
|
||||
* CryptUnregisterDefaultOIDFunction
|
||||
* CryptUnregisterOIDFunction
|
||||
* CryptUnregisterOIDInfo
|
||||
* CryptUpdateProtectedState
|
||||
* CryptVerifyCertificateSignature
|
||||
* CryptVerifyCertificateSignatureEx
|
||||
* CryptVerifyDetachedMessageHash
|
||||
* CryptVerifyDetachedMessageSignature
|
||||
* CryptVerifyMessageHash
|
||||
* CryptVerifyMessageSignature
|
||||
* CryptVerifyMessageSignatureWithKey
|
||||
* CryptVerifyTimeStampSignature
|
||||
* DbgInitOSS
|
||||
* DbgPrintf
|
||||
* PFXExportCertStore
|
||||
* PFXExportCertStore2
|
||||
* PFXExportCertStoreEx
|
||||
* PFXImportCertStore
|
||||
* PFXIsPFXBlob
|
||||
* PFXVerifyPassword
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
static wListDictionary* g_ProtectedMemoryBlocks = nullptr;
|
||||
|
||||
BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags)
|
||||
{
|
||||
BYTE* pCipherText = nullptr;
|
||||
size_t cbOut = 0;
|
||||
size_t cbFinal = 0;
|
||||
WINPR_CIPHER_CTX* enc = nullptr;
|
||||
BYTE randomKey[256] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = nullptr;
|
||||
|
||||
if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS)
|
||||
return FALSE;
|
||||
|
||||
if (winpr_RAND(randomKey, sizeof(randomKey)) < 0)
|
||||
return FALSE;
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
{
|
||||
g_ProtectedMemoryBlocks = ListDictionary_New(TRUE);
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*)calloc(1, sizeof(WINPR_PROTECTED_MEMORY_BLOCK));
|
||||
|
||||
if (!pMemBlock)
|
||||
return FALSE;
|
||||
|
||||
pMemBlock->pData = pData;
|
||||
pMemBlock->cbData = cbData;
|
||||
pMemBlock->dwFlags = dwFlags;
|
||||
|
||||
if (winpr_RAND(pMemBlock->salt, 8) < 0)
|
||||
goto out;
|
||||
|
||||
if (winpr_Cipher_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1, pMemBlock->salt, randomKey,
|
||||
sizeof(randomKey), 4, pMemBlock->key, pMemBlock->iv) <= 0)
|
||||
goto out;
|
||||
|
||||
SecureZeroMemory(randomKey, sizeof(randomKey));
|
||||
|
||||
cbOut = pMemBlock->cbData + 16 - 1;
|
||||
pCipherText = (BYTE*)calloc(1, cbOut);
|
||||
|
||||
if (!pCipherText)
|
||||
goto out;
|
||||
|
||||
if ((enc = winpr_Cipher_NewEx(WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key,
|
||||
sizeof(pMemBlock->key), pMemBlock->iv, sizeof(pMemBlock->iv))) ==
|
||||
nullptr)
|
||||
goto out;
|
||||
if (!winpr_Cipher_Update(enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut))
|
||||
goto out;
|
||||
if (!winpr_Cipher_Final(enc, pCipherText + cbOut, &cbFinal))
|
||||
goto out;
|
||||
winpr_Cipher_Free(enc);
|
||||
|
||||
CopyMemory(pMemBlock->pData, pCipherText, pMemBlock->cbData);
|
||||
free(pCipherText);
|
||||
|
||||
return ListDictionary_Add(g_ProtectedMemoryBlocks, pData, pMemBlock);
|
||||
out:
|
||||
free(pMemBlock);
|
||||
free(pCipherText);
|
||||
winpr_Cipher_Free(enc);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CryptUnprotectMemory(LPVOID pData, WINPR_ATTR_UNUSED DWORD cbData, DWORD dwFlags)
|
||||
{
|
||||
BYTE* pPlainText = nullptr;
|
||||
size_t cbOut = 0;
|
||||
size_t cbFinal = 0;
|
||||
WINPR_CIPHER_CTX* dec = nullptr;
|
||||
WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = nullptr;
|
||||
|
||||
if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS)
|
||||
return FALSE;
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
return FALSE;
|
||||
|
||||
pMemBlock =
|
||||
(WINPR_PROTECTED_MEMORY_BLOCK*)ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData);
|
||||
|
||||
if (!pMemBlock)
|
||||
goto out;
|
||||
|
||||
cbOut = pMemBlock->cbData + 16 - 1;
|
||||
|
||||
pPlainText = (BYTE*)malloc(cbOut);
|
||||
|
||||
if (!pPlainText)
|
||||
goto out;
|
||||
|
||||
if ((dec = winpr_Cipher_NewEx(WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key,
|
||||
sizeof(pMemBlock->key), pMemBlock->iv, sizeof(pMemBlock->iv))) ==
|
||||
nullptr)
|
||||
goto out;
|
||||
if (!winpr_Cipher_Update(dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut))
|
||||
goto out;
|
||||
if (!winpr_Cipher_Final(dec, pPlainText + cbOut, &cbFinal))
|
||||
goto out;
|
||||
winpr_Cipher_Free(dec);
|
||||
|
||||
CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData);
|
||||
SecureZeroMemory(pPlainText, pMemBlock->cbData);
|
||||
free(pPlainText);
|
||||
|
||||
ListDictionary_Remove(g_ProtectedMemoryBlocks, pData);
|
||||
|
||||
free(pMemBlock);
|
||||
|
||||
return TRUE;
|
||||
|
||||
out:
|
||||
free(pPlainText);
|
||||
free(pMemBlock);
|
||||
winpr_Cipher_Free(dec);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CryptProtectData(WINPR_ATTR_UNUSED DATA_BLOB* pDataIn, WINPR_ATTR_UNUSED LPCWSTR szDataDescr,
|
||||
WINPR_ATTR_UNUSED DATA_BLOB* pOptionalEntropy,
|
||||
WINPR_ATTR_UNUSED PVOID pvReserved,
|
||||
WINPR_ATTR_UNUSED CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED DATA_BLOB* pDataOut)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptUnprotectData(WINPR_ATTR_UNUSED DATA_BLOB* pDataIn,
|
||||
WINPR_ATTR_UNUSED LPWSTR* ppszDataDescr,
|
||||
WINPR_ATTR_UNUSED DATA_BLOB* pOptionalEntropy,
|
||||
WINPR_ATTR_UNUSED PVOID pvReserved,
|
||||
WINPR_ATTR_UNUSED CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED DATA_BLOB* pDataOut)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptStringToBinaryW(WINPR_ATTR_UNUSED LPCWSTR pszString, WINPR_ATTR_UNUSED DWORD cchString,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED BYTE* pbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD* pcbBinary, WINPR_ATTR_UNUSED DWORD* pdwSkip,
|
||||
WINPR_ATTR_UNUSED DWORD* pdwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptStringToBinaryA(WINPR_ATTR_UNUSED LPCSTR pszString, WINPR_ATTR_UNUSED DWORD cchString,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED BYTE* pbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD* pcbBinary, WINPR_ATTR_UNUSED DWORD* pdwSkip,
|
||||
WINPR_ATTR_UNUSED DWORD* pdwFlags)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptBinaryToStringW(WINPR_ATTR_UNUSED CONST BYTE* pbBinary, WINPR_ATTR_UNUSED DWORD cbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED LPWSTR pszString,
|
||||
WINPR_ATTR_UNUSED DWORD* pcchString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptBinaryToStringA(WINPR_ATTR_UNUSED CONST BYTE* pbBinary, WINPR_ATTR_UNUSED DWORD cbBinary,
|
||||
WINPR_ATTR_UNUSED DWORD dwFlags, WINPR_ATTR_UNUSED LPSTR pszString,
|
||||
WINPR_ATTR_UNUSED DWORD* pcchString)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: Implement");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
43
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.h
vendored
Normal file
43
third_party/FreeRDP/winpr/libwinpr/crypto/crypto.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Cryptography API (CryptoAPI)
|
||||
*
|
||||
* Copyright 2012-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WINPR_CRYPTO_PRIVATE_H
|
||||
#define WINPR_CRYPTO_PRIVATE_H
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE* pData;
|
||||
DWORD cbData;
|
||||
DWORD dwFlags;
|
||||
BYTE key[32];
|
||||
BYTE iv[32];
|
||||
BYTE salt[8];
|
||||
} WINPR_PROTECTED_MEMORY_BLOCK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPCSTR lpszStoreProvider;
|
||||
DWORD dwMsgAndCertEncodingType;
|
||||
} WINPR_CERTSTORE;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_CRYPTO_PRIVATE_H */
|
||||
776
third_party/FreeRDP/winpr/libwinpr/crypto/hash.c
vendored
Normal file
776
third_party/FreeRDP/winpr/libwinpr/crypto/hash.c
vendored
Normal file
@@ -0,0 +1,776 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
*
|
||||
* Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/md4.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/core_names.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
#ifdef MBEDTLS_MD5_C
|
||||
#include <mbedtls/md5.h>
|
||||
#endif
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/md.h>
|
||||
#if MBEDTLS_VERSION_MAJOR < 3
|
||||
#define mbedtls_md_info_from_ctx(_ctx) (_ctx->md_info)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
#include "md4.h"
|
||||
#endif
|
||||
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
#include "md5.h"
|
||||
#include "hmac_md5.h"
|
||||
#endif
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crypto.hash")
|
||||
|
||||
/**
|
||||
* HMAC
|
||||
*/
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md)
|
||||
{
|
||||
const char* name = winpr_md_type_to_string(md);
|
||||
if (!name)
|
||||
return nullptr;
|
||||
return EVP_get_digestbyname(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
mbedtls_md_type_t winpr_mbedtls_get_md_type(int md)
|
||||
{
|
||||
mbedtls_md_type_t type = MBEDTLS_MD_NONE;
|
||||
|
||||
switch (md)
|
||||
{
|
||||
case WINPR_MD_MD5:
|
||||
type = MBEDTLS_MD_MD5;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA1:
|
||||
type = MBEDTLS_MD_SHA1;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA224:
|
||||
type = MBEDTLS_MD_SHA224;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA256:
|
||||
type = MBEDTLS_MD_SHA256;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA384:
|
||||
type = MBEDTLS_MD_SHA384;
|
||||
break;
|
||||
|
||||
case WINPR_MD_SHA512:
|
||||
type = MBEDTLS_MD_SHA512;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct hash_map
|
||||
{
|
||||
const char* name;
|
||||
WINPR_MD_TYPE md;
|
||||
};
|
||||
static const struct hash_map hashes[] = {
|
||||
{ "md2", WINPR_MD_MD2 }, { "md4", WINPR_MD_MD4 },
|
||||
{ "md5", WINPR_MD_MD5 }, { "sha1", WINPR_MD_SHA1 },
|
||||
{ "sha224", WINPR_MD_SHA224 }, { "sha256", WINPR_MD_SHA256 },
|
||||
{ "sha384", WINPR_MD_SHA384 }, { "sha512", WINPR_MD_SHA512 },
|
||||
{ "sha3_224", WINPR_MD_SHA3_224 }, { "sha3_256", WINPR_MD_SHA3_256 },
|
||||
{ "sha3_384", WINPR_MD_SHA3_384 }, { "sha3_512", WINPR_MD_SHA3_512 },
|
||||
{ "shake128", WINPR_MD_SHAKE128 }, { "shake256", WINPR_MD_SHAKE256 },
|
||||
{ nullptr, WINPR_MD_NONE }
|
||||
};
|
||||
|
||||
WINPR_MD_TYPE winpr_md_type_from_string(const char* name)
|
||||
{
|
||||
const struct hash_map* cur = hashes;
|
||||
while (cur->name)
|
||||
{
|
||||
if (_stricmp(cur->name, name) == 0)
|
||||
return cur->md;
|
||||
cur++;
|
||||
}
|
||||
return WINPR_MD_NONE;
|
||||
}
|
||||
|
||||
const char* winpr_md_type_to_string(WINPR_MD_TYPE md)
|
||||
{
|
||||
const struct hash_map* cur = hashes;
|
||||
while (cur->name)
|
||||
{
|
||||
if (cur->md == md)
|
||||
return cur->name;
|
||||
cur++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct winpr_hmac_ctx_private_st
|
||||
{
|
||||
WINPR_MD_TYPE md;
|
||||
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
WINPR_HMAC_MD5_CTX hmac_md5;
|
||||
#endif
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MAC_CTX* xhmac;
|
||||
#else
|
||||
HMAC_CTX* hmac;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t hmac;
|
||||
#endif
|
||||
};
|
||||
|
||||
WINPR_HMAC_CTX* winpr_HMAC_New(void)
|
||||
{
|
||||
WINPR_HMAC_CTX* ctx = (WINPR_HMAC_CTX*)calloc(1, sizeof(WINPR_HMAC_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
|
||||
if (!(ctx->hmac = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX))))
|
||||
goto fail;
|
||||
|
||||
HMAC_CTX_init(ctx->hmac);
|
||||
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
if (!(ctx->hmac = HMAC_CTX_new()))
|
||||
goto fail;
|
||||
#else
|
||||
EVP_MAC* emac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
|
||||
if (!emac)
|
||||
goto fail;
|
||||
ctx->xhmac = EVP_MAC_CTX_new(emac);
|
||||
EVP_MAC_free(emac);
|
||||
if (!ctx->xhmac)
|
||||
goto fail;
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_init(&ctx->hmac);
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
winpr_HMAC_Free(ctx);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const void* key, size_t keylen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
ctx->md = md;
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
hmac_md5_init(&ctx->hmac_md5, key, keylen);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
char* hash = WINPR_CAST_CONST_PTR_AWAY(winpr_md_type_to_string(md), char*);
|
||||
|
||||
if (!ctx->xhmac)
|
||||
return FALSE;
|
||||
|
||||
const char* param_name = OSSL_MAC_PARAM_DIGEST;
|
||||
const OSSL_PARAM param[] = { OSSL_PARAM_construct_utf8_string(param_name, hash, 0),
|
||||
OSSL_PARAM_construct_end() };
|
||||
|
||||
return EVP_MAC_init(ctx->xhmac, key, keylen, param) == 1;
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
|
||||
if (!evp || !hmac)
|
||||
return FALSE;
|
||||
|
||||
if (keylen > INT_MAX)
|
||||
return FALSE;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_Init_ex(hmac, key, (int)keylen, evp, nullptr); /* no return value on OpenSSL 0.9.x */
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
if (HMAC_Init_ex(hmac, key, (int)keylen, evp, nullptr) == 1)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* hmac = &ctx->hmac;
|
||||
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
|
||||
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
|
||||
|
||||
if (!md_info || !hmac)
|
||||
return FALSE;
|
||||
|
||||
if (mbedtls_md_info_from_ctx(hmac) != md_info)
|
||||
{
|
||||
mbedtls_md_free(hmac); /* can be called at any time after mbedtls_md_init */
|
||||
|
||||
if (mbedtls_md_setup(hmac, md_info, 1) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mbedtls_md_hmac_starts(hmac, key, keylen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const void* input, size_t ilen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
hmac_md5_update(&ctx->hmac_md5, input, ilen);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
return EVP_MAC_update(ctx->xhmac, input, ilen) == 1;
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_Update(hmac, input, ilen); /* no return value on OpenSSL 0.9.x */
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
if (HMAC_Update(hmac, input, ilen) == 1)
|
||||
return TRUE;
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = &ctx->hmac;
|
||||
|
||||
if (mbedtls_md_hmac_update(mdctx, input, ilen) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, void* output, size_t olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
if (olen < WINPR_MD5_DIGEST_LENGTH)
|
||||
return FALSE;
|
||||
hmac_md5_finalize(&ctx->hmac_md5, output);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
const int rc = EVP_MAC_final(ctx->xhmac, output, nullptr, olen);
|
||||
return (rc == 1);
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_Final(hmac, output, nullptr); /* no return value on OpenSSL 0.9.x */
|
||||
return TRUE;
|
||||
#else
|
||||
|
||||
if (HMAC_Final(hmac, output, nullptr) == 1)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = &ctx->hmac;
|
||||
|
||||
if (mbedtls_md_hmac_finish(mdctx, output) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MAC_CTX_free(ctx->xhmac);
|
||||
#else
|
||||
HMAC_CTX* hmac = ctx->hmac;
|
||||
|
||||
if (hmac)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
HMAC_CTX_cleanup(hmac);
|
||||
free(hmac);
|
||||
#else
|
||||
HMAC_CTX_free(hmac);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* hmac = &ctx->hmac;
|
||||
|
||||
if (hmac)
|
||||
mbedtls_md_free(hmac);
|
||||
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_HMAC(WINPR_MD_TYPE md, const void* key, size_t keylen, const void* input, size_t ilen,
|
||||
void* output, size_t olen)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
WINPR_HMAC_CTX* ctx = winpr_HMAC_New();
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
||||
if (!winpr_HMAC_Init(ctx, md, key, keylen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_HMAC_Update(ctx, input, ilen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_HMAC_Final(ctx, output, olen))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_HMAC_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic Digest API
|
||||
*/
|
||||
|
||||
struct winpr_digest_ctx_private_st
|
||||
{
|
||||
WINPR_MD_TYPE md;
|
||||
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
WINPR_MD4_CTX md4;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
WINPR_MD5_CTX md5;
|
||||
#endif
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx;
|
||||
#endif
|
||||
#if defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx;
|
||||
#endif
|
||||
};
|
||||
|
||||
WINPR_DIGEST_CTX* winpr_Digest_New(void)
|
||||
{
|
||||
WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
ctx->mdctx = EVP_MD_CTX_create();
|
||||
#else
|
||||
ctx->mdctx = EVP_MD_CTX_new();
|
||||
#endif
|
||||
if (!ctx->mdctx)
|
||||
goto fail;
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
ctx->mdctx = (mbedtls_md_context_t*)calloc(1, sizeof(mbedtls_md_context_t));
|
||||
|
||||
if (!ctx->mdctx)
|
||||
goto fail;
|
||||
|
||||
mbedtls_md_init(ctx->mdctx);
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
winpr_Digest_Free(ctx);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
if (!mdctx || !evp)
|
||||
return FALSE;
|
||||
|
||||
if (EVP_DigestInit_ex(mdctx, evp, nullptr) != 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to initialize digest %s", winpr_md_type_to_string(ctx->md));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
mbedtls_md_context_t* mdctx = ctx->mdctx;
|
||||
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
|
||||
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
|
||||
|
||||
if (!md_info)
|
||||
return FALSE;
|
||||
|
||||
if (mbedtls_md_info_from_ctx(mdctx) != md_info)
|
||||
{
|
||||
mbedtls_md_free(mdctx); /* can be called at any time after mbedtls_md_init */
|
||||
|
||||
if (mbedtls_md_setup(mdctx, md_info, 0) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mbedtls_md_starts(mdctx) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
ctx->md = md;
|
||||
switch (md)
|
||||
{
|
||||
case WINPR_MD_MD5:
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
winpr_MD5_Init(&ctx->md5);
|
||||
return TRUE;
|
||||
#elif defined(WITH_OPENSSL)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#if !defined(WITH_INTERNAL_MD5)
|
||||
if (md == WINPR_MD_MD5)
|
||||
{
|
||||
EVP_MD* md5 = EVP_MD_fetch(nullptr, "MD5", "fips=no");
|
||||
BOOL rc = winpr_Digest_Init_Internal(ctx, md5);
|
||||
EVP_MD_free(md5);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
|
||||
return winpr_Digest_Init_Internal(ctx, evp);
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
return winpr_Digest_Init_Internal(ctx, md);
|
||||
#endif
|
||||
}
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid FIPS digest %s requested", winpr_md_type_to_string(md));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
ctx->md = md;
|
||||
switch (md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
case WINPR_MD_MD4:
|
||||
winpr_MD4_Init(&ctx->md4);
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
winpr_MD5_Init(&ctx->md5);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
return winpr_Digest_Init_Internal(ctx, evp);
|
||||
#else
|
||||
return winpr_Digest_Init_Internal(ctx, md);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
case WINPR_MD_MD4:
|
||||
winpr_MD4_Update(&ctx->md4, input, ilen);
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
winpr_MD5_Update(&ctx->md5, input, ilen);
|
||||
return TRUE;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return EVP_DigestUpdate(mdctx, input, ilen) == 1;
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = ctx->mdctx;
|
||||
|
||||
if (mbedtls_md_update(mdctx, input, ilen) != 0)
|
||||
return FALSE;
|
||||
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, WINPR_ATTR_UNUSED size_t olen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
switch (ctx->md)
|
||||
{
|
||||
#if defined(WITH_INTERNAL_MD4)
|
||||
case WINPR_MD_MD4:
|
||||
if (olen < WINPR_MD4_DIGEST_LENGTH)
|
||||
return FALSE;
|
||||
winpr_MD4_Final(output, &ctx->md4);
|
||||
return TRUE;
|
||||
#endif
|
||||
#if defined(WITH_INTERNAL_MD5)
|
||||
case WINPR_MD_MD5:
|
||||
if (olen < WINPR_MD5_DIGEST_LENGTH)
|
||||
return FALSE;
|
||||
winpr_MD5_Final(output, &ctx->md5);
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return EVP_DigestFinal_ex(mdctx, output, nullptr) == 1;
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
mbedtls_md_context_t* mdctx = ctx->mdctx;
|
||||
|
||||
if (mbedtls_md_finish(mdctx, output) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md, void* key)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
|
||||
if (!evp)
|
||||
return FALSE;
|
||||
|
||||
const int rdsi = EVP_DigestSignInit(ctx->mdctx, nullptr, evp, nullptr, key);
|
||||
return (rdsi > 0);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return (EVP_DigestSignUpdate(mdctx, input, ilen) == 1);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_MD_CTX* mdctx = ctx->mdctx;
|
||||
|
||||
return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (ctx->mdctx)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
EVP_MD_CTX_destroy(ctx->mdctx);
|
||||
#else
|
||||
EVP_MD_CTX_free(ctx->mdctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
if (ctx->mdctx)
|
||||
{
|
||||
mbedtls_md_free(ctx->mdctx);
|
||||
free(ctx->mdctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
|
||||
size_t olen)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
||||
if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Update(ctx, input, ilen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Final(ctx, output, olen))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
||||
if (!winpr_Digest_Init(ctx, md))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Update(ctx, input, ilen))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Final(ctx, output, olen))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
56
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.c
vendored
Normal file
56
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.c
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hmac_md5.h"
|
||||
#include "md5.h"
|
||||
|
||||
void hmac_md5_init(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* key, size_t key_len)
|
||||
{
|
||||
const WINPR_HMAC_MD5_CTX empty = WINPR_C_ARRAY_INIT;
|
||||
unsigned char k_ipad[KEY_IOPAD_SIZE] = WINPR_C_ARRAY_INIT;
|
||||
unsigned char k_opad[KEY_IOPAD_SIZE] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
assert(ctx);
|
||||
*ctx = empty;
|
||||
|
||||
if (key_len <= KEY_IOPAD_SIZE)
|
||||
{
|
||||
memcpy(k_ipad, key, key_len);
|
||||
memcpy(k_opad, key, key_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
WINPR_MD5_CTX lctx = WINPR_C_ARRAY_INIT;
|
||||
|
||||
winpr_MD5_Init(&lctx);
|
||||
winpr_MD5_Update(&lctx, key, key_len);
|
||||
winpr_MD5_Final(k_ipad, &lctx);
|
||||
memcpy(k_opad, k_ipad, KEY_IOPAD_SIZE);
|
||||
}
|
||||
for (size_t i = 0; i < KEY_IOPAD_SIZE; i++)
|
||||
{
|
||||
k_ipad[i] ^= 0x36;
|
||||
k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
winpr_MD5_Init(&ctx->icontext);
|
||||
winpr_MD5_Update(&ctx->icontext, k_ipad, KEY_IOPAD_SIZE);
|
||||
|
||||
winpr_MD5_Init(&ctx->ocontext);
|
||||
winpr_MD5_Update(&ctx->ocontext, k_opad, KEY_IOPAD_SIZE);
|
||||
}
|
||||
|
||||
void hmac_md5_update(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* text, size_t text_len)
|
||||
{
|
||||
assert(ctx);
|
||||
winpr_MD5_Update(&ctx->icontext, text, text_len);
|
||||
}
|
||||
|
||||
void hmac_md5_finalize(WINPR_HMAC_MD5_CTX* ctx, unsigned char* hmac)
|
||||
{
|
||||
assert(ctx);
|
||||
winpr_MD5_Final(hmac, &ctx->icontext);
|
||||
|
||||
winpr_MD5_Update(&ctx->ocontext, hmac, 16);
|
||||
winpr_MD5_Final(hmac, &ctx->ocontext);
|
||||
}
|
||||
19
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.h
vendored
Normal file
19
third_party/FreeRDP/winpr/libwinpr/crypto/hmac_md5.h
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef WINPR_HMAC_MD5
|
||||
#define WINPR_HMAC_MD5
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#define KEY_IOPAD_SIZE 64
|
||||
typedef struct
|
||||
{
|
||||
WINPR_MD5_CTX icontext;
|
||||
WINPR_MD5_CTX ocontext;
|
||||
} WINPR_HMAC_MD5_CTX;
|
||||
|
||||
void hmac_md5_init(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* key, size_t key_len);
|
||||
void hmac_md5_update(WINPR_HMAC_MD5_CTX* ctx, const unsigned char* text, size_t text_len);
|
||||
void hmac_md5_finalize(WINPR_HMAC_MD5_CTX* ctx, unsigned char* hmac);
|
||||
|
||||
#endif
|
||||
271
third_party/FreeRDP/winpr/libwinpr/crypto/md4.c
vendored
Normal file
271
third_party/FreeRDP/winpr/libwinpr/crypto/md4.c
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD4 Message-Digest Algorithm (RFC 1320).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md4.h"
|
||||
|
||||
/*
|
||||
* The basic MD4 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1320 definitions, with the
|
||||
* optimization for F borrowed from Colin Plumb's MD5 implementation.
|
||||
*/
|
||||
static inline winpr_MD4_u32plus F(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
|
||||
{
|
||||
return ((z) ^ ((x) & ((y) ^ (z))));
|
||||
}
|
||||
static inline winpr_MD4_u32plus G(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
|
||||
{
|
||||
return (((x) & ((y) | (z))) | ((y) & (z)));
|
||||
}
|
||||
static inline winpr_MD4_u32plus H(winpr_MD4_u32plus x, winpr_MD4_u32plus y, winpr_MD4_u32plus z)
|
||||
{
|
||||
return ((x) ^ (y) ^ (z));
|
||||
}
|
||||
|
||||
/*
|
||||
* The MD4 transformation for all three rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, s) \
|
||||
(a) += f((b), (c), (d)) + (x); \
|
||||
(a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s))));
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them in a
|
||||
* properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned memory
|
||||
* accesses is just an optimization. Nothing will break if it fails to detect
|
||||
* a suitable architecture.
|
||||
*
|
||||
* Unfortunately, this optimization may be a C strict aliasing rules violation
|
||||
* if the caller's data buffer has effective type that cannot be aliased by
|
||||
* winpr_MD4_u32plus. In practice, this problem may occur if these MD4 routines are
|
||||
* inlined into a calling function, or with future and dangerously advanced
|
||||
* link-time optimizations. For the time being, keeping these MD4 routines in
|
||||
* their own translation unit avoids the problem.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) (*(const winpr_MD4_u32plus*)&ptr[4ULL * (n)])
|
||||
#define GET(n) SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = (winpr_MD4_u32plus)ptr[4ULL * (n)] | \
|
||||
((winpr_MD4_u32plus)ptr[4ULL * (n) + 1] << 8) | \
|
||||
((winpr_MD4_u32plus)ptr[4ULL * (n) + 2] << 16) | \
|
||||
((winpr_MD4_u32plus)ptr[4ULL * (n) + 3] << 24))
|
||||
#define GET(n) (ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update the bit
|
||||
* counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void* body(WINPR_MD4_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
const winpr_MD4_u32plus ac1 = 0x5a827999;
|
||||
const winpr_MD4_u32plus ac2 = 0x6ed9eba1;
|
||||
|
||||
const unsigned char* ptr = (const unsigned char*)data;
|
||||
|
||||
winpr_MD4_u32plus a = ctx->a;
|
||||
winpr_MD4_u32plus b = ctx->b;
|
||||
winpr_MD4_u32plus c = ctx->c;
|
||||
winpr_MD4_u32plus d = ctx->d;
|
||||
|
||||
do
|
||||
{
|
||||
const winpr_MD4_u32plus saved_a = a;
|
||||
const winpr_MD4_u32plus saved_b = b;
|
||||
const winpr_MD4_u32plus saved_c = c;
|
||||
const winpr_MD4_u32plus saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 3)
|
||||
STEP(F, d, a, b, c, SET(1), 7)
|
||||
STEP(F, c, d, a, b, SET(2), 11)
|
||||
STEP(F, b, c, d, a, SET(3), 19)
|
||||
STEP(F, a, b, c, d, SET(4), 3)
|
||||
STEP(F, d, a, b, c, SET(5), 7)
|
||||
STEP(F, c, d, a, b, SET(6), 11)
|
||||
STEP(F, b, c, d, a, SET(7), 19)
|
||||
STEP(F, a, b, c, d, SET(8), 3)
|
||||
STEP(F, d, a, b, c, SET(9), 7)
|
||||
STEP(F, c, d, a, b, SET(10), 11)
|
||||
STEP(F, b, c, d, a, SET(11), 19)
|
||||
STEP(F, a, b, c, d, SET(12), 3)
|
||||
STEP(F, d, a, b, c, SET(13), 7)
|
||||
STEP(F, c, d, a, b, SET(14), 11)
|
||||
STEP(F, b, c, d, a, SET(15), 19)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(0) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(4) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(8) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(12) + ac1, 13)
|
||||
STEP(G, a, b, c, d, GET(1) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(5) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(9) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(13) + ac1, 13)
|
||||
STEP(G, a, b, c, d, GET(2) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(6) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(10) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(14) + ac1, 13)
|
||||
STEP(G, a, b, c, d, GET(3) + ac1, 3)
|
||||
STEP(G, d, a, b, c, GET(7) + ac1, 5)
|
||||
STEP(G, c, d, a, b, GET(11) + ac1, 9)
|
||||
STEP(G, b, c, d, a, GET(15) + ac1, 13)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(0) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(8) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(4) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(12) + ac2, 15)
|
||||
STEP(H, a, b, c, d, GET(2) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(10) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(6) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(14) + ac2, 15)
|
||||
STEP(H, a, b, c, d, GET(1) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(9) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(5) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(13) + ac2, 15)
|
||||
STEP(H, a, b, c, d, GET(3) + ac2, 3)
|
||||
STEP(H, d, a, b, c, GET(11) + ac2, 9)
|
||||
STEP(H, c, d, a, b, GET(7) + ac2, 11)
|
||||
STEP(H, b, c, d, a, GET(15) + ac2, 15)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void winpr_MD4_Init(WINPR_MD4_CTX* ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
winpr_MD4_u32plus saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
size_t used = saved_lo & 0x3f;
|
||||
|
||||
if (used)
|
||||
{
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (size < available)
|
||||
{
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char*)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64)
|
||||
{
|
||||
data = body(ctx, data, size & ~(size_t)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
static inline void mdOUT(unsigned char* dst, winpr_MD4_u32plus src)
|
||||
{
|
||||
(dst)[0] = (unsigned char)(src);
|
||||
(dst)[1] = (unsigned char)((src) >> 8);
|
||||
(dst)[2] = (unsigned char)((src) >> 16);
|
||||
(dst)[3] = (unsigned char)((src) >> 24);
|
||||
}
|
||||
|
||||
void winpr_MD4_Final(unsigned char* result, WINPR_MD4_CTX* ctx)
|
||||
{
|
||||
size_t used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (available < 8)
|
||||
{
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
mdOUT(&ctx->buffer[56], ctx->lo);
|
||||
mdOUT(&ctx->buffer[60], ctx->hi);
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
mdOUT(&result[0], ctx->a);
|
||||
mdOUT(&result[4], ctx->b);
|
||||
mdOUT(&result[8], ctx->c);
|
||||
mdOUT(&result[12], ctx->d);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
46
third_party/FreeRDP/winpr/libwinpr/crypto/md4.h
vendored
Normal file
46
third_party/FreeRDP/winpr/libwinpr/crypto/md4.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD4 Message-Digest Algorithm (RFC 1320).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md4.c for more information.
|
||||
*/
|
||||
|
||||
#if !defined(WINPR_MD4_H)
|
||||
#define WINPR_MD4_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef UINT32 winpr_MD4_u32plus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
winpr_MD4_u32plus lo, hi;
|
||||
winpr_MD4_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
winpr_MD4_u32plus block[16];
|
||||
} WINPR_MD4_CTX;
|
||||
|
||||
extern void winpr_MD4_Init(WINPR_MD4_CTX* ctx);
|
||||
extern void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const void* data, size_t size);
|
||||
extern void winpr_MD4_Final(unsigned char* result, WINPR_MD4_CTX* ctx);
|
||||
|
||||
#endif
|
||||
296
third_party/FreeRDP/winpr/libwinpr/crypto/md5.c
vendored
Normal file
296
third_party/FreeRDP/winpr/libwinpr/crypto/md5.c
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
static inline winpr_MD5_u32plus F(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((z) ^ ((x) & ((y) ^ (z))));
|
||||
}
|
||||
static inline winpr_MD5_u32plus G(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((y) ^ ((z) & ((x) ^ (y))));
|
||||
}
|
||||
static inline winpr_MD5_u32plus H(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return (((x) ^ (y)) ^ (z));
|
||||
}
|
||||
static inline winpr_MD5_u32plus H2(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((x) ^ ((y) ^ (z)));
|
||||
}
|
||||
static inline winpr_MD5_u32plus I(winpr_MD5_u32plus x, winpr_MD5_u32plus y, winpr_MD5_u32plus z)
|
||||
{
|
||||
return ((y) ^ ((x) | ~(z)));
|
||||
}
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them in a
|
||||
* properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned memory
|
||||
* accesses is just an optimization. Nothing will break if it fails to detect
|
||||
* a suitable architecture.
|
||||
*
|
||||
* Unfortunately, this optimization may be a C strict aliasing rules violation
|
||||
* if the caller's data buffer has effective type that cannot be aliased by
|
||||
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
|
||||
* inlined into a calling function, or with future and dangerously advanced
|
||||
* link-time optimizations. For the time being, keeping these MD5 routines in
|
||||
* their own translation unit avoids the problem.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) (*(const winpr_MD5_u32plus*)&ptr[4ULL * (n)])
|
||||
#define GET(n) SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = (winpr_MD5_u32plus)ptr[4ULL * (n)] | \
|
||||
((winpr_MD5_u32plus)ptr[4ULL * (n) + 1] << 8) | \
|
||||
((winpr_MD5_u32plus)ptr[4ULL * (n) + 2] << 16) | \
|
||||
((winpr_MD5_u32plus)ptr[4ULL * (n) + 3] << 24))
|
||||
#define GET(n) (ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update the bit
|
||||
* counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void* body(WINPR_MD5_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
const unsigned char* ptr = (const unsigned char*)data;
|
||||
|
||||
winpr_MD5_u32plus a = ctx->a;
|
||||
winpr_MD5_u32plus b = ctx->b;
|
||||
winpr_MD5_u32plus c = ctx->c;
|
||||
winpr_MD5_u32plus d = ctx->d;
|
||||
|
||||
do
|
||||
{
|
||||
const winpr_MD5_u32plus saved_a = a;
|
||||
const winpr_MD5_u32plus saved_b = b;
|
||||
const winpr_MD5_u32plus saved_c = c;
|
||||
const winpr_MD5_u32plus saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void winpr_MD5_Init(WINPR_MD5_CTX* ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const void* data, size_t size)
|
||||
{
|
||||
winpr_MD5_u32plus saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
size_t used = saved_lo & 0x3f;
|
||||
|
||||
if (used)
|
||||
{
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (size < available)
|
||||
{
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char*)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64)
|
||||
{
|
||||
data = body(ctx, data, size & ~(size_t)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
static inline void mdOUT(unsigned char* dst, winpr_MD5_u32plus src)
|
||||
{
|
||||
(dst)[0] = (unsigned char)(src);
|
||||
(dst)[1] = (unsigned char)((src) >> 8);
|
||||
(dst)[2] = (unsigned char)((src) >> 16);
|
||||
(dst)[3] = (unsigned char)((src) >> 24);
|
||||
}
|
||||
|
||||
void winpr_MD5_Final(unsigned char* result, WINPR_MD5_CTX* ctx)
|
||||
{
|
||||
size_t used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
size_t available = 64 - used;
|
||||
|
||||
if (available < 8)
|
||||
{
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
mdOUT(&ctx->buffer[56], ctx->lo);
|
||||
mdOUT(&ctx->buffer[60], ctx->hi);
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
mdOUT(&result[0], ctx->a);
|
||||
mdOUT(&result[4], ctx->b);
|
||||
mdOUT(&result[8], ctx->c);
|
||||
mdOUT(&result[12], ctx->d);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
48
third_party/FreeRDP/winpr/libwinpr/crypto/md5.h
vendored
Normal file
48
third_party/FreeRDP/winpr/libwinpr/crypto/md5.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#if !defined(WINPR_MD5_H)
|
||||
#define WINPR_MD5_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef UINT32 winpr_MD5_u32plus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
winpr_MD5_u32plus lo, hi;
|
||||
winpr_MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
winpr_MD5_u32plus block[16];
|
||||
} WINPR_MD5_CTX;
|
||||
|
||||
extern void winpr_MD5_Init(WINPR_MD5_CTX* ctx);
|
||||
extern void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const void* data, size_t size);
|
||||
extern void winpr_MD5_Final(unsigned char* result, WINPR_MD5_CTX* ctx);
|
||||
|
||||
#endif
|
||||
83
third_party/FreeRDP/winpr/libwinpr/crypto/rand.c
vendored
Normal file
83
third_party/FreeRDP/winpr/libwinpr/crypto/rand.c
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
*
|
||||
* Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <winpr/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MBEDTLS
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#ifdef MBEDTLS_HAVEGE_C
|
||||
#include <mbedtls/havege.h>
|
||||
#endif
|
||||
#include <mbedtls/hmac_drbg.h>
|
||||
#endif
|
||||
|
||||
int winpr_RAND(void* output, size_t len)
|
||||
{
|
||||
#if defined(WITH_OPENSSL)
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
if (RAND_bytes(output, (int)len) != 1)
|
||||
return -1;
|
||||
#elif defined(WITH_MBEDTLS)
|
||||
#if defined(MBEDTLS_HAVEGE_C)
|
||||
mbedtls_havege_state hs;
|
||||
mbedtls_havege_init(&hs);
|
||||
|
||||
if (mbedtls_havege_random(&hs, output, len) != 0)
|
||||
return -1;
|
||||
|
||||
mbedtls_havege_free(&hs);
|
||||
#else
|
||||
int status;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_hmac_drbg_context hmac_drbg;
|
||||
const mbedtls_md_info_t* md_info;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_hmac_drbg_init(&hmac_drbg);
|
||||
|
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
if ((status = mbedtls_hmac_drbg_seed(&hmac_drbg, md_info, mbedtls_entropy_func, &entropy,
|
||||
nullptr, 0)) != 0)
|
||||
return -1;
|
||||
|
||||
status = mbedtls_hmac_drbg_random(&hmac_drbg, output, len);
|
||||
mbedtls_hmac_drbg_free(&hmac_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
|
||||
if (status != 0)
|
||||
return -1;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int winpr_RAND_pseudo(void* output, size_t len)
|
||||
{
|
||||
return winpr_RAND(output, len);
|
||||
}
|
||||
89
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.c
vendored
Normal file
89
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.c
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* RC4 implementation for RDP
|
||||
*
|
||||
* Copyright 2023 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2023 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include "rc4.h"
|
||||
|
||||
#define CTX_SIZE 256
|
||||
|
||||
struct winpr_int_rc4_ctx
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
BYTE s[CTX_SIZE];
|
||||
BYTE t[CTX_SIZE];
|
||||
};
|
||||
|
||||
static void swap(BYTE* p1, BYTE* p2)
|
||||
{
|
||||
BYTE t = *p1;
|
||||
*p1 = *p2;
|
||||
*p2 = t;
|
||||
}
|
||||
|
||||
winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength)
|
||||
{
|
||||
winpr_int_RC4_CTX* ctx = calloc(1, sizeof(winpr_int_RC4_CTX));
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < CTX_SIZE; i++)
|
||||
{
|
||||
ctx->s[i] = WINPR_ASSERTING_INT_CAST(BYTE, i);
|
||||
ctx->t[i] = key[i % keylength];
|
||||
}
|
||||
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < CTX_SIZE; i++)
|
||||
{
|
||||
j = (j + ctx->s[i] + ctx->t[i]) % CTX_SIZE;
|
||||
swap(&ctx->s[i], &ctx->s[j]);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
size_t t1 = ctx->i;
|
||||
size_t t2 = ctx->j;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
t1 = (t1 + 1) % CTX_SIZE;
|
||||
t2 = (t2 + ctx->s[t1]) % CTX_SIZE;
|
||||
swap(&ctx->s[t1], &ctx->s[t2]);
|
||||
|
||||
const size_t idx = ((size_t)ctx->s[t1] + ctx->s[t2]) % CTX_SIZE;
|
||||
const BYTE val = ctx->s[idx];
|
||||
const BYTE out = *input++ ^ val;
|
||||
*output++ = out;
|
||||
}
|
||||
|
||||
ctx->i = t1;
|
||||
ctx->j = t2;
|
||||
return TRUE;
|
||||
}
|
||||
35
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.h
vendored
Normal file
35
third_party/FreeRDP/winpr/libwinpr/crypto/rc4.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* RC4 implementation for RDP
|
||||
*
|
||||
* Copyright 2023 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2023 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef WINPR_RC4_H
|
||||
#define WINPR_RC4_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <winpr/winpr.h>
|
||||
|
||||
typedef struct winpr_int_rc4_ctx winpr_int_RC4_CTX;
|
||||
|
||||
void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx);
|
||||
|
||||
WINPR_ATTR_MALLOC(winpr_int_rc4_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength);
|
||||
BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output);
|
||||
|
||||
#endif
|
||||
29
third_party/FreeRDP/winpr/libwinpr/crypto/test/CMakeLists.txt
vendored
Normal file
29
third_party/FreeRDP/winpr/libwinpr/crypto/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
set(MODULE_NAME "TestCrypto")
|
||||
set(MODULE_PREFIX "TEST_CRYPTO")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS TestCryptoHash.c TestCryptoRand.c TestCryptoCipher.c TestCryptoProtectData.c
|
||||
TestCryptoProtectMemory.c TestCryptoCertEnumCertificatesInStore.c
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS})
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} secur32 crypt32 cryptui)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||
88
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c
vendored
Normal file
88
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCertEnumCertificatesInStore.c
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
//#define WITH_CRYPTUI 1
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CRYPTUI
|
||||
#include <cryptuiapi.h>
|
||||
#endif
|
||||
|
||||
int TestCryptoCertEnumCertificatesInStore(int argc, char* argv[])
|
||||
{
|
||||
int index = 0;
|
||||
DWORD status = 0;
|
||||
LPTSTR pszNameString = nullptr;
|
||||
HCERTSTORE hCertStore = nullptr;
|
||||
PCCERT_CONTEXT pCertContext = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
/**
|
||||
* System Store Locations:
|
||||
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa388136/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Requires elevated rights:
|
||||
* hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
||||
* CERT_SYSTEM_STORE_LOCAL_MACHINE, _T("Remote Desktop"));
|
||||
*/
|
||||
|
||||
hCertStore = CertOpenSystemStore(0, _T("MY"));
|
||||
// hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
|
||||
// CERT_SYSTEM_STORE_CURRENT_USER, _T("MY"));
|
||||
|
||||
if (!hCertStore)
|
||||
{
|
||||
printf("Failed to open system store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)))
|
||||
{
|
||||
status =
|
||||
CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, nullptr, 0);
|
||||
if (status == 0)
|
||||
return -1;
|
||||
|
||||
pszNameString = (LPTSTR)calloc(status, sizeof(TCHAR));
|
||||
if (!pszNameString)
|
||||
{
|
||||
printf("Unable to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr,
|
||||
pszNameString, status);
|
||||
if (status == 0)
|
||||
{
|
||||
free(pszNameString);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tprintf(_T("Certificate #%d: %s\n"), index++, pszNameString);
|
||||
|
||||
free(pszNameString);
|
||||
|
||||
#ifdef WITH_CRYPTUI
|
||||
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, nullptr, nullptr, 0,
|
||||
nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!CertCloseStore(hCertStore, 0))
|
||||
{
|
||||
printf("Failed to close system store\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
251
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCipher.c
vendored
Normal file
251
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoCipher.c
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/ssl.h>
|
||||
|
||||
static BOOL test_crypto_cipher_aes_128_cbc(BOOL ex)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE key[16] = "0123456789abcdeF";
|
||||
BYTE iv[16] = "1234567887654321";
|
||||
BYTE ibuf[1024] = WINPR_C_ARRAY_INIT;
|
||||
BYTE obuf[1024] = WINPR_C_ARRAY_INIT;
|
||||
size_t ilen = 0;
|
||||
size_t olen = 0;
|
||||
size_t xlen = 0;
|
||||
const char plaintext[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua.";
|
||||
|
||||
/* encrypt */
|
||||
|
||||
WINPR_CIPHER_CTX* ctx = nullptr;
|
||||
if (ex)
|
||||
ctx = winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_ENCRYPT, key, sizeof(key), iv,
|
||||
sizeof(iv));
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
else
|
||||
ctx = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_ENCRYPT, key, iv);
|
||||
#endif
|
||||
if (!ctx)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (encrypt) failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ilen = strnlen(plaintext, sizeof(plaintext)) + 1;
|
||||
memcpy(ibuf, plaintext, ilen);
|
||||
|
||||
ilen = ((ilen + 15) / 16) * 16;
|
||||
olen = 0;
|
||||
xlen = 0;
|
||||
|
||||
if (!winpr_Cipher_Update(ctx, ibuf, ilen, obuf, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (encrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (!winpr_Cipher_Final(ctx, obuf + xlen, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_Final (encrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (xlen != ilen)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: error, xlen (%" PRIuz ") != ilen (%" PRIuz ") (encrypt)\n",
|
||||
__func__, xlen, ilen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
winpr_Cipher_Free(ctx);
|
||||
ctx = nullptr;
|
||||
|
||||
/* decrypt */
|
||||
|
||||
if (ex)
|
||||
ctx = winpr_Cipher_NewEx(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, key, sizeof(key), iv,
|
||||
sizeof(iv));
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
else
|
||||
ctx = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, key, iv);
|
||||
|
||||
#endif
|
||||
if (!ctx)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (decrypt) failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
memcpy(ibuf, obuf, xlen);
|
||||
memset(obuf, 0, sizeof(obuf));
|
||||
|
||||
ilen = xlen;
|
||||
olen = 0;
|
||||
xlen = 0;
|
||||
|
||||
if (!winpr_Cipher_Update(ctx, ibuf, ilen, obuf, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_New (decrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (!winpr_Cipher_Final(ctx, obuf + xlen, &olen))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Cipher_Final (decrypt) failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
xlen += olen;
|
||||
|
||||
if (xlen != ilen)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: error, xlen (%" PRIuz ") != ilen (%" PRIuz ") (decrypt)\n",
|
||||
__func__, xlen, ilen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp((const char*)obuf, plaintext) != 0)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: error, decrypted data does not match plaintext\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
|
||||
out:
|
||||
winpr_Cipher_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_RC4_KEY[] = "Key";
|
||||
static const char TEST_RC4_PLAINTEXT[] = "Plaintext";
|
||||
static const char TEST_RC4_CIPHERTEXT[] = "\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3";
|
||||
|
||||
static BOOL test_crypto_cipher_rc4(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WINPR_RC4_CTX* ctx = nullptr;
|
||||
|
||||
const size_t len = strnlen(TEST_RC4_PLAINTEXT, sizeof(TEST_RC4_PLAINTEXT));
|
||||
BYTE* text = (BYTE*)calloc(1, len);
|
||||
if (!text)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: failed to allocate text buffer (len=%" PRIuz ")\n", __func__,
|
||||
len);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((ctx = winpr_RC4_New(TEST_RC4_KEY, strnlen(TEST_RC4_KEY, sizeof(TEST_RC4_KEY)))) == nullptr)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_RC4_New failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
rc = winpr_RC4_Update(ctx, len, (const BYTE*)TEST_RC4_PLAINTEXT, text);
|
||||
winpr_RC4_Free(ctx);
|
||||
if (!rc)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_RC4_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(text, TEST_RC4_CIPHERTEXT, len) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(text, len, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_RC4_CIPHERTEXT, len, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "%s: unexpected RC4 ciphertext: Actual: %s Expected: %s\n", __func__,
|
||||
actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
|
||||
out:
|
||||
free(text);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const BYTE* TEST_RAND_DATA =
|
||||
(BYTE*)"\x1F\xC2\xEE\x4C\xA3\x66\x80\xA2\xCE\xFE\x56\xB4\x9E\x08\x30\x96"
|
||||
"\x33\x6A\xA9\x6D\x36\xFD\x3C\xB7\x83\x04\x4E\x5E\xDC\x22\xCD\xF3"
|
||||
"\x48\xDF\x3A\x2A\x61\xF1\xA8\xFA\x1F\xC6\xC7\x1B\x81\xB4\xE1\x0E"
|
||||
"\xCB\xA2\xEF\xA1\x12\x4A\x83\xE5\x1D\x72\x1D\x2D\x26\xA8\x6B\xC0";
|
||||
|
||||
static const BYTE* TEST_CIPHER_KEY =
|
||||
(BYTE*)"\x9D\x7C\xC0\xA1\x94\x3B\x07\x67\x2F\xD3\x83\x10\x51\x83\x38\x0E"
|
||||
"\x1C\x74\x8C\x4E\x15\x79\xD6\xFF\xE2\xF0\x37\x7F\x8C\xD7\xD2\x13";
|
||||
|
||||
static const BYTE* TEST_CIPHER_IV =
|
||||
(BYTE*)"\xFE\xE3\x9F\xF0\xD1\x5E\x37\x0C\xAB\xAB\x9B\x04\xF3\xDB\x99\x15";
|
||||
|
||||
static BOOL test_crypto_cipher_key(void)
|
||||
{
|
||||
int status = 0;
|
||||
BYTE key[32] = WINPR_C_ARRAY_INIT;
|
||||
BYTE iv[16] = WINPR_C_ARRAY_INIT;
|
||||
BYTE salt[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
|
||||
|
||||
status = winpr_Cipher_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1, salt, TEST_RAND_DATA,
|
||||
64, 4, key, iv);
|
||||
|
||||
if (status != 32 || memcmp(key, TEST_CIPHER_KEY, 32) != 0 ||
|
||||
memcmp(iv, TEST_CIPHER_IV, 16) != 0)
|
||||
{
|
||||
char* akstr = nullptr;
|
||||
char* ekstr = nullptr;
|
||||
char* aivstr = nullptr;
|
||||
char* eivstr = nullptr;
|
||||
|
||||
akstr = winpr_BinToHexString(key, 32, 0);
|
||||
ekstr = winpr_BinToHexString(TEST_CIPHER_KEY, 32, 0);
|
||||
|
||||
aivstr = winpr_BinToHexString(iv, 16, 0);
|
||||
eivstr = winpr_BinToHexString(TEST_CIPHER_IV, 16, 0);
|
||||
|
||||
(void)fprintf(stderr, "Unexpected EVP_BytesToKey Key: Actual: %s, Expected: %s\n", akstr,
|
||||
ekstr);
|
||||
(void)fprintf(stderr, "Unexpected EVP_BytesToKey IV : Actual: %s, Expected: %s\n", aivstr,
|
||||
eivstr);
|
||||
|
||||
free(akstr);
|
||||
free(ekstr);
|
||||
free(aivstr);
|
||||
free(eivstr);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestCryptoCipher(int argc, char* argv[])
|
||||
{
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (!test_crypto_cipher_aes_128_cbc(TRUE))
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_cipher_aes_128_cbc(FALSE))
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_cipher_rc4())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_cipher_key())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
318
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoHash.c
vendored
Normal file
318
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoHash.c
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/ssl.h>
|
||||
|
||||
static const char TEST_MD5_DATA[] = "test";
|
||||
static const BYTE TEST_MD5_HASH[] =
|
||||
"\x09\x8f\x6b\xcd\x46\x21\xd3\x73\xca\xde\x4e\x83\x26\x27\xb4\xf6";
|
||||
|
||||
static BOOL test_crypto_hash_md5(void)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE hash[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_DIGEST_CTX* ctx = nullptr;
|
||||
|
||||
if (!(ctx = winpr_Digest_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (!winpr_Digest_Init(ctx, WINPR_MD_MD5))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Update(ctx, (const BYTE*)TEST_MD5_DATA,
|
||||
strnlen(TEST_MD5_DATA, sizeof(TEST_MD5_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(hash, TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected MD5 hash: Actual: %s Expected: %s\n", actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_MD4_DATA[] = "test";
|
||||
static const BYTE TEST_MD4_HASH[] =
|
||||
"\xdb\x34\x6d\x69\x1d\x7a\xcc\x4d\xc2\x62\x5d\xb1\x9f\x9e\x3f\x52";
|
||||
|
||||
static BOOL test_crypto_hash_md4(void)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE hash[WINPR_MD4_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_DIGEST_CTX* ctx = nullptr;
|
||||
|
||||
if (!(ctx = winpr_Digest_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (!winpr_Digest_Init(ctx, WINPR_MD_MD4))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Update(ctx, (const BYTE*)TEST_MD4_DATA,
|
||||
strnlen(TEST_MD4_DATA, sizeof(TEST_MD4_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (memcmp(hash, TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_MD4_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected MD4 hash: Actual: %s Expected: %s\n", actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_SHA1_DATA[] = "test";
|
||||
static const BYTE TEST_SHA1_HASH[] =
|
||||
"\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1c\x4c\x08\x73\xd3\x91\xe9\x87\x98\x2f\xbb\xd3";
|
||||
|
||||
static BOOL test_crypto_hash_sha1(void)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
BYTE hash[WINPR_SHA1_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_DIGEST_CTX* ctx = nullptr;
|
||||
|
||||
if (!(ctx = winpr_Digest_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
if (!winpr_Digest_Init(ctx, WINPR_MD_SHA1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Update(ctx, (const BYTE*)TEST_SHA1_DATA,
|
||||
strnlen(TEST_SHA1_DATA, sizeof(TEST_SHA1_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_Digest_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(hash, TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected SHA1 hash: Actual: %s Expected: %s\n", actual, expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_Digest_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_HMAC_MD5_DATA[] = "Hi There";
|
||||
static const BYTE TEST_HMAC_MD5_KEY[] =
|
||||
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
|
||||
static const BYTE TEST_HMAC_MD5_HASH[] =
|
||||
"\xb5\x79\x91\xa2\x20\x3d\x49\x2d\x73\xfb\x71\x43\xdf\xc5\x08\x28";
|
||||
|
||||
static BOOL test_crypto_hash_hmac_md5(void)
|
||||
{
|
||||
BYTE hash[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_HMAC_CTX* ctx = nullptr;
|
||||
BOOL result = FALSE;
|
||||
|
||||
if (!(ctx = winpr_HMAC_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!winpr_HMAC_Init(ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_MD5_DIGEST_LENGTH))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_MD5_DATA,
|
||||
strnlen(TEST_HMAC_MD5_DATA, sizeof(TEST_HMAC_MD5_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_MD5_DATA,
|
||||
strnlen(TEST_HMAC_MD5_DATA, sizeof(TEST_HMAC_MD5_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected HMAC-MD5 hash: Actual: %s Expected: %s\n", actual,
|
||||
expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_HMAC_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char TEST_HMAC_SHA1_DATA[] = "Hi There";
|
||||
static const BYTE TEST_HMAC_SHA1_KEY[] =
|
||||
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
|
||||
static const BYTE TEST_HMAC_SHA1_HASH[] =
|
||||
"\xab\x23\x08\x2d\xca\x0c\x75\xea\xca\x60\x09\xc0\xb8\x8c\x2d\xf4\xf4\xbf\x88\xee";
|
||||
|
||||
static BOOL test_crypto_hash_hmac_sha1(void)
|
||||
{
|
||||
BYTE hash[WINPR_SHA1_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
|
||||
WINPR_HMAC_CTX* ctx = nullptr;
|
||||
BOOL result = FALSE;
|
||||
|
||||
if (!(ctx = winpr_HMAC_New()))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_New failed\n", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!winpr_HMAC_Init(ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Init failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_SHA1_DATA,
|
||||
strnlen(TEST_HMAC_SHA1_DATA, sizeof(TEST_HMAC_SHA1_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_SHA1_DATA,
|
||||
strnlen(TEST_HMAC_SHA1_DATA, sizeof(TEST_HMAC_SHA1_DATA))))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (memcmp(hash, TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0)
|
||||
{
|
||||
char* actual = nullptr;
|
||||
char* expected = nullptr;
|
||||
|
||||
actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
expected = winpr_BinToHexString(TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE);
|
||||
|
||||
(void)fprintf(stderr, "unexpected HMAC-SHA1 hash: Actual: %s Expected: %s\n", actual,
|
||||
expected);
|
||||
|
||||
free(actual);
|
||||
free(expected);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
out:
|
||||
winpr_HMAC_Free(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
int TestCryptoHash(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (!test_crypto_hash_md5())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_md4())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_sha1())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_hmac_md5())
|
||||
return -1;
|
||||
|
||||
if (!test_crypto_hash_hmac_sha1())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectData.c
vendored
Normal file
10
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectData.c
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
int TestCryptoProtectData(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
55
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c
vendored
Normal file
55
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoProtectMemory.c
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/ssl.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
static const char* SECRET_PASSWORD_TEST = "MySecretPassword123!";
|
||||
|
||||
int TestCryptoProtectMemory(int argc, char* argv[])
|
||||
{
|
||||
UINT32 cbPlainText = 0;
|
||||
UINT32 cbCipherText = 0;
|
||||
const char* pPlainText = nullptr;
|
||||
BYTE* pCipherText = nullptr;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
pPlainText = SECRET_PASSWORD_TEST;
|
||||
cbPlainText = strlen(pPlainText) + 1;
|
||||
cbCipherText = cbPlainText +
|
||||
(CRYPTPROTECTMEMORY_BLOCK_SIZE - (cbPlainText % CRYPTPROTECTMEMORY_BLOCK_SIZE));
|
||||
printf("cbPlainText: %" PRIu32 " cbCipherText: %" PRIu32 "\n", cbPlainText, cbCipherText);
|
||||
pCipherText = (BYTE*)malloc(cbCipherText);
|
||||
if (!pCipherText)
|
||||
{
|
||||
printf("Unable to allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
CopyMemory(pCipherText, pPlainText, cbPlainText);
|
||||
ZeroMemory(&pCipherText[cbPlainText], (cbCipherText - cbPlainText));
|
||||
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
|
||||
|
||||
if (!CryptProtectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
printf("CryptProtectMemory failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("PlainText: %s (cbPlainText = %" PRIu32 ", cbCipherText = %" PRIu32 ")\n", pPlainText,
|
||||
cbPlainText, cbCipherText);
|
||||
winpr_HexDump("crypto.test", WLOG_DEBUG, pCipherText, cbCipherText);
|
||||
|
||||
if (!CryptUnprotectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
printf("CryptUnprotectMemory failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Decrypted CipherText: %s\n", pCipherText);
|
||||
SecureZeroMemory(pCipherText, cbCipherText);
|
||||
free(pCipherText);
|
||||
return 0;
|
||||
}
|
||||
27
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoRand.c
vendored
Normal file
27
third_party/FreeRDP/winpr/libwinpr/crypto/test/TestCryptoRand.c
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
int TestCryptoRand(int argc, char* argv[])
|
||||
{
|
||||
char* str = nullptr;
|
||||
BYTE rnd[16] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (winpr_RAND(rnd, sizeof(rnd)) < 0)
|
||||
return -1;
|
||||
|
||||
str = winpr_BinToHexString(rnd, sizeof(rnd), FALSE);
|
||||
// (void)fprintf(stderr, "Rand: %s\n", str);
|
||||
free(str);
|
||||
|
||||
if (memcmp(rnd, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user