2 * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2015-2016 Cryptography Research, Inc.
5 * Licensed under the OpenSSL license (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 UNROLL 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 UNROLL for (i = 0; i < NLIMBS; i++) {
77 UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) {
78 uint8_t sj = serial[j];
81 buffer |= ((dword_t) sj) << fill;
85 x->limb[LIMBPERM(i)] = (word_t)
86 ((i < NLIMBS - 1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer);
87 fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
88 buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
90 (scarry + x->limb[LIMBPERM(i)] -
91 MODULUS->limb[LIMBPERM(i)]) >> (8 * sizeof(word_t));
93 succ = with_hibit ? 0 - (mask_t) 1 : ~gf_hibit(x);
94 return succ & word_is_zero((word_t)buffer) & ~word_is_zero((word_t)scarry);
97 /* Reduce to canonical form. */
98 void gf_strong_reduce(gf a)
105 /* first, clear high */
106 gf_weak_reduce(a); /* Determined to have negligible perf impact. */
108 /* now the total is less than 2p */
110 /* compute total_value - p. No need to reduce mod p. */
112 for (i = 0; i < NLIMBS; i++) {
113 scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
114 a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i));
115 scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
119 * uncommon case: it was >= p, so now scarry = 0 and this = x common case:
120 * it was < p, so now scarry = -1 and this = x - p + 2^255 so let's add
121 * back in p. will carry back off the top for 2^255.
123 assert(word_is_zero(scarry) | word_is_zero(scarry + 1));
125 scarry_0 = (word_t)scarry;
128 for (i = 0; i < NLIMBS; i++) {
130 carry + a->limb[LIMBPERM(i)] +
131 (scarry_0 & MODULUS->limb[LIMBPERM(i)]);
132 a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i));
133 carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
136 assert(word_is_zero(carry + scarry_0));
139 /* Subtract two gf elements d=a-b */
140 void gf_sub(gf d, const gf a, const gf b)
147 /* Add two field elements d = a+b */
148 void gf_add(gf d, const gf a, const gf b)
155 mask_t gf_eq(const gf a, const gf b)
164 for (i = 0; i < NLIMBS; i++)
165 ret |= c->limb[LIMBPERM(i)];
167 return word_is_zero(ret);
170 mask_t gf_isr(gf a, const gf x)
192 gf_sqrn(L0, L1, 111);
196 gf_sqrn(L0, L1, 223);
201 return gf_eq(L0, ONE);