From 7753be74a3c90e21d0d29d6131d9e751476f81ec Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sun, 20 Jan 2019 13:23:30 +0100 Subject: [PATCH] Replumbing: Add include/openssl/core.h, initially with core types Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/8286) --- doc/man3/OSSL_PARAM.pod | 302 ++++++++++++++++++++++++++++++++++++ doc/man7/openssl-core.h.pod | 96 ++++++++++++ include/openssl/core.h | 143 +++++++++++++++++ include/openssl/ossl_typ.h | 5 + util/private.num | 1 + 5 files changed, 547 insertions(+) create mode 100644 doc/man3/OSSL_PARAM.pod create mode 100644 doc/man7/openssl-core.h.pod create mode 100644 include/openssl/core.h diff --git a/doc/man3/OSSL_PARAM.pod b/doc/man3/OSSL_PARAM.pod new file mode 100644 index 0000000000..9d4748637c --- /dev/null +++ b/doc/man3/OSSL_PARAM.pod @@ -0,0 +1,302 @@ +=pod + +=head1 NAME + +OSSL_PARAM - a structure to pass or request object parameters + +=head1 SYNOPSIS + + #include + + typedef struct ossl_param_st OSSL_PARAM; + struct ossl_param_st { + const char *key; /* the name of the parameter */ + unsigned char data_type; /* declare what kind of content is in buffer */ + void *buffer; /* value being passed in or out */ + size_t buffer_size; /* buffer size */ + size_t *return_size; /* OPTIONAL: address to content size */ + }; + +=head1 DESCRIPTION + +C is a type that allows passing arbitrary data for some +object between two parties that have no or very little shared +knowledge about their respective internal structures for that object. + +A typical usage example could be an application that wants to set some +parameters for an object, or wants to find out some parameters of an +object. + +Arrays of this type can be used for two purposes: + +=over 4 + +=item * + +Setting parameters for some object. +The caller sets up the C array and calls some function +(the I) that has intimate knowledge about the object that can +take the data from the C array and assign them in a +suitable form for the internal structure of the object. + +=item * + +Request parameters of some object. +The caller (the I) sets up the C array and +calls some function (the I) that has intimate knowledge +about the object, which can take the internal data of the object and +copy (possibly convert) that to the buffers prepared by the +I. + +=back + +=head2 C fields + +=over 4 + +=item C + +The identity of the parameter in the form of a string. + +=item C + +=for comment It's still debated if this field should be present, or if +the type should always be implied by how it's used. +Either way, these data types will have to be passed together with the +names as an array of OSSL_ITEM, for discovery purposes. + +The C is a value that describes the type and organization of +the data. +See L below for a description of the types. + +=item C + +=item C + +C is a pointer to the memory where the parameter data is (when +setting parameters) or shall (when requesting parameters) be stored, +and C is its size in bytes. +The organization of the data depends on the parameter type and flag. + +=item C + +When an array of C is used to request data, the +I must set this field to indicate the actual size of the +parameter data. +In case the C is too small for the data, the I +must still set this field to indicate the minimum buffer size +required. + +=back + +B + +The key names and associated types are defined by the entity that +offers these parameters, i.e. names for parameters provided by the +OpenSSL libraries are defined by the libraries, and names for +parameters provided by providers are defined by those providers, +except for the pointer form of strings (see data type descriptions +below). +Entities that want to set or request parameters need to know what +those keys are and of what type, any functionality between those two +entities should remain oblivious and just pass the C array +along. + +=head2 Supported types + +The C field can be one of the following types: + +=over 4 + +=item C + +=item C + +The parameter data is an integer (signed or unsigned) of arbitrary +length, organized in native form, i.e. most significant byte first on +Big-Endian systems, and least significant byte first on Little-Endian +systems. + +=item C + +=for comment It's still debated if we need this or not. + +The parameter data is a floating point value in native form. + +=item C + +The parameter data is a printable string. + +=item C + +The parameter data is an arbitrary string of bytes. + +=back + +Additionally, this flag can be added to any type: + +=over 4 + +=item C + +With this flag, C doesn't point directly at the data, but at a +pointer that points at the data. + +This can be used to indicate that constant data is or will be passed, +and there is therefore no need to copy the data that is passed, just +the pointer to it. + +If an C with this flag set is used to set a parameter, +C must be set to the size of the data, not the size of +the pointer to the data. + +If this C is used in a parameter request, C +is not relevant. +However, the I will set C<*return_size> to the size of the +data (again, not the size of the pointer to the data). + +Note that the use of this flag is B and can only be safely +used for data that remains constant and in a constant location for a +long enough duration (such as the life-time of the entity that +offers these parameters). + +=back + +For convenience, these types are provided: + +=over 4 + +=item C + +=item C + +These are combinations of C as well as +C with C. + +=back + +=head1 NOTES + +Both when setting and requesting parameters, the functions that are +called will have to decide what is and what is not an error. +The recommended behaviour is: + +=over 4 + +=item * + +Keys that a I or I doesn't recognise should simply +be ignored. +That in itself isn't an error. + +=item * + +If the keys that a called I recognises form a consistent +enough set of data, that call should succeed. + +=item * + +A I must never change the fields of an C, it +may only change the contents of the buffers that C and +C point at. + +=item * + +If the data type for a key that it's associated with is incorrect, +the called function may return an error. + +The called function may also try to convert the data to a suitable +form (for example, it's plausible to pass a large number as an octet +string, so even though a given key is defined as an +C, is plausible to pass the value as an +C), but this is in no way mandatory. + +=item * + +If a I finds that some buffers are too small for the +requested data, it must set C<*return_size> for each such +C item to the required size, and eventually return an +error. + +=back + +=begin comment RETURN VALUES doesn't make sense for a manual that only +describes a type, but document checkers still want that section, and +to have more than just the section title. + +=head1 RETURN VALUES + +txt + +=end comment + +=head1 EXAMPLES + +A couple of examples to just show how C arrays could be +set up. + +=head3 Example 1 + +This example is for setting parameters on some object: + + #include + + const char *foo = "some string"; + size_t foo_l = strlen(foo) + 1; + const char bar[] = "some other string"; + const OSSL_PARAM set[] = { + { "foo", OSSL_PARAM_UTF8_STRING_PTR, &foo, foo_l, NULL }, + { "bar", OSSL_PARAM_UTF8_STRING, &bar, sizeof(bar), NULL }, + { NULL, 0, NULL, 0, NULL } + }; + +=head3 Example 2 + +This example is for requesting parameters on some object: + + const char *foo = NULL; + size_t foo_l; + char bar[1024]; + size_t bar_l; + const OSSL_PARAM request[] = { + { "foo", OSSL_PARAM_UTF8_STRING_PTR, &foo, 0 /*irrelevant*/, &foo_l }, + { "bar", OSSL_PARAM_UTF8_STRING, &bar, sizeof(bar), &bar_l }, + { NULL, 0, NULL, 0, NULL } + }; + +A I that receives this array (as C in this example) +could fill in the parameters like this: + + /* const OSSL_PARAM *params */ + + int i; + + for (i = 0; params[i].key != NULL; i++) { + if (strcmp(params[i].key, "foo") == 0) { + *(char **)params[i].buffer = "foo value"; + *params[i].return_size = 10; /* size of "foo value" */ + } else if (strcmp(params[i].key, "bar") == 0) { + memcpy(params[1].buffer, "bar value", 10); + *params[1].return_size = 10; /* size of "bar value" */ + } + /* Ignore stuff we don't know */ + } + +=head1 SEE ALSO + +L + +=head1 HISTORY + +C was added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2019 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. + +=cut diff --git a/doc/man7/openssl-core.h.pod b/doc/man7/openssl-core.h.pod new file mode 100644 index 0000000000..7fd4dfb24e --- /dev/null +++ b/doc/man7/openssl-core.h.pod @@ -0,0 +1,96 @@ +=pod + +=head1 NAME + +openssl/core.h - OpenSSL Core types + +=head1 SYNOPSIS + + #include + +=head1 DESCRIPTION + +The header file defines a number of public types that +are used to communicate between the OpenSSL libraries and +implementation providers. +These types are designed to minimise the need for intimate knowledge +of internal structures between the OpenSSL libraries and the providers. + +The types are: + +=over 4 + +=item C + +This type is a tuple of function identity and function pointer. +Arrays of this type are passed between the OpenSSL libraries and the +providers to describe what functionality one side provides to the +other. +Arrays of this type must be terminated with a tuple having function +identity zero and function pointer C. + +The available function identities and corresponding function +signatures are defined by L. + +Any function identity not recognised by the recipient of this type +will be ignored. +This ensures that providers built with one OpenSSL version in mind +will work together with any other OpenSSL version that supports this +mechanism. + +=item C + +This type is a tuple of integer and pointer. +It's a generic type used as a generic descriptor, its exact meaning +being defined by how it's used. +Arrays of this type are passed between the OpenSSL libraries and the +providers, and must be terminated with a tuple where the integer is +zero and the pointer C. + +=item C + +This type is a tuple of an algorithm name (string), a property +definition (string) and a dispatch table (array of C). +Arrays of this type are passed on demand from the providers to the +OpenSSL libraries to describe what algorithms the providers provide +implementations of, and with what properties. +Arrays of this type must be terminated with a tuple having function +identity zero and function pointer C. + +The algorithm names and property definitions are defined by the +providers. + +=item C + +This type is a structure that allows passing arbitrary object data +between two parties that have no or very little shared knowledge about +their respective internal structures for that object. +It's normally passed in arrays, where the array is terminated with an +element where all fields are zero (for non-pointers) or C (for +pointers). + +These arrays can be used both to set parameters for some object, and +to request parameters. + +C is further described in L + +=back + +=head1 SEE ALSO + +L + +=head1 HISTORY + +The types described here were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2019 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. + +=cut diff --git a/include/openssl/core.h b/include/openssl/core.h new file mode 100644 index 0000000000..98b58bea69 --- /dev/null +++ b/include/openssl/core.h @@ -0,0 +1,143 @@ +/* + * Copyright 2019 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 + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_CORE_H +# define OSSL_CORE_H + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +/*- + * Base types + * ---------- + * + * These are the types that the OpenSSL core and providers have in common + * to communicate data between them. + */ + +/* + * Dispatch table element. function_id numbers are defined further down, + * see macros with '_FUNC' in their names. + * + * An array of these is always terminated by function_id == 0 + */ +struct ossl_dispatch_st { + int function_id; + void (*function)(void); +}; + +/* + * Other items, essentially an int<->pointer map element. + * + * We make this type distinct from OSSL_DISPATCH to ensure that dispatch + * tables remain tables with function pointers only. + * + * This is used whenever we need to pass things like a table of error reason + * codes <-> reason string maps, parameter name <-> parameter type maps, ... + * + * Usage determines which field works as key if any, rather than field order. + * + * An array of these is always terminated by id == 0 && ptr == NULL + */ +struct ossl_item_st { + unsigned int id; + void *ptr; +}; + +/* + * Type to tie together algorithm name, property definition string and + * the algorithm implementation in the form of a dispatch table. + * + * An array of these is always terminated by algorithm_name == NULL + */ +struct ossl_algorithm_st { + const char *algorithm_name; /* key */ + const char *property_definition; /* key */ + const OSSL_DISPATCH *implementation; +}; + +/* + * Type to pass object data in a uniform way, without exposing the object + * structure. + * + * An array of these is always terminated by key == NULL + */ +struct ossl_param_st { + const char *key; /* the name of the parameter */ + unsigned int data_type; /* declare what kind of content is in buffer */ + void *buffer; /* value being passed in or out */ + size_t buffer_size; /* buffer size */ + size_t *return_size; /* OPTIONAL: address to content size */ +}; + +/* Currently supported OSSL_PARAM data types */ +/* + * OSSL_PARAM_INTEGER and OSSL_PARAM_UNSIGNED_INTEGER + * are arbitrary length and therefore require an arbitrarily sized buffer, + * since they may be used to pass numbers larger than what is natively + * available. + * + * The number must be buffered in native form, i.e. MSB first on B_ENDIAN + * systems and LSB first on L_ENDIAN systems. This means that arbitrary + * native integers can be stored in the buffer, just make sure that the + * buffer size is correct and the buffer itself is properly aligned (for + * example by having the buffer field point at a C integer). + */ +# define OSSL_PARAM_INTEGER 1 +# define OSSL_PARAM_UNSIGNED_INTEGER 2 +/*- + * OSSL_PARAM_REAL + * is a C binary floating point values in native form and alignment. + */ +# define OSSL_PARAM_REAL 3 +/*- + * OSSL_PARAM_UTF8_STRING + * is a printable string. Is expteced to be printed as it is. + */ +# define OSSL_PARAM_UTF8_STRING 4 +/*- + * OSSL_PARAM_OCTET_STRING + * is a string of bytes with no further specification. Is expected to be + * printed as a hexdump. + */ +# define OSSL_PARAM_OCTET_STRING 5 + +/*- + * Pointer flag + * + * This flag can be added to any type to signify that the buffer + * pointer is set to point at a pointer to the data instead of + * pointing directly at the data. + * + * This is more relevant for parameter requests, where the responding + * function doesn't need to copy the data to the provided buffer, but + * sets the provided buffer to point at the actual data instead. + * + * WARNING! Using these is FRAGILE, as it assumes that the actual + * data and its location are constant. + */ +# define OSSL_PARAM_POINTER_FLAG 0x80000000UL + +/* + * Convenience pointer types for strings. + */ +# define OSSL_PARAM_UTF8_STRING_PTR \ + (OSSL_PARAM_UTF8_STRING|OSSL_PARAM_POINTER_FLAG) +# define OSSL_PARAM_OCTET_STRING_PTR \ + (OSSL_PARAM_OCTET_STRING|OSSL_PARAM_POINTER_FLAG) + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h index 44ddfaafd5..9b97e3d3ab 100644 --- a/include/openssl/ossl_typ.h +++ b/include/openssl/ossl_typ.h @@ -181,6 +181,11 @@ typedef struct ossl_store_search_st OSSL_STORE_SEARCH; typedef struct openssl_ctx_st OPENSSL_CTX; +typedef struct ossl_dispatch_st OSSL_DISPATCH; +typedef struct ossl_item_st OSSL_ITEM; +typedef struct ossl_algorithm_st OSSL_ALGORITHM; +typedef struct ossl_param_st OSSL_PARAM; + #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ defined(INTMAX_MAX) && defined(UINTMAX_MAX) typedef intmax_t ossl_intmax_t; diff --git a/util/private.num b/util/private.num index c4a2793410..d8aba4d308 100644 --- a/util/private.num +++ b/util/private.num @@ -32,6 +32,7 @@ GEN_SESSION_CB datatype OPENSSL_Applink external OPENSSL_CTX datatype NAMING_AUTHORITY datatype +OSSL_PARAM datatype OSSL_STORE_CTX datatype OSSL_STORE_INFO datatype OSSL_STORE_LOADER datatype -- 2.34.1