1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-10 18:59:39 +02:00

Compare commits

..

No commits in common. "4b179d750a4618fb89ce79e11f8aeb738b847ad8" and "c8d6a3dc857b1e268cef4c3cbcf29d0ae3481947" have entirely different histories.

59 changed files with 74 additions and 64 deletions

View file

@ -139,12 +139,11 @@ class OpenPgpMessageInputStream(
// Comsume packets, potentially stepping into nested layers // Comsume packets, potentially stepping into nested layers
layer@ while (run { layer@ while (run {
packet = packet = try {
try { pIn.nextPacketTag()
pIn.nextPacketTag() } catch (e: NoSuchElementException) {
} catch (e: NoSuchElementException) { throw MalformedOpenPgpMessageException(e.message)
throw MalformedOpenPgpMessageException(e.message) }
}
packet packet
} != null) { } != null) {
@ -211,24 +210,25 @@ class OpenPgpMessageInputStream(
syntaxVerifier.next(InputSymbol.LITERAL_DATA) syntaxVerifier.next(InputSymbol.LITERAL_DATA)
val literalData = packetInputStream!!.readLiteralData() val literalData = packetInputStream!!.readLiteralData()
val streamEncoding = val streamEncoding = try {
try { StreamEncoding.requireFromCode(literalData.format)
StreamEncoding.requireFromCode(literalData.format) } catch (e: NoSuchElementException) {
} catch (e: NoSuchElementException) { throw PGPException("Invalid stream encoding format encountered: ${literalData.format}; ${e.message}")
throw PGPException( }
"Invalid stream encoding format encountered: ${literalData.format}; ${e.message}")
}
val fileName = val fileName = try {
try { literalData.fileName
literalData.fileName } catch (e: IllegalArgumentException) {
} catch (e: IllegalArgumentException) { // Non UTF8
// Non UTF8 throw PGPException("Cannot decode literal data filename: ${e.message}")
throw PGPException("Cannot decode literal data filename: ${e.message}") }
}
// Extract Metadata // Extract Metadata
layerMetadata.child = LiteralData(fileName, literalData.modificationTime, streamEncoding) layerMetadata.child =
LiteralData(
fileName,
literalData.modificationTime,
streamEncoding)
nestedInputStream = literalData.inputStream nestedInputStream = literalData.inputStream
} }
@ -238,15 +238,17 @@ class OpenPgpMessageInputStream(
signatures.enterNesting() signatures.enterNesting()
val compressedData = packetInputStream!!.readCompressedData() val compressedData = packetInputStream!!.readCompressedData()
val compAlg = val compAlg = try {
try { CompressionAlgorithm.requireFromId(compressedData.algorithm)
CompressionAlgorithm.requireFromId(compressedData.algorithm) } catch (e: NoSuchElementException) {
} catch (e: NoSuchElementException) { throw PGPException(e.message)
throw PGPException(e.message) }
}
// Extract Metadata // Extract Metadata
val compressionLayer = CompressedData(compAlg, layerMetadata.depth + 1) val compressionLayer =
CompressedData(
compAlg,
layerMetadata.depth + 1)
LOGGER.debug( LOGGER.debug(
"Compressed Data Packet (${compressionLayer.algorithm}) at depth ${layerMetadata.depth} encountered.") "Compressed Data Packet (${compressionLayer.algorithm}) at depth ${layerMetadata.depth} encountered.")
@ -345,9 +347,7 @@ class OpenPgpMessageInputStream(
"Symmetrically Encrypted Data Packet at depth ${layerMetadata.depth} encountered.") "Symmetrically Encrypted Data Packet at depth ${layerMetadata.depth} encountered.")
syntaxVerifier.next(InputSymbol.ENCRYPTED_DATA) syntaxVerifier.next(InputSymbol.ENCRYPTED_DATA)
val encDataList = packetInputStream!!.readEncryptedDataList() val encDataList = packetInputStream!!.readEncryptedDataList()
if (!encDataList.isIntegrityProtected && if (!encDataList.isIntegrityProtected && !encDataList.isEmpty && !encDataList.get(0).isAEAD) {
!encDataList.isEmpty &&
!encDataList.get(0).isAEAD) {
LOGGER.warn("Symmetrically Encrypted Data Packet is not integrity-protected.") LOGGER.warn("Symmetrically Encrypted Data Packet is not integrity-protected.")
if (!options.isIgnoreMDCErrors()) { if (!options.isIgnoreMDCErrors()) {
throw MessageNotIntegrityProtectedException() throw MessageNotIntegrityProtectedException()
@ -569,14 +569,13 @@ class OpenPgpMessageInputStream(
pkesk: PGPPublicKeyEncryptedData pkesk: PGPPublicKeyEncryptedData
): Boolean { ): Boolean {
try { try {
val decrypted = val decrypted = try {
try { pkesk.getDataStream(decryptorFactory)
pkesk.getDataStream(decryptorFactory) } catch (e: ClassCastException) {
} catch (e: ClassCastException) { throw PGPException(e.message)
throw PGPException(e.message) } catch (e: IllegalArgumentException) {
} catch (e: IllegalArgumentException) { throw PGPException(e.message)
throw PGPException(e.message) }
}
val sessionKey = SessionKey(pkesk.getSessionKey(decryptorFactory)) val sessionKey = SessionKey(pkesk.getSessionKey(decryptorFactory))
throwIfUnacceptable(sessionKey.algorithm) throwIfUnacceptable(sessionKey.algorithm)

View file

@ -165,13 +165,13 @@ class SignatureUtils {
// having them compressed, // having them compressed,
// except for an attacker who is trying to exploit flaws in the decompression // except for an attacker who is trying to exploit flaws in the decompression
// algorithm. // algorithm.
// Therefore, we ignore compressed data packets without attempting // Therefore, we ignore compressed data packets without attempting decompression.
// decompression.
if (nextObject is PGPCompressedData) { if (nextObject is PGPCompressedData) {
// getInputStream() does not do decompression, contrary to getDataStream(). // getInputStream() does not do decompression, contrary to getDataStream().
Streams.drain( Streams.drain(
(nextObject as PGPCompressedData) (nextObject as PGPCompressedData)
.inputStream) // Skip packet without decompressing .inputStream
) // Skip packet without decompressing
} }
if (nextObject is PGPSignatureList) { if (nextObject is PGPSignatureList) {

View file

@ -247,8 +247,7 @@ class ArmorUtils {
.add(OpenPgpFingerprint.of(publicKey).prettyPrint()) .add(OpenPgpFingerprint.of(publicKey).prettyPrint())
// Primary / First User ID // Primary / First User ID
(primary ?: first)?.let { (primary ?: first)?.let {
headerMap headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }
.getOrPut(HEADER_COMMENT) { mutableSetOf() }
.add(it.replace("\n", "\\n").replace("\r", "\\r")) .add(it.replace("\n", "\\n").replace("\r", "\\r"))
} }
// X-1 further identities // X-1 further identities

View file

@ -6,13 +6,13 @@ package org.pgpainless.bouncycastle.fuzzing
import com.code_intelligence.jazzer.api.FuzzedDataProvider import com.code_intelligence.jazzer.api.FuzzedDataProvider
import com.code_intelligence.jazzer.junit.FuzzTest import com.code_intelligence.jazzer.junit.FuzzTest
import java.io.EOFException
import java.io.IOException
import org.bouncycastle.bcpg.ArmoredInputException import org.bouncycastle.bcpg.ArmoredInputException
import org.bouncycastle.bcpg.UnsupportedPacketVersionException import org.bouncycastle.bcpg.UnsupportedPacketVersionException
import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.openpgp.PGPUtil import org.bouncycastle.openpgp.PGPUtil
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory import org.bouncycastle.openpgp.bc.BcPGPObjectFactory
import java.io.EOFException
import java.io.IOException
class PGPObjectFactoryFuzzingTest { class PGPObjectFactoryFuzzingTest {

View file

@ -5,7 +5,6 @@
package org.pgpainless.sop package org.pgpainless.sop
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import kotlin.jvm.Throws import kotlin.jvm.Throws
@ -15,6 +14,7 @@ import org.pgpainless.util.ArmoredOutputStreamFactory
import sop.Ready import sop.Ready
import sop.exception.SOPGPException import sop.exception.SOPGPException
import sop.operation.Armor import sop.operation.Armor
import java.io.IOException
/** Implementation of the `armor` operation using PGPainless. */ /** Implementation of the `armor` operation using PGPainless. */
class ArmorImpl : Armor { class ArmorImpl : Armor {
@ -27,15 +27,14 @@ class ArmorImpl : Armor {
val bufferedOutputStream = BufferedOutputStream(outputStream) val bufferedOutputStream = BufferedOutputStream(outputStream)
// Determine the nature of the given data // Determine the nature of the given data
val openPgpIn = val openPgpIn = OpenPgpInputStream(data, false).apply {
OpenPgpInputStream(data, false).apply { try {
try { inspectBuffer()
inspectBuffer() } catch (e: IOException) {
} catch (e: IOException) { // ignore
// ignore
}
reset()
} }
reset()
}
if (openPgpIn.isAsciiArmored) { if (openPgpIn.isAsciiArmored) {
// armoring already-armored data is an idempotent operation // armoring already-armored data is an idempotent operation

View file

@ -4,13 +4,11 @@
package org.pgpainless.sop package org.pgpainless.sop
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.util.* import java.util.*
import java.util.zip.ZipException
import kotlin.NoSuchElementException
import org.bouncycastle.bcpg.UnsupportedPacketVersionException
import org.bouncycastle.openpgp.PGPException import org.bouncycastle.openpgp.PGPException
import org.bouncycastle.util.io.Streams import org.bouncycastle.util.io.Streams
import org.pgpainless.PGPainless import org.pgpainless.PGPainless
@ -27,6 +25,8 @@ import sop.SessionKey
import sop.exception.SOPGPException import sop.exception.SOPGPException
import sop.operation.Decrypt import sop.operation.Decrypt
import sop.util.UTF8Util import sop.util.UTF8Util
import java.util.zip.ZipException
import kotlin.NoSuchElementException
/** Implementation of the `decrypt` operation using PGPainless. */ /** Implementation of the `decrypt` operation using PGPainless. */
class DecryptImpl : Decrypt { class DecryptImpl : Decrypt {
@ -61,7 +61,8 @@ class DecryptImpl : Decrypt {
throw SOPGPException.BadData(e) throw SOPGPException.BadData(e)
} catch (e: ModificationDetectionException) { } catch (e: ModificationDetectionException) {
throw SOPGPException.BadData(e) throw SOPGPException.BadData(e)
} finally { }
finally {
// Forget passphrases after decryption // Forget passphrases after decryption
protector.clear() protector.clear()
} }

View file

@ -14,7 +14,7 @@ import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals;
public class ArmorFuzzTest { public class AsciiArmorFuzzTest {
private final SOP sop = new SOPImpl(); private final SOP sop = new SOPImpl();

View file

@ -6,8 +6,12 @@ package org.pgpainless.sop.fuzzing;
import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.code_intelligence.jazzer.junit.FuzzTest; import com.code_intelligence.jazzer.junit.FuzzTest;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.io.Streams; import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.pgpainless.exception.MissingDecryptionMethodException;
import org.pgpainless.exception.ModificationDetectionException;
import org.pgpainless.sop.SOPImpl; import org.pgpainless.sop.SOPImpl;
import sop.SOP; import sop.SOP;
import sop.exception.SOPGPException; import sop.exception.SOPGPException;
@ -17,14 +21,22 @@ import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
public class EncryptFuzzTest { public class EncryptedMessageFuzzingTest {
private final SOP sop = new SOPImpl(); private final SOP sop = new SOPImpl();
private final String password = "sw0rdf1sh"; private final String password = "sw0rdf1sh";
@ -41,7 +53,7 @@ public class EncryptFuzzTest {
List<byte[]> keys = new ArrayList<>(); List<byte[]> keys = new ArrayList<>();
String dir = "/org/pgpainless/sop/fuzzing/testKeys"; String dir = "/org/pgpainless/sop/fuzzing/testKeys";
InputStream in = EncryptFuzzTest.class.getResourceAsStream(dir); InputStream in = EncryptedMessageFuzzingTest.class.getResourceAsStream(dir);
BufferedReader reader = new BufferedReader(new InputStreamReader(in)); BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String file; String file;
@ -50,7 +62,7 @@ public class EncryptFuzzTest {
continue; continue;
} }
try(InputStream fIn = EncryptFuzzTest.class.getResourceAsStream(dir + "/" + file)) { try(InputStream fIn = EncryptedMessageFuzzingTest.class.getResourceAsStream(dir + "/" + file)) {
byte[] b = Streams.readAll(fIn); byte[] b = Streams.readAll(fIn);
keys.add(b); keys.add(b);
} }

View file

@ -15,7 +15,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
public class VerifyFuzzTest { public class SignatureFuzzTest {
private final SOP sop = new SOPImpl(); private final SOP sop = new SOPImpl();
private final byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); private final byte[] data = "Hello, World!\n".getBytes(StandardCharsets.UTF_8);