9
9
import ssl
10
10
import sys
11
11
import logging
12
- import binascii
12
+ try :
13
+ from micropython import const
14
+ except (ImportError , AttributeError ):
15
+ def const (x ):
16
+ return x
13
17
14
18
pkcs11 = None
19
+ se_dev = None
15
20
16
21
# Default engine and provider.
17
22
_ENGINE_PATH = "/usr/lib/engines-3/libpkcs11.so"
18
23
_MODULE_PATH = "/usr/lib/softhsm/libsofthsm2.so"
19
24
20
- # Reference EC key for NXP's PlugNTrust
21
- _EC_REF_KEY = binascii .unhexlify (
22
- b"3041020100301306072a8648ce3d020106082a8648ce3d03010704273025"
23
- b"0201010420100000000000000000000000000000000000ffffffffa5a6b5"
24
- b"b6a5a6b5b61000"
25
+ # Reference EC key for the SE.
26
+ _EC_REF_KEY = const (
27
+ b"\x30 \x41 \x02 \x01 \x00 \x30 \x13 \x06 \x07 \x2A \x86 \x48 \xCE \x3D \x02 \x01 "
28
+ b"\x06 \x08 \x2A \x86 \x48 \xCE \x3D \x03 \x01 \x07 \x04 \x27 \x30 \x25 \x02 \x01 "
29
+ b"\x01 \x04 \x20 \xA5 \xA6 \xB5 \xB6 \xA5 \xA6 \xB5 \xB6 \x00 \x00 \x00 \x00 \x00 "
30
+ b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \xFF "
31
+ b"\xFF \xFF \xFF "
25
32
)
26
33
27
34
35
+ def log_level_enabled (level ):
36
+ return logging .getLogger ().isEnabledFor (level )
37
+
38
+
39
+ def ecdsa_sign_callback (key , data ):
40
+ if log_level_enabled (logging .DEBUG ):
41
+ key_hex = "" .join ("%02X" % b for b in key )
42
+ logging .debug (f"ecdsa_sign_callback key:{ key_hex } " )
43
+
44
+ if key [0 :8 ] != b"\xA5 \xA6 \xB5 \xB6 \xA5 \xA6 \xB5 \xB6 " :
45
+ if log_level_enabled (logging .DEBUG ):
46
+ logging .debug ("ecdsa_sign_callback falling back to default sign" )
47
+ return None
48
+
49
+ obj_id = int .from_bytes (key [- 4 :], "big" )
50
+ if log_level_enabled (logging .DEBUG ):
51
+ logging .debug (f"ecdsa_sign_callback oid: 0x{ obj_id :02X} " )
52
+
53
+ # Sign data on SE using reference key object id.
54
+ sig = se_dev .sign (obj_id , data )
55
+ if log_level_enabled (logging .DEBUG ):
56
+ sig_hex = "" .join ("%02X" % b for b in sig )
57
+ logging .debug (f"ecdsa_sign_callback sig: { sig_hex } " )
58
+ logging .info ("Signed using secure element" )
59
+ return sig
60
+
61
+
28
62
def wrap_socket (sock , ssl_params = {}):
29
63
keyfile = ssl_params .get ("keyfile" , None )
30
64
certfile = ssl_params .get ("certfile" , None )
@@ -33,16 +67,27 @@ def wrap_socket(sock, ssl_params={}):
33
67
ciphers = ssl_params .get ("ciphers" , None )
34
68
verify = ssl_params .get ("verify_mode" , ssl .CERT_NONE )
35
69
hostname = ssl_params .get ("server_hostname" , None )
36
- micropython = sys .implementation .name == "micropython"
37
70
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)
71
+ se_key_token = keyfile is not None and "token" in keyfile
72
+ se_crt_token = certfile is not None and "token" in certfile
73
+ sys_micropython = sys .implementation .name == "micropython"
74
+
75
+ if sys_micropython and (se_key_token or se_crt_token ):
76
+ import se05x
77
+
78
+ # Create and initialize SE05x device.
79
+ global se_dev
80
+ if se_dev is None :
81
+ se_dev = se05x .SE05X ()
82
+
83
+ if se_key_token :
84
+ # Create a reference key for the secure element.
85
+ obj_id = int (keyfile .split ("=" )[1 ], 16 )
86
+ keyfile = _EC_REF_KEY [0 :- 4 ] + obj_id .to_bytes (4 , "big" )
87
+
88
+ if se_crt_token :
89
+ # Load the certificate from the secure element.
90
+ certfile = se_dev .read (0x65 , 412 )
46
91
47
92
if keyfile is None or "token" not in keyfile :
48
93
# Use MicroPython/CPython SSL to wrap socket.
@@ -58,6 +103,9 @@ def wrap_socket(sock, ssl_params={}):
58
103
ctx .set_ciphers (ciphers )
59
104
if cafile is not None or cadata is not None :
60
105
ctx .load_verify_locations (cafile = cafile , cadata = cadata )
106
+ if sys_micropython and se_key_token :
107
+ # Set alternate ECDSA sign function.
108
+ ctx ._context .ecdsa_sign_callback = ecdsa_sign_callback
61
109
return ctx .wrap_socket (sock , server_hostname = hostname )
62
110
else :
63
111
# Use M2Crypto to load key and cert from HSM.
0 commit comments