Skip to content

Commit ccd6da4

Browse files
committed
ussl: Add support for sign callback on MicroPython.
Signed-off-by: iabdalkader <[email protected]>
1 parent eae80d2 commit ccd6da4

File tree

1 file changed

+59
-15
lines changed

1 file changed

+59
-15
lines changed

src/arduino_iot_cloud/ussl.py

+59-15
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,52 @@
99
import ssl
1010
import sys
1111
import logging
12-
import binascii
12+
1313

1414
pkcs11 = None
15+
se_dev = None
1516

1617
# Default engine and provider.
1718
_ENGINE_PATH = "/usr/lib/engines-3/libpkcs11.so"
1819
_MODULE_PATH = "/usr/lib/softhsm/libsofthsm2.so"
1920

20-
# Reference EC key for NXP's PlugNTrust
21-
_EC_REF_KEY = binascii.unhexlify(
22-
b"3041020100301306072a8648ce3d020106082a8648ce3d03010704273025"
23-
b"0201010420100000000000000000000000000000000000ffffffffa5a6b5"
24-
b"b6a5a6b5b61000"
21+
# Reference EC key for the SE.
22+
_EC_REF_KEY = const(
23+
b"\x30\x41\x02\x01\x00\x30\x13\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01"
24+
b"\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07\x04\x27\x30\x25\x02\x01"
25+
b"\x01\x04\x20\xA5\xA6\xB5\xB6\xA5\xA6\xB5\xB6\x00\x00\x00\x00\x00"
26+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"
27+
b"\xFF\xFF\xFF"
2528
)
2629

2730

31+
def log_level_enabled(level):
32+
return logging.getLogger().isEnabledFor(level)
33+
34+
35+
def ecdsa_sign_callback(key, data):
36+
if log_level_enabled(logging.DEBUG):
37+
key_hex = "".join("%02X" % b for b in key)
38+
logging.debug(f"ecdsa_sign_callback key:{key_hex}")
39+
40+
if key[0:8] != b"\xA5\xA6\xB5\xB6\xA5\xA6\xB5\xB6":
41+
if log_level_enabled(logging.DEBUG):
42+
logging.debug("ecdsa_sign_callback falling back to default sign")
43+
return None
44+
45+
obj_id = int.from_bytes(key[-4:], "big")
46+
if log_level_enabled(logging.DEBUG):
47+
logging.debug(f"ecdsa_sign_callback oid: 0x{obj_id:02X}")
48+
49+
# Sign data on SE using reference key object id.
50+
sig = se_dev.sign(obj_id, data)
51+
if log_level_enabled(logging.DEBUG):
52+
sig_hex = "".join("%02X" % b for b in sig)
53+
logging.debug(f"ecdsa_sign_callback sig: {sig_hex}")
54+
logging.info("Signed using secure element")
55+
return sig
56+
57+
2858
def wrap_socket(sock, ssl_params={}):
2959
keyfile = ssl_params.get("keyfile", None)
3060
certfile = ssl_params.get("certfile", None)
@@ -33,16 +63,27 @@ def wrap_socket(sock, ssl_params={}):
3363
ciphers = ssl_params.get("ciphers", None)
3464
verify = ssl_params.get("verify_mode", ssl.CERT_NONE)
3565
hostname = ssl_params.get("server_hostname", None)
36-
micropython = sys.implementation.name == "micropython"
3766

38-
if keyfile is not None and "token" in keyfile and micropython:
39-
# Create a reference EC key for NXP EdgeLock device.
40-
objid = int(keyfile.split("=")[1], 16).to_bytes(4, "big")
41-
keyfile = _EC_REF_KEY[0:53] + objid + _EC_REF_KEY[57:]
42-
# Load the certificate from the secure element (when supported).
43-
# import cryptoki
44-
# with cryptoki.open() as token:
45-
# cert = token.read(0x65, 412)
67+
se_key_token = keyfile is not None and "token" in keyfile
68+
se_crt_token = certfile is not None and "token" in certfile
69+
sys_micropython = sys.implementation.name == "micropython"
70+
71+
if sys_micropython and (se_key_token or se_crt_token):
72+
import se05x
73+
74+
# Create and initialize SE05x device.
75+
global se_dev
76+
if se_dev is None:
77+
se_dev = se05x.SE05X()
78+
79+
if se_key_token:
80+
# Create a reference key for the secure element.
81+
obj_id = int(keyfile.split("=")[1], 16)
82+
keyfile = _EC_REF_KEY[0:-4] + obj_id.to_bytes(4, "big")
83+
84+
if se_crt_token:
85+
# Load the certificate from the secure element.
86+
certfile = se_dev.read(0x65, 412)
4687

4788
if keyfile is None or "token" not in keyfile:
4889
# Use MicroPython/CPython SSL to wrap socket.
@@ -58,6 +99,9 @@ def wrap_socket(sock, ssl_params={}):
5899
ctx.set_ciphers(ciphers)
59100
if cafile is not None or cadata is not None:
60101
ctx.load_verify_locations(cafile=cafile, cadata=cadata)
102+
if sys_micropython and se_key_token:
103+
# Set alternate ECDSA sign function.
104+
ctx._context.ecdsa_sign_callback = ecdsa_sign_callback
61105
return ctx.wrap_socket(sock, server_hostname=hostname)
62106
else:
63107
# Use M2Crypto to load key and cert from HSM.

0 commit comments

Comments
 (0)