Skip to content

Commit 585150c

Browse files
committed
Add and use timing neutral memcmp for signing
Fixes #443
1 parent 021412f commit 585150c

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

Diff for: libraries/MySensors/core/MySigning.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,32 @@ uint8_t* signerSha256Final(void) {
407407
memcpy(sha256_hash, _soft_sha256.result(), 32);
408408
return sha256_hash;
409409
}
410+
411+
int signerMemcmp(const void* a, const void* b, size_t sz) {
412+
int retVal;
413+
size_t i;
414+
int done = 0;
415+
const uint8_t* ptrA = (const uint8_t*)a;
416+
const uint8_t* ptrB = (const uint8_t*)b;
417+
for (i=0; i < sz; i++) {
418+
if (ptrA[i] == ptrB[i]) {
419+
if (done > 0) {
420+
done = 1;
421+
} else {
422+
done = 0;
423+
}
424+
} else {
425+
if (done > 0) {
426+
done = 2;
427+
} else {
428+
done = 3;
429+
}
430+
}
431+
}
432+
if (done > 0) {
433+
retVal = -1;
434+
} else {
435+
retVal = 0;
436+
}
437+
return retVal;
438+
}

Diff for: libraries/MySensors/core/MySigning.h

+14
Original file line numberDiff line numberDiff line change
@@ -622,5 +622,19 @@ void signerSha256Update(const uint8_t* data, size_t sz);
622622
*/
623623
uint8_t* signerSha256Final(void);
624624

625+
/**
626+
* @brief Do a timing neutral memory comparison.
627+
*
628+
* The function behaves similar to memcmp with the difference that it will
629+
* always use the same number of instructions for a given number of bytes,
630+
* no matter how the two buffers differ and the response is either 0 or -1.
631+
*
632+
* @param a First buffer for comparison.
633+
* @param b Second buffer for comparison.
634+
* @param sz The number of bytes to compare.
635+
* @returns 0 if buffers match, -1 if they do not.
636+
*/
637+
int signerMemcmp(const void* a, const void* b, size_t sz);
638+
625639
#endif
626640
/** @}*/

Diff for: libraries/MySensors/core/MySigningAtsha204.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
212212
_singning_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
213213

214214
// Compare the caluclated signature with the provided signature
215-
if (memcmp(&msg.data[mGetLength(msg)], &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) {
215+
if (signerMemcmp(&msg.data[mGetLength(msg)], &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) {
216216
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg));
217217
#ifdef MY_SIGNING_NODE_WHITELISTING
218218
DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0);

Diff for: libraries/MySensors/core/MySigningAtsha204Soft.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
222222
_signing_hmac[0] = SIGNING_IDENTIFIER;
223223

224224
// Compare the caluclated signature with the provided signature
225-
if (memcmp(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg))) {
225+
if (signerMemcmp(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg))) {
226226
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), _signing_hmac, MAX_PAYLOAD-mGetLength(msg));
227227
#ifdef MY_SIGNING_NODE_WHITELISTING
228228
DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0);

0 commit comments

Comments
 (0)