Skip to content

tree_jitter_zeroize_drbg crashes on Windows when AWS-LC is built as a static library and linked into a third-party DLL #3540

Description

@benrushcc

Problem:
On Windows, when AWS-LC is built as a static library (BORINGSSL_SHARED_LIBRARY undefined) and then linked into a third-party DLL, the process can crash during DLL_PROCESS_DETACH.

In crypto/fipsmodule/rand/entropy/tree_drbg_jitter_entropy.c:

// Windows shared builds take the zeros option: there this runs from a libcrypto
// global destructor on |DLL_PROCESS_DETACH|, after |ExitProcess|, where
// |CRYPTO_sysrand| faults on bcryptprimitives.dll (loaded on demand, so not
// kept alive by libcrypto's dependency graph). Static builds run it from the
// executable's |atexit| and are unaffected. Zeros still override every state in
// the tree, losing only the defence in depth above, which the write-locked
// frontend DRBGs already cover.

// tree_jitter_zeroize_drbg zeroizes the DRBG state configured in
// |tree_jitter_drbg|.
static void tree_jitter_zeroize_drbg(
  struct tree_jitter_drbg_t *tree_jitter_drbg) {

  uint8_t random_data[CTR_DRBG_ENTROPY_LEN];
#if defined(OPENSSL_WINDOWS) && defined(BORINGSSL_SHARED_LIBRARY)
  OPENSSL_memset(random_data, 0, CTR_DRBG_ENTROPY_LEN);
#else
  CRYPTO_sysrand_if_available(random_data, CTR_DRBG_ENTROPY_LEN);
#endif

  if (CTR_DRBG_reseed(&(tree_jitter_drbg->drbg), random_data, NULL, 0) != 1) {
    abort();
  }
  OPENSSL_cleanse(random_data, CTR_DRBG_ENTROPY_LEN);
  tree_jitter_drbg->reseed_calls_since_initialization += 1;
}

The existing guard only covers the case where AWS-LC itself is built as a shared library. It does not cover the case where a static AWS-LC is embedded into another DLL.

When AWS-LC is compiled statically, BORINGSSL_SHARED_LIBRARY is not defined, so tree_jitter_zeroize_drbg takes the #else branch and calls CRYPTO_sysrand_if_available. If that static library is linked into a third-party DLL, the zeroization path can still be triggered during DLL_PROCESS_DETACH (e.g. via thread-local frontend DRBG destructors). At that point CRYPTO_sysrand_if_available may fault on bcryptprimitives.dll, because that DLL is loaded on demand and may already be unavailable. Result: access violation during process exit.

The existing comment acknowledges this problem for Windows shared builds, but assumes static builds always end up in an executable. It does not account for the static-library-into-DLL case.

Reproduction:

Build AWS-LC as a static library on Windows (e.g. MSYS2 UCRT64 + Clang), without defining BORINGSSL_SHARED_LIBRARY.

Link libcrypto.a into a third-party DLL.

Call an AWS-LC randomness API from that DLL so the tree-jitter DRBG is initialized.

Unload the DLL or exit the process.

Observe an access violation in CRYPTO_sysrand / bcryptprimitives.dll.

Solution:
Broaden the guard so all Windows builds use the zeros option:

#if defined(OPENSSL_WINDOWS)
  OPENSSL_memset(random_data, 0, CTR_DRBG_ENTROPY_LEN);
#else
  CRYPTO_sysrand_if_available(random_data, CTR_DRBG_ENTROPY_LEN);
#endif

Zeros still override every state in the tree. The only thing lost is the additional defence in depth of using random data, which the write-locked frontend DRBGs already cover. No security property is weakened.

Does this change any public APIs? No.

Which algorithm(s) will this impact? Tree-jitter DRBG zeroization only. No cryptographic behavior changes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions