// Copyright 2017 Brian Smith.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

//! PKCS#8 is specified in [RFC 5958].
//!
//! [RFC 5958]: https://tools.ietf.org/html/rfc5958

use crate::{ec, error, io::der};

pub(crate) struct PublicKeyOptions {
    /// Should the wrong public key ASN.1 tagging used by early implementations
    /// of PKCS#8 v2 (including earlier versions of *ring*) be accepted?
    pub accept_legacy_ed25519_public_key_tag: bool,
}

pub(crate) enum Version {
    V1Only,
    V1OrV2(PublicKeyOptions),
    V2Only(PublicKeyOptions),
}

/// A template for constructing PKCS#8 documents.
///
/// Note that this only works for ECC.
pub(crate) struct Template {
    pub bytes: &'static [u8],

    // The range within `bytes` that holds the value (not including the tag and
    // length) for use in the PKCS#8 document's privateKeyAlgorithm field.
    pub alg_id_range: core::ops::Range<usize>,

    // `bytes[alg_id_range][curve_id_index..]` contains the OID identifying the,
    // curve, including the tag and length.
    pub curve_id_index: usize,

    // `bytes` will be split into two parts at `private_key_index`, where the
    // first part is written before the private key and the second part is
    // written after the private key. The public key is written after the second
    // part.
    pub private_key_index: usize,
}

impl Template {
    #[inline]
    fn alg_id_value(&self) -> untrusted::Input {
        untrusted::Input::from(self.alg_id_value_())
    }

    fn alg_id_value_(&self) -> &[u8] {
        &self.bytes[self.alg_id_range.start..self.alg_id_range.end]
    }

    #[inline]
    pub fn curve_oid(&self) -> untrusted::Input {
        untrusted::Input::from(&self.alg_id_value_()[self.curve_id_index..])
    }
}

/// Parses an unencrypted PKCS#8 private key, verifies that it is the right type
/// of key, and returns the key value.
///
/// PKCS#8 is specified in [RFC 5958].
///
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958
pub(crate) fn unwrap_key<'a>(
    template: &Template,
    version: Version,
    input: untrusted::Input<'a>,
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
    unwrap_key_(template.alg_id_value(), version, input)
}

/// Parses an unencrypted PKCS#8 private key, verifies that it is the right type
/// of key, and returns the key value.
///
/// `alg_id` must be the encoded value (not including the outermost `SEQUENCE`
/// tag and length) of the `AlgorithmIdentifier` that identifies the key type.
/// The result will be an encoded `RSAPrivateKey` or `ECPrivateKey` or similar.
///
/// PKCS#8 is specified in [RFC 5958].
///
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958
pub(crate) fn unwrap_key_<'a>(
    alg_id: untrusted::Input,
    version: Version,
    input: untrusted::Input<'a>,
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
    input.read_all(error::KeyRejected::invalid_encoding(), |input| {
        der::nested(
            input,
            der::Tag::Sequence,
            error::KeyRejected::invalid_encoding(),
            |input| unwrap_key__(alg_id, version, input),
        )
    })
}

fn unwrap_key__<'a>(
    alg_id: untrusted::Input,
    version: Version,
    input: &mut untrusted::Reader<'a>,
) -> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>), error::KeyRejected> {
    let actual_version = der::small_nonnegative_integer(input)
        .map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;

    // Do things in a specific order to return more useful errors:
    // 1. Check for completely unsupported version.
    // 2. Check for algorithm mismatch.
    // 3. Check for algorithm-specific version mismatch.

    if actual_version > 1 {
        return Err(error::KeyRejected::version_not_supported());
    };

    let actual_alg_id = der::expect_tag_and_get_value(input, der::Tag::Sequence)
        .map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
    if actual_alg_id.as_slice_less_safe() != alg_id.as_slice_less_safe() {
        return Err(error::KeyRejected::wrong_algorithm());
    }

    let public_key_options = match (actual_version, version) {
        (0, Version::V1Only) => None,
        (0, Version::V1OrV2(_)) => None,
        (1, Version::V1OrV2(options)) | (1, Version::V2Only(options)) => Some(options),
        _ => {
            return Err(error::KeyRejected::version_not_supported());
        }
    };

    let private_key = der::expect_tag_and_get_value(input, der::Tag::OctetString)
        .map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;

    // Ignore any attributes that are present.
    if input.peek(der::Tag::ContextSpecificConstructed0 as u8) {
        let _ = der::expect_tag_and_get_value(input, der::Tag::ContextSpecificConstructed0)
            .map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
    }

    let public_key = if let Some(options) = public_key_options {
        if input.at_end() {
            return Err(error::KeyRejected::public_key_is_missing());
        }

        const INCORRECT_LEGACY: der::Tag = der::Tag::ContextSpecificConstructed1;
        let result =
            if options.accept_legacy_ed25519_public_key_tag && input.peek(INCORRECT_LEGACY as u8) {
                der::nested(
                    input,
                    INCORRECT_LEGACY,
                    error::Unspecified,
                    der::bit_string_with_no_unused_bits,
                )
            } else {
                der::bit_string_tagged_with_no_unused_bits(der::Tag::ContextSpecific1, input)
            };
        let public_key =
            result.map_err(|error::Unspecified| error::KeyRejected::invalid_encoding())?;
        Some(public_key)
    } else {
        None
    };

    Ok((private_key, public_key))
}

/// A generated PKCS#8 document.
pub struct Document {
    bytes: [u8; ec::PKCS8_DOCUMENT_MAX_LEN],
    len: usize,
}

impl AsRef<[u8]> for Document {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        &self.bytes[..self.len]
    }
}

pub(crate) fn wrap_key(template: &Template, private_key: &[u8], public_key: &[u8]) -> Document {
    let mut result = Document {
        bytes: [0; ec::PKCS8_DOCUMENT_MAX_LEN],
        len: template.bytes.len() + private_key.len() + public_key.len(),
    };
    wrap_key_(
        template,
        private_key,
        public_key,
        &mut result.bytes[..result.len],
    );
    result
}

/// Formats a private key "prefix||private_key||middle||public_key" where
/// `template` is "prefix||middle" split at position `private_key_index`.
fn wrap_key_(template: &Template, private_key: &[u8], public_key: &[u8], bytes: &mut [u8]) {
    let (before_private_key, after_private_key) =
        template.bytes.split_at(template.private_key_index);
    let private_key_end_index = template.private_key_index + private_key.len();
    bytes[..template.private_key_index].copy_from_slice(before_private_key);
    bytes[template.private_key_index..private_key_end_index].copy_from_slice(private_key);
    bytes[private_key_end_index..(private_key_end_index + after_private_key.len())]
        .copy_from_slice(after_private_key);
    bytes[(private_key_end_index + after_private_key.len())..].copy_from_slice(public_key);
}
