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 namespace anonymous_tokens {
32 
33 namespace {
34 
CheckKeySize(const RSA & key)35 absl::Status CheckKeySize(const RSA& key) {
36   if (RSA_size(&key) != kRsaModulusSizeInBytes256) {
37     return absl::InvalidArgumentError(
38         "Token type DA7A must use RSA key with the modulus of size 256 bytes.");
39   }
40   return absl::OkStatus();
41 }
42 
43 }  // namespace
44 
45 absl::StatusOr<std::unique_ptr<PrivacyPassRsaBssaPublicMetadataClient>>
Create(const RSA & rsa_public_key)46 PrivacyPassRsaBssaPublicMetadataClient::Create(const RSA& rsa_public_key) {
47   ANON_TOKENS_RETURN_IF_ERROR(CheckKeySize(rsa_public_key));
48 
49   // Create modulus and public exponent strings.
50   ANON_TOKENS_ASSIGN_OR_RETURN(
51       const std::string rsa_modulus,
52       BignumToString(*RSA_get0_n(&rsa_public_key), kRsaModulusSizeInBytes256));
53   ANON_TOKENS_ASSIGN_OR_RETURN(
54       const std::string rsa_e,
55       BignumToString(*RSA_get0_e(&rsa_public_key), kRsaModulusSizeInBytes256));
56 
57   // Create hash digest methods.
58   const EVP_MD* signature_hash_function = EVP_sha384();
59   const EVP_MD* mgf1_hash_function = EVP_sha384();
60 
61   // Create and return client.
62   return absl::WrapUnique(new PrivacyPassRsaBssaPublicMetadataClient(
63       kSaltLengthInBytes48, rsa_modulus, rsa_e, signature_hash_function,
64       mgf1_hash_function));
65 }
66 
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)67 PrivacyPassRsaBssaPublicMetadataClient::PrivacyPassRsaBssaPublicMetadataClient(
68     const int salt_length, const std::string rsa_modulus,
69     const std::string rsa_e, const EVP_MD* signature_hash_function,
70     const EVP_MD* mgf1_hash_function)
71     : salt_length_(salt_length),
72       rsa_modulus_(rsa_modulus),
73       rsa_e_(rsa_e),
74       signature_hash_function_(signature_hash_function),
75       mgf1_hash_function_(mgf1_hash_function) {}
76 
77 absl::StatusOr<ExtendedTokenRequest>
CreateTokenRequest(const absl::string_view challenge,const absl::string_view nonce,const absl::string_view token_key_id,const Extensions & extensions)78 PrivacyPassRsaBssaPublicMetadataClient::CreateTokenRequest(
79     const absl::string_view challenge, const absl::string_view nonce,
80     const absl::string_view token_key_id, const Extensions& extensions) {
81   // Basic validity checks.
82   if (rsa_blinder_ != nullptr) {
83     return absl::FailedPreconditionError(
84         "CreateTokenRequest has already been called.");
85   } else if (token_key_id.size() != 32) {
86     return absl::InvalidArgumentError("token_key_id must be of size 32 bytes.");
87   }
88 
89   // Compute context as sha256 of the challenge.
90   const EVP_MD* sha256 = EVP_sha256();
91   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string context,
92                                ComputeHash(challenge, *sha256));
93 
94   // Populate the token_ object except for the final signature i.e.
95   // authenticator field.
96   token_ = {/*token_type=*/kTokenType,
97             /*token_key_id=*/std::string(token_key_id),
98             /*nonce=*/std::string(nonce),
99             /*context=*/context};
100 
101   // Encode extensions to string.
102   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string encoded_extensions,
103                                EncodeExtensions(extensions));
104 
105   // Create RsaBlinder object.
106   ANON_TOKENS_ASSIGN_OR_RETURN(
107       rsa_blinder_,
108       RsaBlinder::New(rsa_modulus_, rsa_e_, signature_hash_function_,
109                       mgf1_hash_function_, salt_length_,
110                       /*use_rsa_public_exponent=*/false,
111                       /*public_metadata=*/encoded_extensions));
112 
113   // Call Blind on an encoding of the input message.
114   ANON_TOKENS_ASSIGN_OR_RETURN(authenticator_input_,
115                                AuthenticatorInput(token_));
116   ANON_TOKENS_ASSIGN_OR_RETURN(const std::string blinded_message,
117                                rsa_blinder_->Blind(authenticator_input_));
118 
119   // Create the token_request using the token_type, the last byte of the
120   // token_key_id and the blinded_message.
121   TokenRequest token_request = {
122       /*token_type=*/kTokenType,
123       /*truncated_token_key_id=*/
124       static_cast<uint8_t>(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