pull/604/merge
Zackery 2026-09-11 09:44:30 -06:00 committed by GitHub
commit f5119857c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1145 additions and 543 deletions

View File

@ -204,6 +204,19 @@ profiles:
--enable-ocsp-responder --enable-cert-setup-cb --enable-sessioncerts
--enable-tls13 --enable-static --enable-shared
ocsp-nonblock:
# ocsp/ocsp_nonblock: two clients that fetch a live cert and check OCSP
# non-blocking. The plain one needs opensslextra+sni and KEEP_PEER_CERT
# (it calls wolfSSL_get_peer_certificate/X509_get_der); the async one adds
# asynccrypt, alpn and stapling. This profile mirrors the two README
# configure lines and adds tls13 to exercise the TLS 1.3 path against the
# live server -- neither client requires it (both still allow TLS 1.2).
flags: >-
--enable-ocsp --enable-ocspstapling --enable-ocspstapling2
--enable-asynccrypt --enable-opensslextra --enable-sni --enable-alpn
--enable-tls13 --enable-static --enable-shared
cflags: "-DWOLFSSL_NONBLOCK_OCSP -DHAVE_IO_TIMEOUT -DKEEP_PEER_CERT -DWOLFSSL_OCSP_SCREEN_RESPONDER"
pkcs11:
flags: "--enable-pkcs11 --enable-cryptocb --enable-static --enable-shared"
@ -635,9 +648,9 @@ examples:
- id: ocsp-nonblock
path: ocsp/ocsp_nonblock
profile: ocsp
profile: ocsp-nonblock
mode: build-only
reason: "ocsp_nonblock_async connects to an external responder on :443"
reason: "both clients connect to a live OCSP responder on :443"
- id: ocsp-responder
path: ocsp/responder

View File

@ -5,11 +5,13 @@ on:
branches: [master]
paths:
- 'certs/**'
- 'ocsp/ocsp_nonblock/ca_certs/**'
- '.github/workflows/cert-expiry.yml'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'certs/**'
- 'ocsp/ocsp_nonblock/ca_certs/**'
- '.github/workflows/cert-expiry.yml'
# No cron: nightly.yml calls this, so the nightly stays one run and one triage writer
workflow_call:
@ -38,3 +40,5 @@ jobs:
- uses: actions/checkout@v5
- name: Warn on certs nearing expiry
run: ./certs/check-expiry.sh certs
- name: Warn on example CA certs nearing expiry
run: ./certs/check-expiry.sh ocsp/ocsp_nonblock/ca_certs

View File

@ -5,14 +5,20 @@ Online Certificate Status Protocol (OCSP) is used for obtaining the revocation s
## OCSP non-blocking example
This uses a google.com certificate chain to demonstrate validating revocation status using an OCSP server.
This connects to a public server, fetches its leaf certificate, and checks that
certificate's revocation status with a non-blocking OCSP lookup. The certificate
is fetched live so nothing static can expire.
The Google.com certificate defines OCSP in the X509v3 extension "Authority Information Access" section.
It uses `www.digicert.com` because that certificate still has an OCSP responder
(many CAs, including Google, have dropped OCSP). The bundled `ca_certs` hold the
DigiCert CAs used to verify it.
Example usage:
```sh
$ ./configure --enable-ocsp CFLAGS="-DHAVE_IO_TIMEOUT -DWOLFSSL_NONBLOCK_OCSP"
$ ./configure --enable-ocsp --enable-opensslextra --enable-sni \
CFLAGS="-DHAVE_IO_TIMEOUT -DWOLFSSL_NONBLOCK_OCSP -DKEEP_PEER_CERT \
-DWOLFSSL_OCSP_SCREEN_RESPONDER"
$ make
$ sudo make install
@ -20,35 +26,56 @@ $ sudo make install
gcc -o ocsp_nonblock ocsp_nonblock.c -Wall -I/usr/local/include -Os -L/usr/local/lib -lwolfssl
% ./ocsp_nonblock
Fetched www.digicert.com certificate (1777 bytes)
Loaded Trusted CA dir ca_certs (ret 1)
Convert Google.com PEM cert to DER (ret 1)
Verify Google.com cert: 1
Verify www.digicert.com cert: 1
OCSP Lookup:
URL: http://ocsp.pki.goog/gts1c3
Domain: ocsp.pki.goog
Path: /gts1c3
URL: http://ocsp.digicert.com
Domain: ocsp.digicert.com
Path: /
Port: 80
OCSP Response: ret 471, nonblock count 409421
Check OCSP for Google.com (ret 1)
OCSP Response: ret 471, nonblock count 1
Resp ret: 471
Check OCSP for www.digicert.com (ret 1)
Ret = 1: success
```
The `Ret = 1` line is wolfSSL's success code, not the exit status: the program
exits `0` on success and a non-zero error code on failure, so it works in scripts.
If DigiCert's chain changes, pass an alternate CA directory as an argument, e.g.
`./ocsp_nonblock /etc/ssl/certs`.
The certificate fetch (TCP connect plus TLS handshake) and the OCSP responder
connect each time out after 10 seconds. On a slow network, raise it at build
time with `CFLAGS="-DDEFAULT_TIMEOUT_SEC=30 ..."`.
With `WOLFSSL_OCSP_SCREEN_RESPONDER` both clients refuse OCSP responder
addresses in loopback, private and link-local ranges, so a certificate cannot
point the lookup at an internal host. They resolve the responder once and
connect to the address they checked, so a changing DNS answer cannot get
around it. Leave the define out if your responder runs on such an address.
## OCSP non-blocking Async example
This uses your system certificate chain to demonstrate validating revocation status using an OCSP
public server with wolfSSL's Asynchronous cryptography support.
This demonstrates validating revocation status using an OCSP public server with wolfSSL's
Asynchronous cryptography support.
**NOTE:** Before building this example the asynchronous support must be obtained from
(https://github.com/wolfSSL/wolfAsyncCrypt) and installed into wolfSSL by following the
instructions in the *README* file contained in the wolfAsyncCrypt repository.
The example uses `www.digicert.com`, whose certificate still has an OCSP
responder (many CAs, including Google, have dropped OCSP).
The example uses youtube.com as the public server.
The name lookups, the TCP connects, the TLS handshake and the OCSP lookup
inside it share one 15 second deadline (`HANDSHAKE_TIMEOUT_SEC` in the source).
The OCSP lookup is done with wolfSSL's HTTP helpers on a non-blocking socket so
it can be held to that deadline too. Name lookups use glibc's `getaddrinfo_a()`,
so this client builds on Linux.
Example usage:
```sh
$ ./configure --enable-ocsp --enable-asynccrypt --enable-sni --enable-alpn --enable-ocspstapling
--enable-ocspstapling2 --enable-opensslextra --enable-curve25519 CFLAGS="-DWOLFSSL_NONBLOCK_OCSP"
--enable-ocspstapling2 --enable-opensslextra \
CFLAGS="-DWOLFSSL_NONBLOCK_OCSP -DHAVE_IO_TIMEOUT -DWOLFSSL_OCSP_SCREEN_RESPONDER"
$ make
$ sudo make install
@ -59,70 +86,48 @@ gcc -o ocsp_nonblock_async ocsp_nonblock_async.c -Wall -I/usr/local/include -Os
WolfSSL AsyncCrypt Enabled
WolfSSL AsyncCrypt with Simulation Mode
Connecting...
wolfSSL_connect() returned -1 (error code -108)
wolfSSL_connect() returned -1 (error code -108)
wolfSSL_connect() returned -1 (error code -108)
ocsp_cb(): http://ocsp.pki.goog/gsr1
simulate 'want read'
wolfSSL_connect() returned -1 (error code -408)
ocsp_cb(): http://ocsp.pki.goog/gsr1
Running command:
curl -s --data-binary '@ocsp.req' -o 'ocsp.resp' -X POST -H 'Cache-Control: no-cache' -H 'Content-Type: application/ocsp-request' 'http://ocsp.pki.goog/gsr1'
Reading OCSP response from file...
Read 1447 bytes.
*response is (nil)
Allocating 1447 bytes...
*response is now 0x55ef7fdcb4e0
Copying bytes...
Bytes copied.
verify_cb()
preverify_ok = 1
wolfSSL_connect() returned -1 (error code -108)
ocsp_cb(): http://ocsp.pki.goog/gtsr1
ocsp_cb(): http://ocsp.digicert.com
simulate 'want read'
wolfSSL_connect() returned -1 (error code -408)
ocsp_cb(): http://ocsp.pki.goog/gtsr1
Running command:
curl -s --data-binary '@ocsp.req' -o 'ocsp.resp' -X POST -H 'Cache-Control: no-cache' -H 'Content-Type: application/ocsp-request' 'http://ocsp.pki.goog/gtsr1'
Reading OCSP response from file...
Read 724 bytes.
*response is (nil)
Allocating 724 bytes...
*response is now 0x55ef7fdaf030
Copying bytes...
Bytes copied.
ocsp_cb(): http://ocsp.digicert.com
verify_cb()
preverify_ok = 1
wolfSSL_connect() returned -1 (error code -108)
ocsp_cb(): http://ocsp.pki.goog/gts1c3
simulate 'want read'
wolfSSL_connect() returned -1 (error code -408)
ocsp_cb(): http://ocsp.pki.goog/gts1c3
Running command:
curl -s --data-binary '@ocsp.req' -o 'ocsp.resp' -X POST -H 'Cache-Control: no-cache' -H 'Content-Type: application/ocsp-request' 'http://ocsp.pki.goog/gts1c3'
Reading OCSP response from file...
Read 472 bytes.
*response is (nil)
Allocating 472 bytes...
*response is now 0x55ef7fdac4b0
Copying bytes...
Bytes copied.
verify_cb()
preverify_ok = 1
wolfSSL_connect() returned -1 (error code -108)
CONNECTED
Closing connection...
wolfSSL_shutdown() failed with code 2 (error 0)
CLOSED
test_connect() failed
CONNECT FAILED
CONNECT PASSED
DONE
```
The example uses `/etc/ssl/certs/ca-certificates.crt` as the system certs file by default. If your
system doesn't have this file, just run the executable with the path to your own cert file.
If you already have wolfSSL installed and do not want to change it, build a
local wolfSSL copy but skip `make install`, then compile the example straight
against that build (this leaves your existing install untouched):
```sh
# In your local wolfSSL source directory, build only (no install):
$ ./configure --enable-ocsp --enable-asynccrypt --enable-sni --enable-alpn \
--enable-ocspstapling --enable-ocspstapling2 --enable-opensslextra \
CFLAGS="-DWOLFSSL_NONBLOCK_OCSP -DHAVE_IO_TIMEOUT -DWOLFSSL_OCSP_SCREEN_RESPONDER"
$ make
# Back in this example directory, point the compiler at that build:
$ WOLFSSL=/path/to/wolfssl
$ gcc -o ocsp_nonblock_async ocsp_nonblock_async.c -Wall -Os \
-I$WOLFSSL -L$WOLFSSL/src/.libs -lwolfssl
$ LD_LIBRARY_PATH=$WOLFSSL/src/.libs ./ocsp_nonblock_async
```
By default it loads the bundled `ca_certs/DigiCert_Global_Root_G2.pem` to check
digicert.com's certificate, so it runs on its own. digicert.com is a real server,
so its certificate can change. If the check fails, pass another cert file, such as
your system CA bundle:
```
./ocsp_nonblock_asynccrypt ../../mycerts/ca.crt
./ocsp_nonblock_async /etc/ssl/certs/ca-certificates.crt
```
On success it prints `CONNECTED` and, at the end, `CONNECT PASSED`. The
`verify_cb` and `ocsp_cb` lines show the certificate check and OCSP lookup
running.

View File

@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFPDCCBCSgAwIBAgIQAWePH++IIlXYsKcOa3uyIDANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0yMDA3MDIxMjQyNTBaFw0zMDA3MDIxMjQyNTBaMEQxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEVWIFJT
QSBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0eZsx/neTr
f4MXJz0R2fJTIDfN8AwUAu7hy4gI0vp7O8LAAHx2h3bbf8wl+pGMSxaJK9ffDDCD
63FqqFBqE9eTmo3RkgQhlu55a04LsXRLcK6crkBOO0djdonybmhrfGrtBqYvbRat
xenkv0Sg4frhRl4wYh4dnW0LOVRGhbt1G5Q19zm9CqMlq7LlUdAE+6d3a5++ppfG
cnWLmbEVEcLHPAnbl+/iKauQpQlU1Mi+wEBnjE5tK8Q778naXnF+DsedQJ7NEi+b
QoonTHEz9ryeEcUHuQTv7nApa/zCqes5lXn1pMs4LZJ3SVgbkTLj+RbBov/uiwTX
tkBEWawvZH8CAwEAAaOCAgswggIHMB0GA1UdDgQWBBRqTlC/mGidW3sgddRZAXlI
ZpIyBjAfBgNVHSMEGDAWgBROIlQgGJXm427mD/r6uRLtBhePOTAOBgNVHQ8BAf8E
BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQI
MAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
cC5kaWdpY2VydC5jb20wewYDVR0fBHQwcjA3oDWgM4YxaHR0cDovL2NybDMuZGln
aWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA3oDWgM4YxaHR0cDov
L2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDCBzgYD
VR0gBIHGMIHDMIHABgRVHSAAMIG3MCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k
aWdpY2VydC5jb20vQ1BTMIGKBggrBgEFBQcCAjB+DHxBbnkgdXNlIG9mIHRoaXMg
Q2VydGlmaWNhdGUgY29uc3RpdHV0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgUmVseWlu
ZyBQYXJ0eSBBZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL3d3dy5kaWdpY2Vy
dC5jb20vcnBhLXVhMA0GCSqGSIb3DQEBCwUAA4IBAQBSMgrCdY2+O9spnYNvwHiG
+9lCJbyELR0UsoLwpzGpSdkHD7pVDDFJm3//B8Es+17T1o5Hat+HRDsvRr7d3MEy
o9iXkkxLhKEgApA2Ft2eZfPrTolc95PwSWnn3FZ8BhdGO4brTA4+zkPSKoMXi/X+
WLBNN29Z/nbCS7H/qLGt7gViEvTIdU8x+H4l/XigZMUDaVmJ+B5d7cwSK7yOoQdf
oIBGmA5Mp4LhMzo52rf//kXPfE3wYIZVHqVuxxlnTkFYmffCX9/Lon7SWaGdg6Rc
k4RHhHLWtmz2lTZ5CEo2ljDsGzCFGJP7oT4q6Q8oFC38irvdKIJ95cUxYzj4tnOI
-----END CERTIFICATE-----

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----

View File

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw
MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp
kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX
lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm
BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA
gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL
tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud
DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T
AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD
VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG
CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw
AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt
MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG
A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br
aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN
AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ
cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL
RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U
+o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr
PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER
lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs
Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO
z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG
AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw
juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl
1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd
-----END CERTIFICATE-----

View File

@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFYjCCBEqgAwIBAgIQd70NbNs2+RrqIQ/E8FjTDTANBgkqhkiG9w0BAQsFADBX
MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UE
CxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTIwMDYx
OTAwMDA0MloXDTI4MDEyODAwMDA0MlowRzELMAkGA1UEBhMCVVMxIjAgBgNVBAoT
GUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxFDASBgNVBAMTC0dUUyBSb290IFIx
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAthECix7joXebO9y/lD63
ladAPKH9gvl9MgaCcfb2jH/76Nu8ai6Xl6OMS/kr9rH5zoQdsfnFl97vufKj6bwS
iV6nqlKr+CMny6SxnGPb15l+8Ape62im9MZaRw1NEDPjTrETo8gYbEvs/AmQ351k
KSUjB6G00j0uYODP0gmHu81I8E3CwnqIiru6z1kZ1q+PsAewnjHxgsHA3y6mbWwZ
DrXYfiYaRQM9sHmklCitD38m5agI/pboPGiUU+6DOogrFZYJsuB6jC511pzrp1Zk
j5ZPaK49l8KEj8C8QMALXL32h7M1bKwYUH+E4EzNktMg6TO8UpmvMrUpsyUqtEj5
cuHKZPfmghCN6J3Cioj6OGaK/GP5Afl4/Xtcd/p2h/rs37EOeZVXtL0m79YB0esW
CruOC7XFxYpVq9Os6pFLKcwZpDIlTirxZUTQAs6qzkm06p98g7BAe+dDq6dso499
iYH6TKX/1Y7DzkvgtdizjkXPdsDtQCv9Uw+wp9U7DbGKogPeMa3Md+pvez7W35Ei
Eua++tgy/BBjFFFy3l3WFpO9KWgz7zpm7AeKJt8T11dleCfeXkkUAKIAf5qoIbap
sZWwpbkNFhHax2xIPEDgfg1azVY80ZcFuctL7TlLnMQ/0lUTbiSw1nH69MG6zO0b
9f6BQdgAmD06yK56mDcYBZUCAwEAAaOCATgwggE0MA4GA1UdDwEB/wQEAwIBhjAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTkrysmcRorSCeFL1JmLO/wiRNxPjAf
BgNVHSMEGDAWgBRge2YaRQ2XyolQL30EzTSo//z9SzBgBggrBgEFBQcBAQRUMFIw
JQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnBraS5nb29nL2dzcjEwKQYIKwYBBQUH
MAKGHWh0dHA6Ly9wa2kuZ29vZy9nc3IxL2dzcjEuY3J0MDIGA1UdHwQrMCkwJ6Al
oCOGIWh0dHA6Ly9jcmwucGtpLmdvb2cvZ3NyMS9nc3IxLmNybDA7BgNVHSAENDAy
MAgGBmeBDAECATAIBgZngQwBAgIwDQYLKwYBBAHWeQIFAwIwDQYLKwYBBAHWeQIF
AwMwDQYJKoZIhvcNAQELBQADggEBADSkHrEoo9C0dhemMXoh6dFSPsjbdBZBiLg9
NR3t5P+T4Vxfq7vqfM/b5A3Ri1fyJm9bvhdGaJQ3b2t6yMAYN/olUazsaL+yyEn9
WprKASOshIArAoyZl+tJaox118fessmXn1hIVw41oeQa1v1vg4Fv74zPl6/AhSrw
9U5pCZEt4Wi4wStz6dTZ/CLANx8LZh1J7QJVj2fhMtfTJr9w4z30Z209fOU0iOMy
+qduBmpvvYuR7hZL6Dupszfnw0Skfths18dG9ZKb59UhvmaSGZRVbNQpsg3BZlvi
d0lIKO2d1xozclOzgjXPYovJJIultzkMu34qQb9Sz/yilrbCgj8=
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEhzCCA2+gAwIBAgIQOzdfWX2DYt0J79PlD6I4NTANBgkqhkiG9w0BAQsFADBG
MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMzA0MjQxMjAxMTZaFw0yMzA3MTcx
MjAxMTVaMBkxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEjjE+XIQeTp+HYC7t1oTblWTyWA3fy8AdbKLYDxYvyCBhtU3o
hNe8xFj2yLkNzjjG5r/e+9pssNIL7///gh53JaOCAmcwggJjMA4GA1UdDwEB/wQE
AwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQW
BBRqOTqTkUjbMDNo/o2cnpSNng1IATAfBgNVHSMEGDAWgBSKdH+vhc3ulc09nNDi
RhTzcTUdJzBqBggrBgEFBQcBAQReMFwwJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3Nw
LnBraS5nb29nL2d0czFjMzAxBggrBgEFBQcwAoYlaHR0cDovL3BraS5nb29nL3Jl
cG8vY2VydHMvZ3RzMWMzLmRlcjAZBgNVHREEEjAQgg53d3cuZ29vZ2xlLmNvbTAh
BgNVHSAEGjAYMAgGBmeBDAECATAMBgorBgEEAdZ5AgUDMDwGA1UdHwQ1MDMwMaAv
oC2GK2h0dHA6Ly9jcmxzLnBraS5nb29nL2d0czFjMy9RT3ZKME4xc1QyQS5jcmww
ggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdgB6MoxU2LcttiDqOOBSHumEFnAyE4VN
O9IrwTpXo1LrUgAAAYezWq9QAAAEAwBHMEUCID7E4i4X0sXFwbQSmgi+aDvZw5Zc
D6hTicrkqA/3XlmrAiEA8qCimh33lfyW6879dtRbxZ2HTu7mZwD9BaitE2y9m44A
dgDoPtDaPvUGNTLnVyi8iWvJA9PL0RFr7Otp4Xd9bQa9bgAAAYezWq8cAAAEAwBH
MEUCIQDt0g6qUANO5pRDTWlqVUlGvYHAavpVy1oTzaH54v2lnAIgLP5A/29sPUZX
/7txQxZyeUgnzoXidMvpvrjMkjHqL/IwDQYJKoZIhvcNAQELBQADggEBANalC0GR
lmC+Yt6aB1IG9WZn+i9lYmaoIhz1WbDF+GkX6WwMWCJZOd3P7Ul4of3DU8Ql1jhG
fpPvCtXa66Iuc9Ujzhs29Mbrunq7zdYjlB+X8yacFkUHBDkvXtr7em53BfHDHnwb
Sb5CIVm/E/HrfHeCBeK6JQJ4C8m25hUYYv5+Z2s6vDutnX+L0vwMFgE2dNX3Sh45
rtjoG2AHUIkxR/ovAMPIy8hKuhag7yaFZO08us1cNlGXda448O3OTcVSZ+yuyHlu
cI4gZ5/W1Kem0gx3uvjnCttxZ4hR+mknD0dS+XK4sp5LNuc8pi1K40GzL3kHVK5M
suHVECOecBARAJ4=
-----END CERTIFICATE-----

View File

@ -20,6 +20,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
**/
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <poll.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfio.h>
@ -27,8 +36,11 @@
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
/* Requires wolfSSL: --enable-ocsp --enable-opensslextra --enable-sni,
* CFLAGS -DWOLFSSL_NONBLOCK_OCSP -DHAVE_IO_TIMEOUT -DKEEP_PEER_CERT. */
static const char* kCACertsDir = "ca_certs"; /* put CA certs into this directory */
static const char* kGoogleCom = "google.pem"; /* www.google.com */
static const char* kServerHost = "www.digicert.com";
static const word16 kServerPort = 443;
#ifndef HTTP_SCRATCH_BUFFER_SIZE
#define HTTP_SCRATCH_BUFFER_SIZE 512
@ -37,7 +49,7 @@ static const char* kGoogleCom = "google.pem"; /* www.google.com */
#define MAX_URL_ITEM_SIZE 80
#endif
#ifndef DEFAULT_TIMEOUT_SEC
#define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
#define DEFAULT_TIMEOUT_SEC 10 /* cert fetch / OCSP connect limit (sec) */
#endif
static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
@ -50,6 +62,120 @@ static char domainName[MAX_URL_ITEM_SIZE];
static int nonBlockCnt = 0;
static byte* httpBuf;
/* Switch fd to non-blocking so I/O on it can be driven against a deadline.
* Returns 0 on success, -1 on error. */
static int set_nonblocking(SOCKET_T fd)
{
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
return -1;
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) {
return -1;
}
return 0;
}
/* Wait until fd is ready for the direction the caller needs, or until the
* deadline passes. Returns 0 when ready, -1 on timeout or error. */
static int wait_for_socket(SOCKET_T fd, int wantWrite, time_t deadline)
{
struct pollfd pfd;
time_t now = time(NULL);
int ret;
if (now >= deadline) {
return -1;
}
pfd.fd = fd;
pfd.events = wantWrite ? POLLOUT : POLLIN;
pfd.revents = 0;
ret = poll(&pfd, 1, (int)(deadline - now) * 1000);
return (ret > 0) ? 0 : -1;
}
#ifdef WOLFSSL_OCSP_SCREEN_RESPONDER
/* 1 if the IPv4 address is in a loopback, private, link-local or reserved
* range that an OCSP responder must not live in, else 0. */
static int ipv4_blocked(const struct in_addr* in)
{
const unsigned char* a = (const unsigned char*)&in->s_addr;
return (a[0] == 0) || /* 0.0.0.0/8 */
(a[0] == 127) || /* loopback */
(a[0] == 10) || /* 10/8 */
(a[0] == 172 && (a[1] & 0xF0) == 16) || /* 172.16/12 */
(a[0] == 192 && a[1] == 168) || /* 192.168/16 */
(a[0] == 169 && a[1] == 254) || /* link-local */
(a[0] == 100 && (a[1] & 0xC0) == 64) || /* 100.64/10 */
(a[0] >= 224); /* multicast, reserved */
}
#endif
/* Resolve host once, screen every address it returned, then connect straight
* to an accepted address within timeoutSec. Connecting to the address rather
* than the name again means a changing DNS answer cannot slip a blocked
* address past the screen. Returns 0 with *fd set, -1 on failure. */
static int connect_responder(const char* host, word16 port, int timeoutSec,
SOCKET_T* fd)
{
struct addrinfo hints;
struct addrinfo* res = NULL;
struct addrinfo* ai;
char portStr[6];
time_t deadline = time(NULL) + timeoutSec;
int s = -1;
snprintf(portStr, sizeof(portStr), "%u", (unsigned int)port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(host, portStr, &hints, &res) != 0) {
printf("Unable to resolve OCSP responder %s\n", host);
return -1;
}
#ifdef WOLFSSL_OCSP_SCREEN_RESPONDER
/* Reject the responder if any of its addresses is off limits. */
for (ai = res; ai != NULL; ai = ai->ai_next) {
if (ipv4_blocked(&((struct sockaddr_in*)ai->ai_addr)->sin_addr)) {
printf("OCSP responder %s not permitted\n", host);
freeaddrinfo(res);
return -1;
}
}
#endif
for (ai = res; ai != NULL && s == -1; ai = ai->ai_next) {
int err = 0;
socklen_t errLen = sizeof(err);
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (s == -1) {
continue;
}
if (set_nonblocking(s) == 0 &&
(connect(s, ai->ai_addr, ai->ai_addrlen) == 0 ||
(errno == EINPROGRESS &&
wait_for_socket(s, 1, deadline) == 0 &&
getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &errLen) == 0 &&
err == 0))) {
break;
}
close(s);
s = -1;
}
freeaddrinfo(res);
if (s == -1) {
printf("OCSP responder connection failed\n");
return -1;
}
*fd = s;
return 0;
}
/* Return size of the OCSP response or negative for error */
static int OcspLookupNonBlockCb(void* ctx, const char* url, int urlSz,
byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
@ -96,12 +222,10 @@ static int OcspLookupNonBlockCb(void* ctx, const char* url, int urlSz,
httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
httpBuf, httpBufSz);
ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
/* The socket comes back non-blocking, which the response read
* below relies on to report OCSP_WANT_READ. */
ret = connect_responder(domainName, port, io_timeout_sec, &sfd);
if (ret == 0) {
#if defined(WOLFSSL_NONBLOCK_OCSP) && defined(HAVE_IO_TIMEOUT)
wolfIO_SetBlockingMode(sfd, 1); /* non-blocking */
#endif
if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
httpBufSz) {
printf("OCSP http request failed\n");
@ -112,13 +236,13 @@ static int OcspLookupNonBlockCb(void* ctx, const char* url, int urlSz,
}
else {
do {
ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf,
ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf,
httpBuf, HTTP_SCRATCH_BUFFER_SIZE, NULL);
nonBlockCnt++;
if (ret == OCSP_WANT_READ)
return WOLFSSL_CBIO_ERR_WANT_READ;
} while (ret == OCSP_WANT_READ);
printf("OCSP Response: ret %d, nonblock count %d\n",
printf("OCSP Response: ret %d, nonblock count %d\n",
ret, nonBlockCnt);
}
}
@ -145,92 +269,257 @@ static void OcspRespFreeCb(void* ctx, byte *resp)
(void)ctx;
}
/* Duplicate an X509's DER encoding into a newly allocated buffer sized to the
* cert. Returns it (caller XFREEs) and sets *derSz, or NULL on error. */
static byte* dup_x509_der(WOLFSSL_X509* x509, int* derSz)
{
int sz = 0;
const byte* d = wolfSSL_X509_get_der(x509, &sz);
byte* copy;
if (d == NULL) {
return NULL;
}
if (sz <= 0) {
return NULL;
}
copy = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (copy == NULL) {
return NULL;
}
XMEMCPY(copy, d, sz);
*derSz = sz;
return copy;
}
/* Drive wolfSSL_connect() on a non-blocking socket until it finishes or the
* deadline passes. wolfIO_TcpConnect() only times out the TCP connect, and
* per-call socket timeouts can be kept alive by a peer that trickles data, so
* the whole handshake is held to one absolute deadline instead. Returns
* WOLFSSL_SUCCESS, or the wolfSSL_connect() result with *timedOut set when the
* deadline passed. */
static int connect_with_deadline(WOLFSSL* ssl, SOCKET_T fd, int timeoutSec,
int* timedOut)
{
time_t deadline = time(NULL) + timeoutSec;
int ret;
int err;
*timedOut = 0;
for (;;) {
ret = wolfSSL_connect(ssl);
if (ret == WOLFSSL_SUCCESS) {
break;
}
err = wolfSSL_get_error(ssl, ret);
if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) {
break;
}
if (wait_for_socket(fd, err == WOLFSSL_ERROR_WANT_WRITE, deadline)
!= 0) {
*timedOut = 1;
break;
}
}
return ret;
}
/* Open a TLS connection to host:tlsPort and return the peer's leaf certificate
* DER in a newly allocated buffer (caller XFREEs), or NULL on error. */
static byte* fetch_leaf_der(const char* host, word16 tlsPort, const char* caDir,
int* derSz)
{
WOLFSSL_CTX* ctx;
WOLFSSL* ssl;
WOLFSSL_X509* peer;
SOCKET_T fd = SOCKET_INVALID;
byte* der;
int ret;
int timedOut;
ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
if (ctx == NULL) {
printf("Unable to create client context\n");
return NULL;
}
/* Verify the peer during this fetch so we get the genuine host cert; an
* unverified fetch would let an attacker swap in any CA-issued cert. */
wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
if (wolfSSL_CTX_load_verify_locations(ctx, NULL, caDir)
!= WOLFSSL_SUCCESS) {
printf("Unable to load CA certs from %s\n", caDir);
wolfSSL_CTX_free(ctx);
return NULL;
}
if (wolfIO_TcpConnect(&fd, host, tlsPort, io_timeout_sec) != 0) {
printf("TCP connect to %s failed\n", host);
wolfSSL_CTX_free(ctx);
return NULL;
}
if (set_nonblocking(fd) != 0) {
printf("Unable to make socket non-blocking\n");
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return NULL;
}
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
printf("Unable to create SSL object\n");
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return NULL;
}
wolfSSL_set_fd(ssl, fd);
if (wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, host,
(word16)XSTRLEN(host)) != WOLFSSL_SUCCESS) {
printf("wolfSSL_UseSNI failed\n");
wolfSSL_free(ssl);
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return NULL;
}
/* Bind the cert to the hostname; a chain check alone is not enough. */
if (wolfSSL_check_domain_name(ssl, host) != WOLFSSL_SUCCESS) {
printf("wolfSSL_check_domain_name failed\n");
wolfSSL_free(ssl);
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return NULL;
}
ret = connect_with_deadline(ssl, fd, io_timeout_sec, &timedOut);
if (ret != WOLFSSL_SUCCESS) {
if (timedOut) {
printf("TLS connect to %s timed out after %d seconds\n", host,
io_timeout_sec);
}
else {
printf("TLS connect to %s failed (%d)\n", host,
wolfSSL_get_error(ssl, ret));
}
wolfSSL_free(ssl);
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return NULL;
}
peer = wolfSSL_get_peer_certificate(ssl);
if (peer == NULL) {
printf("No peer certificate\n");
wolfSSL_free(ssl);
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return NULL;
}
der = dup_x509_der(peer, derSz);
if (der == NULL) {
printf("Peer certificate DER unavailable\n");
}
wolfSSL_shutdown(ssl); /* clean TLS close before teardown */
wolfSSL_FreeX509(peer);
wolfSSL_free(ssl);
CloseSocket(fd);
wolfSSL_CTX_free(ctx);
return der;
}
int main(int argc, char** argv)
{
int ret;
WOLFSSL_CERT_MANAGER* pCm;
char pem[2048];
int pemSz = 0;
byte der[2000];
/* Allocated by fetch_leaf_der to the exact cert size; freed below. */
byte* der = NULL;
int derSz = 0;
FILE* file;
const char* certFile = kGoogleCom;
const char* caDir = kCACertsDir;
#if 0
wolfSSL_Debugging_ON();
#endif
/* Optional argv[1] overrides the CA directory if the chain changes. */
if (argc > 1) {
certFile = argv[1];
caDir = argv[1];
}
ret = wolfSSL_Init();
if (ret != WOLFSSL_SUCCESS) {
printf("wolfSSL_Init failed (%d)\n", ret);
return ret;
}
/* Fetch the live leaf certificate so nothing static can expire. */
der = fetch_leaf_der(kServerHost, kServerPort, caDir, &derSz);
if (der == NULL) {
printf("Could not fetch %s certificate\n", kServerHost);
wolfSSL_Cleanup();
return -1;
}
printf("Fetched %s certificate (%d bytes)\n", kServerHost, derSz);
/* Create certificate manager context */
pCm = wolfSSL_CertManagerNew();
if (pCm) {
#ifdef HAVE_OCSP
/* Enable OCSP */
ret = wolfSSL_CertManagerEnableOCSP(pCm, 0);
if (ret == WOLFSSL_SUCCESS) {
/* Setup callbacks for OCSP */
ret = wolfSSL_CertManagerSetOCSP_Cb(pCm,
OcspLookupNonBlockCb,
OcspRespFreeCb,
NULL /* optional context */
);
}
#else
ret = WOLFSSL_SUCCESS;
#endif
if (ret == WOLFSSL_SUCCESS) {
/* Load root CAs into Certificate Manager */
ret = wolfSSL_CertManagerLoadCA(pCm, NULL, kCACertsDir);
printf("Loaded Trusted CA dir %s (ret %d)\n", kCACertsDir, ret);
}
if (ret == WOLFSSL_SUCCESS) {
/* Load PEM to buffer */
file = fopen(certFile, "rb");
if (file != NULL) {
pemSz = fread(pem, 1, sizeof(pem), file);
fclose(file);
}
/* Convert certificate to DER/ASN.1 */
ret = wc_CertPemToDer(
(byte*)pem, pemSz,
der, sizeof(der), CERT_TYPE);
if (ret >= 0) {
derSz = ret;
ret = WOLFSSL_SUCCESS;
}
printf("Convert Google.com PEM cert to DER (ret %d)\n", ret);
}
if (ret == WOLFSSL_SUCCESS) {
/* Load and verify certificate */
ret = wolfSSL_CertManagerVerifyBuffer(pCm,
der, derSz, WOLFSSL_FILETYPE_ASN1);
printf("Verify Google.com cert: %d\n", ret);
}
#ifdef HAVE_OCSP
if (ret == WOLFSSL_SUCCESS) {
/* Check OCSP for certificate */
do {
ret = wolfSSL_CertManagerCheckOCSP(pCm,
der, derSz);
} while (ret == OCSP_WANT_READ);
printf("Check OCSP for Google.com (ret %d)\n", ret);
}
#endif
wolfSSL_CertManagerFree(pCm);
}
else {
ret = MEMORY_E;
if (pCm == NULL) {
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL_Cleanup();
return MEMORY_E;
}
printf("Ret = %d: %s\n",
ret, (ret == WOLFSSL_SUCCESS) ?
"success" :
#ifdef HAVE_OCSP
/* Enable OCSP */
ret = wolfSSL_CertManagerEnableOCSP(pCm, 0);
if (ret == WOLFSSL_SUCCESS) {
/* Setup callbacks for OCSP */
ret = wolfSSL_CertManagerSetOCSP_Cb(pCm,
OcspLookupNonBlockCb,
OcspRespFreeCb,
NULL /* optional context */
);
}
#else
ret = WOLFSSL_SUCCESS;
#endif
if (ret == WOLFSSL_SUCCESS) {
/* Load root CAs into Certificate Manager */
ret = wolfSSL_CertManagerLoadCA(pCm, NULL, caDir);
printf("Loaded Trusted CA dir %s (ret %d)\n", caDir, ret);
}
if (ret == WOLFSSL_SUCCESS) {
/* Verify the fetched certificate against the loaded CAs */
ret = wolfSSL_CertManagerVerifyBuffer(pCm, der, derSz,
WOLFSSL_FILETYPE_ASN1);
printf("Verify %s cert: %d\n", kServerHost, ret);
}
#ifdef HAVE_OCSP
if (ret == WOLFSSL_SUCCESS) {
/* Check OCSP for the certificate */
do {
ret = wolfSSL_CertManagerCheckOCSP(pCm, der, derSz);
} while (ret == OCSP_WANT_READ);
printf("Check OCSP for %s (ret %d)\n", kServerHost, ret);
}
#endif
wolfSSL_CertManagerFree(pCm);
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL_Cleanup();
printf("Ret = %d: %s\n",
ret, (ret == WOLFSSL_SUCCESS) ?
"success" :
wc_GetErrorString(ret));
/* Exit 0 on success so scripts and CI can tell pass from fail. */
if (ret == WOLFSSL_SUCCESS) {
return 0;
}
return ret;
}

File diff suppressed because it is too large Load Diff