国密SM2算法陷入安全危机? 假!SM2仍然安全

  • 作者|密码应用研究团队:薛伟佳、王聪丽、王靖然
  • 来源|翼安研习社
  • 发布时间|2021-09-08

事件回顾

2021年8月24日,开源社区OpenSSL发布了OpenSSL 1.1.1l。

发布的这个版本,主要是为了修复一个“缓冲区溢出”漏洞——CVE-2021-3711。

而这个漏洞,可以被攻击者用来更改应用程序的行为,或使应用程序崩溃,导致应用程序拒绝服务或敏感信息泄露。

有人认为,OpenSSL这个漏洞的产生,与国密SM2密文解密有关。

于是,很多非专业人员就在担心:国密SM2是不是不安全?!

在这里插入图片描述

Copyright@王山山

我们认为,这个漏洞其实与SM2密码算法无关,国密SM2算法本身还是安全的。

理由?下面请听我们一一道来。

首先,先了解下这漏洞的发布,会产生什么影响?

我们知道,开源社区OpenSSL,是实现了SSL、TLS协议的开源工具集,同时也是一个通用的密码学库,实现了目前常用的密码算法。

我们经常使用的互联网应用,如网银、在线支付、电商网站、门户网站、电子邮件等,正是广泛使用OpenSSL,来实现数据的安全传输和安全存储。

在这里插入图片描述

因此,该漏洞的发布,将影响OpenSSL 1.1.1l之前的、所有包含SM2商密算法的版本。

并且,业界一些基于OpenSSL改造过的商用国密算法版本,也可能受该漏洞影响。

到底,这个漏洞,是怎么产生的呢?

在这里插入图片描述

Copyright@帝王神殿

根据我们的判断,这个漏洞的产生,是因为在解密SM2公钥加密后的数据时,有可能分配了一个过小的内存。而由于解密后的明文长度,其实大于该内存,所以造成“内存越界”。

换一种通俗点的表达就是,这个漏洞的问题,就在于用一个小杯子去接水,水太多(大于该内存),满溢出来了(内存越界)。

在这里插入图片描述

Copyright@郑插插


漏洞分析

下面,是我们从技术上分析漏洞的推理过程:

OpenSSL密文的解密,一般需要调用两次这个函数:EVP_PKEY_decrypt()

该函数定义是这样的:
在这里插入图片描述

第一次调用,“out”参数传NULL。在函数返回时,“outlen”参数会返回“out”所需的缓冲区大小,并分配一块相应大小的堆内存。

第二次调用,“out”为第一次调用所分配的内存,运算结束后存放解密结果。

在初始化EVP_PKEY_CTX结构后,通过EVP_PKEY_decrypt()可以调用到具体的密码算法执行解密运算。

这里调用的SM2解密函数是pkey_sm2_decrypt(),函数实现如下:

在这里插入图片描述

问题出在哪里呢?

在这里插入图片描述

Copyright@我是小居居

问题就出在sm2_plaintext_size()函数里。

sm2_plaintext_size()函数返回outlen,作为接下来分配堆内存的大小。

查看sm2_plaintext_size()函数可知,返回的长度等于msg_len – overhead

overhead:整个加密后的数据中,不含密文后的长度

overhead = 10 + 2 * field_size + (size_t)md_size

field_size = ec_field_size(EC_KEY_get0_group(key)),对于SM2算法,field_size=32

md_size = EVP_MD_size(digest),SM2密文计算过程中选取的哈希算法是SM3算法,因此md_size=32

由此可知,sm2_plaintext_size函数中的overhead取值等于106(10+2*32+32)

msg_len:整个加密后的数据长度,加密后的数据格式参见GB/T 35276-2017的7.2节“加密数据格式”:

在这里插入图片描述

这里,XCoordinateYCoordinate是加密过程基于随机数计算出的椭圆曲线点的X坐标和Y坐标(对应到上面的field_size)。

所以关键问题来了:在实际加密过程中,椭圆曲线上点的表示可能占31字节,若overhead仍取106,会导致分配内存不足,内存越界写。

在这里插入图片描述

Copyright@浙江众漫文化传媒

这个漏洞看起来很深奥,其实简单点理解就是:

如同有一个容量是300mL的瓶子,里面装的水不知有多少量,如果你另外用一个200mL的杯子去接水,杯子有可能装得下(没事),也可能装不下(满溢)。装不下,不是因为水的质量产生变化,只是接水的杯子容量选错了(如果拿300mL的杯子去接,就肯定不会满溢了)。

这里的水,指的就是经国密SM2解密后的明文。算法解密后的明文(水)本身没问题,问题在于选用的杯子(分配的内存)太小了。


漏洞反思

最后,反思这个漏洞,我们可以得到以下启示:

1、这个漏洞是软件实现的问题,并非SM2密码算法本身的安全性问题。

中国商用密码标准——以我国自主设计研制的祖冲之(ZUC)算法(序列密码算法)、SM2(数字签名算法)、SM3(杂凑密码算法)、SM4(分组密码算法)、SM9(数字签名算法、标识加密算法、密钥协商协议[推进中])等为代表,已陆续纳入国际标准,这足以证明国产密码算法的安全性,可以放心使用,算法本身没问题,但也要给予正确实现(选好“杯子”),否则照样会有类似的漏洞爆出。

2、在开发环节引入代码安全审计,实现安全的前置。

开发人员在代码开发过程中要有安全意识,代码编写要规范,要注意类似内存越界、缓冲区溢出等常见的安全问题和漏洞,安全人员也要提前介入,嵌入到整个开发环节,与开发、测试人员等增强沟通,代码的安全审计要嵌入到整个开发流程中。

3、开源库的使用,应关注相关漏洞报告,并及时更新修复。

使用开源库时,尽可能选择成熟稳定的开源项目,并在漏洞修复后及时进行版本更新。为开源社区贡献代码、帮助改进开源产品,也将是对自身能力的很好提升。

参考文献:

  1. https://www.openssl.org/news/secadv/20210824.txt
  2. https://mp.weixin.qq.com/s/P2aduaUS3s8K7I-cDVJNgA
  3. https://blog.csdn.net/oyt123/article/details/119957176
  4. GB/T35276-2017《信息安全技术 SM2密码算法使用规范》

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/YiAnSociety/article/details/120220543