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,
name_b: &'static str, length_b: 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 {
@ -59,6 +61,8 @@ impl Display for InternalError {
name_c: nc, length_c: lc, }
=> write!(f, "Arrays must be the same length: {} has length {},
{} 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
///
/// 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
#[allow(non_snake_case)]
@ -450,7 +452,7 @@ impl ExpandedSecretKey {
prehashed_message: D,
public_key: &PublicKey,
context: Option<&'a [u8]>,
) -> ed25519::Signature
) -> Result<ed25519::Signature, SignatureError>
where
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.
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;
@ -505,7 +509,7 @@ impl ExpandedSecretKey {
k = Scalar::from_hash(h);
s = &(&k * &self.key) + &r;
InternalSignature { R, s }.into()
Ok(InternalSignature { R, s }.into())
}
}