Skip to content

Add design document for LMS.#22357

Closed
slontis wants to merge 3 commits intoopenssl:masterfrom
slontis:lms_design
Closed

Add design document for LMS.#22357
slontis wants to merge 3 commits intoopenssl:masterfrom
slontis:lms_design

Conversation

@slontis
Copy link
Member

@slontis slontis commented Oct 12, 2023

Checklist
  • documentation is added or updated
  • tests are added or updated

@slontis slontis added branch: master Applies to master branch approval: review pending This pull request needs review by a committer approval: otc review pending hold: discussion The community needs to establish a consensus how to move forward with the issue or PR labels Oct 12, 2023
@slontis
Copy link
Member Author

slontis commented Oct 12, 2023

Put a hold on this to discuss within the OTC..
In particular the new API and what is supported/not supported need to be discussed.

@t8m t8m added the triaged: design The issue/pr deals with a design document label Oct 13, 2023
Comment on lines +113 to +123
__owur int EVP_DigestVerifyHBSInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const char *mdname,
OSSL_LIB_CTX *libctx,
const char *props, EVP_PKEY *pkey,
const OSSL_PARAM params[],
const unsigned char *sig,
size_t siglen);
/* Alias: since the function signature is identical */
#define EVP_DigestVerifyHBSUpdate(a,b,c) EVP_DigestVerifyUpdate(a,b,c)

__owur int EVP_DigestVerifyHBSFinal(EVP_MD_CTX *ctx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this proposal more, except for:

  1. It should not be called with HBS in the name as this is generic call for any possible future signature schemes and not tightly coupled to hash based signatures.
  2. Why do we need both pkey as input parameter and ppctx as output one? Would it be better to have only one of them. I'm unsure which one of them though.
  3. How does it play with this proposal https://github.com/openssl/openssl/blob/master/doc/designs/fetching-composite-algorithms.md

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I was trying to make the Init and FInal calls match... using a matching tag.. I dont care what the tag is.
  2. It is the same API as the existing one with sig added to the end.
  3. We would either need yet another function, or pass the signature in as an OSSL_PARAM.. We dont actually use EVP_SIGNATURE_fetch() normally currently, so this seems a bit early to be adding the EVP_SIGNATURE one.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In PKCS #11 we made the new API C_VerifySignature. Maybe EVP_SignatureVerifyInit?

We also said if you support the C_VerifySignature interface you need to support it for all the signing algorithms (basically they can just store the signature at init time and use the stored signature in Final). The form that takes the signature at init time is more general (for the signature implementers... all signatures can support this form), but less general for the application (applications that don't have the signature until the end can't use signature first without buffering).

Anyway I'm not familiar enough with normal openssl spellings, so you need to moderate my comments with openssl usage

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to make the Init and FInal calls match... using a matching tag.. I dont care what the tag is.

Definitely needs a different name.

We would either need yet another function, or pass the signature in as an OSSL_PARAM.. We dont actually use EVP_SIGNATURE_fetch() normally currently, so this seems a bit early to be adding the EVP_SIGNATURE one.

I don't see why?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do_sigver_init() does this internally. Not much else needs the EVP_SIGNATURE_fetch()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the 3rd option (passing EVP_SIGNATURE) will become available with the effort mentioned... and it's now underway, so it wouldn't be a bad idea to collaborate around designing the API. If we're reusing do_sigver_init() (not sure why we'd have to), it can be modified to fit.

Copy link
Member Author

@slontis slontis Nov 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err how/where can I comment on the composite algorithm design document?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can start a discussion or raise an issue... or wait for the draft PR I'm currently preparing.

Do note that I'm currently exploring EVP_PKEY_sign() / EVP_PKEY_verify() and associated functions rather than EVP_DigestSign and EVP_DigestVerify function groups.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I think of it, I think I'll start with a design document, and we can discuss that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #22672

Comment on lines +181 to +189
In order to support the new API calls there should be 2 additional dispatch
functions..

OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_pbs_init,
(void *ctx, const char *mdname, void *provkey,
const OSSL_PARAM params[],
const unsigned char *sig, size_t siglen))
OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_pbs_final,
(void *ctx))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: It should be possible to implement this init_with_signature function in terms of the existing APIs for those algorithms that do not have this new provided function. We would just cache the signature and use it in the final call. That's another reason why the EVP function should not be named with HBS in the name as this can be a fully generic call supported even with older signature algorithms on older providers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think returning not supported would be sufficient..

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's likely the new API is the new normal. All they NIST signature algorithms are defined needing the signature first. It provides better signature guarantees. Protocol people don't like it because protocols often put the signature at the end. My guess is protocols with end up doing single shot where they use the full algorithm to sign their preselected hashes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing the backwards compat approach seems desirable to me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree

@simo5
Copy link
Contributor

simo5 commented Oct 13, 2023

May I ask for a requirement that if any signing operation is implemented that it can be disabled at built time, leaving only verification operations available?

LMS is something that should never been implemented in a generic software system, NIST and NSA as well recommend that LMS and XMSS signatures are implemented only in Hardware, and the reason is that duplicating state is catastrophic, and in software duplicating state is as simple as restarting a machine after a crash where updates didn't get to disk, or copying around files.

We do not want to give our users a knife that has cyanide laced razor blades for a handle.

@slontis
Copy link
Member Author

slontis commented Oct 15, 2023

May I ask for a requirement that if any signing operation is implemented that it can be disabled at built time, leaving only verification operations available?

LMS is something that should never been implemented in a generic software system, NIST and NSA as well recommend that LMS and XMSS signatures are implemented only in Hardware, and the reason is that duplicating state is catastrophic, and in software duplicating state is as simple as restarting a machine after a crash where updates didn't get to disk, or copying around files.

We do not want to give our users a knife that has cyanide laced razor blades for a handle.

There is no intention of implementing the sign or private key generation

Add a Init_ex function and leave the Final the same.

i.e.
EVP_DigestVerifyInit_ex3(..., const unsigned char *sig, size_t siglen);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@t8m mentioned _with_signature for the libcrypto<->provider interface. Could that be a good idea here as well, instead of yet another ex?

- Support one shot operations:
Using existing EVP_DigestVerifyInit_ex + EVP_DigestVerify calls
- Dont support streaming via existing interface:
EVP_DigestVerifyInit_ex + EVP_DigestVerifyUpdate + EVP_DigestVerifyFinal.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are good choices.

sufficient for this use case. A separate LMS signature dispatch table could be
added if this is ever required.
- CMS and X509 support - this may be added at a later date.
- Implementing Extended Merkle signature scheme (XMSS) is a separate effort.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. HSS with a single tree is basically LMS. No one uses bare LMS, so that's fine. Definitely good not so support signatures and key gen. When implementing XMSS, it's possible to use some common code, but LMS and XMSS is just different enough that it's probably best to have separate implementations (said by someone who has made the combined implementation as a testbed).


Pass the signature after the init via an OSSL_PARAM.


Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about both of theses type of schemes in PKCS #11: 1) adding just a new init function that takes the signature and 2) adding the signature to the mechanism parameter (the equivalent of OSSL_PARAM). Both of these generated the question of what do you return on Final if the signature is included; a) failure if it's not null, b) failure if it's not null and doesn't match, or c) undefined if the application includes the signature. In the end having a complete new set of C_VerifySignatureXXXX functions got rid of all those issues since the Final versions won't have a signature. We made the C_VerifySignatureUpdate a separate function, but your proposal to make it a #define for the normal update is actually good (so applications that need to support both don't have to keep track of which to call the correct update function.

@slontis
Copy link
Member Author

slontis commented Oct 16, 2023

Thanks for your input @rjrelyea

@t8m t8m added tests: exempted The PR is exempt from requirements for testing and removed hold: discussion The community needs to establish a consensus how to move forward with the issue or PR labels Oct 17, 2023
const char *props, EVP_PKEY *pkey,
const OSSL_PARAM params[],
const unsigned char *sig,
size_t siglen);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using EVP_MD_CTX as the primary ctx for EVP_DigestVerify* was a design mistake IMO. The output param of an EVP_PKEY_CTX * is just horrible. We had to hack around this mistake when we moved all this stuff to providers.

This could be an opportunity to do this properly and just make this pass in an EVP_PKEY_CTX.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That idea also ties in on this design: https://github.com/openssl/openssl/blob/master/doc/designs/fetching-composite-algorithms.md

It's actually a good idea, and aligns better with how other (non-PKEY) operations work.

Comment on lines +113 to +123
__owur int EVP_DigestVerifyHBSInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const char *mdname,
OSSL_LIB_CTX *libctx,
const char *props, EVP_PKEY *pkey,
const OSSL_PARAM params[],
const unsigned char *sig,
size_t siglen);
/* Alias: since the function signature is identical */
#define EVP_DigestVerifyHBSUpdate(a,b,c) EVP_DigestVerifyUpdate(a,b,c)

__owur int EVP_DigestVerifyHBSFinal(EVP_MD_CTX *ctx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to make the Init and FInal calls match... using a matching tag.. I dont care what the tag is.

Definitely needs a different name.

We would either need yet another function, or pass the signature in as an OSSL_PARAM.. We dont actually use EVP_SIGNATURE_fetch() normally currently, so this seems a bit early to be adding the EVP_SIGNATURE one.

I don't see why?


For the EVP_DigestVerifyFinal pass a NULL signature.
The signature length must be zero in this case or an error will occur.
If a signature is passed should it just ignore the value?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this proposal more that proposal 1. (Unless we go with my suggestion to use EVP_PKEY_CTX...in which case it really does need a new name).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this proposal more.

const unsigned char *sig,
size_t siglen);
/* Alias: since the function signature is identical */
#define EVP_DigestVerifyHBSUpdate(a,b,c) EVP_DigestVerifyUpdate(a,b,c)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we've done this before - but I think this is very confusing and causes potential problems in the future if we ever want them to do different things.

Comment on lines +181 to +189
In order to support the new API calls there should be 2 additional dispatch
functions..

OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_pbs_init,
(void *ctx, const char *mdname, void *provkey,
const OSSL_PARAM params[],
const unsigned char *sig, size_t siglen))
OSSL_CORE_MAKE_FUNC(int, signature_digest_verify_pbs_final,
(void *ctx))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing the backwards compat approach seems desirable to me.


As well as using the test vectors supplied in [1] and [6], additional interop tests
should be performed by generating data using other toolkits
(such as Ciso or Bouncy Castle).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these implement the sign side?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the RFC originated from Cisco they needed to write a reference implementation. BC has the sign side. The Java SDK only implements the verify.. In my opinion it is asking for trouble implementing stateful signing (which is why it is supposed to be done in hardware only)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomato42
Copy link
Contributor

I would go even further that what Simo said.

I consider not only presence of signature creation a problem, but signature verification too.

Safe use of any stateful hash based signature formats absolutely and unequivocally depends on the signature operation being performed in hardware. Doing it in a way that allows for disaster recovery, over 10, or 20+ years of use, is orders of magnitude harder still. That means that there will be very few originators of such signatures. Which means they will be used in very few places.

In case we have widely deployed implementations that can verify such signatures, there definitely will be people that don't know better and actually implement and use signature creation in software. So, just presence of signature verification is an incentive to do the wrong thing.

As such, I don't think openssl should ship with any code that can do LMS verification. It can have support for providers that support it (to support the hardware modules), but I think including verification code is a mistake. If there are specific users asking for it, it should be a separate provider module, not part of OpenSSL proper. Users should not be able to expect that LMS is supported out of the box.

See also: Nuclear Non-proliferation Treaty

@slontis
Copy link
Member Author

slontis commented Nov 21, 2023

I would go even further that what Simo said.

I consider not only presence of signature creation a problem, but signature verification too.

Safe use of any stateful hash based signature formats absolutely and unequivocally depends on the signature operation being performed in hardware. Doing it in a way that allows for disaster recovery, over 10, or 20+ years of use, is orders of magnitude harder still. That means that there will be very few originators of such signatures. Which means they will be used in very few places.

In case we have widely deployed implementations that can verify such signatures, there definitely will be people that don't know better and actually implement and use signature creation in software. So, just presence of signature verification is an incentive to do the wrong thing.

There is no state associated with the signature verification, so I dont agree. There are many things in crypto that you can do wrong if you dont know what you are doing.
@t-j-h Would you care to respond to why we should do HSS signature and key generation in OpenSSL.

@tomato42
Copy link
Contributor

My point is that there is a difference between "it's hard to do it correctly" and "there's literally at most double digit number of corporations in the world that will be able to do a production deployment correctly".

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/otc but the last update was 61 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/otc but the last update was 91 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/otc but the last update was 122 days ago

@levitte
Copy link
Member

levitte commented Sep 9, 2024

Considering the recent additions to the EVP_PKEY_ sign and verify functionality, maybe this needs an update? Is the new interface ready enough so this can simply be a matter of writing provider code?

@slontis
Copy link
Member Author

slontis commented Sep 9, 2024

I am in the process of writing the code..

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago

@paulidale paulidale requested a review from a team October 10, 2024 03:00
Hash Function Selection
-----------------------

- During the DigestVerifyInit()the passed in digest name is not required
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/()/() /


- Support one shot operations:
Using existing EVP_DigestVerifyInit_ex + EVP_DigestVerify calls
- Dont support streaming via existing interface:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't


For the EVP_DigestVerifyFinal pass a NULL signature.
The signature length must be zero in this case or an error will occur.
If a signature is passed should it just ignore the value?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this proposal more.


As well as using the test vectors supplied in [1] and [6], additional interop tests
should be performed by generating data using other toolkits
(such as Ciso or Bouncy Castle).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Ciso/Cisco/

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 92 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 123 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 154 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 185 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 216 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 247 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 278 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 309 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 340 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 371 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 402 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/committers but the last update was 433 days ago

@t8m
Copy link
Member

t8m commented Dec 31, 2025

@slontis Could you please sync this with the actual implementation?

@t8m t8m added waiting-for: contributor response This pull request is awaiting a response by the contributor and removed approval: review pending This pull request needs review by a committer labels Dec 31, 2025
@slontis
Copy link
Member Author

slontis commented Jan 21, 2026

Closing this as it is not likely to be reviewed if I update it.

@slontis slontis closed this Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch: master Applies to master branch tests: exempted The PR is exempt from requirements for testing triaged: design The issue/pr deals with a design document waiting-for: contributor response This pull request is awaiting a response by the contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.