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