diff --git a/src/edwards.rs b/src/edwards.rs index d29ca2f..5c90195 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -108,6 +108,8 @@ use subtle::ConstantTimeEq; use constants; +use errors::{CurveError, InternalError}; + use field::FieldElement; use scalar::Scalar; @@ -337,11 +339,12 @@ impl Default for CompressedEdwardsY { } impl TryFrom<&[u8]> for CompressedEdwardsY { - type Error = (); + type Error = CurveError; - fn try_from(bytes: &[u8]) -> Result { + fn try_from(bytes: &[u8]) -> Result { if bytes.len() != 32 { - return Err(()); + return Err(CurveError( + InternalError::BytesLengthError{name: "CompressedEdwardsY", length: 32})); } Ok(CompressedEdwardsY::from_slice(bytes)) diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..d6f64c6 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,66 @@ +// -*- mode: rust; -*- +// +// This file is part of curve25519-dalek. +// Copyright (c) 2019 Isis Lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - Isis Agora Lovecruft + +//! Errors which may occur. +//! +//! Currently, these are only used in the implementations of `TryFrom`. +//! +//! This module optionally implements support for the types in the `failure` +//! crate. This can be enabled by building with `--features failure`. + +use core::fmt; +use core::fmt::Display; + +/// Internal errors. Most application-level developers will likely not +/// need to pay any attention to these. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub(crate) enum InternalError { + /// An error in the length of bytes handed to a constructor. + /// + /// To use this, pass a string specifying the `name` of the type which is + /// returning the error, and the `length` in bytes which its constructor + /// expects. + BytesLengthError { + name: &'static str, + length: usize, + }, +} + +impl Display for InternalError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + InternalError::BytesLengthError{ name: n, length: l} + => write!(f, "{} must be {} bytes in length", n, l), + } + } +} + +#[cfg(feature = "failure")] +impl ::failure::Fail for InternalError {} + +/// Errors which may occur. +/// +/// This error may arise due to: +/// +/// * Being given bytes with a length different to what was expected. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct CurveError(pub(crate) InternalError); + +impl Display for CurveError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +#[cfg(feature = "failure")] +impl ::failure::Fail for CurveError { + fn cause(&self) -> Option<&dyn (::failure::Fail)> { + Some(&self.0) + } +} diff --git a/src/lib.rs b/src/lib.rs index 0216628..5359b16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,8 @@ extern crate packed_simd; extern crate byteorder; pub extern crate digest; +#[cfg(feature = "failure")] +extern crate failure; extern crate rand_core; #[cfg(test)] extern crate rand_os; @@ -82,6 +84,9 @@ pub mod constants; // External (and internal) traits. pub mod traits; +// Errors which may occur. +pub mod errors; + //------------------------------------------------------------------------ // curve25519-dalek internal modules //------------------------------------------------------------------------ diff --git a/src/montgomery.rs b/src/montgomery.rs index c85397d..7a4f841 100644 --- a/src/montgomery.rs +++ b/src/montgomery.rs @@ -53,6 +53,7 @@ use core::ops::{Mul, MulAssign}; use constants::APLUS2_OVER_FOUR; use edwards::{CompressedEdwardsY, EdwardsPoint}; +use errors::{CurveError, InternalError}; use field::FieldElement; use scalar::Scalar; @@ -112,11 +113,12 @@ impl ValidityCheck for MontgomeryPoint { } impl TryFrom<&[u8]> for MontgomeryPoint { - type Error = (); + type Error = CurveError; - fn try_from(bytes: &[u8]) -> Result { + fn try_from(bytes: &[u8]) -> Result { if bytes.len() != 32 { - return Err(()); + return Err(CurveError( + InternalError::BytesLengthError{name: "MontgomeryPoint", length: 32})); } let mut array = [0u8; 32]; @@ -128,7 +130,8 @@ impl TryFrom<&[u8]> for MontgomeryPoint { return Ok(P); } - Err(()) + Err(CurveError( + InternalError::BytesLengthError{name: "MontgomeryPoint", length: 32})) } } diff --git a/src/ristretto.rs b/src/ristretto.rs index 59ca562..46c1c2d 100644 --- a/src/ristretto.rs +++ b/src/ristretto.rs @@ -181,6 +181,8 @@ use subtle::ConstantTimeEq; use edwards::EdwardsBasepointTable; use edwards::EdwardsPoint; +use errors::{CurveError, InternalError}; + #[allow(unused_imports)] use prelude::*; @@ -219,11 +221,12 @@ impl ConstantTimeEq for CompressedRistretto { } impl TryFrom<&[u8]> for CompressedRistretto { - type Error = (); + type Error = CurveError; - fn try_from(bytes: &[u8]) -> Result { + fn try_from(bytes: &[u8]) -> Result { if bytes.len() != 32 { - return Err(()); + return Err(CurveError( + InternalError::BytesLengthError{name: "CompressedRistretto", length: 32})); } Ok(CompressedRistretto::from_slice(bytes))