25#include <freerdp/config.h>
31#include <winpr/assert.h>
32#include <winpr/wtypes.h>
34#include <winpr/file.h>
35#include <winpr/crypto.h>
37#include <openssl/pem.h>
38#include <openssl/rsa.h>
39#include <openssl/bn.h>
41#include "cert_common.h"
43#include "opensslcompat.h"
45#define TAG FREERDP_TAG("core")
47static BOOL cert_info_allocate(rdpCertInfo* info,
size_t size);
49BOOL read_bignum(BYTE** dst, DWORD* length,
const BIGNUM* num, BOOL alloc)
62 const int len = BN_num_bytes(num);
68 if (*length < (UINT32)len)
76 *dst = malloc((
size_t)len);
81 crypto_reverse(*dst, (
size_t)len);
82 *length = (UINT32)len;
88BOOL cert_info_create(rdpCertInfo* dst,
const BIGNUM* rsa,
const BIGNUM* rsa_e)
90 const rdpCertInfo empty = { 0 };
97 if (!read_bignum(&dst->Modulus, &dst->ModulusLength, rsa, TRUE))
101 DWORD len =
sizeof(dst->exponent);
102 BYTE* ptr = &dst->exponent[0];
103 if (!read_bignum(&ptr, &len, rsa_e, FALSE))
113BOOL cert_info_clone(rdpCertInfo* dst,
const rdpCertInfo* src)
121 dst->ModulusLength = 0;
122 if (src->ModulusLength > 0)
124 dst->Modulus = malloc(src->ModulusLength);
127 memcpy(dst->Modulus, src->Modulus, src->ModulusLength);
128 dst->ModulusLength = src->ModulusLength;
133void cert_info_free(rdpCertInfo* info)
137 info->ModulusLength = 0;
138 info->Modulus = NULL;
141BOOL cert_info_allocate(rdpCertInfo* info,
size_t size)
144 cert_info_free(info);
146 info->Modulus = (BYTE*)malloc(size);
148 if (!info->Modulus && (size > 0))
150 WLog_ERR(TAG,
"Failed to allocate info->Modulus of size %" PRIuz, size);
153 info->ModulusLength = (UINT32)size;
157BOOL cert_info_read_modulus(rdpCertInfo* info,
size_t size,
wStream* s)
159 if (!Stream_CheckAndLogRequiredLength(TAG, s, size))
161 if (size > UINT32_MAX)
163 WLog_ERR(TAG,
"modulus size %" PRIuz
" exceeds limit of %" PRIu32, size, UINT32_MAX);
166 if (!cert_info_allocate(info, size))
168 Stream_Read(s, info->Modulus, info->ModulusLength);
172BOOL cert_info_read_exponent(rdpCertInfo* info,
size_t size,
wStream* s)
174 if (!Stream_CheckAndLogRequiredLength(TAG, s, size))
178 WLog_ERR(TAG,
"exponent size %" PRIuz
" exceeds limit of %" PRIu32, size, 4);
181 if (!info->Modulus || (info->ModulusLength == 0))
183 WLog_ERR(TAG,
"invalid modulus=%p [%" PRIu32
"]", info->Modulus, info->ModulusLength);
186 Stream_Read(s, &info->exponent[4 - size], size);
187 crypto_reverse(info->Modulus, info->ModulusLength);
188 crypto_reverse(info->exponent, 4);
192#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
193X509* x509_from_rsa(
const RSA* rsa)
195 EVP_PKEY* pubkey = NULL;
198#
if defined(LIBRESSL_VERSION_NUMBER)
206 WLog_ERR(TAG,
"BIO_new() failed");
210 const int rc = PEM_write_bio_RSA_PUBKEY(bio, (RSA*)rsa);
213 WLog_ERR(TAG,
"PEM_write_bio_RSA_PUBKEY(bio, (RSA*)rsa) failed");
217 pubkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
220 WLog_ERR(TAG,
"PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL) failed");
227 WLog_ERR(TAG,
"X509_new() failed");
231 const int res = X509_set_pubkey(x509, pubkey);
234 WLog_ERR(TAG,
"X509_set_pubkey(x509, pubkey) failed");
241 EVP_PKEY_free(pubkey);