OpenVPN 3 Core Library
Loading...
Searching...
No Matches
cipher.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// Wrap the mbed TLS cipher API defined in <mbedtls/cipher.h> so
13// that it can be used as part of the crypto layer of the OpenVPN core.
14
15#ifndef OPENVPN_MBEDTLS_CRYPTO_CIPHER_H
16#define OPENVPN_MBEDTLS_CRYPTO_CIPHER_H
17
18#include <string>
19
20#include <mbedtls/cipher.h>
21
26
29{
30 public:
31 OPENVPN_SIMPLE_EXCEPTION(mbedtls_cipher_mode_error);
32 OPENVPN_SIMPLE_EXCEPTION(mbedtls_cipher_uninitialized);
33
34 // mode parameter for constructor
35 enum
36 {
37 MODE_UNDEF = MBEDTLS_OPERATION_NONE,
38 ENCRYPT = MBEDTLS_ENCRYPT,
39 DECRYPT = MBEDTLS_DECRYPT
40 };
41
47 bool constexpr requires_authtag_at_end()
48 {
49 return true;
50 }
51
52 protected:
54
56 {
57 erase();
58 }
59
62
63
65 {
66 ctx = other.ctx;
67 initialized = other.initialized;
68 other.ctx = {};
69 other.initialized = false;
70 }
71
73 {
74 ctx = other.ctx;
75 initialized = other.initialized;
76 other.ctx = {};
77 other.initialized = false;
78 return *this;
79 }
80
81 static void check_mode(int mode)
82 {
83 // check that mode is valid
84 if (!(mode == ENCRYPT || mode == DECRYPT))
85 throw mbedtls_cipher_mode_error();
86 }
87
88 void erase()
89 {
90 if (initialized)
91 {
92 mbedtls_cipher_free(&ctx);
93 initialized = false;
94 }
95 }
96
97 void check_initialized() const
98 {
100 throw mbedtls_cipher_uninitialized();
101 }
102
103 bool initialized = false;
104 mbedtls_cipher_context_t ctx;
105};
106
108 : public CipherContextCommon
109{
110 CipherContext(const CipherContext &) = delete;
112
113 public:
114 OPENVPN_EXCEPTION(mbedtls_cipher_error);
115
116 // mode parameter for constructor
117 enum
118 {
119 MODE_UNDEF = MBEDTLS_OPERATION_NONE,
120 ENCRYPT = MBEDTLS_ENCRYPT,
121 DECRYPT = MBEDTLS_DECRYPT
122 };
123
124 // mbed TLS cipher constants
125 enum
126 {
127 MAX_IV_LENGTH = MBEDTLS_MAX_IV_LENGTH,
128 CIPH_CBC_MODE = MBEDTLS_MODE_CBC
129 };
130
131 CipherContext() = default;
132
134 {
135 erase();
136 }
137
138 static bool is_supported(SSLLib::Ctx libctx, const CryptoAlgs::Type alg)
139 {
140 return (cipher_type(alg) != nullptr);
141 }
142
143 void init(SSLLib::Ctx libctx,
144 const CryptoAlgs::Type alg,
145 const unsigned char *key,
146 const int mode)
147 {
148 erase();
149
150 check_mode(mode);
151
152 // get cipher type
153 const mbedtls_cipher_info_t *ci = cipher_type(alg);
154 if (!ci)
155 OPENVPN_THROW(mbedtls_cipher_error, CryptoAlgs::name(alg) << ": not usable");
156
157 // initialize cipher context with cipher type
158 if (mbedtls_cipher_setup(&ctx, ci) < 0)
159 throw mbedtls_cipher_error("mbedtls_cipher_setup");
160
161 // set key and encrypt/decrypt mode
162 if (mbedtls_cipher_setkey(&ctx, key, mbedtls_cipher_get_key_bitlen(&ctx), (mbedtls_operation_t)mode) < 0)
163 throw mbedtls_cipher_error("mbedtls_cipher_setkey");
164
165 initialized = true;
166 }
167
168 void reset(const unsigned char *iv)
169 {
171 if (mbedtls_cipher_reset(&ctx) < 0)
172 throw mbedtls_cipher_error("mbedtls_cipher_reset");
173 if (mbedtls_cipher_set_iv(&ctx, iv, iv_length()))
174 throw mbedtls_cipher_error("mbedtls_cipher_set_iv");
175 }
176
177 bool update(unsigned char *out,
178 const size_t max_out_size,
179 const unsigned char *in,
180 const size_t in_size,
181 size_t &out_acc)
182 {
184 size_t outlen;
185 if (mbedtls_cipher_update(&ctx, in, in_size, out, &outlen) >= 0)
186 {
187 out_acc += outlen;
188 return true;
189 }
190 else
191 return false;
192 }
193
194 bool final(unsigned char *out, const size_t max_out_size, size_t &out_acc)
195 {
197 size_t outlen;
198 if (mbedtls_cipher_finish(&ctx, out, &outlen) >= 0)
199 {
200 out_acc += outlen;
201 return true;
202 }
203 else
204 return false;
205 }
206
207 bool is_initialized() const
208 {
209 return initialized;
210 }
211
212 size_t iv_length() const
213 {
215 return mbedtls_cipher_get_iv_size(&ctx);
216 }
217
218 size_t block_size() const
219 {
221 return mbedtls_cipher_get_block_size(&ctx);
222 }
223
224 // return cipher mode (such as CIPH_CBC_MODE, etc.)
225 int cipher_mode() const
226 {
228 return mbedtls_cipher_get_cipher_mode(&ctx);
229 }
230
231 private:
232 static const mbedtls_cipher_info_t *cipher_type(const CryptoAlgs::Type alg)
233 {
234 switch (alg)
235 {
237 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CBC);
239 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_CBC);
241 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CBC);
243 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CTR);
245 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC);
247 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_EDE3_CBC);
248#if MBEDTLS_VERSION_NUMBER < 0x03000000
249 /* no longer supported in newer mbed TLS versions */
251 return mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_BLOWFISH_CBC);
252#endif
253 default:
254 return nullptr;
255 }
256 }
257};
258} // namespace openvpn::MbedTLSCrypto
259
260#endif
CipherContextCommon(CipherContextCommon &&other) noexcept
Definition cipher.hpp:64
CipherContextCommon & operator=(CipherContextCommon &&other)
Definition cipher.hpp:72
CipherContextCommon(const CipherContextCommon &other)=delete
OPENVPN_SIMPLE_EXCEPTION(mbedtls_cipher_uninitialized)
OPENVPN_SIMPLE_EXCEPTION(mbedtls_cipher_mode_error)
CipherContextCommon & operator=(const CipherContextCommon &other)=delete
void init(SSLLib::Ctx libctx, const CryptoAlgs::Type alg, const unsigned char *key, const int mode)
Definition cipher.hpp:143
CipherContext(const CipherContext &)=delete
static bool is_supported(SSLLib::Ctx libctx, const CryptoAlgs::Type alg)
Definition cipher.hpp:138
OPENVPN_EXCEPTION(mbedtls_cipher_error)
bool update(unsigned char *out, const size_t max_out_size, const unsigned char *in, const size_t in_size, size_t &out_acc)
Definition cipher.hpp:177
static const mbedtls_cipher_info_t * cipher_type(const CryptoAlgs::Type alg)
Definition cipher.hpp:232
CipherContext & operator=(const CipherContext &)=delete
void reset(const unsigned char *iv)
Definition cipher.hpp:168
#define OPENVPN_THROW(exc, stuff)
#define unlikely(x)
Definition likely.hpp:22
const char * name(const KeyDerivation kd)
static std::stringstream out
Definition test_path.cpp:10