openssl的源代码中有一个我自认为的bug,可能作者有意这么做,然而我却认为它是bug,起码我在验证证书序列号的号的时候,它出了问题。问题是这样的:用以下命令
openssl x509 -in somecert -serial -noout
可以输出一个证书的序列号,然而当该证书的序列号的第一个字节与数字0x80按位与之后的结果非0的话,那么就会将该数作为负数来对待,如果不信的话,那么你挑选几个序列号的第一个字节和0x80按位与非0的证书来用x509验证试一下,肯定会出现一个负数的序列号,这个错误相对不好重现,因为0x80只有一个位是1。
首先说一下openssl中的d2i和i2d操作,所谓的d就是der,所谓的i就是internal,d2i就是将证书的序列化格式化为内部的c语言数据结构格式,反过来亦然,这个看来令人不知所云的东西看起来是如此的简单,这正归功于asn结构的简洁(虽然它有很长的规范文档,我可没工夫看)。asn的结构基本就是(类型,长度,值)的三元组(我记得曾经在长春的一家公司搞过snmp,然后因为不愿加班离职了),而且是一个递归的嵌套结构,所谓的i2d其实并不需要什么内部运算,只需要将数据按照事先规定好的类型,长度,规则好就是了,d所表达的归根结底是一个字符串,这个字符串通过i结构体的类型长度进行规划,同时根据asn结构的内部含义进行分割,最终的d的形式就是一个char数组,这里面最根本的就是asn结构,另外具有语义意义的是i的结构体。首先看一下openssl中的普遍的结构ASN1_STRING,别的不管,asn-interger就是这个结构定义的:
typedef struct asn1_string_st {
int length;
int type;
unsigned char *data;
long flags;
} ASN1_STRING;
但是再看看c2i_ASN1_INTEGER这个函数:
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len)
{
ASN1_INTEGER *ret=NULL;
const unsigned char *p, *pend;
unsigned char *to,*s;
int i;
if ((a == NULL) || ((*a) == NULL)) {
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
ret->type=V_ASN1_INTEGER;
} else
ret=(*a);
p= *pp;
pend = p + len;
s=(unsigned char *)OPENSSL_malloc((int)len+1);
to=s;
if(!len) {
ret->type=V_ASN1_INTEGER;
} else if (*p & 0x80) {
ret->type=V_ASN1_NEG_INTEGER;
...
} else {
...
}
...
err:
...
return(NULL);
}
由于asn完全不依赖外部结构,因此哪怕一个数据结构的类型都是由asn-interger定义的,如果一个证书的serial是由一个asn-interger表示的话,那么这个asn-interger的type也是一个asn-interger(一切都是递归的),于是看看上面的代码,else if (*p & 0x80)这一句,如果一个*p和0x80按位与不为0的话,那么该数就会被认为是负数,这是不应该的啊,事实是,只有一个asn-interger的type字段和0x80按位与不为0才能被认为是负数,于是这段代码是一段很可悲的代码,我的改进如下:
1.添加一个first_malloc变量,只有在一个变量被malloc的时候才置1,而只有在first_malloc置1的时候才验证*p和0x80按位与的情况;2.将ret->type=V_ASN1_INTEGER这个设置放到函数的最后,然后只有在ret->type为0的情况下才验证*p其与0x80按位与的值,这个策略也正和acl的策略一致,可以完全解除这个可悲的局面。
分享到:
相关推荐
openssl-1.1.1-stable-SNAP-20190915
openssl-devel-1.1.1o-1.el7.x86_64 openssl-devel openssl openssl rpm包
openssl10
arm 架构的 openssl10
openssl-devel-1.0.1e-57.el6.x86_64.rpm离线安装时的相关依赖库: openssl-devel-packages\e2fsprogs-1.41.12-22.el6.x86_64.rpm openssl-devel-packages\e2fsprogs-libs-1.41.12-22.el6.x86_64.rpm openssl-...
最近放开了https服务,安全组扫描出新的漏洞,现对原OpenSSL 1.0.1g版本升级到OpenSSL 1.1.0k,同时重新编译OpenSSH及nginx,在此提供升级脚本,仅供参考
win64 位系统用的!!! OpenSSL 1.1.1.u 安装包,官网下载好的。2023年5月最新编译的哦!
文章《将 Rust 程序编译为 WebAssembly》可能用到的资源:Win64OpenSSL-3_1_0.exe
openssl-1.1.1k-1.el7.x86_64
前端开源库-openssl-self-signed-certificateOpenSSL自签名证书,用于开发的自签名证书,使用OpenSSL生成。有效期至4754年(4754-06-06)。
1.离线安装gcc pcre-devel openssl-devel zlib-devel 下载路径 http://mirrors.163.com/centos/7.4.1708/os/x86_64/Packages/ autogen-libopts-5.18-5.el7.x86_64.rpm cpp-4.8.5-16.el7.x86_64.rpm gcc-4.8.5-16....
Win64OpenSSL-3_2_1
openssl rpm包 openssl-1.1.1o-1.el7.x86_64.rpm openssl-1.1.1o openssl
OpenSSL_1_1_1-stable静态库,OpenSSL_1_1_1-stable,留着备份一哈
Win64OpenSSL-3_1_1.msi,从http://slproweb.com/products/Win32OpenSSL.html下载的openssl windows64位版本
210-openssl-1.1.x-compat.patch
文件为 openssl-1.1.1-stable-SNAP-20200323.tar.gz
openssl-1.0.1u-1 el6
openssl-otc-pol-devel-0.9.8h-1.1.i586.rpm
官方离线安装包,测试可用。请使用rpm -ivh [rpm完整包名] 进行安装