1 // This file is under BSD License 2.0
3 // Sync protocol for p≡p
4 // Copyright (c) 2016-2019, p≡p foundation
6 // Written by Volker Birk
11 // all messages have a timestamp, time out and are removed after timeout
13 fsm KeySync 1, threshold=300 {
20 do newChallengeAndNegotiationBase;
26 state Sole timeout=off {
35 on CannotDecrypt { // cry baby
41 debug > this is our own Beacon; ignore
48 else /* we are requester */ {
50 do tellWeAreNotGrouped;
51 // requester is sending NegotiationRequest
52 send NegotiationRequest;
58 // we get this from another sole device
59 on NegotiationRequest {
60 if sameChallenge { // challenge accepted
62 // this is our own NegotiationRequest; ignore
66 // offerer is accepting by confirming NegotiationOpen
68 go HandshakingOfferer;
73 // we get this from an existing device group
74 on NegotiationRequestGrouped {
75 if sameChallenge { // challenge accepted
77 // offerer is accepting by confirming NegotiationOpen
83 on NegotiationOpen if sameNegotiationAndPartner {
84 // requester is receiving NegotiationOpen
86 go HandshakingRequester;
90 // handshaking without existing Device group
91 state HandshakingOfferer timeout=600 {
101 on Rollback if sameNegotiationAndPartner
104 // Reject is CommitReject
111 on CommitReject if sameNegotiationAndPartner {
116 // Accept means init Phase1Commit
119 send CommitAcceptOfferer;
120 go HandshakingPhase1Offerer;
123 // got a CommitAccept from requester
124 on CommitAcceptRequester if sameNegotiationAndPartner
125 go HandshakingPhase2Offerer;
128 // handshaking without existing Device group
129 state HandshakingRequester timeout=600 {
131 do showSoleHandshake;
133 // Cancel is Rollback
139 on Rollback if sameNegotiationAndPartner
142 // Reject is CommitReject
149 on CommitReject if sameNegotiationAndPartner {
154 // Accept means init Phase1Commit
157 send CommitAcceptRequester;
158 go HandshakingPhase1Requester;
161 // got a CommitAccept from offerer
162 on CommitAcceptOfferer if sameNegotiationAndPartner
163 go HandshakingPhase2Requester;
166 state HandshakingPhase1Offerer {
167 on Rollback if sameNegotiationAndPartner {
172 on CommitReject if sameNegotiationAndPartner {
178 on CommitAcceptRequester if sameNegotiationAndPartner {
179 go FormingGroupOfferer;
183 state HandshakingPhase1Requester {
184 on Rollback if sameNegotiationAndPartner {
189 on CommitReject if sameNegotiationAndPartner {
195 on CommitAcceptOfferer if sameNegotiationAndPartner {
196 go FormingGroupRequester;
200 state HandshakingPhase2Offerer {
214 send CommitAcceptOfferer;
215 go FormingGroupOfferer;
219 state HandshakingPhase2Requester {
233 send CommitAcceptRequester;
234 go FormingGroupRequester;
238 state FormingGroupOfferer {
241 send OwnKeysOfferer; // we're not grouped yet, this is our own keys
252 on OwnKeysRequester if sameNegotiationAndPartner {
254 do receivedKeysAreDefaultKeys;
260 state FormingGroupRequester {
269 on OwnKeysOfferer if sameNegotiationAndPartner {
272 do ownKeysAreDefaultKeys;
273 send OwnKeysRequester;
279 state Grouped timeout=off {
281 do newChallengeAndNegotiationBase;
285 on GroupKeysUpdate if fromGroupMember // double check
290 send GroupKeysUpdate;
296 send NegotiationRequestGrouped;
300 on NegotiationOpen if sameNegotiationAndPartner {
304 go HandshakingGrouped;
310 go HandshakingGrouped;
313 on GroupTrustThisKey if fromGroupMember // double check
316 on GroupKeyResetRequired {
321 // this is for a leaving group member
322 on GroupKeyResetRequiredAndDisable {
323 send InitUnledGroupKeyReset;
324 go DisableOnInitUnledGroupKeyReset;
327 on InitUnledGroupKeyReset {
328 // unled group key reset; new group keys will be elected
329 do unledGroupKeyReset;
333 on GroupKeyReset if fromGroupMember { // double check
335 if isLedGroupKeyReset {
336 // led group key reset is executed without questions
337 do receivedKeysAreDefaultKeys;
340 // unled group key reset; election takes place
342 // this is already the case:
343 // do ownKeysAreDefaultKeys;
346 do receivedKeysAreDefaultKeys;
352 state DisableOnInitUnledGroupKeyReset {
353 on InitUnledGroupKeyReset
357 // sole device handshaking with group
358 state HandshakingToJoin {
360 do showJoinGroupHandshake;
362 // Cancel is Rollback
368 on Rollback if sameNegotiationAndPartner
371 // Reject is CommitReject
378 on CommitAcceptForGroup if sameNegotiationAndPartner
379 go HandshakingToJoinPhase2;
381 on CommitReject if sameNegotiationAndPartner {
386 // Accept is Phase1Commit
390 go HandshakingToJoinPhase1;
394 state HandshakingToJoinPhase1 {
395 on Rollback if sameNegotiationAndPartner
398 on CommitReject if sameNegotiationAndPartner {
403 on CommitAcceptForGroup if sameNegotiationAndPartner
407 state HandshakingToJoinPhase2 {
427 on GroupKeysForNewMember if sameNegotiationAndPartner {
429 do receivedKeysAreDefaultKeys;
431 send GroupKeysAndClose;
437 state HandshakingGrouped {
439 do showGroupedHandshake;
441 // Cancel is Rollback
447 on Rollback if sameNegotiationAndPartner
450 // Reject is CommitReject
456 on CommitReject if sameNegotiationAndPartner
459 // Accept is Phase1Commit
462 go HandshakingGroupedPhase1;
465 on CommitAccept if sameNegotiationAndPartner
466 go HandshakingGroupedPhase2;
468 on GroupTrustThisKey if fromGroupMember { // double check
474 on GroupKeysUpdate if fromGroupMember // double check
478 state HandshakingGroupedPhase1 {
480 send GroupTrustThisKey;
481 send CommitAcceptForGroup;
484 on Rollback if sameNegotiationAndPartner
487 on CommitReject if sameNegotiationAndPartner
490 on CommitAccept if sameNegotiationAndPartner {
492 send GroupKeysForNewMember;
493 do showDeviceAccepted;
497 on GroupTrustThisKey if fromGroupMember // double check
500 on GroupKeysUpdate if fromGroupMember // double check
503 on GroupKeysAndClose if fromGroupMember { // double check
509 state HandshakingGroupedPhase2 {
522 send GroupTrustThisKey;
524 send GroupKeysForNewMember;
525 do showDeviceAccepted;
529 on GroupTrustThisKey if fromGroupMember // double check
532 on GroupKeysUpdate if fromGroupMember // double check
535 on GroupKeysAndClose if fromGroupMember { // double check
545 // beacons are always broadcasted
547 message Beacon 2, type=broadcast, security=unencrypted {
549 auto Version version;
552 message NegotiationRequest 3, security=untrusted {
554 auto Version version;
555 field TID negotiation;
559 message NegotiationOpen 4, security=untrusted {
560 auto Version version;
561 field TID negotiation;
564 message Rollback 5, security=untrusted {
565 field TID negotiation;
568 message CommitReject 6, security=untrusted {
569 field TID negotiation;
572 message CommitAcceptOfferer 7, security=untrusted {
573 field TID negotiation;
576 message CommitAcceptRequester 8, security=untrusted {
577 field TID negotiation;
580 message CommitAccept 9, security=untrusted {
581 field TID negotiation;
584 message CommitAcceptForGroup 10, security=untrusted {
585 field TID negotiation;
588 // default: security=truste
589 // messages are only accepted when coming from the device group
590 message GroupTrustThisKey 11 {
592 field TID negotiation;
596 message GroupKeysForNewMember 12, security=attach_own_keys_for_new_member {
597 field IdentityList ownIdentities;
600 message GroupKeysAndClose 13, security=attach_own_keys_for_new_member {
601 field IdentityList ownIdentities;
604 message OwnKeysOfferer 14, security=attach_own_keys_for_new_member {
605 field IdentityList ownIdentities;
608 message OwnKeysRequester 15, security=attach_own_keys_for_new_member {
609 field IdentityList ownIdentities;
613 message NegotiationRequestGrouped 16, security=untrusted {
615 auto Version version;
616 field TID negotiation;
620 message GroupHandshake 17 {
621 field TID negotiation;
626 message GroupKeysUpdate 18, security=attach_own_keys_for_group {
627 field IdentityList ownIdentities;
630 // initiate unled group key reset
631 message InitUnledGroupKeyReset 19 {
634 message GroupKeyReset 20, security=attach_own_keys_for_group {
636 // set this flag for led group key reset; delivered group keys will
637 // be accepted by all group members; if not set group keys will be
640 field IdentityList ownIdentities;