# HG changeset patch # User Olaf Wintermann # Date 1575469095 -3600 # Node ID b1f7d83f6e6916e22822fafc5e763d781e5fe298 # Parent d405d2ac78e68da84ea2d2c9a6dcfcd6e712ce25 fix aes decrypter stream diff -r d405d2ac78e6 -r b1f7d83f6e69 libidav/crypto.c --- a/libidav/crypto.c Wed Dec 04 11:47:51 2019 +0100 +++ b/libidav/crypto.c Wed Dec 04 15:18:15 2019 +0100 @@ -1018,7 +1018,7 @@ dec->key = key; dec->init = 0; dec->ivpos = 0; - + return dec; } @@ -1034,6 +1034,8 @@ size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec) { int len = s*n; if(!dec->init) { + dec->init = 1; + size_t n = 16 - dec->ivpos; size_t cp = n > len ? len : n; memcpy(dec->ivtmp + dec->ivpos, buf, cp); @@ -1052,7 +1054,7 @@ // the cipher text must be a multiply of 16 // remaining bytes are stored in ctx.buf and must be added to cibuf // the next time - size_t cbufalloc = len + 32; + size_t cbufalloc = len + 64; ULONG clen = 0; char *cbuf = malloc(cbufalloc); @@ -1067,30 +1069,39 @@ // check if the message fits the blocksize int remaining = clen % 16; - if(remaining > 0) { - // add remaining bytes to ctx.buf for the next aes_write run - clen -= remaining; - memcpy(dec->ctx.buf, cbuf + clen - remaining, remaining); + if(remaining == 0) { + // decrypt last block next time, or in aes_decrypter_shutdown + // this makes sure, that shutdown always decrypts the last block + // with BCRYPT_BLOCK_PADDING flag + remaining = 16; } + + // add remaining bytes to ctx.buf for the next aes_write run + clen -= remaining; + memcpy(dec->ctx.buf, cbuf + clen, remaining); dec->ctx.buflen = remaining; // ready to decrypt the message ULONG outlen = clen + 32; unsigned char *out = malloc(outlen); - + // decrypt if(clen > 0) { - if(BCryptDecrypt(dec->ctx.hKey, cbuf, clen, NULL, dec->ctx.pbIV, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) { - fprintf(stderr, "Error: BCryptDecrypt failed\n"); + ULONG enc_len = 0; + ULONG status = BCryptDecrypt(dec->ctx.hKey, cbuf, clen, NULL, dec->ctx.pbIV, 16, out, outlen, &enc_len, 0); + if(status > 0) { + fprintf(stderr, "Error: BCryptDecrypt failed: 0x%X\n", status); free(out); free(cbuf); return 0; - } + } + outlen = enc_len; } // write decrypted data to the output stream and update the hash dec->write(out, 1, outlen, dec->stream); BCryptHashData(dec->sha256.hHash, out, outlen, 0); + free(out); free(cbuf); @@ -1098,7 +1109,7 @@ } void aes_decrypter_shutdown(AESDecrypter *dec) { - if(dec->init && dec->ctx.buflen > 0) { + if(dec->init && dec->ctx.buflen > 0) { ULONG outlen = 64; char out[64]; if(BCryptDecrypt(dec->ctx.hKey, dec->ctx.buf, dec->ctx.buflen, NULL, dec->ctx.pbIV, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) { diff -r d405d2ac78e6 -r b1f7d83f6e69 libidav/crypto.h --- a/libidav/crypto.h Wed Dec 04 11:47:51 2019 +0100 +++ b/libidav/crypto.h Wed Dec 04 15:18:15 2019 +0100 @@ -57,8 +57,8 @@ void *pbKeyObject; unsigned char pbIV[16]; - char buf[16]; - size_t buflen; + unsigned char buf[16]; + ULONG buflen; } WinBCryptCTX; typedef struct WinBCryptSHACTX {