ironcore_documents/
lib.rs1pub mod aes;
2mod signing;
3pub mod v3;
4pub mod v4;
5pub mod v5;
6
7use hmac::{Hmac, Mac};
8use sha2::Sha256;
9use std::{
10 fmt::{Display, Formatter, Result as DisplayResult},
11 sync::{Mutex, MutexGuard},
12};
13use thiserror::Error;
14use v5::key_id_header::KEY_ID_HEADER_LEN;
15
16type HmacSha256 = Hmac<Sha256>;
18
19const CRATE_DEBUG_KEY: &str = match option_env!("MY_CRATE_DEBUG_KEY") {
21 Some(val) => val,
22 None => "2025-10-28T17:23:36",
24};
25
26pub fn redacted_hash(data: &[u8]) -> String {
28 let mut mac = HmacSha256::new_from_slice(CRATE_DEBUG_KEY.as_ref())
29 .expect("HMAC can take key of any size");
30 mac.update(data);
31 hex::encode(mac.finalize().into_bytes())[..8].to_string()
33}
34
35include!(concat!(env!("OUT_DIR"), "/mod.rs"));
36
37#[derive(Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
38pub enum Error {
39 EdocTooShort(usize),
41 HeaderParseErr(String),
43 InvalidVersion(u8),
45 NoIronCoreMagic,
47 SpecifiedLengthTooLong(u32),
49 ProtoSerializationErr(String),
51 HeaderLengthOverflow(u64),
53 EncryptError(String),
55 DecryptError(String),
57 EdekTypeError(String),
60 PayloadTypeError(String),
62 KeyIdHeaderTooShort(usize),
64 KeyIdHeaderMalformed(String),
66}
67
68impl Display for Error {
69 fn fmt(&self, f: &mut Formatter) -> DisplayResult {
70 match self {
71 Error::EdocTooShort(x) => write!(f, "EDOC too short. Found {x} bytes."),
72 Error::HeaderParseErr(x) => write!(f, "Header parse error: '{x}'"),
73 Error::InvalidVersion(x) => write!(f, "Invalid EDOC version: {x}"),
74 Error::NoIronCoreMagic => write!(f, "Missing IronCore Magic bytes in header."),
75 Error::SpecifiedLengthTooLong(x) => {
76 write!(f, "Header too short for specified length: {x} bytes")
77 }
78 Error::ProtoSerializationErr(x) => write!(f, "Protobuf serialization error: '{x}'"),
79 Error::HeaderLengthOverflow(x) => write!(f, "Header length too long: {x} bytes"),
80 Error::EncryptError(x) => write!(f, "{x}"),
81 Error::DecryptError(x) => write!(f, "{x}"),
82 Error::KeyIdHeaderTooShort(x) => write!(
83 f,
84 "Key ID header too short. Found: {x} bytes. Required: {KEY_ID_HEADER_LEN} bytes."
85 ),
86 Error::EdekTypeError(x) => write!(f, "EDEK type error: '{x}'"),
87 Error::PayloadTypeError(x) => write!(f, "Payload type error: '{x}'"),
88 Error::KeyIdHeaderMalformed(x) => write!(f, "Malformed key ID header: '{x}'"),
89 }
90 }
91}
92
93pub fn take_lock<T>(m: &Mutex<T>) -> MutexGuard<T> {
112 m.lock().unwrap_or_else(|e| {
113 let error = format!("Error when acquiring lock: {e}");
114 panic!("{error}");
115 })
116}
117
118#[macro_export]
124macro_rules! impl_secret_debug {
125 ($t:ty) => {
126 impl std::fmt::Debug for $t {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 write!(
129 f,
130 "{}(<redacted:{}...>)",
131 stringify!($t),
132 $crate::redacted_hash(self.0.as_ref())
133 )
134 }
135 }
136 };
137}
138
139#[macro_export]
145macro_rules! impl_secret_debug_named {
146 ($t:ty, $field:ident) => {
147 impl std::fmt::Debug for $t {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 write!(
150 f,
151 "{}{{<redacted:{}...>}}",
152 stringify!($t),
153 $crate::redacted_hash(self.$field.as_ref())
154 )
155 }
156 }
157 };
158}
159
160#[cfg(test)]
161mod test {
162 #[test]
163 fn impl_secret_debug_works() {
164 struct FooSecret([u8; 32]);
165 impl_secret_debug!(FooSecret);
166 let debug_str = format!("{:?}", FooSecret([1; 32]));
167 assert_eq!(debug_str, "FooSecret(<redacted:633f9067...>)");
168 }
169
170 #[test]
171 fn impl_secret_debug_named_works() {
172 struct FooSecret {
173 secret: String,
174 }
175 impl_secret_debug_named!(FooSecret, secret);
176 let debug_str = format!(
177 "{:?}",
178 FooSecret {
179 secret: "yes".to_string()
180 }
181 );
182 assert_eq!(debug_str, "FooSecret{<redacted:bda33dd3...>}");
183 }
184}