77
77
_ATECC_608_VER = const (0x60 )
78
78
79
79
# Clock constants
80
- _WAKE_CLK_FREQ = 100000 # slower clock speed
81
- _TWLO_TIME = 6e-5 # TWlo, in microseconds
80
+ _WAKE_CLK_FREQ = 100000 # slower clock speed
81
+ _TWLO_TIME = 6e-5 # TWlo, in microseconds
82
82
83
83
# Command Opcodes (9-1-3)
84
84
OP_COUNTER = const (0x24 )
92
92
OP_WRITE = const (0x12 )
93
93
94
94
# Maximum execution times, in milliseconds (9-4)
95
- EXEC_TIME = {OP_COUNTER : const (20 ),
96
- OP_INFO : const (1 ),
97
- OP_NONCE : const (7 ),
98
- OP_RANDOM : const (23 ),
99
- OP_SHA : const (47 ),
100
- OP_LOCK : const (32 ),
101
- OP_GEN_KEY : const (115 ),
102
- OP_SIGN : const (70 ),
103
- OP_WRITE : const (26 )}
104
-
105
-
106
- CFG_TLS = b'\x01 #\x00 \x00 \x00 \x00 P\x00 \x00 \x00 \x00 \x00 \x00 \xc0 q\x00 \
95
+ EXEC_TIME = {
96
+ OP_COUNTER : const (20 ),
97
+ OP_INFO : const (1 ),
98
+ OP_NONCE : const (7 ),
99
+ OP_RANDOM : const (23 ),
100
+ OP_SHA : const (47 ),
101
+ OP_LOCK : const (32 ),
102
+ OP_GEN_KEY : const (115 ),
103
+ OP_SIGN : const (70 ),
104
+ OP_WRITE : const (26 ),
105
+ }
106
+
107
+
108
+ CFG_TLS = b"\x01 #\x00 \x00 \x00 \x00 P\x00 \x00 \x00 \x00 \x00 \x00 \xc0 q\x00 \
107
109
\xc0 \x00 U\x00 \x83 \x87 \x87 \x87 /\x87 /\x8f \x8f \x9f \x8f \xaf \
108
110
\x8f \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \
109
111
\xaf \x8f \xff \xff \xff \xff \x00 \x00 \x00 \x00 \xff \xff \xff \xff \x00 \
110
112
\x00 \x00 \x00 \xff \xff \xff \xff \xff \xff \xff \xff \xff \xff \xff \xff \
111
113
\xff \xff \xff \xff \x00 \x00 UU\xff \xff \x00 \x00 \x00 \x00 \x00 \x00 3 \
112
114
\x00 3\x00 3\x00 3\x00 3\x00 \x1c \x00 \x1c \x00 \x1c \x00 <\x00 <\x00 <\x00 < \
113
- \x00 <\x00 <\x00 <\x00 \x1c \x00 '
115
+ \x00 <\x00 <\x00 <\x00 \x1c \x00 "
116
+
114
117
115
118
class ATECC :
116
119
"""
117
120
CircuitPython interface for ATECCx08A Crypto Co-Processor Devices.
118
121
"""
122
+
119
123
def __init__ (self , i2c_bus , address = _REG_ATECC_DEVICE_ADDR , debug = False ):
120
124
"""Initializes an ATECC device.
121
125
:param busio i2c_bus: I2C Bus object.
@@ -132,7 +136,9 @@ def __init__(self, i2c_bus, address=_REG_ATECC_DEVICE_ADDR, debug=False):
132
136
self ._i2c_device = I2CDevice (self ._i2c_bus , address )
133
137
self .idle ()
134
138
if (self .version () >> 8 ) not in (_ATECC_508_VER , _ATECC_608_VER ):
135
- raise RuntimeError ("Failed to find 608 or 508 chip. Please check your wiring." )
139
+ raise RuntimeError (
140
+ "Failed to find 608 or 508 chip. Please check your wiring."
141
+ )
136
142
137
143
def wakeup (self ):
138
144
"""Wakes up THE ATECC608A from sleep or idle modes.
@@ -148,13 +154,13 @@ def wakeup(self):
148
154
try :
149
155
self ._i2c_bus .writeto (0x0 , zero_bits )
150
156
except OSError :
151
- pass # this may fail, that's ok - its just to wake up the chip!
157
+ pass # this may fail, that's ok - its just to wake up the chip!
152
158
time .sleep (_TWLO_TIME )
153
- data = self ._i2c_bus .scan () # check for an i2c device
159
+ data = self ._i2c_bus .scan () # check for an i2c device
154
160
155
161
try :
156
162
if data [0 ] != 96 :
157
- raise TypeError (' ATECCx08 not found - please check your wiring!' )
163
+ raise TypeError (" ATECCx08 not found - please check your wiring!" )
158
164
except IndexError :
159
165
raise IndexError ("ATECCx08 not found - please check your wiring!" )
160
166
self ._i2c_bus .unlock ()
@@ -228,20 +234,18 @@ def lock_all_zones(self):
228
234
self .lock (0 )
229
235
self .lock (1 )
230
236
231
-
232
237
def lock (self , zone ):
233
238
"""Locks specific ATECC zones.
234
239
:param int zone: ATECC zone to lock.
235
240
"""
236
241
self .wakeup ()
237
242
self ._send_command (0x17 , 0x80 | zone , 0x0000 )
238
- time .sleep (EXEC_TIME [OP_LOCK ]/ 1000 )
243
+ time .sleep (EXEC_TIME [OP_LOCK ] / 1000 )
239
244
res = bytearray (1 )
240
245
self ._get_response (res )
241
246
assert res [0 ] == 0x00 , "Failed locking ATECC!"
242
247
self .idle ()
243
248
244
-
245
249
def info (self , mode , param = None ):
246
250
"""Returns device state information
247
251
:param int mode: Mode encoding, see Table 9-26.
@@ -252,7 +256,7 @@ def info(self, mode, param=None):
252
256
self ._send_command (OP_INFO , mode )
253
257
else :
254
258
self ._send_command (OP_INFO , mode , param )
255
- time .sleep (EXEC_TIME [OP_INFO ]/ 1000 )
259
+ time .sleep (EXEC_TIME [OP_INFO ] / 1000 )
256
260
info_out = bytearray (4 )
257
261
self ._get_response (info_out )
258
262
self .idle ()
@@ -281,15 +285,16 @@ def nonce(self, data, mode=0, zero=0x0000):
281
285
calculated_nonce = bytearray (1 )
282
286
else :
283
287
raise RuntimeError ("Invalid mode specified!" )
284
- time .sleep (EXEC_TIME [OP_NONCE ]/ 1000 )
288
+ time .sleep (EXEC_TIME [OP_NONCE ] / 1000 )
285
289
self ._get_response (calculated_nonce )
286
- time .sleep (1 / 1000 )
290
+ time .sleep (1 / 1000 )
287
291
if mode == 0x03 :
288
- assert calculated_nonce [0 ] == 0x00 , "Incorrectly calculated nonce in pass-thru mode"
292
+ assert (
293
+ calculated_nonce [0 ] == 0x00
294
+ ), "Incorrectly calculated nonce in pass-thru mode"
289
295
self .idle ()
290
296
return calculated_nonce
291
297
292
-
293
298
def counter (self , counter = 0 , increment_counter = True ):
294
299
"""Reads the binary count value from one of the two monotonic
295
300
counters located on the device within the configuration zone.
@@ -306,7 +311,7 @@ def counter(self, counter=0, increment_counter=True):
306
311
self ._send_command (OP_COUNTER , 0x01 , counter )
307
312
else :
308
313
self ._send_command (OP_COUNTER , 0x00 , counter )
309
- time .sleep (EXEC_TIME [OP_COUNTER ]/ 1000 )
314
+ time .sleep (EXEC_TIME [OP_COUNTER ] / 1000 )
310
315
count = bytearray (4 )
311
316
self ._get_response (count )
312
317
self .idle ()
@@ -342,7 +347,7 @@ def _random(self, data):
342
347
data_len = len (data )
343
348
while data_len :
344
349
self ._send_command (OP_RANDOM , 0x00 , 0x0000 )
345
- time .sleep (EXEC_TIME [OP_RANDOM ]/ 1000 )
350
+ time .sleep (EXEC_TIME [OP_RANDOM ] / 1000 )
346
351
resp = bytearray (32 )
347
352
self ._get_response (resp )
348
353
copy_len = min (32 , data_len )
@@ -359,7 +364,7 @@ def sha_start(self):
359
364
"""
360
365
self .wakeup ()
361
366
self ._send_command (OP_SHA , 0x00 )
362
- time .sleep (EXEC_TIME [OP_SHA ]/ 1000 )
367
+ time .sleep (EXEC_TIME [OP_SHA ] / 1000 )
363
368
status = bytearray (1 )
364
369
self ._get_response (status )
365
370
assert status [0 ] == 0x00 , "Error during sha_start."
@@ -374,14 +379,13 @@ def sha_update(self, message):
374
379
"""
375
380
self .wakeup ()
376
381
self ._send_command (OP_SHA , 0x01 , 64 , message )
377
- time .sleep (EXEC_TIME [OP_SHA ]/ 1000 )
382
+ time .sleep (EXEC_TIME [OP_SHA ] / 1000 )
378
383
status = bytearray (1 )
379
384
self ._get_response (status )
380
385
assert status [0 ] == 0x00 , "Error during SHA Update"
381
386
self .idle ()
382
387
return status
383
388
384
-
385
389
def sha_digest (self , message = None ):
386
390
"""Returns the digest of the data passed to the
387
391
sha_update method so far.
@@ -397,14 +401,13 @@ def sha_digest(self, message=None):
397
401
self ._send_command (OP_SHA , 0x02 , len (message ), message )
398
402
else :
399
403
self ._send_command (OP_SHA , 0x02 )
400
- time .sleep (EXEC_TIME [OP_SHA ]/ 1000 )
404
+ time .sleep (EXEC_TIME [OP_SHA ] / 1000 )
401
405
digest = bytearray (32 )
402
406
self ._get_response (digest )
403
407
assert len (digest ) == 32 , "SHA response length does not match expected length."
404
408
self .idle ()
405
409
return digest
406
410
407
-
408
411
def gen_key (self , key , slot_num , private_key = False ):
409
412
"""Generates a private or public key.
410
413
:param int slot_num: ECC slot (from 0 to 4).
@@ -417,7 +420,7 @@ def gen_key(self, key, slot_num, private_key=False):
417
420
self ._send_command (OP_GEN_KEY , 0x04 , slot_num )
418
421
else :
419
422
self ._send_command (OP_GEN_KEY , 0x00 , slot_num )
420
- time .sleep (EXEC_TIME [OP_GEN_KEY ]/ 1000 )
423
+ time .sleep (EXEC_TIME [OP_GEN_KEY ] / 1000 )
421
424
self ._get_response (key )
422
425
time .sleep (0.001 )
423
426
self .idle ()
@@ -442,7 +445,7 @@ def sign(self, slot_id):
442
445
"""
443
446
self .wakeup ()
444
447
self ._send_command (0x41 , 0x80 , slot_id )
445
- time .sleep (EXEC_TIME [OP_SIGN ]/ 1000 )
448
+ time .sleep (EXEC_TIME [OP_SIGN ] / 1000 )
446
449
signature = bytearray (64 )
447
450
self ._get_response (signature )
448
451
self .idle ()
@@ -457,7 +460,7 @@ def write_config(self, data):
457
460
if i == 84 :
458
461
# can't write
459
462
continue
460
- self ._write (0 , i // 4 , data [i : i + 4 ])
463
+ self ._write (0 , i // 4 , data [i : i + 4 ])
461
464
462
465
def _write (self , zone , address , buffer ):
463
466
self .wakeup ()
@@ -466,7 +469,7 @@ def _write(self, zone, address, buffer):
466
469
if len (buffer ) == 32 :
467
470
zone |= 0x80
468
471
self ._send_command (0x12 , zone , address , buffer )
469
- time .sleep (26 / 1000 )
472
+ time .sleep (26 / 1000 )
470
473
status = bytearray (1 )
471
474
self ._get_response (status )
472
475
self .idle ()
@@ -483,26 +486,26 @@ def _read(self, zone, address, buffer):
483
486
time .sleep (0.001 )
484
487
self .idle ()
485
488
486
- def _send_command (self , opcode , param_1 , param_2 = 0x00 , data = '' ):
489
+ def _send_command (self , opcode , param_1 , param_2 = 0x00 , data = "" ):
487
490
"""Sends a security command packet over i2c.
488
491
:param byte opcode: The command Opcode
489
492
:param byte param_1: The first parameter
490
493
:param byte param_2: The second parameter, can be two bytes.
491
494
:param byte param_3 data: Optional remaining input data.
492
495
"""
493
496
# assembling command packet
494
- command_packet = bytearray (8 + len (data ))
497
+ command_packet = bytearray (8 + len (data ))
495
498
# word address
496
499
command_packet [0 ] = 0x03
497
500
# i/o group: count
498
- command_packet [1 ] = len (command_packet ) - 1 # count
501
+ command_packet [1 ] = len (command_packet ) - 1 # count
499
502
# security command packets
500
503
command_packet [2 ] = opcode
501
504
command_packet [3 ] = param_1
502
505
command_packet [4 ] = param_2 & 0xFF
503
506
command_packet [5 ] = param_2 >> 8
504
507
for i , cmd in enumerate (data ):
505
- command_packet [6 + i ] = cmd
508
+ command_packet [6 + i ] = cmd
506
509
if self ._debug :
507
510
print ("Command Packet Sz: " , len (command_packet ))
508
511
print ("\t Sending:" , [hex (i ) for i in command_packet ])
@@ -517,12 +520,11 @@ def _send_command(self, opcode, param_1, param_2=0x00, data=''):
517
520
# small sleep
518
521
time .sleep (0.001 )
519
522
520
-
521
523
def _get_response (self , buf , length = None , retries = 20 ):
522
524
self .wakeup ()
523
525
if length is None :
524
526
length = len (buf )
525
- response = bytearray (length + 3 ) # 1 byte header, 2 bytes CRC, len bytes data
527
+ response = bytearray (length + 3 ) # 1 byte header, 2 bytes CRC, len bytes data
526
528
with self ._i2c_device as i2c :
527
529
for _ in range (retries ):
528
530
try :
@@ -539,7 +541,7 @@ def _get_response(self, buf, length=None, retries=20):
539
541
if crc != crc2 :
540
542
raise RuntimeError ("CRC Mismatch" )
541
543
for i in range (length ):
542
- buf [i ] = response [i + 1 ]
544
+ buf [i ] = response [i + 1 ]
543
545
return response [1 ]
544
546
545
547
@staticmethod
@@ -553,7 +555,7 @@ def _at_crc(data, length=None):
553
555
for b in data :
554
556
for shift in range (8 ):
555
557
data_bit = 0
556
- if b & (1 << shift ):
558
+ if b & (1 << shift ):
557
559
data_bit = 1
558
560
crc_bit = (crc >> 15 ) & 0x1
559
561
crc <<= 1
0 commit comments