1e1051a39Sopenharmony_ciSelecting algorithm implementations by properties 2e1051a39Sopenharmony_ci================================================= 3e1051a39Sopenharmony_ci 4e1051a39Sopenharmony_ciProperties are associated with algorithms and are used to select between 5e1051a39Sopenharmony_cidifferent implementations dynamically. 6e1051a39Sopenharmony_ci 7e1051a39Sopenharmony_ciThis implementation is based on a number of assumptions: 8e1051a39Sopenharmony_ci 9e1051a39Sopenharmony_ci* Property definition is uncommon. I.e. providers will be loaded and 10e1051a39Sopenharmony_ci unloaded relatively infrequently, if at all. 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci* The number of distinct property names will be small. 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci* Providers will often give the same implementation properties to most or 15e1051a39Sopenharmony_ci all of their implemented algorithms. E.g. the FIPS property would be set 16e1051a39Sopenharmony_ci across an entire provider. Likewise for, hardware, accelerated, software, 17e1051a39Sopenharmony_ci HSM and, perhaps, constant_time. 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci* There are a lot of algorithm implementations, therefore property 20e1051a39Sopenharmony_ci definitions should be space efficient. However... 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci* ... property queries are very common. These must be fast. 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci* Property queries come from a small set and are reused many times typically. 25e1051a39Sopenharmony_ci I.e. an application tends to use the same set of queries over and over, 26e1051a39Sopenharmony_ci rather than spanning a wide variety of queries. 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ci* Property queries can never add new property definitions. 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ciSome consequences of these assumptions are: 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci* That definition is uncommon and queries are very common, we can treat 33e1051a39Sopenharmony_ci the property definitions as almost immutable. Specifically, a query can 34e1051a39Sopenharmony_ci never change the state of the definitions. 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci* That definition is uncommon and needs to be space efficient, it will 37e1051a39Sopenharmony_ci be feasible to use a hash table to contain the names (and possibly also 38e1051a39Sopenharmony_ci values) of all properties and to reference these instead of duplicating 39e1051a39Sopenharmony_ci strings. Moreover, such a data structure need not be garbage collected. 40e1051a39Sopenharmony_ci By converting strings to integers using a structure such as this, string 41e1051a39Sopenharmony_ci comparison degenerates to integer comparison. Additionally, lists of 42e1051a39Sopenharmony_ci properties can be sorted by the string index which makes comparisons linear 43e1051a39Sopenharmony_ci time rather than quadratic time - the O(n log n) sort cost being amortised. 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ci* A cache for property definitions is also viable, if only implementation 46e1051a39Sopenharmony_ci properties are used and not algorithm properties, or at least these are 47e1051a39Sopenharmony_ci maintained separately. This cache would be a hash table, indexed by 48e1051a39Sopenharmony_ci the property definition string, and algorithms with the same properties 49e1051a39Sopenharmony_ci would share their definition structure. Again, reducing space use. 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci* A query cache is desirable. This would be a hash table keyed by the 52e1051a39Sopenharmony_ci algorithm identifier and the entire query string and it would map to 53e1051a39Sopenharmony_ci the chosen algorithm. When a provider is loaded or unloaded, this cache 54e1051a39Sopenharmony_ci must be invalidated. The cache will also be invalidated when the global 55e1051a39Sopenharmony_ci properties are changed as doing so removes the need to index on both the 56e1051a39Sopenharmony_ci global and requested property strings. 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ciThe implementation: 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_ci* [property_lock.c](property_lock.c) 61e1051a39Sopenharmony_ci contains some wrapper functions to handle the global 62e1051a39Sopenharmony_ci lock more easily. The global lock is held for short periods of time with 63e1051a39Sopenharmony_ci per algorithm locking being used for longer intervals. 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci* [property_string.c](property_string.c) 66e1051a39Sopenharmony_ci contains the string cache which converts property 67e1051a39Sopenharmony_ci names and values to small integer indices. Names and values are stored in 68e1051a39Sopenharmony_ci separate hash tables. The two Boolean values, the strings "yes" and "no", 69e1051a39Sopenharmony_ci are populated as the first two members of the value table. All property 70e1051a39Sopenharmony_ci names reserved by OpenSSL are also populated here. No functions are 71e1051a39Sopenharmony_ci provided to convert from an index back to the original string (this can be 72e1051a39Sopenharmony_ci done by maintaining parallel stacks of strings if required). 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci* [property_parse.c](property_parse.c) 75e1051a39Sopenharmony_ci contains the property definition and query parsers. 76e1051a39Sopenharmony_ci These convert ASCII strings into lists of properties. The resulting 77e1051a39Sopenharmony_ci lists are sorted by the name index. Some additional utility functions 78e1051a39Sopenharmony_ci for dealing with property lists are also included: comparison of a query 79e1051a39Sopenharmony_ci against a definition and merging two queries into a single larger query. 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci* [property.c](property.c) 82e1051a39Sopenharmony_ci contains the main APIs for defining and using properties. 83e1051a39Sopenharmony_ci Algorithms are discovered from their NID and a query string. 84e1051a39Sopenharmony_ci The results are cached. 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci The caching of query results has to be efficient but it must also be robust 87e1051a39Sopenharmony_ci against a denial of service attack. The cache cannot be permitted to grow 88e1051a39Sopenharmony_ci without bounds and must garbage collect under-used entries. The garbage 89e1051a39Sopenharmony_ci collection does not have to be exact. 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci* [defn_cache.c](defn_cache.c) 92e1051a39Sopenharmony_ci contains a cache that maps property definition strings to 93e1051a39Sopenharmony_ci parsed properties. It is used by property.c to improve performance when 94e1051a39Sopenharmony_ci the same definition appears multiple times. 95