您的位置:首页 > 运维架构

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

2017-02-21 13:56 1081 查看
最初源码:

/*
============================================================================
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;
}


问题解决!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: