mirror of
https://github.com/hashicorp/vault.git
synced 2026-03-29 13:53:16 -04:00
Add ChaCha20-Poly1305 support to transit (#3975)
This commit is contained in:
parent
901f98f3ce
commit
ef00a69f11
16 changed files with 3148 additions and 52 deletions
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/base64"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -283,6 +284,13 @@ func TestBackend_datakey(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBackend_rotation(t *testing.T) {
|
||||
defer os.Setenv("TRANSIT_ACC_KEY_TYPE", "")
|
||||
testBackendRotation(t)
|
||||
os.Setenv("TRANSIT_ACC_KEY_TYPE", "CHACHA")
|
||||
testBackendRotation(t)
|
||||
}
|
||||
|
||||
func testBackendRotation(t *testing.T) {
|
||||
decryptData := make(map[string]interface{})
|
||||
encryptHistory := make(map[int]map[string]interface{})
|
||||
logicaltest.Test(t, logicaltest.TestCase{
|
||||
|
|
@ -365,13 +373,17 @@ func TestBackend_basic_derived(t *testing.T) {
|
|||
}
|
||||
|
||||
func testAccStepWritePolicy(t *testing.T, name string, derived bool) logicaltest.TestStep {
|
||||
return logicaltest.TestStep{
|
||||
ts := logicaltest.TestStep{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "keys/" + name,
|
||||
Data: map[string]interface{}{
|
||||
"derived": derived,
|
||||
},
|
||||
}
|
||||
if os.Getenv("TRANSIT_ACC_KEY_TYPE") == "CHACHA" {
|
||||
ts.Data["type"] = "chacha20-poly1305"
|
||||
}
|
||||
return ts
|
||||
}
|
||||
|
||||
func testAccStepListPolicy(t *testing.T, name string, expectNone bool) logicaltest.TestStep {
|
||||
|
|
@ -509,7 +521,11 @@ func testAccStepReadPolicyWithVersions(t *testing.T, name string, expectNone, de
|
|||
if d.Name != name {
|
||||
return fmt.Errorf("bad name: %#v", d)
|
||||
}
|
||||
if d.Type != keysutil.KeyType(keysutil.KeyType_AES256_GCM96).String() {
|
||||
if os.Getenv("TRANSIT_ACC_KEY_TYPE") == "CHACHA" {
|
||||
if d.Type != keysutil.KeyType(keysutil.KeyType_ChaCha20_Poly1305).String() {
|
||||
return fmt.Errorf("bad key type: %#v", d)
|
||||
}
|
||||
} else if d.Type != keysutil.KeyType(keysutil.KeyType_AES256_GCM96).String() {
|
||||
return fmt.Errorf("bad key type: %#v", d)
|
||||
}
|
||||
// Should NOT get a key back
|
||||
|
|
@ -826,6 +842,11 @@ func TestKeyUpgrade(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDerivedKeyUpgrade(t *testing.T) {
|
||||
testDerivedKeyUpgrade(t, keysutil.KeyType_AES256_GCM96)
|
||||
testDerivedKeyUpgrade(t, keysutil.KeyType_ChaCha20_Poly1305)
|
||||
}
|
||||
|
||||
func testDerivedKeyUpgrade(t *testing.T, keyType keysutil.KeyType) {
|
||||
storage := &logical.InmemStorage{}
|
||||
key, _ := uuid.GenerateRandomBytes(32)
|
||||
keyContext, _ := uuid.GenerateRandomBytes(32)
|
||||
|
|
@ -833,7 +854,7 @@ func TestDerivedKeyUpgrade(t *testing.T) {
|
|||
p := &keysutil.Policy{
|
||||
Name: "test",
|
||||
Key: key,
|
||||
Type: keysutil.KeyType_AES256_GCM96,
|
||||
Type: keyType,
|
||||
Derived: true,
|
||||
}
|
||||
|
||||
|
|
@ -883,11 +904,12 @@ func TestDerivedKeyUpgrade(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestConvergentEncryption(t *testing.T) {
|
||||
testConvergentEncryptionCommon(t, 0)
|
||||
testConvergentEncryptionCommon(t, 2)
|
||||
testConvergentEncryptionCommon(t, 0, keysutil.KeyType_AES256_GCM96)
|
||||
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_AES256_GCM96)
|
||||
testConvergentEncryptionCommon(t, 2, keysutil.KeyType_ChaCha20_Poly1305)
|
||||
}
|
||||
|
||||
func testConvergentEncryptionCommon(t *testing.T, ver int) {
|
||||
func testConvergentEncryptionCommon(t *testing.T, ver int, keyType keysutil.KeyType) {
|
||||
var b *backend
|
||||
sysView := logical.TestSystemView()
|
||||
storage := &logical.InmemStorage{}
|
||||
|
|
@ -920,7 +942,7 @@ func testConvergentEncryptionCommon(t *testing.T, ver int) {
|
|||
|
||||
p := &keysutil.Policy{
|
||||
Name: "testkey",
|
||||
Type: keysutil.KeyType_AES256_GCM96,
|
||||
Type: keyType,
|
||||
Derived: true,
|
||||
ConvergentEncryption: true,
|
||||
ConvergentVersion: ver,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
func TestTransit_BackupRestore(t *testing.T) {
|
||||
// Test encryption/decryption after a restore for supported keys
|
||||
testBackupRestore(t, "aes256-gcm96", "encrypt-decrypt")
|
||||
testBackupRestore(t, "chacha20-poly1305", "encrypt-decrypt")
|
||||
testBackupRestore(t, "rsa-2048", "encrypt-decrypt")
|
||||
testBackupRestore(t, "rsa-4096", "encrypt-decrypt")
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ func TestTransit_BackupRestore(t *testing.T) {
|
|||
|
||||
// Test HMAC/verification after a restore for all key types
|
||||
testBackupRestore(t, "aes256-gcm96", "hmac-verify")
|
||||
testBackupRestore(t, "chacha20-poly1305", "hmac-verify")
|
||||
testBackupRestore(t, "ecdsa-p256", "hmac-verify")
|
||||
testBackupRestore(t, "ed25519", "hmac-verify")
|
||||
testBackupRestore(t, "rsa-2048", "hmac-verify")
|
||||
|
|
|
|||
|
|
@ -225,6 +225,8 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d
|
|||
switch keyType {
|
||||
case "aes256-gcm96":
|
||||
polReq.KeyType = keysutil.KeyType_AES256_GCM96
|
||||
case "chacha20-poly1305":
|
||||
polReq.KeyType = keysutil.KeyType_ChaCha20_Poly1305
|
||||
case "ecdsa-p256":
|
||||
return logical.ErrorResponse(fmt.Sprintf("key type %v not supported for this operation", keyType)), logical.ErrInvalidRequest
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ func getExportKey(policy *keysutil.Policy, key *keysutil.KeyEntry, exportType st
|
|||
|
||||
case exportTypeEncryptionKey:
|
||||
switch policy.Type {
|
||||
case keysutil.KeyType_AES256_GCM96:
|
||||
case keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
|
||||
return strings.TrimSpace(base64.StdEncoding.EncodeToString(key.Key)), nil
|
||||
|
||||
case keysutil.KeyType_RSA2048, keysutil.KeyType_RSA4096:
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ import (
|
|||
|
||||
func TestTransit_Export_KeyVersion_ExportsCorrectVersion(t *testing.T) {
|
||||
verifyExportsCorrectVersion(t, "encryption-key", "aes256-gcm96")
|
||||
verifyExportsCorrectVersion(t, "encryption-key", "chacha20-poly1305")
|
||||
verifyExportsCorrectVersion(t, "signing-key", "ecdsa-p256")
|
||||
verifyExportsCorrectVersion(t, "signing-key", "ed25519")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "aes256-gcm96")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "chacha20-poly1305")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "ecdsa-p256")
|
||||
verifyExportsCorrectVersion(t, "hmac-key", "ed25519")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ func (b *backend) pathPolicyWrite(ctx context.Context, req *logical.Request, d *
|
|||
switch keyType {
|
||||
case "aes256-gcm96":
|
||||
polReq.KeyType = keysutil.KeyType_AES256_GCM96
|
||||
case "chacha20-poly1305":
|
||||
polReq.KeyType = keysutil.KeyType_ChaCha20_Poly1305
|
||||
case "ecdsa-p256":
|
||||
polReq.KeyType = keysutil.KeyType_ECDSA_P256
|
||||
case "ed25519":
|
||||
|
|
@ -247,7 +249,7 @@ func (b *backend) pathPolicyRead(ctx context.Context, req *logical.Request, d *f
|
|||
}
|
||||
|
||||
switch p.Type {
|
||||
case keysutil.KeyType_AES256_GCM96:
|
||||
case keysutil.KeyType_AES256_GCM96, keysutil.KeyType_ChaCha20_Poly1305:
|
||||
retKeys := map[string]int64{}
|
||||
for k, v := range p.Keys {
|
||||
retKeys[k] = v.DeprecatedCreationTime
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ func (lm *LockManager) getPolicyCommon(ctx context.Context, req PolicyRequest, l
|
|||
}
|
||||
|
||||
switch req.KeyType {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
if req.Convergent && !req.Derived {
|
||||
lm.UnlockPolicy(lock, lockType)
|
||||
return nil, nil, false, fmt.Errorf("convergent encryption requires derivation to be enabled")
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
|
||||
|
|
@ -48,6 +49,7 @@ const (
|
|||
KeyType_ED25519
|
||||
KeyType_RSA2048
|
||||
KeyType_RSA4096
|
||||
KeyType_ChaCha20_Poly1305
|
||||
)
|
||||
|
||||
const ErrTooOld = "ciphertext or signature version is disallowed by policy (too old)"
|
||||
|
|
@ -75,7 +77,7 @@ type KeyType int
|
|||
|
||||
func (kt KeyType) EncryptionSupported() bool {
|
||||
switch kt {
|
||||
case KeyType_AES256_GCM96, KeyType_RSA2048, KeyType_RSA4096:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -83,7 +85,7 @@ func (kt KeyType) EncryptionSupported() bool {
|
|||
|
||||
func (kt KeyType) DecryptionSupported() bool {
|
||||
switch kt {
|
||||
case KeyType_AES256_GCM96, KeyType_RSA2048, KeyType_RSA4096:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_RSA2048, KeyType_RSA4096:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -107,7 +109,7 @@ func (kt KeyType) HashSignatureInput() bool {
|
|||
|
||||
func (kt KeyType) DerivationSupported() bool {
|
||||
switch kt {
|
||||
case KeyType_AES256_GCM96, KeyType_ED25519:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305, KeyType_ED25519:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -117,6 +119,8 @@ func (kt KeyType) String() string {
|
|||
switch kt {
|
||||
case KeyType_AES256_GCM96:
|
||||
return "aes256-gcm96"
|
||||
case KeyType_ChaCha20_Poly1305:
|
||||
return "chacha20-poly1305"
|
||||
case KeyType_ECDSA_P256:
|
||||
return "ecdsa-p256"
|
||||
case KeyType_ED25519:
|
||||
|
|
@ -569,7 +573,7 @@ func (p *Policy) DeriveKey(context []byte, ver int) ([]byte, error) {
|
|||
}
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
n, err := derBytes.ReadFrom(limReader)
|
||||
if err != nil {
|
||||
return nil, errutil.InternalError{Err: fmt.Sprintf("error reading returned derived bytes: %v", err)}
|
||||
|
|
@ -622,47 +626,62 @@ func (p *Policy) Encrypt(ver int, context, nonce []byte, value string) (string,
|
|||
var ciphertext []byte
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
// Derive the key that should be used
|
||||
key, err := p.DeriveKey(context, ver)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Setup the cipher
|
||||
aesCipher, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
var aead cipher.AEAD
|
||||
|
||||
// Setup the GCM AEAD
|
||||
gcm, err := cipher.NewGCM(aesCipher)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
// Setup the cipher
|
||||
aesCipher, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
// Setup the GCM AEAD
|
||||
gcm, err := cipher.NewGCM(aesCipher)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
aead = gcm
|
||||
|
||||
case KeyType_ChaCha20_Poly1305:
|
||||
cha, err := chacha20poly1305.New(key)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
aead = cha
|
||||
}
|
||||
|
||||
if p.ConvergentEncryption {
|
||||
switch p.ConvergentVersion {
|
||||
case 1:
|
||||
if len(nonce) != gcm.NonceSize() {
|
||||
return "", errutil.UserError{Err: fmt.Sprintf("base64-decoded nonce must be %d bytes long when using convergent encryption with this key", gcm.NonceSize())}
|
||||
if len(nonce) != aead.NonceSize() {
|
||||
return "", errutil.UserError{Err: fmt.Sprintf("base64-decoded nonce must be %d bytes long when using convergent encryption with this key", aead.NonceSize())}
|
||||
}
|
||||
default:
|
||||
nonceHmac := hmac.New(sha256.New, context)
|
||||
nonceHmac.Write(plaintext)
|
||||
nonceSum := nonceHmac.Sum(nil)
|
||||
nonce = nonceSum[:gcm.NonceSize()]
|
||||
nonce = nonceSum[:aead.NonceSize()]
|
||||
}
|
||||
} else {
|
||||
// Compute random nonce
|
||||
nonce, err = uuid.GenerateRandomBytes(gcm.NonceSize())
|
||||
nonce, err = uuid.GenerateRandomBytes(aead.NonceSize())
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypt and tag with GCM
|
||||
ciphertext = gcm.Seal(nil, nonce, plaintext, nil)
|
||||
// Encrypt and tag with AEAD
|
||||
ciphertext = aead.Seal(nil, nonce, plaintext, nil)
|
||||
|
||||
// Place the encrypted data after the nonce
|
||||
if !p.ConvergentEncryption || p.ConvergentVersion > 1 {
|
||||
|
|
@ -736,25 +755,40 @@ func (p *Policy) Decrypt(context, nonce []byte, value string) (string, error) {
|
|||
var plain []byte
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
key, err := p.DeriveKey(context, ver)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Setup the cipher
|
||||
aesCipher, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
var aead cipher.AEAD
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
// Setup the cipher
|
||||
aesCipher, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
// Setup the GCM AEAD
|
||||
gcm, err := cipher.NewGCM(aesCipher)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
aead = gcm
|
||||
|
||||
case KeyType_ChaCha20_Poly1305:
|
||||
cha, err := chacha20poly1305.New(key)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
aead = cha
|
||||
}
|
||||
|
||||
// Setup the GCM AEAD
|
||||
gcm, err := cipher.NewGCM(aesCipher)
|
||||
if err != nil {
|
||||
return "", errutil.InternalError{Err: err.Error()}
|
||||
}
|
||||
|
||||
if len(decoded) < gcm.NonceSize() {
|
||||
if len(decoded) < aead.NonceSize() {
|
||||
return "", errutil.UserError{Err: "invalid ciphertext length"}
|
||||
}
|
||||
|
||||
|
|
@ -763,12 +797,12 @@ func (p *Policy) Decrypt(context, nonce []byte, value string) (string, error) {
|
|||
if p.ConvergentEncryption && p.ConvergentVersion < 2 {
|
||||
ciphertext = decoded
|
||||
} else {
|
||||
nonce = decoded[:gcm.NonceSize()]
|
||||
ciphertext = decoded[gcm.NonceSize():]
|
||||
nonce = decoded[:aead.NonceSize()]
|
||||
ciphertext = decoded[aead.NonceSize():]
|
||||
}
|
||||
|
||||
// Verify and Decrypt
|
||||
plain, err = gcm.Open(nil, nonce, ciphertext, nil)
|
||||
plain, err = aead.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
return "", errutil.UserError{Err: "invalid ciphertext: unable to decrypt"}
|
||||
}
|
||||
|
|
@ -1040,7 +1074,7 @@ func (p *Policy) Rotate(ctx context.Context, storage logical.Storage) (retErr er
|
|||
entry.HMACKey = hmacKey
|
||||
|
||||
switch p.Type {
|
||||
case KeyType_AES256_GCM96:
|
||||
case KeyType_AES256_GCM96, KeyType_ChaCha20_Poly1305:
|
||||
// Generate a 256bit key
|
||||
newKey, err := uuid.GenerateRandomBytes(32)
|
||||
if err != nil {
|
||||
|
|
|
|||
83
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
generated
vendored
Normal file
83
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go
generated
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// Copyright 2016 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 chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539.
|
||||
package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeySize is the size of the key used by this AEAD, in bytes.
|
||||
KeySize = 32
|
||||
// NonceSize is the size of the nonce used with this AEAD, in bytes.
|
||||
NonceSize = 12
|
||||
)
|
||||
|
||||
type chacha20poly1305 struct {
|
||||
key [32]byte
|
||||
}
|
||||
|
||||
// New returns a ChaCha20-Poly1305 AEAD that uses the given, 256-bit key.
|
||||
func New(key []byte) (cipher.AEAD, error) {
|
||||
if len(key) != KeySize {
|
||||
return nil, errors.New("chacha20poly1305: bad key length")
|
||||
}
|
||||
ret := new(chacha20poly1305)
|
||||
copy(ret.key[:], key)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) NonceSize() int {
|
||||
return NonceSize
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) Overhead() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if len(nonce) != NonceSize {
|
||||
panic("chacha20poly1305: bad nonce length passed to Seal")
|
||||
}
|
||||
|
||||
if uint64(len(plaintext)) > (1<<38)-64 {
|
||||
panic("chacha20poly1305: plaintext too large")
|
||||
}
|
||||
|
||||
return c.seal(dst, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
var errOpen = errors.New("chacha20poly1305: message authentication failed")
|
||||
|
||||
func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if len(nonce) != NonceSize {
|
||||
panic("chacha20poly1305: bad nonce length passed to Open")
|
||||
}
|
||||
if len(ciphertext) < 16 {
|
||||
return nil, errOpen
|
||||
}
|
||||
if uint64(len(ciphertext)) > (1<<38)-48 {
|
||||
panic("chacha20poly1305: ciphertext too large")
|
||||
}
|
||||
|
||||
return c.open(dst, nonce, ciphertext, additionalData)
|
||||
}
|
||||
|
||||
// sliceForAppend takes a slice and a requested number of bytes. It returns a
|
||||
// slice with the contents of the given slice followed by that many bytes and a
|
||||
// second slice that aliases into it and contains only the extra bytes. If the
|
||||
// original slice has sufficient capacity then no allocation is performed.
|
||||
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||
if total := len(in) + n; cap(in) >= total {
|
||||
head = in[:total]
|
||||
} else {
|
||||
head = make([]byte, total)
|
||||
copy(head, in)
|
||||
}
|
||||
tail = head[len(in):]
|
||||
return
|
||||
}
|
||||
127
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
generated
vendored
Normal file
127
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
generated
vendored
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// +build go1.7,amd64,!gccgo,!appengine
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
//go:noescape
|
||||
func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
|
||||
|
||||
//go:noescape
|
||||
func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
|
||||
|
||||
// cpuid is implemented in chacha20poly1305_amd64.s.
|
||||
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
|
||||
|
||||
// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s.
|
||||
func xgetbv() (eax, edx uint32)
|
||||
|
||||
var (
|
||||
useASM bool
|
||||
useAVX2 bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
detectCPUFeatures()
|
||||
}
|
||||
|
||||
// detectCPUFeatures is used to detect if cpu instructions
|
||||
// used by the functions implemented in assembler in
|
||||
// chacha20poly1305_amd64.s are supported.
|
||||
func detectCPUFeatures() {
|
||||
maxID, _, _, _ := cpuid(0, 0)
|
||||
if maxID < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, ecx1, _ := cpuid(1, 0)
|
||||
|
||||
haveSSSE3 := isSet(9, ecx1)
|
||||
useASM = haveSSSE3
|
||||
|
||||
haveOSXSAVE := isSet(27, ecx1)
|
||||
|
||||
osSupportsAVX := false
|
||||
// For XGETBV, OSXSAVE bit is required and sufficient.
|
||||
if haveOSXSAVE {
|
||||
eax, _ := xgetbv()
|
||||
// Check if XMM and YMM registers have OS support.
|
||||
osSupportsAVX = isSet(1, eax) && isSet(2, eax)
|
||||
}
|
||||
haveAVX := isSet(28, ecx1) && osSupportsAVX
|
||||
|
||||
if maxID < 7 {
|
||||
return
|
||||
}
|
||||
|
||||
_, ebx7, _, _ := cpuid(7, 0)
|
||||
haveAVX2 := isSet(5, ebx7) && haveAVX
|
||||
haveBMI2 := isSet(8, ebx7)
|
||||
|
||||
useAVX2 = haveAVX2 && haveBMI2
|
||||
}
|
||||
|
||||
// isSet checks if bit at bitpos is set in value.
|
||||
func isSet(bitpos uint, value uint32) bool {
|
||||
return value&(1<<bitpos) != 0
|
||||
}
|
||||
|
||||
// setupState writes a ChaCha20 input matrix to state. See
|
||||
// https://tools.ietf.org/html/rfc7539#section-2.3.
|
||||
func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
|
||||
state[0] = 0x61707865
|
||||
state[1] = 0x3320646e
|
||||
state[2] = 0x79622d32
|
||||
state[3] = 0x6b206574
|
||||
|
||||
state[4] = binary.LittleEndian.Uint32(key[:4])
|
||||
state[5] = binary.LittleEndian.Uint32(key[4:8])
|
||||
state[6] = binary.LittleEndian.Uint32(key[8:12])
|
||||
state[7] = binary.LittleEndian.Uint32(key[12:16])
|
||||
state[8] = binary.LittleEndian.Uint32(key[16:20])
|
||||
state[9] = binary.LittleEndian.Uint32(key[20:24])
|
||||
state[10] = binary.LittleEndian.Uint32(key[24:28])
|
||||
state[11] = binary.LittleEndian.Uint32(key[28:32])
|
||||
|
||||
state[12] = 0
|
||||
state[13] = binary.LittleEndian.Uint32(nonce[:4])
|
||||
state[14] = binary.LittleEndian.Uint32(nonce[4:8])
|
||||
state[15] = binary.LittleEndian.Uint32(nonce[8:12])
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if !useASM {
|
||||
return c.sealGeneric(dst, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
var state [16]uint32
|
||||
setupState(&state, &c.key, nonce)
|
||||
|
||||
ret, out := sliceForAppend(dst, len(plaintext)+16)
|
||||
chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if !useASM {
|
||||
return c.openGeneric(dst, nonce, ciphertext, additionalData)
|
||||
}
|
||||
|
||||
var state [16]uint32
|
||||
setupState(&state, &c.key, nonce)
|
||||
|
||||
ciphertext = ciphertext[:len(ciphertext)-16]
|
||||
ret, out := sliceForAppend(dst, len(ciphertext))
|
||||
if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
return nil, errOpen
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
2714
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
generated
vendored
Normal file
2714
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
70
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
generated
vendored
Normal file
70
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2016 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 chacha20poly1305
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/crypto/internal/chacha20"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
)
|
||||
|
||||
func roundTo16(n int) int {
|
||||
return 16 * ((n + 15) / 16)
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
var counter [16]byte
|
||||
copy(counter[4:], nonce)
|
||||
|
||||
var polyKey [32]byte
|
||||
chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
|
||||
|
||||
ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
|
||||
counter[0] = 1
|
||||
chacha20.XORKeyStream(out, plaintext, &counter, &c.key)
|
||||
|
||||
polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
|
||||
copy(polyInput, additionalData)
|
||||
copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
|
||||
binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
|
||||
binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
|
||||
|
||||
var tag [poly1305.TagSize]byte
|
||||
poly1305.Sum(&tag, polyInput, &polyKey)
|
||||
copy(out[len(plaintext):], tag[:])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
var tag [poly1305.TagSize]byte
|
||||
copy(tag[:], ciphertext[len(ciphertext)-16:])
|
||||
ciphertext = ciphertext[:len(ciphertext)-16]
|
||||
|
||||
var counter [16]byte
|
||||
copy(counter[4:], nonce)
|
||||
|
||||
var polyKey [32]byte
|
||||
chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
|
||||
|
||||
polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
|
||||
copy(polyInput, additionalData)
|
||||
copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
|
||||
binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
|
||||
binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
|
||||
|
||||
ret, out := sliceForAppend(dst, len(ciphertext))
|
||||
if !poly1305.Verify(&tag, polyInput, &polyKey) {
|
||||
for i := range out {
|
||||
out[i] = 0
|
||||
}
|
||||
return nil, errOpen
|
||||
}
|
||||
|
||||
counter[0] = 1
|
||||
chacha20.XORKeyStream(out, ciphertext, &counter, &c.key)
|
||||
return ret, nil
|
||||
}
|
||||
15
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
generated
vendored
Normal file
15
vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2016 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.
|
||||
|
||||
// +build !amd64 !go1.7 gccgo appengine
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
return c.sealGeneric(dst, nonce, plaintext, additionalData)
|
||||
}
|
||||
|
||||
func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
return c.openGeneric(dst, nonce, ciphertext, additionalData)
|
||||
}
|
||||
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
|
@ -1608,6 +1608,12 @@
|
|||
"revision": "5119cf507ed5294cc409c092980c7497ee5d6fd2",
|
||||
"revisionTime": "2018-01-22T10:39:14Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "1zB843WyoSh8oMdbeDfgByEa2TE=",
|
||||
"path": "golang.org/x/crypto/chacha20poly1305",
|
||||
"revision": "650f4a345ab4e5b245a3034b110ebc7299e68186",
|
||||
"revisionTime": "2017-09-27T09:16:38Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "IQkUIOnvlf0tYloFx9mLaXSvXWQ=",
|
||||
"path": "golang.org/x/crypto/curve25519",
|
||||
|
|
|
|||
|
|
@ -34,10 +34,7 @@ values set here cannot be changed after key creation.
|
|||
convergent encryption, where the same plaintext creates the same ciphertext.
|
||||
This requires _derived_ to be set to `true`. When enabled, each
|
||||
encryption(/decryption/rewrap/datakey) operation will derive a `nonce` value
|
||||
rather than randomly generate it. Note that while this is useful for
|
||||
particular situations, all nonce values used with a given context value **must
|
||||
be unique** or it will compromise the security of your key, and the key space
|
||||
for nonces is 96 bit -- not as large as the AES key itself.
|
||||
rather than randomly generate it.
|
||||
|
||||
- `derived` `(bool: false)` – Specifies if key derivation is to be used. If
|
||||
enabled, all encrypt/decrypt requests to this named key must provide a context
|
||||
|
|
@ -53,8 +50,10 @@ values set here cannot be changed after key creation.
|
|||
- `type` `(string: "aes256-gcm96")` – Specifies the type of key to create. The
|
||||
currently-supported types are:
|
||||
|
||||
- `aes256-gcm96` – AES-256 wrapped with GCM using a 12-byte nonce size
|
||||
(symmetric, supports derivation)
|
||||
- `aes256-gcm96` – AES-256 wrapped with GCM using a 96-bit nonce size AEAD
|
||||
(symmetric, supports derivation and convergent encryption)
|
||||
- `chacha20-poly1305` – ChaCha20-Poly1305 AEAD (symmetric, supports
|
||||
derivation and convergent encryption)
|
||||
- `ecdsa-p256` – ECDSA using the P-256 elliptic curve (asymmetric)
|
||||
- `ed25519` – ED25519 (asymmetric, supports derivation)
|
||||
- `rsa-2048` - RSA with bit size of 2048 (asymmetric)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,24 @@ multiple of five) may provide a good alternative, allowing for several keys to
|
|||
be live at once and a deterministic way to decide which key to use at any given
|
||||
time.
|
||||
|
||||
## Key Types
|
||||
|
||||
As of now, the transit secrets engine supports the following key types (all key
|
||||
types also generate separate HMAC keys):
|
||||
|
||||
* `aes256-gcm96`: AES-GCM with a 256-bit AES key and a 96-bit nonce; supports
|
||||
encryption, decryption, key derivation, and convergent encryption
|
||||
* `chacha20-poly1305`: ChaCha20-Poly1305 with a 256-bit key; supports
|
||||
encryption, decryption, key derivation, and convergent encryption
|
||||
* `ed25519`: Ed25519; supports signing, signature verification, and key
|
||||
derivation
|
||||
* `ecdsa-p256`: ECDSA using curve P256; supports signing and signature
|
||||
verification
|
||||
* `rsa-2048`: 2048-bit RSA key; supports encryption, decryption, signing, and
|
||||
signature verification
|
||||
* `rsa-4096`: 4096-bit RSA key; supports encryption, decryption, signing, and
|
||||
signature verification
|
||||
|
||||
## Setup
|
||||
|
||||
Most secrets engines must be configured in advance before they can perform their
|
||||
|
|
|
|||
Loading…
Reference in a new issue