FreeRDP
certificate.c File Reference
#include <freerdp/config.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <winpr/assert.h>
#include <winpr/wtypes.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/print.h>
#include <winpr/crypto.h>
#include <freerdp/crypto/certificate.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include "certificate.h"
#include "cert_common.h"
#include "crypto.h"
#include "x509_utils.h"
#include "privatekey.h"
#include "opensslcompat.h"

Macros

#define TAG   FREERDP_TAG("core")
 
#define CERTIFICATE_TAG   FREERDP_TAG("core.certificate")
 
#define DEBUG_CERTIFICATE(...)
 
#define TSSK_KEY_LENGTH   64
 

Functions

static void certificate_free_int (rdpCertificate *certificate)
 
static BOOL cert_clone_int (rdpCertificate *dst, const rdpCertificate *src)
 
static BOOL cert_blob_copy (rdpCertBlob *dst, const rdpCertBlob *src)
 
static void cert_blob_free (rdpCertBlob *blob)
 
static BOOL cert_blob_write (const rdpCertBlob *blob, wStream *s)
 
static BOOL cert_blob_read (rdpCertBlob *blob, wStream *s)
 
static BOOL is_rsa_key (const X509 *x509)
 
static BOOL certificate_read_x509_certificate (const rdpCertBlob *cert, rdpCertInfo *info)
 
static rdpX509CertChain certificate_new_x509_certificate_chain (UINT32 count)
 
static void certificate_free_x509_certificate_chain (rdpX509CertChain *x509_cert_chain)
 
static BOOL update_x509_from_info (rdpCertificate *cert)
 
static BOOL certificate_process_server_public_key (rdpCertificate *cert, wStream *s, UINT32 length)
 
static BOOL certificate_process_server_public_signature (rdpCertificate *certificate, const BYTE *sigdata, size_t sigdatalen, wStream *s, UINT32 siglen)
 
static BOOL certificate_read_server_proprietary_certificate (rdpCertificate *certificate, wStream *s)
 
static BOOL cert_write_rsa_public_key (wStream *s, const rdpCertificate *cert)
 
static BOOL cert_write_rsa_signature (wStream *s, const void *sigData, size_t sigDataLen)
 
static BOOL cert_write_server_certificate_v1 (wStream *s, const rdpCertificate *certificate)
 
static BOOL cert_write_server_certificate_v2 (wStream *s, const rdpCertificate *certificate)
 
SSIZE_T freerdp_certificate_write_server_cert (const rdpCertificate *certificate, UINT32 dwVersion, wStream *s)
 
static BOOL certificate_read_server_x509_certificate_chain (rdpCertificate *cert, wStream *s)
 
static BOOL certificate_write_server_x509_certificate_chain (const rdpCertificate *certificate, wStream *s)
 
BOOL freerdp_certificate_read_server_cert (rdpCertificate *certificate, const BYTE *server_cert, size_t length)
 
static BOOL cert_x509_chain_copy (rdpX509CertChain *cert, const rdpX509CertChain *src)
 
rdpCertificate * freerdp_certificate_clone (const rdpCertificate *certificate)
 
rdpCertificate * freerdp_certificate_new (void)
 
void freerdp_certificate_free (rdpCertificate *cert)
 
static BOOL freerdp_rsa_from_x509 (rdpCertificate *cert)
 
rdpCertificate * freerdp_certificate_new_from_der (const BYTE *data, size_t length)
 
rdpCertificate * freerdp_certificate_new_from_x509 (const X509 *xcert, const STACK_OF(X509) *chain)
 
static rdpCertificate * freerdp_certificate_new_from (const char *file, BOOL isFile)
 
rdpCertificate * freerdp_certificate_new_from_file (const char *file)
 
rdpCertificate * freerdp_certificate_new_from_pem (const char *pem)
 
const rdpCertInfo * freerdp_certificate_get_info (const rdpCertificate *cert)
 
char * freerdp_certificate_get_fingerprint (const rdpCertificate *cert)
 
char * freerdp_certificate_get_fingerprint_by_hash (const rdpCertificate *cert, const char *hash)
 
char * freerdp_certificate_get_fingerprint_by_hash_ex (const rdpCertificate *cert, const char *hash, BOOL separator)
 
static BOOL bio_read_pem (BIO *bio, char **ppem, size_t *plength)
 
char * freerdp_certificate_get_pem (const rdpCertificate *cert, size_t *pLength)
 
char * freerdp_certificate_get_pem_ex (const rdpCertificate *cert, size_t *pLength, BOOL withCertChain)
 
char * freerdp_certificate_get_subject (const rdpCertificate *cert)
 
char * freerdp_certificate_get_issuer (const rdpCertificate *cert)
 
char * freerdp_certificate_get_upn (const rdpCertificate *cert)
 
char * freerdp_certificate_get_email (const rdpCertificate *cert)
 
char * freerdp_certificate_get_validity (const rdpCertificate *cert, BOOL startDate)
 
BOOL freerdp_certificate_check_eku (const rdpCertificate *cert, int nid)
 
BOOL freerdp_certificate_get_public_key (const rdpCertificate *cert, BYTE **PublicKey, DWORD *PublicKeyLength)
 
BOOL freerdp_certificate_verify (const rdpCertificate *cert, const char *certificate_store_path)
 
char ** freerdp_certificate_get_dns_names (const rdpCertificate *cert, size_t *pcount, size_t **pplengths)
 
char * freerdp_certificate_get_common_name (const rdpCertificate *cert, size_t *plength)
 
WINPR_MD_TYPE freerdp_certificate_get_signature_alg (const rdpCertificate *cert)
 
void freerdp_certificate_free_dns_names (size_t count, size_t *lengths, char **names)
 
char * freerdp_certificate_get_hash (const rdpCertificate *cert, const char *hash, size_t *plength)
 
X509 * freerdp_certificate_get_x509 (rdpCertificate *cert)
 returns a pointer to a X509 structure. Call X509_free when done. More...
 
BOOL freerdp_certificate_publickey_encrypt (const rdpCertificate *cert, const BYTE *input, size_t cbInput, BYTE **poutput, size_t *pcbOutput)
 
static RSA * freerdp_certificate_get_RSA (const rdpCertificate *cert)
 
BYTEfreerdp_certificate_get_der (const rdpCertificate *cert, size_t *pLength)
 
BOOL freerdp_certificate_is_rsa (const rdpCertificate *cert)
 
BOOL freerdp_certificate_is_rdp_security_compatible (const rdpCertificate *cert)
 
char * freerdp_certificate_get_param (const rdpCertificate *cert, enum FREERDP_CERT_PARAM what, size_t *psize)
 

Variables

static const char rsa_magic [4] = "RSA1"
 
static const char * certificate_read_errors []
 
static const BYTE initial_signature []
 

Macro Definition Documentation

◆ CERTIFICATE_TAG

#define CERTIFICATE_TAG   FREERDP_TAG("core.certificate")

◆ DEBUG_CERTIFICATE

#define DEBUG_CERTIFICATE (   ...)
Value:
do \
{ \
} while (0)

◆ TAG

#define TAG   FREERDP_TAG("core")

FreeRDP: A Remote Desktop Protocol Implementation Certificate Handling

Copyright 2011 Jiten Pathy Copyright 2011 Marc-Andre Moreau marca.nosp@m.ndre.nosp@m..more.nosp@m.au@g.nosp@m.mail..nosp@m.com Copyright 2015 Thincast Technologies GmbH Copyright 2015 DI (FH) Martin Haimberger marti.nosp@m.n.ha.nosp@m.imber.nosp@m.ger@.nosp@m.thinc.nosp@m.ast..nosp@m.com Copyright 2023 Armin Novak anova.nosp@m.k@th.nosp@m.incas.nosp@m.t.co.nosp@m.m 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.

◆ TSSK_KEY_LENGTH

#define TSSK_KEY_LENGTH   64

Function Documentation

◆ bio_read_pem()

static BOOL bio_read_pem ( BIO *  bio,
char **  ppem,
size_t *  plength 
)
static
Here is the caller graph for this function:

◆ cert_blob_copy()

static BOOL cert_blob_copy ( rdpCertBlob *  dst,
const rdpCertBlob *  src 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_blob_free()

void cert_blob_free ( rdpCertBlob *  blob)
static
Here is the caller graph for this function:

◆ cert_blob_read()

BOOL cert_blob_read ( rdpCertBlob *  blob,
wStream s 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_blob_write()

BOOL cert_blob_write ( const rdpCertBlob *  blob,
wStream s 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_clone_int()

BOOL cert_clone_int ( rdpCertificate *  dst,
const rdpCertificate *  src 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_write_rsa_public_key()

static BOOL cert_write_rsa_public_key ( wStream s,
const rdpCertificate *  cert 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_write_rsa_signature()

static BOOL cert_write_rsa_signature ( wStream s,
const void *  sigData,
size_t  sigDataLen 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_write_server_certificate_v1()

static BOOL cert_write_server_certificate_v1 ( wStream s,
const rdpCertificate *  certificate 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_write_server_certificate_v2()

static BOOL cert_write_server_certificate_v2 ( wStream s,
const rdpCertificate *  certificate 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cert_x509_chain_copy()

static BOOL cert_x509_chain_copy ( rdpX509CertChain *  cert,
const rdpX509CertChain *  src 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_free_int()

void certificate_free_int ( rdpCertificate *  certificate)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_free_x509_certificate_chain()

static void certificate_free_x509_certificate_chain ( rdpX509CertChain *  x509_cert_chain)
static

Free X.509 Certificate Chain.

Parameters
x509_cert_chainX.509 certificate chain to be freed
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_new_x509_certificate_chain()

static rdpX509CertChain certificate_new_x509_certificate_chain ( UINT32  count)
static

Instantiate new X.509 Certificate Chain.

Parameters
countcertificate chain count
Returns
new X.509 certificate chain
Here is the caller graph for this function:

◆ certificate_process_server_public_key()

static BOOL certificate_process_server_public_key ( rdpCertificate *  cert,
wStream s,
UINT32  length 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_process_server_public_signature()

static BOOL certificate_process_server_public_signature ( rdpCertificate *  certificate,
const BYTE sigdata,
size_t  sigdatalen,
wStream s,
UINT32  siglen 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_read_server_proprietary_certificate()

static BOOL certificate_read_server_proprietary_certificate ( rdpCertificate *  certificate,
wStream s 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_read_server_x509_certificate_chain()

static BOOL certificate_read_server_x509_certificate_chain ( rdpCertificate *  cert,
wStream s 
)
static

Read an X.509 Certificate Chain.

Parameters
certcertificate module
sstream
Returns
TRUE for success, FALSE otherwise.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_read_x509_certificate()

static BOOL certificate_read_x509_certificate ( const rdpCertBlob *  cert,
rdpCertInfo *  info 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ certificate_write_server_x509_certificate_chain()

static BOOL certificate_write_server_x509_certificate_chain ( const rdpCertificate *  certificate,
wStream s 
)
static
Here is the call graph for this function:

◆ freerdp_certificate_check_eku()

BOOL freerdp_certificate_check_eku ( const rdpCertificate *  cert,
int  nid 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_clone()

rdpCertificate* freerdp_certificate_clone ( const rdpCertificate *  certificate)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_free()

void freerdp_certificate_free ( rdpCertificate *  cert)

Free certificate module.

Parameters
certcertificate module to be freed
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_free_dns_names()

void freerdp_certificate_free_dns_names ( size_t  count,
size_t *  lengths,
char **  names 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_common_name()

char* freerdp_certificate_get_common_name ( const rdpCertificate *  cert,
size_t *  plength 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_der()

BYTE* freerdp_certificate_get_der ( const rdpCertificate *  cert,
size_t *  pLength 
)
Here is the caller graph for this function:

◆ freerdp_certificate_get_dns_names()

char** freerdp_certificate_get_dns_names ( const rdpCertificate *  cert,
size_t *  pcount,
size_t **  pplengths 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_email()

char* freerdp_certificate_get_email ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_fingerprint()

char* freerdp_certificate_get_fingerprint ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_fingerprint_by_hash()

char* freerdp_certificate_get_fingerprint_by_hash ( const rdpCertificate *  cert,
const char *  hash 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_fingerprint_by_hash_ex()

char* freerdp_certificate_get_fingerprint_by_hash_ex ( const rdpCertificate *  cert,
const char *  hash,
BOOL  separator 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_hash()

char* freerdp_certificate_get_hash ( const rdpCertificate *  cert,
const char *  hash,
size_t *  plength 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_info()

const rdpCertInfo* freerdp_certificate_get_info ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_issuer()

char* freerdp_certificate_get_issuer ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_param()

char* freerdp_certificate_get_param ( const rdpCertificate *  cert,
enum FREERDP_CERT_PARAM  what,
size_t *  psize 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_pem()

char* freerdp_certificate_get_pem ( const rdpCertificate *  cert,
size_t *  pLength 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_pem_ex()

char* freerdp_certificate_get_pem_ex ( const rdpCertificate *  cert,
size_t *  pLength,
BOOL  withCertChain 
)

Don't manage certificates internally, leave it up entirely to the external client implementation

Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_public_key()

BOOL freerdp_certificate_get_public_key ( const rdpCertificate *  cert,
BYTE **  PublicKey,
DWORD *  PublicKeyLength 
)
Here is the caller graph for this function:

◆ freerdp_certificate_get_RSA()

static RSA* freerdp_certificate_get_RSA ( const rdpCertificate *  cert)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_signature_alg()

WINPR_MD_TYPE freerdp_certificate_get_signature_alg ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_subject()

char* freerdp_certificate_get_subject ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_upn()

char* freerdp_certificate_get_upn ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_validity()

char* freerdp_certificate_get_validity ( const rdpCertificate *  cert,
BOOL  startDate 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_get_x509()

X509* freerdp_certificate_get_x509 ( rdpCertificate *  cert)

returns a pointer to a X509 structure. Call X509_free when done.

Here is the caller graph for this function:

◆ freerdp_certificate_is_rdp_security_compatible()

BOOL freerdp_certificate_is_rdp_security_compatible ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_is_rsa()

BOOL freerdp_certificate_is_rsa ( const rdpCertificate *  cert)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_new()

rdpCertificate* freerdp_certificate_new ( void  )

Instantiate new certificate module.

Returns
new certificate module
Here is the caller graph for this function:

◆ freerdp_certificate_new_from()

static rdpCertificate* freerdp_certificate_new_from ( const char *  file,
BOOL  isFile 
)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_new_from_der()

rdpCertificate* freerdp_certificate_new_from_der ( const BYTE data,
size_t  length 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_new_from_file()

rdpCertificate* freerdp_certificate_new_from_file ( const char *  file)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_new_from_pem()

rdpCertificate* freerdp_certificate_new_from_pem ( const char *  pem)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_new_from_x509()

rdpCertificate* freerdp_certificate_new_from_x509 ( const X509 *  xcert,
const STACK_OF(X509) *  chain 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_publickey_encrypt()

BOOL freerdp_certificate_publickey_encrypt ( const rdpCertificate *  cert,
const BYTE input,
size_t  cbInput,
BYTE **  poutput,
size_t *  pcbOutput 
)

◆ freerdp_certificate_read_server_cert()

BOOL freerdp_certificate_read_server_cert ( rdpCertificate *  certificate,
const BYTE server_cert,
size_t  length 
)

Read a Server Certificate.

Parameters
certificatecertificate module
server_certserver certificate
lengthcertificate length
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_verify()

BOOL freerdp_certificate_verify ( const rdpCertificate *  cert,
const char *  certificate_store_path 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_certificate_write_server_cert()

SSIZE_T freerdp_certificate_write_server_cert ( const rdpCertificate *  certificate,
UINT32  dwVersion,
wStream s 
)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freerdp_rsa_from_x509()

static BOOL freerdp_rsa_from_x509 ( rdpCertificate *  cert)
static
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_rsa_key()

static BOOL is_rsa_key ( const X509 *  x509)
static

Read X.509 Certificate

Here is the caller graph for this function:

◆ update_x509_from_info()

static BOOL update_x509_from_info ( rdpCertificate *  cert)
static
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ certificate_read_errors

const char* certificate_read_errors[]
static
Initial value:
= { "Certificate tag",
"TBSCertificate",
"Explicit Contextual Tag [0]",
"version",
"CertificateSerialNumber",
"AlgorithmIdentifier",
"Issuer Name",
"Validity",
"Subject Name",
"SubjectPublicKeyInfo Tag",
"subjectPublicKeyInfo::AlgorithmIdentifier",
"subjectPublicKeyInfo::subjectPublicKey",
"RSAPublicKey Tag",
"modulusLength",
"zero padding",
"modulusLength",
"modulus",
"publicExponent length",
"publicExponent" }

◆ initial_signature

const BYTE initial_signature[]
static
Initial value:
= {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
}

◆ rsa_magic

const char rsa_magic[4] = "RSA1"
static

X.509 Certificate Structure

Certificate ::= SEQUENCE { tbsCertificate TBSCertificate, signatureAlgorithm AlgorithmIdentifier, signatureValue BIT_STRING }

TBSCertificate ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, serialNumber CertificateSerialNumber, signature AlgorithmIdentifier, issuer Name, validity Validity, subject Name, subjectPublicKeyInfo SubjectPublicKeyInfo, issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, subjectUniqueId [2] IMPLICIT UniqueIdentifier OPTIONAL, extensions [3] EXPLICIT Extensions OPTIONAL }

Version ::= INTEGER { v1(0), v2(1), v3(2) }

CertificateSerialNumber ::= INTEGER

AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT_IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL }

Name ::= CHOICE { RDNSequence }

RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

RelativeDistinguishedName ::= SET OF AttributeTypeAndValue

AttributeTypeAndValue ::= SEQUENCE { type AttributeType, value AttributeValue }

AttributeType ::= OBJECT_IDENTIFIER

AttributeValue ::= ANY DEFINED BY AttributeType

Validity ::= SEQUENCE { notBefore Time, notAfter Time }

Time ::= CHOICE { utcTime UTCTime, generalTime GeneralizedTime }

UniqueIdentifier ::= BIT_STRING

SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT_STRING }

RSAPublicKey ::= SEQUENCE { modulus INTEGER publicExponent INTEGER }

Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension

Extension ::= SEQUENCE { extnID OBJECT_IDENTIFIER critical BOOLEAN DEFAULT FALSE, extnValue OCTET_STRING }