Per-key encoding formats for ML-KEM and ML-DSA#29206
Per-key encoding formats for ML-KEM and ML-DSA#29206vdukhovni wants to merge 2 commits intoopenssl:masterfrom
Conversation
c1cbd8b to
68c5a4d
Compare
6fd48b0 to
b9c748c
Compare
|
Just wondering if getting this via the key manager is more prudent than adding a custom encode format? |
Thanks for taking a look, I don't know what you mean by "getting this via the key manager". By way of background, the JAVA mechanism in Bouncy Castle for getting a seed-only form of a key is to create a second key from just the seed of the first, and then (in the native non-jostle implementation) the key remembers that it was imported from a seed and is output in that format automatically. This PR makes it possible for |
|
My thought won't work because the required function is not public. The idea was to get the key manager from the PKEY and then call Making enough public would be an alternative to this. The import/export provider side APIs are part of the public API contract. |
The problem (for jostle, and other potential applications) isn't lack of a mechanism to just get the seed, that's available via This PR providers two ways to do that, and I'm about to add a commit that completes the story by adding a third.
|
06a08d5 to
0090538
Compare
t-j-h
left a comment
There was a problem hiding this comment.
Thinking on the whole concept here, what if someone wants expanded-only - will we add that here too as a separate flag?
Should this be expanded to cover the general concepts more than just one specific choice here - although I think that choice is the pressing one and others could be delayed until some expresses a need for it.
I'm happy with the code and the names - I would just tweak the accept undefined values behaviour and make things fail if we cannot actually produce seed-only output.
|
|
||
| =item "seed-only" (B<OSSL_PKEY_PARAM_SEED_ONLY>) <unsigned int> | ||
|
|
||
| When this parameter is set, its value is ignored, and the generated key is |
There was a problem hiding this comment.
As a general style approach, I would not have an ignored value here. I would require the user to provide a fixed value (e.g. 1) simply to be consistent and allow for any future possible choices where we may want to expand the values for this parameter.
If users are free to put whatever they like then we can never use the value.
Fixing it to 1 allows for possible future changes - which we may never make.
There was a problem hiding this comment.
Yes, I would treat it as boolean though. Ignored value is ugly and we do not use this concept elsewhere (AFAIK).
There was a problem hiding this comment.
A boolean setting makes little sense though, because just not setting the parameter is the correct/simplest way to not force seed-only. Setting it to zero meaning "do nothing" makes no sense.
If we want to support more values, they should have some non-default effect. For example:
- Do not output the seed, giving an expanded key-only output.
- As in this PR, output only the seed.
- Output both seed and expanded key
All three cases override the provparam output-format, if different.
Basically, any setting here needs to mean something concrete, rather than just be a NOP.
There was a problem hiding this comment.
I don't see a problem with allowing the default value to be an input.
It comes down to a preference about how user code is written and we in general do not enforce this restriction anywhere else.
There is not much difference between
*p++ = OSSL_PARAM_construct_int("foo", &val);
AND
if (val)
*p++ = OSSL_PARAM_construct_int("foo", &val);
| When the seed was not initially known, or was not retained, B<PKCS#8> private | ||
| key files will contain only the private key in FIPS 204 C<sk> format. | ||
|
|
||
| =item "seed-only" (B<OSSL_PKEY_PARAM_SEED_ONLY>) <unsigned int> |
There was a problem hiding this comment.
Seeing this as "seed-only" is fine - but if we have just an expanded-only input then I would expect things to fail of someone sets this parameter - given the name.
The code is "seed-only-if-you-have-it" isn't it?
I would make things fail if there is a request for seed-only and it cannot be provided.
There was a problem hiding this comment.
Or, we can change the name, to "preserve-seed-only" or "seed-only-preferred", ...
The code is more "preserve what got on input" if the input is seed only. Of course that's the only possible outcome with expanded-key-only input, and with "both" we get both by default (unless provparams are set to prefer another output form).
So there are some possible design choices here.
- Implement more faithful "seed-only" semantics keeping the name, but ignore presence or absence of expanded key and fail if the seed is missing. Java would have to use the setting with care.
- Implement more faithful "as-is" semantics, changing the name, and preserving also the "both" input form on import and decode, but then likely keygen ends up always producing "both", and one needs to export and reimport in seed-only form to get seed-only output from a freshly generated key.
- Implement a new option to store an ordered list of output formats along with the key (mirroring the global provparams)
- And of course anyone willing to store the preferred output form along with the key can always use the
OSSL_ENCODER_CTX_new_from_pkey(3)API to get seed-only even when both the seed and expanded key came in.
Likely some variations on the theme. Anyway, for now I'll adopt the forced value, but if anyone has a clear vision for what users would find most useful/least surprising here, please share. All the relevant code is in place, and only small tweaks are needed to adjust naming and/or semantics.
There was a problem hiding this comment.
I wouldn't argue if you'd want to support both semantics, i.e. both "seed-only" (implying a hard fail if seed isn't available) and "prefer-seed-only" (which falls back to whatever is available if the seed isn't).
There was a problem hiding this comment.
I would not be opposed to levitte's suggestion.
It could be an single param with multiple settings of 0 = default, 1 = seed_only, 2 = prefer_seed_only.
Sashan
left a comment
There was a problem hiding this comment.
all my comments are nits. I could not spot nothing wrong with your PR..
I'm just pointing them out so you can decide if it is worth to address them or not.
thanks
a859539 to
3179d81
Compare
Sashan
left a comment
There was a problem hiding this comment.
looks good to me. thanks.
8363fad to
61b34b7
Compare
|
Tests and doc nit updated, based on review from @bob-beck (thanks), code remains the same. |
c448cf3 to
0dd8f39
Compare
We support selection of ML-KEM and ML-DSA key formats on input and output at the provider level, these are essentially global defaults, in effect for the lifetime of the process. Unfortunately, the JAVA interface in openssl-jostle needs to be able to output a specific key in seed-only form. To that end, this PR introduces a new "output-formats" PKEY encoding parameter, that can be used with OSSL_ENCODER_CTX_set_params(3) when encoding a key to PKCS#8, after using OSSL_ENCODER_CTX_new_for_key(3), rather than i2d_PrivateKey(3), i2d_PKCS8PrivateKey(3) or PEM equivalents.
In was premature to make OSSL_(EN|DE)CODER_CTX_[sg]et_finalized() be public interfaces. Forunately, these have not yet appeared outside the "master" branch, so we can still retract them. Also, in the case of decoders, the implementation failed to take into account that the context was duplicated before it was returned to the user, and the duplicated copy failed to copy the "finalized" field. This commit also renames "finalized" to "frozen", because finalisation is a misleading term in this context, it suggests resource reclamation during garbage collection or deallocation, not marking a structure partly immutable.
0dd8f39 to
a1d8c63
Compare
bob-beck
left a comment
There was a problem hiding this comment.
Hooray now with test coverage.
LGTM.
| @@ -65,12 +65,6 @@ OpenSSL 4.0 | |||
|
|
|||
There was a problem hiding this comment.
Would be nice if the commit message stated that it partially reverts commit f480a73.
| #define OSSL_KEM_PARAM_OPERATION_DHKEM "DHKEM" | ||
|
|
||
| /* Provider configuration variables */ | ||
| #define OSSL_PKEY_RETAIN_SEED "pkey_retain_seed" |
There was a problem hiding this comment.
Backport note: this macro definition has been added in commit openssl-3.5.0-alpha1~523 and the change shouldn't be backported to 3.x branches (provided such backport will be happening).
There was a problem hiding this comment.
This won't be backported unless given an exception which is pretty unlikely.
|
This pull request is ready to merge |
|
Merged, thanks for the contribution. |
We support selection of ML-KEM and ML-DSA key formats on input and output at the provider level, these are essentially global defaults, in effect for the lifetime of the process.
Unfortunately, the JAVA interface in openssl-jostle needs to be able to output a specific key in seed-only form. To that end, this PR
introduces a new "output-formats" PKEY encoding parameter, that can be used with OSSL_ENCODER_CTX_set_params(3) when encoding a key to PKCS#8, after using OSSL_ENCODER_CTX_new_for_key(3), rather than i2d_PrivateKey(3), i2d_PKCS8PrivateKey(3) or PEM equivalents.
Problem originally reported in: openssl-projects/openssl-jostle#11 (comment)
Once this is merged, corresponding code changes will be needed in Jostle to ensure that seed-only key construction sets the new parameter when needed.
Checklist