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