xref: /aosp_15_r20/external/cronet/third_party/anonymous_tokens/src/anonymous_tokens/cpp/crypto/crypto_utils.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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