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