Compare commits

...

22 commits

Author SHA1 Message Date
dherrada
af063a6887 Fixed discord invite link 2020-07-08 16:49:04 -04:00
Scott Shawcroft
3bf1545518
Merge pull request #15 from adafruit/black-update
Black reformatting with Python 3 target.
2020-04-08 10:09:01 -07:00
Kattni Rembor
93c032c3b1 Black reformatting with Python 3 target. 2020-04-08 13:04:41 -04:00
sommersoft
edc2c37687 build.yml: add black formatting check
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-04-07 16:11:38 -05:00
Brent Rubell
e801f98d0c
Merge pull request #12 from fgallaire/master
Fix #11
2020-03-31 14:28:53 -04:00
Kattni
0e0e468176
Merge pull request #13 from adafruit/pylint-update
Ran black, updated to pylint 2.x
2020-03-16 16:33:58 -04:00
sommersoft
3cacf8d74b update code of coduct: discord moderation contact section
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-03-15 18:31:12 -05:00
sommersoft
54b0e94190
Merge pull request #14 from sommersoft/patch_coc
Update Code of Conduct
2020-03-13 14:57:02 -05:00
sommersoft
8a83f3bccb update code of conduct 2020-03-13 13:58:50 -05:00
dherrada
f3c9bd653a Ran black, updated to pylint 2.x 2020-03-12 19:08:27 -04:00
sommersoft
95e8df6c4a update pylintrc for black
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-03-08 19:12:05 -05:00
sommersoft
23271886c1 build.yml: move pylint, black, and Sphinx installs to each repo; add description to 'actions-ci/install.sh'
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-03-05 10:11:30 -06:00
Florent Gallaire
19262c98ed Fix #11 2020-03-03 18:38:27 +01:00
Brent Rubell
cdfca6c79f
Merge pull request #10 from fgallaire/master
Add binascii lib in setup.py and fix setup
2020-03-03 10:07:14 -05:00
Florent Gallaire
57c3250337 Fix setup 2020-02-28 03:42:44 +01:00
Florent Gallaire
83bb6d559b Add binascii lib in setup.py 2020-02-28 03:34:23 +01:00
Brent Rubell
dd04479730
Merge pull request #9 from fgallaire/master
Add binascii lib in requirements
2020-02-27 09:07:11 -05:00
Florent Gallaire
bf6dca3ba9 Add binascii lib in requirements 2020-02-27 15:01:36 +01:00
sommersoft
aa75e0a1d3 update pylint examples directive
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-01-14 17:07:38 -06:00
Limor "Ladyada" Fried
41390ceb2f
Merge pull request #8 from adafruit/dherrada-patch-1
Updated build.yml and release.yml
2019-12-27 23:34:13 -05:00
dherrada
f7c30ed9af Moved repository from Travis to GitHub Actions 2019-12-27 22:23:40 -05:00
siddacious
eb395e5127
Merge pull request #6 from adafruit/siddacious-patch-1
Update setup.py to fix pypi deploy
2019-10-28 13:55:51 -07:00
13 changed files with 237 additions and 171 deletions

View file

@ -25,21 +25,31 @@ jobs:
- name: Versions
run: |
python3 --version
- uses: actions/checkout@v1
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Install deps
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install dependencies
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
run: |
sudo apt-get install -y gettext
pip install -r requirements.txt
pip install circuitpython-build-tools Sphinx sphinx-rtd-theme
pip install --force-reinstall pylint==1.9.2
source actions-ci/install.sh
- name: Pip install pylint, black, & Sphinx
run: |
pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
- name: Library version
run: git describe --dirty --always --tags
- name: Check formatting
run: |
black --check --target-version=py35 .
- name: PyLint
run: |
pylint $( find . -path './adafruit*.py' )
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py)
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" ))
- name: Build assets
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Build docs

View file

@ -27,14 +27,18 @@ jobs:
- name: Versions
run: |
python3 --version
- uses: actions/checkout@v1
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install deps
run: |
sudo apt-get install -y gettext
pip install -r requirements.txt
pip install circuitpython-build-tools Sphinx sphinx-rtd-theme
source actions-ci/install.sh
- name: Build assets
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Upload Release Assets
@ -53,15 +57,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Check For setup.py
id: need-pypi
run: |
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Set up Python
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
env:
TWINE_USERNAME: ${{ secrets.pypi_username }}
TWINE_PASSWORD: ${{ secrets.pypi_password }}

View file

@ -52,7 +52,7 @@ confidence=
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option

View file

@ -34,6 +34,8 @@ Examples of unacceptable behavior by participants include:
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Promoting or spreading disinformation, lies, or conspiracy theories against
a person, group, organisation, project, or community
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
@ -41,7 +43,7 @@ Examples of unacceptable behavior by participants include:
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you dont just aim to be
"technically unimpeachable", but rather try to be your best self.
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
supporting others within our community. Providing a positive experience for
@ -72,10 +74,10 @@ You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Helpers by tagging @community moderators. You may also send an
open message from any channel, or a direct message to @kattni#1507,
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@Andon#8175.
to all Community Moderators by tagging @community moderators. You may
also send an open message from any channel, or a direct message to
@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442,
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
Email and direct message reports will be kept confidential.

View file

@ -6,7 +6,7 @@ Introduction
:alt: Documentation Status
.. image:: https://img.shields.io/discord/327254708534116352.svg
:target: https://discord.gg/nBQh6qu
:target: https://adafru.it/discord
:alt: Discord
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_ATECC/workflows/Build%20CI/badge.svg

View file

@ -77,8 +77,8 @@ _ATECC_508_VER = const(0x50)
_ATECC_608_VER = const(0x60)
# Clock constants
_WAKE_CLK_FREQ = 100000 # slower clock speed
_TWLO_TIME = 6e-5 # TWlo, in microseconds
_WAKE_CLK_FREQ = 100000 # slower clock speed
_TWLO_TIME = 6e-5 # TWlo, in microseconds
# Command Opcodes (9-1-3)
OP_COUNTER = const(0x24)
@ -92,30 +92,34 @@ OP_SIGN = const(0x41)
OP_WRITE = const(0x12)
# Maximum execution times, in milliseconds (9-4)
EXEC_TIME = {OP_COUNTER: const(20),
OP_INFO: const(1),
OP_NONCE: const(7),
OP_RANDOM: const(23),
OP_SHA: const(47),
OP_LOCK: const(32),
OP_GEN_KEY: const(115),
OP_SIGN : const(70),
OP_WRITE : const(26)}
EXEC_TIME = {
OP_COUNTER: const(20),
OP_INFO: const(1),
OP_NONCE: const(7),
OP_RANDOM: const(23),
OP_SHA: const(47),
OP_LOCK: const(32),
OP_GEN_KEY: const(115),
OP_SIGN: const(70),
OP_WRITE: const(26),
}
CFG_TLS = b'\x01#\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\xc0q\x00 \
CFG_TLS = b"\x01#\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\xc0q\x00 \
\xc0\x00U\x00\x83 \x87 \x87 \x87/\x87/\x8f\x8f\x9f\x8f\xaf \
\x8f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \
\xaf\x8f\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff\x00 \
\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff \
\xff\xff\xff\xff\x00\x00UU\xff\xff\x00\x00\x00\x00\x00\x003 \
\x003\x003\x003\x003\x00\x1c\x00\x1c\x00\x1c\x00<\x00<\x00<\x00< \
\x00<\x00<\x00<\x00\x1c\x00'
\x00<\x00<\x00<\x00\x1c\x00"
class ATECC:
"""
CircuitPython interface for ATECCx08A Crypto Co-Processor Devices.
"""
def __init__(self, i2c_bus, address=_REG_ATECC_DEVICE_ADDR, debug=False):
"""Initializes an ATECC device.
:param busio i2c_bus: I2C Bus object.
@ -132,7 +136,9 @@ class ATECC:
self._i2c_device = I2CDevice(self._i2c_bus, address)
self.idle()
if (self.version() >> 8) not in (_ATECC_508_VER, _ATECC_608_VER):
raise RuntimeError("Failed to find 608 or 508 chip. Please check your wiring.")
raise RuntimeError(
"Failed to find 608 or 508 chip. Please check your wiring."
)
def wakeup(self):
"""Wakes up THE ATECC608A from sleep or idle modes.
@ -148,13 +154,13 @@ class ATECC:
try:
self._i2c_bus.writeto(0x0, zero_bits)
except OSError:
pass # this may fail, that's ok - its just to wake up the chip!
pass # this may fail, that's ok - its just to wake up the chip!
time.sleep(_TWLO_TIME)
data = self._i2c_bus.scan() # check for an i2c device
data = self._i2c_bus.scan() # check for an i2c device
try:
if data[0] != 96:
raise TypeError('ATECCx08 not found - please check your wiring!')
raise TypeError("ATECCx08 not found - please check your wiring!")
except IndexError:
raise IndexError("ATECCx08 not found - please check your wiring!")
self._i2c_bus.unlock()
@ -211,8 +217,8 @@ class ATECC:
serial_num[8] = temp_sn[0]
time.sleep(0.001)
# neaten up the serial for printing
serial_num = hexlify(serial_num).decode("utf-8")
serial_num = str(serial_num).upper()
serial_num = str(hexlify(serial_num), "utf-8")
serial_num = serial_num.upper()
return serial_num
def version(self):
@ -228,20 +234,18 @@ class ATECC:
self.lock(0)
self.lock(1)
def lock(self, zone):
"""Locks specific ATECC zones.
:param int zone: ATECC zone to lock.
"""
self.wakeup()
self._send_command(0x17, 0x80 | zone, 0x0000)
time.sleep(EXEC_TIME[OP_LOCK]/1000)
time.sleep(EXEC_TIME[OP_LOCK] / 1000)
res = bytearray(1)
self._get_response(res)
assert res[0] == 0x00, "Failed locking ATECC!"
self.idle()
def info(self, mode, param=None):
"""Returns device state information
:param int mode: Mode encoding, see Table 9-26.
@ -252,7 +256,7 @@ class ATECC:
self._send_command(OP_INFO, mode)
else:
self._send_command(OP_INFO, mode, param)
time.sleep(EXEC_TIME[OP_INFO]/1000)
time.sleep(EXEC_TIME[OP_INFO] / 1000)
info_out = bytearray(4)
self._get_response(info_out)
self.idle()
@ -281,15 +285,16 @@ class ATECC:
calculated_nonce = bytearray(1)
else:
raise RuntimeError("Invalid mode specified!")
time.sleep(EXEC_TIME[OP_NONCE]/1000)
time.sleep(EXEC_TIME[OP_NONCE] / 1000)
self._get_response(calculated_nonce)
time.sleep(1/1000)
time.sleep(1 / 1000)
if mode == 0x03:
assert calculated_nonce[0] == 0x00, "Incorrectly calculated nonce in pass-thru mode"
assert (
calculated_nonce[0] == 0x00
), "Incorrectly calculated nonce in pass-thru mode"
self.idle()
return calculated_nonce
def counter(self, counter=0, increment_counter=True):
"""Reads the binary count value from one of the two monotonic
counters located on the device within the configuration zone.
@ -306,7 +311,7 @@ class ATECC:
self._send_command(OP_COUNTER, 0x01, counter)
else:
self._send_command(OP_COUNTER, 0x00, counter)
time.sleep(EXEC_TIME[OP_COUNTER]/1000)
time.sleep(EXEC_TIME[OP_COUNTER] / 1000)
count = bytearray(4)
self._get_response(count)
self.idle()
@ -342,7 +347,7 @@ class ATECC:
data_len = len(data)
while data_len:
self._send_command(OP_RANDOM, 0x00, 0x0000)
time.sleep(EXEC_TIME[OP_RANDOM]/1000)
time.sleep(EXEC_TIME[OP_RANDOM] / 1000)
resp = bytearray(32)
self._get_response(resp)
copy_len = min(32, data_len)
@ -359,7 +364,7 @@ class ATECC:
"""
self.wakeup()
self._send_command(OP_SHA, 0x00)
time.sleep(EXEC_TIME[OP_SHA]/1000)
time.sleep(EXEC_TIME[OP_SHA] / 1000)
status = bytearray(1)
self._get_response(status)
assert status[0] == 0x00, "Error during sha_start."
@ -374,14 +379,13 @@ class ATECC:
"""
self.wakeup()
self._send_command(OP_SHA, 0x01, 64, message)
time.sleep(EXEC_TIME[OP_SHA]/1000)
time.sleep(EXEC_TIME[OP_SHA] / 1000)
status = bytearray(1)
self._get_response(status)
assert status[0] == 0x00, "Error during SHA Update"
self.idle()
return status
def sha_digest(self, message=None):
"""Returns the digest of the data passed to the
sha_update method so far.
@ -397,14 +401,13 @@ class ATECC:
self._send_command(OP_SHA, 0x02, len(message), message)
else:
self._send_command(OP_SHA, 0x02)
time.sleep(EXEC_TIME[OP_SHA]/1000)
time.sleep(EXEC_TIME[OP_SHA] / 1000)
digest = bytearray(32)
self._get_response(digest)
assert len(digest) == 32, "SHA response length does not match expected length."
self.idle()
return digest
def gen_key(self, key, slot_num, private_key=False):
"""Generates a private or public key.
:param int slot_num: ECC slot (from 0 to 4).
@ -417,7 +420,7 @@ class ATECC:
self._send_command(OP_GEN_KEY, 0x04, slot_num)
else:
self._send_command(OP_GEN_KEY, 0x00, slot_num)
time.sleep(EXEC_TIME[OP_GEN_KEY]/1000)
time.sleep(EXEC_TIME[OP_GEN_KEY] / 1000)
self._get_response(key)
time.sleep(0.001)
self.idle()
@ -442,7 +445,7 @@ class ATECC:
"""
self.wakeup()
self._send_command(0x41, 0x80, slot_id)
time.sleep(EXEC_TIME[OP_SIGN]/1000)
time.sleep(EXEC_TIME[OP_SIGN] / 1000)
signature = bytearray(64)
self._get_response(signature)
self.idle()
@ -457,7 +460,7 @@ class ATECC:
if i == 84:
# can't write
continue
self._write(0, i//4, data[i:i+4])
self._write(0, i // 4, data[i : i + 4])
def _write(self, zone, address, buffer):
self.wakeup()
@ -466,7 +469,7 @@ class ATECC:
if len(buffer) == 32:
zone |= 0x80
self._send_command(0x12, zone, address, buffer)
time.sleep(26/1000)
time.sleep(26 / 1000)
status = bytearray(1)
self._get_response(status)
self.idle()
@ -483,7 +486,7 @@ class ATECC:
time.sleep(0.001)
self.idle()
def _send_command(self, opcode, param_1, param_2=0x00, data=''):
def _send_command(self, opcode, param_1, param_2=0x00, data=""):
"""Sends a security command packet over i2c.
:param byte opcode: The command Opcode
:param byte param_1: The first parameter
@ -491,18 +494,18 @@ class ATECC:
:param byte param_3 data: Optional remaining input data.
"""
# assembling command packet
command_packet = bytearray(8+len(data))
command_packet = bytearray(8 + len(data))
# word address
command_packet[0] = 0x03
# i/o group: count
command_packet[1] = len(command_packet) - 1 # count
command_packet[1] = len(command_packet) - 1 # count
# security command packets
command_packet[2] = opcode
command_packet[3] = param_1
command_packet[4] = param_2 & 0xFF
command_packet[5] = param_2 >> 8
for i, cmd in enumerate(data):
command_packet[6+i] = cmd
command_packet[6 + i] = cmd
if self._debug:
print("Command Packet Sz: ", len(command_packet))
print("\tSending:", [hex(i) for i in command_packet])
@ -517,12 +520,11 @@ class ATECC:
# small sleep
time.sleep(0.001)
def _get_response(self, buf, length=None, retries=20):
self.wakeup()
if length is None:
length = len(buf)
response = bytearray(length+3) # 1 byte header, 2 bytes CRC, len bytes data
response = bytearray(length + 3) # 1 byte header, 2 bytes CRC, len bytes data
with self._i2c_device as i2c:
for _ in range(retries):
try:
@ -539,7 +541,7 @@ class ATECC:
if crc != crc2:
raise RuntimeError("CRC Mismatch")
for i in range(length):
buf[i] = response[i+1]
buf[i] = response[i + 1]
return response[1]
@staticmethod
@ -553,7 +555,7 @@ class ATECC:
for b in data:
for shift in range(8):
data_bit = 0
if b & (1<<shift):
if b & (1 << shift):
data_bit = 1
crc_bit = (crc >> 15) & 0x1
crc <<= 1

View file

@ -65,11 +65,11 @@ def get_signature(signature, data):
r_len = 32
s_len = 32
while (r == 0x00 and r_len > 1):
while r == 0x00 and r_len > 1:
r += 1
r_len -= 1
while (s == 0x00 and s_len > 1):
while s == 0x00 and s_len > 1:
s += 1
s_len -= 1
@ -107,8 +107,7 @@ def get_signature(signature, data):
# pylint: disable=too-many-arguments
def get_issuer_or_subject(data, country, state_prov, locality,
org, org_unit, common):
def get_issuer_or_subject(data, country, state_prov, locality, org, org_unit, common):
"""Appends issuer or subject, if they exist, to data."""
if country:
get_name(country, 0x06, data)
@ -117,9 +116,9 @@ def get_issuer_or_subject(data, country, state_prov, locality,
if locality:
get_name(locality, 0x07, data)
if org:
get_name(org, 0x0a, data)
get_name(org, 0x0A, data)
if org_unit:
get_name(org_unit, 0x0b, data)
get_name(org_unit, 0x0B, data)
if common:
get_name(common, 0x03, data)
@ -142,28 +141,30 @@ def get_name(name, obj_type, data):
data.extend(name)
return len(name) + 11
def get_version(data):
"""Appends X.509 version to data."""
# If no extensions are present, but a UniqueIdentifier
# is present, the version SHOULD be 2 (value is 1) [4-1-2]
data += b"\x02\x01\x00"
def get_sequence_header(length, data):
"""Appends sequence header to provided data."""
data += b"\x30"
if length > 255:
data += b"\x82"
data.append((length >> 8) & 0xff)
data.append((length >> 8) & 0xFF)
elif length > 127:
data += b"\x81"
length_byte = struct.pack("B", (length) & 0xff)
length_byte = struct.pack("B", (length) & 0xFF)
data += length_byte
def get_public_key(data, public_key):
"""Appends public key subject and object identifiers."""
# Subject: Public Key
data += b"\x30" + struct.pack("B", (0x59) & 0xff) + b"\x30\x13"
data += b"\x30" + struct.pack("B", (0x59) & 0xFF) + b"\x30\x13"
# Object identifier: EC Public Key
data += b"\x06\x07\x2a\x86\x48\xce\x3d\x02\x01"
# Object identifier: PRIME 256 v1
@ -171,6 +172,7 @@ def get_public_key(data, public_key):
# Extend the buffer by the public key
data += public_key
def get_signature_length(signature):
"""Return length of ECDSA signature.
:param bytearray signature: Signed SHA256 hash.
@ -180,14 +182,14 @@ def get_signature_length(signature):
r_len = 32
s_len = 32
while (r == 0x00 and r_len > 1):
while r == 0x00 and r_len > 1:
r += 1
r_len -= 1
if r & 0x80:
r_len += 1
while (s == 0x00 and s_len > 1):
while s == 0x00 and s_len > 1:
s += 1
s_len -= 1
@ -195,6 +197,7 @@ def get_signature_length(signature):
s_len += 1
return 21 + r_len + s_len
def get_sequence_header_length(seq_header_len):
"""Returns length of SEQUENCE header."""
if seq_header_len > 255:
@ -203,6 +206,7 @@ def get_sequence_header_length(seq_header_len):
return 3
return 2
def issuer_or_subject_length(country, state_prov, city, org, org_unit, common):
"""Returns total length of provided certificate information."""
tot_len = 0

View file

@ -54,6 +54,7 @@ Implementation Notes
from adafruit_binascii import b2a_base64
import adafruit_atecc.adafruit_atecc_asn1 as asn1
class CSR:
"""Certificate Signing Request Builder.
@ -67,9 +68,11 @@ class CSR:
:param str org_unit: Organizational unit name.
"""
# pylint: disable=too-many-arguments, too-many-instance-attributes
def __init__(self, atecc, slot_num, private_key, country, state_prov,
city, org, org_unit):
def __init__(
self, atecc, slot_num, private_key, country, state_prov, city, org, org_unit
):
self._atecc = atecc
self.private_key = private_key
self._slot = slot_num
@ -89,7 +92,6 @@ class CSR:
csr = self._csr_end()
return csr
def _csr_begin(self):
"""Initializes CSR generation. """
assert 0 <= self._slot <= 4, "Provided slot must be between 0 and 4."
@ -100,13 +102,17 @@ class CSR:
return
self._atecc.gen_key(self._key, self._slot, self.private_key)
def _csr_end(self):
"""Generates and returns
a certificate signing request as a base64 string."""
len_issuer_subject = asn1.issuer_or_subject_length(self._country, self._state_province,
self._locality, self._org,
self._org_unit, self._common)
len_issuer_subject = asn1.issuer_or_subject_length(
self._country,
self._state_province,
self._locality,
self._org,
self._org_unit,
self._common,
)
len_sub_header = asn1.get_sequence_header_length(len_issuer_subject)
len_csr_info = self._version_len + len_issuer_subject
@ -126,8 +132,15 @@ class CSR:
asn1.get_sequence_header(len_issuer_subject, csr_info)
# Append Issuer or Subject
asn1.get_issuer_or_subject(csr_info, self._country, self._state_province,
self._locality, self._org, self._org_unit, self._common)
asn1.get_issuer_or_subject(
csr_info,
self._country,
self._state_province,
self._locality,
self._org,
self._org_unit,
self._common,
)
# Append Public Key
asn1.get_public_key(csr_info, self._key)
@ -145,7 +158,7 @@ class CSR:
if chunk_len > 64:
chunk_len = 64
if chunk_len == 64:
self._atecc.sha_update(csr_info[i:i+64])
self._atecc.sha_update(csr_info[i : i + 64])
else:
csr_info_sha_256 = self._atecc.sha_digest(csr_info[i:])

View file

@ -2,7 +2,8 @@
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath(".."))
# -- General configuration ------------------------------------------------
@ -10,10 +11,10 @@ sys.path.insert(0, os.path.abspath('..'))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
]
# Uncomment the below if you use native CircuitPython modules such as
@ -21,29 +22,36 @@ extensions = [
# autodoc module docs will fail to generate with a warning.
autodoc_mock_imports = ["micropython", "adafruit-bus-device", "adafruit-binascii"]
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'BusDevice': ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
intersphinx_mapping = {
"python": ("https://docs.python.org/3.4", None),
"BusDevice": (
"https://circuitpython.readthedocs.io/projects/busdevice/en/latest/",
None,
),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'Adafruit ATECC Library'
copyright = u'2019 Brent Rubell'
author = u'Brent Rubell'
project = "Adafruit ATECC Library"
copyright = "2019 Brent Rubell"
author = "Brent Rubell"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'1.0'
version = "1.0"
# The full version, including alpha/beta/rc tags.
release = u'1.0'
release = "1.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -55,7 +63,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
@ -67,7 +75,7 @@ default_role = "any"
add_function_parentheses = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
@ -82,59 +90,62 @@ napoleon_numpy_docstring = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = 'default'
html_theme_path = ['.']
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ['.']
html_theme_path = ["."]
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
html_favicon = '_static/favicon.ico'
html_favicon = "_static/favicon.ico"
# Output file base name for HTML help builder.
htmlhelp_basename = 'AdafruitAteccLibrarydoc'
htmlhelp_basename = "AdafruitAteccLibrarydoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'AdafruitATECCLibrary.tex', u'AdafruitATECC Library Documentation',
author, 'manual'),
(
master_doc,
"AdafruitATECCLibrary.tex",
"AdafruitATECC Library Documentation",
author,
"manual",
),
]
# -- Options for manual page output ---------------------------------------
@ -142,8 +153,13 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'AdafruitATECClibrary', u'Adafruit ATECC Library Documentation',
[author], 1)
(
master_doc,
"AdafruitATECClibrary",
"Adafruit ATECC Library Documentation",
[author],
1,
)
]
# -- Options for Texinfo output -------------------------------------------
@ -152,7 +168,13 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'AdafruitATECCLibrary', u'Adafruit ATECC Library Documentation',
author, 'AdafruitATECCLibrary', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"AdafruitATECCLibrary",
"Adafruit ATECC Library Documentation",
author,
"AdafruitATECCLibrary",
"One line description of project.",
"Miscellaneous",
),
]

View file

@ -26,8 +26,7 @@ GENERATE_PRIVATE_KEY = True
# -- END Configuration, code below -- #
# Initialize the i2c bus
i2c = busio.I2C(board.SCL, board.SDA,
frequency=_WAKE_CLK_FREQ)
i2c = busio.I2C(board.SCL, board.SDA, frequency=_WAKE_CLK_FREQ)
# Initialize a new atecc object
atecc = ATECC(i2c)
@ -36,7 +35,9 @@ print("ATECC Serial Number: ", atecc.serial_number)
if not atecc.locked:
if not LOCK_ATECC:
raise RuntimeError("The ATECC is not locked, set LOCK_ATECC to True in code.py.")
raise RuntimeError(
"The ATECC is not locked, set LOCK_ATECC to True in code.py."
)
print("Writing default configuration to the device...")
atecc.write_config(CFG_TLS)
print("Wrote configuration, locking ATECC module...")
@ -46,10 +47,18 @@ if not atecc.locked:
print("Generating Certificate Signing Request...")
# Initialize a certificate signing request with provided info
csr = cert_utils.CSR(atecc, ATECC_SLOT, GENERATE_PRIVATE_KEY, MY_COUNTRY, MY_STATE,
MY_CITY, MY_ORG, MY_SECTION)
csr = cert_utils.CSR(
atecc,
ATECC_SLOT,
GENERATE_PRIVATE_KEY,
MY_COUNTRY,
MY_STATE,
MY_CITY,
MY_ORG,
MY_SECTION,
)
# Generate CSR
my_csr = csr.generate_csr()
print("-----BEGIN CERTIFICATE REQUEST-----\n")
print(my_csr.decode('utf-8'))
print(my_csr.decode("utf-8"))
print("-----END CERTIFICATE REQUEST-----")

View file

@ -3,8 +3,7 @@ import busio
from adafruit_atecc.adafruit_atecc import ATECC, _WAKE_CLK_FREQ
# Initialize the i2c bus
i2c = busio.I2C(board.SCL, board.SDA,
frequency=_WAKE_CLK_FREQ)
i2c = busio.I2C(board.SCL, board.SDA, frequency=_WAKE_CLK_FREQ)
# Initialize a new atecc object
atecc = ATECC(i2c)

View file

@ -1,2 +1,3 @@
Adafruit-Blinka
adafruit-circuitpython-busdevice
adafruit-circuitpython-binascii

View file

@ -6,6 +6,7 @@ https://github.com/pypa/sampleproject
"""
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
@ -13,53 +14,45 @@ from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
long_description = f.read()
setup(
name='adafruit-circuitpython-atecc',
name="adafruit-circuitpython-atecc",
use_scm_version=True,
setup_requires=['setuptools_scm'],
description='Driver for Microchip\'s ATECCx08 cryptographic co-processors with secure hardware-based key storage',
setup_requires=["setuptools_scm"],
description="Driver for Microchip's ATECCx08 cryptographic co-processors with secure hardware-based key storage",
long_description=long_description,
long_description_content_type='text/x-rst',
long_description_content_type="text/x-rst",
# The project's main homepage.
url='https://github.com/adafruit/Adafruit_CircuitPython_ATECC',
url="https://github.com/adafruit/Adafruit_CircuitPython_ATECC",
# Author details
author='Adafruit Industries',
author_email='circuitpython@adafruit.com',
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
install_requires=[
'Adafruit-Blinka',
'adafruit-circuitpython-busdevice'
"Adafruit-Blinka",
"adafruit-circuitpython-busdevice",
"adafruit-circuitpython-binascii",
],
# Choose your license
license='MIT',
license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries',
'Topic :: System :: Hardware',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
],
# What does your project relate to?
keywords='adafruit blinka circuitpython micropython atecc atecc, microchip, secure, '
'element, key, co-processor',
keywords="adafruit blinka circuitpython micropython atecc atecc, microchip, secure, "
"element, key, co-processor",
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
# TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER,
# CHANGE `py_modules=['...']` TO `packages=['...']`
py_modules=['adafruit_atecc'],
packages=["adafruit_atecc"],
)