The branch master has been updated via 599429e09a6ddae2d6de2e031bf82817f29f4af0 (commit) via 87e60f09aa8b253c38d457c3560680ba839a6cf2 (commit) via 97abae6a9d94c29314dc28f6d4d6a4171b9b0c38 (commit) from b88a3b10167963e31145e2ba427eb6f55e77f9b8 (commit)
- Log ----------------------------------------------------------------- commit 599429e09a6ddae2d6de2e031bf82817f29f4af0 Author: Matt Caswell <m...@openssl.org> Date: Wed Jun 9 16:10:03 2021 +0100 Add documentation for the newly added OBJ up calls Reviewed-by: Richard Levitte <levi...@openssl.org> Reviewed-by: Tim Hudson <t...@openssl.org> Reviewed-by: Tomas Mraz <to...@openssl.org> Reviewed-by: Paul Dale <pa...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15681) commit 87e60f09aa8b253c38d457c3560680ba839a6cf2 Author: Matt Caswell <m...@openssl.org> Date: Wed Jun 9 15:50:37 2021 +0100 Add a test for the newly added OBJ upcalls Reviewed-by: Richard Levitte <levi...@openssl.org> Reviewed-by: Tim Hudson <t...@openssl.org> Reviewed-by: Tomas Mraz <to...@openssl.org> Reviewed-by: Paul Dale <pa...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15681) commit 97abae6a9d94c29314dc28f6d4d6a4171b9b0c38 Author: Matt Caswell <m...@openssl.org> Date: Wed Jun 9 14:05:26 2021 +0100 Add various OBJ functions as callbacks This enables providers to register new OIDs in the same libcrypto instance as is used by the application. Fixes #15624 Reviewed-by: Richard Levitte <levi...@openssl.org> Reviewed-by: Tim Hudson <t...@openssl.org> Reviewed-by: Tomas Mraz <to...@openssl.org> Reviewed-by: Paul Dale <pa...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15681) ----------------------------------------------------------------------- Summary of changes: crypto/provider_core.c | 37 +++++++ doc/man3/OBJ_nid2obj.pod | 51 ++++++---- doc/man7/provider-base.pod | 34 ++++++- include/openssl/core_dispatch.h | 13 +++ test/build.info | 6 +- test/recipes/{05-test_rand.t => 04-test_upcalls.t} | 9 +- test/upcallstest.c | 112 +++++++++++++++++++++ util/missingcrypto.txt | 1 - 8 files changed, 234 insertions(+), 29 deletions(-) copy test/recipes/{05-test_rand.t => 04-test_upcalls.t} (80%) create mode 100644 test/upcallstest.c diff --git a/crypto/provider_core.c b/crypto/provider_core.c index c6a8fa3f26..4c423a6bda 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -1543,6 +1543,8 @@ static OSSL_FUNC_core_vset_error_fn core_vset_error; static OSSL_FUNC_core_set_error_mark_fn core_set_error_mark; static OSSL_FUNC_core_clear_last_error_mark_fn core_clear_last_error_mark; static OSSL_FUNC_core_pop_error_to_mark_fn core_pop_error_to_mark; +static OSSL_FUNC_core_obj_add_sigid_fn core_obj_add_sigid; +static OSSL_FUNC_core_obj_create_fn core_obj_create; #endif static const OSSL_PARAM *core_gettable_params(const OSSL_CORE_HANDLE *handle) @@ -1673,6 +1675,39 @@ static int core_pop_error_to_mark(const OSSL_CORE_HANDLE *handle) { return ERR_pop_to_mark(); } + +static int core_obj_add_sigid(const OSSL_CORE_HANDLE *prov, + const char *sign_name, const char *digest_name, + const char *pkey_name) +{ + int sign_nid = OBJ_txt2nid(sign_name); + int digest_nid = OBJ_txt2nid(digest_name); + int pkey_nid = OBJ_txt2nid(pkey_name); + + if (sign_nid == NID_undef) + return 0; + + /* + * Check if it already exists. This is a success if so (even if we don't + * have nids for the digest/pkey) + */ + if (OBJ_find_sigid_algs(sign_nid, NULL, NULL)) + return 1; + + if (digest_nid == NID_undef + || pkey_nid == NID_undef) + return 0; + + return OBJ_add_sigid(sign_nid, digest_nid, pkey_nid); +} + +static int core_obj_create(const OSSL_CORE_HANDLE *prov, const char *oid, + const char *sn, const char *ln) +{ + /* Check if it already exists and create it if not */ + return OBJ_txt2nid(oid) != NID_undef + || OBJ_create(oid, sn, ln) != NID_undef; +} #endif /* FIPS_MODULE */ /* @@ -1737,6 +1772,8 @@ static const OSSL_DISPATCH core_dispatch_[] = { (void (*)(void))provider_up_ref_intern }, { OSSL_FUNC_PROVIDER_FREE, (void (*)(void))provider_free_intern }, + { OSSL_FUNC_CORE_OBJ_ADD_SIGID, (void (*)(void))core_obj_add_sigid }, + { OSSL_FUNC_CORE_OBJ_CREATE, (void (*)(void))core_obj_create }, #endif { 0, NULL } }; diff --git a/doc/man3/OBJ_nid2obj.pod b/doc/man3/OBJ_nid2obj.pod index 9089f95622..54b751f6df 100644 --- a/doc/man3/OBJ_nid2obj.pod +++ b/doc/man3/OBJ_nid2obj.pod @@ -5,7 +5,7 @@ i2t_ASN1_OBJECT, OBJ_length, OBJ_get0_data, OBJ_nid2obj, OBJ_nid2ln, OBJ_nid2sn, OBJ_obj2nid, OBJ_txt2nid, OBJ_ln2nid, OBJ_sn2nid, OBJ_cmp, -OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup +OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup, OBJ_add_sigid - ASN1 object utility functions =head1 SYNOPSIS @@ -35,6 +35,8 @@ OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup size_t OBJ_length(const ASN1_OBJECT *obj); const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj); + int OBJ_add_sigid(int signid, int dig_id, int pkey_id); + Deprecated since OpenSSL 1.1.0, can be hidden entirely by defining B<OPENSSL_API_COMPAT> with a suitable version value, see L<openssl_user_macros(7)>: @@ -52,46 +54,53 @@ are available as defined constants. For the functions below, application code should treat all returned values -- OIDs, NIDs, or names -- as constants. -OBJ_nid2obj(), OBJ_nid2ln() and OBJ_nid2sn() convert the NID B<n> to +OBJ_nid2obj(), OBJ_nid2ln() and OBJ_nid2sn() convert the NID I<n> to an ASN1_OBJECT structure, its long name and its short name respectively, or B<NULL> if an error occurred. OBJ_obj2nid(), OBJ_ln2nid(), OBJ_sn2nid() return the corresponding NID -for the object B<o>, the long name <ln> or the short name <sn> respectively +for the object I<o>, the long name I<ln> or the short name I<sn> respectively or NID_undef if an error occurred. -OBJ_txt2nid() returns NID corresponding to text string <s>. B<s> can be +OBJ_txt2nid() returns NID corresponding to text string I<s>. I<s> can be a long name, a short name or the numerical representation of an object. -OBJ_txt2obj() converts the text string B<s> into an ASN1_OBJECT structure. -If B<no_name> is 0 then long names and short names will be interpreted -as well as numerical forms. If B<no_name> is 1 only the numerical form +OBJ_txt2obj() converts the text string I<s> into an ASN1_OBJECT structure. +If I<no_name> is 0 then long names and short names will be interpreted +as well as numerical forms. If I<no_name> is 1 only the numerical form is acceptable. -OBJ_obj2txt() converts the B<ASN1_OBJECT> B<a> into a textual representation. -The representation is written as a null terminated string to B<buf> -at most B<buf_len> bytes are written, truncating the result if necessary. -The total amount of space required is returned. If B<no_name> is 0 then +OBJ_obj2txt() converts the B<ASN1_OBJECT> I<a> into a textual representation. +The representation is written as a null terminated string to I<buf> +at most I<buf_len> bytes are written, truncating the result if necessary. +The total amount of space required is returned. If I<no_name> is 0 then if the object has a long or short name then that will be used, otherwise -the numerical form will be used. If B<no_name> is 1 then the numerical +the numerical form will be used. If I<no_name> is 1 then the numerical form will always be used. -i2t_ASN1_OBJECT() is the same as OBJ_obj2txt() with the B<no_name> set to zero. +i2t_ASN1_OBJECT() is the same as OBJ_obj2txt() with the I<no_name> set to zero. -OBJ_cmp() compares B<a> to B<b>. If the two are identical 0 is returned. +OBJ_cmp() compares I<a> to I<b>. If the two are identical 0 is returned. -OBJ_dup() returns a copy of B<o>. +OBJ_dup() returns a copy of I<o>. -OBJ_create() adds a new object to the internal table. B<oid> is the -numerical form of the object, B<sn> the short name and B<ln> the +OBJ_create() adds a new object to the internal table. I<oid> is the +numerical form of the object, I<sn> the short name and I<ln> the long name. A new NID is returned for the created object in case of success and NID_undef in case of failure. -OBJ_length() returns the size of the content octets of B<obj>. +OBJ_length() returns the size of the content octets of I<obj>. -OBJ_get0_data() returns a pointer to the content octets of B<obj>. +OBJ_get0_data() returns a pointer to the content octets of I<obj>. The returned pointer is an internal pointer which B<must not> be freed. +OBJ_add_sigid() creates a new composite "Signature Algorithm" that associates a +given NID with two other NIDs - one representing the underlying signature +algorithm and the other representing a digest algorithm to be used in +conjunction with it. I<signid> represents the NID for the composite "Signature +Algorithm", I<dig_id> is the NID for the digest algorithm and I<pkey_id> is the +NID for the underlying signature algorithm. + OBJ_cleanup() releases any resources allocated by creating new objects. =head1 NOTES @@ -141,6 +150,8 @@ on error. OBJ_obj2nid(), OBJ_ln2nid(), OBJ_sn2nid() and OBJ_txt2nid() return a NID or B<NID_undef> on error. +OBJ_add_sigid() returns 1 on success or 0 on error. + =head1 EXAMPLES Create an object for B<commonName>: @@ -166,7 +177,7 @@ Create a new object directly: OBJ_obj2txt() is awkward and messy to use: it doesn't follow the convention of other OpenSSL functions where the buffer can be set to B<NULL> to determine the amount of data that should be written. -Instead B<buf> must point to a valid buffer and B<buf_len> should +Instead I<buf> must point to a valid buffer and I<buf_len> should be set to a positive value. A buffer length of 80 should be more than enough to handle any OID encountered in practice. diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod index 7ade4a1c8e..0eb2f5d243 100644 --- a/doc/man7/provider-base.pod +++ b/doc/man7/provider-base.pod @@ -31,6 +31,11 @@ provider-base void core_vset_error(const OSSL_CORE_HANDLE *handle, uint32_t reason, const char *fmt, va_list args); + int core_obj_add_sigid(const OSSL_CORE_HANDLE *prov, const char *sign_name, + const char *digest_name, const char *pkey_name); + int core_obj_create(const OSSL_CORE_HANDLE *handle, const char *oid, + const char *sn, const char *ln); + /* * Some OpenSSL functionality is directly offered to providers via * dispatch @@ -144,6 +149,8 @@ provider): core_new_error OSSL_FUNC_CORE_NEW_ERROR core_set_error_debug OSSL_FUNC_CORE_SET_ERROR_DEBUG core_vset_error OSSL_FUNC_CORE_VSET_ERROR + core_obj_add_sigid OSSL_FUNC_CORE_OBJ_ADD_SIGID + core_obj_create OSSL_FUNC_CORE_OBJ_CREATE CRYPTO_malloc OSSL_FUNC_CRYPTO_MALLOC CRYPTO_zalloc OSSL_FUNC_CRYPTO_ZALLOC CRYPTO_memdup OSSL_FUNC_CRYPTO_MEMDUP @@ -250,16 +257,37 @@ This corresponds to the OpenSSL function L<ERR_vset_error(3)>. =back +The core_obj_create() function registers a new OID and associated short name +I<sn> and long name I<ln> for the given I<handle>. It is similar to the OpenSSL +function L<OBJ_create(3)> except that it returns 1 on success or 0 on failure. +It will treat as success the case where the OID already exists (even if the +short name I<sn> or long name I<ln> provided as arguments differ from those +associated with the existing OID, in which case the new names are not +associated). + +The core_obj_add_sigid() function registers a new composite signature algorithm +(I<sign_name>) consisting of an underlying signature algorithm (I<pkey_name>) +and digest algorithm (I<digest_name>) for the given I<handle>. It assumes that +the OIDs for the composite signature algorithm as well as for the underlying +signature and digest algorithms are either already known to OpenSSL or have been +registered via a call to core_obj_create(). It corresponds to the OpenSSL +function L<OBJ_add_sigid(3)>, except that the objects are identified by name +rather than a numeric NID. Any name (OID, short name or long name) can be used +to identify the object. It will treat as success the case where the composite +signature algorithm already exists (even if registered against a different +underlying signature or digest algorithm). It returns 1 on success or 0 on +failure. + CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_memdup(), CRYPTO_strdup(), CRYPTO_strndup(), CRYPTO_free(), CRYPTO_clear_free(), CRYPTO_realloc(), CRYPTO_clear_realloc(), CRYPTO_secure_malloc(), CRYPTO_secure_zalloc(), CRYPTO_secure_free(), CRYPTO_secure_clear_free(), CRYPTO_secure_allocated(), BIO_new_file(), BIO_new_mem_buf(), BIO_read_ex(), BIO_write_ex(), BIO_up_ref(), -BIO_free(), BIO_vprintf(), BIO_vsnprintf(), OPENSSL_cleanse() -and OPENSSL_hexstr2buf() correspond exactly to the public functions with +BIO_free(), BIO_vprintf(), BIO_vsnprintf(), OPENSSL_cleanse() and +OPENSSL_hexstr2buf() correspond exactly to the public functions with the same name. As a matter of fact, the pointers in the B<OSSL_DISPATCH> -array are direct pointers to those public functions. Note that the BIO +array are typically direct pointers to those public functions. Note that the BIO functions take an B<OSSL_CORE_BIO> type rather than the standard B<BIO> type. This is to ensure that a provider does not mix BIOs from the core with BIOs used on the provider side (the two are not compatible). diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 2a46c10123..99fcda0020 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -91,6 +91,19 @@ OSSL_CORE_MAKE_FUNC(int, core_clear_last_error_mark, # define OSSL_FUNC_CORE_POP_ERROR_TO_MARK 10 OSSL_CORE_MAKE_FUNC(int, core_pop_error_to_mark, (const OSSL_CORE_HANDLE *prov)) + +/* Functions to access the OBJ database */ + +#define OSSL_FUNC_CORE_OBJ_ADD_SIGID 11 +#define OSSL_FUNC_CORE_OBJ_CREATE 12 + +OSSL_CORE_MAKE_FUNC(int, core_obj_add_sigid, + (const OSSL_CORE_HANDLE *prov, const char *sign_name, + const char *digest_name, const char *pkey_name)) +OSSL_CORE_MAKE_FUNC(int, core_obj_create, + (const OSSL_CORE_HANDLE *prov, const char *oid, + const char *sn, const char *ln)) + /* Memory allocation, freeing, clearing. */ #define OSSL_FUNC_CRYPTO_MALLOC 20 OSSL_CORE_MAKE_FUNC(void *, diff --git a/test/build.info b/test/build.info index bc543bd761..eeb2845638 100644 --- a/test/build.info +++ b/test/build.info @@ -56,7 +56,7 @@ IF[{- !$disabled{tests} -}] sysdefaulttest errtest ssl_ctx_test gosttest \ context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ keymgmt_internal_test hexstr_test provider_status_test defltfips_test \ - bio_readbuffer_test user_property_test pkcs7_test + bio_readbuffer_test user_property_test pkcs7_test upcallstest IF[{- !$disabled{'deprecated-3.0'} -}] PROGRAMS{noinst}=enginetest @@ -133,6 +133,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[tls13ccstest]=../include ../apps/include DEPEND[tls13ccstest]=../libcrypto ../libssl libtestutil.a + SOURCE[upcallstest]=upcallstest.c + INCLUDE[upcallstest]=../include ../apps/include + DEPEND[upcallstest]=../libcrypto libtestutil.a + SOURCE[user_property_test]=user_property_test.c INCLUDE[user_property_test]=../include ../apps/include DEPEND[user_property_test]=../libcrypto libtestutil.a diff --git a/test/recipes/05-test_rand.t b/test/recipes/04-test_upcalls.t similarity index 80% copy from test/recipes/05-test_rand.t copy to test/recipes/04-test_upcalls.t index 750b1a28e8..6e5dbd329f 100644 --- a/test/recipes/05-test_rand.t +++ b/test/recipes/04-test_upcalls.t @@ -6,13 +6,14 @@ # in the file LICENSE in the source distribution or at # https://www.openssl.org/source/license.html + use strict; use warnings; + +use OpenSSL::Test::Simple; use OpenSSL::Test; use OpenSSL::Test::Utils; -plan tests => 2; -setup("test_rand"); +setup("test_upcalls"); -ok(run(test(["drbgtest"]))); -ok(run(test(["rand_status_test"]))); +simple_test("test_upcalls", "upcallstest"); diff --git a/test/upcallstest.c b/test/upcallstest.c new file mode 100644 index 0000000000..01e4e95237 --- /dev/null +++ b/test/upcallstest.c @@ -0,0 +1,112 @@ +/* + * Copyright 2021 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 + */ + +#include <openssl/objects.h> +#include <openssl/crypto.h> +#include <openssl/provider.h> +#include "testutil.h" + +static const OSSL_ALGORITHM *obj_query(void *provctx, int operation_id, + int *no_cache) +{ + *no_cache = 0; + return NULL; +} + +static const OSSL_DISPATCH obj_dispatch_table[] = { + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))obj_query }, + { 0, NULL } +}; + +static OSSL_FUNC_core_obj_add_sigid_fn *c_obj_add_sigid = NULL; +static OSSL_FUNC_core_obj_create_fn *c_obj_create = NULL; + +#define SIG_OID "1.3.6.1.4.1.16604.998877.1" +#define SIG_SN "my-sig" +#define SIG_LN "my-sig-long" +#define DIGEST_OID "1.3.6.1.4.1.16604.998877.2" +#define DIGEST_SN "my-digest" +#define DIGEST_LN "my-digest-long" +#define SIGALG_OID "1.3.6.1.4.1.16604.998877.3" +#define SIGALG_SN "my-sigalg" +#define SIGALG_LN "my-sigalg-long" + +static int obj_provider_init(const OSSL_CORE_HANDLE *handle, + const OSSL_DISPATCH *in, + const OSSL_DISPATCH **out, + void **provctx) +{ + *provctx = (void *)handle; + *out = obj_dispatch_table; + + for (; in->function_id != 0; in++) { + switch (in->function_id) { + case OSSL_FUNC_CORE_OBJ_ADD_SIGID: + c_obj_add_sigid = OSSL_FUNC_core_obj_add_sigid(in); + break; + case OSSL_FUNC_CORE_OBJ_CREATE: + c_obj_create = OSSL_FUNC_core_obj_create(in); + break; + break; + default: + /* Just ignore anything we don't understand */ + break; + } + } + + if (!c_obj_create(handle, DIGEST_OID, DIGEST_SN, DIGEST_LN) + || !c_obj_create(handle, SIG_OID, SIG_SN, SIG_LN) + || !c_obj_create(handle, SIGALG_OID, SIGALG_SN, SIGALG_LN)) + return 0; + + if (!c_obj_add_sigid(handle, SIGALG_OID, DIGEST_SN, SIG_LN)) + return 0; + + return 1; +} + +static int obj_create_test(void) +{ + OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); + OSSL_PROVIDER *objprov = NULL; + int sigalgnid, digestnid, signid; + int testresult = 0; + + if (!TEST_ptr(libctx)) + goto err; + + if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "obj-prov", + obj_provider_init)) + || !TEST_ptr(objprov = OSSL_PROVIDER_load(libctx, "obj-prov"))) + goto err; + + /* Check that the provider created the OIDs/NIDs we expected */ + sigalgnid = OBJ_txt2nid(SIGALG_OID); + if (!TEST_int_ne(sigalgnid, NID_undef) + || !TEST_true(OBJ_find_sigid_algs(sigalgnid, &digestnid, &signid)) + || !TEST_int_ne(digestnid, NID_undef) + || !TEST_int_ne(signid, NID_undef) + || !TEST_int_eq(digestnid, OBJ_sn2nid(DIGEST_SN)) + || !TEST_int_eq(signid, OBJ_ln2nid(SIG_LN))) + goto err; + + testresult = 1; + err: + OSSL_PROVIDER_unload(objprov); + OSSL_LIB_CTX_free(libctx); + return testresult; +} + +int setup_tests(void) +{ + + ADD_TEST(obj_create_test); + + return 1; +} diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 67bfc7859d..f01b47162d 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -729,7 +729,6 @@ OBJ_NAME_init(3) OBJ_NAME_new_index(3) OBJ_NAME_remove(3) OBJ_add_object(3) -OBJ_add_sigid(3) OBJ_bsearch_(3) OBJ_bsearch_ex_(3) OBJ_create_objects(3)