@hackage warp-s2n-tls0.1.0.0

TLS support for Warp via s2n-tls

warp-s2n-tls

TLS support for the Warp web server using s2n-tls.

Overview

This library provides an alternative to warp-tls by using AWS's s2n-tls library for TLS termination instead of the Haskell tls package.

Usage

import Network.Wai.Handler.WarpS2N
import Network.Wai.Handler.Warp (defaultSettings, setPort)
import Network.Wai (Application)

main :: IO ()
main = do
    let tlsSet = tlsSettings "cert.pem" "key.pem"
    runTLS tlsSet defaultSettings myApp

myApp :: Application
myApp = ...

Dynamic library loading

To load libs2n.so at runtime instead of linking:

main :: IO ()
main = withS2nTls (Dynamic "/usr/local/lib/libs2n.so") $ \tls -> do
    runTLSLib tls tlsSet warpSet myApp

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

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.

Development

Running tests

Tests require S2N_DONT_MLOCK=1 to avoid exhausting the default mlock limit:

S2N_DONT_MLOCK=1 cabal test

See the Memory Locking section above for details.

  • s2n-tls - High-level Haskell bindings (used internally by this package)
  • s2n-tls-ffi - Low-level FFI bindings for direct s2n-tls access

License

Apache-2.0