--- go/src/github.com/ProtonMail/gopenpgp/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go 2019-07-20 15:43:48.000000000 -0700 +++ go/src/github.com/ProtonMail/gopenpgp/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go 2019-07-20 15:53:58.000000000 -0700 @@ -121,6 +121,53 @@ } } +func parseGNUExtensions(r io.Reader) (f func(out, in []byte), err error) { + var buf [9]byte + + // A three-byte string identifier + _, err = io.ReadFull(r, buf[:3]) + if err != nil { + return + } + gnuExt := string(buf[:3]) + + if gnuExt != "GNU" { + return nil, errors.UnsupportedError("Malformed GNU extension: " + gnuExt) + } + _, err = io.ReadFull(r, buf[:1]) + if err != nil { + return + } + gnuExtType := int(buf[0]) + switch gnuExtType { + case 1: + return nil, nil + case 2: + // Read a serial number, which is prefixed by a 1-byte length. + // The maximum length is 16. + var lenBuf [1]byte + _, err = io.ReadFull(r, lenBuf[:]) + if err != nil { + return + } + + maxLen := 16 + ivLen := int(lenBuf[0]) + if ivLen > maxLen { + ivLen = maxLen + } + ivBuf := make([]byte, ivLen) + // For now we simply discard the IV + _, err = io.ReadFull(r, ivBuf) + if err != nil { + return + } + return nil, nil + default: + return nil, errors.UnsupportedError("unknown S2K GNU protection mode: " + strconv.Itoa(int(gnuExtType))) + } +} + // Iterated writes to out the result of computing the Iterated and Salted S2K // function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, // salt and iteration count. @@ -167,6 +214,12 @@ return } + // GNU Extensions; handle them before we try to look for a hash, which won't + // be needed in most cases anyway. + if buf[0] == 101 { + return parseGNUExtensions(r) + } + hash, ok := HashIdToHash(buf[1]) if !ok { return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) --- go/src/github.com/ProtonMail/gopenpgp/vendor/golang.org/x/crypto/openpgp/packet/private_key.go 2019-07-20 15:43:48.000000000 -0700 +++ go/src/github.com/ProtonMail/gopenpgp/vendor/golang.org/x/crypto/openpgp/packet/private_key.go 2019-07-20 16:26:05.000000000 -0700 @@ -154,6 +154,13 @@ if s2kType == 254 { pk.sha1Checksum = true } + // S2K == nil implies that we got a "GNU Dummy" S2K. For instance, + // because our master secret key is on a USB key in a vault somewhere. + // In that case, there is no further data to consume here. + if pk.s2k == nil { + pk.Encrypted = false + return + } default: return errors.UnsupportedError("deprecated s2k function in private key") }