From d630481d33d2bf50dd6bea6bfa662d1810581c38 Mon Sep 17 00:00:00 2001 From: Kevin Leung Date: Thu, 9 Jul 2026 20:12:52 +1000 Subject: [PATCH 1/2] eval mbedtls: add custom BIO/ALPN/own-cert APIs for libuv TLS integration Expose eval mbedtls primitives needed for libuv-driven TLS transports by adding set_bio, own_cert, ALPN bindings, and WANT_* error constants across Haxe/OCaml/C layers. Also fix BIO/config lifetime management in native stubs, add eval TLS coverage under tests/misc/eval/projects/TlsBio. --- libs/mbedtls/dune | 3 +- libs/mbedtls/mbedtls.ml | 11 +- libs/mbedtls/mbedtls_stubs.c | 183 +++++++--- src/macro/eval/evalSsl.ml | 44 ++- std/eval/_std/mbedtls/Config.hx | 2 + std/eval/_std/mbedtls/Error.hx | 4 + std/eval/_std/mbedtls/Ssl.hx | 2 + tests/misc/eval/projects/TlsBio/Main.hx | 318 ++++++++++++++++++ tests/misc/eval/projects/TlsBio/compile.hxml | 2 + .../eval/projects/TlsBio/compile.hxml.stdout | 1 + .../misc/eval/projects/TlsBio/fixtures/ca.crt | 19 ++ .../eval/projects/TlsBio/fixtures/client.crt | 19 ++ .../eval/projects/TlsBio/fixtures/client.key | 28 ++ .../eval/projects/TlsBio/fixtures/server.crt | 19 ++ .../eval/projects/TlsBio/fixtures/server.key | 28 ++ 15 files changed, 633 insertions(+), 50 deletions(-) create mode 100644 tests/misc/eval/projects/TlsBio/Main.hx create mode 100644 tests/misc/eval/projects/TlsBio/compile.hxml create mode 100644 tests/misc/eval/projects/TlsBio/compile.hxml.stdout create mode 100644 tests/misc/eval/projects/TlsBio/fixtures/ca.crt create mode 100644 tests/misc/eval/projects/TlsBio/fixtures/client.crt create mode 100644 tests/misc/eval/projects/TlsBio/fixtures/client.key create mode 100644 tests/misc/eval/projects/TlsBio/fixtures/server.crt create mode 100644 tests/misc/eval/projects/TlsBio/fixtures/server.key diff --git a/libs/mbedtls/dune b/libs/mbedtls/dune index ca0780ddda2..dd704b9c727 100644 --- a/libs/mbedtls/dune +++ b/libs/mbedtls/dune @@ -4,6 +4,7 @@ (name mbedtls) (foreign_stubs (language c) - (names mbedtls_stubs)) + (names mbedtls_stubs) + (flags (:standard %{env:HAXE_MBEDTLS_CFLAGS=}))) (wrapped false) ) diff --git a/libs/mbedtls/mbedtls.ml b/libs/mbedtls/mbedtls.ml index 513cca45052..99227d4d89b 100644 --- a/libs/mbedtls/mbedtls.ml +++ b/libs/mbedtls/mbedtls.ml @@ -27,16 +27,22 @@ external mbedtls_ssl_config_authmode : mbedtls_ssl_config -> int -> unit = "ml_m external mbedtls_ssl_config_defaults : mbedtls_ssl_config -> int -> int -> int -> mbedtls_result = "ml_mbedtls_ssl_config_defaults" external mbedtls_ssl_config_init : unit -> mbedtls_ssl_config = "ml_mbedtls_ssl_config_init" external mbedtls_ssl_config_rng : mbedtls_ssl_config -> 'a -> unit = "ml_mbedtls_ssl_conf_rng" +external mbedtls_ssl_conf_own_cert : + mbedtls_ssl_config -> mbedtls_x509_crt -> mbedtls_pk_context -> mbedtls_result + = "ml_mbedtls_ssl_conf_own_cert" +external mbedtls_ssl_conf_alpn_protocols : mbedtls_ssl_config -> string array -> mbedtls_result + = "ml_mbedtls_ssl_conf_alpn_protocols" external mbedtls_ssl_init : unit -> mbedtls_ssl_context = "ml_mbedtls_ssl_init" external mbedtls_ssl_get_peer_cert : mbedtls_ssl_context -> mbedtls_x509_crt option = "ml_mbedtls_ssl_get_peer_cert" +external mbedtls_ssl_get_alpn_protocol : mbedtls_ssl_context -> string option = "ml_mbedtls_ssl_get_alpn_protocol" external mbedtls_ssl_handshake : mbedtls_ssl_context -> mbedtls_result = "ml_mbedtls_ssl_handshake" external mbedtls_ssl_read : mbedtls_ssl_context -> bytes -> int -> int -> mbedtls_result = "ml_mbedtls_ssl_read" external mbedtls_ssl_set_bio : mbedtls_ssl_context -> 'a -> - ('a -> bytes -> mbedtls_result) -> - ('a -> bytes -> mbedtls_result) -> + ('a -> bytes -> int -> int -> mbedtls_result) -> + ('a -> bytes -> int -> int -> mbedtls_result) -> unit = "ml_mbedtls_ssl_set_bio" external mbedtls_ssl_set_hostname : mbedtls_ssl_context -> string -> mbedtls_result = "ml_mbedtls_ssl_set_hostname" external mbedtls_ssl_setup : mbedtls_ssl_context -> mbedtls_ssl_config -> mbedtls_result = "ml_mbedtls_ssl_setup" @@ -67,3 +73,4 @@ external hx_get_ssl_authmode_flags : unit -> (string * int) array = "hx_get_ssl_ external hx_get_ssl_endpoint_flags : unit -> (string * int) array = "hx_get_ssl_endpoint_flags" external hx_get_ssl_preset_flags : unit -> (string * int) array = "hx_get_ssl_preset_flags" external hx_get_ssl_transport_flags : unit -> (string * int) array = "hx_get_ssl_transport_flags" +external hx_get_ssl_error_flags : unit -> (string * int) array = "hx_get_ssl_error_flags" diff --git a/libs/mbedtls/mbedtls_stubs.c b/libs/mbedtls/mbedtls_stubs.c index f66484ccd48..5fe5b17d77b 100644 --- a/libs/mbedtls/mbedtls_stubs.c +++ b/libs/mbedtls/mbedtls_stubs.c @@ -1,5 +1,6 @@ #include #include +#include #ifdef _WIN32 #include @@ -284,12 +285,32 @@ CAMLprim value hx_cert_get_notbefore(value chain) { // Config -#define Config_val(v) (*((mbedtls_ssl_config**) Data_custom_val(v))) +struct config_wrapper { + mbedtls_ssl_config *config; + char **alpn_protocols; +}; + +#define ConfigWrapper_ptr(v) (*((struct config_wrapper**) Data_custom_val(v))) +#define Config_val(v) (ConfigWrapper_ptr(v)->config) + +static void free_alpn_protocols(char **alpn) { + if (alpn != NULL) { + for (int i = 0; alpn[i] != NULL; ++i) { + free(alpn[i]); + } + free(alpn); + } +} static void ml_mbedtls_ssl_config_finalize(value v) { - mbedtls_ssl_config* ssl_config = Config_val(v); - if (ssl_config != NULL) { - mbedtls_ssl_config_free(ssl_config); + struct config_wrapper *wrap = ConfigWrapper_ptr(v); + if (wrap != NULL) { + free_alpn_protocols(wrap->alpn_protocols); + if (wrap->config != NULL) { + mbedtls_ssl_config_free(wrap->config); + free(wrap->config); + } + free(wrap); } } @@ -349,13 +370,14 @@ static int verify_callback(void* param, mbedtls_x509_crt *crt, int depth, uint32 CAMLprim value ml_mbedtls_ssl_config_init(void) { CAMLparam0(); CAMLlocal1(obj); - obj = caml_alloc_custom(&ssl_config_ops, sizeof(mbedtls_ssl_config*), 0, 1); - mbedtls_ssl_config* ssl_config = malloc(sizeof(mbedtls_ssl_config)); - mbedtls_ssl_config_init(ssl_config); + obj = caml_alloc_custom(&ssl_config_ops, sizeof(struct config_wrapper*), 0, 1); + struct config_wrapper *wrap = calloc(1, sizeof(struct config_wrapper)); + wrap->config = malloc(sizeof(mbedtls_ssl_config)); + mbedtls_ssl_config_init(wrap->config); #ifdef _WIN32 - mbedtls_ssl_conf_verify(ssl_config, verify_callback, NULL); + mbedtls_ssl_conf_verify(wrap->config, verify_callback, NULL); #endif - Config_val(obj) = ssl_config; + ConfigWrapper_ptr(obj) = wrap; CAMLreturn(obj); } @@ -420,11 +442,13 @@ CAMLprim value ml_mbedtls_pk_parse_key(value ctx, value key, value password, val pwd = Bytes_val(Field(password, 0)); pwdlen = caml_string_length(Field(password, 0)); } - #if MBEDTLS_VERSION_MAJOR >= 3 + #if MBEDTLS_VERSION_MAJOR >= 4 + CAMLreturn(Val_int(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen))); + #elif MBEDTLS_VERSION_MAJOR >= 3 mbedtls_ctr_drbg_context *ctr_drbg = CtrDrbg_val(rng); - CAMLreturn(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen, mbedtls_ctr_drbg_random, NULL)); + CAMLreturn(Val_int(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen, mbedtls_ctr_drbg_random, ctr_drbg))); #else - CAMLreturn(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen)); + CAMLreturn(Val_int(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen))); #endif } @@ -434,11 +458,13 @@ CAMLprim value ml_mbedtls_pk_parse_keyfile(value ctx, value path, value password if (password != Val_none) { pwd = String_val(Field(password, 0)); } - #if MBEDTLS_VERSION_MAJOR >= 3 + #if MBEDTLS_VERSION_MAJOR >= 4 + CAMLreturn(Val_int(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd))); + #elif MBEDTLS_VERSION_MAJOR >= 3 mbedtls_ctr_drbg_context *ctr_drbg = CtrDrbg_val(rng); - CAMLreturn(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd, mbedtls_ctr_drbg_random, ctr_drbg)); + CAMLreturn(Val_int(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd, mbedtls_ctr_drbg_random, ctr_drbg))); #else - CAMLreturn(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd)); + CAMLreturn(Val_int(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd))); #endif } @@ -452,14 +478,56 @@ CAMLprim value ml_mbedtls_pk_parse_public_keyfile(value ctx, value path) { CAMLreturn(mbedtls_pk_parse_public_keyfile(PkContext_val(ctx), String_val(path))); } +CAMLprim value ml_mbedtls_ssl_conf_own_cert(value conf, value cert, value pk) { + CAMLparam3(conf, cert, pk); + CAMLreturn(Val_int(mbedtls_ssl_conf_own_cert(Config_val(conf), X509Crt_val(cert), PkContext_val(pk)))); +} + +CAMLprim value ml_mbedtls_ssl_conf_alpn_protocols(value conf, value protocols) { + CAMLparam2(conf, protocols); +#if defined(MBEDTLS_SSL_ALPN) + struct config_wrapper *wrap = ConfigWrapper_ptr(conf); + int len = Wosize_val(protocols); + char **list = malloc((len + 1) * sizeof(char *)); + for (int i = 0; i < len; ++i) { + list[i] = strdup(String_val(Field(protocols, i))); + } + list[len] = NULL; + free_alpn_protocols(wrap->alpn_protocols); + wrap->alpn_protocols = list; + CAMLreturn(Val_int(mbedtls_ssl_conf_alpn_protocols(Config_val(conf), (const char **)list))); +#else + CAMLreturn(Val_int(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE)); +#endif +} + // Ssl -#define SslContext_val(v) (*((mbedtls_ssl_context**) Data_custom_val(v))) +struct ssl_wrapper { + mbedtls_ssl_context *ctx; + value *bio_root; +}; + +#define SslWrapper_ptr(v) (*((struct ssl_wrapper**) Data_custom_val(v))) +#define SslContext_val(v) (SslWrapper_ptr(v)->ctx) + +static void free_bio_root(struct ssl_wrapper *wrap) { + if (wrap != NULL && wrap->bio_root != NULL) { + caml_remove_generational_global_root(wrap->bio_root); + free(wrap->bio_root); + wrap->bio_root = NULL; + } +} static void ml_mbedtls_ssl_context_finalize(value v) { - mbedtls_ssl_context* ssl_context = SslContext_val(v); - if (ssl_context != NULL) { - mbedtls_ssl_free(ssl_context); + struct ssl_wrapper *wrap = SslWrapper_ptr(v); + if (wrap != NULL) { + free_bio_root(wrap); + if (wrap->ctx != NULL) { + mbedtls_ssl_free(wrap->ctx); + free(wrap->ctx); + } + free(wrap); } } @@ -475,10 +543,11 @@ static struct custom_operations ssl_context_ops = { CAMLprim value ml_mbedtls_ssl_init(void) { CAMLparam0(); CAMLlocal1(obj); - obj = caml_alloc_custom(&ssl_context_ops, sizeof(mbedtls_ssl_context*), 0, 1); - mbedtls_ssl_context* ssl_context = malloc(sizeof(mbedtls_ssl_context)); - mbedtls_ssl_init(ssl_context); - SslContext_val(obj) = ssl_context; + obj = caml_alloc_custom(&ssl_context_ops, sizeof(struct ssl_wrapper*), 0, 1); + struct ssl_wrapper *wrap = calloc(1, sizeof(struct ssl_wrapper)); + wrap->ctx = malloc(sizeof(mbedtls_ssl_context)); + mbedtls_ssl_init(wrap->ctx); + SslWrapper_ptr(obj) = wrap; CAMLreturn(obj); } @@ -507,38 +576,69 @@ CAMLprim value ml_mbedtls_ssl_read(value ssl, value buf, value pos, value len) { static int bio_write_cb(void* ctx, const unsigned char* buf, size_t len) { CAMLparam0(); - CAMLlocal3(r, s, vctx); - vctx = *(value*)ctx; - s = caml_alloc_initialized_string(len, (const char*)buf); - r = caml_callback2(Field(vctx, 1), Field(vctx, 0), s); + CAMLlocal2(r, b); + value vctx = *(value*)ctx; + value args[4]; + b = caml_alloc_initialized_string(len, (const char*)buf); + args[0] = Field(vctx, 0); + args[1] = b; + args[2] = Val_int(0); + args[3] = Val_int(len); + r = caml_callbackN(Field(vctx, 1), 4, args); CAMLreturn(Int_val(r)); } static int bio_read_cb(void* ctx, unsigned char* buf, size_t len) { CAMLparam0(); - CAMLlocal3(r, s, vctx); - vctx = *(value*)ctx; - s = caml_alloc_string(len); - r = caml_callback2(Field(vctx, 2), Field(vctx, 0), s); - memcpy(buf, String_val(s), len); - CAMLreturn(Int_val(r)); + CAMLlocal2(r, b); + value vctx = *(value*)ctx; + value args[4]; + int n; + b = caml_alloc_string(len); + args[0] = Field(vctx, 0); + args[1] = b; + args[2] = Val_int(0); + args[3] = Val_int(len); + r = caml_callbackN(Field(vctx, 2), 4, args); + n = Int_val(r); + if (n > 0) { + if ((size_t)n > len) { + n = (int)len; + } + memcpy(buf, Bytes_val(b), n); + } + CAMLreturn(n); } CAMLprim value ml_mbedtls_ssl_set_bio(value ssl, value p_bio, value f_send, value f_recv) { CAMLparam4(ssl, p_bio, f_send, f_recv); CAMLlocal1(ctx); + struct ssl_wrapper *wrap = SslWrapper_ptr(ssl); + free_bio_root(wrap); ctx = caml_alloc(3, 0); Store_field(ctx, 0, p_bio); Store_field(ctx, 1, f_send); Store_field(ctx, 2, f_recv); - // TODO: this allocation is leaked - value *location = malloc(sizeof(value)); - *location = ctx; - caml_register_generational_global_root(location); - mbedtls_ssl_set_bio(SslContext_val(ssl), (void*)location, bio_write_cb, bio_read_cb, NULL); + wrap->bio_root = malloc(sizeof(value)); + *wrap->bio_root = ctx; + caml_register_generational_global_root(wrap->bio_root); + mbedtls_ssl_set_bio(wrap->ctx, (void*)wrap->bio_root, bio_write_cb, bio_read_cb, NULL); CAMLreturn(Val_unit); } +CAMLprim value ml_mbedtls_ssl_get_alpn_protocol(value ssl) { + CAMLparam1(ssl); +#if defined(MBEDTLS_SSL_ALPN) + const char *proto = mbedtls_ssl_get_alpn_protocol(SslContext_val(ssl)); + if (proto == NULL) { + CAMLreturn(Val_none); + } + CAMLreturn(Val_some(caml_copy_string(proto))); +#else + CAMLreturn(Val_none); +#endif +} + CAMLprim value ml_mbedtls_ssl_set_hostname(value ssl, value hostname) { CAMLparam2(ssl, hostname); CAMLreturn(Val_int(mbedtls_ssl_set_hostname(SslContext_val(ssl), String_val(hostname)))); @@ -641,4 +741,11 @@ CAMLprim value hx_get_ssl_transport_flags(value unit) { const char* names[] = {"SSL_TRANSPORT_STREAM", "SSL_TRANSPORT_DATAGRAM"}; int values[] = {MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_TRANSPORT_DATAGRAM}; CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values)); +} + +CAMLprim value hx_get_ssl_error_flags(value unit) { + CAMLparam1(unit); + const char* names[] = {"WANT_READ", "WANT_WRITE", "PEER_CLOSE_NOTIFY"}; + int values[] = {MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE, MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY}; + CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values)); } \ No newline at end of file diff --git a/src/macro/eval/evalSsl.ml b/src/macro/eval/evalSsl.ml index 4da4b0355d0..4ed2765127e 100644 --- a/src/macro/eval/evalSsl.ml +++ b/src/macro/eval/evalSsl.ml @@ -3,6 +3,7 @@ open EvalValue open EvalEncode open EvalDecode open EvalExceptions +open EvalMisc open Mbedtls let as_x509_crt vthis = match vthis with @@ -66,12 +67,21 @@ let init_constructors add = ) let init_fields init_fields builtins = - let socket_send socket bytes = - Unix.send socket bytes 0 (Bytes.length bytes) [] + let socket_send socket buf pos len = + Unix.send socket buf pos len [] in - let socket_receive socket bytes = - Unix.recv socket bytes 0 (Bytes.length bytes) [] + let socket_receive socket buf pos len = + Unix.recv socket buf pos len [] in + let bio_bridge fn buf pos len = + decode_int (call_value fn [encode_bytes buf; vint pos; vint len]) + in + let make_bio_send send = fun () buf pos len -> bio_bridge send buf pos len in + let make_bio_recv recv = fun () buf pos len -> bio_bridge recv buf pos len in + let decode_string_array v = + Array.of_list (List.map decode_string (decode_array v)) + in + let statics a = List.map (fun (s,i) -> s,vint i) (Array.to_list a) in let native_cert this = as_x509_crt (EvalField.field this (hash "native")) in @@ -146,7 +156,13 @@ let init_fields init_fields builtins = "rng",vifun1(fun this p_rng -> mbedtls_ssl_config_rng (as_config this) (as_ctr_drbg p_rng); vnull - ) + ); + "own_cert",vifun2 (fun this cert pk -> + vint (mbedtls_ssl_conf_own_cert (as_config this) (as_x509_crt cert) (as_pk_context pk)) + ); + "alpn_protocols",vifun1 (fun this protocols -> + vint (mbedtls_ssl_conf_alpn_protocols (as_config this) (decode_string_array protocols)) + ); ]; init_fields builtins (["mbedtls"],"CtrDrbg") [] [ "random",vifun2 (fun this output output_len -> @@ -156,9 +172,11 @@ let init_fields init_fields builtins = vint (mbedtls_ctr_drbg_seed (as_ctr_drbg this) (as_entropy entropy) (match custom with VString s -> Some s.sstring | _ -> None)) ) ]; - init_fields builtins (["mbedtls"],"Error") [ - "strerror",vfun1 (fun code -> encode_string (mbedtls_strerror (decode_int code))); - ] []; + init_fields builtins (["mbedtls"],"Error") ( + (statics (hx_get_ssl_error_flags())) @ [ + "strerror",vfun1 (fun code -> encode_string (mbedtls_strerror (decode_int code))); + ] + ) []; init_fields builtins (["mbedtls"],"PkContext") [] [ "parse_key",vifun3 (fun this key password rng -> vint (mbedtls_pk_parse_key (as_pk_context this) (decode_bytes key) (match password with VNull -> None | _ -> Some (decode_string password)) (as_ctr_drbg rng)); @@ -174,6 +192,11 @@ let init_fields init_fields builtins = ); ]; init_fields builtins (["mbedtls"],"Ssl") [] [ + "get_alpn_protocol",vifun0 (fun this -> + match mbedtls_ssl_get_alpn_protocol (as_ssl this) with + | None -> vnull + | Some proto -> encode_string proto + ); "get_peer_cert",vifun0 (fun this -> match mbedtls_ssl_get_peer_cert (as_ssl this) with | None -> vnull @@ -188,6 +211,10 @@ let init_fields init_fields builtins = "set_hostname",vifun1 (fun this hostname -> vint (mbedtls_ssl_set_hostname (as_ssl this) (decode_string hostname)); ); + "set_bio",vifun2 (fun this send recv -> + mbedtls_ssl_set_bio (as_ssl this) () (make_bio_send send) (make_bio_recv recv); + vnull + ); "setup",vifun1 (fun this conf -> vint (mbedtls_ssl_setup (as_ssl this) (as_config conf)) ); @@ -195,7 +222,6 @@ let init_fields init_fields builtins = vint (mbedtls_ssl_write (as_ssl this) (decode_bytes buf) (decode_int pos) (decode_int len);) ); ]; - let statics a = List.map (fun (s,i) -> s,vint i) (Array.to_list a) in init_fields builtins (["mbedtls"],"SslAuthmode") (statics (hx_get_ssl_authmode_flags())) []; init_fields builtins (["mbedtls"],"SslEndpoint") (statics (hx_get_ssl_endpoint_flags())) []; init_fields builtins (["mbedtls"],"SslPreset") (statics (hx_get_ssl_preset_flags())) []; diff --git a/std/eval/_std/mbedtls/Config.hx b/std/eval/_std/mbedtls/Config.hx index 132a7f0118f..2b7e146085e 100644 --- a/std/eval/_std/mbedtls/Config.hx +++ b/std/eval/_std/mbedtls/Config.hx @@ -3,8 +3,10 @@ package mbedtls; extern class Config { function new():Void; + function alpn_protocols(protocols:Array):Int; function authmode(authmode:SslAuthmode):Void; function ca_chain(ca_chain:X509Crt):Void; function defaults(endpoint:SslEndpoint, transport:SslTransport, preset:SslPreset):Int; + function own_cert(cert:X509Crt, pk:PkContext):Int; function rng(p_rng:T):Void; } diff --git a/std/eval/_std/mbedtls/Error.hx b/std/eval/_std/mbedtls/Error.hx index 343fb0365f1..608076251a6 100644 --- a/std/eval/_std/mbedtls/Error.hx +++ b/std/eval/_std/mbedtls/Error.hx @@ -1,5 +1,9 @@ package mbedtls; class Error { + extern static public var WANT_READ:Int; + extern static public var WANT_WRITE:Int; + extern static public var PEER_CLOSE_NOTIFY:Int; + extern static public function strerror(code:Int):String; } diff --git a/std/eval/_std/mbedtls/Ssl.hx b/std/eval/_std/mbedtls/Ssl.hx index 42fc6843aa6..ead35fad186 100644 --- a/std/eval/_std/mbedtls/Ssl.hx +++ b/std/eval/_std/mbedtls/Ssl.hx @@ -6,9 +6,11 @@ import haxe.io.Bytes; extern class Ssl { function new():Void; + function get_alpn_protocol():Null; function get_peer_cert():Null; function handshake():Int; function read(buf:Bytes, pos:Int, len:Int):Int; + function set_bio(send:(buf:Bytes, pos:Int, len:Int) -> Int, recv:(buf:Bytes, pos:Int, len:Int) -> Int):Void; function set_hostname(hostname:String):Int; function setup(conf:Config):Int; function write(buf:Bytes, pos:Int, len:Int):Int; diff --git a/tests/misc/eval/projects/TlsBio/Main.hx b/tests/misc/eval/projects/TlsBio/Main.hx new file mode 100644 index 00000000000..1b7e71ebc3b --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/Main.hx @@ -0,0 +1,318 @@ +import haxe.io.Bytes; +import mbedtls.Config; +import mbedtls.CtrDrbg; +import mbedtls.Entropy; +import mbedtls.Error; +import mbedtls.PkContext; +import mbedtls.Ssl; +import mbedtls.SslAuthmode; +import mbedtls.SslEndpoint; +import mbedtls.SslPreset; +import mbedtls.SslTransport; +import mbedtls.X509Crt; + +class BioBridge { + public var outgoing = new haxe.io.BytesBuffer(); + var incoming = Bytes.alloc(0); + var incomingPos = 0; + + public function new() {} + + public function send(buf:Bytes, pos:Int, len:Int):Int { + outgoing.addBytes(buf, pos, len); + return len; + } + + public function recv(buf:Bytes, pos:Int, len:Int):Int { + final available = incoming.length - incomingPos; + if (available <= 0) + return Error.WANT_READ; + final n = available > len ? len : available; + buf.blit(pos, incoming, incomingPos, n); + incomingPos += n; + if (incomingPos >= incoming.length) { + incoming = Bytes.alloc(0); + incomingPos = 0; + } + return n; + } + + function addIncoming(data:Bytes) { + if (incomingPos > 0 && incomingPos < incoming.length) { + incoming = incoming.sub(incomingPos, incoming.length - incomingPos); + incomingPos = 0; + } + if (incoming.length == 0) { + incoming = data; + incomingPos = 0; + } else { + final merged = Bytes.alloc(incoming.length + data.length); + merged.blit(0, incoming, 0, incoming.length); + merged.blit(incoming.length, data, 0, data.length); + incoming = merged; + incomingPos = 0; + } + } + + public static function pump(a:BioBridge, b:BioBridge) { + if (a.outgoing.length > 0) { + b.addIncoming(a.outgoing.getBytes()); + a.outgoing = new haxe.io.BytesBuffer(); + } + if (b.outgoing.length > 0) { + a.addIncoming(b.outgoing.getBytes()); + b.outgoing = new haxe.io.BytesBuffer(); + } + } +} + +typedef Rng = { + final drbg:CtrDrbg; +} + +class Main { + static function main() { + testBioHandshake(); + testOwnCert(); + testAlpn(); + testMtls(); + trace("ok"); + } + + static function fixture(name:String):Bytes { + return Bytes.ofString(sys.io.File.getContent('fixtures/$name')); + } + + static function makeRng():Rng { + final entropy = new Entropy(); + final drbg = new CtrDrbg(); + final r = drbg.seed(entropy, "tls-bio-test"); + if (r != 0) + throw Error.strerror(r); + return {drbg: drbg}; + } + + static function loadCa():X509Crt { + final ca = new X509Crt(); + final r = ca.parse(fixture("ca.crt")); + if (r != 0) + throw Error.strerror(r); + return ca; + } + + static function loadCert(name:String):X509Crt { + final cert = new X509Crt(); + final r = cert.parse(fixture('$name.crt')); + if (r != 0) + throw Error.strerror(r); + return cert; + } + + static function loadKey(name:String, drbg:CtrDrbg):PkContext { + final key = new PkContext(); + final r = key.parse_key(fixture('$name.key'), null, drbg); + if (r != 0) + throw Error.strerror(r); + return key; + } + + static function runHandshake(client:Ssl, server:Ssl, clientBio:BioBridge, serverBio:BioBridge) { + var clientDone = false; + var serverDone = false; + var steps = 0; + while (!clientDone || !serverDone) { + if (++steps > 1000) + throw "handshake loop exceeded"; + BioBridge.pump(clientBio, serverBio); + if (!clientDone) { + final r = client.handshake(); + if (r == 0) + clientDone = true; + else if (r != Error.WANT_READ && r != Error.WANT_WRITE) + throw 'client handshake: ${Error.strerror(r)}'; + } + if (!serverDone) { + final r = server.handshake(); + if (r == 0) + serverDone = true; + else if (r != Error.WANT_READ && r != Error.WANT_WRITE) + throw 'server handshake: ${Error.strerror(r)}'; + } + } + } + + static function exchangeAppData(client:Ssl, server:Ssl, clientBio:BioBridge, serverBio:BioBridge) { + final msg = Bytes.ofString("hello tls"); + final out = Bytes.alloc(msg.length); + var written = 0; + var steps = 0; + while (written < msg.length) { + if (++steps > 1000) + throw "client write loop exceeded"; + BioBridge.pump(clientBio, serverBio); + final r = client.write(msg, written, msg.length - written); + if (r > 0) + written += r; + else if (r != Error.WANT_READ && r != Error.WANT_WRITE) + throw 'client write: ${Error.strerror(r)}'; + } + + final inBuf = Bytes.alloc(msg.length); + var read = 0; + steps = 0; + while (read < msg.length) { + if (++steps > 1000) + throw "server read loop exceeded"; + BioBridge.pump(clientBio, serverBio); + final r = server.read(inBuf, read, msg.length - read); + if (r > 0) + read += r; + else if (r != Error.WANT_READ && r != Error.WANT_WRITE) + throw 'server read: ${Error.strerror(r)}'; + } + if (inBuf.toString() != msg.toString()) + throw "app data mismatch"; + } + + static function makeServerConfig(?ownCert:X509Crt, ?ownKey:PkContext, ?ca:X509Crt, ?authmode:SslAuthmode, + ?alpn:Array):Config { + final rng = makeRng(); + final conf = new Config(); + conf.defaults(SslEndpoint.SSL_IS_SERVER, SslTransport.SSL_TRANSPORT_STREAM, SslPreset.SSL_PRESET_DEFAULT); + conf.rng(rng.drbg); + if (ownCert != null && ownKey != null) + conf.own_cert(ownCert, ownKey); + if (ca != null) + conf.ca_chain(ca); + if (authmode != null) + conf.authmode(authmode); + if (alpn != null) + conf.alpn_protocols(alpn); + return conf; + } + + static function makeClientConfig(?ca:X509Crt, ?ownCert:X509Crt, ?ownKey:PkContext, ?authmode:SslAuthmode, + ?alpn:Array):Config { + final rng = makeRng(); + final conf = new Config(); + conf.defaults(SslEndpoint.SSL_IS_CLIENT, SslTransport.SSL_TRANSPORT_STREAM, SslPreset.SSL_PRESET_DEFAULT); + conf.rng(rng.drbg); + if (ca != null) + conf.ca_chain(ca); + if (ownCert != null && ownKey != null) + conf.own_cert(ownCert, ownKey); + if (authmode != null) + conf.authmode(authmode); + if (alpn != null) + conf.alpn_protocols(alpn); + return conf; + } + + static function testBioHandshake() { + final rng = makeRng(); + final serverCert = loadCert("server"); + final serverKey = loadKey("server", rng.drbg); + final ca = loadCa(); + + final serverConf = makeServerConfig(serverCert, serverKey); + final clientConf = makeClientConfig(ca, null, null, SslAuthmode.SSL_VERIFY_REQUIRED); + + final clientBio = new BioBridge(); + final serverBio = new BioBridge(); + + final client = new Ssl(); + if (client.setup(clientConf) != 0) + throw "client setup failed"; + client.set_hostname("localhost"); + client.set_bio(clientBio.send, clientBio.recv); + + final server = new Ssl(); + if (server.setup(serverConf) != 0) + throw "server setup failed"; + server.set_bio(serverBio.send, serverBio.recv); + + runHandshake(client, server, clientBio, serverBio); + exchangeAppData(client, server, clientBio, serverBio); + } + + static function testOwnCert() { + final rng = makeRng(); + final serverCert = loadCert("server"); + final serverKey = loadKey("server", rng.drbg); + final ca = loadCa(); + + final serverConf = makeServerConfig(serverCert, serverKey); + final clientConf = makeClientConfig(ca, null, null, SslAuthmode.SSL_VERIFY_REQUIRED); + + final clientBio = new BioBridge(); + final serverBio = new BioBridge(); + + final client = new Ssl(); + client.setup(clientConf); + client.set_hostname("localhost"); + client.set_bio(clientBio.send, clientBio.recv); + + final server = new Ssl(); + server.setup(serverConf); + server.set_bio(serverBio.send, serverBio.recv); + + runHandshake(client, server, clientBio, serverBio); + } + + static function testAlpn() { + final rng = makeRng(); + final serverCert = loadCert("server"); + final serverKey = loadKey("server", rng.drbg); + final ca = loadCa(); + final alpn = ["h2", "http/1.1"]; + + final serverConf = makeServerConfig(serverCert, serverKey, ca, SslAuthmode.SSL_VERIFY_NONE, alpn); + final clientConf = makeClientConfig(ca, null, null, SslAuthmode.SSL_VERIFY_REQUIRED, alpn); + + final clientBio = new BioBridge(); + final serverBio = new BioBridge(); + + final client = new Ssl(); + client.setup(clientConf); + client.set_hostname("localhost"); + client.set_bio(clientBio.send, clientBio.recv); + + final server = new Ssl(); + server.setup(serverConf); + server.set_bio(serverBio.send, serverBio.recv); + + runHandshake(client, server, clientBio, serverBio); + if (client.get_alpn_protocol() != "h2") + throw 'client alpn: ${client.get_alpn_protocol()}'; + if (server.get_alpn_protocol() != "h2") + throw 'server alpn: ${server.get_alpn_protocol()}'; + } + + static function testMtls() { + final rng = makeRng(); + final serverCert = loadCert("server"); + final serverKey = loadKey("server", rng.drbg); + final clientCert = loadCert("client"); + final clientKey = loadKey("client", rng.drbg); + final ca = loadCa(); + + final serverConf = makeServerConfig(serverCert, serverKey, ca, SslAuthmode.SSL_VERIFY_REQUIRED); + final clientConf = makeClientConfig(ca, clientCert, clientKey, SslAuthmode.SSL_VERIFY_REQUIRED); + + final clientBio = new BioBridge(); + final serverBio = new BioBridge(); + + final client = new Ssl(); + client.setup(clientConf); + client.set_hostname("localhost"); + client.set_bio(clientBio.send, clientBio.recv); + + final server = new Ssl(); + server.setup(serverConf); + server.set_bio(serverBio.send, serverBio.recv); + + runHandshake(client, server, clientBio, serverBio); + if (server.get_peer_cert() == null) + throw "missing peer cert"; + } +} diff --git a/tests/misc/eval/projects/TlsBio/compile.hxml b/tests/misc/eval/projects/TlsBio/compile.hxml new file mode 100644 index 00000000000..d9ece4a40bb --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/compile.hxml @@ -0,0 +1,2 @@ +-m Main +--interp diff --git a/tests/misc/eval/projects/TlsBio/compile.hxml.stdout b/tests/misc/eval/projects/TlsBio/compile.hxml.stdout new file mode 100644 index 00000000000..97caa79727a --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/compile.hxml.stdout @@ -0,0 +1 @@ +Main.hx:79: ok diff --git a/tests/misc/eval/projects/TlsBio/fixtures/ca.crt b/tests/misc/eval/projects/TlsBio/fixtures/ca.crt new file mode 100644 index 00000000000..0c3d9a9b8ff --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/fixtures/ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfugAwIBAgIUUwtpjXtPMECPnjkRfQvSYO3ldLswDQYJKoZIhvcNAQEL +BQAwGTEXMBUGA1UEAwwOVGxzQmlvIFRlc3QgQ0EwHhcNMjYwNzA5MDUyODQxWhcN +MzYwNzA2MDUyODQxWjAZMRcwFQYDVQQDDA5UbHNCaW8gVGVzdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMdwuVY2TBEaEEdw71j1umfvlN/KcUri +5vhzrdQV4kVZnvCvKjNc7FPq2UWs/qg6at2AdrbisKe/Rn2WGWsB/n8CxvfBMAI0 +kFDNhsEh0PHb/YAf/rNKVretO58XzB38nH/6pPNGO+SVN5/H/Gya5Y3fWnEp9/nU +6Ul2nyO4R4O2YOTbZoWa7Px4krk5sEm0pQsmpA6EyFjA4CJd/qHAKZF9/Z0FFdfI +SobUQ1tcCYD8ey2VPs3bwkINkhPitQl5MLrX//53geem/4tXD6FfvipiqBaADJHM +EzswqfZW0YuCWLj9PtDZ9V3uZzYy+ZotvXyPR0NMwhH9W5YbA/pOxJ8CAwEAAaNT +MFEwHQYDVR0OBBYEFOUOAygjuD/76VHuMy5gHIrvjSFnMB8GA1UdIwQYMBaAFOUO +AygjuD/76VHuMy5gHIrvjSFnMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAB1Nt22n/prSpsYhk+Olt2VkNeO8mRErHVU5V7SsBGQsEspGS76CjSnA +Y5qczZ7wEAlhWFwBQX/+wnW3hYQG9gPWCgRHGPKdYf+pqFFHQbe008kaKkyE3CSU +IAPdUtnaF9ISdx5IIAJDtUSK/DQUgdHvagEb8R80rZGB9/44Heo5A1BXoFjhwhRG +M8fIL3twSYxyvXmqwMcwL9Y8Kh5KO60olS0R1YVv4vnjAZKWIIAInaiqolwFMwFs +oY0YRldmNPr3gwITRLMkoHoeb8u4/61MMW6XJE8EwUH5+m/RRbc1Q7qT+InvaGap +yyw73eZBWsLEfRMZJBeB62a/d+LBkSI= +-----END CERTIFICATE----- diff --git a/tests/misc/eval/projects/TlsBio/fixtures/client.crt b/tests/misc/eval/projects/TlsBio/fixtures/client.crt new file mode 100644 index 00000000000..de413d6e6f2 --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/fixtures/client.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDATCCAemgAwIBAgIUFvMx5nb5MElz1RSSSNN7z/Tw28owDQYJKoZIhvcNAQEL +BQAwGTEXMBUGA1UEAwwOVGxzQmlvIFRlc3QgQ0EwHhcNMjYwNzA5MDUyODQxWhcN +MzYwNzA2MDUyODQxWjAYMRYwFAYDVQQDDA1UbHNCaW8gQ2xpZW50MIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkAYBwdmqoLTRO9PPB/3G1eozkbD/BI5n +DxR2oDxDtDFBU82xKuGKNP94wvMQE9cxXofZ9DOTV1ooewr4EdA2d1IoB+bxiWUH +el/FPHP77dPnifKCfaDgzzo7UFLJ5iiUCpqitMfXp5UPzwwEg1+1KWXHZrSa6T1/ +WVpMlhMdiIUjA+XcIBrCGRl3MtSIL8YQiygUUgbTisBd5WR4elS3OVJrYKKyQ/Tm +EBO5HilxjSj/GffYUxjm4msMG7IJ4Pn/5V/YLuN0JtEZ+YDHoWsBy6xvPlli0R4/ +5ndAHzBfrbDCzavNrgoaT/DwLAPl3E2bL5Nx8dO0kwGBfb4LKceprQIDAQABo0Iw +QDAdBgNVHQ4EFgQUl1cfk0wL6CupJLlUDPJmSSJiz0MwHwYDVR0jBBgwFoAU5Q4D +KCO4P/vpUe4zLmAciu+NIWcwDQYJKoZIhvcNAQELBQADggEBADG6K5v/xOGKwFgw +HiTi8T042nrdiO7FoY4qXpuiiShh2tp/iPpkzUQ5B0k6nlnYmxdmGdJUTKGNxdFI +czVErjrCehr/AgLgYB6OKPHAToJywvDIqN3VPuAgCT5uNaijUf24yaXXtE5Dau2M +w+p120v8vI0mAFzf6BtZjQx249AIEiXPKUAAywWn+vqyZCl09rtuEWSkfbsFjNL6 +sK6EdBnj9nZcj9RsNH1YV7VV/WVkAMgLcSLcZCCnCAGuvRJH/0wkytrbgzC9NUe0 +dl2uBXi69mFH0KM3UYSstwhNj6z7NgQaYvA3IXofgAPm9WbK7O2F1aKPc5dD2Som +nNF8IM8= +-----END CERTIFICATE----- diff --git a/tests/misc/eval/projects/TlsBio/fixtures/client.key b/tests/misc/eval/projects/TlsBio/fixtures/client.key new file mode 100644 index 00000000000..e29936cfc3f --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/fixtures/client.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCQBgHB2aqgtNE7 +088H/cbV6jORsP8EjmcPFHagPEO0MUFTzbEq4Yo0/3jC8xAT1zFeh9n0M5NXWih7 +CvgR0DZ3UigH5vGJZQd6X8U8c/vt0+eJ8oJ9oODPOjtQUsnmKJQKmqK0x9enlQ/P +DASDX7UpZcdmtJrpPX9ZWkyWEx2IhSMD5dwgGsIZGXcy1IgvxhCLKBRSBtOKwF3l +ZHh6VLc5UmtgorJD9OYQE7keKXGNKP8Z99hTGObiawwbsgng+f/lX9gu43Qm0Rn5 +gMehawHLrG8+WWLRHj/md0AfMF+tsMLNq82uChpP8PAsA+XcTZsvk3Hx07STAYF9 +vgspx6mtAgMBAAECggEAGkTWNjbO3eANF8XyyYjapvLANC8d3IViu8fmOSS0zp17 +Rl9KlMEtdawxKRGvWYcTDKRntxhfI/wgTQz7oTgibxIPlh1j6cUBH6tvLK8VANR5 +M1qFvYdF6dY7slNfWvkEw4hf6+xVY84W45NUEWg4AVR8kbmYVblvTGthc7AJ33fu +/bELkZjW5nsIZnUTNY/lnrorxuvO5i296W8jHjB3pEE/9RFrb+dUFEgUoYurq32v +9TXoHgX6VsRKt/Zln0FC7Hy/EwwbZdqOmRy5W1m3XwJcRyXA4ONzW/CLR/9kOOyx +p7SGTcC7CUM9Ru3Z4WrOqFdE6Yqlv8J8VXiVtdxHGwKBgQDKdOkd6J2x8XZzDioG +2183WlgTrzYh69XHiUWFjoYKiyaQ56Fc6cpHY4R65wZ33TeK9yhdxcKDAMnV6rFF +fcW5hmumr33yUV9nPcBmppaRiSlUBQa7t52PeQTYGPnkK8J0EWRy/JAVhkXAv20c +MNZA0epdNqPYxy9rtkhhibOPdwKBgQC2HPHQrLD58HLHSflK0nzyNoZBWqlrjru5 ++2zWxejI3sRrMobXt5bpbOVnG22bSpfvPTr7TD2SVAA0P29kLqEvCxAASZANRroL +JaX2Y6EI22M41PGi4KgfPOisWiaATEumHcBS/PfrR/RwXZWJ+4xs0BbmAT0LeIyI +l8yhYZYA+wKBgFH2arn1BoKXosCJp3IHNdEO/kFZ2ax58Z5KcJ7VSGbUVtSrMaSP +8ZhdLbEj/nZgVLApx2nPOiQXGZ9E2Gett3KYfNSKj46eauU9Frt4DdT1lomxTzyH +5X3EHLXvxpsdLCgZMnVq0lokdfDGjsGu885iLWN3T3Xfjc8piLwUJ2GZAoGAKPID +EIbzV47PT617Jm6C9zZ5IxKOSweRf7Re+T8QIrGreeqnVLMLdDouresFzseLt5eN +vlia8159mUG1+tFdHiWfmGDxyXpgdAcn9GjcGRCyk2GVXqiiRDu+mJnAVFJTI+tG +haIo37aS5/yylY6AOSrkKxyWLBETj9aJhLNbNacCgYBWuPjd+gKYjZHZql7tRr/t +XNHeTkLZ4yL9Qrn3qbAqUeZSSt7gli/J9E6AEdpEK3tWVT7yqmYMaa2BUEYnfOKD +GXj7z3DUp/M9qCaUvVCsuxD6F3Q1M+CBsa196OYE8EYih9GSzM1TehAPpaMx+QXB +1qBngQCGuQVuJ9le63xMeQ== +-----END PRIVATE KEY----- diff --git a/tests/misc/eval/projects/TlsBio/fixtures/server.crt b/tests/misc/eval/projects/TlsBio/fixtures/server.crt new file mode 100644 index 00000000000..463cc7f82ca --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/fixtures/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/TCCAeWgAwIBAgIUFvMx5nb5MElz1RSSSNN7z/Tw28kwDQYJKoZIhvcNAQEL +BQAwGTEXMBUGA1UEAwwOVGxzQmlvIFRlc3QgQ0EwHhcNMjYwNzA5MDUyODQxWhcN +MzYwNzA2MDUyODQxWjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCKHHd+PrUpZYSwDg/qeMhOt9WrhGFwnWX7+xBR +paxsbal+KEceoy18Il1Vo33vbPoqjLZXWjd/FSH5RfjJOUj0szqjAK8+asQxGXvq +Ir0FUUHWiaaQxcVOJMu06TBxHmG+wzQbnEEiQDyulJLhEelBV/vCQu7rm9HoC/GA +suSvedyKfz6vZVNZ7gz/lDVQvTWTVHJlRN2RFFjDfVQmB1IveB3J4IeGv7qZFD0T +Bxw0ipvNKfYMBzd7lpJPBXgHzQt87q4O4C8g68MqoVeJ0XgFKaVZIkg4HOHh0CRp +wiQPe1m2dEM7iXPeyRnn8z94tZK99nvhL46wgVBjZ9fxlGFNAgMBAAGjQjBAMB0G +A1UdDgQWBBSYwLLomouRL7/BZm+Kinqh5tA5njAfBgNVHSMEGDAWgBTlDgMoI7g/ +++lR7jMuYByK740hZzANBgkqhkiG9w0BAQsFAAOCAQEAHVX0+D85uxEppLt4b+0Z +qAx1OQQpreniQEZYND3qiYu0go2eXI/r95N6AP1n781gYj4hqVtFPF2q5Jw7SEHj +nhTXa+h+OAEbC0WSm9HPmnG4oJBKc7U7bKg7ykHI7uZCsf9JvtZPQIhEF7qD+LzH +nZAz67Z5f40CVMFOFBSyqVgbLracBJEp4pF90vQyUkpIDsGuctJkWkeo5UrqiDG3 +UZS8jXGV1L2/x6PmFBdHZSiE5potWyJGLNxDLMoqxz/KqffbFAvHVIJmnjINa3PB +KczGQahF7MDxIqIFI8+TgQwK6ck7zgcLGzVWSYWc4dSGqiqQmmLM0U/uO6GLAGm/ +Fw== +-----END CERTIFICATE----- diff --git a/tests/misc/eval/projects/TlsBio/fixtures/server.key b/tests/misc/eval/projects/TlsBio/fixtures/server.key new file mode 100644 index 00000000000..3e29615edca --- /dev/null +++ b/tests/misc/eval/projects/TlsBio/fixtures/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCKHHd+PrUpZYSw +Dg/qeMhOt9WrhGFwnWX7+xBRpaxsbal+KEceoy18Il1Vo33vbPoqjLZXWjd/FSH5 +RfjJOUj0szqjAK8+asQxGXvqIr0FUUHWiaaQxcVOJMu06TBxHmG+wzQbnEEiQDyu +lJLhEelBV/vCQu7rm9HoC/GAsuSvedyKfz6vZVNZ7gz/lDVQvTWTVHJlRN2RFFjD +fVQmB1IveB3J4IeGv7qZFD0TBxw0ipvNKfYMBzd7lpJPBXgHzQt87q4O4C8g68Mq +oVeJ0XgFKaVZIkg4HOHh0CRpwiQPe1m2dEM7iXPeyRnn8z94tZK99nvhL46wgVBj +Z9fxlGFNAgMBAAECggEABQuJKelsgLieojfBSRVka8u3WG6biJuXUB8Zt4HPzJ4s +5Njf0DSxwqkWs7wnK4nVkZxWRNac1F2XQh3WOrOHALlTWQT7YdJQnGKL7j+anAkd +2JJqrTssO/CIKHGkPV2YwHks/B03G+Mw1EfFHcejt6lZHv2G8MBeaJWXGtZuGCLT +uGsfTBGKrSo6kdBOjF3Avfqh5SKyGM2UvtblYy7aLlmI6dllakK5qsSKryYz+HHh ++82xcSJKgqyaLUsq9mOpTzv9P5652Rrdu8+R8Ohr77zOOJ+uU3uQwxkpG99Nu15I +eSQeOHlswlS7seOLytuDs/UN8TWRViAKh7FJIV0CQQKBgQC+tFpNFr2jYaWBYYE/ +Qcv4u8gI2hsmTQtQ3wt0LP0SY9qFU6q16vOZSOhWOdGRzMQKFDZaSlVqYFEP4jnx +GCwa5znK5a0/q7v4X50NSuCSa2KkLywjunGO1FBwPjre86nPEJczNFi1XRzB3Vz8 +dQN41WtP81HdM3BnrBRZemjgxQKBgQC5ZjOEZXNshp9neCAuqVKkmLz5Saf65tLB +st2j3hEpNfA6NjsHwP7TF3lhbYnmFeFBxPZ4KoS2jBMo007QjdMEYPTIQV5oT670 +NgZ0imXK2aUBAtWIdOmIqaF5CDIxXGexoiofk71WYQF16paCfXXxwfdmSXQyspmA +KcPmjMF26QKBgCebN2HpRitnfUMYqAomNSGMhmfoPFlBCQebuzo+mbS3DkxAayTr +DfqY3MADtBWuzEw3lG4+H+0+4bcFyfjbh1VzDlqoRsoBdcGIwgpfsbJXIR5uOaGV ++D2stKQLGJjzTCIYFP7qcT4Bf5Z3zfcUqkrvMCFjrG3fYAn4ACXxOVTtAoGABLLn +aVqc40pCLgAoaKZX9t38JCFOxZgmDUy4O1f8fVvlm8QWGOs2SilVJTf+f7tcOyt/ +x6nkNTA1qBo67CQ8DedbLNwjRWeHmp7n6Po8/Dgp622j9dJovNL3ybaAdynNYv4m +LSi0asUIoXFxoRsG6zqsR4ZjEIngRBRK58P3f0kCgYEAnTPDUEUyBYLYSZN65bTP +yFq1YhWDo5kU7ipc5GQlfYgTfLPuGXgPBXBgEaAIERnatN44p1rQHSnmumgU9qcT +XCF0S8P7+VfSGRmxjLHHEINTDmxta2fImZXR1Z6THqpt4cLDiqhqzISMyHsW8kFb +S2C4yTwnV/FvxSTm1CtBbKo= +-----END PRIVATE KEY----- From 1a1ef241546424b7530ada5112288e384a1bd7cd Mon Sep 17 00:00:00 2001 From: Kevin Leung Date: Thu, 9 Jul 2026 20:42:26 +1000 Subject: [PATCH 2/2] Revert dune changes --- libs/mbedtls/dune | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/mbedtls/dune b/libs/mbedtls/dune index dd704b9c727..ca0780ddda2 100644 --- a/libs/mbedtls/dune +++ b/libs/mbedtls/dune @@ -4,7 +4,6 @@ (name mbedtls) (foreign_stubs (language c) - (names mbedtls_stubs) - (flags (:standard %{env:HAXE_MBEDTLS_CFLAGS=}))) + (names mbedtls_stubs)) (wrapped false) )