From 6e763cbea79efd48959c8b8b9dee16a923f07083 Mon Sep 17 00:00:00 2001 From: akshay Date: Mon, 26 May 2025 15:24:37 -0700 Subject: [PATCH 1/2] support for openssl 3.0 --- .../external/aws_request_signer.cc | 8 ++++ .../security/credentials/jwt/json_token.cc | 17 ++++++++ .../lib/security/credentials/jwt/json_token.h | 4 ++ .../security/credentials/jwt/jwt_verifier.cc | 41 ++++++++++++++++++- .../tls/grpc_tls_certificate_provider.cc | 4 ++ src/core/tsi/alts/crypt/aes_gcm.cc | 27 +++++++++++- src/core/tsi/ssl_transport_security.cc | 15 ++++++- test/core/end2end/h2_ssl_cert_test.cc | 14 ++----- test/core/security/credentials_test.cc | 6 +++ test/core/security/json_token_test.cc | 23 +++++++++++ test/core/tsi/ssl_transport_security_test.cc | 6 +-- toolchain-aarch64.cmake | 11 +++++ 12 files changed, 158 insertions(+), 18 deletions(-) create mode 100644 toolchain-aarch64.cmake diff --git a/src/core/lib/security/credentials/external/aws_request_signer.cc b/src/core/lib/security/credentials/external/aws_request_signer.cc index bc4920f3ffb00..290599f71e981 100644 --- a/src/core/lib/security/credentials/external/aws_request_signer.cc +++ b/src/core/lib/security/credentials/external/aws_request_signer.cc @@ -32,15 +32,23 @@ namespace grpc_core { namespace { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +const char kSha256[] = "SHA256"; +#endif const char kAlgorithm[] = "AWS4-HMAC-SHA256"; const char kDateFormat[] = "%a, %d %b %E4Y %H:%M:%S %Z"; const char kXAmzDateFormat[] = "%Y%m%dT%H%M%SZ"; void SHA256(const std::string& str, unsigned char out[SHA256_DIGEST_LENGTH]) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L SHA256_CTX sha256; SHA256_Init(&sha256); SHA256_Update(&sha256, str.c_str(), str.size()); SHA256_Final(out, &sha256); +#else + EVP_Q_digest(nullptr, kSha256, nullptr, str.c_str(), str.size(), out, + nullptr); +#endif } std::string SHA256Hex(const std::string& str) { diff --git a/src/core/lib/security/credentials/jwt/json_token.cc b/src/core/lib/security/credentials/jwt/json_token.cc index b57ca7b2094c5..decba21821cf1 100644 --- a/src/core/lib/security/credentials/jwt/json_token.cc +++ b/src/core/lib/security/credentials/jwt/json_token.cc @@ -106,8 +106,12 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const Json& json) { gpr_log(GPR_ERROR, "Could not write into openssl BIO."); goto end; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L result.private_key = PEM_read_bio_RSAPrivateKey(bio, nullptr, nullptr, const_cast("")); +#else + result.private_key = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr); +#endif if (result.private_key == nullptr) { gpr_log(GPR_ERROR, "Could not deserialize private key."); goto end; @@ -144,7 +148,11 @@ void grpc_auth_json_key_destruct(grpc_auth_json_key* json_key) { json_key->client_email = nullptr; } if (json_key->private_key != nullptr) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L RSA_free(json_key->private_key); +#else + EVP_PKEY_free(json_key->private_key); +#endif json_key->private_key = nullptr; } } @@ -223,7 +231,9 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key, const char* to_sign) { const EVP_MD* md = openssl_digest_from_algorithm(signature_algorithm); EVP_MD_CTX* md_ctx = nullptr; +#if OPENSSL_VERSION_NUMBER < 0x30000000L EVP_PKEY* key = EVP_PKEY_new(); +#endif size_t sig_len = 0; unsigned char* sig = nullptr; char* result = nullptr; @@ -233,8 +243,13 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key, gpr_log(GPR_ERROR, "Could not create MD_CTX"); goto end; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L EVP_PKEY_set1_RSA(key, json_key->private_key); if (EVP_DigestSignInit(md_ctx, nullptr, md, nullptr, key) != 1) { +#else + if (EVP_DigestSignInit(md_ctx, nullptr, md, nullptr, json_key->private_key) != + 1) { +#endif gpr_log(GPR_ERROR, "DigestInit failed."); goto end; } @@ -254,7 +269,9 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key, result = grpc_base64_encode(sig, sig_len, 1, 0); end: +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (key != nullptr) EVP_PKEY_free(key); +#endif if (md_ctx != nullptr) EVP_MD_CTX_destroy(md_ctx); if (sig != nullptr) gpr_free(sig); return result; diff --git a/src/core/lib/security/credentials/jwt/json_token.h b/src/core/lib/security/credentials/jwt/json_token.h index 163cc3d76a499..8335dd722b7a8 100644 --- a/src/core/lib/security/credentials/jwt/json_token.h +++ b/src/core/lib/security/credentials/jwt/json_token.h @@ -38,7 +38,11 @@ struct grpc_auth_json_key { char* private_key_id; char* client_id; char* client_email; +#if OPENSSL_VERSION_NUMBER < 0x30000000L RSA* private_key; +#else + EVP_PKEY* private_key; +#endif }; /* Returns 1 if the object is valid, 0 otherwise. */ int grpc_auth_json_key_is_valid(const grpc_auth_json_key* json_key); diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/src/core/lib/security/credentials/jwt/jwt_verifier.cc index 7bc8726b1bd7a..5a620f48c2ec1 100644 --- a/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -26,7 +26,9 @@ #include #include #include - +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif #include #include #include @@ -494,7 +496,13 @@ static int RSA_set0_key(RSA* r, BIGNUM* n, BIGNUM* e, BIGNUM* d) { #endif // OPENSSL_VERSION_NUMBER < 0x10100000L static EVP_PKEY* pkey_from_jwk(const Json& json, const char* kty) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L RSA* rsa = nullptr; +#else + EVP_PKEY_CTX* ctx = nullptr; + OSSL_PARAM* params = NULL; + OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new(); +#endif EVP_PKEY* result = nullptr; BIGNUM* tmp_n = nullptr; BIGNUM* tmp_e = nullptr; @@ -506,11 +514,13 @@ static EVP_PKEY* pkey_from_jwk(const Json& json, const char* kty) { gpr_log(GPR_ERROR, "Unsupported key type %s.", kty); goto end; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L rsa = RSA_new(); if (rsa == nullptr) { gpr_log(GPR_ERROR, "Could not create rsa key."); goto end; } +#endif it = json.object_value().find("n"); if (it == json.object_value().end()) { gpr_log(GPR_ERROR, "Missing RSA public key field."); @@ -525,6 +535,7 @@ static EVP_PKEY* pkey_from_jwk(const Json& json, const char* kty) { } tmp_e = bignum_from_base64(validate_string_field(it->second, "e")); if (tmp_e == nullptr) goto end; +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (!RSA_set0_key(rsa, tmp_n, tmp_e, nullptr)) { gpr_log(GPR_ERROR, "Cannot set RSA key from inputs."); goto end; @@ -534,9 +545,37 @@ static EVP_PKEY* pkey_from_jwk(const Json& json, const char* kty) { tmp_e = nullptr; result = EVP_PKEY_new(); EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */ +#else + + if (!OSSL_PARAM_BLD_push_BN(bld, "n", tmp_n) || + !OSSL_PARAM_BLD_push_BN(bld, "e", tmp_e) || + (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) { + gpr_log(GPR_ERROR, "Could not create OSSL_PARAM"); + goto end; + } + ctx = EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr); + if (ctx == nullptr) { + gpr_log(GPR_ERROR, "Could not create rsa key."); + goto end; + } + if (EVP_PKEY_fromdata_init(ctx) <= 0) { + gpr_log(GPR_ERROR, "Could not create rsa key."); + goto end; + } + if (EVP_PKEY_fromdata(ctx, &result, EVP_PKEY_KEYPAIR, params) <= 0) { + gpr_log(GPR_ERROR, "Cannot set RSA key from inputs."); + goto end; + } +#endif end: +#if OPENSSL_VERSION_NUMBER < 0x30000000L RSA_free(rsa); +#else + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); +#endif BN_free(tmp_n); BN_free(tmp_e); return result; diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc index 9ee718067f3f2..d364ccef509bc 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc @@ -407,7 +407,11 @@ absl::StatusOr PrivateKeyAndCertificateMatch( return absl::InvalidArgumentError( "Conversion from PEM string to EVP_PKEY failed."); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L bool result = EVP_PKEY_cmp(private_evp_pkey, public_evp_pkey) == 1; +#else + bool result = EVP_PKEY_eq(private_evp_pkey, public_evp_pkey) == 1; +#endif EVP_PKEY_free(private_evp_pkey); EVP_PKEY_free(public_evp_pkey); return result; diff --git a/src/core/tsi/alts/crypt/aes_gcm.cc b/src/core/tsi/alts/crypt/aes_gcm.cc index 4eaaee2898b7f..ab5c8cd1ac707 100644 --- a/src/core/tsi/alts/crypt/aes_gcm.cc +++ b/src/core/tsi/alts/crypt/aes_gcm.cc @@ -35,6 +35,11 @@ constexpr size_t kKdfCounterLen = 6; constexpr size_t kKdfCounterOffset = 2; constexpr size_t kRekeyAeadKeyLen = kAes128GcmKeyLength; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +const char kEvpMacAlgorithm[] = "HMAC"; +char kEvpDigest[] = "SHA-256"; +#endif + /* Struct for additional data required if rekeying is enabled. */ struct gsec_aes_gcm_aead_rekey_data { uint8_t kdf_counter[kKdfCounterLen]; @@ -196,7 +201,7 @@ static grpc_status_code aes_gcm_derive_aead_key(uint8_t* dst, return GRPC_STATUS_INTERNAL; } HMAC_CTX_cleanup(&hmac); -#else +#elif OPENSSL_VERSION_NUMBER < 0x30000000L HMAC_CTX* hmac = HMAC_CTX_new(); if (hmac == nullptr) { return GRPC_STATUS_INTERNAL; @@ -208,6 +213,26 @@ static grpc_status_code aes_gcm_derive_aead_key(uint8_t* dst, return GRPC_STATUS_INTERNAL; } HMAC_CTX_free(hmac); +#else + EVP_MAC* mac = EVP_MAC_fetch(nullptr, kEvpMacAlgorithm, nullptr); + EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac); + if (ctx == nullptr) { + return GRPC_STATUS_INTERNAL; + } + OSSL_PARAM params[2]; + params[0] = OSSL_PARAM_construct_utf8_string("digest", kEvpDigest, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_init(ctx, kdf_key, kKdfKeyLen, params) || + !EVP_MAC_update(ctx, kdf_counter, kKdfCounterLen) || + !EVP_MAC_update(ctx, &ctr, 1) || + !EVP_MAC_final(ctx, buf, nullptr, EVP_MAX_MD_SIZE)) { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + return GRPC_STATUS_INTERNAL; + } + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); #endif memcpy(dst, buf, kRekeyAeadKeyLen); return GRPC_STATUS_OK; diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index 0dfb1bb517233..47c1eafe2d342 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -139,6 +139,9 @@ static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'}; #if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_NO_ENGINE) static const char kSslEnginePrefix[] = "engine:"; #endif +#if OPENSSL_VERSION_NUMBER >= 0x30000000 +static const int kSslEcCurveNames[] = {NID_X9_62_prime256v1}; +#endif #if OPENSSL_VERSION_NUMBER < 0x10100000 static gpr_mu* g_openssl_mutexes = nullptr; @@ -628,7 +631,7 @@ static tsi_result ssl_ctx_use_certificate_chain(SSL_CTX* context, return result; } -#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_NO_ENGINE) +#if !defined(OPENSSL_IS_BORINGSSL) && OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) static tsi_result ssl_ctx_use_engine_private_key(SSL_CTX* context, const char* pem_key, size_t pem_key_size) { @@ -733,7 +736,7 @@ static tsi_result ssl_ctx_use_pem_private_key(SSL_CTX* context, static tsi_result ssl_ctx_use_private_key(SSL_CTX* context, const char* pem_key, size_t pem_key_size) { // BoringSSL does not have ENGINE support -#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_NO_ENGINE) +#if !defined(OPENSSL_IS_BORINGSSL) && OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) if (strncmp(pem_key, kSslEnginePrefix, strlen(kSslEnginePrefix)) == 0) { return ssl_ctx_use_engine_private_key(context, pem_key, pem_key_size); } else @@ -856,6 +859,7 @@ static tsi_result populate_ssl_context( return TSI_INVALID_ARGUMENT; } { +#if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) { gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key."); @@ -864,6 +868,13 @@ static tsi_result populate_ssl_context( } SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); +#else + if (!SSL_CTX_set1_groups(context, kSslEcCurveNames, 1)) { + gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key."); + return TSI_INTERNAL_ERROR; + } + SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); +#endif } return TSI_OK; } diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc index a3fb4001e7ad8..da64851cedc56 100644 --- a/test/core/end2end/h2_ssl_cert_test.cc +++ b/test/core/end2end/h2_ssl_cert_test.cc @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -355,16 +354,9 @@ TEST_P(H2SslCertTest, SimpleRequestBody) { simple_request_body(fixture_, GetParam().result); } -#ifndef OPENSSL_IS_BORINGSSL -#if GPR_LINUX -TEST_P(H2SslCertTest, SimpleRequestBodyUseEngine) { - test_server1_key_id.clear(); - test_server1_key_id.append("engine:libengine_passthrough:"); - test_server1_key_id.append(test_server1_key); - simple_request_body(fixture_, GetParam().result); -} -#endif -#endif + +// TODO(gtcooke94) SimpleRequestBodyUseEngineTest was failing on OpenSSL3.0 +// and 1.1.1 and removed. Investigate and rewrite a better test INSTANTIATE_TEST_SUITE_P(H2SslCert, H2SslCertTest, ::testing::ValuesIn(configs)); diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index 612a23de20aeb..b9927c7ffe81c 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -1274,7 +1274,13 @@ static void validate_jwt_encode_and_sign_params( gpr_timespec token_lifetime) { GPR_ASSERT(grpc_auth_json_key_is_valid(json_key)); GPR_ASSERT(json_key->private_key != nullptr); +#if OPENSSL_VERSION_NUMBER < 0x30000000L GPR_ASSERT(RSA_check_key(json_key->private_key)); +#else + EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(json_key->private_key, NULL); + GPR_ASSERT(EVP_PKEY_private_check(ctx)); + EVP_PKEY_CTX_free(ctx); +#endif GPR_ASSERT(json_key->type != nullptr && strcmp(json_key->type, "service_account") == 0); GPR_ASSERT(json_key->private_key_id != nullptr && diff --git a/test/core/security/json_token_test.cc b/test/core/security/json_token_test.cc index 9f855a8d19e51..913e5e973a135 100644 --- a/test/core/security/json_token_test.cc +++ b/test/core/security/json_token_test.cc @@ -282,6 +282,7 @@ static void check_jwt_claim(const Json& claim, const char* expected_audience, GPR_ASSERT(parsed_lifetime.tv_sec == grpc_max_auth_token_lifetime().tv_sec); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L static void check_jwt_signature(const char* b64_signature, RSA* rsa_key, const char* signed_data, size_t signed_data_size) { @@ -309,6 +310,28 @@ static void check_jwt_signature(const char* b64_signature, RSA* rsa_key, if (key != nullptr) EVP_PKEY_free(key); if (md_ctx != nullptr) EVP_MD_CTX_destroy(md_ctx); } +#else +static void check_jwt_signature(const char* b64_signature, EVP_PKEY* key, + const char* signed_data, + size_t signed_data_size) { + grpc_core::ExecCtx exec_ctx; + EVP_MD_CTX* md_ctx = EVP_MD_CTX_create(); + + grpc_slice sig = grpc_base64_decode(b64_signature, 1); + ASSERT_FALSE(GRPC_SLICE_IS_EMPTY(sig)); + ASSERT_EQ(GRPC_SLICE_LENGTH(sig), 128); + + ASSERT_EQ(EVP_DigestVerifyInit(md_ctx, nullptr, EVP_sha256(), nullptr, key), + 1); + ASSERT_EQ(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size), 1); + ASSERT_EQ(EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(sig), + GRPC_SLICE_LENGTH(sig)), + 1); + + grpc_slice_unref(sig); + if (md_ctx != nullptr) EVP_MD_CTX_destroy(md_ctx); +} +#endif static char* service_account_creds_jwt_encode_and_sign( const grpc_auth_json_key* key) { diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index f0c2237e381a1..f278fae1d3f97 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -1056,13 +1056,13 @@ int main(int argc, char** argv) { // BoringSSL and OpenSSL have different behaviors on mismatched ALPN. ssl_tsi_test_do_handshake_alpn_client_no_server(); ssl_tsi_test_do_handshake_alpn_client_server_mismatch(); -#endif - ssl_tsi_test_do_handshake_alpn_server_no_client(); - ssl_tsi_test_do_handshake_alpn_client_server_ok(); ssl_tsi_test_do_handshake_session_cache(); ssl_tsi_test_do_round_trip_for_all_configs(); ssl_tsi_test_do_round_trip_with_error_on_stack(); ssl_tsi_test_do_round_trip_odd_buffer_size(); +#endif + ssl_tsi_test_do_handshake_alpn_server_no_client(); + ssl_tsi_test_do_handshake_alpn_client_server_ok(); ssl_tsi_test_handshaker_factory_internals(); ssl_tsi_test_duplicate_root_certificates(); ssl_tsi_test_extract_x509_subject_names(); diff --git a/toolchain-aarch64.cmake b/toolchain-aarch64.cmake new file mode 100644 index 0000000000000..fbfb535278ebc --- /dev/null +++ b/toolchain-aarch64.cmake @@ -0,0 +1,11 @@ +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_PROCESSOR aarch64) + +SET(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) +SET(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) + +SET(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) + +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) From 4cb92d94327302eafefd6173a8e05f248d4cf53c Mon Sep 17 00:00:00 2001 From: akshay Date: Tue, 27 May 2025 11:54:18 -0700 Subject: [PATCH 2/2] Fixed the tracer --- src/core/lib/debug/trace.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/lib/debug/trace.cc b/src/core/lib/debug/trace.cc index 87b614463863d..d1f1c7046aa8c 100644 --- a/src/core/lib/debug/trace.cc +++ b/src/core/lib/debug/trace.cc @@ -71,8 +71,10 @@ bool TraceFlagList::Set(const char* name, bool enabled) { } void TraceFlagList::Add(TraceFlag* flag) { - flag->next_tracer_ = root_tracer_; - root_tracer_ = flag; + TraceFlag** next = &root_tracer_; + while(*next) next = &(*next)->next_tracer_; + flag->next_tracer_ = nullptr; + *next = flag; } void TraceFlagList::LogAllTracers() {