Skip to content

Commit 44e31ac

Browse files
authored
Merge pull request #570 from julek-wolfssl/ocsp-responder-examples
Add OCSP responder examples
2 parents 011d7f3 + e9a5c75 commit 44e31ac

8 files changed

Lines changed: 1273 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ hash/sha512-hash
313313
ocsp/ocsp_nonblock/ocsp_nonblock
314314
ocsp/stapling/ocsp-client
315315
ocsp/stapling/ocsp-server
316+
ocsp/responder/ocsp-request-response
317+
ocsp/responder/ocsp-responder-http
316318

317319
sslkeylog.log
318320

ocsp/responder/Makefile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Makefile for OCSP Responder Examples
2+
#
3+
# wolfSSL must be built with:
4+
# ./configure --enable-ocsp --enable-ocsp-responder
5+
# make && sudo make install
6+
7+
CC = gcc
8+
WOLFSSL_INSTALL_DIR = /usr/local
9+
CFLAGS = -Wall -Wextra -g -I$(WOLFSSL_INSTALL_DIR)/include
10+
LIBS = -L$(WOLFSSL_INSTALL_DIR)/lib -lwolfssl
11+
12+
# Uncomment for static linking:
13+
# LIBS = $(WOLFSSL_INSTALL_DIR)/lib/libwolfssl.a -lm -lpthread
14+
15+
SRC = $(wildcard *.c)
16+
TARGETS = $(patsubst %.c, %, $(SRC))
17+
18+
all: $(TARGETS)
19+
20+
%: %.c
21+
$(CC) -o $@ $< $(CFLAGS) $(LIBS)
22+
23+
clean:
24+
rm -f $(TARGETS)

ocsp/responder/README.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# OCSP Responder Examples
2+
3+
Examples demonstrating the wolfSSL OCSP Responder API added in
4+
[wolfSSL/wolfssl#9761](https://github.com/wolfSSL/wolfssl/pull/9761).
5+
6+
## Prerequisites
7+
8+
Build and install wolfSSL with OCSP responder support:
9+
10+
```sh
11+
cd wolfssl
12+
./configure --enable-ocsp --enable-ocsp-responder
13+
make
14+
sudo make install
15+
sudo ldconfig
16+
```
17+
18+
## Examples
19+
20+
### 1. Raw DER Request/Response (`ocsp-request-response.c`)
21+
22+
Demonstrates the core API without any networking:
23+
24+
- Parse a certificate and build a DER-encoded OCSP request
25+
(`wc_InitOcspRequest`, `wc_EncodeOcspRequest`)
26+
- Create an `OcspResponder`, register a signer, and set certificate statuses
27+
(`wc_OcspResponder_new`, `wc_OcspResponder_AddSigner`,
28+
`wc_OcspResponder_SetCertStatus`)
29+
- Generate a signed OCSP response from the request
30+
(`wc_OcspResponder_WriteResponse`)
31+
- Verify the response against a `WOLFSSL_CERT_MANAGER`
32+
(`wc_CheckCertOcspResponse`)
33+
- Show REVOKED status and error response generation
34+
35+
```sh
36+
make ocsp-request-response
37+
./ocsp-request-response
38+
```
39+
40+
Uses the wolfSSL test certs in `../../certs/` by default.
41+
42+
### 2. Minimal HTTP Responder (`ocsp-responder-http.c`)
43+
44+
A tiny HTTP server that accepts POST requests containing DER OCSP requests and
45+
returns DER OCSP responses. Kept as small as possible.
46+
47+
```sh
48+
make ocsp-responder-http
49+
50+
# Start the responder, marking the server cert as GOOD
51+
./ocsp-responder-http 8080 ../../certs/ca-cert.pem ../../certs/ca-key.pem \
52+
../../certs/server-cert.pem
53+
54+
# Test with OpenSSL (in another terminal)
55+
openssl ocsp -issuer ../../certs/ca-cert.pem -cert ../../certs/server-cert.pem \
56+
-url http://127.0.0.1:8080/ -no_nonce
57+
```
58+
59+
Any certificate files listed after the CA key have their serial numbers
60+
registered as CERT_GOOD. Certificates not registered will get CERT_UNKNOWN.
61+
62+
### 3. nginx + wolfclu SCGI (`nginx-scgi/`)
63+
64+
Production-style deployment: nginx handles HTTP and forwards raw OCSP request
65+
bodies to wolfclu over SCGI. nginx provides TLS termination, access control,
66+
logging, and load balancing while wolfclu focuses on OCSP processing.
67+
68+
Requirements:
69+
- [wolfCLU](https://github.com/wolfSSL/wolfCLU) built and installed
70+
- nginx with SCGI support (enabled by default)
71+
72+
```
73+
+---------+ HTTP POST +-------+ SCGI +---------+
74+
| Client |------------>| nginx |-------->| wolfclu |
75+
|(openssl) |<------------| :8080 |<--------| :8081 |
76+
+---------+ OCSP resp +-------+ +---------+
77+
```
78+
79+
Quick start:
80+
81+
```sh
82+
cd nginx-scgi
83+
./run.sh
84+
```
85+
86+
Or run manually:
87+
88+
```sh
89+
# Terminal 1: Start wolfclu SCGI backend
90+
wolfssl ocsp -scgi -port 8081 \
91+
-rsigner ../../certs/ca-cert.pem \
92+
-rkey ../../certs/ca-key.pem \
93+
-CA ../../certs/ca-cert.pem
94+
95+
# Terminal 2: Start nginx
96+
nginx -c $(pwd)/nginx-scgi/nginx-ocsp.conf
97+
98+
# Terminal 3: Test
99+
openssl ocsp -issuer ../../certs/ca-cert.pem -cert ../../certs/server-cert.pem \
100+
-url http://127.0.0.1:8080/ -no_nonce
101+
```
102+
103+
The `nginx-ocsp.conf` file can be customized for your environment. See the
104+
comments in the file for standalone vs. installed nginx usage.
105+
106+
## Shared Code
107+
108+
`ocsp-load-certs.h` contains file loading utilities (`LoadFile`, `LoadCertDer`,
109+
`LoadKeyDer`) shared between the C examples.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# nginx configuration for proxying OCSP requests to wolfclu via SCGI.
2+
#
3+
# Install: copy this to /etc/nginx/sites-enabled/ or include it from
4+
# nginx.conf, then reload nginx. Alternatively run a standalone nginx:
5+
#
6+
# nginx -c $(pwd)/nginx-ocsp.conf -p $(pwd)
7+
#
8+
# Adjust paths/ports below as needed.
9+
10+
# Run as a foreground process for testing (comment out for daemon mode).
11+
daemon off;
12+
# Uncomment and set if running without root:
13+
# pid /tmp/nginx-ocsp.pid;
14+
15+
events {
16+
worker_connections 64;
17+
}
18+
19+
http {
20+
# Where nginx writes temp files when running standalone.
21+
client_body_temp_path /tmp/nginx-ocsp-body;
22+
proxy_temp_path /tmp/nginx-ocsp-proxy;
23+
fastcgi_temp_path /tmp/nginx-ocsp-fastcgi;
24+
uwsgi_temp_path /tmp/nginx-ocsp-uwsgi;
25+
scgi_temp_path /tmp/nginx-ocsp-scgi;
26+
27+
access_log /dev/stdout;
28+
error_log /dev/stderr info;
29+
30+
server {
31+
listen 8080;
32+
33+
location / {
34+
# Forward OCSP requests to wolfclu running in SCGI mode.
35+
scgi_pass 127.0.0.1:8081;
36+
37+
# Standard SCGI parameter: tell the backend the content length.
38+
include scgi_params;
39+
40+
# Ensure the OCSP request body is forwarded.
41+
scgi_param CONTENT_LENGTH $content_length;
42+
scgi_param CONTENT_TYPE $content_type;
43+
scgi_param REQUEST_METHOD $request_method;
44+
scgi_param REQUEST_URI $request_uri;
45+
}
46+
}
47+
}

ocsp/responder/nginx-scgi/run.sh

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#!/bin/sh
2+
#
3+
# run.sh - Start an OCSP responder using wolfclu (SCGI) behind nginx.
4+
#
5+
# This script:
6+
# 1. Starts wolfclu in SCGI mode on port 8081
7+
# 2. Starts nginx on port 8080, forwarding to wolfclu via SCGI
8+
# 3. Sends a test OCSP query using wolfssl's built-in test certs
9+
#
10+
# Prerequisites:
11+
# - wolfssl built with: --enable-ocsp --enable-ocsp-responder
12+
# - wolfclu built and installed
13+
# - nginx installed with SCGI support (default in most packages)
14+
#
15+
# Usage:
16+
# ./run.sh [options]
17+
#
18+
# Options:
19+
# --ca-cert <file> CA certificate (default: wolfSSL test ca-cert.pem)
20+
# --ca-key <file> CA private key (default: wolfSSL test ca-key.pem)
21+
# --index <file> OpenSSL-format index.txt (optional)
22+
# --port <num> nginx listen port (default: 8080)
23+
# --scgi-port <num> wolfclu SCGI port (default: 8081)
24+
25+
set -e
26+
27+
# Defaults - use wolfSSL test certificates
28+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
29+
CA_CERT="${SCRIPT_DIR}/../../../certs/ca-cert.pem"
30+
CA_KEY="${SCRIPT_DIR}/../../../certs/ca-key.pem"
31+
INDEX_FILE=""
32+
HTTP_PORT=8080
33+
SCGI_PORT=8081
34+
WOLFCLU_PID=""
35+
NGINX_PID=""
36+
37+
cleanup() {
38+
echo ""
39+
echo "Shutting down..."
40+
[ -n "$WOLFCLU_PID" ] && kill "$WOLFCLU_PID" 2>/dev/null || true
41+
[ -n "$NGINX_PID" ] && kill "$NGINX_PID" 2>/dev/null || true
42+
wait 2>/dev/null || true
43+
[ -n "$WORK_DIR" ] && rm -rf "$WORK_DIR"
44+
echo "Done."
45+
}
46+
trap cleanup EXIT INT TERM
47+
48+
# Parse arguments
49+
while [ $# -gt 0 ]; do
50+
case "$1" in
51+
--ca-cert) CA_CERT="$2"; shift 2 ;;
52+
--ca-key) CA_KEY="$2"; shift 2 ;;
53+
--index) INDEX_FILE="$2"; shift 2 ;;
54+
--port) HTTP_PORT="$2"; shift 2 ;;
55+
--scgi-port) SCGI_PORT="$2"; shift 2 ;;
56+
*)
57+
echo "Unknown option: $1"
58+
exit 1
59+
;;
60+
esac
61+
done
62+
63+
# Validate files exist
64+
if [ ! -f "$CA_CERT" ]; then
65+
echo "Error: CA cert not found: $CA_CERT"
66+
exit 1
67+
fi
68+
if [ ! -f "$CA_KEY" ]; then
69+
echo "Error: CA key not found: $CA_KEY"
70+
exit 1
71+
fi
72+
73+
# Check for required tools
74+
if ! command -v wolfssl >/dev/null 2>&1; then
75+
echo "Error: 'wolfssl' (wolfCLU) not found in PATH"
76+
echo "Build wolfCLU from https://github.com/wolfSSL/wolfCLU"
77+
exit 1
78+
fi
79+
if ! command -v nginx >/dev/null 2>&1; then
80+
echo "Error: nginx not found in PATH"
81+
exit 1
82+
fi
83+
84+
echo "=== OCSP Responder: nginx + wolfclu (SCGI) ==="
85+
echo ""
86+
echo "CA cert: $CA_CERT"
87+
echo "CA key: $CA_KEY"
88+
echo "HTTP port: $HTTP_PORT (nginx)"
89+
echo "SCGI port: $SCGI_PORT (wolfclu)"
90+
echo ""
91+
92+
# --- Step 1: Start wolfclu OCSP responder in SCGI mode ---
93+
echo "Starting wolfclu OCSP responder (SCGI on port $SCGI_PORT)..."
94+
95+
set -- -scgi -port "$SCGI_PORT" -rsigner "$CA_CERT" -rkey "$CA_KEY" -CA "$CA_CERT"
96+
if [ -n "$INDEX_FILE" ]; then
97+
set -- "$@" -index "$INDEX_FILE"
98+
fi
99+
100+
wolfssl ocsp "$@" &
101+
WOLFCLU_PID=$!
102+
sleep 1
103+
104+
if ! kill -0 "$WOLFCLU_PID" 2>/dev/null; then
105+
echo "Error: wolfclu failed to start"
106+
exit 1
107+
fi
108+
echo "wolfclu started (PID $WOLFCLU_PID)"
109+
110+
# --- Step 2: Generate nginx config with correct ports ---
111+
WORK_DIR="$(mktemp -d "$SCRIPT_DIR/tmp.XXXXXX")"
112+
NGINX_CONF="$WORK_DIR/nginx-ocsp.conf"
113+
cat > "$NGINX_CONF" <<EOF
114+
daemon off;
115+
pid $WORK_DIR/nginx-ocsp.pid;
116+
error_log /dev/stderr info;
117+
118+
events {
119+
worker_connections 64;
120+
}
121+
122+
http {
123+
client_body_temp_path $WORK_DIR/body;
124+
proxy_temp_path $WORK_DIR/proxy;
125+
fastcgi_temp_path $WORK_DIR/fastcgi;
126+
uwsgi_temp_path $WORK_DIR/uwsgi;
127+
scgi_temp_path $WORK_DIR/scgi;
128+
129+
access_log /dev/stdout;
130+
131+
server {
132+
listen $HTTP_PORT;
133+
134+
location / {
135+
scgi_pass 127.0.0.1:$SCGI_PORT;
136+
137+
scgi_param REQUEST_METHOD \$request_method;
138+
scgi_param REQUEST_URI \$request_uri;
139+
scgi_param QUERY_STRING \$query_string;
140+
scgi_param CONTENT_TYPE \$content_type;
141+
scgi_param CONTENT_LENGTH \$content_length;
142+
scgi_param DOCUMENT_URI \$document_uri;
143+
scgi_param DOCUMENT_ROOT \$document_root;
144+
scgi_param SCGI 1;
145+
scgi_param SERVER_PROTOCOL \$server_protocol;
146+
scgi_param REQUEST_SCHEME \$scheme;
147+
scgi_param HTTPS \$https if_not_empty;
148+
scgi_param REMOTE_ADDR \$remote_addr;
149+
scgi_param REMOTE_PORT \$remote_port;
150+
scgi_param SERVER_PORT \$server_port;
151+
scgi_param SERVER_NAME \$server_name;
152+
}
153+
}
154+
}
155+
EOF
156+
157+
echo "Starting nginx (HTTP on port $HTTP_PORT)..."
158+
nginx -c "$NGINX_CONF" &
159+
NGINX_PID=$!
160+
sleep 1
161+
162+
if ! kill -0 "$NGINX_PID" 2>/dev/null; then
163+
echo "Error: nginx failed to start"
164+
exit 1
165+
fi
166+
echo "nginx started (PID $NGINX_PID)"
167+
168+
echo ""
169+
echo "=== OCSP responder is running ==="
170+
echo ""
171+
echo "Test with wolfssl:"
172+
echo " wolfssl ocsp -issuer $CA_CERT -cert ../../certs/server-cert.pem \\"
173+
echo " -url http://127.0.0.1:$HTTP_PORT/"
174+
echo ""
175+
echo "Test with openssl:"
176+
echo " openssl ocsp -issuer $CA_CERT -cert ../../certs/server-cert.pem \\"
177+
echo " -url http://127.0.0.1:$HTTP_PORT/ -resp_text"
178+
echo ""
179+
echo "Press Ctrl-C to stop."
180+
echo ""
181+
182+
# Wait for either process to exit
183+
wait

0 commit comments

Comments
 (0)