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