STACK API
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))