|
|
|
@ -430,6 +430,24 @@ _pdfio_crypto_cb_t // O - Decryption callback or `NULL` for none
|
|
|
|
|
*ivlen = 0;
|
|
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
|
|
case PDFIO_ENCRYPTION_RC4_40 :
|
|
|
|
|
// Copy the key data for the MD5 hash.
|
|
|
|
|
memcpy(data, pdf->file_key, sizeof(pdf->file_key));
|
|
|
|
|
data[16] = (uint8_t)obj->number;
|
|
|
|
|
data[17] = (uint8_t)(obj->number >> 8);
|
|
|
|
|
data[18] = (uint8_t)(obj->number >> 16);
|
|
|
|
|
data[19] = (uint8_t)obj->generation;
|
|
|
|
|
data[20] = (uint8_t)(obj->generation >> 8);
|
|
|
|
|
|
|
|
|
|
// Hash it...
|
|
|
|
|
_pdfioCryptoMD5Init(&md5);
|
|
|
|
|
_pdfioCryptoMD5Append(&md5, data, sizeof(data));
|
|
|
|
|
_pdfioCryptoMD5Finish(&md5, digest);
|
|
|
|
|
|
|
|
|
|
// Initialize the RC4 context using 40 bits of the digest...
|
|
|
|
|
_pdfioCryptoRC4Init(&ctx->rc4, digest, 5);
|
|
|
|
|
return ((_pdfio_crypto_cb_t)_pdfioCryptoRC4Crypt);
|
|
|
|
|
|
|
|
|
|
case PDFIO_ENCRYPTION_RC4_128 :
|
|
|
|
|
case PDFIO_ENCRYPTION_AES_128 :
|
|
|
|
|
// Copy the key data for the MD5 hash.
|
|
|
|
@ -635,7 +653,7 @@ _pdfioCryptoUnlock(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (version == 2)
|
|
|
|
|
else if (version == 1 || version == 2)
|
|
|
|
|
{
|
|
|
|
|
if (revision == 2)
|
|
|
|
|
{
|
|
|
|
@ -651,6 +669,8 @@ _pdfioCryptoUnlock(
|
|
|
|
|
}
|
|
|
|
|
// TODO: Implement AES-256 - V6 R6
|
|
|
|
|
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: encryption=%d, length=%d\n", pdf->encryption, length);
|
|
|
|
|
|
|
|
|
|
if (pdf->encryption == PDFIO_ENCRYPTION_NONE)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Unsupported encryption V%d R%d.", version, revision);
|
|
|
|
@ -661,23 +681,39 @@ _pdfioCryptoUnlock(
|
|
|
|
|
pdf->file_keylen = (size_t)(length / 8);
|
|
|
|
|
pdf->permissions = (pdfio_permission_t)pdfioDictGetNumber(encrypt_dict, "P");
|
|
|
|
|
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: permissions=%d\n", pdf->permissions);
|
|
|
|
|
|
|
|
|
|
owner_key = pdfioDictGetBinary(encrypt_dict, "O", &owner_keylen);
|
|
|
|
|
user_key = pdfioDictGetBinary(encrypt_dict, "U", &user_keylen);
|
|
|
|
|
|
|
|
|
|
if (!owner_key || owner_keylen < 32 || owner_keylen > sizeof(pdf->owner_key))
|
|
|
|
|
if (!owner_key)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Missing or bad owner key, unable to unlock file.");
|
|
|
|
|
_pdfioFileError(pdf, "Missing owner key, unable to unlock file.");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
else if (owner_keylen < 32 || owner_keylen > sizeof(pdf->owner_key))
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Bad %d bytes owner key, unable to unlock file.", (int)owner_keylen);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: owner_key[%d]=%02X%02X%02X%02X...%02X%02X%02X%02X\n", (int)owner_keylen, owner_key[0], owner_key[1], owner_key[2], owner_key[3], owner_key[28], owner_key[29], owner_key[30], owner_key[31]);
|
|
|
|
|
|
|
|
|
|
memcpy(pdf->owner_key, owner_key, owner_keylen);
|
|
|
|
|
pdf->owner_keylen = owner_keylen;
|
|
|
|
|
|
|
|
|
|
if (!user_key || user_keylen < 32 || user_keylen > sizeof(pdf->user_key))
|
|
|
|
|
if (!user_key)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Missing or bad user key, unable to unlock file.");
|
|
|
|
|
_pdfioFileError(pdf, "Missing user key, unable to unlock file.");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
else if (user_keylen < 32 || user_keylen > sizeof(pdf->user_key))
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Bad %d byte user key, unable to unlock file.", (int)user_keylen);
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: user_key[%d]=%02X%02X%02X%02X...%02X%02X%02X%02X\n", (int)user_keylen, user_key[0], user_key[1], user_key[2], user_key[3], user_key[28], user_key[29], user_key[30], user_key[31]);
|
|
|
|
|
|
|
|
|
|
memcpy(pdf->user_key, user_key, user_keylen);
|
|
|
|
|
pdf->user_keylen = user_keylen;
|
|
|
|
@ -709,20 +745,20 @@ _pdfioCryptoUnlock(
|
|
|
|
|
pad_password(password, pad);
|
|
|
|
|
|
|
|
|
|
// Generate keys to see if things match...
|
|
|
|
|
PDFIO_DEBUG("\nTrying %02X%02X%02X%02X...%02X%02X%02X%02X\n", pad[0], pad[1], pad[2], pad[3], pad[28], pad[29], pad[30], pad[31]);
|
|
|
|
|
PDFIO_DEBUG("P=%d\n", pdf->permissions);
|
|
|
|
|
PDFIO_DEBUG("Fid(%d)=%02X%02X%02X%02X...%02X%02X%02X%02X\n", (int)file_idlen, file_id[0], file_id[1], file_id[2], file_id[3], file_id[12], file_id[13], file_id[14], file_id[15]);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: Trying %02X%02X%02X%02X...%02X%02X%02X%02X\n", pad[0], pad[1], pad[2], pad[3], pad[28], pad[29], pad[30], pad[31]);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: P=%d\n", pdf->permissions);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: Fid(%d)=%02X%02X%02X%02X...%02X%02X%02X%02X\n", (int)file_idlen, file_id[0], file_id[1], file_id[2], file_id[3], file_id[12], file_id[13], file_id[14], file_id[15]);
|
|
|
|
|
|
|
|
|
|
make_owner_key(pdf->encryption, pad, pdf->owner_key, user_pad);
|
|
|
|
|
PDFIO_DEBUG("Upad=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_pad[0], user_pad[1], user_pad[2], user_pad[3], user_pad[28], user_pad[29], user_pad[30], user_pad[31]);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: Upad=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_pad[0], user_pad[1], user_pad[2], user_pad[3], user_pad[28], user_pad[29], user_pad[30], user_pad[31]);
|
|
|
|
|
|
|
|
|
|
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]);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: 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(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", 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]);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: 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("_pdfioCryptoUnlock: 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(own_user_key, pdf->user_key, sizeof(own_user_key)))
|
|
|
|
|
{
|
|
|
|
@ -736,17 +772,17 @@ _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]);
|
|
|
|
|
PDFIO_DEBUG("_pdfioCryptoUnlock: 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(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);
|
|
|
|
|
|
|
|
|
|
PDFIO_DEBUG("Uuse=%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("Updf=%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("_pdfioCryptoUnlock: Uuse=%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("_pdfioCryptoUnlock: Updf=%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]);
|
|
|
|
|
|
|
|
|
|
if (!memcmp(user_key, pdf_user_key, 16))
|
|
|
|
|
if (!memcmp(pad, pdf_user_key, 32) || !memcmp(own_user_key, user_key, 32) || !memcmp(user_key, pdf_user_key, 16))
|
|
|
|
|
{
|
|
|
|
|
// Matches!
|
|
|
|
|
memcpy(pdf->file_key, file_key, sizeof(pdf->file_key));
|
|
|
|
|