[core,aad] use rdpPrivateKey instead of direct SSL

This commit is contained in:
akallabeth 2023-04-25 11:20:00 +02:00 committed by akallabeth
parent b698655176
commit cf477c581c

View File

@ -23,6 +23,8 @@
#include <string.h> #include <string.h>
#include <freerdp/crypto/crypto.h> #include <freerdp/crypto/crypto.h>
#include <freerdp/crypto/privatekey.h>
#include "../crypto/privatekey.h"
#ifdef WITH_CJSON #ifdef WITH_CJSON
#include <cjson/cJSON.h> #include <cjson/cJSON.h>
@ -55,7 +57,7 @@ struct rdp_aad
rdpContext* rdpcontext; rdpContext* rdpcontext;
rdpTransport* transport; rdpTransport* transport;
char* access_token; char* access_token;
EVP_PKEY* pop_key; rdpPrivateKey* key;
char* kid; char* kid;
char* nonce; char* nonce;
char* hostname; char* hostname;
@ -122,7 +124,7 @@ static const char token_http_request_body[] =
"76844c9b6999" "76844c9b6999"
"\r\n\r\n"; "\r\n\r\n";
static BOOL get_encoded_rsa_params(wLog* wlog, EVP_PKEY* pkey, char** e, char** n); static BOOL get_encoded_rsa_params(wLog* wlog, rdpPrivateKey* key, char** e, char** n);
static BOOL generate_pop_key(rdpAad* aad); static BOOL generate_pop_key(rdpAad* aad);
static BOOL read_http_message(rdpAad* aad, BIO* bio, long* status_code, char** content, static BOOL read_http_message(rdpAad* aad, BIO* bio, long* status_code, char** content,
size_t* content_length); size_t* content_length);
@ -579,7 +581,7 @@ static char* aad_create_jws_payload(rdpAad* aad, const char* ts_nonce)
char* e = NULL; char* e = NULL;
char* n = NULL; char* n = NULL;
if (!get_encoded_rsa_params(aad->log, aad->pop_key, &e, &n)) if (!get_encoded_rsa_params(aad->log, aad->key, &e, &n))
return NULL; return NULL;
/* Construct the base64url encoded JWS payload */ /* Construct the base64url encoded JWS payload */
@ -607,22 +609,22 @@ static char* aad_create_jws_payload(rdpAad* aad, const char* ts_nonce)
return jws_payload; return jws_payload;
} }
static BOOL aad_update_digest(rdpAad* aad, EVP_MD_CTX* ctx, const char* what) static BOOL aad_update_digest(rdpAad* aad, WINPR_DIGEST_CTX* ctx, const char* what)
{ {
WINPR_ASSERT(aad); WINPR_ASSERT(aad);
WINPR_ASSERT(ctx); WINPR_ASSERT(ctx);
WINPR_ASSERT(what); WINPR_ASSERT(what);
const int dsu1 = EVP_DigestSignUpdate(ctx, what, strlen(what)); const BOOL dsu1 = winpr_DigestSign_Update(ctx, what, strlen(what));
if (dsu1 <= 0) if (!dsu1)
{ {
WLog_Print(aad->log, WLOG_ERROR, "EVP_DigestSignUpdate [%s] failed with %d", what, dsu1); WLog_Print(aad->log, WLOG_ERROR, "winpr_DigestSign_Update [%s] failed", what);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
static char* aad_final_digest(rdpAad* aad, EVP_MD_CTX* ctx) static char* aad_final_digest(rdpAad* aad, WINPR_DIGEST_CTX* ctx)
{ {
char* jws_signature = NULL; char* jws_signature = NULL;
@ -630,10 +632,10 @@ static char* aad_final_digest(rdpAad* aad, EVP_MD_CTX* ctx)
WINPR_ASSERT(ctx); WINPR_ASSERT(ctx);
size_t siglen = 0; size_t siglen = 0;
const int dsf = EVP_DigestSignFinal(ctx, NULL, &siglen); const int dsf = winpr_DigestSign_Final(ctx, NULL, &siglen);
if (dsf <= 0) if (dsf <= 0)
{ {
WLog_Print(aad->log, WLOG_ERROR, "EVP_DigestSignFinal failed with %d", dsf); WLog_Print(aad->log, WLOG_ERROR, "winpr_DigestSign_Final failed with %d", dsf);
return FALSE; return FALSE;
} }
@ -645,17 +647,17 @@ static char* aad_final_digest(rdpAad* aad, EVP_MD_CTX* ctx)
} }
size_t fsiglen = siglen; size_t fsiglen = siglen;
const int dsf2 = EVP_DigestSignFinal(ctx, (BYTE*)buffer, &fsiglen); const int dsf2 = winpr_DigestSign_Final(ctx, (BYTE*)buffer, &fsiglen);
if (dsf2 <= 0) if (dsf2 <= 0)
{ {
WLog_Print(aad->log, WLOG_ERROR, "EVP_DigestSignFinal failed with %d", dsf2); WLog_Print(aad->log, WLOG_ERROR, "winpr_DigestSign_Final failed with %d", dsf2);
goto fail; goto fail;
} }
if (siglen != fsiglen) if (siglen != fsiglen)
{ {
WLog_Print(aad->log, WLOG_ERROR, WLog_Print(aad->log, WLOG_ERROR,
"EVP_DigestSignFinal returned different sizes, first %" PRIuz " then %" PRIuz, "winpr_DigestSignFinal returned different sizes, first %" PRIuz " then %" PRIuz,
siglen, fsiglen); siglen, fsiglen);
goto fail; goto fail;
} }
@ -671,17 +673,10 @@ static char* aad_create_jws_signature(rdpAad* aad, const char* jws_header, const
WINPR_ASSERT(aad); WINPR_ASSERT(aad);
EVP_MD_CTX* md_ctx = EVP_MD_CTX_new(); WINPR_DIGEST_CTX* md_ctx = freerdp_key_digest_sign(aad->key, WINPR_MD_SHA256);
if (!md_ctx) if (!md_ctx)
{ {
WLog_Print(aad->log, WLOG_ERROR, "EVP_MD_CTX_new failed"); WLog_Print(aad->log, WLOG_ERROR, "winpr_Digest_New failed");
goto fail;
}
const int rdsi = EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, aad->pop_key);
if (rdsi <= 0)
{
WLog_Print(aad->log, WLOG_ERROR, "EVP_DigestSignInit failed with %d", rdsi);
goto fail; goto fail;
} }
@ -694,7 +689,7 @@ static char* aad_create_jws_signature(rdpAad* aad, const char* jws_header, const
jws_signature = aad_final_digest(aad, md_ctx); jws_signature = aad_final_digest(aad, md_ctx);
fail: fail:
EVP_MD_CTX_free(md_ctx); winpr_Digest_Free(md_ctx);
return jws_signature; return jws_signature;
} }
@ -905,44 +900,8 @@ static BOOL read_http_message(rdpAad* aad, BIO* bio, long* status_code, char** c
static BOOL generate_rsa_2048(rdpAad* aad) static BOOL generate_rsa_2048(rdpAad* aad)
{ {
BOOL rc = FALSE;
WINPR_ASSERT(aad); WINPR_ASSERT(aad);
return freerdp_key_generate(aad->key, 2048);
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!aad)
{
WLog_Print(aad->log, WLOG_ERROR, "EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL) failed");
goto fail;
}
const int rki = EVP_PKEY_keygen_init(ctx);
if (rki <= 0)
{
WLog_Print(aad->log, WLOG_ERROR, "EVP_PKEY_keygen_init failed with %d", rki);
goto fail;
}
const int key_bits = 2048;
const int rkb = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits);
if (rkb <= 0)
{
WLog_Print(aad->log, WLOG_ERROR, "EVP_PKEY_CTX_set_rsa_keygen_bits(%d) failed with %d",
key_bits, rkb);
goto fail;
}
const int rkg = EVP_PKEY_keygen(ctx, &aad->pop_key);
if (rkg <= 0)
{
WLog_Print(aad->log, WLOG_ERROR, "EVP_PKEY_keygen failed with %d", rkg);
goto fail;
}
rc = TRUE;
fail:
EVP_PKEY_CTX_free(ctx);
return rc;
} }
static char* generate_rsa_digest_base64_str(rdpAad* aad, const char* input, size_t ilen) static char* generate_rsa_digest_base64_str(rdpAad* aad, const char* input, size_t ilen)
@ -1018,7 +977,7 @@ BOOL generate_pop_key(rdpAad* aad)
goto fail; goto fail;
/* Encode the public key as a JWK */ /* Encode the public key as a JWK */
if (!get_encoded_rsa_params(aad->log, aad->pop_key, &e, &n)) if (!get_encoded_rsa_params(aad->log, aad->key, &e, &n))
goto fail; goto fail;
size_t blen = 0; size_t blen = 0;
@ -1043,34 +1002,18 @@ fail:
return ret; return ret;
} }
static char* bn_to_base64_url(wLog* wlog, BIGNUM* bn) static char* bn_to_base64_url(wLog* wlog, rdpPrivateKey* key, enum FREERDP_KEY_PARAM param)
{ {
WINPR_ASSERT(wlog); WINPR_ASSERT(wlog);
WINPR_ASSERT(bn); WINPR_ASSERT(key);
const int length = BN_num_bytes(bn); size_t len = 0;
if (length < 0) char* bn = freerdp_key_get_param(key, param, &len);
{ if (!bn)
WLog_Print(wlog, WLOG_ERROR, "BN_num_bytes failed with %d", length);
return NULL; return NULL;
}
const size_t alloc_size = (size_t)length + 1ull; char* b64 = crypto_base64url_encode(bn, len);
BYTE* buf = calloc(alloc_size, sizeof(BYTE)); free(bn);
if (!buf)
{
return NULL;
}
const int bnlen = BN_bn2bin(bn, buf);
if (bnlen != length)
{
free(buf);
WLog_Print(wlog, WLOG_ERROR, "BN_bn2bin returned %d, expected result %d", bnlen, length);
return NULL;
}
char* b64 = crypto_base64url_encode(buf, (size_t)length);
free(buf);
if (!b64) if (!b64)
WLog_Print(wlog, WLOG_ERROR, "failed base64 url encode BIGNUM"); WLog_Print(wlog, WLOG_ERROR, "failed base64 url encode BIGNUM");
@ -1078,62 +1021,28 @@ static char* bn_to_base64_url(wLog* wlog, BIGNUM* bn)
return b64; return b64;
} }
BOOL get_encoded_rsa_params(wLog* wlog, EVP_PKEY* pkey, char** pe, char** pn) BOOL get_encoded_rsa_params(wLog* wlog, rdpPrivateKey* key, char** pe, char** pn)
{ {
BOOL rc = FALSE; BOOL rc = FALSE;
BIGNUM *bn_e = NULL, *bn_n = NULL;
char* e = NULL; char* e = NULL;
char* n = NULL; char* n = NULL;
WINPR_ASSERT(wlog); WINPR_ASSERT(wlog);
WINPR_ASSERT(pkey); WINPR_ASSERT(key);
WINPR_ASSERT(pe); WINPR_ASSERT(pe);
WINPR_ASSERT(pn); WINPR_ASSERT(pn);
*pe = NULL; *pe = NULL;
*pn = NULL; *pn = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L e = bn_to_base64_url(wlog, key, FREERDP_KEY_PARAM_RSA_E);
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e))
{
WLog_Print(wlog, WLOG_ERROR, "failed to get RSA E");
goto fail;
}
if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n))
{
WLog_Print(wlog, WLOG_ERROR, "failed to get RSA N");
goto fail;
}
#else
{
const RSA* rsa = NULL;
if (!(rsa = EVP_PKEY_get0_RSA(pkey)))
{
WLog_Print(wlog, WLOG_ERROR, "failed to get RSA");
goto fail;
}
if (!(bn_e = BN_dup(RSA_get0_e(rsa))))
{
WLog_Print(wlog, WLOG_ERROR, "failed to get RSA E");
goto fail;
}
if (!(bn_n = BN_dup(RSA_get0_n(rsa))))
{
WLog_Print(wlog, WLOG_ERROR, "failed to get RSA N");
goto fail;
}
}
#endif
e = bn_to_base64_url(wlog, bn_e);
if (!e) if (!e)
{ {
WLog_Print(wlog, WLOG_ERROR, "failed base64 url encode RSA E"); WLog_Print(wlog, WLOG_ERROR, "failed base64 url encode RSA E");
goto fail; goto fail;
} }
n = bn_to_base64_url(wlog, bn_n); n = bn_to_base64_url(wlog, key, FREERDP_KEY_PARAM_RSA_N);
if (!n) if (!n)
{ {
WLog_Print(wlog, WLOG_ERROR, "failed base64 url encode RSA N"); WLog_Print(wlog, WLOG_ERROR, "failed base64 url encode RSA N");
@ -1142,8 +1051,6 @@ BOOL get_encoded_rsa_params(wLog* wlog, EVP_PKEY* pkey, char** pe, char** pn)
rc = TRUE; rc = TRUE;
fail: fail:
BN_free(bn_e);
BN_free(bn_n);
if (!rc) if (!rc)
{ {
free(e); free(e);
@ -1182,10 +1089,16 @@ rdpAad* aad_new(rdpContext* context, rdpTransport* transport)
return NULL; return NULL;
aad->log = WLog_Get(FREERDP_TAG("aad")); aad->log = WLog_Get(FREERDP_TAG("aad"));
aad->key = freerdp_key_new();
if (!aad->key)
goto fail;
aad->rdpcontext = context; aad->rdpcontext = context;
aad->transport = transport; aad->transport = transport;
return aad; return aad;
fail:
aad_free(aad);
return NULL;
} }
void aad_free(rdpAad* aad) void aad_free(rdpAad* aad)
@ -1197,7 +1110,7 @@ void aad_free(rdpAad* aad)
free(aad->nonce); free(aad->nonce);
free(aad->access_token); free(aad->access_token);
free(aad->kid); free(aad->kid);
EVP_PKEY_free(aad->pop_key); freerdp_key_free(aad->key);
free(aad); free(aad);
} }