OpenVPN
siphash_openssl.c
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) 2026 Arne Schwabe <arne@rfc2549.org>
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
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include "siphash.h"
29#include "siphash_openssl.h"
30
31#ifdef ENABLE_CRYPTO_OPENSSL
32#include <openssl/opensslv.h>
33#endif
34
35/* OpenSSL siphash is currently 2-3 times slower than the reference
36 * implementation, so we only use it for unit testing that our implementation
37 * and OpenSSL agree */
38#if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
39#include <openssl/evp.h>
40#include "crypto_openssl.h"
41#include "crypto_backend.h"
42#include "buffer.h"
43
44struct siphash_context
45{
46 EVP_MAC *mac;
47 EVP_MAC_CTX *ctx;
48 size_t size;
49 OSSL_PARAM params[3];
50};
51
52/*
53 * Computes a SipHash value
54 * in: pointer to input data (read-only)
55 * inlen: input data length in bytes (any size_t value)
56 * k: pointer to the key data (read-only), must be 16 bytes
57 * out: pointer to output data (write-only), outlen bytes must be allocated
58 * outlen: length of the output in bytes, must be 8 or 16
59 */
60int
61siphash_openssl(void *sip_context, const void *in, const size_t inlen,
62 const void *k, uint8_t *out, const size_t outlen)
63{
64 struct siphash_context *sip = sip_context;
65
66
67 sip->params[1] = OSSL_PARAM_construct_octet_string("key", (void *)k,
69 if (!EVP_MAC_init(sip->ctx, NULL, 0, sip->params))
70 {
71 crypto_msg(M_FATAL, "EVP_MAC_init failed");
72 }
73 EVP_MAC_update(sip->ctx, in, inlen);
74
75 size_t outl = 0;
76 EVP_MAC_final(sip->ctx, out, &outl, outlen);
77 return 0;
78}
79
80void *
81siphash_openssl_init(size_t hash_size)
82{
83 struct siphash_context *sip;
84 ALLOC_OBJ(sip, struct siphash_context);
85
86 sip->mac = EVP_MAC_fetch(NULL, "SIPHASH", NULL);
87 if (!sip->mac)
88 {
89 /* Our OpenSSL library does not support SIPHASH */
90 return sip;
91 }
92 sip->ctx = EVP_MAC_CTX_new(sip->mac);
93
94 /* OpenSSL will truly hold a pointer to an int in that parameter */
95 sip->size = hash_size;
96 sip->params[0] = OSSL_PARAM_construct_size_t("size", &sip->size);
97 /* params[1] will hold the key that changes which each invocation */
98 sip->params[2] = OSSL_PARAM_construct_end();
99 return sip;
100}
101
102bool
103siphash_openssl_available(const void *sip_context)
104{
105 const struct siphash_context *sip = sip_context;
106
107 return (bool)(sip->mac);
108}
109
110void
111siphash_openssl_uninit(void *sip_context)
112{
113 struct siphash_context *sip = sip_context;
114 EVP_MAC_CTX_free(sip->ctx);
115 EVP_MAC_free(sip->mac);
116 free(sip_context);
117}
118#else
119/* Do avoid a lot more ifdefs in the test we put dummy functions here */
120// cppcheck-suppress-begin constParameterPointer ; stubs
121
122int
123siphash_openssl(void *sip_context, const void *in, const size_t inlen,
124 const void *k, uint8_t *out, const size_t outlen)
125{
126 return -1;
127}
128
129bool
130siphash_openssl_available(const void *sip_context)
131{
132 return false;
133}
134
135void *
136siphash_openssl_init(size_t hash_size)
137{
138 return NULL;
139}
140
141void
142siphash_openssl_uninit(void *sip_context)
143{
144}
145
146// cppcheck-suppress-end constParameterPointer
147
148#endif /* if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L */
Buffer management functions and garbage collection.
#define ALLOC_OBJ(dptr, type)
Allocate memory for a single object of the given type.
Definition buffer.h:2016
Data Channel Cryptography SSL library-specific backend interface.
Data Channel Cryptography OpenSSL-specific backend interface.
#define crypto_msg(flags,...)
Retrieve any OpenSSL errors, then print the supplied error message.
#define M_FATAL
Definition error.h:90
#define SIPHASH_KEY_SIZE
Definition siphash.h:35
void * siphash_openssl_init(size_t hash_size)
void siphash_openssl_uninit(void *sip_context)
Free the siphash context used for the crypto library.
int siphash_openssl(void *sip_context, const void *in, const size_t inlen, const void *k, uint8_t *out, const size_t outlen)
Calculates SIPHASH using the crypto library function.
bool siphash_openssl_available(const void *sip_context)
Returns if the crypto library is available (and should be used).