def validate_sig(self, to_sign, signature, cert_chain_der, signed_authority=None, extracted_image_attributes=None, imageinfo=None): # Check that openssl is available try: crypto.are_available([crypto.modules.MOD_OPENSSL]) except Exception as e: raise RuntimeError('Cannot validate signing: ' + str(e)) # Get the hash if extracted_image_attributes is None: extracted_image_attributes = self._attribute_extractor( cert_data=cert_chain_der[0], attributes=self.signing_attributes_class()).attributes cert_text = extracted_image_attributes.cert_text cert_sign_algo = crypto.cert.get_sign_algo(cert_text) use_pss = cert_sign_algo == crypto.cert.SIGN_ALGO_RSA_PSS use_dsa = cert_sign_algo == crypto.cert.SIGN_ALGO_ECDSA # Get the hmac params from attestation cert or hash segment hmac_params = self.get_hmac_params_from_cert( extracted_attributes=extracted_image_attributes) if use_dsa: # RSA padding mapping cannot be used to determine # whether HMAC was used or not, so config hmac value must be used logger.debug( "Signer is relying on config's hmac value to determine " "whether signature was generated using HMAC or SHA.") if imageinfo.signing_attributes.hmac: logger.debug( "Signer is assuming that signature was generated using HMAC." ) else: logger.debug( "Signer is assuming that signature was generated using SHA." ) hmac_params = None elif use_pss: hmac_params = None image_hash = Hasher().get_hash( to_sign, hmac_params=hmac_params, sha_algo=extracted_image_attributes.hash_algorithm) # Validate the hash return self.validate_sig_using_hash( image_hash, signature, cert_chain_der, signed_authority=signed_authority, extracted_image_attributes=extracted_image_attributes)
def __init__(self, imageinfo, debug_dir=None, validating=False): # Check that crypto binaries are available try: crypto.are_available([crypto.modules.MOD_OPENSSL]) except Exception as e: raise RuntimeError('Cannot proceed with encryption/decryption: ' + str(e)) BaseEncdec.__init__(self, imageinfo, debug_dir=debug_dir, validating=validating)
def __init__(self, imageinfo, debug_dir=None, validating=False, encrypted_segments_indices=None): try: crypto.are_available([crypto.modules.MOD_ECIESAD]) except Exception as e: raise RuntimeError('Cannot proceed with encryption/decryption: ' + str(e)) super(EncdecUIE2, self).__init__( imageinfo, debug_dir=debug_dir, validating=validating, encrypted_segments_indices=encrypted_segments_indices)
def validate_sig_using_hash(self, image_hash, signature, cert_chain_der, signed_authority=None, extracted_image_attributes=None, message_function=None): # Check that openssl is available try: crypto.are_available([crypto.modules.MOD_OPENSSL]) except Exception as e: raise RuntimeError('Cannot validate signing: ' + str(e)) if extracted_image_attributes is None: extracted_image_attributes = self._attribute_extractor( cert_data=cert_chain_der[0], attributes=self.signing_attributes_class()).attributes cert_sign_algo = crypto.cert.get_sign_algo( extracted_image_attributes.cert_text) use_pss = cert_sign_algo == crypto.cert.SIGN_ALGO_RSA_PSS use_dsa = cert_sign_algo == crypto.cert.SIGN_ALGO_ECDSA if message_function is None: logger.info("Image is signed") else: logger.info(message_function(signed_authority, use_pss, use_dsa)) cert_chain_pem = [] for cert in cert_chain_der: cert_chain_pem.append( crypto.cert.get_cert_in_format(cert, crypto.utils.FORMAT_PEM)) attest_cert, ca_cert_chain = cert_chain_pem[0], '\n'.join( cert_chain_pem[-(len(cert_chain_pem) - 1):]) crypto.cert.validate_cert_chain(attest_cert, ca_cert_chain) public_key = crypto.cert.get_pubkey(attest_cert) if use_dsa: matches = crypto.ecdsa.verify(image_hash, public_key, signature) else: matches = crypto.rsa.verify( image_hash, public_key, signature, padding=crypto.rsa.RSA_PAD_PSS if use_pss else crypto.rsa.RSA_PAD_PKCS, hash_algo=extracted_image_attributes.hash_algorithm) return matches
def validate_sig(self, to_sign, signature, cert_chain_der, signed_authority=None, extracted_image_attributes=None): # Check that openssl is available try: crypto.are_available([crypto.modules.MOD_OPENSSL]) except Exception as e: raise RuntimeError('Cannot validate signing: ' + str(e)) # Get the hash if extracted_image_attributes is None: extracted_image_attributes = AttributeExtractor(cert_data=cert_chain_der[0], hash_segment_metadata=None).attributes cert_text = extracted_image_attributes.cert_text use_pss = crypto.cert.get_sign_algo(cert_text) == crypto.cert.SIGN_ALGO_RSA_PSS # Get the hmac params from attestation cert or hash segment hmac_params = self.get_hmac_params_from_cert(extracted_attributes=extracted_image_attributes) hash_algo = extracted_image_attributes.hash_algorithm image_hash = Hasher().get_hash(to_sign, hmac_params=hmac_params if not use_pss else None, sha_algo=hash_algo) # Validate the hash return self.validate_sig_using_hash(image_hash, signature, cert_chain_der, signed_authority=signed_authority, extracted_image_attributes=extracted_image_attributes)
def sign_hash(self, hash_to_sign, imageinfo, binary_to_sign=None, debug_dir=None, sha_algo=None, binary_to_sign_len=None): # Check that openssl is available try: crypto.are_available([crypto.modules.MOD_OPENSSL]) except Exception as e: raise RuntimeError('Cannot sign: ' + str(e)) # abstract some of the image information signing_attributes = imageinfo.signing_attributes general_properties = imageinfo.general_properties # GET OPENSSL DATA openssl_configfile = self.openssl_info.openssl_config openssl_attest_ca_xts = self.openssl_info.attest_ca_xts openssl_ca_cert_xts = self.openssl_info.ca_cert_xts # GET SIGNING ATTRIBUTE DATA debug_val = int(signing_attributes.debug, 16) if signing_attributes.debug is not None else None multi_serial_numbers = signing_attributes.multi_serial_numbers.serial if signing_attributes.multi_serial_numbers is not None else [] oem_id = int(signing_attributes.oem_id, 16) & 0xFFFF model_id = int(signing_attributes.model_id, 16) & 0xFFFF 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 mask_soc_hw_version = int( signing_attributes.mask_soc_hw_version, 16) if signing_attributes.mask_soc_hw_version is not None else None in_use_soc_hw_version = signing_attributes.in_use_soc_hw_version if signing_attributes.in_use_soc_hw_version is not None else None use_serial_number_in_signing = signing_attributes.use_serial_number_in_signing if signing_attributes.use_serial_number_in_signing is not None else None oem_id_independent = signing_attributes.oem_id_independent if signing_attributes.oem_id_independent is not None else None # GET CERTIFICATE INFORMATION cert_dict = {} cert_dict['id'] = imageinfo.cert_config cert_dict['chip'] = self.config.metadata.chipset cert_dict['keysize'] = general_properties.key_size cert_dict['exponent'] = general_properties.exponent cert_dict['mrc_index'] = general_properties.mrc_index #TODO: Padding is not supported with ECDSA curves cert_dict['padding'] = general_properties.rsa_padding.upper( ) if general_properties.rsa_padding else 'PKCS' cert_dict[ 'hash_algorithm'] = general_properties.hash_algorithm if general_properties.hash_algorithm else 'sha256' # Can't use imageinfo.data_prov_basepath because MockImage can't use it cert_dict['dp_path'] = self.config.data_provisioning.base_path cert_dict['dsa_type'] = general_properties.dsa_type cert_dict['ecdsa_curve'] = general_properties.ecdsa_curve self.cert_data_object = CertData(cert_dict) crypto_params_dict = self.cert_data_object.get_crypto_params() # Create the attestation_certificate_key_pair attestation_certificate_key_pair = None # check if the root cert is using pss # if so and we are creating a new attest cert, the attest cert should use pss #TODO: how do we deal with this in ECDSA? use_pss = general_properties.rsa_padding and general_properties.rsa_padding.lower( ) == 'pss' hash_algorithm = general_properties.hash_algorithm if general_properties.hash_algorithm else 'sha256' logger.info("Using " + ('PSS' if use_pss else 'PKCS') + " RSA padding") 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') priv_key, pub_key = crypto.rsa.gen_keys( signing_attributes.exponent, general_properties.key_size) root_key_pair = { 'private_key': priv_key, 'public_key': pub_key } root_cert = crypto.cert.create_cert( priv_key, subject_params=root_certificate_params, config=openssl_configfile, self_sign=True, hash_algo=hash_algorithm, days=7300, serial=1, sign_algo=crypto.cert.SIGN_ALGO_RSA_PSS if use_pss else crypto.cert.SIGN_ALGO_RSA_PKCS, pad_hash_algo=hash_algorithm) 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' ) priv_key, pub_key = crypto.rsa.gen_keys( signing_attributes.exponent, general_properties.key_size) attestation_ca_certificate_key_pair = { 'private_key': priv_key, 'public_key': pub_key } attestation_ca_certificate_req = crypto.cert.create_cert( priv_key, subject_params=attestation_ca_certificate_params, config=openssl_configfile) attestation_ca_certificate = crypto.cert.sign_cert( attestation_ca_certificate_req, root_cert, root_key_pair['private_key'], extfile=openssl_ca_cert_xts, hash_algo=hash_algorithm, days=7300, serial=1, sign_algo=crypto.cert.SIGN_ALGO_RSA_PSS if use_pss else crypto.cert.SIGN_ALGO_RSA_PKCS, pad_hash_algo=hash_algorithm) 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_oid_supported(signing_attributes) is True: if self.validate_oid_from_config( attestation_ca_certificate_params[ 'certificate_path'], signing_attributes) is False: raise ConfigError("{0} min and max are not set correctly in configuration."\ "Signing will not continue.".format(signing_attributes.object_id.name) ) attestation_certificate_extensions_path = self._generate_attestation_certificate_extensions( openssl_attest_ca_xts, signing_attributes.object_id.name, signing_attributes.object_id.min, signing_attributes.object_id.max) else: attestation_certificate_extensions_path = openssl_attest_ca_xts # Get the binary to sign length if binary_to_sign_len is None: if binary_to_sign is not None: binary_to_sign_len = len(binary_to_sign) else: raise RuntimeError( 'Length of binary could not be computed') logger.info( 'Generating new Attestation certificate and a random key') hmac_params = signerutils.get_hmac_params_from_config( signing_attributes) 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" % binary_to_sign_len + " SW_SIZE" certificate_ou_model_id = "06 " + "%0.4X" % model_id + " MODEL_ID" certificate_hash_alg = self.SHA_OU_MAP[ signing_attributes.hash_algorithm] 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 mask_soc_hw_version is not None: certificate_mask_soc_hw_version = "12 " + "%0.4X" % mask_soc_hw_version + " MASK_SOC_HW_VERSION" certificate_ou.append(certificate_mask_soc_hw_version) if in_use_soc_hw_version == 1: certificate_in_use_soc_hw_version = "13 " + "%0.4X" % in_use_soc_hw_version + " IN_USE_SOC_HW_VERSION" certificate_ou.append(certificate_in_use_soc_hw_version) if use_serial_number_in_signing == 1: certificate_use_serial_number_in_signing = "14 " + "%0.4X" % use_serial_number_in_signing + " USE_SERIAL_NUMBER_IN_SIGNING" certificate_ou.append( certificate_use_serial_number_in_signing) if oem_id_independent == 1: certificate_oem_id_independent = "15 " + "%0.4X" % oem_id_independent + " OEM_ID_INDEPENDENT" certificate_ou.append(certificate_oem_id_independent) certificate_ou_sn_list = [] for index in xrange(0, len(multi_serial_numbers), 6): serial_sublist = multi_serial_numbers[index:index + 6] certificate_sn = "16" for serial in serial_sublist: certificate_sn += " " + serial[2:] # fill last SN OU field with zeros zeros = " 00000000" * (6 - len(serial_sublist)) certificate_sn += zeros certificate_sn += " SN" certificate_ou_sn_list.append(certificate_sn) certificate_ou_sn_list.reverse() certificate_ou.extend(certificate_ou_sn_list) 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: priv_key, pub_key = crypto.rsa.gen_keys( signing_attributes.exponent, general_properties.key_size) attestation_certificate_key_pair = { 'private_key': priv_key, 'public_key': pub_key } # Create the request attestation_certificate_req = crypto.cert.create_cert( attestation_certificate_key_pair['private_key'], subject_params=attestation_certificate_params, config=openssl_configfile) ca_cert, ca_priv_key = ( (attestation_ca_certificate, attestation_ca_certificate_key_pair['private_key']) if num_certs_in_certchain > 2 else (root_cert, root_key_pair['private_key'])) attestation_certificate = crypto.cert.sign_cert( attestation_certificate_req, ca_cert, ca_priv_key, extfile=attestation_certificate_extensions_path, hash_algo=hash_algorithm, days=7300, serial=1, sign_algo=crypto.cert.SIGN_ALGO_RSA_PSS if use_pss else crypto.cert.SIGN_ALGO_RSA_PKCS, pad_hash_algo=hash_algorithm) attestation_certificate = crypto.cert.get_cert_in_format( attestation_certificate, crypto.utils.FORMAT_DER) # Clean temp file if self._is_oid_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.cert.get_cert_in_format( attestation_certificate, crypto.utils.FORMAT_DER) # 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. is_hmac = ishmac(imageinfo) logger.info('Using ' + ('QTI HMAC' if is_hmac else hash_algorithm) + ' for hash segment') hmacParams = self.get_hmac_params_from_cert( crypto.cert.get_text(attestation_certificate)) hash_to_sign = Hasher().get_hash( binary_to_sign, hmac_params=hmacParams if is_hmac else None, sha_algo=sha_algo) signature = crypto.rsa.sign( hash_to_sign, attestation_certificate_key_pair['private_key'], padding=crypto.rsa.RSA_PAD_PSS if use_pss else crypto.rsa.RSA_PAD_PKCS, hash_algo=hash_algorithm) 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.cert.get_cert_in_format( attestation_ca_certificate, crypto.utils.FORMAT_DER) else: attestation_ca_certificate = None root_cert = crypto.cert.get_cert_in_format(root_cert, crypto.utils.FORMAT_DER) root_cert_list = self.cert_data_object.get_rootcerts( general_properties.num_root_certs) 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.cert.create_cert_chain_bin(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.root_key = root_key_pair['private_key'] # Make sure the variable is defined try: attestation_ca_certificate_key_pair except Exception: pass else: signer_output.attestation_ca_key = attestation_ca_certificate_key_pair[ 'private_key'] signer_output.attestation_key = attestation_certificate_key_pair[ 'private_key'] signer_output.hash_to_sign = hash_to_sign return signer_output