Blame libfreerdp/core/certificate.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Certificate Handling
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011 Jiten Pathy
Packit 1fb8d4
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2015 Thincast Technologies GmbH
Packit 1fb8d4
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.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 <errno.h>
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
#include <string.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/wtypes.h>
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/crypto.h>
Packit 1fb8d4
Packit 1fb8d4
#include <openssl/pem.h>
Packit 1fb8d4
#include <openssl/rsa.h>
Packit 1fb8d4
Packit 1fb8d4
#include "certificate.h"
Packit 1fb8d4
#include "../crypto/opensslcompat.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG "com.freerdp.core"
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 *
Packit 1fb8d4
 * X.509 Certificate Structure
Packit 1fb8d4
 *
Packit 1fb8d4
 * Certificate ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	tbsCertificate			TBSCertificate,
Packit 1fb8d4
 * 	signatureAlgorithm		AlgorithmIdentifier,
Packit 1fb8d4
 * 	signatureValue			BIT_STRING
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * TBSCertificate ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	version			[0]	EXPLICIT Version DEFAULT v1,
Packit 1fb8d4
 * 	serialNumber			CertificateSerialNumber,
Packit 1fb8d4
 * 	signature			AlgorithmIdentifier,
Packit 1fb8d4
 * 	issuer				Name,
Packit 1fb8d4
 * 	validity			Validity,
Packit 1fb8d4
 * 	subject				Name,
Packit 1fb8d4
 * 	subjectPublicKeyInfo		SubjectPublicKeyInfo,
Packit 1fb8d4
 * 	issuerUniqueID		[1]	IMPLICIT UniqueIdentifier OPTIONAL,
Packit 1fb8d4
 * 	subjectUniqueId		[2]	IMPLICIT UniqueIdentifier OPTIONAL,
Packit 1fb8d4
 * 	extensions		[3]	EXPLICIT Extensions OPTIONAL
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
Packit 1fb8d4
 *
Packit 1fb8d4
 * CertificateSerialNumber ::= INTEGER
Packit 1fb8d4
 *
Packit 1fb8d4
 * AlgorithmIdentifier ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	algorithm			OBJECT_IDENTIFIER,
Packit 1fb8d4
 * 	parameters			ANY DEFINED BY algorithm OPTIONAL
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * Name ::= CHOICE { RDNSequence }
Packit 1fb8d4
 *
Packit 1fb8d4
 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
Packit 1fb8d4
 *
Packit 1fb8d4
 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
Packit 1fb8d4
 *
Packit 1fb8d4
 * AttributeTypeAndValue ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	type				AttributeType,
Packit 1fb8d4
 * 	value				AttributeValue
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * AttributeType ::= OBJECT_IDENTIFIER
Packit 1fb8d4
 *
Packit 1fb8d4
 * AttributeValue ::= ANY DEFINED BY AttributeType
Packit 1fb8d4
 *
Packit 1fb8d4
 * Validity ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	notBefore			Time,
Packit 1fb8d4
 * 	notAfter			Time
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * Time ::= CHOICE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	utcTime				UTCTime,
Packit 1fb8d4
 * 	generalTime			GeneralizedTime
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * UniqueIdentifier ::= BIT_STRING
Packit 1fb8d4
 *
Packit 1fb8d4
 * SubjectPublicKeyInfo ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	algorithm			AlgorithmIdentifier,
Packit 1fb8d4
 * 	subjectPublicKey		BIT_STRING
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * RSAPublicKey ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	modulus				INTEGER
Packit 1fb8d4
 * 	publicExponent			INTEGER
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Packit 1fb8d4
 *
Packit 1fb8d4
 * Extension ::= SEQUENCE
Packit 1fb8d4
 * {
Packit 1fb8d4
 * 	extnID				OBJECT_IDENTIFIER
Packit 1fb8d4
 * 	critical			BOOLEAN DEFAULT FALSE,
Packit 1fb8d4
 * 	extnValue			OCTET_STRING
Packit 1fb8d4
 * }
Packit 1fb8d4
 *
Packit 1fb8d4
 */
Packit 1fb8d4
Packit Service 5a9772
static const char* certificate_read_errors[] = { "Certificate tag",
Packit Service 5a9772
	                                             "TBSCertificate",
Packit Service 5a9772
	                                             "Explicit Contextual Tag [0]",
Packit Service 5a9772
	                                             "version",
Packit Service 5a9772
	                                             "CertificateSerialNumber",
Packit Service 5a9772
	                                             "AlgorithmIdentifier",
Packit Service 5a9772
	                                             "Issuer Name",
Packit Service 5a9772
	                                             "Validity",
Packit Service 5a9772
	                                             "Subject Name",
Packit Service 5a9772
	                                             "SubjectPublicKeyInfo Tag",
Packit Service 5a9772
	                                             "subjectPublicKeyInfo::AlgorithmIdentifier",
Packit Service 5a9772
	                                             "subjectPublicKeyInfo::subjectPublicKey",
Packit Service 5a9772
	                                             "RSAPublicKey Tag",
Packit Service 5a9772
	                                             "modulusLength",
Packit Service 5a9772
	                                             "zero padding",
Packit Service 5a9772
	                                             "modulusLength",
Packit Service 5a9772
	                                             "modulus",
Packit Service 5a9772
	                                             "publicExponent length",
Packit Service 5a9772
	                                             "publicExponent" };
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Read X.509 Certificate
Packit 1fb8d4
 * @param certificate certificate module
Packit 1fb8d4
 * @param cert X.509 certificate
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info)
Packit 1fb8d4
{
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	size_t length;
Packit 1fb8d4
	BYTE padding;
Packit 1fb8d4
	UINT32 version;
Packit 1fb8d4
	size_t modulus_length;
Packit 1fb8d4
	size_t exponent_length;
Packit 1fb8d4
	int error = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!cert || !info)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	memset(info, 0, sizeof(rdpCertInfo));
Packit 1fb8d4
	s = Stream_New(cert->data, cert->length);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	info->Modulus = 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit Service 5a9772
	if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	if (!ber_read_integer(s, &version)) /* version (INTEGER) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
	version++;
Packit 1fb8d4
Packit 1fb8d4
	/* serialNumber */
Packit 1fb8d4
	if (!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* signature */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length) ||
Packit 1fb8d4
	    !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* issuer */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* validity */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* subject */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* subjectPublicKeyInfo */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* subjectPublicKeyInfo::AlgorithmIdentifier */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length) ||
Packit 1fb8d4
	    !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* subjectPublicKeyInfo::subjectPublicKey */
Packit 1fb8d4
	if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* RSAPublicKey (SEQUENCE) */
Packit 1fb8d4
	if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	/* skip zero padding, if any */
Packit 1fb8d4
	do
Packit 1fb8d4
	{
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 1)
Packit 1fb8d4
			goto error1;
Packit 1fb8d4
Packit 1fb8d4
		Stream_Peek_UINT8(s, padding);
Packit 1fb8d4
Packit 1fb8d4
		if (padding == 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!Stream_SafeSeek(s, 1))
Packit 1fb8d4
				goto error1;
Packit 1fb8d4
Packit 1fb8d4
			modulus_length--;
Packit 1fb8d4
		}
Packit Service 5a9772
	} while (padding == 0);
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit Service 5a9772
	if (modulus_length > UINT32_MAX)
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit Service 5a9772
	if ((Stream_GetRemainingLength(s)) < modulus_length)
Packit Service 5a9772
		goto error1;
Packit Service 5a9772
Packit Service 5a9772
	info->ModulusLength = (UINT32)modulus_length;
Packit Service 5a9772
	info->Modulus = (BYTE*)malloc(info->ModulusLength);
Packit 1fb8d4
Packit 1fb8d4
	if (!info->Modulus)
Packit 1fb8d4
		goto error1;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, info->Modulus, info->ModulusLength);
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit 1fb8d4
	if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */
Packit 1fb8d4
		goto error2;
Packit 1fb8d4
Packit 1fb8d4
	error++;
Packit 1fb8d4
Packit Service 5a9772
	if (((Stream_GetRemainingLength(s)) < exponent_length) || (exponent_length > 4))
Packit 1fb8d4
		goto error2;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, &info->exponent[4 - exponent_length], exponent_length);
Packit 1fb8d4
	crypto_reverse(info->Modulus, info->ModulusLength);
Packit 1fb8d4
	crypto_reverse(info->exponent, 4);
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
error2:
Packit 1fb8d4
	free(info->Modulus);
Packit 1fb8d4
	info->Modulus = 0;
Packit 1fb8d4
error1:
Packit 1fb8d4
	WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d",
Packit 1fb8d4
	         certificate_read_errors[error], error);
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Instantiate new X.509 Certificate Chain.
Packit 1fb8d4
 * @param count certificate chain count
Packit 1fb8d4
 * @return new X.509 certificate chain
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static rdpX509CertChain* certificate_new_x509_certificate_chain(UINT32 count)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpX509CertChain* x509_cert_chain;
Packit Service 5a9772
	x509_cert_chain = (rdpX509CertChain*)malloc(sizeof(rdpX509CertChain));
Packit 1fb8d4
Packit 1fb8d4
	if (!x509_cert_chain)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	x509_cert_chain->count = count;
Packit Service 5a9772
	x509_cert_chain->array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
Packit 1fb8d4
Packit 1fb8d4
	if (!x509_cert_chain->array)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(x509_cert_chain);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return x509_cert_chain;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Free X.509 Certificate Chain.
Packit 1fb8d4
 * @param x509_cert_chain X.509 certificate chain to be freed
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
Packit 1fb8d4
{
Packit 1fb8d4
	int i;
Packit 1fb8d4
Packit 1fb8d4
	if (!x509_cert_chain)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < (int)x509_cert_chain->count; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(x509_cert_chain->array[i].data);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(x509_cert_chain->array);
Packit 1fb8d4
	free(x509_cert_chain);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL certificate_process_server_public_key(rdpCertificate* certificate, wStream* s,
Packit Service 5a9772
                                                  UINT32 length)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE magic[4];
Packit 1fb8d4
	UINT32 keylen;
Packit 1fb8d4
	UINT32 bitlen;
Packit 1fb8d4
	UINT32 datalen;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 20)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, magic, 4);
Packit 1fb8d4
Packit 1fb8d4
	if (memcmp(magic, "RSA1", 4) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "magic error");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT32(s, keylen);
Packit 1fb8d4
	Stream_Read_UINT32(s, bitlen);
Packit 1fb8d4
	Stream_Read_UINT32(s, datalen);
Packit 1fb8d4
	Stream_Read(s, certificate->cert_info.exponent, 4);
Packit 1fb8d4
Packit 1fb8d4
	if ((keylen <= 8) || (Stream_GetRemainingLength(s) < keylen))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	certificate->cert_info.ModulusLength = keylen - 8;
Packit 1fb8d4
	certificate->cert_info.Modulus = malloc(certificate->cert_info.ModulusLength);
Packit 1fb8d4
Packit 1fb8d4
	if (!certificate->cert_info.Modulus)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read(s, certificate->cert_info.Modulus, certificate->cert_info.ModulusLength);
Packit 1fb8d4
	Stream_Seek(s, 8); /* 8 bytes of zero padding */
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
Packit Service 5a9772
                                                        const BYTE* sigdata, size_t sigdatalen,
Packit Service 5a9772
                                                        wStream* s, UINT32 siglen)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(CERT_VALIDATE_PADDING) || defined(CERT_VALIDATE_RSA)
Packit 1fb8d4
	size_t i, sum;
Packit 1fb8d4
#endif
Packit 1fb8d4
#if defined(CERT_VALIDATE_RSA)
Packit 1fb8d4
	BYTE sig[TSSK_KEY_LENGTH];
Packit 1fb8d4
#endif
Packit 1fb8d4
	BYTE encsig[TSSK_KEY_LENGTH + 8];
Packit 1fb8d4
#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
Packit 1fb8d4
	BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
Packit 1fb8d4
#endif
Packit 1fb8d4
#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
Packit 1fb8d4
	(void)sigdata;
Packit 1fb8d4
	(void)sigdatalen;
Packit 1fb8d4
#endif
Packit 1fb8d4
	(void)certificate;
Packit Service 5a9772
	/* Do not bother with validation of server proprietary certificate. The use of MD5 here is not
Packit Service 5a9772
	 * allowed under FIPS. Since the validation is not protecting against anything since the
Packit Service 5a9772
	 * private/public keys are well known and documented in MS-RDPBCGR section 5.3.3.1, we are not
Packit Service 5a9772
	 * gaining any security by using MD5 for signature comparison. Rather then use MD5
Packit Service 5a9772
	 * here we just dont do the validation to avoid its use. Historically, freerdp has been ignoring
Packit Service 5a9772
	 * a failed validation anyways. */
Packit 1fb8d4
#if defined(CERT_VALIDATE_MD5)
Packit 1fb8d4
Packit 1fb8d4
	if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	Stream_Read(s, encsig, siglen);
Packit 1fb8d4
Packit 1fb8d4
	if (siglen < 8)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
		/* Last 8 bytes shall be all zero. */
Packit 1fb8d4
#if defined(CERT_VALIDATE_PADDING)
Packit 1fb8d4
Packit 1fb8d4
	for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++)
Packit 1fb8d4
		sum += encsig[i];
Packit 1fb8d4
Packit 1fb8d4
	if (sum != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "invalid signature");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
#if defined(CERT_VALIDATE_RSA)
Packit 1fb8d4
Packit 1fb8d4
	if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
Packit 1fb8d4
	                              sig) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "invalid RSA decrypt");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Verify signature. */
Packit 1fb8d4
	/* Do not bother with validation of server proprietary certificate as described above. */
Packit 1fb8d4
#if defined(CERT_VALIDATE_MD5)
Packit 1fb8d4
Packit 1fb8d4
	if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "invalid signature");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	/*
Packit 1fb8d4
	 * Verify rest of decrypted data:
Packit 1fb8d4
	 * The 17th byte is 0x00.
Packit 1fb8d4
	 * The 18th through 62nd bytes are each 0xFF.
Packit 1fb8d4
	 * The 63rd byte is 0x01.
Packit 1fb8d4
	 */
Packit 1fb8d4
Packit 1fb8d4
	for (sum = 0, i = 17; i < 62; i++)
Packit 1fb8d4
		sum += sig[i];
Packit 1fb8d4
Packit 1fb8d4
	if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "invalid signature");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Read a Server Proprietary Certificate.\n
Packit 1fb8d4
 * @param certificate certificate module
Packit 1fb8d4
 * @param s stream
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 dwSigAlgId;
Packit 1fb8d4
	UINT32 dwKeyAlgId;
Packit 1fb8d4
	UINT16 wPublicKeyBlobType;
Packit 1fb8d4
	UINT16 wPublicKeyBlobLen;
Packit 1fb8d4
	UINT16 wSignatureBlobType;
Packit 1fb8d4
	UINT16 wSignatureBlobLen;
Packit 1fb8d4
	BYTE* sigdata;
Packit 1fb8d4
	size_t sigdatalen;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 12)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	/* -4, because we need to include dwVersion */
Packit 1fb8d4
	sigdata = Stream_Pointer(s) - 4;
Packit 1fb8d4
	Stream_Read_UINT32(s, dwSigAlgId);
Packit 1fb8d4
	Stream_Read_UINT32(s, dwKeyAlgId);
Packit 1fb8d4
Packit 1fb8d4
	if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG,
Packit Service 5a9772
		         "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
Packit Service 5a9772
		         " dwKeyAlgId=%" PRIu32 "",
Packit 1fb8d4
		         dwSigAlgId, dwKeyAlgId);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT16(s, wPublicKeyBlobType);
Packit 1fb8d4
Packit 1fb8d4
	if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "unsupported public key blob type %" PRIu16 "", wPublicKeyBlobType);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT16(s, wPublicKeyBlobLen);
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < wPublicKeyBlobLen)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "not enough bytes for public key(len=%" PRIu16 ")", wPublicKeyBlobLen);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "error in server public key");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	sigdatalen = Stream_Pointer(s) - sigdata;
Packit 1fb8d4
	Stream_Read_UINT16(s, wSignatureBlobType);
Packit 1fb8d4
Packit 1fb8d4
	if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "unsupported blob signature %" PRIu16 "", wSignatureBlobType);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT16(s, wSignatureBlobLen);
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < wSignatureBlobLen)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "not enough bytes for signature(len=%" PRIu16 ")", wSignatureBlobLen);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (wSignatureBlobLen != 72)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "invalid signature length (got %" PRIu16 ", expected 72)", wSignatureBlobLen);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
Packit Service 5a9772
	                                                 wSignatureBlobLen))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "unable to parse server public signature");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Read an X.509 Certificate Chain.\n
Packit 1fb8d4
 * @param certificate certificate module
Packit 1fb8d4
 * @param s stream
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 i;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
	UINT32 certLength;
Packit 1fb8d4
	UINT32 numCertBlobs;
Packit 1fb8d4
	DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
Packit 1fb8d4
	certificate->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
Packit 1fb8d4
Packit 1fb8d4
	if (!certificate->x509_cert_chain)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; i < numCertBlobs; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read_UINT32(s, certLength);
Packit 1fb8d4
Packit 1fb8d4
		if (Stream_GetRemainingLength(s) < certLength)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit Service 5a9772
		DEBUG_CERTIFICATE("X.509 Certificate #%d, length:%" PRIu32 "", i + 1, certLength);
Packit Service 5a9772
		certificate->x509_cert_chain->array[i].data = (BYTE*)malloc(certLength);
Packit 1fb8d4
Packit 1fb8d4
		if (!certificate->x509_cert_chain->array[i].data)
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
Packit 1fb8d4
		Stream_Read(s, certificate->x509_cert_chain->array[i].data, certLength);
Packit 1fb8d4
		certificate->x509_cert_chain->array[i].length = certLength;
Packit 1fb8d4
Packit 1fb8d4
		if ((numCertBlobs - i) == 2)
Packit 1fb8d4
		{
Packit 1fb8d4
			rdpCertInfo cert_info = { 0 };
Packit 1fb8d4
			DEBUG_CERTIFICATE("License Server Certificate");
Packit Service 5a9772
			ret = certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i],
Packit Service 5a9772
			                                        &cert_info);
Packit Service 5a9772
			DEBUG_LICENSE("modulus length:%" PRIu32 "", cert_info.ModulusLength);
Packit 1fb8d4
			free(cert_info.Modulus);
Packit 1fb8d4
Packit 1fb8d4
			if (!ret)
Packit 1fb8d4
			{
Packit 1fb8d4
				WLog_ERR(TAG, "failed to read License Server, content follows:");
Packit 1fb8d4
				winpr_HexDump(TAG, WLOG_ERROR, certificate->x509_cert_chain->array[i].data,
Packit 1fb8d4
				              certificate->x509_cert_chain->array[i].length);
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (numCertBlobs - i == 1)
Packit 1fb8d4
		{
Packit 1fb8d4
			DEBUG_CERTIFICATE("Terminal Server Certificate");
Packit 1fb8d4
Packit 1fb8d4
			if (!certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i],
Packit 1fb8d4
			                                       &certificate->cert_info))
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
Packit Service 5a9772
			DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", certificate->cert_info.ModulusLength);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Read a Server Certificate.\n
Packit 1fb8d4
 * @param certificate certificate module
Packit 1fb8d4
 * @param server_cert server certificate
Packit 1fb8d4
 * @param length certificate length
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert,
Packit Service 5a9772
                                         size_t length)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	UINT32 dwVersion;
Packit 1fb8d4
Packit Service 5a9772
	if (length < 4) /* NULL certificate is not an error see #1795 */
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	s = Stream_New(server_cert, length);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Stream_New failed!");
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
Packit 1fb8d4
Packit 1fb8d4
	switch (dwVersion & CERT_CHAIN_VERSION_MASK)
Packit 1fb8d4
	{
Packit 1fb8d4
		case CERT_CHAIN_VERSION_1:
Packit 1fb8d4
			ret = certificate_read_server_proprietary_certificate(certificate, s);
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case CERT_CHAIN_VERSION_2:
Packit 1fb8d4
			ret = certificate_read_server_x509_certificate_chain(certificate, s);
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit Service 5a9772
			WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
Packit Service 5a9772
			         dwVersion & CERT_CHAIN_VERSION_MASK);
Packit 1fb8d4
			ret = FALSE;
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Free(s, FALSE);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
rdpRsaKey* key_new_from_content(const char* keycontent, const char* keyfile)
Packit 1fb8d4
{
Packit 1fb8d4
	BIO* bio = NULL;
Packit 1fb8d4
	RSA* rsa = NULL;
Packit 1fb8d4
	rdpRsaKey* key = NULL;
Packit 1fb8d4
	const BIGNUM* rsa_e = NULL;
Packit 1fb8d4
	const BIGNUM* rsa_n = NULL;
Packit 1fb8d4
	const BIGNUM* rsa_d = NULL;
Packit Service 5a9772
	key = (rdpRsaKey*)calloc(1, sizeof(rdpRsaKey));
Packit 1fb8d4
Packit 1fb8d4
	if (!key)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	bio = BIO_new_mem_buf((void*)keycontent, strlen(keycontent));
Packit 1fb8d4
Packit 1fb8d4
	if (!bio)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
Packit 1fb8d4
	BIO_free_all(bio);
Packit 1fb8d4
Packit 1fb8d4
	if (!rsa)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "unable to load RSA key from %s: %s.", keyfile, strerror(errno));
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	switch (RSA_check_key(rsa))
Packit 1fb8d4
	{
Packit 1fb8d4
		case 0:
Packit 1fb8d4
			WLog_ERR(TAG, "invalid RSA key in %s", keyfile);
Packit 1fb8d4
			goto out_free_rsa;
Packit 1fb8d4
Packit 1fb8d4
		case 1:
Packit 1fb8d4
			/* Valid key. */
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit Service 5a9772
			WLog_ERR(TAG, "unexpected error when checking RSA key from %s: %s.", keyfile,
Packit Service 5a9772
			         strerror(errno));
Packit 1fb8d4
			goto out_free_rsa;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
Packit 1fb8d4
Packit 1fb8d4
	if (BN_num_bytes(rsa_e) > 4)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "RSA public exponent too large in %s", keyfile);
Packit 1fb8d4
		goto out_free_rsa;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	key->ModulusLength = BN_num_bytes(rsa_n);
Packit Service 5a9772
	key->Modulus = (BYTE*)malloc(key->ModulusLength);
Packit 1fb8d4
Packit 1fb8d4
	if (!key->Modulus)
Packit 1fb8d4
		goto out_free_rsa;
Packit 1fb8d4
Packit 1fb8d4
	BN_bn2bin(rsa_n, key->Modulus);
Packit 1fb8d4
	crypto_reverse(key->Modulus, key->ModulusLength);
Packit 1fb8d4
	key->PrivateExponentLength = BN_num_bytes(rsa_d);
Packit Service 5a9772
	key->PrivateExponent = (BYTE*)malloc(key->PrivateExponentLength);
Packit 1fb8d4
Packit 1fb8d4
	if (!key->PrivateExponent)
Packit 1fb8d4
		goto out_free_modulus;
Packit 1fb8d4
Packit 1fb8d4
	BN_bn2bin(rsa_d, key->PrivateExponent);
Packit 1fb8d4
	crypto_reverse(key->PrivateExponent, key->PrivateExponentLength);
Packit 1fb8d4
	memset(key->exponent, 0, sizeof(key->exponent));
Packit 1fb8d4
	BN_bn2bin(rsa_e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa_e));
Packit 1fb8d4
	crypto_reverse(key->exponent, sizeof(key->exponent));
Packit 1fb8d4
	RSA_free(rsa);
Packit 1fb8d4
	return key;
Packit 1fb8d4
out_free_modulus:
Packit 1fb8d4
	free(key->Modulus);
Packit 1fb8d4
out_free_rsa:
Packit 1fb8d4
	RSA_free(rsa);
Packit 1fb8d4
out_free:
Packit 1fb8d4
	free(key);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
rdpRsaKey* key_new(const char* keyfile)
Packit 1fb8d4
{
Packit 1fb8d4
	FILE* fp = NULL;
Packit 1fb8d4
	INT64 length;
Packit 1fb8d4
	char* buffer = NULL;
Packit 1fb8d4
	rdpRsaKey* key = NULL;
Packit 1fb8d4
	fp = fopen(keyfile, "rb");
Packit 1fb8d4
Packit 1fb8d4
	if (!fp)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno));
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (_fseeki64(fp, 0, SEEK_END) < 0)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	if ((length = _ftelli64(fp)) < 0)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	if (_fseeki64(fp, 0, SEEK_SET) < 0)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	buffer = (char*)malloc(length + 1);
Packit 1fb8d4
Packit 1fb8d4
	if (!buffer)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit Service 5a9772
	if (fread((void*)buffer, length, 1, fp) != 1)
Packit 1fb8d4
		goto out_free;
Packit 1fb8d4
Packit 1fb8d4
	fclose(fp);
Packit 1fb8d4
	buffer[length] = '\0';
Packit 1fb8d4
	key = key_new_from_content(buffer, keyfile);
Packit 1fb8d4
	free(buffer);
Packit 1fb8d4
	return key;
Packit 1fb8d4
out_free:
Packit 1fb8d4
Packit 1fb8d4
	if (fp)
Packit 1fb8d4
		fclose(fp);
Packit 1fb8d4
Packit 1fb8d4
	free(buffer);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
rdpRsaKey* key_clone(const rdpRsaKey* key)
Packit Service 5a9772
{
Packit Service 5a9772
	rdpRsaKey* _key = (rdpRsaKey*)calloc(1, sizeof(rdpRsaKey));
Packit Service 5a9772
Packit Service 5a9772
	if (!_key)
Packit Service 5a9772
		return NULL;
Packit Service 5a9772
Packit Service 5a9772
	CopyMemory(_key, key, sizeof(rdpRsaKey));
Packit Service 5a9772
Packit Service 5a9772
	if (key->Modulus)
Packit Service 5a9772
	{
Packit Service 5a9772
		_key->Modulus = (BYTE*)malloc(key->ModulusLength);
Packit Service 5a9772
Packit Service 5a9772
		if (!_key->Modulus)
Packit Service 5a9772
			goto out_fail;
Packit Service 5a9772
Packit Service 5a9772
		CopyMemory(_key->Modulus, key->Modulus, key->ModulusLength);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	if (key->PrivateExponent)
Packit Service 5a9772
	{
Packit Service 5a9772
		_key->PrivateExponent = (BYTE*)malloc(key->PrivateExponentLength);
Packit Service 5a9772
Packit Service 5a9772
		if (!_key->PrivateExponent)
Packit Service 5a9772
			goto out_fail;
Packit Service 5a9772
Packit Service 5a9772
		CopyMemory(_key->PrivateExponent, key->PrivateExponent, key->PrivateExponentLength);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	return _key;
Packit Service 5a9772
out_fail:
Packit Service 5a9772
	free(_key->Modulus);
Packit Service 5a9772
	free(_key->PrivateExponent);
Packit Service 5a9772
	free(_key);
Packit Service 5a9772
	return NULL;
Packit Service 5a9772
}
Packit Service 5a9772
Packit 1fb8d4
void key_free(rdpRsaKey* key)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!key)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	free(key->Modulus);
Packit 1fb8d4
	free(key->PrivateExponent);
Packit 1fb8d4
	free(key);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
rdpCertificate* certificate_clone(rdpCertificate* certificate)
Packit 1fb8d4
{
Packit Service 5a9772
	UINT32 index;
Packit Service 5a9772
	rdpCertificate* _certificate = (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
Packit 1fb8d4
Packit 1fb8d4
	if (!_certificate)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(_certificate, certificate, sizeof(rdpCertificate));
Packit 1fb8d4
Packit 1fb8d4
	if (certificate->cert_info.ModulusLength)
Packit 1fb8d4
	{
Packit Service 5a9772
		_certificate->cert_info.Modulus = (BYTE*)malloc(certificate->cert_info.ModulusLength);
Packit 1fb8d4
Packit 1fb8d4
		if (!_certificate->cert_info.Modulus)
Packit 1fb8d4
			goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
		CopyMemory(_certificate->cert_info.Modulus, certificate->cert_info.Modulus,
Packit 1fb8d4
		           certificate->cert_info.ModulusLength);
Packit 1fb8d4
		_certificate->cert_info.ModulusLength = certificate->cert_info.ModulusLength;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (certificate->x509_cert_chain)
Packit 1fb8d4
	{
Packit Service 5a9772
		_certificate->x509_cert_chain = (rdpX509CertChain*)malloc(sizeof(rdpX509CertChain));
Packit 1fb8d4
Packit 1fb8d4
		if (!_certificate->x509_cert_chain)
Packit 1fb8d4
			goto out_fail;
Packit 1fb8d4
Packit Service 5a9772
		CopyMemory(_certificate->x509_cert_chain, certificate->x509_cert_chain,
Packit Service 5a9772
		           sizeof(rdpX509CertChain));
Packit 1fb8d4
Packit 1fb8d4
		if (certificate->x509_cert_chain->count)
Packit 1fb8d4
		{
Packit Service 5a9772
			_certificate->x509_cert_chain->array =
Packit Service 5a9772
			    (rdpCertBlob*)calloc(certificate->x509_cert_chain->count, sizeof(rdpCertBlob));
Packit 1fb8d4
Packit 1fb8d4
			if (!_certificate->x509_cert_chain->array)
Packit 1fb8d4
				goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
			for (index = 0; index < certificate->x509_cert_chain->count; index++)
Packit 1fb8d4
			{
Packit 1fb8d4
				_certificate->x509_cert_chain->array[index].length =
Packit 1fb8d4
				    certificate->x509_cert_chain->array[index].length;
Packit 1fb8d4
Packit 1fb8d4
				if (certificate->x509_cert_chain->array[index].length)
Packit 1fb8d4
				{
Packit Service 5a9772
					_certificate->x509_cert_chain->array[index].data =
Packit Service 5a9772
					    (BYTE*)malloc(certificate->x509_cert_chain->array[index].length);
Packit 1fb8d4
Packit 1fb8d4
					if (!_certificate->x509_cert_chain->array[index].data)
Packit 1fb8d4
					{
Packit Service 5a9772
						for (; index > 0; --index)
Packit 1fb8d4
						{
Packit Service 5a9772
							if (certificate->x509_cert_chain->array[index - 1].length)
Packit Service 5a9772
								free(_certificate->x509_cert_chain->array[index - 1].data);
Packit 1fb8d4
						}
Packit 1fb8d4
Packit 1fb8d4
						goto out_fail;
Packit 1fb8d4
					}
Packit 1fb8d4
Packit 1fb8d4
					CopyMemory(_certificate->x509_cert_chain->array[index].data,
Packit 1fb8d4
					           certificate->x509_cert_chain->array[index].data,
Packit 1fb8d4
					           _certificate->x509_cert_chain->array[index].length);
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return _certificate;
Packit 1fb8d4
out_fail:
Packit 1fb8d4
Packit 1fb8d4
	if (_certificate->x509_cert_chain)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(_certificate->x509_cert_chain->array);
Packit 1fb8d4
		free(_certificate->x509_cert_chain);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(_certificate->cert_info.Modulus);
Packit 1fb8d4
	free(_certificate);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Instantiate new certificate module.\n
Packit 1fb8d4
 * @param rdp RDP module
Packit 1fb8d4
 * @return new certificate module
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
rdpCertificate* certificate_new(void)
Packit 1fb8d4
{
Packit Service 5a9772
	return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Free certificate module.
Packit 1fb8d4
 * @param certificate certificate module to be freed
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
void certificate_free(rdpCertificate* certificate)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!certificate)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	certificate_free_x509_certificate_chain(certificate->x509_cert_chain);
Packit 1fb8d4
	free(certificate->cert_info.Modulus);
Packit 1fb8d4
	free(certificate);
Packit 1fb8d4
}