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

本文详细介绍了堆栈数据结构,特别是OpenSSL中的堆栈实现。堆栈是一种先进后出(LIFO)的数据结构,常用于存储和管理数据。OpenSSL的堆栈实现提供了一系列函数,如创建、复制、插入、删除、查找、排序等操作。堆栈结构包括元素数量、数据指针、排序状态和比较函数等成员。堆栈数据的插入和删除通过内存管理函数完成,如`OPENSSL_sk_insert`和`OPENSSL_sk_delete`。此外,`OPENSSL_sk_sort`用于排序堆栈,`OPENSSL_sk_find`和`OPENSSL_sk_find_ex`用于查找数据。堆栈拷贝和深拷贝分别由`OPENSSL_sk_dup`和`OPENSSL_sk_deep_copy`函数实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆栈介绍

  • 堆栈是一种先进后出的数据结构
  • 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;
}
第一章 基础知识 81.1 对称算法 81.2摘要算法 81.3 公钥算法 91.4 回调函数 11第二章 openssl简介 132.1 openssl简介 132.2 openssl安装 132.2.1 linux下的安装 132.2.2 windows编译与安装 132.3 openssl源代码 142.4 openssl学习方法 16第三章openssl堆栈 173.1 openssl堆栈 173.2 数据结构 173.3 源码 173.4 定义用户自己的堆栈函数 183.5 编程示例 19第四章 openssl哈希表 214.1 哈希表 214.2 哈希表数据结构 214.3 函数说明 224.4 编程示例 24第五章 openssl内存分配 275.1 openssl内存分配 275.2 内存数据结构 275.3 主要函数 285.4 编程示例 28第六章 Openssl动态模块加载 316.1 动态库加载 316.2 DSO概述 316.3 数据结构 316.4 编程示例 32第七章 openssl抽象IO 357.1 openssl抽象IO 357.2 数据结构 357.3 BIO 函数 367.4 编程示例 377.4.1 mem bio 377.4.2 file bio 377.4.3 socket bio 387.4.4 md BIO 407.4.5 cipher BIO 407.4.6 ssl BIO 417.4.7 其他示例 43第八章 Openssl配置文件 448.1 概述 448.2 openssl配置文件读取 448.3 主要函数 448.4 编程示例 45第九章 Openssl随机数 479.1 随机数 479.2 openssl随机数数据结构与源码 479.3 主要函数 489.4 编程示例 49第十章 Openssl文本数据库 5110.1 概述 5110.2 数据结构 5110.3 函数说明 5210.4 编程示例 52第十一章 Openssl大数 5511.1 介绍 5511.2 openssl大数表示 5511.3 大数函数 5511.4 使用示例 58第十二章 Openssl base64编解码 6512.1 BASE64编码介绍 6512.2 BASE64编解码原理 6512.3 主要函数 6612.4 编程示例 66第十三章 Openssl ASN1库 6913.1 ASN1简介 6913.2 DER编码 7013.3 ASN1基本类型示例 7113.4 openssl 的ASN.1库 7313.5 用openssl的ASN.1库DER编码 7413.6 Openssl的ASN.1宏 7513.7 ASN1常用函数 7613.8 属性证书编码 90第十四章 Openssl错误处理 9414.1 概述 9414.2 数据结构 9414.3 主要函数 9614.4 编程示例 98第十五章 Openssl摘要与HMAC 10115.1 概述 10115.2 openssl摘要实现 10115.3 函数说明 10115.4 编程示例 10215.5 HMAC 103第十六章 Openssl数据压缩 10516.1 简介 10516.2 数据结构 10516.3 函数说明 10616.4 openssl中压缩算法协商 10616.5 编程示例 107第十七章 Openssl RSA 10817.1 RSA介绍 10817.2 openssl的RSA实现 10817.3 RSA签名与验证过程 10917.4 数据结构 10917.4.1 RSA_METHOD 10917.4.2 RSA 11017.5 主要函数 11117.6编程示例 11217.6.1密钥生成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值