3#include <QtCore/QCryptographicHash>
4#include <QtCore/QDateTime>
17 return status ? status->signing :
nullptr;
37 return (message_id == MAVLINK_MSG_ID_RADIO_STATUS);
49bool pendingAcceptUnsignedCallback(
const mavlink_status_t* status, uint32_t message_id)
54 case MAVLINK_MSG_ID_RADIO_STATUS:
55 case MAVLINK_MSG_ID_HEARTBEAT:
56 case MAVLINK_MSG_ID_STATUSTEXT:
71 return pendingAcceptUnsignedCallback;
80 setup_signing.target_system = target_system.sysid;
81 setup_signing.target_component = target_system.compid;
83 if (!keyBytes.isEmpty() && keyBytes.size() >=
static_cast<qsizetype
>(
sizeof(setup_signing.secret_key))) {
85 const mavlink_signing_t*
const signing = _channelSigningPtr(channel);
86 const uint64_t channelTs = signing ? signing->timestamp : 0;
88 memcpy(setup_signing.secret_key, keyBytes.constData(),
sizeof(setup_signing.secret_key));
100 (void)mavlink_msg_setup_signing_encode_chan(srcSysId, srcCompId, channel, &message, &payload);
106 return (message.incompat_flags & MAVLINK_IFLAG_SIGNED) != 0;
112 message.incompat_flags |= MAVLINK_IFLAG_SIGNED;
114 message.incompat_flags &=
static_cast<uint8_t
>(~MAVLINK_IFLAG_SIGNED);
122 if (copy.magic == MAVLINK_STX) {
123 copy.incompat_flags &=
static_cast<uint8_t
>(~MAVLINK_IFLAG_SIGNED);
126 static_assert(MAVLINK_CORE_HEADER_LEN == 9,
"MAVLink2 core header layout changed — update CRC recomputation");
127 uint8_t header[MAVLINK_CORE_HEADER_LEN];
128 header[0] = copy.len;
129 header[1] = copy.incompat_flags;
130 header[2] = copy.compat_flags;
131 header[3] = copy.seq;
132 header[4] = copy.sysid;
133 header[5] = copy.compid;
134 header[6] =
static_cast<uint8_t
>(copy.msgid & 0xFF);
135 header[7] =
static_cast<uint8_t
>((copy.msgid >> 8) & 0xFF);
136 header[8] =
static_cast<uint8_t
>((copy.msgid >> 16) & 0xFF);
138 uint16_t checksum = crc_calculate(header, MAVLINK_CORE_HEADER_LEN);
139 crc_accumulate_buffer(&checksum, _MAV_PAYLOAD(©), copy.len);
140 crc_accumulate(mavlink_get_crc_extra(©), &checksum);
142 copy.checksum = checksum;
143 mavlink_ck_a(©) =
static_cast<uint8_t
>(checksum & 0xFF);
144 mavlink_ck_b(©) =
static_cast<uint8_t
>(checksum >> 8);
147 QByteArray buf(MAVLINK_MAX_PACKET_LEN, Qt::Uninitialized);
148 const uint16_t len = mavlink_msg_to_send_buffer(
reinterpret_cast<uint8_t*
>(buf.data()), ©);
160 const uint8_t* header =
reinterpret_cast<const uint8_t*
>(&message.magic);
161 const char* payload = _MAV_PAYLOAD(&message);
162 const uint8_t* sig = message.signature;
163 const uint8_t crc[2] = {
static_cast<uint8_t
>(message.checksum & 0xFF),
static_cast<uint8_t
>(message.checksum >> 8)};
165 const QByteArrayView parts[] = {
167 QByteArrayView(
reinterpret_cast<const char*
>(header), MAVLINK_NUM_HEADER_BYTES),
168 QByteArrayView(payload, message.len),
169 QByteArrayView(
reinterpret_cast<const char*
>(crc),
sizeof(crc)),
173 const auto hash = QCryptographicHash::hashInto(QSpan<uchar>(hashBuf), QSpan<const QByteArrayView>(parts),
174 QCryptographicHash::Sha256);
182 return verifySignature(QByteArrayView(
reinterpret_cast<const char*
>(key.data()), key.size()), message);
191 const mavlink_signing_t*
const signing = _channelSigningPtr(channel);
193 qCWarning(MAVLinkSigningLog) <<
"checkSigningLinkId: no signing struct on channel" << channel;
196 return (signing->link_id ==
static_cast<mavlink_channel_t>(message.signature[0]));
202 const mavlink_signing_status_t last =
203 (status && status->signing) ? status->signing->last_status : MAVLINK_SIGNING_STATUS_NONE;
205 case MAVLINK_SIGNING_STATUS_OK:
206 return QStringLiteral(
"OK");
207 case MAVLINK_SIGNING_STATUS_BAD_SIGNATURE:
208 return QStringLiteral(
"Bad Signature");
209 case MAVLINK_SIGNING_STATUS_NO_STREAMS:
210 return QStringLiteral(
"No Streams");
211 case MAVLINK_SIGNING_STATUS_TOO_MANY_STREAMS:
212 return QStringLiteral(
"Too Many Streams");
213 case MAVLINK_SIGNING_STATUS_OLD_TIMESTAMP:
214 return QStringLiteral(
"Stale Timestamp");
215 case MAVLINK_SIGNING_STATUS_REPLAY:
216 return QStringLiteral(
"Replay Detected");
217 case MAVLINK_SIGNING_STATUS_NONE:
226 if (!status || !status->signing_streams) {
229 return status->signing_streams->num_signing_streams;
235 const mavlink_signing_status_t last =
236 (status && status->signing) ? status->signing->last_status : MAVLINK_SIGNING_STATUS_NONE;
238 case MAVLINK_SIGNING_STATUS_BAD_SIGNATURE:
239 qCWarning(MAVLinkSigningLog) <<
"Channel" << channel <<
"signing failure: bad signature (key mismatch)";
241 case MAVLINK_SIGNING_STATUS_NO_STREAMS:
242 qCWarning(MAVLinkSigningLog) <<
"Channel" << channel <<
"signing failure: no signing streams table";
244 case MAVLINK_SIGNING_STATUS_TOO_MANY_STREAMS:
245 qCWarning(MAVLinkSigningLog) <<
"Channel" << channel <<
"signing failure: stream table full (>"
248 case MAVLINK_SIGNING_STATUS_OLD_TIMESTAMP:
249 qCWarning(MAVLinkSigningLog) <<
"Channel" << channel
250 <<
"signing failure: new stream with stale timestamp (>"
251 << MAVLINK_SIGNING_TIMESTAMP_LIMIT <<
"s old)";
253 case MAVLINK_SIGNING_STATUS_REPLAY:
254 qCWarning(MAVLinkSigningLog) <<
"Channel" << channel
255 <<
"signing failure: replay detected (repeated/old timestamp)";
257 case MAVLINK_SIGNING_STATUS_OK:
258 case MAVLINK_SIGNING_STATUS_NONE:
#define MAVLINK_MAX_SIGNING_STREAMS
mavlink_status_t * mavlink_get_channel_status(uint8_t chan)
struct __mavlink_setup_signing_t mavlink_setup_signing_t
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QByteArray serializeUnsignedCopy(const mavlink_message_t &message)
static constexpr int kSignatureHashBytes
bool checkSigningLinkId(mavlink_channel_t channel, const mavlink_message_t &message)
bool encodeSetupSigning(mavlink_channel_t channel, uint8_t srcSysId, uint8_t srcCompId, mavlink_system_t target_system, QByteArrayView keyBytes, mavlink_message_t &message)
std::array< uint8_t, kSigningKeySize > SigningKey
std::array avoids QByteArray COW detach so secureZero() actually wipes the bytes.
QString signingStatusString(mavlink_channel_t channel)
bool verifySignature(QByteArrayView key, const mavlink_message_t &message)
Verify a key against a signed message's signature.
uint64_t currentSigningTimestampTicks()
Current signing timestamp in 10µs ticks since 2015-01-01.
void createSetupSigning(mavlink_channel_t channel, mavlink_system_t target_system, QByteArrayView keyBytes, mavlink_setup_signing_t &setup_signing)
Build a SETUP_SIGNING payload. Empty keyBytes produces a disable payload (zero key,...
bool secureConnectionAcceptUnsignedCallback(const mavlink_status_t *status, uint32_t message_id)
std::optional< SigningKey > makeSigningKey(QByteArrayView bytes)
Build a SigningKey from arbitrary bytes. Returns nullopt if input is the wrong size.
bool isMessageSigned(const mavlink_message_t &message)
Returns true if the message has a MAVLink2 signature.
mavlink_accept_unsigned_t callbackForPolicy(UnsignedAcceptancePolicy policy)
Maps a high-level policy to the underlying libmavlink callback.
void logSigningFailure(mavlink_channel_t channel)
static constexpr int kSigningKeySize
void setMessageSigned(mavlink_message_t &message, bool isSigned)
Set or clear the MAVLink2 signature incompatibility flag on a message.
static constexpr int kSignaturePrefixBytes
bool insecureConnectionAcceptUnsignedCallback(const mavlink_status_t *status, uint32_t message_id)
int signingStreamCount(mavlink_channel_t channel)