Browse Source

gluon-core: add a "site seed" to site.conf to seed site-specific random values

Matthias Schiffer 6 years ago
parent
commit
8bcd0975af

+ 5 - 0
docs/site-example/site.conf

@@ -15,6 +15,11 @@
   -- Shorthand of the community.
   site_code = 'ffxx',
 
+  -- 32 bytes of random data, encoded in hexacimal
+  -- Must be the same of all nodes in one mesh domain
+  -- Can be generated using: echo $(hexdump -n 32 -e '1/1 "%02x"' </dev/urandom)
+  site_seed = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
+
   -- Prefixes used within the mesh.
   -- prefix6 is required, prefix4 can be omitted if next_node.ip4
   -- is not set.

+ 11 - 0
docs/user/site.rst

@@ -21,6 +21,17 @@ site_code
     The code of your community. It is good practice to use the TLD of
     your community here.
 
+site_seed
+    32 bytes of random data, encoded in hexadecimal, used to seed other random
+    values specific to the mesh domain. It must be the same for all nodes of one
+    mesh, but should be different for firmwares that are not supposed to mesh with
+    each other.
+
+    The recommended way to generate a value for a new site is:
+    ::
+
+        echo $(hexdump -n 32 -e '1/1 "%02x"' </dev/urandom)
+
 prefix4 \: optional
     The IPv4 Subnet of your community mesh network in CIDR notation, e.g.
     ::

+ 1 - 0
package/gluon-core/check_site.lua

@@ -1,5 +1,6 @@
 need_string 'site_code'
 need_string 'site_name'
+need_string_match('site_seed', '^' .. ('%x'):rep(64) .. '$')
 
 if need_table('opkg', nil, false) then
 	need_string('opkg.lede', false)

+ 16 - 0
package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua

@@ -122,6 +122,22 @@ function node_id()
 	return string.gsub(sysconfig.primary_mac, ':', '')
 end
 
+function site_seed_bytes(key, length)
+	local ret = ''
+	local v = ''
+	local i = 0
+
+	-- Inspired by HKDF key expansion, but much simpler, as we don't need
+	-- cryptographic strength
+	while ret:len() < 2*length do
+		i = i + 1
+		v = hash.md5(v .. key .. site.site_seed .. i)
+		ret = ret .. v
+	end
+
+	return ret:sub(0, 2*length)
+end
+
 function get_mesh_devices(uconn)
 	local dump = uconn:call("network.interface", "dump", {})
 	local devices = {}