diff --git a/openssl-sys/build/expando.c b/openssl-sys/build/expando.c index 300c50bb05e386ab43b01d58d7b6c55daca42675..c150dcd51f960fa35370f382cb804de6b2ebcd23 100644 --- a/openssl-sys/build/expando.c +++ b/openssl-sys/build/expando.c @@ -95,6 +95,10 @@ RUST_CONF_OPENSSL_NO_STDIO RUST_CONF_OPENSSL_NO_SM3 #endif +#ifdef OPENSSL_NO_SM4 +RUST_CONF_OPENSSL_NO_SM4 +#endif + #ifdef OPENSSL_NO_DEPRECATED_3_0 RUST_CONF_OPENSSL_NO_DEPRECATED_3_0 #endif diff --git a/openssl-sys/src/handwritten/evp.rs b/openssl-sys/src/handwritten/evp.rs index af89a5c70e5180efda9e10490cb4b2da3f064597..506112ad8e4e9e7490a555b0c106aeb92e491edf 100644 --- a/openssl-sys/src/handwritten/evp.rs +++ b/openssl-sys/src/handwritten/evp.rs @@ -347,6 +347,17 @@ extern "C" { #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] pub fn EVP_seed_ofb() -> *const EVP_CIPHER; + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn EVP_sm4_ecb() -> *const ::EVP_CIPHER; + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn EVP_sm4_cbc() -> *const ::EVP_CIPHER; + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn EVP_sm4_cfb128() -> *const ::EVP_CIPHER; + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn EVP_sm4_ofb() -> *const ::EVP_CIPHER; + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn EVP_sm4_ctr() -> *const ::EVP_CIPHER; + #[cfg(not(ossl110))] pub fn OPENSSL_add_all_algorithms_noconf(); diff --git a/openssl-sys/src/obj_mac.rs b/openssl-sys/src/obj_mac.rs index e3930ef45f5d81459b7b1984c601e88f796317c3..0bd795c8b992240e4e22b896075f76d4e014ddad 100644 --- a/openssl-sys/src/obj_mac.rs +++ b/openssl-sys/src/obj_mac.rs @@ -930,3 +930,31 @@ pub const NID_sm3: c_int = 968; pub const NID_sm3WithRSAEncryption: c_int = 1144; #[cfg(libressl291)] pub const NID_sm3WithRSAEncryption: c_int = 969; +#[cfg(ossl111)] +pub const NID_sm4_ecb: c_int = 1133; +#[cfg(libressl291)] +pub const NID_sm4_ecb: c_int = 973; +#[cfg(ossl111)] +pub const NID_sm4_cbc: c_int = 1134; +#[cfg(libressl291)] +pub const NID_sm4_cbc: c_int = 974; +#[cfg(ossl111)] +pub const NID_sm4_ofb128: c_int = 1135; +#[cfg(libressl291)] +pub const NID_sm4_ofb128: c_int = 975; +#[cfg(ossl111)] +pub const NID_sm4_cfb128: c_int = 1137; +#[cfg(libressl291)] +pub const NID_sm4_cfb128: c_int = 976; +#[cfg(ossl111)] +pub const NID_sm4_cfb1: c_int = 1136; +#[cfg(libressl291)] +pub const NID_sm4_cfb1: c_int = 977; +#[cfg(ossl111)] +pub const NID_sm4_cfb8: c_int = 1138; +#[cfg(libressl291)] +pub const NID_sm4_cfb8: c_int = 978; +#[cfg(ossl111)] +pub const NID_sm4_ctr: c_int = 1139; +#[cfg(libressl291)] +pub const NID_sm4_ctr: c_int = 979; diff --git a/openssl/src/symm.rs b/openssl/src/symm.rs index e228c7149544e78d4694fb234ef989d44a833dba..6f9bbd7bbd875bb81c32eab1ef3664cf7b01549c 100644 --- a/openssl/src/symm.rs +++ b/openssl/src/symm.rs @@ -307,6 +307,31 @@ impl Cipher { unsafe { Cipher(ffi::EVP_seed_ofb()) } } + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn sm4_ecb() -> Cipher { + unsafe { Cipher(ffi::EVP_sm4_ecb()) } + } + + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn sm4_cbc() -> Cipher { + unsafe { Cipher(ffi::EVP_sm4_cbc()) } + } + + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn sm4_ctr() -> Cipher { + unsafe { Cipher(ffi::EVP_sm4_ctr()) } + } + + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn sm4_cfb128() -> Cipher { + unsafe { Cipher(ffi::EVP_sm4_cfb128()) } + } + + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + pub fn sm4_ofb() -> Cipher { + unsafe { Cipher(ffi::EVP_sm4_ofb()) } + } + /// Creates a `Cipher` from a raw pointer to its OpenSSL type. /// /// # Safety @@ -1520,4 +1545,46 @@ mod tests { cipher_test(super::Cipher::seed_ofb(), pt, ct, key, iv); } + + // GB/T 32907-2016 + // http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7803DE42D3BC5E80B0C3E5D8E873D56A + #[test] + #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))] + fn test_sm4_ecb() { + use std::mem; + + let key = vec![ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, + 0x32, 0x10, + ]; + let pt = vec![ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, + 0x32, 0x10, + ]; + let ct = vec![ + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, + 0x42, 0x46, + ]; + let ct1 = vec![ + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, + 0x3f, 0x66, + ]; + + let block_size = Cipher::sm4_ecb().block_size(); + let mut c = Crypter::new(Cipher::sm4_ecb(), Mode::Encrypt, &key, None).unwrap(); + c.pad(false); + + // 1 round + let mut r = vec![0; pt.len() + Cipher::sm4_ecb().block_size()]; + let count = c.update(&pt, &mut r).unwrap(); + assert_eq!(ct, &r[..count]); + + // 1000000 rounds + let mut r1 = vec![0; pt.len() + Cipher::sm4_ecb().block_size()]; + for _ in 0..999999 { + c.update(&r[..block_size], &mut r1).unwrap(); + mem::swap(&mut r, &mut r1); + } + assert_eq!(ct1, &r[..count]); + } }