From 5b01527380f4cc553e2cd5a8aab707978efe66c2 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 21:47:16 +0900 Subject: [PATCH 01/37] Initial commit --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..46fae13 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Daiki Ueno + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 15b65dbf45ce17255d94f5cf10edc78b4cbf169c Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 21:48:29 +0900 Subject: [PATCH 02/37] Initial import Signed-off-by: Daiki Ueno --- README.md | 39 +++++++++++++ crau.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ crau.h | 62 ++++++++++++++++++++ macros.h | 117 +++++++++++++++++++++++++++++++++++++ 4 files changed, 386 insertions(+) create mode 100644 README.md create mode 100644 crau.c create mode 100644 crau.h create mode 100644 macros.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..2d82c55 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# crau + +`crau` is a small helper library to define +[crypto-auditing][crypto-auditing] probes in C applications. The +library shall be either statically linked or bundled into the +application itself. + +## Getting started + +1. Copy all source files (`crau.h`, `crau.c`, and `macros.h`) to your + application and add them to the build infrastructure (e.g., Makefiles). + +1. Define `ENABLE_CRYPTO_AUDITING` to 1, e.g., through `` + +1. (Optional) Customize macros, e.g., `CRAU_CONTEXT_STACK_DEPTH` for + your needs. See the header of `crau.c` for the details. + +1. Include "crau.h" and instrument the code as follows. See `crau.h` + or `macros.h` for the documentation: + +```c +crau_new_context_with_data( + (crau_context_t)some_function, + CRAU_DATA_TYPE_STRING, "name", "pk::sign") +... +crau_data( + CRAU_DATA_TYPE_STRING, "pk::algorithm", "mldsa", + CRAU_DATA_TYPE_WORD, "pk::bits", 1952 * 8) + +sig = mldsa_sign(...); + +crau_pop_context(); +``` + +## License + +MIT + +[crypto-auditing]: https://github.com/latchset/crypto-auditing diff --git a/crau.c b/crau.c new file mode 100644 index 0000000..78ff451 --- /dev/null +++ b/crau.c @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) 2022-2025 The crypto-auditing developers. */ + +/* This file implements the functions a set of high-level functions to + * insert probe points used for crypto-auditing into the application + * programs. + * + * This file is typically copied into the application's source code as + * a copylib, and the following configuration macros can be used to + * override the behavior of the implementation: + * + * * CRAU_CONTEXT_STACK_DEPTH: depth of the thread-local context stack + * (default: 3) + * + * * CRAU_THREAD_LOCAL: thread-local modifier of the C language + * (default: auto-detected) + * + * * CRAU_MAYBE_UNUSED: an attribute to suppress warnings when a + * function argument is not used in the function body (default: + * auto-detected) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "crau.h" + +#include +#include +#include + +#ifdef ENABLE_CRYPTO_AUDITING + +#ifndef CRAU_CONTEXT_STACK_DEPTH +#define CRAU_CONTEXT_STACK_DEPTH 3 +#endif /* CRAU_CONTEXT_STACK_DEPTH */ + +#ifndef CRAU_THREAD_LOCAL +# ifdef thread_local +# define CRAU_THREAD_LOCAL thread_local +# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) +# define CRAU_THREAD_LOCAL _Thread_local +# elif defined(_MSC_VER) +# define CRAU_THREAD_LOCAL __declspec(thread) +# elif defined(__GNUC__) +# define CRAU_THREAD_LOCAL __thread +# else +# error "thread_local support required" +#endif /* CRAU_THREAD_LOCAL */ + +#ifndef CRAU_MAYBE_UNUSED +# if defined(__has_c_attribute) && \ + __has_c_attribute (__maybe_unused__) +# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] +# elif defined(__GNUC__) +# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) +# endif +#endif /* CRAU_MAYBE_UNUSED */ + +static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { + 0, +}; +static CRAU_THREAD_LOCAL size_t context_stack_top = 0; + +void crau_push_context(crau_context_t context) +{ + assert(context_stack_top < CRAU_CONTEXT_STACK_DEPTH); + context_stack[context_stack_top++] = context; +} + +crau_context_t crau_pop_context(void) +{ + assert(context_stack_top > 0); + return context_stack[--context_stack_top]; +} + +crau_context_t crau_current_context(void) +{ + if (context_stack_top == 0) + return ~0UL; + return context_stack[context_stack_top - 1]; +} + +static inline size_t +accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], + va_list ap) +{ + size_t count = 0; + + for (; count < CRAU_MAX_DATA_ELEMS;) { + switch (va_arg(ap, enum crau_data_type_t)) { + case CRAU_DATA_TYPE_WORD: + data[count].key_ptr = va_arg(ap, char *); + data[count].value_ptr = (void *)va_arg(ap, intptr_t); + data[count].value_size = (unsigned long)-2; + count++; + break; + case CRAU_DATA_TYPE_STRING: + data[count].key_ptr = va_arg(ap, char *); + data[count].value_ptr = (void *)va_arg(ap, char *); + data[count].value_size = (unsigned long)-1; + break; + case CRAU_DATA_TYPE_BLOB: + data[count].key_ptr = va_arg(ap, char *); + data[count].value_ptr = va_arg(ap, void *); + data[count].value_size = va_arg(ap, unsigned long); + count++; + break; + } + } + + return count; +} + +void crau_new_context_with_data(crau_context_t context, ...) +{ + struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; + size_t count; + va_list ap; + + va_start(ap); + count = accumulate_datav(data, ap); + va_end(ap); + + CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, + count); + crau_push_context(context); +} + +void crau_data(...) +{ + struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; + size_t count; + va_list ap; + + va_start(ap); + count = accumulate_datav(data, ap); + va_end(ap); + + CRAU_DATA(crau_current_context(), data, count); +} + +#else + +void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) +{ +} + +crau_context_t crau_pop_context(void) +{ + return ~0UL; +} + +crau_context_t crau_current_context(void) +{ + return ~0UL; +} + +void crau_new_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) +{ +} + +void crau_data(...) +{ +} + +#endif /* ENABLE_CRYPTO_AUDITING */ diff --git a/crau.h b/crau.h new file mode 100644 index 0000000..f76733b --- /dev/null +++ b/crau.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) 2022-2025 The crypto-auditing developers. */ + +/* This file declares a set of high-level functions to insert probe + * points used for crypto-auditing into the application programs. See + * for the low-level interface. + */ + +#ifndef CRAU_CRAU_H +#define CRAU_CRAU_H + +#include "macros.h" +#include + +/* An opaque type that represents a context (e.g., TLS handshake) + * where crypto-auditing events occur. + */ +typedef uint64_t crau_context_t; + +/* Types of crypto-auditing event data. CRAU_DATA_TYPE_WORD means an + * integer in a machine word, CRAU_DATA_TYPESTRING means a + * NUL-terminated string. CRAU_DATA_TYPE_BLOB means an explicitly + * sized binary blob. + */ +enum crau_data_type_t { + CRAU_DATA_TYPE_WORD, + CRAU_DATA_TYPE_STRING, + CRAU_DATA_TYPE_BLOB, +}; + +/* Push a new context CONTEXT onto the thread-local context stack. + */ +void crau_push_context(crau_context_t context); + +/* Pop a context from the thread-local context stack. The stack must + * not be empty. + */ +crau_context_t crau_pop_context(void); + +/* Return the context currently active for this thread. + */ +crau_context_t crau_current_context(void); + +/* Push a new context CONTEXT onto the thread-local context stack, + * optionally emitting events through varargs. Typical usage example + * is as follows: + * + * crau_new_context_with_data( + * (crau_context_t)some_function, + * CRAU_DATA_TYPE_STRING, "name", "pk::sign", + * CRAU_DATA_TYPE_STRING, "pk::algorithm", "mldsa", + * CRAU_DATA_TYPE_WORD, "pk::bits", 1952 * 8) + * + * This call must be followed by a `crau_pop_context`. + */ +void crau_new_context_with_data(crau_context_t context, ...); + +/* Emit events through varargs. + */ +void crau_data(...); + +#endif /* CRAU_CRAU_H */ diff --git a/macros.h b/macros.h new file mode 100644 index 0000000..c344ea5 --- /dev/null +++ b/macros.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) 2022-2025 The crypto-auditing developers. */ + +/* This file defines a set of low-level macros to insert probe points + * used for crypto-auditing into the application programs. See + * for a higher-level and more ergonomic interface. + */ + +#ifndef CRAU_MACROS_H +#define CRAU_MACROS_H + +#ifdef ENABLE_CRYPTO_AUDITING + +#ifdef HAVE_SYS_SDT_H +#include +#endif + +/* Introduce a new context CONTEXT, derived from the parent context PARENT. + */ +#define CRAU_NEW_CONTEXT(context, parent) \ + DTRACE_PROBE2(crypto_auditing, new_context, context, parent) + +/* Emit an event with KEY and VALUE. The key is a NUL-terminated + * string, while the value is an integer in the size of a machine + * word. + */ +#define CRAU_WORD_DATA(context, key_ptr, value_ptr) \ + DTRACE_PROBE3(crypto_auditing, word_data, context, key_ptr, value_ptr) + +/* Emit an event with KEY and VALUE. The key is a NUL-terminated + * string, while the value is also a NUL-terminated string. + */ +#define CRAU_STRING_DATA(context, key_ptr, value_ptr) \ + DTRACE_PROBE3(crypto_auditing, string_data, context, key_ptr, value_ptr) + +/* Emit an event with KEY and VALUE. The key is a NUL-terminated + * string, while the value is explicitly sized binary blob of the + * VALUE_SIZE size. + */ +#define CRAU_BLOB_DATA(context, key_ptr, value_ptr, value_size) \ + DTRACE_PROBE4(crypto_auditing, blob_data, context, key_ptr, value_ptr, \ + value_size) + +/* Generic data structure that represents an event. The KEY_PTR field + * points to the name of the event key, and the VALUE_PTR field points + * to the value. + * + * The VALUE_SIZE field is set depending on the type of the value. If + * the value is a machine word, it is set to 0xfffffffe (= -2). If + * the value is a NUL-terminated string, it is set to 0xffffffff (= + * -1). Otherwise, it it set to the actual size of the value. + */ +struct crypto_auditing_data { + char *key_ptr; + void *value_ptr; + unsigned long value_size; +}; + +#define CRAU_WORD(key_ptr, value_ptr) \ + { (char *)(key_ptr), (void *)(intptr_t)(value_ptr), (unsigned long)-2 } +#define CRAU_STRING(key_ptr, value_ptr) \ + { (char *)(key_ptr), (void *)(value_ptr), (unsigned long)-1 } +#define CRAU_BLOB(key_ptr, value_ptr, value_size) \ + { (char *)(key_ptr), (void *)(value_ptr), value_size } + +/* The maximum number of events which can be emitted at once. */ +#define CRAU_MAX_DATA_ELEMS 16 + +/* Emit multiple events at once. + */ +#define CRAU_DATA(context, array_ptr, array_size) \ + DTRACE_PROBE3(crypto_auditing, data, context, array_ptr, array_size) + +/* Emit multiple events at once through varargs. + */ +#define CRAU_DATAV(context, ...) \ + ({ \ + struct crypto_auditing_data __crau_data[] = { __VA_ARGS__ }; \ + CRAU_DATA(context, __crau_data, \ + sizeof(__crau_data) / sizeof(__crau_data[0])); \ + }) + +/* Introduce a new context CONTEXT, derived from PARENT, with optional + * events to be emitted. + */ +#define CRAU_NEW_CONTEXT_WITH_DATA(context, parent, array_ptr, array_size) \ + DTRACE_PROBE4(crypto_auditing, new_context_with_data, context, parent, \ + array_ptr, array_size) + +/* Introduce a new context CONTEXT, derived from PARENT, with optional + * events to be emitted, through varargs. + */ +#define CRAU_NEW_CONTEXT_WITH_DATAV(context, parent, ...) \ + ({ \ + struct crypto_auditing_data __crau_data[] = { __VA_ARGS__ }; \ + CRAU_NEW_CONTEXT_WITH_DATA(context, parent, __crau_data, \ + sizeof(__crau_data) / \ + sizeof(__crau_data[0])); \ + }) + +#else + +#define CRAU_NEW_CONTEXT(context, parent) +#define CRAU_WORD_DATA(context, key_ptr, value_ptr) +#define CRAU_STRING_DATA(context, key_ptr, value_ptr) +#define CRAU_BLOB_DATA(context, key_ptr, value_ptr, value_size) +#define CRAU_WORD(key_ptr, value_ptr) +#define CRAU_STRING(key_ptr, value_ptr) +#define CRAU_BLOB(key_ptr, value_ptr, value_size) +#define CRAU_DATA(context, array_ptr, array_size) +#define CRAU_DATAV(context, ...) +#define CRAU_NEW_CONTEXT_WITH_DATA(context, parent, array_ptr, array_size) +#define CRAU_NEW_CONTEXT_WITH_DATAV(context, parent, ...) + +#endif /* ENABLE_CRYPTO_AUDITING */ + +#endif /* CRAU_MACROS_H */ From 79191d68f272be8dc99cfc945a7ba3f5e4ff33fb Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 22:01:48 +0900 Subject: [PATCH 03/37] =?UTF-8?q?README.md:=20some=5Ffunction=20=E2=86=92?= =?UTF-8?q?=20this=5Ffunction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daiki Ueno --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d82c55..9aa0277 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ application itself. ```c crau_new_context_with_data( - (crau_context_t)some_function, + (crau_context_t)this_function, CRAU_DATA_TYPE_STRING, "name", "pk::sign") ... crau_data( From 8881185b9cbf06451714910454bc0bf69030bee7 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 22:19:51 +0900 Subject: [PATCH 04/37] README.md: Mention low-level macro usage Signed-off-by: Daiki Ueno --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 9aa0277..3e2054f 100644 --- a/README.md +++ b/README.md @@ -19,19 +19,48 @@ application itself. or `macros.h` for the documentation: ```c +/* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( (crau_context_t)this_function, CRAU_DATA_TYPE_STRING, "name", "pk::sign") ... +/* Signing algorithm and bits are known at this point */ crau_data( CRAU_DATA_TYPE_STRING, "pk::algorithm", "mldsa", CRAU_DATA_TYPE_WORD, "pk::bits", 1952 * 8) +/* Do the operation */ sig = mldsa_sign(...); +/* Pop the operation context */ crau_pop_context(); ``` +## Low level macros + +Instead of using those helper functions (`crau_*`), it is also +possible to directly instrument the library with `CRAU_` macros +defined in `macros.h`: + +```c +/* Public key signing operation starts (but the algorithm is not known yet) */ +CRAU_NEW_CONTEXT_WITH_DATAV( + (crau_context_t)this_function, + (crau_context_t)parent_function, + CRAU_STRING_DATA("name", "pk::sign")); +... +/* Signing algorithm and bits are known at this point */ +CRAU_DATAV( + (crau_context_t)this_function, + CRAU_STRING_DATA("pk::algorithm", "mldsa"), + CRAU_WORD_DATA("pk::bits", 1952 * 8)) + +/* Do the operation */ +sig = mldsa_sign(...); +``` + +Note that those macros don't manage context management. + ## License MIT From 7069f87dd326b525d0ed83f84da6345305024e0c Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 22:29:36 +0900 Subject: [PATCH 05/37] crau.c: Fix unterminated #ifdef Signed-off-by: Daiki Ueno --- crau.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crau.c b/crau.c index 78ff451..2847c41 100644 --- a/crau.c +++ b/crau.c @@ -47,6 +47,7 @@ # define CRAU_THREAD_LOCAL __thread # else # error "thread_local support required" +# endif #endif /* CRAU_THREAD_LOCAL */ #ifndef CRAU_MAYBE_UNUSED From 39d01a453137a6cf7d37f0910e0e507225f2a758 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 22:45:13 +0900 Subject: [PATCH 06/37] crau.h: Clarify the scope of crau_context_t Signed-off-by: Daiki Ueno --- crau.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crau.h b/crau.h index f76733b..b0f3515 100644 --- a/crau.h +++ b/crau.h @@ -13,7 +13,8 @@ #include /* An opaque type that represents a context (e.g., TLS handshake) - * where crypto-auditing events occur. + * where crypto-auditing events occur. This should be a unique + * identifier within a thread. */ typedef uint64_t crau_context_t; From 4e4df74674a39d50f546afb36c634ab15840a256 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 17 Sep 2025 23:34:09 +0900 Subject: [PATCH 07/37] crau.c: Move CRAU_MAYBE_UNUSED definition right before the usage Signed-off-by: Daiki Ueno --- crau.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crau.c b/crau.c index 2847c41..25a611f 100644 --- a/crau.c +++ b/crau.c @@ -50,15 +50,6 @@ # endif #endif /* CRAU_THREAD_LOCAL */ -#ifndef CRAU_MAYBE_UNUSED -# if defined(__has_c_attribute) && \ - __has_c_attribute (__maybe_unused__) -# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] -# elif defined(__GNUC__) -# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) -# endif -#endif /* CRAU_MAYBE_UNUSED */ - static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { 0, }; @@ -144,6 +135,15 @@ void crau_data(...) #else +#ifndef CRAU_MAYBE_UNUSED +# if defined(__has_c_attribute) && \ + __has_c_attribute (__maybe_unused__) +# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] +# elif defined(__GNUC__) +# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) +# endif +#endif /* CRAU_MAYBE_UNUSED */ + void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) { } From 45a2792dfebedcdf0fc9aa8551484c424006fbf5 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 19 Sep 2025 15:13:35 +0900 Subject: [PATCH 08/37] README.md: Fix typo Signed-off-by: Daiki Ueno --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e2054f..ec3327f 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ CRAU_DATAV( sig = mldsa_sign(...); ``` -Note that those macros don't manage context management. +Note that those macros don't do context management. ## License From 4e3c5b10718143699088864ceaa91d4b1a63cd9b Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 23 Sep 2025 21:14:44 +0900 Subject: [PATCH 09/37] Infer current context from the call frame Signed-off-by: Daiki Ueno --- crau.c | 18 ++++++++++++++++-- crau.h | 3 +-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/crau.c b/crau.c index 25a611f..40aa6fb 100644 --- a/crau.c +++ b/crau.c @@ -12,6 +12,9 @@ * * CRAU_CONTEXT_STACK_DEPTH: depth of the thread-local context stack * (default: 3) * + * * CRAU_RETURN_ADDRESS: return address of the current function + * (default: auto-detected) + * * * CRAU_THREAD_LOCAL: thread-local modifier of the C language * (default: auto-detected) * @@ -50,6 +53,16 @@ # endif #endif /* CRAU_THREAD_LOCAL */ +#ifndef CRAU_RETURN_ADDRESS +# ifdef __GNUC__ +# define CRAU_RETURN_ADDRESS __builtin_return_address(0) +# elif defined(__CC_ARM) +# define CRAU_RETURN_ADDRESS __return_address() +# else +# error "__builtin_return_address support is required" +# endif +#endif /* CRAU_RETURN_ADDRESS */ + static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { 0, }; @@ -105,8 +118,9 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], return count; } -void crau_new_context_with_data(crau_context_t context, ...) +void crau_new_context_with_data(...) { + crau_context_t context = CRAU_RETURN_ADDRESS; struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; size_t count; va_list ap; @@ -158,7 +172,7 @@ crau_context_t crau_current_context(void) return ~0UL; } -void crau_new_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) +void crau_new_context_with_data(...) { } diff --git a/crau.h b/crau.h index b0f3515..d8d7a98 100644 --- a/crau.h +++ b/crau.h @@ -47,14 +47,13 @@ crau_context_t crau_current_context(void); * is as follows: * * crau_new_context_with_data( - * (crau_context_t)some_function, * CRAU_DATA_TYPE_STRING, "name", "pk::sign", * CRAU_DATA_TYPE_STRING, "pk::algorithm", "mldsa", * CRAU_DATA_TYPE_WORD, "pk::bits", 1952 * 8) * * This call must be followed by a `crau_pop_context`. */ -void crau_new_context_with_data(crau_context_t context, ...); +void crau_new_context_with_data(...); /* Emit events through varargs. */ From 8b62f417a5ffcbbb6f2975cbbbdbfc065b14fd20 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 23 Sep 2025 21:16:12 +0900 Subject: [PATCH 10/37] README.md: Remove context argument from crau_new_context_with_data Signed-off-by: Daiki Ueno --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ec3327f..4829a74 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ application itself. ```c /* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( - (crau_context_t)this_function, CRAU_DATA_TYPE_STRING, "name", "pk::sign") ... /* Signing algorithm and bits are known at this point */ From 50d43d62de831ab8baf9be5ab132677415e46e34 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 23 Sep 2025 21:18:12 +0900 Subject: [PATCH 11/37] Suggest defining configuration macros upon error Signed-off-by: Daiki Ueno --- crau.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crau.c b/crau.c index 40aa6fb..42b35b5 100644 --- a/crau.c +++ b/crau.c @@ -49,7 +49,7 @@ # elif defined(__GNUC__) # define CRAU_THREAD_LOCAL __thread # else -# error "thread_local support required" +# error "thread_local support is required; define CRAU_THREAD_LOCAL" # endif #endif /* CRAU_THREAD_LOCAL */ @@ -59,7 +59,7 @@ # elif defined(__CC_ARM) # define CRAU_RETURN_ADDRESS __return_address() # else -# error "__builtin_return_address support is required" +# error "__builtin_return_address support is required; define CRAU_RETURN_ADDRESS" # endif #endif /* CRAU_RETURN_ADDRESS */ From 330c5f2234d461b77081adeaecd1c15e8509aa86 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 23 Sep 2025 22:17:13 +0900 Subject: [PATCH 12/37] Update doc comments Signed-off-by: Daiki Ueno --- crau.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crau.h b/crau.h index d8d7a98..0e62059 100644 --- a/crau.h +++ b/crau.h @@ -29,7 +29,9 @@ enum crau_data_type_t { CRAU_DATA_TYPE_BLOB, }; -/* Push a new context CONTEXT onto the thread-local context stack. +/* Push a context CONTEXT onto the thread-local context stack. + * + * This call must be followed by a `crau_pop_context`. */ void crau_push_context(crau_context_t context); @@ -42,9 +44,9 @@ crau_context_t crau_pop_context(void); */ crau_context_t crau_current_context(void); -/* Push a new context CONTEXT onto the thread-local context stack, - * optionally emitting events through varargs. Typical usage example - * is as follows: +/* Push a new context (inferred from the call frame) onto the + * thread-local context stack, optionally emitting events through + * varargs. Typical usage example is as follows: * * crau_new_context_with_data( * CRAU_DATA_TYPE_STRING, "name", "pk::sign", From 183bd9d1dc62f31eb7e0e4fac8e7f9ad33341a8a Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 07:54:10 +0900 Subject: [PATCH 13/37] Swap the order of key_ptr and value type Signed-off-by: Daiki Ueno --- README.md | 8 +++++--- crau.c | 7 ++++--- crau.h | 7 ++++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4829a74..8218eff 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,14 @@ application itself. ```c /* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( - CRAU_DATA_TYPE_STRING, "name", "pk::sign") + "name", CRAU_DATA_TYPE_STRING, "pk::sign", + NULL) ... /* Signing algorithm and bits are known at this point */ crau_data( - CRAU_DATA_TYPE_STRING, "pk::algorithm", "mldsa", - CRAU_DATA_TYPE_WORD, "pk::bits", 1952 * 8) + "pk::algorithm", CRAU_DATA_TYPE_STRING, "mldsa", + "pk::bits", CRAU_DATA_TYPE_WORD, 1952 * 8, + NULL) /* Do the operation */ sig = mldsa_sign(...); diff --git a/crau.c b/crau.c index 42b35b5..4ad28a4 100644 --- a/crau.c +++ b/crau.c @@ -94,20 +94,21 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], size_t count = 0; for (; count < CRAU_MAX_DATA_ELEMS;) { + data[count].key_ptr = va_arg(ap, char *); + if (data[count].key_ptr == NULL) + break; + switch (va_arg(ap, enum crau_data_type_t)) { case CRAU_DATA_TYPE_WORD: - data[count].key_ptr = va_arg(ap, char *); data[count].value_ptr = (void *)va_arg(ap, intptr_t); data[count].value_size = (unsigned long)-2; count++; break; case CRAU_DATA_TYPE_STRING: - data[count].key_ptr = va_arg(ap, char *); data[count].value_ptr = (void *)va_arg(ap, char *); data[count].value_size = (unsigned long)-1; break; case CRAU_DATA_TYPE_BLOB: - data[count].key_ptr = va_arg(ap, char *); data[count].value_ptr = va_arg(ap, void *); data[count].value_size = va_arg(ap, unsigned long); count++; diff --git a/crau.h b/crau.h index 0e62059..6a06d47 100644 --- a/crau.h +++ b/crau.h @@ -49,9 +49,10 @@ crau_context_t crau_current_context(void); * varargs. Typical usage example is as follows: * * crau_new_context_with_data( - * CRAU_DATA_TYPE_STRING, "name", "pk::sign", - * CRAU_DATA_TYPE_STRING, "pk::algorithm", "mldsa", - * CRAU_DATA_TYPE_WORD, "pk::bits", 1952 * 8) + * "name", CRAU_DATA_TYPE_STRING, "pk::sign", + * "pk::algorithm", CRAU_DATA_TYPE_STRING, "mldsa", + * "pk::bits", CRAU_DATA_TYPE_WORD, 1952 * 8, + * NULL) * * This call must be followed by a `crau_pop_context`. */ From 4b0d0db1ce01efaf2bd1025fa9026cac7923cc0b Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 08:23:25 +0900 Subject: [PATCH 14/37] Don't include "macros.h" in "crau.h" This allows to shorten the names of the enum members. Signed-off-by: Daiki Ueno --- README.md | 6 +++--- crau.c | 7 +++++++ crau.h | 26 +++++++++++++------------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 8218eff..73caa27 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,13 @@ application itself. ```c /* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( - "name", CRAU_DATA_TYPE_STRING, "pk::sign", + "name", CRAU_STRING, "pk::sign", NULL) ... /* Signing algorithm and bits are known at this point */ crau_data( - "pk::algorithm", CRAU_DATA_TYPE_STRING, "mldsa", - "pk::bits", CRAU_DATA_TYPE_WORD, 1952 * 8, + "pk::algorithm", CRAU_STRING, "mldsa", + "pk::bits", CRAU_WORD, 1952 * 8, NULL) /* Do the operation */ diff --git a/crau.c b/crau.c index 4ad28a4..777b5c2 100644 --- a/crau.c +++ b/crau.c @@ -29,6 +29,13 @@ #include "crau.h" +#include "macros.h" + +/* Avoid name clash with crau_data_type_t */ +#undef CRAU_DATA +#undef CRAU_STRING +#undef CRAU_BLOB + #include #include #include diff --git a/crau.h b/crau.h index 6a06d47..dedb3a5 100644 --- a/crau.h +++ b/crau.h @@ -9,7 +9,6 @@ #ifndef CRAU_CRAU_H #define CRAU_CRAU_H -#include "macros.h" #include /* An opaque type that represents a context (e.g., TLS handshake) @@ -18,15 +17,14 @@ */ typedef uint64_t crau_context_t; -/* Types of crypto-auditing event data. CRAU_DATA_TYPE_WORD means an - * integer in a machine word, CRAU_DATA_TYPESTRING means a - * NUL-terminated string. CRAU_DATA_TYPE_BLOB means an explicitly - * sized binary blob. +/* Types of crypto-auditing event data. CRAU_WORD means an integer in + * a machine word, CRAU_STRING means a NUL-terminated + * string. CRAU_BLOB means an explicitly sized binary blob. */ enum crau_data_type_t { - CRAU_DATA_TYPE_WORD, - CRAU_DATA_TYPE_STRING, - CRAU_DATA_TYPE_BLOB, + CRAU_WORD, + CRAU_STRING, + CRAU_BLOB, }; /* Push a context CONTEXT onto the thread-local context stack. @@ -49,16 +47,18 @@ crau_context_t crau_current_context(void); * varargs. Typical usage example is as follows: * * crau_new_context_with_data( - * "name", CRAU_DATA_TYPE_STRING, "pk::sign", - * "pk::algorithm", CRAU_DATA_TYPE_STRING, "mldsa", - * "pk::bits", CRAU_DATA_TYPE_WORD, 1952 * 8, - * NULL) + * "name", CRAU_STRING, "pk::sign", + * "pk::algorithm", CRAU_STRING, "mldsa", + * "pk::bits", CRAU_WORD, 1952 * 8, + * NULL); * * This call must be followed by a `crau_pop_context`. */ void crau_new_context_with_data(...); -/* Emit events through varargs. +/* Emit events through varargs, under the current thread-local + context. Unlike `crau_new_context_with_data`, this does not push a + new context. */ void crau_data(...); From 5db19f2ef9e814158534ccdf40a7f6dec06b4df5 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 09:51:49 +0900 Subject: [PATCH 15/37] Fix the previous commit Signed-off-by: Daiki Ueno --- crau.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crau.c b/crau.c index 777b5c2..df7386b 100644 --- a/crau.c +++ b/crau.c @@ -24,7 +24,7 @@ */ #ifdef HAVE_CONFIG_H -#include +#include "config.h" #endif #include "crau.h" @@ -106,16 +106,16 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], break; switch (va_arg(ap, enum crau_data_type_t)) { - case CRAU_DATA_TYPE_WORD: + case CRAU_WORD: data[count].value_ptr = (void *)va_arg(ap, intptr_t); data[count].value_size = (unsigned long)-2; count++; break; - case CRAU_DATA_TYPE_STRING: + case CRAU_STRING: data[count].value_ptr = (void *)va_arg(ap, char *); data[count].value_size = (unsigned long)-1; break; - case CRAU_DATA_TYPE_BLOB: + case CRAU_BLOB: data[count].value_ptr = va_arg(ap, void *); data[count].value_size = va_arg(ap, unsigned long); count++; From dd8eeed86d0cc661c51488e9db34a7af54a7b7b0 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 09:54:32 +0900 Subject: [PATCH 16/37] Fix macro naming Signed-off-by: Daiki Ueno --- crau.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crau.c b/crau.c index df7386b..4df3e2b 100644 --- a/crau.c +++ b/crau.c @@ -32,7 +32,7 @@ #include "macros.h" /* Avoid name clash with crau_data_type_t */ -#undef CRAU_DATA +#undef CRAU_WORD #undef CRAU_STRING #undef CRAU_BLOB @@ -62,9 +62,9 @@ #ifndef CRAU_RETURN_ADDRESS # ifdef __GNUC__ -# define CRAU_RETURN_ADDRESS __builtin_return_address(0) +# define CRAU_RETURN_ADDRESS (crau_context_t)__builtin_return_address(0) # elif defined(__CC_ARM) -# define CRAU_RETURN_ADDRESS __return_address() +# define CRAU_RETURN_ADDRESS (crau_context_t)__return_address() # else # error "__builtin_return_address support is required; define CRAU_RETURN_ADDRESS" # endif From 24d0c45e47744c4a0ff46000052a925f327657c1 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 11:44:07 +0900 Subject: [PATCH 17/37] Don't use Instead, just use a bogus context value in the error case. Signed-off-by: Daiki Ueno --- crau.c | 32 +++++++------------------------- crau.h | 28 ++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/crau.c b/crau.c index 4df3e2b..6c9624d 100644 --- a/crau.c +++ b/crau.c @@ -17,10 +17,6 @@ * * * CRAU_THREAD_LOCAL: thread-local modifier of the C language * (default: auto-detected) - * - * * CRAU_MAYBE_UNUSED: an attribute to suppress warnings when a - * function argument is not used in the function body (default: - * auto-detected) */ #ifdef HAVE_CONFIG_H @@ -36,7 +32,6 @@ #undef CRAU_STRING #undef CRAU_BLOB -#include #include #include @@ -75,23 +70,19 @@ static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] }; static CRAU_THREAD_LOCAL size_t context_stack_top = 0; -void crau_push_context(crau_context_t context) +void crau_push_context(void) { - assert(context_stack_top < CRAU_CONTEXT_STACK_DEPTH); - context_stack[context_stack_top++] = context; + context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = CRAU_RETURN_ADDRESS; } crau_context_t crau_pop_context(void) { - assert(context_stack_top > 0); - return context_stack[--context_stack_top]; + return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[--context_stack_top]; } crau_context_t crau_current_context(void) { - if (context_stack_top == 0) - return ~0UL; - return context_stack[context_stack_top - 1]; + return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[context_stack_top - 1]; } static inline size_t @@ -157,27 +148,18 @@ void crau_data(...) #else -#ifndef CRAU_MAYBE_UNUSED -# if defined(__has_c_attribute) && \ - __has_c_attribute (__maybe_unused__) -# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] -# elif defined(__GNUC__) -# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) -# endif -#endif /* CRAU_MAYBE_UNUSED */ - -void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) +void crau_push_context(void) { } crau_context_t crau_pop_context(void) { - return ~0UL; + return CRAU_ORPHANED_CONTEXT; } crau_context_t crau_current_context(void) { - return ~0UL; + return CRAU_ORPHANED_CONTEXT; } void crau_new_context_with_data(...) diff --git a/crau.h b/crau.h index dedb3a5..b2b0cca 100644 --- a/crau.h +++ b/crau.h @@ -17,6 +17,11 @@ */ typedef uint64_t crau_context_t; +/* A special context value used to represent a context which is not + * associated with any parent nor children. + */ +#define CRAU_ORPHANED_CONTEXT ((crau_context_t)-1) + /* Types of crypto-auditing event data. CRAU_WORD means an integer in * a machine word, CRAU_STRING means a NUL-terminated * string. CRAU_BLOB means an explicitly sized binary blob. @@ -27,24 +32,29 @@ enum crau_data_type_t { CRAU_BLOB, }; -/* Push a context CONTEXT onto the thread-local context stack. +/* Push a context (inferred from the call frame) onto the thread-local + * context stack. If the depth of the stack exceeds + * CRAU_CONTEXT_STACK_DEPTH, the older element will be removed. * - * This call must be followed by a `crau_pop_context`. + * This call shall be followed by a `crau_pop_context`. */ -void crau_push_context(crau_context_t context); +void crau_push_context(void); -/* Pop a context from the thread-local context stack. The stack must - * not be empty. +/* Pop a context from the thread-local context stack. If the stack + * is empty, it returns a CRAU_ORPHANED_CONTEXT. */ crau_context_t crau_pop_context(void); -/* Return the context currently active for this thread. +/* Return the context currently active for this thread. If there is no + * active context, it returns a CRAU_ORPHANED_CONTEXT. */ crau_context_t crau_current_context(void); /* Push a new context (inferred from the call frame) onto the * thread-local context stack, optionally emitting events through - * varargs. Typical usage example is as follows: + * varargs. + * + * Typical usage example is as follows: * * crau_new_context_with_data( * "name", CRAU_STRING, "pk::sign", @@ -52,7 +62,9 @@ crau_context_t crau_current_context(void); * "pk::bits", CRAU_WORD, 1952 * 8, * NULL); * - * This call must be followed by a `crau_pop_context`. + * If the depth of the stack exceeds CRAU_CONTEXT_STACK_DEPTH, the + * older element will be removed. This call shall be followed by a + * `crau_pop_context`. */ void crau_new_context_with_data(...); From 913dee99c5837d293332ad4c91c7e58c55f2ab59 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 17:18:45 +0900 Subject: [PATCH 18/37] macros: Fix typo Signed-off-by: Daiki Ueno --- macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macros.h b/macros.h index c344ea5..7b69a79 100644 --- a/macros.h +++ b/macros.h @@ -48,7 +48,7 @@ * The VALUE_SIZE field is set depending on the type of the value. If * the value is a machine word, it is set to 0xfffffffe (= -2). If * the value is a NUL-terminated string, it is set to 0xffffffff (= - * -1). Otherwise, it it set to the actual size of the value. + * -1). Otherwise, it is set to the actual size of the value. */ struct crypto_auditing_data { char *key_ptr; From 7730a6ab75dd912693ff67302fb0e5594e9e23a7 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 17:19:58 +0900 Subject: [PATCH 19/37] Add CRAU_AUTO_CONTEXT and embed it as an argument Otherwise, we can't create a new context based on the caller's return address. Signed-off-by: Daiki Ueno --- README.md | 1 + crau.c | 56 ++++++++++++++++++++++++++++--------------------------- crau.h | 31 +++++++++++++++++++++--------- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 73caa27..23ef8ca 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ application itself. ```c /* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( + CRAU_AUTO_CONTEXT, "name", CRAU_STRING, "pk::sign", NULL) ... diff --git a/crau.c b/crau.c index 6c9624d..80a3fff 100644 --- a/crau.c +++ b/crau.c @@ -17,6 +17,10 @@ * * * CRAU_THREAD_LOCAL: thread-local modifier of the C language * (default: auto-detected) + * + * * CRAU_MAYBE_UNUSED: an attribute to suppress warnings when a + * function argument is not used in the function body (default: + * auto-detected) */ #ifdef HAVE_CONFIG_H @@ -55,24 +59,14 @@ # endif #endif /* CRAU_THREAD_LOCAL */ -#ifndef CRAU_RETURN_ADDRESS -# ifdef __GNUC__ -# define CRAU_RETURN_ADDRESS (crau_context_t)__builtin_return_address(0) -# elif defined(__CC_ARM) -# define CRAU_RETURN_ADDRESS (crau_context_t)__return_address() -# else -# error "__builtin_return_address support is required; define CRAU_RETURN_ADDRESS" -# endif -#endif /* CRAU_RETURN_ADDRESS */ - static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { 0, }; static CRAU_THREAD_LOCAL size_t context_stack_top = 0; -void crau_push_context(void) +void crau_push_context(crau_context_t context) { - context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = CRAU_RETURN_ADDRESS; + context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = context; } crau_context_t crau_pop_context(void) @@ -87,14 +81,14 @@ crau_context_t crau_current_context(void) static inline size_t accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], - va_list ap) + va_list ap, + char *key_ptr) { size_t count = 0; - for (; count < CRAU_MAX_DATA_ELEMS;) { - data[count].key_ptr = va_arg(ap, char *); - if (data[count].key_ptr == NULL) - break; + for (; key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; + key_ptr = va_arg(ap, char *)) { + data[count].key_ptr = key_ptr; switch (va_arg(ap, enum crau_data_type_t)) { case CRAU_WORD: @@ -117,15 +111,14 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], return count; } -void crau_new_context_with_data(...) +void crau_new_context_with_data(crau_context_t context, ...) { - crau_context_t context = CRAU_RETURN_ADDRESS; struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; size_t count; va_list ap; - va_start(ap); - count = accumulate_datav(data, ap); + va_start(ap, context); + count = accumulate_datav(data, ap, va_arg(ap, char *)); va_end(ap); CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, @@ -133,14 +126,14 @@ void crau_new_context_with_data(...) crau_push_context(context); } -void crau_data(...) +void crau_data(char *first_key_ptr, ...) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; size_t count; va_list ap; - va_start(ap); - count = accumulate_datav(data, ap); + va_start(ap, first_key_ptr); + count = accumulate_datav(data, ap, first_key_ptr); va_end(ap); CRAU_DATA(crau_current_context(), data, count); @@ -148,7 +141,16 @@ void crau_data(...) #else -void crau_push_context(void) +#ifndef CRAU_MAYBE_UNUSED +# if defined(__has_c_attribute) && \ + __has_c_attribute (__maybe_unused__) +# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] +# elif defined(__GNUC__) +# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) +# endif +#endif /* CRAU_MAYBE_UNUSED */ + +void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) { } @@ -162,11 +164,11 @@ crau_context_t crau_current_context(void) return CRAU_ORPHANED_CONTEXT; } -void crau_new_context_with_data(...) +void crau_new_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) { } -void crau_data(...) +void crau_data(char *first_key_ptr CRAU_MAYBE_UNUSED, ...) { } diff --git a/crau.h b/crau.h index b2b0cca..2392999 100644 --- a/crau.h +++ b/crau.h @@ -17,6 +17,19 @@ */ typedef uint64_t crau_context_t; +/* A special context value used to represent a context which is not + * associated with any parent nor children. + */ +#ifndef CRAU_AUTO_CONTEXT +# ifdef __GNUC__ +# define CRAU_AUTO_CONTEXT (crau_context_t)__builtin_return_address(0) +# elif defined(__CC_ARM) +# define CRAU_AUTO_CONTEXT (crau_context_t)__return_address() +# else +# define CRAU_AUTO_CONTEXT CRAU_ORPHANED_CONTEXT +# endif +#endif /* CRAU_AUTO_CONTEXT */ + /* A special context value used to represent a context which is not * associated with any parent nor children. */ @@ -32,13 +45,13 @@ enum crau_data_type_t { CRAU_BLOB, }; -/* Push a context (inferred from the call frame) onto the thread-local +/* Push a context CONTEXT onto the thread-local * context stack. If the depth of the stack exceeds * CRAU_CONTEXT_STACK_DEPTH, the older element will be removed. * * This call shall be followed by a `crau_pop_context`. */ -void crau_push_context(void); +void crau_push_context(crau_context_t context); /* Pop a context from the thread-local context stack. If the stack * is empty, it returns a CRAU_ORPHANED_CONTEXT. @@ -50,13 +63,13 @@ crau_context_t crau_pop_context(void); */ crau_context_t crau_current_context(void); -/* Push a new context (inferred from the call frame) onto the - * thread-local context stack, optionally emitting events through - * varargs. +/* Push a new context CONTEXT onto the thread-local context stack, + * optionally emitting events through varargs. * * Typical usage example is as follows: * * crau_new_context_with_data( + * CRAU_AUTO_CONTEXT, * "name", CRAU_STRING, "pk::sign", * "pk::algorithm", CRAU_STRING, "mldsa", * "pk::bits", CRAU_WORD, 1952 * 8, @@ -66,12 +79,12 @@ crau_context_t crau_current_context(void); * older element will be removed. This call shall be followed by a * `crau_pop_context`. */ -void crau_new_context_with_data(...); +void crau_new_context_with_data(crau_context_t context, ...); /* Emit events through varargs, under the current thread-local - context. Unlike `crau_new_context_with_data`, this does not push a - new context. + * context. Unlike `crau_new_context_with_data`, this does not push a + * new context. */ -void crau_data(...); +void crau_data(char *first_key_ptr, ...); #endif /* CRAU_CRAU_H */ From 74ae38196afdb43db80809a1b99458378bd4b6b3 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 17:20:58 +0900 Subject: [PATCH 20/37] .dir-locals.el: Add indentation for Emacs Signed-off-by: Daiki Ueno --- .dir-locals.el | 1 + 1 file changed, 1 insertion(+) create mode 100644 .dir-locals.el diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..042381f --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1 @@ +((c-mode . ((c-file-style . "linux")))) From 5d8b84e7c1b67a6514dbaa4505ec3aca0abe5b2a Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 17:51:47 +0900 Subject: [PATCH 21/37] Define crau_new_context_with_data as a wrapper macro Signed-off-by: Daiki Ueno --- crau.c | 14 ++++++++++---- crau.h | 16 +++++++++++++--- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/crau.c b/crau.c index 80a3fff..ecc68cb 100644 --- a/crau.c +++ b/crau.c @@ -64,11 +64,17 @@ static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] }; static CRAU_THREAD_LOCAL size_t context_stack_top = 0; -void crau_push_context(crau_context_t context) +static inline void push_context(crau_context_t context) { context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = context; } +void crau_push_context(crau_context_t context) +{ + CRAU_NEW_CONTEXT(context, crau_current_context()); + push_context(context); +} + crau_context_t crau_pop_context(void) { return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[--context_stack_top]; @@ -111,7 +117,7 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], return count; } -void crau_new_context_with_data(crau_context_t context, ...) +void crau_push_context_with_data(crau_context_t context, ...) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; size_t count; @@ -123,7 +129,7 @@ void crau_new_context_with_data(crau_context_t context, ...) CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, count); - crau_push_context(context); + push_context(context); } void crau_data(char *first_key_ptr, ...) @@ -164,7 +170,7 @@ crau_context_t crau_current_context(void) return CRAU_ORPHANED_CONTEXT; } -void crau_new_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) +void crau_push_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) { } diff --git a/crau.h b/crau.h index 2392999..bf53241 100644 --- a/crau.h +++ b/crau.h @@ -63,13 +63,22 @@ crau_context_t crau_pop_context(void); */ crau_context_t crau_current_context(void); -/* Push a new context CONTEXT onto the thread-local context stack, +/* Push a context CONTEXT onto the thread-local context stack, * optionally emitting events through varargs. * + * If the depth of the stack exceeds CRAU_CONTEXT_STACK_DEPTH, the + * older element will be removed. This call shall be followed by a + * `crau_pop_context`. + */ +void crau_push_context_with_data(crau_context_t context, ...); + +/* Push a new context (inferred from the current call stack) onto the + * thread-local context stack, optionally emitting events through + * varargs. + * * Typical usage example is as follows: * * crau_new_context_with_data( - * CRAU_AUTO_CONTEXT, * "name", CRAU_STRING, "pk::sign", * "pk::algorithm", CRAU_STRING, "mldsa", * "pk::bits", CRAU_WORD, 1952 * 8, @@ -79,7 +88,8 @@ crau_context_t crau_current_context(void); * older element will be removed. This call shall be followed by a * `crau_pop_context`. */ -void crau_new_context_with_data(crau_context_t context, ...); +#define crau_new_context_with_data(...) \ + crau_push_context_with_data(CRAU_AUTO_CONTEXT, __VA_ARGS__) /* Emit events through varargs, under the current thread-local * context. Unlike `crau_new_context_with_data`, this does not push a From ebb0fa6ceac435be91484d3769b4dd04605353fb Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 17:58:29 +0900 Subject: [PATCH 22/37] Make first argument of crau_data as const Signed-off-by: Daiki Ueno --- README.md | 1 - crau.c | 4 ++-- crau.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 23ef8ca..73caa27 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ application itself. ```c /* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( - CRAU_AUTO_CONTEXT, "name", CRAU_STRING, "pk::sign", NULL) ... diff --git a/crau.c b/crau.c index ecc68cb..3dd14dd 100644 --- a/crau.c +++ b/crau.c @@ -132,14 +132,14 @@ void crau_push_context_with_data(crau_context_t context, ...) push_context(context); } -void crau_data(char *first_key_ptr, ...) +void crau_data(const char *first_key_ptr, ...) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; size_t count; va_list ap; va_start(ap, first_key_ptr); - count = accumulate_datav(data, ap, first_key_ptr); + count = accumulate_datav(data, ap, (char *)first_key_ptr); va_end(ap); CRAU_DATA(crau_current_context(), data, count); diff --git a/crau.h b/crau.h index bf53241..4d9fe44 100644 --- a/crau.h +++ b/crau.h @@ -95,6 +95,6 @@ void crau_push_context_with_data(crau_context_t context, ...); * context. Unlike `crau_new_context_with_data`, this does not push a * new context. */ -void crau_data(char *first_key_ptr, ...); +void crau_data(const char *first_key_ptr, ...); #endif /* CRAU_CRAU_H */ From 4df495e123b86654684d05638093cef61f482034 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Sep 2025 18:27:32 +0900 Subject: [PATCH 23/37] Pacify -Wbad-function-cast Signed-off-by: Daiki Ueno --- crau.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crau.h b/crau.h index 4d9fe44..56eac8b 100644 --- a/crau.h +++ b/crau.h @@ -22,9 +22,9 @@ typedef uint64_t crau_context_t; */ #ifndef CRAU_AUTO_CONTEXT # ifdef __GNUC__ -# define CRAU_AUTO_CONTEXT (crau_context_t)__builtin_return_address(0) +# define CRAU_AUTO_CONTEXT (crau_context_t)(uintptr_t)(char *)__builtin_return_address(0) # elif defined(__CC_ARM) -# define CRAU_AUTO_CONTEXT (crau_context_t)__return_address() +# define CRAU_AUTO_CONTEXT (crau_context_t)(uintptr_t)(char *)__return_address() # else # define CRAU_AUTO_CONTEXT CRAU_ORPHANED_CONTEXT # endif From ad8daeeef98d254aaf42880c71783a697abacabf Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Thu, 25 Sep 2025 10:53:55 +0900 Subject: [PATCH 24/37] Fix element counting in accumulate_datav Signed-off-by: Daiki Ueno --- crau.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crau.c b/crau.c index 3dd14dd..ecd380f 100644 --- a/crau.c +++ b/crau.c @@ -93,14 +93,13 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], size_t count = 0; for (; key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; - key_ptr = va_arg(ap, char *)) { + key_ptr = va_arg(ap, char *), count++) { data[count].key_ptr = key_ptr; switch (va_arg(ap, enum crau_data_type_t)) { case CRAU_WORD: data[count].value_ptr = (void *)va_arg(ap, intptr_t); data[count].value_size = (unsigned long)-2; - count++; break; case CRAU_STRING: data[count].value_ptr = (void *)va_arg(ap, char *); @@ -109,7 +108,6 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], case CRAU_BLOB: data[count].value_ptr = va_arg(ap, void *); data[count].value_size = va_arg(ap, unsigned long); - count++; break; } } From 61fe880072bf2648363c7116eba31beea569051c Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 30 Sep 2025 13:31:12 +0900 Subject: [PATCH 25/37] Fix doc comment of CRAU_AUTO_CONTEXT Signed-off-by: Daiki Ueno --- crau.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crau.h b/crau.h index 56eac8b..2c692cf 100644 --- a/crau.h +++ b/crau.h @@ -17,8 +17,8 @@ */ typedef uint64_t crau_context_t; -/* A special context value used to represent a context which is not - * associated with any parent nor children. +/* A special context value used to represent a context which is + * automatically assigned based on the current call frame. */ #ifndef CRAU_AUTO_CONTEXT # ifdef __GNUC__ @@ -45,16 +45,16 @@ enum crau_data_type_t { CRAU_BLOB, }; -/* Push a context CONTEXT onto the thread-local - * context stack. If the depth of the stack exceeds - * CRAU_CONTEXT_STACK_DEPTH, the older element will be removed. +/* Push a context CONTEXT onto the thread-local context stack. If the + * depth of the stack exceeds CRAU_CONTEXT_STACK_DEPTH, the older + * element will be removed. * * This call shall be followed by a `crau_pop_context`. */ void crau_push_context(crau_context_t context); -/* Pop a context from the thread-local context stack. If the stack - * is empty, it returns a CRAU_ORPHANED_CONTEXT. +/* Pop a context from the thread-local context stack. If the stack is + * empty, it returns a CRAU_ORPHANED_CONTEXT. */ crau_context_t crau_pop_context(void); From b64ad5ae7376a1494db9ae03a60371f5a4f0e6aa Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 30 Sep 2025 18:30:51 +0900 Subject: [PATCH 26/37] Fix type confusion between crau.h and BPF program Signed-off-by: Daiki Ueno --- crau.c | 6 +++--- crau.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crau.c b/crau.c index ecd380f..90dc498 100644 --- a/crau.c +++ b/crau.c @@ -85,12 +85,12 @@ crau_context_t crau_current_context(void) return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[context_stack_top - 1]; } -static inline size_t +static inline unsigned long accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], va_list ap, char *key_ptr) { - size_t count = 0; + unsigned long count = 0; for (; key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; key_ptr = va_arg(ap, char *), count++) { @@ -118,7 +118,7 @@ accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], void crau_push_context_with_data(crau_context_t context, ...) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; - size_t count; + unsigned long count; va_list ap; va_start(ap, context); diff --git a/crau.h b/crau.h index 2c692cf..53860ee 100644 --- a/crau.h +++ b/crau.h @@ -15,16 +15,16 @@ * where crypto-auditing events occur. This should be a unique * identifier within a thread. */ -typedef uint64_t crau_context_t; +typedef long crau_context_t; /* A special context value used to represent a context which is * automatically assigned based on the current call frame. */ #ifndef CRAU_AUTO_CONTEXT # ifdef __GNUC__ -# define CRAU_AUTO_CONTEXT (crau_context_t)(uintptr_t)(char *)__builtin_return_address(0) +# define CRAU_AUTO_CONTEXT (crau_context_t)(intptr_t)(char *)__builtin_return_address(0) # elif defined(__CC_ARM) -# define CRAU_AUTO_CONTEXT (crau_context_t)(uintptr_t)(char *)__return_address() +# define CRAU_AUTO_CONTEXT (crau_context_t)(intptr_t)(char *)__return_address() # else # define CRAU_AUTO_CONTEXT CRAU_ORPHANED_CONTEXT # endif From 41b52e3140bdbc9eaa6250e879e7bdbf34abd84e Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 6 Oct 2025 16:22:04 +0900 Subject: [PATCH 27/37] Make it header-only and relicense as MIT OR Unlicense Signed-off-by: Daiki Ueno --- README.md | 17 ++--- UNLICENSE | 24 +++++++ crau.h | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++- macros.h | 4 +- 4 files changed, 217 insertions(+), 10 deletions(-) create mode 100644 UNLICENSE diff --git a/README.md b/README.md index 73caa27..d521935 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,17 @@ application itself. ## Getting started -1. Copy all source files (`crau.h`, `crau.c`, and `macros.h`) to your - application and add them to the build infrastructure (e.g., Makefiles). - 1. Define `ENABLE_CRYPTO_AUDITING` to 1, e.g., through `` -1. (Optional) Customize macros, e.g., `CRAU_CONTEXT_STACK_DEPTH` for - your needs. See the header of `crau.c` for the details. +1. Include ``. One of the C files should define + `CRAU_IMPLEMENTATION` to get the functions defined. + +1. (Optional) Customize the implementation with configuration macros, + e.g., `CRAU_CONTEXT_STACK_DEPTH` for your needs. See + `` for the details. -1. Include "crau.h" and instrument the code as follows. See `crau.h` - or `macros.h` for the documentation: +1. Instrument the code as follows. See `` and + `` for the documentation: ```c /* Public key signing operation starts (but the algorithm is not known yet) */ @@ -64,6 +65,6 @@ Note that those macros don't do context management. ## License -MIT +MIT or Unlicense [crypto-auditing]: https://github.com/latchset/crypto-auditing diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..efb9808 --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/crau.h b/crau.h index 53860ee..57f5eb8 100644 --- a/crau.h +++ b/crau.h @@ -1,9 +1,36 @@ -/* SPDX-License-Identifier: MIT */ +/* SPDX-License-Identifier: MIT OR Unlicense */ /* Copyright (C) 2022-2025 The crypto-auditing developers. */ /* This file declares a set of high-level functions to insert probe * points used for crypto-auditing into the application programs. See * for the low-level interface. + * + * As this is a header-only library, one of C files that includes + * this file should do: + * + * #define CRAU_IMPLEMENTATION + * #include "crau/crau.h" + * + * to get the necessary functions are defined. + * + * The following configuration macros can also be set to override the + * behavior of the implementation: + * + * * CRAU_CONTEXT_STACK_DEPTH: depth of the thread-local context stack + * (default: 3) + * + * * CRAU_RETURN_ADDRESS: return address of the current function + * (default: auto-detected) + * + * * CRAU_THREAD_LOCAL: thread-local modifier of the C language + * (default: auto-detected) + * + * * CRAU_MAYBE_UNUSED: an attribute to suppress warnings when a + * function argument is not used in the function body (default: + * auto-detected) + * + * Unless ENABLE_CRYPTO_AUDITING is defined, all functions turn to + * no-op. */ #ifndef CRAU_CRAU_H @@ -97,4 +124,157 @@ void crau_push_context_with_data(crau_context_t context, ...); */ void crau_data(const char *first_key_ptr, ...); +#ifdef CRAU_IMPLEMENTATION + +#include "macros.h" + +/* Avoid name clash with crau_data_type_t */ +#undef CRAU_WORD +#undef CRAU_STRING +#undef CRAU_BLOB + +#include +#include + +# ifdef ENABLE_CRYPTO_AUDITING + +# ifndef CRAU_CONTEXT_STACK_DEPTH +# define CRAU_CONTEXT_STACK_DEPTH 3 +# endif /* CRAU_CONTEXT_STACK_DEPTH */ + +# ifndef CRAU_THREAD_LOCAL +# ifdef thread_local +# define CRAU_THREAD_LOCAL thread_local +# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) +# define CRAU_THREAD_LOCAL _Thread_local +# elif defined(_MSC_VER) +# define CRAU_THREAD_LOCAL __declspec(thread) +# elif defined(__GNUC__) +# define CRAU_THREAD_LOCAL __thread +# else +# error "thread_local support is required; define CRAU_THREAD_LOCAL" +# endif +# endif /* CRAU_THREAD_LOCAL */ + +static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { + 0, +}; +static CRAU_THREAD_LOCAL size_t context_stack_top = 0; + +static inline void push_context(crau_context_t context) +{ + context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = context; +} + +void crau_push_context(crau_context_t context) +{ + CRAU_NEW_CONTEXT(context, crau_current_context()); + push_context(context); +} + +crau_context_t crau_pop_context(void) +{ + return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[--context_stack_top]; +} + +crau_context_t crau_current_context(void) +{ + return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[context_stack_top - 1]; +} + +static inline unsigned long +_crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], + va_list ap, + char *key_ptr) +{ + unsigned long count = 0; + + for (; key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; + key_ptr = va_arg(ap, char *), count++) { + data[count].key_ptr = key_ptr; + + switch (va_arg(ap, enum crau_data_type_t)) { + case CRAU_WORD: + data[count].value_ptr = (void *)va_arg(ap, intptr_t); + data[count].value_size = (unsigned long)-2; + break; + case CRAU_STRING: + data[count].value_ptr = (void *)va_arg(ap, char *); + data[count].value_size = (unsigned long)-1; + break; + case CRAU_BLOB: + data[count].value_ptr = va_arg(ap, void *); + data[count].value_size = va_arg(ap, unsigned long); + break; + } + } + + return count; +} + +void crau_push_context_with_data(crau_context_t context, ...) +{ + struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; + unsigned long count; + va_list ap; + + va_start(ap, context); + count = _crau_accumulate_datav(data, ap, va_arg(ap, char *)); + va_end(ap); + + CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, + count); + push_context(context); +} + +void crau_data(const char *first_key_ptr, ...) +{ + struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; + size_t count; + va_list ap; + + va_start(ap, first_key_ptr); + count = _crau_accumulate_datav(data, ap, (char *)first_key_ptr); + va_end(ap); + + CRAU_DATA(crau_current_context(), data, count); +} + +# else + +# ifndef CRAU_MAYBE_UNUSED +# if defined(__has_c_attribute) && \ + __has_c_attribute (__maybe_unused__) +# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] +# elif defined(__GNUC__) +# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) +# endif +# endif /* CRAU_MAYBE_UNUSED */ + +void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) +{ +} + +crau_context_t crau_pop_context(void) +{ + return CRAU_ORPHANED_CONTEXT; +} + +crau_context_t crau_current_context(void) +{ + return CRAU_ORPHANED_CONTEXT; +} + +void crau_push_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) +{ +} + +void crau_data(char *first_key_ptr CRAU_MAYBE_UNUSED, ...) +{ +} + +# endif /* ENABLE_CRYPTO_AUDITING */ + +#endif /* CRAU_IMPLEMENTATION */ + #endif /* CRAU_CRAU_H */ diff --git a/macros.h b/macros.h index 7b69a79..d750f67 100644 --- a/macros.h +++ b/macros.h @@ -1,9 +1,11 @@ -/* SPDX-License-Identifier: MIT */ +/* SPDX-License-Identifier: MIT OR Unlicense */ /* Copyright (C) 2022-2025 The crypto-auditing developers. */ /* This file defines a set of low-level macros to insert probe points * used for crypto-auditing into the application programs. See * for a higher-level and more ergonomic interface. + * + * Unless ENABLE_CRYPTO_AUDITING is defined, all macros turn to no-op. */ #ifndef CRAU_MACROS_H From 3ce9f7694ee9287f574bd8bbea3ee73ae174dc76 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 6 Oct 2025 17:02:19 +0900 Subject: [PATCH 28/37] Minor style fixes Signed-off-by: Daiki Ueno --- crau.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crau.h b/crau.h index 57f5eb8..a65f097 100644 --- a/crau.h +++ b/crau.h @@ -183,9 +183,9 @@ crau_context_t crau_current_context(void) } static inline unsigned long -_crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], - va_list ap, - char *key_ptr) +crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], + va_list ap, + char *key_ptr) { unsigned long count = 0; @@ -219,7 +219,7 @@ void crau_push_context_with_data(crau_context_t context, ...) va_list ap; va_start(ap, context); - count = _crau_accumulate_datav(data, ap, va_arg(ap, char *)); + count = crau_accumulate_datav(data, ap, va_arg(ap, char *)); va_end(ap); CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, @@ -234,7 +234,7 @@ void crau_data(const char *first_key_ptr, ...) va_list ap; va_start(ap, first_key_ptr); - count = _crau_accumulate_datav(data, ap, (char *)first_key_ptr); + count = crau_accumulate_datav(data, ap, (char *)first_key_ptr); va_end(ap); CRAU_DATA(crau_current_context(), data, count); From f2e84a4a87b1330d8d7cd17a1f3ab4cc8381f09a Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 6 Oct 2025 17:07:32 +0900 Subject: [PATCH 29/37] Remove crau.c Signed-off-by: Daiki Ueno --- crau.c | 179 --------------------------------------------------------- 1 file changed, 179 deletions(-) delete mode 100644 crau.c diff --git a/crau.c b/crau.c deleted file mode 100644 index 90dc498..0000000 --- a/crau.c +++ /dev/null @@ -1,179 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright (C) 2022-2025 The crypto-auditing developers. */ - -/* This file implements the functions a set of high-level functions to - * insert probe points used for crypto-auditing into the application - * programs. - * - * This file is typically copied into the application's source code as - * a copylib, and the following configuration macros can be used to - * override the behavior of the implementation: - * - * * CRAU_CONTEXT_STACK_DEPTH: depth of the thread-local context stack - * (default: 3) - * - * * CRAU_RETURN_ADDRESS: return address of the current function - * (default: auto-detected) - * - * * CRAU_THREAD_LOCAL: thread-local modifier of the C language - * (default: auto-detected) - * - * * CRAU_MAYBE_UNUSED: an attribute to suppress warnings when a - * function argument is not used in the function body (default: - * auto-detected) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "crau.h" - -#include "macros.h" - -/* Avoid name clash with crau_data_type_t */ -#undef CRAU_WORD -#undef CRAU_STRING -#undef CRAU_BLOB - -#include -#include - -#ifdef ENABLE_CRYPTO_AUDITING - -#ifndef CRAU_CONTEXT_STACK_DEPTH -#define CRAU_CONTEXT_STACK_DEPTH 3 -#endif /* CRAU_CONTEXT_STACK_DEPTH */ - -#ifndef CRAU_THREAD_LOCAL -# ifdef thread_local -# define CRAU_THREAD_LOCAL thread_local -# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) -# define CRAU_THREAD_LOCAL _Thread_local -# elif defined(_MSC_VER) -# define CRAU_THREAD_LOCAL __declspec(thread) -# elif defined(__GNUC__) -# define CRAU_THREAD_LOCAL __thread -# else -# error "thread_local support is required; define CRAU_THREAD_LOCAL" -# endif -#endif /* CRAU_THREAD_LOCAL */ - -static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { - 0, -}; -static CRAU_THREAD_LOCAL size_t context_stack_top = 0; - -static inline void push_context(crau_context_t context) -{ - context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = context; -} - -void crau_push_context(crau_context_t context) -{ - CRAU_NEW_CONTEXT(context, crau_current_context()); - push_context(context); -} - -crau_context_t crau_pop_context(void) -{ - return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[--context_stack_top]; -} - -crau_context_t crau_current_context(void) -{ - return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[context_stack_top - 1]; -} - -static inline unsigned long -accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], - va_list ap, - char *key_ptr) -{ - unsigned long count = 0; - - for (; key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; - key_ptr = va_arg(ap, char *), count++) { - data[count].key_ptr = key_ptr; - - switch (va_arg(ap, enum crau_data_type_t)) { - case CRAU_WORD: - data[count].value_ptr = (void *)va_arg(ap, intptr_t); - data[count].value_size = (unsigned long)-2; - break; - case CRAU_STRING: - data[count].value_ptr = (void *)va_arg(ap, char *); - data[count].value_size = (unsigned long)-1; - break; - case CRAU_BLOB: - data[count].value_ptr = va_arg(ap, void *); - data[count].value_size = va_arg(ap, unsigned long); - break; - } - } - - return count; -} - -void crau_push_context_with_data(crau_context_t context, ...) -{ - struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; - unsigned long count; - va_list ap; - - va_start(ap, context); - count = accumulate_datav(data, ap, va_arg(ap, char *)); - va_end(ap); - - CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, - count); - push_context(context); -} - -void crau_data(const char *first_key_ptr, ...) -{ - struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; - size_t count; - va_list ap; - - va_start(ap, first_key_ptr); - count = accumulate_datav(data, ap, (char *)first_key_ptr); - va_end(ap); - - CRAU_DATA(crau_current_context(), data, count); -} - -#else - -#ifndef CRAU_MAYBE_UNUSED -# if defined(__has_c_attribute) && \ - __has_c_attribute (__maybe_unused__) -# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] -# elif defined(__GNUC__) -# define CRAU_MAYBE_UNUSED __attribute__((__unused__)) -# endif -#endif /* CRAU_MAYBE_UNUSED */ - -void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) -{ -} - -crau_context_t crau_pop_context(void) -{ - return CRAU_ORPHANED_CONTEXT; -} - -crau_context_t crau_current_context(void) -{ - return CRAU_ORPHANED_CONTEXT; -} - -void crau_push_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) -{ -} - -void crau_data(char *first_key_ptr CRAU_MAYBE_UNUSED, ...) -{ -} - -#endif /* ENABLE_CRYPTO_AUDITING */ From 23376d07ce736ace10380d5ca25ed49eab34e982 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 6 Oct 2025 17:25:57 +0900 Subject: [PATCH 30/37] Fix compilation without ENABLE_CRYPTO_AUDITING Signed-off-by: Daiki Ueno --- crau.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crau.h b/crau.h index a65f097..0357767 100644 --- a/crau.h +++ b/crau.h @@ -269,7 +269,7 @@ void crau_push_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) { } -void crau_data(char *first_key_ptr CRAU_MAYBE_UNUSED, ...) +void crau_data(const char *first_key_ptr CRAU_MAYBE_UNUSED, ...) { } From dab2b97cd959aa8de71386da97c8db6968197858 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 7 Oct 2025 04:58:20 +0900 Subject: [PATCH 31/37] Error out if HAVE_SYS_SDT_H is not defined while it is used Signed-off-by: Daiki Ueno --- macros.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/macros.h b/macros.h index d750f67..9946b53 100644 --- a/macros.h +++ b/macros.h @@ -14,7 +14,9 @@ #ifdef ENABLE_CRYPTO_AUDITING #ifdef HAVE_SYS_SDT_H -#include +# include +#else +# error "define HAVE_SYS_SDT_H" #endif /* Introduce a new context CONTEXT, derived from the parent context PARENT. From e9dd9446fec13914ec0afd4607ac2db284f2c7e8 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 8 Oct 2025 18:07:08 +0900 Subject: [PATCH 32/37] Include unconditionally, check DTRACE_PROBE On macOS, provides a different interface than Linux. Check if the header is actually usable. Signed-off-by: Daiki Ueno --- macros.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/macros.h b/macros.h index 9946b53..0398c7e 100644 --- a/macros.h +++ b/macros.h @@ -13,10 +13,9 @@ #ifdef ENABLE_CRYPTO_AUDITING -#ifdef HAVE_SYS_SDT_H -# include -#else -# error "define HAVE_SYS_SDT_H" +#include +#ifndef DTRACE_PROBE +# error "no DTrace compatibile macros defined in " #endif /* Introduce a new context CONTEXT, derived from the parent context PARENT. From cfc9e310222a5265fc5a64a5c6aacb433f12559a Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 14 Oct 2025 11:43:15 +0900 Subject: [PATCH 33/37] crau.h: Make functions take a stack argument That way the caller can decide where and how to maintain the context stack. Signed-off-by: Daiki Ueno --- README.md | 20 +++--- crau.h | 178 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 117 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d521935..bb19269 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,20 @@ # crau -`crau` is a small helper library to define -[crypto-auditing][crypto-auditing] probes in C applications. The -library shall be either statically linked or bundled into the -application itself. +`crau` is a header-only library to help define +[crypto-auditing][crypto-auditing] probes in C applications. ## Getting started -1. Define `ENABLE_CRYPTO_AUDITING` to 1, e.g., through `` +1. Define `ENABLE_CRYPTO_AUDITING` to 1, e.g., through + ``. Also check if `` is installed and + `DTRACE_PROBE*` macros are defined there. 1. Include ``. One of the C files should define - `CRAU_IMPLEMENTATION` to get the functions defined. + `CRAU_IMPLEMENTATION` to get the functions defined. Also decide + where to manage the context stack: if it is part of another struct, + add field with type `struct crau_context_stack_st`; if it is + maintained globally as thread-local, define a thread-local + variable. 1. (Optional) Customize the implementation with configuration macros, e.g., `CRAU_CONTEXT_STACK_DEPTH` for your needs. See @@ -22,11 +26,13 @@ application itself. ```c /* Public key signing operation starts (but the algorithm is not known yet) */ crau_new_context_with_data( + &stack, "name", CRAU_STRING, "pk::sign", NULL) ... /* Signing algorithm and bits are known at this point */ crau_data( + &stack, "pk::algorithm", CRAU_STRING, "mldsa", "pk::bits", CRAU_WORD, 1952 * 8, NULL) @@ -35,7 +41,7 @@ crau_data( sig = mldsa_sign(...); /* Pop the operation context */ -crau_pop_context(); +crau_pop_context(&stack); ``` ## Low level macros diff --git a/crau.h b/crau.h index 0357767..6910630 100644 --- a/crau.h +++ b/crau.h @@ -36,6 +36,8 @@ #ifndef CRAU_CRAU_H #define CRAU_CRAU_H +#include +#include #include /* An opaque type that represents a context (e.g., TLS handshake) @@ -62,6 +64,15 @@ typedef long crau_context_t; */ #define CRAU_ORPHANED_CONTEXT ((crau_context_t)-1) +#ifndef CRAU_CONTEXT_STACK_DEPTH +# define CRAU_CONTEXT_STACK_DEPTH 3 +#endif /* CRAU_CONTEXT_STACK_DEPTH */ + +struct crau_context_stack_st { + crau_context_t stack[CRAU_CONTEXT_STACK_DEPTH]; + size_t top; +}; + /* Types of crypto-auditing event data. CRAU_WORD means an integer in * a machine word, CRAU_STRING means a NUL-terminated * string. CRAU_BLOB means an explicitly sized binary blob. @@ -72,40 +83,45 @@ enum crau_data_type_t { CRAU_BLOB, }; -/* Push a context CONTEXT onto the thread-local context stack. If the - * depth of the stack exceeds CRAU_CONTEXT_STACK_DEPTH, the older - * element will be removed. +/* Push a context CONTEXT onto the given context stack STACK. If the depth of + * the stack exceeds CRAU_CONTEXT_STACK_DEPTH, the older element will be + * removed. * * This call shall be followed by a `crau_pop_context`. */ -void crau_push_context(crau_context_t context); +void crau_push_context(struct crau_context_stack_st *stack, + crau_context_t context); -/* Pop a context from the thread-local context stack. If the stack is - * empty, it returns a CRAU_ORPHANED_CONTEXT. +/* Pop a context from the given context stack STACK. If the stack is empty, it + * returns a CRAU_ORPHANED_CONTEXT. */ -crau_context_t crau_pop_context(void); +crau_context_t crau_pop_context(struct crau_context_stack_st *stack); -/* Return the context currently active for this thread. If there is no - * active context, it returns a CRAU_ORPHANED_CONTEXT. +/* Return the context currently active in the given context stack STACK. If + * there is no active context, it returns a CRAU_ORPHANED_CONTEXT. */ -crau_context_t crau_current_context(void); +crau_context_t crau_current_context(struct crau_context_stack_st *stack); -/* Push a context CONTEXT onto the thread-local context stack, +/* Push a context CONTEXT onto the given context stack STACK, * optionally emitting events through varargs. * * If the depth of the stack exceeds CRAU_CONTEXT_STACK_DEPTH, the * older element will be removed. This call shall be followed by a * `crau_pop_context`. */ -void crau_push_context_with_data(crau_context_t context, ...); +void crau_push_context_with_data(struct crau_context_stack_st *stack, + crau_context_t context, ...); -/* Push a new context (inferred from the current call stack) onto the - * thread-local context stack, optionally emitting events through - * varargs. +void crau_push_context_with_datav(struct crau_context_stack_st *stack, + crau_context_t context, va_list ap); + +/* Push a new context (inferred from the current call stack) onto the given + * context stack STACK, optionally emitting events through varargs. * * Typical usage example is as follows: * * crau_new_context_with_data( + * stack, * "name", CRAU_STRING, "pk::sign", * "pk::algorithm", CRAU_STRING, "mldsa", * "pk::bits", CRAU_WORD, 1952 * 8, @@ -115,14 +131,19 @@ void crau_push_context_with_data(crau_context_t context, ...); * older element will be removed. This call shall be followed by a * `crau_pop_context`. */ -#define crau_new_context_with_data(...) \ - crau_push_context_with_data(CRAU_AUTO_CONTEXT, __VA_ARGS__) +#define crau_new_context_with_data(stack, ...) \ + crau_push_context_with_data((stack), CRAU_AUTO_CONTEXT, __VA_ARGS__) + +#define crau_new_context_with_datav(stack, ap) \ + crau_push_context_with_datav((stack), CRAU_AUTO_CONTEXT, (ap)) -/* Emit events through varargs, under the current thread-local - * context. Unlike `crau_new_context_with_data`, this does not push a - * new context. +/* Emit events through varargs, under the currently active context in the given + * context stack STACK. Unlike `crau_new_context_with_data`, this does not push + * a new context. */ -void crau_data(const char *first_key_ptr, ...); +void crau_data(struct crau_context_stack_st *stack, ...); + +void crau_datav(struct crau_context_stack_st *stack, va_list ap); #ifdef CRAU_IMPLEMENTATION @@ -133,63 +154,41 @@ void crau_data(const char *first_key_ptr, ...); #undef CRAU_STRING #undef CRAU_BLOB -#include -#include - # ifdef ENABLE_CRYPTO_AUDITING -# ifndef CRAU_CONTEXT_STACK_DEPTH -# define CRAU_CONTEXT_STACK_DEPTH 3 -# endif /* CRAU_CONTEXT_STACK_DEPTH */ - -# ifndef CRAU_THREAD_LOCAL -# ifdef thread_local -# define CRAU_THREAD_LOCAL thread_local -# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) -# define CRAU_THREAD_LOCAL _Thread_local -# elif defined(_MSC_VER) -# define CRAU_THREAD_LOCAL __declspec(thread) -# elif defined(__GNUC__) -# define CRAU_THREAD_LOCAL __thread -# else -# error "thread_local support is required; define CRAU_THREAD_LOCAL" -# endif -# endif /* CRAU_THREAD_LOCAL */ - -static CRAU_THREAD_LOCAL crau_context_t context_stack[CRAU_CONTEXT_STACK_DEPTH] = { - 0, -}; -static CRAU_THREAD_LOCAL size_t context_stack_top = 0; - -static inline void push_context(crau_context_t context) +static inline void push_context(struct crau_context_stack_st *stack, + crau_context_t context) { - context_stack[context_stack_top++ % CRAU_CONTEXT_STACK_DEPTH] = context; + stack->stack[stack->top++ % CRAU_CONTEXT_STACK_DEPTH] = context; } -void crau_push_context(crau_context_t context) +void crau_push_context(struct crau_context_stack_st *stack, + crau_context_t context) { - CRAU_NEW_CONTEXT(context, crau_current_context()); - push_context(context); + CRAU_NEW_CONTEXT(context, crau_current_context(stack)); + push_context(stack, context); } -crau_context_t crau_pop_context(void) +crau_context_t crau_pop_context(struct crau_context_stack_st *stack) { - return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[--context_stack_top]; + return stack->top == 0 ? CRAU_ORPHANED_CONTEXT : + stack->stack[--stack->top]; } -crau_context_t crau_current_context(void) +crau_context_t crau_current_context(struct crau_context_stack_st *stack) { - return context_stack_top == 0 ? CRAU_ORPHANED_CONTEXT : context_stack[context_stack_top - 1]; + return stack->top == 0 ? CRAU_ORPHANED_CONTEXT : + stack->stack[stack->top - 1]; } static inline unsigned long crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], - va_list ap, - char *key_ptr) + va_list ap) { unsigned long count = 0; - for (; key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; + for (key_ptr = va_arg(ap, char *); + key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; key_ptr = va_arg(ap, char *), count++) { data[count].key_ptr = key_ptr; @@ -212,32 +211,48 @@ crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], return count; } -void crau_push_context_with_data(crau_context_t context, ...) +void crau_push_context_with_datav(struct crau_context_stack_st *stack, + crau_context_t context, va_list ap) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; unsigned long count; - va_list ap; - va_start(ap, context); - count = crau_accumulate_datav(data, ap, va_arg(ap, char *)); - va_end(ap); + count = crau_accumulate_datav(data, ap); - CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(), data, + CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(stack), data, count); push_context(context); } -void crau_data(const char *first_key_ptr, ...) +void crau_push_context_with_data(struct crau_context_stack_st *stack, + crau_context_t context, ...) +{ + va_list ap; + + va_start(ap, context); + crau_push_context_with_datav(stack, context, ap); + va_end(ap); +} + +void crau_datav(struct crau_context_stack_st *stack, va_list ap) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; size_t count; + + count = crau_accumulate_datav(data, ap); + + CRAU_DATA(crau_current_context(stack), data, count); +} + +void crau_data(struct crau_context_stack_st *stack, ...) +{ va_list ap; - va_start(ap, first_key_ptr); - count = crau_accumulate_datav(data, ap, (char *)first_key_ptr); + va_start(ap, stack); + crau_datav(stack, ap); va_end(ap); - CRAU_DATA(crau_current_context(), data, count); + CRAU_DATA(crau_current_context(stack), data, count); } # else @@ -251,25 +266,40 @@ void crau_data(const char *first_key_ptr, ...) # endif # endif /* CRAU_MAYBE_UNUSED */ -void crau_push_context(crau_context_t context CRAU_MAYBE_UNUSED) +void crau_push_context(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, + crau_context_t context CRAU_MAYBE_UNUSED) { } -crau_context_t crau_pop_context(void) +crau_context_t +crau_pop_context(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED) { return CRAU_ORPHANED_CONTEXT; } -crau_context_t crau_current_context(void) +crau_context_t +crau_current_context(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED) { return CRAU_ORPHANED_CONTEXT; } -void crau_push_context_with_data(crau_context_t context CRAU_MAYBE_UNUSED, ...) +void crau_push_context_with_datav(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, + crau_context_t context CRAU_MAYBE_UNUSED, + va_list ap CRAU_MAYBE_UNUSED) +{ +} + +void crau_push_context_with_data(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, + crau_context_t context CRAU_MAYBE_UNUSED, ...) +{ +} + +void crau_datav(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, + va_list ap CRAU_MAYBE_UNUSED) { } -void crau_data(const char *first_key_ptr CRAU_MAYBE_UNUSED, ...) +void crau_data(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, ...) { } From 81f5237d384b9b8f62d1d05c63c6a306464121a9 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 14 Oct 2025 14:13:53 +0900 Subject: [PATCH 34/37] crau.h: Drop crau_context_t, always assume it to be long Signed-off-by: Daiki Ueno --- README.md | 6 +++--- crau.h | 46 ++++++++++++++++++++-------------------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index bb19269..1b4a660 100644 --- a/README.md +++ b/README.md @@ -53,13 +53,13 @@ defined in `macros.h`: ```c /* Public key signing operation starts (but the algorithm is not known yet) */ CRAU_NEW_CONTEXT_WITH_DATAV( - (crau_context_t)this_function, - (crau_context_t)parent_function, + (long)this_function, + (long)parent_function, CRAU_STRING_DATA("name", "pk::sign")); ... /* Signing algorithm and bits are known at this point */ CRAU_DATAV( - (crau_context_t)this_function, + (long)this_function, CRAU_STRING_DATA("pk::algorithm", "mldsa"), CRAU_WORD_DATA("pk::bits", 1952 * 8)) diff --git a/crau.h b/crau.h index 6910630..f2b9408 100644 --- a/crau.h +++ b/crau.h @@ -40,20 +40,14 @@ #include #include -/* An opaque type that represents a context (e.g., TLS handshake) - * where crypto-auditing events occur. This should be a unique - * identifier within a thread. - */ -typedef long crau_context_t; - /* A special context value used to represent a context which is * automatically assigned based on the current call frame. */ #ifndef CRAU_AUTO_CONTEXT # ifdef __GNUC__ -# define CRAU_AUTO_CONTEXT (crau_context_t)(intptr_t)(char *)__builtin_return_address(0) +# define CRAU_AUTO_CONTEXT (long)(intptr_t)(char *)__builtin_return_address(0) # elif defined(__CC_ARM) -# define CRAU_AUTO_CONTEXT (crau_context_t)(intptr_t)(char *)__return_address() +# define CRAU_AUTO_CONTEXT (long)(intptr_t)(char *)__return_address() # else # define CRAU_AUTO_CONTEXT CRAU_ORPHANED_CONTEXT # endif @@ -62,14 +56,14 @@ typedef long crau_context_t; /* A special context value used to represent a context which is not * associated with any parent nor children. */ -#define CRAU_ORPHANED_CONTEXT ((crau_context_t)-1) +#define CRAU_ORPHANED_CONTEXT ((long)-1) #ifndef CRAU_CONTEXT_STACK_DEPTH # define CRAU_CONTEXT_STACK_DEPTH 3 #endif /* CRAU_CONTEXT_STACK_DEPTH */ struct crau_context_stack_st { - crau_context_t stack[CRAU_CONTEXT_STACK_DEPTH]; + long stack[CRAU_CONTEXT_STACK_DEPTH]; size_t top; }; @@ -90,17 +84,17 @@ enum crau_data_type_t { * This call shall be followed by a `crau_pop_context`. */ void crau_push_context(struct crau_context_stack_st *stack, - crau_context_t context); + long context); /* Pop a context from the given context stack STACK. If the stack is empty, it * returns a CRAU_ORPHANED_CONTEXT. */ -crau_context_t crau_pop_context(struct crau_context_stack_st *stack); +long crau_pop_context(struct crau_context_stack_st *stack); /* Return the context currently active in the given context stack STACK. If * there is no active context, it returns a CRAU_ORPHANED_CONTEXT. */ -crau_context_t crau_current_context(struct crau_context_stack_st *stack); +long crau_current_context(struct crau_context_stack_st *stack); /* Push a context CONTEXT onto the given context stack STACK, * optionally emitting events through varargs. @@ -110,10 +104,10 @@ crau_context_t crau_current_context(struct crau_context_stack_st *stack); * `crau_pop_context`. */ void crau_push_context_with_data(struct crau_context_stack_st *stack, - crau_context_t context, ...); + long context, ...); void crau_push_context_with_datav(struct crau_context_stack_st *stack, - crau_context_t context, va_list ap); + long context, va_list ap); /* Push a new context (inferred from the current call stack) onto the given * context stack STACK, optionally emitting events through varargs. @@ -157,25 +151,25 @@ void crau_datav(struct crau_context_stack_st *stack, va_list ap); # ifdef ENABLE_CRYPTO_AUDITING static inline void push_context(struct crau_context_stack_st *stack, - crau_context_t context) + long context) { stack->stack[stack->top++ % CRAU_CONTEXT_STACK_DEPTH] = context; } void crau_push_context(struct crau_context_stack_st *stack, - crau_context_t context) + long context) { CRAU_NEW_CONTEXT(context, crau_current_context(stack)); push_context(stack, context); } -crau_context_t crau_pop_context(struct crau_context_stack_st *stack) +long crau_pop_context(struct crau_context_stack_st *stack) { return stack->top == 0 ? CRAU_ORPHANED_CONTEXT : stack->stack[--stack->top]; } -crau_context_t crau_current_context(struct crau_context_stack_st *stack) +long crau_current_context(struct crau_context_stack_st *stack) { return stack->top == 0 ? CRAU_ORPHANED_CONTEXT : stack->stack[stack->top - 1]; @@ -212,7 +206,7 @@ crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], } void crau_push_context_with_datav(struct crau_context_stack_st *stack, - crau_context_t context, va_list ap) + long context, va_list ap) { struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS]; unsigned long count; @@ -225,7 +219,7 @@ void crau_push_context_with_datav(struct crau_context_stack_st *stack, } void crau_push_context_with_data(struct crau_context_stack_st *stack, - crau_context_t context, ...) + long context, ...) { va_list ap; @@ -267,30 +261,30 @@ void crau_data(struct crau_context_stack_st *stack, ...) # endif /* CRAU_MAYBE_UNUSED */ void crau_push_context(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, - crau_context_t context CRAU_MAYBE_UNUSED) + long context CRAU_MAYBE_UNUSED) { } -crau_context_t +long crau_pop_context(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED) { return CRAU_ORPHANED_CONTEXT; } -crau_context_t +long crau_current_context(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED) { return CRAU_ORPHANED_CONTEXT; } void crau_push_context_with_datav(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, - crau_context_t context CRAU_MAYBE_UNUSED, + long context CRAU_MAYBE_UNUSED, va_list ap CRAU_MAYBE_UNUSED) { } void crau_push_context_with_data(struct crau_context_stack_st *stack CRAU_MAYBE_UNUSED, - crau_context_t context CRAU_MAYBE_UNUSED, ...) + long context CRAU_MAYBE_UNUSED, ...) { } From 5027e5572eaae1a502dfe702552338b5a2169328 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 14 Oct 2025 14:45:35 +0900 Subject: [PATCH 35/37] crau.h: Fix the previous commit Signed-off-by: Daiki Ueno --- crau.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crau.h b/crau.h index f2b9408..0d4f9f1 100644 --- a/crau.h +++ b/crau.h @@ -180,6 +180,7 @@ crau_accumulate_datav(struct crypto_auditing_data data[CRAU_MAX_DATA_ELEMS], va_list ap) { unsigned long count = 0; + char *key_ptr; for (key_ptr = va_arg(ap, char *); key_ptr != NULL && count < CRAU_MAX_DATA_ELEMS; @@ -215,7 +216,7 @@ void crau_push_context_with_datav(struct crau_context_stack_st *stack, CRAU_NEW_CONTEXT_WITH_DATA(context, crau_current_context(stack), data, count); - push_context(context); + push_context(stack, context); } void crau_push_context_with_data(struct crau_context_stack_st *stack, @@ -245,8 +246,6 @@ void crau_data(struct crau_context_stack_st *stack, ...) va_start(ap, stack); crau_datav(stack, ap); va_end(ap); - - CRAU_DATA(crau_current_context(stack), data, count); } # else From 5c13217b320dd68c465368aa3f02763302a72d20 Mon Sep 17 00:00:00 2001 From: Julien Olivain Date: Mon, 1 Dec 2025 17:02:06 +0900 Subject: [PATCH 36/37] crau: fix compilation with gcc < 11 If the CRAU_MAYBE_UNUSED macro is unset, the crau.h file tries to automatically detect an appropriate value for it. This autodetection is using the cpp special operator `__has_c_attribute` [1], introduced in gcc 11 [2]. When compiling with a gcc older than version 11, the compilation fails with the error: In file included from audit.h:22, from audit.c:26: crau/crau.h:255:23: error: missing binary operator before token "(" __has_c_attribute (__maybe_unused__) ^ This has been observed, for example, in Rocky Linux 8.10, which contains a gcc v8.5.0. The issue happens because the test for the `__has_c_attribute` availability and the test for the `__maybe_unused__` attribute are in the same directive. Those tests should be separated in two different directives, following the same logic described in the `__has_builtin` documentation [3]. This issue was found in Buildroot, after updating gnutls to version 3.8.11 in [4]. This commit fixes the issue by splitting the test in two. [1] https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fc_005fattribute.html [2] https://gcc.gnu.org/gcc-11/changes.html#c [3] https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fbuiltin.html [4] https://gitlab.com/buildroot.org/buildroot/-/commit/81dbfe1c2ae848b4eb1f896198d13455df50e548 Reported-by: Neal Frager Signed-off-by: Julien Olivain Signed-off-by: Daiki Ueno --- crau.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crau.h b/crau.h index 0d4f9f1..53d3355 100644 --- a/crau.h +++ b/crau.h @@ -251,9 +251,10 @@ void crau_data(struct crau_context_stack_st *stack, ...) # else # ifndef CRAU_MAYBE_UNUSED -# if defined(__has_c_attribute) && \ - __has_c_attribute (__maybe_unused__) -# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] +# if defined(__has_c_attribute) +# if __has_c_attribute (__maybe_unused__) +# define CRAU_MAYBE_UNUSED [[__maybe_unused__]] +# endif # elif defined(__GNUC__) # define CRAU_MAYBE_UNUSED __attribute__((__unused__)) # endif From fc96dbfe8be81efd9ea82a1a337c30c2d033e0d3 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 1 Dec 2025 17:33:58 +0900 Subject: [PATCH 37/37] Remove dist/audit.h The file was provided to make library integration easier, though it turned out to be too primitive and incomplete. This removes the file in favor of the new crau library. Signed-off-by: Daiki Ueno --- dist/audit.h | 91 ---------------------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 dist/audit.h diff --git a/dist/audit.h b/dist/audit.h deleted file mode 100644 index 314282f..0000000 --- a/dist/audit.h +++ /dev/null @@ -1,91 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright (C) 2022-2023 The crypto-auditing developers. */ - -/* This file defines probe points used by crypto-auditing. */ - -#ifdef ENABLE_CRYPTO_AUDITING - -# ifdef HAVE_SYS_SDT_H -# include -# endif - -/* Introduce a new context CONTEXT, derived from PARENT */ -# define CRYPTO_AUDITING_NEW_CONTEXT(context, parent) \ - DTRACE_PROBE2(crypto_auditing, new_context, context, parent) - -/* Assert an event with KEY and VALUE. The key is treated as a - * NUL-terminated string, while the value is in the size of machine - * word - */ -# define CRYPTO_AUDITING_WORD_DATA(context, key_ptr, value_ptr) \ - DTRACE_PROBE3(crypto_auditing, word_data, context, key_ptr, value_ptr) - -/* Assert an event with KEY and VALUE. Both the key and value are - * treated as a NUL-terminated string - */ -# define CRYPTO_AUDITING_STRING_DATA(context, key_ptr, value_ptr) \ - DTRACE_PROBE3(crypto_auditing, string_data, context, key_ptr, value_ptr) - -/* Assert an event with KEY and VALUE. The key is treated as a - * NUL-terminated string, while the value is explicitly sized with - * VALUE_SIZE - */ -# define CRYPTO_AUDITING_BLOB_DATA(context, key_ptr, value_ptr, value_size) \ - DTRACE_PROBE4(crypto_auditing, blob_data, context, key_ptr, value_ptr, value_size) - -struct crypto_auditing_data { - char *key_ptr; - void *value_ptr; - unsigned long value_size; -}; - -# define CRYPTO_AUDITING_WORD(key_ptr, value_ptr) \ - { (char *)(key_ptr), (void *)(intptr_t)(value_ptr), (unsigned long)-2 } -# define CRYPTO_AUDITING_STRING(key_ptr, value_ptr) \ - { (char *)(key_ptr), (void *)(value_ptr), (unsigned long)-1 } -# define CRYPTO_AUDITING_BLOB(key_ptr, value_ptr, value_size) \ - { (char *)(key_ptr), (void *)(value_ptr), value_size } - -/* Assert multiple events (16 at maxiumum) at once as a typed - * array. The VALUE_SIZE field of each element indicates the type of - * event: -2 means a word, -1 means a NUL-terminated string, and any - * other value means a blob with the length of VALUE_SIZE. - */ -# define CRYPTO_AUDITING_DATA(context, array_ptr, array_size) \ - DTRACE_PROBE3(crypto_auditing, data, context, array_ptr, array_size) - -# define CRYPTO_AUDITING_DATAV(context, ...) ({ \ - struct crypto_auditing_data __crypto_auditing_events[] = { __VA_ARGS__ }; \ - CRYPTO_AUDITING_DATA(context, \ - __crypto_auditing_events, \ - sizeof (__crypto_auditing_events) / sizeof (__crypto_auditing_events[0])); \ -}) - -/* Introduce a new context CONTEXT, derived from PARENT, as well as - * assert multiple events. - */ -# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATA(context, parent, array_ptr, array_size) \ - DTRACE_PROBE4(crypto_auditing, new_context_with_data, context, parent, array_ptr, array_size) - -# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATAV(context, parent, ...) ({ \ - struct crypto_auditing_data __crypto_auditing_events[] = { __VA_ARGS__ }; \ - CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATA(context, parent, \ - __crypto_auditing_events, \ - sizeof (__crypto_auditing_events) / sizeof (__crypto_auditing_events[0])); \ -}) - -#else - -# define CRYPTO_AUDITING_NEW_CONTEXT(context, parent) -# define CRYPTO_AUDITING_WORD_DATA(context, key_ptr, value_ptr) -# define CRYPTO_AUDITING_STRING_DATA(context, key_ptr, value_ptr) -# define CRYPTO_AUDITING_BLOB_DATA(context, key_ptr, value_ptr, value_size) -# define CRYPTO_AUDITING_WORD(key_ptr, value_ptr) -# define CRYPTO_AUDITING_STRING(key_ptr, value_ptr) -# define CRYPTO_AUDITING_BLOB(key_ptr, value_ptr, value_size) -# define CRYPTO_AUDITING_DATA(context, array_ptr, array_size) -# define CRYPTO_AUDITING_DATAV(context, ...) -# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATA(context, parent, array_ptr, array_size) -# define CRYPTO_AUDITING_NEW_CONTEXT_WITH_DATAV(context, parent, ...) - -#endif /* ENABLE_CRYPTO_AUDITING */