Fast-DDS icon indicating copy to clipboard operation
Fast-DDS copied to clipboard

[CycloneDDS/FastDDS interoprability] Public key wire representation (DH+MODP-2048-256 kagree_algo)

Open lexamor opened this issue 2 years ago • 1 comments

Is there an already existing issue for this?

  • [X] I have searched the existing issues

Seems #3259 can be related to this

Expected behavior

The auth/secure handshake should be passed successfully if the DH+MODP-2048-256 key agreement algo is selected.

Current behavior

In case if DH+MODP-2048-256 key agreement algorithm is selected during the secure handshake the dh1/dh2 attribute cannot be deserialized on the receiver side.

Steps to reproduce

  1. Configure security (for the both fastdds&cyclone client apps).
  2. Launch them

*fastdds client should be the initiator of the handshake since by default ECDH_prime256v1 can be forced by the CycloneDDS side.

Fast DDS version/commit

2.9.1

Platform/Architecture

Ubuntu Focal 20.04 amd64

Transport layer

Default configuration, UDPv4 & SHM

Additional context

According to the DDS Security spec dh1/dh2 attributes are: The CDR Big Endian Serialization of a Diffie-Hellman Public Key chosen by the Participant. This will be used for key agreement.

FastDDS implementation:

BN_bn2bin/BN_bin2bn openssl functions are used during de-/serialization routine:

// Serialization
static bool store_dh_public_key(
...
        const DH* dh = EVP_PKEY_get0_DH(dhkey);
...
        DH_get0_key(dh, &pub_key, &priv_key);
...
        int len = BN_num_bytes(pub_key);
...
        if (BN_bn2bin(pub_key, pointer) == len)`
        
// De-serialization
static const unsigned char* BN_deserialize_raw(
        BIGNUM** bn,
        const unsigned char* raw_pointer,
        size_t length,
        SecurityException& exception)
{
    // 
    BIGNUM* bnn = BN_new();

	if (BN_bin2bn(raw_pointer, static_cast<int>(length), bnn) != nullptr)
}        

CycloneDDS implementation: i2d_ASN1/d2i_ASN1 openssl functions are used during de-/serialization routine:

//Serialization
  if (!(asn1int = BN_to_ASN1_INTEGER (dh_get_public_key(dhkey), NULL)))
...
  (void) i2d_ASN1_INTEGER (asn1int, &buffer_arg);

//De-serialization
static DDS_Security_ValidationResult_t dh_oct_to_public_key_modp(EVP_PKEY **pkey, const unsigned char *keystr, uint32_t size, DDS_Security_SecurityException *ex)
{
...
  if (!(asn1int = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&keystr, (long)size)))
...
  if (!(pubkey = ASN1_INTEGER_to_BN(asn1int, NULL)))
...

XML configuration file

No response

Relevant log output

CycloneDDS:
fsm: Begin handshake reply failed: Failed to convert octet sequence to ASN1 integer

Network traffic capture

No response

lexamor avatar Aug 16 '23 07:08 lexamor

@lexamor Sorry for being silent on this for more than a year. On version 1.1 of the DDS security specification, the encoding of the dh1/dh2 parameters was underspecified. This was reported on DDSSEC12-56 which has been resolved on version 1.2 (released on March 2024) by adding non-normative information on chapter 8.3.

Extract of that section (emphasis mine):

A Diffie-Hellman public key may be represented as an OctetSeq for the purposes of including it in a BinaryProperties_t. In this scenario the following format shall be used: If the public key corresponds to the “DHE+MODP-2048-256” crypto algorithm, then: • The OctetSeq's value shall contain the big endian representation (an array of bytes) of the DH public key (a big number). Non normative: In OpenSSL 1.1.1, this can be obtained through the BN_bn2bin() API. • The OctetSeq's length shall contain the size in bytes of the big endian representation of the DH public key. Non normative: In OpenSSL 1.1.1, this can be obtained through the BN_num_bytes() API. If the public key corresponds to the “ECDHE-CEUM+P256” or "ECDHE-CEUM+P384" crypto algorithms, then: • The OctetSeq's value shall contain the octet string representation of the ECDHE public key. The octet string representation encoding must conform with Sec. 2.3.3 "Elliptic-Curve-Pointto-Octet-String Conversion'' of the SECG SEC 1 ("Elliptic Curve Cryptography") standard [X]. Non normative: In OpenSSL 1.1.1, this can be obtained through the EC_POINT_point2oct() API, passing POINT_CONVERSION_UNCOMPRESSED as the conversion form. • The OctetSeq's length shall contain the length of the octet string. Non normative: In OpenSSL 1.1.1, this can be obtained as the return value of the EC_POINT_point2oct() API called to obtain the octet string representation.

MiguelCompany avatar Nov 29 '24 09:11 MiguelCompany