OpenVPN 3 Core Library
Loading...
Searching...
No Matches
cipheraead.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 AEAD API.
13
14#pragma once
15
16#include <string>
17
18#include <mbedtls/gcm.h>
19
27
28namespace openvpn::MbedTLSCrypto {
30{
31 public:
32 OPENVPN_EXCEPTION(mbedtls_aead_error);
33
34
35 // mbed TLS cipher constants
36 enum
37 {
38 IV_LEN = 12,
39 AUTH_TAG_LEN = 16
40 };
41
42#if 0
43 // mbed TLS encrypt/decrypt return values
44 enum {
45 GCM_AUTH_FAILED = MBEDTLS_ERR_GCM_AUTH_FAILED,
46 SUCCESS = 0,
47 };
48#endif
49
50 CipherContextAEAD() = default;
51
53 {
54 erase();
55 }
56
58 : CipherContextCommon(std::move(other)), aead_usage_limit_(other.aead_usage_limit_)
59 {
60 }
61
63 {
64 CipherContextAEAD temp(std::move(other));
65 ctx = temp.ctx;
67 temp.ctx = {};
68 temp.initialized = false;
70 return *this;
71 }
72
73
74 void init(SSLLib::Ctx libctx,
75 const CryptoAlgs::Type alg,
76 const unsigned char *key,
77 const unsigned int keysize,
78 const int mode)
79 {
80 erase();
81
82 check_mode(mode);
83
84 // get cipher type
85 unsigned int ckeysz = 0;
86 const mbedtls_cipher_type_t cid = cipher_type(alg, ckeysz);
87 if (cid == MBEDTLS_CIPHER_NONE)
88 OPENVPN_THROW(mbedtls_aead_error, CryptoAlgs::name(alg) << ": not usable");
89
90 if (ckeysz > keysize)
91 throw mbedtls_aead_error("insufficient key material");
92
93 auto *ci = mbedtls_cipher_info_from_type(cid);
94
95 // initialize cipher context with cipher type
96 if (mbedtls_cipher_setup(&ctx, ci) < 0)
97 throw mbedtls_aead_error("mbedtls_cipher_setup");
98
99 if (mbedtls_cipher_setkey(&ctx, key, ckeysz * 8, (mbedtls_operation_t)mode) < 0)
100 throw mbedtls_aead_error("mbedtls_cipher_setkey");
101
102 aead_usage_limit_ = {alg};
103 initialized = true;
104 }
105
106
107
108 void encrypt(const unsigned char *input,
109 unsigned char *output,
110 size_t length,
111 const unsigned char *iv,
112 unsigned char *tag,
113 const unsigned char *ad,
114 size_t ad_len)
115 {
117 const int status = mbedtls_cipher_auth_encrypt_ext(&ctx,
118 iv,
119 IV_LEN,
120 ad,
121 ad_len,
122 input,
123 length,
124 output,
125 length + AUTH_TAG_LEN,
126 &length,
128 if (unlikely(status))
129 OPENVPN_THROW(mbedtls_aead_error, "mbedtls_cipher_auth_encrypt failed with status=" << status);
130 aead_usage_limit_.update(length + ad_len);
131 }
132
135 {
136 return aead_usage_limit_;
137 }
138
153 bool decrypt(const unsigned char *input,
154 unsigned char *output,
155 size_t length,
156 const unsigned char *iv,
157 const unsigned char *tag,
158 const unsigned char *ad,
159 size_t ad_len)
160 {
162
163 if (unlikely(tag != nullptr))
164 {
165 /* If we are called with a non-null tag, the function is not going to be able to decrypt */
166 throw mbedtls_aead_error("tag must be null for aead decrypt");
167 }
168
169 size_t olen;
170 const int status = mbedtls_cipher_auth_decrypt_ext(&ctx,
171 iv,
172 IV_LEN,
173 ad,
174 ad_len,
175 input,
176 length,
177 output,
178 length - AUTH_TAG_LEN,
179 &olen,
181
182 return (olen == length - AUTH_TAG_LEN) && (status == 0);
183 }
184
185 bool is_initialized() const
186 {
187 return initialized;
188 }
189
190 static bool is_supported(void *libctx, const CryptoAlgs::Type alg)
191 {
192 unsigned int keysize;
193 return (cipher_type(alg, keysize) != MBEDTLS_CIPHER_NONE);
194 }
195
196 private:
198 static mbedtls_cipher_type_t cipher_type(const CryptoAlgs::Type alg, unsigned int &keysize)
199 {
200 switch (alg)
201 {
203 keysize = 16;
204 return MBEDTLS_CIPHER_AES_128_GCM;
206 keysize = 24;
207 return MBEDTLS_CIPHER_AES_192_GCM;
209 keysize = 32;
210 return MBEDTLS_CIPHER_AES_256_GCM;
211#ifdef MBEDTLS_CHACHAPOLY_C
213 keysize = 32;
214 return MBEDTLS_CIPHER_CHACHA20_POLY1305;
215#endif
216 default:
217 keysize = 0;
218 return MBEDTLS_CIPHER_NONE;
219 }
220 }
221};
222} // namespace openvpn::MbedTLSCrypto
void update(const std::size_t outlen)
static mbedtls_cipher_type_t cipher_type(const CryptoAlgs::Type alg, unsigned int &keysize)
static bool is_supported(void *libctx, const CryptoAlgs::Type alg)
CipherContextAEAD & operator=(CipherContextAEAD &&other)
const Crypto::AEADUsageLimit & get_usage_limit()
bool decrypt(const unsigned char *input, unsigned char *output, size_t length, const unsigned char *iv, const unsigned char *tag, const unsigned char *ad, size_t ad_len)
void init(SSLLib::Ctx libctx, const CryptoAlgs::Type alg, const unsigned char *key, const unsigned int keysize, const int mode)
void encrypt(const unsigned char *input, unsigned char *output, size_t length, const unsigned char *iv, unsigned char *tag, const unsigned char *ad, size_t ad_len)
CipherContextAEAD(CipherContextAEAD &&other) noexcept
#define OPENVPN_THROW(exc, stuff)
#define unlikely(x)
Definition likely.hpp:22
const char * name(const KeyDerivation kd)
static const char * input[]