openssl编程-基础知识-OpenSSL堆栈

堆栈介绍

  • 堆栈是一种先进后出的数据结构
  • openssl 大量采用堆栈来存放数据。它实现了一 个通用的堆栈,可以方便的存储任意数据
  • 它实现了许多基本的堆栈操作,主要有:堆栈拷贝(sk_dup)、构建新堆栈(sk_new_null,sk_new)、插入数据(sk_insert)、删除数据(sk_delete)、查找数据(sk_find,sk_find_ex)、入栈(sk_push)、出栈(sk_pop)、获取堆栈元素个数(sk_num)、获取堆栈值(sk_value)、设置堆栈值(sk_set)和堆栈排序(sk_sort)

数据结构

  • openssl 堆栈数据结构在 stack.h 中
  • stack.h 位于 include/openssl文件夹下
  • 定义位于crypto/stack文件夹下的stack.c文件内,具体内容如下:

stack.h

/*
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#ifndef HEADER_STACK_H
# define HEADER_STACK_H

#ifdef  __cplusplus
extern "C" {
#endif

typedef struct stack_st OPENSSL_STACK; /* Use STACK_OF(...) instead */

typedef int (*OPENSSL_sk_compfunc)(const void *, const void *);
typedef void (*OPENSSL_sk_freefunc)(void *);
typedef void *(*OPENSSL_sk_copyfunc)(const void *);

int OPENSSL_sk_num(const OPENSSL_STACK *);
void *OPENSSL_sk_value(const OPENSSL_STACK *, int);

void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data);

OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc cmp);
OPENSSL_STACK *OPENSSL_sk_new_null(void);
void OPENSSL_sk_free(OPENSSL_STACK *);
void OPENSSL_sk_pop_free(OPENSSL_STACK *st, void (*func) (void *));
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *, OPENSSL_sk_copyfunc c, OPENSSL_sk_freefunc f);
int OPENSSL_sk_insert(OPENSSL_STACK *sk, const void *data, int where);
void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc);
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p);
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data);
void *OPENSSL_sk_shift(OPENSSL_STACK *st);
void *OPENSSL_sk_pop(OPENSSL_STACK *st);
void OPENSSL_sk_zero(OPENSSL_STACK *st);
OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc cmp);
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *st);
void OPENSSL_sk_sort(OPENSSL_STACK *st);
int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st);

# if OPENSSL_API_COMPAT < 0x10100000L
#  define _STACK OPENSSL_STACK
#  define sk_num OPENSSL_sk_num
#  define sk_value OPENSSL_sk_value
#  define sk_set OPENSSL_sk_set
#  define sk_new OPENSSL_sk_new
#  define sk_new_null OPENSSL_sk_new_null
#  define sk_free OPENSSL_sk_free
#  define sk_pop_free OPENSSL_sk_pop_free
#  define sk_deep_copy OPENSSL_sk_deep_copy
#  define sk_insert OPENSSL_sk_insert
#  define sk_delete OPENSSL_sk_delete
#  define sk_delete_ptr OPENSSL_sk_delete_ptr
#  define sk_find OPENSSL_sk_find
#  define sk_find_ex OPENSSL_sk_find_ex
#  define sk_push OPENSSL_sk_push
#  define sk_unshift OPENSSL_sk_unshift
#  define sk_shift OPENSSL_sk_shift
#  define sk_pop OPENSSL_sk_pop
#  define sk_zero OPENSSL_sk_zero
#  define sk_set_cmp_func OPENSSL_sk_set_cmp_func
#  define sk_dup OPENSSL_sk_dup
#  define sk_sort OPENSSL_sk_sort
#  define sk_is_sorted OPENSSL_sk_is_sorted
# endif

#ifdef  __cplusplus
}
#endif

#endif

stack.cpp

/*
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/numbers.h"
#include <openssl/stack.h>
#include <openssl/objects.h>

struct stack_st {
    int num;
    const char **data;
    int sorted;
    size_t num_alloc;
    OPENSSL_sk_compfunc comp;
};

#undef MIN_NODES
#define MIN_NODES       4

#include <errno.h>

OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
{
    OPENSSL_sk_compfunc old = sk->comp;

    if (sk->comp != c)
        sk->sorted = 0;
    sk->comp = c;

    return old;
}

OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
{
    OPENSSL_STACK *ret;

    if (sk->num < 0)
        return NULL;

    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
        return NULL;

    /* direct structure assignment */
    *ret = *sk;

    if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)
        goto err;
    memcpy(ret->data, sk->data, sizeof(char *) * sk->num);
    return ret;
 err:
    OPENSSL_sk_free(ret);
    return NULL;
}

OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
                             OPENSSL_sk_copyfunc copy_func,
                             OPENSSL_sk_freefunc free_func)
{
    OPENSSL_STACK *ret;
    int i;

    if (sk->num < 0)
        return NULL;

    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
        return NULL;

    /* direct structure assignment */
    *ret = *sk;

    ret->num_alloc = sk->num > MIN_NODES ? (size_t)sk->num : MIN_NODES;
    ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);
    if (ret->data == NULL) {
        OPENSSL_free(ret);
        return NULL;
    }

    for (i = 0; i < ret->num; ++i) {
        if (sk->data[i] == NULL)
            continue;
        if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {
            while (--i >= 0)
                if (ret->data[i] != NULL)
                    free_func((void *)ret->data[i]);
            OPENSSL_sk_free(ret);
            return NULL;
        }
    }
    return ret;
}

OPENSSL_STACK *OPENSSL_sk_new_null(void)
{
    return OPENSSL_sk_new((OPENSSL_sk_compfunc)NULL);
}

OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
{
    OPENSSL_STACK *ret;

    if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
        goto err;
    if ((ret->data = OPENSSL_zalloc(sizeof(*ret->data) * MIN_NODES)) == NULL)
        goto err;
    ret->comp = c;
    ret->num_alloc = MIN_NODES;
    return (ret);

 err:
    OPENSSL_free(ret);
    return (NULL);
}

int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc)
{
    if (st == NULL || st->num < 0 || st->num == INT_MAX) {
        return 0;
    }

    if (st->num_alloc <= (size_t)(st->num + 1)) {
        size_t doub_num_alloc = st->num_alloc * 2;
        const char **tmpdata;

        /* Overflow checks */
        if (doub_num_alloc < st->num_alloc)
            return 0;

        /* Avoid overflow due to multiplication by sizeof(char *) */
        if (doub_num_alloc > SIZE_MAX / sizeof(char *))
            return 0;

        tmpdata = OPENSSL_realloc((char *)st->data,
                                  sizeof(char *) * doub_num_alloc);
        if (tmpdata == NULL)
            return 0;

        st->data = tmpdata;
        st->num_alloc = doub_num_alloc;
    }
    if ((loc >= st->num) || (loc < 0)) {
        st->data[st->num] = data;
    } else {
        memmove(&st->data[loc + 1], &st->data[loc],
                sizeof(st->data[0]) * (st->num - loc));
        st->data[loc] = data;
    }
    st->num++;
    st->sorted = 0;
    return st->num;
}

void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p)
{
    int i;

    for (i = 0; i < st->num; i++)
        if (st->data[i] == p)
            return OPENSSL_sk_delete(st, i);
    return NULL;
}

void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
{
    const char *ret;

    if (st == NULL || loc < 0 || loc >= st->num)
        return NULL;

    ret = st->data[loc];
    if (loc != st->num - 1)
         memmove(&st->data[loc], &st->data[loc + 1],
                 sizeof(st->data[0]) * (st->num - loc - 1));
    st->num--;
    return (void *)ret;
}

static int internal_find(OPENSSL_STACK *st, const void *data,
                         int ret_val_options)
{
    const void *r;
    int i;

    if (st == NULL)
        return -1;

    if (st->comp == NULL) {
        for (i = 0; i < st->num; i++)
            if (st->data[i] == data)
                return (i);
        return (-1);
    }
    OPENSSL_sk_sort(st);
    if (data == NULL)
        return (-1);
    r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,
                        ret_val_options);
    if (r == NULL)
        return (-1);
    return (int)((const char **)r - st->data);
}

int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
{
    return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
}

int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
{
    return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
}

int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
{
    return (OPENSSL_sk_insert(st, data, st->num));
}

int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
{
    return (OPENSSL_sk_insert(st, data, 0));
}

void *OPENSSL_sk_shift(OPENSSL_STACK *st)
{
    if (st == NULL)
        return (NULL);
    if (st->num <= 0)
        return (NULL);
    return (OPENSSL_sk_delete(st, 0));
}

void *OPENSSL_sk_pop(OPENSSL_STACK *st)
{
    if (st == NULL)
        return (NULL);
    if (st->num <= 0)
        return (NULL);
    return (OPENSSL_sk_delete(st, st->num - 1));
}

void OPENSSL_sk_zero(OPENSSL_STACK *st)
{
    if (st == NULL)
        return;
    if (st->num <= 0)
        return;
    memset(st->data, 0, sizeof(*st->data) * st->num);
    st->num = 0;
}

void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
{
    int i;

    if (st == NULL)
        return;
    for (i = 0; i < st->num; i++)
        if (st->data[i] != NULL)
            func((char *)st->data[i]);
    OPENSSL_sk_free(st);
}

void OPENSSL_sk_free(OPENSSL_STACK *st)
{
    if (st == NULL)
        return;
    OPENSSL_free(st->data);
    OPENSSL_free(st);
}

int OPENSSL_sk_num(const OPENSSL_STACK *st)
{
    if (st == NULL)
        return -1;
    return st->num;
}

void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
{
    if (st == NULL || i < 0 || i >= st->num)
        return NULL;
    return (void *)st->data[i];
}

void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
{
    if (st == NULL || i < 0 || i >= st->num)
        return NULL;
    st->data[i] = data;
    return (void *)st->data[i];
}

void OPENSSL_sk_sort(OPENSSL_STACK *st)
{
    if (st && !st->sorted && st->comp != NULL) {
        qsort(st->data, st->num, sizeof(char *), st->comp);
        st->sorted = 1;
    }
}

int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
{
    if (st == NULL)
        return 1;
    return st->sorted;
}

数据结构

struct stack_st {
    int num;
    const char **data;
    int sorted;
    size_t num_alloc;
    OPENSSL_sk_compfunc comp;
};
  • 各项意义如下:
    • num: 堆栈中存放数据的个数。
    • data:  用于存放数据地址,每个数据地址存放在 data[0]到 data[num-1]中。
    • sorted: 堆栈是否已排序,如果排序则值为 1,否则为 0,堆栈数据一般是无序的,只有当用户调用了 sk_sort 操作,其值才为 1。
    • comp: 堆栈内存放数据的比较函数地址,此函数用于排序和查找操作;当用户生成一 个新堆栈时,可以指定comp为用户实现的一个比较函数;或当堆栈已经存在 时通过调用 sk_set_cmp_func 函数来重新指定比较函数。
  • 注意,用户不需要调用底层的堆栈函数(sk_sort、sk_set_cmp_func 等),而是调用他通过 宏实现的各个函数。

函数介绍

  • openssl 堆栈实现源码位于 crypto/stack 目录下。下面分析了部分函数。
  •  sk_set_cmp_func
  • 此函数用于设置堆栈存放数据的比较函数。由于堆栈不知道用户存放的是什么数据,所以,比较函数必须由用户自己实现。
OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c)
{
    OPENSSL_sk_compfunc old = sk->comp;

    if (sk->comp != c)
        sk->sorted = 0;
    sk->comp = c;

    return old;
}
  • OPENSSL_sk_dup 堆栈拷贝
  • 使用OPSNSSL_malloc进行内存的分配,其实质是调用CRYPTO_malloc进行内存的分配
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk)
{
    OPENSSL_STACK *ret;

    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
        goto err;

    if (sk == NULL) {
        ret->num = 0;
        ret->sorted = 0;
        ret->comp = NULL;
    } else {
        /* direct structure assignment */
        *ret = *sk;
    }

    if (sk == NULL || sk->num == 0) {
        /* postpone |ret->data| allocation */
        ret->data = NULL;
        ret->num_alloc = 0;
        return ret;
    }

    /* duplicate |sk->data| content */
    if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL)
        goto err;
    memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
    return ret;

 err:
    ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
    OPENSSL_sk_free(ret);
    return NULL;
}
  • C++版本 
OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk){
    OPENSSL_STACK *ret;
    if((ret = reinterpret_cast<OPENSSL_STACK *>(OPENSSL_malloc(sizeof (*ret)))) == nullptr){
        goto err;
    }
    if (sk == nullptr)
    {
        ret->num = 0;
        ret->sorted = 0;
        ret->comp = nullptr;
    } else{
        //直接结构赋值
        *ret = *sk;
    }
    if (sk == nullptr || sk->num == 0)
    {
        //推迟|ret->data|分配
        ret->data = nullptr;
        ret->num_alloc = 0;
        return ret;
    }
    // 重复|sk->data|内容
    if ((ret->data = static_cast<const void **>(OPENSSL_malloc(sizeof((*ret).data) * sk->num_alloc))) == nullptr)
        goto err;
    memcpy(ret->data,sk->data,sizeof (void*)*sk->num);
    return ret;

    err:
    ERR_raise(ERR_LIB_CRYPTO,ERR_R_MALLOC_FAILURE);
    OPENSSL_sk_free(ret);
    return nullptr;
}
# define OPENSSL_malloc(num) \
        CRYPTO_malloc(num, OPENSSL_FILE, OPENSSL_LINE)
  • *根据配置制作我们自己的__FILE__和__LINE__变体
/*
 * Make our own variants of __FILE__ and __LINE__, depending on configuration
 */

# ifndef OPENSSL_FILE
#  ifdef OPENSSL_NO_FILENAMES
#   define OPENSSL_FILE ""
#   define OPENSSL_LINE 0
#  else
#   define OPENSSL_FILE __FILE__
#   define OPENSSL_LINE __LINE__
#  endif
# endif
  •  CRYPTO_malloc
  • # define INCREMENT(x) /* empty */
void *CRYPTO_malloc(size_t num, const char *file, int line)
{
    INCREMENT(malloc_count);
    if (malloc_impl != CRYPTO_malloc)
        return malloc_impl(num, file, line);

    if (num == 0)
        return NULL;

    FAILTEST();
    if (allow_customize) {
        /*
         * Disallow customization after the first allocation. We only set this
         * if necessary to avoid a store to the same cache line on every
         * allocation.
         */
        allow_customize = 0;
    }

    return malloc(num);
}
  • malloc_count 全局静态变量,在openssl里面出现了三次
  • 定义位于 mem.c 文件中 

  •  只要设置了“allow_customize”,就可以更改以下指针
/*
 * the following pointers may be changed as long as 'allow_customize' is set
 */

static CRYPTO_malloc_fn malloc_impl = CRYPTO_malloc;
  •  INCREMENT  和  FAILTEST
# define FAILTEST() if (shouldfail()) return NULL

#else

# define INCREMENT(x) /* empty */
# define FAILTEST() /* empty */
#endif
  • *allow_customize  禁止在第一次分配后进行自定义。我们仅在必要时设置此值,以避免在每次分配时将存储存储到相同的缓存行。 

 

OPENSSL_sk_deep_copy  深拷贝

OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
                             OPENSSL_sk_copyfunc copy_func,
                             OPENSSL_sk_freefunc free_func)
{
    OPENSSL_STACK *ret;
    int i;

    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
        goto err;

    if (sk == NULL) {
        ret->num = 0;
        ret->sorted = 0;
        ret->comp = NULL;
    } else {
        /* direct structure assignment */
        *ret = *sk;
    }

    if (sk == NULL || sk->num == 0) {
        /* postpone |ret| data allocation */
        ret->data = NULL;
        ret->num_alloc = 0;
        return ret;
    }

    ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;
    ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc);
    if (ret->data == NULL)
        goto err;

    for (i = 0; i < ret->num; ++i) {
        if (sk->data[i] == NULL)
            continue;
        if ((ret->data[i] = copy_func(sk->data[i])) == NULL) {
            while (--i >= 0)
                if (ret->data[i] != NULL)
                    free_func((void *)ret->data[i]);
            goto err;
        }
    }
    return ret;

 err:
    ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
    OPENSSL_sk_free(ret);
    return NULL;
}
OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk,
                                    OPENSSL_sk_copyfunc copy_func,
                                    OPENSSL_sk_freefunc free_func)
{
    OPENSSL_STACK *ret;
    int j;
    if ((ret = reinterpret_cast<OPENSSL_STACK *>(OPENSSL_malloc(sizeof (*ret))))== nullptr)
        goto err;
    if (sk == nullptr)
    {
        ret->num = 0;
        ret->sorted = 0;
        ret->comp = nullptr;
    } else{
        //直接结构赋值
        *ret = *sk;
    }
    if (sk == nullptr || sk->num == 0)
    {
        //推迟|ret->data|分配
        ret->data = nullptr;
        ret->num_alloc = 0;
        return ret;
    }
    ret->num_alloc = sk->num > min_nodes ? sk->num : min_nodes;
    ret->data = static_cast<const void **>(OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc));
    if (ret->data == nullptr)
        goto err;
    for (j = 0; j < ret->num; ++j) {
        if (sk->data[j] == nullptr)
            continue;
        if ((ret->data[j] = copy_func(sk->data[j]))== nullptr){
            while (--j >= 0)
                if (ret->data[j]!= nullptr)
                    free_func((void *)ret->data[j]);
            goto err;
        }
    }
    return ret;

    err:
    ERR_raise(ERR_LIB_CRYPTO,ERR_R_MALLOC_FAILURE);
    OPENSSL_sk_free(ret);
    return nullptr;
}
# define OPENSSL_zalloc(num) \
        CRYPTO_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
  •  CRYPTO_zalloc 内存分配,内部调用 CRYPTO_malloc
void *CRYPTO_zalloc(size_t num, const char *file, int line)
{
    void *ret;

    ret = CRYPTO_malloc(num, file, line);
    FAILTEST();
    if (ret != NULL)
        memset(ret, 0, num);

    return ret;
}
typedef void *(*OPENSSL_sk_copyfunc)(const void *);
typedef void (*OPENSSL_sk_freefunc)(void *);
/* Main error raising functions */
# define ERR_raise(lib, reason) ERR_raise_data((lib),(reason),NULL)
# define ERR_raise_data                                         \
    (ERR_new(),                                                 \
     ERR_set_debug(OPENSSL_FILE,OPENSSL_LINE,OPENSSL_FUNC),     \
     ERR_set_error)
void ERR_new(void)
{
    c_new_error(NULL);
}

void ERR_set_debug(const char *file, int line, const char *func)
{
    c_set_error_debug(NULL, file, line, func);
}

void ERR_set_error(int lib, int reason, const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    c_vset_error(NULL, ERR_PACK(lib, 0, reason), fmt, args);
    va_end(args);
}
void OPENSSL_sk_free(OPENSSL_STACK *st)
{
    if (st == NULL)
        return;
    OPENSSL_free(st->data);
    OPENSSL_free(st);
}

 OPENSSL_sk_new_reserve

OPENSSL_STACK *OPENSSL_sk_new_null(void)
{
    return OPENSSL_sk_new_reserve(NULL, 0);
}

  OPENSSL_sk_new

OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c)
{
    return OPENSSL_sk_new_reserve(c, 0);
}

 OPENSSL_sk_new_reserve

OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n)
{
    OPENSSL_STACK *st = reinterpret_cast<OPENSSL_STACK *>(OPENSSL_zalloc(sizeof(OPENSSL_STACK)));

    if (st == NULL)
        return NULL;

    st->comp = c;

    if (n <= 0)
        return st;

    if (!sk_reserve(st, n, 1)) {
        OPENSSL_sk_free(st);
        return NULL;
    }

    return st;
}

 sk_reserve

/* internal STACK storage allocation */
static int sk_reserve(OPENSSL_STACK *st, int n, int exact)
{
    const void **tmpdata;
    int num_alloc;
    //检查预订是否超过硬限制
    if (n > max_nodes - st->num){
        return 0;
    }
    //指出新的大小
    num_alloc = st->num + n;
    if (num_alloc < min_nodes)
    {
        num_alloc = min_nodes;
    }
    //如果 |st->data| 分配被推迟
    if (st->data == nullptr){
        //此时,|st->num_alloc| 和 |st->num| 是 0
        //所以 |num_alloc| 值为 |n| 或 |min_nodes| 如果大于 |n|
        if((st->data = static_cast<const void **>(OPENSSL_zalloc(sizeof (void *)*num_alloc)))== nullptr)
        {
            ERR_raise(ERR_LIB_CRYPTO,ERR_R_MALLOC_FAILURE);
            return 0;
        }
        st->num_alloc = num_alloc;
        return 1;
    }
    if (!exact){
        if (num_alloc <= st->num_alloc)
            return 1;
        num_alloc = compute_growth(num_alloc,st->num_alloc);
        if (num_alloc == 0)
            return 0;
    } else if (num_alloc == st->num_alloc){
        return 1;
    }
    tmpdata = static_cast<const void **>(OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc));
    if (tmpdata == NULL)
        return 0;

    st->data = tmpdata;
    st->num_alloc = num_alloc;
    return 1;
}

compute_growth 

/*
  * 根据目标大小计算数组增长。
  *
  * 增长分数是有理数,由分子和分母定义。 根据 Andrew Koenig 在他的论文“为什么向量是有效的?”中的说法。 从 JOOP 11(5) 1998 开始,这个因子应该小于黄金比例 (1.618...)。
  *
  * 我们使用 3/2 = 1.5 来简化计算和溢出检查。另一个选项 8/5 = 1.6 允许稍微更快的增长,尽管安全计算更加困难。
  *
  * 避免溢出的限制是正确的。 模三校正项确保限制是在不超过硬限制的情况下可以通过增长因子扩展的最大数。
  *
  * 不要用 |current| 调用它 小于2,否则会无限循环。
  */
static ossl_inline int compute_growth(int target,int current){
    const int limit = (max_nodes / 3)*2 + (max_nodes % 3 ? 1: 0);
    while(current < target){
        //检查我们是否处于硬限制
        if (current >= max_nodes)
            return 0;
        //如果在范围内,则将大小扩大 3/2 倍
        current = current < limit ? current + current / 2 : max_nodes;
    }
    return current;
}

OPENSSL_sk_reserve

int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n)
{
    if (st == NULL)
        return 0;

    if (n < 0)
        return 1;
    return sk_reserve(st, n, 1);
}

OPENSSL_sk_insert 

int OPENSSL_sk_insert(OPENSSL_STACK *st,const void *data,int loc)
{
    if (st == nullptr || st->num == max_nodes){
        return 0;
    }
    if (!sk_reserve(st,1,0))
        return 0;
    if ((loc >= st->num) || (loc < 0)){
        st->data[st->num] = data;
    } else{
        memmove(&st->data[loc+1],&st->data[loc],
                sizeof(st->data[0]) * (st->num - loc));
        st->data[loc] = data;
    }
    st->num++;
    st->sorted = 0;
    return st->num;
}

internal_delete 

static ossl_inline void * internal_delete(OPENSSL_STACK *st,int loc){
    const void *ret = st->data[loc];
    if (loc != st->num-1){
        memmove(&st->data[loc],&st->data[loc+1],
                sizeof (st->data[0]) * (st->num - loc -1));
    }
    st->num--;
    return (void*)ret;
}

 OPENSSL_sk_delete_ptr

void* OPENSSL_sk_delete_ptr(OPENSSL_STACK *st,const void *p){
    for (int j = 0; j < st->num; ++j) {
        if (st->data[j]==p)
            return internal_delete(st,j);
    }
    return nullptr;
}

OPENSSL_sk_delete 

void *OPENSSL_sk_delete(OPENSSL_STACK *st,int loc)
{
    if (st == nullptr || loc < 0 || loc >= st->num){
        return nullptr;
    }
    return internal_delete(st,loc);
}

 internal_find

  • 根据数据地址来查找它在堆栈中的位置。当堆栈设置了比较函数时,它首先对堆栈进行排序,然后通过二分法进行查找。
  • 如果堆栈没有设置比较函数,它只是简单的比较数据地址来查找
static int internal_find(OPENSSL_STACK *st,const void *data,
                         int ret_val_options,int *pnum)
{
    const void *r = nullptr;
    if (st == nullptr || st->num == 0){
        return -1;
    }
    //未排序 采用循环遍历的方式进行查找
    if (st->comp == nullptr){
        for (int i = 0; i < st->num; ++i) {
            if (st->data[i] == data){
                if (pnum != nullptr)
                    *pnum = 1;
                return i;
            }
            if (pnum != nullptr){
                *pnum = 0;
            }
            return -1;
        }
    }
    //根据comp比较函数进行快速排序
    if (!st->sorted){
        if (st->num > 1)
            qsort(st->data,st->num,sizeof (void*),st->comp);
        st->sorted = 1; //空或单元素堆栈被视为已排序
    }
    if (data == nullptr)
        return -1;
    if (pnum != nullptr)
        ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
    r = ossl_bsearch(&data,st->data,st->num,sizeof(void*),
                     st->comp,ret_val_options);
    if (pnum != nullptr){
        *pnum = 0;
        if (r != nullptr){
            const void **p = (const void **)r;
            while (p < st->data + st->num){
                if (st->comp(&data,p) != 0)
                    break;
                ++*pnum;
                ++p;
            }
        }
    }
    return r == nullptr ? -1 : (int)((const void **)r - st->data);
}

 ossl_bsearch

#include <stddef.h>
#include "internal/cryptlib.h"

const void *ossl_bsearch(const void *key, const void *base, int num,
                         int size, int (*cmp) (const void *, const void *),
                         int flags)
{
    const char *base_ = base;
    int l, h, i = 0, c = 0;
    const char *p = NULL;

    if (num == 0)
        return NULL;
    l = 0;
    h = num;
    while (l < h) {
        i = (l + h) / 2;
        p = &(base_[i * size]);
        c = (*cmp) (key, p);
        if (c < 0)
            h = i;
        else if (c > 0)
            l = i + 1;
        else
            break;
    }
    if (c != 0 && !(flags & OSSL_BSEARCH_VALUE_ON_NOMATCH))
        p = NULL;
    else if (c == 0 && (flags & OSSL_BSEARCH_FIRST_VALUE_ON_MATCH)) {
        while (i > 0 && (*cmp) (key, &(base_[(i - 1) * size])) == 0)
            i--;
        p = &(base_[i * size]);
    }
    return p;
}
/* Function for simple binary search */

/* Flags */
# define OSSL_BSEARCH_VALUE_ON_NOMATCH            0x01
# define OSSL_BSEARCH_FIRST_VALUE_ON_MATCH        0x02

 OPENSSL_sk_find

int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
{
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
}

OPENSSL_sk_find_ex

int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
{
    return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
}

OPENSSL_sk_find_all 

int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum)
{
    return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
}

OPENSSL_sk_push 

int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
{
    if (st == NULL)
        return -1;
    return OPENSSL_sk_insert(st, data, st->num);
}

OPENSSL_sk_unshift 

int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data)
{
    return OPENSSL_sk_insert(st, data, 0);
}

OPENSSL_sk_shift 

void *OPENSSL_sk_shift(OPENSSL_STACK *st)
{
    if (st == NULL || st->num == 0)
        return NULL;
    return internal_delete(st, 0);
}

OPENSSL_sk_pop 

void *OPENSSL_sk_pop(OPENSSL_STACK *st)
{
    if (st == NULL || st->num == 0)
        return NULL;
    return internal_delete(st, st->num - 1);
}

OPENSSL_sk_zero 

void OPENSSL_sk_zero(OPENSSL_STACK *st)
{
    if (st == NULL || st->num == 0)
        return;
    memset(st->data, 0, sizeof(*st->data) * st->num);
    st->num = 0;
}

 OPENSSL_sk_pop_free

  • 释放data和结构体 
void OPENSSL_sk_pop_free(OPENSSL_STACK *st, OPENSSL_sk_freefunc func)
{
    int i;

    if (st == NULL)
        return;
    for (i = 0; i < st->num; i++)
        if (st->data[i] != NULL)
            func((char *)st->data[i]);
    OPENSSL_sk_free(st);
}

OPENSSL_sk_free 

void OPENSSL_sk_free(OPENSSL_STACK *st)
{
    if (st == NULL)
        return;
    OPENSSL_free(st->data);
    OPENSSL_free(st);
}

OPENSSL_sk_num 

int OPENSSL_sk_num(const OPENSSL_STACK *st)
{
    return st == NULL ? -1 : st->num;
}

OPENSSL_sk_value 

void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i)
{
    if (st == NULL || i < 0 || i >= st->num)
        return NULL;
    return (void *)st->data[i];
}

OPENSSL_sk_set 

void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data)
{
    if (st == NULL || i < 0 || i >= st->num)
        return NULL;
    st->data[i] = data;
    st->sorted = 0;
    return (void *)st->data[i];
}

OPENSSL_sk_sort 

  • 本函数对堆栈数据排序。它首先根据sorted来判断是否已经排序,如果未排序 则调用了标准C 函数qsort 进行快速排序。
void OPENSSL_sk_sort(OPENSSL_STACK *st)
{
    if (st != NULL && !st->sorted && st->comp != NULL) {
        if (st->num > 1)
            qsort(st->data, st->num, sizeof(void *), st->comp);
        st->sorted = 1; /* empty or single-element stack is considered sorted */
    }
}

OPENSSL_sk_is_sorted 

int OPENSSL_sk_is_sorted(const OPENSSL_STACK *st)
{
    return st == NULL ? 1 : st->sorted;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenSSL编程是一种基于开源的密码学库的编程,为了便于开发者理解和使用OpenSSL,官方提供了一份源码分析的.chm文档。 首先,OpenSSL是一个功能强大的密码学库,提供了各种密码学算法的实现,如对称加密算法(如AES)、非对称加密算法(如RSA)、哈希算法(如MD5)、数字签名等。通过使用OpenSSL库,开发者可以在自己的应用程序中轻松地实现安全性和保密性。 然而,OpenSSL庞大的代码库对于新手来说可能是一个挑战。为了帮助开发者更好地理解OpenSSL的功能和代码结构,官方提供了一份源码分析的.chm文档。 该文档包含了OpenSSL库的最新源代码的详细分析和说明。通过阅读文档,开发者可以逐步了解库的结构和主要功能模块,如SSL/TLS协议库、公钥加密算法库、哈希算法库等。文档还提供了对每个函数的详细解释和用法示例,以及示例代码,帮助开发者更好地理解和应用OpenSSL。 源码分析的.chm文档可以被阅读器打开,并提供了方便的导航和搜索功能。通过使用该文档,开发者可以更高效地学习和使用OpenSSL编程,快速解决问题和实现自己的密码学需求。 总结来说,OpenSSL编程是一种使用开源密码学库的编程技术,官方提供了源码分析的.chm文档,帮助开发者理解和使用OpenSSL库的功能和代码结构。通过阅读该文档,开发者可以更好地掌握OpenSSL编程,并应用于实际的安全性和保密性需求中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值