tryLoadLibCrypto function

DynamicLibrary? tryLoadLibCrypto({
  1. StringBuffer? loadedPath,
})

Try to open libcrypto from the path in _envVar, then from _candidates.

Returns a DynamicLibrary on the first successful load, or null if every candidate fails. Never throws.

at_chops does not call this automatically — consumers decide their own fallback strategy. Pass the returned library to an FFI-backed algorithm's .fromLib constructor (e.g. MlKem768FfiAlgo.fromLib, X25519FfiAlgo.fromLib, AesGcm256FfiAlgo.fromLib).

If loadedPath is provided it will be set to the path that was successfully opened, which callers can use to verify whether the env-var path or a fallback candidate was used.

Implementation

DynamicLibrary? tryLoadLibCrypto({StringBuffer? loadedPath}) {
  final envPath = Platform.environment[_envVar];
  if (envPath != null) {
    final lib = _tryOpen(envPath);
    if (lib != null) {
      loadedPath?.write(envPath);
      return lib;
    }
    // The env var was set but the path failed to open. The most common cause
    // is pointing at a versioned symlink (e.g. libcrypto.so.3): the dynamic
    // linker resolves its baked-in SONAME against system paths and may find an
    // older system OpenSSL instead of the intended one.
    // Fix: set $_envVar to the real .so file — resolve symlinks first:
    //   export $_envVar=$(realpath /your/openssl/lib/libcrypto.so.3)
    stderr.writeln(
      'at_chops warning: $_envVar="$envPath" is set but could not be opened. '
      'Falling back to system candidates. '
      'Tip: if the path is a versioned symlink, point to the real file instead: '
      'export $_envVar=\$(realpath "$envPath")',
    );
  }
  for (final path in _candidates) {
    final lib = _tryOpen(path);
    if (lib != null) {
      loadedPath?.write(path);
      return lib;
    }
  }
  return null;
}