1 //! Low level Elliptic Curve Digital Signature Algorithm (ECDSA) functions. 2 3 use cfg_if::cfg_if; 4 use foreign_types::{ForeignType, ForeignTypeRef}; 5 use libc::c_int; 6 use std::mem; 7 use std::ptr; 8 9 use crate::bn::{BigNum, BigNumRef}; 10 use crate::ec::EcKeyRef; 11 use crate::error::ErrorStack; 12 use crate::pkey::{HasPrivate, HasPublic}; 13 use crate::util::ForeignTypeRefExt; 14 use crate::{cvt_n, cvt_p, LenType}; 15 use openssl_macros::corresponds; 16 17 foreign_type_and_impl_send_sync! { 18 type CType = ffi::ECDSA_SIG; 19 fn drop = ffi::ECDSA_SIG_free; 20 21 /// A low level interface to ECDSA. 22 pub struct EcdsaSig; 23 /// A reference to an [`EcdsaSig`]. 24 pub struct EcdsaSigRef; 25 } 26 27 impl EcdsaSig { 28 /// Computes a digital signature of the hash value `data` using the private EC key eckey. 29 #[corresponds(ECDSA_do_sign)] sign<T>(data: &[u8], eckey: &EcKeyRef<T>) -> Result<EcdsaSig, ErrorStack> where T: HasPrivate,30 pub fn sign<T>(data: &[u8], eckey: &EcKeyRef<T>) -> Result<EcdsaSig, ErrorStack> 31 where 32 T: HasPrivate, 33 { 34 unsafe { 35 assert!(data.len() <= c_int::max_value() as usize); 36 let sig = cvt_p(ffi::ECDSA_do_sign( 37 data.as_ptr(), 38 data.len() as LenType, 39 eckey.as_ptr(), 40 ))?; 41 Ok(EcdsaSig::from_ptr(sig)) 42 } 43 } 44 45 /// Returns a new `EcdsaSig` by setting the `r` and `s` values associated with an ECDSA signature. 46 #[corresponds(ECDSA_SIG_set0)] from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack>47 pub fn from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack> { 48 unsafe { 49 let sig = cvt_p(ffi::ECDSA_SIG_new())?; 50 ECDSA_SIG_set0(sig, r.as_ptr(), s.as_ptr()); 51 mem::forget((r, s)); 52 Ok(EcdsaSig::from_ptr(sig)) 53 } 54 } 55 56 from_der! { 57 /// Decodes a DER-encoded ECDSA signature. 58 #[corresponds(d2i_ECDSA_SIG)] 59 from_der, 60 EcdsaSig, 61 ffi::d2i_ECDSA_SIG 62 } 63 } 64 65 impl EcdsaSigRef { 66 to_der! { 67 /// Serializes the ECDSA signature into a DER-encoded ECDSASignature structure. 68 #[corresponds(i2d_ECDSA_SIG)] 69 to_der, 70 ffi::i2d_ECDSA_SIG 71 } 72 73 /// Verifies if the signature is a valid ECDSA signature using the given public key. 74 #[corresponds(ECDSA_do_verify)] verify<T>(&self, data: &[u8], eckey: &EcKeyRef<T>) -> Result<bool, ErrorStack> where T: HasPublic,75 pub fn verify<T>(&self, data: &[u8], eckey: &EcKeyRef<T>) -> Result<bool, ErrorStack> 76 where 77 T: HasPublic, 78 { 79 unsafe { 80 assert!(data.len() <= c_int::max_value() as usize); 81 cvt_n(ffi::ECDSA_do_verify( 82 data.as_ptr(), 83 data.len() as LenType, 84 self.as_ptr(), 85 eckey.as_ptr(), 86 )) 87 .map(|x| x == 1) 88 } 89 } 90 91 /// Returns internal component: `r` of an `EcdsaSig`. (See X9.62 or FIPS 186-2) 92 #[corresponds(ECDSA_SIG_get0)] r(&self) -> &BigNumRef93 pub fn r(&self) -> &BigNumRef { 94 unsafe { 95 let mut r = ptr::null(); 96 ECDSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut()); 97 BigNumRef::from_const_ptr(r) 98 } 99 } 100 101 /// Returns internal components: `s` of an `EcdsaSig`. (See X9.62 or FIPS 186-2) 102 #[corresponds(ECDSA_SIG_get0)] s(&self) -> &BigNumRef103 pub fn s(&self) -> &BigNumRef { 104 unsafe { 105 let mut s = ptr::null(); 106 ECDSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s); 107 BigNumRef::from_const_ptr(s) 108 } 109 } 110 } 111 112 cfg_if! { 113 if #[cfg(any(ossl110, libressl273))] { 114 use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0}; 115 } else { 116 #[allow(bad_style)] 117 unsafe fn ECDSA_SIG_set0( 118 sig: *mut ffi::ECDSA_SIG, 119 r: *mut ffi::BIGNUM, 120 s: *mut ffi::BIGNUM, 121 ) -> c_int { 122 if r.is_null() || s.is_null() { 123 return 0; 124 } 125 ffi::BN_clear_free((*sig).r); 126 ffi::BN_clear_free((*sig).s); 127 (*sig).r = r; 128 (*sig).s = s; 129 1 130 } 131 132 #[allow(bad_style)] 133 unsafe fn ECDSA_SIG_get0( 134 sig: *const ffi::ECDSA_SIG, 135 pr: *mut *const ffi::BIGNUM, 136 ps: *mut *const ffi::BIGNUM) 137 { 138 if !pr.is_null() { 139 (*pr) = (*sig).r; 140 } 141 if !ps.is_null() { 142 (*ps) = (*sig).s; 143 } 144 } 145 } 146 } 147 148 #[cfg(test)] 149 mod test { 150 use super::*; 151 use crate::ec::EcGroup; 152 use crate::ec::EcKey; 153 use crate::nid::Nid; 154 use crate::pkey::{Private, Public}; 155 get_public_key(group: &EcGroup, x: &EcKey<Private>) -> Result<EcKey<Public>, ErrorStack>156 fn get_public_key(group: &EcGroup, x: &EcKey<Private>) -> Result<EcKey<Public>, ErrorStack> { 157 EcKey::from_public_key(group, x.public_key()) 158 } 159 160 #[test] 161 #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)] sign_and_verify()162 fn sign_and_verify() { 163 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 164 let private_key = EcKey::generate(&group).unwrap(); 165 let public_key = get_public_key(&group, &private_key).unwrap(); 166 167 let private_key2 = EcKey::generate(&group).unwrap(); 168 let public_key2 = get_public_key(&group, &private_key2).unwrap(); 169 170 let data = String::from("hello"); 171 let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap(); 172 173 // Signature can be verified using the correct data & correct public key 174 let verification = res.verify(data.as_bytes(), &public_key).unwrap(); 175 assert!(verification); 176 177 // Signature will not be verified using the incorrect data but the correct public key 178 let verification2 = res 179 .verify(String::from("hello2").as_bytes(), &public_key) 180 .unwrap(); 181 assert!(!verification2); 182 183 // Signature will not be verified using the correct data but the incorrect public key 184 let verification3 = res.verify(data.as_bytes(), &public_key2).unwrap(); 185 assert!(!verification3); 186 } 187 188 #[test] 189 #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)] check_private_components()190 fn check_private_components() { 191 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 192 let private_key = EcKey::generate(&group).unwrap(); 193 let public_key = get_public_key(&group, &private_key).unwrap(); 194 let data = String::from("hello"); 195 let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap(); 196 197 let verification = res.verify(data.as_bytes(), &public_key).unwrap(); 198 assert!(verification); 199 200 let r = res.r().to_owned().unwrap(); 201 let s = res.s().to_owned().unwrap(); 202 203 let res2 = EcdsaSig::from_private_components(r, s).unwrap(); 204 let verification2 = res2.verify(data.as_bytes(), &public_key).unwrap(); 205 assert!(verification2); 206 } 207 208 #[test] 209 #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)] serialize_deserialize()210 fn serialize_deserialize() { 211 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 212 let private_key = EcKey::generate(&group).unwrap(); 213 let public_key = get_public_key(&group, &private_key).unwrap(); 214 215 let data = String::from("hello"); 216 let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap(); 217 218 let der = res.to_der().unwrap(); 219 let sig = EcdsaSig::from_der(&der).unwrap(); 220 221 let verification = sig.verify(data.as_bytes(), &public_key).unwrap(); 222 assert!(verification); 223 } 224 } 225