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