Blame winpr/libwinpr/crypto/cipher.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crypto.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_OPENSSL
Packit 1fb8d4
#include <openssl/aes.h>
Packit 1fb8d4
#include <openssl/rc4.h>
Packit 1fb8d4
#include <openssl/des.h>
Packit 1fb8d4
#include <openssl/evp.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_MBEDTLS
Packit 1fb8d4
#include <mbedtls/md.h>
Packit 1fb8d4
#include <mbedtls/aes.h>
Packit 1fb8d4
#include <mbedtls/arc4.h>
Packit 1fb8d4
#include <mbedtls/des.h>
Packit 1fb8d4
#include <mbedtls/cipher.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * RC4
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_RC4_CTX* ctx = NULL;
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	const EVP_CIPHER* evp = NULL;
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (!key || (keylen == 0))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
Packit 1fb8d4
	if (!(ctx = (WINPR_RC4_CTX*) EVP_CIPHER_CTX_new()))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	evp = EVP_rc4();
Packit 1fb8d4
Packit 1fb8d4
	if (!evp)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*) ctx);
Packit 1fb8d4
	EVP_EncryptInit_ex((EVP_CIPHER_CTX*) ctx, evp, NULL, NULL, NULL);
Packit 1fb8d4
	/* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
Packit 1fb8d4
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
Packit 1fb8d4
Packit 1fb8d4
	if (override_fips == TRUE)
Packit 1fb8d4
		EVP_CIPHER_CTX_set_flags((EVP_CIPHER_CTX*) ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	EVP_CIPHER_CTX_set_key_length((EVP_CIPHER_CTX*) ctx, keylen);
Packit 1fb8d4
	EVP_EncryptInit_ex((EVP_CIPHER_CTX*) ctx, NULL, NULL, key, NULL);
Packit 1fb8d4
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
Packit 1fb8d4
Packit 1fb8d4
	if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(mbedtls_arc4_context))))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	mbedtls_arc4_init((mbedtls_arc4_context*) ctx);
Packit 1fb8d4
	mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, (unsigned int) keylen);
Packit 1fb8d4
#endif
Packit 1fb8d4
	return ctx;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const BYTE* key, size_t keylen)
Packit 1fb8d4
{
Packit 1fb8d4
	return winpr_RC4_New_Internal(key, keylen, TRUE);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen)
Packit 1fb8d4
{
Packit 1fb8d4
	return winpr_RC4_New_Internal(key, keylen, FALSE);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	int outputLength;
Packit 1fb8d4
	EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outputLength, input, length);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) == 0)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!ctx)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*) ctx);
Packit 1fb8d4
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
Packit 1fb8d4
	mbedtls_arc4_free((mbedtls_arc4_context*) ctx);
Packit 1fb8d4
	free(ctx);
Packit 1fb8d4
#endif
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Generic Cipher API
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_OPENSSL
Packit 1fb8d4
extern const EVP_MD* winpr_openssl_get_evp_md(int md);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#ifdef WITH_MBEDTLS
Packit 1fb8d4
extern mbedtls_md_type_t winpr_mbedtls_get_md_type(int md);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
const EVP_CIPHER* winpr_openssl_get_evp_cipher(int cipher)
Packit 1fb8d4
{
Packit 1fb8d4
	const EVP_CIPHER* evp = NULL;
Packit 1fb8d4
Packit 1fb8d4
	switch (cipher)
Packit 1fb8d4
	{
Packit 1fb8d4
		case WINPR_CIPHER_NULL:
Packit 1fb8d4
			evp = EVP_enc_null();
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-128-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-192-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-256-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-128-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-192-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-256-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CFB128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-128-cfb128");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CFB128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-192-cfb128");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CFB128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-256-cfb128");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-128-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-192-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-256-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_GCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-128-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_GCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-192-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_GCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-256-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-128-ccm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-192-ccm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("aes-256-ccm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-128-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-192-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-256-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-128-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-192-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-256-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CFB128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-128-cfb128");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CFB128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-192-cfb128");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CFB128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-256-cfb128");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-128-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-192-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-256-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_GCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-128-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_GCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-192-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_GCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-256-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-128-ccm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-192-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CCM:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("camellia-256-gcm");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("des-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("des-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("des-ede-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("des-ede-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE3_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("des-ede3-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE3_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("des-ede3-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_ARC4_128:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("rc4");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_ECB:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("blowfish-ecb");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_CBC:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("blowfish-cbc");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_CFB64:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("blowfish-cfb64");
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_CTR:
Packit 1fb8d4
			evp = EVP_get_cipherbyname("blowfish-ctr");
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return evp;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#elif defined(WITH_MBEDTLS)
Packit 1fb8d4
mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher)
Packit 1fb8d4
{
Packit 1fb8d4
	mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
Packit 1fb8d4
Packit 1fb8d4
	switch (cipher)
Packit 1fb8d4
	{
Packit 1fb8d4
		case WINPR_CIPHER_NONE:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_NONE;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_NULL:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_NULL;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_128_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_192_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_256_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_128_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_192_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_256_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CFB128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_128_CFB128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CFB128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_192_CFB128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CFB128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_256_CFB128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_128_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_192_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_256_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_GCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_128_GCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_GCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_192_GCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_GCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_256_GCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_128_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_192_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_256_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_128_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_192_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_256_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CFB128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_128_CFB128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CFB128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_192_CFB128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CFB128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_256_CFB128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_128_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_192_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_256_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_GCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_128_GCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_GCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_192_GCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_GCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_256_GCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_DES_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_DES_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_DES_EDE_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_DES_EDE_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE3_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_DES_EDE3_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_DES_EDE3_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_DES_EDE3_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_ECB:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_BLOWFISH_ECB;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_CBC:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_BLOWFISH_CBC;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_CFB64:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_BLOWFISH_CFB64;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_BLOWFISH_CTR:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_BLOWFISH_CTR;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_ARC4_128:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_ARC4_128;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_128_CCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_128_CCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_192_CCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_192_CCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_AES_256_CCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_AES_256_CCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_128_CCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_128_CCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_192_CCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_192_CCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case WINPR_CIPHER_CAMELLIA_256_CCM:
Packit 1fb8d4
			type = MBEDTLS_CIPHER_CAMELLIA_256_CCM;
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return type;
Packit 1fb8d4
}
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_CIPHER_CTX* ctx = NULL;
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	int operation;
Packit 1fb8d4
	const EVP_CIPHER* evp;
Packit 1fb8d4
	EVP_CIPHER_CTX* octx;
Packit 1fb8d4
Packit 1fb8d4
	if (!(evp = winpr_openssl_get_evp_cipher(cipher)))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!(octx = EVP_CIPHER_CTX_new()))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	operation = (op == WINPR_ENCRYPT) ? 1 : 0;
Packit 1fb8d4
Packit 1fb8d4
	if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1)
Packit 1fb8d4
	{
Packit 1fb8d4
		EVP_CIPHER_CTX_free(octx);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	EVP_CIPHER_CTX_set_padding(octx, 0);
Packit 1fb8d4
	ctx = (WINPR_CIPHER_CTX*) octx;
Packit 1fb8d4
#elif defined(WITH_MBEDTLS)
Packit 1fb8d4
	int key_bitlen;
Packit 1fb8d4
	mbedtls_operation_t operation;
Packit 1fb8d4
	mbedtls_cipher_context_t* mctx;
Packit 1fb8d4
	mbedtls_cipher_type_t cipher_type = winpr_mbedtls_get_cipher_type(cipher);
Packit 1fb8d4
	const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(cipher_type);
Packit 1fb8d4
Packit 1fb8d4
	if (!cipher_info)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!(mctx = (mbedtls_cipher_context_t*) calloc(1, sizeof(mbedtls_cipher_context_t))))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
Packit 1fb8d4
	mbedtls_cipher_init(mctx);
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_cipher_setup(mctx, cipher_info) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(mctx);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	key_bitlen = mbedtls_cipher_get_key_bitlen(mctx);
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_cipher_setkey(mctx, key, key_bitlen, operation) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		mbedtls_cipher_free(mctx);
Packit 1fb8d4
		free(mctx);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_cipher_set_padding_mode(mctx, MBEDTLS_PADDING_NONE) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		mbedtls_cipher_free(mctx);
Packit 1fb8d4
		free(mctx);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ctx = (WINPR_CIPHER_CTX*) mctx;
Packit 1fb8d4
#endif
Packit 1fb8d4
	return ctx;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output,
Packit 1fb8d4
                         size_t* olen)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	int outl = (int) * olen;
Packit 1fb8d4
Packit 1fb8d4
	if (EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outl, input, ilen) == 1)
Packit 1fb8d4
	{
Packit 1fb8d4
		*olen = (size_t) outl;
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#elif defined(WITH_MBEDTLS)
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_cipher_update((mbedtls_cipher_context_t*) ctx, input, ilen, output, olen) == 0)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	int outl = (int) * olen;
Packit 1fb8d4
Packit 1fb8d4
	if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) == 1)
Packit 1fb8d4
	{
Packit 1fb8d4
		*olen = (size_t) outl;
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#elif defined(WITH_MBEDTLS)
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) == 0)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!ctx)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*) ctx);
Packit 1fb8d4
#elif defined(WITH_MBEDTLS)
Packit 1fb8d4
	mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx);
Packit 1fb8d4
	free(ctx);
Packit 1fb8d4
#endif
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Key Generation
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal,
Packit 1fb8d4
                            int count, BYTE* key, BYTE* iv)
Packit 1fb8d4
{
Packit 1fb8d4
	/**
Packit 1fb8d4
	 * Key and IV generation compatible with OpenSSL EVP_BytesToKey():
Packit 1fb8d4
	 * https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
Packit 1fb8d4
	 */
Packit 1fb8d4
#if defined(WITH_OPENSSL)
Packit 1fb8d4
	const EVP_MD* evp_md;
Packit 1fb8d4
	const EVP_CIPHER* evp_cipher;
Packit 1fb8d4
	evp_md = winpr_openssl_get_evp_md(md);
Packit 1fb8d4
	evp_cipher = winpr_openssl_get_evp_cipher(cipher);
Packit 1fb8d4
	return EVP_BytesToKey(evp_cipher, evp_md, salt, data, datal, count, key, iv);
Packit 1fb8d4
#elif defined(WITH_MBEDTLS)
Packit 1fb8d4
	int rv = 0;
Packit 1fb8d4
	BYTE md_buf[64];
Packit 1fb8d4
	int niv, nkey, addmd = 0;
Packit 1fb8d4
	unsigned int mds = 0, i;
Packit 1fb8d4
	mbedtls_md_context_t ctx;
Packit 1fb8d4
	const mbedtls_md_info_t* md_info;
Packit 1fb8d4
	mbedtls_cipher_type_t cipher_type;
Packit 1fb8d4
	const mbedtls_cipher_info_t* cipher_info;
Packit 1fb8d4
	mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
Packit 1fb8d4
	md_info = mbedtls_md_info_from_type(md_type);
Packit 1fb8d4
	cipher_type = winpr_mbedtls_get_cipher_type(cipher);
Packit 1fb8d4
	cipher_info = mbedtls_cipher_info_from_type(cipher_type);
Packit 1fb8d4
	nkey = cipher_info->key_bitlen / 8;
Packit 1fb8d4
	niv = cipher_info->iv_size;
Packit 1fb8d4
Packit 1fb8d4
	if ((nkey > 64) || (niv > 64))
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!data)
Packit 1fb8d4
		return nkey;
Packit 1fb8d4
Packit 1fb8d4
	mbedtls_md_init(&ctx;;
Packit 1fb8d4
Packit 1fb8d4
	if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
Packit 1fb8d4
		goto err;
Packit 1fb8d4
Packit 1fb8d4
	while (1)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (mbedtls_md_starts(&ctx) != 0)
Packit 1fb8d4
			goto err;
Packit 1fb8d4
Packit 1fb8d4
		if (addmd++)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
Packit 1fb8d4
				goto err;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (mbedtls_md_update(&ctx, data, datal) != 0)
Packit 1fb8d4
			goto err;
Packit 1fb8d4
Packit 1fb8d4
		if (salt)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (mbedtls_md_update(&ctx, salt, 8) != 0)
Packit 1fb8d4
				goto err;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (mbedtls_md_finish(&ctx, md_buf) != 0)
Packit 1fb8d4
			goto err;
Packit 1fb8d4
Packit 1fb8d4
		mds = mbedtls_md_get_size(md_info);
Packit 1fb8d4
Packit 1fb8d4
		for (i = 1; i < (unsigned int) count; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (mbedtls_md_starts(&ctx) != 0)
Packit 1fb8d4
				goto err;
Packit 1fb8d4
Packit 1fb8d4
			if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
Packit 1fb8d4
				goto err;
Packit 1fb8d4
Packit 1fb8d4
			if (mbedtls_md_finish(&ctx, md_buf) != 0)
Packit 1fb8d4
				goto err;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		i = 0;
Packit 1fb8d4
Packit 1fb8d4
		if (nkey)
Packit 1fb8d4
		{
Packit 1fb8d4
			while (1)
Packit 1fb8d4
			{
Packit 1fb8d4
				if (nkey == 0)
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				if (i == mds)
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				if (key)
Packit 1fb8d4
					*(key++) = md_buf[i];
Packit 1fb8d4
Packit 1fb8d4
				nkey--;
Packit 1fb8d4
				i++;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (niv && (i != mds))
Packit 1fb8d4
		{
Packit 1fb8d4
			while (1)
Packit 1fb8d4
			{
Packit 1fb8d4
				if (niv == 0)
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				if (i == mds)
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				if (iv)
Packit 1fb8d4
					*(iv++) = md_buf[i];
Packit 1fb8d4
Packit 1fb8d4
				niv--;
Packit 1fb8d4
				i++;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if ((nkey == 0) && (niv == 0))
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	rv = cipher_info->key_bitlen / 8;
Packit 1fb8d4
err:
Packit 1fb8d4
	mbedtls_md_free(&ctx;;
Packit 1fb8d4
	SecureZeroMemory(md_buf, 64);
Packit 1fb8d4
	return rv;
Packit 1fb8d4
#endif
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}