#!/usr/bin/env python
#
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Signs all the APK files in a target-files zipfile, producing a new
target-files zip.

Usage:  sign_target_files_apks [flags] input_target_files output_target_files

  -s  (--signapk_jar)  <path>
      Path of the signapks.jar file used to sign an individual APK
      file.

  -e  (--extra_apks)  <name,name,...=key>
      Add extra APK name/key pairs as though they appeared in
      apkcerts.txt (so mappings specified by -k and -d are applied).
      Keys specified in -e override any value for that app contained
      in the apkcerts.txt file.  Option may be repeated to give
      multiple extra packages.

  -k  (--key_mapping)  <src_key=dest_key>
      Add a mapping from the key name as specified in apkcerts.txt (the
      src_key) to the real key you wish to sign the package with
      (dest_key).  Option may be repeated to give multiple key
      mappings.

  -d  (--default_key_mappings)  <dir>
      Set up the following key mappings:

        build/target/product/security/testkey   ==>  $dir/releasekey
        build/target/product/security/media     ==>  $dir/media
        build/target/product/security/shared    ==>  $dir/shared
        build/target/product/security/platform  ==>  $dir/platform

      -d and -k options are added to the set of mappings in the order
      in which they appear on the command line.

  -o  (--replace_ota_keys)
      Replace the certificate (public key) used by OTA package
      verification with the one specified in the input target_files
      zip (in the META/otakeys.txt file).  Key remapping (-k and -d)
      is performed on this key.

  -t  (--tag_changes)  <+tag>,<-tag>,...
      Comma-separated list of changes to make to the set of tags (in
      the last component of the build fingerprint).  Prefix each with
      '+' or '-' to indicate whether that tag should be added or
      removed.  Changes are processed in the order they appear.
      Default value is "-test-keys,+ota-rel-keys,+release-keys".

"""

import sys

if sys.hexversion < 0x02040000:
  print >> sys.stderr, "Python 2.4 or newer is required."
  sys.exit(1)

import cStringIO
import copy
import os
import re
import subprocess
import tempfile
import zipfile

import common

OPTIONS = common.OPTIONS

OPTIONS.extra_apks = {}
OPTIONS.key_map = {}
OPTIONS.replace_ota_keys = False
OPTIONS.tag_changes = ("-test-keys", "+ota-rel-keys", "+release-keys")

def GetApkCerts(tf_zip):
  certmap = {}
  for line in tf_zip.read("META/apkcerts.txt").split("\n"):
    line = line.strip()
    if not line: continue
    m = re.match(r'^name="(.*)"\s+certificate="(.*)\.x509\.pem"\s+'
                 r'private_key="\2\.pk8"$', line)
    if not m:
      raise SigningError("failed to parse line from apkcerts.txt:\n" + line)
    certmap[m.group(1)] = OPTIONS.key_map.get(m.group(2), m.group(2))
  for apk, cert in OPTIONS.extra_apks.iteritems():
    certmap[apk] = OPTIONS.key_map.get(cert, cert)
  return certmap


def CheckAllApksSigned(input_tf_zip, apk_key_map):
  """Check that all the APKs we want to sign have keys specified, and
  error out if they don't."""
  unknown_apks = []
  for info in input_tf_zip.infolist():
    if info.filename.endswith(".apk"):
      name = os.path.basename(info.filename)
      if name not in apk_key_map:
        unknown_apks.append(name)
  if unknown_apks:
    print "ERROR: no key specified for:\n\n ",
    print "\n  ".join(unknown_apks)
    print "\nUse '-e <apkname>=' to specify a key (which may be an"
    print "empty string to not sign this apk)."
    sys.exit(1)


def SharedUserForApk(data):
  tmp = tempfile.NamedTemporaryFile()
  tmp.write(data)
  tmp.flush()

  p = common.Run(["aapt", "dump", "xmltree", tmp.name, "AndroidManifest.xml"],
                 stdout=subprocess.PIPE)
  data, _ = p.communicate()
  if p.returncode != 0:
    raise ExternalError("failed to run aapt dump")
  lines = data.split("\n")
  for i in lines:
    m = re.match(r'^\s*A: android:sharedUserId\([0-9a-fx]*\)="([^"]*)" .*$', i)
    if m:
      return m.group(1)
  return None


def CheckSharedUserIdsConsistent(input_tf_zip, apk_key_map):
  """Check that all packages that request the same shared user id are
  going to be signed with the same key."""

  shared_user_apks = {}
  maxlen = len("(unknown key)")

  for info in input_tf_zip.infolist():
    if info.filename.endswith(".apk"):
      data = input_tf_zip.read(info.filename)

      name = os.path.basename(info.filename)
      shared_user = SharedUserForApk(data)
      key = apk_key_map[name]
      maxlen = max(maxlen, len(key))

      if shared_user is not None:
        shared_user_apks.setdefault(
            shared_user, {}).setdefault(key, []).append(name)

  errors = []
  for k, v in shared_user_apks.iteritems():
    # each shared user should have exactly one key used for all the
    # apks that want that user.
    if len(v) > 1:
      errors.append((k, v))

  if not errors: return

  print "ERROR:  shared user inconsistency.  All apks wanting to use"
  print "        a given shared user must be signed with the same key."
  print
  errors.sort()
  for user, keys in errors:
    print 'shared user id "%s":' % (user,)
    for key, apps in keys.iteritems():
      print '  %-*s   %s' % (maxlen, key or "(unknown key)", apps[0])
      for a in apps[1:]:
        print (' ' * (maxlen+5)) + a
    print

  sys.exit(1)


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


def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords):
  maxsize = max([len(os.path.basename(i.filename))
                 for i in input_tf_zip.infolist()
                 if i.filename.endswith('.apk')])

  for info in input_tf_zip.infolist():
    data = input_tf_zip.read(info.filename)
    out_info = copy.copy(info)
    if info.filename.endswith(".apk"):
      name = os.path.basename(info.filename)
      key = apk_key_map[name]
      if key:
        print "    signing: %-*s (%s)" % (maxsize, name, key)
        signed_data = SignApk(data, key, key_passwords[key])
        output_tf_zip.writestr(out_info, signed_data)
      else:
        # an APK we're not supposed to sign.
        print "NOT signing: %s" % (name,)
        output_tf_zip.writestr(out_info, data)
    elif info.filename in ("SYSTEM/build.prop",
                           "RECOVERY/RAMDISK/default.prop"):
      print "rewriting %s:" % (info.filename,)
      new_data = RewriteProps(data)
      output_tf_zip.writestr(out_info, new_data)
    else:
      # a non-APK file; copy it verbatim
      output_tf_zip.writestr(out_info, data)


def RewriteProps(data):
  output = []
  for line in data.split("\n"):
    line = line.strip()
    original_line = line
    if line and line[0] != '#':
      key, value = line.split("=", 1)
      if key == "ro.build.fingerprint":
        pieces = line.split("/")
        tags = set(pieces[-1].split(","))
        for ch in OPTIONS.tag_changes:
          if ch[0] == "-":
            tags.discard(ch[1:])
          elif ch[0] == "+":
            tags.add(ch[1:])
        line = "/".join(pieces[:-1] + [",".join(sorted(tags))])
      elif key == "ro.build.description":
        pieces = line.split(" ")
        assert len(pieces) == 5
        tags = set(pieces[-1].split(","))
        for ch in OPTIONS.tag_changes:
          if ch[0] == "-":
            tags.discard(ch[1:])
          elif ch[0] == "+":
            tags.add(ch[1:])
        line = " ".join(pieces[:-1] + [",".join(sorted(tags))])
    if line != original_line:
      print "  replace: ", original_line
      print "     with: ", line
    output.append(line)
  return "\n".join(output) + "\n"


def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
  try:
    keylist = input_tf_zip.read("META/otakeys.txt").split()
  except KeyError:
    raise ExternalError("can't read META/otakeys.txt from input")

  mapped_keys = []
  for k in keylist:
    m = re.match(r"^(.*)\.x509\.pem$", k)
    if not m:
      raise ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,))
    k = m.group(1)
    mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem")

  print "using:\n   ", "\n   ".join(mapped_keys)
  print "for OTA package verification"

  # recovery uses a version of the key that has been slightly
  # predigested (by DumpPublicKey.java) and put in res/keys.

  p = common.Run(["java", "-jar",
                  os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")]
                 + mapped_keys,
                 stdout=subprocess.PIPE)
  data, _ = p.communicate()
  if p.returncode != 0:
    raise ExternalError("failed to run dumpkeys")
  common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data)

  # SystemUpdateActivity uses the x509.pem version of the keys, but
  # put into a zipfile system/etc/security/otacerts.zip.

  tempfile = cStringIO.StringIO()
  certs_zip = zipfile.ZipFile(tempfile, "w")
  for k in mapped_keys:
    certs_zip.write(k)
  certs_zip.close()
  common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip",
                     tempfile.getvalue())


def main(argv):

  def option_handler(o, a):
    if o in ("-s", "--signapk_jar"):
      OPTIONS.signapk_jar = a
    elif o in ("-e", "--extra_apks"):
      names, key = a.split("=")
      names = names.split(",")
      for n in names:
        OPTIONS.extra_apks[n] = key
    elif o in ("-d", "--default_key_mappings"):
      OPTIONS.key_map.update({
          "build/target/product/security/testkey": "%s/releasekey" % (a,),
          "build/target/product/security/media": "%s/media" % (a,),
          "build/target/product/security/shared": "%s/shared" % (a,),
          "build/target/product/security/platform": "%s/platform" % (a,),
          })
    elif o in ("-k", "--key_mapping"):
      s, d = a.split("=")
      OPTIONS.key_map[s] = d
    elif o in ("-o", "--replace_ota_keys"):
      OPTIONS.replace_ota_keys = True
    elif o in ("-t", "--tag_changes"):
      new = []
      for i in a.split(","):
        i = i.strip()
        if not i or i[0] not in "-+":
          raise ValueError("Bad tag change '%s'" % (i,))
        new.append(i[0] + i[1:].strip())
      OPTIONS.tag_changes = tuple(new)
    else:
      return False
    return True

  args = common.ParseOptions(argv, __doc__,
                             extra_opts="s:e:d:k:ot:",
                             extra_long_opts=["signapk_jar=",
                                              "extra_apks=",
                                              "default_key_mappings=",
                                              "key_mapping=",
                                              "replace_ota_keys",
                                              "tag_changes="],
                             extra_option_handler=option_handler)

  if len(args) != 2:
    common.Usage(__doc__)
    sys.exit(1)

  input_zip = zipfile.ZipFile(args[0], "r")
  output_zip = zipfile.ZipFile(args[1], "w")

  apk_key_map = GetApkCerts(input_zip)
  CheckAllApksSigned(input_zip, apk_key_map)
  CheckSharedUserIdsConsistent(input_zip, apk_key_map)

  key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
  SignApks(input_zip, output_zip, apk_key_map, key_passwords)

  if OPTIONS.replace_ota_keys:
    ReplaceOtaKeys(input_zip, output_zip)

  input_zip.close()
  output_zip.close()

  print "done."


if __name__ == '__main__':
  try:
    main(sys.argv[1:])
  except common.ExternalError, e:
    print
    print "   ERROR: %s" % (e,)
    print
    sys.exit(1)
