STACK API

From OpenSSLWiki
Jump to navigationJump to search

The stack library provides a generic way to handle collections of objects in OpenSSL. A comparison function can be registered to sort the collection.

Interface is split in two headers, <openssl/stack.h> and <openssl/safestack.h>. The former declares the C functions that will execute the insert, delete, pop, push, and other operations on the stack, while the latter declares a bunch of macros to enforce some type-checking by the compiler; these macros are mostly auto-generated by mkstack.pl.

It is highly discouraged to use the C functions declared in <openssl/stack.h>. Rather, use the macros defined in <openssl/safestack.h> for OpenSSL built-in stacks, and declare your own type-checking wrappers for your custom stacks.

Basic Use[edit]

A stack type is defined with the DECLARE_STACK_OF() macro and its instances are declared with the STACK_OF() macro.

Example from <openssl/x509.h>:

/* a sequence of these are used */
typedef struct x509_attributes_st
        {
        ASN1_OBJECT *object;
        int single; /* 0 for a set, 1 for a single item (which is wrong) */
        union   {
                char            *ptr;
/* 0 */         STACK_OF(ASN1_TYPE) *set;
/* 1 */         ASN1_TYPE       *single;
                } value;
        } X509_ATTRIBUTE;

DECLARE_STACK_OF(X509_ATTRIBUTE)
DECLARE_ASN1_SET_OF(X509_ATTRIBUTE)


typedef struct X509_req_info_st
        {
        ASN1_ENCODING enc;
        ASN1_INTEGER *version;
        X509_NAME *subject;
        X509_PUBKEY *pubkey;
        /*  d=2 hl=2 l=  0 cons: cont: 00 */
        STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
        } X509_REQ_INFO;

For each kind of stack, a set of macros is available to manipulate its state and contents. Here is an example with the BIO object:

/* allocate & free */
#define sk_BIO_new(cmp)                 SKM_sk_new(BIO, (cmp))
#define sk_BIO_new_null()               SKM_sk_new_null(BIO)
#define sk_BIO_free(st)                 SKM_sk_free(BIO, (st))
#define sk_BIO_pop_free(st, free_func)  SKM_sk_pop_free(BIO, (st), (free_func))
#define sk_BIO_dup(st)                  SKM_sk_dup(BIO, st)

/* get & set */
#define sk_BIO_num(st)                  SKM_sk_num(BIO, (st))
#define sk_BIO_value(st, i)             SKM_sk_value(BIO, (st), (i))
#define sk_BIO_set(st, i, val)          SKM_sk_set(BIO, (st), (i), (val))

/* add value */
#define sk_BIO_insert(st, val, i)       SKM_sk_insert(BIO, (st), (val), (i))
#define sk_BIO_push(st, val)            SKM_sk_push(BIO, (st), (val))
#define sk_BIO_unshift(st, val)         SKM_sk_unshift(BIO, (st), (val))

/* sort & find */
#define sk_BIO_set_cmp_func(st, cmp)    SKM_sk_set_cmp_func(BIO, (st), (cmp))
#define sk_BIO_sort(st)                 SKM_sk_sort(BIO, (st))
#define sk_BIO_is_sorted(st)            SKM_sk_is_sorted(BIO, (st))
#define sk_BIO_find(st, val)            SKM_sk_find(BIO, (st), (val))
#define sk_BIO_find_ex(st, val)         SKM_sk_find_ex(BIO, (st), (val))

/* delete value */
#define sk_BIO_delete(st, i)            SKM_sk_delete(BIO, (st), (i))
#define sk_BIO_delete_ptr(st, ptr)      SKM_sk_delete_ptr(BIO, (st), (ptr))
#define sk_BIO_pop(st)                  SKM_sk_pop(BIO, (st))
#define sk_BIO_shift(st)                SKM_sk_shift(BIO, (st))
#define sk_BIO_zero(st)                 SKM_sk_zero(BIO, (st))