From 5e8db5e41c112331bc79307e99ae714f283b3fe9 Mon Sep 17 00:00:00 2001 From: Brad Edwards Date: Sun, 15 Mar 2026 18:46:43 +0000 Subject: [PATCH] HMAC-SHA256 code integrity --- CHANGELOG.md | 18 ++++ README.md | 6 +- daemon/Makefile | 3 +- daemon/hmac_sha256.c | 59 +++++++++++ daemon/hmac_sha256.h | 40 ++++++++ daemon/integrity.c | 58 +++++++++-- daemon/integrity.h | 46 +++++++-- scripts/verify.sh | 25 ++++- tests/Makefile | 12 ++- tests/test_hmac_sha256 | Bin 0 -> 26352 bytes tests/test_hmac_sha256.c | 212 +++++++++++++++++++++++++++++++++++++++ tests/test_integrity | Bin 21800 -> 22208 bytes tests/test_integrity.c | 7 +- 13 files changed, 459 insertions(+), 27 deletions(-) create mode 100644 daemon/hmac_sha256.c create mode 100644 daemon/hmac_sha256.h create mode 100755 tests/test_hmac_sha256 create mode 100644 tests/test_hmac_sha256.c diff --git a/CHANGELOG.md b/CHANGELOG.md index a2e4f0f..3e1cc77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.3.0] - 2026-03-15 + +### Added +- **WP2: HMAC-SHA256 code integrity** (`daemon/hmac_sha256.c`): replaces CRC32 with HMAC-SHA256 using per-session 256-bit random key from `/dev/urandom`. Uses OpenSSL one-shot `HMAC()` (not deprecated `HMAC_CTX_*`). Graviton3 ARMv8.4 SHA extensions accelerate computation. +- `daemon/hmac_sha256.h`: public API (`owl_hmac_sha256`, `owl_hmac_generate_key`) +- `tests/test_hmac_sha256.c`: 10 unit tests (TDD) — RFC 4231 known-answer vectors, empty/large input, key change, null inputs, key generation, integrity baseline+check, violation detection +- Buffer-based integrity functions (`owl_integrity_baseline_buffer`, `owl_integrity_check_buffer`) for testable verification without /proc I/O +- `scripts/verify.sh`: HMAC-SHA256 baseline assertion in protected phase, ld_preload_hook baseline assertion + +### Changed +- `daemon/integrity.h`: `baseline_crc` replaced with `baseline_hmac[32]` + `hmac_key[32]` in `struct owl_integrity` +- `daemon/integrity.c`: baseline and check functions use HMAC-SHA256 via buffer variants; CRC32 retained for heartbeat `state_hash` +- `daemon/Makefile`: added `hmac_sha256.c`, linked `-lssl -lcrypto` +- `tests/Makefile`: added `test_hmac_sha256` suite, updated `test_integrity` linking with OpenSSL +- `tests/test_integrity.c`: init test checks HMAC fields instead of CRC32 +- `scripts/verify.sh`: version bumped to v2.3.0 +- `README.md`: updated status (v2.3.0, 125 tests, 14 suites), HMAC-SHA256 in daemon description, removed CRC32 limitation + ## [2.2.0] - 2026-03-15 ### Added diff --git a/README.md b/README.md index ef60b7c..0a91c84 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Runs on Graviton3 (c7g.large), Ubuntu 24.04, kernel 6.17. - **kernel/** - loadable module. Kprobes on ptrace, /proc/pid/mem, process_vm_readv/writev, mmap, module load/unload. ARM64 system register monitoring. Chardev for event delivery. - **ebpf/** - BPF LSM hooks returning -EPERM (ptrace_access_check, file_open for /proc/pid/mem + /dev/mem + /dev/kmem, file_mprotect). Tracepoints. Kprobe on do_init_module. Ring buffer to userspace. -- **daemon/** - epoll on chardev + BPF ring buffer. Policy engine. Signature scanner. CRC32 code integrity. Self-protection watchdog. TracerPid debugger detection. LD_PRELOAD environ scanning. Process ancestry tree for correlation. +- **daemon/** - epoll on chardev + BPF ring buffer. Policy engine. Signature scanner. HMAC-SHA256 code integrity. Self-protection watchdog. TracerPid debugger detection. LD_PRELOAD environ scanning. Process ancestry tree for correlation. - **game/** - ncurses test target. Mutable state, function pointers, exported address. - **cheats/** - 9 attack programs: process_vm_readv, /proc/pid/mem, /dev/mem, ptrace read, ptrace write, process_vm_writev, LD_PRELOAD, mprotect injection, debug registers. - **platform/** - Lambda + API Gateway + DynamoDB telemetry receiver. @@ -18,9 +18,9 @@ Runs on Graviton3 (c7g.large), Ubuntu 24.04, kernel 6.17. ## Status -v2.2.0. 115 unit tests, 13 suites. eBPF LSM returns EPERM on ptrace, /proc/pid/mem, /dev/mem, /dev/kmem, process_vm_writev. Module can't be unloaded while daemon runs. TracerPid polling detects debuggers attached before daemon start. LD_PRELOAD detection on exec. Process tree tracks ancestry for correlation engine. +v2.3.0. 125 unit tests, 14 suites. eBPF LSM returns EPERM on ptrace, /proc/pid/mem, /dev/mem, /dev/kmem, process_vm_writev. Module can't be unloaded while daemon runs. TracerPid polling detects debuggers attached before daemon start. LD_PRELOAD detection on exec. Process tree tracks ancestry for correlation engine. -Prototype limitations: linear signature scan, CRC32 not cryptographic, no fleet management. +Prototype limitations: linear signature scan, no fleet management. ## Getting started diff --git a/daemon/Makefile b/daemon/Makefile index 1a10cd7..d06a7d9 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -12,7 +12,7 @@ CFLAGS := -std=c11 -Wall -Wextra -Werror \ -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 \ $(INCLUDES) $(CFLAGS_EXTRA) \ -I../ebpf -LDFLAGS := -lpthread -lcurl -lbpf -lelf -lz +LDFLAGS := -lpthread -lcurl -lbpf -lelf -lz -lssl -lcrypto DEPFLAGS = -MMD -MP -MF $(@:.o=.d) # Source files @@ -22,6 +22,7 @@ SRCS := main.c \ process_tree.c \ sig_loader.c \ integrity.c \ + hmac_sha256.c \ self_protect.c \ debugger_detect.c \ preload_detect.c \ diff --git a/daemon/hmac_sha256.c b/daemon/hmac_sha256.c new file mode 100644 index 0000000..89a3cbd --- /dev/null +++ b/daemon/hmac_sha256.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * hmac_sha256.c - HMAC-SHA256 via OpenSSL one-shot HMAC() + * + * Uses the non-deprecated HMAC() function (OpenSSL 3.0+). + * Only HMAC_CTX_* is deprecated; the one-shot variant is stable. + */ + +#include +#include + +#include +#include + +#include "hmac_sha256.h" + +int owl_hmac_sha256(const uint8_t *key, size_t key_len, + const uint8_t *data, size_t data_len, + uint8_t *out) +{ + if (!key || !out) + return -1; + if (!data && data_len > 0) + return -1; + + unsigned int md_len = 0; + const uint8_t empty = 0; + const uint8_t *d = data ? data : ∅ + + unsigned char *result = HMAC(EVP_sha256(), key, (int)key_len, + d, data_len, out, &md_len); + if (!result || md_len != OWL_HMAC_SHA256_LEN) + return -1; + + return 0; +} + +int owl_hmac_generate_key(uint8_t *key, size_t key_len) +{ + if (!key || key_len == 0) + return -1; + + int fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + return -1; + + size_t total = 0; + while (total < key_len) { + ssize_t n = read(fd, key + total, key_len - total); + if (n <= 0) { + close(fd); + return -1; + } + total += (size_t)n; + } + + close(fd); + return 0; +} diff --git a/daemon/hmac_sha256.h b/daemon/hmac_sha256.h new file mode 100644 index 0000000..effc3d8 --- /dev/null +++ b/daemon/hmac_sha256.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * hmac_sha256.h - HMAC-SHA256 wrapper for code integrity verification + * + * Uses OpenSSL one-shot HMAC() with EVP_sha256(). + * Per-session 256-bit random key from /dev/urandom. + */ + +#ifndef OWLBEAR_HMAC_SHA256_H +#define OWLBEAR_HMAC_SHA256_H + +#include +#include + +#define OWL_HMAC_SHA256_LEN 32 + +/** + * owl_hmac_sha256 - Compute HMAC-SHA256 of a buffer + * @key: HMAC key + * @key_len: Key length in bytes + * @data: Input data (may be NULL if data_len is 0) + * @data_len: Input data length + * @out: Output buffer (must be at least OWL_HMAC_SHA256_LEN bytes) + * + * Returns 0 on success, -1 on error. + */ +int owl_hmac_sha256(const uint8_t *key, size_t key_len, + const uint8_t *data, size_t data_len, + uint8_t *out); + +/** + * owl_hmac_generate_key - Generate a random key from /dev/urandom + * @key: Output buffer + * @key_len: Number of random bytes to generate + * + * Returns 0 on success, -1 on error. + */ +int owl_hmac_generate_key(uint8_t *key, size_t key_len); + +#endif /* OWLBEAR_HMAC_SHA256_H */ diff --git a/daemon/integrity.c b/daemon/integrity.c index f27e1b3..a9be78f 100644 --- a/daemon/integrity.c +++ b/daemon/integrity.c @@ -2,7 +2,8 @@ /* * integrity.c - Userspace code integrity verification * - * CRC32 hash of game .text segment for runtime code modification detection. + * HMAC-SHA256 of game .text segment for runtime code modification detection. + * CRC32 retained for heartbeat state_hash. */ #include @@ -13,6 +14,7 @@ #include #include "integrity.h" +#include "hmac_sha256.h" /* ------------------------------------------------------------------------- * CRC32 — standard polynomial 0xEDB88320 (reflected) @@ -190,14 +192,20 @@ int owl_integrity_baseline(struct owl_integrity *ctx, pid_t pid) return -1; } - ctx->baseline_crc = owl_crc32(buf, ctx->text_size); - ctx->baseline_set = true; + if (owl_integrity_baseline_buffer(ctx, buf, ctx->text_size) < 0) { + free(buf); + return -1; + } free(buf); - printf("owlbeard: integrity baseline: text=0x%lx size=%lu crc32=0x%08x\n", + char hex[OWL_HMAC_SHA256_LEN * 2 + 1]; + for (size_t i = 0; i < OWL_HMAC_SHA256_LEN; i++) + sprintf(hex + 2 * i, "%02x", ctx->baseline_hmac[i]); + + printf("owlbeard: integrity baseline: text=0x%lx size=%lu hmac=%s\n", (unsigned long)ctx->text_start, (unsigned long)ctx->text_size, - ctx->baseline_crc); + hex); return 0; } @@ -217,10 +225,46 @@ int owl_integrity_check(const struct owl_integrity *ctx) return -1; } - uint32_t current_crc = owl_crc32(buf, ctx->text_size); + int result = owl_integrity_check_buffer(ctx, buf, ctx->text_size); free(buf); - if (current_crc != ctx->baseline_crc) + return result; +} + +/* ------------------------------------------------------------------------- + * Buffer-based integrity functions (testable without /proc I/O) + * ----------------------------------------------------------------------- */ + +int owl_integrity_baseline_buffer(struct owl_integrity *ctx, + const uint8_t *buf, size_t len) +{ + if (!ctx || !buf) + return -1; + + if (owl_hmac_generate_key(ctx->hmac_key, OWL_HMAC_SHA256_LEN) < 0) + return -1; + + if (owl_hmac_sha256(ctx->hmac_key, OWL_HMAC_SHA256_LEN, + buf, len, ctx->baseline_hmac) < 0) + return -1; + + ctx->baseline_set = true; + return 0; +} + +int owl_integrity_check_buffer(const struct owl_integrity *ctx, + const uint8_t *buf, size_t len) +{ + if (!ctx || !buf || !ctx->baseline_set) + return -1; + + uint8_t current[OWL_HMAC_SHA256_LEN]; + + if (owl_hmac_sha256(ctx->hmac_key, OWL_HMAC_SHA256_LEN, + buf, len, current) < 0) + return -1; + + if (memcmp(current, ctx->baseline_hmac, OWL_HMAC_SHA256_LEN) != 0) return 1; /* Integrity violation */ return 0; diff --git a/daemon/integrity.h b/daemon/integrity.h index 20397a1..99c0325 100644 --- a/daemon/integrity.h +++ b/daemon/integrity.h @@ -2,9 +2,10 @@ /* * integrity.h - Userspace code integrity verification * - * Computes a CRC32 hash of the game's .text segment from /proc//mem - * at baseline, then periodically re-checks. Any mismatch indicates - * runtime code modification (code injection, inline hooks, etc.). + * Computes an HMAC-SHA256 of the game's .text segment from /proc//mem + * at baseline using a per-session random key, then periodically re-checks. + * Any mismatch indicates runtime code modification (code injection, + * inline hooks, etc.). */ #ifndef OWLBEAR_INTEGRITY_H @@ -15,12 +16,15 @@ #include #include +#include "hmac_sha256.h" + /* Integrity checker state */ struct owl_integrity { pid_t target_pid; - uint64_t text_start; /* Virtual address of .text */ - uint64_t text_size; /* Size of .text in bytes */ - uint32_t baseline_crc; /* CRC32 captured at baseline */ + uint64_t text_start; /* Virtual address of .text */ + uint64_t text_size; /* Size of .text in bytes */ + uint8_t baseline_hmac[OWL_HMAC_SHA256_LEN]; /* HMAC-SHA256 at baseline */ + uint8_t hmac_key[OWL_HMAC_SHA256_LEN]; /* Per-session random key */ bool baseline_set; }; @@ -31,12 +35,13 @@ struct owl_integrity { void owl_integrity_init_ctx(struct owl_integrity *ctx); /** - * owl_integrity_baseline - Capture baseline .text CRC32 + * owl_integrity_baseline - Capture baseline .text HMAC-SHA256 * @ctx: Integrity context * @pid: Target PID * * Parses /proc//maps to find the first r-xp segment, - * reads it via /proc//mem, and computes CRC32. + * reads it via /proc//mem, and computes HMAC-SHA256 + * with a fresh random key. * * Returns 0 on success, -1 on error. */ @@ -52,6 +57,31 @@ int owl_integrity_baseline(struct owl_integrity *ctx, pid_t pid); */ int owl_integrity_check(const struct owl_integrity *ctx); +/** + * owl_integrity_baseline_buffer - Capture baseline HMAC-SHA256 of a buffer + * @ctx: Integrity context + * @buf: Data buffer + * @len: Buffer length + * + * Generates a random key, computes HMAC-SHA256, stores both. + * Returns 0 on success, -1 on error. + */ +int owl_integrity_baseline_buffer(struct owl_integrity *ctx, + const uint8_t *buf, size_t len); + +/** + * owl_integrity_check_buffer - Verify buffer against stored baseline + * @ctx: Integrity context (must have baseline set) + * @buf: Data buffer + * @len: Buffer length + * + * Returns 0 if buffer matches baseline. + * Returns 1 if buffer has changed (integrity violation). + * Returns -1 on error. + */ +int owl_integrity_check_buffer(const struct owl_integrity *ctx, + const uint8_t *buf, size_t len); + /** * owl_crc32 - Compute CRC32 of a buffer * @buf: Data buffer diff --git a/scripts/verify.sh b/scripts/verify.sh index df2ba36..a9bd754 100755 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -297,7 +297,7 @@ preflight() { | grep -o '"accountId" *: *"[^"]*"' | cut -d'"' -f4 || echo "local") cat > "${OUT_DIR}/summary.txt" <
"${phase_dir}/dmesg_after.txt" dmesg_since "${phase_mark}" "${phase_dir}/dmesg_phase_diff.txt" @@ -855,6 +867,15 @@ phase_protected() { assert_pass "protected/code integrity baseline captured" fi + # Check integrity baseline uses HMAC-SHA256 (not CRC32) + if [ -f "${phase_dir}/daemon_stdout.log" ] && \ + grep -q "hmac=" "${phase_dir}/daemon_stdout.log" 2>/dev/null; then + assert_pass "protected/code integrity uses HMAC-SHA256" + elif [ -f "${phase_dir}/daemon_stdout.log" ] && \ + grep -q "crc32=" "${phase_dir}/daemon_stdout.log" 2>/dev/null; then + assert_fail "protected/code integrity still uses CRC32 (should be HMAC-SHA256)" + fi + stop_daemon # Unload module @@ -980,7 +1001,7 @@ FOOTER main() { echo "" echo -e "${BOLD}================================================${NC}" - echo -e "${BOLD} Owlbear E2E Verification (v2.2.0)${NC}" + echo -e "${BOLD} Owlbear E2E Verification (v2.3.0)${NC}" echo -e "${BOLD} Evidence Package Builder${NC}" echo -e "${BOLD}================================================${NC}" echo "" diff --git a/tests/Makefile b/tests/Makefile index a9721da..adc1d99 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -24,7 +24,8 @@ TEST_BINS := test_events \ test_self_protect \ test_debugger_detect \ test_preload_detect \ - test_process_tree + test_process_tree \ + test_hmac_sha256 .PHONY: all unit integration clean @@ -69,8 +70,8 @@ test_sig_loader: test_harness.o test_sig_loader.o $(DAEMON_DIR)/sig_loader.o $(D test_event_pipeline: test_harness.o test_event_pipeline.o $(DAEMON_DIR)/event_pipeline.o $(DAEMON_DIR)/policy.o $(DAEMON_DIR)/scanner.o $(DAEMON_DIR)/preload_detect.o $(DAEMON_DIR)/process_tree.o $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -test_integrity: test_harness.o test_integrity.o $(DAEMON_DIR)/integrity.o - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) +test_integrity: test_harness.o test_integrity.o $(DAEMON_DIR)/integrity.o $(DAEMON_DIR)/hmac_sha256.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lssl -lcrypto test_self_protect: test_harness.o test_self_protect.o $(DAEMON_DIR)/self_protect.o $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) @@ -84,6 +85,9 @@ test_preload_detect: test_harness.o test_preload_detect.o $(DAEMON_DIR)/preload_ test_process_tree: test_harness.o test_process_tree.o $(DAEMON_DIR)/process_tree.o $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) +test_hmac_sha256: test_harness.o test_hmac_sha256.o $(DAEMON_DIR)/hmac_sha256.o $(DAEMON_DIR)/integrity.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lssl -lcrypto + # Daemon objects needed by tests $(DAEMON_DIR)/%.o: $(DAEMON_DIR)/%.c $(CC) $(CFLAGS) $(DEPFLAGS) -c -o $@ $< @@ -103,7 +107,7 @@ clean: $(RM) $(TEST_BINS) *.o *.d $(RM) $(DAEMON_DIR)/policy.o $(DAEMON_DIR)/scanner.o $(DAEMON_DIR)/heartbeat.o $(RM) $(DAEMON_DIR)/bpf_event_convert.o $(DAEMON_DIR)/sig_loader.o - $(RM) $(DAEMON_DIR)/event_pipeline.o $(DAEMON_DIR)/integrity.o + $(RM) $(DAEMON_DIR)/event_pipeline.o $(DAEMON_DIR)/integrity.o $(DAEMON_DIR)/hmac_sha256.o $(RM) $(DAEMON_DIR)/self_protect.o $(DAEMON_DIR)/debugger_detect.o $(DAEMON_DIR)/preload_detect.o $(DAEMON_DIR)/process_tree.o $(RM) $(DAEMON_DIR)/*.d diff --git a/tests/test_hmac_sha256 b/tests/test_hmac_sha256 new file mode 100755 index 0000000000000000000000000000000000000000..62630687672800bcab7488418cd4cb221859df38 GIT binary patch literal 26352 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 literal 0 HcmV?d00001 diff --git a/tests/test_hmac_sha256.c b/tests/test_hmac_sha256.c new file mode 100644 index 0000000..522b37e --- /dev/null +++ b/tests/test_hmac_sha256.c @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * test_hmac_sha256.c - Tests for HMAC-SHA256 and integrity buffer functions + */ + +#include +#include + +#include "test_harness.h" +#include "hmac_sha256.h" +#include "integrity.h" + +/* Helper: hex string to bytes */ +static void hex_to_bytes(const char *hex, uint8_t *out, size_t out_len) +{ + for (size_t i = 0; i < out_len; i++) { + unsigned int byte; + sscanf(hex + 2 * i, "%02x", &byte); + out[i] = (uint8_t)byte; + } +} + +/* ------------------------------------------------------------------------- + * RFC 4231 known-answer tests + * ----------------------------------------------------------------------- */ + +TEST(hmac_rfc4231_test1) { + /* Key = 0x0b * 20, data = "Hi There" */ + uint8_t key[20]; + memset(key, 0x0b, sizeof(key)); + const uint8_t *data = (const uint8_t *)"Hi There"; + uint8_t out[OWL_HMAC_SHA256_LEN]; + uint8_t expected[OWL_HMAC_SHA256_LEN]; + + hex_to_bytes("b0344c61d8db38535ca8afceaf0bf12b" + "881dc200c9833da726e9376c2e32cff7", + expected, OWL_HMAC_SHA256_LEN); + + int ret = owl_hmac_sha256(key, sizeof(key), data, 8, out); + ASSERT_EQ(ret, 0); + ASSERT_EQ(memcmp(out, expected, OWL_HMAC_SHA256_LEN), 0); +} + +TEST(hmac_rfc4231_test2) { + /* Key = "Jefe", data = "what do ya want for nothing?" */ + const uint8_t *key = (const uint8_t *)"Jefe"; + const uint8_t *data = (const uint8_t *)"what do ya want for nothing?"; + uint8_t out[OWL_HMAC_SHA256_LEN]; + uint8_t expected[OWL_HMAC_SHA256_LEN]; + + hex_to_bytes("5bdcc146bf60754e6a042426089575c7" + "5a003f089d2739839dec58b964ec3843", + expected, OWL_HMAC_SHA256_LEN); + + int ret = owl_hmac_sha256(key, 4, data, 28, out); + ASSERT_EQ(ret, 0); + ASSERT_EQ(memcmp(out, expected, OWL_HMAC_SHA256_LEN), 0); +} + +/* ------------------------------------------------------------------------- + * Edge cases + * ----------------------------------------------------------------------- */ + +TEST(hmac_empty_input) { + uint8_t key[OWL_HMAC_SHA256_LEN]; + memset(key, 0x42, sizeof(key)); + uint8_t out[OWL_HMAC_SHA256_LEN]; + memset(out, 0, sizeof(out)); + + int ret = owl_hmac_sha256(key, sizeof(key), NULL, 0, out); + ASSERT_EQ(ret, 0); + + /* Output should be non-zero (valid HMAC of empty data) */ + int all_zero = 1; + for (size_t i = 0; i < OWL_HMAC_SHA256_LEN; i++) { + if (out[i] != 0) { + all_zero = 0; + break; + } + } + ASSERT_EQ(all_zero, 0); +} + +TEST(hmac_large_input) { + uint8_t key[OWL_HMAC_SHA256_LEN]; + memset(key, 0xBB, sizeof(key)); + + size_t len = 64 * 1024; + uint8_t *data = malloc(len); + ASSERT_TRUE(data != NULL); + memset(data, 0xAA, len); + + uint8_t out[OWL_HMAC_SHA256_LEN]; + int ret = owl_hmac_sha256(key, sizeof(key), data, len, out); + free(data); + ASSERT_EQ(ret, 0); +} + +TEST(hmac_key_change) { + const uint8_t data[] = "same data for both"; + uint8_t key1[OWL_HMAC_SHA256_LEN], key2[OWL_HMAC_SHA256_LEN]; + memset(key1, 0x11, sizeof(key1)); + memset(key2, 0x22, sizeof(key2)); + + uint8_t out1[OWL_HMAC_SHA256_LEN], out2[OWL_HMAC_SHA256_LEN]; + owl_hmac_sha256(key1, sizeof(key1), data, sizeof(data) - 1, out1); + owl_hmac_sha256(key2, sizeof(key2), data, sizeof(data) - 1, out2); + + ASSERT_NE(memcmp(out1, out2, OWL_HMAC_SHA256_LEN), 0); +} + +TEST(hmac_same_data_same_hash) { + uint8_t key[OWL_HMAC_SHA256_LEN]; + memset(key, 0xCC, sizeof(key)); + const uint8_t data[] = "deterministic"; + + uint8_t out1[OWL_HMAC_SHA256_LEN], out2[OWL_HMAC_SHA256_LEN]; + owl_hmac_sha256(key, sizeof(key), data, sizeof(data) - 1, out1); + owl_hmac_sha256(key, sizeof(key), data, sizeof(data) - 1, out2); + + ASSERT_EQ(memcmp(out1, out2, OWL_HMAC_SHA256_LEN), 0); +} + +TEST(hmac_null_inputs) { + uint8_t key[OWL_HMAC_SHA256_LEN]; + memset(key, 0xDD, sizeof(key)); + uint8_t data[] = "test"; + uint8_t out[OWL_HMAC_SHA256_LEN]; + + ASSERT_EQ(owl_hmac_sha256(NULL, sizeof(key), data, 4, out), -1); + ASSERT_EQ(owl_hmac_sha256(key, sizeof(key), NULL, 4, out), -1); + ASSERT_EQ(owl_hmac_sha256(key, sizeof(key), data, 4, NULL), -1); +} + +TEST(hmac_generate_key) { + uint8_t key1[OWL_HMAC_SHA256_LEN] = {0}; + uint8_t key2[OWL_HMAC_SHA256_LEN] = {0}; + + ASSERT_EQ(owl_hmac_generate_key(key1, sizeof(key1)), 0); + ASSERT_EQ(owl_hmac_generate_key(key2, sizeof(key2)), 0); + + /* key should be non-zero */ + int all_zero = 1; + for (size_t i = 0; i < OWL_HMAC_SHA256_LEN; i++) { + if (key1[i] != 0) { + all_zero = 0; + break; + } + } + ASSERT_EQ(all_zero, 0); + + /* Two generated keys should differ */ + ASSERT_NE(memcmp(key1, key2, OWL_HMAC_SHA256_LEN), 0); +} + +/* ------------------------------------------------------------------------- + * Integrity buffer functions + * ----------------------------------------------------------------------- */ + +TEST(integrity_hmac_baseline_and_check) { + struct owl_integrity ctx; + owl_integrity_init_ctx(&ctx); + + uint8_t buf[256]; + memset(buf, 0x42, sizeof(buf)); + + int ret = owl_integrity_baseline_buffer(&ctx, buf, sizeof(buf)); + ASSERT_EQ(ret, 0); + ASSERT_EQ(ctx.baseline_set, true); + + ret = owl_integrity_check_buffer(&ctx, buf, sizeof(buf)); + ASSERT_EQ(ret, 0); +} + +TEST(integrity_hmac_violation) { + struct owl_integrity ctx; + owl_integrity_init_ctx(&ctx); + + uint8_t buf[256]; + memset(buf, 0x42, sizeof(buf)); + + int ret = owl_integrity_baseline_buffer(&ctx, buf, sizeof(buf)); + ASSERT_EQ(ret, 0); + + /* Modify one byte */ + buf[128] = 0xFF; + ret = owl_integrity_check_buffer(&ctx, buf, sizeof(buf)); + ASSERT_EQ(ret, 1); +} + +/* ------------------------------------------------------------------------- + * Runner + * ----------------------------------------------------------------------- */ + +int main(void) +{ + printf("=== Owlbear HMAC-SHA256 Tests ===\n"); + + RUN_TEST(hmac_rfc4231_test1); + RUN_TEST(hmac_rfc4231_test2); + RUN_TEST(hmac_empty_input); + RUN_TEST(hmac_large_input); + RUN_TEST(hmac_key_change); + RUN_TEST(hmac_same_data_same_hash); + RUN_TEST(hmac_null_inputs); + RUN_TEST(hmac_generate_key); + RUN_TEST(integrity_hmac_baseline_and_check); + RUN_TEST(integrity_hmac_violation); + + TEST_SUMMARY(); + return test_failures; +} diff --git a/tests/test_integrity b/tests/test_integrity index 5c8d0988225000e091650b07aa170dc2ebc3bc71..0847161c01cf85b7fd1c021c4220352be497e473 100755 GIT binary patch literal 22208 zcmeHPeRx#WnLiU4h!#!2ulTVrqOnjRgb*+S(c$C5#U>JgShUs4Br_q=$z+@l3~DrX zL>Y%zYHc^$+AiDeD$i5f=CMjsTIql`L8Tfj+lN+bvwn1EOvI?D(OPDI@A5SWcdq_dW0TdC$4$oO|x%-lf&7C~!EKD&yD{jB0~Z1jVfws};hSn^m#X@I8%9 zWfMRikB?ij?eK7cU?^B9<;DS$UI`&%zzYPKDX1bONP787;pYTLK~^m4q~|15*6lEU zzK~N;@lAi_g3oNQbE2RtXw{?K6jlpw@pc-d${4EU&D(CpUv;8fBX#4E;ss*zbRF;L?$|`sW6qgGh8dEE;uBYxu z5>0hyL8quId&E0a@=1PL@GWDaWARNh*pcK5vQ+vZuP7>V%(% z56Osp+zm|72p;sk&`L00Sr3N1v~xsW&qKd95B-mM=oFU=AA2!C7|ZYNdFbEEL+{K( zUy+AS`E=o9FHsQ2if0z+F1s-5efW$e|5hIQy?N*_Vq2HZ{{xi_0<8xdwjE${r0V5pogd&E)j8*Gu4X-cc+t?D0_(JPym-*WQzIC1k zzfbVSeAl)MR;GpH_# z12Q8()pg*yG>B`q*S`h+1a=Piq;qCV%V{*rO_%jv&L7Wa$$Ip> zmQyIc%cMPXog-r?$uk5jR_mXrvQ9}atP=#a9;y0ax!*uAV%?T{gBH46>NzK6p(9|k zj9BP2Z>lnCp`W9OfaQ`-%erh5=T=$hD!0UNTj*-;C%SH-)4Z-qorO+qQ)Rt{F1Hk% zwZTGHIU+{0g^ms|OVC0;)ub}kZlO=I&^s;k(=GI^7J89|zTHBn@u5n$g+5sk0e4vF z*7uxehaIvtwS7O=Pl8h8&2K3l7g-`QTWafWz1!I}gPw`ze&CN)@nKP3t~EytJx1BV~cb1^Ho6B)O+0g#5Eye*QiJGmq)<5q~p1`0ES zqFQsbBl>a`@4X?4e6nkN2kz;F^qUhZ5Q$2psOc0~thU zhY{!?5A-l8vUZEI!yWS~y2}p{U;IB+8)?Q>hTw-H@?gRek`FqrgtOv`*BeYAUJZfAH!!L zvKklVe$)o!@NtXKufu(eNd88S$kK)+yh64;b@StCFDq4 zR5fs9y{MK5M_N5epdkOHljUj_Zz2%SZvo#=0XZWs7_=tzmidNo{0PE{`FBE^B!WXwfH zyR=l%uB0B{;-((x-=YJ+3IY<8MVu0;*Aw655(!?HW6B`GF6ROq4Tz3e&N12GM?a(n zYdA_14PFF{H@E^w`V|o2eW&nVC%muEdgqiyTZqEF^Lm2UrS}cOdoT8N!h0Xbr1zQJ zdw-?!{uD6o{RtrH8-@3N;eCVf-kkN$DT}rcg?s1q1g}f)9^ri<_eq_tb4+^w;Rn?A zRd6NRekCyOeF2d4Aav38{la@tcyG^o=afZTh!RGx+4~)CH28ew`#}SidM0YupB44Q_tibX?UUg1~YQM7>-&7LL0%h~#3T%bC z(5VUMhd{9{bV2JoT#F+6fiTxgYN=VUIW!g2+fDvl5jo% zjJIP8kkrH6=U0JBpKDB;kB&j(DKy4B{ud$OGYlV54&_kfRf-ok0lHL%z3bmLq2tN_M+&IFS3bDx(0l|C1l zHV;jq7Rz>gMfp76!sn~lb@V$A(B1%HIz@be`cf=S{HJ?_7^>;qxkB+~*P?sew_-?G->(ZcUrRlP&Fx zD4zk7f7r@jCw$%{e115Ge7=Ei;q!OExX<4JNu7hGF5!F*sPtKB+HAMlWXk86Cf{r2 z503D53a<03u-ESl;#>G^0LFb@2PE}H?(x*et~c9f-UL*um6%SFHDK+`bKsJJ>oB!@fAyadhIHf6!yv zsDs57hE>xAu7J>Nd9!aZ)+{JqvZjYr#KqvN8>v6_r54n-FOzPosKv=Z>W z#qH5qfbTC3MlVLY$p%6ymb=dZedaz;uz4)zbLP;Ms15GHE}1U7)b4lC>vVS&>qxQ4 zKY#}`>7d|94#~SGS+wOk1U}^0&Km%`v`ajb-+$r;uNxLD6aL-9+hIE1u??B&)Z^cz z#Z8ZQ1p#b1O4M(|=A|coQ13eHPes_)xJ682YQNGcRl&pR=d# z7$ZsFB%+z8XK;9yo2OOqL2M-PNig;J@2Fd2M2&0R2)dg_9tDwpk0R;UI_c44&XxcQ zON9b9nH}3%G>XPx=g^;eS+yYjByWa>)M#75?bKt~m0qrG4Xx4-`a01-e6ZgT?w=6W zM9!kq1gAfB8j+>tyOrgk8$sHMV7CKyqA#}UU3Czvr8@A%bP*z$z5IY6b*?bI1A*>f zMO#`ZJBfNB>lo-m%cKLBa0X89cufuG@_X9*a7!H59uk!PR39RXbv$HV0o6)7;V#y3cE=o>aJ+@w^}Es2 zjPi#r0}t-6hpsuAmHSU2C4_Y0J`sfb`kf-;3vr~dCAs-*NT8egQ!8PDUrOm`Og##_ zb|<$XLT*P)R;4MX($|C%H}&aTh^Alb28j(Vg-gVVzINbDE#$B~e!Ot=gA5dlAN`wrKXyNx61JeMcg zv-bS33q3EV$RZfWt(1FxY{YR-G9o+tKGCR@O7r_LjWmxUpivf`C}tiXsp<)yV?fHW zmP#P=^`l7ZZXA*zV`qRkN@*UX=rFo7L$ie*&oK?ulpGe1z-e4NsuX?#g@ktWxWHiz z3rrjfA_c=&qY*QvMy?%8R_$?76X16oo-ZH{88e;mjAA&J2-seQXc0RdH|*Cjb;tK{ z#nkVioz*&xq%r0lynk{cs{5O(=Gll7t0pBHcTOtNG9H>N_Um1UgC92F_y?<_159<@*5I74)DVMCW$&YlpyMecEp&e*yyi?a+9H-HRb~m>L*= zI<@ydX+-tc&_$St_8?H=?B`FHx@r$yQybq)8;AJ8_#bd-q?RIZJZHi+kA*zeF~}l? zIQ@-{x|CnDy(w#ZpC>Pg8%DEjhJ$i6`7j0%uF8(XVgL=8?fM2{7jtHpvz^XR)Lwo7 zrf@bM>lkKgFx`Y}eS{i2v=XroV6I2NSa-4a!HD9EE)LRZ`To~GTdp5kbcaC^^QgAVE8R4?=sA@W5MArGPfJUiyoHlm*_Co^y|11B@^zmoy_6(N;~FB~!OlS<#l zP)lTU86CIr;zB76FD&&gbottYzQ%~p>nip8y|Y{!+aer0m5n8HVYOsRJLTn-u~2)EjX@5y<>f^EevDiE4w#vv7xk8i(db7m!t|qF#CvL~cTTC-MWa0I3VOm} zpO?-T7%TO+&&J19S{Y_@f}yrXh|R$-dMy=CFw8=%w7jAn@@*o=xExG(t_DxohyN1r zErk8{NOgHT84Tlh!_}q!sH?fv(^yS8p5ygxniCCq0^YV(<~V=cBHC5qF(KReN+wf? zEneZPnM^rg37`(x{HIKYHY3*zW-=R4KLpqb`1SwDWOe{v@meO61Z1ygGJ}Bo0O@kB zc{7u70ZznL!wvWozzu+RWBc6+IEees9e~&49zO{f!jZ)w;3GK0p?^4-jx$Ub;1>bi zfEv!IHvk?3>;&A71N0q$t8q4*1YCx5%r^k3;7pkp$8BqvqrKR1{-lY8+YuYlFTf{= zwp~IJ%O}#EAG;WzN_@Is7Hwpw7q2+I17 zKlr}_e`gN=pH2QY@K?T($-IQV&DwvqK-qr`{Esm<4Emjb>HpgCihlt7D%=&{mSg`G z)BZ5{4}xC;nAI;bKpsHs$m9a?@@_&*7PCp^0a>u0t(!P$0`hTeNMb-Sj+w){y{a+NV_f)Vo;pKy4 znKnXtIvKEvJ1N*qiZSJXs-!D9JTKtwgF8+-ChLRJFiw>@U&V!GoY#LK z`FOm`>#7~n{ND|j|8H%xSS~l8{J8~qb+W!e!k~nm5^k4phlD*6CM6t@a8SY#2^k(N zQz@3vC1JUQZVBro+#q34LZSWHzYFVx?8;@!7P@BCH$(%GsB7-LGW@&Z>;+L?t+=zI zvaGzaZ0=0SIFWT4M&t27-!4Pr!U4`U*>Nr@fZt1uDNp03fEBZ160j5(aH6|y^m&r5 zu4ARL3Wx*$IbAH^-6E5B7Xy7KF``JI3SQhuJ5 z`HvwEDpMuBMou97-U{^jl75Pui1CW zN;k47{9XpI9P}~mfHxNX3dlQfH+u(u@ z^V(~;4qbE#A^TU!-wF9CXm9^aLE-l}Kp&9w^%n{{zc&QhE$M|)p5HTpzMs>Dto8e+ zdFXw4=zm6>6we@j8bpPkAprK{f|4XoS6?r~j!RW6@U1-d|HA3T?AxV6ST=)AA-@Ha z&2?Rw+LXsHz0YK`r5)XN9rfjr|2?M{v!^~UJn}ONpl|1qcVGiZ z`B&?gin9>(vBq0z9(on07qh2Jg#~_g0(4fM@vvITza+1Be%1r|prn5+H?I5)3G^t@ z3$Qyb7WU2WwT+?3+_E;jS;5oLVnjR}ajF~%M{pF4hYi^mLKu-&oZPkreDqoeZ=12v z-`3#q8{SA8&T>7`cGlR|8ua_{7y@rm7*m4Y+R$QnLLtv)14qiC&3F?8Kc|kiwr+-s zr6vxFt)l!fNV6vd|6#<%tBq~g3<;FpE)fkOHo=I7_}Mm5ecoJJ04@c^JSR5o9e)%r z%yGK)+}%R99===2yk)s3@D_IVz@4AcXRG}DoePd}+D?b?`FQdqJ}*0a9M46}#*c9( zPw(e2=*Zom^L9&(4&3R~T)y%Hc{7X^YnIe%hIaLGdWVRCx8oR^E{Xc`HOyF9vwG>0 z8e{c}6>GJ1#=0d-YcvQhzwYWKwX2rVsl8#b$m{$G1;?^MHa7e49ufI`M7-C-tzOkZ zui{Ye9myfu-f%*%B+22E^Q;T;Y$DRm_&AksAjy&EuPn)-WM6;c&V7wYu4(lgLN&l_ z^+sR77s6u@<7OYOfD^ufWi=j{cv}KS6i-O_dsK1);kskKp#_&BABFUq7j%&I?I}4H z1HC27ghRkLaO=Hh%FDf4a)zy;$l5)zzEzEHTOEs#?&zzg~O9ukyT&>vxCJj^nn zWq7E}I1=_XvNC#{#>!|uhjbgyUzx92&fv{nSW`7&L(KX@L*a1cX>EZqp^olnWmrS# zX`{I|{SOd2*Ky#3?ISO=|D&RyI@b|YA**nL7vV!k8cM%P>MJO>Z6wNzy6;nU{Kr;~ zzWx1e7b`&tvAxJCbYE=sukOngbmd6Xy-RNS5~_F%*rwuF=T!0H$ z!K1S)RafU%3I@4$HpeP{NoHL@D5pwaou?_7l!D5?(pT;ON2$M5%Bk}?1=V>T>64CK z|6f3(oGAO|zD@4m)VU=@c(M2Y!=PIAT~bfM4Yq_!w&~_kn|`M}zfw@i3-8%&rK0!P z^tVfW1+CA7$%fKXkoMiy_y^@?TET}^qDdJ=>4}>7FMF%LI{#HroeL{@d;We62I;H* zSNCZOw#(~5>8t)z_21a^)p>w|hm@d%cKf`rLWF6)cZ44Vrl-MqV!Zh{tz_E zzp1~Pq;RcVDPT$f^IPdFNatWyee)c}EmV{rWkBhv`Xne5P5D>%cg1cYQKbYWwChin z{>yE0N`JPEPO(z4LUZg17XNm;MP-I`_z$Sgz(@I4m&GZdsn~^v_-@t(ydC$0)}s6> U8eOhq>AzkpB+j!b*sAQm0C10XPXGV_ literal 21800 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 diff --git a/tests/test_integrity.c b/tests/test_integrity.c index 037edc0..1526b78 100644 --- a/tests/test_integrity.c +++ b/tests/test_integrity.c @@ -88,11 +88,14 @@ TEST(parse_text_segment_null_input) { TEST(integrity_init_clears_state) { struct owl_integrity ctx; ctx.baseline_set = true; - ctx.baseline_crc = 0xDEADBEEF; + memset(ctx.baseline_hmac, 0xFF, sizeof(ctx.baseline_hmac)); + memset(ctx.hmac_key, 0xFF, sizeof(ctx.hmac_key)); owl_integrity_init_ctx(&ctx); ASSERT_EQ(ctx.baseline_set, false); - ASSERT_EQ(ctx.baseline_crc, 0); + ASSERT_EQ(ctx.baseline_hmac[0], 0); + ASSERT_EQ(ctx.baseline_hmac[31], 0); + ASSERT_EQ(ctx.hmac_key[0], 0); ASSERT_EQ(ctx.target_pid, 0); }