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] 27 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] 39 unsafe fn from_ptr(ptr: *mut Self::CType) -> Self { 40 Md(ptr) 41 } 42 43 #[inline] 44 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] 53 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] 62 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_nid(type_: Nid) -> Option<&'static MdRef>82 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)] fetch( ctx: Option<&LibCtxRef>, algorithm: &str, properties: Option<&str>, ) -> Result<Self, ErrorStack>98 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))] null() -> &'static MdRef119 pub fn null() -> &'static MdRef { 120 unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) } 121 } 122 123 #[inline] md5() -> &'static MdRef124 pub fn md5() -> &'static MdRef { 125 unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) } 126 } 127 128 #[inline] sha1() -> &'static MdRef129 pub fn sha1() -> &'static MdRef { 130 unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) } 131 } 132 133 #[inline] sha224() -> &'static MdRef134 pub fn sha224() -> &'static MdRef { 135 unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) } 136 } 137 138 #[inline] sha256() -> &'static MdRef139 pub fn sha256() -> &'static MdRef { 140 unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) } 141 } 142 143 #[inline] sha384() -> &'static MdRef144 pub fn sha384() -> &'static MdRef { 145 unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) } 146 } 147 148 #[inline] sha512() -> &'static MdRef149 pub fn sha512() -> &'static MdRef { 150 unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) } 151 } 152 153 #[cfg(any(ossl111, libressl380))] 154 #[inline] sha3_224() -> &'static MdRef155 pub fn sha3_224() -> &'static MdRef { 156 unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) } 157 } 158 159 #[cfg(any(ossl111, libressl380))] 160 #[inline] sha3_256() -> &'static MdRef161 pub fn sha3_256() -> &'static MdRef { 162 unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) } 163 } 164 165 #[cfg(any(ossl111, libressl380))] 166 #[inline] sha3_384() -> &'static MdRef167 pub fn sha3_384() -> &'static MdRef { 168 unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) } 169 } 170 171 #[cfg(any(ossl111, libressl380))] 172 #[inline] sha3_512() -> &'static MdRef173 pub fn sha3_512() -> &'static MdRef { 174 unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) } 175 } 176 177 #[cfg(ossl111)] 178 #[inline] shake128() -> &'static MdRef179 pub fn shake128() -> &'static MdRef { 180 unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) } 181 } 182 183 #[cfg(ossl111)] 184 #[inline] shake256() -> &'static MdRef185 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 #[cfg(not(boringssl))] 191 #[inline] ripemd160() -> &'static MdRef192 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] sm3() -> &'static MdRef198 pub fn sm3() -> &'static MdRef { 199 unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) } 200 } 201 } 202 203 /// A reference to an [`Md`]. 204 pub struct MdRef(Opaque); 205 206 impl ForeignTypeRef for MdRef { 207 type CType = ffi::EVP_MD; 208 } 209 210 unsafe impl Sync for MdRef {} 211 unsafe impl Send for MdRef {} 212 213 impl MdRef { 214 /// Returns the block size of the digest in bytes. 215 #[corresponds(EVP_MD_block_size)] 216 #[inline] block_size(&self) -> usize217 pub fn block_size(&self) -> usize { 218 unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize } 219 } 220 221 /// Returns the size of the digest in bytes. 222 #[corresponds(EVP_MD_size)] 223 #[inline] size(&self) -> usize224 pub fn size(&self) -> usize { 225 unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize } 226 } 227 228 /// Returns the [`Nid`] of the digest. 229 #[corresponds(EVP_MD_type)] 230 #[inline] type_(&self) -> Nid231 pub fn type_(&self) -> Nid { 232 unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) } 233 } 234 } 235