Skip to content

Commit

Permalink
re-work implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jakemas committed Feb 3, 2025
1 parent af513a6 commit e506ba1
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 66 deletions.
23 changes: 17 additions & 6 deletions crypto/evp_extra/p_pqdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,21 +302,32 @@ EVP_PKEY *EVP_PKEY_pqdsa_new_raw_private_key(int nid, const uint8_t *in, size_t

EVP_PKEY *ret = EVP_PKEY_pqdsa_new(nid);
if (ret == NULL || ret->pkey.pqdsa_key == NULL) {
// EVP_PKEY_kem_new sets the appropriate error.
// EVP_PKEY_pqdsa_new sets the appropriate error.
goto err;
}

const PQDSA *pqdsa = PQDSA_KEY_get0_dsa(ret->pkey.pqdsa_key);
if (pqdsa->private_key_len != len) {
// Get PQDSA instance and validate lengths
const PQDSA *pqdsa = PQDSA_KEY_get0_dsa(ret->pkey.pqdsa_key);
if (len != pqdsa->private_key_len && len != pqdsa->keygen_seed_len) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
goto err;
}

CBS cbs;
CBS_init(&cbs, in, len);
if (!PQDSA_KEY_set_raw_private_key(ret->pkey.pqdsa_key, &cbs)) {
// PQDSA_KEY_set_raw_private_key sets the appropriate error.
goto err;

// Set key based on input length
if (len == pqdsa->private_key_len) {
if (!PQDSA_KEY_set_raw_private_key(ret->pkey.pqdsa_key, &cbs)) {
// PQDSA_KEY_set_raw_private_key sets the appropriate error.
goto err;
}
}
else if (len == pqdsa->keygen_seed_len) {
if (!PQDSA_KEY_set_raw_keypair_from_seed(ret->pkey.pqdsa_key, &cbs)) {
// PQDSA_KEY_set_raw_keypair_from_seed sets the appropriate error.
goto err;
}
}

return ret;
Expand Down
39 changes: 34 additions & 5 deletions crypto/evp_extra/p_pqdsa_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,41 @@ static int pqdsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key, CBS *pubkey)
return 0;
}

// Set the private (and corresponding public) key
if (!PQDSA_KEY_set_raw_private_key(out->pkey.pqdsa_key, key)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
// caller can either provide the full key of size |private_key_len| or
// |keygen_seed_len|.
if (CBS_len(key) == out->pkey.pqdsa_key->pqdsa->private_key_len) {

// Set the private key
if (!PQDSA_KEY_set_raw_private_key(out->pkey.pqdsa_key, key)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}

// Create buffers to store public key based on size
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;
}

// Construct the public key from the private key
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;
}

out->pkey.pqdsa_key->public_key = public_key;
}
else if (CBS_len(key) == out->pkey.pqdsa_key->pqdsa->keygen_seed_len) {
if (!PQDSA_KEY_set_raw_keypair_from_seed(out->pkey.pqdsa_key, key)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
}

return 1;
}

Expand Down
4 changes: 2 additions & 2 deletions crypto/evp_extra/p_pqdsa_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1456,9 +1456,9 @@ TEST_P(PQDSAParameterTest, RawFunctions) {
EXPECT_NE(public_pkey->pkey.pqdsa_key->public_key, nullptr);
EXPECT_EQ(public_pkey->pkey.pqdsa_key->private_key, nullptr);

// check that both the private and public key are present
// check that private key is present and public key is not present in private_key
ASSERT_NE(private_pkey, nullptr);
EXPECT_NE(private_pkey->pkey.pqdsa_key->public_key, nullptr);
EXPECT_EQ(private_pkey->pkey.pqdsa_key->public_key, nullptr);
EXPECT_NE(private_pkey->pkey.pqdsa_key->private_key, nullptr);

// ---- 5. Test get_raw public/private failure modes ----
Expand Down
1 change: 1 addition & 0 deletions crypto/pqdsa/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ PQDSA_KEY *PQDSA_KEY_new(void);
void PQDSA_KEY_free(PQDSA_KEY *key);
int EVP_PKEY_pqdsa_set_params(EVP_PKEY *pkey, int nid);

int PQDSA_KEY_set_raw_keypair_from_seed(PQDSA_KEY *key, CBS *in);
int PQDSA_KEY_set_raw_public_key(PQDSA_KEY *key, CBS *in);
int PQDSA_KEY_set_raw_private_key(PQDSA_KEY *key, CBS *in);
#if defined(__cplusplus)
Expand Down
85 changes: 33 additions & 52 deletions crypto/pqdsa/pqdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,70 +81,51 @@ int PQDSA_KEY_set_raw_public_key(PQDSA_KEY *key, CBS *in) {
return 1;
}

int PQDSA_KEY_set_raw_private_key(PQDSA_KEY *key, CBS *in) {
// To ensure keypair consistency (public key corresponds with private) this
// funtion will set the both the private and public key on the input |key|.
// This funciton will call into public key from private generation to
// construct the corresponding public key, or if the private key was provided
// as a seed, it will populate directly from the keygen function.
// Returns 1 if both public/private keys are not set, 0 otherwise.

// Check if the parsed length corresponds with the expected length of the
// private key, or the keygen seed.
if (CBS_len(in) != key->pqdsa->private_key_len &&
CBS_len(in) != key->pqdsa->keygen_seed_len) {
int PQDSA_KEY_set_raw_keypair_from_seed(PQDSA_KEY *key, CBS *in) {
// Check if the parsed length corresponds with the expected length.
if (CBS_len(in) != key->pqdsa->keygen_seed_len) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
return 0;
}

//check if called passed seed or expanded representation
if(CBS_len(in) == key->pqdsa->keygen_seed_len) {
// caller has provided seed, first we allocate buffers to store key pair
uint8_t *public_key = OPENSSL_malloc(key->pqdsa->public_key_len);
uint8_t *private_key = OPENSSL_malloc(key->pqdsa->private_key_len);

// check buffers are allocated
if (public_key == NULL || private_key == NULL) {
OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}

// attempt to generate the key from the provided seed
if (!key->pqdsa->method->pqdsa_keygen_internal(public_key, private_key,CBS_data(in))) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}

// set the public and private key
key->public_key = public_key;
key->private_key = private_key;
//allocate buffers to store key pair
uint8_t *public_key = OPENSSL_malloc(key->pqdsa->public_key_len);
uint8_t *private_key = OPENSSL_malloc(key->pqdsa->private_key_len);

// check buffers are allocated
if (public_key == NULL || private_key == NULL) {
OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
return 0;
}

else if (CBS_len(in) == key->pqdsa->private_key_len) {
// caller has provided private key, first we set the private key
key->private_key = OPENSSL_memdup(CBS_data(in), key->pqdsa->private_key_len);
// attempt to generate the key from the provided seed
if (!key->pqdsa->method->pqdsa_keygen_internal(public_key,
private_key,
CBS_data(in))) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}

// Create buffers to store public key based on size
size_t pk_len = key->pqdsa->public_key_len;
uint8_t *public_key = OPENSSL_malloc(pk_len);
// set the public and private key
key->public_key = public_key;
key->private_key = private_key;

if (public_key == NULL) {
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
if (key->private_key == NULL || key->public_key == NULL ) {
return 0;
}

// Construct the public key from the private key
if (!key->pqdsa->method->pqdsa_pack_pk_from_sk(
public_key, CBS_data(in))) {
OPENSSL_free(public_key);
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
return 1;
}

key->public_key = public_key;
int PQDSA_KEY_set_raw_private_key(PQDSA_KEY *key, CBS *in) {
// Check if the parsed length corresponds with the expected length.
if (CBS_len(in) != key->pqdsa->private_key_len) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
return 0;
}

if (key->private_key == NULL || key->public_key == NULL ) {
key->private_key = OPENSSL_memdup(CBS_data(in), key->pqdsa->private_key_len);
if (key->private_key == NULL) {
return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion include/openssl/evp.h
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,9 @@ OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_pqdsa_new_raw_public_key(int nid, const uint8_
// EVP_PKEY_pqdsa_new_raw_private_key generates a new EVP_PKEY object of type
// EVP_PKEY_PQDSA, initializes the PQDSA key based on |nid| and populates the
// secret key part of the PQDSA key with the contents of |in|. It returns the
// pointer to the allocated PKEY on sucess and NULL on error.
// pointer to the allocated PKEY on sucess and NULL on error. If the contents
// of |in| is the private key seed, then this function will generate the
// corresponding key pair and populate both public and private parts of the PKEY.
OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_pqdsa_new_raw_private_key(int nid, const uint8_t *in, size_t len);

// Diffie-Hellman-specific control functions.
Expand Down

0 comments on commit e506ba1

Please sign in to comment.