diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua
index 41e06003354c2f5b287819818690c808a9003169..4713895841fd2669b9c60a7b9beaaf8dcae08b4d 100644
--- a/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua
+++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua
@@ -1,5 +1,6 @@
 local platform_info = require 'platform_info'
 local util = require 'gluon.util'
+local unistd = require 'posix.unistd'
 
 
 local M = setmetatable({}, {
@@ -55,4 +56,34 @@ function M.is_outdoor_device()
 	return false
 end
 
+function M.device_supports_wpa3()
+	-- rt2x00 crashes when enabling WPA3 personal / OWE VAP
+	if M.match('ramips', 'rt305x') or M.match('ramips', 'mt7620') then
+		return false
+	end
+
+	return unistd.access('/lib/gluon/features/wpa3')
+end
+
+function M.device_supports_mfp(uci)
+	local idx = 0
+	local supports_mfp = true
+
+	if not M.device_supports_wpa3() then
+		return false
+	end
+
+	uci:foreach('wireless', 'wifi-device', function()
+		local phypath = '/sys/kernel/debug/ieee80211/phy' .. idx .. '/'
+
+		if not util.file_contains_line(phypath .. 'hwflags', 'MFP_CAPABLE') then
+			supports_mfp = false
+		end
+
+		idx = idx + 1
+	end)
+
+	return supports_mfp
+end
+
 return M
diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
index 96a4a19098feb7ba9b7a18d27c59f7ed647c5869..a6ebfa141be68ca3439a125bc5ee1dde61bf6e4a 100644
--- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
+++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
@@ -35,6 +35,15 @@ function M.contains(table, value)
 	return false
 end
 
+function M.file_contains_line(path, value)
+	for line in io.lines(path) do
+		if line == value then
+			return true
+		end
+	end
+	return false
+end
+
 function M.add_to_set(t, itm)
 	for _,v in ipairs(t) do
 		if v == itm then return false end