文章链接来源:https://mp.weixin.qq.com/s/i2_2XodxUMc8O7JhhyLVSw
商密软件栈SIG :基于 Anolis OS,在整个系统软件层面(包括硬件,固件,bootloader,内核以及 OS)实现以国密算法为主的全栈国密操作系统,结束一直以来国密算法生态碎片化的状况,在技术方面打造社区和生态,在资质合规方面致力于为行业提供基于国密的信息安全标准。
作者:李艺林(伯纪),商密软件栈SIG核心成员。
欢迎更多开发者加入商密软件栈SIG:
网址:https://openanolis.cn/sig/crypto
邮件列表:tc@lists.openanolis.cn
背景
随着近年来国际贸易冲突和技术*,互联网的快速发展,以及 IOT 领域的崛起,金融领域的变革愈演愈烈。摆脱对国外技术和产品的过度依赖,建设行业网络安全环境,增强我国行业信息系统的安全可信显得尤为必要和迫切。
密码算法是保障信息安全的核心技术,尤其是当下互联网核心领域长期以来都是沿用 AES、SHA-2、RSA 等国际通用的密码算法体系及相关标准。
Linux 内核和 OpenSSL 作为互联网的基础软件底座,近几年才对商密算法做了有限的支持,比如内核只实现了基础的 SM3 摘要算法和 SM4 对称加密,鉴于以上原因,近期我们在 Linux 上游社区实现了SM2非对称算法和国密证书,补齐了商密算法在内核的这块短板,并且率先在 Alibaba Cloud Linux 和 Anolis OS 发行版输出。同时蚂蚁的相关团队也积极投入,把商密标准推向了 OpenSSL 社区,并为国密标准的国际化做出了极大的贡献。
OS 内核安全一直是安全界重点研究的课题,今天我们使用商密算法来支撑 Linux 内核 IMA 安全子系统,为客户输出值得信赖的安全可信技术。
IMA简介
IMA 是 Integrity Measurement Architecture 的缩写,它是 Linux 内核中完整性子系统的一部分。目前 Linux 内核的完整性子系统支持 EVM 和 IMA,前者用于保护文件的扩展属性。这篇文章讨论的是后者。
IMA 所能做到的事情包括:
- 能够对正在打开的文件进行完整性评估。
- 能够对正在执行 exec 的文件(可执行程序)进行完整性评估。
- 能够对正在执行 mmap(PROT_EXEC) 的文件(共享库)进行完整性评估。
- 能够对正在加载中的 kernel 模块和固件进行完整性评估。
所谓的完整性评估指的是对内核对文件客体在执行特定的内核操作时,会主动对文件的内容进行完整性检查。为此,IMA 子系统会借用内核的 security 子系统在 open(), execve(), mmap()等系统调用中下的 hook 来执行自己的代码。
IMA签名验证
IMA 在进行完整性验证时,会通过事先存储在文件系统中的文件扩展属性 security.ima 进行。具体来说,借用IMA签名工具 evmctl,在系统部署的时候,管理员以特权用户身份将文件的完整性信息写入文件扩展属性 security.ima 中。
在系统运行时,IMA 子系统会从该扩展属性中读取出文件的完整性信息,同时与实际计算出的完整性信息进行比较。如果结果一致,证明该文件没有遭到过篡改,则允许执行后续的操作;如果结果不一致,证明文件内容遭到了篡改,则后续操作禁止执行。
因此,即使攻击者通过密码破解拿到了本地特权,或者利用安全漏洞拿到了本地特权,但是在准备运行恶意程序或植入了后门的程序的时候,因为在没有 IMA 私钥的情况下是无法构造出合法的 IMA 签名的,因此导致恶意程序或被篡改了的程序均无法运行。即使带有 IMA 保护的存储设备受到离线攻击(比如把存储设备从主机上取下,拿到另一台机器上进行修改,然后再重新安装到主机上),被篡改的文件或攻击者植入的恶意软件在运行时依旧无法运行,这在一定程度上能够抑制类似 Dirty Cow 这样的内核漏洞所带来的危害。
IMA商密化
所谓 IMA 商密化,就是在 IMA 整个签名验证流程中,使用商密算法 SM3 代替国际常用的哈希算法 SHA256、SHA512 等,用 SM2 算法的签名验签取代 RSA 算法。
本文中用到的主要是以下公开的商密算法:
- SM2:基于椭圆曲线密码(ECC)的公钥密码算法标准,提供数字签名,密钥交换,公钥加密,用于替换 RSA/ECDSA/ECDH 等国际算法
- SM3:消息摘要算法,哈希结果为 256 bits,用于替换 MD5/SHA1/SHA256等国际算法
Anolis OS 简介
Anolis OS 是龙蜥社区(OpenAnolis)推出的完全开源、中立、开放的发行版,它支持多计算架构,也面向云端场景优化,100% 兼容 CentOS 8 软件生态。Anolis OS 8 旨在为广大开发者和运维人员提供稳定、高性能、安全、可靠、开源的操作系统服务。
BabaSSL 简介
BabaSSL 是诞生于蚂蚁的项目,是基于之前蚂蚁集团和阿里集团内部的 OpenSSL版本合并而来,项目主体已经在github开源(https://github.com/BabaSSL/BabaSSL ),当前开源的版本是 8.2.1,也是目前最新的稳定版本。
BabaSSL 目前在阿里集团和蚂蚁集团内部得到了非常广泛的使用。从具体场景来看,有如下三个方面,分别是存储、网络和端上的设备。其中网络服务的场景,是BabaSSL 最大的支撑场景,例如淘宝、天猫、阿里云等各种涉及到链路加密的服务器端。
BabaSSL 是主打国内商用密码的密码算法库,在兼容 OpenSSL 1.1.1 版本的基础上,全面支持了商密算法以及商密相关协议,作为国密场景下的密码算法主要解决方案,也是密码算法国产化的工程实现。
相对于传统的 OpenSSL,以下是 BabaSSL 提供一些特色功能:
- 基于 OpenSSL 1.1.1,具备 OpenSSL 1.1.1 的全部能力并且保持兼容
- 支持国密 SM2、 SM3 和 SM4,并对 OpenSSL 1.1.1 中所欠缺的 SM2 能力,比如 X509 证书的签发和验证功能进行了补全
- GM/T 0024 和 TLCP 国密双证书 TLS 协议
- 支持 RFC 8998:TLS 1.3+ 国密单证书
- 提供了对 IETF 正在标准化过程中的 Delegated Credentials
- 支持 IETF QUIC API 底层密码学能力
- 更加完善的 SM2 算法支持,比如 X.509 证书签发、验签的支持
- 正在申请软件密码模块一级资质
可以访问 BabaSSL 官方仓库(https://github.com/BabaSSL/BabaSSL)以获取更多详细信息。
准备环境
主要的环境包括操作系统和上层密码学相关工具包,操作系统这里选择 Anolis 商密版 OS 8.2 镜像(同时支持 x86 和 arm64),目前最新的版本已经完整支持了全套商密算法 SM2/3/4 以及使用 SM2-with-SM3 算法的 X509 证书,也是当下国内唯一从操作系统层面支持商密解决方案的 OS,并且默认开启了 IMA 特性。
上层密码学工具选择内置在镜像中的 BabaSSL,版本是 8.2.1,是完整实现了商密标准的密码算法库。BabaSSL 目前已经替代了 OpenSSL,默认内置在了 Anolis 商密镜像中。
配置 ShangMi 源
ShangMi 源会在下一个版本内置到全栈国密镜像中,当前您也可以通过编辑/etc/yum.repos.d/AnolisOS-ShangMi.repo
来使用 Anolis OS 的 ShangMi 源。
# AnolisOS-ShangMi.repo # [ShangMi] name=AnolisOS-$releasever - ShangMi baseurl=http://mirrors.openanolis.cn/anolis/$releasever/ShangMi/$basearch/os enabled=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ANOLIS gpgcheck=1
安装 IMA 实践必要的工具包
安装实践 IMA 必要的工具包:其中 BabaSSL 默认已经安装到标准目录取代OpenSSL, ima-evm-utils 默认已经安装。
yum install -y keyutils
生成商密密钥和证书
为了使用 IMA 功能,先要准备以下密钥和证书:
CA 根证书,自签名的证书,作为信任根内置到内核里
IMA 私钥,与 IMA 证书对应的 SM2 私钥,用于签名文件
IMA 证书,由 CA 根证书签名,系统启动后动态导入内核
# 创建签名证书请求使用的配置文件openssl.cnf cat > openssl.cnf << EOF [ req ] default_bits = 2048 distinguished_name = req_distinguished_name prompt = no string_mask = utf8only x509_extensions = v3_req [ req_distinguished_name ] O = Test OU = Test CN = Test key emailAddress = test@foo.com [ v3_req ] basicConstraints=critical,CA:FALSE keyUsage=digitalSignature subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always EOF # 生成SM2私钥private.pem openssl ecparam -genkey -name SM2 -out private.pem # 从私钥生成证书请求 openssl req -new \ -key private.pem \ -out csr.pem \ -sm3 -sigopt "sm2_id:1234567812345678" \ -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Alibaba/OU=OS/CN=test/emailAddress=test@foo.com" # 生成一个自签名的根证书ca.crt,作为CA证书 openssl ecparam -genkey -name SM2 -text -out ca.key openssl req -new \ -x509 -days 3650 \ -key ca.key \ -out ca.crt \ -sm3 -sigopt "sm2_id:1234567812345678" \ -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=Alibaba/OU=OS/CN=CA/emailAddress=ca@foo.com" # 使用CA证书给SM2证书请求签名,生成IMA要使用的商密证书cert.pem openssl x509 \ -req -days 3650 \ -in csr.pem \ -out cert.pem \ -sm3 \ -sigopt "sm2_id:1234567812345678" \ -sm2-id "1234567812345678" \ -CA ca.crt -CAkey ca.key -CAcreateserial \ -extfile openssl.cnf -extensions v3_req
编译内核
生成了 CA 证书之后,为了测试和验证 IMA 特性,我们就需要把 CA 根证书内置到内核,这需要使用新的 CA 根证书重新编译内核。
下载Anolis OS的ANCK内核源码
首先下载 Anolis OS 的 ANCK 内核代码,其开发分支为devel-4.19
git clone git@codeup.openanolis.cn:codeup/kernel/cloud-kernel.git -b devel-4.19
编译内核
# 安装编译依赖 yum install -y bison flex elfutils-libelf-devel bc make gcc # 用上一步生成好的ca.crt作为sm2_cert.pem,使用默认配置编译内核 cp -f ca.crt <kernel_src>/certs/sm2_cert.pem # 进入内核源码目录,使用默认配置编译内核 cd <kernel_src> # 如果您是arm的镜像,请将arch/arm64/configs/anolis_defconfig作为.config; # 如果是x86的,请将arch/x86/configs/anolis_defconfig作为.config。以x86为例 cp -f arch/x86/configs/anolis_defconfig .config # 配置系统的可信跟证书为/certs/sm2_cert.pem sed -i 's/CONFIG_SYSTEM_TRUSTED_KEYS=\"\"/CONFIG_SYSTEM_TRUSTED_KEYS=\"certs\/sm2_cert.pem\"/' .config make # 安装modules make modules_install # 安装内核,这一步也会自动生成initramfs并更新grub.cfg make install # 查看vmlinuz ls -l /boot/vmlinuz* # 将新内核(比如vmlinuz-4.19.91+ )设置为缺省的启动内核 grubby --set-default /boot/vmlinuz-4.19.91+ reboot
重启机器后,通过/proc/keys
或者keyctl
可以看到我们的 SM2 根证书已经内置到了内核中:
# cat /proc/keys | grep sm2 02a32516 I------ 1 perm 1f030000 0 0 asymmetri Alibaba: CA: bc08a9e6e43c30fd421ebc6fec7bb9063a089aca: X509.sm2 3a089aca [] # keyctl show %:.secondary_trusted_keys Keyring 371108982 ---lswrv 0 0 keyring: .secondary_trusted_keys 945861859 ---lswrv 0 0 \_ keyring: .builtin_trusted_keys 575535217 ---lswrv 0 0 \_ asymmetric: Build time autogenerated kernel key: 60d20efc1951f58c8bba2b04d937e4fa2a6cd62a 44246294 ---lswrv 0 0 \_ asymmetric: Alibaba: CA: bc08a9e6e43c30fd421ebc6fec7bb9063a089aca
IMA实践
导入IMA证书到内核
为了使用 IMA 功能,我们需要把前面用 CA 证书签名的 IMA 证书 cert.pem 导入到内核,之后才能用该证书正确验签 IMA 私钥签名的文件,因为内核已经集成了 CA 根证书,也只有 CA 签名的证书才能成功导入内核。
因为内核只支持导入 DER 格式的证书,因此我们需要先将 pem 的证书转换为 der 格式的,具体命令如下:
# 内核只支持导入DER格式的证书 openssl x509 -in cert.pem -out cert.der -outform der
用 keyctl 导入证书,注意系统重启后会失效
# 非持久性导入, 重启后失效 keyctl padd asymmetric "IMA" %:.ima < cert.der
IMA 证书导入成功后,我们可以从 /proc/keys 看到证书信息
# IMA证书导入成功后,我们可以从/proc/keys看到证书信息: cat /proc/keys | grep sm2 03cd0857 I------ 1 perm 1f030000 0 0 asymmetri Alibaba: CA: 10024aa19b7b8d73f4b3b413f70bcf94806f9ca2: X509.sm2 806f9ca2 [] 069ced19 I--Q--- 1 perm 39010000 0 0 asymmetri IMA: X509.sm2 604c5d8c []
IMA签名
接下来给系统中需要 IMA 验证的文件加上 SM3 的签名,这里简单粗暴的给常用目录下文件全部签名,如果文件比较多的话,这个过程会持续几分钟。
# 使用SM3哈希算法,private.pem是签名用的私钥,给系统主要目录下所有文件做IMA签名 evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /bin evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /sbin evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /usr evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /lib evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /lib64 evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /etc evmctl ima_sign -a sm3 -s -k /path/to/private.pem -r -t f /home # 通过getfattr可以查看添加到文件扩展属性中的签名数据(不是必需) yum install -y attr getfattr -n security.ima /path/to/file
导入 IMA 策略
IMA 策略是使能 IMA 的必备步骤,策略的内容可以根据实际需要进行定制。为了方便说明问题,这里以用户 imatest 来测试,在下面的规则示例中,当以 imatest 身份运行可执行程序和共享库时,会进行 IMA 度量以及 apprase 检查。
# 创建用户 imatestuseradd imatest # 用户ID可以从/etc/passwd中看到,这里是1001,用户ID会在IMA规则中用到 tail /etc/passwd | grep imatest # imatest:x:1001:1001::/home/imatest:/bin/bash
将下面的文件内容另存为ima.policy
文件:
appraise appraise_type=imasig uid=1001 func=BPRM_CHECK measure uid=1001 func=BPRM_CHECK appraise appraise_type=imasig uid=1001 func=MMAP_CHECK measure uid=1001 func=MMAP_CHECK
上面的规则表示:
- 度量以uid=1001身份运行的程序和共享库,并将度量值记录在 /sys/kernel/security/ima/ascii_runtime_measurements 文件中。
-
评估以 uid=1001 身份运行的程序和共享库,如果程序的完整性被破坏,程序将被拒绝运行。
然后写入 IMA 规则到内核:
cat ima.policy > /sys/kernel/security/ima/policy
IMA 验证
IMA 策略写入内核后,IMA 特性就已经在内核生效了,此时可以以 imatest 用户身份执行一些操作。
su imatest ... ...
通过ascii_runtime_measurements
我们可以看到 IMA 运行时度量的信息,这些都是通过 IMA 验证的文件,以下是部分度量日志:
# cat /sys/kernel/security/ima/ascii_runtime_measurements 10 bcb0e518b79de0d7f2cd20b8a29a7092e65db7ef ima-sig sha1:0000000000000000000000000000000000000000 boot_aggregate 10 d20bcf8ea6f3f8c03dd475766dfe18ccc14d264b ima-sig sm3:66acf6555ad2f6e5b89e1a80644eae4fd0015e5b811be63d1a58415e2f4f2b0e /usr/bin/bash 030211604c5d8c00473045022100ce91713b9aa37a2f8ce16f95acc00a7f072d7d3cc90ad8fae916ffc6072b10f4024 10 b829e4761f7a717dde6daab8089c8bac15fbb139 ima-sig sm3:1bcd4a4cb2a2c4418aa7075f5c012de03a383f3af172579132e5ad21bd5752c5 /usr/lib64/ld-2.17.so 030211604c5d8c0046304402203db3c575be22d35abe49d6e9f7fde0be22be02fdd9211feebf7ae172b8c66 10 be220df2bc614980a06eff27f7286305c7afbdc2 ima-sig sm3:66acf6555ad2f6e5b89e1a80644eae4fd0015e5b811be63d1a58415e2f4f2b0e /usr/bin/bash 030211604c5d8c00473045022100e66e7f2d356668c1779cfbe05838979c789d9f81c8b5cd0e19022b8255ea13f1024 10 d262c29452b0d575a81786c49453fe6f14c0969d ima-sig sm3:1bcd4a4cb2a2c4418aa7075f5c012de03a383f3af172579132e5ad21bd5752c5 /usr/lib64/ld-2.17.so 030211604c5d8c004730450220432ee49d0fe84c36633365afdd1fc138316e5ea2cb854c5dc5b0c9d03619f 10 26bf0fc75828783a0013b9f52045c9a56e8b4853 ima-sig sm3:18781f4c910453fdbcb36a359092128df86a660e230db4bb52765e32e209cf94 /usr/lib64/libtinfo.so.5.9 030211604c5d8c00473045022100fb46c2b15aef6f1005fea3f96d23d95a2d036d5da761d593b76891 10 28ee84f368f892180efaefb3d9b68c90ded73268 ima-sig sm3:1c568b3aa88a2bafe543d4aa1db95c12e7e062f54de5c55c50729fa3ac786ab2 /usr/lib64/libdl-2.17.so 030211604c5d8c00483046022100930e63c0325013bfdbdbe098bc13ac514703af2ff7998fe447675910 10 88120ffffa110b3621947f937117739f46cc8a46 ima-sig sm3:a53099f1946d13df1cf2561be1989cafbf4f1e4908294b315f80b8b07936c6d8 /usr/lib64/libc-2.17.so 030211604c5d8c00473045022010f571c748201ddc229f5b9cbbc4d471fb892b98653f8f73dc614eacfa2 10 1c83184c6b11f31ca8f1090aafc4ee5be8e336b0 ima-sig sm3:a591bc1f9eb1d1b89f0a1a83f6236302132a973515edebec1664499e32e42f12 /usr/lib64/libnss_files-2.17.so 030211604c5d8c00483046022100b51c03e638f2d71f6a4368592d8e055c231441962b1fb0989 ... ...
注意期中第一条日志,boot_aggregate 是系统启动阶段 TPM PCR 的汇聚值,这个值是汇聚 TPM 设备对应 PCR bank 的值做一个 digest,所使用的摘要算法是根据 TPM 设备版本以及支持的 PCR bank 决定,默认是 SHA1,当然这个摘要也可以通过配置成默认优先 SM3,例子中没有 TPM 设备,所以这里值是 0。
接下来,我们再构造一个没有经过签名的可执行文件并执行:
su imatest cd ~ echo 'int main(){}' > dummy.c gcc -o dummy dummy.c
运行 dummy 可执行文件,提示没有权限,这是符合预期的,同样,如果文件的签名是错误的,没有通过签名验证,也是会被拒绝执行的。
# ./dummy bash: ./dummy: Permission denied # dmesg audit: type=1800 audit(1631788187.296:8): pid=1426 uid=1001 auid=0 ses=4 op=appraise_data cause=IMA-signature-required comm="bash" name="/home/imatest/dummy" dev="vda2" ino=668226 res=0
我们看到,通过对这些软件栈的改造,可以平滑迁移到商密算法,并且完全基于商密算法构建出 IMA 的安全机制,而这些机制在以前都是完全且只能构建在国际标准的算法之上的。
未来展望
当下的商密标准或多或少已经在基础软件库中有了支持,虽然一些基础的安全能力也可以在商密算法的基础上建立起来,但是还有部分空白领域仍然需要持续的开拓,以应对我国信息安全行业的安全可信。
期待下篇,我们在内核模块签名之上所做的商密化改造。
—— 完 ——
关于龙蜥SIG
SIG是开放的,并争取让交付成果成为社区发行的一部分,由组内核心成员主导治理,可通过邮件列表和组内的成员进行交流。龙蜥社区SIG目前已超20个,包括硬件兼容性测试 SIG、商密软件栈、高性能存储技术 SIG、Java语言与虚拟机SIG、Cloud Kernel、OceanBase SIG等。
SIG网址:https://openanolis.cn/sig
加入龙蜥社群
加入微信群:添加社区助理-龙蜥社区小龙(微信:openanolis_assis),备注【龙蜥】拉你入群;加入钉钉群:扫描下方钉钉群二维码。欢迎开发者/用户加入龙蜥社区(OpenAnolis)交流,共同推进龙蜥社区的发展,一起打造一个活跃的、健康的开源操作系统生态!
Anolis 商密软件栈钉钉群 龙蜥社区公众号二维码