Ver Fonte

calculate shared_secret on demand

taco há 8 meses atrás
pai
commit
638f41d143

+ 1 - 1
examples/companion_radio/MyMesh.cpp

@@ -1238,7 +1238,7 @@ void MyMesh::handleCmdFrame(size_t len) {
     if (_store->saveMainIdentity(identity)) {
       self_id = identity;
       writeOKFrame();
-      // re-load contacts, to recalc shared secrets
+      // re-load contacts, to invalidate ecdh shared_secrets
       resetContacts();
       _store->loadContacts(this);
     } else {

+ 18 - 6
src/helpers/BaseChatMesh.cpp

@@ -113,8 +113,7 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
       from->gps_lon = 0;
       from->sync_since = 0;
 
-      // only need to calculate the shared_secret once, for better performance
-      self_id.calcSharedSecret(from->shared_secret, id);
+      from->shared_secret_valid = false;  // ecdh shared_secret will be calculated later on demand  
     } else {
       MESH_DEBUG_PRINTLN("onAdvertRecv: contacts table is full!");
       return;
@@ -147,7 +146,7 @@ int BaseChatMesh::searchPeersByHash(const uint8_t* hash) {
 void BaseChatMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) {
   int i = matching_peer_indexes[peer_idx];
   if (i >= 0 && i < num_contacts) {
-    // lookup pre-calculated shared_secret
+    ensureSharedSecretIsValid(contacts[i]);
     memcpy(dest_secret, contacts[i].shared_secret, PUB_KEY_SIZE);
   } else {
     MESH_DEBUG_PRINTLN("getPeerSharedSecret: Invalid peer idx: %d", i);
@@ -293,6 +292,7 @@ void BaseChatMesh::onAckRecv(mesh::Packet* packet, uint32_t ack_crc) {
 void BaseChatMesh::handleReturnPathRetry(const ContactInfo& contact, const uint8_t* path, uint8_t path_len) {
   // NOTE: simplest impl is just to re-send a reciprocal return path to sender (DIRECTLY)
   //        override this method in various firmwares, if there's a better strategy
+  ensureSharedSecretIsValid(contact);
   mesh::Packet* rpath = createPathReturn(contact.id, contact.shared_secret, path, path_len, 0, NULL, 0);
   if (rpath) sendDirect(rpath, contact.out_path, contact.out_path_len, 3000);   // 3 second delay
 }
@@ -342,6 +342,7 @@ mesh::Packet* BaseChatMesh::composeMsgPacket(const ContactInfo& recipient, uint3
     temp[len++] = attempt;  // hide attempt number at tail end of payload
   }
 
+  ensureSharedSecretIsValid(recipient);
   return createDatagram(PAYLOAD_TYPE_TXT_MSG, recipient.id, recipient.shared_secret, temp, len);
 }
 
@@ -373,6 +374,7 @@ int  BaseChatMesh::sendCommandData(const ContactInfo& recipient, uint32_t timest
   temp[4] = (attempt & 3) | (TXT_TYPE_CLI_DATA << 2);
   memcpy(&temp[5], text, text_len + 1);
 
+  ensureSharedSecretIsValid(recipient);
   auto pkt = createDatagram(PAYLOAD_TYPE_TXT_MSG, recipient.id, recipient.shared_secret, temp, 5 + text_len);
   if (pkt == NULL) return MSG_SEND_FAILED;
 
@@ -462,6 +464,7 @@ int BaseChatMesh::sendLogin(const ContactInfo& recipient, const char* password,
       tlen = 4 + len;
     }
 
+    ensureSharedSecretIsValid(recipient);
     pkt = createAnonDatagram(PAYLOAD_TYPE_ANON_REQ, self_id, recipient.id, recipient.shared_secret, temp, tlen);
   }
   if (pkt) {
@@ -489,6 +492,7 @@ int  BaseChatMesh::sendRequest(const ContactInfo& recipient, const uint8_t* req_
     memcpy(temp, &tag, 4);   // mostly an extra blob to help make packet_hash unique
     memcpy(&temp[4], req_data, data_len);
 
+    ensureSharedSecretIsValid(recipient);
     pkt = createDatagram(PAYLOAD_TYPE_REQ, recipient.id, recipient.shared_secret, temp, 4 + data_len);
   }
   if (pkt) {
@@ -516,6 +520,7 @@ int  BaseChatMesh::sendRequest(const ContactInfo& recipient, uint8_t req_type, u
     memset(&temp[5], 0, 4);  // reserved (possibly for 'since' param)
     getRNG()->random(&temp[9], 4);   // random blob to help make packet-hash unique
 
+    ensureSharedSecretIsValid(recipient);
     pkt = createDatagram(PAYLOAD_TYPE_REQ, recipient.id, recipient.shared_secret, temp, sizeof(temp));
   }
   if (pkt) {
@@ -639,6 +644,7 @@ void BaseChatMesh::checkConnections() {
       // calc expected ACK reply
       mesh::Utils::sha256((uint8_t *)&connections[i].expected_ack, 4, data, 9, self_id.pub_key, PUB_KEY_SIZE);
 
+      ensureSharedSecretIsValid(*contact);
       auto pkt = createDatagram(PAYLOAD_TYPE_REQ, contact->id, contact->shared_secret, data, 9);
       if (pkt) {
         sendDirect(pkt, contact->out_path, contact->out_path_len);
@@ -703,14 +709,20 @@ bool BaseChatMesh::addContact(const ContactInfo& contact) {
     auto dest = &contacts[num_contacts++];
     *dest = contact;
 
-    // calc the ECDH shared secret (just once for performance)
-    self_id.calcSharedSecret(dest->shared_secret, contact.id);
-
+    dest->shared_secret_valid = false; // mark shared_secret as needing calculation
     return true;  // success
   }
   return false;
 }
 
+void BaseChatMesh::ensureSharedSecretIsValid(const ContactInfo& contact) {
+  if (contact.shared_secret_valid) {
+    return; // already calculated
+  }
+  self_id.calcSharedSecret(contact.shared_secret, contact.id);
+  contact.shared_secret_valid = true;
+}
+
 bool BaseChatMesh::removeContact(ContactInfo& contact) {
   int idx = 0;
   while (idx < num_contacts && !contacts[idx].id.matches(contact.id)) {

+ 1 - 0
src/helpers/BaseChatMesh.h

@@ -73,6 +73,7 @@ class BaseChatMesh : public mesh::Mesh {
 
   mesh::Packet* composeMsgPacket(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char *text, uint32_t& expected_ack);
   void sendAckTo(const ContactInfo& dest, uint32_t ack_hash);
+  void ensureSharedSecretIsValid(const ContactInfo& contact);
 
 protected:
   BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables)

+ 2 - 1
src/helpers/ContactInfo.h

@@ -9,9 +9,10 @@ struct ContactInfo {
   uint8_t type;   // on of ADV_TYPE_*
   uint8_t flags;
   int8_t out_path_len;
+  mutable bool shared_secret_valid; // flag to indicate if shared_secret has been calculated
   uint8_t out_path[MAX_PATH_SIZE];
   uint32_t last_advert_timestamp;   // by THEIR clock
-  uint8_t shared_secret[PUB_KEY_SIZE];
+  mutable uint8_t shared_secret[PUB_KEY_SIZE];
   uint32_t lastmod;  // by OUR clock
   int32_t gps_lat, gps_lon;    // 6 dec places
   uint32_t sync_since;