put sync.fsm excerpt to external file, update it from sources, cut and add lines breaks avoid too long lines
parent
ae053a06a1
commit
5f55f76692
@ -0,0 +1,694 @@
|
||||
// This file is under BSD License 2.0
|
||||
|
||||
// Sync protocol for p≡p
|
||||
// Copyright (c) 2016-2020, p≡p foundation
|
||||
|
||||
// Written by Volker Birk
|
||||
|
||||
include ./fsm.yml2
|
||||
|
||||
protocol Sync 1 {
|
||||
// all messages have a timestamp,
|
||||
// time out and are removed after timeout
|
||||
|
||||
fsm KeySync 1, threshold=300 {
|
||||
version 1, 2;
|
||||
|
||||
state InitState {
|
||||
on Init {
|
||||
if deviceGrouped {
|
||||
send SynchronizeGroupKeys;
|
||||
go Grouped;
|
||||
}
|
||||
do newChallengeAndNegotiationBase;
|
||||
debug > initial Beacon
|
||||
send Beacon;
|
||||
go Sole;
|
||||
}
|
||||
}
|
||||
|
||||
state Sole timeout=off {
|
||||
on Init {
|
||||
do showBeingSole;
|
||||
}
|
||||
|
||||
on KeyGen {
|
||||
debug > key generated
|
||||
send Beacon;
|
||||
}
|
||||
|
||||
on CannotDecrypt {
|
||||
debug > cry, baby
|
||||
send Beacon;
|
||||
}
|
||||
|
||||
on Beacon {
|
||||
if sameChallenge {
|
||||
debug > this is our own Beacon; ignore
|
||||
}
|
||||
else {
|
||||
if weAreOfferer {
|
||||
do useOwnChallenge;
|
||||
debug > we are Offerer
|
||||
send Beacon;
|
||||
}
|
||||
else /* we are requester */ {
|
||||
do openNegotiation;
|
||||
do tellWeAreNotGrouped;
|
||||
// requester is sending NegotiationRequest
|
||||
do useOwnResponse;
|
||||
send NegotiationRequest;
|
||||
do useOwnChallenge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we get this from another sole device
|
||||
on NegotiationRequest {
|
||||
if sameChallenge { // challenge accepted
|
||||
do storeNegotiation;
|
||||
// offerer is accepting by confirming NegotiationOpen
|
||||
// repeating response is implicit
|
||||
send NegotiationOpen;
|
||||
go HandshakingOfferer;
|
||||
}
|
||||
}
|
||||
|
||||
// we get this from an existing device group
|
||||
on NegotiationRequestGrouped {
|
||||
if sameChallenge { // challenge accepted
|
||||
do storeNegotiation;
|
||||
// offerer is accepting by confirming NegotiationOpen
|
||||
// repeating response is implicit
|
||||
send NegotiationOpen;
|
||||
go HandshakingToJoin;
|
||||
}
|
||||
}
|
||||
|
||||
on NegotiationOpen {
|
||||
if sameResponse {
|
||||
debug > Requester is receiving NegotiationOpen
|
||||
do storeNegotiation;
|
||||
go HandshakingRequester;
|
||||
}
|
||||
else {
|
||||
debug > cannot approve NegotiationOpen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handshaking without existing Device group
|
||||
state HandshakingOfferer timeout=600 {
|
||||
on Init
|
||||
do showSoleHandshake;
|
||||
|
||||
// Cancel is Rollback
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Rollback {
|
||||
if sameNegotiation
|
||||
go Sole;
|
||||
}
|
||||
|
||||
// Reject is CommitReject
|
||||
on Reject {
|
||||
send CommitReject;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
}
|
||||
|
||||
// Accept means init Phase1Commit
|
||||
on Accept {
|
||||
do trustThisKey;
|
||||
go HandshakingPhase1Offerer;
|
||||
}
|
||||
|
||||
// got a CommitAccept from requester
|
||||
on CommitAcceptRequester {
|
||||
if sameNegotiation
|
||||
go HandshakingPhase2Offerer;
|
||||
}
|
||||
}
|
||||
|
||||
// handshaking without existing Device group
|
||||
state HandshakingRequester timeout=600 {
|
||||
on Init
|
||||
do showSoleHandshake;
|
||||
|
||||
// Cancel is Rollback
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Rollback {
|
||||
if sameNegotiation
|
||||
go Sole;
|
||||
}
|
||||
|
||||
// Reject is CommitReject
|
||||
on Reject {
|
||||
send CommitReject;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
}
|
||||
|
||||
// Accept means init Phase1Commit
|
||||
on Accept {
|
||||
do trustThisKey;
|
||||
send CommitAcceptRequester;
|
||||
go HandshakingPhase1Requester;
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingPhase1Offerer {
|
||||
on Rollback {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
go Sole;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitAcceptRequester {
|
||||
if sameNegotiation {
|
||||
send CommitAcceptOfferer;
|
||||
go FormingGroupOfferer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingPhase1Requester {
|
||||
on Rollback {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
go Sole;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitAcceptOfferer {
|
||||
if sameNegotiation {
|
||||
do prepareOwnKeys;
|
||||
send OwnKeysRequester;
|
||||
go FormingGroupRequester;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingPhase2Offerer {
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Reject {
|
||||
send CommitReject;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
|
||||
on Accept {
|
||||
do trustThisKey;
|
||||
send CommitAcceptOfferer;
|
||||
go FormingGroupOfferer;
|
||||
}
|
||||
}
|
||||
|
||||
state FormingGroupOfferer {
|
||||
on Init {
|
||||
// we need to keep in memory which keys
|
||||
// we have before forming a new group
|
||||
do prepareOwnKeys;
|
||||
do backupOwnKeys;
|
||||
}
|
||||
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Rollback
|
||||
go Sole;
|
||||
|
||||
on OwnKeysRequester {
|
||||
if sameNegotiationAndPartner {
|
||||
do saveGroupKeys;
|
||||
do receivedKeysAreDefaultKeys;
|
||||
// send the keys we had before forming a new group
|
||||
do prepareOwnKeysFromBackup;
|
||||
send OwnKeysOfferer;
|
||||
do showGroupCreated;
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state FormingGroupRequester {
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Rollback
|
||||
go Sole;
|
||||
|
||||
on OwnKeysOfferer {
|
||||
if sameNegotiation {
|
||||
do saveGroupKeys;
|
||||
do prepareOwnKeys;
|
||||
do ownKeysAreDefaultKeys;
|
||||
do showGroupCreated;
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state Grouped timeout=off {
|
||||
on Init {
|
||||
do newChallengeAndNegotiationBase;
|
||||
do showBeingInGroup;
|
||||
}
|
||||
|
||||
on CannotDecrypt {
|
||||
debug > cry, baby
|
||||
send SynchronizeGroupKeys;
|
||||
}
|
||||
|
||||
on SynchronizeGroupKeys {
|
||||
do prepareOwnKeys;
|
||||
send GroupKeysUpdate;
|
||||
}
|
||||
|
||||
on GroupKeysUpdate {
|
||||
if fromGroupMember // double check
|
||||
do saveGroupKeys;
|
||||
}
|
||||
|
||||
on KeyGen {
|
||||
do prepareOwnKeys;
|
||||
send GroupKeysUpdate;
|
||||
}
|
||||
|
||||
on Beacon {
|
||||
do openNegotiation;
|
||||
do tellWeAreGrouped;
|
||||
do useOwnResponse;
|
||||
send NegotiationRequestGrouped;
|
||||
do useOwnChallenge;
|
||||
}
|
||||
|
||||
on NegotiationOpen {
|
||||
if sameResponse {
|
||||
do storeNegotiation;
|
||||
do useThisKey;
|
||||
send GroupHandshake;
|
||||
go HandshakingGrouped;
|
||||
}
|
||||
else {
|
||||
debug > cannot approve NegotiationOpen
|
||||
}
|
||||
}
|
||||
|
||||
on GroupHandshake {
|
||||
do storeNegotiation;
|
||||
do storeThisKey;
|
||||
go HandshakingGrouped;
|
||||
}
|
||||
|
||||
on GroupTrustThisKey {
|
||||
if fromGroupMember // double check
|
||||
do trustThisKey;
|
||||
}
|
||||
|
||||
on LeaveDeviceGroup {
|
||||
send InitUnledGroupKeyReset;
|
||||
do disable;
|
||||
do resetOwnKeysUngrouped;
|
||||
}
|
||||
|
||||
on InitUnledGroupKeyReset {
|
||||
debug > unled group key reset; new group keys will be elected
|
||||
do useOwnResponse;
|
||||
send ElectGroupKeyResetLeader;
|
||||
go GroupKeyResetElection;
|
||||
}
|
||||
}
|
||||
|
||||
state GroupKeyResetElection {
|
||||
on ElectGroupKeyResetLeader {
|
||||
if sameResponse {
|
||||
// the first one is from us, we're leading this
|
||||
do resetOwnGroupedKeys;
|
||||
go Grouped;
|
||||
}
|
||||
else {
|
||||
// the first one is not from us
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sole device handshaking with group
|
||||
state HandshakingToJoin {
|
||||
on Init
|
||||
do showJoinGroupHandshake;
|
||||
|
||||
// Cancel is Rollback
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Rollback {
|
||||
if sameNegotiation
|
||||
go Sole;
|
||||
}
|
||||
|
||||
// Reject is CommitReject
|
||||
on Reject {
|
||||
send CommitReject;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
|
||||
on CommitAcceptForGroup {
|
||||
if sameNegotiation
|
||||
go HandshakingToJoinPhase2;
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
}
|
||||
|
||||
// Accept is Phase1Commit
|
||||
on Accept {
|
||||
do trustThisKey;
|
||||
go HandshakingToJoinPhase1;
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingToJoinPhase1 {
|
||||
on Rollback {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
go Sole;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitAcceptForGroup {
|
||||
if sameNegotiation {
|
||||
send CommitAccept;
|
||||
go JoiningGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingToJoinPhase2 {
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Sole;
|
||||
}
|
||||
|
||||
on Reject {
|
||||
send CommitReject;
|
||||
do disable;
|
||||
go End;
|
||||
}
|
||||
|
||||
on Accept {
|
||||
do trustThisKey;
|
||||
send CommitAccept;
|
||||
go JoiningGroup;
|
||||
}
|
||||
}
|
||||
|
||||
state JoiningGroup {
|
||||
on Init {
|
||||
// we need to keep in memory which keys
|
||||
// we have before joining
|
||||
do prepareOwnKeys;
|
||||
do backupOwnKeys;
|
||||
}
|
||||
on GroupKeysForNewMember {
|
||||
if sameNegotiationAndPartner {
|
||||
do saveGroupKeys;
|
||||
do receivedKeysAreDefaultKeys;
|
||||
// send the keys we had before joining
|
||||
do prepareOwnKeysFromBackup;
|
||||
send GroupKeysAndClose;
|
||||
do showDeviceAdded;
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingGrouped {
|
||||
on Init
|
||||
do showGroupedHandshake;
|
||||
|
||||
// Cancel is Rollback
|
||||
on Cancel {
|
||||
send Rollback;
|
||||
go Grouped;
|
||||
}
|
||||
|
||||
on Rollback {
|
||||
if sameNegotiation
|
||||
go Grouped;
|
||||
}
|
||||
|
||||
// Reject is CommitReject
|
||||
on Reject {
|
||||
send CommitReject;
|
||||
go Grouped;
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation
|
||||
go Grouped;
|
||||
}
|
||||
|
||||
// Accept is Phase1Commit
|
||||
on Accept {
|
||||
do trustThisKey;
|
||||
go HandshakingGroupedPhase1;
|
||||
}
|
||||
|
||||
on GroupTrustThisKey {
|
||||
if fromGroupMember { // double check
|
||||
do trustThisKey;
|
||||
if sameNegotiation
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
|
||||
on GroupKeysUpdate {
|
||||
if fromGroupMember // double check
|
||||
do saveGroupKeys;
|
||||
}
|
||||
}
|
||||
|
||||
state HandshakingGroupedPhase1 {
|
||||
on Init {
|
||||
send GroupTrustThisKey;
|
||||
send CommitAcceptForGroup;
|
||||
}
|
||||
|
||||
on Rollback {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitReject {
|
||||
if sameNegotiation {
|
||||
do untrustThisKey;
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
|
||||
on CommitAccept {
|
||||
if sameNegotiation {
|
||||
do prepareOwnKeys;
|
||||
send GroupKeysForNewMember;
|
||||
do showDeviceAccepted;
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
|
||||
on GroupTrustThisKey {
|
||||
if fromGroupMember // double check
|
||||
do trustThisKey;
|
||||
}
|
||||
|
||||
on GroupKeysUpdate {
|
||||
if fromGroupMember // double check
|
||||
do saveGroupKeys;
|
||||
}
|
||||
|
||||
on GroupKeysAndClose {
|
||||
if fromGroupMember { // double check
|
||||
// do not save GroupKeys as default keys; key data is
|
||||
// already imported
|
||||
go Grouped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
external Accept 129;
|
||||
external Reject 130;
|
||||
external Cancel 131;
|
||||
|
||||
// beacons are always broadcasted
|
||||
|
||||
message Beacon 2, type=broadcast,
|
||||
ratelimit=10, security=unencrypted {
|
||||
field TID challenge;
|
||||
auto Version version;
|
||||
}
|
||||
|
||||
message NegotiationRequest 3, security=untrusted {
|
||||
field TID challenge;
|
||||
field TID response;
|
||||
auto Version version;
|
||||
field TID negotiation;
|
||||
field bool is_group;
|
||||
}
|
||||
|
||||
message NegotiationOpen 4, security=untrusted {
|
||||
field TID response;
|
||||
auto Version version;
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
message Rollback 5, security=untrusted {
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
message CommitReject 6, security=untrusted {
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
message CommitAcceptOfferer 7, security=untrusted {
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
message CommitAcceptRequester 8, security=untrusted {
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
message CommitAccept 9, security=untrusted {
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
message CommitAcceptForGroup 10, security=untrusted {
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
// default: security=trusted
|
||||
// messages are only accepted when coming from the device group
|
||||
message GroupTrustThisKey 11 {
|
||||
field Hash key;
|
||||
field TID negotiation;
|
||||
}
|
||||
|
||||
// trust in future
|
||||
message GroupKeysForNewMember 12,
|
||||
security=attach_own_keys_for_new_member {
|
||||
field IdentityList ownIdentities;
|
||||
}
|
||||
|
||||
message GroupKeysAndClose 13,
|
||||
security=attach_own_keys_for_group {
|
||||
field IdentityList ownIdentities;
|
||||
}
|
||||
|
||||
message OwnKeysOfferer 14, security=attach_own_keys_for_group {
|
||||
field IdentityList ownIdentities;
|
||||
}
|
||||
|
||||
message OwnKeysRequester 15,
|
||||
security=attach_own_keys_for_new_member {
|
||||
field IdentityList ownIdentities;
|
||||
}
|
||||
|
||||
// grouped handshake
|
||||
message NegotiationRequestGrouped 16, security=untrusted {
|
||||
field TID challenge;
|
||||
field TID response;
|
||||
auto Version version;
|
||||
field TID negotiation;
|
||||
field bool is_group;
|
||||
}
|
||||
|
||||
message GroupHandshake 17 {
|
||||
field TID negotiation;
|
||||
field Hash key;
|
||||
}
|
||||
|
||||
// update group
|
||||
message GroupKeysUpdate 18, security=attach_own_keys_for_group {
|
||||
field IdentityList ownIdentities;
|
||||
}
|
||||
|
||||
// initiate unled group key reset
|
||||
message InitUnledGroupKeyReset 19 {
|
||||
}
|
||||
|
||||
message ElectGroupKeyResetLeader 20 {
|
||||
field TID response;
|
||||
}
|
||||
|
||||
message SynchronizeGroupKeys 21, ratelimit=60 {
|
||||
}
|
||||
|
||||
[...]
|
||||
}
|
||||
|
||||
[...]
|
||||
|
||||
}
|
Loading…
Reference in New Issue