22#include <openssl/objects.h> 
   23#include <openssl/x509v3.h> 
   24#include <openssl/pem.h> 
   25#include <openssl/rsa.h> 
   26#include <openssl/err.h> 
   28#include <freerdp/config.h> 
   31#include <winpr/string.h> 
   32#include <winpr/assert.h> 
   34#include <freerdp/log.h> 
   36#include "x509_utils.h" 
   38#define TAG FREERDP_TAG("crypto") 
   40BYTE* x509_utils_get_hash(
const X509* xcert, 
const char* hash, 
size_t* length)
 
   42  UINT32 fp_len = EVP_MAX_MD_SIZE;
 
   44  const EVP_MD* md = EVP_get_digestbyname(hash);
 
   47    WLog_ERR(TAG, 
"System does not support %s hash!", hash);
 
   50  if (!xcert || !length)
 
   52    WLog_ERR(TAG, 
"Invalid arguments: xcert=%p, length=%p", xcert, length);
 
   56  fp = calloc(fp_len + 1, 
sizeof(BYTE));
 
   59    WLog_ERR(TAG, 
"could not allocate %" PRIuz 
" bytes", fp_len);
 
   63  if (X509_digest(xcert, md, fp, &fp_len) != 1)
 
   66    WLog_ERR(TAG, 
"certificate does not have a %s hash!", hash);
 
   74static char* crypto_print_name(
const X509_NAME* name)
 
   77  BIO* outBIO = BIO_new(BIO_s_mem());
 
   79  if (X509_NAME_print_ex(outBIO, name, 0, XN_FLAG_ONELINE) > 0)
 
   81    UINT64 size = BIO_number_written(outBIO);
 
   84    buffer = calloc(1, (
size_t)size + 1);
 
   90    const int rc = BIO_read(outBIO, buffer, (
int)size);
 
  100  BIO_free_all(outBIO);
 
  104char* x509_utils_get_subject(
const X509* xcert)
 
  106  char* subject = NULL;
 
  109    WLog_ERR(TAG, 
"Invalid certificate %p", xcert);
 
  112  subject = crypto_print_name(X509_get_subject_name(xcert));
 
  114    WLog_WARN(TAG, 
"certificate does not have a subject!");
 
  120static const char* general_name_type_labels[] = { 
"OTHERNAME", 
"EMAIL    ", 
"DNS      ",
 
  121                                                "X400     ", 
"DIRNAME  ", 
"EDIPARTY ",
 
  122                                                "URI      ", 
"IPADD    ", 
"RID      " };
 
  124static const char* general_name_type_label(
int general_name_type)
 
  126  if ((0 <= general_name_type) &&
 
  127      ((
size_t)general_name_type < ARRAYSIZE(general_name_type_labels)))
 
  129    return general_name_type_labels[general_name_type];
 
  133    static char buffer[80] = { 0 };
 
  134    (void)snprintf(buffer, 
sizeof(buffer), 
"Unknown general name type (%d)", general_name_type);
 
  184typedef int (*general_name_mapper_pr)(GENERAL_NAME* name, 
void* data, 
int index, 
int count);
 
  186static void map_subject_alt_name(
const X509* x509, 
int general_name_type,
 
  187                                 general_name_mapper_pr mapper, 
void* data)
 
  190  STACK_OF(GENERAL_NAME)* gens = NULL;
 
  191  gens = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
 
  198  num = sk_GENERAL_NAME_num(gens);
 
  200  for (
int i = 0; (i < num); i++)
 
  202    GENERAL_NAME* name = sk_GENERAL_NAME_value(gens, i);
 
  206      if ((general_name_type == GEN_ALL) || (general_name_type == name->type))
 
  208        if (!mapper(name, data, i, num))
 
  216  sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
 
  238typedef struct string_list
 
  246static void string_list_initialize(string_list* list)
 
  251  list->maximum = INT_MAX;
 
  254static void string_list_allocate(string_list* list, 
size_t allocate_count)
 
  256  if (!list->strings && list->allocated == 0)
 
  258    list->strings = (
char**)calloc(allocate_count, 
sizeof(
char*));
 
  259    list->allocated = list->strings ? allocate_count : 0;
 
  264static void string_list_free(string_list* list)
 
  269  free((
void*)list->strings);
 
  272static int extract_string(GENERAL_NAME* name, 
void* data, 
int index, 
int count)
 
  274  string_list* list = data;
 
  275  unsigned char* cstring = 0;
 
  276  ASN1_STRING* str = NULL;
 
  283      str = name->d.uniformResourceIdentifier;
 
  287      str = name->d.dNSName;
 
  291      str = name->d.rfc822Name;
 
  298  if ((ASN1_STRING_to_UTF8(&cstring, str)) < 0)
 
  300    WLog_ERR(TAG, 
"ASN1_STRING_to_UTF8() failed for %s: %s",
 
  301             general_name_type_label(name->type), ERR_error_string(ERR_get_error(), NULL));
 
  305  string_list_allocate(list, WINPR_ASSERTING_INT_CAST(WINPR_CIPHER_TYPE, count));
 
  307  if (list->allocated <= 0)
 
  309    OPENSSL_free(cstring);
 
  313  list->strings[list->count] = (
char*)cstring;
 
  316  if (list->count >= list->maximum)
 
  342typedef struct object_list
 
  344  ASN1_OBJECT* type_id;
 
  351static void object_list_initialize(object_list* list)
 
  357  list->maximum = INT_MAX;
 
  360static void object_list_allocate(object_list* list, 
size_t allocate_count)
 
  362  if (!list->strings && (list->allocated == 0) && (allocate_count > 0))
 
  364    list->strings = (
char**)calloc(allocate_count, 
sizeof(list->strings[0]));
 
  365    list->allocated = list->strings ? allocate_count : 0;
 
  370static char* object_string(ASN1_TYPE* 
object)
 
  373  unsigned char* utf8String = NULL;
 
  376  const int length = ASN1_STRING_to_UTF8(&utf8String, object->value.asn1_string);
 
  383  result = strndup((
char*)utf8String, WINPR_ASSERTING_INT_CAST(
size_t, length));
 
  384  OPENSSL_free(utf8String);
 
  388static void object_list_free(object_list* list)
 
  391  free((
void*)list->strings);
 
  394static int extract_othername_object_as_string(GENERAL_NAME* name, 
void* data, 
int index, 
int count)
 
  396  object_list* list = data;
 
  402  if (name->type != GEN_OTHERNAME)
 
  407  if (0 != OBJ_cmp(name->d.otherName->type_id, list->type_id))
 
  412  object_list_allocate(list, WINPR_ASSERTING_INT_CAST(
size_t, count));
 
  414  if (list->allocated <= 0)
 
  419  list->strings[list->count] = object_string(name->d.otherName->value);
 
  421  if (list->strings[list->count])
 
  426  if (list->count >= list->maximum)
 
  434char* x509_utils_get_email(
const X509* x509)
 
  438  string_list_initialize(&list);
 
  440  map_subject_alt_name(x509, GEN_EMAIL, extract_string, &list);
 
  444    string_list_free(&list);
 
  448  result = _strdup(list.strings[0]);
 
  449  OPENSSL_free(list.strings[0]);
 
  450  string_list_free(&list);
 
  454char* x509_utils_get_upn(
const X509* x509)
 
  457  object_list list = { 0 };
 
  458  object_list_initialize(&list);
 
  459  list.type_id = OBJ_nid2obj(NID_ms_upn);
 
  461  map_subject_alt_name(x509, GEN_OTHERNAME, extract_othername_object_as_string, &list);
 
  465    object_list_free(&list);
 
  469  result = list.strings[0];
 
  470  object_list_free(&list);
 
  474char* x509_utils_get_date(
const X509* x509, BOOL startDate)
 
  478  const ASN1_TIME* date = startDate ? X509_get0_notBefore(x509) : X509_get0_notAfter(x509);
 
  482  BIO* bmem = BIO_new(BIO_s_mem());
 
  487  if (ASN1_TIME_print(bmem, date))
 
  489    BUF_MEM* bptr = NULL;
 
  491    BIO_get_mem_ptr(bmem, &bptr);
 
  492    str = strndup(bptr->data, bptr->length);
 
  501void x509_utils_dns_names_free(
size_t count, 
size_t* lengths, 
char** dns_names)
 
  507    for (
size_t i = 0; i < count; i++)
 
  511        OPENSSL_free(dns_names[i]);
 
  515    free((
void*)dns_names);
 
  519char** x509_utils_get_dns_names(
const X509* x509, 
size_t* count, 
size_t** lengths)
 
  522  string_list list = { 0 };
 
  523  string_list_initialize(&list);
 
  524  map_subject_alt_name(x509, GEN_DNS, extract_string, &list);
 
  525  (*count) = list.count;
 
  529    string_list_free(&list);
 
  535  result = (
char**)calloc(list.count, 
sizeof(*result));
 
  536  (*lengths) = calloc(list.count, 
sizeof(**lengths));
 
  538  if (!result || !(*lengths))
 
  540    string_list_free(&list);
 
  548  for (
size_t i = 0; i < list.count; i++)
 
  550    result[i] = list.strings[i];
 
  551    (*lengths)[i] = strlen(result[i]);
 
  554  string_list_free(&list);
 
  558char* x509_utils_get_issuer(
const X509* xcert)
 
  563    WLog_ERR(TAG, 
"Invalid certificate %p", xcert);
 
  566  issuer = crypto_print_name(X509_get_issuer_name(xcert));
 
  568    WLog_WARN(TAG, 
"certificate does not have an issuer!");
 
  572static int asn1_object_cmp(
const ASN1_OBJECT* 
const* a, 
const ASN1_OBJECT* 
const* b)
 
  575    return (a == b) ? 0 : (a ? 1 : -1);
 
  578    return (*a == *b) ? 0 : (*a ? 1 : -1);
 
  580  return OBJ_cmp(*a, *b);
 
  583BOOL x509_utils_check_eku(
const X509* xcert, 
int nid)
 
  586  STACK_OF(ASN1_OBJECT)* oid_stack = NULL;
 
  587  ASN1_OBJECT* oid = NULL;
 
  592  oid = OBJ_nid2obj(nid);
 
  596  oid_stack = X509_get_ext_d2i(xcert, NID_ext_key_usage, NULL, NULL);
 
  600  sk_ASN1_OBJECT_set_cmp_func(oid_stack, asn1_object_cmp);
 
  601  if (sk_ASN1_OBJECT_find(oid_stack, oid) >= 0)
 
  604  sk_ASN1_OBJECT_pop_free(oid_stack, ASN1_OBJECT_free);
 
  608void x509_utils_print_info(
const X509* xcert)
 
  612  char* subject = NULL;
 
  613  subject = x509_utils_get_subject(xcert);
 
  614  issuer = x509_utils_get_issuer(xcert);
 
  615  fp = (
char*)x509_utils_get_hash(xcert, 
"sha256", NULL);
 
  619    WLog_ERR(TAG, 
"error computing fingerprint");
 
  620    goto out_free_issuer;
 
  623  WLog_INFO(TAG, 
"Certificate details:");
 
  624  WLog_INFO(TAG, 
"\tSubject: %s", subject);
 
  625  WLog_INFO(TAG, 
"\tIssuer: %s", issuer);
 
  626  WLog_INFO(TAG, 
"\tThumbprint: %s", fp);
 
  628            "The above X.509 certificate could not be verified, possibly because you do not have " 
  629            "the CA certificate in your certificate store, or the certificate has expired. " 
  630            "Please look at the OpenSSL documentation on how to add a private CA to the store.");
 
  637X509* x509_utils_from_pem(
const char* data, 
size_t len, BOOL fromFile)
 
  642    bio = BIO_new_file(data, 
"rb");
 
  648    bio = BIO_new_mem_buf(data, (
int)len);
 
  653    WLog_ERR(TAG, 
"BIO_new failed for certificate");
 
  657  x509 = PEM_read_bio_X509(bio, NULL, NULL, 0);
 
  660    WLog_ERR(TAG, 
"PEM_read_bio_X509 returned NULL [input length %" PRIuz 
"]", len);
 
  665static WINPR_MD_TYPE hash_nid_to_winpr(
int hash_nid)
 
  676      return WINPR_MD_SHA1;
 
  678      return WINPR_MD_SHA224;
 
  680      return WINPR_MD_SHA256;
 
  682      return WINPR_MD_SHA384;
 
  684      return WINPR_MD_SHA512;
 
  686      return WINPR_MD_RIPEMD160;
 
  687#if (OPENSSL_VERSION_NUMBER >= 0x1010101fL) && !defined(LIBRESSL_VERSION_NUMBER) 
  689      return WINPR_MD_SHA3_224;
 
  691      return WINPR_MD_SHA3_256;
 
  693      return WINPR_MD_SHA3_384;
 
  695      return WINPR_MD_SHA3_512;
 
  697      return WINPR_MD_SHAKE128;
 
  699      return WINPR_MD_SHAKE256;
 
  703      return WINPR_MD_NONE;
 
  707static WINPR_MD_TYPE get_rsa_pss_digest(
const X509_ALGOR* alg)
 
  709  WINPR_MD_TYPE ret = WINPR_MD_NONE;
 
  710  WINPR_MD_TYPE message_digest = WINPR_MD_NONE;
 
  711  WINPR_MD_TYPE mgf1_digest = WINPR_MD_NONE;
 
  713  const void* param_value = NULL;
 
  714  const ASN1_STRING* sequence = NULL;
 
  715  const unsigned char* inp = NULL;
 
  716  RSA_PSS_PARAMS* params = NULL;
 
  717  X509_ALGOR* mgf1_digest_alg = NULL;
 
  721  X509_ALGOR_get0(NULL, ¶m_type, ¶m_value, alg);
 
  726  if (param_type != V_ASN1_SEQUENCE)
 
  728  sequence = param_value;
 
  731  inp = ASN1_STRING_get0_data(sequence);
 
  732  params = d2i_RSA_PSS_PARAMS(NULL, &inp, ASN1_STRING_length(sequence));
 
  739  message_digest = WINPR_MD_SHA1;
 
  740  if (params->hashAlgorithm != NULL)
 
  742    const ASN1_OBJECT* obj = NULL;
 
  743    X509_ALGOR_get0(&obj, NULL, NULL, params->hashAlgorithm);
 
  744    message_digest = hash_nid_to_winpr(OBJ_obj2nid(obj));
 
  745    if (message_digest == WINPR_MD_NONE)
 
  749  mgf1_digest = WINPR_MD_SHA1;
 
  750  if (params->maskGenAlgorithm != NULL)
 
  752    const ASN1_OBJECT* obj = NULL;
 
  753    int mgf_param_type = 0;
 
  754    const void* mgf_param_value = NULL;
 
  755    const ASN1_STRING* mgf_param_sequence = NULL;
 
  757    X509_ALGOR_get0(&obj, &mgf_param_type, &mgf_param_value, params->maskGenAlgorithm);
 
  758    if (OBJ_obj2nid(obj) != NID_mgf1)
 
  762    if (mgf_param_type != V_ASN1_SEQUENCE)
 
  764    mgf_param_sequence = mgf_param_value;
 
  765    inp = ASN1_STRING_get0_data(mgf_param_sequence);
 
  766    mgf1_digest_alg = d2i_X509_ALGOR(NULL, &inp, ASN1_STRING_length(mgf_param_sequence));
 
  767    if (mgf1_digest_alg == NULL)
 
  771    X509_ALGOR_get0(&obj, NULL, NULL, mgf1_digest_alg);
 
  772    mgf1_digest = hash_nid_to_winpr(OBJ_obj2nid(obj));
 
  773    if (mgf1_digest == WINPR_MD_NONE)
 
  780  if (message_digest != mgf1_digest)
 
  782  ret = message_digest;
 
  785  RSA_PSS_PARAMS_free(params);
 
  786  X509_ALGOR_free(mgf1_digest_alg);
 
  790WINPR_MD_TYPE x509_utils_get_signature_alg(
const X509* xcert)
 
  794  const int nid = X509_get_signature_nid(xcert);
 
  796  if (nid == NID_rsassaPss)
 
  798    const X509_ALGOR* alg = NULL;
 
  799    X509_get0_signature(NULL, &alg, xcert);
 
  800    return get_rsa_pss_digest(alg);
 
  804  if (OBJ_find_sigid_algs(nid, &hash_nid, NULL) != 1)
 
  805    return WINPR_MD_NONE;
 
  807  return hash_nid_to_winpr(hash_nid);
 
  810char* x509_utils_get_common_name(
const X509* xcert, 
size_t* plength)
 
  812  X509_NAME* subject_name = X509_get_subject_name(xcert);
 
  813  if (subject_name == NULL)
 
  816  const int index = X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
 
  820  const X509_NAME_ENTRY* entry = X509_NAME_get_entry(subject_name, index);
 
  824  const ASN1_STRING* entry_data = X509_NAME_ENTRY_get_data(entry);
 
  825  if (entry_data == NULL)
 
  828  BYTE* common_name_raw = NULL;
 
  829  const int length = ASN1_STRING_to_UTF8(&common_name_raw, entry_data);
 
  834    *plength = (size_t)length;
 
  836  char* common_name = _strdup((
char*)common_name_raw);
 
  837  OPENSSL_free(common_name_raw);
 
  841static int verify_cb(
int ok, X509_STORE_CTX* csc)
 
  846    int err = X509_STORE_CTX_get_error(csc);
 
  847    int derr = X509_STORE_CTX_get_error_depth(csc);
 
  848    X509* where = X509_STORE_CTX_get_current_cert(csc);
 
  849    const char* what = X509_verify_cert_error_string(err);
 
  850    char* name = x509_utils_get_subject(where);
 
  852    WLog_WARN(TAG, 
"Certificate verification failure '%s (%d)' at stack position %d", what, err,
 
  854    WLog_WARN(TAG, 
"%s", name);
 
  861BOOL x509_utils_verify(X509* xcert, STACK_OF(X509) * chain, 
const char* certificate_store_path)
 
  863  const int purposes[3] = { X509_PURPOSE_SSL_SERVER, X509_PURPOSE_SSL_CLIENT, X509_PURPOSE_ANY };
 
  864  X509_STORE_CTX* csc = NULL;
 
  866  X509_LOOKUP* lookup = NULL;
 
  871  X509_STORE* cert_ctx = X509_STORE_new();
 
  873  if (cert_ctx == NULL)
 
  876#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 
  877  OpenSSL_add_all_algorithms();
 
  879  OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS |
 
  880                          OPENSSL_INIT_LOAD_CONFIG,
 
  884  if (X509_STORE_set_default_paths(cert_ctx) != 1)
 
  887  lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
 
  892  X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
 
  894  if (certificate_store_path != NULL)
 
  896    X509_LOOKUP_add_dir(lookup, certificate_store_path, X509_FILETYPE_PEM);
 
  899  X509_STORE_set_flags(cert_ctx, 0);
 
  901  for (
size_t i = 0; i < ARRAYSIZE(purposes); i++)
 
  905    int purpose = purposes[i];
 
  906    csc = X509_STORE_CTX_new();
 
  910    if (!X509_STORE_CTX_init(csc, cert_ctx, xcert, chain))
 
  913    X509_STORE_CTX_set_purpose(csc, purpose);
 
  914    X509_STORE_CTX_set_verify_cb(csc, verify_cb);
 
  916    rc = X509_verify_cert(csc);
 
  917    err = X509_STORE_CTX_get_error(csc);
 
  919    X509_STORE_CTX_free(csc);
 
  925    else if (err != X509_V_ERR_INVALID_PURPOSE)
 
  929  X509_STORE_free(cert_ctx);