// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

//! This module provide API to communicate with attestation service (AS) to get
//! attestation report endorsed by AS.

use crate::platform;
use crate::AttestationAlgorithm;
use crate::AttestationServiceConfig;
use crate::EndorsedAttestationReport;

use std::collections::HashMap;
use std::io::{Read, Write};
use std::net::TcpStream;
use std::prelude::v1::*;
use std::sync::Arc;

use anyhow::{anyhow, bail, Result};
use log::{debug, trace};
use serde_json::json;
use sgx_types::*;

/// Root certification of the DCAP attestation service provider.
#[cfg(dcap)]
const DCAP_ROOT_CA_CERT: &str = include_str!("../../keys/dcap_root_ca_cert.pem");

/// URL path to get the report from the attestation service.
const AS_REPORT_URL: &str = "/sgx/dev/attestation/v4/report";

#[derive(thiserror::Error, Debug)]
pub(crate) enum AttestationServiceError {
    #[error("Invalid attestation service address.")]
    InvalidAddress,
    #[error("Attestation service responds an malformed response.")]
    InvalidResponse,
    #[error("{0} is missing in HTTP header.")]
    MissingHeader(String),
    #[error(
        "Invalid Attestation Evidence Payload. The client should not repeat the
        request without modifications."
    )]
    BadRequest,
    #[error("Failed to authenticate or authorize request.")]
    Unauthorized,
    #[error("Internal error occurred.")]
    InternalServerError,
    #[error(
        "Service is currently not able to process the request (due to a
        temporary overloading or maintenance). This is a temporary state –the
        same request can be repeated after some time."
    )]
    ServiceUnavailable,
    #[error("TLS connection error.")]
    TlsError,
    #[error("Attestation service responds an unknown error.")]
    Unknown,
}

impl EndorsedAttestationReport {
    pub(crate) fn new(
        att_service_cfg: &AttestationServiceConfig,
        pub_k: sgx_types::sgx_ec256_public_t,
    ) -> anyhow::Result<Self> {
        let (mut ak_id, qe_target_info) = platform::init_sgx_quote()?;

        // For IAS-based attestation, we need to fill our SPID (obtained from Intel)
        // into the attestation key id. For DCAP-based attestation, SPID should be 0
        const SPID_OFFSET: usize = std::mem::size_of::<sgx_ql_att_key_id_t>();
        ak_id.att_key_id[SPID_OFFSET..(SPID_OFFSET + att_service_cfg.spid.id.len())]
            .clone_from_slice(&att_service_cfg.spid.id);

        let sgx_report = platform::create_sgx_isv_enclave_report(pub_k, qe_target_info)?;
        let quote = platform::get_sgx_quote(&ak_id, sgx_report)?;
        let as_report = get_report(
            &att_service_cfg.algo,
            &att_service_cfg.as_url,
            &att_service_cfg.api_key,
            &quote,
        )?;

        Ok(as_report)
    }
}

fn new_tls_stream(url: &url::Url) -> Result<rustls::StreamOwned<rustls::ClientSession, TcpStream>> {
    let host_str = url
        .host_str()
        .ok_or_else(|| AttestationServiceError::InvalidAddress)?;
    let dns_name = webpki::DNSNameRef::try_from_ascii_str(host_str)?;
    let mut config = rustls::ClientConfig::new();
    #[cfg(dcap)]
    config
        .root_store
        .add_pem_file(&mut DCAP_ROOT_CA_CERT.to_string().as_bytes())
        .map_err(|_| AttestationServiceError::TlsError)?;
    config
        .root_store
        .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
    let client = rustls::ClientSession::new(&Arc::new(config), dns_name);
    let addrs = url.socket_addrs(|| match url.scheme() {
        "https" => Some(443),
        _ => None,
    })?;
    let socket = TcpStream::connect(&*addrs)?;
    let stream = rustls::StreamOwned::new(client, socket);

    Ok(stream)
}

/// Get attestation report form the attestation service (e.g., Intel Attestation
/// Service and customized DCAP attestation service).
fn get_report(
    algo: &AttestationAlgorithm,
    url: &url::Url,
    api_key: &str,
    quote: &[u8],
) -> Result<EndorsedAttestationReport> {
    debug!("get_report");
    let encoded_quote = base64::encode(quote);
    let encoded_json = json!({ "isvEnclaveQuote": encoded_quote }).to_string();
    let host_str = url
        .host_str()
        .ok_or_else(|| AttestationServiceError::InvalidAddress)?;

    let request = format!(
        "POST {} HTTP/1.1\r\n\
         HOST: {}\r\n\
         Ocp-Apim-Subscription-Key: {}\r\n\
         Connection: Close\r\n\
         Content-Length: {}\r\n\
         Content-Type: application/json\r\n\r\n\
         {}",
        AS_REPORT_URL,
        host_str,
        api_key,
        encoded_json.len(),
        encoded_json
    );
    trace!("{}", request);

    let mut stream = new_tls_stream(url).map_err(|_| AttestationServiceError::TlsError)?;
    stream.write_all(request.as_bytes())?;
    let mut response = Vec::new();
    stream.read_to_end(&mut response)?;

    trace!("{}", String::from_utf8_lossy(&response));

    let mut headers = [httparse::EMPTY_HEADER; 16];
    let mut http_response = httparse::Response::new(&mut headers);

    debug!("http_response.parse");
    let header_len = match http_response
        .parse(&response)
        .map_err(|_| AttestationServiceError::InvalidResponse)?
    {
        httparse::Status::Complete(s) => s,
        _ => bail!(AttestationServiceError::InvalidResponse),
    };

    match http_response.code {
        Some(200) => {
            debug!("Operation successful.");
        }
        Some(400) => {
            debug!(
                "Invalid Attestation Evidence Payload. The client should not
                 repeat the request without modifications."
            );
            bail!(AttestationServiceError::BadRequest);
        }
        Some(401) => {
            debug!("Failed to authenticate or authorize request.");
            bail!(AttestationServiceError::Unauthorized);
        }
        Some(500) => {
            debug!("Internal error occurred.");
            bail!(AttestationServiceError::InternalServerError);
        }
        Some(503) => {
            debug!(
                "Service is currently not able to process the request (due to a
                 temporary overloading or maintenance). This is a temporary
                 state, the same request can be repeated after some time."
            );
            bail!(AttestationServiceError::ServiceUnavailable);
        }
        _ => {
            debug!("Attestation service responds an unknown error");
            bail!(AttestationServiceError::Unknown);
        }
    }

    let header_map = parse_headers(&http_response);

    debug!("get_content_length");
    if !header_map.contains_key("Content-Length")
        || header_map
            .get("Content-Length")
            .ok_or_else(|| AttestationServiceError::MissingHeader("Content-Length".to_string()))?
            .parse::<u32>()
            .unwrap_or(0)
            == 0
    {
        bail!(AttestationServiceError::MissingHeader(
            "Content-Length".to_string()
        ));
    }

    debug!("get_signature");
    let signature_header = match algo {
        AttestationAlgorithm::SgxEpid => "X-IASReport-Signature",
        AttestationAlgorithm::SgxEcdsa => "X-DCAPReport-Signature",
    };
    let signature = header_map
        .get(signature_header)
        .ok_or_else(|| AttestationServiceError::MissingHeader(signature_header.to_string()))?;
    let signature = base64::decode(signature)?;

    debug!("get_signing_cert");
    let signing_cert_header = match algo {
        AttestationAlgorithm::SgxEpid => "X-IASReport-Signing-Certificate",
        AttestationAlgorithm::SgxEcdsa => "X-DCAPReport-Signing-Certificate",
    };
    let signing_cert = {
        let cert_str = header_map.get(signing_cert_header).ok_or_else(|| {
            AttestationServiceError::MissingHeader(signing_cert_header.to_string())
        })?;
        let decoded_cert = percent_encoding::percent_decode_str(cert_str).decode_utf8()?;
        let certs = rustls::internal::pemfile::certs(&mut decoded_cert.as_bytes())
            .map_err(|_| anyhow!("pemfile error"))?;
        certs[0].0.clone()
    };

    debug!("return_report");
    let report = response[header_len..].to_vec();
    Ok(EndorsedAttestationReport {
        report,
        signature,
        signing_cert,
    })
}

fn parse_headers(resp: &httparse::Response) -> HashMap<String, String> {
    debug!("parse_headers");
    let mut header_map = HashMap::new();
    for h in resp.headers.iter() {
        header_map.insert(
            h.name.to_owned(),
            String::from_utf8_lossy(h.value).into_owned(),
        );
    }

    header_map
}
