From 8bcd0975afc79234a25898b8d484331ff44da7ff Mon Sep 17 00:00:00 2001
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Thu, 22 Jun 2017 00:26:41 +0200
Subject: [PATCH] gluon-core: add a "site seed" to site.conf to seed
 site-specific random values

---
 docs/site-example/site.conf                      |  5 +++++
 docs/user/site.rst                               | 11 +++++++++++
 package/gluon-core/check_site.lua                |  1 +
 .../gluon-core/luasrc/usr/lib/lua/gluon/util.lua | 16 ++++++++++++++++
 4 files changed, 33 insertions(+)

diff --git a/docs/site-example/site.conf b/docs/site-example/site.conf
index 698ab8de4..9ea420ef6 100644
--- a/docs/site-example/site.conf
+++ b/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.
diff --git a/docs/user/site.rst b/docs/user/site.rst
index 51b9e78a9..d82cdd956 100644
--- a/docs/user/site.rst
+++ b/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.
     ::
diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua
index d26b16716..14d102a02 100644
--- a/package/gluon-core/check_site.lua
+++ b/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)
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 80888c8b1..3829841fd 100644
--- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua
+++ b/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 = {}
-- 
GitLab