This repository shows how to use the OpenSSL C API with modern C++.
This mainly shows using the OpenSSL C API
primitives as smart pointers (no
XXX_free needed) and has a bunch of
unit tests demonstrating different
validation methods as well as a few
example data gathering methods (for example
to get a certificate subject as a std::string
).
It also shows how to link against OpenSSL
using CMake and CMakeLists.txt
.
The OpenSSL C API is horrible for (spoiled) modern
C++ developers. Manual frees all over the place,
every _sk_TYPE
has its own _new
and _free
,
internal pointers here and there, and most important,
the documentation sucks. It's extensive, but not useful.
For example, every C method call is described, but not the
overall picture. Every individual method is described, the command
line tools are as well, but not something like,
"Here's how to do X with the C API", where X
could be anything from validating a certificate
against the system-provided chain, a self signed chain,
or checking the purpose, extensions, signing a message,
generating a keypair, or whatever.
Note that cloning this repository does not automatically include the nested git projects.
They can be included by adding the --recurse-submodules
when cloning.
SonarCloud runs static analysis on the code, scans coverage and checks for vulnerabilities.
Valgrind shows no issues when running the tests. You might even say this repo is memory-safe.
The tst
folder has a boatload of unit tests checking
valid, invalid and other scenarios, like expired
certificates or custom (*verify_cb)(int, X509_STORE_CTX *)
lambdas that are passed as function pointers
(because they don't capture anything).
Take a look at the unit tests!
The code shows how to validate if a certificate (PEM encoded) is signed by another certificate.
The code also shows how to validate a certificate against a chain, building a trust store up to a trusted root.
The repo includes a fake root certificate
with the same subject, to show that
the code does not validate by comparing
issuer <> subject, but uses the actual
OpenSSL x509_verify
method.
The code shows how to use the OpenSSL
primitives as unique_ptr
. When those
go out of scope, no manual delete
or
free
is needed. This is important because
in between the new
and the free
, you
might get an exception which leaves a
memory leak.
The code also shows how to print the
issuer
and subject
field of a
certificate. It includes an intermediate
method to convert a PEM file to an
X509
object.
Furthermore the code shows how to parse the subjectAlternativeName.
The unit tests further show how to use the code.
To validate an expired certificate, you can either
pass the X509_V_FLAG_NO_CHECK_TIME
as
X509_VERIFY_PARAM*
(also provided as unique_ptr
),
or provide a custom callback lambda mimicking a
int (*verify_cb)(int, X509_STORE_CTX *)
:
auto verify_callback_accept_exipred = [](int ok, X509_STORE_CTX *ctx) -> int {
/* Tolerate certificate expiration */
if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED)
return 1;
/* Otherwise don't override */
return ok;
};
The repo was tested with OpenSSL 3.0.2 on Ubuntu 22.04.
Make sure to apt install libssl-dev
.
Compile:
mkdir build
cd build
cmake ..
make
Example output:
/home/remy/CLionProjects/cert-test/cmake-build-debug/cert_test
certificate subject: CN=raymii.org
certificate sans : raymii.org www.raymii.org
certificate issuer : C=GB,ST=Greater Manchester,L=Salford,O=Sectigo Limited,CN=Sectigo RSA Domain Validation Secure Server CA
Issuer signed by chain (should be valid): Signature valid
** Take a look at the unit tests for more usage examples! **
GNU GPL v3
Copyright (c) 2023 Remy van Elst
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.