Обсуждение: Proposal for implementing OCSP Stapling in PostgreSQL

Поиск
Список
Период
Сортировка

Proposal for implementing OCSP Stapling in PostgreSQL

От
David Zhang
Дата:
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


Вложения

Re: Proposal for implementing OCSP Stapling in PostgreSQL

От
David Zhang
Дата:
Hi Hackers,

This is the 2nd version patch with following updates:

1) Changed the frontend SSL parameter from `ssl_ocsp_stapling` to 
`sslocspstapling` to align with other SSL parameters.

2) Documented both the backend parameter `ssl_ocsp_file` and the 
frontend parameter `sslocspstapling`.

3) Implemented a check for the `nextUpdate` field in the OCSP response. 
If it is present but expired, the TLS connection will fail."

To add the test cases for OCSP Stapling, I think I should 1) add one 
section to conf/cas.config to generate `ocsp_ca.crt`; 2) use this 
`ocsp_ca` to sign some OCSP responses for server side certificates with 
`good`, `revoked` and `unknown`, and then 3) add some test cases to 
t/001_ssltests.pl.

Any comments or feedback would be greatly appreciated!

Thank you,

David


On 2024-02-05 3:51 p.m., David Zhang wrote:
> 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
>
Вложения

Re: Proposal for implementing OCSP Stapling in PostgreSQL

От
David Zhang
Дата:
Hi Hackers,

This is the third version patch for "Certificate status check using OCSP 
Stapling" with ssl regression test cases added.

Here is how I run the ssl regression test:
     ./configure --enable-tap-tests --with-openssl
     make -j
     cd src/test/ssl
     make sslfiles
     make check PG_TEST_EXTRA=ssl

expected results:
     # +++ tap check in src/test/ssl +++
     t/001_ssltests.pl .. ok
     t/002_scram.pl ..... ok
     t/003_sslinfo.pl ... ok
     All tests successful.
     Files=3, Tests=279, 17 wallclock secs ( 0.05 usr  0.01 sys + 2.32 
cusr  2.16 csys =  4.54 CPU)

     Result: PASS

Notes, before executing the SSL regression tests with the command `make 
check PG_TEST_EXTRA=ssl`, it is necessary to wait for 1 minute after 
running `make sslfiles`. This delay is required because the newly 
generated OCSP responses for the 'expired' test cases need 1 minute to 
pass the nextUpdate period. Once the stapled OCSP response files for the 
tests are committed as test input, there is no need to wait, similar to 
certificate files.

Any comments or feedback would be greatly appreciated!

Thank you,

David
Вложения

Re: Proposal for implementing OCSP Stapling in PostgreSQL

От
Jacob Champion
Дата:
On Tue, Mar 5, 2024 at 4:12 PM David Zhang <david.zhang@highgo.ca> wrote:
> Any comments or feedback would be greatly appreciated!

Hi David -- I haven't had time to get to this for the 17 release
cycle, but I'm interested in this feature and I intend to review it at
some point for 18. I think OCSP will be especially helpful for anyone
relying on sslrootcert=system. Thanks for working on it!

--Jacob