1
0
mirror of https://github.com/systemd/systemd synced 2026-03-30 11:44:49 +02:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Luca Boccassi
ccf609c88c
Merge pull request #20915 from bluca/libsystemd_openssl
libsystemd/sd-id128: use only internal hmac, remove khash/OpenSSL support
2021-10-09 18:37:59 +01:00
Dimitri John Ledkov
af7fb6831f test: set 5 minute timeout on TEST-11-ISSUE-3166 and TEST-50-DISSECT
When they work they finish quickly in under two minutes on slow machines, when
soft lock ups happen in the nested virt machine each test can run for like 5
hours clogging up CI infrastructure. It's best to fail quicker than that when
qemu or kernel are broken.
2021-10-09 18:31:27 +01:00
Zbigniew Jędrzejewski-Szmek
ee6df1fdd4 Add benchmark for sha256 calculations 2021-10-08 13:11:00 +01:00
Zbigniew Jędrzejewski-Szmek
0a0ddfeb68 test-id128: split into functions and add the usual headers 2021-10-08 13:11:00 +01:00
Luca Boccassi
1fc8d0c9dd basic: remove khash helpers
No longer used anywhere. So long, and thanks for all the hashes!
2021-10-08 13:11:00 +01:00
Luca Boccassi
ec4afb4606 libsystemd/sd-id128: use only internal hmac, remove khash/OpenSSL support
Using OpenSSL brings in an additional dependency for all users of
libsystemd.so even though it's just one API that makes use of it.

The khash implementation is awkward as it requires context switches and
computation inside the kernel, thus leaving the process.

Remove both from libsystemd.so, and use exclusively the internal hmac fallback.
While this is not optimized, the sd-id128 API is not used in
performance-critical contexts where hardware acceleration would make a
noticeable difference.
2021-10-08 13:11:00 +01:00
Luca Boccassi
8d39bff4e3 basic: add hmac_sha256 implementation
Based on the FIPS 198 specification. Not optimized and probably
completely unsafe, to be used only for non-strong-cryptographic
purposes when OpenSSL cannot be used.
2021-10-08 13:11:00 +01:00
Luca Boccassi
6eb736727a boot/sha256: sd-ify and move to src/fundamental 2021-10-08 13:11:00 +01:00
Luca Boccassi
5d8a725b08 fundamental: define size_t and memcpy for sd-boot 2021-10-08 13:07:00 +01:00
24 changed files with 305 additions and 577 deletions

View File

@ -58,3 +58,8 @@ The following exceptions apply:
**BSD-3-Clause** license. **BSD-3-Clause** license.
* any files under test/ without an explicit license we assume non-copyrightable * any files under test/ without an explicit license we assume non-copyrightable
(eg: computer-generated fuzzer data) (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.

2
TODO
View File

@ -352,11 +352,9 @@ Features:
* unify on openssl (as soon as OpenSSL 3.0 is out, and the Debian license * unify on openssl (as soon as OpenSSL 3.0 is out, and the Debian license
confusion is gone) confusion is gone)
- port sd_id128_get_machine_app_specific() over from khash
- port resolved over from libgcrypt (DNSSEC code) - port resolved over from libgcrypt (DNSSEC code)
- port journald + fsprg over from libgcrypt - port journald + fsprg over from libgcrypt
- port importd over from libgcrypt - port importd over from libgcrypt
- when that's done: kill khash.c
- when that's done: kill gnutls support in resolved - when that's done: kill gnutls support in resolved
* add growvol and makevol options for /etc/crypttab, similar to * add growvol and makevol options for /etc/crypttab, similar to

62
src/basic/hmac.c Normal file
View File

@ -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);
}

12
src/basic/hmac.h Normal file
View File

@ -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]);

View File

@ -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;
}

View File

@ -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);

View File

@ -72,6 +72,8 @@ basic_sources = files('''
hashmap.h hashmap.h
hexdecoct.c hexdecoct.c
hexdecoct.h hexdecoct.h
hmac.c
hmac.h
hostname-util.c hostname-util.c
hostname-util.h hostname-util.h
in-addr-util.c in-addr-util.c
@ -80,8 +82,6 @@ basic_sources = files('''
inotify-util.h inotify-util.h
io-util.c io-util.c
io-util.h io-util.h
khash.c
khash.h
limits-util.c limits-util.c
limits-util.h limits-util.h
linux/btrfs.h linux/btrfs.h

View File

@ -12,7 +12,6 @@ efi_headers = files('''
missing_efi.h missing_efi.h
pe.h pe.h
random-seed.h random-seed.h
sha256.h
shim.h shim.h
splash.h splash.h
util.h util.h
@ -34,7 +33,6 @@ systemd_boot_sources = '''
devicetree.c devicetree.c
drivers.c drivers.c
random-seed.c random-seed.c
sha256.c
shim.c shim.c
'''.split() '''.split()

View File

@ -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);

View File

@ -59,6 +59,8 @@
#define assert(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); }) #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__) #define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#endif #endif
#define memcpy(a, b, c) CopyMem((a), (b), (c))
#endif #endif
#if defined(static_assert) #if defined(static_assert)

View File

@ -6,10 +6,12 @@ fundamental_headers = files(
'efi-loader-features.h', 'efi-loader-features.h',
'macro-fundamental.h', 'macro-fundamental.h',
'string-util-fundamental.h', 'string-util-fundamental.h',
'sha256.h',
'type.h') 'type.h')
sources = ''' sources = '''
string-util-fundamental.c string-util-fundamental.c
sha256.c
'''.split() '''.split()
# for sd-boot # for sd-boot

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* 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. /* Functions to compute SHA256 message digest of files or memory blocks.
according to the definition of SHA256 in FIPS 180-2. according to the definition of SHA256 in FIPS 180-2.
@ -23,6 +23,10 @@
/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */ /* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
#ifndef SD_BOOT
#include <string.h>
#endif
#include "macro-fundamental.h" #include "macro-fundamental.h"
#include "sha256.h" #include "sha256.h"
@ -45,12 +49,12 @@
/* This array contains the bytes used to pad the buffer to the next /* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (FIPS 180-2:5.1.1) */ 64-byte boundary. (FIPS 180-2:5.1.1) */
static const UINT8 fillbuf[64] = { static const uint8_t fillbuf[64] = {
0x80, 0 /* , 0, 0, ... */ 0x80, 0 /* , 0, 0, ... */
}; };
/* Constants for SHA256 from FIPS 180-2:4.2.2. */ /* 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, 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@ -69,7 +73,7 @@ static const UINT32 K[64] = {
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 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. /* Initialize structure containing state of computation.
(FIPS 180-2:5.3.2) */ (FIPS 180-2:5.3.2) */
@ -96,8 +100,8 @@ void sha256_init_ctx(struct sha256_ctx *ctx) {
aligned for a 32 bits value. */ aligned for a 32 bits value. */
void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) { void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Take yet unprocessed bytes into account. */ /* Take yet unprocessed bytes into account. */
UINT32 bytes = ctx->buflen; uint32_t bytes = ctx->buflen;
UINTN pad; size_t pad;
assert(ctx); assert(ctx);
assert(resbuf); assert(resbuf);
@ -106,7 +110,7 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
ctx->total64 += bytes; ctx->total64 += bytes;
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - 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. */ /* 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); 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); sha256_process_block(ctx->buffer, bytes + pad + 8, ctx);
/* Put result from CTX in first 32 bytes following RESBUF. */ /* Put result from CTX in first 32 bytes following RESBUF. */
for (UINTN i = 0; i < 8; ++i) for (size_t i = 0; i < 8; ++i)
((UINT32 *) resbuf)[i] = SWAP(ctx->H[i]); ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
return resbuf; 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(buffer);
assert(ctx); assert(ctx);
@ -131,10 +135,10 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
both inputs first. */ both inputs first. */
if (ctx->buflen != 0) { if (ctx->buflen != 0) {
UINTN left_over = ctx->buflen; size_t left_over = ctx->buflen;
UINTN add = 128 - left_over > len ? len : 128 - left_over; 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; ctx->buflen += add;
if (ctx->buflen > 64) { if (ctx->buflen > 64) {
@ -142,7 +146,7 @@ void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx)
ctx->buflen &= 63; ctx->buflen &= 63;
/* The regions in the following copy operation cannot overlap. */ /* 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); 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. */ /* To check alignment gcc has an appropriate operator. Other compilers don't. */
# if __GNUC__ >= 2 # if __GNUC__ >= 2
# define UNALIGNED_P(p) (((UINTN) p) % __alignof__(UINT32) != 0) # define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0)
# else # else
# define UNALIGNED_P(p) (((UINTN) p) % sizeof(UINT32) != 0) # define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0)
# endif # endif
if (UNALIGNED_P(buffer)) if (UNALIGNED_P(buffer))
while (len > 64) { while (len > 64) {
CopyMem(ctx->buffer, buffer, 64); memcpy(ctx->buffer, buffer, 64);
sha256_process_block(ctx->buffer, 64, ctx); sha256_process_block(ctx->buffer, 64, ctx);
buffer = (const char *) buffer + 64; buffer = (const char *) buffer + 64;
len -= 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. */ /* Move remaining bytes into internal buffer. */
if (len > 0) { 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; left_over += len;
if (left_over >= 64) { if (left_over >= 64) {
sha256_process_block(ctx->buffer, 64, ctx); sha256_process_block(ctx->buffer, 64, ctx);
left_over -= 64; left_over -= 64;
CopyMem(ctx->buffer, &ctx->buffer[64], left_over); memcpy(ctx->buffer, &ctx->buffer[64], left_over);
} }
ctx->buflen = 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. /* Process LEN bytes of BUFFER, accumulating context into CTX.
It is assumed that LEN % 64 == 0. */ It is assumed that LEN % 64 == 0. */
static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ctx *ctx) { static void sha256_process_block(const void *buffer, size_t len, struct sha256_ctx *ctx) {
const UINT32 *words = buffer; const uint32_t *words = buffer;
UINTN nwords = len / sizeof(UINT32); size_t nwords = len / sizeof(uint32_t);
assert(buffer); assert(buffer);
assert(ctx); assert(ctx);
UINT32 a = ctx->H[0]; uint32_t a = ctx->H[0];
UINT32 b = ctx->H[1]; uint32_t b = ctx->H[1];
UINT32 c = ctx->H[2]; uint32_t c = ctx->H[2];
UINT32 d = ctx->H[3]; uint32_t d = ctx->H[3];
UINT32 e = ctx->H[4]; uint32_t e = ctx->H[4];
UINT32 f = ctx->H[5]; uint32_t f = ctx->H[5];
UINT32 g = ctx->H[6]; uint32_t g = ctx->H[6];
UINT32 h = ctx->H[7]; uint32_t h = ctx->H[7];
/* First increment the byte count. FIPS 180-2 specifies the possible /* 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 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 /* Process all bytes in the buffer with 64 bytes in each round of
the loop. */ the loop. */
while (nwords > 0) { while (nwords > 0) {
UINT32 W[64]; uint32_t W[64];
UINT32 a_save = a; uint32_t a_save = a;
UINT32 b_save = b; uint32_t b_save = b;
UINT32 c_save = c; uint32_t c_save = c;
UINT32 d_save = d; uint32_t d_save = d;
UINT32 e_save = e; uint32_t e_save = e;
UINT32 f_save = f; uint32_t f_save = f;
UINT32 g_save = g; uint32_t g_save = g;
UINT32 h_save = h; uint32_t h_save = h;
/* Operators defined in FIPS 180-2:4.1.2. */ /* Operators defined in FIPS 180-2:4.1.2. */
#define Ch(x, y, z) ((x & y) ^ (~x & z)) #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))) #define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
/* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ /* 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); W[t] = SWAP (*words);
++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]; 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. */ /* The actual computation according to FIPS 180-2:6.2.2 step 3. */
for (UINTN t = 0; t < 64; ++t) { for (size_t t = 0; t < 64; ++t) {
UINT32 T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t]; uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
UINT32 T2 = S0 (a) + Maj (a, b, c); uint32_t T2 = S0 (a) + Maj (a, b, c);
h = g; h = g;
g = f; g = f;
f = e; f = e;

32
src/fundamental/sha256.h Normal file
View File

@ -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);

View File

@ -8,7 +8,7 @@
#include "string-util-fundamental.h" #include "string-util-fundamental.h"
sd_char *startswith(const sd_char *s, const sd_char *prefix) { sd_char *startswith(const sd_char *s, const sd_char *prefix) {
sd_size_t l; size_t l;
assert(s); assert(s);
assert(prefix); assert(prefix);
@ -22,7 +22,7 @@ sd_char *startswith(const sd_char *s, const sd_char *prefix) {
#ifndef SD_BOOT #ifndef SD_BOOT
sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) { sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
sd_size_t l; size_t l;
assert(s); assert(s);
assert(prefix); assert(prefix);
@ -36,7 +36,7 @@ sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
#endif #endif
sd_char* endswith(const sd_char *s, const sd_char *postfix) { sd_char* endswith(const sd_char *s, const sd_char *postfix) {
sd_size_t sl, pl; size_t sl, pl;
assert(s); assert(s);
assert(postfix); 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_char* endswith_no_case(const sd_char *s, const sd_char *postfix) {
sd_size_t sl, pl; size_t sl, pl;
assert(s); assert(s);
assert(postfix); assert(postfix);

View File

@ -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); sd_int strverscmp_improved(const sd_char *a, const sd_char *b);
/* Like startswith(), but operates on arbitrary memory blocks */ /* 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); assert(token);
sd_size_t n = strlen(token) * sizeof(sd_char); size_t n = strlen(token) * sizeof(sd_char);
if (sz < n) if (sz < n)
return NULL; return NULL;

View File

@ -7,7 +7,7 @@
typedef BOOLEAN sd_bool; typedef BOOLEAN sd_bool;
typedef CHAR16 sd_char; typedef CHAR16 sd_char;
typedef INTN sd_int; typedef INTN sd_int;
typedef UINTN sd_size_t; typedef UINTN size_t;
#define true TRUE #define true TRUE
#define false FALSE #define false FALSE
@ -18,5 +18,4 @@ typedef UINTN sd_size_t;
typedef bool sd_bool; typedef bool sd_bool;
typedef char sd_char; typedef char sd_char;
typedef int sd_int; typedef int sd_int;
typedef size_t sd_size_t;
#endif #endif

View File

@ -170,8 +170,7 @@ libsystemd_static = static_library(
include_directories : libsystemd_includes, include_directories : libsystemd_includes,
link_with : libbasic, link_with : libbasic,
dependencies : [threads, dependencies : [threads,
librt, librt],
libopenssl],
c_args : libsystemd_c_args) c_args : libsystemd_c_args)
libsystemd_sym = files('libsystemd.sym') libsystemd_sym = files('libsystemd.sym')

View File

@ -4,21 +4,14 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#if HAVE_OPENSSL
#include <openssl/hmac.h>
#include <openssl/sha.h>
#endif
#include "sd-id128.h" #include "sd-id128.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "hmac.h"
#include "id128-util.h" #include "id128-util.h"
#include "io-util.h" #include "io-util.h"
#if !HAVE_OPENSSL
#include "khash.h"
#endif
#include "macro.h" #include "macro.h"
#include "missing_syscall.h" #include "missing_syscall.h"
#include "random-util.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) { 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; sd_id128_t result;
assert(ret); assert(ret);
#if HAVE_OPENSSL hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), hmac);
/* 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;
/* Take only the first half. */ /* Take only the first half. */
memcpy(&result, md, MIN(sizeof(md), sizeof(result))); memcpy(&result, hmac, MIN(sizeof(hmac), 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
*ret = id128_make_v4_uuid(result); *ret = id128_make_v4_uuid(result);
return 0; return 0;

View File

@ -592,8 +592,6 @@ tests += [
[['src/test/test-id128.c']], [['src/test/test-id128.c']],
[['src/test/test-hash.c']],
[['src/test/test-gcrypt-util.c'], [['src/test/test-gcrypt-util.c'],
[], [], [], 'HAVE_GCRYPT'], [], [], [], 'HAVE_GCRYPT'],
@ -629,6 +627,8 @@ tests += [
[['src/test/test-nscd-flush.c'], [['src/test/test-nscd-flush.c'],
[], [], [], 'ENABLE_NSCD', 'manual'], [], [], [], 'ENABLE_NSCD', 'manual'],
[['src/test/test-hmac.c']],
] ]
############################################################ ############################################################

View File

@ -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;
}

76
src/test/test-hmac.c Normal file
View File

@ -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;
}

View File

@ -12,19 +12,20 @@
#include "id128-util.h" #include "id128-util.h"
#include "macro.h" #include "macro.h"
#include "string-util.h" #include "string-util.h"
#include "tests.h"
#include "tmpfile-util.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 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 STR_WALDI "0102030405060708090a0b0c0d0e0f10"
#define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10" #define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10"
int main(int argc, char *argv[]) { static void test_id128(void) {
sd_id128_t id, id2; sd_id128_t id, id2;
char t[SD_ID128_STRING_MAX], q[ID128_UUID_STRING_MAX]; char t[SD_ID128_STRING_MAX], q[ID128_UUID_STRING_MAX];
_cleanup_free_ char *b = NULL; _cleanup_free_ char *b = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
int r;
log_info("/* %s */", __func__);
assert_se(sd_id128_randomize(&id) == 0); assert_se(sd_id128_randomize(&id) == 0);
printf("random: %s\n", sd_id128_to_string(id, t)); printf("random: %s\n", sd_id128_to_string(id, t));
@ -146,23 +147,54 @@ int main(int argc, char *argv[]) {
assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
assert_se(sd_id128_equal(id, id2)); 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); 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);
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_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_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_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_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 */ /* Query the invocation ID */
r = sd_id128_get_invocation(&id); r = sd_id128_get_invocation(&id);
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to get invocation ID, ignoring: %m"); log_warning_errno(r, "Failed to get invocation ID, ignoring: %m");
else else
log_info("Invocation ID: " SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); 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; return 0;
} }

View File

@ -7,4 +7,6 @@ TEST_NO_NSPAWN=1
# shellcheck source=test/test-functions # shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions" . "${TEST_BASE_DIR:?}/test-functions"
QEMU_TIMEOUT=300
do_test "$@" do_test "$@"

View File

@ -11,6 +11,8 @@ TEST_INSTALL_VERITY_MINIMAL=1
# shellcheck source=test/test-functions # shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions" . "${TEST_BASE_DIR:?}/test-functions"
QEMU_TIMEOUT=300
command -v mksquashfs >/dev/null 2>&1 || exit 0 command -v mksquashfs >/dev/null 2>&1 || exit 0
command -v veritysetup >/dev/null 2>&1 || exit 0 command -v veritysetup >/dev/null 2>&1 || exit 0
command -v sfdisk >/dev/null 2>&1 || exit 0 command -v sfdisk >/dev/null 2>&1 || exit 0