def __init__(self): if not self.py2_exe: print("initializing...") if is_linux(): # is python2 in the path? cmd = ['which', 'python2'] output = run_command(cmd, ret_binary=False) if 'python2' in output: self.py2_exe = output.strip() else: # is python2 in /usr/bin? if os.path.exists('/usr/bin/python2'): self.py2_exe = '/usr/bin/python2' else: # is python in the path? cmd = ['python', '--version'] output = run_command(cmd, ret_binary=False) # if so does the version start with 2? if 'Python' in output: version = output.split()[1] if version.startswith('2'): self.py2_exe = 'python' # check the usual install location for py2 if not self.py2_exe: possible = glob.glob(r'c:\Python*') for p_dir in possible: poss_python_exe = os.path.join(p_dir, 'python.exe') if os.path.exists(poss_python_exe): self.py2_exe = poss_python_exe break
def decrypt(self, message, key, iv, ciphername=AesCbcBase.CIPHERNAME_128): message_path, decrypted_message_path = None, None try: message_path = c_path.create_tmp_file(message) decrypted_message_path = c_path.create_tmp_file() cmd = [ self.openssl, 'enc', ciphername, '-d', '-in', message_path, '-K', key, '-iv', iv, '-out', decrypted_message_path, '-nopad' ] run_command(cmd) return c_path.load_data_from_file(decrypted_message_path) finally: c_path.remove_tmp_file(message_path) c_path.remove_tmp_file(decrypted_message_path)
def encrypt(self, message, key, iv, aad): message_path, encrypted_message_path = None, None try: message_path = c_path.create_tmp_file(message) encrypted_message_path = c_path.create_tmp_file() cmd = [ self.crypto_ccm, '--input-file', message_path, '--key', key, '--iv', iv, '--output', encrypted_message_path, '--operation=encrypt', '--aad', aad ] run_command(cmd, log=False) return c_path.load_data_from_file(encrypted_message_path) finally: c_path.remove_tmp_file(message_path) c_path.remove_tmp_file(encrypted_message_path)
def sign_cert(self, cert, ca_cert, ca_priv_key, extfile=None, hash_algo=CertBase.HASH_ALGO_SHA256, days=None, serial=None, sign_algo=CertBase.SIGN_ALGO_RSA_PKCS, pad_hash_algo=CertBase.HASH_ALGO_SHA256, pad_salt_len=CertBase.PAD_PSS_SALT_1): cert_path, ca_cert_path, ca_priv_path = None, None, None try: cert_path = c_path.create_tmp_file(cert) ca_cert_path = c_path.create_tmp_file(ca_cert) ca_priv_path = c_path.create_tmp_file(ca_priv_key) cmd = [self.openssl, OPENSSL_CERT_MODE, '-req', '-in', cert_path, '-CAkey', ca_priv_path, '-CA', ca_cert_path, ] if days is not None: cmd += ['-days', str(days)] if serial is not None: cmd += ['-set_serial', str(serial)] if extfile is not None: cmd += ['-extfile', extfile] if hash_algo is not None: cmd += ['-' + hash_algo] if sign_algo == self.SIGN_ALGO_RSA_PSS: cmd += ['-sigopt', 'rsa_padding_mode:pss', '-sigopt', 'rsa_pss_saltlen:' + pad_salt_len, '-sigopt', 'digest:' + pad_hash_algo] else: cmd += ['-CAcreateserial'] return run_command(cmd) finally: c_path.remove_tmp_file(cert_path) c_path.remove_tmp_file(ca_cert_path) c_path.remove_tmp_file(ca_priv_path)
def decrypt(self, message, key, iv): message_path, decrypted_message_path = None, None try: message_path = c_path.create_tmp_file(message) decrypted_message_path = c_path.create_tmp_file() cmd = [ self.crypto_cbc, '--input-file', message_path, '--key', key, '--iv', iv, '--output', decrypted_message_path, '--operation=decrypt' ] run_command(cmd, log=False) return c_path.load_data_from_file(decrypted_message_path) finally: c_path.remove_tmp_file(message_path) c_path.remove_tmp_file(decrypted_message_path)
def get_public_key_from_private(self, priv_key): key_path = c_path.create_tmp_file(priv_key) try: cmd = [self.openssl, OPENSSL_RSA_MODE, '-in', key_path, '-pubout'] return run_command(cmd) finally: c_path.remove_tmp_file(key_path)
def decrypt(self, key, cryptogram): cmd = [ self.ecies, '--decrypt', '--key', ensure_str(key), '--cryptogram', ensure_str(cryptogram) ] return run_command(cmd, log=False)
def create_cert(self, priv_key, subject_params=None, config=None, self_sign=False, hash_algo=CertBase.HASH_ALGO_SHA256, days=None, serial=None, sign_algo=CertBase.SIGN_ALGO_RSA_PKCS, pad_hash_algo=CertBase.HASH_ALGO_SHA256, pad_salt_len=CertBase.PAD_PSS_SALT_1): priv_path = c_path.create_tmp_file(priv_key) try: cmd = [self.openssl, 'req', '-new', '-key', priv_path] if subject_params is not None: subject = self.get_subject_from_params(subject_params) cmd += ['-subj', subject] if config is not None: cmd += ['-config', config] if self_sign: cmd += ['-x509'] if days is not None: cmd += ['-days', str(days)] if serial is not None: cmd += ['-set_serial', str(serial)] if hash_algo is not None: cmd += ['-' + hash_algo] if sign_algo == self.SIGN_ALGO_RSA_PSS: cmd += ['-sigopt', 'rsa_padding_mode:pss', '-sigopt', 'rsa_pss_saltlen:' + pad_salt_len, '-sigopt', 'digest:' + pad_hash_algo] return run_command(cmd) finally: c_path.remove_tmp_file(priv_path)
def _gen_rsa_key_pair(self, exponent, keysize): exponent_opt, keysize_opt = self._get_opts(exponent, keysize) cmd = [self.openssl, 'genpkey', '-algorithm', 'RSA', '-outform', 'PEM', '-pkeyopt', 'rsa_keygen_bits:' + keysize_opt, '-pkeyopt', 'rsa_keygen_pubexp:' + exponent_opt] return run_command(cmd)
def encrypt(self, key, aad, message): cmd = [ self.ecies, '--encrypt', '--key', ensure_str(key), '--aad', ensure_str(aad), '--msg', ensure_str(message) ] return run_command(cmd, log=False)
def get_asn1_text(self, cert): cert_path = c_path.create_tmp_file(cert) try: cmd = [self.openssl, 'asn1parse', '-in', cert_path, '-inform', self._get_format_opt(self.get_cert_format(cert))] return run_command(cmd, large_output=True) finally: c_path.remove_tmp_file(cert_path)
def get_asn1_text(self, signature): signature_path = c_path.create_tmp_file(signature) try: cmd = [ self.openssl, 'asn1parse', '-in', signature_path, '-inform', utils.FORMAT_DER ] return run_command(cmd, large_output=True) finally: c_path.remove_tmp_file(signature_path)
def get_pubkey(self, cert): cert_path = c_path.create_tmp_file(cert) try: cmd = [self.openssl, OPENSSL_CERT_MODE, '-in', cert_path, '-pubkey', '-noout', '-inform', self._get_format_opt(self.get_cert_format(cert))] return run_command(cmd) finally: c_path.remove_tmp_file(cert_path)
def _pkeyutl(self, message, key, preopts, options, expected_retcode=0): message_path = c_path.create_tmp_file(message) key_path = c_path.create_tmp_file(key) cmd = ([self.openssl, OPENSSL_PKEYUTL_MODE] + preopts + ['-inkey', key_path, '-in', message_path] + options) try: return run_command(cmd, expected_retcode) finally: c_path.remove_tmp_file(message_path) c_path.remove_tmp_file(key_path)
def get_text_from_key(self, key, inform, is_public=False): key_path = c_path.create_tmp_file(key) try: cmd = [self.openssl, 'rsa', '-text', '-noout', '-in', key_path, '-inform', self._get_format_opt(inform)] if is_public: cmd.append('-pubin') return run_command(cmd) finally: c_path.remove_tmp_file(key_path)
def get_text(self, cert): cert_path = c_path.create_tmp_file(cert) try: cmd = [self.openssl, OPENSSL_CERT_MODE, '-in', cert_path, '-inform', self._get_format_opt(self.get_cert_format(cert)), '-noout', '-text', '-certopt', 'ext_dump'] return run_command(cmd, large_output=True, ret_binary=False) finally: c_path.remove_tmp_file(cert_path)
def get_key_in_format(self, key, outform, is_public=False): # Avoid error by reconverting inform = self.get_key_format(key) if inform == outform: return key key_path = c_path.create_tmp_file(key) try: cmd = [self.openssl, OPENSSL_RSA_MODE, '-in', key_path, '-inform', self._get_format_opt(inform), '-outform', self._get_format_opt(outform)] if is_public: cmd.append('-pubin') return run_command(cmd) finally: c_path.remove_tmp_file(key_path)
def get_cert_in_format(self, cert, outform): # Avoid error by reconverting inform = self.get_cert_format(cert) if inform == outform: return cert inform_opt = self._get_format_opt(inform) outform_opt = self._get_format_opt(outform) cert_path = c_path.create_tmp_file(cert) try: cmd = [self.openssl, OPENSSL_CERT_MODE, '-in', cert_path, '-inform', inform_opt, '-outform', outform_opt] return run_command(cmd) finally: c_path.remove_tmp_file(cert_path)
def validate_cert_chain(self, cert, ca_cert_chain): ca_cert_chain_path, cert_path = None, None try: ca_cert_chain_path = c_path.create_tmp_file(ca_cert_chain) cert_path = c_path.create_tmp_file(cert) # Check validity time valid_from, _ = self.get_validity(self.get_text(cert)) lag = calendar.timegm(valid_from) - int(time.time()) if lag > 0: logger.warning('Local machine\'s time is slow by at least ' + str(lag) + ' seconds.') cmd = [self.openssl, 'verify', '-attime', str(calendar.timegm(valid_from)), '-CAfile', ca_cert_chain_path, cert_path] return (cert_path + ': OK') in run_command(cmd, ret_binary=False) except RuntimeError: return False finally: c_path.remove_tmp_file(ca_cert_chain_path) c_path.remove_tmp_file(cert_path)
def decrypt(self, message, key, iv, aad): message_path, decrypted_message_path = None, None try: message_path = c_path.create_tmp_file(message) decrypted_message_path = c_path.create_tmp_file() cmd = [ self.crypto_ccm, '--input-file', message_path, '--key', key, '--iv', iv, '--output', decrypted_message_path, '--operation=decrypt', '--aad', aad ] output = run_command(cmd, log=False) # Check there is no issue with the output if "Caught HashVerificationFailed..." in output: raise RuntimeError(output) return c_path.load_data_from_file(decrypted_message_path) finally: c_path.remove_tmp_file(message_path) c_path.remove_tmp_file(decrypted_message_path)
def _execute_sign(self): # don't execute sectools, install, or pilsplit if no policy is provided if self.input.build_policy is None: return # Set the host and port for remote signing if self.input.port: os.environ[ENV_SIGNING_SERVER_PORT_TAG] = self.input.port if self.input.host: os.environ[ENV_SIGNING_SERVER_HOST_TAG] = self.input.host # create list containing command arguments to execute Sectools cmds = [executable, c_path.join(SECTOOLS_DIR, "sectools.py"), "secimage", "-i", self.input.source, "-g", self.input.sign_id, "-c", self.input.config] if self.input.app_id: cmds += ["--cfg_app_id", self.input.app_id] if self.input.jtag_id: cmds += ["--cfg_msm_part", self.input.jtag_id] if self.input.soc_hw_version: cmds += ["--cfg_soc_hw_version", self.input.soc_hw_version] if self.input.soc_vers: cmds += ["--cfg_soc_vers", self.input.soc_vers] if self.input.soc_hw_version or self.input.soc_vers: cmds += ["--cfg_in_use_soc_hw_version", ENABLE] if self.input.signer: cmds += ["--cfg_selected_signer", self.input.signer] if self.input.qti_sign: cmds += ["--qti_signing"] if self.input.uie_qti: cmds += ["--cfg_UIE_capability", self.input.uie_qti] cmds += ["--cfg_UIE_key", "UIE_QTI"] if self.input.hash_table_algo: cmds += ["--cfg_segment_hash_algorithm", self.input.hash_table_algo] if self.input.signature_digest_algo: cmds += ["--cfg_hash_algorithm", self.input.signature_digest_algo] if self.input.num_root_certs: cmds += ["--cfg_num_root_certs", self.input.num_root_certs] if self.input.max_num_root_certs: cmds += ["--cfg_max_num_root_certs", self.input.max_num_root_certs] if self.input.selected_cert_config: cmds += ["--cfg_selected_cert_config", self.input.selected_cert_config] if self.input.client_id: cmds += ["--cfg_client_id", self.input.client_id] if self.input.lib_id: cmds += ["--cfg_lib_id", self.input.lib_id] if self.input.serial_number: cmds += ["--cfg_serial_number", self.input.serial_number] cmds += ["--cfg_use_serial_number_in_signing", ENABLE] if self.input.multi_serial_numbers: cmds += ["--cfg_multi_serial_numbers", self.input.multi_serial_numbers] if self.input.image_entry: cmds += ["--cfg_image_entry", self.input.image_entry] if self.input.verbatim_config: cmds += ["--verbatim_config"] if self.input.platform_binding: cmds += ["--platform_binding", self.input.platform_binding] # maintain verbosity level across sectools if logger.verbosity == logger.WARN: cmds += ["-z"] elif logger.verbosity == logger.ERROR: cmds += ["-zz"] elif logger.verbosity == logger.DEBUG: cmds += ["-v"] # execute Sectools for each sec_image_policy for policy in self.input.build_policy.sec_image_policies: _cmds = copy.deepcopy(cmds) _cmds += [policy.cmd_options] # set output directory based on policy target_base_dir = c_path.join(self.input.target_base_dir, policy.id) _cmds += ["-o", target_base_dir] try: logger.debug("\nExecuting Sectools...") run_command(_cmds, large_output=True, error_prefix=False) except Exception as e: logger.error(str(e)) raise RuntimeError("Sectools failed") # install and pilsplit sectools's output file self._execute_install(policy)
def _gen_ecdsa_key_pair(self, curve): cmd = [ self.openssl, 'ecparam', '-genkey', '-name', curve, '-outform', 'PEM', '-noout', '-text' ] return run_command(cmd)