summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@microsoft.com>2021-10-09 19:37:59 +0200
committerGitHub <noreply@github.com>2021-10-09 19:37:59 +0200
commitccf609c88cacddcb5417d1aa1b9f56e55be45379 (patch)
treedb21f181f58dd56f5bba51ef2c9252dbbff500d7
parenttest: set 5 minute timeout on TEST-11-ISSUE-3166 and TEST-50-DISSECT (diff)
parentAdd benchmark for sha256 calculations (diff)
downloadsystemd-ccf609c88cacddcb5417d1aa1b9f56e55be45379.tar.xz
systemd-ccf609c88cacddcb5417d1aa1b9f56e55be45379.zip
Merge pull request #20915 from bluca/libsystemd_openssl
libsystemd/sd-id128: use only internal hmac, remove khash/OpenSSL support
-rw-r--r--LICENSES/README.md5
-rw-r--r--TODO2
-rw-r--r--src/basic/hmac.c62
-rw-r--r--src/basic/hmac.h12
-rw-r--r--src/basic/khash.c321
-rw-r--r--src/basic/khash.h37
-rw-r--r--src/basic/meson.build4
-rw-r--r--src/boot/efi/meson.build2
-rw-r--r--src/boot/efi/sha256.h28
-rw-r--r--src/fundamental/macro-fundamental.h2
-rw-r--r--src/fundamental/meson.build2
-rw-r--r--src/fundamental/sha256.c (renamed from src/boot/efi/sha256.c)94
-rw-r--r--src/fundamental/sha256.h32
-rw-r--r--src/fundamental/string-util-fundamental.c8
-rw-r--r--src/fundamental/string-util-fundamental.h4
-rw-r--r--src/fundamental/type.h3
-rw-r--r--src/libsystemd/meson.build3
-rw-r--r--src/libsystemd/sd-id128/sd-id128.c43
-rw-r--r--src/test/meson.build4
-rw-r--r--src/test/test-hash.c76
-rw-r--r--src/test/test-hmac.c76
-rw-r--r--src/test/test-id128.c58
22 files changed, 301 insertions, 577 deletions
diff --git a/LICENSES/README.md b/LICENSES/README.md
index f01049c13f..3c28de51b1 100644
--- a/LICENSES/README.md
+++ b/LICENSES/README.md
@@ -58,3 +58,8 @@ The following exceptions apply:
**BSD-3-Clause** license.
* any files under test/ without an explicit license we assume non-copyrightable
(eg: computer-generated fuzzer data)
+
+## OpenSSL Notes
+
+Note that building the systemd project with OpenSSL does not affect the libsystemd.so
+shared library, which is not linked with the OpenSSL library.
diff --git a/TODO b/TODO
index d8975158b9..776c90f12e 100644
--- a/TODO
+++ b/TODO
@@ -352,11 +352,9 @@ Features:
* unify on openssl (as soon as OpenSSL 3.0 is out, and the Debian license
confusion is gone)
- - port sd_id128_get_machine_app_specific() over from khash
- port resolved over from libgcrypt (DNSSEC code)
- port journald + fsprg over from libgcrypt
- port importd over from libgcrypt
- - when that's done: kill khash.c
- when that's done: kill gnutls support in resolved
* add growvol and makevol options for /etc/crypttab, similar to
diff --git a/src/basic/hmac.c b/src/basic/hmac.c
new file mode 100644
index 0000000000..1e4e380aaa
--- /dev/null
+++ b/src/basic/hmac.c
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <assert.h>
+#include <string.h>
+
+#include "hmac.h"
+#include "sha256.h"
+
+#define HMAC_BLOCK_SIZE 64
+#define INNER_PADDING_BYTE 0x36
+#define OUTER_PADDING_BYTE 0x5c
+
+void hmac_sha256(const void *key,
+ size_t key_size,
+ const void *input,
+ size_t input_size,
+ uint8_t res[static SHA256_DIGEST_SIZE]) {
+
+ uint8_t inner_padding[HMAC_BLOCK_SIZE] = { };
+ uint8_t outer_padding[HMAC_BLOCK_SIZE] = { };
+ uint8_t replacement_key[SHA256_DIGEST_SIZE];
+ struct sha256_ctx hash;
+
+ assert(key);
+ assert(key_size > 0);
+ assert(res);
+
+ /* Implement algorithm as described by FIPS 198. */
+
+ /* The key needs to be block size length or less, hash it if it's longer. */
+ if (key_size > HMAC_BLOCK_SIZE) {
+ sha256_init_ctx(&hash);
+ sha256_process_bytes(key, key_size, &hash);
+ sha256_finish_ctx(&hash, replacement_key);
+ key = replacement_key;
+ key_size = SHA256_DIGEST_SIZE;
+ }
+
+ /* First, copy the key into the padding arrays. If it's shorter than
+ * the block size, the arrays are already initialized to 0. */
+ memcpy(inner_padding, key, key_size);
+ memcpy(outer_padding, key, key_size);
+
+ /* Then, XOR the provided key and any padding leftovers with the fixed
+ * padding bytes as defined in FIPS 198. */
+ for (size_t i = 0; i < HMAC_BLOCK_SIZE; i++) {
+ inner_padding[i] ^= INNER_PADDING_BYTE;
+ outer_padding[i] ^= OUTER_PADDING_BYTE;
+ }
+
+ /* First pass: hash the inner padding array and the input. */
+ sha256_init_ctx(&hash);
+ sha256_process_bytes(inner_padding, HMAC_BLOCK_SIZE, &hash);
+ sha256_process_bytes(input, input_size, &hash);
+ sha256_finish_ctx(&hash, res);
+
+ /* Second pass: hash the outer padding array and the result of the first pass. */
+ sha256_init_ctx(&hash);
+ sha256_process_bytes(outer_padding, HMAC_BLOCK_SIZE, &hash);
+ sha256_process_bytes(res, SHA256_DIGEST_SIZE, &hash);
+ sha256_finish_ctx(&hash, res);
+}
diff --git a/src/basic/hmac.h b/src/basic/hmac.h
new file mode 100644
index 0000000000..12b594c09b
--- /dev/null
+++ b/src/basic/hmac.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define SHA256_DIGEST_SIZE 32
+
+/* Unoptimized implementation based on FIPS 198. 'res' has to be allocated by
+ * the caller. Prefer external OpenSSL functions, and use this only when
+ * linking to OpenSSL is not desireable (eg: libsystemd.so). */
+void hmac_sha256(const void *key, size_t key_size, const void *input, size_t input_size, uint8_t res[static SHA256_DIGEST_SIZE]);
diff --git a/src/basic/khash.c b/src/basic/khash.c
deleted file mode 100644
index 6a4d1dd594..0000000000
--- a/src/basic/khash.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <linux/if_alg.h>
-#include <stdbool.h>
-#include <sys/socket.h>
-
-#include "alloc-util.h"
-#include "fd-util.h"
-#include "hexdecoct.h"
-#include "khash.h"
-#include "macro.h"
-#include "missing_socket.h"
-#include "string-util.h"
-#include "util.h"
-
-/* On current kernels the maximum digest (according to "grep digestsize /proc/crypto | sort -u") is actually 32, but
- * let's add some extra room, the few wasted bytes don't really matter... */
-#define LONGEST_DIGEST 128
-
-struct khash {
- int fd;
- char *algorithm;
- uint8_t digest[LONGEST_DIGEST+1];
- size_t digest_size;
- bool digest_valid;
-};
-
-int khash_supported(void) {
- static const union {
- struct sockaddr sa;
- struct sockaddr_alg alg;
- } sa = {
- .alg.salg_family = AF_ALG,
- .alg.salg_type = "hash",
- .alg.salg_name = "sha256", /* a very common algorithm */
- };
-
- static int cached = -1;
-
- if (cached < 0) {
- _cleanup_close_ int fd1 = -1, fd2 = -1;
- uint8_t buf[LONGEST_DIGEST+1];
-
- fd1 = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
- if (fd1 < 0) {
- /* The kernel returns EAFNOSUPPORT if AF_ALG is not supported at all */
- if (IN_SET(errno, EAFNOSUPPORT, EOPNOTSUPP))
- return (cached = false);
-
- return -errno;
- }
-
- if (bind(fd1, &sa.sa, sizeof(sa)) < 0) {
- /* The kernel returns ENOENT if the selected algorithm is not supported at all. We use a check
- * for SHA256 as a proxy for whether the whole API is supported at all. After all it's one of
- * the most common hash functions, and if it isn't supported, that's ample indication that
- * something is really off. */
-
- if (IN_SET(errno, ENOENT, EOPNOTSUPP))
- return (cached = false);
-
- return -errno;
- }
-
- fd2 = accept4(fd1, NULL, 0, SOCK_CLOEXEC);
- if (fd2 < 0) {
- if (errno == EOPNOTSUPP)
- return (cached = false);
-
- return -errno;
- }
-
- if (recv(fd2, buf, sizeof(buf), 0) < 0) {
- /* On some kernels we get ENOKEY for non-keyed hash functions (such as sha256), let's refuse
- * using the API in those cases, since the kernel is
- * broken. https://github.com/systemd/systemd/issues/8278 */
-
- if (IN_SET(errno, ENOKEY, EOPNOTSUPP))
- return (cached = false);
- }
-
- cached = true;
- }
-
- return cached;
-}
-
-int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size) {
- union {
- struct sockaddr sa;
- struct sockaddr_alg alg;
- } sa = {
- .alg.salg_family = AF_ALG,
- .alg.salg_type = "hash",
- };
-
- _cleanup_(khash_unrefp) khash *h = NULL;
- _cleanup_close_ int fd = -1;
- int supported;
- ssize_t n;
-
- assert(ret);
- assert(key || key_size == 0);
-
- /* Filter out an empty algorithm early, as we do not support an algorithm by that name. */
- if (isempty(algorithm))
- return -EINVAL;
-
- /* Overly long hash algorithm names we definitely do not support */
- if (strlen(algorithm) >= sizeof(sa.alg.salg_name))
- return -EOPNOTSUPP;
-
- supported = khash_supported();
- if (supported < 0)
- return supported;
- if (supported == 0)
- return -EOPNOTSUPP;
-
- fd = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
- if (fd < 0)
- return -errno;
-
- strcpy((char*) sa.alg.salg_name, algorithm);
- if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
- if (errno == ENOENT)
- return -EOPNOTSUPP;
- return -errno;
- }
-
- if (key) {
- if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, key_size) < 0)
- return -errno;
- }
-
- h = new0(khash, 1);
- if (!h)
- return -ENOMEM;
-
- h->fd = accept4(fd, NULL, 0, SOCK_CLOEXEC);
- if (h->fd < 0)
- return -errno;
-
- h->algorithm = strdup(algorithm);
- if (!h->algorithm)
- return -ENOMEM;
-
- /* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */
- (void) send(h->fd, NULL, 0, 0);
-
- /* Figure out the digest size */
- n = recv(h->fd, h->digest, sizeof(h->digest), 0);
- if (n < 0)
- return -errno;
- if (n >= LONGEST_DIGEST) /* longer than what we expected? If so, we don't support this */
- return -EOPNOTSUPP;
-
- h->digest_size = (size_t) n;
- h->digest_valid = true;
-
- /* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */
- (void) send(h->fd, NULL, 0, 0);
-
- *ret = TAKE_PTR(h);
-
- return 0;
-}
-
-int khash_new(khash **ret, const char *algorithm) {
- return khash_new_with_key(ret, algorithm, NULL, 0);
-}
-
-khash* khash_unref(khash *h) {
- if (!h)
- return NULL;
-
- safe_close(h->fd);
- free(h->algorithm);
- return mfree(h);
-}
-
-int khash_dup(khash *h, khash **ret) {
- _cleanup_(khash_unrefp) khash *copy = NULL;
-
- assert(h);
- assert(ret);
-
- copy = newdup(khash, h, 1);
- if (!copy)
- return -ENOMEM;
-
- copy->fd = -1;
- copy->algorithm = strdup(h->algorithm);
- if (!copy->algorithm)
- return -ENOMEM;
-
- copy->fd = accept4(h->fd, NULL, 0, SOCK_CLOEXEC);
- if (copy->fd < 0)
- return -errno;
-
- *ret = TAKE_PTR(copy);
-
- return 0;
-}
-
-const char *khash_get_algorithm(khash *h) {
- assert(h);
-
- return h->algorithm;
-}
-
-size_t khash_get_size(khash *h) {
- assert(h);
-
- return h->digest_size;
-}
-
-int khash_reset(khash *h) {
- ssize_t n;
-
- assert(h);
-
- n = send(h->fd, NULL, 0, 0);
- if (n < 0)
- return -errno;
-
- h->digest_valid = false;
-
- return 0;
-}
-
-int khash_put(khash *h, const void *buffer, size_t size) {
- ssize_t n;
-
- assert(h);
- assert(buffer || size == 0);
-
- if (size <= 0)
- return 0;
-
- n = send(h->fd, buffer, size, MSG_MORE);
- if (n < 0)
- return -errno;
-
- h->digest_valid = false;
-
- return 0;
-}
-
-int khash_put_iovec(khash *h, const struct iovec *iovec, size_t n) {
- struct msghdr mh = {
- .msg_iov = (struct iovec*) iovec,
- .msg_iovlen = n,
- };
- ssize_t k;
-
- assert(h);
- assert(iovec || n == 0);
-
- if (n <= 0)
- return 0;
-
- k = sendmsg(h->fd, &mh, MSG_MORE);
- if (k < 0)
- return -errno;
-
- h->digest_valid = false;
-
- return 0;
-}
-
-static int retrieve_digest(khash *h) {
- ssize_t n;
-
- assert(h);
-
- if (h->digest_valid)
- return 0;
-
- n = recv(h->fd, h->digest, h->digest_size, 0);
- if (n < 0)
- return n;
- if ((size_t) n != h->digest_size) /* digest size changed? */
- return -EIO;
-
- h->digest_valid = true;
-
- return 0;
-}
-
-int khash_digest_data(khash *h, const void **ret) {
- int r;
-
- assert(h);
- assert(ret);
-
- r = retrieve_digest(h);
- if (r < 0)
- return r;
-
- *ret = h->digest;
- return 0;
-}
-
-int khash_digest_string(khash *h, char **ret) {
- int r;
- char *p;
-
- assert(h);
- assert(ret);
-
- r = retrieve_digest(h);
- if (r < 0)
- return r;
-
- p = hexmem(h->digest, h->digest_size);
- if (!p)
- return -ENOMEM;
-
- *ret = p;
- return 0;
-}
diff --git a/src/basic/khash.h b/src/basic/khash.h
deleted file mode 100644
index a343d306e9..0000000000
--- a/src/basic/khash.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-
-#include "macro.h"
-
-typedef struct khash khash;
-
-int khash_supported(void);
-
-/* For plain hash functions. Hash functions commonly supported on today's kernels are: crc32c, crct10dif, crc32,
- * sha224, sha256, sha512, sha384, sha1, md5, md4, sha3-224, sha3-256, sha3-384, sha3-512, and more. */
-int khash_new(khash **ret, const char *algorithm);
-
-/* For keyed hash functions. Hash functions commonly supported on today's kernels are: hmac(sha256), cmac(aes),
- * cmac(des3_ede), hmac(sha3-512), hmac(sha3-384), hmac(sha3-256), hmac(sha3-224), hmac(rmd160), hmac(rmd128),
- * hmac(sha224), hmac(sha512), hmac(sha384), hmac(sha1), hmac(md5), and more. */
-int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size);
-
-int khash_dup(khash *h, khash **ret);
-khash* khash_unref(khash *h);
-
-const char *khash_get_algorithm(khash *h);
-size_t khash_get_size(khash *h);
-
-int khash_reset(khash *h);
-
-int khash_put(khash *h, const void *buffer, size_t size);
-int khash_put_iovec(khash *h, const struct iovec *iovec, size_t n);
-
-int khash_digest_data(khash *h, const void **ret);
-int khash_digest_string(khash *h, char **ret);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(khash*, khash_unref);
diff --git a/src/basic/meson.build b/src/basic/meson.build
index adb7b666c6..cf97f6de1d 100644
--- a/src/basic/meson.build
+++ b/src/basic/meson.build
@@ -72,6 +72,8 @@ basic_sources = files('''
hashmap.h
hexdecoct.c
hexdecoct.h
+ hmac.c
+ hmac.h
hostname-util.c
hostname-util.h
in-addr-util.c
@@ -80,8 +82,6 @@ basic_sources = files('''
inotify-util.h
io-util.c
io-util.h
- khash.c
- khash.h
limits-util.c
limits-util.h
linux/btrfs.h
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
index fef8572c6a..81b750d5d3 100644
--- a/src/boot/efi/meson.build
+++ b/src/boot/efi/meson.build
@@ -12,7 +12,6 @@ efi_headers = files('''
missing_efi.h
pe.h
random-seed.h
- sha256.h
shim.h
splash.h
util.h
@@ -34,7 +33,6 @@ systemd_boot_sources = '''
devicetree.c
drivers.c
random-seed.c
- sha256.c
shim.c
'''.split()
diff --git a/src/boot/efi/sha256.h b/src/boot/efi/sha256.h
deleted file mode 100644
index 464be59c25..0000000000
--- a/src/boot/efi/sha256.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <efi.h>
-#include <efilib.h>
-
-struct sha256_ctx {
- UINT32 H[8];
-
- union {
- UINT64 total64;
-#define TOTAL64_low (1 - (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
-#define TOTAL64_high (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
- UINT32 total[2];
- };
-
- UINT32 buflen;
-
- union {
- UINT8 buffer[128]; /* NB: always correctly aligned for UINT32. */
- UINT32 buffer32[32];
- UINT64 buffer64[16];
- };
-};
-
-void sha256_init_ctx(struct sha256_ctx *ctx);
-void *sha256_finish_ctx(struct sha256_ctx *ctx, VOID *resbuf);
-void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx);
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h
index 20d8dabf29..7fa4b85be7 100644
--- a/src/fundamental/macro-fundamental.h
+++ b/src/fundamental/macro-fundamental.h
@@ -59,6 +59,8 @@
#define assert(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); })
#define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#endif
+
+ #define memcpy(a, b, c) CopyMem((a), (b), (c))
#endif
#if defined(static_assert)
diff --git a/src/fundamental/meson.build b/src/fundamental/meson.build
index 3c43081cf6..3aa9fab8cb 100644
--- a/src/fundamental/meson.build
+++ b/src/fundamental/meson.build
@@ -6,10 +6,12 @@ fundamental_headers = files(
'efi-loader-features.h',
'macro-fundamental.h',
'string-util-fundamental.h',
+ 'sha256.h',
'type.h')
sources = '''
string-util-fundamental.c
+ sha256.c
'''.split()
# for sd-boot
diff --git a/src/boot/efi/sha256.c b/src/fundamental/sha256.c
index d2e267eeff..0577a24920 100644
--- a/src/boot/efi/sha256.c
+++ b/src/fundamental/sha256.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/* Stolen from glibc and converted to UEFI style. In glibc it comes with the following copyright blurb: */
+/* Stolen from glibc and converted to our style. In glibc it comes with the following copyright blurb: */
/* Functions to compute SHA256 message digest of files or memory blocks.
according to the definition of SHA256 in FIPS 180-2.
@@ -23,6 +23,10 @@
/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
+#ifndef SD_BOOT
+#include <string.h>
+#endif
+
#include "macro-fundamental.h"
#include "sha256.h"
@@ -45,12 +49,12 @@
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (FIPS 180-2:5.1.1) */
-static const UINT8 fillbuf[64] = {
+static const uint8_t fillbuf[64] = {
0x80, 0 /* , 0, 0, ... */
};
/* Constants for SHA256 from FIPS 180-2:4.2.2. */
-static const UINT32 K[64] = {
+static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@@ -69,7 +73,7 @@ static const UINT32 K[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
-static void sha256_process_block(const void *, UINTN, struct sha256_ctx *);
+static void sha256_process_block(const void *, size_t, struct sha256_ctx *);
/* Initialize structure containing state of computation.
(FIPS 180-2:5.3.2) */
@@ -96,8 +100,8 @@ void sha256_init_ctx(struct sha256_ctx *ctx) {
aligned for a 32 bits value. */
void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Take yet unprocessed bytes into account. */
- UINT32 bytes = ctx->buflen;
- UINTN pad;
+ uint32_t bytes = ctx->buflen;
+ size_t pad;
assert(ctx);
assert(resbuf);
@@ -106,7 +110,7 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
ctx->total64 += bytes;
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
- CopyMem(&ctx->buffer[bytes], fillbuf, pad);
+ memcpy(&ctx->buffer[bytes], fillbuf, pad);
/* Put the 64-bit file length in *bits* at the end of the buffer. */
ctx->buffer32[(bytes + pad + 4) / 4] = SWAP(ctx->total[TOTAL64_low] << 3);
@@ -117,13 +121,13 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
sha256_process_block(ctx->buffer, bytes + pad + 8, ctx);
/* Put result from CTX in first 32 bytes following RESBUF. */
- for (UINTN i = 0; i < 8; ++i)
- ((UINT32 *) resbuf)[i] = SWAP(ctx->H[i]);
+ for (size_t i = 0; i < 8; ++i)
+ ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
return resbuf;
}
-void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx) {
+void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx) {
assert(buffer);
assert(ctx);
@@ -131,10 +135,10 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
both inputs first. */
if (ctx->buflen != 0) {
- UINTN left_over = ctx->buflen;
- UINTN add = 128 - left_over > len ? len : 128 - left_over;
+ size_t left_over = ctx->buflen;
+ size_t add = 128 - left_over > len ? len : 128 - left_over;
- CopyMem(&ctx->buffer[left_over], buffer, add);
+ memcpy(&ctx->buffer[left_over], buffer, add);
ctx->buflen += add;
if (ctx->buflen > 64) {
@@ -142,7 +146,7 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap. */
- CopyMem(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+ memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
ctx->buflen);
}
@@ -159,13 +163,13 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
/* To check alignment gcc has an appropriate operator. Other compilers don't. */
# if __GNUC__ >= 2
-# define UNALIGNED_P(p) (((UINTN) p) % __alignof__(UINT32) != 0)
+# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0)
# else
-# define UNALIGNED_P(p) (((UINTN) p) % sizeof(UINT32) != 0)
+# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0)
# endif
if (UNALIGNED_P(buffer))
while (len > 64) {
- CopyMem(ctx->buffer, buffer, 64);
+ memcpy(ctx->buffer, buffer, 64);
sha256_process_block(ctx->buffer, 64, ctx);
buffer = (const char *) buffer + 64;
len -= 64;
@@ -181,14 +185,14 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
/* Move remaining bytes into internal buffer. */
if (len > 0) {
- UINTN left_over = ctx->buflen;
+ size_t left_over = ctx->buflen;
- CopyMem(&ctx->buffer[left_over], buffer, len);
+ memcpy(&ctx->buffer[left_over], buffer, len);
left_over += len;
if (left_over >= 64) {
sha256_process_block(ctx->buffer, 64, ctx);
left_over -= 64;
- CopyMem(ctx->buffer, &ctx->buffer[64], left_over);
+ memcpy(ctx->buffer, &ctx->buffer[64], left_over);
}
ctx->buflen = left_over;
}
@@ -197,21 +201,21 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
/* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0. */
-static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ctx *ctx) {
- const UINT32 *words = buffer;
- UINTN nwords = len / sizeof(UINT32);
+static void sha256_process_block(const void *buffer, size_t len, struct sha256_ctx *ctx) {
+ const uint32_t *words = buffer;
+ size_t nwords = len / sizeof(uint32_t);
assert(buffer);
assert(ctx);
- UINT32 a = ctx->H[0];
- UINT32 b = ctx->H[1];
- UINT32 c = ctx->H[2];
- UINT32 d = ctx->H[3];
- UINT32 e = ctx->H[4];
- UINT32 f = ctx->H[5];
- UINT32 g = ctx->H[6];
- UINT32 h = ctx->H[7];
+ uint32_t a = ctx->H[0];
+ uint32_t b = ctx->H[1];
+ uint32_t c = ctx->H[2];
+ uint32_t d = ctx->H[3];
+ uint32_t e = ctx->H[4];
+ uint32_t f = ctx->H[5];
+ uint32_t g = ctx->H[6];
+ uint32_t h = ctx->H[7];
/* First increment the byte count. FIPS 180-2 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
@@ -221,15 +225,15 @@ static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ct
/* Process all bytes in the buffer with 64 bytes in each round of
the loop. */
while (nwords > 0) {
- UINT32 W[64];
- UINT32 a_save = a;
- UINT32 b_save = b;
- UINT32 c_save = c;
- UINT32 d_save = d;
- UINT32 e_save = e;
- UINT32 f_save = f;
- UINT32 g_save = g;
- UINT32 h_save = h;
+ uint32_t W[64];
+ uint32_t a_save = a;
+ uint32_t b_save = b;
+ uint32_t c_save = c;
+ uint32_t d_save = d;
+ uint32_t e_save = e;
+ uint32_t f_save = f;
+ uint32_t g_save = g;
+ uint32_t h_save = h;
/* Operators defined in FIPS 180-2:4.1.2. */
#define Ch(x, y, z) ((x & y) ^ (~x & z))
@@ -244,17 +248,17 @@ static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ct
#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
/* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
- for (UINTN t = 0; t < 16; ++t) {
+ for (size_t t = 0; t < 16; ++t) {
W[t] = SWAP (*words);
++words;
}
- for (UINTN t = 16; t < 64; ++t)
+ for (size_t t = 16; t < 64; ++t)
W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
/* The actual computation according to FIPS 180-2:6.2.2 step 3. */
- for (UINTN t = 0; t < 64; ++t) {
- UINT32 T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
- UINT32 T2 = S0 (a) + Maj (a, b, c);
+ for (size_t t = 0; t < 64; ++t) {
+ uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
+ uint32_t T2 = S0 (a) + Maj (a, b, c);
h = g;
g = f;
f = e;
diff --git a/src/fundamental/sha256.h b/src/fundamental/sha256.h
new file mode 100644
index 0000000000..9fc090b4e0
--- /dev/null
+++ b/src/fundamental/sha256.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifdef SD_BOOT
+#include <efi.h>
+#include <efilib.h>
+#endif
+
+#include "type.h"
+
+struct sha256_ctx {
+ uint32_t H[8];
+
+ union {
+ uint64_t total64;
+#define TOTAL64_low (1 - (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
+#define TOTAL64_high (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ uint32_t total[2];
+ };
+
+ uint32_t buflen;
+
+ union {
+ uint8_t buffer[128]; /* NB: always correctly aligned for UINT32. */
+ uint32_t buffer32[32];
+ uint64_t buffer64[16];
+ };
+};
+
+void sha256_init_ctx(struct sha256_ctx *ctx);
+void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf);
+void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx);
diff --git a/src/fundamental/string-util-fundamental.c b/src/fundamental/string-util-fundamental.c
index 383e390577..101d3f7196 100644
--- a/src/fundamental/string-util-fundamental.c
+++ b/src/fundamental/string-util-fundamental.c
@@ -8,7 +8,7 @@
#include "string-util-fundamental.h"
sd_char *startswith(const sd_char *s, const sd_char *prefix) {
- sd_size_t l;
+ size_t l;
assert(s);
assert(prefix);
@@ -22,7 +22,7 @@ sd_char *startswith(const sd_char *s, const sd_char *prefix) {
#ifndef SD_BOOT
sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
- sd_size_t l;
+ size_t l;
assert(s);
assert(prefix);
@@ -36,7 +36,7 @@ sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
#endif
sd_char* endswith(const sd_char *s, const sd_char *postfix) {
- sd_size_t sl, pl;
+ size_t sl, pl;
assert(s);
assert(postfix);
@@ -57,7 +57,7 @@ sd_char* endswith(const sd_char *s, const sd_char *postfix) {
}
sd_char* endswith_no_case(const sd_char *s, const sd_char *postfix) {
- sd_size_t sl, pl;
+ size_t sl, pl;
assert(s);
assert(postfix);
diff --git a/src/fundamental/string-util-fundamental.h b/src/fundamental/string-util-fundamental.h
index 7455c05492..dc0c1202be 100644
--- a/src/fundamental/string-util-fundamental.h
+++ b/src/fundamental/string-util-fundamental.h
@@ -68,10 +68,10 @@ static inline const sd_char *yes_no(sd_bool b) {
sd_int strverscmp_improved(const sd_char *a, const sd_char *b);
/* Like startswith(), but operates on arbitrary memory blocks */
-static inline void *memory_startswith(const void *p, sd_size_t sz, const sd_char *token) {
+static inline void *memory_startswith(const void *p, size_t sz, const sd_char *token) {
assert(token);
- sd_size_t n = strlen(token) * sizeof(sd_char);
+ size_t n = strlen(token) * sizeof(sd_char);
if (sz < n)
return NULL;
diff --git a/src/fundamental/type.h b/src/fundamental/type.h
index f645d2de7f..2a9a114bbc 100644
--- a/src/fundamental/type.h
+++ b/src/fundamental/type.h
@@ -7,7 +7,7 @@
typedef BOOLEAN sd_bool;
typedef CHAR16 sd_char;
typedef INTN sd_int;
-typedef UINTN sd_size_t;
+typedef UINTN size_t;
#define true TRUE
#define false FALSE
@@ -18,5 +18,4 @@ typedef UINTN sd_size_t;
typedef bool sd_bool;
typedef char sd_char;
typedef int sd_int;
-typedef size_t sd_size_t;
#endif
diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build
index 8ec871f6a4..02b2cd64b2 100644
--- a/src/libsystemd/meson.build
+++ b/src/libsystemd/meson.build
@@ -170,8 +170,7 @@ libsystemd_static = static_library(
include_directories : libsystemd_includes,
link_with : libbasic,
dependencies : [threads,
- librt,
- libopenssl],
+ librt],
c_args : libsystemd_c_args)
libsystemd_sym = files('libsystemd.sym')
diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c
index 28ae10a198..992b19130e 100644
--- a/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libsystemd/sd-id128/sd-id128.c
@@ -4,21 +4,14 @@
#include <fcntl.h>
#include <unistd.h>
-#if HAVE_OPENSSL
-#include <openssl/hmac.h>
-#include <openssl/sha.h>
-#endif
-
#include "sd-id128.h"
#include "alloc-util.h"
#include "fd-util.h"
#include "hexdecoct.h"
+#include "hmac.h"
#include "id128-util.h"
#include "io-util.h"
-#if !HAVE_OPENSSL
-#include "khash.h"
-#endif
#include "macro.h"
#include "missing_syscall.h"
#include "random-util.h"
@@ -278,43 +271,15 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) {
}
static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) {
+ uint8_t hmac[SHA256_DIGEST_SIZE];
sd_id128_t result;
assert(ret);
-#if HAVE_OPENSSL
- /* We prefer doing this in-process, since we this means we are not dependent on kernel configuration,
- * and this also works in locked down container environments. But some distros don't like OpenSSL's
- * license and its (in-) compatibility with GPL2, hence also support khash */
- uint8_t md[256/8];
- if (!HMAC(EVP_sha256(),
- &base, sizeof(base),
- (const unsigned char*) &app_id, sizeof(app_id),
- md, NULL))
- return -ENOTRECOVERABLE;
+ hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), hmac);
/* Take only the first half. */
- memcpy(&result, md, MIN(sizeof(md), sizeof(result)));
-#else
- _cleanup_(khash_unrefp) khash *h = NULL;
- const void *p;
- int r;
-
- r = khash_new_with_key(&h, "hmac(sha256)", &base, sizeof(base));
- 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)));
-#endif
+ memcpy(&result, hmac, MIN(sizeof(hmac), sizeof(result)));
*ret = id128_make_v4_uuid(result);
return 0;
diff --git a/src/test/meson.build b/src/test/meson.build
index fea7f107fd..292b6329e4 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -592,8 +592,6 @@ tests += [
[['src/test/test-id128.c']],
- [['src/test/test-hash.c']],
-
[['src/test/test-gcrypt-util.c'],
[], [], [], 'HAVE_GCRYPT'],
@@ -629,6 +627,8 @@ tests += [
[['src/test/test-nscd-flush.c'],
[], [], [], 'ENABLE_NSCD', 'manual'],
+
+ [['src/test/test-hmac.c']],
]
############################################################
diff --git a/src/test/test-hash.c b/src/test/test-hash.c
deleted file mode 100644
index 270fcd0df4..0000000000
--- a/src/test/test-hash.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <errno.h>
-#include <stdio.h>
-
-#include "alloc-util.h"
-#include "log.h"
-#include "string-util.h"
-#include "khash.h"
-#include "tests.h"
-
-int main(int argc, char *argv[]) {
- _cleanup_(khash_unrefp) khash *h = NULL, *copy = NULL;
- _cleanup_free_ char *s = NULL;
- int r;
-
- test_setup_logging(LOG_DEBUG);
-
- assert_se(khash_new(&h, NULL) == -EINVAL);
- assert_se(khash_new(&h, "") == -EINVAL);
-
- r = khash_supported();
- assert_se(r >= 0);
- if (r == 0)
- return log_tests_skipped("khash not supported on this kernel");
-
- assert_se(khash_new(&h, "foobar") == -EOPNOTSUPP); /* undefined hash function */
-
- assert_se(khash_new(&h, "sha256") >= 0);
- assert_se(khash_get_size(h) == 32);
- assert_se(streq(khash_get_algorithm(h), "sha256"));
-
- assert_se(khash_digest_string(h, &s) >= 0);
- assert_se(streq(s, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
- s = mfree(s);
-
- assert_se(khash_put(h, "foobar", 6) >= 0);
- assert_se(khash_digest_string(h, &s) >= 0);
- assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"));
- s = mfree(s);
-
- assert_se(khash_put(h, "piep", 4) >= 0);
- assert_se(khash_digest_string(h, &s) >= 0);
- assert_se(streq(s, "f114d872b5ea075d3be9040d0b7a429514b3f9324a8e8e3dc3fb24c34ee56bea"));
- s = mfree(s);
-
- assert_se(khash_put(h, "foo", 3) >= 0);
- assert_se(khash_dup(h, &copy) >= 0);
-
- assert_se(khash_put(h, "bar", 3) >= 0);
- assert_se(khash_put(copy, "bar", 3) >= 0);
-
- assert_se(khash_digest_string(h, &s) >= 0);
- assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"));
- s = mfree(s);
-
- assert_se(khash_digest_string(copy, &s) >= 0);
- assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2"));
- s = mfree(s);
-
- h = khash_unref(h);
-
- assert_se(khash_new_with_key(&h, "hmac(sha256)", "quux", 4) >= 0);
- assert_se(khash_get_size(h) == 32);
- assert_se(streq(khash_get_algorithm(h), "hmac(sha256)"));
-
- assert_se(khash_digest_string(h, &s) >= 0);
- assert_se(streq(s, "abed9f8218ab473f77218a6a7d39abf1d21fa46d0700c4898e330ba88309d5ae"));
- s = mfree(s);
-
- assert_se(khash_put(h, "foobar", 6) >= 0);
- assert_se(khash_digest_string(h, &s) >= 0);
- assert_se(streq(s, "33f6c70a60db66007d5325d5d1dea37c371354e5b83347a59ad339ce9f4ba3dc"));
-
- return 0;
-}
diff --git a/src/test/test-hmac.c b/src/test/test-hmac.c
new file mode 100644
index 0000000000..5c73eca110
--- /dev/null
+++ b/src/test/test-hmac.c
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "hexdecoct.h"
+#include "hmac.h"
+#include "string-util.h"
+#include "tests.h"
+
+static void hmac_sha256_by_string(const char *key, const char *value, uint8_t res[static SHA256_DIGEST_SIZE]) {
+ hmac_sha256(key, strlen(key), value, strlen(value), res);
+}
+
+static void test_hmac(void) {
+ uint8_t result[SHA256_DIGEST_SIZE];
+ char *hex_result = NULL;
+
+ log_info("/* %s */", __func__);
+
+ /* Results compared with output of 'echo -n "<input>" | openssl dgst -sha256 -hmac "<key>"' */
+
+ hmac_sha256_by_string("waldo",
+ "",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "cadd5e42114351181f3abff477641d88efb57d2b5641a1e5c6d623363a6d3bad"));
+ hex_result = mfree(hex_result);
+
+ hmac_sha256_by_string("waldo",
+ "baldohaldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "c47ad5031ba21605e52c6ca68090d66a2dd5ccf84efa4bace15361a8cba63cda"));
+ hex_result = mfree(hex_result);
+
+ hmac_sha256_by_string("waldo",
+ "baldo haldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69"));
+ hex_result = mfree(hex_result);
+
+ hmac_sha256_by_string("waldo",
+ "baldo 4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69 haldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "039f3df430b19753ffb493e5b90708f75c5210b63c6bcbef3374eb3f0a3f97f7"));
+ hex_result = mfree(hex_result);
+
+ hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69",
+ "baldo haldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "c4cfaf48077cbb0bbd177a09e59ec4c248f4ca771503410f5b54b98d88d2f47b"));
+ hex_result = mfree(hex_result);
+
+ hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69",
+ "supercalifragilisticexpialidocious",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "2c059e7a63c4c3b23f47966a65fd2f8a2f5d7161e2e90d78ff68866b5c375cb7"));
+ hex_result = mfree(hex_result);
+
+ hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69c47ad5031ba21605e52c6ca68090d66a2dd5ccf84efa4bace15361a8cba63cda",
+ "supercalifragilisticexpialidocious",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "1dd1d1d45b9d9f9673dc9983c968c46ff3168e03cfeb4156a219eba1af4cff5f"));
+ hex_result = mfree(hex_result);
+}
+
+int main(int argc, char **argv) {
+ test_setup_logging(LOG_INFO);
+
+ test_hmac();
+
+ return 0;
+}
diff --git a/src/test/test-id128.c b/src/test/test-id128.c
index a61b35b9a3..79dc7de159 100644
--- a/src/test/test-id128.c
+++ b/src/test/test-id128.c
@@ -12,19 +12,20 @@
#include "id128-util.h"
#include "macro.h"
#include "string-util.h"
+#include "tests.h"
#include "tmpfile-util.h"
-#include "util.h"
#define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10)
#define STR_WALDI "0102030405060708090a0b0c0d0e0f10"
#define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10"
-int main(int argc, char *argv[]) {
+static void test_id128(void) {
sd_id128_t id, id2;
char t[SD_ID128_STRING_MAX], q[ID128_UUID_STRING_MAX];
_cleanup_free_ char *b = NULL;
_cleanup_close_ int fd = -1;
- int r;
+
+ log_info("/* %s */", __func__);
assert_se(sd_id128_randomize(&id) == 0);
printf("random: %s\n", sd_id128_to_string(id, t));
@@ -146,16 +147,18 @@ int main(int argc, char *argv[]) {
assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
- r = 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);
- if (r == -EOPNOTSUPP)
- log_info("khash not supported on this kernel, skipping sd_id128_get_machine_app_specific() checks");
- else {
- assert_se(r >= 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));
- }
+ 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));
+}
+
+static void test_sd_id128_get_invocation(void) {
+ sd_id128_t id;
+ int r;
+
+ log_info("/* %s */", __func__);
/* Query the invocation ID */
r = sd_id128_get_invocation(&id);
@@ -163,6 +166,35 @@ int main(int argc, char *argv[]) {
log_warning_errno(r, "Failed to get invocation ID, ignoring: %m");
else
log_info("Invocation ID: " SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
+}
+
+static void benchmark_sd_id128_get_machine_app_specific(void) {
+ unsigned iterations = slow_tests_enabled() ? 1000000 : 1000;
+ usec_t t, q;
+
+ log_info("/* %s (%u iterations) */", __func__, iterations);
+
+ sd_id128_t id = ID128_WALDI, id2;
+
+ t = now(CLOCK_MONOTONIC);
+
+ for (unsigned i = 0; i < iterations; i++) {
+ id.qwords[1] = i;
+
+ assert_se(sd_id128_get_machine_app_specific(id, &id2) >= 0);
+ }
+
+ q = now(CLOCK_MONOTONIC) - t;
+
+ log_info("%lf µs each\n", (double) q / iterations);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_INFO);
+
+ test_id128();
+ test_sd_id128_get_invocation();
+ benchmark_sd_id128_get_machine_app_specific();
return 0;
}