Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionally allow messages without MDC #130

Merged
merged 4 commits into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions openpgp/packet/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ type Config struct {
// when producing a generic certification signature onto an existing user ID.
// The identity must be present in the signer Entity.
SigningIdentity string
// InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
// encrypted messages without Modification Detection Code (MDC).
// MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
// in most OpenPGP implementations. Messages without MDC are considered unnecessarily
// insecure and should be prevented whenever possible.
// In case one needs to deal with messages from very old OpenPGP implementations, there
// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
// mode of operation. It should be considered a measure of last resort.
InsecureAllowUnauthenticatedMessages bool
}

func (c *Config) Random() io.Reader {
Expand Down Expand Up @@ -186,3 +195,10 @@ func (c *Config) SigningUserId() string {
}
return c.SigningIdentity
}

func (c *Config) AllowUnauthenticatedMessages() bool {
if c == nil {
return false
}
return c.InsecureAllowUnauthenticatedMessages
}
2 changes: 0 additions & 2 deletions openpgp/packet/symmetrically_encrypted.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
if buf[0] != symmetricallyEncryptedVersion {
return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
}
} else {
return errors.UnsupportedError("Symmetrically encrypted packets without MDC are not supported")
}
se.Contents = r
return nil
Expand Down
10 changes: 8 additions & 2 deletions openpgp/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,14 @@ ParsePackets:
pubKeys = append(pubKeys, keyEnvelopePair{k, p})
}
}
case *packet.SymmetricallyEncrypted, *packet.AEADEncrypted:
edp = p.(packet.EncryptedDataPacket)
case *packet.SymmetricallyEncrypted:
if !p.MDC && !config.AllowUnauthenticatedMessages() {
return nil, errors.UnsupportedError("message is not authenticated")
}
edp = p
break ParsePackets
case *packet.AEADEncrypted:
edp = p
break ParsePackets
case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
// This message isn't encrypted.
Expand Down
53 changes: 53 additions & 0 deletions openpgp/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -716,3 +716,56 @@ func TestCorruptedMessageWrongLength(t *testing.T) {
t.Errorf("Expected error '%s', but got error '%s'", expectedErr, err)
}
}

func TestMessageWithoutMdc(t *testing.T) {
armored, err := os.Open("test_data/aead-ocb-asym-key.asc")
if err != nil {
t.Fatal(err)
}
defer armored.Close()

el, err := ReadArmoredKeyRing(armored)
if err != nil {
t.Fatal(err)
}

armoredMessageWithoutMdc, err := ioutil.ReadFile("test_data/sym-message-without-mdc.asc")
if err != nil {
t.Fatal(err)
}

t.Run("fails with InsecureAllowUnauthenticatedMessages disabled", func(t *testing.T) {
messageWithoutMdc, err := armor.Decode(bytes.NewReader(armoredMessageWithoutMdc))
if err != nil {
t.Fatal(err)
}

_, err = ReadMessage(messageWithoutMdc.Body, el, nil, nil)
if err == nil {
t.Fatal("reading the message should have failed")
}
})

t.Run("succeeds with InsecureAllowUnauthenticatedMessages enabled", func(t *testing.T) {
messageWithoutMdc, err := armor.Decode(bytes.NewReader(armoredMessageWithoutMdc))
if err != nil {
t.Fatal(err)
}

md, err := ReadMessage(messageWithoutMdc.Body, el, nil, &packet.Config{
InsecureAllowUnauthenticatedMessages: true,
})
if err != nil {
t.Fatal("reading the message should have worked")
}

b, err := ioutil.ReadAll(md.UnverifiedBody)
if err != nil {
t.Fatal("reading the message should have worked")
}

if !bytes.Equal(b, []byte("message without mdc\n")) {
t.Error("unexpected message content")
}
})
}
8 changes: 8 additions & 0 deletions openpgp/test_data/sym-message-without-mdc.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN PGP MESSAGE-----

hF4DaLVM+JXUh9ESAQdA7E42KKhtMn7vjYN+CIcoM4QMXODako4DQPYLwhYjHTow
hBVmQWk+WyyDjqB2yZEJPVTDYSvebBynwCGN9AFR6u5dXjFqtNNX6EJEJBzLLL2+
yUMNiMt8/ujn4y4GNaZEbFdf4+K/oQbz6fvQgNipWZGg2Ys0foHi50EzhTDyVG7s
nwkVrIpSuhaZLoqzxbizw5o6YVMc
=//7h
-----END PGP MESSAGE-----