update vendor
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
19a32db84d
commit
94d1cfbfbf
10501 changed files with 2307943 additions and 29279 deletions
329
vendor/google.golang.org/grpc/credentials/alts/alts.go
generated
vendored
Normal file
329
vendor/google.golang.org/grpc/credentials/alts/alts.go
generated
vendored
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
*
|
||||
* 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 alts implements the ALTS credential support by gRPC library, which
|
||||
// encapsulates all the state needed by a client to authenticate with a server
|
||||
// using ALTS and make various assertions, e.g., about the client's identity,
|
||||
// role, or whether it is authorized to make a particular call.
|
||||
// This package is experimental.
|
||||
package alts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/credentials"
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
"google.golang.org/grpc/credentials/alts/internal/handshaker"
|
||||
"google.golang.org/grpc/credentials/alts/internal/handshaker/service"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
||||
const (
|
||||
// hypervisorHandshakerServiceAddress represents the default ALTS gRPC
|
||||
// handshaker service address in the hypervisor.
|
||||
hypervisorHandshakerServiceAddress = "metadata.google.internal:8080"
|
||||
// defaultTimeout specifies the server handshake timeout.
|
||||
defaultTimeout = 30.0 * time.Second
|
||||
// The following constants specify the minimum and maximum acceptable
|
||||
// protocol versions.
|
||||
protocolVersionMaxMajor = 2
|
||||
protocolVersionMaxMinor = 1
|
||||
protocolVersionMinMajor = 2
|
||||
protocolVersionMinMinor = 1
|
||||
)
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
maxRPCVersion = &altspb.RpcProtocolVersions_Version{
|
||||
Major: protocolVersionMaxMajor,
|
||||
Minor: protocolVersionMaxMinor,
|
||||
}
|
||||
minRPCVersion = &altspb.RpcProtocolVersions_Version{
|
||||
Major: protocolVersionMinMajor,
|
||||
Minor: protocolVersionMinMinor,
|
||||
}
|
||||
// ErrUntrustedPlatform is returned from ClientHandshake and
|
||||
// ServerHandshake is running on a platform where the trustworthiness of
|
||||
// the handshaker service is not guaranteed.
|
||||
ErrUntrustedPlatform = errors.New("untrusted platform")
|
||||
)
|
||||
|
||||
// AuthInfo exposes security information from the ALTS handshake to the
|
||||
// application. This interface is to be implemented by ALTS. Users should not
|
||||
// need a brand new implementation of this interface. For situations like
|
||||
// testing, any new implementation should embed this interface. This allows
|
||||
// ALTS to add new methods to this interface.
|
||||
type AuthInfo interface {
|
||||
// ApplicationProtocol returns application protocol negotiated for the
|
||||
// ALTS connection.
|
||||
ApplicationProtocol() string
|
||||
// RecordProtocol returns the record protocol negotiated for the ALTS
|
||||
// connection.
|
||||
RecordProtocol() string
|
||||
// SecurityLevel returns the security level of the created ALTS secure
|
||||
// channel.
|
||||
SecurityLevel() altspb.SecurityLevel
|
||||
// PeerServiceAccount returns the peer service account.
|
||||
PeerServiceAccount() string
|
||||
// LocalServiceAccount returns the local service account.
|
||||
LocalServiceAccount() string
|
||||
// PeerRPCVersions returns the RPC version supported by the peer.
|
||||
PeerRPCVersions() *altspb.RpcProtocolVersions
|
||||
}
|
||||
|
||||
// ClientOptions contains the client-side options of an ALTS channel. These
|
||||
// options will be passed to the underlying ALTS handshaker.
|
||||
type ClientOptions struct {
|
||||
// TargetServiceAccounts contains a list of expected target service
|
||||
// accounts.
|
||||
TargetServiceAccounts []string
|
||||
// HandshakerServiceAddress represents the ALTS handshaker gRPC service
|
||||
// address to connect to.
|
||||
HandshakerServiceAddress string
|
||||
}
|
||||
|
||||
// DefaultClientOptions creates a new ClientOptions object with the default
|
||||
// values.
|
||||
func DefaultClientOptions() *ClientOptions {
|
||||
return &ClientOptions{
|
||||
HandshakerServiceAddress: hypervisorHandshakerServiceAddress,
|
||||
}
|
||||
}
|
||||
|
||||
// ServerOptions contains the server-side options of an ALTS channel. These
|
||||
// options will be passed to the underlying ALTS handshaker.
|
||||
type ServerOptions struct {
|
||||
// HandshakerServiceAddress represents the ALTS handshaker gRPC service
|
||||
// address to connect to.
|
||||
HandshakerServiceAddress string
|
||||
}
|
||||
|
||||
// DefaultServerOptions creates a new ServerOptions object with the default
|
||||
// values.
|
||||
func DefaultServerOptions() *ServerOptions {
|
||||
return &ServerOptions{
|
||||
HandshakerServiceAddress: hypervisorHandshakerServiceAddress,
|
||||
}
|
||||
}
|
||||
|
||||
// altsTC is the credentials required for authenticating a connection using ALTS.
|
||||
// It implements credentials.TransportCredentials interface.
|
||||
type altsTC struct {
|
||||
info *credentials.ProtocolInfo
|
||||
side core.Side
|
||||
accounts []string
|
||||
hsAddress string
|
||||
}
|
||||
|
||||
// NewClientCreds constructs a client-side ALTS TransportCredentials object.
|
||||
func NewClientCreds(opts *ClientOptions) credentials.TransportCredentials {
|
||||
return newALTS(core.ClientSide, opts.TargetServiceAccounts, opts.HandshakerServiceAddress)
|
||||
}
|
||||
|
||||
// NewServerCreds constructs a server-side ALTS TransportCredentials object.
|
||||
func NewServerCreds(opts *ServerOptions) credentials.TransportCredentials {
|
||||
return newALTS(core.ServerSide, nil, opts.HandshakerServiceAddress)
|
||||
}
|
||||
|
||||
func newALTS(side core.Side, accounts []string, hsAddress string) credentials.TransportCredentials {
|
||||
once.Do(func() {
|
||||
vmOnGCP = isRunningOnGCP()
|
||||
})
|
||||
|
||||
if hsAddress == "" {
|
||||
hsAddress = hypervisorHandshakerServiceAddress
|
||||
}
|
||||
return &altsTC{
|
||||
info: &credentials.ProtocolInfo{
|
||||
SecurityProtocol: "alts",
|
||||
SecurityVersion: "1.0",
|
||||
},
|
||||
side: side,
|
||||
accounts: accounts,
|
||||
hsAddress: hsAddress,
|
||||
}
|
||||
}
|
||||
|
||||
// ClientHandshake implements the client side handshake protocol.
|
||||
func (g *altsTC) ClientHandshake(ctx context.Context, addr string, rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
|
||||
if !vmOnGCP {
|
||||
return nil, nil, ErrUntrustedPlatform
|
||||
}
|
||||
|
||||
// Connecting to ALTS handshaker service.
|
||||
hsConn, err := service.Dial(g.hsAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Do not close hsConn since it is shared with other handshakes.
|
||||
|
||||
// Possible context leak:
|
||||
// The cancel function for the child context we create will only be
|
||||
// called a non-nil error is returned.
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
opts := handshaker.DefaultClientHandshakerOptions()
|
||||
opts.TargetServiceAccounts = g.accounts
|
||||
opts.RPCVersions = &altspb.RpcProtocolVersions{
|
||||
MaxRpcVersion: maxRPCVersion,
|
||||
MinRpcVersion: minRPCVersion,
|
||||
}
|
||||
chs, err := handshaker.NewClientHandshaker(ctx, hsConn, rawConn, opts)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
chs.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
secConn, authInfo, err := chs.ClientHandshake(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
altsAuthInfo, ok := authInfo.(AuthInfo)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("client-side auth info is not of type alts.AuthInfo")
|
||||
}
|
||||
match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
|
||||
if !match {
|
||||
return nil, nil, fmt.Errorf("server-side RPC versions are not compatible with this client, local versions: %v, peer versions: %v", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
|
||||
}
|
||||
return secConn, authInfo, nil
|
||||
}
|
||||
|
||||
// ServerHandshake implements the server side ALTS handshaker.
|
||||
func (g *altsTC) ServerHandshake(rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
|
||||
if !vmOnGCP {
|
||||
return nil, nil, ErrUntrustedPlatform
|
||||
}
|
||||
// Connecting to ALTS handshaker service.
|
||||
hsConn, err := service.Dial(g.hsAddress)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Do not close hsConn since it's shared with other handshakes.
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
opts := handshaker.DefaultServerHandshakerOptions()
|
||||
opts.RPCVersions = &altspb.RpcProtocolVersions{
|
||||
MaxRpcVersion: maxRPCVersion,
|
||||
MinRpcVersion: minRPCVersion,
|
||||
}
|
||||
shs, err := handshaker.NewServerHandshaker(ctx, hsConn, rawConn, opts)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
shs.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
secConn, authInfo, err := shs.ServerHandshake(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
altsAuthInfo, ok := authInfo.(AuthInfo)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("server-side auth info is not of type alts.AuthInfo")
|
||||
}
|
||||
match, _ := checkRPCVersions(opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
|
||||
if !match {
|
||||
return nil, nil, fmt.Errorf("client-side RPC versions is not compatible with this server, local versions: %v, peer versions: %v", opts.RPCVersions, altsAuthInfo.PeerRPCVersions())
|
||||
}
|
||||
return secConn, authInfo, nil
|
||||
}
|
||||
|
||||
func (g *altsTC) Info() credentials.ProtocolInfo {
|
||||
return *g.info
|
||||
}
|
||||
|
||||
func (g *altsTC) Clone() credentials.TransportCredentials {
|
||||
info := *g.info
|
||||
var accounts []string
|
||||
if g.accounts != nil {
|
||||
accounts = make([]string, len(g.accounts))
|
||||
copy(accounts, g.accounts)
|
||||
}
|
||||
return &altsTC{
|
||||
info: &info,
|
||||
side: g.side,
|
||||
hsAddress: g.hsAddress,
|
||||
accounts: accounts,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *altsTC) OverrideServerName(serverNameOverride string) error {
|
||||
g.info.ServerName = serverNameOverride
|
||||
return nil
|
||||
}
|
||||
|
||||
// compareRPCVersion returns 0 if v1 == v2, 1 if v1 > v2 and -1 if v1 < v2.
|
||||
func compareRPCVersions(v1, v2 *altspb.RpcProtocolVersions_Version) int {
|
||||
switch {
|
||||
case v1.GetMajor() > v2.GetMajor(),
|
||||
v1.GetMajor() == v2.GetMajor() && v1.GetMinor() > v2.GetMinor():
|
||||
return 1
|
||||
case v1.GetMajor() < v2.GetMajor(),
|
||||
v1.GetMajor() == v2.GetMajor() && v1.GetMinor() < v2.GetMinor():
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// checkRPCVersions performs a version check between local and peer rpc protocol
|
||||
// versions. This function returns true if the check passes which means both
|
||||
// parties agreed on a common rpc protocol to use, and false otherwise. The
|
||||
// function also returns the highest common RPC protocol version both parties
|
||||
// agreed on.
|
||||
func checkRPCVersions(local, peer *altspb.RpcProtocolVersions) (bool, *altspb.RpcProtocolVersions_Version) {
|
||||
if local == nil || peer == nil {
|
||||
grpclog.Error("invalid checkRPCVersions argument, either local or peer is nil.")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// maxCommonVersion is MIN(local.max, peer.max).
|
||||
maxCommonVersion := local.GetMaxRpcVersion()
|
||||
if compareRPCVersions(local.GetMaxRpcVersion(), peer.GetMaxRpcVersion()) > 0 {
|
||||
maxCommonVersion = peer.GetMaxRpcVersion()
|
||||
}
|
||||
|
||||
// minCommonVersion is MAX(local.min, peer.min).
|
||||
minCommonVersion := peer.GetMinRpcVersion()
|
||||
if compareRPCVersions(local.GetMinRpcVersion(), peer.GetMinRpcVersion()) > 0 {
|
||||
minCommonVersion = local.GetMinRpcVersion()
|
||||
}
|
||||
|
||||
if compareRPCVersions(maxCommonVersion, minCommonVersion) < 0 {
|
||||
return false, nil
|
||||
}
|
||||
return true, maxCommonVersion
|
||||
}
|
290
vendor/google.golang.org/grpc/credentials/alts/alts_test.go
generated
vendored
Normal file
290
vendor/google.golang.org/grpc/credentials/alts/alts_test.go
generated
vendored
Normal file
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
*
|
||||
* 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 alts
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
)
|
||||
|
||||
func TestInfoServerName(t *testing.T) {
|
||||
// This is not testing any handshaker functionality, so it's fine to only
|
||||
// use NewServerCreds and not NewClientCreds.
|
||||
alts := NewServerCreds(DefaultServerOptions())
|
||||
if got, want := alts.Info().ServerName, ""; got != want {
|
||||
t.Fatalf("%v.Info().ServerName = %v, want %v", alts, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverrideServerName(t *testing.T) {
|
||||
wantServerName := "server.name"
|
||||
// This is not testing any handshaker functionality, so it's fine to only
|
||||
// use NewServerCreds and not NewClientCreds.
|
||||
c := NewServerCreds(DefaultServerOptions())
|
||||
c.OverrideServerName(wantServerName)
|
||||
if got, want := c.Info().ServerName, wantServerName; got != want {
|
||||
t.Fatalf("c.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneClient(t *testing.T) {
|
||||
wantServerName := "server.name"
|
||||
opt := DefaultClientOptions()
|
||||
opt.TargetServiceAccounts = []string{"not", "empty"}
|
||||
c := NewClientCreds(opt)
|
||||
c.OverrideServerName(wantServerName)
|
||||
cc := c.Clone()
|
||||
if got, want := cc.Info().ServerName, wantServerName; got != want {
|
||||
t.Fatalf("cc.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
cc.OverrideServerName("")
|
||||
if got, want := c.Info().ServerName, wantServerName; got != want {
|
||||
t.Fatalf("Change in clone should not affect the original, c.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := cc.Info().ServerName, ""; got != want {
|
||||
t.Fatalf("cc.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
|
||||
ct := c.(*altsTC)
|
||||
cct := cc.(*altsTC)
|
||||
|
||||
if ct.side != cct.side {
|
||||
t.Errorf("cc.side = %q, want %q", cct.side, ct.side)
|
||||
}
|
||||
if ct.hsAddress != cct.hsAddress {
|
||||
t.Errorf("cc.hsAddress = %q, want %q", cct.hsAddress, ct.hsAddress)
|
||||
}
|
||||
if !reflect.DeepEqual(ct.accounts, cct.accounts) {
|
||||
t.Errorf("cc.accounts = %q, want %q", cct.accounts, ct.accounts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneServer(t *testing.T) {
|
||||
wantServerName := "server.name"
|
||||
c := NewServerCreds(DefaultServerOptions())
|
||||
c.OverrideServerName(wantServerName)
|
||||
cc := c.Clone()
|
||||
if got, want := cc.Info().ServerName, wantServerName; got != want {
|
||||
t.Fatalf("cc.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
cc.OverrideServerName("")
|
||||
if got, want := c.Info().ServerName, wantServerName; got != want {
|
||||
t.Fatalf("Change in clone should not affect the original, c.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
if got, want := cc.Info().ServerName, ""; got != want {
|
||||
t.Fatalf("cc.Info().ServerName = %v, want %v", got, want)
|
||||
}
|
||||
|
||||
ct := c.(*altsTC)
|
||||
cct := cc.(*altsTC)
|
||||
|
||||
if ct.side != cct.side {
|
||||
t.Errorf("cc.side = %q, want %q", cct.side, ct.side)
|
||||
}
|
||||
if ct.hsAddress != cct.hsAddress {
|
||||
t.Errorf("cc.hsAddress = %q, want %q", cct.hsAddress, ct.hsAddress)
|
||||
}
|
||||
if !reflect.DeepEqual(ct.accounts, cct.accounts) {
|
||||
t.Errorf("cc.accounts = %q, want %q", cct.accounts, ct.accounts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
// This is not testing any handshaker functionality, so it's fine to only
|
||||
// use NewServerCreds and not NewClientCreds.
|
||||
c := NewServerCreds(DefaultServerOptions())
|
||||
info := c.Info()
|
||||
if got, want := info.ProtocolVersion, ""; got != want {
|
||||
t.Errorf("info.ProtocolVersion=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := info.SecurityProtocol, "alts"; got != want {
|
||||
t.Errorf("info.SecurityProtocol=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := info.SecurityVersion, "1.0"; got != want {
|
||||
t.Errorf("info.SecurityVersion=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := info.ServerName, ""; got != want {
|
||||
t.Errorf("info.ServerName=%v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareRPCVersions(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
v1 *altspb.RpcProtocolVersions_Version
|
||||
v2 *altspb.RpcProtocolVersions_Version
|
||||
output int
|
||||
}{
|
||||
{
|
||||
version(3, 2),
|
||||
version(2, 1),
|
||||
1,
|
||||
},
|
||||
{
|
||||
version(3, 2),
|
||||
version(3, 1),
|
||||
1,
|
||||
},
|
||||
{
|
||||
version(2, 1),
|
||||
version(3, 2),
|
||||
-1,
|
||||
},
|
||||
{
|
||||
version(3, 1),
|
||||
version(3, 2),
|
||||
-1,
|
||||
},
|
||||
{
|
||||
version(3, 2),
|
||||
version(3, 2),
|
||||
0,
|
||||
},
|
||||
} {
|
||||
if got, want := compareRPCVersions(tc.v1, tc.v2), tc.output; got != want {
|
||||
t.Errorf("compareRPCVersions(%v, %v)=%v, want %v", tc.v1, tc.v2, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckRPCVersions(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
local *altspb.RpcProtocolVersions
|
||||
peer *altspb.RpcProtocolVersions
|
||||
output bool
|
||||
maxCommonVersion *altspb.RpcProtocolVersions_Version
|
||||
}{
|
||||
{
|
||||
"local.max > peer.max and local.min > peer.min",
|
||||
versions(2, 1, 3, 2),
|
||||
versions(1, 2, 2, 1),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max > peer.max and local.min < peer.min",
|
||||
versions(1, 2, 3, 2),
|
||||
versions(2, 1, 2, 1),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max > peer.max and local.min = peer.min",
|
||||
versions(2, 1, 3, 2),
|
||||
versions(2, 1, 2, 1),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max < peer.max and local.min > peer.min",
|
||||
versions(2, 1, 2, 1),
|
||||
versions(1, 2, 3, 2),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max = peer.max and local.min > peer.min",
|
||||
versions(2, 1, 2, 1),
|
||||
versions(1, 2, 2, 1),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max < peer.max and local.min < peer.min",
|
||||
versions(1, 2, 2, 1),
|
||||
versions(2, 1, 3, 2),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max < peer.max and local.min = peer.min",
|
||||
versions(1, 2, 2, 1),
|
||||
versions(1, 2, 3, 2),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"local.max = peer.max and local.min < peer.min",
|
||||
versions(1, 2, 2, 1),
|
||||
versions(2, 1, 2, 1),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"all equal",
|
||||
versions(2, 1, 2, 1),
|
||||
versions(2, 1, 2, 1),
|
||||
true,
|
||||
version(2, 1),
|
||||
},
|
||||
{
|
||||
"max is smaller than min",
|
||||
versions(2, 1, 1, 2),
|
||||
versions(2, 1, 1, 2),
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"no overlap, local > peer",
|
||||
versions(4, 3, 6, 5),
|
||||
versions(1, 0, 2, 1),
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"no overlap, local < peer",
|
||||
versions(1, 0, 2, 1),
|
||||
versions(4, 3, 6, 5),
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"no overlap, max < min",
|
||||
versions(6, 5, 4, 3),
|
||||
versions(2, 1, 1, 0),
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
} {
|
||||
output, maxCommonVersion := checkRPCVersions(tc.local, tc.peer)
|
||||
if got, want := output, tc.output; got != want {
|
||||
t.Errorf("%v: checkRPCVersions(%v, %v)=(%v, _), want (%v, _)", tc.desc, tc.local, tc.peer, got, want)
|
||||
}
|
||||
if got, want := maxCommonVersion, tc.maxCommonVersion; !proto.Equal(got, want) {
|
||||
t.Errorf("%v: checkRPCVersions(%v, %v)=(_, %v), want (_, %v)", tc.desc, tc.local, tc.peer, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func version(major, minor uint32) *altspb.RpcProtocolVersions_Version {
|
||||
return &altspb.RpcProtocolVersions_Version{
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
}
|
||||
}
|
||||
|
||||
func versions(minMajor, minMinor, maxMajor, maxMinor uint32) *altspb.RpcProtocolVersions {
|
||||
return &altspb.RpcProtocolVersions{
|
||||
MinRpcVersion: version(minMajor, minMinor),
|
||||
MaxRpcVersion: version(maxMajor, maxMinor),
|
||||
}
|
||||
}
|
87
vendor/google.golang.org/grpc/credentials/alts/internal/authinfo/authinfo.go
generated
vendored
Normal file
87
vendor/google.golang.org/grpc/credentials/alts/internal/authinfo/authinfo.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
*
|
||||
* 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 authinfo provide authentication information returned by handshakers.
|
||||
package authinfo
|
||||
|
||||
import (
|
||||
"google.golang.org/grpc/credentials"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
)
|
||||
|
||||
var _ credentials.AuthInfo = (*altsAuthInfo)(nil)
|
||||
|
||||
// altsAuthInfo exposes security information from the ALTS handshake to the
|
||||
// application. altsAuthInfo is immutable and implements credentials.AuthInfo.
|
||||
type altsAuthInfo struct {
|
||||
p *altspb.AltsContext
|
||||
}
|
||||
|
||||
// New returns a new altsAuthInfo object given handshaker results.
|
||||
func New(result *altspb.HandshakerResult) credentials.AuthInfo {
|
||||
return newAuthInfo(result)
|
||||
}
|
||||
|
||||
func newAuthInfo(result *altspb.HandshakerResult) *altsAuthInfo {
|
||||
return &altsAuthInfo{
|
||||
p: &altspb.AltsContext{
|
||||
ApplicationProtocol: result.GetApplicationProtocol(),
|
||||
RecordProtocol: result.GetRecordProtocol(),
|
||||
// TODO: assign security level from result.
|
||||
SecurityLevel: altspb.SecurityLevel_INTEGRITY_AND_PRIVACY,
|
||||
PeerServiceAccount: result.GetPeerIdentity().GetServiceAccount(),
|
||||
LocalServiceAccount: result.GetLocalIdentity().GetServiceAccount(),
|
||||
PeerRpcVersions: result.GetPeerRpcVersions(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AuthType identifies the context as providing ALTS authentication information.
|
||||
func (s *altsAuthInfo) AuthType() string {
|
||||
return "alts"
|
||||
}
|
||||
|
||||
// ApplicationProtocol returns the context's application protocol.
|
||||
func (s *altsAuthInfo) ApplicationProtocol() string {
|
||||
return s.p.GetApplicationProtocol()
|
||||
}
|
||||
|
||||
// RecordProtocol returns the context's record protocol.
|
||||
func (s *altsAuthInfo) RecordProtocol() string {
|
||||
return s.p.GetRecordProtocol()
|
||||
}
|
||||
|
||||
// SecurityLevel returns the context's security level.
|
||||
func (s *altsAuthInfo) SecurityLevel() altspb.SecurityLevel {
|
||||
return s.p.GetSecurityLevel()
|
||||
}
|
||||
|
||||
// PeerServiceAccount returns the context's peer service account.
|
||||
func (s *altsAuthInfo) PeerServiceAccount() string {
|
||||
return s.p.GetPeerServiceAccount()
|
||||
}
|
||||
|
||||
// LocalServiceAccount returns the context's local service account.
|
||||
func (s *altsAuthInfo) LocalServiceAccount() string {
|
||||
return s.p.GetLocalServiceAccount()
|
||||
}
|
||||
|
||||
// PeerRPCVersions returns the context's peer RPC versions.
|
||||
func (s *altsAuthInfo) PeerRPCVersions() *altspb.RpcProtocolVersions {
|
||||
return s.p.GetPeerRpcVersions()
|
||||
}
|
134
vendor/google.golang.org/grpc/credentials/alts/internal/authinfo/authinfo_test.go
generated
vendored
Normal file
134
vendor/google.golang.org/grpc/credentials/alts/internal/authinfo/authinfo_test.go
generated
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
*
|
||||
* 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 authinfo
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
)
|
||||
|
||||
const (
|
||||
testAppProtocol = "my_app"
|
||||
testRecordProtocol = "very_secure_protocol"
|
||||
testPeerAccount = "peer_service_account"
|
||||
testLocalAccount = "local_service_account"
|
||||
testPeerHostname = "peer_hostname"
|
||||
testLocalHostname = "local_hostname"
|
||||
)
|
||||
|
||||
func TestALTSAuthInfo(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
result *altspb.HandshakerResult
|
||||
outAppProtocol string
|
||||
outRecordProtocol string
|
||||
outSecurityLevel altspb.SecurityLevel
|
||||
outPeerAccount string
|
||||
outLocalAccount string
|
||||
outPeerRPCVersions *altspb.RpcProtocolVersions
|
||||
}{
|
||||
{
|
||||
&altspb.HandshakerResult{
|
||||
ApplicationProtocol: testAppProtocol,
|
||||
RecordProtocol: testRecordProtocol,
|
||||
PeerIdentity: &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_ServiceAccount{
|
||||
ServiceAccount: testPeerAccount,
|
||||
},
|
||||
},
|
||||
LocalIdentity: &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_ServiceAccount{
|
||||
ServiceAccount: testLocalAccount,
|
||||
},
|
||||
},
|
||||
},
|
||||
testAppProtocol,
|
||||
testRecordProtocol,
|
||||
altspb.SecurityLevel_INTEGRITY_AND_PRIVACY,
|
||||
testPeerAccount,
|
||||
testLocalAccount,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
&altspb.HandshakerResult{
|
||||
ApplicationProtocol: testAppProtocol,
|
||||
RecordProtocol: testRecordProtocol,
|
||||
PeerIdentity: &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_Hostname{
|
||||
Hostname: testPeerHostname,
|
||||
},
|
||||
},
|
||||
LocalIdentity: &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_Hostname{
|
||||
Hostname: testLocalHostname,
|
||||
},
|
||||
},
|
||||
PeerRpcVersions: &altspb.RpcProtocolVersions{
|
||||
MaxRpcVersion: &altspb.RpcProtocolVersions_Version{
|
||||
Major: 20,
|
||||
Minor: 21,
|
||||
},
|
||||
MinRpcVersion: &altspb.RpcProtocolVersions_Version{
|
||||
Major: 10,
|
||||
Minor: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
testAppProtocol,
|
||||
testRecordProtocol,
|
||||
altspb.SecurityLevel_INTEGRITY_AND_PRIVACY,
|
||||
"",
|
||||
"",
|
||||
&altspb.RpcProtocolVersions{
|
||||
MaxRpcVersion: &altspb.RpcProtocolVersions_Version{
|
||||
Major: 20,
|
||||
Minor: 21,
|
||||
},
|
||||
MinRpcVersion: &altspb.RpcProtocolVersions_Version{
|
||||
Major: 10,
|
||||
Minor: 11,
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
authInfo := newAuthInfo(tc.result)
|
||||
if got, want := authInfo.AuthType(), "alts"; got != want {
|
||||
t.Errorf("authInfo.AuthType()=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := authInfo.ApplicationProtocol(), tc.outAppProtocol; got != want {
|
||||
t.Errorf("authInfo.ApplicationProtocol()=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := authInfo.RecordProtocol(), tc.outRecordProtocol; got != want {
|
||||
t.Errorf("authInfo.RecordProtocol()=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := authInfo.SecurityLevel(), tc.outSecurityLevel; got != want {
|
||||
t.Errorf("authInfo.SecurityLevel()=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := authInfo.PeerServiceAccount(), tc.outPeerAccount; got != want {
|
||||
t.Errorf("authInfo.PeerServiceAccount()=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := authInfo.LocalServiceAccount(), tc.outLocalAccount; got != want {
|
||||
t.Errorf("authInfo.LocalServiceAccount()=%v, want %v", got, want)
|
||||
}
|
||||
if got, want := authInfo.PeerRPCVersions(), tc.outPeerRPCVersions; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("authinfo.PeerRpcVersions()=%v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
69
vendor/google.golang.org/grpc/credentials/alts/internal/common.go
generated
vendored
Normal file
69
vendor/google.golang.org/grpc/credentials/alts/internal/common.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
//go:generate ./regenerate.sh
|
||||
|
||||
// Package internal contains common core functionality for ALTS.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
const (
|
||||
// ClientSide identifies the client in this communication.
|
||||
ClientSide Side = iota
|
||||
// ServerSide identifies the server in this communication.
|
||||
ServerSide
|
||||
)
|
||||
|
||||
// PeerNotRespondingError is returned when a peer server is not responding
|
||||
// after a channel has been established. It is treated as a temporary connection
|
||||
// error and re-connection to the server should be attempted.
|
||||
var PeerNotRespondingError = &peerNotRespondingError{}
|
||||
|
||||
// Side identifies the party's role: client or server.
|
||||
type Side int
|
||||
|
||||
type peerNotRespondingError struct{}
|
||||
|
||||
// Return an error message for the purpose of logging.
|
||||
func (e *peerNotRespondingError) Error() string {
|
||||
return "peer server is not responding and re-connection should be attempted."
|
||||
}
|
||||
|
||||
// Temporary indicates if this connection error is temporary or fatal.
|
||||
func (e *peerNotRespondingError) Temporary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Handshaker defines a ALTS handshaker interface.
|
||||
type Handshaker interface {
|
||||
// ClientHandshake starts and completes a client-side handshaking and
|
||||
// returns a secure connection and corresponding auth information.
|
||||
ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error)
|
||||
// ServerHandshake starts and completes a server-side handshaking and
|
||||
// returns a secure connection and corresponding auth information.
|
||||
ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error)
|
||||
// Close terminates the Handshaker. It should be called when the caller
|
||||
// obtains the secure connection.
|
||||
Close()
|
||||
}
|
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 not 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
|
||||
}
|
365
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/handshaker.go
generated
vendored
Normal file
365
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/handshaker.go
generated
vendored
Normal file
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
*
|
||||
* 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 handshaker provides ALTS handshaking functionality for GCP.
|
||||
package handshaker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
"google.golang.org/grpc/credentials/alts/internal/authinfo"
|
||||
"google.golang.org/grpc/credentials/alts/internal/conn"
|
||||
altsgrpc "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
)
|
||||
|
||||
const (
|
||||
// The maximum byte size of receive frames.
|
||||
frameLimit = 64 * 1024 // 64 KB
|
||||
rekeyRecordProtocolName = "ALTSRP_GCM_AES128_REKEY"
|
||||
// maxPendingHandshakes represents the maximum number of concurrent
|
||||
// handshakes.
|
||||
maxPendingHandshakes = 100
|
||||
)
|
||||
|
||||
var (
|
||||
hsProtocol = altspb.HandshakeProtocol_ALTS
|
||||
appProtocols = []string{"grpc"}
|
||||
recordProtocols = []string{rekeyRecordProtocolName}
|
||||
keyLength = map[string]int{
|
||||
rekeyRecordProtocolName: 44,
|
||||
}
|
||||
altsRecordFuncs = map[string]conn.ALTSRecordFunc{
|
||||
// ALTS handshaker protocols.
|
||||
rekeyRecordProtocolName: func(s core.Side, keyData []byte) (conn.ALTSRecordCrypto, error) {
|
||||
return conn.NewAES128GCMRekey(s, keyData)
|
||||
},
|
||||
}
|
||||
// control number of concurrent created (but not closed) handshakers.
|
||||
mu sync.Mutex
|
||||
concurrentHandshakes = int64(0)
|
||||
// errDropped occurs when maxPendingHandshakes is reached.
|
||||
errDropped = errors.New("maximum number of concurrent ALTS handshakes is reached")
|
||||
)
|
||||
|
||||
func init() {
|
||||
for protocol, f := range altsRecordFuncs {
|
||||
if err := conn.RegisterProtocol(protocol, f); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func acquire(n int64) bool {
|
||||
mu.Lock()
|
||||
success := maxPendingHandshakes-concurrentHandshakes >= n
|
||||
if success {
|
||||
concurrentHandshakes += n
|
||||
}
|
||||
mu.Unlock()
|
||||
return success
|
||||
}
|
||||
|
||||
func release(n int64) {
|
||||
mu.Lock()
|
||||
concurrentHandshakes -= n
|
||||
if concurrentHandshakes < 0 {
|
||||
mu.Unlock()
|
||||
panic("bad release")
|
||||
}
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
// ClientHandshakerOptions contains the client handshaker options that can
|
||||
// provided by the caller.
|
||||
type ClientHandshakerOptions struct {
|
||||
// ClientIdentity is the handshaker client local identity.
|
||||
ClientIdentity *altspb.Identity
|
||||
// TargetName is the server service account name for secure name
|
||||
// checking.
|
||||
TargetName string
|
||||
// TargetServiceAccounts contains a list of expected target service
|
||||
// accounts. One of these accounts should match one of the accounts in
|
||||
// the handshaker results. Otherwise, the handshake fails.
|
||||
TargetServiceAccounts []string
|
||||
// RPCVersions specifies the gRPC versions accepted by the client.
|
||||
RPCVersions *altspb.RpcProtocolVersions
|
||||
}
|
||||
|
||||
// ServerHandshakerOptions contains the server handshaker options that can
|
||||
// provided by the caller.
|
||||
type ServerHandshakerOptions struct {
|
||||
// RPCVersions specifies the gRPC versions accepted by the server.
|
||||
RPCVersions *altspb.RpcProtocolVersions
|
||||
}
|
||||
|
||||
// DefaultClientHandshakerOptions returns the default client handshaker options.
|
||||
func DefaultClientHandshakerOptions() *ClientHandshakerOptions {
|
||||
return &ClientHandshakerOptions{}
|
||||
}
|
||||
|
||||
// DefaultServerHandshakerOptions returns the default client handshaker options.
|
||||
func DefaultServerHandshakerOptions() *ServerHandshakerOptions {
|
||||
return &ServerHandshakerOptions{}
|
||||
}
|
||||
|
||||
// TODO: add support for future local and remote endpoint in both client options
|
||||
// and server options (server options struct does not exist now. When
|
||||
// caller can provide endpoints, it should be created.
|
||||
|
||||
// altsHandshaker is used to complete a ALTS handshaking between client and
|
||||
// server. This handshaker talks to the ALTS handshaker service in the metadata
|
||||
// server.
|
||||
type altsHandshaker struct {
|
||||
// RPC stream used to access the ALTS Handshaker service.
|
||||
stream altsgrpc.HandshakerService_DoHandshakeClient
|
||||
// the connection to the peer.
|
||||
conn net.Conn
|
||||
// client handshake options.
|
||||
clientOpts *ClientHandshakerOptions
|
||||
// server handshake options.
|
||||
serverOpts *ServerHandshakerOptions
|
||||
// defines the side doing the handshake, client or server.
|
||||
side core.Side
|
||||
}
|
||||
|
||||
// NewClientHandshaker creates a ALTS handshaker for GCP which contains an RPC
|
||||
// stub created using the passed conn and used to talk to the ALTS Handshaker
|
||||
// service in the metadata server.
|
||||
func NewClientHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, opts *ClientHandshakerOptions) (core.Handshaker, error) {
|
||||
stream, err := altsgrpc.NewHandshakerServiceClient(conn).DoHandshake(ctx, grpc.FailFast(false))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &altsHandshaker{
|
||||
stream: stream,
|
||||
conn: c,
|
||||
clientOpts: opts,
|
||||
side: core.ClientSide,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewServerHandshaker creates a ALTS handshaker for GCP which contains an RPC
|
||||
// stub created using the passed conn and used to talk to the ALTS Handshaker
|
||||
// service in the metadata server.
|
||||
func NewServerHandshaker(ctx context.Context, conn *grpc.ClientConn, c net.Conn, opts *ServerHandshakerOptions) (core.Handshaker, error) {
|
||||
stream, err := altsgrpc.NewHandshakerServiceClient(conn).DoHandshake(ctx, grpc.FailFast(false))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &altsHandshaker{
|
||||
stream: stream,
|
||||
conn: c,
|
||||
serverOpts: opts,
|
||||
side: core.ServerSide,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ClientHandshake starts and completes a client ALTS handshaking for GCP. Once
|
||||
// done, ClientHandshake returns a secure connection.
|
||||
func (h *altsHandshaker) ClientHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {
|
||||
if !acquire(1) {
|
||||
return nil, nil, errDropped
|
||||
}
|
||||
defer release(1)
|
||||
|
||||
if h.side != core.ClientSide {
|
||||
return nil, nil, errors.New("only handshakers created using NewClientHandshaker can perform a client handshaker")
|
||||
}
|
||||
|
||||
// Create target identities from service account list.
|
||||
targetIdentities := make([]*altspb.Identity, 0, len(h.clientOpts.TargetServiceAccounts))
|
||||
for _, account := range h.clientOpts.TargetServiceAccounts {
|
||||
targetIdentities = append(targetIdentities, &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_ServiceAccount{
|
||||
ServiceAccount: account,
|
||||
},
|
||||
})
|
||||
}
|
||||
req := &altspb.HandshakerReq{
|
||||
ReqOneof: &altspb.HandshakerReq_ClientStart{
|
||||
ClientStart: &altspb.StartClientHandshakeReq{
|
||||
HandshakeSecurityProtocol: hsProtocol,
|
||||
ApplicationProtocols: appProtocols,
|
||||
RecordProtocols: recordProtocols,
|
||||
TargetIdentities: targetIdentities,
|
||||
LocalIdentity: h.clientOpts.ClientIdentity,
|
||||
TargetName: h.clientOpts.TargetName,
|
||||
RpcVersions: h.clientOpts.RPCVersions,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn, result, err := h.doHandshake(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authInfo := authinfo.New(result)
|
||||
return conn, authInfo, nil
|
||||
}
|
||||
|
||||
// ServerHandshake starts and completes a server ALTS handshaking for GCP. Once
|
||||
// done, ServerHandshake returns a secure connection.
|
||||
func (h *altsHandshaker) ServerHandshake(ctx context.Context) (net.Conn, credentials.AuthInfo, error) {
|
||||
if !acquire(1) {
|
||||
return nil, nil, errDropped
|
||||
}
|
||||
defer release(1)
|
||||
|
||||
if h.side != core.ServerSide {
|
||||
return nil, nil, errors.New("only handshakers created using NewServerHandshaker can perform a server handshaker")
|
||||
}
|
||||
|
||||
p := make([]byte, frameLimit)
|
||||
n, err := h.conn.Read(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Prepare server parameters.
|
||||
// TODO: currently only ALTS parameters are provided. Might need to use
|
||||
// more options in the future.
|
||||
params := make(map[int32]*altspb.ServerHandshakeParameters)
|
||||
params[int32(altspb.HandshakeProtocol_ALTS)] = &altspb.ServerHandshakeParameters{
|
||||
RecordProtocols: recordProtocols,
|
||||
}
|
||||
req := &altspb.HandshakerReq{
|
||||
ReqOneof: &altspb.HandshakerReq_ServerStart{
|
||||
ServerStart: &altspb.StartServerHandshakeReq{
|
||||
ApplicationProtocols: appProtocols,
|
||||
HandshakeParameters: params,
|
||||
InBytes: p[:n],
|
||||
RpcVersions: h.serverOpts.RPCVersions,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn, result, err := h.doHandshake(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authInfo := authinfo.New(result)
|
||||
return conn, authInfo, nil
|
||||
}
|
||||
|
||||
func (h *altsHandshaker) doHandshake(req *altspb.HandshakerReq) (net.Conn, *altspb.HandshakerResult, error) {
|
||||
resp, err := h.accessHandshakerService(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Check of the returned status is an error.
|
||||
if resp.GetStatus() != nil {
|
||||
if got, want := resp.GetStatus().Code, uint32(codes.OK); got != want {
|
||||
return nil, nil, fmt.Errorf("%v", resp.GetStatus().Details)
|
||||
}
|
||||
}
|
||||
|
||||
var extra []byte
|
||||
if req.GetServerStart() != nil {
|
||||
extra = req.GetServerStart().GetInBytes()[resp.GetBytesConsumed():]
|
||||
}
|
||||
result, extra, err := h.processUntilDone(resp, extra)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// The handshaker returns a 128 bytes key. It should be truncated based
|
||||
// on the returned record protocol.
|
||||
keyLen, ok := keyLength[result.RecordProtocol]
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unknown resulted record protocol %v", result.RecordProtocol)
|
||||
}
|
||||
sc, err := conn.NewConn(h.conn, h.side, result.GetRecordProtocol(), result.KeyData[:keyLen], extra)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return sc, result, nil
|
||||
}
|
||||
|
||||
func (h *altsHandshaker) accessHandshakerService(req *altspb.HandshakerReq) (*altspb.HandshakerResp, error) {
|
||||
if err := h.stream.Send(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := h.stream.Recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// processUntilDone processes the handshake until the handshaker service returns
|
||||
// the results. Handshaker service takes care of frame parsing, so we read
|
||||
// whatever received from the network and send it to the handshaker service.
|
||||
func (h *altsHandshaker) processUntilDone(resp *altspb.HandshakerResp, extra []byte) (*altspb.HandshakerResult, []byte, error) {
|
||||
for {
|
||||
if len(resp.OutFrames) > 0 {
|
||||
if _, err := h.conn.Write(resp.OutFrames); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
if resp.Result != nil {
|
||||
return resp.Result, extra, nil
|
||||
}
|
||||
buf := make([]byte, frameLimit)
|
||||
n, err := h.conn.Read(buf)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, nil, err
|
||||
}
|
||||
// If there is nothing to send to the handshaker service, and
|
||||
// nothing is received from the peer, then we are stuck.
|
||||
// This covers the case when the peer is not responding. Note
|
||||
// that handshaker service connection issues are caught in
|
||||
// accessHandshakerService before we even get here.
|
||||
if len(resp.OutFrames) == 0 && n == 0 {
|
||||
return nil, nil, core.PeerNotRespondingError
|
||||
}
|
||||
// Append extra bytes from the previous interaction with the
|
||||
// handshaker service with the current buffer read from conn.
|
||||
p := append(extra, buf[:n]...)
|
||||
resp, err = h.accessHandshakerService(&altspb.HandshakerReq{
|
||||
ReqOneof: &altspb.HandshakerReq_Next{
|
||||
Next: &altspb.NextHandshakeMessageReq{
|
||||
InBytes: p,
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Set extra based on handshaker service response.
|
||||
if n == 0 {
|
||||
extra = nil
|
||||
} else {
|
||||
extra = buf[resp.GetBytesConsumed():n]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close terminates the Handshaker. It should be called when the caller obtains
|
||||
// the secure connection.
|
||||
func (h *altsHandshaker) Close() {
|
||||
h.stream.CloseSend()
|
||||
}
|
261
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/handshaker_test.go
generated
vendored
Normal file
261
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/handshaker_test.go
generated
vendored
Normal file
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
*
|
||||
* 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 handshaker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
core "google.golang.org/grpc/credentials/alts/internal"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
"google.golang.org/grpc/credentials/alts/internal/testutil"
|
||||
)
|
||||
|
||||
var (
|
||||
testAppProtocols = []string{"grpc"}
|
||||
testRecordProtocol = rekeyRecordProtocolName
|
||||
testKey = []byte{
|
||||
// 44 arbitrary bytes.
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4c, 0xce, 0x4f, 0x49,
|
||||
0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xd2, 0x4c, 0xce, 0x4f, 0x49, 0x1f, 0x8b,
|
||||
0xd2, 0x4c, 0xce, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2,
|
||||
}
|
||||
testServiceAccount = "test_service_account"
|
||||
testTargetServiceAccounts = []string{testServiceAccount}
|
||||
testClientIdentity = &altspb.Identity{
|
||||
IdentityOneof: &altspb.Identity_Hostname{
|
||||
Hostname: "i_am_a_client",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// testRPCStream mimics a altspb.HandshakerService_DoHandshakeClient object.
|
||||
type testRPCStream struct {
|
||||
grpc.ClientStream
|
||||
t *testing.T
|
||||
isClient bool
|
||||
// The resp expected to be returned by Recv(). Make sure this is set to
|
||||
// the content the test requires before Recv() is invoked.
|
||||
recvBuf *altspb.HandshakerResp
|
||||
// false if it is the first access to Handshaker service on Envelope.
|
||||
first bool
|
||||
// useful for testing concurrent calls.
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
func (t *testRPCStream) Recv() (*altspb.HandshakerResp, error) {
|
||||
resp := t.recvBuf
|
||||
t.recvBuf = nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (t *testRPCStream) Send(req *altspb.HandshakerReq) error {
|
||||
var resp *altspb.HandshakerResp
|
||||
if !t.first {
|
||||
// Generate the bytes to be returned by Recv() for the initial
|
||||
// handshaking.
|
||||
t.first = true
|
||||
if t.isClient {
|
||||
resp = &altspb.HandshakerResp{
|
||||
OutFrames: testutil.MakeFrame("ClientInit"),
|
||||
// Simulate consuming ServerInit.
|
||||
BytesConsumed: 14,
|
||||
}
|
||||
} else {
|
||||
resp = &altspb.HandshakerResp{
|
||||
OutFrames: testutil.MakeFrame("ServerInit"),
|
||||
// Simulate consuming ClientInit.
|
||||
BytesConsumed: 14,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Add delay to test concurrent calls.
|
||||
cleanup := stat.Update()
|
||||
defer cleanup()
|
||||
time.Sleep(t.delay)
|
||||
|
||||
// Generate the response to be returned by Recv() for the
|
||||
// follow-up handshaking.
|
||||
result := &altspb.HandshakerResult{
|
||||
RecordProtocol: testRecordProtocol,
|
||||
KeyData: testKey,
|
||||
}
|
||||
resp = &altspb.HandshakerResp{
|
||||
Result: result,
|
||||
// Simulate consuming ClientFinished or ServerFinished.
|
||||
BytesConsumed: 18,
|
||||
}
|
||||
}
|
||||
t.recvBuf = resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *testRPCStream) CloseSend() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var stat testutil.Stats
|
||||
|
||||
func TestClientHandshake(t *testing.T) {
|
||||
for _, testCase := range []struct {
|
||||
delay time.Duration
|
||||
numberOfHandshakes int
|
||||
}{
|
||||
{0 * time.Millisecond, 1},
|
||||
{100 * time.Millisecond, 10 * maxPendingHandshakes},
|
||||
} {
|
||||
errc := make(chan error)
|
||||
stat.Reset()
|
||||
for i := 0; i < testCase.numberOfHandshakes; i++ {
|
||||
stream := &testRPCStream{
|
||||
t: t,
|
||||
isClient: true,
|
||||
}
|
||||
// Preload the inbound frames.
|
||||
f1 := testutil.MakeFrame("ServerInit")
|
||||
f2 := testutil.MakeFrame("ServerFinished")
|
||||
in := bytes.NewBuffer(f1)
|
||||
in.Write(f2)
|
||||
out := new(bytes.Buffer)
|
||||
tc := testutil.NewTestConn(in, out)
|
||||
chs := &altsHandshaker{
|
||||
stream: stream,
|
||||
conn: tc,
|
||||
clientOpts: &ClientHandshakerOptions{
|
||||
TargetServiceAccounts: testTargetServiceAccounts,
|
||||
ClientIdentity: testClientIdentity,
|
||||
},
|
||||
side: core.ClientSide,
|
||||
}
|
||||
go func() {
|
||||
_, context, err := chs.ClientHandshake(context.Background())
|
||||
if err == nil && context == nil {
|
||||
panic("expected non-nil ALTS context")
|
||||
}
|
||||
errc <- err
|
||||
chs.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// Ensure all errors are expected.
|
||||
for i := 0; i < testCase.numberOfHandshakes; i++ {
|
||||
if err := <-errc; err != nil && err != errDropped {
|
||||
t.Errorf("ClientHandshake() = _, %v, want _, <nil> or %v", err, errDropped)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there are no concurrent calls more than the limit.
|
||||
if stat.MaxConcurrentCalls > maxPendingHandshakes {
|
||||
t.Errorf("Observed %d concurrent handshakes; want <= %d", stat.MaxConcurrentCalls, maxPendingHandshakes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerHandshake(t *testing.T) {
|
||||
for _, testCase := range []struct {
|
||||
delay time.Duration
|
||||
numberOfHandshakes int
|
||||
}{
|
||||
{0 * time.Millisecond, 1},
|
||||
{100 * time.Millisecond, 10 * maxPendingHandshakes},
|
||||
} {
|
||||
errc := make(chan error)
|
||||
stat.Reset()
|
||||
for i := 0; i < testCase.numberOfHandshakes; i++ {
|
||||
stream := &testRPCStream{
|
||||
t: t,
|
||||
isClient: false,
|
||||
}
|
||||
// Preload the inbound frames.
|
||||
f1 := testutil.MakeFrame("ClientInit")
|
||||
f2 := testutil.MakeFrame("ClientFinished")
|
||||
in := bytes.NewBuffer(f1)
|
||||
in.Write(f2)
|
||||
out := new(bytes.Buffer)
|
||||
tc := testutil.NewTestConn(in, out)
|
||||
shs := &altsHandshaker{
|
||||
stream: stream,
|
||||
conn: tc,
|
||||
serverOpts: DefaultServerHandshakerOptions(),
|
||||
side: core.ServerSide,
|
||||
}
|
||||
go func() {
|
||||
_, context, err := shs.ServerHandshake(context.Background())
|
||||
if err == nil && context == nil {
|
||||
panic("expected non-nil ALTS context")
|
||||
}
|
||||
errc <- err
|
||||
shs.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// Ensure all errors are expected.
|
||||
for i := 0; i < testCase.numberOfHandshakes; i++ {
|
||||
if err := <-errc; err != nil && err != errDropped {
|
||||
t.Errorf("ServerHandshake() = _, %v, want _, <nil> or %v", err, errDropped)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there are no concurrent calls more than the limit.
|
||||
if stat.MaxConcurrentCalls > maxPendingHandshakes {
|
||||
t.Errorf("Observed %d concurrent handshakes; want <= %d", stat.MaxConcurrentCalls, maxPendingHandshakes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// testUnresponsiveRPCStream is used for testing the PeerNotResponding case.
|
||||
type testUnresponsiveRPCStream struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (t *testUnresponsiveRPCStream) Recv() (*altspb.HandshakerResp, error) {
|
||||
return &altspb.HandshakerResp{}, nil
|
||||
}
|
||||
|
||||
func (t *testUnresponsiveRPCStream) Send(req *altspb.HandshakerReq) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *testUnresponsiveRPCStream) CloseSend() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPeerNotResponding(t *testing.T) {
|
||||
stream := &testUnresponsiveRPCStream{}
|
||||
chs := &altsHandshaker{
|
||||
stream: stream,
|
||||
conn: testutil.NewUnresponsiveTestConn(),
|
||||
clientOpts: &ClientHandshakerOptions{
|
||||
TargetServiceAccounts: testTargetServiceAccounts,
|
||||
ClientIdentity: testClientIdentity,
|
||||
},
|
||||
side: core.ClientSide,
|
||||
}
|
||||
_, context, err := chs.ClientHandshake(context.Background())
|
||||
chs.Close()
|
||||
if context != nil {
|
||||
t.Error("expected non-nil ALTS context")
|
||||
}
|
||||
if got, want := err, core.PeerNotRespondingError; got != want {
|
||||
t.Errorf("ClientHandshake() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
56
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/service/service.go
generated
vendored
Normal file
56
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/service/service.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
*
|
||||
* 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 service manages connections between the VM application and the ALTS
|
||||
// handshaker service.
|
||||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
// hsConn represents a connection to hypervisor handshaker service.
|
||||
hsConn *grpc.ClientConn
|
||||
mu sync.Mutex
|
||||
// hsDialer will be reassigned in tests.
|
||||
hsDialer = grpc.Dial
|
||||
)
|
||||
|
||||
type dialer func(target string, opts ...grpc.DialOption) (*grpc.ClientConn, error)
|
||||
|
||||
// Dial dials the handshake service in the hypervisor. If a connection has
|
||||
// already been established, this function returns it. Otherwise, a new
|
||||
// connection is created.
|
||||
func Dial(hsAddress string) (*grpc.ClientConn, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
if hsConn == nil {
|
||||
// Create a new connection to the handshaker service. Note that
|
||||
// this connection stays open until the application is closed.
|
||||
var err error
|
||||
hsConn, err = hsDialer(hsAddress, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return hsConn, nil
|
||||
}
|
69
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/service/service_test.go
generated
vendored
Normal file
69
vendor/google.golang.org/grpc/credentials/alts/internal/handshaker/service/service_test.go
generated
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
*
|
||||
* 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 service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
// The address is irrelevant in this test.
|
||||
testAddress = "some_address"
|
||||
)
|
||||
|
||||
func TestDial(t *testing.T) {
|
||||
defer func() func() {
|
||||
temp := hsDialer
|
||||
hsDialer = func(target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) {
|
||||
return &grpc.ClientConn{}, nil
|
||||
}
|
||||
return func() {
|
||||
hsDialer = temp
|
||||
}
|
||||
}()
|
||||
|
||||
// Ensure that hsConn is nil at first.
|
||||
hsConn = nil
|
||||
|
||||
// First call to Dial, it should create set hsConn.
|
||||
conn1, err := Dial(testAddress)
|
||||
if err != nil {
|
||||
t.Fatalf("first call to Dial failed: %v", err)
|
||||
}
|
||||
if conn1 == nil {
|
||||
t.Fatal("first call to Dial(_)=(nil, _), want not nil")
|
||||
}
|
||||
if got, want := hsConn, conn1; got != want {
|
||||
t.Fatalf("hsConn=%v, want %v", got, want)
|
||||
}
|
||||
|
||||
// Second call to Dial should return conn1 above.
|
||||
conn2, err := Dial(testAddress)
|
||||
if err != nil {
|
||||
t.Fatalf("second call to Dial(_) failed: %v", err)
|
||||
}
|
||||
if got, want := conn2, conn1; got != want {
|
||||
t.Fatalf("second call to Dial(_)=(%v, _), want (%v,. _)", got, want)
|
||||
}
|
||||
if got, want := hsConn, conn1; got != want {
|
||||
t.Fatalf("hsConn=%v, want %v", got, want)
|
||||
}
|
||||
}
|
136
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go
generated
vendored
Normal file
136
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: grpc/gcp/altscontext.proto
|
||||
|
||||
package grpc_gcp // import "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type AltsContext struct {
|
||||
// The application protocol negotiated for this connection.
|
||||
ApplicationProtocol string `protobuf:"bytes,1,opt,name=application_protocol,json=applicationProtocol,proto3" json:"application_protocol,omitempty"`
|
||||
// The record protocol negotiated for this connection.
|
||||
RecordProtocol string `protobuf:"bytes,2,opt,name=record_protocol,json=recordProtocol,proto3" json:"record_protocol,omitempty"`
|
||||
// The security level of the created secure channel.
|
||||
SecurityLevel SecurityLevel `protobuf:"varint,3,opt,name=security_level,json=securityLevel,proto3,enum=grpc.gcp.SecurityLevel" json:"security_level,omitempty"`
|
||||
// The peer service account.
|
||||
PeerServiceAccount string `protobuf:"bytes,4,opt,name=peer_service_account,json=peerServiceAccount,proto3" json:"peer_service_account,omitempty"`
|
||||
// The local service account.
|
||||
LocalServiceAccount string `protobuf:"bytes,5,opt,name=local_service_account,json=localServiceAccount,proto3" json:"local_service_account,omitempty"`
|
||||
// The RPC protocol versions supported by the peer.
|
||||
PeerRpcVersions *RpcProtocolVersions `protobuf:"bytes,6,opt,name=peer_rpc_versions,json=peerRpcVersions,proto3" json:"peer_rpc_versions,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AltsContext) Reset() { *m = AltsContext{} }
|
||||
func (m *AltsContext) String() string { return proto.CompactTextString(m) }
|
||||
func (*AltsContext) ProtoMessage() {}
|
||||
func (*AltsContext) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_altscontext_4d8d0120fd718d8c, []int{0}
|
||||
}
|
||||
func (m *AltsContext) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AltsContext.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AltsContext) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AltsContext.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *AltsContext) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AltsContext.Merge(dst, src)
|
||||
}
|
||||
func (m *AltsContext) XXX_Size() int {
|
||||
return xxx_messageInfo_AltsContext.Size(m)
|
||||
}
|
||||
func (m *AltsContext) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AltsContext.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AltsContext proto.InternalMessageInfo
|
||||
|
||||
func (m *AltsContext) GetApplicationProtocol() string {
|
||||
if m != nil {
|
||||
return m.ApplicationProtocol
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AltsContext) GetRecordProtocol() string {
|
||||
if m != nil {
|
||||
return m.RecordProtocol
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AltsContext) GetSecurityLevel() SecurityLevel {
|
||||
if m != nil {
|
||||
return m.SecurityLevel
|
||||
}
|
||||
return SecurityLevel_SECURITY_NONE
|
||||
}
|
||||
|
||||
func (m *AltsContext) GetPeerServiceAccount() string {
|
||||
if m != nil {
|
||||
return m.PeerServiceAccount
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AltsContext) GetLocalServiceAccount() string {
|
||||
if m != nil {
|
||||
return m.LocalServiceAccount
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AltsContext) GetPeerRpcVersions() *RpcProtocolVersions {
|
||||
if m != nil {
|
||||
return m.PeerRpcVersions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*AltsContext)(nil), "grpc.gcp.AltsContext")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("grpc/gcp/altscontext.proto", fileDescriptor_altscontext_4d8d0120fd718d8c)
|
||||
}
|
||||
|
||||
var fileDescriptor_altscontext_4d8d0120fd718d8c = []byte{
|
||||
// 335 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x91, 0xcf, 0x4b, 0x2b, 0x31,
|
||||
0x10, 0xc7, 0xd9, 0xbe, 0xf7, 0xca, 0x33, 0xc5, 0x56, 0xd7, 0x16, 0x97, 0x82, 0x50, 0xbc, 0xb8,
|
||||
0xa7, 0x5d, 0xad, 0x77, 0xa5, 0xf5, 0x24, 0x78, 0x28, 0x5b, 0xf0, 0xe0, 0x65, 0x89, 0xd3, 0x10,
|
||||
0x02, 0x69, 0x26, 0x4c, 0xd2, 0xa2, 0xff, 0xaa, 0x7f, 0x8d, 0x6c, 0xd2, 0x6d, 0x8b, 0x1e, 0x67,
|
||||
0x3e, 0xdf, 0xef, 0xfc, 0x64, 0x63, 0x49, 0x16, 0x4a, 0x09, 0xb6, 0xe4, 0xda, 0x3b, 0x40, 0xe3,
|
||||
0xc5, 0x87, 0x2f, 0x2c, 0xa1, 0xc7, 0xf4, 0x7f, 0xc3, 0x0a, 0x09, 0x76, 0x9c, 0xef, 0x55, 0x9e,
|
||||
0xb8, 0x71, 0x16, 0xc9, 0xd7, 0x4e, 0xc0, 0x86, 0x94, 0xff, 0xac, 0x01, 0xd7, 0x6b, 0x34, 0xd1,
|
||||
0x73, 0xfd, 0xd5, 0x61, 0xbd, 0x99, 0xf6, 0xee, 0x29, 0x56, 0x4a, 0xef, 0xd8, 0x90, 0x5b, 0xab,
|
||||
0x15, 0x70, 0xaf, 0xd0, 0xd4, 0x41, 0x04, 0xa8, 0xb3, 0x64, 0x92, 0xe4, 0x27, 0xd5, 0xc5, 0x11,
|
||||
0x5b, 0xec, 0x50, 0x7a, 0xc3, 0x06, 0x24, 0x00, 0x69, 0x75, 0x50, 0x77, 0x82, 0xba, 0x1f, 0xd3,
|
||||
0x7b, 0xe1, 0x03, 0xeb, 0xef, 0x87, 0xd0, 0x62, 0x2b, 0x74, 0xf6, 0x67, 0x92, 0xe4, 0xfd, 0xe9,
|
||||
0x65, 0xd1, 0x0e, 0x5e, 0x2c, 0x77, 0xfc, 0xa5, 0xc1, 0xd5, 0xa9, 0x3b, 0x0e, 0xd3, 0x5b, 0x36,
|
||||
0xb4, 0x42, 0x50, 0xed, 0x04, 0x6d, 0x15, 0x88, 0x9a, 0x03, 0xe0, 0xc6, 0xf8, 0xec, 0x6f, 0xe8,
|
||||
0x96, 0x36, 0x6c, 0x19, 0xd1, 0x2c, 0x92, 0x74, 0xca, 0x46, 0x1a, 0x81, 0xeb, 0x5f, 0x96, 0x7f,
|
||||
0x71, 0x9d, 0x00, 0x7f, 0x78, 0x9e, 0xd9, 0x79, 0xe8, 0x42, 0x16, 0xea, 0xad, 0x20, 0xa7, 0xd0,
|
||||
0xb8, 0xac, 0x3b, 0x49, 0xf2, 0xde, 0xf4, 0xea, 0x30, 0x68, 0x65, 0xa1, 0xdd, 0xeb, 0x75, 0x27,
|
||||
0xaa, 0x06, 0x8d, 0xaf, 0xb2, 0xd0, 0x26, 0xe6, 0x9a, 0x8d, 0x14, 0x46, 0x4f, 0xf3, 0xad, 0x42,
|
||||
0x19, 0x2f, 0xc8, 0x70, 0x3d, 0x3f, 0x3b, 0x3a, 0x79, 0x28, 0xb3, 0x48, 0xde, 0x1e, 0x25, 0xa2,
|
||||
0xd4, 0xa2, 0x90, 0xa8, 0xb9, 0x91, 0x05, 0x92, 0x2c, 0xc3, 0x17, 0x81, 0xc4, 0x4a, 0x18, 0xaf,
|
||||
0xb8, 0x76, 0xe1, 0xe7, 0x65, 0x5b, 0xa5, 0x0c, 0xe7, 0x0e, 0xa2, 0x5a, 0x82, 0x7d, 0xef, 0x86,
|
||||
0xf8, 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x15, 0xf8, 0xd5, 0xb6, 0x23, 0x02, 0x00, 0x00,
|
||||
}
|
1184
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go
generated
vendored
Normal file
1184
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
178
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go
generated
vendored
Normal file
178
vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: grpc/gcp/transport_security_common.proto
|
||||
|
||||
package grpc_gcp // import "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// The security level of the created channel. The list is sorted in increasing
|
||||
// level of security. This order must always be maintained.
|
||||
type SecurityLevel int32
|
||||
|
||||
const (
|
||||
SecurityLevel_SECURITY_NONE SecurityLevel = 0
|
||||
SecurityLevel_INTEGRITY_ONLY SecurityLevel = 1
|
||||
SecurityLevel_INTEGRITY_AND_PRIVACY SecurityLevel = 2
|
||||
)
|
||||
|
||||
var SecurityLevel_name = map[int32]string{
|
||||
0: "SECURITY_NONE",
|
||||
1: "INTEGRITY_ONLY",
|
||||
2: "INTEGRITY_AND_PRIVACY",
|
||||
}
|
||||
var SecurityLevel_value = map[string]int32{
|
||||
"SECURITY_NONE": 0,
|
||||
"INTEGRITY_ONLY": 1,
|
||||
"INTEGRITY_AND_PRIVACY": 2,
|
||||
}
|
||||
|
||||
func (x SecurityLevel) String() string {
|
||||
return proto.EnumName(SecurityLevel_name, int32(x))
|
||||
}
|
||||
func (SecurityLevel) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_transport_security_common_71945991f2c3b4a6, []int{0}
|
||||
}
|
||||
|
||||
// Max and min supported RPC protocol versions.
|
||||
type RpcProtocolVersions struct {
|
||||
// Maximum supported RPC version.
|
||||
MaxRpcVersion *RpcProtocolVersions_Version `protobuf:"bytes,1,opt,name=max_rpc_version,json=maxRpcVersion,proto3" json:"max_rpc_version,omitempty"`
|
||||
// Minimum supported RPC version.
|
||||
MinRpcVersion *RpcProtocolVersions_Version `protobuf:"bytes,2,opt,name=min_rpc_version,json=minRpcVersion,proto3" json:"min_rpc_version,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RpcProtocolVersions) Reset() { *m = RpcProtocolVersions{} }
|
||||
func (m *RpcProtocolVersions) String() string { return proto.CompactTextString(m) }
|
||||
func (*RpcProtocolVersions) ProtoMessage() {}
|
||||
func (*RpcProtocolVersions) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_transport_security_common_71945991f2c3b4a6, []int{0}
|
||||
}
|
||||
func (m *RpcProtocolVersions) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RpcProtocolVersions.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RpcProtocolVersions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RpcProtocolVersions.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *RpcProtocolVersions) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RpcProtocolVersions.Merge(dst, src)
|
||||
}
|
||||
func (m *RpcProtocolVersions) XXX_Size() int {
|
||||
return xxx_messageInfo_RpcProtocolVersions.Size(m)
|
||||
}
|
||||
func (m *RpcProtocolVersions) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RpcProtocolVersions.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RpcProtocolVersions proto.InternalMessageInfo
|
||||
|
||||
func (m *RpcProtocolVersions) GetMaxRpcVersion() *RpcProtocolVersions_Version {
|
||||
if m != nil {
|
||||
return m.MaxRpcVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RpcProtocolVersions) GetMinRpcVersion() *RpcProtocolVersions_Version {
|
||||
if m != nil {
|
||||
return m.MinRpcVersion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RPC version contains a major version and a minor version.
|
||||
type RpcProtocolVersions_Version struct {
|
||||
Major uint32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
|
||||
Minor uint32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RpcProtocolVersions_Version) Reset() { *m = RpcProtocolVersions_Version{} }
|
||||
func (m *RpcProtocolVersions_Version) String() string { return proto.CompactTextString(m) }
|
||||
func (*RpcProtocolVersions_Version) ProtoMessage() {}
|
||||
func (*RpcProtocolVersions_Version) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_transport_security_common_71945991f2c3b4a6, []int{0, 0}
|
||||
}
|
||||
func (m *RpcProtocolVersions_Version) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RpcProtocolVersions_Version.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RpcProtocolVersions_Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RpcProtocolVersions_Version.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *RpcProtocolVersions_Version) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RpcProtocolVersions_Version.Merge(dst, src)
|
||||
}
|
||||
func (m *RpcProtocolVersions_Version) XXX_Size() int {
|
||||
return xxx_messageInfo_RpcProtocolVersions_Version.Size(m)
|
||||
}
|
||||
func (m *RpcProtocolVersions_Version) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RpcProtocolVersions_Version.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RpcProtocolVersions_Version proto.InternalMessageInfo
|
||||
|
||||
func (m *RpcProtocolVersions_Version) GetMajor() uint32 {
|
||||
if m != nil {
|
||||
return m.Major
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *RpcProtocolVersions_Version) GetMinor() uint32 {
|
||||
if m != nil {
|
||||
return m.Minor
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*RpcProtocolVersions)(nil), "grpc.gcp.RpcProtocolVersions")
|
||||
proto.RegisterType((*RpcProtocolVersions_Version)(nil), "grpc.gcp.RpcProtocolVersions.Version")
|
||||
proto.RegisterEnum("grpc.gcp.SecurityLevel", SecurityLevel_name, SecurityLevel_value)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("grpc/gcp/transport_security_common.proto", fileDescriptor_transport_security_common_71945991f2c3b4a6)
|
||||
}
|
||||
|
||||
var fileDescriptor_transport_security_common_71945991f2c3b4a6 = []byte{
|
||||
// 323 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x41, 0x4b, 0x3b, 0x31,
|
||||
0x10, 0xc5, 0xff, 0x5b, 0xf8, 0xab, 0x44, 0x56, 0xeb, 0x6a, 0x41, 0xc5, 0x83, 0x08, 0x42, 0xf1,
|
||||
0x90, 0x05, 0xc5, 0xb3, 0xb4, 0xb5, 0x48, 0xa1, 0x6e, 0xeb, 0xb6, 0x16, 0xea, 0x25, 0xc4, 0x18,
|
||||
0x42, 0x24, 0x9b, 0x09, 0xb3, 0xb1, 0xd4, 0xaf, 0xec, 0xa7, 0x90, 0x4d, 0xbb, 0x14, 0xc1, 0x8b,
|
||||
0xb7, 0xbc, 0xc7, 0xcc, 0x6f, 0x32, 0xf3, 0x48, 0x5b, 0xa1, 0x13, 0xa9, 0x12, 0x2e, 0xf5, 0xc8,
|
||||
0x6d, 0xe9, 0x00, 0x3d, 0x2b, 0xa5, 0xf8, 0x40, 0xed, 0x3f, 0x99, 0x80, 0xa2, 0x00, 0x4b, 0x1d,
|
||||
0x82, 0x87, 0x64, 0xa7, 0xaa, 0xa4, 0x4a, 0xb8, 0x8b, 0xaf, 0x88, 0x1c, 0xe6, 0x4e, 0x8c, 0x2b,
|
||||
0x5b, 0x80, 0x99, 0x49, 0x2c, 0x35, 0xd8, 0x32, 0x79, 0x24, 0xfb, 0x05, 0x5f, 0x32, 0x74, 0x82,
|
||||
0x2d, 0x56, 0xde, 0x71, 0x74, 0x1e, 0xb5, 0x77, 0xaf, 0x2f, 0x69, 0xdd, 0x4b, 0x7f, 0xe9, 0xa3,
|
||||
0xeb, 0x47, 0x1e, 0x17, 0x7c, 0x99, 0x3b, 0xb1, 0x96, 0x01, 0xa7, 0xed, 0x0f, 0x5c, 0xe3, 0x6f,
|
||||
0x38, 0x6d, 0x37, 0xb8, 0xd3, 0x5b, 0xb2, 0x5d, 0x93, 0x8f, 0xc8, 0xff, 0x82, 0xbf, 0x03, 0x86,
|
||||
0xef, 0xc5, 0xf9, 0x4a, 0x04, 0x57, 0x5b, 0xc0, 0x30, 0xa5, 0x72, 0x2b, 0x71, 0xf5, 0x44, 0xe2,
|
||||
0xc9, 0xfa, 0x1e, 0x43, 0xb9, 0x90, 0x26, 0x39, 0x20, 0xf1, 0xa4, 0xdf, 0x7b, 0xce, 0x07, 0xd3,
|
||||
0x39, 0xcb, 0x46, 0x59, 0xbf, 0xf9, 0x2f, 0x49, 0xc8, 0xde, 0x20, 0x9b, 0xf6, 0x1f, 0x82, 0x37,
|
||||
0xca, 0x86, 0xf3, 0x66, 0x94, 0x9c, 0x90, 0xd6, 0xc6, 0xeb, 0x64, 0xf7, 0x6c, 0x9c, 0x0f, 0x66,
|
||||
0x9d, 0xde, 0xbc, 0xd9, 0xe8, 0x2e, 0x49, 0x4b, 0xc3, 0x6a, 0x07, 0x6e, 0x7c, 0x49, 0xb5, 0xf5,
|
||||
0x12, 0x2d, 0x37, 0xdd, 0xb3, 0x69, 0x9d, 0x41, 0x3d, 0xb2, 0x17, 0x12, 0x08, 0x2b, 0x8e, 0xa3,
|
||||
0x97, 0x3b, 0x05, 0xa0, 0x8c, 0xa4, 0x0a, 0x0c, 0xb7, 0x8a, 0x02, 0xaa, 0x34, 0xc4, 0x27, 0x50,
|
||||
0xbe, 0x49, 0xeb, 0x35, 0x37, 0x65, 0x5a, 0x11, 0xd3, 0x9a, 0x98, 0x86, 0xe8, 0x42, 0x11, 0x53,
|
||||
0xc2, 0xbd, 0x6e, 0x05, 0x7d, 0xf3, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x31, 0x14, 0xb4, 0x11, 0xf6,
|
||||
0x01, 0x00, 0x00,
|
||||
}
|
35
vendor/google.golang.org/grpc/credentials/alts/internal/regenerate.sh
generated
vendored
Executable file
35
vendor/google.golang.org/grpc/credentials/alts/internal/regenerate.sh
generated
vendored
Executable file
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
# 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.
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
|
||||
function finish {
|
||||
rm -rf "$TMP"
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
pushd "$TMP"
|
||||
mkdir -p grpc/gcp
|
||||
curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/gcp/altscontext.proto > grpc/gcp/altscontext.proto
|
||||
curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/gcp/handshaker.proto > grpc/gcp/handshaker.proto
|
||||
curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/gcp/transport_security_common.proto > grpc/gcp/transport_security_common.proto
|
||||
|
||||
protoc --go_out=plugins=grpc,paths=source_relative:. -I. grpc/gcp/*.proto
|
||||
popd
|
||||
rm -f proto/grpc_gcp/*.pb.go
|
||||
cp "$TMP"/grpc/gcp/*.pb.go proto/grpc_gcp/
|
||||
|
125
vendor/google.golang.org/grpc/credentials/alts/internal/testutil/testutil.go
generated
vendored
Normal file
125
vendor/google.golang.org/grpc/credentials/alts/internal/testutil/testutil.go
generated
vendored
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
*
|
||||
* 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 testutil include useful test utilities for the handshaker.
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc/credentials/alts/internal/conn"
|
||||
)
|
||||
|
||||
// Stats is used to collect statistics about concurrent handshake calls.
|
||||
type Stats struct {
|
||||
mu sync.Mutex
|
||||
calls int
|
||||
MaxConcurrentCalls int
|
||||
}
|
||||
|
||||
// Update updates the statistics by adding one call.
|
||||
func (s *Stats) Update() func() {
|
||||
s.mu.Lock()
|
||||
s.calls++
|
||||
if s.calls > s.MaxConcurrentCalls {
|
||||
s.MaxConcurrentCalls = s.calls
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
return func() {
|
||||
s.mu.Lock()
|
||||
s.calls--
|
||||
s.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Reset resets the statistics.
|
||||
func (s *Stats) Reset() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.calls = 0
|
||||
s.MaxConcurrentCalls = 0
|
||||
}
|
||||
|
||||
// testConn mimics a net.Conn to the peer.
|
||||
type testConn struct {
|
||||
net.Conn
|
||||
in *bytes.Buffer
|
||||
out *bytes.Buffer
|
||||
}
|
||||
|
||||
// NewTestConn creates a new instance of testConn object.
|
||||
func NewTestConn(in *bytes.Buffer, out *bytes.Buffer) net.Conn {
|
||||
return &testConn{
|
||||
in: in,
|
||||
out: out,
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads from the in buffer.
|
||||
func (c *testConn) Read(b []byte) (n int, err error) {
|
||||
return c.in.Read(b)
|
||||
}
|
||||
|
||||
// Write writes to the out buffer.
|
||||
func (c *testConn) Write(b []byte) (n int, err error) {
|
||||
return c.out.Write(b)
|
||||
}
|
||||
|
||||
// Close closes the testConn object.
|
||||
func (c *testConn) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// unresponsiveTestConn mimics a net.Conn for an unresponsive peer. It is used
|
||||
// for testing the PeerNotResponding case.
|
||||
type unresponsiveTestConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
// NewUnresponsiveTestConn creates a new instance of unresponsiveTestConn object.
|
||||
func NewUnresponsiveTestConn() net.Conn {
|
||||
return &unresponsiveTestConn{}
|
||||
}
|
||||
|
||||
// Read reads from the in buffer.
|
||||
func (c *unresponsiveTestConn) Read(b []byte) (n int, err error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// Write writes to the out buffer.
|
||||
func (c *unresponsiveTestConn) Write(b []byte) (n int, err error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Close closes the TestConn object.
|
||||
func (c *unresponsiveTestConn) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeFrame creates a handshake frame.
|
||||
func MakeFrame(pl string) []byte {
|
||||
f := make([]byte, len(pl)+conn.MsgLenFieldSize)
|
||||
binary.LittleEndian.PutUint32(f, uint32(len(pl)))
|
||||
copy(f[conn.MsgLenFieldSize:], []byte(pl))
|
||||
return f
|
||||
}
|
141
vendor/google.golang.org/grpc/credentials/alts/utils.go
generated
vendored
Normal file
141
vendor/google.golang.org/grpc/credentials/alts/utils.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 alts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/peer"
|
||||
)
|
||||
|
||||
const (
|
||||
linuxProductNameFile = "/sys/class/dmi/id/product_name"
|
||||
windowsCheckCommand = "powershell.exe"
|
||||
windowsCheckCommandArgs = "Get-WmiObject -Class Win32_BIOS"
|
||||
powershellOutputFilter = "Manufacturer"
|
||||
windowsManufacturerRegex = ":(.*)"
|
||||
)
|
||||
|
||||
type platformError string
|
||||
|
||||
func (k platformError) Error() string {
|
||||
return fmt.Sprintf("%s is not supported", string(k))
|
||||
}
|
||||
|
||||
var (
|
||||
// The following two variables will be reassigned in tests.
|
||||
runningOS = runtime.GOOS
|
||||
manufacturerReader = func() (io.Reader, error) {
|
||||
switch runningOS {
|
||||
case "linux":
|
||||
return os.Open(linuxProductNameFile)
|
||||
case "windows":
|
||||
cmd := exec.Command(windowsCheckCommand, windowsCheckCommandArgs)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(strings.TrimSuffix(string(out), "\n"), "\n") {
|
||||
if strings.HasPrefix(line, powershellOutputFilter) {
|
||||
re := regexp.MustCompile(windowsManufacturerRegex)
|
||||
name := re.FindString(line)
|
||||
name = strings.TrimLeft(name, ":")
|
||||
return strings.NewReader(name), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("cannot determine the machine's manufacturer")
|
||||
default:
|
||||
return nil, platformError(runningOS)
|
||||
}
|
||||
}
|
||||
vmOnGCP bool
|
||||
)
|
||||
|
||||
// isRunningOnGCP checks whether the local system, without doing a network request is
|
||||
// running on GCP.
|
||||
func isRunningOnGCP() bool {
|
||||
manufacturer, err := readManufacturer()
|
||||
if err != nil {
|
||||
log.Fatalf("failure to read manufacturer information: %v", err)
|
||||
}
|
||||
name := string(manufacturer)
|
||||
switch runningOS {
|
||||
case "linux":
|
||||
name = strings.TrimSpace(name)
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
case "windows":
|
||||
name = strings.Replace(name, " ", "", -1)
|
||||
name = strings.Replace(name, "\n", "", -1)
|
||||
name = strings.Replace(name, "\r", "", -1)
|
||||
return name == "Google"
|
||||
default:
|
||||
log.Fatal(platformError(runningOS))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func readManufacturer() ([]byte, error) {
|
||||
reader, err := manufacturerReader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reader == nil {
|
||||
return nil, errors.New("got nil reader")
|
||||
}
|
||||
manufacturer, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed reading %v: %v", linuxProductNameFile, err)
|
||||
}
|
||||
return manufacturer, nil
|
||||
}
|
||||
|
||||
// AuthInfoFromContext extracts the alts.AuthInfo object from the given context,
|
||||
// if it exists. This API should be used by gRPC server RPC handlers to get
|
||||
// information about the communicating peer. For client-side, use grpc.Peer()
|
||||
// CallOption.
|
||||
func AuthInfoFromContext(ctx context.Context) (AuthInfo, error) {
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if !ok {
|
||||
return nil, errors.New("no Peer found in Context")
|
||||
}
|
||||
return AuthInfoFromPeer(p)
|
||||
}
|
||||
|
||||
// AuthInfoFromPeer extracts the alts.AuthInfo object from the given peer, if it
|
||||
// exists. This API should be used by gRPC clients after obtaining a peer object
|
||||
// using the grpc.Peer() CallOption.
|
||||
func AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) {
|
||||
altsAuthInfo, ok := p.AuthInfo.(AuthInfo)
|
||||
if !ok {
|
||||
return nil, errors.New("no alts.AuthInfo found in Peer")
|
||||
}
|
||||
return altsAuthInfo, nil
|
||||
}
|
139
vendor/google.golang.org/grpc/credentials/alts/utils_test.go
generated
vendored
Normal file
139
vendor/google.golang.org/grpc/credentials/alts/utils_test.go
generated
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
*
|
||||
* 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 alts
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
altspb "google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp"
|
||||
"google.golang.org/grpc/peer"
|
||||
)
|
||||
|
||||
func TestIsRunningOnGCP(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
description string
|
||||
testOS string
|
||||
testReader io.Reader
|
||||
out bool
|
||||
}{
|
||||
// Linux tests.
|
||||
{"linux: not a GCP platform", "linux", strings.NewReader("not GCP"), false},
|
||||
{"Linux: GCP platform (Google)", "linux", strings.NewReader("Google"), true},
|
||||
{"Linux: GCP platform (Google Compute Engine)", "linux", strings.NewReader("Google Compute Engine"), true},
|
||||
{"Linux: GCP platform (Google Compute Engine) with extra spaces", "linux", strings.NewReader(" Google Compute Engine "), true},
|
||||
// Windows tests.
|
||||
{"windows: not a GCP platform", "windows", strings.NewReader("not GCP"), false},
|
||||
{"windows: GCP platform (Google)", "windows", strings.NewReader("Google"), true},
|
||||
{"windows: GCP platform (Google) with extra spaces", "windows", strings.NewReader(" Google "), true},
|
||||
} {
|
||||
reverseFunc := setup(tc.testOS, tc.testReader)
|
||||
if got, want := isRunningOnGCP(), tc.out; got != want {
|
||||
t.Errorf("%v: isRunningOnGCP()=%v, want %v", tc.description, got, want)
|
||||
}
|
||||
reverseFunc()
|
||||
}
|
||||
}
|
||||
|
||||
func setup(testOS string, testReader io.Reader) func() {
|
||||
tmpOS := runningOS
|
||||
tmpReader := manufacturerReader
|
||||
|
||||
// Set test OS and reader function.
|
||||
runningOS = testOS
|
||||
manufacturerReader = func() (io.Reader, error) {
|
||||
return testReader, nil
|
||||
}
|
||||
|
||||
return func() {
|
||||
runningOS = tmpOS
|
||||
manufacturerReader = tmpReader
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthInfoFromContext(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
altsAuthInfo := &fakeALTSAuthInfo{}
|
||||
p := &peer.Peer{
|
||||
AuthInfo: altsAuthInfo,
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
ctx context.Context
|
||||
success bool
|
||||
out AuthInfo
|
||||
}{
|
||||
{
|
||||
"working case",
|
||||
peer.NewContext(ctx, p),
|
||||
true,
|
||||
altsAuthInfo,
|
||||
},
|
||||
} {
|
||||
authInfo, err := AuthInfoFromContext(tc.ctx)
|
||||
if got, want := (err == nil), tc.success; got != want {
|
||||
t.Errorf("%v: AuthInfoFromContext(_)=(err=nil)=%v, want %v", tc.desc, got, want)
|
||||
}
|
||||
if got, want := authInfo, tc.out; got != want {
|
||||
t.Errorf("%v:, AuthInfoFromContext(_)=(%v, _), want (%v, _)", tc.desc, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthInfoFromPeer(t *testing.T) {
|
||||
altsAuthInfo := &fakeALTSAuthInfo{}
|
||||
p := &peer.Peer{
|
||||
AuthInfo: altsAuthInfo,
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
p *peer.Peer
|
||||
success bool
|
||||
out AuthInfo
|
||||
}{
|
||||
{
|
||||
"working case",
|
||||
p,
|
||||
true,
|
||||
altsAuthInfo,
|
||||
},
|
||||
} {
|
||||
authInfo, err := AuthInfoFromPeer(tc.p)
|
||||
if got, want := (err == nil), tc.success; got != want {
|
||||
t.Errorf("%v: AuthInfoFromPeer(_)=(err=nil)=%v, want %v", tc.desc, got, want)
|
||||
}
|
||||
if got, want := authInfo, tc.out; got != want {
|
||||
t.Errorf("%v:, AuthInfoFromPeer(_)=(%v, _), want (%v, _)", tc.desc, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeALTSAuthInfo struct{}
|
||||
|
||||
func (*fakeALTSAuthInfo) AuthType() string { return "" }
|
||||
func (*fakeALTSAuthInfo) ApplicationProtocol() string { return "" }
|
||||
func (*fakeALTSAuthInfo) RecordProtocol() string { return "" }
|
||||
func (*fakeALTSAuthInfo) SecurityLevel() altspb.SecurityLevel {
|
||||
return altspb.SecurityLevel_SECURITY_NONE
|
||||
}
|
||||
func (*fakeALTSAuthInfo) PeerServiceAccount() string { return "" }
|
||||
func (*fakeALTSAuthInfo) LocalServiceAccount() string { return "" }
|
||||
func (*fakeALTSAuthInfo) PeerRPCVersions() *altspb.RpcProtocolVersions { return nil }
|
Loading…
Add table
Add a link
Reference in a new issue