31
31
32
32
// Define MY_DEBUG_VERBOSE_SIGNING in your sketch to enable signing backend debugprints
33
33
34
- ATSHA204Class atsha204 (MY_SIGNING_ATSHA204_PIN);
35
34
unsigned long _signing_timestamp;
36
35
bool _signing_verification_ongoing = false ;
37
- uint8_t _signing_current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1 ];
36
+ uint8_t _signing_verifying_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1 ];
37
+ uint8_t _signing_signing_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1 ];
38
38
uint8_t _signing_temp_message[SHA_MSG_SIZE];
39
- uint8_t _singning_rx_buffer [SHA204_RSP_SIZE_MAX];
40
- uint8_t _singning_tx_buffer [SHA204_CMD_SIZE_MAX];
39
+ uint8_t _signing_rx_buffer [SHA204_RSP_SIZE_MAX];
40
+ uint8_t _signing_tx_buffer [SHA204_CMD_SIZE_MAX];
41
41
extern uint8_t _doWhitelist[32 ];
42
42
43
43
#ifdef MY_SIGNING_NODE_WHITELISTING
44
44
const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING;
45
45
#endif
46
46
47
- static void signerCalculateSignature (MyMessage &msg);
47
+ static void signerCalculateSignature (MyMessage &msg, bool signing );
48
48
static uint8_t * signerSha256 (const uint8_t * data, size_t sz);
49
49
50
50
@@ -87,14 +87,16 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
87
87
#endif
88
88
89
89
void signerAtsha204Init (void ) {
90
+ atsha204_init (MY_SIGNING_ATSHA204_PIN);
90
91
}
91
92
92
93
bool signerAtsha204CheckTimer (void ) {
93
94
if (_signing_verification_ongoing) {
94
- if (millis () < _signing_timestamp || millis () > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
95
+ if (hwMillis () < _signing_timestamp || hwMillis () > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
95
96
DEBUG_SIGNING_PRINTBUF (F (" Verification timeout" ), NULL , 0 );
96
97
// Purge nonce
97
- memset (_signing_current_nonce, 0x00 , NONCE_NUMIN_SIZE_PASSTHROUGH);
98
+ memset (_signing_signing_nonce, 0x00 , NONCE_NUMIN_SIZE_PASSTHROUGH);
99
+ memset (_signing_verifying_nonce, 0x00 , NONCE_NUMIN_SIZE_PASSTHROUGH);
98
100
_signing_verification_ongoing = false ;
99
101
return false ;
100
102
}
@@ -105,38 +107,41 @@ bool signerAtsha204CheckTimer(void) {
105
107
bool signerAtsha204GetNonce (MyMessage &msg) {
106
108
DEBUG_SIGNING_PRINTBUF (F (" Signing backend: ATSHA204" ), NULL , 0 );
107
109
// Generate random number for use as nonce
108
- // We used a basic whitening technique that takes the first byte of a new random value and builds up a 32-byte random value
110
+ // We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter
109
111
// This 32-byte random value is then hashed (SHA256) to produce the resulting nonce
112
+ (void )atsha204_wakeup (_signing_temp_message);
113
+ if (atsha204_execute (SHA204_RANDOM, RANDOM_SEED_UPDATE, 0 , 0 , NULL ,
114
+ RANDOM_COUNT, _signing_tx_buffer, RANDOM_RSP_SIZE, _signing_rx_buffer) != SHA204_SUCCESS) {
115
+ DEBUG_SIGNING_PRINTBUF (F (" Failed to generate nonce" ), NULL , 0 );
116
+ return false ;
117
+ }
110
118
for (int i = 0 ; i < 32 ; i++) {
111
- if (atsha204.sha204m_execute (SHA204_RANDOM, RANDOM_NO_SEED_UPDATE, 0 , 0 , NULL ,
112
- RANDOM_COUNT, _singning_tx_buffer, RANDOM_RSP_SIZE, _singning_rx_buffer) != SHA204_SUCCESS) {
113
- DEBUG_SIGNING_PRINTBUF (F (" Failed to generate nonce" ), NULL , 0 );
114
- return false ;
115
- }
116
- _signing_current_nonce[i] = _singning_rx_buffer[SHA204_BUFFER_POS_DATA];
119
+ _signing_verifying_nonce[i] = _signing_rx_buffer[SHA204_BUFFER_POS_DATA+i] ^ (hwMillis ()&0xFF );
117
120
}
118
- memcpy (_signing_current_nonce, signerSha256 (_signing_current_nonce, 32 ), MAX_PAYLOAD);
121
+ memcpy (_signing_verifying_nonce, signerSha256 (_signing_verifying_nonce, 32 ), MAX_PAYLOAD);
122
+
123
+ atsha204_idle (); // We just idle the chip now since we expect to use it soon when the signed message arrives
119
124
120
125
// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
121
- memset (&_signing_current_nonce [MAX_PAYLOAD], 0xAA , sizeof (_signing_current_nonce )-MAX_PAYLOAD);
126
+ memset (&_signing_verifying_nonce [MAX_PAYLOAD], 0xAA , sizeof (_signing_verifying_nonce )-MAX_PAYLOAD);
122
127
123
128
// Transfer the first part of the nonce to the message
124
- msg.set (_signing_current_nonce , MAX_PAYLOAD);
129
+ msg.set (_signing_verifying_nonce , MAX_PAYLOAD);
125
130
_signing_verification_ongoing = true ;
126
- _signing_timestamp = millis (); // Set timestamp to determine when to purge nonce
131
+ _signing_timestamp = hwMillis (); // Set timestamp to determine when to purge nonce
127
132
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
128
133
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
129
134
// but this is consider such a rare case that it is accepted and rejects are 'safe'
130
- if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < millis ()) _signing_timestamp = 0 ;
135
+ if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < hwMillis ()) _signing_timestamp = 0 ;
131
136
return true ;
132
137
}
133
138
134
139
void signerAtsha204PutNonce (MyMessage &msg) {
135
140
DEBUG_SIGNING_PRINTBUF (F (" Signing backend: ATSHA204" ), NULL , 0 );
136
141
137
- memcpy (_signing_current_nonce , (uint8_t *)msg.getCustom (), MAX_PAYLOAD);
142
+ memcpy (_signing_signing_nonce , (uint8_t *)msg.getCustom (), MAX_PAYLOAD);
138
143
// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
139
- memset (&_signing_current_nonce [MAX_PAYLOAD], 0xAA , sizeof (_signing_current_nonce )-MAX_PAYLOAD);
144
+ memset (&_signing_signing_nonce [MAX_PAYLOAD], 0xAA , sizeof (_signing_signing_nonce )-MAX_PAYLOAD);
140
145
}
141
146
142
147
bool signerAtsha204SignMsg (MyMessage &msg) {
@@ -148,22 +153,25 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
148
153
149
154
// Calculate signature of message
150
155
mSetSigned (msg, 1 ); // make sure signing flag is set before signature is calculated
151
- signerCalculateSignature (msg);
156
+ signerCalculateSignature (msg, true );
152
157
153
158
if (DO_WHITELIST (msg.destination )) {
154
159
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device
155
- memcpy (_signing_current_nonce , &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], 32 ); // We can reuse the nonce buffer now since it is no longer needed
156
- _signing_current_nonce [32 ] = msg.sender ;
157
- atsha204. getSerialNumber (&_signing_current_nonce [33 ]);
158
- (void )signerSha256 (_signing_current_nonce , 32 +1 +SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
160
+ memcpy (_signing_signing_nonce , &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], 32 ); // We can reuse the nonce buffer now since it is no longer needed
161
+ _signing_signing_nonce [32 ] = msg.sender ;
162
+ atsha204_getSerialNumber (&_signing_signing_nonce [33 ]);
163
+ (void )signerSha256 (_signing_signing_nonce , 32 +1 +SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
159
164
DEBUG_SIGNING_PRINTBUF (F (" Signature salted with serial" ), NULL , 0 );
160
165
}
161
166
167
+ // Put device back to sleep
168
+ atsha204_sleep ();
169
+
162
170
// Overwrite the first byte in the signature with the signing identifier
163
- _singning_rx_buffer [SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
171
+ _signing_rx_buffer [SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
164
172
165
173
// Transfer as much signature data as the remaining space in the message permits
166
- memcpy (&msg.data [mGetLength (msg)], &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength (msg));
174
+ memcpy (&msg.data [mGetLength (msg)], &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength (msg));
167
175
DEBUG_SIGNING_PRINTBUF (F (" Signature in message: " ), (uint8_t *)&msg.data [mGetLength (msg)], MAX_PAYLOAD-mGetLength (msg));
168
176
169
177
return true ;
@@ -187,33 +195,38 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
187
195
}
188
196
189
197
DEBUG_SIGNING_PRINTBUF (F (" Signature in message: " ), (uint8_t *)&msg.data [mGetLength (msg)], MAX_PAYLOAD-mGetLength (msg));
190
- signerCalculateSignature (msg); // Get signature of message
198
+ signerCalculateSignature (msg, false ); // Get signature of message
191
199
192
200
#ifdef MY_SIGNING_NODE_WHITELISTING
193
201
// Look up the senders nodeId in our whitelist and salt the signature with that data
194
202
size_t j;
195
203
for (j=0 ; j < NUM_OF (_signing_whitelist); j++) {
196
204
if (_signing_whitelist[j].nodeId == msg.sender ) {
197
205
DEBUG_SIGNING_PRINTBUF (F (" Sender found in whitelist" ), NULL , 0 );
198
- memcpy (_signing_current_nonce , &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], 32 ); // We can reuse the nonce buffer now since it is no longer needed
199
- _signing_current_nonce [32 ] = msg.sender ;
200
- memcpy (&_signing_current_nonce [33 ], _signing_whitelist[j].serial , SHA204_SERIAL_SZ);
201
- (void )signerSha256 (_signing_current_nonce , 32 +1 +SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
206
+ memcpy (_signing_verifying_nonce , &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], 32 ); // We can reuse the nonce buffer now since it is no longer needed
207
+ _signing_verifying_nonce [32 ] = msg.sender ;
208
+ memcpy (&_signing_verifying_nonce [33 ], _signing_whitelist[j].serial , SHA204_SERIAL_SZ);
209
+ (void )signerSha256 (_signing_verifying_nonce , 32 +1 +SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
202
210
break ;
203
211
}
204
212
}
205
213
if (j == NUM_OF (_signing_whitelist)) {
206
214
DEBUG_SIGNING_PRINTBUF (F (" Sender not found in whitelist, message rejected!" ), NULL , 0 );
215
+ // Put device back to sleep
216
+ atsha204_sleep ();
207
217
return false ;
208
218
}
209
219
#endif
210
220
221
+ // Put device back to sleep
222
+ atsha204_sleep ();
223
+
211
224
// Overwrite the first byte in the signature with the signing identifier
212
- _singning_rx_buffer [SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
225
+ _signing_rx_buffer [SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
213
226
214
227
// Compare the caluclated signature with the provided signature
215
- if (signerMemcmp (&msg.data [mGetLength (msg)], &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength (msg))) {
216
- DEBUG_SIGNING_PRINTBUF (F (" Signature bad: " ), &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength (msg));
228
+ if (signerMemcmp (&msg.data [mGetLength (msg)], &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength (msg))) {
229
+ DEBUG_SIGNING_PRINTBUF (F (" Signature bad: " ), &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength (msg));
217
230
#ifdef MY_SIGNING_NODE_WHITELISTING
218
231
DEBUG_SIGNING_PRINTBUF (F (" Is the sender whitelisted and serial correct?" ), NULL , 0 );
219
232
#endif
@@ -225,44 +238,43 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
225
238
}
226
239
}
227
240
228
- // Helper to calculate signature of msg (returned in _singning_rx_buffer[SHA204_BUFFER_POS_DATA])
229
- static void signerCalculateSignature (MyMessage &msg) {
241
+ // Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
242
+ static void signerCalculateSignature (MyMessage &msg, bool signing) {
243
+ (void )atsha204_wakeup (_signing_temp_message);
230
244
memset (_signing_temp_message, 0 , 32 );
231
245
memcpy (_signing_temp_message, (uint8_t *)&msg.data [1 -HEADER_SIZE], MAX_MESSAGE_LENGTH-1 -(MAX_PAYLOAD-mGetLength (msg)));
232
246
233
247
// Program the data to sign into the ATSHA204
234
248
DEBUG_SIGNING_PRINTBUF (F (" Message to process: " ), (uint8_t *)&msg.data [1 -HEADER_SIZE], MAX_MESSAGE_LENGTH-1 -(MAX_PAYLOAD-mGetLength (msg)));
235
- DEBUG_SIGNING_PRINTBUF (F (" Current nonce: " ), _signing_current_nonce , 32 );
236
- (void )atsha204. sha204m_execute (SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3 , 32 , _signing_temp_message,
237
- WRITE_COUNT_LONG, _singning_tx_buffer , WRITE_RSP_SIZE, _singning_rx_buffer );
249
+ DEBUG_SIGNING_PRINTBUF (F (" Current nonce: " ), signing ? _signing_signing_nonce : _signing_verifying_nonce , 32 );
250
+ (void )atsha204_execute (SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3 , 32 , _signing_temp_message,
251
+ WRITE_COUNT_LONG, _signing_tx_buffer , WRITE_RSP_SIZE, _signing_rx_buffer );
238
252
239
253
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
240
- (void )atsha204.sha204m_execute (SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0 , NONCE_NUMIN_SIZE_PASSTHROUGH, _signing_current_nonce,
241
- NONCE_COUNT_LONG, _singning_tx_buffer, NONCE_RSP_SIZE_SHORT, _singning_rx_buffer);
254
+ (void )atsha204_execute (SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0 , NONCE_NUMIN_SIZE_PASSTHROUGH,
255
+ signing ? _signing_signing_nonce : _signing_verifying_nonce,
256
+ NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer);
242
257
243
258
// Purge nonce when used
244
- memset (_signing_current_nonce , 0x00 , NONCE_NUMIN_SIZE_PASSTHROUGH);
259
+ memset (signing ? _signing_signing_nonce : _signing_verifying_nonce , 0x00 , NONCE_NUMIN_SIZE_PASSTHROUGH);
245
260
246
261
// Generate digest of data and nonce
247
- (void )atsha204. sha204m_execute (SHA204_GENDIG, GENDIG_ZONE_DATA, 8 , 0 , NULL ,
248
- GENDIG_COUNT_DATA, _singning_tx_buffer , GENDIG_RSP_SIZE, _singning_rx_buffer );
262
+ (void )atsha204_execute (SHA204_GENDIG, GENDIG_ZONE_DATA, 8 , 0 , NULL ,
263
+ GENDIG_COUNT_DATA, _signing_tx_buffer , GENDIG_RSP_SIZE, _signing_rx_buffer );
249
264
250
265
// Calculate HMAC of message+nonce digest and secret key
251
- (void )atsha204.sha204m_execute (SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0 , 0 , NULL ,
252
- HMAC_COUNT, _singning_tx_buffer, HMAC_RSP_SIZE, _singning_rx_buffer);
253
-
254
- // Put device back to sleep
255
- atsha204.sha204c_sleep ();
266
+ (void )atsha204_execute (SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0 , 0 , NULL ,
267
+ HMAC_COUNT, _signing_tx_buffer, HMAC_RSP_SIZE, _signing_rx_buffer);
256
268
257
- DEBUG_SIGNING_PRINTBUF (F (" HMAC: " ), &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], 32 );
269
+ DEBUG_SIGNING_PRINTBUF (F (" HMAC: " ), &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], 32 );
258
270
}
259
271
260
272
// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block)
261
- // The pointer to the hash is returned, but the hash is also stored in _singning_rx_buffer [SHA204_BUFFER_POS_DATA])
273
+ // The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer [SHA204_BUFFER_POS_DATA])
262
274
static uint8_t * signerSha256 (const uint8_t * data, size_t sz) {
263
275
// Initiate SHA256 calculator
264
- (void )atsha204. sha204m_execute (SHA204_SHA, SHA_INIT, 0 , 0 , NULL ,
265
- SHA_COUNT_SHORT, _singning_tx_buffer , SHA_RSP_SIZE_SHORT, _singning_rx_buffer );
276
+ (void )atsha204_execute (SHA204_SHA, SHA_INIT, 0 , 0 , NULL ,
277
+ SHA_COUNT_SHORT, _signing_tx_buffer , SHA_RSP_SIZE_SHORT, _signing_rx_buffer );
266
278
267
279
// Calculate a hash
268
280
memset (_signing_temp_message, 0x00 , SHA_MSG_SIZE);
@@ -271,12 +283,9 @@ static uint8_t* signerSha256(const uint8_t* data, size_t sz) {
271
283
// Write length data to the last bytes
272
284
_signing_temp_message[SHA_MSG_SIZE-2 ] = (sz >> 5 );
273
285
_signing_temp_message[SHA_MSG_SIZE-1 ] = (sz << 3 );
274
- (void )atsha204.sha204m_execute (SHA204_SHA, SHA_CALC, 0 , SHA_MSG_SIZE, _signing_temp_message,
275
- SHA_COUNT_LONG, _singning_tx_buffer, SHA_RSP_SIZE_LONG, _singning_rx_buffer);
276
-
277
- // Put device back to sleep
278
- atsha204.sha204c_sleep ();
286
+ (void )atsha204_execute (SHA204_SHA, SHA_CALC, 0 , SHA_MSG_SIZE, _signing_temp_message,
287
+ SHA_COUNT_LONG, _signing_tx_buffer, SHA_RSP_SIZE_LONG, _signing_rx_buffer);
279
288
280
- DEBUG_SIGNING_PRINTBUF (F (" SHA256: " ), &_singning_rx_buffer [SHA204_BUFFER_POS_DATA], 32 );
281
- return &_singning_rx_buffer [SHA204_BUFFER_POS_DATA];
289
+ DEBUG_SIGNING_PRINTBUF (F (" SHA256: " ), &_signing_rx_buffer [SHA204_BUFFER_POS_DATA], 32 );
290
+ return &_signing_rx_buffer [SHA204_BUFFER_POS_DATA];
282
291
}
0 commit comments