]> git.proxmox.com Git - proxmox-backup.git/blobdiff - src/backup/crypt_config.rs
src/backup/crypt_config.rs - generate_rsa_encoded_key: store as json
[proxmox-backup.git] / src / backup / crypt_config.rs
index 15dbc31b078ab52dcc9620a228960eafc961821f..f826d65bd2c3da0fd807b29cfa35bd083e058bbe 100644 (file)
@@ -12,6 +12,7 @@ use openssl::pkcs5::pbkdf2_hmac;
 use openssl::hash::MessageDigest;
 use openssl::symm::{decrypt_aead, Cipher, Crypter, Mode};
 use std::io::Write;
+use chrono::{Local, TimeZone, DateTime};
 
 /// Encryption Configuration with secret key
 ///
@@ -106,76 +107,14 @@ impl CryptConfig {
         Ok((iv, tag))
     }
 
-    /// Compress and encrypt data using a random 16 byte IV.
-    ///
-    /// Return the encrypted data, including IV and MAC (MAGIC || IV || MAC || ENC_DATA).
-    /// If compression does not help, we return the uncompresssed, encrypted data.
-    pub fn encode_chunk(
+    /// Decompress and decrypt date, verify MAC.
+    pub fn decode_compressed_chunk(
         &self,
-        // The data you want to encode
         data: &[u8],
-        // Whether try to compress data before encryption
-        compress: bool,
-        // Magic number used for uncompressed results
-        uncomp_magic: &[u8; 8],
-        // Magic number used for compressed results
-        comp_magic: &[u8; 8],
+        iv: &[u8; 16],
+        tag: &[u8; 16],
     ) -> Result<Vec<u8>, Error> {
 
-        let iv = proxmox::sys::linux::random_data(16)?;
-        let mut c = Crypter::new(self.cipher, Mode::Encrypt, &self.enc_key, Some(&iv))?;
-        c.aad_update(b"")?; //??
-
-        if compress {
-            let compr_data = zstd::block::compress(data, 1)?;
-            // Note: We only use compression if result is shorter
-            if compr_data.len() < data.len() {
-                let mut enc = vec![0; compr_data.len()+44+self.cipher.block_size()];
-
-                enc[0..8].copy_from_slice(comp_magic);
-                enc[8..12].copy_from_slice(&[0u8; 4]);
-                enc[12..28].copy_from_slice(&iv);
-
-                let count = c.update(&compr_data, &mut enc[44..])?;
-                let rest = c.finalize(&mut enc[(44+count)..])?;
-                enc.truncate(44 + count + rest);
-
-                c.get_tag(&mut enc[28..44])?;
-
-                return Ok(enc)
-            }
-        }
-
-        let mut enc = vec![0; data.len()+44+self.cipher.block_size()];
-
-        enc[0..8].copy_from_slice(uncomp_magic);
-        enc[8..12].copy_from_slice(&[0u8; 4]);
-        enc[12..28].copy_from_slice(&iv);
-
-        let count = c.update(data, &mut enc[44..])?;
-        let rest = c.finalize(&mut enc[(44+count)..])?;
-        enc.truncate(44 + count + rest);
-
-        c.get_tag(&mut enc[28..44])?;
-
-        Ok(enc)
-    }
-
-    /// Decompress and decrypt chunk, verify MAC.
-    ///
-    /// Binrary ``data`` is expected to be in format returned by encode_chunk. The magic number
-    /// is not used here.
-    pub fn decode_compressed_chunk(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
-
-        if data.len() < 44 {
-            bail!("Invalid chunk len (<44)");
-        }
-
-        // let magic = &data[0..8];
-        // let crc = &data[8..12];
-        let iv = &data[12..28];
-        let mac = &data[28..44];
-
         let dec = Vec::with_capacity(1024*1024);
 
         let mut decompressor = zstd::stream::write::Decoder::new(dec)?;
@@ -188,7 +127,7 @@ impl CryptConfig {
         let mut decr_buf = [0u8; BUFFER_SIZE];
         let max_decoder_input = BUFFER_SIZE - self.cipher.block_size();
 
-        let mut start = 44;
+        let mut start = 0;
         loop {
             let mut end = start + max_decoder_input;
             if end > data.len() { end = data.len(); }
@@ -201,7 +140,7 @@ impl CryptConfig {
             }
         }
 
-        c.set_tag(mac)?;
+        c.set_tag(tag)?;
         let rest = c.finalize(&mut decr_buf)?;
         if rest > 0 { decompressor.write_all(&decr_buf[..rest])?; }
 
@@ -210,30 +149,41 @@ impl CryptConfig {
         Ok(decompressor.into_inner())
     }
 
-    /// Decrypt chunk, verify MAC.
-    ///
-    /// Binrary ``data`` is expected to be in format returned by encode_chunk. The magic number
-    /// is not used here.
-    pub fn decode_uncompressed_chunk(&self, data: &[u8]) -> Result<Vec<u8>, Error> {
-
-        if data.len() < 44 {
-            bail!("Invalid chunk len (<44)");
-        }
-
-        // let magic = &data[0..8];
-        // let crc = &data[8..12];
-        let iv = &data[12..28];
-        let mac = &data[28..44];
+    /// Decrypt data, verify tag.
+    pub fn decode_uncompressed_chunk(
+        &self,
+        data: &[u8],
+        iv: &[u8; 16],
+        tag: &[u8; 16],
+    ) -> Result<Vec<u8>, Error> {
 
         let decr_data = decrypt_aead(
             self.cipher,
             &self.enc_key,
             Some(iv),
             b"", //??
-            &data[44..],
-            mac,
+            data,
+            tag,
         )?;
 
         Ok(decr_data)
     }
+
+    pub fn generate_rsa_encoded_key(
+        &self,
+        rsa: openssl::rsa::Rsa<openssl::pkey::Public>,
+        created: DateTime<Local>,
+    ) -> Result<Vec<u8>, Error> {
+
+         let modified = Local.timestamp(Local::now().timestamp(), 0);
+        let key_config = super::KeyConfig { kdf: None, created, modified, data: self.enc_key.to_vec() };
+        let data = serde_json::to_string(&key_config)?.as_bytes().to_vec();
+
+        let mut buffer = vec![0u8; rsa.size() as usize];
+        let len = rsa.public_encrypt(&data, &mut buffer, openssl::rsa::Padding::PKCS1)?;
+        if len != buffer.len() {
+            bail!("got unexpected length from rsa.public_encrypt().");
+        }
+        Ok(buffer)
+    }
 }