mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-10 18:59:39 +02:00
Even more fuzzing
This commit is contained in:
parent
891a6b745a
commit
68991800d4
37 changed files with 538 additions and 409 deletions
|
@ -145,7 +145,12 @@ class OpenPgpMessageInputStream(
|
|||
|
||||
// Comsume packets, potentially stepping into nested layers
|
||||
layer@ while (run {
|
||||
packet = pIn.nextPacketTag()
|
||||
packet =
|
||||
try {
|
||||
pIn.nextPacketTag()
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw MalformedOpenPgpMessageException(e)
|
||||
}
|
||||
packet
|
||||
} != null) {
|
||||
|
||||
|
@ -208,12 +213,24 @@ class OpenPgpMessageInputStream(
|
|||
syntaxVerifier.next(InputSymbol.LITERAL_DATA)
|
||||
val literalData = packetInputStream!!.readLiteralData()
|
||||
|
||||
val streamEncoding =
|
||||
try {
|
||||
StreamEncoding.requireFromCode(literalData.format)
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw PGPException(
|
||||
"Invalid stream encoding format encountered: ${literalData.format}; ${e.message}")
|
||||
}
|
||||
|
||||
val fileName =
|
||||
try {
|
||||
literalData.fileName
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// Non UTF8
|
||||
throw PGPException("Cannot decode literal data filename: ${e.message}")
|
||||
}
|
||||
|
||||
// Extract Metadata
|
||||
layerMetadata.child =
|
||||
LiteralData(
|
||||
literalData.fileName,
|
||||
literalData.modificationTime,
|
||||
StreamEncoding.requireFromCode(literalData.format))
|
||||
layerMetadata.child = LiteralData(fileName, literalData.modificationTime, streamEncoding)
|
||||
|
||||
nestedInputStream = literalData.inputStream
|
||||
}
|
||||
|
@ -223,11 +240,15 @@ class OpenPgpMessageInputStream(
|
|||
signatures.enterNesting()
|
||||
val compressedData = packetInputStream!!.readCompressedData()
|
||||
|
||||
val compAlg =
|
||||
try {
|
||||
CompressionAlgorithm.requireFromId(compressedData.algorithm)
|
||||
} catch (e: NoSuchElementException) {
|
||||
throw PGPException(e.message)
|
||||
}
|
||||
|
||||
// Extract Metadata
|
||||
val compressionLayer =
|
||||
CompressedData(
|
||||
CompressionAlgorithm.requireFromId(compressedData.algorithm),
|
||||
layerMetadata.depth + 1)
|
||||
val compressionLayer = CompressedData(compAlg, layerMetadata.depth + 1)
|
||||
|
||||
LOGGER.debug(
|
||||
"Compressed Data Packet (${compressionLayer.algorithm}) at depth ${layerMetadata.depth} encountered.")
|
||||
|
@ -326,32 +347,19 @@ class OpenPgpMessageInputStream(
|
|||
syntaxVerifier.next(InputSymbol.ENCRYPTED_DATA)
|
||||
|
||||
val encDataList = packetInputStream!!.readEncryptedDataList()
|
||||
val esks = ESKsAndData(encDataList)
|
||||
|
||||
when (EncryptedDataPacketType.of(encDataList)!!) {
|
||||
EncryptedDataPacketType.SEIPDv2 ->
|
||||
LOGGER.debug(
|
||||
"Symmetrically Encrypted Integrity Protected Data Packet version 2 at depth " +
|
||||
"${layerMetadata.depth} encountered.")
|
||||
EncryptedDataPacketType.SEIPDv1 ->
|
||||
LOGGER.debug(
|
||||
"Symmetrically Encrypted Integrity Protected Data Packet version 1 at depth " +
|
||||
"${layerMetadata.depth} encountered.")
|
||||
EncryptedDataPacketType.LIBREPGP_OED ->
|
||||
LOGGER.debug(
|
||||
"LibrePGP OCB-Encrypted Data Packet at depth " +
|
||||
"${layerMetadata.depth} encountered.")
|
||||
EncryptedDataPacketType.SED -> {
|
||||
LOGGER.debug(
|
||||
"(Deprecated) Symmetrically Encrypted Data Packet at depth " +
|
||||
"${layerMetadata.depth} encountered.")
|
||||
LOGGER.warn("Symmetrically Encrypted Data Packet is not integrity-protected.")
|
||||
if (!options.isIgnoreMDCErrors()) {
|
||||
throw MessageNotIntegrityProtectedException()
|
||||
}
|
||||
if (encDataList.isEmpty) {
|
||||
LOGGER.debug("Missing encrypted session key packet.")
|
||||
return false
|
||||
}
|
||||
if (!encDataList.isIntegrityProtected && !encDataList.get(0).isAEAD) {
|
||||
LOGGER.warn("Symmetrically Encrypted Data Packet is not integrity-protected.")
|
||||
if (!options.isIgnoreMDCErrors()) {
|
||||
throw MessageNotIntegrityProtectedException()
|
||||
}
|
||||
}
|
||||
|
||||
val esks = ESKsAndData(encDataList)
|
||||
|
||||
LOGGER.debug(
|
||||
"Encrypted Data has ${esks.skesks.size} SKESK(s) and" +
|
||||
" ${esks.pkesks.size + esks.anonPkesks.size} PKESK(s) from which ${esks.anonPkesks.size} PKESK(s)" +
|
||||
|
@ -583,7 +591,14 @@ class OpenPgpMessageInputStream(
|
|||
pkesk: PGPPublicKeyEncryptedData
|
||||
): Boolean {
|
||||
try {
|
||||
val decrypted = pkesk.getDataStream(decryptorFactory)
|
||||
val decrypted =
|
||||
try {
|
||||
pkesk.getDataStream(decryptorFactory)
|
||||
} catch (e: ClassCastException) {
|
||||
throw PGPException(e.message)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw PGPException(e.message)
|
||||
}
|
||||
val sessionKey = SessionKey(pkesk.getSessionKey(decryptorFactory))
|
||||
throwIfUnacceptable(sessionKey.algorithm)
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.bouncycastle.openpgp.PGPOnePassSignature
|
|||
import org.bouncycastle.openpgp.PGPPadding
|
||||
import org.bouncycastle.openpgp.PGPSignature
|
||||
import org.pgpainless.algorithm.OpenPgpPacket
|
||||
import org.pgpainless.exception.MalformedOpenPgpMessageException
|
||||
|
||||
/**
|
||||
* Since we need to update signatures with data from the underlying stream, this class is used to
|
||||
|
@ -61,7 +62,12 @@ class TeeBCPGInputStream(inputStream: BCPGInputStream, outputStream: OutputStrea
|
|||
|
||||
fun readEncryptedDataList(): PGPEncryptedDataList {
|
||||
delayedTee.squeeze()
|
||||
return PGPEncryptedDataList(packetInputStream)
|
||||
return try {
|
||||
PGPEncryptedDataList(packetInputStream)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
// Mismatched SKESK / SEIPD version
|
||||
throw MalformedOpenPgpMessageException(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun readOnePassSignature(): PGPOnePassSignature {
|
||||
|
|
|
@ -15,6 +15,8 @@ import org.pgpainless.decryption_verification.syntax_check.State
|
|||
* @see [RFC4880 §11.3. OpenPGP Messages](https://www.rfc-editor.org/rfc/rfc4880#section-11.3)
|
||||
*/
|
||||
class MalformedOpenPgpMessageException : RuntimeException {
|
||||
constructor(cause: Throwable) : super(cause)
|
||||
|
||||
constructor(message: String) : super(message)
|
||||
|
||||
constructor(message: String, e: MalformedOpenPgpMessageException) : super(message, e)
|
||||
|
|
|
@ -165,13 +165,13 @@ class SignatureUtils {
|
|||
// having them compressed,
|
||||
// except for an attacker who is trying to exploit flaws in the decompression
|
||||
// algorithm.
|
||||
// Therefore, we ignore compressed data packets without attempting decompression.
|
||||
// Therefore, we ignore compressed data packets without attempting
|
||||
// decompression.
|
||||
if (nextObject is PGPCompressedData) {
|
||||
// getInputStream() does not do decompression, contrary to getDataStream().
|
||||
Streams.drain(
|
||||
(nextObject as PGPCompressedData)
|
||||
.inputStream
|
||||
) // Skip packet without decompressing
|
||||
.inputStream) // Skip packet without decompressing
|
||||
}
|
||||
|
||||
if (nextObject is PGPSignatureList) {
|
||||
|
|
|
@ -247,7 +247,8 @@ class ArmorUtils {
|
|||
.add(OpenPgpFingerprint.of(publicKey).prettyPrint())
|
||||
// Primary / First User ID
|
||||
(primary ?: first)?.let {
|
||||
headerMap.getOrPut(HEADER_COMMENT) { mutableSetOf() }
|
||||
headerMap
|
||||
.getOrPut(HEADER_COMMENT) { mutableSetOf() }
|
||||
.add(it.replace("\n", "\\n").replace("\r", "\\r"))
|
||||
}
|
||||
// X-1 further identities
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue