• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "anonymous_tokens/cpp/privacy_pass/rsa_bssa_public_metadata_client.h"
16 
17 #include <memory>
18 
19 #include "absl/status/status.h"
20 #include "absl/status/statusor.h"
21 #include "absl/strings/string_view.h"
22 #include "anonymous_tokens/cpp/crypto/constants.h"
23 #include "anonymous_tokens/cpp/crypto/crypto_utils.h"
24 #include "anonymous_tokens/cpp/crypto/rsa_blinder.h"
25 #include "anonymous_tokens/cpp/privacy_pass/token_encodings.h"
26 #include "anonymous_tokens/cpp/shared/status_utils.h"
27 #include <openssl/base.h>
28 #include <openssl/digest.h>
29 #include <openssl/rsa.h>
30 
31 
32 namespace anonymous_tokens {
33 
34 namespace {
35 
CheckKeySize(const RSA & key)36 absl::Status CheckKeySize(const RSA& key) {
37   if (RSA_size(&key) != kRsaModulusSizeInBytes256) {
38     return absl::InvalidArgumentError(
39         "Token type DA7A must use RSA key with the modulus of size 256 bytes.");
40   }
41   return absl::OkStatus();
42 }
43 
44 }  // namespace
45 
46 absl::StatusOr<std::unique_ptr<PrivacyPassRsaBssaPublicMetadataClient>>
Create(const RSA & rsa_public_key)47 PrivacyPassRsaBssaPublicMetadataClient::Create(const RSA& rsa_public_key) {
48   ANON_TOKENS_RETURN_IF_ERROR(CheckKeySize(rsa_public_key));
49 
50   // Create modulus and public exponent strings.
51   ANON_TOKENS_ASSIGN_OR_RETURN(
52       const std::string rsa_modulus,
53       BignumToString(*RSA_get0_n(&rsa_public_key), kRsaModulusSizeInBytes256));
54   ANON_TOKENS_ASSIGN_OR_RETURN(
55       const std::string rsa_e,
56       BignumToString(*RSA_get0_e(&rsa_public_key), kRsaModulusSizeInBytes256));
57 
58   // Create hash digest methods.
59   const EVP_MD* signature_hash_function = EVP_sha384();
60   const EVP_MD* mgf1_hash_function = EVP_sha384();
61 
62   // Create and return client.
63   return absl::WrapUnique(new PrivacyPassRsaBssaPublicMetadataClient(
64       kSaltLengthInBytes48, rsa_modulus, rsa_e, signature_hash_function,
65       mgf1_hash_function));
66 }
67 
PrivacyPassRsaBssaPublicMetadataClient(const int salt_length,const std::string rsa_modulus,const std::string rsa_e,const EVP_MD * signature_hash_function,const EVP_MD * mgf1_hash_function)68 PrivacyPassRsaBssaPublicMetadataClient::PrivacyPassRsaBssaPublicMetadataClient(
69     const int salt_length, const std::string rsa_modulus,
70     const std::string rsa_e, const EVP_MD* signature_hash_function,
71     const EVP_MD* mgf1_hash_function)
72     : salt_length_(salt_length),
73       rsa_modulus_(rsa_modulus),
74       rsa_e_(rsa_e),
75       signature_hash_function_(signature_hash_function),
76       mgf1_hash_function_(mgf1_hash_function) {}
77 
78 absl::StatusOr<ExtendedTokenRequest>
CreateTokenRequest(const absl::string_view challenge,const absl::string_view nonce,const absl::string_view token_key_id,const Extensions & extensions)79 PrivacyPassRsaBssaPublicMetadataClient::CreateTokenRequest(
80     const absl::string_view challenge, const absl::string_view nonce,
81     const absl::string_view token_key_id, const Extensions& extensions) {
82   // Basic validity checks.
83   if (rsa_blinder_ != nullptr) {
84     return absl::FailedPreconditionError(
85         "CreateTokenRequest has already been called.");
86   } else if (token_key_id.size() != 32) {
87     return absl::InvalidArgumentError("token_key_id must be of size 32 bytes.");
88   }
89 
90   // Compute context as sha256 of the challenge.
91   const EVP_MD* sha256 = EVP_sha256();
92   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string context,
93                                ComputeHash(challenge, *sha256));
94 
95   // Populate the token_ object except for the final signature i.e.
96   // authenticator field.
97   token_ = {/*token_type=*/kTokenType,
98             /*token_key_id=*/std::string(token_key_id),
99             /*nonce=*/std::string(nonce),
100             /*context=*/context};
101 
102   // Encode extensions to string.
103   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string encoded_extensions,
104                                EncodeExtensions(extensions));
105 
106   // Create RsaBlinder object.
107   ANON_TOKENS_ASSIGN_OR_RETURN(
108       rsa_blinder_,
109       RsaBlinder::New(rsa_modulus_, rsa_e_, signature_hash_function_,
110                       mgf1_hash_function_, salt_length_,
111                       /*use_rsa_public_exponent=*/false,
112                       /*public_metadata=*/encoded_extensions));
113 
114   // Call Blind on an encoding of the input message.
115   ANON_TOKENS_ASSIGN_OR_RETURN(authenticator_input_,
116                                AuthenticatorInput(token_));
117   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string blinded_message,
118                                rsa_blinder_->Blind(authenticator_input_));
119 
120   // Create the token_request using the token_type, the last byte of the
121   // token_key_id and the blinded_message.
122   TokenRequest token_request = {
123       /*token_type=*/kTokenType,
124       /*truncated_token_key_id=*/token_key_id[token_key_id.size() - 1],
125       /*blinded_token_request=*/blinded_message};
126 
127   // ExtendedTokenRequest carries the public metadata / encoded extensions list.
128   ExtendedTokenRequest extended_token_request = {/*request=*/token_request,
129                                                  /*extensions=*/extensions};
130   return extended_token_request;
131 }
132 
FinalizeToken(const absl::string_view blinded_signature)133 absl::StatusOr<Token> PrivacyPassRsaBssaPublicMetadataClient::FinalizeToken(
134     const absl::string_view blinded_signature) {
135   if (rsa_blinder_ == nullptr) {
136     return absl::FailedPreconditionError(
137         "CreateRequest must be called before FinalizeToken.");
138   }
139 
140   // Unblind the blinded signature to obtain the final signature and store it as
141   // authenticator in token_.
142   ANON_TOKENS_ASSIGN_OR_RETURN(token_.authenticator,
143                                rsa_blinder_->Unblind(blinded_signature));
144 
145   // Verify the signature for correctness.
146   ANON_TOKENS_RETURN_IF_ERROR(rsa_blinder_->Verify(
147       /*signature=*/token_.authenticator, /*message=*/authenticator_input_));
148 
149   return token_;
150 }
151 
Verify(Token token_to_verify,const absl::string_view encoded_extensions,RSA & rsa_public_key)152 absl::Status PrivacyPassRsaBssaPublicMetadataClient::Verify(
153     Token token_to_verify, const absl::string_view encoded_extensions,
154     RSA& rsa_public_key) {
155   ANON_TOKENS_RETURN_IF_ERROR(CheckKeySize(rsa_public_key));
156   ANON_TOKENS_ASSIGN_OR_RETURN(
157       bssl::UniquePtr<RSA> derived_rsa_public_key,
158       CreatePublicKeyRSAWithPublicMetadata(
159           *RSA_get0_n(&rsa_public_key), *RSA_get0_e(&rsa_public_key),
160           encoded_extensions, /*use_rsa_public_exponent=*/false));
161 
162   // Prepare input parameters for the verification function.
163   const EVP_MD* signature_hash_function = EVP_sha384();
164   const EVP_MD* mgf1_hash_function = EVP_sha384();
165 
166   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string authenticator_input,
167                                AuthenticatorInput(token_to_verify));
168   std::string augmented_message =
169       EncodeMessagePublicMetadata(authenticator_input, encoded_extensions);
170 
171   return RsaBlindSignatureVerify(
172       kSaltLengthInBytes48, signature_hash_function, mgf1_hash_function,
173       /*signature=*/token_to_verify.authenticator,
174       /*message=*/augmented_message, derived_rsa_public_key.get());
175 }
176 
177 }  // namespace anonymous_tokens
178 
179