Commit 18501ee4 authored by Jarvis Zheng's avatar Jarvis Zheng
Browse files

Add sm4 encryption support

parent bba17128
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+11 −0
Original line number Diff line number Diff line
@@ -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();

+28 −0
Original line number Diff line number Diff line
@@ -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;
+67 −0
Original line number Diff line number Diff line
@@ -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]);
    }
}