Skip to content
Snippets Groups Projects
Commit a5faa9a1 authored by Richard T. Carback III's avatar Richard T. Carback III
Browse files

Merge branch 'ttlRedo' into 'release'

rewrite the e2e ttl handling code to be more inteligent and to be consistant

See merge request !519
parents ef852de4 de3be58b
No related branches found
No related tags found
No related merge requests found
......@@ -74,7 +74,7 @@ const (
maxKeys uint16 = 800
ttlScalar float64 = 1.2 // generate 20% extra keys
threshold uint16 = 224
numReKeys uint16 = 64
numReKeys uint16 = 16
)
type E2ESessionParams struct {
......
......@@ -189,7 +189,7 @@ func TestRelationship_GetByID(t *testing.T) {
}
// Shows that GetNewestRekeyableSession acts as expected:
// returning sessions that are confirmed and past ttl
// returning sessions that are confirmed and past rekeyThreshold
func TestRelationship_GetNewestRekeyableSession(t *testing.T) {
mgr := makeTestRelationshipManager(t)
sb := NewRelationship(mgr, Send, params.GetDefaultE2ESessionParams())
......@@ -261,11 +261,18 @@ func TestRelationship_GetSessionForSending(t *testing.T) {
unconfirmedRekey.partnerPubKey, unconfirmedRekey.partnerSource,
unconfirmedRekey.e2eParams)
sb.sessions[0].negotiationStatus = Unconfirmed
sb.sessions[0].keyState.numkeys = 2000
sb.sessions[0].rekeyThreshold = 1000
sb.sessions[0].keyState.numAvailable = 600
sending := sb.getSessionForSending()
if sending.GetID() != sb.sessions[0].GetID() {
t.Error("got an unexpected session")
}
if sending.Status()!=RekeyNeeded || sending.IsConfirmed(){
t.Errorf("returned session is expected to be 'RekeyNedded' " +
"'Unconfirmed', it is: %s, confirmed: %v", sending.Status(),
sending.IsConfirmed())
}
// Second case: unconfirmed active
unconfirmedActive, _ := makeTestSession()
......@@ -274,12 +281,20 @@ func TestRelationship_GetSessionForSending(t *testing.T) {
unconfirmedActive.partnerPubKey, unconfirmedActive.partnerSource,
unconfirmedActive.e2eParams)
sb.sessions[0].negotiationStatus = Unconfirmed
sb.sessions[0].keyState.numkeys = 2000
sb.sessions[0].rekeyThreshold = 1000
sb.sessions[0].keyState.numAvailable = 2000
sending = sb.getSessionForSending()
if sending.GetID() != sb.sessions[0].GetID() {
t.Error("got an unexpected session")
}
if sending.Status()!=Active || sending.IsConfirmed(){
t.Errorf("returned session is expected to be 'Active' " +
"'Unconfirmed', it is: %s, confirmed: %v", sending.Status(),
sending.IsConfirmed())
}
// Third case: confirmed rekey
confirmedRekey, _ := makeTestSession()
......@@ -287,11 +302,19 @@ func TestRelationship_GetSessionForSending(t *testing.T) {
confirmedRekey.partnerPubKey, confirmedRekey.partnerSource,
confirmedRekey.e2eParams)
sb.sessions[0].negotiationStatus = Confirmed
sb.sessions[0].keyState.numkeys = 2000
sb.sessions[0].rekeyThreshold = 1000
sb.sessions[0].keyState.numAvailable = 600
sending = sb.getSessionForSending()
if sending.GetID() != sb.sessions[0].GetID() {
t.Error("got an unexpected session")
}
if sending.Status()!=RekeyNeeded || !sending.IsConfirmed(){
t.Errorf("returned session is expected to be 'RekeyNeeded' " +
"'Confirmed', it is: %s, confirmed: %v", sending.Status(),
sending.IsConfirmed())
}
// Fourth case: confirmed active
confirmedActive, _ := makeTestSession()
......@@ -300,10 +323,17 @@ func TestRelationship_GetSessionForSending(t *testing.T) {
confirmedActive.e2eParams)
sb.sessions[0].negotiationStatus = Confirmed
sb.sessions[0].keyState.numkeys = 2000
sb.sessions[0].keyState.numAvailable = 2000
sb.sessions[0].rekeyThreshold = 1000
sending = sb.getSessionForSending()
if sending.GetID() != sb.sessions[0].GetID() {
t.Error("got an unexpected session")
t.Errorf("got an unexpected session of state: %s", sending.Status())
}
if sending.Status()!=Active || !sending.IsConfirmed(){
t.Errorf("returned session is expected to be 'Active' " +
"'Confirmed', it is: %s, confirmed: %v", sending.Status(),
sending.IsConfirmed())
}
}
......@@ -386,7 +416,7 @@ func TestSessionBuff_TriggerNegotiation(t *testing.T) {
t.Errorf("should have had zero negotiations: %+v", negotiations)
}
session2, _ := makeTestSession()
// Make only a few keys available to trigger the ttl
// Make only a few keys available to trigger the rekeyThreshold
session2 = sb.AddSession(session2.myPrivKey, session2.partnerPubKey,
session2.partnerPubKey, session2.partnerSource,
session2.e2eParams)
......
......@@ -57,8 +57,8 @@ type Session struct {
//denotes if the other party has confirmed this key
negotiationStatus Negotiation
// Value of the counter at which a rekey is triggered
ttl uint32
// Number of keys used before the system attempts a rekey
rekeyThreshold uint32
// Received Keys dirty bits
// Each bit represents a single Key
......@@ -92,7 +92,7 @@ type SessionDisk struct {
Confirmation uint8
// Number of keys usable before rekey
TTL uint32
RekeyThreshold uint32
}
/*CONSTRUCTORS*/
......@@ -101,6 +101,11 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey
baseKey *cyclic.Int, trigger SessionID, relationshipFingerprint []byte,
e2eParams params.E2ESessionParams) *Session {
if e2eParams.MinKeys<10{
jww.FATAL.Panicf("Cannot create a session with a minnimum number " +
"of keys less than 10")
}
confirmation := Unconfirmed
if t == Receive {
confirmation = Confirmed
......@@ -127,7 +132,7 @@ func newSession(ship *relationship, t RelationshipType, myPrivKey, partnerPubKey
t,
session.baseKey.TextVerbose(16, 0),
session.relationshipFingerprint,
session.ttl,
session.rekeyThreshold,
session.myPrivKey.TextVerbose(16, 0),
session.partnerPubKey.TextVerbose(16, 0))
......@@ -287,7 +292,7 @@ func (s *Session) marshal() ([]byte, error) {
sd.Confirmation = uint8(s.negotiationStatus)
}
sd.TTL = s.ttl
sd.RekeyThreshold = s.rekeyThreshold
return json.Marshal(&sd)
}
......@@ -310,7 +315,7 @@ func (s *Session) unmarshal(b []byte) error {
s.myPrivKey = grp.NewIntFromBytes(sd.MyPrivKey)
s.partnerPubKey = grp.NewIntFromBytes(sd.PartnerPubKey)
s.negotiationStatus = Negotiation(sd.Confirmation)
s.ttl = sd.TTL
s.rekeyThreshold = sd.RekeyThreshold
s.relationshipFingerprint = sd.RelationshipFingerprint
copy(s.partnerSource[:], sd.Trigger)
......@@ -357,6 +362,7 @@ func (s *Session) Status() Status {
// copy the num available so it stays consistent as this function does its
// checks
numAvailable := s.keyState.GetNumAvailable()
numUsed := s.keyState.GetNumUsed()
if numAvailable == 0 {
return RekeyEmpty
......@@ -364,7 +370,7 @@ func (s *Session) Status() Status {
return Empty
// do not need to make a copy of getNumKeys becasue it is static and
// only used once
} else if numAvailable <= s.keyState.GetNumKeys()-s.ttl {
} else if numUsed >= s.rekeyThreshold {
return RekeyNeeded
} else {
return Active
......@@ -449,11 +455,11 @@ func (s *Session) triggerNegotiation() bool {
// case, such double locking is preferable because the majority of the time,
// the checked cases will turn out to be false.
s.mux.RLock()
// If we've used more keys than the TTL, it's time for a rekey
if s.keyState.GetNumUsed() >= s.ttl && s.negotiationStatus == Confirmed {
// If we've used more keys than the RekeyThreshold, it's time for a rekey
if s.keyState.GetNumUsed() >= s.rekeyThreshold && s.negotiationStatus == Confirmed {
s.mux.RUnlock()
s.mux.Lock()
if s.keyState.GetNumUsed() >= s.ttl && s.negotiationStatus == Confirmed {
if s.keyState.GetNumUsed() >= s.rekeyThreshold && s.negotiationStatus == Confirmed {
//partnerSource a rekey to create a new session
s.negotiationStatus = NewSessionTriggered
// no save is make after the update because we do not want this state
......@@ -547,18 +553,17 @@ func (s *Session) generate(kv *versioned.KV) *versioned.KV {
p := s.e2eParams
h, _ := hash.NewCMixHash()
//generate ttl and keying info
//generate rekeyThreshold and keying info
numKeys := uint32(randomness.RandInInterval(big.NewInt(
int64(p.MaxKeys-p.MinKeys)),
s.baseKey.Bytes(), h).Int64() + int64(p.MinKeys))
keysTTL := uint32(p.NumRekeys)
//ensure that enough keys are remaining to rekey
if numKeys-keysTTL < uint32(p.NumRekeys) {
numKeys = keysTTL + uint32(p.NumRekeys)
}
// start rekeying when 75% of keys have been used
s.rekeyThreshold = (numKeys*3)/4
s.ttl = uint32(s.e2eParams.NumRekeys)
// the total number of keys should be the number of rekeys plus the
// number of keys to use
numKeys = numKeys + uint32(s.e2eParams.NumRekeys)
//create the new state vectors. This will cause disk operations storing them
......
......@@ -61,9 +61,9 @@ func TestSession_generate_noPrivateKeyReceive(t *testing.T) {
t.Errorf("generated base key does not match expected base key")
}
//verify the ttl was generated
if s.ttl == 0 {
t.Errorf("ttl not generated")
//verify the rekeyThreshold was generated
if s.rekeyThreshold == 0 {
t.Errorf("rekeyThreshold not generated")
}
//verify keystates where created
......@@ -122,9 +122,9 @@ func TestSession_generate_PrivateKeySend(t *testing.T) {
t.Errorf("generated base key does not match expected base key")
}
//verify the ttl was generated
if s.ttl == 0 {
t.Errorf("ttl not generated")
//verify the rekeyThreshold was generated
if s.rekeyThreshold == 0 {
t.Errorf("rekeyThreshold not generated")
}
//verify keystates where created
......@@ -161,8 +161,8 @@ func TestNewSession(t *testing.T) {
if sessionB.relationship == nil {
t.Error("newSession should populate relationship")
}
if sessionB.ttl == 0 {
t.Error("newSession should populate ttl")
if sessionB.rekeyThreshold == 0 {
t.Error("newSession should populate rekeyThreshold")
}
}
......@@ -193,8 +193,8 @@ func TestSession_Load(t *testing.T) {
if sessionB.relationship == nil {
t.Error("load should populate relationship")
}
if sessionB.ttl == 0 {
t.Error("load should populate ttl")
if sessionB.rekeyThreshold == 0 {
t.Error("load should populate rekeyThreshold")
}
}
......@@ -440,14 +440,15 @@ func TestSession_Status(t *testing.T) {
if s.Status() != Empty {
t.Error("Status should have been empty")
}
// Passing the ttl should result in a rekey being needed
s.keyState.numAvailable = s.keyState.numkeys - s.ttl
// Passing the rekeyThreshold should result in a rekey being needed
s.keyState.numAvailable = s.keyState.numkeys - s.rekeyThreshold
if s.Status() != RekeyNeeded {
t.Error("Just past the ttl, rekey should be needed")
t.Error("Just past the rekeyThreshold, rekey should be needed")
}
s.keyState.numAvailable = s.keyState.numkeys
s.rekeyThreshold = 450
if s.Status() != Active {
t.Error("If all keys available, session should be active")
t.Errorf("If all keys available, session should be active, recieved: %s", s.Status())
}
}
......@@ -469,7 +470,7 @@ func TestSession_SetNegotiationStatus(t *testing.T) {
t.Fatal(err)
}
if !object.Timestamp.After(now) {
t.Error("save didn't occur after switching Sending to Sent")
t.Errorf("save didn't occur after switching Sending to Sent")
}
now = time.Now()
......@@ -483,7 +484,7 @@ func TestSession_SetNegotiationStatus(t *testing.T) {
t.Fatal(err)
}
if !object.Timestamp.After(now) {
t.Error("save didn't occur after switching Sent to Confirmed")
t.Errorf("save didn't occur after switching Sent to Confirmed")
}
now = time.Now()
......@@ -535,10 +536,10 @@ func TestSession_SetNegotiationStatus(t *testing.T) {
// Tests that TriggerNegotiation makes only valid state transitions
func TestSession_TriggerNegotiation(t *testing.T) {
s, _ := makeTestSession()
// Set up num keys used to be > ttl: should partnerSource negotiation
// Set up num keys used to be > rekeyThreshold: should partnerSource negotiation
s.keyState.numAvailable = 50
s.keyState.numkeys = 100
s.ttl = 49
s.rekeyThreshold = 49
s.negotiationStatus = Confirmed
if !s.triggerNegotiation() {
......@@ -548,8 +549,8 @@ func TestSession_TriggerNegotiation(t *testing.T) {
t.Errorf("negotiationStatus: got %v, expected %v", s.negotiationStatus, NewSessionTriggered)
}
// Set up num keys used to be = ttl: should partnerSource negotiation
s.ttl = 50
// Set up num keys used to be = rekeyThreshold: should partnerSource negotiation
s.rekeyThreshold = 50
s.negotiationStatus = Confirmed
if !s.triggerNegotiation() {
......@@ -559,8 +560,8 @@ func TestSession_TriggerNegotiation(t *testing.T) {
t.Errorf("negotiationStatus: got %v, expected %v", s.negotiationStatus, NewSessionTriggered)
}
// Set up num keys used to be < ttl: shouldn't partnerSource negotiation
s.ttl = 51
// Set up num keys used to be < rekeyThreshold: shouldn't partnerSource negotiation
s.rekeyThreshold = 51
s.negotiationStatus = Confirmed
if s.triggerNegotiation() {
......@@ -633,7 +634,7 @@ func makeTestSession() (*Session, *context) {
kv: kv,
t: Receive,
negotiationStatus: Confirmed,
ttl: 5,
rekeyThreshold: 5,
}
var err error
s.keyState, err = newStateVector(s.kv,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment