// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "absl/random/internal/seed_material.h"

#include <fcntl.h>

#ifndef _WIN32
#include <unistd.h>
#else
#include <io.h>
#endif

#include <algorithm>
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include <cstring>

#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"

#if defined(__native_client__)

#include <nacl/nacl_random.h>
#define ABSL_RANDOM_USE_NACL_SECURE_RANDOM 1

#elif defined(_WIN32)

#include <windows.h>
#define ABSL_RANDOM_USE_BCRYPT 1
#pragma comment(lib, "bcrypt.lib")

#elif defined(__Fuchsia__)
#include <zircon/syscalls.h>

#endif

#if defined(__GLIBC__) && \
    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
// glibc >= 2.25 has getentropy()
#define ABSL_RANDOM_USE_GET_ENTROPY 1
#endif

#if defined(__EMSCRIPTEN__)
#include <sys/random.h>
// Emscripten has getentropy, but it resides in a different header.
#define ABSL_RANDOM_USE_GET_ENTROPY 1
#endif

#if defined(ABSL_RANDOM_USE_BCRYPT)
#include <bcrypt.h>

#ifndef BCRYPT_SUCCESS
#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
// Also link bcrypt; this can be done via linker options or:
// #pragma comment(lib, "bcrypt.lib")
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
namespace {

// Read OS Entropy for random number seeds.
// TODO(absl-team): Possibly place a cap on how much entropy may be read at a
// time.

#if defined(ABSL_RANDOM_USE_BCRYPT)

// On Windows potentially use the BCRYPT CNG API to read available entropy.
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
  BCRYPT_ALG_HANDLE hProvider;
  NTSTATUS ret;
  ret = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RNG_ALGORITHM,
                                    MS_PRIMITIVE_PROVIDER, 0);
  if (!(BCRYPT_SUCCESS(ret))) {
    ABSL_RAW_LOG(ERROR, "Failed to open crypto provider.");
    return false;
  }
  ret = BCryptGenRandom(
      hProvider,                                             // provider
      reinterpret_cast<UCHAR*>(values.data()),               // buffer
      static_cast<ULONG>(sizeof(uint32_t) * values.size()),  // bytes
      0);                                                    // flags
  BCryptCloseAlgorithmProvider(hProvider, 0);
  return BCRYPT_SUCCESS(ret);
}

#elif defined(ABSL_RANDOM_USE_NACL_SECURE_RANDOM)

// On NaCL use nacl_secure_random to acquire bytes.
bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
  auto buffer = reinterpret_cast<uint8_t*>(values.data());
  size_t buffer_size = sizeof(uint32_t) * values.size();

  uint8_t* output_ptr = buffer;
  while (buffer_size > 0) {
    size_t nread = 0;
    const int error = nacl_secure_random(output_ptr, buffer_size, &nread);
    if (error != 0 || nread > buffer_size) {
      ABSL_RAW_LOG(ERROR, "Failed to read secure_random seed data: %d", error);
      return false;
    }
    output_ptr += nread;
    buffer_size -= nread;
  }
  return true;
}

#elif defined(__Fuchsia__)

bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
  auto buffer = reinterpret_cast<uint8_t*>(values.data());
  size_t buffer_size = sizeof(uint32_t) * values.size();
  zx_cprng_draw(buffer, buffer_size);
  return true;
}

#else

#if defined(ABSL_RANDOM_USE_GET_ENTROPY)
// On *nix, use getentropy() if supported. Note that libc may support
// getentropy(), but the kernel may not, in which case this function will return
// false.
bool ReadSeedMaterialFromGetEntropy(absl::Span<uint32_t> values) {
  auto buffer = reinterpret_cast<uint8_t*>(values.data());
  size_t buffer_size = sizeof(uint32_t) * values.size();
  while (buffer_size > 0) {
    // getentropy() has a maximum permitted length of 256.
    size_t to_read = std::min<size_t>(buffer_size, 256);
    int result = getentropy(buffer, to_read);
    if (result < 0) {
      return false;
    }
    // https://github.com/google/sanitizers/issues/1173
    // MemorySanitizer can't see through getentropy().
    ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buffer, to_read);
    buffer += to_read;
    buffer_size -= to_read;
  }
  return true;
}
#endif  // defined(ABSL_RANDOM_GETENTROPY)

// On *nix, read entropy from /dev/urandom.
bool ReadSeedMaterialFromDevURandom(absl::Span<uint32_t> values) {
  const char kEntropyFile[] = "/dev/urandom";

  auto buffer = reinterpret_cast<uint8_t*>(values.data());
  size_t buffer_size = sizeof(uint32_t) * values.size();

  int dev_urandom = open(kEntropyFile, O_RDONLY);
  bool success = (-1 != dev_urandom);
  if (!success) {
    return false;
  }

  while (success && buffer_size > 0) {
    int bytes_read = read(dev_urandom, buffer, buffer_size);
    int read_error = errno;
    success = (bytes_read > 0);
    if (success) {
      buffer += bytes_read;
      buffer_size -= bytes_read;
    } else if (bytes_read == -1 && read_error == EINTR) {
      success = true;  // Need to try again.
    }
  }
  close(dev_urandom);
  return success;
}

bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
#if defined(ABSL_RANDOM_USE_GET_ENTROPY)
  if (ReadSeedMaterialFromGetEntropy(values)) {
    return true;
  }
#endif
  // Libc may support getentropy, but the kernel may not, so we still have
  // to fallback to ReadSeedMaterialFromDevURandom().
  return ReadSeedMaterialFromDevURandom(values);
}

#endif

}  // namespace

bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values) {
  assert(values.data() != nullptr);
  if (values.data() == nullptr) {
    return false;
  }
  if (values.empty()) {
    return true;
  }
  return ReadSeedMaterialFromOSEntropyImpl(values);
}

void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,
                         absl::Span<uint32_t> seed_material) {
  // Algorithm is based on code available at
  // https://gist.github.com/imneme/540829265469e673d045
  constexpr uint32_t kInitVal = 0x43b0d7e5;
  constexpr uint32_t kHashMul = 0x931e8875;
  constexpr uint32_t kMixMulL = 0xca01f9dd;
  constexpr uint32_t kMixMulR = 0x4973f715;
  constexpr uint32_t kShiftSize = sizeof(uint32_t) * 8 / 2;

  uint32_t hash_const = kInitVal;
  auto hash = [&](uint32_t value) {
    value ^= hash_const;
    hash_const *= kHashMul;
    value *= hash_const;
    value ^= value >> kShiftSize;
    return value;
  };

  auto mix = [&](uint32_t x, uint32_t y) {
    uint32_t result = kMixMulL * x - kMixMulR * y;
    result ^= result >> kShiftSize;
    return result;
  };

  for (const auto& seq_val : sequence) {
    for (auto& elem : seed_material) {
      elem = mix(elem, hash(seq_val));
    }
  }
}

absl::optional<uint32_t> GetSaltMaterial() {
  // Salt must be common for all generators within the same process so read it
  // only once and store in static variable.
  static const auto salt_material = []() -> absl::optional<uint32_t> {
    uint32_t salt_value = 0;

    if (random_internal::ReadSeedMaterialFromOSEntropy(
            MakeSpan(&salt_value, 1))) {
      return salt_value;
    }

    return absl::nullopt;
  }();

  return salt_material;
}

}  // namespace random_internal
ABSL_NAMESPACE_END
}  // namespace absl
