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 3-DES. 16 use crate::{openssl_err, ossl}; 17 use alloc::boxed::Box; 18 use alloc::vec::Vec; 19 use kmr_common::{crypto, crypto::OpaqueOr, explicit, vec_try, Error}; 20 use openssl::symm::{Cipher, Crypter}; 21 22 /// [`crypto::Des`] implementation based on BoringSSL. 23 pub struct BoringDes; 24 25 impl crypto::Des for BoringDes { begin( &self, key: OpaqueOr<crypto::des::Key>, mode: crypto::des::Mode, dir: crypto::SymmetricOperation, ) -> Result<Box<dyn crypto::EmittingOperation>, Error>26 fn begin( 27 &self, 28 key: OpaqueOr<crypto::des::Key>, 29 mode: crypto::des::Mode, 30 dir: crypto::SymmetricOperation, 31 ) -> Result<Box<dyn crypto::EmittingOperation>, Error> { 32 let key = explicit!(key)?; 33 let dir_mode = match dir { 34 crypto::SymmetricOperation::Encrypt => openssl::symm::Mode::Encrypt, 35 crypto::SymmetricOperation::Decrypt => openssl::symm::Mode::Decrypt, 36 }; 37 let crypter = match mode { 38 crypto::des::Mode::EcbNoPadding | crypto::des::Mode::EcbPkcs7Padding => { 39 let cipher = Cipher::des_ede3(); 40 let mut crypter = Crypter::new(cipher, dir_mode, &key.0, None) 41 .map_err(openssl_err!("failed to create ECB Crypter"))?; 42 if let crypto::des::Mode::EcbPkcs7Padding = mode { 43 crypter.pad(true); 44 } else { 45 crypter.pad(false); 46 } 47 crypter 48 } 49 50 crypto::des::Mode::CbcNoPadding { nonce: n } 51 | crypto::des::Mode::CbcPkcs7Padding { nonce: n } => { 52 let cipher = Cipher::des_ede3_cbc(); 53 let mut crypter = Crypter::new(cipher, dir_mode, &key.0, Some(&n[..])) 54 .map_err(openssl_err!("failed to create CBC Crypter"))?; 55 if let crypto::des::Mode::CbcPkcs7Padding { nonce: _ } = mode { 56 crypter.pad(true); 57 } else { 58 crypter.pad(false); 59 } 60 crypter 61 } 62 }; 63 64 Ok(Box::new(BoringDesOperation { crypter })) 65 } 66 } 67 68 /// [`crypto::DesOperation`] implementation based on BoringSSL. 69 pub struct BoringDesOperation { 70 crypter: openssl::symm::Crypter, 71 } 72 73 impl crypto::EmittingOperation for BoringDesOperation { update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error>74 fn update(&mut self, data: &[u8]) -> Result<Vec<u8>, Error> { 75 let mut output = vec_try![0; data.len() + crypto::des::BLOCK_SIZE]?; 76 let out_len = self 77 .crypter 78 .update(data, &mut output[..]) 79 .map_err(openssl_err!("update with {} bytes of data failed", data.len()))?; 80 output.truncate(out_len); 81 Ok(output) 82 } 83 finish(mut self: Box<Self>) -> Result<Vec<u8>, Error>84 fn finish(mut self: Box<Self>) -> Result<Vec<u8>, Error> { 85 let mut output = vec_try![0; crypto::des::BLOCK_SIZE]?; 86 let out_len = ossl!(self.crypter.finalize(&mut output))?; 87 output.truncate(out_len); 88 Ok(output) 89 } 90 } 91