Add ChaCha20-Poly1305 support to transit (#3975)

This commit is contained in:
Jeff Mitchell 2018-02-14 11:59:46 -05:00 committed by GitHub
parent 901f98f3ce
commit ef00a69f11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 3148 additions and 52 deletions

View file

@ -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,

View file

@ -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")

View file

@ -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:

View file

@ -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:

View file

@ -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")
}

View file

@ -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

View file

@ -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")

View file

@ -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 {

View 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
}

View 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
}

File diff suppressed because it is too large Load diff

View 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
}

View 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
View file

@ -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",

View file

@ -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)

View file

@ -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