2022-08-26 22:26:53 +02:00
|
|
|
// Copyright 2011 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package packet
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"github.com/ProtonMail/go-crypto/openpgp/errors"
|
|
|
|
)
|
|
|
|
|
2023-12-13 14:29:02 +01:00
|
|
|
const aeadSaltSize = 32
|
|
|
|
|
2022-08-26 22:26:53 +02:00
|
|
|
// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
|
|
|
|
// encrypted Contents will consist of more OpenPGP packets. See RFC 4880,
|
|
|
|
// sections 5.7 and 5.13.
|
|
|
|
type SymmetricallyEncrypted struct {
|
2023-12-13 14:29:02 +01:00
|
|
|
Version int
|
|
|
|
Contents io.Reader // contains tag for version 2
|
|
|
|
IntegrityProtected bool // If true it is type 18 (with MDC or AEAD). False is packet type 9
|
|
|
|
|
|
|
|
// Specific to version 1
|
|
|
|
prefix []byte
|
|
|
|
|
|
|
|
// Specific to version 2
|
|
|
|
Cipher CipherFunction
|
|
|
|
Mode AEADMode
|
|
|
|
ChunkSizeByte byte
|
|
|
|
Salt [aeadSaltSize]byte
|
2022-08-26 22:26:53 +02:00
|
|
|
}
|
|
|
|
|
2023-12-13 14:29:02 +01:00
|
|
|
const (
|
|
|
|
symmetricallyEncryptedVersionMdc = 1
|
|
|
|
symmetricallyEncryptedVersionAead = 2
|
|
|
|
)
|
2022-08-26 22:26:53 +02:00
|
|
|
|
|
|
|
func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
|
2023-12-13 14:29:02 +01:00
|
|
|
if se.IntegrityProtected {
|
2022-08-26 22:26:53 +02:00
|
|
|
// See RFC 4880, section 5.13.
|
|
|
|
var buf [1]byte
|
|
|
|
_, err := readFull(r, buf[:])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-12-13 14:29:02 +01:00
|
|
|
|
|
|
|
switch buf[0] {
|
|
|
|
case symmetricallyEncryptedVersionMdc:
|
|
|
|
se.Version = symmetricallyEncryptedVersionMdc
|
|
|
|
case symmetricallyEncryptedVersionAead:
|
|
|
|
se.Version = symmetricallyEncryptedVersionAead
|
|
|
|
if err := se.parseAead(r); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
default:
|
2022-08-26 22:26:53 +02:00
|
|
|
return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
se.Contents = r
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decrypt returns a ReadCloser, from which the decrypted Contents of the
|
|
|
|
// packet can be read. An incorrect key will only be detected after trying
|
|
|
|
// to decrypt the entire data.
|
|
|
|
func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
|
2023-12-13 14:29:02 +01:00
|
|
|
if se.Version == symmetricallyEncryptedVersionAead {
|
|
|
|
return se.decryptAead(key)
|
2022-08-26 22:26:53 +02:00
|
|
|
}
|
|
|
|
|
2023-12-13 14:29:02 +01:00
|
|
|
return se.decryptMdc(c, key)
|
2022-08-26 22:26:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
|
|
|
|
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
|
|
|
|
// written.
|
|
|
|
// If config is nil, sensible defaults will be used.
|
2023-12-13 14:29:02 +01:00
|
|
|
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, aeadSupported bool, cipherSuite CipherSuite, key []byte, config *Config) (Contents io.WriteCloser, err error) {
|
2022-08-26 22:26:53 +02:00
|
|
|
writeCloser := noOpCloser{w}
|
2023-12-13 14:29:02 +01:00
|
|
|
ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedIntegrityProtected)
|
2022-08-26 22:26:53 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-12-13 14:29:02 +01:00
|
|
|
if aeadSupported {
|
|
|
|
return serializeSymmetricallyEncryptedAead(ciphertext, cipherSuite, config.AEADConfig.ChunkSizeByte(), config.Random(), key)
|
2022-08-26 22:26:53 +02:00
|
|
|
}
|
|
|
|
|
2023-12-13 14:29:02 +01:00
|
|
|
return serializeSymmetricallyEncryptedMdc(ciphertext, c, key, config)
|
2022-08-26 22:26:53 +02:00
|
|
|
}
|