Add sctp authentication to sctp_lib
This only works for linux >=5.4. When enabled, it will use
a shared key to authenticate messages. The functionality is
controlled by a flag and behind a linux version check.
Performance degradation is minimal, even for smaller messages
and unnoticeable when measuring overall system performance.
Change-Id: I836e61ec38a0c116fd7244b771437738ccca9828
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/aos/network/sctp_lib.cc b/aos/network/sctp_lib.cc
index 6030ea7..77cad02 100644
--- a/aos/network/sctp_lib.cc
+++ b/aos/network/sctp_lib.cc
@@ -31,6 +31,25 @@
struct sctp_sndrcvinfo sndrcvinfo;
} _sctp_cmsg_data_t;
+// Returns true if SCTP authentication is available and enabled.
+bool SctpAuthIsEnabled() {
+#if HAS_SCTP_AUTH
+ struct stat current_stat;
+ if (stat("/proc/sys/net/sctp/auth_enable", ¤t_stat) != -1) {
+ int value = std::stoi(
+ util::ReadFileToStringOrDie("/proc/sys/net/sctp/auth_enable"));
+ CHECK(value == 0 || value == 1)
+ << "Unknown auth enable sysctl value: " << value;
+ return value == 1;
+ } else {
+ LOG(WARNING) << "/proc/sys/net/sctp/auth_enable doesn't exist.";
+ return false;
+ }
+#else
+ return false;
+#endif
+}
+
} // namespace
bool Ipv6Enabled() {
@@ -270,6 +289,44 @@
sizeof(subscribe)) == 0);
}
+ if (!auth_key_.empty()) {
+ CHECK(SctpAuthIsEnabled())
+ << "SCTP Authentication is disabled. Enable it with 'sysctl -w "
+ "net.sctp.auth_enable=1' and try again.";
+#if HAS_SCTP_AUTH
+ // Set up the key with id `1`.
+ sctp_authkey *const authkey =
+ (sctp_authkey *)malloc(sizeof(sctp_authkey) + auth_key_.size());
+ authkey->sca_keynumber = 1;
+ authkey->sca_keylength = auth_key_.size();
+ authkey->sca_assoc_id = SCTP_ALL_ASSOC;
+ memcpy(&authkey->sca_key, auth_key_.data(), auth_key_.size());
+
+ PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_AUTH_KEY, authkey,
+ sizeof(sctp_authkey) + auth_key_.size()) == 0);
+ free(authkey);
+
+ // Set key `1` as active.
+ struct sctp_authkeyid authkeyid;
+ authkeyid.scact_keynumber = 1;
+ authkeyid.scact_assoc_id = SCTP_ALL_ASSOC;
+ PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid,
+ sizeof(authkeyid)) == 0);
+
+ // Set up authentication for data chunks.
+ struct sctp_authchunk authchunk;
+ authchunk.sauth_chunk = 0;
+
+ PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_AUTH_CHUNK, &authchunk,
+ sizeof(authchunk)) == 0);
+
+ // Disallow the null key.
+ authkeyid.scact_keynumber = 0;
+ PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, &authkeyid,
+ sizeof(authkeyid)) == 0);
+#endif
+ }
+
DoSetMaxSize();
}
@@ -335,6 +392,9 @@
return true;
}
+SctpReadWrite::SctpReadWrite(std::vector<uint8_t> auth_key)
+ : auth_key_(std::move(auth_key)) {}
+
void SctpReadWrite::FreeMessage(aos::unique_c_ptr<Message> &&message) {
if (use_pool_) {
free_messages_.emplace_back(std::move(message));