Skip to content

Commit

Permalink
Enable bindings for functions in LibreSSL (#15177)
Browse files Browse the repository at this point in the history
A lot of symbols that are available in LibreSSL are missing in the bindings when macro branches only checked for OpenSSL versions. I added the respective LibreSSL versions.
  • Loading branch information
straight-shoota authored Nov 15, 2024
1 parent 6cec6a9 commit 87ec603
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 20 deletions.
1 change: 1 addition & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
DOCKER_TEST_PREFIX: crystallang/crystal:${{ matrix.crystal_bootstrap_version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.2, 1.12.2, 1.13.3, 1.14.0]
flags: [""]
Expand Down
2 changes: 1 addition & 1 deletion spec/std/openssl/pkcs5_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe OpenSSL::PKCS5 do
end
end

{% if compare_versions(LibSSL::OPENSSL_VERSION, "1.0.0") >= 0 %}
{% if compare_versions(LibSSL::OPENSSL_VERSION, "1.0.0") >= 0 || LibSSL::LIBRESSL_VERSION != "0.0.0" %}
{% if compare_versions(LibSSL::OPENSSL_VERSION, "3.0.0") < 0 %}
[
{OpenSSL::Algorithm::MD4, 1, 16, "1857f69412150bca4542581d0f9e7fd1"},
Expand Down
14 changes: 7 additions & 7 deletions spec/std/openssl/ssl/context_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe OpenSSL::SSL::Context do
(context.options & OpenSSL::SSL::Options::NO_SESSION_RESUMPTION_ON_RENEGOTIATION).should eq(OpenSSL::SSL::Options::NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
(context.options & OpenSSL::SSL::Options::SINGLE_ECDH_USE).should eq(OpenSSL::SSL::Options::SINGLE_ECDH_USE)
(context.options & OpenSSL::SSL::Options::SINGLE_DH_USE).should eq(OpenSSL::SSL::Options::SINGLE_DH_USE)
{% if compare_versions(LibSSL::OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if LibSSL::Options.has_constant?(:NO_RENEGOTIATION) %}
(context.options & OpenSSL::SSL::Options::NO_RENEGOTIATION).should eq(OpenSSL::SSL::Options::NO_RENEGOTIATION)
{% end %}

Expand Down Expand Up @@ -128,12 +128,12 @@ describe OpenSSL::SSL::Context do
context = OpenSSL::SSL::Context::Client.new
level = context.security_level
context.security_level = level + 1
# SSL_CTX_get_security_level is not supported by libressl
{% if LibSSL::OPENSSL_VERSION != "0.0.0" %}

if LibSSL.responds_to?(:ssl_ctx_set_security_level)
context.security_level.should eq(level + 1)
{% else %}
else
context.security_level.should eq 0
{% end %}
end
end

it "adds temporary ecdh curve (P-256)" do
Expand Down Expand Up @@ -194,12 +194,12 @@ describe OpenSSL::SSL::Context do
context.verify_mode.should eq(OpenSSL::SSL::VerifyMode::PEER)
end

{% if compare_versions(LibSSL::OPENSSL_VERSION, "1.0.2") >= 0 %}
if LibSSL.responds_to?(:ssl_ctx_set_alpn_protos)
it "alpn_protocol=" do
context = OpenSSL::SSL::Context::Client.insecure
context.alpn_protocol = "h2"
end
{% end %}
end

it "calls #finalize on insecure client context" do
assert_finalizes("insecure_client_ctx") { OpenSSL::SSL::Context::Client.insecure }
Expand Down
13 changes: 7 additions & 6 deletions src/openssl/lib_crypto.cr
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ lib LibCrypto
alias BioMethodDestroy = Bio* -> Int
alias BioMethodCallbackCtrl = (Bio*, Int, Void*) -> Long

{% if compare_versions(LibCrypto::OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if compare_versions(LibCrypto::OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LibCrypto::LIBRESSL_VERSION, "2.7.0") >= 0 %}
type BioMethod = Void
{% else %}
struct BioMethod
Expand All @@ -129,7 +129,7 @@ lib LibCrypto
fun BIO_new(BioMethod*) : Bio*
fun BIO_free(Bio*) : Int

{% if compare_versions(LibCrypto::OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if compare_versions(LibCrypto::OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LibCrypto::LIBRESSL_VERSION, "2.7.0") >= 0 %}
fun BIO_set_data(Bio*, Void*)
fun BIO_get_data(Bio*) : Void*
fun BIO_set_init(Bio*, Int)
Expand All @@ -145,6 +145,7 @@ lib LibCrypto
fun BIO_meth_set_destroy(BioMethod*, BioMethodDestroy)
fun BIO_meth_set_callback_ctrl(BioMethod*, BioMethodCallbackCtrl)
{% end %}
# LibreSSL does not define these symbols
{% if compare_versions(LibCrypto::OPENSSL_VERSION, "1.1.1") >= 0 %}
fun BIO_meth_set_read_ex(BioMethod*, BioMethodRead)
fun BIO_meth_set_write_ex(BioMethod*, BioMethodWrite)
Expand Down Expand Up @@ -229,7 +230,7 @@ lib LibCrypto

fun evp_digestfinal_ex = EVP_DigestFinal_ex(ctx : EVP_MD_CTX, md : UInt8*, size : UInt32*) : Int32

{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LibCrypto::LIBRESSL_VERSION, "2.7.0") >= 0 %}
fun evp_md_ctx_new = EVP_MD_CTX_new : EVP_MD_CTX
fun evp_md_ctx_free = EVP_MD_CTX_free(ctx : EVP_MD_CTX)
{% else %}
Expand Down Expand Up @@ -306,7 +307,7 @@ lib LibCrypto
fun md5 = MD5(data : UInt8*, length : LibC::SizeT, md : UInt8*) : UInt8*

fun pkcs5_pbkdf2_hmac_sha1 = PKCS5_PBKDF2_HMAC_SHA1(pass : LibC::Char*, passlen : LibC::Int, salt : UInt8*, saltlen : LibC::Int, iter : LibC::Int, keylen : LibC::Int, out : UInt8*) : LibC::Int
{% if compare_versions(OPENSSL_VERSION, "1.0.0") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.0.0") >= 0 || LIBRESSL_VERSION != "0.0.0" %}
fun pkcs5_pbkdf2_hmac = PKCS5_PBKDF2_HMAC(pass : LibC::Char*, passlen : LibC::Int, salt : UInt8*, saltlen : LibC::Int, iter : LibC::Int, digest : EVP_MD, keylen : LibC::Int, out : UInt8*) : LibC::Int
{% end %}

Expand Down Expand Up @@ -380,12 +381,12 @@ lib LibCrypto

fun x509_store_add_cert = X509_STORE_add_cert(ctx : X509_STORE, x : X509) : Int

{% unless compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 %}
{% unless compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LibCrypto::LIBRESSL_VERSION, "3.0.0") >= 0 %}
fun err_load_crypto_strings = ERR_load_crypto_strings
fun openssl_add_all_algorithms = OPENSSL_add_all_algorithms_noconf
{% end %}

{% if compare_versions(OPENSSL_VERSION, "1.0.2") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.0.2") >= 0 || LIBRESSL_VERSION != "0.0.0" %}
type X509VerifyParam = Void*

@[Flags]
Expand Down
14 changes: 8 additions & 6 deletions src/openssl/lib_ssl.cr
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ lib LibSSL
NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x40000000
CRYPTOPRO_TLSEXT_BUG = 0x80000000

{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LIBRESSL_VERSION, "2.3.0") >= 0 %}
MICROSOFT_SESS_ID_BUG = 0x00000000
NETSCAPE_CHALLENGE_BUG = 0x00000000
NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000000
Expand Down Expand Up @@ -243,6 +243,7 @@ lib LibSSL
fun ssl_get_peer_certificate = SSL_get_peer_certificate(handle : SSL) : LibCrypto::X509
{% end %}

# In LibreSSL these functions are implemented as macros
{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 %}
fun ssl_ctx_get_options = SSL_CTX_get_options(ctx : SSLContext) : ULong
fun ssl_ctx_set_options = SSL_CTX_set_options(ctx : SSLContext, larg : ULong) : ULong
Expand All @@ -257,28 +258,29 @@ lib LibSSL
fun ssl_ctx_set_cert_verify_callback = SSL_CTX_set_cert_verify_callback(ctx : SSLContext, callback : CertVerifyCallback, arg : Void*)

# control TLS 1.3 session ticket generation
# LibreSSL does not seem to implement these functions
{% if compare_versions(OPENSSL_VERSION, "1.1.1") >= 0 %}
fun ssl_ctx_set_num_tickets = SSL_CTX_set_num_tickets(ctx : SSLContext, larg : LibC::SizeT) : Int
fun ssl_set_num_tickets = SSL_set_num_tickets(ctx : SSL, larg : LibC::SizeT) : Int
{% end %}

{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if compare_versions(LibSSL::OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LibSSL::LIBRESSL_VERSION, "2.3.0") >= 0 %}
fun tls_method = TLS_method : SSLMethod
{% else %}
fun ssl_library_init = SSL_library_init
fun ssl_load_error_strings = SSL_load_error_strings
fun sslv23_method = SSLv23_method : SSLMethod
{% end %}

{% if compare_versions(OPENSSL_VERSION, "1.0.2") >= 0 || compare_versions(LIBRESSL_VERSION, "2.5.0") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.0.2") >= 0 || compare_versions(LIBRESSL_VERSION, "2.1.0") >= 0 %}
alias ALPNCallback = (SSL, Char**, Char*, Char*, Int, Void*) -> Int

fun ssl_get0_alpn_selected = SSL_get0_alpn_selected(handle : SSL, data : Char**, len : LibC::UInt*) : Void
fun ssl_ctx_set_alpn_select_cb = SSL_CTX_set_alpn_select_cb(ctx : SSLContext, cb : ALPNCallback, arg : Void*) : Void
fun ssl_ctx_set_alpn_protos = SSL_CTX_set_alpn_protos(ctx : SSLContext, protos : Char*, protos_len : Int) : Int
{% end %}

{% if compare_versions(OPENSSL_VERSION, "1.0.2") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.0.2") >= 0 || compare_versions(LIBRESSL_VERSION, "2.7.0") >= 0 %}
alias X509VerifyParam = LibCrypto::X509VerifyParam

fun dtls_method = DTLS_method : SSLMethod
Expand All @@ -288,7 +290,7 @@ lib LibSSL
fun ssl_ctx_set1_param = SSL_CTX_set1_param(ctx : SSLContext, param : X509VerifyParam) : Int
{% end %}

{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if compare_versions(OPENSSL_VERSION, "1.1.0") >= 0 || compare_versions(LIBRESSL_VERSION, "3.6.0") >= 0 %}
fun ssl_ctx_set_security_level = SSL_CTX_set_security_level(ctx : SSLContext, level : Int) : Void
fun ssl_ctx_get_security_level = SSL_CTX_get_security_level(ctx : SSLContext) : Int
{% end %}
Expand All @@ -299,7 +301,7 @@ lib LibSSL
{% end %}
end

{% unless compare_versions(LibSSL::OPENSSL_VERSION, "1.1.0") >= 0 %}
{% if LibSSL.has_method?(:ssl_library_init) %}
LibSSL.ssl_library_init
LibSSL.ssl_load_error_strings
LibCrypto.openssl_add_all_algorithms
Expand Down

0 comments on commit 87ec603

Please sign in to comment.