| /* Copyright (c) 2023, Google Inc. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
| * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| //! Hash functions. |
| //! |
| //! ``` |
| //! use bssl_crypto::digest; |
| //! |
| //! // One-shot hashing. |
| //! let digest: [u8; 32] = digest::Sha256::hash(b"hello"); |
| //! |
| //! // Incremental hashing. |
| //! let mut ctx = digest::Sha256::new(); |
| //! ctx.update(b"hel"); |
| //! ctx.update(b"lo"); |
| //! let digest2: [u8; 32] = ctx.digest(); |
| //! |
| //! assert_eq!(digest, digest2); |
| //! ``` |
| |
| use crate::{sealed, FfiSlice, ForeignTypeRef}; |
| use bssl_sys; |
| |
| #[non_exhaustive] |
| #[doc(hidden)] |
| pub struct MdRef; |
| |
| unsafe impl ForeignTypeRef for MdRef { |
| type CType = bssl_sys::EVP_MD; |
| } |
| |
| /// Used internally to parameterize other primitives. |
| pub trait Algorithm { |
| /// The size of the resulting digest. |
| const OUTPUT_LEN: usize; |
| |
| /// Gets a reference to a message digest algorithm to be used by the HKDF implementation. |
| #[doc(hidden)] |
| fn get_md(_: sealed::Sealed) -> &'static MdRef; |
| } |
| |
| /// The insecure SHA-1 hash algorithm. |
| /// |
| /// Some existing protocols depend on SHA-1 and so it is provided here, but it |
| /// does not provide collision resistance and should not be used if at all |
| /// avoidable. Use SHA-256 instead. |
| #[derive(Clone)] |
| pub struct InsecureSha1 { |
| ctx: bssl_sys::SHA_CTX, |
| } |
| |
| unsafe_iuf_algo!( |
| InsecureSha1, |
| 20, |
| EVP_sha1, |
| SHA1, |
| SHA1_Init, |
| SHA1_Update, |
| SHA1_Final |
| ); |
| |
| /// The SHA-256 hash algorithm. |
| #[derive(Clone)] |
| pub struct Sha256 { |
| ctx: bssl_sys::SHA256_CTX, |
| } |
| |
| unsafe_iuf_algo!( |
| Sha256, |
| 32, |
| EVP_sha256, |
| SHA256, |
| SHA256_Init, |
| SHA256_Update, |
| SHA256_Final |
| ); |
| |
| /// The SHA-384 hash algorithm. |
| #[derive(Clone)] |
| pub struct Sha384 { |
| ctx: bssl_sys::SHA512_CTX, |
| } |
| |
| unsafe_iuf_algo!( |
| Sha384, |
| 48, |
| EVP_sha384, |
| SHA384, |
| SHA384_Init, |
| SHA384_Update, |
| SHA384_Final |
| ); |
| |
| /// The SHA-512 hash algorithm. |
| #[derive(Clone)] |
| pub struct Sha512 { |
| ctx: bssl_sys::SHA512_CTX, |
| } |
| |
| unsafe_iuf_algo!( |
| Sha512, |
| 64, |
| EVP_sha512, |
| SHA512, |
| SHA512_Init, |
| SHA512_Update, |
| SHA512_Final |
| ); |
| |
| /// The SHA-512/256 hash algorithm. |
| #[derive(Clone)] |
| pub struct Sha512_256 { |
| ctx: bssl_sys::SHA512_CTX, |
| } |
| |
| unsafe_iuf_algo!( |
| Sha512_256, |
| 32, |
| EVP_sha512_256, |
| SHA512_256, |
| SHA512_256_Init, |
| SHA512_256_Update, |
| SHA512_256_Final |
| ); |
| |
| #[cfg(test)] |
| mod test { |
| use super::*; |
| use crate::test_helpers::decode_hex; |
| |
| #[test] |
| fn sha256_c_type() { |
| unsafe { |
| assert_eq!( |
| MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(), |
| bssl_sys::EVP_sha256() as *mut _ |
| ) |
| } |
| } |
| |
| #[test] |
| fn sha512_c_type() { |
| unsafe { |
| assert_eq!( |
| MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(), |
| bssl_sys::EVP_sha512() as *mut _ |
| ) |
| } |
| } |
| |
| #[test] |
| fn sha1() { |
| assert_eq!( |
| decode_hex("a9993e364706816aba3e25717850c26c9cd0d89d"), |
| InsecureSha1::hash(b"abc") |
| ); |
| } |
| |
| #[test] |
| fn sha256() { |
| let msg: [u8; 4] = decode_hex("74ba2521"); |
| let expected_digest: [u8; 32] = |
| decode_hex("b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e"); |
| |
| assert_eq!(Sha256::hash(&msg), expected_digest); |
| |
| let mut ctx = Sha256::new(); |
| ctx.update(&msg); |
| assert_eq!(expected_digest, ctx.digest()); |
| |
| let mut ctx = Sha256::new(); |
| ctx.update(&msg[0..1]); |
| let mut ctx2 = ctx.clone(); |
| ctx2.update(&msg[1..]); |
| assert_eq!(expected_digest, ctx2.digest()); |
| } |
| |
| #[test] |
| fn sha384() { |
| assert_eq!( |
| decode_hex("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"), |
| Sha384::hash(b"abc") |
| ); |
| } |
| |
| #[test] |
| fn sha512() { |
| let msg: [u8; 4] = decode_hex("23be86d5"); |
| let expected_digest: [u8; 64] = decode_hex(concat!( |
| "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2", |
| "ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb" |
| )); |
| |
| assert_eq!(Sha512::hash(&msg), expected_digest); |
| |
| let mut ctx = Sha512::new(); |
| ctx.update(&msg); |
| assert_eq!(expected_digest, ctx.digest()); |
| } |
| |
| #[test] |
| fn sha512_256() { |
| assert_eq!( |
| decode_hex("53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"), |
| Sha512_256::hash(b"abc") |
| ); |
| } |
| } |