1use super::{
4 AssuranceError, AssuranceLevel, AssuranceToken, CleanupError, ProtectedMemoryProvider,
5 ProtectedSecret, ProtectionError, SecretOperation, Uninitialized, Validated,
6};
7use crate::v2::{
8 Base64, Codec,
9 secret::{SecretDecodeError, SecretEncodeError, SecretInput},
10 secret_decoder::SecretDecoderState,
11 secret_encoder::SecretEncoderState,
12 specifications::CodecSettings,
13};
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
17#[non_exhaustive]
18pub enum AssuredDecodeError {
19 Assurance(AssuranceError),
21 Protection(ProtectionError),
23 Decode(SecretDecodeError),
25 Cleanup(CleanupError),
27}
28
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31#[non_exhaustive]
32pub enum AssuredEncodeError {
33 Assurance(AssuranceError),
35 Protection(ProtectionError),
37 Encode(SecretEncodeError),
39 Cleanup(CleanupError),
41}
42
43impl core::fmt::Display for AssuredDecodeError {
44 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 match self {
46 Self::Assurance(error) => error.fmt(formatter),
47 Self::Protection(error) => error.fmt(formatter),
48 Self::Decode(error) => error.fmt(formatter),
49 Self::Cleanup(error) => error.fmt(formatter),
50 }
51 }
52}
53
54impl core::fmt::Display for AssuredEncodeError {
55 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56 match self {
57 Self::Assurance(error) => error.fmt(formatter),
58 Self::Protection(error) => error.fmt(formatter),
59 Self::Encode(error) => error.fmt(formatter),
60 Self::Cleanup(error) => error.fmt(formatter),
61 }
62 }
63}
64
65#[cfg(feature = "std")]
66impl std::error::Error for AssuredDecodeError {}
67
68#[cfg(feature = "std")]
69impl std::error::Error for AssuredEncodeError {}
70
71impl<S: Codec> Base64<S> {
72 pub fn decode_assured<'provider, P, Level>(
77 &self,
78 token: &AssuranceToken<'provider, Level>,
79 allocation: ProtectedSecret<'provider, P, Uninitialized, Level>,
80 input: &SecretInput<'_>,
81 ) -> Result<ProtectedSecret<'provider, P, Validated, Level>, AssuredDecodeError>
82 where
83 P: ProtectedMemoryProvider,
84 Level: AssuranceLevel,
85 {
86 token.revalidate().map_err(AssuredDecodeError::Assurance)?;
87 let mut allocation = match allocation.begin_unvalidated(token, SecretOperation::Decode) {
88 Ok(allocation) => allocation,
89 Err((error, allocation)) => {
90 return Err(match allocation.try_close() {
91 Ok(_) => AssuredDecodeError::Protection(error),
92 Err(cleanup) => AssuredDecodeError::Cleanup(cleanup),
93 });
94 }
95 };
96 let output = match allocation.bytes_mut() {
97 Ok(output) => output,
98 Err(error) => {
99 return Err(match allocation.try_close() {
100 Ok(_) => AssuredDecodeError::Protection(error),
101 Err(cleanup) => AssuredDecodeError::Cleanup(cleanup),
102 });
103 }
104 };
105 let result = decode_one_shot(self.settings(), input.classified_bytes(), output);
106 let written = match result {
107 Ok(written) => written,
108 Err(error) => {
109 return Err(match allocation.try_close() {
110 Ok(_) => AssuredDecodeError::Decode(error),
111 Err(cleanup) => AssuredDecodeError::Cleanup(cleanup),
112 });
113 }
114 };
115 if let Err(error) = allocation.set_initialized_len(written) {
116 return Err(match allocation.try_close() {
117 Ok(_) => AssuredDecodeError::Protection(error),
118 Err(cleanup) => AssuredDecodeError::Cleanup(cleanup),
119 });
120 }
121 match allocation.validate(token) {
122 Ok(validated) => Ok(validated),
123 Err((error, allocation)) => Err(match allocation.try_close() {
124 Ok(_) => AssuredDecodeError::Protection(error),
125 Err(cleanup) => AssuredDecodeError::Cleanup(cleanup),
126 }),
127 }
128 }
129
130 pub fn encode_assured<'provider, P, Level>(
132 &self,
133 token: &AssuranceToken<'provider, Level>,
134 allocation: ProtectedSecret<'provider, P, Uninitialized, Level>,
135 input: &SecretInput<'_>,
136 ) -> Result<ProtectedSecret<'provider, P, Validated, Level>, AssuredEncodeError>
137 where
138 P: ProtectedMemoryProvider,
139 Level: AssuranceLevel,
140 {
141 token.revalidate().map_err(AssuredEncodeError::Assurance)?;
142 let mut allocation = match allocation.begin_unvalidated(token, SecretOperation::Encode) {
143 Ok(allocation) => allocation,
144 Err((error, allocation)) => {
145 return Err(match allocation.try_close() {
146 Ok(_) => AssuredEncodeError::Protection(error),
147 Err(cleanup) => AssuredEncodeError::Cleanup(cleanup),
148 });
149 }
150 };
151 let output = match allocation.bytes_mut() {
152 Ok(output) => output,
153 Err(error) => {
154 return Err(match allocation.try_close() {
155 Ok(_) => AssuredEncodeError::Protection(error),
156 Err(cleanup) => AssuredEncodeError::Cleanup(cleanup),
157 });
158 }
159 };
160 let result = encode_one_shot(self.settings(), input.classified_bytes(), output);
161 let written = match result {
162 Ok(written) => written,
163 Err(error) => {
164 return Err(match allocation.try_close() {
165 Ok(_) => AssuredEncodeError::Encode(error),
166 Err(cleanup) => AssuredEncodeError::Cleanup(cleanup),
167 });
168 }
169 };
170 if let Err(error) = allocation.set_initialized_len(written) {
171 return Err(match allocation.try_close() {
172 Ok(_) => AssuredEncodeError::Protection(error),
173 Err(cleanup) => AssuredEncodeError::Cleanup(cleanup),
174 });
175 }
176 match allocation.validate(token) {
177 Ok(validated) => Ok(validated),
178 Err((error, allocation)) => Err(match allocation.try_close() {
179 Ok(_) => AssuredEncodeError::Protection(error),
180 Err(cleanup) => AssuredEncodeError::Cleanup(cleanup),
181 }),
182 }
183 }
184}
185
186fn decode_one_shot(
187 settings: CodecSettings,
188 input: &[u8],
189 output: &mut [u8],
190) -> Result<usize, SecretDecodeError> {
191 crate::wipe_bytes(output);
192 let mut state = SecretDecoderState::new(settings, output.len())?;
193 if let Err(error) = state.update(input, output) {
194 crate::wipe_bytes(output);
195 return Err(error);
196 }
197 let candidate = match state.finish() {
198 Ok(candidate) => candidate,
199 Err(error) => {
200 crate::wipe_bytes(output);
201 return Err(error);
202 }
203 };
204 let written = candidate.written();
205 output[candidate.staged_len..written].copy_from_slice(&candidate.bytes[..candidate.len]);
206 crate::wipe_tail(output, written);
207 Ok(written)
208}
209
210fn encode_one_shot(
211 settings: CodecSettings,
212 input: &[u8],
213 output: &mut [u8],
214) -> Result<usize, SecretEncodeError> {
215 crate::wipe_bytes(output);
216 let mut state = SecretEncoderState::new(settings, input.len(), output.len())?;
217 if let Err(error) = state.update(input, output) {
218 crate::wipe_bytes(output);
219 return Err(error);
220 }
221 match state.finish(output) {
222 Ok(written) => Ok(written),
223 Err(error) => {
224 crate::wipe_bytes(output);
225 Err(error)
226 }
227 }
228}