/src/FreeRDP/winpr/libwinpr/crypto/cipher.c
Line | Count | Source |
1 | | /** |
2 | | * WinPR: Windows Portable Runtime |
3 | | * |
4 | | * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com> |
5 | | * |
6 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
7 | | * you may not use this file except in compliance with the License. |
8 | | * You may obtain a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, software |
13 | | * distributed under the License is distributed on an "AS IS" BASIS, |
14 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | * See the License for the specific language governing permissions and |
16 | | * limitations under the License. |
17 | | */ |
18 | | |
19 | | #include <winpr/config.h> |
20 | | |
21 | | #include <winpr/crt.h> |
22 | | #include <winpr/assert.h> |
23 | | #include <winpr/crypto.h> |
24 | | |
25 | | #include "../log.h" |
26 | | #define TAG WINPR_TAG("crypto.cipher") |
27 | | |
28 | | #if defined(WITH_INTERNAL_RC4) |
29 | | #include "rc4.h" |
30 | | #endif |
31 | | |
32 | | #ifdef WITH_OPENSSL |
33 | | #include <openssl/aes.h> |
34 | | #include <openssl/rc4.h> |
35 | | #include <openssl/des.h> |
36 | | #include <openssl/evp.h> |
37 | | #endif |
38 | | |
39 | | #ifdef WITH_MBEDTLS |
40 | | #include <mbedtls/md.h> |
41 | | #include <mbedtls/aes.h> |
42 | | #include <mbedtls/des.h> |
43 | | #include <mbedtls/cipher.h> |
44 | | #if MBEDTLS_VERSION_MAJOR < 3 |
45 | | #define mbedtls_cipher_info_get_iv_size(_info) (_info->iv_size) |
46 | | #define mbedtls_cipher_info_get_key_bitlen(_info) (_info->key_bitlen) |
47 | | #endif |
48 | | #endif |
49 | | |
50 | | struct winpr_cipher_ctx_private_st |
51 | | { |
52 | | WINPR_CIPHER_TYPE cipher; |
53 | | WINPR_CRYPTO_OPERATION op; |
54 | | |
55 | | #ifdef WITH_OPENSSL |
56 | | EVP_CIPHER_CTX* ectx; |
57 | | #endif |
58 | | #ifdef WITH_MBEDTLS |
59 | | mbedtls_cipher_context_t* mctx; |
60 | | #endif |
61 | | }; |
62 | | |
63 | | /** |
64 | | * RC4 |
65 | | */ |
66 | | |
67 | | struct winpr_rc4_ctx_private_st |
68 | | { |
69 | | #if defined(WITH_INTERNAL_RC4) |
70 | | winpr_int_RC4_CTX* ictx; |
71 | | #else |
72 | | #if defined(WITH_OPENSSL) |
73 | | EVP_CIPHER_CTX* ctx; |
74 | | #endif |
75 | | #endif |
76 | | }; |
77 | | |
78 | | static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips) |
79 | 237 | { |
80 | 237 | if (!key || (keylen == 0)) |
81 | 0 | return nullptr; |
82 | | |
83 | 237 | WINPR_RC4_CTX* ctx = (WINPR_RC4_CTX*)calloc(1, sizeof(WINPR_RC4_CTX)); |
84 | 237 | if (!ctx) |
85 | 0 | return nullptr; |
86 | | |
87 | | #if defined(WITH_INTERNAL_RC4) |
88 | | WINPR_UNUSED(override_fips); |
89 | | ctx->ictx = winpr_int_rc4_new(key, keylen); |
90 | | if (!ctx->ictx) |
91 | | goto fail; |
92 | | #elif defined(WITH_OPENSSL) |
93 | | |
94 | 237 | if (keylen > INT_MAX) |
95 | 0 | goto fail; |
96 | | |
97 | 237 | ctx->ctx = EVP_CIPHER_CTX_new(); |
98 | 237 | if (!ctx->ctx) |
99 | 0 | goto fail; |
100 | | |
101 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
102 | | EVP_CIPHER* evp = EVP_CIPHER_fetch(NULL, "RC4", override_fips ? "fips=no" : NULL); |
103 | | #else |
104 | 237 | const EVP_CIPHER* evp = EVP_rc4(); |
105 | 237 | #endif |
106 | | |
107 | 237 | if (!evp) |
108 | 0 | goto fail; |
109 | | |
110 | 237 | EVP_CIPHER_CTX_reset(ctx->ctx); |
111 | 237 | if (EVP_EncryptInit_ex(ctx->ctx, evp, nullptr, nullptr, nullptr) != 1) |
112 | 0 | goto fail; |
113 | | |
114 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
115 | | EVP_CIPHER_free(evp); |
116 | | |
117 | | /* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */ |
118 | | #if !(OPENSSL_VERSION_NUMBER < 0x10001000L) |
119 | | |
120 | | if (override_fips == TRUE) |
121 | | EVP_CIPHER_CTX_set_flags(ctx->ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW); |
122 | | |
123 | | #endif |
124 | | #endif |
125 | 237 | EVP_CIPHER_CTX_set_key_length(ctx->ctx, (int)keylen); |
126 | 237 | if (EVP_EncryptInit_ex(ctx->ctx, nullptr, nullptr, key, nullptr) != 1) |
127 | 0 | goto fail; |
128 | 237 | #endif |
129 | 237 | return ctx; |
130 | | |
131 | 0 | fail: |
132 | 0 | WINPR_PRAGMA_DIAG_PUSH |
133 | 0 | WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC |
134 | |
|
135 | 0 | winpr_RC4_Free(ctx); |
136 | 0 | WINPR_PRAGMA_DIAG_POP |
137 | 0 | return nullptr; |
138 | 237 | } |
139 | | |
140 | | WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const void* key, size_t keylen) |
141 | 0 | { |
142 | 0 | return winpr_RC4_New_Internal(key, keylen, TRUE); |
143 | 0 | } |
144 | | |
145 | | WINPR_RC4_CTX* winpr_RC4_New(const void* key, size_t keylen) |
146 | 237 | { |
147 | 237 | return winpr_RC4_New_Internal(key, keylen, FALSE); |
148 | 237 | } |
149 | | |
150 | | BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const void* input, void* output) |
151 | 237 | { |
152 | 237 | WINPR_ASSERT(ctx); |
153 | | |
154 | | #if defined(WITH_INTERNAL_RC4) |
155 | | return winpr_int_rc4_update(ctx->ictx, length, input, output); |
156 | | #elif defined(WITH_OPENSSL) |
157 | 237 | WINPR_ASSERT(ctx->ctx); |
158 | 237 | int outputLength = 0; |
159 | 237 | if (length > INT_MAX) |
160 | 0 | return FALSE; |
161 | | |
162 | 237 | WINPR_ASSERT(ctx); |
163 | 237 | return EVP_CipherUpdate(ctx->ctx, output, &outputLength, input, (int)length) == 1; |
164 | 0 | #endif |
165 | 0 | return FALSE; |
166 | 237 | } |
167 | | |
168 | | void winpr_RC4_Free(WINPR_RC4_CTX* ctx) |
169 | 317 | { |
170 | 317 | if (!ctx) |
171 | 80 | return; |
172 | | |
173 | | #if defined(WITH_INTERNAL_RC4) |
174 | | winpr_int_rc4_free(ctx->ictx); |
175 | | #elif defined(WITH_OPENSSL) |
176 | 237 | EVP_CIPHER_CTX_free(ctx->ctx); |
177 | 237 | #endif |
178 | 237 | free(ctx); |
179 | 237 | } |
180 | | |
181 | | /** |
182 | | * Generic Cipher API |
183 | | */ |
184 | | |
185 | | #ifdef WITH_OPENSSL |
186 | | extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md); |
187 | | #endif |
188 | | |
189 | | #ifdef WITH_MBEDTLS |
190 | | extern mbedtls_md_type_t winpr_mbedtls_get_md_type(int md); |
191 | | #endif |
192 | | |
193 | | struct cipher_map |
194 | | { |
195 | | WINPR_CIPHER_TYPE md; |
196 | | const char* name; |
197 | | }; |
198 | | static const struct cipher_map s_cipher_map[] = { |
199 | | { WINPR_CIPHER_NONE, "none" }, |
200 | | { WINPR_CIPHER_NULL, "null" }, |
201 | | { WINPR_CIPHER_AES_128_ECB, "aes-128-ecb" }, |
202 | | { WINPR_CIPHER_AES_192_ECB, "aes-192-ecb" }, |
203 | | { WINPR_CIPHER_AES_256_ECB, "aes-256-ecb" }, |
204 | | { WINPR_CIPHER_AES_128_CBC, "aes-128-cbc" }, |
205 | | { WINPR_CIPHER_AES_192_CBC, "aes-192-cbc" }, |
206 | | { WINPR_CIPHER_AES_256_CBC, "aes-256-cbc" }, |
207 | | { WINPR_CIPHER_AES_128_CFB128, "aes-128-cfb128" }, |
208 | | { WINPR_CIPHER_AES_192_CFB128, "aes-192-cfb128" }, |
209 | | { WINPR_CIPHER_AES_256_CFB128, "aes-256-cfb128" }, |
210 | | { WINPR_CIPHER_AES_128_CTR, "aes-128-ctr" }, |
211 | | { WINPR_CIPHER_AES_192_CTR, "aes-192-ctr" }, |
212 | | { WINPR_CIPHER_AES_256_CTR, "aes-256-ctr" }, |
213 | | { WINPR_CIPHER_AES_128_GCM, "aes-128-gcm" }, |
214 | | { WINPR_CIPHER_AES_192_GCM, "aes-192-gcm" }, |
215 | | { WINPR_CIPHER_AES_256_GCM, "aes-256-gcm" }, |
216 | | { WINPR_CIPHER_CAMELLIA_128_ECB, "camellia-128-ecb" }, |
217 | | { WINPR_CIPHER_CAMELLIA_192_ECB, "camellia-192-ecb" }, |
218 | | { WINPR_CIPHER_CAMELLIA_256_ECB, "camellia-256-ecb" }, |
219 | | { WINPR_CIPHER_CAMELLIA_128_CBC, "camellia-128-cbc" }, |
220 | | { WINPR_CIPHER_CAMELLIA_192_CBC, "camellia-192-cbc" }, |
221 | | { WINPR_CIPHER_CAMELLIA_256_CBC, "camellia-256-cbc" }, |
222 | | { WINPR_CIPHER_CAMELLIA_128_CFB128, "camellia-128-cfb128" }, |
223 | | { WINPR_CIPHER_CAMELLIA_192_CFB128, "camellia-192-cfb128" }, |
224 | | { WINPR_CIPHER_CAMELLIA_256_CFB128, "camellia-256-cfb128" }, |
225 | | { WINPR_CIPHER_CAMELLIA_128_CTR, "camellia-128-ctr" }, |
226 | | { WINPR_CIPHER_CAMELLIA_192_CTR, "camellia-192-ctr" }, |
227 | | { WINPR_CIPHER_CAMELLIA_256_CTR, "camellia-256-ctr" }, |
228 | | { WINPR_CIPHER_CAMELLIA_128_GCM, "camellia-128-gcm" }, |
229 | | { WINPR_CIPHER_CAMELLIA_192_GCM, "camellia-192-gcm" }, |
230 | | { WINPR_CIPHER_CAMELLIA_256_GCM, "camellia-256-gcm" }, |
231 | | { WINPR_CIPHER_DES_ECB, "des-ecb" }, |
232 | | { WINPR_CIPHER_DES_CBC, "des-cbc" }, |
233 | | { WINPR_CIPHER_DES_EDE_ECB, "des-ede-ecb" }, |
234 | | { WINPR_CIPHER_DES_EDE_CBC, "des-ede-cbc" }, |
235 | | { WINPR_CIPHER_DES_EDE3_ECB, "des-ede3-ecb" }, |
236 | | { WINPR_CIPHER_DES_EDE3_CBC, "des-ede3-cbc" }, |
237 | | { WINPR_CIPHER_BLOWFISH_ECB, "blowfish-ecb" }, |
238 | | { WINPR_CIPHER_BLOWFISH_CBC, "blowfish-cbc" }, |
239 | | { WINPR_CIPHER_BLOWFISH_CFB64, "blowfish-cfb64" }, |
240 | | { WINPR_CIPHER_BLOWFISH_CTR, "blowfish-ctr" }, |
241 | | { WINPR_CIPHER_ARC4_128, "rc4" }, |
242 | | { WINPR_CIPHER_AES_128_CCM, "aes-128-ccm" }, |
243 | | { WINPR_CIPHER_AES_192_CCM, "aes-192-ccm" }, |
244 | | { WINPR_CIPHER_AES_256_CCM, "aes-256-ccm" }, |
245 | | { WINPR_CIPHER_CAMELLIA_128_CCM, "camellia-128-ccm" }, |
246 | | { WINPR_CIPHER_CAMELLIA_192_CCM, "camellia-192-ccm" }, |
247 | | { WINPR_CIPHER_CAMELLIA_256_CCM, "camellia-256-ccm" }, |
248 | | }; |
249 | | |
250 | | static int cipher_compare(const void* a, const void* b) |
251 | 0 | { |
252 | 0 | const WINPR_CIPHER_TYPE* cipher = a; |
253 | 0 | const struct cipher_map* map = b; |
254 | 0 | if (*cipher == map->md) |
255 | 0 | return 0; |
256 | 0 | return *cipher > map->md ? 1 : -1; |
257 | 0 | } |
258 | | |
259 | | const char* winpr_cipher_type_to_string(WINPR_CIPHER_TYPE md) |
260 | 0 | { |
261 | 0 | WINPR_CIPHER_TYPE lc = md; |
262 | 0 | const struct cipher_map* ret = bsearch(&lc, s_cipher_map, ARRAYSIZE(s_cipher_map), |
263 | 0 | sizeof(struct cipher_map), cipher_compare); |
264 | 0 | if (!ret) |
265 | 0 | return "unknown"; |
266 | 0 | return ret->name; |
267 | 0 | } |
268 | | |
269 | | static int cipher_string_compare(const void* a, const void* b) |
270 | 0 | { |
271 | 0 | const char* cipher = a; |
272 | 0 | const struct cipher_map* map = b; |
273 | 0 | return strcmp(cipher, map->name); |
274 | 0 | } |
275 | | |
276 | | WINPR_CIPHER_TYPE winpr_cipher_type_from_string(const char* name) |
277 | 0 | { |
278 | 0 | const struct cipher_map* ret = bsearch(name, s_cipher_map, ARRAYSIZE(s_cipher_map), |
279 | 0 | sizeof(struct cipher_map), cipher_string_compare); |
280 | 0 | if (!ret) |
281 | 0 | return WINPR_CIPHER_NONE; |
282 | 0 | return ret->md; |
283 | 0 | } |
284 | | |
285 | | #if defined(WITH_OPENSSL) |
286 | | static const EVP_CIPHER* winpr_openssl_get_evp_cipher(WINPR_CIPHER_TYPE cipher) |
287 | 480 | { |
288 | 480 | const EVP_CIPHER* evp = nullptr; |
289 | | |
290 | 480 | switch (cipher) |
291 | 480 | { |
292 | 0 | case WINPR_CIPHER_NULL: |
293 | 0 | evp = EVP_enc_null(); |
294 | 0 | break; |
295 | | |
296 | 0 | case WINPR_CIPHER_AES_128_ECB: |
297 | 0 | evp = EVP_get_cipherbyname("aes-128-ecb"); |
298 | 0 | break; |
299 | | |
300 | 0 | case WINPR_CIPHER_AES_192_ECB: |
301 | 0 | evp = EVP_get_cipherbyname("aes-192-ecb"); |
302 | 0 | break; |
303 | | |
304 | 0 | case WINPR_CIPHER_AES_256_ECB: |
305 | 0 | evp = EVP_get_cipherbyname("aes-256-ecb"); |
306 | 0 | break; |
307 | | |
308 | 480 | case WINPR_CIPHER_AES_128_CBC: |
309 | 480 | evp = EVP_get_cipherbyname("aes-128-cbc"); |
310 | 480 | break; |
311 | | |
312 | 0 | case WINPR_CIPHER_AES_192_CBC: |
313 | 0 | evp = EVP_get_cipherbyname("aes-192-cbc"); |
314 | 0 | break; |
315 | | |
316 | 0 | case WINPR_CIPHER_AES_256_CBC: |
317 | 0 | evp = EVP_get_cipherbyname("aes-256-cbc"); |
318 | 0 | break; |
319 | | |
320 | 0 | case WINPR_CIPHER_AES_128_CFB128: |
321 | 0 | evp = EVP_get_cipherbyname("aes-128-cfb128"); |
322 | 0 | break; |
323 | | |
324 | 0 | case WINPR_CIPHER_AES_192_CFB128: |
325 | 0 | evp = EVP_get_cipherbyname("aes-192-cfb128"); |
326 | 0 | break; |
327 | | |
328 | 0 | case WINPR_CIPHER_AES_256_CFB128: |
329 | 0 | evp = EVP_get_cipherbyname("aes-256-cfb128"); |
330 | 0 | break; |
331 | | |
332 | 0 | case WINPR_CIPHER_AES_128_CTR: |
333 | 0 | evp = EVP_get_cipherbyname("aes-128-ctr"); |
334 | 0 | break; |
335 | | |
336 | 0 | case WINPR_CIPHER_AES_192_CTR: |
337 | 0 | evp = EVP_get_cipherbyname("aes-192-ctr"); |
338 | 0 | break; |
339 | | |
340 | 0 | case WINPR_CIPHER_AES_256_CTR: |
341 | 0 | evp = EVP_get_cipherbyname("aes-256-ctr"); |
342 | 0 | break; |
343 | | |
344 | 0 | case WINPR_CIPHER_AES_128_GCM: |
345 | 0 | evp = EVP_get_cipherbyname("aes-128-gcm"); |
346 | 0 | break; |
347 | | |
348 | 0 | case WINPR_CIPHER_AES_192_GCM: |
349 | 0 | evp = EVP_get_cipherbyname("aes-192-gcm"); |
350 | 0 | break; |
351 | | |
352 | 0 | case WINPR_CIPHER_AES_256_GCM: |
353 | 0 | evp = EVP_get_cipherbyname("aes-256-gcm"); |
354 | 0 | break; |
355 | | |
356 | 0 | case WINPR_CIPHER_AES_128_CCM: |
357 | 0 | evp = EVP_get_cipherbyname("aes-128-ccm"); |
358 | 0 | break; |
359 | | |
360 | 0 | case WINPR_CIPHER_AES_192_CCM: |
361 | 0 | evp = EVP_get_cipherbyname("aes-192-ccm"); |
362 | 0 | break; |
363 | | |
364 | 0 | case WINPR_CIPHER_AES_256_CCM: |
365 | 0 | evp = EVP_get_cipherbyname("aes-256-ccm"); |
366 | 0 | break; |
367 | | |
368 | 0 | case WINPR_CIPHER_CAMELLIA_128_ECB: |
369 | 0 | evp = EVP_get_cipherbyname("camellia-128-ecb"); |
370 | 0 | break; |
371 | | |
372 | 0 | case WINPR_CIPHER_CAMELLIA_192_ECB: |
373 | 0 | evp = EVP_get_cipherbyname("camellia-192-ecb"); |
374 | 0 | break; |
375 | | |
376 | 0 | case WINPR_CIPHER_CAMELLIA_256_ECB: |
377 | 0 | evp = EVP_get_cipherbyname("camellia-256-ecb"); |
378 | 0 | break; |
379 | | |
380 | 0 | case WINPR_CIPHER_CAMELLIA_128_CBC: |
381 | 0 | evp = EVP_get_cipherbyname("camellia-128-cbc"); |
382 | 0 | break; |
383 | | |
384 | 0 | case WINPR_CIPHER_CAMELLIA_192_CBC: |
385 | 0 | evp = EVP_get_cipherbyname("camellia-192-cbc"); |
386 | 0 | break; |
387 | | |
388 | 0 | case WINPR_CIPHER_CAMELLIA_256_CBC: |
389 | 0 | evp = EVP_get_cipherbyname("camellia-256-cbc"); |
390 | 0 | break; |
391 | | |
392 | 0 | case WINPR_CIPHER_CAMELLIA_128_CFB128: |
393 | 0 | evp = EVP_get_cipherbyname("camellia-128-cfb128"); |
394 | 0 | break; |
395 | | |
396 | 0 | case WINPR_CIPHER_CAMELLIA_192_CFB128: |
397 | 0 | evp = EVP_get_cipherbyname("camellia-192-cfb128"); |
398 | 0 | break; |
399 | | |
400 | 0 | case WINPR_CIPHER_CAMELLIA_256_CFB128: |
401 | 0 | evp = EVP_get_cipherbyname("camellia-256-cfb128"); |
402 | 0 | break; |
403 | | |
404 | 0 | case WINPR_CIPHER_CAMELLIA_128_CTR: |
405 | 0 | evp = EVP_get_cipherbyname("camellia-128-ctr"); |
406 | 0 | break; |
407 | | |
408 | 0 | case WINPR_CIPHER_CAMELLIA_192_CTR: |
409 | 0 | evp = EVP_get_cipherbyname("camellia-192-ctr"); |
410 | 0 | break; |
411 | | |
412 | 0 | case WINPR_CIPHER_CAMELLIA_256_CTR: |
413 | 0 | evp = EVP_get_cipherbyname("camellia-256-ctr"); |
414 | 0 | break; |
415 | | |
416 | 0 | case WINPR_CIPHER_CAMELLIA_128_GCM: |
417 | 0 | evp = EVP_get_cipherbyname("camellia-128-gcm"); |
418 | 0 | break; |
419 | | |
420 | 0 | case WINPR_CIPHER_CAMELLIA_192_GCM: |
421 | 0 | evp = EVP_get_cipherbyname("camellia-192-gcm"); |
422 | 0 | break; |
423 | | |
424 | 0 | case WINPR_CIPHER_CAMELLIA_256_GCM: |
425 | 0 | evp = EVP_get_cipherbyname("camellia-256-gcm"); |
426 | 0 | break; |
427 | | |
428 | 0 | case WINPR_CIPHER_CAMELLIA_128_CCM: |
429 | 0 | evp = EVP_get_cipherbyname("camellia-128-ccm"); |
430 | 0 | break; |
431 | | |
432 | 0 | case WINPR_CIPHER_CAMELLIA_192_CCM: |
433 | 0 | evp = EVP_get_cipherbyname("camellia-192-ccm"); |
434 | 0 | break; |
435 | | |
436 | 0 | case WINPR_CIPHER_CAMELLIA_256_CCM: |
437 | 0 | evp = EVP_get_cipherbyname("camellia-256-ccm"); |
438 | 0 | break; |
439 | | |
440 | 0 | case WINPR_CIPHER_DES_ECB: |
441 | 0 | evp = EVP_get_cipherbyname("des-ecb"); |
442 | 0 | break; |
443 | | |
444 | 0 | case WINPR_CIPHER_DES_CBC: |
445 | 0 | evp = EVP_get_cipherbyname("des-cbc"); |
446 | 0 | break; |
447 | | |
448 | 0 | case WINPR_CIPHER_DES_EDE_ECB: |
449 | 0 | evp = EVP_get_cipherbyname("des-ede-ecb"); |
450 | 0 | break; |
451 | | |
452 | 0 | case WINPR_CIPHER_DES_EDE_CBC: |
453 | 0 | evp = EVP_get_cipherbyname("des-ede-cbc"); |
454 | 0 | break; |
455 | | |
456 | 0 | case WINPR_CIPHER_DES_EDE3_ECB: |
457 | 0 | evp = EVP_get_cipherbyname("des-ede3-ecb"); |
458 | 0 | break; |
459 | | |
460 | 0 | case WINPR_CIPHER_DES_EDE3_CBC: |
461 | 0 | evp = EVP_get_cipherbyname("des-ede3-cbc"); |
462 | 0 | break; |
463 | | |
464 | 0 | case WINPR_CIPHER_ARC4_128: |
465 | 0 | evp = EVP_get_cipherbyname("rc4"); |
466 | 0 | break; |
467 | | |
468 | 0 | case WINPR_CIPHER_BLOWFISH_ECB: |
469 | 0 | evp = EVP_get_cipherbyname("blowfish-ecb"); |
470 | 0 | break; |
471 | | |
472 | 0 | case WINPR_CIPHER_BLOWFISH_CBC: |
473 | 0 | evp = EVP_get_cipherbyname("blowfish-cbc"); |
474 | 0 | break; |
475 | | |
476 | 0 | case WINPR_CIPHER_BLOWFISH_CFB64: |
477 | 0 | evp = EVP_get_cipherbyname("blowfish-cfb64"); |
478 | 0 | break; |
479 | | |
480 | 0 | case WINPR_CIPHER_BLOWFISH_CTR: |
481 | 0 | evp = EVP_get_cipherbyname("blowfish-ctr"); |
482 | 0 | break; |
483 | 0 | default: |
484 | 0 | break; |
485 | 480 | } |
486 | | |
487 | 480 | return evp; |
488 | 480 | } |
489 | | |
490 | | #elif defined(WITH_MBEDTLS) |
491 | | mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) |
492 | | { |
493 | | mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE; |
494 | | |
495 | | switch (cipher) |
496 | | { |
497 | | case WINPR_CIPHER_NONE: |
498 | | type = MBEDTLS_CIPHER_NONE; |
499 | | break; |
500 | | |
501 | | case WINPR_CIPHER_NULL: |
502 | | type = MBEDTLS_CIPHER_NULL; |
503 | | break; |
504 | | |
505 | | case WINPR_CIPHER_AES_128_ECB: |
506 | | type = MBEDTLS_CIPHER_AES_128_ECB; |
507 | | break; |
508 | | |
509 | | case WINPR_CIPHER_AES_192_ECB: |
510 | | type = MBEDTLS_CIPHER_AES_192_ECB; |
511 | | break; |
512 | | |
513 | | case WINPR_CIPHER_AES_256_ECB: |
514 | | type = MBEDTLS_CIPHER_AES_256_ECB; |
515 | | break; |
516 | | |
517 | | case WINPR_CIPHER_AES_128_CBC: |
518 | | type = MBEDTLS_CIPHER_AES_128_CBC; |
519 | | break; |
520 | | |
521 | | case WINPR_CIPHER_AES_192_CBC: |
522 | | type = MBEDTLS_CIPHER_AES_192_CBC; |
523 | | break; |
524 | | |
525 | | case WINPR_CIPHER_AES_256_CBC: |
526 | | type = MBEDTLS_CIPHER_AES_256_CBC; |
527 | | break; |
528 | | |
529 | | case WINPR_CIPHER_AES_128_CFB128: |
530 | | type = MBEDTLS_CIPHER_AES_128_CFB128; |
531 | | break; |
532 | | |
533 | | case WINPR_CIPHER_AES_192_CFB128: |
534 | | type = MBEDTLS_CIPHER_AES_192_CFB128; |
535 | | break; |
536 | | |
537 | | case WINPR_CIPHER_AES_256_CFB128: |
538 | | type = MBEDTLS_CIPHER_AES_256_CFB128; |
539 | | break; |
540 | | |
541 | | case WINPR_CIPHER_AES_128_CTR: |
542 | | type = MBEDTLS_CIPHER_AES_128_CTR; |
543 | | break; |
544 | | |
545 | | case WINPR_CIPHER_AES_192_CTR: |
546 | | type = MBEDTLS_CIPHER_AES_192_CTR; |
547 | | break; |
548 | | |
549 | | case WINPR_CIPHER_AES_256_CTR: |
550 | | type = MBEDTLS_CIPHER_AES_256_CTR; |
551 | | break; |
552 | | |
553 | | case WINPR_CIPHER_AES_128_GCM: |
554 | | type = MBEDTLS_CIPHER_AES_128_GCM; |
555 | | break; |
556 | | |
557 | | case WINPR_CIPHER_AES_192_GCM: |
558 | | type = MBEDTLS_CIPHER_AES_192_GCM; |
559 | | break; |
560 | | |
561 | | case WINPR_CIPHER_AES_256_GCM: |
562 | | type = MBEDTLS_CIPHER_AES_256_GCM; |
563 | | break; |
564 | | |
565 | | case WINPR_CIPHER_AES_128_CCM: |
566 | | type = MBEDTLS_CIPHER_AES_128_CCM; |
567 | | break; |
568 | | |
569 | | case WINPR_CIPHER_AES_192_CCM: |
570 | | type = MBEDTLS_CIPHER_AES_192_CCM; |
571 | | break; |
572 | | |
573 | | case WINPR_CIPHER_AES_256_CCM: |
574 | | type = MBEDTLS_CIPHER_AES_256_CCM; |
575 | | break; |
576 | | } |
577 | | |
578 | | return type; |
579 | | } |
580 | | #endif |
581 | | |
582 | | #if !defined(WITHOUT_WINPR_3x_DEPRECATED) |
583 | | WINPR_CIPHER_CTX* winpr_Cipher_New(WINPR_CIPHER_TYPE cipher, WINPR_CRYPTO_OPERATION op, |
584 | | const void* key, const void* iv) |
585 | 0 | { |
586 | 0 | return winpr_Cipher_NewEx(cipher, op, key, 0, iv, 0); |
587 | 0 | } |
588 | | #endif |
589 | | |
590 | | WINPR_API WINPR_ATTR_NODISCARD WINPR_CIPHER_CTX* |
591 | | winpr_Cipher_NewEx(WINPR_CIPHER_TYPE cipher, WINPR_CRYPTO_OPERATION op, const void* key, |
592 | | WINPR_ATTR_UNUSED size_t keylen, const void* iv, WINPR_ATTR_UNUSED size_t ivlen) |
593 | 480 | { |
594 | 480 | if (cipher == WINPR_CIPHER_ARC4_128) |
595 | 0 | { |
596 | 0 | WLog_ERR(TAG, |
597 | 0 | "WINPR_CIPHER_ARC4_128 (RC4) cipher not supported, use winpr_RC4_new instead"); |
598 | 0 | return nullptr; |
599 | 0 | } |
600 | | |
601 | 480 | WINPR_CIPHER_CTX* ctx = calloc(1, sizeof(WINPR_CIPHER_CTX)); |
602 | 480 | if (!ctx) |
603 | 0 | return nullptr; |
604 | | |
605 | 480 | ctx->cipher = cipher; |
606 | 480 | ctx->op = op; |
607 | | |
608 | 480 | #if defined(WITH_OPENSSL) |
609 | 480 | const EVP_CIPHER* evp = winpr_openssl_get_evp_cipher(cipher); |
610 | 480 | if (!evp) |
611 | 0 | goto fail; |
612 | | |
613 | 480 | ctx->ectx = EVP_CIPHER_CTX_new(); |
614 | 480 | if (!ctx->ectx) |
615 | 0 | goto fail; |
616 | | |
617 | 480 | { |
618 | 480 | const int operation = (op == WINPR_ENCRYPT) ? 1 : 0; |
619 | 480 | if (EVP_CipherInit_ex(ctx->ectx, evp, nullptr, key, iv, operation) != 1) |
620 | 0 | goto fail; |
621 | 480 | } |
622 | | |
623 | 480 | EVP_CIPHER_CTX_set_padding(ctx->ectx, 0); |
624 | | |
625 | | #elif defined(WITH_MBEDTLS) |
626 | | mbedtls_cipher_type_t cipher_type = winpr_mbedtls_get_cipher_type(cipher); |
627 | | const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(cipher_type); |
628 | | |
629 | | if (!cipher_info) |
630 | | goto fail; |
631 | | |
632 | | ctx->mctx = calloc(1, sizeof(mbedtls_cipher_context_t)); |
633 | | if (!ctx->mctx) |
634 | | goto fail; |
635 | | |
636 | | const mbedtls_operation_t operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; |
637 | | mbedtls_cipher_init(ctx->mctx); |
638 | | |
639 | | if (mbedtls_cipher_setup(ctx->mctx, cipher_info) != 0) |
640 | | goto fail; |
641 | | |
642 | | const int key_bitlen = mbedtls_cipher_get_key_bitlen(ctx->mctx); |
643 | | |
644 | | if (mbedtls_cipher_setkey(ctx->mctx, key, key_bitlen, operation) != 0) |
645 | | goto fail; |
646 | | |
647 | | if (mbedtls_cipher_set_padding_mode(ctx->mctx, MBEDTLS_PADDING_NONE) != 0) |
648 | | goto fail; |
649 | | |
650 | | #endif |
651 | 480 | return ctx; |
652 | | |
653 | 0 | fail: |
654 | 0 | winpr_Cipher_Free(ctx); |
655 | 0 | return nullptr; |
656 | 480 | } |
657 | | |
658 | | BOOL winpr_Cipher_SetPadding(WINPR_CIPHER_CTX* ctx, BOOL enabled) |
659 | 0 | { |
660 | 0 | WINPR_ASSERT(ctx); |
661 | |
|
662 | 0 | #if defined(WITH_OPENSSL) |
663 | 0 | if (!ctx->ectx) |
664 | 0 | return FALSE; |
665 | 0 | EVP_CIPHER_CTX_set_padding(ctx->ectx, enabled); |
666 | | #elif defined(WITH_MBEDTLS) |
667 | | mbedtls_cipher_padding_t option = enabled ? MBEDTLS_PADDING_PKCS7 : MBEDTLS_PADDING_NONE; |
668 | | if (mbedtls_cipher_set_padding_mode((mbedtls_cipher_context_t*)ctx, option) != 0) |
669 | | return FALSE; |
670 | | #else |
671 | | return FALSE; |
672 | | #endif |
673 | 0 | return TRUE; |
674 | 0 | } |
675 | | |
676 | | BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const void* input, size_t ilen, void* output, |
677 | | size_t* olen) |
678 | 480 | { |
679 | 480 | WINPR_ASSERT(ctx); |
680 | 480 | WINPR_ASSERT(olen); |
681 | | |
682 | 480 | #if defined(WITH_OPENSSL) |
683 | 480 | int outl = (int)*olen; |
684 | | |
685 | 480 | if (ilen > INT_MAX) |
686 | 0 | { |
687 | 0 | WLog_ERR(TAG, "input length %" PRIuz " > %d, abort", ilen, INT_MAX); |
688 | 0 | return FALSE; |
689 | 0 | } |
690 | | |
691 | 480 | WINPR_ASSERT(ctx->ectx); |
692 | 480 | if (EVP_CipherUpdate(ctx->ectx, output, &outl, input, (int)ilen) == 1) |
693 | 480 | { |
694 | 480 | *olen = (size_t)outl; |
695 | 480 | return TRUE; |
696 | 480 | } |
697 | | |
698 | | #elif defined(WITH_MBEDTLS) |
699 | | WINPR_ASSERT(ctx->mctx); |
700 | | if (mbedtls_cipher_update(ctx->mctx, input, ilen, output, olen) == 0) |
701 | | return TRUE; |
702 | | |
703 | | #endif |
704 | | |
705 | 0 | WLog_ERR(TAG, "Failed to update the data"); |
706 | 0 | return FALSE; |
707 | 480 | } |
708 | | |
709 | | BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, void* output, size_t* olen) |
710 | 480 | { |
711 | 480 | WINPR_ASSERT(ctx); |
712 | | |
713 | 480 | #if defined(WITH_OPENSSL) |
714 | 480 | int outl = (int)*olen; |
715 | | |
716 | 480 | WINPR_ASSERT(ctx->ectx); |
717 | 480 | if (EVP_CipherFinal_ex(ctx->ectx, output, &outl) == 1) |
718 | 282 | { |
719 | 282 | *olen = (size_t)outl; |
720 | 282 | return TRUE; |
721 | 282 | } |
722 | | |
723 | | #elif defined(WITH_MBEDTLS) |
724 | | |
725 | | WINPR_ASSERT(ctx->mctx); |
726 | | if (mbedtls_cipher_finish(ctx->mctx, output, olen) == 0) |
727 | | return TRUE; |
728 | | |
729 | | #endif |
730 | | |
731 | 198 | return FALSE; |
732 | 480 | } |
733 | | |
734 | | void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx) |
735 | 480 | { |
736 | 480 | if (!ctx) |
737 | 0 | return; |
738 | | |
739 | 480 | #if defined(WITH_OPENSSL) |
740 | 480 | if (ctx->ectx) |
741 | 480 | EVP_CIPHER_CTX_free(ctx->ectx); |
742 | | #elif defined(WITH_MBEDTLS) |
743 | | if (ctx->mctx) |
744 | | { |
745 | | mbedtls_cipher_free(ctx->mctx); |
746 | | free(ctx->mctx); |
747 | | } |
748 | | #endif |
749 | | |
750 | 480 | free(ctx); |
751 | 480 | } |
752 | | |
753 | | /** |
754 | | * Key Generation |
755 | | */ |
756 | | |
757 | | int winpr_Cipher_BytesToKey(int cipher, WINPR_MD_TYPE md, const void* salt, const void* data, |
758 | | size_t datal, size_t count, void* key, void* iv) |
759 | 0 | { |
760 | | /** |
761 | | * Key and IV generation compatible with OpenSSL EVP_BytesToKey(): |
762 | | * https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html |
763 | | */ |
764 | 0 | #if defined(WITH_OPENSSL) |
765 | 0 | const EVP_MD* evp_md = nullptr; |
766 | 0 | const EVP_CIPHER* evp_cipher = nullptr; |
767 | 0 | evp_md = winpr_openssl_get_evp_md(md); |
768 | 0 | evp_cipher = winpr_openssl_get_evp_cipher(WINPR_ASSERTING_INT_CAST(WINPR_CIPHER_TYPE, cipher)); |
769 | 0 | WINPR_ASSERT(datal <= INT_MAX); |
770 | 0 | WINPR_ASSERT(count <= INT_MAX); |
771 | 0 | return EVP_BytesToKey(evp_cipher, evp_md, salt, data, (int)datal, (int)count, key, iv); |
772 | | #elif defined(WITH_MBEDTLS) |
773 | | int rv = 0; |
774 | | BYTE md_buf[64]; |
775 | | int niv, nkey, addmd = 0; |
776 | | unsigned int mds = 0; |
777 | | mbedtls_md_context_t ctx; |
778 | | const mbedtls_md_info_t* md_info; |
779 | | mbedtls_cipher_type_t cipher_type; |
780 | | const mbedtls_cipher_info_t* cipher_info; |
781 | | mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md); |
782 | | md_info = mbedtls_md_info_from_type(md_type); |
783 | | cipher_type = winpr_mbedtls_get_cipher_type(cipher); |
784 | | cipher_info = mbedtls_cipher_info_from_type(cipher_type); |
785 | | nkey = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; |
786 | | niv = mbedtls_cipher_info_get_iv_size(cipher_info); |
787 | | |
788 | | if ((nkey > 64) || (niv > 64)) |
789 | | return 0; |
790 | | |
791 | | if (!data) |
792 | | return nkey; |
793 | | |
794 | | mbedtls_md_init(&ctx); |
795 | | |
796 | | if (mbedtls_md_setup(&ctx, md_info, 0) != 0) |
797 | | goto err; |
798 | | |
799 | | while (1) |
800 | | { |
801 | | if (mbedtls_md_starts(&ctx) != 0) |
802 | | goto err; |
803 | | |
804 | | if (addmd++) |
805 | | { |
806 | | if (mbedtls_md_update(&ctx, md_buf, mds) != 0) |
807 | | goto err; |
808 | | } |
809 | | |
810 | | if (mbedtls_md_update(&ctx, data, datal) != 0) |
811 | | goto err; |
812 | | |
813 | | if (salt) |
814 | | { |
815 | | if (mbedtls_md_update(&ctx, salt, 8) != 0) |
816 | | goto err; |
817 | | } |
818 | | |
819 | | if (mbedtls_md_finish(&ctx, md_buf) != 0) |
820 | | goto err; |
821 | | |
822 | | mds = mbedtls_md_get_size(md_info); |
823 | | |
824 | | for (unsigned int i = 1; i < (unsigned int)count; i++) |
825 | | { |
826 | | if (mbedtls_md_starts(&ctx) != 0) |
827 | | goto err; |
828 | | |
829 | | if (mbedtls_md_update(&ctx, md_buf, mds) != 0) |
830 | | goto err; |
831 | | |
832 | | if (mbedtls_md_finish(&ctx, md_buf) != 0) |
833 | | goto err; |
834 | | } |
835 | | |
836 | | unsigned int i = 0; |
837 | | |
838 | | if (nkey) |
839 | | { |
840 | | while (1) |
841 | | { |
842 | | if (nkey == 0) |
843 | | break; |
844 | | |
845 | | if (i == mds) |
846 | | break; |
847 | | |
848 | | if (key) |
849 | | *(BYTE*)(key++) = md_buf[i]; |
850 | | |
851 | | nkey--; |
852 | | i++; |
853 | | } |
854 | | } |
855 | | |
856 | | if (niv && (i != mds)) |
857 | | { |
858 | | while (1) |
859 | | { |
860 | | if (niv == 0) |
861 | | break; |
862 | | |
863 | | if (i == mds) |
864 | | break; |
865 | | |
866 | | if (iv) |
867 | | *(BYTE*)(iv++) = md_buf[i]; |
868 | | |
869 | | niv--; |
870 | | i++; |
871 | | } |
872 | | } |
873 | | |
874 | | if ((nkey == 0) && (niv == 0)) |
875 | | break; |
876 | | } |
877 | | |
878 | | rv = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; |
879 | | err: |
880 | | mbedtls_md_free(&ctx); |
881 | | SecureZeroMemory(md_buf, 64); |
882 | | return rv; |
883 | | #else |
884 | | return 0; |
885 | | #endif |
886 | 0 | } |