1# Tests for espsecure.py (esp_hsm_sign.py) using the pytest framework 2# 3# Assumes openssl binary is in the PATH 4 5import configparser 6import os 7import os.path 8import sys 9import tempfile 10from collections import namedtuple 11 12from conftest import need_to_install_package_err 13 14try: 15 import espsecure 16 import pkcs11 17except ImportError: 18 need_to_install_package_err() 19 20TEST_DIR = os.path.abspath(os.path.dirname(__file__)) 21 22TOKEN_PIN = "1234" 23TOKEN_PIN_SO = "123456" 24 25 26class EspSecureHSMTestCase: 27 @classmethod 28 def setup_class(self): 29 self.cleanup_files = [] # keep a list of files _open()ed by each test case 30 31 @classmethod 32 def teardown_class(self): 33 for f in self.cleanup_files: 34 f.close() 35 36 def _open(self, image_file): 37 f = open(os.path.join(TEST_DIR, "secure_images", image_file), "rb") 38 self.cleanup_files.append(f) 39 return f 40 41 def get_pkcs11lib(self): 42 if sys.maxsize > 2**32: 43 # 64-bits 44 WINDOWS_SOFTHSM = "c:/SoftHSM2/lib/softhsm2-x64.dll" 45 else: 46 # 32-bits 47 WINDOWS_SOFTHSM = "c:/SoftHSM2/lib/softhsm2.dll" 48 # use SoftHSM2 49 LIBS = [ 50 "/usr/local/lib/softhsm/libsofthsm2.so", # macOS or local build 51 "/usr/lib/softhsm/libsofthsm2.so", # Debian 52 "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", # Ubuntu 16.04 53 WINDOWS_SOFTHSM, # Windows 54 ] 55 56 for lib in LIBS: 57 if os.path.isfile(lib): 58 print("Using lib:", lib) 59 return lib 60 61 return None 62 63 # RSA-PSS token 64 def softhsm_setup_token(self, filename, token_label): 65 self.pkcs11_lib = self.get_pkcs11lib() 66 if self.pkcs11_lib is None: 67 print("PKCS11 lib does not exist") 68 sys.exit(-1) 69 lib = pkcs11.lib(self.pkcs11_lib) 70 token = lib.get_token(token_label=token_label) 71 slot = token.slot.slot_id 72 session = token.open(rw=True, user_pin=TOKEN_PIN) 73 74 keyID = (0x0,) 75 label = "Private Key for Digital Signature" 76 label_pubkey = "Public Key for Digital Signature" 77 pubTemplate = [ 78 (pkcs11.Attribute.CLASS, pkcs11.constants.ObjectClass.PUBLIC_KEY), 79 (pkcs11.Attribute.TOKEN, True), 80 (pkcs11.Attribute.PRIVATE, False), 81 (pkcs11.Attribute.MODULUS_BITS, 0x0C00), 82 (pkcs11.Attribute.PUBLIC_EXPONENT, (0x01, 0x00, 0x01)), 83 (pkcs11.Attribute.ENCRYPT, True), 84 (pkcs11.Attribute.VERIFY, True), 85 (pkcs11.Attribute.VERIFY_RECOVER, True), 86 (pkcs11.Attribute.WRAP, True), 87 (pkcs11.Attribute.LABEL, label_pubkey), 88 (pkcs11.Attribute.ID, keyID), 89 ] 90 91 privTemplate = [ 92 (pkcs11.Attribute.CLASS, pkcs11.constants.ObjectClass.PRIVATE_KEY), 93 (pkcs11.Attribute.TOKEN, True), 94 (pkcs11.Attribute.PRIVATE, True), 95 (pkcs11.Attribute.DECRYPT, True), 96 (pkcs11.Attribute.SIGN, True), 97 (pkcs11.Attribute.SENSITIVE, True), 98 (pkcs11.Attribute.SIGN_RECOVER, True), 99 (pkcs11.Attribute.LABEL, label), 100 (pkcs11.Attribute.UNWRAP, True), 101 (pkcs11.Attribute.ID, keyID), 102 ] 103 session.generate_keypair( 104 pkcs11.KeyType.RSA, 105 3072, 106 private_template=privTemplate, 107 public_template=pubTemplate, 108 ) 109 110 # Generate HSM config file 111 configfile = os.path.join(TEST_DIR, "secure_images", filename) 112 config = configparser.ConfigParser() 113 114 section = "hsm_config" 115 config.add_section(section) 116 117 config.set(section, "pkcs11_lib", self.pkcs11_lib) 118 config.set(section, "credentials", TOKEN_PIN) 119 config.set(section, "slot", str(slot)) 120 config.set(section, "label", label) 121 config.set(section, "label_pubkey", label_pubkey) 122 123 with open(configfile, "w") as c: 124 config.write(c) 125 126 session.close() 127 128 129class TestSigning(EspSecureHSMTestCase): 130 VerifyArgs = namedtuple( 131 "verify_signature_args", ["version", "hsm", "hsm_config", "keyfile", "datafile"] 132 ) 133 134 SignArgs = namedtuple( 135 "sign_data_args", 136 [ 137 "version", 138 "keyfile", 139 "output", 140 "append_signatures", 141 "hsm", 142 "hsm_config", 143 "pub_key", 144 "signature", 145 "datafile", 146 ], 147 ) 148 149 def test_sign_v2_hsm(self): 150 # Sign using SoftHSMv2 + Verify 151 self.softhsm_setup_token("softhsm_v2.ini", "softhsm-test-token") 152 with tempfile.NamedTemporaryFile() as output_file: 153 args = self.SignArgs( 154 "2", 155 None, 156 output_file.name, 157 False, 158 True, 159 os.path.join(TEST_DIR, "secure_images", "softhsm_v2.ini"), 160 None, 161 None, 162 self._open("bootloader_unsigned_v2.bin"), 163 ) 164 espsecure.sign_data(args) 165 166 args = self.VerifyArgs( 167 "2", 168 True, 169 os.path.join(TEST_DIR, "secure_images", "softhsm_v2.ini"), 170 None, 171 output_file, 172 ) 173 espsecure.verify_signature(args) 174 175 def test_sign_v2_hsm_append_signatures_multiple_steps(self): 176 # Append signatures using HSM + Verify with an appended key 177 self.softhsm_setup_token("softhsm_v2_1.ini", "softhsm-test-token-1") 178 with tempfile.NamedTemporaryFile() as output_file1: 179 args = self.SignArgs( 180 "2", 181 None, 182 output_file1.name, 183 True, 184 True, 185 os.path.join(TEST_DIR, "secure_images", "softhsm_v2_1.ini"), 186 None, 187 None, 188 self._open("bootloader_unsigned_v2.bin"), 189 ) 190 espsecure.sign_data(args) 191 192 self.softhsm_setup_token("softhsm_v2_2.ini", "softhsm-test-token-2") 193 with tempfile.NamedTemporaryFile() as output_file2: 194 args = self.SignArgs( 195 "2", 196 None, 197 output_file2.name, 198 True, 199 True, 200 os.path.join(TEST_DIR, "secure_images", "softhsm_v2_2.ini"), 201 None, 202 None, 203 self._open(output_file1.name), 204 ) 205 espsecure.sign_data(args) 206 207 self.softhsm_setup_token("softhsm_v2_3.ini", "softhsm-test-token-3") 208 with tempfile.NamedTemporaryFile() as output_file3: 209 args = self.SignArgs( 210 "2", 211 None, 212 output_file3.name, 213 True, 214 True, 215 os.path.join(TEST_DIR, "secure_images", "softhsm_v2_3.ini"), 216 None, 217 None, 218 self._open(output_file2.name), 219 ) 220 espsecure.sign_data(args) 221 222 args = self.VerifyArgs( 223 "2", 224 True, 225 os.path.join(TEST_DIR, "secure_images", "softhsm_v2_1.ini"), 226 None, 227 output_file3, 228 ) 229 espsecure.verify_signature(args) 230 output_file3.seek(0) 231 232 args = self.VerifyArgs( 233 "2", 234 True, 235 os.path.join(TEST_DIR, "secure_images", "softhsm_v2_2.ini"), 236 None, 237 output_file3, 238 ) 239 espsecure.verify_signature(args) 240 output_file3.seek(0) 241 242 args = self.VerifyArgs( 243 "2", 244 True, 245 os.path.join(TEST_DIR, "secure_images", "softhsm_v2_3.ini"), 246 None, 247 output_file3, 248 ) 249 espsecure.verify_signature(args) 250