From 4241a8684c1dfabd6689733688add3dd20928783 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Sun, 1 Feb 2026 09:07:58 +0900 Subject: [PATCH 1/5] docs: Update architecture diagram Signed-off-by: Daiki Ueno --- docs/architecture.md | 57 +++---- docs/architecture.odg | Bin 30090 -> 28976 bytes docs/architecture.svg | 389 +++++++++++++++++------------------------- 3 files changed, 178 insertions(+), 268 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index bb98e51..dff850d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -4,8 +4,8 @@ - [Summary](#summary) - [Design Details](#design-details) - [Architecture](#architecture) - - [crypto-auditing agent](#crypto-auditing-agent) - - [crypto-auditing event broker](#crypto-auditing-event-broker) + - [crau-agent](#crau-agent) + - [Log analysis tools](#log-analysis-tools) ## Summary @@ -19,48 +19,35 @@ The following figure illustrates the proposed architecture. ![](architecture.svg) -At the highest level, the architecture can be seen as a variant of -[MQTT] (Message Queuing Telemetry Transport): the programs being -monitored acts as a publisher, the programs consume the collected -information act as a subscriber, and there will be intermediate -components that coordinate the communication flow between them. +At the highest level, the architecture consists of two parts: +crau-agent and log analysis tools (crau-query, crau-monitor). -- **crypto-auditing agent**: A program that receives events from publishers and write them onto the primary log storage -- **crypto-auditing event broker**: A program that accesses the primary log storage and notify the subscribers +crau-agent runs as a system service, receives cryptographic events +from the kernel through eBPF, and writes them onto the primary log +file. -### crypto-auditing agent +Log analysis tools provide users with access to the primary log +storage. -The responsibilities of crypto-auditing agent include: +### crau-agent -- Install BPF program to monitor USDT -- Get notified an event when USDT is reached -- Write events to primary log storage +The responsibilities of crau-agent include: -The agent is meant to work as fast as possible, while it shouldn't be -resource intensive, by utilizing asynchronous I/O mechanisms for -communicating with the publishers, through the kernel ([BPF ring -buffer] and [io_uring]). +- Install BPF program to monitor USDT events +- Receive notification events on execution reaching USDT probes +- Write received events to primary log file -### crypto-auditing event broker +The agent is meant to work as fast as possible with minimal resource +consumption. The current implementation leverages [eBPF ring buffers] +and [io_uring] for asynchronous I/O. -The event broker is the only process which has direct access to the -primary log storage on behalf of the subscribers. The -responsibilities of event broker include: +### Log analysis tools -- Subscription management - - Accept connections from subscribers - - Deliver events to subscribers - - For each event, ensure every subscriber receives it at most once -- Event management - - Read events from primary log storage - - Truncate primary log storage based on policies, such as certain time has elapsed, and/or all subscribers have read (or skipped) certain range of event sequence +The log analysis tools provides ways to access the primary log file, +either at any later time or at real-time. -The event broker caters for multiple types of subscribers: some may -periodically (daily, for example) check the log and calculate -statistics, and others may immediately consume events and provide -real-time diagnostics. +The current implementation contains crau-query for the former, and +crau-monitor for the latter. -[MQTT]: https://mqtt.org [BPF ring buffer]: https://www.kernel.org/doc/html/latest/bpf/ringbuf.html [io_uring]: https://en.wikipedia.org/wiki/Io_uring - diff --git a/docs/architecture.odg b/docs/architecture.odg index b200f01dc7be08c119fecf1a965c82c057038e49..2629fed99a87b7e0b14d092d692aac0ad36282ab 100644 GIT binary patch literal 28976 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%0AE!sd=q|TBU-n3|tMJC8fHQB)o`3bF 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�Amb{4`8uqw-Z)@A1%WvB{dZ|7c_T71 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 afAFs=@~B8QHUPj!eprz%TF&YB-v0rCksnq7 diff --git a/docs/architecture.svg b/docs/architecture.svg index 5af5bbd..3f1ccd5 100644 --- a/docs/architecture.svg +++ b/docs/architecture.svg @@ -1,6 +1,6 @@ - + @@ -11,50 +11,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - + @@ -101,294 +110,208 @@ - - - - Kernel + + + - - - - crypto-auditingagent + + + + Kernel - - - - - + + + + crypto-auditingagent - - - - - + + + + crau-query - - - - crypto-auditingevent broker + + + + + + Log file(CBOR) - - - - - - Primary log storage + + + + BPF program - - - - BPF program + + + + Shared library - - - - Shared library + + + + Target program - - - - Insights sink + + + + Target program - - - - Real-time auditsink + + + + Shared library - - - - Target program + + + + Target program - - - - Target program + + + + Target program - + - - - - Shared library + + + + Read - + - - - - - - Statistics for Insights(daily) + + + + Attach - + - - - - Insights client + + + + Attach - - - - Target program + - - - - Target program + + + + crau-agent - + - - - - Write + - - - - Read + + + - - - - Attach + + + - - - - Attach + + + - - - - Subscribe + + + - - - - - - - - - - - - - - - - - Use - - - - - - BPF ring buffer - - - - - - io_uring + + + - - + + + + + USDT - - - - - crypto-auditingagent + + + + + USDT - - - - - - - - - - - - - - - - - - - - - - - - Use - - - - - - - - - - - - - - + + + + + crau-monitor - - - - - - - - - - - - USDT - - - - - - - - USDT + + + + + Write From 6e39a39bc749c830c8d4d2ace9f89a7dd4fd47a5 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 13 Feb 2026 16:35:38 +0900 Subject: [PATCH 2/5] types, monitor: Fix typo Signed-off-by: Daiki Ueno --- crypto-auditing/src/types.rs | 2 +- monitor/src/monitor.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto-auditing/src/types.rs b/crypto-auditing/src/types.rs index 5241899..f9cccf2 100644 --- a/crypto-auditing/src/types.rs +++ b/crypto-auditing/src/types.rs @@ -124,7 +124,7 @@ impl ContextTracker { if !self.all_contexts.contains_key(group.context()) { // Either this library did not do a new_context for this context, or the // log we have is truncated at the beginning. Just assume that this context - // has no parent and create a new one so we don't loose the information in + // has no parent and create a new one so we don't lose the information in // this message. let context_obj = Rc::new(RefCell::new(Context { id: *group.context(), diff --git a/monitor/src/monitor.rs b/monitor/src/monitor.rs index bd0868e..8a7ba6b 100644 --- a/monitor/src/monitor.rs +++ b/monitor/src/monitor.rs @@ -153,7 +153,7 @@ async fn shutdown( if let Err(e) = maybe_value { info!(error = %e, "error receiving ctrl-c") } - info!("shutting down event broker"); + info!("shutting down event monitor"); if let Err(e) = shutdown_sender.send(()) { info!(error = %e, "unable to send shutdown"); } From 6e42ac6dd099cbc939bc9a58fd05c771c4af36f7 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 13 Feb 2026 16:37:00 +0900 Subject: [PATCH 3/5] logging-format: Shorten tls::certificate_{sign,verify} event names Signed-off-by: Daiki Ueno --- README.md | 8 ++++---- docs/logging-format.md | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 629cd72..0d2165d 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ $ crau-query --log-file audit.cborseq "start": 49431631956782, "end": 49431631963209, "events": { - "name": "tls::certificate_verify", + "name": "tls::verify", "tls::signature_algorithm": 2057 } } @@ -124,7 +124,7 @@ $ crau-query --log-file audit.cborseq "start": 49431628203429, "end": 49431628207396, "events": { - "name": "tls::certificate_verify", + "name": "tls::verify", "tls::signature_algorithm": 2057 } } @@ -145,7 +145,7 @@ $ crau-query --log-file audit.cborseq "start": 49434509684783, "end": 49434509694813, "events": { - "name": "tls::certificate_verify", + "name": "tls::verify", "tls::signature_algorithm": 2057 } } @@ -166,7 +166,7 @@ $ crau-query --log-file audit.cborseq "start": 49434503929186, "end": 49434503940540, "events": { - "name": "tls::certificate_verify", + "name": "tls::verify", "tls::signature_algorithm": 2057 } } diff --git a/docs/logging-format.md b/docs/logging-format.md index 9c2ae6d..278136d 100644 --- a/docs/logging-format.md +++ b/docs/logging-format.md @@ -75,7 +75,7 @@ a more efficient (binary) format will be used in practical deployment. { "type": "string_data", "context": "00..02", - "name": "tls::certificate_verify" + "name": "tls::verify" }, { "type": "word_data", @@ -94,7 +94,7 @@ This can be conceptually represented as a tree of events: - `tls::handshake_client` (00..01) - `tls::protocol_version` = 0x0304 - - `tls::certificate_verify` (00..02) + - `tls::verify` (00..02) - `tls::signature_algorithm` = 0x0804 - `pk::bits` = 3072 @@ -159,7 +159,7 @@ like the following, preserving the same semantics: }, { "type": "string_data", - "name": "tls::certificate_verify" + "name": "tls::verify" }, { "type": "word_data", @@ -210,13 +210,13 @@ and TLS probe points. ##### TLS context names -| name | description | -|---------------------------|------------------------------------------------------------------| -| `tls::handshake_client` | TLS handshake for client | -| `tls::handshake_server` | TLS handshake for server | -| `tls::certificate_sign` | Digital signature is created using certificate in TLS handshake | -| `tls::certificate_verify` | Digital signature is verified using certificate in TLS handshake | -| `tls::key_exchange` | Shared secret derivation in TLS handshake | +| name | description | +|-------------------------|------------------------------------------------------------------| +| `tls::handshake_client` | TLS handshake for client | +| `tls::handshake_server` | TLS handshake for server | +| `tls::sign` | Digital signature is created using certificate in TLS handshake | +| `tls::verify` | Digital signature is verified using certificate in TLS handshake | +| `tls::key_exchange` | Shared secret derivation in TLS handshake | ##### TLS keys @@ -286,7 +286,7 @@ These contexts are only useful when a public key operation cannot be determined from the outer context. If it is obvious from the outer context, the probe point provider may choose to not create a new context. For example, when the parent context is -`tls::certificate_verify`, there is no need to create a new context +`tls::verify`, there is no need to create a new context with `pk::verify`. | name | description | From 1616c335612d7913ed36a66e186fc99b9bb5838d Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 17 Feb 2026 18:57:17 +0900 Subject: [PATCH 4/5] README.md: Mention PQC migration as the primary use-case Signed-off-by: Daiki Ueno --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 0d2165d..f2204a7 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,14 @@ using BPF USDT probes to intercept specific entry points in crypto libraries, as they are used by user space processes on the system, and collect data so that it can be analyzed later. +The primary use-case of this project is to facilitate the migration of +organizations to post-quantum cryptography. Since post-quantum +algorithms are relatively new and not all applications are immediately +compatible, mandatory switch from classical cryptography is +impractical. To enable a smoother transition, crypto-auditing can be +employed at run time to identify any instances where classical +cryptography is still in use. + The design documents can be found from the following links: - [Objectives and high-level design](docs/objectives.md) From a045f2ffbe24a4178bf986864a39bb234be44a0f Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Tue, 17 Feb 2026 18:58:10 +0900 Subject: [PATCH 5/5] README.md: Remove GnuTLS build steps Given the instrumented GnuTLS is available in Fedora 43+, stop suggesting building it manually. Signed-off-by: Daiki Ueno --- README.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f2204a7..499bf85 100644 --- a/README.md +++ b/README.md @@ -27,23 +27,15 @@ The design documents can be found from the following links: ## Installation 1. Install the latest Rust toolchain -2. Install the instrumented crypto libraries, such as GnuTLS: -```console -$ git clone --depth=1 -b wip/usdt https://gitlab.com/gnutls/gnutls.git -$ ./bootstrap -$ ./configure --prefix=/path/to/installation --enable-crypto-auditing -$ make -j$(nproc) -$ sudo make install -``` -3. Install the dependencies (note that libbpf 1.1.1 or later is required) +2. Install the dependencies (note that libbpf 1.1.1 or later is required) ```console $ sudo dnf install bpftool make libbpf-devel llvm-devel rustfmt ``` -4. Build the programs with `make` +3. Build the programs with `make` ```console $ make ``` -5. Install the programs with `make install` +4. Install the programs with `make install` ```console $ sudo make install ``` @@ -80,7 +72,7 @@ $ sudo systemctl start crau-agent.service ```console $ crau-monitor ``` -7. On another terminal, run any commands using the instrumented library +7. On another terminal, run any commands using the instrumented library, such as GnuTLS in Fedora Linux 43 or later ```console $ gnutls-serv --x509certfile=doc/credentials/x509/cert-rsa-pss.pem --x509keyfile=doc/credentials/x509/key-rsa-pss.pem & $ gnutls-cli --x509cafile=doc/credentials/x509/ca.pem localhost -p 5556