Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions src/Identity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,24 @@ LocalIdentity::LocalIdentity(const char* prv_hex, const char* pub_hex) : Identit
}

LocalIdentity::LocalIdentity(RNG* rng) {
uint8_t seed[SEED_SIZE];
rng->random(seed, SEED_SIZE);
ed25519_create_keypair(pub_key, prv_key, seed);
}

bool LocalIdentity::readFrom(Stream& s) {
bool success = (s.readBytes(pub_key, PUB_KEY_SIZE) == PUB_KEY_SIZE);
success = success && (s.readBytes(prv_key, PRV_KEY_SIZE) == PRV_KEY_SIZE);
memset(seed, 0, SEED_SIZE);
if (success) {
s.readBytes(seed, SEED_SIZE);
}
return success;
}

bool LocalIdentity::writeTo(Stream& s) const {
bool success = (s.write(pub_key, PUB_KEY_SIZE) == PUB_KEY_SIZE);
success = success && (s.write(prv_key, PRV_KEY_SIZE) == PRV_KEY_SIZE);
success = success && (s.write(seed, SEED_SIZE) == SEED_SIZE);
return success;
}

Expand All @@ -65,26 +69,38 @@ void LocalIdentity::printTo(Stream& s) const {
s.print("prv_key: "); Utils::printHex(s, prv_key, PRV_KEY_SIZE); s.println();
}

size_t LocalIdentity::writeTo(uint8_t* dest, size_t max_len) {
size_t LocalIdentity::writePubkeyTo(uint8_t* dest, size_t max_len) {
if (max_len < PUB_KEY_SIZE) return 0; // not big enough
memcpy(dest, pub_key, PUB_KEY_SIZE);
return PUB_KEY_SIZE;
}

size_t LocalIdentity::writePrvkeyTo(uint8_t* dest, size_t max_len) {
if (max_len < PRV_KEY_SIZE) return 0; // not big enough
memcpy(dest, prv_key, PRV_KEY_SIZE);
return PRV_KEY_SIZE;
}

if (max_len < PRV_KEY_SIZE + PUB_KEY_SIZE) { // only room for prv_key
memcpy(dest, prv_key, PRV_KEY_SIZE);
return PRV_KEY_SIZE;
}
memcpy(dest, prv_key, PRV_KEY_SIZE); // otherwise can fit prv + pub keys
memcpy(&dest[PRV_KEY_SIZE], pub_key, PUB_KEY_SIZE);
return PRV_KEY_SIZE + PUB_KEY_SIZE;
size_t LocalIdentity::writeSeedTo(uint8_t* dest, size_t max_len) {
if (max_len < SEED_SIZE) return 0; // not big enough
memcpy(dest, seed, SEED_SIZE);
return SEED_SIZE;
}

void LocalIdentity::readFrom(const uint8_t* src, size_t len) {
if (len == PRV_KEY_SIZE + PUB_KEY_SIZE) { // has prv + pub keys
memcpy(prv_key, src, PRV_KEY_SIZE);
memcpy(pub_key, &src[PRV_KEY_SIZE], PUB_KEY_SIZE);
memset(seed, 0, SEED_SIZE);
} else if (len == PRV_KEY_SIZE) {
memcpy(prv_key, src, PRV_KEY_SIZE);
// now need to re-calculate the pub_key
ed25519_derive_pub(pub_key, prv_key);
memset(seed, 0, SEED_SIZE);
} else if (len == SEED_SIZE) {
memcpy(seed, src, SEED_SIZE);
// re-generate the keypair from the given seed
ed25519_create_keypair(pub_key, prv_key, seed);
}
}

Expand All @@ -96,4 +112,4 @@ void LocalIdentity::calcSharedSecret(uint8_t* secret, const uint8_t* other_pub_k
ed25519_key_exchange(secret, other_pub_key, prv_key);
}

}
}
15 changes: 14 additions & 1 deletion src/Identity.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Identity {
*/
class LocalIdentity : public Identity {
uint8_t prv_key[PRV_KEY_SIZE];
uint8_t seed[SEED_SIZE];
public:
LocalIdentity();
LocalIdentity(const char* prv_hex, const char* pub_hex);
Expand Down Expand Up @@ -76,7 +77,19 @@ class LocalIdentity : public Identity {
bool readFrom(Stream& s);
bool writeTo(Stream& s) const;
void printTo(Stream& s) const;
size_t writeTo(uint8_t* dest, size_t max_len);
size_t writePubkeyTo(uint8_t* dest, size_t max_len);
size_t writePrvkeyTo(uint8_t* dest, size_t max_len);
size_t writeSeedTo(uint8_t* dest, size_t max_len);
/**
* \brief Set the Ed25519 keypair.
* \param src IN - the source for the key(s) or seed
* \param len IN - length of the input; if equal to SEED_SIZE, src is
* assumed to be a new seed, from which new private and public keys
* will be generated. If equal to PRV_KEY_SIZE, the corresponding
* public key will be re-generated. If equal to PRV_KEY_SIZE+
* PUB_KEY_SIZE, no key regen is needed. The seed can only later
* be obtained via the `get prv.seed` CLI if SEED_SIZE is used.
*/
void readFrom(const uint8_t* src, size_t len);
};

Expand Down
18 changes: 17 additions & 1 deletion src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,14 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
sprintf(reply, "> %s", _prefs->guest_password);
} else if (sender_timestamp == 0 && memcmp(config, "prv.key", 7) == 0) { // from serial command line only
uint8_t prv_key[PRV_KEY_SIZE];
int len = _callbacks->getSelfId().writeTo(prv_key, PRV_KEY_SIZE);
int len = _callbacks->getSelfId().writePrvkeyTo(prv_key, PRV_KEY_SIZE);
mesh::Utils::toHex(tmp, prv_key, len);
sprintf(reply, "> %s", tmp);
} else if (sender_timestamp == 0 && memcmp(config, "prv.seed", 8) == 0) { // from serial command line only
uint8_t seed[SEED_SIZE];
int len = _callbacks->getSelfId().writeSeedTo(seed, SEED_SIZE);
mesh::Utils::toHex(tmp, seed, len);
sprintf(reply, "> %s", tmp);
} else if (memcmp(config, "name", 4) == 0) {
sprintf(reply, "> %s", _prefs->node_name);
} else if (memcmp(config, "repeat", 6) == 0) {
Expand Down Expand Up @@ -393,6 +398,17 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
} else {
strcpy(reply, "Error, invalid key");
}
} else if (sender_timestamp == 0 && memcmp(config, "prv.seed ", 9) == 0) { // from serial command line only
uint8_t seed[SEED_SIZE];
bool success = mesh::Utils::fromHex(seed, SEED_SIZE, &config[9]);
if (success) {
mesh::LocalIdentity new_id;
new_id.readFrom(seed, SEED_SIZE);
_callbacks->saveIdentity(new_id);
strcpy(reply, "OK");
} else {
strcpy(reply, "Error, invalid seed");
}
} else if (memcmp(config, "name ", 5) == 0) {
StrHelper::strncpy(_prefs->node_name, &config[5], sizeof(_prefs->node_name));
savePrefs();
Expand Down