9
9
import ssl
10
10
import sys
11
11
import logging
12
- import binascii
12
+
13
13
14
14
pkcs11 = None
15
+ se_dev = None
15
16
16
17
# Default engine and provider.
17
18
_ENGINE_PATH = "/usr/lib/engines-3/libpkcs11.so"
18
19
_MODULE_PATH = "/usr/lib/softhsm/libsofthsm2.so"
19
20
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 "
25
28
)
26
29
27
30
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
+
28
58
def wrap_socket (sock , ssl_params = {}):
29
59
keyfile = ssl_params .get ("keyfile" , None )
30
60
certfile = ssl_params .get ("certfile" , None )
@@ -33,16 +63,27 @@ def wrap_socket(sock, ssl_params={}):
33
63
ciphers = ssl_params .get ("ciphers" , None )
34
64
verify = ssl_params .get ("verify_mode" , ssl .CERT_NONE )
35
65
hostname = ssl_params .get ("server_hostname" , None )
36
- micropython = sys .implementation .name == "micropython"
37
66
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 )
46
87
47
88
if keyfile is None or "token" not in keyfile :
48
89
# Use MicroPython/CPython SSL to wrap socket.
@@ -58,6 +99,9 @@ def wrap_socket(sock, ssl_params={}):
58
99
ctx .set_ciphers (ciphers )
59
100
if cafile is not None or cadata is not None :
60
101
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
61
105
return ctx .wrap_socket (sock , server_hostname = hostname )
62
106
else :
63
107
# Use M2Crypto to load key and cert from HSM.
0 commit comments