]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/evp/bio_enc.c
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include "internal/cryptlib.h"
13 #include <openssl/buffer.h>
14 #include <openssl/evp.h>
15 #include "internal/bio.h"
17 static int enc_write(BIO
*h
, const char *buf
, int num
);
18 static int enc_read(BIO
*h
, char *buf
, int size
);
20 * static int enc_puts(BIO *h, const char *str);
23 * static int enc_gets(BIO *h, char *str, int size);
25 static long enc_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
26 static int enc_new(BIO
*h
);
27 static int enc_free(BIO
*data
);
28 static long enc_callback_ctrl(BIO
*h
, int cmd
, bio_info_cb
*fps
);
29 #define ENC_BLOCK_SIZE (1024*4)
30 #define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2)
32 typedef struct enc_struct
{
35 int cont
; /* <= 0 when finished */
37 int ok
; /* bad decrypt */
38 EVP_CIPHER_CTX
*cipher
;
40 * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return
41 * up to a block more data than is presented to it
43 char buf
[ENC_BLOCK_SIZE
+ BUF_OFFSET
+ 2];
46 static const BIO_METHOD methods_enc
= {
47 BIO_TYPE_CIPHER
, "cipher",
58 const BIO_METHOD
*BIO_f_cipher(void)
60 return (&methods_enc
);
63 static int enc_new(BIO
*bi
)
67 ctx
= OPENSSL_zalloc(sizeof(*ctx
));
71 ctx
->cipher
= EVP_CIPHER_CTX_new();
72 if (ctx
->cipher
== NULL
) {
78 BIO_set_data(bi
, ctx
);
84 static int enc_free(BIO
*a
)
95 EVP_CIPHER_CTX_free(b
->cipher
);
96 OPENSSL_clear_free(b
, sizeof(BIO_ENC_CTX
));
97 BIO_set_data(a
, NULL
);
103 static int enc_read(BIO
*b
, char *out
, int outl
)
111 ctx
= BIO_get_data(b
);
114 if ((ctx
== NULL
) || (next
== NULL
))
117 /* First check if there are bytes decoded/encoded */
118 if (ctx
->buf_len
> 0) {
119 i
= ctx
->buf_len
- ctx
->buf_off
;
122 memcpy(out
, &(ctx
->buf
[ctx
->buf_off
]), i
);
127 if (ctx
->buf_len
== ctx
->buf_off
) {
134 * At this point, we have room of outl bytes and an empty buffer, so we
135 * should read in some more.
143 * read in at IV offset, read the EVP_Cipher documentation about why
145 i
= BIO_read(next
, &(ctx
->buf
[BUF_OFFSET
]), ENC_BLOCK_SIZE
);
148 /* Should be continue next time we are called? */
149 if (!BIO_should_retry(next
)) {
151 i
= EVP_CipherFinal_ex(ctx
->cipher
,
152 (unsigned char *)ctx
->buf
,
157 ret
= (ret
== 0) ? i
: ret
;
161 if (!EVP_CipherUpdate(ctx
->cipher
,
162 (unsigned char *)ctx
->buf
, &ctx
->buf_len
,
163 (unsigned char *)&(ctx
->buf
[BUF_OFFSET
]),
165 BIO_clear_retry_flags(b
);
170 * Note: it is possible for EVP_CipherUpdate to decrypt zero
171 * bytes because this is or looks like the final block: if this
172 * happens we should retry and either read more data or decrypt
175 if (ctx
->buf_len
== 0)
179 if (ctx
->buf_len
<= outl
)
185 memcpy(out
, ctx
->buf
, i
);
192 BIO_clear_retry_flags(b
);
193 BIO_copy_next_retry(b
);
194 return ((ret
== 0) ? ctx
->cont
: ret
);
197 static int enc_write(BIO
*b
, const char *in
, int inl
)
203 ctx
= BIO_get_data(b
);
205 if ((ctx
== NULL
) || (next
== NULL
))
210 BIO_clear_retry_flags(b
);
211 n
= ctx
->buf_len
- ctx
->buf_off
;
213 i
= BIO_write(next
, &(ctx
->buf
[ctx
->buf_off
]), n
);
215 BIO_copy_next_retry(b
);
221 /* at this point all pending data has been written */
223 if ((in
== NULL
) || (inl
<= 0))
228 n
= (inl
> ENC_BLOCK_SIZE
) ? ENC_BLOCK_SIZE
: inl
;
229 if (!EVP_CipherUpdate(ctx
->cipher
,
230 (unsigned char *)ctx
->buf
, &ctx
->buf_len
,
231 (unsigned char *)in
, n
)) {
232 BIO_clear_retry_flags(b
);
241 i
= BIO_write(next
, &(ctx
->buf
[ctx
->buf_off
]), n
);
243 BIO_copy_next_retry(b
);
244 return (ret
== inl
) ? i
: ret
- inl
;
252 BIO_copy_next_retry(b
);
256 static long enc_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
259 BIO_ENC_CTX
*ctx
, *dctx
;
262 EVP_CIPHER_CTX
**c_ctx
;
265 ctx
= BIO_get_data(b
);
274 if (!EVP_CipherInit_ex(ctx
->cipher
, NULL
, NULL
, NULL
, NULL
,
275 EVP_CIPHER_CTX_encrypting(ctx
->cipher
)))
277 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
279 case BIO_CTRL_EOF
: /* More to read */
283 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
285 case BIO_CTRL_WPENDING
:
286 ret
= ctx
->buf_len
- ctx
->buf_off
;
288 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
290 case BIO_CTRL_PENDING
: /* More to read in buffer */
291 ret
= ctx
->buf_len
- ctx
->buf_off
;
293 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
296 /* do a final write */
298 while (ctx
->buf_len
!= ctx
->buf_off
) {
299 i
= enc_write(b
, NULL
, 0);
304 if (!ctx
->finished
) {
307 ret
= EVP_CipherFinal_ex(ctx
->cipher
,
308 (unsigned char *)ctx
->buf
,
314 /* push out the bytes */
318 /* Finally flush the underlying BIO */
319 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
321 case BIO_C_GET_CIPHER_STATUS
:
324 case BIO_C_DO_STATE_MACHINE
:
325 BIO_clear_retry_flags(b
);
326 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
327 BIO_copy_next_retry(b
);
329 case BIO_C_GET_CIPHER_CTX
:
330 c_ctx
= (EVP_CIPHER_CTX
**)ptr
;
331 *c_ctx
= ctx
->cipher
;
336 dctx
= BIO_get_data(dbio
);
337 dctx
->cipher
= EVP_CIPHER_CTX_new();
338 if (dctx
->cipher
== NULL
)
340 ret
= EVP_CIPHER_CTX_copy(dctx
->cipher
, ctx
->cipher
);
342 BIO_set_init(dbio
, 1);
345 ret
= BIO_ctrl(next
, cmd
, num
, ptr
);
351 static long enc_callback_ctrl(BIO
*b
, int cmd
, bio_info_cb
*fp
)
354 BIO
*next
= BIO_next(b
);
360 ret
= BIO_callback_ctrl(next
, cmd
, fp
);
367 void BIO_set_cipher_ctx(b,c)
371 if (b == NULL) return;
373 if ((b->callback != NULL) &&
374 (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0))
378 ctx=(BIO_ENC_CTX *)b->ptr;
379 memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX));
381 if (b->callback != NULL)
382 b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L);
386 int BIO_set_cipher(BIO
*b
, const EVP_CIPHER
*c
, const unsigned char *k
,
387 const unsigned char *i
, int e
)
390 long (*callback
) (struct bio_st
*, int, const char *, int, long, long);
392 ctx
= BIO_get_data(b
);
396 callback
= BIO_get_callback(b
);
398 if ((callback
!= NULL
) &&
399 (callback(b
, BIO_CB_CTRL
, (const char *)c
, BIO_CTRL_SET
, e
,
405 if (!EVP_CipherInit_ex(ctx
->cipher
, c
, NULL
, k
, i
, e
))
408 if (callback
!= NULL
)
409 return callback(b
, BIO_CB_CTRL
, (const char *)c
, BIO_CTRL_SET
, e
, 1L);