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