packages feed

s2n-tls-ffi (empty) → 0.1.0.0

raw patch · 9 files changed

+7363/−0 lines, 9 filesdep +basedep +s2n-tls-ffidep +unix

Dependencies added: base, s2n-tls-ffi, unix

Files

+ CHANGELOG.md view
@@ -0,0 +1,6 @@+# Changelog++## 0.1.0.0 -- 2026-04-28++* Initial release+* Support for linked and dynamic loading via `Library` type
+ LICENSE view
@@ -0,0 +1,190 @@+                                 Apache License+                           Version 2.0, January 2004+                        http://www.apache.org/licenses/++   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++   1. Definitions.++      "License" shall mean the terms and conditions for use, reproduction,+      and distribution as defined by Sections 1 through 9 of this document.++      "Licensor" shall mean the copyright owner or entity authorized by+      the copyright owner that is granting the License.++      "Legal Entity" shall mean the union of the acting entity and all+      other entities that control, are controlled by, or are under common+      control with that entity. For the purposes of this definition,+      "control" means (i) the power, direct or indirect, to cause the+      direction or management of such entity, whether by contract or+      otherwise, or (ii) ownership of fifty percent (50%) or more of the+      outstanding shares, or (iii) beneficial ownership of such entity.++      "You" (or "Your") shall mean an individual or Legal Entity+      exercising permissions granted by this License.++      "Source" form shall mean the preferred form for making modifications,+      including but not limited to software source code, documentation+      source, and configuration files.++      "Object" form shall mean any form resulting from mechanical+      transformation or translation of a Source form, including but+      not limited to compiled object code, generated documentation,+      and conversions to other media types.++      "Work" shall mean the work of authorship, whether in Source or+      Object form, made available under the License, as indicated by a+      copyright notice that is included in or attached to the work+      (an example is provided in the Appendix below).++      "Derivative Works" shall mean any work, whether in Source or Object+      form, that is based on (or derived from) the Work and for which the+      editorial revisions, annotations, elaborations, or other modifications+      represent, as a whole, an original work of authorship. For the purposes+      of this License, Derivative Works shall not include works that remain+      separable from, or merely link (or bind by name) to the interfaces of,+      the Work and Derivative Works thereof.++      "Contribution" shall mean any work of authorship, including+      the original version of the Work and any modifications or additions+      to that Work or Derivative Works thereof, that is intentionally+      submitted to the Licensor for inclusion in the Work by the copyright owner+      or by an individual or Legal Entity authorized to submit on behalf of+      the copyright owner. For the purposes of this definition, "submitted"+      means any form of electronic, verbal, or written communication sent+      to the Licensor or its representatives, including but not limited to+      communication on electronic mailing lists, source code control systems,+      and issue tracking systems that are managed by, or on behalf of, the+      Licensor for the purpose of discussing and improving the Work, but+      excluding communication that is conspicuously marked or otherwise+      designated in writing by the copyright owner as "Not a Contribution."++      "Contributor" shall mean Licensor and any individual or Legal Entity+      on behalf of whom a Contribution has been received by Licensor and+      subsequently incorporated within the Work.++   2. Grant of Copyright License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      copyright license to reproduce, prepare Derivative Works of,+      publicly display, publicly perform, sublicense, and distribute the+      Work and such Derivative Works in Source or Object form.++   3. Grant of Patent License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      (except as stated in this section) patent license to make, have made,+      use, offer to sell, sell, import, and otherwise transfer the Work,+      where such license applies only to those patent claims licensable+      by such Contributor that are necessarily infringed by their+      Contribution(s) alone or by combination of their Contribution(s)+      with the Work to which such Contribution(s) was submitted. If You+      institute patent litigation against any entity (including a+      cross-claim or counterclaim in a lawsuit) alleging that the Work+      or a Contribution incorporated within the Work constitutes direct+      or contributory patent infringement, then any patent licenses+      granted to You under this License for that Work shall terminate+      as of the date such litigation is filed.++   4. Redistribution. You may reproduce and distribute copies of the+      Work or Derivative Works thereof in any medium, with or without+      modifications, and in Source or Object form, provided that You+      meet the following conditions:++      (a) You must give any other recipients of the Work or+          Derivative Works a copy of this License; and++      (b) You must cause any modified files to carry prominent notices+          stating that You changed the files; and++      (c) You must retain, in the Source form of any Derivative Works+          that You distribute, all copyright, patent, trademark, and+          attribution notices from the Source form of the Work,+          excluding those notices that do not pertain to any part of+          the Derivative Works; and++      (d) If the Work includes a "NOTICE" text file as part of its+          distribution, then any Derivative Works that You distribute must+          include a readable copy of the attribution notices contained+          within such NOTICE file, excluding those notices that do not+          pertain to any part of the Derivative Works, in at least one+          of the following places: within a NOTICE text file distributed+          as part of the Derivative Works; within the Source form or+          documentation, if provided along with the Derivative Works; or,+          within a display generated by the Derivative Works, if and+          wherever such third-party notices normally appear. The contents+          of the NOTICE file are for informational purposes only and+          do not modify the License. You may add Your own attribution+          notices within Derivative Works that You distribute, alongside+          or as an addendum to the NOTICE text from the Work, provided+          that such additional attribution notices cannot be construed+          as modifying the License.++      You may add Your own copyright statement to Your modifications and+      may provide additional or different license terms and conditions+      for use, reproduction, or distribution of Your modifications, or+      for any such Derivative Works as a whole, provided Your use,+      reproduction, and distribution of the Work otherwise complies with+      the conditions stated in this License.++   5. Submission of Contributions. Unless You explicitly state otherwise,+      any Contribution intentionally submitted for inclusion in the Work+      by You to the Licensor shall be under the terms and conditions of+      this License, without any additional terms or conditions.+      Notwithstanding the above, nothing herein shall supersede or modify+      the terms of any separate license agreement you may have executed+      with Licensor regarding such Contributions.++   6. Trademarks. This License does not grant permission to use the trade+      names, trademarks, service marks, or product names of the Licensor,+      except as required for reasonable and customary use in describing the+      origin of the Work and reproducing the content of the NOTICE file.++   7. Disclaimer of Warranty. Unless required by applicable law or+      agreed to in writing, Licensor provides the Work (and each+      Contributor provides its Contributions) on an "AS IS" BASIS,+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+      implied, including, without limitation, any warranties or conditions+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+      PARTICULAR PURPOSE. You are solely responsible for determining the+      appropriateness of using or redistributing the Work and assume any+      risks associated with Your exercise of permissions under this License.++   8. Limitation of Liability. In no event and under no legal theory,+      whether in tort (including negligence), contract, or otherwise,+      unless required by applicable law (such as deliberate and grossly+      negligent acts) or agreed to in writing, shall any Contributor be+      liable to You for damages, including any direct, indirect, special,+      incidental, or consequential damages of any character arising as a+      result of this License or out of the use or inability to use the+      Work (including but not limited to damages for loss of goodwill,+      work stoppage, computer failure or malfunction, or any and all+      other commercial damages or losses), even if such Contributor+      has been advised of the possibility of such damages.++   9. Accepting Warranty or Additional Liability. While redistributing+      the Work or Derivative Works thereof, You may choose to offer,+      and charge a fee for, acceptance of support, warranty, indemnity,+      or other liability obligations and/or rights consistent with this+      License. However, in accepting such obligations, You may act only+      on Your own behalf and on Your sole responsibility, not on behalf+      of any other Contributor, and only if You agree to indemnify,+      defend, and hold each Contributor harmless for any liability+      incurred by, or claims asserted against, such Contributor by reason+      of your accepting any such warranty or additional liability.++   END OF TERMS AND CONDITIONS++   Copyright 2026 Daniel Goertzen++   Licensed under the Apache License, Version 2.0 (the "License");+   you may not use this file except in compliance with the License.+   You may obtain a copy of the License at++       http://www.apache.org/licenses/LICENSE-2.0++   Unless required by applicable law or agreed to in writing, software+   distributed under the License is distributed on an "AS IS" BASIS,+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+   See the License for the specific language governing permissions and+   limitations under the License.
+ README.md view
@@ -0,0 +1,77 @@+# s2n-tls-ffi++Low-level FFI bindings to the [s2n-tls](https://github.com/aws/s2n-tls) library.++This package provides raw FFI bindings which higher-level packages can build upon.++### Using a Linked s2n-tls Library++Call `withS2nTlsFfi` with `Linked` to use the linked-in s2n-tls library.++```haskell+import S2nTls.Ffi++main :: IO ()+main = withS2nTlsFfi Linked $ \ffi -> do+    -- use ffi...+```++### Using a Dynamically Loaded s2n-tls library++Call `withS2nTlsFfi` with `Dynamic path` to load s2n-tls at runtime. This enables runtime selection of different library builds - for example, switching between FIPS and non-FIPS crypto backends without recompiling your application.++```haskell+import S2nTls.Ffi++main :: IO ()+main = do+    let lib = if needFips then Dynamic "libs2n-fips.so" else Dynamic "libs2n.so"+    withS2nTlsFfi lib $ \ffi -> do+        -- use ffi...+```++## Error Handling via C Wrappers++s2n-tls stores error information in thread-local storage (TLS). When a function fails, the error code and debug message are available via `s2n_errno_location()` and `s2n_strerror_debug()`. However, Haskell's FFI provides no guarantee that a subsequent call will execute on the same OS thread, making direct access to thread-local error state unreliable.++To solve this, most s2n functions are called through thin C wrappers that:++1. Call the underlying s2n function+2. If it fails, immediately read the error code and debug string from TLS+3. Copy this information into an output struct with an owned 256-byte buffer+4. Return to Haskell with the error information safely captured++This ensures error information is captured in the same C stack frame before control returns to Haskell. The `S2nTlsFfi` record exposes these wrapped functions, which return `Either S2nError result` for functions that can fail.++Note that `s2n_send` and `s2n_recv` have special behavior: if the error was `S2N_ERR_T_BLOCKED`, debug info is not captured because this is a frequent, expected case that doesn't need debug overhead.++### Direct Error Functions++The `s2n_strerror` and `s2n_strerror_name` functions are **not** subject to thread-local storage limitations - they take an error code as input and return static strings. These can be called directly without wrappers if you need to format error messages yourself.++## Missing Symbol Behavior++Symbol loading is forgiving - missing symbols don't cause failure at load time. This allows the bindings to work with different versions of s2n-tls that may not export all functions.++- The `missingSymbols` field of `S2nTlsFfi` lists symbol names that couldn't be loaded+- Calling a function for a missing symbol throws a `MissingSymbol` exception+- Check `missingSymbols` at startup if your application requires specific functions++## Tests++The `memory-safety` test suite invokes all FFI functions to detect segfaults and memory errors. It does not verify correct behavior - only that calling each function doesn't crash. Each function name is printed before invocation, so if a crash occurs you can identify the culprit.++Run with:++```+cabal test memory-safety+```++## Related Packages++- [s2n-tls](https://github.com/goertzenator/s2n-tls) - High-level Haskell bindings built on this package+- [warp-s2n-tls](https://github.com/goertzenator/warp-s2n-tls) - TLS support for Warp using s2n-tls++## License++Apache-2.0
+ cbits/s2n_wrapper.c view
@@ -0,0 +1,3185 @@+/*+ * s2n_wrapper.c - C wrappers for s2n-tls functions+ *+ * These wrappers capture error information from thread-local storage+ * immediately after s2n function calls, making error handling safe+ * for Haskell FFI where TLS can be unreliable.+ */++#include "s2n_wrapper.h"+#include <stddef.h>+#include <stdio.h>++/* ============================================================================+ * Initialization & Cleanup+ * ============================================================================ */++int s2n_wrap_init(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cleanup(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cleanup_final(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_crypto_disable_init(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_disable_atexit(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_get_fips_mode(+    int (*fn)(int *),+    int *fips_mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(fips_mode);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Stack Traces+ * ============================================================================ */++int s2n_wrap_stack_traces_enabled_set(+    int (*fn)(int),+    int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_calculate_stacktrace(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_free_stacktrace(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn();+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_get_stacktrace(+    int (*fn)(void *),+    void *stacktrace,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(stacktrace);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Config Management+ * ============================================================================ */++void *s2n_wrap_config_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn();+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_config_new_minimal(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn();+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_free(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_free_dhparams(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_free_cert_chain_and_key(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_wall_clock(+    int (*fn)(void *, void *, void *),+    void *config, void *clock_fn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, clock_fn, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_monotonic_clock(+    int (*fn)(void *, void *, void *),+    void *config, void *clock_fn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, clock_fn, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Cache Callbacks+ * ============================================================================ */++int s2n_wrap_config_set_cache_store_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_cache_retrieve_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_cache_delete_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Memory & Random Callbacks+ * ============================================================================ */++int s2n_wrap_mem_set_callbacks(+    int (*fn)(void *, void *, void *, void *),+    void *init_cb, void *cleanup_cb, void *malloc_cb, void *free_cb,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(init_cb, cleanup_cb, malloc_cb, free_cb);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_rand_set_callbacks(+    int (*fn)(void *, void *, void *, void *),+    void *init_cb, void *cleanup_cb, void *seed_cb, void *mix_cb,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(init_cb, cleanup_cb, seed_cb, mix_cb);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Certificate Chain Management+ * ============================================================================ */++void *s2n_wrap_cert_chain_and_key_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn();+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_load_pem(+    int (*fn)(void *, const char *, const char *),+    void *chain_and_key, const char *chain_pem, const char *private_key_pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key, chain_pem, private_key_pem);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_load_pem_bytes(+    int (*fn)(void *, const uint8_t *, uint32_t, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *chain_pem, uint32_t chain_pem_len,+    const uint8_t *private_key_pem, uint32_t private_key_pem_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key, chain_pem, chain_pem_len, private_key_pem, private_key_pem_len);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_load_public_pem_bytes(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *chain_pem, uint32_t chain_pem_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key, chain_pem, chain_pem_len);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_free(+    int (*fn)(void *),+    void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_set_ctx(+    int (*fn)(void *, void *),+    void *chain_and_key, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_cert_chain_and_key_get_ctx(+    void *(*fn)(void *),+    void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(chain_and_key);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_cert_chain_and_key_get_private_key(+    void *(*fn)(void *),+    void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(chain_and_key);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_set_ocsp_data(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key, data, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_and_key_set_sct_list(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain_and_key, data, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_cert_tiebreak_callback(+    int (*fn)(void *, void *),+    void *config, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_add_cert_chain_and_key(+    int (*fn)(void *, const char *, const char *),+    void *config, const char *chain_pem, const char *private_key_pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, chain_pem, private_key_pem);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_add_cert_chain_and_key_to_store(+    int (*fn)(void *, void *),+    void *config, void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, chain_and_key);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_cert_chain_and_key_defaults(+    int (*fn)(void *, void **, uint32_t),+    void *config, void **chain_and_key_array, uint32_t count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, chain_and_key_array, count);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Trust Store+ * ============================================================================ */++int s2n_wrap_config_set_verification_ca_location(+    int (*fn)(void *, const char *, const char *),+    void *config, const char *ca_pem_filename, const char *ca_dir,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, ca_pem_filename, ca_dir);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_add_pem_to_trust_store(+    int (*fn)(void *, const char *),+    void *config, const char *pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, pem);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_wipe_trust_store(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_load_system_certs(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_cert_authorities_from_trust_store(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Verification & Validation+ * ============================================================================ */++int s2n_wrap_config_set_verify_after_sign(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, mode);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_check_stapled_ocsp_response(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t check,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, check);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_disable_x509_time_verification(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_disable_x509_verification(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_max_cert_chain_depth(+    int (*fn)(void *, uint16_t),+    void *config, uint16_t depth,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, depth);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_verify_host_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * DH Parameters+ * ============================================================================ */++int s2n_wrap_config_add_dhparams(+    int (*fn)(void *, const char *),+    void *config, const char *dhparams_pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, dhparams_pem);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Security Policies & Preferences+ * ============================================================================ */++int s2n_wrap_config_set_cipher_preferences(+    int (*fn)(void *, const char *),+    void *config, const char *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, version);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_append_protocol_preference(+    int (*fn)(void *, const uint8_t *, uint8_t),+    void *config, const uint8_t *protocol, uint8_t protocol_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, protocol, protocol_len);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_protocol_preferences(+    int (*fn)(void *, const char **, int),+    void *config, const char **protocols, int protocol_count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, protocols, protocol_count);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_status_request_type(+    int (*fn)(void *, int),+    void *config, int type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_ct_support_level(+    int (*fn)(void *, int),+    void *config, int level,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, level);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_alert_behavior(+    int (*fn)(void *, int),+    void *config, int behavior,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, behavior);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Extension Data+ * ============================================================================ */++int s2n_wrap_config_set_extension_data(+    int (*fn)(void *, int, const uint8_t *, uint32_t),+    void *config, int extension_type, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, extension_type, data, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_send_max_fragment_length(+    int (*fn)(void *, int),+    void *config, int mfl_code,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, mfl_code);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_accept_max_fragment_length(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Session & Ticket Configuration+ * ============================================================================ */++int s2n_wrap_config_set_session_state_lifetime(+    int (*fn)(void *, uint64_t),+    void *config, uint64_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, lifetime);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_session_tickets_onoff(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_session_cache_onoff(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_ticket_encrypt_decrypt_key_lifetime(+    int (*fn)(void *, uint64_t),+    void *config, uint64_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, lifetime);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_ticket_decrypt_key_lifetime(+    int (*fn)(void *, uint64_t),+    void *config, uint64_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, lifetime);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_add_ticket_crypto_key(+    int (*fn)(void *, const uint8_t *, uint32_t, const uint8_t *, uint32_t, uint64_t),+    void *config, const uint8_t *name, uint32_t name_len,+    const uint8_t *key, uint32_t key_len, uint64_t intro_time_in_seconds_from_epoch,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, name, name_len, key, key_len, intro_time_in_seconds_from_epoch);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_require_ticket_forward_secrecy(+    int (*fn)(void *, int),+    void *config, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Buffer & I/O Configuration+ * ============================================================================ */++int s2n_wrap_config_set_send_buffer_size(+    int (*fn)(void *, uint32_t),+    void *config, uint32_t size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, size);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_recv_multi_record(+    int (*fn)(void *, int),+    void *config, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Miscellaneous Config+ * ============================================================================ */++int s2n_wrap_config_set_ctx(+    int (*fn)(void *, void *),+    void *config, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_get_ctx(+    int (*fn)(void *, void **),+    void *config, void **ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_client_hello_cb(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_client_hello_cb_mode(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, mode);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_max_blinding_delay(+    int (*fn)(void *, uint32_t),+    void *config, uint32_t max_delay,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, max_delay);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_get_client_auth_type(+    int (*fn)(void *, int *),+    void *config, int *auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, auth_type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_client_auth_type(+    int (*fn)(void *, int),+    void *config, int auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, auth_type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_initial_ticket_count(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, count);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_psk_mode(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, mode);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_psk_selection_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_async_pkey_callback(+    int (*fn)(void *, void *),+    void *config, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_async_pkey_validation_mode(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, mode);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_session_ticket_cb(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_key_log_cb(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_enable_cert_req_dss_legacy_compat(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_server_max_early_data_size(+    int (*fn)(void *, uint32_t),+    void *config, uint32_t size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, size);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_early_data_cb(+    int (*fn)(void *, void *),+    void *config, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, callback);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_get_supported_groups(+    int (*fn)(void *, uint16_t *, uint16_t, uint16_t *),+    void *config, uint16_t *groups, uint16_t groups_count, uint16_t *groups_count_out,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, groups, groups_count, groups_count_out);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_config_set_serialization_version(+    int (*fn)(void *, int),+    void *config, int version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(config, version);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Connection Creation & Management+ * ============================================================================ */++void *s2n_wrap_connection_new(+    void *(*fn)(int),+    int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(mode);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_config(+    int (*fn)(void *, void *),+    void *conn, void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, config);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_ctx(+    int (*fn)(void *, void *),+    void *conn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_connection_get_ctx(+    void *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_cb_done(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_server_name_extension_used(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Client Hello Access+ * ============================================================================ */++void *s2n_wrap_connection_get_client_hello(+    void *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_client_hello_parse_message(+    void *(*fn)(const uint8_t *, uint32_t),+    const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(data, length);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_free(+    int (*fn)(void **),+    void **client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_raw_message_length(+    ssize_t (*fn)(void *),+    void *client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_raw_message(+    ssize_t (*fn)(void *, uint8_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello, out, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_cipher_suites_length(+    ssize_t (*fn)(void *),+    void *client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_cipher_suites(+    ssize_t (*fn)(void *, uint8_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello, out, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_extensions_length(+    ssize_t (*fn)(void *),+    void *client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_extensions(+    ssize_t (*fn)(void *, uint8_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello, out, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_extension_length(+    ssize_t (*fn)(void *, int),+    void *client_hello, int extension_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello, extension_type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_client_hello_get_extension_by_id(+    ssize_t (*fn)(void *, int, uint8_t *, uint32_t),+    void *client_hello, int extension_type, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(client_hello, extension_type, out, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_has_extension(+    int (*fn)(void *, uint16_t, int *),+    void *client_hello, uint16_t extension_iana, int *exists,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, extension_iana, exists);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_session_id_length(+    int (*fn)(void *, uint32_t *),+    void *client_hello, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_session_id(+    int (*fn)(void *, uint8_t *, uint32_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t *out_length, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, out, out_length, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_compression_methods_length(+    int (*fn)(void *, uint32_t *),+    void *client_hello, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_compression_methods(+    int (*fn)(void *, uint8_t *, uint32_t, uint32_t *),+    void *client_hello, uint8_t *out, uint32_t max_length, uint32_t *out_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, out, max_length, out_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_legacy_protocol_version(+    int (*fn)(void *, uint8_t *),+    void *client_hello, uint8_t *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, version);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_supported_groups(+    int (*fn)(void *, uint16_t *, uint16_t, uint16_t *),+    void *client_hello, uint16_t *groups, uint16_t groups_count, uint16_t *groups_count_out,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, groups, groups_count, groups_count_out);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_server_name_length(+    int (*fn)(void *, uint16_t *),+    void *client_hello, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_server_name(+    int (*fn)(void *, uint8_t *, uint16_t, uint16_t *),+    void *client_hello, uint8_t *out, uint16_t max_length, uint16_t *out_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, out, max_length, out_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_client_hello_get_legacy_record_version(+    int (*fn)(void *, uint8_t *),+    void *client_hello, uint8_t *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(client_hello, version);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * File Descriptor & I/O+ * ============================================================================ */++int s2n_wrap_connection_set_fd(+    int (*fn)(void *, int),+    void *conn, int fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, fd);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_read_fd(+    int (*fn)(void *, int),+    void *conn, int fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, fd);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_write_fd(+    int (*fn)(void *, int),+    void *conn, int fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, fd);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_read_fd(+    int (*fn)(void *, int *),+    void *conn, int *fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, fd);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_write_fd(+    int (*fn)(void *, int *),+    void *conn, int *fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, fd);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_use_corked_io(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_recv_ctx(+    int (*fn)(void *, void *),+    void *conn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_send_ctx(+    int (*fn)(void *, void *),+    void *conn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_recv_cb(+    int (*fn)(void *, void *),+    void *conn, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, callback);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_send_cb(+    int (*fn)(void *, void *),+    void *conn, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, callback);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Connection Preferences+ * ============================================================================ */++int s2n_wrap_connection_prefer_throughput(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_prefer_low_latency(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_recv_buffering(+    int (*fn)(void *, int),+    void *conn, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_dynamic_buffers(+    int (*fn)(void *, int),+    void *conn, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, enabled);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_dynamic_record_threshold(+    int (*fn)(void *, uint32_t, uint16_t),+    void *conn, uint32_t resize_threshold, uint16_t timeout_threshold,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, resize_threshold, timeout_threshold);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Host Verification+ * ============================================================================ */++int s2n_wrap_connection_set_verify_host_callback(+    int (*fn)(void *, void *, void *),+    void *conn, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, callback, ctx);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Blinding & Security+ * ============================================================================ */++int s2n_wrap_connection_set_blinding(+    int (*fn)(void *, int),+    void *conn, int blinding,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, blinding);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Cipher & Protocol Configuration+ * ============================================================================ */++int s2n_wrap_connection_set_cipher_preferences(+    int (*fn)(void *, const char *),+    void *conn, const char *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, version);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_request_key_update(+    int (*fn)(void *, int),+    void *conn, int peer_request,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, peer_request);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_append_protocol_preference(+    int (*fn)(void *, const uint8_t *, uint8_t),+    void *conn, const uint8_t *protocol, uint8_t protocol_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, protocol, protocol_len);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_protocol_preferences(+    int (*fn)(void *, const char **, int),+    void *conn, const char **protocols, int protocol_count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, protocols, protocol_count);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Server Name (SNI)+ * ============================================================================ */++int s2n_wrap_set_server_name(+    int (*fn)(void *, const char *),+    void *conn, const char *server_name,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, server_name);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const char *s2n_wrap_get_server_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Application Protocol (ALPN)+ * ============================================================================ */++const char *s2n_wrap_get_application_protocol(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * OCSP & Certificate Transparency+ * ============================================================================ */++const uint8_t *s2n_wrap_connection_get_ocsp_response(+    const uint8_t *(*fn)(void *, uint32_t *),+    void *conn, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const uint8_t *result = fn(conn, length);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const uint8_t *s2n_wrap_connection_get_sct_list(+    const uint8_t *(*fn)(void *, uint32_t *),+    void *conn, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const uint8_t *result = fn(conn, length);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Handshake & TLS Operations+ * ============================================================================ */++int s2n_wrap_negotiate(+    int (*fn)(void *, int *),+    void *conn, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, blocked);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++ssize_t s2n_wrap_send(+    ssize_t (*fn)(void *, const void *, ssize_t, int *),+    void *conn, const void *buf, ssize_t size, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(conn, buf, size, blocked);+    int err = *(err_funcs->errno_location)();+    bool is_blocked = err_funcs->error_get_type(err) == 3; // S2N_ERR_T_BLOCKED==3+    if (result < 0)+    {+        S2N_FILL_ERROR_MAYBE(err_funcs, err_out, !is_blocked);+    }+    return result;+}++ssize_t s2n_wrap_recv(+    ssize_t (*fn)(void *, void *, ssize_t, int *),+    void *conn, void *buf, ssize_t size, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    ssize_t result = fn(conn, buf, size, blocked);+    int err = *(err_funcs->errno_location)();+    bool is_blocked = err_funcs->error_get_type(err) == 3; // S2N_ERR_T_BLOCKED==3+    if (result < 0)+    {+        S2N_FILL_ERROR_MAYBE(err_funcs, err_out, !is_blocked);+    }+    return result;+}++int s2n_wrap_connection_free_handshake(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_release_buffers(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_wipe(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_free(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_shutdown(+    int (*fn)(void *, int *),+    void *conn, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, blocked);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_shutdown_send(+    int (*fn)(void *, int *),+    void *conn, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, blocked);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Client Authentication+ * ============================================================================ */++int s2n_wrap_connection_get_client_auth_type(+    int (*fn)(void *, int *),+    void *conn, int *auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, auth_type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_client_auth_type(+    int (*fn)(void *, int),+    void *conn, int auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, auth_type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_client_cert_chain(+    int (*fn)(void *, const uint8_t **, uint32_t *),+    void *conn, const uint8_t **cert_chain, uint32_t *cert_chain_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, cert_chain, cert_chain_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_client_cert_used(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Session Management+ * ============================================================================ */++int s2n_wrap_connection_add_new_tickets_to_send(+    int (*fn)(void *, uint8_t),+    void *conn, uint8_t num_tickets,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, num_tickets);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_tickets_sent(+    int (*fn)(void *, uint16_t *),+    void *conn, uint16_t *tickets_sent,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, tickets_sent);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_server_keying_material_lifetime(+    int (*fn)(void *, uint32_t),+    void *conn, uint32_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, lifetime);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_session_ticket_get_data_len(+    int (*fn)(void *, size_t *),+    void *ticket, size_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(ticket, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_session_ticket_get_data(+    int (*fn)(void *, size_t, uint8_t *),+    void *ticket, size_t max_length, uint8_t *data,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(ticket, max_length, data);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_session_ticket_get_lifetime(+    int (*fn)(void *, uint32_t *),+    void *ticket, uint32_t *lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(ticket, lifetime);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_session(+    int (*fn)(void *, const uint8_t *, size_t),+    void *conn, const uint8_t *session, size_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, session, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_session(+    int (*fn)(void *, uint8_t *, size_t),+    void *conn, uint8_t *session, size_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, session, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_session_ticket_lifetime_hint(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_session_length(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_session_id_length(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_session_id(+    int (*fn)(void *, uint8_t *, size_t),+    void *conn, uint8_t *session_id, size_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, session_id, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_is_session_resumed(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Certificate Information+ * ============================================================================ */++int s2n_wrap_connection_is_ocsp_stapled(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_selected_signature_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *sig_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, sig_alg);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_selected_digest_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *hash_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, hash_alg);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_selected_client_cert_signature_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *sig_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, sig_alg);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_selected_client_cert_digest_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *hash_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, hash_alg);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_connection_get_selected_cert(+    void *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_get_length(+    int (*fn)(void *, uint32_t *),+    void *chain, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_chain_get_cert(+    int (*fn)(void *, void **, uint32_t),+    void *chain, void **cert, uint32_t index,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(chain, cert, index);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_get_der(+    int (*fn)(void *, const uint8_t **, uint32_t *),+    void *cert, const uint8_t **der, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(cert, der, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_peer_cert_chain(+    int (*fn)(void *, void *),+    void *conn, void *cert_chain,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, cert_chain);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_get_x509_extension_value_length(+    int (*fn)(void *, const uint8_t *, uint32_t *),+    void *cert, const uint8_t *oid, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(cert, oid, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_get_x509_extension_value(+    int (*fn)(void *, const uint8_t *, uint8_t *, uint32_t *, int *),+    void *cert, const uint8_t *oid, uint8_t *value, uint32_t *length, int *critical,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(cert, oid, value, length, critical);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_get_utf8_string_from_extension_data_length(+    int (*fn)(const uint8_t *, uint32_t, uint32_t *),+    const uint8_t *data, uint32_t data_length, uint32_t *utf8_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(data, data_length, utf8_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_cert_get_utf8_string_from_extension_data(+    int (*fn)(const uint8_t *, uint32_t, uint8_t *, uint32_t *),+    const uint8_t *data, uint32_t data_length, uint8_t *utf8, uint32_t *utf8_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(data, data_length, utf8, utf8_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Pre-Shared Keys (PSK)+ * ============================================================================ */++void *s2n_wrap_external_psk_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn();+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_free(+    int (*fn)(void **),+    void **psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_set_identity(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *psk, const uint8_t *identity, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, identity, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_set_secret(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *psk, const uint8_t *secret, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, secret, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_set_hmac(+    int (*fn)(void *, int),+    void *psk, int hmac,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, hmac);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_append_psk(+    int (*fn)(void *, void *),+    void *conn, void *psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, psk);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_psk_mode(+    int (*fn)(void *, int),+    void *conn, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, mode);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_negotiated_psk_identity_length(+    int (*fn)(void *, uint16_t *),+    void *conn, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_negotiated_psk_identity(+    int (*fn)(void *, uint8_t *, uint16_t),+    void *conn, uint8_t *identity, uint16_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, identity, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++void *s2n_wrap_offered_psk_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    void *result = fn();+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_psk_free(+    int (*fn)(void **),+    void **psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_psk_get_identity(+    int (*fn)(void *, uint8_t **, uint16_t *),+    void *psk, uint8_t **identity, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, identity, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_psk_list_next(+    int (*fn)(void *, void *),+    void *psk_list, void *psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk_list, psk);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_psk_list_reread(+    int (*fn)(void *),+    void *psk_list,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk_list);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_psk_list_choose_psk(+    int (*fn)(void *, void *),+    void *psk_list, void *psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk_list, psk);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_configure_early_data(+    int (*fn)(void *, uint32_t, uint8_t, uint8_t),+    void *psk, uint32_t max_early_data_size, uint8_t cipher_suite_first_byte, uint8_t cipher_suite_second_byte,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, max_early_data_size, cipher_suite_first_byte, cipher_suite_second_byte);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_set_application_protocol(+    int (*fn)(void *, const uint8_t *, uint8_t),+    void *psk, const uint8_t *protocol, uint8_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, protocol, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_psk_set_early_data_context(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *psk, const uint8_t *context, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(psk, context, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Protocol Version Information+ * ============================================================================ */++int s2n_wrap_connection_get_client_protocol_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_server_protocol_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_actual_protocol_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_client_hello_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Cipher & Security Information+ * ============================================================================ */++const char *s2n_wrap_connection_get_cipher(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_certificate_match(+    int (*fn)(void *, int *),+    void *conn, int *cert_match,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, cert_match);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_master_secret(+    int (*fn)(void *, uint8_t *, size_t),+    void *conn, uint8_t *secret, size_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, secret, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_tls_exporter(+    int (*fn)(void *, const uint8_t *, uint32_t, const uint8_t *, uint32_t, uint8_t *, uint32_t),+    void *conn, const uint8_t *label, uint32_t label_length,+    const uint8_t *context, uint32_t context_length,+    uint8_t *output, uint32_t output_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, label, label_length, context, context_length, output, output_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_cipher_iana_value(+    int (*fn)(void *, uint8_t *, uint8_t *),+    void *conn, uint8_t *first, uint8_t *second,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, first, second);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_is_valid_for_cipher_preferences(+    int (*fn)(void *, const char *),+    void *conn, const char *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, version);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const char *s2n_wrap_connection_get_curve(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const char *s2n_wrap_connection_get_kem_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const char *s2n_wrap_connection_get_kem_group_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_key_exchange_group(+    int (*fn)(void *, const char **),+    void *conn, const char **group_name,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, group_name);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_alert(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const char *s2n_wrap_connection_get_handshake_type_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++const char *s2n_wrap_connection_get_last_message_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    const char *result = fn(conn);+    if (result == NULL)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Async Private Key Operations+ * ============================================================================ */++int s2n_wrap_async_pkey_op_perform(+    int (*fn)(void *, void *),+    void *op, void *key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op, key);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_async_pkey_op_apply(+    int (*fn)(void *, void *),+    void *op, void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op, conn);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_async_pkey_op_free(+    int (*fn)(void *),+    void *op,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_async_pkey_op_get_op_type(+    int (*fn)(void *, int *),+    void *op, int *op_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op, op_type);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_async_pkey_op_get_input_size(+    int (*fn)(void *, uint32_t *),+    void *op, uint32_t *size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op, size);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_async_pkey_op_get_input(+    int (*fn)(void *, uint8_t *, uint32_t),+    void *op, uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op, data, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_async_pkey_op_set_output(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *op, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(op, data, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Early Data+ * ============================================================================ */++int s2n_wrap_connection_set_server_max_early_data_size(+    int (*fn)(void *, uint32_t),+    void *conn, uint32_t size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, size);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_set_server_early_data_context(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *conn, const uint8_t *context, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, context, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_early_data_status(+    int (*fn)(void *, int *),+    void *conn, int *status,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, status);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_remaining_early_data_size(+    int (*fn)(void *, uint32_t *),+    void *conn, uint32_t *size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, size);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_get_max_early_data_size(+    int (*fn)(void *, uint32_t *),+    void *conn, uint32_t *size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, size);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_send_early_data(+    int (*fn)(void *, const uint8_t *, ssize_t, ssize_t *, int *),+    void *conn, const uint8_t *data, ssize_t data_len, ssize_t *written, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, data, data_len, written, blocked);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_recv_early_data(+    int (*fn)(void *, uint8_t *, ssize_t, ssize_t *, int *),+    void *conn, uint8_t *data, ssize_t max_data_len, ssize_t *read, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, data, max_data_len, read, blocked);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_early_data_get_context_length(+    int (*fn)(void *, uint16_t *),+    void *early_data, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(early_data, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_early_data_get_context(+    int (*fn)(void *, uint8_t *, uint16_t),+    void *early_data, uint8_t *context, uint16_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(early_data, context, max_length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_early_data_reject(+    int (*fn)(void *),+    void *early_data,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(early_data);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_offered_early_data_accept(+    int (*fn)(void *),+    void *early_data,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(early_data);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++/* ============================================================================+ * Connection Serialization+ * ============================================================================ */++int s2n_wrap_connection_serialization_length(+    int (*fn)(void *, uint32_t *),+    void *conn, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_serialize(+    int (*fn)(void *, uint8_t *, uint32_t),+    void *conn, uint8_t *buffer, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, buffer, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}++int s2n_wrap_connection_deserialize(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *conn, const uint8_t *buffer, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out)+{+    int result = fn(conn, buffer, length);+    if (result < 0)+    {+        S2N_FILL_ERROR(err_funcs, err_out);+    }+    return result;+}
+ cbits/s2n_wrapper.h view
@@ -0,0 +1,1294 @@+/*+ * s2n_wrapper.h - C wrappers for s2n-tls functions+ *+ * These wrappers capture error information from thread-local storage+ * immediately after s2n function calls, making error handling safe+ * for Haskell FFI where TLS can be unreliable.+ */++#ifndef S2N_WRAPPER_H+#define S2N_WRAPPER_H++#include <stddef.h>+#include <stdint.h>+#include <stdbool.h>+#include <string.h>+#include <sys/types.h>++/* Size of the owned debug string buffer in S2nErrorInfo */+#define S2N_ERROR_DEBUG_STRING_SIZE 256++/*+ * Error Functions Struct+ * Holds pointers to s2n error functions, loaded first during initialization.+ * These are used by all wrappers to capture error information.+ */+typedef struct+{+    int *(*errno_location)(void);+    const char *(*strerror_debug)(int error, const char *lang);+    int (*error_get_type)(int error);+} S2nErrorFuncs;++/*+ * Error Info Output Struct+ * Populated by wrappers on failure with full error information.+ * Uses an owned buffer for the debug string since s2n's string pointers+ * are ephemeral and may become invalid.+ */+typedef struct+{+    int error_code;+    char debug_string[S2N_ERROR_DEBUG_STRING_SIZE];+} S2nErrorInfo;++/*+ * Helper macro to populate error info on failure.+ * Copies the debug string into the owned buffer.+ */+#define S2N_FILL_ERROR_MAYBE(err_funcs, err_out, do_dbg)                             \+    do                                                                               \+    {                                                                                \+        (err_out)->error_code = *(err_funcs)->errno_location();                      \+        const char *_dbg = (err_funcs)->strerror_debug((err_out)->error_code, "EN"); \+        if (_dbg && (do_dbg))                                                        \+        {                                                                            \+            strncpy((err_out)->debug_string, _dbg, S2N_ERROR_DEBUG_STRING_SIZE - 1); \+            (err_out)->debug_string[S2N_ERROR_DEBUG_STRING_SIZE - 1] = '\0';         \+        }                                                                            \+        else                                                                         \+        {                                                                            \+            (err_out)->debug_string[0] = '\0';                                       \+        }                                                                            \+    } while (0)++/*+ * Helper macro to populate error info on failure.+ * Copies the debug string into the owned buffer.+ */+#define S2N_FILL_ERROR(err_funcs, err_out) S2N_FILL_ERROR_MAYBE(err_funcs, err_out, true)++/* ============================================================================+ * Wrapper Function Declarations+ * ============================================================================+ * Each wrapper takes:+ * - Function pointer to the underlying s2n function+ * - Same arguments as the original function+ * - Pointer to S2nErrorFuncs struct+ * - Pointer to S2nErrorInfo output struct+ * Returns the same type as the underlying function.+ */++/* --- Initialization & Cleanup --- */+int s2n_wrap_init(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cleanup(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cleanup_final(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_crypto_disable_init(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_disable_atexit(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* s2n_get_openssl_version returns long, no error - no wrapper needed */+/* s2n_get_fips_mode takes output param */+int s2n_wrap_get_fips_mode(+    int (*fn)(int *),+    int *fips_mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Stack Traces --- */+/* s2n_stack_traces_enabled returns bool, no wrapper needed */++int s2n_wrap_stack_traces_enabled_set(+    int (*fn)(int),+    int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_calculate_stacktrace(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_free_stacktrace(+    int (*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_get_stacktrace(+    int (*fn)(void *),+    void *stacktrace,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Config Management --- */+void *s2n_wrap_config_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_config_new_minimal(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_free(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_free_dhparams(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_free_cert_chain_and_key(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_wall_clock(+    int (*fn)(void *, void *, void *),+    void *config, void *clock_fn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_monotonic_clock(+    int (*fn)(void *, void *, void *),+    void *config, void *clock_fn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Cache Callbacks --- */+int s2n_wrap_config_set_cache_store_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_cache_retrieve_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_cache_delete_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Memory & Random Callbacks --- */+int s2n_wrap_mem_set_callbacks(+    int (*fn)(void *, void *, void *, void *),+    void *init_cb, void *cleanup_cb, void *malloc_cb, void *free_cb,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_rand_set_callbacks(+    int (*fn)(void *, void *, void *, void *),+    void *init_cb, void *cleanup_cb, void *seed_cb, void *mix_cb,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Certificate Chain Management --- */+void *s2n_wrap_cert_chain_and_key_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_load_pem(+    int (*fn)(void *, const char *, const char *),+    void *chain_and_key, const char *chain_pem, const char *private_key_pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_load_pem_bytes(+    int (*fn)(void *, const uint8_t *, uint32_t, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *chain_pem, uint32_t chain_pem_len,+    const uint8_t *private_key_pem, uint32_t private_key_pem_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_load_public_pem_bytes(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *chain_pem, uint32_t chain_pem_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_free(+    int (*fn)(void *),+    void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_set_ctx(+    int (*fn)(void *, void *),+    void *chain_and_key, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_cert_chain_and_key_get_ctx(+    void *(*fn)(void *),+    void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_cert_chain_and_key_get_private_key(+    void *(*fn)(void *),+    void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_set_ocsp_data(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_and_key_set_sct_list(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *chain_and_key, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_cert_tiebreak_callback(+    int (*fn)(void *, void *),+    void *config, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_add_cert_chain_and_key(+    int (*fn)(void *, const char *, const char *),+    void *config, const char *chain_pem, const char *private_key_pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_add_cert_chain_and_key_to_store(+    int (*fn)(void *, void *),+    void *config, void *chain_and_key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_cert_chain_and_key_defaults(+    int (*fn)(void *, void **, uint32_t),+    void *config, void **chain_and_key_array, uint32_t count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Trust Store --- */+int s2n_wrap_config_set_verification_ca_location(+    int (*fn)(void *, const char *, const char *),+    void *config, const char *ca_pem_filename, const char *ca_dir,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_add_pem_to_trust_store(+    int (*fn)(void *, const char *),+    void *config, const char *pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_wipe_trust_store(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_load_system_certs(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_cert_authorities_from_trust_store(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Verification & Validation --- */+int s2n_wrap_config_set_verify_after_sign(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_check_stapled_ocsp_response(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t check,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_disable_x509_time_verification(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_disable_x509_verification(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_max_cert_chain_depth(+    int (*fn)(void *, uint16_t),+    void *config, uint16_t depth,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_verify_host_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- DH Parameters --- */+int s2n_wrap_config_add_dhparams(+    int (*fn)(void *, const char *),+    void *config, const char *dhparams_pem,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Security Policies & Preferences --- */+int s2n_wrap_config_set_cipher_preferences(+    int (*fn)(void *, const char *),+    void *config, const char *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_append_protocol_preference(+    int (*fn)(void *, const uint8_t *, uint8_t),+    void *config, const uint8_t *protocol, uint8_t protocol_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_protocol_preferences(+    int (*fn)(void *, const char **, int),+    void *config, const char **protocols, int protocol_count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_status_request_type(+    int (*fn)(void *, int),+    void *config, int type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_ct_support_level(+    int (*fn)(void *, int),+    void *config, int level,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_alert_behavior(+    int (*fn)(void *, int),+    void *config, int behavior,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Extension Data --- */+int s2n_wrap_config_set_extension_data(+    int (*fn)(void *, int, const uint8_t *, uint32_t),+    void *config, int extension_type, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_send_max_fragment_length(+    int (*fn)(void *, int),+    void *config, int mfl_code,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_accept_max_fragment_length(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Session & Ticket Configuration --- */+int s2n_wrap_config_set_session_state_lifetime(+    int (*fn)(void *, uint64_t),+    void *config, uint64_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_session_tickets_onoff(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_session_cache_onoff(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_ticket_encrypt_decrypt_key_lifetime(+    int (*fn)(void *, uint64_t),+    void *config, uint64_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_ticket_decrypt_key_lifetime(+    int (*fn)(void *, uint64_t),+    void *config, uint64_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_add_ticket_crypto_key(+    int (*fn)(void *, const uint8_t *, uint32_t, const uint8_t *, uint32_t, uint64_t),+    void *config, const uint8_t *name, uint32_t name_len,+    const uint8_t *key, uint32_t key_len, uint64_t intro_time_in_seconds_from_epoch,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_require_ticket_forward_secrecy(+    int (*fn)(void *, int),+    void *config, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Buffer & I/O Configuration --- */+int s2n_wrap_config_set_send_buffer_size(+    int (*fn)(void *, uint32_t),+    void *config, uint32_t size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_recv_multi_record(+    int (*fn)(void *, int),+    void *config, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Miscellaneous Config --- */+int s2n_wrap_config_set_ctx(+    int (*fn)(void *, void *),+    void *config, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_get_ctx(+    int (*fn)(void *, void **),+    void *config, void **ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_client_hello_cb(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_client_hello_cb_mode(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_max_blinding_delay(+    int (*fn)(void *, uint32_t),+    void *config, uint32_t max_delay,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_get_client_auth_type(+    int (*fn)(void *, int *),+    void *config, int *auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_client_auth_type(+    int (*fn)(void *, int),+    void *config, int auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_initial_ticket_count(+    int (*fn)(void *, uint8_t),+    void *config, uint8_t count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_psk_mode(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_psk_selection_callback(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_async_pkey_callback(+    int (*fn)(void *, void *),+    void *config, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_async_pkey_validation_mode(+    int (*fn)(void *, int),+    void *config, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_session_ticket_cb(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_key_log_cb(+    int (*fn)(void *, void *, void *),+    void *config, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_enable_cert_req_dss_legacy_compat(+    int (*fn)(void *),+    void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_server_max_early_data_size(+    int (*fn)(void *, uint32_t),+    void *config, uint32_t size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_early_data_cb(+    int (*fn)(void *, void *),+    void *config, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_get_supported_groups(+    int (*fn)(void *, uint16_t *, uint16_t, uint16_t *),+    void *config, uint16_t *groups, uint16_t groups_count, uint16_t *groups_count_out,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_config_set_serialization_version(+    int (*fn)(void *, int),+    void *config, int version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Connection Creation & Management --- */+void *s2n_wrap_connection_new(+    void *(*fn)(int),+    int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_config(+    int (*fn)(void *, void *),+    void *conn, void *config,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_ctx(+    int (*fn)(void *, void *),+    void *conn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_connection_get_ctx(+    void *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_cb_done(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_server_name_extension_used(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Client Hello Access --- */+void *s2n_wrap_connection_get_client_hello(+    void *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_client_hello_parse_message(+    void *(*fn)(const uint8_t *, uint32_t),+    const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_free(+    int (*fn)(void **),+    void **client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_raw_message_length(+    ssize_t (*fn)(void *),+    void *client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_raw_message(+    ssize_t (*fn)(void *, uint8_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_cipher_suites_length(+    ssize_t (*fn)(void *),+    void *client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_cipher_suites(+    ssize_t (*fn)(void *, uint8_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_extensions_length(+    ssize_t (*fn)(void *),+    void *client_hello,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_extensions(+    ssize_t (*fn)(void *, uint8_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_extension_length(+    ssize_t (*fn)(void *, int),+    void *client_hello, int extension_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_client_hello_get_extension_by_id(+    ssize_t (*fn)(void *, int, uint8_t *, uint32_t),+    void *client_hello, int extension_type, uint8_t *out, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_has_extension(+    int (*fn)(void *, uint16_t, int *),+    void *client_hello, uint16_t extension_iana, int *exists,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_session_id_length(+    int (*fn)(void *, uint32_t *),+    void *client_hello, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_session_id(+    int (*fn)(void *, uint8_t *, uint32_t *, uint32_t),+    void *client_hello, uint8_t *out, uint32_t *out_length, uint32_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_compression_methods_length(+    int (*fn)(void *, uint32_t *),+    void *client_hello, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_compression_methods(+    int (*fn)(void *, uint8_t *, uint32_t, uint32_t *),+    void *client_hello, uint8_t *out, uint32_t max_length, uint32_t *out_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_legacy_protocol_version(+    int (*fn)(void *, uint8_t *),+    void *client_hello, uint8_t *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_supported_groups(+    int (*fn)(void *, uint16_t *, uint16_t, uint16_t *),+    void *client_hello, uint16_t *groups, uint16_t groups_count, uint16_t *groups_count_out,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_server_name_length(+    int (*fn)(void *, uint16_t *),+    void *client_hello, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_server_name(+    int (*fn)(void *, uint8_t *, uint16_t, uint16_t *),+    void *client_hello, uint8_t *out, uint16_t max_length, uint16_t *out_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_client_hello_get_legacy_record_version(+    int (*fn)(void *, uint8_t *),+    void *client_hello, uint8_t *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- File Descriptor & I/O --- */+int s2n_wrap_connection_set_fd(+    int (*fn)(void *, int),+    void *conn, int fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_read_fd(+    int (*fn)(void *, int),+    void *conn, int fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_write_fd(+    int (*fn)(void *, int),+    void *conn, int fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_read_fd(+    int (*fn)(void *, int *),+    void *conn, int *fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_write_fd(+    int (*fn)(void *, int *),+    void *conn, int *fd,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_use_corked_io(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_recv_ctx(+    int (*fn)(void *, void *),+    void *conn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_send_ctx(+    int (*fn)(void *, void *),+    void *conn, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_recv_cb(+    int (*fn)(void *, void *),+    void *conn, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_send_cb(+    int (*fn)(void *, void *),+    void *conn, void *callback,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Connection Preferences --- */+int s2n_wrap_connection_prefer_throughput(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_prefer_low_latency(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_recv_buffering(+    int (*fn)(void *, int),+    void *conn, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* s2n_peek_buffered returns uint32, no error - no wrapper needed */++int s2n_wrap_connection_set_dynamic_buffers(+    int (*fn)(void *, int),+    void *conn, int enabled,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_dynamic_record_threshold(+    int (*fn)(void *, uint32_t, uint16_t),+    void *conn, uint32_t resize_threshold, uint16_t timeout_threshold,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Host Verification --- */+int s2n_wrap_connection_set_verify_host_callback(+    int (*fn)(void *, void *, void *),+    void *conn, void *callback, void *ctx,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Blinding & Security --- */+int s2n_wrap_connection_set_blinding(+    int (*fn)(void *, int),+    void *conn, int blinding,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* s2n_connection_get_delay returns uint64, no error - no wrapper needed */++/* --- Cipher & Protocol Configuration --- */+int s2n_wrap_connection_set_cipher_preferences(+    int (*fn)(void *, const char *),+    void *conn, const char *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_request_key_update(+    int (*fn)(void *, int),+    void *conn, int peer_request,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_append_protocol_preference(+    int (*fn)(void *, const uint8_t *, uint8_t),+    void *conn, const uint8_t *protocol, uint8_t protocol_len,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_protocol_preferences(+    int (*fn)(void *, const char **, int),+    void *conn, const char **protocols, int protocol_count,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Server Name (SNI) --- */+int s2n_wrap_set_server_name(+    int (*fn)(void *, const char *),+    void *conn, const char *server_name,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const char *s2n_wrap_get_server_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Application Protocol (ALPN) --- */+const char *s2n_wrap_get_application_protocol(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- OCSP & Certificate Transparency --- */+const uint8_t *s2n_wrap_connection_get_ocsp_response(+    const uint8_t *(*fn)(void *, uint32_t *),+    void *conn, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const uint8_t *s2n_wrap_connection_get_sct_list(+    const uint8_t *(*fn)(void *, uint32_t *),+    void *conn, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Handshake & TLS Operations --- */+int s2n_wrap_negotiate(+    int (*fn)(void *, int *),+    void *conn, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_send(+    ssize_t (*fn)(void *, const void *, ssize_t, int *),+    void *conn, const void *buf, ssize_t size, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++ssize_t s2n_wrap_recv(+    ssize_t (*fn)(void *, void *, ssize_t, int *),+    void *conn, void *buf, ssize_t size, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* s2n_peek returns uint32, no error - no wrapper needed */++int s2n_wrap_connection_free_handshake(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_release_buffers(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_wipe(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_free(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_shutdown(+    int (*fn)(void *, int *),+    void *conn, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_shutdown_send(+    int (*fn)(void *, int *),+    void *conn, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Client Authentication --- */+int s2n_wrap_connection_get_client_auth_type(+    int (*fn)(void *, int *),+    void *conn, int *auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_client_auth_type(+    int (*fn)(void *, int),+    void *conn, int auth_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_client_cert_chain(+    int (*fn)(void *, const uint8_t **, uint32_t *),+    void *conn, const uint8_t **cert_chain, uint32_t *cert_chain_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_client_cert_used(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Session Management --- */+int s2n_wrap_connection_add_new_tickets_to_send(+    int (*fn)(void *, uint8_t),+    void *conn, uint8_t num_tickets,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_tickets_sent(+    int (*fn)(void *, uint16_t *),+    void *conn, uint16_t *tickets_sent,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_server_keying_material_lifetime(+    int (*fn)(void *, uint32_t),+    void *conn, uint32_t lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_session_ticket_get_data_len(+    int (*fn)(void *, size_t *),+    void *ticket, size_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_session_ticket_get_data(+    int (*fn)(void *, size_t, uint8_t *),+    void *ticket, size_t max_length, uint8_t *data,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_session_ticket_get_lifetime(+    int (*fn)(void *, uint32_t *),+    void *ticket, uint32_t *lifetime,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_session(+    int (*fn)(void *, const uint8_t *, size_t),+    void *conn, const uint8_t *session, size_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_session(+    int (*fn)(void *, uint8_t *, size_t),+    void *conn, uint8_t *session, size_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_session_ticket_lifetime_hint(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_session_length(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_session_id_length(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_session_id(+    int (*fn)(void *, uint8_t *, size_t),+    void *conn, uint8_t *session_id, size_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_is_session_resumed(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Certificate Information --- */+int s2n_wrap_connection_is_ocsp_stapled(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_selected_signature_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *sig_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_selected_digest_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *hash_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_selected_client_cert_signature_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *sig_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_selected_client_cert_digest_algorithm(+    int (*fn)(void *, int *),+    void *conn, int *hash_alg,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_connection_get_selected_cert(+    void *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_get_length(+    int (*fn)(void *, uint32_t *),+    void *chain, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_chain_get_cert(+    int (*fn)(void *, void **, uint32_t),+    void *chain, void **cert, uint32_t index,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_get_der(+    int (*fn)(void *, const uint8_t **, uint32_t *),+    void *cert, const uint8_t **der, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_peer_cert_chain(+    int (*fn)(void *, void *),+    void *conn, void *cert_chain,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_get_x509_extension_value_length(+    int (*fn)(void *, const uint8_t *, uint32_t *),+    void *cert, const uint8_t *oid, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_get_x509_extension_value(+    int (*fn)(void *, const uint8_t *, uint8_t *, uint32_t *, int *),+    void *cert, const uint8_t *oid, uint8_t *value, uint32_t *length, int *critical,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_get_utf8_string_from_extension_data_length(+    int (*fn)(const uint8_t *, uint32_t, uint32_t *),+    const uint8_t *data, uint32_t data_length, uint32_t *utf8_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_cert_get_utf8_string_from_extension_data(+    int (*fn)(const uint8_t *, uint32_t, uint8_t *, uint32_t *),+    const uint8_t *data, uint32_t data_length, uint8_t *utf8, uint32_t *utf8_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Pre-Shared Keys (PSK) --- */+void *s2n_wrap_external_psk_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_free(+    int (*fn)(void **),+    void **psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_set_identity(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *psk, const uint8_t *identity, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_set_secret(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *psk, const uint8_t *secret, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_set_hmac(+    int (*fn)(void *, int),+    void *psk, int hmac,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_append_psk(+    int (*fn)(void *, void *),+    void *conn, void *psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_psk_mode(+    int (*fn)(void *, int),+    void *conn, int mode,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_negotiated_psk_identity_length(+    int (*fn)(void *, uint16_t *),+    void *conn, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_negotiated_psk_identity(+    int (*fn)(void *, uint8_t *, uint16_t),+    void *conn, uint8_t *identity, uint16_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++void *s2n_wrap_offered_psk_new(+    void *(*fn)(void),+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_psk_free(+    int (*fn)(void **),+    void **psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_psk_get_identity(+    int (*fn)(void *, uint8_t **, uint16_t *),+    void *psk, uint8_t **identity, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* s2n_offered_psk_list_has_next returns bool, no error - no wrapper needed */++int s2n_wrap_offered_psk_list_next(+    int (*fn)(void *, void *),+    void *psk_list, void *psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_psk_list_reread(+    int (*fn)(void *),+    void *psk_list,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_psk_list_choose_psk(+    int (*fn)(void *, void *),+    void *psk_list, void *psk,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_configure_early_data(+    int (*fn)(void *, uint32_t, uint8_t, uint8_t),+    void *psk, uint32_t max_early_data_size, uint8_t cipher_suite_first_byte, uint8_t cipher_suite_second_byte,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_set_application_protocol(+    int (*fn)(void *, const uint8_t *, uint8_t),+    void *psk, const uint8_t *protocol, uint8_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_psk_set_early_data_context(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *psk, const uint8_t *context, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Connection Statistics --- */+/* s2n_connection_get_wire_bytes_in returns uint64, no error - no wrapper needed */+/* s2n_connection_get_wire_bytes_out returns uint64, no error - no wrapper needed */++/* --- Protocol Version Information --- */+int s2n_wrap_connection_get_client_protocol_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_server_protocol_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_actual_protocol_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_client_hello_version(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Cipher & Security Information --- */+const char *s2n_wrap_connection_get_cipher(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_certificate_match(+    int (*fn)(void *, int *),+    void *conn, int *cert_match,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_master_secret(+    int (*fn)(void *, uint8_t *, size_t),+    void *conn, uint8_t *secret, size_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_tls_exporter(+    int (*fn)(void *, const uint8_t *, uint32_t, const uint8_t *, uint32_t, uint8_t *, uint32_t),+    void *conn, const uint8_t *label, uint32_t label_length,+    const uint8_t *context, uint32_t context_length,+    uint8_t *output, uint32_t output_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_cipher_iana_value(+    int (*fn)(void *, uint8_t *, uint8_t *),+    void *conn, uint8_t *first, uint8_t *second,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_is_valid_for_cipher_preferences(+    int (*fn)(void *, const char *),+    void *conn, const char *version,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const char *s2n_wrap_connection_get_curve(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const char *s2n_wrap_connection_get_kem_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const char *s2n_wrap_connection_get_kem_group_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_key_exchange_group(+    int (*fn)(void *, const char **),+    void *conn, const char **group_name,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_alert(+    int (*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const char *s2n_wrap_connection_get_handshake_type_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++const char *s2n_wrap_connection_get_last_message_name(+    const char *(*fn)(void *),+    void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Async Private Key Operations --- */+int s2n_wrap_async_pkey_op_perform(+    int (*fn)(void *, void *),+    void *op, void *key,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_async_pkey_op_apply(+    int (*fn)(void *, void *),+    void *op, void *conn,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_async_pkey_op_free(+    int (*fn)(void *),+    void *op,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_async_pkey_op_get_op_type(+    int (*fn)(void *, int *),+    void *op, int *op_type,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_async_pkey_op_get_input_size(+    int (*fn)(void *, uint32_t *),+    void *op, uint32_t *size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_async_pkey_op_get_input(+    int (*fn)(void *, uint8_t *, uint32_t),+    void *op, uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_async_pkey_op_set_output(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *op, const uint8_t *data, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Early Data --- */+int s2n_wrap_connection_set_server_max_early_data_size(+    int (*fn)(void *, uint32_t),+    void *conn, uint32_t size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_set_server_early_data_context(+    int (*fn)(void *, const uint8_t *, uint16_t),+    void *conn, const uint8_t *context, uint16_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_early_data_status(+    int (*fn)(void *, int *),+    void *conn, int *status,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_remaining_early_data_size(+    int (*fn)(void *, uint32_t *),+    void *conn, uint32_t *size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_get_max_early_data_size(+    int (*fn)(void *, uint32_t *),+    void *conn, uint32_t *size,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_send_early_data(+    int (*fn)(void *, const uint8_t *, ssize_t, ssize_t *, int *),+    void *conn, const uint8_t *data, ssize_t data_len, ssize_t *written, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_recv_early_data(+    int (*fn)(void *, uint8_t *, ssize_t, ssize_t *, int *),+    void *conn, uint8_t *data, ssize_t max_data_len, ssize_t *read, int *blocked,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_early_data_get_context_length(+    int (*fn)(void *, uint16_t *),+    void *early_data, uint16_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_early_data_get_context(+    int (*fn)(void *, uint8_t *, uint16_t),+    void *early_data, uint8_t *context, uint16_t max_length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_early_data_reject(+    int (*fn)(void *),+    void *early_data,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_offered_early_data_accept(+    int (*fn)(void *),+    void *early_data,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++/* --- Connection Serialization --- */+int s2n_wrap_connection_serialization_length(+    int (*fn)(void *, uint32_t *),+    void *conn, uint32_t *length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_serialize(+    int (*fn)(void *, uint8_t *, uint32_t),+    void *conn, uint8_t *buffer, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++int s2n_wrap_connection_deserialize(+    int (*fn)(void *, const uint8_t *, uint32_t),+    void *conn, const uint8_t *buffer, uint32_t length,+    const S2nErrorFuncs *err_funcs, S2nErrorInfo *err_out);++#endif /* S2N_WRAPPER_H */
+ s2n-tls-ffi.cabal view
@@ -0,0 +1,60 @@+cabal-version:      3.0+name:               s2n-tls-ffi+version:            0.1.0.0+synopsis:           Low-level FFI bindings to the s2n-tls library+description:+    Low-level FFI bindings to the s2n-tls library.++license:            Apache-2.0+license-file:       LICENSE+author:             Daniel Goertzen+maintainer:         daniel.goertzen@gmail.com+copyright:          2026 Daniel Goertzen+category:           Cryptography, FFI, Network+build-type:         Simple+tested-with:        GHC == 9.8.2+extra-doc-files:+    CHANGELOG.md+    README.md+extra-source-files: cbits/s2n_wrapper.h+homepage:           https://github.com/goertzenator/s2n-tls-ffi+bug-reports:        https://github.com/goertzenator/s2n-tls-ffi/issues++source-repository head+    type:     git+    location: https://github.com/goertzenator/s2n-tls-ffi.git++source-repository this+    type:     git+    location: https://github.com/goertzenator/s2n-tls-ffi.git+    tag:      v0.1.0.0++library+    exposed-modules:+        S2nTls.Ffi+        S2nTls.Ffi.Types++    build-depends:+        base >= 4.14 && < 5+      , unix >= 2.7 && < 2.9++    hs-source-dirs:   src+    default-language: GHC2021+    ghc-options:      -Wall -haddock++    -- C wrapper for capturing error info from thread-local storage+    c-sources:        cbits/s2n_wrapper.c+    include-dirs:     cbits++    -- Required for Linked mode (symbols loaded via dlopen(NULL))+    extra-libraries:  s2n++test-suite memory-safety+    type:             exitcode-stdio-1.0+    main-is:          MemorySafety.hs+    hs-source-dirs:   test+    default-language: GHC2021+    build-depends:+        base >= 4.14 && < 5+      , s2n-tls-ffi+    ghc-options:      -threaded -rtsopts "-with-rtsopts=-N"
+ src/S2nTls/Ffi.hs view
@@ -0,0 +1,918 @@+{-# LANGUAGE RecordWildCards #-}++{- |+Module      : S2nTls.Ffi+Description : Low-level FFI bindings to the s2n-tls library+Copyright   : (c) 2026 Daniel Goertzen+License     : Apache-2.0+Maintainer  : daniel.goertzen@gmail.com+Stability   : experimental+Portability : non-portable (requires s2n-tls C library)++This module provides low-level FFI bindings to the s2n-tls library.++The core type is 'S2nTlsFfi', a record containing all FFI function+pointers. Use 'withS2nTlsFfi' with a 'Library' to obtain one:++* 'Linked': For executables that link s2n-tls at compile time.+  Uses dlopen(NULL) to load symbols from the running executable.++* @'Dynamic' path@: To load the library at runtime via dlopen.+  Pass the path to libs2n.so.++C wrappers are used to safely capture error information+(including TLS-dependent error strings) in the same C stack frame,+avoiding thread-local storage issues in Haskell FFI.++Symbol loading is forgiving - missing symbols don't cause failure+at load time. Instead, calling a missing symbol throws 'MissingSymbol'.+Check the 'missingSymbols' field to see which symbols weren't found.++= Memory Locking (mlock)++== What is mlock?++s2n-tls uses the Linux @mlock()@ system call to lock memory pages containing+cryptographic secrets (private keys, session keys, etc.) into RAM. This prevents+the operating system from swapping these pages to disk, where they could+potentially be recovered by an attacker after your application terminates.++== The RLIMIT_MEMLOCK Limit++Linux enforces a per-process limit on how much memory can be locked, controlled+by @RLIMIT_MEMLOCK@. On many systems, this defaults to just __64 KB__ (or even+32 KB on some Debian versions). Since s2n-tls locks memory for all TLS+connections and cryptographic operations, this limit can be exhausted quickly+in applications handling multiple connections.++When the limit is exceeded, you'll see errors like:++> Error Message: 'error calling mlock'+> Debug String: 'Error encountered in s2n_mem.c line 106'++== Solutions++__Option 1: Increase the mlock limit (recommended for production)__++Raise the limit for your shell session:++> ulimit -l unlimited++Or set it to a specific value (in KB):++> ulimit -l 65536  # 64 MB++For systemd services, add to your unit file:++> [Service]+> LimitMEMLOCK=infinity++For persistent user limits, add to @\/etc\/security\/limits.conf@:++> youruser  soft  memlock  unlimited+> youruser  hard  memlock  unlimited++__Option 2: Disable mlock (acceptable for development\/testing)__++Set the environment variable to disable memory locking entirely:++> S2N_DONT_MLOCK=1 ./your-application++== Security Considerations++* __With mlock enabled__: Secrets are protected from being written to swap,+  reducing the risk of recovery from disk. This is the recommended setting+  for production deployments handling sensitive data.++* __With mlock disabled__: Secrets may be swapped to disk under memory+  pressure. This is generally acceptable for development, testing, and+  applications where the threat model doesn't include disk forensics.++* __Note__: Even with mlock enabled, laptop suspend\/hibernate modes may+  save RAM contents to disk regardless of memory locks.++== Running Tests++Tests may exhaust the default mlock limit. Use:++> S2N_DONT_MLOCK=1 cabal test+-}+module S2nTls.Ffi (+    -- * Core Types+    S2nTlsFfi (..),++    -- * Library Loading+    Library (..),+    withS2nTlsFfi,+    LoadError (..),++    -- * Error Types+    MissingSymbol (..),+    S2nError (..),+    S2nErrorFuncs (..),+) where++import Control.Exception (Exception, bracket, throwIO)+import Control.Monad (when)+import Data.IORef (modifyIORef', newIORef, readIORef)+import Data.Word (Word16, Word32, Word64, Word8)+import Foreign.C.String (CString)+import Foreign.C.Types (CBool (..), CInt (..), CLong (..), CSize (..))+import Foreign.Marshal.Alloc (alloca, free, malloc)+import Foreign.Ptr (FunPtr, Ptr, nullFunPtr, nullPtr)+import Foreign.Storable (peek, poke)+import System.Posix.DynamicLinker (DL, RTLDFlags (RTLD_LAZY, RTLD_LOCAL), dlclose, dlopen, dlsym)+import System.Posix.Types (CSsize (..))++import S2nTls.Ffi.Types++-- | Specifies how to load the s2n-tls library.+data Library+    = -- | Load symbols from the currently linked executable (uses dlopen(NULL))+      Linked+    | -- | Load library dynamically from the given path+      Dynamic String+    deriving (Show, Eq)++-- | Errors that can occur when loading the s2n-tls library.+data LoadError+    = -- | Library file could not be opened+      LibraryNotFound FilePath String+    | -- | A required symbol was not found in the library+      RequiredSymbolNotFound String+    deriving (Show, Eq)++instance Exception LoadError++class TransformError a where+    transformError :: (Ptr S2nError -> IO a) -> IO (Either S2nError a)++instance TransformError CInt where+    transformError action = alloca $ \errInfoPtr -> do+        res <- action errInfoPtr+        if res < 0+            then Left <$> peek errInfoPtr+            else pure $ Right res++instance TransformError CSsize where+    transformError action = alloca $ \errInfoPtr -> do+        res <- action errInfoPtr+        if res < 0+            then Left <$> peek errInfoPtr+            else pure $ Right res++instance TransformError (Ptr a) where+    transformError action = alloca $ \errInfoPtr -> do+        res <- action errInfoPtr+        if res == nullPtr+            then Left <$> peek errInfoPtr+            else pure $ Right res++-- CSize is unsigned, so functions returning CSize typically can't fail+-- They always return a valid size value+instance TransformError CSize where+    transformError action = alloca $ \errInfoPtr -> do+        res <- action errInfoPtr+        pure $ Right res++const2 :: a -> b -> c -> a+const2 x _ _ = x++const3 :: a -> b -> c -> d -> a+const3 x _ _ _ = x++const4 :: a -> b -> c -> d -> e -> a+const4 x _ _ _ _ = x++const5 :: a -> b -> c -> d -> e -> f -> a+const5 x _ _ _ _ _ = x++const6 :: a -> b -> c -> d -> e -> f -> g -> a+const6 x _ _ _ _ _ _ = x++const7 :: a -> b -> c -> d -> e -> f -> g -> h -> a+const7 x _ _ _ _ _ _ _ = x++{- | Load the s2n-tls library and provide a 'S2nTlsFfi' record to the+given callback. The library is automatically unloaded when the callback+returns (or throws an exception).++@+-- Use symbols from the linked executable+withS2nTlsFfi Linked $ \\ffi -> do+    result <- s2n_init ffi+    ...++-- Load library dynamically+withS2nTlsFfi (Dynamic "libs2n.so") $ \\ffi -> do+    print (missingSymbols ffi)  -- see which symbols weren't found+    ...+@+-}+withS2nTlsFfi ::+    -- | How to load the library+    Library ->+    -- | Callback that receives the populated 'S2nTlsFfi' record+    (S2nTlsFfi -> IO a) ->+    IO a+withS2nTlsFfi lib action =+    bracket (openLib (libraryPath lib)) dlclose $ \dl ->+        bracket (malloc :: IO (Ptr S2nErrorFuncs)) free $ \errFuncsPtr -> do+            -- Load error functions first (fatal if missing)+            errFuncs <- loadErrorFuncs dl+            poke errFuncsPtr errFuncs++            -- Load all other symbols (forgiving)+            (ffi, missing) <- loadSymbols dl errFuncsPtr+            action ffi{missingSymbols = missing}++-- | Convert Library to the path string for dlopen+libraryPath :: Library -> FilePath+libraryPath Linked = ""+libraryPath (Dynamic path) = path++-- | Open the library, handling empty path for dlopen(NULL)+openLib :: FilePath -> IO DL+openLib path = dlopen path [RTLD_LAZY, RTLD_LOCAL]++-- | Load the error functions (required for meaningful error reporting)+loadErrorFuncs :: DL -> IO S2nErrorFuncs+loadErrorFuncs dl = do+    el <- dlsym dl "s2n_errno_location"+    sd <- dlsym dl "s2n_strerror_debug"+    et <- dlsym dl "s2n_error_get_type"+    pure $ S2nErrorFuncs el sd et++-- | Create a closure that throws MissingSymbol+throwMissing :: String -> IO a+throwMissing name = throwIO (MissingSymbol name)++-- | Indicate where a symbol is required vs optional+data MethodRequirement = Mandatory | Optional+    deriving (Show, Eq)++{- | Load all s2n-tls symbols from the given dynamic library handle.+Returns the S2nTlsFfi record and list of missing symbol names.+-}+loadSymbols :: DL -> Ptr S2nErrorFuncs -> IO (S2nTlsFfi, [String])+loadSymbols dl errFuncsPtr = do+    missingRef <- newIORef []++    let+        -- Helper to load a symbol with forgiving behavior+        load :: String -> MethodRequirement -> IO (FunPtr a)+        load name req = do+            ptr <- dlsym dl name+            when (ptr == nullFunPtr) $ do+                modifyIORef' missingRef (name :)+            if ptr == nullFunPtr && req == Mandatory+                then do+                    throwMissing name+                else do+                    pure ptr++        mkMethod0Direct :: String -> MethodRequirement -> (FunPtr x -> IO r) -> IO (IO r)+        mkMethod0Direct name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then throwMissing name+                    else action ptr++        mkMethod1Direct :: String -> MethodRequirement -> (FunPtr x -> a -> IO r) -> IO (a -> IO r)+        mkMethod1Direct name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const (throwMissing name)+                    else action ptr++        mkMethod2Direct :: String -> MethodRequirement -> (FunPtr x -> a -> b -> IO r) -> IO (a -> b -> IO r)+        mkMethod2Direct name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const2 (throwMissing name)+                    else action ptr++        -- Note: C wrappers have signature: FunPtr -> args... -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r+        mkMethod0 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (IO (Either S2nError r))+        mkMethod0 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then throwMissing name+                    else transformError (action ptr errFuncsPtr)++        mkMethod1 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> IO (Either S2nError r))+        mkMethod1 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const (throwMissing name)+                    else \a -> transformError (action ptr a errFuncsPtr)++        mkMethod2 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> b -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> b -> IO (Either S2nError r))+        mkMethod2 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const2 (throwMissing name)+                    else \a b -> transformError (action ptr a b errFuncsPtr)++        mkMethod3 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> b -> c -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> b -> c -> IO (Either S2nError r))+        mkMethod3 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const3 (throwMissing name)+                    else \a b c -> transformError (action ptr a b c errFuncsPtr)++        mkMethod4 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> b -> c -> d -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> b -> c -> d -> IO (Either S2nError r))+        mkMethod4 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const4 (throwMissing name)+                    else \a b c d -> transformError (action ptr a b c d errFuncsPtr)++        mkMethod5 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> b -> c -> d -> e -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> b -> c -> d -> e -> IO (Either S2nError r))+        mkMethod5 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const5 (throwMissing name)+                    else \a b c d e -> transformError (action ptr a b c d e errFuncsPtr)++        mkMethod6 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> b -> c -> d -> e -> f -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> b -> c -> d -> e -> f -> IO (Either S2nError r))+        mkMethod6 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const6 (throwMissing name)+                    else \a b c d e f -> transformError (action ptr a b c d e f errFuncsPtr)++        mkMethod7 :: (TransformError r) => String -> MethodRequirement -> (FunPtr () -> a -> b -> c -> d -> e -> f -> g -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO r) -> IO (a -> b -> c -> d -> e -> f -> g -> IO (Either S2nError r))+        mkMethod7 name req action = do+            ptr <- load name req+            pure $+                if ptr == nullFunPtr+                    then const7 (throwMissing name)+                    else \a b c d e f g -> transformError (action ptr a b c d e f g errFuncsPtr)++    -- Initialization & Cleanup+    s2n_init <- mkMethod0 "s2n_init" Optional c_wrap_init+    s2n_cleanup <- mkMethod0 "s2n_cleanup" Optional c_wrap_cleanup+    s2n_cleanup_final <- mkMethod0 "s2n_cleanup_final" Optional c_wrap_cleanup_final+    s2n_crypto_disable_init <- mkMethod0 "s2n_crypto_disable_init" Optional c_wrap_crypto_disable_init+    s2n_disable_atexit <- mkMethod0 "s2n_disable_atexit" Optional c_wrap_disable_atexit+    s2n_get_openssl_version <- mkMethod0Direct "s2n_get_openssl_version" Mandatory mk_s2n_get_openssl_version+    s2n_get_fips_mode <- mkMethod1 "s2n_get_fips_mode" Optional c_wrap_get_fips_mode++    -- Error Handling (load function pointers and wrap directly)+    s2n_errno_location <- mkMethod0Direct "s2n_errno_location" Mandatory mk_s2n_errno_location+    s2n_strerror <- mkMethod2Direct "s2n_strerror" Mandatory mk_s2n_strerror+    s2n_strerror_debug <- mkMethod2Direct "s2n_strerror_debug" Mandatory mk_s2n_strerror_debug+    s2n_strerror_source <- mkMethod1Direct "s2n_strerror_source" Mandatory mk_s2n_strerror_source+    s2n_error_get_type <- mkMethod1Direct "s2n_error_get_type" Mandatory mk_s2n_error_get_type+    s2n_strerror_name <- mkMethod1Direct "s2n_strerror_name" Mandatory mk_s2n_strerror_name++    -- Stack Traces+    s2n_stack_traces_enabled <- mkMethod0Direct "s2n_stack_traces_enabled" Optional mk_s2n_stack_traces_enabled+    s2n_stack_traces_enabled_set <- mkMethod1 "s2n_stack_traces_enabled_set" Optional c_wrap_stack_traces_enabled_set+    s2n_calculate_stacktrace <- mkMethod0 "s2n_calculate_stacktrace" Optional c_wrap_calculate_stacktrace+    s2n_free_stacktrace <- mkMethod0 "s2n_free_stacktrace" Optional c_wrap_free_stacktrace+    s2n_get_stacktrace <- mkMethod1 "s2n_get_stacktrace" Optional c_wrap_get_stacktrace++    -- Config Management+    s2n_config_new <- mkMethod0 "s2n_config_new" Optional c_wrap_config_new+    s2n_config_new_minimal <- mkMethod0 "s2n_config_new_minimal" Optional c_wrap_config_new_minimal+    s2n_config_free <- mkMethod1 "s2n_config_free" Optional c_wrap_config_free+    s2n_config_free_dhparams <- mkMethod1 "s2n_config_free_dhparams" Optional c_wrap_config_free_dhparams+    s2n_config_free_cert_chain_and_key <- mkMethod1 "s2n_config_free_cert_chain_and_key" Optional c_wrap_config_free_cert_chain_and_key+    s2n_config_set_wall_clock <- mkMethod3 "s2n_config_set_wall_clock" Optional c_wrap_config_set_wall_clock+    s2n_config_set_monotonic_clock <- mkMethod3 "s2n_config_set_monotonic_clock" Optional c_wrap_config_set_monotonic_clock+    -- Cache Callbacks+    s2n_config_set_cache_store_callback <- mkMethod3 "s2n_config_set_cache_store_callback" Optional c_wrap_config_set_cache_store_callback+    s2n_config_set_cache_retrieve_callback <- mkMethod3 "s2n_config_set_cache_retrieve_callback" Optional c_wrap_config_set_cache_retrieve_callback+    s2n_config_set_cache_delete_callback <- mkMethod3 "s2n_config_set_cache_delete_callback" Optional c_wrap_config_set_cache_delete_callback+    -- Memory & Random Callbacks+    s2n_mem_set_callbacks <- mkMethod4 "s2n_mem_set_callbacks" Optional c_wrap_mem_set_callbacks+    s2n_rand_set_callbacks <- mkMethod4 "s2n_rand_set_callbacks" Optional c_wrap_rand_set_callbacks++    -- Certificate Chain Management+    s2n_cert_chain_and_key_new <- mkMethod0 "s2n_cert_chain_and_key_new" Optional c_wrap_cert_chain_and_key_new+    s2n_cert_chain_and_key_load_pem <- mkMethod3 "s2n_cert_chain_and_key_load_pem" Optional c_wrap_cert_chain_and_key_load_pem+    s2n_cert_chain_and_key_load_pem_bytes <- mkMethod5 "s2n_cert_chain_and_key_load_pem_bytes" Optional c_wrap_cert_chain_and_key_load_pem_bytes+    s2n_cert_chain_and_key_load_public_pem_bytes <- mkMethod3 "s2n_cert_chain_and_key_load_public_pem_bytes" Optional c_wrap_cert_chain_and_key_load_public_pem_bytes+    s2n_cert_chain_and_key_free <- mkMethod1 "s2n_cert_chain_and_key_free" Optional c_wrap_cert_chain_and_key_free+    s2n_cert_chain_and_key_set_ctx <- mkMethod2 "s2n_cert_chain_and_key_set_ctx" Optional c_wrap_cert_chain_and_key_set_ctx+    s2n_cert_chain_and_key_get_ctx <- mkMethod1Direct "s2n_cert_chain_and_key_get_ctx" Mandatory mk_s2n_cert_chain_and_key_get_ctx+    s2n_cert_chain_and_key_get_private_key <- mkMethod1 "s2n_cert_chain_and_key_get_private_key" Optional c_wrap_cert_chain_and_key_get_private_key+    s2n_cert_chain_and_key_set_ocsp_data <- mkMethod3 "s2n_cert_chain_and_key_set_ocsp_data" Optional c_wrap_cert_chain_and_key_set_ocsp_data+    s2n_cert_chain_and_key_set_sct_list <- mkMethod3 "s2n_cert_chain_and_key_set_sct_list" Optional c_wrap_cert_chain_and_key_set_sct_list+    s2n_config_set_cert_tiebreak_callback <- mkMethod2 "s2n_config_set_cert_tiebreak_callback" Optional c_wrap_config_set_cert_tiebreak_callback+    s2n_config_add_cert_chain_and_key <- mkMethod3 "s2n_config_add_cert_chain_and_key" Optional c_wrap_config_add_cert_chain_and_key+    s2n_config_add_cert_chain_and_key_to_store <- mkMethod2 "s2n_config_add_cert_chain_and_key_to_store" Optional c_wrap_config_add_cert_chain_and_key_to_store+    s2n_config_set_cert_chain_and_key_defaults <- mkMethod3 "s2n_config_set_cert_chain_and_key_defaults" Optional c_wrap_config_set_cert_chain_and_key_defaults++    -- Trust Store+    s2n_config_set_verification_ca_location <- mkMethod3 "s2n_config_set_verification_ca_location" Optional c_wrap_config_set_verification_ca_location+    s2n_config_add_pem_to_trust_store <- mkMethod2 "s2n_config_add_pem_to_trust_store" Optional c_wrap_config_add_pem_to_trust_store+    s2n_config_wipe_trust_store <- mkMethod1 "s2n_config_wipe_trust_store" Optional c_wrap_config_wipe_trust_store+    s2n_config_load_system_certs <- mkMethod1 "s2n_config_load_system_certs" Optional c_wrap_config_load_system_certs+    s2n_config_set_cert_authorities_from_trust_store <- mkMethod1 "s2n_config_set_cert_authorities_from_trust_store" Optional c_wrap_config_set_cert_authorities_from_trust_store++    -- Verification & Validation+    s2n_config_set_verify_after_sign <- mkMethod2 "s2n_config_set_verify_after_sign" Optional c_wrap_config_set_verify_after_sign+    s2n_config_set_check_stapled_ocsp_response <- mkMethod2 "s2n_config_set_check_stapled_ocsp_response" Optional c_wrap_config_set_check_stapled_ocsp_response+    s2n_config_disable_x509_time_verification <- mkMethod1 "s2n_config_disable_x509_time_verification" Optional c_wrap_config_disable_x509_time_verification+    s2n_config_disable_x509_verification <- mkMethod1 "s2n_config_disable_x509_verification" Optional c_wrap_config_disable_x509_verification+    s2n_config_set_max_cert_chain_depth <- mkMethod2 "s2n_config_set_max_cert_chain_depth" Optional c_wrap_config_set_max_cert_chain_depth+    s2n_config_set_verify_host_callback <- mkMethod3 "s2n_config_set_verify_host_callback" Optional c_wrap_config_set_verify_host_callback++    -- DH Parameters+    s2n_config_add_dhparams <- mkMethod2 "s2n_config_add_dhparams" Optional c_wrap_config_add_dhparams++    -- Security Policies & Preferences+    s2n_config_set_cipher_preferences <- mkMethod2 "s2n_config_set_cipher_preferences" Optional c_wrap_config_set_cipher_preferences+    s2n_config_append_protocol_preference <- mkMethod3 "s2n_config_append_protocol_preference" Optional c_wrap_config_append_protocol_preference+    s2n_config_set_protocol_preferences <- mkMethod3 "s2n_config_set_protocol_preferences" Optional c_wrap_config_set_protocol_preferences+    s2n_config_set_status_request_type <- mkMethod2 "s2n_config_set_status_request_type" Optional c_wrap_config_set_status_request_type+    s2n_config_set_ct_support_level <- mkMethod2 "s2n_config_set_ct_support_level" Optional c_wrap_config_set_ct_support_level+    s2n_config_set_alert_behavior <- mkMethod2 "s2n_config_set_alert_behavior" Optional c_wrap_config_set_alert_behavior++    -- Extension Data+    s2n_config_set_extension_data <- mkMethod4 "s2n_config_set_extension_data" Optional c_wrap_config_set_extension_data+    s2n_config_send_max_fragment_length <- mkMethod2 "s2n_config_send_max_fragment_length" Optional c_wrap_config_send_max_fragment_length+    s2n_config_accept_max_fragment_length <- mkMethod1 "s2n_config_accept_max_fragment_length" Optional c_wrap_config_accept_max_fragment_length++    -- Session & Ticket Configuration+    s2n_config_set_session_state_lifetime <- mkMethod2 "s2n_config_set_session_state_lifetime" Optional c_wrap_config_set_session_state_lifetime+    s2n_config_set_session_tickets_onoff <- mkMethod2 "s2n_config_set_session_tickets_onoff" Optional c_wrap_config_set_session_tickets_onoff+    s2n_config_set_session_cache_onoff <- mkMethod2 "s2n_config_set_session_cache_onoff" Optional c_wrap_config_set_session_cache_onoff+    s2n_config_set_ticket_encrypt_decrypt_key_lifetime <- mkMethod2 "s2n_config_set_ticket_encrypt_decrypt_key_lifetime" Optional c_wrap_config_set_ticket_encrypt_decrypt_key_lifetime+    s2n_config_set_ticket_decrypt_key_lifetime <- mkMethod2 "s2n_config_set_ticket_decrypt_key_lifetime" Optional c_wrap_config_set_ticket_decrypt_key_lifetime+    s2n_config_add_ticket_crypto_key <- mkMethod6 "s2n_config_add_ticket_crypto_key" Optional c_wrap_config_add_ticket_crypto_key+    s2n_config_require_ticket_forward_secrecy <- mkMethod2 "s2n_config_require_ticket_forward_secrecy" Optional c_wrap_config_require_ticket_forward_secrecy+    -- Buffer & I/O Configuration+    s2n_config_set_send_buffer_size <- mkMethod2 "s2n_config_set_send_buffer_size" Optional c_wrap_config_set_send_buffer_size+    s2n_config_set_recv_multi_record <- mkMethod2 "s2n_config_set_recv_multi_record" Optional c_wrap_config_set_recv_multi_record++    -- Miscellaneous Config+    s2n_config_set_ctx <- mkMethod2 "s2n_config_set_ctx" Optional c_wrap_config_set_ctx+    s2n_config_get_ctx <- mkMethod2 "s2n_config_get_ctx" Optional c_wrap_config_get_ctx+    s2n_config_set_client_hello_cb <- mkMethod3 "s2n_config_set_client_hello_cb" Optional c_wrap_config_set_client_hello_cb+    s2n_config_set_client_hello_cb_mode <- mkMethod2 "s2n_config_set_client_hello_cb_mode" Optional c_wrap_config_set_client_hello_cb_mode+    s2n_config_set_max_blinding_delay <- mkMethod2 "s2n_config_set_max_blinding_delay" Optional c_wrap_config_set_max_blinding_delay+    s2n_config_get_client_auth_type <- mkMethod2 "s2n_config_get_client_auth_type" Optional c_wrap_config_get_client_auth_type+    s2n_config_set_client_auth_type <- mkMethod2 "s2n_config_set_client_auth_type" Optional c_wrap_config_set_client_auth_type+    s2n_config_set_initial_ticket_count <- mkMethod2 "s2n_config_set_initial_ticket_count" Optional c_wrap_config_set_initial_ticket_count+    s2n_config_set_psk_mode <- mkMethod2 "s2n_config_set_psk_mode" Optional c_wrap_config_set_psk_mode+    s2n_config_set_psk_selection_callback <- mkMethod3 "s2n_config_set_psk_selection_callback" Optional c_wrap_config_set_psk_selection_callback+    s2n_config_set_async_pkey_callback <- mkMethod2 "s2n_config_set_async_pkey_callback" Optional c_wrap_config_set_async_pkey_callback+    s2n_config_set_async_pkey_validation_mode <- mkMethod2 "s2n_config_set_async_pkey_validation_mode" Optional c_wrap_config_set_async_pkey_validation_mode+    s2n_config_set_session_ticket_cb <- mkMethod3 "s2n_config_set_session_ticket_cb" Optional c_wrap_config_set_session_ticket_cb+    s2n_config_set_key_log_cb <- mkMethod3 "s2n_config_set_key_log_cb" Optional c_wrap_config_set_key_log_cb+    s2n_config_enable_cert_req_dss_legacy_compat <- mkMethod1 "s2n_config_enable_cert_req_dss_legacy_compat" Optional c_wrap_config_enable_cert_req_dss_legacy_compat+    s2n_config_set_server_max_early_data_size <- mkMethod2 "s2n_config_set_server_max_early_data_size" Optional c_wrap_config_set_server_max_early_data_size+    s2n_config_set_early_data_cb <- mkMethod2 "s2n_config_set_early_data_cb" Optional c_wrap_config_set_early_data_cb+    s2n_config_get_supported_groups <- mkMethod4 "s2n_config_get_supported_groups" Optional c_wrap_config_get_supported_groups+    s2n_config_set_serialization_version <- mkMethod2 "s2n_config_set_serialization_version" Optional c_wrap_config_set_serialization_version++    -- Connection Creation & Management+    s2n_connection_new <- mkMethod1 "s2n_connection_new" Optional c_wrap_connection_new+    s2n_connection_set_config <- mkMethod2 "s2n_connection_set_config" Optional c_wrap_connection_set_config+    s2n_connection_set_ctx <- mkMethod2 "s2n_connection_set_ctx" Optional c_wrap_connection_set_ctx+    s2n_connection_get_ctx <- mkMethod1 "s2n_connection_get_ctx" Optional c_wrap_connection_get_ctx+    s2n_client_hello_cb_done <- mkMethod1 "s2n_client_hello_cb_done" Optional c_wrap_client_hello_cb_done+    s2n_connection_server_name_extension_used <- mkMethod1 "s2n_connection_server_name_extension_used" Optional c_wrap_connection_server_name_extension_used++    -- Client Hello Access+    s2n_connection_get_client_hello <- mkMethod1 "s2n_connection_get_client_hello" Optional c_wrap_connection_get_client_hello+    s2n_client_hello_parse_message <- mkMethod2 "s2n_client_hello_parse_message" Optional c_wrap_client_hello_parse_message+    s2n_client_hello_free <- mkMethod1 "s2n_client_hello_free" Optional c_wrap_client_hello_free+    s2n_client_hello_get_raw_message_length <- mkMethod1 "s2n_client_hello_get_raw_message_length" Optional c_wrap_client_hello_get_raw_message_length+    s2n_client_hello_get_raw_message <- mkMethod3 "s2n_client_hello_get_raw_message" Optional c_wrap_client_hello_get_raw_message+    s2n_client_hello_get_cipher_suites_length <- mkMethod1 "s2n_client_hello_get_cipher_suites_length" Optional c_wrap_client_hello_get_cipher_suites_length+    s2n_client_hello_get_cipher_suites <- mkMethod3 "s2n_client_hello_get_cipher_suites" Optional c_wrap_client_hello_get_cipher_suites+    s2n_client_hello_get_extensions_length <- mkMethod1 "s2n_client_hello_get_extensions_length" Optional c_wrap_client_hello_get_extensions_length+    s2n_client_hello_get_extensions <- mkMethod3 "s2n_client_hello_get_extensions" Optional c_wrap_client_hello_get_extensions+    s2n_client_hello_get_extension_length <- mkMethod2 "s2n_client_hello_get_extension_length" Optional c_wrap_client_hello_get_extension_length+    s2n_client_hello_get_extension_by_id <- mkMethod4 "s2n_client_hello_get_extension_by_id" Optional c_wrap_client_hello_get_extension_by_id+    s2n_client_hello_has_extension <- mkMethod3 "s2n_client_hello_has_extension" Optional c_wrap_client_hello_has_extension+    s2n_client_hello_get_session_id_length <- mkMethod2 "s2n_client_hello_get_session_id_length" Optional c_wrap_client_hello_get_session_id_length+    s2n_client_hello_get_session_id <- mkMethod4 "s2n_client_hello_get_session_id" Optional c_wrap_client_hello_get_session_id+    s2n_client_hello_get_compression_methods_length <- mkMethod2 "s2n_client_hello_get_compression_methods_length" Optional c_wrap_client_hello_get_compression_methods_length+    s2n_client_hello_get_compression_methods <- mkMethod4 "s2n_client_hello_get_compression_methods" Optional c_wrap_client_hello_get_compression_methods+    s2n_client_hello_get_legacy_protocol_version <- mkMethod2 "s2n_client_hello_get_legacy_protocol_version" Optional c_wrap_client_hello_get_legacy_protocol_version+    s2n_client_hello_get_supported_groups <- mkMethod4 "s2n_client_hello_get_supported_groups" Optional c_wrap_client_hello_get_supported_groups+    s2n_client_hello_get_server_name_length <- mkMethod2 "s2n_client_hello_get_server_name_length" Optional c_wrap_client_hello_get_server_name_length+    s2n_client_hello_get_server_name <- mkMethod4 "s2n_client_hello_get_server_name" Optional c_wrap_client_hello_get_server_name+    s2n_client_hello_get_legacy_record_version <- mkMethod2 "s2n_client_hello_get_legacy_record_version" Optional c_wrap_client_hello_get_legacy_record_version++    -- File Descriptor & I/O+    s2n_connection_set_fd <- mkMethod2 "s2n_connection_set_fd" Optional c_wrap_connection_set_fd+    s2n_connection_set_read_fd <- mkMethod2 "s2n_connection_set_read_fd" Optional c_wrap_connection_set_read_fd+    s2n_connection_set_write_fd <- mkMethod2 "s2n_connection_set_write_fd" Optional c_wrap_connection_set_write_fd+    s2n_connection_get_read_fd <- mkMethod2 "s2n_connection_get_read_fd" Optional c_wrap_connection_get_read_fd+    s2n_connection_get_write_fd <- mkMethod2 "s2n_connection_get_write_fd" Optional c_wrap_connection_get_write_fd+    s2n_connection_use_corked_io <- mkMethod1 "s2n_connection_use_corked_io" Optional c_wrap_connection_use_corked_io+    s2n_connection_set_recv_ctx <- mkMethod2 "s2n_connection_set_recv_ctx" Optional c_wrap_connection_set_recv_ctx+    s2n_connection_set_send_ctx <- mkMethod2 "s2n_connection_set_send_ctx" Optional c_wrap_connection_set_send_ctx+    s2n_connection_set_recv_cb <- mkMethod2 "s2n_connection_set_recv_cb" Optional c_wrap_connection_set_recv_cb+    s2n_connection_set_send_cb <- mkMethod2 "s2n_connection_set_send_cb" Optional c_wrap_connection_set_send_cb+    -- Connection Preferences+    s2n_connection_prefer_throughput <- mkMethod1 "s2n_connection_prefer_throughput" Optional c_wrap_connection_prefer_throughput+    s2n_connection_prefer_low_latency <- mkMethod1 "s2n_connection_prefer_low_latency" Optional c_wrap_connection_prefer_low_latency+    s2n_connection_set_recv_buffering <- mkMethod2 "s2n_connection_set_recv_buffering" Optional c_wrap_connection_set_recv_buffering+    s2n_peek_buffered <- mkMethod1Direct "s2n_peek_buffered" Optional mk_s2n_peek_buffered+    s2n_connection_set_dynamic_buffers <- mkMethod2 "s2n_connection_set_dynamic_buffers" Optional c_wrap_connection_set_dynamic_buffers+    s2n_connection_set_dynamic_record_threshold <- mkMethod3 "s2n_connection_set_dynamic_record_threshold" Optional c_wrap_connection_set_dynamic_record_threshold++    -- Host Verification+    s2n_connection_set_verify_host_callback <- mkMethod3 "s2n_connection_set_verify_host_callback" Optional c_wrap_connection_set_verify_host_callback+    -- Blinding & Security+    s2n_connection_set_blinding <- mkMethod2 "s2n_connection_set_blinding" Optional c_wrap_connection_set_blinding+    s2n_connection_get_delay <- mkMethod1Direct "s2n_connection_get_delay" Optional mk_s2n_connection_get_delay+    -- Cipher & Protocol Configuration+    s2n_connection_set_cipher_preferences <- mkMethod2 "s2n_connection_set_cipher_preferences" Optional c_wrap_connection_set_cipher_preferences+    s2n_connection_request_key_update <- mkMethod2 "s2n_connection_request_key_update" Optional c_wrap_connection_request_key_update+    s2n_connection_append_protocol_preference <- mkMethod3 "s2n_connection_append_protocol_preference" Optional c_wrap_connection_append_protocol_preference+    s2n_connection_set_protocol_preferences <- mkMethod3 "s2n_connection_set_protocol_preferences" Optional c_wrap_connection_set_protocol_preferences+    -- Server Name (SNI)+    s2n_set_server_name <- mkMethod2 "s2n_set_server_name" Optional c_wrap_set_server_name+    s2n_get_server_name <- mkMethod1 "s2n_get_server_name" Optional c_wrap_get_server_name+    -- Application Protocol (ALPN)+    s2n_get_application_protocol <- mkMethod1 "s2n_get_application_protocol" Optional c_wrap_get_application_protocol+    -- OCSP & Certificate Transparency+    s2n_connection_get_ocsp_response <- mkMethod2 "s2n_connection_get_ocsp_response" Optional c_wrap_connection_get_ocsp_response+    s2n_connection_get_sct_list <- mkMethod2 "s2n_connection_get_sct_list" Optional c_wrap_connection_get_sct_list+    -- Handshake & TLS Operations+    s2n_negotiate <- mkMethod2 "s2n_negotiate" Optional c_wrap_negotiate+    s2n_send <- mkMethod4 "s2n_send" Optional c_wrap_send+    s2n_recv <- mkMethod4 "s2n_recv" Optional c_wrap_recv+    s2n_peek <- mkMethod1Direct "s2n_peek" Optional mk_s2n_peek+    s2n_connection_free_handshake <- mkMethod1 "s2n_connection_free_handshake" Optional c_wrap_connection_free_handshake+    s2n_connection_release_buffers <- mkMethod1 "s2n_connection_release_buffers" Optional c_wrap_connection_release_buffers+    s2n_connection_wipe <- mkMethod1 "s2n_connection_wipe" Optional c_wrap_connection_wipe+    s2n_connection_free <- mkMethod1 "s2n_connection_free" Optional c_wrap_connection_free+    s2n_shutdown <- mkMethod2 "s2n_shutdown" Optional c_wrap_shutdown+    s2n_shutdown_send <- mkMethod2 "s2n_shutdown_send" Optional c_wrap_shutdown_send+    -- Client Authentication+    s2n_connection_get_client_auth_type <- mkMethod2 "s2n_connection_get_client_auth_type" Optional c_wrap_connection_get_client_auth_type+    s2n_connection_set_client_auth_type <- mkMethod2 "s2n_connection_set_client_auth_type" Optional c_wrap_connection_set_client_auth_type+    s2n_connection_get_client_cert_chain <- mkMethod3 "s2n_connection_get_client_cert_chain" Optional c_wrap_connection_get_client_cert_chain+    s2n_connection_client_cert_used <- mkMethod1 "s2n_connection_client_cert_used" Optional c_wrap_connection_client_cert_used+    -- Session Management+    s2n_connection_add_new_tickets_to_send <- mkMethod2 "s2n_connection_add_new_tickets_to_send" Optional c_wrap_connection_add_new_tickets_to_send+    s2n_connection_get_tickets_sent <- mkMethod2 "s2n_connection_get_tickets_sent" Optional c_wrap_connection_get_tickets_sent+    s2n_connection_set_server_keying_material_lifetime <- mkMethod2 "s2n_connection_set_server_keying_material_lifetime" Optional c_wrap_connection_set_server_keying_material_lifetime+    s2n_session_ticket_get_data_len <- mkMethod2 "s2n_session_ticket_get_data_len" Optional c_wrap_session_ticket_get_data_len+    s2n_session_ticket_get_data <- mkMethod3 "s2n_session_ticket_get_data" Optional c_wrap_session_ticket_get_data+    s2n_session_ticket_get_lifetime <- mkMethod2 "s2n_session_ticket_get_lifetime" Optional c_wrap_session_ticket_get_lifetime+    s2n_connection_set_session <- mkMethod3 "s2n_connection_set_session" Optional c_wrap_connection_set_session+    s2n_connection_get_session <- mkMethod3 "s2n_connection_get_session" Optional c_wrap_connection_get_session+    s2n_connection_get_session_ticket_lifetime_hint <- mkMethod1 "s2n_connection_get_session_ticket_lifetime_hint" Optional c_wrap_connection_get_session_ticket_lifetime_hint+    s2n_connection_get_session_length <- mkMethod1 "s2n_connection_get_session_length" Optional c_wrap_connection_get_session_length+    s2n_connection_get_session_id_length <- mkMethod1 "s2n_connection_get_session_id_length" Optional c_wrap_connection_get_session_id_length+    s2n_connection_get_session_id <- mkMethod3 "s2n_connection_get_session_id" Optional c_wrap_connection_get_session_id+    s2n_connection_is_session_resumed <- mkMethod1 "s2n_connection_is_session_resumed" Optional c_wrap_connection_is_session_resumed+    -- Certificate Information+    s2n_connection_is_ocsp_stapled <- mkMethod1 "s2n_connection_is_ocsp_stapled" Optional c_wrap_connection_is_ocsp_stapled+    s2n_connection_get_selected_signature_algorithm <- mkMethod2 "s2n_connection_get_selected_signature_algorithm" Optional c_wrap_connection_get_selected_signature_algorithm+    s2n_connection_get_selected_digest_algorithm <- mkMethod2 "s2n_connection_get_selected_digest_algorithm" Optional c_wrap_connection_get_selected_digest_algorithm+    s2n_connection_get_selected_client_cert_signature_algorithm <- mkMethod2 "s2n_connection_get_selected_client_cert_signature_algorithm" Optional c_wrap_connection_get_selected_client_cert_signature_algorithm+    s2n_connection_get_selected_client_cert_digest_algorithm <- mkMethod2 "s2n_connection_get_selected_client_cert_digest_algorithm" Optional c_wrap_connection_get_selected_client_cert_digest_algorithm+    s2n_connection_get_selected_cert <- mkMethod1 "s2n_connection_get_selected_cert" Optional c_wrap_connection_get_selected_cert+    s2n_cert_chain_get_length <- mkMethod2 "s2n_cert_chain_get_length" Optional c_wrap_cert_chain_get_length+    s2n_cert_chain_get_cert <- mkMethod3 "s2n_cert_chain_get_cert" Optional c_wrap_cert_chain_get_cert+    s2n_cert_get_der <- mkMethod3 "s2n_cert_get_der" Optional c_wrap_cert_get_der+    s2n_connection_get_peer_cert_chain <- mkMethod2 "s2n_connection_get_peer_cert_chain" Optional c_wrap_connection_get_peer_cert_chain+    s2n_cert_get_x509_extension_value_length <- mkMethod3 "s2n_cert_get_x509_extension_value_length" Optional c_wrap_cert_get_x509_extension_value_length+    s2n_cert_get_x509_extension_value <- mkMethod5 "s2n_cert_get_x509_extension_value" Optional c_wrap_cert_get_x509_extension_value+    s2n_cert_get_utf8_string_from_extension_data_length <- mkMethod3 "s2n_cert_get_utf8_string_from_extension_data_length" Optional c_wrap_cert_get_utf8_string_from_extension_data_length+    s2n_cert_get_utf8_string_from_extension_data <- mkMethod4 "s2n_cert_get_utf8_string_from_extension_data" Optional c_wrap_cert_get_utf8_string_from_extension_data+    -- Pre-Shared Keys (PSK)+    s2n_external_psk_new <- mkMethod0 "s2n_external_psk_new" Optional c_wrap_external_psk_new+    s2n_psk_free <- mkMethod1 "s2n_psk_free" Optional c_wrap_psk_free+    s2n_psk_set_identity <- mkMethod3 "s2n_psk_set_identity" Optional c_wrap_psk_set_identity+    s2n_psk_set_secret <- mkMethod3 "s2n_psk_set_secret" Optional c_wrap_psk_set_secret+    s2n_psk_set_hmac <- mkMethod2 "s2n_psk_set_hmac" Optional c_wrap_psk_set_hmac+    s2n_connection_append_psk <- mkMethod2 "s2n_connection_append_psk" Optional c_wrap_connection_append_psk+    s2n_connection_set_psk_mode <- mkMethod2 "s2n_connection_set_psk_mode" Optional c_wrap_connection_set_psk_mode+    s2n_connection_get_negotiated_psk_identity_length <- mkMethod2 "s2n_connection_get_negotiated_psk_identity_length" Optional c_wrap_connection_get_negotiated_psk_identity_length+    s2n_connection_get_negotiated_psk_identity <- mkMethod3 "s2n_connection_get_negotiated_psk_identity" Optional c_wrap_connection_get_negotiated_psk_identity+    s2n_offered_psk_new <- mkMethod0 "s2n_offered_psk_new" Optional c_wrap_offered_psk_new+    s2n_offered_psk_free <- mkMethod1 "s2n_offered_psk_free" Optional c_wrap_offered_psk_free+    s2n_offered_psk_get_identity <- mkMethod3 "s2n_offered_psk_get_identity" Optional c_wrap_offered_psk_get_identity+    s2n_offered_psk_list_has_next <- mkMethod1Direct "s2n_offered_psk_list_has_next" Optional mk_s2n_offered_psk_list_has_next+    s2n_offered_psk_list_next <- mkMethod2 "s2n_offered_psk_list_next" Optional c_wrap_offered_psk_list_next+    s2n_offered_psk_list_reread <- mkMethod1 "s2n_offered_psk_list_reread" Optional c_wrap_offered_psk_list_reread+    s2n_offered_psk_list_choose_psk <- mkMethod2 "s2n_offered_psk_list_choose_psk" Optional c_wrap_offered_psk_list_choose_psk+    s2n_psk_configure_early_data <- mkMethod4 "s2n_psk_configure_early_data" Optional c_wrap_psk_configure_early_data+    s2n_psk_set_application_protocol <- mkMethod3 "s2n_psk_set_application_protocol" Optional c_wrap_psk_set_application_protocol+    s2n_psk_set_early_data_context <- mkMethod3 "s2n_psk_set_early_data_context" Optional c_wrap_psk_set_early_data_context+    -- Connection Statistics+    s2n_connection_get_wire_bytes_in <- mkMethod1Direct "s2n_connection_get_wire_bytes_in" Optional mk_s2n_connection_get_wire_bytes_in+    s2n_connection_get_wire_bytes_out <- mkMethod1Direct "s2n_connection_get_wire_bytes_out" Optional mk_s2n_connection_get_wire_bytes_out+    -- Protocol Version Information+    s2n_connection_get_client_protocol_version <- mkMethod1 "s2n_connection_get_client_protocol_version" Optional c_wrap_connection_get_client_protocol_version+    s2n_connection_get_server_protocol_version <- mkMethod1 "s2n_connection_get_server_protocol_version" Optional c_wrap_connection_get_server_protocol_version+    s2n_connection_get_actual_protocol_version <- mkMethod1 "s2n_connection_get_actual_protocol_version" Optional c_wrap_connection_get_actual_protocol_version+    s2n_connection_get_client_hello_version <- mkMethod1 "s2n_connection_get_client_hello_version" Optional c_wrap_connection_get_client_hello_version+    -- Cipher & Security Information+    s2n_connection_get_cipher <- mkMethod1 "s2n_connection_get_cipher" Optional c_wrap_connection_get_cipher+    s2n_connection_get_certificate_match <- mkMethod2 "s2n_connection_get_certificate_match" Optional c_wrap_connection_get_certificate_match+    s2n_connection_get_master_secret <- mkMethod3 "s2n_connection_get_master_secret" Optional c_wrap_connection_get_master_secret+    s2n_connection_tls_exporter <- mkMethod7 "s2n_connection_tls_exporter" Optional c_wrap_connection_tls_exporter+    s2n_connection_get_cipher_iana_value <- mkMethod3 "s2n_connection_get_cipher_iana_value" Optional c_wrap_connection_get_cipher_iana_value+    s2n_connection_is_valid_for_cipher_preferences <- mkMethod2 "s2n_connection_is_valid_for_cipher_preferences" Optional c_wrap_connection_is_valid_for_cipher_preferences+    s2n_connection_get_curve <- mkMethod1 "s2n_connection_get_curve" Optional c_wrap_connection_get_curve+    s2n_connection_get_kem_name <- mkMethod1 "s2n_connection_get_kem_name" Optional c_wrap_connection_get_kem_name+    s2n_connection_get_kem_group_name <- mkMethod1 "s2n_connection_get_kem_group_name" Optional c_wrap_connection_get_kem_group_name+    s2n_connection_get_key_exchange_group <- mkMethod2 "s2n_connection_get_key_exchange_group" Optional c_wrap_connection_get_key_exchange_group+    s2n_connection_get_alert <- mkMethod1 "s2n_connection_get_alert" Optional c_wrap_connection_get_alert+    s2n_connection_get_handshake_type_name <- mkMethod1 "s2n_connection_get_handshake_type_name" Optional c_wrap_connection_get_handshake_type_name+    s2n_connection_get_last_message_name <- mkMethod1 "s2n_connection_get_last_message_name" Optional c_wrap_connection_get_last_message_name+    -- Async Private Key Operations+    s2n_async_pkey_op_perform <- mkMethod2 "s2n_async_pkey_op_perform" Optional c_wrap_async_pkey_op_perform+    s2n_async_pkey_op_apply <- mkMethod2 "s2n_async_pkey_op_apply" Optional c_wrap_async_pkey_op_apply+    s2n_async_pkey_op_free <- mkMethod1 "s2n_async_pkey_op_free" Optional c_wrap_async_pkey_op_free+    s2n_async_pkey_op_get_op_type <- mkMethod2 "s2n_async_pkey_op_get_op_type" Optional c_wrap_async_pkey_op_get_op_type+    s2n_async_pkey_op_get_input_size <- mkMethod2 "s2n_async_pkey_op_get_input_size" Optional c_wrap_async_pkey_op_get_input_size+    s2n_async_pkey_op_get_input <- mkMethod3 "s2n_async_pkey_op_get_input" Optional c_wrap_async_pkey_op_get_input+    s2n_async_pkey_op_set_output <- mkMethod3 "s2n_async_pkey_op_set_output" Optional c_wrap_async_pkey_op_set_output+    -- Early Data+    s2n_connection_set_server_max_early_data_size <- mkMethod2 "s2n_connection_set_server_max_early_data_size" Optional c_wrap_connection_set_server_max_early_data_size+    s2n_connection_set_server_early_data_context <- mkMethod3 "s2n_connection_set_server_early_data_context" Optional c_wrap_connection_set_server_early_data_context+    s2n_connection_get_early_data_status <- mkMethod2 "s2n_connection_get_early_data_status" Optional c_wrap_connection_get_early_data_status+    s2n_connection_get_remaining_early_data_size <- mkMethod2 "s2n_connection_get_remaining_early_data_size" Optional c_wrap_connection_get_remaining_early_data_size+    s2n_connection_get_max_early_data_size <- mkMethod2 "s2n_connection_get_max_early_data_size" Optional c_wrap_connection_get_max_early_data_size+    s2n_send_early_data <- mkMethod5 "s2n_send_early_data" Optional c_wrap_send_early_data+    s2n_recv_early_data <- mkMethod5 "s2n_recv_early_data" Optional c_wrap_recv_early_data+    s2n_offered_early_data_get_context_length <- mkMethod2 "s2n_offered_early_data_get_context_length" Optional c_wrap_offered_early_data_get_context_length+    s2n_offered_early_data_get_context <- mkMethod3 "s2n_offered_early_data_get_context" Optional c_wrap_offered_early_data_get_context+    s2n_offered_early_data_reject <- mkMethod1 "s2n_offered_early_data_reject" Optional c_wrap_offered_early_data_reject+    s2n_offered_early_data_accept <- mkMethod1 "s2n_offered_early_data_accept" Optional c_wrap_offered_early_data_accept+    -- Connection Serialization+    s2n_connection_serialization_length <- mkMethod2 "s2n_connection_serialization_length" Optional c_wrap_connection_serialization_length+    s2n_connection_serialize <- mkMethod3 "s2n_connection_serialize" Optional c_wrap_connection_serialize+    s2n_connection_deserialize <- mkMethod3 "s2n_connection_deserialize" Optional c_wrap_connection_deserialize++    missingSymbols <- readIORef missingRef+    pure (S2nTlsFfi{..}, missingSymbols)++-- Foreign imports for C wrappers and direct function pointers+-- These are defined in cbits/s2n_wrapper.c++foreign import ccall "dynamic" mk_s2n_errno_location :: FunPtr (IO (Ptr CInt)) -> IO (Ptr CInt)+foreign import ccall "dynamic" mk_s2n_strerror :: FunPtr (CInt -> CString -> IO CString) -> CInt -> CString -> IO CString+foreign import ccall "dynamic" mk_s2n_strerror_debug :: FunPtr (CInt -> CString -> IO CString) -> CInt -> CString -> IO CString+foreign import ccall "dynamic" mk_s2n_strerror_source :: FunPtr (CInt -> IO CString) -> CInt -> IO CString+foreign import ccall "dynamic" mk_s2n_strerror_name :: FunPtr (CInt -> IO CString) -> CInt -> IO CString+foreign import ccall "dynamic" mk_s2n_error_get_type :: FunPtr (CInt -> IO S2nErrorType) -> CInt -> IO S2nErrorType+foreign import ccall "dynamic" mk_s2n_get_openssl_version :: FunPtr (IO CLong) -> IO CLong+foreign import ccall "dynamic" mk_s2n_stack_traces_enabled :: FunPtr (IO CBool) -> IO CBool+foreign import ccall "dynamic" mk_s2n_peek :: FunPtr (Ptr S2nConnection -> IO Word32) -> Ptr S2nConnection -> IO Word32+foreign import ccall "dynamic" mk_s2n_peek_buffered :: FunPtr (Ptr S2nConnection -> IO Word32) -> Ptr S2nConnection -> IO Word32+foreign import ccall "dynamic" mk_s2n_connection_get_delay :: FunPtr (Ptr S2nConnection -> IO Word64) -> Ptr S2nConnection -> IO Word64+foreign import ccall "dynamic" mk_s2n_connection_get_wire_bytes_in :: FunPtr (Ptr S2nConnection -> IO Word64) -> Ptr S2nConnection -> IO Word64+foreign import ccall "dynamic" mk_s2n_connection_get_wire_bytes_out :: FunPtr (Ptr S2nConnection -> IO Word64) -> Ptr S2nConnection -> IO Word64+foreign import ccall "dynamic" mk_s2n_cert_chain_and_key_get_ctx :: FunPtr (Ptr S2nCertChainAndKey -> IO (Ptr ())) -> Ptr S2nCertChainAndKey -> IO (Ptr ())+foreign import ccall "dynamic" mk_s2n_offered_psk_list_has_next :: FunPtr (Ptr S2nOfferedPskList -> IO CBool) -> Ptr S2nOfferedPskList -> IO CBool++-- C wrapper imports+foreign import ccall safe "s2n_wrap_init" c_wrap_init :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cleanup" c_wrap_cleanup :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cleanup_final" c_wrap_cleanup_final :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_crypto_disable_init" c_wrap_crypto_disable_init :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_disable_atexit" c_wrap_disable_atexit :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_get_fips_mode" c_wrap_get_fips_mode :: FunPtr () -> Ptr S2nFipsMode -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_stack_traces_enabled_set" c_wrap_stack_traces_enabled_set :: FunPtr () -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_calculate_stacktrace" c_wrap_calculate_stacktrace :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_free_stacktrace" c_wrap_free_stacktrace :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_get_stacktrace" c_wrap_get_stacktrace :: FunPtr () -> Ptr S2nStacktrace -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_new" c_wrap_config_new :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nConfig)+foreign import ccall safe "s2n_wrap_config_new_minimal" c_wrap_config_new_minimal :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nConfig)+foreign import ccall safe "s2n_wrap_config_free" c_wrap_config_free :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_free_dhparams" c_wrap_config_free_dhparams :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_free_cert_chain_and_key" c_wrap_config_free_cert_chain_and_key :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_wall_clock" c_wrap_config_set_wall_clock :: FunPtr () -> Ptr S2nConfig -> S2nClockTimeNanoseconds -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_monotonic_clock" c_wrap_config_set_monotonic_clock :: FunPtr () -> Ptr S2nConfig -> S2nClockTimeNanoseconds -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cache_store_callback" c_wrap_config_set_cache_store_callback :: FunPtr () -> Ptr S2nConfig -> S2nCacheStoreCallback -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cache_retrieve_callback" c_wrap_config_set_cache_retrieve_callback :: FunPtr () -> Ptr S2nConfig -> S2nCacheRetrieveCallback -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cache_delete_callback" c_wrap_config_set_cache_delete_callback :: FunPtr () -> Ptr S2nConfig -> S2nCacheDeleteCallback -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_mem_set_callbacks" c_wrap_mem_set_callbacks :: FunPtr () -> S2nMemInitCallback -> S2nMemCleanupCallback -> S2nMemMallocCallback -> S2nMemFreeCallback -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_rand_set_callbacks" c_wrap_rand_set_callbacks :: FunPtr () -> S2nRandInitCallback -> S2nRandCleanupCallback -> S2nRandSeedCallback -> S2nRandMixCallback -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_new" c_wrap_cert_chain_and_key_new :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nCertChainAndKey)+foreign import ccall safe "s2n_wrap_cert_chain_and_key_load_pem" c_wrap_cert_chain_and_key_load_pem :: FunPtr () -> Ptr S2nCertChainAndKey -> CString -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_load_pem_bytes" c_wrap_cert_chain_and_key_load_pem_bytes :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_load_public_pem_bytes" c_wrap_cert_chain_and_key_load_public_pem_bytes :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_free" c_wrap_cert_chain_and_key_free :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_set_ctx" c_wrap_cert_chain_and_key_set_ctx :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_get_private_key" c_wrap_cert_chain_and_key_get_private_key :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nCertPrivateKey)+foreign import ccall safe "s2n_wrap_cert_chain_and_key_set_ocsp_data" c_wrap_cert_chain_and_key_set_ocsp_data :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_and_key_set_sct_list" c_wrap_cert_chain_and_key_set_sct_list :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cert_tiebreak_callback" c_wrap_config_set_cert_tiebreak_callback :: FunPtr () -> Ptr S2nConfig -> S2nCertTiebreakCallback -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_add_cert_chain_and_key" c_wrap_config_add_cert_chain_and_key :: FunPtr () -> Ptr S2nConfig -> CString -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_add_cert_chain_and_key_to_store" c_wrap_config_add_cert_chain_and_key_to_store :: FunPtr () -> Ptr S2nConfig -> Ptr S2nCertChainAndKey -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cert_chain_and_key_defaults" c_wrap_config_set_cert_chain_and_key_defaults :: FunPtr () -> Ptr S2nConfig -> Ptr (Ptr S2nCertChainAndKey) -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_verification_ca_location" c_wrap_config_set_verification_ca_location :: FunPtr () -> Ptr S2nConfig -> CString -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_add_pem_to_trust_store" c_wrap_config_add_pem_to_trust_store :: FunPtr () -> Ptr S2nConfig -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_wipe_trust_store" c_wrap_config_wipe_trust_store :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_load_system_certs" c_wrap_config_load_system_certs :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cert_authorities_from_trust_store" c_wrap_config_set_cert_authorities_from_trust_store :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_verify_after_sign" c_wrap_config_set_verify_after_sign :: FunPtr () -> Ptr S2nConfig -> S2nVerifyAfterSign -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_check_stapled_ocsp_response" c_wrap_config_set_check_stapled_ocsp_response :: FunPtr () -> Ptr S2nConfig -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_disable_x509_time_verification" c_wrap_config_disable_x509_time_verification :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_disable_x509_verification" c_wrap_config_disable_x509_verification :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_max_cert_chain_depth" c_wrap_config_set_max_cert_chain_depth :: FunPtr () -> Ptr S2nConfig -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_verify_host_callback" c_wrap_config_set_verify_host_callback :: FunPtr () -> Ptr S2nConfig -> S2nVerifyHostFn -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_add_dhparams" c_wrap_config_add_dhparams :: FunPtr () -> Ptr S2nConfig -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_cipher_preferences" c_wrap_config_set_cipher_preferences :: FunPtr () -> Ptr S2nConfig -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_append_protocol_preference" c_wrap_config_append_protocol_preference :: FunPtr () -> Ptr S2nConfig -> Ptr Word8 -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_protocol_preferences" c_wrap_config_set_protocol_preferences :: FunPtr () -> Ptr S2nConfig -> Ptr CString -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_status_request_type" c_wrap_config_set_status_request_type :: FunPtr () -> Ptr S2nConfig -> S2nStatusRequestType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_ct_support_level" c_wrap_config_set_ct_support_level :: FunPtr () -> Ptr S2nConfig -> S2nCtSupportLevel -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_alert_behavior" c_wrap_config_set_alert_behavior :: FunPtr () -> Ptr S2nConfig -> S2nAlertBehavior -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_extension_data" c_wrap_config_set_extension_data :: FunPtr () -> Ptr S2nConfig -> S2nTlsExtensionType -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_send_max_fragment_length" c_wrap_config_send_max_fragment_length :: FunPtr () -> Ptr S2nConfig -> S2nMaxFragLen -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_accept_max_fragment_length" c_wrap_config_accept_max_fragment_length :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_session_state_lifetime" c_wrap_config_set_session_state_lifetime :: FunPtr () -> Ptr S2nConfig -> Word64 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_session_tickets_onoff" c_wrap_config_set_session_tickets_onoff :: FunPtr () -> Ptr S2nConfig -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_session_cache_onoff" c_wrap_config_set_session_cache_onoff :: FunPtr () -> Ptr S2nConfig -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_ticket_encrypt_decrypt_key_lifetime" c_wrap_config_set_ticket_encrypt_decrypt_key_lifetime :: FunPtr () -> Ptr S2nConfig -> Word64 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_ticket_decrypt_key_lifetime" c_wrap_config_set_ticket_decrypt_key_lifetime :: FunPtr () -> Ptr S2nConfig -> Word64 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_add_ticket_crypto_key" c_wrap_config_add_ticket_crypto_key :: FunPtr () -> Ptr S2nConfig -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Word64 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_require_ticket_forward_secrecy" c_wrap_config_require_ticket_forward_secrecy :: FunPtr () -> Ptr S2nConfig -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_send_buffer_size" c_wrap_config_set_send_buffer_size :: FunPtr () -> Ptr S2nConfig -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_recv_multi_record" c_wrap_config_set_recv_multi_record :: FunPtr () -> Ptr S2nConfig -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_ctx" c_wrap_config_set_ctx :: FunPtr () -> Ptr S2nConfig -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_get_ctx" c_wrap_config_get_ctx :: FunPtr () -> Ptr S2nConfig -> Ptr (Ptr ()) -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_client_hello_cb" c_wrap_config_set_client_hello_cb :: FunPtr () -> Ptr S2nConfig -> S2nClientHelloFn -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_client_hello_cb_mode" c_wrap_config_set_client_hello_cb_mode :: FunPtr () -> Ptr S2nConfig -> S2nClientHelloCbMode -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_max_blinding_delay" c_wrap_config_set_max_blinding_delay :: FunPtr () -> Ptr S2nConfig -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_get_client_auth_type" c_wrap_config_get_client_auth_type :: FunPtr () -> Ptr S2nConfig -> Ptr S2nCertAuthType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_client_auth_type" c_wrap_config_set_client_auth_type :: FunPtr () -> Ptr S2nConfig -> S2nCertAuthType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_initial_ticket_count" c_wrap_config_set_initial_ticket_count :: FunPtr () -> Ptr S2nConfig -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_psk_mode" c_wrap_config_set_psk_mode :: FunPtr () -> Ptr S2nConfig -> S2nPskMode -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_psk_selection_callback" c_wrap_config_set_psk_selection_callback :: FunPtr () -> Ptr S2nConfig -> S2nPskSelectionCallback -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_async_pkey_callback" c_wrap_config_set_async_pkey_callback :: FunPtr () -> Ptr S2nConfig -> S2nAsyncPkeyFn -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_async_pkey_validation_mode" c_wrap_config_set_async_pkey_validation_mode :: FunPtr () -> Ptr S2nConfig -> S2nAsyncPkeyValidationMode -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_session_ticket_cb" c_wrap_config_set_session_ticket_cb :: FunPtr () -> Ptr S2nConfig -> S2nSessionTicketFn -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_key_log_cb" c_wrap_config_set_key_log_cb :: FunPtr () -> Ptr S2nConfig -> S2nKeyLogFn -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_enable_cert_req_dss_legacy_compat" c_wrap_config_enable_cert_req_dss_legacy_compat :: FunPtr () -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_server_max_early_data_size" c_wrap_config_set_server_max_early_data_size :: FunPtr () -> Ptr S2nConfig -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_early_data_cb" c_wrap_config_set_early_data_cb :: FunPtr () -> Ptr S2nConfig -> S2nEarlyDataCb -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_get_supported_groups" c_wrap_config_get_supported_groups :: FunPtr () -> Ptr S2nConfig -> Ptr Word16 -> Word16 -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_config_set_serialization_version" c_wrap_config_set_serialization_version :: FunPtr () -> Ptr S2nConfig -> S2nSerializationVersion -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_new" c_wrap_connection_new :: FunPtr () -> S2nMode -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nConnection)+foreign import ccall safe "s2n_wrap_connection_set_config" c_wrap_connection_set_config :: FunPtr () -> Ptr S2nConnection -> Ptr S2nConfig -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_ctx" c_wrap_connection_set_ctx :: FunPtr () -> Ptr S2nConnection -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_ctx" c_wrap_connection_get_ctx :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr ())+foreign import ccall safe "s2n_wrap_client_hello_cb_done" c_wrap_client_hello_cb_done :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_server_name_extension_used" c_wrap_connection_server_name_extension_used :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_client_hello" c_wrap_connection_get_client_hello :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nClientHello)+foreign import ccall safe "s2n_wrap_client_hello_parse_message" c_wrap_client_hello_parse_message :: FunPtr () -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nClientHello)+foreign import ccall safe "s2n_wrap_client_hello_free" c_wrap_client_hello_free :: FunPtr () -> Ptr (Ptr S2nClientHello) -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_raw_message_length" c_wrap_client_hello_get_raw_message_length :: FunPtr () -> Ptr S2nClientHello -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_raw_message" c_wrap_client_hello_get_raw_message :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_cipher_suites_length" c_wrap_client_hello_get_cipher_suites_length :: FunPtr () -> Ptr S2nClientHello -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_cipher_suites" c_wrap_client_hello_get_cipher_suites :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_extensions_length" c_wrap_client_hello_get_extensions_length :: FunPtr () -> Ptr S2nClientHello -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_extensions" c_wrap_client_hello_get_extensions :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_extension_length" c_wrap_client_hello_get_extension_length :: FunPtr () -> Ptr S2nClientHello -> S2nTlsExtensionType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_get_extension_by_id" c_wrap_client_hello_get_extension_by_id :: FunPtr () -> Ptr S2nClientHello -> S2nTlsExtensionType -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_client_hello_has_extension" c_wrap_client_hello_has_extension :: FunPtr () -> Ptr S2nClientHello -> Word16 -> Ptr CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_session_id_length" c_wrap_client_hello_get_session_id_length :: FunPtr () -> Ptr S2nClientHello -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_session_id" c_wrap_client_hello_get_session_id :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Ptr Word32 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_compression_methods_length" c_wrap_client_hello_get_compression_methods_length :: FunPtr () -> Ptr S2nClientHello -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_compression_methods" c_wrap_client_hello_get_compression_methods :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Word32 -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_legacy_protocol_version" c_wrap_client_hello_get_legacy_protocol_version :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_supported_groups" c_wrap_client_hello_get_supported_groups :: FunPtr () -> Ptr S2nClientHello -> Ptr Word16 -> Word16 -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_server_name_length" c_wrap_client_hello_get_server_name_length :: FunPtr () -> Ptr S2nClientHello -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_server_name" c_wrap_client_hello_get_server_name :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Word16 -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_client_hello_get_legacy_record_version" c_wrap_client_hello_get_legacy_record_version :: FunPtr () -> Ptr S2nClientHello -> Ptr Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_fd" c_wrap_connection_set_fd :: FunPtr () -> Ptr S2nConnection -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_read_fd" c_wrap_connection_set_read_fd :: FunPtr () -> Ptr S2nConnection -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_write_fd" c_wrap_connection_set_write_fd :: FunPtr () -> Ptr S2nConnection -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_read_fd" c_wrap_connection_get_read_fd :: FunPtr () -> Ptr S2nConnection -> Ptr CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_write_fd" c_wrap_connection_get_write_fd :: FunPtr () -> Ptr S2nConnection -> Ptr CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_use_corked_io" c_wrap_connection_use_corked_io :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_recv_ctx" c_wrap_connection_set_recv_ctx :: FunPtr () -> Ptr S2nConnection -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_send_ctx" c_wrap_connection_set_send_ctx :: FunPtr () -> Ptr S2nConnection -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_recv_cb" c_wrap_connection_set_recv_cb :: FunPtr () -> Ptr S2nConnection -> S2nRecvFn -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_send_cb" c_wrap_connection_set_send_cb :: FunPtr () -> Ptr S2nConnection -> S2nSendFn -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_prefer_throughput" c_wrap_connection_prefer_throughput :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_prefer_low_latency" c_wrap_connection_prefer_low_latency :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_recv_buffering" c_wrap_connection_set_recv_buffering :: FunPtr () -> Ptr S2nConnection -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_dynamic_buffers" c_wrap_connection_set_dynamic_buffers :: FunPtr () -> Ptr S2nConnection -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_dynamic_record_threshold" c_wrap_connection_set_dynamic_record_threshold :: FunPtr () -> Ptr S2nConnection -> Word32 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_verify_host_callback" c_wrap_connection_set_verify_host_callback :: FunPtr () -> Ptr S2nConnection -> S2nVerifyHostFn -> Ptr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_blinding" c_wrap_connection_set_blinding :: FunPtr () -> Ptr S2nConnection -> S2nBlinding -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_cipher_preferences" c_wrap_connection_set_cipher_preferences :: FunPtr () -> Ptr S2nConnection -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_request_key_update" c_wrap_connection_request_key_update :: FunPtr () -> Ptr S2nConnection -> S2nPeerKeyUpdate -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_append_protocol_preference" c_wrap_connection_append_protocol_preference :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_protocol_preferences" c_wrap_connection_set_protocol_preferences :: FunPtr () -> Ptr S2nConnection -> Ptr CString -> CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_set_server_name" c_wrap_set_server_name :: FunPtr () -> Ptr S2nConnection -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_get_server_name" c_wrap_get_server_name :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_get_application_protocol" c_wrap_get_application_protocol :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_connection_get_ocsp_response" c_wrap_connection_get_ocsp_response :: FunPtr () -> Ptr S2nConnection -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr Word8)+foreign import ccall safe "s2n_wrap_connection_get_sct_list" c_wrap_connection_get_sct_list :: FunPtr () -> Ptr S2nConnection -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr Word8)+foreign import ccall safe "s2n_wrap_negotiate" c_wrap_negotiate :: FunPtr () -> Ptr S2nConnection -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_send" c_wrap_send :: FunPtr () -> Ptr S2nConnection -> Ptr () -> CSsize -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_recv" c_wrap_recv :: FunPtr () -> Ptr S2nConnection -> Ptr () -> CSsize -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CSsize+foreign import ccall safe "s2n_wrap_connection_free_handshake" c_wrap_connection_free_handshake :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_release_buffers" c_wrap_connection_release_buffers :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_wipe" c_wrap_connection_wipe :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_free" c_wrap_connection_free :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_shutdown" c_wrap_shutdown :: FunPtr () -> Ptr S2nConnection -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_shutdown_send" c_wrap_shutdown_send :: FunPtr () -> Ptr S2nConnection -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_client_auth_type" c_wrap_connection_get_client_auth_type :: FunPtr () -> Ptr S2nConnection -> Ptr S2nCertAuthType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_client_auth_type" c_wrap_connection_set_client_auth_type :: FunPtr () -> Ptr S2nConnection -> S2nCertAuthType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_client_cert_chain" c_wrap_connection_get_client_cert_chain :: FunPtr () -> Ptr S2nConnection -> Ptr (Ptr Word8) -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_client_cert_used" c_wrap_connection_client_cert_used :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_add_new_tickets_to_send" c_wrap_connection_add_new_tickets_to_send :: FunPtr () -> Ptr S2nConnection -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_tickets_sent" c_wrap_connection_get_tickets_sent :: FunPtr () -> Ptr S2nConnection -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_server_keying_material_lifetime" c_wrap_connection_set_server_keying_material_lifetime :: FunPtr () -> Ptr S2nConnection -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_session_ticket_get_data_len" c_wrap_session_ticket_get_data_len :: FunPtr () -> Ptr S2nSessionTicket -> Ptr CSize -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_session_ticket_get_data" c_wrap_session_ticket_get_data :: FunPtr () -> Ptr S2nSessionTicket -> CSize -> Ptr Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_session_ticket_get_lifetime" c_wrap_session_ticket_get_lifetime :: FunPtr () -> Ptr S2nSessionTicket -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_session" c_wrap_connection_set_session :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> CSize -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_session" c_wrap_connection_get_session :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> CSize -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_session_ticket_lifetime_hint" c_wrap_connection_get_session_ticket_lifetime_hint :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_session_length" c_wrap_connection_get_session_length :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_session_id_length" c_wrap_connection_get_session_id_length :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_session_id" c_wrap_connection_get_session_id :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> CSize -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_is_session_resumed" c_wrap_connection_is_session_resumed :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_is_ocsp_stapled" c_wrap_connection_is_ocsp_stapled :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_selected_signature_algorithm" c_wrap_connection_get_selected_signature_algorithm :: FunPtr () -> Ptr S2nConnection -> Ptr S2nTlsSignatureAlgorithm -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_selected_digest_algorithm" c_wrap_connection_get_selected_digest_algorithm :: FunPtr () -> Ptr S2nConnection -> Ptr S2nTlsHashAlgorithm -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_selected_client_cert_signature_algorithm" c_wrap_connection_get_selected_client_cert_signature_algorithm :: FunPtr () -> Ptr S2nConnection -> Ptr S2nTlsSignatureAlgorithm -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_selected_client_cert_digest_algorithm" c_wrap_connection_get_selected_client_cert_digest_algorithm :: FunPtr () -> Ptr S2nConnection -> Ptr S2nTlsHashAlgorithm -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_selected_cert" c_wrap_connection_get_selected_cert :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nCertChainAndKey)+foreign import ccall safe "s2n_wrap_cert_chain_get_length" c_wrap_cert_chain_get_length :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_chain_get_cert" c_wrap_cert_chain_get_cert :: FunPtr () -> Ptr S2nCertChainAndKey -> Ptr (Ptr S2nCert) -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_get_der" c_wrap_cert_get_der :: FunPtr () -> Ptr S2nCert -> Ptr (Ptr Word8) -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_peer_cert_chain" c_wrap_connection_get_peer_cert_chain :: FunPtr () -> Ptr S2nConnection -> Ptr S2nCertChainAndKey -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_get_x509_extension_value_length" c_wrap_cert_get_x509_extension_value_length :: FunPtr () -> Ptr S2nCert -> Ptr Word8 -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_get_x509_extension_value" c_wrap_cert_get_x509_extension_value :: FunPtr () -> Ptr S2nCert -> Ptr Word8 -> Ptr Word8 -> Ptr Word32 -> Ptr CInt -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_get_utf8_string_from_extension_data_length" c_wrap_cert_get_utf8_string_from_extension_data_length :: FunPtr () -> Ptr Word8 -> Word32 -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_cert_get_utf8_string_from_extension_data" c_wrap_cert_get_utf8_string_from_extension_data :: FunPtr () -> Ptr Word8 -> Word32 -> Ptr Word8 -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_external_psk_new" c_wrap_external_psk_new :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nPsk)+foreign import ccall safe "s2n_wrap_psk_free" c_wrap_psk_free :: FunPtr () -> Ptr (Ptr S2nPsk) -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_psk_set_identity" c_wrap_psk_set_identity :: FunPtr () -> Ptr S2nPsk -> Ptr Word8 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_psk_set_secret" c_wrap_psk_set_secret :: FunPtr () -> Ptr S2nPsk -> Ptr Word8 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_psk_set_hmac" c_wrap_psk_set_hmac :: FunPtr () -> Ptr S2nPsk -> S2nPskHmac -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_append_psk" c_wrap_connection_append_psk :: FunPtr () -> Ptr S2nConnection -> Ptr S2nPsk -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_psk_mode" c_wrap_connection_set_psk_mode :: FunPtr () -> Ptr S2nConnection -> S2nPskMode -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_negotiated_psk_identity_length" c_wrap_connection_get_negotiated_psk_identity_length :: FunPtr () -> Ptr S2nConnection -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_negotiated_psk_identity" c_wrap_connection_get_negotiated_psk_identity :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_psk_new" c_wrap_offered_psk_new :: FunPtr () -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO (Ptr S2nOfferedPsk)+foreign import ccall safe "s2n_wrap_offered_psk_free" c_wrap_offered_psk_free :: FunPtr () -> Ptr (Ptr S2nOfferedPsk) -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_psk_get_identity" c_wrap_offered_psk_get_identity :: FunPtr () -> Ptr S2nOfferedPsk -> Ptr (Ptr Word8) -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_psk_list_next" c_wrap_offered_psk_list_next :: FunPtr () -> Ptr S2nOfferedPskList -> Ptr S2nOfferedPsk -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_psk_list_reread" c_wrap_offered_psk_list_reread :: FunPtr () -> Ptr S2nOfferedPskList -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_psk_list_choose_psk" c_wrap_offered_psk_list_choose_psk :: FunPtr () -> Ptr S2nOfferedPskList -> Ptr S2nOfferedPsk -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_psk_configure_early_data" c_wrap_psk_configure_early_data :: FunPtr () -> Ptr S2nPsk -> Word32 -> Word8 -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_psk_set_application_protocol" c_wrap_psk_set_application_protocol :: FunPtr () -> Ptr S2nPsk -> Ptr Word8 -> Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_psk_set_early_data_context" c_wrap_psk_set_early_data_context :: FunPtr () -> Ptr S2nPsk -> Ptr Word8 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_client_protocol_version" c_wrap_connection_get_client_protocol_version :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_server_protocol_version" c_wrap_connection_get_server_protocol_version :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_actual_protocol_version" c_wrap_connection_get_actual_protocol_version :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_client_hello_version" c_wrap_connection_get_client_hello_version :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_cipher" c_wrap_connection_get_cipher :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_connection_get_certificate_match" c_wrap_connection_get_certificate_match :: FunPtr () -> Ptr S2nConnection -> Ptr S2nCertSniMatch -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_master_secret" c_wrap_connection_get_master_secret :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> CSize -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_tls_exporter" c_wrap_connection_tls_exporter :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_cipher_iana_value" c_wrap_connection_get_cipher_iana_value :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Ptr Word8 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_is_valid_for_cipher_preferences" c_wrap_connection_is_valid_for_cipher_preferences :: FunPtr () -> Ptr S2nConnection -> CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_curve" c_wrap_connection_get_curve :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_connection_get_kem_name" c_wrap_connection_get_kem_name :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_connection_get_kem_group_name" c_wrap_connection_get_kem_group_name :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_connection_get_key_exchange_group" c_wrap_connection_get_key_exchange_group :: FunPtr () -> Ptr S2nConnection -> Ptr CString -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_alert" c_wrap_connection_get_alert :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_handshake_type_name" c_wrap_connection_get_handshake_type_name :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_connection_get_last_message_name" c_wrap_connection_get_last_message_name :: FunPtr () -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CString+foreign import ccall safe "s2n_wrap_async_pkey_op_perform" c_wrap_async_pkey_op_perform :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr S2nCertPrivateKey -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_async_pkey_op_apply" c_wrap_async_pkey_op_apply :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr S2nConnection -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_async_pkey_op_free" c_wrap_async_pkey_op_free :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_async_pkey_op_get_op_type" c_wrap_async_pkey_op_get_op_type :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr S2nAsyncPkeyOpType -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_async_pkey_op_get_input_size" c_wrap_async_pkey_op_get_input_size :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_async_pkey_op_get_input" c_wrap_async_pkey_op_get_input :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_async_pkey_op_set_output" c_wrap_async_pkey_op_set_output :: FunPtr () -> Ptr S2nAsyncPkeyOp -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_server_max_early_data_size" c_wrap_connection_set_server_max_early_data_size :: FunPtr () -> Ptr S2nConnection -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_set_server_early_data_context" c_wrap_connection_set_server_early_data_context :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_early_data_status" c_wrap_connection_get_early_data_status :: FunPtr () -> Ptr S2nConnection -> Ptr S2nEarlyDataStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_remaining_early_data_size" c_wrap_connection_get_remaining_early_data_size :: FunPtr () -> Ptr S2nConnection -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_get_max_early_data_size" c_wrap_connection_get_max_early_data_size :: FunPtr () -> Ptr S2nConnection -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_send_early_data" c_wrap_send_early_data :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> CSsize -> Ptr CSsize -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_recv_early_data" c_wrap_recv_early_data :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> CSsize -> Ptr CSsize -> Ptr S2nBlockedStatus -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_early_data_get_context_length" c_wrap_offered_early_data_get_context_length :: FunPtr () -> Ptr S2nOfferedEarlyData -> Ptr Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_early_data_get_context" c_wrap_offered_early_data_get_context :: FunPtr () -> Ptr S2nOfferedEarlyData -> Ptr Word8 -> Word16 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_early_data_reject" c_wrap_offered_early_data_reject :: FunPtr () -> Ptr S2nOfferedEarlyData -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_offered_early_data_accept" c_wrap_offered_early_data_accept :: FunPtr () -> Ptr S2nOfferedEarlyData -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_serialization_length" c_wrap_connection_serialization_length :: FunPtr () -> Ptr S2nConnection -> Ptr Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_serialize" c_wrap_connection_serialize :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt+foreign import ccall safe "s2n_wrap_connection_deserialize" c_wrap_connection_deserialize :: FunPtr () -> Ptr S2nConnection -> Ptr Word8 -> Word32 -> Ptr S2nErrorFuncs -> Ptr S2nError -> IO CInt
+ src/S2nTls/Ffi/Types.hs view
@@ -0,0 +1,1134 @@+{-# LANGUAGE PatternSynonyms #-}++{- |+Module      : S2nTls.Ffi.Types+Description : Core types for s2n-tls FFI bindings+Copyright   : (c) 2026 Daniel Goertzen+License     : Apache-2.0+Maintainer  : daniel.goertzen@gmail.com+Stability   : experimental+Portability : non-portable (requires s2n-tls C library)++This module defines the core types used by the s2n-tls FFI bindings,+including the 'S2nTlsFfi' record that contains all FFI function pointers.+-}+module S2nTls.Ffi.Types (+  -- * Error Types+  S2nError (..),+  S2nErrorFuncs (..),+  MissingSymbol (..),++  -- * Opaque Types+  S2nConfig,+  S2nConnection,+  S2nCertChainAndKey,+  S2nCert,+  S2nClientHello,+  S2nPsk,+  S2nOfferedPsk,+  S2nOfferedPskList,+  S2nSessionTicket,+  S2nAsyncPkeyOp,+  S2nCertPrivateKey,+  S2nOfferedEarlyData,+  S2nStacktrace,++  -- * Return Codes+  pattern S2nSuccess,+  pattern S2nFailure,+  pattern S2nCallbackBlocked,++  -- * TLS Versions+  pattern S2nMinimumSupportedTlsRecordMajorVersion,+  pattern S2nMaximumSupportedTlsRecordMajorVersion,+  pattern S2nSslv2,+  pattern S2nSslv3,+  pattern S2nTls10,+  pattern S2nTls11,+  pattern S2nTls12,+  pattern S2nTls13,+  pattern S2nUnknownProtocolVersion,++  -- * Enumerations+  S2nErrorType (..),+  pattern S2nErrTOk,+  pattern S2nErrTIo,+  pattern S2nErrTClosed,+  pattern S2nErrTBlocked,+  pattern S2nErrTAlert,+  pattern S2nErrTProto,+  pattern S2nErrTInternal,+  pattern S2nErrTUsage,+  S2nMode (..),+  pattern S2nServer,+  pattern S2nClient,+  S2nBlinding (..),+  pattern S2nBuiltInBlinding,+  pattern S2nSelfServiceBlinding,+  S2nBlockedStatus (..),+  pattern S2nNotBlocked,+  pattern S2nBlockedOnRead,+  pattern S2nBlockedOnWrite,+  pattern S2nBlockedOnApplicationInput,+  pattern S2nBlockedOnEarlyData,+  S2nCertAuthType (..),+  pattern S2nCertAuthNone,+  pattern S2nCertAuthRequired,+  pattern S2nCertAuthOptional,+  S2nPskHmac (..),+  pattern S2nPskHmacSha256,+  pattern S2nPskHmacSha384,+  S2nPskMode (..),+  pattern S2nPskModeResumption,+  pattern S2nPskModeExternal,+  S2nEarlyDataStatus (..),+  pattern S2nEarlyDataStatusOk,+  pattern S2nEarlyDataStatusNotRequested,+  pattern S2nEarlyDataStatusRejected,+  pattern S2nEarlyDataStatusEnd,+  S2nAsyncPkeyOpType (..),+  pattern S2nAsyncDecrypt,+  pattern S2nAsyncSign,+  S2nAsyncPkeyValidationMode (..),+  pattern S2nAsyncPkeyValidationFast,+  pattern S2nAsyncPkeyValidationStrict,+  S2nSerializationVersion (..),+  pattern S2nSerializedConnNone,+  pattern S2nSerializedConnV1,+  S2nTlsExtensionType (..),+  pattern S2nExtensionServerName,+  pattern S2nExtensionMaxFragLen,+  pattern S2nExtensionOcspStapling,+  pattern S2nExtensionSupportedGroups,+  pattern S2nExtensionEcPointFormats,+  pattern S2nExtensionSignatureAlgorithms,+  pattern S2nExtensionAlpn,+  pattern S2nExtensionCertificateTransparency,+  pattern S2nExtensionRenegotiationInfo,+  S2nMaxFragLen (..),+  pattern S2nTlsMaxFragLen512,+  pattern S2nTlsMaxFragLen1024,+  pattern S2nTlsMaxFragLen2048,+  pattern S2nTlsMaxFragLen4096,+  S2nFipsMode (..),+  pattern S2nFipsModeDisabled,+  pattern S2nFipsModeEnabled,+  S2nStatusRequestType (..),+  pattern S2nStatusRequestNone,+  pattern S2nStatusRequestOcsp,+  S2nCtSupportLevel (..),+  pattern S2nCtSupportNone,+  pattern S2nCtSupportRequest,+  S2nAlertBehavior (..),+  pattern S2nAlertFailOnWarnings,+  pattern S2nAlertIgnoreWarnings,+  S2nClientHelloCbMode (..),+  pattern S2nClientHelloCbBlocking,+  pattern S2nClientHelloCbNonblocking,+  S2nTlsSignatureAlgorithm (..),+  pattern S2nTlsSignatureAnonymous,+  pattern S2nTlsSignatureRsa,+  pattern S2nTlsSignatureEcdsa,+  pattern S2nTlsSignatureRsaPssRsae,+  pattern S2nTlsSignatureRsaPssPss,+  S2nTlsHashAlgorithm (..),+  pattern S2nTlsHashNone,+  pattern S2nTlsHashMd5,+  pattern S2nTlsHashSha1,+  pattern S2nTlsHashSha224,+  pattern S2nTlsHashSha256,+  pattern S2nTlsHashSha384,+  pattern S2nTlsHashSha512,+  S2nCertSniMatch (..),+  pattern S2nCertSniMatchNotApplicable,+  pattern S2nCertSniMatched,+  pattern S2nCertSniNoMatchFound,+  S2nPeerKeyUpdate (..),+  pattern S2nKeyUpdateNotRequested,+  pattern S2nKeyUpdateRequested,+  S2nVerifyAfterSign (..),+  pattern S2nVerifyAfterSignDisabled,+  pattern S2nVerifyAfterSignEnabled,++  -- * Callback Types+  S2nClockTimeNanoseconds,+  S2nRecvFn,+  S2nSendFn,+  S2nCacheStoreCallback,+  S2nCacheRetrieveCallback,+  S2nCacheDeleteCallback,+  S2nMemInitCallback,+  S2nMemCleanupCallback,+  S2nMemMallocCallback,+  S2nMemFreeCallback,+  S2nRandInitCallback,+  S2nRandCleanupCallback,+  S2nRandSeedCallback,+  S2nRandMixCallback,+  S2nClientHelloFn,+  S2nCertTiebreakCallback,+  S2nVerifyHostFn,+  S2nPskSelectionCallback,+  S2nAsyncPkeyFn,+  S2nSessionTicketFn,+  S2nKeyLogFn,+  S2nEarlyDataCb,++  -- * FFI Record+  S2nTlsFfi (..),+) where++import Control.Exception (Exception)+import Data.Word (Word16, Word32, Word64, Word8)+import Foreign.C.String (CString, castCharToCChar, peekCString)+import Foreign.C.Types (CBool (..), CInt (..), CLong (..), CSize (..))+import Foreign.Marshal.Array (pokeArray0)+import Foreign.Ptr (FunPtr, Ptr, plusPtr)+import Foreign.Storable (Storable (..))+import System.Posix.Types (CSsize (..))++--------------------------------------------------------------------------------+-- Error Types+--------------------------------------------------------------------------------++{- | Exception thrown when calling an s2n function that wasn't loaded.+The string contains the name of the missing symbol.+-}+newtype MissingSymbol = MissingSymbol String+  deriving (Show, Eq)++instance Exception MissingSymbol++{- | Full error information captured from an s2n function call.+Contains the error code plus the string representations.+-}+data S2nError = S2nError+  { s2nErrorCode :: !CInt+  , s2nErrorDebugMessage :: String+  -- ^ Result of s2n_strerror_debug()+  }+  deriving (Show, Eq)++instance Exception S2nError++{- | Struct of error function pointers, passed to C wrappers.+Loaded first during initialization - fatal if any are missing.+-}+data S2nErrorFuncs = S2nErrorFuncs+  { errnoLocation :: !(FunPtr (IO (Ptr CInt)))+  , strerrorDebug :: !(FunPtr (CInt -> CString -> IO CString))+  , errorGetType :: !(FunPtr (CInt -> IO S2nErrorType))+  }++instance Storable S2nErrorFuncs where+  sizeOf _ = 3 * sizeOf (undefined :: FunPtr ())+  alignment _ = alignment (undefined :: FunPtr ())+  peek ptr = do+    a <- peekByteOff ptr 0+    b <- peekByteOff ptr (sizeOf (undefined :: FunPtr ()))+    c <- peekByteOff ptr (2 * sizeOf (undefined :: FunPtr ()))+    pure $ S2nErrorFuncs a b c+  poke ptr (S2nErrorFuncs a b c) = do+    pokeByteOff ptr 0 a+    pokeByteOff ptr (sizeOf (undefined :: FunPtr ())) b+    pokeByteOff ptr (2 * sizeOf (undefined :: FunPtr ())) c++-- | Size of the debug string buffer in S2nError (must match C S2N_ERROR_DEBUG_STRING_SIZE)+s2nErrorDebugStringSize :: Int+s2nErrorDebugStringSize = 256++{- | Output struct populated by C wrappers on error.+Contains error code and an owned copy of the debug string.+-}+instance Storable S2nError where+  sizeOf _ = sizeOf (undefined :: CInt) + s2nErrorDebugStringSize+  alignment _ = alignment (undefined :: CInt)+  peek ptr = do+    code <- peekByteOff ptr 0+    -- Read the fixed-size debug string buffer+    let strPtr = ptr `plusPtr` sizeOf (undefined :: CInt)+    dbgStr <- peekCString strPtr+    pure $ S2nError code dbgStr+  poke ptr (S2nError code dbgStr) = do+    pokeByteOff ptr 0 code+    -- Write the debug string to the fixed-size buffer+    let strPtr = ptr `plusPtr` sizeOf (undefined :: CInt)+    -- Zero out the buffer first, then copy the string+    _ <- memset strPtr 0 (fromIntegral s2nErrorDebugStringSize)+    let truncated = take (s2nErrorDebugStringSize - 1) dbgStr+    pokeArray0 0 strPtr (map castCharToCChar truncated)++-- | Foreign import for memset+foreign import ccall unsafe "string.h memset"+  memset :: Ptr a -> CInt -> CSize -> IO (Ptr a)++--------------------------------------------------------------------------------+-- Opaque Types+--------------------------------------------------------------------------------++-- | Opaque type representing an s2n configuration.+data S2nConfig++-- | Opaque type representing an s2n connection.+data S2nConnection++-- | Opaque type representing a certificate chain and private key pair.+data S2nCertChainAndKey++-- | Opaque type representing a certificate.+data S2nCert++-- | Opaque type representing a parsed ClientHello message.+data S2nClientHello++-- | Opaque type representing a pre-shared key.+data S2nPsk++-- | Opaque type representing an offered PSK during negotiation.+data S2nOfferedPsk++-- | Opaque type representing a list of offered PSKs.+data S2nOfferedPskList++-- | Opaque type representing a session ticket.+data S2nSessionTicket++-- | Opaque type representing an async private key operation.+data S2nAsyncPkeyOp++-- | Opaque type representing a certificate's private key.+data S2nCertPrivateKey++-- | Opaque type representing offered early data.+data S2nOfferedEarlyData++-- | Opaque type representing a stack trace.+data S2nStacktrace++--------------------------------------------------------------------------------+-- Return Codes+--------------------------------------------------------------------------------++-- | Function completed successfully.+pattern S2nSuccess :: CInt+pattern S2nSuccess = 0++-- | Function encountered an error.+pattern S2nFailure :: CInt+pattern S2nFailure = -1++-- | Callback was blocked and needs to be retried.+pattern S2nCallbackBlocked :: CInt+pattern S2nCallbackBlocked = -2++--------------------------------------------------------------------------------+-- TLS Versions+--------------------------------------------------------------------------------++-- | Minimum supported TLS record major version.+pattern S2nMinimumSupportedTlsRecordMajorVersion :: Word8+pattern S2nMinimumSupportedTlsRecordMajorVersion = 2++-- | Maximum supported TLS record major version.+pattern S2nMaximumSupportedTlsRecordMajorVersion :: Word8+pattern S2nMaximumSupportedTlsRecordMajorVersion = 3++-- | SSL version 2 (deprecated, insecure).+pattern S2nSslv2 :: CInt+pattern S2nSslv2 = 20++-- | SSL version 3 (deprecated, insecure).+pattern S2nSslv3 :: CInt+pattern S2nSslv3 = 30++-- | TLS version 1.0.+pattern S2nTls10 :: CInt+pattern S2nTls10 = 31++-- | TLS version 1.1.+pattern S2nTls11 :: CInt+pattern S2nTls11 = 32++-- | TLS version 1.2.+pattern S2nTls12 :: CInt+pattern S2nTls12 = 33++-- | TLS version 1.3.+pattern S2nTls13 :: CInt+pattern S2nTls13 = 34++-- | Unknown or unrecognized protocol version.+pattern S2nUnknownProtocolVersion :: CInt+pattern S2nUnknownProtocolVersion = 0++--------------------------------------------------------------------------------+-- Enumerations+--------------------------------------------------------------------------------++-- | Type of error returned by s2n functions.+newtype S2nErrorType = S2nErrorType CInt+  deriving (Eq, Ord, Show, Storable)++-- | No error occurred.+pattern S2nErrTOk :: S2nErrorType+pattern S2nErrTOk = S2nErrorType 0++-- | I\/O error (check errno).+pattern S2nErrTIo :: S2nErrorType+pattern S2nErrTIo = S2nErrorType 1++-- | Connection was closed.+pattern S2nErrTClosed :: S2nErrorType+pattern S2nErrTClosed = S2nErrorType 2++-- | Operation blocked (retry needed).+pattern S2nErrTBlocked :: S2nErrorType+pattern S2nErrTBlocked = S2nErrorType 3++-- | TLS alert received.+pattern S2nErrTAlert :: S2nErrorType+pattern S2nErrTAlert = S2nErrorType 4++-- | Protocol error.+pattern S2nErrTProto :: S2nErrorType+pattern S2nErrTProto = S2nErrorType 5++-- | Internal library error.+pattern S2nErrTInternal :: S2nErrorType+pattern S2nErrTInternal = S2nErrorType 6++-- | Incorrect API usage.+pattern S2nErrTUsage :: S2nErrorType+pattern S2nErrTUsage = S2nErrorType 7++-- | TLS connection mode (server or client).+newtype S2nMode = S2nMode CInt+  deriving (Eq, Ord, Show, Storable)++-- | Server mode.+pattern S2nServer :: S2nMode+pattern S2nServer = S2nMode 0++-- | Client mode.+pattern S2nClient :: S2nMode+pattern S2nClient = S2nMode 1++-- | Blinding mode for timing attack mitigation.+newtype S2nBlinding = S2nBlinding CInt+  deriving (Eq, Ord, Show, Storable)++-- | s2n handles blinding automatically.+pattern S2nBuiltInBlinding :: S2nBlinding+pattern S2nBuiltInBlinding = S2nBlinding 0++-- | Application handles blinding delays.+pattern S2nSelfServiceBlinding :: S2nBlinding+pattern S2nSelfServiceBlinding = S2nBlinding 1++-- | Status indicating why an operation was blocked.+newtype S2nBlockedStatus = S2nBlockedStatus CInt+  deriving (Eq, Ord, Show, Storable)++-- | Operation completed successfully.+pattern S2nNotBlocked :: S2nBlockedStatus+pattern S2nNotBlocked = S2nBlockedStatus 0++-- | Blocked waiting for data to read.+pattern S2nBlockedOnRead :: S2nBlockedStatus+pattern S2nBlockedOnRead = S2nBlockedStatus 1++-- | Blocked waiting to write data.+pattern S2nBlockedOnWrite :: S2nBlockedStatus+pattern S2nBlockedOnWrite = S2nBlockedStatus 2++-- | Blocked waiting for application input.+pattern S2nBlockedOnApplicationInput :: S2nBlockedStatus+pattern S2nBlockedOnApplicationInput = S2nBlockedStatus 3++-- | Blocked on early data processing.+pattern S2nBlockedOnEarlyData :: S2nBlockedStatus+pattern S2nBlockedOnEarlyData = S2nBlockedStatus 4++-- | Client certificate authentication mode.+newtype S2nCertAuthType = S2nCertAuthType CInt+  deriving (Eq, Ord, Show, Storable)++-- | No client authentication.+pattern S2nCertAuthNone :: S2nCertAuthType+pattern S2nCertAuthNone = S2nCertAuthType 0++-- | Client certificate required.+pattern S2nCertAuthRequired :: S2nCertAuthType+pattern S2nCertAuthRequired = S2nCertAuthType 1++-- | Client certificate optional.+pattern S2nCertAuthOptional :: S2nCertAuthType+pattern S2nCertAuthOptional = S2nCertAuthType 2++-- | HMAC algorithm for pre-shared keys.+newtype S2nPskHmac = S2nPskHmac CInt+  deriving (Eq, Ord, Show, Storable)++-- | HMAC-SHA256 for PSK.+pattern S2nPskHmacSha256 :: S2nPskHmac+pattern S2nPskHmacSha256 = S2nPskHmac 0++-- | HMAC-SHA384 for PSK.+pattern S2nPskHmacSha384 :: S2nPskHmac+pattern S2nPskHmacSha384 = S2nPskHmac 1++-- | Pre-shared key mode.+newtype S2nPskMode = S2nPskMode CInt+  deriving (Eq, Ord, Show, Storable)++-- | PSK for session resumption.+pattern S2nPskModeResumption :: S2nPskMode+pattern S2nPskModeResumption = S2nPskMode 0++-- | External\/out-of-band PSK.+pattern S2nPskModeExternal :: S2nPskMode+pattern S2nPskModeExternal = S2nPskMode 1++-- | Status of TLS 1.3 early data (0-RTT).+newtype S2nEarlyDataStatus = S2nEarlyDataStatus CInt+  deriving (Eq, Ord, Show, Storable)++-- | Early data accepted.+pattern S2nEarlyDataStatusOk :: S2nEarlyDataStatus+pattern S2nEarlyDataStatusOk = S2nEarlyDataStatus 0++-- | Early data not requested.+pattern S2nEarlyDataStatusNotRequested :: S2nEarlyDataStatus+pattern S2nEarlyDataStatusNotRequested = S2nEarlyDataStatus 1++-- | Early data rejected.+pattern S2nEarlyDataStatusRejected :: S2nEarlyDataStatus+pattern S2nEarlyDataStatusRejected = S2nEarlyDataStatus 2++-- | Early data processing complete.+pattern S2nEarlyDataStatusEnd :: S2nEarlyDataStatus+pattern S2nEarlyDataStatusEnd = S2nEarlyDataStatus 3++-- | Type of async private key operation.+newtype S2nAsyncPkeyOpType = S2nAsyncPkeyOpType CInt+  deriving (Eq, Ord, Show, Storable)++-- | Decryption operation.+pattern S2nAsyncDecrypt :: S2nAsyncPkeyOpType+pattern S2nAsyncDecrypt = S2nAsyncPkeyOpType 0++-- | Signing operation.+pattern S2nAsyncSign :: S2nAsyncPkeyOpType+pattern S2nAsyncSign = S2nAsyncPkeyOpType 1++-- | Validation mode for async private key operations.+newtype S2nAsyncPkeyValidationMode = S2nAsyncPkeyValidationMode CInt+  deriving (Eq, Ord, Show, Storable)++-- | Fast validation (less strict).+pattern S2nAsyncPkeyValidationFast :: S2nAsyncPkeyValidationMode+pattern S2nAsyncPkeyValidationFast = S2nAsyncPkeyValidationMode 0++-- | Strict validation.+pattern S2nAsyncPkeyValidationStrict :: S2nAsyncPkeyValidationMode+pattern S2nAsyncPkeyValidationStrict = S2nAsyncPkeyValidationMode 1++-- | Connection serialization format version.+newtype S2nSerializationVersion = S2nSerializationVersion CInt+  deriving (Eq, Ord, Show, Storable)++-- | No serialization.+pattern S2nSerializedConnNone :: S2nSerializationVersion+pattern S2nSerializedConnNone = S2nSerializationVersion 0++-- | Serialization format version 1.+pattern S2nSerializedConnV1 :: S2nSerializationVersion+pattern S2nSerializedConnV1 = S2nSerializationVersion 1++-- | TLS extension type identifier.+newtype S2nTlsExtensionType = S2nTlsExtensionType CInt+  deriving (Eq, Ord, Show, Storable)++-- | Server Name Indication (SNI) extension.+pattern S2nExtensionServerName :: S2nTlsExtensionType+pattern S2nExtensionServerName = S2nTlsExtensionType 0++-- | Maximum fragment length extension.+pattern S2nExtensionMaxFragLen :: S2nTlsExtensionType+pattern S2nExtensionMaxFragLen = S2nTlsExtensionType 1++-- | OCSP stapling extension.+pattern S2nExtensionOcspStapling :: S2nTlsExtensionType+pattern S2nExtensionOcspStapling = S2nTlsExtensionType 5++-- | Supported groups (elliptic curves) extension.+pattern S2nExtensionSupportedGroups :: S2nTlsExtensionType+pattern S2nExtensionSupportedGroups = S2nTlsExtensionType 10++-- | EC point formats extension.+pattern S2nExtensionEcPointFormats :: S2nTlsExtensionType+pattern S2nExtensionEcPointFormats = S2nTlsExtensionType 11++-- | Signature algorithms extension.+pattern S2nExtensionSignatureAlgorithms :: S2nTlsExtensionType+pattern S2nExtensionSignatureAlgorithms = S2nTlsExtensionType 13++-- | Application-Layer Protocol Negotiation (ALPN) extension.+pattern S2nExtensionAlpn :: S2nTlsExtensionType+pattern S2nExtensionAlpn = S2nTlsExtensionType 16++-- | Certificate Transparency extension.+pattern S2nExtensionCertificateTransparency :: S2nTlsExtensionType+pattern S2nExtensionCertificateTransparency = S2nTlsExtensionType 18++-- | Renegotiation info extension.+pattern S2nExtensionRenegotiationInfo :: S2nTlsExtensionType+pattern S2nExtensionRenegotiationInfo = S2nTlsExtensionType 65281++-- | Maximum TLS fragment length.+newtype S2nMaxFragLen = S2nMaxFragLen CInt+  deriving (Eq, Ord, Show, Storable)++-- | Maximum fragment length of 512 bytes.+pattern S2nTlsMaxFragLen512 :: S2nMaxFragLen+pattern S2nTlsMaxFragLen512 = S2nMaxFragLen 1++-- | Maximum fragment length of 1024 bytes.+pattern S2nTlsMaxFragLen1024 :: S2nMaxFragLen+pattern S2nTlsMaxFragLen1024 = S2nMaxFragLen 2++-- | Maximum fragment length of 2048 bytes.+pattern S2nTlsMaxFragLen2048 :: S2nMaxFragLen+pattern S2nTlsMaxFragLen2048 = S2nMaxFragLen 3++-- | Maximum fragment length of 4096 bytes.+pattern S2nTlsMaxFragLen4096 :: S2nMaxFragLen+pattern S2nTlsMaxFragLen4096 = S2nMaxFragLen 4++-- | FIPS mode status.+newtype S2nFipsMode = S2nFipsMode CInt+  deriving (Eq, Ord, Show, Storable)++-- | FIPS mode disabled.+pattern S2nFipsModeDisabled :: S2nFipsMode+pattern S2nFipsModeDisabled = S2nFipsMode 0++-- | FIPS mode enabled.+pattern S2nFipsModeEnabled :: S2nFipsMode+pattern S2nFipsModeEnabled = S2nFipsMode 1++-- | OCSP status request type.+newtype S2nStatusRequestType = S2nStatusRequestType CInt+  deriving (Eq, Ord, Show, Storable)++-- | No status request.+pattern S2nStatusRequestNone :: S2nStatusRequestType+pattern S2nStatusRequestNone = S2nStatusRequestType 0++-- | Request OCSP status.+pattern S2nStatusRequestOcsp :: S2nStatusRequestType+pattern S2nStatusRequestOcsp = S2nStatusRequestType 1++-- | Certificate Transparency support level.+newtype S2nCtSupportLevel = S2nCtSupportLevel CInt+  deriving (Eq, Ord, Show, Storable)++-- | No Certificate Transparency support.+pattern S2nCtSupportNone :: S2nCtSupportLevel+pattern S2nCtSupportNone = S2nCtSupportLevel 0++-- | Request Certificate Transparency.+pattern S2nCtSupportRequest :: S2nCtSupportLevel+pattern S2nCtSupportRequest = S2nCtSupportLevel 1++-- | TLS alert behavior on warnings.+newtype S2nAlertBehavior = S2nAlertBehavior CInt+  deriving (Eq, Ord, Show, Storable)++-- | Fail on warning alerts.+pattern S2nAlertFailOnWarnings :: S2nAlertBehavior+pattern S2nAlertFailOnWarnings = S2nAlertBehavior 0++-- | Ignore warning alerts.+pattern S2nAlertIgnoreWarnings :: S2nAlertBehavior+pattern S2nAlertIgnoreWarnings = S2nAlertBehavior 1++-- | Client hello callback mode.+newtype S2nClientHelloCbMode = S2nClientHelloCbMode CInt+  deriving (Eq, Ord, Show, Storable)++-- | Blocking callback mode.+pattern S2nClientHelloCbBlocking :: S2nClientHelloCbMode+pattern S2nClientHelloCbBlocking = S2nClientHelloCbMode 0++-- | Non-blocking callback mode.+pattern S2nClientHelloCbNonblocking :: S2nClientHelloCbMode+pattern S2nClientHelloCbNonblocking = S2nClientHelloCbMode 1++-- | TLS signature algorithm.+newtype S2nTlsSignatureAlgorithm = S2nTlsSignatureAlgorithm CInt+  deriving (Eq, Ord, Show, Storable)++-- | Anonymous (no signature).+pattern S2nTlsSignatureAnonymous :: S2nTlsSignatureAlgorithm+pattern S2nTlsSignatureAnonymous = S2nTlsSignatureAlgorithm 0++-- | RSA signature.+pattern S2nTlsSignatureRsa :: S2nTlsSignatureAlgorithm+pattern S2nTlsSignatureRsa = S2nTlsSignatureAlgorithm 1++-- | ECDSA signature.+pattern S2nTlsSignatureEcdsa :: S2nTlsSignatureAlgorithm+pattern S2nTlsSignatureEcdsa = S2nTlsSignatureAlgorithm 3++-- | RSA-PSS with RSAE key.+pattern S2nTlsSignatureRsaPssRsae :: S2nTlsSignatureAlgorithm+pattern S2nTlsSignatureRsaPssRsae = S2nTlsSignatureAlgorithm 4++-- | RSA-PSS with PSS key.+pattern S2nTlsSignatureRsaPssPss :: S2nTlsSignatureAlgorithm+pattern S2nTlsSignatureRsaPssPss = S2nTlsSignatureAlgorithm 5++-- | TLS hash algorithm.+newtype S2nTlsHashAlgorithm = S2nTlsHashAlgorithm CInt+  deriving (Eq, Ord, Show, Storable)++-- | No hash algorithm.+pattern S2nTlsHashNone :: S2nTlsHashAlgorithm+pattern S2nTlsHashNone = S2nTlsHashAlgorithm 0++-- | MD5 hash (deprecated).+pattern S2nTlsHashMd5 :: S2nTlsHashAlgorithm+pattern S2nTlsHashMd5 = S2nTlsHashAlgorithm 1++-- | SHA-1 hash (deprecated).+pattern S2nTlsHashSha1 :: S2nTlsHashAlgorithm+pattern S2nTlsHashSha1 = S2nTlsHashAlgorithm 2++-- | SHA-224 hash.+pattern S2nTlsHashSha224 :: S2nTlsHashAlgorithm+pattern S2nTlsHashSha224 = S2nTlsHashAlgorithm 3++-- | SHA-256 hash.+pattern S2nTlsHashSha256 :: S2nTlsHashAlgorithm+pattern S2nTlsHashSha256 = S2nTlsHashAlgorithm 4++-- | SHA-384 hash.+pattern S2nTlsHashSha384 :: S2nTlsHashAlgorithm+pattern S2nTlsHashSha384 = S2nTlsHashAlgorithm 5++-- | SHA-512 hash.+pattern S2nTlsHashSha512 :: S2nTlsHashAlgorithm+pattern S2nTlsHashSha512 = S2nTlsHashAlgorithm 6++-- | Certificate SNI match result.+newtype S2nCertSniMatch = S2nCertSniMatch CInt+  deriving (Eq, Ord, Show, Storable)++-- | SNI matching not applicable.+pattern S2nCertSniMatchNotApplicable :: S2nCertSniMatch+pattern S2nCertSniMatchNotApplicable = S2nCertSniMatch 0++-- | Certificate matches SNI.+pattern S2nCertSniMatched :: S2nCertSniMatch+pattern S2nCertSniMatched = S2nCertSniMatch 1++-- | No matching certificate found.+pattern S2nCertSniNoMatchFound :: S2nCertSniMatch+pattern S2nCertSniNoMatchFound = S2nCertSniMatch 2++-- | Peer key update request type.+newtype S2nPeerKeyUpdate = S2nPeerKeyUpdate CInt+  deriving (Eq, Ord, Show, Storable)++-- | Key update not requested.+pattern S2nKeyUpdateNotRequested :: S2nPeerKeyUpdate+pattern S2nKeyUpdateNotRequested = S2nPeerKeyUpdate 0++-- | Key update requested.+pattern S2nKeyUpdateRequested :: S2nPeerKeyUpdate+pattern S2nKeyUpdateRequested = S2nPeerKeyUpdate 1++-- | Verify-after-sign mode for signatures.+newtype S2nVerifyAfterSign = S2nVerifyAfterSign CInt+  deriving (Eq, Ord, Show, Storable)++-- | Verification after signing disabled.+pattern S2nVerifyAfterSignDisabled :: S2nVerifyAfterSign+pattern S2nVerifyAfterSignDisabled = S2nVerifyAfterSign 0++-- | Verification after signing enabled.+pattern S2nVerifyAfterSignEnabled :: S2nVerifyAfterSign+pattern S2nVerifyAfterSignEnabled = S2nVerifyAfterSign 1++--------------------------------------------------------------------------------+-- Callback Types+--------------------------------------------------------------------------------++-- | Clock callback: returns current time in nanoseconds.+type S2nClockTimeNanoseconds = FunPtr (Ptr () -> Ptr Word64 -> IO CInt)++-- | Receive callback for custom I/O.+type S2nRecvFn = FunPtr (Ptr () -> Ptr Word8 -> Word32 -> IO CInt)++-- | Send callback for custom I/O.+type S2nSendFn = FunPtr (Ptr () -> Ptr Word8 -> Word32 -> IO CInt)++-- | Cache store callback.+type S2nCacheStoreCallback = FunPtr (Ptr S2nConnection -> Ptr () -> Word64 -> Ptr Word8 -> Word64 -> Ptr Word8 -> Word64 -> IO CInt)++-- | Cache retrieve callback.+type S2nCacheRetrieveCallback = FunPtr (Ptr S2nConnection -> Ptr () -> Ptr Word8 -> Word64 -> Ptr Word8 -> Ptr Word64 -> IO CInt)++-- | Cache delete callback.+type S2nCacheDeleteCallback = FunPtr (Ptr S2nConnection -> Ptr () -> Ptr Word8 -> Word64 -> IO CInt)++-- | Memory initialization callback.+type S2nMemInitCallback = FunPtr (IO CInt)++-- | Memory cleanup callback.+type S2nMemCleanupCallback = FunPtr (IO CInt)++-- | Memory allocation callback.+type S2nMemMallocCallback = FunPtr (Ptr (Ptr ()) -> Word32 -> Word32 -> IO CInt)++-- | Memory free callback.+type S2nMemFreeCallback = FunPtr (Ptr () -> Word32 -> IO CInt)++-- | Random initialization callback.+type S2nRandInitCallback = FunPtr (IO CInt)++-- | Random cleanup callback.+type S2nRandCleanupCallback = FunPtr (IO CInt)++-- | Random seed callback.+type S2nRandSeedCallback = FunPtr (Ptr () -> Word32 -> IO CInt)++-- | Random mix callback.+type S2nRandMixCallback = FunPtr (Ptr () -> Word32 -> IO CInt)++-- | Client hello callback.+type S2nClientHelloFn = FunPtr (Ptr S2nConnection -> Ptr () -> IO CInt)++-- | Certificate tiebreak callback.+type S2nCertTiebreakCallback = FunPtr (Ptr S2nCertChainAndKey -> Ptr S2nCertChainAndKey -> Word8 -> Ptr (Ptr S2nCertChainAndKey) -> IO CInt)++-- | Verify host callback.+type S2nVerifyHostFn = FunPtr (CString -> CSize -> Ptr () -> IO Word8)++-- | PSK selection callback.+type S2nPskSelectionCallback = FunPtr (Ptr S2nConnection -> Ptr () -> Ptr S2nOfferedPskList -> IO CInt)++-- | Async private key callback.+type S2nAsyncPkeyFn = FunPtr (Ptr S2nConnection -> Ptr S2nAsyncPkeyOp -> IO CInt)++-- | Session ticket callback.+type S2nSessionTicketFn = FunPtr (Ptr S2nConnection -> Ptr () -> Ptr S2nSessionTicket -> IO CInt)++-- | Key log callback (for debugging).+type S2nKeyLogFn = FunPtr (Ptr () -> Ptr S2nConnection -> Ptr Word8 -> CSize -> IO CInt)++-- | Early data callback.+type S2nEarlyDataCb = FunPtr (Ptr S2nConnection -> Ptr S2nOfferedEarlyData -> IO CInt)++--------------------------------------------------------------------------------+-- S2nTlsFfi Record+--------------------------------------------------------------------------------++{- | A record containing all FFI bindings to the s2n-tls library.++This record is populated by 'S2nTls.Ffi.withS2nTlsFfi' with the 'S2nTls.Ffi.Library'+parameter specifying either 'S2nTls.Ffi.Linked' or 'S2nTls.Ffi.Dynamic' loading.+-}+data S2nTlsFfi = S2nTlsFfi+  { missingSymbols :: [String]+  -- ^ List of symbol names that couldn't be loaded.+  -- Calling functions for these symbols will throw 'MissingSymbol'.+  , s2n_init :: IO (Either S2nError CInt)+  -- ^ __Initialization & Cleanup__+  , s2n_cleanup :: IO (Either S2nError CInt)+  , s2n_cleanup_final :: IO (Either S2nError CInt)+  , s2n_crypto_disable_init :: IO (Either S2nError CInt)+  , s2n_disable_atexit :: IO (Either S2nError CInt)+  , s2n_get_openssl_version :: IO CLong+  , s2n_get_fips_mode :: Ptr S2nFipsMode -> IO (Either S2nError CInt)+  , s2n_errno_location :: IO (Ptr CInt)+  -- ^ __Error Handling__+  , s2n_error_get_type :: CInt -> IO S2nErrorType+  , s2n_strerror :: CInt -> CString -> IO CString+  , s2n_strerror_debug :: CInt -> CString -> IO CString+  , s2n_strerror_name :: CInt -> IO CString+  , s2n_strerror_source :: CInt -> IO CString+  , s2n_stack_traces_enabled :: IO CBool+  -- ^ __Stack Traces__+  , s2n_stack_traces_enabled_set :: CInt -> IO (Either S2nError CInt)+  , s2n_calculate_stacktrace :: IO (Either S2nError CInt)+  , s2n_free_stacktrace :: IO (Either S2nError CInt)+  , s2n_get_stacktrace :: Ptr S2nStacktrace -> IO (Either S2nError CInt)+  , s2n_config_new :: IO (Either S2nError (Ptr S2nConfig))+  -- ^ __Config Management__+  , s2n_config_new_minimal :: IO (Either S2nError (Ptr S2nConfig))+  , s2n_config_free :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_free_dhparams :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_free_cert_chain_and_key :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_set_wall_clock :: Ptr S2nConfig -> S2nClockTimeNanoseconds -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_set_monotonic_clock :: Ptr S2nConfig -> S2nClockTimeNanoseconds -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_set_cache_store_callback :: Ptr S2nConfig -> S2nCacheStoreCallback -> Ptr () -> IO (Either S2nError CInt)+  -- ^ __Cache Callbacks__+  , s2n_config_set_cache_retrieve_callback :: Ptr S2nConfig -> S2nCacheRetrieveCallback -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_set_cache_delete_callback :: Ptr S2nConfig -> S2nCacheDeleteCallback -> Ptr () -> IO (Either S2nError CInt)+  , s2n_mem_set_callbacks :: S2nMemInitCallback -> S2nMemCleanupCallback -> S2nMemMallocCallback -> S2nMemFreeCallback -> IO (Either S2nError CInt)+  -- ^ __Memory & Random Callbacks__+  , s2n_rand_set_callbacks :: S2nRandInitCallback -> S2nRandCleanupCallback -> S2nRandSeedCallback -> S2nRandMixCallback -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_new :: IO (Either S2nError (Ptr S2nCertChainAndKey))+  -- ^ __Certificate Chain Management__+  , s2n_cert_chain_and_key_load_pem :: Ptr S2nCertChainAndKey -> CString -> CString -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_load_pem_bytes :: Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_load_public_pem_bytes :: Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_free :: Ptr S2nCertChainAndKey -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_set_ctx :: Ptr S2nCertChainAndKey -> Ptr () -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_get_ctx :: Ptr S2nCertChainAndKey -> IO (Ptr ())+  , s2n_cert_chain_and_key_get_private_key :: Ptr S2nCertChainAndKey -> IO (Either S2nError (Ptr S2nCertPrivateKey))+  , s2n_cert_chain_and_key_set_ocsp_data :: Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_cert_chain_and_key_set_sct_list :: Ptr S2nCertChainAndKey -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_config_set_cert_tiebreak_callback :: Ptr S2nConfig -> S2nCertTiebreakCallback -> IO (Either S2nError CInt)+  , s2n_config_add_cert_chain_and_key :: Ptr S2nConfig -> CString -> CString -> IO (Either S2nError CInt)+  , s2n_config_add_cert_chain_and_key_to_store :: Ptr S2nConfig -> Ptr S2nCertChainAndKey -> IO (Either S2nError CInt)+  , s2n_config_set_cert_chain_and_key_defaults :: Ptr S2nConfig -> Ptr (Ptr S2nCertChainAndKey) -> Word32 -> IO (Either S2nError CInt)+  , s2n_config_set_verification_ca_location :: Ptr S2nConfig -> CString -> CString -> IO (Either S2nError CInt)+  -- ^ __Trust Store__+  , s2n_config_add_pem_to_trust_store :: Ptr S2nConfig -> CString -> IO (Either S2nError CInt)+  , s2n_config_wipe_trust_store :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_load_system_certs :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_set_cert_authorities_from_trust_store :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_set_verify_after_sign :: Ptr S2nConfig -> S2nVerifyAfterSign -> IO (Either S2nError CInt)+  -- ^ __Verification & Validation__+  , s2n_config_set_check_stapled_ocsp_response :: Ptr S2nConfig -> CInt -> IO (Either S2nError CInt)+  , s2n_config_disable_x509_time_verification :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , -- , s2n_config_disable_x509_intent_verification :: Ptr S2nConfig -> IO (Either S2nError CInt)+    s2n_config_disable_x509_verification :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_set_max_cert_chain_depth :: Ptr S2nConfig -> Word16 -> IO (Either S2nError CInt)+  , s2n_config_set_verify_host_callback :: Ptr S2nConfig -> S2nVerifyHostFn -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_add_dhparams :: Ptr S2nConfig -> CString -> IO (Either S2nError CInt)+  -- ^ __DH Parameters__+  , s2n_config_set_cipher_preferences :: Ptr S2nConfig -> CString -> IO (Either S2nError CInt)+  -- ^ __Security Policies & Preferences__+  , s2n_config_append_protocol_preference :: Ptr S2nConfig -> Ptr Word8 -> Word8 -> IO (Either S2nError CInt)+  , s2n_config_set_protocol_preferences :: Ptr S2nConfig -> Ptr CString -> CInt -> IO (Either S2nError CInt)+  , s2n_config_set_status_request_type :: Ptr S2nConfig -> S2nStatusRequestType -> IO (Either S2nError CInt)+  , s2n_config_set_ct_support_level :: Ptr S2nConfig -> S2nCtSupportLevel -> IO (Either S2nError CInt)+  , s2n_config_set_alert_behavior :: Ptr S2nConfig -> S2nAlertBehavior -> IO (Either S2nError CInt)+  , s2n_config_set_extension_data :: Ptr S2nConfig -> S2nTlsExtensionType -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  -- ^ __Extension Data__+  , s2n_config_send_max_fragment_length :: Ptr S2nConfig -> S2nMaxFragLen -> IO (Either S2nError CInt)+  , s2n_config_accept_max_fragment_length :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_set_session_state_lifetime :: Ptr S2nConfig -> Word64 -> IO (Either S2nError CInt)+  -- ^ __Session & Ticket Configuration__+  , s2n_config_set_session_tickets_onoff :: Ptr S2nConfig -> Word8 -> IO (Either S2nError CInt)+  , s2n_config_set_session_cache_onoff :: Ptr S2nConfig -> Word8 -> IO (Either S2nError CInt)+  , s2n_config_set_ticket_encrypt_decrypt_key_lifetime :: Ptr S2nConfig -> Word64 -> IO (Either S2nError CInt)+  , s2n_config_set_ticket_decrypt_key_lifetime :: Ptr S2nConfig -> Word64 -> IO (Either S2nError CInt)+  , s2n_config_add_ticket_crypto_key :: Ptr S2nConfig -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Word64 -> IO (Either S2nError CInt)+  , s2n_config_require_ticket_forward_secrecy :: Ptr S2nConfig -> CInt -> IO (Either S2nError CInt)+  , s2n_config_set_send_buffer_size :: Ptr S2nConfig -> Word32 -> IO (Either S2nError CInt)+  -- ^ __Buffer & I\/O Configuration__+  , s2n_config_set_recv_multi_record :: Ptr S2nConfig -> CInt -> IO (Either S2nError CInt)+  , s2n_config_set_ctx :: Ptr S2nConfig -> Ptr () -> IO (Either S2nError CInt)+  -- ^ __Miscellaneous Config__+  , s2n_config_get_ctx :: Ptr S2nConfig -> Ptr (Ptr ()) -> IO (Either S2nError CInt)+  , s2n_config_set_client_hello_cb :: Ptr S2nConfig -> S2nClientHelloFn -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_set_client_hello_cb_mode :: Ptr S2nConfig -> S2nClientHelloCbMode -> IO (Either S2nError CInt)+  , s2n_config_set_max_blinding_delay :: Ptr S2nConfig -> Word32 -> IO (Either S2nError CInt)+  , s2n_config_get_client_auth_type :: Ptr S2nConfig -> Ptr S2nCertAuthType -> IO (Either S2nError CInt)+  , s2n_config_set_client_auth_type :: Ptr S2nConfig -> S2nCertAuthType -> IO (Either S2nError CInt)+  , s2n_config_set_initial_ticket_count :: Ptr S2nConfig -> Word8 -> IO (Either S2nError CInt)+  , s2n_config_set_psk_mode :: Ptr S2nConfig -> S2nPskMode -> IO (Either S2nError CInt)+  , s2n_config_set_psk_selection_callback :: Ptr S2nConfig -> S2nPskSelectionCallback -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_set_async_pkey_callback :: Ptr S2nConfig -> S2nAsyncPkeyFn -> IO (Either S2nError CInt)+  , s2n_config_set_async_pkey_validation_mode :: Ptr S2nConfig -> S2nAsyncPkeyValidationMode -> IO (Either S2nError CInt)+  , s2n_config_set_session_ticket_cb :: Ptr S2nConfig -> S2nSessionTicketFn -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_set_key_log_cb :: Ptr S2nConfig -> S2nKeyLogFn -> Ptr () -> IO (Either S2nError CInt)+  , s2n_config_enable_cert_req_dss_legacy_compat :: Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_config_set_server_max_early_data_size :: Ptr S2nConfig -> Word32 -> IO (Either S2nError CInt)+  , s2n_config_set_early_data_cb :: Ptr S2nConfig -> S2nEarlyDataCb -> IO (Either S2nError CInt)+  , s2n_config_get_supported_groups :: Ptr S2nConfig -> Ptr Word16 -> Word16 -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_config_set_serialization_version :: Ptr S2nConfig -> S2nSerializationVersion -> IO (Either S2nError CInt)+  , s2n_connection_new :: S2nMode -> IO (Either S2nError (Ptr S2nConnection))+  -- ^ __Connection Creation & Management__+  , s2n_connection_set_config :: Ptr S2nConnection -> Ptr S2nConfig -> IO (Either S2nError CInt)+  , s2n_connection_set_ctx :: Ptr S2nConnection -> Ptr () -> IO (Either S2nError CInt)+  , s2n_connection_get_ctx :: Ptr S2nConnection -> IO (Either S2nError (Ptr ()))+  , s2n_client_hello_cb_done :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_server_name_extension_used :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_client_hello :: Ptr S2nConnection -> IO (Either S2nError (Ptr S2nClientHello))+  -- ^ __Client Hello Access__+  , s2n_client_hello_parse_message :: Ptr Word8 -> Word32 -> IO (Either S2nError (Ptr S2nClientHello))+  , s2n_client_hello_free :: Ptr (Ptr S2nClientHello) -> IO (Either S2nError CInt)+  , s2n_client_hello_get_raw_message_length :: Ptr S2nClientHello -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_raw_message :: Ptr S2nClientHello -> Ptr Word8 -> Word32 -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_cipher_suites_length :: Ptr S2nClientHello -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_cipher_suites :: Ptr S2nClientHello -> Ptr Word8 -> Word32 -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_extensions_length :: Ptr S2nClientHello -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_extensions :: Ptr S2nClientHello -> Ptr Word8 -> Word32 -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_extension_length :: Ptr S2nClientHello -> S2nTlsExtensionType -> IO (Either S2nError CSsize)+  , s2n_client_hello_get_extension_by_id :: Ptr S2nClientHello -> S2nTlsExtensionType -> Ptr Word8 -> Word32 -> IO (Either S2nError CSsize)+  , s2n_client_hello_has_extension :: Ptr S2nClientHello -> Word16 -> Ptr CInt -> IO (Either S2nError CInt)+  , s2n_client_hello_get_session_id_length :: Ptr S2nClientHello -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_session_id :: Ptr S2nClientHello -> Ptr Word8 -> Ptr Word32 -> Word32 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_compression_methods_length :: Ptr S2nClientHello -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_compression_methods :: Ptr S2nClientHello -> Ptr Word8 -> Word32 -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_legacy_protocol_version :: Ptr S2nClientHello -> Ptr Word8 -> IO (Either S2nError CInt)+  , -- , s2n_client_hello_get_random :: Ptr S2nClientHello -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+    s2n_client_hello_get_supported_groups :: Ptr S2nClientHello -> Ptr Word16 -> Word16 -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_server_name_length :: Ptr S2nClientHello -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_server_name :: Ptr S2nClientHello -> Ptr Word8 -> Word16 -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_client_hello_get_legacy_record_version :: Ptr S2nClientHello -> Ptr Word8 -> IO (Either S2nError CInt)+  , s2n_connection_set_fd :: Ptr S2nConnection -> CInt -> IO (Either S2nError CInt)+  -- ^ __File Descriptor & I\/O__+  , s2n_connection_set_read_fd :: Ptr S2nConnection -> CInt -> IO (Either S2nError CInt)+  , s2n_connection_set_write_fd :: Ptr S2nConnection -> CInt -> IO (Either S2nError CInt)+  , s2n_connection_get_read_fd :: Ptr S2nConnection -> Ptr CInt -> IO (Either S2nError CInt)+  , s2n_connection_get_write_fd :: Ptr S2nConnection -> Ptr CInt -> IO (Either S2nError CInt)+  , s2n_connection_use_corked_io :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_set_recv_ctx :: Ptr S2nConnection -> Ptr () -> IO (Either S2nError CInt)+  , s2n_connection_set_send_ctx :: Ptr S2nConnection -> Ptr () -> IO (Either S2nError CInt)+  , s2n_connection_set_recv_cb :: Ptr S2nConnection -> S2nRecvFn -> IO (Either S2nError CInt)+  , s2n_connection_set_send_cb :: Ptr S2nConnection -> S2nSendFn -> IO (Either S2nError CInt)+  , s2n_connection_prefer_throughput :: Ptr S2nConnection -> IO (Either S2nError CInt)+  -- ^ __Connection Preferences__+  , s2n_connection_prefer_low_latency :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_set_recv_buffering :: Ptr S2nConnection -> CInt -> IO (Either S2nError CInt)+  , s2n_peek_buffered :: Ptr S2nConnection -> IO Word32+  , s2n_connection_set_dynamic_buffers :: Ptr S2nConnection -> CInt -> IO (Either S2nError CInt)+  , s2n_connection_set_dynamic_record_threshold :: Ptr S2nConnection -> Word32 -> Word16 -> IO (Either S2nError CInt)+  , s2n_connection_set_verify_host_callback :: Ptr S2nConnection -> S2nVerifyHostFn -> Ptr () -> IO (Either S2nError CInt)+  -- ^ __Host Verification__+  , s2n_connection_set_blinding :: Ptr S2nConnection -> S2nBlinding -> IO (Either S2nError CInt)+  -- ^ __Blinding & Security__+  , s2n_connection_get_delay :: Ptr S2nConnection -> IO Word64+  , s2n_connection_set_cipher_preferences :: Ptr S2nConnection -> CString -> IO (Either S2nError CInt)+  -- ^ __Cipher & Protocol Configuration__+  , s2n_connection_request_key_update :: Ptr S2nConnection -> S2nPeerKeyUpdate -> IO (Either S2nError CInt)+  , s2n_connection_append_protocol_preference :: Ptr S2nConnection -> Ptr Word8 -> Word8 -> IO (Either S2nError CInt)+  , s2n_connection_set_protocol_preferences :: Ptr S2nConnection -> Ptr CString -> CInt -> IO (Either S2nError CInt)+  , s2n_set_server_name :: Ptr S2nConnection -> CString -> IO (Either S2nError CInt)+  -- ^ __Server Name (SNI)__+  , s2n_get_server_name :: Ptr S2nConnection -> IO (Either S2nError CString)+  , s2n_get_application_protocol :: Ptr S2nConnection -> IO (Either S2nError CString)+  -- ^ __Application Protocol (ALPN)__+  , s2n_connection_get_ocsp_response :: Ptr S2nConnection -> Ptr Word32 -> IO (Either S2nError (Ptr Word8))+  -- ^ __OCSP & Certificate Transparency__+  , s2n_connection_get_sct_list :: Ptr S2nConnection -> Ptr Word32 -> IO (Either S2nError (Ptr Word8))+  , s2n_negotiate :: Ptr S2nConnection -> Ptr S2nBlockedStatus -> IO (Either S2nError CInt)+  -- ^ __Handshake & TLS Operations__+  , s2n_send :: Ptr S2nConnection -> Ptr () -> CSsize -> Ptr S2nBlockedStatus -> IO (Either S2nError CSsize)+  , s2n_recv :: Ptr S2nConnection -> Ptr () -> CSsize -> Ptr S2nBlockedStatus -> IO (Either S2nError CSsize)+  , s2n_peek :: Ptr S2nConnection -> IO Word32+  , s2n_connection_free_handshake :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_release_buffers :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_wipe :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_free :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_shutdown :: Ptr S2nConnection -> Ptr S2nBlockedStatus -> IO (Either S2nError CInt)+  , s2n_shutdown_send :: Ptr S2nConnection -> Ptr S2nBlockedStatus -> IO (Either S2nError CInt)+  , s2n_connection_get_client_auth_type :: Ptr S2nConnection -> Ptr S2nCertAuthType -> IO (Either S2nError CInt)+  -- ^ __Client Authentication__+  , s2n_connection_set_client_auth_type :: Ptr S2nConnection -> S2nCertAuthType -> IO (Either S2nError CInt)+  , s2n_connection_get_client_cert_chain :: Ptr S2nConnection -> Ptr (Ptr Word8) -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_connection_client_cert_used :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_add_new_tickets_to_send :: Ptr S2nConnection -> Word8 -> IO (Either S2nError CInt)+  -- ^ __Session Management__+  , s2n_connection_get_tickets_sent :: Ptr S2nConnection -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_connection_set_server_keying_material_lifetime :: Ptr S2nConnection -> Word32 -> IO (Either S2nError CInt)+  , s2n_session_ticket_get_data_len :: Ptr S2nSessionTicket -> Ptr CSize -> IO (Either S2nError CInt)+  , s2n_session_ticket_get_data :: Ptr S2nSessionTicket -> CSize -> Ptr Word8 -> IO (Either S2nError CInt)+  , s2n_session_ticket_get_lifetime :: Ptr S2nSessionTicket -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_connection_set_session :: Ptr S2nConnection -> Ptr Word8 -> CSize -> IO (Either S2nError CInt)+  , s2n_connection_get_session :: Ptr S2nConnection -> Ptr Word8 -> CSize -> IO (Either S2nError CInt)+  , s2n_connection_get_session_ticket_lifetime_hint :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_session_length :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_session_id_length :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_session_id :: Ptr S2nConnection -> Ptr Word8 -> CSize -> IO (Either S2nError CInt)+  , s2n_connection_is_session_resumed :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_is_ocsp_stapled :: Ptr S2nConnection -> IO (Either S2nError CInt)+  -- ^ __Certificate Information__+  , s2n_connection_get_selected_signature_algorithm :: Ptr S2nConnection -> Ptr S2nTlsSignatureAlgorithm -> IO (Either S2nError CInt)+  , s2n_connection_get_selected_digest_algorithm :: Ptr S2nConnection -> Ptr S2nTlsHashAlgorithm -> IO (Either S2nError CInt)+  , s2n_connection_get_selected_client_cert_signature_algorithm :: Ptr S2nConnection -> Ptr S2nTlsSignatureAlgorithm -> IO (Either S2nError CInt)+  , s2n_connection_get_selected_client_cert_digest_algorithm :: Ptr S2nConnection -> Ptr S2nTlsHashAlgorithm -> IO (Either S2nError CInt)+  , -- , s2n_connection_get_signature_scheme :: Ptr S2nConnection -> Ptr CString -> IO (Either S2nError CInt)+    s2n_connection_get_selected_cert :: Ptr S2nConnection -> IO (Either S2nError (Ptr S2nCertChainAndKey))+  , s2n_cert_chain_get_length :: Ptr S2nCertChainAndKey -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_cert_chain_get_cert :: Ptr S2nCertChainAndKey -> Ptr (Ptr S2nCert) -> Word32 -> IO (Either S2nError CInt)+  , s2n_cert_get_der :: Ptr S2nCert -> Ptr (Ptr Word8) -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_connection_get_peer_cert_chain :: Ptr S2nConnection -> Ptr S2nCertChainAndKey -> IO (Either S2nError CInt)+  , s2n_cert_get_x509_extension_value_length :: Ptr S2nCert -> Ptr Word8 -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_cert_get_x509_extension_value :: Ptr S2nCert -> Ptr Word8 -> Ptr Word8 -> Ptr Word32 -> Ptr CInt -> IO (Either S2nError CInt)+  , s2n_cert_get_utf8_string_from_extension_data_length :: Ptr Word8 -> Word32 -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_cert_get_utf8_string_from_extension_data :: Ptr Word8 -> Word32 -> Ptr Word8 -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_external_psk_new :: IO (Either S2nError (Ptr S2nPsk))+  -- ^ __Pre-Shared Keys (PSK)__+  , s2n_psk_free :: Ptr (Ptr S2nPsk) -> IO (Either S2nError CInt)+  , s2n_psk_set_identity :: Ptr S2nPsk -> Ptr Word8 -> Word16 -> IO (Either S2nError CInt)+  , s2n_psk_set_secret :: Ptr S2nPsk -> Ptr Word8 -> Word16 -> IO (Either S2nError CInt)+  , s2n_psk_set_hmac :: Ptr S2nPsk -> S2nPskHmac -> IO (Either S2nError CInt)+  , s2n_connection_append_psk :: Ptr S2nConnection -> Ptr S2nPsk -> IO (Either S2nError CInt)+  , s2n_connection_set_psk_mode :: Ptr S2nConnection -> S2nPskMode -> IO (Either S2nError CInt)+  , s2n_connection_get_negotiated_psk_identity_length :: Ptr S2nConnection -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_connection_get_negotiated_psk_identity :: Ptr S2nConnection -> Ptr Word8 -> Word16 -> IO (Either S2nError CInt)+  , s2n_offered_psk_new :: IO (Either S2nError (Ptr S2nOfferedPsk))+  , s2n_offered_psk_free :: Ptr (Ptr S2nOfferedPsk) -> IO (Either S2nError CInt)+  , s2n_offered_psk_get_identity :: Ptr S2nOfferedPsk -> Ptr (Ptr Word8) -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_offered_psk_list_has_next :: Ptr S2nOfferedPskList -> IO CBool+  , s2n_offered_psk_list_next :: Ptr S2nOfferedPskList -> Ptr S2nOfferedPsk -> IO (Either S2nError CInt)+  , s2n_offered_psk_list_reread :: Ptr S2nOfferedPskList -> IO (Either S2nError CInt)+  , s2n_offered_psk_list_choose_psk :: Ptr S2nOfferedPskList -> Ptr S2nOfferedPsk -> IO (Either S2nError CInt)+  , s2n_psk_configure_early_data :: Ptr S2nPsk -> Word32 -> Word8 -> Word8 -> IO (Either S2nError CInt)+  , s2n_psk_set_application_protocol :: Ptr S2nPsk -> Ptr Word8 -> Word8 -> IO (Either S2nError CInt)+  , s2n_psk_set_early_data_context :: Ptr S2nPsk -> Ptr Word8 -> Word16 -> IO (Either S2nError CInt)+  , s2n_connection_get_wire_bytes_in :: Ptr S2nConnection -> IO Word64+  -- ^ __Connection Statistics__+  , s2n_connection_get_wire_bytes_out :: Ptr S2nConnection -> IO Word64+  , s2n_connection_get_client_protocol_version :: Ptr S2nConnection -> IO (Either S2nError CInt)+  -- ^ __Protocol Version Information__+  , s2n_connection_get_server_protocol_version :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_actual_protocol_version :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_client_hello_version :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_cipher :: Ptr S2nConnection -> IO (Either S2nError CString)+  -- ^ __Cipher & Security Information__+  , s2n_connection_get_certificate_match :: Ptr S2nConnection -> Ptr S2nCertSniMatch -> IO (Either S2nError CInt)+  , s2n_connection_get_master_secret :: Ptr S2nConnection -> Ptr Word8 -> CSize -> IO (Either S2nError CInt)+  , s2n_connection_tls_exporter :: Ptr S2nConnection -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_connection_get_cipher_iana_value :: Ptr S2nConnection -> Ptr Word8 -> Ptr Word8 -> IO (Either S2nError CInt)+  , s2n_connection_is_valid_for_cipher_preferences :: Ptr S2nConnection -> CString -> IO (Either S2nError CInt)+  , s2n_connection_get_curve :: Ptr S2nConnection -> IO (Either S2nError CString)+  , s2n_connection_get_kem_name :: Ptr S2nConnection -> IO (Either S2nError CString)+  , s2n_connection_get_kem_group_name :: Ptr S2nConnection -> IO (Either S2nError CString)+  , s2n_connection_get_key_exchange_group :: Ptr S2nConnection -> Ptr CString -> IO (Either S2nError CInt)+  , s2n_connection_get_alert :: Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_connection_get_handshake_type_name :: Ptr S2nConnection -> IO (Either S2nError CString)+  , s2n_connection_get_last_message_name :: Ptr S2nConnection -> IO (Either S2nError CString)+  , s2n_async_pkey_op_perform :: Ptr S2nAsyncPkeyOp -> Ptr S2nCertPrivateKey -> IO (Either S2nError CInt)+  -- ^ __Async Private Key Operations__+  , s2n_async_pkey_op_apply :: Ptr S2nAsyncPkeyOp -> Ptr S2nConnection -> IO (Either S2nError CInt)+  , s2n_async_pkey_op_free :: Ptr S2nAsyncPkeyOp -> IO (Either S2nError CInt)+  , s2n_async_pkey_op_get_op_type :: Ptr S2nAsyncPkeyOp -> Ptr S2nAsyncPkeyOpType -> IO (Either S2nError CInt)+  , s2n_async_pkey_op_get_input_size :: Ptr S2nAsyncPkeyOp -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_async_pkey_op_get_input :: Ptr S2nAsyncPkeyOp -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_async_pkey_op_set_output :: Ptr S2nAsyncPkeyOp -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_connection_set_server_max_early_data_size :: Ptr S2nConnection -> Word32 -> IO (Either S2nError CInt)+  -- ^ __Early Data__+  , s2n_connection_set_server_early_data_context :: Ptr S2nConnection -> Ptr Word8 -> Word16 -> IO (Either S2nError CInt)+  , s2n_connection_get_early_data_status :: Ptr S2nConnection -> Ptr S2nEarlyDataStatus -> IO (Either S2nError CInt)+  , s2n_connection_get_remaining_early_data_size :: Ptr S2nConnection -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_connection_get_max_early_data_size :: Ptr S2nConnection -> Ptr Word32 -> IO (Either S2nError CInt)+  , s2n_send_early_data :: Ptr S2nConnection -> Ptr Word8 -> CSsize -> Ptr CSsize -> Ptr S2nBlockedStatus -> IO (Either S2nError CInt)+  , s2n_recv_early_data :: Ptr S2nConnection -> Ptr Word8 -> CSsize -> Ptr CSsize -> Ptr S2nBlockedStatus -> IO (Either S2nError CInt)+  , s2n_offered_early_data_get_context_length :: Ptr S2nOfferedEarlyData -> Ptr Word16 -> IO (Either S2nError CInt)+  , s2n_offered_early_data_get_context :: Ptr S2nOfferedEarlyData -> Ptr Word8 -> Word16 -> IO (Either S2nError CInt)+  , s2n_offered_early_data_reject :: Ptr S2nOfferedEarlyData -> IO (Either S2nError CInt)+  , s2n_offered_early_data_accept :: Ptr S2nOfferedEarlyData -> IO (Either S2nError CInt)+  , s2n_connection_serialization_length :: Ptr S2nConnection -> Ptr Word32 -> IO (Either S2nError CInt)+  -- ^ __Connection Serialization__+  , s2n_connection_serialize :: Ptr S2nConnection -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  , s2n_connection_deserialize :: Ptr S2nConnection -> Ptr Word8 -> Word32 -> IO (Either S2nError CInt)+  }
+ test/MemorySafety.hs view
@@ -0,0 +1,499 @@+{-# LANGUAGE NumericUnderscores #-}++{- |+Module      : Main+Description : Memory safety tests for s2n-tls FFI bindings++This test invokes all FFI functions to check for segfaults and memory errors.+Each function name is printed before invocation so crashes can be identified.+-}+module Main where++import Control.Exception (SomeException, catch)+import Control.Monad (void)+import Data.Word (Word16, Word32, Word8)+import Foreign.C.String (withCString)+import Foreign.C.Types (CInt (..))+import Foreign.Marshal.Alloc (alloca, allocaBytes)+import Foreign.Marshal.Array (allocaArray, pokeArray)+import Foreign.Ptr (Ptr, nullFunPtr, nullPtr)+import Foreign.Storable (poke)+import System.IO (hFlush, stdout)++import S2nTls.Ffi+import S2nTls.Ffi.Types++-- | Print function name and flush, then invoke it. Catches exceptions (only segfaults crash).+invoke :: String -> IO a -> IO ()+invoke name action = do+    putStrLn $ "  " ++ name+    hFlush stdout+    result <- (Right <$> action) `catch` \(e :: SomeException) -> pure (Left e)+    case result of+        Right _ -> pure ()+        Left _ -> pure () -- Exceptions are OK, we only care about segfaults++main :: IO ()+main = withS2nTlsFfi Linked $ \ffi -> do+    putStrLn "=== s2n-tls Memory Safety Tests ==="+    hFlush stdout++    runInitTests ffi+    runErrorTests ffi+    runStackTraceTests ffi+    runConfigTests ffi+    runCertChainTests ffi+    runConnectionTests ffi+    runPskTests ffi+    runCleanupTests ffi++    putStrLn "=== All tests completed ==="+    hFlush stdout++--------------------------------------------------------------------------------+-- Initialization Tests+--------------------------------------------------------------------------------++runInitTests :: S2nTlsFfi -> IO ()+runInitTests ffi = do+    putStrLn "\n[Initialization]"+    hFlush stdout+    invoke "s2n_init" $ s2n_init ffi+    invoke "s2n_crypto_disable_init" $ s2n_crypto_disable_init ffi+    invoke "s2n_disable_atexit" $ s2n_disable_atexit ffi+    invoke "s2n_get_openssl_version" $ s2n_get_openssl_version ffi+    alloca $ \ptr ->+        invoke "s2n_get_fips_mode" $ s2n_get_fips_mode ffi ptr++--------------------------------------------------------------------------------+-- Error Handling Tests+--------------------------------------------------------------------------------++runErrorTests :: S2nTlsFfi -> IO ()+runErrorTests ffi = do+    putStrLn "\n[Error Handling]"+    hFlush stdout+    invoke "s2n_errno_location" $ s2n_errno_location ffi+    invoke "s2n_error_get_type" $ s2n_error_get_type ffi 0+    withCString "EN" $ \lang -> do+        invoke "s2n_strerror" $ s2n_strerror ffi 0 lang+        invoke "s2n_strerror_debug" $ s2n_strerror_debug ffi 0 lang+    invoke "s2n_strerror_name" $ s2n_strerror_name ffi 0+    invoke "s2n_strerror_source" $ s2n_strerror_source ffi 0++--------------------------------------------------------------------------------+-- Stack Trace Tests+--------------------------------------------------------------------------------++runStackTraceTests :: S2nTlsFfi -> IO ()+runStackTraceTests ffi = do+    putStrLn "\n[Stack Traces]"+    hFlush stdout+    invoke "s2n_stack_traces_enabled" $ s2n_stack_traces_enabled ffi+    invoke "s2n_stack_traces_enabled_set" $ s2n_stack_traces_enabled_set ffi 0+    invoke "s2n_calculate_stacktrace" $ s2n_calculate_stacktrace ffi+    allocaBytes 8 $ \ptr ->+        invoke "s2n_get_stacktrace" $ s2n_get_stacktrace ffi ptr+    invoke "s2n_free_stacktrace" $ s2n_free_stacktrace ffi++--------------------------------------------------------------------------------+-- Config Tests+--------------------------------------------------------------------------------++runConfigTests :: S2nTlsFfi -> IO ()+runConfigTests ffi = do+    putStrLn "\n[Config]"+    hFlush stdout+    invoke "s2n_config_new" $ s2n_config_new ffi+    invoke "s2n_config_new_minimal" $ s2n_config_new_minimal ffi++    -- Run config operation tests with a fresh config+    withConfig ffi $ \cfg -> do+        putStrLn "\n[Config Operations]"+        hFlush stdout+        invoke "s2n_config_set_wall_clock" $ s2n_config_set_wall_clock ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_monotonic_clock" $ s2n_config_set_monotonic_clock ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_cache_store_callback" $ s2n_config_set_cache_store_callback ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_cache_retrieve_callback" $ s2n_config_set_cache_retrieve_callback ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_cache_delete_callback" $ s2n_config_set_cache_delete_callback ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_wipe_trust_store" $ s2n_config_wipe_trust_store ffi cfg+        invoke "s2n_config_load_system_certs" $ s2n_config_load_system_certs ffi cfg+        withCString "/nonexistent" $ \path ->+            invoke "s2n_config_set_verification_ca_location" $ s2n_config_set_verification_ca_location ffi cfg path nullPtr+        withCString "-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----" $ \pem ->+            invoke "s2n_config_add_pem_to_trust_store" $ s2n_config_add_pem_to_trust_store ffi cfg pem+        invoke "s2n_config_set_cert_authorities_from_trust_store" $ s2n_config_set_cert_authorities_from_trust_store ffi cfg+        invoke "s2n_config_set_verify_after_sign" $ s2n_config_set_verify_after_sign ffi cfg (S2nVerifyAfterSign 0)+        invoke "s2n_config_set_check_stapled_ocsp_response" $ s2n_config_set_check_stapled_ocsp_response ffi cfg 0+        invoke "s2n_config_disable_x509_time_verification" $ s2n_config_disable_x509_time_verification ffi cfg+        invoke "s2n_config_disable_x509_verification" $ s2n_config_disable_x509_verification ffi cfg+        invoke "s2n_config_set_max_cert_chain_depth" $ s2n_config_set_max_cert_chain_depth ffi cfg 10+        invoke "s2n_config_set_verify_host_callback" $ s2n_config_set_verify_host_callback ffi cfg nullFunPtr nullPtr+        withCString "-----BEGIN DH PARAMETERS-----\ntest\n-----END DH PARAMETERS-----" $ \dh ->+            invoke "s2n_config_add_dhparams" $ s2n_config_add_dhparams ffi cfg dh+        withCString "default_tls13" $ \policy ->+            invoke "s2n_config_set_cipher_preferences" $ s2n_config_set_cipher_preferences ffi cfg policy+        allocaArray 10 $ \protoPtr ->+            invoke "s2n_config_append_protocol_preference" $ s2n_config_append_protocol_preference ffi cfg protoPtr 5+        withCString "h2" $ \proto1 ->+            allocaArray 1 $ \protos -> do+                pokeArray protos [proto1]+                invoke "s2n_config_set_protocol_preferences" $ s2n_config_set_protocol_preferences ffi cfg protos 1+        invoke "s2n_config_set_status_request_type" $ s2n_config_set_status_request_type ffi cfg (S2nStatusRequestType 0)+        invoke "s2n_config_set_ct_support_level" $ s2n_config_set_ct_support_level ffi cfg (S2nCtSupportLevel 0)+        invoke "s2n_config_set_alert_behavior" $ s2n_config_set_alert_behavior ffi cfg (S2nAlertBehavior 0)+        allocaBytes 16 $ \buf ->+            invoke "s2n_config_set_extension_data" $ s2n_config_set_extension_data ffi cfg (S2nTlsExtensionType 0) buf 16+        invoke "s2n_config_send_max_fragment_length" $ s2n_config_send_max_fragment_length ffi cfg (S2nMaxFragLen 1)+        invoke "s2n_config_accept_max_fragment_length" $ s2n_config_accept_max_fragment_length ffi cfg+        invoke "s2n_config_set_session_state_lifetime" $ s2n_config_set_session_state_lifetime ffi cfg 3600+        invoke "s2n_config_set_session_tickets_onoff" $ s2n_config_set_session_tickets_onoff ffi cfg 1+        invoke "s2n_config_set_session_cache_onoff" $ s2n_config_set_session_cache_onoff ffi cfg 1+        invoke "s2n_config_set_ticket_encrypt_decrypt_key_lifetime" $ s2n_config_set_ticket_encrypt_decrypt_key_lifetime ffi cfg 3600+        invoke "s2n_config_set_ticket_decrypt_key_lifetime" $ s2n_config_set_ticket_decrypt_key_lifetime ffi cfg 7200+        allocaBytes 16 $ \keyName -> allocaBytes 32 $ \keyData ->+            invoke "s2n_config_add_ticket_crypto_key" $ s2n_config_add_ticket_crypto_key ffi cfg keyName 16 keyData 32 0+        invoke "s2n_config_require_ticket_forward_secrecy" $ s2n_config_require_ticket_forward_secrecy ffi cfg 1+        invoke "s2n_config_set_send_buffer_size" $ s2n_config_set_send_buffer_size ffi cfg 16384+        invoke "s2n_config_set_recv_multi_record" $ s2n_config_set_recv_multi_record ffi cfg 1+        invoke "s2n_config_set_client_hello_cb" $ s2n_config_set_client_hello_cb ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_client_hello_cb_mode" $ s2n_config_set_client_hello_cb_mode ffi cfg (S2nClientHelloCbMode 0)+        invoke "s2n_config_set_max_blinding_delay" $ s2n_config_set_max_blinding_delay ffi cfg 30+        alloca $ \authType ->+            invoke "s2n_config_get_client_auth_type" $ s2n_config_get_client_auth_type ffi cfg authType+        invoke "s2n_config_set_client_auth_type" $ s2n_config_set_client_auth_type ffi cfg (S2nCertAuthType 0)+        invoke "s2n_config_set_initial_ticket_count" $ s2n_config_set_initial_ticket_count ffi cfg 2+        invoke "s2n_config_set_psk_mode" $ s2n_config_set_psk_mode ffi cfg (S2nPskMode 0)+        invoke "s2n_config_set_psk_selection_callback" $ s2n_config_set_psk_selection_callback ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_async_pkey_callback" $ s2n_config_set_async_pkey_callback ffi cfg nullFunPtr+        invoke "s2n_config_set_async_pkey_validation_mode" $ s2n_config_set_async_pkey_validation_mode ffi cfg (S2nAsyncPkeyValidationMode 0)+        invoke "s2n_config_set_session_ticket_cb" $ s2n_config_set_session_ticket_cb ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_set_key_log_cb" $ s2n_config_set_key_log_cb ffi cfg nullFunPtr nullPtr+        invoke "s2n_config_enable_cert_req_dss_legacy_compat" $ s2n_config_enable_cert_req_dss_legacy_compat ffi cfg+        invoke "s2n_config_set_server_max_early_data_size" $ s2n_config_set_server_max_early_data_size ffi cfg 16384+        invoke "s2n_config_set_early_data_cb" $ s2n_config_set_early_data_cb ffi cfg nullFunPtr+        invoke "s2n_config_set_ctx" $ s2n_config_set_ctx ffi cfg nullPtr+        alloca $ \ctxPtr ->+            invoke "s2n_config_get_ctx" $ s2n_config_get_ctx ffi cfg ctxPtr+        allocaArray 10 $ \groups -> alloca $ \count ->+            invoke "s2n_config_get_supported_groups" $ s2n_config_get_supported_groups ffi cfg groups 10 count+        invoke "s2n_config_set_serialization_version" $ s2n_config_set_serialization_version ffi cfg (S2nSerializationVersion 0)+        invoke "s2n_config_set_cert_tiebreak_callback" $ s2n_config_set_cert_tiebreak_callback ffi cfg nullFunPtr+        withCString "" $ \emptyPath ->+            invoke "s2n_config_add_cert_chain_and_key" $ s2n_config_add_cert_chain_and_key ffi cfg emptyPath emptyPath+        invoke "s2n_config_free_dhparams" $ s2n_config_free_dhparams ffi cfg+        invoke "s2n_config_free_cert_chain_and_key" $ s2n_config_free_cert_chain_and_key ffi cfg++    -- Test s2n_config_free separately+    result <- s2n_config_new ffi+    case result of+        Left _ -> pure ()+        Right cfg -> invoke "s2n_config_free" $ s2n_config_free ffi cfg++-- | Helper to run tests with a fresh config+withConfig :: S2nTlsFfi -> (Ptr S2nConfig -> IO ()) -> IO ()+withConfig ffi action = do+    result <- s2n_config_new ffi+    case result of+        Left _ -> putStrLn "  [skipped - config creation failed]"+        Right cfg -> do+            action cfg+            void $ s2n_config_free ffi cfg++--------------------------------------------------------------------------------+-- Certificate Chain Tests+--------------------------------------------------------------------------------++runCertChainTests :: S2nTlsFfi -> IO ()+runCertChainTests ffi = do+    putStrLn "\n[Certificate Chain]"+    hFlush stdout+    invoke "s2n_cert_chain_and_key_new" $ s2n_cert_chain_and_key_new ffi++    withCertChain ffi $ \cert -> do+        withCString "-----BEGIN CERTIFICATE-----\ntest\n-----END CERTIFICATE-----" $ \pemCert ->+            withCString "-----BEGIN PRIVATE KEY-----\ntest\n-----END PRIVATE KEY-----" $ \pemKey ->+                invoke "s2n_cert_chain_and_key_load_pem" $ s2n_cert_chain_and_key_load_pem ffi cert pemCert pemKey+        allocaBytes 100 $ \certBuf -> allocaBytes 100 $ \keyBuf ->+            invoke "s2n_cert_chain_and_key_load_pem_bytes" $ s2n_cert_chain_and_key_load_pem_bytes ffi cert certBuf 100 keyBuf 100+        allocaBytes 100 $ \buf ->+            invoke "s2n_cert_chain_and_key_load_public_pem_bytes" $ s2n_cert_chain_and_key_load_public_pem_bytes ffi cert buf 100+        invoke "s2n_cert_chain_and_key_set_ctx" $ s2n_cert_chain_and_key_set_ctx ffi cert nullPtr+        invoke "s2n_cert_chain_and_key_get_ctx" $ s2n_cert_chain_and_key_get_ctx ffi cert+        invoke "s2n_cert_chain_and_key_get_private_key" $ s2n_cert_chain_and_key_get_private_key ffi cert+        allocaBytes 100 $ \buf ->+            invoke "s2n_cert_chain_and_key_set_ocsp_data" $ s2n_cert_chain_and_key_set_ocsp_data ffi cert buf 100+        allocaBytes 100 $ \buf ->+            invoke "s2n_cert_chain_and_key_set_sct_list" $ s2n_cert_chain_and_key_set_sct_list ffi cert buf 100+        alloca $ \lengthPtr ->+            invoke "s2n_cert_chain_get_length" $ s2n_cert_chain_get_length ffi cert lengthPtr+        alloca $ \certPtr ->+            invoke "s2n_cert_chain_get_cert" $ s2n_cert_chain_get_cert ffi cert certPtr 0++    -- Test s2n_cert_chain_and_key_free separately+    result <- s2n_cert_chain_and_key_new ffi+    case result of+        Left _ -> pure ()+        Right cert -> invoke "s2n_cert_chain_and_key_free" $ s2n_cert_chain_and_key_free ffi cert++-- | Helper to run tests with a fresh cert chain+withCertChain :: S2nTlsFfi -> (Ptr S2nCertChainAndKey -> IO ()) -> IO ()+withCertChain ffi action = do+    result <- s2n_cert_chain_and_key_new ffi+    case result of+        Left _ -> putStrLn "  [skipped - cert chain creation failed]"+        Right cert -> do+            action cert+            void $ s2n_cert_chain_and_key_free ffi cert++--------------------------------------------------------------------------------+-- Connection Tests+--------------------------------------------------------------------------------++runConnectionTests :: S2nTlsFfi -> IO ()+runConnectionTests ffi = do+    putStrLn "\n[Connection]"+    hFlush stdout+    invoke "s2n_connection_new (client)" $ s2n_connection_new ffi S2nClient+    invoke "s2n_connection_new (server)" $ s2n_connection_new ffi S2nServer++    withConnection ffi $ \conn -> do+        putStrLn "\n[Connection Operations]"+        hFlush stdout++        -- Config assignment+        cfgResult <- s2n_config_new ffi+        case cfgResult of+            Left _ -> pure ()+            Right cfg -> do+                invoke "s2n_connection_set_config" $ s2n_connection_set_config ffi conn cfg+                void $ s2n_config_free ffi cfg++        invoke "s2n_connection_set_ctx" $ s2n_connection_set_ctx ffi conn nullPtr+        invoke "s2n_connection_get_ctx" $ s2n_connection_get_ctx ffi conn+        invoke "s2n_client_hello_cb_done" $ s2n_client_hello_cb_done ffi conn+        invoke "s2n_connection_server_name_extension_used" $ s2n_connection_server_name_extension_used ffi conn+        invoke "s2n_connection_get_client_hello" $ s2n_connection_get_client_hello ffi conn+        allocaBytes 100 $ \buf ->+            invoke "s2n_client_hello_parse_message" $ s2n_client_hello_parse_message ffi buf 100+        invoke "s2n_connection_set_fd" $ s2n_connection_set_fd ffi conn (-1)+        invoke "s2n_connection_set_read_fd" $ s2n_connection_set_read_fd ffi conn (-1)+        invoke "s2n_connection_set_write_fd" $ s2n_connection_set_write_fd ffi conn (-1)+        alloca $ \fdPtr -> do+            invoke "s2n_connection_get_read_fd" $ s2n_connection_get_read_fd ffi conn fdPtr+            invoke "s2n_connection_get_write_fd" $ s2n_connection_get_write_fd ffi conn fdPtr+        invoke "s2n_connection_use_corked_io" $ s2n_connection_use_corked_io ffi conn+        invoke "s2n_connection_set_recv_ctx" $ s2n_connection_set_recv_ctx ffi conn nullPtr+        invoke "s2n_connection_set_send_ctx" $ s2n_connection_set_send_ctx ffi conn nullPtr+        invoke "s2n_connection_set_recv_cb" $ s2n_connection_set_recv_cb ffi conn nullFunPtr+        invoke "s2n_connection_set_send_cb" $ s2n_connection_set_send_cb ffi conn nullFunPtr+        invoke "s2n_connection_prefer_throughput" $ s2n_connection_prefer_throughput ffi conn+        invoke "s2n_connection_prefer_low_latency" $ s2n_connection_prefer_low_latency ffi conn+        invoke "s2n_connection_set_recv_buffering" $ s2n_connection_set_recv_buffering ffi conn 1+        invoke "s2n_peek_buffered" $ s2n_peek_buffered ffi conn+        invoke "s2n_connection_set_dynamic_buffers" $ s2n_connection_set_dynamic_buffers ffi conn 1+        invoke "s2n_connection_set_dynamic_record_threshold" $ s2n_connection_set_dynamic_record_threshold ffi conn 1400 100+        invoke "s2n_connection_set_verify_host_callback" $ s2n_connection_set_verify_host_callback ffi conn nullFunPtr nullPtr+        invoke "s2n_connection_set_blinding" $ s2n_connection_set_blinding ffi conn S2nSelfServiceBlinding+        invoke "s2n_connection_get_delay" $ s2n_connection_get_delay ffi conn+        withCString "default_tls13" $ \policy ->+            invoke "s2n_connection_set_cipher_preferences" $ s2n_connection_set_cipher_preferences ffi conn policy+        invoke "s2n_connection_request_key_update" $ s2n_connection_request_key_update ffi conn (S2nPeerKeyUpdate 0)+        allocaBytes 10 $ \proto ->+            invoke "s2n_connection_append_protocol_preference" $ s2n_connection_append_protocol_preference ffi conn proto 5+        withCString "h2" $ \proto1 ->+            allocaArray 1 $ \protos -> do+                pokeArray protos [proto1]+                invoke "s2n_connection_set_protocol_preferences" $ s2n_connection_set_protocol_preferences ffi conn protos 1+        withCString "example.com" $ \name ->+            invoke "s2n_set_server_name" $ s2n_set_server_name ffi conn name+        invoke "s2n_get_server_name" $ s2n_get_server_name ffi conn+        invoke "s2n_get_application_protocol" $ s2n_get_application_protocol ffi conn+        alloca $ \lenPtr -> do+            invoke "s2n_connection_get_ocsp_response" $ s2n_connection_get_ocsp_response ffi conn lenPtr+            invoke "s2n_connection_get_sct_list" $ s2n_connection_get_sct_list ffi conn lenPtr+        alloca $ \blocked -> do+            invoke "s2n_negotiate" $ s2n_negotiate ffi conn blocked+            allocaBytes 100 $ \buf -> do+                invoke "s2n_send" $ s2n_send ffi conn buf 100 blocked+                invoke "s2n_recv" $ s2n_recv ffi conn buf 100 blocked+            invoke "s2n_shutdown" $ s2n_shutdown ffi conn blocked+            invoke "s2n_shutdown_send" $ s2n_shutdown_send ffi conn blocked+        invoke "s2n_peek" $ s2n_peek ffi conn+        alloca $ \authType ->+            invoke "s2n_connection_get_client_auth_type" $ s2n_connection_get_client_auth_type ffi conn authType+        invoke "s2n_connection_set_client_auth_type" $ s2n_connection_set_client_auth_type ffi conn (S2nCertAuthType 0)+        alloca $ \certPtr -> alloca $ \lenPtr ->+            invoke "s2n_connection_get_client_cert_chain" $ s2n_connection_get_client_cert_chain ffi conn certPtr lenPtr+        invoke "s2n_connection_client_cert_used" $ s2n_connection_client_cert_used ffi conn+        invoke "s2n_connection_add_new_tickets_to_send" $ s2n_connection_add_new_tickets_to_send ffi conn 1+        alloca $ \ticketsPtr ->+            invoke "s2n_connection_get_tickets_sent" $ s2n_connection_get_tickets_sent ffi conn ticketsPtr+        invoke "s2n_connection_set_server_keying_material_lifetime" $ s2n_connection_set_server_keying_material_lifetime ffi conn 86400+        allocaBytes 256 $ \buf -> do+            invoke "s2n_connection_set_session" $ s2n_connection_set_session ffi conn buf 256+            invoke "s2n_connection_get_session" $ s2n_connection_get_session ffi conn buf 256+        invoke "s2n_connection_get_session_ticket_lifetime_hint" $ s2n_connection_get_session_ticket_lifetime_hint ffi conn+        invoke "s2n_connection_get_session_length" $ s2n_connection_get_session_length ffi conn+        invoke "s2n_connection_get_session_id_length" $ s2n_connection_get_session_id_length ffi conn+        allocaBytes 32 $ \buf ->+            invoke "s2n_connection_get_session_id" $ s2n_connection_get_session_id ffi conn buf 32+        invoke "s2n_connection_is_session_resumed" $ s2n_connection_is_session_resumed ffi conn+        invoke "s2n_connection_is_ocsp_stapled" $ s2n_connection_is_ocsp_stapled ffi conn+        alloca $ \sigAlg -> do+            invoke "s2n_connection_get_selected_signature_algorithm" $ s2n_connection_get_selected_signature_algorithm ffi conn sigAlg+            invoke "s2n_connection_get_selected_client_cert_signature_algorithm" $ s2n_connection_get_selected_client_cert_signature_algorithm ffi conn sigAlg+        alloca $ \hashAlg -> do+            invoke "s2n_connection_get_selected_digest_algorithm" $ s2n_connection_get_selected_digest_algorithm ffi conn hashAlg+            invoke "s2n_connection_get_selected_client_cert_digest_algorithm" $ s2n_connection_get_selected_client_cert_digest_algorithm ffi conn hashAlg+        invoke "s2n_connection_get_selected_cert" $ s2n_connection_get_selected_cert ffi conn+        certResult <- s2n_cert_chain_and_key_new ffi+        case certResult of+            Left _ -> pure ()+            Right peerCert -> do+                invoke "s2n_connection_get_peer_cert_chain" $ s2n_connection_get_peer_cert_chain ffi conn peerCert+                void $ s2n_cert_chain_and_key_free ffi peerCert+        invoke "s2n_connection_get_wire_bytes_in" $ s2n_connection_get_wire_bytes_in ffi conn+        invoke "s2n_connection_get_wire_bytes_out" $ s2n_connection_get_wire_bytes_out ffi conn+        invoke "s2n_connection_get_client_protocol_version" $ s2n_connection_get_client_protocol_version ffi conn+        invoke "s2n_connection_get_server_protocol_version" $ s2n_connection_get_server_protocol_version ffi conn+        invoke "s2n_connection_get_actual_protocol_version" $ s2n_connection_get_actual_protocol_version ffi conn+        invoke "s2n_connection_get_client_hello_version" $ s2n_connection_get_client_hello_version ffi conn+        invoke "s2n_connection_get_cipher" $ s2n_connection_get_cipher ffi conn+        alloca $ \sniMatch ->+            invoke "s2n_connection_get_certificate_match" $ s2n_connection_get_certificate_match ffi conn sniMatch+        allocaBytes 48 $ \buf ->+            invoke "s2n_connection_get_master_secret" $ s2n_connection_get_master_secret ffi conn buf 48+        allocaBytes 32 $ \label -> allocaBytes 32 $ \context -> allocaBytes 32 $ \output ->+            invoke "s2n_connection_tls_exporter" $ s2n_connection_tls_exporter ffi conn label 32 context 32 output 32+        alloca $ \first -> alloca $ \second ->+            invoke "s2n_connection_get_cipher_iana_value" $ s2n_connection_get_cipher_iana_value ffi conn first second+        withCString "default_tls13" $ \policy ->+            invoke "s2n_connection_is_valid_for_cipher_preferences" $ s2n_connection_is_valid_for_cipher_preferences ffi conn policy+        invoke "s2n_connection_get_curve" $ s2n_connection_get_curve ffi conn+        invoke "s2n_connection_get_kem_name" $ s2n_connection_get_kem_name ffi conn+        invoke "s2n_connection_get_kem_group_name" $ s2n_connection_get_kem_group_name ffi conn+        alloca $ \groupName ->+            invoke "s2n_connection_get_key_exchange_group" $ s2n_connection_get_key_exchange_group ffi conn groupName+        invoke "s2n_connection_get_alert" $ s2n_connection_get_alert ffi conn+        invoke "s2n_connection_get_handshake_type_name" $ s2n_connection_get_handshake_type_name ffi conn+        invoke "s2n_connection_get_last_message_name" $ s2n_connection_get_last_message_name ffi conn+        invoke "s2n_connection_set_psk_mode" $ s2n_connection_set_psk_mode ffi conn (S2nPskMode 0)+        alloca $ \lenPtr ->+            invoke "s2n_connection_get_negotiated_psk_identity_length" $ s2n_connection_get_negotiated_psk_identity_length ffi conn lenPtr+        allocaBytes 32 $ \buf ->+            invoke "s2n_connection_get_negotiated_psk_identity" $ s2n_connection_get_negotiated_psk_identity ffi conn buf 32+        invoke "s2n_connection_set_server_max_early_data_size" $ s2n_connection_set_server_max_early_data_size ffi conn 16384+        allocaBytes 100 $ \ctx ->+            invoke "s2n_connection_set_server_early_data_context" $ s2n_connection_set_server_early_data_context ffi conn ctx 100+        alloca $ \status ->+            invoke "s2n_connection_get_early_data_status" $ s2n_connection_get_early_data_status ffi conn status+        alloca $ \remaining ->+            invoke "s2n_connection_get_remaining_early_data_size" $ s2n_connection_get_remaining_early_data_size ffi conn remaining+        alloca $ \maxSize ->+            invoke "s2n_connection_get_max_early_data_size" $ s2n_connection_get_max_early_data_size ffi conn maxSize+        alloca $ \blocked -> allocaBytes 100 $ \buf -> alloca $ \written -> do+            invoke "s2n_send_early_data" $ s2n_send_early_data ffi conn buf 100 written blocked+            invoke "s2n_recv_early_data" $ s2n_recv_early_data ffi conn buf 100 written blocked+        alloca $ \lenPtr ->+            invoke "s2n_connection_serialization_length" $ s2n_connection_serialization_length ffi conn lenPtr+        allocaBytes 1024 $ \buf -> do+            invoke "s2n_connection_serialize" $ s2n_connection_serialize ffi conn buf 1024+            invoke "s2n_connection_deserialize" $ s2n_connection_deserialize ffi conn buf 1024+        invoke "s2n_connection_free_handshake" $ s2n_connection_free_handshake ffi conn+        invoke "s2n_connection_release_buffers" $ s2n_connection_release_buffers ffi conn+        invoke "s2n_connection_wipe" $ s2n_connection_wipe ffi conn++    -- Test s2n_connection_free separately+    result <- s2n_connection_new ffi S2nClient+    case result of+        Left _ -> pure ()+        Right conn -> invoke "s2n_connection_free" $ s2n_connection_free ffi conn++-- | Helper to run tests with a fresh connection+withConnection :: S2nTlsFfi -> (Ptr S2nConnection -> IO ()) -> IO ()+withConnection ffi action = do+    result <- s2n_connection_new ffi S2nClient+    case result of+        Left _ -> putStrLn "  [skipped - connection creation failed]"+        Right conn -> do+            action conn+            void $ s2n_connection_free ffi conn++--------------------------------------------------------------------------------+-- PSK Tests+--------------------------------------------------------------------------------++runPskTests :: S2nTlsFfi -> IO ()+runPskTests ffi = do+    putStrLn "\n[PSK]"+    hFlush stdout+    invoke "s2n_external_psk_new" $ s2n_external_psk_new ffi++    withPsk ffi $ \psk -> do+        allocaBytes 32 $ \identity ->+            invoke "s2n_psk_set_identity" $ s2n_psk_set_identity ffi psk identity 32+        allocaBytes 32 $ \secret ->+            invoke "s2n_psk_set_secret" $ s2n_psk_set_secret ffi psk secret 32+        invoke "s2n_psk_set_hmac" $ s2n_psk_set_hmac ffi psk S2nPskHmacSha256+        invoke "s2n_psk_configure_early_data" $ s2n_psk_configure_early_data ffi psk 16384 33 34+        allocaBytes 10 $ \proto ->+            invoke "s2n_psk_set_application_protocol" $ s2n_psk_set_application_protocol ffi psk proto 10+        allocaBytes 32 $ \ctx ->+            invoke "s2n_psk_set_early_data_context" $ s2n_psk_set_early_data_context ffi psk ctx 32++    -- Test s2n_connection_append_psk+    pskResult <- s2n_external_psk_new ffi+    connResult <- s2n_connection_new ffi S2nClient+    case (pskResult, connResult) of+        (Right psk, Right conn) -> do+            invoke "s2n_connection_append_psk" $ s2n_connection_append_psk ffi conn psk+            void $ s2n_connection_free ffi conn+            alloca $ \pskPtr -> do+                poke pskPtr psk+                void $ s2n_psk_free ffi pskPtr+        _ -> pure ()++    -- Test s2n_psk_free+    pskResult2 <- s2n_external_psk_new ffi+    case pskResult2 of+        Left _ -> pure ()+        Right psk ->+            alloca $ \pskPtr -> do+                poke pskPtr psk+                invoke "s2n_psk_free" $ s2n_psk_free ffi pskPtr++    -- Test offered PSK functions+    invoke "s2n_offered_psk_new" $ s2n_offered_psk_new ffi+    offeredResult <- s2n_offered_psk_new ffi+    case offeredResult of+        Left _ -> pure ()+        Right offered -> do+            alloca $ \identityPtr -> alloca $ \lenPtr ->+                invoke "s2n_offered_psk_get_identity" $ s2n_offered_psk_get_identity ffi offered identityPtr lenPtr+            alloca $ \offeredPtr -> do+                poke offeredPtr offered+                invoke "s2n_offered_psk_free" $ s2n_offered_psk_free ffi offeredPtr++-- | Helper to run tests with a fresh PSK+withPsk :: S2nTlsFfi -> (Ptr S2nPsk -> IO ()) -> IO ()+withPsk ffi action = do+    result <- s2n_external_psk_new ffi+    case result of+        Left _ -> putStrLn "  [skipped - PSK creation failed]"+        Right psk -> do+            action psk+            alloca $ \pskPtr -> do+                poke pskPtr psk+                void $ s2n_psk_free ffi pskPtr++--------------------------------------------------------------------------------+-- Cleanup Tests+--------------------------------------------------------------------------------++runCleanupTests :: S2nTlsFfi -> IO ()+runCleanupTests ffi = do+    putStrLn "\n[Cleanup]"+    hFlush stdout+    invoke "s2n_cleanup" $ s2n_cleanup ffi+    invoke "s2n_cleanup_final" $ s2n_cleanup_final ffi