OpenSSL 堆栈操作及其安全堆栈实现

读openssl的源码一直可以看到DEFINE_STACK_OF这个宏,它被定义在safestack.h这个头文件中。openssl的堆栈实现共涉及到三个文件,stack.h、stack.c 和safestack.h;其中stack.h、stack.c 实现了stack_st结构体,及对该结构体对象进行操作的一系列以OPENSSL_sk开头的函数,主要有:堆栈拷贝(OPENSSL_sk_dup)、构建新堆栈(OPENSSL_sk_new_null,OPENSSL_sk_new)、插入数据(OPENSSL_sk_insert)、删除数据(OPENSSL_sk_delete)、查找数据(OPENSSL_sk_find,OPENSSL_sk_find_ex)、入栈(OPENSSL_sk_push)、出栈(OPENSSL_sk_pop)、获取堆栈元素个数(OPENSSL_sk_num)、获取堆栈值(OPENSSL_sk_value)、设置堆栈值(OPENSSL_sk_set)和堆栈排序(OPENSSL_sk_sort)。

比对openssl0.9.6版本,stack_st,被定义成STACK,

typedef struct stack_st
	{
	int num;
	char **data;
	int sorted;

	int num_alloc;
	int (*comp)(const char * const *, const char * const *);
	} STACK;

       而openssl1.1.0版本,该结构体声明在了stack.c文件中,且在stack.h中,typedef struct stack_st OPENSSL_STACK; /* Use STACK_OF(...) instead */  使得调用者对该结构体的具体成员不得操作,有点类的私有成员变量的意思在里边.

safestack.h封装的提升使得SKM_DEFINE_STACK_OF(t1, t2, t3),出现了多态的样式,只要给该宏传入类型即可用他生成一套对该数据类型操作的函数来,而其本质还是转换为对OPENSSL_STACK 类型的操作。

# define STACK_OF(type) struct stack_st_##type
# define SKM_DEFINE_STACK_OF(t1, t2, t3) \
    STACK_OF(t1); \
    typedef int (*sk_##t1##_compfunc)(const t3 * const *a, const t3 *const *b); \
    typedef void (*sk_##t1##_freefunc)(t3 *a); \
    typedef t3 * (*sk_##t1##_copyfunc)(const t3 *a); \
    static ossl_inline int sk_##t1##_num(const STACK_OF(t1) *sk) \
    { \
        return OPENSSL_sk_num((const OPENSSL_STACK *)sk); \
    } \
    static ossl_inline t2 *sk_##t1##_value(const STACK_OF(t1) *sk, int idx) \
    { \
        return (t2 *)OPENSSL_sk_value((const OPENSSL_STACK *)sk, idx); \
    } \
    static ossl_inline STACK_OF(t1) *sk_##t1##_new(sk_##t1##_compfunc compare) \
    { \
        return (STACK_OF(t1) *)OPENSSL_sk_new((OPENSSL_sk_compfunc)compare); \
    } \
    static ossl_inline STACK_OF(t1) *sk_##t1##_new_null(void) \
    { \
        return (STACK_OF(t1) *)OPENSSL_sk_new_null(); \
    } \
    static ossl_inline STACK_OF(t1) *sk_##t1##_new_reserve(sk_##t1##_compfunc compare, int n) \
    { \
        return (STACK_OF(t1) *)OPENSSL_sk_new_reserve((OPENSSL_sk_compfunc)compare, n); \
    } \
    static ossl_inline int sk_##t1##_reserve(STACK_OF(t1) *sk, int n) \
    { \
        return OPENSSL_sk_reserve((OPENSSL_STACK *)sk, n); \
    } \
    static ossl_inline void sk_##t1##_free(STACK_OF(t1) *sk) \
    { \
        OPENSSL_sk_free((OPENSSL_STACK *)sk); \
    } \
    static ossl_inline void sk_##t1##_zero(STACK_OF(t1) *sk) \
    { \
        OPENSSL_sk_zero((OPENSSL_STACK *)sk); \
    } \
    static ossl_inline t2 *sk_##t1##_delete(STACK_OF(t1) *sk, int i) \
    { \
        return (t2 *)OPENSSL_sk_delete((OPENSSL_STACK *)sk, i); \
    } \
    static ossl_inline t2 *sk_##t1##_delete_ptr(STACK_OF(t1) *sk, t2 *ptr) \
    { \
        return (t2 *)OPENSSL_sk_delete_ptr((OPENSSL_STACK *)sk, \
                                           (const void *)ptr); \
    } \
    static ossl_inline int sk_##t1##_push(STACK_OF(t1) *sk, t2 *ptr) \
    { \
        return OPENSSL_sk_push((OPENSSL_STACK *)sk, (const void *)ptr); \
    } \
    static ossl_inline int sk_##t1##_unshift(STACK_OF(t1) *sk, t2 *ptr) \
    { \
        return OPENSSL_sk_unshift((OPENSSL_STACK *)sk, (const void *)ptr); \
    } \
    static ossl_inline t2 *sk_##t1##_pop(STACK_OF(t1) *sk) \
    { \
        return (t2 *)OPENSSL_sk_pop((OPENSSL_STACK *)sk); \
    } \
    static ossl_inline t2 *sk_##t1##_shift(STACK_OF(t1) *sk) \
    { \
        return (t2 *)OPENSSL_sk_shift((OPENSSL_STACK *)sk); \
    } \
    static ossl_inline void sk_##t1##_pop_free(STACK_OF(t1) *sk, sk_##t1##_freefunc freefunc) \
    { \
        OPENSSL_sk_pop_free((OPENSSL_STACK *)sk, (OPENSSL_sk_freefunc)freefunc); \
    } \
    static ossl_inline int sk_##t1##_insert(STACK_OF(t1) *sk, t2 *ptr, int idx) \
    { \
        return OPENSSL_sk_insert((OPENSSL_STACK *)sk, (const void *)ptr, idx); \
    } \
    static ossl_inline t2 *sk_##t1##_set(STACK_OF(t1) *sk, int idx, t2 *ptr) \
    { \
        return (t2 *)OPENSSL_sk_set((OPENSSL_STACK *)sk, idx, (const void *)ptr); \
    } \
    static ossl_inline int sk_##t1##_find(STACK_OF(t1) *sk, t2 *ptr) \
    { \
        return OPENSSL_sk_find((OPENSSL_STACK *)sk, (const void *)ptr); \
    } \
    static ossl_inline int sk_##t1##_find_ex(STACK_OF(t1) *sk, t2 *ptr) \
    { \
        return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \
    } \
    static ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \
    { \
        OPENSSL_sk_sort((OPENSSL_STACK *)sk); \
    } \
    static ossl_inline int sk_##t1##_is_sorted(const STACK_OF(t1) *sk) \
    { \
        return OPENSSL_sk_is_sorted((const OPENSSL_STACK *)sk); \
    } \
    static ossl_inline STACK_OF(t1) * sk_##t1##_dup(const STACK_OF(t1) *sk) \
    { \
        return (STACK_OF(t1) *)OPENSSL_sk_dup((const OPENSSL_STACK *)sk); \
    } \
    static ossl_inline STACK_OF(t1) *sk_##t1##_deep_copy(const STACK_OF(t1) *sk, \
                                                    sk_##t1##_copyfunc copyfunc, \
                                                    sk_##t1##_freefunc freefunc) \
    { \
        return (STACK_OF(t1) *)OPENSSL_sk_deep_copy((const OPENSSL_STACK *)sk, \
                                            (OPENSSL_sk_copyfunc)copyfunc, \
                                            (OPENSSL_sk_freefunc)freefunc); \
    } \
    static ossl_inline sk_##t1##_compfunc sk_##t1##_set_cmp_func(STACK_OF(t1) *sk, sk_##t1##_compfunc compare) \
    { \
        return (sk_##t1##_compfunc)OPENSSL_sk_set_cmp_func((OPENSSL_STACK *)sk, (OPENSSL_sk_compfunc)compare); \
    }

仔细阅读你会发现,STACK_OF(type) 只有对新类型结构体的声明而没有定义,与0.9.6版本的实现不同。如下

#define STACK_OF(type) struct stack_st_##type
#define PREDECLARE_STACK_OF(type) STACK_OF(type);

#define DECLARE_STACK_OF(type) \
STACK_OF(type) \
    { \
    STACK stack; \
    };   //0.9.6   STACK_OF(type) 结构的定义

我在这块陷入了困境,而后请教前辈才渐渐悟到其中道理,此处只声明了结构体,在使用的时候,也仅只是定义了一个结构体对象的指针,也即结构体的入口地址,结构体中存储的成员,他并不直接去访问。而是通过宏里边实现的操作函数,把STACK_OF(type)转为stack_st类型,调用OPENSSL_STACK(和stack_st是一个)结构的操作函数去处理成员。STACK_OF(type)虽然没有定义成员,但它的对象有存放地址,该地址处存放的数据的类型,和stack_st成员的类型一模一样,操作的时候,只要按照stack_st的内存结构去读去写即可。

至此其他人也可以利用宏define SKM_DEFINE_STACK_OF(t1, t2, t3)定义出对t1结构对象操作的一套API出来,我简单测试如下:

#include "openssl/stack.h"
#include "openssl/X509.h"

struct TASK
{
	int ID;
	std::string name;
	std::string otherInfo;
};

DEFINE_STACK_OF(TASK)

int compareFun(const TASK * const *first, const TASK *const *second)
{
	return (*first)->ID - (*second)->ID;
}

void freeTeskFun(TASK *task)
{
	delete task;
}
void taskStackTest()
{
	STACK_OF(TASK) *mytask = sk_TASK_new(compareFun);
	TASK *t1=new TASK{1,std::string{"ssss"},std::string{"other1"}};
	sk_TASK_push(mytask, t1);
	TASK *t2 = new TASK{int(2),std::string{"two"},std::string{"twootherinfo"}};
	sk_TASK_push(mytask, t2);

	std::cout << sk_TASK_num(mytask) << std::endl;

	TASK *popDT = static_cast<TASK *>(sk_TASK_pop(mytask));
	std::cout << popDT->ID<<" "<< popDT->name << std::endl;
	delete popDT;
	//OPENSSL_STACK *ll = (OPENSSL_STACK *)mytask;
	sk_TASK_pop_free(mytask,freeTeskFun);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值