├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── docs
├── 20005927A_ATECC508A.pdf
├── PYBOARD_ATECCX08A.fzz
├── PYBOARD_ATECCX08A_bb.png
└── PYBOARD_ATECCX08A_bb.svg
├── manifest.py
├── micropython-lib
└── logging.py
├── modules
└── cryptoauthlib
│ ├── __init__.py
│ ├── basic.py
│ ├── constant.py
│ ├── device.py
│ ├── exceptions.py
│ ├── host.py
│ ├── packet.py
│ ├── status.py
│ └── util.py
└── tests
└── ateccX08a
├── __init__.py
├── tests_info.py
├── tests_lock.py
├── tests_nonce.py
├── tests_random.py
├── tests_read.py
├── tests_selftest.py
├── tests_sha.py
├── tests_sign.py
├── tests_verify.py
└── tests_write.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Per default everything gets normalized and gets LF line endings on checkout.
2 | * text eol=lf
3 |
4 | # These will always have CRLF line endings on checkout.
5 | *.vcxproj text eol=crlf
6 | *.props text eol=crlf
7 | *.bat text eol=crlf
8 |
9 | # These are binary so should never be modified by git.
10 | *.pdf binary
11 | *.png binary
12 | *.jpg binary
13 | *.dxf binary
14 | *.mpy binary
15 |
16 | # These should also not be modified by git.
17 | tests/** -text
18 | examples/** -text
19 | cryptoauthlib/** -text
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 | .hypothesis/
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 | local_settings.py
55 |
56 | # Flask stuff:
57 | instance/
58 | .webassets-cache
59 |
60 | # Scrapy stuff:
61 | .scrapy
62 |
63 | # Sphinx documentation
64 | docs/_build/
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # IPython Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # dotenv
79 | .env
80 |
81 | # virtualenv
82 | venv/
83 | ENV/
84 |
85 | # Spyder project settings
86 | .spyderproject
87 |
88 | # Rope project settings
89 | .ropeproject
90 |
91 | # micropython-lib
92 | micropython-lib/ucryptoauthlib/
93 |
94 | # vs code
95 | .vscode/*
96 |
97 | # vs code - Local History
98 | .history/*
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2019 Damiano Mazzella
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ucryptoauthlib
2 |
3 | Lightweight driver for Microchip Crypto Authentication secure elements written in pure python for micropython.
4 |
5 | WARNING: this project is in beta stage and is subject to changes of the
6 | code-base, including project-wide name changes and API changes.
7 |
8 | > [!TIP]
9 | > If you find **ucryptoauthlib** useful, consider :star: this project
10 | > and why not ... [Buy me a coffee](https://www.buymeacoffee.com/damianomazp) :smile:
11 |
12 | Features
13 | ---------------------
14 |
15 | - Allows PyBoard to control Microchip Crypto Authentication secure elements
16 | - Automatic recognition of the Microchip Crypto Authentication secure element
17 | - The API are the same of the [Library](https://github.com/MicrochipTech/cryptoauthlib) wrote by Microchip
18 |
19 | Usage
20 | ---------------------
21 |
22 | - PyBoard basic connection:
23 |
24 |
25 |
26 |
27 |
28 |
29 | - BASIC
30 |
31 | ```python
32 | MicroPython v1.10-127-g5801a003f-dirty on 2019-02-24; PYBv1.1 with STM32F405RG
33 | Type "help()" for more information.
34 | >>> from cryptoauthlib.device import ATECCX08A
35 | >>> device = ATECCX08A()
36 | >>> print(device)
37 |
38 | >>>
39 | ```
40 |
41 | - TESTS:
42 |
43 | ```python
44 | MicroPython v1.10-127-g5801a003f-dirty on 2019-02-24; PYBv1.1 with STM32F405RG
45 | Type "help()" for more information.
46 | >>> import ateccX08a; ateccX08a.test()
47 | INFO:ateccX08a
48 | INFO:ateccX08a INFO SUCCEDED
49 | INFO:ateccX08a SHA SUCCEDED
50 | INFO:ateccX08a RANDOM SUCCEDED
51 | INFO:ateccX08a NONCE SUCCEDED
52 | INFO:ateccX08a READ SUCCEDED
53 | INFO:ateccX08a WRITE SUCCEDED
54 | INFO:ateccX08a LOCK SKIPPED
55 | INFO:ateccX08a VERIFY SUCCEDED
56 | INFO:ateccX08a SIGN SUCCEDED
57 | INFO:ateccX08a SELFTEST SUCCEDED
58 | >>>
59 | ```
60 |
61 | Enable DEBUG:
62 | ```python
63 | import logging
64 | logging.basicConfig(level=logging.DEBUG)
65 | ```
66 |
67 | External dependencies
68 | ---------------------
69 |
70 | Only for tests:
71 | 'logging' already available into folder 'micropython-lib' of this repository
72 |
73 | Install 'cryptoauthlib' into the PyBoard
74 | ---------------------
75 |
76 | 1. Freeze package using FROZEN_MANIFEST:
77 | ```bash
78 | $ git clone https://github.com/micropython/micropython.git
79 | $ cd micropython
80 | micropython$ git submodule update --init
81 | micropython$ git clone https://github.com/dmazzella/ucryptoauthlib.git micropython-lib/ucryptoauthlib
82 | micropython$ make -C mpy-cross && make -C ports/stm32 BOARD=PYBD_SF6 FROZEN_MANIFEST="$(pwd)/micropython-lib/ucryptoauthlib/manifest.py"
83 | ```
84 | P.S.
85 | 'micropython-lib' is an example where to copy 'ucryptoauthlib', if you prefer to change this directory you need to modify manifest.py to reflect the changes
86 |
87 | Software
88 | ---------------------
89 |
90 | Currently supported commands are:
91 |
92 | * INFO
93 | * LOCK
94 | * NONCE
95 | * RANDOM
96 | * READ (1)
97 | * SHA (1)
98 | * WRITE (1)
99 | * VERIFY (1)
100 | * GENKEY
101 | * SIGN
102 | * SELFTEST
103 |
104 | (1) Not all features are implemented, see follow list for details
105 |
106 | Currently implemented methods are:
107 |
108 | 
109 |
110 | - [x] ```atcab_version()```
111 | - [x] ```atcab_get_addr(zone, slot=0, block=0, offset=0)```
112 | - [x] ```atcab_get_zone_size(zone, slot=0)```
113 | - [ ] ```atcab_checkmac(mode, key_id, challenge, response, other_data)```
114 | - [ ] ```atcab_counter(mode, counter_id)```
115 | - [ ] ```atcab_counter_increment(counter_id)```
116 | - [ ] ```atcab_counter_read(counter_id)```
117 | - [ ] ```atcab_derivekey(mode, key_id, mac)```
118 | - [ ] ```atcab_ecdh_base(mode, key_id, public_key)```
119 | - [ ] ```atcab_ecdh(key_id, public_key)```
120 | - [ ] ```atcab_ecdh_enc(key_id, public_key, read_key, read_key_id)```
121 | - [ ] ```atcab_ecdh_ioenc(key_id, public_key, io_key)```
122 | - [ ] ```atcab_ecdh_tempkey(public_key)```
123 | - [ ] ```atcab_ecdh_tempkey_ioenc(public_key, io_key)```
124 | - [x] ```atcab_gendig(zone, key_id, other_data)```
125 | - [x] ```atcab_genkey_base(mode, key_id, other_data=None)```
126 | - [x] ```atcab_genkey(key_id)```
127 | - [x] ```atcab_get_pubkey(key_id)```
128 | - [ ] ```atcab_hmac(mode, key_id)```
129 | - [x] ```atcab_info_base(mode=0)```
130 | - [x] ```atcab_info()```
131 | - [ ] ```atcab_kdf(mode, key_id, details, message)```
132 | - [x] ```atcab_lock(mode, crc=0)```
133 | - [x] ```atcab_lock_config_zone()```
134 | - [x] ```atcab_lock_config_zone_crc(crc)```
135 | - [x] ```atcab_lock_data_zone()```
136 | - [x] ```atcab_lock_data_zone_crc(crc)```
137 | - [x] ```atcab_lock_data_slot(slot)```
138 | - [ ] ```atcab_mac(mode, key_id, challenge)```
139 | - [x] ```atcab_nonce_base(mode, zero=0, numbers=None)```
140 | - [x] ```atcab_nonce(numbers=None)```
141 | - [x] ```atcab_nonce_load(target, numbers=None)```
142 | - [x] ```atcab_nonce_rand(numbers=None)```
143 | - [x] ```atcab_challenge(numbers=None)```
144 | - [x] ```atcab_challenge_seed_update(numbers=None)```
145 | - [ ] ```atcab_priv_write(key_id, priv_key, write_key_id, write_key)```
146 | - [x] ```atcab_random()```
147 | - [x] ```atcab_read_zone(zone, slot=0, block=0, offset=0, length=0)```
148 | - [x] ```atcab_read_serial_number()```
149 | - [x] ```atcab_read_bytes_zone(zone, slot=0, block=0, offset=0, length=0)```
150 | - [x] ```atcab_is_slot_locked(slot)```
151 | - [x] ```atcab_is_locked(zone)```
152 | - [x] ```atcab_read_config_zone()```
153 | - [x] ```atcab_read_enc(key_id, block, data, enc_key, enc_key_id)```
154 | - [ ] ```atcab_cmp_config_zone(config_data)```
155 | - [ ] ```atcab_read_sig(slot)```
156 | - [x] ```atcab_read_pubkey(slot)```
157 | - [ ] ```atcab_secureboot(mode, param2, digest, signature)```
158 | - [ ] ```atcab_secureboot_mac(mode, digest, signature, num_in, io_key)```
159 | - [x] ```atcab_selftest(mode, param2=0)```
160 | - [x] ```atcab_sha_base(mode=0, data=b'', key_slot=None)```
161 | - [x] ```atcab_sha(data)```
162 | - [ ] ```atcab_sha_hmac(data, key_slot, target)```
163 | - [x] ```atcab_sign_base(mode, key_id)```
164 | - [x] ```atcab_sign(key_id, message)```
165 | - [x] ```atcab_sign_internal(key_id, is_invalidate=False, is_full_sn=False)```
166 | - [x] ```atcab_updateextra(mode, value)```
167 | - [x] ```atcab_verify(mode, key_id, signature, public_key=None, other_data=None, mac=None)```
168 | - [x] ```atcab_verify_extern(message, signature, public_key)```
169 | - [ ] ```atcab_verify_extern_mac(message, signature, public_key, num_in, io_key, is_verified)```
170 | - [x] ```atcab_verify_stored(message, signature, key_id)```
171 | - [ ] ```atcab_verify_stored_mac(message, signature, key_id, num_in, io_key, is_verified)```
172 | - [ ] ```atcab_verify_validate( key_id, signature, other_data, is_verified)```
173 | - [ ] ```atcab_verify_invalidate( key_id, signature, other_data, is_verified)```
174 | - [x] ```atcab_write(zone, address, value=None, mac=None)```
175 | - [x] ```atcab_write_zone(zone, slot=0, block=0, offset=0, data=None)```
176 | - [x] ```atcab_write_bytes_zone(zone, slot=0, offset=0, data=None)```
177 | - [x] ```atcab_write_pubkey(slot, public_key)```
178 | - [x] ```atcab_write_config_zone(config_data)```
179 | - [ ] ```atcab_write_enc(key_id, block, data, enc_key, enc_key_id)```
180 | - [ ] ```atcab_write_config_counter(counter_id, counter_value)```
181 |
182 | Hardware
183 | ---------------------
184 |
185 | Currently supported devices are:
186 |
187 | - [ATECC508A](http://www.microchip.com/ATECC508A)
188 | - [ATECC608A](http://www.microchip.com/ATECC608A)
189 |
--------------------------------------------------------------------------------
/docs/20005927A_ATECC508A.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmazzella/ucryptoauthlib/a4227ff3a14b6d50b374756086ca914fc2cafb7e/docs/20005927A_ATECC508A.pdf
--------------------------------------------------------------------------------
/docs/PYBOARD_ATECCX08A.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmazzella/ucryptoauthlib/a4227ff3a14b6d50b374756086ca914fc2cafb7e/docs/PYBOARD_ATECCX08A.fzz
--------------------------------------------------------------------------------
/docs/PYBOARD_ATECCX08A_bb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dmazzella/ucryptoauthlib/a4227ff3a14b6d50b374756086ca914fc2cafb7e/docs/PYBOARD_ATECCX08A_bb.png
--------------------------------------------------------------------------------
/manifest.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint:disable=undefined-variable
3 | freeze('$(MPY_DIR)/micropython-lib/ucryptoauthlib/modules', opt=0)
4 | ## uncomment the line below for enable 'logging' module
5 | #freeze('$(MPY_DIR)/micropython-lib/ucryptoauthlib/micropython-lib', opt=0)
6 |
--------------------------------------------------------------------------------
/micropython-lib/logging.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E1101
3 | import sys
4 |
5 | _stream = sys.stderr
6 |
7 | CRITICAL = 50
8 | ERROR = 40
9 | WARNING = 30
10 | INFO = 20
11 | DEBUG = 10
12 | NOTSET = 0
13 |
14 | _level_dict = {
15 | CRITICAL: "CRIT",
16 | ERROR: "ERROR",
17 | WARNING: "WARN",
18 | INFO: "INFO",
19 | DEBUG: "DEBUG",
20 | }
21 |
22 | class Logger(object):
23 |
24 | def __init__(self, name):
25 | self.level = NOTSET
26 | self.name = name or "root"
27 |
28 | def _level_str(self, level):
29 | global _level_dict
30 | if level in _level_dict:
31 | return _level_dict[level]
32 | return "LVL" + str(level)
33 |
34 | def log(self, level, msg, *args, **kwargs):
35 | global _level, _stream
36 | if level >= (self.level or _level):
37 | log_format_list = [self._level_str(level), self.name]
38 | log_format_msg = ":".join(map(str, log_format_list))
39 | try:
40 | print(log_format_msg, msg % args, file=_stream)
41 | except TypeError as te:
42 | print(
43 | ("--- Logging error ---\n"
44 | "{!r}\n"
45 | "Message: {!r}\n"
46 | "Arguments: {!r}".format(te, msg, args)
47 | ), file=_stream)
48 | if _stream not in (sys.stderr, sys.stdout) \
49 | and hasattr(_stream, "flush"):
50 | _stream.flush()
51 |
52 | def debug(self, msg, *args, **kwargs):
53 | self.log(DEBUG, msg, *args, **kwargs)
54 |
55 | def info(self, msg, *args, **kwargs):
56 | self.log(INFO, msg, *args, **kwargs)
57 |
58 | def warning(self, msg, *args, **kwargs):
59 | self.log(WARNING, msg, *args, **kwargs)
60 |
61 | def error(self, msg, *args, **kwargs):
62 | self.log(ERROR, msg, *args, **kwargs)
63 |
64 | def critical(self, msg, *args, **kwargs):
65 | self.log(CRITICAL, msg, *args, **kwargs)
66 |
67 | def exc(self, e, msg, *args):
68 | self.log(ERROR, msg, *args)
69 | sys.print_exception(e, _stream)
70 |
71 | def exception(self, msg, *args):
72 | e = None
73 | if hasattr(sys, 'exc_info'):
74 | e = sys.exc_info()[1]
75 | self.exc(e, msg, *args)
76 |
77 | _level = INFO
78 | _loggers = {}
79 |
80 | def getLogger(name=""):
81 | global _loggers
82 | if name in _loggers:
83 | return _loggers[name]
84 | l = Logger(name)
85 | _loggers[name] = l
86 | return l
87 |
88 | def info(msg, *args):
89 | getLogger(None).info(msg, *args)
90 |
91 | def debug(msg, *args):
92 | getLogger(None).debug(msg, *args)
93 |
94 | def basicConfig(level=INFO, filename=None, stream=None, format=None):
95 | global _level, _stream
96 | _level = level
97 | if stream:
98 | _stream = stream
99 | if filename is not None:
100 | raise AttributeError("filename")
101 | if format is not None:
102 | raise AttributeError("format")
103 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/__init__.py:
--------------------------------------------------------------------------------
1 | import sys
2 | from cryptoauthlib import constant
3 | from cryptoauthlib import status
4 |
5 | constant = sys.modules[constant.__name__]
6 | status = sys.modules[status.__name__]
7 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/basic.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from cryptoauthlib import constant as ATCA_CONSTANTS
3 | from cryptoauthlib import exceptions as ATCA_EXCEPTIONS
4 | from cryptoauthlib import status as ATCA_STATUS
5 | from cryptoauthlib.packet import ATCAPacket
6 |
7 | _ATCA_VERSION = "20190104"
8 | _BYTES_LIKE_OBJECT = (bytes, bytearray, memoryview)
9 |
10 |
11 | class ATECCBasic(object):
12 | """ ATECCBasic """
13 |
14 | _device = None
15 |
16 | def execute(self, packet):
17 | """ Abstract execute method """
18 | raise NotImplementedError()
19 |
20 | def is_error(self, data):
21 | # error packets are always 4 bytes long
22 | if data[ATCA_CONSTANTS.ATCA_COUNT_IDX] == 0x04:
23 | return ATCA_STATUS.decode_error(
24 | data[ATCA_CONSTANTS.ATCA_RSP_DATA_IDX]
25 | )
26 | else:
27 | return ATCA_STATUS.ATCA_SUCCESS, None
28 |
29 | def atcab_version(self):
30 | return _ATCA_VERSION
31 |
32 | def atcab_get_addr(self, zone, slot=0, block=0, offset=0):
33 | mem_zone = zone & ATCA_CONSTANTS.ATCA_ZONE_MASK
34 | if mem_zone not in (
35 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
36 | ATCA_CONSTANTS.ATCA_ZONE_DATA,
37 | ATCA_CONSTANTS.ATCA_ZONE_OTP
38 | ):
39 | raise ATCA_EXCEPTIONS.BadArgumentError()
40 |
41 | if slot < 0 or slot > 15:
42 | raise ATCA_EXCEPTIONS.BadArgumentError()
43 |
44 | addr = 0
45 | offset = offset & 0x07
46 | if mem_zone in (
47 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
48 | ATCA_CONSTANTS.ATCA_ZONE_OTP
49 | ):
50 | addr = block << 3
51 | addr = addr | offset
52 | elif mem_zone == ATCA_CONSTANTS.ATCA_ZONE_DATA:
53 | addr = slot << 3
54 | addr = addr | offset
55 | addr = addr | block << 8
56 |
57 | return addr
58 |
59 | def atcab_get_zone_size(self, zone, slot=0):
60 | if zone not in (
61 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
62 | ATCA_CONSTANTS.ATCA_ZONE_DATA,
63 | ATCA_CONSTANTS.ATCA_ZONE_OTP
64 | ):
65 | raise ATCA_EXCEPTIONS.BadArgumentError()
66 |
67 | if slot < 0 or slot > 15:
68 | raise ATCA_EXCEPTIONS.BadArgumentError()
69 |
70 | if zone == ATCA_CONSTANTS.ATCA_ZONE_CONFIG:
71 | return 128
72 | elif zone == ATCA_CONSTANTS.ATCA_ZONE_OTP:
73 | return 64
74 | elif zone == ATCA_CONSTANTS.ATCA_ZONE_DATA:
75 | if slot < 8:
76 | return 36
77 | elif slot == 8:
78 | return 412
79 | elif slot < 16:
80 | return 72
81 |
82 | ###########################################################################
83 | # CryptoAuthLib Basic API methods for CheckMAC command #
84 | ###########################################################################
85 |
86 | def atcab_checkmac(self, mode, key_id, challenge, response, other_data):
87 | raise NotImplementedError("atcab_checkmac")
88 |
89 | ###########################################################################
90 | # CryptoAuthLib Basic API methods for Counter command #
91 | ###########################################################################
92 |
93 | def atcab_counter(self, mode, counter_id):
94 | raise NotImplementedError("atcab_counter")
95 |
96 | def atcab_counter_increment(self, counter_id):
97 | raise NotImplementedError("atcab_counter_increment")
98 |
99 | def atcab_counter_read(self, counter_id):
100 | raise NotImplementedError("atcab_counter_read")
101 |
102 | ###########################################################################
103 | # CryptoAuthLib Basic API methods for DeriveKey command #
104 | ###########################################################################
105 |
106 | def atcab_derivekey(self, mode, key_id, mac):
107 | raise NotImplementedError("atcab_derivekey")
108 |
109 | ###########################################################################
110 | # CryptoAuthLib Basic API methods for ECDH command #
111 | ###########################################################################
112 |
113 | def atcab_ecdh_base(self, mode, key_id, public_key):
114 | raise NotImplementedError("atcab_ecdh_base")
115 |
116 | def atcab_ecdh(self, key_id, public_key):
117 | raise NotImplementedError("atcab_ecdh")
118 |
119 | def atcab_ecdh_enc(self, key_id, public_key, read_key, read_key_id):
120 | raise NotImplementedError("atcab_ecdh_enc")
121 |
122 | def atcab_ecdh_ioenc(self, key_id, public_key, io_key):
123 | raise NotImplementedError("atcab_ecdh_ioenc")
124 |
125 | def atcab_ecdh_tempkey(self, public_key):
126 | raise NotImplementedError("atcab_ecdh_tempkey")
127 |
128 | def atcab_ecdh_tempkey_ioenc(self, public_key, io_key):
129 | raise NotImplementedError("atcab_ecdh_tempkey_ioenc")
130 |
131 | ###########################################################################
132 | # CryptoAuthLib Basic API methods for GenDig command #
133 | ###########################################################################
134 |
135 | def atcab_gendig(self, zone, key_id, other_data):
136 | if (zone < 0x00 or zone > 0x05):
137 | raise ATCA_EXCEPTIONS.BadArgumentError(
138 | "Zone must be between zero and 5")
139 |
140 | packet = ATCAPacket(
141 | opcode=ATCA_CONSTANTS.ATCA_GENDIG,
142 | param1=zone,
143 | param2=key_id,
144 | request_data=other_data
145 | )
146 | self.execute(packet)
147 | return packet
148 |
149 | ###########################################################################
150 | # CryptoAuthLib Basic API methods for GenKey command #
151 | ###########################################################################
152 |
153 | def atcab_genkey_base(self, mode, key_id, other_data=None):
154 |
155 | txsize = 0
156 | if mode & ATCA_CONSTANTS.GENKEY_MODE_PUBKEY_DIGEST:
157 | txsize = ATCA_CONSTANTS.GENKEY_COUNT_DATA
158 | else:
159 | txsize = ATCA_CONSTANTS.GENKEY_COUNT
160 |
161 | has_other_data = isinstance(other_data, _BYTES_LIKE_OBJECT)
162 | data = other_data if has_other_data else b''
163 |
164 | packet = ATCAPacket(
165 | txsize=txsize,
166 | opcode=ATCA_CONSTANTS.ATCA_GENKEY,
167 | param1=mode,
168 | param2=key_id,
169 | request_data=data
170 | )
171 | self.execute(packet)
172 | return packet
173 |
174 | def atcab_genkey(self, key_id):
175 | return self.atcab_genkey_base(ATCA_CONSTANTS.GENKEY_MODE_PRIVATE, key_id)
176 |
177 | def atcab_get_pubkey(self, key_id):
178 | return self.atcab_genkey_base(ATCA_CONSTANTS.GENKEY_MODE_PUBLIC, key_id)
179 |
180 | ###########################################################################
181 | # CryptoAuthLib Basic API methods for HMAC command #
182 | ###########################################################################
183 |
184 | def atcab_hmac(self, mode, key_id):
185 | raise NotImplementedError("atcab_hmac")
186 |
187 | ###########################################################################
188 | # CryptoAuthLib Basic API methods for Info command #
189 | ###########################################################################
190 |
191 | def atcab_info_base(self, mode=0):
192 | packet = ATCAPacket(
193 | opcode=ATCA_CONSTANTS.ATCA_INFO,
194 | param1=mode
195 | )
196 | self.execute(packet)
197 | return packet
198 |
199 | def atcab_info(self):
200 | return self.atcab_info_base(ATCA_CONSTANTS.INFO_MODE_REVISION)
201 |
202 | ###########################################################################
203 | # CryptoAuthLib Basic API methods for KDF command #
204 | ###########################################################################
205 |
206 | def atcab_kdf(self, mode, key_id, details, message):
207 | raise NotImplementedError("atcab_kdf")
208 |
209 | ###########################################################################
210 | # CryptoAuthLib Basic API methods for Lock command #
211 | ###########################################################################
212 |
213 | def atcab_lock(self, mode, crc=0):
214 | packet = ATCAPacket(
215 | txsize=ATCA_CONSTANTS.LOCK_COUNT,
216 | opcode=ATCA_CONSTANTS.ATCA_LOCK,
217 | param1=mode,
218 | param2=crc
219 | )
220 | self.execute(packet)
221 | return packet
222 |
223 | def atcab_lock_config_zone(self):
224 | return self.atcab_lock(
225 | ATCA_CONSTANTS.LOCK_ZONE_NO_CRC | ATCA_CONSTANTS.LOCK_ZONE_CONFIG
226 | )
227 |
228 | def atcab_lock_config_zone_crc(self, crc):
229 | return self.atcab_lock(ATCA_CONSTANTS.LOCK_ZONE_CONFIG, crc)
230 |
231 | def atcab_lock_data_zone(self):
232 | return self.atcab_lock(
233 | ATCA_CONSTANTS.LOCK_ZONE_NO_CRC | ATCA_CONSTANTS.LOCK_ZONE_DATA
234 | )
235 |
236 | def atcab_lock_data_zone_crc(self, crc):
237 | return self.atcab_lock(ATCA_CONSTANTS.LOCK_ZONE_DATA, crc)
238 |
239 | def atcab_lock_data_slot(self, slot):
240 | if slot < 0 or slot > 15:
241 | raise ATCA_EXCEPTIONS.BadArgumentError()
242 |
243 | return self.atcab_lock((slot << 2) | ATCA_CONSTANTS.LOCK_ZONE_DATA_SLOT)
244 |
245 | ###########################################################################
246 | # CryptoAuthLib Basic API methods for MAC command #
247 | ###########################################################################
248 |
249 | def atcab_mac(self, mode, key_id, challenge):
250 | raise NotImplementedError("atcab_mac")
251 |
252 | ###########################################################################
253 | # CryptoAuthLib Basic API methods for Nonce command #
254 | ###########################################################################
255 |
256 | def atcab_nonce_base(self, mode, zero=0, numbers=None):
257 | nonce_mode = mode & ATCA_CONSTANTS.NONCE_MODE_MASK
258 | if nonce_mode not in (
259 | ATCA_CONSTANTS.NONCE_MODE_SEED_UPDATE,
260 | ATCA_CONSTANTS.NONCE_MODE_NO_SEED_UPDATE,
261 | ATCA_CONSTANTS.NONCE_MODE_PASSTHROUGH
262 | ):
263 | raise ATCA_EXCEPTIONS.BadArgumentError()
264 |
265 | if not isinstance(numbers, _BYTES_LIKE_OBJECT):
266 | raise ATCA_EXCEPTIONS.BadArgumentError()
267 |
268 | txsize = 0
269 | if nonce_mode in (
270 | ATCA_CONSTANTS.NONCE_MODE_SEED_UPDATE,
271 | ATCA_CONSTANTS.NONCE_MODE_NO_SEED_UPDATE
272 | ):
273 | txsize = ATCA_CONSTANTS.NONCE_COUNT_SHORT
274 | elif nonce_mode == ATCA_CONSTANTS.NONCE_MODE_PASSTHROUGH:
275 | nonce_mode_input = mode & ATCA_CONSTANTS.NONCE_MODE_INPUT_LEN_MASK
276 | if nonce_mode_input == ATCA_CONSTANTS.NONCE_MODE_INPUT_LEN_64:
277 | txsize = ATCA_CONSTANTS.NONCE_COUNT_LONG_64
278 | else:
279 | txsize = ATCA_CONSTANTS.NONCE_COUNT_LONG
280 | else:
281 | raise ATCA_EXCEPTIONS.BadArgumentError()
282 |
283 | n_mv = memoryview(numbers)
284 | if len(n_mv) < txsize-ATCA_CONSTANTS.ATCA_CMD_SIZE_MIN:
285 | raise ATCA_EXCEPTIONS.BadArgumentError()
286 |
287 | packet = ATCAPacket(
288 | txsize=txsize,
289 | opcode=ATCA_CONSTANTS.ATCA_NONCE,
290 | param1=mode,
291 | param2=zero,
292 | request_data=n_mv[:txsize-ATCA_CONSTANTS.ATCA_CMD_SIZE_MIN]
293 | )
294 |
295 | self.execute(packet)
296 | return packet
297 |
298 | def atcab_nonce(self, numbers=None):
299 | return self.atcab_nonce_base(
300 | ATCA_CONSTANTS.NONCE_MODE_PASSTHROUGH,
301 | numbers=numbers
302 | )
303 |
304 | def atcab_nonce_load(self, target, numbers=None):
305 | if not isinstance(numbers, _BYTES_LIKE_OBJECT):
306 | raise ATCA_EXCEPTIONS.BadArgumentError()
307 |
308 | mode = ATCA_CONSTANTS.NONCE_MODE_PASSTHROUGH
309 | mode = mode | (ATCA_CONSTANTS.NONCE_MODE_TARGET_MASK & target)
310 |
311 | if len(numbers) == 32:
312 | mode = mode | ATCA_CONSTANTS.NONCE_MODE_INPUT_LEN_32
313 | elif len(numbers) == 64:
314 | mode = mode | ATCA_CONSTANTS.NONCE_MODE_INPUT_LEN_64
315 | else:
316 | raise ATCA_EXCEPTIONS.BadArgumentError()
317 |
318 | return self.atcab_nonce_base(mode, numbers=numbers)
319 |
320 | def atcab_nonce_rand(self, numbers=None):
321 | return self.atcab_nonce_base(
322 | ATCA_CONSTANTS.NONCE_MODE_SEED_UPDATE,
323 | numbers=numbers
324 | )
325 |
326 | def atcab_challenge(self, numbers=None):
327 | return self.atcab_nonce_base(
328 | ATCA_CONSTANTS.NONCE_MODE_PASSTHROUGH,
329 | numbers=numbers
330 | )
331 |
332 | def atcab_challenge_seed_update(self, numbers=None):
333 | return self.atcab_nonce_base(
334 | ATCA_CONSTANTS.NONCE_MODE_SEED_UPDATE,
335 | numbers=numbers
336 | )
337 |
338 | ###########################################################################
339 | # CryptoAuthLib Basic API methods for PrivWrite command #
340 | ###########################################################################
341 |
342 | def atcab_priv_write(self, key_id, priv_key, write_key_id, write_key):
343 | raise NotImplementedError("atcab_priv_write")
344 |
345 | ###########################################################################
346 | # CryptoAuthLib Basic API methods for Random command #
347 | ###########################################################################
348 |
349 | def atcab_random(self):
350 | packet = ATCAPacket(
351 | opcode=ATCA_CONSTANTS.ATCA_RANDOM,
352 | param1=ATCA_CONSTANTS.RANDOM_SEED_UPDATE,
353 | )
354 | self.execute(packet)
355 | return packet
356 |
357 | ###########################################################################
358 | # CryptoAuthLib Basic API methods for Read command #
359 | ###########################################################################
360 |
361 | def atcab_read_zone(self, zone, slot=0, block=0, offset=0, length=0):
362 | if length not in (
363 | ATCA_CONSTANTS.ATCA_WORD_SIZE,
364 | ATCA_CONSTANTS.ATCA_BLOCK_SIZE
365 | ):
366 | raise ATCA_EXCEPTIONS.BadArgumentError()
367 |
368 | addr = self.atcab_get_addr(zone, slot=slot, block=block, offset=offset)
369 |
370 | if length == ATCA_CONSTANTS.ATCA_BLOCK_SIZE:
371 | zone = zone | ATCA_CONSTANTS.ATCA_ZONE_READWRITE_32
372 |
373 | packet = ATCAPacket(
374 | opcode=ATCA_CONSTANTS.ATCA_READ,
375 | param1=zone,
376 | param2=addr
377 | )
378 | self.execute(packet)
379 | return packet
380 |
381 | def atcab_read_serial_number(self):
382 | return self.atcab_read_zone(
383 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
384 | length=ATCA_CONSTANTS.ATCA_BLOCK_SIZE
385 | )
386 |
387 | def atcab_read_bytes_zone(self, zone, slot=0, block=0, offset=0, length=0):
388 | zone_size = self.atcab_get_zone_size(zone, slot=slot)
389 |
390 | if offset + length > zone_size:
391 | raise ATCA_EXCEPTIONS.BadArgumentError()
392 |
393 | packets = []
394 |
395 | BS = ATCA_CONSTANTS.ATCA_BLOCK_SIZE
396 | WS = ATCA_CONSTANTS.ATCA_WORD_SIZE
397 |
398 | r_sz = BS
399 | d_idx = r_idx = r_of = c_blk = c_of = 0
400 | c_blk = offset // BS
401 | while d_idx < length:
402 | if r_sz == BS and zone_size - c_blk * BS < BS:
403 | r_sz = WS
404 | c_of = ((d_idx + offset) // WS) % (BS // WS)
405 |
406 | packet = self.atcab_read_zone(
407 | zone,
408 | slot=slot,
409 | block=c_blk,
410 | offset=c_of,
411 | length=r_sz
412 | )
413 | packets.append(packet)
414 |
415 | r_of = c_blk * BS + c_of * WS
416 | r_idx = offset - r_of if r_of < offset else 0
417 | d_idx += length - d_idx if length - d_idx < r_sz - r_idx else r_sz - r_idx
418 |
419 | if r_sz == BS:
420 | c_blk += 1
421 | else:
422 | c_of += 1
423 |
424 | return packets
425 |
426 | def atcab_is_slot_locked(self, slot):
427 | # Read the word with the lock bytes
428 | # ( SlotLock[2], RFU[2] ) ( config block = 2, word offset = 6 )
429 | packet = self.atcab_read_zone(
430 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
431 | slot=0,
432 | block=2,
433 | offset=6,
434 | length=ATCA_CONSTANTS.ATCA_WORD_SIZE
435 | )
436 | return bool((packet[0+1] | (packet[1+1] << 8) & (1 << slot)) == 0)
437 |
438 | def atcab_is_locked(self, zone):
439 | if zone not in (
440 | ATCA_CONSTANTS.LOCK_ZONE_CONFIG,
441 | ATCA_CONSTANTS.LOCK_ZONE_DATA
442 | ):
443 | raise ATCA_EXCEPTIONS.BadArgumentError()
444 |
445 | # Read the word with the lock bytes
446 | # (UserExtra, Selector, LockValue, LockConfig) (config block = 2, word offset = 5)
447 | packet = self.atcab_read_zone(
448 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
449 | slot=0,
450 | block=2,
451 | offset=5,
452 | length=ATCA_CONSTANTS.ATCA_WORD_SIZE
453 | )
454 | if zone == ATCA_CONSTANTS.LOCK_ZONE_CONFIG:
455 | return bool(packet[3+1] != 0x55)
456 | elif zone == ATCA_CONSTANTS.LOCK_ZONE_DATA:
457 | return bool(packet[2+1] != 0x55)
458 |
459 | def atcab_read_config_zone(self):
460 | return self.atcab_read_bytes_zone(
461 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
462 | length=ATCA_CONSTANTS.ATCA_ECC_CONFIG_SIZE
463 | )
464 |
465 | def atcab_read_enc(self, key_id, block, enc_key_id, num_in=b'\x00' * 32):
466 | """Perform a simple encrypted read.
467 | See Atmel Application Note: Encrypted Reads and Writes
468 | """
469 | if key_id < 0 or key_id > 15:
470 | raise ATCA_EXCEPTIONS.BadArgumentError("Read key out of range")
471 | if enc_key_id < 0 or enc_key_id > 15:
472 | raise ATCA_EXCEPTIONS.BadArgumentError("Encryption key out of range")
473 | if len(num_in) != 32:
474 | raise ATCA_EXCEPTIONS.BadArgumentError("numin length must be 32")
475 |
476 | # Write nonce to TempKey in pass through mode (p71)
477 | self.atcab_nonce(num_in)
478 |
479 | # Supply OtherData so GenDig behavior is the same for keys with
480 | # SlotConfig.NoMac set
481 | other_data = bytearray(4)
482 | other_data[0] = ATCA_CONSTANTS.ATCA_GENDIG
483 | other_data[1] = ATCA_CONSTANTS.GENDIG_ZONE_DATA
484 | other_data[2] = enc_key_id
485 | other_data[3] = enc_key_id >> 8
486 |
487 | # Generate digest and retreive session key from TempKey.value (p68)
488 | gendig_packet = self.atcab_gendig(
489 | ATCA_CONSTANTS.GENDIG_ZONE_DATA, enc_key_id, other_data)
490 | session_key = gendig_packet.response_data[-32:]
491 |
492 | # Read cipher text value (p81)
493 | read_packet = self.atcab_read_zone(
494 | ATCA_CONSTANTS.ATCA_ZONE_DATA |
495 | ATCA_CONSTANTS.ATCA_ZONE_READWRITE_32,
496 | key_id, block, 0, ATCA_CONSTANTS.ATCA_BLOCK_SIZE)
497 | cipher_text = read_packet.response_data
498 |
499 | # Decrypt
500 | plain_text = bytes(a ^ b for (a, b) in zip(cipher_text, session_key))
501 | return plain_text
502 |
503 | def atcab_cmp_config_zone(self, config_data):
504 | raise NotImplementedError("atcab_cmp_config_zone")
505 |
506 | def atcab_read_sig(self, slot):
507 | raise NotImplementedError("atcab_read_sig")
508 |
509 | def atcab_read_pubkey(self, slot):
510 | # Check the value of the slot. Only slots 8 to 15 are large enough to store a public key
511 | if slot < 8 or slot > 15:
512 | raise ATCA_EXCEPTIONS.BadArgumentError(
513 | "Only slots 8 to 15 are large enough to store a public key")
514 |
515 | # The 64 byte P256 public key gets written to a 72 byte slot in the following pattern
516 | #
517 | # | Block 1 | Block 2 | Block 3 |
518 | # | Pad: 4 Bytes | PubKey[0:27] | PubKey[28:31] | Pad: 4 Bytes | PubKey[32:55] | PubKey[56:63] |
519 |
520 | ZD = ATCA_CONSTANTS.ATCA_ZONE_DATA
521 | BS = ATCA_CONSTANTS.ATCA_BLOCK_SIZE
522 | PKD = ATCA_CONSTANTS.ATCA_PUB_KEY_PAD
523 | KS = ATCA_CONSTANTS.ATCA_KEY_SIZE
524 |
525 | public_key = b''
526 | packet = self.atcab_read_zone(ZD, slot=slot, block=0, length=BS)
527 | public_key += packet[1:-2]
528 | packet = self.atcab_read_zone(ZD, slot=slot, block=1, length=BS)
529 | public_key += packet[1:-2]
530 | packet = self.atcab_read_zone(ZD, slot=slot, block=2, length=BS)
531 | public_key += packet[1:-2]
532 |
533 | return public_key[PKD:PKD+KS] + public_key[KS+PKD+PKD:KS+PKD+PKD+KS]
534 |
535 | ###########################################################################
536 | # CryptoAuthLib Basic API methods for SecureBoot command #
537 | ###########################################################################
538 |
539 | def atcab_secureboot(self, mode, param2, digest, signature):
540 | raise NotImplementedError("atcab_secureboot")
541 |
542 | def atcab_secureboot_mac(self, mode, digest, signature, num_in, io_key):
543 | raise NotImplementedError("atcab_secureboot_mac")
544 |
545 | ###########################################################################
546 | # CryptoAuthLib Basic API methods for SelfTest command #
547 | ###########################################################################
548 |
549 | def atcab_selftest(self, mode, param2=0):
550 | if self._device != "ATECC608A":
551 | raise ATCA_EXCEPTIONS.UnsupportedDeviceError("atcab_selftest")
552 | packet = ATCAPacket(
553 | opcode=ATCA_CONSTANTS.ATCA_SELFTEST,
554 | param1=mode,
555 | param2=param2
556 | )
557 | self.execute(packet)
558 | RSP_DATA_IDX = ATCA_CONSTANTS.ATCA_RSP_DATA_IDX
559 | return packet[RSP_DATA_IDX] & int(not mode) == ATCA_STATUS.ATCA_SUCCESS
560 |
561 | ###########################################################################
562 | # CryptoAuthLib Basic API methods for SHA command #
563 | ###########################################################################
564 |
565 | def atcab_sha_base(self, mode=0, data=b'', key_slot=None):
566 | if not isinstance(data, _BYTES_LIKE_OBJECT):
567 | raise ATCA_EXCEPTIONS.BadArgumentError()
568 |
569 | txsize = 0
570 | cmd_mode = mode & ATCA_CONSTANTS.SHA_MODE_MASK
571 | if cmd_mode in (
572 | ATCA_CONSTANTS.SHA_MODE_SHA256_START,
573 | ATCA_CONSTANTS.SHA_MODE_HMAC_START,
574 | ATCA_CONSTANTS.SHA_MODE_SHA256_PUBLIC
575 | ):
576 | txsize = ATCA_CONSTANTS.ATCA_CMD_SIZE_MIN
577 | elif cmd_mode in (
578 | ATCA_CONSTANTS.SHA_MODE_SHA256_UPDATE,
579 | ATCA_CONSTANTS.SHA_MODE_SHA256_END,
580 | ATCA_CONSTANTS.SHA_MODE_HMAC_END
581 | ):
582 | txsize = ATCA_CONSTANTS.ATCA_CMD_SIZE_MIN + len(data)
583 | else:
584 | raise ATCA_EXCEPTIONS.BadArgumentError()
585 |
586 | packet = ATCAPacket(
587 | txsize=txsize,
588 | opcode=ATCA_CONSTANTS.ATCA_SHA,
589 | param1=mode,
590 | param2=len(data) if not isinstance(key_slot, int) else key_slot,
591 | request_data=data
592 | )
593 | self.execute(packet)
594 | return packet
595 |
596 | def atcab_sha(self, data):
597 | bs = ATCA_CONSTANTS.ATCA_SHA256_BLOCK_SIZE
598 | d_mv = memoryview(data)
599 | packet = self.atcab_sha_base(ATCA_CONSTANTS.SHA_MODE_SHA256_START)
600 | chunks, rest = divmod(len(d_mv), bs)
601 | for chunk in range(chunks):
602 | m = ATCA_CONSTANTS.SHA_MODE_SHA256_UPDATE
603 | b = d_mv[chunk:chunk + bs]
604 | packet = self.atcab_sha_base(m, b)
605 | m = ATCA_CONSTANTS.SHA_MODE_SHA256_END
606 | b = d_mv[chunks * bs:chunks * bs + rest]
607 | packet = self.atcab_sha_base(m, b)
608 | return packet
609 |
610 | def atcab_sha_hmac(self, data, key_slot, target):
611 | raise NotImplementedError("atcab_sha_hmac")
612 |
613 | ###########################################################################
614 | # CryptoAuthLib Basic API methods for Sign command #
615 | ###########################################################################
616 |
617 | def atcab_sign_base(self, mode, key_id):
618 | packet = ATCAPacket(
619 | txsize=ATCA_CONSTANTS.SIGN_COUNT,
620 | opcode=ATCA_CONSTANTS.ATCA_SIGN,
621 | param1=mode,
622 | param2=key_id
623 | )
624 | self.execute(packet)
625 | return packet
626 |
627 | def atcab_sign(self, key_id, message):
628 | nonce_target = ATCA_CONSTANTS.NONCE_MODE_TARGET_TEMPKEY
629 | sign_source = ATCA_CONSTANTS.SIGN_MODE_SOURCE_TEMPKEY
630 |
631 | # Load message into device
632 | if self._device == "ATECC608A":
633 | # Use the Message Digest Buffer for the ATECC608A
634 | nonce_target = ATCA_CONSTANTS.NONCE_MODE_TARGET_MSGDIGBUF
635 | sign_source = ATCA_CONSTANTS.SIGN_MODE_SOURCE_MSGDIGBUF
636 |
637 | self.atcab_nonce_load(nonce_target, message)
638 | return self.atcab_sign_base(
639 | ATCA_CONSTANTS.SIGN_MODE_EXTERNAL | sign_source,
640 | key_id
641 | )
642 |
643 | def atcab_sign_internal(self, key_id, is_invalidate=False, is_full_sn=False):
644 | mode = ATCA_CONSTANTS.SIGN_MODE_INTERNAL
645 | if is_invalidate:
646 | mode = mode | ATCA_CONSTANTS.SIGN_MODE_INVALIDATE
647 |
648 | if is_full_sn:
649 | mode = mode | ATCA_CONSTANTS.SIGN_MODE_INCLUDE_SN
650 |
651 | return self.atcab_sign_base(mode, key_id)
652 |
653 | ###########################################################################
654 | # CryptoAuthLib Basic API methods for UpdateExtra command #
655 | ###########################################################################
656 |
657 | def atcab_updateextra(self, mode, value):
658 | packet = ATCAPacket(
659 | opcode=ATCA_CONSTANTS.ATCA_UPDATE_EXTRA,
660 | param1=mode,
661 | param2=value
662 | )
663 | self.execute(packet)
664 | return packet
665 |
666 | ###########################################################################
667 | # CryptoAuthLib Basic API methods for Verify command #
668 | ###########################################################################
669 |
670 | def atcab_verify(self, mode, key_id, signature, public_key=None, other_data=None, mac=None):
671 | if not isinstance(signature, _BYTES_LIKE_OBJECT):
672 | raise ATCA_EXCEPTIONS.BadArgumentError()
673 |
674 | verify_mode = (mode & ATCA_CONSTANTS.VERIFY_MODE_MASK)
675 |
676 | VME = ATCA_CONSTANTS.VERIFY_MODE_EXTERNAL
677 | has_public_key = isinstance(public_key, _BYTES_LIKE_OBJECT)
678 | if verify_mode == VME and not has_public_key:
679 | raise ATCA_EXCEPTIONS.BadArgumentError()
680 |
681 | VMV = ATCA_CONSTANTS.VERIFY_MODE_VALIDATE
682 | VMI = ATCA_CONSTANTS.VERIFY_MODE_INVALIDATE
683 | has_other_data = isinstance(other_data, _BYTES_LIKE_OBJECT)
684 | if verify_mode in (VMV, VMI) and not has_other_data:
685 | raise ATCA_EXCEPTIONS.BadArgumentError()
686 |
687 | txsize = 0
688 | if verify_mode == ATCA_CONSTANTS.VERIFY_MODE_STORED:
689 | txsize = ATCA_CONSTANTS.VERIFY_256_STORED_COUNT
690 | elif verify_mode in (ATCA_CONSTANTS.VERIFY_MODE_VALIDATE_EXTERNAL,
691 | ATCA_CONSTANTS.VERIFY_MODE_EXTERNAL):
692 | txsize = ATCA_CONSTANTS.VERIFY_256_EXTERNAL_COUNT
693 | elif verify_mode in (ATCA_CONSTANTS.VERIFY_MODE_VALIDATE,
694 | ATCA_CONSTANTS.VERIFY_MODE_INVALIDATE):
695 | txsize = ATCA_CONSTANTS.VERIFY_256_VALIDATE_COUNT
696 |
697 | SS = ATCA_CONSTANTS.ATCA_SIG_SIZE
698 | PKS = ATCA_CONSTANTS.ATCA_PUB_KEY_SIZE
699 | VODS = ATCA_CONSTANTS.VERIFY_OTHER_DATA_SIZE
700 | data_size = SS
701 | if has_public_key:
702 | data_size += PKS
703 | elif has_other_data:
704 | data_size += VODS
705 |
706 | data = bytearray(data_size)
707 |
708 | data[0:SS] = signature
709 | if has_public_key:
710 | data[SS:SS+PKS] = public_key
711 | elif has_other_data:
712 | data[SS:SS+VODS] = other_data
713 |
714 | packet = ATCAPacket(
715 | txsize=txsize,
716 | opcode=ATCA_CONSTANTS.ATCA_VERIFY,
717 | param1=mode,
718 | param2=key_id,
719 | request_data=data
720 | )
721 | self.execute(packet)
722 | return packet
723 |
724 | def atcab_verify_extern(self, message, signature, public_key):
725 | if not isinstance(message, _BYTES_LIKE_OBJECT):
726 | raise ATCA_EXCEPTIONS.BadArgumentError()
727 |
728 | if not isinstance(signature, _BYTES_LIKE_OBJECT):
729 | raise ATCA_EXCEPTIONS.BadArgumentError()
730 |
731 | if not isinstance(public_key, _BYTES_LIKE_OBJECT):
732 | raise ATCA_EXCEPTIONS.BadArgumentError()
733 |
734 | nonce_target = ATCA_CONSTANTS.NONCE_MODE_TARGET_TEMPKEY
735 | verify_source = ATCA_CONSTANTS.VERIFY_MODE_SOURCE_TEMPKEY
736 |
737 | # Load message into device
738 | if self._device == "ATECC608A":
739 | # Use the Message Digest Buffer for the ATECC608A
740 | nonce_target = ATCA_CONSTANTS.NONCE_MODE_TARGET_MSGDIGBUF
741 | verify_source = ATCA_CONSTANTS.VERIFY_MODE_SOURCE_MSGDIGBUF
742 |
743 | self.atcab_nonce_load(nonce_target, message)
744 | try:
745 | packet = self.atcab_verify(
746 | ATCA_CONSTANTS.VERIFY_MODE_EXTERNAL | verify_source,
747 | ATCA_CONSTANTS.VERIFY_KEY_P256,
748 | signature,
749 | public_key
750 | )
751 | return packet[1] == ATCA_STATUS.ATCA_SUCCESS
752 | except ATCA_EXCEPTIONS.CheckmacVerifyFailedError:
753 | # Verify failed, but command succeeded
754 | return False
755 |
756 | def atcab_verify_extern_mac(self, message, signature, public_key, num_in, io_key, is_verified):
757 | raise NotImplementedError("atcab_verify_extern_mac")
758 |
759 | def atcab_verify_stored(self, message, signature, key_id):
760 | if not isinstance(message, _BYTES_LIKE_OBJECT):
761 | raise ATCA_EXCEPTIONS.BadArgumentError()
762 |
763 | if not isinstance(signature, _BYTES_LIKE_OBJECT):
764 | raise ATCA_EXCEPTIONS.BadArgumentError()
765 |
766 | nonce_target = ATCA_CONSTANTS.NONCE_MODE_TARGET_TEMPKEY
767 | verify_source = ATCA_CONSTANTS.VERIFY_MODE_SOURCE_TEMPKEY
768 |
769 | # Load message into device
770 | if self._device == "ATECC608A":
771 | # Use the Message Digest Buffer for the ATECC608A
772 | nonce_target = ATCA_CONSTANTS.NONCE_MODE_TARGET_MSGDIGBUF
773 | verify_source = ATCA_CONSTANTS.VERIFY_MODE_SOURCE_MSGDIGBUF
774 |
775 | self.atcab_nonce_load(nonce_target, message)
776 | try:
777 | packet = self.atcab_verify(
778 | ATCA_CONSTANTS.VERIFY_MODE_STORED | verify_source,
779 | key_id,
780 | signature
781 | )
782 | return packet[1] == ATCA_STATUS.ATCA_SUCCESS
783 | except ATCA_EXCEPTIONS.CheckmacVerifyFailedError:
784 | # Verify failed, but command succeeded
785 | return False
786 |
787 | def atcab_verify_stored_mac(self, message, signature, key_id, num_in, io_key, is_verified):
788 | raise NotImplementedError("atcab_verify_stored_mac")
789 |
790 | def atcab_verify_validate(self, key_id, signature, other_data, is_verified):
791 | raise NotImplementedError("atcab_verify_validate")
792 |
793 | def atcab_verify_invalidate(self, key_id, signature, other_data, is_verified):
794 | raise NotImplementedError("atcab_verify_invalidate")
795 |
796 | ###########################################################################
797 | # CryptoAuthLib Basic API methods for Write command #
798 | ###########################################################################
799 |
800 | def atcab_write(self, zone, address, value=None, mac=None):
801 | if not isinstance(value, _BYTES_LIKE_OBJECT):
802 | raise ATCA_EXCEPTIONS.BadArgumentError()
803 |
804 | txsize = ATCA_CONSTANTS.ATCA_CMD_SIZE_MIN
805 | data = bytearray(64)
806 | if zone & ATCA_CONSTANTS.ATCA_ZONE_READWRITE_32:
807 | # 32-byte write
808 | data[0:32] = value
809 | txsize += ATCA_CONSTANTS.ATCA_BLOCK_SIZE
810 | # Only 32-byte writes can have a MAC
811 | if isinstance(mac, _BYTES_LIKE_OBJECT):
812 | data[32:64] = mac
813 | txsize += ATCA_CONSTANTS.WRITE_MAC_SIZE
814 | else:
815 | # 4-byte write
816 | data[0:4] = value
817 | txsize += ATCA_CONSTANTS.ATCA_WORD_SIZE
818 |
819 | packet = ATCAPacket(
820 | txsize=txsize,
821 | opcode=ATCA_CONSTANTS.ATCA_WRITE,
822 | param1=zone,
823 | param2=address,
824 | request_data=data[:txsize-ATCA_CONSTANTS.ATCA_CMD_SIZE_MIN]
825 | )
826 | self.execute(packet)
827 | return packet
828 |
829 | def atcab_write_zone(self, zone, slot=0, block=0, offset=0, data=None):
830 | if not isinstance(data, _BYTES_LIKE_OBJECT):
831 | raise ATCA_EXCEPTIONS.BadArgumentError()
832 |
833 | length = len(data)
834 | if length not in (
835 | ATCA_CONSTANTS.ATCA_WORD_SIZE,
836 | ATCA_CONSTANTS.ATCA_BLOCK_SIZE
837 | ):
838 | raise ATCA_EXCEPTIONS.BadArgumentError()
839 |
840 | if length == ATCA_CONSTANTS.ATCA_BLOCK_SIZE:
841 | zone = zone | ATCA_CONSTANTS.ATCA_ZONE_READWRITE_32
842 |
843 | addr = self.atcab_get_addr(zone, slot=slot, block=block, offset=offset)
844 | return self.atcab_write(zone, addr, data)
845 |
846 | def atcab_write_bytes_zone(self, zone, slot=0, offset=0, data=None):
847 | if not isinstance(data, _BYTES_LIKE_OBJECT):
848 | raise ATCA_EXCEPTIONS.BadArgumentError()
849 |
850 | zone_size = self.atcab_get_zone_size(zone, slot=slot)
851 |
852 | length = len(data)
853 | if offset + length > zone_size:
854 | raise ATCA_EXCEPTIONS.BadArgumentError()
855 |
856 | packets = []
857 |
858 | BS = ATCA_CONSTANTS.ATCA_BLOCK_SIZE
859 | WS = ATCA_CONSTANTS.ATCA_WORD_SIZE
860 | ZC = ATCA_CONSTANTS.ATCA_ZONE_CONFIG
861 |
862 | d_idx = 0
863 | c_blk = offset // BS
864 | c_wrd = (offset % BS) // WS
865 | d_mv = memoryview(data)
866 | while d_idx < length:
867 | # The last item makes sure we handle the selector, user extra, and lock bytes in the config properly
868 | if c_wrd == 0 and length - d_idx >= BS and not (zone == ZC and c_blk == 2):
869 | packet = self.atcab_write_zone(
870 | zone,
871 | slot=slot,
872 | block=c_blk,
873 | offset=0,
874 | data=d_mv[d_idx:d_idx+BS]
875 | )
876 | packets.append(packet)
877 | d_idx += BS
878 | c_blk += 1
879 | else:
880 | # Skip trying to change UserExtra, Selector, LockValue and LockConfig which require the UpdateExtra command to change
881 | if not (zone == ZC and c_blk == 2 and c_wrd == 5):
882 | packet = self.atcab_write_zone(
883 | zone,
884 | slot=slot,
885 | block=c_blk,
886 | offset=c_wrd,
887 | data=d_mv[d_idx:d_idx+WS]
888 | )
889 | packets.append(packet)
890 | d_idx += WS
891 | c_wrd += 1
892 | if c_wrd == BS // WS:
893 | c_blk += 1
894 | c_wrd = 0
895 |
896 | return packets
897 |
898 | def atcab_write_pubkey(self, slot, public_key):
899 | if not isinstance(public_key, _BYTES_LIKE_OBJECT):
900 | raise ATCA_EXCEPTIONS.BadArgumentError()
901 |
902 | # Check the value of the slot. Only slots 8 to 15 are large enough to store a public key
903 | if slot < 8 or slot > 15:
904 | raise ATCA_EXCEPTIONS.BadArgumentError(
905 | "Only slots 8 to 15 are large enough to store a public key")
906 |
907 | public_key_formatted = bytearray(72)
908 |
909 | # The 64 byte P256 public key gets written to a 72 byte slot in the following pattern
910 | #
911 | # | Block 1 | Block 2 | Block 3 |
912 | # | Pad: 4 Bytes | PubKey[0:27] | PubKey[28:31] | Pad: 4 Bytes | PubKey[32:55] | PubKey[56:63] |
913 |
914 | PKD = ATCA_CONSTANTS.ATCA_PUB_KEY_PAD
915 | KS = ATCA_CONSTANTS.ATCA_KEY_SIZE
916 |
917 | # Copy X to padded position
918 | public_key_formatted[PKD:PKD+KS] = public_key[0:KS]
919 | # Copy Y to padded position
920 | public_key_formatted[KS+PKD+PKD:KS+PKD+PKD+KS] = public_key[KS:KS+KS]
921 |
922 | packets = self.atcab_write_bytes_zone(
923 | ATCA_CONSTANTS.ATCA_ZONE_DATA,
924 | slot=slot,
925 | data=public_key_formatted
926 | )
927 |
928 | return packets
929 |
930 | def atcab_write_config_zone(self, config_data):
931 | if not isinstance(config_data, _BYTES_LIKE_OBJECT):
932 | raise ATCA_EXCEPTIONS.BadArgumentError()
933 |
934 | config_size = self.atcab_get_zone_size(ATCA_CONSTANTS.ATCA_ZONE_CONFIG)
935 |
936 | # Write config zone excluding UserExtra and Selector
937 | packets = self.atcab_write_bytes_zone(
938 | ATCA_CONSTANTS.ATCA_ZONE_CONFIG,
939 | slot=0,
940 | offset=16,
941 | data=config_data[16:config_size - 16]
942 | )
943 |
944 | # Write the UserExtra and Selector. This may fail if either value is already non-zero.
945 | packet = self.atcab_updateextra(
946 | ATCA_CONSTANTS.UPDATE_MODE_USER_EXTRA,
947 | config_data[84]
948 | )
949 | packets.append(packet)
950 |
951 | packet = self.atcab_updateextra(
952 | ATCA_CONSTANTS.UPDATE_MODE_SELECTOR,
953 | config_data[85]
954 | )
955 | packets.append(packet)
956 |
957 | return packets
958 |
959 | def atcab_write_enc(self, key_id, block, data, enc_key, enc_key_id):
960 | raise NotImplementedError("atcab_write_enc")
961 |
962 | def atcab_write_config_counter(self, counter_id, counter_value):
963 | raise NotImplementedError("atcab_write_config_counter")
964 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/constant.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import sys
4 | from micropython import const
5 |
6 |
7 | class C(object):
8 | def __getattr__(self, a):
9 | if a == "ATCA_CMD_SIZE_MIN":
10 | return const(7)
11 | elif a == "ATCA_CMD_SIZE_MAX":
12 | return const(4 * 36 + 7)
13 | elif a == "CMD_STATUS_SUCCESS":
14 | return const(0x00)
15 | elif a == "CMD_STATUS_WAKEUP":
16 | return const(0x11)
17 | elif a == "CMD_STATUS_BYTE_PARSE":
18 | return const(0x03)
19 | elif a == "CMD_STATUS_BYTE_ECC":
20 | return const(0x05)
21 | elif a == "CMD_STATUS_BYTE_EXEC":
22 | return const(0x0F)
23 | elif a == "CMD_STATUS_BYTE_COMM":
24 | return const(0xFF)
25 | elif a == "ATCA_CHECKMAC":
26 | return const(0x28)
27 | elif a == "ATCA_DERIVE_KEY":
28 | return const(0x1C)
29 | elif a == "ATCA_INFO":
30 | return const(0x30)
31 | elif a == "ATCA_GENDIG":
32 | return const(0x15)
33 | elif a == "ATCA_GENKEY":
34 | return const(0x40)
35 | elif a == "ATCA_HMAC":
36 | return const(0x11)
37 | elif a == "ATCA_LOCK":
38 | return const(0x17)
39 | elif a == "ATCA_MAC":
40 | return const(0x08)
41 | elif a == "ATCA_NONCE":
42 | return const(0x16)
43 | elif a == "ATCA_PAUSE":
44 | return const(0x01)
45 | elif a == "ATCA_PRIVWRITE":
46 | return const(0x46)
47 | elif a == "ATCA_RANDOM":
48 | return const(0x1B)
49 | elif a == "ATCA_READ":
50 | return const(0x02)
51 | elif a == "ATCA_SIGN":
52 | return const(0x41)
53 | elif a == "ATCA_UPDATE_EXTRA":
54 | return const(0x20)
55 | elif a == "ATCA_VERIFY":
56 | return const(0x45)
57 | elif a == "ATCA_WRITE":
58 | return const(0x12)
59 | elif a == "ATCA_ECDH":
60 | return const(0x43)
61 | elif a == "ATCA_COUNTER":
62 | return const(0x24)
63 | elif a == "ATCA_SHA":
64 | return const(0x47)
65 | elif a == "ATCA_AES":
66 | return const(0x51)
67 | elif a == "ATCA_KDF":
68 | return const(0x56)
69 | elif a == "ATCA_SECUREBOOT":
70 | return const(0x80)
71 | elif a == "ATCA_SELFTEST":
72 | return const(0x77)
73 | elif a == "ATCA_KEY_SIZE":
74 | return const(32)
75 | elif a == "ATCA_BLOCK_SIZE":
76 | return const(32)
77 | elif a == "ATCA_WORD_SIZE":
78 | return const(4)
79 | elif a == "ATCA_PUB_KEY_PAD":
80 | return const(4)
81 | elif a == "ATCA_SERIAL_NUM_SIZE":
82 | return const(9)
83 | elif a == "ATCA_RSP_SIZE_VAL":
84 | return const(7)
85 | elif a == "ATCA_KEY_COUNT":
86 | return const(16)
87 | elif a == "ATCA_ECC_CONFIG_SIZE":
88 | return const(128)
89 | elif a == "ATCA_SHA_CONFIG_SIZE":
90 | return const(88)
91 | elif a == "ATCA_OTP_SIZE":
92 | return const(64)
93 | elif a == "ATCA_DATA_SIZE":
94 | return const(16 * 32)
95 | elif a == "ATCA_AES_GFM_SIZE":
96 | return const(32)
97 | elif a == "ATCA_CHIPMODE_OFFSET":
98 | return const(19)
99 | elif a == "ATCA_CHIPMODE_I2C_ADDRESS_FLAG":
100 | return const(0x01)
101 | elif a == "ATCA_CHIPMODE_TTL_ENABLE_FLAG":
102 | return const(0x02)
103 | elif a == "ATCA_CHIPMODE_WATCHDOG_MASK":
104 | return const(0x04)
105 | elif a == "ATCA_CHIPMODE_WATCHDOG_SHORT":
106 | return const(0x00)
107 | elif a == "ATCA_CHIPMODE_WATCHDOG_LONG":
108 | return const(0x04)
109 | elif a == "ATCA_CHIPMODE_CLOCK_DIV_MASK":
110 | return const(0xF8)
111 | elif a == "ATCA_CHIPMODE_CLOCK_DIV_M0":
112 | return const(0x00)
113 | elif a == "ATCA_CHIPMODE_CLOCK_DIV_M1":
114 | return const(0x28)
115 | elif a == "ATCA_CHIPMODE_CLOCK_DIV_M2":
116 | return const(0x68)
117 | elif a == "ATCA_COUNT_SIZE":
118 | return const(1)
119 | elif a == "ATCA_CRC_SIZE":
120 | return const(2)
121 | elif a == "ATCA_PACKET_OVERHEAD":
122 | return const(3)
123 | elif a == "ATCA_PUB_KEY_SIZE":
124 | return const(64)
125 | elif a == "ATCA_PRIV_KEY_SIZE":
126 | return const(32)
127 | elif a == "ATCA_SIG_SIZE":
128 | return const(64)
129 | elif a == "RSA2048_KEY_SIZE":
130 | return const(256)
131 | elif a == "ATCA_RSP_SIZE_MIN":
132 | return const(4)
133 | elif a == "ATCA_RSP_SIZE_4":
134 | return const(7)
135 | elif a == "ATCA_RSP_SIZE_72":
136 | return const(75)
137 | elif a == "ATCA_RSP_SIZE_64":
138 | return const(67)
139 | elif a == "ATCA_RSP_SIZE_32":
140 | return const(35)
141 | elif a == "ATCA_RSP_SIZE_16":
142 | return const(19)
143 | elif a == "ATCA_RSP_SIZE_MAX":
144 | return const(75)
145 | elif a == "OUTNONCE_SIZE":
146 | return const(32)
147 | elif a == "ATCA_KEY_ID_MAX":
148 | return const(15)
149 | elif a == "ATCA_OTP_BLOCK_MAX":
150 | return const(1)
151 | elif a == "ATCA_COUNT_IDX":
152 | return const(0)
153 | elif a == "ATCA_OPCODE_IDX":
154 | return const(1)
155 | elif a == "ATCA_PARAM1_IDX":
156 | return const(2)
157 | elif a == "ATCA_PARAM2_IDX":
158 | return const(3)
159 | elif a == "ATCA_DATA_IDX":
160 | return const(5)
161 | elif a == "ATCA_RSP_DATA_IDX":
162 | return const(1)
163 | elif a == "ATCA_ZONE_CONFIG":
164 | return const(0x00)
165 | elif a == "ATCA_ZONE_OTP":
166 | return const(0x01)
167 | elif a == "ATCA_ZONE_DATA":
168 | return const(0x02)
169 | elif a == "ATCA_ZONE_MASK":
170 | return const(0x03)
171 | elif a == "ATCA_ZONE_ENCRYPTED":
172 | return const(0x40)
173 | elif a == "ATCA_ZONE_READWRITE_32":
174 | return const(0x80)
175 | elif a == "ATCA_ADDRESS_MASK_CONFIG":
176 | return const(0x001F)
177 | elif a == "ATCA_ADDRESS_MASK_OTP":
178 | return const(0x000F)
179 | elif a == "ATCA_ADDRESS_MASK":
180 | return const(0x007F)
181 | elif a == "ATCA_TEMPKEY_KEYID":
182 | return const(0xFFFF)
183 | elif a == "ATCA_B283_KEY_TYPE":
184 | return const(0)
185 | elif a == "ATCA_K283_KEY_TYPE":
186 | return const(1)
187 | elif a == "ATCA_P256_KEY_TYPE":
188 | return const(4)
189 | elif a == "ATCA_AES_KEY_TYPE":
190 | return const(6)
191 | elif a == "ATCA_SHA_KEY_TYPE":
192 | return const(7)
193 | elif a == "AES_MODE_IDX":
194 | return const(2)
195 | elif a == "AES_KEYID_IDX":
196 | return const(3)
197 | elif a == "AES_INPUT_IDX":
198 | return const(5)
199 | elif a == "AES_COUNT":
200 | return const(23)
201 | elif a == "AES_MODE_MASK":
202 | return const(0xC7)
203 | elif a == "AES_MODE_KEY_BLOCK_MASK":
204 | return const(0xC0)
205 | elif a == "AES_MODE_OP_MASK":
206 | return const(0x07)
207 | elif a == "AES_MODE_ENCRYPT":
208 | return const(0x00)
209 | elif a == "AES_MODE_DECRYPT":
210 | return const(0x01)
211 | elif a == "AES_MODE_GFM":
212 | return const(0x03)
213 | elif a == "AES_MODE_KEY_BLOCK_POS":
214 | return const(6)
215 | elif a == "AES_DATA_SIZE":
216 | return const(16)
217 | elif a == "AES_RSP_SIZE":
218 | return const(19)
219 | elif a == "CHECKMAC_MODE_IDX":
220 | return const(2)
221 | elif a == "CHECKMAC_KEYID_IDX":
222 | return const(3)
223 | elif a == "CHECKMAC_CLIENT_CHALLENGE_IDX":
224 | return const(5)
225 | elif a == "CHECKMAC_CLIENT_RESPONSE_IDX":
226 | return const(37)
227 | elif a == "CHECKMAC_DATA_IDX":
228 | return const(69)
229 | elif a == "CHECKMAC_COUNT":
230 | return const(84)
231 | elif a == "CHECKMAC_MODE_CHALLENGE":
232 | return const(0x00)
233 | elif a == "CHECKMAC_MODE_BLOCK2_TEMPKEY":
234 | return const(0x01)
235 | elif a == "CHECKMAC_MODE_BLOCK1_TEMPKEY":
236 | return const(0x02)
237 | elif a == "CHECKMAC_MODE_SOURCE_FLAG_MATCH":
238 | return const(0x04)
239 | elif a == "CHECKMAC_MODE_INCLUDE_OTP_64":
240 | return const(0x20)
241 | elif a == "CHECKMAC_MODE_MASK":
242 | return const(0x27)
243 | elif a == "CHECKMAC_CLIENT_CHALLENGE_SIZE":
244 | return const(32)
245 | elif a == "CHECKMAC_CLIENT_RESPONSE_SIZE":
246 | return const(32)
247 | elif a == "CHECKMAC_OTHER_DATA_SIZE":
248 | return const(13)
249 | elif a == "CHECKMAC_CLIENT_COMMAND_SIZE":
250 | return const(4)
251 | elif a == "CHECKMAC_CMD_MATCH":
252 | return const(0)
253 | elif a == "CHECKMAC_CMD_MISMATCH":
254 | return const(1)
255 | elif a == "CHECKMAC_RSP_SIZE":
256 | return const(4)
257 | elif a == "COUNTER_COUNT":
258 | return const(7)
259 | elif a == "COUNTER_MODE_IDX":
260 | return const(2)
261 | elif a == "COUNTER_KEYID_IDX":
262 | return const(3)
263 | elif a == "COUNTER_MODE_MASK":
264 | return const(0x01)
265 | elif a == "COUNTER_MAX_VALUE":
266 | return const(2097151)
267 | elif a == "COUNTER_MODE_READ":
268 | return const(0x00)
269 | elif a == "COUNTER_MODE_INCREMENT":
270 | return const(0x01)
271 | elif a == "COUNTER_RSP_SIZE":
272 | return const(7)
273 | elif a == "DERIVE_KEY_RANDOM_IDX":
274 | return const(2)
275 | elif a == "DERIVE_KEY_TARGETKEY_IDX":
276 | return const(3)
277 | elif a == "DERIVE_KEY_MAC_IDX":
278 | return const(5)
279 | elif a == "DERIVE_KEY_COUNT_SMALL":
280 | return const(7)
281 | elif a == "DERIVE_KEY_MODE":
282 | return const(0x04)
283 | elif a == "DERIVE_KEY_COUNT_LARGE":
284 | return const(39)
285 | elif a == "DERIVE_KEY_RANDOM_FLAG":
286 | return const(4)
287 | elif a == "DERIVE_KEY_MAC_SIZE":
288 | return const(32)
289 | elif a == "DERIVE_KEY_RSP_SIZE":
290 | return const(4)
291 | elif a == "ECDH_PREFIX_MODE":
292 | return const(0x00)
293 | elif a == "ECDH_COUNT":
294 | return const(7 + 64)
295 | elif a == "ECDH_MODE_SOURCE_MASK":
296 | return const(0x01)
297 | elif a == "ECDH_MODE_SOURCE_EEPROM_SLOT":
298 | return const(0x00)
299 | elif a == "ECDH_MODE_SOURCE_TEMPKEY":
300 | return const(0x01)
301 | elif a == "ECDH_MODE_OUTPUT_MASK":
302 | return const(0x02)
303 | elif a == "ECDH_MODE_OUTPUT_CLEAR":
304 | return const(0x00)
305 | elif a == "ECDH_MODE_OUTPUT_ENC":
306 | return const(0x02)
307 | elif a == "ECDH_MODE_COPY_MASK":
308 | return const(0x0C)
309 | elif a == "ECDH_MODE_COPY_COMPATIBLE":
310 | return const(0x00)
311 | elif a == "ECDH_MODE_COPY_EEPROM_SLOT":
312 | return const(0x04)
313 | elif a == "ECDH_MODE_COPY_TEMP_KEY":
314 | return const(0x08)
315 | elif a == "ECDH_MODE_COPY_OUTPUT_BUFFER":
316 | return const(0x0C)
317 | elif a == "ECDH_KEY_SIZE":
318 | return const(32)
319 | elif a == "ECDH_RSP_SIZE":
320 | return const(67)
321 | elif a == "GENDIG_ZONE_IDX":
322 | return const(2)
323 | elif a == "GENDIG_KEYID_IDX":
324 | return const(3)
325 | elif a == "GENDIG_DATA_IDX":
326 | return const(5)
327 | elif a == "GENDIG_COUNT":
328 | return const(7)
329 | elif a == "GENDIG_ZONE_CONFIG":
330 | return const(0)
331 | elif a == "GENDIG_ZONE_OTP":
332 | return const(1)
333 | elif a == "GENDIG_ZONE_DATA":
334 | return const(2)
335 | elif a == "GENDIG_ZONE_SHARED_NONCE":
336 | return const(3)
337 | elif a == "GENDIG_ZONE_COUNTER":
338 | return const(4)
339 | elif a == "GENDIG_ZONE_KEY_CONFIG":
340 | return const(5)
341 | elif a == "GENDIG_RSP_SIZE":
342 | return const(4)
343 | elif a == "GENKEY_MODE_IDX":
344 | return const(2)
345 | elif a == "GENKEY_KEYID_IDX":
346 | return const(3)
347 | elif a == "GENKEY_DATA_IDX":
348 | return const(5)
349 | elif a == "GENKEY_COUNT":
350 | return const(7)
351 | elif a == "GENKEY_COUNT_DATA":
352 | return const(10)
353 | elif a == "GENKEY_OTHER_DATA_SIZE":
354 | return const(3)
355 | elif a == "GENKEY_MODE_MASK":
356 | return const(0x1C)
357 | elif a == "GENKEY_MODE_PRIVATE":
358 | return const(0x04)
359 | elif a == "GENKEY_MODE_PUBLIC":
360 | return const(0x00)
361 | elif a == "GENKEY_MODE_DIGEST":
362 | return const(0x08)
363 | elif a == "GENKEY_MODE_PUBKEY_DIGEST":
364 | return const(0x10)
365 | elif a == "GENKEY_PRIVATE_TO_TEMPKEY":
366 | return const(0xFFFF)
367 | elif a == "GENKEY_RSP_SIZE_SHORT":
368 | return const(4)
369 | elif a == "GENKEY_RSP_SIZE_LONG":
370 | return const(75)
371 | elif a == "HMAC_MODE_IDX":
372 | return const(2)
373 | elif a == "HMAC_KEYID_IDX":
374 | return const(3)
375 | elif a == "HMAC_COUNT":
376 | return const(7)
377 | elif a == "HMAC_MODE_FLAG_TK_RAND":
378 | return const(0x00)
379 | elif a == "HMAC_MODE_FLAG_TK_NORAND":
380 | return const(0x04)
381 | elif a == "HMAC_MODE_FLAG_OTP88":
382 | return const(0x10)
383 | elif a == "HMAC_MODE_FLAG_OTP64":
384 | return const(0x20)
385 | elif a == "HMAC_MODE_FLAG_FULLSN":
386 | return const(0x40)
387 | elif a == "HMAC_MODE_MASK":
388 | return const(0x74)
389 | elif a == "HMAC_DIGEST_SIZE":
390 | return const(32)
391 | elif a == "HMAC_RSP_SIZE":
392 | return const(35)
393 | elif a == "INFO_PARAM1_IDX":
394 | return const(2)
395 | elif a == "INFO_PARAM2_IDX":
396 | return const(3)
397 | elif a == "INFO_COUNT":
398 | return const(7)
399 | elif a == "INFO_MODE_REVISION":
400 | return const(0x00)
401 | elif a == "INFO_MODE_KEY_VALID":
402 | return const(0x01)
403 | elif a == "INFO_MODE_STATE":
404 | return const(0x02)
405 | elif a == "INFO_MODE_GPIO":
406 | return const(0x03)
407 | elif a == "INFO_MODE_VOL_KEY_PERMIT":
408 | return const(0x04)
409 | elif a == "INFO_MODE_MAX":
410 | return const(0x03)
411 | elif a == "INFO_NO_STATE":
412 | return const(0x00)
413 | elif a == "INFO_OUTPUT_STATE_MASK":
414 | return const(0x01)
415 | elif a == "INFO_DRIVER_STATE_MASK":
416 | return const(0x02)
417 | elif a == "INFO_PARAM2_SET_LATCH_STATE":
418 | return const(0x0002)
419 | elif a == "INFO_PARAM2_LATCH_SET":
420 | return const(0x0001)
421 | elif a == "INFO_PARAM2_LATCH_CLEAR":
422 | return const(0x0000)
423 | elif a == "INFO_SIZE":
424 | return const(0x04)
425 | elif a == "INFO_RSP_SIZE":
426 | return const(7)
427 | elif a == "KDF_MODE_IDX":
428 | return const(2)
429 | elif a == "KDF_KEYID_IDX":
430 | return const(3)
431 | elif a == "KDF_DETAILS_IDX":
432 | return const(5)
433 | elif a == "KDF_DETAILS_SIZE":
434 | return const(4)
435 | elif a == "KDF_MESSAGE_IDX":
436 | return const(5 + 4)
437 | elif a == "KDF_MODE_SOURCE_MASK":
438 | return const(0x03)
439 | elif a == "KDF_MODE_SOURCE_TEMPKEY":
440 | return const(0x00)
441 | elif a == "KDF_MODE_SOURCE_TEMPKEY_UP":
442 | return const(0x01)
443 | elif a == "KDF_MODE_SOURCE_SLOT":
444 | return const(0x02)
445 | elif a == "KDF_MODE_SOURCE_ALTKEYBUF":
446 | return const(0x03)
447 | elif a == "KDF_MODE_TARGET_MASK":
448 | return const(0x1C)
449 | elif a == "KDF_MODE_TARGET_TEMPKEY":
450 | return const(0x00)
451 | elif a == "KDF_MODE_TARGET_TEMPKEY_UP":
452 | return const(0x04)
453 | elif a == "KDF_MODE_TARGET_SLOT":
454 | return const(0x08)
455 | elif a == "KDF_MODE_TARGET_ALTKEYBUF":
456 | return const(0x0C)
457 | elif a == "KDF_MODE_TARGET_OUTPUT":
458 | return const(0x10)
459 | elif a == "KDF_MODE_TARGET_OUTPUT_ENC":
460 | return const(0x14)
461 | elif a == "KDF_MODE_ALG_MASK":
462 | return const(0x60)
463 | elif a == "KDF_MODE_ALG_PRF":
464 | return const(0x00)
465 | elif a == "KDF_MODE_ALG_AES":
466 | return const(0x20)
467 | elif a == "KDF_MODE_ALG_HKDF":
468 | return const(0x40)
469 | elif a == "KDF_DETAILS_PRF_KEY_LEN_MASK":
470 | return const(0x00000003)
471 | elif a == "KDF_DETAILS_PRF_KEY_LEN_16":
472 | return const(0x00000000)
473 | elif a == "KDF_DETAILS_PRF_KEY_LEN_32":
474 | return const(0x00000001)
475 | elif a == "KDF_DETAILS_PRF_KEY_LEN_48":
476 | return const(0x00000002)
477 | elif a == "KDF_DETAILS_PRF_KEY_LEN_64":
478 | return const(0x00000003)
479 | elif a == "KDF_DETAILS_PRF_TARGET_LEN_MASK":
480 | return const(0x00000100)
481 | elif a == "KDF_DETAILS_PRF_TARGET_LEN_32":
482 | return const(0x00000000)
483 | elif a == "KDF_DETAILS_PRF_TARGET_LEN_64":
484 | return const(0x00000100)
485 | elif a == "KDF_DETAILS_PRF_AEAD_MASK":
486 | return const(0x00000600)
487 | elif a == "KDF_DETAILS_PRF_AEAD_MODE0":
488 | return const(0x00000000)
489 | elif a == "KDF_DETAILS_PRF_AEAD_MODE1":
490 | return const(0x00000200)
491 | elif a == "KDF_DETAILS_AES_KEY_LOC_MASK":
492 | return const(0x00000003)
493 | elif a == "KDF_DETAILS_HKDF_MSG_LOC_MASK":
494 | return const(0x00000003)
495 | elif a == "KDF_DETAILS_HKDF_MSG_LOC_SLOT":
496 | return const(0x00000000)
497 | elif a == "KDF_DETAILS_HKDF_MSG_LOC_TEMPKEY":
498 | return const(0x00000001)
499 | elif a == "KDF_DETAILS_HKDF_MSG_LOC_INPUT":
500 | return const(0x00000002)
501 | elif a == "KDF_DETAILS_HKDF_MSG_LOC_IV":
502 | return const(0x00000003)
503 | elif a == "KDF_DETAILS_HKDF_ZERO_KEY":
504 | return const(0x00000004)
505 | elif a == "LOCK_ZONE_IDX":
506 | return const(2)
507 | elif a == "LOCK_SUMMARY_IDX":
508 | return const(3)
509 | elif a == "LOCK_COUNT":
510 | return const(7)
511 | elif a == "LOCK_ZONE_CONFIG":
512 | return const(0x00)
513 | elif a == "LOCK_ZONE_DATA":
514 | return const(0x01)
515 | elif a == "LOCK_ZONE_DATA_SLOT":
516 | return const(0x02)
517 | elif a == "LOCK_ZONE_NO_CRC":
518 | return const(0x80)
519 | elif a == "LOCK_ZONE_MASK":
520 | return const(0xBF)
521 | elif a == "ATCA_UNLOCKED":
522 | return const(0x55)
523 | elif a == "ATCA_LOCKED":
524 | return const(0x00)
525 | elif a == "LOCK_RSP_SIZE":
526 | return const(4)
527 | elif a == "MAC_MODE_IDX":
528 | return const(2)
529 | elif a == "MAC_KEYID_IDX":
530 | return const(3)
531 | elif a == "MAC_CHALLENGE_IDX":
532 | return const(5)
533 | elif a == "MAC_COUNT_SHORT":
534 | return const(7)
535 | elif a == "MAC_COUNT_LONG":
536 | return const(39)
537 | elif a == "MAC_MODE_CHALLENGE":
538 | return const(0x00)
539 | elif a == "MAC_MODE_BLOCK2_TEMPKEY":
540 | return const(0x01)
541 | elif a == "MAC_MODE_BLOCK1_TEMPKEY":
542 | return const(0x02)
543 | elif a == "MAC_MODE_SOURCE_FLAG_MATCH":
544 | return const(0x04)
545 | elif a == "MAC_MODE_PTNONCE_TEMPKEY":
546 | return const(0x06)
547 | elif a == "MAC_MODE_PASSTHROUGH":
548 | return const(0x07)
549 | elif a == "MAC_MODE_INCLUDE_OTP_88":
550 | return const(0x10)
551 | elif a == "MAC_MODE_INCLUDE_OTP_64":
552 | return const(0x20)
553 | elif a == "MAC_MODE_INCLUDE_SN":
554 | return const(0x40)
555 | elif a == "MAC_CHALLENGE_SIZE":
556 | return const(32)
557 | elif a == "MAC_SIZE":
558 | return const(32)
559 | elif a == "MAC_MODE_MASK":
560 | return const(0x77)
561 | elif a == "MAC_RSP_SIZE":
562 | return const(35)
563 | elif a == "NONCE_MODE_IDX":
564 | return const(2)
565 | elif a == "NONCE_PARAM2_IDX":
566 | return const(3)
567 | elif a == "NONCE_INPUT_IDX":
568 | return const(5)
569 | elif a == "NONCE_COUNT_SHORT":
570 | return const(7 + 20)
571 | elif a == "NONCE_COUNT_LONG":
572 | return const(7 + 32)
573 | elif a == "NONCE_COUNT_LONG_64":
574 | return const(7 + 64)
575 | elif a == "NONCE_MODE_MASK":
576 | return const(0x03)
577 | elif a == "NONCE_MODE_SEED_UPDATE":
578 | return const(0x00)
579 | elif a == "NONCE_MODE_NO_SEED_UPDATE":
580 | return const(0x01)
581 | elif a == "NONCE_MODE_INVALID":
582 | return const(0x02)
583 | elif a == "NONCE_MODE_PASSTHROUGH":
584 | return const(0x03)
585 | elif a == "NONCE_MODE_INPUT_LEN_MASK":
586 | return const(0x20)
587 | elif a == "NONCE_MODE_INPUT_LEN_32":
588 | return const(0x00)
589 | elif a == "NONCE_MODE_INPUT_LEN_64":
590 | return const(0x20)
591 | elif a == "NONCE_MODE_TARGET_MASK":
592 | return const(0xC0)
593 | elif a == "NONCE_MODE_TARGET_TEMPKEY":
594 | return const(0x00)
595 | elif a == "NONCE_MODE_TARGET_MSGDIGBUF":
596 | return const(0x40)
597 | elif a == "NONCE_MODE_TARGET_ALTKEYBUF":
598 | return const(0x80)
599 | elif a == "NONCE_ZERO_CALC_MASK":
600 | return const(0x8000)
601 | elif a == "NONCE_ZERO_CALC_RANDOM":
602 | return const(0x0000)
603 | elif a == "NONCE_ZERO_CALC_TEMPKEY":
604 | return const(0x8000)
605 | elif a == "NONCE_NUMIN_SIZE":
606 | return const(20)
607 | elif a == "NONCE_NUMIN_SIZE_PASSTHROUGH":
608 | return const(32)
609 | elif a == "NONCE_RSP_SIZE_SHORT":
610 | return const(4)
611 | elif a == "NONCE_RSP_SIZE_LONG":
612 | return const(35)
613 | elif a == "PAUSE_SELECT_IDX":
614 | return const(2)
615 | elif a == "PAUSE_PARAM2_IDX":
616 | return const(3)
617 | elif a == "PAUSE_COUNT":
618 | return const(7)
619 | elif a == "PAUSE_RSP_SIZE":
620 | return const(4)
621 | elif a == "PRIVWRITE_ZONE_IDX":
622 | return const(2)
623 | elif a == "PRIVWRITE_KEYID_IDX":
624 | return const(3)
625 | elif a == "PRIVWRITE_VALUE_IDX":
626 | return const(5)
627 | elif a == "PRIVWRITE_MAC_IDX":
628 | return const(41)
629 | elif a == "PRIVWRITE_COUNT":
630 | return const(75)
631 | elif a == "PRIVWRITE_ZONE_MASK":
632 | return const(0x40)
633 | elif a == "PRIVWRITE_MODE_ENCRYPT":
634 | return const(0x40)
635 | elif a == "PRIVWRITE_RSP_SIZE":
636 | return const(4)
637 | elif a == "RANDOM_MODE_IDX":
638 | return const(2)
639 | elif a == "RANDOM_PARAM2_IDX":
640 | return const(3)
641 | elif a == "RANDOM_COUNT":
642 | return const(7)
643 | elif a == "RANDOM_SEED_UPDATE":
644 | return const(0x00)
645 | elif a == "RANDOM_NO_SEED_UPDATE":
646 | return const(0x01)
647 | elif a == "RANDOM_NUM_SIZE":
648 | return const(32)
649 | elif a == "RANDOM_RSP_SIZE":
650 | return const(35)
651 | elif a == "READ_ZONE_IDX":
652 | return const(2)
653 | elif a == "READ_ADDR_IDX":
654 | return const(3)
655 | elif a == "READ_COUNT":
656 | return const(7)
657 | elif a == "READ_ZONE_MASK":
658 | return const(0x83)
659 | elif a == "READ_4_RSP_SIZE":
660 | return const(7)
661 | elif a == "READ_32_RSP_SIZE":
662 | return const(35)
663 | elif a == "SECUREBOOT_MODE_IDX":
664 | return const(2)
665 | elif a == "SECUREBOOT_DIGEST_SIZE":
666 | return const(32)
667 | elif a == "SECUREBOOT_SIGNATURE_SIZE":
668 | return const(64)
669 | elif a == "SECUREBOOT_COUNT_DIG":
670 | return const(7 + 32)
671 | elif a == "SECUREBOOT_COUNT_DIG_SIG":
672 | return const(7 + 32 + 64)
673 | elif a == "SECUREBOOT_MAC_SIZE":
674 | return const(32)
675 | elif a == "SECUREBOOT_RSP_SIZE_NO_MAC":
676 | return const(4)
677 | elif a == "SECUREBOOT_RSP_SIZE_MAC":
678 | return const(3 + 32)
679 | elif a == "SECUREBOOT_MODE_MASK":
680 | return const(0x07)
681 | elif a == "SECUREBOOT_MODE_FULL":
682 | return const(0x05)
683 | elif a == "SECUREBOOT_MODE_FULL_STORE":
684 | return const(0x06)
685 | elif a == "SECUREBOOT_MODE_FULL_COPY":
686 | return const(0x07)
687 | elif a == "SECUREBOOT_MODE_PROHIBIT_FLAG":
688 | return const(0x40)
689 | elif a == "SECUREBOOT_MODE_ENC_MAC_FLAG":
690 | return const(0x80)
691 | elif a == "SECUREBOOTCONFIG_OFFSET":
692 | return const(70)
693 | elif a == "SECUREBOOTCONFIG_MODE_MASK":
694 | return const(0x0003)
695 | elif a == "SECUREBOOTCONFIG_MODE_DISABLED":
696 | return const(0x0000)
697 | elif a == "SECUREBOOTCONFIG_MODE_FULL_BOTH":
698 | return const(0x0001)
699 | elif a == "SECUREBOOTCONFIG_MODE_FULL_SIG":
700 | return const(0x0002)
701 | elif a == "SECUREBOOTCONFIG_MODE_FULL_DIG":
702 | return const(0x0003)
703 | elif a == "SELFTEST_MODE_IDX":
704 | return const(2)
705 | elif a == "SELFTEST_COUNT":
706 | return const(7)
707 | elif a == "SELFTEST_MODE_RNG":
708 | return const(0x01)
709 | elif a == "SELFTEST_MODE_ECDSA_SIGN_VERIFY":
710 | return const(0x02)
711 | elif a == "SELFTEST_MODE_ECDH":
712 | return const(0x08)
713 | elif a == "SELFTEST_MODE_AES":
714 | return const(0x10)
715 | elif a == "SELFTEST_MODE_SHA":
716 | return const(0x20)
717 | elif a == "SELFTEST_MODE_ALL":
718 | return const(0x3B)
719 | elif a == "SELFTEST_RSP_SIZE":
720 | return const(4)
721 | elif a == "SHA_COUNT_SHORT":
722 | return const(7)
723 | elif a == "SHA_COUNT_LONG":
724 | return const(7)
725 | elif a == "ATCA_SHA_DIGEST_SIZE":
726 | return const(32)
727 | elif a == "SHA_DATA_MAX":
728 | return const(64)
729 | elif a == "ATCA_SHA256_BLOCK_SIZE":
730 | return const(64)
731 | elif a == "SHA_CONTEXT_MAX_SIZE":
732 | return const(99)
733 | elif a == "SHA_MODE_MASK":
734 | return const(0x07)
735 | elif a == "SHA_MODE_SHA256_START":
736 | return const(0x00)
737 | elif a == "SHA_MODE_SHA256_UPDATE":
738 | return const(0x01)
739 | elif a == "SHA_MODE_SHA256_END":
740 | return const(0x02)
741 | elif a == "SHA_MODE_SHA256_PUBLIC":
742 | return const(0x03)
743 | elif a == "SHA_MODE_HMAC_START":
744 | return const(0x04)
745 | elif a == "SHA_MODE_HMAC_UPDATE":
746 | return const(0x01)
747 | elif a == "SHA_MODE_HMAC_END":
748 | return const(0x05)
749 | elif a == "SHA_MODE_608_HMAC_END":
750 | return const(0x02)
751 | elif a == "SHA_MODE_READ_CONTEXT":
752 | return const(0x06)
753 | elif a == "SHA_MODE_WRITE_CONTEXT":
754 | return const(0x07)
755 | elif a == "SHA_MODE_TARGET_MASK":
756 | return const(0xC0)
757 | elif a == "SHA_MODE_TARGET_TEMPKEY":
758 | return const(0x00)
759 | elif a == "SHA_MODE_TARGET_MSGDIGBUF":
760 | return const(0x40)
761 | elif a == "SHA_MODE_TARGET_OUT_ONLY":
762 | return const(0xC0)
763 | elif a == "SHA_RSP_SIZE":
764 | return const(35)
765 | elif a == "SHA_RSP_SIZE_SHORT":
766 | return const(4)
767 | elif a == "SHA_RSP_SIZE_LONG":
768 | return const(35)
769 | elif a == "SIGN_MODE_IDX":
770 | return const(2)
771 | elif a == "SIGN_KEYID_IDX":
772 | return const(3)
773 | elif a == "SIGN_COUNT":
774 | return const(7)
775 | elif a == "SIGN_MODE_MASK":
776 | return const(0xE1)
777 | elif a == "SIGN_MODE_INTERNAL":
778 | return const(0x00)
779 | elif a == "SIGN_MODE_INVALIDATE":
780 | return const(0x01)
781 | elif a == "SIGN_MODE_INCLUDE_SN":
782 | return const(0x40)
783 | elif a == "SIGN_MODE_EXTERNAL":
784 | return const(0x80)
785 | elif a == "SIGN_MODE_SOURCE_MASK":
786 | return const(0x20)
787 | elif a == "SIGN_MODE_SOURCE_TEMPKEY":
788 | return const(0x00)
789 | elif a == "SIGN_MODE_SOURCE_MSGDIGBUF":
790 | return const(0x20)
791 | elif a == "SIGN_RSP_SIZE":
792 | return const(75)
793 | elif a == "UPDATE_MODE_IDX":
794 | return const(2)
795 | elif a == "UPDATE_VALUE_IDX":
796 | return const(3)
797 | elif a == "UPDATE_COUNT":
798 | return const(7)
799 | elif a == "UPDATE_MODE_USER_EXTRA":
800 | return const(0x00)
801 | elif a == "UPDATE_MODE_SELECTOR":
802 | return const(0x01)
803 | elif a == "UPDATE_MODE_USER_EXTRA_ADD":
804 | return const(0x01)
805 | elif a == "UPDATE_MODE_DEC_COUNTER":
806 | return const(0x02)
807 | elif a == "UPDATE_RSP_SIZE":
808 | return const(4)
809 | elif a == "VERIFY_MODE_IDX":
810 | return const(2)
811 | elif a == "VERIFY_KEYID_IDX":
812 | return const(3)
813 | elif a == "VERIFY_DATA_IDX":
814 | return const(5)
815 | elif a == "VERIFY_256_STORED_COUNT":
816 | return const(71)
817 | elif a == "VERIFY_283_STORED_COUNT":
818 | return const(79)
819 | elif a == "VERIFY_256_VALIDATE_COUNT":
820 | return const(90)
821 | elif a == "VERIFY_283_VALIDATE_COUNT":
822 | return const(98)
823 | elif a == "VERIFY_256_EXTERNAL_COUNT":
824 | return const(135)
825 | elif a == "VERIFY_283_EXTERNAL_COUNT":
826 | return const(151)
827 | elif a == "VERIFY_256_KEY_SIZE":
828 | return const(64)
829 | elif a == "VERIFY_283_KEY_SIZE":
830 | return const(72)
831 | elif a == "VERIFY_256_SIGNATURE_SIZE":
832 | return const(64)
833 | elif a == "VERIFY_283_SIGNATURE_SIZE":
834 | return const(72)
835 | elif a == "VERIFY_OTHER_DATA_SIZE":
836 | return const(19)
837 | elif a == "VERIFY_MODE_MASK":
838 | return const(0x03)
839 | elif a == "VERIFY_MODE_STORED":
840 | return const(0x00)
841 | elif a == "VERIFY_MODE_VALIDATE_EXTERNAL":
842 | return const(0x01)
843 | elif a == "VERIFY_MODE_EXTERNAL":
844 | return const(0x02)
845 | elif a == "VERIFY_MODE_VALIDATE":
846 | return const(0x03)
847 | elif a == "VERIFY_MODE_INVALIDATE":
848 | return const(0x07)
849 | elif a == "VERIFY_MODE_SOURCE_MASK":
850 | return const(0x20)
851 | elif a == "VERIFY_MODE_SOURCE_TEMPKEY":
852 | return const(0x00)
853 | elif a == "VERIFY_MODE_SOURCE_MSGDIGBUF":
854 | return const(0x20)
855 | elif a == "VERIFY_MODE_MAC_FLAG":
856 | return const(0x80)
857 | elif a == "VERIFY_KEY_B283":
858 | return const(0)
859 | elif a == "VERIFY_KEY_K283":
860 | return const(0x0001)
861 | elif a == "VERIFY_KEY_P256":
862 | return const(0x0004)
863 | elif a == "VERIFY_RSP_SIZE":
864 | return const(4)
865 | elif a == "VERIFY_RSP_SIZE_MAC":
866 | return const(35)
867 | elif a == "WRITE_ZONE_IDX":
868 | return const(2)
869 | elif a == "WRITE_ADDR_IDX":
870 | return const(3)
871 | elif a == "WRITE_VALUE_IDX":
872 | return const(5)
873 | elif a == "WRITE_MAC_VS_IDX":
874 | return const(9)
875 | elif a == "WRITE_MAC_VL_IDX":
876 | return const(37)
877 | elif a == "WRITE_MAC_SIZE":
878 | return const(32)
879 | elif a == "WRITE_ZONE_MASK":
880 | return const(0xC3)
881 | elif a == "WRITE_ZONE_WITH_MAC":
882 | return const(0x40)
883 | elif a == "WRITE_ZONE_OTP":
884 | return const(1)
885 | elif a == "WRITE_ZONE_DATA":
886 | return const(2)
887 | elif a == "WRITE_RSP_SIZE":
888 | return const(4)
889 | elif a == "ATECC508A_EXECUTION_TIME":
890 | return {
891 | self.ATCA_CHECKMAC: const(13),
892 | self.ATCA_COUNTER: const(20),
893 | self.ATCA_DERIVE_KEY: const(50),
894 | self.ATCA_ECDH: const(58),
895 | self.ATCA_GENDIG: const(11),
896 | self.ATCA_GENKEY: const(115),
897 | self.ATCA_HMAC: const(23),
898 | self.ATCA_INFO: const(2),
899 | self.ATCA_LOCK: const(32),
900 | self.ATCA_MAC: const(14),
901 | self.ATCA_NONCE: const(29),
902 | self.ATCA_PAUSE: const(3),
903 | self.ATCA_PRIVWRITE: const(48),
904 | self.ATCA_RANDOM: const(23),
905 | self.ATCA_READ: const(5),
906 | self.ATCA_SHA: const(9),
907 | self.ATCA_SIGN: const(60),
908 | self.ATCA_UPDATE_EXTRA: const(10),
909 | self.ATCA_VERIFY: const(72),
910 | self.ATCA_WRITE: const(26)
911 | }
912 | elif a == "ATECC608A_EXECUTION_TIME":
913 | return {
914 | self.ATCA_AES: const(27),
915 | self.ATCA_CHECKMAC: const(40),
916 | self.ATCA_COUNTER: const(25),
917 | self.ATCA_DERIVE_KEY: const(50),
918 | self.ATCA_ECDH: const(60),
919 | self.ATCA_GENDIG: const(25),
920 | self.ATCA_GENKEY: const(115),
921 | self.ATCA_INFO: const(5),
922 | self.ATCA_KDF: const(165),
923 | self.ATCA_LOCK: const(35),
924 | self.ATCA_MAC: const(55),
925 | self.ATCA_NONCE: const(20),
926 | self.ATCA_PRIVWRITE: const(50),
927 | self.ATCA_RANDOM: const(23),
928 | self.ATCA_READ: const(5),
929 | self.ATCA_SECUREBOOT: const(80),
930 | self.ATCA_SELFTEST: const(250),
931 | self.ATCA_SHA: const(36),
932 | self.ATCA_SIGN: const(115),
933 | self.ATCA_UPDATE_EXTRA: const(10),
934 | self.ATCA_VERIFY: const(105),
935 | self.ATCA_WRITE: const(45)
936 | }
937 | elif a == "EXECUTION_TIME":
938 | return {
939 | "ATECC508A": self.ATECC508A_EXECUTION_TIME,
940 | "ATECC608A": self.ATECC608A_EXECUTION_TIME
941 | }
942 |
943 | sys.modules[__name__] = C()
--------------------------------------------------------------------------------
/modules/cryptoauthlib/device.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import machine
4 | import ubinascii
5 | import utime
6 | import micropython
7 |
8 | import cryptoauthlib.constant as ATCA_CONSTANTS
9 | import cryptoauthlib.exceptions as ATCA_EXCEPTIONS
10 | import cryptoauthlib.status as ATCA_STATUS
11 | from cryptoauthlib.basic import ATECCBasic
12 |
13 |
14 | I2C_ADDRESS = micropython.const(0xC0 >> 1)
15 | BAUDRATE = micropython.const(1000000)
16 | WAKE_DELAY = micropython.const(150)
17 | RX_RETRIES = micropython.const(20)
18 | SUPPORTED_DEVICES = {0x50: "ATECC508A", 0x60: "ATECC608A"}
19 |
20 |
21 | class ATECCX08A(ATECCBasic):
22 | """ ATECCX08A over I2C """
23 |
24 | def __init__(
25 | self,
26 | bus=machine.I2C(1, freq=133000),
27 | address=I2C_ADDRESS, retries=RX_RETRIES):
28 |
29 | if address not in bus.scan():
30 | raise ATCA_EXCEPTIONS.NoDevicesFoundError()
31 |
32 | self._bus = bus
33 | self._address = address
34 | self._retries = retries
35 | try:
36 | self._device = SUPPORTED_DEVICES[self.atcab_info()[1+2]]
37 | except KeyError:
38 | raise ATCA_EXCEPTIONS.UnsupportedDeviceError()
39 |
40 | def __str__(self):
41 | return "<{:s} address=0x{:02x} retries={:d}>".format(
42 | self._device or self.__class__.__name__,
43 | self._address,
44 | self._retries
45 | )
46 |
47 | def __repr__(self):
48 | return str(self)
49 |
50 | @property
51 | def device(self):
52 | return self._device
53 |
54 | def wake(self):
55 | self._bus.writeto(self._address, b'\x00\x00')
56 |
57 | def idle(self):
58 | self._bus.writeto(self._address, b'\x02')
59 |
60 | def sleep(self):
61 | self._bus.writeto(self._address, b'\x01')
62 |
63 | def execute(self, packet):
64 |
65 | retries = self._retries
66 | while retries:
67 | try:
68 | self.wake()
69 | # Wait tWHI + tWLO
70 | utime.sleep_us(WAKE_DELAY)
71 |
72 | # Set device name
73 | if isinstance(self._device, str):
74 | packet.device = self._device
75 |
76 | # Send the command
77 | self._bus.writeto(self._address, b'\x03' + packet.to_buffer())
78 |
79 | resp = packet.response_data_mv
80 |
81 | # Cyclic reading up to the completion of the calculation and in
82 | # any case no later than the tEXEC
83 | d_t = packet.delay
84 | p_t = utime.ticks_ms()
85 | while utime.ticks_diff(utime.ticks_ms(), p_t) <= min(d_t, 250):
86 | try:
87 | self._bus.readfrom_into(self._address, resp[0:1])
88 | self._bus.readfrom_into(self._address, resp[1:resp[0]])
89 | except OSError:
90 | continue
91 | else:
92 | break
93 |
94 | # Check response
95 | err, exc = self.is_error(resp)
96 | if err == ATCA_STATUS.ATCA_SUCCESS:
97 | packet._response_data = resp[:resp[0]]
98 | return
99 | elif err == ATCA_STATUS.ATCA_WAKE_SUCCESS:
100 | return
101 | elif err == ATCA_STATUS.ATCA_WATCHDOG_ABOUT_TO_EXPIRE:
102 | self.sleep()
103 | else:
104 | if exc is not None:
105 | packet._response_data = resp[:resp[0]]
106 | raise exc(ubinascii.hexlify(packet._response_data))
107 | except OSError:
108 | retries -= 1
109 | else:
110 | raise ATCA_EXCEPTIONS.GenericError("max retry")
111 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/exceptions.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | class CryptoError(Exception):
5 | pass
6 |
7 |
8 | class ConfigZoneLockedError(CryptoError):
9 | def __init__(self, *args):
10 | super().__init__("Config Zone Locked", *args)
11 |
12 |
13 | class DataZoneLockedError(CryptoError):
14 | def __init__(self, *args):
15 | super().__init__("Configuration Enabled", *args)
16 |
17 |
18 | class WakeFailedError(CryptoError):
19 | def __init__(self, *args):
20 | super().__init__("Device Wake failed", *args)
21 |
22 |
23 | class CheckmacVerifyFailedError(CryptoError):
24 | def __init__(self, *args):
25 | super().__init__(
26 | "response status byte indicates CheckMac/Verify failure "
27 | "(status byte = 0x01)",
28 | *args
29 | )
30 |
31 |
32 | class ParseError(CryptoError):
33 | def __init__(self, *args):
34 | super().__init__(
35 | "response status byte indicates parsing error "
36 | "(status byte = 0x03)",
37 | *args
38 | )
39 |
40 | class WatchDogAboutToExpireError(CryptoError):
41 | def __init__(self, *args):
42 | super().__init__(
43 | "response status indicate insufficient time to execute the given "
44 | "commmand begore watchdog timer will expire (status byte = 0xEE)",
45 | *args
46 | )
47 |
48 | class CrcError(CryptoError):
49 | def __init__(self, *args):
50 | super().__init__(
51 | "response status byte indicates CRC error (status byte = 0xFF)",
52 | *args
53 | )
54 |
55 |
56 | class StatusUnknownError(CryptoError):
57 | def __init__(self, *args):
58 | super().__init__("Response status byte is unknown", *args)
59 |
60 |
61 | class EccFaultError(CryptoError):
62 | def __init__(self, *args):
63 | super().__init__(
64 | "response status byte is ECC fault (status byte = 0x05)",
65 | *args
66 | )
67 |
68 |
69 | class SelfTestError(CryptoError):
70 | def __init__(self, *args):
71 | super().__init__(
72 | "response status byte is Self Test Error, "
73 | "chip in failure mode (status byte = 0x07)",
74 | *args
75 | )
76 |
77 |
78 | class HealthTestError(CryptoError):
79 | def __init__(self, *args):
80 | super().__init__("random number generator health test error", *args)
81 |
82 |
83 | class FunctionError(CryptoError):
84 | def __init__(self, *args):
85 | super().__init__(
86 | "Function could not execute due to incorrect condition / state.",
87 | *args
88 | )
89 |
90 |
91 | class GenericError(CryptoError):
92 | def __init__(self, *args):
93 | super().__init__("unspecified error", *args)
94 |
95 |
96 | class BadArgumentError(CryptoError):
97 | def __init__(self, *args):
98 | super().__init__(
99 | "bad argument (out of range, null pointer, etc.)",
100 | *args
101 | )
102 |
103 |
104 | class InvalidIdentifierError(CryptoError):
105 | def __init__(self, *args):
106 | super().__init__("invalid device id, id not set", *args)
107 |
108 |
109 | class InvalidSizeError(CryptoError):
110 | def __init__(self, *args):
111 | super().__init__(
112 | "Count value is out of range or greater than buffer size.",
113 | *args
114 | )
115 |
116 |
117 | class BadCrcError(CryptoError):
118 | def __init__(self, *args):
119 | super().__init__("incorrect CRC received", *args)
120 |
121 |
122 | class ReceiveError(CryptoError):
123 | def __init__(self, *args):
124 | super().__init__(
125 | "Timed out while waiting for response. "
126 | "Number of bytes received is > 0.",
127 | *args
128 | )
129 |
130 |
131 | class NoResponseError(CryptoError):
132 | def __init__(self, *args):
133 | super().__init__(
134 | "error while the Command layer is polling for a command response.",
135 | *args
136 | )
137 |
138 |
139 | class ResyncWithWakeupError(CryptoError):
140 | def __init__(self, *args):
141 | super().__init__(
142 | "Re-synchronization succeeded, but only after generating a Wake-up",
143 | *args
144 | )
145 |
146 |
147 | class ParityError(CryptoError):
148 | def __init__(self, *args):
149 | super().__init__("for protocols needing parity", *args)
150 |
151 |
152 | class TransmissionTimeoutError(CryptoError):
153 | def __init__(self, *args):
154 | super().__init__(
155 | "for Microchip PHY protocol, "
156 | "timeout on transmission waiting for master",
157 | *args
158 | )
159 |
160 |
161 | class ReceiveTimeoutError(CryptoError):
162 | def __init__(self, *args):
163 | super().__init__(
164 | "for Microchip PHY protocol, timeout on receipt waiting for master",
165 | *args
166 | )
167 |
168 |
169 | class CommunicationError(CryptoError):
170 | def __init__(self, *args):
171 | super().__init__(
172 | "Communication with device failed. "
173 | "Same as in hardware dependent modules.",
174 | *args
175 | )
176 |
177 |
178 | class TimeOutError(CryptoError):
179 | def __init__(self, *args):
180 | super().__init__(
181 | "Timed out while waiting for response. "
182 | "Number of bytes received is 0.",
183 | *args
184 | )
185 |
186 |
187 | class BadOpcodeError(CryptoError):
188 | def __init__(self, *args):
189 | super().__init__("Opcode is not supported by the device",
190 | *args)
191 |
192 |
193 | class ExecutionError(CryptoError):
194 | def __init__(self, *args):
195 | super().__init__(
196 | "chip was in a state where it could not execute the command, response "
197 | "status byte indicates command execution error (status byte = 0x0F)",
198 | *args
199 | )
200 |
201 |
202 | class UnimplementedError(CryptoError):
203 | def __init__(self, *args):
204 | super().__init__(
205 | "Function or some element of it hasn't been implemented yet",
206 | *args
207 | )
208 |
209 |
210 | class AssertionFailure(CryptoError):
211 | def __init__(self, *args):
212 | super().__init__("Code failed run-time consistency check", *args)
213 |
214 |
215 | class TransmissionError(CryptoError):
216 | def __init__(self, *args):
217 | super().__init__("Failed to write", *args)
218 |
219 |
220 | class ZoneNotLockedError(CryptoError):
221 | def __init__(self, *args):
222 | super().__init__("required zone was not locked", *args)
223 |
224 |
225 | class NoDevicesFoundError(CryptoError):
226 | def __init__(self, *args):
227 | super().__init__(
228 | "For protocols that support device discovery (kit protocol), "
229 | "no devices were found",
230 | *args
231 | )
232 |
233 |
234 | class UnsupportedDeviceError(CryptoError):
235 | def __init__(self, *args):
236 | super().__init__(*args)
237 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/host.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=import-error
3 | import uhashlib
4 |
5 | ###########################################################################
6 | # CryptoAuthLib Host API methods for SHA command #
7 | ###########################################################################
8 |
9 |
10 | def atcah_sha256(message):
11 | return uhashlib.sha256(message).digest()
12 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/packet.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | # pylint: disable=E0602
4 | import micropython
5 | import ustruct
6 | import utime
7 | from ubinascii import hexlify
8 | from cryptoauthlib import constant as ATCA
9 |
10 |
11 | class ATCAPacket(object):
12 | """ ATCAPacket """
13 |
14 | struct_format = ""
44 | ).format(
45 | self.__class__.__name__,
46 | self.txsize,
47 | self.opcode,
48 | self.param1,
49 | self.param2,
50 | hexlify(self.request_data),
51 | hexlify(self.response_data),
52 | self.device
53 | )
54 |
55 | def __repr__(self):
56 | return str(self)
57 |
58 | def __getitem__(self, i):
59 | return self._response_data[i]
60 |
61 | def __getattr__(self, name):
62 | if name == "delay":
63 | return ATCA.EXECUTION_TIME.get(
64 | self.device, "ATECC508A"
65 | ).get(self.opcode, 250)
66 | elif name == "request_length":
67 | return len(self._request_data)
68 | elif name == "request_data":
69 | return self._request_data
70 | elif name == "request_data_mv":
71 | return memoryview(self._request_data)
72 | elif name == "response_length":
73 | return len(self._response_data)
74 | elif name == "response_data":
75 | return self._response_data
76 | elif name == "response_data_mv":
77 | return memoryview(self._response_data)
78 | else:
79 | raise AttributeError(name)
80 |
81 | def to_buffer(self):
82 | params = self.response_data or bytearray(self.txsize)
83 | ustruct.pack_into(
84 | ATCAPacket.struct_format.format(len(self.request_data)),
85 | params,
86 | 0,
87 | self.txsize,
88 | self.opcode,
89 | self.param1,
90 | self.param2,
91 | self.request_data
92 | )
93 | self.at_crc(params, self.txsize-ATCA.ATCA_CRC_SIZE)
94 | return params
95 |
96 | @micropython.viper
97 | def at_crc(self, src: ptr8, length: int) -> int:
98 | polynom = 0x8005
99 | crc = 0
100 | for i in range(length):
101 | d = src[i]
102 | for b in range(8):
103 | data_bit = 1 if d & 1 << b else 0
104 | crc_bit = crc >> 15 & 0xff
105 | crc = crc << 1 & 0xffff
106 | if data_bit != crc_bit:
107 | crc = crc ^ polynom & 0xffff
108 | src[length] = crc & 0x00ff
109 | src[length+1] = crc >> 8 & 0xff
110 | return crc
111 |
112 | # def at_crc(self, src, length):
113 | # polynom = 0x8005
114 | # crc = 0
115 | # for i in range(length):
116 | # d = src[i]
117 | # for b in range(8):
118 | # data_bit = 1 if d & 1 << b else 0
119 | # crc_bit = crc >> 15 & 0xff
120 | # crc = crc << 1 & 0xffff
121 | # if data_bit != crc_bit:
122 | # crc = crc ^ polynom & 0xffff
123 | # src[length] = crc & 0x00ff
124 | # src[length+1] = crc >> 8 & 0xff
125 | # return crc
126 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/status.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import sys
4 | from micropython import const
5 |
6 | from cryptoauthlib import exceptions as ATCA_EXECUTIONS
7 |
8 |
9 | class S(object):
10 |
11 | def __getattr__(self, a):
12 | if a == "ATCA_SUCCESS":
13 | return const(0x00)
14 | elif a == "ATCA_CONFIG_ZONE_LOCKED":
15 | return const(0x01)
16 | elif a == "ATCA_DATA_ZONE_LOCKED":
17 | return const(0x02)
18 | elif a == "ATCA_WAKE_FAILED":
19 | return const(0xD0)
20 | elif a == "ATCA_CHECKMAC_VERIFY_FAILED":
21 | return const(0xD1)
22 | elif a == "ATCA_PARSE_ERROR":
23 | return const(0xD2)
24 | elif a == "ATCA_STATUS_CRC":
25 | return const(0xD4)
26 | elif a == "ATCA_STATUS_UNKNOWN":
27 | return const(0xD5)
28 | elif a == "ATCA_STATUS_ECC":
29 | return const(0xD6)
30 | elif a == "ATCA_STATUS_SELFTEST_ERROR":
31 | return const(0xD7)
32 | elif a == "ATCA_FUNC_FAIL":
33 | return const(0xE0)
34 | elif a == "ATCA_GEN_FAIL":
35 | return const(0xE1)
36 | elif a == "ATCA_BAD_PARAM":
37 | return const(0xE2)
38 | elif a == "ATCA_INVALID_ID":
39 | return const(0xE3)
40 | elif a == "ATCA_INVALID_SIZE":
41 | return const(0xE4)
42 | elif a == "ATCA_RX_CRC_ERROR":
43 | return const(0xE5)
44 | elif a == "ATCA_RX_FAIL":
45 | return const(0xE6)
46 | elif a == "ATCA_RX_NO_RESPONSE":
47 | return const(0xE7)
48 | elif a == "ATCA_RESYNC_WITH_WAKEUP":
49 | return const(0xE8)
50 | elif a == "ATCA_PARITY_ERROR":
51 | return const(0xE9)
52 | elif a == "ATCA_TX_TIMEOUT":
53 | return const(0xEA)
54 | elif a == "ATCA_RX_TIMEOUT":
55 | return const(0xEB)
56 | elif a == "ATCA_TOO_MANY_COMM_RETRIES":
57 | return const(0xEC)
58 | elif a == "ATCA_SMALL_BUFFER":
59 | return const(0xED)
60 | elif a == "ATCA_COMM_FAIL":
61 | return const(0xF0)
62 | elif a == "ATCA_TIMEOUT":
63 | return const(0xF1)
64 | elif a == "ATCA_BAD_OPCODE":
65 | return const(0xF2)
66 | elif a == "ATCA_WAKE_SUCCESS":
67 | return const(0xF3)
68 | elif a == "ATCA_EXECUTION_ERROR":
69 | return const(0xF4)
70 | elif a == "ATCA_UNIMPLEMENTED":
71 | return const(0xF5)
72 | elif a == "ATCA_ASSERT_FAILURE":
73 | return const(0xF6)
74 | elif a == "ATCA_TX_FAIL":
75 | return const(0xF7)
76 | elif a == "ATCA_NOT_LOCKED":
77 | return const(0xF8)
78 | elif a == "ATCA_NO_DEVICES":
79 | return const(0xF9)
80 | elif a == "ATCA_HEALTH_TEST_ERROR":
81 | return const(0xFA)
82 | elif a == "ATCA_ALLOC_FAILURE":
83 | return const(0xFB)
84 | elif a == "ATCA_WATCHDOG_ABOUT_TO_EXPIRE":
85 | return const(0xEE)
86 |
87 | def decode_error(self, error):
88 | return {
89 | 0x00: (self.ATCA_SUCCESS, None),
90 | 0x01: (self.ATCA_CHECKMAC_VERIFY_FAILED, ATCA_EXECUTIONS.CheckmacVerifyFailedError),
91 | 0x03: (self.ATCA_PARSE_ERROR, ATCA_EXECUTIONS.ParseError),
92 | 0x05: (self.ATCA_STATUS_ECC, ATCA_EXECUTIONS.EccFaultError),
93 | 0x07: (self.ATCA_STATUS_SELFTEST_ERROR, ATCA_EXECUTIONS.SelfTestError),
94 | 0x08: (self.ATCA_HEALTH_TEST_ERROR, ATCA_EXECUTIONS.HealthTestError),
95 | 0x0F: (self.ATCA_EXECUTION_ERROR, ATCA_EXECUTIONS.ExecutionError),
96 | 0x11: (self.ATCA_WAKE_SUCCESS, None),
97 | 0xEE: (self.ATCA_WATCHDOG_ABOUT_TO_EXPIRE, ATCA_EXECUTIONS.WatchDogAboutToExpireError),
98 | 0xFF: (self.ATCA_STATUS_CRC, ATCA_EXECUTIONS.CrcError),
99 | }.get(error, (self.ATCA_GEN_FAIL, ATCA_EXECUTIONS.GenericError))
100 |
101 |
102 | sys.modules[__name__] = S()
103 |
--------------------------------------------------------------------------------
/modules/cryptoauthlib/util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import sys
4 | import uctypes
5 | from ubinascii import hexlify
6 |
7 | """
8 | SlotConfig (Bytes 20 to 51)
9 |
10 | 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
11 | -------------------------------------------------
12 | | | | | | | | |
13 | -------------------------------------------------
14 | | | | | | | |
15 | WriteConfig - | | | | | |
16 | WriteKey - | | | | |
17 | IsSecret - | | | |
18 | EncryptRead - | | |
19 | LimitedUse - | |
20 | NoMac - |
21 | ReadKey -
22 |
23 |
24 | ReadKey : 4 = 3-0
25 | NoMac : 1 = 4;
26 | LimitedUse : 1 = 5
27 | EncryptRead : 1 = 6
28 | IsSecret : 1 = 7
29 | WriteKey : 4 = 11-8
30 | WriteConfig : 4 = 15-12
31 | """
32 |
33 | SLOT_CONFIG_STRUCT = {
34 | "ReadKey": uctypes.BFUINT32 | 0 | 0 << uctypes.BF_POS | 4 << uctypes.BF_LEN,
35 | "NoMac": uctypes.BFUINT32 | 0 | 4 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
36 | "LimitedUse": uctypes.BFUINT32 | 0 | 5 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
37 | "EncryptRead": uctypes.BFUINT32 | 0 | 6 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
38 | "IsSecret": uctypes.BFUINT32 | 0 | 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
39 | "WriteKey": uctypes.BFUINT32 | 0 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN,
40 | "WriteConfig": uctypes.BFUINT32 | 0 | 12 << uctypes.BF_POS | 4 << uctypes.BF_LEN
41 | }
42 |
43 |
44 | def dump_slot(slot, index=None, stream=None):
45 | slot_stuct = uctypes.struct(
46 | uctypes.addressof(slot),
47 | SLOT_CONFIG_STRUCT,
48 | uctypes.LITTLE_ENDIAN
49 | )
50 |
51 | if not stream:
52 | stream = sys.stderr
53 |
54 | index_s = "[{:d}]".format(index) if isinstance(index, int) else ""
55 |
56 | stream.write("Slot{:s}({:s}):".format(index_s, hexlify(slot)))
57 | stream.write("ReadKey({:04b})".format(slot_stuct.ReadKey))
58 | stream.write("NoMac({:d})".format(slot_stuct.NoMac))
59 | stream.write("LimitedUse({:d})".format(slot_stuct.LimitedUse))
60 | stream.write("EncryptRead({:d})".format(slot_stuct.EncryptRead))
61 | stream.write("IsSecret({:d})".format(slot_stuct.IsSecret))
62 | stream.write("WriteKey({:04b})".format(slot_stuct.WriteKey))
63 | stream.write("WriteConfig({:04b})\n".format(slot_stuct.WriteConfig))
64 | return stream if stream not in (sys.stderr, sys.stdout) else None
65 |
66 |
67 | """
68 | KeyConfig (Bytes 96 through 127)
69 |
70 | 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
71 | -------------------------------------------------
72 | | | | | | | | | | | |
73 | -------------------------------------------------
74 | | | | | | | | | | |
75 | X509id - | | | | | | | | |
76 | RFU - | | | | | | | |
77 | IntrusionDisable - | | | | | | |
78 | AuthKey - | | | | | |
79 | ReqAuth - | | | | |
80 | ReqRandom - | | | |
81 | Lockable - | | |
82 | KeyType - | |
83 | PubInfo - |
84 | Private -
85 |
86 | Private : 1 = 0
87 | PubInfo : 1 = 1
88 | KeyType : 3 = 4-2
89 | Lockable : 1 = 5
90 | ReqRandom : 1 = 6
91 | ReqAuth : 1 = 7
92 | AuthKey : 4 = 11-8
93 | IntrusionDisable : 1 = 12
94 | RFU : 1 = 13
95 | X509id : 2 = 15-14
96 | """
97 |
98 | KEY_CONFIG_STRUCT = {
99 | "Private": uctypes.BFUINT32 | 0 | 0 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
100 | "PubInfo": uctypes.BFUINT32 | 0 | 1 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
101 | "KeyType": uctypes.BFUINT32 | 0 | 2 << uctypes.BF_POS | 3 << uctypes.BF_LEN,
102 | "Lockable": uctypes.BFUINT32 | 0 | 5 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
103 | "ReqRandom": uctypes.BFUINT32 | 0 | 6 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
104 | "ReqAuth": uctypes.BFUINT32 | 0 | 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
105 | "AuthKey": uctypes.BFUINT32 | 0 | 8 << uctypes.BF_POS | 4 << uctypes.BF_LEN,
106 | "IntrusionDisable": uctypes.BFUINT32 | 0 | 12 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
107 | "RFU": uctypes.BFUINT32 | 0 | 13 << uctypes.BF_POS | 1 << uctypes.BF_LEN,
108 | "X509id": uctypes.BFUINT32 | 0 | 14 << uctypes.BF_POS | 2 << uctypes.BF_LEN
109 | }
110 |
111 |
112 | def dump_key(key, index=None, stream=None):
113 | key_stuct = uctypes.struct(
114 | uctypes.addressof(key),
115 | KEY_CONFIG_STRUCT,
116 | uctypes.LITTLE_ENDIAN
117 | )
118 |
119 | if not stream:
120 | stream = sys.stderr
121 |
122 | index_k = "[{:d}]".format(index) if isinstance(index, int) else ""
123 |
124 | stream.write("Key{:s}({:s}):".format(index_k, hexlify(key)))
125 | stream.write("Private({:d})".format(key_stuct.Private))
126 | stream.write("PubInfo({:d})".format(key_stuct.PubInfo))
127 | stream.write("KeyType({:03b})".format(key_stuct.KeyType))
128 | stream.write("Lockable({:d})".format(key_stuct.Lockable))
129 | stream.write("ReqRandom({:d})".format(key_stuct.ReqRandom))
130 | stream.write("ReqAuth({:d})".format(key_stuct.ReqAuth))
131 | stream.write("AuthKey({:04b})".format(key_stuct.AuthKey))
132 | stream.write("IntrusionDisable({:d})" .format(key_stuct.IntrusionDisable))
133 | stream.write("RFU({:d})".format(key_stuct.RFU))
134 | stream.write("X509id({:02b})\n".format(key_stuct.X509id))
135 | return stream if stream not in (sys.stderr, sys.stdout) else None
136 |
137 |
138 | def dump_configuration(configuration, stream=None):
139 | if not isinstance(configuration, (bytes, bytearray, memoryview)):
140 | raise TypeError()
141 |
142 | if len(configuration) != 128:
143 | raise ValueError("expected: 128 got: {:d}".format(len(configuration)))
144 |
145 | if not stream:
146 | stream = sys.stderr
147 |
148 | c = memoryview(configuration)
149 |
150 | stream.write("SN<0:3>({:s})\n".format(hexlify(c[0:4])))
151 | stream.write("RevNum({:s})\n".format(hexlify(c[4:8])))
152 | stream.write("SN<4:8>({:s})\n".format(hexlify(c[8:13])))
153 | stream.write("AES_Enable({:08b})\n".format(c[13]))
154 | stream.write("I2C_Enable({:08b})\n".format(c[14]))
155 | stream.write("Reserved({:08b})\n".format(c[15]))
156 | stream.write("I2C_Address({:08b})\n".format(c[16]))
157 | stream.write("Reserved({:08b})\n".format(c[17]))
158 | stream.write("CountMatch({:08b})\n".format(c[18]))
159 | stream.write("ChipMode({:08b})\n".format(c[19]))
160 | SlotConfig = c[20:52]
161 | stream.write("SlotConfig:\n")
162 | for idx, slot_buf in enumerate(range(0, 32, 2)):
163 | dump_slot(SlotConfig[slot_buf:slot_buf+2], index=idx, stream=stream)
164 | stream.write("Counter[0]({:s})\n".format(hexlify(c[52:60])))
165 | stream.write("Counter[1]({:s})\n".format(hexlify(c[60:68])))
166 | stream.write("UserLock({:08b})\n".format(c[68]))
167 | stream.write("VolatileKeyPermission({:08b})\n".format(c[69]))
168 | stream.write("SecureBoot({:s})\n".format(hexlify(c[70:72])))
169 | stream.write("KdflvLoc({:08b})\n".format(c[72]))
170 | stream.write("KdflvStr({:s})\n".format(hexlify(c[73:75])))
171 | stream.write("Reserved({:s})\n".format(hexlify(c[75:84])))
172 | stream.write("UserExtra({:08b})\n".format(c[84]))
173 | stream.write("UserExtraAdd({:08b})\n".format(c[85]))
174 | stream.write("LockValue({:08b})\n".format(c[86]))
175 | stream.write("LockConfig({:08b})\n".format(c[87]))
176 | stream.write("SlotLocked({:s})\n".format(hexlify(c[88:90])))
177 | stream.write("ChipOptions({:s})\n".format(hexlify(c[90:92])))
178 | stream.write("X509format({:s})\n".format(hexlify(c[92:96])))
179 | KeyConfig = c[96:128]
180 | stream.write("KeyConfig:\n")
181 | for idx, key_buf in enumerate(range(0, 32, 2)):
182 | dump_key(KeyConfig[key_buf:key_buf+2], index=idx, stream=stream)
183 | return stream if stream not in (sys.stderr, sys.stdout) else None
184 |
--------------------------------------------------------------------------------
/tests/ateccX08a/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E1101
3 | import gc
4 | gc.threshold(4096)
5 | import logging
6 |
7 | from cryptoauthlib.device import ATECCX08A
8 | from ateccX08a import tests_info
9 | from ateccX08a import tests_sha
10 | from ateccX08a import tests_random
11 | from ateccX08a import tests_nonce
12 | from ateccX08a import tests_read
13 | from ateccX08a import tests_write
14 | from ateccX08a import tests_lock
15 | from ateccX08a import tests_verify
16 | from ateccX08a import tests_sign
17 | from ateccX08a import tests_selftest
18 |
19 | log = logging.getLogger("ateccX08a")
20 |
21 |
22 | def test(exclude=[
23 | # 'info',
24 | # 'sha',
25 | # 'random',
26 | # 'nonce',
27 | # 'read',
28 | # 'write',
29 | 'lock',
30 | # 'verify',
31 | # 'sign',
32 | # 'selftest'
33 | ]):
34 | device = ATECCX08A()
35 | log.info("%s", device)
36 |
37 | if 'info' not in exclude:
38 | tests_info.run(device)
39 | log.info("INFO SUCCEDED")
40 | else:
41 | log.info("INFO SKIPPED")
42 |
43 | if 'sha' not in exclude:
44 | tests_sha.run(device)
45 | log.info("SHA SUCCEDED")
46 | else:
47 | log.info("SHA SKIPPED")
48 |
49 | if 'random' not in exclude:
50 | tests_random.run(device)
51 | log.info("RANDOM SUCCEDED")
52 | else:
53 | log.info("RANDOM SKIPPED")
54 |
55 | if 'nonce' not in exclude:
56 | tests_nonce.run(device)
57 | log.info("NONCE SUCCEDED")
58 | else:
59 | log.info("NONCE SKIPPED")
60 |
61 | if 'read' not in exclude:
62 | tests_read.run(device)
63 | log.info("READ SUCCEDED")
64 | else:
65 | log.info("READ SKIPPED")
66 |
67 | if 'write' not in exclude:
68 | tests_write.run(device)
69 | log.info("WRITE SUCCEDED")
70 | else:
71 | log.info("WRITE SKIPPED")
72 |
73 | if 'lock' not in exclude:
74 | tests_lock.run(device)
75 | log.info("LOCK SUCCEDED")
76 | else:
77 | log.info("LOCK SKIPPED")
78 |
79 | if 'verify' not in exclude:
80 | tests_verify.run(device)
81 | log.info("VERIFY SUCCEDED")
82 | else:
83 | log.info("VERIFY SKIPPED")
84 |
85 | if 'sign' not in exclude:
86 | tests_sign.run(device)
87 | log.info("SIGN SUCCEDED")
88 | else:
89 | log.info("SIGN SKIPPED")
90 |
91 | if 'selftest' not in exclude:
92 | tests_selftest.run(device)
93 | log.info("SELFTEST SUCCEDED")
94 | else:
95 | log.info("SELFTEST SKIPPED")
96 |
97 |
98 |
99 | # import logging
100 | # logging.basicConfig(level=logging.DEBUG)
101 |
102 | # import ateccX08a; ateccX08a.test()
103 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_info.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 |
6 | from cryptoauthlib.constant import INFO_MODE_REVISION, INFO_MODE_STATE
7 |
8 | log = logging.getLogger("ateccX08a.tests_info")
9 |
10 |
11 | def run(device=None):
12 | if not device:
13 | raise ValueError("device")
14 |
15 | expected = {
16 | "ATECC508A": b'\x07\x00\x00P\x00\x03\x91',
17 | "ATECC608A": b'\x07\x00\x00`\x02\x808'
18 | }
19 | packet = device.atcab_info()
20 | assert packet.response_data == expected[device.device], hexlify(packet.response_data)
21 | log.debug("atcab_info: %s", hexlify(packet.response_data))
22 |
23 | packet = device.atcab_info_base(INFO_MODE_REVISION)
24 | assert packet.response_data == expected[device.device], hexlify(packet.response_data)
25 | log.debug("atcab_info_base - revision: %s", hexlify(packet.response_data))
26 |
27 | expected = b'\x07\x00\x00\x00\x00\x03\xad'
28 | packet = device.atcab_info_base(INFO_MODE_STATE)
29 | assert expected == packet.response_data, hexlify(packet.response_data)
30 | log.debug("atcab_info_base - state: %s", hexlify(packet.response_data))
31 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_lock.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 |
6 | log = logging.getLogger("ateccX08a.tests_lock")
7 |
8 |
9 | def run(device=None):
10 | if not device:
11 | raise ValueError("device")
12 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_nonce.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 |
6 | from cryptoauthlib.constant import (
7 | NONCE_MODE_SEED_UPDATE,
8 | NONCE_MODE_NO_SEED_UPDATE,
9 | NONCE_MODE_PASSTHROUGH,
10 | NONCE_MODE_TARGET_TEMPKEY,
11 | NONCE_MODE_TARGET_MSGDIGBUF,
12 | NONCE_MODE_TARGET_ALTKEYBUF,
13 | )
14 |
15 | log = logging.getLogger("ateccX08a.tests_nonce")
16 |
17 |
18 | def run(device=None):
19 | if not device:
20 | raise ValueError("device")
21 |
22 | numbers = b'\x00' * 32
23 |
24 | packet = device.atcab_nonce_base(NONCE_MODE_SEED_UPDATE, numbers=numbers)
25 | log.debug("atcab_nonce_base NONCE_MODE_SEED_UPDATE: %s", hexlify(packet.response_data))
26 |
27 | packet = device.atcab_nonce_base(NONCE_MODE_NO_SEED_UPDATE, numbers=numbers)
28 | log.debug("atcab_nonce_base NONCE_MODE_NO_SEED_UPDATE: %s", hexlify(packet.response_data))
29 |
30 | packet = device.atcab_nonce_base(NONCE_MODE_PASSTHROUGH, numbers=numbers)
31 | log.debug("atcab_nonce_base NONCE_MODE_PASSTHROUGH: %s", hexlify(packet.response_data))
32 |
33 | packet = device.atcab_nonce(numbers=numbers)
34 | log.debug("atcab_nonce: %s", hexlify(packet.response_data))
35 |
36 | packet = device.atcab_nonce_load(NONCE_MODE_TARGET_TEMPKEY, numbers=numbers)
37 | log.debug("atcab_nonce_load NONCE_MODE_TARGET_TEMPKEY: %s", hexlify(packet.response_data))
38 |
39 | packet = device.atcab_nonce_load(NONCE_MODE_TARGET_MSGDIGBUF, numbers=numbers)
40 | log.debug("atcab_nonce_load NONCE_MODE_TARGET_MSGDIGBUF: %s", hexlify(packet.response_data))
41 |
42 | packet = device.atcab_nonce_load(NONCE_MODE_TARGET_ALTKEYBUF, numbers=numbers)
43 | log.debug("atcab_nonce_load NONCE_MODE_TARGET_ALTKEYBUF: %s", hexlify(packet.response_data))
44 |
45 | packet = device.atcab_nonce_rand(numbers=numbers)
46 | log.debug("atcab_nonce_rand: %s", hexlify(packet.response_data))
47 |
48 | packet = device.atcab_challenge(numbers=numbers)
49 | log.debug("atcab_challenge: %s", hexlify(packet.response_data))
50 |
51 | packet = device.atcab_challenge_seed_update(numbers=numbers)
52 | log.debug("atcab_challenge_seed_update: %s", hexlify(packet.response_data))
53 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_random.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 |
6 |
7 | log = logging.getLogger("ateccX08a.tests_random")
8 |
9 |
10 | def run(device=None):
11 | if not device:
12 | raise ValueError("device")
13 |
14 | packet = device.atcab_random()
15 | log.debug("atcab_random: %s", hexlify(packet.response_data))
16 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_read.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 | from uio import BytesIO, StringIO
6 |
7 | from cryptoauthlib import constant as ATCA_CONSTANTS
8 | from cryptoauthlib import util as ATEC_UTIL
9 | from cryptoauthlib import exceptions as ATCA_EXCEPTIONS
10 |
11 | log = logging.getLogger("ateccX08a.tests_read")
12 |
13 | def run(device=None):
14 | if not device:
15 | raise ValueError("device")
16 |
17 | packet = device.atcab_read_serial_number()
18 | sn0_1, sn8 = packet.response_data[1:1+2], packet.response_data[9+4:9+4+1]
19 | assert b'\x01#' == sn0_1, hexlify(sn0_1)
20 | assert b'\xee' == sn8, hexlify(sn8)
21 | log.debug("atcab_read_serial_number: %s", hexlify(packet.response_data))
22 |
23 | packets = device.atcab_read_config_zone()
24 | config = b''.join([bytes(packet.response_data[1:-2])
25 | for packet in packets])
26 | log.debug("atcab_read_config_zone %d: %s", len(config), hexlify(config))
27 | # ATEC_UTIL.dump_configuration(config)
28 |
29 | for slot in range(16):
30 | slot_locked = device.atcab_is_slot_locked(slot)
31 | log.debug("atcab_is_slot_locked %d: %s", slot, slot_locked)
32 |
33 | locked_config = device.atcab_is_locked(ATCA_CONSTANTS.LOCK_ZONE_CONFIG)
34 | log.debug("atcab_is_locked LOCK_ZONE_CONFIG: %r", locked_config)
35 |
36 | locked_data = device.atcab_is_locked(ATCA_CONSTANTS.LOCK_ZONE_DATA)
37 | log.debug("atcab_is_locked LOCK_ZONE_DATA: %r", locked_data)
38 |
39 | try:
40 | slot = 11
41 | public_key = device.atcab_read_pubkey(slot)
42 | log.debug("atcab_read_pubkey slot %d: %s", slot, hexlify(public_key))
43 | except ATCA_EXCEPTIONS.ExecutionError:
44 | pass
45 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_selftest.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 |
5 | from cryptoauthlib import constant as ATCA_CONSTANTS
6 |
7 | log = logging.getLogger("ateccX08a.tests_selftest")
8 |
9 |
10 | def run(device=None):
11 | if not device:
12 | raise ValueError("device")
13 |
14 | tests = (
15 | (ATCA_CONSTANTS.SELFTEST_MODE_RNG, "RNG"),
16 | (ATCA_CONSTANTS.SELFTEST_MODE_ECDSA_SIGN_VERIFY, "ECDSA_SIGN_VERIFY"),
17 | (ATCA_CONSTANTS.SELFTEST_MODE_ECDH, "ECDH"),
18 | (ATCA_CONSTANTS.SELFTEST_MODE_AES, "AES"),
19 | (ATCA_CONSTANTS.SELFTEST_MODE_SHA, "SHA"),
20 | (ATCA_CONSTANTS.SELFTEST_MODE_ALL, "ALL")
21 | )
22 | for mode, mode_str in tests:
23 | status = device.atcab_selftest(mode)
24 | assert status
25 | log.debug("atcab_selftest %s: %s", mode_str, status)
26 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_sha.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 |
6 | from cryptoauthlib.constant import (
7 | SHA_MODE_SHA256_START,
8 | SHA_MODE_SHA256_UPDATE,
9 | SHA_MODE_SHA256_END,
10 | ATCA_SHA256_BLOCK_SIZE
11 | )
12 |
13 | log = logging.getLogger("ateccX08a.tests_sha")
14 |
15 |
16 | def run(device=None):
17 | if not device:
18 | raise ValueError("device")
19 |
20 | expected = b"\x1a:\xa5E\x04\x94S\xaf\xdf\x17\xe9\x89\xa4\x1f\xa0\x97\x94\xa5\x1b\xd5\xdb\x9167gU\x0c\x0f\n\xf3'\xd4"
21 | message = b'\xBC' * ATCA_SHA256_BLOCK_SIZE
22 | packet = device.atcab_sha(message)
23 | assert expected in bytes(packet.response_data), hexlify(packet.response_data)
24 | log.debug("atcab_sha: %s", hexlify(packet.response_data))
25 |
26 | expected = b'p~\x97\xe6\xf8d]\xf5\xd8\x068.g\x01\xc8\xe2\xe2\x16`\x17\xf6\nV\xe6\xaa\xc0\xc2\xd2\xdb\xbb"\x81'
27 | message = b'\x5A' * ATCA_SHA256_BLOCK_SIZE
28 | packet = device.atcab_sha_base(SHA_MODE_SHA256_START)
29 | packet = device.atcab_sha_base(SHA_MODE_SHA256_UPDATE, message)
30 | packet = device.atcab_sha_base(SHA_MODE_SHA256_UPDATE, message)
31 | packet = device.atcab_sha_base(SHA_MODE_SHA256_UPDATE, message)
32 | packet = device.atcab_sha_base(SHA_MODE_SHA256_END)
33 | assert expected in bytes(packet.response_data), hexlify(packet.response_data)
34 | log.debug("atcab_sha_base: %s", hexlify(packet.response_data))
35 |
36 | # test HW SHA with a long message > SHA block size and not an exact SHA block-size increment
37 | expected = b'\xa9"\x18VCp\xa0W\'?\xf4\x85\xa8\x07?2\xfc\x1f\x14\x12\xec\xa2\xe3\x0b\x81\xa8\x87v\x0ba1r'
38 | message = b'\xBC' * (ATCA_SHA256_BLOCK_SIZE + 63)
39 | packet = device.atcab_sha(message)
40 | assert expected in bytes(packet.response_data), hexlify(packet.response_data)
41 | log.debug("atcab_sha %d: %s", len(message), hexlify(packet.response_data))
42 |
43 | # test HW SHA with a short message < SHA block size and not an exact SHA block-size increment
44 | expected = b'0?\xf8\xba@\xa2\x06\xe7\xa9P\x02\x1e\xf5\x10f\xd4\xa0\x01Tu2>\xe9\xf2J\xc8\xc9c)\x8f4\xce'
45 | message = b'\xBC' * 10
46 | packet = device.atcab_sha(message)
47 | assert expected in bytes(packet.response_data), hexlify(packet.response_data)
48 | log.debug("atcab_sha %d: %s", len(message), hexlify(packet.response_data))
49 |
50 | # test NIST HW SHA
51 | expected = b'\xbax\x16\xbf\x8f\x01\xcf\xeaAA@\xde]\xae"#\xb0\x03a\xa3\x96\x17z\x9c\xb4\x10\xffa\xf2\x00\x15\xad'
52 | message = "abc"
53 | packet = device.atcab_sha(message)
54 | assert expected in bytes(packet.response_data), hexlify(packet.response_data)
55 | log.debug("atcab_sha nist 1: %s", hexlify(packet.response_data))
56 |
57 | expected = b'$\x8dja\xd2\x068\xb8\xe5\xc0&\x93\x0c>`9\xa3<\xe4Yd\xff!g\xf6\xec\xed\xd4\x19\xdb\x06\xc1'
58 | message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
59 | packet = device.atcab_sha(message)
60 | assert expected in bytes(packet.response_data), hexlify(packet.response_data)
61 | log.debug("atcab_sha nist 2: %s", hexlify(packet.response_data))
62 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_sign.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify
5 |
6 | log = logging.getLogger("ateccX08a.tests_sign")
7 |
8 | _MESSAGE = b'a message to sign via ECDSA '
9 |
10 | def run(device=None):
11 | if not device:
12 | raise ValueError("device")
13 |
14 | slot = 2
15 | public_key_gen = device.atcab_genkey(slot)[1:-2]
16 | log.debug("atcab_genkey %r", hexlify(public_key_gen))
17 | public_key = device.atcab_get_pubkey(slot)[1:-2]
18 | assert bytes(public_key_gen) == public_key
19 | log.debug("atcab_get_pubkey %r", hexlify(public_key))
20 | digest = device.atcab_sha(_MESSAGE)[1:-2]
21 | log.debug("atcab_sha %r %r", _MESSAGE, hexlify(digest))
22 | signature = device.atcab_sign(slot, digest)[1:-2]
23 | log.debug("atcab_sign %r", hexlify(signature))
24 | verified = device.atcab_verify_extern(digest, signature, public_key)
25 | log.debug("atcab_verify_extern %r", verified)
26 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_verify.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 | from ubinascii import hexlify, unhexlify
5 |
6 | from cryptoauthlib import constant as ATCA_CONSTANTS
7 |
8 | log = logging.getLogger("ateccX08a.tests_verify")
9 |
10 | _TEST_KEYS = {
11 | "PRIVATE": bytes([
12 | 0XF3, 0XFC, 0XCC, 0X0D, 0X00, 0XD8, 0X03, 0X19, 0X54, 0XF9, 0X08, 0X64, 0XD4, 0X3C, 0X24, 0X7F,
13 | 0X4B, 0XF5, 0XF0, 0X66, 0X5C, 0X6B, 0X50, 0XCC, 0X17, 0X74, 0X9A, 0X27, 0XD1, 0XCF, 0X76, 0X64
14 | ]),
15 | "PUBLIC": bytes([
16 | 0X8D, 0X61, 0X7E, 0X65, 0XC9, 0X50, 0X8E, 0X64, 0XBC, 0XC5, 0X67, 0X3A, 0XC8, 0X2A, 0X67, 0X99,
17 | 0XDA, 0X3C, 0X14, 0X46, 0X68, 0X2C, 0X25, 0X8C, 0X46, 0X3F, 0XFF, 0XDF, 0X58, 0XDF, 0XD2, 0XFA,
18 | 0X3E, 0X6C, 0X37, 0X8B, 0X53, 0XD7, 0X95, 0XC4, 0XA4, 0XDF, 0XFB, 0X41, 0X99, 0XED, 0XD7, 0X86,
19 | 0X2F, 0X23, 0XAB, 0XAF, 0X02, 0X03, 0XB4, 0XB8, 0X91, 0X1B, 0XA0, 0X56, 0X99, 0X94, 0XE1, 0X01
20 | ]),
21 | "MESSAGE": b'a message to sign via ECDSA ',
22 | "SIGNATURE": {
23 | "R": bytes([
24 | 0X71, 0X07, 0X7D, 0X35, 0X6F, 0XCD, 0X70, 0XD4, 0XCC, 0X47, 0X2A, 0XD0, 0X49, 0X0E, 0X75, 0XAB,
25 | 0XC5, 0X41, 0X98, 0XEE, 0X6A, 0X96, 0X7B, 0X90, 0XF2, 0XC7, 0XE3, 0XC8, 0X2B, 0XBF, 0X54, 0X96
26 | ]),
27 | "S": bytes([
28 | 0X77, 0X8E, 0XFE, 0X0B, 0XF6, 0X9D, 0X15, 0XED, 0XA0, 0X71, 0XBD, 0XD3, 0XFE, 0X46, 0X99, 0X26,
29 | 0X31, 0XF8, 0X80, 0X01, 0X13, 0X76, 0XCD, 0X45, 0X7C, 0X62, 0X55, 0X43, 0XC9, 0X7F, 0XCC, 0XD9
30 | ])
31 | }
32 | }
33 |
34 |
35 | def run(device=None, configuration=None):
36 | if not device:
37 | raise ValueError("device")
38 |
39 | public_key = _TEST_KEYS["PUBLIC"]
40 | message = _TEST_KEYS["MESSAGE"]
41 | digest = device.atcab_sha(message)[1:-2]
42 | signature = _TEST_KEYS["SIGNATURE"]["R"] + _TEST_KEYS["SIGNATURE"]["S"]
43 | # # verify the signature extern
44 | verified = device.atcab_verify_extern(digest, signature, public_key)
45 | log.debug("atcab_verify_extern %r", verified)
46 |
47 | # # verify the signature stored
48 | # slot = 11
49 | # device.atcab_nonce_load(ATCA_CONSTANTS.NONCE_MODE_TARGET_TEMPKEY, digest)
50 | # verified = device.atcab_verify_stored(message, signature, slot)
51 | # log.debug("atcab_verify_stored %r", verified)
52 |
--------------------------------------------------------------------------------
/tests/ateccX08a/tests_write.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # pylint: disable=E0401
3 | import logging
4 |
5 | from ubinascii import hexlify
6 |
7 | from cryptoauthlib import util as ATEC_UTIL
8 | from cryptoauthlib import constant as ATCA_CONSTANTS
9 | from cryptoauthlib import exceptions as ATCA_EXCEPTIONS
10 | from cryptoauthlib import status as ATCA_STATUS
11 |
12 | log = logging.getLogger("ateccX08a.tests_write")
13 |
14 |
15 | _TEST_CONFIG = {
16 | "ATECC508A": bytes([
17 | 0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x00, 0x01, 0x00,
18 | 0xC0, 0x00, 0x55, 0x00, 0x8F, 0x2F, 0xC4, 0x44, 0x87, 0x20, 0xC4, 0xF4, 0x8F, 0x0F, 0x8F, 0x8F,
19 | 0x9F, 0x8F, 0x83, 0x64, 0xC4, 0x44, 0xC4, 0x64, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
20 | 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
21 | 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
22 | 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 | 0x33, 0x00, 0x1C, 0x00, 0x13, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x33, 0x00,
24 | 0x1C, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x30, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x32, 0x00, 0x30, 0x00
25 | ]),
26 | "ATECC608A": bytes([
27 | 0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x01, 0x01, 0x00,
28 | 0xC0, 0x00, 0xA1, 0x00, 0xAF, 0x2F, 0xC4, 0x44, 0x87, 0x20, 0xC4, 0xF4, 0x8F, 0x0F, 0x0F, 0x0F,
29 | 0x9F, 0x8F, 0x83, 0x64, 0xC4, 0x44, 0xC4, 0x64, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
30 | 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
31 | 0x00, 0x00, 0x00, 0x00, 0xFF, 0x84, 0x03, 0xBC, 0x09, 0x69, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00,
32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0E, 0x40, 0x00, 0x00, 0x00, 0x00,
33 | 0x33, 0x00, 0x1C, 0x00, 0x13, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x33, 0x00,
34 | 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x10, 0x30, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x32, 0x00, 0x30, 0x00
35 | ])
36 | }
37 |
38 | _TEST_KEYS = {
39 | "PRIVATE": bytes([
40 | 0XF3, 0XFC, 0XCC, 0X0D, 0X00, 0XD8, 0X03, 0X19, 0X54, 0XF9, 0X08, 0X64, 0XD4, 0X3C, 0X24, 0X7F,
41 | 0X4B, 0XF5, 0XF0, 0X66, 0X5C, 0X6B, 0X50, 0XCC, 0X17, 0X74, 0X9A, 0X27, 0XD1, 0XCF, 0X76, 0X64
42 | ]),
43 | "PUBLIC": bytes([
44 | 0X8D, 0X61, 0X7E, 0X65, 0XC9, 0X50, 0X8E, 0X64, 0XBC, 0XC5, 0X67, 0X3A, 0XC8, 0X2A, 0X67, 0X99,
45 | 0XDA, 0X3C, 0X14, 0X46, 0X68, 0X2C, 0X25, 0X8C, 0X46, 0X3F, 0XFF, 0XDF, 0X58, 0XDF, 0XD2, 0XFA,
46 | 0X3E, 0X6C, 0X37, 0X8B, 0X53, 0XD7, 0X95, 0XC4, 0XA4, 0XDF, 0XFB, 0X41, 0X99, 0XED, 0XD7, 0X86,
47 | 0X2F, 0X23, 0XAB, 0XAF, 0X02, 0X03, 0XB4, 0XB8, 0X91, 0X1B, 0XA0, 0X56, 0X99, 0X94, 0XE1, 0X01
48 | ]),
49 | "MESSAGE": b'a message to sign via ECDSA ',
50 | "SIGNATURE": {
51 | "R": bytes([
52 | 0X71, 0X07, 0X7D, 0X35, 0X6F, 0XCD, 0X70, 0XD4, 0XCC, 0X47, 0X2A, 0XD0, 0X49, 0X0E, 0X75, 0XAB,
53 | 0XC5, 0X41, 0X98, 0XEE, 0X6A, 0X96, 0X7B, 0X90, 0XF2, 0XC7, 0XE3, 0XC8, 0X2B, 0XBF, 0X54, 0X96
54 | ]),
55 | "S": bytes([
56 | 0X77, 0X8E, 0XFE, 0X0B, 0XF6, 0X9D, 0X15, 0XED, 0XA0, 0X71, 0XBD, 0XD3, 0XFE, 0X46, 0X99, 0X26,
57 | 0X31, 0XF8, 0X80, 0X01, 0X13, 0X76, 0XCD, 0X45, 0X7C, 0X62, 0X55, 0X43, 0XC9, 0X7F, 0XCC, 0XD9
58 | ])
59 | }
60 | }
61 |
62 |
63 | def run(device=None):
64 | if not device:
65 | raise ValueError("device")
66 |
67 | config = _TEST_CONFIG[device.device]
68 |
69 | log.debug("test_config for %s : %s", device.device, hexlify(config))
70 | # ATEC_UTIL.dump_configuration(config)
71 |
72 | if not device.atcab_is_locked(ATCA_CONSTANTS.LOCK_ZONE_CONFIG):
73 | device.atcab_write_config_zone(config)
74 | device.atcab_lock_config_zone()
75 | else:
76 | log.debug("configuration zone locked")
77 |
78 | if not device.atcab_is_locked(ATCA_CONSTANTS.LOCK_ZONE_DATA):
79 | device.atcab_lock_data_zone()
80 | else:
81 | log.debug("data zone locked")
82 |
83 | slot = 11
84 | if not device.atcab_is_slot_locked(slot):
85 | public_key = _TEST_KEYS["PUBLIC"]
86 | # # write public_key to slot
87 | device.atcab_write_pubkey(slot, public_key)
88 | # # verify wrote public_key
89 | assert public_key == device.atcab_read_pubkey(slot)
90 | else:
91 | log.debug("slot %d locked", slot)
92 |
--------------------------------------------------------------------------------