LibrePDF / OpenPDF

OpenPDF is a free Java library for creating and editing PDF files, with a LGPL and MPL open source license. OpenPDF is based on a fork of iText. We welcome contributions from other developers. Please feel free to submit pull-requests and bugreports to this GitHub repository.
Other
3.58k stars 590 forks source link

Fix code scanning alert - Using a static initialization vector for encryption #1043

Closed andreasrosdal closed 9 months ago

andreasrosdal commented 9 months ago

Fix CodeQL code scanning alert: A static initialization vector should not be used for encryption.

When a cipher is used in certain modes such as CBC or GCM, it requires an initialization vector (IV). Under the same secret key, IVs should be unique and ideally unpredictable. If the same IV is used with the same secret key, then the same plaintext results in the same ciphertext. This can let an attacker learn if the same data pieces are transferred or stored, or help the attacker run a dictionary attack.

Tracking issue for:

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L954-L954

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L926-L926

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L900-L900

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L820-L820

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L803-L803

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L784-L784

mkl-public commented 9 months ago

When a cipher is used in certain modes such as CBC or GCM, it requires an initialization vector (IV). Under the same secret key, IVs should be unique and ideally unpredictable. If the same IV is used with the same secret key, then the same plaintext results in the same ciphertext. This can let an attacker learn if the same data pieces are transferred or stored, or help the attacker run a dictionary attack.

In the cases at hand this is the PDF encryption as specified.

First please be aware that encrypting a single block in ECB mode is equivalent to encrypting it in CBC mode with an IV of zeroes.

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L954-L954

This is in computePermsAlg10.

ISO 32000-2 in section 7.6.4.4.9 "Algorithm 10: Computing the encryption dictionary’s Perms (permissions) value (Security handlers of revision 6)" requires:

"Encrypt the 16-byte block using AES-256 in ECB mode"

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L926-L926

This is in computeOAndOeAlg9.

ISO 32000-2 in section 7.6.4.4.8 "Algorithm 9: Computing the encryption dictionary’s O (owner password) and OE (owner encryption) values (Security handlers of revision 6)" requires:

"encrypt the file encryption key using AES-256 in CBC mode with no padding and an initialization vector of zero"

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L900-L900

This is in computeUAndUeAlg8.

ISO 32000-2 in section 7.6.4.4.7 "Algorithm 8: Computing the encryption dictionary’s U (user password) and UE (user encryption) values (Security handlers of revision 6)" requires

"encrypt the file encryption key using AES-256 in CBC mode with no padding and an initialization vector of zero"

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L820-L820

This is in decryptAndCheckPerms which as documented "implements step f of Algorithm 2.A".

ISO 32000-2 in section 7.6.4.3.3 "Algorithm 2.A: Retrieving the file encryption key from an encrypted document in order to decrypt it (revision 6 and later)" requires in step f:

"Decrypt the 16-byte Perms string using AES-256 in ECB mode"

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L803-L803

This is in setupByUserPassword which as documented "implements step e of Algorithm 2.A".

ISO 32000-2 in section 7.6.4.3.3 "Algorithm 2.A: Retrieving the file encryption key from an encrypted document in order to decrypt it (revision 6 and later)" requires in step e:

"decrypt the 32-byte UE string using AES-256 in CBC mode with no padding and an initialization vector of zero"

https://github.com/LibrePDF/OpenPDF/blob/fafed7e71b504f9ed932c22eb91bdc8a68efb321/openpdf/src/main/java/com/lowagie/text/pdf/PdfEncryption.java#L784-L784

This is in setupByOwnerPassword which as documented "implements step d of Algorithm 2.A".

ISO 32000-2 in section 7.6.4.3.3 "Algorithm 2.A: Retrieving the file encryption key from an encrypted document in order to decrypt it (revision 6 and later)" requires in step d:

"decrypt the 32-byte OE string using AES-256 in CBC mode with no padding and an initialization vector of zero."


Most of these usages actually are non-critical. Merely in case of the Perms key in algorithm 10 this can help an attacker as much of the Perms value is known. See e.g. https://www.nds.rub.de/media/nds/veroeffentlichungen/2021/05/05/PDF_Encryption.pdf "PracticalDecryptionexFiltration:BreakingPDFEncryption". Nonetheless, this is implemented according to spec.