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