mirror of
https://github.com/David112x/android-firmware-qti-sdm670
synced 2025-11-10 01:26:05 +08:00
248 lines
10 KiB
Python
Executable File
248 lines
10 KiB
Python
Executable File
# ===============================================================================
|
|
#
|
|
# Copyright (c) 2013-2017 Qualcomm Technologies, Inc.
|
|
# All Rights Reserved.
|
|
# Confidential and Proprietary - Qualcomm Technologies, Inc.
|
|
#
|
|
# ===============================================================================
|
|
"""
|
|
#===============================================================================
|
|
#
|
|
# Qualcomm Technologies, Inc. is NOT responsible for any misusage of the example
|
|
# codes. OEMs should implement their own client and server infrastructure.
|
|
#
|
|
#===============================================================================
|
|
|
|
This file simulates the client signer:
|
|
1. Create tosign package
|
|
2. Upload tosign package to the shared location
|
|
3. Trigger server to sign with server hosted keys
|
|
4. Download sig package from the shared location
|
|
5. Generate signed image with sig package
|
|
|
|
To use this file, please configure the SERVER_SETTINGS at the start of the
|
|
code and the TEST_SETTINGS at the end of the code, before executing this file.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import shutil
|
|
import socket
|
|
import sys
|
|
|
|
# Add sectools directory in path to allow sectools import
|
|
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.append(os.path.join(DIR_PATH, '..'))
|
|
|
|
from sectools.features.isc.api.intf import SecImageAPIIntf
|
|
|
|
"""SERVER_SETTINGS: Following global variables define the server settings
|
|
|
|
1. HOST : The IP address of the server to connect to.
|
|
2. PORT : The port of the server to connect to for socket communication.
|
|
|
|
3. SHARED_LOCATION: A network location where both the client and the server have
|
|
write permissions. This is the location where the hash
|
|
package and the signature package will be exchanged
|
|
between the server and the client.
|
|
|
|
4. SEND_SIGN_ATTRS: Flag to send signing attributes from the client to the
|
|
server. Setting this flag to True will override the
|
|
server signing attributes with the client signing
|
|
attributes. Setting this flag to True requires that the
|
|
server's "ACCEPT_SIGN_ATTRS" is also set to True. Otherwise,
|
|
error will be returned from server on signing requests.
|
|
"""
|
|
# PLEASE SET THE IP ADDRESS OF THE SERVER HERE
|
|
HOST = 'localhost'
|
|
|
|
# PLEASE SET THE PORT NUMBER OF THE SERVER HERE
|
|
PORT = 50050
|
|
|
|
# PLEASE SET THE PATH TO THE LOCATION SHARED WITH THE SERVER
|
|
SHARED_LOCATION = os.path.join(os.path.abspath(DIR_PATH), 'shared')
|
|
|
|
# PLEASE SET THIS SETTING AS PER THE SERVER SETTING FOR "ACCEPT_SIGN_ATTRS"
|
|
SEND_SIGN_ATTRS = True
|
|
|
|
"""Following global variables are used for socket communication protocol."""
|
|
REQ = 'request'
|
|
REQ_INFO = 'request_info'
|
|
REQ_VAL_SIGN = 'sign'
|
|
|
|
RESP = 'response'
|
|
RESP_INFO = 'response_info'
|
|
RESP_VAL_INVALID = 'invalid'
|
|
|
|
|
|
class SampleClientSigner(SecImageAPIIntf):
|
|
"""Overrides the SecImageAPIIntf to allow one-shot signing of image files.
|
|
"""
|
|
|
|
def __init__(self, verbose=False, debug=False, quiet=False):
|
|
"""Initializes the basic settings for SecImageAPIIntf, sets the
|
|
server settings and creates the shared network location if it doesnt
|
|
already exist.
|
|
"""
|
|
# Initialize the base
|
|
SecImageAPIIntf.__init__(self, send_signattrs=SEND_SIGN_ATTRS,
|
|
verbose=verbose, debug=debug, quiet=quiet)
|
|
|
|
# Set the server information
|
|
self.host = HOST
|
|
self.port = PORT
|
|
|
|
# Create the network location if it doesnt exist
|
|
self.shared_location = SHARED_LOCATION
|
|
if not os.path.exists(self.shared_location):
|
|
# Create the shared location
|
|
print 'Creating the shared location: ' + str(self.shared_location)
|
|
os.makedirs(self.shared_location)
|
|
print 'Shared location set to: ' + str(self.shared_location)
|
|
|
|
def signwithserver(self, chipset, output_dir, sign_id, hash_package,
|
|
verbose=False, debug=False, quiet=False):
|
|
"""Signs the hash package with the server. See documentation from
|
|
SecImageAPIIntf.signwithserver for API information.
|
|
|
|
1. Uploads the hash package to the server by copying the file.
|
|
2. Sends a signing request message to the server over socket.
|
|
3. Downloads the signature package from the server.
|
|
"""
|
|
retcode = 0
|
|
errstr = ''
|
|
sig_package = ''
|
|
|
|
try:
|
|
# Create a directory to share this package
|
|
hash_package_shared_dir = os.path.join(self.shared_location, sign_id)
|
|
if not os.path.exists(hash_package_shared_dir):
|
|
print 'Creating directory for sharing hash package: ' + str(hash_package_shared_dir)
|
|
os.makedirs(hash_package_shared_dir)
|
|
|
|
# Remove existing hash package
|
|
hash_package_shared = os.path.join(hash_package_shared_dir,
|
|
os.path.basename(hash_package))
|
|
if os.path.exists(hash_package_shared):
|
|
print 'Removing existing shared hash package: ' + str(hash_package_shared)
|
|
os.remove(hash_package_shared)
|
|
|
|
# Upload to the shared location
|
|
print 'Uploading hash package:'
|
|
print ' from: ' + str(hash_package)
|
|
print ' to: ' + str(hash_package_shared)
|
|
shutil.copy(hash_package, hash_package_shared)
|
|
|
|
# Set the signing request
|
|
request = REQ_VAL_SIGN
|
|
request_info = {}
|
|
request_info['hash_package'] = hash_package_shared
|
|
|
|
# Create the request packet
|
|
request_dict = {}
|
|
request_dict[REQ] = request
|
|
request_dict[REQ_INFO] = request_info
|
|
request_data = json.dumps(request_dict)
|
|
|
|
# Create the socket & send the request
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
print 'Connecting to server at host: ' + (self.host) + ' port: ' + str(self.port)
|
|
s.connect((self.host, self.port))
|
|
print 'Sending signing request to the server'
|
|
s.sendall(request_data)
|
|
print 'Waiting for server response'
|
|
response_data = s.recv(10 * 1024)
|
|
print 'Got server response'
|
|
s.close()
|
|
|
|
# Decode the server response
|
|
response_dict = json.loads(response_data)
|
|
response = response_dict[RESP]
|
|
response_info = response_dict[RESP_INFO]
|
|
|
|
if response == REQ_VAL_SIGN:
|
|
# Decode the signing response
|
|
retcode = response_info['retcode']
|
|
errstr = str(response_info['errstr'])
|
|
sig_package_shared = str(response_info['sig_package'])
|
|
|
|
if retcode == 0:
|
|
# Remove existing signature package
|
|
sig_package = os.path.join(os.path.dirname(hash_package),
|
|
os.path.basename(sig_package_shared))
|
|
if os.path.exists(sig_package):
|
|
print 'Removing existing signature package: ' + str(sig_package)
|
|
os.remove(sig_package)
|
|
|
|
# Download signature package from the shared location
|
|
print 'Downloading signature package:'
|
|
print ' from: ' + str(sig_package_shared)
|
|
print ' to: ' + str(sig_package)
|
|
shutil.copy(sig_package_shared, sig_package)
|
|
|
|
# Invalid response
|
|
else:
|
|
retcode = 1
|
|
errstr = 'Invalid server response: ' + response
|
|
sig_package = ''
|
|
|
|
except Exception as e:
|
|
print e
|
|
retcode = 1
|
|
errstr = 'Exception occurred - ' + str(e)
|
|
sig_package = ''
|
|
|
|
return retcode, errstr, sig_package
|
|
|
|
def sign_metabuild(self, chipset, metabuild, output_dir):
|
|
# Get the images from the metabuild
|
|
retcode, errstr, images = self.getmetabuildimages(chipset, metabuild,
|
|
**self._classmethod_kwargs)
|
|
|
|
if retcode != 0:
|
|
print 'Error getting metabuild images. ' + errstr
|
|
else:
|
|
# Print the images from the metabuild
|
|
print 'Got the following from the metabuild'
|
|
print json.dumps(images, sort_keys=True, indent=4, separators=(',', ': '))
|
|
|
|
# Sign the images from the metabuild
|
|
for sign_id, image_info in images.items():
|
|
if image_info['retcode'] == 0:
|
|
print 'Signing ' + sign_id
|
|
i_retcode, i_errstr, signed_image, expected_path = \
|
|
self.sign(chipset, output_dir, sign_id=sign_id,
|
|
metabuild=metabuild)
|
|
if i_retcode == 0:
|
|
print ('Signed ' + sign_id + '\n'
|
|
' unsigned image at: ' + image_info['path'] + '\n'
|
|
' signed image at: ' + signed_image + '\n'
|
|
' expected path at: ' + expected_path)
|
|
else:
|
|
print 'Signing ' + sign_id + ' failed. ' + i_errstr
|
|
else:
|
|
print 'Sign id ' + sign_id + ' could not be found from metabuild. ' + image_info['errstr']
|
|
|
|
|
|
if __name__ == '__main__':
|
|
"""TEST_SETTINGS: Following variables define the testing settings
|
|
"""
|
|
chipset = '8994'
|
|
sign_id = 'pmic'
|
|
imagefile = os.path.join(DIR_PATH, 'pmic.mbn')
|
|
output_dir = os.path.join(DIR_PATH, 'client_output')
|
|
root_cert_hash = '8ecf3eaa03f772e28479fa2f0bbae2141ccad6f106b384d1c46263edb5b02838'
|
|
|
|
# Call the signer to sign
|
|
client = SampleClientSigner(verbose=False, debug=False, quiet=False)
|
|
retcode, errstr, signed_image, expected_path = \
|
|
client.sign(chipset, output_dir, sign_id, imagefile)
|
|
|
|
# Print the result
|
|
print 'Signing result: ' + str(retcode)
|
|
if retcode != 0:
|
|
print 'Error: ' + str(errstr)
|
|
else:
|
|
print 'Signed File: ' + str(signed_image)
|
|
print 'Expected Path: ' + str(expected_path)
|