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