Skip to content

tpm: Hash qualifying data in TPM2_Certify for IAK-based AK certification#1239

Merged
ansasaki merged 1 commit into
keylime:masterfrom
ansasaki:hash_before_certify
May 13, 2026
Merged

tpm: Hash qualifying data in TPM2_Certify for IAK-based AK certification#1239
ansasaki merged 1 commit into
keylime:masterfrom
ansasaki:hash_before_certify

Conversation

@ansasaki
Copy link
Copy Markdown
Contributor

@ansasaki ansasaki commented May 12, 2026

tpm: Hash qualifying data in TPM2_Certify for IAK-based AK certification

Type of Change

(Select all that apply)

  • Bug fix (non-breaking change)
  • New feature (non-breaking change)
  • Breaking change (fix/feature causing existing behavior to change)
  • Documentation update (standalone)
  • Code refactor (no functional changes)
  • Test cases (added/modified)
  • CI/CD changes
  • Other (please specify: ______)

Related Issues

Resolves: #1226
See also: keylime/keylime#1892

Change Description

Concise Summary

Hash agent ID (SHA-256) before passing it as qualifying data to TPM2_Certify.

Technical Details

When the agent certifies the AK with the IAK using TPM2_Certify, it passes the agent ID string directly as qualifyingData (TPM2B_DATA). The TPM 2.0 spec limits TPM2B_DATA to sizeof(TPMT_HA) bytes, which depends on the TPM's supported hash algorithms. On SHA-256-only TPMs (e.g., NVIDIA Grace Hopper aarch64), this limit is 34 bytes — smaller than a standard UUID string (36 bytes). Since Keylime supports arbitrary strings as agent IDs, the qualifying data can be even longer.

This PR hashes the agent ID with SHA-256 before using it as qualifying data, producing a fixed 32-byte value that fits within TPM2B_DATA on any TPM. The qualifying data is arbitrary per the TPM 2.0 spec (Part 3, Section 18.2) — hashing it is fully compliant.

Changes:

  • Hash agent ID in main.rs: Use keylime::crypto::hash with MessageDigest::sha256() to hash the agent ID before passing it to TPM2_Certify. No new dependencies — uses the existing openssl crate via the keylime crypto module.

  • Update test in tpm.rs: test_certify_credential_with_iak now hashes the qualifying data to match the production code path.

  • Bump pull-mode API version to 2.6 in config/base.rs.

Documentation Updates Required

(Check all that apply)

  • Updated markdown docs (file path: ______)
  • Updated code comments/docstrings
  • Needs user guide updates (docs/)
  • Needs ReadTheDocs updates
  • No docs needed (requires maintainer approval)

Documentation updates are included in the companion Python PR.

Verification Process

  1. Run cargo fmt && cargo clippy --all-targets — no new warnings
  2. Run cargo test — existing tests pass
  3. Integration test with swtpm:
    • Verify that a new agent (2.6) registers successfully with the updated registrar
    • Verify that registration works with agent IDs longer than 34 bytes (e.g., non-UUID strings)

Checklist

Additional Context

  • Deployment ordering: The companion Python PR (Verifier must expect hashed agent ID in IAK certify qualifying data keylime#1892) must be merged first. It adds backward-compatible "try both" support to the registrar, accepting both hashed (new agents) and raw (old agents) qualifying data. If this Rust PR is merged first, agents on SHA-256-only TPMs with long agent IDs will send hashed qualifying data to a registrar that cannot verify it.
  • No new dependencies were added. The hash is computed using the existing keylime::crypto::hash function backed by openssl.

This PR was created with the assistance of Claude Opus 4.6 (Anthropic).

Summary by CodeRabbit

  • New Features

    • Added support for API version 2.6.
  • Updates

    • Agent registration now computes IAK/IDevID attestations at registration time and selects qualifying data based on registrar API version (SHA-256 for 2.6+).
  • Tests / CI

    • Unit tests adjusted for the new qualifying-data behavior; e2e scenario now pins upstream source/branch used by CI.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

The PR changes agent registration to compute SHA‑256(agent_uuid) as TPM certify() qualifying_data (used for IAK/IDevID), derives attest/signature during register_agent, removes precomputed attest/signature fields, and updates API v2.6 support, tests, and CI environment pinning.

Changes

IAK/IDevID Certification and Registration Flow

Layer / File(s) Summary
API v2.6, config, and CI pinning
keylime-agent/src/api.rs, keylime-agent/src/api.rs, keylime/src/config/base.rs, packit-ci.fmf
Adds configure_api_v2_6 and get_api_scope arm for "2.6", extends SUPPORTED_API_VERSIONS to include "2.6", and pins KEYLIME_UPSTREAM_URL/KEYLIME_UPSTREAM_BRANCH in the /e2e CI scenario.
Agent startup: remove precomputed certify and update push-model registration
keylime-agent/src/main.rs, keylime-push-model-agent/src/registration.rs
Remove device_id.certify(...) from main() and stop populating attest/signature in AgentRegistration construction within the agent and push-model agent.
AgentRegistration flow: early registrar client and in-flight certification
keylime/src/agent_registration.rs
Remove attest/signature fields from AgentRegistration; build RegistrarClient before TPM work; choose qualifying_data based on registrar_client.supports_api_version("2.6") (SHA‑256 digest for 2.6+, raw UUID otherwise with a size warning); call dev_id.certify(...) to produce attest/signature; reuse registrar_client to register and activate the agent.
RegistrarClient API compatibility check
keylime/src/registrar_client.rs
Add RegistrarClient::supports_api_version(&self, version: &str) -> bool to check registrar-advertised supported_api_versions.
TPM test update
keylime/src/tpm.rs
Update test_certify_credential_with_iak to use SHA‑256 of a UUID as qualifying_data (converted to tss_esapi::structures::Data) and assert the attestation's extra_data matches the digest.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: hashing agent ID before passing to TPM2_Certify for IAK-based certification.
Linked Issues check ✅ Passed All objectives from issue #1226 are met: agent hashes agent ID with SHA-256 before certify [keylime/src/agent_registration.rs], uses fixed digest as qualifying_data, tests updated [keylime/src/tpm.rs], API version bumped [keylime/src/config/base.rs], and API v2.6 support added [keylime-agent/src/api.rs].
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the hashing solution for TPM2_Certify: agent registration flow updated, agent ID hashing applied, tests updated, API versioning adjusted, and agent IDs removed from hardcoded certify calls.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packit-ci.fmf`:
- Around line 9-10: The CI is pointing to a personal fork/branch; update
KEYLIME_UPSTREAM_URL and KEYLIME_UPSTREAM_BRANCH to use the canonical Keylime
repository and an immutable ref: set KEYLIME_UPSTREAM_URL to
"https://github.com/keylime/keylime.git" (or the official org URL) and set
KEYLIME_UPSTREAM_BRANCH to a pinned commit SHA or a stable tag that includes
verifier-side hash support (instead of "hash_before_certify"); ensure the chosen
tag/SHA is referenced in the CI config so the e2e dependency is reproducible and
stable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4dd81425-b0fa-4d0b-b961-a65d1d92985e

📥 Commits

Reviewing files that changed from the base of the PR and between 63d7107 and c2b889c.

📒 Files selected for processing (4)
  • keylime-agent/src/main.rs
  • keylime/src/config/base.rs
  • keylime/src/tpm.rs
  • packit-ci.fmf

Comment thread packit-ci.fmf Outdated
Comment on lines +9 to +10
KEYLIME_UPSTREAM_URL: "https://github.com/ansasaki/keylime.git"
KEYLIME_UPSTREAM_BRANCH: "hash_before_certify"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use canonical upstream (preferably immutable ref) for e2e dependency source.

Pointing CI to a personal fork/feature branch makes gating non-reproducible and vulnerable to branch rewrites or disappearance. Please switch to the official Keylime repo and a stable ref (ideally a pinned commit/tag containing the verifier-side hash support).

Suggested change
-    KEYLIME_UPSTREAM_URL: "https://github.com/ansasaki/keylime.git"
-    KEYLIME_UPSTREAM_BRANCH: "hash_before_certify"
+    KEYLIME_UPSTREAM_URL: "https://github.com/keylime/keylime.git"
+    KEYLIME_UPSTREAM_BRANCH: "main"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
KEYLIME_UPSTREAM_URL: "https://github.com/ansasaki/keylime.git"
KEYLIME_UPSTREAM_BRANCH: "hash_before_certify"
KEYLIME_UPSTREAM_URL: "https://github.com/keylime/keylime.git"
KEYLIME_UPSTREAM_BRANCH: "main"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packit-ci.fmf` around lines 9 - 10, The CI is pointing to a personal
fork/branch; update KEYLIME_UPSTREAM_URL and KEYLIME_UPSTREAM_BRANCH to use the
canonical Keylime repository and an immutable ref: set KEYLIME_UPSTREAM_URL to
"https://github.com/keylime/keylime.git" (or the official org URL) and set
KEYLIME_UPSTREAM_BRANCH to a pinned commit SHA or a stable tag that includes
verifier-side hash support (instead of "hash_before_certify"); ensure the chosen
tag/SHA is referenced in the CI config so the e2e dependency is reproducible and
stable.

@ansasaki ansasaki force-pushed the hash_before_certify branch from c2b889c to 9368744 Compare May 12, 2026 16:21
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 85.41667% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.69%. Comparing base (63d7107) to head (81a9b9b).

Files with missing lines Patch % Lines
keylime/src/agent_registration.rs 78.12% 7 Missing ⚠️
Additional details and impacted files
Flag Coverage Δ
e2e-testsuite 39.05% <79.16%> (+0.12%) ⬆️
upstream-unit-tests 65.70% <60.00%> (-0.65%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
keylime-agent/src/api.rs 88.32% <100.00%> (+1.81%) ⬆️
keylime-agent/src/main.rs 18.48% <ø> (+0.27%) ⬆️
keylime-push-model-agent/src/registration.rs 51.28% <ø> (+1.28%) ⬆️
keylime/src/config/base.rs 87.66% <ø> (ø)
keylime/src/registrar_client.rs 82.95% <100.00%> (+0.27%) ⬆️
keylime/src/tpm.rs 64.59% <ø> (ø)
keylime/src/agent_registration.rs 86.02% <78.12%> (-6.39%) ⬇️

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread keylime-agent/src/main.rs Outdated
Comment thread keylime-agent/src/api.rs
Comment thread keylime/src/tpm.rs Outdated
Comment thread keylime/src/tpm.rs Outdated
SHA-256 hash the agent ID before passing it as qualifyingData to
TPM2_Certify when certifying the AK with the IAK. This produces a fixed
32-byte value that fits within TPM2B_DATA on all TPMs, including those
that only support SHA-256 (where the limit is 34 bytes).

Without this fix, UUID strings (36 bytes) and other agent IDs exceed the
TPM2B_DATA capacity on SHA-256-only TPMs, causing TPM_RC_SIZE errors
during registration.

Bumps the pull-mode API version to 2.6.

Fixes: keylime#1226

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
@ansasaki ansasaki force-pushed the hash_before_certify branch from 9368744 to 81a9b9b Compare May 13, 2026 10:52
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packit-ci.fmf (1)

9-10: ⚠️ Potential issue | 🟠 Major

CI dependency should use canonical repository and immutable reference.

As noted in previous review, pointing to a personal fork branch makes CI non-reproducible and vulnerable to branch rewrites or removal. Once the companion registrar PR supporting hashed qualifying data is merged upstream, update these to reference the official Keylime repository and a stable tag or commit SHA.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packit-ci.fmf` around lines 9 - 10, Replace the personal fork and mutable
branch in the CI variables by pointing KEYLIME_UPSTREAM_URL to the official
Keylime repository (e.g. https://github.com/keylime/keylime.git) and set
KEYLIME_UPSTREAM_BRANCH to an immutable reference (a released tag or specific
commit SHA) once the upstream registrar PR is merged; update the variables
KEYLIME_UPSTREAM_URL and KEYLIME_UPSTREAM_BRANCH accordingly to ensure
reproducible builds.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packit-ci.fmf`:
- Around line 9-10: Replace the personal fork and mutable branch in the CI
variables by pointing KEYLIME_UPSTREAM_URL to the official Keylime repository
(e.g. https://github.com/keylime/keylime.git) and set KEYLIME_UPSTREAM_BRANCH to
an immutable reference (a released tag or specific commit SHA) once the upstream
registrar PR is merged; update the variables KEYLIME_UPSTREAM_URL and
KEYLIME_UPSTREAM_BRANCH accordingly to ensure reproducible builds.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c1717806-e85d-47b5-b723-5bfeb7a3f4f4

📥 Commits

Reviewing files that changed from the base of the PR and between 9368744 and 81a9b9b.

📒 Files selected for processing (8)
  • keylime-agent/src/api.rs
  • keylime-agent/src/main.rs
  • keylime-push-model-agent/src/registration.rs
  • keylime/src/agent_registration.rs
  • keylime/src/config/base.rs
  • keylime/src/registrar_client.rs
  • keylime/src/tpm.rs
  • packit-ci.fmf
💤 Files with no reviewable changes (1)
  • keylime-push-model-agent/src/registration.rs

Copy link
Copy Markdown
Contributor

@sarroutbi sarroutbi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM. Please, remember to drop [DO NOT MERGE](81a9b9b) commit before pushing

Copy link
Copy Markdown
Contributor

@sergio-correia sergio-correia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates, LGTM

@ansasaki ansasaki force-pushed the hash_before_certify branch from 81a9b9b to 6a6b104 Compare May 13, 2026 15:24
@ansasaki ansasaki merged commit d057ce3 into keylime:master May 13, 2026
9 of 14 checks passed
@ansasaki ansasaki deleted the hash_before_certify branch May 13, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants