24#include <openssl/objects.h> 
   25#include <openssl/bn.h> 
   27#include <freerdp/config.h> 
   30#include <winpr/assert.h> 
   32#include <freerdp/log.h> 
   33#include <freerdp/crypto/crypto.h> 
   36#include "privatekey.h" 
   38#define TAG FREERDP_TAG("crypto") 
   40static SSIZE_T crypto_rsa_common(
const BYTE* input, 
size_t length, UINT32 key_length,
 
   41                                 const BYTE* modulus, 
const BYTE* exponent, 
size_t exponent_size,
 
   42                                 BYTE* output, 
size_t out_length)
 
   45  int output_length = -1;
 
   46  BYTE* input_reverse = NULL;
 
   47  BYTE* modulus_reverse = NULL;
 
   48  BYTE* exponent_reverse = NULL;
 
   53  size_t bufferSize = 0;
 
   55  if (!input || !modulus || !exponent || !output)
 
   58  if (exponent_size > INT_MAX / 2)
 
   61  if (key_length >= INT_MAX / 2 - exponent_size)
 
   64  bufferSize = 2ULL * key_length + exponent_size;
 
   65  if (length > bufferSize)
 
   68  input_reverse = (BYTE*)calloc(bufferSize, 1);
 
   73  modulus_reverse = input_reverse + key_length;
 
   74  exponent_reverse = modulus_reverse + key_length;
 
   75  memcpy(modulus_reverse, modulus, key_length);
 
   76  crypto_reverse(modulus_reverse, key_length);
 
   77  memcpy(exponent_reverse, exponent, exponent_size);
 
   78  crypto_reverse(exponent_reverse, exponent_size);
 
   79  memcpy(input_reverse, input, length);
 
   80  crypto_reverse(input_reverse, length);
 
   82  if (!(ctx = BN_CTX_new()))
 
   85  if (!(mod = BN_new()))
 
   88  if (!(exp = BN_new()))
 
   97  if (!BN_bin2bn(modulus_reverse, (
int)key_length, mod))
 
  100  if (!BN_bin2bn(exponent_reverse, (
int)exponent_size, exp))
 
  102  if (!BN_bin2bn(input_reverse, (
int)length, x))
 
  104  if (BN_mod_exp(y, x, exp, mod, ctx) != 1)
 
  106  output_length = BN_bn2bin(y, output);
 
  107  if (output_length < 0)
 
  109  if (WINPR_ASSERTING_INT_CAST(
size_t, output_length) > out_length)
 
  111  crypto_reverse(output, WINPR_ASSERTING_INT_CAST(
size_t, output_length));
 
  113  if ((
size_t)output_length < key_length)
 
  115    size_t diff = key_length - WINPR_ASSERTING_INT_CAST(
size_t, output_length);
 
  116    if ((
size_t)output_length + diff > out_length)
 
  117      diff = out_length - (size_t)output_length;
 
  118    memset(output + output_length, 0, diff);
 
  128  return output_length;
 
  131static SSIZE_T crypto_rsa_public(
const BYTE* input, 
size_t length, 
const rdpCertInfo* cert,
 
  132                                 BYTE* output, 
size_t output_length)
 
  135  return crypto_rsa_common(input, length, cert->ModulusLength, cert->Modulus, cert->exponent,
 
  136                           sizeof(cert->exponent), output, output_length);
 
  139static SSIZE_T crypto_rsa_private(
const BYTE* input, 
size_t length, 
const rdpPrivateKey* key,
 
  140                                  BYTE* output, 
size_t output_length)
 
  143  const rdpCertInfo* info = freerdp_key_get_info(key);
 
  146  size_t PrivateExponentLength = 0;
 
  147  const BYTE* PrivateExponent = freerdp_key_get_exponent(key, &PrivateExponentLength);
 
  148  return crypto_rsa_common(input, length, info->ModulusLength, info->Modulus, PrivateExponent,
 
  149                           PrivateExponentLength, output, output_length);
 
  152SSIZE_T crypto_rsa_public_encrypt(
const BYTE* input, 
size_t length, 
const rdpCertInfo* cert,
 
  153                                  BYTE* output, 
size_t output_length)
 
  155  return crypto_rsa_public(input, length, cert, output, output_length);
 
  158SSIZE_T crypto_rsa_public_decrypt(
const BYTE* input, 
size_t length, 
const rdpCertInfo* cert,
 
  159                                  BYTE* output, 
size_t output_length)
 
  161  return crypto_rsa_public(input, length, cert, output, output_length);
 
  164SSIZE_T crypto_rsa_private_encrypt(
const BYTE* input, 
size_t length, 
const rdpPrivateKey* key,
 
  165                                   BYTE* output, 
size_t output_length)
 
  167  return crypto_rsa_private(input, length, key, output, output_length);
 
  170SSIZE_T crypto_rsa_private_decrypt(
const BYTE* input, 
size_t length, 
const rdpPrivateKey* key,
 
  171                                   BYTE* output, 
size_t output_length)
 
  173  return crypto_rsa_private(input, length, key, output, output_length);
 
  176void crypto_reverse(BYTE* data, 
size_t length)
 
  181  for (
size_t i = 0, j = length - 1; i < j; i++, j--)
 
  183    const BYTE temp = data[i];
 
  189char* crypto_read_pem(
const char* WINPR_RESTRICT filename, 
size_t* WINPR_RESTRICT plength)
 
  194  WINPR_ASSERT(filename);
 
  199  fp = winpr_fopen(filename, 
"r");
 
  202  const int rs = _fseeki64(fp, 0, SEEK_END);
 
  205  const int64_t size = _ftelli64(fp);
 
  208  const int rc = _fseeki64(fp, 0, SEEK_SET);
 
  212  pem = calloc(WINPR_ASSERTING_INT_CAST(
size_t, size) + 1, 
sizeof(
char));
 
  216  const size_t fr = fread(pem, (
size_t)size, 1, fp);
 
  221    *plength = strnlen(pem, WINPR_ASSERTING_INT_CAST(
size_t, size));
 
  227  char buffer[8192] = { 0 };
 
  228  WLog_WARN(TAG, 
"Failed to read PEM from file '%s' [%s]", filename,
 
  229            winpr_strerror(errno, buffer, 
sizeof(buffer)));
 
  237BOOL crypto_write_pem(
const char* WINPR_RESTRICT filename, 
const char* WINPR_RESTRICT pem,
 
  240  WINPR_ASSERT(filename);
 
  241  WINPR_ASSERT(pem || (length == 0));
 
  243  WINPR_ASSERT(filename);
 
  246  const size_t size = strnlen(pem, length) + 1;
 
  248  FILE* fp = winpr_fopen(filename, 
"w");
 
  251  rc = fwrite(pem, 1, size, fp);
 
  256    char buffer[8192] = { 0 };
 
  257    WLog_WARN(TAG, 
"Failed to write PEM [%" PRIuz 
"] to file '%s' [%s]", length, filename,
 
  258              winpr_strerror(errno, buffer, 
sizeof(buffer)));