QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MAVLinkSigningKeys.h
Go to the documentation of this file.
1#pragma once
2
3#include <QtCore/QByteArray>
4#include <QtCore/QByteArrayView>
5#include <QtCore/QHash>
6#include <QtCore/QLatin1StringView>
7#include <QtCore/QObject>
8#include <QtCore/QTimer>
9#include <QtQmlIntegration/QtQmlIntegration>
10#include <optional>
11
12#include "MAVLinkSigning.h"
13
16class Vehicle;
17
20class MAVLinkSigningKey : public QObject
21{
22 Q_OBJECT
23 QML_ELEMENT
24 QML_UNCREATABLE("")
25
26 Q_PROPERTY(QString name READ name CONSTANT)
27
28public:
29 explicit MAVLinkSigningKey(const QString& name, const MAVLinkSigning::SigningKey& keyBytes,
30 QObject* parent = nullptr);
31 ~MAVLinkSigningKey() override;
32
33 const QString& name() const { return _name; }
34
35 const MAVLinkSigning::SigningKey& keyBytes() const { return _keyBytes; }
36
38 uint64_t lastTimestamp() const { return _lastTimestamp; }
39 void setLastTimestamp(uint64_t ts) { _lastTimestamp = ts; }
40
41private:
42 const QString _name;
43 MAVLinkSigning::SigningKey _keyBytes; // 32-byte derived key — secureZero on destruction
44 uint64_t _lastTimestamp = 0;
45};
46
49class MAVLinkSigningKeys : public QObject
50{
51 Q_OBJECT
52 QML_ANONYMOUS
53
54 Q_PROPERTY(QmlObjectListModel* keys READ keys CONSTANT)
55 Q_PROPERTY(int keyUsageRevision READ keyUsageRevision NOTIFY keyUsageChanged)
56
57 friend class SigningTest;
58
59public:
61
62 explicit MAVLinkSigningKeys(QObject* parent = nullptr);
63 ~MAVLinkSigningKeys() override;
64
68 Q_INVOKABLE bool addKey(const QString& name, const QString& passphrase);
69
72 Q_INVOKABLE bool addRawKey(const QString& name, const QString& hexKey);
73
75 Q_INVOKABLE static QString generateRandomHexKey();
76
77 Q_INVOKABLE void removeKey(const QString& name);
78
80 Q_INVOKABLE void removeAllKeys();
81
83 Q_INVOKABLE bool isKeyInUse(const QString& name) const;
84
86 Q_INVOKABLE QString keyHexByName(const QString& name) const;
87
89 MAVLinkSigningKey* keyAt(int index) const;
90
92 std::optional<MAVLinkSigning::SigningKey> keyBytesByName(const QString& name) const;
93
95 uint64_t lastTimestamp(const QString& name) const;
96
98 void recordTimestamp(const QString& name, uint64_t ts);
99
101 void recordTimestamps(const QHash<QString, uint64_t>& batch);
102
104 void flushAllTimestamps();
105
107 QString tryDetectKey(SigningController* controller, const mavlink_message_t& message);
108
109 QmlObjectListModel* keys() const { return _keys; }
110
111 int keyUsageRevision() const { return _keyUsageRevision; }
112
113signals:
116
117private:
118 void _save();
119 void _load();
120 bool _validateNewKey(const QString& name) const;
121 MAVLinkSigningKey* _insertKey(const QString& name, const MAVLinkSigning::SigningKey& keyBytes);
122 void _connectVehicle(Vehicle* vehicle);
123 void _disconnectVehicle(Vehicle* vehicle);
124 QHash<QString, uint64_t> _snapshotAllTimestamps() const;
125
126 QmlObjectListModel* _keys = nullptr;
127 QHash<QString, MAVLinkSigningKey*> _keyIndex; // O(1) name lookups alongside QML model
128 int _keyUsageRevision = 0;
129 QTimer* _timestampFlushTimer = nullptr;
130
131 static constexpr QLatin1StringView kSettingsGroup = QLatin1StringView("MAVLinkSigningKeys");
132 static constexpr QLatin1StringView kManifestKey = QLatin1StringView("manifest"); // key names list (no secrets)
133 static constexpr QLatin1StringView kKeySubgroup = QLatin1StringView("keys"); // <kSettingsGroup>/keys/<name> = key bytes
134 static constexpr QLatin1StringView kTimestampSubgroup = QLatin1StringView("timestamps"); // <kSettingsGroup>/timestamps/<name> = quint64
135 static constexpr int kTimestampFlushIntervalMs = 5000;
136
139 static constexpr QByteArrayView kPbkdf2Salt = QByteArrayView("QGroundControl-MAVLink-Signing-v1");
141 static constexpr int kPbkdf2Iterations = 600'000;
142
143 static constexpr int kSigningKeySize = MAVLinkSigning::kSigningKeySize;
144 static constexpr int kMaxKeys = 64;
146 static constexpr int kMinPassphraseLength = 8;
147
148public:
150 static void setPbkdf2IterationsForTesting(int iterations) { _pbkdf2IterationsOverride = iterations; }
151
152private:
153 static int _effectivePbkdf2Iterations() {
154 return _pbkdf2IterationsOverride > 0 ? _pbkdf2IterationsOverride : kPbkdf2Iterations;
155 }
156 static inline int _pbkdf2IterationsOverride = 0;
157};
struct __mavlink_message mavlink_message_t
A single named signing key entry.
const MAVLinkSigning::SigningKey & keyBytes() const
void setLastTimestamp(uint64_t ts)
const QString & name() const
uint64_t lastTimestamp() const
10µs ticks since 2015-01-01; persisted for forward-progress across restarts with skewed clock.
Bag of named MAVLink signing keys; correct key per vehicle is auto-detected from incoming signed pack...
static MAVLinkSigningKeys * instance()
std::optional< MAVLinkSigning::SigningKey > keyBytesByName(const QString &name) const
Key bytes for the key with the given name, or nullopt if not found.
void flushAllTimestamps()
Walk every signing channel and persist its current timestamp under the active key's name.
MAVLinkSigningKey * keyAt(int index) const
Key entry at the given index, or nullptr if invalid.
void recordTimestamps(const QHash< QString, uint64_t > &batch)
Batch update with single QSettings + sync; per-entry monotonic guard still applies.
Q_INVOKABLE bool addRawKey(const QString &name, const QString &hexKey)
Q_INVOKABLE void removeAllKeys()
Used by tests and full reset.
void recordTimestamp(const QString &name, uint64_t ts)
Update in-memory + persisted last-timestamp for name. Monotonic — older values are dropped.
Q_INVOKABLE void removeKey(const QString &name)
QString tryDetectKey(SigningController *controller, const mavlink_message_t &message)
Try every stored key against message's signature; on match, configures channel and returns the key na...
Q_INVOKABLE bool addKey(const QString &name, const QString &passphrase)
Q_INVOKABLE bool isKeyInUse(const QString &name) const
True if any connected vehicle is using the key with the given name.
Q_INVOKABLE QString keyHexByName(const QString &name) const
Hex-encoded key bytes for export (empty if not found).
uint64_t lastTimestamp(const QString &name) const
Last persisted signing timestamp for name, or 0 if unknown / no entry.
static void setPbkdf2IterationsForTesting(int iterations)
Test-only override for PBKDF2 iteration count; 0 restores production default.
static Q_INVOKABLE QString generateRandomHexKey()
Cryptographically random 64-char hex string (32 bytes).
QmlObjectListModel * keys() const
Owns MAVLink signing state and the deferred-confirmation state machine for one LinkInterface.
std::array< uint8_t, kSigningKeySize > SigningKey
std::array avoids QByteArray COW detach so secureZero() actually wipes the bytes.
static constexpr int kSigningKeySize