Skip to content

feat(duvet): RFC 8032 (EdDSA) requirement coverage + annotation-regression CI - #3477

Open
dougch wants to merge 9 commits into
aws:mainfrom
dougch:duvet-demo
Open

dougch wants to merge 9 commits into
aws:mainfrom
dougch:duvet-demo

Conversation

@dougch

@dougch dougch commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Context and motivation

Requirement-to-code traceability makes it visible which spec requirements are actually implemented and tested, and keeps that link from silently rotting. This PR is a focused demonstration on the EdDSA surface; it does not publish a report or gate on full coverage.

Description of changes

Adds a scoped Duvet setup that traces RFC 8032 (EdDSA) requirements to the Ed25519 / Ed25519ph implementation and tests in crypto/fipsmodule/curve25519/, plus a CI check that fails when a requirement annotation is removed.

Duvet links each normative spec requirement to the source that implements and tests it, via in-tree //= citation annotations, and reports coverage.

Contents

  • .duvet/config.toml — source patterns, the RFC 8032 spec, requirement patterns, report config.
  • .duvet/requirements/ — requirements extracted from RFC 8032 prose (duvet extract).
  • .duvet/rfc8032-requirements/ — a few descriptive (non-RFC-2119) statements pinned by hand.
  • //= citations in curve25519.c and matching type=test citations in ed25519_test.cc.
  • .duvet/README.md — layout, links, and how to generate reports locally.
  • .duvet/scripts/check_annotations.py + .duvet/annotations.baseline — annotation-regression guard.
  • .github/workflows/duvet.yml — runs the guard on PRs touching .duvet/ or the annotated source, and uploads the HTML report as an artifact.

Testing

The Duvet Annotation Coverage workflow installs Duvet (cargo install duvet --locked, matching the existing check-test-vectors workflow) and runs the regression guard:

  • Fails when any baselined //= citation is removed or broken.
  • Ignores newly added annotations (prints a reminder to refresh the baseline).

Refresh the baseline after intentional changes:

python3 .duvet/scripts/check_annotations.py --update

Generated reports live under .duvet/reports/ and are gitignored — nothing is published.

Sample local report

Screenshot showing the RFC passage and the associated line in the code where this is implemented. Note the missing test, which doesn't mean we're not testing, but that the annotation hasn't been created.
Screenshot 2026-09-02 at 10 40 10

Review considerations

  • Uses a committed baseline diff rather than duvet report --ci (which demands 100% coverage) so the check targets removals without forcing every extracted requirement to be cited.
  • The section-8.7 implementation citation is not yet paired with a test; tracked in the README TODOs.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

@dougch
dougch requested a review from a team as a code owner September 2, 2026 17:38
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

🔒 Security ReviewView Report

Please review before merging.

Wire Duvet coverage for the Ed25519 / Ed25519ph surface in
crypto/fipsmodule/curve25519/. Requirements are extracted from RFC 8032
prose, with a few descriptive (non-RFC-2119) statements hand-authored in
rfc8032-requirements/. Source is annotated with //= citations and matching
type=test annotations. Adds .duvet/README.md covering layout and local
report generation. Reports are gitignored, not published.
Add check_annotations.py, which snapshots the source-code //= citations
Duvet parses and fails when any baselined annotation is removed or broken.
Adding annotations never fails; refresh the baseline with --update. The
Duvet Annotation Coverage workflow runs the check on PRs touching .duvet/
or the annotated source and uploads the HTML report as an artifact.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

Comment thread crypto/fipsmodule/curve25519/curve25519.c
Comment thread crypto/fipsmodule/curve25519/curve25519.c
Comment thread crypto/fipsmodule/curve25519/curve25519.c
@codecov-commenter

codecov-commenter commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.20%. Comparing base (fac7cb9) to head (61e8c4d).
⚠️ Report is 41 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3477      +/-   ##
==========================================
+ Coverage   78.02%   78.20%   +0.17%     
==========================================
  Files         700      700              
  Lines      125037   125886     +849     
  Branches    17343    17411      +68     
==========================================
+ Hits        97563    98452     +889     
+ Misses      26605    26563      -42     
- Partials      869      871       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

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

sgmenda
sgmenda previously approved these changes Sep 14, 2026

@sgmenda sgmenda left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm sans nits

Comment thread .github/workflows/duvet.yml Outdated
Comment thread .duvet/scripts/check_annotations.py Outdated
Duvet releases to Crates are lagging- but this could be a forcing function, so agree.

Co-authored-by: Sanketh Menda <sgmenda@amazon.com>
Co-authored-by: Sanketh Menda <sgmenda@amazon.com>
@dougch
dougch requested a review from sgmenda September 14, 2026 17:19
sgmenda
sgmenda previously approved these changes Sep 14, 2026

@sgmenda sgmenda left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

Declares FIPS_service_indicator_lock/unlock_state directly instead of
relying on bcm.c amalgamation include order. Silences clang-tidy
implicit-function-declaration on standalone/diff analysis.
The regression check diffed a multiset keyed only on
(target#section, kind, source_file). Two distinct citations to the same
triple (e.g. curve25519.c cites rfc8032#section-5.1 on both ED25519_sign
and ED25519ph_sign) collided: deleting one while adding another to the
same triple netted to zero and CI reported OK, masking the removal.

Include the duvet-reported source line in the key so same-triple
citations are distinct. duvet does not carry the quoted //# text on
source citations, so line is the only available disambiguator; baseline
regenerated to the 4-column format.
sgmenda
sgmenda previously approved these changes Sep 16, 2026

@sgmenda sgmenda left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm

Bare --version 0.4 fails cargo arg-parsing (needs full X.Y.Z or an
explicit comparator like ^0.4).
@dougch

dougch commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

clang-tidy made some suggestions
#3514

dougch added a commit that referenced this pull request Sep 16, 2026
### Issues:
No GitHub issue. Root cause surfaced by the clang-tidy run on #3477 (RFC
8032 Duvet annotations), which added comment lines adjacent to these
calls and re-triggered a pre-existing `implicit-function-declaration`
warning. This PR fixes the underlying cause independently of that
annotation work.

### Description of changes:
`crypto/fipsmodule/curve25519/curve25519.c` calls
`FIPS_service_indicator_lock_state()` /
`FIPS_service_indicator_unlock_state()` but does not include the header
that declares them, `crypto/fipsmodule/service_indicator/internal.h`.
Nothing in its existing include chain reaches that header (the public
`<openssl/service_indicator.h>` does not declare the lock/unlock
functions), so the calls rely on an implicit function declaration.

This change adds `#include "../service_indicator/internal.h"`, matching
the 12 other fipsmodule translation units that use these functions (e.g.
`hmac.c`, `ec_key.c`, `ecdh.c`, `e_aesccm.c`).

### Call-outs:
- No functional change today: in FIPS builds the module links as a unit
and the real symbol resolves; the assumed `int f()` prototype vs. actual
`void f(void)` is harmless for a no-arg call.
- The fix matters as latent correctness: implicit declarations are a
hard error under C23 / newer clang, and in non-FIPS builds the missing
include bypasses the intended `OPENSSL_INLINE` no-op definition.

### Testing:
No new tests. Covered by existing curve25519/Ed25519 suites; the change
only makes an already-used declaration visible. Verified the include
path matches sibling fipsmodule files.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
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