记录openssl asn1编解码开发遇到的内存错误问题 SIGSEGV

最初源码:


/*
 ============================================================================
 Name        : opensslproj.c
 Author      : YeQiang
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <time.h>

#define LOG printf

typedef struct X509V4_VALID_st {
	ASN1_GENERALIZEDTIME *notBefore;
	ASN1_GENERALIZEDTIME *notAfter;
} X509V4_VALID;

DECLARE_ASN1_FUNCTIONS(X509V4_VALID)

ASN1_SEQUENCE(X509V4_VALID) = {
	ASN1_SIMPLE(X509V4_VALID, notBefore, ASN1_GENERALIZEDTIME),
	ASN1_SIMPLE(X509V4_VALID, notAfter, ASN1_GENERALIZEDTIME)
}ASN1_SEQUENCE_END(X509V4_VALID)

IMPLEMENT_ASN1_FUNCTIONS(X509V4_VALID)

void util_saveToFile(const char *filepath, const char *buf, size_t len) {
	FILE *envFile;
	size_t writeBytes;
	LOG("saveing file %s(len=%d)\n", filepath, len);
	envFile = fopen(filepath, "wb");
	if (!envFile) {
		LOG("cannot open file for write:%s\n", filepath);
		return;
	}
	writeBytes = fwrite(buf, 1, len, envFile);
	LOG("writeBytes:%d\n", writeBytes);
	fclose(envFile);
}

void util_cprintHex(const char *buf, size_t len) {
	int i;
	printf("p=%x:{", buf);
	for (i = 0; i < len; i++) {
		unsigned char c = buf[i];
		printf("%2.2x ", c);
	}
	printf("}\n");
}

int main(void) {
	int len;
	time_t t;
	X509V4_VALID *v = X509V4_VALID_new();
	unsigned char *der;

	t = 1; //1970-1-1 00:00:00 + 1s
	ASN1_GENERALIZEDTIME_set(v->notBefore, t);
	t = 100;
	ASN1_GENERALIZEDTIME_set(v->notAfter, t);

	len = i2d_X509V4_VALID(v, &der);
	printf("ASN1_i2d_bio:%d\n", len);
	if (len > 0) {
		util_cprintHex(der, len);
		util_saveToFile("/tmp/a.der", der, len);
	}

	//	X509V4_VALID_free(v);//sig fail

	X509V4_VALID *v2 = 0, *vv = 0;
	vv = d2i_X509V4_VALID(&v2, &der, len);

	printf("v2=%x, vv=%x\n", v2, vv);

	//	CRYPTO_free(der);
	X509V4_VALID_free(v);
	X509V4_VALID_free(vv);
	return EXIT_SUCCESS;
}

运行结果:

[yeqiang@localhost opensslproj]$ ./src/a.out 
ASN1_i2d_bio:36
p=1334130:{30 22 18 0f 31 39 37 30 30 31 30 31 30 30 30 30 30 31 5a 18 0f 31 39 37 30 30 31 30 31 30 30 30 31 34 30 5a }
saveing file /tmp/a.der(len=36)
writeBytes:36
v2=1334160, vv=1334160

代码调整:

/*
 ============================================================================
 Name        : opensslproj.c
 Author      : YeQiang
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <time.h>

#define LOG printf

typedef struct X509V4_VALID_st {
	ASN1_GENERALIZEDTIME *notBefore;
	ASN1_GENERALIZEDTIME *notAfter;
} X509V4_VALID;

DECLARE_ASN1_FUNCTIONS(X509V4_VALID)

ASN1_SEQUENCE(X509V4_VALID) = {
	ASN1_SIMPLE(X509V4_VALID, notBefore, ASN1_GENERALIZEDTIME),
	ASN1_SIMPLE(X509V4_VALID, notAfter, ASN1_GENERALIZEDTIME)
}ASN1_SEQUENCE_END(X509V4_VALID)

IMPLEMENT_ASN1_FUNCTIONS(X509V4_VALID)

void util_saveToFile(const char *filepath, const char *buf, size_t len) {
	FILE *envFile;
	size_t writeBytes;
	LOG("saveing file %s(len=%d)\n", filepath, len);
	envFile = fopen(filepath, "wb");
	if (!envFile) {
		LOG("cannot open file for write:%s\n", filepath);
		return;
	}
	writeBytes = fwrite(buf, 1, len, envFile);
	LOG("writeBytes:%d\n", writeBytes);
	fclose(envFile);
}

void util_cprintHex(const char *buf, size_t len) {
	int i;
	printf("p=%x:{", buf);
	for (i = 0; i < len; i++) {
		unsigned char c = buf[i];
		printf("%2.2x ", c);
	}
	printf("}\n");
}

void test1() {
	int len;
	time_t t;
	X509V4_VALID *v = X509V4_VALID_new();
	unsigned char *der;

	t = 1; //1970-1-1 00:00:00 + 1s
	ASN1_GENERALIZEDTIME_set(v->notBefore, t);
	t = 100;
	ASN1_GENERALIZEDTIME_set(v->notAfter, t);

	len = i2d_X509V4_VALID(v, &der);
	printf("ASN1_i2d_bio:%d\n", len);
	if (len > 0) {
		util_cprintHex(der, len);
		util_saveToFile("/tmp/a.der", der, len);
	}

	//	X509V4_VALID_free(v);//sig fail

	X509V4_VALID *v2 = 0, *vv = 0;
	vv = d2i_X509V4_VALID(&v2, &der, len);

	printf("v2=%x, vv=%x\n", v2, vv);

	//	CRYPTO_free(der);
	X509V4_VALID_free(v);
	X509V4_VALID_free(vv);

}

int main(void) {
	test1();
	return EXIT_SUCCESS;
}

运行崩溃,gdb信息如下:

Starting program: /home/yeqiang/cppworkspace/opensslproj/src/a.out 
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.21-13.fc22.x86_64


Program received signal SIGSEGV, Segmentation fault.
ASN1_put_object (pp=pp@entry=0x7fffffffdaa8, constructed=constructed@entry=1, length=34, 
    tag=tag@entry=16, xclass=xclass@entry=0) at asn1_lib.c:210
210	        *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
(gdb) bt
#0  ASN1_put_object (pp=pp@entry=0x7fffffffdaa8, constructed=constructed@entry=1, length=34, 
    tag=tag@entry=16, xclass=xclass@entry=0) at asn1_lib.c:210
#1  0x00007ffff7ad45f5 in ASN1_item_ex_i2d (pval=pval@entry=0x7fffffffda40, 
    out=out@entry=0x7fffffffdaa8, it=it@entry=0x400da0 <X509V4_VALID_it>, tag=16, tag@entry=-1, 
    aclass=aclass@entry=0) at tasn_enc.c:232
#2  0x00007ffff7ad4847 in asn1_item_flags_i2d (flags=0, it=0x400da0 <X509V4_VALID_it>, 
    out=0x7fffffffdaa8, val=0x603010) at tasn_enc.c:118
#3  ASN1_item_i2d (val=<optimized out>, out=0x7fffffffdaa8, it=0x400da0 <X509V4_VALID_it>)
    at tasn_enc.c:90
#4  0x0000000000400a0d in i2d_X509V4_VALID (a=0x603010, out=0x7fffffffdaa8) at opensslproj.c:32
#5  0x0000000000400bb6 in test1 () at opensslproj.c:69
#6  0x0000000000400c6f in main () at opensslproj.c:90


分析tasn_enc.c:100代码:

static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
                               const ASN1_ITEM *it, int flags)
{
    if (out && !*out) {
        unsigned char *p, *buf;
        int len;
        len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
        if (len <= 0)
            return len;
        buf = OPENSSL_malloc(len);
        if (!buf)
            return -1;
        p = buf;
        ASN1_item_ex_i2d(&val, &p, it, -1, flags);
        *out = buf;
        return len;
    }

    return ASN1_item_ex_i2d(&val, out, it, -1, flags);
}

发现现有代码传入的out有合法值,而*out没有初始化,是随机值,违背了本段代码意图。因此调整代码如下:


/*
 ============================================================================
 Name        : opensslproj.c
 Author      : YeQiang
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <time.h>

#define LOG printf

typedef struct X509V4_VALID_st {
	ASN1_GENERALIZEDTIME *notBefore;
	ASN1_GENERALIZEDTIME *notAfter;
} X509V4_VALID;

DECLARE_ASN1_FUNCTIONS(X509V4_VALID)

ASN1_SEQUENCE(X509V4_VALID) = {
	ASN1_SIMPLE(X509V4_VALID, notBefore, ASN1_GENERALIZEDTIME),
	ASN1_SIMPLE(X509V4_VALID, notAfter, ASN1_GENERALIZEDTIME)
}ASN1_SEQUENCE_END(X509V4_VALID)

IMPLEMENT_ASN1_FUNCTIONS(X509V4_VALID)

void util_saveToFile(const char *filepath, const char *buf, size_t len) {
	FILE *envFile;
	size_t writeBytes;
	LOG("saveing file %s(len=%d)\n", filepath, len);
	envFile = fopen(filepath, "wb");
	if (!envFile) {
		LOG("cannot open file for write:%s\n", filepath);
		return;
	}
	writeBytes = fwrite(buf, 1, len, envFile);
	LOG("writeBytes:%d\n", writeBytes);
	fclose(envFile);
}

void util_cprintHex(const char *buf, size_t len) {
	int i;
	printf("p=%x:{", buf);
	for (i = 0; i < len; i++) {
		unsigned char c = buf[i];
		printf("%2.2x ", c);
	}
	printf("}\n");
}

void test1() {
	int len;
	time_t t;
	X509V4_VALID *v = X509V4_VALID_new();
	unsigned char *der = NULL; //必须初始化为NULL

	t = 1; //1970-1-1 00:00:00 + 1s
	ASN1_GENERALIZEDTIME_set(v->notBefore, t);
	t = 100;
	ASN1_GENERALIZEDTIME_set(v->notAfter, t);

	len = i2d_X509V4_VALID(v, &der);
	printf("ASN1_i2d_bio:%d\n", len);
	if (len > 0) {
		util_cprintHex(der, len);
		util_saveToFile("/tmp/a.der", der, len);
	}

	//	X509V4_VALID_free(v);//sig fail

	X509V4_VALID *v2 = 0, *vv = 0;
	vv = d2i_X509V4_VALID(&v2, &der, len);

	printf("v2=%x, vv=%x\n", v2, vv);

	//	CRYPTO_free(der);
	X509V4_VALID_free(v);
	X509V4_VALID_free(vv);

}

int main(void) {
	test1();
	return EXIT_SUCCESS;
}

问题解决!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值