Newer
Older
// This package kms implements a simplistic key managment system (kms) for
// Quantum Key Distribution Networks (QKDN) which is a simple emulated KMS. x
// It relies on the emulated quantum link out of the quantumlayer package
package kms
import (
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
pbETSI "code.fbi.h-da.de/danet/quant/ekms/internal/api/gen/proto/go/kmsetsi"
pbIC "code.fbi.h-da.de/danet/quant/ekms/internal/api/gen/proto/go/kmsintercom"
"code.fbi.h-da.de/danet/quant/ekms/internal/kms/event"
pbQS "code.fbi.h-da.de/danet/quipsec/gen/go/quipsec"
"github.com/google/uuid"
)
Previous *kmsPeer
Next *kmsPeer
}
type BitKeyLength string
const (
BitKeyLen128 BitKeyLength = "128"
BitKeyLen256 BitKeyLength = "256"
BitKeyLen512 BitKeyLength = "512"
)
// The general emulated KMS
kmsName string
kmsUUID uuid.UUID
interComAddr string
// TODO create a mapping between ids and address
quantumModules map[string]QuantumModule
quantumModulesMutex sync.RWMutex
kmsPeersMutex sync.Mutex
// TODO(maba): find a better name for this
keysForPathId map[uuid.UUID]string
routingTable map[uuid.UUID]*Route
routingTableMutex sync.RWMutex
KmsPeers map[string]*kmsPeer
pbETSI.UnimplementedKmsETSIServer
pbIC.UnimplementedKmsTalkerServer
supportedKeyLengths map[BitKeyLength]bool
eventBus *event.EventBus
// Will keep information about the quantum elements that this EKMS is talking to
// This actually constitutes a quantum element with only a single link
/*
type QuantumElementInterface interface {
GetQlID() qlElementId
}*/
func NewEKMS(kmsName string, kmsUUID uuid.UUID, logOutput io.Writer, logLevel log.Level, logInJson bool, interComAddr string) (newEKMS *EKMS) {
/*
* Setup logging
*/
//What level
log.SetLevel(logLevel)
// Where to send log out put
log.SetOutput(logOutput)
// and plain-text (standard) or json
if !logInJson {
log.SetFormatter(&log.TextFormatter{})
} else {
log.SetFormatter(&log.JSONFormatter{})
}
// print code function if level is set to Trace
if logLevel == log.TraceLevel {
log.SetReportCaller(true)
} else {
log.SetReportCaller(false)
}
kmsName: kmsName,
kmsUUID: kmsUUID,
interComAddr: interComAddr,
quantumModules: make(map[string]QuantumModule),
routingTable: make(map[uuid.UUID]*Route),
KmsPeers: make(map[string]*kmsPeer),
supportedKeyLengths: make(map[BitKeyLength]bool),
eventBus: event.NewEventBus(),
createdEKMS.supportedKeyLengths[BitKeyLen256] = true
// start the inter communication gRPC server
go createdEKMS.startGRPC(interComAddr)
}
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
func (kms *EKMS) startGRPC(interComAddr string) {
lis, err := net.Listen("tcp", interComAddr)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
healthCheck := health.NewServer()
healthpb.RegisterHealthServer(s, healthCheck)
pbIC.RegisterKmsTalkerServer(s, &kmsTalkerServer{
keyNegotiationMap: make(map[uuid.UUID]*kmsKSElement),
eKMS: kms,
})
pbQS.RegisterKmsQkdmCommunicationServiceServer(s, &quipSecServer{
eKMS: kms,
})
go func() {
// set status to serving
healthCheck.SetServingStatus(pbIC.KmsTalker_ServiceDesc.ServiceName, healthpb.HealthCheckResponse_SERVING)
// TODO: add logic for adjusting health status based on operating status of
// the services
// for{}
}()
log.Infof("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func (kms *EKMS) AddQuantumElement(qm QuantumModule) error {
kms.quantumModulesMutex.Lock()
log.Info(qm.Address())
kms.quantumModules[qm.Address()] = qm
kms.quantumModulesMutex.Unlock()
return nil
func (kms *EKMS) AddPeer(peerKmsId string, kmsPeerSocket string, servingQLE QuantumModule) (*kmsPeer, error) {
if _, there := kms.KmsPeers[kmsPeerSocket]; there {
log.Errorf("Trying to add existing peer %s", kmsPeerSocket)
return nil, fmt.Errorf("Trying to add existing peer %s", kmsPeerSocket)
}
peer, err := NewKmsPeer(peerKmsId, servingQLE, kmsPeerSocket, kms.interComAddr, kms.eventBus)
}
peer.tcpSocketStr = kmsPeerSocket
kms.kmsPeersMutex.Lock()
kms.kmsPeersMutex.Unlock()
func (kms *EKMS) AssignForwardingRoute(pId, pHop, nHop string) error {
pathId, err := uuid.Parse(pId)
if err != nil {
return fmt.Errorf("The given path id %s is no uuid; err = ", pathId, err)
}
var previousHop *kmsPeer
var nextHop *kmsPeer
var ok bool
if pHop != "" {
previousHop, ok = kms.KmsPeers[pHop]
if !ok {
return fmt.Errorf("No peer found for %s", pHop)
}
}
if nHop != "" {
nextHop, ok = kms.KmsPeers[nHop]
if !ok {
return fmt.Errorf("No peer found for %s", nHop)
}
}
kms.routingTableMutex.Lock()
// set the route within routing table
kms.routingTable[pathId] = &Route{
Previous: previousHop,
Next: nextHop,
}
kms.routingTableMutex.Unlock()
err = kms.eventBus.Publish(event.NewRouteEvent())
if err != nil {
log.Error(err)
}
func (kms *EKMS) EventBus() *event.EventBus {
return kms.eventBus
}
// TODO/XXX error handling
func (kms *EKMS) RemovePeer(kmsPeerSocket string) {
log.Errorf("%s: Can not find a peer with socket: %s", kms.kmsName, kmsPeerSocket)
func (kms *EKMS) FindPeerUuid(lookup uuid.UUID) (peer *kmsPeer) {
if kms.KmsPeers != nil {
for _, peer = range kms.KmsPeers {
if peer.id == lookup {
return peer
}
}
}
return nil
}
func (kms *EKMS) RoutingTableDeepCopy() map[uuid.UUID]*Route {
copy := make(map[uuid.UUID]*Route, len(kms.KmsPeers))
kms.routingTableMutex.Lock()
for k, v := range kms.routingTable {
copy[k] = v
}
kms.routingTableMutex.Unlock()
return copy
}
func (kms *EKMS) PeersDeepCopy() map[string]*kmsPeer {
copy := make(map[string]*kmsPeer, len(kms.KmsPeers))
kms.kmsPeersMutex.Lock()
for k, v := range kms.KmsPeers {
copy[k] = v
}
kms.kmsPeersMutex.Unlock()
return copy
}