Skip to content

Add initial support for crypto callbacks.#114

Open
roberthdevries wants to merge 2 commits intowolfSSL:masterfrom
roberthdevries:add-support-for-crypto-callbacks
Open

Add initial support for crypto callbacks.#114
roberthdevries wants to merge 2 commits intowolfSSL:masterfrom
roberthdevries:add-support-for-crypto-callbacks

Conversation

@roberthdevries
Copy link
Copy Markdown
Contributor

This patch does not add support for types of callbacks. Adding support for callbacks for cipher functions is complicated by issues with cffi code generation for the wc_CryptoInfo structure with two layers of anonymous unions.
Uncommenting more parts of the cipher struct causes errors regarding conflicting struct sizes of other parts of the wc_CryptoInfo struct.
Cffi cdef and the compiler seem to disagree.

However as it is, callbacks work for random and hash functions.

Copy link
Copy Markdown
Contributor

@JeremiahM37 JeremiahM37 left a comment

Choose a reason for hiding this comment

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

Skoll Code Review

Scan type: review
Overall recommendation: REQUEST_CHANGES
Findings: 14 total — 9 posted, 5 skipped
7 finding(s) posted as inline comments (see file-level comments below)

Posted findings

  • [High] Importing wolfcrypt fails when CRYPTO_CB is disabled at build timewolfcrypt/__init__.py:49 and wolfcrypt/cryptocb.py:33-58
  • [High] Double unregister of device on context-manager exit + GCwolfcrypt/cryptocb.py:73-77, 117-118
  • [Medium] Return value of wolfCrypt_Init not checkedwolfcrypt/__init__.py:52
  • [Medium] Debug print() statements left in production callback dispatcherwolfcrypt/cryptocb.py:80, 84, 85, 107, 111
  • [Medium] Hash digest dict KeyError on unmapped hash typeswolfcrypt/cryptocb.py:84, 90
  • [Medium] Digest output buffer not size-validatedwolfcrypt/cryptocb.py:90
  • [Medium] RNG output length not validatedwolfcrypt/cryptocb.py:96-97
  • [Medium] No tests for hash callbacks despite PR claimtests/test_cryptocb.py
  • [Low] Free-floating string literal used as 'comment' in build_ffi.py is misleadingscripts/build_ffi.py:1376-1412

Skipped findings

  • [Medium] Anonymous-union cdef relies on '...' partial layout — may not match reality
  • [Low] ctx==NULL fallback would never be reached — wrong return code
  • [Low] Type annotations on overridable methods declare positional args with leading underscores
  • [Low] rng_callback signature passes raw cffi pointer with no type annotation
  • [Info] Stale exception import in init.py guard

Review generated by Skoll

Comment thread wolfcrypt/cryptocb.py Outdated
def __enter__(self) -> Self:
return self

def __exit__(self, exc_type, exc_value, traceback) -> None:
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.

🔴 [High] Double unregister of device on context-manager exit + GC

Both __exit__ and __del__ call self._unregister(). When used as a context manager (the test does exactly this: with RngCryptoCallback(10): ...), the device is unregistered on __exit__ and again later when the object is garbage-collected. If a second CryptoCallback was registered with the same device_id between exit and GC (a reasonable usage pattern, e.g., in successive tests), the GC-time unregister will rip out the live registration belonging to the new object, causing test pollution / NULL callback dispatch. There is also no flag to record "already unregistered."

def __exit__(self, exc_type, exc_value, traceback) -> None:
    self._unregister()

def __del__(self) -> None:
    self._unregister()

def _unregister(self) -> None:
    _lib.wc_CryptoCb_UnRegisterDevice(self.device_id)

Recommendation: Track registration state with a _registered flag, set it to False after unregistering, and follow the same try/except AttributeError pattern used by Random.__del__ in wolfcrypt/random.py to avoid errors during interpreter shutdown.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The tracking of the registration is done in the wolfcrypt library itself. Unregistering a device twice is a noop.
__del__ is not certain to be called at any time soon (unless a gc.collect() call is done explicitly) so if more fine-grained control is required to control the lifespan of the callback, a context manager is the typical solution in Python.

So the unregister in __exit__ must not be removed.

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.

wc_CryptoCb_UnRegisterDevice looks up by devId only — no ownership check (cryptocb.c:428). The double-unregister is only a no-op if the slot is still INVALID_DEVID at the second call. In the cross-instance case (cb1 exits → cb2 registers same devId → cb1 GC'd), cb1's del will find cb2's live slot and ClearDev it. A _registered flag in del avoids this without removing exit's unregister.

Comment thread wolfcrypt/__init__.py Outdated
Comment thread wolfcrypt/cryptocb.py Outdated
Comment thread wolfcrypt/cryptocb.py
Comment thread wolfcrypt/cryptocb.py
Comment thread wolfcrypt/cryptocb.py
Comment thread scripts/build_ffi.py Outdated
* Comment out code in build_ffi.py instead of quoted string.
* Check return value of wolfCrypt_init()
* Complete algorithm type hash table
* Change dicts into defaultdicts with a sensible value when key is missing.
* Convert debug print to debug log messages
* Add length checks to produce nicer exceptions.
Comment thread wolfcrypt/cryptocb.py

from wolfcrypt.exceptions import WolfCryptError

ALGO_TYPE_NAME: Final = defaultdict(
Copy link
Copy Markdown
Contributor

@JeremiahM37 JeremiahM37 Apr 29, 2026

Choose a reason for hiding this comment

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

Module-level dicts read _lib.WC_ALGO_TYPE_* / _lib.WC_HASH_TYPE_* at import, but those are only in the cdef when CRYPTO_CB is enabled — so import wolfcrypt.cryptocb fails with AttributeError before reaching the if _lib.CRYPTO_CB_ENABLED: guard. Move the dicts inside the guard, and make the CryptoCallback import in wolfcrypt/__init__.py conditional too.

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