xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/crypto/ec_extra/hash_to_curve.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /* Copyright (c) 2020, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/ec.h>
16 
17 #include <openssl/digest.h>
18 #include <openssl/err.h>
19 #include <openssl/nid.h>
20 
21 #include <assert.h>
22 
23 #include "internal.h"
24 #include "../fipsmodule/bn/internal.h"
25 #include "../fipsmodule/ec/internal.h"
26 #include "../internal.h"
27 
28 
29 // This file implements hash-to-curve, as described in RFC 9380.
30 //
31 // This hash-to-curve implementation is written generically with the
32 // expectation that we will eventually wish to support other curves. If it
33 // becomes a performance bottleneck, some possible optimizations by
34 // specializing it to the curve:
35 //
36 // - Rather than using a generic |felem_exp|, specialize the exponentation to
37 //   c2 with a faster addition chain.
38 //
39 // - |felem_mul| and |felem_sqr| are indirect calls to generic Montgomery
40 //   code. Given the few curves, we could specialize
41 //   |map_to_curve_simple_swu|. But doing this reasonably without duplicating
42 //   code in C is difficult. (C++ templates would be useful here.)
43 //
44 // - P-521's Z and c2 have small power-of-two absolute values. We could save
45 //   two multiplications in SSWU. (Other curves have reasonable values of Z
46 //   and inconvenient c2.) This is unlikely to be worthwhile without C++
47 //   templates to make specializing more convenient.
48 
49 // expand_message_xmd implements the operation described in section 5.3.1 of
50 // RFC 9380. It returns one on success and zero on error.
expand_message_xmd(const EVP_MD * md,uint8_t * out,size_t out_len,const uint8_t * msg,size_t msg_len,const uint8_t * dst,size_t dst_len)51 static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
52                               const uint8_t *msg, size_t msg_len,
53                               const uint8_t *dst, size_t dst_len) {
54   // See https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/issues/352
55   if (dst_len == 0) {
56     OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
57     return 0;
58   }
59 
60   int ret = 0;
61   const size_t block_size = EVP_MD_block_size(md);
62   const size_t md_size = EVP_MD_size(md);
63   EVP_MD_CTX ctx;
64   EVP_MD_CTX_init(&ctx);
65 
66   // Long DSTs are hashed down to size. See section 5.3.3.
67   static_assert(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
68   uint8_t dst_buf[EVP_MAX_MD_SIZE];
69   if (dst_len >= 256) {
70     static const char kPrefix[] = "H2C-OVERSIZE-DST-";
71     if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
72         !EVP_DigestUpdate(&ctx, kPrefix, sizeof(kPrefix) - 1) ||
73         !EVP_DigestUpdate(&ctx, dst, dst_len) ||
74         !EVP_DigestFinal_ex(&ctx, dst_buf, NULL)) {
75       goto err;
76     }
77     dst = dst_buf;
78     dst_len = md_size;
79   }
80   uint8_t dst_len_u8 = (uint8_t)dst_len;
81 
82   // Compute b_0.
83   static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
84   // If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
85   // be returned. This depends on the static assert above.
86   uint8_t l_i_b_str_zero[3] = {out_len >> 8, out_len, 0};
87   uint8_t b_0[EVP_MAX_MD_SIZE];
88   if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
89       !EVP_DigestUpdate(&ctx, kZeros, block_size) ||
90       !EVP_DigestUpdate(&ctx, msg, msg_len) ||
91       !EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
92       !EVP_DigestUpdate(&ctx, dst, dst_len) ||
93       !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
94       !EVP_DigestFinal_ex(&ctx, b_0, NULL)) {
95     goto err;
96   }
97 
98   uint8_t b_i[EVP_MAX_MD_SIZE];
99   uint8_t i = 1;
100   while (out_len > 0) {
101     if (i == 0) {
102       // Input was too large.
103       OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
104       goto err;
105     }
106     if (i > 1) {
107       for (size_t j = 0; j < md_size; j++) {
108         b_i[j] ^= b_0[j];
109       }
110     } else {
111       OPENSSL_memcpy(b_i, b_0, md_size);
112     }
113 
114     if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
115         !EVP_DigestUpdate(&ctx, b_i, md_size) ||
116         !EVP_DigestUpdate(&ctx, &i, 1) ||
117         !EVP_DigestUpdate(&ctx, dst, dst_len) ||
118         !EVP_DigestUpdate(&ctx, &dst_len_u8, 1) ||
119         !EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
120       goto err;
121     }
122 
123     size_t todo = out_len >= md_size ? md_size : out_len;
124     OPENSSL_memcpy(out, b_i, todo);
125     out += todo;
126     out_len -= todo;
127     i++;
128   }
129 
130   ret = 1;
131 
132 err:
133   EVP_MD_CTX_cleanup(&ctx);
134   return ret;
135 }
136 
137 // num_bytes_to_derive determines the number of bytes to derive when hashing to
138 // a number modulo |modulus|. See the hash_to_field operation defined in
139 // section 5.2 of RFC 9380.
num_bytes_to_derive(size_t * out,const BIGNUM * modulus,unsigned k)140 static int num_bytes_to_derive(size_t *out, const BIGNUM *modulus, unsigned k) {
141   size_t bits = BN_num_bits(modulus);
142   size_t L = (bits + k + 7) / 8;
143   // We require 2^(8*L) < 2^(2*bits - 2) <= n^2 so to fit in bounds for
144   // |felem_reduce| and |ec_scalar_reduce|. All defined hash-to-curve suites
145   // define |k| to be well under this bound. (|k| is usually around half of
146   // |p_bits|.)
147   if (L * 8 >= 2 * bits - 2 ||
148       L > 2 * EC_MAX_BYTES) {
149     assert(0);
150     OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
151     return 0;
152   }
153 
154   *out = L;
155   return 1;
156 }
157 
158 // big_endian_to_words decodes |in| as a big-endian integer and writes the
159 // result to |out|. |num_words| must be large enough to contain the output.
big_endian_to_words(BN_ULONG * out,size_t num_words,const uint8_t * in,size_t len)160 static void big_endian_to_words(BN_ULONG *out, size_t num_words,
161                                 const uint8_t *in, size_t len) {
162   assert(len <= num_words * sizeof(BN_ULONG));
163   // Ensure any excess bytes are zeroed.
164   OPENSSL_memset(out, 0, num_words * sizeof(BN_ULONG));
165   uint8_t *out_u8 = (uint8_t *)out;
166   for (size_t i = 0; i < len; i++) {
167     out_u8[len - 1 - i] = in[i];
168   }
169 }
170 
171 // hash_to_field implements the operation described in section 5.2
172 // of RFC 9380, with count = 2. |k| is the security factor.
hash_to_field2(const EC_GROUP * group,const EVP_MD * md,EC_FELEM * out1,EC_FELEM * out2,const uint8_t * dst,size_t dst_len,unsigned k,const uint8_t * msg,size_t msg_len)173 static int hash_to_field2(const EC_GROUP *group, const EVP_MD *md,
174                           EC_FELEM *out1, EC_FELEM *out2, const uint8_t *dst,
175                           size_t dst_len, unsigned k, const uint8_t *msg,
176                           size_t msg_len) {
177   size_t L;
178   uint8_t buf[4 * EC_MAX_BYTES];
179   if (!num_bytes_to_derive(&L, &group->field.N, k) ||
180       !expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len)) {
181     return 0;
182   }
183   BN_ULONG words[2 * EC_MAX_WORDS];
184   size_t num_words = 2 * group->field.N.width;
185   big_endian_to_words(words, num_words, buf, L);
186   group->meth->felem_reduce(group, out1, words, num_words);
187   big_endian_to_words(words, num_words, buf + L, L);
188   group->meth->felem_reduce(group, out2, words, num_words);
189   return 1;
190 }
191 
192 // hash_to_scalar behaves like |hash_to_field2| but returns a value modulo the
193 // group order rather than a field element. |k| is the security factor.
hash_to_scalar(const EC_GROUP * group,const EVP_MD * md,EC_SCALAR * out,const uint8_t * dst,size_t dst_len,unsigned k,const uint8_t * msg,size_t msg_len)194 static int hash_to_scalar(const EC_GROUP *group, const EVP_MD *md,
195                           EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
196                           unsigned k, const uint8_t *msg, size_t msg_len) {
197   const BIGNUM *order = EC_GROUP_get0_order(group);
198   size_t L;
199   uint8_t buf[EC_MAX_BYTES * 2];
200   if (!num_bytes_to_derive(&L, order, k) ||
201       !expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len)) {
202     return 0;
203   }
204 
205   BN_ULONG words[2 * EC_MAX_WORDS];
206   size_t num_words = 2 * order->width;
207   big_endian_to_words(words, num_words, buf, L);
208   ec_scalar_reduce(group, out, words, num_words);
209   return 1;
210 }
211 
mul_A(const EC_GROUP * group,EC_FELEM * out,const EC_FELEM * in)212 static inline void mul_A(const EC_GROUP *group, EC_FELEM *out,
213                          const EC_FELEM *in) {
214   assert(group->a_is_minus3);
215   EC_FELEM tmp;
216   ec_felem_add(group, &tmp, in, in);      // tmp = 2*in
217   ec_felem_add(group, &tmp, &tmp, &tmp);  // tmp = 4*in
218   ec_felem_sub(group, out, in, &tmp);     // out = -3*in
219 }
220 
221 // sgn0 implements the operation described in section 4.1.2 of RFC 9380.
sgn0(const EC_GROUP * group,const EC_FELEM * a)222 static BN_ULONG sgn0(const EC_GROUP *group, const EC_FELEM *a) {
223   uint8_t buf[EC_MAX_BYTES];
224   size_t len;
225   ec_felem_to_bytes(group, buf, &len, a);
226   return buf[len - 1] & 1;
227 }
228 
is_3mod4(const EC_GROUP * group)229 OPENSSL_UNUSED static int is_3mod4(const EC_GROUP *group) {
230   return group->field.N.width > 0 && (group->field.N.d[0] & 3) == 3;
231 }
232 
233 // sqrt_ratio_3mod4 implements the operation described in appendix F.2.1.2
234 // of RFC 9380.
sqrt_ratio_3mod4(const EC_GROUP * group,const EC_FELEM * Z,const BN_ULONG * c1,size_t num_c1,const EC_FELEM * c2,EC_FELEM * out_y,const EC_FELEM * u,const EC_FELEM * v)235 static BN_ULONG sqrt_ratio_3mod4(const EC_GROUP *group, const EC_FELEM *Z,
236                                  const BN_ULONG *c1, size_t num_c1,
237                                  const EC_FELEM *c2, EC_FELEM *out_y,
238                                  const EC_FELEM *u, const EC_FELEM *v) {
239   assert(is_3mod4(group));
240 
241   void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
242                           const EC_FELEM *b) = group->meth->felem_mul;
243   void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
244       group->meth->felem_sqr;
245 
246   EC_FELEM tv1, tv2, tv3, y1, y2;
247   felem_sqr(group, &tv1, v);                             // 1. tv1 = v^2
248   felem_mul(group, &tv2, u, v);                          // 2. tv2 = u * v
249   felem_mul(group, &tv1, &tv1, &tv2);                    // 3. tv1 = tv1 * tv2
250   group->meth->felem_exp(group, &y1, &tv1, c1, num_c1);  // 4. y1 = tv1^c1
251   felem_mul(group, &y1, &y1, &tv2);                      // 5. y1 = y1 * tv2
252   felem_mul(group, &y2, &y1, c2);                        // 6. y2 = y1 * c2
253   felem_sqr(group, &tv3, &y1);                           // 7. tv3 = y1^2
254   felem_mul(group, &tv3, &tv3, v);                       // 8. tv3 = tv3 * v
255 
256   // 9. isQR = tv3 == u
257   // 10. y = CMOV(y2, y1, isQR)
258   // 11. return (isQR, y)
259   //
260   // Note the specification's CMOV function and our |ec_felem_select| have the
261   // opposite argument order.
262   ec_felem_sub(group, &tv1, &tv3, u);
263   const BN_ULONG isQR = ~ec_felem_non_zero_mask(group, &tv1);
264   ec_felem_select(group, out_y, isQR, &y1, &y2);
265   return isQR;
266 }
267 
268 // map_to_curve_simple_swu implements the operation described in section 6.6.2
269 // of RFC 9380, using the straight-line implementation in appendix F.2.
map_to_curve_simple_swu(const EC_GROUP * group,const EC_FELEM * Z,const BN_ULONG * c1,size_t num_c1,const EC_FELEM * c2,EC_JACOBIAN * out,const EC_FELEM * u)270 static void map_to_curve_simple_swu(const EC_GROUP *group, const EC_FELEM *Z,
271                                     const BN_ULONG *c1, size_t num_c1,
272                                     const EC_FELEM *c2, EC_JACOBIAN *out,
273                                     const EC_FELEM *u) {
274   // This function requires the prime be 3 mod 4, and that A = -3.
275   assert(is_3mod4(group));
276   assert(group->a_is_minus3);
277 
278   void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
279                           const EC_FELEM *b) = group->meth->felem_mul;
280   void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
281       group->meth->felem_sqr;
282 
283   EC_FELEM tv1, tv2, tv3, tv4, tv5, tv6, x, y, y1;
284   felem_sqr(group, &tv1, u);                             // 1. tv1 = u^2
285   felem_mul(group, &tv1, Z, &tv1);                       // 2. tv1 = Z * tv1
286   felem_sqr(group, &tv2, &tv1);                          // 3. tv2 = tv1^2
287   ec_felem_add(group, &tv2, &tv2, &tv1);                 // 4. tv2 = tv2 + tv1
288   ec_felem_add(group, &tv3, &tv2, ec_felem_one(group));  // 5. tv3 = tv2 + 1
289   felem_mul(group, &tv3, &group->b, &tv3);               // 6. tv3 = B * tv3
290 
291   // 7. tv4 = CMOV(Z, -tv2, tv2 != 0)
292   const BN_ULONG tv2_non_zero = ec_felem_non_zero_mask(group, &tv2);
293   ec_felem_neg(group, &tv4, &tv2);
294   ec_felem_select(group, &tv4, tv2_non_zero, &tv4, Z);
295 
296   mul_A(group, &tv4, &tv4);                 // 8. tv4 = A * tv4
297   felem_sqr(group, &tv2, &tv3);             // 9. tv2 = tv3^2
298   felem_sqr(group, &tv6, &tv4);             // 10. tv6 = tv4^2
299   mul_A(group, &tv5, &tv6);                 // 11. tv5 = A * tv6
300   ec_felem_add(group, &tv2, &tv2, &tv5);    // 12. tv2 = tv2 + tv5
301   felem_mul(group, &tv2, &tv2, &tv3);       // 13. tv2 = tv2 * tv3
302   felem_mul(group, &tv6, &tv6, &tv4);       // 14. tv6 = tv6 * tv4
303   felem_mul(group, &tv5, &group->b, &tv6);  // 15. tv5 = B * tv6
304   ec_felem_add(group, &tv2, &tv2, &tv5);    // 16. tv2 = tv2 + tv5
305   felem_mul(group, &x, &tv1, &tv3);         // 17. x = tv1 * tv3
306 
307   // 18. (is_gx1_square, y1) = sqrt_ratio(tv2, tv6)
308   const BN_ULONG is_gx1_square =
309       sqrt_ratio_3mod4(group, Z, c1, num_c1, c2, &y1, &tv2, &tv6);
310 
311   felem_mul(group, &y, &tv1, u);  // 19. y = tv1 * u
312   felem_mul(group, &y, &y, &y1);  // 20. y = y * y1
313 
314   // 21. x = CMOV(x, tv3, is_gx1_square)
315   ec_felem_select(group, &x, is_gx1_square, &tv3, &x);
316   // 22. y = CMOV(y, y1, is_gx1_square)
317   ec_felem_select(group, &y, is_gx1_square, &y1, &y);
318 
319   // 23. e1 = sgn0(u) == sgn0(y)
320   BN_ULONG sgn0_u = sgn0(group, u);
321   BN_ULONG sgn0_y = sgn0(group, &y);
322   BN_ULONG not_e1 = sgn0_u ^ sgn0_y;
323   not_e1 = ((BN_ULONG)0) - not_e1;
324 
325   // 24. y = CMOV(-y, y, e1)
326   ec_felem_neg(group, &tv1, &y);
327   ec_felem_select(group, &y, not_e1, &tv1, &y);
328 
329   // 25. x = x / tv4
330   //
331   // Our output is in projective coordinates, so rather than inverting |tv4|
332   // now, represent (x / tv4, y) as (x * tv4, y * tv4^3, tv4). This is much more
333   // efficient if the caller will do further computation on the output. (If the
334   // caller will immediately convert to affine coordinates, it is slightly less
335   // efficient, but only by a few field multiplications.)
336   felem_mul(group, &out->X, &x, &tv4);
337   felem_mul(group, &out->Y, &y, &tv6);
338   out->Z = tv4;
339 }
340 
hash_to_curve(const EC_GROUP * group,const EVP_MD * md,const EC_FELEM * Z,const EC_FELEM * c2,unsigned k,EC_JACOBIAN * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)341 static int hash_to_curve(const EC_GROUP *group, const EVP_MD *md,
342                          const EC_FELEM *Z, const EC_FELEM *c2, unsigned k,
343                          EC_JACOBIAN *out, const uint8_t *dst, size_t dst_len,
344                          const uint8_t *msg, size_t msg_len) {
345   EC_FELEM u0, u1;
346   if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len)) {
347     return 0;
348   }
349 
350   // Compute |c1| = (p - 3) / 4.
351   BN_ULONG c1[EC_MAX_WORDS];
352   size_t num_c1 = group->field.N.width;
353   if (!bn_copy_words(c1, num_c1, &group->field.N)) {
354     return 0;
355   }
356   bn_rshift_words(c1, c1, /*shift=*/2, /*num=*/num_c1);
357 
358   EC_JACOBIAN Q0, Q1;
359   map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q0, &u0);
360   map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q1, &u1);
361 
362   group->meth->add(group, out, &Q0, &Q1);  // R = Q0 + Q1
363   // All our curves have cofactor one, so |clear_cofactor| is a no-op.
364   return 1;
365 }
366 
felem_from_u8(const EC_GROUP * group,EC_FELEM * out,uint8_t a)367 static int felem_from_u8(const EC_GROUP *group, EC_FELEM *out, uint8_t a) {
368   uint8_t bytes[EC_MAX_BYTES] = {0};
369   size_t len = BN_num_bytes(&group->field.N);
370   bytes[len - 1] = a;
371   return ec_felem_from_bytes(group, out, bytes, len);
372 }
373 
374 // kP256Sqrt10 is sqrt(10) in P-256's field. It was computed as follows in
375 // python3:
376 //
377 // p =  2**256 - 2**224 + 2**192 + 2**96 - 1
378 // c2 = pow(10, (p+1)//4, p)
379 // assert pow(c2, 2, p) == 10
380 // ", ".join("0x%02x" % b for b in c2.to_bytes(256//8, 'big'))
381 static const uint8_t kP256Sqrt10[] = {
382     0xda, 0x53, 0x8e, 0x3b, 0xe1, 0xd8, 0x9b, 0x99, 0xc9, 0x78, 0xfc,
383     0x67, 0x51, 0x80, 0xaa, 0xb2, 0x7b, 0x8d, 0x1f, 0xf8, 0x4c, 0x55,
384     0xd5, 0xb6, 0x2c, 0xcd, 0x34, 0x27, 0xe4, 0x33, 0xc4, 0x7f};
385 
386 // kP384Sqrt12 is sqrt(12) in P-384's field. It was computed as follows in
387 // python3:
388 //
389 // p = 2**384 - 2**128 - 2**96 + 2**32 - 1
390 // c2 = pow(12, (p+1)//4, p)
391 // assert pow(c2, 2, p) == 12
392 // ", ".join("0x%02x" % b for b in c2.to_bytes(384//8, 'big'))
393 static const uint8_t kP384Sqrt12[] = {
394     0x2a, 0xcc, 0xb4, 0xa6, 0x56, 0xb0, 0x24, 0x9c, 0x71, 0xf0, 0x50, 0x0e,
395     0x83, 0xda, 0x2f, 0xdd, 0x7f, 0x98, 0xe3, 0x83, 0xd6, 0x8b, 0x53, 0x87,
396     0x1f, 0x87, 0x2f, 0xcb, 0x9c, 0xcb, 0x80, 0xc5, 0x3c, 0x0d, 0xe1, 0xf8,
397     0xa8, 0x0f, 0x7e, 0x19, 0x14, 0xe2, 0xec, 0x69, 0xf5, 0xa6, 0x26, 0xb3};
398 
ec_hash_to_curve_p256_xmd_sha256_sswu(const EC_GROUP * group,EC_JACOBIAN * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)399 int ec_hash_to_curve_p256_xmd_sha256_sswu(const EC_GROUP *group,
400                                           EC_JACOBIAN *out, const uint8_t *dst,
401                                           size_t dst_len, const uint8_t *msg,
402                                           size_t msg_len) {
403   // See section 8.3 of RFC 9380.
404   if (EC_GROUP_get_curve_name(group) != NID_X9_62_prime256v1) {
405     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
406     return 0;
407   }
408 
409   // Z = -10, c2 = sqrt(10)
410   EC_FELEM Z, c2;
411   if (!felem_from_u8(group, &Z, 10) ||
412       !ec_felem_from_bytes(group, &c2, kP256Sqrt10, sizeof(kP256Sqrt10))) {
413     return 0;
414   }
415   ec_felem_neg(group, &Z, &Z);
416 
417   return hash_to_curve(group, EVP_sha256(), &Z, &c2, /*k=*/128, out, dst,
418                        dst_len, msg, msg_len);
419 }
420 
EC_hash_to_curve_p256_xmd_sha256_sswu(const EC_GROUP * group,EC_POINT * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)421 int EC_hash_to_curve_p256_xmd_sha256_sswu(const EC_GROUP *group, EC_POINT *out,
422                                           const uint8_t *dst, size_t dst_len,
423                                           const uint8_t *msg, size_t msg_len) {
424   if (EC_GROUP_cmp(group, out->group, NULL) != 0) {
425     OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
426     return 0;
427   }
428   return ec_hash_to_curve_p256_xmd_sha256_sswu(group, &out->raw, dst, dst_len,
429                                                msg, msg_len);
430 }
431 
ec_hash_to_curve_p384_xmd_sha384_sswu(const EC_GROUP * group,EC_JACOBIAN * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)432 int ec_hash_to_curve_p384_xmd_sha384_sswu(const EC_GROUP *group,
433                                           EC_JACOBIAN *out, const uint8_t *dst,
434                                           size_t dst_len, const uint8_t *msg,
435                                           size_t msg_len) {
436   // See section 8.3 of RFC 9380.
437   if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
438     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
439     return 0;
440   }
441 
442   // Z = -12, c2 = sqrt(12)
443   EC_FELEM Z, c2;
444   if (!felem_from_u8(group, &Z, 12) ||
445       !ec_felem_from_bytes(group, &c2, kP384Sqrt12, sizeof(kP384Sqrt12))) {
446     return 0;
447   }
448   ec_felem_neg(group, &Z, &Z);
449 
450   return hash_to_curve(group, EVP_sha384(), &Z, &c2, /*k=*/192, out, dst,
451                        dst_len, msg, msg_len);
452 }
453 
EC_hash_to_curve_p384_xmd_sha384_sswu(const EC_GROUP * group,EC_POINT * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)454 int EC_hash_to_curve_p384_xmd_sha384_sswu(const EC_GROUP *group, EC_POINT *out,
455                                           const uint8_t *dst, size_t dst_len,
456                                           const uint8_t *msg, size_t msg_len) {
457   if (EC_GROUP_cmp(group, out->group, NULL) != 0) {
458     OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
459     return 0;
460   }
461   return ec_hash_to_curve_p384_xmd_sha384_sswu(group, &out->raw, dst, dst_len,
462                                                msg, msg_len);
463 }
464 
ec_hash_to_scalar_p384_xmd_sha384(const EC_GROUP * group,EC_SCALAR * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)465 int ec_hash_to_scalar_p384_xmd_sha384(
466     const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
467     const uint8_t *msg, size_t msg_len) {
468   if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
469     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
470     return 0;
471   }
472 
473   return hash_to_scalar(group, EVP_sha384(), out, dst, dst_len, /*k=*/192, msg,
474                         msg_len);
475 }
476 
ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(const EC_GROUP * group,EC_JACOBIAN * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)477 int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
478     const EC_GROUP *group, EC_JACOBIAN *out, const uint8_t *dst,
479     size_t dst_len, const uint8_t *msg, size_t msg_len) {
480   // See section 8.3 of draft-irtf-cfrg-hash-to-curve-07.
481   if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
482     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
483     return 0;
484   }
485 
486   // Z = -12, c2 = sqrt(12)
487   EC_FELEM Z, c2;
488   if (!felem_from_u8(group, &Z, 12) ||
489       !ec_felem_from_bytes(group, &c2, kP384Sqrt12, sizeof(kP384Sqrt12))) {
490     return 0;
491   }
492   ec_felem_neg(group, &Z, &Z);
493 
494   return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/192, out, dst,
495                        dst_len, msg, msg_len);
496 }
497 
ec_hash_to_scalar_p384_xmd_sha512_draft07(const EC_GROUP * group,EC_SCALAR * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)498 int ec_hash_to_scalar_p384_xmd_sha512_draft07(
499     const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
500     const uint8_t *msg, size_t msg_len) {
501   if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
502     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
503     return 0;
504   }
505 
506   return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/192, msg,
507                         msg_len);
508 }
509