• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <openssl/type_check.h>
21 
22 #include <assert.h>
23 
24 #include "internal.h"
25 #include "../fipsmodule/bn/internal.h"
26 #include "../fipsmodule/ec/internal.h"
27 #include "../internal.h"
28 
29 
30 // This file implements hash-to-curve, as described in
31 // draft-irtf-cfrg-hash-to-curve-07.
32 //
33 // This hash-to-curve implementation is written generically with the
34 // expectation that we will eventually wish to support other curves. If it
35 // becomes a performance bottleneck, some possible optimizations by
36 // specializing it to the curve:
37 //
38 // - Rather than using a generic |felem_exp|, specialize the exponentation to
39 //   c2 with a faster addition chain.
40 //
41 // - |felem_mul| and |felem_sqr| are indirect calls to generic Montgomery
42 //   code. Given the few curves, we could specialize
43 //   |map_to_curve_simple_swu|. But doing this reasonably without duplicating
44 //   code in C is difficult. (C++ templates would be useful here.)
45 //
46 // - P-521's Z and c2 have small power-of-two absolute values. We could save
47 //   two multiplications in SSWU. (Other curves have reasonable values of Z
48 //   and inconvenient c2.) This is unlikely to be worthwhile without C++
49 //   templates to make specializing more convenient.
50 
51 // expand_message_xmd implements the operation described in section 5.3.1 of
52 // draft-irtf-cfrg-hash-to-curve-07. It returns one on success and zero on
53 // allocation failure or if |out_len| was too large. If |is_draft06| is one, it
54 // implements the operation from draft-irtf-cfrg-hash-to-curve-06 instead.
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,int is_draft06)55 static int expand_message_xmd(const EVP_MD *md, uint8_t *out, size_t out_len,
56                               const uint8_t *msg, size_t msg_len,
57                               const uint8_t *dst, size_t dst_len,
58                               int is_draft06) {
59   int ret = 0;
60   const size_t block_size = EVP_MD_block_size(md);
61   const size_t md_size = EVP_MD_size(md);
62   EVP_MD_CTX ctx;
63   EVP_MD_CTX_init(&ctx);
64 
65   // Long DSTs are hashed down to size. See section 5.3.3.
66   OPENSSL_STATIC_ASSERT(EVP_MAX_MD_SIZE < 256, "hashed DST still too large");
67   uint8_t dst_buf[EVP_MAX_MD_SIZE];
68   if (dst_len >= 256) {
69     static const char kPrefix[] = "H2C-OVERSIZE-DST-";
70     if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
71         !EVP_DigestUpdate(&ctx, kPrefix, sizeof(kPrefix) - 1) ||
72         !EVP_DigestUpdate(&ctx, dst, dst_len) ||
73         !EVP_DigestFinal_ex(&ctx, dst_buf, NULL)) {
74       goto err;
75     }
76     dst = dst_buf;
77     dst_len = md_size;
78   }
79   uint8_t dst_len_u8 = (uint8_t)dst_len;
80 
81   // Compute b_0.
82   static const uint8_t kZeros[EVP_MAX_MD_BLOCK_SIZE] = {0};
83   // If |out_len| exceeds 16 bits then |i| will wrap below causing an error to
84   // be returned. This depends on the static assert above.
85   uint8_t l_i_b_str_zero[3] = {out_len >> 8, out_len, 0};
86   uint8_t b_0[EVP_MAX_MD_SIZE];
87   if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
88       !EVP_DigestUpdate(&ctx, kZeros, block_size) ||
89       !EVP_DigestUpdate(&ctx, msg, msg_len) ||
90       !EVP_DigestUpdate(&ctx, l_i_b_str_zero, sizeof(l_i_b_str_zero)) ||
91       (is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
92       !EVP_DigestUpdate(&ctx, dst, dst_len) ||
93       (!is_draft06 && !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         (is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
118         !EVP_DigestUpdate(&ctx, dst, dst_len) ||
119         (!is_draft06 && !EVP_DigestUpdate(&ctx, &dst_len_u8, 1)) ||
120         !EVP_DigestFinal_ex(&ctx, b_i, NULL)) {
121       goto err;
122     }
123 
124     size_t todo = out_len >= md_size ? md_size : out_len;
125     OPENSSL_memcpy(out, b_i, todo);
126     out += todo;
127     out_len -= todo;
128     i++;
129   }
130 
131   ret = 1;
132 
133 err:
134   EVP_MD_CTX_cleanup(&ctx);
135   return ret;
136 }
137 
138 // num_bytes_to_derive determines the number of bytes to derive when hashing to
139 // a number modulo |modulus|. See the hash_to_field operation defined in
140 // section 5.2 of draft-irtf-cfrg-hash-to-curve-07.
num_bytes_to_derive(size_t * out,const BIGNUM * modulus,unsigned k)141 static int num_bytes_to_derive(size_t *out, const BIGNUM *modulus, unsigned k) {
142   size_t bits = BN_num_bits(modulus);
143   size_t L = (bits + k + 7) / 8;
144   // We require 2^(8*L) < 2^(2*bits - 2) <= n^2 so to fit in bounds for
145   // |felem_reduce| and |ec_scalar_reduce|. All defined hash-to-curve suites
146   // define |k| to be well under this bound. (|k| is usually around half of
147   // |p_bits|.)
148   if (L * 8 >= 2 * bits - 2 ||
149       L > 2 * EC_MAX_BYTES) {
150     assert(0);
151     OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
152     return 0;
153   }
154 
155   *out = L;
156   return 1;
157 }
158 
159 // big_endian_to_words decodes |in| as a big-endian integer and writes the
160 // 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)161 static void big_endian_to_words(BN_ULONG *out, size_t num_words,
162                                 const uint8_t *in, size_t len) {
163   assert(len <= num_words * sizeof(BN_ULONG));
164   // Ensure any excess bytes are zeroed.
165   OPENSSL_memset(out, 0, num_words * sizeof(BN_ULONG));
166   uint8_t *out_u8 = (uint8_t *)out;
167   for (size_t i = 0; i < len; i++) {
168     out_u8[len - 1 - i] = in[i];
169   }
170 }
171 
172 // hash_to_field implements the operation described in section 5.2
173 // of draft-irtf-cfrg-hash-to-curve-07, with count = 2. |k| is the security
174 // 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,int is_draft06)175 static int hash_to_field2(const EC_GROUP *group, const EVP_MD *md,
176                           EC_FELEM *out1, EC_FELEM *out2, const uint8_t *dst,
177                           size_t dst_len, unsigned k, const uint8_t *msg,
178                           size_t msg_len, int is_draft06) {
179   size_t L;
180   uint8_t buf[4 * EC_MAX_BYTES];
181   if (!num_bytes_to_derive(&L, &group->field, k) ||
182       !expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len,
183                           is_draft06)) {
184     return 0;
185   }
186   BN_ULONG words[2 * EC_MAX_WORDS];
187   size_t num_words = 2 * group->field.width;
188   big_endian_to_words(words, num_words, buf, L);
189   group->meth->felem_reduce(group, out1, words, num_words);
190   big_endian_to_words(words, num_words, buf + L, L);
191   group->meth->felem_reduce(group, out2, words, num_words);
192   return 1;
193 }
194 
195 // hash_to_scalar behaves like |hash_to_field2| but returns a value modulo the
196 // 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,int is_draft06)197 static int hash_to_scalar(const EC_GROUP *group, const EVP_MD *md,
198                           EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
199                           unsigned k, const uint8_t *msg, size_t msg_len,
200                           int is_draft06) {
201   size_t L;
202   uint8_t buf[EC_MAX_BYTES * 2];
203   if (!num_bytes_to_derive(&L, &group->order, k) ||
204       !expand_message_xmd(md, buf, L, msg, msg_len, dst, dst_len, is_draft06)) {
205     return 0;
206   }
207 
208   BN_ULONG words[2 * EC_MAX_WORDS];
209   size_t num_words = 2 * group->order.width;
210   big_endian_to_words(words, num_words, buf, L);
211   ec_scalar_reduce(group, out, words, num_words);
212   return 1;
213 }
214 
mul_A(const EC_GROUP * group,EC_FELEM * out,const EC_FELEM * in)215 static inline void mul_A(const EC_GROUP *group, EC_FELEM *out,
216                          const EC_FELEM *in) {
217   assert(group->a_is_minus3);
218   EC_FELEM tmp;
219   ec_felem_add(group, &tmp, in, in);      // tmp = 2*in
220   ec_felem_add(group, &tmp, &tmp, &tmp);  // tmp = 4*in
221   ec_felem_sub(group, out, in, &tmp);     // out = -3*in
222 }
223 
mul_minus_A(const EC_GROUP * group,EC_FELEM * out,const EC_FELEM * in)224 static inline void mul_minus_A(const EC_GROUP *group, EC_FELEM *out,
225                                const EC_FELEM *in) {
226   assert(group->a_is_minus3);
227   EC_FELEM tmp;
228   ec_felem_add(group, &tmp, in, in);   // tmp = 2*in
229   ec_felem_add(group, out, &tmp, in);  // out = 3*in
230 }
231 
232 // sgn0_le implements the operation described in section 4.1.2 of
233 // draft-irtf-cfrg-hash-to-curve-07.
sgn0_le(const EC_GROUP * group,const EC_FELEM * a)234 static BN_ULONG sgn0_le(const EC_GROUP *group, const EC_FELEM *a) {
235   uint8_t buf[EC_MAX_BYTES];
236   size_t len;
237   ec_felem_to_bytes(group, buf, &len, a);
238   return buf[len - 1] & 1;
239 }
240 
241 // map_to_curve_simple_swu implements the operation described in section 6.6.2
242 // of draft-irtf-cfrg-hash-to-curve-07, using the optimization in appendix
243 // D.2.1. It returns one on success and zero on error.
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_RAW_POINT * out,const EC_FELEM * u)244 static int map_to_curve_simple_swu(const EC_GROUP *group, const EC_FELEM *Z,
245                                    const BN_ULONG *c1, size_t num_c1,
246                                    const EC_FELEM *c2, EC_RAW_POINT *out,
247                                    const EC_FELEM *u) {
248   void (*const felem_mul)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a,
249                           const EC_FELEM *b) = group->meth->felem_mul;
250   void (*const felem_sqr)(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a) =
251       group->meth->felem_sqr;
252 
253   // This function requires the prime be 3 mod 4, and that A = -3.
254   if (group->field.width == 0 || (group->field.d[0] & 3) != 3 ||
255       !group->a_is_minus3) {
256     OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
257     return 0;
258   }
259 
260   EC_FELEM tv1, tv2, tv3, tv4, xd, x1n, x2n, tmp, gxd, gx1, y1, y2;
261   felem_sqr(group, &tv1, u);                         // tv1 = u^2
262   felem_mul(group, &tv3, Z, &tv1);                   // tv3 = Z * tv1
263   felem_sqr(group, &tv2, &tv3);                      // tv2 = tv3^2
264   ec_felem_add(group, &xd, &tv2, &tv3);              // xd = tv2 + tv3
265   ec_felem_add(group, &x1n, &xd, &group->one);       // x1n = xd + 1
266   felem_mul(group, &x1n, &x1n, &group->b);           // x1n = x1n * B
267   mul_minus_A(group, &xd, &xd);                      // xd = -A * xd
268   BN_ULONG e1 = ec_felem_non_zero_mask(group, &xd);  // e1 = xd == 0 [flipped]
269   mul_A(group, &tmp, Z);
270   ec_felem_select(group, &xd, e1, &xd, &tmp);  // xd = CMOV(xd, Z * A, e1)
271   felem_sqr(group, &tv2, &xd);                 // tv2 = xd^2
272   felem_mul(group, &gxd, &tv2, &xd);           // gxd = tv2 * xd = xd^3
273   mul_A(group, &tv2, &tv2);                    // tv2 = A * tv2
274   felem_sqr(group, &gx1, &x1n);                // gx1 = x1n^2
275   ec_felem_add(group, &gx1, &gx1, &tv2);       // gx1 = gx1 + tv2
276   felem_mul(group, &gx1, &gx1, &x1n);          // gx1 = gx1 * x1n
277   felem_mul(group, &tv2, &group->b, &gxd);     // tv2 = B * gxd
278   ec_felem_add(group, &gx1, &gx1, &tv2);       // gx1 = gx1 + tv2
279   felem_sqr(group, &tv4, &gxd);                // tv4 = gxd^2
280   felem_mul(group, &tv2, &gx1, &gxd);          // tv2 = gx1 * gxd
281   felem_mul(group, &tv4, &tv4, &tv2);          // tv4 = tv4 * tv2
282   group->meth->felem_exp(group, &y1, &tv4, c1, num_c1);  // y1 = tv4^c1
283   felem_mul(group, &y1, &y1, &tv2);                      // y1 = y1 * tv2
284   felem_mul(group, &x2n, &tv3, &x1n);                    // x2n = tv3 * x1n
285   felem_mul(group, &y2, &y1, c2);                        // y2 = y1 * c2
286   felem_mul(group, &y2, &y2, &tv1);                      // y2 = y2 * tv1
287   felem_mul(group, &y2, &y2, u);                         // y2 = y2 * u
288   felem_sqr(group, &tv2, &y1);                           // tv2 = y1^2
289   felem_mul(group, &tv2, &tv2, &gxd);                    // tv2 = tv2 * gxd
290   ec_felem_sub(group, &tv3, &tv2, &gx1);
291   BN_ULONG e2 =
292       ec_felem_non_zero_mask(group, &tv3);       // e2 = tv2 == gx1 [flipped]
293   ec_felem_select(group, &x1n, e2, &x2n, &x1n);  // xn = CMOV(x2n, x1n, e2)
294   ec_felem_select(group, &y1, e2, &y2, &y1);     // y = CMOV(y2, y1, e2)
295   BN_ULONG sgn0_u = sgn0_le(group, u);
296   BN_ULONG sgn0_y = sgn0_le(group, &y1);
297   BN_ULONG e3 = sgn0_u ^ sgn0_y;
298   e3 = ((BN_ULONG)0) - e3;  // e3 = sgn0(u) == sgn0(y) [flipped]
299   ec_felem_neg(group, &y2, &y1);
300   ec_felem_select(group, &y1, e3, &y2, &y1);  // y = CMOV(-y, y, e3)
301 
302   // Appendix D.1 describes how to convert (x1n, xd, y1, 1) to Jacobian
303   // coordinates. Note yd = 1. Also note that gxd computed above is xd^3.
304   felem_mul(group, &out->X, &x1n, &xd);     // X = xn * xd
305   felem_mul(group, &out->Y, &y1, &gxd);     // Y = yn * gxd = yn * xd^3
306   out->Z = xd;                              // Z = xd
307   return 1;
308 }
309 
hash_to_curve(const EC_GROUP * group,const EVP_MD * md,const EC_FELEM * Z,const EC_FELEM * c2,unsigned k,EC_RAW_POINT * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len,int is_draft06)310 static int hash_to_curve(const EC_GROUP *group, const EVP_MD *md,
311                          const EC_FELEM *Z, const EC_FELEM *c2, unsigned k,
312                          EC_RAW_POINT *out, const uint8_t *dst, size_t dst_len,
313                          const uint8_t *msg, size_t msg_len, int is_draft06) {
314   EC_FELEM u0, u1;
315   if (!hash_to_field2(group, md, &u0, &u1, dst, dst_len, k, msg, msg_len,
316                       is_draft06)) {
317     return 0;
318   }
319 
320   // Compute |c1| = (p - 3) / 4.
321   BN_ULONG c1[EC_MAX_WORDS];
322   size_t num_c1 = group->field.width;
323   if (!bn_copy_words(c1, num_c1, &group->field)) {
324     return 0;
325   }
326   bn_rshift_words(c1, c1, /*shift=*/2, /*num=*/num_c1);
327 
328   EC_RAW_POINT Q0, Q1;
329   if (!map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q0, &u0) ||
330       !map_to_curve_simple_swu(group, Z, c1, num_c1, c2, &Q1, &u1)) {
331     return 0;
332   }
333 
334   group->meth->add(group, out, &Q0, &Q1);  // R = Q0 + Q1
335   // All our curves have cofactor one, so |clear_cofactor| is a no-op.
336   return 1;
337 }
338 
felem_from_u8(const EC_GROUP * group,EC_FELEM * out,uint8_t a)339 static int felem_from_u8(const EC_GROUP *group, EC_FELEM *out, uint8_t a) {
340   uint8_t bytes[EC_MAX_BYTES] = {0};
341   size_t len = BN_num_bytes(&group->field);
342   bytes[len - 1] = a;
343   return ec_felem_from_bytes(group, out, bytes, len);
344 }
345 
ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(const EC_GROUP * group,EC_RAW_POINT * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)346 int ec_hash_to_curve_p384_xmd_sha512_sswu_draft07(
347     const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
348     size_t dst_len, const uint8_t *msg, size_t msg_len) {
349   // See section 8.3 of draft-irtf-cfrg-hash-to-curve-07.
350   if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
351     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
352     return 0;
353   }
354 
355   // kSqrt1728 was computed as follows in python3:
356   //
357   // p = 2**384 - 2**128 - 2**96 + 2**32 - 1
358   // z3 = 12**3
359   // c2 = pow(z3, (p+1)//4, p)
360   // assert z3 == pow(c2, 2, p)
361   // ", ".join("0x%02x" % b for b in c2.to_bytes(384//8, 'big')
362 
363   static const uint8_t kSqrt1728[] = {
364       0x01, 0x98, 0x77, 0xcc, 0x10, 0x41, 0xb7, 0x55, 0x57, 0x43, 0xc0, 0xae,
365       0x2e, 0x3a, 0x3e, 0x61, 0xfb, 0x2a, 0xaa, 0x2e, 0x0e, 0x87, 0xea, 0x55,
366       0x7a, 0x56, 0x3d, 0x8b, 0x59, 0x8a, 0x09, 0x40, 0xd0, 0xa6, 0x97, 0xa9,
367       0xe0, 0xb9, 0xe9, 0x2c, 0xfa, 0xa3, 0x14, 0xf5, 0x83, 0xc9, 0xd0, 0x66
368   };
369 
370   // Z = -12, c2 = sqrt(1728)
371   EC_FELEM Z, c2;
372   if (!felem_from_u8(group, &Z, 12) ||
373       !ec_felem_from_bytes(group, &c2, kSqrt1728, sizeof(kSqrt1728))) {
374     return 0;
375   }
376   ec_felem_neg(group, &Z, &Z);
377 
378   return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/192, out, dst,
379                        dst_len, msg, msg_len, /*is_draft06=*/0);
380 }
381 
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)382 int ec_hash_to_scalar_p384_xmd_sha512_draft07(
383     const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
384     const uint8_t *msg, size_t msg_len) {
385   if (EC_GROUP_get_curve_name(group) != NID_secp384r1) {
386     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
387     return 0;
388   }
389 
390   return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/192, msg,
391                         msg_len, /*is_draft06=*/0);
392 }
393 
ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(const EC_GROUP * group,EC_RAW_POINT * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)394 int ec_hash_to_curve_p521_xmd_sha512_sswu_draft06(
395     const EC_GROUP *group, EC_RAW_POINT *out, const uint8_t *dst,
396     size_t dst_len, const uint8_t *msg, size_t msg_len) {
397   // See section 8.3 of draft-irtf-cfrg-hash-to-curve-06.
398   if (EC_GROUP_get_curve_name(group) != NID_secp521r1) {
399     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
400     return 0;
401   }
402 
403   // Z = -4, c2 = 8.
404   EC_FELEM Z, c2;
405   if (!felem_from_u8(group, &Z, 4) ||
406       !felem_from_u8(group, &c2, 8)) {
407     return 0;
408   }
409   ec_felem_neg(group, &Z, &Z);
410 
411   return hash_to_curve(group, EVP_sha512(), &Z, &c2, /*k=*/256, out, dst,
412                        dst_len, msg, msg_len, /*is_draft06=*/1);
413 }
414 
ec_hash_to_scalar_p521_xmd_sha512_draft06(const EC_GROUP * group,EC_SCALAR * out,const uint8_t * dst,size_t dst_len,const uint8_t * msg,size_t msg_len)415 int ec_hash_to_scalar_p521_xmd_sha512_draft06(
416     const EC_GROUP *group, EC_SCALAR *out, const uint8_t *dst, size_t dst_len,
417     const uint8_t *msg, size_t msg_len) {
418   if (EC_GROUP_get_curve_name(group) != NID_secp521r1) {
419     OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
420     return 0;
421   }
422 
423   return hash_to_scalar(group, EVP_sha512(), out, dst, dst_len, /*k=*/256, msg,
424                         msg_len, /*is_draft06=*/1);
425 }
426