-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support to export ML-DSA key-pairs in seed format #2194
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2194 +/- ##
==========================================
- Coverage 79.04% 79.01% -0.03%
==========================================
Files 612 612
Lines 106067 106239 +172
Branches 14985 15013 +28
==========================================
+ Hits 83842 83950 +108
- Misses 21571 21632 +61
- Partials 654 657 +3 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have we just considered exposing access to the opaque PQDSA_KEY
type stored in the EVP and then having more proper access functions like get_private_key_seed etc using that type? I'm not a big fan of the "raw" key meaning on EVP because it differs based on the key types, and now can very on the size dimension which seems really goofy.
crypto/evp_extra/p_pqdsa_asn1.c
Outdated
static int pqdsa_get_priv_raw_seed(PQDSA_KEY *key, const PQDSA *pqdsa, | ||
uint8_t *out,size_t *out_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static int pqdsa_get_priv_raw_seed(PQDSA_KEY *key, const PQDSA *pqdsa, | |
uint8_t *out,size_t *out_len) { | |
static int pqdsa_get_priv_raw_seed(PQDSA_KEY *key, const PQDSA *pqdsa, | |
uint8_t *out,0 size_t *out_len) { | |
GUARD_PTR(key); | |
GUARD_PTR(out_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added to PQDSA_KEY_get_priv_raw_seed
in c307952
crypto/evp_extra/p_pqdsa_asn1.c
Outdated
return 0; | ||
} | ||
|
||
if (*out_len != key->pqdsa->keygen_seed_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (*out_len != key->pqdsa->keygen_seed_len) { | |
if (*out_len < key->pqdsa->keygen_seed_len) { |
A buffer should be allowed to be bigger I'd imagine? The point is that we set *out_len
the actual value of what we wrote. Though I do realize this i gated later, I don't know if it needs to be gated here per-se.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, added in c307952
crypto/evp_extra/p_pqdsa_asn1.c
Outdated
static int pqdsa_get_priv_raw_key(PQDSA_KEY *key, const PQDSA *pqdsa, | ||
uint8_t *out,size_t *out_len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static int pqdsa_get_priv_raw_key(PQDSA_KEY *key, const PQDSA *pqdsa, | |
uint8_t *out,size_t *out_len) { | |
static int pqdsa_get_priv_raw_key(PQDSA_KEY *key, const PQDSA *pqdsa, | |
uint8_t *out, size_t *out_len) { | |
GUARD_PTR(key); | |
GUARD_PTR(out_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added to pqdsa_get_priv_raw
in c307952
Agreed, thank you for the feedback. I've updated the implementation (c307952) so that |
Issues:
Resolves #CryptoAlg-2918
#ACCP-130
Description of changes:
Support the ability to export ML-DSA key seeds. We modify the core algorithm implementation to store the
seed
used during key generation. This will allow the key pair to be reconstructed at a later stage from just the seed.This is performed within
ml_dsa_keypair
, which has been modified to accept an addition argumentseed
that is a pointer to output array ofML_DSA_SEEDBYTES
bytes.These changes bubble up to the
ml_dsa.c
definitions of keygen, that are now modified to support the provided buffer to store the seed:We store the seed in the
PQDSA_KEY
struct duringpkey_pqdsa_keygen
:To export, this PR supports:
EVP_marshal_private_key
to export full format private keyEVP_marshal_private_key_v2
to export seed format private keyPQDSA_KEY_get_priv_raw_seed
to export raw format in seed formFIPS Compliance: I'm glad you're asking, yes this is compliant with FIPS, NIST have published PQC FAQs specifically to address this exact implementation: https://csrc.nist.gov/Projects/post-quantum-cryptography/faqs#Rdc7.
Performance Impact
Converting to seed-based storage for both public and private keys yields the following improvements:
Converting to seed-based storage for private keys yields the following improvements:
The proposed seed-based approach achieves an average storage reduction of 99.4% across all ML-DSA variants.
Call-outs:
Once we have alignment on the EVP API functionality, I will add documentation.
Testing:
Added new test suite
Marshalv2ParseSeed
for parsing as well as additional test for parsing seeds inRawFunctions
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.