2022-10-27 11:56:10 +02:00
|
|
|
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
package org.pgpainless.decryption_verification.syntax_check;
|
|
|
|
|
|
|
|
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
|
|
|
|
2022-10-27 12:42:30 +02:00
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
|
2022-10-27 12:07:22 +02:00
|
|
|
/**
|
|
|
|
* This class describes the syntax for OpenPGP messages as specified by rfc4880.
|
|
|
|
*
|
|
|
|
* @see <a href="https://www.rfc-editor.org/rfc/rfc4880#section-11.3">
|
|
|
|
* rfc4880 - §11.3. OpenPGP Messages</a>
|
|
|
|
* @see <a href="https://blog.jabberhead.tk/2022/09/14/using-pushdown-automata-to-verify-packet-sequences/">
|
|
|
|
* Blog post about theoretic background and translation of grammar to PDA syntax</a>
|
|
|
|
* @see <a href="https://blog.jabberhead.tk/2022/10/26/implementing-packet-sequence-validation-using-pushdown-automata/">
|
|
|
|
* Blog post about practically implementing the PDA for packet syntax validation</a>
|
|
|
|
*/
|
2022-10-27 11:56:10 +02:00
|
|
|
public class OpenPgpMessageSyntax implements Syntax {
|
|
|
|
|
|
|
|
@Override
|
2022-10-27 12:42:30 +02:00
|
|
|
public @Nonnull Transition transition(@Nonnull State from, @Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
2022-10-27 11:56:10 +02:00
|
|
|
throws MalformedOpenPgpMessageException {
|
|
|
|
switch (from) {
|
|
|
|
case OpenPgpMessage:
|
|
|
|
return fromOpenPgpMessage(input, stackItem);
|
|
|
|
case LiteralMessage:
|
|
|
|
return fromLiteralMessage(input, stackItem);
|
|
|
|
case CompressedMessage:
|
|
|
|
return fromCompressedMessage(input, stackItem);
|
|
|
|
case EncryptedMessage:
|
|
|
|
return fromEncryptedMessage(input, stackItem);
|
|
|
|
case Valid:
|
|
|
|
return fromValid(input, stackItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new MalformedOpenPgpMessageException(from, input, stackItem);
|
|
|
|
}
|
|
|
|
|
2022-11-25 14:38:45 +01:00
|
|
|
@Nonnull
|
2022-10-27 12:42:30 +02:00
|
|
|
Transition fromOpenPgpMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
2022-10-27 11:56:10 +02:00
|
|
|
throws MalformedOpenPgpMessageException {
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem != StackSymbol.msg) {
|
2022-10-27 11:56:10 +02:00
|
|
|
throw new MalformedOpenPgpMessageException(State.OpenPgpMessage, input, stackItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (input) {
|
|
|
|
case LiteralData:
|
|
|
|
return new Transition(State.LiteralMessage);
|
|
|
|
|
|
|
|
case Signature:
|
2022-10-27 12:07:22 +02:00
|
|
|
return new Transition(State.OpenPgpMessage, StackSymbol.msg);
|
2022-10-27 11:56:10 +02:00
|
|
|
|
|
|
|
case OnePassSignature:
|
2022-10-27 12:07:22 +02:00
|
|
|
return new Transition(State.OpenPgpMessage, StackSymbol.ops, StackSymbol.msg);
|
2022-10-27 11:56:10 +02:00
|
|
|
|
|
|
|
case CompressedData:
|
|
|
|
return new Transition(State.CompressedMessage);
|
|
|
|
|
|
|
|
case EncryptedData:
|
|
|
|
return new Transition(State.EncryptedMessage);
|
|
|
|
|
|
|
|
case EndOfSequence:
|
|
|
|
default:
|
|
|
|
throw new MalformedOpenPgpMessageException(State.OpenPgpMessage, input, stackItem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-25 14:38:45 +01:00
|
|
|
@Nonnull
|
2022-10-27 12:42:30 +02:00
|
|
|
Transition fromLiteralMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
2022-10-27 11:56:10 +02:00
|
|
|
throws MalformedOpenPgpMessageException {
|
|
|
|
switch (input) {
|
|
|
|
case Signature:
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem == StackSymbol.ops) {
|
2022-10-27 11:56:10 +02:00
|
|
|
return new Transition(State.LiteralMessage);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EndOfSequence:
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem == StackSymbol.terminus) {
|
2022-10-27 11:56:10 +02:00
|
|
|
return new Transition(State.Valid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new MalformedOpenPgpMessageException(State.LiteralMessage, input, stackItem);
|
|
|
|
}
|
|
|
|
|
2022-11-25 14:38:45 +01:00
|
|
|
@Nonnull
|
2022-10-27 12:42:30 +02:00
|
|
|
Transition fromCompressedMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
2022-10-27 11:56:10 +02:00
|
|
|
throws MalformedOpenPgpMessageException {
|
|
|
|
switch (input) {
|
|
|
|
case Signature:
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem == StackSymbol.ops) {
|
2022-10-27 11:56:10 +02:00
|
|
|
return new Transition(State.CompressedMessage);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EndOfSequence:
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem == StackSymbol.terminus) {
|
2022-10-27 11:56:10 +02:00
|
|
|
return new Transition(State.Valid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new MalformedOpenPgpMessageException(State.CompressedMessage, input, stackItem);
|
|
|
|
}
|
|
|
|
|
2022-11-25 14:38:45 +01:00
|
|
|
@Nonnull
|
2022-10-27 12:42:30 +02:00
|
|
|
Transition fromEncryptedMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
2022-10-27 11:56:10 +02:00
|
|
|
throws MalformedOpenPgpMessageException {
|
|
|
|
switch (input) {
|
|
|
|
case Signature:
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem == StackSymbol.ops) {
|
2022-10-27 11:56:10 +02:00
|
|
|
return new Transition(State.EncryptedMessage);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EndOfSequence:
|
2022-10-27 12:07:22 +02:00
|
|
|
if (stackItem == StackSymbol.terminus) {
|
2022-10-27 11:56:10 +02:00
|
|
|
return new Transition(State.Valid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new MalformedOpenPgpMessageException(State.EncryptedMessage, input, stackItem);
|
|
|
|
}
|
|
|
|
|
2022-11-25 14:38:45 +01:00
|
|
|
@Nonnull
|
2022-10-27 12:42:30 +02:00
|
|
|
Transition fromValid(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
2022-10-27 11:56:10 +02:00
|
|
|
throws MalformedOpenPgpMessageException {
|
2023-05-01 09:35:28 +02:00
|
|
|
if (input == InputSymbol.EndOfSequence) {
|
|
|
|
// allow subsequent read() calls.
|
|
|
|
return new Transition(State.Valid);
|
|
|
|
}
|
2022-10-27 12:07:22 +02:00
|
|
|
// There is no applicable transition rule out of Valid
|
2022-10-27 11:56:10 +02:00
|
|
|
throw new MalformedOpenPgpMessageException(State.Valid, input, stackItem);
|
|
|
|
}
|
|
|
|
}
|