24 #include <openssl/objects.h>
25 #include <openssl/bn.h>
27 #include <freerdp/config.h>
29 #include <winpr/crt.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")
40 static 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 ((
size_t)output_length > out_length)
111 crypto_reverse(output, output_length);
113 if ((
size_t)output_length < key_length)
115 size_t diff = key_length - 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;
131 static 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);
139 static 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);
152 SSIZE_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);
158 SSIZE_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);
164 SSIZE_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);
170 SSIZE_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);
176 void 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];
189 char* 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 SSIZE_T size = _ftelli64(fp);
208 const int rc = _fseeki64(fp, 0, SEEK_SET);
212 pem = calloc(size + 1,
sizeof(
char));
216 const size_t fr = fread(pem, (
size_t)size, 1, fp);
221 *plength = strnlen(pem, 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)));
237 BOOL 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)));