bool signerSignMsg(MyMessage &msg) { bool ret; #if defined(MY_SIGNING_FEATURE) // If destination is known to require signed messages and we are the sender, // sign this message unless it is identified as an exception if (DO_SIGN(msg.destination) && msg.sender == getNodeId()) { if (skipSign(msg)) { ret = true; } else { // Send nonce-request _signingNonceStatus=SIGN_WAITING_FOR_NONCE; if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL, I_NONCE_REQUEST).set(""))) { SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n")); ret = false; } else { SIGN_DEBUG(PSTR("Nonce requested from %d. Waiting...\n"), msg.destination); // We have to wait for the nonce to arrive before we can sign our original message // Other messages could come in-between. We trust _process() takes care of them unsigned long enter = hwMillis(); _msgSign = msg; // Copy the message to sign since message buffer might be touched in _process() while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && _signingNonceStatus==SIGN_WAITING_FOR_NONCE) { _process(); } if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { SIGN_DEBUG(PSTR("Timeout waiting for nonce!\n")); ret = false; } else { if (_signingNonceStatus == SIGN_OK) { // process() received a nonce and signerProcessInternal successfully signed the message msg = _msgSign; // Write the signed message back SIGN_DEBUG(PSTR("Message to send has been signed\n")); ret = true; // After this point, only the 'last' member of the message structure is allowed to be altered if the // message has been signed, or signature will become invalid and the message rejected by the receiver } else { SIGN_DEBUG(PSTR("Message to send could not be signed!\n")); ret = false; } } } } } else if (getNodeId() == msg.sender) { mSetSigned(msg, 0); // Message is not supposed to be signed, make sure it is marked unsigned SIGN_DEBUG(PSTR("Will not sign message for destination %d as it does not require it\n"), msg.destination); ret = true; } else { SIGN_DEBUG(PSTR("Will not sign message since it was from %d and we are %d\n"), msg.sender, getNodeId()); ret = true; } #else (void)msg; ret = true; #endif // MY_SIGNING_FEATURE return ret; }
bool signerAtsha204SoftSignMsg(MyMessage &msg) { // If we cannot fit any signature in the message, refuse to sign it if (mGetLength(msg) > MAX_PAYLOAD-2) { DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0); return false; } // Calculate signature of message mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated signerCalculateSignature(msg); if (DO_WHITELIST(msg.destination)) { // Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided _signing_sha256.init(); for (int i=0; i<32; i++) _signing_sha256.write(_signing_hmac[i]); _signing_sha256.write(msg.sender); for (int i=0; i<SHA204_SERIAL_SZ; i++) _signing_sha256.write(_signing_node_serial_info[i]); memcpy(_signing_hmac, _signing_sha256.result(), 32); DEBUG_SIGNING_PRINTBUF(F("SHA256: "), _signing_hmac, 32); DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0); } // Overwrite the first byte in the signature with the signing identifier _signing_hmac[0] = SIGNING_IDENTIFIER; // Transfer as much signature data as the remaining space in the message permits memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg)); DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); return true; }
bool signerVerifyMsg(MyMessage &msg) { bool verificationResult = true; // Before processing message, reject unsigned messages if signing is required and check signature // (if it is signed and addressed to us) // Note that we do not care at all about any signature found if we do not require signing #if defined(MY_SIGNING_FEATURE) && defined(MY_SIGNING_REQUEST_SIGNATURES) // If we are a node, or we are a gateway and the sender require signatures (or just a strict gw) // and we are the destination... #if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) if (msg.destination == getNodeId()) { #else if ((!MY_IS_GATEWAY || DO_SIGN(msg.sender)) && msg.destination == getNodeId()) { #endif // Internal messages of certain types are not verified if (skipSign(msg)) { verificationResult = true; } else if (!mGetSigned(msg)) { // Got unsigned message that should have been signed SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n")); verificationResult = false; } else { if (!signerBackendVerifyMsg(msg)) { SIGN_DEBUG(PSTR("Signature verification failed!\n")); verificationResult = false; } #if defined(MY_NODE_LOCK_FEATURE) if (verificationResult) { // On successful verification, clear lock counters nof_nonce_requests = 0; nof_failed_verifications = 0; } else { nof_failed_verifications++; SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications); if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) { _nodeLock("TMFV"); //Too many failed verifications } } #endif mSetSigned(msg,0); // Clear the sign-flag now as verification is completed } } #else (void)msg; #endif // MY_SIGNING_REQUEST_SIGNATURES return verificationResult; } static uint8_t sha256_hash[32]; Sha256Class _soft_sha256; void signerSha256Init(void) { memset(sha256_hash, 0, 32); _soft_sha256.init(); }