forked from toolshed/abra
chore: make deps, go mod vendor
This commit is contained in:
115
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
115
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
@ -46,6 +46,7 @@ type MessageDetails struct {
|
||||
DecryptedWith Key // the private key used to decrypt the message, if any.
|
||||
IsSigned bool // true if the message is signed.
|
||||
SignedByKeyId uint64 // the key id of the signer, if any.
|
||||
SignedByFingerprint []byte // the key fingerprint of the signer, if any.
|
||||
SignedBy *Key // the key of the signer, if available.
|
||||
LiteralData *packet.LiteralData // the metadata of the contents
|
||||
UnverifiedBody io.Reader // the contents of the message.
|
||||
@ -117,7 +118,7 @@ ParsePackets:
|
||||
// This packet contains the decryption key encrypted to a public key.
|
||||
md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
|
||||
switch p.Algo {
|
||||
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH:
|
||||
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH, packet.PubKeyAlgoX25519, packet.PubKeyAlgoX448:
|
||||
break
|
||||
default:
|
||||
continue
|
||||
@ -232,7 +233,7 @@ FindKey:
|
||||
}
|
||||
mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config)
|
||||
if sensitiveParsingErr != nil {
|
||||
return nil, errors.StructuralError("parsing error")
|
||||
return nil, errors.HandleSensitiveParsingError(sensitiveParsingErr, md.decrypted != nil)
|
||||
}
|
||||
return mdFinal, nil
|
||||
}
|
||||
@ -270,13 +271,17 @@ FindLiteralData:
|
||||
prevLast = true
|
||||
}
|
||||
|
||||
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
|
||||
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType, p.Salt)
|
||||
if err != nil {
|
||||
md.SignatureError = err
|
||||
}
|
||||
|
||||
md.IsSigned = true
|
||||
if p.Version == 6 {
|
||||
md.SignedByFingerprint = p.KeyFingerprint
|
||||
}
|
||||
md.SignedByKeyId = p.KeyId
|
||||
|
||||
if keyring != nil {
|
||||
keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
@ -292,7 +297,7 @@ FindLiteralData:
|
||||
if md.IsSigned && md.SignatureError == nil {
|
||||
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config}
|
||||
} else if md.decrypted != nil {
|
||||
md.UnverifiedBody = checkReader{md}
|
||||
md.UnverifiedBody = &checkReader{md, false}
|
||||
} else {
|
||||
md.UnverifiedBody = md.LiteralData.Body
|
||||
}
|
||||
@ -300,12 +305,22 @@ FindLiteralData:
|
||||
return md, nil
|
||||
}
|
||||
|
||||
func wrapHashForSignature(hashFunc hash.Hash, sigType packet.SignatureType) (hash.Hash, error) {
|
||||
switch sigType {
|
||||
case packet.SigTypeBinary:
|
||||
return hashFunc, nil
|
||||
case packet.SigTypeText:
|
||||
return NewCanonicalTextHash(hashFunc), nil
|
||||
}
|
||||
return nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
|
||||
}
|
||||
|
||||
// hashForSignature returns a pair of hashes that can be used to verify a
|
||||
// signature. The signature may specify that the contents of the signed message
|
||||
// should be preprocessed (i.e. to normalize line endings). Thus this function
|
||||
// returns two hashes. The second should be used to hash the message itself and
|
||||
// performs any needed preprocessing.
|
||||
func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
|
||||
func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType, sigSalt []byte) (hash.Hash, hash.Hash, error) {
|
||||
if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok {
|
||||
return nil, nil, errors.UnsupportedError("unsupported hash function")
|
||||
}
|
||||
@ -313,14 +328,19 @@ func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.
|
||||
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc)))
|
||||
}
|
||||
h := hashFunc.New()
|
||||
|
||||
if sigSalt != nil {
|
||||
h.Write(sigSalt)
|
||||
}
|
||||
wrappedHash, err := wrapHashForSignature(h, sigType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
switch sigType {
|
||||
case packet.SigTypeBinary:
|
||||
return h, h, nil
|
||||
return h, wrappedHash, nil
|
||||
case packet.SigTypeText:
|
||||
return h, NewCanonicalTextHash(h), nil
|
||||
return h, wrappedHash, nil
|
||||
}
|
||||
|
||||
return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
|
||||
}
|
||||
|
||||
@ -328,21 +348,27 @@ func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType) (hash.
|
||||
// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
|
||||
// MDC checks.
|
||||
type checkReader struct {
|
||||
md *MessageDetails
|
||||
md *MessageDetails
|
||||
checked bool
|
||||
}
|
||||
|
||||
func (cr checkReader) Read(buf []byte) (int, error) {
|
||||
func (cr *checkReader) Read(buf []byte) (int, error) {
|
||||
n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf)
|
||||
if sensitiveParsingError == io.EOF {
|
||||
if cr.checked {
|
||||
// Only check once
|
||||
return n, io.EOF
|
||||
}
|
||||
mdcErr := cr.md.decrypted.Close()
|
||||
if mdcErr != nil {
|
||||
return n, mdcErr
|
||||
}
|
||||
cr.checked = true
|
||||
return n, io.EOF
|
||||
}
|
||||
|
||||
if sensitiveParsingError != nil {
|
||||
return n, errors.StructuralError("parsing error")
|
||||
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
|
||||
}
|
||||
|
||||
return n, nil
|
||||
@ -366,6 +392,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
scr.wrappedHash.Write(buf[:n])
|
||||
}
|
||||
|
||||
readsDecryptedData := scr.md.decrypted != nil
|
||||
if sensitiveParsingError == io.EOF {
|
||||
var p packet.Packet
|
||||
var readError error
|
||||
@ -384,7 +411,7 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
key := scr.md.SignedBy
|
||||
signatureError := key.PublicKey.VerifySignature(scr.h, sig)
|
||||
if signatureError == nil {
|
||||
signatureError = checkSignatureDetails(key, sig, scr.config)
|
||||
signatureError = checkMessageSignatureDetails(key, sig, scr.config)
|
||||
}
|
||||
scr.md.Signature = sig
|
||||
scr.md.SignatureError = signatureError
|
||||
@ -408,16 +435,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
// unsigned hash of its own. In order to check this we need to
|
||||
// close that Reader.
|
||||
if scr.md.decrypted != nil {
|
||||
mdcErr := scr.md.decrypted.Close()
|
||||
if mdcErr != nil {
|
||||
return n, mdcErr
|
||||
if sensitiveParsingError := scr.md.decrypted.Close(); sensitiveParsingError != nil {
|
||||
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
|
||||
}
|
||||
}
|
||||
return n, io.EOF
|
||||
}
|
||||
|
||||
if sensitiveParsingError != nil {
|
||||
return n, errors.StructuralError("parsing error")
|
||||
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, readsDecryptedData)
|
||||
}
|
||||
|
||||
return n, nil
|
||||
@ -428,14 +454,13 @@ func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
|
||||
// if any, and a possible signature verification error.
|
||||
// If the signer isn't known, ErrUnknownIssuer is returned.
|
||||
func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
return verifyDetachedSignature(keyring, signed, signature, nil, false, config)
|
||||
}
|
||||
|
||||
// VerifyDetachedSignatureAndHash performs the same actions as
|
||||
// VerifyDetachedSignature and checks that the expected hash functions were used.
|
||||
func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
|
||||
}
|
||||
|
||||
// CheckDetachedSignature takes a signed file and a detached signature and
|
||||
@ -443,25 +468,24 @@ func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader
|
||||
// signature verification error. If the signer isn't known,
|
||||
// ErrUnknownIssuer is returned.
|
||||
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
|
||||
var expectedHashes []crypto.Hash
|
||||
return CheckDetachedSignatureAndHash(keyring, signed, signature, expectedHashes, config)
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, nil, false, config)
|
||||
return
|
||||
}
|
||||
|
||||
// CheckDetachedSignatureAndHash performs the same actions as
|
||||
// CheckDetachedSignature and checks that the expected hash functions were used.
|
||||
func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, config)
|
||||
_, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
|
||||
return
|
||||
}
|
||||
|
||||
func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, checkHashes bool, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
|
||||
var issuerKeyId uint64
|
||||
var hashFunc crypto.Hash
|
||||
var sigType packet.SignatureType
|
||||
var keys []Key
|
||||
var p packet.Packet
|
||||
|
||||
expectedHashesLen := len(expectedHashes)
|
||||
packets := packet.NewReader(signature)
|
||||
for {
|
||||
p, err = packets.Next()
|
||||
@ -483,16 +507,19 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
|
||||
issuerKeyId = *sig.IssuerKeyId
|
||||
hashFunc = sig.Hash
|
||||
sigType = sig.SigType
|
||||
|
||||
for i, expectedHash := range expectedHashes {
|
||||
if hashFunc == expectedHash {
|
||||
break
|
||||
if checkHashes {
|
||||
matchFound := false
|
||||
// check for hashes
|
||||
for _, expectedHash := range expectedHashes {
|
||||
if hashFunc == expectedHash {
|
||||
matchFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if i+1 == expectedHashesLen {
|
||||
return nil, nil, errors.StructuralError("hash algorithm mismatch with cleartext message headers")
|
||||
if !matchFound {
|
||||
return nil, nil, errors.StructuralError("hash algorithm or salt mismatch with cleartext message headers")
|
||||
}
|
||||
}
|
||||
|
||||
keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
|
||||
if len(keys) > 0 {
|
||||
break
|
||||
@ -503,7 +530,11 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
h, wrappedHash, err := hashForSignature(hashFunc, sigType)
|
||||
h, err := sig.PrepareVerify()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
wrappedHash, err := wrapHashForSignature(h, sigType)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -515,7 +546,7 @@ func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expec
|
||||
for _, key := range keys {
|
||||
err = key.PublicKey.VerifySignature(h, sig)
|
||||
if err == nil {
|
||||
return sig, key.Entity, checkSignatureDetails(&key, sig, config)
|
||||
return sig, key.Entity, checkMessageSignatureDetails(&key, sig, config)
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,7 +564,7 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
|
||||
return CheckDetachedSignature(keyring, signed, body, config)
|
||||
}
|
||||
|
||||
// checkSignatureDetails returns an error if:
|
||||
// checkMessageSignatureDetails returns an error if:
|
||||
// - The signature (or one of the binding signatures mentioned below)
|
||||
// has a unknown critical notation data subpacket
|
||||
// - The primary key of the signing entity is revoked
|
||||
@ -551,15 +582,11 @@ func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader,
|
||||
// NOTE: The order of these checks is important, as the caller may choose to
|
||||
// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never
|
||||
// ignore any other errors.
|
||||
//
|
||||
// TODO: Also return an error if:
|
||||
// - The primary key is expired according to a direct-key signature
|
||||
// - (For V5 keys only:) The direct-key signature (exists and) is expired
|
||||
func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
|
||||
func checkMessageSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
|
||||
now := config.Now()
|
||||
primaryIdentity := key.Entity.PrimaryIdentity()
|
||||
primarySelfSignature, primaryIdentity := key.Entity.PrimarySelfSignature()
|
||||
signedBySubKey := key.PublicKey != key.Entity.PrimaryKey
|
||||
sigsToCheck := []*packet.Signature{signature, primaryIdentity.SelfSignature}
|
||||
sigsToCheck := []*packet.Signature{signature, primarySelfSignature}
|
||||
if signedBySubKey {
|
||||
sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature)
|
||||
}
|
||||
@ -572,10 +599,10 @@ func checkSignatureDetails(key *Key, signature *packet.Signature, config *packet
|
||||
}
|
||||
if key.Entity.Revoked(now) || // primary key is revoked
|
||||
(signedBySubKey && key.Revoked(now)) || // subkey is revoked
|
||||
primaryIdentity.Revoked(now) { // primary identity is revoked
|
||||
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // primary identity is revoked for v4
|
||||
return errors.ErrKeyRevoked
|
||||
}
|
||||
if key.Entity.PrimaryKey.KeyExpired(primaryIdentity.SelfSignature, now) { // primary key is expired
|
||||
if key.Entity.PrimaryKey.KeyExpired(primarySelfSignature, now) { // primary key is expired
|
||||
return errors.ErrKeyExpired
|
||||
}
|
||||
if signedBySubKey {
|
||||
|
Reference in New Issue
Block a user