Skip to content

Commit 57713f5

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

File tree

1 file changed

+62
-15
lines changed

1 file changed

+62
-15
lines changed

src/arduino_iot_cloud/ussl.py

+62-15
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,55 @@
99
import ssl
1010
import sys
1111
import logging
12-
import binascii
12+
try:
13+
from micropython import const
14+
except (ImportError, AttributeError):
15+
const = lambda x: x
1316

1417
pkcs11 = None
18+
se_dev = None
1519

1620
# Default engine and provider.
1721
_ENGINE_PATH = "/usr/lib/engines-3/libpkcs11.so"
1822
_MODULE_PATH = "/usr/lib/softhsm/libsofthsm2.so"
1923

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

2733

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

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)
70+
se_key_token = keyfile is not None and "token" in keyfile
71+
se_crt_token = certfile is not None and "token" in certfile
72+
sys_micropython = sys.implementation.name == "micropython"
73+
74+
if sys_micropython and (se_key_token or se_crt_token):
75+
import se05x
76+
77+
# Create and initialize SE05x device.
78+
global se_dev
79+
if se_dev is None:
80+
se_dev = se05x.SE05X()
81+
82+
if se_key_token:
83+
# Create a reference key for the secure element.
84+
obj_id = int(keyfile.split("=")[1], 16)
85+
keyfile = _EC_REF_KEY[0:-4] + obj_id.to_bytes(4, "big")
86+
87+
if se_crt_token:
88+
# Load the certificate from the secure element.
89+
certfile = se_dev.read(0x65, 412)
4690

4791
if keyfile is None or "token" not in keyfile:
4892
# Use MicroPython/CPython SSL to wrap socket.
@@ -58,6 +102,9 @@ def wrap_socket(sock, ssl_params={}):
58102
ctx.set_ciphers(ciphers)
59103
if cafile is not None or cadata is not None:
60104
ctx.load_verify_locations(cafile=cafile, cadata=cadata)
105+
if sys_micropython and se_key_token:
106+
# Set alternate ECDSA sign function.
107+
ctx._context.ecdsa_sign_callback = ecdsa_sign_callback
61108
return ctx.wrap_socket(sock, server_hostname=hostname)
62109
else:
63110
# Use M2Crypto to load key and cert from HSM.

0 commit comments

Comments
 (0)