// Copyright 2023 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.

//! Definitions of NIST elliptic curves.
//!
//! If you're looking for curve25519, see the `x25519` and `ed25519` modules.

// This module is substantially internal-only and is only public for the
// [`Curve`] trait, which is shared by ECDH and ECDSA.

use crate::{cbb_to_buffer, parse_with_cbs, scoped, sealed, Buffer, FfiSlice};
use alloc::{fmt::Debug, vec::Vec};
use core::ptr::{null, null_mut};

/// An elliptic curve.
///
/// ## Safety
/// The current EC implementation are thread-safe.
/// Implementers should make sure that further additions to the curve family
/// should respect thread-safety, too.
pub trait Curve: Debug + Sync + Send + sealed::Sealed {
    /// Return the underlying [`Group`] of the curve
    fn group() -> Group;

    /// Hash `data` using a hash function suitable for the curve. (I.e.
    /// SHA-256 for P-256 and SHA-384 for P-384.)
    #[doc(hidden)]
    fn hash(data: &[u8]) -> Vec<u8>;
}

/// The NIST P-256 curve, also called secp256r1.
#[derive(Debug)]
pub struct P256;

impl sealed::Sealed for P256 {}

impl Curve for P256 {
    fn group() -> Group {
        Group::P256
    }

    fn hash(data: &[u8]) -> Vec<u8> {
        crate::digest::Sha256::hash(data).to_vec()
    }
}

/// The NIST P-384 curve, also called secp384r1.
#[derive(Debug)]
pub struct P384;

impl sealed::Sealed for P384 {}

impl Curve for P384 {
    fn group() -> Group {
        Group::P384
    }

    fn hash(data: &[u8]) -> Vec<u8> {
        crate::digest::Sha384::hash(data).to_vec()
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[doc(hidden)]
pub enum Group {
    P256,
    P384,
}

impl Group {
    fn as_ffi_ptr(self) -> *const bssl_sys::EC_GROUP {
        // Safety: These functions cannot fail and no resources need to be
        // released in the future.
        match self {
            Group::P256 => unsafe { bssl_sys::EC_group_p256() },
            Group::P384 => unsafe { bssl_sys::EC_group_p384() },
        }
    }

    fn as_evp_pkey_alg(self) -> *const bssl_sys::EVP_PKEY_ALG {
        // Safety: These functions cannot fail and no resources need to be
        // released in the future.
        match self {
            Group::P256 => unsafe { bssl_sys::EVP_pkey_ec_p256() },
            Group::P384 => unsafe { bssl_sys::EVP_pkey_ec_p384() },
        }
    }
}

/// Point is a valid, finite point on some curve.
pub(crate) struct Point {
    group: *const bssl_sys::EC_GROUP,
    point: *mut bssl_sys::EC_POINT,
}

impl Point {
    /// Construct an uninitialized curve point. This is not public and all
    /// callers must ensure that the point is initialized before being returned.
    fn new(group: Group) -> Self {
        let group = group.as_ffi_ptr();
        // Safety: `group` is valid because it was constructed just above.
        let point = unsafe { bssl_sys::EC_POINT_new(group) };
        // `EC_POINT_new` only fails if out of memory, which is not a case that
        // is handled short of panicking.
        assert!(!point.is_null());
        Self { group, point }
    }

    /// Construct a point by multiplying the curve's base point by the given
    /// scalar.
    ///
    /// Safety: `scalar` must be a valid pointer.
    unsafe fn from_scalar(group: Group, scalar: *const bssl_sys::BIGNUM) -> Option<Self> {
        let point = Self::new(group);
        // Safety: the members of `point` are valid by construction. `scalar`
        // is assumed to be valid.
        let result = unsafe {
            bssl_sys::EC_POINT_mul(
                point.group,
                point.point,
                scalar,
                /*q=*/ null(),
                /*m=*/ null(),
                /*ctx=*/ null_mut(),
            )
        };
        if result != 1 {
            return None;
        }
        if 1 == unsafe { bssl_sys::EC_POINT_is_at_infinity(point.group, point.point) } {
            return None;
        }
        Some(point)
    }

    /// Duplicate the given finite point.
    unsafe fn clone_from_ptr(
        group: *const bssl_sys::EC_GROUP,
        point: *const bssl_sys::EC_POINT,
    ) -> Point {
        assert_eq!(0, unsafe {
            bssl_sys::EC_POINT_is_at_infinity(group, point)
        });

        // Safety: we assume that the caller is passing valid pointers
        let new_point = unsafe { bssl_sys::EC_POINT_dup(point, group) };
        // `EC_POINT_dup` only fails if out of memory, which is not a case that
        // is handled short of panicking.
        assert!(!new_point.is_null());

        Self {
            group,
            point: new_point,
        }
    }

    pub fn as_ffi_ptr(&self) -> *const bssl_sys::EC_POINT {
        self.point
    }

    fn from_x962(group: Group, x962: &[u8]) -> Option<Self> {
        let point = Self::new(group);
        // Safety: `point` is valid by construction. `x962` is a valid memory
        // buffer.
        let result = unsafe {
            bssl_sys::EC_POINT_oct2point(
                point.group,
                point.point,
                x962.as_ffi_ptr(),
                x962.len(),
                /*bn_ctx=*/ null_mut(),
            )
        };
        if result == 1 {
            // The X9.62 encoding of the point at infinity is 0x00, but
            // BoringSSL will never parse it. So this should be moot,
            // but `Point` must never contain infinity.
            assert_eq!(0, unsafe {
                bssl_sys::EC_POINT_is_at_infinity(point.group, point.point)
            });
            Some(point)
        } else {
            None
        }
    }

    /// Create a new point from an uncompressed X9.62 representation.
    ///
    /// (X9.62 is the standard representation of an elliptic-curve point that
    /// starts with an 0x04 byte.)
    pub fn from_x962_uncompressed(group: Group, x962: &[u8]) -> Option<Self> {
        const UNCOMPRESSED: u8 =
            bssl_sys::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED as u8;
        if x962.first()? != &UNCOMPRESSED {
            return None;
        }

        Self::from_x962(group, x962)
    }

    pub fn to_x962_uncompressed(&self) -> Buffer {
        // Safety: arguments are valid, `EC_KEY` ensures that the group is
        // correct for the point, and a `Point` is always finite.
        unsafe {
            to_x962(
                self.group,
                self.point,
                bssl_sys::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED,
            )
        }
    }

    pub fn from_x962_compressed(group: Group, x962: &[u8]) -> Option<Self> {
        // The first byte of the compressed format can be either 0x02 or 0x03,
        // to indicate whether the y coordinate of the point is even or odd.
        let first_byte = *x962.first()?;
        if first_byte != 2 && first_byte != 3 {
            return None;
        }

        Self::from_x962(group, x962)
    }

    /// WARNING: compressed form is rarely used and is not as well supported as
    /// the uncompressed form.
    pub fn to_x962_compressed(&self) -> Buffer {
        // Safety: arguments are valid, `EC_KEY` ensures that the group is
        // correct for the point, and a `Point` is always finite.
        unsafe {
            to_x962(
                self.group,
                self.point,
                bssl_sys::point_conversion_form_t::POINT_CONVERSION_COMPRESSED,
            )
        }
    }

    pub fn from_der_subject_public_key_info(group: Group, spki: &[u8]) -> Option<Self> {
        let alg = group.as_evp_pkey_alg();
        let mut pkey =
            scoped::EvpPkey::from_der_subject_public_key_info(spki, core::slice::from_ref(&alg))?;
        let ec_key = unsafe { bssl_sys::EVP_PKEY_get0_EC_KEY(pkey.as_ffi_ptr()) };
        // We only passed in one allowed algorithm, an EC algorithm.
        assert!(!ec_key.is_null());
        let parsed_group = unsafe { bssl_sys::EC_KEY_get0_group(ec_key) };
        // We only passed in one allowed algorithm, this EC group.
        assert!(parsed_group == group.as_ffi_ptr());
        let point = unsafe { bssl_sys::EC_KEY_get0_public_key(ec_key) };
        // A valid EC SPKI cannot be missing the public key.
        assert!(!point.is_null());
        // Safety: `ec_key` is still owned by `pkey` and doesn't need to be freed.
        Some(unsafe { Self::clone_from_ptr(parsed_group, point) })
    }

    /// Calls `func` with an `EC_KEY` that contains a copy of this point.
    pub fn with_point_as_ec_key<F, T>(&self, func: F) -> T
    where
        F: FnOnce(*mut bssl_sys::EC_KEY) -> T,
    {
        let mut ec_key = scoped::EcKey::new();
        // Safety: `self.group` is always valid by construction and this doesn't
        // pass ownership.
        assert_eq!(1, unsafe {
            bssl_sys::EC_KEY_set_group(ec_key.as_ffi_ptr(), self.group)
        });
        // Safety: `self.point` is always valid by construction and this doesn't
        // pass ownership.
        assert_eq!(1, unsafe {
            bssl_sys::EC_KEY_set_public_key(ec_key.as_ffi_ptr(), self.point)
        });
        func(ec_key.as_ffi_ptr())
    }

    pub fn to_der_subject_public_key_info(&self) -> Buffer {
        // Safety: `ec_key` is a valid pointer in this context.
        self.with_point_as_ec_key(|ec_key| unsafe { to_der_subject_public_key_info(ec_key) })
    }
}

// Safety:
//
// An `EC_POINT` can be used concurrently from multiple threads so long as no
// mutating operations are performed. The mutating operations used here are
// `EC_POINT_mul` and `EC_POINT_oct2point`, which can be observed by setting
// `point` to be `*const` in the struct and seeing what errors trigger.
//
// Both those operations are done internally, however, before a `Point` is
// returned. So, after construction, callers cannot mutate the `EC_POINT`.
unsafe impl Sync for Point {}
unsafe impl Send for Point {}

impl Drop for Point {
    fn drop(&mut self) {
        // Safety: `self.point` must be valid because only valid `Point`s can
        // be constructed. `self.group` does not need to be freed.
        unsafe { bssl_sys::EC_POINT_free(self.point) }
    }
}

/// Key holds both a public and private key. While BoringSSL allows an `EC_KEY`
/// to also be a) empty, b) holding only a private scalar, or c) holding only
// a public key, those cases are never exposed as a `Key`.
pub(crate) struct Key(*mut bssl_sys::EC_KEY);

impl Key {
    /// Construct an uninitialized key. This is not public and all
    /// callers must ensure that the key is initialized before being returned.
    fn new(group: Group) -> Self {
        let key = unsafe { bssl_sys::EC_KEY_new() };
        // `EC_KEY_new` only fails if out of memory, which is not a case that
        // is handled short of panicking.
        assert!(!key.is_null());

        // Setting the group on a fresh `EC_KEY` never fails.
        assert_eq!(1, unsafe {
            bssl_sys::EC_KEY_set_group(key, group.as_ffi_ptr())
        });

        Self(key)
    }

    pub fn as_ffi_ptr(&self) -> *const bssl_sys::EC_KEY {
        self.0
    }

    /// Generate a random private key.
    pub fn generate(group: Group) -> Self {
        let key = Self::new(group);
        // Generation only fails if out of memory, which is only handled by
        // panicking.
        assert_eq!(1, unsafe { bssl_sys::EC_KEY_generate_key(key.0) });
        // `EC_KEY_generate_key` is documented as also setting the public key.
        key
    }

    /// Construct a private key from a big-endian representation of the private
    /// scalar. The scalar must be zero padded to the correct length for the
    /// curve.
    pub fn from_big_endian(group: Group, scalar: &[u8]) -> Option<Self> {
        let key = Self::new(group);
        // Safety: `key.0` is always valid by construction.
        let result = unsafe { bssl_sys::EC_KEY_oct2priv(key.0, scalar.as_ffi_ptr(), scalar.len()) };
        if result != 1 {
            return None;
        }

        // BoringSSL allows an `EC_KEY` to have a private scalar without a
        // public point, but `Key` is never exposed in that state.

        // Safety: `key.0` is valid by construction. The returned value is
        // still owned the `EC_KEY`.
        let scalar = unsafe { bssl_sys::EC_KEY_get0_private_key(key.0) };
        assert!(!scalar.is_null());

        // Safety: `scalar` is a valid pointer.
        let point = unsafe { Point::from_scalar(group, scalar)? };
        // Safety: `key.0` is valid by construction, as is `point.point`. The
        // point is copied into the `EC_KEY` so ownership isn't being moved.
        let result = unsafe { bssl_sys::EC_KEY_set_public_key(key.0, point.point) };
        // Setting the public key should only fail if out of memory, which this
        // crate doesn't handle, or if the groups don't match, which is
        // impossible.
        assert_eq!(result, 1);

        Some(key)
    }

    pub fn to_big_endian(&self) -> Buffer {
        let mut ptr: *mut u8 = null_mut();
        // Safety: `self.0` is valid by construction. If this returns non-zero
        // then ptr holds ownership of a buffer.
        unsafe {
            let len = bssl_sys::EC_KEY_priv2buf(self.0, &mut ptr);
            assert!(len != 0);
            Buffer::new(ptr, len)
        }
    }

    /// Parses an ECPrivateKey structure from [RFC 5915].
    ///
    /// [RFC 5915]: <https://datatracker.ietf.org/doc/html/rfc5915>
    pub fn from_der_ec_private_key(group: Group, der: &[u8]) -> Option<Self> {
        let key = parse_with_cbs(
            der,
            // Safety: in this context, `key` is the non-null result of
            // `EC_KEY_parse_private_key`.
            |key| unsafe { bssl_sys::EC_KEY_free(key) },
            // Safety: `cbs` is valid per `parse_with_cbs` and `group` always
            // returns a valid pointer.
            |cbs| unsafe { bssl_sys::EC_KEY_parse_private_key(cbs, group.as_ffi_ptr()) },
        )?;
        Some(Self(key))
    }

    /// Parses an ECPrivateKey structure from [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_ec_private_key_with_curve_names(der: &[u8]) -> Option<Self> {
        let key = parse_with_cbs(
            der,
            // Safety: in this context, `key` is the non-null result of
            // `EC_KEY_parse_private_key`.
            |key| unsafe { bssl_sys::EC_KEY_free(key) },
            // Safety: `cbs` is valid per `parse_with_cbs`.
            |cbs| unsafe { bssl_sys::EC_KEY_parse_private_key(cbs, null()) },
        )?;
        let key = Self(key);
        if key.get_group().is_none() {
            None
        } else {
            Some(key)
        }
    }

    /// Serializes this private key as an ECPrivateKey structure from [RFC 5915].
    ///
    /// This method also **serialise** known curve names as `ECParameters`.
    ///
    /// [RFC 5915]: <https://datatracker.ietf.org/doc/html/rfc5915>
    pub fn to_der_ec_private_key(&self) -> Buffer {
        cbb_to_buffer(64, |cbb| unsafe {
            // Safety: the `EC_KEY` is always valid so `EC_KEY_marshal_private_key`
            // should only fail if out of memory, which this crate doesn't handle.
            assert_eq!(1, bssl_sys::EC_KEY_marshal_private_key(cbb, self.0, 0));
        })
    }

    /// Parses a PrivateKeyInfo structure (from RFC 5208).
    pub fn from_der_private_key_info(group: Group, der: &[u8]) -> Option<Self> {
        let alg = group.as_evp_pkey_alg();
        let pkey = scoped::EvpPkey::from_der_private_key_info(der, core::slice::from_ref(&alg))?;
        // Safety: the pkey is not aliased
        let ec_key = Self::from_evp_pkey(pkey)?;
        // We only passed in one allowed algorithm, this EC group.
        (ec_key.get_group()? == group).then_some(ec_key)
    }

    // Safety: the pkey must not be aliased via `as_ffi_ptr`
    pub(crate) fn from_evp_pkey(mut pkey: scoped::EvpPkey) -> Option<Self> {
        let ec_key = unsafe { bssl_sys::EVP_PKEY_get1_EC_KEY(pkey.as_ffi_ptr()) };
        if ec_key.is_null() {
            return None;
        }
        // Safety: `EVP_PKEY_get1_EC_KEY` returned owned key, which we can move
        // into the returned object and whose lifetime is independent of the EVP pkey.
        Some(Self(ec_key))
    }

    pub(crate) fn get_group(&self) -> Option<Group> {
        // Safety: we own the `EC_KEY`
        let id = unsafe { bssl_sys::EC_KEY_get0_group(self.0) };
        if id == Group::P256.as_ffi_ptr() {
            Some(Group::P256)
        } else if id == Group::P384.as_ffi_ptr() {
            Some(Group::P384)
        } else {
            None
        }
    }

    /// Serializes this private key as a PrivateKeyInfo structure from RFC 5208.
    pub fn to_der_private_key_info(&self) -> Buffer {
        let mut pkey = scoped::EvpPkey::new();
        // Safety: `pkey` was just allocated above; the `EC_KEY` is valid by
        // construction. This call takes a reference to the `EC_KEY` and so
        // hasn't stolen ownership from `self`.
        assert_eq!(1, unsafe {
            bssl_sys::EVP_PKEY_set1_EC_KEY(pkey.as_ffi_ptr(), self.0)
        });
        cbb_to_buffer(64, |cbb| unsafe {
            // `EVP_marshal_private_key` should always return one because this
            // key is valid by construction.
            assert_eq!(1, bssl_sys::EVP_marshal_private_key(cbb, pkey.as_ffi_ptr()));
        })
    }

    pub fn to_point(&self) -> Point {
        // Safety: `self.0` is valid by construction.
        let group = unsafe { bssl_sys::EC_KEY_get0_group(self.0) };
        let point = unsafe { bssl_sys::EC_KEY_get0_public_key(self.0) };
        // A `Key` is never constructed without a public key.
        assert!(!point.is_null());
        // Safety: pointers are valid and `clone_from_ptr` doesn't take
        // ownership.
        unsafe { Point::clone_from_ptr(group, point) }
    }

    pub fn to_x962_uncompressed(&self) -> Buffer {
        // Safety: `self.0` is valid by construction.
        let group = unsafe { bssl_sys::EC_KEY_get0_group(self.0) };
        let point = unsafe { bssl_sys::EC_KEY_get0_public_key(self.0) };
        // Safety: arguments are valid, `EC_KEY` ensures that the group is
        // correct for the point, and a `Key` always holds a finite public point.
        unsafe {
            to_x962(
                group,
                point,
                bssl_sys::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED,
            )
        }
    }

    /// WARNING: compressed form is rarely used and is not as well supported as
    /// the uncompressed form.
    pub fn to_x962_compressed(&self) -> Buffer {
        // Safety: `self.0` is valid by construction.
        let group = unsafe { bssl_sys::EC_KEY_get0_group(self.0) };
        let point = unsafe { bssl_sys::EC_KEY_get0_public_key(self.0) };
        // Safety: arguments are valid, `EC_KEY` ensures that the group is
        // correct for the point, and a `Key` always holds a finite public point.
        unsafe {
            to_x962(
                group,
                point,
                bssl_sys::point_conversion_form_t::POINT_CONVERSION_COMPRESSED,
            )
        }
    }

    pub fn to_der_subject_public_key_info(&self) -> Buffer {
        // Safety: `self.0` is always valid by construction.
        unsafe { to_der_subject_public_key_info(self.0) }
    }
}

// Safety:
//
// An `EC_KEY` is safe to use from multiple threads so long as no mutating
// operations are performed. (Reference count changes don't count as mutating.)
// The mutating operations used here are:
//   * EC_KEY_generate_key
//   * EC_KEY_oct2priv
//   * EC_KEY_set_public_key
// But those are all done internally, before a `Key` is returned. So, once
// constructed, callers cannot mutate the `EC_KEY`.
unsafe impl Sync for Key {}
unsafe impl Send for Key {}

impl Drop for Key {
    fn drop(&mut self) {
        // Safety: `self.0` must be valid because only valid `Key`s can
        // be constructed.
        unsafe { bssl_sys::EC_KEY_free(self.0) }
    }
}

impl Clone for Key {
    fn clone(&self) -> Self {
        unsafe {
            bssl_sys::EC_KEY_up_ref(self.0);
        }
        Self(self.0)
    }
}

/// Serialize a finite point to X9.62 format.
///
/// Callers must ensure that the arguments are valid, that the point has the
/// specified group, and that the point is finite.
unsafe fn to_x962(
    group: *const bssl_sys::EC_GROUP,
    point: *const bssl_sys::EC_POINT,
    form: bssl_sys::point_conversion_form_t,
) -> Buffer {
    cbb_to_buffer(
        // This length is just a hint and is tuned for P-256's output length.
        if form == bssl_sys::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED {
            1 + 32 + 32
        } else {
            1 + 32
        },
        |cbb| unsafe {
            // Safety: the caller must ensure that the arguments are valid.
            let result =
                bssl_sys::EC_POINT_point2cbb(cbb, group, point, form, /*bn_ctx=*/ null_mut());
            // The public key is always finite, so `EC_POINT_point2cbb` only fails
            // if out of memory, which isn't handled by this crate.
            assert_eq!(result, 1);
        },
    )
}

unsafe fn to_der_subject_public_key_info(ec_key: *mut bssl_sys::EC_KEY) -> Buffer {
    let mut pkey = scoped::EvpPkey::new();
    // Safety: this takes a reference to `ec_key` and so doesn't steal ownership.
    assert_eq!(1, unsafe {
        bssl_sys::EVP_PKEY_set1_EC_KEY(pkey.as_ffi_ptr(), ec_key)
    });
    cbb_to_buffer(
        // This length is just a hint and is tuned for P-256's output length.
        65,
        |cbb| unsafe {
            // The arguments are valid so this will only fail if out of memory,
            // which this crate doesn't handle.
            assert_eq!(1, bssl_sys::EVP_marshal_public_key(cbb, pkey.as_ffi_ptr()));
        },
    )
}

#[cfg(test)]
mod test {
    use super::*;

    #[derive(PartialEq)]
    enum Corruption {
        ShouldBeDetected,
        DontTest,
    }

    fn test_point_format<Serialize, Parse>(
        group: Group,
        serialize_func: Serialize,
        parse_func: Parse,
        corruption: Corruption,
    ) where
        Serialize: FnOnce(&Point) -> Buffer,
        Parse: Fn(&[u8]) -> Option<Point>,
    {
        let key = Key::generate(group);
        let point = key.to_point();

        let mut vec = serialize_func(&point).as_ref().to_vec();
        let point2 = parse_func(vec.as_slice()).unwrap();
        assert_eq!(
            point.to_x962_uncompressed().as_ref(),
            point2.to_x962_uncompressed().as_ref()
        );

        assert!(parse_func(&vec.as_slice()[0..16]).is_none());

        // Messing with the first byte should always cause an error.
        vec[0] ^= 64;
        assert!(parse_func(vec.as_slice()).is_none());
        vec[0] ^= 64;

        if corruption == Corruption::ShouldBeDetected {
            vec[11] ^= 1;
            assert!(parse_func(vec.as_slice()).is_none());
            vec[11] ^= 1;
        }

        assert!(parse_func(b"").is_none());
    }

    #[test]
    fn x962() {
        let x962 = b"\x04\x74\xcf\x69\xcb\xd1\x2b\x75\x07\x42\x85\xcf\x69\x6f\xc2\x56\x4b\x90\xe7\xeb\xbc\xd0\xe7\x20\x36\x86\x66\xbe\xcc\x94\x75\xa2\xa4\x4c\x2a\xf8\xa2\x56\xb8\x92\xb7\x7d\x17\xba\x97\x93\xbb\xf2\x9f\x52\x26\x7d\x90\xf9\x2c\x37\x26\x02\xbb\x4e\xd1\x89\x7c\xad\x54";
        assert!(Point::from_x962_uncompressed(Group::P256, x962).is_some());

        test_point_format(
            Group::P256,
            |point| point.to_x962_uncompressed(),
            |buf| Point::from_x962_uncompressed(Group::P256, buf),
            Corruption::ShouldBeDetected,
        );

        test_point_format(
            Group::P384,
            |point| point.to_x962_uncompressed(),
            |buf| Point::from_x962_uncompressed(Group::P384, buf),
            Corruption::ShouldBeDetected,
        );

        test_point_format(
            Group::P256,
            |point| point.to_x962_compressed(),
            |buf| Point::from_x962_compressed(Group::P256, buf),
            // Flipping a bit in a compressed point has a reasonable chance of
            // producing another valid point, so we can't run a bit-flip test
            // in this case.
            Corruption::DontTest,
        );

        test_point_format(
            Group::P384,
            |point| point.to_x962_compressed(),
            |buf| Point::from_x962_compressed(Group::P384, buf),
            // Flipping a bit in a compressed point has a reasonable chance of
            // producing another valid point, so we can't run a bit-flip test
            // in this case.
            Corruption::DontTest,
        );
    }

    #[test]
    fn x962_crossing_formats() {
        let point = Key::generate(Group::P256).to_point();
        let uncompressed = point.to_x962_uncompressed();
        let compressed = point.to_x962_compressed();

        // Compressed points won't be accepted by the uncompressed function and
        // vice-versa.
        assert!(Point::from_x962_uncompressed(Group::P256, compressed.as_ref()).is_none());
        assert!(Point::from_x962_compressed(Group::P256, uncompressed.as_ref()).is_none());
    }

    #[test]
    fn x962_infinity_not_accepted() {
        // 0x00 is the X9.62 encoding of the point at infinity.
        let infinity = &[0];
        assert!(Point::from_x962_uncompressed(Group::P256, infinity).is_none());
        assert!(Point::from_x962_compressed(Group::P256, infinity).is_none());
    }

    #[test]
    fn x962_empty() {
        // The X9.62 functions look at the first byte to check the type. They
        // must handle the case of an empty input correctly.
        let empty = b"";
        assert!(Point::from_x962_uncompressed(Group::P256, empty).is_none());
        assert!(Point::from_x962_compressed(Group::P256, empty).is_none());
    }

    #[test]
    fn spki() {
        test_point_format(
            Group::P256,
            |point| point.to_der_subject_public_key_info(),
            |buf| Point::from_der_subject_public_key_info(Group::P256, buf),
            Corruption::ShouldBeDetected,
        );

        test_point_format(
            Group::P384,
            |point| point.to_der_subject_public_key_info(),
            |buf| Point::from_der_subject_public_key_info(Group::P384, buf),
            Corruption::ShouldBeDetected,
        );
    }

    fn test_key_format<Serialize, Parse>(group: Group, serialize_func: Serialize, parse_func: Parse)
    where
        Serialize: FnOnce(&Key) -> Buffer,
        Parse: Fn(&[u8]) -> Option<Key>,
    {
        let key = Key::generate(group);
        assert_eq!(key.get_group().unwrap(), group);

        let vec = serialize_func(&key).as_ref().to_vec();
        let key2 = parse_func(vec.as_slice()).unwrap();
        assert_eq!(
            key.to_x962_uncompressed().as_ref(),
            key2.to_x962_uncompressed().as_ref()
        );
        assert_eq!(key.get_group(), key2.get_group());

        assert!(parse_func(&vec.as_slice()[0..16]).is_none());
        assert!(parse_func(b"").is_none());
    }

    #[test]
    fn der_ec_private_key() {
        for group in [Group::P256, Group::P384] {
            test_key_format(
                group,
                |key| key.to_der_ec_private_key(),
                |buf| Key::from_der_ec_private_key(group, buf),
            );
            test_key_format(
                group,
                |key| key.to_der_ec_private_key(),
                |buf| Key::from_der_ec_private_key_with_curve_names(buf),
            );
        }
    }

    #[test]
    fn der_private_key_info() {
        for group in [Group::P256, Group::P384] {
            test_key_format(
                group,
                |key| key.to_der_private_key_info(),
                |buf| Key::from_der_private_key_info(group, buf),
            );
        }
    }

    #[test]
    fn big_endian() {
        for group in [Group::P256, Group::P384] {
            test_key_format(
                group,
                |key| key.to_big_endian(),
                |buf| Key::from_big_endian(group, buf),
            );
        }
    }
}
