1 //! Message digest algorithms. 2 3 #[cfg(ossl300)] 4 use crate::cvt_p; 5 #[cfg(ossl300)] 6 use crate::error::ErrorStack; 7 #[cfg(ossl300)] 8 use crate::lib_ctx::LibCtxRef; 9 use crate::nid::Nid; 10 use cfg_if::cfg_if; 11 use foreign_types::{ForeignTypeRef, Opaque}; 12 use openssl_macros::corresponds; 13 #[cfg(ossl300)] 14 use std::ffi::CString; 15 #[cfg(ossl300)] 16 use std::ptr; 17 18 cfg_if! { 19 if #[cfg(ossl300)] { 20 use foreign_types::ForeignType; 21 use std::ops::{Deref, DerefMut}; 22 23 type Inner = *mut ffi::EVP_MD; 24 25 impl Drop for Md { 26 #[inline] dropnull27 fn drop(&mut self) { 28 unsafe { 29 ffi::EVP_MD_free(self.as_ptr()); 30 } 31 } 32 } 33 34 impl ForeignType for Md { 35 type CType = ffi::EVP_MD; 36 type Ref = MdRef; 37 38 #[inline] from_ptrnull39 unsafe fn from_ptr(ptr: *mut Self::CType) -> Self { 40 Md(ptr) 41 } 42 43 #[inline] as_ptrnull44 fn as_ptr(&self) -> *mut Self::CType { 45 self.0 46 } 47 } 48 49 impl Deref for Md { 50 type Target = MdRef; 51 52 #[inline] derefnull53 fn deref(&self) -> &Self::Target { 54 unsafe { 55 MdRef::from_ptr(self.as_ptr()) 56 } 57 } 58 } 59 60 impl DerefMut for Md { 61 #[inline] deref_mutnull62 fn deref_mut(&mut self) -> &mut Self::Target { 63 unsafe { 64 MdRef::from_ptr_mut(self.as_ptr()) 65 } 66 } 67 } 68 } else { 69 enum Inner {} 70 } 71 } 72 73 /// A message digest algorithm. 74 pub struct Md(Inner); 75 76 unsafe impl Sync for Md {} 77 unsafe impl Send for Md {} 78 79 impl Md { 80 /// Returns the `Md` corresponding to an [`Nid`]. 81 #[corresponds(EVP_get_digestbynid)] from_nidnull82 pub fn from_nid(type_: Nid) -> Option<&'static MdRef> { 83 unsafe { 84 let ptr = ffi::EVP_get_digestbynid(type_.as_raw()); 85 if ptr.is_null() { 86 None 87 } else { 88 Some(MdRef::from_ptr(ptr as *mut _)) 89 } 90 } 91 } 92 93 /// Fetches an `Md` object corresponding to the specified algorithm name and properties. 94 /// 95 /// Requires OpenSSL 3.0.0 or newer. 96 #[corresponds(EVP_MD_fetch)] 97 #[cfg(ossl300)] fetchnull98 pub fn fetch( 99 ctx: Option<&LibCtxRef>, 100 algorithm: &str, 101 properties: Option<&str>, 102 ) -> Result<Self, ErrorStack> { 103 let algorithm = CString::new(algorithm).unwrap(); 104 let properties = properties.map(|s| CString::new(s).unwrap()); 105 106 unsafe { 107 let ptr = cvt_p(ffi::EVP_MD_fetch( 108 ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), 109 algorithm.as_ptr(), 110 properties.map_or(ptr::null_mut(), |s| s.as_ptr()), 111 ))?; 112 113 Ok(Md::from_ptr(ptr)) 114 } 115 } 116 117 #[inline] 118 #[cfg(not(boringssl))] nullnull119 pub fn null() -> &'static MdRef { 120 unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) } 121 } 122 123 #[inline] md5null124 pub fn md5() -> &'static MdRef { 125 unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) } 126 } 127 128 #[inline] sha1null129 pub fn sha1() -> &'static MdRef { 130 unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) } 131 } 132 133 #[inline] sha224null134 pub fn sha224() -> &'static MdRef { 135 unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) } 136 } 137 138 #[inline] sha256null139 pub fn sha256() -> &'static MdRef { 140 unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) } 141 } 142 143 #[inline] sha384null144 pub fn sha384() -> &'static MdRef { 145 unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) } 146 } 147 148 #[inline] sha512null149 pub fn sha512() -> &'static MdRef { 150 unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) } 151 } 152 153 #[cfg(ossl111)] 154 #[inline] sha3_224null155 pub fn sha3_224() -> &'static MdRef { 156 unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) } 157 } 158 159 #[cfg(ossl111)] 160 #[inline] sha3_256null161 pub fn sha3_256() -> &'static MdRef { 162 unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) } 163 } 164 165 #[cfg(ossl111)] 166 #[inline] sha3_384null167 pub fn sha3_384() -> &'static MdRef { 168 unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) } 169 } 170 171 #[cfg(ossl111)] 172 #[inline] sha3_512null173 pub fn sha3_512() -> &'static MdRef { 174 unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) } 175 } 176 177 #[cfg(ossl111)] 178 #[inline] shake128null179 pub fn shake128() -> &'static MdRef { 180 unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) } 181 } 182 183 #[cfg(ossl111)] 184 #[inline] shake256null185 pub fn shake256() -> &'static MdRef { 186 unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) } 187 } 188 189 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))] 190 #[inline] 191 #[cfg(not(boringssl))] ripemd160null192 pub fn ripemd160() -> &'static MdRef { 193 unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) } 194 } 195 196 #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))] 197 #[inline] 198 #[cfg(not(boringssl))] sm3null199 pub fn sm3() -> &'static MdRef { 200 unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) } 201 } 202 } 203 204 /// A reference to an [`Md`]. 205 pub struct MdRef(Opaque); 206 207 impl ForeignTypeRef for MdRef { 208 type CType = ffi::EVP_MD; 209 } 210 211 unsafe impl Sync for MdRef {} 212 unsafe impl Send for MdRef {} 213 214 impl MdRef { 215 /// Returns the block size of the digest in bytes. 216 #[corresponds(EVP_MD_block_size)] 217 #[inline] block_sizenull218 pub fn block_size(&self) -> usize { 219 unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize } 220 } 221 222 /// Returns the size of the digest in bytes. 223 #[corresponds(EVP_MD_size)] 224 #[inline] sizenull225 pub fn size(&self) -> usize { 226 unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize } 227 } 228 229 /// Returns the [`Nid`] of the digest. 230 #[corresponds(EVP_MD_type)] 231 #[inline] type_null232 pub fn type_(&self) -> Nid { 233 unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) } 234 } 235 } 236