/src/boringssl/crypto/fipsmodule/cipher/cipher.cc.inc
Line | Count | Source |
1 | | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/cipher.h> |
16 | | |
17 | | #include <assert.h> |
18 | | #include <limits.h> |
19 | | #include <string.h> |
20 | | |
21 | | #include <openssl/err.h> |
22 | | #include <openssl/mem.h> |
23 | | #include <openssl/nid.h> |
24 | | #include <openssl/span.h> |
25 | | |
26 | | #include "../../internal.h" |
27 | | #include "../../mem_internal.h" |
28 | | #include "../service_indicator/internal.h" |
29 | | #include "internal.h" |
30 | | |
31 | | |
32 | | using namespace bssl; |
33 | | |
34 | 34.1k | void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) { |
35 | 34.1k | OPENSSL_memset(ctx, 0, sizeof(EVP_CIPHER_CTX)); |
36 | 34.1k | } |
37 | | |
38 | 0 | EVP_CIPHER_CTX *EVP_CIPHER_CTX_new() { |
39 | 0 | EVP_CIPHER_CTX *ctx = New<EVP_CIPHER_CTX>(); |
40 | 0 | if (ctx) { |
41 | 0 | EVP_CIPHER_CTX_init(ctx); |
42 | 0 | } |
43 | 0 | return ctx; |
44 | 0 | } |
45 | | |
46 | 34.1k | int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) { |
47 | 34.1k | if (c->cipher != nullptr && c->cipher->cleanup) { |
48 | 0 | c->cipher->cleanup(c); |
49 | 0 | } |
50 | 34.1k | OPENSSL_free(c->cipher_data); |
51 | | |
52 | 34.1k | OPENSSL_memset(c, 0, sizeof(EVP_CIPHER_CTX)); |
53 | 34.1k | return 1; |
54 | 34.1k | } |
55 | | |
56 | 0 | void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { |
57 | 0 | if (ctx) { |
58 | 0 | EVP_CIPHER_CTX_cleanup(ctx); |
59 | 0 | Delete(ctx); |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | 0 | int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { |
64 | 0 | if (in == nullptr || in->cipher == nullptr) { |
65 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INPUT_NOT_INITIALIZED); |
66 | 0 | return 0; |
67 | 0 | } |
68 | | |
69 | 0 | if (in->poisoned) { |
70 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
71 | 0 | return 0; |
72 | 0 | } |
73 | | |
74 | 0 | EVP_CIPHER_CTX_cleanup(out); |
75 | 0 | OPENSSL_memcpy(out, in, sizeof(EVP_CIPHER_CTX)); |
76 | |
|
77 | 0 | if (in->cipher_data && in->cipher->ctx_size) { |
78 | 0 | out->cipher_data = OPENSSL_memdup(in->cipher_data, in->cipher->ctx_size); |
79 | 0 | if (!out->cipher_data) { |
80 | 0 | out->cipher = nullptr; |
81 | 0 | return 0; |
82 | 0 | } |
83 | 0 | } |
84 | | |
85 | 0 | if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) { |
86 | 0 | if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) { |
87 | 0 | out->cipher = nullptr; |
88 | 0 | return 0; |
89 | 0 | } |
90 | 0 | } |
91 | | |
92 | 0 | return 1; |
93 | 0 | } |
94 | | |
95 | 0 | int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) { |
96 | 0 | EVP_CIPHER_CTX_cleanup(ctx); |
97 | 0 | EVP_CIPHER_CTX_init(ctx); |
98 | 0 | return 1; |
99 | 0 | } |
100 | | |
101 | | int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
102 | | ENGINE *engine, const uint8_t *key, const uint8_t *iv, |
103 | 35.8k | int enc) { |
104 | 35.8k | if (enc == -1) { |
105 | 0 | enc = ctx->encrypt; |
106 | 35.8k | } else { |
107 | 35.8k | if (enc) { |
108 | 19.5k | enc = 1; |
109 | 19.5k | } |
110 | 35.8k | ctx->encrypt = enc; |
111 | 35.8k | } |
112 | | |
113 | 35.8k | if (cipher) { |
114 | | // Ensure a context left from last time is cleared (the previous check |
115 | | // attempted to avoid this if the same ENGINE and EVP_CIPHER could be |
116 | | // used). |
117 | 33.9k | if (ctx->cipher) { |
118 | 0 | EVP_CIPHER_CTX_cleanup(ctx); |
119 | | // Restore encrypt and flags |
120 | 0 | ctx->encrypt = enc; |
121 | 0 | } |
122 | | |
123 | 33.9k | ctx->cipher = cipher; |
124 | 33.9k | if (ctx->cipher->ctx_size) { |
125 | 33.9k | ctx->cipher_data = OPENSSL_malloc(ctx->cipher->ctx_size); |
126 | 33.9k | if (!ctx->cipher_data) { |
127 | 0 | ctx->cipher = nullptr; |
128 | 0 | return 0; |
129 | 0 | } |
130 | 33.9k | } else { |
131 | 0 | ctx->cipher_data = nullptr; |
132 | 0 | } |
133 | | |
134 | 33.9k | ctx->key_len = cipher->key_len; |
135 | 33.9k | ctx->flags = 0; |
136 | | |
137 | 33.9k | if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { |
138 | 6 | if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, nullptr)) { |
139 | 0 | ctx->cipher = nullptr; |
140 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INITIALIZATION_ERROR); |
141 | 0 | return 0; |
142 | 0 | } |
143 | 6 | } |
144 | 33.9k | } else if (!ctx->cipher) { |
145 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_CIPHER_SET); |
146 | 0 | return 0; |
147 | 0 | } |
148 | | |
149 | | // we assume block size is a power of 2 in *cryptUpdate |
150 | 35.8k | assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 || |
151 | 35.8k | ctx->cipher->block_size == 16); |
152 | | |
153 | 35.8k | if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { |
154 | 35.8k | switch (EVP_CIPHER_CTX_mode(ctx)) { |
155 | 0 | case EVP_CIPH_STREAM_CIPHER: |
156 | 0 | case EVP_CIPH_ECB_MODE: |
157 | 0 | break; |
158 | | |
159 | 0 | case EVP_CIPH_CFB_MODE: |
160 | 0 | ctx->num = 0; |
161 | 0 | [[fallthrough]]; |
162 | |
|
163 | 35.8k | case EVP_CIPH_CBC_MODE: |
164 | 35.8k | assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof(ctx->iv)); |
165 | 35.8k | if (iv) { |
166 | 6.04k | OPENSSL_memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); |
167 | 6.04k | } |
168 | 35.8k | OPENSSL_memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); |
169 | 35.8k | break; |
170 | | |
171 | 0 | case EVP_CIPH_CTR_MODE: |
172 | 0 | case EVP_CIPH_OFB_MODE: |
173 | 0 | ctx->num = 0; |
174 | | // Don't reuse IV for CTR mode |
175 | 0 | if (iv) { |
176 | 0 | OPENSSL_memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx)); |
177 | 0 | } |
178 | 0 | break; |
179 | | |
180 | 0 | default: |
181 | 0 | return 0; |
182 | 35.8k | } |
183 | 35.8k | } |
184 | | |
185 | 35.8k | if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { |
186 | 33.9k | if (!ctx->cipher->init(ctx, key, iv, enc)) { |
187 | 0 | return 0; |
188 | 0 | } |
189 | 33.9k | } |
190 | | |
191 | 35.8k | ctx->buf_len = 0; |
192 | 35.8k | ctx->final_used = 0; |
193 | | // Clear the poisoned flag to permit reuse of a CTX that previously had a |
194 | | // failed operation. |
195 | 35.8k | ctx->poisoned = 0; |
196 | 35.8k | return 1; |
197 | 35.8k | } |
198 | | |
199 | | int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
200 | 2.74k | ENGINE *impl, const uint8_t *key, const uint8_t *iv) { |
201 | 2.74k | return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1); |
202 | 2.74k | } |
203 | | |
204 | | int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
205 | 695 | ENGINE *impl, const uint8_t *key, const uint8_t *iv) { |
206 | 695 | return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0); |
207 | 695 | } |
208 | | |
209 | | // block_remainder returns the number of bytes to remove from `len` to get a |
210 | | // multiple of `ctx`'s block size. |
211 | 8.88k | static size_t block_remainder(const EVP_CIPHER_CTX *ctx, size_t len) { |
212 | | // `block_size` must be a power of two. |
213 | 8.88k | assert(ctx->cipher->block_size != 0); |
214 | 8.88k | assert((ctx->cipher->block_size & (ctx->cipher->block_size - 1)) == 0); |
215 | 8.88k | return len & (ctx->cipher->block_size - 1); |
216 | 8.88k | } |
217 | | |
218 | | int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, |
219 | 0 | const uint8_t *in, int in_len) { |
220 | 0 | *out_len = 0; |
221 | 0 | if (in_len < 0) { |
222 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_OVERFLOW); |
223 | 0 | return 0; |
224 | 0 | } |
225 | 0 | size_t in_len_sz = static_cast<size_t>(in_len); |
226 | 0 | size_t out_len_sz; |
227 | 0 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) && out == nullptr) { |
228 | 0 | if (!EVP_CipherUpdateAAD(ctx, in, in_len_sz)) { |
229 | 0 | return 0; |
230 | 0 | } |
231 | 0 | out_len_sz = in_len_sz; // Even though no output was written! |
232 | 0 | } else { |
233 | | // in_len_sz is < INT_MAX which is no more than half of SIZE_MAX. |
234 | 0 | size_t max_out_len = |
235 | 0 | std::min(in_len_sz + ctx->cipher->block_size - 1, size_t{INT_MAX}); |
236 | 0 | if (!EVP_EncryptUpdate_ex(ctx, out, &out_len_sz, max_out_len, in, |
237 | 0 | in_len_sz)) { |
238 | 0 | return 0; |
239 | 0 | } |
240 | 0 | } |
241 | 0 | *out_len = static_cast<int>(out_len_sz); |
242 | 0 | return 1; |
243 | 0 | } |
244 | | |
245 | | template <typename F> |
246 | 10.4k | static int WrapWithPoison(EVP_CIPHER_CTX *ctx, F f) { |
247 | 10.4k | if (ctx->poisoned) { |
248 | | // `ctx` has been left in an indeterminate state by a previous failed |
249 | | // operation. Do not allow proceeding. |
250 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
251 | 0 | return 0; |
252 | 0 | } |
253 | 10.4k | if (!f()) { |
254 | | // Functions using `WrapWithPoison` may leave `ctx` in an indeterminate |
255 | | // state. Mark the object as poisoned. |
256 | 0 | ctx->poisoned = 1; |
257 | 0 | return 0; |
258 | 0 | } |
259 | 10.4k | return 1; |
260 | 10.4k | } bcm.cc:int WrapWithPoison<EVP_EncryptUpdate_ex::$_0>(evp_cipher_ctx_st*, EVP_EncryptUpdate_ex::$_0) Line | Count | Source | 246 | 4.99k | static int WrapWithPoison(EVP_CIPHER_CTX *ctx, F f) { | 247 | 4.99k | if (ctx->poisoned) { | 248 | | // `ctx` has been left in an indeterminate state by a previous failed | 249 | | // operation. Do not allow proceeding. | 250 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | 251 | 0 | return 0; | 252 | 0 | } | 253 | 4.99k | if (!f()) { | 254 | | // Functions using `WrapWithPoison` may leave `ctx` in an indeterminate | 255 | | // state. Mark the object as poisoned. | 256 | 0 | ctx->poisoned = 1; | 257 | 0 | return 0; | 258 | 0 | } | 259 | 4.99k | return 1; | 260 | 4.99k | } |
bcm.cc:int WrapWithPoison<EVP_EncryptFinal_ex2::$_0>(evp_cipher_ctx_st*, EVP_EncryptFinal_ex2::$_0) Line | Count | Source | 246 | 1.61k | static int WrapWithPoison(EVP_CIPHER_CTX *ctx, F f) { | 247 | 1.61k | if (ctx->poisoned) { | 248 | | // `ctx` has been left in an indeterminate state by a previous failed | 249 | | // operation. Do not allow proceeding. | 250 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | 251 | 0 | return 0; | 252 | 0 | } | 253 | 1.61k | if (!f()) { | 254 | | // Functions using `WrapWithPoison` may leave `ctx` in an indeterminate | 255 | | // state. Mark the object as poisoned. | 256 | 0 | ctx->poisoned = 1; | 257 | 0 | return 0; | 258 | 0 | } | 259 | 1.61k | return 1; | 260 | 1.61k | } |
bcm.cc:int WrapWithPoison<EVP_DecryptUpdate_ex::$_0>(evp_cipher_ctx_st*, EVP_DecryptUpdate_ex::$_0) Line | Count | Source | 246 | 3.85k | static int WrapWithPoison(EVP_CIPHER_CTX *ctx, F f) { | 247 | 3.85k | if (ctx->poisoned) { | 248 | | // `ctx` has been left in an indeterminate state by a previous failed | 249 | | // operation. Do not allow proceeding. | 250 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | 251 | 0 | return 0; | 252 | 0 | } | 253 | 3.85k | if (!f()) { | 254 | | // Functions using `WrapWithPoison` may leave `ctx` in an indeterminate | 255 | | // state. Mark the object as poisoned. | 256 | 0 | ctx->poisoned = 1; | 257 | 0 | return 0; | 258 | 0 | } | 259 | 3.85k | return 1; | 260 | 3.85k | } |
bcm.cc:int WrapWithPoison<EVP_DecryptFinal_ex2::$_0>(evp_cipher_ctx_st*, EVP_DecryptFinal_ex2::$_0) Line | Count | Source | 246 | 14 | static int WrapWithPoison(EVP_CIPHER_CTX *ctx, F f) { | 247 | 14 | if (ctx->poisoned) { | 248 | | // `ctx` has been left in an indeterminate state by a previous failed | 249 | | // operation. Do not allow proceeding. | 250 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | 251 | 0 | return 0; | 252 | 0 | } | 253 | 14 | if (!f()) { | 254 | | // Functions using `WrapWithPoison` may leave `ctx` in an indeterminate | 255 | | // state. Mark the object as poisoned. | 256 | 0 | ctx->poisoned = 1; | 257 | 0 | return 0; | 258 | 0 | } | 259 | 14 | return 1; | 260 | 14 | } |
Unexecuted instantiation: bcm.cc:int WrapWithPoison<EVP_CipherUpdateAAD::$_0>(evp_cipher_ctx_st*, EVP_CipherUpdateAAD::$_0) |
261 | | |
262 | | static int EVP_EncryptUpdate_ex_internal(EVP_CIPHER_CTX *ctx, uint8_t *out, |
263 | | size_t *out_len, size_t max_out_len, |
264 | 8.86k | const uint8_t *in, size_t in_len) { |
265 | 8.86k | *out_len = 0; |
266 | | |
267 | | // Ciphers that use blocks may write up to `block_size` extra bytes. Ensure |
268 | | // the output does not overflow `*out_len`. |
269 | 8.86k | Span<const uint8_t> in_span(in, in_len); |
270 | 8.86k | size_t block_size = ctx->cipher->block_size; |
271 | | |
272 | 8.86k | if (in_span.empty()) { |
273 | 0 | return 1; |
274 | 0 | } |
275 | | |
276 | 8.86k | size_t buf_len = ctx->buf_len; |
277 | 8.86k | assert(block_size <= sizeof(ctx->buf)); |
278 | 8.86k | Span<uint8_t> out_span(out, max_out_len); |
279 | 8.86k | if (buf_len != 0) { |
280 | 1.91k | if (block_size - buf_len > in_span.size()) { |
281 | 0 | CopyToPrefix(in_span, Span(ctx->buf).subspan(buf_len)); |
282 | 0 | ctx->buf_len += in_span.size(); |
283 | 0 | return 1; |
284 | 1.91k | } else { |
285 | 1.91k | size_t j = block_size - buf_len; |
286 | 1.91k | CopyToPrefix(in_span.first(j), Span(ctx->buf).subspan(buf_len)); |
287 | 1.91k | if (out_span.size() < block_size) { |
288 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); |
289 | 0 | return 0; |
290 | 0 | } |
291 | 1.91k | if (!ctx->cipher->cipher_update(ctx, out_span.data(), ctx->buf, |
292 | 1.91k | block_size)) { |
293 | 0 | return 0; |
294 | 0 | } |
295 | 1.91k | in_span = in_span.subspan(j); |
296 | 1.91k | out_span = out_span.subspan(block_size); |
297 | 1.91k | } |
298 | 1.91k | } |
299 | | |
300 | 8.86k | size_t whole_blocks = in_span.size() - block_remainder(ctx, in_span.size()); |
301 | 8.86k | if (whole_blocks > 0) { |
302 | 6.24k | if (out_span.size() < whole_blocks) { |
303 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); |
304 | 0 | return 0; |
305 | 0 | } |
306 | 6.24k | if (!ctx->cipher->cipher_update(ctx, out_span.data(), in_span.data(), |
307 | 6.24k | whole_blocks)) { |
308 | 0 | return 0; |
309 | 0 | } |
310 | 6.24k | in_span = in_span.subspan(whole_blocks); |
311 | 6.24k | out_span = out_span.subspan(whole_blocks); |
312 | 6.24k | } |
313 | | |
314 | 8.86k | assert(in_span.size() < block_size); |
315 | 8.86k | CopyToPrefix(in_span, ctx->buf); |
316 | 8.86k | ctx->buf_len = in_span.size(); |
317 | | |
318 | 8.86k | *out_len = max_out_len - out_span.size(); |
319 | 8.86k | return 1; |
320 | 8.86k | } |
321 | | |
322 | | int EVP_EncryptUpdate_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, size_t *out_len, |
323 | 4.99k | size_t max_out_len, const uint8_t *in, size_t in_len) { |
324 | 4.99k | *out_len = 0; |
325 | 4.99k | return WrapWithPoison(ctx, [&] { |
326 | 4.99k | return EVP_EncryptUpdate_ex_internal(ctx, out, out_len, max_out_len, in, |
327 | 4.99k | in_len); |
328 | 4.99k | }); |
329 | 4.99k | } |
330 | | |
331 | 0 | int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { |
332 | 0 | size_t out_len_sz; |
333 | 0 | int ret = |
334 | 0 | EVP_EncryptFinal_ex2(ctx, out, &out_len_sz, ctx->cipher->block_size); |
335 | 0 | static_assert(EVP_MAX_BLOCK_LENGTH <= INT_MAX); |
336 | 0 | *out_len = static_cast<int>(out_len_sz); |
337 | 0 | return ret; |
338 | 0 | } |
339 | | |
340 | | static int EVP_EncryptFinal_ex2_internal(EVP_CIPHER_CTX *ctx, uint8_t *out, |
341 | 1.61k | size_t *out_len, size_t max_out_len) { |
342 | 1.61k | *out_len = 0; |
343 | | |
344 | 1.61k | size_t block_size = ctx->cipher->block_size; |
345 | 1.61k | assert(block_size <= sizeof(ctx->buf)); |
346 | 1.61k | if (block_size == 1) { |
347 | 0 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { |
348 | 0 | return ctx->cipher->cipher_final(ctx); |
349 | 0 | } |
350 | 0 | return 1; |
351 | 0 | } |
352 | | |
353 | 1.61k | size_t buf_len = ctx->buf_len; |
354 | 1.61k | if (ctx->flags & EVP_CIPH_NO_PADDING) { |
355 | 1.44k | if (buf_len) { |
356 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); |
357 | 0 | return 0; |
358 | 0 | } |
359 | 1.44k | return 1; |
360 | 1.44k | } |
361 | | |
362 | 174 | size_t padding = block_size - buf_len; |
363 | 1.32k | for (size_t i = buf_len; i < block_size; i++) { |
364 | 1.14k | ctx->buf[i] = padding; |
365 | 1.14k | } |
366 | | |
367 | 174 | Span<uint8_t> out_span(out, max_out_len); |
368 | 174 | if (out_span.size() < block_size) { |
369 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); |
370 | 0 | return 0; |
371 | 0 | } |
372 | 174 | if (!ctx->cipher->cipher_update(ctx, out_span.data(), ctx->buf, block_size)) { |
373 | 0 | return 0; |
374 | 0 | } |
375 | 174 | out_span = out_span.subspan(block_size); |
376 | | |
377 | 174 | *out_len = max_out_len - out_span.size(); |
378 | 174 | return 1; |
379 | 174 | } |
380 | | |
381 | | int EVP_EncryptFinal_ex2(EVP_CIPHER_CTX *ctx, uint8_t *out, size_t *out_len, |
382 | 1.61k | size_t max_out_len) { |
383 | 1.61k | *out_len = 0; |
384 | 1.61k | return WrapWithPoison(ctx, [&] { |
385 | 1.61k | if (!EVP_EncryptFinal_ex2_internal(ctx, out, out_len, max_out_len)) { |
386 | 0 | return 0; |
387 | 0 | } |
388 | 1.61k | EVP_Cipher_verify_service_indicator(ctx); |
389 | 1.61k | return 1; |
390 | 1.61k | }); |
391 | 1.61k | } |
392 | | |
393 | | int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, |
394 | 0 | const uint8_t *in, int in_len) { |
395 | 0 | *out_len = 0; |
396 | 0 | if (in_len < 0) { |
397 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_OVERFLOW); |
398 | 0 | return 0; |
399 | 0 | } |
400 | 0 | size_t in_len_sz = static_cast<size_t>(in_len); |
401 | 0 | size_t out_len_sz; |
402 | 0 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) && out == nullptr) { |
403 | 0 | if (!EVP_CipherUpdateAAD(ctx, in, in_len_sz)) { |
404 | 0 | return 0; |
405 | 0 | } |
406 | 0 | out_len_sz = in_len_sz; |
407 | 0 | } else { |
408 | | // in_len_sz is < INT_MAX which is no more than half of SIZE_MAX. |
409 | 0 | size_t max_out_len = |
410 | 0 | std::min(in_len_sz + ctx->cipher->block_size - 1, size_t{INT_MAX}); |
411 | 0 | if (!EVP_DecryptUpdate_ex(ctx, out, &out_len_sz, max_out_len, in, |
412 | 0 | in_len_sz)) { |
413 | 0 | return 0; |
414 | 0 | } |
415 | 0 | } |
416 | 0 | *out_len = static_cast<int>(out_len_sz); |
417 | 0 | return 1; |
418 | 0 | } |
419 | | |
420 | | static int EVP_DecryptUpdate_ex_internal(EVP_CIPHER_CTX *ctx, uint8_t *out, |
421 | | size_t *out_len, size_t max_out_len, |
422 | 3.85k | const uint8_t *in, size_t in_len) { |
423 | 3.85k | *out_len = 0; |
424 | | |
425 | | // Ciphers that use blocks may write up to `block_size` extra bytes. Ensure |
426 | | // the output does not overflow `*out_len`. |
427 | 3.85k | Span<const uint8_t> in_span(in, in_len); |
428 | 3.85k | size_t block_size = ctx->cipher->block_size; |
429 | | |
430 | 3.85k | if (in_span.empty()) { |
431 | 0 | return 1; |
432 | 0 | } |
433 | | |
434 | 3.85k | Span<uint8_t> out_span(out, max_out_len); |
435 | 3.85k | if (ctx->flags & EVP_CIPH_NO_PADDING) { |
436 | | // Use the shared block handling logic from encryption. |
437 | 3.84k | return EVP_EncryptUpdate_ex_internal(ctx, out_span.data(), out_len, |
438 | 3.84k | out_span.size(), in_span.data(), |
439 | 3.84k | in_span.size()); |
440 | 3.84k | } |
441 | | |
442 | 3.85k | assert(block_size <= sizeof(ctx->final)); |
443 | 14 | if (ctx->final_used) { |
444 | 0 | if (out_span.size() < block_size) { |
445 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); |
446 | 0 | return 0; |
447 | 0 | } |
448 | 0 | CopyToPrefix(Span(ctx->final).first(block_size), out_span); |
449 | 0 | ctx->final_used = 0; |
450 | 0 | out_span = out_span.subspan(block_size); |
451 | 0 | } |
452 | | |
453 | | // Use the shared block handling logic from encryption. |
454 | 14 | if (block_size > 1 && |
455 | 14 | block_remainder(ctx, ctx->buf_len + in_span.size()) == 0) { |
456 | | // Decryption would end on a block boundary. In this case, although we |
457 | | // can decrypt up to the block boundary, we cannot output the final |
458 | | // plaintext block yet. It may be the final block, with padding to |
459 | | // remove. |
460 | | // |
461 | | // Instead, output all but the final block's decryption, then decrypt the |
462 | | // final block into ctx->final, to be processed later. |
463 | | |
464 | | // NOTE: Not _really_ necessary, but let's try aligning the second |
465 | | // EVP_EncryptUpdate_ex call to a block boundary to mess with the buffer |
466 | | // less. |
467 | 14 | size_t head = in_span.size() > block_size ? in_span.size() - block_size : 0; |
468 | 14 | size_t head_out_len; |
469 | 14 | if (!EVP_EncryptUpdate_ex_internal(ctx, out_span.data(), &head_out_len, |
470 | 14 | out_span.size(), in_span.data(), head)) { |
471 | 0 | return 0; |
472 | 0 | } |
473 | 14 | in_span = in_span.subspan(head); |
474 | 14 | out_span = out_span.subspan(head_out_len); |
475 | 14 | size_t final_size; |
476 | 14 | if (!EVP_EncryptUpdate_ex_internal(ctx, ctx->final, &final_size, |
477 | 14 | sizeof(ctx->final), in_span.data(), |
478 | 14 | in_span.size())) { |
479 | 0 | return 0; |
480 | 0 | } |
481 | 14 | ctx->final_used = 1; |
482 | 14 | assert(final_size == block_size); |
483 | 14 | assert(ctx->buf_len == 0); |
484 | 14 | } else { |
485 | | // Buffer will be non-empty. |
486 | 0 | size_t written_out_len; |
487 | 0 | if (!EVP_EncryptUpdate_ex_internal(ctx, out_span.data(), &written_out_len, |
488 | 0 | out_span.size(), in_span.data(), |
489 | 0 | in_span.size())) { |
490 | 0 | return 0; |
491 | 0 | } |
492 | 0 | assert(block_size == 1 || ctx->buf_len != 0); |
493 | 0 | out_span = out_span.subspan(written_out_len); |
494 | 0 | } |
495 | | |
496 | 14 | *out_len = max_out_len - out_span.size(); |
497 | 14 | return 1; |
498 | 14 | } |
499 | | |
500 | | int EVP_DecryptUpdate_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, size_t *out_len, |
501 | 3.85k | size_t max_out_len, const uint8_t *in, size_t in_len) { |
502 | 3.85k | return WrapWithPoison(ctx, [&] { |
503 | 3.85k | return EVP_DecryptUpdate_ex_internal(ctx, out, out_len, max_out_len, in, |
504 | 3.85k | in_len); |
505 | 3.85k | }); |
506 | 3.85k | } |
507 | | |
508 | 0 | int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { |
509 | 0 | size_t out_len_sz; |
510 | 0 | int ret = |
511 | 0 | EVP_DecryptFinal_ex2(ctx, out, &out_len_sz, ctx->cipher->block_size); |
512 | 0 | static_assert(EVP_MAX_BLOCK_LENGTH <= INT_MAX); |
513 | 0 | *out_len = static_cast<int>(out_len_sz); |
514 | 0 | return ret; |
515 | 0 | } |
516 | | |
517 | | static int EVP_DecryptFinal_ex2_internal(EVP_CIPHER_CTX *ctx, |
518 | | unsigned char *out, size_t *out_len, |
519 | 14 | size_t max_out_len) { |
520 | 14 | *out_len = 0; |
521 | | |
522 | 14 | size_t block_size = ctx->cipher->block_size; |
523 | 14 | assert(block_size <= sizeof(ctx->buf)); |
524 | 14 | if (block_size == 1) { |
525 | 0 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { |
526 | 0 | return ctx->cipher->cipher_final(ctx); |
527 | 0 | } |
528 | 0 | return 1; |
529 | 0 | } |
530 | | |
531 | 14 | size_t buf_len = ctx->buf_len; |
532 | 14 | if (ctx->flags & EVP_CIPH_NO_PADDING) { |
533 | 0 | if (buf_len) { |
534 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); |
535 | 0 | return 0; |
536 | 0 | } |
537 | 0 | return 1; |
538 | 0 | } |
539 | | |
540 | 14 | if (buf_len || !ctx->final_used) { |
541 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_WRONG_FINAL_BLOCK_LENGTH); |
542 | 0 | return 0; |
543 | 0 | } |
544 | 14 | assert(block_size <= sizeof(ctx->final)); |
545 | | |
546 | | // The following assumes that the ciphertext has been authenticated. |
547 | | // Otherwise it provides a padding oracle. |
548 | 14 | size_t padding = ctx->final[block_size - 1]; |
549 | 14 | if (padding == 0 || padding > block_size) { |
550 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); |
551 | 0 | return 0; |
552 | 0 | } |
553 | | |
554 | 110 | for (size_t i = block_size - padding; i < block_size; i++) { |
555 | 96 | if (ctx->final[i] != padding) { |
556 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); |
557 | 0 | return 0; |
558 | 0 | } |
559 | 96 | } |
560 | | |
561 | 14 | Span<uint8_t> out_span(out, max_out_len); |
562 | 14 | size_t payload = ctx->cipher->block_size - padding; |
563 | 14 | if (out_span.size() < payload) { |
564 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); |
565 | 0 | return 0; |
566 | 0 | } |
567 | 14 | CopyToPrefix(Span(ctx->final).first(payload), out_span); |
568 | 14 | out_span = out_span.subspan(payload); |
569 | | |
570 | 14 | *out_len = max_out_len - out_span.size(); |
571 | 14 | return 1; |
572 | 14 | } |
573 | | |
574 | | int EVP_DecryptFinal_ex2(EVP_CIPHER_CTX *ctx, unsigned char *out, |
575 | 14 | size_t *out_len, size_t max_out_len) { |
576 | 14 | *out_len = 0; |
577 | 14 | return WrapWithPoison(ctx, [&] { |
578 | 14 | if (!EVP_DecryptFinal_ex2_internal(ctx, out, out_len, max_out_len)) { |
579 | 0 | return 0; |
580 | 0 | } |
581 | 14 | EVP_Cipher_verify_service_indicator(ctx); |
582 | 14 | return 1; |
583 | 14 | }); |
584 | 14 | } |
585 | | |
586 | | int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, |
587 | 0 | size_t in_len) { |
588 | 0 | const int kError = |
589 | 0 | (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) ? -1 : 0; |
590 | |
|
591 | 0 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) && |
592 | 0 | in_len > size_t{INT_MAX}) { |
593 | | // Can't represent the return value? That'd be bad. |
594 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_OVERFLOW); |
595 | 0 | return kError; |
596 | 0 | } |
597 | | |
598 | 0 | size_t out_len; |
599 | 0 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) && in == nullptr) { |
600 | 0 | if (!ctx->cipher->cipher_final(ctx)) { |
601 | 0 | return kError; |
602 | 0 | } |
603 | 0 | out_len = 0; |
604 | 0 | } else if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) && |
605 | 0 | out == nullptr) { |
606 | 0 | if (!ctx->cipher->update_aad(ctx, in, in_len)) { |
607 | 0 | return kError; |
608 | 0 | } |
609 | 0 | out_len = in_len; // Yes, even though no output was written! |
610 | 0 | } else { |
611 | 0 | if (!ctx->cipher->cipher_update(ctx, out, in, in_len)) { |
612 | 0 | return kError; |
613 | 0 | } |
614 | 0 | out_len = in_len; |
615 | 0 | } |
616 | | |
617 | | // `EVP_CIPH_FLAG_CUSTOM_CIPHER` never sets the FIPS indicator via |
618 | | // `EVP_Cipher` because it's complicated whether the operation has completed |
619 | | // or not. E.g. AES-GCM with a non-NULL `in` argument hasn't completed an |
620 | | // operation. Callers should use the `EVP_AEAD` API or, at least, |
621 | | // `EVP_CipherUpdate` etc. |
622 | | // |
623 | | // This call can't be pushed into `EVP_Cipher_verify_service_indicator` |
624 | | // because whether `ret` indicates success or not depends on whether |
625 | | // `EVP_CIPH_FLAG_CUSTOM_CIPHER` is set. (This unreasonable, but matches |
626 | | // OpenSSL.) |
627 | 0 | if (!(ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER)) { |
628 | 0 | EVP_Cipher_verify_service_indicator(ctx); |
629 | 0 | } |
630 | | |
631 | | // Custom ciphers return byte count; regular ciphers return boolean. |
632 | 0 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { |
633 | 0 | return static_cast<int>(out_len); |
634 | 0 | } |
635 | 0 | return 1; |
636 | 0 | } |
637 | | |
638 | | int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, |
639 | 0 | const uint8_t *in, int in_len) { |
640 | 0 | if (ctx->encrypt) { |
641 | 0 | return EVP_EncryptUpdate(ctx, out, out_len, in, in_len); |
642 | 0 | } else { |
643 | 0 | return EVP_DecryptUpdate(ctx, out, out_len, in, in_len); |
644 | 0 | } |
645 | 0 | } |
646 | | |
647 | | int EVP_CipherUpdate_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, size_t *out_len, |
648 | 0 | size_t max_out_len, const uint8_t *in, size_t in_len) { |
649 | 0 | if (ctx->encrypt) { |
650 | 0 | return EVP_EncryptUpdate_ex(ctx, out, out_len, max_out_len, in, in_len); |
651 | 0 | } else { |
652 | 0 | return EVP_DecryptUpdate_ex(ctx, out, out_len, max_out_len, in, in_len); |
653 | 0 | } |
654 | 0 | } |
655 | | |
656 | 0 | int EVP_CipherUpdateAAD(EVP_CIPHER_CTX *ctx, const uint8_t *in, size_t in_len) { |
657 | 0 | return WrapWithPoison(ctx, [&] { |
658 | 0 | if (!(ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER)) { |
659 | 0 | OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
660 | 0 | return 0; |
661 | 0 | } |
662 | 0 | return ctx->cipher->update_aad(ctx, in, in_len); |
663 | 0 | }); |
664 | 0 | } |
665 | | |
666 | 0 | int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { |
667 | 0 | if (ctx->encrypt) { |
668 | 0 | return EVP_EncryptFinal_ex(ctx, out, out_len); |
669 | 0 | } else { |
670 | 0 | return EVP_DecryptFinal_ex(ctx, out, out_len); |
671 | 0 | } |
672 | 0 | } |
673 | | |
674 | | int EVP_CipherFinal_ex2(EVP_CIPHER_CTX *ctx, uint8_t *out, size_t *out_len, |
675 | 0 | size_t max_out_len) { |
676 | 0 | if (ctx->encrypt) { |
677 | 0 | return EVP_EncryptFinal_ex2(ctx, out, out_len, max_out_len); |
678 | 0 | } else { |
679 | 0 | return EVP_DecryptFinal_ex2(ctx, out, out_len, max_out_len); |
680 | 0 | } |
681 | 0 | } |
682 | | |
683 | | size_t EVP_CIPHER_CTX_max_next_update(const EVP_CIPHER_CTX *ctx, |
684 | 0 | size_t in_len) { |
685 | 0 | if (in_len == 0) { |
686 | 0 | return 0; |
687 | 0 | } |
688 | | |
689 | 0 | size_t block_size = ctx->cipher->block_size; |
690 | | // |block_size| must be a power of 2. |
691 | 0 | assert(block_size != 0 && (block_size & (block_size - 1)) == 0); |
692 | 0 | size_t buf_len = ctx->buf_len; |
693 | | |
694 | | // Any buffered input is combined with |in_len|, then we round down to a |
695 | | // multiple of the block size. |
696 | 0 | size_t ret = (in_len + buf_len) & ~(block_size - 1); |
697 | 0 | if (!ctx->encrypt && block_size > 1 && !(ctx->flags & EVP_CIPH_NO_PADDING)) { |
698 | 0 | if (ctx->final_used) { |
699 | | // There was a buffered decrypted block. Now that it is known to not have |
700 | | // padding, DecryptUpdate will output it. |
701 | 0 | ret += block_size; |
702 | 0 | } |
703 | 0 | if (block_remainder(ctx, in_len + buf_len) == 0) { |
704 | | // This call ends on a block boundary. The last block will be buffered in |
705 | | // |ctx->final| until it is known to have padding. |
706 | 0 | assert(ret >= block_size); |
707 | 0 | ret -= block_size; |
708 | 0 | } |
709 | 0 | } |
710 | 0 | return ret; |
711 | 0 | } |
712 | | |
713 | 0 | size_t EVP_CIPHER_CTX_max_final(const EVP_CIPHER_CTX *ctx) { |
714 | 0 | size_t block_size = ctx->cipher->block_size; |
715 | 0 | if (block_size == 1 || (ctx->flags & EVP_CIPH_NO_PADDING)) { |
716 | 0 | return 0; |
717 | 0 | } |
718 | 0 | if (ctx->encrypt) { |
719 | 0 | return block_size; |
720 | 0 | } else { |
721 | | // At least one byte will be removed when processing padding. |
722 | 0 | return block_size - 1; |
723 | 0 | } |
724 | 0 | } |
725 | | |
726 | 0 | const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) { |
727 | 0 | return ctx->cipher; |
728 | 0 | } |
729 | | |
730 | 0 | int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) { return ctx->cipher->nid; } |
731 | | |
732 | 0 | int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) { |
733 | 0 | return ctx->encrypt; |
734 | 0 | } |
735 | | |
736 | 13.9k | unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) { |
737 | 13.9k | return ctx->cipher->block_size; |
738 | 13.9k | } |
739 | | |
740 | 12 | unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) { |
741 | 12 | return ctx->key_len; |
742 | 12 | } |
743 | | |
744 | 79.2k | unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) { |
745 | 79.2k | if (EVP_CIPHER_mode(ctx->cipher) == EVP_CIPH_GCM_MODE) { |
746 | 0 | int length; |
747 | 0 | int res = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, 0, |
748 | 0 | &length); |
749 | | // EVP_CIPHER_CTX_ctrl returning an error should be impossible under this |
750 | | // circumstance. If it somehow did, fallback to the static cipher iv_len. |
751 | 0 | if (res == 1) { |
752 | 0 | return length; |
753 | 0 | } |
754 | 0 | } |
755 | 79.2k | return ctx->cipher->iv_len; |
756 | 79.2k | } |
757 | | |
758 | 0 | void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) { |
759 | 0 | return ctx->app_data; |
760 | 0 | } |
761 | | |
762 | 0 | void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) { |
763 | 0 | ctx->app_data = data; |
764 | 0 | } |
765 | | |
766 | 35.8k | uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) { |
767 | 35.8k | return ctx->cipher->flags & ~EVP_CIPH_MODE_MASK; |
768 | 35.8k | } |
769 | | |
770 | 49.7k | uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx) { |
771 | 49.7k | return ctx->cipher->flags & EVP_CIPH_MODE_MASK; |
772 | 49.7k | } |
773 | | |
774 | 6 | int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, int arg, void *ptr) { |
775 | 6 | int ret; |
776 | 6 | if (!ctx->cipher) { |
777 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_CIPHER_SET); |
778 | 0 | return 0; |
779 | 0 | } |
780 | | |
781 | 6 | if (!ctx->cipher->ctrl) { |
782 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_NOT_IMPLEMENTED); |
783 | 0 | return 0; |
784 | 0 | } |
785 | | |
786 | 6 | ret = ctx->cipher->ctrl(ctx, command, arg, ptr); |
787 | 6 | if (ret == -1) { |
788 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED); |
789 | 0 | return 0; |
790 | 0 | } |
791 | | |
792 | 6 | return ret; |
793 | 6 | } |
794 | | |
795 | 32.3k | int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) { |
796 | 32.3k | if (pad) { |
797 | 0 | ctx->flags &= ~EVP_CIPH_NO_PADDING; |
798 | 32.3k | } else { |
799 | 32.3k | ctx->flags |= EVP_CIPH_NO_PADDING; |
800 | 32.3k | } |
801 | 32.3k | return 1; |
802 | 32.3k | } |
803 | | |
804 | 0 | int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) { |
805 | 0 | if (c->key_len == key_len) { |
806 | 0 | return 1; |
807 | 0 | } |
808 | | |
809 | 0 | if (key_len == 0 || !(c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) { |
810 | 0 | OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_KEY_LENGTH); |
811 | 0 | return 0; |
812 | 0 | } |
813 | | |
814 | 0 | c->key_len = key_len; |
815 | 0 | return 1; |
816 | 0 | } |
817 | | |
818 | 0 | int EVP_CIPHER_nid(const EVP_CIPHER *cipher) { return cipher->nid; } |
819 | | |
820 | 0 | unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher) { |
821 | 0 | return cipher->block_size; |
822 | 0 | } |
823 | | |
824 | 32.3k | unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher) { |
825 | 32.3k | return cipher->key_len; |
826 | 32.3k | } |
827 | | |
828 | 2.74k | unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) { |
829 | 2.74k | return cipher->iv_len; |
830 | 2.74k | } |
831 | | |
832 | 0 | uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher) { |
833 | 0 | return cipher->flags & ~EVP_CIPH_MODE_MASK; |
834 | 0 | } |
835 | | |
836 | 79.2k | uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher) { |
837 | 79.2k | return cipher->flags & EVP_CIPH_MODE_MASK; |
838 | 79.2k | } |
839 | | |
840 | | int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
841 | 0 | const uint8_t *key, const uint8_t *iv, int enc) { |
842 | 0 | if (cipher) { |
843 | 0 | EVP_CIPHER_CTX_init(ctx); |
844 | 0 | } |
845 | 0 | return EVP_CipherInit_ex(ctx, cipher, nullptr, key, iv, enc); |
846 | 0 | } |
847 | | |
848 | | int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
849 | 0 | const uint8_t *key, const uint8_t *iv) { |
850 | 0 | return EVP_CipherInit(ctx, cipher, key, iv, 1); |
851 | 0 | } |
852 | | |
853 | | int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
854 | 0 | const uint8_t *key, const uint8_t *iv) { |
855 | 0 | return EVP_CipherInit(ctx, cipher, key, iv, 0); |
856 | 0 | } |
857 | | |
858 | 0 | int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { |
859 | 0 | return EVP_CipherFinal_ex(ctx, out, out_len); |
860 | 0 | } |
861 | | |
862 | 0 | int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { |
863 | 0 | return EVP_EncryptFinal_ex(ctx, out, out_len); |
864 | 0 | } |
865 | | |
866 | 0 | int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { |
867 | 0 | return EVP_DecryptFinal_ex(ctx, out, out_len); |
868 | 0 | } |
869 | | |
870 | 0 | int EVP_add_cipher_alias(const char *a, const char *b) { return 1; } |
871 | | |
872 | 0 | void EVP_CIPHER_CTX_set_flags(const EVP_CIPHER_CTX *ctx, uint32_t flags) {} |