def encrypt(self, message, key, iv): """ Function to encrypt binary with a CBC 128 bit cipher. input: binary_blob: Binary blob to encrypt hex_preexisting_128_bit_key: hex representation of 128bit key | None, if None, the key is generated hex_preexisting_iv: hex representation of image IV | None, if None, the IV is generated output: (encrypted_binary, encryption_key, image_iv): Tuple with the encrypted binary, the key, and the IV """ 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.openssl, 'enc', '-aes-128-cbc', '-in', message_path, '-out', encrypted_message_path, '-K', key, '-iv', iv, '-nopad' ] run_command(cmd) return c_path.load_data_from_file(encrypted_message_path) finally: if message_path is not None: c_path.remove_tmp_file(message_path) if encrypted_message_path is not None: c_path.remove_tmp_file(encrypted_message_path)
def decrypt(self, message, key, iv): """ Function to decrypt a CBC encrypted binary. input: encrypted_blob: Encrypted Binary blob to decrypt hex_preexisting_128_bit_key: hex representation of 128bit key hex_preexisting_iv: hex representation of image IV output: plaintext_binary: Decrypted plaintext binary """ 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', '-aes-128-cbc', '-d', '-in', message_path, '-out', decrypted_message_path, '-K', key, '-iv', iv, '-nopad' ] run_command(cmd) return c_path.load_data_from_file(decrypted_message_path) finally: if message_path is not None: c_path.remove_tmp_file(message_path) if decrypted_message_path is not None: c_path.remove_tmp_file(decrypted_message_path)
def validate_cert_chain(self, root_cert, ca_cert_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 """ ca_cert_chain_path, root_cert_path = None, None try: ca_cert_chain_path = c_path.create_tmp_file(ca_cert_chain) root_cert_path = c_path.create_tmp_file(root_cert) cmd = [ self.openssl, 'verify', '-CAfile', ca_cert_chain_path, root_cert_path ] validity = run_command(cmd).rstrip() return validity == (root_cert_path + ': OK') finally: if ca_cert_chain_path is not None: c_path.remove_tmp_file(ca_cert_chain_path) if root_cert_path is not None: c_path.remove_tmp_file(root_cert_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 encrypt(self, message, key, iv, aad): """ Function to encrypt binary with a CCM 128 bit cipher. input: binary_blob: Binary blob to encrypt hex_preexisting_128_bit_key: hex representarion of 128bit key | None, if None, the key is generated hex_preexisting_iv: hex representarion of image IV | None, if None, the IV is generated hex_preexisting_aad: hex representation of Additional Authentication data needed by the algorithm output: (encrypted_binary, encryption_key, image_iv, hex_preexisting_aad): Tuple with the encrypted binary, the key, the IV, and the 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_cbc, '--operation=encrypt', '--input-file', message_path, '--output', encrypted_message_path, '--key', key, '--iv', iv, '--aad', aad ] run_command(cmd) return c_path.load_data_from_file(encrypted_message_path) finally: if message_path is not None: c_path.remove_tmp_file(message_path) if encrypted_message_path is not None: c_path.remove_tmp_file(encrypted_message_path)
def verify(self, message, key, signature): """ Decrypt and verify an encrypted message using a public key and signature :param message: message to verify :param key: public key :param signature: signature :return verified: boolean outcome of verification :rtype: bool """ signature = EcdsaOpenSSLImpl.strip_sig_padding(signature) expected_retcode = 1 message_path = c_path.create_tmp_file(message) key_path = c_path.create_tmp_file(key) signature_path = c_path.create_tmp_file(signature) cmd = ([ self.openssl, OPENSSL_PKEYUTL_MODE, '-verify', '-pubin', '-inkey', key_path, '-sigfile', signature_path, '-in', message_path ]) try: output = run_command(cmd, expected_retcode) if output.strip() == 'Signature Verified Successfully': return True else: return False finally: c_path.remove_tmp_file(message_path) c_path.remove_tmp_file(key_path) c_path.remove_tmp_file(signature_path)
def decrypt(self, message, key, iv, aad): """ Function to decrypt a CCM encrypted binary. input: encrypted_blob: Encrypted Binary blob to decrypt hex_preexisting_128_bit_key: hex representarion of 128bit key hex_preexisting_iv: hex representarion of image IV hex_preexisting_aad: hex representation of Additional Authentication data needed by the algorithm output: plaintext_binary: Decrypted plaintext binary """ 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, '--operation=decrypt', '--input-file', message_path, '--output', decrypted_message_path, '--key', key, '--iv', iv, '--aad', aad ] run_command(cmd) return c_path.load_data_from_file(decrypted_message_path) finally: if message_path is not None: c_path.remove_tmp_file(message_path) if decrypted_message_path is not None: c_path.remove_tmp_file(decrypted_message_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 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 verify(self, message, key, signature, padding=RsaBase.RSA_PAD_PSS, hash_algo=RsaBase.RSA_HASH_SHA256, salt_len=RsaBase.RSA_PAD_PSS_SALT_1): """ Decrypt an encrypted message with a public key input: encrypted_message = String representation of encrypted message public_key = String representation of public key output: message = String representing decrypted message """ padding_opt = self._get_pad_opt(OPENSSL_PKEYUTL_MODE, padding) hash_opt = self._get_hash_opt(hash_algo) pad_opts = [] signature_path = None if padding == RsaBase.RSA_PAD_PSS: signature_path = c_path.create_tmp_file(signature) pad_opts += ['-sigfile', signature_path, '-pkeyopt', 'rsa_pss_saltlen:' + salt_len, '-pkeyopt', 'digest:' + hash_opt] try: output = self._pkeyutl(message, key, ['-verify', '-pubin'], ['-pkeyopt', 'rsa_padding_mode:'+padding_opt], expected_retcode=1) if output.strip() == 'Signature Verified Successfully': return True else: return False finally: if signature_path is not None: c_path.remove_tmp_file(signature_path)
def verify(self, message, key, signature, padding=RsaBase.RSA_PAD_PSS, hash_algo=RsaBase.RSA_HASH_SHA256, salt_len=RsaBase.RSA_PAD_PSS_SALT_1): # Create options for the rsa operation pad_opts = [ '-pkeyopt', 'rsa_padding_mode:' + self._get_pad_opt(OPENSSL_PKEYUTL_MODE, padding) ] if padding == self.RSA_PAD_PSS: hash_opt = self._get_hash_opt(hash_algo) pad_opts += [ '-pkeyopt', 'rsa_pss_saltlen:' + salt_len, '-pkeyopt', 'digest:' + hash_opt ] signature_path = c_path.create_tmp_file(signature) pad_opts = ['-sigfile', signature_path] + pad_opts # Return if message matches signature try: expected_retcode = 0 if OpenSSLDiscoveryImpl.is_supported_version( self.openssl, min_version=OPENSSL_PKEYUTL_FIXED_VERSION_MIN) else 1 output = self._pkeyutl(message, key, ['-verify', '-pubin'], pad_opts, expected_retcode=expected_retcode) return 'Signature Verified Successfully' in output finally: c_path.remove_tmp_file(signature_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 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 _generate_pkcs11_cfg(self, token_driver_home): pkcs11_cfg_template_data = ensure_str(c_misc.load_data_from_file(self.PKCS11_CFG_TEMPLATE)) pkcs11_cfg_data = signerutils.macro_replace(pkcs11_cfg_template_data, "token_driver_home", token_driver_home, isMandatory=True) return c_path.create_tmp_file(data=pkcs11_cfg_data)
def _decode_encryption_parameters_blob(self, encryption_params_blob, private_key): encryption_params_blob = self.extract_encryption_parameters( encryption_params_blob)[1] tmp_config_file_path = c_path.create_tmp_file( data=encryption_params_blob) encryption_params_parser = CoreConfig(auto_gen_ssd_xml_config, tmp_config_file_path).root encrypted_image_encryption_key_base64 = encryption_params_parser.MD_SIGN[ 0].IEK_ENC_INFO[0].IEK_CIPHER_VALUE encrypted_image_encryption_key = binascii.a2b_base64( encrypted_image_encryption_key_base64) if self.iek_enc_algo == IEK_ENC_ALGO_RSA_2048: private_key_pem = crypto.rsa.get_key_in_format( private_key, crypto.utils.FORMAT_PEM) image_encryption_key = crypto.rsa.decrypt( encrypted_image_encryption_key, private_key_pem, padding=crypto.rsa.RSA_PAD_PKCS) else: image_encryption_iv_base64 = encryption_params_parser.MD_SIGN[ 0].IEK_ENC_INFO[0].IEK_ENC_IV image_encryption_iv_bin = binascii.a2b_base64( image_encryption_iv_base64) image_encryption_iv_hex = binascii.hexlify(image_encryption_iv_bin) image_encryption_key = crypto.aes_cbc.decrypt( encrypted_image_encryption_key, binascii.hexlify(private_key), image_encryption_iv_hex) image_encryption_iv_base64 = encryption_params_parser.MD_SIGN[ 0].IMG_ENC_INFO[0].IMG_ENC_IV image_encryption_iv = binascii.a2b_base64(image_encryption_iv_base64) return image_encryption_key, image_encryption_iv
def gen_keys(self, curve, priv_key_path=None, pub_key_path=None): # Generate the key pair using openssl priv_key = self._gen_ecdsa_key_pair(curve) # 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 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 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 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 create_cert(self, priv_key, subject_params=None, config=None, hash_algo=CertBase.HASH_ALGO_SHA256, self_sign=False, days=None, serial=None, padding=CertBase.PAD_PKCS, pad_hash_algo=CertBase.HASH_ALGO_SHA256, pad_salt_len=CertBase.PAD_PSS_SALT_1): """ Create a self signed certificate input: subject_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 days = validity period of certificate in days configfile = configfile used by openssl serial_num = Serial number of certificate padding = Type of padding output: certificate: String representation of PEM certificate. """ 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 hash_algo is not None: cmd += ['-' + hash_algo] if self_sign: cmd += ['-x509'] if padding == self.PAD_PSS: cmd += [ '-sigopt', 'rsa_padding_mode:pss', '-sigopt', 'rsa_pss_saltlen:' + pad_salt_len, '-sigopt', 'digest:' + pad_hash_algo ] if serial is not None: cmd += ['-set_serial', str(serial)] if days is not None: cmd += ['-days', str(days)] return run_command(cmd) finally: c_path.remove_tmp_file(priv_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 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 _generate_attestation_certificate_extensions( self, attestation_certificate_extensions_path, oid_name, min_str, max_str): v3_attest_file = ensure_str( c_path.load_data_from_file( attestation_certificate_extensions_path)) v3_attest_file_new = v3_attest_file + self._generate_oid_config( oid_name, min_str, max_str) v3_attest_file_temp = c_path.create_tmp_file(data=v3_attest_file_new) return v3_attest_file_temp
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 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 get_pubkey_from_cert(self, cert, inform, text_output=False): inform_opt = self._get_format_opt(inform) cert_path, pub_path = None, None try: cert_path = c_path.create_tmp_file(cert) cmd = [ self.openssl, OPENSSL_CERT_MODE, '-pubkey', '-noout', '-in', cert_path, '-inform', inform_opt ] pub_key = run_command(cmd) if text_output: pub_path = c_path.create_tmp_file(pub_key) cmd = [ self.openssl, 'rsa', '-pubin', '-text', '-noout' '-in', cert_path, '-inform', inform_opt ] pub_key = run_command(cmd) finally: if cert_path is not None: c_path.remove_tmp_file(cert_path) if pub_path is not None: c_path.remove_tmp_file(pub_path) return pub_key
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 encrypt_segment(self, binary_segment, segment_num): ''' Encrypt elf segments using cbc encryption input: binary_segment: A string representing the binary segment that needs to be encrypted. segment_num: The segment number, used to calculate the segment IV output: encrypted_binary_segment: CBC encrypted segment ''' if len(binary_segment) < 16 and len(binary_segment) != 0: raise RuntimeError("The input plaintext is less than the minimum.") else: pt_fn = c_path.create_tmp_file(data=binary_segment) op_fn = c_path.create_tmp_file() self.encryption_parameters.ssd_p.enc_segment( segment_num, pt_fn, op_fn) encrypted_binary_segment = c_path.load_data_from_file(op_fn) os.unlink(pt_fn) os.unlink(op_fn) return encrypted_binary_segment
def verify(self, message, key, signature): # Remove padding and save signature to file signature = EcdsaOpenSSLImpl.strip_sig_padding(signature) signature_path = c_path.create_tmp_file(signature) # Return if message matches signature try: output = self._pkeyutl(message, key, ['-verify', '-pubin'], ['-sigfile', signature_path], expected_retcode=1) return output.strip() == 'Signature Verified Successfully' finally: c_path.remove_tmp_file(signature_path)