def discover_openSSL_implementation(self): logger.debug("Beginning discovery of openssl implementation") logger.debug("Looking for openssl binary") openssl_binaries = self.which_cmd('openssl') if len(openssl_binaries)>0: logger.debug("Found OpenSSL binary at {0}".format(openssl_binaries[0])) import openssl_binary_implementation as openssl_impl if sys.platform!='linux2': openssl_impl.openssl_binary_path=self.relative_path_to_packaged_openssl_binary else: openssl_impl.openssl_binary_path=openssl_binaries[0] if 'OPENSSL_DIR' in os.environ: if sys.platform!='linux2': openssl_impl.openssl_binary_path=os.path.join(os.environ['OPENSSL_DIR'],'openssl.exe') else: openssl_impl.openssl_binary_path=os.path.join(os.environ['OPENSSL_DIR'],'openssl') openssl_impl.ccm_crypto_path=self.relative_path_to_packaged_ccm_binary openssl_impl.cbc_crypto_path=self.relative_path_to_packaged_cbc_binary else: try: logger.debug("Looking for M2Crypto") import M2Crypto as openssl_impl except ImportError: logger.debug("Could not find M2Crypto module") logger.critical("Could not find OpenSSL Implementation") raise RuntimeError("Could not find OpenSSL Implementation") return openssl_impl
def split_certificate_blob_into_certs(certificate_blob): """ Split a binary certificate chain blob into single binary certificates input: certificate_blob: String containing the entire certificate blob output: [cert1, cert2, ...] List of individual certificates found in the blob This function looks for a pattern ('0\x82.{2}0\x82') that marks the beginning of all certs, and splits the blob on these markers. """ offsets=[] certificates_list=[] certificate_start_pattern = r'0\x82.{2}0\x82' for matches in re.finditer(certificate_start_pattern, certificate_blob): offsets.append(matches.start()) logger.debug("Offsets:" + repr(offsets)) for index, offset_val in enumerate(offsets): start_offset = offset_val if index < len(offsets)-1: end_offset = offsets[index+1] else: end_offset = None certificate = certificate_blob[start_offset:end_offset] certificates_list.append(certificate) return certificates_list
def chipsets(self): """(list[str]) List of chipset names supported by the configs in the config dir. """ chipsets = [] for config in self.configs: chipsets.append(config.chipset) logger.debug('Chipsets found from the configs: ' + str(chipsets)) return chipsets
def _get_subject_string_from_certificate_params(certificate_params): subject_list=[] for key in certificate_params: if type(certificate_params[key])==list: for item in certificate_params[key]: subject_list.append(key + '=' + item) continue subject_list.append(key + "=" + certificate_params[key]) logger.debug("Subject List = " + repr(subject_list)) subject_string = r'/'+r"/".join(subject_list) logger.debug("Subject String = " + subject_string) return subject_string
def get_chipset_config_path(self, chipset): """ :param str chipset: chipset to return config file for :returns: config path corresponding to the given chipset :rtype: str """ logger.debug('Searching configs corresponding to chipset: ' + chipset) chipset_dir = c_path.join(self.config_dir, chipset) if c_path.validate_dir(chipset_dir): return self._get_config_path(chipset_dir) raise RuntimeError('Did not find config for chipset: "' + chipset + '"')
def transfer_from_obj(self, obj): """Updates the values of the config root node using the attributes of the object provided. :param Cfg_Secimage obj: Object to be used for obtaining the values. """ assert isinstance(obj, self.obj_module.Cfg_Secimage) logger.debug('Updating config contents using object: ' + obj) self.root = self.transfer_from_obj_to_node(obj, self.root, defines.CONFIG_STRUCTURE, defines.ROOTNODE_NAME) logger.debug('Config contents updated.')
def transfer_to_obj(self, obj): """Updates the attributes of the object provided using the values of the root config node. :params: same as :meth:`transfer_from_obj` """ assert isinstance(obj, self.obj_module.Cfg_Secimage) logger.debug('Updating object using config contents: ' + obj) obj = self.transfer_from_node_to_obj(self.root, obj, defines.CONFIG_STRUCTURE, defines.ROOTNODE_NAME,) logger.debug('Object updated using the config.')
def qcom_hmac(self, data, hmac_params): if data == None or hmac_params == None: raise RuntimeError('Input parameters to the HMAC function are incorrect') else: msm_id = hmac_params.MSM_ID sw_id = hmac_params.SW_ID ipad = 0x3636363636363636 opad = 0x5C5C5C5C5C5C5C5C logger.debug("MSM_ID key : " + repr(msm_id)) logger.debug("SW_ID key : " + repr(sw_id)) logger.debug("ipad : " + repr(ipad)) logger.debug("opad : " + repr(opad)) Si = sw_id ^ ipad Si = binascii.unhexlify(format(Si,'x')) So = msm_id ^ opad So = binascii.unhexlify(format(So,'x')) msg_step1 = hashlib.sha256(data).hexdigest() msg_step1_bin = binascii.a2b_hex(msg_step1) logger.debug2("H(code image) : " + msg_step1) msg_step2 = hashlib.sha256(Si + msg_step1_bin).hexdigest() msg_step2_bin = binascii.a2b_hex(msg_step2) logger.debug2("H[(SWID^ipad) || H(code image)] : " + msg_step2) msg_step3 = hashlib.sha256(So + msg_step2_bin).hexdigest() msg_step3_bin = binascii.a2b_hex(msg_step3) logger.debug2("H[(MSMID^opad) || H[(SWID^ipad) || H(code image)]] : " + msg_step3) hmac = msg_step3_bin return hmac
def verify_certificate_chain(certificate_chain): """ Verify the certificate chain to be valid input: certificate_chain: [cert1,cert2,cert3] List of certificates (*in PEM FORMAT*) in the certificate chain. It assumes that the last certificate is the Root CA certificate. output: [True|False] Boolean value """ CAfile_contents = _create_CAfile_contents_from_cert_chain(certificate_chain) CAfile_tempfile_name=utility_functions.store_data_to_temp_file(CAfile_contents) level1_cert_to_verify_contents = certificate_chain[0] level1_cert_to_verify_tempfile_name=utility_functions.store_data_to_temp_file(level1_cert_to_verify_contents) try: verify_level1_cert_command_out = utility_functions.system_command_logged([openssl_binary_path, 'verify', '-CAfile', CAfile_tempfile_name, level1_cert_to_verify_tempfile_name]) except: logger.critical("verify_certificate_chain: OPENSSL could not verify cert chain") logger.debug("OpenSSL verify command output: " + verify_level1_cert_command_out) logger.debug("Deleting temporary files: " + CAfile_tempfile_name +", " + level1_cert_to_verify_tempfile_name) os.unlink(CAfile_tempfile_name) os.unlink(level1_cert_to_verify_tempfile_name) if verify_level1_cert_command_out.rstrip() == level1_cert_to_verify_tempfile_name + ": OK": logger.debug("The certificate chain is verified") return True else: logger.debug("The certificate chain is not verified") return False
def sign(self, signingpackage_fname, outputdir): signaturepackage_binary = None cmds = self._getCmds(signingpackage_fname, outputdir) cass_server = self.cass_signer_attributes.server.host if self.cass_signer_attributes.server else "default CASS server" logger.info("Connecting to {0}".format(cass_server)) output = self._executeCmds(cmds) logger.debug(output) signaturepackage_filepath = os.path.join(outputdir, self.SIGNATUREPACKPAGE_RELPATH) if os.path.isfile(signaturepackage_filepath): logger.info("Signature package retrieved from server.") signaturepackage_binary = c_misc.load_data_from_file(signaturepackage_filepath) #clean up path, filename = os.path.split(signaturepackage_filepath) shutil.rmtree(path) return signaturepackage_binary
def get_public_key_from_certificate(certificate): if 'BEGIN CERTIFICATE' not in certificate: certificate = cert_der_to_pem(certificate) pubkey=_extract_public_key_from_certificate(certificate) pubkey_file_name=utility_functions.store_data_to_temp_file(pubkey) command_list=[openssl_binary_path,'rsa','-pubin','-inform','PEM','-text','-noout','<',pubkey_file_name] logger.debug("Command_list = " + repr(command_list)) pubkey_text = utility_functions.system_command_logged(command_list, stderr_to_temp=True) logger.debug2("Pubkey text: " + pubkey_text) os.unlink(pubkey_file_name)
def _generate_signing_package(self, hash_to_sign, signing_attributes, cass_signer_attributes, image_path, signingpackage_fname, binary_to_sign): signingpackage = SigningPackage(secimage.__version__) signingrequest = signingpackage.createSigningRequest("image_to_sign=%s" % image_path) hexbindigest = binascii.b2a_hex(hash_to_sign) logger.debug("Digest to sign (hexbinary)= [%s]" % hexbindigest) signingrequest.setDigest(hexbindigest) signingrequest.setCapability(cass_signer_attributes.capability) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_SIZE, "0x%.8X" % len(binary_to_sign)) hmac_params = signerutils.get_hmac_params_from_config(signing_attributes) signingrequest.setSigningAttribute(Certificate.SIGNATTR_HW_ID, "0x%s" % hmac_params.msm_id_str) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_ID, signing_attributes.sw_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_MODEL_ID, signing_attributes.model_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_OEM_ID, signing_attributes.oem_id) if signing_attributes.debug: signingrequest.setSigningAttribute(Certificate.SIGNATTR_DEBUG, signing_attributes.debug) if signing_attributes.app_id: signingrequest.setSigningAttribute(Certificate.SIGNATTR_APP_ID, signing_attributes.app_id) if signing_attributes.crash_dump: signingrequest.setSigningAttribute(Certificate.SIGNATTR_CRASH_DUMP, signing_attributes.crash_dump) if self._is_tcg_supported(signing_attributes) is True: signingrequest.setSigningAttribute(Certificate.SIGNATTR_TCG_MIN, signing_attributes.tcg_min) signingrequest.setSigningAttribute(Certificate.SIGNATTR_TCG_MAX, signing_attributes.tcg_max) else: #opendsp does not CASS_SIGNATTR_USE_EXP3 currently if signing_attributes.exponent == 3: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'TRUE') elif signing_attributes.exponent == 65537: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'FALSE') else: raise RuntimeError, "Exponent value of {0} is invalid!".format(signing_attributes.exponent) # Set signature algorithm to SHA256 by default signingrequest.setSigningAttribute(Certificate.SIGNATTR_SHA256, 'TRUE') pathname, fname = os.path.split(signingpackage_fname) c_path.create_dir(pathname) signingpackage.toxml() signingpackage.saveToFile(signingpackage_fname) logger.info("Signing package created. Digest = [%s]" % signingpackage.getDigest()) return signingpackage
def privkey_pem_to_der(pem_privkey): """ Convert PEM format PRIVATE key into DER format input: pem_privkey: String containing base64 PEM Private key output der_privkey: String containing binary Private key """ pem_tempfile_name = utility_functions.store_data_to_temp_file(pem_privkey) try: der_privkey = utility_functions.system_command_logged([openssl_binary_path, 'rsa', '-in', pem_tempfile_name, '-inform', 'PEM', '-outform', 'DER'], stderr_to_temp=True) except: logger.critical("privkey_pem_to_der: OPENSSL Could not convert PEM key to DER key") logger.debug2("PEM Format private key: " + hexdump(der_privkey)) logger.debug("Deleting temporary file: " + pem_tempfile_name) os.unlink(pem_tempfile_name) return der_privkey
def privkey_der_to_pem(der_privkey): """ Convert binary DER format PRIVATE key into base64 coded ASCII PEM format input: der_privkey: String containing binary PRIVATE KEY output pem_privkey: String containing base64 PEM PRIVATE KEY """ der_tempfile_name = utility_functions.store_data_to_temp_file(der_privkey) try: pem_privkey = utility_functions.system_command_logged([openssl_binary_path, 'rsa', '-in', der_tempfile_name, '-inform', 'DER', '-outform', 'PEM'], stderr_to_temp=True) except: logger.critical("privkey_der_to_pem: OPENSSL Could not convert DER key to PEM") logger.debug2("PEM Format Private Key: " + pem_privkey) logger.debug("Deleting temporary file: " + der_tempfile_name) os.unlink(der_tempfile_name) return pem_privkey
def cert_pem_to_der(pem_certificate): """ Convert PEM format certificate into DER format input: pem_certificate: String containing base64 PEM certificate output der_certificate: String containing binary certificate """ pem_tempfile_name = utility_functions.store_data_to_temp_file(pem_certificate) try: der_certificate = utility_functions.system_command_logged([openssl_binary_path, 'x509', '-in', pem_tempfile_name, '-inform', 'PEM', '-outform', 'DER'], stderr_to_temp=True) except: logger.critical("cert_pem_to_der: OPENSSL could not convert PEM cert to DER") logger.debug2("PEM Format certificate: " + hexdump(der_certificate)) logger.debug("Deleting temporary file: " + pem_tempfile_name) os.unlink(pem_tempfile_name) return der_certificate
def cert_der_to_pem(der_certificate): """ Convert binary DER format certificate into base64 coded ASCII PEM format input: der_certificate: String containing binary certificate output pem_certificate: String containing base64 PEM certificate """ der_tempfile_name = utility_functions.store_data_to_temp_file(der_certificate) try: pem_certificate = utility_functions.system_command_logged([openssl_binary_path, 'x509', '-in', der_tempfile_name, '-inform', 'DER', '-outform', 'PEM'], stderr_to_temp=True) except: logger.critical("cert_der_to_pem: OPENSSL could not convert DER cert to PEM") logger.debug2("PEM Format certificate: " + pem_certificate) logger.debug("Deleting temporary file: " + der_tempfile_name) os.unlink(der_tempfile_name) return pem_certificate
def _process_signature_package(self, signaturepackage, signingpackage, signature_result_file): signaturePackage = SignaturePackage(signaturepackage) logger.debug("Signing package digest from Signature Package = [%s]" % signaturePackage.getSPDigest()) if (signaturePackage.getSPDigest().lower() != signingpackage.getDigest().lower()): raise ExternalSignerError, "Signing Package Digest mismatched from Signature Package!" if signaturePackage.getCount() == 1: signatureResponse = signaturePackage.getSignatureResponse(1) else: raise ExternalSignerError, "Signature Package has unexpected count = %d!" % signaturePackage.getCount() statusCode = signatureResponse.getStatusCode() logger.debug("Status returned from Signature Response: %s" % statusCode) if statusCode == "1": signatureResponse.saveResultToFile(signature_result_file) else: raise ExternalSignerError, "Error returned from Signature Response:\n%s" % signatureResponse.getError()
def __init__(self, data, debug_dir=None, debug_prefix=None, debug_suffix=None, ): # Public properties self.debug_dir = debug_dir self.debug_prefix = debug_prefix self.debug_suffix = debug_suffix # Store the original image self.store_debug_data(df.FILE_DATA_IN, data) """ Extract the various segments/sections of the data: 1. Elf header 2. Prog headers 3. Bin """ # Extract the header self.ehdr = extract_ehdr(data) self.store_debug_data(df.FILE_HDR_IN, self.ehdr.pack()) self.store_debug_data(df.FILE_HDR_IN_REPR, repr(self.ehdr), suffix=df.FILE_HDR_IN_REPR_SUFFIX) # Extract the program headers self.phdrs = extract_phdrs(data, self.ehdr) self.store_debug_data(df.FILE_PHDR_IN, pack_phdrs(self.phdrs)) self.store_debug_data(df.FILE_PHDR_IN_REPR, repr_phdrs(self.phdrs), suffix=df.FILE_PHDR_IN_REPR_SUFFIX) # Dump the individual segments self.segments = extract_segments(data, self.phdrs) for idx, phdr in enumerate(self.phdrs): length = len(self.segments[phdr]) is_load = self._segment_to_put(phdr) if length >= 0 and length <= 16: logger.debug(('' if is_load else 'Non-') + 'Loadable segment - ' + str(idx + 1) + ' is of size: ' + str(length)) if is_load and (length > 0 and length <= 16): logger.warning(('' if is_load else 'Non-') + 'Loadable segment - ' + str(idx + 1) + ' is of size: ' + str(length)) self.store_debug_data(df.FILE_SEGMENT_IN.format(idx), self.segments[phdr]) # Zero out the sections for now zero_out_sections(self.ehdr)
def get_rootcerts(self): root_cert_list = [] for i in range(0, self.general_properties.num_root_certs): config_cert_name = self.cert_config.multirootcert.root_cert_name root_cert_path_to_replace = os.path.join(self.cert_config.multirootcert.directory, config_cert_name) root_cert_path = self.replace_macros( root_cert_path_to_replace, exponent=str(self.signing_attributes.exponent), key_size=str(self.general_properties.key_size), index=str(i)) if os.path.isfile(root_cert_path) is False: err_str = "certificate_path does not exist: {0}!".format(root_cert_path) raise RuntimeError(err_str) root_cert = c_misc.load_data_from_file(root_cert_path) root_cert_list.append(root_cert) logger.debug('Package root cert {0}: {1}'.format(i, root_cert_path)) return root_cert_list
def query_data_path(self, T1_namespace, T2_namespace, T3_namespace, asset_tag): query_result = self.data_prov.query(T1_namespace, T2_namespace, T3_namespace)[0] # check if asset folder has been found correctly # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# if not query_result.config: raise RuntimeError('DataProvisioner: ' + c_path.join(query_result.path, 'config.xml') + ' is not found') # check if config.xml is valid # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# try: asset_file_name = str( getattr(query_result.config.METACONFIG, asset_tag)) except Exception: raise RuntimeError('DataProvisioner: ' + asset_tag + ' is not found in config.xml') return 'ERROR' # Inject the mrc_index into file string before the period # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# asset_file_name = string.replace(asset_file_name, '.', str(self.cert_mrc_index) + '.') # check if asset file exists # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~# asset_file_path = os.path.join(query_result.path, asset_file_name) asset_file_path = os.path.normpath(asset_file_path) if not c_path.validate_file(asset_file_path): raise RuntimeError('DataProvisioner: ' + asset_file_path + ' is not found') self.log_once(asset_tag + " = " + asset_file_path) logger.debug("DataProvisioner config: " + str(query_result.config)) return asset_file_path
def gen_rsa_key_pair(key_size_in_bits, key_exponent, priv_key_output_file, pub_key_output_file): """ Generate RSA Key pair input: key_size_in_bits: Size of the key in bits. key_exponent: [3, 65537] Exponent used in key calculation. priv_key_output_file: File name for storing private key pub_key_output_file: File name for storing public key output: returned value: {"public_key": [Generated public key], "private_key": [Generated private key] } Dictionary holding the values of public and private keys """ logger.debug("the openssl_binary is:{0}".format(openssl_binary_path)) if key_exponent==3: exponent_str="-3" elif key_exponent == 65537: exponent_str="-f4" else: logger.warning("Exponent value supplied is INVALID! going with default exponent of 65537.") exponent_str="-f4" key_size_str=str(key_size_in_bits) if priv_key_output_file is not None: pk_file=open(priv_key_output_file,"wb") else: pk_file=tempfile.NamedTemporaryFile(delete=False) logger.debug("No output file specified for private key storage, so creating temp file: " + pk_file.name) try: private_key = utility_functions.system_command_logged([openssl_binary_path, "genrsa", exponent_str, key_size_str], stderr_to_temp=True) except subprocess.CalledProcessError, e: logger.critical("gen_rsa_key_pair: OPENSSL Errored out on generation of RSA key.") logger.critical("call to OpenSSL binary returned an error!: retval = " + str(e.returncode) + " Command = " + str(e.cmd)) raise RuntimeError("call to OpenSSL binary returned an error!: retval = " + str(e.returncode) + " Command = " + str(e.cmd))
def _create_sigining_request(certificate_params, key_pair, days=7300, configfile="opensslroot.cfg"): """ Create a CSR (Certificate Signing Request) input: certificate_params ={ 'C' : "US", 'ST' : "California", 'L' : "San Diego", 'O' : "ASIC", 'CN' : "Qualcomm", } Dictionary of parameters to put in the certificate. The parameters above are an example key_pair = None | key_pair = {"public_key": [Generated public key], "private_key": [Generated private key] } Dictionary holding the values of public and private keys. If this is None, a key is generated. days = validity period of certificate in days configfile = configfile used by openssl output: certificate_request: String representation of PEM certificate signing request (CSR). key_pair : {"public_key": [Generated public key], "private_key": [Generated private key] } """ subject_string = _get_subject_string_from_certificate_params(certificate_params) if key_pair == None: logger.debug("No key pair provided, will generate a key RSA 2048 bits") key_tempfile_name="certificate.key" command_list=[openssl_binary_path, "req", "-new", "-nodes", "-keyout", key_tempfile_name, "-subj", subject_string, "-newkey", "rsa:2048", "-days", str(days), "-config", configfile] else: key_tempfile_name =utility_functions.store_data_to_temp_file(key_pair['private_key']) command_list = [openssl_binary_path, "req", "-new", "-key", key_tempfile_name, "-subj", subject_string, "-days", str(days), "-config", configfile] logger.debug("Command List: " + repr(command_list)) return _execute_openssl_certificate_command(command_list, key_pair, key_tempfile_name)
def _create_self_signed_certificate(certificate_params, key_pair, days, configfile, serial_num): """ Create a self signed certificate input: certificate_params ={ 'C' : "US", 'ST' : "California", 'L' : "San Diego", 'O' : "ASIC", 'CN' : "Qualcomm", } Dictionary of parameters to put in the certificate. The parameters above are an example key_pair = None | key_pair = {"public_key": [Generated public key], "private_key": [Generated private key] } Dictionary holding the values of public and private keys. If this is None, a key is generated. days = validity period of certificate in days configfile = configfile used by openssl serial_num = Serial number of certificate output: certificate: String representation of PEM certificate. key_pair : {"public_key": [Generated public key], "private_key": [Generated private key] } """ subject_string = _get_subject_string_from_certificate_params(certificate_params) if key_pair == None: logger.debug("No key pair provided, will generate a key RSA 2048 bits") key_tempfile_name="certificate.key" command_list = [openssl_binary_path, "req", "-new", "-x509", "-keyout", key_tempfile_name, "-subj", subject_string, "-newkey", "rsa:2048", "-days", str(days), "-config", configfile, "-set_serial", str(serial_num), "-sha256"] else: key_tempfile_name =utility_functions.store_data_to_temp_file(key_pair['private_key']) command_list = [openssl_binary_path, "req", "-new", "-key", key_tempfile_name, "-x509", "-subj", subject_string, "-days", str(days), "-config", configfile, "-set_serial", str(serial_num), "-sha256"] return _execute_openssl_certificate_command(command_list, key_pair, key_tempfile_name)
def get_env_build_policy(environment): # get the supported build policies from the policy file supported_build_policies = sectools_builder_core.BuildPolicy.get_supported_build_policies( DEFAULT_POLICY_FILE) enabled_env_build_policies = [] # get the enabled build policy from the environment using the ids from the supported build policies for policy in supported_build_policies: if environment.get("USES_SEC_POLICY_" + policy.upper()): logger.debug("Found build policy environment variable {0}".format( "USES_SEC_POLICY_" + policy.upper())) enabled_env_build_policies.append(policy) elif environment.get("SEC_POLICY_" + policy.upper()): logger.debug("Found build policy environment variable {0}".format( "SEC_POLICY_" + policy.upper())) enabled_env_build_policies.append(policy) elif environment.get(policy.upper()): logger.debug("Found build policy environment variable {0}".format( policy.upper())) enabled_env_build_policies.append(policy) elif environment.get(policy): logger.debug( "Found build policy environment variable {0}".format(policy)) enabled_env_build_policies.append(policy) if not enabled_env_build_policies: logger.info( "No environmental build policy variable was enabled nor was one provided as a command line argument. Sectools will not be executed." ) logger.info( "If execution of Sectools is desired, a build policy must be set in the environment or passed as a command line argument. Supported build policies are: {0}" .format(", ".join(supported_build_policies).upper())) return None elif len(enabled_env_build_policies) > 1: error_message = "The following environmental build policy variables are enabled: {0}. Only one build policy can be enabled at a time.".format( ", ".join(enabled_env_build_policies).upper()) logger.error(error_message) raise RuntimeError(error_message) else: logger.debug( "Successfully retrieved build policy {0} from environment".format( enabled_env_build_policies[0].upper())) return enabled_env_build_policies[0]
def config_paths(self): """(list[tuple(str)]) List of the config paths found in the workspace conforming to the naming structure. """ config_dir = self.config_dir config_paths = [] logger.debug('Searching config path sets in dir: ' + config_dir) for entry in os.listdir(config_dir): path = c_path.join(config_dir, entry) if c_path.validate_dir(path): config = self._get_config_path(path) if config: config_paths.append(config) else: logger.debug2('Skipping dir: ' + entry + '\n' ' ' + 'Does not contain any configs') else: logger.debug2('Skipping file in first level: ' + entry) logger.debug('Config paths found from the config dir: ' + str(config_paths)) return config_paths
def config_paths(self): """(list[tuple(str)]) List of the config paths found in the workspace conforming to the naming structure. """ config_dir = self.config_dir config_paths = [] logger.debug('Searching config path sets in dir: ' + config_dir) for entry in os.listdir(config_dir): path = c_path.join(config_dir, entry) if c_path.validate_dir(path): oem, qc, ui, user = self._get_config_paths(path) if oem or qc or ui or user: config_paths.append((oem, qc, ui, user)) else: logger.debug2('Skipping dir: ' + entry + '\n' ' ' + 'Does not contain any configs') else: logger.debug2('Skipping file in first level: ' + entry) logger.debug('Config paths found from the config dir: ' + str(config_paths)) return config_paths
def _apply_attribute_overrides(self): if self.attributes_to_override and len( self.attributes_to_override) > 0: for key, value in self.attributes_to_override.iteritems(): if key in self.attribute_dict.keys(): # add new entry to dictionary self.attribute_dict.update(value) # remove old dictionary entry if key != value.keys()[0]: del self.attribute_dict[key] logger.debug( "Overrode CASS signing request's \"{0}\" attribute with {1}." .format(key, value)) else: raise RuntimeError( "Attempted to override CASS signing request's \"{0}\" attribute with \"{1}\" but \"{0}\" is not an attribute of CASS signing request.\n" "If you would like to add \"{1}\" to CASS signing request's attributes, add {2} to the dictionary created in _create_attributes_to_add" .format(key, value.keys()[0], value)) else: logger.debug("No CASS signing request attributes were overridden.")
def get_signing_request_class(self, cass_capability): logger.debug("CASS capability set to \"{0}\"".format(cass_capability)) signing_requests = self.get_map() supported_capabilities = list() # search for a signing request that supports the specified cass capability for signing_request_id, signing_request_class in signing_requests.iteritems( ): supported_capabilities.extend( signing_request_class.get_supported_capabilities()) if cass_capability in signing_request_class.get_supported_capabilities( ): return signing_request_class # no signing request was found that supports the specified cass capability so default to secure boot 2 signing request logger.debug("\"{0}\" is not a pre-configured CASS capability.\n". format(cass_capability) + "The pre-configured CASS capabilities are: " + ", ".join(supported_capabilities)) logger.info( "Using CASS Secure Boot 2 signing request for CASS capability \"{0}\"" .format(cass_capability)) return signing_request_secure_boot_2.SecureBoot2SigningRequest
def build(self): logger.debug("Executing SectoolsBuilderCore.build()") # construct build policy object based on selected build_policy_id if self.input.build_policy is None and self.input.build_policy_id is None: logger.error("A build policy was not provided. Sectools execution, installation, and pilsplitting will be skipped.") elif self.input.build_policy is None: logger.debug("Constructing BuildPolicy based on selected build_policy_id...") self.input.build_policy = BuildPolicy(self.input.policy_file, self.input.build_policy_id, self.input.sign_id, self.input.sectools_install_base_dir, self.input.additional_secimage_policy_ids) logger.debug("\n\nConstructed BuildPolicy:\n" + str(self.input.build_policy) + "\n") # either call sectools and proceed with installation and pilsplitting or return SCons callback to build method if self.input.execute_sectools: # update config file with relocatable value self._generate_config_file() # validate files and paths errors = [] validate_file(self.input.source, "source", errors) validate_dir(self.input.target_base_dir, "target_base_dir", errors) validate_dir(self.input.sectools_install_base_dir, "sectools_install_base_dir", errors) validate_dir(self.input.pilsplitter_target_base_dir, "pilsplitter_target_base_dir", errors) if errors: err_string = "\n".join(errors) logger.error(err_string) raise RuntimeError(err_string) # drive sign, install, and pilsplit sequence self._execute_sign() else: # return SCons callback to build method return self._scons_callback()
def data_to_sign(self): # Backup the parsegen backup = _BackupMbnParsegen(self._mbn_parsegen) # Set the current attributes if self.authority == defines.AUTHORITY_QC: self._mbn_parsegen.sign = self._data_signature self._mbn_parsegen.cert_chain = self._cert_chain self._mbn_parsegen.sign_qc = self._data_signature_qc self._mbn_parsegen.cert_chain_qc = self._cert_chain_qc # Set padding info self._mbn_parsegen.set_pad_info(self.sig_size, self.cert_chain_size) # Update version number before applying signature # if SECBOOT_MBN_HDR[ self.secboot_version] == self._mbn_parsegen.header.get_version( ): logger.debug("Updating version to " + str(self._mbn_parsegen.header.get_version())) self._mbn_parsegen.header.set_version_in_bin( self._mbn_parsegen.header.get_version()) else: raise RuntimeError( 'Version check failed. MBN header version (%s) does not match expected version (%s).' % (str(self._mbn_parsegen.header.get_version()), str(SECBOOT_MBN_HDR[self.secboot_version]))) # Get the data to sign (header + code) retval = self._mbn_parsegen.get_header( self.authority).pack() + self._mbn_parsegen.code # Clear padding info self._mbn_parsegen.set_pad_info(0, 0) # Restore the parsegen backup.restore(self._mbn_parsegen) return retval
def get_image_info_from_meta(cls, meta_info): # Get a list of all files tagged with sign_id meta_images_list = meta_info.get_files_detailed('sign_id') for image in meta_images_list: try: logger.debug('Found image from meta_build for signing: ' + image.sign_id) source_path = None dest_path = None for each_path in image.file_path: if source_path is None: if getattr(each_path, 'sign_source', False): source_path = each_path.value if dest_path is None: if getattr(each_path, 'sign_dest', False): dest_path = each_path.value if source_path and dest_path: break if source_path is None or dest_path is None: raise RuntimeError('SourcePath, DestPath should not be missing.') sign_id = image.sign_id chipset = image.chipset image_src_path = ImagePath() image_dest_path = DestImagePath() image_src_path.image_dir_base = image.image_dir_base image_src_path.image_dir_ext = source_path image_src_path.image_name = image.file_name[0].value image_dest_path.image_dir_base = image.image_dir_base image_dest_path.image_dir_ext = dest_path image_dest_path.image_name = image.file_name[0].value except Exception as e: logger.error(str(e)) continue yield (sign_id, chipset, image_src_path, image_dest_path)
def _sign_csr_with_CA_certificate(certificate_signing_request, CA_certificate, CA_key_pair, days, serial_num, extfile_name): """ Sign a Certificate signing request with a higher level CA certificate input: certificate_signing_request: String form of CSR CA_certificate: String representation of a higher level CA certificate CA_key_pair : {"public_key": [Generated public key], "private_key": [Generated private key] } The key pair of the CA_certificate days = validity period of certificate in days serial_num = Serial number of certificate extfile_name = Name of the extensions file to be used by openssl output: CA_signed_certificate: String representation of CA Signed certificate (PEM) CA_key_pair: {"public_key": CA public key, "private_key": CA private key } """ CA_certificate_tempfile_name =utility_functions.store_data_to_temp_file(CA_certificate) CA_privkey_tempfile_name = utility_functions.store_data_to_temp_file(CA_key_pair['private_key']) certificate_signing_request_tempfile_name = utility_functions.store_data_to_temp_file(certificate_signing_request) command_list=[openssl_binary_path, "x509", "-req", "-in", certificate_signing_request_tempfile_name, "-CAkey", CA_privkey_tempfile_name, "-CA", CA_certificate_tempfile_name, "-days", str(days), "-set_serial", str(serial_num), "-extfile", extfile_name, "-sha256"] logger.debug("Command_list = " + repr(command_list)) CA_signed_certificate = utility_functions.system_command_logged(command_list, stderr_to_temp=True) logger.debug("Generated Output of openssl certificate command: " + CA_signed_certificate) os.unlink(CA_certificate_tempfile_name) os.unlink(CA_privkey_tempfile_name) os.unlink(certificate_signing_request_tempfile_name) return (CA_signed_certificate, CA_key_pair)
def _generate_signing_package(self, hash_to_sign, signing_attributes, cass_signer_attributes, image_path, signingpackage_fname, binary_to_sign): signingpackage = SigningPackage(secimage.__version__) signingrequest = signingpackage.createSigningRequest("image_to_sign=%s" % image_path) hexbindigest = binascii.b2a_hex(hash_to_sign) logger.debug("Digest to sign (hexbinary)= [%s]" % hexbindigest) signingrequest.setDigest(hexbindigest) signingrequest.setCapability(cass_signer_attributes.capability) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_SIZE, "0x%.8X" % len(binary_to_sign)) hmac_params = signerutils.get_hmac_params_from_config(signing_attributes) signingrequest.setSigningAttribute(Certificate.SIGNATTR_HW_ID, "0x%s" % hmac_params.msm_id_str) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_ID, signing_attributes.sw_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_MODEL_ID, signing_attributes.model_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_OEM_ID, signing_attributes.oem_id) if signing_attributes.debug: signingrequest.setSigningAttribute(Certificate.SIGNATTR_DEBUG, signing_attributes.debug) if signing_attributes.app_id: signingrequest.setSigningAttribute(Certificate.SIGNATTR_APP_ID, signing_attributes.app_id) if signing_attributes.crash_dump: signingrequest.setSigningAttribute(Certificate.SIGNATTR_CRASH_DUMP, signing_attributes.crash_dump) if signing_attributes.exponent == 3: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'TRUE') elif signing_attributes.exponent == 65537: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'FALSE') else: raise RuntimeError, "Exponent value of {0} is invalid!".format(signing_attributes.exponent) # Set signature algorithm to SHA256 by default signingrequest.setSigningAttribute(Certificate.SIGNATTR_SHA256, 'TRUE') pathname, fname = os.path.split(signingpackage_fname) c_path.create_dir(pathname) signingpackage.toxml() signingpackage.saveToFile(signingpackage_fname) logger.info("Signing package created. Digest = [%s]" % signingpackage.getDigest()) return signingpackage
def get_image_info_from_meta(cls, meta_info): # Get a list of all files tagged with sign_id meta_images_list = meta_info.get_files_detailed('sign_id') for image in meta_images_list: try: logger.debug('Found image from meta_build for signing: ' + image.sign_id) source_path = None dest_path = None for each_path in image.file_path: if source_path is None: if getattr(each_path, 'sign_source', False): source_path = each_path.value if dest_path is None: if getattr(each_path, 'sign_dest', False): dest_path = each_path.value if source_path and dest_path: break if source_path is None or dest_path is None: raise RuntimeError('SourcePath, DestPath should not be missing.') sign_id = image.sign_id chipset = image.chipset image_src_path = ImagePath() image_dest_path = DestImagePath() image_src_path.image_dir_base = image.image_dir_base image_src_path.image_dir_ext = source_path image_src_path.image_name = image.file_name[0].value image_dest_path.image_dir_base = image.image_dir_base image_dest_path.image_dir_ext = dest_path image_dest_path.image_name = image.file_name[0].value except Exception as e: logger.error(str(e)) continue yield (sign_id, chipset, image_src_path, image_dest_path, MetaError.SUCCESS)
def _get_hmacparams_from_certificate_subject_dictionary(certificate_subject_dictionary): """ Return a dictionary of the HMAC params from the certificate subject dictionary input: certificate_subject_dictionary = dictionary of subject params from certificate output: hmac_params = Dictionary of HMAC parameters from certificate subject """ sw_id_re=re.compile(r'01 ([0-9A-F]{16}) SW_ID') hw_id_re=re.compile(r'02 ([0-9A-F]{16}) HW_ID') if 'OU' in certificate_subject_dictionary.keys() and type(certificate_subject_dictionary['OU'])==list: certificate_subject_dictionary['OU'].sort() sw_id_element = sw_id_re.match(certificate_subject_dictionary['OU'][0]) hw_id_element = hw_id_re.match(certificate_subject_dictionary['OU'][1]) if sw_id_element == None: logger.critical("Error in certificate subject. SW_ID field not found. Not a valid certificate. Exiting") raise RuntimeError("Error in certificate subject. SW_ID field not found. Not a valid certificate. Exiting") elif hw_id_element == None: logger.critical("Error in certificate subject. HW_ID field not found. Not a valid certificate. Exiting") raise RuntimeError("Error in certificate subject. HW_ID field not found. Not a valid certificate. Exiting") else: logger.debug("Valid certificate: Found SW_ID and HW_ID") sw_id_text = sw_id_element.group(1) hw_id_text = hw_id_element.group(1) logger.debug('SW_ID = ' + sw_id_text) logger.debug('HW_ID = ' + hw_id_text) hw_id_int = int(hw_id_text, 16) sw_id_int = int(sw_id_text, 16) hmac_params = HmacParams(hw_id_int, sw_id_int) return hmac_params
def verify(self): '''verifies self.database is correct. Checks for type/bin file mismatch. bin files not in level 3. Lack of binfiles. Too many binfiles. Etc.Some things are implicitly verified by the file handler, like existence of files/folders and correct paths, since it can't create the database with bad paths :raises: RuntimeError ''' if len(self.database.files) > 0: raise RuntimeError( "DataProvisioner: binary files {0} exist within security_policy level of Data Provisioning file structure" ).format(self.database.files) for lvl1_name, lvl1_obj in self.database.children.items(): if len(lvl1_obj.files) > 0: raise RuntimeError( "DataProvisioner: binary files {0} exists within security_policy_type level of Data Provisioning file structure" ).format(lvl1_obj.files) for lvl2_name, lvl2_obj in lvl1_obj.children.items(): if len(lvl2_obj.files) > 0: raise RuntimeError( "DataProvisioner: binary files {0} exists within data_prov_id level of Data Provisioning file structure" ).format(lvl2_obj.files) for lvl3_name, lvl3_obj in lvl2_obj.children.items(): # if len(lvl3_obj.files) == 0: # raise RuntimeError("DataProvisioner: there are no binary files in data_prov_id of Data Provisioning file structure. {0}".format(lvl3_obj.path)) for file_name in lvl3_obj.files: if c_path.validate_dir(file_name): raise RuntimeError( "DataProvisioner: Directories are not allowed within the data_prov_id directory of the Data Provisioning file structure" ) logger.debug("DataProvisioner database verification passed") return True
def _get_rootcerts_from_config(self, cert_config, num_root_certs): root_cert_list = [] if cert_config.multirootcert: for i in range(0, num_root_certs): config_cert_name = cert_config.multirootcert.root_cert_name cert_name = signerutils.macro_replace(config_cert_name, "index", str(i), isMandatory=True) root_cert_path = os.path.join( cert_config.multirootcert.directory, cert_name) if os.path.isfile(root_cert_path) is False: err_str = "certificate_path does not exist: {0}!".format( root_cert_path) raise RuntimeError(err_str) root_cert = c_misc.load_data_from_file(root_cert_path) root_cert_list.append(root_cert) logger.debug('Package root cert {0}: {1}'.format( i, root_cert_path)) return root_cert_list
def invokeSecImage(self, args, input_filename, dest_config): sign_id = self._get_sign_id() cmds = [ "secimage", "-g", sign_id, "-i", input_filename, "-c", dest_config, "-o", os.path.join(args.output_dir, SECIMAGE_OUTPUTDIR) ] if args.verbose: cmds.append("-v") if args.debug: cmds.append("-d") if args.validate: cmds.append("-a") else: cmds.append("-sa") logger.debug("""\nExecute command: python sectools.py {0}\n""".format(' '.join(cmds))) return self._executeCmds(cmds, args.verbose or args.debug)
def _generate_new_encryption_params_blob(self): self.l1_key = self._get_l1_key() self.l2_key = self._get_l2_key() self.l3_key = self._get_l3_key() encryption_params_hdr = EncryptionParamsHeader() encryption_params_hdr.add_encryption_param_section() eps_hdr1 = EncryptionParamsSectionHdr(None, None, 1, 0) eps_body1 = EncryptionParamsSectionBody(l1_key_blob=self.l1_key, image_id_bitmap=self.image_id) self.encryption_params_blob = encryption_params_hdr.get_header_blob() + \ eps_hdr1.get_header_blob() + \ eps_body1.get_binary_blob() self.l3_image_iv = eps_body1.get_image_iv() self.l3_key = eps_body1.get_l3_key() logger.debug("Encryption Params: \n" + hexdump(self.encryption_params_blob)) logger.debug("L1 Key: \n" + hexdump(self.l1_key)) return self.encryption_params_blob, self.l1_key
def discover_openSSL_implementation(self): logger.debug("Beginning discovery of openssl implementation") logger.debug("Looking for openssl binary") openssl_binaries = self.which_cmd('openssl') if len(openssl_binaries)>0: logger.debug("Found OpenSSL binary at {0}".format(openssl_binaries[0])) import openssl_binary_implementation as openssl_impl if sys.platform!='linux2': openssl_impl.openssl_binary_path=self.relative_path_to_packaged_openssl_binary else: openssl_impl.openssl_binary_path=openssl_binaries[0] openssl_impl.ccm_crypto_path=self.relative_path_to_packaged_ccm_binary openssl_impl.cbc_crypto_path=self.relative_path_to_packaged_cbc_binary else: try: logger.debug("Looking for M2Crypto") import M2Crypto as openssl_impl except ImportError: logger.debug("Could not find M2Crypto module") logger.critical("Could not find OpenSSL Implementation") raise RuntimeError("Could not find OpenSSL Implementation") return openssl_impl
def get_signing_request_class(self, cass_capability, secboot_version, sw_id): logger.debug("CASS capability set to \"{0}\"".format(cass_capability)) signing_requests = self.get_map() supported_capabilities = list() secboot_version_signing_request_id_map = {} # search for a signing request that supports the specified cass capability for signing_request_id, signing_request_class in signing_requests.items( ): supported_capabilities.extend( signing_request_class.get_supported_capabilities()) secboot_version_signing_request_id_map[ signing_request_class.get_secboot_version( )] = signing_request_id if cass_capability in signing_request_class.get_supported_capabilities( ): return signing_request_class # no signing request was found that supports the specified cass capability so print supported capabilities logger.debug("\"{0}\" is not a pre-configured CASS capability\n". format(cass_capability) + "The pre-configured CASS capabilities are: " + ", ".join(supported_capabilities)) # For MBNv3 SPSS images use SBL2 Engine img_id = extract_image_id_from_sw_id(sw_id) if (img_id == SP_MCP_SW_ID or img_id == SP_APPS_SW_ID) and secboot_version == SECBOOT_VERSION_1_0: secboot_version = SECBOOT_VERSION_2_0 logger.info( "Using CASS Secure Boot {0} signing request for CASS capability \"{1}\"" .format(secboot_version, cass_capability)) try: return signing_requests[ secboot_version_signing_request_id_map[secboot_version]] except KeyError: raise RuntimeError( "CASS Signer does not support Secboot version {0}".format( secboot_version))
def _execute_pilsplit(self, file_to_pilsplit, pilsplit_prefix, subdirectory): logger.debug("\nPilsplitting Sectools's output file...") if self.input.pilsplitter_target_base_dir: # Attempt pilsplit 3 times before failing pilsplit_successful = False for i in range(3): try: if subdirectory: subdir = c_path.join( self.input.pilsplitter_target_base_dir, subdirectory) c_path.create_dir(subdir) prefix = c_path.join(subdir, pilsplit_prefix) else: subdir = self.input.pilsplitter_target_base_dir prefix = c_path.join( self.input.pilsplitter_target_base_dir, pilsplit_prefix) SecImageCore.pil_split(file_to_pilsplit, prefix) except: # Pilsplitting failed so retry pilsplit continue pilsplit_successful = True logger.info( "Pilsplitted \"{0}\" into directory \"{1}\"".format( file_to_pilsplit, subdir)) break if not pilsplit_successful: error_message = "Failed to pilsplit \"{0}\"".format( file_to_pilsplit) logger.error(error_message) raise RuntimeError(error_message) else: logger.info( "Pilsplit was skipped because a value for pilsplitter_target_base_dir was not provided" )
def _execute_install(self, policy): logger.debug("\nInstalling Sectools's output file...") if self.input.sectools_install_base_dir: path, filename = os.path.split(self.input.source) chipset = SecImageConfigParser(self.input.config).root.metadata.get_chipset() src = c_path.normalize(c_path.join(self.input.target_base_dir, policy.id, chipset, self.input.sign_id, filename)) for install_location in policy.install_locations: if self.input.install_file_name: dest = c_path.join(install_location, self.input.install_file_name) else: dest = c_path.join(install_location, filename) try: c_path.create_dir(install_location) install_successful, error = c_path.copy_file(src, dest, None, True) if not install_successful: logger.error(error) except RuntimeError as e: logger.error(str(e)) install_successful = False if not install_successful: error_message = "Failed to install \"{0}\" to \"{1}\"".format(src, dest) logger.error(error_message) raise RuntimeError(error_message) logger.info("Installed \"{0}\" to \"{1}\"".format(src, dest)) # pilsplit sectools's output file pilsplit_subdirectory = "" if install_location != self.input.sectools_install_base_dir: pilsplit_subdirectory = install_location.replace(os.path.join(self.input.sectools_install_base_dir, "", ""), "") pilsplit_prefix = self.input.install_file_name.split(".")[0] if self.input.install_file_name else filename.split(".")[0] self._execute_pilsplit(dest, pilsplit_prefix, pilsplit_subdirectory) else: logger.info("Installation was skipped because a value for sectools_install_base_dir was not provided") if self.input.pilsplitter_target_base_dir: logger.info("Pilsplitting was skipped because a value for sectools_install_base_dir was not provided")
def verify_certificate_chain(certificate_chain): """ Verify the certificate chain to be valid input: certificate_chain: [cert1,cert2,cert3] List of certificates (*in PEM FORMAT*) in the certificate chain. It assumes that the last certificate is the Root CA certificate. output: [True|False] Boolean value """ CAfile_contents = _create_CAfile_contents_from_cert_chain( certificate_chain) CAfile_tempfile_name = utility_functions.store_data_to_temp_file( CAfile_contents) level1_cert_to_verify_contents = certificate_chain[0] level1_cert_to_verify_tempfile_name = utility_functions.store_data_to_temp_file( level1_cert_to_verify_contents) try: verify_level1_cert_command_out = utility_functions.system_command_logged( [ openssl_binary_path, 'verify', '-CAfile', CAfile_tempfile_name, level1_cert_to_verify_tempfile_name ]) except: logger.critical( "verify_certificate_chain: OPENSSL could not verify cert chain") os.unlink(CAfile_tempfile_name) os.unlink(level1_cert_to_verify_tempfile_name) raise RuntimeError( "verify_certificate_chain: OPENSSL could not verify cert chain") logger.debug("OpenSSL verify command output: " + verify_level1_cert_command_out) logger.debug("Deleting temporary files: " + CAfile_tempfile_name + ", " + level1_cert_to_verify_tempfile_name) os.unlink(CAfile_tempfile_name) os.unlink(level1_cert_to_verify_tempfile_name) if verify_level1_cert_command_out.rstrip( ) == level1_cert_to_verify_tempfile_name + ": OK": logger.debug("The certificate chain is verified") return True else: logger.debug("The certificate chain is not verified") return False
def privkey_der_to_pem(der_privkey): """ Convert binary DER format PRIVATE key into base64 coded ASCII PEM format input: der_privkey: String containing binary PRIVATE KEY output pem_privkey: String containing base64 PEM PRIVATE KEY """ der_tempfile_name = utility_functions.store_data_to_temp_file(der_privkey) try: pem_privkey = utility_functions.system_command_logged( [ openssl_binary_path, 'rsa', '-in', der_tempfile_name, '-inform', 'DER', '-outform', 'PEM' ], stderr_to_temp=True) except: logger.critical( "privkey_der_to_pem: OPENSSL Could not convert DER key to PEM") logger.debug2("PEM Format Private Key: " + pem_privkey) logger.debug("Deleting temporary file: " + der_tempfile_name) os.unlink(der_tempfile_name) return pem_privkey
def query_data_prov(self, level1_namespace, level2_namespace, level3_namespace, asset_tag, return_file_path=False): query_result = self.data_prov.query(level1_namespace, level2_namespace, level3_namespace)[0] '''check if config.xml exists''' if not query_result.config: raise RuntimeError('DataProvisioner: ' + c_path.join(query_result.path, 'config.xml') + ' is not found') '''check if config.xml is valid''' try: asset_file_name = str(getattr(query_result.config.METACONFIG, asset_tag)) except Exception: raise RuntimeError('DataProvisioner: ' + asset_tag + ' is not found in config.xml') '''check if asset file exists''' asset_file_path = os.path.join(query_result.path, asset_file_name) if not c_path.validate_file(asset_file_path): raise RuntimeError('DataProvisioner: ' + asset_file_path + ' is not found') self.log_once(asset_tag + " = " + asset_file_path) logger.debug("DataProvisioner config: " + str(query_result.config)) if return_file_path: return asset_file_path else: return query_result.files[asset_file_name]
def read(self, xml_path, config_xml_path=None): import auto_gen_fm_config import auto_gen_fmconf_config try: self.path = c_path.normalize(xml_path) self.config_path = c_path.normalize(config_xml_path) # load the FM config data if(self.config_path is not None): c_config.CoreConfig.__init__(self.core_fmconfig, auto_gen_fmconf_config, self.config_path) self.filtermethod = self.core_fmconfig.root.filterType.method else: # TODO: change default to None or error out, check with Maria self.filtermethod = 'all' # populate the FM data model self._populate(self.path, auto_gen_fm_config, self.core_config) except Exception: logger.debug('fuseMasterData: Exception raised') raise
def _scons_callback(self): logger.debug("Creating SCons callback...") scons_targets = get_scons_targets(self.input) if self.input.target_image_type_filter is not None: logger.debug( "Filtering SCons target list to only include {0} images...". format(target_name_map[self.input.target_image_type_filter])) logger.debug("SCons target list before filtering: {0}".format( scons_targets)) scons_targets = scons_targets[self.input.target_image_type_filter] logger.debug( "SCons target list after filtering: {0}".format(scons_targets)) return self.input.environment.builder_function_handler( scons_targets, self.input.source, INPUT=self.input)
def get_rootcerts(self): root_cert_list = [] for i in range(0, self.general_properties.num_root_certs): config_cert_name = self.cert_config.multirootcert.root_cert_name root_cert_path_to_replace = os.path.join( self.cert_config.multirootcert.directory, config_cert_name) root_cert_path = self.replace_macros( root_cert_path_to_replace, exponent=str(self.signing_attributes.exponent), key_size=str(self.general_properties.key_size), index=str(i)) if os.path.isfile(root_cert_path) is False: err_str = "certificate_path does not exist: {0}!".format( root_cert_path) raise RuntimeError(err_str) root_cert = c_misc.load_data_from_file(root_cert_path) root_cert_list.append(root_cert) logger.debug('Package root cert {0}: {1}'.format( i, root_cert_path)) return root_cert_list
def privkey_pem_to_der(pem_privkey): """ Convert PEM format PRIVATE key into DER format input: pem_privkey: String containing base64 PEM Private key output der_privkey: String containing binary Private key """ pem_tempfile_name = utility_functions.store_data_to_temp_file(pem_privkey) try: der_privkey = utility_functions.system_command_logged( [ openssl_binary_path, 'rsa', '-in', pem_tempfile_name, '-inform', 'PEM', '-outform', 'DER' ], stderr_to_temp=True) except: logger.critical( "privkey_pem_to_der: OPENSSL Could not convert PEM key to DER key") logger.debug2("PEM Format private key: " + hexdump(der_privkey)) logger.debug("Deleting temporary file: " + pem_tempfile_name) os.unlink(pem_tempfile_name) return der_privkey
def main(args): """Parses the command line arguments, performs any basic operations based on the parsed arguments and starts processing using the dpc module. """ # Log to file log_to_file(args.output_dir) # Print the tool's launch command logger.debug('\n\n DebugPolicy launched as: "' + ' '.join(sys.argv) + '"\n') # Initialize DebugPolicyCore dpc = DebugPolicyCore(debug=args.debug) # Configure DebugPolicyCore if args.dbgp_config_path: dpc.dbgp_config = args.dbgp_config_path if args.secimage_config_path: dpc.secimage_config = args.secimage_config_path if args.platform: dpc.dbgp_config, dpc.secimage_config = get_chipset_mode_config(args.platform) if args.input_file: dpc.set_input_file(args.input_file) if args.output_dir: dpc.output_dir = args.output_dir # Process dpc.process(verify_setup=args.verify_inputs, generate=args.generate, sign=args.sign, validate=args.validate) # Print summary of operations print_summary()
def generate_new_cert(self, cert_type, cert_info, prev_cert_info, extfile=None, self_sign=False, padding=PAD_PKCS): # Update the subject parameters subject_params = self.create_subject_params(cert_type, cert_info.params.params) # Generate the certificate request cert_req, priv_key, pub_key = self.generate_cert_request( cert_type, cert_info, subject_params, self_sign=self_sign, key_exp=self.signing_attributes.exponent, key_size=self.signing_attributes.key_size, padding=padding) # Settle on the extfile if extfile is None: extfile = cert_info.extfile # Sign the certificate request if not self_sign: logger.debug('Signing certificate request for ' + cert_type) cert = self.sign_cert_request(cert_req, prev_cert_info, extfile, padding=padding) else: cert = cert_req return cert, priv_key, pub_key
def _validate_tcg_raw(self, tcg_min_attest, tcg_max_attest, tcg_min_ca, tcg_max_ca): tcg_ok = False if (self.config.general_properties.num_certs_in_certchain == 2) and \ (self.config.signing.signature_format == "opendsp"): logger.info( "2-level certificate chain is not supported for opendsp signature" ) return False if tcg_min_attest is not None: assert (isinstance(tcg_min_attest, BaseAttribute)) if tcg_max_attest is not None: assert (isinstance(tcg_max_attest, BaseAttribute)) if tcg_min_ca is not None: assert (isinstance(tcg_min_ca, BaseAttribute)) if tcg_max_ca is not None: assert (isinstance(tcg_max_ca, BaseAttribute)) if ((tcg_min_attest is None) and (tcg_max_attest is None) and (tcg_min_ca is None) and (tcg_max_ca is None)): # This is ok. No TCGs in attest cert. tcg_ok = True logger.debug( "\nNo TCGs found in Attestation cert or CA cert. This is OK.") elif ((tcg_min_attest is not None) and (tcg_max_attest is not None) and (tcg_min_ca is None) and (tcg_max_ca is None)): logger.info( "\nTCGs found in Attestation cert, but not in CA cert. This is invalid." ) elif ((tcg_min_attest is None) and (tcg_max_attest is None) and (tcg_min_ca is not None) and (tcg_max_ca is not None)): logger.info( "\nNo TCGs found in Attestation cert, but there are TCGs in CA cert. This is invalid." ) elif ((tcg_min_attest is not None) and (tcg_max_attest is not None) and (tcg_min_ca is not None) and (tcg_max_ca is not None)): if (tcg_min_ca.value <= tcg_min_attest.value <= tcg_max_attest.value <= tcg_max_ca.value): tcg_ok = True logger.debug("\nTCG values fall within CA constraints.") else: logger.info("\nTCG values are outside the CA constraints.") else: logger.info("\nInvalid TCG values") tcg_log_mesg = "\nAttestation cert : tcg_min={0} tcg_max={1}". \ format(tcg_min_attest, tcg_max_attest) + \ "\nCA cert (allowed): tcg_min={0} tcg_max={1}\n". \ format(tcg_min_ca, tcg_max_ca) if (tcg_ok is False): logger.info(tcg_log_mesg) else: logger.debug(tcg_log_mesg) return tcg_ok
def gen_keys(self, exponent, keysize, priv_key_path=None, pub_key_path=None): # Generate the key pair using openssl priv_key = self._gen_rsa_key_pair(exponent, keysize) # Save the private key to file priv_path = priv_key_path if priv_key_path is not None else c_path.create_tmp_file() # Generate the public key file try: logger.debug('Writing generated private key to PEM file: ' + priv_path) c_path.store_data_to_file(priv_path, priv_key) # Extract the public key from the private key pub_key = self.get_public_key_from_private(priv_key) finally: # Cleanup temp file c_path.remove_tmp_file(priv_path) # Save the public key to file if pub_key_path is not None: logger.debug('Writing generated public key to PEM file: ' + pub_key_path) c_path.store_data_to_file(pub_key_path, pub_key) return priv_key, pub_key
def _validate_tcg_raw(self, tcg_min_attest, tcg_max_attest, tcg_min_ca, tcg_max_ca): tcg_ok = False if (self.config.general_properties.num_certs_in_certchain == 2) and \ (self.config.signing.signature_format == "opendsp"): logger.info("2-level certificate chain is not supported for opendsp signature") return False if tcg_min_attest is not None: assert(isinstance(tcg_min_attest, BaseAttribute)) if tcg_max_attest is not None: assert(isinstance(tcg_max_attest, BaseAttribute)) if tcg_min_ca is not None: assert(isinstance(tcg_min_ca, BaseAttribute)) if tcg_max_ca is not None: assert(isinstance(tcg_max_ca, BaseAttribute)) if ((tcg_min_attest is None) and (tcg_max_attest is None) and (tcg_min_ca is None) and (tcg_max_ca is None)): # This is ok. No TCGs in attest cert. tcg_ok = True logger.debug("\nNo TCGs found in Attestation cert or CA cert. This is OK.") elif ((tcg_min_attest is not None) and (tcg_max_attest is not None) and (tcg_min_ca is None) and (tcg_max_ca is None)): logger.info("\nTCGs found in Attestation cert, but not in CA cert. This is invalid.") elif ((tcg_min_attest is None) and (tcg_max_attest is None) and (tcg_min_ca is not None) and (tcg_max_ca is not None)): logger.info("\nNo TCGs found in Attestation cert, but there are TCGs in CA cert. This is invalid.") elif ((tcg_min_attest is not None) and (tcg_max_attest is not None) and (tcg_min_ca is not None) and (tcg_max_ca is not None)): if (tcg_min_ca.value <= tcg_min_attest.value <= tcg_max_attest.value <= tcg_max_ca.value): tcg_ok = True logger.debug("\nTCG values fall within CA constraints.") else: logger.info("\nTCG values are outside the CA constraints.") else: logger.info("\nInvalid TCG values") tcg_log_mesg = "\nAttestation cert : tcg_min={0} tcg_max={1}". \ format(tcg_min_attest, tcg_max_attest) + \ "\nCA cert (allowed): tcg_min={0} tcg_max={1}\n". \ format(tcg_min_ca, tcg_max_ca) if (tcg_ok is False): logger.info(tcg_log_mesg) else: logger.debug(tcg_log_mesg) return tcg_ok
def _validate_attributes_with_tcg_rule(self, attest_cert_obj): isValid = True #Enforce TCG rules attributes_zero_list = [ Certificate.SIGNATTR_SW_ID, Certificate.SIGNATTR_HW_ID, Certificate.SIGNATTR_OEM_ID, Certificate.SIGNATTR_MODEL_ID, ] attributes_none_list = [ Certificate.SIGNATTR_APP_ID, Certificate.SIGNATTR_CRASH_DUMP, Certificate.SIGNATTR_ROT_EN, ] if attest_cert_obj.tcg_min and attest_cert_obj.tcg_max: #Only enforce TCG rules currently for attr_name in attributes_zero_list: attr = attest_cert_obj.get_attr(attr_name) if attr.value != 0: logger.debug("{0} should be 0 under TCG validation rules. Current value is {1}".\ format(attr_name, attr.str)) isValid = False for attr_name in attributes_none_list: attr = attest_cert_obj.get_attr(attr_name) if attr != None: logger.debug("{0} should be None under TCG validation rules. Current value is {1}".\ format(attr_name, attr.str)) isValid = False attr = attest_cert_obj.get_attr(Certificate.SIGNATTR_DEBUG) if attr is not None and attr.value != DEBUG_DISABLED: logger.debug("{0} should be 2 under TCG validation rules. Current value is {1}".\ format(Certificate.SIGNATTR_DEBUG, attr.str)) isValid = False return isValid
if len(args) > 1: feature = args[1] for supported_feature in FEATURES_LIST: if feature == supported_feature.CMD_ARG_TOOL_NAME: supported_feature.main(supported_feature.parse_args(sys.argv[1:])) break else: raise RuntimeError('Feature provided from command line: "' + feature + '" is invalid.' + '\n' ' ' + 'Please choose from : ' + str([f.CMD_ARG_TOOL_NAME for f in FEATURES_LIST])) if __name__ == '__main__': try: # Check that the command line are valid and are normalized. args = SectoolsParser().pos_args main(args) except Exception: logger.debug(traceback.format_exc()) logger.error(sys.exc_info()[1]) sys.exit(1) except KeyboardInterrupt: print logger.error('Keyboard Interrupt Received. Exiting!') sys.exit(1) sys.exit(0)
def _sign(self, hash_to_sign, cert_config, signing_attributes, general_properties, binary_to_sign): openssl_config_file_paths = self.config.signing.signer_attributes.local_signer_attributes.openssl_config_inputs self._validate_config(cert_config, general_properties, openssl_config_file_paths) # Obtain all the information from the signing_attributes debug_val = int(signing_attributes.debug, 16) if signing_attributes.debug is not None else None msm_part = int(signing_attributes.msm_part, 16) oem_id = int(signing_attributes.oem_id, 16) model_id = int(signing_attributes.model_id, 16) num_certs_in_certchain = general_properties.num_certs_in_certchain app_id = int(signing_attributes.app_id, 16) if signing_attributes.app_id is not None else None crash_dump = int(signing_attributes.crash_dump, 16) if signing_attributes.crash_dump is not None else None rot_en = int(signing_attributes.rot_en, 16) if signing_attributes.rot_en is not None else None # Create the crypto_params_dict self.certconfig_parser = CertConfigParser(cert_config, signing_attributes, general_properties) crypto_params_dict = self.certconfig_parser.get_crypto_params() hmac_params = signerutils.get_hmac_params_from_config(signing_attributes) # Create the attestation_certificate_key_pair attestation_certificate_key_pair = None root_certificate_params = crypto_params_dict['root_certificate_properties'] root_certificate_params_is_valid, generate_new_root_certificate = self._validate_certificate_params_dict(root_certificate_params) if root_certificate_params_is_valid: if generate_new_root_certificate: logger.info('Generating new Root certificate and a random key') generated_root_key_pair = crypto_functions.gen_rsa_key_pair(general_properties.key_size, key_exponent=signing_attributes.exponent) root_cert, root_key_pair = crypto_functions.create_root_certficate(root_certificate_params, generated_root_key_pair, 7300, openssl_config_file_paths.openssl_configfile_path, 1) else: logger.info('Using a predefined Root certificate and a predefined key') logger.info('Key Used: '+ root_certificate_params['private_key_path']) logger.info('Certificate Used: '+ root_certificate_params['certificate_path']) root_cert, root_key_pair = self._get_certificate_and_key_pair_from_files(root_certificate_params) else: logger.error("Root certificate params are invalid! Please check config file.") raise RuntimeError("Root certificate params are invalid! Please check config file.") if num_certs_in_certchain > 2: logger.debug("Generating Attestation CA certificate, since certchain size is greater than 2") attestation_ca_certificate_params = crypto_params_dict['attest_ca_certificate_properties'] attestation_ca_params_is_valid, generate_new_attestation_ca = self._validate_certificate_params_dict(attestation_ca_certificate_params) if attestation_ca_params_is_valid: if generate_new_attestation_ca: logger.info('Generating new Attestation CA certificate and a random key') generated_attestation_ca__key_pair = crypto_functions.gen_rsa_key_pair(general_properties.key_size, key_exponent=signing_attributes.exponent) attestation_ca_certificate, attestation_ca_certificate_key_pair = \ crypto_functions.create_certificate(attestation_ca_certificate_params, generated_attestation_ca__key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=openssl_config_file_paths.ca_certificate_extensions_path) else: logger.info('Using a predefined Attestation CA certificate and a predefined key') logger.info('Key Used: '+ attestation_ca_certificate_params['private_key_path']) logger.info('Certificate Used: '+ attestation_ca_certificate_params['certificate_path']) attestation_ca_certificate, attestation_ca_certificate_key_pair = self._get_certificate_and_key_pair_from_files(attestation_ca_certificate_params) else: logger.error("Attestation CA certificate params are invalid! Please check config file.") raise RuntimeError("Attestation CA certificate params are invalid! Please check config file.") attestation_certificate_params = crypto_params_dict['attest_certificate_properties'] attestation_certificate_params_is_valid, generate_new_attestation_certificate = self._validate_certificate_params_dict(attestation_certificate_params) if attestation_certificate_params_is_valid: if generate_new_attestation_certificate: #TCG support if self._is_tcg_supported(signing_attributes) is True: if self.validate_tcg_from_config(attestation_ca_certificate_params['certificate_path'], signing_attributes) is False: raise ConfigError("tcg_min and tcg_max are not set correctly in configuration."\ "Signing will not continue." ) attestation_certificate_extensions_path = self._generate_attestation_certificate_extensions( openssl_config_file_paths.attestation_certificate_extensions_path, signing_attributes.tcg_min, signing_attributes.tcg_max) else: attestation_certificate_extensions_path = openssl_config_file_paths.attestation_certificate_extensions_path logger.info('Generating new Attestation certificate and a random key') certificate_ou_sw_id ="01 " + hmac_params.sw_id_str + " SW_ID" certificate_ou_hw_id ="02 " + hmac_params.msm_id_str + " HW_ID" certificate_ou_oem_id ="04 " + "%0.4X" % oem_id + " OEM_ID" certificate_ou_sw_size ="05 " + "%0.8X" % len(binary_to_sign) + " SW_SIZE" certificate_ou_model_id ="06 " + "%0.4X" % model_id + " MODEL_ID" certificate_hash_alg = "07 0001 SHA256" certificate_ou = [ certificate_ou_sw_id, certificate_ou_hw_id, certificate_ou_oem_id, certificate_ou_sw_size, certificate_ou_model_id, certificate_hash_alg ] #Optional attributes if debug_val is not None: certificate_ou_debug_id ="03 " + "%0.16X" % debug_val + " DEBUG" certificate_ou.append(certificate_ou_debug_id) if app_id is not None: certificate_app_id = "08 " + "%0.16X" % app_id + " APP_ID" certificate_ou.append(certificate_app_id) if crash_dump is not None: certificate_crash_dump = "09 " + "%0.16X" % crash_dump + " CRASH_DUMP" certificate_ou.append(certificate_crash_dump) if rot_en is not None: certificate_rot_en = "10 " + "%0.16X" % rot_en + " ROT_EN" certificate_ou.append(certificate_rot_en) if 'OU' in attestation_certificate_params.keys(): if type(attestation_certificate_params['OU'])==list: for item in attestation_certificate_params['OU']: certificate_ou.append(item) else: certificate_ou.append(attestation_certificate_params['OU']) attestation_certificate_params['OU']=certificate_ou if attestation_certificate_key_pair is None: attestation_certificate_key_pair = crypto_functions.gen_rsa_key_pair(key_exponent=signing_attributes.exponent, key_size_in_bits = general_properties.key_size) if num_certs_in_certchain > 2: #sign the attestation cert with the attestation_ca_cert attestation_certificate, attestation_certificate_key_pair = \ crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, attestation_ca_certificate, attestation_ca_certificate_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=attestation_certificate_extensions_path) else: #sign the attestation cert with the root cert attestation_certificate, attestation_certificate_key_pair = \ crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=attestation_certificate_extensions_path) attestation_certificate = crypto_functions.cert_pem_to_der(attestation_certificate) #Clean temp file if self._is_tcg_supported(signing_attributes) is True: c_path.clean_file(attestation_certificate_extensions_path) else: #generate_new_attestation_certificate == False logger.info('Using a predefined Attestation certificate and a predefined key') logger.info('Key Used: '+ attestation_certificate_params['private_key_path']) logger.info('Certificate Used: '+ attestation_certificate_params['certificate_path']) attestation_certificate, attestation_certificate_key_pair = self._get_certificate_and_key_pair_from_files(attestation_certificate_params) attestation_certificate = crypto_functions.cert_pem_to_der(attestation_certificate) # Since the get_hmac_params_from_certificate_chain always works with the first cert in the cert chain, # this function will work for a single der certificate as well. hmac_params = crypto_functions.get_hmacparams_from_certificate_chain(attestation_certificate) hasher = Hasher() hash_to_sign=hasher.qcom_hmac(binary_to_sign, hmac_params) signature = crypto_functions.encrypt_with_private_key(hash_to_sign, attestation_certificate_key_pair['private_key']) else: logger.error("Attestation certificate params are invalid! Please check config file.") raise RuntimeError("Attestation certificate params are invalid! Please check config file.") if num_certs_in_certchain > 2: attestation_ca_certificate = crypto_functions.cert_pem_to_der(attestation_ca_certificate) else: attestation_ca_certificate = None root_cert = crypto_functions.cert_pem_to_der(root_cert) root_cert_list = self.certconfig_parser.get_rootcerts() certificate_list = self._get_certificate_list(general_properties.num_root_certs, num_certs_in_certchain, attestation_certificate, attestation_ca_certificate, root_cert, root_cert_list) cert_chain=crypto_functions.create_certificate_chain(certificate_list) signer_output = SignerOutput() signer_output.root_cert = root_cert signer_output.attestation_ca_cert = attestation_ca_certificate signer_output.attestation_cert = attestation_certificate signer_output.signature = signature signer_output.cert_chain = cert_chain signer_output.root_cert_list = root_cert_list signer_output.attestation_key = attestation_certificate_key_pair['private_key'] return signer_output