Fix ed25519ph context length error handling in sign_prehashed().

RFC8032 specifies that the context cannot be greater than 255 octets,
but in the previous implementation in ed25519-dalek, this error would
only be caught by a debug_assert.  This changes the sign_prehashed()
function to return a Result so that the error can be handled at
runtime and the library no longer allows misuse by creating signatures
that other libraries cannot handle.
This commit is contained in:
Isis Lovecruft 2020-07-14 00:25:40 +00:00
parent 33bb760ea8
commit 989c5e4c18
No known key found for this signature in database
GPG key ID: AB41313533E8E812
2 changed files with 12 additions and 4 deletions

View file

@ -41,6 +41,8 @@ pub(crate) enum InternalError {
ArrayLengthError{ name_a: &'static str, length_a: usize, ArrayLengthError{ name_a: &'static str, length_a: usize,
name_b: &'static str, length_b: usize, name_b: &'static str, length_b: usize,
name_c: &'static str, length_c: usize, }, name_c: &'static str, length_c: usize, },
/// An ed25519ph signature can only take up to 255 octets of context.
PrehashedContextLengthError,
} }
impl Display for InternalError { impl Display for InternalError {
@ -59,6 +61,8 @@ impl Display for InternalError {
name_c: nc, length_c: lc, } name_c: nc, length_c: lc, }
=> write!(f, "Arrays must be the same length: {} has length {}, => write!(f, "Arrays must be the same length: {} has length {},
{} has length {}, {} has length {}.", na, la, nb, lb, nc, lc), {} has length {}, {} has length {}.", na, la, nb, lb, nc, lc),
InternalError::PrehashedContextError
=> write!(f, "An ed25519ph signature can only take up to 255 octets of context"),
} }
} }
} }

View file

@ -441,7 +441,9 @@ impl ExpandedSecretKey {
/// ///
/// # Returns /// # Returns
/// ///
/// An Ed25519ph [`Signature`] on the `prehashed_message`. /// A `Result` whose `Ok` value is an Ed25519ph [`Signature`] on the
/// `prehashed_message` if the context was 255 bytes or less, otherwise
/// a `SignatureError`.
/// ///
/// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1 /// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -450,7 +452,7 @@ impl ExpandedSecretKey {
prehashed_message: D, prehashed_message: D,
public_key: &PublicKey, public_key: &PublicKey,
context: Option<&'a [u8]>, context: Option<&'a [u8]>,
) -> ed25519::Signature ) -> Result<ed25519::Signature, SignatureError>
where where
D: Digest<OutputSize = U64>, D: Digest<OutputSize = U64>,
{ {
@ -463,7 +465,9 @@ impl ExpandedSecretKey {
let ctx: &[u8] = context.unwrap_or(b""); // By default, the context is an empty string. let ctx: &[u8] = context.unwrap_or(b""); // By default, the context is an empty string.
debug_assert!(ctx.len() <= 255, "The context must not be longer than 255 octets."); if ctx.len() > 255 {
return Err(SignatureError(InternalError::PrehashedContextError));
}
let ctx_len: u8 = ctx.len() as u8; let ctx_len: u8 = ctx.len() as u8;
@ -505,7 +509,7 @@ impl ExpandedSecretKey {
k = Scalar::from_hash(h); k = Scalar::from_hash(h);
s = &(&k * &self.key) + &r; s = &(&k * &self.key) + &r;
InternalSignature { R, s }.into() Ok(InternalSignature { R, s }.into())
} }
} }