You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

753 lines
20 KiB

4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
  1. // This file is under BSD License 2.0
  2. // Sync protocol for p≡p
  3. // Copyright (c) 2016-2020, p≡p foundation
  4. // Written by Volker Birk
  5. include ./fsm.yml2
  6. protocol Sync 1 {
  7. // all messages have a timestamp, time out and are removed after timeout
  8. fsm KeySync 1, threshold=300 {
  9. version 1, 2;
  10. state InitState {
  11. on Init {
  12. if deviceGrouped {
  13. send SynchronizeGroupKeys;
  14. go Grouped;
  15. }
  16. do newChallengeAndNegotiationBase;
  17. debug > initial Beacon
  18. send Beacon;
  19. go Sole;
  20. }
  21. }
  22. state Sole timeout=off {
  23. on Init {
  24. do showBeingSole;
  25. }
  26. on KeyGen {
  27. debug > key generated
  28. send Beacon;
  29. }
  30. on CannotDecrypt {
  31. debug > cry, baby
  32. send Beacon;
  33. }
  34. on Beacon {
  35. if sameChallenge {
  36. debug > this is our own Beacon; ignore
  37. }
  38. else {
  39. if weAreOfferer {
  40. do useOwnChallenge;
  41. debug > we are Offerer
  42. send Beacon;
  43. }
  44. else /* we are requester */ {
  45. do openNegotiation;
  46. do tellWeAreNotGrouped;
  47. // requester is sending NegotiationRequest
  48. do useOwnResponse;
  49. send NegotiationRequest;
  50. do useOwnChallenge;
  51. }
  52. }
  53. }
  54. // we get this from another sole device
  55. on NegotiationRequest {
  56. if sameChallenge { // challenge accepted
  57. do storeNegotiation;
  58. // offerer is accepting by confirming NegotiationOpen
  59. // repeating response is implicit
  60. send NegotiationOpen;
  61. go HandshakingOfferer;
  62. }
  63. }
  64. // we get this from an existing device group
  65. on NegotiationRequestGrouped {
  66. if sameChallenge { // challenge accepted
  67. do storeNegotiation;
  68. // offerer is accepting by confirming NegotiationOpen
  69. // repeating response is implicit
  70. send NegotiationOpen;
  71. go HandshakingToJoin;
  72. }
  73. }
  74. on NegotiationOpen {
  75. if sameResponse {
  76. debug > Requester is receiving NegotiationOpen
  77. do storeNegotiation;
  78. go HandshakingRequester;
  79. }
  80. else {
  81. debug > cannot approve NegotiationOpen
  82. }
  83. }
  84. }
  85. // handshaking without existing Device group
  86. state HandshakingOfferer timeout=600 {
  87. on Init
  88. do showSoleHandshake;
  89. // Cancel is Rollback
  90. on Cancel {
  91. send Rollback;
  92. go Sole;
  93. }
  94. on Rollback {
  95. if sameNegotiation
  96. go Sole;
  97. }
  98. // Reject is CommitReject
  99. on Reject {
  100. send CommitReject;
  101. do disable;
  102. go End;
  103. }
  104. on CommitReject {
  105. if sameNegotiation {
  106. do disable;
  107. go End;
  108. }
  109. }
  110. // Accept means init Phase1Commit
  111. on Accept {
  112. do trustThisKey;
  113. go HandshakingPhase1Offerer;
  114. }
  115. // got a CommitAccept from requester
  116. on CommitAcceptRequester {
  117. if sameNegotiation
  118. go HandshakingPhase2Offerer;
  119. }
  120. }
  121. // handshaking without existing Device group
  122. state HandshakingRequester timeout=600 {
  123. on Init
  124. do showSoleHandshake;
  125. // Cancel is Rollback
  126. on Cancel {
  127. send Rollback;
  128. go Sole;
  129. }
  130. on Rollback {
  131. if sameNegotiation
  132. go Sole;
  133. }
  134. // Reject is CommitReject
  135. on Reject {
  136. send CommitReject;
  137. do disable;
  138. go End;
  139. }
  140. on CommitReject {
  141. if sameNegotiation {
  142. do disable;
  143. go End;
  144. }
  145. }
  146. // Accept means init Phase1Commit
  147. on Accept {
  148. do trustThisKey;
  149. send CommitAcceptRequester;
  150. go HandshakingPhase1Requester;
  151. }
  152. }
  153. state HandshakingPhase1Offerer {
  154. on Rollback {
  155. if sameNegotiation {
  156. do untrustThisKey;
  157. go Sole;
  158. }
  159. }
  160. on CommitReject {
  161. if sameNegotiation {
  162. do untrustThisKey;
  163. do disable;
  164. go End;
  165. }
  166. }
  167. on CommitAcceptRequester {
  168. if sameNegotiation {
  169. send CommitAcceptOfferer;
  170. go FormingGroupOfferer;
  171. }
  172. }
  173. }
  174. state HandshakingPhase1Requester {
  175. on Rollback {
  176. if sameNegotiation {
  177. do untrustThisKey;
  178. go Sole;
  179. }
  180. }
  181. on CommitReject {
  182. if sameNegotiation {
  183. do untrustThisKey;
  184. do disable;
  185. go End;
  186. }
  187. }
  188. on CommitAcceptOfferer {
  189. if sameNegotiation {
  190. do prepareOwnKeys;
  191. send OwnKeysRequester;
  192. go FormingGroupRequester;
  193. }
  194. }
  195. }
  196. state HandshakingPhase2Offerer {
  197. on Cancel {
  198. send Rollback;
  199. go Sole;
  200. }
  201. on Reject {
  202. send CommitReject;
  203. do disable;
  204. go End;
  205. }
  206. on Accept {
  207. do trustThisKey;
  208. send CommitAcceptOfferer;
  209. go FormingGroupOfferer;
  210. }
  211. }
  212. state FormingGroupOfferer {
  213. on Init {
  214. // we need to keep in memory which keys we have before forming
  215. // a new group
  216. do prepareOwnKeys;
  217. do backupOwnKeys;
  218. }
  219. on Cancel {
  220. send Rollback;
  221. go Sole;
  222. }
  223. on Rollback
  224. go Sole;
  225. on OwnKeysRequester {
  226. if sameNegotiationAndPartner {
  227. do saveGroupKeys;
  228. do receivedKeysAreDefaultKeys;
  229. // send the keys we had before forming a new group
  230. do prepareOwnKeysFromBackup;
  231. send OwnKeysOfferer;
  232. do showGroupCreated;
  233. go Grouped;
  234. }
  235. }
  236. }
  237. state FormingGroupRequester {
  238. on Cancel {
  239. send Rollback;
  240. go Sole;
  241. }
  242. on Rollback
  243. go Sole;
  244. on OwnKeysOfferer {
  245. if sameNegotiation {
  246. do saveGroupKeys;
  247. do prepareOwnKeys;
  248. do ownKeysAreDefaultKeys;
  249. do showGroupCreated;
  250. go Grouped;
  251. }
  252. }
  253. }
  254. state Grouped timeout=off {
  255. on Init {
  256. do newChallengeAndNegotiationBase;
  257. do showBeingInGroup;
  258. }
  259. on CannotDecrypt {
  260. debug > cry, baby
  261. send SynchronizeGroupKeys;
  262. }
  263. on SynchronizeGroupKeys {
  264. do prepareOwnKeys;
  265. send GroupKeysUpdate;
  266. }
  267. on GroupKeysUpdate {
  268. if fromGroupMember // double check
  269. do saveGroupKeys;
  270. }
  271. on KeyGen {
  272. do prepareOwnKeys;
  273. send GroupKeysUpdate;
  274. }
  275. on Beacon {
  276. do openNegotiation;
  277. do tellWeAreGrouped;
  278. do useOwnResponse;
  279. send NegotiationRequestGrouped;
  280. do useOwnChallenge;
  281. }
  282. on NegotiationOpen {
  283. if sameResponse {
  284. do storeNegotiation;
  285. do useThisKey;
  286. send GroupHandshake;
  287. go HandshakingGrouped;
  288. }
  289. else {
  290. debug > cannot approve NegotiationOpen
  291. }
  292. }
  293. on GroupHandshake {
  294. do storeNegotiation;
  295. do storeThisKey;
  296. go HandshakingGrouped;
  297. }
  298. on GroupTrustThisKey {
  299. if fromGroupMember // double check
  300. do trustThisKey;
  301. }
  302. on LeaveDeviceGroup {
  303. send InitUnledGroupKeyReset;
  304. do disable;
  305. do resetOwnKeysUngrouped;
  306. }
  307. on InitUnledGroupKeyReset {
  308. debug > unled group key reset; new group keys will be elected
  309. do useOwnResponse;
  310. send ElectGroupKeyResetLeader;
  311. go GroupKeyResetElection;
  312. }
  313. }
  314. state GroupKeyResetElection {
  315. on ElectGroupKeyResetLeader {
  316. if sameResponse {
  317. // the first one is from us, we're leading this
  318. do resetOwnGroupedKeys;
  319. go Grouped;
  320. }
  321. else {
  322. // the first one is not from us
  323. go Grouped;
  324. }
  325. }
  326. }
  327. // sole device handshaking with group
  328. state HandshakingToJoin {
  329. on Init
  330. do showJoinGroupHandshake;
  331. // Cancel is Rollback
  332. on Cancel {
  333. send Rollback;
  334. go Sole;
  335. }
  336. on Rollback {
  337. if sameNegotiation
  338. go Sole;
  339. }
  340. // Reject is CommitReject
  341. on Reject {
  342. send CommitReject;
  343. do disable;
  344. go End;
  345. }
  346. on CommitAcceptForGroup {
  347. if sameNegotiation
  348. go HandshakingToJoinPhase2;
  349. }
  350. on CommitReject {
  351. if sameNegotiation {
  352. do disable;
  353. go End;
  354. }
  355. }
  356. // Accept is Phase1Commit
  357. on Accept {
  358. do trustThisKey;
  359. go HandshakingToJoinPhase1;
  360. }
  361. }
  362. state HandshakingToJoinPhase1 {
  363. on Rollback {
  364. if sameNegotiation {
  365. do untrustThisKey;
  366. go Sole;
  367. }
  368. }
  369. on CommitReject {
  370. if sameNegotiation {
  371. do untrustThisKey;
  372. do disable;
  373. go End;
  374. }
  375. }
  376. on CommitAcceptForGroup {
  377. if sameNegotiation {
  378. send CommitAccept;
  379. go JoiningGroup;
  380. }
  381. }
  382. }
  383. state HandshakingToJoinPhase2 {
  384. on Cancel {
  385. send Rollback;
  386. go Sole;
  387. }
  388. on Reject {
  389. send CommitReject;
  390. do disable;
  391. go End;
  392. }
  393. on Accept {
  394. do trustThisKey;
  395. send CommitAccept;
  396. go JoiningGroup;
  397. }
  398. }
  399. state JoiningGroup {
  400. on Init {
  401. // we need to keep in memory which keys we have before joining
  402. do prepareOwnKeys;
  403. do backupOwnKeys;
  404. }
  405. on GroupKeysForNewMember {
  406. if sameNegotiationAndPartner {
  407. do saveGroupKeys;
  408. do receivedKeysAreDefaultKeys;
  409. // send the keys we had before joining
  410. do prepareOwnKeysFromBackup;
  411. send GroupKeysAndClose;
  412. do showDeviceAdded;
  413. go Grouped;
  414. }
  415. }
  416. }
  417. state HandshakingGrouped {
  418. on Init
  419. do showGroupedHandshake;
  420. // Cancel is Rollback
  421. on Cancel {
  422. send Rollback;
  423. go Grouped;
  424. }
  425. on Rollback {
  426. if sameNegotiation
  427. go Grouped;
  428. }
  429. // Reject is CommitReject
  430. on Reject {
  431. send CommitReject;
  432. go Grouped;
  433. }
  434. on CommitReject {
  435. if sameNegotiation
  436. go Grouped;
  437. }
  438. // Accept is Phase1Commit
  439. on Accept {
  440. do trustThisKey;
  441. go HandshakingGroupedPhase1;
  442. }
  443. on GroupTrustThisKey {
  444. if fromGroupMember { // double check
  445. do trustThisKey;
  446. if sameNegotiation
  447. go Grouped;
  448. }
  449. }
  450. on GroupKeysUpdate {
  451. if fromGroupMember // double check
  452. do saveGroupKeys;
  453. }
  454. }
  455. state HandshakingGroupedPhase1 {
  456. on Init {
  457. send GroupTrustThisKey;
  458. send CommitAcceptForGroup;
  459. }
  460. on Rollback {
  461. if sameNegotiation {
  462. do untrustThisKey;
  463. go Grouped;
  464. }
  465. }
  466. on CommitReject {
  467. if sameNegotiation {
  468. do untrustThisKey;
  469. go Grouped;
  470. }
  471. }
  472. on CommitAccept {
  473. if sameNegotiation {
  474. do prepareOwnKeys;
  475. send GroupKeysForNewMember;
  476. do showDeviceAccepted;
  477. go Grouped;
  478. }
  479. }
  480. on GroupTrustThisKey {
  481. if fromGroupMember // double check
  482. do trustThisKey;
  483. }
  484. on GroupKeysUpdate {
  485. if fromGroupMember // double check
  486. do saveGroupKeys;
  487. }
  488. on GroupKeysAndClose {
  489. if fromGroupMember { // double check
  490. // do not save GroupKeys as default keys; key data is
  491. // already imported
  492. go Grouped;
  493. }
  494. }
  495. }
  496. external Accept 129;
  497. external Reject 130;
  498. external Cancel 131;
  499. // beacons are always broadcasted
  500. message Beacon 2, type=broadcast, ratelimit=10, security=unencrypted {
  501. field TID challenge;
  502. auto Version version;
  503. }
  504. message NegotiationRequest 3, security=untrusted {
  505. field TID challenge;
  506. field TID response;
  507. auto Version version;
  508. field TID negotiation;
  509. field bool is_group;
  510. }
  511. message NegotiationOpen 4, security=untrusted {
  512. field TID response;
  513. auto Version version;
  514. field TID negotiation;
  515. }
  516. message Rollback 5, security=untrusted {
  517. field TID negotiation;
  518. }
  519. message CommitReject 6, security=untrusted {
  520. field TID negotiation;
  521. }
  522. message CommitAcceptOfferer 7, security=untrusted {
  523. field TID negotiation;
  524. }
  525. message CommitAcceptRequester 8, security=untrusted {
  526. field TID negotiation;
  527. }
  528. message CommitAccept 9, security=untrusted {
  529. field TID negotiation;
  530. }
  531. message CommitAcceptForGroup 10, security=untrusted {
  532. field TID negotiation;
  533. }
  534. // default: security=trusted
  535. // messages are only accepted when coming from the device group
  536. message GroupTrustThisKey 11 {
  537. field Hash key;
  538. field TID negotiation;
  539. }
  540. // trust in future
  541. message GroupKeysForNewMember 12, security=attach_own_keys_for_new_member {
  542. field IdentityList ownIdentities;
  543. }
  544. message GroupKeysAndClose 13, security=attach_own_keys_for_group {
  545. field IdentityList ownIdentities;
  546. }
  547. message OwnKeysOfferer 14, security=attach_own_keys_for_group {
  548. field IdentityList ownIdentities;
  549. }
  550. message OwnKeysRequester 15, security=attach_own_keys_for_new_member {
  551. field IdentityList ownIdentities;
  552. }
  553. // grouped handshake
  554. message NegotiationRequestGrouped 16, security=untrusted {
  555. field TID challenge;
  556. field TID response;
  557. auto Version version;
  558. field TID negotiation;
  559. field bool is_group;
  560. }
  561. message GroupHandshake 17 {
  562. field TID negotiation;
  563. field Hash key;
  564. }
  565. // update group
  566. message GroupKeysUpdate 18, security=attach_own_keys_for_group {
  567. field IdentityList ownIdentities;
  568. }
  569. // initiate unled group key reset
  570. message InitUnledGroupKeyReset 19 {
  571. }
  572. message ElectGroupKeyResetLeader 20 {
  573. field TID response;
  574. }
  575. message SynchronizeGroupKeys 21, ratelimit=60 {
  576. }
  577. // This could be part of TrustSync, but actually it does not matter.
  578. // This message will not be sent by the Sync thread. It is used by
  579. // decrypt_message() to mark a previously computed rating. It is only
  580. // valid when signed with an own key.
  581. message ReceiverRating 22, security=ignore {
  582. field Rating rating;
  583. }
  584. }
  585. fsm TrustSync 2, threshold=300 {
  586. version 1, 0;
  587. state InitState {
  588. on Init {
  589. go WaitForTrustUpdate;
  590. }
  591. }
  592. state WaitForTrustUpdate {
  593. on TrustUpdate {
  594. }
  595. }
  596. // if trust changes send an update to the device group
  597. message TrustUpdate 2 {
  598. field IdentityList trust;
  599. }
  600. // if we should know the trust status ask the device group
  601. message TrustRequest 3 {
  602. field IdentityList trust;
  603. }
  604. }
  605. fsm GroupSync 3, threshold=300 {
  606. version 1, 0;
  607. state InitState {
  608. on Init {
  609. go WaitForGroupUpdate;
  610. }
  611. }
  612. state WaitForGroupUpdate {
  613. on GroupSyncUpdate {
  614. }
  615. on RequestUpdate {
  616. }
  617. }
  618. // reflect incoming ManagedGroup messages
  619. message GroupSyncUpdate 2 {
  620. embed Distribution ManagedGroup msg;
  621. }
  622. // in case a ManagedGroup message arrives for an unknown group ask the
  623. // other devices
  624. message GroupSyncRequest 3 {
  625. field Identity groupIdentity;
  626. }
  627. }
  628. }