OpenVPN
openssl_compat.h
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 * Copyright (C) 2010-2026 Sentyron B.V. <openvpn@sentyron.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, see <https://www.gnu.org/licenses/>.
22 */
23
34#ifndef OPENSSL_COMPAT_H_
35#define OPENSSL_COMPAT_H_
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include "buffer.h"
42
43#include <openssl/rsa.h>
44#include <openssl/ssl.h>
45#include <openssl/x509.h>
46#include <openssl/err.h>
47
48/* Define the type of error. This is something that is less
49 * intrusive than casts everywhere */
50#if defined(OPENSSL_IS_AWSLC)
51typedef uint32_t openssl_err_t;
52#else
53typedef unsigned long openssl_err_t;
54#endif
55
56
57/* Functionality missing in 1.1.0 */
58#if OPENSSL_VERSION_NUMBER < 0x10101000L && !defined(ENABLE_CRYPTO_WOLFSSL)
59#define SSL_CTX_set1_groups SSL_CTX_set1_curves
60#endif
61
62/* Functionality missing in LibreSSL before 3.5 */
63#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL
69static inline void
70X509_OBJECT_free(X509_OBJECT *obj)
71{
72 if (obj)
73 {
74 X509_OBJECT_free_contents(obj);
75 OPENSSL_free(obj);
76 }
77}
78
79#define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
80#define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
81#endif
82
83#if defined(LIBRESSL_VERSION_NUMBER)
84#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT
85#endif
86
87#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050400fL \
88 || defined(OPENSSL_IS_AWSLC)
89#define SSL_get_peer_tmp_key SSL_get_server_tmp_key
90#endif
91
92/* Functionality missing in 1.1.1 */
93#if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_EC)
94
95/* Note that this is not a perfect emulation of the new function but
96 * is good enough for our case of printing certificate details during
97 * handshake */
98static inline int
99EVP_PKEY_get_group_name(EVP_PKEY *pkey, char *gname, size_t gname_sz, size_t *gname_len)
100{
101 const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
102 if (ec == NULL)
103 {
104 return 0;
105 }
106 const EC_GROUP *group = EC_KEY_get0_group(ec);
107 int nid = EC_GROUP_get_curve_name(group);
108
109 if (nid == 0)
110 {
111 return 0;
112 }
113 const char *curve = OBJ_nid2sn(nid);
114 if (!curve)
115 {
116 curve = "(error fetching curve name)";
117 }
118
119 strncpynt(gname, curve, gname_sz);
120
121 /* strncpynt ensures null termination so just strlen is fine here */
122 *gname_len = strlen(curve);
123 return 1;
124}
125#endif /* if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_EC) */
126
127#if OPENSSL_VERSION_NUMBER < 0x30000000L
128#define EVP_MD_get0_name EVP_MD_name
129#define EVP_CIPHER_get0_name EVP_CIPHER_name
130#define EVP_CIPHER_CTX_get_mode EVP_CIPHER_CTX_mode
131
133#define SSL_CTX_new_ex(libctx, propq, method) SSL_CTX_new((method))
134
135/* Some safe typedefs to avoid too many ifdefs */
136typedef void OSSL_LIB_CTX;
137typedef void OSSL_PROVIDER;
138
139/* Mimics the functions but only when the default context without
140 * options is chosen */
141static inline const EVP_CIPHER *
142EVP_CIPHER_fetch(void *ctx, const char *algorithm, const char *properties)
143{
144 ASSERT(!ctx);
145 ASSERT(!properties);
146 return EVP_get_cipherbyname(algorithm);
147}
148
149static inline const EVP_MD *
150EVP_MD_fetch(void *ctx, const char *algorithm, const char *properties)
151{
152 ASSERT(!ctx);
153 ASSERT(!properties);
154 return EVP_get_digestbyname(algorithm);
155}
156
157static inline void
158EVP_CIPHER_free(const EVP_CIPHER *cipher)
159{
160 /* OpenSSL 1.1.1 and lower use only const EVP_CIPHER, nothing to free */
161}
162
163static inline void
164EVP_MD_free(const EVP_MD *md)
165{
166 /* OpenSSL 1.1.1 and lower use only const EVP_MD, nothing to free */
167}
168
169static inline openssl_err_t
170ERR_get_error_all(const char **file, int *line, const char **func, const char **data, int *flags)
171{
172 static const char *empty = "";
173 *func = empty;
174 openssl_err_t err = ERR_get_error_line_data(file, line, data, flags);
175 return err;
176}
177
178#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
179
180#if OPENSSL_VERSION_NUMBER < 0x30500000 \
181 && (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER > 0x3050400fL)
182static inline int
183SSL_get0_peer_signature_name(SSL *ssl, const char **sigalg)
184{
185 int peer_sig_nid;
186 if (SSL_get_peer_signature_nid(ssl, &peer_sig_nid) && peer_sig_nid != NID_undef)
187 {
188 *sigalg = OBJ_nid2sn(peer_sig_nid);
189 return 1;
190 }
191 return 0;
192}
193#elif defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER <= 0x3050400fL
194/* The older LibreSSL version do not implement any variant of getting the peer
195 * signature */
196static inline int
197SSL_get0_peer_signature_name(const SSL *ssl, const char **sigalg)
198{
199 *sigalg = NULL;
200 return 0;
201}
202#endif /* if OPENSSL_VERSION_NUMBER < 0x30500000 && (!defined(LIBRESSL_VERSION_NUMBER) || \
203 LIBRESSL_VERSION_NUMBER > 0x3050400fL) */
204
205#if OPENSSL_VERSION_NUMBER < 0x30200000L && OPENSSL_VERSION_NUMBER >= 0x30000000L
206static inline const char *
207SSL_get0_group_name(SSL *s)
208{
209 int nid = (int)SSL_get_negotiated_group(s);
210 return SSL_group_to_name(s, nid);
211}
212#endif
213
214/* Introduced in OpenSSL 3.6.0 */
215#ifndef EVP_CIPH_FLAG_ENC_THEN_MAC
216#define EVP_CIPH_FLAG_ENC_THEN_MAC 0x10000000
217#endif
218
219#endif /* OPENSSL_COMPAT_H_ */
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:362
static openssl_err_t ERR_get_error_all(const char **file, int *line, const char **func, const char **data, int *flags)
static void EVP_CIPHER_free(const EVP_CIPHER *cipher)
void OSSL_PROVIDER
static int SSL_get0_peer_signature_name(SSL *ssl, const char **sigalg)
static const EVP_CIPHER * EVP_CIPHER_fetch(void *ctx, const char *algorithm, const char *properties)
void OSSL_LIB_CTX
static void EVP_MD_free(const EVP_MD *md)
static const EVP_MD * EVP_MD_fetch(void *ctx, const char *algorithm, const char *properties)
unsigned long openssl_err_t
static int EVP_PKEY_get_group_name(EVP_PKEY *pkey, char *gname, size_t gname_sz, size_t *gname_len)
#define ASSERT(x)
Definition error.h:219