// Copyright (c) 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/blind_sign_auth/blind_sign_auth.h"

#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/cleanup/cleanup.h"
#include "absl/functional/bind_front.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "anonymous_tokens/cpp/crypto/crypto_utils.h"
#include "anonymous_tokens/cpp/privacy_pass/rsa_bssa_public_metadata_client.h"
#include "anonymous_tokens/cpp/privacy_pass/token_encodings.h"
#include "anonymous_tokens/cpp/shared/proto_utils.h"
#include "quiche/blind_sign_auth/blind_sign_auth_interface.h"
#include "quiche/blind_sign_auth/blind_sign_auth_protos.h"
#include "quiche/blind_sign_auth/blind_sign_message_interface.h"
#include "quiche/blind_sign_auth/blind_sign_message_response.h"
#include "quiche/blind_sign_auth/blind_sign_tracing_hooks.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/quiche_random.h"

namespace quiche {
namespace {

constexpr absl::string_view kIssuerHostname =
    "https://ipprotection-ppissuer.googleapis.com";
constexpr size_t kExpectedExtensionTypesSize = 5;
constexpr std::array<const uint16_t, kExpectedExtensionTypesSize>
    kExpectedExtensionTypes = {0x0001, 0x0002, 0xF001, 0xF002, 0xF003};

using google::protobuf::Any;
using privacy::ppn::AndroidAttestationData;
using privacy::ppn::AttestAndSignRequest;
using privacy::ppn::AttestAndSignResponse;
using privacy::ppn::AttestationData;
using privacy::ppn::AuthAndSignRequest;
using privacy::ppn::AuthAndSignResponse;
using privacy::ppn::GetInitialDataRequest;
using privacy::ppn::GetInitialDataResponse;
using privacy::ppn::PrivacyPassTokenData;
using anonymous_tokens::AnonymousTokensUseCase;
using anonymous_tokens::CreatePublicKeyRSA;
using anonymous_tokens::DecodeExtensions;
using anonymous_tokens::ExpirationTimestamp;
using anonymous_tokens::ExtendedTokenRequest;
using anonymous_tokens::Extensions;
using anonymous_tokens::GeoHint;
using anonymous_tokens::MarshalTokenChallenge;
using anonymous_tokens::ParseUseCase;
using anonymous_tokens::
    PrivacyPassRsaBssaPublicMetadataClient;
using anonymous_tokens::RSAPublicKey;
using anonymous_tokens::Token;
using anonymous_tokens::TokenChallenge;
using anonymous_tokens::ValidateExtensionsOrderAndValues;

}  // namespace

void BlindSignAuth::GetTokens(std::optional<std::string> oauth_token,
                              int num_tokens, ProxyLayer proxy_layer,
                              BlindSignAuthServiceType service_type,
                              SignedTokenCallback callback,
                              std::unique_ptr<BlindSignTracingHooks> hooks) {
  if (hooks != nullptr) {
    hooks->OnGetInitialDataStart();
  }
  // Create GetInitialData RPC.
  GetInitialDataRequest request;
  request.set_use_attestation(false);
  request.set_service_type(BlindSignAuthServiceTypeToString(service_type));
  request.set_location_granularity(
      privacy::ppn::GetInitialDataRequest_LocationGranularity_CITY_GEOS);
  // Validation version must be 2 to use ProxyLayer.
  request.set_validation_version(2);
  request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(proxy_layer));

  // Call GetInitialData on the BlindSignMessageInterface Fetcher.
  std::string body_bytes = request.SerializeAsString();
  BlindSignMessageCallback initial_data_callback = absl::bind_front(
      &BlindSignAuth::GetInitialDataCallback, this, oauth_token, num_tokens,
      proxy_layer, service_type, std::move(callback), std::move(hooks));
  fetcher_->DoRequest(BlindSignMessageRequestType::kGetInitialData, oauth_token,
                      body_bytes, std::move(initial_data_callback));
}

void BlindSignAuth::GetInitialDataCallback(
    std::optional<std::string> oauth_token, int num_tokens,
    ProxyLayer proxy_layer, BlindSignAuthServiceType service_type,
    SignedTokenCallback callback, std::unique_ptr<BlindSignTracingHooks> hooks,
    absl::StatusOr<BlindSignMessageResponse> response) {
  if (hooks != nullptr) {
    hooks->OnGetInitialDataEnd();
  }
  absl::StatusOr<GetInitialDataResponse> initial_data_response =
      ParseGetInitialDataResponseMessage(response);
  if (!initial_data_response.ok()) {
    std::move(callback)(initial_data_response.status());
    return;
  }

  // Create token signing requests.
  const bool use_privacy_pass_client =
      initial_data_response->has_privacy_pass_data() &&
      auth_options_.enable_privacy_pass();

  if (use_privacy_pass_client) {
    QUICHE_DVLOG(1) << "Using Privacy Pass client";
    GeneratePrivacyPassTokens(*initial_data_response, std::move(oauth_token),
                              num_tokens, proxy_layer, service_type,
                              std::move(callback), std::move(hooks));
  } else {
    QUICHE_LOG(ERROR) << "Non-Privacy Pass tokens are no longer supported";
    std::move(callback)(absl::UnimplementedError(
        "Non-Privacy Pass tokens are no longer supported"));
    return;
  }
}

void BlindSignAuth::GeneratePrivacyPassTokens(
    privacy::ppn::GetInitialDataResponse initial_data_response,
    std::optional<std::string> oauth_token, int num_tokens,
    ProxyLayer proxy_layer, BlindSignAuthServiceType service_type,
    SignedTokenCallback callback,
    std::unique_ptr<BlindSignTracingHooks> hooks) {
  absl::StatusOr<PrivacyPassContext> pp_context =
      CreatePrivacyPassContext(initial_data_response);
  if (!pp_context.ok()) {
    std::move(callback)(pp_context.status());
    return;
  }

  // Create token challenge.
  TokenChallenge challenge;
  challenge.issuer_name = kIssuerHostname;
  absl::StatusOr<std::string> token_challenge =
      MarshalTokenChallenge(challenge);
  if (!token_challenge.ok()) {
    QUICHE_LOG(WARNING) << "Failed to marshal token challenge: "
                        << token_challenge.status();
    std::move(callback)(
        absl::InvalidArgumentError("Failed to marshal token challenge"));
    return;
  }

  if (hooks != nullptr) {
    hooks->OnGenerateBlindedTokenRequestsStart();
  }
  absl::StatusOr<GeneratedTokenRequests> token_requests_data =
      GenerateBlindedTokenRequests(num_tokens, *pp_context->rsa_public_key,
                                   *token_challenge, pp_context->token_key_id,
                                   pp_context->extensions);
  if (hooks != nullptr) {
    hooks->OnGenerateBlindedTokenRequestsEnd();
  }
  if (!token_requests_data.ok()) {
    std::move(callback)(token_requests_data.status());
    return;
  }

  AuthAndSignRequest sign_request;
  sign_request.set_service_type(BlindSignAuthServiceTypeToString(service_type));
  sign_request.set_key_type(privacy::ppn::AT_PUBLIC_METADATA_KEY_TYPE);
  sign_request.set_key_version(
      initial_data_response.at_public_metadata_public_key().key_version());
  *sign_request.mutable_blinded_token() = {
      token_requests_data->privacy_pass_blinded_tokens_b64.begin(),
      token_requests_data->privacy_pass_blinded_tokens_b64.end()};
  sign_request.mutable_public_metadata_extensions()->assign(
      initial_data_response.privacy_pass_data().public_metadata_extensions());
  // TODO(b/295924807): deprecate this option after AT server defaults to it
  sign_request.set_do_not_use_rsa_public_exponent(true);
  sign_request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(proxy_layer));

  if (hooks != nullptr) {
    hooks->OnAuthAndSignStart();
  }
  BlindSignMessageCallback auth_and_sign_callback =
      absl::bind_front(&BlindSignAuth::PrivacyPassAuthAndSignCallback, this,
                       *std::move(pp_context),
                       std::move(token_requests_data->privacy_pass_clients),
                       std::move(callback), std::move(hooks));
  // TODO(b/304811277): remove other usages of string.data()
  fetcher_->DoRequest(BlindSignMessageRequestType::kAuthAndSign, oauth_token,
                      sign_request.SerializeAsString(),
                      std::move(auth_and_sign_callback));
}

void BlindSignAuth::PrivacyPassAuthAndSignCallback(
    const PrivacyPassContext& pp_context,
    std::vector<std::unique_ptr<anonymous_tokens::
                                    PrivacyPassRsaBssaPublicMetadataClient>>
        privacy_pass_clients,
    SignedTokenCallback callback, std::unique_ptr<BlindSignTracingHooks> hooks,
    absl::StatusOr<BlindSignMessageResponse> response) {
  if (hooks != nullptr) {
    hooks->OnAuthAndSignEnd();
  }
  // Validate response.
  if (!response.ok()) {
    QUICHE_LOG(WARNING) << "AuthAndSign failed: " << response.status();
    std::move(callback)(absl::Status(response.status().code(),
                                     "AuthAndSign failed: invalid response"));
    return;
  }
  absl::StatusCode code = response->status_code();
  if (code != absl::StatusCode::kOk) {
    QUICHE_LOG(WARNING) << "AuthAndSign failed with code: " << code;
    std::move(callback)(absl::Status(code, "AuthAndSign failed"));
    return;
  }

  // Decode AuthAndSignResponse.
  AuthAndSignResponse sign_response;
  if (!sign_response.ParseFromString(response->body())) {
    QUICHE_LOG(WARNING) << "Failed to parse AuthAndSignResponse";
    std::move(callback)(
        absl::InternalError("Failed to parse AuthAndSignResponse"));
    return;
  }
  if (static_cast<size_t>(sign_response.blinded_token_signature_size()) >
      privacy_pass_clients.size()) {
    QUICHE_LOG(WARNING) << "Number of signatures is greater than the number of "
                           "Privacy Pass tokens sent";
    std::move(callback)(absl::InternalError(
        "Number of signatures is greater than the number of "
        "Privacy Pass tokens sent"));
    return;
  }

  if (hooks != nullptr) {
    hooks->OnUnblindTokensStart();
  }
  absl::Cleanup unblind_tokens_end = [hooks = std::move(hooks)]() {
    if (hooks != nullptr) {
      hooks->OnUnblindTokensEnd();
    }
  };

  // Create tokens using blinded signatures.
  std::vector<BlindSignToken> tokens_vec;
  tokens_vec.resize(sign_response.blinded_token_signature_size());
  for (int i = 0; i < sign_response.blinded_token_signature_size(); i++) {
    task_bundle_->Add([&, i]() {
      std::string unescaped_blinded_sig;
      if (!absl::Base64Unescape(sign_response.blinded_token_signature()[i],
                                &unescaped_blinded_sig)) {
        QUICHE_LOG(WARNING) << "Failed to unescape blinded signature";
        return absl::InternalError("Failed to unescape blinded signature");
      }

      absl::StatusOr<Token> token =
          privacy_pass_clients[i]->FinalizeToken(unescaped_blinded_sig);
      if (!token.ok()) {
        QUICHE_LOG(WARNING) << "Failed to finalize token: " << token.status();
        return absl::InternalError("Failed to finalize token");
      }

      absl::StatusOr<std::string> marshaled_token = MarshalToken(*token);
      if (!marshaled_token.ok()) {
        QUICHE_LOG(WARNING)
            << "Failed to marshal token: " << marshaled_token.status();
        return absl::InternalError("Failed to marshal token");
      }

      PrivacyPassTokenData privacy_pass_token_data;
      privacy_pass_token_data.mutable_token()->assign(
          ConvertBase64ToWebSafeBase64(absl::Base64Escape(*marshaled_token)));
      privacy_pass_token_data.mutable_encoded_extensions()->assign(
          ConvertBase64ToWebSafeBase64(
              absl::Base64Escape(pp_context.public_metadata_extensions_str)));
      privacy_pass_token_data.set_use_case_override(pp_context.use_case);
      tokens_vec[i] = BlindSignToken{
          privacy_pass_token_data.SerializeAsString(),
          pp_context.public_metadata_expiry_time, pp_context.geo_hint};
      return absl::OkStatus();
    });
  }
  absl::Status status = task_bundle_->Join();
  if (!status.ok()) {
    std::move(callback)(status);
    return;
  }

  std::move(callback)(absl::Span<BlindSignToken>(tokens_vec));
}

void BlindSignAuth::GetAttestationTokens(
    int num_tokens, ProxyLayer layer,
    AttestationDataCallback attestation_data_callback,
    SignedTokenCallback token_callback) {
  GetInitialDataRequest request;
  request.set_service_type(BlindSignAuthServiceTypeToString(
      BlindSignAuthServiceType::kPrivateAratea));
  // Validation version must be 2 to use ProxyLayer.
  request.set_validation_version(2);
  request.set_proxy_layer(QuicheProxyLayerToPpnProxyLayer(layer));
  request.set_use_attestation(true);

  // Send GetAttestationData RPC on the BlindSignMessageInterface.
  std::string body_bytes = request.SerializeAsString();
  BlindSignMessageCallback initial_data_callback = absl::bind_front(
      &BlindSignAuth::GetAttestationTokensCallback, this, num_tokens,
      std::move(attestation_data_callback), std::move(token_callback));
  fetcher_->DoRequest(BlindSignMessageRequestType::kGetInitialData,
                      /*authorization_header=*/std::nullopt, body_bytes,
                      std::move(initial_data_callback));
}

void BlindSignAuth::GetAttestationTokensCallback(
    int num_tokens, AttestationDataCallback attestation_data_callback,
    SignedTokenCallback token_callback,
    absl::StatusOr<BlindSignMessageResponse> response) {
  absl::StatusOr<GetInitialDataResponse> initial_data_response =
      ParseGetInitialDataResponseMessage(response);
  if (!initial_data_response.ok()) {
    std::move(token_callback)(initial_data_response.status());
    return;
  }

  const bool use_privacy_pass_client =
      auth_options_.enable_privacy_pass() &&
      initial_data_response->has_privacy_pass_data();
  if (use_privacy_pass_client) {
    QUICHE_DVLOG(1) << "Using Privacy Pass client for GetAttestationTokens";
  } else {
    QUICHE_LOG(ERROR) << "Non-Privacy Pass tokens are no longer supported";
    std::move(token_callback)(absl::UnimplementedError(
        "Non-Privacy Pass tokens are no longer supported"));
    return;
  }

  // Return attestation nonce, caller will use it as the attestation challenge.
  if (!initial_data_response->has_attestation()) {
    QUICHE_LOG(WARNING)
        << "GetInitialDataResponse does not have attestation data";
    std::move(token_callback)(absl::InternalError(
        "GetInitialDataResponse does not have attestation data"));
    return;
  }
  absl::string_view attestation_nonce =
      initial_data_response->attestation().attestation_nonce();
  quiche::AttestAndSignCallback attest_and_sign_callback = absl::bind_front(
      &BlindSignAuth::AttestAndSign, this, num_tokens,
      *std::move(initial_data_response), std::move(token_callback));
  std::move(attestation_data_callback)(attestation_nonce,
                                       std::move(attest_and_sign_callback));
}

void BlindSignAuth::AttestAndSign(
    int num_tokens, privacy::ppn::GetInitialDataResponse initial_data_response,
    SignedTokenCallback callback,
    absl::StatusOr<google::protobuf::Any> attestation_data,
    std::optional<const absl::string_view> token_challenge) {
  absl::StatusOr<PrivacyPassContext> pp_context =
      CreatePrivacyPassContext(initial_data_response);
  if (!pp_context.ok()) {
    std::move(callback)(pp_context.status());
    return;
  }

  // Create token challenge if not provided.
  std::string token_challenge_str;
  if (!token_challenge.has_value()) {
    TokenChallenge challenge;
    challenge.issuer_name = kIssuerHostname;
    if (absl::StatusOr<std::string> constant_challenge =
            MarshalTokenChallenge(challenge);
        constant_challenge.ok()) {
      token_challenge_str = *constant_challenge;
    } else {
      QUICHE_LOG(WARNING) << "Failed to marshal token challenge: "
                          << constant_challenge.status();
      std::move(callback)(
          absl::InvalidArgumentError("Failed to marshal token challenge"));
      return;
    }
  } else {
    token_challenge_str = *token_challenge;
  }

  absl::StatusOr<GeneratedTokenRequests> token_requests_data =
      GenerateBlindedTokenRequests(
          num_tokens, *pp_context->rsa_public_key, token_challenge_str,
          pp_context->token_key_id, pp_context->extensions);
  if (!token_requests_data.ok()) {
    std::move(callback)(token_requests_data.status());
    return;
  }

  if (!attestation_data.ok()) {
    std::move(callback)(attestation_data.status());
    return;
  }

  AttestationData attestation_data_proto;
  *attestation_data_proto.mutable_attestation_data() = *attestation_data;

  // Create AttestAndSignRequest.
  AttestAndSignRequest sign_request;
  sign_request.set_service_type(BlindSignAuthServiceTypeToString(
      BlindSignAuthServiceType::kPrivateAratea));
  sign_request.mutable_blinded_tokens()->Assign(
      token_requests_data->privacy_pass_blinded_tokens_b64.begin(),
      token_requests_data->privacy_pass_blinded_tokens_b64.end());
  sign_request.set_key_version(
      initial_data_response.at_public_metadata_public_key().key_version());
  sign_request.mutable_public_metadata_extensions()->assign(
      initial_data_response.privacy_pass_data().public_metadata_extensions());
  *sign_request.mutable_attestation() = attestation_data_proto;

  BlindSignMessageCallback attestation_data_callback = absl::bind_front(
      &BlindSignAuth::AttestAndSignCallback, this, *std::move(pp_context),
      std::move(token_requests_data->privacy_pass_clients),
      std::move(callback));

  fetcher_->DoRequest(BlindSignMessageRequestType::kAttestAndSign,
                      /*authorization_header=*/std::nullopt,
                      sign_request.SerializeAsString(),
                      std::move(attestation_data_callback));
}

void BlindSignAuth::AttestAndSignCallback(
    PrivacyPassContext pp_context,
    const std::vector<std::unique_ptr<
        anonymous_tokens::
            PrivacyPassRsaBssaPublicMetadataClient>>& privacy_pass_clients,
    SignedTokenCallback callback,
    absl::StatusOr<BlindSignMessageResponse> response) {
  // Validate response.
  if (!response.ok()) {
    QUICHE_LOG(WARNING) << "AttestAndSign failed: " << response.status();
    std::move(callback)(absl::Status(response.status().code(),
                                     "AttestAndSign failed: invalid response"));
    return;
  }
  absl::StatusCode code = response->status_code();
  if (code != absl::StatusCode::kOk) {
    QUICHE_LOG(WARNING) << "AttestAndSign failed with code: " << code;
    std::move(callback)(absl::Status(code, "AttestAndSign failed"));
    return;
  }

  // Decode AttestAndSignResponse.
  AttestAndSignResponse sign_response;
  if (!sign_response.ParseFromString(response->body())) {
    QUICHE_LOG(WARNING) << "Failed to parse AttestAndSignResponse";
    std::move(callback)(
        absl::InternalError("Failed to parse AttestAndSignResponse"));
    return;
  }
  if (static_cast<size_t>(sign_response.blinded_token_signatures_size()) >
      privacy_pass_clients.size()) {
    QUICHE_LOG(WARNING) << "Number of signatures is greater than the number of "
                           "Privacy Pass tokens sent";
    std::move(callback)(absl::InternalError(
        "Number of signatures is greater than the number of "
        "Privacy Pass tokens sent"));
    return;
  }

  // Create tokens using blinded signatures.
  std::vector<BlindSignToken> tokens_vec;
  tokens_vec.resize(sign_response.blinded_token_signatures_size());
  for (int i = 0; i < sign_response.blinded_token_signatures_size(); i++) {
    task_bundle_->Add([&, i]() {
      std::string unescaped_blinded_sig;
      if (!absl::Base64Unescape(sign_response.blinded_token_signatures()[i],
                                &unescaped_blinded_sig)) {
        QUICHE_LOG(WARNING) << "Failed to unescape blinded signature";
        return absl::InternalError("Failed to unescape blinded signature");
      }

      absl::StatusOr<Token> token =
          privacy_pass_clients[i]->FinalizeToken(unescaped_blinded_sig);
      if (!token.ok()) {
        QUICHE_LOG(WARNING) << "Failed to finalize token: " << token.status();
        return absl::InternalError("Failed to finalize token");
      }

      absl::StatusOr<std::string> marshaled_token = MarshalToken(*token);
      if (!marshaled_token.ok()) {
        QUICHE_LOG(WARNING)
            << "Failed to marshal token: " << marshaled_token.status();
        return absl::InternalError("Failed to marshal token");
      }

      PrivacyPassTokenData privacy_pass_token_data;
      privacy_pass_token_data.mutable_token()->assign(
          ConvertBase64ToWebSafeBase64(absl::Base64Escape(*marshaled_token)));
      privacy_pass_token_data.mutable_encoded_extensions()->assign(
          ConvertBase64ToWebSafeBase64(
              absl::Base64Escape(pp_context.public_metadata_extensions_str)));
      privacy_pass_token_data.set_use_case_override(pp_context.use_case);
      tokens_vec[i] = BlindSignToken{
          privacy_pass_token_data.SerializeAsString(),
          pp_context.public_metadata_expiry_time, pp_context.geo_hint};
      return absl::OkStatus();
    });
  }
  absl::Status status = task_bundle_->Join();
  if (!status.ok()) {
    std::move(callback)(status);
    return;
  }
  std::move(callback)(absl::Span<BlindSignToken>(tokens_vec));
}

absl::StatusOr<privacy::ppn::GetInitialDataResponse>
BlindSignAuth::ParseGetInitialDataResponseMessage(
    const absl::StatusOr<BlindSignMessageResponse>& response) {
  if (!response.ok()) {
    QUICHE_LOG(WARNING) << "GetInitialDataRequest failed: "
                        << response.status();
    return absl::Status(response.status().code(),
                        "GetInitialDataRequest failed: invalid response");
  }
  if (absl::StatusCode code = response->status_code();
      code != absl::StatusCode::kOk) {
    QUICHE_LOG(WARNING) << "GetInitialDataRequest failed with code: " << code;
    return absl::Status(code, "GetInitialDataRequest failed");
  }
  // Parse GetInitialDataResponse.
  GetInitialDataResponse initial_data_response;
  if (!initial_data_response.ParseFromString(response->body())) {
    QUICHE_LOG(WARNING) << "Failed to parse GetInitialDataResponse";
    return absl::InternalError("Failed to parse GetInitialDataResponse");
  }
  return initial_data_response;
}

absl::StatusOr<BlindSignAuth::PrivacyPassContext>
BlindSignAuth::CreatePrivacyPassContext(
    const privacy::ppn::GetInitialDataResponse& initial_data_response) {
  RSAPublicKey public_key_proto;
  if (!public_key_proto.ParseFromString(
          initial_data_response.at_public_metadata_public_key()
              .serialized_public_key())) {
    return absl::InvalidArgumentError(
        "Failed to parse Privacy Pass public key");
  }
  absl::StatusOr<bssl::UniquePtr<RSA>> bssl_rsa_key =
      CreatePublicKeyRSA(public_key_proto.n(), public_key_proto.e());
  if (!bssl_rsa_key.ok()) {
    return absl::InternalError(absl::StrCat("Failed to create RSA public key: ",
                                            bssl_rsa_key.status().ToString()));
  }

  PrivacyPassContext context;
  context.rsa_public_key = *std::move(bssl_rsa_key);
  context.key_version =
      initial_data_response.at_public_metadata_public_key().key_version();
  context.token_key_id =
      initial_data_response.privacy_pass_data().token_key_id();
  context.public_metadata_extensions_str =
      initial_data_response.privacy_pass_data().public_metadata_extensions();

  absl::StatusOr<Extensions> extensions =
      DecodeExtensions(context.public_metadata_extensions_str);
  if (!extensions.ok()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Failed to decode extensions: ", extensions.status().ToString()));
  }

  if (absl::Status validation_result = ValidateExtensionsOrderAndValues(
          *extensions, absl::MakeSpan(kExpectedExtensionTypes), absl::Now());
      validation_result.ok()) {
    context.extensions = *std::move(extensions);
  } else {
    return absl::InvalidArgumentError(absl::StrCat(
        "Failed to validate extensions: ", validation_result.ToString()));
  }

  if (absl::StatusOr<ExpirationTimestamp> expiration_timestamp =
          ExpirationTimestamp::FromExtension(
              context.extensions.extensions.at(0));
      expiration_timestamp.ok()) {
    context.public_metadata_expiry_time =
        absl::FromUnixSeconds(expiration_timestamp->timestamp);
  } else {
    return absl::InvalidArgumentError(
        absl::StrCat("Failed to parse expiration timestamp: ",
                     expiration_timestamp.status().ToString()));
  }

  if (absl::StatusOr<GeoHint> geo_hint =
          GeoHint::FromExtension(context.extensions.extensions.at(1));
      geo_hint.ok()) {
    context.geo_hint = *std::move(geo_hint);
  } else {
    return absl::InvalidArgumentError(absl::StrCat(
        "Failed to parse geo hint: ", geo_hint.status().ToString()));
  }

  if (absl::StatusOr<AnonymousTokensUseCase> use_case = ParseUseCase(
          initial_data_response.at_public_metadata_public_key().use_case());
      use_case.ok()) {
    context.use_case = *std::move(use_case);
  } else {
    return absl::InvalidArgumentError(absl::StrCat(
        "Failed to parse use case: ", use_case.status().ToString()));
  }

  return context;
}

absl::StatusOr<BlindSignAuth::GeneratedTokenRequests>
BlindSignAuth::GenerateBlindedTokenRequests(
    int num_tokens, const RSA& rsa_public_key,
    absl::string_view token_challenge_str, absl::string_view token_key_id,
    const anonymous_tokens::Extensions& extensions) {
  GeneratedTokenRequests result;
  result.privacy_pass_clients.resize(num_tokens);
  result.privacy_pass_blinded_tokens_b64.resize(num_tokens);
  QuicheRandom* random = QuicheRandom::GetInstance();

  for (int i = 0; i < num_tokens; i++) {
    task_bundle_->Add([&, i]() {
      auto client =
          PrivacyPassRsaBssaPublicMetadataClient::Create(rsa_public_key);
      if (!client.ok()) {
        return absl::InternalError(
            absl::StrCat("Failed to create Privacy Pass client: ",
                         client.status().ToString()));
      }

      std::string nonce_rand(32, '\0');
      random->RandBytes(nonce_rand.data(), nonce_rand.size());

      absl::StatusOr<ExtendedTokenRequest> extended_token_request =
          (*client)->CreateTokenRequest(token_challenge_str, nonce_rand,
                                        token_key_id, extensions);
      if (!extended_token_request.ok()) {
        return absl::InternalError(
            absl::StrCat("Failed to create ExtendedTokenRequest: ",
                         extended_token_request.status().ToString()));
      }
      result.privacy_pass_clients[i] = *std::move(client);
      result.privacy_pass_blinded_tokens_b64[i] = absl::Base64Escape(
          extended_token_request->request.blinded_token_request);
      return absl::OkStatus();
    });
  }
  absl::Status status = task_bundle_->Join();
  if (!status.ok()) {
    return status;
  }
  return result;
}

privacy::ppn::ProxyLayer BlindSignAuth::QuicheProxyLayerToPpnProxyLayer(
    quiche::ProxyLayer proxy_layer) {
  switch (proxy_layer) {
    case ProxyLayer::kProxyA: {
      return privacy::ppn::ProxyLayer::PROXY_A;
    }
    case ProxyLayer::kProxyB: {
      return privacy::ppn::ProxyLayer::PROXY_B;
    }
    case ProxyLayer::kTerminalLayer: {
      return privacy::ppn::ProxyLayer::TERMINAL_LAYER;
    }
  }
}

std::string BlindSignAuth::ConvertBase64ToWebSafeBase64(
    std::string base64_string) {
  absl::c_replace(base64_string, /*old_value=*/'+', /*new_value=*/'-');
  absl::c_replace(base64_string, /*old_value=*/'/', /*new_value=*/'_');
  return base64_string;
}

std::string BlindSignAuthServiceTypeToString(
    quiche::BlindSignAuthServiceType service_type) {
  switch (service_type) {
    case BlindSignAuthServiceType::kChromeIpBlinding: {
      return "chromeipblinding";
    }
    case BlindSignAuthServiceType::kCronetIpBlinding: {
      return "cronetipblinding";
    }
    case BlindSignAuthServiceType::kWebviewIpBlinding: {
      // Currently WebView uses the same service type as Chrome.
      // TODO(b/280621504): Change this once we have a more specific service
      // type.
      return "chromeipblinding";
    }
    case BlindSignAuthServiceType::kPrivateAratea: {
      return "privatearatea";
    }
    case BlindSignAuthServiceType::kChromePrivateAratea: {
      return "chromeprivatearatea";
    }
  }
}

}  // namespace quiche
