diff --git a/go.mod b/go.mod index f6a00da3a5..a4f5db8b7c 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 + github.com/hashicorp/golang-lru v0.5.1 github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 github.com/lestrrat-go/jwx v1.2.7 github.com/lucas-clemente/quic-go v0.23.0 diff --git a/go.sum b/go.sum index 82438feb63..c91ce92fe7 100644 --- a/go.sum +++ b/go.sum @@ -346,6 +346,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= diff --git a/go/co/BUILD.bazel b/go/co/BUILD.bazel index 9e38700f26..0f5d074bbc 100644 --- a/go/co/BUILD.bazel +++ b/go/co/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//go/co/reservation/segment/admission/stateless:go_default_library", "//go/co/reservationstorage:go_default_library", "//go/co/reservationstore:go_default_library", + "//go/lib/addr:go_default_library", "//go/lib/colibri/coliquic:go_default_library", "//go/lib/keyconf:go_default_library", "//go/lib/log:go_default_library", @@ -33,6 +34,7 @@ go_library( "//go/pkg/proto/colibri:go_default_library", "//go/pkg/storage:go_default_library", "@org_golang_google_grpc//:go_default_library", + "@org_golang_google_grpc//resolver:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", ], ) diff --git a/go/co/main.go b/go/co/main.go index 4802d84f98..d593cdfc63 100644 --- a/go/co/main.go +++ b/go/co/main.go @@ -16,16 +16,19 @@ package main import ( "context" + "net" "path/filepath" "time" "golang.org/x/sync/errgroup" "google.golang.org/grpc" + "google.golang.org/grpc/resolver" coli_conf "github.com/scionproto/scion/go/co/reservation/conf" admission "github.com/scionproto/scion/go/co/reservation/segment/admission/stateless" "github.com/scionproto/scion/go/co/reservationstorage" "github.com/scionproto/scion/go/co/reservationstore" + "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/colibri/coliquic" "github.com/scionproto/scion/go/lib/keyconf" "github.com/scionproto/scion/go/lib/log" @@ -93,6 +96,7 @@ func realMain(ctx context.Context, cfg *config.Config) error { type cfgObjs struct { masterKey keyconf.Master stack *coliquic.ServerStack + dialer *libgrpc.TCPDialer } func setup(ctx context.Context, cfg *config.Config, topo *topology.Loader) (*cfgObjs, error) { @@ -122,8 +126,28 @@ func setupNetwork(ctx context.Context, cfg *config.Config, topo *topology.Loader return nil, serrors.WrapStr("initializing server stack", err) } + dialerAddr := &net.TCPAddr{ + IP: serverAddr.Host.IP, + } + dialer := &libgrpc.TCPDialer{ + LocalAddr: dialerAddr, + SvcResolver: func(dst addr.HostSVC) []resolver.Address { + targets := []resolver.Address{} + switch dst.Base() { + case addr.SvcCS: + for _, entry := range topo.ControlServiceAddresses() { + targets = append(targets, resolver.Address{Addr: entry.String()}) + } + default: + panic("Unsupported address type, implementation error?") + } + return targets + }, + } + return &cfgObjs{ - stack: stack, + stack: stack, + dialer: dialer, }, nil } @@ -140,7 +164,7 @@ func setupColibri(g *errgroup.Group, cfg *config.Config, cfgObjs *cfgObjs, topo Caps: cfg.Colibri.Capacities, Delta: cfg.Colibri.Delta, } - colibriStore, err := reservationstore.NewStore(topo, cfgObjs.stack.Daemon, + colibriStore, err := reservationstore.NewStore(topo, cfgObjs.dialer, cfgObjs.stack.Router, cfgObjs.stack.Dialer, db, admitter, cfgObjs.masterKey.Key0) if err != nil { return nil, serrors.WrapStr("initializing colibri store", err) diff --git a/go/co/reservation/e2e/response.go b/go/co/reservation/e2e/response.go index f94a715737..a6404e226f 100644 --- a/go/co/reservation/e2e/response.go +++ b/go/co/reservation/e2e/response.go @@ -15,6 +15,8 @@ package e2e import ( + "time" + base "github.com/scionproto/scion/go/co/reservation" "github.com/scionproto/scion/go/lib/colibri/reservation" "github.com/scionproto/scion/go/lib/serrors" @@ -25,6 +27,7 @@ type SetupResponse interface { ToRaw(step int, rsvID *reservation.ID) ([]byte, error) SetAuthenticator(currentStep int, authenticator []byte) + GetTimestamp() time.Time } type SetupResponseSuccess struct { @@ -54,6 +57,10 @@ func (r *SetupResponseSuccess) SetAuthenticator(step int, authenticator []byte) r.Authenticators[step] = authenticator } +func (r *SetupResponseSuccess) GetTimestamp() time.Time { + return r.Timestamp +} + type SetupResponseFailure struct { base.AuthenticatedResponse FailedStep uint8 @@ -84,3 +91,7 @@ func (r *SetupResponseFailure) ToRaw(step int, rsvID *reservation.ID) ([]byte, e func (r *SetupResponseFailure) SetAuthenticator(step int, authenticator []byte) { r.Authenticators[step] = authenticator } + +func (r *SetupResponseFailure) GetTimestamp() time.Time { + return r.Timestamp +} diff --git a/go/co/reservation/request_response.go b/go/co/reservation/request_response.go index 7e136bea93..76b33c2769 100644 --- a/go/co/reservation/request_response.go +++ b/go/co/reservation/request_response.go @@ -138,6 +138,7 @@ type Response interface { GetAuthenticators() [][]byte SetAuthenticator(currentStep int, authenticator []byte) + GetTimestamp() time.Time Success() bool ToRaw() []byte } @@ -172,6 +173,9 @@ func (r *ResponseSuccess) ToRaw() []byte { r.Serialize(buff[1:5]) return buff } +func (r *ResponseSuccess) GetTimestamp() time.Time { + return r.Timestamp +} type ResponseFailure struct { AuthenticatedResponse @@ -189,3 +193,6 @@ func (r *ResponseFailure) ToRaw() []byte { copy(buff[6:], []byte(r.Message)) return buff } +func (r *ResponseFailure) GetTimestamp() time.Time { + return r.Timestamp +} diff --git a/go/co/reservation/segment/response.go b/go/co/reservation/segment/response.go index fdc5ae13a7..2e7a6b8cdf 100644 --- a/go/co/reservation/segment/response.go +++ b/go/co/reservation/segment/response.go @@ -15,6 +15,8 @@ package segment import ( + "time" + base "github.com/scionproto/scion/go/co/reservation" "github.com/scionproto/scion/go/lib/colibri/reservation" ) @@ -24,6 +26,7 @@ type SegmentSetupResponse interface { GetAuthenticators() [][]byte SetAuthenticator(currentStep int, authenticator []byte) + GetTimestamp() time.Time Success() bool ToRaw(step int) []byte // returns the response serialized to the `step` node ToRawAllHFs() []byte @@ -63,6 +66,9 @@ func (r *SegmentSetupResponseSuccess) ToRaw(step int) []byte { func (r *SegmentSetupResponseSuccess) ToRawAllHFs() []byte { return r.ToRaw(0) } +func (r *SegmentSetupResponseSuccess) GetTimestamp() time.Time { + return r.Timestamp +} type SegmentSetupResponseFailure struct { base.AuthenticatedResponse @@ -85,3 +91,6 @@ func (r *SegmentSetupResponseFailure) ToRaw(step int) []byte { func (r *SegmentSetupResponseFailure) ToRawAllHFs() []byte { return r.ToRaw(1) } +func (r *SegmentSetupResponseFailure) GetTimestamp() time.Time { + return r.Timestamp +} diff --git a/go/co/reservationstore/BUILD.bazel b/go/co/reservationstore/BUILD.bazel index 3f90785817..acaced6e4d 100644 --- a/go/co/reservationstore/BUILD.bazel +++ b/go/co/reservationstore/BUILD.bazel @@ -27,7 +27,7 @@ go_test( "//go/lib/colibri/reservation:go_default_library", "//go/lib/daemon/mock_daemon:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/test:go_default_library", + "//go/lib/drkey/fake:go_default_library", "//go/lib/pathpol:go_default_library", "//go/lib/slayers/path/colibri:go_default_library", "//go/lib/slayers/path/scion:go_default_library", @@ -64,9 +64,8 @@ go_library( "//go/lib/colibri/coliquic:go_default_library", "//go/lib/colibri/dataplane:go_default_library", "//go/lib/colibri/reservation:go_default_library", - "//go/lib/daemon:go_default_library", + "//go/lib/ctrl/drkey:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/drkeyutil:go_default_library", "//go/lib/log:go_default_library", "//go/lib/pathpol:go_default_library", "//go/lib/periodic:go_default_library", @@ -75,6 +74,9 @@ go_library( "//go/lib/snet:go_default_library", "//go/lib/topology:go_default_library", "//go/lib/util:go_default_library", + "//go/pkg/grpc:go_default_library", "//go/pkg/proto/colibri:go_default_library", + "//go/pkg/proto/control_plane:go_default_library", + "@com_github_dchest_cmac//:go_default_library", ], ) diff --git a/go/co/reservationstore/drkey.go b/go/co/reservationstore/drkey.go index c8691a4e3c..1972a01261 100644 --- a/go/co/reservationstore/drkey.go +++ b/go/co/reservationstore/drkey.go @@ -16,19 +16,26 @@ package reservationstore import ( "context" + "crypto/aes" "crypto/subtle" "encoding/hex" + "fmt" + "sync" + "time" + + "github.com/dchest/cmac" base "github.com/scionproto/scion/go/co/reservation" "github.com/scionproto/scion/go/co/reservation/e2e" "github.com/scionproto/scion/go/co/reservation/segment" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/colibri/reservation" - "github.com/scionproto/scion/go/lib/daemon" + drkeyctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" "github.com/scionproto/scion/go/lib/drkey" - drkut "github.com/scionproto/scion/go/lib/drkey/drkeyutil" "github.com/scionproto/scion/go/lib/log" "github.com/scionproto/scion/go/lib/serrors" + libgrpc "github.com/scionproto/scion/go/pkg/grpc" + cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" ) type Authenticator interface { @@ -92,13 +99,20 @@ type macVerifier interface { // DRKeyAuthenticator implements macComputer and macVerifier using DRKey. type DRKeyAuthenticator struct { localIA addr.IA - connector daemon.Connector // to obtain level 1 & 2 keys + fastKeyer fastKeyer + slowKeyer slowKeyer } -func NewDRKeyAuthenticator(localIA addr.IA, connector daemon.Connector) Authenticator { +func NewDRKeyAuthenticator(localIA addr.IA, dialer libgrpc.Dialer) Authenticator { return &DRKeyAuthenticator{ - localIA: localIA, - connector: connector, + localIA: localIA, + fastKeyer: &deriver{ + localIA: localIA, + secreter: &cachingSVfetcher{ + dialer: dialer, + }, + }, + slowKeyer: newLvl1Fetcher(localIA, dialer), } } @@ -159,12 +173,12 @@ func (a *DRKeyAuthenticator) ComputeE2ESetupRequestTransitMAC(ctx context.Contex func (a *DRKeyAuthenticator) ComputeResponseMAC(ctx context.Context, res base.Response, path *base.TransparentPath) error { - key, err := a.getDRKeyAS2AS(ctx, a.localIA, path.SrcIA()) + key, err := a.fastAS2AS(ctx, path.SrcIA(), res.GetTimestamp()) if err != nil { return err } payload := res.ToRaw() - mac, err := MAC(payload, key) + mac, err := MAC(payload, key.Key) if err != nil { return err } @@ -175,12 +189,12 @@ func (a *DRKeyAuthenticator) ComputeResponseMAC(ctx context.Context, func (a *DRKeyAuthenticator) ComputeSegmentSetupResponseMAC(ctx context.Context, res segment.SegmentSetupResponse, path *base.TransparentPath) error { - key, err := a.getDRKeyAS2AS(ctx, a.localIA, path.SrcIA()) + key, err := a.fastAS2AS(ctx, path.SrcIA(), res.GetTimestamp()) if err != nil { return err } payload := res.ToRawAllHFs() - mac, err := MAC(payload, key) + mac, err := MAC(payload, key.Key) if err != nil { return err } @@ -191,12 +205,12 @@ func (a *DRKeyAuthenticator) ComputeSegmentSetupResponseMAC(ctx context.Context, func (a *DRKeyAuthenticator) ComputeE2EResponseMAC(ctx context.Context, res base.Response, path *base.TransparentPath, srcHost addr.HostAddr) error { - key, err := a.getDRKeyAS2Host(ctx, a.localIA, path.SrcIA(), srcHost) + key, err := a.fastAS2Host(ctx, path.SrcIA(), srcHost, res.GetTimestamp()) if err != nil { return err } payload := res.ToRaw() - mac, err := MAC(payload, key) + mac, err := MAC(payload, key.Key) if err != nil { return err } @@ -209,7 +223,7 @@ func (a *DRKeyAuthenticator) ComputeE2EResponseMAC(ctx context.Context, res base func (a *DRKeyAuthenticator) ComputeE2ESetupResponseMAC(ctx context.Context, res e2e.SetupResponse, path *base.TransparentPath, srcHost addr.HostAddr, rsvID *reservation.ID) error { - key, err := a.getDRKeyAS2Host(ctx, a.localIA, path.SrcIA(), srcHost) + key, err := a.fastAS2Host(ctx, path.SrcIA(), srcHost, res.GetTimestamp()) if err != nil { return err } @@ -217,7 +231,7 @@ func (a *DRKeyAuthenticator) ComputeE2ESetupResponseMAC(ctx context.Context, res if err != nil { return err } - mac, err := MAC(payload, key) + mac, err := MAC(payload, key.Key) if err != nil { return err } @@ -289,7 +303,7 @@ func (a *DRKeyAuthenticator) ValidateE2ESetupRequest(ctx context.Context, func (a *DRKeyAuthenticator) ValidateResponse(ctx context.Context, res base.Response, path *base.TransparentPath) (bool, error) { - keys, err := a.slowAS2ASFromPath(ctx, path.Steps) + keys, err := a.slowAS2ASFromPath(ctx, path.Steps, res.GetTimestamp()) if err != nil { return false, err } @@ -318,7 +332,8 @@ func (a *DRKeyAuthenticator) ValidateSegmentSetupResponse(ctx context.Context, return true, nil } - keys, err := a.slowAS2ASFromPath(ctx, path.Steps[:stepsLength]) // returns stepsLength -1 keys + keys, err := a.slowAS2ASFromPath(ctx, path.Steps[:stepsLength], + res.GetTimestamp()) // returns stepsLength -1 keys if err != nil { return false, err } @@ -364,18 +379,18 @@ func (a *DRKeyAuthenticator) validateE2ESetupRequestAtDestination(ctx context.Co func (a *DRKeyAuthenticator) validateSegmentPayloadInitialMAC(ctx context.Context, req *base.Request, immutableInput []byte) (bool, error) { - key, err := a.getDRKeyAS2AS(ctx, a.localIA, req.Path.SrcIA()) + key, err := a.fastAS2AS(ctx, req.Path.SrcIA(), req.Timestamp) if err != nil { return false, serrors.WrapStr("obtaining drkey", err, "fast", a.localIA, "slow", req.Path.SrcIA()) } - mac, err := MAC(immutableInput, key) + mac, err := MAC(immutableInput, key.Key) if err != nil { return false, serrors.WrapStr("validating segment initial request", err) } res := subtle.ConstantTimeCompare(mac, req.CurrentValidatorField()) if res != 1 { - log.Info("source authentication failed", "id", req.ID, + log.FromCtx(ctx).Info("source authentication failed", "id", req.ID, "fast_side", a.localIA, "slow_side", req.Path.SrcIA(), "mac", hex.EncodeToString(mac), "expected", hex.EncodeToString(req.CurrentValidatorField())) @@ -389,19 +404,19 @@ func (a *DRKeyAuthenticator) validateSegmentPayloadInitialMAC(ctx context.Contex func (a *DRKeyAuthenticator) validateE2EPayloadInitialMAC(ctx context.Context, req *e2e.Request, immutableInput []byte) (bool, error) { - key, err := a.getDRKeyAS2Host(ctx, a.localIA, req.Path.SrcIA(), addr.HostFromIP(req.SrcHost)) + key, err := a.fastAS2Host(ctx, req.Path.SrcIA(), addr.HostFromIP(req.SrcHost), req.Timestamp) if err != nil { return false, serrors.WrapStr("obtaining drkey", err, "fast", a.localIA, "slow_ia", req.Path.SrcIA(), "slow_host", req.SrcHost) } - mac, err := MAC(immutableInput, key) + mac, err := MAC(immutableInput, key.Key) if err != nil { return false, serrors.WrapStr("validating e2e initial request", err) } res := subtle.ConstantTimeCompare(mac, req.CurrentValidatorField()) if res != 1 { - log.Info("source authentication failed", "id", req.ID, + log.FromCtx(ctx).Info("source authentication failed", "id", req.ID, "fast_side", a.localIA, "slow_ia", req.Path.SrcIA(), "slow_host", req.SrcHost, "mac", hex.EncodeToString(mac), @@ -423,7 +438,7 @@ func (a *DRKeyAuthenticator) validateAtDestination(ctx context.Context, req *bas return false, serrors.New("insconsistent length in request", "auth_count", len(req.Authenticators), "step_count", len(req.Path.Steps)) } - keys, err := a.slowAS2ASFromPath(ctx, req.Path.Steps[:len(req.Path.Steps)-1]) + keys, err := a.slowAS2ASFromPath(ctx, req.Path.Steps[:len(req.Path.Steps)-1], req.Timestamp) if err != nil { return false, serrors.WrapStr("source authentication failed", err, "id", req.ID) } @@ -433,7 +448,7 @@ func (a *DRKeyAuthenticator) validateAtDestination(ctx context.Context, req *bas payloadFcn) } -func validateAuthenticators(keys [][]byte, authenticators [][]byte, +func validateAuthenticators(keys []drkey.Key, authenticators [][]byte, payloadFcn func(step int) []byte) (bool, error) { if len(authenticators) != len(keys) { @@ -461,7 +476,7 @@ func validateAuthenticators(keys [][]byte, authenticators [][]byte, func (a *DRKeyAuthenticator) computeInitialMACforPayloadWithSegKeys(ctx context.Context, payload []byte, req *base.Request) error { - keys, err := a.slowAS2ASFromPath(ctx, req.Path.Steps) + keys, err := a.slowAS2ASFromPath(ctx, req.Path.Steps, req.Timestamp) if err != nil { return err } @@ -469,7 +484,7 @@ func (a *DRKeyAuthenticator) computeInitialMACforPayloadWithSegKeys(ctx context. } func (a *DRKeyAuthenticator) computeInitialMACforPayload(ctx context.Context, payload []byte, - req *base.Request, keys [][]byte) error { + req *base.Request, keys []drkey.Key) error { assert(len(keys) == len(req.Path.Steps)-1, "bad key set with length %d (should be %d)", len(keys), len(req.Path.Steps)-1) @@ -486,43 +501,48 @@ func (a *DRKeyAuthenticator) computeInitialMACforPayload(ctx context.Context, pa func (a *DRKeyAuthenticator) computeTransitMACforPayload(ctx context.Context, payload []byte, req *base.Request) error { - key, err := a.getDRKeyAS2AS(ctx, a.localIA, req.Path.DstIA()) + key, err := a.fastAS2AS(ctx, req.Path.DstIA(), req.Timestamp) if err != nil { return err } - req.Authenticators[req.Path.CurrentStep-1], err = MAC(payload, key) + req.Authenticators[req.Path.CurrentStep-1], err = MAC(payload, key.Key) return err } func (a *DRKeyAuthenticator) computeTransitMACforE2EPayload(ctx context.Context, payload []byte, req *e2e.Request) error { - key, err := a.getDRKeyAS2AS(ctx, a.localIA, req.Path.DstIA()) + key, err := a.fastAS2AS(ctx, req.Path.DstIA(), req.Timestamp) if err != nil { return err } - req.Authenticators[req.Path.CurrentStep-1], err = MAC(payload, key) + req.Authenticators[req.Path.CurrentStep-1], err = MAC(payload, key.Key) return err } -// slowLvl1FromPath gets the L1 keys from the slow side to all ASes in the path. +// slowAS2ASFromPath gets the AS-AS keys from the slow side to all ASes in the path. // Note: this is the slow side. -func (a *DRKeyAuthenticator) slowAS2ASFromPath(ctx context.Context, steps []base.PathStep) ( - [][]byte, error) { - - return a.slowKeysFromPath(ctx, steps, func(ctx context.Context, fast addr.IA) ([]byte, error) { - return a.getDRKeyAS2AS(ctx, fast, a.localIA) +func (a *DRKeyAuthenticator) slowAS2ASFromPath(ctx context.Context, + steps []base.PathStep, ts time.Time) ( + []drkey.Key, error) { + + return a.slowKeysFromPath(ctx, steps, func(ctx context.Context, + fast addr.IA) (drkey.Key, error) { + k, err := a.slowAS2AS(ctx, fast, ts) + return k.Key, err }) } // slowKeysFromPath retrieves the drkeys specified in the steps[1]..steps[n-1]. It skips the // first step as it is the initiator. The IAs in the steps are used as the fast side of the // drkeys, and the function `getKeyWithFastSide` is called with them, to retrieve the drkeys. -func (a *DRKeyAuthenticator) slowKeysFromPath(ctx context.Context, steps []base.PathStep, - getKeyWithFastSide func(ctx context.Context, fast addr.IA) ([]byte, error)) ([][]byte, error) { +func (a *DRKeyAuthenticator) slowKeysFromPath(ctx context.Context, + steps []base.PathStep, + getKeyWithFastSide func(ctx context.Context, + fast addr.IA) (drkey.Key, error)) ([]drkey.Key, error) { seen := make(map[addr.IA]struct{}) - keys := make([][]byte, len(steps)-1) + keys := make([]drkey.Key, len(steps)-1) for i := 0; i < len(steps)-1; i++ { step := steps[i+1] if step.IA.Equal(a.localIA) { @@ -543,20 +563,38 @@ func (a *DRKeyAuthenticator) slowKeysFromPath(ctx context.Context, steps []base. return keys, nil } -func (a *DRKeyAuthenticator) getDRKeyAS2AS(ctx context.Context, fast, slow addr.IA) ( - []byte, error) { +func (a *DRKeyAuthenticator) fastAS2AS(ctx context.Context, remoteIA addr.IA, + valTime time.Time) (drkey.Lvl1Key, error) { + return a.fastKeyer.Lvl1(ctx, drkey.Lvl1Meta{ + ProtoId: drkey.COLIBRI, + Validity: valTime, + SrcIA: a.localIA, + DstIA: remoteIA, + }) +} - keys, err := drkut.GetLvl2Keys(ctx, a.connector, drkey.AS2AS, "colibri", - drkut.SlowIAs(slow), drkut.FastIAs(fast)) - return keys[0], err +func (a *DRKeyAuthenticator) slowAS2AS(ctx context.Context, remoteIA addr.IA, + valTime time.Time) (drkey.Lvl1Key, error) { + return a.slowKeyer.Lvl1(ctx, drkey.Lvl1Meta{ + ProtoId: drkey.COLIBRI, + Validity: valTime, + SrcIA: remoteIA, + DstIA: a.localIA, + }) } -func (a *DRKeyAuthenticator) getDRKeyAS2Host(ctx context.Context, fast, slowIA addr.IA, - slowHost addr.HostAddr) ([]byte, error) { +func (a *DRKeyAuthenticator) fastAS2Host(ctx context.Context, remoteIA addr.IA, + remoteHost addr.HostAddr, valTime time.Time) (drkey.ASHostKey, error) { - keys, err := drkut.GetLvl2Keys(ctx, a.connector, drkey.AS2Host, "colibri", - drkut.SlowIAs(slowIA), drkut.SlowHosts(slowHost), drkut.FastIAs(fast)) - return keys[0], err + return a.fastKeyer.ASHost(ctx, drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.COLIBRI, + Validity: valTime, + SrcIA: a.localIA, + DstIA: remoteIA, + }, + DstHost: remoteHost.String(), + }) } func inputInitialBaseRequest(req *base.Request) []byte { @@ -612,6 +650,212 @@ func inputTransitE2ESetupRequestForStep(req *e2e.SetupReq, step int) []byte { return buff[:len(buff)-remainingSteps] } -func MAC(payload, key []byte) ([]byte, error) { - return drkut.MAC(payload, key) +func MAC(payload []byte, key drkey.Key) ([]byte, error) { + block, err := aes.NewCipher(key[:]) + if err != nil { + return nil, serrors.WrapStr("initializing aes cipher", err) + } + mac, err := cmac.New(block) + if err != nil { + return nil, serrors.WrapStr("initializing cmac", err) + } + _, err = mac.Write(payload) + if err != nil { + return nil, serrors.WrapStr("preparing mac", err) + } + return mac.Sum(nil), nil +} + +type fastKeyer interface { + Lvl1(context.Context, drkey.Lvl1Meta) (drkey.Lvl1Key, error) + ASHost(context.Context, drkey.ASHostMeta) (drkey.ASHostKey, error) +} + +type deriver struct { + localIA addr.IA + secreter secreter + deriver drkey.SpecificDeriver +} + +func (d *deriver) Lvl1(ctx context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + if meta.SrcIA != d.localIA { + panic(fmt.Sprintf("cannot derive, SrcIA != localIA, SrcIA=%s, localIA=%s", + meta.SrcIA, d.localIA)) + } + + svMeta := drkey.SVMeta{ + Validity: meta.Validity, + ProtoId: meta.ProtoId, + } + sv, err := d.secreter.SV(ctx, svMeta) + if err != nil { + return drkey.Lvl1Key{}, err + } + lvl1, err := d.deriver.DeriveLvl1(meta, sv.Key) + if err != nil { + return drkey.Lvl1Key{}, err + } + return drkey.Lvl1Key{ + ProtoId: meta.ProtoId, + Epoch: sv.Epoch, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Key: lvl1, + }, nil +} + +func (d *deriver) ASHost(ctx context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + lvl1Meta := drkey.Lvl1Meta{ + Validity: meta.Validity, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + ProtoId: meta.ProtoId, + } + lvl1, err := d.Lvl1(ctx, lvl1Meta) + if err != nil { + return drkey.ASHostKey{}, err + } + lvl2, err := d.deriver.DeriveASHost(meta, lvl1.Key) + if err != nil { + return drkey.ASHostKey{}, err + } + return drkey.ASHostKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1.Epoch, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + DstHost: meta.DstHost, + Key: lvl2, + }, nil +} + +type slowKeyer interface { + Lvl1(context.Context, drkey.Lvl1Meta) (drkey.Lvl1Key, error) +} + +type lvl1Fetcher struct { + mtx sync.Mutex + localIA addr.IA + dialer libgrpc.Dialer + cache map[addr.IA][]drkey.Lvl1Key // TODO expired entries should be cleaned up periodically +} + +func newLvl1Fetcher(localIA addr.IA, dialer libgrpc.Dialer) *lvl1Fetcher { + return &lvl1Fetcher{ + localIA: localIA, + dialer: dialer, + cache: map[addr.IA][]drkey.Lvl1Key{}, + } +} + +func (f *lvl1Fetcher) Lvl1(ctx context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + f.mtx.Lock() + defer f.mtx.Unlock() + + if meta.ProtoId != drkey.COLIBRI { + return drkey.Lvl1Key{}, serrors.New("meta.ProtoId must be set to COLIBRI", + "meta.ProtoId", meta.ProtoId) + } + + if meta.DstIA != f.localIA { + return drkey.Lvl1Key{}, serrors.New("cannot fetch, DstIA != localIA", "DstIA=", f.localIA, + "localIA=", meta.DstIA) + } + + lvl1Keys, ok := f.cache[meta.SrcIA] + if ok { + for _, key := range lvl1Keys { + if key.Epoch.Contains(meta.Validity) { + return key, nil + } + } + } + + // get it from local CS + lvl1Key, err := f.fetch(ctx, meta) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("obtaining level 1 key from CS", err) + } + f.cache[meta.SrcIA] = append(f.cache[meta.SrcIA], lvl1Key) + + return lvl1Key, nil +} + +func (f *lvl1Fetcher) fetch(ctx context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + conn, err := f.dialer.Dial(ctx, addr.SvcCS) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := cppb.NewDRKeyIntraServiceClient(conn) + protoReq, err := drkeyctrl.IntraLvl1ToProtoRequest(meta) + if err != nil { + return drkey.Lvl1Key{}, + serrors.WrapStr("parsing AS-AS request to protobuf", err) + } + rep, err := client.IntraLvl1(ctx, protoReq) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("requesting AS-AS key", err) + } + key, err := drkeyctrl.GetASASKeyFromReply(meta, rep) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("obtaining AS-AS key from reply", err) + } + return key, nil +} + +type secreter interface { + SV(context.Context, drkey.SVMeta) (drkey.SV, error) +} + +type cachingSVfetcher struct { + dialer libgrpc.Dialer + cache []drkey.SV // TODO expired entries should be cleaned up periodically + mtx sync.Mutex // TODO could use RWMutex, but should be careful to avoid double-fetching SV! +} + +func (f *cachingSVfetcher) SV(ctx context.Context, meta drkey.SVMeta) (drkey.SV, error) { + f.mtx.Lock() + defer f.mtx.Unlock() + + if meta.ProtoId != drkey.COLIBRI { + return drkey.SV{}, serrors.New("meta.ProtoId must be set to COLIBRI", + "meta.ProtoId", meta.ProtoId) + } + + for i := range f.cache { + if f.cache[i].Epoch.Contains(meta.Validity) { + return f.cache[i], nil + } + } + + key, err := f.fetch(ctx, meta) + if err != nil { + return drkey.SV{}, err + } + f.cache = append(f.cache, key) + return key, nil +} + +func (f *cachingSVfetcher) fetch(ctx context.Context, meta drkey.SVMeta) (drkey.SV, error) { + conn, err := f.dialer.Dial(ctx, addr.SvcCS) + if err != nil { + return drkey.SV{}, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := cppb.NewDRKeyIntraServiceClient(conn) + protoReq, err := drkeyctrl.SVMetaToProtoRequest(meta) + if err != nil { + return drkey.SV{}, + serrors.WrapStr("parsing SV request to protobuf", err) + } + rep, err := client.SV(ctx, protoReq) + if err != nil { + return drkey.SV{}, serrors.WrapStr("requesting SV", err) + } + key, err := drkeyctrl.GetSVFromReply(meta.ProtoId, rep) + if err != nil { + return drkey.SV{}, serrors.WrapStr("obtaining SV from reply", err) + } + return key, nil } diff --git a/go/co/reservationstore/drkey_test.go b/go/co/reservationstore/drkey_test.go index 3e725676b6..52db69dbec 100644 --- a/go/co/reservationstore/drkey_test.go +++ b/go/co/reservationstore/drkey_test.go @@ -16,6 +16,7 @@ package reservationstore import ( "context" + "fmt" "net" "testing" "time" @@ -32,7 +33,7 @@ import ( "github.com/scionproto/scion/go/lib/colibri/reservation" "github.com/scionproto/scion/go/lib/daemon/mock_daemon" "github.com/scionproto/scion/go/lib/drkey" - dkt "github.com/scionproto/scion/go/lib/drkey/test" + fakedrkey "github.com/scionproto/scion/go/lib/drkey/fake" "github.com/scionproto/scion/go/lib/snet/path" "github.com/scionproto/scion/go/lib/util" "github.com/scionproto/scion/go/lib/xtest" @@ -62,7 +63,6 @@ func TestE2EBaseReqInitialMac(t *testing.T) { }, }, } - mockKeys := mockKeysSlowIsSrcWithHost(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -73,21 +73,19 @@ func TestE2EBaseReqInitialMac(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { + mockDRKeys(t, daemon, srcIA(), net.ParseIP(srcHost())) - return mustFindKey(t, mockKeys, meta) - }) - - tc.clientReq.CreateAuthenticators(ctx, daemon) + err := tc.clientReq.CreateAuthenticators(ctx, daemon) + require.NoError(t, err) // copy authenticators to transit request, as if they were received for i, a := range tc.clientReq.Authenticators { tc.transitReq.Authenticators[i] = a } + + authIA := tc.clientReq.Path.Steps[1].IA auth := DRKeyAuthenticator{ - localIA: tc.clientReq.Path.Steps[1].IA, - connector: daemon, + localIA: authIA, + fastKeyer: fakeFastKeyer{localIA: authIA}, } tc.transitReq.Path.CurrentStep = 1 // second AS, first transit AS ok, err := auth.ValidateE2ERequest(ctx, &tc.transitReq) @@ -136,7 +134,6 @@ func TestE2ESetupReqInitialMac(t *testing.T) { }, }, } - mockKeys := mockKeysSlowIsSrcWithHost(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -147,21 +144,19 @@ func TestE2ESetupReqInitialMac(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) + mockDRKeys(t, daemon, srcIA(), net.ParseIP(srcHost())) - tc.clientReq.CreateAuthenticators(ctx, daemon) + err := tc.clientReq.CreateAuthenticators(ctx, daemon) + require.NoError(t, err) // copy authenticators to transit request, as if they were received for i, a := range tc.clientReq.Authenticators { tc.transitReq.Authenticators[i] = a } + + authIA := tc.clientReq.Path.Steps[1].IA auth := DRKeyAuthenticator{ - localIA: tc.clientReq.Path.Steps[1].IA, - connector: daemon, + localIA: authIA, + fastKeyer: fakeFastKeyer{localIA: authIA}, } tc.transitReq.Path.CurrentStep = 1 // second AS, first transit AS ok, err := auth.ValidateE2ESetupRequest(ctx, &tc.transitReq) @@ -185,7 +180,6 @@ func TestE2ERequestTransitMac(t *testing.T) { }, }, } - mockKeys := mockKeysSlowIsDst(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -193,22 +187,13 @@ func TestE2ERequestTransitMac(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) - // at the transit ASes: for step := 1; step < len(tc.transitReq.Path.Steps); step++ { tc.transitReq.Path.CurrentStep = step + authIA := tc.transitReq.Path.Steps[step].IA auth := DRKeyAuthenticator{ - localIA: tc.transitReq.Path.Steps[step].IA, - connector: daemon, + localIA: authIA, + fastKeyer: fakeFastKeyer{localIA: authIA}, } err := auth.ComputeE2ERequestTransitMAC(ctx, &tc.transitReq) require.NoError(t, err) @@ -216,9 +201,10 @@ func TestE2ERequestTransitMac(t *testing.T) { // at the destination AS: tc.transitReq.Path.CurrentStep = len(tc.transitReq.Path.Steps) - 1 + dstIA := tc.transitReq.Path.DstIA() auth := DRKeyAuthenticator{ - localIA: tc.transitReq.Path.DstIA(), - connector: daemon, + localIA: dstIA, + slowKeyer: fakeSlowKeyer{localIA: dstIA}, } ok, err := auth.validateE2ERequestAtDestination(ctx, &tc.transitReq) require.NoError(t, err) @@ -249,7 +235,6 @@ func TestE2ESetupRequestTransitMac(t *testing.T) { }, }, } - mockKeys := mockKeysSlowIsDst(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -257,16 +242,6 @@ func TestE2ESetupRequestTransitMac(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) - // at the transit ASes: for step := 0; step < len(tc.transitReq.Path.Steps); step++ { tc.transitReq.AllocationTrail = append(tc.transitReq.AllocationTrail, 11) @@ -274,9 +249,10 @@ func TestE2ESetupRequestTransitMac(t *testing.T) { continue } tc.transitReq.Path.CurrentStep = step + authIA := tc.transitReq.Path.Steps[step].IA auth := DRKeyAuthenticator{ - localIA: tc.transitReq.Path.Steps[step].IA, - connector: daemon, + localIA: authIA, + fastKeyer: fakeFastKeyer{localIA: authIA}, } err := auth.ComputeE2ESetupRequestTransitMAC(ctx, &tc.transitReq) require.NoError(t, err) @@ -284,9 +260,10 @@ func TestE2ESetupRequestTransitMac(t *testing.T) { // at the destination AS: tc.transitReq.Path.CurrentStep = len(tc.transitReq.Path.Steps) - 1 + dstIA := tc.transitReq.Path.DstIA() auth := DRKeyAuthenticator{ - localIA: tc.transitReq.Path.DstIA(), - connector: daemon, + localIA: dstIA, + slowKeyer: fakeSlowKeyer{localIA: dstIA}, } ok, err := auth.validateE2ESetupRequestAtDestination(ctx, &tc.transitReq) require.NoError(t, err) @@ -310,7 +287,6 @@ func TestComputeAndValidateResponse(t *testing.T) { path: ct.NewPath(0, "1-ff00:0:111", 1, 1, "1-ff00:0:110", 2, 1, "1-ff00:0:112", 0), }, } - mockKeys := mockKeysSlowIsSrc(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -318,31 +294,23 @@ func TestComputeAndValidateResponse(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) - // at the transit ASes: for step := 1; step < len(tc.path.Steps); step++ { tc.path.CurrentStep = step + authIA := tc.path.Steps[step].IA auth := DRKeyAuthenticator{ - localIA: tc.path.Steps[step].IA, - connector: daemon, + localIA: authIA, + fastKeyer: fakeFastKeyer{localIA: authIA}, } err := auth.ComputeResponseMAC(ctx, tc.res, tc.path) require.NoError(t, err) } // at the initiator AS: + srcIA := tc.path.SrcIA() auth := DRKeyAuthenticator{ - localIA: tc.path.SrcIA(), - connector: daemon, + localIA: srcIA, + slowKeyer: fakeSlowKeyer{localIA: srcIA}, } tc.path.CurrentStep = 0 ok, err := auth.ValidateResponse(ctx, tc.res, tc.path) @@ -412,7 +380,6 @@ func TestComputeAndValidateSegmentSetupResponse(t *testing.T) { lastStepWhichComputes: 2, }, } - mockKeys := mockKeysSlowIsSrc(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -420,16 +387,6 @@ func TestComputeAndValidateSegmentSetupResponse(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) - // at the transit ASes: for step := len(tc.path.Steps) - 1; step >= 0; step-- { tc.path.CurrentStep = step @@ -445,18 +402,20 @@ func TestComputeAndValidateSegmentSetupResponse(t *testing.T) { if step > tc.lastStepWhichComputes || step == 0 { continue } + authIA := tc.path.Steps[step].IA auth := DRKeyAuthenticator{ - localIA: tc.path.Steps[step].IA, - connector: daemon, + localIA: authIA, + fastKeyer: fakeFastKeyer{localIA: authIA}, } err := auth.ComputeSegmentSetupResponseMAC(ctx, tc.res, tc.path) require.NoError(t, err) } // at the initiator AS: + srcIA := tc.path.SrcIA() auth := DRKeyAuthenticator{ - localIA: tc.path.SrcIA(), - connector: daemon, + localIA: srcIA, + slowKeyer: fakeSlowKeyer{localIA: srcIA}, } tc.path.CurrentStep = 0 ok, err := auth.ValidateSegmentSetupResponse(ctx, tc.res, tc.path) @@ -489,7 +448,6 @@ func TestComputeAndValidateE2EResponseError(t *testing.T) { }, } - mockKeys := mockKeysSlowIsSrcWithHost(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -497,16 +455,6 @@ func TestComputeAndValidateE2EResponseError(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) - // colibri services, all ASes: for i := len(tc.path.Steps) - 1; i >= 0; i-- { // from last to first step := tc.path.Steps[i] @@ -514,7 +462,7 @@ func TestComputeAndValidateE2EResponseError(t *testing.T) { auth := DRKeyAuthenticator{ localIA: step.IA, - connector: daemon, + fastKeyer: fakeFastKeyer{localIA: step.IA}, } if failure, ok := tc.response.(*base.ResponseFailure); ok { @@ -530,6 +478,11 @@ func TestComputeAndValidateE2EResponseError(t *testing.T) { } // initiator end-host: + ctrl := gomock.NewController(t) + defer ctrl.Finish() + daemon := mock_daemon.NewMockConnector(ctrl) + mockDRKeys(t, daemon, srcIA(), tc.srcHost) + switch res := tc.response.(type) { case *base.ResponseFailure: clientRes := &libcol.E2EResponseError{ @@ -605,7 +558,6 @@ func TestComputeAndValidateE2ESetupResponse(t *testing.T) { }, } - mockKeys := mockKeysSlowIsSrcWithHost(t) for name, tc := range cases { name, tc := name, tc t.Run(name, func(t *testing.T) { @@ -613,16 +565,6 @@ func TestComputeAndValidateE2ESetupResponse(t *testing.T) { ctx, cancelF := context.WithTimeout(context.Background(), time.Second) defer cancelF() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - daemon := mock_daemon.NewMockConnector(ctrl) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - return mustFindKey(t, mockKeys, meta) - }) - // mock the compuation of the drkey authenticator by the col service of all ASes. // walk in reverse from last to first AS. for i := len(tc.path.Steps) - 1; i >= 0; i-- { // from last to first @@ -646,7 +588,7 @@ func TestComputeAndValidateE2ESetupResponse(t *testing.T) { auth := DRKeyAuthenticator{ localIA: step.IA, - connector: daemon, + fastKeyer: fakeFastKeyer{localIA: step.IA}, } err := auth.ComputeE2ESetupResponseMAC(ctx, tc.response, tc.path, addr.HostFromIP(tc.srcHost), tc.rsvID) @@ -654,6 +596,11 @@ func TestComputeAndValidateE2ESetupResponse(t *testing.T) { } // initiator end-host: + ctrl := gomock.NewController(t) + defer ctrl.Finish() + daemon := mock_daemon.NewMockConnector(ctrl) + mockDRKeys(t, daemon, srcIA(), tc.srcHost) + switch res := tc.response.(type) { case *e2e.SetupResponseSuccess: colibriPath := e2e.DeriveColibriPath(tc.rsvID, tc.token) @@ -689,12 +636,8 @@ func TestComputeAndValidateE2ESetupResponse(t *testing.T) { } } -func srcIA() string { - return "1-ff00:0:111" -} - -func dstIA() string { - return "1-ff00:0:112" +func srcIA() addr.IA { + return xtest.MustParseIA("1-ff00:0:111") } func srcHost() string { @@ -705,37 +648,45 @@ func dstHost() string { return "10.2.2.2" } -func mockKeysSlowIsSrc(t *testing.T) dkt.KeyMap { - return dkt.MockKeys1SlowSide(t, srcIA(), - "1-ff00:0:111", - "1-ff00:0:110", - "1-ff00:0:112", - ) +type fakeFastKeyer struct { + localIA addr.IA } -// mockKeysSlowIsSrcWithHost uses AS 1-ff00:0:111 as slow path. -func mockKeysSlowIsSrcWithHost(t *testing.T) dkt.KeyMap { - return dkt.MockKeys1SlowSideWithHost(t, srcIA(), srcHost(), - "1-ff00:0:111", - "1-ff00:0:110", - "1-ff00:0:112", - ) +func (f fakeFastKeyer) Lvl1(_ context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + if meta.SrcIA != f.localIA { + panic(fmt.Sprintf("cannot derive, SrcIA != localIA, SrcIA=%s, localIA=%s", + meta.SrcIA, f.localIA)) + } + return fakedrkey.Lvl1Key(meta), nil } -// mockKeysSlowIsDst uses AS 1-ff00:0:112 as slow path. -func mockKeysSlowIsDst(t *testing.T) dkt.KeyMap { - return dkt.MockKeys1SlowSide(t, dstIA(), - "1-ff00:0:111", - "1-ff00:0:110", - "1-ff00:0:112", - ) +func (f fakeFastKeyer) ASHost(_ context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + if meta.SrcIA != f.localIA { + panic(fmt.Sprintf("cannot derive, SrcIA != localIA, SrcIA=%s, localIA=%s", + meta.SrcIA, f.localIA)) + } + return fakedrkey.ASHost(meta), nil } -func mustFindKey(t *testing.T, mockKeys dkt.KeyMap, meta drkey.Lvl2Meta) (drkey.Lvl2Key, error) { +type fakeSlowKeyer struct { + localIA addr.IA +} + +func (f fakeSlowKeyer) Lvl1(_ context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + if meta.DstIA != f.localIA { + panic(fmt.Sprintf("cannot fetch, DstIA != localIA, DstIA=%s, localIA=%s", + meta.DstIA, f.localIA)) + } + return fakedrkey.Lvl1Key(meta), nil +} + +func mockDRKeys(t *testing.T, daemon *mock_daemon.MockConnector, localIA addr.IA, localIP net.IP) { t.Helper() - k, ok := dkt.GetKey(mockKeys, meta.SrcIA, meta.DstIA) - require.True(t, ok, "not found %s", meta.SrcIA) - require.Equal(t, meta.KeyType, k.KeyType, "wrong key type. Expected: %v, got: %v", - meta.KeyType, k.KeyType) - return k, nil + + fake := fakedrkey.Keyer{ + LocalIA: localIA, + LocalIP: localIP, + } + daemon.EXPECT().DRKeyGetASHostKey(gomock.Any(), gomock.Any()).AnyTimes(). + DoAndReturn(fake.DRKeyGetASHostKey) } diff --git a/go/co/reservationstore/store.go b/go/co/reservationstore/store.go index f9a0c4fd67..015c841023 100644 --- a/go/co/reservationstore/store.go +++ b/go/co/reservationstore/store.go @@ -33,13 +33,13 @@ import ( "github.com/scionproto/scion/go/lib/colibri/coliquic" libcolibri "github.com/scionproto/scion/go/lib/colibri/dataplane" "github.com/scionproto/scion/go/lib/colibri/reservation" - "github.com/scionproto/scion/go/lib/daemon" "github.com/scionproto/scion/go/lib/log" "github.com/scionproto/scion/go/lib/scrypto" "github.com/scionproto/scion/go/lib/serrors" "github.com/scionproto/scion/go/lib/snet" "github.com/scionproto/scion/go/lib/topology" "github.com/scionproto/scion/go/lib/util" + libgrpc "github.com/scionproto/scion/go/pkg/grpc" colpb "github.com/scionproto/scion/go/pkg/proto/colibri" ) @@ -59,7 +59,8 @@ type Store struct { var _ reservationstorage.Store = (*Store)(nil) // NewStore creates a new reservation store. -func NewStore(topo *topology.Loader, sd daemon.Connector, router snet.Router, +func NewStore(topo *topology.Loader, tcpDialer libgrpc.Dialer, + router snet.Router, dialer coliquic.GRPCClientDialer, db backend.DB, admitter admission.Admitter, masterKey []byte) (*Store, error) { @@ -85,7 +86,7 @@ func NewStore(topo *topology.Loader, sd daemon.Connector, router snet.Router, db: db, admitter: admitter, operator: operator, - authenticator: NewDRKeyAuthenticator(topo.IA(), sd), + authenticator: NewDRKeyAuthenticator(topo.IA(), tcpDialer), colibriKey: colibriKey, }, nil } @@ -435,7 +436,8 @@ func (s *Store) ConfirmSegmentReservation(ctx context.Context, req *base.Request Message: "failed to confirm index", } if !req.IsFirstAS() { - if err := s.authenticator.ComputeResponseMAC(ctx, failedResponse, req.Path); err != nil { + if err := s.authenticator.ComputeResponseMAC(ctx, failedResponse, + req.Path); err != nil { return nil, serrors.WrapStr("authenticating response", err) } } @@ -1267,6 +1269,7 @@ func (s *Store) authenticateE2ESetupReq(ctx context.Context, req *e2e.SetupReq) func (s *Store) admitSegmentReservation(ctx context.Context, req *segment.SetupReq) ( segment.SegmentSetupResponse, error) { + logger := log.FromCtx(ctx) failedResponse := &segment.SegmentSetupResponseFailure{ AuthenticatedResponse: base.AuthenticatedResponse{ @@ -1287,7 +1290,7 @@ func (s *Store) admitSegmentReservation(ctx context.Context, req *segment.SetupR return res, nil } - log.Debug("segment admission", "id", req.ID, "src_ia", req.Path.SrcIA(), + logger.Debug("segment admission", "id", req.ID, "src_ia", req.Path.SrcIA(), "dst_ia", req.Path.DstIA(), "path", req.Path) if err := req.Validate(); err != nil { failedResponse.Message = s.errWrapStr("request failed validation", err).Error() @@ -1342,13 +1345,13 @@ func (s *Store) admitSegmentReservation(ctx context.Context, req *segment.SetupR // compute admission max BW err = s.admitter.AdmitRsv(ctx, tx, req) if err != nil { - log.Debug("segment not admitted here", "id", req.ID.String(), "err", err) + logger.Debug("segment not admitted here", "id", req.ID.String(), "err", err) failedResponse.Message = "segment not admitted: " + s.err(err).Error() return updateResponse(failedResponse) } // admitted; the request contains already the value inside the "allocation beads" of the rsv allocBW := req.AllocTrail[len(req.AllocTrail)-1].AllocBW - log.Info("COLIBRI admission successful", "id", req.ID.String(), "idx", req.Index, + logger.Info("COLIBRI admission successful", "id", req.ID.String(), "idx", req.Index, "alloc", allocBW, "trail", req.AllocTrail) idx, err := rsv.NewIndex(req.Index, req.ExpirationTime, req.MinBW, req.MaxBW, allocBW, diff --git a/go/cs/BUILD.bazel b/go/cs/BUILD.bazel index 967dea0f40..d3cc7659af 100644 --- a/go/cs/BUILD.bazel +++ b/go/cs/BUILD.bazel @@ -21,6 +21,7 @@ go_library( "//go/cs/segreq/grpc:go_default_library", "//go/lib/addr:go_default_library", "//go/lib/common:go_default_library", + "//go/lib/drkey:go_default_library", "//go/lib/infra/infraenv:go_default_library", "//go/lib/infra/modules/segfetcher/grpc:go_default_library", "//go/lib/infra/modules/seghandler:go_default_library", @@ -34,6 +35,7 @@ go_library( "//go/lib/serrors:go_default_library", "//go/lib/snet:go_default_library", "//go/lib/topology:go_default_library", + "//go/lib/util:go_default_library", "//go/pkg/api/cppki/api:go_default_library", "//go/pkg/api/jwtauth:go_default_library", "//go/pkg/api/segments/api:go_default_library", @@ -69,8 +71,6 @@ go_library( "@com_github_go_chi_chi_v5//:go_default_library", "@com_github_go_chi_cors//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library", - "@com_github_grpc_ecosystem_grpc_opentracing//go/otgrpc:go_default_library", - "@com_github_opentracing_opentracing_go//:go_default_library", "@com_github_spf13_cobra//:go_default_library", "@in_gopkg_yaml_v2//:go_default_library", "@org_golang_google_grpc//:go_default_library", diff --git a/go/cs/config/BUILD.bazel b/go/cs/config/BUILD.bazel index 79ee88e6fe..e1fe327485 100644 --- a/go/cs/config/BUILD.bazel +++ b/go/cs/config/BUILD.bazel @@ -13,7 +13,7 @@ go_library( deps = [ "//go/lib/addr:go_default_library", "//go/lib/config:go_default_library", - "//go/lib/drkey/protocol:go_default_library", + "//go/lib/drkey:go_default_library", "//go/lib/env:go_default_library", "//go/lib/log:go_default_library", "//go/lib/serrors:go_default_library", @@ -22,6 +22,7 @@ go_library( "//go/pkg/api/jwtauth:go_default_library", "//go/pkg/storage:go_default_library", "//go/pkg/trust/config:go_default_library", + "@af_inet_netaddr//:go_default_library", ], ) @@ -33,13 +34,14 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//go/lib/drkey:go_default_library", "//go/lib/env/envtest:go_default_library", "//go/lib/log/logtest:go_default_library", "//go/pkg/api/apitest:go_default_library", "//go/pkg/api/jwtauth:go_default_library", "//go/pkg/storage:go_default_library", "//go/pkg/storage/test:go_default_library", - "@com_github_burntsushi_toml//:go_default_library", + "@af_inet_netaddr//:go_default_library", "@com_github_pelletier_go_toml//:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/go/cs/config/drkey.go b/go/cs/config/drkey.go index ad2a6702a2..601d637e0b 100644 --- a/go/cs/config/drkey.go +++ b/go/cs/config/drkey.go @@ -16,68 +16,59 @@ package config import ( "io" + "strings" "time" + "inet.af/netaddr" + "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/config" - "github.com/scionproto/scion/go/lib/drkey/protocol" + "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/lib/serrors" - "github.com/scionproto/scion/go/lib/util" "github.com/scionproto/scion/go/pkg/storage" ) const ( // DefaultEpochDuration is the default duration for the drkey SV and derived keys - DefaultEpochDuration = 24 * time.Hour + DefaultEpochDuration = 24 * time.Hour + DefaultPrefetchEntries = 10000 + EnvVarEpochDuration = "SCION_TESTING_DRKEY_EPOCH_DURATION" ) var _ (config.Config) = (*DRKeyConfig)(nil) // DRKeyConfig is the configuration for the connection to the trust database. type DRKeyConfig struct { - // enabled is set to true if we find all the required fields in the configuration. - enabled bool // DRKeyDB contains the DRKey DB configuration. - DRKeyDB storage.DBConfig `toml:"drkey_db,omitempty"` - // EpochDuration is the duration of the keys in this CS. - EpochDuration util.DurWrap `toml:"epoch_duration,omitempty"` - // AuthorizedDelegations is the DelegationList for this CS. - Delegation DelegationList `toml:"delegation,omitempty"` - - //TLS config - CertFile string `toml:"cert_file,omitempty"` - KeyFile string `toml:"key_file,omitempty"` -} - -// NewDRKeyConfig returns a pointer to a valid, empty configuration. -func NewDRKeyConfig() *DRKeyConfig { - c := DRKeyConfig{ - DRKeyDB: storage.DBConfig{}, - Delegation: DelegationList{}, - } - return &c + Lvl1DB storage.DBConfig `toml:"lvl1_db,omitempty"` + // DRKeyDB contains the DRKey DB configuration. + SVDB storage.DBConfig `toml:"sv_db,omitempty"` + // Delegations is the authorized SVHostList for this CS. + Delegation SVHostList `toml:"delegation,omitempty"` + // PrefetchEntries is the number of lvl1 keys to be prefetched + PrefetchEntries int `toml:"prefetch_entries,omitempty"` } // InitDefaults initializes values of unset keys and determines if the configuration enables DRKey. func (cfg *DRKeyConfig) InitDefaults() { - cfg.enabled = true - if cfg.EpochDuration.Duration == 0 { - cfg.EpochDuration.Duration = DefaultEpochDuration + if cfg.PrefetchEntries == 0 { + cfg.PrefetchEntries = DefaultPrefetchEntries } - config.InitAll(&cfg.Delegation) + config.InitAll( + cfg.Lvl1DB.WithDefault(""), + cfg.SVDB.WithDefault(""), + &cfg.Delegation, + ) } // Enabled returns true if DRKey is configured. False otherwise. func (cfg *DRKeyConfig) Enabled() bool { - if cfg.DRKeyDB.Connection == "" { - return false - } - return true + return cfg.Lvl1DB.Connection != "" } // Validate validates that all values are parsable. func (cfg *DRKeyConfig) Validate() error { - return config.ValidateAll(&cfg.DRKeyDB, &cfg.Delegation) + return config.ValidateAll(&cfg.Lvl1DB, &cfg.SVDB, &cfg.Delegation) } // Sample writes a config sample to the writer. @@ -87,10 +78,17 @@ func (cfg *DRKeyConfig) Sample(dst io.Writer, path config.Path, ctx config.CtxMa config.CtxMap{config.ID: idSample}, config.OverrideName( config.FormatData( - &cfg.DRKeyDB, - storage.SetID(storage.SampleDRKeyDB, idSample).Connection, + &cfg.Lvl1DB, + storage.SetID(storage.SampleDRKeyLvl1DB, idSample).Connection, ), - "drkey_db", + "lvl1_db", + ), + config.OverrideName( + config.FormatData( + &cfg.SVDB, + storage.SetID(storage.SampleDRKeySVDB, idSample).Connection, + ), + "sv_db", ), &cfg.Delegation, ) @@ -101,24 +99,29 @@ func (cfg *DRKeyConfig) ConfigName() string { return "drkey" } -// DelegationList configures which endhosts can get delegation secrets, per protocol. -type DelegationList map[string][]string +// SVHostList configures which endhosts can get delegation secrets, per protocol. +type SVHostList map[string][]string -var _ (config.Config) = (*DelegationList)(nil) +var _ (config.Config) = (*SVHostList)(nil) // InitDefaults will not add or modify any entry in the config. -func (cfg *DelegationList) InitDefaults() { +func (cfg *SVHostList) InitDefaults() { if *cfg == nil { - *cfg = make(DelegationList) + *cfg = make(SVHostList) } } // Validate validates that the protocols exist, and their addresses are parsable. -func (cfg *DelegationList) Validate() error { +func (cfg *SVHostList) Validate() error { for proto, list := range *cfg { - if _, found := protocol.KnownDerivations[proto]; !found { + protoString := "PROTOCOL_" + strings.ToUpper(proto) + protoID, ok := drkey.ProtocolStringToId(protoString) + if !ok { return serrors.New("Configured protocol not found", "protocol", proto) } + if protoID == drkey.Generic { + return serrors.New("GENERIC protocol is not allowed") + } for _, ip := range list { if h := addr.HostFromIPStr(ip); h == nil { return serrors.New("Syntax error: not a valid address", "ip", ip) @@ -129,32 +132,39 @@ func (cfg *DelegationList) Validate() error { } // Sample writes a config sample to the writer. -func (cfg *DelegationList) Sample(dst io.Writer, path config.Path, ctx config.CtxMap) { - config.WriteString(dst, drkeyDelegationListSample) +func (cfg *SVHostList) Sample(dst io.Writer, path config.Path, ctx config.CtxMap) { + config.WriteString(dst, drkeySVHostListSample) } // ConfigName is the key in the toml file. -func (cfg *DelegationList) ConfigName() string { +func (cfg *SVHostList) ConfigName() string { return "delegation" } -// ToMapPerHost will return map where there is a set of supported protocols per host. -func (cfg *DelegationList) ToMapPerHost() map[[16]byte]map[string]struct{} { - m := make(map[[16]byte]map[string]struct{}) +type HostProto struct { + Host netaddr.IP + Proto drkey.Protocol +} + +// ToAllowedSet will return map where there is a set of supported (Host,Protocol). +func (cfg *SVHostList) ToAllowedSet() map[HostProto]struct{} { + m := make(map[HostProto]struct{}) for proto, ipList := range *cfg { for _, ip := range ipList { - host := addr.HostFromIPStr(ip) - if host == nil { + host, err := netaddr.ParseIP(ip) + if err != nil { + continue + } + protoString := "PROTOCOL_" + strings.ToUpper(proto) + protoID, ok := drkey.ProtocolStringToId(protoString) + if !ok { continue } - var rawHost [16]byte - copy(rawHost[:], host.IP().To16()) - protoSet := m[rawHost] - if protoSet == nil { - protoSet = make(map[string]struct{}) + hostProto := HostProto{ + Host: host, + Proto: protoID, } - protoSet[proto] = struct{}{} - m[rawHost] = protoSet + m[hostProto] = struct{}{} } } return m diff --git a/go/cs/config/drkey_test.go b/go/cs/config/drkey_test.go index 1024f09263..184240efaf 100644 --- a/go/cs/config/drkey_test.go +++ b/go/cs/config/drkey_test.go @@ -17,118 +17,143 @@ package config import ( "bytes" "io/ioutil" - "net" "os" "testing" - "time" - "github.com/BurntSushi/toml" + toml "github.com/pelletier/go-toml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "inet.af/netaddr" + "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/pkg/storage" ) func TestInitDefaults(t *testing.T) { var cfg DRKeyConfig cfg.InitDefaults() - assert.EqualValues(t, 24*time.Hour, cfg.EpochDuration.Duration) + assert.EqualValues(t, DefaultPrefetchEntries, cfg.PrefetchEntries) + assert.NotNil(t, cfg.Delegation) } -func TestDRKeyConfigSample(t *testing.T) { +func TestSample(t *testing.T) { var sample bytes.Buffer var cfg DRKeyConfig cfg.Sample(&sample, nil, nil) - meta, err := toml.Decode(sample.String(), &cfg) + err := toml.NewDecoder(bytes.NewReader(sample.Bytes())).Strict(true).Decode(&cfg) require.NoError(t, err) - require.Empty(t, meta.Undecoded()) err = cfg.Validate() require.NoError(t, err) - assert.Equal(t, DefaultEpochDuration, cfg.EpochDuration.Duration) } func TestDisable(t *testing.T) { - var cfg = NewDRKeyConfig() - require.False(t, cfg.Enabled()) - var err error - err = cfg.Validate() - require.NoError(t, err) - cfg.EpochDuration.Duration = 10 * time.Hour - require.False(t, cfg.Enabled()) - cfg.DRKeyDB.Connection = "a" - cfg.InitDefaults() - require.True(t, cfg.Enabled()) - err = cfg.Validate() - require.NoError(t, err) - assert.EqualValues(t, 10*time.Hour, cfg.EpochDuration.Duration) + cases := []struct { + name string + prepareCfg func(cfg *DRKeyConfig) + expectEnabled bool + }{ + { + name: "default", + expectEnabled: false, + }, + { + name: "with CacheEntries", + prepareCfg: func(cfg *DRKeyConfig) { + cfg.PrefetchEntries = 100 + }, + expectEnabled: false, + }, + { + name: "with Lvl1DB", + prepareCfg: func(cfg *DRKeyConfig) { + cfg.Lvl1DB.Connection = "test" + }, + expectEnabled: true, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + cfg := &DRKeyConfig{} + cfg.InitDefaults() + if c.prepareCfg != nil { + c.prepareCfg(cfg) + } + require.NoError(t, cfg.Validate()) + assert.Equal(t, c.expectEnabled, cfg.Enabled()) + }) + } } -func TestValidate(t *testing.T) { - var err error - var cfg = NewDRKeyConfig() - err = cfg.Validate() - require.NoError(t, err) - cfg.EpochDuration.Duration = 10 * time.Hour - sample1 := `piskes = ["not an address"]` - toml.Decode(sample1, &cfg.Delegation) - require.Error(t, cfg.Validate()) - sample2 := `piskes = ["1.1.1.1"]` - toml.Decode(sample2, &cfg.Delegation) - require.NoError(t, cfg.Validate()) - cfg.DRKeyDB.Connection = "a" - require.NoError(t, cfg.Validate()) -} - -func TestDelegationListDefaults(t *testing.T) { - var cfg DelegationList +func TestSVHostListDefaults(t *testing.T) { + var cfg SVHostList cfg.InitDefaults() require.NotNil(t, cfg) require.Empty(t, cfg) } -func TestDelegationListSyntax(t *testing.T) { - var cfg DelegationList - sample1 := `piskes = ["1.1.1.1"]` - meta, err := toml.Decode(sample1, &cfg) +func TestSVHostListSyntax(t *testing.T) { + var cfg SVHostList + var err error + sample1 := `scmp = ["1.1.1.1"]` + err = toml.NewDecoder(bytes.NewReader([]byte(sample1))).Strict(true).Decode(&cfg) require.NoError(t, err) - require.Empty(t, meta.Undecoded()) require.NoError(t, cfg.Validate()) - sample2 := `piskes = ["not an address"]` - meta, err = toml.Decode(sample2, &cfg) + sample2 := `scmp = ["not an address"]` + err = toml.NewDecoder(bytes.NewReader([]byte(sample2))).Strict(true).Decode(&cfg) require.NoError(t, err) - require.Empty(t, meta.Undecoded()) require.Error(t, cfg.Validate()) } func TestToMapPerHost(t *testing.T) { - var cfg DelegationList - sample := `piskes = ["1.1.1.1", "2.2.2.2"] + var cfg SVHostList + sample := `dns = ["1.1.1.1", "2.2.2.2"] scmp = ["1.1.1.1"]` - toml.Decode(sample, &cfg) + ip1111, err := netaddr.ParseIP("1.1.1.1") + require.NoError(t, err) + ip2222, err := netaddr.ParseIP("2.2.2.2") + require.NoError(t, err) + err = toml.NewDecoder(bytes.NewReader([]byte(sample))).Strict(true).Decode(&cfg) + require.NoError(t, err) require.NoError(t, cfg.Validate()) - m := cfg.ToMapPerHost() - require.Len(t, m, 2) - - var rawIP [16]byte - copy(rawIP[:], net.ParseIP("1.1.1.1").To16()) - require.Len(t, m[rawIP], 2) - require.Contains(t, m[rawIP], "piskes") - require.Contains(t, m[rawIP], "scmp") - - copy(rawIP[:], net.ParseIP("2.2.2.2").To16()) - require.Len(t, m[rawIP], 1) - require.Contains(t, m[rawIP], "piskes") + m := cfg.ToAllowedSet() + + require.Len(t, m, 3) + require.Contains(t, m, HostProto{ + Host: ip1111, + Proto: drkey.DNS, + }) + require.Contains(t, m, HostProto{ + Host: ip2222, + Proto: drkey.DNS, + }) + require.Contains(t, m, HostProto{ + Host: ip1111, + Proto: drkey.SCMP, + }) } func TestNewLvl1DB(t *testing.T) { cfg := DRKeyConfig{} cfg.InitDefaults() - cfg.DRKeyDB.Connection = tempFile(t) - db, err := storage.NewDRKeyLvl1Storage(cfg.DRKeyDB) + cfg.Lvl1DB.Connection = tempFile(t) + db, err := storage.NewDRKeyLvl1Storage(cfg.Lvl1DB) + defer func() { + db.Close() + os.Remove(cfg.Lvl1DB.Connection) + }() + require.NoError(t, err) + require.NotNil(t, db) +} + +func TestNewSVDB(t *testing.T) { + cfg := DRKeyConfig{} + cfg.InitDefaults() + cfg.SVDB.Connection = tempFile(t) + db, err := storage.NewDRKeySVStorage(cfg.SVDB) defer func() { db.Close() - os.Remove(cfg.DRKeyDB.Connection) + os.Remove(cfg.Lvl1DB.Connection) }() require.NoError(t, err) require.NotNil(t, db) diff --git a/go/cs/config/sample.go b/go/cs/config/sample.go index 59138ea25e..d320e87d5a 100644 --- a/go/cs/config/sample.go +++ b/go/cs/config/sample.go @@ -52,12 +52,12 @@ mode = "in-process" ` const drkeySample = ` -# EpochDuration of the DRKey secret value and of all derived keys. (default "24h") -epoch_duration = "24h" +# Number of distinct Lvl1Keys to be prefetched. +prefetch_entries = 10000 ` -const drkeyDelegationListSample = ` -# The list of hosts authorized to get a DS per protocol. -piskes = [ "127.0.0.1", "127.0.0.2"] +const drkeySVHostListSample = ` +# The list of hosts authorized to get a SV per protocol. +scmp = [ "127.0.0.1", "127.0.0.2"] ` const serviceSample = ` diff --git a/go/cs/main.go b/go/cs/main.go index b3004ef8c4..966de0b32b 100644 --- a/go/cs/main.go +++ b/go/cs/main.go @@ -21,14 +21,13 @@ import ( "fmt" "net/http" _ "net/http/pprof" + "os" "path/filepath" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/cors" promgrpc "github.com/grpc-ecosystem/go-grpc-prometheus" - "github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" - "github.com/opentracing/opentracing-go" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" "google.golang.org/grpc" @@ -48,6 +47,7 @@ import ( segreqgrpc "github.com/scionproto/scion/go/cs/segreq/grpc" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/common" + libdrkey "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/lib/infra/infraenv" segfetchergrpc "github.com/scionproto/scion/go/lib/infra/modules/segfetcher/grpc" "github.com/scionproto/scion/go/lib/infra/modules/seghandler" @@ -61,6 +61,7 @@ import ( "github.com/scionproto/scion/go/lib/serrors" "github.com/scionproto/scion/go/lib/snet" "github.com/scionproto/scion/go/lib/topology" + "github.com/scionproto/scion/go/lib/util" cppkiapi "github.com/scionproto/scion/go/pkg/api/cppki/api" "github.com/scionproto/scion/go/pkg/api/jwtauth" segapi "github.com/scionproto/scion/go/pkg/api/segments/api" @@ -512,57 +513,79 @@ func realMain(ctx context.Context) error { dpb.RegisterDiscoveryServiceServer(quicServer, ds) //DRKey feature - masterKey, err := loadMasterSecret(globalCfg.General.ConfigDir) - if err != nil { - return serrors.WrapStr("loading master secret in DRKey", err) - } - svFactory := drkey.NewSecretValueFactory( - masterKey.Key0, globalCfg.DRKey.EpochDuration.Duration) - drkeyDB, err := storage.NewDRKeyLvl1Storage(globalCfg.DRKey.DRKeyDB) - if err != nil { - return serrors.WrapStr("initializing DRKey DB", err) - } - loader := trust.FileLoader{ - CertFile: globalCfg.DRKey.CertFile, - KeyFile: globalCfg.DRKey.KeyFile, - } - tlsMgr := trust.NewTLSCryptoManager(loader, trustDB) - drkeyFetcher := drkeygrpc.DRKeyFetcher{ - Getter: drkeygrpc.Lvl1KeyFetcher{ + var drkeyEngine drkey.ServiceEngine + var quicTLSServer *grpc.Server + var epochDuration time.Duration + if globalCfg.DRKey.Enabled() { + epochDuration, err = loadEpochDuration() + if err != nil { + return err + } + log.Debug("DRKey debug info", "epoch duration", epochDuration.String()) + masterKey, err := loadMasterSecret(globalCfg.General.ConfigDir) + if err != nil { + return serrors.WrapStr("loading master secret in DRKey", err) + } + svDB, err := storage.NewDRKeySVStorage(globalCfg.DRKey.SVDB) + if err != nil { + return serrors.WrapStr("initializing Secret Value DB", err) + } + svDB = libdrkey.SVWithMetrics(string(storage.BackendSqlite), svDB) + defer svDB.Close() + drkeyDB, err := storage.NewDRKeyLvl1Storage(globalCfg.DRKey.Lvl1DB) + if err != nil { + return serrors.WrapStr("initializing DRKey DB", err) + } + drkeyDB = libdrkey.Lvl1WithMetrics(string(storage.BackendSqlite), drkeyDB) + defer drkeyDB.Close() + loader := trust.X509KeyPairProvider{ + IA: topo.IA(), + DB: trustDB, + Loader: cstrust.LoadingRing{ + Dir: filepath.Join(globalCfg.General.ConfigDir, "crypto/as"), + }, + } + tlsMgr := trust.NewTLSCryptoManager(loader, trustDB) + drkeyFetcher := drkeygrpc.Fetcher{ Dialer: &libgrpc.TLSQUICDialer{ - Rewriter: nc.AddressRewriter(nil), - Dialer: quicStack.TLSDialer, - Credentials: trust.GetTansportCredentials(tlsMgr), + Rewriter: nc.AddressRewriter(nil), + Dialer: quicStack.TLSDialer, + Credentials: credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + GetClientCertificate: tlsMgr.GetClientCertificate, + VerifyPeerCertificate: tlsMgr.VerifyServerCertificate, + VerifyConnection: tlsMgr.VerifyConnection, + }), }, - Router: segreq.NewRouter(fetcherCfg), - }, + Router: segreq.NewRouter(fetcherCfg), + MaxRetries: 20, + } + drkeyEngine, err = drkey.NewServiceEngine(topo.IA(), svDB, masterKey.Key0, + epochDuration, drkeyDB, drkeyFetcher, globalCfg.DRKey.PrefetchEntries) + if err != nil { + return serrors.WrapStr("initializing Service Store", err) + } + drkeyService := &drkeygrpc.Server{ + LocalIA: topo.IA(), + Engine: drkeyEngine, + AllowedSVHostProto: globalCfg.DRKey.Delegation.ToAllowedSet(), + } + srvConfig := &tls.Config{ + InsecureSkipVerify: true, + GetCertificate: tlsMgr.GetCertificate, + VerifyPeerCertificate: tlsMgr.VerifyClientCertificate, + ClientAuth: tls.RequireAnyClientCert, + } + quicTLSServer = grpc.NewServer( + grpc.Creds(credentials.NewTLS(srvConfig)), + libgrpc.UnaryServerInterceptor(), + ) + cppb.RegisterDRKeyInterServiceServer(quicTLSServer, drkeyService) + cppb.RegisterDRKeyIntraServiceServer(tcpServer, drkeyService) + log.Info("DRKey is enabled") + } else { + log.Info("DRKey is DISABLED by configuration") } - drkeyServStore := &drkey.ServiceStore{ - LocalIA: topo.IA(), - DB: drkeyDB, - SecretValues: svFactory, - Fetcher: drkeyFetcher, - } - drkeyService := &drkeygrpc.DRKeyServer{ - LocalIA: topo.IA(), - Store: drkeyServStore, - AllowedDSs: globalCfg.DRKey.Delegation.ToMapPerHost(), - } - srvConfig := &tls.Config{ - InsecureSkipVerify: true, - GetCertificate: tlsMgr.GetCertificate, - VerifyPeerCertificate: tlsMgr.VerifyPeerCertificate, - ClientAuth: tls.RequireAnyClientCert, - } - quicTLSServer := grpc.NewServer( - grpc.Creds(credentials.NewTLS(srvConfig)), - grpc.ChainUnaryInterceptor( - otgrpc.OpenTracingServerInterceptor(opentracing.GlobalTracer()), - libgrpc.LogIDServerInterceptor(), - ), - ) - cppb.RegisterDRKeyLvl1ServiceServer(quicTLSServer, drkeyService) - cppb.RegisterDRKeyLvl2ServiceServer(tcpServer, drkeyService) dsHealth := health.NewServer() dsHealth.SetServingStatus("discovery", healthpb.HealthCheckResponse_SERVING) @@ -605,6 +628,7 @@ func realMain(ctx context.Context) error { cleanup.Add(func() error { tcpServer.GracefulStop(); return nil }) if globalCfg.DRKey.Enabled() { + promgrpc.Register(quicTLSServer) g.Go(func() error { defer log.HandlePanic() return quicTLSServer.Serve(quicStack.TLSListener) @@ -709,7 +733,7 @@ func realMain(ctx context.Context) error { Signer: signer, Inspector: inspector, Metrics: metrics, - DRKeyStore: drkeyServStore, + DRKeyEngine: drkeyEngine, MACGen: macGen, NextHopper: topo, StaticInfo: func() *beaconing.StaticInfoCfg { return staticInfo }, @@ -717,7 +741,7 @@ func realMain(ctx context.Context) error { OriginationInterval: globalCfg.BS.OriginationInterval.Duration, PropagationInterval: globalCfg.BS.PropagationInterval.Duration, RegistrationInterval: globalCfg.BS.RegistrationInterval.Duration, - DRKeyEpochInterval: globalCfg.DRKey.EpochDuration.Duration, + DRKeyEpochInterval: epochDuration, HiddenPathRegistrationCfg: hpWriterCfg, AllowIsdLoop: isdLoopAllowed, }) @@ -831,3 +855,14 @@ func (h *healther) GetTRCHealth(ctx context.Context) api.TRCHealthData { TRCID: trc.TRC.ID, } } +func loadEpochDuration() (time.Duration, error) { + s := os.Getenv(config.EnvVarEpochDuration) + if s == "" { + return config.DefaultEpochDuration, nil + } + duration, err := util.ParseDuration(s) + if err != nil { + return 0, serrors.WrapStr("parsing SCION_TESTING_DRKEY_EPOCH_DURATION", err) + } + return duration, nil +} diff --git a/go/daemon/BUILD.bazel b/go/daemon/BUILD.bazel index 887398d353..79be2b1481 100644 --- a/go/daemon/BUILD.bazel +++ b/go/daemon/BUILD.bazel @@ -14,7 +14,7 @@ go_library( visibility = ["//visibility:private"], deps = [ "//go/lib/addr:go_default_library", - "//go/lib/drkeystorage:go_default_library", + "//go/lib/drkey:go_default_library", "//go/lib/infra:go_default_library", "//go/lib/infra/modules/segfetcher:go_default_library", "//go/lib/infra/modules/segfetcher/grpc:go_default_library", diff --git a/go/daemon/main.go b/go/daemon/main.go index 2121c2bdf0..5218aa96a4 100644 --- a/go/daemon/main.go +++ b/go/daemon/main.go @@ -32,7 +32,7 @@ import ( "google.golang.org/grpc/resolver" "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkeystorage" + libdrkey "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/lib/infra" "github.com/scionproto/scion/go/lib/infra/modules/segfetcher" segfetchergrpc "github.com/scionproto/scion/go/lib/infra/modules/segfetcher/grpc" @@ -189,18 +189,23 @@ func realMain(ctx context.Context) error { }, 10*time.Second, 10*time.Second) defer trcLoader.Stop() - drkeyDB, err := storage.NewDRKeyLvl2Storage(globalCfg.DRKeyDB) - if err != nil { - log.Error("Creating Lvl2 DRKey DB", "err", err) - } - defer drkeyDB.Close() - drkeyFetcher := dk_grpc.DRKeyFetcher{ - Dialer: dialer, + var drkeyClientEngine drkey.ClientEngine + if globalCfg.DRKeyLvl2DB.Connection != "" { + drkeyDB, err := storage.NewDRKeyLvl2Storage(globalCfg.DRKeyLvl2DB) + if err != nil { + return serrors.WrapStr("creating lvl2 DRKey DB", err) + } + drkeyDB = libdrkey.Lvl2WithMetrics(string(storage.BackendSqlite), drkeyDB) + defer drkeyDB.Close() + + drkeyFetcher := dk_grpc.Fetcher{ + Dialer: dialer, + } + drkeyClientEngine = drkey.NewClientEngine(topo.IA(), drkeyDB, drkeyFetcher) + drkeyClientCleaner := periodic.Start(drkey.NewClientEngineCleaner(drkeyClientEngine), + 5*time.Minute, 5*time.Minute) + defer drkeyClientCleaner.Stop() } - drkeyStore := drkey.NewClientStore(topo.IA(), drkeyDB, drkeyFetcher) - drkeyCleaner := periodic.Start(drkeystorage.NewStoreCleaner(drkeyStore), - time.Hour, 10*time.Minute) - defer drkeyCleaner.Stop() listen := daemon.APIAddress(globalCfg.SD.Address) listener, err := net.Listen("tcp", listen) @@ -255,11 +260,11 @@ func realMain(ctx context.Context) error { Cfg: globalCfg.SD, }, ), - Engine: engine, - RevCache: revCache, - DRKeyStore: drkeyStore, - ColFetcher: colibri.NewFetcher(dialer), - ColClient: &colibri.DaemonClient{Dialer: dialer}, + Engine: engine, + RevCache: revCache, + DRKeyClient: drkeyClientEngine, + ColFetcher: colibri.NewFetcher(dialer), + ColClient: &colibri.DaemonClient{Dialer: dialer}, }, )) diff --git a/go/lib/colibri/BUILD.bazel b/go/lib/colibri/BUILD.bazel index 230758ce21..357f47652c 100644 --- a/go/lib/colibri/BUILD.bazel +++ b/go/lib/colibri/BUILD.bazel @@ -16,13 +16,13 @@ go_library( "//go/lib/colibri/reservation:go_default_library", "//go/lib/common:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/drkeyutil:go_default_library", "//go/lib/serrors:go_default_library", "//go/lib/slayers/path/colibri:go_default_library", "//go/lib/slayers/path/empty:go_default_library", "//go/lib/snet:go_default_library", "//go/lib/snet/path:go_default_library", "//go/lib/util:go_default_library", + "@com_github_dchest_cmac//:go_default_library", ], ) diff --git a/go/lib/colibri/client/BUILD.bazel b/go/lib/colibri/client/BUILD.bazel index 2b84c4b785..a5c5b2afa4 100644 --- a/go/lib/colibri/client/BUILD.bazel +++ b/go/lib/colibri/client/BUILD.bazel @@ -22,13 +22,13 @@ go_test( srcs = ["reservation_test.go"], embed = [":go_default_library"], deps = [ + "//go/lib/addr:go_default_library", "//go/lib/colibri:go_default_library", "//go/lib/colibri/client/sorting:go_default_library", "//go/lib/colibri/coltest:go_default_library", "//go/lib/colibri/reservation:go_default_library", "//go/lib/daemon/mock_daemon:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/drkey/test:go_default_library", + "//go/lib/drkey/fake:go_default_library", "//go/lib/serrors:go_default_library", "//go/lib/snet:go_default_library", "//go/lib/snet/path:go_default_library", diff --git a/go/lib/colibri/client/fallingback/BUILD.bazel b/go/lib/colibri/client/fallingback/BUILD.bazel index 1379978df0..596481df71 100644 --- a/go/lib/colibri/client/fallingback/BUILD.bazel +++ b/go/lib/colibri/client/fallingback/BUILD.bazel @@ -22,8 +22,7 @@ go_test( "//go/lib/colibri/client:go_default_library", "//go/lib/colibri/coltest:go_default_library", "//go/lib/daemon/mock_daemon:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/drkey/test:go_default_library", + "//go/lib/drkey/fake:go_default_library", "//go/lib/xtest:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/go/lib/colibri/client/fallingback/functions_test.go b/go/lib/colibri/client/fallingback/functions_test.go index f3f9336d0a..5441f66828 100644 --- a/go/lib/colibri/client/fallingback/functions_test.go +++ b/go/lib/colibri/client/fallingback/functions_test.go @@ -28,8 +28,7 @@ import ( "github.com/scionproto/scion/go/lib/colibri/client" ct "github.com/scionproto/scion/go/lib/colibri/coltest" "github.com/scionproto/scion/go/lib/daemon/mock_daemon" - "github.com/scionproto/scion/go/lib/drkey" - dkt "github.com/scionproto/scion/go/lib/drkey/test" + fakedrkey "github.com/scionproto/scion/go/lib/drkey/fake" "github.com/scionproto/scion/go/lib/xtest" ) @@ -53,20 +52,12 @@ func TestCaptureTrips(t *testing.T) { defer ctrl.Finish() daemon := mock_daemon.NewMockConnector(ctrl) daemon.EXPECT().ColibriListRsvs(gomock.Any(), gomock.Any()).Return(stitchables, nil) - - mockKeys := dkt.MockKeys1SlowSideWithHost(t, "1-ff00:0:111", "10.1.1.1", - "1-ff00:0:111", - "1-ff00:0:110", - "1-ff00:0:112", - ) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - - k, ok := dkt.GetKey(mockKeys, meta.SrcIA, meta.DstIA) - require.True(t, ok, "not found %s", meta.SrcIA) - return k, nil - }) + fake := fakedrkey.Keyer{ + LocalIA: srcIA, + LocalIP: srcHost, + } + daemon.EXPECT().DRKeyGetASHostKey(gomock.Any(), gomock.Any()).AnyTimes(). + DoAndReturn(fake.DRKeyGetASHostKey) capturedTrips := make([]*colibri.FullTrip, 0) _, err := client.NewReservation(ctx, daemon, srcIA, srcHost, dstIA, dstHost, 11, 0, diff --git a/go/lib/colibri/client/reservation_test.go b/go/lib/colibri/client/reservation_test.go index c8943c981d..d64824a199 100644 --- a/go/lib/colibri/client/reservation_test.go +++ b/go/lib/colibri/client/reservation_test.go @@ -16,6 +16,7 @@ package client import ( "context" + "net" "sync" "testing" "time" @@ -24,13 +25,13 @@ import ( "github.com/stretchr/testify/require" // TODO(juagargi) unify test packages + "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/colibri" "github.com/scionproto/scion/go/lib/colibri/client/sorting" ct "github.com/scionproto/scion/go/lib/colibri/coltest" "github.com/scionproto/scion/go/lib/colibri/reservation" "github.com/scionproto/scion/go/lib/daemon/mock_daemon" - "github.com/scionproto/scion/go/lib/drkey" - dkt "github.com/scionproto/scion/go/lib/drkey/test" + fakedrkey "github.com/scionproto/scion/go/lib/drkey/fake" "github.com/scionproto/scion/go/lib/serrors" "github.com/scionproto/scion/go/lib/snet" snetpath "github.com/scionproto/scion/go/lib/snet/path" @@ -58,7 +59,7 @@ func TestNewReservation(t *testing.T) { ct.NewStitchableSegments("1-ff00:0:111", "1-ff00:0:112", ct.WithUpSegs(1), ), nil) - mockDRKeys(t, daemon, strSrcIA, strSrcHost) + mockDRKeys(t, daemon, srcIA, srcHost) rsv, err := NewReservation(ctx, daemon, srcIA, srcHost, dstIA, dstHost, 11, 0, sorting.ByExpiration) @@ -94,7 +95,7 @@ func TestReservationOpen(t *testing.T) { ct.NewStitchableSegments("1-ff00:0:111", "1-ff00:0:112", ct.WithUpSegs(1), ), nil) - mockDRKeys(t, daemon, strSrcIA, strSrcHost) + mockDRKeys(t, daemon, srcIA, srcHost) rsv, err := NewReservation(ctx, daemon, srcIA, srcHost, dstIA, dstHost, 11, 0, sorting.ByExpiration) @@ -172,7 +173,7 @@ func TestReservationOpenSuccessfully(t *testing.T) { ct.NewStitchableSegments("1-ff00:0:111", "1-ff00:0:112", ct.WithUpSegs(1), ), nil) - mockDRKeys(t, daemon, strSrcIA, strSrcHost) + mockDRKeys(t, daemon, srcIA, srcHost) rsv, err := NewReservation(ctx, daemon, srcIA, srcHost, dstIA, dstHost, 11, 0, sorting.ByExpiration) @@ -236,7 +237,7 @@ func TestReservationFailOnRenewal(t *testing.T) { daemon := mock_daemon.NewMockConnector(ctrl) daemon.EXPECT().ColibriListRsvs(gomock.Any(), gomock.Any()).Return( stitchables, nil) - mockDRKeys(t, daemon, strSrcIA, strSrcHost) + mockDRKeys(t, daemon, srcIA, srcHost) trips := colibri.CombineAll(stitchables) // unsorted; will use [0] : @@ -326,19 +327,13 @@ func TestReservationFailOnRenewal(t *testing.T) { require.Nil(t, rsv.runner) } -func mockDRKeys(t *testing.T, daemon *mock_daemon.MockConnector, srcIA, srcHost string) { +func mockDRKeys(t *testing.T, daemon *mock_daemon.MockConnector, localIA addr.IA, localIP net.IP) { t.Helper() - mockKeys := dkt.MockKeys1SlowSideWithHost(t, srcIA, srcHost, - "1-ff00:0:111", - "1-ff00:0:110", - "1-ff00:0:112", - ) - daemon.EXPECT().DRKeyGetLvl2Key(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes(). - DoAndReturn(func(_ context.Context, meta drkey.Lvl2Meta, ts time.Time) ( - drkey.Lvl2Key, error) { - k, ok := dkt.GetKey(mockKeys, meta.SrcIA, meta.DstIA) - require.True(t, ok, "not found %s", meta.SrcIA) - return k, nil - }) + fake := fakedrkey.Keyer{ + LocalIA: localIA, + LocalIP: localIP, + } + daemon.EXPECT().DRKeyGetASHostKey(gomock.Any(), gomock.Any()).AnyTimes(). + DoAndReturn(fake.DRKeyGetASHostKey) } diff --git a/go/lib/colibri/drkey.go b/go/lib/colibri/drkey.go index ece7bc0658..e210525784 100644 --- a/go/lib/colibri/drkey.go +++ b/go/lib/colibri/drkey.go @@ -18,26 +18,34 @@ package colibri import ( "context" + "crypto/aes" + "crypto/subtle" "encoding/binary" "net" "time" + "github.com/dchest/cmac" + base "github.com/scionproto/scion/go/co/reservation" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/colibri/reservation" "github.com/scionproto/scion/go/lib/common" "github.com/scionproto/scion/go/lib/drkey" - dkut "github.com/scionproto/scion/go/lib/drkey/drkeyutil" "github.com/scionproto/scion/go/lib/serrors" colpath "github.com/scionproto/scion/go/lib/slayers/path/colibri" snetpath "github.com/scionproto/scion/go/lib/snet/path" "github.com/scionproto/scion/go/lib/util" ) -func createAuthsForBaseRequest(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +// DRKeyGetter is the interface used to obtain AS-Host DRKeys. Usually this is just the daemon. +type DRKeyGetter interface { + DRKeyGetASHostKey(ctx context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) +} + +func createAuthsForBaseRequest(ctx context.Context, conn DRKeyGetter, req *BaseRequest) error { - keys, err := getKeys(ctx, conn, req.Path.Steps, req.SrcHost) + keys, err := getKeys(ctx, conn, req.Path.Steps, req.SrcHost, req.TimeStamp) if err != nil { return err } @@ -45,25 +53,25 @@ func createAuthsForBaseRequest(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, // MAC and set authenticators inside request payload := make([]byte, minSizeBaseReq(req)) serializeBaseRequest(payload, req) - req.Authenticators, err = dkut.ComputeAuthenticators(payload, keys) + req.Authenticators, err = computeAuthenticators(payload, keys) return err } -func createAuthsForE2EReservationSetup(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func createAuthsForE2EReservationSetup(ctx context.Context, conn DRKeyGetter, req *E2EReservationSetup) error { - keys, err := getKeys(ctx, conn, req.Path.Steps, req.SrcHost) + keys, err := getKeys(ctx, conn, req.Path.Steps, req.SrcHost, req.TimeStamp) if err != nil { return err } payload := make([]byte, minSizeE2ESetupReq(req)) serializeE2EReservationSetup(payload, req) - req.Authenticators, err = dkut.ComputeAuthenticators(payload, keys) + req.Authenticators, err = computeAuthenticators(payload, keys) return err } -func validateResponseAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func validateResponseAuthenticators(ctx context.Context, conn DRKeyGetter, res *E2EResponse, requestPath *base.TransparentPath, srcHost net.IP, reqTimestamp time.Time) error { @@ -77,10 +85,11 @@ func validateResponseAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2K if err != nil { return err } - return validateBasic(ctx, conn, payloads, res.Authenticators, requestPath, srcHost) + return validateBasic(ctx, conn, payloads, res.Authenticators, + requestPath, srcHost, reqTimestamp) } -func validateResponseErrorAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func validateResponseErrorAuthenticators(ctx context.Context, conn DRKeyGetter, res *E2EResponseError, requestPath *base.TransparentPath, srcHost net.IP, reqTimestamp time.Time) error { @@ -100,10 +109,11 @@ func validateResponseErrorAuthenticators(ctx context.Context, conn dkut.DRKeyGet res.Authenticators = res.Authenticators[:res.FailedAS+1] requestPath.Steps = requestPath.Steps[:res.FailedAS+1] payloads := serializeResponseError(res, reqTimestamp) - return validateBasic(ctx, conn, payloads, res.Authenticators, requestPath, srcHost) + return validateBasic(ctx, conn, payloads, res.Authenticators, + requestPath, srcHost, reqTimestamp) } -func validateSetupErrorAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func validateSetupErrorAuthenticators(ctx context.Context, conn DRKeyGetter, res *E2ESetupError, requestPath *base.TransparentPath, srcHost net.IP, reqTimestamp time.Time) error { @@ -123,28 +133,40 @@ func validateSetupErrorAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl res.Authenticators = res.Authenticators[:res.FailedAS+1] requestPath.Steps = requestPath.Steps[:res.FailedAS+1] payloads := serializeSetupError(res, reqTimestamp) - return validateBasic(ctx, conn, payloads, res.Authenticators, requestPath, srcHost) + return validateBasic(ctx, conn, payloads, res.Authenticators, + requestPath, srcHost, reqTimestamp) } -func getKeys(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, steps []base.PathStep, - srcHost net.IP) ([][]byte, error) { +func getKeys(ctx context.Context, conn DRKeyGetter, steps []base.PathStep, + srcHost net.IP, valTime time.Time) ([]drkey.Key, error) { if len(steps) < 2 { return nil, serrors.New("wrong path in request") } - return getKeysWithLocalIA(ctx, conn, steps[1:], steps[0].IA, srcHost) + return getKeysWithLocalIA(ctx, conn, steps[1:], steps[0].IA, srcHost, valTime) } -func getKeysWithLocalIA(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, steps []base.PathStep, - srcIA addr.IA, srcHost net.IP) ([][]byte, error) { +func getKeysWithLocalIA(ctx context.Context, conn DRKeyGetter, steps []base.PathStep, + localIA addr.IA, host net.IP, valtime time.Time) ([]drkey.Key, error) { - ias := make([]addr.IA, len(steps)) + keys := make([]drkey.Key, len(steps)) for i, step := range steps { - ias[i] = step.IA + key, err := conn.DRKeyGetASHostKey(ctx, + drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.COLIBRI, + Validity: valtime, + SrcIA: step.IA, + DstIA: localIA, + }, + DstHost: host.String(), + }) + if err != nil { + return nil, err + } + keys[i] = key.Key } - return dkut.GetLvl2Keys(ctx, conn, drkey.AS2Host, "colibri", - dkut.SlowIAs(srcIA), dkut.SlowHosts(addr.HostFromIP(srcHost)), - dkut.FastIAs(ias...)) + return keys, nil } func minSizeBaseReq(req *BaseRequest) int { @@ -264,15 +286,17 @@ func serializeSetupError(res *E2ESetupError, timestamp time.Time) [][]byte { return payloads } -func validateBasic(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, payloads [][]byte, - authenticators [][]byte, requestPath *base.TransparentPath, srcHost net.IP) error { +func validateBasic(ctx context.Context, conn DRKeyGetter, payloads [][]byte, + authenticators [][]byte, requestPath *base.TransparentPath, + srcHost net.IP, valTime time.Time) error { - keys, err := getKeysWithLocalIA(ctx, conn, requestPath.Steps, requestPath.SrcIA(), srcHost) + keys, err := getKeysWithLocalIA(ctx, conn, requestPath.Steps, + requestPath.SrcIA(), srcHost, valTime) if err != nil { return err } - ok, err := dkut.ValidateAuthenticators(payloads, keys, authenticators) + ok, err := validateAuthenticators(payloads, keys, authenticators) if err != nil { return err } @@ -299,3 +323,54 @@ func checkEqualLength(authenticators [][]byte, path *base.TransparentPath) error } return nil } + +// ComputeAuthenticators returns the authenticators obtained to apply a MAC function to the +// same payload. +func computeAuthenticators(payload []byte, keys []drkey.Key) ([][]byte, error) { + auths := make([][]byte, len(keys)) + for i, k := range keys { + var err error + auths[i], err = computeMAC(payload, k) + if err != nil { + return nil, err + } + } + return auths, nil +} + +// ValidateAuthenticators validates each authenticators[i] against MAC(payload[i], keys[i]). +// Returns error if the MAC function returns any error, or true/false if each of the authenticators +// matches the result of each MAC function invocation. +func validateAuthenticators(payloads [][]byte, keys []drkey.Key, authenticators [][]byte) ( + bool, error) { + + if len(payloads) != len(keys) || len(keys) != len(authenticators) { + return false, serrors.New("wrong lengths (must be the same)") + } + for i := range keys { + mac, err := computeMAC(payloads[i], keys[i]) + if err != nil { + return false, serrors.WrapStr("MAC function", err) + } + if subtle.ConstantTimeCompare(mac, authenticators[i]) != 1 { + return false, nil + } + } + return true, nil +} + +func computeMAC(payload []byte, key drkey.Key) ([]byte, error) { + block, err := aes.NewCipher(key[:]) + if err != nil { + return nil, serrors.WrapStr("initializing aes cipher", err) + } + mac, err := cmac.New(block) + if err != nil { + return nil, serrors.WrapStr("initializing cmac", err) + } + _, err = mac.Write(payload) + if err != nil { + return nil, serrors.WrapStr("preparing mac", err) + } + return mac.Sum(nil), nil +} diff --git a/go/lib/colibri/e2e.go b/go/lib/colibri/e2e.go index 6d29bf41c2..86bf7e6cf3 100644 --- a/go/lib/colibri/e2e.go +++ b/go/lib/colibri/e2e.go @@ -24,7 +24,6 @@ import ( base "github.com/scionproto/scion/go/co/reservation" "github.com/scionproto/scion/go/lib/colibri/reservation" - dkut "github.com/scionproto/scion/go/lib/drkey/drkeyutil" "github.com/scionproto/scion/go/lib/snet" ) @@ -39,7 +38,7 @@ type BaseRequest struct { Authenticators [][]byte // per spec., MACs for AS_i on the immutable data } -func (r *BaseRequest) CreateAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer) error { +func (r *BaseRequest) CreateAuthenticators(ctx context.Context, conn DRKeyGetter) error { return createAuthsForBaseRequest(ctx, conn, r) } @@ -52,13 +51,13 @@ type E2EReservationSetup struct { } func (r *E2EReservationSetup) CreateAuthenticators(ctx context.Context, - conn dkut.DRKeyGetLvl2Keyer) error { + conn DRKeyGetter) error { return createAuthsForE2EReservationSetup(ctx, conn, r) } // NewReservation creates a new E2EReservationSetup, including the authenticator fields. -func NewReservation(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func NewReservation(ctx context.Context, conn DRKeyGetter, fullTrip *FullTrip, srcHost, dstHost net.IP, requestedBW reservation.BWCls) (*E2EReservationSetup, error) { @@ -90,7 +89,7 @@ type E2EResponse struct { } // ValidateAuthenticators returns nil if the source validation for all hops succeeds. -func (r *E2EResponse) ValidateAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func (r *E2EResponse) ValidateAuthenticators(ctx context.Context, conn DRKeyGetter, requestPath *base.TransparentPath, srcHost net.IP, requestTimestamp time.Time) error { return validateResponseAuthenticators(ctx, conn, r, requestPath, srcHost, requestTimestamp) @@ -106,7 +105,7 @@ func (e *E2EResponseError) Error() string { return e.Message } -func (r *E2EResponseError) ValidateAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func (r *E2EResponseError) ValidateAuthenticators(ctx context.Context, conn DRKeyGetter, requestPath *base.TransparentPath, srcHost net.IP, requestTimestamp time.Time) error { return validateResponseErrorAuthenticators(ctx, conn, r, requestPath, srcHost, requestTimestamp) @@ -117,7 +116,7 @@ type E2ESetupError struct { AllocationTrail []reservation.BWCls } -func (r *E2ESetupError) ValidateAuthenticators(ctx context.Context, conn dkut.DRKeyGetLvl2Keyer, +func (r *E2ESetupError) ValidateAuthenticators(ctx context.Context, conn DRKeyGetter, requestPath *base.TransparentPath, srcHost net.IP, requestTimestamp time.Time) error { return validateSetupErrorAuthenticators(ctx, conn, r, requestPath, srcHost, requestTimestamp) diff --git a/go/lib/ctrl/drkey/BUILD.bazel b/go/lib/ctrl/drkey/BUILD.bazel index 48fd8090f8..f0e77db608 100644 --- a/go/lib/ctrl/drkey/BUILD.bazel +++ b/go/lib/ctrl/drkey/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "lvl1_req.go", "lvl2_req.go", + "sv_req.go", ], importpath = "github.com/scionproto/scion/go/lib/ctrl/drkey", visibility = ["//visibility:public"], @@ -14,25 +15,21 @@ go_library( "//go/lib/scrypto/cppki:go_default_library", "//go/lib/serrors:go_default_library", "//go/pkg/proto/drkey:go_default_library", - "@com_github_golang_protobuf//ptypes:go_default_library_gen", + "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) go_test( name = "go_default_test", - srcs = [ - "lvl2_req_test.go", - "protobuf_test.go", - ], - embed = [":go_default_library"], + srcs = ["protobuf_test.go"], deps = [ - "//go/lib/addr:go_default_library", + ":go_default_library", "//go/lib/drkey:go_default_library", "//go/lib/util:go_default_library", "//go/lib/xtest:go_default_library", "//go/pkg/proto/drkey:go_default_library", - "@com_github_golang_protobuf//ptypes:go_default_library_gen", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", + "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) diff --git a/go/lib/ctrl/drkey/lvl1_req.go b/go/lib/ctrl/drkey/lvl1_req.go index fb627774c3..bcf2036300 100644 --- a/go/lib/ctrl/drkey/lvl1_req.go +++ b/go/lib/ctrl/drkey/lvl1_req.go @@ -15,110 +15,107 @@ package drkey import ( - "time" + "google.golang.org/protobuf/types/known/timestamppb" - "github.com/golang/protobuf/ptypes" - - "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/lib/scrypto/cppki" "github.com/scionproto/scion/go/lib/serrors" dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" ) -// Lvl1Req represents a level 1 request between CS. -type Lvl1Req struct { - ValTime time.Time - Timestamp time.Time -} - -// NewLvl1Req returns a fresh Lvl1Req -func NewLvl1Req(valTime time.Time) Lvl1Req { - return Lvl1Req{ - ValTime: valTime, - Timestamp: time.Now(), - } -} - -// Lvl1reqToProtoRequest parses the Lvl1Req to a protobuf Lvl1Request. -func Lvl1reqToProtoRequest(req Lvl1Req) (*dkpb.DRKeyLvl1Request, error) { - valTime, err := ptypes.TimestampProto(req.ValTime) - if err != nil { - return nil, serrors.WrapStr("invalid valTime from request", err) - } - timestamp, err := ptypes.TimestampProto(req.Timestamp) - if err != nil { - return nil, serrors.WrapStr("invalid timeStamp from request", err) - } - return &dkpb.DRKeyLvl1Request{ - ValTime: valTime, - Timestamp: timestamp, +func Lvl1MetaToProtoRequest(meta drkey.Lvl1Meta) (*dkpb.Lvl1Request, error) { + return &dkpb.Lvl1Request{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: dkpb.Protocol(meta.ProtoId), }, nil } // GetLvl1KeyFromReply extracts the level 1 drkey from the reply. -func GetLvl1KeyFromReply(srcIA, dstIA addr.IA, rep *dkpb.DRKeyLvl1Response) (drkey.Lvl1Key, error) { +func GetLvl1KeyFromReply(meta drkey.Lvl1Meta, + rep *dkpb.Lvl1Response) (drkey.Lvl1Key, error) { - epochBegin, err := ptypes.Timestamp(rep.EpochBegin) + err := rep.EpochBegin.CheckValid() if err != nil { return drkey.Lvl1Key{}, serrors.WrapStr("invalid EpochBegin from response", err) } - epochEnd, err := ptypes.Timestamp(rep.EpochEnd) + err = rep.EpochEnd.CheckValid() if err != nil { return drkey.Lvl1Key{}, serrors.WrapStr("invalid EpochEnd from response", err) } epoch := drkey.Epoch{ Validity: cppki.Validity{ - NotBefore: epochBegin, - NotAfter: epochEnd, + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), }, } - return drkey.Lvl1Key{ - Lvl1Meta: drkey.Lvl1Meta{ - SrcIA: srcIA, - DstIA: dstIA, - Epoch: epoch, - }, - Key: drkey.DRKey(rep.Drkey), + returningKey := drkey.Lvl1Key{ + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + ProtoId: meta.ProtoId, + } + if len(rep.Key) != 16 { + return drkey.Lvl1Key{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil +} + +// KeyToLvl1Resp builds a Lvl1Resp provided a Lvl1Key. +func KeyToLvl1Resp(drkey drkey.Lvl1Key) (*dkpb.Lvl1Response, error) { + return &dkpb.Lvl1Response{ + EpochBegin: timestamppb.New(drkey.Epoch.NotBefore), + EpochEnd: timestamppb.New(drkey.Epoch.NotAfter), + Key: drkey.Key[:], }, nil } -// KeyToLvl1Resp builds a Lvl1Resp provided a given Lvl1Key. -func KeyToLvl1Resp(drkey drkey.Lvl1Key) (*dkpb.DRKeyLvl1Response, error) { - epochBegin, err := ptypes.TimestampProto(drkey.Epoch.NotBefore) - if err != nil { - return nil, serrors.WrapStr("invalid EpochBegin from key", err) - } - epochEnd, err := ptypes.TimestampProto(drkey.Epoch.NotAfter) - if err != nil { - return nil, serrors.WrapStr("invalid EpochEnd from key", err) - } - now, err := ptypes.TimestampProto(time.Now()) - if err != nil { - return nil, serrors.WrapStr("invalid conversion to timestamp", err) - } +func IntraLvl1ToProtoRequest(meta drkey.Lvl1Meta) (*dkpb.IntraLvl1Request, error) { + return &dkpb.IntraLvl1Request{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: dkpb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + }, nil +} - return &dkpb.DRKeyLvl1Response{ - EpochBegin: epochBegin, - EpochEnd: epochEnd, - Drkey: []byte(drkey.Key), - Timestamp: now, +// KeyToASASResp builds a ASASResp provided a Lvl1Key. +func KeyToASASResp(drkey drkey.Lvl1Key) (*dkpb.IntraLvl1Response, error) { + return &dkpb.IntraLvl1Response{ + EpochBegin: timestamppb.New(drkey.Epoch.NotBefore), + EpochEnd: timestamppb.New(drkey.Epoch.NotAfter), + Key: drkey.Key[:], }, nil } -// RequestToLvl1Req parses the protobuf Lvl1Request to a Lvl1Req. -func RequestToLvl1Req(req *dkpb.DRKeyLvl1Request) (Lvl1Req, error) { - valTime, err := ptypes.Timestamp(req.ValTime) +func GetASASKeyFromReply(meta drkey.Lvl1Meta, + rep *dkpb.IntraLvl1Response) (drkey.Lvl1Key, error) { + + err := rep.EpochBegin.CheckValid() if err != nil { - return Lvl1Req{}, serrors.WrapStr("invalid valTime from pb req", err) + return drkey.Lvl1Key{}, serrors.WrapStr("invalid EpochBegin from response", err) } - timestamp, err := ptypes.Timestamp(req.Timestamp) + err = rep.EpochEnd.CheckValid() if err != nil { - return Lvl1Req{}, serrors.WrapStr("invalid timeStamp from pb req", err) + return drkey.Lvl1Key{}, serrors.WrapStr("invalid EpochEnd from response", err) } - - return Lvl1Req{ - ValTime: valTime, - Timestamp: timestamp, - }, nil + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, + } + returningKey := drkey.Lvl1Key{ + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + ProtoId: meta.ProtoId, + } + if len(rep.Key) != 16 { + return drkey.Lvl1Key{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil } diff --git a/go/lib/ctrl/drkey/lvl2_req.go b/go/lib/ctrl/drkey/lvl2_req.go index 2b3a38569d..f1ac646379 100644 --- a/go/lib/ctrl/drkey/lvl2_req.go +++ b/go/lib/ctrl/drkey/lvl2_req.go @@ -15,9 +15,7 @@ package drkey import ( - "time" - - "github.com/golang/protobuf/ptypes" + "google.golang.org/protobuf/types/known/timestamppb" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/drkey" @@ -26,167 +24,207 @@ import ( dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" ) -// Host represents a host part of a level 2 drkey. -type Host struct { - Type addr.HostAddrType // uint8 - Host []byte +func ASHostMetaToProtoRequest(meta drkey.ASHostMeta) (*dkpb.ASHostRequest, error) { + return &dkpb.ASHostRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: dkpb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + DstHost: meta.DstHost, + }, nil } -// NewHost returns a new Host from an addr.HostAddr. -func NewHost(host addr.HostAddr) Host { - if host == nil { - host = addr.HostNone{} - } - return Host{ - Type: host.Type(), - Host: host.Pack(), +func RequestToASHostMeta(req *dkpb.ASHostRequest) (drkey.ASHostMeta, error) { + err := req.ValTime.CheckValid() + if err != nil { + return drkey.ASHostMeta{}, serrors.WrapStr("invalid valTime from pb request", err) } + return drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(req.ProtocolId), + Validity: req.ValTime.AsTime(), + SrcIA: addr.IA(req.SrcIa), + DstIA: addr.IA(req.DstIa), + }, + DstHost: req.DstHost, + }, nil } -// ToHostAddr returns the host as a addr.HostAddr. -func (h *Host) ToHostAddr() addr.HostAddr { - host, err := addr.HostFromRaw(h.Host, h.Type) +func KeyToASHostResp(drkey drkey.ASHostKey) (*dkpb.ASHostResponse, error) { + return &dkpb.ASHostResponse{ + EpochBegin: timestamppb.New(drkey.Epoch.NotBefore), + EpochEnd: timestamppb.New(drkey.Epoch.NotAfter), + Key: drkey.Key[:], + }, nil +} + +func GetASHostKeyFromReply(rep *dkpb.ASHostResponse, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + + err := rep.EpochBegin.CheckValid() if err != nil { - panic("Could not convert addr.HostAddr to drkey.Host") + return drkey.ASHostKey{}, serrors.WrapStr("invalid EpochBegin from response", err) + } + err = rep.EpochEnd.CheckValid() + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("invalid EpochEnd from response", err) + } + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, } - return host -} -// Lvl2Req represents a level 2 key request from an endhost to a CS. -type Lvl2Req struct { - Protocol string - ReqType uint32 - ValTime time.Time - SrcIA addr.IA - DstIA addr.IA - SrcHost Host - DstHost Host - Misc []byte -} + returningKey := drkey.ASHostKey{ + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + DstHost: meta.DstHost, + } -// NewLvl2ReqFromMeta constructs a level 2 request from a standard level 2 meta info. -func NewLvl2ReqFromMeta(meta drkey.Lvl2Meta, valTime time.Time) Lvl2Req { - return Lvl2Req{ - ReqType: uint32(meta.KeyType), - Protocol: meta.Protocol, - ValTime: valTime, - SrcIA: meta.SrcIA, - DstIA: meta.DstIA, - SrcHost: NewHost(meta.SrcHost), - DstHost: NewHost(meta.DstHost), + if len(rep.Key) != 16 { + return drkey.ASHostKey{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil } -// ToMeta returns metadata of the requested Lvl2 DRKey. -func (c Lvl2Req) ToMeta() drkey.Lvl2Meta { - return drkey.Lvl2Meta{ - KeyType: drkey.Lvl2KeyType(c.ReqType), - Protocol: c.Protocol, - SrcIA: c.SrcIA, - DstIA: c.DstIA, - SrcHost: c.SrcHost.ToHostAddr(), - DstHost: c.DstHost.ToHostAddr(), - } +func HostASMetaToProtoRequest(meta drkey.HostASMeta) (*dkpb.HostASRequest, error) { + return &dkpb.HostASRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: dkpb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + SrcHost: meta.SrcHost, + }, nil } -// RequestToLvl2Req parses the protobuf Lvl2Request to a Lvl2Req. -func RequestToLvl2Req(req *dkpb.DRKeyLvl2Request) (Lvl2Req, error) { - valTime, err := ptypes.Timestamp(req.ValTime) +func RequestToHostASMeta(req *dkpb.HostASRequest) (drkey.HostASMeta, error) { + err := req.ValTime.CheckValid() if err != nil { - return Lvl2Req{}, serrors.WrapStr("invalid valTime from pb request", err) - } - - return Lvl2Req{ - Protocol: req.Protocol, - ReqType: req.ReqType, - ValTime: valTime, - SrcIA: addr.IA(req.SrcIa), - DstIA: addr.IA(req.DstIa), - SrcHost: Host{ - Type: addr.HostAddrType(req.SrcHost.Type), - Host: req.SrcHost.Host, - }, - DstHost: Host{ - Type: addr.HostAddrType(req.DstHost.Type), - Host: req.DstHost.Host, + return drkey.HostASMeta{}, serrors.WrapStr("invalid valTime from pb request", err) + } + return drkey.HostASMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(req.ProtocolId), + Validity: req.ValTime.AsTime(), + SrcIA: addr.IA(req.SrcIa), + DstIA: addr.IA(req.DstIa), }, - Misc: req.Misc, + SrcHost: req.SrcHost, }, nil } -// KeyToLvl2Resp builds a Lvl2Resp provided a given Lvl2Key. -func KeyToLvl2Resp(drkey drkey.Lvl2Key) (*dkpb.DRKeyLvl2Response, error) { - epochBegin, err := ptypes.TimestampProto(drkey.Epoch.NotBefore) +func KeyToHostASResp(drkey drkey.HostASKey) (*dkpb.HostASResponse, error) { + return &dkpb.HostASResponse{ + EpochBegin: timestamppb.New(drkey.Epoch.NotBefore), + EpochEnd: timestamppb.New(drkey.Epoch.NotAfter), + Key: drkey.Key[:], + }, nil +} + +func GetHostASKeyFromReply(rep *dkpb.HostASResponse, + meta drkey.HostASMeta) (drkey.HostASKey, error) { + + err := rep.EpochBegin.CheckValid() if err != nil { - return nil, serrors.WrapStr("invalid EpochBegin from key", err) + return drkey.HostASKey{}, serrors.WrapStr("invalid EpochBegin from response", err) } - epochEnd, err := ptypes.TimestampProto(drkey.Epoch.NotAfter) + err = rep.EpochEnd.CheckValid() if err != nil { - return nil, serrors.WrapStr("invalid EpochEnd from key", err) + return drkey.HostASKey{}, serrors.WrapStr("invalid EpochEnd from response", err) } - now, err := ptypes.TimestampProto(time.Now()) - if err != nil { - return nil, serrors.WrapStr("invalid conversion to timestamp", err) + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, + } + + returningKey := drkey.HostASKey{ + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + SrcHost: meta.SrcHost, + } + if len(rep.Key) != 16 { + return drkey.HostASKey{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil +} - return &dkpb.DRKeyLvl2Response{ - EpochBegin: epochBegin, - EpochEnd: epochEnd, - Drkey: []byte(drkey.Key), - Timestamp: now, +func HostHostMetaToProtoRequest(meta drkey.HostHostMeta) (*dkpb.HostHostRequest, error) { + return &dkpb.HostHostRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: dkpb.Protocol(meta.ProtoId), + DstIa: uint64(meta.DstIA), + SrcIa: uint64(meta.SrcIA), + DstHost: meta.DstHost, + SrcHost: meta.SrcHost, }, nil } -// Lvl2reqToProtoRequest parses the Lvl2Req to a protobuf Lvl2Request. -func Lvl2reqToProtoRequest(req Lvl2Req) (*dkpb.DRKeyLvl2Request, error) { - valTime, err := ptypes.TimestampProto(req.ValTime) +func RequestToHostHostMeta(req *dkpb.HostHostRequest) (drkey.HostHostMeta, error) { + err := req.ValTime.CheckValid() if err != nil { - return nil, serrors.WrapStr("invalid valTime from request", err) - } - return &dkpb.DRKeyLvl2Request{ - Protocol: req.Protocol, - ReqType: req.ReqType, - DstIa: uint64(req.DstIA), - SrcIa: uint64(req.SrcIA), - ValTime: valTime, - SrcHost: &dkpb.DRKeyLvl2Request_DRKeyHost{ - Type: uint32(req.SrcHost.Type), - Host: req.SrcHost.Host, - }, - DstHost: &dkpb.DRKeyLvl2Request_DRKeyHost{ - Type: uint32(req.DstHost.Type), - Host: req.DstHost.Host, + return drkey.HostHostMeta{}, serrors.WrapStr("invalid valTime from pb request", err) + } + return drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(req.ProtocolId), + Validity: req.ValTime.AsTime(), + SrcIA: addr.IA(req.SrcIa), + DstIA: addr.IA(req.DstIa), }, + SrcHost: req.SrcHost, + DstHost: req.DstHost, + }, nil +} + +func KeyToHostHostResp(drkey drkey.HostHostKey) (*dkpb.HostHostResponse, error) { + return &dkpb.HostHostResponse{ + EpochBegin: timestamppb.New(drkey.Epoch.NotBefore), + EpochEnd: timestamppb.New(drkey.Epoch.NotAfter), + Key: drkey.Key[:], }, nil } -// GetLvl2KeyFromReply extracts the level 2 drkey from the reply. -func GetLvl2KeyFromReply(rep *dkpb.DRKeyLvl2Response, meta drkey.Lvl2Meta) (drkey.Lvl2Key, error) { +func GetHostHostKeyFromReply(rep *dkpb.HostHostResponse, + meta drkey.HostHostMeta) (drkey.HostHostKey, error) { - epochBegin, err := ptypes.Timestamp(rep.EpochBegin) + err := rep.EpochBegin.CheckValid() if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("invalid EpochBegin from response", err) + return drkey.HostHostKey{}, serrors.WrapStr("invalid EpochBegin from response", err) } - epochEnd, err := ptypes.Timestamp(rep.EpochEnd) + err = rep.EpochEnd.CheckValid() if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("invalid EpochEnd from response", err) + return drkey.HostHostKey{}, serrors.WrapStr("invalid EpochEnd from response", err) } epoch := drkey.Epoch{ Validity: cppki.Validity{ - NotBefore: epochBegin, - NotAfter: epochEnd, + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), }, } - return drkey.Lvl2Key{ - Lvl2Meta: drkey.Lvl2Meta{ - KeyType: meta.KeyType, - Protocol: meta.Protocol, - SrcIA: meta.SrcIA, - DstIA: meta.DstIA, - SrcHost: meta.SrcHost, - DstHost: meta.DstHost, - Epoch: epoch, - }, - Key: drkey.DRKey(rep.Drkey), - }, nil + + returningKey := drkey.HostHostKey{ + ProtoId: meta.ProtoId, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Epoch: epoch, + SrcHost: meta.SrcHost, + DstHost: meta.DstHost, + } + if len(rep.Key) != 16 { + return drkey.HostHostKey{}, serrors.New("key size in reply is not 16 bytes", + "len", len(rep.Key)) + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil } diff --git a/go/lib/ctrl/drkey/lvl2_req_test.go b/go/lib/ctrl/drkey/lvl2_req_test.go deleted file mode 100644 index a85ad0b185..0000000000 --- a/go/lib/ctrl/drkey/lvl2_req_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2021 ETH Zurich -// -// 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 drkey - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/util" - "github.com/scionproto/scion/go/lib/xtest" -) - -func TestToMeta(t *testing.T) { - expTime := util.SecsToTime(1) - cases := map[string]struct { - req Lvl2Req - meta drkey.Lvl2Meta - }{ - "as2as": { - req: Lvl2Req{ - ReqType: uint32(drkey.AS2AS), - Protocol: "prot", - ValTime: expTime, - SrcIA: xtest.MustParseIA("1-ff00:0:111"), - DstIA: xtest.MustParseIA("1-ff00:0:112"), - }, - meta: drkey.Lvl2Meta{ - KeyType: drkey.AS2AS, - Protocol: "prot", - SrcIA: xtest.MustParseIA("1-ff00:0:111"), - DstIA: xtest.MustParseIA("1-ff00:0:112"), - SrcHost: addr.HostNone{}, - DstHost: addr.HostNone{}, - }, - }, - "as2host": { - req: Lvl2Req{ - ReqType: uint32(drkey.AS2Host), - Protocol: "prot", - ValTime: expTime, - SrcIA: xtest.MustParseIA("1-ff00:0:111"), - DstIA: xtest.MustParseIA("1-ff00:0:112"), - DstHost: NewHost(addr.HostFromIPStr("10.1.1.2")), - }, - meta: drkey.Lvl2Meta{ - KeyType: drkey.AS2Host, - Protocol: "prot", - SrcIA: xtest.MustParseIA("1-ff00:0:111"), - DstIA: xtest.MustParseIA("1-ff00:0:112"), - SrcHost: addr.HostNone{}, - DstHost: addr.HostFromIPStr("10.1.1.2"), - }, - }, - "host2host": { - req: Lvl2Req{ - ReqType: uint32(drkey.Host2Host), - Protocol: "prot", - ValTime: expTime, - SrcIA: xtest.MustParseIA("1-ff00:0:111"), - DstIA: xtest.MustParseIA("1-ff00:0:112"), - SrcHost: NewHost(addr.HostFromIPStr("10.1.1.1")), - DstHost: NewHost(addr.HostFromIPStr("10.1.1.2")), - }, - meta: drkey.Lvl2Meta{ - KeyType: drkey.Host2Host, - Protocol: "prot", - SrcIA: xtest.MustParseIA("1-ff00:0:111"), - DstIA: xtest.MustParseIA("1-ff00:0:112"), - SrcHost: addr.HostFromIPStr("10.1.1.1"), - DstHost: addr.HostFromIPStr("10.1.1.2"), - }, - }, - } - for name, tc := range cases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - require.Equal(t, tc.meta, tc.req.ToMeta()) - }) - } -} diff --git a/go/lib/ctrl/drkey/protobuf_test.go b/go/lib/ctrl/drkey/protobuf_test.go index 3963e1f699..63c1d243d8 100644 --- a/go/lib/ctrl/drkey/protobuf_test.go +++ b/go/lib/ctrl/drkey/protobuf_test.go @@ -18,11 +18,10 @@ import ( "testing" "time" - "github.com/golang/protobuf/ptypes" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/timestamppb" - "github.com/scionproto/scion/go/lib/addr" ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/lib/util" @@ -30,188 +29,301 @@ import ( dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" ) -func TestLvl1reqToProtoRequest(t *testing.T) { +func TestLvl1MetaToProtoRequest(t *testing.T) { now := time.Now().UTC() - valTime, err := ptypes.TimestampProto(now) - require.NoError(t, err) - timestamp, err := ptypes.TimestampProto(now) - require.NoError(t, err) + valTime := timestamppb.New(now) - pbReq := &dkpb.DRKeyLvl1Request{ - ValTime: valTime, - Timestamp: timestamp, + pbReq := &dkpb.Lvl1Request{ + ValTime: valTime, } - lvl1Req := ctrl.Lvl1Req{ - ValTime: now, - Timestamp: now, + lvl1Meta := drkey.Lvl1Meta{ + Validity: now, } - req, err := ctrl.Lvl1reqToProtoRequest(lvl1Req) + req, err := ctrl.Lvl1MetaToProtoRequest(lvl1Meta) require.NoError(t, err) assert.Equal(t, pbReq, req) } -func TestRequestToLvl1Req(t *testing.T) { - now := time.Now().UTC() - - valTime, err := ptypes.TimestampProto(now) - require.NoError(t, err) - timestamp, err := ptypes.TimestampProto(now) - require.NoError(t, err) - - req := &dkpb.DRKeyLvl1Request{ - ValTime: valTime, - Timestamp: timestamp, - } - - lvl1Req, err := ctrl.RequestToLvl1Req(req) - require.NoError(t, err) - assert.Equal(t, now, lvl1Req.ValTime) - assert.Equal(t, now, lvl1Req.Timestamp) -} - func TestKeyToLvl1Resp(t *testing.T) { - epochBegin, err := ptypes.TimestampProto(util.SecsToTime(0)) - require.NoError(t, err) - epochEnd, err := ptypes.TimestampProto(util.SecsToTime(1)) - require.NoError(t, err) dstIA := xtest.MustParseIA("1-ff00:0:110") srcIA := xtest.MustParseIA("1-ff00:0:111") k := xtest.MustParseHexString("c584cad32613547c64823c756651b6f5") // just a level 1 key lvl1Key := drkey.Lvl1Key{ - Lvl1Meta: drkey.Lvl1Meta{ - Epoch: drkey.NewEpoch(0, 1), - SrcIA: srcIA, - DstIA: dstIA, - }, - Key: k, + Epoch: drkey.NewEpoch(0, 1), + SrcIA: srcIA, + DstIA: dstIA, } + copy(lvl1Key.Key[:], k) - targetResp := &dkpb.DRKeyLvl1Response{ - EpochBegin: epochBegin, - EpochEnd: epochEnd, - Drkey: k, + targetResp := &dkpb.Lvl1Response{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: []byte(k), } pbResp, err := ctrl.KeyToLvl1Resp(lvl1Key) - targetResp.Timestamp = pbResp.Timestamp require.NoError(t, err) assert.Equal(t, targetResp, pbResp) } func TestGetLvl1KeyFromReply(t *testing.T) { - epochBegin, err := ptypes.TimestampProto(util.SecsToTime(0)) - require.NoError(t, err) - epochEnd, err := ptypes.TimestampProto(util.SecsToTime(1)) - require.NoError(t, err) dstIA := xtest.MustParseIA("1-ff00:0:110") srcIA := xtest.MustParseIA("1-ff00:0:111") k := xtest.MustParseHexString("c584cad32613547c64823c756651b6f5") // just a level 1 key - resp := &dkpb.DRKeyLvl1Response{ - EpochBegin: epochBegin, - EpochEnd: epochEnd, - Drkey: k, + resp := &dkpb.Lvl1Response{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: []byte(k), + } + lvl1meta := drkey.Lvl1Meta{ + ProtoId: drkey.SCMP, + SrcIA: srcIA, + DstIA: dstIA, } targetLvl1Key := drkey.Lvl1Key{ - Lvl1Meta: drkey.Lvl1Meta{ - Epoch: drkey.NewEpoch(0, 1), - SrcIA: srcIA, - DstIA: dstIA, - }, - Key: k, + ProtoId: drkey.SCMP, + Epoch: drkey.NewEpoch(0, 1), + SrcIA: srcIA, + DstIA: dstIA, } + copy(targetLvl1Key.Key[:], k) - lvl1Key, err := ctrl.GetLvl1KeyFromReply(srcIA, dstIA, resp) + lvl1Key, err := ctrl.GetLvl1KeyFromReply(lvl1meta, resp) require.NoError(t, err) assert.Equal(t, targetLvl1Key, lvl1Key) } -func TestRequestToLvl2Req(t *testing.T) { +func TestRequestToASHostMeta(t *testing.T) { now := time.Now().UTC() - valTime, err := ptypes.TimestampProto(now) - require.NoError(t, err) + valTime := timestamppb.New(now) dstIA := xtest.MustParseIA("1-ff00:0:110") srcIA := xtest.MustParseIA("1-ff00:0:111") - reqType := drkey.Host2Host - hostType := addr.HostTypeSVC - hostAddr := addr.SvcCS - - req := &dkpb.DRKeyLvl2Request{ - Protocol: "piskes", - ReqType: uint32(reqType), - DstIa: uint64(dstIA), - SrcIa: uint64(srcIA), - ValTime: valTime, - SrcHost: &dkpb.DRKeyLvl2Request_DRKeyHost{ - Type: uint32(hostType), - Host: hostAddr.Pack(), - }, - DstHost: &dkpb.DRKeyLvl2Request_DRKeyHost{ - Type: uint32(hostType), - Host: hostAddr.Pack(), - }, + strAddr := "127.0.0.1" + + req := &dkpb.ASHostRequest{ + ProtocolId: dkpb.Protocol_PROTOCOL_GENERIC_UNSPECIFIED, + DstIa: uint64(dstIA), + SrcIa: uint64(srcIA), + ValTime: valTime, + DstHost: strAddr, } - targetLvl2Req := ctrl.Lvl2Req{ - Protocol: "piskes", - ReqType: uint32(reqType), - ValTime: now, - SrcIA: srcIA, - DstIA: dstIA, - SrcHost: ctrl.Host{ - Type: hostType, - Host: hostAddr.Pack(), + targetLvl2Req := drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Generic, + Validity: now, + SrcIA: srcIA, + DstIA: dstIA, }, - DstHost: ctrl.Host{ - Type: hostType, - Host: hostAddr.Pack(), + DstHost: strAddr, + } + + lvl2Req, err := ctrl.RequestToASHostMeta(req) + require.NoError(t, err) + assert.Equal(t, targetLvl2Req, lvl2Req) +} + +func TestRequestToHostASMeta(t *testing.T) { + now := time.Now().UTC() + valTime := timestamppb.New(now) + dstIA := xtest.MustParseIA("1-ff00:0:110") + srcIA := xtest.MustParseIA("1-ff00:0:111") + strAddr := "127.0.0.1" + + req := &dkpb.HostASRequest{ + ProtocolId: dkpb.Protocol_PROTOCOL_GENERIC_UNSPECIFIED, + DstIa: uint64(dstIA), + SrcIa: uint64(srcIA), + ValTime: valTime, + SrcHost: strAddr, + } + + targetLvl2Req := drkey.HostASMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Generic, + Validity: now, + SrcIA: srcIA, + DstIA: dstIA, }, + SrcHost: strAddr, } - lvl2Req, err := ctrl.RequestToLvl2Req(req) + lvl2Req, err := ctrl.RequestToHostASMeta(req) require.NoError(t, err) assert.Equal(t, targetLvl2Req, lvl2Req) +} + +func TestRequestToHostHostMeta(t *testing.T) { + now := time.Now().UTC() + valTime := timestamppb.New(now) + dstIA := xtest.MustParseIA("1-ff00:0:110") + srcIA := xtest.MustParseIA("1-ff00:0:111") + strAddr := "127.0.0.1" + + req := &dkpb.HostHostRequest{ + ProtocolId: dkpb.Protocol_PROTOCOL_GENERIC_UNSPECIFIED, + DstIa: uint64(dstIA), + SrcIa: uint64(srcIA), + ValTime: valTime, + SrcHost: strAddr, + DstHost: strAddr, + } + targetLvl2Req := drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Generic, + Validity: now, + SrcIA: srcIA, + DstIA: dstIA, + }, + SrcHost: strAddr, + DstHost: strAddr, + } + + lvl2Req, err := ctrl.RequestToHostHostMeta(req) + require.NoError(t, err) + assert.Equal(t, targetLvl2Req, lvl2Req) } -func TestKeyToLvl2Resp(t *testing.T) { +func TestKeyToASHostResp(t *testing.T) { srcIA := xtest.MustParseIA("1-ff00:0:1") dstIA := xtest.MustParseIA("1-ff00:0:2") key := xtest.MustParseHexString("47bfbb7d94706dc9e79825e5a837b006") - meta := drkey.Lvl2Meta{ - KeyType: drkey.AS2AS, - Protocol: "scmp", - Epoch: drkey.NewEpoch(0, 1), - SrcIA: srcIA, - DstIA: dstIA, - SrcHost: addr.HostNone{}, - DstHost: addr.HostNone{}, + strAddr := "127.0.0.1" + + asHostKey := drkey.ASHostKey{ + ProtoId: drkey.SCMP, + Epoch: drkey.NewEpoch(0, 1), + SrcIA: srcIA, + DstIA: dstIA, + DstHost: strAddr, } - lvl2Key := drkey.Lvl2Key{ - Lvl2Meta: meta, - Key: key, + copy(asHostKey.Key[:], key) + + targetResp := &dkpb.ASHostResponse{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: asHostKey.Key[:], } - epochBegin, err := ptypes.TimestampProto(lvl2Key.Epoch.NotBefore) + resp, err := ctrl.KeyToASHostResp(asHostKey) require.NoError(t, err) - epochEnd, err := ptypes.TimestampProto(lvl2Key.Epoch.NotAfter) + assert.Equal(t, targetResp, resp) +} + +func TestKeyToHostASResp(t *testing.T) { + srcIA := xtest.MustParseIA("1-ff00:0:1") + dstIA := xtest.MustParseIA("1-ff00:0:2") + rawKey := xtest.MustParseHexString("47bfbb7d94706dc9e79825e5a837b006") + strAddr := "127.0.0.1" + + key := drkey.HostASKey{ + ProtoId: drkey.SCMP, + Epoch: drkey.NewEpoch(0, 1), + SrcIA: srcIA, + DstIA: dstIA, + SrcHost: strAddr, + } + copy(key.Key[:], rawKey) + + targetResp := &dkpb.HostASResponse{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: key.Key[:], + } + + resp, err := ctrl.KeyToHostASResp(key) require.NoError(t, err) + assert.Equal(t, targetResp, resp) +} - targetResp := &dkpb.DRKeyLvl2Response{ - EpochBegin: epochBegin, - EpochEnd: epochEnd, - Drkey: []byte(lvl2Key.Key), +func TestKeyToHostHostResp(t *testing.T) { + srcIA := xtest.MustParseIA("1-ff00:0:1") + dstIA := xtest.MustParseIA("1-ff00:0:2") + rawKey := xtest.MustParseHexString("47bfbb7d94706dc9e79825e5a837b006") + strAddr := "127.0.0.1" + + key := drkey.HostHostKey{ + ProtoId: drkey.SCMP, + Epoch: drkey.NewEpoch(0, 1), + SrcIA: srcIA, + DstIA: dstIA, + SrcHost: strAddr, + DstHost: strAddr, } + copy(key.Key[:], rawKey) - resp, err := ctrl.KeyToLvl2Resp(lvl2Key) + targetResp := &dkpb.HostHostResponse{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: key.Key[:], + } + + resp, err := ctrl.KeyToHostHostResp(key) require.NoError(t, err) - targetResp.Timestamp = resp.Timestamp assert.Equal(t, targetResp, resp) } + +func SVMetaToProtoRequest(t *testing.T) { + now := time.Now().UTC() + svReq := drkey.SVMeta{ + ProtoId: drkey.Generic, + Validity: now, + } + valTime := timestamppb.New(now) + targetProtoReq := &dkpb.SVRequest{ + ProtocolId: dkpb.Protocol_PROTOCOL_GENERIC_UNSPECIFIED, + ValTime: valTime, + } + protoReq, err := ctrl.SVMetaToProtoRequest(svReq) + require.NoError(t, err) + require.Equal(t, targetProtoReq, protoReq) +} + +func TestGetSVFromReply(t *testing.T) { + k := xtest.MustParseHexString("d29d00c39398b7588c0d31a4ffc77841") + proto := drkey.SCMP + + resp := &dkpb.SVResponse{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: k, + } + + targetSV := drkey.SV{ + Epoch: drkey.NewEpoch(0, 1), + ProtoId: proto, + } + copy(targetSV.Key[:], k) + sv, err := ctrl.GetSVFromReply(proto, resp) + require.NoError(t, err) + require.Equal(t, targetSV, sv) +} + +func TestSVtoProtoResp(t *testing.T) { + k := xtest.MustParseHexString("d29d00c39398b7588c0d31a4ffc77841") + + sv := drkey.SV{ + Epoch: drkey.NewEpoch(0, 1), + ProtoId: drkey.SCMP, + } + copy(sv.Key[:], k) + + targetResp := &dkpb.SVResponse{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: k, + } + + resp, err := ctrl.SVtoProtoResp(sv) + require.NoError(t, err) + require.Equal(t, targetResp, resp) +} diff --git a/go/lib/ctrl/drkey/sv_req.go b/go/lib/ctrl/drkey/sv_req.go new file mode 100644 index 0000000000..5c6eef657e --- /dev/null +++ b/go/lib/ctrl/drkey/sv_req.go @@ -0,0 +1,78 @@ +// Copyright 2021 ETH Zurich +// +// 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 drkey + +import ( + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/serrors" + dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" +) + +// SVMetaToProtoRequest parses the SVReq to a protobuf SVRequest. +func SVMetaToProtoRequest(meta drkey.SVMeta) (*dkpb.SVRequest, error) { + return &dkpb.SVRequest{ + ValTime: timestamppb.New(meta.Validity), + ProtocolId: dkpb.Protocol(meta.ProtoId), + }, nil +} + +// SVRequestToMeta parses the SVReq to a protobuf SVRequest. +func SVRequestToMeta(req *dkpb.SVRequest) (drkey.SVMeta, error) { + err := req.ValTime.CheckValid() + if err != nil { + return drkey.SVMeta{}, serrors.WrapStr("invalid valTime from request", err) + } + return drkey.SVMeta{ + Validity: req.ValTime.AsTime(), + ProtoId: drkey.Protocol(req.ProtocolId), + }, nil +} + +// GetSVFromReply extracts the SV from the reply. +func GetSVFromReply(proto drkey.Protocol, rep *dkpb.SVResponse) (drkey.SV, error) { + + err := rep.EpochBegin.CheckValid() + if err != nil { + return drkey.SV{}, serrors.WrapStr("invalid EpochBegin from response", err) + } + err = rep.EpochEnd.CheckValid() + if err != nil { + return drkey.SV{}, serrors.WrapStr("invalid EpochEnd from response", err) + } + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: rep.EpochBegin.AsTime(), + NotAfter: rep.EpochEnd.AsTime(), + }, + } + returningKey := drkey.SV{ + ProtoId: proto, + Epoch: epoch, + } + copy(returningKey.Key[:], rep.Key) + return returningKey, nil +} + +// SVtoProtoResp builds a SVResponse provided a SV. +func SVtoProtoResp(drkey drkey.SV) (*dkpb.SVResponse, error) { + return &dkpb.SVResponse{ + EpochBegin: timestamppb.New(drkey.Epoch.NotBefore), + EpochEnd: timestamppb.New(drkey.Epoch.NotAfter), + Key: drkey.Key[:], + }, nil +} diff --git a/go/lib/daemon/daemon.go b/go/lib/daemon/daemon.go index 3dab77519b..ca9fdf72b2 100644 --- a/go/lib/daemon/daemon.go +++ b/go/lib/daemon/daemon.go @@ -83,9 +83,6 @@ type Connector interface { SVCInfo(ctx context.Context, svcTypes []addr.HostSVC) (map[addr.HostSVC]string, error) // RevNotification sends a RevocationInfo message to the daemon. RevNotification(ctx context.Context, revInfo *path_mgmt.RevInfo) error - // DRKeyGetLvl2Key sends a DRKey Lvl2Key request to SCIOND - DRKeyGetLvl2Key(ctx context.Context, meta drkey.Lvl2Meta, - valTime time.Time) (drkey.Lvl2Key, error) // ColibriListRsvs requests the list of reservations towards dstIA. ColibriListRsvs(ctx context.Context, dstIA addr.IA) (*col.StitchableSegments, error) // ColibriSetupRsv requests a COLIBRI E2E reservation stitching up to three segments. @@ -97,6 +94,9 @@ type Connector interface { // ColibriAddAdmissionEntry adds an entry to the admission list. It returns the effective // validity time for the entry in the list. ColibriAddAdmissionEntry(ctx context.Context, entry *col.AdmissionEntry) (time.Time, error) + DRKeyGetASHostKey(ctx context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) + DRKeyGetHostASKey(ctx context.Context, meta drkey.HostASMeta) (drkey.HostASKey, error) + DRKeyGetHostHostKey(ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) // Close shuts down the connection to the daemon. Close(ctx context.Context) error } diff --git a/go/lib/daemon/fake/fake.go b/go/lib/daemon/fake/fake.go index fe313a2392..b64bc5e4f8 100644 --- a/go/lib/daemon/fake/fake.go +++ b/go/lib/daemon/fake/fake.go @@ -186,8 +186,20 @@ func (c connector) RevNotification(ctx context.Context, panic("not implemented") } -func (c connector) DRKeyGetLvl2Key(ctx context.Context, meta drkey.Lvl2Meta, - valTime time.Time) (drkey.Lvl2Key, error) { +func (c connector) DRKeyGetASHostKey(ctx context.Context, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + + panic("not implemented") +} + +func (c connector) DRKeyGetHostASKey(ctx context.Context, + meta drkey.HostASMeta) (drkey.HostASKey, error) { + + panic("not implemented") +} + +func (c connector) DRKeyGetHostHostKey(ctx context.Context, + meta drkey.HostHostMeta) (drkey.HostHostKey, error) { panic("not implemented") } diff --git a/go/lib/daemon/grpc.go b/go/lib/daemon/grpc.go index 3769b0c922..9eccf473dc 100644 --- a/go/lib/daemon/grpc.go +++ b/go/lib/daemon/grpc.go @@ -164,29 +164,6 @@ func (c grpcConn) RevNotification(ctx context.Context, revInfo *path_mgmt.RevInf } -func (c grpcConn) DRKeyGetLvl2Key(ctx context.Context, meta drkey.Lvl2Meta, - valTime time.Time) (drkey.Lvl2Key, error) { - - client := sdpb.NewDaemonServiceClient(c.conn) - - lvl2Req := dkctrl.NewLvl2ReqFromMeta(meta, valTime) - pbLvl2Req, err := lvl2reqToProtoRequest(lvl2Req) - if err != nil { - return drkey.Lvl2Key{}, err - } - - reply, err := client.DRKeyLvl2(ctx, pbLvl2Req) - if err != nil { - return drkey.Lvl2Key{}, err - } - - lvl2Key, err := getLvl2KeyFromReply(reply, meta) - if err != nil { - return drkey.Lvl2Key{}, err - } - return lvl2Key, nil -} - func (c grpcConn) ColibriListRsvs(ctx context.Context, dstIA addr.IA) ( *col.StitchableSegments, error) { @@ -323,6 +300,72 @@ func (c grpcConn) ColibriAddAdmissionEntry(ctx context.Context, entry *col.Admis return util.SecsToTime(res.Base.ValidUntil), nil } +func (c grpcConn) DRKeyGetASHostKey(ctx context.Context, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + + client := sdpb.NewDaemonServiceClient(c.conn) + + pbReq, err := dkctrl.ASHostMetaToProtoRequest(meta) + if err != nil { + return drkey.ASHostKey{}, err + } + + reply, err := client.ASHost(ctx, pbReq) + if err != nil { + return drkey.ASHostKey{}, err + } + + key, err := dkctrl.GetASHostKeyFromReply(reply, meta) + if err != nil { + return drkey.ASHostKey{}, err + } + return key, nil +} + +func (c grpcConn) DRKeyGetHostASKey(ctx context.Context, + meta drkey.HostASMeta) (drkey.HostASKey, error) { + + client := sdpb.NewDaemonServiceClient(c.conn) + + req, err := dkctrl.HostASMetaToProtoRequest(meta) + if err != nil { + return drkey.HostASKey{}, err + } + + reply, err := client.HostAS(ctx, req) + if err != nil { + return drkey.HostASKey{}, err + } + + key, err := dkctrl.GetHostASKeyFromReply(reply, meta) + if err != nil { + return drkey.HostASKey{}, err + } + return key, nil +} + +func (c grpcConn) DRKeyGetHostHostKey(ctx context.Context, + meta drkey.HostHostMeta) (drkey.HostHostKey, error) { + + client := sdpb.NewDaemonServiceClient(c.conn) + + pbReq, err := dkctrl.HostHostMetaToProtoRequest(meta) + if err != nil { + return drkey.HostHostKey{}, err + } + + reply, err := client.HostHost(ctx, pbReq) + if err != nil { + return drkey.HostHostKey{}, err + } + + key, err := dkctrl.GetHostHostKeyFromReply(reply, meta) + if err != nil { + return drkey.HostHostKey{}, err + } + return key, nil +} + func (c grpcConn) Close(_ context.Context) error { return c.conn.Close() } @@ -420,18 +463,3 @@ func topoServiceTypeToSVCAddr(st topology.ServiceType) addr.HostSVC { return addr.SvcNone } } - -func lvl2reqToProtoRequest(req dkctrl.Lvl2Req) (*sdpb.DRKeyLvl2Request, error) { - baseReq, err := dkctrl.Lvl2reqToProtoRequest(req) - if err != nil { - return nil, err - } - return &sdpb.DRKeyLvl2Request{ - BaseReq: baseReq, - }, nil -} - -// getLvl2KeyFromReply decrypts and extracts the level 1 drkey from the reply. -func getLvl2KeyFromReply(rep *sdpb.DRKeyLvl2Response, meta drkey.Lvl2Meta) (drkey.Lvl2Key, error) { - return dkctrl.GetLvl2KeyFromReply(rep.BaseRep, meta) -} diff --git a/go/lib/daemon/mock_daemon/mock.go b/go/lib/daemon/mock_daemon/mock.go index da3ed0e0b5..0ec21fa70b 100644 --- a/go/lib/daemon/mock_daemon/mock.go +++ b/go/lib/daemon/mock_daemon/mock.go @@ -131,19 +131,49 @@ func (mr *MockConnectorMockRecorder) ColibriSetupRsv(arg0, arg1 interface{}) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ColibriSetupRsv", reflect.TypeOf((*MockConnector)(nil).ColibriSetupRsv), arg0, arg1) } -// DRKeyGetLvl2Key mocks base method. -func (m *MockConnector) DRKeyGetLvl2Key(arg0 context.Context, arg1 drkey.Lvl2Meta, arg2 time.Time) (drkey.Lvl2Key, error) { +// DRKeyGetASHostKey mocks base method. +func (m *MockConnector) DRKeyGetASHostKey(arg0 context.Context, arg1 drkey.ASHostMeta) (drkey.ASHostKey, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DRKeyGetLvl2Key", arg0, arg1, arg2) - ret0, _ := ret[0].(drkey.Lvl2Key) + ret := m.ctrl.Call(m, "DRKeyGetASHostKey", arg0, arg1) + ret0, _ := ret[0].(drkey.ASHostKey) ret1, _ := ret[1].(error) return ret0, ret1 } -// DRKeyGetLvl2Key indicates an expected call of DRKeyGetLvl2Key. -func (mr *MockConnectorMockRecorder) DRKeyGetLvl2Key(arg0, arg1, arg2 interface{}) *gomock.Call { +// DRKeyGetASHostKey indicates an expected call of DRKeyGetASHostKey. +func (mr *MockConnectorMockRecorder) DRKeyGetASHostKey(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyGetLvl2Key", reflect.TypeOf((*MockConnector)(nil).DRKeyGetLvl2Key), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyGetASHostKey", reflect.TypeOf((*MockConnector)(nil).DRKeyGetASHostKey), arg0, arg1) +} + +// DRKeyGetHostASKey mocks base method. +func (m *MockConnector) DRKeyGetHostASKey(arg0 context.Context, arg1 drkey.HostASMeta) (drkey.HostASKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DRKeyGetHostASKey", arg0, arg1) + ret0, _ := ret[0].(drkey.HostASKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DRKeyGetHostASKey indicates an expected call of DRKeyGetHostASKey. +func (mr *MockConnectorMockRecorder) DRKeyGetHostASKey(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyGetHostASKey", reflect.TypeOf((*MockConnector)(nil).DRKeyGetHostASKey), arg0, arg1) +} + +// DRKeyGetHostHostKey mocks base method. +func (m *MockConnector) DRKeyGetHostHostKey(arg0 context.Context, arg1 drkey.HostHostMeta) (drkey.HostHostKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DRKeyGetHostHostKey", arg0, arg1) + ret0, _ := ret[0].(drkey.HostHostKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DRKeyGetHostHostKey indicates an expected call of DRKeyGetHostHostKey. +func (mr *MockConnectorMockRecorder) DRKeyGetHostHostKey(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyGetHostHostKey", reflect.TypeOf((*MockConnector)(nil).DRKeyGetHostHostKey), arg0, arg1) } // IFInfo mocks base method. diff --git a/go/lib/drkey/BUILD.bazel b/go/lib/drkey/BUILD.bazel index 7b691c61a5..6029b99f6a 100644 --- a/go/lib/drkey/BUILD.bazel +++ b/go/lib/drkey/BUILD.bazel @@ -5,27 +5,43 @@ go_library( srcs = [ "db.go", "drkey.go", - "epoch.go", - "level1.go", - "level2.go", - "secret_value.go", + "generic.go", + "metrics.go", + "protocol.go", + "specific.go", ], importpath = "github.com/scionproto/scion/go/lib/drkey", visibility = ["//visibility:public"], deps = [ "//go/lib/addr:go_default_library", "//go/lib/infra/modules/db:go_default_library", + "//go/lib/prom:go_default_library", "//go/lib/scrypto/cppki:go_default_library", + "//go/lib/serrors:go_default_library", + "//go/lib/slayers:go_default_library", + "//go/lib/tracing:go_default_library", "//go/lib/util:go_default_library", + "//go/pkg/proto/drkey:go_default_library", + "@com_github_opentracing_opentracing_go//:go_default_library", + "@com_github_prometheus_client_golang//prometheus:go_default_library", "@org_golang_x_crypto//pbkdf2:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["secret_value_test.go"], - embed = [":go_default_library"], + srcs = [ + "metrics_test.go", + "protocol_test.go", + "secret_value_test.go", + ], deps = [ + ":go_default_library", + "//go/lib/drkey/dbtest:go_default_library", + "//go/lib/drkey/protocoltest:go_default_library", + "//go/lib/drkey/sqlite:go_default_library", "//go/lib/xtest:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/go/lib/drkey/db.go b/go/lib/drkey/db.go index ecb17e477c..cb690cb538 100644 --- a/go/lib/drkey/db.go +++ b/go/lib/drkey/db.go @@ -17,31 +17,44 @@ package drkey import ( "context" "io" + "time" - "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/infra/modules/db" + "github.com/scionproto/scion/go/lib/serrors" ) -// BaseDB defines basic interface -type BaseDB interface { +var ErrKeyNotFound = serrors.New("Key not found") + +// SecretValueDB is the database for Secret Values. +type SecretValueDB interface { + GetSV(ctx context.Context, meta SVMeta) (SV, error) + InsertSV(ctx context.Context, key SV) error + DeleteExpiredSV(ctx context.Context, cutoff time.Time) (int64, error) + io.Closer db.LimitSetter } // Lvl1DB is the drkey database interface for level 1. type Lvl1DB interface { - BaseDB - GetLvl1Key(ctx context.Context, key Lvl1Meta, valTime uint32) (Lvl1Key, error) + GetLvl1Key(ctx context.Context, meta Lvl1Meta) (Lvl1Key, error) InsertLvl1Key(ctx context.Context, key Lvl1Key) error - RemoveOutdatedLvl1Keys(ctx context.Context, cutoff uint32) (int64, error) - GetLvl1SrcASes(ctx context.Context) ([]addr.IA, error) - GetValidLvl1SrcASes(ctx context.Context, valTime uint32) ([]addr.IA, error) + DeleteExpiredLvl1Keys(ctx context.Context, cutoff time.Time) (int64, error) + + io.Closer + db.LimitSetter } -// Lvl2DB is the drkey database interface for level 2. +// Lvl2DB is the drkey database interface for end-host keys. type Lvl2DB interface { - BaseDB - GetLvl2Key(ctx context.Context, key Lvl2Meta, valTime uint32) (Lvl2Key, error) - InsertLvl2Key(ctx context.Context, key Lvl2Key) error - RemoveOutdatedLvl2Keys(ctx context.Context, cutoff uint32) (int64, error) + GetASHostKey(ctx context.Context, meta ASHostMeta) (ASHostKey, error) + GetHostASKey(ctx context.Context, meta HostASMeta) (HostASKey, error) + GetHostHostKey(ctx context.Context, meta HostHostMeta) (HostHostKey, error) + InsertASHostKey(ctx context.Context, key ASHostKey) error + InsertHostASKey(ctx context.Context, key HostASKey) error + InsertHostHostKey(ctx context.Context, key HostHostKey) error + DeleteExpiredLvl2Keys(ctx context.Context, cutoff time.Time) (int64, error) + + io.Closer + db.LimitSetter } diff --git a/go/pkg/cs/drkey/test/BUILD.bazel b/go/lib/drkey/dbtest/BUILD.bazel similarity index 51% rename from go/pkg/cs/drkey/test/BUILD.bazel rename to go/lib/drkey/dbtest/BUILD.bazel index 187dd2b0c0..49348a2696 100644 --- a/go/pkg/cs/drkey/test/BUILD.bazel +++ b/go/lib/drkey/dbtest/BUILD.bazel @@ -2,16 +2,14 @@ load("//lint:go.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["testcommons.go"], - importpath = "github.com/scionproto/scion/go/pkg/cs/drkey/test", + srcs = ["dbtest.go"], + importpath = "github.com/scionproto/scion/go/lib/drkey/dbtest", visibility = ["//visibility:public"], deps = [ - "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkeystorage:go_default_library", - "//go/lib/util:go_default_library", + "//go/lib/drkey/protocoltest:go_default_library", + "//go/lib/scrypto/cppki:go_default_library", "//go/lib/xtest:go_default_library", - "//go/pkg/cs/drkey:go_default_library", "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/go/lib/drkey/dbtest/dbtest.go b/go/lib/drkey/dbtest/dbtest.go new file mode 100644 index 0000000000..83c63f9c89 --- /dev/null +++ b/go/lib/drkey/dbtest/dbtest.go @@ -0,0 +1,229 @@ +// Copyright 2019 ETH Zurich +// +// 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 dbtest + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/drkey/protocoltest" + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/xtest" +) + +const ( + timeOffset = 10 * 60 // 10 minutes + timeout = 3 * time.Second +) + +var ( + srcIA = xtest.MustParseIA("1-ff00:0:111") + dstIA = xtest.MustParseIA("1-ff00:0:112") + srcHost = "192.168.1.37" + dstHost = "192.168.1.38" +) + +type TestableLvl1DB interface { + drkey.Lvl1DB + Prepare(t *testing.T, ctx context.Context) +} + +// Test should be used to test any implementation of the Lvl1DB interface. An +// implementation of the Lvl1DB interface should at least have one test +// method that calls this test-suite. +func TestLvl1(t *testing.T, db TestableLvl1DB) { + prepareCtx, cancelF := context.WithTimeout(context.Background(), 2*timeout) + db.Prepare(t, prepareCtx) + cancelF() + defer db.Close() + testDRKeyLvl1(t, db) +} + +func testDRKeyLvl1(t *testing.T, db drkey.Lvl1DB) { + ctx, cancelF := context.WithTimeout(context.Background(), timeout) + defer cancelF() + + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(timeOffset * time.Second), + }, + } + protoId := drkey.Protocol(0) + drkeyLvl1 := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + + lvl1Meta := drkey.Lvl1Meta{ + Validity: time.Now(), + ProtoId: protoId, + SrcIA: srcIA, + DstIA: dstIA, + } + + err := db.InsertLvl1Key(ctx, drkeyLvl1) + require.NoError(t, err) + // same key again. It should be okay. + err = db.InsertLvl1Key(ctx, drkeyLvl1) + require.NoError(t, err) + + newKey, err := db.GetLvl1Key(ctx, lvl1Meta) + require.NoError(t, err) + require.Equal(t, drkeyLvl1.Key, newKey.Key) + + rows, err := db.DeleteExpiredLvl1Keys(ctx, + time.Now().Add(-timeOffset*time.Second)) + require.NoError(t, err) + require.EqualValues(t, 0, rows) + + rows, err = db.DeleteExpiredLvl1Keys(ctx, + time.Now().Add(2*timeOffset*time.Second)) + require.NoError(t, err) + require.EqualValues(t, 1, rows) + +} + +type TestableLvl2DB interface { + drkey.Lvl2DB + Prepare(t *testing.T, ctx context.Context) +} + +// Test should be used to test any implementation of the Lvl2DB interface. An +// implementation of the Lvl2DB interface should at least have one test +// method that calls this test-suite. +func TestLvl2(t *testing.T, db TestableLvl2DB) { + prepareCtx, cancelF := context.WithTimeout(context.Background(), 2*timeout) + db.Prepare(t, prepareCtx) + cancelF() + defer db.Close() + testDRKeyLvl2(t, db) +} + +func testDRKeyLvl2(t *testing.T, db drkey.Lvl2DB) { + ctx, cancelF := context.WithTimeout(context.Background(), time.Second) + defer cancelF() + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(timeOffset * time.Second), + }, + } + protoId := drkey.Protocol(0) + drkeyLvl1 := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + + // AS-Host + as2HostMeta := drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: 25, + SrcIA: srcIA, + DstIA: dstIA, + Validity: time.Now(), + }, + DstHost: dstHost, + } + asHostKey, err := protocoltest.DeriveASHostGeneric(as2HostMeta, drkeyLvl1) + require.NoError(t, err) + + err = db.InsertASHostKey(ctx, asHostKey) + require.NoError(t, err) + err = db.InsertASHostKey(ctx, asHostKey) + require.NoError(t, err) + + newKey, err := db.GetASHostKey(ctx, as2HostMeta) + require.NoError(t, err) + require.Equal(t, asHostKey.Key, newKey.Key) + + // Host-Host + h2hMeta := drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: 25, + SrcIA: srcIA, + DstIA: dstIA, + Validity: time.Now(), + }, + SrcHost: srcHost, + DstHost: dstHost, + } + h2hKey, err := protocoltest.DeriveHostHostGeneric(h2hMeta, drkeyLvl1) + require.NoError(t, err) + + err = db.InsertHostHostKey(ctx, h2hKey) + require.NoError(t, err) + err = db.InsertHostHostKey(ctx, h2hKey) + require.NoError(t, err) + + newh2hKey, err := db.GetHostHostKey(ctx, h2hMeta) + require.NoError(t, err) + require.Equal(t, h2hKey.Key, newh2hKey.Key) + + _, err = db.DeleteExpiredLvl2Keys(ctx, + time.Now().Add(-timeOffset*time.Second)) + require.NoError(t, err) + +} + +type TestableSVDB interface { + drkey.SecretValueDB + Prepare(t *testing.T, ctx context.Context) +} + +// Test should be used to test any implementation of the SecretValueDB interface. An +// implementation of the SecretValueDB interface should at least have one test +// method that calls this test-suite. +func TestSecretValueDB(t *testing.T, db TestableSVDB) { + prepareCtx, cancelF := context.WithTimeout(context.Background(), 2*timeout) + db.Prepare(t, prepareCtx) + cancelF() + defer db.Close() + testSecretValue(t, db) +} + +func testSecretValue(t *testing.T, db drkey.SecretValueDB) { + ctx, cancelF := context.WithTimeout(context.Background(), timeout) + defer cancelF() + + epoch := drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: time.Now(), + NotAfter: time.Now().Add(timeOffset * time.Second), + }, + } + sv, err := drkey.DeriveSV(drkey.Protocol(0), epoch, []byte("0123456789012345")) + require.NoError(t, err) + + err = db.InsertSV(ctx, sv) + require.NoError(t, err) + // same key again. It should be okay. + err = db.InsertSV(ctx, sv) + require.NoError(t, err) + newSV, err := db.GetSV(ctx, drkey.SVMeta{ + ProtoId: drkey.Protocol(0), + Validity: time.Now(), + }) + require.NoError(t, err) + require.EqualValues(t, sv.Key, newSV.Key) + + rows, err := db.DeleteExpiredSV(ctx, + time.Now().Add(-timeOffset*time.Second)) + require.NoError(t, err) + require.EqualValues(t, 0, rows) + + rows, err = db.DeleteExpiredSV(ctx, + time.Now().Add(2*timeOffset*time.Second)) + require.NoError(t, err) + require.EqualValues(t, 1, rows) +} diff --git a/go/lib/drkey/drkey.go b/go/lib/drkey/drkey.go index b74cc44d98..c7562ebd2f 100644 --- a/go/lib/drkey/drkey.go +++ b/go/lib/drkey/drkey.go @@ -14,16 +14,200 @@ package drkey -import "bytes" +import ( + "crypto/sha256" + "encoding/binary" + "fmt" + "time" -// DRKey represents a raw binary key -type DRKey []byte + "golang.org/x/crypto/pbkdf2" -func (k DRKey) String() string { + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/serrors" + "github.com/scionproto/scion/go/lib/util" + pb "github.com/scionproto/scion/go/pkg/proto/drkey" +) + +// Epoch represents a validity period. +type Epoch struct { + cppki.Validity +} + +// Equal returns true if both Epochs are identical. +func (e Epoch) Equal(other Epoch) bool { + return e.NotBefore == other.NotBefore && + e.NotAfter == other.NotAfter +} + +// NewEpoch constructs an Epoch from its uint32 encoded begin and end parts. +func NewEpoch(begin, end uint32) Epoch { + return Epoch{ + cppki.Validity{ + NotBefore: util.SecsToTime(begin).UTC(), + NotAfter: util.SecsToTime(end).UTC(), + }, + } +} + +// Contains indicates whether the time point is inside this Epoch. +func (e *Epoch) Contains(t time.Time) bool { + return e.Validity.Contains(t) +} + +// Protocol is the 2-byte size protocol identifier +type Protocol uint16 + +// DRKey protocol types. +const ( + Generic = Protocol(pb.Protocol_PROTOCOL_GENERIC_UNSPECIFIED) + SCMP = Protocol(pb.Protocol_PROTOCOL_SCMP) + DNS = Protocol(pb.Protocol_PROTOCOL_DNS) + COLIBRI = Protocol(pb.Protocol_PROTOCOL_COLIBRI) +) + +func (p Protocol) String() string { + name, ok := pb.Protocol_name[int32(p)] + if !ok { + return fmt.Sprintf("UNKNOWN(%d)", p) + } + return name +} + +// IsPredefined checks whether this is a well-known, built-in protocol +// identifier, i.e. Generic, SCMP or DNS. Returns false for all other +// protocol identifiers ("niche protocols"). +func (p Protocol) IsPredefined() bool { + _, ok := pb.Protocol_name[int32(p)] + return ok +} + +func ProtocolStringToId(protocol string) (Protocol, bool) { + id, ok := pb.Protocol_value[protocol] + return Protocol(id), ok +} + +// Key represents a raw binary key +type Key [16]byte + +func (k Key) String() string { return "[redacted key]" } -// Equal returns true if both DRKeys are identical -func (k DRKey) Equal(other DRKey) bool { - return bytes.Equal(k, other) +const drkeySalt = "Derive DRKey Key" + +// SVMeta represents the information about a DRKey secret value. +type SVMeta struct { + Validity time.Time + ProtoId Protocol +} + +// SV represents a DRKey secret value. +type SV struct { + Epoch Epoch + ProtoId Protocol + Key Key +} + +// DeriveSV constructs a valid SV. asSecret is typically the AS master secret. +func DeriveSV(protoID Protocol, epoch Epoch, asSecret []byte) (SV, error) { + msLen := len(asSecret) + if msLen == 0 { + return SV{}, serrors.New("Invalid zero sized secret") + } + + totalLen := msLen + 18 + buf := make([]byte, totalLen) + offset := 0 + binary.BigEndian.PutUint64(buf[:], uint64(msLen)) + offset += 8 + copy(buf[offset:], asSecret) + offset += msLen + binary.BigEndian.PutUint16(buf[offset:], uint16(protoID)) + offset += 2 + binary.BigEndian.PutUint32(buf[offset:], util.TimeToSecs(epoch.NotBefore)) + offset += 4 + binary.BigEndian.PutUint32(buf[offset:], util.TimeToSecs(epoch.NotAfter)) + + key := pbkdf2.Key(buf, []byte(drkeySalt), 1000, 16, sha256.New) + sv := SV{ + Epoch: epoch, + ProtoId: protoID, + } + copy(sv.Key[:], key) + return sv, nil +} + +// / Lvl1Meta contains metadata to obtain a lvl1 key. +type Lvl1Meta struct { + Validity time.Time + ProtoId Protocol + SrcIA, DstIA addr.IA +} + +// Lvl1Key represents a level 1 DRKey. +type Lvl1Key struct { + Epoch Epoch + ProtoId Protocol + SrcIA, DstIA addr.IA + Key Key +} + +// Lvl2Meta contains metadata to obtain end host keys +// (aka lvl2/3 keys). +type Lvl2Meta struct { + ProtoId Protocol + Validity time.Time + SrcIA addr.IA + DstIA addr.IA +} + +// ASHost represents the associated information for the ASHost key. +type ASHostMeta struct { + Lvl2Meta + DstHost string +} + +// ASHost represents a ASHost key. +type ASHostKey struct { + ProtoId Protocol + Epoch Epoch + SrcIA addr.IA + DstIA addr.IA + DstHost string + Key Key +} + +// HostASMeta represents the associated information for the HostAS key. +type HostASMeta struct { + Lvl2Meta + SrcHost string +} + +// HostASKey represents a Host-AS key. +type HostASKey struct { + ProtoId Protocol + Epoch Epoch + SrcIA addr.IA + DstIA addr.IA + SrcHost string + Key Key +} + +// HostHostMeta represents the associated information for the HostHostMeta key. +type HostHostMeta struct { + Lvl2Meta + SrcHost string + DstHost string +} + +// HostHostKey represents a Host-Host DRKey. +type HostHostKey struct { + ProtoId Protocol + Epoch Epoch + SrcIA addr.IA + DstIA addr.IA + SrcHost string + DstHost string + Key Key } diff --git a/go/lib/drkey/drkeydbsqlite/db_test.go b/go/lib/drkey/drkeydbsqlite/db_test.go deleted file mode 100644 index d5aa4d64b0..0000000000 --- a/go/lib/drkey/drkeydbsqlite/db_test.go +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkeydbsqlite - -import ( - "context" - "encoding/binary" - "io/ioutil" - "net" - "os" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkey/protocol" - "github.com/scionproto/scion/go/lib/scrypto/cppki" - "github.com/scionproto/scion/go/lib/util" -) - -const ( - timeOffset = 10 * 60 // 10 minutes -) - -var ( - asMasterPassword = []byte("0123456789012345") - rawSrcIA = []byte{0xF0, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77} - rawDstIA = []byte{0xF0, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x88} - SrcHostIP = net.IPv4(192, 168, 1, 37) - DstHostIP = net.IPv4(192, 168, 1, 38) -) - -func TestDRKeyLvl1(t *testing.T) { - ctx, cancelF := context.WithTimeout(context.Background(), time.Second) - defer cancelF() - db, cleanF := newLvl1Database(t) - defer cleanF() - - epoch := drkey.Epoch{ - Validity: cppki.Validity{ - NotBefore: time.Now(), - NotAfter: time.Now().Add(timeOffset * time.Second), - }, - } - sv, err := drkey.DeriveSV(drkey.SVMeta{Epoch: epoch}, asMasterPassword) - require.NoError(t, err) - - drkeyLvl1, err := protocol.DeriveLvl1(drkey.Lvl1Meta{ - Epoch: epoch, - SrcIA: addr.IA(binary.BigEndian.Uint64(rawSrcIA)), - DstIA: addr.IA(binary.BigEndian.Uint64(rawDstIA))}, sv) - require.NoError(t, err) - - err = db.InsertLvl1Key(ctx, drkeyLvl1) - require.NoError(t, err) - // same key again. It should be okay. - err = db.InsertLvl1Key(ctx, drkeyLvl1) - require.NoError(t, err) - - newKey, err := db.GetLvl1Key(ctx, drkeyLvl1.Lvl1Meta, util.TimeToSecs(time.Now())) - require.NoError(t, err) - require.Equal(t, drkeyLvl1.Key, newKey.Key) - - rows, err := db.RemoveOutdatedLvl1Keys(ctx, - util.TimeToSecs(time.Now().Add(-timeOffset*time.Second))) - require.NoError(t, err) - require.EqualValues(t, 0, rows) - - rows, err = db.RemoveOutdatedLvl1Keys(ctx, - util.TimeToSecs(time.Now().Add(2*timeOffset*time.Second))) - require.NoError(t, err) - require.EqualValues(t, 1, rows) - -} - -func TestDRKeyLvl2(t *testing.T) { - ctx, cancelF := context.WithTimeout(context.Background(), time.Second) - defer cancelF() - - db, cleanF := newLvl2Database(t) - defer cleanF() - - srcIA := addr.IA(binary.BigEndian.Uint64(rawSrcIA)) - dstIA := addr.IA(binary.BigEndian.Uint64(rawDstIA)) - epoch := drkey.Epoch{ - Validity: cppki.Validity{ - NotBefore: time.Now(), - NotAfter: time.Now().Add(timeOffset * time.Second), - }, - } - sv, err := drkey.DeriveSV(drkey.SVMeta{Epoch: epoch}, asMasterPassword) - require.NoError(t, err) - drkeyLvl1, err := protocol.DeriveLvl1(drkey.Lvl1Meta{ - Epoch: epoch, - SrcIA: srcIA, - DstIA: dstIA, - }, sv) - require.NoError(t, err) - - standardImpl := protocol.Standard{} - drkeyLvl2, err := standardImpl.DeriveLvl2(drkey.Lvl2Meta{ - KeyType: drkey.Host2Host, - Protocol: "test", - Epoch: epoch, - SrcIA: srcIA, - DstIA: dstIA, - SrcHost: addr.HostFromIP(SrcHostIP), - DstHost: addr.HostFromIP(DstHostIP), - }, drkeyLvl1) - require.NoError(t, err) - - err = db.InsertLvl2Key(ctx, drkeyLvl2) - require.NoError(t, err) - err = db.InsertLvl2Key(ctx, drkeyLvl2) - require.NoError(t, err) - - newKey, err := db.GetLvl2Key(ctx, drkeyLvl2.Lvl2Meta, util.TimeToSecs(time.Now())) - require.NoError(t, err) - require.Equal(t, drkeyLvl2.Key, newKey.Key) - - rows, err := db.RemoveOutdatedLvl2Keys(ctx, - util.TimeToSecs(time.Now().Add(-timeOffset*time.Second))) - require.NoError(t, err) - require.EqualValues(t, 0, rows) - - rows, err = db.RemoveOutdatedLvl2Keys(ctx, - util.TimeToSecs(time.Now().Add(2*timeOffset*time.Second))) - require.NoError(t, err) - require.EqualValues(t, 1, rows) -} - -func TestGetMentionedASes(t *testing.T) { - ctx, cancelF := context.WithTimeout(context.Background(), time.Second) - defer cancelF() - - db, cleanF := newLvl1Database(t) - defer cleanF() - - pairsL1 := [][]interface{}{ - {"1-ff00:0:111", "1-ff00:0:112", 1}, - {"1-ff00:0:111", "1-ff00:0:110", 10}, - {"2-ff00:0:211", "1-ff00:0:113", 1}, - } - for _, p := range pairsL1 { - srcIA, _ := addr.ParseIA(p[0].(string)) - dstIA, _ := addr.ParseIA(p[1].(string)) - begin := time.Unix(0, 0) - epoch := drkey.Epoch{ - Validity: cppki.Validity{ - NotBefore: begin, - NotAfter: begin.Add(time.Duration(p[2].(int)) * time.Second), - }, - } - sv, err := drkey.DeriveSV(drkey.SVMeta{Epoch: epoch}, asMasterPassword) - require.NoError(t, err) - - key, err := protocol.DeriveLvl1(drkey.Lvl1Meta{ - Epoch: epoch, - SrcIA: srcIA, - DstIA: dstIA, - }, sv) - require.NoError(t, err) - - err = db.InsertLvl1Key(ctx, key) - require.NoError(t, err) - } - - list, err := db.GetLvl1SrcASes(ctx) - require.NoError(t, err) - - expected := []addr.IA{ - ia("1-ff00:0:111"), - ia("2-ff00:0:211"), - } - - require.Equal(t, expected, list) - - list, err = db.GetValidLvl1SrcASes(ctx, 3) - require.NoError(t, err) - - expected = []addr.IA{ - ia("1-ff00:0:111"), - } - require.Equal(t, expected, list) -} - -func ia(iaStr string) addr.IA { - ia, err := addr.ParseIA(iaStr) - if err != nil { - panic("Invalid value") - } - return ia -} - -func newLvl1Database(t *testing.T) (*Lvl1Backend, func()) { - file, err := ioutil.TempFile("", "db-test-") - require.NoError(t, err) - name := file.Name() - err = file.Close() - require.NoError(t, err) - db, err := NewLvl1Backend(name) - require.NoError(t, err) - - return db, func() { - db.Close() - os.Remove(name) - } -} - -func newLvl2Database(t *testing.T) (*Lvl2Backend, func()) { - file, err := ioutil.TempFile("", "db-test-") - require.NoError(t, err) - name := file.Name() - err = file.Close() - require.NoError(t, err) - db, err := NewLvl2Backend(name) - require.NoError(t, err) - - return db, func() { - db.Close() - os.Remove(name) - } -} diff --git a/go/lib/drkey/drkeydbsqlite/lvl1db.go b/go/lib/drkey/drkeydbsqlite/lvl1db.go deleted file mode 100644 index c955d00109..0000000000 --- a/go/lib/drkey/drkeydbsqlite/lvl1db.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkeydbsqlite - -import ( - "context" - "database/sql" - - _ "github.com/mattn/go-sqlite3" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/serrors" -) - -const ( - // Lvl1SchemaVersion is the version of the SQLite schema understood by this backend. - // Whenever changes to the schema are made, this version number should be increased - // to prevent data corruption between incompatible database schemas. - Lvl1SchemaVersion = 1 - // Lvl1Schema is the SQLite database layout. - Lvl1Schema = ` - CREATE TABLE DRKeyLvl1 ( - SrcIsdID INTEGER NOT NULL, - SrcAsID INTEGER NOT NULL, - DstIsdID INTEGER NOT NULL, - DstAsID INTEGER NOT NULL, - EpochBegin INTEGER NOT NULL, - EpochEnd INTEGER NOT NULL, - Key TEXT NOT NULL, - PRIMARY KEY (SrcIsdID, SrcAsID, DstIsdID, DstAsID, EpochBegin) - );` -) - -var _ drkey.Lvl1DB = (*Lvl1Backend)(nil) - -// Lvl1Backend implements a level 1 drkey DB with sqlite. -type Lvl1Backend struct { - dbBaseBackend - getLvl1SrcASesStmt *sql.Stmt - getValidLvl1SrcASesStmt *sql.Stmt - getLvl1KeyStmt *sql.Stmt - insertLvl1KeyStmt *sql.Stmt - removeOutdatedLvl1KeysStmt *sql.Stmt -} - -// NewLvl1Backend creates a database and prepares all statements. -func NewLvl1Backend(path string) (*Lvl1Backend, error) { - base, err := newBaseBackend(path, Lvl1Schema, Lvl1SchemaVersion) - if err != nil { - return nil, err - } - b := &Lvl1Backend{ - dbBaseBackend: *base, - } - stmts := preparedStmts{ - getLvl1SrcASes: &b.getLvl1SrcASesStmt, - getValidLvl1SrcASes: &b.getValidLvl1SrcASesStmt, - getLvl1Key: &b.getLvl1KeyStmt, - insertLvl1Key: &b.insertLvl1KeyStmt, - removeOutdatedLvl1Keys: &b.removeOutdatedLvl1KeysStmt, - } - if err := base.prepareAll(stmts); err != nil { - return nil, err - } - return b, nil -} - -const getLvl1SrcASes = ` -SELECT SrcIsdID as I, SrcASID as A FROM DRKeyLvl1 -GROUP BY I, A -` - -// GetLvl1SrcASes returns a list of distinct ASes seen in the SRC of a level 1 key -func (b *Lvl1Backend) GetLvl1SrcASes(ctx context.Context) ([]addr.IA, error) { - rows, err := b.getLvl1SrcASesStmt.QueryContext(ctx) - if err != nil { - if err != sql.ErrNoRows { - err = serrors.WrapStr(unableToExecuteStmt, err) - } - return nil, err - } - defer rows.Close() - ases := []addr.IA{} - for rows.Next() { - var I, A int - if err := rows.Scan(&I, &A); err != nil { - return nil, serrors.WrapStr("Cannot copy from SQL to memory", err) - } - ia, err := addr.IAFrom(addr.ISD(I), addr.AS(A)) - if err != nil { - return nil, err - } - ases = append(ases, ia) - } - if err := rows.Err(); err != nil { - return nil, err - } - return ases, nil -} - -const getValidLvl1SrcASes = ` -SELECT SrcIsdID as I, SrcASID as A FROM DRKeyLvl1 -WHERE EpochBegin <= ? AND ? < EpochEnd -GROUP BY I, A -` - -// GetValidLvl1SrcASes returns a list of distinct IAs that have a still valid level 1 key -// If the level 1 key is still valid according to valTime, its src IA will be in the list -func (b *Lvl1Backend) GetValidLvl1SrcASes(ctx context.Context, valTime uint32) ([]addr.IA, error) { - rows, err := b.getValidLvl1SrcASesStmt.QueryContext(ctx, valTime, valTime) - if err != nil { - if err != sql.ErrNoRows { - err = serrors.WrapStr(unableToExecuteStmt, err) - } - return nil, err - } - defer rows.Close() - ases := []addr.IA{} - for rows.Next() { - var I, A int - if err := rows.Scan(&I, &A); err != nil { - return nil, serrors.WrapStr("Cannot copy from SQL to memory", err) - } - ia, err := addr.IAFrom(addr.ISD(I), addr.AS(A)) - if err != nil { - return nil, err - } - ases = append(ases, ia) - } - if err := rows.Err(); err != nil { - return nil, err - } - return ases, nil -} - -const getLvl1Key = ` -SELECT EpochBegin, EpochEnd, Key FROM DRKeyLvl1 -WHERE SrcIsdID=? AND SrcAsID=? AND DstIsdID=? AND DstAsID=? -AND EpochBegin<=? AND ?= EpochEnd -` - -// RemoveOutdatedLvl1Keys removes all expired first level DRKeys. I.e. all the keys -// which expiration time is strictly smaller than the cutoff -func (b *Lvl1Backend) RemoveOutdatedLvl1Keys(ctx context.Context, cutoff uint32) (int64, error) { - res, err := b.removeOutdatedLvl1KeysStmt.ExecContext(ctx, cutoff) - if err != nil { - return 0, err - } - return res.RowsAffected() -} diff --git a/go/lib/drkey/drkeydbsqlite/lvl2db.go b/go/lib/drkey/drkeydbsqlite/lvl2db.go deleted file mode 100644 index a94b4b7eed..0000000000 --- a/go/lib/drkey/drkeydbsqlite/lvl2db.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkeydbsqlite - -import ( - "context" - "database/sql" - - _ "github.com/mattn/go-sqlite3" - - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/serrors" -) - -const ( - // Lvl2SchemaVersion is the version of the SQLite schema understood by this backend. - // Whenever changes to the schema are made, this version number should be increased - // to prevent data corruption between incompatible database schemas. - Lvl2SchemaVersion = 1 - // Lvl2Schema is the SQLite database layout. - Lvl2Schema = ` - CREATE TABLE DRKeyLvl2 ( - Protocol TEXT NOT NULL, - Type INTEGER NOT NULL, - SrcIsdID INTEGER NOT NULL, - SrcAsID INTEGER NOT NULL, - DstIsdID INTEGER NOT NULL, - DstAsID INTEGER NOT NULL, - SrcHostIP TEXT, - DstHostIP TEXT, - EpochBegin INTEGER NOT NULL, - EpochEnd INTEGER NOT NULL, - Key TEXT NOT NULL, - PRIMARY KEY (Protocol, Type, SrcIsdID, SrcAsID,` + - ` DstIsdID, DstAsID, SrcHostIP, DstHostIP, EpochBegin) - );` -) - -var _ drkey.Lvl2DB = (*Lvl2Backend)(nil) - -// Lvl2Backend implements a level 2 drkey DB with sqlite. -type Lvl2Backend struct { - dbBaseBackend - getLvl2KeyStmt *sql.Stmt - insertLvl2KeyStmt *sql.Stmt - removeOutdatedLvl2KeysStmt *sql.Stmt -} - -// NewLvl2Backend creates a database and prepares all statements. -func NewLvl2Backend(path string) (*Lvl2Backend, error) { - base, err := newBaseBackend(path, Lvl2Schema, Lvl2SchemaVersion) - if err != nil { - return nil, err - } - b := &Lvl2Backend{ - dbBaseBackend: *base, - } - stmts := preparedStmts{ - getLvl2Key: &b.getLvl2KeyStmt, - insertLvl2Key: &b.insertLvl2KeyStmt, - removeOutdatedLvl2Keys: &b.removeOutdatedLvl2KeysStmt, - } - if err := base.prepareAll(stmts); err != nil { - return nil, err - } - return b, nil -} - -const getLvl2Key = ` -SELECT EpochBegin, EpochEnd, Key -FROM DRKeyLvl2 WHERE Protocol=? AND Type=? AND SrcIsdID=? AND SrcAsID=? AND -DstIsdID=? AND DstAsID=? AND SrcHostIP=? AND DstHostIP=? -AND EpochBegin<=? AND ?= EpochEnd -` - -// RemoveOutdatedLvl2Keys removes all expired second level DRKeys, I.e. those keys -// which expiration time is strictly less than the cutoff -func (b *Lvl2Backend) RemoveOutdatedLvl2Keys(ctx context.Context, cutoff uint32) (int64, error) { - res, err := b.removeOutdatedLvl2KeysStmt.ExecContext(ctx, cutoff) - if err != nil { - return 0, err - } - return res.RowsAffected() -} diff --git a/go/lib/drkey/drkeyutil/util.go b/go/lib/drkey/drkeyutil/util.go deleted file mode 100644 index 35a542d84e..0000000000 --- a/go/lib/drkey/drkeyutil/util.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright 2021 ETH Zurich -// -// 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 drkeyutil - -import ( - "context" - "crypto/aes" - "crypto/subtle" - "sync" - "time" - - "github.com/dchest/cmac" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/log" - "github.com/scionproto/scion/go/lib/serrors" -) - -// ComputeAuthenticators returns the authenticators obtained to apply a MAC function to the -// same payload. -func ComputeAuthenticators(payload []byte, keys [][]byte) ([][]byte, error) { - auths := make([][]byte, len(keys)) - for i, k := range keys { - var err error - auths[i], err = MAC(payload, k) - if err != nil { - return nil, err - } - } - return auths, nil -} - -// ValidateAuthenticators validates each authenticators[i] against MAC(payload[i], keys[i]). -// Returns error if the MAC function returns any error, or true/false if each of the authenticators -// matches the result of each MAC function invocation. -func ValidateAuthenticators(payloads [][]byte, keys [][]byte, authenticators [][]byte) ( - bool, error) { - - if len(payloads) != len(keys) || len(keys) != len(authenticators) { - return false, serrors.New("wrong lengths (must be the same)") - } - for i := range keys { - mac, err := MAC(payloads[i], keys[i]) - if err != nil { - return false, serrors.WrapStr("MAC function", err) - } - if subtle.ConstantTimeCompare(mac, authenticators[i]) != 1 { - return false, nil - } - } - return true, nil -} - -func MAC(payload []byte, key []byte) ([]byte, error) { - block, err := aes.NewCipher(key) - if err != nil { - return nil, serrors.WrapStr("initializing aes cipher", err) - } - mac, err := cmac.New(block) - if err != nil { - return nil, serrors.WrapStr("initializing cmac", err) - } - _, err = mac.Write(payload) - if err != nil { - return nil, serrors.WrapStr("preparing mac", err) - } - return mac.Sum(nil), nil -} - -// GetLvl2Keys gets the lvl2 keys with the functional options in the arguments. -// Example of use: keys,err := GetLvl2Keys(AS2AS, "colibri", SlowIAs(slow),FastIAs(fast)) -func GetLvl2Keys(ctx context.Context, conn DRKeyGetLvl2Keyer, - keyType drkey.Lvl2KeyType, protocol string, - options ...keyOptsModifier) ([][]byte, error) { - - opts := &lvl2GetterOptions{ - ctx: ctx, - connector: conn, - keyType: keyType, - protocol: protocol, - } - for _, mod := range options { - mod(opts) - } - return getLvl2Keys(opts) -} - -func SlowIAs(ias ...addr.IA) keyOptsModifier { - return func(op *lvl2GetterOptions) { - op.slowIAs = make([]addr.IA, len(ias)) - copy(op.slowIAs, ias) - } -} - -func SlowHosts(hosts ...addr.HostAddr) keyOptsModifier { - return func(op *lvl2GetterOptions) { - op.slowHosts = make([]addr.HostAddr, len(hosts)) - copy(op.slowHosts, hosts) - } -} - -func FastIAs(ias ...addr.IA) keyOptsModifier { - return func(op *lvl2GetterOptions) { - op.fastIAs = make([]addr.IA, len(ias)) - copy(op.fastIAs, ias) - } -} - -func FastHosts(hosts ...addr.HostAddr) keyOptsModifier { - return func(op *lvl2GetterOptions) { - op.fastHosts = make([]addr.HostAddr, len(hosts)) - copy(op.fastHosts, hosts) - } -} - -type keyOptsModifier func(*lvl2GetterOptions) - -type lvl2GetterOptions struct { - ctx context.Context - connector DRKeyGetLvl2Keyer - keyType drkey.Lvl2KeyType - protocol string - slowIAs []addr.IA - fastIAs []addr.IA - slowHosts []addr.HostAddr - fastHosts []addr.HostAddr -} - -func getLvl2Keys(opts *lvl2GetterOptions) ([][]byte, error) { - // check number of hosts is enough, and concordance with IAs length - switch opts.keyType { - case drkey.Host2Host: - if len(opts.fastHosts) != len(opts.fastIAs) { - panic("wrong number of hosts/IAs in the fast side") - } - fallthrough - case drkey.AS2Host: - if len(opts.slowHosts) != len(opts.slowIAs) { - panic("wrong number of hosts/IAs in the slow side") - } - fallthrough - case drkey.AS2AS: - if (len(opts.fastIAs) > 1 && len(opts.slowIAs) > 1 && - len(opts.fastIAs) != len(opts.slowIAs)) || - len(opts.fastIAs) < 1 || len(opts.slowIAs) < 1 { - panic("specify 1 fast side and n slow, n fast and 1 slow, or n fast and n slow " + - "(n fast and m slow is not allowed)") - } - } - // check no more hosts than needed - switch opts.keyType { - case drkey.AS2AS: - if len(opts.slowHosts) > 0 { - panic("no slow hosts allowed for this key type") - } - fallthrough - case drkey.AS2Host: - if len(opts.fastHosts) > 0 { - panic("no fast hosts allowed for this key type") - } - } - - // functions to extend IAs and hosts: - extendIAs := func(ias *[]addr.IA, length int) { - if len(*ias) < length { - master := (*ias)[0] - *ias = make([]addr.IA, length) - for i := 0; i < length; i++ { - (*ias)[i] = master - } - } - } - extendHosts := func(hosts *[]addr.HostAddr, length int) { - if len(*hosts) < length { - var master addr.HostAddr = addr.HostNone{} - if len(*hosts) > 0 { - master = (*hosts)[0] - } - *hosts = make([]addr.HostAddr, length) - for i := 0; i < length; i++ { - (*hosts)[i] = master - } - } - } - // we make everything the same length - length := len(opts.fastIAs) - if len(opts.slowIAs) > length { - length = len(opts.slowIAs) - extendIAs(&opts.fastIAs, length) - } else { - extendIAs(&opts.slowIAs, length) - } - extendHosts(&opts.slowHosts, length) - extendHosts(&opts.fastHosts, length) - - metas := make([]drkey.Lvl2Meta, length) - for i := 0; i < length; i++ { - metas[i] = drkey.Lvl2Meta{ - KeyType: opts.keyType, - Protocol: opts.protocol, - SrcIA: opts.fastIAs[i], - DstIA: opts.slowIAs[i], - SrcHost: opts.fastHosts[i], - DstHost: opts.slowHosts[i], - } - } - - return getKeys(opts.ctx, opts.connector, time.Now(), metas) -} - -type DRKeyGetLvl2Keyer interface { - DRKeyGetLvl2Key(context.Context, drkey.Lvl2Meta, time.Time) (drkey.Lvl2Key, error) -} - -func getKeys(ctx context.Context, conn DRKeyGetLvl2Keyer, valTime time.Time, - metas []drkey.Lvl2Meta) ([][]byte, error) { - keys := make([][]byte, len(metas)) - errs := serrors.List{} - wg := sync.WaitGroup{} - wg.Add(len(metas)) - for i, meta := range metas { - i, meta := i, meta - go func() { - defer log.HandlePanic() - defer wg.Done() - k, err := conn.DRKeyGetLvl2Key(ctx, meta, valTime) - if err != nil { - errs = append(errs, err) - } - keys[i] = k.Key - }() - } - wg.Wait() - return keys, errs.ToError() -} diff --git a/go/lib/drkey/epoch.go b/go/lib/drkey/epoch.go deleted file mode 100644 index 082feacfdc..0000000000 --- a/go/lib/drkey/epoch.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018 ETH Zurich -// -// 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 drkey - -import ( - "time" - - "github.com/scionproto/scion/go/lib/scrypto/cppki" - "github.com/scionproto/scion/go/lib/util" -) - -// Epoch represents a validity period. -type Epoch struct { - cppki.Validity -} - -// Equal returns true if both Epochs are identical. -func (e Epoch) Equal(other Epoch) bool { - return e.NotBefore == other.NotBefore && - e.NotAfter == other.NotAfter -} - -// NewEpoch constructs an Epoch from its uint32 encoded begin and end parts. -func NewEpoch(begin, end uint32) Epoch { - return Epoch{ - cppki.Validity{ - NotBefore: util.SecsToTime(begin).UTC(), - NotAfter: util.SecsToTime(end).UTC(), - }, - } -} - -// Contains indicates whether the time point is inside this Epoch. -func (e *Epoch) Contains(t time.Time) bool { - return e.Validity.Contains(t) -} diff --git a/go/lib/drkey/exchange/BUILD.bazel b/go/lib/drkey/exchange/BUILD.bazel deleted file mode 100644 index 4b16531fdd..0000000000 --- a/go/lib/drkey/exchange/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("//lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["grpc.go"], - importpath = "github.com/scionproto/scion/go/lib/drkey/exchange", - visibility = ["//visibility:public"], - deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/scrypto/cppki:go_default_library", - "//go/lib/serrors:go_default_library", - "@org_golang_google_grpc//credentials:go_default_library", - "@org_golang_google_grpc//peer:go_default_library", - ], -) diff --git a/go/lib/drkey/exchange/grpc.go b/go/lib/drkey/exchange/grpc.go deleted file mode 100644 index a7f8b4b0c4..0000000000 --- a/go/lib/drkey/exchange/grpc.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 exchange - -import ( - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/peer" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/scrypto/cppki" - "github.com/scionproto/scion/go/lib/serrors" -) - -func ExtractIAFromPeer(peer *peer.Peer) (addr.IA, error) { - tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo) - if !ok { - return 0, serrors.New("auth info is not of type TLS info", - "peer", peer, "authType", peer.AuthInfo.AuthType()) - } - chain := tlsInfo.State.PeerCertificates - certIA, err := cppki.ExtractIA(chain[0].Subject) - if err != nil { - return 0, serrors.WrapStr("extracting IA from peer cert", err) - } - return certIA, nil -} diff --git a/go/lib/drkey/drkeyutil/BUILD.bazel b/go/lib/drkey/fake/BUILD.bazel similarity index 59% rename from go/lib/drkey/drkeyutil/BUILD.bazel rename to go/lib/drkey/fake/BUILD.bazel index ae6b66452a..06faffcfb2 100644 --- a/go/lib/drkey/drkeyutil/BUILD.bazel +++ b/go/lib/drkey/fake/BUILD.bazel @@ -2,14 +2,13 @@ load("//lint:go.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["util.go"], - importpath = "github.com/scionproto/scion/go/lib/drkey/drkeyutil", + srcs = ["fake.go"], + importpath = "github.com/scionproto/scion/go/lib/drkey/fake", visibility = ["//visibility:public"], deps = [ "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/log:go_default_library", + "//go/lib/scrypto/cppki:go_default_library", "//go/lib/serrors:go_default_library", - "@com_github_dchest_cmac//:go_default_library", ], ) diff --git a/go/lib/drkey/fake/fake.go b/go/lib/drkey/fake/fake.go new file mode 100644 index 0000000000..99fc10afb3 --- /dev/null +++ b/go/lib/drkey/fake/fake.go @@ -0,0 +1,125 @@ +// Copyright 2021 ETH Zurich +// +// 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 fake provides fake DRKeys for testing. +// Note: not all key types are currently supported, simply because there is +// currently no need. +package fake + +import ( + "context" + "encoding/binary" + "math/rand" + "net" + "time" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/serrors" +) + +// Keyer allows to obtain fake keys with the same interface as the daemon. +type Keyer struct { + LocalIA addr.IA + LocalIP net.IP +} + +func (k Keyer) DRKeyGetASHostKey(_ context.Context, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + + if meta.DstIA != k.LocalIA { + return drkey.ASHostKey{}, serrors.New("invalid request, req.dstIA != localIA", + "req.dstIA", meta.DstIA, "localIA", k.LocalIA) + } + dstIP := net.ParseIP(meta.DstHost) + if !k.LocalIP.Equal(dstIP) { + return drkey.ASHostKey{}, serrors.New("invalid request, req.dstHost != local IP", + "req.dstHost", meta.DstHost, "local IP", k.LocalIP) + } + return ASHost(meta), nil +} + +// Epoch returns the issuer's epoch containing the validity timestamp. +// Note that different issuers can use different epochs (e.g. different lengths +// or different start time). +func Epoch(issuer addr.IA, validity time.Time) drkey.Epoch { + r := rand.New(rand.NewSource(int64(issuer))) + epochLen := time.Duration(2+r.Intn(8)) * time.Second // very short epochs, 2-10s for testing + + epochStart := validity.Truncate(epochLen) + epochEnd := epochStart.Add(epochLen) + return drkey.Epoch{ + Validity: cppki.Validity{ + NotBefore: epochStart, + NotAfter: epochEnd, + }, + } +} + +// Lvl1Key builds a fake Level1 key. +func Lvl1Key(meta drkey.Lvl1Meta) drkey.Lvl1Key { + epoch := Epoch(meta.SrcIA, meta.Validity) + + const keyTypeLvl1 uint8 = 0 + var key drkey.Key + key[0] = keyTypeLvl1 + key[1] = byte(epoch.NotBefore.Second()) + key[2] = byte(meta.ProtoId) // truncated + // ISD truncated to 1 byte, AS truncated to 2 bytes. + // More than enough to represent the AS IDs usuually used in testing. + key[3] = byte(meta.SrcIA.ISD()) + binary.BigEndian.PutUint16(key[4:], uint16(meta.SrcIA.AS())) + key[6] = byte(meta.DstIA.ISD()) + binary.BigEndian.PutUint16(key[7:], uint16(meta.DstIA.AS())) + + return drkey.Lvl1Key{ + ProtoId: meta.ProtoId, + Epoch: epoch, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + Key: key, + } +} + +// Lvl1Key builds a fake ASHost key. +// This is _not_ properly derived from the fake Lvl1Key(). +func ASHost(meta drkey.ASHostMeta) drkey.ASHostKey { + epoch := Epoch(meta.SrcIA, meta.Validity) + + const keyTypeASHost uint8 = 2 + var key drkey.Key + key[0] = keyTypeASHost + key[1] = byte(epoch.NotBefore.Second()) + key[2] = byte(meta.ProtoId) // truncated + // ISD truncated to 1 byte, AS truncated to 2 bytes. + // More than enough to represent the AS IDs usuually used in testing. + key[3] = byte(meta.SrcIA.ISD()) + binary.BigEndian.PutUint16(key[4:], uint16(meta.SrcIA.AS())) + key[6] = byte(meta.DstIA.ISD()) + binary.BigEndian.PutUint16(key[7:], uint16(meta.DstIA.AS())) + + ip := net.ParseIP(meta.DstHost) + key[9] = byte(len(ip)) + copy(key[10:], ip[:]) + + return drkey.ASHostKey{ + ProtoId: meta.ProtoId, + Epoch: epoch, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + DstHost: meta.DstHost, + Key: key, + } +} diff --git a/go/lib/drkey/generic.go b/go/lib/drkey/generic.go new file mode 100644 index 0000000000..39c03f4263 --- /dev/null +++ b/go/lib/drkey/generic.go @@ -0,0 +1,78 @@ +// Copyright 2019 ETH Zurich +// +// 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 drkey + +import ( + "encoding/binary" + + "github.com/scionproto/scion/go/lib/serrors" +) + +// GenericDeriver implements the level 2/3 generic drkey derivation. +type GenericDeriver struct { + buf [32]byte +} + +func (p *GenericDeriver) inputDeriveLvl2(input []byte, derType keyType, + proto Protocol, host hostAddr) int { + hostAddr := host.RawAddr + l := len(hostAddr) + + // Calculate a multiple of 16 such that the input fits in + nrBlocks := (4+l-1)/16 + 1 + inputLength := 16 * nrBlocks + + _ = input[inputLength-1] + input[0] = uint8(derType) + binary.BigEndian.PutUint16(input[1:], uint16(proto)) + input[3] = uint8(host.AddrType&0x3)<<2 | uint8(host.AddrLen&0x3) + copy(input[4:], hostAddr) + copy(input[4+l:inputLength], zeroBlock[:]) + + return inputLength +} + +// DeriveASHost returns the ASHost derived key. +func (p *GenericDeriver) DeriveASHost(meta ASHostMeta, key Key) (Key, error) { + host, err := packtoHostAddr(meta.DstHost) + if err != nil { + return Key{}, serrors.WrapStr("parsing dst host", err) + } + len := p.inputDeriveLvl2(p.buf[:], asToHost, meta.ProtoId, host) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} + +// DeriveHostAS returns the HostAS derived key. +func (p *GenericDeriver) DeriveHostAS(meta HostASMeta, key Key) (Key, error) { + host, err := packtoHostAddr(meta.SrcHost) + if err != nil { + return Key{}, serrors.WrapStr("parsing src host", err) + } + len := p.inputDeriveLvl2(p.buf[:], hostToAS, meta.ProtoId, host) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} + +// DeriveHostToHost returns the HostHost derived key. +func (p *GenericDeriver) DeriveHostToHost(dstHost string, key Key) (Key, error) { + host, err := packtoHostAddr(dstHost) + if err != nil { + return Key{}, serrors.WrapStr("deriving input H2H", err) + } + len := inputDeriveHostToHost(p.buf[:], host) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} diff --git a/go/lib/drkey/level1.go b/go/lib/drkey/level1.go deleted file mode 100644 index 8d25571eab..0000000000 --- a/go/lib/drkey/level1.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkey - -import ( - "bytes" - - "github.com/scionproto/scion/go/lib/addr" -) - -// Lvl1Meta represents the information about a level 1 DRKey other than the key itself. -type Lvl1Meta struct { - Epoch Epoch - SrcIA addr.IA - DstIA addr.IA -} - -// Equal returns true if both meta are identical. -func (m Lvl1Meta) Equal(other Lvl1Meta) bool { - return m.Epoch.Equal(other.Epoch) && m.SrcIA.Equal(other.SrcIA) && m.DstIA.Equal(other.DstIA) -} - -// Lvl1Key represents a level 1 DRKey. -type Lvl1Key struct { - Lvl1Meta - Key DRKey -} - -// Equal returns true if both level 1 keys are identical. -func (k Lvl1Key) Equal(other Lvl1Key) bool { - return k.Lvl1Meta.Equal(other.Lvl1Meta) && bytes.Equal(k.Key, other.Key) -} diff --git a/go/lib/drkey/level2.go b/go/lib/drkey/level2.go deleted file mode 100644 index 9f4b9f5dbf..0000000000 --- a/go/lib/drkey/level2.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkey - -import ( - "bytes" - - "github.com/scionproto/scion/go/lib/addr" -) - -// Lvl2KeyType represents the different types of level 2 DRKeys (AS->AS, AS->host, host->host). -type Lvl2KeyType uint8 - -// Lvl2KeyType constants -const ( - AS2AS Lvl2KeyType = iota - AS2Host - Host2Host -) - -// Lvl2Meta represents the information about a level 2 DRKey, without the key itself. -type Lvl2Meta struct { - KeyType Lvl2KeyType - Protocol string - Epoch Epoch - SrcIA addr.IA - DstIA addr.IA - SrcHost addr.HostAddr - DstHost addr.HostAddr -} - -// Equal returns true if both meta are identical. -func (m Lvl2Meta) Equal(other Lvl2Meta) bool { - return m.KeyType == other.KeyType && m.Protocol == other.Protocol && - m.Epoch.Equal(other.Epoch) && m.SrcIA.Equal(other.SrcIA) && m.DstIA.Equal(other.DstIA) && - m.SrcHost.Equal(other.SrcHost) && m.DstHost.Equal(other.DstHost) -} - -// Lvl2Key represents a level 2 DRKey. -type Lvl2Key struct { - Lvl2Meta - Key DRKey -} - -// Equal returns true if both level 2 keys are identical. -func (k Lvl2Key) Equal(other Lvl2Key) bool { - return k.Lvl2Meta.Equal(other.Lvl2Meta) && bytes.Equal(k.Key, other.Key) -} - -// DelegationSecret is similar to a level 2 key, type AS to AS. -type DelegationSecret struct { - Protocol string - Epoch Epoch - SrcIA addr.IA - DstIA addr.IA - Key DRKey -} diff --git a/go/lib/drkey/metrics.go b/go/lib/drkey/metrics.go new file mode 100644 index 0000000000..7b4826a3c1 --- /dev/null +++ b/go/lib/drkey/metrics.go @@ -0,0 +1,383 @@ +// Copyright 2021 ETH Zurich +// +// 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 drkey + +import ( + "context" + "fmt" + "sync" + "time" + + "github.com/opentracing/opentracing-go" + "github.com/prometheus/client_golang/prometheus" + + dblib "github.com/scionproto/scion/go/lib/infra/modules/db" + "github.com/scionproto/scion/go/lib/prom" + "github.com/scionproto/scion/go/lib/tracing" +) + +const ( + svNamespace = "secretValueDB" + lvl1Namespace = "drkeyLvl1DB" + lvl2Namespace = "drkeyLvl2DB" + + promDBName = "db" +) + +type promOp string + +const ( + promOpGetSV promOp = "get_sv" + promOpInsertSV promOp = "insert_sv" + promOpRemoveOutdatedSV promOp = "remove_outdated_sv" + promOpGetLvl1Key promOp = "get_lvl1_key" + promOpInsertLvl1Key promOp = "insert_lvl1_key" + promOpRemoveOutdatedLvl1Keys promOp = "remove_outdated_lvl1_keys" + promOpGetASHostKey promOp = "get_as_host_key" + promOpInsertASHostKey promOp = "insert_as_host_key" + promOpGetHostASKey promOp = "get_host_as_key" + promOpInsertHostASKey promOp = "insert_as_host_key" + promOpGetHostHostKey promOp = "get_host_host_key" + promOpInsertHostHostKey promOp = "insert_host_host_key" + promOpRemoveOutdatedLvl2Keys promOp = "remove_outdated_lvl2_keys" +) + +var ( + queriesSVTotal *prometheus.CounterVec + resultsSVTotal *prometheus.CounterVec + queriesLvl1Total *prometheus.CounterVec + resultsLvl1Total *prometheus.CounterVec + queriesLvl2Total *prometheus.CounterVec + resultsLvl2Total *prometheus.CounterVec + + initMetricsSVOnce sync.Once + initMetricsLvl1Once sync.Once + initMetricsLvl2Once sync.Once +) + +func initMetricsSV() { + initMetricsSVOnce.Do(func() { + queriesSVTotal = prom.NewCounterVec(svNamespace, "", "queries_total", + "Total queries to the SecretValueDB.", []string{promDBName, prom.LabelOperation}) + resultsSVTotal = prom.NewCounterVec(svNamespace, "", "results_total", + "The results of the SecretValueDB ops.", + []string{promDBName, prom.LabelResult, prom.LabelOperation}) + }) +} + +func initMetricsLvl1() { + initMetricsLvl1Once.Do(func() { + queriesLvl1Total = prom.NewCounterVec(lvl1Namespace, "", "queries_total", + "Total queries to the lvl1DRKeyDB.", []string{promDBName, prom.LabelOperation}) + resultsLvl1Total = prom.NewCounterVec(lvl1Namespace, "", "results_total", + "The results of the lvl1DRKeyDB ops.", + []string{promDBName, prom.LabelResult, prom.LabelOperation}) + }) +} + +func initMetricsLvl2() { + initMetricsLvl2Once.Do(func() { + queriesLvl2Total = prom.NewCounterVec(lvl2Namespace, "", "queries_total", + "Total queries to the lvl2DRKeyDB.", []string{promDBName, prom.LabelOperation}) + resultsLvl2Total = prom.NewCounterVec(lvl2Namespace, "", "results_total", + "The results of the lvl2DRKeyDB ops.", + []string{promDBName, prom.LabelResult, prom.LabelOperation}) + }) +} + +// SVWithMetrics wraps the given SecretValueDB into one that also exports metrics. +func SVWithMetrics(dbName string, svdb SecretValueDB) SecretValueDB { + initMetricsSV() + labels := prometheus.Labels{promDBName: dbName} + return &MetricsSVDB{ + db: svdb, + metrics: &countersSV{ + queriesSVTotal: queriesSVTotal.MustCurryWith(labels), + resultsSVTotal: resultsSVTotal.MustCurryWith(labels), + }, + } +} + +type countersSV struct { + queriesSVTotal *prometheus.CounterVec + resultsSVTotal *prometheus.CounterVec +} + +func (c *countersSV) Observe(ctx context.Context, op promOp, + action func(ctx context.Context) error) { + span, ctx := opentracing.StartSpanFromContext(ctx, fmt.Sprintf("drkeySVDB.%s", string(op))) + defer span.Finish() + c.queriesSVTotal.WithLabelValues(string(op)).Inc() + err := action(ctx) + + label := dblib.ErrToMetricLabel(err) + tracing.Error(span, err) + tracing.ResultLabel(span, label) + + c.resultsSVTotal.WithLabelValues(label, string(op)).Inc() +} + +var _ SecretValueDB = (*MetricsSVDB)(nil) + +// MetricsSVDB is a SecretValueDB wrapper that exports the counts of operations as +// prometheus metrics +type MetricsSVDB struct { + db SecretValueDB + metrics *countersSV +} + +func (db *MetricsSVDB) SetMaxOpenConns(maxOpenConns int) { + db.db.SetMaxOpenConns(maxOpenConns) +} + +func (db *MetricsSVDB) SetMaxIdleConns(maxIdleConns int) { + db.db.SetMaxIdleConns(maxIdleConns) +} + +func (db *MetricsSVDB) Close() error { + return db.db.Close() +} + +func (db *MetricsSVDB) GetSV(ctx context.Context, meta SVMeta) (SV, error) { + var ret SV + var err error + db.metrics.Observe(ctx, promOpGetSV, func(ctx context.Context) error { + ret, err = db.db.GetSV(ctx, meta) + return err + }) + return ret, err +} + +func (db *MetricsSVDB) InsertSV(ctx context.Context, sv SV) error { + var err error + db.metrics.Observe(ctx, promOpInsertSV, func(ctx context.Context) error { + err = db.db.InsertSV(ctx, sv) + return err + }) + return err +} + +func (db *MetricsSVDB) DeleteExpiredSV(ctx context.Context, cutoff time.Time) (int64, error) { + var ret int64 + var err error + db.metrics.Observe(ctx, promOpRemoveOutdatedSV, func(ctx context.Context) error { + ret, err = db.db.DeleteExpiredSV(ctx, cutoff) + return err + }) + return ret, err +} + +// Lvl1WithMetrics wraps the given Lvl1DRKeyDB into one that also exports metrics. +func Lvl1WithMetrics(dbName string, lvl1db Lvl1DB) Lvl1DB { + initMetricsLvl1() + labels := prometheus.Labels{promDBName: dbName} + return &MetricsLvl1DB{ + db: lvl1db, + metrics: &countersLvl1{ + queriesLvl1Total: queriesLvl1Total.MustCurryWith(labels), + resultsLvl1Total: resultsLvl1Total.MustCurryWith(labels), + }, + } +} + +type countersLvl1 struct { + queriesLvl1Total *prometheus.CounterVec + resultsLvl1Total *prometheus.CounterVec +} + +func (c *countersLvl1) Observe(ctx context.Context, op promOp, + action func(ctx context.Context) error) { + span, ctx := opentracing.StartSpanFromContext(ctx, fmt.Sprintf("drkeyLvl1DB.%s", string(op))) + defer span.Finish() + c.queriesLvl1Total.WithLabelValues(string(op)).Inc() + err := action(ctx) + + label := dblib.ErrToMetricLabel(err) + tracing.Error(span, err) + tracing.ResultLabel(span, label) + + c.resultsLvl1Total.WithLabelValues(label, string(op)).Inc() +} + +var _ Lvl1DB = (*MetricsLvl1DB)(nil) + +// MetricsLvl1DB is a Lvl1DB wrapper that exports the counts of operations as prometheus metrics +type MetricsLvl1DB struct { + db Lvl1DB + metrics *countersLvl1 +} + +func (db *MetricsLvl1DB) SetMaxOpenConns(maxOpenConns int) { + db.db.SetMaxOpenConns(maxOpenConns) +} + +func (db *MetricsLvl1DB) SetMaxIdleConns(maxIdleConns int) { + db.db.SetMaxIdleConns(maxIdleConns) +} + +func (db *MetricsLvl1DB) Close() error { + return db.db.Close() +} + +func (db *MetricsLvl1DB) GetLvl1Key(ctx context.Context, meta Lvl1Meta) (Lvl1Key, error) { + var ret Lvl1Key + var err error + db.metrics.Observe(ctx, promOpGetLvl1Key, func(ctx context.Context) error { + ret, err = db.db.GetLvl1Key(ctx, meta) + return err + }) + return ret, err +} + +func (db *MetricsLvl1DB) InsertLvl1Key(ctx context.Context, key Lvl1Key) error { + var err error + db.metrics.Observe(ctx, promOpInsertLvl1Key, func(ctx context.Context) error { + err = db.db.InsertLvl1Key(ctx, key) + return err + }) + return err +} + +func (db *MetricsLvl1DB) DeleteExpiredLvl1Keys(ctx context.Context, + cutoff time.Time) (int64, error) { + var ret int64 + var err error + db.metrics.Observe(ctx, promOpRemoveOutdatedLvl1Keys, func(ctx context.Context) error { + ret, err = db.db.DeleteExpiredLvl1Keys(ctx, cutoff) + return err + }) + return ret, err +} + +// Lvl2WithMetrics wraps the given Lvl2DRKeyDB into one that also exports metrics. +func Lvl2WithMetrics(dbName string, lvl2db Lvl2DB) Lvl2DB { + initMetricsLvl2() + labels := prometheus.Labels{promDBName: dbName} + return &MetricsLvl2DB{ + db: lvl2db, + metrics: &countersLvl2{ + queriesLvl2Total: queriesLvl2Total.MustCurryWith(labels), + resultsLvl2Total: resultsLvl2Total.MustCurryWith(labels), + }, + } +} + +type countersLvl2 struct { + queriesLvl2Total *prometheus.CounterVec + resultsLvl2Total *prometheus.CounterVec +} + +func (c *countersLvl2) Observe(ctx context.Context, op promOp, + action func(ctx context.Context) error) { + span, ctx := opentracing.StartSpanFromContext(ctx, fmt.Sprintf("drkeyLvl2DB.%s", string(op))) + defer span.Finish() + c.queriesLvl2Total.WithLabelValues(string(op)).Inc() + err := action(ctx) + + label := dblib.ErrToMetricLabel(err) + tracing.Error(span, err) + tracing.ResultLabel(span, label) + + c.resultsLvl2Total.WithLabelValues(label, string(op)).Inc() +} + +var _ Lvl2DB = (*MetricsLvl2DB)(nil) + +// MetricsLvl2DB is a Lvl2DB wrapper that exports the counts of operations as prometheus metrics +type MetricsLvl2DB struct { + db Lvl2DB + metrics *countersLvl2 +} + +func (db *MetricsLvl2DB) SetMaxOpenConns(maxOpenConns int) { + db.db.SetMaxOpenConns(maxOpenConns) +} + +func (db *MetricsLvl2DB) SetMaxIdleConns(maxIdleConns int) { + db.db.SetMaxIdleConns(maxIdleConns) +} + +func (db *MetricsLvl2DB) Close() error { + return db.db.Close() +} + +func (db *MetricsLvl2DB) GetASHostKey(ctx context.Context, meta ASHostMeta) (ASHostKey, error) { + var ret ASHostKey + var err error + db.metrics.Observe(ctx, promOpGetASHostKey, func(ctx context.Context) error { + ret, err = db.db.GetASHostKey(ctx, meta) + return err + }) + return ret, err +} + +func (db *MetricsLvl2DB) InsertASHostKey(ctx context.Context, key ASHostKey) error { + var err error + db.metrics.Observe(ctx, promOpInsertASHostKey, func(ctx context.Context) error { + err = db.db.InsertASHostKey(ctx, key) + return err + }) + return err +} + +func (db *MetricsLvl2DB) GetHostASKey(ctx context.Context, meta HostASMeta) (HostASKey, error) { + var ret HostASKey + var err error + db.metrics.Observe(ctx, promOpGetHostASKey, func(ctx context.Context) error { + ret, err = db.db.GetHostASKey(ctx, meta) + return err + }) + return ret, err +} + +func (db *MetricsLvl2DB) InsertHostASKey(ctx context.Context, key HostASKey) error { + var err error + db.metrics.Observe(ctx, promOpInsertHostASKey, func(ctx context.Context) error { + err = db.db.InsertHostASKey(ctx, key) + return err + }) + return err +} + +func (db *MetricsLvl2DB) GetHostHostKey(ctx context.Context, + meta HostHostMeta) (HostHostKey, error) { + var ret HostHostKey + var err error + db.metrics.Observe(ctx, promOpGetHostHostKey, func(ctx context.Context) error { + ret, err = db.db.GetHostHostKey(ctx, meta) + return err + }) + return ret, err +} + +func (db *MetricsLvl2DB) InsertHostHostKey(ctx context.Context, key HostHostKey) error { + var err error + db.metrics.Observe(ctx, promOpInsertHostHostKey, func(ctx context.Context) error { + err = db.db.InsertHostHostKey(ctx, key) + return err + }) + return err +} + +func (db *MetricsLvl2DB) DeleteExpiredLvl2Keys(ctx context.Context, + cutoff time.Time) (int64, error) { + var ret int64 + var err error + db.metrics.Observe(ctx, promOpRemoveOutdatedLvl2Keys, func(ctx context.Context) error { + ret, err = db.db.DeleteExpiredLvl2Keys(ctx, cutoff) + return err + }) + return ret, err +} diff --git a/go/lib/drkey/metrics_test.go b/go/lib/drkey/metrics_test.go new file mode 100644 index 0000000000..6b3bb577d6 --- /dev/null +++ b/go/lib/drkey/metrics_test.go @@ -0,0 +1,113 @@ +// Copyright 2021 ETH Zurich +// +// 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 drkey_test + +import ( + "context" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/drkey/dbtest" + "github.com/scionproto/scion/go/lib/drkey/sqlite" +) + +var _ dbtest.TestableSVDB = (*TestSVBackend)(nil) + +type TestSVBackend struct { + drkey.SecretValueDB +} + +func (b *TestSVBackend) Prepare(t *testing.T, _ context.Context) { + db := newSVDatabase(t) + b.SecretValueDB = drkey.SVWithMetrics("testdb", db) +} + +func TestSVDBSuite(t *testing.T) { + tdb := &TestSVBackend{} + dbtest.TestSecretValueDB(t, tdb) +} + +func newSVDatabase(t *testing.T) *sqlite.SVBackend { + dir := t.TempDir() + file, err := ioutil.TempFile(dir, "db-test-") + require.NoError(t, err) + name := file.Name() + err = file.Close() + require.NoError(t, err) + db, err := sqlite.NewSVBackend(name) + require.NoError(t, err) + return db +} + +var _ dbtest.TestableLvl1DB = (*TestLvl1Backend)(nil) + +type TestLvl1Backend struct { + drkey.Lvl1DB +} + +func (b *TestLvl1Backend) Prepare(t *testing.T, _ context.Context) { + db := newLvl1Database(t) + b.Lvl1DB = drkey.Lvl1WithMetrics("testdb", db) +} + +func TestLvl1DBSuite(t *testing.T) { + tdb := &TestLvl1Backend{} + dbtest.TestLvl1(t, tdb) +} + +func newLvl1Database(t *testing.T) *sqlite.Lvl1Backend { + dir := t.TempDir() + file, err := ioutil.TempFile(dir, "db-test-") + require.NoError(t, err) + name := file.Name() + err = file.Close() + require.NoError(t, err) + db, err := sqlite.NewLvl1Backend(name) + require.NoError(t, err) + + return db +} + +var _ dbtest.TestableLvl2DB = (*TestLvl2Backend)(nil) + +type TestLvl2Backend struct { + drkey.Lvl2DB +} + +func (b *TestLvl2Backend) Prepare(t *testing.T, _ context.Context) { + db := newLvl2Database(t) + b.Lvl2DB = drkey.Lvl2WithMetrics("testdb", db) +} + +func TestLvl2DBSuite(t *testing.T) { + tdb := &TestLvl2Backend{} + dbtest.TestLvl2(t, tdb) +} + +func newLvl2Database(t *testing.T) *sqlite.Lvl2Backend { + dir := t.TempDir() + file, err := ioutil.TempFile(dir, "db-test-") + require.NoError(t, err) + name := file.Name() + err = file.Close() + require.NoError(t, err) + db, err := sqlite.NewLvl2Backend(name) + require.NoError(t, err) + + return db +} diff --git a/go/lib/drkey/protocol.go b/go/lib/drkey/protocol.go new file mode 100644 index 0000000000..a820010753 --- /dev/null +++ b/go/lib/drkey/protocol.go @@ -0,0 +1,152 @@ +// Copyright 2019 ETH Zurich +// +// 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 drkey + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/binary" + "math" + "net" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/serrors" + sc_header "github.com/scionproto/scion/go/lib/slayers" +) + +// keyType represents the different types of keys (host->AS, AS->host, host->host). +type keyType uint8 + +// Key types. +const ( + asToAs keyType = iota + asToHost + hostToAS + hostToHost +) + +var ( + zeroBlock [aes.BlockSize]byte +) + +// hostAddr is the address representation of a host as defined in the SCION header. +type hostAddr struct { + AddrLen sc_header.AddrLen + AddrType sc_header.AddrType + RawAddr []byte +} + +// packtoHostAddr returns a HostAddr parsing a given address in string format. +func packtoHostAddr(host string) (hostAddr, error) { + // trying IP + ipAddr := addr.HostFromIPStr(host) + if ipAddr != nil { + if ip := ipAddr.IP().To4(); ip != nil { + return hostAddr{ + AddrLen: sc_header.AddrLen4, + AddrType: sc_header.T4Ip, + RawAddr: ip, + }, nil + } + return hostAddr{ + AddrLen: sc_header.AddrLen16, + AddrType: sc_header.T16Ip, + RawAddr: ipAddr.IP(), + }, nil + } + // trying SVC + svcAddr := addr.HostSVCFromString(host) + if svcAddr != addr.SvcNone { + return hostAddr{ + AddrLen: sc_header.AddrLen4, + AddrType: sc_header.T4Svc, + RawAddr: svcAddr.PackWithPad(2), + }, nil + } + return hostAddr{}, serrors.New("unsupported address", "addr", host) +} + +// AddrToString returns the string representation of the HostAddr. +func (h *hostAddr) AddrToString() string { + switch h.AddrLen { + case sc_header.AddrLen4: + switch h.AddrType { + case sc_header.T4Ip: + addr := &net.IPAddr{IP: net.IP(h.RawAddr)} + return addr.String() + case sc_header.T4Svc: + addr := addr.HostSVC(binary.BigEndian.Uint16(h.RawAddr[:addr.HostLenSVC])) + return addr.String() + } + case sc_header.AddrLen16: + switch h.AddrType { + case sc_header.T16Ip: + addr := &net.IPAddr{IP: net.IP(h.RawAddr)} + return addr.String() + } + } + return "" +} + +// Equal returns returns true if both HostAddresses are equal. +func (h *hostAddr) Equal(other *hostAddr) bool { + return h.AddrLen == other.AddrLen && h.AddrType == other.AddrType && + bytes.Equal(h.RawAddr, other.RawAddr) +} + +func inputDeriveHostToHost(input []byte, host hostAddr) int { + hostAddr := host.RawAddr + l := len(hostAddr) + + // Calculate a multiple of 16 such that the input fits in + nrBlocks := int(math.Ceil((2 + float64(l)) / 16)) + inputLength := 16 * nrBlocks + + _ = input[inputLength-1] + input[0] = uint8(hostToHost) + input[1] = uint8(host.AddrType&0x3)<<2 | uint8(host.AddrLen&0x3) + copy(input[2:], hostAddr) + copy(input[2+l:inputLength], zeroBlock[:]) + + return inputLength +} + +// DeriveKey derives the following key given an input and a higher-level key. +// The input buffer is overwritten. +func deriveKey(input []byte, inputLen int, upKey Key) (Key, error) { + var key Key + b, err := initAESCBC(upKey[:]) + if err != nil { + return key, err + } + mac := cbcMac(b, input[:inputLen]) + copy(key[:], mac) + return key, nil +} + +func initAESCBC(key []byte) (cipher.BlockMode, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, serrors.New("Unable to initialize AES cipher") + } + mode := cipher.NewCBCEncrypter(block, zeroBlock[:]) + return mode, nil +} + +func cbcMac(block cipher.BlockMode, b []byte) []byte { + block.CryptBlocks(b, b) + return b[len(b)-aes.BlockSize:] +} diff --git a/go/lib/drkey/protocol/BUILD.bazel b/go/lib/drkey/protocol/BUILD.bazel deleted file mode 100644 index 4e86998456..0000000000 --- a/go/lib/drkey/protocol/BUILD.bazel +++ /dev/null @@ -1,34 +0,0 @@ -load("//lint:go.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "colibri.go", - "delegated.go", - "piskes.go", - "protocol.go", - "scmp.go", - "standard.go", - ], - importpath = "github.com/scionproto/scion/go/lib/drkey/protocol", - visibility = ["//visibility:public"], - deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/scrypto:go_default_library", - "//go/lib/serrors:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["protocol_test.go"], - embed = [":go_default_library"], - deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/xtest:go_default_library", - "@com_github_stretchr_testify//assert:go_default_library", - "@com_github_stretchr_testify//require:go_default_library", - ], -) diff --git a/go/lib/drkey/protocol/colibri.go b/go/lib/drkey/protocol/colibri.go deleted file mode 100644 index 92b06ba7af..0000000000 --- a/go/lib/drkey/protocol/colibri.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2021 ETH Zurich -// -// 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 protocol - -import ( - "github.com/scionproto/scion/go/lib/drkey" -) - -var _ DelegatedDerivation = colibri{} - -func init() { - p := colibri{} - KnownDerivations[p.Name()] = p -} - -// colibri implements the derivation for the COLIBRI source authentication protocol. -type colibri struct{} - -// Name returns scmp. -func (colibri) Name() string { - return "colibri" -} - -// DeriveLvl2 uses the standard derivation. -func (colibri) DeriveLvl2(meta drkey.Lvl2Meta, key drkey.Lvl1Key) (drkey.Lvl2Key, error) { - return Delegated{}.DeriveLvl2(meta, key) -} - -func (colibri) DeriveLvl2FromDS(meta drkey.Lvl2Meta, ds drkey.DelegationSecret) ( - drkey.Lvl2Key, error) { - - return Delegated{}.DeriveLvl2FromDS(meta, ds) -} diff --git a/go/lib/drkey/protocol/delegated.go b/go/lib/drkey/protocol/delegated.go deleted file mode 100644 index dee491e1cc..0000000000 --- a/go/lib/drkey/protocol/delegated.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 protocol - -import ( - "errors" - - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/scrypto" - "github.com/scionproto/scion/go/lib/serrors" -) - -// Delegated implements the level 2 drkey derivation from level 1, without DS. It relies on the -// Standard implementation to derive the DS from the level 1 key. -type Delegated struct{} - -// DeriveLvl2 derives the level 2 DRKey without passing through a delegation secret. -func (p Delegated) DeriveLvl2(meta drkey.Lvl2Meta, key drkey.Lvl1Key) (drkey.Lvl2Key, error) { - metaForDS := meta - metaForDS.KeyType = drkey.AS2AS - dsKey, err := Standard{}.DeriveLvl2(metaForDS, key) - if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("Error deriving DS", err) - } - ds := drkey.DelegationSecret{ - Protocol: meta.Protocol, - Epoch: meta.Epoch, - SrcIA: meta.SrcIA, - DstIA: meta.DstIA, - Key: dsKey.Key, - } - return p.DeriveLvl2FromDS(meta, ds) -} - -// DeriveLvl2FromDS will derive the level 2 key from a delegation secret. -func (p Delegated) DeriveLvl2FromDS(meta drkey.Lvl2Meta, ds drkey.DelegationSecret) ( - drkey.Lvl2Key, error) { - - h, err := scrypto.InitMac([]byte(ds.Key)) - if err != nil { - return drkey.Lvl2Key{}, err - } - - pLen := 0 - buffs := [][]byte{} - // add to buffs in reverse order: - switch meta.KeyType { - case drkey.Host2Host: - if meta.SrcHost.Size() == 0 { - return drkey.Lvl2Key{}, errors.New("Level 2 DRKey requires a src host, but it is empty") - } - b := meta.SrcHost.Pack() - buffs = [][]byte{ - b, - {byte(len(b))}, - } - pLen += len(b) + 1 - fallthrough - case drkey.AS2Host: - if meta.DstHost.Size() == 0 { - return drkey.Lvl2Key{}, errors.New("Level 2 DRKey requires a dst host, but it is empty") - } - b := meta.DstHost.Pack() - buffs = append(buffs, - b, - []byte{byte(len(b))}) - pLen += len(b) + 1 - case drkey.AS2AS: - return drkey.Lvl2Key{ - Lvl2Meta: meta, - Key: ds.Key, - }, nil - default: - return drkey.Lvl2Key{}, serrors.New("Unknown DRKey type") - } - all := make([]byte, pLen) - pLen = 0 - for i := len(buffs) - 1; i >= 0; i-- { - copy(all[pLen:], buffs[i]) - pLen += len(buffs[i]) - } - h.Write(all) - return drkey.Lvl2Key{ - Lvl2Meta: meta, - Key: drkey.DRKey(h.Sum(nil)), - }, nil -} diff --git a/go/lib/drkey/protocol/piskes.go b/go/lib/drkey/protocol/piskes.go deleted file mode 100644 index 44bc88777d..0000000000 --- a/go/lib/drkey/protocol/piskes.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 protocol - -import ( - "github.com/scionproto/scion/go/lib/drkey" -) - -var _ DelegatedDerivation = piskes{} - -// piskes implements the derivation for the PISKES protocol. -type piskes struct{} - -// Name returns scmp. -func (piskes) Name() string { - return "piskes" -} - -// DeriveLvl2 uses the standard derivation. -func (piskes) DeriveLvl2(meta drkey.Lvl2Meta, key drkey.Lvl1Key) (drkey.Lvl2Key, error) { - return Delegated{}.DeriveLvl2(meta, key) -} - -func (piskes) DeriveLvl2FromDS(meta drkey.Lvl2Meta, ds drkey.DelegationSecret) ( - drkey.Lvl2Key, error) { - - return Delegated{}.DeriveLvl2FromDS(meta, ds) -} - -func init() { - p := piskes{} - KnownDerivations[p.Name()] = p -} diff --git a/go/lib/drkey/protocol/protocol.go b/go/lib/drkey/protocol/protocol.go deleted file mode 100644 index fec568ed0d..0000000000 --- a/go/lib/drkey/protocol/protocol.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 protocol - -import ( - "encoding/binary" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/scrypto" -) - -// Derivation specifies the interface to implement for a derivation method. -type Derivation interface { - Name() string - DeriveLvl2(meta drkey.Lvl2Meta, key drkey.Lvl1Key) (drkey.Lvl2Key, error) -} - -// DelegatedDerivation extends a Derivation with a derivation from a DS. -type DelegatedDerivation interface { - Derivation - DeriveLvl2FromDS(meta drkey.Lvl2Meta, ds drkey.DelegationSecret) (drkey.Lvl2Key, error) -} - -// KnownDerivations maps the derivation names to their implementations. -// Add a new derivation by inserting your protocol name and a `Derivation` type in the map. -var KnownDerivations = make(map[string]Derivation) - -// DeriveLvl1 constructs a new level 1 DRKey. -func DeriveLvl1(meta drkey.Lvl1Meta, sv drkey.SV) (drkey.Lvl1Key, error) { - mac, err := scrypto.InitMac([]byte(sv.Key)) - if err != nil { - return drkey.Lvl1Key{}, err - } - all := make([]byte, addr.IABytes) - binary.BigEndian.PutUint64(all, uint64(meta.DstIA)) - mac.Write(all) - return drkey.Lvl1Key{ - Lvl1Meta: meta, - Key: drkey.DRKey(mac.Sum(nil)), - }, nil -} diff --git a/go/lib/drkey/protocol/protocol_test.go b/go/lib/drkey/protocol/protocol_test.go deleted file mode 100644 index 82a8eda09a..0000000000 --- a/go/lib/drkey/protocol/protocol_test.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 protocol - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/xtest" -) - -func TestDeriveStandard(t *testing.T) { - lvl1 := getLvl1(t) - protoToKey := map[string][]byte{ - "foo": xtest.MustParseHexString("def3aa32ce47d4374469148b5c04fac5"), - "bar": xtest.MustParseHexString("8ada021cabf2b14765f468f3c8995edb"), - "fooo": xtest.MustParseHexString("7f8e507aecf38c09e4cb10a0ff0cc497"), - } - - for proto, key := range protoToKey { - meta := drkey.Lvl2Meta{ - Protocol: proto, - KeyType: drkey.AS2AS, - SrcIA: lvl1.SrcIA, - DstIA: lvl1.DstIA, - } - lvl2, err := Standard{}.DeriveLvl2(meta, lvl1) - require.NoError(t, err) - assert.EqualValues(t, key, lvl2.Key) - } - - dstHost := addr.HostFromIPStr("127.0.0.1") - protoToKey = map[string][]byte{ - "foo": xtest.MustParseHexString("84e628f7c9318d6831ff4f85827f7af3"), - "bar": xtest.MustParseHexString("f51fa0769a6e3d2b9570eefb788a92c0"), - "fooo": xtest.MustParseHexString("d88513be2ff73b11615053540146e960"), - } - for proto, key := range protoToKey { - meta := drkey.Lvl2Meta{ - Protocol: proto, - KeyType: drkey.AS2Host, - SrcIA: lvl1.SrcIA, - DstIA: lvl1.DstIA, - DstHost: dstHost, - } - lvl2, err := Standard{}.DeriveLvl2(meta, lvl1) - require.NoError(t, err) - assert.EqualValues(t, key, lvl2.Key) - } - - srcHost := addr.HostFromIPStr("127.0.0.2") - protoToKey = map[string][]byte{ - "foo": xtest.MustParseHexString("3ca3190844028277e05ebfaf3c2dd3b0"), - "bar": xtest.MustParseHexString("b0bc9ccbd6ca923bdfbad7d1ad358960"), - "fooo": xtest.MustParseHexString("5635ad5283cfe080e2c8e99e6c3306af"), - } - for proto, key := range protoToKey { - meta := drkey.Lvl2Meta{ - Protocol: proto, - KeyType: drkey.Host2Host, - SrcIA: lvl1.SrcIA, - DstIA: lvl1.DstIA, - SrcHost: srcHost, - DstHost: dstHost, - } - lvl2, err := Standard{}.DeriveLvl2(meta, lvl1) - require.NoError(t, err) - assert.EqualValues(t, key, lvl2.Key) - } -} - -func TestDeriveDelegated(t *testing.T) { - lvl1 := getLvl1(t) - for _, proto := range []string{"foo", "bar", "fooo"} { - meta := drkey.Lvl2Meta{ - Protocol: proto, - KeyType: drkey.AS2AS, - SrcIA: lvl1.SrcIA, - DstIA: lvl1.DstIA, - } - lvl2standard, err := Standard{}.DeriveLvl2(meta, lvl1) - require.NoError(t, err) - lvl2deleg, err := Delegated{}.DeriveLvl2(meta, lvl1) - require.NoError(t, err) - assert.Equal(t, lvl2standard.Key, lvl2deleg.Key) - } - - protoToLvl2 := map[string][]byte{ - "foo": xtest.MustParseHexString("b4279b032d7d81c38754ab7b253f5ac0"), - "bar": xtest.MustParseHexString("a30df8ad348bfce1ecdf1cf83c9e5265"), - "fooo": xtest.MustParseHexString("434817fb40cb602b36c80e88789aee46"), - } - for proto, key := range protoToLvl2 { - meta := drkey.Lvl2Meta{ - Protocol: proto, - KeyType: drkey.AS2Host, - SrcIA: lvl1.SrcIA, - DstIA: lvl1.DstIA, - DstHost: addr.HostFromIPStr("127.0.0.1"), - } - lvl2, err := Delegated{}.DeriveLvl2(meta, lvl1) - require.NoError(t, err) - assert.EqualValues(t, key, lvl2.Key) - } -} - -func TestDeriveDelegatedViaDS(t *testing.T) { - // derive DS and then derive key. Compare to derive directly key - lvl1Key := getLvl1(t) - meta := drkey.Lvl2Meta{ - Protocol: "piskes", - KeyType: drkey.AS2AS, - SrcIA: lvl1Key.SrcIA, - DstIA: lvl1Key.DstIA, - SrcHost: addr.HostNone{}, - DstHost: addr.HostNone{}, - } - lvl2Key, err := piskes{}.DeriveLvl2(meta, lvl1Key) - require.NoError(t, err) - ds := drkey.DelegationSecret{ - Protocol: lvl2Key.Protocol, - Epoch: lvl2Key.Epoch, - SrcIA: lvl2Key.SrcIA, - DstIA: lvl2Key.DstIA, - Key: lvl2Key.Key, - } - srcHost := addr.HostFromIPStr("1.1.1.1") - dstHost := addr.HostFromIPStr("2.2.2.2") - meta = drkey.Lvl2Meta{ - Protocol: meta.Protocol, - KeyType: drkey.Host2Host, - SrcIA: meta.SrcIA, - DstIA: meta.DstIA, - SrcHost: srcHost, - DstHost: dstHost, - } - lvl2KeyViaDS, err := piskes{}.DeriveLvl2FromDS(meta, ds) - require.NoError(t, err) - _ = lvl2KeyViaDS - // now get the level 2 key directly without explicitly going through DS - lvl2Key, err = piskes{}.DeriveLvl2(meta, lvl1Key) - require.NoError(t, err) - assert.Equal(t, lvl2Key, lvl2KeyViaDS) -} - -func getLvl1(t *testing.T) drkey.Lvl1Key { - meta := drkey.SVMeta{ - Epoch: drkey.NewEpoch(0, 1), - } - asSecret := []byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7} - svTgtKey := xtest.MustParseHexString("47bfbb7d94706dc9e79825e5a837b006") - epoch := drkey.NewEpoch(0, 1) - srcIA, _ := addr.ParseIA("1-ff00:0:111") - dstIA, _ := addr.ParseIA("1-ff00:0:112") - sv, err := drkey.DeriveSV(meta, asSecret) - require.NoError(t, err) - require.EqualValues(t, svTgtKey, sv.Key) - - lvlTgtKey := xtest.MustParseHexString("51663adbc06e55f40a9ad899cf0775e5") - lvl1, err := DeriveLvl1(drkey.Lvl1Meta{ - Epoch: epoch, - SrcIA: srcIA, - DstIA: dstIA, - }, sv) - require.NoError(t, err) - require.EqualValues(t, lvlTgtKey, lvl1.Key) - - return lvl1 -} - -func TestExistingImplementations(t *testing.T) { - // we test that we have the two implementations we know for now (scmp,piskes) - require.Len(t, KnownDerivations, 3) - require.Contains(t, KnownDerivations, "scmp") - require.Contains(t, KnownDerivations, "piskes") - require.Contains(t, KnownDerivations, "colibri") -} diff --git a/go/lib/drkey/protocol/scmp.go b/go/lib/drkey/protocol/scmp.go deleted file mode 100644 index a3b788aacd..0000000000 --- a/go/lib/drkey/protocol/scmp.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 protocol - -import ( - "github.com/scionproto/scion/go/lib/drkey" -) - -var _ Derivation = scmp{} - -// scmp implements the derivation for the SCMP protocol. -type scmp struct{} - -// Name returns scmp. -func (scmp) Name() string { - return "scmp" -} - -// DeriveLvl2 uses the standard derivation. -func (scmp) DeriveLvl2(meta drkey.Lvl2Meta, key drkey.Lvl1Key) (drkey.Lvl2Key, error) { - return Standard{}.DeriveLvl2(meta, key) -} - -func init() { - s := scmp{} - KnownDerivations[s.Name()] = s -} diff --git a/go/lib/drkey/protocol/standard.go b/go/lib/drkey/protocol/standard.go deleted file mode 100644 index 5c1a318f38..0000000000 --- a/go/lib/drkey/protocol/standard.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 protocol - -import ( - "errors" - - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/scrypto" - "github.com/scionproto/scion/go/lib/serrors" -) - -// TODO(juagargi) the standard derivation (in this file) and delegated one will be just -// functions: won't implement any interface in particular. The way to configure -// a new protocol will look like the SCMP or PISKES protocols: new type with their functions, and -// registration with the correct name. No configuration will be allowed to change this (the -// configuration file will not include any mapping protocol->derivation). - -// Standard implements the level 2 drkey derivation from level 1, without DS. -type Standard struct{} - -// DeriveLvl2 derives the level 2 DRKey without passing through a delegation secret. -func (p Standard) DeriveLvl2(meta drkey.Lvl2Meta, key drkey.Lvl1Key) (drkey.Lvl2Key, error) { - h, err := scrypto.InitMac([]byte(key.Key)) - if err != nil { - return drkey.Lvl2Key{}, err - } - - pLen := 0 - // add to buffs in reverse order: - buffs := [][]byte{} - switch meta.KeyType { - case drkey.Host2Host: - if meta.SrcHost.Size() == 0 { - return drkey.Lvl2Key{}, errors.New("Level 2 DRKey requires a src host, but it is empty") - } - b := meta.SrcHost.Pack() - buffs = [][]byte{ - b, - {byte(len(b))}, - } - pLen += len(b) + 1 - fallthrough - case drkey.AS2Host: - if meta.DstHost.Size() == 0 { - return drkey.Lvl2Key{}, errors.New("Level 2 DRKey requires a dst host, but it is empty") - } - b := meta.DstHost.Pack() - buffs = append(buffs, - b, - []byte{byte(len(b))}) - pLen += len(b) + 1 - fallthrough - case drkey.AS2AS: - b := []byte(meta.Protocol) - buffs = append(buffs, - []byte{byte(meta.KeyType)}, - b, - []byte{byte(len(b))}) - pLen += len(b) + 2 - default: - return drkey.Lvl2Key{}, serrors.New("Unknown DRKey type") - } - all := make([]byte, pLen) - pLen = 0 - for i := len(buffs) - 1; i >= 0; i-- { - copy(all[pLen:], buffs[i]) - pLen += len(buffs[i]) - } - h.Write(all) - return drkey.Lvl2Key{ - Lvl2Meta: meta, - Key: drkey.DRKey(h.Sum(nil)), - }, nil -} diff --git a/go/lib/drkey/protocol_test.go b/go/lib/drkey/protocol_test.go new file mode 100644 index 0000000000..9f371ecced --- /dev/null +++ b/go/lib/drkey/protocol_test.go @@ -0,0 +1,379 @@ +// Copyright 2019 ETH Zurich +// +// 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 drkey_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/drkey/protocoltest" + "github.com/scionproto/scion/go/lib/xtest" +) + +func TestDeriveASHostGeneric(t *testing.T) { + protoId := drkey.Generic + epoch := drkey.NewEpoch(0, 1) + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + lvl1Key := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + dstHost := "127.0.0.1" + + testCases := map[string]struct { + meta drkey.ASHostMeta + assertFormatErr assert.ErrorAssertionFunc + expectedKey drkey.Key + }{ + "wrong no-host": { + meta: drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + }, + assertFormatErr: assert.Error, + }, + "invalid as-host": { + meta: drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + DstHost: "", + }, + assertFormatErr: assert.Error, + }, + "valid as-host": { + meta: drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + DstHost: dstHost, + }, + assertFormatErr: assert.NoError, + expectedKey: drkey.Key{0x5d, 0xe0, 0xd2, 0x4d, 0x7f, 0xd0, + 0xab, 0x2e, 0xeb, 0x9d, 0x40, 0xb6, 0x23, 0x10, 0xbd, 0xd1}, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + key, err := protocoltest.DeriveASHostGeneric(tc.meta, lvl1Key) + tc.assertFormatErr(t, err) + if err == nil { + assert.EqualValues(t, tc.expectedKey, key.Key) + } + }) + } +} + +func TestDeriveGenericHostAS(t *testing.T) { + protoId := drkey.Generic + epoch := drkey.NewEpoch(0, 1) + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + lvl1Key := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + srcHost := "127.0.0.2" + testCases := map[string]struct { + meta drkey.HostASMeta + assertFormatErr assert.ErrorAssertionFunc + expectedKey drkey.Key + }{ + "valid host-as": { + meta: drkey.HostASMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: srcHost, + }, + assertFormatErr: assert.NoError, + expectedKey: drkey.Key{0xe4, 0x2e, 0xfc, 0x50, 0x1a, 0x21, + 0xdb, 0x6e, 0x14, 0x83, 0x88, 0x81, 0x9b, 0xb9, 0xd0, 0x18}, + }, + "invalid host-as": { + meta: drkey.HostASMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: "", + }, + assertFormatErr: assert.Error, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + key, err := protocoltest.DeriveHostASGeneric(tc.meta, lvl1Key) + tc.assertFormatErr(t, err) + if err == nil { + assert.EqualValues(t, tc.expectedKey, key.Key) + } + }) + } +} + +func TestDeriveGenericHostHost(t *testing.T) { + protoId := drkey.Generic + epoch := drkey.NewEpoch(0, 1) + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + lvl1Key := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + srcHost := "127.0.0.2" + dstHost := "127.0.0.1" + + testCases := map[string]struct { + meta drkey.HostHostMeta + assertFormatErr assert.ErrorAssertionFunc + expectedKey drkey.Key + }{ + "valid host-host": { + meta: drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: srcHost, + DstHost: dstHost, + }, + assertFormatErr: assert.NoError, + expectedKey: drkey.Key{0x56, 0xd0, 0x9, 0x4d, 0xe3, 0x3, + 0xf7, 0x3f, 0xf9, 0x25, 0x1a, 0x8b, 0x65, 0x23, 0x2f, 0x4}, + }, + "invalid host-host src": { + meta: drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: "", + DstHost: dstHost, + }, + assertFormatErr: assert.Error, + }, + "invalid host-host dst": { + meta: drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: srcHost, + DstHost: "", + }, + assertFormatErr: assert.Error, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + key, err := protocoltest.DeriveHostHostGeneric(tc.meta, lvl1Key) + tc.assertFormatErr(t, err) + if err == nil { + assert.EqualValues(t, tc.expectedKey, key.Key) + } + }) + } +} + +func TestDeriveASHostSpecific(t *testing.T) { + protoId := drkey.SCMP + epoch := drkey.NewEpoch(0, 1) + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + lvl1Key := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + dstHost := ("127.0.0.1") + + testCases := map[string]struct { + meta drkey.ASHostMeta + assertFormatErr assert.ErrorAssertionFunc + expectedKey drkey.Key + }{ + "wrong no-host": { + meta: drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + }, + assertFormatErr: assert.Error, + }, + "invalid as-host": { + meta: drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + DstHost: "", + }, + assertFormatErr: assert.Error, + }, + "valid as-host": { + meta: drkey.ASHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + DstHost: dstHost, + }, + assertFormatErr: assert.NoError, + expectedKey: drkey.Key{0xab, 0x5e, 0x5e, 0x58, 0xb7, 0x7e, 0xdc, + 0xb1, 0x88, 0xc1, 0x36, 0xb9, 0x7d, 0x61, 0xcb, 0xdd}, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + key, err := protocoltest.DeriveASHostSpecific(tc.meta, lvl1Key) + tc.assertFormatErr(t, err) + if err == nil { + assert.EqualValues(t, tc.expectedKey, key.Key) + } + }) + } +} + +func TestDeriveSpecificHostAS(t *testing.T) { + protoId := drkey.SCMP + epoch := drkey.NewEpoch(0, 1) + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + lvl1Key := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + srcHost := "127.0.0.2" + testCases := map[string]struct { + meta drkey.HostASMeta + assertFormatErr assert.ErrorAssertionFunc + expectedKey drkey.Key + }{ + "valid host-as": { + meta: drkey.HostASMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: srcHost, + }, + assertFormatErr: assert.NoError, + expectedKey: drkey.Key{0x36, 0x4e, 0xd4, 0x79, 0x2d, 0x6b, 0x7f, + 0x2d, 0xa2, 0xa9, 0xcb, 0xab, 0x8c, 0xa6, 0xcd, 0xcf}, + }, + "invalid host-as": { + meta: drkey.HostASMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: "", + }, + assertFormatErr: assert.Error, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + key, err := protocoltest.DeriveHostASSpecific(tc.meta, lvl1Key) + tc.assertFormatErr(t, err) + if err == nil { + assert.EqualValues(t, tc.expectedKey, key.Key) + } + }) + } +} + +func TestDeriveSpecificHostHost(t *testing.T) { + protoId := drkey.SCMP + epoch := drkey.NewEpoch(0, 1) + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + lvl1Key := protocoltest.GetLvl1(t, protoId, epoch, srcIA, dstIA) + srcHost := "127.0.0.2" + dstHost := "127.0.0.1" + + testCases := map[string]struct { + meta drkey.HostHostMeta + assertFormatErr assert.ErrorAssertionFunc + expectedKey drkey.Key + }{ + "valid host-host": { + meta: drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: srcHost, + DstHost: dstHost, + }, + assertFormatErr: assert.NoError, + expectedKey: drkey.Key{0x7f, 0x40, 0xc5, 0xe9, 0xdf, 0x22, 0x5a, + 0xe9, 0x93, 0x97, 0x91, 0xcc, 0x2a, 0x8f, 0xbc, 0xf7}, + }, + "invalid host-host src": { + meta: drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: "", + DstHost: dstHost, + }, + assertFormatErr: assert.Error, + }, + "invalid host-host dst": { + meta: drkey.HostHostMeta{ + Lvl2Meta: drkey.Lvl2Meta{ + ProtoId: drkey.Protocol(10000), + }, + SrcHost: srcHost, + DstHost: "", + }, + assertFormatErr: assert.Error, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + key, err := protocoltest.DeriveHostHostSpecific(tc.meta, lvl1Key) + tc.assertFormatErr(t, err) + if err == nil { + assert.EqualValues(t, tc.expectedKey, key.Key) + } + }) + } +} + +func TestDeriveLvl1(t *testing.T) { + asSecret := []byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7} + sv, err := drkey.DeriveSV(drkey.SCMP, drkey.NewEpoch(0, 1), asSecret) + require.NoError(t, err) + + deriver := &drkey.SpecificDeriver{} + + srcIA := xtest.MustParseIA("1-ff00:0:111") + dstIA := xtest.MustParseIA("1-ff00:0:112") + + lvl1Meta := drkey.Lvl1Meta{ + SrcIA: srcIA, + DstIA: dstIA, + ProtoId: drkey.SCMP, + } + lvl1Target := drkey.Key{0xa8, 0x23, 0xf5, 0xb9, 0x56, 0xde, + 0x7c, 0xc, 0xbc, 0x5a, 0x69, 0x42, 0xf5, 0xb6, 0xfc, 0x10} + + key, err := deriver.DeriveLvl1(lvl1Meta, sv.Key) + require.NoError(t, err) + assert.Equal(t, lvl1Target, key) + + // Calling a second time with the same deriver should yield the + // same key + key, err = deriver.DeriveLvl1(lvl1Meta, sv.Key) + require.NoError(t, err) + + assert.Equal(t, lvl1Target, key) + +} diff --git a/go/lib/drkey/test/BUILD.bazel b/go/lib/drkey/protocoltest/BUILD.bazel similarity index 58% rename from go/lib/drkey/test/BUILD.bazel rename to go/lib/drkey/protocoltest/BUILD.bazel index 4250127614..a828793263 100644 --- a/go/lib/drkey/test/BUILD.bazel +++ b/go/lib/drkey/protocoltest/BUILD.bazel @@ -2,12 +2,12 @@ load("//lint:go.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["mock_keys.go"], - importpath = "github.com/scionproto/scion/go/lib/drkey/test", + srcs = ["commons.go"], + importpath = "github.com/scionproto/scion/go/lib/drkey/protocoltest", visibility = ["//visibility:public"], deps = [ "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/xtest:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/go/lib/drkey/protocoltest/commons.go b/go/lib/drkey/protocoltest/commons.go new file mode 100644 index 0000000000..c169aa85d3 --- /dev/null +++ b/go/lib/drkey/protocoltest/commons.go @@ -0,0 +1,154 @@ +package protocoltest + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/drkey" +) + +func GetLvl1(t *testing.T, protoID drkey.Protocol, epoch drkey.Epoch, + srcIA, dstIA addr.IA) drkey.Lvl1Key { + asSecret := []byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7} + sv, err := drkey.DeriveSV(protoID, epoch, asSecret) + require.NoError(t, err) + + lvl1Meta := drkey.Lvl1Meta{ + SrcIA: srcIA, + DstIA: dstIA, + ProtoId: sv.ProtoId, + } + key, err := (&drkey.SpecificDeriver{}).DeriveLvl1(lvl1Meta, sv.Key) + require.NoError(t, err) + return drkey.Lvl1Key{ + Epoch: sv.Epoch, + SrcIA: srcIA, + DstIA: dstIA, + ProtoId: sv.ProtoId, + Key: key, + } +} + +func DeriveASHostGeneric(meta drkey.ASHostMeta, lvl1key drkey.Lvl1Key) (drkey.ASHostKey, error) { + + derivedKey, err := (&drkey.GenericDeriver{}).DeriveASHost(meta, lvl1key.Key) + if err != nil { + return drkey.ASHostKey{}, err + } + + return drkey.ASHostKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1key.Epoch, + SrcIA: lvl1key.SrcIA, + DstIA: lvl1key.DstIA, + DstHost: meta.DstHost, + Key: derivedKey, + }, nil +} + +func DeriveHostASGeneric(meta drkey.HostASMeta, lvl1key drkey.Lvl1Key) (drkey.HostASKey, error) { + derivedKey, err := (&drkey.GenericDeriver{}).DeriveHostAS(meta, lvl1key.Key) + if err != nil { + return drkey.HostASKey{}, err + } + + return drkey.HostASKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1key.Epoch, + SrcIA: lvl1key.SrcIA, + DstIA: lvl1key.DstIA, + SrcHost: meta.SrcHost, + Key: derivedKey, + }, nil +} + +func DeriveHostHostGeneric(meta drkey.HostHostMeta, + lvl1key drkey.Lvl1Key) (drkey.HostHostKey, error) { + + hostASMeta := drkey.HostASMeta{ + Lvl2Meta: meta.Lvl2Meta, + SrcHost: meta.SrcHost, + } + hostASKey, err := (&drkey.GenericDeriver{}).DeriveHostAS(hostASMeta, lvl1key.Key) + if err != nil { + return drkey.HostHostKey{}, err + } + h2hKey, err := (&drkey.GenericDeriver{}).DeriveHostToHost(meta.DstHost, hostASKey) + if err != nil { + return drkey.HostHostKey{}, err + } + + return drkey.HostHostKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1key.Epoch, + SrcIA: lvl1key.SrcIA, + DstIA: lvl1key.DstIA, + SrcHost: meta.SrcHost, + DstHost: meta.DstHost, + Key: h2hKey, + }, nil +} + +func DeriveASHostSpecific(meta drkey.ASHostMeta, lvl1key drkey.Lvl1Key) (drkey.ASHostKey, error) { + + derivedKey, err := (&drkey.SpecificDeriver{}).DeriveASHost(meta, lvl1key.Key) + if err != nil { + return drkey.ASHostKey{}, err + } + + return drkey.ASHostKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1key.Epoch, + SrcIA: lvl1key.SrcIA, + DstIA: lvl1key.DstIA, + DstHost: meta.DstHost, + Key: derivedKey, + }, nil +} + +func DeriveHostASSpecific(meta drkey.HostASMeta, lvl1key drkey.Lvl1Key) (drkey.HostASKey, error) { + + derivedKey, err := (&drkey.SpecificDeriver{}).DeriveHostAS(meta, lvl1key.Key) + if err != nil { + return drkey.HostASKey{}, err + } + + return drkey.HostASKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1key.Epoch, + SrcIA: lvl1key.SrcIA, + DstIA: lvl1key.DstIA, + SrcHost: meta.SrcHost, + Key: derivedKey, + }, nil +} + +func DeriveHostHostSpecific(meta drkey.HostHostMeta, + lvl1key drkey.Lvl1Key) (drkey.HostHostKey, error) { + + hostASMeta := drkey.HostASMeta{ + Lvl2Meta: meta.Lvl2Meta, + SrcHost: meta.SrcHost, + } + + hostASKey, err := (&drkey.SpecificDeriver{}).DeriveHostAS(hostASMeta, lvl1key.Key) + if err != nil { + return drkey.HostHostKey{}, err + } + h2hKey, err := (&drkey.SpecificDeriver{}).DeriveHostToHost(meta.DstHost, hostASKey) + if err != nil { + return drkey.HostHostKey{}, err + } + + return drkey.HostHostKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1key.Epoch, + SrcIA: lvl1key.SrcIA, + DstIA: lvl1key.DstIA, + SrcHost: meta.SrcHost, + DstHost: meta.DstHost, + Key: h2hKey, + }, nil +} diff --git a/go/lib/drkey/secret_value.go b/go/lib/drkey/secret_value.go deleted file mode 100644 index 9439712947..0000000000 --- a/go/lib/drkey/secret_value.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkey - -import ( - "bytes" - "crypto/sha256" - "encoding/binary" - "errors" - - "golang.org/x/crypto/pbkdf2" - - "github.com/scionproto/scion/go/lib/util" -) - -const drkeySalt = "Derive DRKey Key" // same as in Python - -// SVMeta represents the information about a DRKey secret value. -type SVMeta struct { - Epoch Epoch -} - -// SV represents a DRKey secret value. -type SV struct { - SVMeta - Key DRKey -} - -// Equal returns true if both secret values are identical. -func (sv SV) Equal(other SV) bool { - return sv.Epoch.Equal(other.Epoch) && bytes.Equal(sv.Key, other.Key) -} - -// DeriveSV constructs a valid SV. asSecret is typically the AS master secret. -func DeriveSV(meta SVMeta, asSecret []byte) (SV, error) { - msLen := len(asSecret) - if msLen == 0 { - return SV{}, errors.New("Invalid zero sized secret") - } - all := make([]byte, 1+msLen+8) - copy(all, []byte{byte(msLen)}) - copy(all[1:], asSecret) - binary.LittleEndian.PutUint32(all[msLen+1:], util.TimeToSecs(meta.Epoch.NotBefore)) - binary.LittleEndian.PutUint32(all[msLen+5:], util.TimeToSecs(meta.Epoch.NotAfter)) - - key := pbkdf2.Key(all, []byte(drkeySalt), 1000, 16, sha256.New) - return SV{ - SVMeta: meta, - Key: DRKey(key), - }, nil -} diff --git a/go/lib/drkey/secret_value_test.go b/go/lib/drkey/secret_value_test.go index f299dcebb8..f1e523ea3f 100644 --- a/go/lib/drkey/secret_value_test.go +++ b/go/lib/drkey/secret_value_test.go @@ -12,27 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -package drkey +package drkey_test import ( - "encoding/hex" "testing" - "github.com/scionproto/scion/go/lib/xtest" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/drkey" ) func TestDeriveSV(t *testing.T) { - meta := SVMeta{NewEpoch(0, 1)} + asSecret := []byte{0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7} - targetKey := xtest.MustParseHexString("47bfbb7d94706dc9e79825e5a837b006") + targetKey := drkey.Key{0xc3, 0xb4, 0x84, 0x3c, 0x99, 0x3, + 0x14, 0xf9, 0xac, 0x55, 0x4f, 0x9b, 0x78, 0x1c, 0xde, 0xb7} - got, err := DeriveSV(meta, asSecret) - if err != nil { - t.Errorf("DeriveSV() error = %v", err) - return - } - if !got.Key.Equal(targetKey) { - t.Fatalf("Unexpected sv key: %s, expected: %s", - hex.EncodeToString(got.Key), hex.EncodeToString(targetKey)) - } + got, err := drkey.DeriveSV(0, drkey.NewEpoch(0, 1), asSecret) + require.NoError(t, err) + require.EqualValues(t, targetKey, got.Key) } diff --git a/go/lib/drkey/specific.go b/go/lib/drkey/specific.go new file mode 100644 index 0000000000..173d84dfa3 --- /dev/null +++ b/go/lib/drkey/specific.go @@ -0,0 +1,94 @@ +// Copyright 2019 ETH Zurich +// +// 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 drkey + +import ( + "crypto/aes" + "encoding/binary" + + "github.com/scionproto/scion/go/lib/serrors" +) + +// SpecificDeriver implements the specific drkey derivation. +type SpecificDeriver struct { + buf [32]byte +} + +// DeriveLvl1 returns the Lvl1 derived key. +func (p *SpecificDeriver) DeriveLvl1(meta Lvl1Meta, key Key) (Key, error) { + len := inputDeriveLvl1(p.buf[:], meta) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} + +func inputDeriveLvl1(buf []byte, meta Lvl1Meta) int { + _ = buf[aes.BlockSize-1] + buf[0] = byte(asToAs) + binary.BigEndian.PutUint64(buf[1:], uint64(meta.DstIA)) + copy(buf[9:], zeroBlock[:]) + + return aes.BlockSize +} + +func (p *SpecificDeriver) inputDeriveLvl2(input []byte, derType keyType, + host hostAddr) int { + hostAddr := host.RawAddr + l := len(hostAddr) + + // Calculate a multiple of 16 such that the input fits in + nrBlocks := (2+l-1)/16 + 1 + inputLength := 16 * nrBlocks + + _ = input[inputLength-1] + input[0] = uint8(derType) + input[1] = uint8(host.AddrType&0x3)<<2 | uint8(host.AddrLen&0x3) + copy(input[2:], hostAddr) + copy(input[2+l:inputLength], zeroBlock[:]) + + return inputLength +} + +// DeriveASHost returns the ASHost derived key. +func (p *SpecificDeriver) DeriveASHost(meta ASHostMeta, key Key) (Key, error) { + host, err := packtoHostAddr(meta.DstHost) + if err != nil { + return Key{}, serrors.WrapStr("parsing dst host", err) + } + len := p.inputDeriveLvl2(p.buf[:], asToHost, host) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} + +// DeriveHostAS returns the HostAS derived key. +func (p *SpecificDeriver) DeriveHostAS(meta HostASMeta, key Key) (Key, error) { + host, err := packtoHostAddr(meta.SrcHost) + if err != nil { + return Key{}, serrors.WrapStr("parsing src host", err) + } + len := p.inputDeriveLvl2(p.buf[:], hostToAS, host) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} + +// DeriveHostToHost returns the HostHost derived key. +func (p *SpecificDeriver) DeriveHostToHost(dstHost string, key Key) (Key, error) { + host, err := packtoHostAddr(dstHost) + if err != nil { + return Key{}, serrors.WrapStr("deriving input H2H", err) + } + len := inputDeriveHostToHost(p.buf[:], host) + outKey, err := deriveKey(p.buf[:], len, key) + return outKey, err +} diff --git a/go/lib/drkey/drkeydbsqlite/BUILD.bazel b/go/lib/drkey/sqlite/BUILD.bazel similarity index 63% rename from go/lib/drkey/drkeydbsqlite/BUILD.bazel rename to go/lib/drkey/sqlite/BUILD.bazel index d4343ad534..289aa81ce3 100644 --- a/go/lib/drkey/drkeydbsqlite/BUILD.bazel +++ b/go/lib/drkey/sqlite/BUILD.bazel @@ -6,14 +6,14 @@ go_library( "base_db.go", "lvl1db.go", "lvl2db.go", + "sv_db.go", ], - importpath = "github.com/scionproto/scion/go/lib/drkey/drkeydbsqlite", + importpath = "github.com/scionproto/scion/go/lib/drkey/sqlite", visibility = ["//visibility:public"], deps = [ - "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", "//go/lib/infra/modules/db:go_default_library", - "//go/lib/serrors:go_default_library", + "//go/lib/util:go_default_library", "@com_github_mattn_go_sqlite3//:go_default_library", ], ) @@ -23,11 +23,7 @@ go_test( srcs = ["db_test.go"], embed = [":go_default_library"], deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/drkey/protocol:go_default_library", - "//go/lib/scrypto/cppki:go_default_library", - "//go/lib/util:go_default_library", + "//go/lib/drkey/dbtest:go_default_library", "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/go/lib/drkey/drkeydbsqlite/base_db.go b/go/lib/drkey/sqlite/base_db.go similarity index 65% rename from go/lib/drkey/drkeydbsqlite/base_db.go rename to go/lib/drkey/sqlite/base_db.go index fc391569a6..eeddb51b8c 100644 --- a/go/lib/drkey/drkeydbsqlite/base_db.go +++ b/go/lib/drkey/sqlite/base_db.go @@ -12,16 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -package drkeydbsqlite +package sqlite import ( "database/sql" _ "github.com/mattn/go-sqlite3" - "github.com/scionproto/scion/go/lib/drkey" "github.com/scionproto/scion/go/lib/infra/modules/db" - "github.com/scionproto/scion/go/lib/serrors" ) const ( @@ -29,8 +27,6 @@ const ( unableToExecuteStmt = "Unable to execute stmt" ) -var _ drkey.BaseDB = (*dbBaseBackend)(nil) - // dbBaseBackend is the common part of all level backends. type dbBaseBackend struct { db *sql.DB @@ -47,28 +43,6 @@ func newBaseBackend(path, schema string, version int) (*dbBaseBackend, error) { }, nil } -type preparedStmts map[string]**sql.Stmt - -// prepareAll will create the prepared statements or return an error as soon as one fails. -func (b *dbBaseBackend) prepareAll(stmts preparedStmts) error { - var err error - // On future errors, close the sql database before exiting - defer func() { - if err != nil { - b.Close() - } - }() - for str, stmt := range stmts { - // FIXME(matzf): the sqlclosecheck linter does not like this pattern. - // Perhapse this should be refactored to just avoid the prepared statements; - // this does not appear to be goroutine safe anyway. - if *stmt, err = b.db.Prepare(str); err != nil { // nolint:sqlclosecheck - return serrors.WrapStr(unableToPrepareStmt, err) - } - } - return nil -} - // Close closes the database connection. func (b *dbBaseBackend) Close() error { return b.db.Close() diff --git a/go/lib/drkey/sqlite/db_test.go b/go/lib/drkey/sqlite/db_test.go new file mode 100644 index 0000000000..08b416d693 --- /dev/null +++ b/go/lib/drkey/sqlite/db_test.go @@ -0,0 +1,109 @@ +// Copyright 2019 ETH Zurich +// +// 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 sqlite + +import ( + "context" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/drkey/dbtest" +) + +var _ dbtest.TestableSVDB = (*TestSVBackend)(nil) + +type TestSVBackend struct { + *SVBackend +} + +func (b *TestSVBackend) Prepare(t *testing.T, _ context.Context) { + db := newSVDatabase(t) + b.SVBackend = db +} + +func TestSVDBSuite(t *testing.T) { + tdb := &TestSVBackend{} + dbtest.TestSecretValueDB(t, tdb) +} + +func newSVDatabase(t *testing.T) *SVBackend { + dir := t.TempDir() + file, err := ioutil.TempFile(dir, "db-test-") + require.NoError(t, err) + name := file.Name() + err = file.Close() + require.NoError(t, err) + db, err := NewSVBackend(name) + require.NoError(t, err) + return db +} + +var _ dbtest.TestableLvl1DB = (*TestLvl1Backend)(nil) + +type TestLvl1Backend struct { + *Lvl1Backend +} + +func (b *TestLvl1Backend) Prepare(t *testing.T, _ context.Context) { + db := newLvl1Database(t) + b.Lvl1Backend = db +} + +func TestLvl1DBSuite(t *testing.T) { + tdb := &TestLvl1Backend{} + dbtest.TestLvl1(t, tdb) +} + +func newLvl1Database(t *testing.T) *Lvl1Backend { + dir := t.TempDir() + file, err := ioutil.TempFile(dir, "db-test-") + require.NoError(t, err) + name := file.Name() + err = file.Close() + require.NoError(t, err) + db, err := NewLvl1Backend(name) + require.NoError(t, err) + return db +} + +var _ dbtest.TestableLvl2DB = (*TestLvl2Backend)(nil) + +type TestLvl2Backend struct { + *Lvl2Backend +} + +func (b *TestLvl2Backend) Prepare(t *testing.T, _ context.Context) { + db := newLvl2Database(t) + b.Lvl2Backend = db +} + +func TestLvl2DBSuite(t *testing.T) { + tdb := &TestLvl2Backend{} + dbtest.TestLvl2(t, tdb) +} + +func newLvl2Database(t *testing.T) *Lvl2Backend { + dir := t.TempDir() + file, err := ioutil.TempFile(dir, "db-test-") + require.NoError(t, err) + name := file.Name() + err = file.Close() + require.NoError(t, err) + db, err := NewLvl2Backend(name) + require.NoError(t, err) + return db +} diff --git a/go/lib/drkey/sqlite/lvl1db.go b/go/lib/drkey/sqlite/lvl1db.go new file mode 100644 index 0000000000..5ece9f1faf --- /dev/null +++ b/go/lib/drkey/sqlite/lvl1db.go @@ -0,0 +1,132 @@ +// Copyright 2019 ETH Zurich +// +// 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 sqlite + +import ( + "context" + "database/sql" + "time" + + _ "github.com/mattn/go-sqlite3" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/infra/modules/db" + "github.com/scionproto/scion/go/lib/util" +) + +const ( + // Lvl1SchemaVersion is the version of the SQLite schema understood by this backend. + // Whenever changes to the schema are made, this version number should be increased + // to prevent data corruption between incompatible database schemas. + Lvl1SchemaVersion = 1 + // Lvl1Schema is the SQLite database layout. + Lvl1Schema = ` + CREATE TABLE DRKeyLvl1 ( + SrcIsdID INTEGER NOT NULL, + SrcAsID INTEGER NOT NULL, + DstIsdID INTEGER NOT NULL, + DstAsID INTEGER NOT NULL, + Protocol INTEGER NOT NULL, + EpochBegin INTEGER NOT NULL, + EpochEnd INTEGER NOT NULL, + Key BLOB NOT NULL, + PRIMARY KEY (SrcIsdID, SrcAsID, DstIsdID, DstAsID, Protocol, EpochBegin) + );` +) + +var _ drkey.Lvl1DB = (*Lvl1Backend)(nil) + +// Lvl1Backend implements a level 1 drkey DB with sqlite. +type Lvl1Backend struct { + dbBaseBackend +} + +// NewLvl1Backend creates a database and prepares all statements. +func NewLvl1Backend(path string) (*Lvl1Backend, error) { + base, err := newBaseBackend(path, Lvl1Schema, Lvl1SchemaVersion) + if err != nil { + return nil, err + } + b := &Lvl1Backend{ + dbBaseBackend: *base, + } + return b, nil +} + +const getLvl1Key = ` +SELECT EpochBegin, EpochEnd, Key FROM DRKeyLvl1 +WHERE SrcIsdID=? AND SrcAsID=? AND DstIsdID=? AND DstAsID=? +AND Protocol=? +AND EpochBegin<=? AND ?= EpochEnd +` + +// RemoveOutdatedLvl1Keys removes all expired lvl1 key, i.e. all the keys +// which expiration time is strictly smaller than the cutoff +func (b *Lvl1Backend) DeleteExpiredLvl1Keys(ctx context.Context, cutoff time.Time) (int64, error) { + cutoffSecs := util.TimeToSecs(cutoff) + res, err := b.db.ExecContext(ctx, deleteExpiredLvl1Keys, cutoffSecs) + if err != nil { + return 0, db.NewWriteError("deleting outdated lvl1 key", err) + } + return res.RowsAffected() +} diff --git a/go/lib/drkey/sqlite/lvl2db.go b/go/lib/drkey/sqlite/lvl2db.go new file mode 100644 index 0000000000..62ba92128e --- /dev/null +++ b/go/lib/drkey/sqlite/lvl2db.go @@ -0,0 +1,311 @@ +// Copyright 2019 ETH Zurich +// +// 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 sqlite + +import ( + "context" + "database/sql" + "time" + + _ "github.com/mattn/go-sqlite3" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/infra/modules/db" + "github.com/scionproto/scion/go/lib/util" +) + +const ( + // Lvl2SchemaVersion is the version of the SQLite schema understood by this backend. + // Whenever changes to the schema are made, this version number should be increased + // to prevent data corruption between incompatible database schemas. + Lvl2SchemaVersion = 1 + // Lvl2Schema is the SQLite database layout. + Lvl2Schema = ` + CREATE TABLE ASHost ( + Protocol INTEGER NOT NULL, + SrcIsdID INTEGER NOT NULL, + SrcAsID INTEGER NOT NULL, + DstIsdID INTEGER NOT NULL, + DstAsID INTEGER NOT NULL, + DstHostIP TEXT, + EpochBegin INTEGER NOT NULL, + EpochEnd INTEGER NOT NULL, + Key BLOB NOT NULL, + PRIMARY KEY (Protocol, SrcIsdID, SrcAsID,` + + ` DstIsdID, DstAsID, DstHostIP, EpochBegin) + ); + + CREATE TABLE HostAS ( + Protocol INTEGER NOT NULL, + SrcIsdID INTEGER NOT NULL, + SrcAsID INTEGER NOT NULL, + DstIsdID INTEGER NOT NULL, + DstAsID INTEGER NOT NULL, + SrcHostIP TEXT, + EpochBegin INTEGER NOT NULL, + EpochEnd INTEGER NOT NULL, + Key BLOB NOT NULL, + PRIMARY KEY (Protocol, SrcIsdID, SrcAsID,` + + ` DstIsdID, DstAsID, SrcHostIP, EpochBegin) + ); + + CREATE TABLE HostHost ( + Protocol INTEGER NOT NULL, + SrcIsdID INTEGER NOT NULL, + SrcAsID INTEGER NOT NULL, + DstIsdID INTEGER NOT NULL, + DstAsID INTEGER NOT NULL, + SrcHostIP TEXT, + DstHostIP TEXT, + EpochBegin INTEGER NOT NULL, + EpochEnd INTEGER NOT NULL, + Key BLOB NOT NULL, + PRIMARY KEY (Protocol, SrcIsdID, SrcAsID,` + + ` DstIsdID, DstAsID, SrcHostIP, DstHostIP, EpochBegin) + ); + ` +) + +var _ drkey.Lvl2DB = (*Lvl2Backend)(nil) + +// Lvl2Backend implements a level 2 drkey DB with sqlite. +type Lvl2Backend struct { + dbBaseBackend +} + +// NewLvl2Backend creates a database and prepares all statements. +func NewLvl2Backend(path string) (*Lvl2Backend, error) { + base, err := newBaseBackend(path, Lvl2Schema, Lvl2SchemaVersion) + if err != nil { + return nil, err + } + b := &Lvl2Backend{ + dbBaseBackend: *base, + } + return b, nil +} + +const getASHostKey = ` +SELECT EpochBegin, EpochEnd, Key +FROM ASHost WHERE Protocol=? AND SrcIsdID=? AND SrcAsID=? AND +DstIsdID=? AND DstAsID=? AND DstHostIP=? +AND EpochBegin<=? AND ?= EpochEnd; +DELETE FROM HostAS WHERE ? >= EpochEnd; +DELETE FROM HostHost WHERE ? >= EpochEnd; +` + +// RemoveOutdatedLvl2Keys removes all expired lvl2/3 keys, i.e. those keys +// which expiration time is strictly less than the cutoff +func (b *Lvl2Backend) DeleteExpiredLvl2Keys(ctx context.Context, cutoff time.Time) (int64, error) { + // XXX(JordiSubira): It only returns the removed rows for the last statement. + // We might want to change this return value. + cutoffSecs := util.TimeToSecs(cutoff) + res, err := b.db.ExecContext(ctx, deleteExpiredLvl2Keys, cutoffSecs, cutoffSecs, cutoffSecs) + if err != nil { + return 0, db.NewWriteError("deleting outdated lvl2 key", err) + } + return res.RowsAffected() +} diff --git a/go/lib/drkey/sqlite/sv_db.go b/go/lib/drkey/sqlite/sv_db.go new file mode 100644 index 0000000000..6bfb366206 --- /dev/null +++ b/go/lib/drkey/sqlite/sv_db.go @@ -0,0 +1,117 @@ +// Copyright 2021 ETH Zurich +// +// 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 sqlite + +import ( + "context" + "database/sql" + "time" + + _ "github.com/mattn/go-sqlite3" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/infra/modules/db" + "github.com/scionproto/scion/go/lib/util" +) + +const ( + SVSchemaVersion = 1 + SVSchema = ` + CREATE TABLE DRKeySV ( + Protocol INTEGER NOT NULL, + EpochBegin INTEGER NOT NULL, + EpochEnd INTEGER NOT NULL, + Key BLOB NOT NULL, + PRIMARY KEY (Protocol, EpochBegin) + );` +) + +var _ drkey.SecretValueDB = (*SVBackend)(nil) + +// SVBackend implements a SV DB with sqlite. +type SVBackend struct { + dbBaseBackend +} + +// NewSVBackend creates a database and prepares all statements. +func NewSVBackend(path string) (*SVBackend, error) { + base, err := newBaseBackend(path, SVSchema, SVSchemaVersion) + if err != nil { + return nil, err + } + b := &SVBackend{ + dbBaseBackend: *base, + } + return b, nil +} + +const getSV = ` +SELECT EpochBegin, EpochEnd, Key FROM DRKeySV +WHERE Protocol=? +AND EpochBegin<=? AND ?= EpochEnd +` + +// RemoveOutdatedSV removes all expired SVs, i.e. all the keys +// which expiration time is strictly smaller than the cutoff +func (b *SVBackend) DeleteExpiredSV(ctx context.Context, cutoff time.Time) (int64, error) { + cutoffSecs := util.TimeToSecs(cutoff) + res, err := b.db.ExecContext(ctx, deleteExpiredSV, cutoffSecs) + if err != nil { + return 0, db.NewWriteError("deleting outdated SVs", err) + } + return res.RowsAffected() +} diff --git a/go/lib/drkey/test/mock_keys.go b/go/lib/drkey/test/mock_keys.go deleted file mode 100644 index 92cf0cf1b8..0000000000 --- a/go/lib/drkey/test/mock_keys.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2021 ETH Zurich -// -// 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 test - -import ( - "encoding/binary" - "testing" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/xtest" -) - -type KeyMap map[fastSlow]drkey.Lvl2Key - -type fastSlow struct { - fast addr.IA - slow addr.IA -} - -func GetKey(keyMap KeyMap, fastIA, slowIA addr.IA) (drkey.Lvl2Key, bool) { - k, ok := keyMap[fastSlow{fast: fastIA, slow: slowIA}] - return k, ok -} - -func MockKeys1SlowSide(t *testing.T, slowIA string, fastIAs ...string) KeyMap { - return mockKeysManyFast(t, drkey.AS2AS, slowIA, addr.HostNone{}, fastIAs...) -} - -func MockKeys1SlowSideWithHost(t *testing.T, slowIA, slowHost string, - fastIAs ...string) KeyMap { - - sHost := addr.HostFromIP(xtest.MustParseIP(t, slowHost)) - return mockKeysManyFast(t, drkey.AS2Host, slowIA, sHost, fastIAs...) -} - -func mockKeysManyFast(t *testing.T, keyType drkey.Lvl2KeyType, slowIA string, sHost addr.HostAddr, - fastIAs ...string) KeyMap { - - t.Helper() - sIA := xtest.MustParseIA(slowIA) - m := make(KeyMap) - for _, fast := range fastIAs { - fIA := xtest.MustParseIA(fast) - m[fastSlow{fast: fIA, slow: sIA}] = mockKey(keyType, fIA, sIA, sHost) - } - return m -} - -func mockKey(keyType drkey.Lvl2KeyType, fast, slow addr.IA, slowhost addr.HostAddr) drkey.Lvl2Key { - k := xtest.MustParseHexString("0123456789abcdef0123456789abcdef") // 16 bytes - binary.BigEndian.PutUint64(k[:8], uint64(fast)) - binary.BigEndian.PutUint64(k[8:], uint64(slow)) - return drkey.Lvl2Key{ - Lvl2Meta: drkey.Lvl2Meta{ - KeyType: keyType, - Protocol: "colibri", - Epoch: drkey.NewEpoch(0, 100), - SrcIA: fast, - DstIA: slow, - DstHost: slowhost, - }, - Key: k, - } -} diff --git a/go/lib/drkeystorage/BUILD.bazel b/go/lib/drkeystorage/BUILD.bazel deleted file mode 100644 index 9e5640db1f..0000000000 --- a/go/lib/drkeystorage/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -load("//lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["store.go"], - importpath = "github.com/scionproto/scion/go/lib/drkeystorage", - visibility = ["//visibility:public"], - deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/infra/modules/cleaner:go_default_library", - ], -) diff --git a/go/lib/drkeystorage/mock_drkeystorage/BUILD.bazel b/go/lib/drkeystorage/mock_drkeystorage/BUILD.bazel deleted file mode 100644 index 63e11eaaf9..0000000000 --- a/go/lib/drkeystorage/mock_drkeystorage/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -load("//lint:go.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["store.go"], - importpath = "github.com/scionproto/scion/go/lib/drkeystorage/mock_drkeystorage", - visibility = ["//visibility:public"], - deps = [ - "//go/lib/addr:go_default_library", - "//go/lib/drkey:go_default_library", - "@com_github_golang_mock//gomock:go_default_library", - ], -) diff --git a/go/lib/drkeystorage/mock_drkeystorage/store.go b/go/lib/drkeystorage/mock_drkeystorage/store.go deleted file mode 100644 index 19c5ee3564..0000000000 --- a/go/lib/drkeystorage/mock_drkeystorage/store.go +++ /dev/null @@ -1,226 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/go/lib/drkeystorage (interfaces: SecretValueFactory,BaseStore,ServiceStore,ClientStore) - -// Package mock_drkeystorage is a generated GoMock package. -package mock_drkeystorage - -import ( - context "context" - gomock "github.com/golang/mock/gomock" - addr "github.com/scionproto/scion/go/lib/addr" - drkey "github.com/scionproto/scion/go/lib/drkey" - reflect "reflect" - time "time" -) - -// MockSecretValueFactory is a mock of SecretValueFactory interface -type MockSecretValueFactory struct { - ctrl *gomock.Controller - recorder *MockSecretValueFactoryMockRecorder -} - -// MockSecretValueFactoryMockRecorder is the mock recorder for MockSecretValueFactory -type MockSecretValueFactoryMockRecorder struct { - mock *MockSecretValueFactory -} - -// NewMockSecretValueFactory creates a new mock instance -func NewMockSecretValueFactory(ctrl *gomock.Controller) *MockSecretValueFactory { - mock := &MockSecretValueFactory{ctrl: ctrl} - mock.recorder = &MockSecretValueFactoryMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockSecretValueFactory) EXPECT() *MockSecretValueFactoryMockRecorder { - return m.recorder -} - -// GetSecretValue mocks base method -func (m *MockSecretValueFactory) GetSecretValue(arg0 time.Time) (drkey.SV, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSecretValue", arg0) - ret0, _ := ret[0].(drkey.SV) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSecretValue indicates an expected call of GetSecretValue -func (mr *MockSecretValueFactoryMockRecorder) GetSecretValue(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretValue", reflect.TypeOf((*MockSecretValueFactory)(nil).GetSecretValue), arg0) -} - -// MockBaseStore is a mock of BaseStore interface -type MockBaseStore struct { - ctrl *gomock.Controller - recorder *MockBaseStoreMockRecorder -} - -// MockBaseStoreMockRecorder is the mock recorder for MockBaseStore -type MockBaseStoreMockRecorder struct { - mock *MockBaseStore -} - -// NewMockBaseStore creates a new mock instance -func NewMockBaseStore(ctrl *gomock.Controller) *MockBaseStore { - mock := &MockBaseStore{ctrl: ctrl} - mock.recorder = &MockBaseStoreMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockBaseStore) EXPECT() *MockBaseStoreMockRecorder { - return m.recorder -} - -// DeleteExpiredKeys mocks base method -func (m *MockBaseStore) DeleteExpiredKeys(arg0 context.Context) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteExpiredKeys", arg0) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteExpiredKeys indicates an expected call of DeleteExpiredKeys -func (mr *MockBaseStoreMockRecorder) DeleteExpiredKeys(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteExpiredKeys", reflect.TypeOf((*MockBaseStore)(nil).DeleteExpiredKeys), arg0) -} - -// MockServiceStore is a mock of ServiceStore interface -type MockServiceStore struct { - ctrl *gomock.Controller - recorder *MockServiceStoreMockRecorder -} - -// MockServiceStoreMockRecorder is the mock recorder for MockServiceStore -type MockServiceStoreMockRecorder struct { - mock *MockServiceStore -} - -// NewMockServiceStore creates a new mock instance -func NewMockServiceStore(ctrl *gomock.Controller) *MockServiceStore { - mock := &MockServiceStore{ctrl: ctrl} - mock.recorder = &MockServiceStoreMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockServiceStore) EXPECT() *MockServiceStoreMockRecorder { - return m.recorder -} - -// DeleteExpiredKeys mocks base method -func (m *MockServiceStore) DeleteExpiredKeys(arg0 context.Context) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteExpiredKeys", arg0) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteExpiredKeys indicates an expected call of DeleteExpiredKeys -func (mr *MockServiceStoreMockRecorder) DeleteExpiredKeys(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteExpiredKeys", reflect.TypeOf((*MockServiceStore)(nil).DeleteExpiredKeys), arg0) -} - -// DeriveLvl1 mocks base method -func (m *MockServiceStore) DeriveLvl1(arg0 addr.IA, arg1 time.Time) (drkey.Lvl1Key, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeriveLvl1", arg0, arg1) - ret0, _ := ret[0].(drkey.Lvl1Key) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeriveLvl1 indicates an expected call of DeriveLvl1 -func (mr *MockServiceStoreMockRecorder) DeriveLvl1(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeriveLvl1", reflect.TypeOf((*MockServiceStore)(nil).DeriveLvl1), arg0, arg1) -} - -// GetLvl1Key mocks base method -func (m *MockServiceStore) GetLvl1Key(arg0 context.Context, arg1 drkey.Lvl1Meta, arg2 time.Time) (drkey.Lvl1Key, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLvl1Key", arg0, arg1, arg2) - ret0, _ := ret[0].(drkey.Lvl1Key) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLvl1Key indicates an expected call of GetLvl1Key -func (mr *MockServiceStoreMockRecorder) GetLvl1Key(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl1Key", reflect.TypeOf((*MockServiceStore)(nil).GetLvl1Key), arg0, arg1, arg2) -} - -// KnownASes mocks base method -func (m *MockServiceStore) KnownASes(arg0 context.Context) ([]addr.IA, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "KnownASes", arg0) - ret0, _ := ret[0].([]addr.IA) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// KnownASes indicates an expected call of KnownASes -func (mr *MockServiceStoreMockRecorder) KnownASes(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KnownASes", reflect.TypeOf((*MockServiceStore)(nil).KnownASes), arg0) -} - -// MockClientStore is a mock of ClientStore interface -type MockClientStore struct { - ctrl *gomock.Controller - recorder *MockClientStoreMockRecorder -} - -// MockClientStoreMockRecorder is the mock recorder for MockClientStore -type MockClientStoreMockRecorder struct { - mock *MockClientStore -} - -// NewMockClientStore creates a new mock instance -func NewMockClientStore(ctrl *gomock.Controller) *MockClientStore { - mock := &MockClientStore{ctrl: ctrl} - mock.recorder = &MockClientStoreMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockClientStore) EXPECT() *MockClientStoreMockRecorder { - return m.recorder -} - -// DeleteExpiredKeys mocks base method -func (m *MockClientStore) DeleteExpiredKeys(arg0 context.Context) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteExpiredKeys", arg0) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// DeleteExpiredKeys indicates an expected call of DeleteExpiredKeys -func (mr *MockClientStoreMockRecorder) DeleteExpiredKeys(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteExpiredKeys", reflect.TypeOf((*MockClientStore)(nil).DeleteExpiredKeys), arg0) -} - -// GetLvl2Key mocks base method -func (m *MockClientStore) GetLvl2Key(arg0 context.Context, arg1 drkey.Lvl2Meta, arg2 time.Time) (drkey.Lvl2Key, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLvl2Key", arg0, arg1, arg2) - ret0, _ := ret[0].(drkey.Lvl2Key) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLvl2Key indicates an expected call of GetLvl2Key -func (mr *MockClientStoreMockRecorder) GetLvl2Key(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl2Key", reflect.TypeOf((*MockClientStore)(nil).GetLvl2Key), arg0, arg1, arg2) -} diff --git a/go/lib/drkeystorage/store.go b/go/lib/drkeystorage/store.go deleted file mode 100644 index cebb98ff34..0000000000 --- a/go/lib/drkeystorage/store.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkeystorage - -import ( - "context" - "time" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/infra/modules/cleaner" -) - -// SecretValueFactory has the functionality to store secret values. -type SecretValueFactory interface { - GetSecretValue(time.Time) (drkey.SV, error) -} - -// BaseStore is the common base for any drkey store. -type BaseStore interface { - DeleteExpiredKeys(ctx context.Context) (int, error) -} - -// ServiceStore is the level 1 drkey store, used by the CS. -// It will keep a cache of those keys that were retrieved from the network. -// It automatically removes expired keys. -type ServiceStore interface { - BaseStore - DeriveLvl1(dstIA addr.IA, valTime time.Time) (drkey.Lvl1Key, error) - GetLvl1Key(ctx context.Context, meta drkey.Lvl1Meta, valTime time.Time) (drkey.Lvl1Key, error) - KnownASes(ctx context.Context) ([]addr.IA, error) -} - -// ClientStore is the level 2 drkey store, used by sciond. -// It can get level 2 keys from its backes storage, or by -// asking a remote CS. -type ClientStore interface { - BaseStore - GetLvl2Key(ctx context.Context, meta drkey.Lvl2Meta, valTime time.Time) (drkey.Lvl2Key, error) -} - -// NewStoreCleaner creates a Cleaner task that removes expired level 1 drkeys. -func NewStoreCleaner(s BaseStore) *cleaner.Cleaner { - return cleaner.New(func(ctx context.Context) (int, error) { - return s.DeleteExpiredKeys(ctx) - }, "drkey") -} diff --git a/go/pkg/cs/BUILD.bazel b/go/pkg/cs/BUILD.bazel index 9b381db398..8c100123f1 100644 --- a/go/pkg/cs/BUILD.bazel +++ b/go/pkg/cs/BUILD.bazel @@ -24,7 +24,6 @@ go_library( "//go/lib/config:go_default_library", "//go/lib/ctrl/path_mgmt:go_default_library", "//go/lib/ctrl/seg:go_default_library", - "//go/lib/drkeystorage:go_default_library", "//go/lib/env:go_default_library", "//go/lib/infra:go_default_library", "//go/lib/infra/modules/seghandler:go_default_library", diff --git a/go/pkg/cs/drkey/BUILD.bazel b/go/pkg/cs/drkey/BUILD.bazel index 3a2c55fac9..8b9c1dd509 100644 --- a/go/pkg/cs/drkey/BUILD.bazel +++ b/go/pkg/cs/drkey/BUILD.bazel @@ -3,39 +3,41 @@ load("//lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "arc.go", "prefetcher.go", - "secret_value_store.go", - "service_store.go", + "secret_value_mgr.go", + "service_engine.go", ], importpath = "github.com/scionproto/scion/go/pkg/cs/drkey", visibility = ["//visibility:public"], deps = [ "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/protocol:go_default_library", - "//go/lib/drkeystorage:go_default_library", + "//go/lib/infra/modules/cleaner:go_default_library", "//go/lib/log:go_default_library", "//go/lib/periodic:go_default_library", "//go/lib/serrors:go_default_library", - "//go/lib/util:go_default_library", + "@com_github_hashicorp_golang_lru//:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ + "arc_test.go", "export_test.go", - "secret_value_store_test.go", - "service_store_test.go", + "prefetcher_test.go", + "service_engine_test.go", ], embed = [":go_default_library"], deps = [ + "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/drkeydbsqlite:go_default_library", + "//go/lib/drkey/sqlite:go_default_library", + "//go/lib/serrors:go_default_library", "//go/lib/util:go_default_library", "//go/lib/xtest:go_default_library", "//go/pkg/cs/drkey/mock_drkey:go_default_library", - "//go/pkg/cs/drkey/test:go_default_library", "@com_github_golang_mock//gomock:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", diff --git a/go/pkg/cs/drkey/arc.go b/go/pkg/cs/drkey/arc.go new file mode 100644 index 0000000000..cac7e6cdcf --- /dev/null +++ b/go/pkg/cs/drkey/arc.go @@ -0,0 +1,56 @@ +// Copyright 2021 ETH Zurich +// +// 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 drkey + +import ( + lru "github.com/hashicorp/golang-lru" + + "github.com/scionproto/scion/go/lib/serrors" +) + +var _ Lvl1PrefetchListKeeper = (*Lvl1ARC)(nil) + +// Lvl1ARC maintains an Adaptative Replacement Cache, storing +// the necessary metadata to prefetch Lvl1 keys +type Lvl1ARC struct { + cache *lru.ARCCache +} + +// NewLvl1ARC returns a Lvl1ARC cache of a given size +func NewLvl1ARC(size int) (*Lvl1ARC, error) { + cache, err := lru.NewARC(size) + if err != nil { + return nil, serrors.WrapStr("creating Lvl1ARC cache", err) + } + return &Lvl1ARC{ + cache: cache, + }, nil +} + +// Update is intended to merely update the frequency of a given remote AS +// in the ARC cache +func (c *Lvl1ARC) Update(keyPair Lvl1PrefetchInfo) { + c.cache.Add(keyPair, keyPair) +} + +// GetCachedASes returns the list of AS currently in cache +func (c *Lvl1ARC) GetLvl1InfoArray() []Lvl1PrefetchInfo { + list := []Lvl1PrefetchInfo{} + for _, k := range c.cache.Keys() { + lvl1Info := k.(Lvl1PrefetchInfo) + list = append(list, lvl1Info) + } + return list +} diff --git a/go/pkg/cs/drkey/arc_test.go b/go/pkg/cs/drkey/arc_test.go new file mode 100644 index 0000000000..ca6baf8785 --- /dev/null +++ b/go/pkg/cs/drkey/arc_test.go @@ -0,0 +1,67 @@ +// Copyright 2021 ETH Zurich +// +// 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 drkey_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/drkey" + cs_drkey "github.com/scionproto/scion/go/pkg/cs/drkey" +) + +func TestLvl1ARC(t *testing.T) { + + _, err := cs_drkey.NewLvl1ARC(-10) + require.Error(t, err) + cache, err := cs_drkey.NewLvl1ARC(5) + require.NoError(t, err) + + as0 := addr.MustIAFrom(1, 0) + cacheKey0 := cs_drkey.Lvl1PrefetchInfo{ + IA: as0, + Proto: drkey.Protocol(0), + } + cache.Update(cacheKey0) + assert.Len(t, cache.GetLvl1InfoArray(), 1) + + assert.Contains(t, cache.GetLvl1InfoArray(), cacheKey0) + + for j := 0; j < 4; j++ { + for i := 0; i < 10; i++ { + cacheKey := cs_drkey.Lvl1PrefetchInfo{ + IA: addr.MustIAFrom(1, addr.AS(i)), + Proto: drkey.Protocol(0), + } + cache.Update(cacheKey) + } + } + assert.Len(t, cache.GetLvl1InfoArray(), 5) + assert.NotContains(t, cache.GetLvl1InfoArray(), cacheKey0) + + as10 := addr.MustIAFrom(1, 10) + cacheKey10 := cs_drkey.Lvl1PrefetchInfo{ + IA: as10, + Proto: drkey.Protocol(0), + } + cache.Update(cacheKey10) + assert.Contains(t, cache.GetLvl1InfoArray(), cacheKey10) + cache.Update(cacheKey0) + assert.NotContains(t, cache.GetLvl1InfoArray(), cacheKey10) + +} diff --git a/go/pkg/cs/drkey/export_test.go b/go/pkg/cs/drkey/export_test.go index 94db816dda..09fc42e992 100644 --- a/go/pkg/cs/drkey/export_test.go +++ b/go/pkg/cs/drkey/export_test.go @@ -1,4 +1,4 @@ -// Copyright 2020 ETH Zurich +// Copyright 2021 ETH Zurich // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,20 +17,22 @@ package drkey import ( "time" + "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/drkey" ) -func (c *SecretValueStore) SetTimeNowFunction(f func() time.Time) { - c.mutex.Lock() - defer c.mutex.Unlock() - c.timeNowFcn = f - -} - -func (c *SecretValueStore) CleanExpired() { - c.cleanExpired() +func NewTestServiceEngine(localIA addr.IA, svdb drkey.SecretValueDB, masterKey []byte, + keyDur time.Duration, + db drkey.Lvl1DB, fetcher Fetcher, list Lvl1PrefetchListKeeper) *serviceEngine { + return &serviceEngine{ + secretBackend: newSecretValueBackend(svdb, masterKey, keyDur), + LocalIA: localIA, + DB: db, + Fetcher: fetcher, + prefetchKeeper: list, + } } -func (c *SecretValueStore) Cache() map[int64]drkey.SV { - return c.cache +func FromPrefetcher() fromPrefetcher { + return fromPrefetcher{} } diff --git a/go/pkg/cs/drkey/grpc/BUILD.bazel b/go/pkg/cs/drkey/grpc/BUILD.bazel index 72fd3cd343..972130d4e2 100644 --- a/go/pkg/cs/drkey/grpc/BUILD.bazel +++ b/go/pkg/cs/drkey/grpc/BUILD.bazel @@ -3,59 +3,64 @@ load("//lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "drkey_fetcher.go", "drkey_service.go", + "fetcher.go", ], importpath = "github.com/scionproto/scion/go/pkg/cs/drkey/grpc", visibility = ["//visibility:public"], deps = [ + "//go/cs/config:go_default_library", "//go/lib/addr:go_default_library", "//go/lib/common:go_default_library", "//go/lib/ctrl/drkey:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/exchange:go_default_library", - "//go/lib/drkey/protocol:go_default_library", - "//go/lib/drkeystorage:go_default_library", "//go/lib/log:go_default_library", + "//go/lib/scrypto/cppki:go_default_library", "//go/lib/serrors:go_default_library", "//go/lib/snet:go_default_library", "//go/pkg/cs/drkey:go_default_library", "//go/pkg/grpc:go_default_library", "//go/pkg/proto/control_plane:go_default_library", "//go/pkg/proto/drkey:go_default_library", + "@af_inet_netaddr//:go_default_library", + "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_grpc//peer:go_default_library", + "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ - "drkey_fetcher_test.go", "drkey_service_test.go", "export_test.go", - "lvl1_exchange_test.go", + "fetcher_test.go", ], data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ - "//go/lib/ctrl/drkey:go_default_library", + "//go/cs/config:go_default_library", + "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkeystorage/mock_drkeystorage:go_default_library", "//go/lib/scrypto/cppki:go_default_library", + "//go/lib/snet:go_default_library", + "//go/lib/snet/mock_snet:go_default_library", "//go/lib/util:go_default_library", "//go/lib/xtest:go_default_library", - "//go/pkg/cs/drkey/grpc/mock_grpc:go_default_library", - "//go/pkg/cs/drkey/test:go_default_library", + "//go/pkg/cs/drkey/mock_drkey:go_default_library", + "//go/pkg/grpc/mock_grpc:go_default_library", "//go/pkg/proto/control_plane:go_default_library", "//go/pkg/proto/drkey:go_default_library", "//go/pkg/trust:go_default_library", "//go/pkg/trust/mock_trust:go_default_library", + "@af_inet_netaddr//:go_default_library", "@com_github_golang_mock//gomock:go_default_library", - "@com_github_golang_protobuf//ptypes:go_default_library_gen", "@com_github_stretchr_testify//assert:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", + "@org_golang_google_grpc//peer:go_default_library", "@org_golang_google_grpc//test/bufconn:go_default_library", + "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", ], ) diff --git a/go/pkg/cs/drkey/grpc/drkey_fetcher.go b/go/pkg/cs/drkey/grpc/drkey_fetcher.go deleted file mode 100644 index 9e17c7cf43..0000000000 --- a/go/pkg/cs/drkey/grpc/drkey_fetcher.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 grpc - -import ( - "context" - "time" - - "github.com/scionproto/scion/go/lib/addr" - ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/log" - "github.com/scionproto/scion/go/lib/serrors" - "github.com/scionproto/scion/go/lib/snet" - csdrkey "github.com/scionproto/scion/go/pkg/cs/drkey" - sc_grpc "github.com/scionproto/scion/go/pkg/grpc" - cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" - dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" -) - -type Lvl1KeyGetter interface { - GetLvl1Key(ctx context.Context, srcIA addr.IA, - req *dkpb.DRKeyLvl1Request) (*dkpb.DRKeyLvl1Response, error) -} - -type Lvl1KeyFetcher struct { - Dialer sc_grpc.Dialer - Router snet.Router -} - -var _ Lvl1KeyGetter = (*Lvl1KeyFetcher)(nil) - -func (f Lvl1KeyFetcher) GetLvl1Key(ctx context.Context, srcIA addr.IA, - req *dkpb.DRKeyLvl1Request) (*dkpb.DRKeyLvl1Response, error) { - logger := log.FromCtx(ctx) - - logger.Info("Resolving server", "srcIA", srcIA.String()) - path, err := f.Router.Route(ctx, srcIA) - if err != nil || path == nil { - return nil, serrors.WrapStr("unable to find path to", err, "IA", srcIA) - } - remote := &snet.SVCAddr{ - IA: srcIA, - Path: path.Dataplane(), - NextHop: path.UnderlayNextHop(), - SVC: addr.SvcCS, - } - conn, err := f.Dialer.Dial(ctx, remote) - if err != nil { - return nil, serrors.WrapStr("dialing", err) - } - defer conn.Close() - client := cppb.NewDRKeyLvl1ServiceClient(conn) - rep, err := client.DRKeyLvl1(ctx, req) - if err != nil { - return nil, serrors.WrapStr("requesting level 1 key", err) - } - return rep, nil -} - -// DRKeyFetcher obtains Lvl1 DRKey from a remote CS. -type DRKeyFetcher struct { - Getter Lvl1KeyGetter -} - -var _ csdrkey.Fetcher = (*DRKeyFetcher)(nil) - -// GetLvl1FromOtherCS queries a CS for a level 1 key. -func (f DRKeyFetcher) GetLvl1FromOtherCS(ctx context.Context, - srcIA, dstIA addr.IA, valTime time.Time) (drkey.Lvl1Key, error) { - - lvl1req := ctrl.NewLvl1Req(valTime) - req, err := ctrl.Lvl1reqToProtoRequest(lvl1req) - if err != nil { - return drkey.Lvl1Key{}, - serrors.WrapStr("parsing lvl1 request to protobuf", err) - } - - rep, err := f.Getter.GetLvl1Key(ctx, srcIA, req) - if err != nil { - return drkey.Lvl1Key{}, err - } - - lvl1Key, err := ctrl.GetLvl1KeyFromReply(srcIA, dstIA, rep) - if err != nil { - return drkey.Lvl1Key{}, serrors.WrapStr("obtaining level 1 key from reply", err) - } - - return lvl1Key, nil -} diff --git a/go/pkg/cs/drkey/grpc/drkey_fetcher_test.go b/go/pkg/cs/drkey/grpc/drkey_fetcher_test.go deleted file mode 100644 index 691dc14e6c..0000000000 --- a/go/pkg/cs/drkey/grpc/drkey_fetcher_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2021 ETH Zurich -// -// 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 grpc_test - -import ( - "context" - "testing" - "time" - - "github.com/golang/mock/gomock" - "github.com/golang/protobuf/ptypes" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/util" - "github.com/scionproto/scion/go/lib/xtest" - dk_grpc "github.com/scionproto/scion/go/pkg/cs/drkey/grpc" - mock_grpc "github.com/scionproto/scion/go/pkg/cs/drkey/grpc/mock_grpc" - dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" -) - -func TestGetLvl1FromOtherCS(t *testing.T) { - srcIA := xtest.MustParseIA("1-ff00:0:111") - dstIA := xtest.MustParseIA("1-ff00:0:112") - epochBegin, err := ptypes.TimestampProto(util.SecsToTime(0)) - require.NoError(t, err) - epochEnd, err := ptypes.TimestampProto(util.SecsToTime(1)) - require.NoError(t, err) - key := xtest.MustParseHexString("7f8e507aecf38c09e4cb10a0ff0cc497") - - testCases := map[string]struct { - req *dkpb.DRKeyLvl1Request - rep *dkpb.DRKeyLvl1Response - getter func(ctrl *gomock.Controller) dk_grpc.Lvl1KeyGetter - assertErr assert.ErrorAssertionFunc - }{ - "valid": { - getter: func(ctrl *gomock.Controller) dk_grpc.Lvl1KeyGetter { - rep := &dkpb.DRKeyLvl1Response{ - EpochBegin: epochBegin, - EpochEnd: epochEnd, - Drkey: key, - } - getter := mock_grpc.NewMockLvl1KeyGetter(ctrl) - getter.EXPECT().GetLvl1Key(gomock.Any(), gomock.Eq(srcIA), - gomock.Any()).Return(rep, nil) - return getter - }, - assertErr: assert.NoError, - }, - } - - for name, tc := range testCases { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - fetcher := dk_grpc.DRKeyFetcher{ - Getter: tc.getter(ctrl), - } - - _, err := fetcher.GetLvl1FromOtherCS(context.Background(), srcIA, dstIA, time.Now()) - tc.assertErr(t, err) - }) - } -} diff --git a/go/pkg/cs/drkey/grpc/drkey_service.go b/go/pkg/cs/drkey/grpc/drkey_service.go index 18804705c4..7747850e22 100644 --- a/go/pkg/cs/drkey/grpc/drkey_service.go +++ b/go/pkg/cs/drkey/grpc/drkey_service.go @@ -18,216 +18,362 @@ import ( "context" "net" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/peer" + "google.golang.org/protobuf/types/known/timestamppb" + "inet.af/netaddr" + "github.com/scionproto/scion/go/cs/config" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/common" ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkey/exchange" - "github.com/scionproto/scion/go/lib/drkey/protocol" - "github.com/scionproto/scion/go/lib/drkeystorage" "github.com/scionproto/scion/go/lib/log" + "github.com/scionproto/scion/go/lib/scrypto/cppki" "github.com/scionproto/scion/go/lib/serrors" + cs_drkey "github.com/scionproto/scion/go/pkg/cs/drkey" cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" ) -// DRKeyServer keeps track of the level 1 drkey keys. It is backed by a drkey.DB . -type DRKeyServer struct { +// Server keeps track of the drkeys. +type Server struct { LocalIA addr.IA - Store drkeystorage.ServiceStore - // AllowedDSs is a set of protocols per IP address (in 16 byte form). Represents the allowed - // protocols hosts can obtain delegation secrets for. - AllowedDSs map[[16]byte]map[string]struct{} + Engine cs_drkey.ServiceEngine + // AllowedSVHostProto is a set of Host,Protocol pairs that represents the allowed + // protocols hosts can obtain secrets values for. + AllowedSVHostProto map[config.HostProto]struct{} } -var _ cppb.DRKeyLvl1ServiceServer = &DRKeyServer{} -var _ cppb.DRKeyLvl2ServiceServer = &DRKeyServer{} +var _ cppb.DRKeyInterServiceServer = &Server{} +var _ cppb.DRKeyIntraServiceServer = &Server{} -// DRKeyLvl1 handle a level 1 request and returns a level 1 response. -func (d *DRKeyServer) DRKeyLvl1(ctx context.Context, - req *dkpb.DRKeyLvl1Request) (*dkpb.DRKeyLvl1Response, error) { +// Lvl1 handle a level 1 request and returns a level 1 response. +func (d *Server) Lvl1(ctx context.Context, + req *dkpb.Lvl1Request) (*dkpb.Lvl1Response, error) { logger := log.FromCtx(ctx) peer, ok := peer.FromContext(ctx) if !ok { - logger.Error("[DRKey gRPC server] Cannot retrieve peer from ctx") - return nil, serrors.New("retrieving peer information from ctx") + return nil, serrors.New("Cannot retrieve peer information from ctx") } - parsedReq, err := ctrl.RequestToLvl1Req(req) + dstIA, err := extractIAFromPeer(peer) if err != nil { - logger.Error("[DRKey gRPC server] Invalid DRKey Lvl1 request", - "peer", peer, "err", err) - return nil, err + return nil, serrors.WrapStr("retrieving info from certficate", err) } - dstIA, err := exchange.ExtractIAFromPeer(peer) + lvl1Meta, err := getMeta(req.ProtocolId, req.ValTime, d.LocalIA, dstIA) if err != nil { - logger.Error("[DRKey gRPC server] Error retrieving auth info from certicate", - "err", err) - return nil, serrors.WrapStr("retrieving info from certficate", err) + return nil, serrors.WrapStr("invalid DRKey Lvl1 request", err) + } + + // validate requested ProtoID is specific + if !lvl1Meta.ProtoId.IsPredefined() { + return nil, serrors.New("The requested protocol id is not recognized", + "protoID", lvl1Meta.ProtoId) } logger.Debug("[DRKey gRPC server] Received Lvl1 request", - "lvl1_req", parsedReq, "peer", peer.Addr.String(), "IA from cert", dstIA.String()) - lvl1Key, err := d.Store.DeriveLvl1(dstIA, parsedReq.ValTime) + "lvl1_meta", lvl1Meta, "peer", peer.Addr.String(), "IA from cert", dstIA.String()) + + lvl1Key, err := d.Engine.DeriveLvl1(lvl1Meta) if err != nil { - logger.Error("Error deriving level 1 key", "err", err) - return nil, err + return nil, serrors.WrapStr("deriving level 1 key", err) } resp, err := ctrl.KeyToLvl1Resp(lvl1Key) if err != nil { - logger.Error("[DRKey gRPC server] Error parsing DRKey Lvl1 to protobuf resp", "err", err) - return nil, err + return nil, serrors.WrapStr("parsing DRKey Lvl1 to protobuf resp", err) } return resp, nil } -// DRKeyLvl2 handles a level 2 drkey request and returns a level 2 response. -func (d *DRKeyServer) DRKeyLvl2(ctx context.Context, - req *cppb.DRKeyLvl2Request) (*cppb.DRKeyLvl2Response, error) { +func getMeta(protoId dkpb.Protocol, ts *timestamppb.Timestamp, srcIA, + dstIA addr.IA) (drkey.Lvl1Meta, error) { + err := ts.CheckValid() + if err != nil { + return drkey.Lvl1Meta{}, serrors.WrapStr("invalid valTime from pb req", err) + } + return drkey.Lvl1Meta{ + Validity: ts.AsTime(), + ProtoId: drkey.Protocol(protoId), + SrcIA: srcIA, + DstIA: dstIA, + }, nil +} + +func extractIAFromPeer(peer *peer.Peer) (addr.IA, error) { + if peer.AuthInfo == nil { + return 0, serrors.New("no auth info", "peer", peer) + } + tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo) + if !ok { + return 0, serrors.New("auth info is not of type TLS info", + "peer", peer, "authType", peer.AuthInfo.AuthType()) + } + chain := tlsInfo.State.PeerCertificates + certIA, err := cppki.ExtractIA(chain[0].Subject) + if err != nil { + return 0, serrors.WrapStr("extracting IA from peer cert", err) + } + return certIA, nil +} + +func (d *Server) IntraLvl1(ctx context.Context, + req *dkpb.IntraLvl1Request) (*dkpb.IntraLvl1Response, error) { + peer, ok := peer.FromContext(ctx) + if !ok { + return nil, serrors.New("Cannot retrieve peer information from ctx") + } + + if d.LocalIA != addr.IA(req.SrcIa) && d.LocalIA != addr.IA(req.DstIa) { + return nil, serrors.New("Local IA is not part of the request") + } + + meta, err := getMeta(req.ProtocolId, req.ValTime, addr.IA(req.SrcIa), addr.IA(req.DstIa)) + if err != nil { + return nil, serrors.WrapStr("parsing AS-AS request", err) + } + if err := d.validateAllowedHost(meta.ProtoId, peer.Addr); err != nil { + return nil, serrors.WrapStr("validating AS-AS request", err) + } + + lvl1Key, err := d.Engine.GetLvl1Key(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("getting AS-AS host key", err) + } + + resp, err := ctrl.KeyToASASResp(lvl1Key) + if err != nil { + return nil, serrors.WrapStr("encoding AS-AS to Protobuf response", err) + } + return resp, nil +} + +func (d *Server) ASHost(ctx context.Context, + req *dkpb.ASHostRequest) (*dkpb.ASHostResponse, error) { logger := log.FromCtx(ctx) peer, ok := peer.FromContext(ctx) if !ok { - logger.Error("[DRKey gRPC server] Cannot retrieve peer from ctx") - return nil, serrors.New("retrieving peer information from ctx") + return nil, serrors.New("Cannot retrieve peer information from ctx") } - parsedReq, err := requestToLvl2Req(req) + meta, err := ctrl.RequestToASHostMeta(req) if err != nil { - logger.Error("[DRKey gRPC server] Invalid DRKey Lvl2 request", - "peer", peer, "err", err) - return nil, err + return nil, serrors.WrapStr("parsing DRKey AS-Host request", err) } - if err := d.validateLvl2Req(parsedReq, peer.Addr); err != nil { - log.Error("[DRKey gRPC server] Error validating Lvl2 request", - "err", err) - return nil, err + if err := validateASHostReq(meta, d.LocalIA, peer.Addr); err != nil { + return nil, serrors.WrapStr("validating AS-Host request", err) } - srcIA := parsedReq.SrcIA - dstIA := parsedReq.DstIA - logger.Debug(" [DRKey gRPC server] Received lvl2 request", - "Type", parsedReq.ReqType, "protocol", parsedReq.Protocol, - "SrcIA", srcIA, "DstIA", dstIA) - lvl1Meta := drkey.Lvl1Meta{ - SrcIA: srcIA, - DstIA: dstIA, + logger.Debug(" [DRKey gRPC server] Received AS-Host request", + "protocol", meta.ProtoId, + "SrcIA", meta.SrcIA, "DstIA", meta.DstIA) + + asHostKey, err := d.Engine.DeriveASHost(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("deriving AS-Host request", err) } - lvl1Key, err := d.Store.GetLvl1Key(ctx, lvl1Meta, parsedReq.ValTime) + + resp, err := ctrl.KeyToASHostResp(asHostKey) if err != nil { - logger.Error("[DRKey gRPC server] Error getting the level 1 key", - "err", err) - return nil, err + return nil, serrors.WrapStr("parsing AS-Host request", err) } - lvl2Meta := drkey.Lvl2Meta{ - Epoch: lvl1Key.Epoch, - SrcIA: srcIA, - DstIA: dstIA, - KeyType: drkey.Lvl2KeyType(parsedReq.ReqType), - Protocol: parsedReq.Protocol, - SrcHost: parsedReq.SrcHost.ToHostAddr(), - DstHost: parsedReq.DstHost.ToHostAddr(), + return resp, nil +} + +// validateASHostReq returns and error if the requesting host is different from the +// requested dst host. The source AS infraestructure nodes are not supposed to contact +// the local CS but to derive this key from the SV instead. +func validateASHostReq(meta drkey.ASHostMeta, localIA addr.IA, peerAddr net.Addr) error { + hostAddr, err := hostAddrFromPeer(peerAddr) + if err != nil { + return err + } + + if !meta.DstIA.Equal(localIA) { + return serrors.New("invalid request, req.dstIA != localIA", + "req.dstIA", meta.DstIA, "localIA", localIA) + } + dstHost := addr.HostFromIPStr(meta.DstHost) + if !hostAddr.Equal(dstHost) { + return serrors.New("invalid request, dst_host != remote host", + "dst_host", dstHost, "remote_host", hostAddr) + } + return nil +} + +func (d *Server) HostAS(ctx context.Context, + req *dkpb.HostASRequest) (*dkpb.HostASResponse, error) { + logger := log.FromCtx(ctx) + peer, ok := peer.FromContext(ctx) + if !ok { + return nil, serrors.New("Cannot retrieve peer information from ctx") } - lvl2Key, err := deriveLvl2(lvl2Meta, lvl1Key) + meta, err := ctrl.RequestToHostASMeta(req) if err != nil { - logger.Error("[DRKey gRPC server] Error deriving level 2 key", - "err", err) - return nil, err + return nil, serrors.WrapStr("parsing Host-AS request", err) + } + if err := validateHostASReq(meta, d.LocalIA, peer.Addr); err != nil { + return nil, serrors.WrapStr("validating Host-AS request", err) + } + logger.Debug(" [DRKey gRPC server] Received Host-AS request", + "protocol", meta.ProtoId, + "SrcIA", meta.SrcIA, "DstIA", meta.DstIA) + key, err := d.Engine.DeriveHostAS(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("deriving Host-AS request", err) } - resp, err := keyToLvl2Resp(lvl2Key) + resp, err := ctrl.KeyToHostASResp(key) if err != nil { - logger.Debug("[DRKey gRPC server] Error parsing DRKey Lvl2 to protobuf resp", - "err", err) - return nil, err + return nil, serrors.WrapStr("parsing Host-AS request", err) } return resp, nil } -func requestToLvl2Req(req *cppb.DRKeyLvl2Request) (ctrl.Lvl2Req, error) { - return ctrl.RequestToLvl2Req(req.BaseReq) +// validateASHostReq returns and error if the requesting host is different from the +// requested src host. The dst AS infraestructure nodes are not supposed to contact +// the local CS but to derive this key from the SV instead. +func validateHostASReq(meta drkey.HostASMeta, localIA addr.IA, peerAddr net.Addr) error { + hostAddr, err := hostAddrFromPeer(peerAddr) + if err != nil { + return err + } + + if !meta.SrcIA.Equal(localIA) { + return serrors.New("invalid request, req.SrcIA != localIA", + "req.SrcIA", meta.SrcIA, "localIA", localIA) + } + srcHost := addr.HostFromIPStr(meta.SrcHost) + if !hostAddr.Equal(srcHost) { + return serrors.New("invalid request, src_host != remote host", + "src_host", srcHost, "remote_host", hostAddr) + } + return nil } -func keyToLvl2Resp(drkey drkey.Lvl2Key) (*cppb.DRKeyLvl2Response, error) { - baseRep, err := ctrl.KeyToLvl2Resp(drkey) +func (d *Server) HostHost(ctx context.Context, + req *dkpb.HostHostRequest) (*dkpb.HostHostResponse, error) { + logger := log.FromCtx(ctx) + peer, ok := peer.FromContext(ctx) + if !ok { + return nil, serrors.New("Cannot retrieve peer information from ctx") + } + + meta, err := ctrl.RequestToHostHostMeta(req) if err != nil { - return nil, err + return nil, serrors.WrapStr("parsing Host-Host request", err) } - return &cppb.DRKeyLvl2Response{ - BaseRep: baseRep, - }, nil + if err := validateHostHostReq(meta, d.LocalIA, peer.Addr); err != nil { + return nil, serrors.WrapStr("validating Host-Host request", err) + } + + logger.Debug(" [DRKey gRPC server] Received Host-Host request", + "protocol", meta.ProtoId, + "SrcIA", meta.SrcIA, "DstIA", meta.DstIA) + + key, err := d.Engine.DeriveHostHost(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("deriving Host-Host request", err) + } + + resp, err := ctrl.KeyToHostHostResp(key) + if err != nil { + return nil, serrors.WrapStr("parsing Host-Host request", err) + } + return resp, nil +} + +// validateHostHostReq returns and error if the requesting host is different from the +// requested src host or the dst host. +func validateHostHostReq(meta drkey.HostHostMeta, localIA addr.IA, peerAddr net.Addr) error { + hostAddr, err := hostAddrFromPeer(peerAddr) + if err != nil { + return err + } + + if meta.SrcIA.Equal(localIA) { + srcHost := addr.HostFromIPStr(meta.SrcHost) + if !hostAddr.Equal(srcHost) { + return serrors.New("invalid request, src_host != remote host", + "src_host", srcHost, "remote_host", hostAddr) + } + return nil + } + + if meta.DstIA.Equal(localIA) { + dstHost := addr.HostFromIPStr(meta.DstHost) + if !hostAddr.Equal(dstHost) { + return serrors.New("invalid request, dst_host != remote host", + "dst_host", dstHost, "remote_host", hostAddr) + } + return nil + } + return serrors.New("invalid request, localIA not found in request", + "localIA", localIA, "srcIA", meta.SrcIA, "dstIA", meta.DstIA) +} + +func hostAddrFromPeer(peerAddr net.Addr) (addr.HostAddr, error) { + tcpAddr, ok := peerAddr.(*net.TCPAddr) + if !ok { + return nil, serrors.New("invalid peer address type, expected *net.TCPAddr", + "peer", peerAddr, "type", common.TypeOf(peerAddr)) + } + return addr.HostFromIP(tcpAddr.IP), nil } -// deriveLvl2 will derive the level 2 key specified by the meta data and the level 1 key. -func deriveLvl2(meta drkey.Lvl2Meta, lvl1Key drkey.Lvl1Key) ( - drkey.Lvl2Key, error) { +// SV handles a SV request and returns a SV response. +func (d *Server) SV(ctx context.Context, + req *dkpb.SVRequest) (*dkpb.SVResponse, error) { + peer, ok := peer.FromContext(ctx) + if !ok { + return nil, serrors.New("Cannot retrieve peer information from ctx") + } - der, found := protocol.KnownDerivations[meta.Protocol] - if !found { - return drkey.Lvl2Key{}, serrors.New("no derivation found for protocol", - "protocol", meta.Protocol) + meta, err := ctrl.SVRequestToMeta(req) + if err != nil { + return nil, serrors.WrapStr("parsing Host-Host request", err) + } + if err := d.validateAllowedHost(meta.ProtoId, peer.Addr); err != nil { + return nil, serrors.WrapStr("validating SV request", err) + } + sv, err := d.Engine.GetSecretValue(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("getting SV from persistence", err) } - return der.DeriveLvl2(meta, lvl1Key) + resp, err := ctrl.SVtoProtoResp(sv) + if err != nil { + return nil, serrors.WrapStr("encoding SV to Protobuf response", err) + } + return resp, nil } -// validateLvl2Req checks that the requester is in the destination of the key -// if AS2Host or host2host, and checks that the requester is authorized as to -// get a DS if AS2AS (AS2AS == DS). -func (d *DRKeyServer) validateLvl2Req(req ctrl.Lvl2Req, peerAddr net.Addr) error { +// validateAllowedHost checks that the requester is authorized to receive a SV +func (d *Server) validateAllowedHost(protoId drkey.Protocol, peerAddr net.Addr) error { tcpAddr, ok := peerAddr.(*net.TCPAddr) if !ok { return serrors.New("invalid peer address type, expected *net.TCPAddr", "peer", peerAddr, "type", common.TypeOf(peerAddr)) } - localAddr := addr.HostFromIP(tcpAddr.IP) - - if req.SrcIA != d.LocalIA && req.DstIA != d.LocalIA { - return serrors.New("invalid request, localIA not found in request", - "localIA", d.LocalIA, "srcIA", req.SrcIA, "dstIA", req.DstIA) + localAddr, ok := netaddr.FromStdIP(tcpAddr.IP) + if !ok { + return serrors.New("unable to parse IP", "addr", tcpAddr.IP.String()) + } + hostProto := config.HostProto{ + Host: localAddr, + Proto: protoId, } - switch drkey.Lvl2KeyType(req.ReqType) { - case drkey.Host2Host: - if req.SrcIA == d.LocalIA { - if localAddr.Equal(req.SrcHost.ToHostAddr()) { - break - } - } - fallthrough - case drkey.AS2Host: - if req.DstIA == d.LocalIA { - if localAddr.Equal(req.DstHost.ToHostAddr()) { - break - } - } - fallthrough - case drkey.AS2AS: - // check in the allowed endhosts list - var rawIP [16]byte - copy(rawIP[:], localAddr.IP().To16()) - protocolSet, foundSet := d.AllowedDSs[rawIP] - if foundSet { - if _, found := protocolSet[req.Protocol]; found { - log.Debug("Authorized delegated secret", - "reqType", req.ReqType, - "requester address", localAddr, - "srcHost", req.SrcHost.ToHostAddr().String(), - "dstHost", req.DstHost.ToHostAddr().String(), - ) - return nil - } - } - return serrors.New("endhost not allowed for DRKey request", - "reqType", req.ReqType, - "endhost address", localAddr, - "protocol", req.Protocol, - "srcHost", req.SrcHost.ToHostAddr().String(), - "dstHost", req.DstHost.ToHostAddr().String(), + _, foundSet := d.AllowedSVHostProto[hostProto] + if foundSet { + log.Debug("Authorized delegated secret", + "protocol", protoId.String(), + "requester address", localAddr.String(), ) - default: - return serrors.New("unknown request type", "reqType", req.ReqType) + return nil } - return nil + return serrors.New("endhost not allowed for DRKey request", + "protocol", protoId.String(), + "requester address", localAddr.String(), + ) } diff --git a/go/pkg/cs/drkey/grpc/drkey_service_test.go b/go/pkg/cs/drkey/grpc/drkey_service_test.go index 4a9663b8ff..07ba6e5f46 100644 --- a/go/pkg/cs/drkey/grpc/drkey_service_test.go +++ b/go/pkg/cs/drkey/grpc/drkey_service_test.go @@ -15,22 +15,379 @@ package grpc_test import ( + "context" + "net" "testing" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/grpc/peer" + "google.golang.org/protobuf/types/known/timestamppb" + "inet.af/netaddr" + "github.com/scionproto/scion/go/cs/config" + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/util" "github.com/scionproto/scion/go/lib/xtest" dk_grpc "github.com/scionproto/scion/go/pkg/cs/drkey/grpc" - "github.com/scionproto/scion/go/pkg/cs/drkey/test" + "github.com/scionproto/scion/go/pkg/cs/drkey/mock_drkey" + dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" ) -func TestDeriveLvl2Key(t *testing.T) { +var ( + ia111 = xtest.MustParseIA("1-ff00:0:111") + ia112 = xtest.MustParseIA("1-ff00:0:112") + tcpHost1 = netaddr.MustParseIPPort("127.0.0.1:12345") + tcpHost2 = netaddr.MustParseIPPort("127.0.0.2:12345") + lvl2Meta = drkey.Lvl2Meta{ + SrcIA: ia111, + DstIA: ia112, + } + lvl1Raw = xtest.MustParseHexString("7f8e507aecf38c09e4cb10a0ff0cc497") +) + +func TestDRKeySV(t *testing.T) { + sv, targetResp := getSVandResp(t) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + serviceStore := mock_drkey.NewMockServiceEngine(ctrl) + serviceStore.EXPECT().GetSecretValue(gomock.Any(), gomock.Any()).Return(sv, nil) + + list := map[config.HostProto]struct{}{ + { + Host: tcpHost1.IP(), + Proto: drkey.SCMP, + }: {}, + } + server := dk_grpc.Server{ + LocalIA: ia111, + Engine: serviceStore, + AllowedSVHostProto: list, + } + requestPeer := &peer.Peer{ + Addr: tcpHost1.TCPAddr(), + } + peerCtx := peer.NewContext(context.Background(), requestPeer) + request := &dkpb.SVRequest{ + ValTime: timestamppb.Now(), + ProtocolId: dkpb.Protocol_PROTOCOL_SCMP, + } + resp, err := server.SV(peerCtx, request) + require.NoError(t, err) + require.EqualValues(t, targetResp, resp) +} + +func TestValidateASHost(t *testing.T) { + testCases := map[string]struct { + peerAddr net.Addr + req drkey.ASHostMeta + LocalIA addr.IA + assertErr assert.ErrorAssertionFunc + }{ + "no host": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.ASHostMeta{ + Lvl2Meta: lvl2Meta, + }, + LocalIA: ia112, + assertErr: assert.Error, + }, + "no localIA": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.ASHostMeta{ + Lvl2Meta: lvl2Meta, + DstHost: tcpHost1.IP().String(), + }, + assertErr: assert.Error, + }, + "mismatch addr": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.ASHostMeta{ + Lvl2Meta: lvl2Meta, + DstHost: tcpHost2.IP().String(), + }, + LocalIA: ia112, + assertErr: assert.Error, + }, + "valid host": { + peerAddr: tcpHost2.TCPAddr(), + req: drkey.ASHostMeta{ + Lvl2Meta: lvl2Meta, + DstHost: tcpHost2.IP().String(), + }, + LocalIA: ia112, + assertErr: assert.NoError, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + err := dk_grpc.ValidateASHostReq(tc.req, tc.LocalIA, tc.peerAddr) + tc.assertErr(t, err) + }) + } +} - expectedKey := xtest.MustParseHexString("b90ceff1586e5b5cc3313445df18f271") +func TestValidateHostASReq(t *testing.T) { + testCases := map[string]struct { + peerAddr net.Addr + req drkey.HostASMeta + LocalIA addr.IA + assertErr assert.ErrorAssertionFunc + }{ + "no host": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.HostASMeta{ + Lvl2Meta: lvl2Meta, + }, + LocalIA: ia111, + assertErr: assert.Error, + }, + "no localIA": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.HostASMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.IP().String(), + }, + assertErr: assert.Error, + }, + "mismatch addr": { + peerAddr: tcpHost2.TCPAddr(), + req: drkey.HostASMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.String(), + }, + LocalIA: ia111, + assertErr: assert.Error, + }, + "valid src": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.HostASMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.IP().String(), + }, + LocalIA: ia111, + assertErr: assert.NoError, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { - meta, lvl1Key := test.GetInputToDeriveLvl2Key(t) + err := dk_grpc.ValidateHostASReq(tc.req, tc.LocalIA, tc.peerAddr) + tc.assertErr(t, err) + }) + } +} + +func TestValidateHostHostReq(t *testing.T) { + testCases := map[string]struct { + peerAddr net.Addr + req drkey.HostHostMeta + LocalIA addr.IA + assertErr assert.ErrorAssertionFunc + }{ + "no host": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.HostHostMeta{ + Lvl2Meta: lvl2Meta, + }, + LocalIA: ia111, + assertErr: assert.Error, + }, + "no localIA": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.HostHostMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.IP().String(), + DstHost: tcpHost2.IP().String(), + }, + assertErr: assert.Error, + }, + "mismatch addr": { + peerAddr: tcpHost2.TCPAddr(), + req: drkey.HostHostMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.IP().String(), + DstHost: tcpHost2.IP().String(), + }, + LocalIA: ia111, + assertErr: assert.Error, + }, + "valid src": { + peerAddr: tcpHost1.TCPAddr(), + req: drkey.HostHostMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.IP().String(), + DstHost: tcpHost2.IP().String(), + }, + LocalIA: ia111, + assertErr: assert.NoError, + }, + "valid dst": { + peerAddr: tcpHost2.TCPAddr(), + req: drkey.HostHostMeta{ + Lvl2Meta: lvl2Meta, + SrcHost: tcpHost1.IP().String(), + DstHost: tcpHost2.IP().String(), + }, + LocalIA: ia112, + assertErr: assert.NoError, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + + err := dk_grpc.ValidateHostHostReq(tc.req, tc.LocalIA, tc.peerAddr) + tc.assertErr(t, err) + }) + } +} + +func TestLvl1(t *testing.T) { + // TODO(JordiSubira): Extend this test with more cases + grpcServer := dk_grpc.Server{} - lvl2Key, err := dk_grpc.DeriveLvl2(meta, lvl1Key) + request := dkpb.Lvl1Request{ + ProtocolId: 200, + ValTime: timestamppb.Now(), + } + ctx := peer.NewContext(context.Background(), &peer.Peer{}) + _, err := grpcServer.Lvl1(ctx, &request) + require.Error(t, err) +} + +func TestASHost(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + lvl1Key := drkey.Lvl1Key{ + SrcIA: ia111, + DstIA: ia112, + Epoch: drkey.NewEpoch(0, 2), + } + copy(lvl1Key.Key[:], lvl1Raw) + engine := mock_drkey.NewMockServiceEngine(ctrl) + engine.EXPECT().DeriveASHost(gomock.Any(), gomock.Any()).Return( + drkey.ASHostKey{}, nil).AnyTimes() + + grpcServer := dk_grpc.Server{ + LocalIA: ia112, + Engine: engine, + } + remotePeer := peer.Peer{ + Addr: tcpHost1.TCPAddr(), + } + request := &dkpb.ASHostRequest{ + ProtocolId: 200, + ValTime: timestamppb.Now(), + SrcIa: uint64(ia111), + DstIa: uint64(ia112), + DstHost: "127.0.0.1", + } + ctx := peer.NewContext(context.Background(), &remotePeer) + _, err := grpcServer.ASHost(ctx, request) require.NoError(t, err) - require.EqualValues(t, expectedKey, lvl2Key.Key) + + request.ProtocolId = dkpb.Protocol_PROTOCOL_SCMP + _, err = grpcServer.ASHost(ctx, request) + require.NoError(t, err) +} + +func TestHostAS(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + lvl1Key := drkey.Lvl1Key{ + SrcIA: ia111, + DstIA: ia112, + Epoch: drkey.NewEpoch(0, 2), + } + copy(lvl1Key.Key[:], lvl1Raw) + engine := mock_drkey.NewMockServiceEngine(ctrl) + engine.EXPECT().DeriveHostAS(gomock.Any(), gomock.Any()).Return( + drkey.HostASKey{}, nil).AnyTimes() + + grpcServer := dk_grpc.Server{ + LocalIA: ia111, + Engine: engine, + } + remotePeer := peer.Peer{ + Addr: tcpHost1.TCPAddr(), + } + request := &dkpb.HostASRequest{ + ProtocolId: 200, + ValTime: timestamppb.Now(), + SrcIa: uint64(ia111), + DstIa: uint64(ia112), + SrcHost: "127.0.0.1", + } + ctx := peer.NewContext(context.Background(), &remotePeer) + _, err := grpcServer.HostAS(ctx, request) + require.NoError(t, err) + + request.ProtocolId = dkpb.Protocol_PROTOCOL_SCMP + _, err = grpcServer.HostAS(ctx, request) + require.NoError(t, err) +} + +func TestHostHost(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + lvl1Key := drkey.Lvl1Key{ + SrcIA: ia111, + DstIA: ia112, + Epoch: drkey.NewEpoch(0, 2), + } + copy(lvl1Key.Key[:], lvl1Raw) + engine := mock_drkey.NewMockServiceEngine(ctrl) + engine.EXPECT().DeriveHostHost(gomock.Any(), gomock.Any()).Return( + drkey.HostHostKey{}, nil).AnyTimes() + + grpcServer := dk_grpc.Server{ + LocalIA: ia111, + Engine: engine, + } + remotePeer := peer.Peer{ + Addr: tcpHost1.TCPAddr(), + } + request := &dkpb.HostHostRequest{ + ProtocolId: 200, + ValTime: timestamppb.Now(), + SrcIa: uint64(ia111), + DstIa: uint64(ia112), + SrcHost: "127.0.0.1", + DstHost: "127.0.0.2", + } + ctx := peer.NewContext(context.Background(), &remotePeer) + _, err := grpcServer.HostHost(ctx, request) + require.NoError(t, err) + + request.ProtocolId = dkpb.Protocol_PROTOCOL_SCMP + _, err = grpcServer.HostHost(ctx, request) + require.NoError(t, err) +} + +func getSVandResp(t *testing.T) (drkey.SV, *dkpb.SVResponse) { + k := xtest.MustParseHexString("d29d00c39398b7588c0d31a4ffc77841") + + sv := drkey.SV{ + Epoch: drkey.NewEpoch(0, 1), + ProtoId: drkey.SCMP, + } + copy(sv.Key[:], k) + + targetResp := &dkpb.SVResponse{ + EpochBegin: timestamppb.New(util.SecsToTime(0)), + EpochEnd: timestamppb.New(util.SecsToTime(1)), + Key: k, + } + return sv, targetResp } diff --git a/go/pkg/cs/drkey/grpc/export_test.go b/go/pkg/cs/drkey/grpc/export_test.go index 5e4f68b1fd..25c92bf292 100644 --- a/go/pkg/cs/drkey/grpc/export_test.go +++ b/go/pkg/cs/drkey/grpc/export_test.go @@ -15,5 +15,7 @@ package grpc var ( - DeriveLvl2 = deriveLvl2 + ValidateASHostReq = validateASHostReq + ValidateHostASReq = validateHostASReq + ValidateHostHostReq = validateHostHostReq ) diff --git a/go/pkg/cs/drkey/grpc/fetcher.go b/go/pkg/cs/drkey/grpc/fetcher.go new file mode 100644 index 0000000000..641eac9779 --- /dev/null +++ b/go/pkg/cs/drkey/grpc/fetcher.go @@ -0,0 +1,128 @@ +// Copyright 2020 ETH Zurich +// +// 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 grpc + +import ( + "context" + "errors" + "math/rand" + "time" + + "github.com/scionproto/scion/go/lib/addr" + ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/log" + "github.com/scionproto/scion/go/lib/serrors" + "github.com/scionproto/scion/go/lib/snet" + csdrkey "github.com/scionproto/scion/go/pkg/cs/drkey" + sc_grpc "github.com/scionproto/scion/go/pkg/grpc" + cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" + dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" +) + +const ( + // defaultRPCDialTimeout is the timeout used for dialing the gRPC ClientConn. + // This is shorter than the typical context deadline for the request. + // Having a separate, more aggressive timeout for dialing allows to abort + // quickly. This allows the surrounding infrastructure to retry quickly -- in + // the case where this request goes over SCION/QUIC, retries are used to + // route around broken paths. + // This timeout needs to be long enough to allow for service address + // resolution and the QUIC handshake to complete (two roundtrips). + defaultRPCDialTimeout time.Duration = 2 * time.Second +) + +var errNotReachable = serrors.New("remote not reachable") + +// Fetcher obtains Lvl1 DRKey from a remote CS. +type Fetcher struct { + Dialer sc_grpc.Dialer + Router snet.Router + MaxRetries int +} + +var _ csdrkey.Fetcher = (*Fetcher)(nil) + +// Lvl1 queries a CS for a level 1 key. +func (f Fetcher) Lvl1(ctx context.Context, + meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + logger := log.FromCtx(ctx) + + req, err := ctrl.Lvl1MetaToProtoRequest(meta) + if err != nil { + return drkey.Lvl1Key{}, + serrors.WrapStr("parsing lvl1 request to protobuf", err) + } + + var rep *dkpb.Lvl1Response + for i := 0; i < f.MaxRetries; i++ { + rep, err = f.getLvl1Key(ctx, meta.SrcIA, req) + if errors.Is(err, errNotReachable) { + logger.Debug("Lvl1 fetch failed", "try", i+1, "peer", meta.SrcIA, "err", err) + return drkey.Lvl1Key{}, err + } + if err == nil { + lvl1Key, err := ctrl.GetLvl1KeyFromReply(meta, rep) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("obtaining level 1 key from reply", err) + } + return lvl1Key, nil + } + logger.Debug("Lvl1 fetch failed", "try", i+1, "peer", meta.SrcIA, "err", err) + } + return drkey.Lvl1Key{}, serrors.New("Reached max retry attempts on fetching lvl1 key") +} + +func (f Fetcher) getLvl1Key(ctx context.Context, srcIA addr.IA, + req *dkpb.Lvl1Request) (*dkpb.Lvl1Response, error) { + logger := log.FromCtx(ctx) + + logger.Info("Resolving server", "srcIA", srcIA.String()) + path, err := f.pathToDst(ctx, srcIA) + if err != nil { + return nil, err + } + remote := &snet.SVCAddr{ + IA: srcIA, + Path: path.Dataplane(), + NextHop: path.UnderlayNextHop(), + SVC: addr.SvcCS, + } + dialCtx, cancelF := context.WithTimeout(ctx, defaultRPCDialTimeout) + defer cancelF() + conn, err := f.Dialer.Dial(dialCtx, remote) + if err != nil { + return nil, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := cppb.NewDRKeyInterServiceClient(conn) + rep, err := client.Lvl1(ctx, req) + if err != nil { + return nil, serrors.WrapStr("requesting level 1 key", err) + } + return rep, nil +} + +func (f Fetcher) pathToDst(ctx context.Context, dst addr.IA) (snet.Path, error) { + paths, err := f.Router.AllRoutes(ctx, dst) + if err != nil { + return nil, serrors.Wrap(errNotReachable, err) + } + if len(paths) == 0 { + return nil, errNotReachable + } + path := paths[rand.Intn(len(paths))] + return path, nil +} diff --git a/go/pkg/cs/drkey/grpc/fetcher_test.go b/go/pkg/cs/drkey/grpc/fetcher_test.go new file mode 100644 index 0000000000..6a86e7df48 --- /dev/null +++ b/go/pkg/cs/drkey/grpc/fetcher_test.go @@ -0,0 +1,135 @@ +// Copyright 2020 ETH Zurich +// +// 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 grpc_test + +import ( + "context" + "crypto/tls" + "log" + "net" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/test/bufconn" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/snet" + "github.com/scionproto/scion/go/lib/snet/mock_snet" + "github.com/scionproto/scion/go/lib/xtest" + dk_grpc "github.com/scionproto/scion/go/pkg/cs/drkey/grpc" + "github.com/scionproto/scion/go/pkg/cs/drkey/mock_drkey" + "github.com/scionproto/scion/go/pkg/grpc/mock_grpc" + cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" + "github.com/scionproto/scion/go/pkg/trust" + "github.com/scionproto/scion/go/pkg/trust/mock_trust" +) + +func dialer(creds credentials.TransportCredentials, + drkeyServer cppb.DRKeyInterServiceServer) func(context.Context, string) (net.Conn, error) { + bufsize := 1024 * 1024 + listener := bufconn.Listen(bufsize) + + server := grpc.NewServer(grpc.Creds(creds)) + + cppb.RegisterDRKeyInterServiceServer(server, drkeyServer) + + go func() { + if err := server.Serve(listener); err != nil { + log.Fatal(err) + } + }() + + return func(context.Context, string) (net.Conn, error) { + return listener.Dial() + } +} + +func TestLvl1KeyFetching(t *testing.T) { + trc := xtest.LoadTRC(t, "testdata/common/trcs/ISD1-B1-S1.trc") + crt111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem" + key111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/cp-as.key" + tlsCert, err := tls.LoadX509KeyPair(crt111File, key111File) + require.NoError(t, err) + chain, err := cppki.ReadPEMCerts(crt111File) + _ = chain + require.NoError(t, err) + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + lvl1db := mock_drkey.NewMockServiceEngine(ctrl) + lvl1db.EXPECT().DeriveLvl1(gomock.Any()).Return(drkey.Lvl1Key{}, nil) + + mgrdb := mock_trust.NewMockDB(ctrl) + mgrdb.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).AnyTimes().Return(trc, nil) + loader := mock_trust.NewMockX509KeyPairLoader(ctrl) + loader.EXPECT().LoadX509KeyPair(gomock.Any(), gomock.Any()).AnyTimes().Return(&tlsCert, nil) + mgr := trust.NewTLSCryptoManager(loader, mgrdb) + + drkeyServ := &dk_grpc.Server{ + Engine: lvl1db, + } + + serverConf := &tls.Config{ + InsecureSkipVerify: true, + GetCertificate: mgr.GetCertificate, + VerifyPeerCertificate: mgr.VerifyClientCertificate, + ClientAuth: tls.RequireAnyClientCert, + } + serverCreds := credentials.NewTLS(serverConf) + + clientCreds := credentials.NewTLS(&tls.Config{ + InsecureSkipVerify: true, + GetClientCertificate: mgr.GetClientCertificate, + VerifyPeerCertificate: mgr.VerifyServerCertificate, + VerifyConnection: mgr.VerifyConnection, + }) + + conn, err := grpc.DialContext(context.Background(), + "1-ff00:0:111,127.0.0.1:10000", + grpc.WithTransportCredentials(clientCreds), + grpc.WithContextDialer(dialer(serverCreds, drkeyServ)), + ) + require.NoError(t, err) + defer conn.Close() + + dialer := mock_grpc.NewMockDialer(ctrl) + dialer.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(conn, nil) + + path := mock_snet.NewMockPath(ctrl) + path.EXPECT().Dataplane().Return(nil) + path.EXPECT().UnderlayNextHop().Return(&net.UDPAddr{}) + router := mock_snet.NewMockRouter(ctrl) + router.EXPECT().AllRoutes(gomock.Any(), gomock.Any()).Return([]snet.Path{path}, nil) + + fetcher := dk_grpc.Fetcher{ + Dialer: dialer, + Router: router, + MaxRetries: 10, + } + + meta := drkey.Lvl1Meta{ + ProtoId: drkey.Generic, + Validity: time.Now(), + SrcIA: xtest.MustParseIA("1-ff00:0:111"), + } + _, err = fetcher.Lvl1(context.Background(), meta) + require.NoError(t, err) +} diff --git a/go/pkg/cs/drkey/grpc/lvl1_exchange_test.go b/go/pkg/cs/drkey/grpc/lvl1_exchange_test.go deleted file mode 100644 index 1b43b5df54..0000000000 --- a/go/pkg/cs/drkey/grpc/lvl1_exchange_test.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 grpc_test - -import ( - "context" - "crypto/tls" - "log" - "net" - "testing" - "time" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/test/bufconn" - - pb_ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" - "github.com/scionproto/scion/go/lib/drkey" - mock_st "github.com/scionproto/scion/go/lib/drkeystorage/mock_drkeystorage" - "github.com/scionproto/scion/go/lib/scrypto/cppki" - "github.com/scionproto/scion/go/lib/xtest" - dk_grpc "github.com/scionproto/scion/go/pkg/cs/drkey/grpc" - cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" - "github.com/scionproto/scion/go/pkg/trust" - "github.com/scionproto/scion/go/pkg/trust/mock_trust" -) - -func dialer(creds credentials.TransportCredentials, - drkeyServer cppb.DRKeyLvl1ServiceServer) func(context.Context, string) (net.Conn, error) { - bufsize := 1024 * 1024 - listener := bufconn.Listen(bufsize) - - server := grpc.NewServer(grpc.Creds(creds)) - - cppb.RegisterDRKeyLvl1ServiceServer(server, drkeyServer) - - go func() { - if err := server.Serve(listener); err != nil { - log.Fatal(err) - } - }() - - return func(context.Context, string) (net.Conn, error) { - return listener.Dial() - } -} - -func TestLvl1KeyFetching(t *testing.T) { - trc := xtest.LoadTRC(t, "testdata/common/trcs/ISD1-B1-S1.trc") - crt111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem" - key111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/cp-as.key" - tlsCert, err := tls.LoadX509KeyPair(crt111File, key111File) - require.NoError(t, err) - chain, err := cppki.ReadPEMCerts(crt111File) - _ = chain - require.NoError(t, err) - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - lvl1db := mock_st.NewMockServiceStore(ctrl) - lvl1db.EXPECT().DeriveLvl1(gomock.Any(), gomock.Any()).Return(drkey.Lvl1Key{}, nil) - - mgrdb := mock_trust.NewMockDB(ctrl) - mgrdb.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).AnyTimes().Return(trc, nil) - loader := mock_trust.NewMockX509KeyPairLoader(ctrl) - loader.EXPECT().LoadX509KeyPair().AnyTimes().Return(&tlsCert, nil) - mgr := trust.NewTLSCryptoManager(loader, mgrdb) - - drkeyServ := &dk_grpc.DRKeyServer{ - Store: lvl1db, - } - - serverConf := &tls.Config{ - InsecureSkipVerify: true, - GetCertificate: mgr.GetCertificate, - VerifyPeerCertificate: mgr.VerifyPeerCertificate, - ClientAuth: tls.RequireAnyClientCert, - } - serverCreds := credentials.NewTLS(serverConf) - - clientConf := &tls.Config{ - InsecureSkipVerify: true, - GetClientCertificate: mgr.GetClientCertificate, - VerifyPeerCertificate: mgr.VerifyPeerCertificate, - } - clientCreds := trust.NewClientCredentials(clientConf) - - conn, err := grpc.DialContext(context.Background(), - "1-ff00:0:111,127.0.0.1:10000", - grpc.WithTransportCredentials(clientCreds), - grpc.WithContextDialer(dialer(serverCreds, drkeyServ)), - ) - require.NoError(t, err) - defer conn.Close() - - client := cppb.NewDRKeyLvl1ServiceClient(conn) - - lvl1req := pb_ctrl.NewLvl1Req(time.Now()) - req, err := pb_ctrl.Lvl1reqToProtoRequest(lvl1req) - require.NoError(t, err) - _, err = client.DRKeyLvl1(context.Background(), req) - require.NoError(t, err) -} - -// XXX(JordiSubira) TestLvl1KeyFetching below checks correct Lvl1 key exchange as from Go1.15 -// which introduces VerifyConnection callback to access TLS state during handshake. - -// func TestLvl1KeyFetching(t *testing.T) { -// trc := xtest.LoadTRC(t, "testdata/common/trcs/ISD1-B1-S1.trc") -// crt111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem" -// key111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/cp-as.key" -// tlsCert, err := tls.LoadX509KeyPair(crt111File, key111File) -// require.NoError(t, err) -// chain, err := cppki.ReadPEMCerts(crt111File) -// _ = chain -// require.NoError(t, err) -// ia111 := xtest.MustParseIA("1-ff00:0:111") - -// ctrl := gomock.NewController(t) -// defer ctrl.Finish() - -// lvl1db := mock_st.NewMockServiceStore(ctrl) -// lvl1db.EXPECT().DeriveLvl1(gomock.Any(), gomock.Any()).Return(drkey.Lvl1Key{}, nil) - -// mgrdb := mock_trust.NewMockDB(ctrl) -// mgrdb.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).AnyTimes().Return(trc, nil) -// loader := mock_trust.NewMockX509KeyPairLoader(ctrl) -// loader.EXPECT().LoadX509KeyPair().AnyTimes().Return(&tlsCert, nil) -// mgr := trust.NewTLSCryptoManager(loader, mgrdb) - -// drkeyServ := &DRKeyServer{ -// Store: lvl1db, -// } - -// serverConf := &tls.Config{ -// InsecureSkipVerify: true, -// GetCertificate: mgr.GetCertificate, -// VerifyPeerCertificate: mgr.VerifyPeerCertificate, -// ClientAuth: tls.RequireAnyClientCert, -// } -// serverCreds := credentials.NewTLS(serverConf) -// clientConf := &tls.Config{ -// InsecureSkipVerify: true, -// GetClientCertificate: mgr.GetClientCertificate, -// VerifyPeerCertificate: mgr.VerifyPeerCertificate, -// VerifyConnection: verifyConnection, -// } -// clientCreds := credentials.NewTLS(clientConf) - -// conn, err := grpc.DialContext(context.Background(), -// "1-ff00:0:112", -// grpc.WithTransportCredentials(clientCreds), -// grpc.WithContextDialer(dialer(serverCreds, drkeyServ)), -// ) -// // conn, err := grpc.DialContext(context.Background(), "", -// // grpc.WithInsecure(), -// // grpc.WithContextDialer(dialer(serverCreds, drkeyServ))) -// require.NoError(t, err) -// defer conn.Close() - -// client := cppb.NewDRKeyLvl1ServiceClient(conn) - -// lvl1req := pb_ctrl.NewLvl1Req(ia111, time.Now()) -// req, err := lvl1reqToProtoRequest(lvl1req) -// require.NoError(t, err) -// _, err = client.DRKeyLvl1(context.Background(), req) -// require.NoError(t, err) -// } - -// func verifyConnection(cs tls.ConnectionState) error { -// serverIA, err := addr.IAFromString(cs.ServerName) -// if err != nil { -// return serrors.WrapStr("extracting IA from server name", err) -// } -// certIA, err := cppki.ExtractIA(cs.PeerCertificates[0].Subject) -// if err != nil { -// return serrors.WrapStr("extracting IA from peer cert", err) -// } -// if !serverIA.Equal(*certIA) { -// return serrors.New("extracted IA from cert and server IA do not match", -// "peer IA", certIA, "server IA", serverIA) -// } -// return nil -// } diff --git a/go/pkg/cs/drkey/grpc/mock_grpc/BUILD.bazel b/go/pkg/cs/drkey/grpc/mock_grpc/BUILD.bazel deleted file mode 100644 index 4212f8ef2f..0000000000 --- a/go/pkg/cs/drkey/grpc/mock_grpc/BUILD.bazel +++ /dev/null @@ -1,22 +0,0 @@ -load("//lint:go.bzl", "go_library") -load("@com_github_jmhodges_bazel_gomock//:gomock.bzl", "gomock") - -gomock( - name = "go_default_mock", - out = "mock.go", - interfaces = ["Lvl1KeyGetter"], - library = "//go/pkg/cs/drkey/grpc:go_default_library", - package = "mock_grpc", -) - -go_library( - name = "go_default_library", - srcs = ["mock.go"], - importpath = "github.com/scionproto/scion/go/pkg/cs/drkey/grpc/mock_grpc", - visibility = ["//visibility:public"], - deps = [ - "//go/lib/addr:go_default_library", - "//go/pkg/proto/drkey:go_default_library", - "@com_github_golang_mock//gomock:go_default_library", - ], -) diff --git a/go/pkg/cs/drkey/grpc/mock_grpc/mock.go b/go/pkg/cs/drkey/grpc/mock_grpc/mock.go deleted file mode 100644 index 5f5bca8e58..0000000000 --- a/go/pkg/cs/drkey/grpc/mock_grpc/mock.go +++ /dev/null @@ -1,52 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/go/pkg/cs/drkey/grpc (interfaces: Lvl1KeyGetter) - -// Package mock_grpc is a generated GoMock package. -package mock_grpc - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - addr "github.com/scionproto/scion/go/lib/addr" - drkey "github.com/scionproto/scion/go/pkg/proto/drkey" -) - -// MockLvl1KeyGetter is a mock of Lvl1KeyGetter interface. -type MockLvl1KeyGetter struct { - ctrl *gomock.Controller - recorder *MockLvl1KeyGetterMockRecorder -} - -// MockLvl1KeyGetterMockRecorder is the mock recorder for MockLvl1KeyGetter. -type MockLvl1KeyGetterMockRecorder struct { - mock *MockLvl1KeyGetter -} - -// NewMockLvl1KeyGetter creates a new mock instance. -func NewMockLvl1KeyGetter(ctrl *gomock.Controller) *MockLvl1KeyGetter { - mock := &MockLvl1KeyGetter{ctrl: ctrl} - mock.recorder = &MockLvl1KeyGetterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockLvl1KeyGetter) EXPECT() *MockLvl1KeyGetterMockRecorder { - return m.recorder -} - -// GetLvl1Key mocks base method. -func (m *MockLvl1KeyGetter) GetLvl1Key(arg0 context.Context, arg1 addr.IA, arg2 *drkey.DRKeyLvl1Request) (*drkey.DRKeyLvl1Response, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLvl1Key", arg0, arg1, arg2) - ret0, _ := ret[0].(*drkey.DRKeyLvl1Response) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLvl1Key indicates an expected call of GetLvl1Key. -func (mr *MockLvl1KeyGetterMockRecorder) GetLvl1Key(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl1Key", reflect.TypeOf((*MockLvl1KeyGetter)(nil).GetLvl1Key), arg0, arg1, arg2) -} diff --git a/go/pkg/cs/drkey/mock_drkey/BUILD.bazel b/go/pkg/cs/drkey/mock_drkey/BUILD.bazel index a9aa2f8b9c..3475560b0b 100644 --- a/go/pkg/cs/drkey/mock_drkey/BUILD.bazel +++ b/go/pkg/cs/drkey/mock_drkey/BUILD.bazel @@ -1,13 +1,26 @@ load("//lint:go.bzl", "go_library") +load("@com_github_jmhodges_bazel_gomock//:gomock.bzl", "gomock") + +gomock( + name = "go_default_mock", + out = "mock.go", + interfaces = [ + "Fetcher", + "Lvl1PrefetchListKeeper", + "ServiceEngine", + ], + library = "//go/pkg/cs/drkey:go_default_library", + package = "mock_drkey", +) go_library( name = "go_default_library", - srcs = ["fetcher.go"], + srcs = ["mock.go"], importpath = "github.com/scionproto/scion/go/pkg/cs/drkey/mock_drkey", visibility = ["//visibility:public"], deps = [ - "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", + "//go/pkg/cs/drkey:go_default_library", "@com_github_golang_mock//gomock:go_default_library", ], ) diff --git a/go/pkg/cs/drkey/mock_drkey/fetcher.go b/go/pkg/cs/drkey/mock_drkey/fetcher.go deleted file mode 100644 index 2bc524535e..0000000000 --- a/go/pkg/cs/drkey/mock_drkey/fetcher.go +++ /dev/null @@ -1,52 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/go/pkg/cs/drkey (interfaces: Fetcher) - -// Package mock_drkey is a generated GoMock package. -package mock_drkey - -import ( - context "context" - gomock "github.com/golang/mock/gomock" - addr "github.com/scionproto/scion/go/lib/addr" - drkey "github.com/scionproto/scion/go/lib/drkey" - reflect "reflect" - time "time" -) - -// MockFetcher is a mock of Fetcher interface -type MockFetcher struct { - ctrl *gomock.Controller - recorder *MockFetcherMockRecorder -} - -// MockFetcherMockRecorder is the mock recorder for MockFetcher -type MockFetcherMockRecorder struct { - mock *MockFetcher -} - -// NewMockFetcher creates a new mock instance -func NewMockFetcher(ctrl *gomock.Controller) *MockFetcher { - mock := &MockFetcher{ctrl: ctrl} - mock.recorder = &MockFetcherMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockFetcher) EXPECT() *MockFetcherMockRecorder { - return m.recorder -} - -// GetLvl1FromOtherCS mocks base method -func (m *MockFetcher) GetLvl1FromOtherCS(arg0 context.Context, arg1, arg2 addr.IA, arg3 time.Time) (drkey.Lvl1Key, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLvl1FromOtherCS", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].(drkey.Lvl1Key) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLvl1FromOtherCS indicates an expected call of GetLvl1FromOtherCS -func (mr *MockFetcherMockRecorder) GetLvl1FromOtherCS(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl1FromOtherCS", reflect.TypeOf((*MockFetcher)(nil).GetLvl1FromOtherCS), arg0, arg1, arg2, arg3) -} diff --git a/go/pkg/cs/drkey/mock_drkey/mock.go b/go/pkg/cs/drkey/mock_drkey/mock.go new file mode 100644 index 0000000000..4b7e375f85 --- /dev/null +++ b/go/pkg/cs/drkey/mock_drkey/mock.go @@ -0,0 +1,243 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/scionproto/scion/go/pkg/cs/drkey (interfaces: Fetcher,Lvl1PrefetchListKeeper,ServiceEngine) + +// Package mock_drkey is a generated GoMock package. +package mock_drkey + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + drkey "github.com/scionproto/scion/go/lib/drkey" + drkey0 "github.com/scionproto/scion/go/pkg/cs/drkey" +) + +// MockFetcher is a mock of Fetcher interface. +type MockFetcher struct { + ctrl *gomock.Controller + recorder *MockFetcherMockRecorder +} + +// MockFetcherMockRecorder is the mock recorder for MockFetcher. +type MockFetcherMockRecorder struct { + mock *MockFetcher +} + +// NewMockFetcher creates a new mock instance. +func NewMockFetcher(ctrl *gomock.Controller) *MockFetcher { + mock := &MockFetcher{ctrl: ctrl} + mock.recorder = &MockFetcherMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockFetcher) EXPECT() *MockFetcherMockRecorder { + return m.recorder +} + +// Lvl1 mocks base method. +func (m *MockFetcher) Lvl1(arg0 context.Context, arg1 drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Lvl1", arg0, arg1) + ret0, _ := ret[0].(drkey.Lvl1Key) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Lvl1 indicates an expected call of Lvl1. +func (mr *MockFetcherMockRecorder) Lvl1(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lvl1", reflect.TypeOf((*MockFetcher)(nil).Lvl1), arg0, arg1) +} + +// MockLvl1PrefetchListKeeper is a mock of Lvl1PrefetchListKeeper interface. +type MockLvl1PrefetchListKeeper struct { + ctrl *gomock.Controller + recorder *MockLvl1PrefetchListKeeperMockRecorder +} + +// MockLvl1PrefetchListKeeperMockRecorder is the mock recorder for MockLvl1PrefetchListKeeper. +type MockLvl1PrefetchListKeeperMockRecorder struct { + mock *MockLvl1PrefetchListKeeper +} + +// NewMockLvl1PrefetchListKeeper creates a new mock instance. +func NewMockLvl1PrefetchListKeeper(ctrl *gomock.Controller) *MockLvl1PrefetchListKeeper { + mock := &MockLvl1PrefetchListKeeper{ctrl: ctrl} + mock.recorder = &MockLvl1PrefetchListKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockLvl1PrefetchListKeeper) EXPECT() *MockLvl1PrefetchListKeeperMockRecorder { + return m.recorder +} + +// GetLvl1InfoArray mocks base method. +func (m *MockLvl1PrefetchListKeeper) GetLvl1InfoArray() []drkey0.Lvl1PrefetchInfo { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLvl1InfoArray") + ret0, _ := ret[0].([]drkey0.Lvl1PrefetchInfo) + return ret0 +} + +// GetLvl1InfoArray indicates an expected call of GetLvl1InfoArray. +func (mr *MockLvl1PrefetchListKeeperMockRecorder) GetLvl1InfoArray() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl1InfoArray", reflect.TypeOf((*MockLvl1PrefetchListKeeper)(nil).GetLvl1InfoArray)) +} + +// Update mocks base method. +func (m *MockLvl1PrefetchListKeeper) Update(arg0 drkey0.Lvl1PrefetchInfo) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Update", arg0) +} + +// Update indicates an expected call of Update. +func (mr *MockLvl1PrefetchListKeeperMockRecorder) Update(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockLvl1PrefetchListKeeper)(nil).Update), arg0) +} + +// MockServiceEngine is a mock of ServiceEngine interface. +type MockServiceEngine struct { + ctrl *gomock.Controller + recorder *MockServiceEngineMockRecorder +} + +// MockServiceEngineMockRecorder is the mock recorder for MockServiceEngine. +type MockServiceEngineMockRecorder struct { + mock *MockServiceEngine +} + +// NewMockServiceEngine creates a new mock instance. +func NewMockServiceEngine(ctrl *gomock.Controller) *MockServiceEngine { + mock := &MockServiceEngine{ctrl: ctrl} + mock.recorder = &MockServiceEngineMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockServiceEngine) EXPECT() *MockServiceEngineMockRecorder { + return m.recorder +} + +// DeleteExpiredKeys mocks base method. +func (m *MockServiceEngine) DeleteExpiredKeys(arg0 context.Context) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteExpiredKeys", arg0) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteExpiredKeys indicates an expected call of DeleteExpiredKeys. +func (mr *MockServiceEngineMockRecorder) DeleteExpiredKeys(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteExpiredKeys", reflect.TypeOf((*MockServiceEngine)(nil).DeleteExpiredKeys), arg0) +} + +// DeriveASHost mocks base method. +func (m *MockServiceEngine) DeriveASHost(arg0 context.Context, arg1 drkey.ASHostMeta) (drkey.ASHostKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeriveASHost", arg0, arg1) + ret0, _ := ret[0].(drkey.ASHostKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeriveASHost indicates an expected call of DeriveASHost. +func (mr *MockServiceEngineMockRecorder) DeriveASHost(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeriveASHost", reflect.TypeOf((*MockServiceEngine)(nil).DeriveASHost), arg0, arg1) +} + +// DeriveHostAS mocks base method. +func (m *MockServiceEngine) DeriveHostAS(arg0 context.Context, arg1 drkey.HostASMeta) (drkey.HostASKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeriveHostAS", arg0, arg1) + ret0, _ := ret[0].(drkey.HostASKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeriveHostAS indicates an expected call of DeriveHostAS. +func (mr *MockServiceEngineMockRecorder) DeriveHostAS(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeriveHostAS", reflect.TypeOf((*MockServiceEngine)(nil).DeriveHostAS), arg0, arg1) +} + +// DeriveHostHost mocks base method. +func (m *MockServiceEngine) DeriveHostHost(arg0 context.Context, arg1 drkey.HostHostMeta) (drkey.HostHostKey, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeriveHostHost", arg0, arg1) + ret0, _ := ret[0].(drkey.HostHostKey) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeriveHostHost indicates an expected call of DeriveHostHost. +func (mr *MockServiceEngineMockRecorder) DeriveHostHost(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeriveHostHost", reflect.TypeOf((*MockServiceEngine)(nil).DeriveHostHost), arg0, arg1) +} + +// DeriveLvl1 mocks base method. +func (m *MockServiceEngine) DeriveLvl1(arg0 drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeriveLvl1", arg0) + ret0, _ := ret[0].(drkey.Lvl1Key) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeriveLvl1 indicates an expected call of DeriveLvl1. +func (mr *MockServiceEngineMockRecorder) DeriveLvl1(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeriveLvl1", reflect.TypeOf((*MockServiceEngine)(nil).DeriveLvl1), arg0) +} + +// GetLvl1Key mocks base method. +func (m *MockServiceEngine) GetLvl1Key(arg0 context.Context, arg1 drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLvl1Key", arg0, arg1) + ret0, _ := ret[0].(drkey.Lvl1Key) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetLvl1Key indicates an expected call of GetLvl1Key. +func (mr *MockServiceEngineMockRecorder) GetLvl1Key(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl1Key", reflect.TypeOf((*MockServiceEngine)(nil).GetLvl1Key), arg0, arg1) +} + +// GetLvl1PrefetchInfo mocks base method. +func (m *MockServiceEngine) GetLvl1PrefetchInfo() []drkey0.Lvl1PrefetchInfo { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetLvl1PrefetchInfo") + ret0, _ := ret[0].([]drkey0.Lvl1PrefetchInfo) + return ret0 +} + +// GetLvl1PrefetchInfo indicates an expected call of GetLvl1PrefetchInfo. +func (mr *MockServiceEngineMockRecorder) GetLvl1PrefetchInfo() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLvl1PrefetchInfo", reflect.TypeOf((*MockServiceEngine)(nil).GetLvl1PrefetchInfo)) +} + +// GetSecretValue mocks base method. +func (m *MockServiceEngine) GetSecretValue(arg0 context.Context, arg1 drkey.SVMeta) (drkey.SV, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecretValue", arg0, arg1) + ret0, _ := ret[0].(drkey.SV) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecretValue indicates an expected call of GetSecretValue. +func (mr *MockServiceEngineMockRecorder) GetSecretValue(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretValue", reflect.TypeOf((*MockServiceEngine)(nil).GetSecretValue), arg0, arg1) +} diff --git a/go/pkg/cs/drkey/prefetcher.go b/go/pkg/cs/drkey/prefetcher.go index fa4d9e8551..728e3c2f93 100644 --- a/go/pkg/cs/drkey/prefetcher.go +++ b/go/pkg/cs/drkey/prefetcher.go @@ -21,17 +21,32 @@ import ( "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkeystorage" "github.com/scionproto/scion/go/lib/log" "github.com/scionproto/scion/go/lib/periodic" ) +// Lvl1PrefetchListKeeper maintains a likst for those lvl1 keys +// that are recently/frequently used +type Lvl1PrefetchListKeeper interface { + //Update updates the keys in Lvl1Cache based on the Lvl1Key metadata + Update(key Lvl1PrefetchInfo) + // GetLvl1InfoArray retrieves an array whose memebers contains information regarding + // lvl1 keys to prefetch + GetLvl1InfoArray() []Lvl1PrefetchInfo +} + +// Lvl1PrefetchInfo contains the information to prefetch lvl1 keys from remote CSes. +type Lvl1PrefetchInfo struct { + IA addr.IA + Proto drkey.Protocol +} + var _ periodic.Task = (*Prefetcher)(nil) // Prefetcher is in charge of getting the level 1 keys before they expire. type Prefetcher struct { LocalIA addr.IA - Store drkeystorage.ServiceStore + Engine ServiceEngine // XXX(JordiSubira): At the moment we assume "global" KeyDuration, i.e. // every AS involved uses the same EpochDuration. This will be improve // further in the future, so that the prefetcher get keys in advance @@ -47,34 +62,37 @@ func (f *Prefetcher) Name() string { // Run requests the level 1 keys to other CSs. func (f *Prefetcher) Run(ctx context.Context) { + logger := log.FromCtx(ctx) var wg sync.WaitGroup - ases, err := f.Store.KnownASes(ctx) - if err != nil { - log.Error("Could not prefetch level 1 keys", "error", err) - return - } - log.Debug("Prefetching level 1 DRKeys", "ASes", ases) + ases := f.Engine.GetLvl1PrefetchInfo() + logger.Debug("Prefetching level 1 DRKeys", "ASes", ases) when := time.Now().Add(f.KeyDuration) - for _, srcIA := range ases { - srcIA := srcIA + for _, key := range ases { + key := key wg.Add(1) go func() { defer log.HandlePanic() - getLvl1Key(ctx, f.Store, srcIA, f.LocalIA, when, &wg) + getLvl1Key(ctx, f.Engine, key.IA, f.LocalIA, key.Proto, when, &wg) }() } wg.Wait() } -func getLvl1Key(ctx context.Context, store drkeystorage.ServiceStore, - srcIA, dstIA addr.IA, valTime time.Time, wg *sync.WaitGroup) { +type fromPrefetcher struct{} + +func getLvl1Key(ctx context.Context, engine ServiceEngine, + srcIA, dstIA addr.IA, proto drkey.Protocol, valTime time.Time, wg *sync.WaitGroup) { defer wg.Done() meta := drkey.Lvl1Meta{ - SrcIA: srcIA, - DstIA: dstIA, + Validity: valTime, + SrcIA: srcIA, + DstIA: dstIA, + ProtoId: proto, } - _, err := store.GetLvl1Key(ctx, meta, valTime) + pref_ctx := context.WithValue(ctx, fromPrefetcher{}, true) + _, err := engine.GetLvl1Key(pref_ctx, meta) if err != nil { - log.Error("Failed to prefetch the level 1 key", "remote AS", srcIA.String(), "error", err) + log.Error("Failed to prefetch the level 1 key", "remote AS", srcIA.String(), + "protocol", proto, "error", err) } } diff --git a/go/pkg/cs/drkey/prefetcher_test.go b/go/pkg/cs/drkey/prefetcher_test.go new file mode 100644 index 0000000000..9d238cde0b --- /dev/null +++ b/go/pkg/cs/drkey/prefetcher_test.go @@ -0,0 +1,67 @@ +// Copyright 2021 ETH Zurich +// +// 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 drkey_test + +import ( + "context" + "testing" + "time" + + "github.com/golang/mock/gomock" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/xtest" + cs_drkey "github.com/scionproto/scion/go/pkg/cs/drkey" + "github.com/scionproto/scion/go/pkg/cs/drkey/mock_drkey" +) + +func TestPrefetcherRun(t *testing.T) { + mctrl := gomock.NewController(t) + defer mctrl.Finish() + + mock_engine := mock_drkey.NewMockServiceEngine(mctrl) + + prefetcher := cs_drkey.Prefetcher{ + Engine: mock_engine, + LocalIA: xtest.MustParseIA("1-ff00:0:110"), + KeyDuration: time.Hour, + } + + firstCached := mock_engine.EXPECT().GetLvl1PrefetchInfo().Times(1).Return(nil) + + cachedKeys := []cs_drkey.Lvl1PrefetchInfo{ + { + IA: xtest.MustParseIA("1-ff00:0:112"), + Proto: drkey.DNS, + }, + } + secondCached := mock_engine.EXPECT().GetLvl1PrefetchInfo().After( + firstCached).Times(1).Return(cachedKeys) + + cachedKeys = append(cachedKeys, cs_drkey.Lvl1PrefetchInfo{ + IA: xtest.MustParseIA("1-ff00:0:111"), + Proto: drkey.DNS, + }) + mock_engine.EXPECT().GetLvl1PrefetchInfo().After( + secondCached).Times(1).Return(cachedKeys) + + // 0 + 1 + 2 calls at each run respectively + mock_engine.EXPECT().GetLvl1Key(gomock.Any(), gomock.Any()).Times(3) + + prefetcher.Run(context.Background()) + prefetcher.Run(context.Background()) + prefetcher.Run(context.Background()) + +} diff --git a/go/pkg/cs/drkey/secret_value_mgr.go b/go/pkg/cs/drkey/secret_value_mgr.go new file mode 100644 index 0000000000..57d335e1ce --- /dev/null +++ b/go/pkg/cs/drkey/secret_value_mgr.go @@ -0,0 +1,75 @@ +// Copyright 2019 ETH Zurich +// +// 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 drkey + +import ( + "context" + "time" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/serrors" +) + +// SecretValueStore keeps the current and next secret values and removes the expired ones. +type secretValueBackend struct { + DB drkey.SecretValueDB + masterKey []byte + keyDuration time.Duration +} + +// NewSecretValueStore creates a new SecretValueStore and initializes the cleaner. +func newSecretValueBackend(db drkey.SecretValueDB, masterKey []byte, + keyDuration time.Duration) *secretValueBackend { + return &secretValueBackend{ + DB: db, + masterKey: masterKey, + keyDuration: keyDuration, + } +} + +// DeleteExpiredSV deletes any expired secret value +func (s *secretValueBackend) deleteExpiredSV(ctx context.Context) (int, error) { + i, err := s.DB.DeleteExpiredSV(ctx, time.Now()) + return int(i), err +} + +// GetSecretValue returns a valid secret value for the provided metadata. +// It tries to retrieve the secret value from persistence, otherwise +// it creates a new one and stores it away. +func (s *secretValueBackend) getSecretValue(ctx context.Context, + meta drkey.SVMeta) (drkey.SV, error) { + duration := int64(s.keyDuration / time.Second) // duration in seconds + k, err := s.DB.GetSV(ctx, meta) + if err == nil { + return k, nil + } + if err != drkey.ErrKeyNotFound { + return drkey.SV{}, serrors.WrapStr("retrieving SV from DB", err) + } + + idx := meta.Validity.Unix() / duration + begin := uint32(idx * duration) + end := begin + uint32(duration) + epoch := drkey.NewEpoch(begin, end) + sv, err := drkey.DeriveSV(meta.ProtoId, epoch, s.masterKey) + if err != nil { + return drkey.SV{}, serrors.WrapStr("deriving DRKey secret value", err) + } + err = s.DB.InsertSV(ctx, sv) + if err != nil { + return drkey.SV{}, serrors.WrapStr("inserting SV in persistence", err) + } + return sv, nil +} diff --git a/go/pkg/cs/drkey/secret_value_store.go b/go/pkg/cs/drkey/secret_value_store.go deleted file mode 100644 index b6d6824615..0000000000 --- a/go/pkg/cs/drkey/secret_value_store.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2019 ETH Zurich -// -// 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 drkey - -import ( - "runtime" - "sync" - "time" - - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/log" - "github.com/scionproto/scion/go/lib/serrors" -) - -// SecretValueStore keeps the current and next secret values and removes the expired ones. -type SecretValueStore struct { - // TODO(JordiSubira): simplify class to be more consistent with keeping current and next - // secret values. - cache map[int64]drkey.SV - mutex sync.Mutex - - keyDuration time.Duration - stopCleaning chan bool - timeNowFcn func() time.Time -} - -// NewSecretValueStore creates a new SecretValueStore and initializes the cleaner. -func NewSecretValueStore(keyDuration time.Duration) *SecretValueStore { - m := &SecretValueStore{ - cache: make(map[int64]drkey.SV), - keyDuration: keyDuration, - stopCleaning: make(chan bool), - timeNowFcn: time.Now, - } - runtime.SetFinalizer(m, stopCleaner) - go func() { - defer log.HandlePanic() - m.startCleaner() - }() - return m -} - -// Get returns the element, and an indicator of its presence. -func (m *SecretValueStore) Get(idx int64) (drkey.SV, bool) { - m.mutex.Lock() - defer m.mutex.Unlock() - - k, found := m.cache[idx] - return k, found -} - -// Set sets the key, and registers this element in this shard. -func (m *SecretValueStore) Set(idx int64, key drkey.SV) { - m.mutex.Lock() - defer m.mutex.Unlock() - - m.cache[idx] = key -} - -// cleanExpired removes the current shard at once. -func (m *SecretValueStore) cleanExpired() { - m.mutex.Lock() - defer m.mutex.Unlock() - - now := m.timeNowFcn() - for idx, value := range m.cache { - if !value.Epoch.Contains(now) { - delete(m.cache, idx) - } - } -} - -func stopCleaner(m *SecretValueStore) { - m.stopCleaning <- true -} - -func (m *SecretValueStore) startCleaner() { - ticker := time.NewTicker(2 * m.keyDuration) - for { - select { - case <-ticker.C: - m.cleanExpired() - case <-m.stopCleaning: - ticker.Stop() - return - } - } -} - -// SecretValueFactory stores the secret value -type SecretValueFactory struct { - keyDuration time.Duration - masterKey []byte - keyMap *SecretValueStore - mapMutex sync.Mutex -} - -// NewSecretValueFactory return a default initialized SecretValueFactory. -func NewSecretValueFactory(masterKey []byte, - keyDuration time.Duration) *SecretValueFactory { - - s := &SecretValueFactory{ - masterKey: masterKey, - keyDuration: keyDuration, - } - s.keyMap = NewSecretValueStore(s.keyDuration) - return s -} - -// GetSecretValue derives or reuses the secret value for this time stamp. -func (s *SecretValueFactory) GetSecretValue(t time.Time) (drkey.SV, error) { - s.mapMutex.Lock() - defer s.mapMutex.Unlock() - - duration := int64(s.keyDuration / time.Second) // duration in seconds - idx := t.Unix() / duration - k, found := s.keyMap.Get(idx) - if !found { - begin := uint32(idx * duration) - end := begin + uint32(duration) - epoch := drkey.NewEpoch(begin, end) - var err error - k, err = drkey.DeriveSV(drkey.SVMeta{Epoch: epoch}, s.masterKey) - if err != nil { - return drkey.SV{}, serrors.WrapStr("Cannot establish the DRKey secret value", err) - } - s.keyMap.Set(idx, k) - } - return k, nil -} diff --git a/go/pkg/cs/drkey/secret_value_store_test.go b/go/pkg/cs/drkey/secret_value_store_test.go deleted file mode 100644 index 63b4856d05..0000000000 --- a/go/pkg/cs/drkey/secret_value_store_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 drkey_test - -import ( - "context" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/util" - csdrkey "github.com/scionproto/scion/go/pkg/cs/drkey" -) - -// waitCondWithTimeout waits for the condition cond and return true, or timeout and return false. -func waitCondWithTimeout(dur time.Duration, cond *sync.Cond) bool { - ctx, cancelF := context.WithTimeout(context.Background(), dur) - defer cancelF() - done := make(chan struct{}) - go func() { - cond.Wait() - done <- struct{}{} - }() - select { - case <-done: - return true - case <-ctx.Done(): - } - return false -} - -// TestSecretValueStoreTicker checks that the store starts a ticker to clean expired values. -func TestSecretValueStoreTicker(t *testing.T) { - var m sync.Mutex - cond := sync.NewCond(&m) - m.Lock() - c := csdrkey.NewSecretValueStore(time.Millisecond) - // This timeNowFcn is used to mock time.Now() to test expiring entries in the tests below. - // This _has_ to be called by the cleanup function. Therefore, we can (ab-)use this to check - // that the background cleaner is indeed running. - testTimeNowFunc := func() time.Time { - cond.Broadcast() - return time.Unix(0, 0) - } - c.SetTimeNowFunction(testTimeNowFunc) - ret := waitCondWithTimeout(time.Minute, cond) - require.True(t, ret) -} - -func TestSecretValueStore(t *testing.T) { - c := csdrkey.NewSecretValueStore(time.Hour) - var now atomic.Value - testTimeNowFunc := func() time.Time { - return now.Load().(time.Time) - } - c.SetTimeNowFunction(testTimeNowFunc) - now.Store(time.Unix(10, 0)) - - k1 := drkey.SV{ - SVMeta: drkey.SVMeta{Epoch: drkey.NewEpoch(10, 12)}, - Key: drkey.DRKey([]byte{1, 2, 3}), - } - c.Set(1, k1) - c.CleanExpired() - k, found := c.Get(1) - require.True(t, found) - require.Equal(t, k1, k) - require.Len(t, c.Cache(), 1) - - k2 := drkey.SV{ - SVMeta: drkey.SVMeta{Epoch: drkey.NewEpoch(11, 13)}, - Key: drkey.DRKey([]byte{2, 3, 4}), - } - now.Store(time.Unix(12, 0).Add(-1 * time.Nanosecond)) - c.Set(2, k2) - require.Len(t, c.Cache(), 2) - c.CleanExpired() - require.Len(t, c.Cache(), 2) - now.Store(time.Unix(12, 1)) - c.CleanExpired() - require.Len(t, c.Cache(), 1) - _, found = c.Get(1) - require.False(t, found) -} - -func TestSecretValueFactory(t *testing.T) { - master := []byte{} - fac := csdrkey.NewSecretValueFactory(master, 10*time.Second) - _, err := fac.GetSecretValue(time.Now()) - require.Error(t, err) - master = []byte{0, 1, 2, 3} - fac = csdrkey.NewSecretValueFactory(master, 10*time.Second) - k, err := fac.GetSecretValue(util.SecsToTime(10)) - require.NoError(t, err) - require.EqualValues(t, 10, k.Epoch.NotBefore.Unix()) - require.EqualValues(t, 20, k.Epoch.NotAfter.Unix()) - - now := time.Unix(10, 0) - k, _ = fac.GetSecretValue(now) - savedCurrSV := k - - // advance time 9 seconds - now = now.Add(9 * time.Second) - k, _ = fac.GetSecretValue(now) - require.Equal(t, savedCurrSV.Key, k.Key) - - // advance it so we are in total 10 seconds in the future of the original clock - now = now.Add(time.Second) - k, _ = fac.GetSecretValue(now) - require.NotEqual(t, savedCurrSV.Key, k.Key) - require.Equal(t, savedCurrSV.Epoch.NotAfter, k.Epoch.NotBefore) -} diff --git a/go/pkg/cs/drkey/service_engine.go b/go/pkg/cs/drkey/service_engine.go new file mode 100644 index 0000000000..480283555c --- /dev/null +++ b/go/pkg/cs/drkey/service_engine.go @@ -0,0 +1,313 @@ +// Copyright 2020 ETH Zurich +// +// 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 drkey + +import ( + "context" + "time" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/infra/modules/cleaner" + "github.com/scionproto/scion/go/lib/log" + "github.com/scionproto/scion/go/lib/serrors" +) + +// Fetcher obtains a Lvl1 DRKey from a remote CS. +type Fetcher interface { + Lvl1(ctx context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) +} + +// ServiceEngine maintain and provides secret values, lvl1 keys and prefetching information. +type ServiceEngine interface { + // Storing SVs in the server allows for the server to still have access to + // handed out secrets even after rebooting. It is not critical to the server + // to derive secret values fast, so the lookup operation is acceptable. + + GetSecretValue(ctx context.Context, meta drkey.SVMeta) (drkey.SV, error) + + DeriveLvl1(meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) + DeriveASHost(ctx context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) + DeriveHostAS(ctx context.Context, meta drkey.HostASMeta) (drkey.HostASKey, error) + DeriveHostHost(ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) + GetLvl1Key(ctx context.Context, meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) + GetLvl1PrefetchInfo() []Lvl1PrefetchInfo + + DeleteExpiredKeys(ctx context.Context) (int, error) +} + +// NewServiceEngineCleaner creates a Cleaner task that removes expired lvl1 keys. +func NewServiceEngineCleaner(s ServiceEngine) *cleaner.Cleaner { + return cleaner.New(func(ctx context.Context) (int, error) { + return s.DeleteExpiredKeys(ctx) + }, "drkey_serv_store") +} + +// serviceEngine keeps track of the level 1 drkey keys. It is backed by a drkey.DB +type serviceEngine struct { + secretBackend *secretValueBackend + LocalIA addr.IA + DB drkey.Lvl1DB + Fetcher Fetcher + prefetchKeeper Lvl1PrefetchListKeeper +} + +var _ ServiceEngine = (*serviceEngine)(nil) + +func NewServiceEngine(localIA addr.IA, svdb drkey.SecretValueDB, masterKey []byte, + keyDur time.Duration, lvl1db drkey.Lvl1DB, fetcher Fetcher, + listSize int) (*serviceEngine, error) { + list, err := NewLvl1ARC(listSize) + if err != nil { + return nil, err + } + return &serviceEngine{ + secretBackend: newSecretValueBackend(svdb, masterKey, keyDur), + LocalIA: localIA, + DB: lvl1db, + Fetcher: fetcher, + prefetchKeeper: list, + }, nil +} + +// GetSecretValue returns a valid secret value for the provided metadata. +// It tries to retrieve the secret value from persistence, otherwise +// it creates a new one and stores it away. +func (s *serviceEngine) GetSecretValue(ctx context.Context, + meta drkey.SVMeta) (drkey.SV, error) { + return s.secretBackend.getSecretValue(ctx, meta) +} + +// GetLvl1Key returns the level 1 drkey from the local DB or if not found, by asking any CS in +// the source AS of the key. It also updates the Lvl1Cache, if needed +func (s *serviceEngine) GetLvl1Key(ctx context.Context, + meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + key, err := s.getLvl1Key(ctx, meta) + if err == nil && ctx.Value(fromPrefetcher{}) == nil && meta.SrcIA != s.LocalIA { + keyInfo := Lvl1PrefetchInfo{ + IA: key.SrcIA, + Proto: meta.ProtoId, + } + s.prefetchKeeper.Update(keyInfo) + } + return key, err +} + +func (s *serviceEngine) getLvl1Key(ctx context.Context, + meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + logger := log.FromCtx(ctx) + + if meta.SrcIA == s.LocalIA { + return s.DeriveLvl1(meta) + } + + if meta.DstIA != s.LocalIA { + return drkey.Lvl1Key{}, + serrors.New("Neither srcIA nor dstIA matches localIA", "srcIA", meta.SrcIA, + "dstIA", meta.DstIA, "localIA", s.LocalIA) + } + + // look in the DB + k, err := s.DB.GetLvl1Key(ctx, meta) + if err == nil { + logger.Debug("[DRKey Backend] L1 key found in storage") + return k, nil + } + if err != drkey.ErrKeyNotFound { + return drkey.Lvl1Key{}, serrors.WrapStr("retrieving key from DB", err) + } + + // get it from another server + remoteKey, err := s.Fetcher.Lvl1(ctx, meta) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("obtaining level 1 key from CS", err) + } + // keep it in our DB + err = s.DB.InsertLvl1Key(ctx, remoteKey) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("storing obtained key in DB", err) + } + return remoteKey, nil +} + +func (s *serviceEngine) obtainLvl1Key(ctx context.Context, + meta drkey.Lvl2Meta) (drkey.Lvl1Key, error) { + proto := meta.ProtoId + if !proto.IsPredefined() { + proto = drkey.Generic + } + lvl1Meta := drkey.Lvl1Meta{ + Validity: meta.Validity, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + ProtoId: proto, + } + return s.getLvl1Key(ctx, lvl1Meta) + +} + +func (s *serviceEngine) deleteExpiredLvl1Keys(ctx context.Context) (int, error) { + i, err := s.DB.DeleteExpiredLvl1Keys(ctx, time.Now()) + return int(i), err +} + +// DeleteExpiredKeys will remove any lvl1 expired keys. +func (s *serviceEngine) DeleteExpiredKeys(ctx context.Context) (int, error) { + lvl1Removed, err := s.deleteExpiredLvl1Keys(ctx) + if err != nil { + return int(lvl1Removed), err + } + svRemoved, err := s.secretBackend.deleteExpiredSV(ctx) + return int(lvl1Removed + svRemoved), err +} + +// GetLvl1PrefetchInfo returns a list of ASes currently in the cache. +func (s *serviceEngine) GetLvl1PrefetchInfo() []Lvl1PrefetchInfo { + return s.prefetchKeeper.GetLvl1InfoArray() +} + +// DeriveLvl1 returns a Lvl1 key based on the presented information +func (s *serviceEngine) DeriveLvl1(meta drkey.Lvl1Meta) (drkey.Lvl1Key, error) { + sv, err := s.GetSecretValue(context.Background(), drkey.SVMeta{ + ProtoId: meta.ProtoId, + Validity: meta.Validity, + }) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("getting secret value", err) + } + key, err := deriveLvl1(meta, sv) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("deriving level 1 key", err) + } + return key, nil +} + +func deriveLvl1(meta drkey.Lvl1Meta, sv drkey.SV) (drkey.Lvl1Key, error) { + key, err := (&drkey.SpecificDeriver{}).DeriveLvl1(meta, sv.Key) + if err != nil { + return drkey.Lvl1Key{}, serrors.WrapStr("computing lvl1 raw key", err) + } + return drkey.Lvl1Key{ + Epoch: sv.Epoch, + SrcIA: meta.SrcIA, + DstIA: meta.DstIA, + ProtoId: sv.ProtoId, + Key: key, + }, nil +} + +// DeriveASHost returns an AS-Host key based on the presented information +func (s *serviceEngine) DeriveASHost(ctx context.Context, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + // input size for the current implementation will be at most 2*aes.Blocksize + var key drkey.Key + var err error + + lvl1Key, err := s.obtainLvl1Key(ctx, meta.Lvl2Meta) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("getting lvl1 key", err) + } + + if meta.ProtoId.IsPredefined() { + key, err = (&drkey.SpecificDeriver{}).DeriveASHost(meta, lvl1Key.Key) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("parsing derivation input", err) + } + } else { + key, err = (&drkey.GenericDeriver{}).DeriveASHost(meta, lvl1Key.Key) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("parsing derivation input", err) + } + } + return drkey.ASHostKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1Key.Epoch, + SrcIA: lvl1Key.SrcIA, + DstIA: lvl1Key.DstIA, + DstHost: meta.DstHost, + Key: key, + }, nil +} + +// DeriveHostAS returns an Host-AS key based on the presented information +func (s *serviceEngine) DeriveHostAS(ctx context.Context, + meta drkey.HostASMeta) (drkey.HostASKey, error) { + // input size for the current implementation will be at most 2*aes.Blocksize + var key drkey.Key + var err error + + lvl1Key, err := s.obtainLvl1Key(ctx, meta.Lvl2Meta) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("getting lvl1 key", err) + } + + if meta.ProtoId.IsPredefined() { + key, err = (&drkey.SpecificDeriver{}).DeriveHostAS(meta, lvl1Key.Key) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("parsing derivation input", err) + } + } else { + key, err = (&drkey.GenericDeriver{}).DeriveHostAS(meta, lvl1Key.Key) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("parsing derivation input", err) + } + } + return drkey.HostASKey{ + ProtoId: meta.ProtoId, + Epoch: lvl1Key.Epoch, + SrcIA: lvl1Key.SrcIA, + DstIA: lvl1Key.DstIA, + SrcHost: meta.SrcHost, + Key: key, + }, nil +} + +// DeriveHostHost returns an Host-Host key based on the presented information +func (s *serviceEngine) DeriveHostHost(ctx context.Context, + meta drkey.HostHostMeta) (drkey.HostHostKey, error) { + hostASMeta := drkey.HostASMeta{ + Lvl2Meta: meta.Lvl2Meta, + SrcHost: meta.SrcHost, + } + // input size for the current implementation will be at most 2*aes.Blocksize + var key drkey.Key + var err error + + hostASKey, err := s.DeriveHostAS(ctx, hostASMeta) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("computing intermediate Host-AS key", err) + } + + if meta.ProtoId.IsPredefined() { + key, err = (&drkey.SpecificDeriver{}).DeriveHostToHost(meta.DstHost, hostASKey.Key) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("parsing derivation input", err) + } + } else { + key, err = (&drkey.GenericDeriver{}).DeriveHostToHost(meta.DstHost, hostASKey.Key) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("parsing derivation input", err) + } + } + return drkey.HostHostKey{ + ProtoId: hostASKey.ProtoId, + Epoch: hostASKey.Epoch, + SrcIA: hostASKey.SrcIA, + DstIA: hostASKey.DstIA, + SrcHost: hostASKey.SrcHost, + DstHost: meta.DstHost, + Key: key, + }, nil +} diff --git a/go/pkg/cs/drkey/service_engine_test.go b/go/pkg/cs/drkey/service_engine_test.go new file mode 100644 index 0000000000..7b0b0043bc --- /dev/null +++ b/go/pkg/cs/drkey/service_engine_test.go @@ -0,0 +1,191 @@ +// Copyright 2020 ETH Zurich +// +// 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 drkey_test + +import ( + "context" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/drkey/sqlite" + "github.com/scionproto/scion/go/lib/serrors" + "github.com/scionproto/scion/go/lib/util" + "github.com/scionproto/scion/go/lib/xtest" + cs_drkey "github.com/scionproto/scion/go/pkg/cs/drkey" + "github.com/scionproto/scion/go/pkg/cs/drkey/mock_drkey" +) + +var ( + masterKey = xtest.MustParseHexString("305554050357005ae398259bcdae7468") + srcIA = xtest.MustParseIA("1-ff00:0:112") + dstIA = xtest.MustParseIA("1-ff00:0:111") +) + +func TestGetSV(t *testing.T) { + svdb := newSVDatabase(t) + defer svdb.Close() + + store, err := cs_drkey.NewServiceEngine(srcIA, svdb, masterKey, time.Minute, nil, nil, 10) + require.NoError(t, err) + + meta := drkey.SVMeta{ + ProtoId: drkey.Generic, + Validity: util.SecsToTime(0).UTC(), + } + + rcvKey1, err := store.GetSecretValue(context.Background(), meta) + require.NoError(t, err) + meta.Validity = util.SecsToTime(1).UTC() + rcvKey2, err := store.GetSecretValue(context.Background(), meta) + require.NoError(t, err) + assert.EqualValues(t, rcvKey1, rcvKey2) + meta.Validity = util.SecsToTime(61).UTC() + rcvKey3, err := store.GetSecretValue(context.Background(), meta) + require.NoError(t, err) + assert.NotEqualValues(t, rcvKey1, rcvKey3) +} + +func TestDeriveLvl1Key(t *testing.T) { + svdb := newSVDatabase(t) + defer svdb.Close() + + store, err := cs_drkey.NewServiceEngine(srcIA, svdb, masterKey, time.Minute, nil, nil, 10) + require.NoError(t, err) + + meta := drkey.Lvl1Meta{ + DstIA: dstIA, + ProtoId: drkey.Protocol(0), + Validity: time.Now(), + } + + _, err = store.DeriveLvl1(meta) + require.NoError(t, err) +} + +func TestGetLvl1Key(t *testing.T) { + svdb := newSVDatabase(t) + defer svdb.Close() + lvl1db := newLvl1Database(t) + defer lvl1db.Close() + k := xtest.MustParseHexString("c584cad32613547c64823c756651b6f5") // just a level 1 key + + firstLvl1Key := drkey.Lvl1Key{ + Epoch: drkey.NewEpoch(0, 2), + SrcIA: srcIA, + DstIA: dstIA, + ProtoId: drkey.Generic, + } + copy(firstLvl1Key.Key[:], k) + secondLvl1Key := drkey.Lvl1Key{ + Epoch: drkey.NewEpoch(2, 4), + SrcIA: srcIA, + DstIA: dstIA, + ProtoId: drkey.Generic, + } + copy(secondLvl1Key.Key[:], k) + mctrl := gomock.NewController(t) + defer mctrl.Finish() + + fetcher := mock_drkey.NewMockFetcher(mctrl) + firstCall := fetcher.EXPECT().Lvl1(gomock.Any(), + gomock.Any()).Return(firstLvl1Key, nil) + secondCall := fetcher.EXPECT().Lvl1(gomock.Any(), + gomock.Any()).Return(secondLvl1Key, nil).After(firstCall) + fetcher.EXPECT().Lvl1(gomock.Any(), + gomock.Any()).Return(drkey.Lvl1Key{}, + serrors.New("error retrieving key")).After(secondCall) + + cache := mock_drkey.NewMockLvl1PrefetchListKeeper(mctrl) + // It must be called exactly 3 times + cache.EXPECT().Update(gomock.Any()).Times(3) + + store := cs_drkey.NewTestServiceEngine(dstIA, svdb, masterKey, + time.Minute, lvl1db, fetcher, cache) + + // it must fetch first key from remote + rcvKey1, err := store.GetLvl1Key(context.Background(), drkey.Lvl1Meta{ + ProtoId: firstLvl1Key.ProtoId, + DstIA: firstLvl1Key.DstIA, + SrcIA: firstLvl1Key.SrcIA, + Validity: util.SecsToTime(0).UTC(), + }) + require.NoError(t, err) + assert.Equal(t, firstLvl1Key, rcvKey1) + // it must not fetch key from remote and return previous key + rcvKey2, err := store.GetLvl1Key(context.Background(), drkey.Lvl1Meta{ + ProtoId: firstLvl1Key.ProtoId, + DstIA: firstLvl1Key.DstIA, + SrcIA: firstLvl1Key.SrcIA, + Validity: util.SecsToTime(1).UTC(), + }) + require.NoError(t, err) + assert.Equal(t, firstLvl1Key, rcvKey2) + // it must fetch second key from remote + rcvKey3, err := store.GetLvl1Key(context.Background(), drkey.Lvl1Meta{ + ProtoId: firstLvl1Key.ProtoId, + DstIA: firstLvl1Key.DstIA, + SrcIA: firstLvl1Key.SrcIA, + Validity: util.SecsToTime(3).UTC(), + }) + require.NoError(t, err) + assert.Equal(t, secondLvl1Key, rcvKey3) + //Simulate a call coming from the prefetcher, it must not update cache + pref_ctx := context.WithValue(context.Background(), cs_drkey.FromPrefetcher(), true) + rcvKey4, err := store.GetLvl1Key(pref_ctx, drkey.Lvl1Meta{ + ProtoId: firstLvl1Key.ProtoId, + DstIA: firstLvl1Key.DstIA, + SrcIA: firstLvl1Key.SrcIA, + Validity: util.SecsToTime(3).UTC(), + }) + require.NoError(t, err) + assert.Equal(t, secondLvl1Key, rcvKey4) + // This call returns an error, hence the cache must not be updated + _, err = store.GetLvl1Key(context.Background(), drkey.Lvl1Meta{ + ProtoId: firstLvl1Key.ProtoId, + DstIA: firstLvl1Key.DstIA, + SrcIA: firstLvl1Key.SrcIA, + Validity: util.SecsToTime(5).UTC(), + }) + require.Error(t, err) + //Requesting local key should not update the cache + locallvl1Meta := drkey.Lvl1Meta{ + SrcIA: dstIA, + DstIA: xtest.MustParseIA("1-ff00:0:111"), + ProtoId: drkey.Generic, + Validity: util.SecsToTime(1).UTC(), + } + _, err = store.GetLvl1Key(context.Background(), locallvl1Meta) + require.NoError(t, err) + +} + +func newLvl1Database(t *testing.T) *sqlite.Lvl1Backend { + db, err := sqlite.NewLvl1Backend("file::memory:") + require.NoError(t, err) + + return db +} + +func newSVDatabase(t *testing.T) *sqlite.SVBackend { + db, err := sqlite.NewSVBackend("file::memory:") + require.NoError(t, err) + + return db +} diff --git a/go/pkg/cs/drkey/service_store.go b/go/pkg/cs/drkey/service_store.go deleted file mode 100644 index d25df49787..0000000000 --- a/go/pkg/cs/drkey/service_store.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 drkey - -import ( - "context" - "database/sql" - "time" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkey/protocol" - "github.com/scionproto/scion/go/lib/drkeystorage" - "github.com/scionproto/scion/go/lib/log" - "github.com/scionproto/scion/go/lib/serrors" - "github.com/scionproto/scion/go/lib/util" -) - -// Fetcher obtains a Lvl1 DRKey from a remote CS. -type Fetcher interface { - GetLvl1FromOtherCS(ctx context.Context, - srcIA, dstIA addr.IA, valTime time.Time) (drkey.Lvl1Key, error) -} - -// ServiceStore keeps track of the level 1 drkey keys. It is backed by a drkey.DB . -type ServiceStore struct { - LocalIA addr.IA - DB drkey.Lvl1DB - SecretValues drkeystorage.SecretValueFactory - Fetcher Fetcher -} - -var _ drkeystorage.ServiceStore = (*ServiceStore)(nil) - -// GetLvl1Key returns the level 1 drkey from the local DB or if not found, by asking any CS in -// the source AS of the key. -func (s *ServiceStore) GetLvl1Key(ctx context.Context, meta drkey.Lvl1Meta, - valTime time.Time) (drkey.Lvl1Key, error) { - logger := log.FromCtx(ctx) - - if meta.SrcIA == s.LocalIA { - return s.DeriveLvl1(meta.DstIA, valTime) - } - - if meta.DstIA != s.LocalIA { - return drkey.Lvl1Key{}, - serrors.New("Neither srcIA nor dstIA matches localIA", "srcIA", meta.SrcIA, - "dstIA", meta.DstIA, "localIA", s.LocalIA) - } - - // look in the DB - k, err := s.DB.GetLvl1Key(ctx, meta, util.TimeToSecs(valTime)) - if err == nil { - logger.Debug("[DRKey ServiceStore] L1 key found in storage") - return k, err - } - if err != sql.ErrNoRows { - return drkey.Lvl1Key{}, serrors.WrapStr("retrieving key from DB", err) - } - // get it from another server - k, err = s.Fetcher.GetLvl1FromOtherCS(ctx, meta.SrcIA, meta.DstIA, valTime) - if err != nil { - return drkey.Lvl1Key{}, serrors.WrapStr("obtaining level 1 key from CS", err) - } - // keep it in our DB - err = s.DB.InsertLvl1Key(ctx, k) - if err != nil { - return drkey.Lvl1Key{}, serrors.WrapStr("storing obtained key in DB", err) - } - return k, nil -} - -// DeleteExpiredKeys will remove any expired keys. -func (s *ServiceStore) DeleteExpiredKeys(ctx context.Context) (int, error) { - i, err := s.DB.RemoveOutdatedLvl1Keys(ctx, util.TimeToSecs(time.Now())) - return int(i), err -} - -// KnownASes returns a list with distinct AS seen as sources in level 1 DRKeys. -func (s *ServiceStore) KnownASes(ctx context.Context) ([]addr.IA, error) { - return s.DB.GetLvl1SrcASes(ctx) -} - -// DeriveLvl1 returns a Lvl1 DRKey based on present information -func (s *ServiceStore) DeriveLvl1(dstIA addr.IA, valTime time.Time) (drkey.Lvl1Key, error) { - sv, err := s.SecretValues.GetSecretValue(valTime) - if err != nil { - return drkey.Lvl1Key{}, serrors.WrapStr("getting secret value", err) - } - meta := drkey.Lvl1Meta{ - Epoch: sv.Epoch, - SrcIA: s.LocalIA, - DstIA: dstIA, - } - key, err := protocol.DeriveLvl1(meta, sv) - if err != nil { - return drkey.Lvl1Key{}, serrors.WrapStr("deriving level 1 key", err) - } - return key, nil -} diff --git a/go/pkg/cs/drkey/service_store_test.go b/go/pkg/cs/drkey/service_store_test.go deleted file mode 100644 index 5638baa4b8..0000000000 --- a/go/pkg/cs/drkey/service_store_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 drkey_test - -import ( - "context" - "testing" - "time" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkey/drkeydbsqlite" - "github.com/scionproto/scion/go/lib/util" - "github.com/scionproto/scion/go/lib/xtest" - cs_drkey "github.com/scionproto/scion/go/pkg/cs/drkey" - "github.com/scionproto/scion/go/pkg/cs/drkey/mock_drkey" - "github.com/scionproto/scion/go/pkg/cs/drkey/test" -) - -func TestDeriveLvl1Key(t *testing.T) { - srcIA := xtest.MustParseIA("1-ff00:0:112") - dstIA := xtest.MustParseIA("1-ff00:0:111") - expectedKey := xtest.MustParseHexString("87ee10bcc9ef1501783949a267f8ec6b") - - store := cs_drkey.ServiceStore{ - LocalIA: srcIA, - SecretValues: test.GetSecretValueTestFactory(), - } - lvl1Key, err := store.DeriveLvl1(dstIA, time.Now()) - require.NoError(t, err) - require.EqualValues(t, expectedKey, lvl1Key.Key) -} - -func TestGetLvl1Key(t *testing.T) { - lvl1db := newLvl1Database(t) - defer lvl1db.Close() - localIA := xtest.MustParseIA("1-ff00:0:110") - dstIA := localIA - srcIA := xtest.MustParseIA("1-ff00:0:111") - k := xtest.MustParseHexString("c584cad32613547c64823c756651b6f5") // just a level 1 key - - firstLvl1Key := drkey.Lvl1Key{ - Key: k, - Lvl1Meta: drkey.Lvl1Meta{ - Epoch: drkey.NewEpoch(0, 2), - SrcIA: srcIA, - DstIA: dstIA, - }, - } - secondLvl1Key := drkey.Lvl1Key{ - Key: k, - Lvl1Meta: drkey.Lvl1Meta{ - Epoch: drkey.NewEpoch(2, 4), - SrcIA: srcIA, - DstIA: dstIA, - }, - } - - mctrl := gomock.NewController(t) - defer mctrl.Finish() - - fetcher := mock_drkey.NewMockFetcher(mctrl) - firstCall := fetcher.EXPECT().GetLvl1FromOtherCS(gomock.Any(), gomock.Any(), gomock.Any(), - gomock.Any()).Return(firstLvl1Key, nil) - fetcher.EXPECT().GetLvl1FromOtherCS(gomock.Any(), gomock.Any(), gomock.Any(), - gomock.Any()).Return(secondLvl1Key, nil).After(firstCall) - - store := &cs_drkey.ServiceStore{ - LocalIA: localIA, - DB: lvl1db, - Fetcher: fetcher, - } - - // it must fetch first key from remote - rcvKey1, err := store.GetLvl1Key(context.Background(), firstLvl1Key.Lvl1Meta, - util.SecsToTime(0).UTC()) - require.NoError(t, err) - assert.Equal(t, firstLvl1Key, rcvKey1) - // it must not fetch key from remote and return previous key - rcvKey2, err := store.GetLvl1Key(context.Background(), firstLvl1Key.Lvl1Meta, - util.SecsToTime(1).UTC()) - require.NoError(t, err) - assert.Equal(t, firstLvl1Key, rcvKey2) - // it must fetch second key from remote - rcvKey3, err := store.GetLvl1Key(context.Background(), firstLvl1Key.Lvl1Meta, - util.SecsToTime(3).UTC()) - require.NoError(t, err) - assert.Equal(t, secondLvl1Key, rcvKey3) -} - -func newLvl1Database(t *testing.T) *drkeydbsqlite.Lvl1Backend { - db, err := drkeydbsqlite.NewLvl1Backend("file::memory:") - require.NoError(t, err) - - return db -} diff --git a/go/pkg/cs/drkey/test/testcommons.go b/go/pkg/cs/drkey/test/testcommons.go deleted file mode 100644 index f160b598fc..0000000000 --- a/go/pkg/cs/drkey/test/testcommons.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkeystorage" - "github.com/scionproto/scion/go/lib/util" - "github.com/scionproto/scion/go/lib/xtest" - csdrkey "github.com/scionproto/scion/go/pkg/cs/drkey" -) - -func getTestMasterSecret() []byte { - return []byte{0, 1, 2, 3} -} - -// SecretValueTestFactory works as a SecretValueFactory but uses a user-controlled-variable instead -// of time.Now when calling GetSecretValue. -type SecretValueTestFactory struct { - csdrkey.SecretValueFactory - Now time.Time -} - -func (f *SecretValueTestFactory) GetSecretValue(_ time.Time) (drkey.SV, error) { - return f.SecretValueFactory.GetSecretValue(f.Now) -} - -func GetSecretValueTestFactory() drkeystorage.SecretValueFactory { - return &SecretValueTestFactory{ - SecretValueFactory: *csdrkey.NewSecretValueFactory(getTestMasterSecret(), 10*time.Second), - Now: util.SecsToTime(0), - } -} - -func GetInputToDeriveLvl2Key(t *testing.T) (drkey.Lvl2Meta, drkey.Lvl1Key) { - srcIA := xtest.MustParseIA("1-ff00:0:1") - dstIA := xtest.MustParseIA("1-ff00:0:2") - k := xtest.MustParseHexString("c584cad32613547c64823c756651b6f5") // just a level 1 key - - sv, err := GetSecretValueTestFactory().GetSecretValue(util.SecsToTime(0)) - require.NoError(t, err) - - lvl1Key := drkey.Lvl1Key{ - Key: k, - Lvl1Meta: drkey.Lvl1Meta{ - Epoch: sv.Epoch, - SrcIA: srcIA, - DstIA: dstIA, - }, - } - - var srcHost addr.HostAddr = addr.HostNone{} - var dstHost addr.HostAddr = addr.HostNone{} - meta := drkey.Lvl2Meta{ - KeyType: drkey.AS2AS, - Protocol: "scmp", - Epoch: lvl1Key.Epoch, - SrcIA: srcIA, - DstIA: dstIA, - SrcHost: srcHost, - DstHost: dstHost, - } - return meta, lvl1Key -} diff --git a/go/pkg/cs/tasks.go b/go/pkg/cs/tasks.go index a60e382ce8..9c6253df89 100644 --- a/go/pkg/cs/tasks.go +++ b/go/pkg/cs/tasks.go @@ -25,7 +25,6 @@ import ( "github.com/scionproto/scion/go/cs/ifstate" "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/ctrl/seg" - "github.com/scionproto/scion/go/lib/drkeystorage" "github.com/scionproto/scion/go/lib/infra/modules/seghandler" "github.com/scionproto/scion/go/lib/metrics" "github.com/scionproto/scion/go/lib/pathdb" @@ -60,7 +59,7 @@ type TasksConfig struct { Signer seg.Signer Inspector trust.Inspector Metrics *Metrics - DRKeyStore drkeystorage.ServiceStore + DRKeyEngine drkey.ServiceEngine MACGen func() hash.Hash StaticInfo func() *beaconing.StaticInfoCfg @@ -214,26 +213,24 @@ func (t *TasksConfig) extender(task string, ia addr.IA, mtu uint16, } } -func (t *TasksConfig) DRKeyCleaner() *periodic.Runner { - if t.DRKeyStore == nil { +func (t *TasksConfig) DRKeyLvl1Cleaner() *periodic.Runner { + if t.DRKeyEngine == nil { return nil } - // TODO(juagargi): if there has been a change in the duration, we need to keep - // the already sent keys (and their duration) as they were already handed to other entities cleanerPeriod := 2 * t.DRKeyEpochInterval - return periodic.Start(drkeystorage.NewStoreCleaner(t.DRKeyStore), + return periodic.Start(drkey.NewServiceEngineCleaner(t.DRKeyEngine), cleanerPeriod, cleanerPeriod) } func (t *TasksConfig) DRKeyPrefetcher() *periodic.Runner { - if t.DRKeyStore == nil { + if t.DRKeyEngine == nil { return nil } prefetchPeriod := t.DRKeyEpochInterval / 2 return periodic.Start( &drkey.Prefetcher{ LocalIA: t.IA, - Store: t.DRKeyStore, + Engine: t.DRKeyEngine, KeyDuration: t.DRKeyEpochInterval, }, prefetchPeriod, prefetchPeriod) @@ -246,8 +243,10 @@ type Tasks struct { Registrars []*periodic.Runner DRKeyPrefetcher *periodic.Runner - PathCleaner *periodic.Runner - DRKeyCleaner *periodic.Runner + BeaconCleaner *periodic.Runner + PathCleaner *periodic.Runner + DRKeyLvl1Cleaner *periodic.Runner + DRKeySVCleaner *periodic.Runner } func StartTasks(cfg TasksConfig) (*Tasks, error) { @@ -270,7 +269,7 @@ func StartTasks(cfg TasksConfig) (*Tasks, error) { 10*time.Second, 10*time.Second, ), - DRKeyCleaner: cfg.DRKeyCleaner(), + DRKeyLvl1Cleaner: cfg.DRKeyLvl1Cleaner(), }, nil } @@ -285,14 +284,16 @@ func (t *Tasks) Kill() { t.Propagator, t.DRKeyPrefetcher, t.PathCleaner, - t.DRKeyCleaner, + t.DRKeyLvl1Cleaner, + t.DRKeySVCleaner, }) killRunners(t.Registrars) t.Originator = nil t.Propagator = nil t.DRKeyPrefetcher = nil t.PathCleaner = nil - t.DRKeyCleaner = nil + t.DRKeyLvl1Cleaner = nil + t.DRKeySVCleaner = nil t.Registrars = nil } diff --git a/go/pkg/daemon/BUILD.bazel b/go/pkg/daemon/BUILD.bazel index 1ad8fac8a5..6f9e2b7753 100644 --- a/go/pkg/daemon/BUILD.bazel +++ b/go/pkg/daemon/BUILD.bazel @@ -8,7 +8,6 @@ go_library( deps = [ "//go/lib/addr:go_default_library", "//go/lib/daemon:go_default_library", - "//go/lib/drkeystorage:go_default_library", "//go/lib/env:go_default_library", "//go/lib/log:go_default_library", "//go/lib/metrics:go_default_library", @@ -16,6 +15,7 @@ go_library( "//go/lib/revcache:go_default_library", "//go/lib/serrors:go_default_library", "//go/pkg/daemon/colibri:go_default_library", + "//go/pkg/daemon/drkey:go_default_library", "//go/pkg/daemon/fetcher:go_default_library", "//go/pkg/daemon/internal/servers:go_default_library", "//go/pkg/grpc:go_default_library", diff --git a/go/pkg/daemon/config/config.go b/go/pkg/daemon/config/config.go index 6b6713c005..aecd630e77 100644 --- a/go/pkg/daemon/config/config.go +++ b/go/pkg/daemon/config/config.go @@ -46,7 +46,7 @@ type Config struct { Tracing env.Tracing `toml:"tracing,omitempty"` TrustDB storage.DBConfig `toml:"trust_db,omitempty"` PathDB storage.DBConfig `toml:"path_db,omitempty"` - DRKeyDB storage.DBConfig `toml:"drkey_db,omitempty"` + DRKeyLvl2DB storage.DBConfig `toml:"drkey_lvl2_db,omitempty"` SD SDConfig `toml:"sd,omitempty"` TrustEngine trustengine.Config `toml:"trustengine,omitempty"` } @@ -75,7 +75,7 @@ func (cfg *Config) Validate() error { &cfg.API, &cfg.TrustDB, &cfg.PathDB, - &cfg.DRKeyDB, + &cfg.DRKeyLvl2DB, &cfg.SD, &cfg.TrustEngine, ) @@ -105,10 +105,10 @@ func (cfg *Config) Sample(dst io.Writer, path config.Path, _ config.CtxMap) { ), config.OverrideName( config.FormatData( - &cfg.DRKeyDB, - fmt.Sprintf(storage.DefaultDRKeyDBPath, "sd"), + &cfg.DRKeyLvl2DB, + fmt.Sprintf(storage.DefaultDRKeyLvl2DBPath, "sd"), ), - "drkey_db", + "drkey_lvl2_db", ), &cfg.SD, &cfg.TrustEngine, diff --git a/go/pkg/daemon/daemon.go b/go/pkg/daemon/daemon.go index 4f6905e293..4705ad04dd 100644 --- a/go/pkg/daemon/daemon.go +++ b/go/pkg/daemon/daemon.go @@ -27,7 +27,6 @@ import ( "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/daemon" - "github.com/scionproto/scion/go/lib/drkeystorage" "github.com/scionproto/scion/go/lib/env" "github.com/scionproto/scion/go/lib/log" "github.com/scionproto/scion/go/lib/metrics" @@ -35,6 +34,7 @@ import ( "github.com/scionproto/scion/go/lib/revcache" "github.com/scionproto/scion/go/lib/serrors" "github.com/scionproto/scion/go/pkg/daemon/colibri" + "github.com/scionproto/scion/go/pkg/daemon/drkey" "github.com/scionproto/scion/go/pkg/daemon/fetcher" "github.com/scionproto/scion/go/pkg/daemon/internal/servers" libgrpc "github.com/scionproto/scion/go/pkg/grpc" @@ -108,15 +108,15 @@ func TrustEngine( // ServerConfig is the configuration for the daemon API server. type ServerConfig struct { - IA addr.IA - MTU uint16 - Fetcher fetcher.Fetcher - RevCache revcache.RevCache - Engine trust.Engine - Topology servers.Topology - DRKeyStore drkeystorage.ClientStore - ColFetcher colibri.Fetcher - ColClient *colibri.DaemonClient + IA addr.IA + MTU uint16 + Fetcher fetcher.Fetcher + RevCache revcache.RevCache + Engine trust.Engine + Topology servers.Topology + DRKeyClient drkey.ClientEngine + ColFetcher colibri.Fetcher + ColClient *colibri.DaemonClient } // NewServer constructs a daemon API server. @@ -128,7 +128,7 @@ func NewServer(cfg ServerConfig) *servers.DaemonServer { ASInspector: cfg.Engine.Inspector, RevCache: cfg.RevCache, Topology: cfg.Topology, - DRKeyStore: cfg.DRKeyStore, + DRKeyClient: cfg.DRKeyClient, ColFetcher: cfg.ColFetcher, ColClient: cfg.ColClient, Metrics: servers.Metrics{ diff --git a/go/pkg/daemon/drkey/BUILD.bazel b/go/pkg/daemon/drkey/BUILD.bazel index b76b94faee..2d9448a38a 100644 --- a/go/pkg/daemon/drkey/BUILD.bazel +++ b/go/pkg/daemon/drkey/BUILD.bazel @@ -2,15 +2,13 @@ load("//lint:go.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["client_store.go"], + srcs = ["client_engine.go"], importpath = "github.com/scionproto/scion/go/pkg/daemon/drkey", visibility = ["//visibility:public"], deps = [ "//go/lib/addr:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkeystorage:go_default_library", - "//go/lib/log:go_default_library", + "//go/lib/infra/modules/cleaner:go_default_library", "//go/lib/serrors:go_default_library", - "//go/lib/util:go_default_library", ], ) diff --git a/go/pkg/daemon/drkey/client_engine.go b/go/pkg/daemon/drkey/client_engine.go new file mode 100644 index 0000000000..0bea82fcb2 --- /dev/null +++ b/go/pkg/daemon/drkey/client_engine.go @@ -0,0 +1,144 @@ +// Copyright 2020 ETH Zurich +// +// 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 drkey + +import ( + "context" + "time" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/infra/modules/cleaner" + "github.com/scionproto/scion/go/lib/serrors" +) + +// ClientEngine manages secret values and lvl2 keys and provides them to end hosts. +type ClientEngine interface { + GetASHostKey(ctx context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) + GetHostASKey(ctx context.Context, meta drkey.HostASMeta) (drkey.HostASKey, error) + GetHostHostKey(ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) + DeleteExpiredKeys(ctx context.Context) (int, error) +} + +// NewClientEngineCleaner creates a Cleaner task that removes expired lvl2 keys. +func NewClientEngineCleaner(s ClientEngine) *cleaner.Cleaner { + return cleaner.New(func(ctx context.Context) (int, error) { + return s.DeleteExpiredKeys(ctx) + }, "drkey_client_store") +} + +// Fetcher obtains a end host keys from the local CS. +type Fetcher interface { + ASHostKey(ctx context.Context, meta drkey.ASHostMeta) (drkey.ASHostKey, error) + HostASKey(ctx context.Context, meta drkey.HostASMeta) (drkey.HostASKey, error) + HostHostKey(ctx context.Context, meta drkey.HostHostMeta) (drkey.HostHostKey, error) +} + +// clientEngine is the DRKey store used in the client side. +type clientEngine struct { + ia addr.IA + db drkey.Lvl2DB + fetcher Fetcher +} + +var _ ClientEngine = &clientEngine{} + +// NewClientEngine constructs a new client store without assigned messenger. +func NewClientEngine(local addr.IA, db drkey.Lvl2DB, fetcher Fetcher) *clientEngine { + return &clientEngine{ + ia: local, + db: db, + fetcher: fetcher, + } +} + +// GetASHostKey returns the ASHost key from the local DB or if not found, by asking our local CS. +func (s *clientEngine) GetASHostKey(ctx context.Context, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + + // is it in storage? + k, err := s.db.GetASHostKey(ctx, meta) + if err == nil { + return k, nil + } + if err != drkey.ErrKeyNotFound { + return drkey.ASHostKey{}, serrors.WrapStr("looking up AS-HOST key in DB", err) + } + + // if not, ask our CS for it + remoteKey, err := s.fetcher.ASHostKey(ctx, meta) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("fetching AS-Host key from local CS", err) + } + if err = s.db.InsertASHostKey(ctx, remoteKey); err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("inserting AS-Host key in DB", err) + } + return remoteKey, nil +} + +// GetHostASKey returns the HostAS key from the local DB or if not found, by asking our local CS. +func (s *clientEngine) GetHostASKey(ctx context.Context, + meta drkey.HostASMeta) (drkey.HostASKey, error) { + + // is it in storage? + k, err := s.db.GetHostASKey(ctx, meta) + if err == nil { + return k, nil + } + if err != drkey.ErrKeyNotFound { + return drkey.HostASKey{}, serrors.WrapStr("looking up Host-AS key in DB", err) + } + // if not, ask our CS for it + + remoteKey, err := s.fetcher.HostASKey(ctx, meta) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("fetching Host-AS key from local CS", err) + } + if err = s.db.InsertHostASKey(ctx, remoteKey); err != nil { + return drkey.HostASKey{}, serrors.WrapStr("inserting Host-AS key in DB", err) + } + return remoteKey, nil +} + +// GetHostHostKey returns the HostHost key from the local DB or if not found, +// by asking our local CS. +func (s *clientEngine) GetHostHostKey(ctx context.Context, + meta drkey.HostHostMeta) (drkey.HostHostKey, error) { + + // is it in storage? + k, err := s.db.GetHostHostKey(ctx, meta) + if err == nil { + return k, nil + } + if err != drkey.ErrKeyNotFound { + return drkey.HostHostKey{}, serrors.WrapStr("looking up Host-Host key in DB", err) + } + // if not, ask our CS for it + + remoteKey, err := s.fetcher.HostHostKey(ctx, meta) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("fetching Host-Host key from local CS", err) + } + if err = s.db.InsertHostHostKey(ctx, remoteKey); err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("inserting Host-Host key in DB", err) + } + return remoteKey, nil +} + +// DeleteExpiredKeys will remove any expired keys. +func (s *clientEngine) DeleteExpiredKeys(ctx context.Context) (int, error) { + i, err := s.db.DeleteExpiredLvl2Keys(ctx, time.Now()) + return int(i), err +} diff --git a/go/pkg/daemon/drkey/client_store.go b/go/pkg/daemon/drkey/client_store.go deleted file mode 100644 index dd99bf8096..0000000000 --- a/go/pkg/daemon/drkey/client_store.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 drkey - -import ( - "context" - "database/sql" - "time" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkeystorage" - "github.com/scionproto/scion/go/lib/log" - "github.com/scionproto/scion/go/lib/serrors" - "github.com/scionproto/scion/go/lib/util" -) - -// Fetcher obtains a Lvl2 DRKey from the local CS. -type Fetcher interface { - GetDRKeyLvl2(ctx context.Context, meta drkey.Lvl2Meta, a addr.IA, - valTime time.Time) (drkey.Lvl2Key, error) -} - -// ClientStore is the DRKey store used in the client side, i.e. sciond. -// It implements drkeystorage.ClientStore. -type ClientStore struct { - ia addr.IA - db drkey.Lvl2DB - fetcher Fetcher -} - -var _ drkeystorage.ClientStore = &ClientStore{} - -// NewClientStore constructs a new client store without assigned messenger. -func NewClientStore(local addr.IA, db drkey.Lvl2DB, fetcher Fetcher) *ClientStore { - return &ClientStore{ - ia: local, - db: db, - fetcher: fetcher, - } -} - -// GetLvl2Key returns the level 2 drkey from the local DB or if not found, by asking our local CS. -func (s *ClientStore) GetLvl2Key(ctx context.Context, meta drkey.Lvl2Meta, - valTime time.Time) (drkey.Lvl2Key, error) { - - logger := log.FromCtx(ctx) - // is it in storage? - k, err := s.db.GetLvl2Key(ctx, meta, util.TimeToSecs(valTime)) - if err == nil { - return k, err - } - if err != sql.ErrNoRows { - return drkey.Lvl2Key{}, serrors.WrapStr("looking up level 2 key in DB", err) - } - logger.Debug("[DRKey ClientStore] Level 2 key not stored. Requesting it to CS") - // if not, ask our CS for it - - k, err = s.fetcher.GetDRKeyLvl2(ctx, meta, s.ia, valTime) - if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("fetching lvl2 key from local CS", err) - } - if err = s.db.InsertLvl2Key(ctx, k); err != nil { - logger.Error("[DRKey ClientStore] Could not insert level 2 in DB", "error", err) - return k, serrors.WrapStr("inserting level 2 key in DB", err) - } - return k, nil -} - -// DeleteExpiredKeys will remove any expired keys. -func (s *ClientStore) DeleteExpiredKeys(ctx context.Context) (int, error) { - i, err := s.db.RemoveOutdatedLvl2Keys(ctx, util.TimeToSecs(time.Now())) - return int(i), err -} diff --git a/go/pkg/daemon/drkey/grpc/BUILD.bazel b/go/pkg/daemon/drkey/grpc/BUILD.bazel index 4197bf599d..885ee20acb 100644 --- a/go/pkg/daemon/drkey/grpc/BUILD.bazel +++ b/go/pkg/daemon/drkey/grpc/BUILD.bazel @@ -2,7 +2,7 @@ load("//lint:go.bzl", "go_library", "go_test") go_library( name = "go_default_library", - srcs = ["lvl2_fetcher.go"], + srcs = ["fetcher.go"], importpath = "github.com/scionproto/scion/go/pkg/daemon/drkey/grpc", visibility = ["//visibility:public"], deps = [ @@ -18,7 +18,7 @@ go_library( go_test( name = "go_default_test", - srcs = ["lvl2_fetching_test.go"], + srcs = ["fetching_test.go"], deps = [ ":go_default_library", "//go/lib/drkey:go_default_library", diff --git a/go/pkg/daemon/drkey/grpc/fetcher.go b/go/pkg/daemon/drkey/grpc/fetcher.go new file mode 100644 index 0000000000..09397fa6a8 --- /dev/null +++ b/go/pkg/daemon/drkey/grpc/fetcher.go @@ -0,0 +1,115 @@ +// Copyright 2020 ETH Zurich +// +// 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 grpc + +import ( + "context" + + "github.com/scionproto/scion/go/lib/addr" + ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" + "github.com/scionproto/scion/go/lib/drkey" + "github.com/scionproto/scion/go/lib/serrors" + sd_drkey "github.com/scionproto/scion/go/pkg/daemon/drkey" + sc_grpc "github.com/scionproto/scion/go/pkg/grpc" + cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" +) + +// DRKeyFetcher obtains end-host key from the local CS. +type Fetcher struct { + Dialer sc_grpc.Dialer +} + +var _ sd_drkey.Fetcher = (*Fetcher)(nil) + +func (f Fetcher) ASHostKey(ctx context.Context, + meta drkey.ASHostMeta) (drkey.ASHostKey, error) { + + conn, err := f.Dialer.Dial(ctx, addr.SvcCS) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := cppb.NewDRKeyIntraServiceClient(conn) + protoReq, err := ctrl.ASHostMetaToProtoRequest(meta) + if err != nil { + return drkey.ASHostKey{}, + serrors.WrapStr("parsing AS-HOST request to protobuf", err) + } + rep, err := client.ASHost(ctx, protoReq) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("requesting AS-HOST key", err) + } + + key, err := ctrl.GetASHostKeyFromReply(rep, meta) + if err != nil { + return drkey.ASHostKey{}, serrors.WrapStr("obtaining AS-HOST key from reply", err) + } + + return key, nil +} + +func (f Fetcher) HostASKey(ctx context.Context, + meta drkey.HostASMeta) (drkey.HostASKey, error) { + + conn, err := f.Dialer.Dial(ctx, addr.SvcCS) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := cppb.NewDRKeyIntraServiceClient(conn) + protoReq, err := ctrl.HostASMetaToProtoRequest(meta) + if err != nil { + return drkey.HostASKey{}, + serrors.WrapStr("parsing HOST-AS request to protobuf", err) + } + rep, err := client.HostAS(ctx, protoReq) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("requesting HOST-AS key", err) + } + + key, err := ctrl.GetHostASKeyFromReply(rep, meta) + if err != nil { + return drkey.HostASKey{}, serrors.WrapStr("obtaining HOST-AS key from reply", err) + } + + return key, nil +} + +func (f Fetcher) HostHostKey(ctx context.Context, + meta drkey.HostHostMeta) (drkey.HostHostKey, error) { + + conn, err := f.Dialer.Dial(ctx, addr.SvcCS) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("dialing", err) + } + defer conn.Close() + client := cppb.NewDRKeyIntraServiceClient(conn) + protoReq, err := ctrl.HostHostMetaToProtoRequest(meta) + if err != nil { + return drkey.HostHostKey{}, + serrors.WrapStr("parsing HOST-AS request to protobuf", err) + } + rep, err := client.HostHost(ctx, protoReq) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("requesting Host-Host key", err) + } + + key, err := ctrl.GetHostHostKeyFromReply(rep, meta) + if err != nil { + return drkey.HostHostKey{}, serrors.WrapStr("obtaining Host-Host key from reply", err) + } + + return key, nil +} diff --git a/go/pkg/daemon/drkey/grpc/lvl2_fetching_test.go b/go/pkg/daemon/drkey/grpc/fetching_test.go similarity index 75% rename from go/pkg/daemon/drkey/grpc/lvl2_fetching_test.go rename to go/pkg/daemon/drkey/grpc/fetching_test.go index 1b4b96f182..89c4f2805d 100644 --- a/go/pkg/daemon/drkey/grpc/lvl2_fetching_test.go +++ b/go/pkg/daemon/drkey/grpc/fetching_test.go @@ -36,14 +36,14 @@ import ( drkey_pb "github.com/scionproto/scion/go/pkg/proto/drkey" ) -func dialer(drkeyServer cppb.DRKeyLvl2ServiceServer) func(context.Context, +func dialer(drkeyServer cppb.DRKeyIntraServiceServer) func(context.Context, string) (net.Conn, error) { bufsize := 1024 * 1024 listener := bufconn.Listen(bufsize) server := grpc.NewServer() - cppb.RegisterDRKeyLvl2ServiceServer(server, drkeyServer) + cppb.RegisterDRKeyIntraServiceServer(server, drkeyServer) go func() { if err := server.Serve(listener); err != nil { @@ -56,7 +56,7 @@ func dialer(drkeyServer cppb.DRKeyLvl2ServiceServer) func(context.Context, } } -func TestLvl2KeyFetching(t *testing.T) { +func TestGetHostHost(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -67,20 +67,14 @@ func TestLvl2KeyFetching(t *testing.T) { epochEnd, err := ptypes.TimestampProto(now.Add(24 * time.Hour)) require.NoError(t, err) - timestamp, err := ptypes.TimestampProto(time.Now().UTC()) - require.NoError(t, err) - - resp := &cppb.DRKeyLvl2Response{ - BaseRep: &drkey_pb.DRKeyLvl2Response{ - Timestamp: timestamp, - Drkey: xtest.MustParseHexString("c584cad32613547c64823c756651b6f5"), - EpochBegin: epochBegin, - EpochEnd: epochEnd, - }, + resp := &drkey_pb.HostHostResponse{ + Key: xtest.MustParseHexString("c584cad32613547c64823c756651b6f5"), + EpochBegin: epochBegin, + EpochEnd: epochEnd, } - daemonSrv := mock_cppb.NewMockDRKeyLvl2ServiceServer(ctrl) - daemonSrv.EXPECT().DRKeyLvl2(gomock.Any(), + daemonSrv := mock_cppb.NewMockDRKeyIntraServiceServer(ctrl) + daemonSrv.EXPECT().HostHost(gomock.Any(), gomock.Any()).Return( resp, nil, @@ -97,11 +91,11 @@ func TestLvl2KeyFetching(t *testing.T) { dialer := mock_grpc.NewMockDialer(ctrl) dialer.EXPECT().Dial(gomock.Any(), gomock.Any()).Return(conn, nil) - fetcher := sd_grpc.DRKeyFetcher{ + fetcher := sd_grpc.Fetcher{ Dialer: dialer, } - meta := drkey.Lvl2Meta{} - _, err = fetcher.GetDRKeyLvl2(context.Background(), meta, 0, now) + meta := drkey.HostHostMeta{} + _, err = fetcher.HostHostKey(context.Background(), meta) require.NoError(t, err) } diff --git a/go/pkg/daemon/drkey/grpc/lvl2_fetcher.go b/go/pkg/daemon/drkey/grpc/lvl2_fetcher.go deleted file mode 100644 index 0b41a24129..0000000000 --- a/go/pkg/daemon/drkey/grpc/lvl2_fetcher.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 grpc - -import ( - "context" - "time" - - "github.com/scionproto/scion/go/lib/addr" - ctrl "github.com/scionproto/scion/go/lib/ctrl/drkey" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/serrors" - sd_drkey "github.com/scionproto/scion/go/pkg/daemon/drkey" - sc_grpc "github.com/scionproto/scion/go/pkg/grpc" - cppb "github.com/scionproto/scion/go/pkg/proto/control_plane" -) - -// DRKeyFetcher obtains Lvl2 DRKey from the local CS. -type DRKeyFetcher struct { - Dialer sc_grpc.Dialer -} - -var _ sd_drkey.Fetcher = (*DRKeyFetcher)(nil) - -// GetDRKeyLvl2 fetches the Lvl2Key corresponding to the metadata by requesting -// the CS. -func (f DRKeyFetcher) GetDRKeyLvl2(ctx context.Context, lvl2meta drkey.Lvl2Meta, - dstIA addr.IA, valTime time.Time) (drkey.Lvl2Key, error) { - - // logger := log.FromCtx(ctx) - conn, err := f.Dialer.Dial(ctx, addr.SvcCS) - if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("dialing", err) - } - defer conn.Close() - client := cppb.NewDRKeyLvl2ServiceClient(conn) - lvl2req := ctrl.NewLvl2ReqFromMeta(lvl2meta, valTime) - req, err := lvl2reqToProtoRequest(lvl2req) - if err != nil { - return drkey.Lvl2Key{}, - serrors.WrapStr("parsing lvl2 request to protobuf", err) - } - rep, err := client.DRKeyLvl2(ctx, req) - if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("requesting level 2 key", err) - } - - lvl2Key, err := getLvl2KeyFromReply(rep, lvl2meta) - if err != nil { - return drkey.Lvl2Key{}, serrors.WrapStr("obtaining level 2 key from reply", err) - } - - return lvl2Key, nil -} - -func lvl2reqToProtoRequest(req ctrl.Lvl2Req) (*cppb.DRKeyLvl2Request, error) { - baseReq, err := ctrl.Lvl2reqToProtoRequest(req) - if err != nil { - return nil, err - } - return &cppb.DRKeyLvl2Request{ - BaseReq: baseReq, - }, nil -} - -// getLvl2KeyFromReply decrypts and extracts the level 1 drkey from the reply. -func getLvl2KeyFromReply(rep *cppb.DRKeyLvl2Response, meta drkey.Lvl2Meta) (drkey.Lvl2Key, error) { - return ctrl.GetLvl2KeyFromReply(rep.BaseRep, meta) -} diff --git a/go/pkg/daemon/internal/servers/BUILD.bazel b/go/pkg/daemon/internal/servers/BUILD.bazel index 526e5edc21..3cc8968374 100644 --- a/go/pkg/daemon/internal/servers/BUILD.bazel +++ b/go/pkg/daemon/internal/servers/BUILD.bazel @@ -13,8 +13,6 @@ go_library( "//go/lib/common:go_default_library", "//go/lib/ctrl/drkey:go_default_library", "//go/lib/ctrl/path_mgmt:go_default_library", - "//go/lib/drkey:go_default_library", - "//go/lib/drkeystorage:go_default_library", "//go/lib/log:go_default_library", "//go/lib/metrics:go_default_library", "//go/lib/prom:go_default_library", @@ -25,8 +23,10 @@ go_library( "//go/lib/topology:go_default_library", "//go/lib/util:go_default_library", "//go/pkg/daemon/colibri:go_default_library", + "//go/pkg/daemon/drkey:go_default_library", "//go/pkg/daemon/fetcher:go_default_library", "//go/pkg/proto/daemon:go_default_library", + "//go/pkg/proto/drkey:go_default_library", "//go/pkg/trust:go_default_library", "//go/proto:go_default_library", "@com_github_opentracing_opentracing_go//:go_default_library", diff --git a/go/pkg/daemon/internal/servers/grpc.go b/go/pkg/daemon/internal/servers/grpc.go index 38848db953..d3268c8801 100644 --- a/go/pkg/daemon/internal/servers/grpc.go +++ b/go/pkg/daemon/internal/servers/grpc.go @@ -30,8 +30,6 @@ import ( "github.com/scionproto/scion/go/lib/common" ctrl_drkey "github.com/scionproto/scion/go/lib/ctrl/drkey" "github.com/scionproto/scion/go/lib/ctrl/path_mgmt" - "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkeystorage" "github.com/scionproto/scion/go/lib/log" "github.com/scionproto/scion/go/lib/prom" "github.com/scionproto/scion/go/lib/revcache" @@ -41,8 +39,10 @@ import ( "github.com/scionproto/scion/go/lib/topology" "github.com/scionproto/scion/go/lib/util" "github.com/scionproto/scion/go/pkg/daemon/colibri" + daemon_drkey "github.com/scionproto/scion/go/pkg/daemon/drkey" "github.com/scionproto/scion/go/pkg/daemon/fetcher" sdpb "github.com/scionproto/scion/go/pkg/proto/daemon" + dkpb "github.com/scionproto/scion/go/pkg/proto/drkey" "github.com/scionproto/scion/go/pkg/trust" "github.com/scionproto/scion/go/proto" ) @@ -61,7 +61,7 @@ type DaemonServer struct { Fetcher fetcher.Fetcher RevCache revcache.RevCache ASInspector trust.Inspector - DRKeyStore drkeystorage.ClientStore + DRKeyClient daemon_drkey.ClientEngine ColFetcher colibri.Fetcher ColClient *colibri.DaemonClient @@ -348,45 +348,64 @@ func (s *DaemonServer) notifyInterfaceDown(ctx context.Context, return &sdpb.NotifyInterfaceDownResponse{}, nil } -// DRKeyLvl2 serves a Lvl2Key request -func (s *DaemonServer) DRKeyLvl2(ctx context.Context, - req *sdpb.DRKeyLvl2Request) (*sdpb.DRKeyLvl2Response, error) { +func (s *DaemonServer) ASHost(ctx context.Context, + req *dkpb.ASHostRequest) (*dkpb.ASHostResponse, error) { - logger := log.FromCtx(ctx) - - parsedReq, err := requestToLvl2Req(req) + meta, err := ctrl_drkey.RequestToASHostMeta(req) if err != nil { - logger.Error("[DRKey DeamonService] Invalid DRKey Lvl2 request", "err", err) - return nil, serrors.WrapStr("parsing protobuf Lvl2Req", err) + return nil, serrors.WrapStr("parsing protobuf ASHostReq", err) } - lvl2Key, err := s.DRKeyStore.GetLvl2Key(ctx, parsedReq.ToMeta(), parsedReq.ValTime) + lvl2Key, err := s.DRKeyClient.GetASHostKey(ctx, meta) if err != nil { - logger.Error("[DRKey DeamonService] Error getting Lvl2Key", "err", err) - return nil, serrors.WrapStr("getting Lvl2Key from client store", err) + return nil, serrors.WrapStr("getting AS-Host from client store", err) } - resp, err := keyToLvl2Resp(lvl2Key) + resp, err := ctrl_drkey.KeyToASHostResp(lvl2Key) if err != nil { - logger.Debug("[DRKey DeamonService] Error parsing DRKey Lvl2 to protobuf resp", - "err", err) - return nil, serrors.WrapStr("parsing to protobuf Lvl2Rep", err) + return nil, serrors.WrapStr("parsing to protobuf AS-Host", err) } return resp, nil } -func requestToLvl2Req(req *sdpb.DRKeyLvl2Request) (ctrl_drkey.Lvl2Req, error) { - return ctrl_drkey.RequestToLvl2Req(req.BaseReq) +func (s *DaemonServer) HostAS(ctx context.Context, + req *dkpb.HostASRequest) (*dkpb.HostASResponse, error) { + + meta, err := ctrl_drkey.RequestToHostASMeta(req) + if err != nil { + return nil, serrors.WrapStr("parsing protobuf HostASReq", err) + } + + lvl2Key, err := s.DRKeyClient.GetHostASKey(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("getting Host-AS from client store", err) + } + + resp, err := ctrl_drkey.KeyToHostASResp(lvl2Key) + if err != nil { + return nil, serrors.WrapStr("parsing to protobuf Host-AS", err) + } + return resp, nil } -func keyToLvl2Resp(drkey drkey.Lvl2Key) (*sdpb.DRKeyLvl2Response, error) { - baseRep, err := ctrl_drkey.KeyToLvl2Resp(drkey) +func (s *DaemonServer) HostHost(ctx context.Context, + req *dkpb.HostHostRequest) (*dkpb.HostHostResponse, error) { + + meta, err := ctrl_drkey.RequestToHostHostMeta(req) if err != nil { - return nil, err + return nil, serrors.WrapStr("parsing protobuf HostHostReq", err) + } + + lvl2Key, err := s.DRKeyClient.GetHostHostKey(ctx, meta) + if err != nil { + return nil, serrors.WrapStr("getting Host-AS from client store", err) } - return &sdpb.DRKeyLvl2Response{ - BaseRep: baseRep, - }, nil + + resp, err := ctrl_drkey.KeyToHostHostResp(lvl2Key) + if err != nil { + return nil, serrors.WrapStr("parsing to protobuf Host-Host", err) + } + return resp, nil } func (s *DaemonServer) ColibriListRsvs(ctx context.Context, req *sdpb.ColibriListRsvsRequest) ( diff --git a/go/pkg/proto/control_plane/drkey.pb.go b/go/pkg/proto/control_plane/drkey.pb.go index c1e5d03e7a..de861ced3d 100644 --- a/go/pkg/proto/control_plane/drkey.pb.go +++ b/go/pkg/proto/control_plane/drkey.pb.go @@ -15,7 +15,6 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" - sync "sync" ) const ( @@ -25,100 +24,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type DRKeyLvl2Request struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BaseReq *drkey.DRKeyLvl2Request `protobuf:"bytes,1,opt,name=base_req,json=baseReq,proto3" json:"base_req,omitempty"` -} - -func (x *DRKeyLvl2Request) Reset() { - *x = DRKeyLvl2Request{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_control_plane_v1_drkey_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DRKeyLvl2Request) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DRKeyLvl2Request) ProtoMessage() {} - -func (x *DRKeyLvl2Request) ProtoReflect() protoreflect.Message { - mi := &file_proto_control_plane_v1_drkey_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DRKeyLvl2Request.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Request) Descriptor() ([]byte, []int) { - return file_proto_control_plane_v1_drkey_proto_rawDescGZIP(), []int{0} -} - -func (x *DRKeyLvl2Request) GetBaseReq() *drkey.DRKeyLvl2Request { - if x != nil { - return x.BaseReq - } - return nil -} - -type DRKeyLvl2Response struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BaseRep *drkey.DRKeyLvl2Response `protobuf:"bytes,1,opt,name=base_rep,json=baseRep,proto3" json:"base_rep,omitempty"` -} - -func (x *DRKeyLvl2Response) Reset() { - *x = DRKeyLvl2Response{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_control_plane_v1_drkey_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DRKeyLvl2Response) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DRKeyLvl2Response) ProtoMessage() {} - -func (x *DRKeyLvl2Response) ProtoReflect() protoreflect.Message { - mi := &file_proto_control_plane_v1_drkey_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DRKeyLvl2Response.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Response) Descriptor() ([]byte, []int) { - return file_proto_control_plane_v1_drkey_proto_rawDescGZIP(), []int{1} -} - -func (x *DRKeyLvl2Response) GetBaseRep() *drkey.DRKeyLvl2Response { - if x != nil { - return x.BaseRep - } - return nil -} - var File_proto_control_plane_v1_drkey_proto protoreflect.FileDescriptor var file_proto_control_plane_v1_drkey_proto_rawDesc = []byte{ @@ -127,72 +32,80 @@ var file_proto_control_plane_v1_drkey_proto_rawDesc = []byte{ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x1a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x76, - 0x31, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x54, 0x0a, 0x10, - 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, - 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, - 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x52, - 0x65, 0x71, 0x22, 0x56, 0x0a, 0x11, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, - 0x72, 0x65, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x31, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x62, 0x0a, 0x11, + 0x44, 0x52, 0x4b, 0x65, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x4c, 0x76, 0x6c, 0x31, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x70, 0x32, 0x70, 0x0a, 0x10, 0x44, 0x52, - 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x31, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5c, - 0x0a, 0x09, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x31, 0x12, 0x25, 0x2e, 0x70, 0x72, + 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, - 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, - 0x6c, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0x76, 0x0a, 0x10, - 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x62, 0x0a, 0x09, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x12, 0x28, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, - 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_control_plane_v1_drkey_proto_rawDescOnce sync.Once - file_proto_control_plane_v1_drkey_proto_rawDescData = file_proto_control_plane_v1_drkey_proto_rawDesc -) - -func file_proto_control_plane_v1_drkey_proto_rawDescGZIP() []byte { - file_proto_control_plane_v1_drkey_proto_rawDescOnce.Do(func() { - file_proto_control_plane_v1_drkey_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_control_plane_v1_drkey_proto_rawDescData) - }) - return file_proto_control_plane_v1_drkey_proto_rawDescData + 0x31, 0x2e, 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x32, 0xbf, 0x03, 0x0a, 0x11, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5c, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x4c, + 0x76, 0x6c, 0x31, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, + 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x4c, + 0x76, 0x6c, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x06, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x22, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x06, 0x48, 0x6f, 0x73, + 0x74, 0x41, 0x53, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, + 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, + 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x59, + 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x02, 0x53, 0x56, 0x12, + 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x56, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, + 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } -var file_proto_control_plane_v1_drkey_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_proto_control_plane_v1_drkey_proto_goTypes = []interface{}{ - (*DRKeyLvl2Request)(nil), // 0: proto.control_plane.v1.DRKeyLvl2Request - (*DRKeyLvl2Response)(nil), // 1: proto.control_plane.v1.DRKeyLvl2Response - (*drkey.DRKeyLvl2Request)(nil), // 2: proto.drkey.mgmt.v1.DRKeyLvl2Request - (*drkey.DRKeyLvl2Response)(nil), // 3: proto.drkey.mgmt.v1.DRKeyLvl2Response - (*drkey.DRKeyLvl1Request)(nil), // 4: proto.drkey.mgmt.v1.DRKeyLvl1Request - (*drkey.DRKeyLvl1Response)(nil), // 5: proto.drkey.mgmt.v1.DRKeyLvl1Response + (*drkey.Lvl1Request)(nil), // 0: proto.drkey.mgmt.v1.Lvl1Request + (*drkey.IntraLvl1Request)(nil), // 1: proto.drkey.mgmt.v1.IntraLvl1Request + (*drkey.ASHostRequest)(nil), // 2: proto.drkey.mgmt.v1.ASHostRequest + (*drkey.HostASRequest)(nil), // 3: proto.drkey.mgmt.v1.HostASRequest + (*drkey.HostHostRequest)(nil), // 4: proto.drkey.mgmt.v1.HostHostRequest + (*drkey.SVRequest)(nil), // 5: proto.drkey.mgmt.v1.SVRequest + (*drkey.Lvl1Response)(nil), // 6: proto.drkey.mgmt.v1.Lvl1Response + (*drkey.IntraLvl1Response)(nil), // 7: proto.drkey.mgmt.v1.IntraLvl1Response + (*drkey.ASHostResponse)(nil), // 8: proto.drkey.mgmt.v1.ASHostResponse + (*drkey.HostASResponse)(nil), // 9: proto.drkey.mgmt.v1.HostASResponse + (*drkey.HostHostResponse)(nil), // 10: proto.drkey.mgmt.v1.HostHostResponse + (*drkey.SVResponse)(nil), // 11: proto.drkey.mgmt.v1.SVResponse } var file_proto_control_plane_v1_drkey_proto_depIdxs = []int32{ - 2, // 0: proto.control_plane.v1.DRKeyLvl2Request.base_req:type_name -> proto.drkey.mgmt.v1.DRKeyLvl2Request - 3, // 1: proto.control_plane.v1.DRKeyLvl2Response.base_rep:type_name -> proto.drkey.mgmt.v1.DRKeyLvl2Response - 4, // 2: proto.control_plane.v1.DRKeyLvl1Service.DRKeyLvl1:input_type -> proto.drkey.mgmt.v1.DRKeyLvl1Request - 0, // 3: proto.control_plane.v1.DRKeyLvl2Service.DRKeyLvl2:input_type -> proto.control_plane.v1.DRKeyLvl2Request - 5, // 4: proto.control_plane.v1.DRKeyLvl1Service.DRKeyLvl1:output_type -> proto.drkey.mgmt.v1.DRKeyLvl1Response - 1, // 5: proto.control_plane.v1.DRKeyLvl2Service.DRKeyLvl2:output_type -> proto.control_plane.v1.DRKeyLvl2Response - 4, // [4:6] is the sub-list for method output_type - 2, // [2:4] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 0, // 0: proto.control_plane.v1.DRKeyInterService.Lvl1:input_type -> proto.drkey.mgmt.v1.Lvl1Request + 1, // 1: proto.control_plane.v1.DRKeyIntraService.IntraLvl1:input_type -> proto.drkey.mgmt.v1.IntraLvl1Request + 2, // 2: proto.control_plane.v1.DRKeyIntraService.ASHost:input_type -> proto.drkey.mgmt.v1.ASHostRequest + 3, // 3: proto.control_plane.v1.DRKeyIntraService.HostAS:input_type -> proto.drkey.mgmt.v1.HostASRequest + 4, // 4: proto.control_plane.v1.DRKeyIntraService.HostHost:input_type -> proto.drkey.mgmt.v1.HostHostRequest + 5, // 5: proto.control_plane.v1.DRKeyIntraService.SV:input_type -> proto.drkey.mgmt.v1.SVRequest + 6, // 6: proto.control_plane.v1.DRKeyInterService.Lvl1:output_type -> proto.drkey.mgmt.v1.Lvl1Response + 7, // 7: proto.control_plane.v1.DRKeyIntraService.IntraLvl1:output_type -> proto.drkey.mgmt.v1.IntraLvl1Response + 8, // 8: proto.control_plane.v1.DRKeyIntraService.ASHost:output_type -> proto.drkey.mgmt.v1.ASHostResponse + 9, // 9: proto.control_plane.v1.DRKeyIntraService.HostAS:output_type -> proto.drkey.mgmt.v1.HostASResponse + 10, // 10: proto.control_plane.v1.DRKeyIntraService.HostHost:output_type -> proto.drkey.mgmt.v1.HostHostResponse + 11, // 11: proto.control_plane.v1.DRKeyIntraService.SV:output_type -> proto.drkey.mgmt.v1.SVResponse + 6, // [6:12] is the sub-list for method output_type + 0, // [0:6] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } func init() { file_proto_control_plane_v1_drkey_proto_init() } @@ -200,45 +113,18 @@ func file_proto_control_plane_v1_drkey_proto_init() { if File_proto_control_plane_v1_drkey_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_proto_control_plane_v1_drkey_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Request); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_control_plane_v1_drkey_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Response); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_control_plane_v1_drkey_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 0, NumExtensions: 0, NumServices: 2, }, GoTypes: file_proto_control_plane_v1_drkey_proto_goTypes, DependencyIndexes: file_proto_control_plane_v1_drkey_proto_depIdxs, - MessageInfos: file_proto_control_plane_v1_drkey_proto_msgTypes, }.Build() File_proto_control_plane_v1_drkey_proto = out.File file_proto_control_plane_v1_drkey_proto_rawDesc = nil @@ -254,144 +140,288 @@ var _ grpc.ClientConnInterface // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion6 -// DRKeyLvl1ServiceClient is the client API for DRKeyLvl1Service service. +// DRKeyInterServiceClient is the client API for DRKeyInterService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type DRKeyLvl1ServiceClient interface { - DRKeyLvl1(ctx context.Context, in *drkey.DRKeyLvl1Request, opts ...grpc.CallOption) (*drkey.DRKeyLvl1Response, error) +type DRKeyInterServiceClient interface { + Lvl1(ctx context.Context, in *drkey.Lvl1Request, opts ...grpc.CallOption) (*drkey.Lvl1Response, error) } -type dRKeyLvl1ServiceClient struct { +type dRKeyInterServiceClient struct { cc grpc.ClientConnInterface } -func NewDRKeyLvl1ServiceClient(cc grpc.ClientConnInterface) DRKeyLvl1ServiceClient { - return &dRKeyLvl1ServiceClient{cc} +func NewDRKeyInterServiceClient(cc grpc.ClientConnInterface) DRKeyInterServiceClient { + return &dRKeyInterServiceClient{cc} } -func (c *dRKeyLvl1ServiceClient) DRKeyLvl1(ctx context.Context, in *drkey.DRKeyLvl1Request, opts ...grpc.CallOption) (*drkey.DRKeyLvl1Response, error) { - out := new(drkey.DRKeyLvl1Response) - err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyLvl1Service/DRKeyLvl1", in, out, opts...) +func (c *dRKeyInterServiceClient) Lvl1(ctx context.Context, in *drkey.Lvl1Request, opts ...grpc.CallOption) (*drkey.Lvl1Response, error) { + out := new(drkey.Lvl1Response) + err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyInterService/Lvl1", in, out, opts...) if err != nil { return nil, err } return out, nil } -// DRKeyLvl1ServiceServer is the server API for DRKeyLvl1Service service. -type DRKeyLvl1ServiceServer interface { - DRKeyLvl1(context.Context, *drkey.DRKeyLvl1Request) (*drkey.DRKeyLvl1Response, error) +// DRKeyInterServiceServer is the server API for DRKeyInterService service. +type DRKeyInterServiceServer interface { + Lvl1(context.Context, *drkey.Lvl1Request) (*drkey.Lvl1Response, error) } -// UnimplementedDRKeyLvl1ServiceServer can be embedded to have forward compatible implementations. -type UnimplementedDRKeyLvl1ServiceServer struct { +// UnimplementedDRKeyInterServiceServer can be embedded to have forward compatible implementations. +type UnimplementedDRKeyInterServiceServer struct { } -func (*UnimplementedDRKeyLvl1ServiceServer) DRKeyLvl1(context.Context, *drkey.DRKeyLvl1Request) (*drkey.DRKeyLvl1Response, error) { - return nil, status.Errorf(codes.Unimplemented, "method DRKeyLvl1 not implemented") +func (*UnimplementedDRKeyInterServiceServer) Lvl1(context.Context, *drkey.Lvl1Request) (*drkey.Lvl1Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method Lvl1 not implemented") } -func RegisterDRKeyLvl1ServiceServer(s *grpc.Server, srv DRKeyLvl1ServiceServer) { - s.RegisterService(&_DRKeyLvl1Service_serviceDesc, srv) +func RegisterDRKeyInterServiceServer(s *grpc.Server, srv DRKeyInterServiceServer) { + s.RegisterService(&_DRKeyInterService_serviceDesc, srv) } -func _DRKeyLvl1Service_DRKeyLvl1_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(drkey.DRKeyLvl1Request) +func _DRKeyInterService_Lvl1_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.Lvl1Request) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(DRKeyLvl1ServiceServer).DRKeyLvl1(ctx, in) + return srv.(DRKeyInterServiceServer).Lvl1(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/proto.control_plane.v1.DRKeyLvl1Service/DRKeyLvl1", + FullMethod: "/proto.control_plane.v1.DRKeyInterService/Lvl1", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DRKeyLvl1ServiceServer).DRKeyLvl1(ctx, req.(*drkey.DRKeyLvl1Request)) + return srv.(DRKeyInterServiceServer).Lvl1(ctx, req.(*drkey.Lvl1Request)) } return interceptor(ctx, in, info, handler) } -var _DRKeyLvl1Service_serviceDesc = grpc.ServiceDesc{ - ServiceName: "proto.control_plane.v1.DRKeyLvl1Service", - HandlerType: (*DRKeyLvl1ServiceServer)(nil), +var _DRKeyInterService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "proto.control_plane.v1.DRKeyInterService", + HandlerType: (*DRKeyInterServiceServer)(nil), Methods: []grpc.MethodDesc{ { - MethodName: "DRKeyLvl1", - Handler: _DRKeyLvl1Service_DRKeyLvl1_Handler, + MethodName: "Lvl1", + Handler: _DRKeyInterService_Lvl1_Handler, }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/control_plane/v1/drkey.proto", } -// DRKeyLvl2ServiceClient is the client API for DRKeyLvl2Service service. +// DRKeyIntraServiceClient is the client API for DRKeyIntraService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type DRKeyLvl2ServiceClient interface { - DRKeyLvl2(ctx context.Context, in *DRKeyLvl2Request, opts ...grpc.CallOption) (*DRKeyLvl2Response, error) +type DRKeyIntraServiceClient interface { + IntraLvl1(ctx context.Context, in *drkey.IntraLvl1Request, opts ...grpc.CallOption) (*drkey.IntraLvl1Response, error) + ASHost(ctx context.Context, in *drkey.ASHostRequest, opts ...grpc.CallOption) (*drkey.ASHostResponse, error) + HostAS(ctx context.Context, in *drkey.HostASRequest, opts ...grpc.CallOption) (*drkey.HostASResponse, error) + HostHost(ctx context.Context, in *drkey.HostHostRequest, opts ...grpc.CallOption) (*drkey.HostHostResponse, error) + SV(ctx context.Context, in *drkey.SVRequest, opts ...grpc.CallOption) (*drkey.SVResponse, error) } -type dRKeyLvl2ServiceClient struct { +type dRKeyIntraServiceClient struct { cc grpc.ClientConnInterface } -func NewDRKeyLvl2ServiceClient(cc grpc.ClientConnInterface) DRKeyLvl2ServiceClient { - return &dRKeyLvl2ServiceClient{cc} +func NewDRKeyIntraServiceClient(cc grpc.ClientConnInterface) DRKeyIntraServiceClient { + return &dRKeyIntraServiceClient{cc} } -func (c *dRKeyLvl2ServiceClient) DRKeyLvl2(ctx context.Context, in *DRKeyLvl2Request, opts ...grpc.CallOption) (*DRKeyLvl2Response, error) { - out := new(DRKeyLvl2Response) - err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyLvl2Service/DRKeyLvl2", in, out, opts...) +func (c *dRKeyIntraServiceClient) IntraLvl1(ctx context.Context, in *drkey.IntraLvl1Request, opts ...grpc.CallOption) (*drkey.IntraLvl1Response, error) { + out := new(drkey.IntraLvl1Response) + err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyIntraService/IntraLvl1", in, out, opts...) if err != nil { return nil, err } return out, nil } -// DRKeyLvl2ServiceServer is the server API for DRKeyLvl2Service service. -type DRKeyLvl2ServiceServer interface { - DRKeyLvl2(context.Context, *DRKeyLvl2Request) (*DRKeyLvl2Response, error) +func (c *dRKeyIntraServiceClient) ASHost(ctx context.Context, in *drkey.ASHostRequest, opts ...grpc.CallOption) (*drkey.ASHostResponse, error) { + out := new(drkey.ASHostResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyIntraService/ASHost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil } -// UnimplementedDRKeyLvl2ServiceServer can be embedded to have forward compatible implementations. -type UnimplementedDRKeyLvl2ServiceServer struct { +func (c *dRKeyIntraServiceClient) HostAS(ctx context.Context, in *drkey.HostASRequest, opts ...grpc.CallOption) (*drkey.HostASResponse, error) { + out := new(drkey.HostASResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyIntraService/HostAS", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil } -func (*UnimplementedDRKeyLvl2ServiceServer) DRKeyLvl2(context.Context, *DRKeyLvl2Request) (*DRKeyLvl2Response, error) { - return nil, status.Errorf(codes.Unimplemented, "method DRKeyLvl2 not implemented") +func (c *dRKeyIntraServiceClient) HostHost(ctx context.Context, in *drkey.HostHostRequest, opts ...grpc.CallOption) (*drkey.HostHostResponse, error) { + out := new(drkey.HostHostResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyIntraService/HostHost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dRKeyIntraServiceClient) SV(ctx context.Context, in *drkey.SVRequest, opts ...grpc.CallOption) (*drkey.SVResponse, error) { + out := new(drkey.SVResponse) + err := c.cc.Invoke(ctx, "/proto.control_plane.v1.DRKeyIntraService/SV", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil } -func RegisterDRKeyLvl2ServiceServer(s *grpc.Server, srv DRKeyLvl2ServiceServer) { - s.RegisterService(&_DRKeyLvl2Service_serviceDesc, srv) +// DRKeyIntraServiceServer is the server API for DRKeyIntraService service. +type DRKeyIntraServiceServer interface { + IntraLvl1(context.Context, *drkey.IntraLvl1Request) (*drkey.IntraLvl1Response, error) + ASHost(context.Context, *drkey.ASHostRequest) (*drkey.ASHostResponse, error) + HostAS(context.Context, *drkey.HostASRequest) (*drkey.HostASResponse, error) + HostHost(context.Context, *drkey.HostHostRequest) (*drkey.HostHostResponse, error) + SV(context.Context, *drkey.SVRequest) (*drkey.SVResponse, error) +} + +// UnimplementedDRKeyIntraServiceServer can be embedded to have forward compatible implementations. +type UnimplementedDRKeyIntraServiceServer struct { +} + +func (*UnimplementedDRKeyIntraServiceServer) IntraLvl1(context.Context, *drkey.IntraLvl1Request) (*drkey.IntraLvl1Response, error) { + return nil, status.Errorf(codes.Unimplemented, "method IntraLvl1 not implemented") +} +func (*UnimplementedDRKeyIntraServiceServer) ASHost(context.Context, *drkey.ASHostRequest) (*drkey.ASHostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ASHost not implemented") +} +func (*UnimplementedDRKeyIntraServiceServer) HostAS(context.Context, *drkey.HostASRequest) (*drkey.HostASResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HostAS not implemented") +} +func (*UnimplementedDRKeyIntraServiceServer) HostHost(context.Context, *drkey.HostHostRequest) (*drkey.HostHostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HostHost not implemented") +} +func (*UnimplementedDRKeyIntraServiceServer) SV(context.Context, *drkey.SVRequest) (*drkey.SVResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SV not implemented") } -func _DRKeyLvl2Service_DRKeyLvl2_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DRKeyLvl2Request) +func RegisterDRKeyIntraServiceServer(s *grpc.Server, srv DRKeyIntraServiceServer) { + s.RegisterService(&_DRKeyIntraService_serviceDesc, srv) +} + +func _DRKeyIntraService_IntraLvl1_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.IntraLvl1Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DRKeyIntraServiceServer).IntraLvl1(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.v1.DRKeyIntraService/IntraLvl1", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DRKeyIntraServiceServer).IntraLvl1(ctx, req.(*drkey.IntraLvl1Request)) + } + return interceptor(ctx, in, info, handler) +} + +func _DRKeyIntraService_ASHost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.ASHostRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DRKeyIntraServiceServer).ASHost(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.v1.DRKeyIntraService/ASHost", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DRKeyIntraServiceServer).ASHost(ctx, req.(*drkey.ASHostRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DRKeyIntraService_HostAS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.HostASRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DRKeyIntraServiceServer).HostAS(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.v1.DRKeyIntraService/HostAS", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DRKeyIntraServiceServer).HostAS(ctx, req.(*drkey.HostASRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DRKeyIntraService_HostHost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.HostHostRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(DRKeyLvl2ServiceServer).DRKeyLvl2(ctx, in) + return srv.(DRKeyIntraServiceServer).HostHost(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/proto.control_plane.v1.DRKeyLvl2Service/DRKeyLvl2", + FullMethod: "/proto.control_plane.v1.DRKeyIntraService/HostHost", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DRKeyLvl2ServiceServer).DRKeyLvl2(ctx, req.(*DRKeyLvl2Request)) + return srv.(DRKeyIntraServiceServer).HostHost(ctx, req.(*drkey.HostHostRequest)) } return interceptor(ctx, in, info, handler) } -var _DRKeyLvl2Service_serviceDesc = grpc.ServiceDesc{ - ServiceName: "proto.control_plane.v1.DRKeyLvl2Service", - HandlerType: (*DRKeyLvl2ServiceServer)(nil), +func _DRKeyIntraService_SV_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.SVRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DRKeyIntraServiceServer).SV(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.control_plane.v1.DRKeyIntraService/SV", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DRKeyIntraServiceServer).SV(ctx, req.(*drkey.SVRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _DRKeyIntraService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "proto.control_plane.v1.DRKeyIntraService", + HandlerType: (*DRKeyIntraServiceServer)(nil), Methods: []grpc.MethodDesc{ { - MethodName: "DRKeyLvl2", - Handler: _DRKeyLvl2Service_DRKeyLvl2_Handler, + MethodName: "IntraLvl1", + Handler: _DRKeyIntraService_IntraLvl1_Handler, + }, + { + MethodName: "ASHost", + Handler: _DRKeyIntraService_ASHost_Handler, + }, + { + MethodName: "HostAS", + Handler: _DRKeyIntraService_HostAS_Handler, + }, + { + MethodName: "HostHost", + Handler: _DRKeyIntraService_HostHost_Handler, + }, + { + MethodName: "SV", + Handler: _DRKeyIntraService_SV_Handler, }, }, Streams: []grpc.StreamDesc{}, diff --git a/go/pkg/proto/control_plane/mock_control_plane/BUILD.bazel b/go/pkg/proto/control_plane/mock_control_plane/BUILD.bazel index fd27e091b4..684d897ecd 100644 --- a/go/pkg/proto/control_plane/mock_control_plane/BUILD.bazel +++ b/go/pkg/proto/control_plane/mock_control_plane/BUILD.bazel @@ -7,8 +7,8 @@ gomock( interfaces = [ "ChainRenewalServiceServer", "TrustMaterialServiceServer", - "DRKeyLvl2ServiceServer", - "DRKeyLvl1ServiceServer", + "DRKeyIntraServiceServer", + "DRKeyInterServiceServer", ], library = "//go/pkg/proto/control_plane:go_default_library", package = "mock_control_plane", diff --git a/go/pkg/proto/control_plane/mock_control_plane/mock.go b/go/pkg/proto/control_plane/mock_control_plane/mock.go index aa4888da8e..90cff80d51 100644 --- a/go/pkg/proto/control_plane/mock_control_plane/mock.go +++ b/go/pkg/proto/control_plane/mock_control_plane/mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/scionproto/scion/go/pkg/proto/control_plane (interfaces: ChainRenewalServiceServer,TrustMaterialServiceServer,DRKeyLvl2ServiceServer,DRKeyLvl1ServiceServer) +// Source: github.com/scionproto/scion/go/pkg/proto/control_plane (interfaces: ChainRenewalServiceServer,TrustMaterialServiceServer,DRKeyIntraServiceServer,DRKeyInterServiceServer) // Package mock_control_plane is a generated GoMock package. package mock_control_plane @@ -104,78 +104,138 @@ func (mr *MockTrustMaterialServiceServerMockRecorder) TRC(arg0, arg1 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TRC", reflect.TypeOf((*MockTrustMaterialServiceServer)(nil).TRC), arg0, arg1) } -// MockDRKeyLvl2ServiceServer is a mock of DRKeyLvl2ServiceServer interface. -type MockDRKeyLvl2ServiceServer struct { +// MockDRKeyIntraServiceServer is a mock of DRKeyIntraServiceServer interface. +type MockDRKeyIntraServiceServer struct { ctrl *gomock.Controller - recorder *MockDRKeyLvl2ServiceServerMockRecorder + recorder *MockDRKeyIntraServiceServerMockRecorder } -// MockDRKeyLvl2ServiceServerMockRecorder is the mock recorder for MockDRKeyLvl2ServiceServer. -type MockDRKeyLvl2ServiceServerMockRecorder struct { - mock *MockDRKeyLvl2ServiceServer +// MockDRKeyIntraServiceServerMockRecorder is the mock recorder for MockDRKeyIntraServiceServer. +type MockDRKeyIntraServiceServerMockRecorder struct { + mock *MockDRKeyIntraServiceServer } -// NewMockDRKeyLvl2ServiceServer creates a new mock instance. -func NewMockDRKeyLvl2ServiceServer(ctrl *gomock.Controller) *MockDRKeyLvl2ServiceServer { - mock := &MockDRKeyLvl2ServiceServer{ctrl: ctrl} - mock.recorder = &MockDRKeyLvl2ServiceServerMockRecorder{mock} +// NewMockDRKeyIntraServiceServer creates a new mock instance. +func NewMockDRKeyIntraServiceServer(ctrl *gomock.Controller) *MockDRKeyIntraServiceServer { + mock := &MockDRKeyIntraServiceServer{ctrl: ctrl} + mock.recorder = &MockDRKeyIntraServiceServerMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockDRKeyLvl2ServiceServer) EXPECT() *MockDRKeyLvl2ServiceServerMockRecorder { +func (m *MockDRKeyIntraServiceServer) EXPECT() *MockDRKeyIntraServiceServerMockRecorder { return m.recorder } -// DRKeyLvl2 mocks base method. -func (m *MockDRKeyLvl2ServiceServer) DRKeyLvl2(arg0 context.Context, arg1 *control_plane.DRKeyLvl2Request) (*control_plane.DRKeyLvl2Response, error) { +// ASHost mocks base method. +func (m *MockDRKeyIntraServiceServer) ASHost(arg0 context.Context, arg1 *drkey.ASHostRequest) (*drkey.ASHostResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DRKeyLvl2", arg0, arg1) - ret0, _ := ret[0].(*control_plane.DRKeyLvl2Response) + ret := m.ctrl.Call(m, "ASHost", arg0, arg1) + ret0, _ := ret[0].(*drkey.ASHostResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// DRKeyLvl2 indicates an expected call of DRKeyLvl2. -func (mr *MockDRKeyLvl2ServiceServerMockRecorder) DRKeyLvl2(arg0, arg1 interface{}) *gomock.Call { +// ASHost indicates an expected call of ASHost. +func (mr *MockDRKeyIntraServiceServerMockRecorder) ASHost(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyLvl2", reflect.TypeOf((*MockDRKeyLvl2ServiceServer)(nil).DRKeyLvl2), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ASHost", reflect.TypeOf((*MockDRKeyIntraServiceServer)(nil).ASHost), arg0, arg1) } -// MockDRKeyLvl1ServiceServer is a mock of DRKeyLvl1ServiceServer interface. -type MockDRKeyLvl1ServiceServer struct { +// HostAS mocks base method. +func (m *MockDRKeyIntraServiceServer) HostAS(arg0 context.Context, arg1 *drkey.HostASRequest) (*drkey.HostASResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HostAS", arg0, arg1) + ret0, _ := ret[0].(*drkey.HostASResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HostAS indicates an expected call of HostAS. +func (mr *MockDRKeyIntraServiceServerMockRecorder) HostAS(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HostAS", reflect.TypeOf((*MockDRKeyIntraServiceServer)(nil).HostAS), arg0, arg1) +} + +// HostHost mocks base method. +func (m *MockDRKeyIntraServiceServer) HostHost(arg0 context.Context, arg1 *drkey.HostHostRequest) (*drkey.HostHostResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HostHost", arg0, arg1) + ret0, _ := ret[0].(*drkey.HostHostResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HostHost indicates an expected call of HostHost. +func (mr *MockDRKeyIntraServiceServerMockRecorder) HostHost(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HostHost", reflect.TypeOf((*MockDRKeyIntraServiceServer)(nil).HostHost), arg0, arg1) +} + +// IntraLvl1 mocks base method. +func (m *MockDRKeyIntraServiceServer) IntraLvl1(arg0 context.Context, arg1 *drkey.IntraLvl1Request) (*drkey.IntraLvl1Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IntraLvl1", arg0, arg1) + ret0, _ := ret[0].(*drkey.IntraLvl1Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IntraLvl1 indicates an expected call of IntraLvl1. +func (mr *MockDRKeyIntraServiceServerMockRecorder) IntraLvl1(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IntraLvl1", reflect.TypeOf((*MockDRKeyIntraServiceServer)(nil).IntraLvl1), arg0, arg1) +} + +// SV mocks base method. +func (m *MockDRKeyIntraServiceServer) SV(arg0 context.Context, arg1 *drkey.SVRequest) (*drkey.SVResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SV", arg0, arg1) + ret0, _ := ret[0].(*drkey.SVResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SV indicates an expected call of SV. +func (mr *MockDRKeyIntraServiceServerMockRecorder) SV(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SV", reflect.TypeOf((*MockDRKeyIntraServiceServer)(nil).SV), arg0, arg1) +} + +// MockDRKeyInterServiceServer is a mock of DRKeyInterServiceServer interface. +type MockDRKeyInterServiceServer struct { ctrl *gomock.Controller - recorder *MockDRKeyLvl1ServiceServerMockRecorder + recorder *MockDRKeyInterServiceServerMockRecorder } -// MockDRKeyLvl1ServiceServerMockRecorder is the mock recorder for MockDRKeyLvl1ServiceServer. -type MockDRKeyLvl1ServiceServerMockRecorder struct { - mock *MockDRKeyLvl1ServiceServer +// MockDRKeyInterServiceServerMockRecorder is the mock recorder for MockDRKeyInterServiceServer. +type MockDRKeyInterServiceServerMockRecorder struct { + mock *MockDRKeyInterServiceServer } -// NewMockDRKeyLvl1ServiceServer creates a new mock instance. -func NewMockDRKeyLvl1ServiceServer(ctrl *gomock.Controller) *MockDRKeyLvl1ServiceServer { - mock := &MockDRKeyLvl1ServiceServer{ctrl: ctrl} - mock.recorder = &MockDRKeyLvl1ServiceServerMockRecorder{mock} +// NewMockDRKeyInterServiceServer creates a new mock instance. +func NewMockDRKeyInterServiceServer(ctrl *gomock.Controller) *MockDRKeyInterServiceServer { + mock := &MockDRKeyInterServiceServer{ctrl: ctrl} + mock.recorder = &MockDRKeyInterServiceServerMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockDRKeyLvl1ServiceServer) EXPECT() *MockDRKeyLvl1ServiceServerMockRecorder { +func (m *MockDRKeyInterServiceServer) EXPECT() *MockDRKeyInterServiceServerMockRecorder { return m.recorder } -// DRKeyLvl1 mocks base method. -func (m *MockDRKeyLvl1ServiceServer) DRKeyLvl1(arg0 context.Context, arg1 *drkey.DRKeyLvl1Request) (*drkey.DRKeyLvl1Response, error) { +// Lvl1 mocks base method. +func (m *MockDRKeyInterServiceServer) Lvl1(arg0 context.Context, arg1 *drkey.Lvl1Request) (*drkey.Lvl1Response, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DRKeyLvl1", arg0, arg1) - ret0, _ := ret[0].(*drkey.DRKeyLvl1Response) + ret := m.ctrl.Call(m, "Lvl1", arg0, arg1) + ret0, _ := ret[0].(*drkey.Lvl1Response) ret1, _ := ret[1].(error) return ret0, ret1 } -// DRKeyLvl1 indicates an expected call of DRKeyLvl1. -func (mr *MockDRKeyLvl1ServiceServerMockRecorder) DRKeyLvl1(arg0, arg1 interface{}) *gomock.Call { +// Lvl1 indicates an expected call of Lvl1. +func (mr *MockDRKeyInterServiceServerMockRecorder) Lvl1(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyLvl1", reflect.TypeOf((*MockDRKeyLvl1ServiceServer)(nil).DRKeyLvl1), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lvl1", reflect.TypeOf((*MockDRKeyInterServiceServer)(nil).Lvl1), arg0, arg1) } diff --git a/go/pkg/proto/daemon/daemon.pb.go b/go/pkg/proto/daemon/daemon.pb.go index cdf4a0f545..cd79e798e9 100644 --- a/go/pkg/proto/daemon/daemon.pb.go +++ b/go/pkg/proto/daemon/daemon.pb.go @@ -1004,16 +1004,16 @@ func (*NotifyInterfaceDownResponse) Descriptor() ([]byte, []int) { return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} } -type DRKeyLvl2Request struct { +type SVRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - BaseReq *drkey.DRKeyLvl2Request `protobuf:"bytes,1,opt,name=base_req,json=baseReq,proto3" json:"base_req,omitempty"` + BaseReq *drkey.SVRequest `protobuf:"bytes,1,opt,name=base_req,json=baseReq,proto3" json:"base_req,omitempty"` } -func (x *DRKeyLvl2Request) Reset() { - *x = DRKeyLvl2Request{} +func (x *SVRequest) Reset() { + *x = SVRequest{} if protoimpl.UnsafeEnabled { mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1021,13 +1021,13 @@ func (x *DRKeyLvl2Request) Reset() { } } -func (x *DRKeyLvl2Request) String() string { +func (x *SVRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl2Request) ProtoMessage() {} +func (*SVRequest) ProtoMessage() {} -func (x *DRKeyLvl2Request) ProtoReflect() protoreflect.Message { +func (x *SVRequest) ProtoReflect() protoreflect.Message { mi := &file_proto_daemon_v1_daemon_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1039,28 +1039,28 @@ func (x *DRKeyLvl2Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl2Request.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Request) Descriptor() ([]byte, []int) { +// Deprecated: Use SVRequest.ProtoReflect.Descriptor instead. +func (*SVRequest) Descriptor() ([]byte, []int) { return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} } -func (x *DRKeyLvl2Request) GetBaseReq() *drkey.DRKeyLvl2Request { +func (x *SVRequest) GetBaseReq() *drkey.SVRequest { if x != nil { return x.BaseReq } return nil } -type DRKeyLvl2Response struct { +type SVResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - BaseRep *drkey.DRKeyLvl2Response `protobuf:"bytes,1,opt,name=base_rep,json=baseRep,proto3" json:"base_rep,omitempty"` + BaseRep *drkey.SVResponse `protobuf:"bytes,1,opt,name=base_rep,json=baseRep,proto3" json:"base_rep,omitempty"` } -func (x *DRKeyLvl2Response) Reset() { - *x = DRKeyLvl2Response{} +func (x *SVResponse) Reset() { + *x = SVResponse{} if protoimpl.UnsafeEnabled { mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1068,13 +1068,13 @@ func (x *DRKeyLvl2Response) Reset() { } } -func (x *DRKeyLvl2Response) String() string { +func (x *SVResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl2Response) ProtoMessage() {} +func (*SVResponse) ProtoMessage() {} -func (x *DRKeyLvl2Response) ProtoReflect() protoreflect.Message { +func (x *SVResponse) ProtoReflect() protoreflect.Message { mi := &file_proto_daemon_v1_daemon_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1086,12 +1086,12 @@ func (x *DRKeyLvl2Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl2Response.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Response) Descriptor() ([]byte, []int) { +// Deprecated: Use SVResponse.ProtoReflect.Descriptor instead. +func (*SVResponse) Descriptor() ([]byte, []int) { return file_proto_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} } -func (x *DRKeyLvl2Response) GetBaseRep() *drkey.DRKeyLvl2Response { +func (x *SVResponse) GetBaseRep() *drkey.SVResponse { if x != nil { return x.BaseRep } @@ -1593,136 +1593,145 @@ var file_proto_daemon_v1_daemon_proto_rawDesc = []byte{ 0x52, 0x05, 0x69, 0x73, 0x64, 0x41, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x0a, 0x10, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, - 0x76, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, - 0x73, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x22, 0x56, 0x0a, 0x11, - 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, - 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, - 0x76, 0x6c, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x62, 0x61, 0x73, - 0x65, 0x52, 0x65, 0x70, 0x22, 0x56, 0x0a, 0x16, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x73, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, - 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x09, 0x53, 0x56, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, + 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x56, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x71, 0x22, 0x48, + 0x0a, 0x0a, 0x53, 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x08, + 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, + 0x07, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x70, 0x22, 0x56, 0x0a, 0x16, 0x43, 0x6f, 0x6c, 0x69, + 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x69, 0x74, 0x63, 0x68, 0x61, 0x62, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, + 0x22, 0x58, 0x0a, 0x17, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x73, 0x76, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x74, 0x69, 0x74, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x57, 0x0a, 0x16, 0x43, 0x6f, + 0x6c, 0x69, 0x62, 0x72, 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, + 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x73, 0x65, 0x72, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, + 0x61, 0x73, 0x65, 0x22, 0x59, 0x0a, 0x17, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x53, 0x65, + 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, + 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x69, 0x74, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x58, 0x0a, 0x17, - 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, 0x76, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x69, - 0x74, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x57, 0x0a, 0x16, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, - 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, - 0x59, 0x0a, 0x17, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, - 0x73, 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x61, - 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x75, + 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x5b, + 0x0a, 0x18, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, + 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x61, + 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, + 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x5d, 0x0a, 0x19, 0x43, + 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x73, 0x76, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, + 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x5b, 0x0a, 0x18, 0x43, 0x6f, - 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, - 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, - 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x5d, 0x0a, 0x19, 0x43, 0x6f, 0x6c, 0x69, 0x62, - 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, - 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x73, - 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x61, 0x0a, 0x1f, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, - 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x61, 0x73, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x64, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x63, 0x0a, 0x20, 0x43, 0x6f, 0x6c, - 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, - 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, + 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x61, 0x0a, 0x1f, 0x43, 0x6f, + 0x6c, 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, + 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x2a, 0x6c, - 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x49, - 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, - 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x5f, 0x48, - 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, 0x32, 0xd2, 0x07, 0x0a, - 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, - 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x02, 0x41, 0x53, 0x12, 0x1a, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x22, 0x63, 0x0a, + 0x20, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x04, 0x62, 0x61, + 0x73, 0x65, 0x2a, 0x6c, 0x0a, 0x08, 0x4c, 0x69, 0x6e, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, + 0x0a, 0x15, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4c, 0x49, 0x4e, + 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, + 0x17, 0x0a, 0x13, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, + 0x54, 0x49, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x49, 0x4e, 0x4b, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x4e, 0x45, 0x54, 0x10, 0x03, + 0x32, 0x81, 0x09, 0x0a, 0x0d, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x1d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, + 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, + 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x02, + 0x41, 0x53, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0a, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, + 0x2e, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, + 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x20, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, - 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, - 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x09, 0x44, 0x52, 0x4b, - 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, - 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, - 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x66, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, - 0x76, 0x73, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x73, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, 0x76, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x69, 0x62, - 0x72, 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, - 0x69, 0x62, 0x72, 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x53, 0x65, 0x74, - 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x6c, 0x0a, 0x11, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, - 0x70, 0x52, 0x73, 0x76, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, - 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, - 0x52, 0x73, 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x81, 0x01, - 0x0a, 0x18, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x30, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x13, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, + 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, + 0x63, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x44, + 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, + 0x0f, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, 0x76, 0x73, + 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, + 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, + 0x62, 0x72, 0x69, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x73, 0x76, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, + 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, + 0x72, 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x53, 0x65, 0x74, 0x75, 0x70, + 0x52, 0x73, 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, + 0x11, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, + 0x73, 0x76, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, + 0x6e, 0x75, 0x70, 0x52, 0x73, 0x76, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x73, + 0x76, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x81, 0x01, 0x0a, 0x18, + 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, + 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6c, 0x69, 0x62, 0x72, 0x69, 0x41, 0x64, 0x64, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, - 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x61, - 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x53, 0x0a, 0x06, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x53, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x06, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x12, 0x22, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x59, 0x0a, 0x08, 0x48, 0x6f, 0x73, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, + 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, + 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, + 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1758,8 +1767,8 @@ var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ (*Underlay)(nil), // 15: proto.daemon.v1.Underlay (*NotifyInterfaceDownRequest)(nil), // 16: proto.daemon.v1.NotifyInterfaceDownRequest (*NotifyInterfaceDownResponse)(nil), // 17: proto.daemon.v1.NotifyInterfaceDownResponse - (*DRKeyLvl2Request)(nil), // 18: proto.daemon.v1.DRKeyLvl2Request - (*DRKeyLvl2Response)(nil), // 19: proto.daemon.v1.DRKeyLvl2Response + (*SVRequest)(nil), // 18: proto.daemon.v1.SVRequest + (*SVResponse)(nil), // 19: proto.daemon.v1.SVResponse (*ColibriListRsvsRequest)(nil), // 20: proto.daemon.v1.ColibriListRsvsRequest (*ColibriListRsvsResponse)(nil), // 21: proto.daemon.v1.ColibriListRsvsResponse (*ColibriSetupRsvRequest)(nil), // 22: proto.daemon.v1.ColibriSetupRsvRequest @@ -1772,8 +1781,8 @@ var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ nil, // 29: proto.daemon.v1.ServicesResponse.ServicesEntry (*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp (*durationpb.Duration)(nil), // 31: google.protobuf.Duration - (*drkey.DRKeyLvl2Request)(nil), // 32: proto.drkey.mgmt.v1.DRKeyLvl2Request - (*drkey.DRKeyLvl2Response)(nil), // 33: proto.drkey.mgmt.v1.DRKeyLvl2Response + (*drkey.SVRequest)(nil), // 32: proto.drkey.mgmt.v1.SVRequest + (*drkey.SVResponse)(nil), // 33: proto.drkey.mgmt.v1.SVResponse (*colibri.ListStitchablesRequest)(nil), // 34: proto.colibri.v1.ListStitchablesRequest (*colibri.ListStitchablesResponse)(nil), // 35: proto.colibri.v1.ListStitchablesResponse (*colibri.SetupReservationRequest)(nil), // 36: proto.colibri.v1.SetupReservationRequest @@ -1782,6 +1791,12 @@ var file_proto_daemon_v1_daemon_proto_goTypes = []interface{}{ (*colibri.CleanupReservationResponse)(nil), // 39: proto.colibri.v1.CleanupReservationResponse (*colibri.AddAdmissionEntryRequest)(nil), // 40: proto.colibri.v1.AddAdmissionEntryRequest (*colibri.AddAdmissionEntryResponse)(nil), // 41: proto.colibri.v1.AddAdmissionEntryResponse + (*drkey.ASHostRequest)(nil), // 42: proto.drkey.mgmt.v1.ASHostRequest + (*drkey.HostASRequest)(nil), // 43: proto.drkey.mgmt.v1.HostASRequest + (*drkey.HostHostRequest)(nil), // 44: proto.drkey.mgmt.v1.HostHostRequest + (*drkey.ASHostResponse)(nil), // 45: proto.drkey.mgmt.v1.ASHostResponse + (*drkey.HostASResponse)(nil), // 46: proto.drkey.mgmt.v1.HostASResponse + (*drkey.HostHostResponse)(nil), // 47: proto.drkey.mgmt.v1.HostHostResponse } var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 3, // 0: proto.daemon.v1.PathsResponse.paths:type_name -> proto.daemon.v1.Path @@ -1795,8 +1810,8 @@ var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 15, // 8: proto.daemon.v1.Interface.address:type_name -> proto.daemon.v1.Underlay 29, // 9: proto.daemon.v1.ServicesResponse.services:type_name -> proto.daemon.v1.ServicesResponse.ServicesEntry 14, // 10: proto.daemon.v1.ListService.services:type_name -> proto.daemon.v1.Service - 32, // 11: proto.daemon.v1.DRKeyLvl2Request.base_req:type_name -> proto.drkey.mgmt.v1.DRKeyLvl2Request - 33, // 12: proto.daemon.v1.DRKeyLvl2Response.base_rep:type_name -> proto.drkey.mgmt.v1.DRKeyLvl2Response + 32, // 11: proto.daemon.v1.SVRequest.base_req:type_name -> proto.drkey.mgmt.v1.SVRequest + 33, // 12: proto.daemon.v1.SVResponse.base_rep:type_name -> proto.drkey.mgmt.v1.SVResponse 34, // 13: proto.daemon.v1.ColibriListRsvsRequest.base:type_name -> proto.colibri.v1.ListStitchablesRequest 35, // 14: proto.daemon.v1.ColibriListRsvsResponse.base:type_name -> proto.colibri.v1.ListStitchablesResponse 36, // 15: proto.daemon.v1.ColibriSetupRsvRequest.base:type_name -> proto.colibri.v1.SetupReservationRequest @@ -1812,23 +1827,27 @@ var file_proto_daemon_v1_daemon_proto_depIdxs = []int32{ 8, // 25: proto.daemon.v1.DaemonService.Interfaces:input_type -> proto.daemon.v1.InterfacesRequest 11, // 26: proto.daemon.v1.DaemonService.Services:input_type -> proto.daemon.v1.ServicesRequest 16, // 27: proto.daemon.v1.DaemonService.NotifyInterfaceDown:input_type -> proto.daemon.v1.NotifyInterfaceDownRequest - 18, // 28: proto.daemon.v1.DaemonService.DRKeyLvl2:input_type -> proto.daemon.v1.DRKeyLvl2Request - 20, // 29: proto.daemon.v1.DaemonService.ColibriListRsvs:input_type -> proto.daemon.v1.ColibriListRsvsRequest - 22, // 30: proto.daemon.v1.DaemonService.ColibriSetupRsv:input_type -> proto.daemon.v1.ColibriSetupRsvRequest - 24, // 31: proto.daemon.v1.DaemonService.ColibriCleanupRsv:input_type -> proto.daemon.v1.ColibriCleanupRsvRequest - 26, // 32: proto.daemon.v1.DaemonService.ColibriAddAdmissionEntry:input_type -> proto.daemon.v1.ColibriAddAdmissionEntryRequest - 2, // 33: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse - 7, // 34: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse - 9, // 35: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse - 12, // 36: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse - 17, // 37: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse - 19, // 38: proto.daemon.v1.DaemonService.DRKeyLvl2:output_type -> proto.daemon.v1.DRKeyLvl2Response - 21, // 39: proto.daemon.v1.DaemonService.ColibriListRsvs:output_type -> proto.daemon.v1.ColibriListRsvsResponse - 23, // 40: proto.daemon.v1.DaemonService.ColibriSetupRsv:output_type -> proto.daemon.v1.ColibriSetupRsvResponse - 25, // 41: proto.daemon.v1.DaemonService.ColibriCleanupRsv:output_type -> proto.daemon.v1.ColibriCleanupRsvResponse - 27, // 42: proto.daemon.v1.DaemonService.ColibriAddAdmissionEntry:output_type -> proto.daemon.v1.ColibriAddAdmissionEntryResponse - 33, // [33:43] is the sub-list for method output_type - 23, // [23:33] is the sub-list for method input_type + 20, // 28: proto.daemon.v1.DaemonService.ColibriListRsvs:input_type -> proto.daemon.v1.ColibriListRsvsRequest + 22, // 29: proto.daemon.v1.DaemonService.ColibriSetupRsv:input_type -> proto.daemon.v1.ColibriSetupRsvRequest + 24, // 30: proto.daemon.v1.DaemonService.ColibriCleanupRsv:input_type -> proto.daemon.v1.ColibriCleanupRsvRequest + 26, // 31: proto.daemon.v1.DaemonService.ColibriAddAdmissionEntry:input_type -> proto.daemon.v1.ColibriAddAdmissionEntryRequest + 42, // 32: proto.daemon.v1.DaemonService.ASHost:input_type -> proto.drkey.mgmt.v1.ASHostRequest + 43, // 33: proto.daemon.v1.DaemonService.HostAS:input_type -> proto.drkey.mgmt.v1.HostASRequest + 44, // 34: proto.daemon.v1.DaemonService.HostHost:input_type -> proto.drkey.mgmt.v1.HostHostRequest + 2, // 35: proto.daemon.v1.DaemonService.Paths:output_type -> proto.daemon.v1.PathsResponse + 7, // 36: proto.daemon.v1.DaemonService.AS:output_type -> proto.daemon.v1.ASResponse + 9, // 37: proto.daemon.v1.DaemonService.Interfaces:output_type -> proto.daemon.v1.InterfacesResponse + 12, // 38: proto.daemon.v1.DaemonService.Services:output_type -> proto.daemon.v1.ServicesResponse + 17, // 39: proto.daemon.v1.DaemonService.NotifyInterfaceDown:output_type -> proto.daemon.v1.NotifyInterfaceDownResponse + 21, // 40: proto.daemon.v1.DaemonService.ColibriListRsvs:output_type -> proto.daemon.v1.ColibriListRsvsResponse + 23, // 41: proto.daemon.v1.DaemonService.ColibriSetupRsv:output_type -> proto.daemon.v1.ColibriSetupRsvResponse + 25, // 42: proto.daemon.v1.DaemonService.ColibriCleanupRsv:output_type -> proto.daemon.v1.ColibriCleanupRsvResponse + 27, // 43: proto.daemon.v1.DaemonService.ColibriAddAdmissionEntry:output_type -> proto.daemon.v1.ColibriAddAdmissionEntryResponse + 45, // 44: proto.daemon.v1.DaemonService.ASHost:output_type -> proto.drkey.mgmt.v1.ASHostResponse + 46, // 45: proto.daemon.v1.DaemonService.HostAS:output_type -> proto.drkey.mgmt.v1.HostASResponse + 47, // 46: proto.daemon.v1.DaemonService.HostHost:output_type -> proto.drkey.mgmt.v1.HostHostResponse + 35, // [35:47] is the sub-list for method output_type + 23, // [23:35] is the sub-list for method input_type 23, // [23:23] is the sub-list for extension type_name 23, // [23:23] is the sub-list for extension extendee 0, // [0:23] is the sub-list for field type_name @@ -2045,7 +2064,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Request); i { + switch v := v.(*SVRequest); i { case 0: return &v.state case 1: @@ -2057,7 +2076,7 @@ func file_proto_daemon_v1_daemon_proto_init() { } } file_proto_daemon_v1_daemon_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Response); i { + switch v := v.(*SVResponse); i { case 0: return &v.state case 1: @@ -2203,11 +2222,13 @@ type DaemonServiceClient interface { Interfaces(ctx context.Context, in *InterfacesRequest, opts ...grpc.CallOption) (*InterfacesResponse, error) Services(ctx context.Context, in *ServicesRequest, opts ...grpc.CallOption) (*ServicesResponse, error) NotifyInterfaceDown(ctx context.Context, in *NotifyInterfaceDownRequest, opts ...grpc.CallOption) (*NotifyInterfaceDownResponse, error) - DRKeyLvl2(ctx context.Context, in *DRKeyLvl2Request, opts ...grpc.CallOption) (*DRKeyLvl2Response, error) ColibriListRsvs(ctx context.Context, in *ColibriListRsvsRequest, opts ...grpc.CallOption) (*ColibriListRsvsResponse, error) ColibriSetupRsv(ctx context.Context, in *ColibriSetupRsvRequest, opts ...grpc.CallOption) (*ColibriSetupRsvResponse, error) ColibriCleanupRsv(ctx context.Context, in *ColibriCleanupRsvRequest, opts ...grpc.CallOption) (*ColibriCleanupRsvResponse, error) ColibriAddAdmissionEntry(ctx context.Context, in *ColibriAddAdmissionEntryRequest, opts ...grpc.CallOption) (*ColibriAddAdmissionEntryResponse, error) + ASHost(ctx context.Context, in *drkey.ASHostRequest, opts ...grpc.CallOption) (*drkey.ASHostResponse, error) + HostAS(ctx context.Context, in *drkey.HostASRequest, opts ...grpc.CallOption) (*drkey.HostASResponse, error) + HostHost(ctx context.Context, in *drkey.HostHostRequest, opts ...grpc.CallOption) (*drkey.HostHostResponse, error) } type daemonServiceClient struct { @@ -2263,15 +2284,6 @@ func (c *daemonServiceClient) NotifyInterfaceDown(ctx context.Context, in *Notif return out, nil } -func (c *daemonServiceClient) DRKeyLvl2(ctx context.Context, in *DRKeyLvl2Request, opts ...grpc.CallOption) (*DRKeyLvl2Response, error) { - out := new(DRKeyLvl2Response) - err := c.cc.Invoke(ctx, "/proto.daemon.v1.DaemonService/DRKeyLvl2", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *daemonServiceClient) ColibriListRsvs(ctx context.Context, in *ColibriListRsvsRequest, opts ...grpc.CallOption) (*ColibriListRsvsResponse, error) { out := new(ColibriListRsvsResponse) err := c.cc.Invoke(ctx, "/proto.daemon.v1.DaemonService/ColibriListRsvs", in, out, opts...) @@ -2308,6 +2320,33 @@ func (c *daemonServiceClient) ColibriAddAdmissionEntry(ctx context.Context, in * return out, nil } +func (c *daemonServiceClient) ASHost(ctx context.Context, in *drkey.ASHostRequest, opts ...grpc.CallOption) (*drkey.ASHostResponse, error) { + out := new(drkey.ASHostResponse) + err := c.cc.Invoke(ctx, "/proto.daemon.v1.DaemonService/ASHost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *daemonServiceClient) HostAS(ctx context.Context, in *drkey.HostASRequest, opts ...grpc.CallOption) (*drkey.HostASResponse, error) { + out := new(drkey.HostASResponse) + err := c.cc.Invoke(ctx, "/proto.daemon.v1.DaemonService/HostAS", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *daemonServiceClient) HostHost(ctx context.Context, in *drkey.HostHostRequest, opts ...grpc.CallOption) (*drkey.HostHostResponse, error) { + out := new(drkey.HostHostResponse) + err := c.cc.Invoke(ctx, "/proto.daemon.v1.DaemonService/HostHost", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // DaemonServiceServer is the server API for DaemonService service. type DaemonServiceServer interface { Paths(context.Context, *PathsRequest) (*PathsResponse, error) @@ -2315,11 +2354,13 @@ type DaemonServiceServer interface { Interfaces(context.Context, *InterfacesRequest) (*InterfacesResponse, error) Services(context.Context, *ServicesRequest) (*ServicesResponse, error) NotifyInterfaceDown(context.Context, *NotifyInterfaceDownRequest) (*NotifyInterfaceDownResponse, error) - DRKeyLvl2(context.Context, *DRKeyLvl2Request) (*DRKeyLvl2Response, error) ColibriListRsvs(context.Context, *ColibriListRsvsRequest) (*ColibriListRsvsResponse, error) ColibriSetupRsv(context.Context, *ColibriSetupRsvRequest) (*ColibriSetupRsvResponse, error) ColibriCleanupRsv(context.Context, *ColibriCleanupRsvRequest) (*ColibriCleanupRsvResponse, error) ColibriAddAdmissionEntry(context.Context, *ColibriAddAdmissionEntryRequest) (*ColibriAddAdmissionEntryResponse, error) + ASHost(context.Context, *drkey.ASHostRequest) (*drkey.ASHostResponse, error) + HostAS(context.Context, *drkey.HostASRequest) (*drkey.HostASResponse, error) + HostHost(context.Context, *drkey.HostHostRequest) (*drkey.HostHostResponse, error) } // UnimplementedDaemonServiceServer can be embedded to have forward compatible implementations. @@ -2341,9 +2382,6 @@ func (*UnimplementedDaemonServiceServer) Services(context.Context, *ServicesRequ func (*UnimplementedDaemonServiceServer) NotifyInterfaceDown(context.Context, *NotifyInterfaceDownRequest) (*NotifyInterfaceDownResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method NotifyInterfaceDown not implemented") } -func (*UnimplementedDaemonServiceServer) DRKeyLvl2(context.Context, *DRKeyLvl2Request) (*DRKeyLvl2Response, error) { - return nil, status.Errorf(codes.Unimplemented, "method DRKeyLvl2 not implemented") -} func (*UnimplementedDaemonServiceServer) ColibriListRsvs(context.Context, *ColibriListRsvsRequest) (*ColibriListRsvsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ColibriListRsvs not implemented") } @@ -2356,6 +2394,15 @@ func (*UnimplementedDaemonServiceServer) ColibriCleanupRsv(context.Context, *Col func (*UnimplementedDaemonServiceServer) ColibriAddAdmissionEntry(context.Context, *ColibriAddAdmissionEntryRequest) (*ColibriAddAdmissionEntryResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ColibriAddAdmissionEntry not implemented") } +func (*UnimplementedDaemonServiceServer) ASHost(context.Context, *drkey.ASHostRequest) (*drkey.ASHostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ASHost not implemented") +} +func (*UnimplementedDaemonServiceServer) HostAS(context.Context, *drkey.HostASRequest) (*drkey.HostASResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HostAS not implemented") +} +func (*UnimplementedDaemonServiceServer) HostHost(context.Context, *drkey.HostHostRequest) (*drkey.HostHostResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HostHost not implemented") +} func RegisterDaemonServiceServer(s *grpc.Server, srv DaemonServiceServer) { s.RegisterService(&_DaemonService_serviceDesc, srv) @@ -2451,24 +2498,6 @@ func _DaemonService_NotifyInterfaceDown_Handler(srv interface{}, ctx context.Con return interceptor(ctx, in, info, handler) } -func _DaemonService_DRKeyLvl2_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DRKeyLvl2Request) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DaemonServiceServer).DRKeyLvl2(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/proto.daemon.v1.DaemonService/DRKeyLvl2", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DaemonServiceServer).DRKeyLvl2(ctx, req.(*DRKeyLvl2Request)) - } - return interceptor(ctx, in, info, handler) -} - func _DaemonService_ColibriListRsvs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ColibriListRsvsRequest) if err := dec(in); err != nil { @@ -2541,6 +2570,60 @@ func _DaemonService_ColibriAddAdmissionEntry_Handler(srv interface{}, ctx contex return interceptor(ctx, in, info, handler) } +func _DaemonService_ASHost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.ASHostRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).ASHost(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.daemon.v1.DaemonService/ASHost", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).ASHost(ctx, req.(*drkey.ASHostRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DaemonService_HostAS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.HostASRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).HostAS(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.daemon.v1.DaemonService/HostAS", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).HostAS(ctx, req.(*drkey.HostASRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DaemonService_HostHost_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(drkey.HostHostRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).HostHost(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.daemon.v1.DaemonService/HostHost", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).HostHost(ctx, req.(*drkey.HostHostRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _DaemonService_serviceDesc = grpc.ServiceDesc{ ServiceName: "proto.daemon.v1.DaemonService", HandlerType: (*DaemonServiceServer)(nil), @@ -2565,10 +2648,6 @@ var _DaemonService_serviceDesc = grpc.ServiceDesc{ MethodName: "NotifyInterfaceDown", Handler: _DaemonService_NotifyInterfaceDown_Handler, }, - { - MethodName: "DRKeyLvl2", - Handler: _DaemonService_DRKeyLvl2_Handler, - }, { MethodName: "ColibriListRsvs", Handler: _DaemonService_ColibriListRsvs_Handler, @@ -2585,6 +2664,18 @@ var _DaemonService_serviceDesc = grpc.ServiceDesc{ MethodName: "ColibriAddAdmissionEntry", Handler: _DaemonService_ColibriAddAdmissionEntry_Handler, }, + { + MethodName: "ASHost", + Handler: _DaemonService_ASHost_Handler, + }, + { + MethodName: "HostAS", + Handler: _DaemonService_HostAS_Handler, + }, + { + MethodName: "HostHost", + Handler: _DaemonService_HostHost_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/daemon/v1/daemon.proto", diff --git a/go/pkg/proto/daemon/mock_daemon/BUILD.bazel b/go/pkg/proto/daemon/mock_daemon/BUILD.bazel index 7a898e601d..67cc7dc593 100644 --- a/go/pkg/proto/daemon/mock_daemon/BUILD.bazel +++ b/go/pkg/proto/daemon/mock_daemon/BUILD.bazel @@ -7,6 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//go/pkg/proto/daemon:go_default_library", + "//go/pkg/proto/drkey:go_default_library", "@com_github_golang_mock//gomock:go_default_library", ], ) diff --git a/go/pkg/proto/daemon/mock_daemon/daemon.go b/go/pkg/proto/daemon/mock_daemon/daemon.go index 5a0464b2f6..55bcf554d4 100644 --- a/go/pkg/proto/daemon/mock_daemon/daemon.go +++ b/go/pkg/proto/daemon/mock_daemon/daemon.go @@ -8,6 +8,7 @@ import ( context "context" gomock "github.com/golang/mock/gomock" daemon "github.com/scionproto/scion/go/pkg/proto/daemon" + drkey "github.com/scionproto/scion/go/pkg/proto/drkey" reflect "reflect" ) @@ -49,19 +50,109 @@ func (mr *MockDaemonServiceServerMockRecorder) AS(arg0, arg1 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AS", reflect.TypeOf((*MockDaemonServiceServer)(nil).AS), arg0, arg1) } -// DRKeyLvl2 mocks base method -func (m *MockDaemonServiceServer) DRKeyLvl2(arg0 context.Context, arg1 *daemon.DRKeyLvl2Request) (*daemon.DRKeyLvl2Response, error) { +// ASHost mocks base method +func (m *MockDaemonServiceServer) ASHost(arg0 context.Context, arg1 *drkey.ASHostRequest) (*drkey.ASHostResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DRKeyLvl2", arg0, arg1) - ret0, _ := ret[0].(*daemon.DRKeyLvl2Response) + ret := m.ctrl.Call(m, "ASHost", arg0, arg1) + ret0, _ := ret[0].(*drkey.ASHostResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// DRKeyLvl2 indicates an expected call of DRKeyLvl2 -func (mr *MockDaemonServiceServerMockRecorder) DRKeyLvl2(arg0, arg1 interface{}) *gomock.Call { +// ASHost indicates an expected call of ASHost +func (mr *MockDaemonServiceServerMockRecorder) ASHost(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DRKeyLvl2", reflect.TypeOf((*MockDaemonServiceServer)(nil).DRKeyLvl2), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ASHost", reflect.TypeOf((*MockDaemonServiceServer)(nil).ASHost), arg0, arg1) +} + +// ColibriAddAdmissionEntry mocks base method +func (m *MockDaemonServiceServer) ColibriAddAdmissionEntry(arg0 context.Context, arg1 *daemon.ColibriAdmissionEntry) (*daemon.ColibriAdmissionEntryResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ColibriAddAdmissionEntry", arg0, arg1) + ret0, _ := ret[0].(*daemon.ColibriAdmissionEntryResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ColibriAddAdmissionEntry indicates an expected call of ColibriAddAdmissionEntry +func (mr *MockDaemonServiceServerMockRecorder) ColibriAddAdmissionEntry(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ColibriAddAdmissionEntry", reflect.TypeOf((*MockDaemonServiceServer)(nil).ColibriAddAdmissionEntry), arg0, arg1) +} + +// ColibriCleanupRsv mocks base method +func (m *MockDaemonServiceServer) ColibriCleanupRsv(arg0 context.Context, arg1 *daemon.ColibriCleanupRequest) (*daemon.ColibriCleanupResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ColibriCleanupRsv", arg0, arg1) + ret0, _ := ret[0].(*daemon.ColibriCleanupResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ColibriCleanupRsv indicates an expected call of ColibriCleanupRsv +func (mr *MockDaemonServiceServerMockRecorder) ColibriCleanupRsv(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ColibriCleanupRsv", reflect.TypeOf((*MockDaemonServiceServer)(nil).ColibriCleanupRsv), arg0, arg1) +} + +// ColibriListRsvs mocks base method +func (m *MockDaemonServiceServer) ColibriListRsvs(arg0 context.Context, arg1 *daemon.ColibriListRequest) (*daemon.ColibriListResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ColibriListRsvs", arg0, arg1) + ret0, _ := ret[0].(*daemon.ColibriListResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ColibriListRsvs indicates an expected call of ColibriListRsvs +func (mr *MockDaemonServiceServerMockRecorder) ColibriListRsvs(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ColibriListRsvs", reflect.TypeOf((*MockDaemonServiceServer)(nil).ColibriListRsvs), arg0, arg1) +} + +// ColibriSetupRsv mocks base method +func (m *MockDaemonServiceServer) ColibriSetupRsv(arg0 context.Context, arg1 *daemon.ColibriSetupRequest) (*daemon.ColibriSetupResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ColibriSetupRsv", arg0, arg1) + ret0, _ := ret[0].(*daemon.ColibriSetupResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ColibriSetupRsv indicates an expected call of ColibriSetupRsv +func (mr *MockDaemonServiceServerMockRecorder) ColibriSetupRsv(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ColibriSetupRsv", reflect.TypeOf((*MockDaemonServiceServer)(nil).ColibriSetupRsv), arg0, arg1) +} + +// HostAS mocks base method +func (m *MockDaemonServiceServer) HostAS(arg0 context.Context, arg1 *drkey.HostASRequest) (*drkey.HostASResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HostAS", arg0, arg1) + ret0, _ := ret[0].(*drkey.HostASResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HostAS indicates an expected call of HostAS +func (mr *MockDaemonServiceServerMockRecorder) HostAS(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HostAS", reflect.TypeOf((*MockDaemonServiceServer)(nil).HostAS), arg0, arg1) +} + +// HostHost mocks base method +func (m *MockDaemonServiceServer) HostHost(arg0 context.Context, arg1 *drkey.HostHostRequest) (*drkey.HostHostResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HostHost", arg0, arg1) + ret0, _ := ret[0].(*drkey.HostHostResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HostHost indicates an expected call of HostHost +func (mr *MockDaemonServiceServerMockRecorder) HostHost(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HostHost", reflect.TypeOf((*MockDaemonServiceServer)(nil).HostHost), arg0, arg1) } // Interfaces mocks base method @@ -109,6 +200,21 @@ func (mr *MockDaemonServiceServerMockRecorder) Paths(arg0, arg1 interface{}) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Paths", reflect.TypeOf((*MockDaemonServiceServer)(nil).Paths), arg0, arg1) } +// SV mocks base method +func (m *MockDaemonServiceServer) SV(arg0 context.Context, arg1 *daemon.SVRequest) (*daemon.SVResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SV", arg0, arg1) + ret0, _ := ret[0].(*daemon.SVResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SV indicates an expected call of SV +func (mr *MockDaemonServiceServerMockRecorder) SV(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SV", reflect.TypeOf((*MockDaemonServiceServer)(nil).SV), arg0, arg1) +} + // Services mocks base method func (m *MockDaemonServiceServer) Services(arg0 context.Context, arg1 *daemon.ServicesRequest) (*daemon.ServicesResponse, error) { m.ctrl.T.Helper() diff --git a/go/pkg/proto/drkey/mgmt.pb.go b/go/pkg/proto/drkey/mgmt.pb.go index 2940f2c106..70af62ceda 100644 --- a/go/pkg/proto/drkey/mgmt.pb.go +++ b/go/pkg/proto/drkey/mgmt.pb.go @@ -21,17 +21,69 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type DRKeyLvl1Request struct { +type Protocol int32 + +const ( + Protocol_PROTOCOL_GENERIC_UNSPECIFIED Protocol = 0 + Protocol_PROTOCOL_SCMP Protocol = 1 + Protocol_PROTOCOL_DNS Protocol = 2 + Protocol_PROTOCOL_COLIBRI Protocol = 3 +) + +// Enum value maps for Protocol. +var ( + Protocol_name = map[int32]string{ + 0: "PROTOCOL_GENERIC_UNSPECIFIED", + 1: "PROTOCOL_SCMP", + 2: "PROTOCOL_DNS", + 3: "PROTOCOL_COLIBRI", + } + Protocol_value = map[string]int32{ + "PROTOCOL_GENERIC_UNSPECIFIED": 0, + "PROTOCOL_SCMP": 1, + "PROTOCOL_DNS": 2, + "PROTOCOL_COLIBRI": 3, + } +) + +func (x Protocol) Enum() *Protocol { + p := new(Protocol) + *p = x + return p +} + +func (x Protocol) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Protocol) Descriptor() protoreflect.EnumDescriptor { + return file_proto_drkey_mgmt_v1_mgmt_proto_enumTypes[0].Descriptor() +} + +func (Protocol) Type() protoreflect.EnumType { + return &file_proto_drkey_mgmt_v1_mgmt_proto_enumTypes[0] +} + +func (x Protocol) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Protocol.Descriptor instead. +func (Protocol) EnumDescriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{0} +} + +type SVRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` - Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` + ProtocolId Protocol `protobuf:"varint,2,opt,name=protocol_id,json=protocolId,proto3,enum=proto.drkey.mgmt.v1.Protocol" json:"protocol_id,omitempty"` } -func (x *DRKeyLvl1Request) Reset() { - *x = DRKeyLvl1Request{} +func (x *SVRequest) Reset() { + *x = SVRequest{} if protoimpl.UnsafeEnabled { mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -39,13 +91,13 @@ func (x *DRKeyLvl1Request) Reset() { } } -func (x *DRKeyLvl1Request) String() string { +func (x *SVRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl1Request) ProtoMessage() {} +func (*SVRequest) ProtoMessage() {} -func (x *DRKeyLvl1Request) ProtoReflect() protoreflect.Message { +func (x *SVRequest) ProtoReflect() protoreflect.Message { mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -57,38 +109,37 @@ func (x *DRKeyLvl1Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl1Request.ProtoReflect.Descriptor instead. -func (*DRKeyLvl1Request) Descriptor() ([]byte, []int) { +// Deprecated: Use SVRequest.ProtoReflect.Descriptor instead. +func (*SVRequest) Descriptor() ([]byte, []int) { return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{0} } -func (x *DRKeyLvl1Request) GetValTime() *timestamppb.Timestamp { +func (x *SVRequest) GetValTime() *timestamppb.Timestamp { if x != nil { return x.ValTime } return nil } -func (x *DRKeyLvl1Request) GetTimestamp() *timestamppb.Timestamp { +func (x *SVRequest) GetProtocolId() Protocol { if x != nil { - return x.Timestamp + return x.ProtocolId } - return nil + return Protocol_PROTOCOL_GENERIC_UNSPECIFIED } -type DRKeyLvl1Response struct { +type SVResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` - Drkey []byte `protobuf:"bytes,3,opt,name=drkey,proto3" json:"drkey,omitempty"` - Timestamp *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` } -func (x *DRKeyLvl1Response) Reset() { - *x = DRKeyLvl1Response{} +func (x *SVResponse) Reset() { + *x = SVResponse{} if protoimpl.UnsafeEnabled { mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -96,13 +147,13 @@ func (x *DRKeyLvl1Response) Reset() { } } -func (x *DRKeyLvl1Response) String() string { +func (x *SVResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl1Response) ProtoMessage() {} +func (*SVResponse) ProtoMessage() {} -func (x *DRKeyLvl1Response) ProtoReflect() protoreflect.Message { +func (x *SVResponse) ProtoReflect() protoreflect.Message { mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -114,71 +165,114 @@ func (x *DRKeyLvl1Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl1Response.ProtoReflect.Descriptor instead. -func (*DRKeyLvl1Response) Descriptor() ([]byte, []int) { +// Deprecated: Use SVResponse.ProtoReflect.Descriptor instead. +func (*SVResponse) Descriptor() ([]byte, []int) { return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{1} } -func (x *DRKeyLvl1Response) GetEpochBegin() *timestamppb.Timestamp { +func (x *SVResponse) GetEpochBegin() *timestamppb.Timestamp { if x != nil { return x.EpochBegin } return nil } -func (x *DRKeyLvl1Response) GetEpochEnd() *timestamppb.Timestamp { +func (x *SVResponse) GetEpochEnd() *timestamppb.Timestamp { if x != nil { return x.EpochEnd } return nil } -func (x *DRKeyLvl1Response) GetDrkey() []byte { +func (x *SVResponse) GetKey() []byte { if x != nil { - return x.Drkey + return x.Key } return nil } -func (x *DRKeyLvl1Response) GetTimestamp() *timestamppb.Timestamp { +type Lvl1Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` + ProtocolId Protocol `protobuf:"varint,2,opt,name=protocol_id,json=protocolId,proto3,enum=proto.drkey.mgmt.v1.Protocol" json:"protocol_id,omitempty"` +} + +func (x *Lvl1Request) Reset() { + *x = Lvl1Request{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Lvl1Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Lvl1Request) ProtoMessage() {} + +func (x *Lvl1Request) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Lvl1Request.ProtoReflect.Descriptor instead. +func (*Lvl1Request) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{2} +} + +func (x *Lvl1Request) GetValTime() *timestamppb.Timestamp { if x != nil { - return x.Timestamp + return x.ValTime } return nil } -type DRKeyLvl2Request struct { +func (x *Lvl1Request) GetProtocolId() Protocol { + if x != nil { + return x.ProtocolId + } + return Protocol_PROTOCOL_GENERIC_UNSPECIFIED +} + +type Lvl1Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Protocol string `protobuf:"bytes,1,opt,name=protocol,proto3" json:"protocol,omitempty"` - ReqType uint32 `protobuf:"varint,2,opt,name=req_type,json=reqType,proto3" json:"req_type,omitempty"` - ValTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` - SrcIa uint64 `protobuf:"varint,4,opt,name=src_ia,json=srcIa,proto3" json:"src_ia,omitempty"` - DstIa uint64 `protobuf:"varint,5,opt,name=dst_ia,json=dstIa,proto3" json:"dst_ia,omitempty"` - SrcHost *DRKeyLvl2Request_DRKeyHost `protobuf:"bytes,6,opt,name=src_host,json=srcHost,proto3" json:"src_host,omitempty"` - DstHost *DRKeyLvl2Request_DRKeyHost `protobuf:"bytes,7,opt,name=dst_host,json=dstHost,proto3" json:"dst_host,omitempty"` - Misc []byte `protobuf:"bytes,8,opt,name=misc,proto3" json:"misc,omitempty"` + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` } -func (x *DRKeyLvl2Request) Reset() { - *x = DRKeyLvl2Request{} +func (x *Lvl1Response) Reset() { + *x = Lvl1Response{} if protoimpl.UnsafeEnabled { - mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[2] + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *DRKeyLvl2Request) String() string { +func (x *Lvl1Response) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl2Request) ProtoMessage() {} +func (*Lvl1Response) ProtoMessage() {} -func (x *DRKeyLvl2Request) ProtoReflect() protoreflect.Message { - mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[2] +func (x *Lvl1Response) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -189,96 +283,337 @@ func (x *DRKeyLvl2Request) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl2Request.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Request) Descriptor() ([]byte, []int) { - return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{2} +// Deprecated: Use Lvl1Response.ProtoReflect.Descriptor instead. +func (*Lvl1Response) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{3} } -func (x *DRKeyLvl2Request) GetProtocol() string { +func (x *Lvl1Response) GetEpochBegin() *timestamppb.Timestamp { if x != nil { - return x.Protocol + return x.EpochBegin } - return "" + return nil +} + +func (x *Lvl1Response) GetEpochEnd() *timestamppb.Timestamp { + if x != nil { + return x.EpochEnd + } + return nil +} + +func (x *Lvl1Response) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +type IntraLvl1Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` + ProtocolId Protocol `protobuf:"varint,2,opt,name=protocol_id,json=protocolId,proto3,enum=proto.drkey.mgmt.v1.Protocol" json:"protocol_id,omitempty"` + SrcIa uint64 `protobuf:"varint,3,opt,name=src_ia,json=srcIa,proto3" json:"src_ia,omitempty"` + DstIa uint64 `protobuf:"varint,4,opt,name=dst_ia,json=dstIa,proto3" json:"dst_ia,omitempty"` +} + +func (x *IntraLvl1Request) Reset() { + *x = IntraLvl1Request{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IntraLvl1Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IntraLvl1Request) ProtoMessage() {} + +func (x *IntraLvl1Request) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (x *DRKeyLvl2Request) GetReqType() uint32 { +// Deprecated: Use IntraLvl1Request.ProtoReflect.Descriptor instead. +func (*IntraLvl1Request) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{4} +} + +func (x *IntraLvl1Request) GetValTime() *timestamppb.Timestamp { if x != nil { - return x.ReqType + return x.ValTime + } + return nil +} + +func (x *IntraLvl1Request) GetProtocolId() Protocol { + if x != nil { + return x.ProtocolId + } + return Protocol_PROTOCOL_GENERIC_UNSPECIFIED +} + +func (x *IntraLvl1Request) GetSrcIa() uint64 { + if x != nil { + return x.SrcIa + } + return 0 +} + +func (x *IntraLvl1Request) GetDstIa() uint64 { + if x != nil { + return x.DstIa } return 0 } -func (x *DRKeyLvl2Request) GetValTime() *timestamppb.Timestamp { +type IntraLvl1Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *IntraLvl1Response) Reset() { + *x = IntraLvl1Response{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IntraLvl1Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IntraLvl1Response) ProtoMessage() {} + +func (x *IntraLvl1Response) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IntraLvl1Response.ProtoReflect.Descriptor instead. +func (*IntraLvl1Response) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{5} +} + +func (x *IntraLvl1Response) GetEpochBegin() *timestamppb.Timestamp { + if x != nil { + return x.EpochBegin + } + return nil +} + +func (x *IntraLvl1Response) GetEpochEnd() *timestamppb.Timestamp { + if x != nil { + return x.EpochEnd + } + return nil +} + +func (x *IntraLvl1Response) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} + +type HostASRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` + ProtocolId Protocol `protobuf:"varint,2,opt,name=protocol_id,json=protocolId,proto3,enum=proto.drkey.mgmt.v1.Protocol" json:"protocol_id,omitempty"` + SrcIa uint64 `protobuf:"varint,3,opt,name=src_ia,json=srcIa,proto3" json:"src_ia,omitempty"` + DstIa uint64 `protobuf:"varint,4,opt,name=dst_ia,json=dstIa,proto3" json:"dst_ia,omitempty"` + SrcHost string `protobuf:"bytes,5,opt,name=src_host,json=srcHost,proto3" json:"src_host,omitempty"` +} + +func (x *HostASRequest) Reset() { + *x = HostASRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HostASRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostASRequest) ProtoMessage() {} + +func (x *HostASRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HostASRequest.ProtoReflect.Descriptor instead. +func (*HostASRequest) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{6} +} + +func (x *HostASRequest) GetValTime() *timestamppb.Timestamp { if x != nil { return x.ValTime } return nil } -func (x *DRKeyLvl2Request) GetSrcIa() uint64 { +func (x *HostASRequest) GetProtocolId() Protocol { + if x != nil { + return x.ProtocolId + } + return Protocol_PROTOCOL_GENERIC_UNSPECIFIED +} + +func (x *HostASRequest) GetSrcIa() uint64 { if x != nil { return x.SrcIa } return 0 } -func (x *DRKeyLvl2Request) GetDstIa() uint64 { +func (x *HostASRequest) GetDstIa() uint64 { if x != nil { return x.DstIa } return 0 } -func (x *DRKeyLvl2Request) GetSrcHost() *DRKeyLvl2Request_DRKeyHost { +func (x *HostASRequest) GetSrcHost() string { if x != nil { return x.SrcHost } + return "" +} + +type HostASResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *HostASResponse) Reset() { + *x = HostASResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HostASResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostASResponse) ProtoMessage() {} + +func (x *HostASResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HostASResponse.ProtoReflect.Descriptor instead. +func (*HostASResponse) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{7} +} + +func (x *HostASResponse) GetEpochBegin() *timestamppb.Timestamp { + if x != nil { + return x.EpochBegin + } return nil } -func (x *DRKeyLvl2Request) GetDstHost() *DRKeyLvl2Request_DRKeyHost { +func (x *HostASResponse) GetEpochEnd() *timestamppb.Timestamp { if x != nil { - return x.DstHost + return x.EpochEnd } return nil } -func (x *DRKeyLvl2Request) GetMisc() []byte { +func (x *HostASResponse) GetKey() []byte { if x != nil { - return x.Misc + return x.Key } return nil } -type DRKeyLvl2Response struct { +type ASHostRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Drkey []byte `protobuf:"bytes,2,opt,name=drkey,proto3" json:"drkey,omitempty"` - EpochBegin *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` - EpochEnd *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` - Misc []byte `protobuf:"bytes,5,opt,name=misc,proto3" json:"misc,omitempty"` + ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` + ProtocolId Protocol `protobuf:"varint,2,opt,name=protocol_id,json=protocolId,proto3,enum=proto.drkey.mgmt.v1.Protocol" json:"protocol_id,omitempty"` + SrcIa uint64 `protobuf:"varint,3,opt,name=src_ia,json=srcIa,proto3" json:"src_ia,omitempty"` + DstIa uint64 `protobuf:"varint,4,opt,name=dst_ia,json=dstIa,proto3" json:"dst_ia,omitempty"` + DstHost string `protobuf:"bytes,5,opt,name=dst_host,json=dstHost,proto3" json:"dst_host,omitempty"` } -func (x *DRKeyLvl2Response) Reset() { - *x = DRKeyLvl2Response{} +func (x *ASHostRequest) Reset() { + *x = ASHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[3] + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *DRKeyLvl2Response) String() string { +func (x *ASHostRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl2Response) ProtoMessage() {} +func (*ASHostRequest) ProtoMessage() {} -func (x *DRKeyLvl2Response) ProtoReflect() protoreflect.Message { - mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[3] +func (x *ASHostRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -289,72 +624,139 @@ func (x *DRKeyLvl2Response) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl2Response.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Response) Descriptor() ([]byte, []int) { - return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{3} +// Deprecated: Use ASHostRequest.ProtoReflect.Descriptor instead. +func (*ASHostRequest) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{8} } -func (x *DRKeyLvl2Response) GetTimestamp() *timestamppb.Timestamp { +func (x *ASHostRequest) GetValTime() *timestamppb.Timestamp { if x != nil { - return x.Timestamp + return x.ValTime } return nil } -func (x *DRKeyLvl2Response) GetDrkey() []byte { +func (x *ASHostRequest) GetProtocolId() Protocol { if x != nil { - return x.Drkey + return x.ProtocolId } - return nil + return Protocol_PROTOCOL_GENERIC_UNSPECIFIED +} + +func (x *ASHostRequest) GetSrcIa() uint64 { + if x != nil { + return x.SrcIa + } + return 0 +} + +func (x *ASHostRequest) GetDstIa() uint64 { + if x != nil { + return x.DstIa + } + return 0 } -func (x *DRKeyLvl2Response) GetEpochBegin() *timestamppb.Timestamp { +func (x *ASHostRequest) GetDstHost() string { + if x != nil { + return x.DstHost + } + return "" +} + +type ASHostResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *ASHostResponse) Reset() { + *x = ASHostResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ASHostResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ASHostResponse) ProtoMessage() {} + +func (x *ASHostResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ASHostResponse.ProtoReflect.Descriptor instead. +func (*ASHostResponse) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{9} +} + +func (x *ASHostResponse) GetEpochBegin() *timestamppb.Timestamp { if x != nil { return x.EpochBegin } return nil } -func (x *DRKeyLvl2Response) GetEpochEnd() *timestamppb.Timestamp { +func (x *ASHostResponse) GetEpochEnd() *timestamppb.Timestamp { if x != nil { return x.EpochEnd } return nil } -func (x *DRKeyLvl2Response) GetMisc() []byte { +func (x *ASHostResponse) GetKey() []byte { if x != nil { - return x.Misc + return x.Key } return nil } -type DRKeyLvl2Request_DRKeyHost struct { +type HostHostRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Type uint32 `protobuf:"varint,1,opt,name=type,proto3" json:"type,omitempty"` - Host []byte `protobuf:"bytes,2,opt,name=host,proto3" json:"host,omitempty"` + ValTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=val_time,json=valTime,proto3" json:"val_time,omitempty"` + ProtocolId Protocol `protobuf:"varint,2,opt,name=protocol_id,json=protocolId,proto3,enum=proto.drkey.mgmt.v1.Protocol" json:"protocol_id,omitempty"` + SrcIa uint64 `protobuf:"varint,3,opt,name=src_ia,json=srcIa,proto3" json:"src_ia,omitempty"` + DstIa uint64 `protobuf:"varint,4,opt,name=dst_ia,json=dstIa,proto3" json:"dst_ia,omitempty"` + SrcHost string `protobuf:"bytes,5,opt,name=src_host,json=srcHost,proto3" json:"src_host,omitempty"` + DstHost string `protobuf:"bytes,6,opt,name=dst_host,json=dstHost,proto3" json:"dst_host,omitempty"` } -func (x *DRKeyLvl2Request_DRKeyHost) Reset() { - *x = DRKeyLvl2Request_DRKeyHost{} +func (x *HostHostRequest) Reset() { + *x = HostHostRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[4] + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *DRKeyLvl2Request_DRKeyHost) String() string { +func (x *HostHostRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*DRKeyLvl2Request_DRKeyHost) ProtoMessage() {} +func (*HostHostRequest) ProtoMessage() {} -func (x *DRKeyLvl2Request_DRKeyHost) ProtoReflect() protoreflect.Message { - mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[4] +func (x *HostHostRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -365,21 +767,112 @@ func (x *DRKeyLvl2Request_DRKeyHost) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DRKeyLvl2Request_DRKeyHost.ProtoReflect.Descriptor instead. -func (*DRKeyLvl2Request_DRKeyHost) Descriptor() ([]byte, []int) { - return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{2, 0} +// Deprecated: Use HostHostRequest.ProtoReflect.Descriptor instead. +func (*HostHostRequest) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{10} } -func (x *DRKeyLvl2Request_DRKeyHost) GetType() uint32 { +func (x *HostHostRequest) GetValTime() *timestamppb.Timestamp { if x != nil { - return x.Type + return x.ValTime + } + return nil +} + +func (x *HostHostRequest) GetProtocolId() Protocol { + if x != nil { + return x.ProtocolId + } + return Protocol_PROTOCOL_GENERIC_UNSPECIFIED +} + +func (x *HostHostRequest) GetSrcIa() uint64 { + if x != nil { + return x.SrcIa + } + return 0 +} + +func (x *HostHostRequest) GetDstIa() uint64 { + if x != nil { + return x.DstIa } return 0 } -func (x *DRKeyLvl2Request_DRKeyHost) GetHost() []byte { +func (x *HostHostRequest) GetSrcHost() string { + if x != nil { + return x.SrcHost + } + return "" +} + +func (x *HostHostRequest) GetDstHost() string { + if x != nil { + return x.DstHost + } + return "" +} + +type HostHostResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EpochBegin *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=epoch_begin,json=epochBegin,proto3" json:"epoch_begin,omitempty"` + EpochEnd *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=epoch_end,json=epochEnd,proto3" json:"epoch_end,omitempty"` + Key []byte `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` +} + +func (x *HostHostResponse) Reset() { + *x = HostHostResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HostHostResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostHostResponse) ProtoMessage() {} + +func (x *HostHostResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HostHostResponse.ProtoReflect.Descriptor instead. +func (*HostHostResponse) Descriptor() ([]byte, []int) { + return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP(), []int{11} +} + +func (x *HostHostResponse) GetEpochBegin() *timestamppb.Timestamp { + if x != nil { + return x.EpochBegin + } + return nil +} + +func (x *HostHostResponse) GetEpochEnd() *timestamppb.Timestamp { + if x != nil { + return x.EpochEnd + } + return nil +} + +func (x *HostHostResponse) GetKey() []byte { if x != nil { - return x.Host + return x.Key } return nil } @@ -392,16 +885,55 @@ var file_proto_drkey_mgmt_v1_mgmt_proto_rawDesc = []byte{ 0x12, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x44, 0x52, 0x4b, 0x65, 0x79, - 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, - 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xd9, 0x01, 0x0a, - 0x11, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x01, 0x0a, 0x09, 0x53, 0x56, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, + 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, + 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x22, 0x94, 0x01, 0x0a, 0x0a, + 0x53, 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x22, 0x84, 0x01, 0x0a, 0x0b, 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x22, 0x96, 0x01, 0x0a, 0x0c, 0x4c, 0x76, + 0x6c, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x22, 0xb7, 0x01, 0x0a, 0x10, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x4c, 0x76, 0x6c, 0x31, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, + 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, + 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x15, + 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x22, 0x9b, 0x01, 0x0a, + 0x11, 0x49, 0x6e, 0x74, 0x72, 0x61, 0x4c, 0x76, 0x6c, 0x31, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, @@ -409,56 +941,89 @@ var file_proto_drkey_mgmt_v1_mgmt_proto_rawDesc = []byte{ 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x72, 0x6b, 0x65, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x12, 0x38, - 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcf, 0x01, 0x0a, 0x0d, 0x48, + 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, + 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, + 0x74, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, + 0x61, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x98, 0x01, 0x0a, + 0x0e, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xcf, 0x01, 0x0a, 0x0d, 0x41, 0x53, 0x48, 0x6f, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x3e, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, + 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, + 0x12, 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, + 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, + 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x41, 0x53, + 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x8f, 0x03, 0x0a, 0x10, 0x44, 0x52, 0x4b, - 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x65, 0x71, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x72, 0x65, 0x71, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x73, - 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x72, 0x63, - 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x4a, 0x0a, 0x08, 0x73, 0x72, 0x63, - 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x07, 0x73, 0x72, - 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x64, 0x72, 0x6b, 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x52, - 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, - 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, 0x6f, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x69, 0x73, 0x63, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x6d, 0x69, 0x73, 0x63, 0x1a, 0x33, 0x0a, 0x09, 0x44, 0x52, 0x4b, 0x65, 0x79, 0x48, 0x6f, - 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x22, 0xed, 0x01, 0x0a, 0x11, 0x44, - 0x52, 0x4b, 0x65, 0x79, 0x4c, 0x76, 0x6c, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x72, - 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x64, 0x72, 0x6b, 0x65, 0x79, - 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, - 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x69, 0x73, 0x63, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6d, 0x69, 0x73, 0x63, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, + 0x6e, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x22, 0xec, 0x01, 0x0a, 0x0f, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x3e, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x64, 0x72, 0x6b, + 0x65, 0x79, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x64, 0x12, + 0x15, 0x0a, 0x06, 0x73, 0x72, 0x63, 0x5f, 0x69, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x73, 0x72, 0x63, 0x49, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x73, 0x74, 0x5f, 0x69, 0x61, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x73, 0x74, 0x49, 0x61, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x72, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x72, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x73, 0x74, 0x5f, + 0x68, 0x6f, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x73, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x22, 0x9a, 0x01, 0x0a, 0x10, 0x48, 0x6f, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x42, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x6e, 0x64, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x2a, 0x73, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x20, 0x0a, 0x1c, + 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x49, 0x43, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, + 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x53, 0x43, 0x4d, 0x50, 0x10, + 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x44, 0x4e, + 0x53, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, + 0x43, 0x4f, 0x4c, 0x49, 0x42, 0x52, 0x49, 0x10, 0x03, 0x22, 0x0a, 0x08, 0x80, 0x80, 0x04, 0x10, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x63, 0x69, 0x6f, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, + 0x63, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x64, 0x72, 0x6b, 0x65, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -473,32 +1038,54 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_rawDescGZIP() []byte { return file_proto_drkey_mgmt_v1_mgmt_proto_rawDescData } -var file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_proto_drkey_mgmt_v1_mgmt_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_proto_drkey_mgmt_v1_mgmt_proto_goTypes = []interface{}{ - (*DRKeyLvl1Request)(nil), // 0: proto.drkey.mgmt.v1.DRKeyLvl1Request - (*DRKeyLvl1Response)(nil), // 1: proto.drkey.mgmt.v1.DRKeyLvl1Response - (*DRKeyLvl2Request)(nil), // 2: proto.drkey.mgmt.v1.DRKeyLvl2Request - (*DRKeyLvl2Response)(nil), // 3: proto.drkey.mgmt.v1.DRKeyLvl2Response - (*DRKeyLvl2Request_DRKeyHost)(nil), // 4: proto.drkey.mgmt.v1.DRKeyLvl2Request.DRKeyHost - (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp + (Protocol)(0), // 0: proto.drkey.mgmt.v1.Protocol + (*SVRequest)(nil), // 1: proto.drkey.mgmt.v1.SVRequest + (*SVResponse)(nil), // 2: proto.drkey.mgmt.v1.SVResponse + (*Lvl1Request)(nil), // 3: proto.drkey.mgmt.v1.Lvl1Request + (*Lvl1Response)(nil), // 4: proto.drkey.mgmt.v1.Lvl1Response + (*IntraLvl1Request)(nil), // 5: proto.drkey.mgmt.v1.IntraLvl1Request + (*IntraLvl1Response)(nil), // 6: proto.drkey.mgmt.v1.IntraLvl1Response + (*HostASRequest)(nil), // 7: proto.drkey.mgmt.v1.HostASRequest + (*HostASResponse)(nil), // 8: proto.drkey.mgmt.v1.HostASResponse + (*ASHostRequest)(nil), // 9: proto.drkey.mgmt.v1.ASHostRequest + (*ASHostResponse)(nil), // 10: proto.drkey.mgmt.v1.ASHostResponse + (*HostHostRequest)(nil), // 11: proto.drkey.mgmt.v1.HostHostRequest + (*HostHostResponse)(nil), // 12: proto.drkey.mgmt.v1.HostHostResponse + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp } var file_proto_drkey_mgmt_v1_mgmt_proto_depIdxs = []int32{ - 5, // 0: proto.drkey.mgmt.v1.DRKeyLvl1Request.val_time:type_name -> google.protobuf.Timestamp - 5, // 1: proto.drkey.mgmt.v1.DRKeyLvl1Request.timestamp:type_name -> google.protobuf.Timestamp - 5, // 2: proto.drkey.mgmt.v1.DRKeyLvl1Response.epoch_begin:type_name -> google.protobuf.Timestamp - 5, // 3: proto.drkey.mgmt.v1.DRKeyLvl1Response.epoch_end:type_name -> google.protobuf.Timestamp - 5, // 4: proto.drkey.mgmt.v1.DRKeyLvl1Response.timestamp:type_name -> google.protobuf.Timestamp - 5, // 5: proto.drkey.mgmt.v1.DRKeyLvl2Request.val_time:type_name -> google.protobuf.Timestamp - 4, // 6: proto.drkey.mgmt.v1.DRKeyLvl2Request.src_host:type_name -> proto.drkey.mgmt.v1.DRKeyLvl2Request.DRKeyHost - 4, // 7: proto.drkey.mgmt.v1.DRKeyLvl2Request.dst_host:type_name -> proto.drkey.mgmt.v1.DRKeyLvl2Request.DRKeyHost - 5, // 8: proto.drkey.mgmt.v1.DRKeyLvl2Response.timestamp:type_name -> google.protobuf.Timestamp - 5, // 9: proto.drkey.mgmt.v1.DRKeyLvl2Response.epoch_begin:type_name -> google.protobuf.Timestamp - 5, // 10: proto.drkey.mgmt.v1.DRKeyLvl2Response.epoch_end:type_name -> google.protobuf.Timestamp - 11, // [11:11] is the sub-list for method output_type - 11, // [11:11] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 13, // 0: proto.drkey.mgmt.v1.SVRequest.val_time:type_name -> google.protobuf.Timestamp + 0, // 1: proto.drkey.mgmt.v1.SVRequest.protocol_id:type_name -> proto.drkey.mgmt.v1.Protocol + 13, // 2: proto.drkey.mgmt.v1.SVResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 13, // 3: proto.drkey.mgmt.v1.SVResponse.epoch_end:type_name -> google.protobuf.Timestamp + 13, // 4: proto.drkey.mgmt.v1.Lvl1Request.val_time:type_name -> google.protobuf.Timestamp + 0, // 5: proto.drkey.mgmt.v1.Lvl1Request.protocol_id:type_name -> proto.drkey.mgmt.v1.Protocol + 13, // 6: proto.drkey.mgmt.v1.Lvl1Response.epoch_begin:type_name -> google.protobuf.Timestamp + 13, // 7: proto.drkey.mgmt.v1.Lvl1Response.epoch_end:type_name -> google.protobuf.Timestamp + 13, // 8: proto.drkey.mgmt.v1.IntraLvl1Request.val_time:type_name -> google.protobuf.Timestamp + 0, // 9: proto.drkey.mgmt.v1.IntraLvl1Request.protocol_id:type_name -> proto.drkey.mgmt.v1.Protocol + 13, // 10: proto.drkey.mgmt.v1.IntraLvl1Response.epoch_begin:type_name -> google.protobuf.Timestamp + 13, // 11: proto.drkey.mgmt.v1.IntraLvl1Response.epoch_end:type_name -> google.protobuf.Timestamp + 13, // 12: proto.drkey.mgmt.v1.HostASRequest.val_time:type_name -> google.protobuf.Timestamp + 0, // 13: proto.drkey.mgmt.v1.HostASRequest.protocol_id:type_name -> proto.drkey.mgmt.v1.Protocol + 13, // 14: proto.drkey.mgmt.v1.HostASResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 13, // 15: proto.drkey.mgmt.v1.HostASResponse.epoch_end:type_name -> google.protobuf.Timestamp + 13, // 16: proto.drkey.mgmt.v1.ASHostRequest.val_time:type_name -> google.protobuf.Timestamp + 0, // 17: proto.drkey.mgmt.v1.ASHostRequest.protocol_id:type_name -> proto.drkey.mgmt.v1.Protocol + 13, // 18: proto.drkey.mgmt.v1.ASHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 13, // 19: proto.drkey.mgmt.v1.ASHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 13, // 20: proto.drkey.mgmt.v1.HostHostRequest.val_time:type_name -> google.protobuf.Timestamp + 0, // 21: proto.drkey.mgmt.v1.HostHostRequest.protocol_id:type_name -> proto.drkey.mgmt.v1.Protocol + 13, // 22: proto.drkey.mgmt.v1.HostHostResponse.epoch_begin:type_name -> google.protobuf.Timestamp + 13, // 23: proto.drkey.mgmt.v1.HostHostResponse.epoch_end:type_name -> google.protobuf.Timestamp + 24, // [24:24] is the sub-list for method output_type + 24, // [24:24] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name } func init() { file_proto_drkey_mgmt_v1_mgmt_proto_init() } @@ -508,7 +1095,7 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_init() { } if !protoimpl.UnsafeEnabled { file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl1Request); i { + switch v := v.(*SVRequest); i { case 0: return &v.state case 1: @@ -520,7 +1107,7 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_init() { } } file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl1Response); i { + switch v := v.(*SVResponse); i { case 0: return &v.state case 1: @@ -532,7 +1119,7 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_init() { } } file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Request); i { + switch v := v.(*Lvl1Request); i { case 0: return &v.state case 1: @@ -544,7 +1131,7 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_init() { } } file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Response); i { + switch v := v.(*Lvl1Response); i { case 0: return &v.state case 1: @@ -556,7 +1143,91 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_init() { } } file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DRKeyLvl2Request_DRKeyHost); i { + switch v := v.(*IntraLvl1Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IntraLvl1Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HostASRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HostASResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ASHostRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ASHostResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HostHostRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HostHostResponse); i { case 0: return &v.state case 1: @@ -573,13 +1244,14 @@ func file_proto_drkey_mgmt_v1_mgmt_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_drkey_mgmt_v1_mgmt_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, + NumEnums: 1, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, GoTypes: file_proto_drkey_mgmt_v1_mgmt_proto_goTypes, DependencyIndexes: file_proto_drkey_mgmt_v1_mgmt_proto_depIdxs, + EnumInfos: file_proto_drkey_mgmt_v1_mgmt_proto_enumTypes, MessageInfos: file_proto_drkey_mgmt_v1_mgmt_proto_msgTypes, }.Build() File_proto_drkey_mgmt_v1_mgmt_proto = out.File diff --git a/go/pkg/storage/BUILD.bazel b/go/pkg/storage/BUILD.bazel index b8c03d854e..5fe391b670 100644 --- a/go/pkg/storage/BUILD.bazel +++ b/go/pkg/storage/BUILD.bazel @@ -15,7 +15,7 @@ go_library( "//go/lib/addr:go_default_library", "//go/lib/config:go_default_library", "//go/lib/drkey:go_default_library", - "//go/lib/drkey/drkeydbsqlite:go_default_library", + "//go/lib/drkey/sqlite:go_default_library", "//go/lib/infra/modules/cleaner:go_default_library", "//go/lib/infra/modules/db:go_default_library", "//go/lib/log:go_default_library", diff --git a/go/pkg/storage/storage.go b/go/pkg/storage/storage.go index 17d8895c16..13f038802f 100644 --- a/go/pkg/storage/storage.go +++ b/go/pkg/storage/storage.go @@ -27,7 +27,7 @@ import ( "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/config" "github.com/scionproto/scion/go/lib/drkey" - "github.com/scionproto/scion/go/lib/drkey/drkeydbsqlite" + "github.com/scionproto/scion/go/lib/drkey/sqlite" "github.com/scionproto/scion/go/lib/infra/modules/cleaner" "github.com/scionproto/scion/go/lib/infra/modules/db" "github.com/scionproto/scion/go/lib/log" @@ -50,11 +50,13 @@ const ( // BackendSqlite indicates an sqlite backend. BackendSqlite Backend = "sqlite" // DefaultPath indicates the default connection string for a generic database. - DefaultPath = "/share/scion.db" - DefaultTrustDBPath = "/share/data/%s.trust.db" - DefaultPathDBPath = "/share/cache/%s.path.db" - DefaultDRKeyDBPath = "/share/cache/%s.drkey.db" - DefaultColibriDBPath = "/share/cache/%s.colibri.db" + DefaultPath = "/share/scion.db" + DefaultTrustDBPath = "/share/data/%s.trust.db" + DefaultPathDBPath = "/share/cache/%s.path.db" + DefaultColibriDBPath = "/share/cache/%s.colibri.db" + DefaultDRKeyLvl1DBPath = "/share/cache/%s.drkey_lv1.db" + DefaultDRKeyLvl2DBPath = "/share/cache/%s.drkey_lv2.db" + DefaultDRKeySVDBPath = "/share/cache/%s.drkey_sv.db" ) // Default samples for various databases. @@ -68,8 +70,14 @@ var ( SampleTrustDB = DBConfig{ Connection: DefaultTrustDBPath, } - SampleDRKeyDB = DBConfig{ - Connection: DefaultDRKeyDBPath, + SampleDRKeyLvl1DB = DBConfig{ + Connection: DefaultDRKeyLvl1DBPath, + } + SampleDRKeyLvl2DB = DBConfig{ + Connection: DefaultDRKeyLvl2DBPath, + } + SampleDRKeySVDB = DBConfig{ + Connection: DefaultDRKeySVDBPath, } SampleColibriDB = DBConfig{ Connection: DefaultColibriDBPath, @@ -246,9 +254,19 @@ func NewTrustStorage(c DBConfig) (TrustDB, error) { return db, nil } +func NewDRKeySVStorage(c DBConfig) (drkey.SecretValueDB, error) { + log.Info("Connecting DRKeySVDB", " ", BackendSqlite, "connection", c.Connection) + db, err := sqlite.NewSVBackend(c.Connection) + if err != nil { + return nil, err + } + SetConnLimits(db, c) + return db, nil +} + func NewDRKeyLvl1Storage(c DBConfig) (drkey.Lvl1DB, error) { - log.Info("Connecting DRKeyDB", " ", BackendSqlite, "connection", c.Connection) - db, err := drkeydbsqlite.NewLvl1Backend(c.Connection) + log.Info("Connecting DRKeyLvl1DB", " ", BackendSqlite, "connection", c.Connection) + db, err := sqlite.NewLvl1Backend(c.Connection) if err != nil { return nil, err } @@ -258,7 +276,7 @@ func NewDRKeyLvl1Storage(c DBConfig) (drkey.Lvl1DB, error) { func NewDRKeyLvl2Storage(c DBConfig) (drkey.Lvl2DB, error) { log.Info("Connecting DRKeyDB", " ", BackendSqlite, "connection", c.Connection) - db, err := drkeydbsqlite.NewLvl2Backend(c.Connection) + db, err := sqlite.NewLvl2Backend(c.Connection) if err != nil { return nil, err } diff --git a/go/pkg/trust/BUILD.bazel b/go/pkg/trust/BUILD.bazel index 798a8fc270..80d35b6bc0 100644 --- a/go/pkg/trust/BUILD.bazel +++ b/go/pkg/trust/BUILD.bazel @@ -16,8 +16,8 @@ go_library( "signer_gen.go", "store.go", "tls_handshake.go", - "transport_credentials.go", "verifier.go", + "x509KeyPairProvider.go", ], importpath = "github.com/scionproto/scion/go/pkg/trust", visibility = ["//visibility:public"], @@ -41,7 +41,6 @@ go_library( "@com_github_opentracing_opentracing_go//:go_default_library", "@com_github_opentracing_opentracing_go//ext:go_default_library", "@com_github_patrickmn_go_cache//:go_default_library", - "@org_golang_google_grpc//credentials:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -62,6 +61,7 @@ go_test( "tls_handshake_test.go", "verifier_bench_test.go", "verifier_test.go", + "x509KeyPairProvider_test.go", ], data = glob(["testdata/**"]), embed = [":go_default_library"], diff --git a/go/pkg/trust/mock_trust/mock.go b/go/pkg/trust/mock_trust/mock.go index 8fd01ce6b4..0e30b5cc0f 100644 --- a/go/pkg/trust/mock_trust/mock.go +++ b/go/pkg/trust/mock_trust/mock.go @@ -426,16 +426,16 @@ func (m *MockX509KeyPairLoader) EXPECT() *MockX509KeyPairLoaderMockRecorder { } // LoadX509KeyPair mocks base method. -func (m *MockX509KeyPairLoader) LoadX509KeyPair() (*tls.Certificate, error) { +func (m *MockX509KeyPairLoader) LoadX509KeyPair(arg0 context.Context, arg1 x509.ExtKeyUsage) (*tls.Certificate, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LoadX509KeyPair") + ret := m.ctrl.Call(m, "LoadX509KeyPair", arg0, arg1) ret0, _ := ret[0].(*tls.Certificate) ret1, _ := ret[1].(error) return ret0, ret1 } // LoadX509KeyPair indicates an expected call of LoadX509KeyPair. -func (mr *MockX509KeyPairLoaderMockRecorder) LoadX509KeyPair() *gomock.Call { +func (mr *MockX509KeyPairLoaderMockRecorder) LoadX509KeyPair(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadX509KeyPair", reflect.TypeOf((*MockX509KeyPairLoader)(nil).LoadX509KeyPair)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadX509KeyPair", reflect.TypeOf((*MockX509KeyPairLoader)(nil).LoadX509KeyPair), arg0, arg1) } diff --git a/go/pkg/trust/tls_handshake.go b/go/pkg/trust/tls_handshake.go index 6637aa09fa..fb05f0d4ad 100644 --- a/go/pkg/trust/tls_handshake.go +++ b/go/pkg/trust/tls_handshake.go @@ -18,8 +18,10 @@ import ( "context" "crypto/tls" "crypto/x509" + "strings" "time" + "github.com/scionproto/scion/go/lib/addr" "github.com/scionproto/scion/go/lib/scrypto/cppki" "github.com/scionproto/scion/go/lib/serrors" ) @@ -28,12 +30,12 @@ const defaultTimeout = 5 * time.Second // X509KeyPairLoader provides a certificate to be presented during TLS handshake. type X509KeyPairLoader interface { - LoadX509KeyPair() (*tls.Certificate, error) + LoadX509KeyPair(ctx context.Context, extKeyUsage x509.ExtKeyUsage) (*tls.Certificate, error) } // TLSCryptoManager implements callbacks which will be called during TLS handshake. type TLSCryptoManager struct { - Loader X509KeyPairLoader + loader X509KeyPairLoader DB DB Timeout time.Duration } @@ -42,14 +44,14 @@ type TLSCryptoManager struct { func NewTLSCryptoManager(loader X509KeyPairLoader, db DB) *TLSCryptoManager { return &TLSCryptoManager{ DB: db, - Loader: loader, + loader: loader, Timeout: defaultTimeout, } } // GetCertificate retrieves a certificate to be presented during TLS handshake. -func (m *TLSCryptoManager) GetCertificate(_ *tls.ClientHelloInfo) (*tls.Certificate, error) { - c, err := m.Loader.LoadX509KeyPair() +func (m *TLSCryptoManager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + c, err := m.loader.LoadX509KeyPair(hello.Context(), x509.ExtKeyUsageServerAuth) if err != nil { return nil, serrors.WrapStr("loading server key pair", err) } @@ -57,19 +59,46 @@ func (m *TLSCryptoManager) GetCertificate(_ *tls.ClientHelloInfo) (*tls.Certific } // GetClientCertificate retrieves a client certificate to be presented during TLS handshake. -func (m *TLSCryptoManager) GetClientCertificate(_ *tls.CertificateRequestInfo) (*tls.Certificate, +func (m *TLSCryptoManager) GetClientCertificate(reqInfo *tls.CertificateRequestInfo) (*tls.Certificate, error) { - c, err := m.Loader.LoadX509KeyPair() + c, err := m.loader.LoadX509KeyPair(reqInfo.Context(), x509.ExtKeyUsageClientAuth) if err != nil { return nil, serrors.WrapStr("loading client key pair", err) } return c, nil } +func (m *TLSCryptoManager) VerifyServerCertificate(rawCerts [][]byte, + _ [][]*x509.Certificate) error { + return m.verifyPeerCertificate(rawCerts, x509.ExtKeyUsageServerAuth) +} + +func (m *TLSCryptoManager) VerifyClientCertificate(rawCerts [][]byte, + _ [][]*x509.Certificate) error { + return m.verifyPeerCertificate(rawCerts, x509.ExtKeyUsageClientAuth) +} + +func (m *TLSCryptoManager) VerifyConnection(cs tls.ConnectionState) error { + serverNameIA := strings.Split(cs.ServerName, ",")[0] + serverIA, err := addr.ParseIA(serverNameIA) + if err != nil { + return serrors.WrapStr("extracting IA from server name", err) + } + certIA, err := cppki.ExtractIA(cs.PeerCertificates[0].Subject) + if err != nil { + return serrors.WrapStr("extracting IA from peer cert", err) + } + if !serverIA.Equal(certIA) { + return serrors.New("extracted IA from cert and server IA do not match", + "peer IA", certIA, "server IA", serverIA) + } + return nil +} + // VerifyPeerCertificate verifies the certificate presented by the peer during TLS handshake, // based on the TRC. -func (m *TLSCryptoManager) VerifyPeerCertificate(rawCerts [][]byte, - _ [][]*x509.Certificate) error { +func (m *TLSCryptoManager) verifyPeerCertificate(rawCerts [][]byte, + extKeyUsage x509.ExtKeyUsage) error { chain := make([]*x509.Certificate, len(rawCerts)) for i, asn1Data := range rawCerts { cert, err := x509.ParseCertificate(asn1Data) @@ -78,6 +107,9 @@ func (m *TLSCryptoManager) VerifyPeerCertificate(rawCerts [][]byte, } chain[i] = cert } + if err := verifyExtendedKeyUsage(chain[0], extKeyUsage); err != nil { + return err + } ia, err := cppki.ExtractIA(chain[0].Subject) if err != nil { return serrors.WrapStr("extracting ISD-AS from peer certificate", err) @@ -107,17 +139,13 @@ func verifyChain(chain []*x509.Certificate, trcs []cppki.SignedTRC) error { return errs.ToError() } -// FileLoader loads key pair from file -type FileLoader struct { - CertFile string - KeyFile string -} - -// LoadX509KeyPair returns the TLS certificate to be provided during a TLS handshake. -func (l FileLoader) LoadX509KeyPair() (*tls.Certificate, error) { - cert, err := tls.LoadX509KeyPair(l.CertFile, l.KeyFile) - if err != nil { - return nil, serrors.WrapStr("loading certificates for DRKey gRPCs", err) +// verifyExtendedKeyUsage return an error if the certifcate extended key usages do not +// include any requested extended key usage. +func verifyExtendedKeyUsage(cert *x509.Certificate, expectedKeyUsage x509.ExtKeyUsage) error { + for _, certExtKeyUsage := range cert.ExtKeyUsage { + if expectedKeyUsage == certExtKeyUsage { + return nil + } } - return &cert, nil + return serrors.New("Invalid certificate key usages") } diff --git a/go/pkg/trust/tls_handshake_test.go b/go/pkg/trust/tls_handshake_test.go index e3aa697c7c..acb9e20868 100644 --- a/go/pkg/trust/tls_handshake_test.go +++ b/go/pkg/trust/tls_handshake_test.go @@ -30,7 +30,7 @@ import ( "github.com/scionproto/scion/go/pkg/trust/mock_trust" ) -func TestTLSCryptoManagerVerifyPeerCertificate(t *testing.T) { +func TestTLSCryptoManagerVerifyServerCertificate(t *testing.T) { trc := xtest.LoadTRC(t, "testdata/common/trcs/ISD1-B1-S1.trc") crt111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem" @@ -59,7 +59,42 @@ func TestTLSCryptoManagerVerifyPeerCertificate(t *testing.T) { Timeout: 5 * time.Second, } rawChain := loadRawChain(t, crt111File) - err := mgr.VerifyPeerCertificate(rawChain, nil) + err := mgr.VerifyServerCertificate(rawChain, nil) + tc.assertErr(t, err) + }) + } +} + +func TestTLSCryptoManagerVerifyClientCertificate(t *testing.T) { + trc := xtest.LoadTRC(t, "testdata/common/trcs/ISD1-B1-S1.trc") + crt111File := "testdata/common/ISD1/ASff00_0_111/crypto/as/ISD1-ASff00_0_111.pem" + + testCases := map[string]struct { + db func(ctrl *gomock.Controller) trust.DB + assertErr assert.ErrorAssertionFunc + }{ + "valid": { + db: func(ctrl *gomock.Controller) trust.DB { + db := mock_trust.NewMockDB(ctrl) + db.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).Return(trc, nil) + return db + }, + assertErr: assert.NoError, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + db := tc.db(ctrl) + mgr := trust.TLSCryptoManager{ + DB: db, + Timeout: 5 * time.Second, + } + rawChain := loadRawChain(t, crt111File) + err := mgr.VerifyClientCertificate(rawChain, nil) tc.assertErr(t, err) }) } @@ -80,7 +115,7 @@ func TestHandshake(t *testing.T) { db := mock_trust.NewMockDB(ctrl) db.EXPECT().SignedTRC(gomock.Any(), gomock.Any()).MaxTimes(2).Return(trc, nil) loader := mock_trust.NewMockX509KeyPairLoader(ctrl) - loader.EXPECT().LoadX509KeyPair().MaxTimes(2).Return(&tlsCert, nil) + loader.EXPECT().LoadX509KeyPair(gomock.Any(), gomock.Any()).MaxTimes(2).Return(&tlsCert, nil) mgr := trust.NewTLSCryptoManager(loader, db) clientConn, serverConn := net.Pipe() @@ -90,12 +125,12 @@ func TestHandshake(t *testing.T) { client := tls.Client(clientConn, &tls.Config{ InsecureSkipVerify: true, GetClientCertificate: mgr.GetClientCertificate, - VerifyPeerCertificate: mgr.VerifyPeerCertificate, + VerifyPeerCertificate: mgr.VerifyServerCertificate, }) server := tls.Server(serverConn, &tls.Config{ InsecureSkipVerify: true, GetCertificate: mgr.GetCertificate, - VerifyPeerCertificate: mgr.VerifyPeerCertificate, + VerifyPeerCertificate: mgr.VerifyClientCertificate, ClientAuth: tls.RequireAnyClientCert, }) diff --git a/go/pkg/trust/transport_credentials.go b/go/pkg/trust/transport_credentials.go deleted file mode 100644 index c3dae980b6..0000000000 --- a/go/pkg/trust/transport_credentials.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2020 ETH Zurich -// -// 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 trust - -import ( - "context" - "crypto/tls" - "net" - "strings" - - "google.golang.org/grpc/credentials" - - "github.com/scionproto/scion/go/lib/addr" - "github.com/scionproto/scion/go/lib/scrypto/cppki" - "github.com/scionproto/scion/go/lib/serrors" -) - -// XXX(JordiSubira): ClientCredentials enables hooking a procedure to validate -// the TLS state during the client handshake. Note that the current implementation -// extends the grpc/credentials callback for TLS credentials by carrying out the -// validation after the handshake has been completed (this last using the provided -// TLS config). -// Go1.15 introduces the VerifyConnection callback within TLS Config which would -// enable hooking the procedure to validate the TLS state within the TLS client -// handshake. Therefore, if Go1.15 (or greater) is used ClientCredentials should -// be deprecated using the aforementioned alternative. - -// ClientCredentials implements credentials.TransportCredentials extending -// the ClientHandshake callback -type ClientCredentials struct { - credentials.TransportCredentials -} - -// NewClientCredentials returns a new instance which embeds tlsCred, which in turn -// implements credentials.TransportCredentials interface -func NewClientCredentials(conf *tls.Config) credentials.TransportCredentials { - return &ClientCredentials{ - credentials.NewTLS(conf), - } -} - -// ClientHandshake extends the embedded TransportCredentials callback by verifying the peer's name -// and the information provided in the certificate. Upon error the connection is closed and a -// non-temporary error is returned. -func (c *ClientCredentials) ClientHandshake(ctx context.Context, authority string, - rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) { - conn, authInfo, err := c.TransportCredentials.ClientHandshake(ctx, authority, rawConn) - if err != nil { - return nil, nil, err - } - - tlsInfo, ok := authInfo.(credentials.TLSInfo) - if !ok { - conn.Close() - return nil, nil, &nonTempWrapper{ - serrors.New("authInfo should be type tlsInfo and is", - "authInfoType", authInfo.AuthType()), - } - } - // XXX (JordiSubira): In Go1.13 tls.ConnectionState.ServerName is only set - // on the server side. Thus, we pass authority as the serverName. - if err = verifyConnection(tlsInfo.State, authority); err != nil { - conn.Close() - return nil, nil, &nonTempWrapper{ - serrors.WrapStr("verifying connection in client handshake", err), - } - } - return conn, tlsInfo, nil -} - -type nonTempWrapper struct { - error -} - -func (e *nonTempWrapper) Temporary() bool { - return false -} - -func verifyConnection(cs tls.ConnectionState, serverName string) error { - serverNameIA := strings.Split(serverName, ",")[0] - serverIA, err := addr.ParseIA(serverNameIA) - if err != nil { - return serrors.WrapStr("extracting IA from server name", err) - } - certIA, err := cppki.ExtractIA(cs.PeerCertificates[0].Subject) - if err != nil { - return serrors.WrapStr("extracting IA from peer cert", err) - } - if !serverIA.Equal(certIA) { - return serrors.New("extracted IA from cert and server IA do not match", - "peer IA", certIA, "server IA", serverIA) - } - return nil -} - -// GetTansportCredentials returns a configuration which implements TransportCredentials -// interface, based on the provided TLSCryptoManager -func GetTansportCredentials(mgr *TLSCryptoManager) credentials.TransportCredentials { - config := &tls.Config{ - InsecureSkipVerify: true, - GetClientCertificate: mgr.GetClientCertificate, - VerifyPeerCertificate: mgr.VerifyPeerCertificate, - } - return NewClientCredentials(config) -} diff --git a/go/pkg/trust/x509KeyPairProvider.go b/go/pkg/trust/x509KeyPairProvider.go new file mode 100644 index 0000000000..fd6d10f13a --- /dev/null +++ b/go/pkg/trust/x509KeyPairProvider.go @@ -0,0 +1,141 @@ +// Copyright 2021 ETH Zurich +// +// 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 trust + +import ( + "context" + "crypto" + "crypto/tls" + "crypto/x509" + "time" + + "github.com/scionproto/scion/go/lib/addr" + "github.com/scionproto/scion/go/lib/log" + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/serrors" +) + +type X509KeyPairProvider struct { + IA addr.IA + DB DB + Loader KeyRing +} + +var _ X509KeyPairLoader = (*X509KeyPairProvider)(nil) + +func (p X509KeyPairProvider) LoadX509KeyPair(ctx context.Context, extKeyUsage x509.ExtKeyUsage) ( + *tls.Certificate, error) { + keys, err := p.Loader.PrivateKeys(ctx) + if err != nil { + log.Error("Error getting keys", "err", err) + return nil, err + } + if len(keys) == 0 { + log.Error("No available keys") + return nil, serrors.New("no private key found") + } + + trcs, _, err := activeTRCs(ctx, p.DB, p.IA.ISD()) + if err != nil { + return nil, serrors.WrapStr("loading TRCs", err) + } + + var bestChain []*x509.Certificate + var bestKey crypto.Signer + var bestExpiry time.Time + for _, key := range keys { + cert, expiry, err := p.bestKeyPair(ctx, trcs, extKeyUsage, key) + if err != nil { + log.Error("Error getting best key pair", "err", err) + return nil, err + } + if cert == nil { + continue + } + if bestChain != nil && bestExpiry.Before(expiry) { + continue + } + bestChain = cert + bestKey = key + bestExpiry = expiry + } + if bestChain == nil { + log.Error("No certificate chain found for DRKey") + return nil, serrors.New("no certificate found for DRKey gRPC") + } + certificate := make([][]byte, len(bestChain)) + for i := range bestChain { + certificate[i] = bestChain[i].Raw + } + return &tls.Certificate{ + Certificate: certificate, + PrivateKey: bestKey, + Leaf: bestChain[0], + }, nil +} + +func (p X509KeyPairProvider) bestKeyPair(ctx context.Context, trcs []cppki.SignedTRC, + extKeyUsage x509.ExtKeyUsage, signer crypto.Signer) ([]*x509.Certificate, time.Time, error) { + skid, err := cppki.SubjectKeyID(signer.Public()) + if err != nil { + return nil, time.Time{}, nil + } + chains, err := p.DB.Chains(ctx, ChainQuery{ + IA: p.IA, + SubjectKeyID: skid, + Date: time.Now(), + }) + if err != nil { + return nil, time.Time{}, err + } + chain := bestEKUChain(&trcs[0].TRC, chains, extKeyUsage) + if chain == nil && len(trcs) == 1 { + return nil, time.Time{}, nil + } + var inGrace bool + // Attempt to find a chain that is verifiable only in grace period. If we + // have not found a chain yet. + if chain == nil && len(trcs) == 2 { + chain = bestEKUChain(&trcs[1].TRC, chains, extKeyUsage) + if chain == nil { + return nil, time.Time{}, nil + } + inGrace = true + } + expiry := min(chain[0].NotAfter, trcs[0].TRC.Validity.NotAfter) + if inGrace { + expiry = min(chain[0].NotAfter, trcs[0].TRC.GracePeriodEnd()) + } + return chain, expiry, nil +} + +func bestEKUChain(trc *cppki.TRC, chains [][]*x509.Certificate, + extKeyUsage x509.ExtKeyUsage) []*x509.Certificate { + opts := cppki.VerifyOptions{TRC: []*cppki.TRC{trc}} + var best []*x509.Certificate + for _, chain := range chains { + if err := cppki.VerifyChain(chain, opts); err != nil { + continue + } + if err := verifyExtendedKeyUsage(chain[0], extKeyUsage); err != nil { + continue + } + if len(best) > 0 && chain[0].NotAfter.Before(best[0].NotAfter) { + continue + } + best = chain + } + return best +} diff --git a/go/pkg/trust/x509KeyPairProvider_test.go b/go/pkg/trust/x509KeyPairProvider_test.go new file mode 100644 index 0000000000..04716c02d4 --- /dev/null +++ b/go/pkg/trust/x509KeyPairProvider_test.go @@ -0,0 +1,456 @@ +// Copyright 2021 ETH Zurich +// +// 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 trust_test + +import ( + "context" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "encoding/pem" + "os" + "path/filepath" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/scionproto/scion/go/lib/scrypto/cppki" + "github.com/scionproto/scion/go/lib/serrors" + "github.com/scionproto/scion/go/lib/xtest" + "github.com/scionproto/scion/go/pkg/trust" + "github.com/scionproto/scion/go/pkg/trust/mock_trust" +) + +func TestLoadX509KeyPair(t *testing.T) { + if *updateNonDeterministic { + t.Skip("test crypto is being updated") + } + + getChain := func(t *testing.T) []*x509.Certificate { + return xtest.LoadChain(t, + filepath.Join(goldenDir, "ISD1/ASff00_0_110/crypto/as/ISD1-ASff00_0_110.pem")) + } + + trc := xtest.LoadTRC(t, filepath.Join(goldenDir, "ISD1/trcs/ISD1-B1-S1.trc")) + key := loadSigner(t, filepath.Join(goldenDir, "ISD1/ASff00_0_110/crypto/as/cp-as.key")) + + chain := getChain(t) + longer := getChain(t) + longer[0].NotAfter = longer[0].NotAfter.Add(time.Hour) + longer[0].SubjectKeyId = []byte("longer") + + shorter := getChain(t) + shorter[0].NotAfter = shorter[0].NotAfter.Add(-time.Hour) + shorter[0].SubjectKeyId = []byte("shorter") + + testCases := map[string]struct { + keyLoader func(mctrcl *gomock.Controller) trust.KeyRing + db func(mctrcl *gomock.Controller) trust.DB + extKeyUsage x509.ExtKeyUsage + assertFunc assert.ErrorAssertionFunc + expectedCert func() *tls.Certificate + }{ + "valid": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + cert := chain[0] + db := mock_trust.NewMockDB(mctrl) + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + trc, nil, + ) + db.EXPECT().Chains(gomock.Any(), matcher).Return( + [][]*x509.Certificate{chain}, nil, + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.NoError, + expectedCert: func() *tls.Certificate { + certificate := make([][]byte, len(chain)) + for i := range chain { + certificate[i] = chain[i].Raw + } + return &tls.Certificate{ + Certificate: certificate, + PrivateKey: key, + Leaf: chain[0], + } + }, + }, + "newest": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + cert := chain[0] + db := mock_trust.NewMockDB(mctrl) + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + trc, nil, + ) + db.EXPECT().Chains(gomock.Any(), matcher).Return( + [][]*x509.Certificate{chain, longer, shorter}, nil, + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.NoError, + expectedCert: func() *tls.Certificate { + certificate := make([][]byte, len(longer)) + for i := range longer { + certificate[i] = longer[i].Raw + } + return &tls.Certificate{ + Certificate: certificate, + PrivateKey: key, + Leaf: longer[0], + } + }, + }, + "select best from grace": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + cert := chain[0] + db := mock_trust.NewMockDB(mctrl) + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + + trc2 := xtest.LoadTRC(t, filepath.Join(goldenDir, "ISD1/trcs/ISD1-B1-S1.trc")) + trc2.TRC.ID.Serial = 2 + trc2.TRC.Validity.NotBefore = time.Now() + trc2.TRC.GracePeriod = 5 * time.Minute + + roots, err := trc2.TRC.RootCerts() + require.NoError(t, err) + key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + for _, root := range roots { + root.PublicKey = key.Public() + } + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + trc2, nil, + ) + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1, Serial: 1, Base: 1}).Return( + trc, nil, + ) + db.EXPECT().Chains(gomock.Any(), matcher).Return( + [][]*x509.Certificate{chain, longer, shorter}, nil, + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.NoError, + expectedCert: func() *tls.Certificate { + certificate := make([][]byte, len(chain)) + for i := range chain { + certificate[i] = longer[i].Raw + } + return &tls.Certificate{ + Certificate: certificate, + PrivateKey: key, + Leaf: longer[0], + } + }, + }, + "no keys": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + return mock_trust.NewMockDB(mctrl) + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + "rsa key": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + + priv, err := rsa.GenerateKey(rand.Reader, 512) + require.NoError(t, err) + + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{priv}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + db := mock_trust.NewMockDB(mctrl) + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + trc, nil, + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + "no chain found": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + db := mock_trust.NewMockDB(mctrl) + cert := chain[0] + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + db.EXPECT().SignedTRC(ctxMatcher{}, + cppki.TRCID{ISD: 1}).Return(trc, nil) + db.EXPECT().Chains(gomock.Any(), matcher).Return(nil, nil) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + "db.SignedTRC error": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + db := mock_trust.NewMockDB(mctrl) + db.EXPECT().SignedTRC(ctxMatcher{}, + cppki.TRCID{ISD: 1}).Return( + cppki.SignedTRC{}, serrors.New("fail")) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + "db.SignedTRC not found": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + db := mock_trust.NewMockDB(mctrl) + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + cppki.SignedTRC{}, nil) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + "db.Chain error": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + db := mock_trust.NewMockDB(mctrl) + cert := chain[0] + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + db.EXPECT().SignedTRC(ctxMatcher{}, + cppki.TRCID{ISD: 1}).Return(trc, nil) + db.EXPECT().Chains(gomock.Any(), matcher).Return( + nil, serrors.New("fail"), + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + "correct EKU": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + invalidExtChain := getChain(t) + invalidExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ + x509.ExtKeyUsageClientAuth, + x509.ExtKeyUsageTimeStamping, + } + validExtChain := getChain(t) + validExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ + x509.ExtKeyUsageServerAuth, + x509.ExtKeyUsageTimeStamping, + } + cert := validExtChain[0] + db := mock_trust.NewMockDB(mctrl) + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + trc, nil, + ) + db.EXPECT().Chains(gomock.Any(), matcher).Return( + [][]*x509.Certificate{invalidExtChain, validExtChain}, nil, + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.NoError, + expectedCert: func() *tls.Certificate { + validExtChain := getChain(t) + validExtChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ + x509.ExtKeyUsageServerAuth, + x509.ExtKeyUsageTimeStamping, + } + certificate := make([][]byte, len(validExtChain)) + for i := range validExtChain { + certificate[i] = validExtChain[i].Raw + } + return &tls.Certificate{ + Certificate: certificate, + PrivateKey: key, + Leaf: validExtChain[0], + } + }, + }, + "wrong EKU": { + keyLoader: func(mctrl *gomock.Controller) trust.KeyRing { + loader := mock_trust.NewMockKeyRing(mctrl) + loader.EXPECT().PrivateKeys(gomock.Any()).Return( + []crypto.Signer{key}, nil, + ) + return loader + }, + db: func(mctrl *gomock.Controller) trust.DB { + extChain := getChain(t) + extChain[0].ExtKeyUsage = []x509.ExtKeyUsage{ + x509.ExtKeyUsageClientAuth, + x509.ExtKeyUsageTimeStamping, + } + cert := extChain[0] + db := mock_trust.NewMockDB(mctrl) + matcher := chainQueryMatcher{ + ia: xtest.MustParseIA("1-ff00:0:110"), + skid: cert.SubjectKeyId, + } + db.EXPECT().SignedTRC(ctxMatcher{}, cppki.TRCID{ISD: 1}).Return( + trc, nil, + ) + db.EXPECT().Chains(gomock.Any(), matcher).Return( + [][]*x509.Certificate{extChain}, nil, + ) + return db + }, + extKeyUsage: x509.ExtKeyUsageServerAuth, + assertFunc: assert.Error, + expectedCert: func() *tls.Certificate { + return nil + }, + }, + } + for name, tc := range testCases { + name, tc := name, tc + t.Run(name, func(t *testing.T) { + //t.Parallel() + mctrl := gomock.NewController(t) + defer mctrl.Finish() + + provider := trust.X509KeyPairProvider{ + IA: xtest.MustParseIA("1-ff00:0:110"), + DB: tc.db(mctrl), + Loader: tc.keyLoader(mctrl), + } + tlsCert, err := provider.LoadX509KeyPair(context.Background(), tc.extKeyUsage) + tc.assertFunc(t, err) + if err == nil { + assert.Equal(t, tc.expectedCert().Leaf.SubjectKeyId, tlsCert.Leaf.SubjectKeyId) + } + + }) + } +} + +func loadSigner(t *testing.T, file string) crypto.Signer { + raw, err := os.ReadFile(file) + require.NoError(t, err) + block, _ := pem.Decode(raw) + if block == nil || block.Type != "PRIVATE KEY" { + panic("no valid private key block") + } + key, err := x509.ParsePKCS8PrivateKey(block.Bytes) + require.NoError(t, err) + return key.(crypto.Signer) +} diff --git a/licenses/data/com_github_hashicorp_golang_lru/LICENSE b/licenses/data/com_github_hashicorp_golang_lru/LICENSE new file mode 100644 index 0000000000..be2cc4dfb6 --- /dev/null +++ b/licenses/data/com_github_hashicorp_golang_lru/LICENSE @@ -0,0 +1,362 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. diff --git a/proto/control_plane/v1/drkey.proto b/proto/control_plane/v1/drkey.proto index 4434ad044b..6861348234 100644 --- a/proto/control_plane/v1/drkey.proto +++ b/proto/control_plane/v1/drkey.proto @@ -20,22 +20,20 @@ package proto.control_plane.v1; import "proto/drkey/mgmt/v1/mgmt.proto"; -service DRKeyLvl1Service{ +service DRKeyInterService{ // Return the Lvl1Key that matches the request - rpc DRKeyLvl1(proto.drkey.mgmt.v1.DRKeyLvl1Request) returns (proto.drkey.mgmt.v1.DRKeyLvl1Response) {} + rpc Lvl1(proto.drkey.mgmt.v1.Lvl1Request) returns (proto.drkey.mgmt.v1.Lvl1Response) {} } -service DRKeyLvl2Service{ - // Return the Lvl2Key that matches the request - rpc DRKeyLvl2(DRKeyLvl2Request) returns (DRKeyLvl2Response) {} -} - -message DRKeyLvl2Request{ - // BaseReq contains the basic information for the Lvl2 request - proto.drkey.mgmt.v1.DRKeyLvl2Request base_req = 1; -} - -message DRKeyLvl2Response{ - // BaseRep contains the basic information for the Lvl2 response - proto.drkey.mgmt.v1.DRKeyLvl2Response base_rep = 1; +service DRKeyIntraService{ + // Return the ASAS that matches the request + rpc IntraLvl1(proto.drkey.mgmt.v1.IntraLvl1Request) returns (proto.drkey.mgmt.v1.IntraLvl1Response) {} + // Return the AS-Host that matches the request + rpc ASHost(proto.drkey.mgmt.v1.ASHostRequest) returns (proto.drkey.mgmt.v1.ASHostResponse) {} + // Return the Host-AS that matches the request + rpc HostAS(proto.drkey.mgmt.v1.HostASRequest) returns (proto.drkey.mgmt.v1.HostASResponse) {} + // Return the Host-Host that matches the request + rpc HostHost(proto.drkey.mgmt.v1.HostHostRequest) returns (proto.drkey.mgmt.v1.HostHostResponse) {} + // Return the SV that matches the request + rpc SV(proto.drkey.mgmt.v1.SVRequest) returns (proto.drkey.mgmt.v1.SVResponse) {} } diff --git a/proto/daemon/v1/daemon.proto b/proto/daemon/v1/daemon.proto index 04d3a6fa47..a11eb9ea09 100644 --- a/proto/daemon/v1/daemon.proto +++ b/proto/daemon/v1/daemon.proto @@ -36,8 +36,6 @@ service DaemonService { rpc Services(ServicesRequest) returns (ServicesResponse) {} // Inform the SCION Daemon of a revocation. rpc NotifyInterfaceDown(NotifyInterfaceDownRequest) returns (NotifyInterfaceDownResponse) {} - // Return the Lvl2Key that matches the request. - rpc DRKeyLvl2(DRKeyLvl2Request) returns (DRKeyLvl2Response) {} // Obtain a list of reservation information from the AS towards another one. rpc ColibriListRsvs(ColibriListRsvsRequest) returns (ColibriListRsvsResponse) {} // Setup an E2E reservation. @@ -46,6 +44,12 @@ service DaemonService { rpc ColibriCleanupRsv(ColibriCleanupRsvRequest) returns (ColibriCleanupRsvResponse) {} // Adds a new automatically expiring entry to the admission list for the host. rpc ColibriAddAdmissionEntry(ColibriAddAdmissionEntryRequest) returns (ColibriAddAdmissionEntryResponse) {} + // ASHost returns a key that matches the request. + rpc ASHost (proto.drkey.mgmt.v1.ASHostRequest) returns (proto.drkey.mgmt.v1.ASHostResponse) {} + // HostAS returns a key that matches the request. + rpc HostAS (proto.drkey.mgmt.v1.HostASRequest) returns (proto.drkey.mgmt.v1.HostASResponse) {} + // HostHost returns a key that matches the request. + rpc HostHost (proto.drkey.mgmt.v1.HostHostRequest) returns (proto.drkey.mgmt.v1.HostHostResponse) {} } message PathsRequest { @@ -195,14 +199,14 @@ message NotifyInterfaceDownRequest { message NotifyInterfaceDownResponse {}; -message DRKeyLvl2Request{ - // BaseReq contains the basic information for the Lvl2 request - proto.drkey.mgmt.v1.DRKeyLvl2Request base_req = 1; +message SVRequest{ + // BaseReq contains the basic information for the SV request + proto.drkey.mgmt.v1.SVRequest base_req = 1; } -message DRKeyLvl2Response { - // BaseRep contains the basic information for the Lvl2 response - proto.drkey.mgmt.v1.DRKeyLvl2Response base_rep = 1; +message SVResponse{ + // BaseReq contains the basic information for the SV request + proto.drkey.mgmt.v1.SVResponse base_rep = 1; } message ColibriListRsvsRequest { diff --git a/proto/drkey/mgmt/v1/mgmt.proto b/proto/drkey/mgmt/v1/mgmt.proto index cd8efbc015..795563ba7c 100644 --- a/proto/drkey/mgmt/v1/mgmt.proto +++ b/proto/drkey/mgmt/v1/mgmt.proto @@ -20,63 +20,140 @@ package proto.drkey.mgmt.v1; import "google/protobuf/timestamp.proto"; -// DRKeyLvl1Request leaves out the 'dstIA' field which can be extracted from +message SVRequest{ + // Point in time when the requested key is valid. + google.protobuf.Timestamp val_time = 1; + // Protocol value. + Protocol protocol_id = 2; +} + +message SVResponse{ + // Begin of the validity period. + google.protobuf.Timestamp epoch_begin = 1; + // End of the validity period. + google.protobuf.Timestamp epoch_end = 2; + // SV key. + bytes key = 3; +} + +// Lvl1Request leaves out the 'dstIA' field which can be extracted from // the transport itself (ideally from authenticated information). -message DRKeyLvl1Request{ - // Point in time where requested DRKey is valid. Used to identify the epoch +message Lvl1Request{ + // Point in time where requested key is valid. google.protobuf.Timestamp val_time = 1; - // Point in time when the request was created - google.protobuf.Timestamp timestamp = 2; + // Protocol value. + Protocol protocol_id = 2; } -// DRKeyLvl1Response leaves out the 'dstIA' and 'srcIA' fields which can be +// Lvl1Response leaves out the 'dstIA' and 'srcIA' fields which can be // extracted from the transport itself (ideally from authenticated information). -message DRKeyLvl1Response{ - // Begin of validity period of DRKey +message Lvl1Response{ + // Begin of the validity period google.protobuf.Timestamp epoch_begin = 1; - // End of validity period of DRKey + // End of the validity period google.protobuf.Timestamp epoch_end = 2; - // Lvl1 DRKey - bytes drkey = 3; - // Creation time of this reply - google.protobuf.Timestamp timestamp = 4; + // Lvl1 key + bytes key = 3; } -message DRKeyLvl2Request{ - message DRKeyHost{ - // AddrType - uint32 type = 1; - // Host address - bytes host = 2; - } - // Protocol identifier - string protocol = 1; - // Requested DRKeyProtoKeyType - uint32 req_type = 2; - // Point in time where requested DRKey is valid. Used to identify the epoch - google.protobuf.Timestamp val_time = 3; - // Src ISD-AS of the requested DRKey - uint64 src_ia = 4; - // Dst ISD-AS of the requested DRKey - uint64 dst_ia = 5; - // Src Host of the request DRKey (optional) - DRKeyHost src_host = 6; - // Dst Host of the request DRKey (optional) - DRKeyHost dst_host = 7; - // Additional information (optional) - bytes misc = 8; +message IntraLvl1Request{ + // Point in time where requested key is valid. + google.protobuf.Timestamp val_time = 1; + // Protocol value. + Protocol protocol_id = 2; + // Src ISD-AS of the requested DRKey. + uint64 src_ia = 3; + // Dst ISD-AS of the requested DRKey. + uint64 dst_ia = 4; } -message DRKeyLvl2Response{ - // Timestamp - google.protobuf.Timestamp timestamp = 1; - // Derived DRKey - bytes drkey = 2; - // Begin of validity period of DRKey - google.protobuf.Timestamp epoch_begin = 3; - // End of validity period of DRKey - google.protobuf.Timestamp epoch_end = 4; - // Additional information (optional) - bytes misc = 5; +message IntraLvl1Response{ + // Begin of validity period of DRKey. + google.protobuf.Timestamp epoch_begin = 1; + // End of validity period of DRKey. + google.protobuf.Timestamp epoch_end = 2; + // Lvl1 key. + bytes key = 3; } + +message HostASRequest{ + // Point in time where requested key is valid. + google.protobuf.Timestamp val_time = 1; + // Protocol value. + Protocol protocol_id = 2; + // Src ISD-AS of the requested DRKey. + uint64 src_ia = 3; + // Dst ISD-AS of the requested DRKey. + uint64 dst_ia = 4; + // Src Host of the request DRKey. + string src_host = 5; + } + + message HostASResponse{ + // Begin of validity period of DRKey. + google.protobuf.Timestamp epoch_begin = 1; + // End of validity period of DRKey. + google.protobuf.Timestamp epoch_end = 2; + // Lvl2 key. + bytes key = 3; + } + + message ASHostRequest{ + // Point in time where requested key is valid. + google.protobuf.Timestamp val_time = 1; + // Protocol value. + Protocol protocol_id = 2; + // Src ISD-AS of the requested DRKey. + uint64 src_ia = 3; + // Dst ISD-AS of the requested DRKey. + uint64 dst_ia = 4; + // Dst Host of the request DRKey. + string dst_host = 5; + } + + message ASHostResponse{ + // Begin of validity period of DRKey. + google.protobuf.Timestamp epoch_begin = 1; + // End of validity period of DRKey. + google.protobuf.Timestamp epoch_end = 2; + // Lvl2 key. + bytes key = 3; + } + + message HostHostRequest{ + // Point in time where requested key is valid. + google.protobuf.Timestamp val_time = 1; + // Protocol value. + Protocol protocol_id = 2; + // Src ISD-AS of the requested DRKey. + uint64 src_ia = 3; + // Dst ISD-AS of the requested DRKey. + uint64 dst_ia = 4; + // Src Host of the request DRKey. + string src_host = 5; + // Dst Host of the request DRKey. + string dst_host = 6; + } + + message HostHostResponse{ + // Begin of validity period of DRKey. + google.protobuf.Timestamp epoch_begin = 1; + // End of validity period of DRKey. + google.protobuf.Timestamp epoch_end = 2; + // Lvl2 key. + bytes key = 3; + } + +enum Protocol{ + // Generic is used to derive keys in the generic derivation scheme + PROTOCOL_GENERIC_UNSPECIFIED = 0; + // SCMP protocol + PROTOCOL_SCMP = 1; + // DNS protocol + PROTOCOL_DNS = 2; + // COLIBRI protocol + PROTOCOL_COLIBRI = 3; + reserved 65536 to max; // only 16-bit values allowed +} + diff --git a/python/topology/common.py b/python/topology/common.py index 332fa6548d..a3efcb5fe4 100644 --- a/python/topology/common.py +++ b/python/topology/common.py @@ -17,7 +17,7 @@ import os import subprocess from urllib.parse import urlsplit -from typing import Mapping, Tuple +from typing import Mapping, Tuple, List # SCION from python.lib.scion_addr import ISD_AS @@ -124,6 +124,16 @@ def sciond_ip(docker, topo_id, networks: Mapping[IPNetwork, return None +def colibri_ip_list(docker, topo_id, + networks: Mapping[IPNetwork, NetworkDescription]) -> List[str]: + list = [] + for net_desc in networks.values(): + for prog, ip_net in net_desc.ip_net.items(): + if '-'.join(prog.split('-')[0:2]) == 'co%s' % topo_id.file_fmt(): + list.append(str(ip_net.ip)) + return list + + def prom_addr_dispatcher(docker, topo_id, networks: Mapping[IPNetwork, NetworkDescription], port, name): diff --git a/python/topology/go.py b/python/topology/go.py index cf4e813ed0..1b1c37efc1 100755 --- a/python/topology/go.py +++ b/python/topology/go.py @@ -27,6 +27,7 @@ from python.topology.common import ( ArgsTopoDicts, DISP_CONFIG_NAME, + colibri_ip_list, docker_host, prom_addr, prom_addr_dispatcher, @@ -108,7 +109,7 @@ def generate_control_service(self): def _build_control_service_conf(self, topo_id, ia, base, name, infra_elem, ca): config_dir = '/share/conf' if self.args.docker else base - sd_ip = sciond_ip(self.args.docker, topo_id, self.args.networks) + co_ip_list = colibri_ip_list(self.args.docker, topo_id, self.args.networks) raw_entry = { 'general': { 'id': name, @@ -126,15 +127,14 @@ def _build_control_service_conf(self, topo_id, ia, base, name, infra_elem, ca): 'connection': os.path.join(self.db_dir, '%s.path.db' % name), }, 'drkey': { - 'cert_file': os.path.join(base, 'crypto', 'as', - f'{topo_id.ISD()}-{topo_id.AS_file()}.pem'), - 'key_file': os.path.join(base, 'crypto', 'as', 'cp-as.key'), - 'drkey_db': { - 'connection': os.path.join(self.db_dir, '%s.drkey.db' % name), + 'lvl1_db': { + 'connection': os.path.join(self.db_dir, '%s.lvl1.db' % name), + }, + 'sv_db': { + 'connection': os.path.join(self.db_dir, '%s.sv.db' % name), }, 'delegation': { - 'colibri': [str(sd_ip)], # local daemon must be able to get the colibri DS - 'piskes': [str(sd_ip)], # local daemon must be able to use piskes + 'colibri': co_ip_list, # ColServ must be able to get the colibri SV }, }, 'tracing': self._tracing_entry(), @@ -274,7 +274,7 @@ def _build_sciond_conf(self, topo_id, ia, base): 'path_db': { 'connection': os.path.join(self.db_dir, '%s.path.db' % name), }, - 'drkey_db': { + 'drkey_lvl2_db': { 'connection': os.path.join(self.db_dir, '%s.drkey.db' % name), }, 'sd': {