absl::Status Initialize()

in kmsp11/main/bridge.cc [59:121]


absl::Status Initialize(CK_VOID_PTR pInitArgs) {
  auto* init_args = static_cast<CK_C_INITIALIZE_ARGS*>(pInitArgs);
  if (init_args) {
    if ((init_args->flags & CKF_OS_LOCKING_OK) != CKF_OS_LOCKING_OK &&
        (init_args->CreateMutex || init_args->DestroyMutex ||
         init_args->LockMutex || init_args->UnlockMutex)) {
      return NewInvalidArgumentError("library requires os locking",
                                     CKR_CANT_LOCK, SOURCE_LOCATION);
    }
    if ((init_args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) ==
        CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
      return NewInvalidArgumentError("library requires thread creation",
                                     CKR_NEED_TO_CREATE_THREADS,
                                     SOURCE_LOCATION);
    }
  }

  LibraryConfig config;
  if (init_args && init_args->pReserved) {
    // This behavior isn't part of the spec, but there are numerous libraries
    // in the wild that allow specifying a config file in pInitArgs->pReserved.
    // There's also support for providing config this way in the OpenSSL engine:
    // https://github.com/OpenSC/libp11/blob/4084f83ee5ea51353facf151126b7d6d739d0784/src/eng_front.c#L62
    ASSIGN_OR_RETURN(
        config, LoadConfigFromFile(static_cast<char*>(init_args->pReserved)));
  } else {
    ASSIGN_OR_RETURN(config, LoadConfigFromEnvironment());
  }

  // Registering fork handlers is a one-time operation.
  if (!config.skip_fork_handlers()) {
    static const absl::Status kForkHandlersRegistered = RegisterForkHandlers();
    RETURN_IF_ERROR(kForkHandlersRegistered);
  }

  Provider* existing_provider = GetGlobalProvider();
  if (existing_provider) {
    return FailedPreconditionError("the library is already initialized",
                                   CKR_CRYPTOKI_ALREADY_INITIALIZED,
                                   SOURCE_LOCATION);
  }

  CHECK(kCryptoLibraryInitialized);
  if (config.require_fips_mode()) {
    absl::Status self_test_result = CheckFipsSelfTest();
    CHECK(self_test_result.ok()) << "FIPS tests failed: " << self_test_result;
  }

  // Provider::New emits info log messages (for example, noting that a CKV is
  // being skipped due to state DISABLED), so logging should be initialized
  // before it is invoked.
  RETURN_IF_ERROR(
      InitializeLogging(config.log_directory(), config.log_filename_suffix()));

  absl::StatusOr<std::unique_ptr<Provider>> new_provider =
      Provider::New(config);
  if (!new_provider.ok()) {
    ShutdownLogging();
    return new_provider.status();
  }

  return SetGlobalProvider(std::move(new_provider).value());
}