• 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 #ifndef THIRD_PARTY_ANONYMOUS_TOKENS_CPP_CRYPTO_CRYPTO_UTILS_H_
16 #define THIRD_PARTY_ANONYMOUS_TOKENS_CPP_CRYPTO_CRYPTO_UTILS_H_
17 
18 #include <stddef.h>
19 
20 #include <memory>
21 #include <optional>
22 #include <string>
23 
24 #include "absl/status/statusor.h"
25 #include "absl/strings/string_view.h"
26 #include "quiche/blind_sign_auth/anonymous_tokens/proto/anonymous_tokens.pb.h"
27 #include "openssl/base.h"
28 #include "openssl/bn.h"
29 #include "openssl/evp.h"
30 #include "openssl/rsa.h"
31 #include "quiche/common/platform/api/quiche_export.h"
32 // copybara:strip_begin(internal comment)
33 // The QUICHE_EXPORT annotation is necessary for some classes and functions
34 // to link correctly on Windows. Please do not remove them!
35 // copybara:strip_end
36 
37 namespace private_membership {
38 namespace anonymous_tokens {
39 
40 // Internal functions only exposed for testing.
41 namespace internal {
42 
43 // Outputs a public metadata `hash` using HKDF with the public metadata as
44 // input and the rsa modulus as salt. The expected output hash size is passed as
45 // out_len_bytes.
46 //
47 // Implementation follows the steps listed in
48 // https://datatracker.ietf.org/doc/draft-amjad-cfrg-partially-blind-rsa/
49 //
50 // This method internally calls HKDF with output size of more than
51 // out_len_bytes and later truncates the output to out_len_bytes. This is done
52 // so that the output is indifferentiable from truly random bytes.
53 // https://cfrg.github.io/draft-irtf-cfrg-hash-to-curve/draft-irtf-cfrg-hash-to-curve.html#name-hashing-to-a-finite-field
54 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT
55 PublicMetadataHashWithHKDF(absl::string_view public_metadata,
56                            absl::string_view rsa_modulus_str,
57                            size_t out_len_bytes);
58 
59 }  // namespace internal
60 
61 // Deletes a BN_CTX.
62 class BnCtxDeleter {
63  public:
operator()64   void operator()(BN_CTX* ctx) { BN_CTX_free(ctx); }
65 };
66 typedef std::unique_ptr<BN_CTX, BnCtxDeleter> BnCtxPtr;
67 
68 // Deletes a BN_MONT_CTX.
69 class BnMontCtxDeleter {
70  public:
operator()71   void operator()(BN_MONT_CTX* mont_ctx) { BN_MONT_CTX_free(mont_ctx); }
72 };
73 typedef std::unique_ptr<BN_MONT_CTX, BnMontCtxDeleter> BnMontCtxPtr;
74 
75 // Deletes an EVP_MD_CTX.
76 class EvpMdCtxDeleter {
77  public:
operator()78   void operator()(EVP_MD_CTX* ctx) { EVP_MD_CTX_destroy(ctx); }
79 };
80 typedef std::unique_ptr<EVP_MD_CTX, EvpMdCtxDeleter> EvpMdCtxPtr;
81 
82 // Creates and starts a BIGNUM context.
83 absl::StatusOr<BnCtxPtr> QUICHE_EXPORT GetAndStartBigNumCtx();
84 
85 // Creates a new BIGNUM.
86 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT NewBigNum();
87 
88 // Converts a BIGNUM to string.
89 absl::StatusOr<std::string> QUICHE_EXPORT BignumToString(
90     const BIGNUM& big_num, size_t output_len);
91 
92 // Converts a string to BIGNUM.
93 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT StringToBignum(
94     absl::string_view input_str);
95 
96 // Retrieve error messages from OpenSSL.
97 std::string QUICHE_EXPORT GetSslErrors();
98 
99 // Generate a message mask. For more details, see
100 // https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/
101 absl::StatusOr<std::string> QUICHE_EXPORT GenerateMask(
102     const RSABlindSignaturePublicKey& public_key);
103 
104 // Mask message using protocol at
105 // https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/
106 std::string QUICHE_EXPORT MaskMessageConcat(absl::string_view mask,
107                                                   absl::string_view message);
108 
109 // Encode Message and Public Metadata using steps in
110 // https://datatracker.ietf.org/doc/draft-amjad-cfrg-partially-blind-rsa/
111 //
112 // The length of public metadata must fit in 4 bytes.
113 std::string QUICHE_EXPORT EncodeMessagePublicMetadata(
114     absl::string_view message, absl::string_view public_metadata);
115 
116 // Compute 2^(x - 1/2).
117 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT GetRsaSqrtTwo(
118     int x);
119 
120 // Compute compute 2^x.
121 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT ComputePowerOfTwo(
122     int x);
123 
124 // Converts the AnonymousTokens proto hash type to the equivalent EVP digest.
125 absl::StatusOr<const EVP_MD*> QUICHE_EXPORT
126 ProtoHashTypeToEVPDigest(HashType hash_type);
127 
128 // Converts the AnonymousTokens proto hash type for mask generation function to
129 // the equivalent EVP digest.
130 absl::StatusOr<const EVP_MD*> QUICHE_EXPORT
131 ProtoMaskGenFunctionToEVPDigest(MaskGenFunction mgf);
132 
133 // ComputeHash sub-routine used during blindness and verification of RSA blind
134 // signatures protocol with or without public metadata.
135 absl::StatusOr<std::string> QUICHE_EXPORT ComputeHash(
136     absl::string_view input, const EVP_MD& hasher);
137 
138 // Computes the Carmichael LCM given phi(p) and phi(q) where N = p*q is a safe
139 // RSA modulus.
140 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT
141 ComputeCarmichaelLcm(const BIGNUM& phi_p, const BIGNUM& phi_q, BN_CTX& bn_ctx);
142 
143 // Converts AnonymousTokens::RSAPrivateKey to bssl::UniquePtr<RSA> without
144 // public metadata augmentation.
145 absl::StatusOr<bssl::UniquePtr<RSA>> QUICHE_EXPORT
146 AnonymousTokensRSAPrivateKeyToRSA(const RSAPrivateKey& private_key);
147 
148 // Converts AnonymousTokens::RSAPublicKey to bssl::UniquePtr<RSA> without
149 // public metadata augmentation.
150 absl::StatusOr<bssl::UniquePtr<RSA>> QUICHE_EXPORT
151 AnonymousTokensRSAPublicKeyToRSA(const RSAPublicKey& public_key);
152 
153 // Compute exponent based only on the public metadata. Assumes that n is a safe
154 // modulus i.e. it produces a strong RSA key pair. If not, the exponent may be
155 // invalid.
156 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT
157 PublicMetadataExponent(const BIGNUM& n, absl::string_view public_metadata);
158 
159 // Computes final exponent by multiplying the public exponent e with the
160 // exponent derived from public metadata. Assumes that n is a safe modulus i.e.
161 // it produces a strong RSA key pair. If not, the exponent may be invalid.
162 //
163 // Empty public metadata is considered to be a valid value for public_metadata
164 // and will output an exponent different than `e` as well.
165 absl::StatusOr<bssl::UniquePtr<BIGNUM>> QUICHE_EXPORT
166 ComputeFinalExponentUnderPublicMetadata(const BIGNUM& n, const BIGNUM& e,
167                                         absl::string_view public_metadata);
168 
169 // Helper method that implements RSA PSS Blind Signatures verification protocol
170 // for both the standard scheme as well as the public metadata version.
171 //
172 // The standard public exponent e in rsa_public_key should always have a
173 // standard value even if the public_metada is not std::nullopt.
174 //
175 // If the public_metadata is set to std::nullopt, augmented_rsa_e should be
176 // equal to a standard public exponent same as the value of e in rsa_public_key.
177 // Otherwise, it will be equal to a new public exponent value derived using the
178 // public metadata.
179 absl::Status QUICHE_EXPORT RsaBlindSignatureVerify(
180     int salt_length, const EVP_MD* sig_hash, const EVP_MD* mgf1_hash,
181     RSA* rsa_public_key, const BIGNUM& rsa_modulus,
182     const BIGNUM& augmented_rsa_e, absl::string_view signature,
183     absl::string_view message,
184     std::optional<absl::string_view> public_metadata = std::nullopt);
185 
186 }  // namespace anonymous_tokens
187 }  // namespace private_membership
188 
189 #endif  // THIRD_PARTY_ANONYMOUS_TOKENS_CPP_CRYPTO_CRYPTO_UTILS_H_
190