Skip to content

Commit 8727a1a

Browse files
committed
HTCONDOR-1290: Update Scitokens-cpp to openssl 3.0
-Changed internal code to remove use of deprecated functions in openssl 3.0
1 parent 66f1a76 commit 8727a1a

File tree

1 file changed

+127
-21
lines changed

1 file changed

+127
-21
lines changed

src/scitokens_internal.cpp

Lines changed: 127 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
#include <openssl/bn.h>
1111
#include <openssl/ec.h>
1212

13+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
14+
#include <openssl/evp.h>
15+
#include <openssl/param_build.h>
16+
#endif
17+
#define EC_NAME NID_X9_62_prime256v1
18+
1319
#include "scitokens_internal.h"
1420

1521
using namespace scitokens;
@@ -243,8 +249,60 @@ std::string
243249
es256_from_coords(const std::string &x_str, const std::string &y_str) {
244250
auto x_decode = b64url_decode_nopadding(x_str);
245251
auto y_decode = b64url_decode_nopadding(y_str);
252+
std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
253+
std::unique_ptr<BIGNUM, decltype(&BN_free)> x_bignum(BN_bin2bn(reinterpret_cast<const unsigned char *>(x_decode.c_str()), x_decode.size(), nullptr), BN_free);
254+
std::unique_ptr<BIGNUM, decltype(&BN_free)> y_bignum(BN_bin2bn(reinterpret_cast<const unsigned char *>(y_decode.c_str()), y_decode.size(), nullptr), BN_free);
255+
256+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
257+
unsigned char *buf;
258+
OSSL_PARAM *params;
259+
std::unique_ptr<EC_GROUP, decltype(&EC_GROUP_free)> ec_group(EC_GROUP_new_by_curve_name(EC_NAME),EC_GROUP_free);
260+
if (!ec_group.get()) {
261+
throw UnsupportedKeyException("Unable to get OpenSSL EC group");
262+
}
246263

247-
std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), EC_KEY_free);
264+
std::unique_ptr<EC_POINT, decltype(&EC_POINT_free)> Q_point(EC_POINT_new(ec_group.get()), EC_POINT_free);
265+
if (!Q_point.get()) {
266+
throw UnsupportedKeyException("Unable to allocate new EC point");
267+
}
268+
269+
if (!EC_POINT_set_affine_coordinates(ec_group.get(), Q_point.get(), x_bignum.get(), y_bignum.get(), NULL)) {
270+
throw UnsupportedKeyException("Invalid elliptic curve point in key");
271+
}
272+
273+
size_t out_len = EC_POINT_point2buf(ec_group.get(), Q_point.get(),POINT_CONVERSION_UNCOMPRESSED,&buf,NULL);
274+
if (out_len == 0) {
275+
throw UnsupportedKeyException("Failed to convert EC point to octet base buffer");
276+
}
277+
278+
std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)> param_build(OSSL_PARAM_BLD_new(), OSSL_PARAM_BLD_free);
279+
if (!param_build.get()
280+
|| !OSSL_PARAM_BLD_push_utf8_string(param_build.get(),"group","prime256v1",0)
281+
|| !OSSL_PARAM_BLD_push_octet_string(param_build.get(),"pub",buf,out_len)
282+
|| (params = OSSL_PARAM_BLD_to_param(param_build.get())) == NULL) {
283+
throw UnsupportedKeyException("Failed to build EC public key parameters");
284+
}
285+
286+
EVP_PKEY *pkey = NULL;
287+
std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> ec_ctx(EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL), EVP_PKEY_CTX_free);
288+
if (!ec_ctx.get()) {
289+
throw UnsupportedKeyException("Failed to set EC PKEY context");
290+
}
291+
292+
if (EVP_PKEY_fromdata_init(ec_ctx.get()) <= 0
293+
|| EVP_PKEY_fromdata(ec_ctx.get(),&pkey,EVP_PKEY_PUBLIC_KEY,params) <= 0
294+
|| pkey == NULL) {
295+
throw UnsupportedKeyException("Failed to set the EC public key");
296+
}
297+
298+
if (PEM_write_bio_PUBKEY(pubkey_bio.get(), pkey) == 0) {
299+
throw UnsupportedKeyException("Failed to serialize EC public key");
300+
}
301+
EVP_PKEY_free(pkey);
302+
OSSL_PARAM_free(params);
303+
OPENSSL_free(buf);
304+
#else
305+
std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> ec(EC_KEY_new_by_curve_name(EC_NAME), EC_KEY_free);
248306
if (!ec.get()) {
249307
throw UnsupportedKeyException("OpenSSL does not support the P-256 curve");
250308
}
@@ -258,8 +316,7 @@ es256_from_coords(const std::string &x_str, const std::string &y_str) {
258316
if (!Q_point.get()) {
259317
throw UnsupportedKeyException("Unable to allocate new EC point");
260318
}
261-
std::unique_ptr<BIGNUM, decltype(&BN_free)> x_bignum(BN_bin2bn(reinterpret_cast<const unsigned char *>(x_decode.c_str()), x_decode.size(), nullptr), BN_free);
262-
std::unique_ptr<BIGNUM, decltype(&BN_free)> y_bignum(BN_bin2bn(reinterpret_cast<const unsigned char *>(y_decode.c_str()), y_decode.size(), nullptr), BN_free);
319+
263320
if (EC_POINT_set_affine_coordinates_GFp(params, Q_point.get(), x_bignum.get(), y_bignum.get(), NULL) != 1) {
264321
throw UnsupportedKeyException("Invalid elliptic curve point in key");
265322
}
@@ -268,11 +325,11 @@ es256_from_coords(const std::string &x_str, const std::string &y_str) {
268325
throw UnsupportedKeyException("Unable to set the EC public key");
269326
}
270327

271-
std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
272-
if (PEM_write_bio_EC_PUBKEY(pubkey_bio.get(), ec.get()) == 0) {
328+
if (PEM_write_bio_EC_PUBKEY(pubkey_bio.get(), ec.get()) == 0) {
273329
throw UnsupportedKeyException("Failed to serialize EC public key");
274330
}
275-
331+
#endif
332+
276333
char *mem_data;
277334
size_t mem_len = BIO_get_mem_data(pubkey_bio.get(), &mem_data);
278335
std::string result = std::string(mem_data, mem_len);
@@ -284,29 +341,57 @@ std::string
284341
rs256_from_coords(const std::string &e_str, const std::string &n_str) {
285342
auto e_decode = b64url_decode_nopadding(e_str);
286343
auto n_decode = b64url_decode_nopadding(n_str);
344+
std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
287345
std::unique_ptr<BIGNUM, decltype(&BN_free)> e_bignum(BN_bin2bn(reinterpret_cast<const unsigned char *>(e_decode.c_str()), e_decode.size(), nullptr), BN_free);
288346
std::unique_ptr<BIGNUM, decltype(&BN_free)> n_bignum(BN_bin2bn(reinterpret_cast<const unsigned char *>(n_decode.c_str()), n_decode.size(), nullptr), BN_free);
289-
290-
std::unique_ptr<RSA, decltype(&RSA_free)> rsa(RSA_new(), RSA_free);
291-
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
292-
rsa->e = e_bignum.get();
293-
rsa->n = n_bignum.get();
294-
rsa->d = nullptr;
347+
348+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
349+
OSSL_PARAM *params;
350+
std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)> rsa_ctx(EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL), EVP_PKEY_CTX_free);
351+
if (!rsa_ctx.get()) {
352+
throw UnsupportedKeyException("Failed to set RSA PKEY context");
353+
}
354+
355+
std::unique_ptr<OSSL_PARAM_BLD, decltype(&OSSL_PARAM_BLD_free)> param_build(OSSL_PARAM_BLD_new(), OSSL_PARAM_BLD_free);
356+
if (!param_build.get()
357+
|| !OSSL_PARAM_BLD_push_BN_pad(param_build.get(),"e",e_bignum.get(),BN_num_bytes(e_bignum.get()))
358+
|| !OSSL_PARAM_BLD_push_BN_pad(param_build.get(),"n",n_bignum.get(),BN_num_bytes(n_bignum.get()))
359+
|| (params = OSSL_PARAM_BLD_to_param(param_build.get())) == NULL) {
360+
throw UnsupportedKeyException("Failed to build RSA public key parameters");
361+
}
362+
363+
EVP_PKEY *pkey = NULL;
364+
if (EVP_PKEY_fromdata_init(rsa_ctx.get()) <= 0
365+
|| EVP_PKEY_fromdata(rsa_ctx.get(),&pkey,EVP_PKEY_PUBLIC_KEY,params) <= 0
366+
|| pkey == NULL) {
367+
throw UnsupportedKeyException("Failed to set the RSA public key");
368+
}
369+
370+
if (PEM_write_bio_PUBKEY(pubkey_bio.get(), pkey) == 0) {
371+
throw UnsupportedKeyException("Failed to serialize RSA public key");
372+
}
373+
EVP_PKEY_free(pkey);
374+
OSSL_PARAM_free(params);
295375
#else
296-
RSA_set0_key(rsa.get(), n_bignum.get(), e_bignum.get(), nullptr);
297-
#endif
298-
e_bignum.release();
299-
n_bignum.release();
300-
376+
std::unique_ptr<RSA, decltype(&RSA_free)> rsa(RSA_new(), RSA_free);
377+
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
378+
rsa->e = e_bignum.get();
379+
rsa->n = n_bignum.get();
380+
rsa->d = nullptr;
381+
#else
382+
RSA_set0_key(rsa.get(), n_bignum.get(), e_bignum.get(), nullptr);
383+
#endif
301384
std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> pkey(EVP_PKEY_new(), EVP_PKEY_free);
302385
if (EVP_PKEY_set1_RSA(pkey.get(), rsa.get()) != 1) {
303386
throw UnsupportedKeyException("Failed to set the public key");
304387
}
305-
306-
std::unique_ptr<BIO, decltype(&BIO_free_all)> pubkey_bio(BIO_new(BIO_s_mem()), BIO_free_all);
388+
307389
if (PEM_write_bio_PUBKEY(pubkey_bio.get(), pkey.get()) == 0) {
308390
throw UnsupportedKeyException("Failed to serialize RSA public key");
309391
}
392+
#endif
393+
e_bignum.release();
394+
n_bignum.release();
310395

311396
char *mem_data;
312397
size_t mem_len = BIO_get_mem_data(pubkey_bio.get(), &mem_data);
@@ -525,6 +610,28 @@ scitokens::Validator::store_public_ec_key(const std::string &issuer, const std::
525610
if ((size_t)BIO_write(pubkey_bio.get(), public_key.data(), public_key.size()) != public_key.size()) {
526611
return false;
527612
}
613+
614+
std::unique_ptr<BIGNUM, decltype(&BN_free)> x_bignum(BN_new(), BN_free);
615+
std::unique_ptr<BIGNUM, decltype(&BN_free)> y_bignum(BN_new(), BN_free);
616+
617+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
618+
std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> pkey(PEM_read_bio_PUBKEY(pubkey_bio.get(),nullptr,nullptr,nullptr), EVP_PKEY_free);
619+
if (!pkey.get()) {return false;}
620+
621+
std::unique_ptr<EC_GROUP, decltype(&EC_GROUP_free)> ec_group(EC_GROUP_new_by_curve_name(EC_NAME),EC_GROUP_free);
622+
if (!ec_group.get()) {
623+
throw UnsupportedKeyException("Unable to get OpenSSL EC group");
624+
}
625+
626+
std::unique_ptr<EC_POINT, decltype(&EC_POINT_free)> Q_point(EC_POINT_new(ec_group.get()), EC_POINT_free);
627+
if (!Q_point.get()) {
628+
throw UnsupportedKeyException("Unable to get OpenSSL EC point");
629+
}
630+
631+
if (!EC_POINT_get_affine_coordinates(ec_group.get(), Q_point.get(), x_bignum.get(), y_bignum.get(), NULL)) {
632+
throw UnsupportedKeyException("Unable to get OpenSSL affine coordinates");
633+
}
634+
#else
528635
std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)> pkey
529636
(PEM_read_bio_EC_PUBKEY(pubkey_bio.get(), nullptr, nullptr, nullptr), EC_KEY_free);
530637
if (!pkey) {return false;}
@@ -539,11 +646,10 @@ scitokens::Validator::store_public_ec_key(const std::string &issuer, const std::
539646
throw UnsupportedKeyException("Unable to get OpenSSL EC point");
540647
}
541648

542-
std::unique_ptr<BIGNUM, decltype(&BN_free)> x_bignum(BN_new(), BN_free);
543-
std::unique_ptr<BIGNUM, decltype(&BN_free)> y_bignum(BN_new(), BN_free);
544649
if (!EC_POINT_get_affine_coordinates_GFp(params, point, x_bignum.get(), y_bignum.get(), nullptr)) {
545650
throw UnsupportedKeyException("Unable to get OpenSSL affine coordinates");
546651
}
652+
#endif
547653

548654
auto x_num = BN_num_bytes(x_bignum.get());
549655
auto y_num = BN_num_bytes(y_bignum.get());

0 commit comments

Comments
 (0)