OpenVPN 3 Core Library
Loading...
Searching...
No Matches
tls1prf.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#pragma once
13#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
14#include <openssl/core_names.h>
15#include <openssl/params.h>
16#endif
17
18#include <openssl/kdf.h>
19
20
21
23
24namespace openvpn::OpenSSLCrypto {
25
27{
28 public:
29#if OPENSSL_VERSION_NUMBER >= 0x30000000L
30 static bool PRF(unsigned char *label,
31 const size_t label_len,
32 const unsigned char *sec,
33 const size_t slen,
34 unsigned char *out1,
35 const size_t olen)
36
37 {
38 using EVP_KDF_ptr = std::unique_ptr<EVP_KDF, decltype(&::EVP_KDF_free)>;
39 using EVP_KDF_CTX_ptr = std::unique_ptr<EVP_KDF_CTX, decltype(&::EVP_KDF_CTX_free)>;
40
41 EVP_KDF_ptr kdf{::EVP_KDF_fetch(NULL, "TLS1-PRF", NULL), ::EVP_KDF_free};
42 if (!kdf)
43 {
44 return false;
45 }
46
47 EVP_KDF_CTX_ptr kctx{::EVP_KDF_CTX_new(kdf.get()), ::EVP_KDF_CTX_free};
48
49 if (!kctx)
50 {
51 return false;
52 }
53
54 OSSL_PARAM params[4];
55 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
56 const_cast<char *>(SN_md5_sha1),
57 strlen(SN_md5_sha1));
58 params[1] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET,
59 const_cast<unsigned char *>(sec),
60 slen);
61 params[2] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
62 label,
63 label_len);
64 params[3] = OSSL_PARAM_construct_end();
65
66 if (::EVP_KDF_derive(kctx.get(), out1, olen, params) <= 0)
67 {
68 return false;
69 }
70
71 return true;
72 }
73#else
74 static bool PRF(unsigned char *label,
75 const size_t label_len,
76 const unsigned char *sec,
77 const size_t slen,
78 unsigned char *out1,
79 const size_t olen)
80 {
81 /* TODO use EVP_PKEY_CTX_new_from_name and library context for OpenSSL 3.0 but
82 * this needs passing the library context down here.*/
83 using EVP_PKEY_CTX_ptr = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>;
84
85 EVP_PKEY_CTX_ptr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL), ::EVP_PKEY_CTX_free);
86
87 if (!pctx.get())
88 return false;
89
90 if (!EVP_PKEY_derive_init(pctx.get()))
91 return false;
92
93 if (!EVP_PKEY_CTX_set_tls1_prf_md(pctx.get(), EVP_md5_sha1()))
94 return false;
95 if (!is_safe_conversion<int>(slen)
96 || !EVP_PKEY_CTX_set1_tls1_prf_secret(pctx.get(), sec, static_cast<int>(slen)))
97 return false;
98
99 if (!is_safe_conversion<int>(label_len)
100 || !EVP_PKEY_CTX_add1_tls1_prf_seed(pctx.get(), label, static_cast<int>(label_len)))
101 return false;
102
103 size_t out_len = olen;
104 if (!EVP_PKEY_derive(pctx.get(), out1, &out_len))
105 return false;
106
107 if (out_len != olen)
108 return false;
109
110 return true;
111 }
112#endif
113};
114
115} // namespace openvpn::OpenSSLCrypto
static bool PRF(unsigned char *label, const size_t label_len, const unsigned char *sec, const size_t slen, unsigned char *out1, const size_t olen)
Definition tls1prf.hpp:74
static const std::string out1