Export BlindSignAuth to GoB, packaging in PPN protos and Anonymous Tokens client crypto library.

PiperOrigin-RevId: 518092689
diff --git a/build/source_list.bzl b/build/source_list.bzl
index 3d8f341..d592628 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -1587,12 +1587,14 @@
 ]
 protobuf_blind_sign_auth = [
     "blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.proto",
+    "blind_sign_auth/proto/any.proto",
     "blind_sign_auth/proto/attestation.proto",
     "blind_sign_auth/proto/auth_and_sign.proto",
     "blind_sign_auth/proto/get_initial_data.proto",
     "blind_sign_auth/proto/key_services.proto",
     "blind_sign_auth/proto/public_metadata.proto",
     "blind_sign_auth/proto/spend_token_data.proto",
+    "blind_sign_auth/proto/timestamp.proto",
 ]
 libevent_hdrs = [
     "quic/bindings/quic_libevent.h",
diff --git a/build/source_list.gni b/build/source_list.gni
index 5e70945..cd27eea 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -1587,12 +1587,14 @@
 ]
 protobuf_blind_sign_auth = [
     "src/quiche/blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.proto",
+    "src/quiche/blind_sign_auth/proto/any.proto",
     "src/quiche/blind_sign_auth/proto/attestation.proto",
     "src/quiche/blind_sign_auth/proto/auth_and_sign.proto",
     "src/quiche/blind_sign_auth/proto/get_initial_data.proto",
     "src/quiche/blind_sign_auth/proto/key_services.proto",
     "src/quiche/blind_sign_auth/proto/public_metadata.proto",
     "src/quiche/blind_sign_auth/proto/spend_token_data.proto",
+    "src/quiche/blind_sign_auth/proto/timestamp.proto",
 ]
 libevent_hdrs = [
     "src/quiche/quic/bindings/quic_libevent.h",
diff --git a/build/source_list.json b/build/source_list.json
index 22a67dc..7f8511c 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -1586,12 +1586,14 @@
   ],
   "protobuf_blind_sign_auth": [
     "quiche/blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.proto",
+    "quiche/blind_sign_auth/proto/any.proto",
     "quiche/blind_sign_auth/proto/attestation.proto",
     "quiche/blind_sign_auth/proto/auth_and_sign.proto",
     "quiche/blind_sign_auth/proto/get_initial_data.proto",
     "quiche/blind_sign_auth/proto/key_services.proto",
     "quiche/blind_sign_auth/proto/public_metadata.proto",
-    "quiche/blind_sign_auth/proto/spend_token_data.proto"
+    "quiche/blind_sign_auth/proto/spend_token_data.proto",
+    "quiche/blind_sign_auth/proto/timestamp.proto"
   ],
   "libevent_hdrs": [
     "quiche/quic/bindings/quic_libevent.h"
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc
index 15584e1..6bd2209 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client.cc
@@ -263,7 +263,7 @@
 
 absl::Status AnonymousTokensRsaBssaClient::Verify(
     const RSABlindSignatureToken& /*token*/, absl::string_view /*message*/,
-    std::optional<absl::string_view> /*public_metadata*/) {
+    absl::optional<absl::string_view> /*public_metadata*/) {
   return absl::UnimplementedError("Verify not implemented yet.");
 }
 
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc
index 909096d..9a317f4 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/client/anonymous_tokens_rsa_bssa_client_test.cc
@@ -41,7 +41,7 @@
                     MessageMaskType mask_type = AT_MESSAGE_MASK_CONCAT,
                     int message_mask_size = 32) {
   ANON_TOKENS_ASSIGN_OR_RETURN(auto key, CreateTestKey());
-  key.second.set_use_case(use_case);
+  key.second.set_use_case(std::string(use_case));
   key.second.set_key_version(key_version);
   key.second.set_message_mask_type(mask_type);
   key.second.set_message_mask_size(message_mask_size);
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/at_crypto_utils_test.cc b/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/at_crypto_utils_test.cc
index da712dc..2e0005f 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/at_crypto_utils_test.cc
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/at_crypto_utils_test.cc
@@ -136,7 +136,8 @@
   std::string data = absl::HexStringToBytes(params.input_hex);
   std::string expected_digest =
       absl::HexStringToBytes(params.expected_digest_hex);
-  QUICHE_EXPECT_OK_AND_ASSIGN(auto computed_hash, ComputeHash(data, *params.hasher));
+  ANON_TOKENS_QUICHE_EXPECT_OK_AND_ASSIGN(auto computed_hash,
+                                   ComputeHash(data, *params.hasher));
   EXPECT_EQ(computed_hash, expected_digest);
 }
 
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/proto_utils_test.cc b/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/proto_utils_test.cc
index a6ff0a2..45dfe9c 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/proto_utils_test.cc
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/proto_utils_test.cc
@@ -27,8 +27,6 @@
 namespace anonymous_tokens {
 namespace {
 
-using ::testing::EqualsProto;
-
 TEST(ProtoUtilsTest, EmptyUseCase) {
   EXPECT_THAT(ParseUseCase("").status().code(),
               absl::StatusCode::kInvalidArgument);
@@ -75,15 +73,13 @@
   quiche::protobuf::Timestamp proto;
   ANON_TOKENS_QUICHE_EXPECT_OK_AND_ASSIGN(
       proto, TimeToProto(absl::FromUnixSeconds(1596762373)));
-  EXPECT_THAT(proto, EqualsProto(R"pb(
-                seconds: 1596762373 nanos: 0
-              )pb"));
+  EXPECT_EQ(proto.seconds(), 1596762373);
+  EXPECT_EQ(proto.nanos(), 0);
 
   ANON_TOKENS_QUICHE_EXPECT_OK_AND_ASSIGN(
       proto, TimeToProto(absl::FromUnixMillis(1596762373123L)));
-  EXPECT_THAT(proto, EqualsProto(R"pb(
-                seconds: 1596762373 nanos: 123000000
-              )pb"));
+  EXPECT_EQ(proto.seconds(), 1596762373);
+  EXPECT_EQ(proto.nanos(), 123000000);
 }
 
 TEST(ProtoUtilsTest, TimeToProtoBad) {
diff --git a/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/status_utils.h b/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/status_utils.h
index e698702..e0bd70d 100644
--- a/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/status_utils.h
+++ b/quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/status_utils.h
@@ -35,7 +35,7 @@
   if (ABSL_PREDICT_FALSE(!statusor.ok())) {                      \
     return statusor.status();                                    \
   }                                                              \
-  lhs = std::move(statusor.value())
+  lhs = *std::move(statusor)
 
 #define ANON_TOKENS_RETURN_IF_ERROR(expr)                  \
   do {                                                     \
diff --git a/quiche/blind_sign_auth/blind_sign_auth.cc b/quiche/blind_sign_auth/blind_sign_auth.cc
index f09e6df..413eb64 100644
--- a/quiche/blind_sign_auth/blind_sign_auth.cc
+++ b/quiche/blind_sign_auth/blind_sign_auth.cc
@@ -10,7 +10,6 @@
 #include <string>
 #include <vector>
 
-#include "privacy/net/common/cpp/public_metadata/fingerprint.h"
 #include "quiche/blind_sign_auth/proto/auth_and_sign.pb.h"
 #include "quiche/blind_sign_auth/proto/get_initial_data.pb.h"
 #include "quiche/blind_sign_auth/proto/key_services.pb.h"
@@ -28,6 +27,14 @@
 #include "quiche/common/quiche_random.h"
 
 namespace quiche {
+namespace {
+
+template <typename T>
+std::string OmitDefault(T value) {
+  return value == 0 ? "" : absl::StrCat(value);
+}
+
+}  // namespace
 
 void BlindSignAuth::GetTokens(
     absl::string_view oauth_token, int num_tokens,
@@ -101,7 +108,7 @@
     random->RandBytes(rand_bytes.data(), rand_bytes.size());
     plaintext_message.set_plaintext_message(absl::StrCat("blind:", rand_bytes));
     uint64_t fingerprint = 0;
-    absl::Status fingerprint_status = privacy::ppn::FingerprintPublicMetadata(
+    absl::Status fingerprint_status = FingerprintPublicMetadata(
         initial_data_response.public_metadata_info().public_metadata(),
         &fingerprint);
     if (!fingerprint_status.ok()) {
@@ -126,7 +133,7 @@
 
   // Create AuthAndSign RPC.
   privacy::ppn::AuthAndSignRequest sign_request;
-  sign_request.set_oauth_token(oauth_token);
+  sign_request.set_oauth_token(std::string(oauth_token));
   sign_request.set_service_type("chromeipblinding");
   sign_request.set_key_type(privacy::ppn::AT_PUBLIC_METADATA_KEY_TYPE);
   sign_request.set_key_version(
@@ -252,10 +259,38 @@
       return;
     }
     spend_token_data.set_use_case(*use_case);
+    spend_token_data.set_message_mask(
+        signed_tokens->at(i).token().message_mask());
     tokens_vec.push_back(spend_token_data.SerializeAsString());
   }
 
   callback(absl::Span<std::string>(tokens_vec));
 }
 
+absl::Status BlindSignAuth::FingerprintPublicMetadata(
+    const privacy::ppn::PublicMetadata& metadata, uint64_t* fingerprint) {
+  const EVP_MD* hasher = EVP_sha256();
+  std::string digest;
+  digest.resize(EVP_MAX_MD_SIZE);
+
+  uint32_t digest_length = 0;
+  // Concatenate fields in tag number order, omitting fields whose values match
+  // the default. This enables new fields to be added without changing the
+  // resulting encoding.
+  const std::string input = absl::StrCat(            //
+      metadata.exit_location().country(),            //
+      metadata.exit_location().city_geo_id(),        //
+      metadata.service_type(),                       //
+      OmitDefault(metadata.expiration().seconds()),  //
+      OmitDefault(metadata.expiration().nanos()));
+  if (EVP_Digest(input.data(), input.length(),
+                 reinterpret_cast<uint8_t*>(&digest[0]), &digest_length, hasher,
+                 nullptr) != 1) {
+    return absl::InternalError("EVP_Digest failed");
+  }
+  // Return the first uint64_t of the SHA-256 hash.
+  memcpy(fingerprint, digest.data(), sizeof(*fingerprint));
+  return absl::OkStatus();
+}
+
 }  // namespace quiche
diff --git a/quiche/blind_sign_auth/blind_sign_auth.h b/quiche/blind_sign_auth/blind_sign_auth.h
index 5a85dea..5a9384b 100644
--- a/quiche/blind_sign_auth/blind_sign_auth.h
+++ b/quiche/blind_sign_auth/blind_sign_auth.h
@@ -53,6 +53,8 @@
       private_membership::anonymous_tokens::AnonymousTokensRsaBssaClient*
           bssa_client,
       std::function<void(absl::StatusOr<absl::Span<std::string>>)> callback);
+  absl::Status FingerprintPublicMetadata(
+      const privacy::ppn::PublicMetadata& metadata, uint64_t* fingerprint);
 
   BlindSignHttpInterface* http_fetcher_ = nullptr;
 };
diff --git a/quiche/blind_sign_auth/blind_sign_auth_test.cc b/quiche/blind_sign_auth/blind_sign_auth_test.cc
index 39bf880..d7e677a 100644
--- a/quiche/blind_sign_auth/blind_sign_auth_test.cc
+++ b/quiche/blind_sign_auth/blind_sign_auth_test.cc
@@ -8,8 +8,8 @@
 #include <memory>
 #include <string>
 #include <utility>
-#include <vector>
 
+#include "quiche/blind_sign_auth/proto/timestamp.pb.h"
 #include "quiche/blind_sign_auth/proto/auth_and_sign.pb.h"
 #include "quiche/blind_sign_auth/proto/get_initial_data.pb.h"
 #include "quiche/blind_sign_auth/proto/key_services.pb.h"
@@ -22,7 +22,6 @@
 #include "quiche/blind_sign_auth/anonymous_tokens/cpp/crypto/testing_utils.h"
 #include "quiche/blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.pb.h"
 #include "openssl/base.h"
-
 #include "quiche/blind_sign_auth/blind_sign_http_response.h"
 #include "quiche/blind_sign_auth/test_tools/mock_blind_sign_http_interface.h"
 #include "quiche/common/platform/api/quiche_mutex.h"
@@ -35,13 +34,11 @@
 
 using ::testing::_;
 using ::testing::Eq;
-using ::testing::EqualsProto;
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::InvokeArgument;
 using ::testing::StartsWith;
 using ::testing::Unused;
-using ::testing::proto::WhenDeserializedAs;
 
 class BlindSignAuthTest : public QuicheTest {
  protected:
@@ -53,7 +50,13 @@
     }
     keypair_ = *std::move(keypair);
     keypair_.second.set_key_version(1);
-    keypair_.second.set_use_case("CHROME_IP_BLINDING");
+    keypair_.second.set_use_case("TEST_USE_CASE");
+
+    // Create fake GetInitialDataRequest.
+    expected_get_initial_data_request_.set_use_attestation(false);
+    expected_get_initial_data_request_.set_service_type("chromeipblinding");
+    expected_get_initial_data_request_.set_location_granularity(
+        privacy::ppn::GetInitialDataRequest_LocationGranularity_UNKNOWN);
 
     // Create fake public key response.
     privacy::ppn::GetInitialDataResponse fake_get_initial_data_response;
@@ -72,11 +75,18 @@
       }
       validation_version: 1
     )pb";
-    privacy::ppn::PublicMetadataInfo public_metadata_info;
-    ASSERT_TRUE(proto2::TextFormat::ParseFromString(public_metadata_str,
-                                                    &public_metadata_info));
+    privacy::ppn::PublicMetadata::Location location;
+    location.set_country("US");
+    quiche::protobuf::Timestamp expiration;
+    expiration.set_seconds(3600);
+    privacy::ppn::PublicMetadata public_metadata;
+    *public_metadata.mutable_exit_location() = location;
+    public_metadata.set_service_type("chromeipblinding");
+    *public_metadata.mutable_expiration() = expiration;
+    public_metadata_info_.set_validation_version(1);
+    *public_metadata_info_.mutable_public_metadata() = public_metadata;
     *fake_get_initial_data_response.mutable_public_metadata_info() =
-        public_metadata_info;
+        public_metadata_info_;
     fake_get_initial_data_response_ = fake_get_initial_data_response;
 
     blind_sign_auth_ = std::make_unique<BlindSignAuth>(&mock_http_interface_);
@@ -100,14 +110,8 @@
     // privacy::ppn::AT_PUBLIC_METADATA_KEY_TYPE.
     EXPECT_EQ(request.key_type(), privacy::ppn::AT_PUBLIC_METADATA_KEY_TYPE);
     EXPECT_EQ(request.public_key_hash(), "");
-    EXPECT_THAT(request.public_metadata_info(), EqualsProto(R"pb(
-                  public_metadata {
-                    exit_location { country: "US" }
-                    service_type: "chromeipblinding"
-                    expiration { seconds: 3600 }
-                  }
-                  validation_version: 1
-                )pb"));
+    EXPECT_EQ(request.public_metadata_info().SerializeAsString(),
+              public_metadata_info_.SerializeAsString());
     EXPECT_EQ(request.key_version(), keypair_.second.key_version());
 
     // Construct AuthAndSignResponse.
@@ -130,22 +134,17 @@
       privacy::ppn::SpendTokenData spend_token_data;
       ASSERT_TRUE(spend_token_data.ParseFromString(token));
       // Validate token structure.
-      EXPECT_THAT(spend_token_data.public_metadata(), EqualsProto(R"pb(
-                    public_metadata {
-                      exit_location { country: "US" }
-                      service_type: "chromeipblinding"
-                      expiration { seconds: 3600 }
-                    }
-                    validation_version: 1
-                  )pb"));
+      EXPECT_EQ(spend_token_data.public_metadata().SerializeAsString(),
+                public_metadata_info_.SerializeAsString());
       EXPECT_THAT(spend_token_data.unblinded_token(), StartsWith("blind:"));
       EXPECT_GE(spend_token_data.unblinded_token_signature().size(),
                 spend_token_data.unblinded_token().size());
       EXPECT_EQ(spend_token_data.signing_key_version(),
                 keypair_.second.key_version());
-      EXPECT_THAT(spend_token_data.use_case(),
-                  private_membership::anonymous_tokens::AnonymousTokensUseCase::
-                      CHROME_IP_BLINDING);
+      EXPECT_NE(spend_token_data.use_case(),
+                private_membership::anonymous_tokens::AnonymousTokensUseCase::
+                    ANONYMOUS_TOKENS_USE_CASE_UNDEFINED);
+      EXPECT_NE(spend_token_data.message_mask(), "");
     }
   }
 
@@ -154,14 +153,11 @@
   std::pair<bssl::UniquePtr<RSA>,
             private_membership::anonymous_tokens::RSABlindSignaturePublicKey>
       keypair_;
+  privacy::ppn::PublicMetadataInfo public_metadata_info_;
   privacy::ppn::AuthAndSignResponse sign_response_;
   privacy::ppn::GetInitialDataResponse fake_get_initial_data_response_;
   std::string oauth_token_ = "oauth_token";
-  absl::string_view expected_get_initial_data_request_ = R"pb(
-    use_attestation: false
-    service_type: "chromeipblinding"
-    location_granularity: 0
-  )pb";
+  privacy::ppn::GetInitialDataRequest expected_get_initial_data_request_;
 };
 
 TEST_F(BlindSignAuthTest, TestGetTokensSuccessful) {
@@ -174,8 +170,7 @@
     EXPECT_CALL(
         mock_http_interface_,
         DoRequest(Eq("/v1/getInitialData"), Eq(oauth_token_),
-                  WhenDeserializedAs<privacy::ppn::GetInitialDataRequest>(
-                      EqualsProto(expected_get_initial_data_request_)),
+                  Eq(expected_get_initial_data_request_.SerializeAsString()),
                   _))
         .Times(1)
         .WillOnce(InvokeArgument<3>(fake_public_key_response));
@@ -237,11 +232,10 @@
   BlindSignHttpResponse fake_public_key_response(
       200, fake_get_initial_data_response_.SerializeAsString());
 
-  EXPECT_CALL(mock_http_interface_,
-              DoRequest(Eq("/v1/getInitialData"), Eq(oauth_token_),
-                        WhenDeserializedAs<privacy::ppn::GetInitialDataRequest>(
-                            EqualsProto(expected_get_initial_data_request_)),
-                        _))
+  EXPECT_CALL(
+      mock_http_interface_,
+      DoRequest(Eq("/v1/getInitialData"), Eq(oauth_token_),
+                Eq(expected_get_initial_data_request_.SerializeAsString()), _))
       .Times(1)
       .WillOnce(InvokeArgument<3>(fake_public_key_response));
 
@@ -269,8 +263,7 @@
     EXPECT_CALL(
         mock_http_interface_,
         DoRequest(Eq("/v1/getInitialData"), Eq(oauth_token_),
-                  WhenDeserializedAs<privacy::ppn::GetInitialDataRequest>(
-                      EqualsProto(expected_get_initial_data_request_)),
+                  Eq(expected_get_initial_data_request_.SerializeAsString()),
                   _))
         .Times(1)
         .WillOnce(InvokeArgument<3>(fake_public_key_response));
diff --git a/quiche/blind_sign_auth/proto/any.proto b/quiche/blind_sign_auth/proto/any.proto
new file mode 100644
index 0000000..c4fa835
--- /dev/null
+++ b/quiche/blind_sign_auth/proto/any.proto
@@ -0,0 +1,26 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
+syntax = "proto3";
+
+package quiche.protobuf;
+
+// Cloned from
+// https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/any.proto.
+message Any {
+  string type_url = 1;
+
+  // Must be a valid serialized protocol buffer of the above specified type.
+  bytes value = 2;
+}
diff --git a/quiche/blind_sign_auth/proto/attestation.proto b/quiche/blind_sign_auth/proto/attestation.proto
index 1743234..8e658e9 100644
--- a/quiche/blind_sign_auth/proto/attestation.proto
+++ b/quiche/blind_sign_auth/proto/attestation.proto
@@ -1,17 +1,26 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
 syntax = "proto3";
 
 package privacy.ppn;
 
 import "quiche/blind_sign_auth/proto/any.proto";
-import "storage/datapol/annotations/proto/semantic_annotations.proto";
 
-option go_api_flag = "OPEN_TO_OPAQUE_HYBRID";
-option java_api_version = 2;
 option java_multiple_files = true;
 option java_outer_classname = "AttestationProto";
 option java_package = "com.google.android.libraries.privacy.ppn.proto";
-option cc_api_version = 2;
-option (datapol.file_vetting_status) = "latest";
 
 message NonceRequest {}
 
diff --git a/quiche/blind_sign_auth/proto/auth_and_sign.proto b/quiche/blind_sign_auth/proto/auth_and_sign.proto
index 64d396d..38f82d1 100644
--- a/quiche/blind_sign_auth/proto/auth_and_sign.proto
+++ b/quiche/blind_sign_auth/proto/auth_and_sign.proto
@@ -1,3 +1,17 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
 syntax = "proto3";
 
 package privacy.ppn;
@@ -5,10 +19,6 @@
 import "quiche/blind_sign_auth/proto/attestation.proto";
 import "quiche/blind_sign_auth/proto/key_services.proto";
 import "quiche/blind_sign_auth/proto/public_metadata.proto";
-import "storage/datapol/annotations/proto/semantic_annotations.proto";
-
-option cc_api_version = 2;
-option (datapol.file_vetting_status) = "latest";
 
 // Client is requesting to auth using the provided auth token.
 // Next ID: 9
diff --git a/quiche/blind_sign_auth/proto/get_initial_data.proto b/quiche/blind_sign_auth/proto/get_initial_data.proto
index f05b637..317b356 100644
--- a/quiche/blind_sign_auth/proto/get_initial_data.proto
+++ b/quiche/blind_sign_auth/proto/get_initial_data.proto
@@ -1,15 +1,26 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
 syntax = "proto3";
 
 package privacy.ppn;
 
 import "quiche/blind_sign_auth/proto/attestation.proto";
 import "quiche/blind_sign_auth/proto/public_metadata.proto";
-import "storage/datapol/annotations/proto/semantic_annotations.proto";
 import "quiche/blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.proto";
 
 option java_multiple_files = true;
-option cc_api_version = 2;
-option (datapol.file_vetting_status) = "latest";
 
 // Request data needed to prepare for AuthAndSign.
 message GetInitialDataRequest {
@@ -43,4 +54,4 @@
   // Data needed to set up attestation, included if use_attestation is true or
   // if the service_type input requires it.
   privacy.ppn.PrepareAttestationData attestation = 3;
-}
\ No newline at end of file
+}
diff --git a/quiche/blind_sign_auth/proto/key_services.proto b/quiche/blind_sign_auth/proto/key_services.proto
index 271b033..343fea8 100644
--- a/quiche/blind_sign_auth/proto/key_services.proto
+++ b/quiche/blind_sign_auth/proto/key_services.proto
@@ -1,11 +1,22 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
 syntax = "proto3";
 
 package privacy.ppn;
 
-import "storage/datapol/annotations/proto/semantic_annotations.proto";
-
 option java_multiple_files = true;
-option (datapol.file_vetting_status) = "latest";
 
 // Indicates client's desired or capable key support.
 enum KeyType {
diff --git a/quiche/blind_sign_auth/proto/public_metadata.proto b/quiche/blind_sign_auth/proto/public_metadata.proto
index c542e0f..5154200 100644
--- a/quiche/blind_sign_auth/proto/public_metadata.proto
+++ b/quiche/blind_sign_auth/proto/public_metadata.proto
@@ -1,13 +1,24 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
 syntax = "proto3";
 
 package privacy.ppn;
 
 import "quiche/blind_sign_auth/proto/timestamp.proto";
-import "storage/datapol/annotations/proto/semantic_annotations.proto";
 
 option java_multiple_files = true;
-option cc_api_version = 2;
-option (datapol.file_vetting_status) = "latest";
 
 // Contains fields which will be cryptographically linked to a blinded token and
 // visible to client, signer, and verifier. Clients should validate/set fields
diff --git a/quiche/blind_sign_auth/proto/spend_token_data.proto b/quiche/blind_sign_auth/proto/spend_token_data.proto
index ba2af00..a70bb80 100644
--- a/quiche/blind_sign_auth/proto/spend_token_data.proto
+++ b/quiche/blind_sign_auth/proto/spend_token_data.proto
@@ -1,3 +1,17 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
 syntax = "proto3";
 
 package privacy.ppn;
@@ -5,8 +19,6 @@
 import "quiche/blind_sign_auth/proto/public_metadata.proto";
 import "quiche/blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.proto";
 
-option cc_api_version = 2;
-
 message SpendTokenData {
   // Public metadata associated with the token being spent.
   // See go/ppn-token-spend and go/ppn-phosphor-at-service for details.
diff --git a/quiche/blind_sign_auth/proto/timestamp.proto b/quiche/blind_sign_auth/proto/timestamp.proto
new file mode 100644
index 0000000..1d99392
--- /dev/null
+++ b/quiche/blind_sign_auth/proto/timestamp.proto
@@ -0,0 +1,32 @@
+// Copyright 2023 Google LLC
+//
+// 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.
+
+syntax = "proto3";
+
+package quiche.protobuf;
+
+// Copied from
+// https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/timestamp.proto.
+message Timestamp {
+  // Represents seconds of UTC time since Unix epoch
+  // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+  // 9999-12-31T23:59:59Z inclusive.
+  int64 seconds = 1;
+
+  // Non-negative fractions of a second at nanosecond resolution. Negative
+  // second values with fractions must still have non-negative nanos values
+  // that count forward in time. Must be from 0 to 999,999,999
+  // inclusive.
+  int32 nanos = 2;
+}
diff --git a/quiche/common/test_tools/quiche_test_utils.h b/quiche/common/test_tools/quiche_test_utils.h
index d35ed7f..811611a 100644
--- a/quiche/common/test_tools/quiche_test_utils.h
+++ b/quiche/common/test_tools/quiche_test_utils.h
@@ -57,6 +57,15 @@
   return ::testing::ExplainMatchResult(matcher, arg.value(), result_listener);
 }
 
+MATCHER_P(StatusIs, code, "Matcher against only a specific status code") {
+  if (ExtractStatus(arg).code() != code) {
+    *result_listener << "Expected status " << absl::StatusCodeToString(code)
+                     << ", got " << ExtractStatus(arg);
+    return false;
+  }
+  return true;
+}
+
 MATCHER_P2(StatusIs, code, matcher, "Matcher against a specific status code") {
   if (ExtractStatus(arg).code() != code) {
     *result_listener << "Expected status " << absl::StatusCodeToString(code)