Proposal for implementing OCSP Stapling in PostgreSQL

From: David Zhang <david(dot)zhang(at)highgo(dot)ca>
To: Pgsql Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Proposal for implementing OCSP Stapling in PostgreSQL
Date: 2024-02-05 23:51:03
Message-ID: f3e54f35-5691-4ee1-8a5f-97867ca3e548@highgo.ca
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hello PostgreSQL Hackers,

This proposal suggests implementing OCSP Stapling in PostgreSQL as an
alternative and more efficient method for checking certificate
revocation, aligning with the trend shift from Certificate Revocation
Lists (CRL).

1. benefits
OCSP Stapling offers several advantages over traditional CRL checks,
including:

*) enhances user trust and real-time certificate verification without
relying on potentially outdated CRLs.
*) helps address privacy concerns associated with traditional OCSP
checks, where the client contacts the OCSP responder directly.
*) reduces latency by eliminating the need for the client to perform an
additional round-trip to the OCSP responder.
*) efficient resource utilization by allowing the server to cache and
reuse OCSP responses.

2. a POC patch with below changes:
*) a new configuration option 'ssl_ocsp_file' to enable/disable OCSP
Stapling and specify OCSP responses for PostgreSQL servers. For
instance, ssl_ocsp_file = '_server.resp'

*) a server-side callback function responsible for generating OCSP
stapling responses. This function comes into play only when a client
requests the server's certificate status during the SSL/TLS handshake.

*) a new connection parameter 'ssl_ocsp_stapling' on the client side.
For example, when 'ssl_ocsp_stapling=1', the psql client will send a
certificate status request to the PostgreSQL server.

*) a client-side callback function within the libpq interface to
validate and check the stapled OCSP response received from the server.
If the server's certificate status is valid, the TLS handshake
continues; otherwise, the connection is rejected.

3.  test cases for 'make check' are not yet ready as they could be
complicated, but basic tests can be performed as demonstrated below:
To run the tests, OpenSSL tools are required to simulate the OCSP
responder for generating OCSP responses. Additionally, initial
certificate generation, including a self-signed root CA, OCSP response
signing certificate, and PostgreSQL server certificate, is needed.

*) add ocsp atrributes to openssl.cnf
$ openssl version
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)

$ diff openssl-ocsp.cnf /etc/ssl/openssl.cnf
204d203
< authorityInfoAccess = OCSP;URI:http://127.0.0.1:6655
232,235d230
< [ v3_ocsp ]
< basicConstraints = CA:FALSE
< keyUsage = nonRepudiation, digitalSignature, keyEncipherment
< extendedKeyUsage = OCSPSigning
255c250
< keyUsage = critical, cRLSign, digitalSignature, keyCertSign
---
>

*) prepare OCSP responder for generating OCSP response
$ mkdir -p demoCA/newcerts
$ touch demoCA/index.txt
$ echo '01' > demoCA/serial

# create a self-signed root CA
$ openssl req -new -nodes -out rootCA.csr -keyout rootCA.key -subj
"/C=CA/ST=BC/L=VAN/O=IDO/OU=DEV/CN=rootCA"
$ openssl x509 -req -in rootCA.csr -days 3650 -extfile openssl-ocsp.cnf
-extensions v3_ca -signkey rootCA.key -out rootCA.crt

# create a certificate for OCSP responder
$ openssl req -new -nodes -out ocspSigning.csr -keyout ocspSigning.key
-subj "/C=CA/ST=BC/L=VAN/O=IDO/OU=DEV/CN=ocspSigner"
$ openssl ca -keyfile rootCA.key -cert rootCA.crt -in ocspSigning.csr
-out ocspSigning.crt -config openssl-ocsp.cnf -extensions v3_ocsp
    Sign the certificate? [y/n]:y
    1 out of 1 certificate requests certified, commit? [y/n]y

# create a certificate for PostgreSQL server
$ openssl req -new -nodes -out server.csr -keyout server.key -subj
"/C=CA/ST=BC/L=VAN/O=IDO/OU=DEV/CN=server"
$ openssl ca -batch -days 365 -keyfile rootCA.key -cert rootCA.crt
-config openssl-ocsp.cnf -out server.crt -infiles server.csr

# start OCSP responder
$ openssl ocsp -index demoCA/index.txt -port 6655 -rsigner
ocspSigning.crt -rkey ocspSigning.key -CA rootCA.crt -text

# make sure PostgreSQL server's certificate is 'good'
$ openssl ocsp -issuer rootCA.crt -url http://127.0.0.1:6655 -resp_text
-noverify -cert server.crt

# generate OCSP response when certificate status is 'good' and save as
_server.resp-good:
$ openssl ocsp -issuer rootCA.crt -cert server.crt -url
http://127.0.0.1:6655 -respout _server.resp-good

# revoke PostgreSQL server's certificate
$ openssl ca -keyfile rootCA.key -cert rootCA.crt -revoke server.crt

# make sure PostgreSQL server's certificate is 'revoked'
$ openssl ocsp -issuer rootCA.crt -url http://127.0.0.1:6655 -resp_text
-noverify -cert server.crt

### generate OCSP response when certificate status is 'revoked' and save
as _server.resp-revoked:
$ openssl ocsp -issuer rootCA.crt -cert server.crt -url
http://127.0.0.1:6655 -respout _server.resp-revoked

*) setup OCSP stapling on PostgreSQL server side
copy 'rootCA.crt, server.key, server.crt, _server.resp-good, and
_server.resp-revoked' to pgdata folder and update PostgreSQL server
configuration by specifying ssl_ocsp_file = '_server.resp', where
'_server.resp' is either a copy of '_server.resp-good' or
'_server.resp-revoked' depending on the test case, for example:

listen_addresses = '*'
ssl = on
ssl_ca_file = 'rootCA.crt'
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_ocsp_file = '_server.resp'

*) test with psql client
3.1) PostgreSQL server's certificate status is 'good'
$ cp -pr _server.resp-good _server.resp
$ psql -d "sslmode=verify-ca sslrootcert=rootCA.crt user=david
dbname=postgres ssl_ocsp_stapling=1" -h 127.0.0.1 -p 5432
psql (17devel)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384,
compression: off)
Type "help" for help.

postgres=#

3.2) PostgreSQL server's certificate status is 'revoked'
$ cp -pr _server.resp-revoked _server.resp
$ psql -d "sslmode=verify-ca sslrootcert=rootCA.crt user=david
dbname=postgres ssl_ocsp_stapling=1" -h 127.0.0.1 -p 5432
psql: error: connection to server at "127.0.0.1", port 5432 failed: SSL
error: ocsp callback failure

3.3) PostgreSQL server's certificate status is 'revoked' but OCSP
stapling is not required by psql client:
$ psql -d "sslmode=verify-ca sslrootcert=rootCA.crt user=david
dbname=postgres ssl_ocsp_stapling=0" -h 127.0.0.1 -p 5432
psql (17devel)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384,
compression: off)
Type "help" for help.

postgres=#

This is a highly experimental proof of concept, and any comments or
feedback would be greatly appreciated!

Best regards,
David Zhang

===============
Highgo Software Canada
www.highgo.ca

Attachment Content-Type Size
openssl-ocsp.cnf text/plain 12.4 KB
v1-0001-support-certificate-status-check-using-OCSP-stapling.patch text/plain 13.8 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Kyotaro Horiguchi 2024-02-06 00:39:09 Re: Change COPY ... ON_ERROR ignore to ON_ERROR ignore_row
Previous Message Michael Paquier 2024-02-05 23:48:55 Re: Make COPY format extendable: Extract COPY TO format implementations