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