- C 39.7%
- Shell 26.8%
- Scheme 25.1%
- Makefile 8.1%
- Common Lisp 0.3%
| .builds | ||
| .jerboa | ||
| docs | ||
| scripts | ||
| src | ||
| support | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| jerboa_ssl_shim.c | ||
| jpkg.sexp | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| SECURITY.md | ||
jerboa-ssl
TLS-encrypted TCP socket connections for Jerboa via FFI to OpenSSL.
This library provides the raw TLS transport layer — connect, read, write, close. It does not implement HTTP. It is intended as a building block for higher-level libraries like jerboa-https.
Why
Jerboa currently delegates TLS to native libraries. Without this shim, talking to HTTPS services requires shelling out to a tool such as curl for every request, which spawns a subprocess each time. This library gives Jerboa clients native TLS sockets with no subprocess overhead.
Requirements
- Jerboa and
jerbuild - A supported, patched OpenSSL development package. Release evidence currently accepts OpenSSL 4.0.1+, 3.6.3+, 3.5.7+, 3.4.6+, or 3.0.21+.
- Linux x86_64
- GCC
On Debian/Ubuntu:
sudo apt install build-essential libssl-dev
Build
make
This compiles jerboa_ssl_shim.c into jerboa_ssl_shim.so or
jerboa_ssl_shim.dylib.
Test
make security
make test
make audit
make sbom
make openssl-advisory-check
make reproducibility-report
make target-evidence
make release-evidence
Connects to example.com:443 over TLS, sends an HTTP GET, and verifies the response.
The release-evidence target archives OpenSSL advisory status, native linkage,
SBOM/platform support notes, source/artifact hashes, target-deployment proof
status, and hash-only reproducibility output. Target proof markers are supplied
with JSSL_TARGET_PROOF_FILE; set JSSL_REQUIRE_TARGET_PROOF=1 to fail a
release when the proof is missing.
Usage
(import (jerboa-ssl))
(ssl-init!)
(let ([conn (ssl-connect "example.com" 443)])
(ssl-write-string conn
"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
;; Refuse responses larger than 1 MiB or slower than 15 seconds total.
(let ([response (utf8->string (ssl-read-all conn 1048576 15))])
(display response))
(ssl-close conn))
(ssl-cleanup!)
To use the library from another project, add the generated lib/ directory to
the Jerboa library path:
jerbuild exec --libdirs /path/to/jerboa-ssl/lib your-program.ss
Production executables must statically link and register the SSL shim; the
library never searches the current directory or a bare platform-loader name.
Interpreter development may set JERBOA_SSL_ALLOW_DYNAMIC_NATIVE=1 together
with an absolute, canonical JERBOA_SSL_LIB directory. The library and every
ancestor must have an expected root/current-user owner and safe mode;
privileged processes ignore both variables. Dynamic loading is
rejected for root or real/effective-ID-mismatched processes and is not a
production deployment mechanism.
API Reference
(ssl-init!)
Initialize OpenSSL. Call once at program start. Safe to call multiple times (idempotent).
(ssl-cleanup!)
Release OpenSSL global resources. Call at program shutdown.
(ssl-connect hostname port) -> connection
Connect to hostname (string) on port (integer) over TLS.
- Resolves DNS via
getaddrinfo(IPv4 and IPv6) - Creates a TCP socket and connects
- Sets up TLS with SNI (
SSL_set_tlsext_host_name) and OpenSSL certificate name verification - Verifies the server certificate against system CA roots
- Returns an opaque connection handle
Raises an exception with a descriptive error message on failure (DNS resolution, connection refused, TLS handshake error, certificate verification failure).
(ssl-write conn bytevector) -> void
Write the entire bytevector to the connection. Handles partial writes internally (loops until all bytes are sent). Raises on error.
(ssl-write-string conn string) -> void
Convenience wrapper — converts the string to UTF-8 and calls ssl-write.
(ssl-read conn bytevector length) -> integer
Low-level read. Reads up to length bytes into bytevector. Returns the number of bytes actually read, or 0 on EOF.
(let ([buf (make-bytevector 4096)])
(let ([n (ssl-read conn buf 4096)])
(display (format "Read ~a bytes\n" n))))
(ssl-read-all conn max-bytes timeout-seconds) -> bytevector
High-level bounded read. Reads until the peer closes the connection and returns
a single bytevector. max-bytes is a hard body limit and timeout-seconds is a
total deadline, not a per-read timeout. Limit and deadline violations raise
distinct errors. Callers that need larger or longer transfers should stream
them through ssl-read with protocol-specific limits.
(ssl-close conn) -> void
Shut down the TLS session and close the underlying TCP socket. Frees all associated resources. Safe to call multiple times.
(ssl-connection? obj) -> boolean
Returns #t if obj is an active (not yet closed) SSL connection.
Architecture
jerboa-ssl/
├── jerboa_ssl_shim.c C shim (OpenSSL FFI wrapper)
├── src/
│ └── jerboa-ssl.ss Jerboa source library
├── tests/
│ └── ssl-test.ss Integration test
├── Makefile
└── README.md
The C shim (jerboa_ssl_shim.c) wraps OpenSSL into simple C functions that
Jerboa's FFI can call. It manages a jerboa_ssl_conn struct that bundles the
SSL*, SSL_CTX*, and socket file descriptor together. The Scheme side passes
this around as an opaque void* integer.
Why a C shim?
The FFI can call C functions directly, but OpenSSL's API involves:
- Structs that must be allocated and threaded through multiple calls
- Macros (
SSL_set_tlsext_host_name) that can't be called from FFI - Multi-step workflows (DNS lookup, socket connect, TLS handshake) that are simpler in C
The shim collapses each workflow into a single callable function.
Notes for AWS
- SNI is mandatory. AWS rejects TLS connections without Server Name Indication. This library sets SNI automatically via
SSL_set_tlsext_host_name. - Certificate verification is enabled. The library loads system CA certificates and verifies the server's certificate chain, including hostname or IP-address matching.
- Connection reuse. This library provides raw TLS transport. For high-throughput use (thousands of requests), implement HTTP/1.1 keep-alive and connection pooling at the HTTP layer above this.
License
See LICENSE.