-
Malte Bauch authoredMalte Bauch authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
kms.go 5.38 KiB
// 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 (
"fmt"
"io"
"sync"
log "github.com/sirupsen/logrus"
pbETSI "code.fbi.h-da.de/danet/proto-kms/api/gen/proto/go/kmsetsi"
pbIC "code.fbi.h-da.de/danet/proto-kms/api/gen/proto/go/kmsintercom"
"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
type EKMS struct {
kmsName string
kmsUUID uuid.UUID
interComAddr string
qleMapMutex sync.Mutex
quantumModules map[uuid.UUID]QuantumModule
quantumModulesMutex sync.RWMutex
externalNotifierQLE chan uint32
kmsPeersMutex sync.Mutex
// TODO(maba): find a better name for this
// TODO: add mutex
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)
}
createdEKMS := &EKMS{
kmsName: kmsName,
kmsUUID: kmsUUID,
interComAddr: interComAddr,
quantumModules: make(map[uuid.UUID]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 StartInterComm(interComAddr, createdEKMS)
return createdEKMS
}
func (kms *EKMS) AddQuantumElement(qm QuantumModule) error {
kms.quantumModulesMutex.Lock()
kms.quantumModules[qm.ID()] = 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)
if err != nil {
return nil, err
}
peer.tcpSocketStr = kmsPeerSocket
kms.kmsPeersMutex.Lock()
kms.KmsPeers[kmsPeerSocket] = peer
kms.kmsPeersMutex.Unlock()
//go peer.PeerHandler(kms.kmsName)
return peer, nil
}
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)
return
}
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
}