diff --git a/openssl-dynamic/src/main/c/ssl.c b/openssl-dynamic/src/main/c/ssl.c index 90af1b56e..f441a3f4d 100644 --- a/openssl-dynamic/src/main/c/ssl.c +++ b/openssl-dynamic/src/main/c/ssl.c @@ -2670,26 +2670,26 @@ TCN_IMPLEMENT_CALL(void, SSL, setRenegotiateMode)(TCN_STDARGS, jlong ssl, jint m } TCN_IMPLEMENT_CALL(void, SSL, addCredential)(TCN_STDARGS, jlong ssl, jlong cred) { + if (!check_credential_api(e)) return; SSL *ssl_ = J2P(ssl, SSL *); TCN_CHECK_NULL(ssl_, ssl, /* void */); - + #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* credential = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(credential, credential, /* void */); - + int result = SSL_add1_credential(ssl_, credential); if (result == 0) { tcn_Throw(e, "Failed to add credential to SSL"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL API is only supported by BoringSSL"); -#endif // OPENSSL_IS_BORINGSSL +#endif } TCN_IMPLEMENT_CALL(jlong, SSL, getSelectedCredential)(TCN_STDARGS, jlong ssl) { + if (!check_credential_api(e)) return 0; SSL *ssl_ = J2P(ssl, SSL *); TCN_CHECK_NULL(ssl_, ssl, 0); - + #ifdef OPENSSL_IS_BORINGSSL const SSL_CREDENTIAL* credential = SSL_get0_selected_credential(ssl_); if (credential == NULL) { @@ -2697,9 +2697,8 @@ TCN_IMPLEMENT_CALL(jlong, SSL, getSelectedCredential)(TCN_STDARGS, jlong ssl) { } return (jlong)(intptr_t)credential; #else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL API is only supported by BoringSSL"); - return 0; -#endif // OPENSSL_IS_BORINGSSL + return 0; // Unreachable - check_credential_api throws +#endif } // JNI Method Registration Table Begin diff --git a/openssl-dynamic/src/main/c/ssl_private.h b/openssl-dynamic/src/main/c/ssl_private.h index 02032a429..3f44760ff 100644 --- a/openssl-dynamic/src/main/c/ssl_private.h +++ b/openssl-dynamic/src/main/c/ssl_private.h @@ -518,4 +518,42 @@ enum ssl_verify_result_t tcn_SSL_cert_custom_verify(SSL* ssl, uint8_t *out_alert #define tcn_SSL_set1_curves(s, glist, glistlen) SSL_ctrl(s, SSL_CTRL_SET_GROUPS, glistlen,(char *)(glist)) #endif // defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) +// SSL_CREDENTIAL API runtime detection for FIPS compatibility +#ifdef OPENSSL_IS_BORINGSSL +// Use weak symbols to detect if SSL_CREDENTIAL API is available at runtime +// FIPS BoringSSL builds (fips-20230428 and earlier) don't have these symbols +__attribute__((weak)) extern SSL_CREDENTIAL* SSL_CREDENTIAL_new_x509(void); +__attribute__((weak)) extern SSL_CREDENTIAL* SSL_CREDENTIAL_new_delegated(void); +__attribute__((weak)) extern void SSL_CREDENTIAL_free(SSL_CREDENTIAL*); +__attribute__((weak)) extern void SSL_CREDENTIAL_up_ref(SSL_CREDENTIAL*); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_private_key(SSL_CREDENTIAL*, EVP_PKEY*); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_cert_chain(SSL_CREDENTIAL*, CRYPTO_BUFFER *const*, size_t); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_trust_anchor_id(SSL_CREDENTIAL*, const uint8_t*, size_t); +__attribute__((weak)) extern void SSL_CREDENTIAL_set_must_match_issuer(SSL_CREDENTIAL*, int); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_ocsp_response(SSL_CREDENTIAL*, CRYPTO_BUFFER*); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_signed_cert_timestamp_list(SSL_CREDENTIAL*, CRYPTO_BUFFER*); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_certificate_properties(SSL_CREDENTIAL*, CRYPTO_BUFFER*); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_signing_algorithm_prefs(SSL_CREDENTIAL*, const uint16_t*, size_t); +__attribute__((weak)) extern int SSL_CREDENTIAL_set1_delegated_credential(SSL_CREDENTIAL*, CRYPTO_BUFFER*); +__attribute__((weak)) extern int SSL_add1_credential(SSL*, SSL_CREDENTIAL*); +__attribute__((weak)) extern int SSL_CTX_add1_credential(SSL_CTX*, SSL_CREDENTIAL*); +__attribute__((weak)) extern const SSL_CREDENTIAL* SSL_get0_selected_credential(const SSL*); + +// Check if credential API is available and throw if not +// Returns 1 if available, 0 if not (with exception thrown) +static inline int check_credential_api(JNIEnv* e) { + if (SSL_CREDENTIAL_new_x509 == NULL) { + tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL API not available."); + return 0; + } + return 1; +} + +#else +__attribute__((unused)) static inline int check_credential_api(JNIEnv* e) { + tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL API not available."); + return 0; +} +#endif // OPENSSL_IS_BORINGSSL + #endif /* SSL_PRIVATE_H */ diff --git a/openssl-dynamic/src/main/c/sslcontext.c b/openssl-dynamic/src/main/c/sslcontext.c index e81d6d5e4..6f0f7f6b0 100644 --- a/openssl-dynamic/src/main/c/sslcontext.c +++ b/openssl-dynamic/src/main/c/sslcontext.c @@ -2945,6 +2945,7 @@ TCN_IMPLEMENT_CALL(jint, SSLContext, addCertificateCompressionAlgorithm0)(TCN_ST } TCN_IMPLEMENT_CALL(void, SSLContext, addCredential)(TCN_STDARGS, jlong ctx, jlong cred) { + if (!check_credential_api(e)) return; tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *); TCN_CHECK_NULL(c, ctx, /* void */); @@ -2956,9 +2957,7 @@ TCN_IMPLEMENT_CALL(void, SSLContext, addCredential)(TCN_STDARGS, jlong ctx, jlon if (result == 0) { tcn_Throw(e, "Failed to add credential to SSL_CTX"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL API is only supported by BoringSSL"); -#endif // OPENSSL_IS_BORINGSSL +#endif } // JNI Method Registration Table Begin diff --git a/openssl-dynamic/src/main/c/sslcredential.c b/openssl-dynamic/src/main/c/sslcredential.c index 18181bda2..76156e6c5 100644 --- a/openssl-dynamic/src/main/c/sslcredential.c +++ b/openssl-dynamic/src/main/c/sslcredential.c @@ -43,39 +43,38 @@ static void throw_openssl_error(JNIEnv* env, const char* msg) { // Core SSL_CREDENTIAL functions TCN_IMPLEMENT_CALL(jlong, SSLCredential, newX509)(TCN_STDARGS) { + if (!check_credential_api(e)) return 0; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* cred = SSL_CREDENTIAL_new_x509(); TCN_CHECK_NULL(cred, credential, 0); return (jlong)(intptr_t)cred; #else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_new_x509 is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); - return 0; + return 0; // Unreachable - check_credential_api throws #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, upRef)(TCN_STDARGS, jlong cred) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); SSL_CREDENTIAL_up_ref(c); -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_up_ref is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, free)(TCN_STDARGS, jlong cred) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; if (c != NULL) { SSL_CREDENTIAL_free(c); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_free is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } // SSL_CREDENTIAL configuration methods TCN_IMPLEMENT_CALL(void, SSLCredential, setPrivateKey)(TCN_STDARGS, jlong cred, jlong key) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; EVP_PKEY* pkey = (EVP_PKEY*)(intptr_t)key; @@ -86,12 +85,11 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setPrivateKey)(TCN_STDARGS, jlong cred, if (SSL_CREDENTIAL_set1_private_key(c, pkey) == 0) { throw_openssl_error(e, "Failed to set private key"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_private_key is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setCertChain)(TCN_STDARGS, jlong cred, jlongArray certs) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -125,12 +123,11 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setCertChain)(TCN_STDARGS, jlong cred, j if (result == 0) { throw_openssl_error(e, "Failed to set certificate chain"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_cert_chain is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setOcspResponse)(TCN_STDARGS, jlong cred, jbyteArray ocsp) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -156,12 +153,11 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setOcspResponse)(TCN_STDARGS, jlong cred if (result == 0) { throw_openssl_error(e, "Failed to set OCSP response"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_ocsp_response is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setSigningAlgorithmPrefs)(TCN_STDARGS, jlong cred, jintArray prefs) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -194,12 +190,11 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setSigningAlgorithmPrefs)(TCN_STDARGS, j if (result == 0) { throw_openssl_error(e, "Failed to set signing algorithm preferences"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_signing_algorithm_prefs is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setCertificateProperties)(TCN_STDARGS, jlong cred, jbyteArray cert_props) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -225,12 +220,11 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setCertificateProperties)(TCN_STDARGS, j if (result == 0) { throw_openssl_error(e, "Failed to set certificate properties"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_certificate_properties is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setSignedCertTimestampList)(TCN_STDARGS, jlong cred, jbyteArray sct_list) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -256,23 +250,21 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setSignedCertTimestampList)(TCN_STDARGS, if (result == 0) { throw_openssl_error(e, "Failed to set signed certificate timestamp list"); } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_signed_cert_timestamp_list is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setMustMatchIssuer)(TCN_STDARGS, jlong cred, jboolean match) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); SSL_CREDENTIAL_set_must_match_issuer(c, match == JNI_TRUE ? 1 : 0); -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set_must_match_issuer is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } // Trust anchor configuration TCN_IMPLEMENT_CALL(void, SSLCredential, setTrustAnchorId)(TCN_STDARGS, jlong cred, jbyteArray id) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -294,13 +286,12 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setTrustAnchorId)(TCN_STDARGS, jlong cre throw_openssl_error(e, "Failed to set trust anchor ID"); return; } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_trust_anchor_id is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif } // Delegated credentials TCN_IMPLEMENT_CALL(jlong, SSLCredential, newDelegated)(TCN_STDARGS) { + if (!check_credential_api(e)) return 0; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* credential = SSL_CREDENTIAL_new_delegated(); if (credential == NULL) { @@ -309,12 +300,12 @@ TCN_IMPLEMENT_CALL(jlong, SSLCredential, newDelegated)(TCN_STDARGS) { } return (jlong)(intptr_t)credential; #else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_new_delegated is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); - return 0; + return 0; // Unreachable - check_credential_api throws #endif } TCN_IMPLEMENT_CALL(void, SSLCredential, setDelegatedCredential)(TCN_STDARGS, jlong cred, jbyteArray dc) { + if (!check_credential_api(e)) return; #ifdef OPENSSL_IS_BORINGSSL SSL_CREDENTIAL* c = (SSL_CREDENTIAL*)(intptr_t)cred; TCN_CHECK_NULL(c, credential, /* void */); @@ -341,8 +332,6 @@ TCN_IMPLEMENT_CALL(void, SSLCredential, setDelegatedCredential)(TCN_STDARGS, jlo throw_openssl_error(e, "Failed to set delegated credential"); return; } -#else - tcn_ThrowUnsupportedOperationException(e, "SSL_CREDENTIAL_set1_delegated_credential is not supported. SSL_CREDENTIAL API is a BoringSSL-specific feature."); #endif }