Tor 0.4.9.8
Loading...
Searching...
No Matches
aes_openssl.c
Go to the documentation of this file.
1/* Copyright (c) 2001, Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5/* See LICENSE for licensing information */
6
7/**
8 * \file aes_openssl.c
9 * \brief Use OpenSSL to implement AES_CTR.
10 **/
11
12#define USE_AES_RAW
13#define TOR_AES_PRIVATE
14
15#include "orconfig.h"
16#include "lib/crypt_ops/aes.h"
18#include "lib/log/util_bug.h"
19#include "lib/arch/bytes.h"
20
21#ifdef _WIN32 /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
22 #include <winsock2.h>
23 #include <ws2tcpip.h>
24#endif
25
26#include "lib/crypt_ops/compat_openssl.h"
27#include <openssl/opensslv.h>
29
30DISABLE_GCC_WARNING("-Wredundant-decls")
31
32#include <stdlib.h>
33#include <string.h>
34#include <openssl/aes.h>
35#include <openssl/evp.h>
36#include <openssl/engine.h>
37#include <openssl/modes.h>
38
39ENABLE_GCC_WARNING("-Wredundant-decls")
40
41#include "lib/log/log.h"
42#include "lib/ctime/di_ops.h"
43
44/* Cached values of our EVP_CIPHER items. If we don't pre-fetch them,
45 * then EVP_CipherInit calls EVP_CIPHER_fetch itself,
46 * which is surprisingly expensive.
47 */
48static const EVP_CIPHER *aes128ctr = NULL;
49static const EVP_CIPHER *aes192ctr = NULL;
50static const EVP_CIPHER *aes256ctr = NULL;
51static const EVP_CIPHER *aes128ecb = NULL;
52static const EVP_CIPHER *aes192ecb = NULL;
53static const EVP_CIPHER *aes256ecb = NULL;
54
55#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(3,0,0) \
56 && !defined(LIBRESSL_VERSION_NUMBER)
57#define RESOLVE_CIPHER(c) \
58 EVP_CIPHER_fetch(NULL, OBJ_nid2sn(EVP_CIPHER_get_nid(c)), "")
59#else
60#define RESOLVE_CIPHER(c) (c)
61#endif
62
63/**
64 * Pre-fetch the versions of every AES cipher with its associated provider.
65 */
66static void
68{
69 aes128ctr = RESOLVE_CIPHER(EVP_aes_128_ctr());
70 aes192ctr = RESOLVE_CIPHER(EVP_aes_192_ctr());
71 aes256ctr = RESOLVE_CIPHER(EVP_aes_256_ctr());
72 aes128ecb = RESOLVE_CIPHER(EVP_aes_128_ecb());
73 aes192ecb = RESOLVE_CIPHER(EVP_aes_192_ecb());
74 aes256ecb = RESOLVE_CIPHER(EVP_aes_256_ecb());
75}
76#define INIT_CIPHERS() STMT_BEGIN { \
77 if (PREDICT_UNLIKELY(NULL == aes128ctr)) { \
78 init_ciphers(); \
79 } \
80 } STMT_END
81
82/* We have 2 strategies for getting the AES block cipher: Via OpenSSL's
83 * AES_encrypt function, or via OpenSSL's EVP_EncryptUpdate function.
84 *
85 * If there's any hardware acceleration in play, we want to be using EVP_* so
86 * we can get it. Otherwise, we'll want AES_*, which seems to be about 5%
87 * faster than indirecting through the EVP layer.
88 */
89
90/* We have 2 strategies for getting a plug-in counter mode: use our own, or
91 * use OpenSSL's.
92 *
93 * Here we have a counter mode that's faster than the one shipping with
94 * OpenSSL pre-1.0 (by about 10%!). But OpenSSL 1.0.0 added a counter mode
95 * implementation faster than the one here (by about 7%). So we pick which
96 * one to used based on the Openssl version above. (OpenSSL 1.0.0a fixed a
97 * critical bug in that counter mode implementation, so we need to test to
98 * make sure that we have a fixed version.)
99 */
100
101/* We don't actually define the struct here. */
102
104aes_new_cipher(const uint8_t *key, const uint8_t *iv, int key_bits)
105{
106 INIT_CIPHERS();
107 EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new();
108 const EVP_CIPHER *c = NULL;
109 switch (key_bits) {
110 case 128: c = aes128ctr; break;
111 case 192: c = aes192ctr; break;
112 case 256: c = aes256ctr; break;
113 default: tor_assert_unreached(); // LCOV_EXCL_LINE
114 }
115 EVP_EncryptInit(cipher, c, key, iv);
116 return (aes_cnt_cipher_t *) cipher;
117}
118void
119aes_cipher_free_(aes_cnt_cipher_t *cipher_)
120{
121 if (!cipher_)
122 return;
123 EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
124 EVP_CIPHER_CTX_reset(cipher);
125 EVP_CIPHER_CTX_free(cipher);
126}
127
128/** Changes the key of the cipher;
129 * sets the IV to 0.
130 */
131void
132aes_cipher_set_key(aes_cnt_cipher_t *cipher_, const uint8_t *key, int key_bits)
133{
134 EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
135 uint8_t iv[16] = {0};
136 const EVP_CIPHER *c = NULL;
137 switch (key_bits) {
138 case 128: c = aes128ctr; break;
139 case 192: c = aes192ctr; break;
140 case 256: c = aes256ctr; break;
141 default: tor_assert_unreached(); // LCOV_EXCL_LINE
142 }
143
144 // No need to call EVP_CIPHER_CTX_Reset here; EncryptInit already
145 // does it for us.
146 EVP_EncryptInit(cipher, c, key, iv);
147}
148/** Change the IV of this stream cipher without changing the key.
149 *
150 * Requires that the cipher stream position is at an even multiple of 16 bytes.
151 */
152void
153aes_cipher_set_iv_aligned(aes_cnt_cipher_t *cipher_, const uint8_t *iv)
154{
155 EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
156#ifdef LIBRESSL_VERSION_NUMBER
157 EVP_CIPHER_CTX_set_iv(cipher, iv, 16);
158#else
159 // We would have to do this if the cipher's position were not aligned:
160 // EVP_CIPHER_CTX_set_num(cipher, 0);
161
162 memcpy(EVP_CIPHER_CTX_iv_noconst(cipher), iv, 16);
163#endif
164}
165void
166aes_crypt_inplace(aes_cnt_cipher_t *cipher_, char *data, size_t len)
167{
168 int outl;
169 EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_;
170
171 tor_assert(len < INT_MAX);
172
173 EVP_EncryptUpdate(cipher, (unsigned char*)data,
174 &outl, (unsigned char*)data, (int)len);
175}
176
177/* ========
178 * Functions for "raw" (ECB) AES.
179 *
180 * I'm choosing the name "raw" here because ECB is not a mode;
181 * it's a disaster. The only way to use this safely is
182 * within a real construction.
183 */
184
185/**
186 * Create a new instance of AES using a key of length 'key_bits'
187 * for raw block encryption.
188 *
189 * This is even more low-level than counter-mode, and you should
190 * only use it with extreme caution.
191 */
192aes_raw_t *
193aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
194{
195 INIT_CIPHERS();
196 EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new();
197 tor_assert(cipher);
198 const EVP_CIPHER *c = NULL;
199 switch (key_bits) {
200 case 128: c = aes128ecb; break;
201 case 192: c = aes192ecb; break;
202 case 256: c = aes256ecb; break;
203 default: tor_assert_unreached();
204 }
205
206 // No need to call EVP_CIPHER_CTX_Reset here; EncryptInit already
207 // does it for us.
208 int r = EVP_CipherInit(cipher, c, key, NULL, encrypt);
209 tor_assert(r == 1);
210 EVP_CIPHER_CTX_set_padding(cipher, 0);
211 return (aes_raw_t *)cipher;
212}
213/**
214 * Replace the key on an existing aes_raw_t.
215 *
216 * This may be faster than freeing and reallocating.
217 */
218void
219aes_raw_set_key(aes_raw_t **cipher_, const uint8_t *key,
220 int key_bits, bool encrypt)
221{
222 const EVP_CIPHER *c = *(EVP_CIPHER**) cipher_;
223 switch (key_bits) {
224 case 128: c = aes128ecb; break;
225 case 192: c = aes192ecb; break;
226 case 256: c = aes256ecb; break;
227 default: tor_assert_unreached();
228 }
229 aes_raw_t *cipherp = *cipher_;
230 EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *)cipherp;
231 int r = EVP_CipherInit(cipher, c, key, NULL, encrypt);
232 tor_assert(r == 1);
233 EVP_CIPHER_CTX_set_padding(cipher, 0);
234}
235
236/**
237 * Release storage held by 'cipher'.
238 */
239void
240aes_raw_free_(aes_raw_t *cipher_)
241{
242 if (!cipher_)
243 return;
244 EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *)cipher_;
245#ifdef OPENSSL_1_1_API
246 EVP_CIPHER_CTX_reset(cipher);
247#else
248 EVP_CIPHER_CTX_cleanup(cipher);
249#endif
250 EVP_CIPHER_CTX_free(cipher);
251}
252#define aes_raw_free(cipher) \
253 FREE_AND_NULL(aes_raw_t, aes_raw_free_, (cipher))
254/**
255 * Encrypt a single 16-byte block with 'cipher',
256 * which must have been initialized for encryption.
257 */
258void
259aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block)
260{
261 int outl = 16;
262 int r = EVP_EncryptUpdate((EVP_CIPHER_CTX *)cipher, block, &outl, block, 16);
263 tor_assert(r == 1);
264 tor_assert(outl == 16);
265}
266/**
267 * Decrypt a single 16-byte block with 'cipher',
268 * which must have been initialized for decryption.
269 */
270void
271aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block)
272{
273 int outl = 16;
274 int r = EVP_DecryptUpdate((EVP_CIPHER_CTX *)cipher, block, &outl, block, 16);
275 tor_assert(r == 1);
276 tor_assert(outl == 16);
277}
Headers for aes.c.
void aes_cipher_set_key(aes_cnt_cipher_t *cipher_, const uint8_t *key, int key_bits)
void aes_cipher_set_iv_aligned(aes_cnt_cipher_t *cipher_, const uint8_t *iv)
void aes_raw_set_key(aes_raw_t **cipher_, const uint8_t *key, int key_bits, bool encrypt)
void aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block)
void aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block)
static void init_ciphers(void)
Definition aes_openssl.c:67
void aes_raw_free_(aes_raw_t *cipher_)
aes_raw_t * aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
Inline functions for reading and writing multibyte values from the middle of strings,...
Headers for crypto_openssl_mgt.c.
Common functions for cryptographic routines.
Headers for di_ops.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition util_bug.h:103