// 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 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 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).
    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))
    }

    /// Serializes this private key as an ECPrivateKey structure from RFC 5915.
    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,
                    bssl_sys::EC_PKEY_NO_PARAMETERS as u32
                )
            );
        })
    }

    /// 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 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 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>(serialize_func: Serialize, parse_func: Parse)
    where
        Serialize: FnOnce(&Key) -> Buffer,
        Parse: Fn(&[u8]) -> Option<Key>,
    {
        let key = Key::generate(Group::P256);

        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!(parse_func(&vec.as_slice()[0..16]).is_none());
        assert!(parse_func(b"").is_none());
    }

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

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

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