OpenVPN 3 Core Library
Loading...
Searching...
No Matches
x509cert.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// Wrap a mbed TLS x509_crt object
13
14#ifndef OPENVPN_MBEDTLS_PKI_X509CERT_H
15#define OPENVPN_MBEDTLS_PKI_X509CERT_H
16
17#include <string>
18#include <sstream>
19#include <cstring>
20#include <iostream>
21
22#include <mbedtls/x509.h>
23#include <mbedtls/pem.h>
24#include <mbedtls/base64.h>
25
28#include <openvpn/common/rc.hpp>
31
32namespace openvpn::MbedTLSPKI {
33
34class X509Cert : public RC<thread_unsafe_refcount>
35{
36 public:
38
40 : chain(nullptr)
41 {
42 }
43
44 X509Cert(const std::string &cert_txt, const std::string &title, const bool strict)
45 : chain(nullptr)
46 {
47 try
48 {
49 parse(cert_txt, title, strict);
50 }
51 catch (...)
52 {
53 dealloc();
54 throw;
55 }
56 }
57
58 void parse(const std::string &cert_txt, const std::string &title, const bool strict)
59 {
60 alloc();
61
62 if (cert_txt.empty())
63 throw MbedTLSException(title + " certificate is undefined");
64
65 // cert_txt.length() is increased by 1 as it does not include the NULL-terminator
66 // which mbedtls_x509_crt_parse() expects to see.
67 const int status = mbedtls_x509_crt_parse(chain,
68 (const unsigned char *)cert_txt.c_str(),
69 cert_txt.length() + 1);
70 if (status < 0)
71 {
72 throw MbedTLSException("error parsing " + title + " certificate", status);
73 }
74 if (status > 0)
75 {
76 std::ostringstream os;
77 os << status << " certificate(s) in " << title << " bundle failed to parse";
78 if (strict)
79 throw MbedTLSException(os.str());
80 else
81 OPENVPN_LOG("MBEDTLS: " << os.str());
82 }
83 }
84
85 static std::string der_to_pem(const unsigned char *der, size_t der_size)
86 {
87 size_t olen = 0;
88 int ret;
89
90 ret = mbedtls_pem_write_buffer(begin_cert,
92 der,
93 der_size,
94 NULL,
95 0,
96 &olen);
97 if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
98 throw MbedTLSException("X509Cert::extract: can't calculate PEM size");
99
100 BufferAllocated buff(olen);
101
102 ret = mbedtls_pem_write_buffer(begin_cert,
103 end_cert,
104 der,
105 der_size,
106 buff.data(),
107 buff.max_size(),
108 &olen);
109 if (ret)
110 throw MbedTLSException("X509Cert::extract: can't write PEM buffer");
111
112 return std::string((const char *)buff.data());
113 }
114
115 std::string extract() const
116 {
117 return der_to_pem(chain->raw.p, chain->raw.len);
118 }
119
120 std::vector<std::string> extract_extra_certs() const
121 {
122 std::vector<std::string> extra_certs;
123
124 /* extra certificates are appended to the main one */
125 for (mbedtls_x509_crt *cert = chain->next; cert; cert = cert->next)
126 {
127 extra_certs.push_back(der_to_pem(cert->raw.p, cert->raw.len));
128 }
129 return extra_certs;
130 }
131
132 mbedtls_x509_crt *get() const
133 {
134 return chain;
135 }
136
137 virtual ~X509Cert()
138 {
139 dealloc();
140 }
141
142 protected:
143 void alloc()
144 {
145 if (!chain)
146 {
147 chain = new mbedtls_x509_crt;
148 mbedtls_x509_crt_init(chain);
149 }
150 }
151
152 mbedtls_x509_crt *chain;
153
154 private:
155 void dealloc()
156 {
157 if (chain)
158 {
159 mbedtls_x509_crt_free(chain);
160 delete chain;
161 chain = nullptr;
162 }
163 }
164
165 constexpr static const char *begin_cert = "-----BEGIN CERTIFICATE-----\n";
166 constexpr static const char *end_cert = "-----END CERTIFICATE-----\n";
167};
168} // namespace openvpn::MbedTLSPKI
169
170#endif
size_t max_size() const
Return the maximum allowable size value in T objects given the current offset (without considering re...
Definition buffer.hpp:1377
T * data()
Get a mutable pointer to the start of the array.
Definition buffer.hpp:1450
std::vector< std::string > extract_extra_certs() const
Definition x509cert.hpp:120
void parse(const std::string &cert_txt, const std::string &title, const bool strict)
Definition x509cert.hpp:58
mbedtls_x509_crt * get() const
Definition x509cert.hpp:132
X509Cert(const std::string &cert_txt, const std::string &title, const bool strict)
Definition x509cert.hpp:44
static constexpr const char * end_cert
Definition x509cert.hpp:166
std::string extract() const
Definition x509cert.hpp:115
mbedtls_x509_crt * chain
Definition x509cert.hpp:152
static std::string der_to_pem(const unsigned char *der, size_t der_size)
Definition x509cert.hpp:85
static constexpr const char * begin_cert
Definition x509cert.hpp:165
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
#define OPENVPN_LOG(args)
const std::string cert_txt
std::string ret
std::ostringstream os