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
14#include <mbedtls/ssl.h>
15
16namespace openvpn::MbedTLSCrypto {
18{
19 public:
20#ifdef HAVE_MBEDTLS_SSL_TLS_PRF
21 /* mbedtls-2.18.0 to mbed TLS 3.0 */
22 static bool PRF(unsigned char *label,
23 const size_t label_len,
24 const unsigned char *sec,
25 const size_t slen,
26 unsigned char *output,
27 const size_t olen)
28 {
29 return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1, sec,
30 slen, "", label, label_len, output,
31 olen));
32 }
33#else
34 /*
35 * Use the TLS PRF function for generating data channel keys.
36 * This code is adapted from the OpenSSL library.
37 *
38 * TLS generates keys as such:
39 *
40 * master_secret[48] = PRF(pre_master_secret[48], "master secret",
41 * ClientHello.random[32] + ServerHello.random[32])
42 *
43 * key_block[] = PRF(SecurityParameters.master_secret[48],
44 * "key expansion",
45 * SecurityParameters.server_random[32] +
46 * SecurityParameters.client_random[32]);
47 *
48 * Notes:
49 *
50 * (1) key_block contains a full set of 4 keys.
51 * (2) The pre-master secret is generated by the client.
52 */
53
54 public:
55 static bool PRF(unsigned char *label,
56 const size_t label_len,
57 const unsigned char *sec,
58 const size_t slen,
59 unsigned char *out1,
60 const size_t olen)
61 {
62 size_t len, i;
63 const unsigned char *S1, *S2;
64 unsigned char *out2;
65
66 out2 = new unsigned char[olen];
67
68 len = slen / 2;
69 S1 = sec;
70 S2 = &(sec[len]);
71 len += (slen & 1); /* add for odd, make longer */
72
73 hash(CryptoAlgs::MD5, S1, len, label, label_len, out1, olen);
74 hash(CryptoAlgs::SHA1, S2, len, label, label_len, out2, olen);
75
76 for (i = 0; i < olen; i++)
77 out1[i] ^= out2[i];
78
79 std::memset(out2, 0, olen);
80 delete[] out2;
81 return true;
82 }
83
84 private:
85 static void hash(const CryptoAlgs::Type md,
86 const unsigned char *sec,
87 const size_t sec_len,
88 const unsigned char *seed,
89 const size_t seed_len,
90 unsigned char *out,
91 size_t olen)
92 {
93 size_t j;
94 unsigned char A1[HMACContext::MAX_HMAC_SIZE];
95 size_t A1_len;
96 HMACContext ctx;
97 HMACContext ctx_tmp;
98 const size_t chunk = CryptoAlgs::size(md);
99
100 ctx.init(md, sec, sec_len);
101 ctx_tmp.init(md, sec, sec_len);
102 ctx.update(seed, seed_len);
103 A1_len = ctx.final(A1);
104
105 for (;;)
106 {
107 ctx.reset();
108 ctx_tmp.reset();
109 ctx.update(A1, A1_len);
110 ctx_tmp.update(A1, A1_len);
111 ctx.update(seed, seed_len);
112
113 if (olen > chunk)
114 {
115 j = ctx.final(out);
116 out += j;
117 olen -= j;
118 A1_len = ctx_tmp.final(A1); /* calc the next A1 value */
119 }
120 else /* last one */
121 {
122 A1_len = ctx.final(A1);
123 memcpy(out, A1, olen);
124 break;
125 }
126 }
127 std::memset(A1, 0, sizeof(A1));
128 }
129
130#endif
131};
132
133} // namespace openvpn::MbedTLSCrypto
void update(const unsigned char *in, const size_t size)
Definition hmac.hpp:75
size_t final(unsigned char *out)
Definition hmac.hpp:82
void init(const CryptoAlgs::Type digest, const unsigned char *key, const size_t key_size)
Definition hmac.hpp:56
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:55
static void hash(const CryptoAlgs::Type md, const unsigned char *sec, const size_t sec_len, const unsigned char *seed, const size_t seed_len, unsigned char *out, size_t olen)
Definition tls1prf.hpp:85
size_t size(const Type type)
static const std::string out1
static const std::string out2
static std::stringstream out
Definition test_path.cpp:10