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