Ejemplo n.º 1
0
def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map):
  unsigned = tempfile.NamedTemporaryFile()
  unsigned.write(data)
  unsigned.flush()

  signed = tempfile.NamedTemporaryFile()

  # For pre-N builds, don't upgrade to SHA-256 JAR signatures based on the APK's
  # minSdkVersion to avoid increasing incremental OTA update sizes. If an APK
  # didn't change, we don't want its signature to change due to the switch
  # from SHA-1 to SHA-256.
  # By default, APK signer chooses SHA-256 signatures if the APK's minSdkVersion
  # is 18 or higher. For pre-N builds we disable this mechanism by pretending
  # that the APK's minSdkVersion is 1.
  # For N+ builds, we let APK signer rely on the APK's minSdkVersion to
  # determine whether to use SHA-256.
  min_api_level = None
  if platform_api_level > 23:
    # Let APK signer choose whether to use SHA-1 or SHA-256, based on the APK's
    # minSdkVersion attribute
    min_api_level = None
  else:
    # Force APK signer to use SHA-1
    min_api_level = 1

  common.SignFile(unsigned.name, signed.name, keyname, pw,
      min_api_level=min_api_level,
      codename_to_api_level_map=codename_to_api_level_map)

  data = signed.read()
  unsigned.close()
  signed.close()

  return data
Ejemplo n.º 2
0
  def ExtractApexPayloadAndSignApks(self, apk_entries, apk_keys):
    """Extracts the payload image and signs the containing apk files."""
    if not os.path.exists(self.debugfs_path):
      raise ApexSigningError(
          "Couldn't find location of debugfs_static: " +
          "Path {} does not exist. ".format(self.debugfs_path) +
          "Make sure bin/debugfs_static can be found in -p <path>")
    payload_dir = common.MakeTempDir()
    extract_cmd = ['deapexer', '--debugfs_path',
                   self.debugfs_path, 'extract', self.apex_path, payload_dir]
    common.RunAndCheckOutput(extract_cmd)

    has_signed_apk = False
    for entry in apk_entries:
      apk_path = os.path.join(payload_dir, entry)
      assert os.path.exists(self.apex_path)

      key_name = apk_keys.get(os.path.basename(entry))
      if key_name in common.SPECIAL_CERT_STRINGS:
        logger.info('Not signing: %s due to special cert string', apk_path)
        continue

      logger.info('Signing apk file %s in apex %s', apk_path, self.apex_path)
      # Rename the unsigned apk and overwrite the original apk path with the
      # signed apk file.
      unsigned_apk = common.MakeTempFile()
      os.rename(apk_path, unsigned_apk)
      common.SignFile(
          unsigned_apk, apk_path, key_name, self.key_passwords.get(key_name),
          codename_to_api_level_map=self.codename_to_api_level_map)
      has_signed_apk = True
    return payload_dir, has_signed_apk
Ejemplo n.º 3
0
    def ExtractApexPayloadAndSignApks(self, apk_entries, apk_keys):
        """Extracts the payload image and signs the containing apk files."""
        payload_dir = common.MakeTempDir()
        extract_cmd = ['deapexer', 'extract', self.apex_path, payload_dir]
        common.RunAndCheckOutput(extract_cmd)

        has_signed_apk = False
        for entry in apk_entries:
            apk_path = os.path.join(payload_dir, entry)
            assert os.path.exists(self.apex_path)

            key_name = apk_keys.get(os.path.basename(entry))
            if key_name in common.SPECIAL_CERT_STRINGS:
                logger.info('Not signing: %s due to special cert string',
                            apk_path)
                continue

            logger.info('Signing apk file %s in apex %s', apk_path,
                        self.apex_path)
            # Rename the unsigned apk and overwrite the original apk path with the
            # signed apk file.
            unsigned_apk = common.MakeTempFile()
            os.rename(apk_path, unsigned_apk)
            common.SignFile(
                unsigned_apk,
                apk_path,
                key_name,
                self.key_passwords,
                codename_to_api_level_map=self.codename_to_api_level_map)
            has_signed_apk = True
        return payload_dir, has_signed_apk
def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
            is_compressed):
  unsigned = tempfile.NamedTemporaryFile()
  unsigned.write(data)
  unsigned.flush()

  if is_compressed:
    uncompressed = tempfile.NamedTemporaryFile()
    with gzip.open(unsigned.name, "rb") as in_file, open(uncompressed.name, "wb") as out_file:
      shutil.copyfileobj(in_file, out_file)

    # Finally, close the "unsigned" file (which is gzip compressed), and then
    # replace it with the uncompressed version.
    #
    # TODO(narayan): All this nastiness can be avoided if python 3.2 is in use,
    # we could just gzip / gunzip in-memory buffers instead.
    unsigned.close()
    unsigned = uncompressed

  signed = tempfile.NamedTemporaryFile()

  # For pre-N builds, don't upgrade to SHA-256 JAR signatures based on the APK's
  # minSdkVersion to avoid increasing incremental OTA update sizes. If an APK
  # didn't change, we don't want its signature to change due to the switch
  # from SHA-1 to SHA-256.
  # By default, APK signer chooses SHA-256 signatures if the APK's minSdkVersion
  # is 18 or higher. For pre-N builds we disable this mechanism by pretending
  # that the APK's minSdkVersion is 1.
  # For N+ builds, we let APK signer rely on the APK's minSdkVersion to
  # determine whether to use SHA-256.
  min_api_level = None
  if platform_api_level > 23:
    # Let APK signer choose whether to use SHA-1 or SHA-256, based on the APK's
    # minSdkVersion attribute
    min_api_level = None
  else:
    # Force APK signer to use SHA-1
    min_api_level = 1

  common.SignFile(unsigned.name, signed.name, keyname, pw,
      min_api_level=min_api_level,
      codename_to_api_level_map=codename_to_api_level_map)

  data = None;
  if is_compressed:
    # Recompress the file after it has been signed.
    compressed = tempfile.NamedTemporaryFile()
    with open(signed.name, "rb") as in_file, gzip.open(compressed.name, "wb") as out_file:
      shutil.copyfileobj(in_file, out_file)

    data = compressed.read()
    compressed.close()
  else:
    data = signed.read()

  unsigned.close()
  signed.close()

  return data
Ejemplo n.º 5
0
def SignApex(apex_data,
             payload_key,
             container_key,
             container_pw,
             codename_to_api_level_map,
             signing_args=None):
    """Signs the current APEX with the given payload/container keys.

  Args:
    apex_data: Raw APEX data.
    payload_key: The path to payload signing key (w/o extension).
    container_key: The path to container signing key (w/o extension).
    container_pw: The matching password of the container_key, or None.
    codename_to_api_level_map: A dict that maps from codename to API level.
    signing_args: Additional args to be passed to the payload signer.

  Returns:
    (signed_apex, payload_key_name): signed_apex is the path to the signed APEX
        file; payload_key_name is a str of the payload signing key name (e.g.
        com.android.tzdata).
  """
    apex_file = common.MakeTempFile(prefix='apex-', suffix='.apex')
    with open(apex_file, 'wb') as apex_fp:
        apex_fp.write(apex_data)

    APEX_PAYLOAD_IMAGE = 'apex_payload.img'

    # Signing an APEX is a two step process.
    # 1. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given payload_key.
    payload_dir = common.MakeTempDir(prefix='apex-payload-')
    with zipfile.ZipFile(apex_file) as apex_fd:
        payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)

    payload_info = apex_utils.ParseApexPayloadInfo(payload_file)
    apex_utils.SignApexPayload(payload_file, payload_key,
                               payload_info['apex.key'],
                               payload_info['Algorithm'], payload_info['Salt'],
                               signing_args)

    common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
    apex_zip = zipfile.ZipFile(apex_file, 'a')
    common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
    common.ZipClose(apex_zip)

    # 2. Sign the overall APEX container with container_key.
    signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
    common.SignFile(apex_file,
                    signed_apex,
                    container_key,
                    container_pw,
                    codename_to_api_level_map=codename_to_api_level_map)

    signed_and_aligned_apex = common.MakeTempFile(prefix='apex-container-',
                                                  suffix='.apex')
    common.RunAndCheckOutput(
        ['zipalign', '-f', '4096', signed_apex, signed_and_aligned_apex])

    return (signed_and_aligned_apex, payload_info['apex.key'])
Ejemplo n.º 6
0
def SignOutput(input_zip_name, output_zip_name):
    key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
    pw = key_passwords[OPTIONS.package_key]

    common.SignFile(input_zip_name,
                    output_zip_name,
                    OPTIONS.package_key,
                    pw,
                    whole_file=True)
def SignApk(data, keyname, pw):
    unsigned = tempfile.NamedTemporaryFile()
    unsigned.write(data)
    unsigned.flush()

    signed = tempfile.NamedTemporaryFile()

    common.SignFile(unsigned.name, signed.name, keyname, pw, align=4)

    data = signed.read()
    unsigned.close()
    signed.close()

    return data
Ejemplo n.º 8
0
def SignCompressedApex(avbtool, apex_file, payload_key, container_key,
                       container_pw, apk_keys, codename_to_api_level_map,
                       no_hashtree, signing_args=None):
  """Signs the current compressed APEX with the given payload/container keys.

  Args:
    apex_file: Raw uncompressed APEX data.
    payload_key: The path to payload signing key (w/ extension).
    container_key: The path to container signing key (w/o extension).
    container_pw: The matching password of the container_key, or None.
    apk_keys: A dict that holds the signing keys for apk files.
    codename_to_api_level_map: A dict that maps from codename to API level.
    no_hashtree: Don't include hashtree in the signed APEX.
    signing_args: Additional args to be passed to the payload signer.

  Returns:
    The path to the signed APEX file.
  """
  debugfs_path = os.path.join(OPTIONS.search_path, 'bin', 'debugfs_static')

  # 1. Decompress original_apex inside compressed apex.
  original_apex_file = common.MakeTempFile(prefix='original-apex-',
                                           suffix='.apex')
  # Decompression target path should not exist
  os.remove(original_apex_file)
  common.RunAndCheckOutput(['deapexer', '--debugfs_path', debugfs_path,
                            'decompress', '--input', apex_file,
                            '--output', original_apex_file])

  # 2. Sign original_apex
  signed_original_apex_file = SignUncompressedApex(
      avbtool,
      original_apex_file,
      payload_key,
      container_key,
      container_pw,
      apk_keys,
      codename_to_api_level_map,
      no_hashtree,
      signing_args)

  # 3. Compress signed original apex.
  compressed_apex_file = common.MakeTempFile(prefix='apex-container-',
                                             suffix='.capex')
  common.RunAndCheckOutput(['apex_compression_tool',
                            'compress',
                            '--apex_compression_tool_path', os.getenv('PATH'),
                            '--input', signed_original_apex_file,
                            '--output', compressed_apex_file])

  # 4. Sign the APEX container with container_key.
  signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.capex')

  password = container_pw.get(container_key) if container_pw else None
  common.SignFile(
      compressed_apex_file,
      signed_apex,
      container_key,
      password,
      codename_to_api_level_map=codename_to_api_level_map,
      extra_signapk_args=OPTIONS.extra_signapk_args)

  return signed_apex
Ejemplo n.º 9
0
def SignUncompressedApex(avbtool, apex_file, payload_key, container_key,
                         container_pw, apk_keys, codename_to_api_level_map,
                         no_hashtree, signing_args=None):
  """Signs the current uncompressed APEX with the given payload/container keys.

  Args:
    apex_file: Uncompressed APEX file.
    payload_key: The path to payload signing key (w/ extension).
    container_key: The path to container signing key (w/o extension).
    container_pw: The matching password of the container_key, or None.
    apk_keys: A dict that holds the signing keys for apk files.
    codename_to_api_level_map: A dict that maps from codename to API level.
    no_hashtree: Don't include hashtree in the signed APEX.
    signing_args: Additional args to be passed to the payload signer.

  Returns:
    The path to the signed APEX file.
  """
  # 1. Extract the apex payload image and sign the containing apk files. Repack
  # the apex file after signing.
  apk_signer = ApexApkSigner(apex_file, container_pw,
                             codename_to_api_level_map)
  apex_file = apk_signer.ProcessApexFile(apk_keys, payload_key, signing_args)

  # 2a. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given
  # payload_key.
  payload_dir = common.MakeTempDir(prefix='apex-payload-')
  with zipfile.ZipFile(apex_file) as apex_fd:
    payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
    zip_items = apex_fd.namelist()

  payload_info = ParseApexPayloadInfo(avbtool, payload_file)
  if no_hashtree is None:
    no_hashtree = payload_info.get("Tree Size", 0) == 0
  SignApexPayload(
      avbtool,
      payload_file,
      payload_key,
      payload_info['apex.key'],
      payload_info['Algorithm'],
      payload_info['Salt'],
      payload_info['Hash Algorithm'],
      no_hashtree,
      signing_args)

  # 2b. Update the embedded payload public key.
  payload_public_key = common.ExtractAvbPublicKey(avbtool, payload_key)
  common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
  if APEX_PUBKEY in zip_items:
    common.ZipDelete(apex_file, APEX_PUBKEY)
  apex_zip = zipfile.ZipFile(apex_file, 'a', allowZip64=True)
  common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
  common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
  common.ZipClose(apex_zip)

  # 3. Sign the APEX container with container_key.
  signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')

  # Specify the 4K alignment when calling SignApk.
  extra_signapk_args = OPTIONS.extra_signapk_args[:]
  extra_signapk_args.extend(['-a', '4096', '--align-file-size'])

  password = container_pw.get(container_key) if container_pw else None
  common.SignFile(
      apex_file,
      signed_apex,
      container_key,
      password,
      codename_to_api_level_map=codename_to_api_level_map,
      extra_signapk_args=extra_signapk_args)

  return signed_apex
Ejemplo n.º 10
0
def main(argv):
  common.SignFile(argv[1], argv[2], argv[0], None, whole_file=True)
Ejemplo n.º 11
0
def SignApex(apex_data,
             payload_key,
             container_key,
             container_pw,
             codename_to_api_level_map,
             signing_args=None):
    """Signs the current APEX with the given payload/container keys.

  Args:
    apex_data: Raw APEX data.
    payload_key: The path to payload signing key (w/ extension).
    container_key: The path to container signing key (w/o extension).
    container_pw: The matching password of the container_key, or None.
    codename_to_api_level_map: A dict that maps from codename to API level.
    signing_args: Additional args to be passed to the payload signer.

  Returns:
    The path to the signed APEX file.
  """
    apex_file = common.MakeTempFile(prefix='apex-', suffix='.apex')
    with open(apex_file, 'wb') as apex_fp:
        apex_fp.write(apex_data)

    APEX_PAYLOAD_IMAGE = 'apex_payload.img'
    APEX_PUBKEY = 'apex_pubkey'

    # 1a. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given
    # payload_key.
    payload_dir = common.MakeTempDir(prefix='apex-payload-')
    with zipfile.ZipFile(apex_file) as apex_fd:
        payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
        zip_items = apex_fd.namelist()

    payload_info = ParseApexPayloadInfo(payload_file)
    SignApexPayload(payload_file, payload_key, payload_info['apex.key'],
                    payload_info['Algorithm'], payload_info['Salt'],
                    signing_args)

    # 1b. Update the embedded payload public key.
    payload_public_key = common.ExtractAvbPublicKey(payload_key)

    common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
    if APEX_PUBKEY in zip_items:
        common.ZipDelete(apex_file, APEX_PUBKEY)
    apex_zip = zipfile.ZipFile(apex_file, 'a')
    common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
    common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
    common.ZipClose(apex_zip)

    # 2. Align the files at page boundary (same as in apexer).
    aligned_apex = common.MakeTempFile(prefix='apex-container-',
                                       suffix='.apex')
    common.RunAndCheckOutput(
        ['zipalign', '-f', '4096', apex_file, aligned_apex])

    # 3. Sign the APEX container with container_key.
    signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')

    # Specify the 4K alignment when calling SignApk.
    extra_signapk_args = OPTIONS.extra_signapk_args[:]
    extra_signapk_args.extend(['-a', '4096'])

    common.SignFile(aligned_apex,
                    signed_apex,
                    container_key,
                    container_pw,
                    codename_to_api_level_map=codename_to_api_level_map,
                    extra_signapk_args=extra_signapk_args)

    return signed_apex