Refactor signing backend (#690)
Cleaned up the AES driver and removed some cppcheck isues in the process.
This commit is contained in:
committed by
Henrik Ekblad
parent
61e6cecb3f
commit
1040fbebc5
+286
-247
@@ -36,6 +36,9 @@
|
|||||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) && !defined(MY_SIGNING_REQUEST_SIGNATURES)
|
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL) && !defined(MY_SIGNING_REQUEST_SIGNATURES)
|
||||||
#error You have to require signatures if you want to require signatures from all (also enable MY_SIGNING_REQUEST_SIGNATURES in your gateway)
|
#error You have to require signatures if you want to require signatures from all (also enable MY_SIGNING_REQUEST_SIGNATURES in your gateway)
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MY_SIGNING_SOFT) && defined(MY_SIGNING_ATSHA204)
|
||||||
|
#error You have to pick one and only one signing backend
|
||||||
|
#endif
|
||||||
#ifdef MY_SIGNING_FEATURE
|
#ifdef MY_SIGNING_FEATURE
|
||||||
uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication
|
uint8_t _doSign[32]; // Bitfield indicating which sensors require signed communication
|
||||||
uint8_t _doWhitelist[32]; // Bitfield indicating which sensors require serial salted signatures
|
uint8_t _doWhitelist[32]; // Bitfield indicating which sensors require serial salted signatures
|
||||||
@@ -47,23 +50,17 @@ static uint8_t nof_nonce_requests = 0;
|
|||||||
static uint8_t nof_failed_verifications = 0;
|
static uint8_t nof_failed_verifications = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Status when waiting for signing nonce in signerProcessInternal
|
// Status when waiting for signing nonce in signerSignMsg
|
||||||
enum { SIGN_WAITING_FOR_NONCE = 0, SIGN_OK = 1 };
|
enum { SIGN_WAITING_FOR_NONCE = 0, SIGN_OK = 1 };
|
||||||
|
|
||||||
// Macros for manipulating signing requirement table
|
// Macros for manipulating signing requirement tables
|
||||||
#define DO_SIGN(node) (~_doSign[node>>3]&(1<<node%8))
|
#define DO_SIGN(node) (~_doSign[node>>3]&(1<<node%8))
|
||||||
#define SET_SIGN(node) (_doSign[node>>3]&=~(1<<node%8))
|
#define SET_SIGN(node) (_doSign[node>>3]&=~(1<<node%8))
|
||||||
#define CLEAR_SIGN(node) (_doSign[node>>3]|=(1<<node%8))
|
#define CLEAR_SIGN(node) (_doSign[node>>3]|=(1<<node%8))
|
||||||
|
#define DO_WHITELIST(node) (~_doWhitelist[node>>3]&(1<<node%8))
|
||||||
|
#define SET_WHITELIST(node) (_doWhitelist[node>>3]&=~(1<<node%8))
|
||||||
|
#define CLEAR_WHITELIST(node) (_doWhitelist[node>>3]|=(1<<node%8))
|
||||||
|
|
||||||
/*
|
|
||||||
* Stores signing identifier and a new nonce in provided message for signing operations.
|
|
||||||
*
|
|
||||||
* All space in message payload buffer is used for signing identifier and nonce.
|
|
||||||
* Returns false if subsystem is busy processing an ongoing signing operation.
|
|
||||||
* If successful, this marks the start of a signing operation at the receiving side so
|
|
||||||
* implementation is expected to do any necessary initializations within this call.
|
|
||||||
* This function is typically called as action when receiving a I_NONCE_REQUEST message.
|
|
||||||
*/
|
|
||||||
#if defined(MY_SIGNING_SOFT)
|
#if defined(MY_SIGNING_SOFT)
|
||||||
extern void signerAtsha204SoftInit(void);
|
extern void signerAtsha204SoftInit(void);
|
||||||
extern bool signerAtsha204SoftCheckTimer(void);
|
extern bool signerAtsha204SoftCheckTimer(void);
|
||||||
@@ -71,53 +68,34 @@ extern bool signerAtsha204SoftGetNonce(MyMessage &msg);
|
|||||||
extern void signerAtsha204SoftPutNonce(MyMessage &msg);
|
extern void signerAtsha204SoftPutNonce(MyMessage &msg);
|
||||||
extern bool signerAtsha204SoftVerifyMsg(MyMessage &msg);
|
extern bool signerAtsha204SoftVerifyMsg(MyMessage &msg);
|
||||||
extern bool signerAtsha204SoftSignMsg(MyMessage &msg);
|
extern bool signerAtsha204SoftSignMsg(MyMessage &msg);
|
||||||
#endif
|
#define signerBackendInit signerAtsha204SoftInit
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
#define signerBackendCheckTimer signerAtsha204SoftCheckTimer
|
||||||
|
#define signerBackendGetNonce signerAtsha204SoftGetNonce
|
||||||
|
#define signerBackendPutNonce signerAtsha204SoftPutNonce
|
||||||
|
#define signerBackendVerifyMsg signerAtsha204SoftVerifyMsg
|
||||||
|
#define signerBackendSignMsg signerAtsha204SoftSignMsg
|
||||||
|
#elif defined(MY_SIGNING_ATSHA204)
|
||||||
extern void signerAtsha204Init(void);
|
extern void signerAtsha204Init(void);
|
||||||
extern bool signerAtsha204CheckTimer(void);
|
extern bool signerAtsha204CheckTimer(void);
|
||||||
extern bool signerAtsha204GetNonce(MyMessage &msg);
|
extern bool signerAtsha204GetNonce(MyMessage &msg);
|
||||||
extern void signerAtsha204PutNonce(MyMessage &msg);
|
extern void signerAtsha204PutNonce(MyMessage &msg);
|
||||||
extern bool signerAtsha204VerifyMsg(MyMessage &msg);
|
extern bool signerAtsha204VerifyMsg(MyMessage &msg);
|
||||||
extern bool signerAtsha204SignMsg(MyMessage &msg);
|
extern bool signerAtsha204SignMsg(MyMessage &msg);
|
||||||
|
#define signerBackendInit signerAtsha204Init
|
||||||
|
#define signerBackendCheckTimer signerAtsha204CheckTimer
|
||||||
|
#define signerBackendGetNonce signerAtsha204GetNonce
|
||||||
|
#define signerBackendPutNonce signerAtsha204PutNonce
|
||||||
|
#define signerBackendVerifyMsg signerAtsha204VerifyMsg
|
||||||
|
#define signerBackendSignMsg signerAtsha204SignMsg
|
||||||
#endif
|
#endif
|
||||||
|
static bool skipSign(MyMessage &msg);
|
||||||
// Helper function to centralize signing/verification exceptions
|
#else // not MY_SIGNING_FEATURE
|
||||||
static bool skipSign(MyMessage &msg)
|
#define signerBackendCheckTimer() true
|
||||||
{
|
|
||||||
if mGetAck(msg) {
|
|
||||||
SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type);
|
|
||||||
return true;
|
|
||||||
} else if (mGetCommand(msg) == C_INTERNAL &&
|
|
||||||
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE ||
|
|
||||||
msg.type == I_SIGNING_PRESENTATION ||
|
|
||||||
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
|
|
||||||
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
|
|
||||||
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
|
|
||||||
msg.type == I_PING || msg.type == I_PONG ||
|
|
||||||
msg.type == I_REGISTRATION_REQUEST )) {
|
|
||||||
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
|
||||||
return true;
|
|
||||||
} else if (mGetCommand(msg) == C_STREAM &&
|
|
||||||
(msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE ||
|
|
||||||
msg.type == ST_SOUND || msg.type == ST_IMAGE)) {
|
|
||||||
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // MY_SIGNING_FEATURE
|
#endif // MY_SIGNING_FEATURE
|
||||||
|
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination);
|
||||||
// Helper to prepare a signing presentation message
|
static bool signerInternalProcessPresentation(MyMessage &msg);
|
||||||
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
|
static bool signerInternalProcessNonceRequest(MyMessage &msg);
|
||||||
{
|
static bool signerInternalProcessNonceResponse(MyMessage &msg);
|
||||||
// Only supports version 1 for now
|
|
||||||
(void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set("");
|
|
||||||
mSetLength(msg, 2);
|
|
||||||
mSetPayloadType(msg, P_CUSTOM); // displayed as hex
|
|
||||||
msg.data[0] = SIGNING_PRESENTATION_VERSION_1;
|
|
||||||
msg.data[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void signerInit(void)
|
void signerInit(void)
|
||||||
{
|
{
|
||||||
@@ -130,12 +108,7 @@ void signerInit(void)
|
|||||||
hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
hwReadConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
||||||
sizeof(_doWhitelist));
|
sizeof(_doWhitelist));
|
||||||
|
|
||||||
#if defined(MY_SIGNING_SOFT)
|
signerBackendInit();
|
||||||
signerAtsha204SoftInit();
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
|
||||||
signerAtsha204Init();
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,212 +137,92 @@ void signerPresentation(MyMessage &msg, uint8_t destination)
|
|||||||
|
|
||||||
bool signerProcessInternal(MyMessage &msg)
|
bool signerProcessInternal(MyMessage &msg)
|
||||||
{
|
{
|
||||||
uint8_t sender = msg.sender;
|
bool ret;
|
||||||
(void)sender;
|
switch (msg.type) {
|
||||||
#if !defined(MY_SIGNING_FEATURE)
|
case I_SIGNING_PRESENTATION:
|
||||||
if (msg.type == I_SIGNING_PRESENTATION) {
|
ret = signerInternalProcessPresentation(msg);
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
break;
|
||||||
// If we act as gateway and do not have the signing feature and receive a signing request we still
|
case I_NONCE_REQUEST:
|
||||||
// need to do make sure the requester does not believe the gateway still require signatures
|
ret = signerInternalProcessNonceRequest(msg);
|
||||||
prepareSigningPresentation(msg, sender);
|
break;
|
||||||
SIGN_DEBUG(
|
case I_NONCE_RESPONSE:
|
||||||
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
|
ret = signerInternalProcessNonceResponse(msg);
|
||||||
sender);
|
break;
|
||||||
if (!_sendRoute(msg)) {
|
default:
|
||||||
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
ret = false; // Let the transport process this message further as it is not related to signing
|
||||||
}
|
break;
|
||||||
return true; // No need to further process I_SIGNING_PRESENTATION in this case
|
|
||||||
#else
|
|
||||||
// If we act as a node and do not have the signing feature then we just silently drop any signing
|
|
||||||
// presentation messages received
|
|
||||||
SIGN_DEBUG(PSTR("Received signing presentation, but signing is not supported (message ignored)\n"));
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#elif defined(MY_SIGNING_FEATURE)
|
return ret;
|
||||||
if (msg.type == I_NONCE_REQUEST) {
|
|
||||||
#if defined(MY_NODE_LOCK_FEATURE)
|
|
||||||
nof_nonce_requests++;
|
|
||||||
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"),
|
|
||||||
MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
|
|
||||||
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
|
|
||||||
_nodeLock("TMNR"); //Too many nonces requested
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_SOFT)
|
|
||||||
if (signerAtsha204SoftGetNonce(msg)) {
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
|
||||||
if (signerAtsha204GetNonce(msg)) {
|
|
||||||
#endif
|
|
||||||
if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) {
|
|
||||||
SIGN_DEBUG(PSTR("Failed to transmit nonce!\n"));
|
|
||||||
} else {
|
|
||||||
SIGN_DEBUG(PSTR("Transmitted nonce\n"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SIGN_DEBUG(PSTR("Failed to generate nonce!\n"));
|
|
||||||
}
|
|
||||||
return true; // No need to further process I_NONCE_REQUEST
|
|
||||||
} else if (msg.type == I_SIGNING_PRESENTATION) {
|
|
||||||
if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
|
|
||||||
SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
|
|
||||||
return true; // Just drop this presentation message
|
|
||||||
}
|
|
||||||
// We only handle version 1 here...
|
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
|
||||||
// We received an indicator that the sender require us to sign all messages we send to it
|
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender);
|
|
||||||
SET_SIGN(msg.sender);
|
|
||||||
} else {
|
|
||||||
// We received an indicator that the sender does not require us to sign all messages we send to it
|
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender);
|
|
||||||
CLEAR_SIGN(msg.sender);
|
|
||||||
}
|
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
|
||||||
// We received an indicator that the sender require us to salt signatures with serial
|
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender);
|
|
||||||
SET_WHITELIST(msg.sender);
|
|
||||||
} else {
|
|
||||||
// We received an indicator that the sender does not require us to sign all messages we send to it
|
|
||||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender);
|
|
||||||
CLEAR_WHITELIST(msg.sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save updated tables
|
|
||||||
hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
|
|
||||||
sizeof(_doSign));
|
|
||||||
hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
|
||||||
sizeof(_doWhitelist));
|
|
||||||
|
|
||||||
// Inform sender about our preference if we are a gateway, but only require signing if the sender
|
|
||||||
// required signing unless we explicitly configure it to
|
|
||||||
// We do not want a gateway to require signing from all nodes in a network just because it wants one node
|
|
||||||
// to sign it's messages unless we explicitly configure it to
|
|
||||||
#if defined(MY_GATEWAY_FEATURE)
|
|
||||||
prepareSigningPresentation(msg, sender);
|
|
||||||
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
|
|
||||||
if (DO_SIGN(sender)) {
|
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
|
||||||
}
|
|
||||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_NODE_WHITELISTING)
|
|
||||||
if (DO_WHITELIST(sender)) {
|
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
|
||||||
}
|
|
||||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
|
||||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender);
|
|
||||||
} else {
|
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender);
|
|
||||||
}
|
|
||||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender);
|
|
||||||
} else {
|
|
||||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), sender);
|
|
||||||
}
|
|
||||||
if (!_sendRoute(msg)) {
|
|
||||||
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
|
||||||
}
|
|
||||||
#endif // MY_GATEWAY_FEATURE
|
|
||||||
return true; // No need to further process I_SIGNING_PRESENTATION
|
|
||||||
} else if (msg.type == I_NONCE_RESPONSE) {
|
|
||||||
// Proceed with signing if nonce has been received
|
|
||||||
SIGN_DEBUG(PSTR("Nonce received from %d. Proceeding with signing...\n"), sender);
|
|
||||||
if (sender != _msgSign.destination) {
|
|
||||||
SIGN_DEBUG(PSTR("Nonce did not come from the destination (%d) of the message to be signed! "
|
|
||||||
"It came from %d.\n"), _msgSign.destination, sender);
|
|
||||||
SIGN_DEBUG(PSTR("Silently discarding this nonce\n"));
|
|
||||||
return true; // No need to further process I_NONCE_RESPONSE
|
|
||||||
}
|
|
||||||
#if defined(MY_SIGNING_SOFT)
|
|
||||||
signerAtsha204SoftPutNonce(msg);
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
|
||||||
signerAtsha204PutNonce(msg);
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_SOFT)
|
|
||||||
if (!signerAtsha204SoftSignMsg(_msgSign)) {
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
|
||||||
if (!signerAtsha204SignMsg(_msgSign)) {
|
|
||||||
#endif
|
|
||||||
SIGN_DEBUG(PSTR("Failed to sign message!\n"));
|
|
||||||
} else {
|
|
||||||
SIGN_DEBUG(PSTR("Message signed\n"));
|
|
||||||
_signingNonceStatus = SIGN_OK; // _msgSign now contains the signed message pending transmission
|
|
||||||
}
|
|
||||||
return true; // No need to further process I_NONCE_RESPONSE
|
|
||||||
}
|
|
||||||
#endif // MY_SIGNING_FEATURE
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signerCheckTimer(void) {
|
bool signerCheckTimer(void)
|
||||||
#if defined(MY_SIGNING_SOFT)
|
{
|
||||||
return signerAtsha204SoftCheckTimer();
|
return signerBackendCheckTimer();
|
||||||
#elif defined(MY_SIGNING_ATSHA204)
|
|
||||||
return signerAtsha204CheckTimer();
|
|
||||||
#else
|
|
||||||
return true; // Without a configured backend, we always give "positive" results
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signerSignMsg(MyMessage &msg) {
|
bool signerSignMsg(MyMessage &msg)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
#if defined(MY_SIGNING_FEATURE)
|
#if defined(MY_SIGNING_FEATURE)
|
||||||
// If destination is known to require signed messages and we are the sender,
|
// If destination is known to require signed messages and we are the sender,
|
||||||
// sign this message unless it is a handshake message
|
// sign this message unless it is identified as an exception
|
||||||
if (DO_SIGN(msg.destination) && msg.sender == getNodeId()) {
|
if (DO_SIGN(msg.destination) && msg.sender == getNodeId()) {
|
||||||
if (skipSign(msg)) {
|
if (skipSign(msg)) {
|
||||||
return true;
|
ret = true;
|
||||||
} else {
|
} else {
|
||||||
// Send nonce-request
|
// Send nonce-request
|
||||||
_signingNonceStatus=SIGN_WAITING_FOR_NONCE;
|
_signingNonceStatus=SIGN_WAITING_FOR_NONCE;
|
||||||
if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
|
if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
|
||||||
I_NONCE_REQUEST).set(""))) {
|
I_NONCE_REQUEST).set(""))) {
|
||||||
SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n"));
|
SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n"));
|
||||||
return false;
|
ret = false;
|
||||||
}
|
|
||||||
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"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
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"));
|
|
||||||
} else {
|
} else {
|
||||||
SIGN_DEBUG(PSTR("Message to send could not be signed!\n"));
|
SIGN_DEBUG(PSTR("Nonce requested from %d. Waiting...\n"), msg.destination);
|
||||||
return false;
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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 if (getNodeId() == msg.sender) {
|
} else if (getNodeId() == msg.sender) {
|
||||||
mSetSigned(msg, 0); // Message is not supposed to be signed, make sure it is marked unsigned
|
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
|
#else
|
||||||
(void)msg;
|
(void)msg;
|
||||||
|
ret = true;
|
||||||
#endif // MY_SIGNING_FEATURE
|
#endif // MY_SIGNING_FEATURE
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signerVerifyMsg(MyMessage &msg) {
|
bool signerVerifyMsg(MyMessage &msg)
|
||||||
|
{
|
||||||
bool verificationResult = true;
|
bool verificationResult = true;
|
||||||
// Before processing message, reject unsigned messages if signing is required and check signature
|
// Before processing message, reject unsigned messages if signing is required and check signature
|
||||||
// (if it is signed and addressed to us)
|
// (if it is signed and addressed to us)
|
||||||
@@ -390,14 +243,9 @@ bool signerVerifyMsg(MyMessage &msg) {
|
|||||||
SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n"));
|
SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n"));
|
||||||
verificationResult = false;
|
verificationResult = false;
|
||||||
} else {
|
} else {
|
||||||
#if defined(MY_SIGNING_SOFT)
|
if (!signerBackendVerifyMsg(msg)) {
|
||||||
verificationResult = signerAtsha204SoftVerifyMsg(msg);
|
|
||||||
#endif
|
|
||||||
#if defined(MY_SIGNING_ATSHA204)
|
|
||||||
verificationResult = signerAtsha204VerifyMsg(msg);
|
|
||||||
#endif
|
|
||||||
if (!verificationResult) {
|
|
||||||
SIGN_DEBUG(PSTR("Signature verification failed!\n"));
|
SIGN_DEBUG(PSTR("Signature verification failed!\n"));
|
||||||
|
verificationResult = false;
|
||||||
}
|
}
|
||||||
#if defined(MY_NODE_LOCK_FEATURE)
|
#if defined(MY_NODE_LOCK_FEATURE)
|
||||||
if (verificationResult) {
|
if (verificationResult) {
|
||||||
@@ -425,23 +273,27 @@ bool signerVerifyMsg(MyMessage &msg) {
|
|||||||
static uint8_t sha256_hash[32];
|
static uint8_t sha256_hash[32];
|
||||||
Sha256Class _soft_sha256;
|
Sha256Class _soft_sha256;
|
||||||
|
|
||||||
void signerSha256Init(void) {
|
void signerSha256Init(void)
|
||||||
|
{
|
||||||
memset(sha256_hash, 0, 32);
|
memset(sha256_hash, 0, 32);
|
||||||
_soft_sha256.init();
|
_soft_sha256.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void signerSha256Update(const uint8_t* data, size_t sz) {
|
void signerSha256Update(const uint8_t* data, size_t sz)
|
||||||
|
{
|
||||||
for (size_t i = 0; i < sz; i++) {
|
for (size_t i = 0; i < sz; i++) {
|
||||||
_soft_sha256.write(data[i]);
|
_soft_sha256.write(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* signerSha256Final(void) {
|
uint8_t* signerSha256Final(void)
|
||||||
|
{
|
||||||
memcpy(sha256_hash, _soft_sha256.result(), 32);
|
memcpy(sha256_hash, _soft_sha256.result(), 32);
|
||||||
return sha256_hash;
|
return sha256_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
int signerMemcmp(const void* a, const void* b, size_t sz) {
|
int signerMemcmp(const void* a, const void* b, size_t sz)
|
||||||
|
{
|
||||||
int retVal;
|
int retVal;
|
||||||
size_t i;
|
size_t i;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
@@ -469,3 +321,190 @@ int signerMemcmp(const void* a, const void* b, size_t sz) {
|
|||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MY_SIGNING_FEATURE)
|
||||||
|
// Helper function to centralize signing/verification exceptions
|
||||||
|
static bool skipSign(MyMessage &msg)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
if (mGetAck(msg)) {
|
||||||
|
SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||||
|
ret = true;
|
||||||
|
} else if (mGetCommand(msg) == C_INTERNAL &&
|
||||||
|
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE ||
|
||||||
|
msg.type == I_SIGNING_PRESENTATION ||
|
||||||
|
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
|
||||||
|
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
|
||||||
|
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
|
||||||
|
msg.type == I_PING || msg.type == I_PONG ||
|
||||||
|
msg.type == I_REGISTRATION_REQUEST )) {
|
||||||
|
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||||
|
ret = true;
|
||||||
|
} else if (mGetCommand(msg) == C_STREAM &&
|
||||||
|
(msg.type == ST_FIRMWARE_REQUEST || msg.type == ST_FIRMWARE_RESPONSE ||
|
||||||
|
msg.type == ST_SOUND || msg.type == ST_IMAGE)) {
|
||||||
|
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Helper to prepare a signing presentation message
|
||||||
|
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
|
||||||
|
{
|
||||||
|
// Only supports version 1 for now
|
||||||
|
(void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set("");
|
||||||
|
mSetLength(msg, 2);
|
||||||
|
mSetPayloadType(msg, P_CUSTOM); // displayed as hex
|
||||||
|
msg.data[0] = SIGNING_PRESENTATION_VERSION_1;
|
||||||
|
msg.data[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to process presentation mesages
|
||||||
|
static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||||
|
{
|
||||||
|
#if defined(MY_SIGNING_FEATURE)
|
||||||
|
if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
|
||||||
|
SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
|
||||||
|
return true; // Just drop this presentation message
|
||||||
|
}
|
||||||
|
// We only handle version 1 here...
|
||||||
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
||||||
|
// We received an indicator that the sender require us to sign all messages we send to it
|
||||||
|
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender);
|
||||||
|
SET_SIGN(msg.sender);
|
||||||
|
} else {
|
||||||
|
// We received an indicator that the sender does not require us to sign all messages we send to it
|
||||||
|
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender);
|
||||||
|
CLEAR_SIGN(msg.sender);
|
||||||
|
}
|
||||||
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
||||||
|
// We received an indicator that the sender require us to salt signatures with serial
|
||||||
|
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender);
|
||||||
|
SET_WHITELIST(msg.sender);
|
||||||
|
} else {
|
||||||
|
// We received an indicator that the sender does not require us to sign all messages we send to it
|
||||||
|
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender);
|
||||||
|
CLEAR_WHITELIST(msg.sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save updated tables
|
||||||
|
hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
|
||||||
|
sizeof(_doSign));
|
||||||
|
hwWriteConfigBlock((void*)_doWhitelist, (void*)EEPROM_WHITELIST_REQUIREMENT_TABLE_ADDRESS,
|
||||||
|
sizeof(_doWhitelist));
|
||||||
|
|
||||||
|
// Inform sender about our preference if we are a gateway, but only require signing if the sender
|
||||||
|
// required signing unless we explicitly configure it to
|
||||||
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
|
prepareSigningPresentation(msg, msg.sender);
|
||||||
|
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
|
||||||
|
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||||
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
||||||
|
#else
|
||||||
|
if (DO_SIGN(msg.sender)) {
|
||||||
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // MY_SIGNING_REQUEST_SIGNATURES
|
||||||
|
#if defined(MY_SIGNING_NODE_WHITELISTING)
|
||||||
|
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||||
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
||||||
|
#else
|
||||||
|
if (DO_WHITELIST(msg.sender)) {
|
||||||
|
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // MY_SIGNING_NODE_WHITELISTING
|
||||||
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
||||||
|
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), msg.sender);
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), msg.sender);
|
||||||
|
}
|
||||||
|
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
||||||
|
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), msg.sender);
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), msg.sender);
|
||||||
|
}
|
||||||
|
if (!_sendRoute(msg)) {
|
||||||
|
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
||||||
|
}
|
||||||
|
#endif // MY_GATEWAY_FEATURE
|
||||||
|
#else // not MY_SIGNING_FEATURE
|
||||||
|
#if defined(MY_GATEWAY_FEATURE)
|
||||||
|
// If we act as gateway and do not have the signing feature and receive a signing request we still
|
||||||
|
// need to do make sure the requester does not believe the gateway still require signatures
|
||||||
|
prepareSigningPresentation(msg, msg.sender);
|
||||||
|
SIGN_DEBUG(
|
||||||
|
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
|
||||||
|
msg.sender);
|
||||||
|
if (!_sendRoute(msg)) {
|
||||||
|
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
||||||
|
}
|
||||||
|
#else // not MY_GATEWAY_FEATURE
|
||||||
|
// If we act as a node and do not have the signing feature then we just silently drop any signing
|
||||||
|
// presentation messages received
|
||||||
|
(void)msg;
|
||||||
|
SIGN_DEBUG(PSTR("Received signing presentation, but signing is not supported (message ignored)\n"));
|
||||||
|
#endif // not MY_GATEWAY_FEATURE
|
||||||
|
#endif // not MY_SIGNING_FEATURE
|
||||||
|
return true; // No need to further process I_SIGNING_PRESENTATION
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to process nonce request mesages
|
||||||
|
static bool signerInternalProcessNonceRequest(MyMessage &msg)
|
||||||
|
{
|
||||||
|
#if defined(MY_SIGNING_FEATURE)
|
||||||
|
#if defined(MY_NODE_LOCK_FEATURE)
|
||||||
|
nof_nonce_requests++;
|
||||||
|
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"),
|
||||||
|
MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
|
||||||
|
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
|
||||||
|
_nodeLock("TMNR"); //Too many nonces requested
|
||||||
|
}
|
||||||
|
#endif // MY_NODE_LOCK_FEATURE
|
||||||
|
if (signerBackendGetNonce(msg)) {
|
||||||
|
if (!_sendRoute(build(msg, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_NONCE_RESPONSE))) {
|
||||||
|
SIGN_DEBUG(PSTR("Failed to transmit nonce!\n"));
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Transmitted nonce\n"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Failed to generate nonce!\n"));
|
||||||
|
}
|
||||||
|
#else // not MY_SIGNING_FEATURE
|
||||||
|
(void)msg;
|
||||||
|
SIGN_DEBUG(PSTR("Received nonce request, but signing is not supported (message ignored)\n"));
|
||||||
|
#endif // MY_SIGNING_FEATURE
|
||||||
|
return true; // No need to further process I_NONCE_REQUEST
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to process nonce response mesages
|
||||||
|
static bool signerInternalProcessNonceResponse(MyMessage &msg)
|
||||||
|
{
|
||||||
|
#if defined(MY_SIGNING_FEATURE)
|
||||||
|
// Proceed with signing if nonce has been received
|
||||||
|
SIGN_DEBUG(PSTR("Nonce received from %d.\n"), msg.sender);
|
||||||
|
if (msg.sender != _msgSign.destination) {
|
||||||
|
SIGN_DEBUG(PSTR("Nonce did not come from the destination (%d) of the message to be signed! "
|
||||||
|
"It came from %d.\n"), _msgSign.destination, msg.sender);
|
||||||
|
SIGN_DEBUG(PSTR("Silently discarding this nonce\n"));
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Proceeding with signing...\n"));
|
||||||
|
signerBackendPutNonce(msg);
|
||||||
|
if (!signerBackendSignMsg(_msgSign)) {
|
||||||
|
SIGN_DEBUG(PSTR("Failed to sign message!\n"));
|
||||||
|
} else {
|
||||||
|
SIGN_DEBUG(PSTR("Message signed\n"));
|
||||||
|
_signingNonceStatus = SIGN_OK; // _msgSign now contains the signed message pending transmission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)msg;
|
||||||
|
SIGN_DEBUG(PSTR("Received nonce response, but signing is not supported (message ignored)\n"));
|
||||||
|
#endif
|
||||||
|
return true; // No need to further process I_NONCE_RESPONSE
|
||||||
|
}
|
||||||
|
|||||||
@@ -490,14 +490,6 @@ typedef struct {
|
|||||||
/** @brief Helper macro to determine the number of elements in a array */
|
/** @brief Helper macro to determine the number of elements in a array */
|
||||||
#define NUM_OF(x) (sizeof(x)/sizeof(x[0]))
|
#define NUM_OF(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
/** @brief Helper macro to determine if node require serial salted signatures */
|
|
||||||
#define DO_WHITELIST(node) (~_doWhitelist[node>>3]&(1<<node%8))
|
|
||||||
/** @brief Helper macro to set that node require serial salted signatures */
|
|
||||||
#define SET_WHITELIST(node) (_doWhitelist[node>>3]&=~(1<<node%8))
|
|
||||||
/** @brief Helper macro to set that node does not require serial salted signatures */
|
|
||||||
#define CLEAR_WHITELIST(node) (_doWhitelist[node>>3]|=(1<<node%8))
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes signing infrastructure and associated backend.
|
* @brief Initializes signing infrastructure and associated backend.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ static char i2h(uint8_t i)
|
|||||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||||
{
|
{
|
||||||
static char printBuffer[300];
|
static char printBuffer[300];
|
||||||
|
if (NULL == buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
#ifdef MY_GATEWAY_FEATURE
|
#ifdef MY_GATEWAY_FEATURE
|
||||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||||
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
||||||
|
|||||||
@@ -64,25 +64,17 @@ static char i2h(uint8_t i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz)
|
#define __FlashStringHelper char
|
||||||
{
|
#define MY_SERIALDEVICE.print debug
|
||||||
static char printBuffer[300];
|
#endif
|
||||||
|
|
||||||
for (int i=0; i<sz; i++) {
|
|
||||||
printBuffer[i * 2] = i2h(buf[i] >> 4);
|
|
||||||
printBuffer[(i * 2) + 1] = i2h(buf[i]);
|
|
||||||
}
|
|
||||||
printBuffer[sz * 2] = '\0';
|
|
||||||
debug(str);
|
|
||||||
if (sz > 0) {
|
|
||||||
debug(printBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||||
{
|
{
|
||||||
static char printBuffer[300];
|
static char printBuffer[300];
|
||||||
#ifdef MY_GATEWAY_FEATURE
|
if (NULL == buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if defined(MY_GATEWAY_FEATURE) && !defined(__linux__)
|
||||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||||
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
||||||
MY_SERIALDEVICE.print(printBuffer);
|
MY_SERIALDEVICE.print(printBuffer);
|
||||||
@@ -92,7 +84,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
|
|||||||
printBuffer[(i * 2) + 1] = i2h(buf[i]);
|
printBuffer[(i * 2) + 1] = i2h(buf[i]);
|
||||||
}
|
}
|
||||||
printBuffer[sz * 2] = '\0';
|
printBuffer[sz * 2] = '\0';
|
||||||
#ifdef MY_GATEWAY_FEATURE
|
#if defined(MY_GATEWAY_FEATURE) && !defined(__linux__)
|
||||||
// Truncate message if this is gateway node
|
// Truncate message if this is gateway node
|
||||||
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
|
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
|
||||||
#endif
|
#endif
|
||||||
@@ -100,9 +92,10 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
|
|||||||
if (sz > 0) {
|
if (sz > 0) {
|
||||||
MY_SERIALDEVICE.print(printBuffer);
|
MY_SERIALDEVICE.print(printBuffer);
|
||||||
}
|
}
|
||||||
|
#if !defined(__linux__)
|
||||||
MY_SERIALDEVICE.println("");
|
MY_SERIALDEVICE.println("");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* __linux__ */
|
|
||||||
#else
|
#else
|
||||||
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
|
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+6
-1
@@ -104,7 +104,7 @@ const static byte s_inv [0x100] PROGMEM = {
|
|||||||
} ;
|
} ;
|
||||||
|
|
||||||
// times 2 in the GF(2^8)
|
// times 2 in the GF(2^8)
|
||||||
#define f2(x) ((x) & 0x80 ? (x << 1) ^ WPOLY : x << 1)
|
#define f2(x) (((x) & 0x80) ? (x << 1) ^ WPOLY : x << 1)
|
||||||
#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
|
#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
|
||||||
|
|
||||||
static byte s_box (byte x)
|
static byte s_box (byte x)
|
||||||
@@ -248,6 +248,11 @@ static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
|||||||
AES::AES()
|
AES::AES()
|
||||||
{
|
{
|
||||||
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
|
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
|
||||||
|
IVC = 0x01;
|
||||||
|
round = 0;
|
||||||
|
pad = 0;
|
||||||
|
size = 0;
|
||||||
|
memset(key_sched, 0, KEY_SCHEDULE_BYTES);
|
||||||
memcpy(iv,ar_iv,8);
|
memcpy(iv,ar_iv,8);
|
||||||
memcpy(iv+8,ar_iv,8);
|
memcpy(iv+8,ar_iv,8);
|
||||||
arr_pad[0] = 0x01;
|
arr_pad[0] = 0x01;
|
||||||
|
|||||||
@@ -312,42 +312,6 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @example aes.pde
|
|
||||||
* <b>For Arduino</b><br>
|
|
||||||
* <b>Updated: spaniakos 2015 </b><br>
|
|
||||||
*
|
|
||||||
* This is an example of how to use AES in CBC mode easily.
|
|
||||||
* The text and keys can be either in HEX or String format.<br />
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @example aes.cpp
|
|
||||||
* <b>For Rasberry pi</b><br>
|
|
||||||
* <b>Updated: spaniakos 2015 </b><br>
|
|
||||||
*
|
|
||||||
* This is an example of how to use AES in CBC mode easily.
|
|
||||||
* The text and keys can be either in HEX or String format.<br />
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @example test_vectors.pde
|
|
||||||
* <b>For Arduino</b><br>
|
|
||||||
* <b>Updated: spaniakos 2015 </b><br>
|
|
||||||
*
|
|
||||||
* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
|
|
||||||
* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @example test_vectors.cpp
|
|
||||||
* <b>For Rasberry pi</b><br>
|
|
||||||
* <b>Updated: spaniakos 2015 </b><br>
|
|
||||||
*
|
|
||||||
* This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.<br />
|
|
||||||
* plus is a classical approach to the AES encryption library with out the easy to use add-on modifications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup aeslib AES library for Arduino and Raspberry pi
|
* @defgroup aeslib AES library for Arduino and Raspberry pi
|
||||||
* @ingroup internals
|
* @ingroup internals
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,62 +0,0 @@
|
|||||||
#############################################################################
|
|
||||||
#
|
|
||||||
# Makefile for AES on Raspberry Pi
|
|
||||||
#
|
|
||||||
# License: GPL (General Public License)
|
|
||||||
# Author: Georgios Spanos (spaniakos) <spaniakos@gmail.com>
|
|
||||||
# Date: 02/12/2014
|
|
||||||
#
|
|
||||||
# Description:
|
|
||||||
# ------------
|
|
||||||
# use make all and mak install to install the library
|
|
||||||
# You can change the install directory by editing the LIBDIR line
|
|
||||||
#
|
|
||||||
PREFIX=/usr/local
|
|
||||||
|
|
||||||
# Library parameters
|
|
||||||
# where to put the lib
|
|
||||||
LIBDIR=$(PREFIX)/lib
|
|
||||||
# lib name
|
|
||||||
LIB=libAES
|
|
||||||
# shared library name
|
|
||||||
LIBNAME=$(LIB).so.1.0
|
|
||||||
|
|
||||||
# Where to put the header files
|
|
||||||
HEADER_DIR=${PREFIX}/include/AES
|
|
||||||
|
|
||||||
# The recommended compiler flags for the Raspberry Pi
|
|
||||||
CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
|
|
||||||
|
|
||||||
# make all
|
|
||||||
# reinstall the library after each recompilation
|
|
||||||
all: libAES
|
|
||||||
|
|
||||||
# Make the library
|
|
||||||
libAES: AES.o
|
|
||||||
g++ -shared -Wl,-soname,$@.so.1 ${CCFLAGS} -o ${LIBNAME} $^
|
|
||||||
|
|
||||||
# Library parts
|
|
||||||
AES.o: AES.cpp
|
|
||||||
g++ -Wall -fPIC ${CCFLAGS} -c $^
|
|
||||||
|
|
||||||
# clear build files
|
|
||||||
clean:
|
|
||||||
rm -rf *.o ${LIB}.*
|
|
||||||
rm -rf ${LIBDIR}/${LIB}.*
|
|
||||||
rm -rf ${HEADER_DIR}
|
|
||||||
|
|
||||||
install: all install-libs install-headers
|
|
||||||
|
|
||||||
# Install the library to LIBPATH
|
|
||||||
install-libs:
|
|
||||||
@echo "[Installing Libs]"
|
|
||||||
@if ( test ! -d $(PREFIX)/lib ) ; then mkdir -p $(PREFIX)/lib ; fi
|
|
||||||
@install -m 0755 ${LIBNAME} ${LIBDIR}
|
|
||||||
@ln -sf ${LIBDIR}/${LIBNAME} ${LIBDIR}/${LIB}.so.1
|
|
||||||
@ln -sf ${LIBDIR}/${LIBNAME} ${LIBDIR}/${LIB}.so
|
|
||||||
@ldconfig
|
|
||||||
|
|
||||||
install-headers:
|
|
||||||
@echo "[Installing Headers]"
|
|
||||||
@if ( test ! -d ${HEADER_DIR} ) ; then mkdir -p ${HEADER_DIR} ; fi
|
|
||||||
@install -m 0644 *.h ${HEADER_DIR}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#include <AES.h>
|
|
||||||
#include "./printf.h"
|
|
||||||
|
|
||||||
AES aes ;
|
|
||||||
|
|
||||||
byte *key = (unsigned char*)"0123456789010123";
|
|
||||||
|
|
||||||
byte plain[] = "Add NodeAdd NodeAdd NodeAdd NodeAdd Node";
|
|
||||||
|
|
||||||
//real iv = iv x2 ex: 01234567 = 0123456701234567
|
|
||||||
unsigned long long int my_iv = 36753562;
|
|
||||||
|
|
||||||
void setup ()
|
|
||||||
{
|
|
||||||
Serial.begin (57600) ;
|
|
||||||
printf_begin();
|
|
||||||
delay(500);
|
|
||||||
printf("\n===testng mode\n") ;
|
|
||||||
|
|
||||||
// otfly_test () ;
|
|
||||||
// otfly_test256 () ;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop ()
|
|
||||||
{
|
|
||||||
prekey_test () ;
|
|
||||||
delay(2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void prekey (int bits)
|
|
||||||
{
|
|
||||||
aes.iv_inc();
|
|
||||||
byte iv [N_BLOCK] ;
|
|
||||||
byte plain_p[48];
|
|
||||||
byte cipher [48] ;
|
|
||||||
byte check [48] ;
|
|
||||||
unsigned long ms = micros ();
|
|
||||||
aes.set_IV(my_iv);
|
|
||||||
aes.get_IV(iv);
|
|
||||||
aes.do_aes_encrypt(plain,41,cipher,key,bits,iv);
|
|
||||||
Serial.print("Encryption took: ");
|
|
||||||
Serial.println(micros() - ms);
|
|
||||||
ms = micros ();
|
|
||||||
aes.set_IV(my_iv);
|
|
||||||
aes.get_IV(iv);
|
|
||||||
aes.do_aes_decrypt(cipher,48,check,key,bits,iv);
|
|
||||||
Serial.print("Decryption took: ");
|
|
||||||
Serial.println(micros() - ms);
|
|
||||||
printf("\n\nPLAIN :");
|
|
||||||
aes.printArray(plain,(bool)true);
|
|
||||||
printf("\nCIPHER:");
|
|
||||||
aes.printArray(cipher,(bool)false);
|
|
||||||
printf("\nCHECK :");
|
|
||||||
aes.printArray(check,(bool)true);
|
|
||||||
printf("\nIV :");
|
|
||||||
aes.printArray(iv,16);
|
|
||||||
printf("\n============================================================\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void prekey_test ()
|
|
||||||
{
|
|
||||||
prekey (128) ;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
Monte Carlo test vectors:
|
|
||||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmct.zip
|
|
||||||
|
|
||||||
(Compare the Monte Carlo output to the ECBMCT128.rsp file)
|
|
||||||
|
|
||||||
Known Answer Tests:
|
|
||||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
|
|
||||||
|
|
||||||
- Compare the other test outputs to
|
|
||||||
ECBVarTxt128.rsp
|
|
||||||
ECBVarKey128.rsp
|
|
||||||
ECBVarTxt192.rsp
|
|
||||||
ECBVarKey192.rsp
|
|
||||||
ECBVarTxt256.rsp
|
|
||||||
ECBVarKey256.rsp
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,191 +0,0 @@
|
|||||||
#include <AES.h>
|
|
||||||
|
|
||||||
AES aes ;
|
|
||||||
|
|
||||||
byte key [2*N_BLOCK] ;
|
|
||||||
byte plain [N_BLOCK] ;
|
|
||||||
byte iv [N_BLOCK] ;
|
|
||||||
byte cipher [N_BLOCK] ;
|
|
||||||
byte check [N_BLOCK] ;
|
|
||||||
|
|
||||||
void loop ()
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
void setup ()
|
|
||||||
{
|
|
||||||
Serial.begin (57600) ;
|
|
||||||
Serial.print ("AES library test vectors") ;
|
|
||||||
|
|
||||||
monte_carlo (128) ;
|
|
||||||
|
|
||||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
|
|
||||||
{
|
|
||||||
prekey_test_var_plaintext (keysize) ;
|
|
||||||
prekey_test_var_key (keysize) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void prekey_test_var_plaintext (int bits)
|
|
||||||
{
|
|
||||||
Serial.println () ;
|
|
||||||
Serial.print ("ECB Varying Plaintext ") ;
|
|
||||||
Serial.print (bits) ;
|
|
||||||
Serial.println (" bits") ;
|
|
||||||
Serial.println () ;
|
|
||||||
|
|
||||||
byte succ ;
|
|
||||||
set_bits (bits, key, 0) ; // all zero key
|
|
||||||
succ = aes.set_key (key, bits) ;
|
|
||||||
if (succ != SUCCESS)
|
|
||||||
Serial.println ("Failure set_key") ;
|
|
||||||
|
|
||||||
|
|
||||||
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++)
|
|
||||||
{
|
|
||||||
Serial.print ("COUNT = ") ; Serial.println (bitcount-1) ;
|
|
||||||
print_value ("KEY = ", key, bits) ;
|
|
||||||
set_bits (128, plain, bitcount) ;
|
|
||||||
|
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
|
||||||
|
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
|
||||||
if (succ != SUCCESS)
|
|
||||||
Serial.println ("Failure encrypt") ;
|
|
||||||
|
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
|
||||||
|
|
||||||
succ = aes.decrypt (cipher, check) ;
|
|
||||||
if (succ != SUCCESS)
|
|
||||||
Serial.println ("Failure decrypt") ;
|
|
||||||
|
|
||||||
//print_value ("CHECK = ", check, 128) ;
|
|
||||||
check_same (plain, check, 128) ;
|
|
||||||
Serial.println () ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void prekey_test_var_key (int bits)
|
|
||||||
{
|
|
||||||
Serial.println () ;
|
|
||||||
Serial.print ("ECB Varying Key ") ;
|
|
||||||
Serial.print (bits) ;
|
|
||||||
Serial.println (" bits") ;
|
|
||||||
Serial.println () ;
|
|
||||||
|
|
||||||
byte succ ;
|
|
||||||
set_bits (128, plain, 0) ;
|
|
||||||
|
|
||||||
for (int bitcount = 1 ; bitcount <= bits ; bitcount++)
|
|
||||||
{
|
|
||||||
set_bits (bits, key, bitcount) ; // all zero key
|
|
||||||
succ = aes.set_key (key, bits) ;
|
|
||||||
if (succ != SUCCESS)
|
|
||||||
Serial.println ("Failure set_key") ;
|
|
||||||
Serial.print ("COUNT = ") ; Serial.println (bitcount-1) ;
|
|
||||||
print_value ("KEY = ", key, bits) ;
|
|
||||||
|
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
|
||||||
|
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
|
||||||
if (succ != SUCCESS)
|
|
||||||
Serial.println ("Failure encrypt") ;
|
|
||||||
|
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
|
||||||
|
|
||||||
succ = aes.decrypt (cipher, check) ;
|
|
||||||
if (succ != SUCCESS)
|
|
||||||
Serial.println ("Failure decrypt") ;
|
|
||||||
|
|
||||||
check_same (plain, check, 128) ;
|
|
||||||
Serial.println () ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_bits (int bits, byte * a, int count)
|
|
||||||
{
|
|
||||||
bits >>= 3 ;
|
|
||||||
byte bcount = count >> 3 ;
|
|
||||||
for (byte i = 0 ; i < bcount ; i++)
|
|
||||||
a [i] = 0xFF ;
|
|
||||||
if ((count & 7) != 0)
|
|
||||||
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
|
||||||
for (byte i = bcount ; i < bits ; i++)
|
|
||||||
a [i] = 0x00 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_same (byte * a, byte * b, int bits)
|
|
||||||
{
|
|
||||||
bits >>= 3 ;
|
|
||||||
for (byte i = 0 ; i < bits ; i++)
|
|
||||||
if (a[i] != b[i])
|
|
||||||
{
|
|
||||||
Serial.println ("Failure plain != check") ;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char hex[] = "0123456789abcdef" ;
|
|
||||||
|
|
||||||
|
|
||||||
void print_value (const char * str, byte * a, int bits)
|
|
||||||
{
|
|
||||||
Serial.print (str) ;
|
|
||||||
bits >>= 3 ;
|
|
||||||
for (int i = 0 ; i < bits ; i++)
|
|
||||||
{
|
|
||||||
byte b = a[i] ;
|
|
||||||
Serial.print (hex [b >> 4]) ;
|
|
||||||
Serial.print (hex [b & 15]) ;
|
|
||||||
}
|
|
||||||
Serial.println () ;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte monteplain [] =
|
|
||||||
{ 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
|
|
||||||
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ;
|
|
||||||
byte montekey [] =
|
|
||||||
{ 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
|
|
||||||
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ;
|
|
||||||
|
|
||||||
void monte_carlo (int bits)
|
|
||||||
{
|
|
||||||
Serial.println () ;
|
|
||||||
Serial.print ("Monte Carlo ") ;
|
|
||||||
Serial.print (bits) ;
|
|
||||||
Serial.println (" bits") ;
|
|
||||||
Serial.println () ;
|
|
||||||
byte succ ;
|
|
||||||
for (int i = 0 ; i < 16 ; i++)
|
|
||||||
{
|
|
||||||
plain [i] = monteplain [i] ;
|
|
||||||
key [i] = montekey [i] ;
|
|
||||||
}
|
|
||||||
for (int i = 0 ; i < 100 ; i++)
|
|
||||||
{
|
|
||||||
Serial.print ("COUNT = ") ; Serial.println (i) ;
|
|
||||||
print_value ("KEY = ", key, bits) ;
|
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
|
||||||
succ = aes.set_key (key, bits) ;
|
|
||||||
for (int j = 0 ; j < 1000 ; j++)
|
|
||||||
{
|
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
|
||||||
aes.copy_n_bytes (plain, cipher, 16) ;
|
|
||||||
}
|
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
|
||||||
Serial.println () ;
|
|
||||||
if (bits == 128)
|
|
||||||
{
|
|
||||||
for (byte k = 0 ; k < 16 ; k++)
|
|
||||||
key [k] ^= cipher [k] ;
|
|
||||||
}
|
|
||||||
else if (bits == 192)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#############################################################################
|
|
||||||
#
|
|
||||||
# Makefile for AES examples on Raspberry Pi
|
|
||||||
#
|
|
||||||
# License: GPL (General Public License)
|
|
||||||
# Author: gnulnulf <arco@appeltaart.mine.nu>
|
|
||||||
# Date: 2013/02/07 (version 1.0)
|
|
||||||
#
|
|
||||||
# Description:
|
|
||||||
# ------------
|
|
||||||
# use make all and make install to install the examples
|
|
||||||
# You can change the install directory by editing the prefix line
|
|
||||||
#
|
|
||||||
prefix := /usr/local
|
|
||||||
|
|
||||||
# The recommended compiler flags for the Raspberry Pi
|
|
||||||
CCFLAGS=-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
|
|
||||||
#CCFLAGS=
|
|
||||||
|
|
||||||
# define all programs
|
|
||||||
PROGRAMS = aes test_vectors
|
|
||||||
SOURCES = ${PROGRAMS:=.cpp}
|
|
||||||
|
|
||||||
all: ${PROGRAMS}
|
|
||||||
|
|
||||||
${PROGRAMS}: ${SOURCES}
|
|
||||||
g++ ${CCFLAGS} -Wall -I../ -lAES $@.cpp -o $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(PROGRAMS)
|
|
||||||
|
|
||||||
install: all
|
|
||||||
test -d $(prefix) || mkdir $(prefix)
|
|
||||||
test -d $(prefix)/bin || mkdir $(prefix)/bin
|
|
||||||
for prog in $(PROGRAMS); do \
|
|
||||||
install -m 0755 $$prog $(prefix)/bin; \
|
|
||||||
done
|
|
||||||
|
|
||||||
.PHONY: install
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
Monte Carlo test vectors:
|
|
||||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/aesmct.zip
|
|
||||||
|
|
||||||
(Compare the Monte Carlo output to the ECBMCT128.rsp file)
|
|
||||||
|
|
||||||
Known Answer Tests:
|
|
||||||
http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
|
|
||||||
|
|
||||||
- Compare the other test outputs to
|
|
||||||
ECBVarTxt128.rsp
|
|
||||||
ECBVarKey128.rsp
|
|
||||||
ECBVarTxt192.rsp
|
|
||||||
ECBVarKey192.rsp
|
|
||||||
ECBVarTxt256.rsp
|
|
||||||
ECBVarKey256.rsp
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#include <AES.h>
|
|
||||||
#include "printf.h"
|
|
||||||
|
|
||||||
AES aes;
|
|
||||||
|
|
||||||
void prekey_test ();
|
|
||||||
void prekey (int bits, int blocks);
|
|
||||||
|
|
||||||
byte key[] = "01234567899876543210012345678998";
|
|
||||||
|
|
||||||
byte plain[] = "TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST";
|
|
||||||
|
|
||||||
//real iv = iv x2 ex: 01234567 = 0123456701234567
|
|
||||||
unsigned long long int my_iv = 01234567;
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
printf("\n===testng mode\n") ;
|
|
||||||
|
|
||||||
for (int i=0; i<1; i++) {
|
|
||||||
prekey_test () ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void prekey (int bits)
|
|
||||||
{
|
|
||||||
byte iv [N_BLOCK] ;
|
|
||||||
byte plain_p[sizeof(plain) + (N_BLOCK - (sizeof(plain) % 16)) - 1];
|
|
||||||
byte cipher[sizeof(plain_p)];
|
|
||||||
aes.do_aes_encrypt(plain,sizeof(plain),cipher,key,bits);
|
|
||||||
aes.get_IV(iv);
|
|
||||||
aes.do_aes_dencrypt(cipher,aes.get_size(),plain_p,key,bits,iv);
|
|
||||||
//normally u have sizeof(cipher) but if its in the same sketch you cannot determin it dynamically
|
|
||||||
|
|
||||||
printf("\n\nPLAIN :");
|
|
||||||
aes.printArray(plain);
|
|
||||||
printf("\nCIPHER:");
|
|
||||||
aes.printArray(cipher);
|
|
||||||
printf("\nPlain2:");
|
|
||||||
aes.printArray(plain_p);
|
|
||||||
printf("\n============================================================\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void prekey_test ()
|
|
||||||
{
|
|
||||||
prekey (128) ;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,182 +0,0 @@
|
|||||||
#include <AES.h>
|
|
||||||
#include "printf.h"
|
|
||||||
|
|
||||||
AES aes ;
|
|
||||||
|
|
||||||
byte key [2*N_BLOCK] ;
|
|
||||||
byte plain [N_BLOCK] ;
|
|
||||||
byte iv [N_BLOCK] ;
|
|
||||||
byte cipher [N_BLOCK] ;
|
|
||||||
byte check [N_BLOCK] ;
|
|
||||||
|
|
||||||
void print_value (const char * str, byte * a, int bits);
|
|
||||||
void prekey_test_var_plaintext (int bits);
|
|
||||||
void prekey_test_var_key (int bits);
|
|
||||||
void set_bits (int bits, byte * a, int count);
|
|
||||||
void check_same (byte * a, byte * b, int bits);
|
|
||||||
void monte_carlo (int bits);
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
printf ("AES library test vectors") ;
|
|
||||||
|
|
||||||
monte_carlo (128) ;
|
|
||||||
|
|
||||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64) {
|
|
||||||
prekey_test_var_plaintext (keysize) ;
|
|
||||||
prekey_test_var_key (keysize) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void prekey_test_var_plaintext (int bits)
|
|
||||||
{
|
|
||||||
printf ("\nECB Varying Plaintext %i bits\n",bits) ;
|
|
||||||
|
|
||||||
byte succ ;
|
|
||||||
set_bits (bits, key, 0) ; // all zero key
|
|
||||||
succ = aes.set_key (key, bits) ;
|
|
||||||
if (succ != SUCCESS) {
|
|
||||||
printf("Failure set_key\n") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) {
|
|
||||||
printf ("COUNT = %i \n",bitcount-1);
|
|
||||||
print_value ("KEY = ", key, bits) ;
|
|
||||||
set_bits (128, plain, bitcount) ;
|
|
||||||
|
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
|
||||||
|
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
|
||||||
if (succ != SUCCESS) {
|
|
||||||
printf ("Failure encrypt\n") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
|
||||||
|
|
||||||
succ = aes.decrypt (cipher, check) ;
|
|
||||||
if (succ != SUCCESS) {
|
|
||||||
printf ("Failure decrypt\n") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//print_value ("CHECK = ", check, 128) ;
|
|
||||||
check_same (plain, check, 128) ;
|
|
||||||
printf ("\n") ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void prekey_test_var_key (int bits)
|
|
||||||
{
|
|
||||||
printf ("\nECB Varying key %i bits\n",bits);
|
|
||||||
|
|
||||||
byte succ ;
|
|
||||||
set_bits (128, plain, 0) ;
|
|
||||||
|
|
||||||
for (int bitcount = 1 ; bitcount <= bits ; bitcount++) {
|
|
||||||
set_bits (bits, key, bitcount) ; // all zero key
|
|
||||||
succ = aes.set_key (key, bits) ;
|
|
||||||
if (succ != SUCCESS) {
|
|
||||||
printf ("Failure set_key\n") ;
|
|
||||||
}
|
|
||||||
printf ("COUNT = %i\n",bitcount-1);
|
|
||||||
print_value ("KEY = ", key, bits) ;
|
|
||||||
|
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
|
||||||
|
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
|
||||||
if (succ != SUCCESS) {
|
|
||||||
printf ("Failure encrypt\n") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
|
||||||
|
|
||||||
succ = aes.decrypt (cipher, check) ;
|
|
||||||
if (succ != SUCCESS) {
|
|
||||||
printf ("Failure decrypt\n") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_same (plain, check, 128) ;
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_bits (int bits, byte * a, int count)
|
|
||||||
{
|
|
||||||
bits >>= 3 ;
|
|
||||||
byte bcount = count >> 3 ;
|
|
||||||
for (byte i = 0 ; i < bcount ; i++) {
|
|
||||||
a [i] = 0xFF ;
|
|
||||||
}
|
|
||||||
if ((count & 7) != 0) {
|
|
||||||
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
|
||||||
}
|
|
||||||
for (byte i = bcount ; i < bits ; i++) {
|
|
||||||
a [i] = 0x00 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_same (byte * a, byte * b, int bits)
|
|
||||||
{
|
|
||||||
bits >>= 3 ;
|
|
||||||
for (byte i = 0 ; i < bits ; i++)
|
|
||||||
if (a[i] != b[i]) {
|
|
||||||
printf ("Failure plain != check\n") ;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char hex[] = "0123456789abcdef" ;
|
|
||||||
|
|
||||||
|
|
||||||
void print_value (const char * str, byte * a, int bits)
|
|
||||||
{
|
|
||||||
printf ("%s",str) ;
|
|
||||||
bits >>= 3 ;
|
|
||||||
for (int i = 0 ; i < bits ; i++) {
|
|
||||||
byte b = a[i] ;
|
|
||||||
printf("%c%c",hex[b >> 4],hex [b & 15]);
|
|
||||||
//Serial.print (hex [b >> 4]) ;
|
|
||||||
//Serial.print (hex [b & 15]) ;
|
|
||||||
}
|
|
||||||
printf("\n") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte monteplain [] = {
|
|
||||||
0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
|
|
||||||
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f
|
|
||||||
} ;
|
|
||||||
byte montekey [] = {
|
|
||||||
0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
|
|
||||||
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd
|
|
||||||
} ;
|
|
||||||
|
|
||||||
void monte_carlo (int bits)
|
|
||||||
{
|
|
||||||
printf ("\nMonte Carlo %i bits\n",bits);
|
|
||||||
byte succ;
|
|
||||||
for (int i = 0 ; i < 16 ; i++) {
|
|
||||||
plain [i] = monteplain [i] ;
|
|
||||||
key [i] = montekey [i] ;
|
|
||||||
}
|
|
||||||
for (int i = 0 ; i < 100 ; i++) {
|
|
||||||
printf ("COUNT = %i\n",i);
|
|
||||||
print_value ("KEY = ", key, bits) ;
|
|
||||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
|
||||||
succ = aes.set_key (key, bits) ;
|
|
||||||
for (int j = 0 ; j < 1000 ; j++) {
|
|
||||||
succ = aes.encrypt (plain, cipher) ;
|
|
||||||
aes.copy_n_bytes (plain, cipher, 16) ;
|
|
||||||
}
|
|
||||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
|
||||||
printf("\n");
|
|
||||||
if (bits == 128) {
|
|
||||||
for (byte k = 0 ; k < 16 ; k++) {
|
|
||||||
key [k] ^= cipher [k] ;
|
|
||||||
}
|
|
||||||
} else if (bits == 192) {
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
version 2 as published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
/* Galileo support from spaniakos <spaniakos@gmail.com> */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file printf.h
|
|
||||||
*
|
|
||||||
* Setup necessary to direct stdout to the Arduino Serial library, which
|
|
||||||
* enables 'printf'
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __PRINTF_H__
|
|
||||||
#define __PRINTF_H__
|
|
||||||
|
|
||||||
#if defined (ARDUINO) && !defined (__arm__) && !defined(__ARDUINO_X86__)
|
|
||||||
|
|
||||||
int serial_putc( char c, FILE * )
|
|
||||||
{
|
|
||||||
Serial.write( c );
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printf_begin(void)
|
|
||||||
{
|
|
||||||
fdevopen( &serial_putc, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined (__arm__)
|
|
||||||
|
|
||||||
void printf_begin(void) {}
|
|
||||||
|
|
||||||
#elif defined(__ARDUINO_X86__)
|
|
||||||
int serial_putc( char c, FILE * )
|
|
||||||
{
|
|
||||||
Serial.write( c );
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printf_begin(void)
|
|
||||||
{
|
|
||||||
//JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
|
|
||||||
stdout = freopen("/dev/ttyGS0","w",stdout);
|
|
||||||
delay(500);
|
|
||||||
printf("redirecting to Serial...");
|
|
||||||
|
|
||||||
//JESUS -----------------------------------------------------------
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error This example is only for use on Arduino.
|
|
||||||
#endif // ARDUINO
|
|
||||||
|
|
||||||
#endif // __PRINTF_H__
|
|
||||||
@@ -177,7 +177,6 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
|||||||
|
|
||||||
static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
||||||
{
|
{
|
||||||
uint8_t count_byte;
|
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t ret_code;
|
uint8_t ret_code;
|
||||||
|
|
||||||
@@ -189,6 +188,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
|||||||
|
|
||||||
ret_code = swi_receive_bytes(size, response);
|
ret_code = swi_receive_bytes(size, response);
|
||||||
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
|
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
|
||||||
|
uint8_t count_byte;
|
||||||
count_byte = response[SHA204_BUFFER_POS_COUNT];
|
count_byte = response[SHA204_BUFFER_POS_COUNT];
|
||||||
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
|
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
|
||||||
return SHA204_INVALID_SIZE;
|
return SHA204_INVALID_SIZE;
|
||||||
|
|||||||
@@ -32,6 +32,16 @@ const uint8_t sha256InitState[] PROGMEM = {
|
|||||||
0x19,0xcd,0xe0,0x5b // H7
|
0x19,0xcd,0xe0,0x5b // H7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Sha256Class::Sha256Class()
|
||||||
|
{
|
||||||
|
memset(keyBuffer, 0, BLOCK_LENGTH);
|
||||||
|
memset(innerHash, 0, HASH_LENGTH);
|
||||||
|
memset(buffer.b, 0, BLOCK_LENGTH);
|
||||||
|
memset(state.b, 0, BLOCK_LENGTH);
|
||||||
|
bufferOffset = 0;
|
||||||
|
byteCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Sha256Class::init(void)
|
void Sha256Class::init(void)
|
||||||
{
|
{
|
||||||
memcpy_P(state.b,sha256InitState,32);
|
memcpy_P(state.b,sha256InitState,32);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ union _state {
|
|||||||
class Sha256Class
|
class Sha256Class
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Sha256Class(); // Constructor
|
||||||
void init(void);
|
void init(void);
|
||||||
void initHmac(const uint8_t* secret, int secretLength);
|
void initHmac(const uint8_t* secret, int secretLength);
|
||||||
uint8_t* result(void);
|
uint8_t* result(void);
|
||||||
|
|||||||
@@ -261,7 +261,6 @@ uint8_t atsha204Class::sha204p_resync(uint8_t size, uint8_t *response)
|
|||||||
|
|
||||||
uint8_t atsha204Class::sha204p_receive_response(uint8_t size, uint8_t *response)
|
uint8_t atsha204Class::sha204p_receive_response(uint8_t size, uint8_t *response)
|
||||||
{
|
{
|
||||||
uint8_t count_byte;
|
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t ret_code;
|
uint8_t ret_code;
|
||||||
|
|
||||||
@@ -273,6 +272,7 @@ uint8_t atsha204Class::sha204p_receive_response(uint8_t size, uint8_t *response)
|
|||||||
|
|
||||||
ret_code = swi_receive_bytes(size, response);
|
ret_code = swi_receive_bytes(size, response);
|
||||||
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
|
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
|
||||||
|
uint8_t count_byte;
|
||||||
count_byte = response[SHA204_BUFFER_POS_COUNT];
|
count_byte = response[SHA204_BUFFER_POS_COUNT];
|
||||||
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
|
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
|
||||||
return SHA204_INVALID_SIZE;
|
return SHA204_INVALID_SIZE;
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param[in] pin The pin to use for communication
|
* @param[in] pin The pin to use for communication
|
||||||
*/
|
*/
|
||||||
atsha204Class(uint8_t pin);
|
explicit atsha204Class(uint8_t pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wake up device
|
* @brief Wake up device
|
||||||
|
|||||||
@@ -32,12 +32,12 @@
|
|||||||
"autoformat_on_save": true,
|
"autoformat_on_save": true,
|
||||||
"options_c":
|
"options_c":
|
||||||
{
|
{
|
||||||
"additional_options_file": "$project_path/../../.tools/astyle/config/style.cfg",
|
"additional_options_file": "$project_path/../../.mystools/astyle/config/style.cfg",
|
||||||
"use_only_additional_options": true
|
"use_only_additional_options": true
|
||||||
},
|
},
|
||||||
"options_c++":
|
"options_c++":
|
||||||
{
|
{
|
||||||
"additional_options_file": "$project_path/../../.astylerc",
|
"additional_options_file": "$project_path/../../.mystools/astyle/config/style.cfg",
|
||||||
"use_only_additional_options": true
|
"use_only_additional_options": true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -65,6 +65,8 @@
|
|||||||
// The project defines build targets for all Arduino based boards supported by MySensors.
|
// The project defines build targets for all Arduino based boards supported by MySensors.
|
||||||
// The plugin needed to do the build (which require the Arduino IDE to be installed) is
|
// The plugin needed to do the build (which require the Arduino IDE to be installed) is
|
||||||
// available here: https://github.com/jacobrosenthal/arduino-cli
|
// available here: https://github.com/jacobrosenthal/arduino-cli
|
||||||
|
// You also need to make sure you set up sketch book paths properly and that you can
|
||||||
|
// build sketches and examples for the MySensors library in the IDE.
|
||||||
"build_systems":
|
"build_systems":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||||
|
* between your home built sensors/actuators and HA controller of choice.
|
||||||
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||||
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||||
|
* network topology allowing messages to be routed to nodes.
|
||||||
|
*
|
||||||
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
|
* Copyright (C) 2013-2016 Sensnology AB
|
||||||
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
|
*
|
||||||
|
* Documentation: http://www.mysensors.org
|
||||||
|
* Support Forum: http://forum.mysensors.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
*******************************
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <pins_arduino.h>
|
||||||
|
#define MY_DEBUG
|
||||||
|
#define MY_GATEWAY_SERIAL
|
||||||
|
#define MY_DEBUG_VERBOSE_SIGNING
|
||||||
|
//#define MY_SIGNING_SOFT
|
||||||
|
#define MY_SIGNING_ATSHA204
|
||||||
|
#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}}
|
||||||
|
#define MY_SIGNING_REQUEST_SIGNATURES
|
||||||
|
#ifndef MY_SIGNING_SOFT_RANDOMSEED_PIN
|
||||||
|
#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
|
||||||
|
#endif
|
||||||
|
#ifndef MY_SIGNING_ATSHA204_PIN
|
||||||
|
#define MY_SIGNING_ATSHA204_PIN 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <MySensors.h>
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||||
|
* between your home built sensors/actuators and HA controller of choice.
|
||||||
|
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||||
|
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||||
|
* network topology allowing messages to be routed to nodes.
|
||||||
|
*
|
||||||
|
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||||
|
* Copyright (C) 2013-2016 Sensnology AB
|
||||||
|
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||||
|
*
|
||||||
|
* Documentation: http://www.mysensors.org
|
||||||
|
* Support Forum: http://forum.mysensors.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
*******************************
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <pins_arduino.h>
|
||||||
|
#define MY_DEBUG
|
||||||
|
#define MY_GATEWAY_SERIAL
|
||||||
|
#define MY_DEBUG_VERBOSE_SIGNING
|
||||||
|
#define MY_SIGNING_SOFT
|
||||||
|
//#define MY_SIGNING_ATSHA204
|
||||||
|
#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}}
|
||||||
|
#define MY_SIGNING_REQUEST_SIGNATURES
|
||||||
|
#ifndef MY_SIGNING_SOFT_RANDOMSEED_PIN
|
||||||
|
#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
|
||||||
|
#endif
|
||||||
|
#ifndef MY_SIGNING_ATSHA204_PIN
|
||||||
|
#define MY_SIGNING_ATSHA204_PIN 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <MySensors.h>
|
||||||
Reference in New Issue
Block a user