diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/internal/man3/ossl_ht_new.pod | 374 | ||||
-rw-r--r-- | doc/man3/CRYPTO_THREAD_run_once.pod | 4 | ||||
-rw-r--r-- | doc/man3/OPENSSL_malloc.pod | 27 |
3 files changed, 400 insertions, 5 deletions
diff --git a/doc/internal/man3/ossl_ht_new.pod b/doc/internal/man3/ossl_ht_new.pod new file mode 100644 index 0000000000..f90ecc2258 --- /dev/null +++ b/doc/internal/man3/ossl_ht_new.pod @@ -0,0 +1,374 @@ +=pod + +=head1 NAME + +ossl_ht_new, ossl_ht_free, +ossl_ht_read_lock, ossl_ht_read_unlock, +ossl_ht_write_lock, ossl_ht_write_unlock, +ossl_ht_flush, ossl_ht_insert, +ossl_ht_delete, ossl_ht_count, +ossl_ht_foreach_until, ossl_ht_filter, +ossl_ht_value_list_free, ossl_ht_get, +ossl_ht_put, HT_START_KEY_DEFN, +HT_END_KEY_DEFN, HT_DEF_KEY_FIELD_CHAR_ARRAY, +HT_DEF_KEY_FIELD_UINT8T_ARRAY, HT_DEF_KEY_FIELD, +HT_INIT_KEY, HT_KEY_RESET, HT_SET_KEY_FIELD, +HT_SET_KEY_STRING, HT_SET_KEY_BLOB, +TO_HT_KEY, FROM_HT_KEY, +IMPLEMENT_HT_VALUE_TYPE_FNS +- internal rcu locked hashtables + +=head1 SYNOPSIS + + HT *ossl_ht_new(HT_CONFIG *conf); + void ossl_ht_free(HT *htable); + void ossl_ht_read_lock(HT *htable); + void ossl_ht_read_unlock(HT *htable); + void ossl_ht_write_lock(HT *htable); + void ossl_ht_write_unlock(HT *htable); + int ossl_ht_flush(HT *htable); + int ossl_ht_insert(HT *htable, HT_KEY *key, HT_VALUE *data, HT_VALUE **olddata); + int ossl_ht_delete(HT *htable, HT_KEY *key); + size_t ossl_ht_count(HT *htable); + void ossl_ht_foreach_until(HT *htable, int (*cb)(HT_VALUE *obj, void *arg), void *arg); + HT_VALUE_LIST *ossl_ht_filter(HT *htable, size_t max_len, int (*filter)(HT_VALUE *obj)); + void ossl_ht_value_list_free(HT_VALUE_LIST *list); + HT_VALUE *ossl_ht_get(HT *htable, HT_KEY *key); + void ossl_ht_put(HT_VALUE *value); + HT_START_KEY_DEFN(keyname); + HT_END_KEY_DEFN(keyname); + HT_DEF_KEY_FIELD(name, type); + HT_DEF_KEY_FIELD_CHAR_ARRAY(name, size); + HT_DEF_KEY_FIELD_UINT8T_ARRAY(name, size); + HT_INIT_KEY(key); + HT_KEY_RESET(key); + HT_SET_KEY_FIELD(key, member, value); + HT_SET_KEY_STRING(key, member, value); + HT_SET_KEY_BLOB(key, member, value, len); + TO_HT_KEY(key); + FROM_HT_KEY(key, type); + IMPLEMENT_HT_VALUE_TYPE_FNS(vtype, name, pfx); + +=head1 DESCRIPTION + +This API provides a library-internal implementation of a hashtable that provides +reference counted object retrieval under the protection of an rcu lock. API +type safety is offered via conversion macros to and from the generic HT_VALUE +type. + +=over 2 + +=item * + +ossl_ht_new() returns a new HT (hashtable object) used to store data +elements based on a defined key. The call accepts an HT_CONFIG pointer which +contains configurations options for hashtable. Current config options consist +of: + I<ht_free_fn> The function to call to free a value, may be B<NULL>. + I<ht_hash_fn> The function to generate a hash value for a key, may be B<NULL>. + I<init_neighborhood_len> The initial number of neighborhoods in the hash table. + +Note that init_bucket_len may be set to zero, which will use the default initial +bucket size, which will be automatically expanded with the hash table load +average reaches 0.75. + +Note that lockless_read operation implies behavioral restrictions. Specifically + Only element additions are allowed, deletion operations will fail + Hash table growth is inhibited. init_bucket_len should be set to an + appropriate value to prevent performance degradation + The table owner is responsible for ensuring there are no readers during a + freeing of the table. + +Note that lockless_write operations are done at your own risk. Lockless + operation in a multithreaded environment will cause data corruption. It + is the callers responsibility in this mode of operation to provide thread + synchronization. + +=item * + +ossl_ht_free() frees an allocated hash table. Each element in the table +will have its reference count dropped, and, if said count reaches zero, the hash +tables registered free function will be called to release the element data. + +=item * + +ossl_ht_read_lock(), ossl_ht_read_unlock(), ossl_ht_write_lock() and +ossl_ht_write_unlock() lock the table for reading and writing/modification. +These function are not required for use in the event a table is to be used in a +lockless fashion, but if they are not used, it is the responsibility of the caller +to ensure thread synchronization. Note that an rcu lock is used internally for these +operations, so for table modifying actions (ossl_ht_flush() and ossl_ht_delete() +the write lock must be taken and released to ensure rcu synchronization takes +place. + +=item * + +ossl_ht_flush() empties a hash table. All elements will have their +reference counts decremented, and, on reaching zero, the free function will be +called to release the element data. + +=item * + +ossl_ht_insert() inserts an HT_VALUE element into the hash table, to be +hashed using the corresponding HT_KEY value. + +=item * + +ossl_ht_delete() deletes an entry from the hashtable indexed by the passed +HT_KEY value. + +=item * + +ossl_ht_count() returns the number of elements within the hash table. + +=item * + +ossl_ht_foreach_until() iterates over all elements in the hash table, calling +the passed callback function for each. The return value of the callback +indicates if the iteration should continue or not. Returning 1 indicates +iteration should continue, while returning 0 indicates that iteration should +terminate. + +Note that the iteration is done under read lock protection, and as such +modifications to the table are disallowed in the callback function. +Modification to the value content are permitted, if the caller is able to +properly synchronize such modifications with other threads. + +=item * + +ossl_ht_filter() iterates over all elements of the hash table, calling +the filter callback for each element. If the callback returns 1, the +corresponding HT_VALUE is placed on a list, and its reference count incremented. +The completed list is returned to the caller as an HT_VALUE_LIST object + +=item * + +ossl_ht_value_list_free() frees an HT_VALUE_LIST. For each element on +the list, its reference count is decremented, and after traversing the list, the +list object is freed. Note, NULL elements are allowed on the list, but for any +element which is taken from the list by a caller, they must call +ossl_ht_put on the HT_VALUE to prevent memory leaks. + +=item * + +ossl_ht_get() preforms a lookup of an HT_KEY in the hashtable, returning +its corresponding value. + +=item * + +HT_START_KEY_DEFN() Begins the definition of a key type. the keyname parameter +defines the structure name, and presets a common key header. + +=item * + +HT_END_KEY_DEFN() Finalizes a key definition. the keyname parameter (which may +differ from the name passed in HT_START_KEY_DEFN(), defines the key type name. +The resulting type may be converted to an HT_KEY variable via the HT_TO_KEY() +macro, and back using the HT_FROM_KEY() macro. + +=item * + +HT_DEF_KEY_FIELD() Allows for the creation of data fields within a key. Note, +this macro can be used for any data type, but it is recommended that strings and +binary arrays be created with the HT_DEF_KEY_FIELD_CHAR_ARRAY() and +HT_DEF_KEY_FIELD_UINT8T_ARRAY() macros to ensure proper in-lining of key data. + +=item * + +HT_DEF_KEY_FIELD_CHAR_ARRAY() Creates a string field of fixed size +within a key definition. Note these items will be NULL terminated. + +=item * + +HT_DEF_KEY_FIELD_UINT8T_ARRAY() Creates an array of uint8_t elements within a +key. + +=item * + +HT_INIT_KEY() Initializes a key for use. Can be called multiple times, but must +be called at least once before using in any hashtable method. + +=item * + +HT_KEY_RESET() Resets a key's data to all zeros. + +=item * + +HT_SET_KEY_FIELD() Sets a field in a key (as defined by HT_DEF_KEY_FIELD()) to a +given value. + +=item * + +HT_SET_KEY_STRING() Preforms a strncpy() of a source string to the destination +key field. + +=item * + +HT_SET_KEY_BLOB() Preforms a memcpy() of a source uint8_t buffer to a +destination key field. + +=item * + +TO_HT_KEY() Converts a key type as defined by HT_START_KEY_DEFN() and +HE_END_KEY_DEFN() to the generic HT_KEY type + +=item * + +FROM_HT_KEY() Converts an HT_KEY back to a specific key type as defined by +HT_START_KEY_DEFN() and HT_END_KEY_DEFN() + +=item * + +IMPLEMENT_HT_VALUE_TYPE_FNS() creates template conversion functions for +manipulating the hashtable using specific data types. This macro accepts two +parameters, a NAME, which is used to prefix the hashtable function so that it +may be associated with a specific hash table, and TYPE which defines the type of +data the instantiated function accepts. The list of functions instantiated by +this macro are below. + +=over 2 + +=item * + +int ossl_ht_NAME_TYPE_insert(HT* h, HT_KEY *key, <type> *value, HT_VALUE **olddata) +Inserts a value to the hash table of type TYPE into the hash table using the +provided key. If olddata is not NULL, and a matching key already exists in the +table, the operation is a replacement, and the old data is returned in this +pointer + +=item * + +<TYPE> ossl_ht_NAME_TYPE_get(HT *h, HT_KEY *key, HT_VALUE **v) +Looks up an item in the hash table based on key, and returns the data it found, +if any. v holds a pointer to the HT_VALUE associated with the data. + +=item * + +<TYPE> *ossl_ht_NAME_TYPE_from_value(HT_VALUE *v) +Validates that the HT_VALUE provided matches the TYPE specified, and returns the +value data. If there is a type mismatch, NULL is returned + +=item * + +HT_VALUE *ossl_ht_NAME_TYPE_to_value(<TYPE> *data) +Converts the data pointer provided to an HT_VALUE object + +=item * + +int ossl_ht_NAME_TYPE_type(HT_VALUE *v) +Returns true if the HT_VALUE object passed in is of type <TYPE> + +=back + +=back + +=head1 RETURN VALUES + +ossl_ht_new() returns an HT* struct on success and NULL on error + +void ossl_ht_free(HT *htable); + +ossl_ht_flush() and ossl_ht_insert() return 1 on success and 0 on error + +ossl_ht_delete() returns 1 if the key was successfully deleted, and 0 if the +key was not found. + +ossl_ht_count() returns the number of elements in the hash table + +ossl_ht_filter() returns an HT_VALUE_LIST of all elements matching the +provided filter + +ossl_ht_get() returns an HT_VALUE pointer, or NULL if the element was not +found. + +=head1 EXAMPLES + +#include <stdio.h> +#include <string.h> + +#include <openssl/err.h> +#include <openssl/crypto.h> +#include <internal/hashtable.h> + +HT_START_KEY_DEFN(intkey) +HT_DEF_KEY_FIELD(myintkey, int) +HT_END_KEY_DEFN(INTKEY) + +IMPLEMENT_HT_VALUE_TYPE_FNS(int, test, static) + +static void int_free_fn(HT_VALUE *v) +{ + int *i = ossl_crypto_test_int_from_value(v); + + fprintf(stderr, "Freeing an element\n"); + OPENSSL_free(i); +} + +static int test_int_hashtable(void) +{ + /* + * our config says: + * int_free_fn - Our free handler + * NULL - Use default hash fn + * 0 - use default initial bucket size + */ + HT_CONFIG hash_conf = { + int_free_fn, + NULL, + 0 + }; + INTKEY key; + HT *ht = NULL; + HT_VALUE *v; + int rc; + int *newval = OPENSSL_malloc(sizeof(int)); + + ht = ossl_ht_new(&hash_conf); + + if (ht == NULL) + return 0; + + if (newval == NULL) + goto out; + + *newval = 1; + + /* insert */ + HT_INIT_KEY(&key); + HT_SET_KEY_FIELD(&key, myintkey, 47); + ossl_ht_write_lock(ht); + rc = ossl_ht_test_int_insert(ht, TO_HT_KEY(&key), newval, NULL); + ossl_ht_write_unlock(ht); + if (rc == 0) + goto out; + + /* num_items */ + if (ossl_ht_count(ht) != 1) + goto out; + + /* lookup */ + HT_RESET_KEY(&key); + HT_SET_KEY_FIELD(&key, myintkey, 47); + ossl_ht_read_lock(ht); + v = ossl_ht_get(ht, TO_HT_KEY(&key); + fprintf(stderr, "found element with key 47 holding value %d\n", + *ossl_ht_test_int_from_value(v)); + ossl_ht_read_unlock(ht); + + rc = 1; +end: + /* this will call the free function for our element */ + ossl_ht_free(ht); + return rc; +} + +=head1 COPYRIGHT + +Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (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 +L<https://www.openssl.org/source/license.html>. + +=cut diff --git a/doc/man3/CRYPTO_THREAD_run_once.pod b/doc/man3/CRYPTO_THREAD_run_once.pod index 3658a39278..9d7eefb5d3 100644 --- a/doc/man3/CRYPTO_THREAD_run_once.pod +++ b/doc/man3/CRYPTO_THREAD_run_once.pod @@ -238,6 +238,10 @@ repeatedly load/unload shared libraries that allocate locks. L<crypto(7)>, L<openssl-threads(7)>. +=head1 HISTORY + +CRYPTO_atomic_store() was added in OpenSSL 3.4.0 + =head1 COPYRIGHT Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OPENSSL_malloc.pod b/doc/man3/OPENSSL_malloc.pod index 7dc6468f0e..9e8e0eebc0 100644 --- a/doc/man3/OPENSSL_malloc.pod +++ b/doc/man3/OPENSSL_malloc.pod @@ -3,9 +3,9 @@ =head1 NAME OPENSSL_malloc_init, -OPENSSL_malloc, OPENSSL_zalloc, OPENSSL_realloc, OPENSSL_free, -OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse, -CRYPTO_malloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free, +OPENSSL_malloc, OPENSSL_aligned_alloc, OPENSSL_zalloc, OPENSSL_realloc, +OPENSSL_free, OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse, +CRYPTO_malloc, CRYPTO_aligned_alloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free, OPENSSL_strdup, OPENSSL_strndup, OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat, CRYPTO_strdup, CRYPTO_strndup, @@ -28,6 +28,7 @@ OPENSSL_MALLOC_FD int OPENSSL_malloc_init(void); void *OPENSSL_malloc(size_t num); + void *OPENSSL_aligned_alloc(size_t num, size_t alignment, void **freeptr); void *OPENSSL_zalloc(size_t num); void *OPENSSL_realloc(void *addr, size_t num); void OPENSSL_free(void *addr); @@ -41,6 +42,8 @@ OPENSSL_MALLOC_FD void OPENSSL_cleanse(void *ptr, size_t len); void *CRYPTO_malloc(size_t num, const char *file, int line); + void *CRYPTO_aligned_alloc(size_t num, size_t align, void **freeptr, + const char *file, int line); void *CRYPTO_zalloc(size_t num, const char *file, int line); void *CRYPTO_realloc(void *p, size_t num, const char *file, int line); void CRYPTO_free(void *str, const char *, int); @@ -96,6 +99,20 @@ OPENSSL_malloc(), OPENSSL_realloc(), and OPENSSL_free() are like the C malloc(), realloc(), and free() functions. OPENSSL_zalloc() calls memset() to zero the memory before returning. +OPENSSL_aligned_alloc() operates just as OPENSSL_malloc does, but it +allows for the caller to specify an alignment value, for instances in +which the default alignment of malloc is insufficient for the callers +needs. Note, the alignment value must be a power of 2, and the size +specified must be a multiple of the alignment. +NOTE: The call to OPENSSL_aligned_alloc() accepts a 3rd argument, I<freeptr> +which must point to a void pointer. On some platforms, there is no available +library call to obtain memory allocations greater than what malloc provides. In +this case, OPENSSL_aligned_alloc implements its own alignment routine, +allocating additional memory and offsetting the returned pointer to be on the +requested alignment boundary. In order to safely free allocations made by this +method, the caller must return the value in the I<freeptr> variable, rather than +the returned pointer. + OPENSSL_clear_realloc() and OPENSSL_clear_free() should be used when the buffer at B<addr> holds sensitive information. The old buffer is filled with zero's by calling OPENSSL_cleanse() @@ -168,7 +185,7 @@ OPENSSL_malloc_init(), OPENSSL_free(), OPENSSL_clear_free() CRYPTO_free(), CRYPTO_clear_free() and CRYPTO_get_mem_functions() return no value. -OPENSSL_malloc(), OPENSSL_zalloc(), OPENSSL_realloc(), +OPENSSL_malloc(), OPENSSL_aligned_alloc(), OPENSSL_zalloc(), OPENSSL_realloc(), OPENSSL_clear_realloc(), CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_realloc(), CRYPTO_clear_realloc(), @@ -194,7 +211,7 @@ CRYPTO_mem_leaks_cb(), CRYPTO_set_mem_debug(), CRYPTO_mem_ctrl() were deprecated in OpenSSL 3.0. The memory-leak checking has been deprecated in OpenSSL 3.0 in favor of clang's memory and leak sanitizer. - +OPENSSL_aligned_alloc(), CRYPTO_aligned_alloc() were added in OpenSSL 3.4.0 =head1 COPYRIGHT |