From 5d8a725b0800ce572bb3308c03e98561251a9284 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 8 Oct 2021 13:06:51 +0100 Subject: [PATCH 1/7] fundamental: define size_t and memcpy for sd-boot --- src/fundamental/macro-fundamental.h | 2 ++ src/fundamental/string-util-fundamental.c | 8 ++++---- src/fundamental/string-util-fundamental.h | 4 ++-- src/fundamental/type.h | 3 +-- 4 files changed, 9 insertions(+), 8 deletions(-) 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/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 From 6eb736727a484741095510380f16b4e5fb6b964a Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 7 Oct 2021 17:15:32 +0100 Subject: [PATCH 2/7] boot/sha256: sd-ify and move to src/fundamental --- src/boot/efi/meson.build | 2 - src/boot/efi/sha256.h | 28 -------- src/fundamental/meson.build | 2 + src/{boot/efi => fundamental}/sha256.c | 94 ++++++++++++++------------ src/fundamental/sha256.h | 32 +++++++++ 5 files changed, 83 insertions(+), 75 deletions(-) delete mode 100644 src/boot/efi/sha256.h rename src/{boot/efi => fundamental}/sha256.c (79%) create mode 100644 src/fundamental/sha256.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 -#include - -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/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 similarity index 79% rename from src/boot/efi/sha256.c rename to 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 , 2007. */ +#ifndef SD_BOOT +#include +#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 +#include +#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); From 8d39bff4e36ee3996c5b087ee62ae0d33a82c837 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 7 Oct 2021 21:02:44 +0100 Subject: [PATCH 3/7] 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. --- src/basic/hmac.c | 62 +++++++++++++++++++++++++++++++++++ src/basic/hmac.h | 12 +++++++ src/basic/meson.build | 2 ++ src/test/meson.build | 2 ++ src/test/test-hmac.c | 76 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 src/basic/hmac.c create mode 100644 src/basic/hmac.h create mode 100644 src/test/test-hmac.c 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 +#include + +#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 +#include + +#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/meson.build b/src/basic/meson.build index adb7b666c6..a4a7469856 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 diff --git a/src/test/meson.build b/src/test/meson.build index fea7f107fd..c24641fc7e 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -629,6 +629,8 @@ tests += [ [['src/test/test-nscd-flush.c'], [], [], [], 'ENABLE_NSCD', 'manual'], + + [['src/test/test-hmac.c']], ] ############################################################ 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 "" | openssl dgst -sha256 -hmac ""' */ + + 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; +} From ec4afb4606e2b1ea44b0f32778a51c2a8be7eadd Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 30 Sep 2021 11:01:45 +0100 Subject: [PATCH 4/7] 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. --- LICENSES/README.md | 5 ++++ src/libsystemd/meson.build | 3 +-- src/libsystemd/sd-id128/sd-id128.c | 43 +++--------------------------- src/test/test-id128.c | 15 ++++------- 4 files changed, 15 insertions(+), 51 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/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 #include -#if HAVE_OPENSSL -#include -#include -#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/test-id128.c b/src/test/test-id128.c index a61b35b9a3..55fdab0ab8 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -146,16 +146,11 @@ 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)); /* Query the invocation ID */ r = sd_id128_get_invocation(&id); From 1fc8d0c9dd6a21de81e49cfa01af4a4d9a3ed37d Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Thu, 7 Oct 2021 21:49:19 +0100 Subject: [PATCH 5/7] basic: remove khash helpers No longer used anywhere. So long, and thanks for all the hashes! --- TODO | 2 - src/basic/khash.c | 321 ------------------------------------------ src/basic/khash.h | 37 ----- src/basic/meson.build | 2 - src/test/meson.build | 2 - src/test/test-hash.c | 76 ---------- 6 files changed, 440 deletions(-) delete mode 100644 src/basic/khash.c delete mode 100644 src/basic/khash.h delete mode 100644 src/test/test-hash.c 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/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 -#include -#include - -#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 -#include -#include - -#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 a4a7469856..cf97f6de1d 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -82,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/test/meson.build b/src/test/meson.build index c24641fc7e..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'], 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 -#include - -#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, ©) >= 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; -} From 0a0ddfeb682921873f040d9b8fbfa4a044a5141f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 8 Oct 2021 09:29:47 +0200 Subject: [PATCH 6/7] test-id128: split into functions and add the usual headers --- src/test/test-id128.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/test/test-id128.c b/src/test/test-id128.c index 55fdab0ab8..f6755f20cc 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)); @@ -151,6 +152,13 @@ int main(int argc, char *argv[]) { 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); @@ -158,6 +166,13 @@ 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)); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_id128(); + test_sd_id128_get_invocation(); return 0; } From ee6df1fdd4ad682429c234720446597969df0985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 8 Oct 2021 09:35:50 +0200 Subject: [PATCH 7/7] Add benchmark for sha256 calculations --- src/test/test-id128.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/test/test-id128.c b/src/test/test-id128.c index f6755f20cc..79dc7de159 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -168,11 +168,33 @@ static void test_sd_id128_get_invocation(void) { 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; }