aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/theupdateframework
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/theupdateframework')
-rw-r--r--vendor/github.com/theupdateframework/go-tuf/LICENSE27
-rw-r--r--vendor/github.com/theupdateframework/go-tuf/encrypted/encrypted.go226
2 files changed, 253 insertions, 0 deletions
diff --git a/vendor/github.com/theupdateframework/go-tuf/LICENSE b/vendor/github.com/theupdateframework/go-tuf/LICENSE
new file mode 100644
index 000000000..38163dd4b
--- /dev/null
+++ b/vendor/github.com/theupdateframework/go-tuf/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2014-2020 Prime Directive, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Prime Directive, Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/theupdateframework/go-tuf/encrypted/encrypted.go b/vendor/github.com/theupdateframework/go-tuf/encrypted/encrypted.go
new file mode 100644
index 000000000..4d174d61f
--- /dev/null
+++ b/vendor/github.com/theupdateframework/go-tuf/encrypted/encrypted.go
@@ -0,0 +1,226 @@
+// Package encrypted provides a simple, secure system for encrypting data
+// symmetrically with a passphrase.
+//
+// It uses scrypt derive a key from the passphrase and the NaCl secret box
+// cipher for authenticated encryption.
+package encrypted
+
+import (
+ "crypto/rand"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/nacl/secretbox"
+ "golang.org/x/crypto/scrypt"
+)
+
+const saltSize = 32
+
+const (
+ boxKeySize = 32
+ boxNonceSize = 24
+)
+
+const (
+ // N parameter was chosen to be ~100ms of work using the default implementation
+ // on the 2.3GHz Core i7 Haswell processor in a late-2013 Apple Retina Macbook
+ // Pro (it takes ~113ms).
+ scryptN = 32768
+ scryptR = 8
+ scryptP = 1
+)
+
+const (
+ nameScrypt = "scrypt"
+ nameSecretBox = "nacl/secretbox"
+)
+
+type data struct {
+ KDF scryptKDF `json:"kdf"`
+ Cipher secretBoxCipher `json:"cipher"`
+ Ciphertext []byte `json:"ciphertext"`
+}
+
+type scryptParams struct {
+ N int `json:"N"`
+ R int `json:"r"`
+ P int `json:"p"`
+}
+
+func newScryptKDF() (scryptKDF, error) {
+ salt := make([]byte, saltSize)
+ if err := fillRandom(salt); err != nil {
+ return scryptKDF{}, err
+ }
+ return scryptKDF{
+ Name: nameScrypt,
+ Params: scryptParams{
+ N: scryptN,
+ R: scryptR,
+ P: scryptP,
+ },
+ Salt: salt,
+ }, nil
+}
+
+type scryptKDF struct {
+ Name string `json:"name"`
+ Params scryptParams `json:"params"`
+ Salt []byte `json:"salt"`
+}
+
+func (s *scryptKDF) Key(passphrase []byte) ([]byte, error) {
+ return scrypt.Key(passphrase, s.Salt, s.Params.N, s.Params.R, s.Params.P, boxKeySize)
+}
+
+// CheckParams checks that the encoded KDF parameters are what we expect them to
+// be. If we do not do this, an attacker could cause a DoS by tampering with
+// them.
+func (s *scryptKDF) CheckParams() error {
+ if s.Params.N != scryptN || s.Params.R != scryptR || s.Params.P != scryptP {
+ return errors.New("encrypted: unexpected kdf parameters")
+ }
+ return nil
+}
+
+func newSecretBoxCipher() (secretBoxCipher, error) {
+ nonce := make([]byte, boxNonceSize)
+ if err := fillRandom(nonce); err != nil {
+ return secretBoxCipher{}, err
+ }
+ return secretBoxCipher{
+ Name: nameSecretBox,
+ Nonce: nonce,
+ }, nil
+}
+
+type secretBoxCipher struct {
+ Name string `json:"name"`
+ Nonce []byte `json:"nonce"`
+
+ encrypted bool
+}
+
+func (s *secretBoxCipher) Encrypt(plaintext, key []byte) []byte {
+ var keyBytes [boxKeySize]byte
+ var nonceBytes [boxNonceSize]byte
+
+ if len(key) != len(keyBytes) {
+ panic("incorrect key size")
+ }
+ if len(s.Nonce) != len(nonceBytes) {
+ panic("incorrect nonce size")
+ }
+
+ copy(keyBytes[:], key)
+ copy(nonceBytes[:], s.Nonce)
+
+ // ensure that we don't re-use nonces
+ if s.encrypted {
+ panic("Encrypt must only be called once for each cipher instance")
+ }
+ s.encrypted = true
+
+ return secretbox.Seal(nil, plaintext, &nonceBytes, &keyBytes)
+}
+
+func (s *secretBoxCipher) Decrypt(ciphertext, key []byte) ([]byte, error) {
+ var keyBytes [boxKeySize]byte
+ var nonceBytes [boxNonceSize]byte
+
+ if len(key) != len(keyBytes) {
+ panic("incorrect key size")
+ }
+ if len(s.Nonce) != len(nonceBytes) {
+ // return an error instead of panicking since the nonce is user input
+ return nil, errors.New("encrypted: incorrect nonce size")
+ }
+
+ copy(keyBytes[:], key)
+ copy(nonceBytes[:], s.Nonce)
+
+ res, ok := secretbox.Open(nil, ciphertext, &nonceBytes, &keyBytes)
+ if !ok {
+ return nil, errors.New("encrypted: decryption failed")
+ }
+ return res, nil
+}
+
+// Encrypt takes a passphrase and plaintext, and returns a JSON object
+// containing ciphertext and the details necessary to decrypt it.
+func Encrypt(plaintext, passphrase []byte) ([]byte, error) {
+ k, err := newScryptKDF()
+ if err != nil {
+ return nil, err
+ }
+ key, err := k.Key(passphrase)
+ if err != nil {
+ return nil, err
+ }
+
+ c, err := newSecretBoxCipher()
+ if err != nil {
+ return nil, err
+ }
+
+ data := &data{
+ KDF: k,
+ Cipher: c,
+ }
+ data.Ciphertext = c.Encrypt(plaintext, key)
+
+ return json.Marshal(data)
+}
+
+// Marshal encrypts the JSON encoding of v using passphrase.
+func Marshal(v interface{}, passphrase []byte) ([]byte, error) {
+ data, err := json.MarshalIndent(v, "", "\t")
+ if err != nil {
+ return nil, err
+ }
+ return Encrypt(data, passphrase)
+}
+
+// Decrypt takes a JSON-encoded ciphertext object encrypted using Encrypt and
+// tries to decrypt it using passphrase. If successful, it returns the
+// plaintext.
+func Decrypt(ciphertext, passphrase []byte) ([]byte, error) {
+ data := &data{}
+ if err := json.Unmarshal(ciphertext, data); err != nil {
+ return nil, err
+ }
+
+ if data.KDF.Name != nameScrypt {
+ return nil, fmt.Errorf("encrypted: unknown kdf name %q", data.KDF.Name)
+ }
+ if data.Cipher.Name != nameSecretBox {
+ return nil, fmt.Errorf("encrypted: unknown cipher name %q", data.Cipher.Name)
+ }
+ if err := data.KDF.CheckParams(); err != nil {
+ return nil, err
+ }
+
+ key, err := data.KDF.Key(passphrase)
+ if err != nil {
+ return nil, err
+ }
+
+ return data.Cipher.Decrypt(data.Ciphertext, key)
+}
+
+// Unmarshal decrypts the data using passphrase and unmarshals the resulting
+// plaintext into the value pointed to by v.
+func Unmarshal(data []byte, v interface{}, passphrase []byte) error {
+ decrypted, err := Decrypt(data, passphrase)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(decrypted, v)
+}
+
+func fillRandom(b []byte) error {
+ _, err := io.ReadFull(rand.Reader, b)
+ return err
+}