diff --git a/go.mod b/go.mod index 898522e7da98d27f0fecaf823c591d11d439c19f..117c18367f5feaa1b9dd98d0ca60c6aa2a9bee56 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/google/uuid v1.3.0 - google.golang.org/grpc v1.56.1 + google.golang.org/grpc v1.56.2 google.golang.org/protobuf v1.31.0 ) diff --git a/go.sum b/go.sum index c53bd580d4f739afe6cfa7a55af24f6bf5bfda6e..dd5cac2ad34df0f5e7bdbd392eb30bfea2ded46b 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= diff --git a/kms/kms-keystore.go b/kms/kms-keystore.go index bdf7240a2a50788a0cfe6099dd843bdbe2a9f549..c04cfbfba9f856c6fc5612a22721e7440a4aa178 100644 --- a/kms/kms-keystore.go +++ b/kms/kms-keystore.go @@ -22,7 +22,7 @@ type kmsKSElement struct { type kmsKeyStore struct { keyStoreMutex sync.Mutex - keyStore map[string]kmsKSElement + keyStore map[string]*kmsKSElement } func (ks *kmsKeyStore) addKey(bulkKeyId int64, keyToadd []byte) { @@ -40,7 +40,7 @@ func (ks *kmsKeyStore) addKey(bulkKeyId int64, keyToadd []byte) { return } // ok to add - ks.keyStore[newKeyElement.keyID] = newKeyElement + ks.keyStore[newKeyElement.keyID] = &newKeyElement } @@ -54,13 +54,11 @@ func (ks *kmsKeyStore) KeyChopper256Bit(bulkKey *quantumlayer.QuantumLayerBulkKe // Let's chop! key := *bulkKey.BulkKey - for len(key) > 8 { - tmpkey := key[:8] + for len(key) > 32 { + tmpkey := key[:32] ks.addKey(bulkKey.BulkKeyId, tmpkey) // shorten the key storage - key = key[8:] - + key = key[32:] } return nil - } diff --git a/kms/kms.go b/kms/kms.go index 11fd477a8512b3449e2ba8efce20ff373ae87343..73eadff830a8f902fb136249433f544ea49e2def 100644 --- a/kms/kms.go +++ b/kms/kms.go @@ -80,10 +80,10 @@ func (kms *EKMS) AddQuantumElement(kmsUDPAddrr string) *QuantumElement { ql.PowerOn() ksl := kmsKeyStore{ - keyStore: make(map[string]kmsKSElement), + keyStore: make(map[string]*kmsKSElement), } ksr := kmsKeyStore{ - keyStore: make(map[string]kmsKSElement), + keyStore: make(map[string]*kmsKSElement), } qle := QuantumElement{ @@ -181,7 +181,13 @@ func (kms *EKMS) AddPeer(kmsPeerSocket string, servingQLE *QuantumElement) { // 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.Printf("Can not find a peer with socekt: %s", kmsPeerSocket) + return } func (kms *EKMS) AddExternalNotifierQLE(in chan uint32) { diff --git a/kms/kmsetsi.go b/kms/kmsetsi.go index 6351d30eca7473c77aad5b9c2e33aabe83c247e0..cc5ac8e41ba7f15a595fa0132e2323982382116b 100644 --- a/kms/kmsetsi.go +++ b/kms/kmsetsi.go @@ -2,14 +2,18 @@ package kms import ( "context" + "encoding/base64" "errors" "flag" "fmt" "log" "net" + "os/exec" pb "code.fbi.h-da.de/demoquandt/proto-kms/api/gen/proto/go/kmsetsi" "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) var ( @@ -19,6 +23,7 @@ var ( type etsiServer struct { pb.UnimplementedKmsETSIServer handlingEkms *EKMS + visitedKeys map[*kmsKSElement]bool } func (es *etsiServer) ETSICapabilities(ctx context.Context, in *pb.ETSICapabilitiesRequest) (capReply *pb.ETSICapabilitiesReply, err error) { @@ -92,15 +97,38 @@ func (es *etsiServer) ETSIGetPeerList(ctx context.Context, in *pb.ETSIKMSPeerLis return r, nil } -func (es *etsiServer) GetEncryptKeys256Bit(ctx context.Context, in *pb.ETSIGetEncryptKeys256BitRequest) (*pb.ETSIGetEncryptKeys256BitReply, error) { +func (es *etsiServer) ETSIGetEncryptKeys256Bit(ctx context.Context, in *pb.ETSIGetEncryptKeys256BitRequest) (*pb.ETSIGetEncryptKeys256BitReply, error) { log.Printf("Received request for n=%d keys", in.GetAmount()) - testBytes := []byte{120, 120, 120} + var randomKey *kmsKSElement + var err error + // NOTE: change change change! + for _, qe := range es.handlingEkms.QuantumElements { + quantumElementLocalKeyStore := qe.keyStoreLocal + randomKey, err = randomItemFromMap[string, *kmsKSElement](quantumElementLocalKeyStore.keyStore, es.visitedKeys) + if err != nil { + return nil, status.Errorf(codes.Internal, "%v", err) + } + es.visitedKeys[randomKey] = true + } + + keyAsString := base64.StdEncoding.EncodeToString(randomKey.key) + // push the key to the encryptor via ssh + ssh := "ssh" + complexArg := fmt.Sprintf("(rc=$(sed \"12 c PresharedKey = %s\" /etc/wireguard/wg0.conf); echo \"$rc\" > /etc/wireguard/wg0.conf)", keyAsString) + args := []string{"root@172.20.0.5", "-oStrictHostKeyChecking=no", complexArg} + + cmd := exec.Command(ssh, args...) + err = cmd.Run() + if err != nil { + log.Println("could not execute command") + return nil, status.Errorf(codes.Internal, "%v", err) + } // Construct any response return &pb.ETSIGetEncryptKeys256BitReply{ - KeyID: "2", - Key: testBytes, + KeyID: randomKey.keyID, + Key: randomKey.key, }, nil } @@ -115,6 +143,7 @@ func StartETSI(listenAddr string, callingKMS *EKMS) { s := grpc.NewServer() pb.RegisterKmsETSIServer(s, &etsiServer{ handlingEkms: callingKMS, + visitedKeys: make(map[*kmsKSElement]bool), }) log.Printf("server listening at %v", lis.Addr()) if err := s.Serve(lis); err != nil { diff --git a/kms/kmspeers.go b/kms/kmspeers.go index d3089f397b079446850368d21e42cf4bffc722f9..65207e2335e994c97b088e7f03d16af1a7784558 100644 --- a/kms/kmspeers.go +++ b/kms/kmspeers.go @@ -2,8 +2,11 @@ package kms import ( "context" + "encoding/base64" + "fmt" "log" "net" + "os/exec" "time" pb "code.fbi.h-da.de/demoquandt/proto-kms/api/gen/proto/go/kmsetsi" @@ -35,6 +38,7 @@ type kmsPeer struct { tcpSocketStr string // string rep. of tcpSocket name string // the name of the kms peer id uuid.UUID // uuid of the peer + quit chan bool // cancel the peer goroutine } func NewKmsPeer(servQLE *QuantumElement, in chan string) (peer kmsPeer) { @@ -43,12 +47,12 @@ func NewKmsPeer(servQLE *QuantumElement, in chan string) (peer kmsPeer) { servingQLE: servQLE, id: uuid.New(), externalNotifierKMSPeer: in, + quit: make(chan bool), } } // Handles everything with respect to a specific KMS peer func (ph *kmsPeer) PeerHandler(kmsName string) { - log.Printf("%s started PeerHandler for %s:", kmsName, ph.tcpSocketStr) // contact peer @@ -73,11 +77,58 @@ func (ph *kmsPeer) PeerHandler(kmsName string) { if ph.externalNotifierKMSPeer != nil { ph.externalNotifierKMSPeer <- ph.tcpSocketStr } - return } + + // NOTE: If a session is created, we also request a encryption key for now + //quantumElementRequest, err := c.ETSIGetQuantumInterfaces(ctx, &pb.ETSIKMSQuantumInterfaceListRequest{}) + //if err != nil { + // log.Println("Could not request quantum elements: ", err) + // ph.peerStatus = KmsPeerDown + // // Send notification about change + // if ph.externalNotifierKMSPeer != nil { + // ph.externalNotifierKMSPeer <- ph.tcpSocketStr + // } + // return + //} + + //if quantumElementRequest.QlElementInfo != nil { + // peerQuantumElement := quantumElementRequest.QlElementInfo[0].QleID + //} else { + // // return error?! + //} + // Works and peer moves to kmsPeerUp ph.peerStatus = KmsPeerUp + encryptKeyRequest, err := c.ETSIGetEncryptKeys256Bit(ctx, &pb.ETSIGetEncryptKeys256BitRequest{Amount: 1}) + if err != nil { + log.Println("could not request a encryption key: ", err) + ph.peerStatus = KmsPeerDown + // Send notification about change + if ph.externalNotifierKMSPeer != nil { + ph.externalNotifierKMSPeer <- ph.tcpSocketStr + } + return + } + + // check if key is in remoteKeyStore + if key, ok := ph.servingQLE.keyStoreRemote.keyStore[encryptKeyRequest.KeyID]; ok { + keyAsString := base64.StdEncoding.EncodeToString(key.key) + log.Printf("Agreed Key: %s", keyAsString) + + // push the key to the encryptor via ssh + ssh := "ssh" + complexArg := fmt.Sprintf("(rc=$(sed \"12 c PresharedKey = %s\" /etc/wireguard/wg0.conf); echo \"$rc\" > /etc/wireguard/wg0.conf)", keyAsString) + args := []string{"root@172.20.0.4", "-oStrictHostKeyChecking=no", complexArg} + + cmd := exec.Command(ssh, args...) + err := cmd.Run() + if err != nil { + log.Println("could not execute command") + return + } + } + // Send notification about change if ph.externalNotifierKMSPeer != nil { ph.externalNotifierKMSPeer <- ph.tcpSocketStr @@ -85,23 +136,28 @@ func (ph *kmsPeer) PeerHandler(kmsName string) { log.Printf("Greeting: %s which is now in peerStatus %d", r.GetPeerKmsName(), ph.peerStatus) + // NOTE: should be possible to cancel! // By now, do check only the liveliness of the peer, nothing else. - for { - time.Sleep(30 * time.Second) - // Contact the server and print out its response. - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - _, err := c.ETSICapabilities(ctx, &pb.ETSICapabilitiesRequest{MyKmsName: kmsName}) - if err != nil { - log.Printf("could not greet: %v", err) - ph.peerStatus = KmsPeerDown - // Send notification about change - if ph.externalNotifierKMSPeer != nil { - ph.externalNotifierKMSPeer <- ph.tcpSocketStr - } - } - - } + //for { + // select { + // case <-ph.quit: + // return + // default: + // // Contact the server and print out its response. + // ctx, cancel := context.WithTimeout(context.Background(), time.Second) + // defer cancel() + // _, err := c.ETSICapabilities(ctx, &pb.ETSICapabilitiesRequest{MyKmsName: kmsName}) + // if err != nil { + // log.Printf("could not greet: %v", err) + // ph.peerStatus = KmsPeerDown + // // Send notification about change + // if ph.externalNotifierKMSPeer != nil { + // ph.externalNotifierKMSPeer <- ph.tcpSocketStr + // } + // } + // time.Sleep(30 * time.Second) + // } + //} } func (ph *kmsPeer) GetKmsPeerStatus() KmsPeerStatus { diff --git a/kms/util.go b/kms/util.go new file mode 100644 index 0000000000000000000000000000000000000000..b9b5c35056b54c27409fb6a35aa35ad51f58560e --- /dev/null +++ b/kms/util.go @@ -0,0 +1,16 @@ +package kms + +import "fmt" + +// Ewww... don't +func randomItemFromMap[T, M comparable](m map[T]M, v map[M]bool) (M, error) { + for _, item := range m { + if v[item] { + continue + } + return item, nil + } + + var r M + return r, fmt.Errorf("Could not return a random item from map %v", m) +}