1use crate::error::Error;
2
3use openssl::rand::rand_bytes;
4use openssl::symm::{decrypt_aead, encrypt_aead, Cipher};
5use serde::{Deserialize, Serialize};
6use zeroize::Zeroizing;
7
8#[cfg(target_arch = "aarch64")]
21const UNIQUE_SEALING_KEY: u64 =
22 rust_rsi::RSI_SEALING_KEY_FLAGS_KEY | rust_rsi::RSI_SEALING_KEY_FLAGS_RIM;
23
24const AES_GCM_256_IV_LEN: usize = 12;
25const AES_GCM_256_TAG_LEN: usize = 16;
26const SEALING_KEY_LEN: usize = 32;
27
28#[cfg(target_arch = "x86_64")]
30const SEALING_KEY: [u8; SEALING_KEY_LEN] = [
31 0x63, 0x10, 0xc1, 0xf0, 0x53, 0xd5, 0x52, 0x40, 0x29, 0xfa, 0x7f, 0x7d, 0xcd, 0x9e, 0x28, 0x2c,
32 0x4a, 0x93, 0x9d, 0x55, 0xb9, 0x89, 0x15, 0x44, 0x45, 0xa3, 0x86, 0x1e, 0x1f, 0xa1, 0xe2, 0xce,
33];
34
35#[derive(Serialize, Deserialize)]
36struct Header {
37 tag: [u8; AES_GCM_256_TAG_LEN],
38 iv: [u8; AES_GCM_256_IV_LEN],
39}
40
41impl Header {
42 fn new() -> Result<Self, Error> {
43 let mut instance = Self {
44 tag: [0u8; AES_GCM_256_TAG_LEN],
45 iv: [0u8; AES_GCM_256_IV_LEN],
46 };
47 rand_bytes(&mut instance.iv).map_err(|_| Error::Sealing)?;
48 Ok(instance)
49 }
50}
51
52#[derive(Serialize, Deserialize)]
53struct SealedData {
54 header: Header,
55 ciphertext: Vec<u8>,
56}
57
58fn sealing_key() -> Result<[u8; SEALING_KEY_LEN], Error> {
59 cfg_if::cfg_if! {
60 if #[cfg(target_arch="x86_64")] {
62 Ok(SEALING_KEY)
63 } else {
64 rust_rsi::sealing_key(UNIQUE_SEALING_KEY, 0).or(Err(Error::SealingKey))
65 }
66 }
67}
68
69pub fn seal(plaintext: &[u8]) -> Result<Vec<u8>, Error> {
70 let mut header = Header::new()?;
71 let cipher = Cipher::aes_256_gcm();
72 let sealing_key = Zeroizing::new(sealing_key().map_err(|_| Error::SealingKey)?);
73
74 let enc_res = encrypt_aead(
75 cipher,
76 sealing_key.as_ref(),
77 Some(&header.iv),
78 &[],
79 plaintext,
80 &mut header.tag,
81 );
82
83 let sealed_data = SealedData {
84 header: header,
85 ciphertext: enc_res.map_err(|_| Error::Sealing)?,
86 };
87
88 bincode::serialize(&sealed_data).map_err(|_| Error::Sealing)
89}
90
91pub fn unseal(sealed: &[u8]) -> Result<Vec<u8>, Error> {
92 let sealed_data: SealedData = bincode::deserialize(sealed).map_err(|_| Error::Sealing)?;
93 let cipher = Cipher::aes_256_gcm();
94 let sealing_key = Zeroizing::new(sealing_key().map_err(|_| Error::SealingKey)?);
95
96 let dec_res = decrypt_aead(
97 cipher,
98 sealing_key.as_ref(),
99 Some(&sealed_data.header.iv),
100 &[],
101 &sealed_data.ciphertext,
102 &sealed_data.header.tag,
103 );
104
105 dec_res.map_err(|_| Error::Sealing)
106}