// Copyright (C) 2019 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.

// Build rules to build shim apexes.

package {
    default_applicable_licenses: ["Android-Apache-2.0"],
}

genrule {
  name: "com.android.apex.cts.shim.pem",
  out: ["com.android.apex.cts.shim.pem"],
  cmd: "openssl genrsa -out $(out) 4096",
}

genrule {
  name: "com.android.apex.cts.shim.pubkey",
  srcs: [":com.android.apex.cts.shim.pem"],
  out: ["com.android.apex.cts.shim.pubkey"],
  tools: ["avbtool"],
  cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
}

apex_key {
  name: "com.android.apex.cts.shim.key",
  private_key: ":com.android.apex.cts.shim.pem",
  public_key: ":com.android.apex.cts.shim.pubkey",
  installable: false,
}

genrule {
  name: "com.android.apex.cts.shim.debug.pem",
  out: ["com.android.apex.cts.shim.debug.pem"],
  cmd: "openssl genrsa -out $(out) 4096",
}

genrule {
  name: "com.android.apex.cts.shim.debug.pubkey",
  srcs: [":com.android.apex.cts.shim.debug.pem"],
  out: ["com.android.apex.cts.shim.debug.pubkey"],
  tools: ["avbtool"],
  cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
}

apex_key {
  name: "com.android.apex.cts.shim.debug.key",
  private_key: ":com.android.apex.cts.shim.debug.pem",
  public_key: ":com.android.apex.cts.shim.debug.pubkey",
  installable: false,
}

genrule {
  name: "generate_hash_of_dev_null",
  out: ["hash.txt"],
  cmd: "sha512sum -b /dev/null | cut -d' ' -f1 | tee $(out)",
}

prebuilt_etc {
  name: "hash_of_dev_null",
  src: ":generate_hash_of_dev_null",
  filename: "hash.txt",
  installable: false,
}

apex {
  name: "com.android.apex.cts.shim.v3",
  manifest: "manifest_v3.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  apps: ["CtsShim", "CtsShimPriv"],
  installable: false,
  allowed_files: "default_shim_allowed_list.txt",
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2",
  manifest: "manifest_v2.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  apps: ["CtsShim", "CtsShimPriv"],
  installable: false,
  allowed_files: "default_shim_allowed_list.txt",
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_sign_payload_with_different_key",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.debug.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  allowed_files: "default_shim_allowed_list.txt",
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_without_apk_in_apex",
  manifest: "manifest_v2.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  allowed_files: "default_shim_allowed_list.txt",
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_no_hashtree",
  manifest: "manifest_v2.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  apps: ["CtsShim", "CtsShimPriv"],
  installable: false,
  allowed_files: "default_shim_allowed_list.txt",
  generate_hashtree: false,
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_unsigned_payload",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  apps: ["CtsShim", "CtsShimPriv"],
  installable: false,
  allowed_files: "default_shim_allowed_list.txt",
  test_only_unsigned_payload: true,
  updatable: false,
}

override_apex {
    name: "com.android.apex.cts.shim.v2_different_package_name",
    package_name: "com.android.apex.cts.shim.different",
    // Use rebootless APEX to re-use this APEX in the rebootless update test case.
    base: "com.android.apex.cts.shim.v2_rebootless",
}

genrule {
  name: "generate_empty_hash",
  out: ["hash.txt"],
  cmd: "touch $(out)",
}

prebuilt_etc {
  name: "empty_hash",
  src: ":generate_empty_hash",
  filename: "hash.txt",
  installable: false,
}

// Use empty hash.txt to make sure that this apex has wrong SHA512, hence trying
// to stage it should fail.
apex {
  name: "com.android.apex.cts.shim.v2_wrong_sha",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["empty_hash"],
  installable: false,
  updatable: false,
}

prebuilt_etc {
  name: "apex_shim_additional_file",
  src: "additional_file",
  filename: "additional_file",
  installable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_additional_file",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null", "apex_shim_additional_file"],
  installable: false,
  updatable: false,
}

prebuilt_etc {
  name: "apex_shim_additional_folder",
  src: "additional_file",
  filename: "additional_file",
  sub_dir: "additional_folder",
  installable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_additional_folder",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null", "apex_shim_additional_folder"],
  installable: false,
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_with_pre_install_hook",
  manifest: "manifest_v2_with_pre_install_hook.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_with_post_install_hook",
  manifest: "manifest_v2_with_post_install_hook.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  updatable: false,
}

genrule {
  name: "generate_hash_v1",
  srcs: [
    ":com.android.apex.cts.shim.v2",
    ":com.android.apex.cts.shim.v2_without_apk_in_apex",
    ":com.android.apex.cts.shim.v2_additional_file",
    ":com.android.apex.cts.shim.v2_additional_folder",
    ":com.android.apex.cts.shim.v2_different_certificate",
    ":com.android.apex.cts.shim.v2_different_package_name",
    ":com.android.apex.cts.shim.v2_no_hashtree",
    ":com.android.apex.cts.shim.v2_signed_bob",
    ":com.android.apex.cts.shim.v2_signed_bob_rot",
    ":com.android.apex.cts.shim.v2_signed_bob_rot_rollback",
    ":com.android.apex.cts.shim.v2_with_pre_install_hook",
    ":com.android.apex.cts.shim.v2_with_post_install_hook",
    ":com.android.apex.cts.shim.v2_sdk_target_p",
    ":com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p",
    ":com.android.apex.cts.shim.v2_rebootless",
    ":com.android.apex.cts.shim.v3",
    ":com.android.apex.cts.shim.v3_rebootless",
    ":com.android.apex.cts.shim.v3_signed_bob",
    ":com.android.apex.cts.shim.v3_signed_bob_rot",
  ],
  out: ["hash.txt"],
  cmd: "sha512sum -b $(in) | cut -d' ' -f1 | tee $(out)",
}

prebuilt_etc {
  name: "hash_v1",
  src: ":generate_hash_v1",
  filename: "hash.txt",
  installable: false,
}

apex {
  name: "com.android.apex.cts.shim.v1",
  manifest: "manifest.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_v1"],
  apps: ["CtsShim", "CtsShimPriv"],
  allowed_files: "default_shim_allowed_list.txt",
  updatable: false,
}

// This is to install the flattened version of com.android.apex.cts.shim.
// Because com.android.apex.cts.shim is provided as prebuilt and the build system
// doesn't support install "flattened" version from "prebult" yet, GSI, which should
// have both "flatttened" and "unflattened" APEXes, is missing the flattened version
// of com.android.apex.cts.shim.
// TODO(b/159426728):  When the build system can install "flattened" from "prebuilts",
// this can be removed.
override_apex {
  name: "com.android.apex.cts.shim.v1_with_prebuilts",
  base: "com.android.apex.cts.shim.v1",
  apps: ["CtsShimPrebuilt", "CtsShimPrivPrebuilt"],
  allowed_files: "prebuilts_shim_allowed_list.txt",
}

genrule {
  name: "com.android.apex.cts.shim_not_pre_installed.pem",
  out: ["com.android.apex.cts.shim_not_pre_installed.pem"],
  cmd: "openssl genrsa -out $(out) 4096",
}

genrule {
  name: "com.android.apex.cts.shim_not_pre_installed.pubkey",
  srcs: [":com.android.apex.cts.shim_not_pre_installed.pem"],
  out: ["com.android.apex.cts.shim_not_pre_installed.pubkey"],
  tools: ["avbtool"],
  cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
}

apex_key {
  name: "com.android.apex.cts.shim_not_pre_installed.key",
  private_key: ":com.android.apex.cts.shim_not_pre_installed.pem",
  public_key: ":com.android.apex.cts.shim_not_pre_installed.pubkey",
  installable: false,
}

apex {
  name: "com.android.apex.cts.shim_not_pre_installed",
  manifest: "manifest_not_pre_installed.json",
  androidManifest: "AndroidManifestNotPreInstalled.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim_not_pre_installed.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v2_different_certificate",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  certificate: ":com.android.apex.cts.shim.debug.cert",
  updatable: false,
}

android_app_certificate {
  name: "com.android.apex.cts.shim.debug.cert",
  certificate: "com.android.apex.cts.shim.debug.cert",
}

// Build rules to build shim apex with rotated keys

// We name the original key used to sign cts.shim.v1 package as alice.
// We then create a second key called bob. The second key bob is used to rotate the
// original key alice.

// Create private key bob in pem format
genrule {
  name: "com.android.apex.rotation.key.bob.pem",
  out: ["bob.pem"],
  cmd: "openssl req -x509 -newkey rsa:4096 -nodes -days 999999 -subj '/DN=/EMAILADDRESS=android@android.com/CN=Android/OU=Android/O=Android/L=Mountain View/ST=California/C=US' -keyout $(out)",
}

// Converts bob's private key to pk8 format
genrule {
  name: "com.android.apex.rotation.key.bob.pk8",
  srcs: [":com.android.apex.rotation.key.bob.pem"],
  out: ["bob.pk8"],
  cmd: "openssl pkcs8 -topk8 -inform PEM -outform DER -in $(in) -out $(out) -nocrypt",
}

// Extract bob's public key from its private key
genrule {
    name: "com.android.apex.rotation.key.bob.x509.pem",
    srcs: [":com.android.apex.rotation.key.bob.pem"],
    out: ["bob.x509.pem"],
    cmd: "openssl req -x509 -key $(in) -newkey rsa:4096 -nodes -days 999999 -subj '/DN=/EMAILADDRESS=android@android.com/CN=Android/OU=Android/O=Android/L=Mountain View/ST=California/C=US' -out $(out)",
}

// Create lineage file for rotating alice to bob
genrule {
  name: "com.android.apex.rotation.key.bob.rot",
  srcs: [
    "alice.pk8",
    "alice.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
    ":com.android.apex.rotation.key.bob.x509.pem",
  ],
  out: ["bob.rot"],
  tools: [":apksigner"],
  cmd: "$(location :apksigner) rotate --out $(out) --old-signer --key $(location alice.pk8) --cert $(location alice.x509.pem) --new-signer --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem)",
}

// Create lineage file for rotating alice to bob with rollback capability
genrule {
  name: "com.android.apex.rotation.key.bob.rot.rollback",
  srcs: [
    "alice.pk8",
    "alice.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
    ":com.android.apex.rotation.key.bob.x509.pem",
  ],
  out: ["bob.rot"],
  tools: [":apksigner"],
  cmd: "$(location :apksigner) rotate --out $(out) --old-signer --key $(location alice.pk8) --cert $(location alice.x509.pem) --set-rollback true --new-signer --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem)",
}

// v2 cts shim package signed by bob, without lineage
genrule {
  name: "com.android.apex.cts.shim.v2_signed_bob",
  out: ["com.android.apex.cts.shim.v2_signed_bob"],
  tools: [":apksigner"],
  srcs: [
    ":com.android.apex.cts.shim.v2",
    ":com.android.apex.rotation.key.bob.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
  ],
  dist: {
    targets: ["com.android.apex.cts.shim.v2_signed_bob"],
    dest: "com.android.apex.cts.shim.v2_signed_bob.apex",
  },
  cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --out $(out) $(location :com.android.apex.cts.shim.v2)",
}

// v2 cts shim package signed by bob + lineage
genrule {
  name: "com.android.apex.cts.shim.v2_signed_bob_rot",
  out: ["com.android.apex.cts.shim.v2_signed_bob_rot"],
  tools: [":apksigner"],
  srcs: [
    ":com.android.apex.cts.shim.v2",
    ":com.android.apex.rotation.key.bob.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
    ":com.android.apex.rotation.key.bob.rot",
  ],
  dist: {
    targets: ["com.android.apex.cts.shim.v2_signed_bob_rot"],
    dest: "com.android.apex.cts.shim.v2_signed_bob_rot.apex",
  },
  cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot) --out $(out) $(location :com.android.apex.cts.shim.v2)",
}

// v2 cts shim package signed by bob + lineage + rollback capability
genrule {
  name: "com.android.apex.cts.shim.v2_signed_bob_rot_rollback",
  out: ["com.android.apex.cts.shim.v2_signed_bob_rot_rollback"],
  tools: [":apksigner"],
  srcs: [
    ":com.android.apex.cts.shim.v2",
    ":com.android.apex.rotation.key.bob.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
    ":com.android.apex.rotation.key.bob.rot.rollback",
  ],
  dist: {
    targets: ["com.android.apex.cts.shim.v2_signed_bob_rot_rollback"],
    dest: "com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex",
  },
  cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot.rollback) --out $(out) $(location :com.android.apex.cts.shim.v2)",
}

// v3 cts shim package signed by bob
genrule {
  name: "com.android.apex.cts.shim.v3_signed_bob",
  out: ["com.android.apex.cts.shim.v3_signed_bob"],
  tools: [":apksigner"],
  srcs: [
    ":com.android.apex.cts.shim.v3",
    ":com.android.apex.rotation.key.bob.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
  ],
  dist: {
    targets: ["com.android.apex.cts.shim.v3_signed_bob"],
    dest: "com.android.apex.cts.shim.v3_signed_bob.apex",
  },
  cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --out $(out) $(location :com.android.apex.cts.shim.v3)",
}

// v3 cts shim package signed by bob + lineage
genrule {
  name: "com.android.apex.cts.shim.v3_signed_bob_rot",
  out: ["com.android.apex.cts.shim.v3_signed_bob_rot"],
  tools: [":apksigner"],
  srcs: [
    ":com.android.apex.cts.shim.v3",
    ":com.android.apex.rotation.key.bob.x509.pem",
    ":com.android.apex.rotation.key.bob.pk8",
    ":com.android.apex.rotation.key.bob.rot",
  ],
  dist: {
    targets: ["com.android.apex.cts.shim.v3_signed_bob_rot"],
    dest: "com.android.apex.cts.shim.v3_signed_bob_rot.apex",
  },
  cmd: "$(location :apksigner) sign --v1-signing-enabled false --v2-signing-enabled false --key $(location :com.android.apex.rotation.key.bob.pk8) --cert $(location :com.android.apex.rotation.key.bob.x509.pem) --lineage $(location :com.android.apex.rotation.key.bob.rot) --out $(out) $(location :com.android.apex.cts.shim.v3)",
}

// This one is only used in ApexdHostTest and not meant to be installed
// and hence shouldn't be allowed in hash.txt of v1 shim APEX.
apex {
  name: "com.android.apex.cts.shim.v2_legacy",
  manifest: "manifest_v2.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  apps: ["CtsShim", "CtsShimPriv"],
  installable: false,
  min_sdk_version: "29",
  updatable: false,
}

genrule {
  name: "com.android.apex.cts.shim.v2_no_pb",
  srcs: [":com.android.apex.cts.shim.v2_legacy"],
  out: ["com.android.apex.cts.shim.v2_no_pb.apex"],
  tools: ["zip2zip"],
  cmd: "$(location zip2zip) -i $(in) -x apex_manifest.pb -o $(out)",
}

// Apex shim that targets an old sdk (P)
apex {
  name: "com.android.apex.cts.shim.v2_sdk_target_p",
  // Use manifest_v2_rebootless to also re-use this APEX in the rebootless update test case.
  manifest: "manifest_v2_rebootless.json",
  androidManifest: "AndroidManifestSdkTargetP.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  apps: ["CtsShim", "CtsShimPriv"],
  updatable: false,
}

// Apex shim with apk-in-apex that targets sdk P
apex {
  name: "com.android.apex.cts.shim.v2_apk_in_apex_sdk_target_p",
  manifest: "manifest_v2.json",
  androidManifest: "AndroidManifest.xml",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  apps: ["CtsShimTargetPSdk"],
  installable: false,
  updatable: false,
}

// Apex shim with unsigned apk
genrule {
  name: "com.android.apex.cts.shim.v2_unsigned_apk_container",
  // Use shim.v2_rebootless to re-use same APEX in the rebootless update test case.
  srcs: [":com.android.apex.cts.shim.v2_rebootless"],
  out: ["com.android.apex.cts.shim.v2_unsigned_apk_container.apex"],
  cmd: "cp -v $(in) $(out) && zip -d $(out) META-INF*",
}

// Apex shim for testing rebootless updates
apex {
  name: "com.android.apex.cts.shim.v2_rebootless",
  manifest: "manifest_v2_rebootless.json",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  updatable: false,
}

apex {
  name: "com.android.apex.cts.shim.v3_rebootless",
  manifest: "manifest_v3_rebootless.json",
  file_contexts: ":apex.test-file_contexts",
  key: "com.android.apex.cts.shim.key",
  prebuilts: ["hash_of_dev_null"],
  installable: false,
  updatable: false,
}