Skip to content

Commit

Permalink
Marshalling/Unmarshalling DH public keys
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth committed Oct 15, 2024
1 parent 81dbec0 commit fa832dc
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 5 deletions.
117 changes: 117 additions & 0 deletions crypto/dh_extra/dh_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1051,3 +1051,120 @@ TEST(DHTest, DHCheckForStandardParams) {
ASSERT_TRUE(DH_check(dh2.get(), &flags));
EXPECT_EQ(flags, 0);
}

TEST(DHTest, DHKeyGen) {
const uint8_t dh512_pem[] = {
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x44,
0x48, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x53,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x45, 0x59, 0x43, 0x51, 0x51,
0x44, 0x61, 0x57, 0x44, 0x77, 0x57, 0x32, 0x59, 0x55, 0x69, 0x69, 0x64,
0x44, 0x6b, 0x72, 0x33, 0x56, 0x76, 0x54, 0x4d, 0x71, 0x53, 0x33, 0x55,
0x76, 0x6c, 0x4d, 0x37, 0x67, 0x45, 0x2b, 0x77, 0x2f, 0x74, 0x6c, 0x4f,
0x2b, 0x63, 0x69, 0x6b, 0x51, 0x44, 0x37, 0x56, 0x64, 0x47, 0x55, 0x4e,
0x4e, 0x70, 0x6d, 0x64, 0x73, 0x70, 0x31, 0x33, 0x59, 0x6e, 0x0a, 0x61,
0x36, 0x4c, 0x54, 0x31, 0x42, 0x4c, 0x69, 0x47, 0x50, 0x54, 0x64, 0x48,
0x67, 0x68, 0x4d, 0x39, 0x74, 0x67, 0x41, 0x50, 0x6e, 0x78, 0x48, 0x64,
0x4f, 0x67, 0x7a, 0x41, 0x67, 0x45, 0x43, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d,
0x2d, 0x45, 0x4e, 0x44, 0x20, 0x44, 0x48, 0x20, 0x50, 0x41, 0x52, 0x41,
0x4d, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
};
const uint64_t encoded_g = 2;
const char encoded_p_dec_str[] = "11435638110073884015312138951374632602058080675070521707579703088370446597672067452229024566834732449017970455481029703480957707976441965258194321262569523";

bssl::UniquePtr<EVP_PKEY> epkey_dh_params(nullptr);
{
bssl::UniquePtr<BIO> in_bio(BIO_new_mem_buf(dh512_pem, sizeof(dh512_pem)));
ASSERT_TRUE(in_bio);

epkey_dh_params.reset(PEM_read_bio_Parameters(in_bio.get(), nullptr));
ASSERT_TRUE(epkey_dh_params);
}

// Sanity check the parsing
{
DH *dh_params = EVP_PKEY_get0_DH(epkey_dh_params.get());
const BIGNUM *p = DH_get0_p(dh_params);
const BIGNUM *g = DH_get0_g(dh_params);
uint64_t parsed_g = 0;
ASSERT_TRUE(BN_get_u64(g, &parsed_g));
ASSERT_EQ(parsed_g, encoded_g);
const char *parsed_p_dec_str = BN_bn2dec(p);
ASSERT_NE(parsed_p_dec_str, nullptr);
ASSERT_EQ(OPENSSL_strcasecmp(encoded_p_dec_str, parsed_p_dec_str), 0);
OPENSSL_free((void *)parsed_p_dec_str);
}

// Perform keygen operation
bssl::UniquePtr<EVP_PKEY> gen_dh(nullptr);
{
bssl::UniquePtr<EVP_PKEY_CTX> epkey_ctx(
EVP_PKEY_CTX_new(epkey_dh_params.get(), nullptr));
ASSERT_TRUE(epkey_ctx);

ASSERT_TRUE(EVP_PKEY_keygen_init(epkey_ctx.get()));
EVP_PKEY *gen_dh_raw = nullptr;
ASSERT_TRUE(EVP_PKEY_keygen(epkey_ctx.get(), &gen_dh_raw));
gen_dh.reset(gen_dh_raw);
ASSERT_TRUE(gen_dh);
}

// Marshall pubkey to der
const uint8_t* pubkey_der = NULL;
size_t pubkey_der_len = 0;
{
bssl::UniquePtr<BIO> out_bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(out_bio);
ASSERT_TRUE(i2d_PUBKEY_bio(out_bio.get(), gen_dh.get()));
ASSERT_TRUE(BIO_flush(out_bio.get()));
ASSERT_TRUE(BIO_mem_contents(out_bio.get(), &pubkey_der, &pubkey_der_len));
ASSERT_GT(pubkey_der_len, (size_t)0);
ASSERT_NE(pubkey_der, nullptr);
// We own the allocation after this
pubkey_der = (const uint8_t*)OPENSSL_memdup(pubkey_der, pubkey_der_len);
}

// Parse der to pubkey
bssl::UniquePtr<EVP_PKEY> parsed_der_pubkey(nullptr);
{
bssl::UniquePtr<BIO> in_bio(BIO_new_mem_buf(pubkey_der, pubkey_der_len));
ASSERT_TRUE(in_bio);
EVP_PKEY* parsed_dh_pubkey_raw = nullptr;
ASSERT_TRUE(d2i_PUBKEY_bio(in_bio.get(), &parsed_dh_pubkey_raw));
parsed_der_pubkey.reset(parsed_dh_pubkey_raw);
ASSERT_TRUE(parsed_der_pubkey);
}

ASSERT_TRUE(EVP_PKEY_cmp(gen_dh.get(), parsed_der_pubkey.get()));

// Marshall pubkey to PEM
const uint8_t* pubkey_pem = NULL;
size_t pubkey_pem_len = 0;
{
bssl::UniquePtr<BIO> out_bio(BIO_new(BIO_s_mem()));
ASSERT_TRUE(out_bio);
ASSERT_TRUE(PEM_write_bio_PUBKEY(out_bio.get(), gen_dh.get()));
ASSERT_TRUE(BIO_flush(out_bio.get()));
ASSERT_TRUE(BIO_mem_contents(out_bio.get(), &pubkey_pem, &pubkey_pem_len));
ASSERT_GT(pubkey_pem_len, (size_t)0);
ASSERT_NE(pubkey_pem, nullptr);
// We own the allocation after this
pubkey_pem = (const uint8_t*)OPENSSL_memdup(pubkey_pem, pubkey_pem_len);
}

// Parse PEM to pubkey
bssl::UniquePtr<EVP_PKEY> parsed_pem_pubkey(nullptr);
{
bssl::UniquePtr<BIO> in_bio(BIO_new_mem_buf(pubkey_pem, pubkey_pem_len));
ASSERT_TRUE(in_bio);
EVP_PKEY* pem_pubkey_raw = NULL;
ASSERT_TRUE(PEM_read_bio_PUBKEY(in_bio.get(), &pem_pubkey_raw, NULL, NULL));
parsed_pem_pubkey.reset(pem_pubkey_raw);
ASSERT_TRUE(parsed_pem_pubkey);
}

ASSERT_TRUE(EVP_PKEY_cmp(gen_dh.get(), parsed_pem_pubkey.get()));

OPENSSL_free((void*)pubkey_der);
OPENSSL_free((void*)pubkey_pem);

}
65 changes: 63 additions & 2 deletions crypto/evp_extra/p_dh_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,61 @@
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/x509.h>

#include "internal.h"
#include "../internal.h"
#include "../fipsmodule/cpucap/internal.h"
#include "../fipsmodule/dh/internal.h"
#include "../internal.h"
#include "internal.h"

static int dh_pub_encode(CBB *out, const EVP_PKEY *key) {
CBB spki, algorithm, oid, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, dh_asn1_meth.oid, dh_asn1_meth.oid_len) ||
!DH_marshal_parameters(&algorithm, key->pkey.dh) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
!BN_marshal_asn1(&key_bitstring, key->pkey.dh->pub_key) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}

return 1;
}

static int dh_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
// RFC 2786
BIGNUM* pubkey = NULL;
DH* dh = DH_parse_parameters(params);
if (dh == NULL || key == NULL || CBS_len(key) == 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}

pubkey = BN_new();
if(pubkey == NULL || !BN_parse_asn1_unsigned(key, pubkey)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}

int out_flags = 0;
if(!DH_check_pub_key(dh, pubkey, &out_flags) || out_flags) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
dh->pub_key = pubkey;

EVP_PKEY_assign_DH(out, dh);
return 1;

err:
DH_free(dh);
BN_free(pubkey);
return 0;
}


static void dh_free(EVP_PKEY *pkey) {
Expand Down Expand Up @@ -80,13 +131,23 @@ static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {

const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
.pkey_id = EVP_PKEY_DH,
// 1.2.840.113549.1.3.1
// ((1)*40 + (2)) = 42 = 0x2a
// 840 = 0b_0000110_1001000 => 0b_1000_0110_0100_1000 = 0x86 0x48
// 113549 = 0b_0000110_1110111_0001101 => 0b_1000_0110_1111_0111_0000_1101 = 0x86 0xF7 0x0D
.oid = {0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x03, 0x01},
.oid_len = 9,
.pem_str = "DH",
.info = "OpenSSL PKCS#3 DH method",
.pub_cmp = dh_pub_cmp,
.pkey_size = dh_size,
.pkey_bits = dh_bits,
.param_missing = dh_param_missing,
.param_copy = dh_param_copy,
.param_cmp = dh_param_cmp,
.pkey_free = dh_free,
.pub_encode = dh_pub_encode,
.pub_decode = dh_pub_decode,
};

int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) {
Expand Down
3 changes: 2 additions & 1 deletion crypto/evp_extra/p_methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const EVP_PKEY_ASN1_METHOD *const asn1_evp_pkey_methods[] = {
&dilithium3_asn1_meth,
#endif
&kem_asn1_meth,
&hmac_asn1_meth
&hmac_asn1_meth,
&dh_asn1_meth
};
const size_t asn1_evp_pkey_methods_size = sizeof(asn1_evp_pkey_methods)/sizeof(asn1_evp_pkey_methods[0]);

Expand Down
4 changes: 2 additions & 2 deletions crypto/fipsmodule/evp/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,10 @@ void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx);

#ifdef ENABLE_DILITHIUM
#define NON_FIPS_EVP_PKEY_METHODS 3
#define ASN1_EVP_PKEY_METHODS 9
#define ASN1_EVP_PKEY_METHODS 10
#else
#define NON_FIPS_EVP_PKEY_METHODS 2
#define ASN1_EVP_PKEY_METHODS 8
#define ASN1_EVP_PKEY_METHODS 9
#endif

struct fips_evp_pkey_methods {
Expand Down

0 comments on commit fa832dc

Please sign in to comment.