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
+ const = lambda x : x
13
16
14
17
pkcs11 = None
18
+ se_dev = None
15
19
16
20
# Default engine and provider.
17
21
_ENGINE_PATH = "/usr/lib/engines-3/libpkcs11.so"
18
22
_MODULE_PATH = "/usr/lib/softhsm/libsofthsm2.so"
19
23
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 "
25
31
)
26
32
27
33
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
+
28
61
def wrap_socket (sock , ssl_params = {}):
29
62
keyfile = ssl_params .get ("keyfile" , None )
30
63
certfile = ssl_params .get ("certfile" , None )
@@ -33,16 +66,27 @@ def wrap_socket(sock, ssl_params={}):
33
66
ciphers = ssl_params .get ("ciphers" , None )
34
67
verify = ssl_params .get ("verify_mode" , ssl .CERT_NONE )
35
68
hostname = ssl_params .get ("server_hostname" , None )
36
- micropython = sys .implementation .name == "micropython"
37
69
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 )
46
90
47
91
if keyfile is None or "token" not in keyfile :
48
92
# Use MicroPython/CPython SSL to wrap socket.
@@ -58,6 +102,9 @@ def wrap_socket(sock, ssl_params={}):
58
102
ctx .set_ciphers (ciphers )
59
103
if cafile is not None or cadata is not None :
60
104
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
61
108
return ctx .wrap_socket (sock , server_hostname = hostname )
62
109
else :
63
110
# Use M2Crypto to load key and cert from HSM.
0 commit comments