• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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