xref: /aosp_15_r20/external/boringssl/src/rust/bssl-crypto/src/digest.rs (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
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 /// Provides the ability to hash in an algorithm-agnostic manner.
45 pub trait Algorithm {
46     /// The size of the resulting digest.
47     const OUTPUT_LEN: usize;
48     /// The block length (in bytes).
49     const BLOCK_LEN: usize;
50 
51     /// Gets a reference to a message digest algorithm to be used by the HKDF implementation.
52     #[doc(hidden)]
get_md(_: sealed::Sealed) -> &'static MdRef53     fn get_md(_: sealed::Sealed) -> &'static MdRef;
54 
55     /// Hashes a message.
hash_to_vec(input: &[u8]) -> Vec<u8>56     fn hash_to_vec(input: &[u8]) -> Vec<u8>;
57 
58     /// Create a new context for incremental hashing.
new() -> Self59     fn new() -> Self;
60 
61     /// Hash the contents of `input`.
update(&mut self, input: &[u8])62     fn update(&mut self, input: &[u8]);
63 
64     /// Finish the hashing and return the digest.
digest_to_vec(self) -> Vec<u8>65     fn digest_to_vec(self) -> Vec<u8>;
66 }
67 
68 /// The insecure SHA-1 hash algorithm.
69 ///
70 /// Some existing protocols depend on SHA-1 and so it is provided here, but it
71 /// does not provide collision resistance and should not be used if at all
72 /// avoidable. Use SHA-256 instead.
73 #[derive(Clone)]
74 pub struct InsecureSha1 {
75     ctx: bssl_sys::SHA_CTX,
76 }
77 
78 unsafe_iuf_algo!(
79     InsecureSha1,
80     20,
81     64,
82     EVP_sha1,
83     SHA1,
84     SHA1_Init,
85     SHA1_Update,
86     SHA1_Final
87 );
88 
89 /// The SHA-256 hash algorithm.
90 #[derive(Clone)]
91 pub struct Sha256 {
92     ctx: bssl_sys::SHA256_CTX,
93 }
94 
95 unsafe_iuf_algo!(
96     Sha256,
97     32,
98     64,
99     EVP_sha256,
100     SHA256,
101     SHA256_Init,
102     SHA256_Update,
103     SHA256_Final
104 );
105 
106 /// The SHA-384 hash algorithm.
107 #[derive(Clone)]
108 pub struct Sha384 {
109     ctx: bssl_sys::SHA512_CTX,
110 }
111 
112 unsafe_iuf_algo!(
113     Sha384,
114     48,
115     128,
116     EVP_sha384,
117     SHA384,
118     SHA384_Init,
119     SHA384_Update,
120     SHA384_Final
121 );
122 
123 /// The SHA-512 hash algorithm.
124 #[derive(Clone)]
125 pub struct Sha512 {
126     ctx: bssl_sys::SHA512_CTX,
127 }
128 
129 unsafe_iuf_algo!(
130     Sha512,
131     64,
132     128,
133     EVP_sha512,
134     SHA512,
135     SHA512_Init,
136     SHA512_Update,
137     SHA512_Final
138 );
139 
140 /// The SHA-512/256 hash algorithm.
141 #[derive(Clone)]
142 pub struct Sha512_256 {
143     ctx: bssl_sys::SHA512_CTX,
144 }
145 
146 unsafe_iuf_algo!(
147     Sha512_256,
148     32,
149     128,
150     EVP_sha512_256,
151     SHA512_256,
152     SHA512_256_Init,
153     SHA512_256_Update,
154     SHA512_256_Final
155 );
156 
157 #[cfg(test)]
158 mod test {
159     use super::*;
160     use crate::test_helpers::decode_hex;
161 
162     #[test]
sha256_c_type()163     fn sha256_c_type() {
164         unsafe {
165             assert_eq!(
166                 MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(),
167                 bssl_sys::EVP_sha256() as *mut _
168             )
169         }
170     }
171 
172     #[test]
sha512_c_type()173     fn sha512_c_type() {
174         unsafe {
175             assert_eq!(
176                 MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(),
177                 bssl_sys::EVP_sha512() as *mut _
178             )
179         }
180     }
181 
182     #[test]
sha1()183     fn sha1() {
184         assert_eq!(
185             decode_hex("a9993e364706816aba3e25717850c26c9cd0d89d"),
186             InsecureSha1::hash(b"abc")
187         );
188     }
189 
190     #[test]
sha256()191     fn sha256() {
192         let msg: [u8; 4] = decode_hex("74ba2521");
193         let expected_digest: [u8; 32] =
194             decode_hex("b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e");
195 
196         assert_eq!(Sha256::hash(&msg), expected_digest);
197 
198         let mut ctx = Sha256::new();
199         ctx.update(&msg);
200         assert_eq!(expected_digest, ctx.digest());
201 
202         let mut ctx = Sha256::new();
203         ctx.update(&msg[0..1]);
204         let mut ctx2 = ctx.clone();
205         ctx2.update(&msg[1..]);
206         assert_eq!(expected_digest, ctx2.digest());
207     }
208 
209     #[test]
sha384()210     fn sha384() {
211         assert_eq!(
212             decode_hex("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"),
213             Sha384::hash(b"abc")
214         );
215     }
216 
217     #[test]
sha512()218     fn sha512() {
219         let msg: [u8; 4] = decode_hex("23be86d5");
220         let expected_digest: [u8; 64] = decode_hex(concat!(
221             "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2",
222             "ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb"
223         ));
224 
225         assert_eq!(Sha512::hash(&msg), expected_digest);
226 
227         let mut ctx = Sha512::new();
228         ctx.update(&msg);
229         assert_eq!(expected_digest, ctx.digest());
230     }
231 
232     #[test]
sha512_256()233     fn sha512_256() {
234         assert_eq!(
235             decode_hex("53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"),
236             Sha512_256::hash(b"abc")
237         );
238     }
239 }
240