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 ANONYMOUS_TOKENS_CPP_CRYPTO_CRYPTO_UTILS_H_ 16 #define 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 <openssl/base.h> 27 #include <openssl/bn.h> 28 #include <openssl/evp.h> 29 #include <openssl/rsa.h> 30 31 namespace anonymous_tokens { 32 33 // Internal functions only exposed for testing. 34 namespace internal { 35 36 // Outputs a public metadata `hash` using HKDF with the public metadata as 37 // input and the rsa modulus as salt. The expected output hash size is passed as 38 // out_len_bytes. 39 // 40 // Implementation follows the steps listed in 41 // https://datatracker.ietf.org/doc/draft-amjad-cfrg-partially-blind-rsa/ 42 // 43 // This method internally calls HKDF with output size of more than 44 // out_len_bytes and later truncates the output to out_len_bytes. This is done 45 // so that the output is indifferentiable from truly random bytes. 46 // https://cfrg.github.io/draft-irtf-cfrg-hash-to-curve/draft-irtf-cfrg-hash-to-curve.html#name-hashing-to-a-finite-field 47 absl::StatusOr<bssl::UniquePtr<BIGNUM>> 48 PublicMetadataHashWithHKDF(absl::string_view public_metadata, 49 absl::string_view rsa_modulus_str, 50 size_t out_len_bytes); 51 52 } // namespace internal 53 54 // Deletes a BN_CTX. 55 class BnCtxDeleter { 56 public: operator()57 void operator()(BN_CTX* ctx) { BN_CTX_free(ctx); } 58 }; 59 typedef std::unique_ptr<BN_CTX, BnCtxDeleter> BnCtxPtr; 60 61 // Deletes a BN_MONT_CTX. 62 class BnMontCtxDeleter { 63 public: operator()64 void operator()(BN_MONT_CTX* mont_ctx) { BN_MONT_CTX_free(mont_ctx); } 65 }; 66 typedef std::unique_ptr<BN_MONT_CTX, BnMontCtxDeleter> BnMontCtxPtr; 67 68 // Deletes an EVP_MD_CTX. 69 class EvpMdCtxDeleter { 70 public: operator()71 void operator()(EVP_MD_CTX* ctx) { EVP_MD_CTX_destroy(ctx); } 72 }; 73 typedef std::unique_ptr<EVP_MD_CTX, EvpMdCtxDeleter> EvpMdCtxPtr; 74 75 // Creates and starts a BIGNUM context. 76 absl::StatusOr<BnCtxPtr> GetAndStartBigNumCtx(); 77 78 // Creates a new BIGNUM. 79 absl::StatusOr<bssl::UniquePtr<BIGNUM>> NewBigNum(); 80 81 // Converts a BIGNUM to string. 82 absl::StatusOr<std::string> BignumToString( 83 const BIGNUM& big_num, size_t output_len); 84 85 // Converts a string to BIGNUM. 86 absl::StatusOr<bssl::UniquePtr<BIGNUM>> StringToBignum( 87 absl::string_view input_str); 88 89 // Retrieve error messages from OpenSSL. 90 std::string GetSslErrors(); 91 92 // Mask message using protocol at 93 // https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/ 94 std::string MaskMessageConcat(absl::string_view mask, 95 absl::string_view message); 96 97 // Encode Message and Public Metadata using steps in 98 // https://datatracker.ietf.org/doc/draft-amjad-cfrg-partially-blind-rsa/ 99 // 100 // The length of public metadata must fit in 4 bytes. 101 std::string EncodeMessagePublicMetadata( 102 absl::string_view message, absl::string_view public_metadata); 103 104 // Compute 2^(x - 1/2). 105 absl::StatusOr<bssl::UniquePtr<BIGNUM>> GetRsaSqrtTwo( 106 int x); 107 108 // Compute compute 2^x. 109 absl::StatusOr<bssl::UniquePtr<BIGNUM>> ComputePowerOfTwo( 110 int x); 111 112 // ComputeHash sub-routine used during blindness and verification of RSA blind 113 // signatures protocol with or without public metadata. 114 absl::StatusOr<std::string> ComputeHash( 115 absl::string_view input, const EVP_MD& hasher); 116 117 // Computes the Carmichael LCM given phi(p) and phi(q) where N = p*q is a safe 118 // RSA modulus. 119 absl::StatusOr<bssl::UniquePtr<BIGNUM>> 120 ComputeCarmichaelLcm(const BIGNUM& phi_p, const BIGNUM& phi_q, BN_CTX& bn_ctx); 121 122 // Create bssl::UniquePtr<RSA> representing a RSA private key. 123 // 124 // Note that this method should not be used to create a key with public exponent 125 // greater than 2^32. 126 absl::StatusOr<bssl::UniquePtr<RSA>> 127 CreatePrivateKeyRSA(absl::string_view rsa_modulus, 128 absl::string_view public_exponent, 129 absl::string_view private_exponent, absl::string_view p, 130 absl::string_view q, absl::string_view dp, 131 absl::string_view dq, absl::string_view crt); 132 133 // Create bssl::UniquePtr<RSA> representing a RSA public key. 134 // 135 // Note that this method should not be used to create a key with public exponent 136 // greater than 2^32. 137 absl::StatusOr<bssl::UniquePtr<RSA>> 138 CreatePublicKeyRSA(absl::string_view rsa_modulus, 139 absl::string_view public_exponent); 140 141 // Create bssl::UniquePtr<RSA> representing a RSA public key derived using 142 // public metadata. 143 // 144 // If the boolean "use_rsa_public_exponent" is set to false, the public exponent 145 // is not used in any computations. 146 // 147 // Setting "use_rsa_public_exponent" to true is deprecated. 148 absl::StatusOr<bssl::UniquePtr<RSA>> 149 CreatePublicKeyRSAWithPublicMetadata(const BIGNUM& rsa_modulus, 150 const BIGNUM& public_exponent, 151 absl::string_view public_metadata, 152 bool use_rsa_public_exponent); 153 154 // Create bssl::UniquePtr<RSA> representing a RSA public key derived using 155 // public metadata. 156 // 157 // If the boolean "use_rsa_public_exponent" is set to false, the public exponent 158 // is not used in any computations. 159 // 160 // Setting "use_rsa_public_exponent" to true is deprecated. 161 absl::StatusOr<bssl::UniquePtr<RSA>> 162 CreatePublicKeyRSAWithPublicMetadata(absl::string_view rsa_modulus, 163 absl::string_view public_exponent, 164 absl::string_view public_metadata, 165 bool use_rsa_public_exponent); 166 167 // Compute exponent using only the public metadata and RSA modulus n. Assumes 168 // that n is a safe modulus i.e. it produces a strong RSA key pair. If not, the 169 // exponent may be invalid. 170 // 171 // Empty public metadata is considered to be a valid value for public_metadata 172 // and will output a valid exponent. 173 absl::StatusOr<bssl::UniquePtr<BIGNUM>> 174 ComputeExponentWithPublicMetadata(const BIGNUM& n, 175 absl::string_view public_metadata); 176 177 // Computes exponent by multiplying the public exponent e with the 178 // exponent derived from public metadata and RSA modulus n. Assumes that n is a 179 // safe modulus i.e. it produces a strong RSA key pair. If not, the exponent may 180 // be invalid. 181 // 182 // Empty public metadata is considered to be a valid value for public_metadata 183 // and will output an exponent different than `e` as well. 184 // 185 // This function is now deprecated. 186 absl::StatusOr<bssl::UniquePtr<BIGNUM>> 187 ComputeExponentWithPublicMetadataAndPublicExponent( 188 const BIGNUM& n, const BIGNUM& e, absl::string_view public_metadata); 189 190 // Helper method that implements RSA PSS Blind Signatures verification protocol 191 // for both the standard scheme as well as the public metadata version. 192 // 193 // For the public metadata version, 194 // 195 // 1) `rsa_public_key' must contain a public exponent derived using the public 196 // metadata. 197 // 198 // 2) The `message' must be an encoding of an original input message 199 // and the public metadata e.g. by using EncodeMessagePublicMetadata method in 200 // this file. The caller should make sure that its original input message is a 201 // random message. In case it is not, it should be concatenated with a random 202 // string. 203 absl::Status RsaBlindSignatureVerify( 204 int salt_length, const EVP_MD* sig_hash, const EVP_MD* mgf1_hash, 205 absl::string_view signature, absl::string_view message, 206 RSA* rsa_public_key); 207 208 // This method outputs a DER encoding of RSASSA-PSS (RSA Signature Scheme with 209 // Appendix - Probabilistic Signature Scheme) Public Key as described here 210 // https://datatracker.ietf.org/doc/html/rfc3447.html using the object 211 // identifier(s) here: https://oidref.com/1.2.840.113549.1.1.10 and using a 212 // fixed salt length of 48 bytes, SHA384 as the signature's hash function as 213 // well as the hash function that the signature's mask generating function is 214 // based on. A publicly availble equivalent function is available in Goa here: 215 // https://github.com/cloudflare/pat-go/blob/11579ba5b0b9b77d3e8e3d5247a98811227ac82e/x509util.go#L56 216 // 217 absl::StatusOr<std::string> RsaSsaPssPublicKeyToDerEncoding( 218 const RSA* rsa); 219 220 } // namespace anonymous_tokens 221 222 #endif // ANONYMOUS_TOKENS_CPP_CRYPTO_CRYPTO_UTILS_H_ 223