Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
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.

MySigning.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * The MySensors Arduino library handles the wireless radio link and protocol
  3. * between your home built sensors/actuators and HA controller of choice.
  4. * The sensors forms a self healing radio network with optional repeaters. Each
  5. * repeater and gateway builds a routing tables in EEPROM which keeps track of the
  6. * network topology allowing messages to be routed to nodes.
  7. *
  8. * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
  9. * Copyright (C) 2013-2018 Sensnology AB
  10. * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
  11. *
  12. * Documentation: http://www.mysensors.org
  13. * Support Forum: http://forum.mysensors.org
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License
  17. * version 2 as published by the Free Software Foundation.
  18. */
  19. #include "MySigning.h"
  20. #define SIGNING_PRESENTATION_VERSION_1 1
  21. #define SIGNING_PRESENTATION_REQUIRE_SIGNATURES (1 << 0)
  22. #define SIGNING_PRESENTATION_REQUIRE_WHITELISTING (1 << 1)
  23. #if defined(MY_DEBUG_VERBOSE_SIGNING)
  24. #define SIGN_DEBUG(x,...) DEBUG_OUTPUT(x, ##__VA_ARGS__)
  25. #else
  26. #define SIGN_DEBUG(x,...)
  27. #endif
  28. #if defined(MY_SIGNING_REQUEST_SIGNATURES) &&\
  29. (!defined(MY_SIGNING_ATSHA204) && !defined(MY_SIGNING_SOFT))
  30. #error You have to pick either MY_SIGNING_ATSHA204 or MY_SIGNING_SOFT to reqire signatures!
  31. #endif
  32. #if defined(MY_SIGNING_SOFT) && defined(MY_SIGNING_ATSHA204)
  33. #error You have to pick one and only one signing backend
  34. #endif
  35. #ifdef MY_SIGNING_FEATURE
  36. static uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication
  37. static uint8_t _doWhitelist[32]; // Bitfield indicating which sensors require salted signatures
  38. static MyMessage _msgSign; // Buffer for message to sign.
  39. static uint8_t _signingNonceStatus;
  40. static bool stateValid = false;
  41. #ifdef MY_NODE_LOCK_FEATURE
  42. static uint8_t nof_nonce_requests = 0;
  43. static uint8_t nof_failed_verifications = 0;
  44. #endif
  45. // Status when waiting for signing nonce in signerSignMsg
  46. enum { SIGN_WAITING_FOR_NONCE = 0, SIGN_OK = 1 };
  47. // Macros for manipulating signing requirement tables
  48. #define DO_SIGN(node) (~_doSign[node>>3]&(1<<node%8))
  49. #define SET_SIGN(node) (_doSign[node>>3]&=~(1<<node%8))
  50. #if defined(MY_SIGNING_WEAK_SECURITY)
  51. #define CLEAR_SIGN(node) (_doSign[node>>3]|=(1<<node%8))
  52. #endif
  53. #define DO_WHITELIST(node) (~_doWhitelist[node>>3]&(1<<node%8))
  54. #define SET_WHITELIST(node) (_doWhitelist[node>>3]&=~(1<<node%8))
  55. #if defined(MY_SIGNING_WEAK_SECURITY)
  56. #define CLEAR_WHITELIST(node) (_doWhitelist[node>>3]|=(1<<node%8))
  57. #endif
  58. #if defined(MY_SIGNING_SOFT)
  59. extern bool signerAtsha204SoftInit(void);
  60. extern bool signerAtsha204SoftCheckTimer(void);
  61. extern bool signerAtsha204SoftGetNonce(MyMessage &msg);
  62. extern void signerAtsha204SoftPutNonce(MyMessage &msg);
  63. extern bool signerAtsha204SoftVerifyMsg(MyMessage &msg);
  64. extern bool signerAtsha204SoftSignMsg(MyMessage &msg);
  65. #define signerBackendInit signerAtsha204SoftInit
  66. #define signerBackendCheckTimer signerAtsha204SoftCheckTimer
  67. #define signerBackendGetNonce signerAtsha204SoftGetNonce
  68. #define signerBackendPutNonce signerAtsha204SoftPutNonce
  69. #define signerBackendVerifyMsg signerAtsha204SoftVerifyMsg
  70. #define signerBackendSignMsg signerAtsha204SoftSignMsg
  71. #elif defined(MY_SIGNING_ATSHA204)
  72. extern bool signerAtsha204Init(void);
  73. extern bool signerAtsha204CheckTimer(void);
  74. extern bool signerAtsha204GetNonce(MyMessage &msg);
  75. extern void signerAtsha204PutNonce(MyMessage &msg);
  76. extern bool signerAtsha204VerifyMsg(MyMessage &msg);
  77. extern bool signerAtsha204SignMsg(MyMessage &msg);
  78. #define signerBackendInit signerAtsha204Init
  79. #define signerBackendCheckTimer signerAtsha204CheckTimer
  80. #define signerBackendGetNonce signerAtsha204GetNonce
  81. #define signerBackendPutNonce signerAtsha204PutNonce
  82. #define signerBackendVerifyMsg signerAtsha204VerifyMsg
  83. #define signerBackendSignMsg signerAtsha204SignMsg
  84. #endif
  85. static bool skipSign(MyMessage &msg);
  86. #else // not MY_SIGNING_FEATURE
  87. #define signerBackendCheckTimer() true
  88. #endif // MY_SIGNING_FEATURE
  89. static void prepareSigningPresentation(MyMessage &msg, uint8_t destination);
  90. static bool signerInternalProcessPresentation(MyMessage &msg);
  91. static bool signerInternalProcessNonceRequest(MyMessage &msg);
  92. static bool signerInternalProcessNonceResponse(MyMessage &msg);
  93. #if (defined(MY_ENCRYPTION_FEATURE) || defined(MY_SIGNING_FEATURE)) &&\
  94. !defined(MY_SIGNING_SIMPLE_PASSWD)
  95. static bool signerInternalValidatePersonalization(void);
  96. #endif
  97. void signerInit(void)
  98. {
  99. #if defined(MY_SIGNING_FEATURE)
  100. stateValid = true;
  101. #endif
  102. #if (defined (MY_ENCRYPTION_FEATURE) || defined (MY_SIGNING_FEATURE)) &&\
  103. !defined (MY_SIGNING_SIMPLE_PASSWD)
  104. // Suppress this warning since it is only fixed on Linux builds and this keeps the code more tidy
  105. // cppcheck-suppress knownConditionTrueFalse
  106. if (!signerInternalValidatePersonalization()) {
  107. SIGN_DEBUG(PSTR("!SGN:PER:TAMPERED\n"));
  108. #if defined(MY_SIGNING_FEATURE)
  109. stateValid = false;
  110. #endif
  111. } else {
  112. SIGN_DEBUG(PSTR("SGN:PER:OK\n"));
  113. }
  114. #endif
  115. #if defined(MY_SIGNING_FEATURE)
  116. // Read out the signing requirements from EEPROM
  117. hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
  118. sizeof(_doSign));
  119. // Read out the whitelist requirements from EEPROM
  120. hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
  121. sizeof(_doWhitelist));
  122. if (!signerBackendInit()) {
  123. SIGN_DEBUG(PSTR("!SGN:INI:BND FAIL\n"));
  124. } else {
  125. SIGN_DEBUG(PSTR("SGN:INI:BND OK\n"));
  126. }
  127. #endif
  128. }
  129. void signerPresentation(MyMessage &msg, uint8_t destination)
  130. {
  131. prepareSigningPresentation(msg, destination);
  132. #if defined(MY_SIGNING_REQUEST_SIGNATURES)
  133. msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
  134. SIGN_DEBUG(PSTR("SGN:PRE:SGN REQ\n")); // Signing required
  135. #else
  136. SIGN_DEBUG(PSTR("SGN:PRE:SGN NREQ\n")); // Signing not required
  137. #endif
  138. #if defined(MY_SIGNING_NODE_WHITELISTING)
  139. msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
  140. SIGN_DEBUG(PSTR("SGN:PRE:WHI REQ\n")); // Whitelisting required
  141. #else
  142. SIGN_DEBUG(PSTR("SGN:PRE:WHI NREQ\n")); // Whitelisting not required
  143. #endif
  144. if (!_sendRoute(msg)) {
  145. SIGN_DEBUG(PSTR("!SGN:PRE:XMT,TO=%" PRIu8 " FAIL\n"),
  146. destination); // Failed to transmit presentation!
  147. } else {
  148. SIGN_DEBUG(PSTR("SGN:PRE:XMT,TO=%" PRIu8 "\n"), destination); // Transmitted signing presentation!
  149. }
  150. if (destination == GATEWAY_ADDRESS) {
  151. SIGN_DEBUG(PSTR("SGN:PRE:WAIT GW\n")); // Waiting for GW to send signing preferences...
  152. wait(2000, C_INTERNAL, I_SIGNING_PRESENTATION);
  153. }
  154. }
  155. bool signerProcessInternal(MyMessage &msg)
  156. {
  157. bool ret;
  158. switch (msg.type) {
  159. case I_SIGNING_PRESENTATION:
  160. ret = signerInternalProcessPresentation(msg);
  161. break;
  162. case I_NONCE_REQUEST:
  163. ret = signerInternalProcessNonceRequest(msg);
  164. break;
  165. case I_NONCE_RESPONSE:
  166. ret = signerInternalProcessNonceResponse(msg);
  167. break;
  168. default:
  169. ret = false; // Let the transport process this message further as it is not related to signing
  170. break;
  171. }
  172. return ret;
  173. }
  174. bool signerCheckTimer(void)
  175. {
  176. return signerBackendCheckTimer();
  177. }
  178. bool signerSignMsg(MyMessage &msg)
  179. {
  180. bool ret;
  181. #if defined(MY_SIGNING_FEATURE)
  182. // If destination is known to require signed messages and we are the sender,
  183. // sign this message unless it is identified as an exception
  184. if (DO_SIGN(msg.destination) && msg.sender == getNodeId()) {
  185. if (skipSign(msg)) {
  186. ret = true;
  187. } else {
  188. // Before starting, validate that our state is good, or signing will fail
  189. if (!stateValid) {
  190. SIGN_DEBUG(PSTR("!SGN:SGN:STATE\n")); // Signing system is not in a valid state
  191. ret = false;
  192. } else {
  193. // Send nonce-request
  194. _signingNonceStatus=SIGN_WAITING_FOR_NONCE;
  195. if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
  196. I_NONCE_REQUEST).set(""))) {
  197. SIGN_DEBUG(PSTR("!SGN:SGN:NCE REQ,TO=%" PRIu8 " FAIL\n"),
  198. msg.destination); // Failed to transmit nonce request!
  199. ret = false;
  200. } else {
  201. SIGN_DEBUG(PSTR("SGN:SGN:NCE REQ,TO=%" PRIu8 "\n"), msg.destination); // Nonce requested
  202. // We have to wait for the nonce to arrive before we can sign our original message
  203. // Other messages could come in-between. We trust _process() takes care of them
  204. unsigned long enter = hwMillis();
  205. _msgSign = msg; // Copy the message to sign since buffer might be touched in _process()
  206. while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS &&
  207. _signingNonceStatus==SIGN_WAITING_FOR_NONCE) {
  208. _process();
  209. }
  210. if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
  211. SIGN_DEBUG(PSTR("!SGN:SGN:NCE TMO\n")); // Timeout waiting for nonce!
  212. ret = false;
  213. } else {
  214. if (_signingNonceStatus == SIGN_OK) {
  215. // process() received a nonce and signerProcessInternal successfully signed the message
  216. msg = _msgSign; // Write the signed message back
  217. SIGN_DEBUG(PSTR("SGN:SGN:SGN\n")); // Message to send has been signed
  218. ret = true;
  219. // After this point, only the 'last' member of the message structure is allowed to be
  220. // altered if the message has been signed, or signature will become invalid and the
  221. // message rejected by the receiver
  222. } else {
  223. SIGN_DEBUG(PSTR("!SGN:SGN:SGN FAIL\n")); // Message to send could not be signed!
  224. ret = false;
  225. }
  226. }
  227. }
  228. }
  229. }
  230. } else if (getNodeId() == msg.sender) {
  231. mSetSigned(msg, 0); // Message is not supposed to be signed, make sure it is marked unsigned
  232. SIGN_DEBUG(PSTR("SGN:SGN:NREQ=%" PRIu8 "\n"),
  233. msg.destination); // Do not sign message as it is not req
  234. ret = true;
  235. } else {
  236. SIGN_DEBUG(PSTR("SGN:SGN:%" PRIu8 "!=%" PRIu8 " NUS\n"), msg.sender,
  237. getNodeId()); // Will not sign message since it was from someone else
  238. ret = true;
  239. }
  240. #else
  241. (void)msg;
  242. ret = true;
  243. #endif // MY_SIGNING_FEATURE
  244. return ret;
  245. }
  246. bool signerVerifyMsg(MyMessage &msg)
  247. {
  248. bool verificationResult = true;
  249. // Before processing message, reject unsigned messages if signing is required and check signature
  250. // (if it is signed and addressed to us)
  251. // Note that we do not care at all about any signature found if we do not require signing
  252. #if defined(MY_SIGNING_FEATURE) && defined(MY_SIGNING_REQUEST_SIGNATURES)
  253. // If we are a node, or we are a gateway and the sender require signatures (or just a strict gw)
  254. // and we are the destination...
  255. #if defined(MY_SIGNING_WEAK_SECURITY)
  256. if ((!MY_IS_GATEWAY || DO_SIGN(msg.sender)) && msg.destination == getNodeId()) {
  257. #else
  258. if (msg.destination == getNodeId()) {
  259. #endif
  260. // Internal messages of certain types are not verified
  261. if (skipSign(msg)) {
  262. verificationResult = true;
  263. } else if (!mGetSigned(msg)) {
  264. // Got unsigned message that should have been signed
  265. SIGN_DEBUG(PSTR("!SGN:VER:NSG\n")); // Message is not signed, but it should have been!
  266. verificationResult = false;
  267. } else {
  268. // Before starting, validate that our state is good, or signing will fail
  269. if (!stateValid) {
  270. SIGN_DEBUG(PSTR("!SGN:VER:STATE\n")); // Signing system is not in a valid state
  271. verificationResult = false;
  272. } else {
  273. if (!signerBackendVerifyMsg(msg)) {
  274. SIGN_DEBUG(PSTR("!SGN:VER:FAIL\n")); // Signature verification failed!
  275. verificationResult = false;
  276. } else {
  277. SIGN_DEBUG(PSTR("SGN:VER:OK\n"));
  278. }
  279. }
  280. #if defined(MY_NODE_LOCK_FEATURE)
  281. if (verificationResult) {
  282. // On successful verification, clear lock counters
  283. nof_nonce_requests = 0;
  284. nof_failed_verifications = 0;
  285. } else {
  286. nof_failed_verifications++;
  287. SIGN_DEBUG(PSTR("SGN:VER:LEFT=%" PRIu8 "\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
  288. if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) {
  289. _nodeLock("TMFV"); // Too many failed verifications
  290. }
  291. }
  292. #endif
  293. mSetSigned(msg,0); // Clear the sign-flag now as verification is completed
  294. }
  295. }
  296. #else
  297. (void)msg;
  298. #endif // MY_SIGNING_REQUEST_SIGNATURES
  299. return verificationResult;
  300. }
  301. int signerMemcmp(const void* a, const void* b, size_t sz)
  302. {
  303. int retVal;
  304. size_t i;
  305. int done = 0;
  306. const uint8_t* ptrA = (const uint8_t*)a;
  307. const uint8_t* ptrB = (const uint8_t*)b;
  308. for (i=0; i < sz; i++) {
  309. if (ptrA[i] == ptrB[i]) {
  310. if (done > 0) {
  311. done = 1;
  312. } else {
  313. done = 0;
  314. }
  315. } else {
  316. if (done > 0) {
  317. done = 2;
  318. } else {
  319. done = 3;
  320. }
  321. }
  322. }
  323. if (done > 0) {
  324. retVal = -1;
  325. } else {
  326. retVal = 0;
  327. }
  328. return retVal;
  329. }
  330. #if defined(MY_SIGNING_FEATURE)
  331. // Helper function to centralize signing/verification exceptions
  332. static bool skipSign(MyMessage &msg)
  333. {
  334. bool ret = false;
  335. if (mGetAck(msg)) {
  336. ret = true;
  337. } else if (mGetCommand(msg) == C_INTERNAL &&
  338. (msg.type == I_SIGNING_PRESENTATION ||
  339. msg.type == I_REGISTRATION_REQUEST ||
  340. msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE ||
  341. msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
  342. msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
  343. msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
  344. msg.type == I_PING || msg.type == I_PONG ||
  345. msg.type == I_DISCOVER_REQUEST || msg.type == I_DISCOVER_RESPONSE ||
  346. msg.type == I_LOG_MESSAGE)) {
  347. ret = true;
  348. } else if (mGetCommand(msg) == C_STREAM &&
  349. (msg.type == ST_SOUND ||
  350. msg.type == ST_IMAGE ||
  351. msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE )) {
  352. ret = true;
  353. }
  354. if (ret) {
  355. SIGN_DEBUG(PSTR("SGN:SKP:%s CMD=%" PRIu8 ",TYPE=%" PRIu8 "\n"), mGetAck(msg) ? "ACK" : "MSG",
  356. mGetCommand(msg),
  357. msg.type); //Skip signing/verification of this message
  358. }
  359. return ret;
  360. }
  361. #endif
  362. // Helper to prepare a signing presentation message
  363. static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
  364. {
  365. // Only supports version 1 for now
  366. (void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set("");
  367. mSetLength(msg, 2);
  368. mSetPayloadType(msg, P_CUSTOM); // displayed as hex
  369. msg.data[0] = SIGNING_PRESENTATION_VERSION_1;
  370. msg.data[1] = 0;
  371. }
  372. // Helper to process presentation messages
  373. static bool signerInternalProcessPresentation(MyMessage &msg)
  374. {
  375. const uint8_t sender = msg.sender;
  376. #if defined(MY_SIGNING_FEATURE)
  377. if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
  378. SIGN_DEBUG(PSTR("!SGN:PRE:VER=%" PRIu8 "\n"),
  379. msg.data[0]); // Unsupported signing presentation version
  380. return true; // Just drop this presentation message
  381. }
  382. // We only handle version 1 here...
  383. if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
  384. // We received an indicator that the sender require us to sign all messages we send to it
  385. SIGN_DEBUG(PSTR("SGN:PRE:SGN REQ,FROM=%" PRIu8 "\n"), sender); // Node require signatures
  386. SET_SIGN(sender);
  387. } else {
  388. #if defined(MY_SIGNING_WEAK_SECURITY)
  389. // We received an indicator that the sender does not require us to sign messages we send to it
  390. SIGN_DEBUG(PSTR("SGN:PRE:SGN NREQ,FROM=%" PRIu8 "\n"), sender); // Node does not require signatures
  391. CLEAR_SIGN(sender);
  392. #else
  393. if (DO_SIGN(sender)) {
  394. SIGN_DEBUG(PSTR("!SGN:PRE:SGN NREQ,FROM=%" PRIu8 " REJ\n"),
  395. sender); // Node does not require signatures but used to do so
  396. }
  397. #endif
  398. }
  399. if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
  400. // We received an indicator that the sender require us to salt signatures with serial
  401. SIGN_DEBUG(PSTR("SGN:PRE:WHI REQ,FROM=%" PRIu8 "\n"), sender); // Node require whitelisting
  402. SET_WHITELIST(sender);
  403. } else {
  404. #if defined(MY_SIGNING_WEAK_SECURITY)
  405. // We received an indicator that the sender does not require us to sign messages we send to it
  406. SIGN_DEBUG(PSTR("SGN:PRE:WHI NREQ,FROM=%" PRIu8 "\n"),
  407. sender); // Node does not require whitelisting
  408. CLEAR_WHITELIST(sender);
  409. #else
  410. if (DO_WHITELIST(sender)) {
  411. SIGN_DEBUG(PSTR("!SGN:PRE:WHI NREQ,FROM=%" PRIu8 " REJ\n"),
  412. sender); // Node does not require whitelisting but used to do so
  413. }
  414. #endif
  415. }
  416. // Save updated tables
  417. hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
  418. sizeof(_doSign));
  419. hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
  420. sizeof(_doWhitelist));
  421. // Inform sender about our preference if we are a gateway, but only require signing if the sender
  422. // required signing unless we explicitly configure it to
  423. #if defined(MY_GATEWAY_FEATURE)
  424. prepareSigningPresentation(msg, sender);
  425. #if defined(MY_SIGNING_REQUEST_SIGNATURES)
  426. #if defined(MY_SIGNING_WEAK_SECURITY)
  427. if (DO_SIGN(sender)) {
  428. msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
  429. }
  430. #else
  431. msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
  432. #endif
  433. #endif // MY_SIGNING_REQUEST_SIGNATURES
  434. #if defined(MY_SIGNING_NODE_WHITELISTING)
  435. msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
  436. #endif // MY_SIGNING_NODE_WHITELISTING
  437. if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
  438. SIGN_DEBUG(PSTR("SGN:PRE:SGN REQ,TO=%" PRIu8 "\n"),
  439. sender); // Inform node that we require signatures
  440. } else {
  441. SIGN_DEBUG(PSTR("SGN:PRE:SGN NREQ,TO=%" PRIu8 "\n"),
  442. sender); // Inform node that we do not require signatures
  443. }
  444. if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
  445. SIGN_DEBUG(PSTR("SGN:PRE:WHI REQ,TO=%" PRIu8 "\n"),
  446. sender); // Inform node that we require whitelisting
  447. } else {
  448. SIGN_DEBUG(PSTR("SGN:PRE:WHI NREQ,TO=%" PRIu8 "\n"),
  449. sender); // Inform node that we do not require whitelisting
  450. }
  451. if (!_sendRoute(msg)) {
  452. SIGN_DEBUG(PSTR("!SGN:PRE:XMT,TO=%" PRIu8 " FAIL\n"),
  453. sender); // Failed to transmit signing presentation!
  454. } else {
  455. SIGN_DEBUG(PSTR("SGN:PRE:XMT,TO=%" PRIu8 "\n"), sender);
  456. }
  457. #endif // MY_GATEWAY_FEATURE
  458. #else // not MY_SIGNING_FEATURE
  459. #if defined(MY_GATEWAY_FEATURE)
  460. // If we act as gateway and do not have the signing feature and receive a signing request we still
  461. // need to do make sure the requester does not believe the gateway still require signatures
  462. prepareSigningPresentation(msg, sender);
  463. SIGN_DEBUG(PSTR("SGN:PRE:NSUP,TO=%" PRIu8 "\n"),
  464. sender); // Informing node that we do not support signing
  465. if (!_sendRoute(msg)) {
  466. SIGN_DEBUG(PSTR("!SGN:PRE:XMT,TO=%" PRIu8 " FAIL\n"),
  467. sender); // Failed to transmit signing presentation!
  468. } else {
  469. SIGN_DEBUG(PSTR("SGN:PRE:XMT,TO=%" PRIu8 "\n"), sender);
  470. }
  471. #else // not MY_GATEWAY_FEATURE
  472. // If we act as a node and do not have the signing feature then we just silently drop any signing
  473. // presentation messages received
  474. (void)msg;
  475. (void)sender;
  476. // Received signing presentation, but signing is not supported (message ignored)
  477. SIGN_DEBUG(
  478. PSTR("SGN:PRE:NSUP\n"));
  479. #endif // not MY_GATEWAY_FEATURE
  480. #endif // not MY_SIGNING_FEATURE
  481. return true; // No need to further process I_SIGNING_PRESENTATION
  482. }
  483. // Helper to process nonce request messages
  484. static bool signerInternalProcessNonceRequest(MyMessage &msg)
  485. {
  486. #if defined(MY_SIGNING_FEATURE)
  487. #if defined(MY_NODE_LOCK_FEATURE)
  488. nof_nonce_requests++;
  489. SIGN_DEBUG(PSTR("SGN:NCE:LEFT=%" PRIu8 "\n"),
  490. MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests); // Nonce requests left until lockdown
  491. if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
  492. _nodeLock("TMNR"); // Too many nonces requested
  493. }
  494. #endif // MY_NODE_LOCK_FEATURE
  495. if (signerBackendGetNonce(msg)) {
  496. if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) {
  497. SIGN_DEBUG(PSTR("!SGN:NCE:XMT,TO=%" PRIu8 " FAIL\n"), msg.sender); // Failed to transmit nonce!
  498. } else {
  499. SIGN_DEBUG(PSTR("SGN:NCE:XMT,TO=%" PRIu8 "\n"), msg.sender);
  500. }
  501. } else {
  502. SIGN_DEBUG(PSTR("!SGN:NCE:GEN\n")); // Failed to generate nonce!
  503. }
  504. #else // not MY_SIGNING_FEATURE
  505. (void)msg;
  506. SIGN_DEBUG(
  507. PSTR("SGN:NCE:NSUP (DROPPED)\n")); // Received nonce request/response without signing support
  508. #endif // MY_SIGNING_FEATURE
  509. return true; // No need to further process I_NONCE_REQUEST
  510. }
  511. // Helper to process nonce response messages
  512. static bool signerInternalProcessNonceResponse(MyMessage &msg)
  513. {
  514. #if defined(MY_SIGNING_FEATURE)
  515. // Proceed with signing if nonce has been received
  516. SIGN_DEBUG(PSTR("SGN:NCE:FROM=%" PRIu8 "\n"), msg.sender);
  517. if (msg.sender != _msgSign.destination) {
  518. SIGN_DEBUG(PSTR("SGN:NCE:%" PRIu8 "!=%" PRIu8 " (DROPPED)\n"), _msgSign.destination, msg.sender);
  519. } else {
  520. signerBackendPutNonce(msg);
  521. if (signerBackendSignMsg(_msgSign)) {
  522. // _msgSign now contains the signed message pending transmission
  523. _signingNonceStatus = SIGN_OK;
  524. }
  525. }
  526. #else
  527. (void)msg;
  528. SIGN_DEBUG(
  529. PSTR("SGN:NCE:NSUP (DROPPED)\n")); // Received nonce request/response without signing support
  530. #endif
  531. return true; // No need to further process I_NONCE_RESPONSE
  532. }
  533. #if (defined(MY_ENCRYPTION_FEATURE) || defined(MY_SIGNING_FEATURE)) &&\
  534. !defined(MY_SIGNING_SIMPLE_PASSWD)
  535. static bool signerInternalValidatePersonalization(void)
  536. {
  537. #ifdef __linux__
  538. // Personalization on linux is a bit more crude
  539. return true;
  540. #else
  541. uint8_t buffer[SIZE_SIGNING_SOFT_HMAC_KEY + SIZE_RF_ENCRYPTION_AES_KEY + SIZE_SIGNING_SOFT_SERIAL];
  542. uint8_t hash[32];
  543. uint8_t checksum;
  544. hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS,
  545. SIZE_SIGNING_SOFT_HMAC_KEY);
  546. hwReadConfigBlock((void*)&buffer[SIZE_SIGNING_SOFT_HMAC_KEY],
  547. (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, SIZE_RF_ENCRYPTION_AES_KEY);
  548. hwReadConfigBlock((void*)&buffer[SIZE_SIGNING_SOFT_HMAC_KEY + SIZE_RF_ENCRYPTION_AES_KEY],
  549. (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, SIZE_SIGNING_SOFT_SERIAL);
  550. hwReadConfigBlock((void*)&checksum, (void*)EEPROM_PERSONALIZATION_CHECKSUM_ADDRESS,
  551. SIZE_PERSONALIZATION_CHECKSUM);
  552. SHA256(hash, buffer, sizeof(buffer));
  553. return (checksum == hash[0]);
  554. #endif
  555. }
  556. #endif