• 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 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