diff --git a/Makefile-man.am b/Makefile-man.am
index 013e0d79671..228e29fc4f4 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -397,6 +397,7 @@ MANPAGES_ALIAS += \
man/sd_id128_from_string.3 \
man/sd_id128_get_boot.3 \
man/sd_id128_get_invocation.3 \
+ man/sd_id128_get_machine_app_specific.3 \
man/sd_id128_is_null.3 \
man/sd_id128_t.3 \
man/sd_is_mq.3 \
@@ -750,6 +751,7 @@ man/sd_id128_equal.3: man/sd-id128.3
man/sd_id128_from_string.3: man/sd_id128_to_string.3
man/sd_id128_get_boot.3: man/sd_id128_get_machine.3
man/sd_id128_get_invocation.3: man/sd_id128_get_machine.3
+man/sd_id128_get_machine_app_specific.3: man/sd_id128_get_machine.3
man/sd_id128_is_null.3: man/sd-id128.3
man/sd_id128_t.3: man/sd-id128.3
man/sd_is_mq.3: man/sd_is_fifo.3
@@ -1531,6 +1533,9 @@ man/sd_id128_get_boot.html: man/sd_id128_get_machine.html
man/sd_id128_get_invocation.html: man/sd_id128_get_machine.html
$(html-alias)
+man/sd_id128_get_machine_app_specific.html: man/sd_id128_get_machine.html
+ $(html-alias)
+
man/sd_id128_is_null.html: man/sd-id128.html
$(html-alias)
diff --git a/man/machine-id.xml b/man/machine-id.xml
index a722649de4e..3c261bffcc3 100644
--- a/man/machine-id.xml
+++ b/man/machine-id.xml
@@ -71,13 +71,14 @@
This machine ID adheres to the same format and logic as the
D-Bus machine ID.
- This ID uniquely identifies the host. It should be considered "confidential", and must not
- be exposed in untrusted environments, in particular on the network. If a stable unique
- identifier that is tied to the machine is needed for some application, the machine ID or any
- part of it must not be used directly. Instead the machine ID should be hashed with a
- cryptographic, keyed hash function, using a fixed, application-specific key. That way the ID
- will be properly unique, and derived in a constant way from the machine ID but there will be no
- way to retrieve the original machine ID from the application-specific one.
+ This ID uniquely identifies the host. It should be considered "confidential", and must not be exposed in
+ untrusted environments, in particular on the network. If a stable unique identifier that is tied to the machine is
+ needed for some application, the machine ID or any part of it must not be used directly. Instead the machine ID
+ should be hashed with a cryptographic, keyed hash function, using a fixed, application-specific key. That way the
+ ID will be properly unique, and derived in a constant way from the machine ID but there will be no way to retrieve
+ the original machine ID from the application-specific one. The
+ sd_id128_get_machine_app_specific3
+ API provides an implementation of such an algorithm.
The
systemd-machine-id-setup1
diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml
index 9a86c24aed1..3938c6d836c 100644
--- a/man/sd_id128_get_machine.xml
+++ b/man/sd_id128_get_machine.xml
@@ -44,6 +44,7 @@
sd_id128_get_machine
+ sd_id128_get_machine_app_specific
sd_id128_get_boot
sd_id128_get_invocation
Retrieve 128-bit IDs
@@ -58,6 +59,12 @@
sd_id128_t *ret
+
+ int sd_id128_get_machine_app_specific
+ sd_id128_t app_id
+ sd_id128_t *ret
+
+
int sd_id128_get_boot
sd_id128_t *ret
@@ -74,11 +81,22 @@
Description
- sd_id128_get_machine() returns the
- machine ID of the executing host. This reads and parses the
- machine-id5
- file. This function caches the machine ID internally to make
- retrieving the machine ID a cheap operation.
+ sd_id128_get_machine() returns the machine ID of the executing host. This reads and
+ parses the machine-id5
+ file. This function caches the machine ID internally to make retrieving the machine ID a cheap operation. This ID
+ may be used wherever a unique identifier for the local system is needed. However, it is recommended to use this ID
+ as-is only in trusted environments. In untrusted environments it is recommended to derive an application specific
+ ID from this machine ID, in an irreversable (cryptographically secure) way. To make this easy
+ sd_id128_get_machine_app_specific() is provided, see below.
+
+ sd_id128_get_machine_app_specific() is similar to
+ sd_id128_get_machine(), but retrieves a machine ID that is specific to the application that is
+ identified by the indicated application ID. It is recommended to use this function instead of
+ sd_id128_get_machine() when passing an ID to untrusted environments, in order to make sure
+ that the original machine ID may not be determined externally. The application-specific ID should be generated via
+ a tool like journalctl --new-id128, and may be compiled into the application. This function will
+ return the same application-specific ID for each combination of machine ID and application ID. Internally, this
+ function calculates HMAC-SHA256 of the application ID, keyed by the machine ID.
sd_id128_get_boot() returns the boot ID
of the executing kernel. This reads and parses the
@@ -95,10 +113,10 @@
systemd.exec5 for details. The
ID is cached internally. In future a different mechanism to determine the invocation ID may be added.
- Note that sd_id128_get_boot() and sd_id128_get_invocation() always
- return UUID v4 compatible IDs. sd_id128_get_machine() will also return a UUID v4-compatible
- ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible
- one. For more information, see
+ Note that sd_id128_get_machine_app_specific(), sd_id128_get_boot()
+ and sd_id128_get_invocation() always return UUID v4 compatible IDs.
+ sd_id128_get_machine() will also return a UUID v4-compatible ID on new installations but might
+ not on older. It is possible to convert the machine ID into a UUID v4-compatible one. For more information, see
machine-id5.
For more information about the sd_id128_t
@@ -117,12 +135,35 @@
Notes
- The sd_id128_get_machine(), sd_id128_get_boot() and
- sd_id128_get_invocation() interfaces are available as a shared library, which can be compiled
- and linked to with the libsystemd The sd_id128_get_machine(), sd_id128_get_machine_app_specific()
+ sd_id128_get_boot() and sd_id128_get_invocation() interfaces are
+ available as a shared library, which can be compiled and linked to with the
+ libsystemd pkg-config1 file.
+
+ Examples
+
+
+ Application-specific machine ID
+
+ Here's a simple example for an application specific machine ID:
+
+ #include <systemd/sd-id128.h>
+#include <stdio.h>
+
+#define OUR_APPLICATION_ID SD_ID128_MAKE(c2,73,27,73,23,db,45,4e,a6,3b,b9,6e,79,b5,3e,97)
+
+int main(int argc, char *argv[]) {
+ sd_id128_t id;
+ sd_id128_get_machine_app_specific(OUR_APPLICATION_ID, &id);
+ printf("Our application ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id));
+ return 0;
+}
+
+
+
See Also
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index d48ef6bbe2a..46c4dac7d71 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -511,3 +511,8 @@ global:
sd_bus_get_exit_on_disconnect;
sd_id128_get_invocation;
} LIBSYSTEMD_231;
+
+LIBSYSTEMD_233 {
+global:
+ sd_id128_get_machine_app_specific;
+} LIBSYSTEMD_232;
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index d4450c70a00..0d673ba655e 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -27,6 +27,7 @@
#include "hexdecoct.h"
#include "id128-util.h"
#include "io-util.h"
+#include "khash.h"
#include "macro.h"
#include "random-util.h"
#include "util.h"
@@ -181,3 +182,34 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) {
*ret = make_v4_uuid(t);
return 0;
}
+
+_public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
+ _cleanup_(khash_unrefp) khash *h = NULL;
+ sd_id128_t m, result;
+ const void *p;
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ r = sd_id128_get_machine(&m);
+ if (r < 0)
+ return r;
+
+ r = khash_new_with_key(&h, "hmac(sha256)", &m, sizeof(m));
+ if (r < 0)
+ return r;
+
+ r = khash_put(h, &app_id, sizeof(app_id));
+ if (r < 0)
+ return r;
+
+ r = khash_digest_data(h, &p);
+ if (r < 0)
+ return r;
+
+ /* We chop off the trailing 16 bytes */
+ memcpy(&result, p, MIN(khash_get_size(h), sizeof(result)));
+
+ *ret = make_v4_uuid(result);
+ return 0;
+}
diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h
index ee011b1861b..6cc8e4ac0e9 100644
--- a/src/systemd/sd-id128.h
+++ b/src/systemd/sd-id128.h
@@ -39,12 +39,12 @@ union sd_id128 {
#define SD_ID128_STRING_MAX 33
char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]);
-
int sd_id128_from_string(const char *s, sd_id128_t *ret);
int sd_id128_randomize(sd_id128_t *ret);
int sd_id128_get_machine(sd_id128_t *ret);
+int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret);
int sd_id128_get_boot(sd_id128_t *ret);
int sd_id128_get_invocation(sd_id128_t *ret);
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index 1c8e5549daf..ab5a111ba94 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -153,5 +153,11 @@ int main(int argc, char *argv[]) {
assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
+ assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0);
+ assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0);
+ assert_se(sd_id128_equal(id, id2));
+ assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), &id2) >= 0);
+ assert_se(!sd_id128_equal(id, id2));
+
return 0;
}