mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-07 09:36:44 +00:00
![Paddy](/assets/img/avatar_default.png)
Switch to using Go modules. This migrates our vendor.json to use Go 1.11's modules system, and replaces the vendor folder with the output of go mod vendor. The vendored code should remain basically the same; I believe some tree shaking of packages and support scripts/licenses/READMEs/etc. happened. This also fixes Travis and our Makefile to no longer use govendor.
159 lines
4.8 KiB
Go
159 lines
4.8 KiB
Go
// 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 (
|
|
"bytes"
|
|
"crypto/cipher"
|
|
"io"
|
|
"strconv"
|
|
|
|
"github.com/keybase/go-crypto/openpgp/errors"
|
|
"github.com/keybase/go-crypto/openpgp/s2k"
|
|
)
|
|
|
|
// This is the largest session key that we'll support. Since no 512-bit cipher
|
|
// has even been seriously used, this is comfortably large.
|
|
const maxSessionKeySizeInBytes = 64
|
|
|
|
// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
|
|
// 4880, section 5.3.
|
|
type SymmetricKeyEncrypted struct {
|
|
CipherFunc CipherFunction
|
|
s2k func(out, in []byte)
|
|
encryptedKey []byte
|
|
}
|
|
|
|
const symmetricKeyEncryptedVersion = 4
|
|
|
|
func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
|
|
// RFC 4880, section 5.3.
|
|
var buf [2]byte
|
|
if _, err := readFull(r, buf[:]); err != nil {
|
|
return err
|
|
}
|
|
if buf[0] != symmetricKeyEncryptedVersion {
|
|
return errors.UnsupportedError("SymmetricKeyEncrypted version")
|
|
}
|
|
ske.CipherFunc = CipherFunction(buf[1])
|
|
|
|
if ske.CipherFunc.KeySize() == 0 {
|
|
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
|
|
}
|
|
|
|
var err error
|
|
ske.s2k, err = s2k.Parse(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if ske.s2k == nil {
|
|
return errors.UnsupportedError("can't use dummy S2K for symmetric key encryption")
|
|
}
|
|
|
|
encryptedKey := make([]byte, maxSessionKeySizeInBytes)
|
|
// The session key may follow. We just have to try and read to find
|
|
// out. If it exists then we limit it to maxSessionKeySizeInBytes.
|
|
n, err := readFull(r, encryptedKey)
|
|
if err != nil && err != io.ErrUnexpectedEOF {
|
|
return err
|
|
}
|
|
|
|
if n != 0 {
|
|
if n == maxSessionKeySizeInBytes {
|
|
return errors.UnsupportedError("oversized encrypted session key")
|
|
}
|
|
ske.encryptedKey = encryptedKey[:n]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Decrypt attempts to decrypt an encrypted session key and returns the key and
|
|
// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
|
|
// packet.
|
|
func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
|
|
key := make([]byte, ske.CipherFunc.KeySize())
|
|
ske.s2k(key, passphrase)
|
|
|
|
if len(ske.encryptedKey) == 0 {
|
|
return key, ske.CipherFunc, nil
|
|
}
|
|
|
|
// the IV is all zeros
|
|
iv := make([]byte, ske.CipherFunc.blockSize())
|
|
c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
|
|
plaintextKey := make([]byte, len(ske.encryptedKey))
|
|
c.XORKeyStream(plaintextKey, ske.encryptedKey)
|
|
cipherFunc := CipherFunction(plaintextKey[0])
|
|
if cipherFunc.blockSize() == 0 {
|
|
return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
|
}
|
|
plaintextKey = plaintextKey[1:]
|
|
if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() {
|
|
return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " +
|
|
"not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")")
|
|
}
|
|
return plaintextKey, cipherFunc, nil
|
|
}
|
|
|
|
// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
|
|
// packet contains a random session key, encrypted by a key derived from the
|
|
// given passphrase. The session key is returned and must be passed to
|
|
// SerializeSymmetricallyEncrypted.
|
|
// If config is nil, sensible defaults will be used.
|
|
func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
|
|
cipherFunc := config.Cipher()
|
|
keySize := cipherFunc.KeySize()
|
|
if keySize == 0 {
|
|
return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
|
|
}
|
|
|
|
s2kBuf := new(bytes.Buffer)
|
|
keyEncryptingKey := make([]byte, keySize)
|
|
// s2k.Serialize salts and stretches the passphrase, and writes the
|
|
// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
|
|
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
|
|
if err != nil {
|
|
return
|
|
}
|
|
s2kBytes := s2kBuf.Bytes()
|
|
|
|
packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
|
|
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var buf [2]byte
|
|
buf[0] = symmetricKeyEncryptedVersion
|
|
buf[1] = byte(cipherFunc)
|
|
_, err = w.Write(buf[:])
|
|
if err != nil {
|
|
return
|
|
}
|
|
_, err = w.Write(s2kBytes)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
sessionKey := make([]byte, keySize)
|
|
_, err = io.ReadFull(config.Random(), sessionKey)
|
|
if err != nil {
|
|
return
|
|
}
|
|
iv := make([]byte, cipherFunc.blockSize())
|
|
c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
|
|
encryptedCipherAndKey := make([]byte, keySize+1)
|
|
c.XORKeyStream(encryptedCipherAndKey, buf[1:])
|
|
c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
|
|
_, err = w.Write(encryptedCipherAndKey)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
key = sessionKey
|
|
return
|
|
}
|