2 * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2015-2016 Cryptography Research, Inc.
5 * Licensed under the Apache License 2.0 (the "License"). You may not use
6 * this file except in compliance with the License. You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
10 * Originally written by Mike Hamburg
14 static const gf MODULUS = {
15 FIELD_LITERAL(0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff,
16 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff,
17 0xffffffffffffff, 0xffffffffffffff)
20 /* Serialize to wire format. */
21 void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit)
23 unsigned int j = 0, fill = 0;
29 gf_strong_reduce(red);
31 assert(gf_hibit(red) == 0);
33 for (i = 0; i < (with_hibit ? X_SER_BYTES : SER_BYTES); i++) {
34 if (fill < 8 && j < NLIMBS) {
35 buffer |= ((dword_t) red->limb[LIMBPERM(j)]) << fill;
36 fill += LIMB_PLACE_VALUE(LIMBPERM(j));
39 serial[i] = (uint8_t)buffer;
45 /* Return high bit of x = low bit of 2x mod p */
46 mask_t gf_hibit(const gf x)
52 return 0 - (y->limb[0] & 1);
55 /* Return high bit of x = low bit of 2x mod p */
56 mask_t gf_lobit(const gf x)
62 return 0 - (y->limb[0] & 1);
65 /* Deserialize from wire format; return -1 on success and 0 on failure. */
66 mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit,
69 unsigned int j = 0, fill = 0;
72 const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES;
76 for (i = 0; i < NLIMBS; i++) {
77 while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) {
83 buffer |= ((dword_t) sj) << fill;
87 x->limb[LIMBPERM(i)] = (word_t)
88 ((i < NLIMBS - 1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer);
89 fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
90 buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
92 (scarry + x->limb[LIMBPERM(i)] -
93 MODULUS->limb[LIMBPERM(i)]) >> (8 * sizeof(word_t));
95 succ = with_hibit ? 0 - (mask_t) 1 : ~gf_hibit(x);
96 return succ & word_is_zero((word_t)buffer) & ~word_is_zero((word_t)scarry);
99 /* Reduce to canonical form. */
100 void gf_strong_reduce(gf a)
107 /* first, clear high */
108 gf_weak_reduce(a); /* Determined to have negligible perf impact. */
110 /* now the total is less than 2p */
112 /* compute total_value - p. No need to reduce mod p. */
114 for (i = 0; i < NLIMBS; i++) {
115 scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
116 a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i));
117 scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
121 * uncommon case: it was >= p, so now scarry = 0 and this = x common case:
122 * it was < p, so now scarry = -1 and this = x - p + 2^255 so let's add
123 * back in p. will carry back off the top for 2^255.
125 assert(scarry == 0 || scarry == -1);
127 scarry_0 = (word_t)scarry;
130 for (i = 0; i < NLIMBS; i++) {
132 carry + a->limb[LIMBPERM(i)] +
133 (scarry_0 & MODULUS->limb[LIMBPERM(i)]);
134 a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i));
135 carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
138 assert(carry < 2 && ((word_t)carry + scarry_0) == 0);
141 /* Subtract two gf elements d=a-b */
142 void gf_sub(gf d, const gf a, const gf b)
149 /* Add two field elements d = a+b */
150 void gf_add(gf d, const gf a, const gf b)
157 mask_t gf_eq(const gf a, const gf b)
166 for (i = 0; i < NLIMBS; i++)
167 ret |= c->limb[LIMBPERM(i)];
169 return word_is_zero(ret);
172 mask_t gf_isr(gf a, const gf x)
194 gf_sqrn(L0, L1, 111);
198 gf_sqrn(L0, L1, 223);
203 return gf_eq(L0, ONE);