]>
Commit | Line | Data |
---|---|---|
62867571 | 1 | /* |
28428130 | 2 | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. |
d02b48c6 | 3 | * |
4a8b0c55 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
62867571 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
11 | #include <errno.h> | |
b39fc560 | 12 | #include "internal/cryptlib.h" |
ec577822 BM |
13 | #include <openssl/buffer.h> |
14 | #include <openssl/evp.h> | |
a146ae55 | 15 | #include "internal/bio.h" |
d02b48c6 | 16 | |
0e1c0612 UM |
17 | static int enc_write(BIO *h, const char *buf, int num); |
18 | static int enc_read(BIO *h, char *buf, int size); | |
0e1c0612 | 19 | static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); |
d02b48c6 RE |
20 | static int enc_new(BIO *h); |
21 | static int enc_free(BIO *data); | |
fce78bd4 | 22 | static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); |
0f113f3e | 23 | #define ENC_BLOCK_SIZE (1024*4) |
c1a7dcbe AP |
24 | #define ENC_MIN_CHUNK (256) |
25 | #define BUF_OFFSET (ENC_MIN_CHUNK + EVP_MAX_BLOCK_LENGTH) | |
0f113f3e MC |
26 | |
27 | typedef struct enc_struct { | |
28 | int buf_len; | |
29 | int buf_off; | |
30 | int cont; /* <= 0 when finished */ | |
31 | int finished; | |
32 | int ok; /* bad decrypt */ | |
846ec07d | 33 | EVP_CIPHER_CTX *cipher; |
c1a7dcbe | 34 | unsigned char *read_start, *read_end; |
0f113f3e MC |
35 | /* |
36 | * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return | |
37 | * up to a block more data than is presented to it | |
38 | */ | |
c1a7dcbe | 39 | unsigned char buf[BUF_OFFSET + ENC_BLOCK_SIZE]; |
0f113f3e MC |
40 | } BIO_ENC_CTX; |
41 | ||
04f6b0fd | 42 | static const BIO_METHOD methods_enc = { |
27ab9195 DB |
43 | BIO_TYPE_CIPHER, |
44 | "cipher", | |
3befffa3 MC |
45 | /* TODO: Convert to new style write function */ |
46 | bwrite_conv, | |
0f113f3e | 47 | enc_write, |
d07aee2c MC |
48 | /* TODO: Convert to new style read function */ |
49 | bread_conv, | |
0f113f3e MC |
50 | enc_read, |
51 | NULL, /* enc_puts, */ | |
52 | NULL, /* enc_gets, */ | |
53 | enc_ctrl, | |
54 | enc_new, | |
55 | enc_free, | |
56 | enc_callback_ctrl, | |
57 | }; | |
d02b48c6 | 58 | |
04f6b0fd | 59 | const BIO_METHOD *BIO_f_cipher(void) |
0f113f3e | 60 | { |
26a7d938 | 61 | return &methods_enc; |
0f113f3e | 62 | } |
d02b48c6 | 63 | |
6b691a5c | 64 | static int enc_new(BIO *bi) |
0f113f3e MC |
65 | { |
66 | BIO_ENC_CTX *ctx; | |
67 | ||
cdb10bae RS |
68 | if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { |
69 | EVPerr(EVP_F_ENC_NEW, ERR_R_MALLOC_FAILURE); | |
846ec07d | 70 | return 0; |
cdb10bae | 71 | } |
0f113f3e | 72 | |
846ec07d RL |
73 | ctx->cipher = EVP_CIPHER_CTX_new(); |
74 | if (ctx->cipher == NULL) { | |
75 | OPENSSL_free(ctx); | |
76 | return 0; | |
77 | } | |
0f113f3e | 78 | ctx->cont = 1; |
0f113f3e | 79 | ctx->ok = 1; |
c1a7dcbe | 80 | ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); |
a146ae55 MC |
81 | BIO_set_data(bi, ctx); |
82 | BIO_set_init(bi, 1); | |
83 | ||
846ec07d | 84 | return 1; |
0f113f3e | 85 | } |
d02b48c6 | 86 | |
6b691a5c | 87 | static int enc_free(BIO *a) |
0f113f3e MC |
88 | { |
89 | BIO_ENC_CTX *b; | |
90 | ||
91 | if (a == NULL) | |
a146ae55 MC |
92 | return 0; |
93 | ||
94 | b = BIO_get_data(a); | |
95 | if (b == NULL) | |
96 | return 0; | |
97 | ||
846ec07d | 98 | EVP_CIPHER_CTX_free(b->cipher); |
a146ae55 MC |
99 | OPENSSL_clear_free(b, sizeof(BIO_ENC_CTX)); |
100 | BIO_set_data(a, NULL); | |
101 | BIO_set_init(a, 0); | |
102 | ||
103 | return 1; | |
0f113f3e MC |
104 | } |
105 | ||
6b691a5c | 106 | static int enc_read(BIO *b, char *out, int outl) |
0f113f3e | 107 | { |
c1a7dcbe | 108 | int ret = 0, i, blocksize; |
0f113f3e | 109 | BIO_ENC_CTX *ctx; |
a146ae55 | 110 | BIO *next; |
0f113f3e MC |
111 | |
112 | if (out == NULL) | |
26a7d938 | 113 | return 0; |
a146ae55 | 114 | ctx = BIO_get_data(b); |
0f113f3e | 115 | |
a146ae55 MC |
116 | next = BIO_next(b); |
117 | if ((ctx == NULL) || (next == NULL)) | |
118 | return 0; | |
0f113f3e MC |
119 | |
120 | /* First check if there are bytes decoded/encoded */ | |
121 | if (ctx->buf_len > 0) { | |
122 | i = ctx->buf_len - ctx->buf_off; | |
123 | if (i > outl) | |
124 | i = outl; | |
125 | memcpy(out, &(ctx->buf[ctx->buf_off]), i); | |
126 | ret = i; | |
127 | out += i; | |
128 | outl -= i; | |
129 | ctx->buf_off += i; | |
130 | if (ctx->buf_len == ctx->buf_off) { | |
131 | ctx->buf_len = 0; | |
132 | ctx->buf_off = 0; | |
133 | } | |
134 | } | |
135 | ||
c1a7dcbe AP |
136 | blocksize = EVP_CIPHER_CTX_block_size(ctx->cipher); |
137 | if (blocksize == 1) | |
138 | blocksize = 0; | |
139 | ||
0f113f3e MC |
140 | /* |
141 | * At this point, we have room of outl bytes and an empty buffer, so we | |
142 | * should read in some more. | |
143 | */ | |
144 | ||
145 | while (outl > 0) { | |
146 | if (ctx->cont <= 0) | |
147 | break; | |
148 | ||
c1a7dcbe AP |
149 | if (ctx->read_start == ctx->read_end) { /* time to read more data */ |
150 | ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); | |
9e421962 AP |
151 | i = BIO_read(next, ctx->read_start, ENC_BLOCK_SIZE); |
152 | if (i > 0) | |
153 | ctx->read_end += i; | |
154 | } else { | |
155 | i = ctx->read_end - ctx->read_start; | |
abdb460d | 156 | } |
0f113f3e MC |
157 | |
158 | if (i <= 0) { | |
159 | /* Should be continue next time we are called? */ | |
a146ae55 | 160 | if (!BIO_should_retry(next)) { |
0f113f3e | 161 | ctx->cont = i; |
846ec07d | 162 | i = EVP_CipherFinal_ex(ctx->cipher, |
abdb460d | 163 | ctx->buf, &(ctx->buf_len)); |
0f113f3e MC |
164 | ctx->ok = i; |
165 | ctx->buf_off = 0; | |
166 | } else { | |
167 | ret = (ret == 0) ? i : ret; | |
168 | break; | |
169 | } | |
170 | } else { | |
c1a7dcbe AP |
171 | if (outl > ENC_MIN_CHUNK) { |
172 | /* | |
173 | * Depending on flags block cipher decrypt can write | |
174 | * one extra block and then back off, i.e. output buffer | |
175 | * has to accommodate extra block... | |
176 | */ | |
177 | int j = outl - blocksize, buf_len; | |
178 | ||
179 | if (!EVP_CipherUpdate(ctx->cipher, | |
180 | (unsigned char *)out, &buf_len, | |
181 | ctx->read_start, i > j ? j : i)) { | |
182 | BIO_clear_retry_flags(b); | |
183 | return 0; | |
184 | } | |
185 | ret += buf_len; | |
186 | out += buf_len; | |
187 | outl -= buf_len; | |
188 | ||
189 | if ((i -= j) <= 0) { | |
190 | ctx->read_start = ctx->read_end; | |
191 | continue; | |
192 | } | |
193 | ctx->read_start += j; | |
194 | } | |
195 | if (i > ENC_MIN_CHUNK) | |
196 | i = ENC_MIN_CHUNK; | |
846ec07d | 197 | if (!EVP_CipherUpdate(ctx->cipher, |
abdb460d | 198 | ctx->buf, &ctx->buf_len, |
c1a7dcbe | 199 | ctx->read_start, i)) { |
0f113f3e | 200 | BIO_clear_retry_flags(b); |
ee6ce5cc | 201 | ctx->ok = 0; |
0f113f3e MC |
202 | return 0; |
203 | } | |
c1a7dcbe | 204 | ctx->read_start += i; |
0f113f3e MC |
205 | ctx->cont = 1; |
206 | /* | |
207 | * Note: it is possible for EVP_CipherUpdate to decrypt zero | |
208 | * bytes because this is or looks like the final block: if this | |
209 | * happens we should retry and either read more data or decrypt | |
210 | * the final block | |
211 | */ | |
212 | if (ctx->buf_len == 0) | |
213 | continue; | |
214 | } | |
215 | ||
216 | if (ctx->buf_len <= outl) | |
217 | i = ctx->buf_len; | |
218 | else | |
219 | i = outl; | |
220 | if (i <= 0) | |
221 | break; | |
222 | memcpy(out, ctx->buf, i); | |
223 | ret += i; | |
224 | ctx->buf_off = i; | |
225 | outl -= i; | |
226 | out += i; | |
227 | } | |
228 | ||
229 | BIO_clear_retry_flags(b); | |
230 | BIO_copy_next_retry(b); | |
231 | return ((ret == 0) ? ctx->cont : ret); | |
232 | } | |
d02b48c6 | 233 | |
0e1c0612 | 234 | static int enc_write(BIO *b, const char *in, int inl) |
0f113f3e MC |
235 | { |
236 | int ret = 0, n, i; | |
237 | BIO_ENC_CTX *ctx; | |
a146ae55 MC |
238 | BIO *next; |
239 | ||
240 | ctx = BIO_get_data(b); | |
241 | next = BIO_next(b); | |
242 | if ((ctx == NULL) || (next == NULL)) | |
243 | return 0; | |
0f113f3e | 244 | |
0f113f3e MC |
245 | ret = inl; |
246 | ||
247 | BIO_clear_retry_flags(b); | |
248 | n = ctx->buf_len - ctx->buf_off; | |
249 | while (n > 0) { | |
a146ae55 | 250 | i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); |
0f113f3e MC |
251 | if (i <= 0) { |
252 | BIO_copy_next_retry(b); | |
26a7d938 | 253 | return i; |
0f113f3e MC |
254 | } |
255 | ctx->buf_off += i; | |
256 | n -= i; | |
257 | } | |
258 | /* at this point all pending data has been written */ | |
259 | ||
260 | if ((in == NULL) || (inl <= 0)) | |
26a7d938 | 261 | return 0; |
0f113f3e MC |
262 | |
263 | ctx->buf_off = 0; | |
264 | while (inl > 0) { | |
265 | n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; | |
846ec07d | 266 | if (!EVP_CipherUpdate(ctx->cipher, |
abdb460d AP |
267 | ctx->buf, &ctx->buf_len, |
268 | (const unsigned char *)in, n)) { | |
0f113f3e | 269 | BIO_clear_retry_flags(b); |
976ef6ad | 270 | ctx->ok = 0; |
0f113f3e MC |
271 | return 0; |
272 | } | |
273 | inl -= n; | |
274 | in += n; | |
275 | ||
276 | ctx->buf_off = 0; | |
277 | n = ctx->buf_len; | |
278 | while (n > 0) { | |
a146ae55 | 279 | i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); |
0f113f3e MC |
280 | if (i <= 0) { |
281 | BIO_copy_next_retry(b); | |
282 | return (ret == inl) ? i : ret - inl; | |
283 | } | |
284 | n -= i; | |
285 | ctx->buf_off += i; | |
286 | } | |
287 | ctx->buf_len = 0; | |
288 | ctx->buf_off = 0; | |
289 | } | |
290 | BIO_copy_next_retry(b); | |
26a7d938 | 291 | return ret; |
0f113f3e | 292 | } |
d02b48c6 | 293 | |
0e1c0612 | 294 | static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) |
0f113f3e MC |
295 | { |
296 | BIO *dbio; | |
297 | BIO_ENC_CTX *ctx, *dctx; | |
298 | long ret = 1; | |
299 | int i; | |
300 | EVP_CIPHER_CTX **c_ctx; | |
a146ae55 | 301 | BIO *next; |
0f113f3e | 302 | |
a146ae55 MC |
303 | ctx = BIO_get_data(b); |
304 | next = BIO_next(b); | |
305 | if (ctx == NULL) | |
306 | return 0; | |
0f113f3e MC |
307 | |
308 | switch (cmd) { | |
309 | case BIO_CTRL_RESET: | |
310 | ctx->ok = 1; | |
311 | ctx->finished = 0; | |
846ec07d RL |
312 | if (!EVP_CipherInit_ex(ctx->cipher, NULL, NULL, NULL, NULL, |
313 | EVP_CIPHER_CTX_encrypting(ctx->cipher))) | |
0f113f3e | 314 | return 0; |
a146ae55 | 315 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
316 | break; |
317 | case BIO_CTRL_EOF: /* More to read */ | |
318 | if (ctx->cont <= 0) | |
319 | ret = 1; | |
320 | else | |
a146ae55 | 321 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
322 | break; |
323 | case BIO_CTRL_WPENDING: | |
324 | ret = ctx->buf_len - ctx->buf_off; | |
325 | if (ret <= 0) | |
a146ae55 | 326 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
327 | break; |
328 | case BIO_CTRL_PENDING: /* More to read in buffer */ | |
329 | ret = ctx->buf_len - ctx->buf_off; | |
330 | if (ret <= 0) | |
a146ae55 | 331 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
332 | break; |
333 | case BIO_CTRL_FLUSH: | |
334 | /* do a final write */ | |
335 | again: | |
336 | while (ctx->buf_len != ctx->buf_off) { | |
337 | i = enc_write(b, NULL, 0); | |
338 | if (i < 0) | |
339 | return i; | |
340 | } | |
341 | ||
342 | if (!ctx->finished) { | |
343 | ctx->finished = 1; | |
344 | ctx->buf_off = 0; | |
846ec07d | 345 | ret = EVP_CipherFinal_ex(ctx->cipher, |
0f113f3e MC |
346 | (unsigned char *)ctx->buf, |
347 | &(ctx->buf_len)); | |
348 | ctx->ok = (int)ret; | |
349 | if (ret <= 0) | |
350 | break; | |
351 | ||
352 | /* push out the bytes */ | |
353 | goto again; | |
354 | } | |
355 | ||
356 | /* Finally flush the underlying BIO */ | |
a146ae55 | 357 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
358 | break; |
359 | case BIO_C_GET_CIPHER_STATUS: | |
360 | ret = (long)ctx->ok; | |
361 | break; | |
362 | case BIO_C_DO_STATE_MACHINE: | |
363 | BIO_clear_retry_flags(b); | |
a146ae55 | 364 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
365 | BIO_copy_next_retry(b); |
366 | break; | |
367 | case BIO_C_GET_CIPHER_CTX: | |
368 | c_ctx = (EVP_CIPHER_CTX **)ptr; | |
846ec07d | 369 | *c_ctx = ctx->cipher; |
a146ae55 | 370 | BIO_set_init(b, 1); |
0f113f3e MC |
371 | break; |
372 | case BIO_CTRL_DUP: | |
373 | dbio = (BIO *)ptr; | |
a146ae55 | 374 | dctx = BIO_get_data(dbio); |
846ec07d RL |
375 | dctx->cipher = EVP_CIPHER_CTX_new(); |
376 | if (dctx->cipher == NULL) | |
377 | return 0; | |
378 | ret = EVP_CIPHER_CTX_copy(dctx->cipher, ctx->cipher); | |
0f113f3e | 379 | if (ret) |
a146ae55 | 380 | BIO_set_init(dbio, 1); |
0f113f3e MC |
381 | break; |
382 | default: | |
a146ae55 | 383 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
384 | break; |
385 | } | |
26a7d938 | 386 | return ret; |
0f113f3e | 387 | } |
d02b48c6 | 388 | |
fce78bd4 | 389 | static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) |
0f113f3e | 390 | { |
a146ae55 | 391 | BIO *next = BIO_next(b); |
0f113f3e | 392 | |
a146ae55 | 393 | if (next == NULL) |
26a7d938 | 394 | return 0; |
1f2235ea D |
395 | |
396 | return BIO_callback_ctrl(next, cmd, fp); | |
0f113f3e | 397 | } |
d3442bc7 | 398 | |
b6dcdbfc | 399 | int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, |
0f113f3e MC |
400 | const unsigned char *i, int e) |
401 | { | |
402 | BIO_ENC_CTX *ctx; | |
a146ae55 | 403 | long (*callback) (struct bio_st *, int, const char *, int, long, long); |
0f113f3e | 404 | |
a146ae55 MC |
405 | ctx = BIO_get_data(b); |
406 | if (ctx == NULL) | |
0f113f3e MC |
407 | return 0; |
408 | ||
a146ae55 MC |
409 | callback = BIO_get_callback(b); |
410 | ||
411 | if ((callback != NULL) && | |
412 | (callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, | |
413 | 0L) <= 0)) | |
0f113f3e MC |
414 | return 0; |
415 | ||
a146ae55 MC |
416 | BIO_set_init(b, 1); |
417 | ||
846ec07d | 418 | if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e)) |
0f113f3e MC |
419 | return 0; |
420 | ||
a146ae55 MC |
421 | if (callback != NULL) |
422 | return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); | |
0f113f3e MC |
423 | return 1; |
424 | } |