Re: Migrating to 3.x - how to handle PKEY types and Sig Algorithms?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 22/08/2023 06:20, Dr. Pala wrote:
Hello OpenSSL Community,

We are in the process of upgrading the LibPKI project to use the OSSL 3.x instead of the OSSL 1.1.1x that we are using today ... and we can use some help. Specifically, we noticed some inconsistent behavior when porting from the 1.1.1x version and we hope you can */_help us finding what are we doing wrong and what is the right way of doing things_/* in the new "providers" world :)

The original code, when compiled against the OpenSSL 1.1.1x branch, works correctly... However, with the 3.x version, things do not behave the same way and our applications fail when compiled/linked against it. Our setting is OpenSSL 3.x with the OQS provider installed. The application successfully loads the 'default' provider first, then the 'legacy', and finally the 'oqsprovider' one

Here's some of my initial questions:

  * *EVP_PKEY_id() and EVP_PKEY_type()* are not reliable anymore with
    providers (e.g., for "dilithium2" from the OQS provider they all
    return '0'). What shall we use to get the type of a PKEY structure
    (i.e., this is an "RSA" key or a "Falcon512" one) ? Currently, to
    address the issue with *EVP_PKEY_id*(), we are getting the name from
    the pkey (pkey_name = *EVP_PKEY_get0_type_name*(pkey) - Example
    Code:
    https://github.com/openca/libpki/blob/00b1fbb434dbf1ffd09fcad5ddfb7ceb7eeaba6a/src/openssl/pki_keypair.c#L350) and then converting that into an ID (*OBJ_sn2nid*(pkey_name)). If that is the supposed way of doing things (I really doubt it, we just used it as an hack), /_how do we get the type of key from the ID_ (i.e., the functionality provided via*EVP_PKEY_type()*/) ? Shall we... string/mem compare when *EVP_PKEY_type*() returns 0? In other words, how do I know an EVP_KEY is an RSA one instead of a dilithium or falcon one (e.g., EVP_PKEY_type() vs. EVP_PKEY_EC, EVP_PKEY_RSA, etc.)? Example Code: https://github.com/openca/libpki/blob/28c510193735e6a68671bfb4cb4e66589a1fd9d0/src/drivers/hsm_main.c#L530


We use EVP_PKEY_is_a() extensively internally to check whether a pkey is a particular type.

https://www.openssl.org/docs/man3.1/man3/EVP_PKEY_is_a.html

  * *OBJ_add_sigid() and OBJ_find_sigid_by_algs()* do not seem to work
    as usual. Specifically, with the above configuration (i.e., with the
    {default, legacy, oqsprovider} providers loaded), during the
    initialization of the library/application, we try to add a bunch of
    OIDs for new signature types that sometimes seem to persist and
    sometimes they do not. For example,  at startup _/we add a series of
    OIDs for hash-n-sign with dilithium2/_. We do this by creating the
    new signature OIDs with *OBJ_create*() first, and then we use those
    new IDs with the *OBJ_add_sigid*() with different hash identifiers.
    When we use the *OBJ_find_sigid_by_algs()* function right after
    adding the signature ID and, for some algorithms, the function fails
    to find it. For example, we can add a DILITHIUM2-SHA3_256 signature
    correctly, but the same code fails to retrieve the
    DILITHIUM2-SHA3_512. Even more strange is the fact that if we try to
    find sigid that were found during initialization, we now fail for no
    apparent reason. Example Code:
    https://github.com/openca/libpki/blob/28c510193735e6a68671bfb4cb4e66589a1fd9d0/src/openssl/pki_oid_defs.c#L622

This sounds like it should work, so I don't know why you are seeing odd behaviour. Perhaps raise a github issue for this?

One thing that does spring to mind is that I know that oqsprovider already registers various sigid OIDs - so plausibly there is some kind of issue caused by that:

https://github.com/open-quantum-safe/oqs-provider/blob/b6da1e97b7180a779981d1b0bfa0ab2cd723066d/oqsprov/oqsprov.c#L592-L619

https://github.com/open-quantum-safe/oqs-provider/blob/b6da1e97b7180a779981d1b0bfa0ab2cd723066d/oqsprov/oqsprov.c#L45-L71


  * *How to replace PKEY/ASN1_PKEY methods.* In our library, we
    currently provide a new type of algorithm (i.e., Composite Crypto)
    via a PKEY/ASN1_PKEY combination that we inject at initialization
    time via the *EVP_PKEY_meth_add0*() and *EVP_PKEY_asn1_add0*(). What
    is the equivalent functions to use under the providers' paradigm? In
    other words, do we need to generate a separate provider object or
    can we inject it programmatically? Example Code:
    https://github.com/openca/libpki/blob/28c510193735e6a68671bfb4cb4e66589a1fd9d0/src/openssl/composite/composite_init.c#L326

Yes, you would need a new provider to add a new algorithm (although the old approach should still *work* - even though it is deprecated). You can just add a "built-in" one if you want (so no need to create a separate .so file for it - it can just live in your application code)

https://www.openssl.org/docs/man3.1/man3/OSSL_PROVIDER_add_builtin.html


Start by looking at the page for general information for provider authors:

https://www.openssl.org/docs/man3.1/man7/provider.html

Richard Levitte has a "toy" provider example which you can look at here:

https://github.com/provider-corner/vigenere/blob/main/vigenere.c

To implement an algorithm yourself you need to first determine what kind of algorithm it is (e.g. cipher, signature, key-exchange, etc) and then implement the appropriate provider functions for that algorithm. To implement a new signature algorithm you would need to implement the signature functions as well as the key management functions. E.g. see

https://www.openssl.org/docs/man3.1/man7/provider-signature.html

and

https://www.openssl.org/docs/man3.1/man7/provider-keymgmt.html



  * *EVP_PKEY_get0() fails when called from within the pkey_bits()
    function of the EVP_PKEY_ASN1_METHOD*. Specifically, when the
    pkey_bits() function is called with the parameter of type `const
    EVP_PKEY *pk`, the EVP_PKEY_get0(pk) function always returns NULL.
    What are we supposed to use to retrieve the internal key structure?
    Example Code:
    https://github.com/openca/libpki/blob/28c510193735e6a68671bfb4cb4e66589a1fd9d0/src/openssl/composite/composite_ameth.c#L963


EVP_PKEY_get0() returns a pointer to the legacy key structure (e.g. RSA, DSA, DH, EC_KEY, etc). It won't work if you call it on a provider based EVP_PKEY (returns NULL) but you can call the typed equivalents, e.g. EVP_PKEY_get0_RSA(). In that case it gives you a cached *copy* of the legacy key (the real key is held in the provider and is inaccessibly directly to the application).

It's unclear to me from your question whether you are talking about your *own* EVP_PKEY type, i.e. one you've defined yourself that does not use a provider. If so then this should still work as it did before, i.e. as long as data has been assigned to the key via EVP_PKEY_assign() then it should be available via a subsequent call to EVP_PKEY_get0().


Matt


The migration to the 3.x has some interesting differences that are quite challenging, thanks everybody for any help you can provide :)

Cheers,
Max

--
Best Regards,
Massimiliano Pala, Ph.D.
OpenCA Labs Director
OpenCA Logo



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux