diff --git a/.gitignore b/.gitignore index 222bce1..fa3bb5f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,5 @@ /packages /pdfio.xcodeproj/xcshareddata /testpdfio -/testpdfio-out.pdf -/testpdfio-out2.pdf +/testpdfio-*.pdf /x64 diff --git a/pdfio-aes.c b/pdfio-aes.c index 9c91e5b..2f504c5 100644 --- a/pdfio-aes.c +++ b/pdfio-aes.c @@ -170,7 +170,7 @@ _pdfioCryptoAESInit( // multiple of 16 bytes (excess is not decrypted). // -void +size_t // O - Number of bytes in output buffer _pdfioCryptoAESDecrypt( _pdfio_aes_t *ctx, // I - AES context uint8_t *outbuffer, // I - Output buffer @@ -178,6 +178,7 @@ _pdfioCryptoAESDecrypt( size_t len) // I - Number of bytes to decrypt { uint8_t next_iv[16]; // Next IV value + size_t outbytes = 0; // Output bytes if (inbuffer != outbuffer) @@ -196,7 +197,10 @@ _pdfioCryptoAESDecrypt( memcpy(ctx->iv, next_iv, 16); outbuffer += 16; len -= 16; + outbytes += 16; } + + return (outbytes); } @@ -207,7 +211,7 @@ _pdfioCryptoAESDecrypt( // be a multiple of 16 bytes. // -void +size_t // O - Number of bytes in output buffer _pdfioCryptoAESEncrypt( _pdfio_aes_t *ctx, // I - AES context uint8_t *outbuffer, // I - Output buffer @@ -215,6 +219,7 @@ _pdfioCryptoAESEncrypt( size_t len) // I - Number of bytes to decrypt { uint8_t *iv = ctx->iv; // Current IV for CBC + size_t outbytes = 0; // Output bytes if (inbuffer != outbuffer) @@ -232,6 +237,7 @@ _pdfioCryptoAESEncrypt( iv = outbuffer; outbuffer += 16; len -= 16; + outbytes += 16; } if (len > 0) @@ -242,10 +248,13 @@ _pdfioCryptoAESEncrypt( XorWithIv(outbuffer, iv); Cipher((state_t*)outbuffer, ctx); iv = outbuffer; + outbytes += 16; } /* store Iv in ctx for next call */ memcpy(ctx->iv, iv, 16); + + return (outbytes); } diff --git a/pdfio-private.h b/pdfio-private.h index 51eb199..80f3b03 100644 --- a/pdfio-private.h +++ b/pdfio-private.h @@ -211,7 +211,7 @@ typedef union _pdfio_crypto_ctx_u // Cryptographic contexts _pdfio_aes_t aes; // AES-128/256 context _pdfio_rc4_t rc4; // RC4-40/128 context } _pdfio_crypto_ctx_t; -typedef void (*_pdfio_crypto_cb_t)(_pdfio_crypto_ctx_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len); +typedef size_t (*_pdfio_crypto_cb_t)(_pdfio_crypto_ctx_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len); struct _pdfio_array_s { @@ -342,8 +342,8 @@ extern pdfio_array_t *_pdfioArrayRead(pdfio_file_t *pdf, _pdfio_token_t *ts) _PD extern bool _pdfioArrayWrite(pdfio_array_t *a) _PDFIO_INTERNAL; extern void _pdfioCryptoAESInit(_pdfio_aes_t *ctx, const uint8_t *key, size_t keylen, const uint8_t *iv) _PDFIO_INTERNAL; -extern void _pdfioCryptoAESDecrypt(_pdfio_aes_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; -extern void _pdfioCryptoAESEncrypt(_pdfio_aes_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; +extern size_t _pdfioCryptoAESDecrypt(_pdfio_aes_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; +extern size_t _pdfioCryptoAESEncrypt(_pdfio_aes_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; extern void _pdfioCryptoMakeRandom(uint8_t *buffer, size_t bytes) _PDFIO_INTERNAL; extern _pdfio_crypto_cb_t _pdfioCryptoMakeReader(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_crypto_ctx_t *ctx, uint8_t *iv, size_t *ivlen) _PDFIO_INTERNAL; extern _pdfio_crypto_cb_t _pdfioCryptoMakeWriter(pdfio_file_t *pdf, pdfio_obj_t *obj, _pdfio_crypto_ctx_t *ctx, uint8_t *iv, size_t *ivlen) _PDFIO_INTERNAL; @@ -351,7 +351,7 @@ extern void _pdfioCryptoMD5Append(_pdfio_md5_t *pms, const uint8_t *data, size_ extern void _pdfioCryptoMD5Finish(_pdfio_md5_t *pms, uint8_t digest[16]) _PDFIO_INTERNAL; extern void _pdfioCryptoMD5Init(_pdfio_md5_t *pms) _PDFIO_INTERNAL; extern void _pdfioCryptoRC4Init(_pdfio_rc4_t *ctx, const uint8_t *key, size_t keylen) _PDFIO_INTERNAL; -extern void _pdfioCryptoRC4Crypt(_pdfio_rc4_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; +extern size_t _pdfioCryptoRC4Crypt(_pdfio_rc4_t *ctx, uint8_t *outbuffer, const uint8_t *inbuffer, size_t len) _PDFIO_INTERNAL; extern void _pdfioCryptoSHA256Append(_pdfio_sha256_t *, const uint8_t *bytes, size_t bytecount) _PDFIO_INTERNAL; extern void _pdfioCryptoSHA256Init(_pdfio_sha256_t *ctx) _PDFIO_INTERNAL; extern void _pdfioCryptoSHA256Finish(_pdfio_sha256_t *ctx, uint8_t *Message_Digest) _PDFIO_INTERNAL; diff --git a/pdfio-rc4.c b/pdfio-rc4.c index 77cdaea..cbaf2dc 100644 --- a/pdfio-rc4.c +++ b/pdfio-rc4.c @@ -69,7 +69,7 @@ _pdfioCryptoRC4Init( // "inbuffer" and "outbuffer" can point to the same memory. // -void +size_t // O - Number of output bytes _pdfioCryptoRC4Crypt( _pdfio_rc4_t *ctx, // I - Context uint8_t *outbuffer, // I - Output buffer @@ -79,6 +79,7 @@ _pdfioCryptoRC4Crypt( uint8_t tmp, // Swap variable i, j, // Looping vars t; // Current S box + size_t outbytes = len; // Number of output bytes // Loop through the entire buffer... @@ -107,4 +108,6 @@ _pdfioCryptoRC4Crypt( // Copy current S box indices back to context... ctx->i = i; ctx->j = j; + + return (outbytes); } diff --git a/pdfio-stream.c b/pdfio-stream.c index 8cb792f..4be541c 100644 --- a/pdfio-stream.c +++ b/pdfio-stream.c @@ -54,6 +54,9 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream while ((status = deflate(&st->flate, Z_FINISH)) != Z_STREAM_END) { + size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out; + // Bytes to write + if (status < Z_OK && status != Z_BUF_ERROR) { _pdfioFileError(st->pdf, "Flate compression failed: %s", zstrerror(status)); @@ -64,10 +67,10 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream if (st->crypto_cb) { // Encrypt it first... - (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, sizeof(st->cbuffer) - st->flate.avail_out); + bytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes); } - if (!_pdfioFileWrite(st->pdf, st->cbuffer, sizeof(st->cbuffer) - st->flate.avail_out)) + if (!_pdfioFileWrite(st->pdf, st->cbuffer, bytes)) { ret = false; goto done; @@ -80,13 +83,16 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream if (st->flate.avail_out < (uInt)sizeof(st->cbuffer)) { // Write any residuals... + size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out; + // Bytes to write + if (st->crypto_cb) { // Encrypt it first... - (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, sizeof(st->cbuffer) - st->flate.avail_out); + bytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes); } - if (!_pdfioFileWrite(st->pdf, st->cbuffer, sizeof(st->cbuffer) - st->flate.avail_out)) + if (!_pdfioFileWrite(st->pdf, st->cbuffer, bytes)) { ret = false; goto done; @@ -755,7 +761,8 @@ pdfioStreamWrite( { // Encrypt data before writing... unsigned char temp[8192]; // Temporary buffer - size_t cbytes; // Current bytes + size_t cbytes, // Current bytes + outbytes; // Output bytes bufptr = (const unsigned char *)buffer; @@ -764,8 +771,8 @@ pdfioStreamWrite( if ((cbytes = bytes) > sizeof(temp)) cbytes = sizeof(temp); - (st->crypto_cb)(&st->crypto_ctx, temp, bufptr, cbytes); - if (!_pdfioFileWrite(st->pdf, temp, cbytes)) + outbytes = (st->crypto_cb)(&st->crypto_ctx, temp, bufptr, cbytes); + if (!_pdfioFileWrite(st->pdf, temp, outbytes)) return (false); bytes -= cbytes; @@ -1153,13 +1160,15 @@ stream_write(pdfio_stream_t *st, // I - Stream if (st->flate.avail_out < (sizeof(st->cbuffer) / 8)) { // Flush the compression buffer... + size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out; + if (st->crypto_cb) { // Encrypt it first... - (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, sizeof(st->cbuffer) - st->flate.avail_out); + bytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes); } - if (!_pdfioFileWrite(st->pdf, st->cbuffer, sizeof(st->cbuffer) - st->flate.avail_out)) + if (!_pdfioFileWrite(st->pdf, st->cbuffer, bytes)) return (false); st->flate.next_out = (Bytef *)st->cbuffer;