├── .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 | PYBOARD plus ATECCX08A 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 | ![API Implemented](https://progress-bar.dev/61) 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 | --------------------------------------------------------------------------------