ring_native_ossl/
digest.rs1use native_ossl::digest::{DigestAlg, DigestCtx};
9use std::ffi::CStr;
10
11#[derive(Debug)]
13pub struct Algorithm {
14 pub(crate) name: &'static CStr,
15 pub output_len: usize,
16 pub block_len: usize,
17}
18
19pub static SHA256: Algorithm = Algorithm {
20 name: c"SHA2-256",
21 output_len: 32,
22 block_len: 64,
23};
24pub static SHA384: Algorithm = Algorithm {
25 name: c"SHA2-384",
26 output_len: 48,
27 block_len: 128,
28};
29pub static SHA512: Algorithm = Algorithm {
30 name: c"SHA2-512",
31 output_len: 64,
32 block_len: 128,
33};
34pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
35 name: c"SHA1",
36 output_len: 20,
37 block_len: 64,
38};
39
40pub struct Digest {
42 value: [u8; 64],
43 len: usize,
44 alg: &'static Algorithm,
45}
46
47impl Digest {
48 #[must_use]
49 pub fn algorithm(&self) -> &'static Algorithm {
50 self.alg
51 }
52}
53
54impl AsRef<[u8]> for Digest {
55 fn as_ref(&self) -> &[u8] {
56 &self.value[..self.len]
57 }
58}
59
60pub struct Context {
62 alg: &'static Algorithm,
63 ctx: DigestCtx,
64}
65
66impl Context {
67 #[must_use]
72 pub fn new(algorithm: &'static Algorithm) -> Self {
73 let alg_obj = DigestAlg::fetch(algorithm.name, None)
74 .unwrap_or_else(|e| panic!("OpenSSL digest algorithm unavailable: {e}"));
75 let ctx = alg_obj
76 .new_context()
77 .unwrap_or_else(|e| panic!("EVP_MD_CTX_new failed: {e}"));
78 Self {
79 alg: algorithm,
80 ctx,
81 }
82 }
83
84 pub fn update(&mut self, data: &[u8]) {
88 self.ctx
89 .update(data)
90 .unwrap_or_else(|e| panic!("EVP_DigestUpdate failed: {e}"));
91 }
92
93 #[must_use]
97 pub fn clone_state(&self) -> Self {
98 Self {
99 alg: self.alg,
100 ctx: self
101 .ctx
102 .fork()
103 .unwrap_or_else(|e| panic!("EVP_MD_CTX_copy_ex failed: {e}")),
104 }
105 }
106
107 #[must_use]
111 pub fn finish(mut self) -> Digest {
112 let mut out = [0u8; 64];
113 let n = self
114 .ctx
115 .finish(&mut out)
116 .unwrap_or_else(|e| panic!("EVP_DigestFinal_ex failed: {e}"));
117 Digest {
118 value: out,
119 len: n,
120 alg: self.alg,
121 }
122 }
123
124 #[must_use]
125 pub fn algorithm(&self) -> &'static Algorithm {
126 self.alg
127 }
128}
129
130impl Clone for Context {
131 fn clone(&self) -> Self {
132 self.clone_state()
133 }
134}
135
136#[must_use]
138pub fn digest(algorithm: &'static Algorithm, data: &[u8]) -> Digest {
139 let mut ctx = Context::new(algorithm);
140 ctx.update(data);
141 ctx.finish()
142}