Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
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.
 
 
 
 
 
 

152 lines
3.7 KiB

  1. #include <comms.h>
  2. #include <strobe_rng_init.h>
  3. static const size_t MAC_LEN = 8;
  4. static const size_t CHALLENGE_LEN = 16;
  5. static const uint8_t domain[] = "com.funkthat.lora.irrigation.shared.v0.0.1";
  6. static int comms_pktbuf_equal(struct pktbuf a, struct pktbuf b);
  7. /* returns 1 if equal, 0 if not equal */
  8. static int
  9. comms_pktbuf_equal(struct pktbuf a, struct pktbuf b)
  10. {
  11. if (a.pktlen != b.pktlen)
  12. return 0;
  13. return memcmp(a.pkt, b.pkt, a.pktlen) == 0;
  14. }
  15. size_t
  16. _strobe_state_size()
  17. {
  18. return sizeof(strobe_s);
  19. }
  20. void
  21. comms_init(struct comms_state *cs, process_msgfunc_t pmf, struct pktbuf *shared)
  22. {
  23. *cs = (struct comms_state){
  24. .cs_comm_state = COMMS_WAIT_REQUEST,
  25. .cs_procmsg = pmf,
  26. };
  27. strobe_init(&cs->cs_start, domain, sizeof domain - 1);
  28. if (shared != NULL)
  29. strobe_key(&cs->cs_start, SYM_KEY, shared->pkt, shared->pktlen);
  30. /* copy starting state over to initial state */
  31. cs->cs_state = cs->cs_start;
  32. }
  33. #define CONFIRMED_STR_BASE "confirmed"
  34. #define CONFIRMED_STR ((const uint8_t *)CONFIRMED_STR_BASE)
  35. #define CONFIRMED_STR_LEN (sizeof(CONFIRMED_STR_BASE) - 1)
  36. /*
  37. * encrypted data to be processed is passed in via pbin.
  38. *
  39. * The pktbuf pointed to by pbout contains the buffer that a [encrypted]
  40. * response will be written to. The length needs to be updated, where 0
  41. * means no reply.
  42. */
  43. void
  44. comms_process(struct comms_state *cs, struct pktbuf pbin, struct pktbuf *pbout)
  45. {
  46. uint8_t buf[64] = {};
  47. struct pktbuf pbmsg, pbrep;
  48. ssize_t cnt, ret, msglen;
  49. /* if the current msg matches the previous */
  50. if (comms_pktbuf_equal(pbin, cs->cs_prevmsg)) {
  51. /* send the previous response */
  52. pbout->pktlen = cs->cs_prevmsgresp.pktlen;
  53. memcpy(pbout->pkt, cs->cs_prevmsgresp.pkt, pbout->pktlen);
  54. return;
  55. }
  56. strobe_attach_buffer(&cs->cs_state, pbin.pkt, pbin.pktlen);
  57. cnt = strobe_get(&cs->cs_state, APP_CIPHERTEXT, buf, pbin.pktlen -
  58. MAC_LEN);
  59. msglen = cnt;
  60. cnt = strobe_get(&cs->cs_state, MAC, pbin.pkt +
  61. (pbin.pktlen - MAC_LEN), MAC_LEN);
  62. /* XXX - cnt != MAC_LEN test case */
  63. /*
  64. * if we have arrived here, MAC has been verified, and buf now
  65. * contains the data to operate upon.
  66. */
  67. /* attach the buffer for output */
  68. strobe_attach_buffer(&cs->cs_state, pbout->pkt, pbout->pktlen);
  69. ret = 0;
  70. switch (cs->cs_comm_state) {
  71. case COMMS_WAIT_REQUEST:
  72. /* XXX - reqreset check */
  73. bare_strobe_randomize(buf, CHALLENGE_LEN);
  74. ret = strobe_put(&cs->cs_state, APP_CIPHERTEXT, buf,
  75. CHALLENGE_LEN);
  76. ret += strobe_put(&cs->cs_state, MAC, NULL, MAC_LEN);
  77. strobe_operate(&cs->cs_state, RATCHET, NULL, 32);
  78. cs->cs_comm_state = COMMS_WAIT_CONFIRM;
  79. break;
  80. case COMMS_WAIT_CONFIRM:
  81. /* XXX - confirm check */
  82. ret = strobe_put(&cs->cs_state, APP_CIPHERTEXT, CONFIRMED_STR,
  83. CONFIRMED_STR_LEN);
  84. ret += strobe_put(&cs->cs_state, MAC, NULL, MAC_LEN);
  85. cs->cs_comm_state = COMMS_PROCESS_MSGS;
  86. break;
  87. case COMMS_PROCESS_MSGS: {
  88. uint8_t repbuf[pbout->pktlen - MAC_LEN];
  89. memset(repbuf, '\x00', sizeof repbuf);
  90. pbmsg.pkt = buf;
  91. pbmsg.pktlen = msglen;
  92. pbrep.pkt = repbuf;
  93. pbrep.pktlen = sizeof repbuf;
  94. cs->cs_procmsg(pbmsg, &pbrep);
  95. ret = strobe_put(&cs->cs_state, APP_CIPHERTEXT, repbuf,
  96. pbrep.pktlen);
  97. ret += strobe_put(&cs->cs_state, MAC, NULL, MAC_LEN);
  98. break;
  99. }
  100. }
  101. /* set the output buffer length */
  102. pbout->pktlen = ret;
  103. if (ret != 0) {
  104. /* we accepted a new message store it */
  105. /* store the req */
  106. cs->cs_prevmsg.pkt = cs->cs_prevmsgbuf;
  107. cs->cs_prevmsg.pktlen = pbin.pktlen;
  108. memcpy(cs->cs_prevmsg.pkt, pbin.pkt, pbin.pktlen);
  109. /* store the response */
  110. cs->cs_prevmsgresp.pkt = cs->cs_prevmsgrespbuf;
  111. cs->cs_prevmsgresp.pktlen = pbout->pktlen;
  112. memcpy(cs->cs_prevmsgresp.pkt, pbout->pkt, pbout->pktlen);
  113. }
  114. }