FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Curve25519 CryptoCb fix by Frauschi · Pull Request #11308 · wolfSSL/wolfssl · GitHub

Curve25519 CryptoCb fix - #11308

Open
Frauschi wants to merge 2 commits into
wolfSSL:masterfrom
Frauschi:curve25519-cryptocb-fix
Open

Curve25519 CryptoCb fix#11308
Frauschi wants to merge 2 commits into
wolfSSL:masterfrom
Frauschi:curve25519-cryptocb-fix

Conversation

Copy link
Copy Markdown
Contributor

Description

wc_CryptoCb_Curve25519MakePub() took no devId. It looked up INVALID_DEVID and then fell back to wc_CryptoCb_FindDeviceByIndex(0), so it always landed on whichever device was registered first. Every route to an X25519 public point derivation went through it, so a key created with wc_curve25519_init_ex(&key, heap, myDevId) had its private scalar offered to a device the application never selected, with no way to opt out. wc_CryptoCb_Curve25519Generic() had the same shape. This mirrors what #11209 did for curve448.

  • Both functions take a leading int devId, and the index-0 fallback is gated on devId == INVALID_DEVID. Both are WOLFSSL_LOCAL, so no public ABI change.
  • wc_curve25519_make_key() and wc_curve25519_export_public_ex() derive the point through a new curve25519_key_make_pub() that passes the key's devId and only allows the callback when the key is actually bound to a device. The keyless public API keeps its old behaviour, having no key to take a devId from.
  • Under WOLFSSL_CURVE25519_BLINDING both wc_curve25519_make_pub() and wc_curve25519_generic() fall through to their blinded variant after the callback declines, and that variant dispatched to the same device again, showing a declining device the scalar twice. The inner call now runs with the callback disabled.

Second commit, independent: curve25519_keyagree_test() fills pubKey inside a block guarded on HAVE_CURVE25519_KEY_EXPORT, but the block computing a shared secret against pubKey required only the import, so NO_CURVE25519_KEY_EXPORT builds failed in testwolfcrypt. curve448_keyagree_test() has the identical defect. Both consuming guards now require the export.

Behaviour change: under WOLF_CRYPTO_CB_ONLY_CURVE25519, an unbound key passed to wc_curve25519_export_public_ex() now returns NO_VALID_DEVID instead of reaching the first registered device, since there is no software fallback. Such builds must use wc_curve25519_init_ex() with a real devId. wc_curve25519_make_key() already behaved this way. Documented as a \return.

Testing

New test_wc_curve25519_cryptocb registers two spy devices, the decoy first so it holds the slot the old fallback would have picked, and covers a key bound to device A (B sees nothing), a key naming an unregistered devId, an unbound key on both the keygen and export paths, and the keyless APIs. Each derived point is compared against the one keygen produced.

Proofs rather than claims:

  • Reverting just the && (devId == INVALID_DEVID) term makes the new test fail; restoring it passes.
  • A callback that declines everything was dispatched 2x per call before the blinding fix and 1x after.
  • The new MC/DC vector in test_cryptocb_whitebox.c uses WB_DEVID_NOCB so the first two operands genuinely sit at (F,T) and only the third changes, giving unique-cause rather than masking MC/DC. Confirmed by instrumenting the decision.

make check green (17 pass / 6 skip / 0 fail) on --enable-all --enable-cryptocb and on the same with --disable-armasm. The second leg matters: WOLFSSL_CURVE25519_BLINDING is only auto-enabled when ARMASM is off, so on aarch64 a plain --enable-all compiles none of the blinded paths this PR touches. testwolfcrypt also passes with -DNO_CURVE25519_KEY_EXPORT and with -DNO_CURVE448_KEY_EXPORT.

New CI entry cryptocb-curve25519-no-key-export covers a build with the X25519 export compiled out, which nothing in CI compiled before. wolfCrypt only, because src/internal.c and src/tls.c call wc_curve25519_export_public_ex() unconditionally and TLS cannot link without it. It carries its own cflags adding -Werror (a per-entry value replaces the job's --cflags), so an unreferenced static fails the build. Narrowing curve25519_key_make_pub()'s guard makes that entry fail, so it has teeth.

Frauschi self-assigned this Aug 28, 2026

Copy link
Copy Markdown

Can one of the admins verify this patch?

github-actions Bot commented Aug 28, 2026
edited
Loading

Copy link
Copy Markdown

Frauschi force-pushed the curve25519-cryptocb-fix branch from 4e65e4c to 0a9a933 Compare August 28, 2026 14:13

wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Fenrir Automated Review — PR #11308

Scan targets checked: wolfcrypt-bugs, wolfcrypt-port-bugs, wolfcrypt-rs-bugs, wolfcrypt-src, wolfssl-bugs, wolfssl-src

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread tests/api/test_curve25519.c Outdated
wc_CryptoCb_Curve25519MakePub took no devId and resolved its device with a
lookup for INVALID_DEVID, falling back to the first registered device. Every
route to an X25519 public point derivation went through it, so a key bound to
one device had its private scalar offered to whichever device happened to be
registered first, with no way to opt out.

Give both wc_CryptoCb_Curve25519MakePub and wc_CryptoCb_Curve25519Generic a
devId parameter and let only a caller that selected no device settle for the
first registered one, matching the curve448 siblings. wc_curve25519_make_key
and wc_curve25519_export_public_ex now derive the point through a devId
carrying helper instead of the keyless public API; the keyless API itself
keeps its old behaviour since it has no key to take a devId from.

Under WOLFSSL_CURVE25519_BLINDING both wc_curve25519_make_pub and
wc_curve25519_generic fall through to their blinded variant after the
callback declined, which dispatched the same private scalar to the same
device a second time. The blinded call now runs with the callback disabled,
so a declining device is offered the scalar once.

Under WOLF_CRYPTO_CB_ONLY_CURVE25519 an unbound key passed to
wc_curve25519_export_public_ex now returns NO_VALID_DEVID rather than
reaching the first registered device. Such builds must create keys with
wc_curve25519_init_ex and a real devId.
…test

curve25519_keyagree_test and curve448_keyagree_test fill pubKey by exporting
userA's public point and importing it back, inside a block guarded on the key
export. The block that then computes a shared secret against pubKey is guarded
on the shared secret and the key import alone, so building with
NO_CURVE25519_KEY_EXPORT or NO_CURVE448_KEY_EXPORT leaves it running against a
key that never received a public point, and testwolfcrypt fails.

Require the export in the consuming block too, and add a CI entry building
wolfCrypt with the X25519 export compiled out so the combination stays
covered. That entry is wolfCrypt only, since src/internal.c and src/tls.c
call wc_curve25519_export_public_ex unconditionally and TLS therefore cannot
link without it, and it carries its own -Werror so an unreferenced static
fails the build rather than passing as a warning.
Frauschi force-pushed the curve25519-cryptocb-fix branch from 0a9a933 to c4b1838 Compare August 28, 2026 21:02
Comment thread tests/api/test_curve25519.c Outdated

wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Fenrir Automated Review — PR #11308

Scan targets checked: wolfcrypt-bugs, wolfcrypt-port-bugs, wolfcrypt-rs-bugs, wolfcrypt-src, wolfssl-bugs, wolfssl-src

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

wolfSSL-Fenrir-bot dismissed their stale review August 29, 2026 09:31

Fenrir's latest completed scan found no issues; clearing the prior automated change request.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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


Back | FazBrowse Home | New Git URL