xref: /aosp_15_r20/system/keymint/boringssl/src/aes.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker //! BoringSSL-based implementation of AES.
16*9860b763SAndroid Build Coastguard Worker use crate::{openssl_err, openssl_err_or, ossl};
17*9860b763SAndroid Build Coastguard Worker use alloc::boxed::Box;
18*9860b763SAndroid Build Coastguard Worker use alloc::vec::Vec;
19*9860b763SAndroid Build Coastguard Worker use core::cmp::min;
20*9860b763SAndroid Build Coastguard Worker use kmr_common::{
21*9860b763SAndroid Build Coastguard Worker     crypto, crypto::OpaqueOr, explicit, km_err, vec_try, vec_try_with_capacity, Error,
22*9860b763SAndroid Build Coastguard Worker     FallibleAllocExt,
23*9860b763SAndroid Build Coastguard Worker };
24*9860b763SAndroid Build Coastguard Worker use openssl::symm::{Cipher, Crypter};
25*9860b763SAndroid Build Coastguard Worker 
26*9860b763SAndroid Build Coastguard Worker /// [`crypto::Aes`] implementation based on BoringSSL.
27*9860b763SAndroid Build Coastguard Worker pub struct BoringAes;
28*9860b763SAndroid Build Coastguard Worker 
29*9860b763SAndroid Build Coastguard Worker impl crypto::Aes for BoringAes {
begin( &self, key: OpaqueOr<crypto::aes::Key>, mode: crypto::aes::CipherMode, dir: crypto::SymmetricOperation, ) -> Result<Box<dyn crypto::EmittingOperation>, Error>30*9860b763SAndroid Build Coastguard Worker     fn begin(
31*9860b763SAndroid Build Coastguard Worker         &self,
32*9860b763SAndroid Build Coastguard Worker         key: OpaqueOr<crypto::aes::Key>,
33*9860b763SAndroid Build Coastguard Worker         mode: crypto::aes::CipherMode,
34*9860b763SAndroid Build Coastguard Worker         dir: crypto::SymmetricOperation,
35*9860b763SAndroid Build Coastguard Worker     ) -> Result<Box<dyn crypto::EmittingOperation>, Error> {
36*9860b763SAndroid Build Coastguard Worker         let key = explicit!(key)?;
37*9860b763SAndroid Build Coastguard Worker         let dir_mode = match dir {
38*9860b763SAndroid Build Coastguard Worker             crypto::SymmetricOperation::Encrypt => openssl::symm::Mode::Encrypt,
39*9860b763SAndroid Build Coastguard Worker             crypto::SymmetricOperation::Decrypt => openssl::symm::Mode::Decrypt,
40*9860b763SAndroid Build Coastguard Worker         };
41*9860b763SAndroid Build Coastguard Worker         let crypter = match mode {
42*9860b763SAndroid Build Coastguard Worker             crypto::aes::CipherMode::EcbNoPadding | crypto::aes::CipherMode::EcbPkcs7Padding => {
43*9860b763SAndroid Build Coastguard Worker                 let (cipher, key) = match &key {
44*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes128(k) => (Cipher::aes_128_ecb(), &k[..]),
45*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes192(k) => (Cipher::aes_192_ecb(), &k[..]),
46*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes256(k) => (Cipher::aes_256_ecb(), &k[..]),
47*9860b763SAndroid Build Coastguard Worker                 };
48*9860b763SAndroid Build Coastguard Worker                 let mut crypter = Crypter::new(cipher, dir_mode, key, None)
49*9860b763SAndroid Build Coastguard Worker                     .map_err(openssl_err!("failed to create ECB Crypter"))?;
50*9860b763SAndroid Build Coastguard Worker                 if let crypto::aes::CipherMode::EcbPkcs7Padding = mode {
51*9860b763SAndroid Build Coastguard Worker                     crypter.pad(true);
52*9860b763SAndroid Build Coastguard Worker                 } else {
53*9860b763SAndroid Build Coastguard Worker                     crypter.pad(false);
54*9860b763SAndroid Build Coastguard Worker                 }
55*9860b763SAndroid Build Coastguard Worker                 crypter
56*9860b763SAndroid Build Coastguard Worker             }
57*9860b763SAndroid Build Coastguard Worker 
58*9860b763SAndroid Build Coastguard Worker             crypto::aes::CipherMode::CbcNoPadding { nonce: n }
59*9860b763SAndroid Build Coastguard Worker             | crypto::aes::CipherMode::CbcPkcs7Padding { nonce: n } => {
60*9860b763SAndroid Build Coastguard Worker                 let (cipher, key) = match &key {
61*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes128(k) => (Cipher::aes_128_cbc(), &k[..]),
62*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes192(k) => (Cipher::aes_192_cbc(), &k[..]),
63*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes256(k) => (Cipher::aes_256_cbc(), &k[..]),
64*9860b763SAndroid Build Coastguard Worker                 };
65*9860b763SAndroid Build Coastguard Worker                 let mut crypter = Crypter::new(cipher, dir_mode, key, Some(&n[..]))
66*9860b763SAndroid Build Coastguard Worker                     .map_err(openssl_err!("failed to create CBC Crypter"))?;
67*9860b763SAndroid Build Coastguard Worker                 if let crypto::aes::CipherMode::CbcPkcs7Padding { nonce: _ } = mode {
68*9860b763SAndroid Build Coastguard Worker                     crypter.pad(true);
69*9860b763SAndroid Build Coastguard Worker                 } else {
70*9860b763SAndroid Build Coastguard Worker                     crypter.pad(false);
71*9860b763SAndroid Build Coastguard Worker                 }
72*9860b763SAndroid Build Coastguard Worker                 crypter
73*9860b763SAndroid Build Coastguard Worker             }
74*9860b763SAndroid Build Coastguard Worker 
75*9860b763SAndroid Build Coastguard Worker             crypto::aes::CipherMode::Ctr { nonce: n } => {
76*9860b763SAndroid Build Coastguard Worker                 let (cipher, key) = match &key {
77*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes128(k) => (Cipher::aes_128_ctr(), &k[..]),
78*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes192(k) => (Cipher::aes_192_ctr(), &k[..]),
79*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes256(k) => (Cipher::aes_256_ctr(), &k[..]),
80*9860b763SAndroid Build Coastguard Worker                 };
81*9860b763SAndroid Build Coastguard Worker                 Crypter::new(cipher, dir_mode, key, Some(&n[..]))
82*9860b763SAndroid Build Coastguard Worker                     .map_err(openssl_err!("failed to create CTR Crypter"))?
83*9860b763SAndroid Build Coastguard Worker             }
84*9860b763SAndroid Build Coastguard Worker         };
85*9860b763SAndroid Build Coastguard Worker 
86*9860b763SAndroid Build Coastguard Worker         Ok(Box::new(BoringAesOperation { crypter }))
87*9860b763SAndroid Build Coastguard Worker     }
88*9860b763SAndroid Build Coastguard Worker 
begin_aead( &self, key: OpaqueOr<crypto::aes::Key>, mode: crypto::aes::GcmMode, dir: crypto::SymmetricOperation, ) -> Result<Box<dyn crypto::AadOperation>, Error>89*9860b763SAndroid Build Coastguard Worker     fn begin_aead(
90*9860b763SAndroid Build Coastguard Worker         &self,
91*9860b763SAndroid Build Coastguard Worker         key: OpaqueOr<crypto::aes::Key>,
92*9860b763SAndroid Build Coastguard Worker         mode: crypto::aes::GcmMode,
93*9860b763SAndroid Build Coastguard Worker         dir: crypto::SymmetricOperation,
94*9860b763SAndroid Build Coastguard Worker     ) -> Result<Box<dyn crypto::AadOperation>, Error> {
95*9860b763SAndroid Build Coastguard Worker         let key = explicit!(key)?;
96*9860b763SAndroid Build Coastguard Worker         let dir_mode = match dir {
97*9860b763SAndroid Build Coastguard Worker             crypto::SymmetricOperation::Encrypt => openssl::symm::Mode::Encrypt,
98*9860b763SAndroid Build Coastguard Worker             crypto::SymmetricOperation::Decrypt => openssl::symm::Mode::Decrypt,
99*9860b763SAndroid Build Coastguard Worker         };
100*9860b763SAndroid Build Coastguard Worker         let crypter = match mode {
101*9860b763SAndroid Build Coastguard Worker             crypto::aes::GcmMode::GcmTag12 { nonce: n }
102*9860b763SAndroid Build Coastguard Worker             | crypto::aes::GcmMode::GcmTag13 { nonce: n }
103*9860b763SAndroid Build Coastguard Worker             | crypto::aes::GcmMode::GcmTag14 { nonce: n }
104*9860b763SAndroid Build Coastguard Worker             | crypto::aes::GcmMode::GcmTag15 { nonce: n }
105*9860b763SAndroid Build Coastguard Worker             | crypto::aes::GcmMode::GcmTag16 { nonce: n } => {
106*9860b763SAndroid Build Coastguard Worker                 let (cipher, key) = match &key {
107*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes128(k) => (Cipher::aes_128_gcm(), &k[..]),
108*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes192(k) => (Cipher::aes_192_gcm(), &k[..]),
109*9860b763SAndroid Build Coastguard Worker                     crypto::aes::Key::Aes256(k) => (Cipher::aes_256_gcm(), &k[..]),
110*9860b763SAndroid Build Coastguard Worker                 };
111*9860b763SAndroid Build Coastguard Worker                 Crypter::new(cipher, dir_mode, key, Some(&n[..])).map_err(openssl_err!(
112*9860b763SAndroid Build Coastguard Worker                     "failed to create GCM Crypter for {:?} {:?}",
113*9860b763SAndroid Build Coastguard Worker                     mode,
114*9860b763SAndroid Build Coastguard Worker                     dir
115*9860b763SAndroid Build Coastguard Worker                 ))?
116*9860b763SAndroid Build Coastguard Worker             }
117*9860b763SAndroid Build Coastguard Worker         };
118*9860b763SAndroid Build Coastguard Worker 
119*9860b763SAndroid Build Coastguard Worker         Ok(match dir {
120*9860b763SAndroid Build Coastguard Worker             crypto::SymmetricOperation::Encrypt => Box::new({
121*9860b763SAndroid Build Coastguard Worker                 BoringAesGcmEncryptOperation { mode, inner: BoringAesOperation { crypter } }
122*9860b763SAndroid Build Coastguard Worker             }),
123*9860b763SAndroid Build Coastguard Worker             crypto::SymmetricOperation::Decrypt => Box::new(BoringAesGcmDecryptOperation {
124*9860b763SAndroid Build Coastguard Worker                 crypter,
125*9860b763SAndroid Build Coastguard Worker                 decrypt_tag_len: mode.tag_len(),
126*9860b763SAndroid Build Coastguard Worker                 pending_input_tail: vec_try_with_capacity!(mode.tag_len())?,
127*9860b763SAndroid Build Coastguard Worker             }),
128*9860b763SAndroid Build Coastguard Worker         })
129*9860b763SAndroid Build Coastguard Worker     }
130*9860b763SAndroid Build Coastguard Worker }
131*9860b763SAndroid Build Coastguard Worker 
132*9860b763SAndroid Build Coastguard Worker /// AES operation based on BoringSSL.
133*9860b763SAndroid Build Coastguard Worker pub struct BoringAesOperation {
134*9860b763SAndroid Build Coastguard Worker     crypter: openssl::symm::Crypter,
135*9860b763SAndroid Build Coastguard Worker }
136*9860b763SAndroid Build Coastguard Worker 
137*9860b763SAndroid Build Coastguard Worker impl crypto::EmittingOperation for BoringAesOperation {
update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error>138*9860b763SAndroid Build Coastguard Worker     fn update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error> {
139*9860b763SAndroid Build Coastguard Worker         let mut output = vec_try![0; data.len() + crypto::aes::BLOCK_SIZE]?;
140*9860b763SAndroid Build Coastguard Worker         let out_len = self
141*9860b763SAndroid Build Coastguard Worker             .crypter
142*9860b763SAndroid Build Coastguard Worker             .update(data, &mut output)
143*9860b763SAndroid Build Coastguard Worker             .map_err(openssl_err!("update {} bytes from input failed", data.len()))?;
144*9860b763SAndroid Build Coastguard Worker         output.truncate(out_len);
145*9860b763SAndroid Build Coastguard Worker         Ok(output)
146*9860b763SAndroid Build Coastguard Worker     }
147*9860b763SAndroid Build Coastguard Worker 
finish(mut self: Box<Self>) -> Result<Vec<u8>, Error>148*9860b763SAndroid Build Coastguard Worker     fn finish(mut self: Box<Self>) -> Result<Vec<u8>, Error> {
149*9860b763SAndroid Build Coastguard Worker         let mut output = vec_try![0; crypto::aes::BLOCK_SIZE]?;
150*9860b763SAndroid Build Coastguard Worker         let out_len = ossl!(self.crypter.finalize(&mut output))?;
151*9860b763SAndroid Build Coastguard Worker         output.truncate(out_len);
152*9860b763SAndroid Build Coastguard Worker         Ok(output)
153*9860b763SAndroid Build Coastguard Worker     }
154*9860b763SAndroid Build Coastguard Worker }
155*9860b763SAndroid Build Coastguard Worker 
156*9860b763SAndroid Build Coastguard Worker /// AES-GCM encrypt operation based on BoringSSL.
157*9860b763SAndroid Build Coastguard Worker pub struct BoringAesGcmEncryptOperation {
158*9860b763SAndroid Build Coastguard Worker     mode: crypto::aes::GcmMode,
159*9860b763SAndroid Build Coastguard Worker     inner: BoringAesOperation,
160*9860b763SAndroid Build Coastguard Worker }
161*9860b763SAndroid Build Coastguard Worker 
162*9860b763SAndroid Build Coastguard Worker impl crypto::AadOperation for BoringAesGcmEncryptOperation {
update_aad(&mut self, aad: &[u8]) -> Result<(), Error>163*9860b763SAndroid Build Coastguard Worker     fn update_aad(&mut self, aad: &[u8]) -> Result<(), Error> {
164*9860b763SAndroid Build Coastguard Worker         ossl!(self.inner.crypter.aad_update(aad))
165*9860b763SAndroid Build Coastguard Worker     }
166*9860b763SAndroid Build Coastguard Worker }
167*9860b763SAndroid Build Coastguard Worker 
168*9860b763SAndroid Build Coastguard Worker impl crypto::EmittingOperation for BoringAesGcmEncryptOperation {
update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error>169*9860b763SAndroid Build Coastguard Worker     fn update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error> {
170*9860b763SAndroid Build Coastguard Worker         self.inner.update(data)
171*9860b763SAndroid Build Coastguard Worker     }
172*9860b763SAndroid Build Coastguard Worker 
finish(mut self: Box<Self>) -> Result<Vec<u8>, Error>173*9860b763SAndroid Build Coastguard Worker     fn finish(mut self: Box<Self>) -> Result<Vec<u8>, Error> {
174*9860b763SAndroid Build Coastguard Worker         let mut output = vec_try![0; crypto::aes::BLOCK_SIZE + self.mode.tag_len()]?;
175*9860b763SAndroid Build Coastguard Worker         let offset = self
176*9860b763SAndroid Build Coastguard Worker             .inner
177*9860b763SAndroid Build Coastguard Worker             .crypter
178*9860b763SAndroid Build Coastguard Worker             .finalize(&mut output)
179*9860b763SAndroid Build Coastguard Worker             .map_err(openssl_err_or!(VerificationFailed, "failed to finalize"))?;
180*9860b763SAndroid Build Coastguard Worker 
181*9860b763SAndroid Build Coastguard Worker         self.inner
182*9860b763SAndroid Build Coastguard Worker             .crypter
183*9860b763SAndroid Build Coastguard Worker             .get_tag(&mut output[offset..offset + self.mode.tag_len()])
184*9860b763SAndroid Build Coastguard Worker             .map_err(openssl_err!("failed to get tag of len {}", self.mode.tag_len()))?;
185*9860b763SAndroid Build Coastguard Worker         output.truncate(offset + self.mode.tag_len());
186*9860b763SAndroid Build Coastguard Worker         Ok(output)
187*9860b763SAndroid Build Coastguard Worker     }
188*9860b763SAndroid Build Coastguard Worker }
189*9860b763SAndroid Build Coastguard Worker 
190*9860b763SAndroid Build Coastguard Worker /// AES-GCM decrypt operation based on BoringSSL.
191*9860b763SAndroid Build Coastguard Worker pub struct BoringAesGcmDecryptOperation {
192*9860b763SAndroid Build Coastguard Worker     crypter: openssl::symm::Crypter,
193*9860b763SAndroid Build Coastguard Worker 
194*9860b763SAndroid Build Coastguard Worker     // Size of a final tag when decrypting.
195*9860b763SAndroid Build Coastguard Worker     decrypt_tag_len: usize,
196*9860b763SAndroid Build Coastguard Worker 
197*9860b763SAndroid Build Coastguard Worker     // For decryption, the last `decrypt_tag_len` bytes of input must be fed in separately.
198*9860b763SAndroid Build Coastguard Worker     // However, the overall size of the input data is not known in advance, so we need to hold up to
199*9860b763SAndroid Build Coastguard Worker     // `decrypt_tag_len` bytes on input in reserve until `finish()`.
200*9860b763SAndroid Build Coastguard Worker     pending_input_tail: Vec<u8>, // Capacity = decrypt_tag_len
201*9860b763SAndroid Build Coastguard Worker }
202*9860b763SAndroid Build Coastguard Worker 
203*9860b763SAndroid Build Coastguard Worker impl crypto::AadOperation for BoringAesGcmDecryptOperation {
update_aad(&mut self, aad: &[u8]) -> Result<(), Error>204*9860b763SAndroid Build Coastguard Worker     fn update_aad(&mut self, aad: &[u8]) -> Result<(), Error> {
205*9860b763SAndroid Build Coastguard Worker         ossl!(self.crypter.aad_update(aad))
206*9860b763SAndroid Build Coastguard Worker     }
207*9860b763SAndroid Build Coastguard Worker }
208*9860b763SAndroid Build Coastguard Worker 
209*9860b763SAndroid Build Coastguard Worker impl crypto::EmittingOperation for BoringAesGcmDecryptOperation {
update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error>210*9860b763SAndroid Build Coastguard Worker     fn update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error> {
211*9860b763SAndroid Build Coastguard Worker         // The current input is the (self.pending_input_tail || data) combination.
212*9860b763SAndroid Build Coastguard Worker         let combined_len = self.pending_input_tail.len() + data.len();
213*9860b763SAndroid Build Coastguard Worker         if combined_len <= self.decrypt_tag_len {
214*9860b763SAndroid Build Coastguard Worker             // Adding on this data is still not enough for more than just a tag,
215*9860b763SAndroid Build Coastguard Worker             // so save off the input data for next time and return.
216*9860b763SAndroid Build Coastguard Worker             self.pending_input_tail.try_extend_from_slice(data)?;
217*9860b763SAndroid Build Coastguard Worker             return Ok(Vec::new());
218*9860b763SAndroid Build Coastguard Worker         }
219*9860b763SAndroid Build Coastguard Worker 
220*9860b763SAndroid Build Coastguard Worker         // At this point the combination (self.pending_input_tail || data) includes enough data to both:
221*9860b763SAndroid Build Coastguard Worker         // - feed some into the cipher
222*9860b763SAndroid Build Coastguard Worker         // - still keep a full self.decrypt_tag_len worth of data still pending.
223*9860b763SAndroid Build Coastguard Worker         let cipherable_len = combined_len - self.decrypt_tag_len;
224*9860b763SAndroid Build Coastguard Worker         let cipherable_from_pending = min(cipherable_len, self.pending_input_tail.len());
225*9860b763SAndroid Build Coastguard Worker         let cipherable_from_data = cipherable_len - cipherable_from_pending;
226*9860b763SAndroid Build Coastguard Worker 
227*9860b763SAndroid Build Coastguard Worker         let mut output = vec_try![0; data.len()]?;
228*9860b763SAndroid Build Coastguard Worker         let mut offset = 0;
229*9860b763SAndroid Build Coastguard Worker         if cipherable_from_pending > 0 {
230*9860b763SAndroid Build Coastguard Worker             offset = self
231*9860b763SAndroid Build Coastguard Worker                 .crypter
232*9860b763SAndroid Build Coastguard Worker                 .update(&self.pending_input_tail[..cipherable_from_pending], &mut output)
233*9860b763SAndroid Build Coastguard Worker                 .map_err(openssl_err!(
234*9860b763SAndroid Build Coastguard Worker                     "update {} bytes from pending failed",
235*9860b763SAndroid Build Coastguard Worker                     cipherable_from_pending
236*9860b763SAndroid Build Coastguard Worker                 ))?;
237*9860b763SAndroid Build Coastguard Worker         }
238*9860b763SAndroid Build Coastguard Worker         if cipherable_from_data > 0 {
239*9860b763SAndroid Build Coastguard Worker             let out_len = self
240*9860b763SAndroid Build Coastguard Worker                 .crypter
241*9860b763SAndroid Build Coastguard Worker                 .update(&data[..cipherable_from_data], &mut output[offset..])
242*9860b763SAndroid Build Coastguard Worker                 .map_err(openssl_err!("update {} bytes from input failed", cipherable_from_data))?;
243*9860b763SAndroid Build Coastguard Worker             offset += out_len;
244*9860b763SAndroid Build Coastguard Worker         }
245*9860b763SAndroid Build Coastguard Worker         output.truncate(offset);
246*9860b763SAndroid Build Coastguard Worker 
247*9860b763SAndroid Build Coastguard Worker         // Reset `self.pending_input_tail` to the unused data.
248*9860b763SAndroid Build Coastguard Worker         let leftover_pending = self.pending_input_tail.len() - cipherable_from_pending;
249*9860b763SAndroid Build Coastguard Worker         self.pending_input_tail.resize(self.decrypt_tag_len, 0);
250*9860b763SAndroid Build Coastguard Worker         self.pending_input_tail.copy_within(cipherable_from_pending.., 0);
251*9860b763SAndroid Build Coastguard Worker         self.pending_input_tail[leftover_pending..].copy_from_slice(&data[cipherable_from_data..]);
252*9860b763SAndroid Build Coastguard Worker 
253*9860b763SAndroid Build Coastguard Worker         Ok(output)
254*9860b763SAndroid Build Coastguard Worker     }
255*9860b763SAndroid Build Coastguard Worker 
finish(mut self: Box<Self>) -> Result<Vec<u8>, Error>256*9860b763SAndroid Build Coastguard Worker     fn finish(mut self: Box<Self>) -> Result<Vec<u8>, Error> {
257*9860b763SAndroid Build Coastguard Worker         // Need to feed in the entire tag before completion.
258*9860b763SAndroid Build Coastguard Worker         if self.pending_input_tail.len() != self.decrypt_tag_len {
259*9860b763SAndroid Build Coastguard Worker             return Err(km_err!(
260*9860b763SAndroid Build Coastguard Worker                 InvalidTag,
261*9860b763SAndroid Build Coastguard Worker                 "only {} bytes of pending data, need {}",
262*9860b763SAndroid Build Coastguard Worker                 self.pending_input_tail.len(),
263*9860b763SAndroid Build Coastguard Worker                 self.decrypt_tag_len
264*9860b763SAndroid Build Coastguard Worker             ));
265*9860b763SAndroid Build Coastguard Worker         }
266*9860b763SAndroid Build Coastguard Worker         self.crypter.set_tag(&self.pending_input_tail).map_err(openssl_err!(
267*9860b763SAndroid Build Coastguard Worker             "failed to set {} bytes of tag",
268*9860b763SAndroid Build Coastguard Worker             self.pending_input_tail.len()
269*9860b763SAndroid Build Coastguard Worker         ))?;
270*9860b763SAndroid Build Coastguard Worker 
271*9860b763SAndroid Build Coastguard Worker         // Feeding in just the tag should not result in any output data.
272*9860b763SAndroid Build Coastguard Worker         let mut output = Vec::new();
273*9860b763SAndroid Build Coastguard Worker         let out_len = self
274*9860b763SAndroid Build Coastguard Worker             .crypter
275*9860b763SAndroid Build Coastguard Worker             .finalize(&mut output)
276*9860b763SAndroid Build Coastguard Worker             .map_err(openssl_err_or!(VerificationFailed, "failed to finalize"))?;
277*9860b763SAndroid Build Coastguard Worker         if out_len != 0 {
278*9860b763SAndroid Build Coastguard Worker             return Err(km_err!(
279*9860b763SAndroid Build Coastguard Worker                 BoringSslError,
280*9860b763SAndroid Build Coastguard Worker                 "finalizing AES-GCM tag produced {} bytes of data!",
281*9860b763SAndroid Build Coastguard Worker                 out_len
282*9860b763SAndroid Build Coastguard Worker             ));
283*9860b763SAndroid Build Coastguard Worker         }
284*9860b763SAndroid Build Coastguard Worker         Ok(output)
285*9860b763SAndroid Build Coastguard Worker     }
286*9860b763SAndroid Build Coastguard Worker }
287