// Copyright 2024 The BoringSSL Authors
//
// 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
//
//     https://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.

//! Elliptic Curve Digital Signature Algorithm.
//!
//! The module implements ECDSA for the NIST curves P-256 and P-384.
//!
//! ```
//! use bssl_crypto::{ecdsa, ec::P256};
//!
//! let key = ecdsa::PrivateKey::<P256>::generate();
//! // Publish your public key.
//! let public_key_bytes = key.to_der_subject_public_key_info();
//!
//! // Sign and publish some message.
//! let signed_message = b"hello world";
//! let mut sig = key.sign(signed_message);
//!
//! // Anyone with the public key can verify it.
//! let public_key = ecdsa::PublicKey::<P256>::from_der_subject_public_key_info(
//!     public_key_bytes.as_ref()).unwrap();
//! assert!(public_key.verify(signed_message, sig.as_slice()).is_ok());
//! ```

use crate::{
    ec::{self, Group},
    with_output_vec, Buffer, FfiSlice, InvalidSignatureError,
};
use alloc::vec::Vec;
use core::marker::PhantomData;

/// An ECDSA public key over the given curve.
pub struct PublicKey<C: ec::Curve> {
    point: ec::Point,
    marker: PhantomData<C>,
}

impl<C: ec::Curve> PublicKey<C> {
    /// Parse a public key in uncompressed X9.62 format. (This is the common
    /// format for elliptic curve points beginning with an 0x04 byte.)
    pub fn from_x962_uncompressed(x962: &[u8]) -> Option<Self> {
        let point = ec::Point::from_x962_uncompressed(C::group(), x962)?;
        Some(Self {
            point,
            marker: PhantomData,
        })
    }

    /// Serialize this key as uncompressed X9.62 format.
    pub fn to_x962_uncompressed(&self) -> Buffer {
        self.point.to_x962_uncompressed()
    }

    /// Parse a public key in compressed X9.62 point format.
    pub fn from_x962_compressed(x962: &[u8]) -> Option<Self> {
        let point = ec::Point::from_x962_compressed(C::group(), x962)?;
        Some(Self {
            point,
            marker: PhantomData,
        })
    }

    /// Serialize this key as compressed X9.62 format.
    ///
    /// WARNING: compressed form is rarely used and is not as well supported as
    /// the uncompressed form.
    pub fn to_x962_compressed(&self) -> Buffer {
        self.point.to_x962_compressed()
    }

    /// Parse a public key in SubjectPublicKeyInfo format.
    /// (This is found in, e.g., X.509 certificates.)
    pub fn from_der_subject_public_key_info(spki: &[u8]) -> Option<Self> {
        let point = ec::Point::from_der_subject_public_key_info(C::group(), spki)?;
        Some(Self {
            point,
            marker: PhantomData,
        })
    }

    /// Serialize this key in SubjectPublicKeyInfo format.
    pub fn to_der_subject_public_key_info(&self) -> Buffer {
        self.point.to_der_subject_public_key_info()
    }

    /// Verify `signature` as a valid ASN.1-based signature of a digest of
    /// `signed_msg` with this public key. SHA-256 will be used to produce the
    /// digest if the curve of this public key is P-256. SHA-384 will be used to
    /// produce the digest if the curve of this public key is P-384.
    pub fn verify(&self, signed_msg: &[u8], signature: &[u8]) -> Result<(), InvalidSignatureError> {
        let digest = C::hash(signed_msg);
        let result = self.point.with_point_as_ec_key(|ec_key| unsafe {
            // Safety: `ec_key` is valid per `with_point_as_ec_key`.
            bssl_sys::ECDSA_verify(
                /*type=*/ 0,
                digest.as_slice().as_ffi_ptr(),
                digest.len(),
                signature.as_ffi_ptr(),
                signature.len(),
                ec_key,
            )
        });
        if result == 1 {
            Ok(())
        } else {
            Err(InvalidSignatureError)
        }
    }

    /// Verify `signature` as a valid P1363-based signature of a digest of
    /// `signed_msg` with this public key. SHA-256 will be used to produce the
    /// digest if the curve of this public key is P-256. SHA-384 will be used to
    /// produce the digest if the curve of this public key is P-384.
    pub fn verify_p1363(
        &self,
        signed_msg: &[u8],
        signature: &[u8],
    ) -> Result<(), InvalidSignatureError> {
        let digest = C::hash(signed_msg);
        let result = self.point.with_point_as_ec_key(|ec_key| unsafe {
            // Safety: `ec_key` is valid per `with_point_as_ec_key`.
            bssl_sys::ECDSA_verify_p1363(
                digest.as_slice().as_ffi_ptr(),
                digest.len(),
                signature.as_ffi_ptr(),
                signature.len(),
                ec_key,
            )
        });
        if result == 1 {
            Ok(())
        } else {
            Err(InvalidSignatureError)
        }
    }
}

/// An ECDSA private key over the given curve.
pub struct PrivateKey<C: ec::Curve> {
    key: ec::Key,
    marker: PhantomData<C>,
}

impl<C: ec::Curve> Clone for PrivateKey<C> {
    fn clone(&self) -> Self {
        Self {
            key: self.key.clone(),
            marker: PhantomData,
        }
    }
}

/// Parsed `ECPrivateKey` dispatched into the corresponding curve types.
pub enum ParsedPrivateKey {
    /// A P-256 private key.
    P256(PrivateKey<ec::P256>),
    /// A P-384 private key.
    P384(PrivateKey<ec::P384>),
}

impl ParsedPrivateKey {
    /// Parses an ECPrivateKey structure froma DER encoded structure per [RFC 5915],
    /// whose curve is specified by the `ECParameters`.
    ///
    /// Unless the curve group is one of the variants of [`Group`], this method returns [`None`].
    ///
    /// [RFC 5915]: <https://datatracker.ietf.org/doc/html/rfc5915>
    pub fn from_der(der: &[u8]) -> Option<Self> {
        let key = ec::Key::from_der_ec_private_key_with_curve_names(der)?;
        match key.get_group()? {
            Group::P256 => Some(ParsedPrivateKey::P256(PrivateKey {
                key,
                marker: PhantomData,
            })),
            Group::P384 => Some(ParsedPrivateKey::P384(PrivateKey {
                key,
                marker: PhantomData,
            })),
        }
    }
}

impl<C: ec::Curve> PrivateKey<C> {
    /// Generate a random private key.
    pub fn generate() -> Self {
        Self {
            key: ec::Key::generate(C::group()),
            marker: PhantomData,
        }
    }

    /// Parse a `PrivateKey` from a zero-padded, big-endian representation of the secret scalar.
    pub fn from_big_endian(scalar: &[u8]) -> Option<Self> {
        let key = ec::Key::from_big_endian(C::group(), scalar)?;
        Some(Self {
            key,
            marker: PhantomData,
        })
    }

    /// Return the private key as zero-padded, big-endian bytes.
    pub fn to_big_endian(&self) -> Buffer {
        self.key.to_big_endian()
    }

    /// Parse an ECPrivateKey structure (from RFC 5915). The key must be on the
    /// specified curve.
    pub fn from_der_ec_private_key(der: &[u8]) -> Option<Self> {
        let key = ec::Key::from_der_ec_private_key(C::group(), der)?;
        Some(Self {
            key,
            marker: PhantomData,
        })
    }

    /// Serialize this private key as an ECPrivateKey structure (from RFC 5915).
    pub fn to_der_ec_private_key(&self) -> Buffer {
        self.key.to_der_ec_private_key()
    }

    /// Parse a PrivateKeyInfo structure (from RFC 5208), commonly called
    /// "PKCS#8 format". The key must be on the specified curve.
    pub fn from_der_private_key_info(der: &[u8]) -> Option<Self> {
        let key = ec::Key::from_der_private_key_info(C::group(), der)?;
        Some(Self {
            key,
            marker: PhantomData,
        })
    }

    // Caller must make sure that the group of the key matches `C`,
    // or else it panics.
    pub(crate) fn from_ec_key(key: ec::Key) -> Self {
        assert_eq!(key.get_group(), Some(C::group()));
        Self {
            key,
            marker: PhantomData,
        }
    }

    /// Serialize this private key as a PrivateKeyInfo structure (from RFC 5208),
    /// commonly called "PKCS#8 format".
    pub fn to_der_private_key_info(&self) -> Buffer {
        self.key.to_der_private_key_info()
    }

    /// Serialize the _public_ part of this key in uncompressed X9.62 format.
    pub fn to_x962_uncompressed(&self) -> Buffer {
        self.key.to_x962_uncompressed()
    }

    /// Serialize the _public_ part of this key in compressed X9.62 format.
    ///
    /// WARNING: compressed form is rarely used and is not as well supported as
    /// the uncompressed form.
    pub fn to_x962_compressed(&self) -> Buffer {
        self.key.to_x962_compressed()
    }

    /// Serialize this key in SubjectPublicKeyInfo format.
    pub fn to_der_subject_public_key_info(&self) -> Buffer {
        self.key.to_der_subject_public_key_info()
    }

    /// Return the public key corresponding to this private key.
    pub fn to_public_key(&self) -> PublicKey<C> {
        PublicKey {
            point: self.key.to_point(),
            marker: PhantomData,
        }
    }

    /// Sign a digest of `to_be_signed` using this key and return the
    /// ASN.1-based signature. SHA-256 will be used to produce the digest if the
    /// curve of this public key is P-256. SHA-384 will be used to produce the
    /// digest if the curve of this public key is P-384.
    pub fn sign(&self, to_be_signed: &[u8]) -> Vec<u8> {
        // Safety: `self.key` is valid by construction.
        let max_size = unsafe { bssl_sys::ECDSA_size(self.key.as_ffi_ptr()) };
        // No curve can be empty.
        assert_ne!(max_size, 0);

        let digest = C::hash(to_be_signed);

        unsafe {
            with_output_vec(max_size, |out_buf| {
                let mut out_len: core::ffi::c_uint = 0;
                // Safety: `out_buf` points to at least `max_size` bytes,
                // as required.
                let result = {
                    bssl_sys::ECDSA_sign(
                        /*type=*/ 0,
                        digest.as_slice().as_ffi_ptr(),
                        digest.len(),
                        out_buf,
                        &mut out_len,
                        self.key.as_ffi_ptr(),
                    )
                };
                // Signing should never fail unless we're out of memory,
                // which this crate doesn't handle.
                assert_eq!(result, 1);
                let out_len = out_len as usize;
                assert!(out_len <= max_size);
                // Safety: `out_len` bytes have been written.
                out_len
            })
        }
    }

    /// Sign a digest of `to_be_signed` using this key and return the
    /// P1363-based signature. SHA-256 will be used to produce the digest if
    /// the curve of this public key is P-256. SHA-384 will be used to produce
    /// the digest if the curve of this public key is P-384.
    pub fn sign_p1363(&self, to_be_signed: &[u8]) -> Vec<u8> {
        // Safety: `self.key` is valid by construction.
        let max_size = unsafe { bssl_sys::ECDSA_size_p1363(self.key.as_ffi_ptr()) };
        // No curve can be empty.
        assert_ne!(max_size, 0);

        let digest = C::hash(to_be_signed);

        unsafe {
            with_output_vec(max_size, |out_buf| {
                let mut out_len = 0usize;
                // Safety: `out_buf` points to at least `size` bytes, as
                // required.
                let result = {
                    bssl_sys::ECDSA_sign_p1363(
                        digest.as_slice().as_ffi_ptr(),
                        digest.len(),
                        out_buf,
                        &mut out_len,
                        max_size,
                        self.key.as_ffi_ptr(),
                    )
                };
                // Signing should never fail unless we're out of memory,
                // which this crate doesn't handle.
                assert_eq!(result, 1);
                assert!(out_len <= max_size);
                // Safety: `out_len` bytes have been written.
                out_len
            })
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::ec::{P256, P384};

    fn check_curve<C: ec::Curve>() {
        let signed_message = b"hello world";
        let key = PrivateKey::<C>::generate();
        let mut sig = key.sign(signed_message);
        let mut sig_p1363 = key.sign_p1363(signed_message);

        let public_key = PublicKey::<C>::from_der_subject_public_key_info(
            key.to_der_subject_public_key_info().as_ref(),
        )
        .unwrap();
        assert!(public_key.verify(signed_message, sig.as_slice()).is_ok());
        assert!(public_key
            .verify_p1363(signed_message, sig_p1363.as_slice())
            .is_ok());

        sig[10] ^= 1;
        assert!(public_key.verify(signed_message, sig.as_slice()).is_err());
        sig_p1363[10] ^= 1;
        assert!(public_key
            .verify_p1363(signed_message, sig_p1363.as_slice())
            .is_err());
    }

    fn check_compressed<C: ec::Curve>() {
        let signed_message = b"hello world";
        let key = PrivateKey::<C>::generate();
        let mut sig = key.sign(signed_message);
        let mut sig_p1363 = key.sign_p1363(signed_message);

        let public_key =
            PublicKey::<C>::from_x962_compressed(key.to_x962_compressed().as_ref()).unwrap();
        assert!(public_key.verify(signed_message, sig.as_slice()).is_ok());
        assert!(public_key
            .verify_p1363(signed_message, sig_p1363.as_slice())
            .is_ok());

        sig[10] ^= 1;
        assert!(public_key.verify(signed_message, sig.as_slice()).is_err());
        sig_p1363[10] ^= 1;
        assert!(public_key
            .verify_p1363(signed_message, sig_p1363.as_slice())
            .is_err());
    }

    fn check_parsing<C: ec::Curve>() {
        let key = PrivateKey::<C>::generate();
        let der = key.to_der_ec_private_key();
        let parsed = ParsedPrivateKey::from_der(der.as_ref()).unwrap();
        match parsed {
            ParsedPrivateKey::P256(_) => assert!(matches!(C::group(), Group::P256)),
            ParsedPrivateKey::P384(_) => assert!(matches!(C::group(), Group::P384)),
        }
    }

    #[test]
    fn p256() {
        check_curve::<P256>();
        check_compressed::<P256>();
        check_parsing::<P256>();
    }

    #[test]
    fn p384() {
        check_curve::<P384>();
        check_compressed::<P384>();
        check_parsing::<P384>();
    }
}
