mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Allow generating MAC addresses from machine ID
@ 2023-11-15  9:02 Uwe Kleine-König
  2023-11-15  9:02 ` [PATCH v2 1/2] common: machine_id: support deriving app specific UUIDs Uwe Kleine-König
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Uwe Kleine-König @ 2023-11-15  9:02 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Alexander Shiyan, Thorsten Scherer, Ahmad Fatoum, barebox

Hello,

this series contains two patches by Ahmad that he send earlier starting
with Message-Id: <20230911155927.3786335-1-a.fatoum@pengutronix.de>.

Patch #1 was already applied back then as 9831b2e5fed8 ("common:
machine_id: support deriving app specific UUIDs").

Changes since (implicit) v1:

 - fix compilation with MACHINE_ID=n (Sascha)
 - fix typo in NET_ETHADDR_FROM_MACHINE_ID helptext (Thorsten)
 - rename of_populate_ethaddr -> populate_ethaddr as it's not about of any more (Sascha)

On Tue, Sep 12, 2023 at 12:49:03PM +0200, Sascha Hauer wrote:
> On Mon, Sep 11, 2023 at 05:59:27PM +0200, Ahmad Fatoum wrote:
> > @@ -566,11 +568,18 @@ static int of_populate_ethaddr(void)
> >
> >             ret = of_get_mac_addr_nvmem(edev->parent->of_node,
> >                                         edev->ethaddr);
> > +           if (ret && IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID)) {
>
> This check doesn't seem to be needed, generate_ether_addr() already
> returns -ENOSYS when this option is not enabled.

I kept this check, Ahmad already argued that is should be kept. (I only
swapped the checks to have the static one first which is IMHO more
natural.)

Best regards
Uwe

Ahmad Fatoum (2):
  common: machine_id: support deriving app specific UUIDs
  net: add generic MAC address derivation from machine ID

 common/machine_id.c  | 84 ++++++++++++++++++++++++++++++++++++++++++--
 include/linux/uuid.h |  8 +++++
 include/machine_id.h | 11 ++++++
 include/net.h        |  2 ++
 net/Kconfig          | 17 +++++++++
 net/eth.c            | 15 ++++++--
 net/net.c            | 49 ++++++++++++++++++++++++--
 7 files changed, 179 insertions(+), 7 deletions(-)

base-commit: bc5e49335067d0c6c6e97c082a0368fe9d86b725
-- 
2.42.0.586.gbc5204569f7d.dirty




^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/2] common: machine_id: support deriving app specific UUIDs
  2023-11-15  9:02 [PATCH v2 0/2] Allow generating MAC addresses from machine ID Uwe Kleine-König
@ 2023-11-15  9:02 ` Uwe Kleine-König
  2023-11-15  9:02 ` [PATCH v2 2/2] net: add generic MAC address derivation from machine ID Uwe Kleine-König
  2023-11-21  8:33 ` [PATCH v2 0/2] Allow generating MAC addresses " Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Uwe Kleine-König @ 2023-11-15  9:02 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: Ahmad Fatoum, Alexander Shiyan, Thorsten Scherer, barebox

From: Ahmad Fatoum <a.fatoum@pengutronix.de>

libsystemd provides a sd_id128_get_machine_app_specific() function that
allows deriving an application specific UUID without directly leaking
the machine ID.

Let's provide an equivalent for barebox that will be used in a following
commit to generate a stable MAC instead of randomizing it.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/machine_id.c  | 84 ++++++++++++++++++++++++++++++++++++++++++--
 include/linux/uuid.h |  8 +++++
 include/machine_id.h | 11 ++++++
 3 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/common/machine_id.c b/common/machine_id.c
index 8c273b934989..edc8ad0ac156 100644
--- a/common/machine_id.c
+++ b/common/machine_id.c
@@ -13,17 +13,96 @@
 
 #define MACHINE_ID_LENGTH 32
 
+static bool __machine_id_initialized;
 static void *__machine_id_hashable;
 static size_t __machine_id_hashable_length;
 
-
+/**
+ * machine_id_set_hashable - Provide per-board unique data
+ * @hashable: Buffer
+ * @len: size of buffer
+ *
+ * The data supplied to the last call of this function prior to
+ * late_initcall will be hashed and stored into global.machine_id,
+ * which can be later used for fixup into the kernel command line
+ * or for deriving application specific unique IDs via
+ * machine_id_get_app_specific().
+ */
 void machine_id_set_hashable(const void *hashable, size_t len)
 {
-
 	__machine_id_hashable = xmemdup(hashable, len);
 	__machine_id_hashable_length = len;
 }
 
+/**
+ * machine_id_get_app_specific - Generates an application-specific UUID
+ * @result: UUID output of the function
+ * @...: pairs of (const void *, size_t) arguments of data to factor
+ * into the UUID followed by a NULL sentinel value.
+ *
+ * Combines the machine ID with the application specific varargs data
+ * to arrive at an application-specific and board-specific UUID that is
+ * stable and unique.
+ *
+ * The function returns 0 if a UUID was successfully written into @result
+ * and a negative error code otherwise.
+ */
+int machine_id_get_app_specific(uuid_t *result, ...)
+{
+	static u8 hmac[SHA256_DIGEST_SIZE];
+	const void *data;
+	size_t size;
+	va_list args;
+	struct digest *d;
+	int ret;
+
+	if (!__machine_id_initialized)
+		return -ENODATA;
+
+	d = digest_alloc("hmac(sha256)");
+	if (!d)
+		return -ENOSYS;
+
+	ret = digest_set_key(d, __machine_id_hashable, __machine_id_hashable_length);
+	if (ret)
+		goto out;
+
+	ret = digest_init(d);
+	if (ret)
+		goto out;
+
+	ret = -ENODATA;
+
+	va_start(args, result);
+
+	while ((data = va_arg(args, const void *))) {
+		size = va_arg(args, size_t);
+
+		ret = digest_update(d, data, size);
+		if (ret)
+			break;
+	}
+
+	va_end(args);
+
+	if (ret)
+		goto out;
+
+	ret = digest_final(d, hmac);
+	if (ret)
+		goto out;
+
+	/* Take only the first half. */
+	memcpy(result, hmac, min(sizeof(hmac), sizeof(*result)));
+
+	uuid_make_v4(result);
+
+out:
+	digest_free(d);
+
+	return ret;
+}
+
 static int machine_id_set_globalvar(void)
 {
 	struct digest *digest = NULL;
@@ -61,6 +140,7 @@ static int machine_id_set_globalvar(void)
 	env_machine_id = basprintf("%.*s", MACHINE_ID_LENGTH, hex_machine_id);
 	globalvar_add_simple("machine_id", env_machine_id);
 	free(env_machine_id);
+	__machine_id_initialized = true;
 
 out:
 	digest_free(digest);
diff --git a/include/linux/uuid.h b/include/linux/uuid.h
index 6b1a3efa1e0b..1e4ffb343452 100644
--- a/include/linux/uuid.h
+++ b/include/linux/uuid.h
@@ -107,6 +107,14 @@ extern const u8 uuid_index[16];
 int guid_parse(const char *uuid, guid_t *u);
 int uuid_parse(const char *uuid, uuid_t *u);
 
+static inline void uuid_make_v4(uuid_t *u) {
+	/* Set UUID version to 4 --- truly random generation */
+	u->b[6] = (u->b[6] & 0x0F) | 0x40;
+
+	/* Set the UUID variant to DCE */
+	u->b[8] = (u->b[8] & 0x3F) | 0x80;
+}
+
 /* MEI UUID type, don't use anywhere else */
 #include <uapi/linux/uuid.h>
 
diff --git a/include/machine_id.h b/include/machine_id.h
index e30bbada1acd..9245a5412770 100644
--- a/include/machine_id.h
+++ b/include/machine_id.h
@@ -3,9 +3,13 @@
 #ifndef __MACHINE_ID_H__
 #define __MACHINE_ID_H__
 
+#include <linux/types.h>
+#include <linux/uuid.h>
+
 #if IS_ENABLED(CONFIG_MACHINE_ID)
 
 void machine_id_set_hashable(const void *hashable, size_t len);
+int machine_id_get_app_specific(uuid_t *result, ...) __attribute__((__sentinel__));
 
 #else
 
@@ -13,6 +17,13 @@ static inline void machine_id_set_hashable(const void *hashable, size_t len)
 {
 }
 
+static inline int machine_id_get_app_specific(uuid_t *result, ...)
+	__attribute__((__sentinel__));
+static inline int machine_id_get_app_specific(uuid_t *result, ...)
+{
+	return -ENOSYS;
+}
+
 #endif /* CONFIG_MACHINE_ID */
 
 #endif  /* __MACHINE_ID_H__ */
-- 
2.42.0.586.gbc5204569f7d.dirty




^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] net: add generic MAC address derivation from machine ID
  2023-11-15  9:02 [PATCH v2 0/2] Allow generating MAC addresses from machine ID Uwe Kleine-König
  2023-11-15  9:02 ` [PATCH v2 1/2] common: machine_id: support deriving app specific UUIDs Uwe Kleine-König
@ 2023-11-15  9:02 ` Uwe Kleine-König
  2023-11-21  8:33 ` [PATCH v2 0/2] Allow generating MAC addresses " Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Uwe Kleine-König @ 2023-11-15  9:02 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Ahmad Fatoum, Alexander Shiyan, Thorsten Scherer, Ahmad Fatoum, barebox

From: Ahmad Fatoum <ahmad@a3f.at>

Especially during development, devices often lack a MAC address. While a
MAC address can be easily added to the environment:

  nv dev.eth0.ethaddr="aa:bb:cc:dd:ee:ff"

It's easily lost when flashing complete new images, e.g. from CI.
Make the development experience neater by deriving a stable MAC address
if possible.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/net.h |  2 ++
 net/Kconfig   | 17 +++++++++++++++++
 net/eth.c     | 15 ++++++++++++---
 net/net.c     | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 78 insertions(+), 5 deletions(-)

diff --git a/include/net.h b/include/net.h
index a0ef8bee0404..de43c29f74ac 100644
--- a/include/net.h
+++ b/include/net.h
@@ -418,6 +418,8 @@ static inline int is_broadcast_ether_addr(const u8 *addr)
 #define ETH_ALEN	6	/* Octets in an Ethernet address */
 #define ETH_HLEN	14	/* Total octets in header.*/
 
+int generate_ether_addr(u8 *addr, int ethid);
+
 /**
  * random_ether_addr - Generate software assigned random Ethernet address
  * @addr: Pointer to a six-byte array containing the Ethernet address
diff --git a/net/Kconfig b/net/Kconfig
index 59f14c23cba2..07e623670e22 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -6,6 +6,23 @@ menuconfig NET
 
 if NET
 
+config NET_ETHADDR_FROM_MACHINE_ID
+	bool
+	prompt "generate stable Ethernet address"
+	depends on MACHINE_ID && HAVE_DIGEST_SHA256 && HAVE_DIGEST_HMAC
+	help
+	  By default, barebox will generate random Ethernet addresses for
+	  interfaces that had no explicit Ethernet address set via
+	  either board code or NVMEM properties in device tree.
+
+	  Say y here, to randomize Ethernet addresses only if no machine ID
+	  is available. Should barebox have a machine ID, it will be used
+	  alongside the hostname to generate MAC addresses that are unlikely
+	  to change between subsequent runs of barebox.
+
+	  This is not recommended for use in production as it may leak
+	  information about the machine ID.
+
 config NET_NFS
 	bool
 	prompt "nfs support"
diff --git a/net/eth.c b/net/eth.c
index ccac5e2a6488..d1474ec57df3 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -10,6 +10,7 @@
 #include <dhcp.h>
 #include <net.h>
 #include <dma.h>
+#include <machine_id.h>
 #include <of.h>
 #include <of_net.h>
 #include <linux/phy.h>
@@ -554,10 +555,11 @@ void eth_open_all(void)
 	}
 }
 
-static int of_populate_ethaddr(void)
+static int populate_ethaddr(void)
 {
 	char str[sizeof("xx:xx:xx:xx:xx:xx")];
 	struct eth_device *edev;
+	bool generated = false;
 	int ret;
 
 	list_for_each_entry(edev, &netdev_list, list) {
@@ -566,14 +568,21 @@ static int of_populate_ethaddr(void)
 
 		ret = of_get_mac_addr_nvmem(edev->parent->of_node,
 					    edev->ethaddr);
+		if (IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID) && ret) {
+			ret = generate_ether_addr(edev->ethaddr, edev->dev.id);
+			generated = true;
+		}
 		if (ret)
 			continue;
 
 		ethaddr_to_string(edev->ethaddr, str);
-		dev_info(&edev->dev, "Got preset MAC address from device tree: %s\n", str);
+		if (generated)
+			dev_notice(&edev->dev, "Generated MAC address from unique id: %s\n", str);
+		else
+			dev_info(&edev->dev, "Got preset MAC address from NVMEM: %s\n", str);
 		eth_set_ethaddr(edev, edev->ethaddr);
 	}
 
 	return 0;
 }
-postenvironment_initcall(of_populate_ethaddr);
+postenvironment_initcall(populate_ethaddr);
diff --git a/net/net.c b/net/net.c
index bf2117ff7ec2..e38179491d7a 100644
--- a/net/net.c
+++ b/net/net.c
@@ -25,6 +25,7 @@
 #include <init.h>
 #include <globalvar.h>
 #include <magicvar.h>
+#include <machine_id.h>
 #include <linux/ctype.h>
 #include <linux/err.h>
 
@@ -365,6 +366,43 @@ IPaddr_t net_get_gateway(void)
 
 static LIST_HEAD(connection_list);
 
+/**
+ * generate_ether_addr - Generates stable software assigned Ethernet address
+ * @addr: Pointer to a six-byte array to contain the Ethernet address
+ * @ethid: index of the Ethernet interface
+ *
+ * Derives an Ethernet address (MAC) from the machine ID, that's stable
+ * per board that is not multicast and has the local assigned bit set.
+ *
+ * Return 0 if an address could be generated or a negative error code otherwise.
+ */
+int generate_ether_addr(u8 *ethaddr, int ethid)
+{
+	const char *hostname;
+	uuid_t id;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID))
+		return -ENOSYS;
+
+	hostname = barebox_get_hostname();
+	if (!hostname)
+		return -EINVAL;
+
+	ret = machine_id_get_app_specific(&id, ARRAY_AND_SIZE("barebox-macaddr:"),
+					  hostname, strlen(hostname), NULL);
+	if (ret)
+		return ret;
+
+	memcpy(ethaddr, &id.b, ETH_ALEN);
+	eth_addr_add(ethaddr, ethid);
+
+	ethaddr[0] &= 0xfe;	/* clear multicast bit */
+	ethaddr[0] |= 0x02;	/* set local assignment bit (IEEE802) */
+
+	return 0;
+}
+
 static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest,
 				      rx_handler_f *handler, void *ctx)
 {
@@ -381,9 +419,16 @@ static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest,
 
 	if (!is_valid_ether_addr(edev->ethaddr)) {
 		char str[sizeof("xx:xx:xx:xx:xx:xx")];
-		random_ether_addr(edev->ethaddr);
+
+		ret = generate_ether_addr(edev->ethaddr, edev->dev.id);
+		if (ret)
+			random_ether_addr(edev->ethaddr);
+
 		ethaddr_to_string(edev->ethaddr, str);
-		dev_warn(&edev->dev, "No MAC address set. Using random address %s\n", str);
+
+		dev_warn(&edev->dev, "No MAC address set. Using %s %s\n",
+			 ret == 1 ? "address computed from unique ID" : "random address",
+			 str);
 		eth_set_ethaddr(edev, edev->ethaddr);
 	}
 
-- 
2.42.0.586.gbc5204569f7d.dirty




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 0/2] Allow generating MAC addresses from machine ID
  2023-11-15  9:02 [PATCH v2 0/2] Allow generating MAC addresses from machine ID Uwe Kleine-König
  2023-11-15  9:02 ` [PATCH v2 1/2] common: machine_id: support deriving app specific UUIDs Uwe Kleine-König
  2023-11-15  9:02 ` [PATCH v2 2/2] net: add generic MAC address derivation from machine ID Uwe Kleine-König
@ 2023-11-21  8:33 ` Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2023-11-21  8:33 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Alexander Shiyan, Thorsten Scherer, Ahmad Fatoum, barebox

On Wed, Nov 15, 2023 at 10:02:39AM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> this series contains two patches by Ahmad that he send earlier starting
> with Message-Id: <20230911155927.3786335-1-a.fatoum@pengutronix.de>.
> 
> Patch #1 was already applied back then as 9831b2e5fed8 ("common:
> machine_id: support deriving app specific UUIDs").
> 
> Changes since (implicit) v1:
> 
>  - fix compilation with MACHINE_ID=n (Sascha)
>  - fix typo in NET_ETHADDR_FROM_MACHINE_ID helptext (Thorsten)
>  - rename of_populate_ethaddr -> populate_ethaddr as it's not about of any more (Sascha)

This series neither applies to master nor to next, please resend

Sascha

> 
> On Tue, Sep 12, 2023 at 12:49:03PM +0200, Sascha Hauer wrote:
> > On Mon, Sep 11, 2023 at 05:59:27PM +0200, Ahmad Fatoum wrote:
> > > @@ -566,11 +568,18 @@ static int of_populate_ethaddr(void)
> > >
> > >             ret = of_get_mac_addr_nvmem(edev->parent->of_node,
> > >                                         edev->ethaddr);
> > > +           if (ret && IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID)) {
> >
> > This check doesn't seem to be needed, generate_ether_addr() already
> > returns -ENOSYS when this option is not enabled.
> 
> I kept this check, Ahmad already argued that is should be kept. (I only
> swapped the checks to have the static one first which is IMHO more
> natural.)
> 
> Best regards
> Uwe
> 
> Ahmad Fatoum (2):
>   common: machine_id: support deriving app specific UUIDs
>   net: add generic MAC address derivation from machine ID
> 
>  common/machine_id.c  | 84 ++++++++++++++++++++++++++++++++++++++++++--
>  include/linux/uuid.h |  8 +++++
>  include/machine_id.h | 11 ++++++
>  include/net.h        |  2 ++
>  net/Kconfig          | 17 +++++++++
>  net/eth.c            | 15 ++++++--
>  net/net.c            | 49 ++++++++++++++++++++++++--
>  7 files changed, 179 insertions(+), 7 deletions(-)
> 
> base-commit: bc5e49335067d0c6c6e97c082a0368fe9d86b725
> -- 
> 2.42.0.586.gbc5204569f7d.dirty
> 
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-11-21  8:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-15  9:02 [PATCH v2 0/2] Allow generating MAC addresses from machine ID Uwe Kleine-König
2023-11-15  9:02 ` [PATCH v2 1/2] common: machine_id: support deriving app specific UUIDs Uwe Kleine-König
2023-11-15  9:02 ` [PATCH v2 2/2] net: add generic MAC address derivation from machine ID Uwe Kleine-König
2023-11-21  8:33 ` [PATCH v2 0/2] Allow generating MAC addresses " Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox