1 /* Copyright (c) 2023, Google Inc. 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 AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 16 //! Hash functions. 17 //! 18 //! ``` 19 //! use bssl_crypto::digest; 20 //! 21 //! // One-shot hashing. 22 //! let digest: [u8; 32] = digest::Sha256::hash(b"hello"); 23 //! 24 //! // Incremental hashing. 25 //! let mut ctx = digest::Sha256::new(); 26 //! ctx.update(b"hel"); 27 //! ctx.update(b"lo"); 28 //! let digest2: [u8; 32] = ctx.digest(); 29 //! 30 //! assert_eq!(digest, digest2); 31 //! ``` 32 33 use crate::{sealed, FfiSlice, ForeignTypeRef}; 34 use alloc::vec::Vec; 35 36 #[non_exhaustive] 37 #[doc(hidden)] 38 pub struct MdRef; 39 40 unsafe impl ForeignTypeRef for MdRef { 41 type CType = bssl_sys::EVP_MD; 42 } 43 44 /// Used internally to parameterize other primitives. 45 pub trait Algorithm { 46 /// The size of the resulting digest. 47 const OUTPUT_LEN: usize; 48 49 /// Gets a reference to a message digest algorithm to be used by the HKDF implementation. 50 #[doc(hidden)] get_md(_: sealed::Sealed) -> &'static MdRef51 fn get_md(_: sealed::Sealed) -> &'static MdRef; 52 53 /// Hashes a message. hash_to_vec(input: &[u8]) -> Vec<u8>54 fn hash_to_vec(input: &[u8]) -> Vec<u8>; 55 } 56 57 /// The insecure SHA-1 hash algorithm. 58 /// 59 /// Some existing protocols depend on SHA-1 and so it is provided here, but it 60 /// does not provide collision resistance and should not be used if at all 61 /// avoidable. Use SHA-256 instead. 62 #[derive(Clone)] 63 pub struct InsecureSha1 { 64 ctx: bssl_sys::SHA_CTX, 65 } 66 67 unsafe_iuf_algo!( 68 InsecureSha1, 69 20, 70 EVP_sha1, 71 SHA1, 72 SHA1_Init, 73 SHA1_Update, 74 SHA1_Final 75 ); 76 77 /// The SHA-256 hash algorithm. 78 #[derive(Clone)] 79 pub struct Sha256 { 80 ctx: bssl_sys::SHA256_CTX, 81 } 82 83 unsafe_iuf_algo!( 84 Sha256, 85 32, 86 EVP_sha256, 87 SHA256, 88 SHA256_Init, 89 SHA256_Update, 90 SHA256_Final 91 ); 92 93 /// The SHA-384 hash algorithm. 94 #[derive(Clone)] 95 pub struct Sha384 { 96 ctx: bssl_sys::SHA512_CTX, 97 } 98 99 unsafe_iuf_algo!( 100 Sha384, 101 48, 102 EVP_sha384, 103 SHA384, 104 SHA384_Init, 105 SHA384_Update, 106 SHA384_Final 107 ); 108 109 /// The SHA-512 hash algorithm. 110 #[derive(Clone)] 111 pub struct Sha512 { 112 ctx: bssl_sys::SHA512_CTX, 113 } 114 115 unsafe_iuf_algo!( 116 Sha512, 117 64, 118 EVP_sha512, 119 SHA512, 120 SHA512_Init, 121 SHA512_Update, 122 SHA512_Final 123 ); 124 125 /// The SHA-512/256 hash algorithm. 126 #[derive(Clone)] 127 pub struct Sha512_256 { 128 ctx: bssl_sys::SHA512_CTX, 129 } 130 131 unsafe_iuf_algo!( 132 Sha512_256, 133 32, 134 EVP_sha512_256, 135 SHA512_256, 136 SHA512_256_Init, 137 SHA512_256_Update, 138 SHA512_256_Final 139 ); 140 141 #[cfg(test)] 142 mod test { 143 use super::*; 144 use crate::test_helpers::decode_hex; 145 146 #[test] sha256_c_type()147 fn sha256_c_type() { 148 unsafe { 149 assert_eq!( 150 MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(), 151 bssl_sys::EVP_sha256() as *mut _ 152 ) 153 } 154 } 155 156 #[test] sha512_c_type()157 fn sha512_c_type() { 158 unsafe { 159 assert_eq!( 160 MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(), 161 bssl_sys::EVP_sha512() as *mut _ 162 ) 163 } 164 } 165 166 #[test] sha1()167 fn sha1() { 168 assert_eq!( 169 decode_hex("a9993e364706816aba3e25717850c26c9cd0d89d"), 170 InsecureSha1::hash(b"abc") 171 ); 172 } 173 174 #[test] sha256()175 fn sha256() { 176 let msg: [u8; 4] = decode_hex("74ba2521"); 177 let expected_digest: [u8; 32] = 178 decode_hex("b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e"); 179 180 assert_eq!(Sha256::hash(&msg), expected_digest); 181 182 let mut ctx = Sha256::new(); 183 ctx.update(&msg); 184 assert_eq!(expected_digest, ctx.digest()); 185 186 let mut ctx = Sha256::new(); 187 ctx.update(&msg[0..1]); 188 let mut ctx2 = ctx.clone(); 189 ctx2.update(&msg[1..]); 190 assert_eq!(expected_digest, ctx2.digest()); 191 } 192 193 #[test] sha384()194 fn sha384() { 195 assert_eq!( 196 decode_hex("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"), 197 Sha384::hash(b"abc") 198 ); 199 } 200 201 #[test] sha512()202 fn sha512() { 203 let msg: [u8; 4] = decode_hex("23be86d5"); 204 let expected_digest: [u8; 64] = decode_hex(concat!( 205 "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2", 206 "ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb" 207 )); 208 209 assert_eq!(Sha512::hash(&msg), expected_digest); 210 211 let mut ctx = Sha512::new(); 212 ctx.update(&msg); 213 assert_eq!(expected_digest, ctx.digest()); 214 } 215 216 #[test] sha512_256()217 fn sha512_256() { 218 assert_eq!( 219 decode_hex("53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"), 220 Sha512_256::hash(b"abc") 221 ); 222 } 223 } 224