/root/doris/be/src/util/encryption_util.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "util/encryption_util.h" |
19 | | |
20 | | #include <openssl/err.h> |
21 | | #include <openssl/evp.h> |
22 | | #include <openssl/ossl_typ.h> |
23 | | #include <sys/types.h> |
24 | | |
25 | | #include <algorithm> |
26 | | #include <cstring> |
27 | | #include <string> |
28 | | #include <unordered_map> |
29 | | |
30 | | namespace doris { |
31 | | |
32 | | static const int ENCRYPTION_MAX_KEY_LENGTH = 256; |
33 | | |
34 | 620 | const EVP_CIPHER* get_evp_type(const EncryptionMode mode) { |
35 | 620 | switch (mode) { |
36 | 96 | case EncryptionMode::AES_128_ECB: |
37 | 96 | return EVP_aes_128_ecb(); |
38 | 4 | case EncryptionMode::AES_128_CBC: |
39 | 4 | return EVP_aes_128_cbc(); |
40 | 0 | case EncryptionMode::AES_128_CFB: |
41 | 0 | return EVP_aes_128_cfb(); |
42 | 0 | case EncryptionMode::AES_128_CFB1: |
43 | 0 | return EVP_aes_128_cfb1(); |
44 | 0 | case EncryptionMode::AES_128_CFB8: |
45 | 0 | return EVP_aes_128_cfb8(); |
46 | 0 | case EncryptionMode::AES_128_CFB128: |
47 | 0 | return EVP_aes_128_cfb128(); |
48 | 0 | case EncryptionMode::AES_128_CTR: |
49 | 0 | return EVP_aes_128_ctr(); |
50 | 85 | case EncryptionMode::AES_128_OFB: |
51 | 85 | return EVP_aes_128_ofb(); |
52 | 0 | case EncryptionMode::AES_192_ECB: |
53 | 0 | return EVP_aes_192_ecb(); |
54 | 0 | case EncryptionMode::AES_192_CBC: |
55 | 0 | return EVP_aes_192_cbc(); |
56 | 0 | case EncryptionMode::AES_192_CFB: |
57 | 0 | return EVP_aes_192_cfb(); |
58 | 0 | case EncryptionMode::AES_192_CFB1: |
59 | 0 | return EVP_aes_192_cfb1(); |
60 | 0 | case EncryptionMode::AES_192_CFB8: |
61 | 0 | return EVP_aes_192_cfb8(); |
62 | 0 | case EncryptionMode::AES_192_CFB128: |
63 | 0 | return EVP_aes_192_cfb128(); |
64 | 0 | case EncryptionMode::AES_192_CTR: |
65 | 0 | return EVP_aes_192_ctr(); |
66 | 0 | case EncryptionMode::AES_192_OFB: |
67 | 0 | return EVP_aes_192_ofb(); |
68 | 85 | case EncryptionMode::AES_256_ECB: |
69 | 85 | return EVP_aes_256_ecb(); |
70 | 0 | case EncryptionMode::AES_256_CBC: |
71 | 0 | return EVP_aes_256_cbc(); |
72 | 0 | case EncryptionMode::AES_256_CFB: |
73 | 0 | return EVP_aes_256_cfb(); |
74 | 0 | case EncryptionMode::AES_256_CFB1: |
75 | 0 | return EVP_aes_256_cfb1(); |
76 | 0 | case EncryptionMode::AES_256_CFB8: |
77 | 0 | return EVP_aes_256_cfb8(); |
78 | 0 | case EncryptionMode::AES_256_CFB128: |
79 | 0 | return EVP_aes_256_cfb128(); |
80 | 0 | case EncryptionMode::AES_256_CTR: |
81 | 0 | return EVP_aes_256_ctr(); |
82 | 0 | case EncryptionMode::AES_256_OFB: |
83 | 0 | return EVP_aes_256_ofb(); |
84 | 0 | case EncryptionMode::AES_128_GCM: |
85 | 0 | return EVP_aes_128_gcm(); |
86 | 0 | case EncryptionMode::AES_192_GCM: |
87 | 0 | return EVP_aes_192_gcm(); |
88 | 0 | case EncryptionMode::AES_256_GCM: |
89 | 0 | return EVP_aes_256_gcm(); |
90 | 4 | case EncryptionMode::SM4_128_CBC: |
91 | 4 | return EVP_sm4_cbc(); |
92 | 176 | case EncryptionMode::SM4_128_ECB: |
93 | 176 | return EVP_sm4_ecb(); |
94 | 0 | case EncryptionMode::SM4_128_CFB128: |
95 | 0 | return EVP_sm4_cfb128(); |
96 | 85 | case EncryptionMode::SM4_128_OFB: |
97 | 85 | return EVP_sm4_ofb(); |
98 | 85 | case EncryptionMode::SM4_128_CTR: |
99 | 85 | return EVP_sm4_ctr(); |
100 | 0 | default: |
101 | 0 | return nullptr; |
102 | 620 | } |
103 | 620 | } |
104 | | |
105 | | static std::unordered_map<EncryptionMode, uint> mode_key_sizes = { |
106 | | {EncryptionMode::AES_128_ECB, 128}, {EncryptionMode::AES_192_ECB, 192}, |
107 | | {EncryptionMode::AES_256_ECB, 256}, {EncryptionMode::AES_128_CBC, 128}, |
108 | | {EncryptionMode::AES_192_CBC, 192}, {EncryptionMode::AES_256_CBC, 256}, |
109 | | {EncryptionMode::AES_128_CFB, 128}, {EncryptionMode::AES_192_CFB, 192}, |
110 | | {EncryptionMode::AES_256_CFB, 256}, {EncryptionMode::AES_128_CFB1, 128}, |
111 | | {EncryptionMode::AES_192_CFB1, 192}, {EncryptionMode::AES_256_CFB1, 256}, |
112 | | {EncryptionMode::AES_128_CFB8, 128}, {EncryptionMode::AES_192_CFB8, 192}, |
113 | | {EncryptionMode::AES_256_CFB8, 256}, {EncryptionMode::AES_128_CFB128, 128}, |
114 | | {EncryptionMode::AES_192_CFB128, 192}, {EncryptionMode::AES_256_CFB128, 256}, |
115 | | {EncryptionMode::AES_128_CTR, 128}, {EncryptionMode::AES_192_CTR, 192}, |
116 | | {EncryptionMode::AES_256_CTR, 256}, {EncryptionMode::AES_128_OFB, 128}, |
117 | | {EncryptionMode::AES_192_OFB, 192}, {EncryptionMode::AES_256_OFB, 256}, |
118 | | {EncryptionMode::AES_128_GCM, 128}, {EncryptionMode::AES_192_GCM, 192}, |
119 | | {EncryptionMode::AES_256_GCM, 256}, |
120 | | |
121 | | {EncryptionMode::SM4_128_ECB, 128}, {EncryptionMode::SM4_128_CBC, 128}, |
122 | | {EncryptionMode::SM4_128_CFB128, 128}, {EncryptionMode::SM4_128_OFB, 128}, |
123 | | {EncryptionMode::SM4_128_CTR, 128}}; |
124 | | |
125 | | static void create_key(const unsigned char* origin_key, uint32_t key_length, uint8_t* encrypt_key, |
126 | 620 | EncryptionMode mode) { |
127 | 620 | const uint key_size = mode_key_sizes[mode] / 8; |
128 | 620 | uint8_t* origin_key_end = ((uint8_t*)origin_key) + key_length; /* origin key boundary*/ |
129 | | |
130 | 620 | uint8_t* encrypt_key_end; /* encrypt key boundary */ |
131 | 620 | encrypt_key_end = encrypt_key + key_size; |
132 | | |
133 | 620 | std::memset(encrypt_key, 0, key_size); /* initialize key */ |
134 | | |
135 | 620 | uint8_t* ptr; /* Start of the encrypt key*/ |
136 | 620 | uint8_t* origin_ptr; /* Start of the origin key */ |
137 | 5.58k | for (ptr = encrypt_key, origin_ptr = (uint8_t*)origin_key; origin_ptr < origin_key_end; |
138 | 4.96k | ptr++, origin_ptr++) { |
139 | 4.96k | if (ptr == encrypt_key_end) { |
140 | | /* loop over origin key until we used all key */ |
141 | 0 | ptr = encrypt_key; |
142 | 0 | } |
143 | 4.96k | *ptr ^= *origin_ptr; |
144 | 4.96k | } |
145 | 620 | } |
146 | | |
147 | | static int do_encrypt(EVP_CIPHER_CTX* cipher_ctx, const EVP_CIPHER* cipher, |
148 | | const unsigned char* source, uint32_t source_length, |
149 | | const unsigned char* encrypt_key, const unsigned char* iv, bool padding, |
150 | 324 | unsigned char* encrypt, int* length_ptr) { |
151 | 324 | int ret = EVP_EncryptInit(cipher_ctx, cipher, encrypt_key, iv); |
152 | 324 | if (ret == 0) { |
153 | 0 | return ret; |
154 | 0 | } |
155 | 324 | ret = EVP_CIPHER_CTX_set_padding(cipher_ctx, padding); |
156 | 324 | if (ret == 0) { |
157 | 0 | return ret; |
158 | 0 | } |
159 | 324 | int u_len = 0; |
160 | 324 | ret = EVP_EncryptUpdate(cipher_ctx, encrypt, &u_len, source, source_length); |
161 | 324 | if (ret == 0) { |
162 | 0 | return ret; |
163 | 0 | } |
164 | 324 | int f_len = 0; |
165 | 324 | ret = EVP_EncryptFinal(cipher_ctx, encrypt + u_len, &f_len); |
166 | 324 | *length_ptr = u_len + f_len; |
167 | 324 | return ret; |
168 | 324 | } |
169 | | |
170 | | static int do_gcm_encrypt(EVP_CIPHER_CTX* cipher_ctx, const EVP_CIPHER* cipher, |
171 | | const unsigned char* source, uint32_t source_length, |
172 | | const unsigned char* encrypt_key, const unsigned char* iv, int iv_length, |
173 | | unsigned char* encrypt, int* length_ptr, const unsigned char* aad, |
174 | 0 | uint32_t aad_length) { |
175 | 0 | int ret = EVP_EncryptInit_ex(cipher_ctx, cipher, nullptr, nullptr, nullptr); |
176 | 0 | if (ret != 1) { |
177 | 0 | return ret; |
178 | 0 | } |
179 | 0 | ret = EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GCM_SET_IVLEN, iv_length, nullptr); |
180 | 0 | if (ret != 1) { |
181 | 0 | return ret; |
182 | 0 | } |
183 | 0 | ret = EVP_EncryptInit_ex(cipher_ctx, nullptr, nullptr, encrypt_key, iv); |
184 | 0 | if (ret != 1) { |
185 | 0 | return ret; |
186 | 0 | } |
187 | 0 | if (aad) { |
188 | 0 | int tmp_len = 0; |
189 | 0 | ret = EVP_EncryptUpdate(cipher_ctx, nullptr, &tmp_len, aad, aad_length); |
190 | 0 | if (ret != 1) { |
191 | 0 | return ret; |
192 | 0 | } |
193 | 0 | } |
194 | | |
195 | 0 | std::memcpy(encrypt, iv, iv_length); |
196 | 0 | encrypt += iv_length; |
197 | |
|
198 | 0 | int u_len = 0; |
199 | 0 | ret = EVP_EncryptUpdate(cipher_ctx, encrypt, &u_len, source, source_length); |
200 | 0 | if (ret != 1) { |
201 | 0 | return ret; |
202 | 0 | } |
203 | 0 | encrypt += u_len; |
204 | |
|
205 | 0 | int f_len = 0; |
206 | 0 | ret = EVP_EncryptFinal_ex(cipher_ctx, encrypt, &f_len); |
207 | 0 | if (ret != 1) { |
208 | 0 | return ret; |
209 | 0 | } |
210 | 0 | encrypt += f_len; |
211 | |
|
212 | 0 | ret = EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GCM_GET_TAG, EncryptionUtil::GCM_TAG_SIZE, |
213 | 0 | encrypt); |
214 | 0 | *length_ptr = iv_length + u_len + f_len + EncryptionUtil::GCM_TAG_SIZE; |
215 | 0 | return ret; |
216 | 0 | } |
217 | | |
218 | | int EncryptionUtil::encrypt(EncryptionMode mode, const unsigned char* source, |
219 | | uint32_t source_length, const unsigned char* key, uint32_t key_length, |
220 | | const char* iv_str, int iv_input_length, bool padding, |
221 | 324 | unsigned char* encrypt, const unsigned char* aad, uint32_t aad_length) { |
222 | 324 | const EVP_CIPHER* cipher = get_evp_type(mode); |
223 | | /* The encrypt key to be used for encryption */ |
224 | 324 | unsigned char encrypt_key[ENCRYPTION_MAX_KEY_LENGTH / 8]; |
225 | 324 | create_key(key, key_length, encrypt_key, mode); |
226 | | |
227 | 324 | int iv_length = EVP_CIPHER_iv_length(cipher); |
228 | 324 | if (cipher == nullptr || (iv_length > 0 && !iv_str)) { |
229 | 0 | return AES_BAD_DATA; |
230 | 0 | } |
231 | 324 | char* init_vec = nullptr; |
232 | 324 | std::string iv_default("DORISDORISDORIS_"); |
233 | | |
234 | 324 | if (iv_str) { |
235 | 270 | init_vec = &iv_default[0]; |
236 | 270 | memcpy(init_vec, iv_str, std::min(iv_input_length, EVP_MAX_IV_LENGTH)); |
237 | 270 | init_vec[iv_length] = '\0'; |
238 | 270 | } |
239 | 324 | EVP_CIPHER_CTX* cipher_ctx = EVP_CIPHER_CTX_new(); |
240 | 324 | EVP_CIPHER_CTX_reset(cipher_ctx); |
241 | 324 | int length = 0; |
242 | 324 | int ret = 0; |
243 | 324 | if (is_gcm_mode(mode)) { |
244 | 0 | ret = do_gcm_encrypt(cipher_ctx, cipher, source, source_length, encrypt_key, |
245 | 0 | reinterpret_cast<unsigned char*>(init_vec), iv_length, encrypt, |
246 | 0 | &length, aad, aad_length); |
247 | 324 | } else { |
248 | 324 | ret = do_encrypt(cipher_ctx, cipher, source, source_length, encrypt_key, |
249 | 324 | reinterpret_cast<unsigned char*>(init_vec), padding, encrypt, &length); |
250 | 324 | } |
251 | | |
252 | 324 | EVP_CIPHER_CTX_free(cipher_ctx); |
253 | 324 | if (ret == 0) { |
254 | 0 | ERR_clear_error(); |
255 | 0 | return AES_BAD_DATA; |
256 | 324 | } else { |
257 | 324 | return length; |
258 | 324 | } |
259 | 324 | } |
260 | | |
261 | | static int do_decrypt(EVP_CIPHER_CTX* cipher_ctx, const EVP_CIPHER* cipher, |
262 | | const unsigned char* encrypt, uint32_t encrypt_length, |
263 | | const unsigned char* encrypt_key, const unsigned char* iv, bool padding, |
264 | 296 | unsigned char* decrypt_content, int* length_ptr) { |
265 | 296 | int ret = EVP_DecryptInit(cipher_ctx, cipher, encrypt_key, iv); |
266 | 296 | if (ret == 0) { |
267 | 0 | return ret; |
268 | 0 | } |
269 | 296 | ret = EVP_CIPHER_CTX_set_padding(cipher_ctx, padding); |
270 | 296 | if (ret == 0) { |
271 | 0 | return ret; |
272 | 0 | } |
273 | 296 | int u_len = 0; |
274 | 296 | ret = EVP_DecryptUpdate(cipher_ctx, decrypt_content, &u_len, encrypt, encrypt_length); |
275 | 296 | if (ret == 0) { |
276 | 0 | return ret; |
277 | 0 | } |
278 | 296 | int f_len = 0; |
279 | 296 | ret = EVP_DecryptFinal_ex(cipher_ctx, decrypt_content + u_len, &f_len); |
280 | 296 | *length_ptr = u_len + f_len; |
281 | 296 | return ret; |
282 | 296 | } |
283 | | |
284 | | static int do_gcm_decrypt(EVP_CIPHER_CTX* cipher_ctx, const EVP_CIPHER* cipher, |
285 | | const unsigned char* encrypt, uint32_t encrypt_length, |
286 | | const unsigned char* encrypt_key, int iv_length, |
287 | | unsigned char* decrypt_content, int* length_ptr, const unsigned char* aad, |
288 | 0 | uint32_t aad_length) { |
289 | 0 | if (encrypt_length < iv_length + EncryptionUtil::GCM_TAG_SIZE) { |
290 | 0 | return -1; |
291 | 0 | } |
292 | 0 | int ret = EVP_DecryptInit_ex(cipher_ctx, cipher, nullptr, nullptr, nullptr); |
293 | 0 | if (ret != 1) { |
294 | 0 | return ret; |
295 | 0 | } |
296 | 0 | ret = EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GCM_SET_IVLEN, iv_length, nullptr); |
297 | 0 | if (ret != 1) { |
298 | 0 | return ret; |
299 | 0 | } |
300 | 0 | ret = EVP_DecryptInit_ex(cipher_ctx, nullptr, nullptr, encrypt_key, encrypt); |
301 | 0 | if (ret != 1) { |
302 | 0 | return ret; |
303 | 0 | } |
304 | 0 | encrypt += iv_length; |
305 | 0 | if (aad) { |
306 | 0 | int tmp_len = 0; |
307 | 0 | ret = EVP_DecryptUpdate(cipher_ctx, nullptr, &tmp_len, aad, aad_length); |
308 | 0 | if (ret != 1) { |
309 | 0 | return ret; |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | 0 | uint32_t real_encrypt_length = encrypt_length - iv_length - EncryptionUtil::GCM_TAG_SIZE; |
314 | 0 | int u_len = 0; |
315 | 0 | ret = EVP_DecryptUpdate(cipher_ctx, decrypt_content, &u_len, encrypt, real_encrypt_length); |
316 | 0 | if (ret != 1) { |
317 | 0 | return ret; |
318 | 0 | } |
319 | 0 | encrypt += real_encrypt_length; |
320 | 0 | decrypt_content += u_len; |
321 | |
|
322 | 0 | void* tag = const_cast<void*>(reinterpret_cast<const void*>(encrypt)); |
323 | 0 | ret = EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GCM_SET_TAG, EncryptionUtil::GCM_TAG_SIZE, tag); |
324 | 0 | if (ret != 1) { |
325 | 0 | return ret; |
326 | 0 | } |
327 | | |
328 | 0 | int f_len = 0; |
329 | 0 | ret = EVP_DecryptFinal_ex(cipher_ctx, decrypt_content, &f_len); |
330 | 0 | *length_ptr = u_len + f_len; |
331 | 0 | return ret; |
332 | 0 | } |
333 | | |
334 | | int EncryptionUtil::decrypt(EncryptionMode mode, const unsigned char* encrypt, |
335 | | uint32_t encrypt_length, const unsigned char* key, uint32_t key_length, |
336 | | const char* iv_str, int iv_input_length, bool padding, |
337 | | unsigned char* decrypt_content, const unsigned char* aad, |
338 | 296 | uint32_t aad_length) { |
339 | 296 | const EVP_CIPHER* cipher = get_evp_type(mode); |
340 | | |
341 | | /* The encrypt key to be used for decryption */ |
342 | 296 | unsigned char encrypt_key[ENCRYPTION_MAX_KEY_LENGTH / 8]; |
343 | 296 | create_key(key, key_length, encrypt_key, mode); |
344 | | |
345 | 296 | int iv_length = EVP_CIPHER_iv_length(cipher); |
346 | 296 | if (cipher == nullptr || (iv_length > 0 && !iv_str)) { |
347 | 0 | return AES_BAD_DATA; |
348 | 0 | } |
349 | 296 | char* init_vec = nullptr; |
350 | 296 | std::string iv_default("DORISDORISDORIS_"); |
351 | | |
352 | 296 | if (iv_str) { |
353 | 248 | init_vec = &iv_default[0]; |
354 | 248 | memcpy(init_vec, iv_str, std::min(iv_input_length, EVP_MAX_IV_LENGTH)); |
355 | 248 | init_vec[iv_length] = '\0'; |
356 | 248 | } |
357 | 296 | EVP_CIPHER_CTX* cipher_ctx = EVP_CIPHER_CTX_new(); |
358 | 296 | EVP_CIPHER_CTX_reset(cipher_ctx); |
359 | 296 | int length = 0; |
360 | 296 | int ret = 0; |
361 | 296 | if (is_gcm_mode(mode)) { |
362 | 0 | ret = do_gcm_decrypt(cipher_ctx, cipher, encrypt, encrypt_length, encrypt_key, iv_length, |
363 | 0 | decrypt_content, &length, aad, aad_length); |
364 | 296 | } else { |
365 | 296 | ret = do_decrypt(cipher_ctx, cipher, encrypt, encrypt_length, encrypt_key, |
366 | 296 | reinterpret_cast<unsigned char*>(init_vec), padding, decrypt_content, |
367 | 296 | &length); |
368 | 296 | } |
369 | 296 | EVP_CIPHER_CTX_free(cipher_ctx); |
370 | 296 | if (ret > 0) { |
371 | 296 | return length; |
372 | 296 | } else { |
373 | 0 | ERR_clear_error(); |
374 | 0 | return AES_BAD_DATA; |
375 | 0 | } |
376 | 296 | } |
377 | | |
378 | | } // namespace doris |