Skip to content

Commit 144bf41

Browse files
committed
Verify Safe DDS signature
This is an squashed commit of a privately reviewed branch. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> Reviewed-by: danipiza <dpizarrogallego@gmail.com>
1 parent 62c044f commit 144bf41

File tree

6 files changed

+464
-6
lines changed

6 files changed

+464
-6
lines changed

include/fastdds/dds/core/policy/ParameterTypes.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,10 @@ enum ParameterId_t : uint16_t
187187
/* Participant specific */
188188
PID_WIREPROTOCOL_CONFIG = 0x8300,
189189
/* RPC specific */
190-
PID_RPC_MORE_REPLIES = 0x8400
190+
PID_RPC_MORE_REPLIES = 0x8400,
191+
192+
/* eProsima Safe DDS extensions */
193+
PID_SAFE_DDS_SIGNATURE = 0x9000,
191194
};
192195

193196
/*!

include/fastdds/rtps/common/VendorId_t.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ using VendorId_t = std::array<uint8_t, 2>;
3333

3434
const VendorId_t c_VendorId_Unknown = {0x00, 0x00};
3535
const VendorId_t c_VendorId_eProsima = {0x01, 0x0F};
36+
const VendorId_t c_VendorId_SafeDDS = {0x01, 0x15};
3637
const VendorId_t c_VendorId_rti_connext = {0x01, 0x01};
3738
const VendorId_t c_VendorId_opendds = {0x01, 0x03};
3839

src/cpp/rtps/builtin/data/ParticipantProxyData.cpp

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include <utils/SystemInfo.hpp>
4040
#include <utils/TimeConversion.hpp>
4141

42+
#include <utils/license/LicenseTools.hpp>
43+
4244
#include "ProxyDataFilters.hpp"
4345
#include "ProxyHashTables.hpp"
4446

@@ -50,6 +52,20 @@ namespace rtps {
5052

5153
using ::operator <<;
5254

55+
static bool validate_safedds_signature(
56+
const octet* const buffer,
57+
uint16_t length)
58+
{
59+
if (length != 0x50)
60+
{
61+
return false;
62+
}
63+
64+
const octet* const data = buffer;
65+
const octet* const signature = buffer + 0x10;
66+
return verify_safedds_signature(data, 0x10, signature, 0x40);
67+
}
68+
5369
ParticipantProxyData::ParticipantProxyData(
5470
const RTPSParticipantAllocationAttributes& allocation)
5571
: ParticipantBuiltinTopicData(
@@ -482,8 +498,11 @@ bool ParticipantProxyData::read_from_cdr_message(
482498
bool should_filter_locators,
483499
fastdds::rtps::VendorId_t source_vendor_id)
484500
{
501+
bool shall_validate_safedds_signature = source_vendor_id == c_VendorId_SafeDDS;
502+
bool safedds_signature_valid = false;
503+
485504
auto param_process =
486-
[this, &network, &should_filter_locators, source_vendor_id](
505+
[this, &network, &should_filter_locators, source_vendor_id, &safedds_signature_valid](
487506
CDRMessage_t* msg, const ParameterId_t& pid, uint16_t plength)
488507
{
489508
vendor_id = source_vendor_id;
@@ -897,6 +916,21 @@ bool ParticipantProxyData::read_from_cdr_message(
897916
}
898917
break;
899918
}
919+
case fastdds::dds::PID_SAFE_DDS_SIGNATURE:
920+
{
921+
if (source_vendor_id == c_VendorId_SafeDDS)
922+
{
923+
// Validate length
924+
if (msg->length - msg->pos < plength)
925+
{
926+
return false;
927+
}
928+
929+
safedds_signature_valid = validate_safedds_signature(&msg->buffer[msg->pos], plength);
930+
msg->pos += plength;
931+
}
932+
break;
933+
}
900934
default:
901935
{
902936
break;
@@ -910,15 +944,17 @@ bool ParticipantProxyData::read_from_cdr_message(
910944
clear();
911945
try
912946
{
913-
return ParameterList::readParameterListfromCDRMsg(
914-
*msg, param_process, use_encapsulation,
915-
qos_size);
947+
if (ParameterList::readParameterListfromCDRMsg(*msg, param_process, use_encapsulation, qos_size))
948+
{
949+
return !shall_validate_safedds_signature || safedds_signature_valid;
950+
}
916951
}
917952
catch (std::bad_alloc& ba)
918953
{
919954
std::cerr << "bad_alloc caught: " << ba.what() << '\n';
920-
return false;
921955
}
956+
957+
return false;
922958
}
923959

924960
bool ParticipantProxyData::is_from_this_host() const
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file LicenseTools.hpp
17+
*/
18+
19+
#ifndef UTILS_LICENSE__LICENSETOOLS_HPP_
20+
#define UTILS_LICENSE__LICENSETOOLS_HPP_
21+
22+
#if HAVE_SECURITY
23+
#include <openssl/evp.h>
24+
#include <openssl/x509.h>
25+
#include <openssl/pem.h>
26+
#include <openssl/err.h>
27+
#include <openssl/rsa.h>
28+
#endif // HAVE_SECURITY
29+
30+
#include <fastdds/rtps/common/Types.hpp>
31+
32+
namespace eprosima {
33+
34+
using fastdds::rtps::octet;
35+
36+
/**
37+
* @brief Verify signature of data using eProsima's licensing public key.
38+
*
39+
* @param data Pointer to the data to verify.
40+
* @param data_length Length of the data to verify.
41+
* @param signature Pointer to the signature.
42+
* @param signature_length Length of the signature.
43+
*
44+
* @return true if the signature is valid, false otherwise.
45+
*/
46+
bool verify_safedds_signature(
47+
const octet* data,
48+
size_t data_length,
49+
const octet* signature,
50+
size_t signature_length)
51+
{
52+
#if HAVE_SECURITY
53+
static const unsigned char pubkey_der[] =
54+
{
55+
0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0x4a, 0x01, 0xe9, 0xd4,
56+
0x16, 0x79, 0xbd, 0x2e, 0x17, 0xeb, 0xc9, 0x68, 0x07, 0xd7, 0x65, 0x82, 0x0d, 0x56, 0x5d, 0x61,
57+
0x8c, 0xab, 0x77, 0xdb, 0x55, 0xd2, 0xa1, 0x2e, 0x31, 0xaa, 0xdb, 0xaa
58+
};
59+
60+
struct OperationCTX
61+
{
62+
EVP_PKEY* pkey = nullptr;
63+
EVP_MD_CTX* md_ctx = nullptr;
64+
65+
~OperationCTX()
66+
{
67+
if (md_ctx != nullptr)
68+
{
69+
EVP_MD_CTX_free(md_ctx);
70+
}
71+
if (pkey != nullptr)
72+
{
73+
EVP_PKEY_free(pkey);
74+
}
75+
}
76+
77+
};
78+
79+
OperationCTX ctx;
80+
81+
const unsigned char* p = pubkey_der;
82+
ctx.pkey = d2i_PUBKEY(nullptr, &p, sizeof(pubkey_der));
83+
if (ctx.pkey == nullptr)
84+
{
85+
return false;
86+
}
87+
88+
ctx.md_ctx = EVP_MD_CTX_new();
89+
if (ctx.md_ctx == nullptr)
90+
{
91+
return false;
92+
}
93+
94+
if (EVP_DigestVerifyInit(ctx.md_ctx, nullptr, nullptr, nullptr, ctx.pkey) != 1)
95+
{
96+
return false;
97+
}
98+
99+
int verify_result = EVP_DigestVerify(ctx.md_ctx, signature, signature_length, data, data_length);
100+
return verify_result == 1;
101+
#else
102+
static_cast<void>(data);
103+
static_cast<void>(data_length);
104+
static_cast<void>(signature);
105+
static_cast<void>(signature_length);
106+
107+
return true;
108+
#endif // HAVE_SECURITY
109+
}
110+
111+
} // namespace eprosima
112+
113+
#endif // UTILS_LICENSE__LICENSETOOLS_HPP_

0 commit comments

Comments
 (0)