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