hcrypto: Fix EVP_CipherUpdate() bugs
This commit is contained in:

committed by
Jeffrey Altman

parent
47e6c68de8
commit
11846fcabb
@@ -857,37 +857,34 @@ EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, void *out, int *outlen,
|
|||||||
|
|
||||||
*outlen = 0;
|
*outlen = 0;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* If there in no spare bytes in the left from last Update and the
|
* If there in no bytes left over from the last Update and the
|
||||||
* input length is on the block boundery, the EVP_CipherUpdate()
|
* input length is on a block boundary, then we can take a
|
||||||
* function can take a shortcut (and preformance gain) and
|
* shortcut (and preformance gain) and directly encrypt the
|
||||||
* directly encrypt the data, otherwise we hav to fix it up and
|
* data.
|
||||||
* store extra it the EVP_CIPHER_CTX.
|
|
||||||
*/
|
*/
|
||||||
if (ctx->buf_len == 0 && (inlen & ctx->block_mask) == 0) {
|
if (ctx->buf_len == 0 && inlen && (inlen & ctx->block_mask) == 0) {
|
||||||
ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
|
ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
*outlen = inlen;
|
*outlen = inlen;
|
||||||
else
|
else
|
||||||
*outlen = 0;
|
*outlen = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
blocksize = EVP_CIPHER_CTX_block_size(ctx);
|
||||||
left = blocksize - ctx->buf_len;
|
left = blocksize - ctx->buf_len;
|
||||||
assert(left > 0);
|
assert(left > 0);
|
||||||
|
|
||||||
if (ctx->buf_len) {
|
if (ctx->buf_len) {
|
||||||
|
/* If we can't fill one block in the buffer, save the input there */
|
||||||
/* if total buffer is smaller then input, store locally */
|
|
||||||
if (inlen < left) {
|
if (inlen < left) {
|
||||||
memcpy(ctx->buf + ctx->buf_len, in, inlen);
|
memcpy(ctx->buf + ctx->buf_len, in, inlen);
|
||||||
ctx->buf_len += inlen;
|
ctx->buf_len += inlen;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill in local buffer and encrypt */
|
/* Fill the buffer and encrypt */
|
||||||
memcpy(ctx->buf + ctx->buf_len, in, left);
|
memcpy(ctx->buf + ctx->buf_len, in, left);
|
||||||
ret = (*ctx->cipher->do_cipher)(ctx, out, ctx->buf, blocksize);
|
ret = (*ctx->cipher->do_cipher)(ctx, out, ctx->buf, blocksize);
|
||||||
memset_s(ctx->buf, blocksize, 0, blocksize);
|
memset_s(ctx->buf, blocksize, 0, blocksize);
|
||||||
@@ -905,12 +902,16 @@ EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, void *out, int *outlen,
|
|||||||
ctx->buf_len = (inlen & ctx->block_mask);
|
ctx->buf_len = (inlen & ctx->block_mask);
|
||||||
inlen &= ~ctx->block_mask;
|
inlen &= ~ctx->block_mask;
|
||||||
|
|
||||||
ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
|
if (inlen) {
|
||||||
if (ret != 1)
|
/* Encrypt all the whole blocks of input that we have */
|
||||||
return ret;
|
ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
|
||||||
|
if (ret != 1)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
*outlen += inlen;
|
*outlen += inlen;
|
||||||
|
|
||||||
|
/* Save the tail of the input, if any */
|
||||||
in = ((unsigned char *)in) + inlen;
|
in = ((unsigned char *)in) + inlen;
|
||||||
memcpy(ctx->buf, in, ctx->buf_len);
|
memcpy(ctx->buf, in, ctx->buf_len);
|
||||||
}
|
}
|
||||||
@@ -969,7 +970,7 @@ EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, void *out, int *outlen)
|
|||||||
* @param in in data to the operation.
|
* @param in in data to the operation.
|
||||||
* @param size length of data.
|
* @param size length of data.
|
||||||
*
|
*
|
||||||
* @return 1 on success.
|
* @return bytes encrypted on success, zero on failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
|
Reference in New Issue
Block a user