From 71b431bd059aaefaa67b54a34adfaadc4014902c Mon Sep 17 00:00:00 2001 From: schwarze <> Date: Sat, 5 Nov 2016 13:36:33 +0000 Subject: convert the remaining manual pages from pod to mdoc --- src/lib/libcrypto/man/engine.3 | 1187 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1187 insertions(+) create mode 100644 src/lib/libcrypto/man/engine.3 (limited to 'src/lib/libcrypto/man/engine.3') diff --git a/src/lib/libcrypto/man/engine.3 b/src/lib/libcrypto/man/engine.3 new file mode 100644 index 0000000000..3624fa76e4 --- /dev/null +++ b/src/lib/libcrypto/man/engine.3 @@ -0,0 +1,1187 @@ +.Dd $Mdocdate: November 5 2016 $ +.Dt ENGINE 3 +.Os +.Sh NAME +.Nm ENGINE_add , +.Nm ENGINE_by_id , +.Nm ENGINE_finish , +.Nm ENGINE_get_first , +.Nm ENGINE_get_last , +.Nm ENGINE_get_next , +.Nm ENGINE_get_prev , +.Nm ENGINE_init , +.Nm ENGINE_load_builtin_engines , +.Nm ENGINE_remove +.Nd ENGINE cryptographic module support +.Sh SYNOPSIS +.In openssl/engine.h +.Ft ENGINE * +.Fn ENGINE_get_first void +.Ft ENGINE * +.Fn ENGINE_get_last void +.Ft ENGINE * +.Fo ENGINE_get_next +.Fa "ENGINE *e" +.Fc +.Ft ENGINE * +.Fo ENGINE_get_prev +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_add +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_remove +.Fa "ENGINE *e" +.Fc +.Ft ENGINE * +.Fo ENGINE_by_id +.Fa "const char *id" +.Fc +.Ft int +.Fo ENGINE_init +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_finish +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_load_openssl void +.Ft void +.Fn ENGINE_load_dynamic void +.Ft void +.Fn ENGINE_load_cryptodev void +.Ft void +.Fn ENGINE_load_builtin_engines void +.Ft void +.Fn ENGINE_cleanup void +.Ft ENGINE * +.Fn ENGINE_get_default_RSA void +.Ft ENGINE * +.Fn ENGINE_get_default_DSA void +.Ft ENGINE * +.Fn ENGINE_get_default_ECDH void +.Ft ENGINE * +.Fn ENGINE_get_default_ECDSA void +.Ft ENGINE * +.Fn ENGINE_get_default_DH void +.Ft ENGINE * +.Fn ENGINE_get_default_RAND void +.Ft ENGINE * +.Fo ENGINE_get_cipher_engine +.Fa "int nid" +.Fc +.Ft ENGINE * +.Fo ENGINE_get_digest_engine +.Fa "int nid" +.Fc +.Ft int +.Fo ENGINE_set_default_RSA +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_DSA +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_ECDH +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_ECDSA +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_DH +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_RAND +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_ciphers +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_digests +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_default_string +.Fa "ENGINE *e" +.Fa "const char *list" +.Fc +.Ft int +.Fo ENGINE_set_default +.Fa "ENGINE *e" +.Fa "unsigned int flags" +.Fc +.Ft unsigned int +.Fn ENGINE_get_table_flags void +.Ft void +.Fo ENGINE_set_table_flags +.Fa "unsigned int flags" +.Fc +.Ft int +.Fo ENGINE_register_RSA +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_RSA +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_RSA void +.Ft int +.Fo ENGINE_register_DSA +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_DSA +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_DSA void +.Ft int +.Fo ENGINE_register_ECDH +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_ECDH +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_ECDH void +.Ft int +.Fo ENGINE_register_ECDSA +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_ECDSA +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_ECDSA void +.Ft int +.Fo ENGINE_register_DH +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_DH +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_DH void +.Ft int +.Fo ENGINE_register_RAND +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_RAND +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_RAND void +.Ft int +.Fo ENGINE_register_STORE +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_STORE +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_STORE void +.Ft int +.Fo ENGINE_register_ciphers +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_ciphers +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_ciphers void +.Ft int +.Fo ENGINE_register_digests +.Fa "ENGINE *e" +.Fc +.Ft void +.Fo ENGINE_unregister_digests +.Fa "ENGINE *e" +.Fc +.Ft void +.Fn ENGINE_register_all_digests void +.Ft int +.Fo ENGINE_register_complete +.Fa "ENGINE *e" +.Fc +.Ft int +.Fn ENGINE_register_all_complete void +.Ft int +.Fo ENGINE_ctrl +.Fa "ENGINE *e" +.Fa "int cmd" +.Fa "long i" +.Fa "void *p" +.Fa "void (*f)(void)" +.Fc +.Ft int +.Fo ENGINE_cmd_is_executable +.Fa "ENGINE *e" +.Fa "int cmd" +.Fc +.Ft int +.Fo ENGINE_ctrl_cmd +.Fa "ENGINE *e" +.Fa "const char *cmd_name" +.Fa "long i" +.Fa "void *p" +.Fa "void (*f)(void)" +.Fa "int cmd_optional" +.Fc +.Ft int +.Fo ENGINE_ctrl_cmd_string +.Fa "ENGINE *e" +.Fa "const char *cmd_name" +.Fa "const char *arg" +.Fa "int cmd_optional" +.Fc +.Ft int +.Fo ENGINE_set_ex_data +.Fa "ENGINE *e" +.Fa "int idx" +.Fa "void *arg" +.Fc +.Ft void * +.Fo ENGINE_get_ex_data +.Fa "const ENGINE *e" +.Fa "int idx" +.Fc +.Ft int +.Fo ENGINE_get_ex_new_index +.Fa "long argl" +.Fa "void *argp" +.Fa "CRYPTO_EX_new *new_func" +.Fa "CRYPTO_EX_dup *dup_func" +.Fa "CRYPTO_EX_free *free_func" +.Fc +.Ft ENGINE * +.Fn ENGINE_new void +.Ft int +.Fo ENGINE_free +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_up_ref +.Fa "ENGINE *e" +.Fc +.Ft int +.Fo ENGINE_set_id +.Fa "ENGINE *e" +.Fa "const char *id" +.Fc +.Ft int +.Fo ENGINE_set_name +.Fa "ENGINE *e" +.Fa "const char *name" +.Fc +.Ft int +.Fo ENGINE_set_RSA +.Fa "ENGINE *e" +.Fa "const RSA_METHOD *rsa_meth" +.Fc +.Ft int +.Fo ENGINE_set_DSA +.Fa "ENGINE *e" +.Fa "const DSA_METHOD *dsa_meth" +.Fc +.Ft int +.Fo ENGINE_set_ECDH +.Fa "ENGINE *e" +.Fa "const ECDH_METHOD *dh_meth" +.Fc +.Ft int +.Fo ENGINE_set_ECDSA +.Fa "ENGINE *e" +.Fa "const ECDSA_METHOD *dh_meth" +.Fc +.Ft int +.Fo ENGINE_set_DH +.Fa "ENGINE *e" +.Fa "const DH_METHOD *dh_meth" +.Fc +.Ft int +.Fo ENGINE_set_RAND +.Fa "ENGINE *e" +.Fa "const RAND_METHOD *rand_meth" +.Fc +.Ft int +.Fo ENGINE_set_STORE +.Fa "ENGINE *e" +.Fa "const STORE_METHOD *rand_meth" +.Fc +.Ft int +.Fo ENGINE_set_destroy_function +.Fa "ENGINE *e" +.Fa "ENGINE_GEN_INT_FUNC_PTR destroy_f" +.Fc +.Ft int +.Fo ENGINE_set_init_function +.Fa "ENGINE *e" +.Fa "ENGINE_GEN_INT_FUNC_PTR init_f" +.Fc +.Ft int +.Fo ENGINE_set_finish_function +.Fa "ENGINE *e" +.Fa "ENGINE_GEN_INT_FUNC_PTR finish_f" +.Fc +.Ft int +.Fo ENGINE_set_ctrl_function +.Fa "ENGINE *e" +.Fa "ENGINE_CTRL_FUNC_PTR ctrl_f" +.Fc +.Ft int +.Fo ENGINE_set_load_privkey_function +.Fa "ENGINE *e" +.Fa "ENGINE_LOAD_KEY_PTR loadpriv_f" +.Fc +.Ft int +.Fo ENGINE_set_load_pubkey_function +.Fa "ENGINE *e" +.Fa "ENGINE_LOAD_KEY_PTR loadpub_f" +.Fc +.Ft int +.Fo ENGINE_set_ciphers +.Fa "ENGINE *e" +.Fa "ENGINE_CIPHERS_PTR f" +.Fc +.Ft int +.Fo ENGINE_set_digests +.Fa "ENGINE *e" +.Fa "ENGINE_DIGESTS_PTR f" +.Fc +.Ft int +.Fo ENGINE_set_flags +.Fa "ENGINE *e" +.Fa "int flags" +.Fc +.Ft int +.Fo ENGINE_set_cmd_defns +.Fa "ENGINE *e" +.Fa "const ENGINE_CMD_DEFN *defns" +.Fc +.Ft const char * +.Fo ENGINE_get_id +.Fa "const ENGINE *e" +.Fc +.Ft const char * +.Fo ENGINE_get_name +.Fa "const ENGINE *e" +.Fc +.Ft const RSA_METHOD * +.Fo ENGINE_get_RSA +.Fa "const ENGINE *e" +.Fc +.Ft const DSA_METHOD * +.Fo ENGINE_get_DSA +.Fa "const ENGINE *e" +.Fc +.Ft const ECDH_METHOD * +.Fo ENGINE_get_ECDH +.Fa "const ENGINE *e" +.Fc +.Ft const ECDSA_METHOD * +.Fo ENGINE_get_ECDSA +.Fa "const ENGINE *e" +.Fc +.Ft const DH_METHOD * +.Fo ENGINE_get_DH +.Fa "const ENGINE *e" +.Fc +.Ft const RAND_METHOD * +.Fo ENGINE_get_RAND +.Fa "const ENGINE *e" +.Fc +.Ft const STORE_METHOD * +.Fo ENGINE_get_STORE +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_GEN_INT_FUNC_PTR +.Fo ENGINE_get_destroy_function +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_GEN_INT_FUNC_PTR +.Fo ENGINE_get_init_function +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_GEN_INT_FUNC_PTR +.Fo ENGINE_get_finish_function +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_CTRL_FUNC_PTR +.Fo ENGINE_get_ctrl_function +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_LOAD_KEY_PTR +.Fo ENGINE_get_load_privkey_function +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_LOAD_KEY_PTR +.Fo ENGINE_get_load_pubkey_function +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_CIPHERS_PTR +.Fo ENGINE_get_ciphers +.Fa "const ENGINE *e" +.Fc +.Ft ENGINE_DIGESTS_PTR +.Fo ENGINE_get_digests +.Fa "const ENGINE *e" +.Fc +.Ft const EVP_CIPHER * +.Fo ENGINE_get_cipher +.Fa "ENGINE *e" +.Fa "int nid" +.Fc +.Ft const EVP_MD * +.Fo ENGINE_get_digest +.Fa "ENGINE *e" +.Fa "int nid" +.Fc +.Ft int +.Fo ENGINE_get_flags +.Fa "const ENGINE *e" +.Fc +.Ft const ENGINE_CMD_DEFN * +.Fo ENGINE_get_cmd_defns +.Fa "const ENGINE *e" +.Fc +.Ft EVP_PKEY * +.Fo ENGINE_load_private_key +.Fa "ENGINE *e" +.Fa "const char *key_id" +.Fa "UI_METHOD *ui_method" +.Fa "void *callback_data" +.Fc +.Ft EVP_PKEY * +.Fo ENGINE_load_public_key +.Fa "ENGINE *e" +.Fa "const char *key_id" +.Fa "UI_METHOD *ui_method" +.Fa "void *callback_data" +.Fc +.Ft void +.Fn ENGINE_add_conf_module void +.Sh DESCRIPTION +These functions create, manipulate, and use cryptographic modules +in the form of +.Vt ENGINE +objects. +These objects act as containers for implementations of cryptographic +algorithms, and support a reference-counted mechanism to allow them to +be dynamically loaded in and out of the running application. +.Pp +The cryptographic functionality that can be provided by an +.Vt ENGINE +implementation includes the following abstractions: +.Pp +.Bl -bullet -compact +.It +.Vt RSA_METHOD : +for providing alternative RSA implementations +.It +.Vt DSA_METHOD , DH_METHOD , RAND_METHOD , ECDH_METHOD , +.Vt ECDSA_METHOD , STORE_METHOD : +similarly for other OpenSSL APIs +.It +.Vt EVP_CIPHER : +potentially multiple cipher algorithms (indexed by 'nid') +.It +.Vt EVP_DIGEST : +potentially multiple hash algorithms (indexed by 'nid') +.It +key-loading: loading public and/or private EVP_PKEY keys +.El +.Ss Reference counting and handles +Due to the modular nature of the +.Nm engine +API, pointers to +.Vt ENGINE Ns s +need to be treated as handles - ie. not only as pointers, but also +as references to the underlying +.Vt ENGINE +object. +One should obtain a new reference when making copies of an +.Vt ENGINE +pointer if the copies will be used (and released) independently. +.Pp +.Vt ENGINE +objects have two levels of reference-counting to match the way in +which the objects are used. +At the most basic level, each +.Vt ENGINE +pointer is inherently a +.Sy structural +reference - a structural reference is required to use the pointer value +at all, as this kind of reference is a guarantee that the structure can +not be deallocated until the reference is released. +.Pp +However, a structural reference provides no guarantee that the +.Vt ENGINE +is initialised and able to use any of its cryptographic implementations. +Indeed it's quite possible that most +.Vt ENGINE Ns s +will not initialise at all in typical environments, as +.Vt ENGINE Ns s +are typically used to support specialised hardware. +To use an +.Vt ENGINE Ap s +functionality, you need a +.Sy functional +reference. +This kind of reference can be considered a specialised form of +structural reference, because each functional reference implicitly +contains a structural reference as well - however to avoid +difficult-to-find programming bugs, it is recommended to treat the two +kinds of reference independently. +If you have a functional reference to an +.Vt ENGINE , +you have a guarantee that the +.Vt ENGINE +has been initialised ready to perform cryptographic operations and +will remain uninitialised until after you have released your +reference. +.Pp +.Em Structural references +.Pp +This basic type of reference is used for instantiating new +.Vt ENGINE Ns s, +iterating across OpenSSL's internal linked-list of loaded +.Vt ENGINE Ns s, +reading information about an +.Vt ENGINE , +etc. +Essentially a structural reference is sufficient if you only need to +query or manipulate the data of an +.Vt ENGINE +implementation rather than use its functionality. +.Pp +The +.Fn ENGINE_new +function returns a structural reference to a new (empty) +.Vt ENGINE +object. +There are other +.Nm engine +API functions that return structural references such as +.Fn ENGINE_by_id , +.Fn ENGINE_get_first , +.Fn ENGINE_get_last , +.Fn ENGINE_get_next , +and +.Fn ENGINE_get_prev . +All structural references should be released by a corresponding call +to the +.Fn ENGINE_free +function. +The +.Vt ENGINE +object itself will only actually be cleaned up and deallocated when +the last structural reference is released. +.Pp +It should also be noted that many +.Nm engine +API function calls that accept a structural reference will internally +obtain another reference. +Typically this happens whenever the supplied +.Vt ENGINE +will be needed by OpenSSL after the function has returned. +For example, the function to add a new +.Vt ENGINE +to OpenSSL's internal list is +.Fn ENGINE_add . +If this function returns success, OpenSSL will have stored a new +structural reference internally so the caller is still responsible for +freeing their own reference with +.Fn ENGINE_free +when they are finished with it. +In a similar way, some functions will automatically release the +structural reference passed to it if part of the function's job is +to do so. +For example, the +.Fn ENGINE_get_next +and +.Fn ENGINE_get_prev +functions are used for iterating across the internal +.Vt ENGINE +list. +They +will return a new structural reference to the next (or previous) +.Vt ENGINE +in the list or +.Dv NULL +if at the end (or beginning) of the list, but in either case the +structural reference passed to the function is released on behalf +of the caller. +.Pp +To clarify a particular function's handling of references, one should +always consult that function's manual page, or failing that the +.In openssl/engine.h +header file includes some hints. +.Pp +.Em Functional references +.Pp +As mentioned, functional references exist when the cryptographic +functionality of an +.Vt ENGINE +is required to be available. +A functional reference can be obtained in one of two ways; from an +existing structural reference to the required +.Vt ENGINE , +or by asking OpenSSL for the default operational +.Vt ENGINE +for a given cryptographic purpose. +.Pp +To obtain a functional reference from an existing structural reference, +call the +.Fn ENGINE_init +function. +This returns zero if the +.Vt ENGINE +was not already operational and couldn't be successfully initialised +(eg. lack of system drivers, no special hardware attached, etc.), +otherwise it will return non-zero to indicate that the +.Vt ENGINE +is now operational and will have allocated a new +.Sy functional +reference to the +.Vt ENGINE . +All functional references are released by calling +.Fn ENGINE_finish , +which removes the implicit structural reference as well. +.Pp +The second way to get a functional reference is by asking OpenSSL for a +default implementation for a given task, eg. +by +.Fn ENGINE_get_default_RSA , +.Fn ENGINE_get_default_cipher_engine , +etc. +These are discussed in the next section, though they are not usually +required by application programmers as they are used automatically when +creating and using the relevant algorithm-specific types in OpenSSL, +such as RSA, DSA, EVP_CIPHER_CTX, etc. +.Ss Default implementations +For each supported abstraction, the +.Nm engine +code maintains an internal table of state to control which +implementations are available for a given abstraction and which +should be used by default. +These implementations are registered in the tables and indexed by an +.Fa nid +value, because abstractions like +.Vt EVP_CIPHER +and +.Vt EVP_DIGEST +support many distinct algorithms and modes, and +.Vt ENGINE Ns s +can support arbitrarily many of them. +In the case of other abstractions like RSA, DSA, etc., there is +only one "algorithm" so all implementations implicitly register +using the same +.Fa nid +index. +.Pp +When a default +.Vt ENGINE +is requested for a given abstraction/algorithm/mode, (eg. when +calling +.Fn RSA_new_method NULL ) , +a "get_default" call will be made to the +.Nm engine +subsystem to process the corresponding state table and return +a functional reference to an initialised +.Vt ENGINE +whose implementation should be used. +If no +.Vt ENGINE +should (or can) be used, it will return +.Dv NULL +and the caller will operate with a +.Dv NULL +.Vt ENGINE +handle. +This usually equates to using the conventional software implementation. +In the latter case, OpenSSL will from then on behave the way it used to +before the +.Nm engine +API existed. +.Pp +Each state table has a flag to note whether it has processed this +"get_default" query since the table was last modified, because to +process this question it must iterate across all the registered +.Vt ENGINE Ns s +in the table trying to initialise each of them in turn, in case one of +them is operational. +If it returns a functional reference to an +.Vt ENGINE , +it will also cache another reference to speed up processing future +queries (without needing to iterate across the table). +Likewise, it will cache a +.Dv NULL +response if no +.Vt ENGINE +was available so that future queries won't repeat the same iteration +unless the state table changes. +This behaviour can also be changed; if the +.Dv ENGINE_TABLE_FLAG_NOINIT +flag is set (using +.Fn ENGINE_set_table_flags ) , +no attempted initialisations will take place, instead the only way for +the state table to return a +.Pf non- Dv NULL +.Vt ENGINE +to the "get_default" query will be if one is expressly set in the table. +For example, +.Fn ENGINE_set_default_RSA +does the same job as +.Fn ENGINE_register_RSA +except that it also sets the state table's cached response for the +"get_default" query. +In the case of abstractions like +.Vt EVP_CIPHER , +where implementations are indexed by +.Fa nid , +these flags and cached-responses are distinct for each +.Fa nid +value. +.Ss Application requirements +This section will explain the basic things an application programmer +should support to make the most useful elements of the +.Nm engine +functionality available to the user. +The first thing to consider is whether the programmer wishes to make +alternative +.Vt ENGINE +modules available to the application and user. +OpenSSL maintains an internal linked list of "visible" +.Vt ENGINE Ns s +from which it has to operate. +At start-up, this list is empty, and in fact if an application does +not call any +.Nm engine +API calls and it uses static +linking against openssl, then the resulting application binary will +not contain any alternative +.Nm engine +code at all. +So the first consideration is whether any/all available +.Vt ENGINE +implementations should be made visible to OpenSSL. +This is controlled by calling the various "load" functions, eg. +.Fn ENGINE_load_builtin_engines +to make all +.Vt ENGINE +implementations bundled with OpenSSL available. +.Pp +Note that +.Fn ENGINE_load_dynamic +is a placeholder and does not enable dynamic engine loading support. +.Pp +Having called any of these functions, +.Vt ENGINE +objects would have been dynamically allocated and populated with +these implementations and linked into OpenSSL's internal linked +list. +.Pp +If no +.Nm engine +API functions are called at all in an application, then there are +no inherent memory leaks to worry about from the +.Nm engine +functionality, however if any +.Vt ENGINE Ns s +are loaded, even if they are never registered or used, it is necessary +to use the +.Fn ENGINE_cleanup +function to correspondingly cleanup before program exit, if the caller +wishes to avoid memory leaks. +This mechanism uses an internal callback registration table so that any +.Nm engine +API functionality that knows it requires cleanup can register its +cleanup details to be called during +.Fn ENGINE_cleanup . +This approach allows +.Fn ENGINE_cleanup +to clean up after any +.Nm engine +functionality at all that your program uses, yet doesn't automatically +create linker dependencies to all possible +.Nm engine +functionality - only the cleanup callbacks required by the functionality +you do use will be required by the linker. +.Pp +The fact that +.Vt ENGINE Ns s +are made visible to OpenSSL (and thus are linked into the program +and loaded into memory at run-time) does not mean they are "registered" +or called into use by OpenSSL automatically - that behaviour is +something for the application to control. +Some applications will want to allow the user to specify exactly which +.Vt ENGINE +they want used if any is to be used at all. +Others may prefer to load all support and have OpenSSL automatically use +at run-time any +.Vt ENGINE +that is able to successfully initialised - ie. to assume that this +corresponds to acceleration hardware attached to the machine or +some such thing. +There are probably numerous other ways in which applications may prefer +to handle things, so we will simply illustrate the consequences as they +apply to a couple of simple cases and leave developers to consider these +and the source code to openssl's builtin utilities as guides. +.Pp +.Em Using a specific ENGINE implementation +.Pp +Here we'll assume an application has been configured by its user or +admin to want to use the "ACME" +.Vt ENGINE +if it is available in the version of OpenSSL the application was +compiled with. +If it is available, it should be used by default for all RSA, DSA, and +symmetric cipher operation, otherwise OpenSSL should use its builtin +software as usual. +The following code illustrates how to approach this: +.Bd -literal +ENGINE *e; +const char *engine_id = "ACME"; +ENGINE_load_builtin_engines(); +e = ENGINE_by_id(engine_id); +if (!e) + /* the engine isn't available */ + return; +if (!ENGINE_init(e)) { + /* the engine couldn't initialise, release 'e' */ + ENGINE_free(e); + return; +} +if (!ENGINE_set_default_RSA(e)) + /* This should only happen when 'e' can't initialise, but the previous + * statement suggests it did. */ + abort(); +ENGINE_set_default_DSA(e); +ENGINE_set_default_ciphers(e); +/* Release the functional reference from ENGINE_init() */ +ENGINE_finish(e); +/* Release the structural reference from ENGINE_by_id() */ +ENGINE_free(e); +.Ed +.Pp +.Em Automatically using builtin ENGINE implementations +.Pp +Here we'll assume we want to load and register all +.Vt ENGINE +implementations bundled with OpenSSL, such that for any cryptographic +algorithm required by OpenSSL - if there is an +.Vt ENGINE +that implements it and can be initialise, it should be used. +The following code illustrates how this can work; +.Bd -literal +/* Load all bundled ENGINEs into memory and make them visible */ +ENGINE_load_builtin_engines(); +/* Register all of them for every algorithm they collectively implement */ +ENGINE_register_all_complete(); +.Ed +.Pp +That's all that's required. +For example, the next time OpenSSL tries to set up an RSA key, any bundled +.Vt ENGINE Ns s +that implement +.Vt RSA_METHOD +will be passed to +.Fn ENGINE_init +and if any of those succeed, that +.Vt ENGINE +will be set as the default for RSA use from then on. +.Ss Advanced configuration support +There is a mechanism supported by the +.Nm engine +framework that allows each +.Vt ENGINE +implementation to define an arbitrary set of configuration +"commands" and expose them to OpenSSL and any applications based on +OpenSSL. +This mechanism is entirely based on the use of name-value pairs +and assumes ASCII input (no unicode or UTF for now!), so it is ideal if +applications want to provide a transparent way for users to provide +arbitrary configuration "directives" directly to such +.Vt ENGINE Ns s. +It is also possible for the application to dynamically interrogate the +loaded +.Vt ENGINE +implementations for the names, descriptions, and input flags of +their available "control commands", providing a more flexible +configuration scheme. +However, if the user is expected to know which +.Vt ENGINE +device he/she is using (in the case of specialised hardware, this +goes without saying) then applications may not need to concern +themselves with discovering the supported control commands and +simply prefer to pass settings into +.Vt ENGINE s +exactly as they are provided by the user. +.Pp +Before illustrating how control commands work, it is worth mentioning +what they are typically used for. +Broadly speaking there are two uses for control commands; the first is +to provide the necessary details to the implementation (which may know +nothing at all specific to the host system) so that it can be +initialised for use. +This could include the path to any driver or config files it needs to +load, required network addresses, smart-card identifiers, passwords to +initialise protected devices, logging information, etc etc. +This class of commands typically needs to be passed to an +.Vt ENGINE +.Sy before +attempting to initialise it, ie. before calling +.Fn ENGINE_init . +The other class of commands consist of settings or operations that tweak +certain behaviour or cause certain operations to take place, and these +commands may work either before or after +.Fn ENGINE_init , +or in some cases both. +.Vt ENGINE +implementations should provide indications of this in the descriptions +attached to builtin control commands and/or in external product +documentation. +.Pp +.Em Issuing control commands to an ENGINE +.Pp +Let's illustrate by example; a function for which the caller supplies +the name of the +.Vt ENGINE +it wishes to use, a table of string-pairs for use before initialisation, +and another table for use after initialisation. +Note that the string-pairs used for control commands consist of a +command "name" followed by the command "parameter" - the parameter +could be +.Dv NULL +in some cases but the name can not. +This function should initialise the +.Vt ENGINE +(issuing the "pre" commands beforehand and the "post" commands +afterwards) and set it as the default for everything except RAND +and then return a boolean success or failure. +.Bd -literal +int +generic_load_engine_fn(const char *engine_id, + const char **pre_cmds, int pre_num, + const char **post_cmds, int post_num) +{ + ENGINE *e = ENGINE_by_id(engine_id); + + if (!e) + return 0; + while (pre_num--) { + if (!ENGINE_ctrl_cmd_string(e, + pre_cmds[0], pre_cmds[1], 0)) { + fprintf(stderr, + "Failed command (%s - %s:%s)\en", + engine_id, pre_cmds[0], + pre_cmds[1] ? pre_cmds[1] : "(NULL)"); + ENGINE_free(e); + return 0; + } + pre_cmds += 2; + } + if (!ENGINE_init(e)) { + fprintf(stderr, "Failed initialisation\en"); + ENGINE_free(e); + return 0; + } + /* + * ENGINE_init() returned a functional reference, + * so free the structural reference from + * ENGINE_by_id(). + */ + ENGINE_free(e); + while (post_num--) { + if (!ENGINE_ctrl_cmd_string(e, + post_cmds[0], post_cmds[1], 0)) { + fprintf(stderr, + "Failed command (%s - %s:%s)\en", + engine_id, post_cmds[0], + post_cmds[1] ? post_cmds[1] : "(NULL)"); + ENGINE_finish(e); + return 0; + } + post_cmds += 2; + } + ENGINE_set_default(e, ENGINE_METHOD_ALL & ~ENGINE_METHOD_RAND); + /* Success */ + return 1; +} +.Ed +.Pp +Note that +.Fn ENGINE_ctrl_cmd_string +accepts a boolean argument that can relax the semantics of the function. +If set to non-zero it will only return failure if the +.Vt ENGINE +supported the given command name but failed while executing it, if the +.Vt ENGINE +doesn't support the command name it will simply return success without +doing anything. +In this case we assume the user is only supplying commands specific to +the given +.Vt ENGINE +so we set this to FALSE. +.Pp +.Em Discovering supported control commands +.Pp +It is possible to discover at run-time the names, numerical-ids, +descriptions and input parameters of the control commands supported by an +.Vt ENGINE +using a structural reference. +Note that some control commands are defined by OpenSSL itself and it +will intercept and handle these control commands on behalf of the +.Vt ENGINE , +ie. the +.Vt ENGINE Ap s +ctrl() handler is not used for the control command. +.In openssl/engine.h +defines an index, +.Dv ENGINE_CMD_BASE , +that all control commands implemented by +.Vt ENGINE Ns s +should be numbered from. +Any command value lower than this symbol is considered a "generic" +command is handled directly by the OpenSSL core routines. +.Pp +It is using these "core" control commands that one can discover the +control commands implemented by a given +.Vt ENGINE , +specifically the commands: +.Bd -literal +#define ENGINE_HAS_CTRL_FUNCTION 10 +#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 +#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 +#define ENGINE_CTRL_GET_CMD_FROM_NAME 13 +#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 +#define ENGINE_CTRL_GET_NAME_FROM_CMD 15 +#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 +#define ENGINE_CTRL_GET_DESC_FROM_CMD 17 +#define ENGINE_CTRL_GET_CMD_FLAGS 18 +.Ed +.Pp +Whilst these commands are automatically processed by the OpenSSL +framework code, they use various properties exposed by each +.Vt ENGINE +to process these queries. +An +.Vt ENGINE +has 3 properties it exposes that can affect how this behaves; +it can supply a ctrl() handler, it can specify +.Dv ENGINE_FLAGS_MANUAL_CMD_CTRL +in the +.Vt ENGINE Ap s +flags, and it can expose an array of control command descriptions. +If an +.Vt ENGINE +specifies the +.Dv ENGINE_FLAGS_MANUAL_CMD_CTRL +flag, then it will simply pass all these "core" control commands +directly to the +.Vt ENGINE Ap s +ctrl() handler (and thus, it must have supplied one), so it is up +to the +.Vt ENGINE +to reply to these "discovery" commands itself. +If that flag is not set, then the OpenSSL framework code will work with +the following rules; +.Bl -tag -width Ds +.It If no ctrl() handler is supplied: +.Dv ENGINE_HAS_CTRL_FUNCTION +returns FALSE (zero), all other commands fail. +.It If a ctrl() handler was supplied but no array of control commands: +.Dv ENGINE_HAS_CTRL_FUNCTION +returns TRUE, all other commands fail. +.It If a ctrl() handler and array of control commands was supplied: +.Dv ENGINE_HAS_CTRL_FUNCTION +returns TRUE, all other commands proceed processing... +.El +.Pp +If the +.Vt ENGINE Ns s +array of control commands is empty, then all other commands will fail. +Otherwise +.Dv ENGINE_CTRL_GET_FIRST_CMD_TYPE +returns the identifier of the first command supported by the +.Vt ENGINE , +.Dv ENGINE_GET_NEXT_CMD_TYPE +takes the identifier of a command supported by the +.Vt ENGINE +and returns the next command identifier or fails if there are no more, +.Dv ENGINE_CMD_FROM_NAME +takes a string name for a command and returns the corresponding +identifier or fails if no such command name exists, and the remaining +commands take a command identifier and return properties of the +corresponding commands. +All except +.Dv ENGINE_CTRL_GET_FLAGS +return the string length of a command name or description, or +populate a supplied character buffer with a copy of the command +name or description. +.Dv ENGINE_CTRL_GET_FLAGS +returns a bitwise-OR'd mask of the following possible values: +.Bd -literal +#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 +#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 +#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 +#define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 +.Ed +.Pp +If the +.Dv ENGINE_CMD_FLAG_INTERNAL +flag is set, then any other flags are purely informational to the caller. +This flag will prevent the command being usable for any higher-level +.Vt ENGINE +functions such as +.Fn ENGINE_ctrl_cmd_string . +"INTERNAL" commands are not intended to be exposed to text-based +configuration by applications, administrations, users, etc. +These can support arbitrary operations via +.Fn ENGINE_ctrl , +including passing to and/or from the control commands data of any +arbitrary type. +These commands are supported in the discovery mechanisms simply allow +applications to determine if an +.Vt ENGINE +supports certain specific commands it might want to use (eg. +application "foo" might query various +.Vt ENGINE Ns s +to see if they implement "FOO_GET_VENDOR_LOGO_GIF" - and +.Vt ENGINE +could therefore decide whether or not to support this "foo"-specific +extension). +.Ss Future developments +The +.Nm engine +API and internal architecture is currently being reviewed. +Slated for possible release in 0.9.8 is support for transparent loading +of "dynamic" +.Vt ENGINE Ns s (built as self-contained shared libraries). +This would allow +.Vt ENGINE +implementations to be provided independently of +OpenSSL libraries and/or OpenSSL-based applications, and would also +remove any requirement for applications to explicitly use the "dynamic" +.Vt ENGINE +to bind to shared-library implementations. +.Sh SEE ALSO +.Xr dh 3 , +.Xr dsa 3 , +.Xr rsa 3 -- cgit v1.2.3-55-g6feb