diff --git a/goKMS/kms/kms.go b/goKMS/kms/kms.go index 7907eec31a4da93cbc027f2d95771752f484a502..a002fa643c5ff5dd7aae29590193889cd2d1fd0b 100644 --- a/goKMS/kms/kms.go +++ b/goKMS/kms/kms.go @@ -37,8 +37,8 @@ import ( type Route struct { PathId uuid.UUID - Previous *peers.Peer - Next *peers.Peer + Previous *peers.KmsPeer + Next *peers.KmsPeer RemoteKMS *util.RemoteKMS } @@ -75,7 +75,7 @@ type KMS struct { // TODO(maba): find a better name for this routingTable map[uuid.UUID]*Route routingTableMutex sync.RWMutex - KmsPeers map[string]*peers.Peer + KmsPeers map[string]*peers.KmsPeer pbIC.UnimplementedKmsTalkerServer supportedKeyLengths map[BitKeyLength]bool eventBus *event.EventBus @@ -132,7 +132,7 @@ func NewKMS(kmsUUID uuid.UUID, logOutput io.Writer, logLevel log.Level, logInJso quantumModules: make(map[string]peers.QuantumModule), routingTable: make(map[uuid.UUID]*Route), PKStore: make(map[string]map[uuid.UUID]*PlatformKey), - KmsPeers: make(map[string]*peers.Peer), + KmsPeers: make(map[string]*peers.KmsPeer), supportedKeyLengths: make(map[BitKeyLength]bool), eventBus: event.NewEventBus(), ckmsAkmsClient: ckmsAkmsClient, @@ -188,7 +188,7 @@ func (kms *KMS) initializePeers(config *config.Config) error { pqm := peer.QuantumModule switch qmt := peer.QuantumModule.QmType; qmt { case "emulated": - qm = peers.NewEmulatedQuantumModule(pqm.Address, config.Id) + qm = peers.NewDanetQuantumModule(pqm.Address, config.Id) case "etsi": qm, err = peers.NewETSI014HTTPQuantumModule(pqm.Address, config.Id, pqm.SlaveSAEID, pqm.MasterSAEID, config.QuantumModuleTLS, pqm.MasterMode) if err != nil { @@ -300,7 +300,7 @@ func (kms *KMS) AddQuantumElement(qm peers.QuantumModule) error { return nil } -func (kms *KMS) AddPeer(peerKmsId string, kmsPeerSocket string, servingQLE peers.QuantumModule, client *peers.GRPCClient) (*peers.Peer, error) { +func (kms *KMS) AddPeer(peerKmsId string, kmsPeerSocket string, servingQLE peers.QuantumModule, client *peers.GRPCClient) (*peers.KmsPeer, error) { // check if peer exists if _, there := kms.KmsPeers[peerKmsId]; there { log.Errorf("Trying to add existing peer %s, with KMS ID %s", kmsPeerSocket, peerKmsId) @@ -326,8 +326,8 @@ func (kms *KMS) AssignForwardingRoute(pId, pHop, nHop string, remoteKMS *util.Re return fmt.Errorf("the given path id %s is no uuid; err = %w", pathId, err) } - var previousHop *peers.Peer - var nextHop *peers.Peer + var previousHop *peers.KmsPeer + var nextHop *peers.KmsPeer var ok bool if pHop != "" { previousHop, ok = kms.KmsPeers[pHop] @@ -504,7 +504,7 @@ func (kms *KMS) RemovePeer(kmsPeerSocket string) { log.Errorf("%s: Can not find a peer with socket: %s", kms.kmsName, kmsPeerSocket) } -func (kms *KMS) FindPeerUuid(lookup uuid.UUID) (peer *peers.Peer) { +func (kms *KMS) FindPeerUuid(lookup uuid.UUID) (peer *peers.KmsPeer) { if kms.KmsPeers != nil { for _, peer = range kms.KmsPeers { if peer.GetKmsPeerId() == lookup { @@ -528,8 +528,8 @@ func (kms *KMS) RoutingTableDeepCopy() map[uuid.UUID]*Route { return routingTableCopy } -func (kms *KMS) PeersDeepCopy() map[string]*peers.Peer { - peersCopy := make(map[string]*peers.Peer, len(kms.KmsPeers)) +func (kms *KMS) PeersDeepCopy() map[string]*peers.KmsPeer { + peersCopy := make(map[string]*peers.KmsPeer, len(kms.KmsPeers)) kms.kmsPeersMutex.Lock() defer kms.kmsPeersMutex.Unlock() diff --git a/goKMS/kms/kmsintercom.go b/goKMS/kms/kmsintercom.go index dff5a2a23d018b44bf59265643704cf9909a33f5..225aac2227b0d79a90bc93afd36d70222f6e02c8 100644 --- a/goKMS/kms/kmsintercom.go +++ b/goKMS/kms/kmsintercom.go @@ -108,7 +108,7 @@ func (s *kmsTalkerServer) SyncQkdBulk(ctx context.Context, in *pb.SyncQkdBulkReq return nil, status.Errorf(codes.Internal, "peer with ID: %s does not exist in peers", in.GetKmsId()) } - eqm, ok := peer.QuantumModule().(*peers.EmulatedQuantumModule) + eqm, ok := peer.QuantumModule().(*peers.DanetQuantumModule) if !ok { return nil, status.Errorf(codes.Internal, "expected emulated quantum module") } @@ -133,7 +133,7 @@ func (s *kmsTalkerServer) SyncKeyIdsForBulk(ctx context.Context, in *pb.SyncKeyI return nil, status.Errorf(codes.Internal, "For KMS id: %s, no peer exists", in.GetKmsId()) } - eqm, ok := peer.QuantumModule().(*peers.EmulatedQuantumModule) + eqm, ok := peer.QuantumModule().(*peers.DanetQuantumModule) if !ok { return nil, status.Errorf(codes.Internal, "expected a emulated quantum module") } diff --git a/goKMS/kms/peers/danetQuantummodule.go b/goKMS/kms/peers/danetQuantummodule.go new file mode 100644 index 0000000000000000000000000000000000000000..13300f5f8673d32a8da2c8eb6c3e80a9b8420a84 --- /dev/null +++ b/goKMS/kms/peers/danetQuantummodule.go @@ -0,0 +1,183 @@ +package peers + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + pbIC "code.fbi.h-da.de/danet/quant/goKMS/api/gen/proto/go/kmsintercom" + "code.fbi.h-da.de/danet/quant/goKMS/kms/event" + "code.fbi.h-da.de/danet/quant/goKMS/kms/store" + "code.fbi.h-da.de/danet/quant/goKMS/kms/util" + "code.fbi.h-da.de/danet/quant/quantumlayer" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +type DanetQuantumModule struct { + QlID uuid.UUID + kmsId string + // QuantumElementLink *quantumlayer.QuantumlayerEmuPRNG // contains information about the quantum links + // key stores of unchopped bulk keys go here + addr string + RawBulkKeysMutex sync.Mutex + RawBulkKeys map[int64]*quantumlayer.QuantumLayerBulkKey + keyStore *store.KmsKeyStore // the keys used between two peers. + kmsClient *GRPCClient + kmsEventBus *event.EventBus + kmsTcpSocketStr string +} + +func NewDanetQuantumModule(kmsUDPAddr string, kmsId string) *DanetQuantumModule { + return &DanetQuantumModule{ + QlID: uuid.New(), + kmsId: kmsId, + addr: kmsUDPAddr, + RawBulkKeys: make(map[int64]*quantumlayer.QuantumLayerBulkKey), + keyStore: store.NewKmsKeyStore(256), + kmsClient: nil, + kmsEventBus: nil, + kmsTcpSocketStr: "", + } +} + +func (qm *DanetQuantumModule) ID() uuid.UUID { + return qm.QlID +} + +func (qm *DanetQuantumModule) Initialize() error { + return nil +} + +func (qm *DanetQuantumModule) SetKmsPeerInformation(kmsClient *GRPCClient, kmsEventBus *event.EventBus, kmsTcpSocketStr string) error { + qm.kmsClient = kmsClient + qm.kmsEventBus = kmsEventBus + qm.kmsTcpSocketStr = kmsTcpSocketStr + return nil +} + +func (qm *DanetQuantumModule) Address() string { + return qm.addr +} + +func (qm *DanetQuantumModule) Sync() error { + rawBulkKeyIds := util.KeysOfMap(qm.RawBulkKeys) + log.Info("Found the following bulk key ids for usage: ", rawBulkKeyIds) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + initialPeerSetupResponse, err := qm.kmsClient.SyncQkdBulk(ctx, &pbIC.SyncQkdBulkRequest{ + Timestamp: time.Now().Unix(), + KmsId: qm.kmsId, + BulkId: rawBulkKeyIds, + }) + if err != nil { + return err + } + + bulkKey, ok := qm.RawBulkKeys[initialPeerSetupResponse.BulkId] + if !ok { + return fmt.Errorf("could not find raw bulk key with id: %d", initialPeerSetupResponse.BulkId) + } + + // TODO: Initially the peer partners should discuss about the key length, + // for now it is hardcoded. + qm.keyStore = store.NewKmsKeyStore(256) + + keyIds, keyData, err := qm.KeyChopper(bulkKey, []string{}) + if err != nil { + return err + } + + _, err = qm.kmsClient.SyncKeyIdsForBulk(ctx, &pbIC.SyncKeyIdsForBulkRequest{ + Timestamp: time.Now().Unix(), + KmsId: qm.kmsId, + BulkId: initialPeerSetupResponse.BulkId, + KeyId: keyIds, + }) + if err != nil { + return err + } + + for keyId, key := range keyData { + qm.keyStore.AddKey(keyId, key) + } + + qm.RawBulkKeysMutex.Lock() + delete(qm.RawBulkKeys, initialPeerSetupResponse.BulkId) + qm.RawBulkKeysMutex.Unlock() + + // Send notification about change + if qm.kmsEventBus != nil { + go func() { + err := qm.kmsEventBus.Publish(event.NewPeerEvent(qm.kmsTcpSocketStr)) + if err != nil { + log.Error(err) + } + }() + } + + return nil +} + +func (qm *DanetQuantumModule) KeyStore() *store.KmsKeyStore { + return qm.keyStore +} + +func (qm *DanetQuantumModule) SetKeyStore(newKeyStore *store.KmsKeyStore) { + qm.keyStore = newKeyStore +} + +func (qm *DanetQuantumModule) KmsGrpcClient() *GRPCClient { + return qm.kmsClient +} + +func (qm *DanetQuantumModule) SetKmsGrpcClient(peer *GRPCClient) { + qm.kmsClient = peer +} + +// Takes a bulk of keys and chops them in chopFactor keys each +// Any remainder is discarded +// If keyIds is empty, uuids are generated. +func (qm *DanetQuantumModule) KeyChopper(bulkKey *quantumlayer.QuantumLayerBulkKey, keyIds []string) ([]string, map[uuid.UUID][]byte, error) { + if qm.keyStore.KeySingleSize == 0 { + return nil, nil, errors.New("KeyChopper: no keySingleSize set") + } + + if bulkKey.BulkKeyLength != len(bulkKey.BulkKey) { + if (bulkKey.BulkKeyLength) != (len(bulkKey.BulkKey) * 8) { + log.Errorf("Length missmatch, even when converting 'bulkKey.BulkKey' to bytes: %d, %d", bulkKey.BulkKeyLength, len(bulkKey.BulkKey)) + return nil, nil, errors.New("bulkKey length mismatch") + } + } + + initialKeyIdsLen := len(keyIds) + + // Let's chop! + keyData := make(map[uuid.UUID][]byte) + chopFactor := qm.keyStore.KeySingleSize >> 3 + key := bulkKey.BulkKey + counter := 0 + for len(key) > int(chopFactor) { + var keyId uuid.UUID + var err error + if initialKeyIdsLen == 0 { + keyId = uuid.New() + keyIds = append(keyIds, keyId.String()) + } else { + keyId, err = uuid.Parse(keyIds[counter]) + if err != nil { + return nil, nil, fmt.Errorf("the provided ID: %s can not be parsed as UUID", keyIds[counter]) + } + counter++ + } + tmpkey := key[:chopFactor] + keyData[keyId] = tmpkey + + // shorten the key storage + key = key[chopFactor:] + } + return keyIds, keyData, nil +} diff --git a/goKMS/kms/peers/etsi14Quantummodule.go b/goKMS/kms/peers/etsi14Quantummodule.go new file mode 100644 index 0000000000000000000000000000000000000000..65e51140e6cbaff04e855da9d28ac94844f04272 --- /dev/null +++ b/goKMS/kms/peers/etsi14Quantummodule.go @@ -0,0 +1,155 @@ +package peers + +import ( + "context" + "fmt" + "net/http" + "net/url" + "time" + + etsi14ClientGenerated "code.fbi.h-da.de/danet/quant/etsi014/go/rest/etsi/client" + pbIC "code.fbi.h-da.de/danet/quant/goKMS/api/gen/proto/go/kmsintercom" + "code.fbi.h-da.de/danet/quant/goKMS/config" + etsi14ClientImpl "code.fbi.h-da.de/danet/quant/goKMS/kms/etsi/etsi14/client" + "code.fbi.h-da.de/danet/quant/goKMS/kms/event" + "code.fbi.h-da.de/danet/quant/goKMS/kms/store" + kmstls "code.fbi.h-da.de/danet/quant/goKMS/kms/tls" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +type ETSI014HTTPQuantumModule struct { + id uuid.UUID + kmsId string + addr string + keyStore *store.KmsKeyStore + kmsClient *GRPCClient + client *etsi14ClientImpl.ClientImpl + SlaveSAEID string + MasterSAEID string + master bool +} + +func NewETSI014HTTPQuantumModule(addr, kmsId, slaveSAEID, masterSAEID string, tlsConfig config.TLSConfig, master bool) (*ETSI014HTTPQuantumModule, error) { + parsedUrl, err := url.Parse(addr) + if err != nil { + return nil, err + } + + restClientConf := &etsi14ClientGenerated.Configuration{ + Debug: true, + Servers: etsi14ClientGenerated.ServerConfigurations{ + { + URL: parsedUrl.String(), + Description: "QKD Module with ETSI14 implemented as API.", + }, + }, + Scheme: parsedUrl.Scheme, + } + + if tlsConfig.TLS { + tlsConf, err := kmstls.GenerateTlsLibraryConfig(tlsConfig) + if err != nil { + return nil, fmt.Errorf("unable to generate TLS config: %w", err) + } + + restClientConf.HTTPClient = &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: tlsConf, + }, + } + } + + client, err := etsi14ClientImpl.NewClientImpl(restClientConf) + if err != nil { + return nil, err + } + + return &ETSI014HTTPQuantumModule{ + id: uuid.New(), + kmsId: kmsId, + addr: addr, + keyStore: store.NewKmsKeyStore(256), + kmsClient: nil, + client: client, + SlaveSAEID: slaveSAEID, + MasterSAEID: masterSAEID, + master: master, + }, nil +} + +func (qm *ETSI014HTTPQuantumModule) ID() uuid.UUID { + return qm.id +} + +func (qm *ETSI014HTTPQuantumModule) Client() *etsi14ClientImpl.ClientImpl { + return qm.client +} + +func (qm *ETSI014HTTPQuantumModule) Initialize() error { + // start polling + if qm.master { + go func() { + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + + // TODO: add context/channel to stop + for range ticker.C { + container, _, err := qm.client.GetKey(qm.SlaveSAEID) + if err != nil { + log.Error(err) + break + } + + keyIds := make([]string, len(container.GetKeys())) + for i, keyItem := range container.GetKeys() { + keyIds[i] = keyItem.GetKeyID() + } + + _, err = qm.kmsClient.KeyIdNotification(context.Background(), + &pbIC.KeyIdNotificationRequest{ + Timestamp: time.Now().Unix(), + KmsId: qm.kmsId, + KeyIds: keyIds, + }) + if err != nil { + log.Error(err) + break + } + + if err := store.AddETSIKeysToKeystore(qm.keyStore, container.GetKeys()); err != nil { + log.Error(err) + } + } + }() + } + return nil +} + +func (qm *ETSI014HTTPQuantumModule) SetKmsPeerInformation(kmsClient *GRPCClient, kmsEventBus *event.EventBus, kmsTcpSocketStr string) error { + qm.kmsClient = kmsClient + return nil +} + +func (qm *ETSI014HTTPQuantumModule) Address() string { + return qm.addr +} + +func (qm *ETSI014HTTPQuantumModule) KeyStore() *store.KmsKeyStore { + return qm.keyStore +} + +func (qm *ETSI014HTTPQuantumModule) SetKeyStore(newKeyStore *store.KmsKeyStore) { + qm.keyStore = newKeyStore +} + +func (qm *ETSI014HTTPQuantumModule) Sync() error { + return nil +} + +func (qm *ETSI014HTTPQuantumModule) KmsGrpcClient() *GRPCClient { + return nil +} + +func (qm *ETSI014HTTPQuantumModule) SetKmsGrpcClient(peer *GRPCClient) { +} diff --git a/goKMS/kms/peers/peers.go b/goKMS/kms/peers/kmsPeer.go similarity index 67% rename from goKMS/kms/peers/peers.go rename to goKMS/kms/peers/kmsPeer.go index e3098811ee99bd9672dc4f9f5b8ff88b194a6cb7..c9bacc956397406665a31816190d02bf4f83b0e7 100644 --- a/goKMS/kms/peers/peers.go +++ b/goKMS/kms/peers/kmsPeer.go @@ -15,6 +15,14 @@ import ( log "github.com/sirupsen/logrus" ) +// NOTE: currently not used, could be of usage later on +// type kmsPeerInfo interface { +// GetKmsPeerStatus() KmsPeerStatus +// GetKmsPeerId() uuid.UUID +// GetKmsPeerQkdiId() uint32 +// KmsPeerKeyInit() +// } + type KmsPeerStatus int16 const ( @@ -24,19 +32,11 @@ const ( KmsPeerUnknown // not known, not initialized ) -// NOTE: currently not used, could be of usage later on -// type kmsPeerInfo interface { -// GetKmsPeerStatus() KmsPeerStatus -// GetKmsPeerId() uuid.UUID -// GetKmsPeerQkdiId() uint32 -// KmsPeerKeyInit() -// } - type GRPCClient struct { pbIC.KmsTalkerClient } -type Peer struct { +type KmsPeer struct { peerClient *GRPCClient peerStatus KmsPeerStatus peerKmsId uuid.UUID @@ -52,11 +52,7 @@ type Peer struct { } // TODO: check intercomaddr -> remove? -func NewKmsPeer(peerKmsId string, servQM QuantumModule, tcpSocketStr string, interComAddr string, client *GRPCClient, eventBus *event.EventBus) (*Peer, error) { - if servQM.Peer() != nil { - return nil, fmt.Errorf("QuantumModule with ID: %s, already has a peer", servQM.ID()) - } - +func NewKmsPeer(peerKmsId string, quantummodule QuantumModule, tcpSocketStr string, interComAddr string, client *GRPCClient, eventBus *event.EventBus) (*KmsPeer, error) { var peerKmsIdUUID uuid.UUID if peerKmsId == "" { peerKmsIdUUID = uuid.New() @@ -74,7 +70,12 @@ func NewKmsPeer(peerKmsId string, servQM QuantumModule, tcpSocketStr string, int return nil, err } - peer := &Peer{ + err = quantummodule.SetKmsPeerInformation(client, eventBus, tcpSocketStr) + if err != nil { + return nil, err + } + + kmsPeer := &KmsPeer{ // NOTE It could be a good idea to turn client and status into its own // struct (and additional information) e.g. a link // We need multiple peer clients! @@ -84,7 +85,7 @@ func NewKmsPeer(peerKmsId string, servQM QuantumModule, tcpSocketStr string, int peerKmsId: peerKmsIdUUID, interComAddr: interComAddr, // NOTE a peer could have multiple quantum modules - servingQuantumModul: servQM, + servingQuantumModul: quantummodule, tcpSocket: tcpSocket, TcpSocketStr: tcpSocketStr, et: crypto.NewAES(), @@ -92,61 +93,64 @@ func NewKmsPeer(peerKmsId string, servQM QuantumModule, tcpSocketStr string, int eventBus: eventBus, } - servQM.SetPeer(peer) - - if err := servQM.Initialize(); err != nil { + if err := quantummodule.Initialize(); err != nil { return nil, err } - return peer, nil + return kmsPeer, nil } -func (ph *Peer) Client() *GRPCClient { - return ph.peerClient +func (kp *KmsPeer) Client() *GRPCClient { + return kp.peerClient } -func (ph *Peer) EventBus() *event.EventBus { - return ph.eventBus +func (kp *KmsPeer) EventBus() *event.EventBus { + return kp.eventBus } -func (ph *Peer) Address() *net.TCPAddr { - return ph.tcpSocket +func (kp *KmsPeer) Address() *net.TCPAddr { + return kp.tcpSocket } -func (ph *Peer) QuantumModule() QuantumModule { - return ph.servingQuantumModul +func (kp *KmsPeer) QuantumModule() QuantumModule { + return kp.servingQuantumModul } -func (ph *Peer) CryptoAlgo() crypto.CryptoAlgorithm { - return ph.et +func (kp *KmsPeer) CryptoAlgo() crypto.CryptoAlgorithm { + return kp.et } -func (ph *Peer) SyncBulkKeys() error { - return ph.servingQuantumModul.Sync() +func (kp *KmsPeer) SyncBulkKeys() error { + err := kp.servingQuantumModul.Sync() + if err != nil { + kp.peerStatus = KmsPeerUp + return nil + } + return err } // TransportKeyNegotiation sends a request for a transport key negotiation to // the peer KMS. The key that was agreed upon, is used to create a encrypted // payload. -func (ph *Peer) TransportKeyNegotiation() error { +func (kp *KmsPeer) TransportKeyNegotiation() error { // ctx, cancel := context.WithTimeout(context.Background(), time.Second) // req, err := ph.peerClient.InterComTransportKeyNegotiation() return nil } -func (ph *Peer) SendInitialPayloadBasedOnGRPCClient(key *crypto.Key, pathId, processId uuid.UUID, kmsId string, remoteKMS *util.RemoteKMS) error { - if ph.peerClient.KmsTalkerClient != nil { - return ph.SendPayload(key, pathId, processId) +func (kp *KmsPeer) SendInitialPayloadBasedOnGRPCClient(key *crypto.Key, pathId, processId uuid.UUID, kmsId string, remoteKMS *util.RemoteKMS) error { + if kp.peerClient.KmsTalkerClient != nil { + return kp.SendPayload(key, pathId, processId) } - return fmt.Errorf("Could not find a valid peer client.") + return fmt.Errorf("could not find a valid peer client") } -func (ph *Peer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) error { +func (kp *KmsPeer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) error { // NOTE: It should be assumed that there are keys available if we try to // send. - if ph.servingQuantumModul.KeyStore().Length() == 0 { + if kp.servingQuantumModul.KeyStore().Length() == 0 { log.Debug("Syncing bulk keys before sending the payload") - err := ph.SyncBulkKeys() + err := kp.SyncBulkKeys() if err != nil { return err } @@ -155,7 +159,7 @@ func (ph *Peer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) er // TODO: Return a message if keys are empty // select a key from key store - key, err := ph.servingQuantumModul.KeyStore().GetKey() + key, err := kp.servingQuantumModul.KeyStore().GetKey() if err != nil { return err } @@ -163,7 +167,7 @@ func (ph *Peer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) er // Start the negotiation process for a transport key ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - _, err = ph.peerClient.InterComTransportKeyNegotiation(ctx, &pbIC.InterComTransportKeyNegotiationRequest{ + _, err = kp.peerClient.InterComTransportKeyNegotiation(ctx, &pbIC.InterComTransportKeyNegotiationRequest{ Timestamp: time.Now().Unix(), PathID: pathId.String(), KeyToUse: key.KeyID.String(), @@ -172,12 +176,12 @@ func (ph *Peer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) er return err } - ph.servingQuantumModul.KeyStore().DeleteKey(key.KeyID) + kp.servingQuantumModul.KeyStore().DeleteKey(key.KeyID) // TODO: would be better to update the index counter here (to keep it // synchronized). - nonce, encryptedPayload, err := ph.et.Encrypt(payload.Key, key.Key) + nonce, encryptedPayload, err := kp.et.Encrypt(payload.Key, key.Key) if err != nil { return err } @@ -189,7 +193,7 @@ func (ph *Peer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) er ctx2, cancel2 := context.WithTimeout(context.Background(), time.Second) defer cancel2() - _, err = ph.peerClient.KeyForwarding(ctx2, &pbIC.KeyForwardingRequest{ + _, err = kp.peerClient.KeyForwarding(ctx2, &pbIC.KeyForwardingRequest{ Timestamp: time.Now().Unix(), PathId: pathId.String(), ProcessId: processId.String(), @@ -206,14 +210,14 @@ func (ph *Peer) SendPayload(payload *crypto.Key, pathId, processId uuid.UUID) er return nil } -func (ph *Peer) Status() KmsPeerStatus { - return ph.peerStatus +func (kp *KmsPeer) Status() KmsPeerStatus { + return kp.peerStatus } -func (ph *Peer) SetStatus(updateStatus KmsPeerStatus) { - ph.peerStatus = updateStatus +func (kp *KmsPeer) SetStatus(updateStatus KmsPeerStatus) { + kp.peerStatus = updateStatus } -func (ph *Peer) GetKmsPeerId() uuid.UUID { - return ph.peerKmsId +func (kp *KmsPeer) GetKmsPeerId() uuid.UUID { + return kp.peerKmsId } diff --git a/goKMS/kms/peers/qmodule.go b/goKMS/kms/peers/qmodule.go deleted file mode 100644 index aa531e9acce11f20b4aac390e5b3512d4f4e98a1..0000000000000000000000000000000000000000 --- a/goKMS/kms/peers/qmodule.go +++ /dev/null @@ -1,351 +0,0 @@ -package peers - -import ( - "context" - "errors" - "fmt" - "net/http" - "net/url" - "sync" - "time" - - etsi14ClientGenerated "code.fbi.h-da.de/danet/quant/etsi014/go/rest/etsi/client" - pbIC "code.fbi.h-da.de/danet/quant/goKMS/api/gen/proto/go/kmsintercom" - "code.fbi.h-da.de/danet/quant/goKMS/config" - etsi14ClientImpl "code.fbi.h-da.de/danet/quant/goKMS/kms/etsi/etsi14/client" - "code.fbi.h-da.de/danet/quant/goKMS/kms/event" - "code.fbi.h-da.de/danet/quant/goKMS/kms/store" - kmstls "code.fbi.h-da.de/danet/quant/goKMS/kms/tls" - "code.fbi.h-da.de/danet/quant/goKMS/kms/util" - "code.fbi.h-da.de/danet/quant/quantumlayer" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" -) - -// QuantumModule ... -type QuantumModule interface { - ID() uuid.UUID - Initialize() error - // NOTE: Sync will be removed as soon as the emulated quantum module has been - // changed to push a constant byte stream. - KeyStore() *store.KmsKeyStore - SetKeyStore(*store.KmsKeyStore) - Sync() error - Peer() *Peer - SetPeer(*Peer) - Address() string -} - -type EmulatedQuantumModule struct { - QlID uuid.UUID - kmsId string - // QuantumElementLink *quantumlayer.QuantumlayerEmuPRNG // contains information about the quantum links - // key stores of unchopped bulk keys go here - addr string - RawBulkKeysMutex sync.Mutex - RawBulkKeys map[int64]*quantumlayer.QuantumLayerBulkKey - keyStore *store.KmsKeyStore // the keys used between two peers. - peer *Peer -} - -func NewEmulatedQuantumModule(kmsUDPAddr string, kmsId string) *EmulatedQuantumModule { - return &EmulatedQuantumModule{ - QlID: uuid.New(), - // QuantumElementLink: ql, - kmsId: kmsId, - addr: kmsUDPAddr, - RawBulkKeys: make(map[int64]*quantumlayer.QuantumLayerBulkKey), - keyStore: store.NewKmsKeyStore(256), - peer: nil, - } -} - -func (eqe *EmulatedQuantumModule) ID() uuid.UUID { - return eqe.QlID -} - -func (eqe *EmulatedQuantumModule) Initialize() error { - // TODO: error handling - // go eqe.keyHandler() - return nil -} - -func (eqe *EmulatedQuantumModule) Address() string { - return eqe.addr -} - -func (eqe *EmulatedQuantumModule) Sync() error { - rawBulkKeyIds := util.KeysOfMap(eqe.RawBulkKeys) - log.Info("Found the following bulk key ids for usage: ", rawBulkKeyIds) - - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - initialPeerSetupResponse, err := eqe.peer.Client().SyncQkdBulk(ctx, &pbIC.SyncQkdBulkRequest{ - Timestamp: time.Now().Unix(), - KmsId: eqe.kmsId, - BulkId: rawBulkKeyIds, - }) - if err != nil { - return err - } - - bulkKey, ok := eqe.RawBulkKeys[initialPeerSetupResponse.BulkId] - if !ok { - return fmt.Errorf("could not find raw bulk key with id: %d", initialPeerSetupResponse.BulkId) - } - - // TODO: Initially the peer partners should discuss about the key length, - // for now it is hardcoded. - eqe.keyStore = store.NewKmsKeyStore(256) - - keyIds, keyData, err := eqe.KeyChopper(bulkKey, []string{}) - if err != nil { - return err - } - - _, err = eqe.peer.Client().SyncKeyIdsForBulk(ctx, &pbIC.SyncKeyIdsForBulkRequest{ - Timestamp: time.Now().Unix(), - KmsId: eqe.kmsId, - BulkId: initialPeerSetupResponse.BulkId, - KeyId: keyIds, - }) - if err != nil { - return err - } - - for keyId, key := range keyData { - eqe.keyStore.AddKey(keyId, key) - } - - eqe.RawBulkKeysMutex.Lock() - delete(eqe.RawBulkKeys, initialPeerSetupResponse.BulkId) - eqe.RawBulkKeysMutex.Unlock() - - // update the peer status to up - eqe.peer.SetStatus(KmsPeerUp) - // Send notification about change - if eqe.peer.EventBus() != nil { - go func() { - err := eqe.peer.EventBus().Publish(event.NewPeerEvent(eqe.peer.TcpSocketStr)) - if err != nil { - log.Error(err) - } - }() - } - - return nil -} - -func (eqe *EmulatedQuantumModule) KeyStore() *store.KmsKeyStore { - return eqe.keyStore -} - -func (eqe *EmulatedQuantumModule) SetKeyStore(newKeyStore *store.KmsKeyStore) { - eqe.keyStore = newKeyStore -} - -func (eqe *EmulatedQuantumModule) Peer() *Peer { - return eqe.peer -} - -func (eqe *EmulatedQuantumModule) SetPeer(peer *Peer) { - eqe.peer = peer -} - -//func (eqe *EmulatedQuantumModule) keyHandler() { -// // periodically walk through quantum element and retrieve the key bulk buffer -// for { -// log.Debugf("%s: KeyHandler reading...\n", eqe.ID()) -// bulkKeys, err := eqe.QuantumElementLink.GetKeyBulkPeer() -// if err != nil { -// log.Errorf("%s: failed to retrieve bulkkeys with error %s", eqe.ID(), err) -// } else { -// // Add to the slice, but not process yet. -// log.Debugf("%s: produced %d bytes of key", eqe.ID(), bulkKeys.BulkKeyLength) -// eqe.rawBulkKeysMutex.Lock() -// eqe.rawBulkKeys[bulkKeys.BulkKeyId] = &bulkKeys -// eqe.rawBulkKeysMutex.Unlock() -// } -// // TODO: hardcoded -// time.Sleep(5 * time.Second) -// } -//} - -// Takes a bulk of keys and chops them in chopFactor keys each -// Any remainder is discarded -// If keyIds is empty, uuids are generated. -func (eqe *EmulatedQuantumModule) KeyChopper(bulkKey *quantumlayer.QuantumLayerBulkKey, keyIds []string) ([]string, map[uuid.UUID][]byte, error) { - if eqe.keyStore.KeySingleSize == 0 { - return nil, nil, errors.New("KeyChopper: no keySingleSize set") - } - - if bulkKey.BulkKeyLength != len(bulkKey.BulkKey) { - if (bulkKey.BulkKeyLength) != (len(bulkKey.BulkKey) * 8) { - log.Errorf("Length missmatch, even when converting 'bulkKey.BulkKey' to bytes: %d, %d", bulkKey.BulkKeyLength, len(bulkKey.BulkKey)) - return nil, nil, errors.New("bulkKey length mismatch") - } - } - - initialKeyIdsLen := len(keyIds) - - // Let's chop! - keyData := make(map[uuid.UUID][]byte) - chopFactor := eqe.keyStore.KeySingleSize >> 3 - key := bulkKey.BulkKey - counter := 0 - for len(key) > int(chopFactor) { - var keyId uuid.UUID - var err error - if initialKeyIdsLen == 0 { - keyId = uuid.New() - keyIds = append(keyIds, keyId.String()) - } else { - keyId, err = uuid.Parse(keyIds[counter]) - if err != nil { - return nil, nil, fmt.Errorf("the provided ID: %s can not be parsed as UUID", keyIds[counter]) - } - counter++ - } - tmpkey := key[:chopFactor] - keyData[keyId] = tmpkey - - // shorten the key storage - key = key[chopFactor:] - } - return keyIds, keyData, nil -} - -type ETSI014HTTPQuantumModule struct { - id uuid.UUID - kmsId string - addr string - keyStore *store.KmsKeyStore - peer *Peer - client *etsi14ClientImpl.ClientImpl - SlaveSAEID string - MasterSAEID string - master bool -} - -func NewETSI014HTTPQuantumModule(addr, kmsId, slaveSAEID, masterSAEID string, tlsConfig config.TLSConfig, master bool) (*ETSI014HTTPQuantumModule, error) { - parsedUrl, err := url.Parse(addr) - if err != nil { - return nil, err - } - - restClientConf := &etsi14ClientGenerated.Configuration{ - Debug: true, - Servers: etsi14ClientGenerated.ServerConfigurations{ - { - URL: parsedUrl.String(), - Description: "QKD Module with ETSI14 implemented as API.", - }, - }, - Scheme: parsedUrl.Scheme, - } - - if tlsConfig.TLS { - tlsConf, err := kmstls.GenerateTlsLibraryConfig(tlsConfig) - if err != nil { - return nil, fmt.Errorf("unable to generate TLS config: %w", err) - } - - restClientConf.HTTPClient = &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: tlsConf, - }, - } - } - - client, err := etsi14ClientImpl.NewClientImpl(restClientConf) - if err != nil { - return nil, err - } - - return &ETSI014HTTPQuantumModule{ - id: uuid.New(), - kmsId: kmsId, - addr: addr, - keyStore: store.NewKmsKeyStore(256), - peer: nil, - client: client, - SlaveSAEID: slaveSAEID, - MasterSAEID: masterSAEID, - master: master, - }, nil -} - -func (eqe *ETSI014HTTPQuantumModule) ID() uuid.UUID { - return eqe.id -} - -func (eqe *ETSI014HTTPQuantumModule) Client() *etsi14ClientImpl.ClientImpl { - return eqe.client -} - -func (eqe *ETSI014HTTPQuantumModule) Initialize() error { - // start polling - if eqe.master { - go func() { - ticker := time.NewTicker(2 * time.Second) - defer ticker.Stop() - - // TODO: add context/channel to stop - for { - select { - case <-ticker.C: - container, _, err := eqe.client.GetKey(eqe.SlaveSAEID) - if err != nil { - log.Error(err) - break - } - - keyIds := make([]string, len(container.GetKeys())) - for i, keyItem := range container.GetKeys() { - keyIds[i] = keyItem.GetKeyID() - } - - _, err = eqe.peer.Client().KeyIdNotification(context.Background(), - &pbIC.KeyIdNotificationRequest{ - Timestamp: time.Now().Unix(), - KmsId: eqe.kmsId, - KeyIds: keyIds, - }) - if err != nil { - log.Error(err) - break - } - - if err := store.AddETSIKeysToKeystore(eqe.keyStore, container.GetKeys()); err != nil { - log.Error(err) - } - } - } - }() - } - return nil -} - -func (eqe *ETSI014HTTPQuantumModule) Address() string { - return eqe.addr -} - -func (eqe *ETSI014HTTPQuantumModule) KeyStore() *store.KmsKeyStore { - return eqe.keyStore -} - -func (eqe *ETSI014HTTPQuantumModule) SetKeyStore(newKeyStore *store.KmsKeyStore) { - eqe.keyStore = newKeyStore -} - -func (eqe *ETSI014HTTPQuantumModule) Peer() *Peer { - return eqe.peer -} - -func (eqe *ETSI014HTTPQuantumModule) SetPeer(peer *Peer) { - eqe.peer = peer -} - -func (eqe *ETSI014HTTPQuantumModule) Sync() error { - return nil -} diff --git a/goKMS/kms/peers/quantummodule.go b/goKMS/kms/peers/quantummodule.go new file mode 100644 index 0000000000000000000000000000000000000000..6e12f0524dfdaa53c1277219c9c99c71c988e2a6 --- /dev/null +++ b/goKMS/kms/peers/quantummodule.go @@ -0,0 +1,18 @@ +package peers + +import ( + "code.fbi.h-da.de/danet/quant/goKMS/kms/event" + "code.fbi.h-da.de/danet/quant/goKMS/kms/store" + "github.com/google/uuid" +) + +// QuantumModule interface definition. +type QuantumModule interface { + ID() uuid.UUID + Initialize() error + SetKmsPeerInformation(kmsClient *GRPCClient, kmsEventBus *event.EventBus, kmsTcpSocketStr string) error + KeyStore() *store.KmsKeyStore + SetKeyStore(*store.KmsKeyStore) + Sync() error + Address() string +} diff --git a/goKMS/kms/quipsec.go b/goKMS/kms/quipsec.go index 9965204c85b4e2ce3c35927ce4d892779fe1bf35..d2a850923c9f10ed3c28bd4eb98e00e996cb8638 100644 --- a/goKMS/kms/quipsec.go +++ b/goKMS/kms/quipsec.go @@ -36,7 +36,7 @@ func (qs *quipSecServer) PushKeys(ctx context.Context, req *pb.PushKeysRequest) return nil, status.Errorf(codes.Internal, "could not find a quantum module for host address: %s", host) } - eqm, ok := qm.(*peers.EmulatedQuantumModule) + eqm, ok := qm.(*peers.DanetQuantumModule) if !ok { logrus.Errorf("quantum module is of wrong type") return nil, status.Errorf(codes.Internal, "quantum module is of wrong type") diff --git a/goKMS/main.go b/goKMS/main.go index e7c39a224a243e0b4d1c9c5a8ab083b23bf77542..51d6ade05bd16142771c94dd80ea6d349f2afabf 100644 --- a/goKMS/main.go +++ b/goKMS/main.go @@ -60,7 +60,7 @@ func main() { certFile := flag.String("certFile", "", "location of the gNMI cert file (overwrites settings in config file)") keyFile := flag.String("keyFile", "", "location of the gNMI key file (overwrites settings in config file)") caFile := flag.String("caFile", "", "location of the gNMI ca file (overwrites settings in config file)") - noGRPCPassthrough := flag.Bool("noGRPCPassthrough", false, "set the default resolve scheme for grpc to not use passthrough, default is false") + noGRPCPassthrough := flag.Bool("noGRPCPassthrough", false, "set the default resolve scheme for grpc to not use passthrough, default is false") flag.Parse()