-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathecdh.py
More file actions
136 lines (109 loc) · 5.23 KB
/
ecdh.py
File metadata and controls
136 lines (109 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
"""
ECDH Shared Secret Generation Example
"""
# (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
#
# Subject to your compliance with these terms, you may use Microchip software
# and any derivatives exclusively with Microchip products. It is your
# responsibility to comply with third party license terms applicable to your
# use of third party software (including open source software) that may
# accompany Microchip software.
#
# THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
# EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
# WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
# PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
# SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
# OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
# MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
# FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
# LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
# THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
# THIS SOFTWARE.
from cryptoauthlib import *
from common import *
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
from cryptography.utils import int_from_bytes
import time
def ECDH(slot, iface='hid', **kwargs):
ATCA_SUCCESS = 0x00
# Loading cryptoauthlib(python specific)
load_cryptoauthlib()
# Get the target default config
cfg = eval('cfg_ateccx08a_{}_default()'.format(atca_names_map.get(iface)))
# Set interface parameters
if kwargs is not None:
for k, v in kwargs.items():
icfg = getattr(cfg.cfg, 'atca{}'.format(iface))
setattr(icfg, k, int(v, 16))
# Basic Raspberry Pi I2C check
if 'bus' not in kwargs:
if 'i2c' == iface and check_if_rpi():
cfg.cfg.atcai2c.bus = 1
# Initialize the stack
assert atcab_init(cfg) == ATCA_SUCCESS
# Get the device type from the info command
info = bytearray(4)
assert atcab_info(info) == ATCA_SUCCESS
dev_name = get_device_name(info)
dev_type = get_device_type_id(dev_name)
# Check device type
if dev_type in ['ATSHA204A', 'ATECC108A']:
raise ValueError('Device does not support ECDH operations')
elif dev_type != cfg.devtype:
cfg.dev_type = dev_type
assert atcab_release() == ATCA_SUCCESS
time.sleep(1)
assert atcab_init(cfg) == ATCA_SUCCESS
# Create a host private key
host_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
# Convert host's public key into ATECCx08 format
host_pub = host_key.public_key().public_bytes(encoding=Encoding.X962, format=PublicFormat.UncompressedPoint)[1:]
# Display the host's public key
print("\nHost Public Key:")
print(convert_ec_pub_to_pem(host_pub))
# Buffers for device public key and shared secret
device_pub = bytearray(64)
device_shared = bytearray(32)
# Generate a device private key and perform the ECDH operation
# This step is using the unencrypted form of the ECDH calls due to configuration details that will be specific
# for the use case. See atcab_ecdh_enc and atcab_ecdh_tempkey_ioenc functions.
if dev_type == get_device_type_id('ATECC508A'):
assert atcab_genkey(slot, device_pub) == ATCA_SUCCESS
assert atcab_ecdh(slot, host_pub, device_shared) == ATCA_SUCCESS
else:
assert atcab_genkey(0xFFFF, device_pub) == ATCA_SUCCESS
assert atcab_ecdh_tempkey(host_pub, device_shared) == ATCA_SUCCESS
# Display the device's public key
print("\nDevice public key:")
print(convert_ec_pub_to_pem(device_pub))
# Convert device public key to a cryptography public key object
device_pub = ec.EllipticCurvePublicNumbers(
curve=ec.SECP256R1(),
x=int_from_bytes(device_pub[0:32], byteorder='big'),
y=int_from_bytes(device_pub[32:64], byteorder='big'),
).public_key(default_backend())
# Perform the host side ECDH computation
host_shared = host_key.exchange(ec.ECDH(), device_pub)
# Display the host side computed symmetric key
print('\nHost Calculated Shared Secret:')
print(pretty_print_hex(host_shared, indent=' '))
# Display the device side computed symmetric key
print('\nDevice Calculated Shared Secret:')
print(pretty_print_hex(device_shared, indent=' '))
# Compare both independently calculated
print('\nComparing host and device generated secrets:')
if host_shared == device_shared:
print(" Success - Generated secrets match!")
else:
print(" Error in calculation")
assert atcab_release() == ATCA_SUCCESS
if __name__ == '__main__':
parser = setup_example_runner(__file__)
parser.add_argument('-s', '--slot', default=2, type=int, help='Slot to use for key generation (ATECC508A only)')
args = parser.parse_args()
print('\nPerforming ECDH operations in the clear - see datasheet for encryption details')
ECDH(args.slot, args.iface, **parse_interface_params(args.params))
print('\nDone')