diff --git a/pdfio-common.c b/pdfio-common.c index 5f54d70..00da8e6 100644 --- a/pdfio-common.c +++ b/pdfio-common.c @@ -329,6 +329,11 @@ _pdfioFileRead(pdfio_file_t *pdf, // I - PDF file pdf->bufpos += rbytes; continue; } + else if (rbytes < 0 && (errno == EINTR || errno == EAGAIN)) + { + rbytes = 0; + continue; + } else break; } diff --git a/pdfio-crypto.c b/pdfio-crypto.c index bcbe64e..27c5d66 100644 --- a/pdfio-crypto.c +++ b/pdfio-crypto.c @@ -104,7 +104,7 @@ static void decrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_ static void encrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]); static void make_file_key(pdfio_encryption_t encryption, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, uint8_t file_key[16]); static void make_owner_key(pdfio_encryption_t encryption, const uint8_t *owner_pad, const uint8_t *user_pad, uint8_t owner_key[32]); -static void make_user_key(pdfio_encryption_t encryption, const unsigned char *file_id, size_t file_idlen, uint8_t user_key[32]); +static void make_user_key(const unsigned char *file_id, size_t file_idlen, uint8_t user_key[32]); static void pad_password(const char *password, uint8_t pad[32]); @@ -166,7 +166,7 @@ _pdfioCryptoLock( pdf->file_keylen = 16; // Generate the user key... - make_user_key(encryption, file_id, file_idlen, pdf->user_key); + make_user_key(file_id, file_idlen, pdf->user_key); encrypt_user_key(encryption, pdf->file_key, pdf->user_key); pdf->user_keylen = 32; @@ -415,6 +415,8 @@ _pdfio_crypto_cb_t // O - Decryption callback or `NULL` for none uint8_t digest[16]; /* MD5 digest value */ + PDFIO_DEBUG("_pdfioCryptoMakeReader(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", pdf, obj, (int)obj->number, ctx, iv, ivlen, (int)*ivlen); + // Range check input... if (!pdf) { @@ -479,6 +481,8 @@ _pdfio_crypto_cb_t // O - Encryption callback or `NULL` for none uint8_t digest[16]; /* MD5 digest value */ + PDFIO_DEBUG("_pdfioCryptoMakeWriter(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", pdf, obj, (int)obj->number, ctx, iv, ivlen, (int)*ivlen); + // Range check input... if (!pdf) { @@ -565,13 +569,10 @@ _pdfioCryptoUnlock( return (false); } - handler = pdfioDictGetName(encrypt_dict, "Filter"); - version = (int)pdfioDictGetNumber(encrypt_dict, "V"); - revision = (int)pdfioDictGetNumber(encrypt_dict, "R"); - length = (int)pdfioDictGetNumber(encrypt_dict, "Length"); - stream_filter = pdfioDictGetName(encrypt_dict, "StmF"); - string_filter = pdfioDictGetName(encrypt_dict, "StrF"); - cf_dict = pdfioDictGetDict(encrypt_dict, "CF"); + handler = pdfioDictGetName(encrypt_dict, "Filter"); + version = (int)pdfioDictGetNumber(encrypt_dict, "V"); + revision = (int)pdfioDictGetNumber(encrypt_dict, "R"); + length = (int)pdfioDictGetNumber(encrypt_dict, "Length"); if (!handler || strcmp(handler, "Standard")) { @@ -585,7 +586,41 @@ _pdfioCryptoUnlock( pdfio_dict_t *filter; // Crypt Filter const char *cfm; // Crypt filter method - if ((filter = pdfioDictGetDict(cf_dict, stream_filter)) != NULL && (cfm = pdfioDictGetName(filter, "CFM")) != NULL) + stream_filter = pdfioDictGetName(encrypt_dict, "StmF"); + string_filter = pdfioDictGetName(encrypt_dict, "StrF"); + cf_dict = pdfioDictGetDict(encrypt_dict, "CF"); + + if (!cf_dict) + { + _pdfioFileError(pdf, "Missing encryption filter dictionary."); + return (false); + } + else if (!stream_filter) + { + _pdfioFileError(pdf, "Missing stream encryption filter."); + return (false); + } + else if (!string_filter) + { + _pdfioFileError(pdf, "Missing string encryption filter."); + return (false); + } + else if (strcmp(stream_filter, string_filter)) + { + _pdfioFileError(pdf, "Different stream and string encryption filters - not supported."); + return (false); + } + else if ((filter = pdfioDictGetDict(cf_dict, stream_filter)) == NULL) + { + _pdfioFileError(pdf, "Missing stream encryption filter '%s'.", stream_filter); + return (false); + } + else if ((cfm = pdfioDictGetName(filter, "CFM")) == NULL) + { + _pdfioFileError(pdf, "Missing encryption filter method."); + return (false); + } + else { if (!strcmp(cfm, "V2")) { @@ -623,7 +658,7 @@ _pdfioCryptoUnlock( } // Grab the remaining values we need to unlock the PDF... - pdf->file_keylen = length / 8; + pdf->file_keylen = (size_t)(length / 8); pdf->permissions = (pdfio_permission_t)pdfioDictGetNumber(encrypt_dict, "P"); owner_key = pdfioDictGetBinary(encrypt_dict, "O", &owner_keylen); @@ -667,7 +702,7 @@ _pdfioCryptoUnlock( uint8_t pad[32], // Padded password file_key[16], // File key user_pad[32], // Padded user password - user_key[32], // User key + own_user_key[32], // Calculated user key pdf_user_key[32]; // Decrypted user key // Pad the supplied password, if any... @@ -684,12 +719,12 @@ _pdfioCryptoUnlock( make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, user_pad, pdf->owner_key, file_key); PDFIO_DEBUG("Fown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]); - make_user_key(pdf->encryption, file_id, file_idlen, user_key); + make_user_key(file_id, file_idlen, own_user_key); PDFIO_DEBUG("U=%02X%02X%02X%02X...%02X%02X%02X%02X\n", pdf->user_key[0], pdf->user_key[1], pdf->user_key[2], pdf->user_key[3], pdf->user_key[28], pdf->user_key[29], pdf->user_key[30], pdf->user_key[31]); - PDFIO_DEBUG("Uown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_key[0], user_key[1], user_key[2], user_key[3], user_key[28], user_key[29], user_key[30], user_key[31]); + PDFIO_DEBUG("Uown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", own_user_key[0], own_user_key[1], own_user_key[2], own_user_key[3], own_user_key[28], own_user_key[29], own_user_key[30], own_user_key[31]); - if (!memcmp(user_key, pdf->user_key, sizeof(user_key))) + if (!memcmp(own_user_key, pdf->user_key, sizeof(own_user_key))) { // Matches! memcpy(pdf->file_key, file_key, sizeof(pdf->file_key)); @@ -703,7 +738,7 @@ _pdfioCryptoUnlock( make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, pad, pdf->owner_key, file_key); PDFIO_DEBUG("Fuse=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]); - make_user_key(pdf->encryption, file_id, file_idlen, user_key); + make_user_key(file_id, file_idlen, user_key); memcpy(pdf_user_key, pdf->user_key, sizeof(pdf_user_key)); decrypt_user_key(pdf->encryption, file_key, pdf_user_key); @@ -928,7 +963,6 @@ make_owner_key( static void make_user_key( - pdfio_encryption_t encryption, // I - Type of encryption const unsigned char *file_id, // I - File ID value size_t file_idlen, // I - Length of file ID uint8_t user_key[32]) // O - User key diff --git a/pdfio-stream.c b/pdfio-stream.c index de77031..59c25fc 100644 --- a/pdfio-stream.c +++ b/pdfio-stream.c @@ -68,7 +68,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream if (st->crypto_cb) { // Encrypt it first... - outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes & ~15); + outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes & (size_t)~15); } else { @@ -93,7 +93,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream } st->flate.next_out = (Bytef *)st->cbuffer + bytes; - st->flate.avail_out = (uInt)sizeof(st->cbuffer) - bytes; + st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - bytes); } if (st->flate.avail_out < (uInt)sizeof(st->cbuffer)) @@ -430,7 +430,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object uint8_t iv[64]; // Initialization vector size_t ivlen; // Length of initialization vector, if any - ivlen = _pdfioFilePeek(st->pdf, iv, sizeof(iv)); + ivlen = (size_t)_pdfioFilePeek(st->pdf, iv, sizeof(iv)); if ((st->crypto_cb = _pdfioCryptoMakeReader(st->pdf, obj, &st->crypto_ctx, iv, &ivlen)) == NULL) { @@ -441,6 +441,9 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object if (ivlen > 0) _pdfioFileConsume(st->pdf, ivlen); + + if (st->pdf->encryption >= PDFIO_ENCRYPTION_AES_128) + st->remaining = (st->remaining + 15) & (size_t)~15; } if (decode) @@ -558,7 +561,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object } if (st->crypto_cb) - rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); + rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes); st->flate.next_in = (Bytef *)st->cbuffer; st->flate.avail_in = (uInt)rbytes; @@ -825,8 +828,8 @@ pdfioStreamWrite( if (st->bufptr > st->buffer || bytes < 16) { // Write through the stream's buffer... - if ((cbytes = bytes) > (st->bufend - st->bufptr)) - cbytes = st->bufend - st->bufptr; + if ((cbytes = bytes) > (size_t)(st->bufend - st->bufptr)) + cbytes = (size_t)(st->bufend - st->bufptr); memcpy(st->bufptr, bufptr, cbytes); st->bufptr += cbytes; @@ -848,7 +851,7 @@ pdfioStreamWrite( if (cbytes & 15) { // AES has a 16-byte block size, so save the last few bytes... - cbytes &= ~15; + cbytes &= (size_t)~15; } outbytes = (st->crypto_cb)(&st->crypto_ctx, temp, bufptr, cbytes); @@ -1007,7 +1010,7 @@ stream_read(pdfio_stream_t *st, // I - Stream st->remaining -= (size_t)rbytes; if (st->crypto_cb) - (st->crypto_cb)(&st->crypto_ctx, (uint8_t *)buffer, (uint8_t *)buffer, rbytes); + (st->crypto_cb)(&st->crypto_ctx, (uint8_t *)buffer, (uint8_t *)buffer, (size_t)rbytes); } return (rbytes); @@ -1034,7 +1037,7 @@ stream_read(pdfio_stream_t *st, // I - Stream return (-1); // End of file... if (st->crypto_cb) - rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); + rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes); st->remaining -= (size_t)rbytes; st->flate.next_in = (Bytef *)st->cbuffer; @@ -1090,7 +1093,7 @@ stream_read(pdfio_stream_t *st, // I - Stream return (-1); // End of file... if (st->crypto_cb) - rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); + rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes); st->remaining -= (size_t)rbytes; st->flate.next_in = (Bytef *)st->cbuffer; @@ -1157,7 +1160,7 @@ stream_read(pdfio_stream_t *st, // I - Stream return (-1); // End of file... if (st->crypto_cb) - rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); + rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes); st->remaining -= (size_t)rbytes; st->flate.next_in = (Bytef *)st->cbuffer; @@ -1261,7 +1264,7 @@ stream_write(pdfio_stream_t *st, // I - Stream if (st->crypto_cb) { // Encrypt it first... - outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, cbytes & ~15); + outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, cbytes & (size_t)~15); } else { @@ -1284,7 +1287,7 @@ stream_write(pdfio_stream_t *st, // I - Stream } st->flate.next_out = (Bytef *)st->cbuffer + cbytes; - st->flate.avail_out = sizeof(st->cbuffer) - cbytes; + st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - cbytes); } // Deflate what we can this time... diff --git a/pdfio-token.c b/pdfio-token.c index 6cb79c8..7e9dc62 100644 --- a/pdfio-token.c +++ b/pdfio-token.c @@ -498,9 +498,6 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack break; } - while (tb->bufptr < tb->bufend && isspace(*(tb->bufptr))) - tb->bufptr ++; - *bufptr = '\0'; PDFIO_DEBUG("_pdfioTokenRead: Read '%s'.\n", buffer);