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 use core::convert::TryInto; 20 21 /// Parameters for EdDSA signing and verification. 22 pub struct EdDSAParameters; 23 24 impl core::fmt::Debug for EdDSAParameters { fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error>25 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { 26 write!(f, "ring::signature::ED25519") 27 } 28 } 29 30 /// Verification of [Ed25519] signatures. 31 /// 32 /// Ed25519 uses SHA-512 as the digest algorithm. 33 /// 34 /// [Ed25519]: https://ed25519.cr.yp.to/ 35 pub static ED25519: EdDSAParameters = EdDSAParameters {}; 36 37 impl signature::VerificationAlgorithm for EdDSAParameters { verify( &self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input, ) -> Result<(), error::Unspecified>38 fn verify( 39 &self, 40 public_key: untrusted::Input, 41 msg: untrusted::Input, 42 signature: untrusted::Input, 43 ) -> Result<(), error::Unspecified> { 44 let public_key: &[u8; ELEM_LEN] = public_key.as_slice_less_safe().try_into()?; 45 let (signature_r, signature_s) = signature.read_all(error::Unspecified, |input| { 46 let signature_r: &[u8; ELEM_LEN] = input 47 .read_bytes(ELEM_LEN)? 48 .as_slice_less_safe() 49 .try_into()?; 50 let signature_s: &[u8; SCALAR_LEN] = input 51 .read_bytes(SCALAR_LEN)? 52 .as_slice_less_safe() 53 .try_into()?; 54 Ok((signature_r, signature_s)) 55 })?; 56 57 let signature_s = Scalar::from_bytes_checked(*signature_s)?; 58 59 let mut a = ExtPoint::from_encoded_point_vartime(public_key)?; 60 a.invert_vartime(); 61 62 let h_digest = eddsa_digest(signature_r, public_key, msg.as_slice_less_safe()); 63 let h = Scalar::from_sha512_digest_reduced(h_digest); 64 65 let mut r = Point::new_at_infinity(); 66 unsafe { GFp_x25519_ge_double_scalarmult_vartime(&mut r, &h, &a, &signature_s) }; 67 let r_check = r.into_encoded_point(); 68 if *signature_r != r_check { 69 return Err(error::Unspecified); 70 } 71 Ok(()) 72 } 73 } 74 75 impl sealed::Sealed for EdDSAParameters {} 76 77 extern "C" { GFp_x25519_ge_double_scalarmult_vartime( r: &mut Point, a_coeff: &Scalar, a: &ExtPoint, b_coeff: &Scalar, )78 fn GFp_x25519_ge_double_scalarmult_vartime( 79 r: &mut Point, 80 a_coeff: &Scalar, 81 a: &ExtPoint, 82 b_coeff: &Scalar, 83 ); 84 } 85