// Copyright 2022, 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.

//! Integration test for Rialto.

use android_system_virtualizationservice::{
    aidl::android::system::virtualizationservice::{
        VirtualMachineConfig::VirtualMachineConfig,
        VirtualMachineRawConfig::VirtualMachineRawConfig,
    },
    binder::{ParcelFileDescriptor, ProcessState},
};
use anyhow::{bail, Context, Result};
use bssl_avf::{rand_bytes, sha256, EcKey, PKey};
use client_vm_csr::generate_attestation_key_and_csr;
use coset::{CborSerializable, CoseMac0, CoseSign};
use hwtrust::{rkp, session::Session};
use log::{info, warn};
use service_vm_comm::{
    ClientVmAttestationParams, Csr, CsrPayload, EcdsaP256KeyPair, GenerateCertificateRequestParams,
    Request, RequestProcessingError, Response, VmType,
};
use service_vm_fake_chain::client_vm::{
    fake_client_vm_dice_artifacts, fake_sub_components, SubComponent,
};
use service_vm_manager::ServiceVm;
use std::fs;
use std::fs::File;
use std::panic;
use std::path::PathBuf;
use std::str::FromStr;
use vmclient::VmInstance;
use x509_cert::{
    certificate::{Certificate, Version},
    der::{self, asn1, Decode, Encode},
    name::Name,
    spki::{AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfo},
};

const UNSIGNED_RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto_unsigned.bin";
const INSTANCE_IMG_PATH: &str = "/data/local/tmp/rialto_test/arm64/instance.img";
const TEST_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";

#[cfg(dice_changes)]
#[test]
fn process_requests_in_protected_vm() -> Result<()> {
    if hypervisor_props::is_protected_vm_supported()? {
        // The test is skipped if the feature flag |dice_changes| is not enabled, because when
        // the flag is off, the DICE chain is truncated in the pvmfw, and the service VM cannot
        // verify the chain due to the missing entries in the chain.
        check_processing_requests(VmType::ProtectedVm)
    } else {
        warn!("pVMs are not supported on device, skipping test");
        Ok(())
    }
}

#[test]
fn process_requests_in_non_protected_vm() -> Result<()> {
    check_processing_requests(VmType::NonProtectedVm)
}

fn check_processing_requests(vm_type: VmType) -> Result<()> {
    let mut vm = start_service_vm(vm_type)?;

    check_processing_reverse_request(&mut vm)?;
    let key_pair = check_processing_generating_key_pair_request(&mut vm)?;
    check_processing_generating_certificate_request(&mut vm, &key_pair.maced_public_key)?;
    check_attestation_request(&mut vm, &key_pair, vm_type)?;
    Ok(())
}

fn check_processing_reverse_request(vm: &mut ServiceVm) -> Result<()> {
    let message = "abc".repeat(500);
    let request = Request::Reverse(message.as_bytes().to_vec());

    let response = vm.process_request(request)?;
    info!("Received response: {response:?}.");

    let expected_response: Vec<u8> = message.as_bytes().iter().rev().cloned().collect();
    assert_eq!(Response::Reverse(expected_response), response);
    Ok(())
}

fn check_processing_generating_key_pair_request(vm: &mut ServiceVm) -> Result<EcdsaP256KeyPair> {
    let request = Request::GenerateEcdsaP256KeyPair;

    let response = vm.process_request(request)?;
    info!("Received response: {response:?}.");

    match response {
        Response::GenerateEcdsaP256KeyPair(key_pair) => {
            assert_array_has_nonzero(&key_pair.maced_public_key);
            assert_array_has_nonzero(&key_pair.key_blob);
            Ok(key_pair)
        }
        _ => bail!("Incorrect response type: {response:?}"),
    }
}

fn assert_array_has_nonzero(v: &[u8]) {
    assert!(v.iter().any(|&x| x != 0))
}

fn check_processing_generating_certificate_request(
    vm: &mut ServiceVm,
    maced_public_key: &[u8],
) -> Result<()> {
    let params = GenerateCertificateRequestParams {
        keys_to_sign: vec![maced_public_key.to_vec()],
        challenge: vec![],
    };
    let request = Request::GenerateCertificateRequest(params);

    let response = vm.process_request(request)?;
    info!("Received response: {response:?}.");

    match response {
        Response::GenerateCertificateRequest(csr) => check_csr(csr),
        _ => bail!("Incorrect response type: {response:?}"),
    }
}

fn check_attestation_request(
    vm: &mut ServiceVm,
    remotely_provisioned_key_pair: &EcdsaP256KeyPair,
    vm_type: VmType,
) -> Result<()> {
    /// The following data was generated randomly with urandom.
    const CHALLENGE: [u8; 16] = [
        0x7d, 0x86, 0x58, 0x79, 0x3a, 0x09, 0xdf, 0x1c, 0xa5, 0x80, 0x80, 0x15, 0x2b, 0x13, 0x17,
        0x5c,
    ];
    let dice_artifacts = fake_client_vm_dice_artifacts()?;
    let attestation_data = generate_attestation_key_and_csr(&CHALLENGE, &dice_artifacts)?;
    let cert_chain = fs::read(TEST_CERT_CHAIN_PATH)?;
    // The certificate chain contains several certificates, but we only need the first one.
    // Parsing the data with trailing data always fails with a `TrailingData` error.
    let cert_len: usize = match Certificate::from_der(&cert_chain).unwrap_err().kind() {
        der::ErrorKind::TrailingData { decoded, .. } => decoded.try_into().unwrap(),
        e => bail!("Unexpected error: {e}"),
    };

    // Builds the mock parameters for the client VM attestation.
    // The `csr` and `remotely_provisioned_key_blob` parameters are extracted from the same
    // libraries as in production.
    // The `remotely_provisioned_cert` parameter is an RKP certificate extracted from a test
    // certificate chain retrieved from RKPD.
    let params = ClientVmAttestationParams {
        csr: attestation_data.csr.clone().into_cbor_vec()?,
        remotely_provisioned_key_blob: remotely_provisioned_key_pair.key_blob.to_vec(),
        remotely_provisioned_cert: cert_chain[..cert_len].to_vec(),
    };
    let request = Request::RequestClientVmAttestation(params);

    let response = vm.process_request(request)?;
    info!("Received response: {response:?}.");

    match response {
        Response::RequestClientVmAttestation(certificate) => {
            // The end-to-end test for non-protected VM attestation works because both the service
            // VM and the client VM use the same fake DICE chain.
            assert_eq!(vm_type, VmType::NonProtectedVm);
            check_certificate_for_client_vm(
                &certificate,
                &remotely_provisioned_key_pair.maced_public_key,
                &attestation_data.csr,
                &Certificate::from_der(&cert_chain[..cert_len]).unwrap(),
            )?;
            Ok(())
        }
        Response::Err(RequestProcessingError::InvalidDiceChain) => {
            // The end-to-end test for protected VM attestation doesn't work because the service VM
            // compares the fake DICE chain in the CSR with the real DICE chain.
            // We cannot generate a valid DICE chain with the same payloads up to pvmfw.
            assert_eq!(vm_type, VmType::ProtectedVm);
            Ok(())
        }
        _ => bail!("Incorrect response type: {response:?}"),
    }
}

fn check_vm_components(vm_components: &asn1::SequenceOf<asn1::Any, 4>) -> Result<()> {
    let expected_components = fake_sub_components();
    assert_eq!(expected_components.len(), vm_components.len());
    for (i, expected_component) in expected_components.iter().enumerate() {
        check_vm_component(vm_components.get(i).unwrap(), expected_component)?;
    }
    Ok(())
}

fn check_vm_component(vm_component: &asn1::Any, expected_component: &SubComponent) -> Result<()> {
    let vm_component = vm_component.decode_as::<asn1::SequenceOf<asn1::Any, 4>>().unwrap();
    assert_eq!(4, vm_component.len());
    let name = vm_component.get(0).unwrap().decode_as::<asn1::Utf8StringRef>().unwrap();
    assert_eq!(expected_component.name, name.as_ref());
    let version = vm_component.get(1).unwrap().decode_as::<u64>().unwrap();
    assert_eq!(expected_component.version, version);
    let code_hash = vm_component.get(2).unwrap().decode_as::<asn1::OctetString>().unwrap();
    assert_eq!(expected_component.code_hash, code_hash.as_bytes());
    let authority_hash = vm_component.get(3).unwrap().decode_as::<asn1::OctetString>().unwrap();
    assert_eq!(expected_component.authority_hash, authority_hash.as_bytes());
    Ok(())
}

fn check_certificate_for_client_vm(
    certificate: &[u8],
    maced_public_key: &[u8],
    csr: &Csr,
    parent_certificate: &Certificate,
) -> Result<()> {
    let cose_mac = CoseMac0::from_slice(maced_public_key)?;
    let authority_public_key =
        EcKey::from_cose_public_key_slice(&cose_mac.payload.unwrap()).unwrap();
    let cert = Certificate::from_der(certificate).unwrap();

    // Checks the certificate signature against the authority public key.
    const ECDSA_WITH_SHA_256: ObjectIdentifier =
        ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.2");
    let expected_algorithm = AlgorithmIdentifier { oid: ECDSA_WITH_SHA_256, parameters: None };
    assert_eq!(expected_algorithm, cert.signature_algorithm);
    let tbs_cert = cert.tbs_certificate;
    let digest = sha256(&tbs_cert.to_der().unwrap()).unwrap();
    authority_public_key
        .ecdsa_verify_der(cert.signature.raw_bytes(), &digest)
        .expect("Failed to verify the certificate signature with the authority public key");

    // Checks that the certificate's subject public key is equal to the key in the CSR.
    let cose_sign = CoseSign::from_slice(&csr.signed_csr_payload)?;
    let csr_payload =
        cose_sign.payload.as_ref().and_then(|v| CsrPayload::from_cbor_slice(v).ok()).unwrap();
    let subject_public_key = EcKey::from_cose_public_key_slice(&csr_payload.public_key).unwrap();
    let expected_spki_data =
        PKey::try_from(subject_public_key).unwrap().subject_public_key_info().unwrap();
    let expected_spki = SubjectPublicKeyInfo::from_der(&expected_spki_data).unwrap();
    assert_eq!(expected_spki, tbs_cert.subject_public_key_info);

    // Checks the certificate extension.
    const ATTESTATION_EXTENSION_OID: ObjectIdentifier =
        ObjectIdentifier::new_unwrap("1.3.6.1.4.1.11129.2.1.29.1");
    let extensions = tbs_cert.extensions.unwrap();
    assert_eq!(1, extensions.len());
    let extension = &extensions[0];
    assert_eq!(ATTESTATION_EXTENSION_OID, extension.extn_id);
    assert!(!extension.critical);
    let attestation_ext =
        asn1::SequenceOf::<asn1::Any, 3>::from_der(extension.extn_value.as_bytes()).unwrap();
    assert_eq!(3, attestation_ext.len());
    let challenge = attestation_ext.get(0).unwrap().decode_as::<asn1::OctetString>().unwrap();
    assert_eq!(csr_payload.challenge, challenge.as_bytes());
    let is_vm_secure = attestation_ext.get(1).unwrap().decode_as::<bool>().unwrap();
    assert!(
        !is_vm_secure,
        "The VM shouldn't be secure as the last payload added in the test is in Debug mode"
    );
    let vm_components =
        attestation_ext.get(2).unwrap().decode_as::<asn1::SequenceOf<asn1::Any, 4>>().unwrap();
    check_vm_components(&vm_components)?;

    // Checks other fields on the certificate
    assert_eq!(Version::V3, tbs_cert.version);
    assert_eq!(parent_certificate.tbs_certificate.validity, tbs_cert.validity);
    assert_eq!(
        Name::from_str("CN=Android Protected Virtual Machine Key").unwrap(),
        tbs_cert.subject
    );
    assert_eq!(parent_certificate.tbs_certificate.subject, tbs_cert.issuer);

    Ok(())
}

fn check_csr(csr: Vec<u8>) -> Result<()> {
    let _csr = rkp::Csr::from_cbor(&Session::default(), &csr[..]).context("Failed to parse CSR")?;
    Ok(())
}

fn start_service_vm(vm_type: VmType) -> Result<ServiceVm> {
    android_logger::init_once(
        android_logger::Config::default()
            .with_tag("rialto")
            .with_max_level(log::LevelFilter::Debug),
    );
    // Redirect panic messages to logcat.
    panic::set_hook(Box::new(|panic_info| {
        log::error!("{}", panic_info);
    }));
    // We need to start the thread pool for Binder to work properly, especially link_to_death.
    ProcessState::start_thread_pool();
    ServiceVm::start_vm(vm_instance(vm_type)?, vm_type)
}

fn vm_instance(vm_type: VmType) -> Result<VmInstance> {
    match vm_type {
        VmType::ProtectedVm => {
            service_vm_manager::protected_vm_instance(PathBuf::from(INSTANCE_IMG_PATH))
        }
        VmType::NonProtectedVm => nonprotected_vm_instance(),
    }
}

fn nonprotected_vm_instance() -> Result<VmInstance> {
    let rialto = File::open(UNSIGNED_RIALTO_PATH).context("Failed to open Rialto kernel binary")?;
    // Do not use `#allocateInstanceId` to generate the instance ID because the method
    // also adds an instance ID to the database it manages.
    // This is not necessary for this test.
    let mut instance_id = [0u8; 64];
    rand_bytes(&mut instance_id).unwrap();
    let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig {
        name: String::from("Non protected rialto"),
        bootloader: Some(ParcelFileDescriptor::new(rialto)),
        protectedVm: false,
        memoryMib: 300,
        platformVersion: "~1.0".to_string(),
        instanceId: instance_id,
        ..Default::default()
    });
    let console = Some(service_vm_manager::android_log_fd()?);
    let log = Some(service_vm_manager::android_log_fd()?);
    let virtmgr = vmclient::VirtualizationService::new().context("Failed to spawn VirtMgr")?;
    let service = virtmgr.connect().context("Failed to connect to VirtMgr")?;
    info!("Connected to VirtMgr for service VM");
    VmInstance::create(service.as_ref(), &config, console, /* consoleIn */ None, log, None)
        .context("Failed to create VM")
}
