transport.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. generic transport class for handling OpenDroneID messages
  3. */
  4. #include <Arduino.h>
  5. #include "transport.h"
  6. #include "parameters.h"
  7. #include "util.h"
  8. #include "monocypher.h"
  9. const char *Transport::parse_fail = "uninitialised";
  10. uint32_t Transport::last_location_ms;
  11. uint32_t Transport::last_basic_id_ms;
  12. uint32_t Transport::last_self_id_ms;
  13. uint32_t Transport::last_operator_id_ms;
  14. uint32_t Transport::last_system_ms;
  15. uint32_t Transport::last_system_timestamp;
  16. float Transport::last_location_timestamp;
  17. mavlink_open_drone_id_location_t Transport::location;
  18. mavlink_open_drone_id_basic_id_t Transport::basic_id;
  19. mavlink_open_drone_id_authentication_t Transport::authentication;
  20. mavlink_open_drone_id_self_id_t Transport::self_id;
  21. mavlink_open_drone_id_system_t Transport::system;
  22. mavlink_open_drone_id_operator_id_t Transport::operator_id;
  23. Transport::Transport()
  24. {
  25. }
  26. /*
  27. check we are OK to arm
  28. */
  29. uint8_t Transport::arm_status_check(const char *&reason)
  30. {
  31. const uint32_t max_age_location_ms = 3000;
  32. const uint32_t max_age_other_ms = 22000;
  33. const uint32_t now_ms = millis();
  34. uint8_t status = MAV_ODID_ARM_STATUS_PRE_ARM_FAIL_GENERIC;
  35. //return status OK if we have enabled the force arm option
  36. if (g.options & OPTIONS_FORCE_ARM_OK) {
  37. status = MAV_ODID_ARM_STATUS_GOOD_TO_ARM;
  38. return status;
  39. }
  40. char return_string[200]; //make it bigger to accomodate all possible errors
  41. memset(return_string, 0, 200);
  42. strcpy (return_string, "missing ");
  43. static char return_string_full[50];
  44. memset(return_string_full, 0, 50);
  45. if (last_location_ms == 0 || now_ms - last_location_ms > max_age_location_ms) {
  46. strcat(return_string, "LOC ");
  47. }
  48. if (!g.have_basic_id_info()) {
  49. // if there is no basic ID data stored in the parameters give warning. If basic ID data are streamed to RID device,
  50. // it will store them in the parameters
  51. strcat(return_string, "ID ");
  52. }
  53. if (last_self_id_ms == 0 || now_ms - last_self_id_ms > max_age_other_ms) {
  54. strcat(return_string, "SELF_ID ");
  55. }
  56. if (last_operator_id_ms == 0 || now_ms - last_operator_id_ms > max_age_other_ms) {
  57. strcat(return_string, "OP_ID ");
  58. }
  59. if (last_system_ms == 0 || now_ms - last_system_ms > max_age_location_ms) {
  60. // we use location age limit for system as the operator location needs to come in as fast
  61. // as the vehicle location for FAA standard
  62. strcat(return_string, "SYS ");
  63. }
  64. if (location.latitude == 0 && location.longitude == 0) {
  65. if (strcmp(return_string ,"missing ") == 0) {
  66. //if the return string only contains the word missing, there is no error.
  67. strcpy(return_string, "zero LOC ");
  68. }
  69. else {
  70. strcat(return_string, "zero LOC ");
  71. }
  72. }
  73. if (system.operator_latitude == 0 && system.operator_longitude == 0) {
  74. if (strcmp(return_string ,"missing ") == 0) {
  75. //if the return string only contains the word missing, there is no error.
  76. strcpy(return_string, "zero OP_LOC ");
  77. }
  78. else {
  79. strcat(return_string, "zero OP_LOC ");
  80. }
  81. }
  82. if (return_string == nullptr && reason == nullptr) {
  83. status = MAV_ODID_ARM_STATUS_GOOD_TO_ARM;
  84. } else {
  85. if (reason!=nullptr) {
  86. strncpy(return_string_full, reason, 49);
  87. }
  88. strncat(return_string_full, return_string, 49 - strlen(return_string_full));
  89. reason = return_string_full;
  90. }
  91. return status;
  92. }
  93. /*
  94. make a session key
  95. */
  96. void Transport::make_session_key(uint8_t key[8]) const
  97. {
  98. struct {
  99. uint32_t time_us;
  100. uint8_t mac[8];
  101. uint32_t rand;
  102. } data {};
  103. static_assert(sizeof(data) % 4 == 0, "data must be multiple of 4 bytes");
  104. esp_efuse_mac_get_default(data.mac);
  105. data.time_us = micros();
  106. data.rand = random(0xFFFFFFFF);
  107. const uint64_t c64 = crc_crc64((const uint32_t *)&data, sizeof(data)/sizeof(uint32_t));
  108. memcpy(key, (uint8_t *)&c64, 8);
  109. }
  110. /*
  111. check signature in a command against public keys
  112. */
  113. bool Transport::check_signature(uint8_t sig_length, uint8_t data_len, uint32_t sequence, uint32_t operation,
  114. const uint8_t *data)
  115. {
  116. if (g.no_public_keys()) {
  117. // allow through if no keys are setup
  118. return true;
  119. }
  120. if (sig_length != 64) {
  121. // monocypher signatures are 64 bytes
  122. return false;
  123. }
  124. /*
  125. loop over all public keys, if one matches then we are OK
  126. */
  127. for (uint8_t i=0; i<MAX_PUBLIC_KEYS; i++) {
  128. uint8_t key[32];
  129. if (!g.get_public_key(i, key)) {
  130. continue;
  131. }
  132. crypto_check_ctx ctx {};
  133. crypto_check_ctx_abstract *actx = (crypto_check_ctx_abstract*)&ctx;
  134. crypto_check_init(actx, &data[data_len], key);
  135. crypto_check_update(actx, (const uint8_t*)&sequence, sizeof(sequence));
  136. crypto_check_update(actx, (const uint8_t*)&operation, sizeof(operation));
  137. crypto_check_update(actx, data, data_len);
  138. if (operation != SECURE_COMMAND_GET_SESSION_KEY &&
  139. operation != SECURE_COMMAND_GET_REMOTEID_SESSION_KEY) {
  140. crypto_check_update(actx, session_key, sizeof(session_key));
  141. }
  142. if (crypto_check_final(actx) == 0) {
  143. // good signature
  144. return true;
  145. }
  146. }
  147. return false;
  148. }