Skip to content

Commit

Permalink
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Suppor…
Browse files Browse the repository at this point in the history
…t cryptography module
  • Loading branch information
InfoHunter committed Jun 13, 2024
1 parent 06289fc commit 26e2cf7
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 9 deletions.
2 changes: 2 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,7 @@ compile_error! {
fn main() {
if let Ok(_) = env::var("DEP_OPENSSL_TONGSUO") {
println!("cargo:rustc-cfg=tongsuo");
} else if cfg!(feature = "crypto_adaptor_tongsuo") {
println!("cargo:rustc-cfg=tongsuo");
}
}
129 changes: 122 additions & 7 deletions src/modules/crypto/crypto_adaptors/tongsuo_adaptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::errors::RvError;
use crate::modules::crypto::{AEADCipher, AESKeySize, BlockCipher, CipherMode, AES};
use openssl::symm::{Cipher, Crypter, Mode, encrypt, encrypt_aead, decrypt, decrypt_aead};
use openssl::rand::rand_priv_bytes;
use crate::modules::crypto::SM4;

pub struct AdaptorCTX {
ctx: Crypter,
Expand Down Expand Up @@ -326,22 +327,97 @@ impl AEADCipher for AES {
}

impl SM4 {
fn new(
/// This function is the constructor of the SM4 struct, it returns a new SM4 object on success.
///
/// keygen: true stands for generating a key and iv; if false, then the caller needs to feed in
/// the specific key and iv values through the parameters.
/// mode: cipher mode of SM4, such as CBC, GCM, etc. If omitted, CipherMode::CBC is default.
/// key: symmetric key that is used to encrypt and decrypt data.
/// iv: initialization vector. This depends on specific mode, for instance, ECB requires no IV.
pub fn new(
keygen: bool,
mode: Option<CipherMode>,
key: Option<Vec<u8>>,
iv: Option<Vec<u8>>,
) -> Result<Self, RvError> {
let ret = SM4 { mode: mode.unwrap(), key: key.unwrap(), iv: iv.unwrap(), aad: None, ctx: None };
// default algorithm: SM4-CBC.
let mut c_mode = CipherMode::CBC;
let sm4_key: Vec<u8>;
let sm4_iv: Vec<u8>;

if let Some(x) = mode {
c_mode = x;
}

Ok(ret)
if keygen == false {
match (key, iv) {
(Some(x), Some(y)) => {
sm4_key = x.clone();
sm4_iv = y.clone();
},
_ => return Err(RvError::ErrCryptoCipherInitFailed),
}
} else {
// generate new key and iv based on k_size.
// for SM4, key is 16 bytes and iv is 16 bytes
let mut buf = [0; 16];
let mut buf2 = [0; 16];
rand_priv_bytes(&mut buf).unwrap();
sm4_key = buf.to_vec();
rand_priv_bytes(&mut buf2).unwrap();
sm4_iv = buf2.to_vec();
}

Ok (
SM4 {
mode: c_mode,
key: sm4_key,
iv: sm4_iv,
aad: None,
ctx: None,
tag: None,
}
)
}

/// This function returns the key and iv vaule stored in one SM4 object.
///
/// Two values are returned in a tuple: the first element represents the key, and the second
/// element represents the IV. Elements may be None if unset.
pub fn get_key_iv(&self) -> (Vec<u8>, Vec<u8>) {
(self.key.clone(), self.iv.clone())
}
}

impl BlockCipher for SM4 {
fn encrypt(&mut self, plain: Vec<u8>) -> Result<Vec<u8>, RvError> {
Err(RvError::ErrCryptoCipherOPNotSupported)
fn encrypt(&mut self, plaintext: &Vec<u8>) -> Result<Vec<u8>, RvError> {
match self.mode {
CipherMode::CBC => {
let ciphertext = encrypt(
Cipher::sm4_cbc(),
&self.key,
Some(&self.iv),
plaintext).unwrap();
return Ok(ciphertext.to_vec());
}
CipherMode::GCM => {
// aes_128_gcm's tag is 16-bytes long.
let tag: &mut [u8] = &mut [0; 16];
let ciphertext = encrypt_aead(
Cipher::sm4_gcm(),
&self.key,
Some(&self.iv),
&self.aad.clone().unwrap(),
plaintext,
tag
).unwrap();
self.tag = Some(tag.to_vec());
return Ok(ciphertext.to_vec());
}
_ => Err(RvError::ErrCryptoCipherOPNotSupported),
}
}

fn encrypt_update(&mut self, plaintext: Vec<u8>, ciphertext: &mut Vec<u8>
) -> Result<usize, RvError> {
Err(RvError::ErrCryptoCipherOPNotSupported)
Expand All @@ -350,8 +426,30 @@ impl BlockCipher for SM4 {
) -> Result<usize, RvError> {
Err(RvError::ErrCryptoCipherOPNotSupported)
}
fn decrypt(&mut self, plain: Vec<u8>) -> Result<Vec<u8>, RvError> {
Err(RvError::ErrCryptoCipherOPNotSupported)
fn decrypt(&mut self, ciphertext: &Vec<u8>) -> Result<Vec<u8>, RvError> {
match self.mode {
CipherMode::CBC => {
let plaintext = decrypt(
Cipher::sm4_cbc(),
&self.key,
Some(&self.iv),
ciphertext).unwrap();
return Ok(plaintext.to_vec());
}
CipherMode::GCM => {
// SM4 is a fixed 128-bit cipher, the tag is 16-bytes long.
let plaintext = decrypt_aead(
Cipher::sm4_gcm(),
&self.key,
Some(&self.iv),
&self.aad.clone().unwrap(),
ciphertext,
&self.tag.clone().unwrap()
).unwrap();
return Ok(plaintext.to_vec());
}
_ => Err(RvError::ErrCryptoCipherOPNotSupported),
}
}
fn decrypt_update(&mut self, ciphertext: Vec<u8>, plaintext: &mut Vec<u8>
) -> Result<usize, RvError> {
Expand All @@ -362,3 +460,20 @@ impl BlockCipher for SM4 {
Err(RvError::ErrCryptoCipherOPNotSupported)
}
}

impl AEADCipher for SM4 {
fn set_aad(&mut self, aad: Vec<u8>) -> Result<(), RvError> {
self.aad = Some(aad.clone());
Ok(())
}
fn get_tag(&mut self) -> Result<Vec<u8>, RvError> {
if self.tag == None {
return Err(RvError::ErrCryptoCipherNoTag);
}
Ok(self.tag.clone().unwrap())
}
fn set_tag(&mut self, tag: Vec<u8>) -> Result<(), RvError> {
self.tag = Some(tag.clone());
Ok(())
}
}
18 changes: 16 additions & 2 deletions src/modules/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ pub struct SM4 {
mode: CipherMode,
key: Vec<u8>,
iv: Vec<u8>,
aad: Option<String>,
aad: Option<Vec<u8>>,
tag: Option<Vec<u8>>,
ctx: Option<AdaptorCTX>,
}

Expand Down Expand Up @@ -118,7 +119,7 @@ pub trait AEADCipher: BlockCipher {

#[cfg(test)]
mod crypto_test {
use crate::modules::crypto::{AES, AESKeySize, CipherMode, BlockCipher, AEADCipher};
use crate::modules::crypto::{SM4, AES, AESKeySize, CipherMode, BlockCipher, AEADCipher};

#[test]
fn test_aes_keygen() {
Expand Down Expand Up @@ -277,4 +278,17 @@ mod crypto_test {
// evaluate the result.
assert_eq!(data2.to_vec(), pt);
}

#[cfg(feature = "crypto_adaptor_tongsuo")]
#[test]
fn test_sm4_keygen() {
let data = b"The best way to not feel hopeless is to get up and do something.".to_vec();
let mut sm4_encrypter = SM4::new(true, Some(CipherMode::CBC), None, None).unwrap();
let mut sm4_decrypter = SM4::new(false, Some(CipherMode::CBC),
Some(sm4_encrypter.get_key_iv().0), Some(sm4_encrypter.get_key_iv().1)).unwrap();

let ct = sm4_encrypter.encrypt(&data).unwrap();
let pt = sm4_decrypter.decrypt(&ct).unwrap();
assert_eq!(data, pt);
}
}

0 comments on commit 26e2cf7

Please sign in to comment.