Bumping k8s dependencies to 1.13
This commit is contained in:
131
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aeadrekey.go
generated
vendored
Normal file
131
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aeadrekey.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// rekeyAEAD holds the necessary information for an AEAD based on
|
||||
// AES-GCM that performs nonce-based key derivation and XORs the
|
||||
// nonce with a random mask.
|
||||
type rekeyAEAD struct {
|
||||
kdfKey []byte
|
||||
kdfCounter []byte
|
||||
nonceMask []byte
|
||||
nonceBuf []byte
|
||||
gcmAEAD cipher.AEAD
|
||||
}
|
||||
|
||||
// KeySizeError signals that the given key does not have the correct size.
|
||||
type KeySizeError int
|
||||
|
||||
func (k KeySizeError) Error() string {
|
||||
return "alts/conn: invalid key size " + strconv.Itoa(int(k))
|
||||
}
|
||||
|
||||
// newRekeyAEAD creates a new instance of aes128gcm with rekeying.
|
||||
// The key argument should be 44 bytes, the first 32 bytes are used as a key
|
||||
// for HKDF-expand and the remainining 12 bytes are used as a random mask for
|
||||
// the counter.
|
||||
func newRekeyAEAD(key []byte) (*rekeyAEAD, error) {
|
||||
k := len(key)
|
||||
if k != kdfKeyLen+nonceLen {
|
||||
return nil, KeySizeError(k)
|
||||
}
|
||||
return &rekeyAEAD{
|
||||
kdfKey: key[:kdfKeyLen],
|
||||
kdfCounter: make([]byte, kdfCounterLen),
|
||||
nonceMask: key[kdfKeyLen:],
|
||||
nonceBuf: make([]byte, nonceLen),
|
||||
gcmAEAD: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Seal rekeys if nonce[2:8] is different than in the last call, masks the nonce,
|
||||
// and calls Seal for aes128gcm.
|
||||
func (s *rekeyAEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
||||
if err := s.rekeyIfRequired(nonce); err != nil {
|
||||
panic(fmt.Sprintf("Rekeying failed with: %s", err.Error()))
|
||||
}
|
||||
maskNonce(s.nonceBuf, nonce, s.nonceMask)
|
||||
return s.gcmAEAD.Seal(dst, s.nonceBuf, plaintext, additionalData)
|
||||
}
|
||||
|
||||
// Open rekeys if nonce[2:8] is different than in the last call, masks the nonce,
|
||||
// and calls Open for aes128gcm.
|
||||
func (s *rekeyAEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if err := s.rekeyIfRequired(nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
maskNonce(s.nonceBuf, nonce, s.nonceMask)
|
||||
return s.gcmAEAD.Open(dst, s.nonceBuf, ciphertext, additionalData)
|
||||
}
|
||||
|
||||
// rekeyIfRequired creates a new aes128gcm AEAD if the existing AEAD is nil
|
||||
// or cannot be used with given nonce.
|
||||
func (s *rekeyAEAD) rekeyIfRequired(nonce []byte) error {
|
||||
newKdfCounter := nonce[kdfCounterOffset : kdfCounterOffset+kdfCounterLen]
|
||||
if s.gcmAEAD != nil && bytes.Equal(newKdfCounter, s.kdfCounter) {
|
||||
return nil
|
||||
}
|
||||
copy(s.kdfCounter, newKdfCounter)
|
||||
a, err := aes.NewCipher(hkdfExpand(s.kdfKey, s.kdfCounter))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.gcmAEAD, err = cipher.NewGCM(a)
|
||||
return err
|
||||
}
|
||||
|
||||
// maskNonce XORs the given nonce with the mask and stores the result in dst.
|
||||
func maskNonce(dst, nonce, mask []byte) {
|
||||
nonce1 := binary.LittleEndian.Uint64(nonce[:sizeUint64])
|
||||
nonce2 := binary.LittleEndian.Uint32(nonce[sizeUint64:])
|
||||
mask1 := binary.LittleEndian.Uint64(mask[:sizeUint64])
|
||||
mask2 := binary.LittleEndian.Uint32(mask[sizeUint64:])
|
||||
binary.LittleEndian.PutUint64(dst[:sizeUint64], nonce1^mask1)
|
||||
binary.LittleEndian.PutUint32(dst[sizeUint64:], nonce2^mask2)
|
||||
}
|
||||
|
||||
// NonceSize returns the required nonce size.
|
||||
func (s *rekeyAEAD) NonceSize() int {
|
||||
return s.gcmAEAD.NonceSize()
|
||||
}
|
||||
|
||||
// Overhead returns the ciphertext overhead.
|
||||
func (s *rekeyAEAD) Overhead() int {
|
||||
return s.gcmAEAD.Overhead()
|
||||
}
|
||||
|
||||
// hkdfExpand computes the first 16 bytes of the HKDF-expand function
|
||||
// defined in RFC5869.
|
||||
func hkdfExpand(key, info []byte) []byte {
|
||||
mac := hmac.New(sha256.New, key)
|
||||
mac.Write(info)
|
||||
mac.Write([]byte{0x01}[:])
|
||||
return mac.Sum(nil)[:aeadKeyLen]
|
||||
}
|
263
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aeadrekey_test.go
generated
vendored
Normal file
263
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aeadrekey_test.go
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// cryptoTestVector is struct for a rekey test vector
|
||||
type rekeyAEADTestVector struct {
|
||||
desc string
|
||||
key, nonce, plaintext, aad, ciphertext []byte
|
||||
}
|
||||
|
||||
// Test encrypt and decrypt using (adapted) test vectors for AES-GCM.
|
||||
func TestAES128GCMRekeyEncrypt(t *testing.T) {
|
||||
for _, test := range []rekeyAEADTestVector{
|
||||
// NIST vectors from:
|
||||
// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
|
||||
//
|
||||
// IEEE vectors from:
|
||||
// http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf
|
||||
//
|
||||
// Key expanded by setting
|
||||
// expandedKey = (key ||
|
||||
// key ^ {0x01,..,0x01} ||
|
||||
// key ^ {0x02,..,0x02})[0:44].
|
||||
{
|
||||
desc: "Derived from NIST test vector 1",
|
||||
key: dehex("0000000000000000000000000000000001010101010101010101010101010101020202020202020202020202"),
|
||||
nonce: dehex("000000000000000000000000"),
|
||||
aad: dehex(""),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("85e873e002f6ebdc4060954eb8675508"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from NIST test vector 2",
|
||||
key: dehex("0000000000000000000000000000000001010101010101010101010101010101020202020202020202020202"),
|
||||
nonce: dehex("000000000000000000000000"),
|
||||
aad: dehex(""),
|
||||
plaintext: dehex("00000000000000000000000000000000"),
|
||||
ciphertext: dehex("51e9a8cb23ca2512c8256afff8e72d681aca19a1148ac115e83df4888cc00d11"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from NIST test vector 3",
|
||||
key: dehex("feffe9928665731c6d6a8f9467308308fffee8938764721d6c6b8e9566318209fcfdeb908467711e6f688d96"),
|
||||
nonce: dehex("cafebabefacedbaddecaf888"),
|
||||
aad: dehex(""),
|
||||
plaintext: dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"),
|
||||
ciphertext: dehex("1018ed5a1402a86516d6576d70b2ffccca261b94df88b58f53b64dfba435d18b2f6e3b7869f9353d4ac8cf09afb1663daa7b4017e6fc2c177c0c087c0df1162129952213cee1bc6e9c8495dd705e1f3d"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from NIST test vector 4",
|
||||
key: dehex("feffe9928665731c6d6a8f9467308308fffee8938764721d6c6b8e9566318209fcfdeb908467711e6f688d96"),
|
||||
nonce: dehex("cafebabefacedbaddecaf888"),
|
||||
aad: dehex("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
|
||||
plaintext: dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
|
||||
ciphertext: dehex("1018ed5a1402a86516d6576d70b2ffccca261b94df88b58f53b64dfba435d18b2f6e3b7869f9353d4ac8cf09afb1663daa7b4017e6fc2c177c0c087c4764565d077e9124001ddb27fc0848c5"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from adapted NIST test vector 4 for KDF counter boundary (flip nonce bit 15)",
|
||||
key: dehex("feffe9928665731c6d6a8f9467308308fffee8938764721d6c6b8e9566318209fcfdeb908467711e6f688d96"),
|
||||
nonce: dehex("ca7ebabefacedbaddecaf888"),
|
||||
aad: dehex("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
|
||||
plaintext: dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
|
||||
ciphertext: dehex("e650d3c0fb879327f2d03287fa93cd07342b136215adbca00c3bd5099ec41832b1d18e0423ed26bb12c6cd09debb29230a94c0cee15903656f85edb6fc509b1b28216382172ecbcc31e1e9b1"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from adapted NIST test vector 4 for KDF counter boundary (flip nonce bit 16)",
|
||||
key: dehex("feffe9928665731c6d6a8f9467308308fffee8938764721d6c6b8e9566318209fcfdeb908467711e6f688d96"),
|
||||
nonce: dehex("cafebbbefacedbaddecaf888"),
|
||||
aad: dehex("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
|
||||
plaintext: dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
|
||||
ciphertext: dehex("c0121e6c954d0767f96630c33450999791b2da2ad05c4190169ccad9ac86ff1c721e3d82f2ad22ab463bab4a0754b7dd68ca4de7ea2531b625eda01f89312b2ab957d5c7f8568dd95fcdcd1f"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from adapted NIST test vector 4 for KDF counter boundary (flip nonce bit 63)",
|
||||
key: dehex("feffe9928665731c6d6a8f9467308308fffee8938764721d6c6b8e9566318209fcfdeb908467711e6f688d96"),
|
||||
nonce: dehex("cafebabefacedb2ddecaf888"),
|
||||
aad: dehex("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
|
||||
plaintext: dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
|
||||
ciphertext: dehex("8af37ea5684a4d81d4fd817261fd9743099e7e6a025eaacf8e54b124fb5743149e05cb89f4a49467fe2e5e5965f29a19f99416b0016b54585d12553783ba59e9f782e82e097c336bf7989f08"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from adapted NIST test vector 4 for KDF counter boundary (flip nonce bit 64)",
|
||||
key: dehex("feffe9928665731c6d6a8f9467308308fffee8938764721d6c6b8e9566318209fcfdeb908467711e6f688d96"),
|
||||
nonce: dehex("cafebabefacedbaddfcaf888"),
|
||||
aad: dehex("feedfacedeadbeeffeedfacedeadbeefabaddad2"),
|
||||
plaintext: dehex("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"),
|
||||
ciphertext: dehex("fbd528448d0346bfa878634864d407a35a039de9db2f1feb8e965b3ae9356ce6289441d77f8f0df294891f37ea438b223e3bf2bdc53d4c5a74fb680bb312a8dec6f7252cbcd7f5799750ad78"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.1.1 54-byte auth",
|
||||
key: dehex("ad7a2bd03eac835a6f620fdcb506b345ac7b2ad13fad825b6e630eddb407b244af7829d23cae81586d600dde"),
|
||||
nonce: dehex("12153524c0895e81b2c28465"),
|
||||
aad: dehex("d609b1f056637a0d46df998d88e5222ab2c2846512153524c0895e8108000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340001"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("3ea0b584f3c85e93f9320ea591699efb"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.1.2 54-byte auth",
|
||||
key: dehex("e3c08a8f06c6e3ad95a70557b23f75483ce33021a9c72b7025666204c69c0b72e1c2888d04c4e1af97a50755"),
|
||||
nonce: dehex("12153524c0895e81b2c28465"),
|
||||
aad: dehex("d609b1f056637a0d46df998d88e5222ab2c2846512153524c0895e8108000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340001"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("294e028bf1fe6f14c4e8f7305c933eb5"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.2.1 60-byte crypt",
|
||||
key: dehex("ad7a2bd03eac835a6f620fdcb506b345ac7b2ad13fad825b6e630eddb407b244af7829d23cae81586d600dde"),
|
||||
nonce: dehex("12153524c0895e81b2c28465"),
|
||||
aad: dehex("d609b1f056637a0d46df998d88e52e00b2c2846512153524c0895e81"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0002"),
|
||||
ciphertext: dehex("db3d25719c6b0a3ca6145c159d5c6ed9aff9c6e0b79f17019ea923b8665ddf52137ad611f0d1bf417a7ca85e45afe106ff9c7569d335d086ae6c03f00987ccd6"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.2.2 60-byte crypt",
|
||||
key: dehex("e3c08a8f06c6e3ad95a70557b23f75483ce33021a9c72b7025666204c69c0b72e1c2888d04c4e1af97a50755"),
|
||||
nonce: dehex("12153524c0895e81b2c28465"),
|
||||
aad: dehex("d609b1f056637a0d46df998d88e52e00b2c2846512153524c0895e81"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0002"),
|
||||
ciphertext: dehex("1641f28ec13afcc8f7903389787201051644914933e9202bb9d06aa020c2a67ef51dfe7bc00a856c55b8f8133e77f659132502bad63f5713d57d0c11e0f871ed"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.3.1 60-byte auth",
|
||||
key: dehex("071b113b0ca743fecccf3d051f737382061a103a0da642ffcdce3c041e727283051913390ea541fccecd3f07"),
|
||||
nonce: dehex("f0761e8dcd3d000176d457ed"),
|
||||
aad: dehex("e20106d7cd0df0761e8dcd3d88e5400076d457ed08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0003"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("58837a10562b0f1f8edbe58ca55811d3"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.3.2 60-byte auth",
|
||||
key: dehex("691d3ee909d7f54167fd1ca0b5d769081f2bde1aee655fdbab80bd5295ae6be76b1f3ceb0bd5f74365ff1ea2"),
|
||||
nonce: dehex("f0761e8dcd3d000176d457ed"),
|
||||
aad: dehex("e20106d7cd0df0761e8dcd3d88e5400076d457ed08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0003"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("c2722ff6ca29a257718a529d1f0c6a3b"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.4.1 54-byte crypt",
|
||||
key: dehex("071b113b0ca743fecccf3d051f737382061a103a0da642ffcdce3c041e727283051913390ea541fccecd3f07"),
|
||||
nonce: dehex("f0761e8dcd3d000176d457ed"),
|
||||
aad: dehex("e20106d7cd0df0761e8dcd3d88e54c2a76d457ed"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340004"),
|
||||
ciphertext: dehex("fd96b715b93a13346af51e8acdf792cdc7b2686f8574c70e6b0cbf16291ded427ad73fec48cd298e0528a1f4c644a949fc31dc9279706ddba33f"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.4.2 54-byte crypt",
|
||||
key: dehex("691d3ee909d7f54167fd1ca0b5d769081f2bde1aee655fdbab80bd5295ae6be76b1f3ceb0bd5f74365ff1ea2"),
|
||||
nonce: dehex("f0761e8dcd3d000176d457ed"),
|
||||
aad: dehex("e20106d7cd0df0761e8dcd3d88e54c2a76d457ed"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340004"),
|
||||
ciphertext: dehex("b68f6300c2e9ae833bdc070e24021a3477118e78ccf84e11a485d861476c300f175353d5cdf92008a4f878e6cc3577768085c50a0e98fda6cbb8"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.5.1 65-byte auth",
|
||||
key: dehex("013fe00b5f11be7f866d0cbbc55a7a90003ee10a5e10bf7e876c0dbac45b7b91033de2095d13bc7d846f0eb9"),
|
||||
nonce: dehex("7cfde9f9e33724c68932d612"),
|
||||
aad: dehex("84c5d513d2aaf6e5bbd2727788e523008932d6127cfde9f9e33724c608000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0005"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("cca20eecda6283f09bb3543dd99edb9b"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.5.2 65-byte auth",
|
||||
key: dehex("83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a82381c291b78fe5fde3c2d89068"),
|
||||
nonce: dehex("7cfde9f9e33724c68932d612"),
|
||||
aad: dehex("84c5d513d2aaf6e5bbd2727788e523008932d6127cfde9f9e33724c608000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0005"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("b232cc1da5117bf15003734fa599d271"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.6.1 61-byte crypt",
|
||||
key: dehex("013fe00b5f11be7f866d0cbbc55a7a90003ee10a5e10bf7e876c0dbac45b7b91033de2095d13bc7d846f0eb9"),
|
||||
nonce: dehex("7cfde9f9e33724c68932d612"),
|
||||
aad: dehex("84c5d513d2aaf6e5bbd2727788e52f008932d6127cfde9f9e33724c6"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b0006"),
|
||||
ciphertext: dehex("ff1910d35ad7e5657890c7c560146fd038707f204b66edbc3d161f8ace244b985921023c436e3a1c3532ecd5d09a056d70be583f0d10829d9387d07d33d872e490"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.6.2 61-byte crypt",
|
||||
key: dehex("83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a82381c291b78fe5fde3c2d89068"),
|
||||
nonce: dehex("7cfde9f9e33724c68932d612"),
|
||||
aad: dehex("84c5d513d2aaf6e5bbd2727788e52f008932d6127cfde9f9e33724c6"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b0006"),
|
||||
ciphertext: dehex("0db4cf956b5f97eca4eab82a6955307f9ae02a32dd7d93f83d66ad04e1cfdc5182ad12abdea5bbb619a1bd5fb9a573590fba908e9c7a46c1f7ba0905d1b55ffda4"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.7.1 79-byte crypt",
|
||||
key: dehex("88ee087fd95da9fbf6725aa9d757b0cd89ef097ed85ca8faf7735ba8d656b1cc8aec0a7ddb5fabf9f47058ab"),
|
||||
nonce: dehex("7ae8e2ca4ec500012e58495c"),
|
||||
aad: dehex("68f2e77696ce7ae8e2ca4ec588e541002e58495c08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d0007"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("813f0e630f96fb2d030f58d83f5cdfd0"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.7.2 79-byte crypt",
|
||||
key: dehex("4c973dbc7364621674f8b5b89e5c15511fced9216490fb1c1a2caa0ffe0407e54e953fbe7166601476fab7ba"),
|
||||
nonce: dehex("7ae8e2ca4ec500012e58495c"),
|
||||
aad: dehex("68f2e77696ce7ae8e2ca4ec588e541002e58495c08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d0007"),
|
||||
plaintext: dehex(""),
|
||||
ciphertext: dehex("77e5a44c21eb07188aacbd74d1980e97"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.8.1 61-byte crypt",
|
||||
key: dehex("88ee087fd95da9fbf6725aa9d757b0cd89ef097ed85ca8faf7735ba8d656b1cc8aec0a7ddb5fabf9f47058ab"),
|
||||
nonce: dehex("7ae8e2ca4ec500012e58495c"),
|
||||
aad: dehex("68f2e77696ce7ae8e2ca4ec588e54d002e58495c"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748490008"),
|
||||
ciphertext: dehex("958ec3f6d60afeda99efd888f175e5fcd4c87b9bcc5c2f5426253a8b506296c8c43309ab2adb5939462541d95e80811e04e706b1498f2c407c7fb234f8cc01a647550ee6b557b35a7e3945381821f4"),
|
||||
},
|
||||
{
|
||||
desc: "Derived from IEEE 2.8.2 61-byte crypt",
|
||||
key: dehex("4c973dbc7364621674f8b5b89e5c15511fced9216490fb1c1a2caa0ffe0407e54e953fbe7166601476fab7ba"),
|
||||
nonce: dehex("7ae8e2ca4ec500012e58495c"),
|
||||
aad: dehex("68f2e77696ce7ae8e2ca4ec588e54d002e58495c"),
|
||||
plaintext: dehex("08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748490008"),
|
||||
ciphertext: dehex("b44d072011cd36d272a9b7a98db9aa90cbc5c67b93ddce67c854503214e2e896ec7e9db649ed4bcf6f850aac0223d0cf92c83db80795c3a17ecc1248bb00591712b1ae71e268164196252162810b00"),
|
||||
}} {
|
||||
aead, err := newRekeyAEAD(test.key)
|
||||
if err != nil {
|
||||
t.Fatal("unexpected failure in newRekeyAEAD: ", err.Error())
|
||||
}
|
||||
if got := aead.Seal(nil, test.nonce, test.plaintext, test.aad); !bytes.Equal(got, test.ciphertext) {
|
||||
t.Errorf("Unexpected ciphertext for test vector '%s':\nciphertext=%s\nwant= %s",
|
||||
test.desc, hex.EncodeToString(got), hex.EncodeToString(test.ciphertext))
|
||||
}
|
||||
if got, err := aead.Open(nil, test.nonce, test.ciphertext, test.aad); err != nil || !bytes.Equal(got, test.plaintext) {
|
||||
t.Errorf("Unexpected plaintext for test vector '%s':\nplaintext=%s (err=%v)\nwant= %s",
|
||||
test.desc, hex.EncodeToString(got), err, hex.EncodeToString(test.plaintext))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func dehex(s string) []byte {
|
||||
if len(s) == 0 {
|
||||
return make([]byte, 0)
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b
|
||||
}
|
105
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcm.go
generated
vendored
Normal file
105
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcm.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
// Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in
|
||||
// each direction).
|
||||
overflowLenAES128GCM = 5
|
||||
)
|
||||
|
||||
// aes128gcm is the struct that holds necessary information for ALTS record.
|
||||
// The counter value is NOT included in the payload during the encryption and
|
||||
// decryption operations.
|
||||
type aes128gcm struct {
|
||||
// inCounter is used in ALTS record to check that incoming counters are
|
||||
// as expected, since ALTS record guarantees that messages are unwrapped
|
||||
// in the same order that the peer wrapped them.
|
||||
inCounter Counter
|
||||
outCounter Counter
|
||||
aead cipher.AEAD
|
||||
}
|
||||
|
||||
// NewAES128GCM creates an instance that uses aes128gcm for ALTS record.
|
||||
func NewAES128GCM(side core.Side, key []byte) (ALTSRecordCrypto, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, err := cipher.NewGCM(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &aes128gcm{
|
||||
inCounter: NewInCounter(side, overflowLenAES128GCM),
|
||||
outCounter: NewOutCounter(side, overflowLenAES128GCM),
|
||||
aead: a,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt is the encryption function. dst can contain bytes at the beginning of
|
||||
// the ciphertext that will not be encrypted but will be authenticated. If dst
|
||||
// has enough capacity to hold these bytes, the ciphertext and the tag, no
|
||||
// allocation and copy operations will be performed. dst and plaintext do not
|
||||
// overlap.
|
||||
func (s *aes128gcm) Encrypt(dst, plaintext []byte) ([]byte, error) {
|
||||
// If we need to allocate an output buffer, we want to include space for
|
||||
// GCM tag to avoid forcing ALTS record to reallocate as well.
|
||||
dlen := len(dst)
|
||||
dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize)
|
||||
seq, err := s.outCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := out[:len(plaintext)]
|
||||
copy(data, plaintext) // data may alias plaintext
|
||||
|
||||
// Seal appends the ciphertext and the tag to its first argument and
|
||||
// returns the updated slice. However, SliceForAppend above ensures that
|
||||
// dst has enough capacity to avoid a reallocation and copy due to the
|
||||
// append.
|
||||
dst = s.aead.Seal(dst[:dlen], seq, data, nil)
|
||||
s.outCounter.Inc()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (s *aes128gcm) EncryptionOverhead() int {
|
||||
return GcmTagSize
|
||||
}
|
||||
|
||||
func (s *aes128gcm) Decrypt(dst, ciphertext []byte) ([]byte, error) {
|
||||
seq, err := s.inCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If dst is equal to ciphertext[:0], ciphertext storage is reused.
|
||||
plaintext, err := s.aead.Open(dst, seq, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, ErrAuth
|
||||
}
|
||||
s.inCounter.Inc()
|
||||
return plaintext, nil
|
||||
}
|
223
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcm_test.go
generated
vendored
Normal file
223
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcm_test.go
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
// cryptoTestVector is struct for a GCM test vector
|
||||
type cryptoTestVector struct {
|
||||
key, counter, plaintext, ciphertext, tag []byte
|
||||
allocateDst bool
|
||||
}
|
||||
|
||||
// getGCMCryptoPair outputs a client/server pair on aes128gcm.
|
||||
func getGCMCryptoPair(key []byte, counter []byte, t *testing.T) (ALTSRecordCrypto, ALTSRecordCrypto) {
|
||||
client, err := NewAES128GCM(core.ClientSide, key)
|
||||
if err != nil {
|
||||
t.Fatalf("NewAES128GCM(ClientSide, key) = %v", err)
|
||||
}
|
||||
server, err := NewAES128GCM(core.ServerSide, key)
|
||||
if err != nil {
|
||||
t.Fatalf("NewAES128GCM(ServerSide, key) = %v", err)
|
||||
}
|
||||
// set counter if provided.
|
||||
if counter != nil {
|
||||
if CounterSide(counter) == core.ClientSide {
|
||||
client.(*aes128gcm).outCounter = CounterFromValue(counter, overflowLenAES128GCM)
|
||||
server.(*aes128gcm).inCounter = CounterFromValue(counter, overflowLenAES128GCM)
|
||||
} else {
|
||||
server.(*aes128gcm).outCounter = CounterFromValue(counter, overflowLenAES128GCM)
|
||||
client.(*aes128gcm).inCounter = CounterFromValue(counter, overflowLenAES128GCM)
|
||||
}
|
||||
}
|
||||
return client, server
|
||||
}
|
||||
|
||||
func testGCMEncryptionDecryption(sender ALTSRecordCrypto, receiver ALTSRecordCrypto, test *cryptoTestVector, withCounter bool, t *testing.T) {
|
||||
// Ciphertext is: counter + encrypted text + tag.
|
||||
ciphertext := []byte(nil)
|
||||
if withCounter {
|
||||
ciphertext = append(ciphertext, test.counter...)
|
||||
}
|
||||
ciphertext = append(ciphertext, test.ciphertext...)
|
||||
ciphertext = append(ciphertext, test.tag...)
|
||||
|
||||
// Decrypt.
|
||||
if got, err := receiver.Decrypt(nil, ciphertext); err != nil || !bytes.Equal(got, test.plaintext) {
|
||||
t.Errorf("key=%v\ncounter=%v\ntag=%v\nciphertext=%v\nDecrypt = %v, %v\nwant: %v",
|
||||
test.key, test.counter, test.tag, test.ciphertext, got, err, test.plaintext)
|
||||
}
|
||||
|
||||
// Encrypt.
|
||||
var dst []byte
|
||||
if test.allocateDst {
|
||||
dst = make([]byte, len(test.plaintext)+sender.EncryptionOverhead())
|
||||
}
|
||||
if got, err := sender.Encrypt(dst[:0], test.plaintext); err != nil || !bytes.Equal(got, ciphertext) {
|
||||
t.Errorf("key=%v\ncounter=%v\nplaintext=%v\nEncrypt = %v, %v\nwant: %v",
|
||||
test.key, test.counter, test.plaintext, got, err, ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
// Test encrypt and decrypt using test vectors for aes128gcm.
|
||||
func TestAES128GCMEncrypt(t *testing.T) {
|
||||
for _, test := range []cryptoTestVector{
|
||||
{
|
||||
key: dehex("11754cd72aec309bf52f7687212e8957"),
|
||||
counter: dehex("3c819d9a9bed087615030b65"),
|
||||
plaintext: nil,
|
||||
ciphertext: nil,
|
||||
tag: dehex("250327c674aaf477aef2675748cf6971"),
|
||||
allocateDst: false,
|
||||
},
|
||||
{
|
||||
key: dehex("ca47248ac0b6f8372a97ac43508308ed"),
|
||||
counter: dehex("ffd2b598feabc9019262d2be"),
|
||||
plaintext: nil,
|
||||
ciphertext: nil,
|
||||
tag: dehex("60d20404af527d248d893ae495707d1a"),
|
||||
allocateDst: false,
|
||||
},
|
||||
{
|
||||
key: dehex("7fddb57453c241d03efbed3ac44e371c"),
|
||||
counter: dehex("ee283a3fc75575e33efd4887"),
|
||||
plaintext: dehex("d5de42b461646c255c87bd2962d3b9a2"),
|
||||
ciphertext: dehex("2ccda4a5415cb91e135c2a0f78c9b2fd"),
|
||||
tag: dehex("b36d1df9b9d5e596f83e8b7f52971cb3"),
|
||||
allocateDst: false,
|
||||
},
|
||||
{
|
||||
key: dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"),
|
||||
counter: dehex("54cc7dc2c37ec006bcc6d1da"),
|
||||
plaintext: dehex("007c5e5b3e59df24a7c355584fc1518d"),
|
||||
ciphertext: dehex("0e1bde206a07a9c2c1b65300f8c64997"),
|
||||
tag: dehex("2b4401346697138c7a4891ee59867d0c"),
|
||||
allocateDst: false,
|
||||
},
|
||||
{
|
||||
key: dehex("11754cd72aec309bf52f7687212e8957"),
|
||||
counter: dehex("3c819d9a9bed087615030b65"),
|
||||
plaintext: nil,
|
||||
ciphertext: nil,
|
||||
tag: dehex("250327c674aaf477aef2675748cf6971"),
|
||||
allocateDst: true,
|
||||
},
|
||||
{
|
||||
key: dehex("ca47248ac0b6f8372a97ac43508308ed"),
|
||||
counter: dehex("ffd2b598feabc9019262d2be"),
|
||||
plaintext: nil,
|
||||
ciphertext: nil,
|
||||
tag: dehex("60d20404af527d248d893ae495707d1a"),
|
||||
allocateDst: true,
|
||||
},
|
||||
{
|
||||
key: dehex("7fddb57453c241d03efbed3ac44e371c"),
|
||||
counter: dehex("ee283a3fc75575e33efd4887"),
|
||||
plaintext: dehex("d5de42b461646c255c87bd2962d3b9a2"),
|
||||
ciphertext: dehex("2ccda4a5415cb91e135c2a0f78c9b2fd"),
|
||||
tag: dehex("b36d1df9b9d5e596f83e8b7f52971cb3"),
|
||||
allocateDst: true,
|
||||
},
|
||||
{
|
||||
key: dehex("ab72c77b97cb5fe9a382d9fe81ffdbed"),
|
||||
counter: dehex("54cc7dc2c37ec006bcc6d1da"),
|
||||
plaintext: dehex("007c5e5b3e59df24a7c355584fc1518d"),
|
||||
ciphertext: dehex("0e1bde206a07a9c2c1b65300f8c64997"),
|
||||
tag: dehex("2b4401346697138c7a4891ee59867d0c"),
|
||||
allocateDst: true,
|
||||
},
|
||||
} {
|
||||
// Test encryption and decryption for aes128gcm.
|
||||
client, server := getGCMCryptoPair(test.key, test.counter, t)
|
||||
if CounterSide(test.counter) == core.ClientSide {
|
||||
testGCMEncryptionDecryption(client, server, &test, false, t)
|
||||
} else {
|
||||
testGCMEncryptionDecryption(server, client, &test, false, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGCMEncryptRoundtrip(client ALTSRecordCrypto, server ALTSRecordCrypto, t *testing.T) {
|
||||
// Encrypt.
|
||||
const plaintext = "This is plaintext."
|
||||
var err error
|
||||
buf := []byte(plaintext)
|
||||
buf, err = client.Encrypt(buf[:0], buf)
|
||||
if err != nil {
|
||||
t.Fatal("Encrypting with client-side context: unexpected error", err, "\n",
|
||||
"Plaintext:", []byte(plaintext))
|
||||
}
|
||||
|
||||
// Encrypt a second message.
|
||||
const plaintext2 = "This is a second plaintext."
|
||||
buf2 := []byte(plaintext2)
|
||||
buf2, err = client.Encrypt(buf2[:0], buf2)
|
||||
if err != nil {
|
||||
t.Fatal("Encrypting with client-side context: unexpected error", err, "\n",
|
||||
"Plaintext:", []byte(plaintext2))
|
||||
}
|
||||
|
||||
// Decryption fails: cannot decrypt second message before first.
|
||||
if got, err := server.Decrypt(nil, buf2); err == nil {
|
||||
t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n",
|
||||
" Original plaintext:", []byte(plaintext2), "\n",
|
||||
" Ciphertext:", buf2, "\n",
|
||||
" Decrypted plaintext:", got)
|
||||
}
|
||||
|
||||
// Decryption fails: wrong counter space.
|
||||
if got, err := client.Decrypt(nil, buf); err == nil {
|
||||
t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want counter space error:\n",
|
||||
" Original plaintext:", []byte(plaintext), "\n",
|
||||
" Ciphertext:", buf, "\n",
|
||||
" Decrypted plaintext:", got)
|
||||
}
|
||||
|
||||
// Decrypt first message.
|
||||
ciphertext := append([]byte(nil), buf...)
|
||||
buf, err = server.Decrypt(buf[:0], buf)
|
||||
if err != nil || string(buf) != plaintext {
|
||||
t.Fatal("Decrypting client-side ciphertext with a server-side context did not produce original content:\n",
|
||||
" Original plaintext:", []byte(plaintext), "\n",
|
||||
" Ciphertext:", ciphertext, "\n",
|
||||
" Decryption error:", err, "\n",
|
||||
" Decrypted plaintext:", buf)
|
||||
}
|
||||
|
||||
// Decryption fails: replay attack.
|
||||
if got, err := server.Decrypt(nil, buf); err == nil {
|
||||
t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n",
|
||||
" Original plaintext:", []byte(plaintext), "\n",
|
||||
" Ciphertext:", buf, "\n",
|
||||
" Decrypted plaintext:", got)
|
||||
}
|
||||
}
|
||||
|
||||
// Test encrypt and decrypt on roundtrip messages for aes128gcm.
|
||||
func TestAES128GCMEncryptRoundtrip(t *testing.T) {
|
||||
// Test for aes128gcm.
|
||||
key := make([]byte, 16)
|
||||
client, server := getGCMCryptoPair(key, nil, t)
|
||||
testGCMEncryptRoundtrip(client, server, t)
|
||||
}
|
116
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcmrekey.go
generated
vendored
Normal file
116
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcmrekey.go
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
// Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in
|
||||
// each direction).
|
||||
overflowLenAES128GCMRekey = 8
|
||||
nonceLen = 12
|
||||
aeadKeyLen = 16
|
||||
kdfKeyLen = 32
|
||||
kdfCounterOffset = 2
|
||||
kdfCounterLen = 6
|
||||
sizeUint64 = 8
|
||||
)
|
||||
|
||||
// aes128gcmRekey is the struct that holds necessary information for ALTS record.
|
||||
// The counter value is NOT included in the payload during the encryption and
|
||||
// decryption operations.
|
||||
type aes128gcmRekey struct {
|
||||
// inCounter is used in ALTS record to check that incoming counters are
|
||||
// as expected, since ALTS record guarantees that messages are unwrapped
|
||||
// in the same order that the peer wrapped them.
|
||||
inCounter Counter
|
||||
outCounter Counter
|
||||
inAEAD cipher.AEAD
|
||||
outAEAD cipher.AEAD
|
||||
}
|
||||
|
||||
// NewAES128GCMRekey creates an instance that uses aes128gcm with rekeying
|
||||
// for ALTS record. The key argument should be 44 bytes, the first 32 bytes
|
||||
// are used as a key for HKDF-expand and the remainining 12 bytes are used
|
||||
// as a random mask for the counter.
|
||||
func NewAES128GCMRekey(side core.Side, key []byte) (ALTSRecordCrypto, error) {
|
||||
inCounter := NewInCounter(side, overflowLenAES128GCMRekey)
|
||||
outCounter := NewOutCounter(side, overflowLenAES128GCMRekey)
|
||||
inAEAD, err := newRekeyAEAD(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outAEAD, err := newRekeyAEAD(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &aes128gcmRekey{
|
||||
inCounter,
|
||||
outCounter,
|
||||
inAEAD,
|
||||
outAEAD,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Encrypt is the encryption function. dst can contain bytes at the beginning of
|
||||
// the ciphertext that will not be encrypted but will be authenticated. If dst
|
||||
// has enough capacity to hold these bytes, the ciphertext and the tag, no
|
||||
// allocation and copy operations will be performed. dst and plaintext do not
|
||||
// overlap.
|
||||
func (s *aes128gcmRekey) Encrypt(dst, plaintext []byte) ([]byte, error) {
|
||||
// If we need to allocate an output buffer, we want to include space for
|
||||
// GCM tag to avoid forcing ALTS record to reallocate as well.
|
||||
dlen := len(dst)
|
||||
dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize)
|
||||
seq, err := s.outCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := out[:len(plaintext)]
|
||||
copy(data, plaintext) // data may alias plaintext
|
||||
|
||||
// Seal appends the ciphertext and the tag to its first argument and
|
||||
// returns the updated slice. However, SliceForAppend above ensures that
|
||||
// dst has enough capacity to avoid a reallocation and copy due to the
|
||||
// append.
|
||||
dst = s.outAEAD.Seal(dst[:dlen], seq, data, nil)
|
||||
s.outCounter.Inc()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
func (s *aes128gcmRekey) EncryptionOverhead() int {
|
||||
return GcmTagSize
|
||||
}
|
||||
|
||||
func (s *aes128gcmRekey) Decrypt(dst, ciphertext []byte) ([]byte, error) {
|
||||
seq, err := s.inCounter.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext, err := s.inAEAD.Open(dst, seq, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, ErrAuth
|
||||
}
|
||||
s.inCounter.Inc()
|
||||
return plaintext, nil
|
||||
}
|
117
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcmrekey_test.go
generated
vendored
Normal file
117
vendor/google.golang.org/grpc/credentials/alts/internal/conn/aes128gcmrekey_test.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
// cryptoTestVector is struct for a rekey test vector
|
||||
type rekeyTestVector struct {
|
||||
key, nonce, plaintext, ciphertext []byte
|
||||
}
|
||||
|
||||
// getGCMCryptoPair outputs a client/server pair on aes128gcmRekey.
|
||||
func getRekeyCryptoPair(key []byte, counter []byte, t *testing.T) (ALTSRecordCrypto, ALTSRecordCrypto) {
|
||||
client, err := NewAES128GCMRekey(core.ClientSide, key)
|
||||
if err != nil {
|
||||
t.Fatalf("NewAES128GCMRekey(ClientSide, key) = %v", err)
|
||||
}
|
||||
server, err := NewAES128GCMRekey(core.ServerSide, key)
|
||||
if err != nil {
|
||||
t.Fatalf("NewAES128GCMRekey(ServerSide, key) = %v", err)
|
||||
}
|
||||
// set counter if provided.
|
||||
if counter != nil {
|
||||
if CounterSide(counter) == core.ClientSide {
|
||||
client.(*aes128gcmRekey).outCounter = CounterFromValue(counter, overflowLenAES128GCMRekey)
|
||||
server.(*aes128gcmRekey).inCounter = CounterFromValue(counter, overflowLenAES128GCMRekey)
|
||||
} else {
|
||||
server.(*aes128gcmRekey).outCounter = CounterFromValue(counter, overflowLenAES128GCMRekey)
|
||||
client.(*aes128gcmRekey).inCounter = CounterFromValue(counter, overflowLenAES128GCMRekey)
|
||||
}
|
||||
}
|
||||
return client, server
|
||||
}
|
||||
|
||||
func testRekeyEncryptRoundtrip(client ALTSRecordCrypto, server ALTSRecordCrypto, t *testing.T) {
|
||||
// Encrypt.
|
||||
const plaintext = "This is plaintext."
|
||||
var err error
|
||||
buf := []byte(plaintext)
|
||||
buf, err = client.Encrypt(buf[:0], buf)
|
||||
if err != nil {
|
||||
t.Fatal("Encrypting with client-side context: unexpected error", err, "\n",
|
||||
"Plaintext:", []byte(plaintext))
|
||||
}
|
||||
|
||||
// Encrypt a second message.
|
||||
const plaintext2 = "This is a second plaintext."
|
||||
buf2 := []byte(plaintext2)
|
||||
buf2, err = client.Encrypt(buf2[:0], buf2)
|
||||
if err != nil {
|
||||
t.Fatal("Encrypting with client-side context: unexpected error", err, "\n",
|
||||
"Plaintext:", []byte(plaintext2))
|
||||
}
|
||||
|
||||
// Decryption fails: cannot decrypt second message before first.
|
||||
if got, err := server.Decrypt(nil, buf2); err == nil {
|
||||
t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n",
|
||||
" Original plaintext:", []byte(plaintext2), "\n",
|
||||
" Ciphertext:", buf2, "\n",
|
||||
" Decrypted plaintext:", got)
|
||||
}
|
||||
|
||||
// Decryption fails: wrong counter space.
|
||||
if got, err := client.Decrypt(nil, buf); err == nil {
|
||||
t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want counter space error:\n",
|
||||
" Original plaintext:", []byte(plaintext), "\n",
|
||||
" Ciphertext:", buf, "\n",
|
||||
" Decrypted plaintext:", got)
|
||||
}
|
||||
|
||||
// Decrypt first message.
|
||||
ciphertext := append([]byte(nil), buf...)
|
||||
buf, err = server.Decrypt(buf[:0], buf)
|
||||
if err != nil || string(buf) != plaintext {
|
||||
t.Fatal("Decrypting client-side ciphertext with a server-side context did not produce original content:\n",
|
||||
" Original plaintext:", []byte(plaintext), "\n",
|
||||
" Ciphertext:", ciphertext, "\n",
|
||||
" Decryption error:", err, "\n",
|
||||
" Decrypted plaintext:", buf)
|
||||
}
|
||||
|
||||
// Decryption fails: replay attack.
|
||||
if got, err := server.Decrypt(nil, buf); err == nil {
|
||||
t.Error("Decrypting client-side ciphertext with a client-side context unexpectedly succeeded; want unexpected counter error:\n",
|
||||
" Original plaintext:", []byte(plaintext), "\n",
|
||||
" Ciphertext:", buf, "\n",
|
||||
" Decrypted plaintext:", got)
|
||||
}
|
||||
}
|
||||
|
||||
// Test encrypt and decrypt on roundtrip messages for aes128gcmRekey.
|
||||
func TestAES128GCMRekeyEncryptRoundtrip(t *testing.T) {
|
||||
// Test for aes128gcmRekey.
|
||||
key := make([]byte, 44)
|
||||
client, server := getRekeyCryptoPair(key, nil, t)
|
||||
testRekeyEncryptRoundtrip(client, server, t)
|
||||
}
|
70
vendor/google.golang.org/grpc/credentials/alts/internal/conn/common.go
generated
vendored
Normal file
70
vendor/google.golang.org/grpc/credentials/alts/internal/conn/common.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
// GcmTagSize is the GCM tag size is the difference in length between
|
||||
// plaintext and ciphertext. From crypto/cipher/gcm.go in Go crypto
|
||||
// library.
|
||||
GcmTagSize = 16
|
||||
)
|
||||
|
||||
// ErrAuth occurs on authentication failure.
|
||||
var ErrAuth = errors.New("message authentication failed")
|
||||
|
||||
// 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 head, tail
|
||||
}
|
||||
|
||||
// ParseFramedMsg parse the provided buffer and returns a frame of the format
|
||||
// msgLength+msg and any remaining bytes in that buffer.
|
||||
func ParseFramedMsg(b []byte, maxLen uint32) ([]byte, []byte, error) {
|
||||
// If the size field is not complete, return the provided buffer as
|
||||
// remaining buffer.
|
||||
if len(b) < MsgLenFieldSize {
|
||||
return nil, b, nil
|
||||
}
|
||||
msgLenField := b[:MsgLenFieldSize]
|
||||
length := binary.LittleEndian.Uint32(msgLenField)
|
||||
if length > maxLen {
|
||||
return nil, nil, fmt.Errorf("received the frame length %d larger than the limit %d", length, maxLen)
|
||||
}
|
||||
if len(b) < int(length)+4 { // account for the first 4 msg length bytes.
|
||||
// Frame is not complete yet.
|
||||
return nil, b, nil
|
||||
}
|
||||
return b[:MsgLenFieldSize+length], b[MsgLenFieldSize+length:], nil
|
||||
}
|
62
vendor/google.golang.org/grpc/credentials/alts/internal/conn/counter.go
generated
vendored
Normal file
62
vendor/google.golang.org/grpc/credentials/alts/internal/conn/counter.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
const counterLen = 12
|
||||
|
||||
var (
|
||||
errInvalidCounter = errors.New("invalid counter")
|
||||
)
|
||||
|
||||
// Counter is a 96-bit, little-endian counter.
|
||||
type Counter struct {
|
||||
value [counterLen]byte
|
||||
invalid bool
|
||||
overflowLen int
|
||||
}
|
||||
|
||||
// Value returns the current value of the counter as a byte slice.
|
||||
func (c *Counter) Value() ([]byte, error) {
|
||||
if c.invalid {
|
||||
return nil, errInvalidCounter
|
||||
}
|
||||
return c.value[:], nil
|
||||
}
|
||||
|
||||
// Inc increments the counter and checks for overflow.
|
||||
func (c *Counter) Inc() {
|
||||
// If the counter is already invalid, there is no need to increase it.
|
||||
if c.invalid {
|
||||
return
|
||||
}
|
||||
i := 0
|
||||
for ; i < c.overflowLen; i++ {
|
||||
c.value[i]++
|
||||
if c.value[i] != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == c.overflowLen {
|
||||
c.invalid = true
|
||||
}
|
||||
}
|
141
vendor/google.golang.org/grpc/credentials/alts/internal/conn/counter_test.go
generated
vendored
Normal file
141
vendor/google.golang.org/grpc/credentials/alts/internal/conn/counter_test.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
const (
|
||||
testOverflowLen = 5
|
||||
)
|
||||
|
||||
func TestCounterSides(t *testing.T) {
|
||||
for _, side := range []core.Side{core.ClientSide, core.ServerSide} {
|
||||
outCounter := NewOutCounter(side, testOverflowLen)
|
||||
inCounter := NewInCounter(side, testOverflowLen)
|
||||
for i := 0; i < 1024; i++ {
|
||||
value, _ := outCounter.Value()
|
||||
if g, w := CounterSide(value), side; g != w {
|
||||
t.Errorf("after %d iterations, CounterSide(outCounter.Value()) = %v, want %v", i, g, w)
|
||||
break
|
||||
}
|
||||
value, _ = inCounter.Value()
|
||||
if g, w := CounterSide(value), side; g == w {
|
||||
t.Errorf("after %d iterations, CounterSide(inCounter.Value()) = %v, want %v", i, g, w)
|
||||
break
|
||||
}
|
||||
outCounter.Inc()
|
||||
inCounter.Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCounterInc(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
counter []byte
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
counter: []byte{0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
want: []byte{0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
counter: []byte{0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80},
|
||||
want: []byte{0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80},
|
||||
},
|
||||
{
|
||||
counter: []byte{0xff, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
want: []byte{0x00, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
counter: []byte{0x42, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
want: []byte{0x43, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
},
|
||||
{
|
||||
counter: []byte{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
want: []byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
{
|
||||
counter: []byte{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80},
|
||||
want: []byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80},
|
||||
},
|
||||
} {
|
||||
c := CounterFromValue(test.counter, overflowLenAES128GCM)
|
||||
c.Inc()
|
||||
value, _ := c.Value()
|
||||
if g, w := value, test.want; !bytes.Equal(g, w) || c.invalid {
|
||||
t.Errorf("counter(%v).Inc() =\n%v, want\n%v", test.counter, g, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRolloverCounter(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
desc string
|
||||
value []byte
|
||||
overflowLen int
|
||||
}{
|
||||
{
|
||||
desc: "testing overflow without rekeying 1",
|
||||
value: []byte{0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80},
|
||||
overflowLen: 5,
|
||||
},
|
||||
{
|
||||
desc: "testing overflow without rekeying 2",
|
||||
value: []byte{0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
overflowLen: 5,
|
||||
},
|
||||
{
|
||||
desc: "testing overflow for rekeying mode 1",
|
||||
value: []byte{0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80},
|
||||
overflowLen: 8,
|
||||
},
|
||||
{
|
||||
desc: "testing overflow for rekeying mode 2",
|
||||
value: []byte{0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00},
|
||||
overflowLen: 8,
|
||||
},
|
||||
} {
|
||||
c := CounterFromValue(test.value, overflowLenAES128GCM)
|
||||
|
||||
// First Inc() + Value() should work.
|
||||
c.Inc()
|
||||
_, err := c.Value()
|
||||
if err != nil {
|
||||
t.Errorf("%v: first Inc() + Value() unexpectedly failed: %v, want <nil> error", test.desc, err)
|
||||
}
|
||||
// Second Inc() + Value() should fail.
|
||||
c.Inc()
|
||||
_, err = c.Value()
|
||||
if err != errInvalidCounter {
|
||||
t.Errorf("%v: second Inc() + Value() unexpectedly succeeded: want %v", test.desc, errInvalidCounter)
|
||||
}
|
||||
// Third Inc() + Value() should also fail because the counter is
|
||||
// already in an invalid state.
|
||||
c.Inc()
|
||||
_, err = c.Value()
|
||||
if err != errInvalidCounter {
|
||||
t.Errorf("%v: Third Inc() + Value() unexpectedly succeeded: want %v", test.desc, errInvalidCounter)
|
||||
}
|
||||
}
|
||||
}
|
271
vendor/google.golang.org/grpc/credentials/alts/internal/conn/record.go
generated
vendored
Normal file
271
vendor/google.golang.org/grpc/credentials/alts/internal/conn/record.go
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
// Package conn contains an implementation of a secure channel created by gRPC
|
||||
// handshakers.
|
||||
package conn
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
// ALTSRecordCrypto is the interface for gRPC ALTS record protocol.
|
||||
type ALTSRecordCrypto interface {
|
||||
// Encrypt encrypts the plaintext and computes the tag (if any) of dst
|
||||
// and plaintext, dst and plaintext do not overlap.
|
||||
Encrypt(dst, plaintext []byte) ([]byte, error)
|
||||
// EncryptionOverhead returns the tag size (if any) in bytes.
|
||||
EncryptionOverhead() int
|
||||
// Decrypt decrypts ciphertext and verify the tag (if any). dst and
|
||||
// ciphertext may alias exactly or not at all. To reuse ciphertext's
|
||||
// storage for the decrypted output, use ciphertext[:0] as dst.
|
||||
Decrypt(dst, ciphertext []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// ALTSRecordFunc is a function type for factory functions that create
|
||||
// ALTSRecordCrypto instances.
|
||||
type ALTSRecordFunc func(s core.Side, keyData []byte) (ALTSRecordCrypto, error)
|
||||
|
||||
const (
|
||||
// MsgLenFieldSize is the byte size of the frame length field of a
|
||||
// framed message.
|
||||
MsgLenFieldSize = 4
|
||||
// The byte size of the message type field of a framed message.
|
||||
msgTypeFieldSize = 4
|
||||
// The bytes size limit for a ALTS record message.
|
||||
altsRecordLengthLimit = 1024 * 1024 // 1 MiB
|
||||
// The default bytes size of a ALTS record message.
|
||||
altsRecordDefaultLength = 4 * 1024 // 4KiB
|
||||
// Message type value included in ALTS record framing.
|
||||
altsRecordMsgType = uint32(0x06)
|
||||
// The initial write buffer size.
|
||||
altsWriteBufferInitialSize = 32 * 1024 // 32KiB
|
||||
// The maximum write buffer size. This *must* be multiple of
|
||||
// altsRecordDefaultLength.
|
||||
altsWriteBufferMaxSize = 512 * 1024 // 512KiB
|
||||
)
|
||||
|
||||
var (
|
||||
protocols = make(map[string]ALTSRecordFunc)
|
||||
)
|
||||
|
||||
// RegisterProtocol register a ALTS record encryption protocol.
|
||||
func RegisterProtocol(protocol string, f ALTSRecordFunc) error {
|
||||
if _, ok := protocols[protocol]; ok {
|
||||
return fmt.Errorf("protocol %v is already registered", protocol)
|
||||
}
|
||||
protocols[protocol] = f
|
||||
return nil
|
||||
}
|
||||
|
||||
// conn represents a secured connection. It implements the net.Conn interface.
|
||||
type conn struct {
|
||||
net.Conn
|
||||
crypto ALTSRecordCrypto
|
||||
// buf holds data that has been read from the connection and decrypted,
|
||||
// but has not yet been returned by Read.
|
||||
buf []byte
|
||||
payloadLengthLimit int
|
||||
// protected holds data read from the network but have not yet been
|
||||
// decrypted. This data might not compose a complete frame.
|
||||
protected []byte
|
||||
// writeBuf is a buffer used to contain encrypted frames before being
|
||||
// written to the network.
|
||||
writeBuf []byte
|
||||
// nextFrame stores the next frame (in protected buffer) info.
|
||||
nextFrame []byte
|
||||
// overhead is the calculated overhead of each frame.
|
||||
overhead int
|
||||
}
|
||||
|
||||
// NewConn creates a new secure channel instance given the other party role and
|
||||
// handshaking result.
|
||||
func NewConn(c net.Conn, side core.Side, recordProtocol string, key []byte, protected []byte) (net.Conn, error) {
|
||||
newCrypto := protocols[recordProtocol]
|
||||
if newCrypto == nil {
|
||||
return nil, fmt.Errorf("negotiated unknown next_protocol %q", recordProtocol)
|
||||
}
|
||||
crypto, err := newCrypto(side, key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("protocol %q: %v", recordProtocol, err)
|
||||
}
|
||||
overhead := MsgLenFieldSize + msgTypeFieldSize + crypto.EncryptionOverhead()
|
||||
payloadLengthLimit := altsRecordDefaultLength - overhead
|
||||
if protected == nil {
|
||||
// We pre-allocate protected to be of size
|
||||
// 2*altsRecordDefaultLength-1 during initialization. We only
|
||||
// read from the network into protected when protected does not
|
||||
// contain a complete frame, which is at most
|
||||
// altsRecordDefaultLength-1 (bytes). And we read at most
|
||||
// altsRecordDefaultLength (bytes) data into protected at one
|
||||
// time. Therefore, 2*altsRecordDefaultLength-1 is large enough
|
||||
// to buffer data read from the network.
|
||||
protected = make([]byte, 0, 2*altsRecordDefaultLength-1)
|
||||
}
|
||||
|
||||
altsConn := &conn{
|
||||
Conn: c,
|
||||
crypto: crypto,
|
||||
payloadLengthLimit: payloadLengthLimit,
|
||||
protected: protected,
|
||||
writeBuf: make([]byte, altsWriteBufferInitialSize),
|
||||
nextFrame: protected,
|
||||
overhead: overhead,
|
||||
}
|
||||
return altsConn, nil
|
||||
}
|
||||
|
||||
// Read reads and decrypts a frame from the underlying connection, and copies the
|
||||
// decrypted payload into b. If the size of the payload is greater than len(b),
|
||||
// Read retains the remaining bytes in an internal buffer, and subsequent calls
|
||||
// to Read will read from this buffer until it is exhausted.
|
||||
func (p *conn) Read(b []byte) (n int, err error) {
|
||||
if len(p.buf) == 0 {
|
||||
var framedMsg []byte
|
||||
framedMsg, p.nextFrame, err = ParseFramedMsg(p.nextFrame, altsRecordLengthLimit)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
// Check whether the next frame to be decrypted has been
|
||||
// completely received yet.
|
||||
if len(framedMsg) == 0 {
|
||||
copy(p.protected, p.nextFrame)
|
||||
p.protected = p.protected[:len(p.nextFrame)]
|
||||
// Always copy next incomplete frame to the beginning of
|
||||
// the protected buffer and reset nextFrame to it.
|
||||
p.nextFrame = p.protected
|
||||
}
|
||||
// Check whether a complete frame has been received yet.
|
||||
for len(framedMsg) == 0 {
|
||||
if len(p.protected) == cap(p.protected) {
|
||||
tmp := make([]byte, len(p.protected), cap(p.protected)+altsRecordDefaultLength)
|
||||
copy(tmp, p.protected)
|
||||
p.protected = tmp
|
||||
}
|
||||
n, err = p.Conn.Read(p.protected[len(p.protected):min(cap(p.protected), len(p.protected)+altsRecordDefaultLength)])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
p.protected = p.protected[:len(p.protected)+n]
|
||||
framedMsg, p.nextFrame, err = ParseFramedMsg(p.protected, altsRecordLengthLimit)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
// Now we have a complete frame, decrypted it.
|
||||
msg := framedMsg[MsgLenFieldSize:]
|
||||
msgType := binary.LittleEndian.Uint32(msg[:msgTypeFieldSize])
|
||||
if msgType&0xff != altsRecordMsgType {
|
||||
return 0, fmt.Errorf("received frame with incorrect message type %v, expected lower byte %v",
|
||||
msgType, altsRecordMsgType)
|
||||
}
|
||||
ciphertext := msg[msgTypeFieldSize:]
|
||||
|
||||
// Decrypt requires that if the dst and ciphertext alias, they
|
||||
// must alias exactly. Code here used to use msg[:0], but msg
|
||||
// starts MsgLenFieldSize+msgTypeFieldSize bytes earlier than
|
||||
// ciphertext, so they alias inexactly. Using ciphertext[:0]
|
||||
// arranges the appropriate aliasing without needing to copy
|
||||
// ciphertext or use a separate destination buffer. For more info
|
||||
// check: https://golang.org/pkg/crypto/cipher/#AEAD.
|
||||
p.buf, err = p.crypto.Decrypt(ciphertext[:0], ciphertext)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
n = copy(b, p.buf)
|
||||
p.buf = p.buf[n:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Write encrypts, frames, and writes bytes from b to the underlying connection.
|
||||
func (p *conn) Write(b []byte) (n int, err error) {
|
||||
n = len(b)
|
||||
// Calculate the output buffer size with framing and encryption overhead.
|
||||
numOfFrames := int(math.Ceil(float64(len(b)) / float64(p.payloadLengthLimit)))
|
||||
size := len(b) + numOfFrames*p.overhead
|
||||
// If writeBuf is too small, increase its size up to the maximum size.
|
||||
partialBSize := len(b)
|
||||
if size > altsWriteBufferMaxSize {
|
||||
size = altsWriteBufferMaxSize
|
||||
const numOfFramesInMaxWriteBuf = altsWriteBufferMaxSize / altsRecordDefaultLength
|
||||
partialBSize = numOfFramesInMaxWriteBuf * p.payloadLengthLimit
|
||||
}
|
||||
if len(p.writeBuf) < size {
|
||||
p.writeBuf = make([]byte, size)
|
||||
}
|
||||
|
||||
for partialBStart := 0; partialBStart < len(b); partialBStart += partialBSize {
|
||||
partialBEnd := partialBStart + partialBSize
|
||||
if partialBEnd > len(b) {
|
||||
partialBEnd = len(b)
|
||||
}
|
||||
partialB := b[partialBStart:partialBEnd]
|
||||
writeBufIndex := 0
|
||||
for len(partialB) > 0 {
|
||||
payloadLen := len(partialB)
|
||||
if payloadLen > p.payloadLengthLimit {
|
||||
payloadLen = p.payloadLengthLimit
|
||||
}
|
||||
buf := partialB[:payloadLen]
|
||||
partialB = partialB[payloadLen:]
|
||||
|
||||
// Write buffer contains: length, type, payload, and tag
|
||||
// if any.
|
||||
|
||||
// 1. Fill in type field.
|
||||
msg := p.writeBuf[writeBufIndex+MsgLenFieldSize:]
|
||||
binary.LittleEndian.PutUint32(msg, altsRecordMsgType)
|
||||
|
||||
// 2. Encrypt the payload and create a tag if any.
|
||||
msg, err = p.crypto.Encrypt(msg[:msgTypeFieldSize], buf)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// 3. Fill in the size field.
|
||||
binary.LittleEndian.PutUint32(p.writeBuf[writeBufIndex:], uint32(len(msg)))
|
||||
|
||||
// 4. Increase writeBufIndex.
|
||||
writeBufIndex += len(buf) + p.overhead
|
||||
}
|
||||
nn, err := p.Conn.Write(p.writeBuf[:writeBufIndex])
|
||||
if err != nil {
|
||||
// We need to calculate the actual data size that was
|
||||
// written. This means we need to remove header,
|
||||
// encryption overheads, and any partially-written
|
||||
// frame data.
|
||||
numOfWrittenFrames := int(math.Floor(float64(nn) / float64(altsRecordDefaultLength)))
|
||||
return partialBStart + numOfWrittenFrames*p.payloadLengthLimit, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
274
vendor/google.golang.org/grpc/credentials/alts/internal/conn/record_test.go
generated
vendored
Normal file
274
vendor/google.golang.org/grpc/credentials/alts/internal/conn/record_test.go
generated
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
nextProtocols = []string{"ALTSRP_GCM_AES128"}
|
||||
altsRecordFuncs = map[string]ALTSRecordFunc{
|
||||
// ALTS handshaker protocols.
|
||||
"ALTSRP_GCM_AES128": func(s core.Side, keyData []byte) (ALTSRecordCrypto, error) {
|
||||
return NewAES128GCM(s, keyData)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
for protocol, f := range altsRecordFuncs {
|
||||
if err := RegisterProtocol(protocol, f); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// testConn mimics a net.Conn to the peer.
|
||||
type testConn struct {
|
||||
net.Conn
|
||||
in *bytes.Buffer
|
||||
out *bytes.Buffer
|
||||
}
|
||||
|
||||
func (c *testConn) Read(b []byte) (n int, err error) {
|
||||
return c.in.Read(b)
|
||||
}
|
||||
|
||||
func (c *testConn) Write(b []byte) (n int, err error) {
|
||||
return c.out.Write(b)
|
||||
}
|
||||
|
||||
func (c *testConn) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newTestALTSRecordConn(in, out *bytes.Buffer, side core.Side, np string) *conn {
|
||||
key := []byte{
|
||||
// 16 arbitrary bytes.
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4c, 0xce, 0x4f, 0x49}
|
||||
tc := testConn{
|
||||
in: in,
|
||||
out: out,
|
||||
}
|
||||
c, err := NewConn(&tc, side, np, key, nil)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unexpected error creating test ALTS record connection: %v", err))
|
||||
}
|
||||
return c.(*conn)
|
||||
}
|
||||
|
||||
func newConnPair(np string) (client, server *conn) {
|
||||
clientBuf := new(bytes.Buffer)
|
||||
serverBuf := new(bytes.Buffer)
|
||||
clientConn := newTestALTSRecordConn(clientBuf, serverBuf, core.ClientSide, np)
|
||||
serverConn := newTestALTSRecordConn(serverBuf, clientBuf, core.ServerSide, np)
|
||||
return clientConn, serverConn
|
||||
}
|
||||
|
||||
func testPingPong(t *testing.T, np string) {
|
||||
clientConn, serverConn := newConnPair(np)
|
||||
clientMsg := []byte("Client Message")
|
||||
if n, err := clientConn.Write(clientMsg); n != len(clientMsg) || err != nil {
|
||||
t.Fatalf("Client Write() = %v, %v; want %v, <nil>", n, err, len(clientMsg))
|
||||
}
|
||||
rcvClientMsg := make([]byte, len(clientMsg))
|
||||
if n, err := serverConn.Read(rcvClientMsg); n != len(rcvClientMsg) || err != nil {
|
||||
t.Fatalf("Server Read() = %v, %v; want %v, <nil>", n, err, len(rcvClientMsg))
|
||||
}
|
||||
if !reflect.DeepEqual(clientMsg, rcvClientMsg) {
|
||||
t.Fatalf("Client Write()/Server Read() = %v, want %v", rcvClientMsg, clientMsg)
|
||||
}
|
||||
|
||||
serverMsg := []byte("Server Message")
|
||||
if n, err := serverConn.Write(serverMsg); n != len(serverMsg) || err != nil {
|
||||
t.Fatalf("Server Write() = %v, %v; want %v, <nil>", n, err, len(serverMsg))
|
||||
}
|
||||
rcvServerMsg := make([]byte, len(serverMsg))
|
||||
if n, err := clientConn.Read(rcvServerMsg); n != len(rcvServerMsg) || err != nil {
|
||||
t.Fatalf("Client Read() = %v, %v; want %v, <nil>", n, err, len(rcvServerMsg))
|
||||
}
|
||||
if !reflect.DeepEqual(serverMsg, rcvServerMsg) {
|
||||
t.Fatalf("Server Write()/Client Read() = %v, want %v", rcvServerMsg, serverMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPingPong(t *testing.T) {
|
||||
for _, np := range nextProtocols {
|
||||
testPingPong(t, np)
|
||||
}
|
||||
}
|
||||
|
||||
func testSmallReadBuffer(t *testing.T, np string) {
|
||||
clientConn, serverConn := newConnPair(np)
|
||||
msg := []byte("Very Important Message")
|
||||
if n, err := clientConn.Write(msg); err != nil {
|
||||
t.Fatalf("Write() = %v, %v; want %v, <nil>", n, err, len(msg))
|
||||
}
|
||||
rcvMsg := make([]byte, len(msg))
|
||||
n := 2 // Arbitrary index to break rcvMsg in two.
|
||||
rcvMsg1 := rcvMsg[:n]
|
||||
rcvMsg2 := rcvMsg[n:]
|
||||
if n, err := serverConn.Read(rcvMsg1); n != len(rcvMsg1) || err != nil {
|
||||
t.Fatalf("Read() = %v, %v; want %v, <nil>", n, err, len(rcvMsg1))
|
||||
}
|
||||
if n, err := serverConn.Read(rcvMsg2); n != len(rcvMsg2) || err != nil {
|
||||
t.Fatalf("Read() = %v, %v; want %v, <nil>", n, err, len(rcvMsg2))
|
||||
}
|
||||
if !reflect.DeepEqual(msg, rcvMsg) {
|
||||
t.Fatalf("Write()/Read() = %v, want %v", rcvMsg, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSmallReadBuffer(t *testing.T) {
|
||||
for _, np := range nextProtocols {
|
||||
testSmallReadBuffer(t, np)
|
||||
}
|
||||
}
|
||||
|
||||
func testLargeMsg(t *testing.T, np string) {
|
||||
clientConn, serverConn := newConnPair(np)
|
||||
// msgLen is such that the length in the framing is larger than the
|
||||
// default size of one frame.
|
||||
msgLen := altsRecordDefaultLength - msgTypeFieldSize - clientConn.crypto.EncryptionOverhead() + 1
|
||||
msg := make([]byte, msgLen)
|
||||
if n, err := clientConn.Write(msg); n != len(msg) || err != nil {
|
||||
t.Fatalf("Write() = %v, %v; want %v, <nil>", n, err, len(msg))
|
||||
}
|
||||
rcvMsg := make([]byte, len(msg))
|
||||
if n, err := io.ReadFull(serverConn, rcvMsg); n != len(rcvMsg) || err != nil {
|
||||
t.Fatalf("Read() = %v, %v; want %v, <nil>", n, err, len(rcvMsg))
|
||||
}
|
||||
if !reflect.DeepEqual(msg, rcvMsg) {
|
||||
t.Fatalf("Write()/Server Read() = %v, want %v", rcvMsg, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLargeMsg(t *testing.T) {
|
||||
for _, np := range nextProtocols {
|
||||
testLargeMsg(t, np)
|
||||
}
|
||||
}
|
||||
|
||||
func testIncorrectMsgType(t *testing.T, np string) {
|
||||
// framedMsg is an empty ciphertext with correct framing but wrong
|
||||
// message type.
|
||||
framedMsg := make([]byte, MsgLenFieldSize+msgTypeFieldSize)
|
||||
binary.LittleEndian.PutUint32(framedMsg[:MsgLenFieldSize], msgTypeFieldSize)
|
||||
wrongMsgType := uint32(0x22)
|
||||
binary.LittleEndian.PutUint32(framedMsg[MsgLenFieldSize:], wrongMsgType)
|
||||
|
||||
in := bytes.NewBuffer(framedMsg)
|
||||
c := newTestALTSRecordConn(in, nil, core.ClientSide, np)
|
||||
b := make([]byte, 1)
|
||||
if n, err := c.Read(b); n != 0 || err == nil {
|
||||
t.Fatalf("Read() = <nil>, want %v", fmt.Errorf("received frame with incorrect message type %v", wrongMsgType))
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncorrectMsgType(t *testing.T) {
|
||||
for _, np := range nextProtocols {
|
||||
testIncorrectMsgType(t, np)
|
||||
}
|
||||
}
|
||||
|
||||
func testFrameTooLarge(t *testing.T, np string) {
|
||||
buf := new(bytes.Buffer)
|
||||
clientConn := newTestALTSRecordConn(nil, buf, core.ClientSide, np)
|
||||
serverConn := newTestALTSRecordConn(buf, nil, core.ServerSide, np)
|
||||
// payloadLen is such that the length in the framing is larger than
|
||||
// allowed in one frame.
|
||||
payloadLen := altsRecordLengthLimit - msgTypeFieldSize - clientConn.crypto.EncryptionOverhead() + 1
|
||||
payload := make([]byte, payloadLen)
|
||||
c, err := clientConn.crypto.Encrypt(nil, payload)
|
||||
if err != nil {
|
||||
t.Fatalf(fmt.Sprintf("Error encrypting message: %v", err))
|
||||
}
|
||||
msgLen := msgTypeFieldSize + len(c)
|
||||
framedMsg := make([]byte, MsgLenFieldSize+msgLen)
|
||||
binary.LittleEndian.PutUint32(framedMsg[:MsgLenFieldSize], uint32(msgTypeFieldSize+len(c)))
|
||||
msg := framedMsg[MsgLenFieldSize:]
|
||||
binary.LittleEndian.PutUint32(msg[:msgTypeFieldSize], altsRecordMsgType)
|
||||
copy(msg[msgTypeFieldSize:], c)
|
||||
if _, err = buf.Write(framedMsg); err != nil {
|
||||
t.Fatal(fmt.Sprintf("Unexpected error writing to buffer: %v", err))
|
||||
}
|
||||
b := make([]byte, 1)
|
||||
if n, err := serverConn.Read(b); n != 0 || err == nil {
|
||||
t.Fatalf("Read() = <nil>, want %v", fmt.Errorf("received the frame length %d larger than the limit %d", altsRecordLengthLimit+1, altsRecordLengthLimit))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFrameTooLarge(t *testing.T) {
|
||||
for _, np := range nextProtocols {
|
||||
testFrameTooLarge(t, np)
|
||||
}
|
||||
}
|
||||
|
||||
func testWriteLargeData(t *testing.T, np string) {
|
||||
// Test sending and receiving messages larger than the maximum write
|
||||
// buffer size.
|
||||
clientConn, serverConn := newConnPair(np)
|
||||
// Message size is intentionally chosen to not be multiple of
|
||||
// payloadLengthLimtit.
|
||||
msgSize := altsWriteBufferMaxSize + (100 * 1024)
|
||||
clientMsg := make([]byte, msgSize)
|
||||
for i := 0; i < msgSize; i++ {
|
||||
clientMsg[i] = 0xAA
|
||||
}
|
||||
if n, err := clientConn.Write(clientMsg); n != len(clientMsg) || err != nil {
|
||||
t.Fatalf("Client Write() = %v, %v; want %v, <nil>", n, err, len(clientMsg))
|
||||
}
|
||||
// We need to keep reading until the entire message is received. The
|
||||
// reason we set all bytes of the message to a value other than zero is
|
||||
// to avoid ambiguous zero-init value of rcvClientMsg buffer and the
|
||||
// actual received data.
|
||||
rcvClientMsg := make([]byte, 0, msgSize)
|
||||
numberOfExpectedFrames := int(math.Ceil(float64(msgSize) / float64(serverConn.payloadLengthLimit)))
|
||||
for i := 0; i < numberOfExpectedFrames; i++ {
|
||||
expectedRcvSize := serverConn.payloadLengthLimit
|
||||
if i == numberOfExpectedFrames-1 {
|
||||
// Last frame might be smaller.
|
||||
expectedRcvSize = msgSize % serverConn.payloadLengthLimit
|
||||
}
|
||||
tmpBuf := make([]byte, expectedRcvSize)
|
||||
if n, err := serverConn.Read(tmpBuf); n != len(tmpBuf) || err != nil {
|
||||
t.Fatalf("Server Read() = %v, %v; want %v, <nil>", n, err, len(tmpBuf))
|
||||
}
|
||||
rcvClientMsg = append(rcvClientMsg, tmpBuf...)
|
||||
}
|
||||
if !reflect.DeepEqual(clientMsg, rcvClientMsg) {
|
||||
t.Fatalf("Client Write()/Server Read() = %v, want %v", rcvClientMsg, clientMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteLargeData(t *testing.T) {
|
||||
for _, np := range nextProtocols {
|
||||
testWriteLargeData(t, np)
|
||||
}
|
||||
}
|
63
vendor/google.golang.org/grpc/credentials/alts/internal/conn/utils.go
generated
vendored
Normal file
63
vendor/google.golang.org/grpc/credentials/alts/internal/conn/utils.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package conn
|
||||
|
||||
import core "google.golang.org/grpc/credentials/alts/internal"
|
||||
|
||||
// NewOutCounter returns an outgoing counter initialized to the starting sequence
|
||||
// number for the client/server side of a connection.
|
||||
func NewOutCounter(s core.Side, overflowLen int) (c Counter) {
|
||||
c.overflowLen = overflowLen
|
||||
if s == core.ServerSide {
|
||||
// Server counters in ALTS record have the little-endian high bit
|
||||
// set.
|
||||
c.value[counterLen-1] = 0x80
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewInCounter returns an incoming counter initialized to the starting sequence
|
||||
// number for the client/server side of a connection. This is used in ALTS record
|
||||
// to check that incoming counters are as expected, since ALTS record guarantees
|
||||
// that messages are unwrapped in the same order that the peer wrapped them.
|
||||
func NewInCounter(s core.Side, overflowLen int) (c Counter) {
|
||||
c.overflowLen = overflowLen
|
||||
if s == core.ClientSide {
|
||||
// Server counters in ALTS record have the little-endian high bit
|
||||
// set.
|
||||
c.value[counterLen-1] = 0x80
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CounterFromValue creates a new counter given an initial value.
|
||||
func CounterFromValue(value []byte, overflowLen int) (c Counter) {
|
||||
c.overflowLen = overflowLen
|
||||
copy(c.value[:], value)
|
||||
return
|
||||
}
|
||||
|
||||
// CounterSide returns the connection side (client/server) a sequence counter is
|
||||
// associated with.
|
||||
func CounterSide(c []byte) core.Side {
|
||||
if c[counterLen-1]&0x80 == 0x80 {
|
||||
return core.ServerSide
|
||||
}
|
||||
return core.ClientSide
|
||||
}
|
Reference in New Issue
Block a user