1 // Copyright 2015-2016 Brian Smith. 2 // 3 // Permission to use, copy, modify, and/or distribute this software for any 4 // purpose with or without fee is hereby granted, provided that the above 5 // copyright notice and this permission notice appear in all copies. 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 //! EdDSA Signatures. 16 17 use super::{super::ops::*, eddsa_digest}; 18 use crate::{error, sealed, signature}; 19 20 /// Parameters for EdDSA signing and verification. 21 pub struct EdDSAParameters; 22 23 impl core::fmt::Debug for EdDSAParameters { fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error>24 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { 25 write!(f, "ring::signature::ED25519") 26 } 27 } 28 29 /// Verification of [Ed25519] signatures. 30 /// 31 /// Ed25519 uses SHA-512 as the digest algorithm. 32 /// 33 /// [Ed25519]: https://ed25519.cr.yp.to/ 34 pub static ED25519: EdDSAParameters = EdDSAParameters {}; 35 36 impl signature::VerificationAlgorithm for EdDSAParameters { verify( &self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input, ) -> Result<(), error::Unspecified>37 fn verify( 38 &self, 39 public_key: untrusted::Input, 40 msg: untrusted::Input, 41 signature: untrusted::Input, 42 ) -> Result<(), error::Unspecified> { 43 let public_key: &[u8; ELEM_LEN] = public_key.as_slice_less_safe().try_into()?; 44 let (signature_r, signature_s) = signature.read_all(error::Unspecified, |input| { 45 let signature_r: &[u8; ELEM_LEN] = input 46 .read_bytes(ELEM_LEN)? 47 .as_slice_less_safe() 48 .try_into()?; 49 let signature_s: &[u8; SCALAR_LEN] = input 50 .read_bytes(SCALAR_LEN)? 51 .as_slice_less_safe() 52 .try_into()?; 53 Ok((signature_r, signature_s)) 54 })?; 55 56 let signature_s = Scalar::from_bytes_checked(*signature_s)?; 57 58 let mut a = ExtPoint::from_encoded_point_vartime(public_key)?; 59 a.invert_vartime(); 60 61 let h_digest = eddsa_digest(signature_r, public_key, msg.as_slice_less_safe()); 62 let h = Scalar::from_sha512_digest_reduced(h_digest); 63 64 let mut r = Point::new_at_infinity(); 65 unsafe { x25519_ge_double_scalarmult_vartime(&mut r, &h, &a, &signature_s) }; 66 let r_check = r.into_encoded_point(); 67 if *signature_r != r_check { 68 return Err(error::Unspecified); 69 } 70 Ok(()) 71 } 72 } 73 74 impl sealed::Sealed for EdDSAParameters {} 75 76 prefixed_extern! { 77 fn x25519_ge_double_scalarmult_vartime( 78 r: &mut Point, 79 a_coeff: &Scalar, 80 a: &ExtPoint, 81 b_coeff: &Scalar, 82 ); 83 } 84