-
Notifications
You must be signed in to change notification settings - Fork 121
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
Support keypair calculation for PQDSA PKEY #2145
Changes from 4 commits
3d1bff4
09abb11
6756bfe
a8c9562
cd8da04
aa87eeb
db900c0
54224d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,7 +149,40 @@ static int pqdsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey) | |
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | ||
return 0; | ||
} | ||
return PQDSA_KEY_set_raw_private_key(out->pkey.pqdsa_key,CBS_data(key)); | ||
|
||
// Set the private key | ||
if (!PQDSA_KEY_set_raw_private_key(out->pkey.pqdsa_key, CBS_data(key))) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | ||
return 0; | ||
} | ||
|
||
// Calculate public key from private key if method exists | ||
if (out->pkey.pqdsa_key->pqdsa->method->pqdsa_pack_pk_from_sk != NULL) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we always return failure ( Upon seeing a successful return code, a caller assumes the EVP_PKEY is initialized and might subsequently SEGFAULT on a call to (e.g.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see. I was trying to prevent against a failure if the ptr is non-null, as you say. Removed this check in cd8da04 and cleaned up the surrounding logic to only return |
||
size_t pk_len = out->pkey.pqdsa_key->pqdsa->public_key_len; | ||
uint8_t *public_key = OPENSSL_malloc(pk_len); | ||
|
||
if (public_key == NULL) { | ||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); | ||
return 0; | ||
} | ||
// attempt to construct the public key from priv | ||
if (!out->pkey.pqdsa_key->pqdsa->method->pqdsa_pack_pk_from_sk( | ||
public_key, CBS_data(key))) { | ||
OPENSSL_free(public_key); | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | ||
return 0; | ||
} | ||
// set the public key | ||
int ret = PQDSA_KEY_set_raw_public_key(out->pkey.pqdsa_key, public_key); | ||
OPENSSL_free(public_key); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since public_key was allocated internally can the PKEY just take ownership of it without having to copy it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see this as being possible, as the size of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, you allocate the key on L162, looking at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. got it! 54224d2 |
||
|
||
if (!ret) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); | ||
return 0; | ||
} | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
static int pqdsa_priv_encode(CBB *out, const EVP_PKEY *pkey) { | ||
|
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.
How expensive is this calculation? What customer workflow needs the public key given the private key? Could this be lazily initialized?
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.
Other types of EVP_PKEY (which have public/private components) ensure that the public key is populated whenever a private key is deserialized. For example, see EC and ED25519.
Other EVP_PKEY_xxx methods (such as EVP_PKEY_cmp) assume that the public key is populated for any EVP_PKEY that has functions available for public keys. (In fact
EVP_PKEY_cmp
can currently SEGFAULT for EVP_PKEY_PQDSA due to this.)There might be other places for this computation to take place, but it needs to be done when deserializing a private key.
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.
Ahhhh good point, looking at ED25519 a little more should we add raw support?
Here in ML-DSA:
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.
We do implement set priv raw for pqdsa, just not as part of the EVP methods...
Some more background:
set_priv_raw
is not implemented for ML-DSA or ML-KEM. In ED25519 things are a little different, as there are no "parameter sets" for ED25519, it's just one algorithm. In ML-DSA/ML-KEM we have multiple NIDs to define algorithm versions.As such, we implement
EVP_PKEY_pqdsa_new_raw_private_key
at https://github.com/aws/aws-lc/blob/main/include/openssl/evp.h#L960-L970 just like for KEMs. I suppose your suggestion is then to removeEVP_PKEY_pqdsa_new_raw_private_key
/EVP_PKEY_pqdsa_new_raw_public_key
and support viaEVP_PKEY_new_raw_private_key
/EVP_PKEY_new_raw_public_key
? The problem is,EVP_PKEY_new_raw_private_key
expectstype
notnid
andtype = EVP_PKEY_PQDSA
is not specific enough to know which NID it is... there's no OID, and we can't use the length to determine uniqueness as another scheme could have the same length.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.
In the aws-lc-rs, I'm just using the length of the "raw" key to differentiate between the NIDs under the
EVP_PKEY_PQDSA
type: justsmth/aws-lc-rs@088e116Would this be an acceptable approach for more cohesive integration into
EVP_PKEY_new_raw_private_key
andEVP_PKEY_new_raw_public_key
?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.
Yeah I considered that too, it works, but it does present an issue should another algorithm be added that has the same length of raw keys -- which may sound unlikely, but would present issues with HashML-DSA that has a different OID/NID but same lengths. I do have some ideas -- but likely out of scope for this PR.