Skip to content
Snippets Groups Projects
Commit 5a24b1bb authored by Martin Stiemerling's avatar Martin Stiemerling :speech_balloon: Committed by Malte Bauch
Browse files

Initial keystores implemented

parent 7d39f1dd
Branches
Tags
1 merge request!1Move proto kms into ekms
package kms
import (
"crypto/sha256"
"errors"
"fmt"
"log"
"sync"
"code.fbi.h-da.de/m.stiemerling/proto-kms/quantumlayer"
)
type kmsKS interface {
KeyChopper256Bit(bulkKey *quantumlayer.QuantumLayerBulkKey) (err error)
addKey(int64, [8]byte)
}
// holds a single ready to use 256 bit key
type kmsKSElement struct {
keyID string
key []byte // a 256 bit key
}
type kmsKeyStore struct {
keyStoreMutex sync.Mutex
keyStore map[string]kmsKSElement
}
func (ks *kmsKeyStore) addKey(bulkKeyId int64, keyToadd []byte) {
newKeyElement := kmsKSElement{}
//generate keyID out of bulkKeyId and has of keyToadd
h := sha256.New()
hasofkey := string(h.Sum(keyToadd[:]))
newKeyElement.keyID = fmt.Sprintf("%x.%x", bulkKeyId, hasofkey)
newKeyElement.key = keyToadd
ks.keyStoreMutex.Lock()
defer ks.keyStoreMutex.Unlock()
// test for collisions
if _, notThere := ks.keyStore[newKeyElement.keyID]; notThere {
log.Fatalf("Whop: addKey collission of key id %s for bulkKeyID %d", newKeyElement.keyID, bulkKeyId)
return
}
// ok to add
ks.keyStore[newKeyElement.keyID] = newKeyElement
}
// Takes a bulk of keys and chops them in 256bit keys each
// Any remainder is discarded
func (ks *kmsKeyStore) KeyChopper256Bit(bulkKey *quantumlayer.QuantumLayerBulkKey) (err error) {
if bulkKey.BulkKeyLength != len(*bulkKey.BulkKey) {
err = errors.New("bulkKey length mismatch")
return err
}
// Let's chop!
key := *bulkKey.BulkKey
for len(key) > 8 {
tmpkey := key[:8]
ks.addKey(bulkKey.BulkKeyId, tmpkey)
// shorten the key storage
key = key[8:]
}
return nil
}
......@@ -5,53 +5,132 @@
package kms
import (
"crypto/rand"
"log"
"math/big"
"sync"
"time"
"code.fbi.h-da.de/m.stiemerling/proto-kms/quantumlayer"
"github.com/google/uuid"
)
type Qkdnkms interface {
AddQuantumElement() *QuantumElement
GlobalKeyHandler(time.Duration) error
}
type qlElementId uuid.UUID
type qlElementId uint64
type qlElementLinkID int
// The general emulated KMS
type eKMS struct {
kmsName string
kmsUUID uuid.UUID
qleMapMutex sync.Mutex
QuantumElements map[qlElementId]*QuantumElement
KeyStorages map[qlElementId]map[qlElementLinkID]uint64
}
// 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 QuantumElement struct {
qlElementName string // the name of this Quantum Element
qlElementUUID uuid.UUID // the uuid for this device
QlElement *quantumlayer.QuantumlayerEmuPRNG // the actual quantum element
QuantumElementLinks map[qlElementLinkID]*quantumlayer.QuantumLayer // contains information about the quantum links
qlID qlElementId
QuantumElementLink *quantumlayer.QuantumlayerEmuPRNG // contains information about the quantum links
//key stores go here
keyStoreLocal *kmsKeyStore // the keys this local entity has produced and are ready to use
keyStoreRemote *kmsKeyStore // the keys th remote entity (peer) has produced and are ready to use
}
func NeweKMS() (newekms *eKMS) {
func NeweKMS(kmsName string, kmsUUID uuid.UUID) (newekms *eKMS) {
return &eKMS{
kmsName: kmsName,
kmsUUID: kmsUUID,
QuantumElements: make(map[qlElementId]*QuantumElement),
KeyStorages: make(map[qlElementId]map[qlElementLinkID]uint64),
}
}
func (kms *eKMS) AddQuantumElement(kmsName string, kmsUUID uuid.UUID, kmsUDPAddrr string) *QuantumElement {
func (kms *eKMS) AddQuantumElement(kmsUDPAddrr string) *QuantumElement {
//Get an emulated Quantumlayer
ql := quantumlayer.NewQuantumlayerEmuPRNG()
ql.PowerOn(kmsUDPAddrr)
ksl := kmsKeyStore{
keyStore: make(map[string]kmsKSElement),
}
ksr := kmsKeyStore{
keyStore: make(map[string]kmsKSElement),
}
qle := QuantumElement{
qlElementName: kmsName,
qlElementUUID: kmsUUID,
QlElement: ql,
QuantumElementLinks: make(map[qlElementLinkID]*quantumlayer.QuantumLayer),
QuantumElementLink: ql,
keyStoreLocal: &ksl,
keyStoreRemote: &ksr,
}
kms.QuantumElements[qlElementId(kmsUUID)] = &qle
// generate a ID for this quantum element that is unique locally
var randError error
qle.qlID, randError = kms.GenerateNewQleID()
if randError != nil {
log.Fatalf("GenerateNewQleID: %s", randError)
return nil
}
kms.QuantumElements[qle.qlID] = &qle
return &qle
}
func (kms *eKMS) GlobalKeyHandler(waitTime time.Duration) error {
// periodically walk through QuantumElements and retrieve their
// - local key bulk buffer
// - remote key bulk buffer
// feed this into the corresponding key buffers of the kmss
for {
for currentQE := range kms.QuantumElements {
log.Printf("%s GlobalKeyHandler reading...\n", kms.kmsName)
bulkKeysLocal, err := kms.QuantumElements[currentQE].QuantumElementLink.GetKeyBatchLocal()
if err != nil {
log.Printf("%s failed to retrieve local bulkkeys with error %s", kms.kmsName, err)
} else {
// process bulkKeysLocal
log.Printf("%s produced %d bytes of key locally", kms.kmsName, bulkKeysLocal.BulkKeyLength)
kms.QuantumElements[currentQE].keyStoreLocal.KeyChopper256Bit(&bulkKeysLocal)
}
bulkKeysRemote, err := kms.QuantumElements[currentQE].QuantumElementLink.GetKeyBatchPeer()
if err != nil {
log.Printf("%s failed to retrieve remote bulkkeys with error %s", kms.kmsName, err)
} else {
// process bulkKeysRemote
log.Printf("%s received %d bytes of key from remote peer", kms.kmsName, bulkKeysRemote.BulkKeyLength)
kms.QuantumElements[currentQE].keyStoreRemote.KeyChopper256Bit(&bulkKeysLocal)
}
}
time.Sleep(waitTime)
}
}
// This has a design flaw, as the generated ID is returned to the calling function and used there.
// However, when being used a potential other caller might received the same qlElementId
// TODO/XXX: This would be collision and must be eventually avoided
func (kms *eKMS) GenerateNewQleID() (qlElementId, error) {
for { // this needs a condiction to stop!
bigRand, randError := rand.Int(rand.Reader, big.NewInt(100000))
if randError != nil {
return 0, randError
}
propopsedQlElementID := qlElementId(bigRand.Uint64())
// check if ID is already taken
if kms.QuantumElements[propopsedQlElementID] == nil {
return propopsedQlElementID, nil
}
//keep going....
}
}
......@@ -4,6 +4,7 @@ import (
"flag"
"log"
"net"
"time"
"code.fbi.h-da.de/m.stiemerling/proto-kms/kms"
"github.com/google/uuid"
......@@ -56,10 +57,10 @@ func main() {
func emulatedKMS(myName string, myUDPAddr string, peerUDPAddr string) {
// Attach to eKMS
emuKMS := kms.NeweKMS()
emuKMS := kms.NeweKMS(myName, uuid.New())
// Fire up Quantum LinK
myQL := emuKMS.AddQuantumElement(myName, uuid.New(), myUDPAddr)
myQL := emuKMS.AddQuantumElement(myUDPAddr)
udpQL2Addr, err := net.ResolveUDPAddr("udp", peerUDPAddr)
if err != nil {
......@@ -67,18 +68,8 @@ func emulatedKMS(myName string, myUDPAddr string, peerUDPAddr string) {
return
}
myQL.QlElement.AddPeer(*udpQL2Addr)
myQL.QuantumElementLink.AddPeer(*udpQL2Addr)
for {
resultQLLocal, err := myQL.QlElement.GetKeyBatchLocal()
if err == nil {
log.Printf("Current key IDs are for %s local %d:", myName, resultQLLocal.BulkKeyId)
}
resultQLRemote, err := myQL.QlElement.GetKeyBatchPeer()
if err == nil {
log.Printf("Current key IDs are for remote %d:", resultQLRemote.BulkKeyId)
}
}
// TODO/XXX catch errors!
emuKMS.GlobalKeyHandler(7 * time.Second)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment