Coverage Report

Created: 2025-04-24 07:09

/src/blst_normal/src/e1.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright Supranational LLC
3
 * Licensed under the Apache License, Version 2.0, see LICENSE for details.
4
 * SPDX-License-Identifier: Apache-2.0
5
 */
6
7
#include "point.h"
8
#include "fields.h"
9
#include "errors.h"
10
11
/*
12
 * y^2 = x^3 + B
13
 */
14
static const vec384 B_E1 = {        /* (4 << 384) % P */
15
    TO_LIMB_T(0xaa270000000cfff3), TO_LIMB_T(0x53cc0032fc34000a),
16
    TO_LIMB_T(0x478fe97a6b0a807f), TO_LIMB_T(0xb1d37ebee6ba24d7),
17
    TO_LIMB_T(0x8ec9733bbf78ab2f), TO_LIMB_T(0x09d645513d83de7e)
18
};
19
20
const POINTonE1 BLS12_381_G1 = {    /* generator point [in Montgomery] */
21
  /* (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905
22
   *    a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P */
23
  { TO_LIMB_T(0x5cb38790fd530c16), TO_LIMB_T(0x7817fc679976fff5),
24
    TO_LIMB_T(0x154f95c7143ba1c1), TO_LIMB_T(0xf0ae6acdf3d0e747),
25
    TO_LIMB_T(0xedce6ecc21dbf440), TO_LIMB_T(0x120177419e0bfb75) },
26
  /* (0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af6
27
   *    00db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 << 384) % P */
28
  { TO_LIMB_T(0xbaac93d50ce72271), TO_LIMB_T(0x8c22631a7918fd8e),
29
    TO_LIMB_T(0xdd595f13570725ce), TO_LIMB_T(0x51ac582950405194),
30
    TO_LIMB_T(0x0e1c8c3fad0059c0), TO_LIMB_T(0x0bbc3efc5008a26a) },
31
  { ONE_MONT_P }
32
};
33
34
const POINTonE1 BLS12_381_NEG_G1 = { /* negative generator [in Montgomery] */
35
  /* (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905
36
   *    a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P */
37
  { TO_LIMB_T(0x5cb38790fd530c16), TO_LIMB_T(0x7817fc679976fff5),
38
    TO_LIMB_T(0x154f95c7143ba1c1), TO_LIMB_T(0xf0ae6acdf3d0e747),
39
    TO_LIMB_T(0xedce6ecc21dbf440), TO_LIMB_T(0x120177419e0bfb75) },
40
  /* (0x114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c9
41
   *    6655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca << 384) % P */
42
  { TO_LIMB_T(0xff526c2af318883a), TO_LIMB_T(0x92899ce4383b0270),
43
    TO_LIMB_T(0x89d7738d9fa9d055), TO_LIMB_T(0x12caf35ba344c12a),
44
    TO_LIMB_T(0x3cff1b76964b5317), TO_LIMB_T(0x0e44d2ede9774430) },
45
  { ONE_MONT_P }
46
};
47
48
static inline void mul_by_b_onE1(vec384 out, const vec384 in)
49
7.23k
{   lshift_fp(out, in, 2);   }
50
51
static inline void mul_by_4b_onE1(vec384 out, const vec384 in)
52
0
{   lshift_fp(out, in, 4);   }
53
54
static void POINTonE1_cneg(POINTonE1 *p, bool_t cbit)
55
311k
{   cneg_fp(p->Y, p->Y, cbit);   }
56
57
void blst_p1_cneg(POINTonE1 *a, int cbit)
58
2.79k
{   POINTonE1_cneg(a, is_zero(cbit) ^ 1);   }
59
60
static void POINTonE1_from_Jacobian(POINTonE1 *out, const POINTonE1 *in)
61
4.10k
{
62
4.10k
    vec384 Z, ZZ;
63
4.10k
    limb_t inf = vec_is_zero(in->Z, sizeof(in->Z));
64
65
4.10k
    reciprocal_fp(Z, in->Z);                            /* 1/Z   */
66
67
4.10k
    sqr_fp(ZZ, Z);
68
4.10k
    mul_fp(out->X, in->X, ZZ);                          /* X = X/Z^2 */
69
70
4.10k
    mul_fp(ZZ, ZZ, Z);
71
4.10k
    mul_fp(out->Y, in->Y, ZZ);                          /* Y = Y/Z^3 */
72
73
4.10k
    vec_select(out->Z, in->Z, BLS12_381_G1.Z,
74
4.10k
                       sizeof(BLS12_381_G1.Z), inf);    /* Z = inf ? 0 : 1 */
75
4.10k
}
76
77
void blst_p1_from_jacobian(POINTonE1 *out, const POINTonE1 *a)
78
0
{   POINTonE1_from_Jacobian(out, a);   }
79
80
static void POINTonE1_to_affine(POINTonE1_affine *out, const POINTonE1 *in)
81
9.87k
{
82
9.87k
    POINTonE1 p;
83
84
9.87k
    if (!vec_is_equal(in->Z, BLS12_381_Rx.p, sizeof(in->Z))) {
85
4.10k
        POINTonE1_from_Jacobian(&p, in);
86
4.10k
        in = &p;
87
4.10k
    }
88
9.87k
    vec_copy(out, in, sizeof(*out));
89
9.87k
}
90
91
void blst_p1_to_affine(POINTonE1_affine *out, const POINTonE1 *a)
92
9.87k
{   POINTonE1_to_affine(out, a);   }
93
94
void blst_p1_from_affine(POINTonE1 *out, const POINTonE1_affine *a)
95
2.47k
{
96
2.47k
    vec_copy(out, a, sizeof(*a));
97
2.47k
    vec_select(out->Z, a->X, BLS12_381_Rx.p, sizeof(out->Z),
98
2.47k
                       vec_is_zero(a, sizeof(*a)));
99
2.47k
}
100
101
static bool_t POINTonE1_affine_on_curve(const POINTonE1_affine *p)
102
19.0k
{
103
19.0k
    vec384 XXX, YY;
104
105
19.0k
    sqr_fp(XXX, p->X);
106
19.0k
    mul_fp(XXX, XXX, p->X);                             /* X^3 */
107
19.0k
    add_fp(XXX, XXX, B_E1);                             /* X^3 + B */
108
109
19.0k
    sqr_fp(YY, p->Y);                                   /* Y^2 */
110
111
19.0k
    return vec_is_equal(XXX, YY, sizeof(XXX));
112
19.0k
}
113
114
int blst_p1_affine_on_curve(const POINTonE1_affine *p)
115
18.9k
{   return (int)(POINTonE1_affine_on_curve(p) | vec_is_zero(p, sizeof(*p)));   }
116
117
static bool_t POINTonE1_on_curve(const POINTonE1 *p)
118
7.23k
{
119
7.23k
    vec384 XXX, YY, BZ6;
120
7.23k
    limb_t inf = vec_is_zero(p->Z, sizeof(p->Z));
121
122
7.23k
    sqr_fp(BZ6, p->Z);
123
7.23k
    mul_fp(BZ6, BZ6, p->Z);
124
7.23k
    sqr_fp(BZ6, BZ6);                                   /* Z^6 */
125
7.23k
    mul_by_b_onE1(BZ6, BZ6);                            /* B*Z^6 */
126
127
7.23k
    sqr_fp(XXX, p->X);
128
7.23k
    mul_fp(XXX, XXX, p->X);                             /* X^3 */
129
7.23k
    add_fp(XXX, XXX, BZ6);                              /* X^3 + B*Z^6 */
130
131
7.23k
    sqr_fp(YY, p->Y);                                   /* Y^2 */
132
133
7.23k
    return vec_is_equal(XXX, YY, sizeof(XXX)) | inf;
134
7.23k
}
135
136
int blst_p1_on_curve(const POINTonE1 *p)
137
7.23k
{   return (int)POINTonE1_on_curve(p);   }
138
139
static limb_t POINTonE1_affine_Serialize_BE(unsigned char out[96],
140
                                            const POINTonE1_affine *in)
141
92
{
142
92
    vec384 temp;
143
144
92
    from_fp(temp, in->X);
145
92
    be_bytes_from_limbs(out, temp, sizeof(temp));
146
147
92
    from_fp(temp, in->Y);
148
92
    be_bytes_from_limbs(out + 48, temp, sizeof(temp));
149
150
92
    return sgn0_pty_mod_384(temp, BLS12_381_P);
151
92
}
152
153
void blst_p1_affine_serialize(unsigned char out[96],
154
                              const POINTonE1_affine *in)
155
40
{
156
40
    if (vec_is_zero(in->X, 2*sizeof(in->X))) {
157
0
        bytes_zero(out, 96);
158
0
        out[0] = 0x40;    /* infinity bit */
159
40
    } else {
160
40
        (void)POINTonE1_affine_Serialize_BE(out, in);
161
40
    }
162
40
}
163
164
static limb_t POINTonE1_Serialize_BE(unsigned char out[96],
165
                                     const POINTonE1 *in)
166
52
{
167
52
    POINTonE1 p;
168
169
52
    if (!vec_is_equal(in->Z, BLS12_381_Rx.p, sizeof(in->Z))) {
170
0
        POINTonE1_from_Jacobian(&p, in);
171
0
        in = &p;
172
0
    }
173
174
52
    return POINTonE1_affine_Serialize_BE(out, (const POINTonE1_affine *)in);
175
52
}
176
177
static void POINTonE1_Serialize(unsigned char out[96], const POINTonE1 *in)
178
2.47k
{
179
2.47k
    if (vec_is_zero(in->Z, sizeof(in->Z))) {
180
2.42k
        bytes_zero(out, 96);
181
2.42k
        out[0] = 0x40;    /* infinity bit */
182
2.42k
    } else {
183
52
        (void)POINTonE1_Serialize_BE(out, in);
184
52
    }
185
2.47k
}
186
187
void blst_p1_serialize(unsigned char out[96], const POINTonE1 *in)
188
2.47k
{   POINTonE1_Serialize(out, in);   }
189
190
static limb_t POINTonE1_affine_Compress_BE(unsigned char out[48],
191
                                           const POINTonE1_affine *in)
192
40
{
193
40
    vec384 temp;
194
195
40
    from_fp(temp, in->X);
196
40
    be_bytes_from_limbs(out, temp, sizeof(temp));
197
198
40
    return sgn0_pty_mont_384(in->Y, BLS12_381_P, p0);
199
40
}
200
201
void blst_p1_affine_compress(unsigned char out[48], const POINTonE1_affine *in)
202
135
{
203
135
    if (vec_is_zero(in->X, 2*sizeof(in->X))) {
204
95
        bytes_zero(out, 48);
205
95
        out[0] = 0xc0;    /* compressed and infinity bits */
206
95
    } else {
207
40
        limb_t sign = POINTonE1_affine_Compress_BE(out, in);
208
40
        out[0] |= (unsigned char)(0x80 | ((sign & 2) << 4));
209
40
    }
210
135
}
211
212
static limb_t POINTonE1_Compress_BE(unsigned char out[48],
213
                                    const POINTonE1 *in)
214
0
{
215
0
    POINTonE1 p;
216
217
0
    if (!vec_is_equal(in->Z, BLS12_381_Rx.p, sizeof(in->Z))) {
218
0
        POINTonE1_from_Jacobian(&p, in);
219
0
        in = &p;
220
0
    }
221
222
0
    return POINTonE1_affine_Compress_BE(out, (const POINTonE1_affine *)in);
223
0
}
224
225
void blst_p1_compress(unsigned char out[48], const POINTonE1 *in)
226
0
{
227
0
    if (vec_is_zero(in->Z, sizeof(in->Z))) {
228
0
        bytes_zero(out, 48);
229
0
        out[0] = 0xc0;    /* compressed and infinity bits */
230
0
    } else {
231
0
        limb_t sign = POINTonE1_Compress_BE(out, in);
232
0
        out[0] |= (unsigned char)(0x80 | ((sign & 2) << 4));
233
0
    }
234
0
}
235
236
static limb_t POINTonE1_Uncompress_BE(POINTonE1_affine *out,
237
                                      const unsigned char in[48])
238
216
{
239
216
    POINTonE1_affine ret;
240
216
    vec384 temp;
241
242
216
    limbs_from_be_bytes(ret.X, in, sizeof(ret.X));
243
    /* clear top 3 bits in case caller was conveying some information there */
244
216
    ret.X[sizeof(ret.X)/sizeof(limb_t)-1] &= ((limb_t)0-1) >> 3;
245
216
    add_fp(temp, ret.X, ZERO_384);  /* less than modulus? */
246
216
    if (!vec_is_equal(temp, ret.X, sizeof(temp)))
247
21
        return (limb_t)0 - BLST_BAD_ENCODING;
248
195
    mul_fp(ret.X, ret.X, BLS12_381_RR);
249
250
195
    sqr_fp(ret.Y, ret.X);
251
195
    mul_fp(ret.Y, ret.Y, ret.X);
252
195
    add_fp(ret.Y, ret.Y, B_E1);                         /* X^3 + B */
253
195
    if (!sqrt_fp(ret.Y, ret.Y))
254
20
        return (limb_t)0 - BLST_POINT_NOT_ON_CURVE;
255
256
175
    vec_copy(out, &ret, sizeof(ret));
257
258
175
    return sgn0_pty_mont_384(out->Y, BLS12_381_P, p0);
259
195
}
260
261
static BLST_ERROR POINTonE1_Uncompress_Z(POINTonE1_affine *out,
262
                                         const unsigned char in[48])
263
481
{
264
481
    unsigned char in0 = in[0];
265
481
    limb_t sgn0_pty;
266
267
481
    if ((in0 & 0x80) == 0)      /* compressed bit */
268
213
        return BLST_BAD_ENCODING;
269
270
268
    if (in0 & 0x40) {           /* infinity bit */
271
52
        if (byte_is_zero(in0 & 0x3f) & bytes_are_zero(in+1, 47)) {
272
20
            vec_zero(out, sizeof(*out));
273
20
            return BLST_SUCCESS;
274
32
        } else {
275
32
            return BLST_BAD_ENCODING;
276
32
        }
277
52
    }
278
279
216
    sgn0_pty = POINTonE1_Uncompress_BE(out, in);
280
281
216
    if (sgn0_pty > 3)
282
41
        return (BLST_ERROR)(0 - sgn0_pty); /* POINT_NOT_ON_CURVE */
283
284
175
    sgn0_pty >>= 1; /* skip over parity bit */
285
175
    sgn0_pty ^= (in0 & 0x20) >> 5;
286
175
    cneg_fp(out->Y, out->Y, sgn0_pty);
287
288
    /* (0,±2) is not in group, but application might want to ignore? */
289
175
    return vec_is_zero(out->X, sizeof(out->X)) ? BLST_POINT_NOT_IN_GROUP
290
175
                                               : BLST_SUCCESS;
291
216
}
292
293
BLST_ERROR blst_p1_uncompress(POINTonE1_affine *out, const unsigned char in[48])
294
364
{   return POINTonE1_Uncompress_Z(out, in);   }
295
296
static BLST_ERROR POINTonE1_Deserialize_BE(POINTonE1_affine *out,
297
                                           const unsigned char in[96])
298
172
{
299
172
    POINTonE1_affine ret;
300
172
    vec384 temp;
301
302
172
    limbs_from_be_bytes(ret.X, in, sizeof(ret.X));
303
172
    limbs_from_be_bytes(ret.Y, in + 48, sizeof(ret.Y));
304
305
    /* clear top 3 bits in case caller was conveying some information there */
306
172
    ret.X[sizeof(ret.X)/sizeof(limb_t)-1] &= ((limb_t)0-1) >> 3;
307
172
    add_fp(temp, ret.X, ZERO_384);  /* less than modulus? */
308
172
    if (!vec_is_equal(temp, ret.X, sizeof(temp)))
309
20
        return BLST_BAD_ENCODING;
310
311
152
    add_fp(temp, ret.Y, ZERO_384);  /* less than modulus? */
312
152
    if (!vec_is_equal(temp, ret.Y, sizeof(temp)))
313
20
        return BLST_BAD_ENCODING;
314
315
132
    mul_fp(ret.X, ret.X, BLS12_381_RR);
316
132
    mul_fp(ret.Y, ret.Y, BLS12_381_RR);
317
318
132
    if (!POINTonE1_affine_on_curve(&ret))
319
90
        return BLST_POINT_NOT_ON_CURVE;
320
321
42
    vec_copy(out, &ret, sizeof(ret));
322
323
    /* (0,±2) is not in group, but application might want to ignore? */
324
42
    return vec_is_zero(out->X, sizeof(out->X)) ? BLST_POINT_NOT_IN_GROUP
325
42
                                               : BLST_SUCCESS;
326
132
}
327
328
static BLST_ERROR POINTonE1_Deserialize_Z(POINTonE1_affine *out,
329
                                          const unsigned char in[96])
330
2.74k
{
331
2.74k
    unsigned char in0 = in[0];
332
333
2.74k
    if ((in0 & 0xe0) == 0)
334
172
        return POINTonE1_Deserialize_BE(out, in);
335
336
2.57k
    if (in0 & 0x80)             /* compressed bit */
337
117
        return POINTonE1_Uncompress_Z(out, in);
338
339
2.45k
    if (in0 & 0x40) {           /* infinity bit */
340
2.44k
        if (byte_is_zero(in0 & 0x3f) & bytes_are_zero(in+1, 95)) {
341
2.42k
            vec_zero(out, sizeof(*out));
342
2.42k
            return BLST_SUCCESS;
343
2.42k
        }
344
2.44k
    }
345
346
35
    return BLST_BAD_ENCODING;
347
2.45k
}
348
349
BLST_ERROR blst_p1_deserialize(POINTonE1_affine *out,
350
                               const unsigned char in[96])
351
272
{   return POINTonE1_Deserialize_Z(out, in);   }
352
353
#include "ec_ops.h"
354
POINT_DADD_IMPL(POINTonE1, 384, fp)
355
POINT_DADD_AFFINE_IMPL_A0(POINTonE1, 384, fp, BLS12_381_Rx.p)
356
POINT_ADD_IMPL(POINTonE1, 384, fp)
357
POINT_ADD_AFFINE_IMPL(POINTonE1, 384, fp, BLS12_381_Rx.p)
358
POINT_DOUBLE_IMPL_A0(POINTonE1, 384, fp)
359
POINT_IS_EQUAL_IMPL(POINTonE1, 384, fp)
360
361
void blst_p1_add(POINTonE1 *out, const POINTonE1 *a, const POINTonE1 *b)
362
344
{   POINTonE1_add(out, a, b);   }
363
364
void blst_p1_add_or_double(POINTonE1 *out, const POINTonE1 *a,
365
                                           const POINTonE1 *b)
366
134
{   POINTonE1_dadd(out, a, b, NULL);   }
367
368
void blst_p1_add_affine(POINTonE1 *out, const POINTonE1 *a,
369
                                        const POINTonE1_affine *b)
370
2.86k
{   POINTonE1_add_affine(out, a, b);   }
371
372
void blst_p1_add_or_double_affine(POINTonE1 *out, const POINTonE1 *a,
373
                                                  const POINTonE1_affine *b)
374
203
{   POINTonE1_dadd_affine(out, a, b);   }
375
376
void blst_p1_double(POINTonE1 *out, const POINTonE1 *a)
377
114
{   POINTonE1_double(out, a);   }
378
379
int blst_p1_is_equal(const POINTonE1 *a, const POINTonE1 *b)
380
4.05k
{   return (int)POINTonE1_is_equal(a, b);   }
381
382
#include "ec_mult.h"
383
POINT_MULT_SCALAR_WX_IMPL(POINTonE1, 4)
384
POINT_MULT_SCALAR_WX_IMPL(POINTonE1, 5)
385
386
#ifdef __BLST_PRIVATE_TESTMODE__
387
POINT_AFFINE_MULT_SCALAR_IMPL(POINTonE1)
388
389
DECLARE_PRIVATE_POINTXZ(POINTonE1, 384)
390
POINT_LADDER_PRE_IMPL(POINTonE1, 384, fp)
391
POINT_LADDER_STEP_IMPL_A0(POINTonE1, 384, fp, onE1)
392
POINT_LADDER_POST_IMPL_A0(POINTonE1, 384, fp, onE1)
393
POINT_MULT_SCALAR_LADDER_IMPL(POINTonE1)
394
#endif
395
396
static const vec384 beta = {            /* such that beta^3 - 1 = 0  */
397
    /* -1/2 * (1 + sqrt(-3)) = ((P-2)^(P-2)) * (1 + (P-3)^((P+1)/4)) */
398
    /* (0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4
399
          897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac << 384) % P */
400
    TO_LIMB_T(0xcd03c9e48671f071), TO_LIMB_T(0x5dab22461fcda5d2),
401
    TO_LIMB_T(0x587042afd3851b95), TO_LIMB_T(0x8eb60ebe01bacb9e),
402
    TO_LIMB_T(0x03f97d6e83d050d2), TO_LIMB_T(0x18f0206554638741)
403
};
404
405
static void sigma(POINTonE1 *out, const POINTonE1 *in)
406
36.7k
{
407
36.7k
    vec_copy(out->X, in->X, 2*sizeof(out->X));
408
36.7k
    mul_fp(out->Z, in->Z, beta);
409
36.7k
}
410
411
/* Gallant-Lambert-Vanstone, ~45% faster than POINTonE1_mult_w5 */
412
static void POINTonE1_mult_glv(POINTonE1 *out, const POINTonE1 *in,
413
                               const pow256 SK)
414
4.33k
{
415
4.33k
    union { vec256 l; pow256 s; } val;
416
417
    /* SK/z^2 [in constant time] */
418
419
4.33k
    limbs_from_le_bytes(val.l, SK, 32);
420
4.33k
    div_by_zz(val.l);
421
4.33k
    le_bytes_from_limbs(val.s, val.l, 32);
422
423
4.33k
    {
424
4.33k
        const byte *scalars[2] = { val.s+16, val.s };
425
4.33k
        POINTonE1 table[2][1<<(5-1)];   /* 4.5KB */
426
4.33k
        size_t i;
427
428
4.33k
        POINTonE1_precompute_w5(table[0], in);
429
73.6k
        for (i = 0; i < 1<<(5-1); i++) {
430
69.3k
            mul_fp(table[1][i].X, table[0][i].X, beta);
431
69.3k
            cneg_fp(table[1][i].Y, table[0][i].Y, 1);
432
69.3k
            vec_copy(table[1][i].Z, table[0][i].Z, sizeof(table[1][i].Z));
433
69.3k
        }
434
435
4.33k
        POINTonE1s_mult_w5(out, NULL, 2, scalars, 128, table);
436
4.33k
        POINTonE1_cneg(out, 1);
437
4.33k
        mul_fp(out->Z, out->Z, beta);
438
4.33k
        mul_fp(out->Z, out->Z, beta);
439
4.33k
    }
440
441
4.33k
    vec_zero(val.l, sizeof(val));   /* scrub the copy of SK */
442
4.33k
}
443
444
static void POINTonE1_sign(POINTonE1 *out, const POINTonE1 *in, const pow256 SK)
445
4.01k
{
446
4.01k
    vec384 Z, ZZ;
447
4.01k
    limb_t inf;
448
449
4.01k
    POINTonE1_mult_glv(out, in, SK);
450
451
    /* convert to affine to remove possible bias in out->Z */
452
4.01k
    inf = vec_is_zero(out->Z, sizeof(out->Z));
453
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
454
    flt_reciprocal_fp(Z, out->Z);                       /* 1/Z   */
455
#else
456
4.01k
    reciprocal_fp(Z, out->Z);                           /* 1/Z   */
457
4.01k
#endif
458
459
4.01k
    sqr_fp(ZZ, Z);
460
4.01k
    mul_fp(out->X, out->X, ZZ);                         /* X = X/Z^2 */
461
462
4.01k
    mul_fp(ZZ, ZZ, Z);
463
4.01k
    mul_fp(out->Y, out->Y, ZZ);                         /* Y = Y/Z^3 */
464
465
4.01k
    vec_select(out->Z, out->Z, BLS12_381_G1.Z, sizeof(BLS12_381_G1.Z),
466
4.01k
                       inf);                            /* Z = inf ? 0 : 1 */
467
4.01k
}
468
469
void blst_sk_to_pk_in_g1(POINTonE1 *out, const pow256 SK)
470
4.01k
{   POINTonE1_sign(out, &BLS12_381_G1, SK);   }
471
472
void blst_sign_pk_in_g2(POINTonE1 *out, const POINTonE1 *msg, const pow256 SK)
473
0
{   POINTonE1_sign(out, msg, SK);   }
474
475
void blst_sk_to_pk2_in_g1(unsigned char out[96], POINTonE1_affine *PK,
476
                          const pow256 SK)
477
0
{
478
0
    POINTonE1 P[1];
479
480
0
    POINTonE1_sign(P, &BLS12_381_G1, SK);
481
0
    if (PK != NULL)
482
0
        vec_copy(PK, P, sizeof(*PK));
483
0
    if (out != NULL) {
484
0
        limb_t sgn0_pty = POINTonE1_Serialize_BE(out, P);
485
0
        out[0] |= (sgn0_pty & 2) << 4;      /* pre-decorate */
486
0
        out[0] |= vec_is_zero(P->Z, sizeof(P->Z)) << 6;
487
0
    }
488
0
}
489
490
void blst_sign_pk2_in_g2(unsigned char out[96], POINTonE1_affine *sig,
491
                         const POINTonE1 *hash, const pow256 SK)
492
0
{
493
0
    POINTonE1 P[1];
494
495
0
    POINTonE1_sign(P, hash, SK);
496
0
    if (sig != NULL)
497
0
        vec_copy(sig, P, sizeof(*sig));
498
0
    if (out != NULL) {
499
0
        limb_t sgn0_pty = POINTonE1_Serialize_BE(out, P);
500
0
        out[0] |= (sgn0_pty & 2) << 4;      /* pre-decorate */
501
0
        out[0] |= vec_is_zero(P->Z, sizeof(P->Z)) << 6;
502
0
    }
503
0
}
504
505
void blst_p1_mult(POINTonE1 *out, const POINTonE1 *a,
506
                                  const byte *scalar, size_t nbits)
507
2.45k
{
508
2.45k
    if (nbits < 176) {
509
1.63k
        if (nbits)
510
823
            POINTonE1_mult_w4(out, a, scalar, nbits);
511
814
        else
512
814
            vec_zero(out, sizeof(*out));
513
1.63k
    } else if (nbits <= 256) {
514
383
        union { vec256 l; pow256 s; } val;
515
383
        size_t i, j, top, mask = (size_t)0 - 1;
516
517
        /* this is not about constant-time-ness, but branch optimization */
518
12.6k
        for (top = (nbits + 7)/8, i=0, j=0; i<sizeof(val.s);) {
519
12.2k
            val.s[i++] = scalar[j] & mask;
520
12.2k
            mask = 0 - ((i - top) >> (8*sizeof(top)-1));
521
12.2k
            j += 1 & mask;
522
12.2k
        }
523
524
383
        if (check_mod_256(val.s, BLS12_381_r))  /* z^4 is the formal limit */
525
320
            POINTonE1_mult_glv(out, a, val.s);
526
63
        else    /* should never be the case, added for formal completeness */
527
63
            POINTonE1_mult_w5(out, a, scalar, nbits);
528
529
383
        vec_zero(val.l, sizeof(val));
530
437
    } else {    /* should never be the case, added for formal completeness */
531
437
        POINTonE1_mult_w5(out, a, scalar, nbits);
532
437
    }
533
2.45k
}
534
535
void blst_p1_unchecked_mult(POINTonE1 *out, const POINTonE1 *a,
536
                                            const byte *scalar, size_t nbits)
537
0
{
538
0
    if (nbits)
539
0
        POINTonE1_mult_w4(out, a, scalar, nbits);
540
0
    else
541
0
        vec_zero(out, sizeof(*out));
542
0
}
543
544
int blst_p1_affine_is_equal(const POINTonE1_affine *a,
545
                            const POINTonE1_affine *b)
546
79
{   return (int)vec_is_equal(a, b, sizeof(*a));   }
547
548
int blst_p1_is_inf(const POINTonE1 *p)
549
2.86k
{   return (int)vec_is_zero(p->Z, sizeof(p->Z));   }
550
551
const POINTonE1 *blst_p1_generator(void)
552
0
{   return &BLS12_381_G1;   }
553
554
int blst_p1_affine_is_inf(const POINTonE1_affine *p)
555
5.63k
{   return (int)vec_is_zero(p, sizeof(*p));   }
556
557
const POINTonE1_affine *blst_p1_affine_generator(void)
558
0
{   return (const POINTonE1_affine *)&BLS12_381_G1;   }
559
560
size_t blst_p1_sizeof(void)
561
0
{   return sizeof(POINTonE1);   }
562
563
size_t blst_p1_affine_sizeof(void)
564
0
{   return sizeof(POINTonE1_affine);   }