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/ekms/internal/api/gen/proto/go/kmsetsi"
pbIC "code.fbi.h-da.de/danet/ekms/internal/api/gen/proto/go/kmsintercom"
pbQS "code.fbi.h-da.de/danet/quipsec/gen/go/quipsec"
"github.com/google/uuid"
)
//type Qkdnkms interface {
// //AddExternalNotifierGeneral(chan bool) // used to indicate unspecific changes
// AddExternalNotifierQLE(chan uint32) // used to indicate changes to specific Quantum Link Element (QLE)
// AddExternalNotifierKMSPeer(chan string) // used to indicate changes to specific KMSPeer
// AddQuantumElement() *EmulatedQuantumModule
// GlobalKeyHandler(time.Duration) error
// AddPeer(kmsPeerSocket string, servingQLE *EmulatedQuantumModule)
// RemovePeer(kmsPeerSocket string)
// FindPeerUuid(uuid.UUID) *kmsPeer
//}
type Route struct {
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
qleMapMutex sync.Mutex
// TODO create a mapping between ids and address
quantumModules map[string]QuantumModule
quantumModulesMutex sync.RWMutex
externalNotifierQLE chan uint32
kmsPeersMutex sync.Mutex
// TODO(maba): find a better name for this
keysForPathId map[uuid.UUID]string
routingTable map[uuid.UUID]*Route
KmsPeers map[string]*kmsPeer
externalNotifierKMSPeer chan string
pbETSI.UnimplementedKmsETSIServer
pbIC.UnimplementedKmsTalkerServer
supportedKeyLengths map[BitKeyLength]bool
// 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,
quantumModules: make(map[string]QuantumModule),
routingTable: make(map[uuid.UUID]*Route),
KmsPeers: make(map[string]*kmsPeer),
externalNotifierQLE: nil, // just be surely set to nil!
externalNotifierKMSPeer: nil, // just be surely set to nil!
supportedKeyLengths: make(map[BitKeyLength]bool),
createdEKMS.supportedKeyLengths[BitKeyLen256] = true
// start the inter communication gRPC server
go createdEKMS.startGRPC(interComAddr)
}
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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) {
//check if peer exists
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.externalNotifierKMSPeer)
}
peer.tcpSocketStr = kmsPeerSocket
kms.kmsPeersMutex.Lock()
kms.kmsPeersMutex.Unlock()
//go peer.PeerHandler(kms.kmsName)
return peer, nil
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
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)
}
}
// set the route within routing table
kms.routingTable[pathId] = &Route{
Previous: previousHop,
Next: nextHop,
}
return nil
}
// TODO/XXX error handling
func (kms *EKMS) RemovePeer(kmsPeerSocket string) {
if _, there := kms.KmsPeers[kmsPeerSocket]; there {
//peer.quit <- true
delete(kms.KmsPeers, kmsPeerSocket)
return
}
log.Errorf("%s: Can not find a peer with socket: %s", kms.kmsName, kmsPeerSocket)
func (kms *EKMS) AddExternalNotifierQLE(in chan uint32) {
kms.externalNotifierQLE = in
}
func (kms *EKMS) AddExternalNotifierKMSPeer(in chan string) {
kms.externalNotifierKMSPeer = in
}
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) 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
}