Blame crypto/ec/ecp_nistp256.c

Packit Service 084de1
/*
Packit Service 084de1
 * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
Packit Service 084de1
 *
Packit Service 084de1
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit Service 084de1
 * this file except in compliance with the License.  You can obtain a copy
Packit Service 084de1
 * in the file LICENSE in the source distribution or at
Packit Service 084de1
 * https://www.openssl.org/source/license.html
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
/* Copyright 2011 Google Inc.
Packit Service 084de1
 *
Packit Service 084de1
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service 084de1
 *
Packit Service 084de1
 * you may not use this file except in compliance with the License.
Packit Service 084de1
 * You may obtain a copy of the License at
Packit Service 084de1
 *
Packit Service 084de1
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service 084de1
 *
Packit Service 084de1
 *  Unless required by applicable law or agreed to in writing, software
Packit Service 084de1
 *  distributed under the License is distributed on an "AS IS" BASIS,
Packit Service 084de1
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service 084de1
 *  See the License for the specific language governing permissions and
Packit Service 084de1
 *  limitations under the License.
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * A 64-bit implementation of the NIST P-256 elliptic curve point multiplication
Packit Service 084de1
 *
Packit Service 084de1
 * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
Packit Service 084de1
 * Otherwise based on Emilia's P224 work, which was inspired by my curve25519
Packit Service 084de1
 * work which got its smarts from Daniel J. Bernstein's work on the same.
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
#include <openssl/opensslconf.h>
Packit Service 084de1
#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
Packit Service 084de1
NON_EMPTY_TRANSLATION_UNIT
Packit Service 084de1
#else
Packit Service 084de1
Packit Service 084de1
# include <stdint.h>
Packit Service 084de1
# include <string.h>
Packit Service 084de1
# include <openssl/err.h>
Packit Service 084de1
# include "ec_local.h"
Packit Service 084de1
Packit Service 084de1
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
Packit Service 084de1
  /* even with gcc, the typedef won't work for 32-bit platforms */
Packit Service 084de1
typedef __uint128_t uint128_t;  /* nonstandard; implemented by gcc on 64-bit
Packit Service 084de1
                                 * platforms */
Packit Service 084de1
typedef __int128_t int128_t;
Packit Service 084de1
# else
Packit Service 084de1
#  error "Your compiler doesn't appear to support 128-bit integer types"
Packit Service 084de1
# endif
Packit Service 084de1
Packit Service 084de1
typedef uint8_t u8;
Packit Service 084de1
typedef uint32_t u32;
Packit Service 084de1
typedef uint64_t u64;
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We
Packit Service 084de1
 * can serialise an element of this field into 32 bytes. We call this an
Packit Service 084de1
 * felem_bytearray.
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
typedef u8 felem_bytearray[32];
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * These are the parameters of P256, taken from FIPS 186-3, page 86. These
Packit Service 084de1
 * values are big-endian.
Packit Service 084de1
 */
Packit Service 084de1
static const felem_bytearray nistp256_curve_params[5] = {
Packit Service 084de1
    {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */
Packit Service 084de1
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Packit Service 084de1
     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
Packit Service 084de1
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
Packit Service 084de1
    {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */
Packit Service 084de1
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Packit Service 084de1
     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
Packit Service 084de1
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc},
Packit Service 084de1
    {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, /* b */
Packit Service 084de1
     0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc,
Packit Service 084de1
     0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
Packit Service 084de1
     0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b},
Packit Service 084de1
    {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */
Packit Service 084de1
     0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
Packit Service 084de1
     0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
Packit Service 084de1
     0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96},
Packit Service 084de1
    {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */
Packit Service 084de1
     0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
Packit Service 084de1
     0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
Packit Service 084de1
     0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * The representation of field elements.
Packit Service 084de1
 * ------------------------------------
Packit Service 084de1
 *
Packit Service 084de1
 * We represent field elements with either four 128-bit values, eight 128-bit
Packit Service 084de1
 * values, or four 64-bit values. The field element represented is:
Packit Service 084de1
 *   v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192  (mod p)
Packit Service 084de1
 * or:
Packit Service 084de1
 *   v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512  (mod p)
Packit Service 084de1
 *
Packit Service 084de1
 * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits
Packit Service 084de1
 * apart, but are 128-bits wide, the most significant bits of each limb overlap
Packit Service 084de1
 * with the least significant bits of the next.
Packit Service 084de1
 *
Packit Service 084de1
 * A field element with four limbs is an 'felem'. One with eight limbs is a
Packit Service 084de1
 * 'longfelem'
Packit Service 084de1
 *
Packit Service 084de1
 * A field element with four, 64-bit values is called a 'smallfelem'. Small
Packit Service 084de1
 * values are used as intermediate values before multiplication.
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
# define NLIMBS 4
Packit Service 084de1
Packit Service 084de1
typedef uint128_t limb;
Packit Service 084de1
typedef limb felem[NLIMBS];
Packit Service 084de1
typedef limb longfelem[NLIMBS * 2];
Packit Service 084de1
typedef u64 smallfelem[NLIMBS];
Packit Service 084de1
Packit Service 084de1
/* This is the value of the prime as four 64-bit words, little-endian. */
Packit Service 084de1
static const u64 kPrime[4] =
Packit Service 084de1
    { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul };
Packit Service 084de1
static const u64 bottom63bits = 0x7ffffffffffffffful;
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * bin32_to_felem takes a little-endian byte array and converts it into felem
Packit Service 084de1
 * form. This assumes that the CPU is little-endian.
Packit Service 084de1
 */
Packit Service 084de1
static void bin32_to_felem(felem out, const u8 in[32])
Packit Service 084de1
{
Packit Service 084de1
    out[0] = *((u64 *)&in[0]);
Packit Service 084de1
    out[1] = *((u64 *)&in[8]);
Packit Service 084de1
    out[2] = *((u64 *)&in[16]);
Packit Service 084de1
    out[3] = *((u64 *)&in[24]);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * smallfelem_to_bin32 takes a smallfelem and serialises into a little
Packit Service 084de1
 * endian, 32 byte array. This assumes that the CPU is little-endian.
Packit Service 084de1
 */
Packit Service 084de1
static void smallfelem_to_bin32(u8 out[32], const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    *((u64 *)&out[0]) = in[0];
Packit Service 084de1
    *((u64 *)&out[8]) = in[1];
Packit Service 084de1
    *((u64 *)&out[16]) = in[2];
Packit Service 084de1
    *((u64 *)&out[24]) = in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* BN_to_felem converts an OpenSSL BIGNUM into an felem */
Packit Service 084de1
static int BN_to_felem(felem out, const BIGNUM *bn)
Packit Service 084de1
{
Packit Service 084de1
    felem_bytearray b_out;
Packit Service 084de1
    int num_bytes;
Packit Service 084de1
Packit Service 084de1
    if (BN_is_negative(bn)) {
Packit Service 084de1
        ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
Packit Service 084de1
        return 0;
Packit Service 084de1
    }
Packit Service 084de1
    num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out));
Packit Service 084de1
    if (num_bytes < 0) {
Packit Service 084de1
        ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
Packit Service 084de1
        return 0;
Packit Service 084de1
    }
Packit Service 084de1
    bin32_to_felem(out, b_out);
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* felem_to_BN converts an felem into an OpenSSL BIGNUM */
Packit Service 084de1
static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    felem_bytearray b_out;
Packit Service 084de1
    smallfelem_to_bin32(b_out, in);
Packit Service 084de1
    return BN_lebin2bn(b_out, sizeof(b_out), out);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * Field operations
Packit Service 084de1
 * ----------------
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
static void smallfelem_one(smallfelem out)
Packit Service 084de1
{
Packit Service 084de1
    out[0] = 1;
Packit Service 084de1
    out[1] = 0;
Packit Service 084de1
    out[2] = 0;
Packit Service 084de1
    out[3] = 0;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void smallfelem_assign(smallfelem out, const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] = in[0];
Packit Service 084de1
    out[1] = in[1];
Packit Service 084de1
    out[2] = in[2];
Packit Service 084de1
    out[3] = in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void felem_assign(felem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] = in[0];
Packit Service 084de1
    out[1] = in[1];
Packit Service 084de1
    out[2] = in[2];
Packit Service 084de1
    out[3] = in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* felem_sum sets out = out + in. */
Packit Service 084de1
static void felem_sum(felem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] += in[0];
Packit Service 084de1
    out[1] += in[1];
Packit Service 084de1
    out[2] += in[2];
Packit Service 084de1
    out[3] += in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* felem_small_sum sets out = out + in. */
Packit Service 084de1
static void felem_small_sum(felem out, const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] += in[0];
Packit Service 084de1
    out[1] += in[1];
Packit Service 084de1
    out[2] += in[2];
Packit Service 084de1
    out[3] += in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* felem_scalar sets out = out * scalar */
Packit Service 084de1
static void felem_scalar(felem out, const u64 scalar)
Packit Service 084de1
{
Packit Service 084de1
    out[0] *= scalar;
Packit Service 084de1
    out[1] *= scalar;
Packit Service 084de1
    out[2] *= scalar;
Packit Service 084de1
    out[3] *= scalar;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* longfelem_scalar sets out = out * scalar */
Packit Service 084de1
static void longfelem_scalar(longfelem out, const u64 scalar)
Packit Service 084de1
{
Packit Service 084de1
    out[0] *= scalar;
Packit Service 084de1
    out[1] *= scalar;
Packit Service 084de1
    out[2] *= scalar;
Packit Service 084de1
    out[3] *= scalar;
Packit Service 084de1
    out[4] *= scalar;
Packit Service 084de1
    out[5] *= scalar;
Packit Service 084de1
    out[6] *= scalar;
Packit Service 084de1
    out[7] *= scalar;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
Packit Service 084de1
# define two105 (((limb)1) << 105)
Packit Service 084de1
# define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
Packit Service 084de1
Packit Service 084de1
/* zero105 is 0 mod p */
Packit Service 084de1
static const felem zero105 =
Packit Service 084de1
    { two105m41m9, two105, two105m41p9, two105m41p9 };
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * smallfelem_neg sets |out| to |-small|
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < out[i] + 2^105
Packit Service 084de1
 */
Packit Service 084de1
static void smallfelem_neg(felem out, const smallfelem small)
Packit Service 084de1
{
Packit Service 084de1
    /* In order to prevent underflow, we subtract from 0 mod p. */
Packit Service 084de1
    out[0] = zero105[0] - small[0];
Packit Service 084de1
    out[1] = zero105[1] - small[1];
Packit Service 084de1
    out[2] = zero105[2] - small[2];
Packit Service 084de1
    out[3] = zero105[3] - small[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_diff subtracts |in| from |out|
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[i] < 2^104
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < out[i] + 2^105
Packit Service 084de1
 */
Packit Service 084de1
static void felem_diff(felem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    /*
Packit Service 084de1
     * In order to prevent underflow, we add 0 mod p before subtracting.
Packit Service 084de1
     */
Packit Service 084de1
    out[0] += zero105[0];
Packit Service 084de1
    out[1] += zero105[1];
Packit Service 084de1
    out[2] += zero105[2];
Packit Service 084de1
    out[3] += zero105[3];
Packit Service 084de1
Packit Service 084de1
    out[0] -= in[0];
Packit Service 084de1
    out[1] -= in[1];
Packit Service 084de1
    out[2] -= in[2];
Packit Service 084de1
    out[3] -= in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
Packit Service 084de1
# define two107 (((limb)1) << 107)
Packit Service 084de1
# define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
Packit Service 084de1
Packit Service 084de1
/* zero107 is 0 mod p */
Packit Service 084de1
static const felem zero107 =
Packit Service 084de1
    { two107m43m11, two107, two107m43p11, two107m43p11 };
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * An alternative felem_diff for larger inputs |in|
Packit Service 084de1
 * felem_diff_zero107 subtracts |in| from |out|
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[i] < 2^106
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < out[i] + 2^107
Packit Service 084de1
 */
Packit Service 084de1
static void felem_diff_zero107(felem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    /*
Packit Service 084de1
     * In order to prevent underflow, we add 0 mod p before subtracting.
Packit Service 084de1
     */
Packit Service 084de1
    out[0] += zero107[0];
Packit Service 084de1
    out[1] += zero107[1];
Packit Service 084de1
    out[2] += zero107[2];
Packit Service 084de1
    out[3] += zero107[3];
Packit Service 084de1
Packit Service 084de1
    out[0] -= in[0];
Packit Service 084de1
    out[1] -= in[1];
Packit Service 084de1
    out[2] -= in[2];
Packit Service 084de1
    out[3] -= in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * longfelem_diff subtracts |in| from |out|
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[i] < 7*2^67
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < out[i] + 2^70 + 2^40
Packit Service 084de1
 */
Packit Service 084de1
static void longfelem_diff(longfelem out, const longfelem in)
Packit Service 084de1
{
Packit Service 084de1
    static const limb two70m8p6 =
Packit Service 084de1
        (((limb) 1) << 70) - (((limb) 1) << 8) + (((limb) 1) << 6);
Packit Service 084de1
    static const limb two70p40 = (((limb) 1) << 70) + (((limb) 1) << 40);
Packit Service 084de1
    static const limb two70 = (((limb) 1) << 70);
Packit Service 084de1
    static const limb two70m40m38p6 =
Packit Service 084de1
        (((limb) 1) << 70) - (((limb) 1) << 40) - (((limb) 1) << 38) +
Packit Service 084de1
        (((limb) 1) << 6);
Packit Service 084de1
    static const limb two70m6 = (((limb) 1) << 70) - (((limb) 1) << 6);
Packit Service 084de1
Packit Service 084de1
    /* add 0 mod p to avoid underflow */
Packit Service 084de1
    out[0] += two70m8p6;
Packit Service 084de1
    out[1] += two70p40;
Packit Service 084de1
    out[2] += two70;
Packit Service 084de1
    out[3] += two70m40m38p6;
Packit Service 084de1
    out[4] += two70m6;
Packit Service 084de1
    out[5] += two70m6;
Packit Service 084de1
    out[6] += two70m6;
Packit Service 084de1
    out[7] += two70m6;
Packit Service 084de1
Packit Service 084de1
    /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */
Packit Service 084de1
    out[0] -= in[0];
Packit Service 084de1
    out[1] -= in[1];
Packit Service 084de1
    out[2] -= in[2];
Packit Service 084de1
    out[3] -= in[3];
Packit Service 084de1
    out[4] -= in[4];
Packit Service 084de1
    out[5] -= in[5];
Packit Service 084de1
    out[6] -= in[6];
Packit Service 084de1
    out[7] -= in[7];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# define two64m0 (((limb)1) << 64) - 1
Packit Service 084de1
# define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
Packit Service 084de1
# define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
Packit Service 084de1
# define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
Packit Service 084de1
Packit Service 084de1
/* zero110 is 0 mod p */
Packit Service 084de1
static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 };
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_shrink converts an felem into a smallfelem. The result isn't quite
Packit Service 084de1
 * minimal as the value may be greater than p.
Packit Service 084de1
 *
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[i] < 2^109
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 2^64
Packit Service 084de1
 */
Packit Service 084de1
static void felem_shrink(smallfelem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    felem tmp;
Packit Service 084de1
    u64 a, b, mask;
Packit Service 084de1
    u64 high, low;
Packit Service 084de1
    static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */
Packit Service 084de1
Packit Service 084de1
    /* Carry 2->3 */
Packit Service 084de1
    tmp[3] = zero110[3] + in[3] + ((u64)(in[2] >> 64));
Packit Service 084de1
    /* tmp[3] < 2^110 */
Packit Service 084de1
Packit Service 084de1
    tmp[2] = zero110[2] + (u64)in[2];
Packit Service 084de1
    tmp[0] = zero110[0] + in[0];
Packit Service 084de1
    tmp[1] = zero110[1] + in[1];
Packit Service 084de1
    /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */
Packit Service 084de1
Packit Service 084de1
    /*
Packit Service 084de1
     * We perform two partial reductions where we eliminate the high-word of
Packit Service 084de1
     * tmp[3]. We don't update the other words till the end.
Packit Service 084de1
     */
Packit Service 084de1
    a = tmp[3] >> 64;           /* a < 2^46 */
Packit Service 084de1
    tmp[3] = (u64)tmp[3];
Packit Service 084de1
    tmp[3] -= a;
Packit Service 084de1
    tmp[3] += ((limb) a) << 32;
Packit Service 084de1
    /* tmp[3] < 2^79 */
Packit Service 084de1
Packit Service 084de1
    b = a;
Packit Service 084de1
    a = tmp[3] >> 64;           /* a < 2^15 */
Packit Service 084de1
    b += a;                     /* b < 2^46 + 2^15 < 2^47 */
Packit Service 084de1
    tmp[3] = (u64)tmp[3];
Packit Service 084de1
    tmp[3] -= a;
Packit Service 084de1
    tmp[3] += ((limb) a) << 32;
Packit Service 084de1
    /* tmp[3] < 2^64 + 2^47 */
Packit Service 084de1
Packit Service 084de1
    /*
Packit Service 084de1
     * This adjusts the other two words to complete the two partial
Packit Service 084de1
     * reductions.
Packit Service 084de1
     */
Packit Service 084de1
    tmp[0] += b;
Packit Service 084de1
    tmp[1] -= (((limb) b) << 32);
Packit Service 084de1
Packit Service 084de1
    /*
Packit Service 084de1
     * In order to make space in tmp[3] for the carry from 2 -> 3, we
Packit Service 084de1
     * conditionally subtract kPrime if tmp[3] is large enough.
Packit Service 084de1
     */
Packit Service 084de1
    high = (u64)(tmp[3] >> 64);
Packit Service 084de1
    /* As tmp[3] < 2^65, high is either 1 or 0 */
Packit Service 084de1
    high = 0 - high;
Packit Service 084de1
    /*-
Packit Service 084de1
     * high is:
Packit Service 084de1
     *   all ones   if the high word of tmp[3] is 1
Packit Service 084de1
     *   all zeros  if the high word of tmp[3] if 0
Packit Service 084de1
     */
Packit Service 084de1
    low = (u64)tmp[3];
Packit Service 084de1
    mask = 0 - (low >> 63);
Packit Service 084de1
    /*-
Packit Service 084de1
     * mask is:
Packit Service 084de1
     *   all ones   if the MSB of low is 1
Packit Service 084de1
     *   all zeros  if the MSB of low if 0
Packit Service 084de1
     */
Packit Service 084de1
    low &= bottom63bits;
Packit Service 084de1
    low -= kPrime3Test;
Packit Service 084de1
    /* if low was greater than kPrime3Test then the MSB is zero */
Packit Service 084de1
    low = ~low;
Packit Service 084de1
    low = 0 - (low >> 63);
Packit Service 084de1
    /*-
Packit Service 084de1
     * low is:
Packit Service 084de1
     *   all ones   if low was > kPrime3Test
Packit Service 084de1
     *   all zeros  if low was <= kPrime3Test
Packit Service 084de1
     */
Packit Service 084de1
    mask = (mask & low) | high;
Packit Service 084de1
    tmp[0] -= mask & kPrime[0];
Packit Service 084de1
    tmp[1] -= mask & kPrime[1];
Packit Service 084de1
    /* kPrime[2] is zero, so omitted */
Packit Service 084de1
    tmp[3] -= mask & kPrime[3];
Packit Service 084de1
    /* tmp[3] < 2**64 - 2**32 + 1 */
Packit Service 084de1
Packit Service 084de1
    tmp[1] += ((u64)(tmp[0] >> 64));
Packit Service 084de1
    tmp[0] = (u64)tmp[0];
Packit Service 084de1
    tmp[2] += ((u64)(tmp[1] >> 64));
Packit Service 084de1
    tmp[1] = (u64)tmp[1];
Packit Service 084de1
    tmp[3] += ((u64)(tmp[2] >> 64));
Packit Service 084de1
    tmp[2] = (u64)tmp[2];
Packit Service 084de1
    /* tmp[i] < 2^64 */
Packit Service 084de1
Packit Service 084de1
    out[0] = tmp[0];
Packit Service 084de1
    out[1] = tmp[1];
Packit Service 084de1
    out[2] = tmp[2];
Packit Service 084de1
    out[3] = tmp[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* smallfelem_expand converts a smallfelem to an felem */
Packit Service 084de1
static void smallfelem_expand(felem out, const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] = in[0];
Packit Service 084de1
    out[1] = in[1];
Packit Service 084de1
    out[2] = in[2];
Packit Service 084de1
    out[3] = in[3];
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * smallfelem_square sets |out| = |small|^2
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   small[i] < 2^64
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 7 * 2^64 < 2^67
Packit Service 084de1
 */
Packit Service 084de1
static void smallfelem_square(longfelem out, const smallfelem small)
Packit Service 084de1
{
Packit Service 084de1
    limb a;
Packit Service 084de1
    u64 high, low;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[0]) * small[0];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[0] = low;
Packit Service 084de1
    out[1] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[0]) * small[1];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[1] += low;
Packit Service 084de1
    out[1] += low;
Packit Service 084de1
    out[2] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[0]) * small[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[2] += low;
Packit Service 084de1
    out[2] *= 2;
Packit Service 084de1
    out[3] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[0]) * small[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[3] += low;
Packit Service 084de1
    out[4] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[1]) * small[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[3] += low;
Packit Service 084de1
    out[3] *= 2;
Packit Service 084de1
    out[4] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[1]) * small[1];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[2] += low;
Packit Service 084de1
    out[3] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[1]) * small[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[4] += low;
Packit Service 084de1
    out[4] *= 2;
Packit Service 084de1
    out[5] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[2]) * small[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[5] += low;
Packit Service 084de1
    out[5] *= 2;
Packit Service 084de1
    out[6] = high;
Packit Service 084de1
    out[6] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[2]) * small[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[4] += low;
Packit Service 084de1
    out[5] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small[3]) * small[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[6] += low;
Packit Service 084de1
    out[7] = high;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_square sets |out| = |in|^2
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[i] < 2^109
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 7 * 2^64 < 2^67
Packit Service 084de1
 */
Packit Service 084de1
static void felem_square(longfelem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    u64 small[4];
Packit Service 084de1
    felem_shrink(small, in);
Packit Service 084de1
    smallfelem_square(out, small);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * smallfelem_mul sets |out| = |small1| * |small2|
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   small1[i] < 2^64
Packit Service 084de1
 *   small2[i] < 2^64
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 7 * 2^64 < 2^67
Packit Service 084de1
 */
Packit Service 084de1
static void smallfelem_mul(longfelem out, const smallfelem small1,
Packit Service 084de1
                           const smallfelem small2)
Packit Service 084de1
{
Packit Service 084de1
    limb a;
Packit Service 084de1
    u64 high, low;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[0]) * small2[0];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[0] = low;
Packit Service 084de1
    out[1] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[0]) * small2[1];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[1] += low;
Packit Service 084de1
    out[2] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[1]) * small2[0];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[1] += low;
Packit Service 084de1
    out[2] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[0]) * small2[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[2] += low;
Packit Service 084de1
    out[3] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[1]) * small2[1];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[2] += low;
Packit Service 084de1
    out[3] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[2]) * small2[0];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[2] += low;
Packit Service 084de1
    out[3] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[0]) * small2[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[3] += low;
Packit Service 084de1
    out[4] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[1]) * small2[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[3] += low;
Packit Service 084de1
    out[4] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[2]) * small2[1];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[3] += low;
Packit Service 084de1
    out[4] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[3]) * small2[0];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[3] += low;
Packit Service 084de1
    out[4] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[1]) * small2[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[4] += low;
Packit Service 084de1
    out[5] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[2]) * small2[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[4] += low;
Packit Service 084de1
    out[5] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[3]) * small2[1];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[4] += low;
Packit Service 084de1
    out[5] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[2]) * small2[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[5] += low;
Packit Service 084de1
    out[6] = high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[3]) * small2[2];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[5] += low;
Packit Service 084de1
    out[6] += high;
Packit Service 084de1
Packit Service 084de1
    a = ((uint128_t) small1[3]) * small2[3];
Packit Service 084de1
    low = a;
Packit Service 084de1
    high = a >> 64;
Packit Service 084de1
    out[6] += low;
Packit Service 084de1
    out[7] = high;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_mul sets |out| = |in1| * |in2|
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in1[i] < 2^109
Packit Service 084de1
 *   in2[i] < 2^109
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 7 * 2^64 < 2^67
Packit Service 084de1
 */
Packit Service 084de1
static void felem_mul(longfelem out, const felem in1, const felem in2)
Packit Service 084de1
{
Packit Service 084de1
    smallfelem small1, small2;
Packit Service 084de1
    felem_shrink(small1, in1);
Packit Service 084de1
    felem_shrink(small2, in2);
Packit Service 084de1
    smallfelem_mul(out, small1, small2);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_small_mul sets |out| = |small1| * |in2|
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   small1[i] < 2^64
Packit Service 084de1
 *   in2[i] < 2^109
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 7 * 2^64 < 2^67
Packit Service 084de1
 */
Packit Service 084de1
static void felem_small_mul(longfelem out, const smallfelem small1,
Packit Service 084de1
                            const felem in2)
Packit Service 084de1
{
Packit Service 084de1
    smallfelem small2;
Packit Service 084de1
    felem_shrink(small2, in2);
Packit Service 084de1
    smallfelem_mul(out, small1, small2);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
# define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
Packit Service 084de1
# define two100 (((limb)1) << 100)
Packit Service 084de1
# define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
Packit Service 084de1
/* zero100 is 0 mod p */
Packit Service 084de1
static const felem zero100 =
Packit Service 084de1
    { two100m36m4, two100, two100m36p4, two100m36p4 };
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * Internal function for the different flavours of felem_reduce.
Packit Service 084de1
 * felem_reduce_ reduces the higher coefficients in[4]-in[7].
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7]
Packit Service 084de1
 *   out[1] >= in[7] + 2^32*in[4]
Packit Service 084de1
 *   out[2] >= in[5] + 2^32*in[5]
Packit Service 084de1
 *   out[3] >= in[4] + 2^32*in[5] + 2^32*in[6]
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[0] <= out[0] + in[4] + 2^32*in[5]
Packit Service 084de1
 *   out[1] <= out[1] + in[5] + 2^33*in[6]
Packit Service 084de1
 *   out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7]
Packit Service 084de1
 *   out[3] <= out[3] + 2^32*in[4] + 3*in[7]
Packit Service 084de1
 */
Packit Service 084de1
static void felem_reduce_(felem out, const longfelem in)
Packit Service 084de1
{
Packit Service 084de1
    int128_t c;
Packit Service 084de1
    /* combine common terms from below */
Packit Service 084de1
    c = in[4] + (in[5] << 32);
Packit Service 084de1
    out[0] += c;
Packit Service 084de1
    out[3] -= c;
Packit Service 084de1
Packit Service 084de1
    c = in[5] - in[7];
Packit Service 084de1
    out[1] += c;
Packit Service 084de1
    out[2] -= c;
Packit Service 084de1
Packit Service 084de1
    /* the remaining terms */
Packit Service 084de1
    /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */
Packit Service 084de1
    out[1] -= (in[4] << 32);
Packit Service 084de1
    out[3] += (in[4] << 32);
Packit Service 084de1
Packit Service 084de1
    /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */
Packit Service 084de1
    out[2] -= (in[5] << 32);
Packit Service 084de1
Packit Service 084de1
    /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */
Packit Service 084de1
    out[0] -= in[6];
Packit Service 084de1
    out[0] -= (in[6] << 32);
Packit Service 084de1
    out[1] += (in[6] << 33);
Packit Service 084de1
    out[2] += (in[6] * 2);
Packit Service 084de1
    out[3] -= (in[6] << 32);
Packit Service 084de1
Packit Service 084de1
    /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */
Packit Service 084de1
    out[0] -= in[7];
Packit Service 084de1
    out[0] -= (in[7] << 32);
Packit Service 084de1
    out[2] += (in[7] << 33);
Packit Service 084de1
    out[3] += (in[7] * 3);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_reduce converts a longfelem into an felem.
Packit Service 084de1
 * To be called directly after felem_square or felem_mul.
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64
Packit Service 084de1
 *   in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 2^101
Packit Service 084de1
 */
Packit Service 084de1
static void felem_reduce(felem out, const longfelem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] = zero100[0] + in[0];
Packit Service 084de1
    out[1] = zero100[1] + in[1];
Packit Service 084de1
    out[2] = zero100[2] + in[2];
Packit Service 084de1
    out[3] = zero100[3] + in[3];
Packit Service 084de1
Packit Service 084de1
    felem_reduce_(out, in);
Packit Service 084de1
Packit Service 084de1
    /*-
Packit Service 084de1
     * out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0
Packit Service 084de1
     * out[1] > 2^100 - 2^64 - 7*2^96 > 0
Packit Service 084de1
     * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0
Packit Service 084de1
     * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0
Packit Service 084de1
     *
Packit Service 084de1
     * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101
Packit Service 084de1
     * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101
Packit Service 084de1
     * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101
Packit Service 084de1
     * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101
Packit Service 084de1
     */
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_reduce_zero105 converts a larger longfelem into an felem.
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   in[0] < 2^71
Packit Service 084de1
 * On exit:
Packit Service 084de1
 *   out[i] < 2^106
Packit Service 084de1
 */
Packit Service 084de1
static void felem_reduce_zero105(felem out, const longfelem in)
Packit Service 084de1
{
Packit Service 084de1
    out[0] = zero105[0] + in[0];
Packit Service 084de1
    out[1] = zero105[1] + in[1];
Packit Service 084de1
    out[2] = zero105[2] + in[2];
Packit Service 084de1
    out[3] = zero105[3] + in[3];
Packit Service 084de1
Packit Service 084de1
    felem_reduce_(out, in);
Packit Service 084de1
Packit Service 084de1
    /*-
Packit Service 084de1
     * out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0
Packit Service 084de1
     * out[1] > 2^105 - 2^71 - 2^103 > 0
Packit Service 084de1
     * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0
Packit Service 084de1
     * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0
Packit Service 084de1
     *
Packit Service 084de1
     * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
Packit Service 084de1
     * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
Packit Service 084de1
     * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106
Packit Service 084de1
     * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106
Packit Service 084de1
     */
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * subtract_u64 sets *result = *result - v and *carry to one if the
Packit Service 084de1
 * subtraction underflowed.
Packit Service 084de1
 */
Packit Service 084de1
static void subtract_u64(u64 *result, u64 *carry, u64 v)
Packit Service 084de1
{
Packit Service 084de1
    uint128_t r = *result;
Packit Service 084de1
    r -= v;
Packit Service 084de1
    *carry = (r >> 64) & 1;
Packit Service 084de1
    *result = (u64)r;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * felem_contract converts |in| to its unique, minimal representation. On
Packit Service 084de1
 * entry: in[i] < 2^109
Packit Service 084de1
 */
Packit Service 084de1
static void felem_contract(smallfelem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    unsigned i;
Packit Service 084de1
    u64 all_equal_so_far = 0, result = 0, carry;
Packit Service 084de1
Packit Service 084de1
    felem_shrink(out, in);
Packit Service 084de1
    /* small is minimal except that the value might be > p */
Packit Service 084de1
Packit Service 084de1
    all_equal_so_far--;
Packit Service 084de1
    /*
Packit Service 084de1
     * We are doing a constant time test if out >= kPrime. We need to compare
Packit Service 084de1
     * each u64, from most-significant to least significant. For each one, if
Packit Service 084de1
     * all words so far have been equal (m is all ones) then a non-equal
Packit Service 084de1
     * result is the answer. Otherwise we continue.
Packit Service 084de1
     */
Packit Service 084de1
    for (i = 3; i < 4; i--) {
Packit Service 084de1
        u64 equal;
Packit Service 084de1
        uint128_t a = ((uint128_t) kPrime[i]) - out[i];
Packit Service 084de1
        /*
Packit Service 084de1
         * if out[i] > kPrime[i] then a will underflow and the high 64-bits
Packit Service 084de1
         * will all be set.
Packit Service 084de1
         */
Packit Service 084de1
        result |= all_equal_so_far & ((u64)(a >> 64));
Packit Service 084de1
Packit Service 084de1
        /*
Packit Service 084de1
         * if kPrime[i] == out[i] then |equal| will be all zeros and the
Packit Service 084de1
         * decrement will make it all ones.
Packit Service 084de1
         */
Packit Service 084de1
        equal = kPrime[i] ^ out[i];
Packit Service 084de1
        equal--;
Packit Service 084de1
        equal &= equal << 32;
Packit Service 084de1
        equal &= equal << 16;
Packit Service 084de1
        equal &= equal << 8;
Packit Service 084de1
        equal &= equal << 4;
Packit Service 084de1
        equal &= equal << 2;
Packit Service 084de1
        equal &= equal << 1;
Packit Service 084de1
        equal = 0 - (equal >> 63);
Packit Service 084de1
Packit Service 084de1
        all_equal_so_far &= equal;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    /*
Packit Service 084de1
     * if all_equal_so_far is still all ones then the two values are equal
Packit Service 084de1
     * and so out >= kPrime is true.
Packit Service 084de1
     */
Packit Service 084de1
    result |= all_equal_so_far;
Packit Service 084de1
Packit Service 084de1
    /* if out >= kPrime then we subtract kPrime. */
Packit Service 084de1
    subtract_u64(&out[0], &carry, result & kPrime[0]);
Packit Service 084de1
    subtract_u64(&out[1], &carry, carry);
Packit Service 084de1
    subtract_u64(&out[2], &carry, carry);
Packit Service 084de1
    subtract_u64(&out[3], &carry, carry);
Packit Service 084de1
Packit Service 084de1
    subtract_u64(&out[1], &carry, result & kPrime[1]);
Packit Service 084de1
    subtract_u64(&out[2], &carry, carry);
Packit Service 084de1
    subtract_u64(&out[3], &carry, carry);
Packit Service 084de1
Packit Service 084de1
    subtract_u64(&out[2], &carry, result & kPrime[2]);
Packit Service 084de1
    subtract_u64(&out[3], &carry, carry);
Packit Service 084de1
Packit Service 084de1
    subtract_u64(&out[3], &carry, result & kPrime[3]);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void smallfelem_square_contract(smallfelem out, const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    longfelem longtmp;
Packit Service 084de1
    felem tmp;
Packit Service 084de1
Packit Service 084de1
    smallfelem_square(longtmp, in);
Packit Service 084de1
    felem_reduce(tmp, longtmp);
Packit Service 084de1
    felem_contract(out, tmp);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void smallfelem_mul_contract(smallfelem out, const smallfelem in1,
Packit Service 084de1
                                    const smallfelem in2)
Packit Service 084de1
{
Packit Service 084de1
    longfelem longtmp;
Packit Service 084de1
    felem tmp;
Packit Service 084de1
Packit Service 084de1
    smallfelem_mul(longtmp, in1, in2);
Packit Service 084de1
    felem_reduce(tmp, longtmp);
Packit Service 084de1
    felem_contract(out, tmp);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
Packit Service 084de1
 * otherwise.
Packit Service 084de1
 * On entry:
Packit Service 084de1
 *   small[i] < 2^64
Packit Service 084de1
 */
Packit Service 084de1
static limb smallfelem_is_zero(const smallfelem small)
Packit Service 084de1
{
Packit Service 084de1
    limb result;
Packit Service 084de1
    u64 is_p;
Packit Service 084de1
Packit Service 084de1
    u64 is_zero = small[0] | small[1] | small[2] | small[3];
Packit Service 084de1
    is_zero--;
Packit Service 084de1
    is_zero &= is_zero << 32;
Packit Service 084de1
    is_zero &= is_zero << 16;
Packit Service 084de1
    is_zero &= is_zero << 8;
Packit Service 084de1
    is_zero &= is_zero << 4;
Packit Service 084de1
    is_zero &= is_zero << 2;
Packit Service 084de1
    is_zero &= is_zero << 1;
Packit Service 084de1
    is_zero = 0 - (is_zero >> 63);
Packit Service 084de1
Packit Service 084de1
    is_p = (small[0] ^ kPrime[0]) |
Packit Service 084de1
        (small[1] ^ kPrime[1]) |
Packit Service 084de1
        (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]);
Packit Service 084de1
    is_p--;
Packit Service 084de1
    is_p &= is_p << 32;
Packit Service 084de1
    is_p &= is_p << 16;
Packit Service 084de1
    is_p &= is_p << 8;
Packit Service 084de1
    is_p &= is_p << 4;
Packit Service 084de1
    is_p &= is_p << 2;
Packit Service 084de1
    is_p &= is_p << 1;
Packit Service 084de1
    is_p = 0 - (is_p >> 63);
Packit Service 084de1
Packit Service 084de1
    is_zero |= is_p;
Packit Service 084de1
Packit Service 084de1
    result = is_zero;
Packit Service 084de1
    result |= ((limb) is_zero) << 64;
Packit Service 084de1
    return result;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int smallfelem_is_zero_int(const void *small)
Packit Service 084de1
{
Packit Service 084de1
    return (int)(smallfelem_is_zero(small) & ((limb) 1));
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * felem_inv calculates |out| = |in|^{-1}
Packit Service 084de1
 *
Packit Service 084de1
 * Based on Fermat's Little Theorem:
Packit Service 084de1
 *   a^p = a (mod p)
Packit Service 084de1
 *   a^{p-1} = 1 (mod p)
Packit Service 084de1
 *   a^{p-2} = a^{-1} (mod p)
Packit Service 084de1
 */
Packit Service 084de1
static void felem_inv(felem out, const felem in)
Packit Service 084de1
{
Packit Service 084de1
    felem ftmp, ftmp2;
Packit Service 084de1
    /* each e_I will hold |in|^{2^I - 1} */
Packit Service 084de1
    felem e2, e4, e8, e16, e32, e64;
Packit Service 084de1
    longfelem tmp;
Packit Service 084de1
    unsigned i;
Packit Service 084de1
Packit Service 084de1
    felem_square(tmp, in);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^1 */
Packit Service 084de1
    felem_mul(tmp, in, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^2 - 2^0 */
Packit Service 084de1
    felem_assign(e2, ftmp);
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^3 - 2^1 */
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^4 - 2^2 */
Packit Service 084de1
    felem_mul(tmp, ftmp, e2);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^4 - 2^0 */
Packit Service 084de1
    felem_assign(e4, ftmp);
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^5 - 2^1 */
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^6 - 2^2 */
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^7 - 2^3 */
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^8 - 2^4 */
Packit Service 084de1
    felem_mul(tmp, ftmp, e4);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^8 - 2^0 */
Packit Service 084de1
    felem_assign(e8, ftmp);
Packit Service 084de1
    for (i = 0; i < 8; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp);
Packit Service 084de1
        felem_reduce(ftmp, tmp);
Packit Service 084de1
    }                           /* 2^16 - 2^8 */
Packit Service 084de1
    felem_mul(tmp, ftmp, e8);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^16 - 2^0 */
Packit Service 084de1
    felem_assign(e16, ftmp);
Packit Service 084de1
    for (i = 0; i < 16; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp);
Packit Service 084de1
        felem_reduce(ftmp, tmp);
Packit Service 084de1
    }                           /* 2^32 - 2^16 */
Packit Service 084de1
    felem_mul(tmp, ftmp, e16);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^32 - 2^0 */
Packit Service 084de1
    felem_assign(e32, ftmp);
Packit Service 084de1
    for (i = 0; i < 32; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp);
Packit Service 084de1
        felem_reduce(ftmp, tmp);
Packit Service 084de1
    }                           /* 2^64 - 2^32 */
Packit Service 084de1
    felem_assign(e64, ftmp);
Packit Service 084de1
    felem_mul(tmp, ftmp, in);
Packit Service 084de1
    felem_reduce(ftmp, tmp);    /* 2^64 - 2^32 + 2^0 */
Packit Service 084de1
    for (i = 0; i < 192; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp);
Packit Service 084de1
        felem_reduce(ftmp, tmp);
Packit Service 084de1
    }                           /* 2^256 - 2^224 + 2^192 */
Packit Service 084de1
Packit Service 084de1
    felem_mul(tmp, e64, e32);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^64 - 2^0 */
Packit Service 084de1
    for (i = 0; i < 16; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp2);
Packit Service 084de1
        felem_reduce(ftmp2, tmp);
Packit Service 084de1
    }                           /* 2^80 - 2^16 */
Packit Service 084de1
    felem_mul(tmp, ftmp2, e16);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^80 - 2^0 */
Packit Service 084de1
    for (i = 0; i < 8; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp2);
Packit Service 084de1
        felem_reduce(ftmp2, tmp);
Packit Service 084de1
    }                           /* 2^88 - 2^8 */
Packit Service 084de1
    felem_mul(tmp, ftmp2, e8);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^88 - 2^0 */
Packit Service 084de1
    for (i = 0; i < 4; i++) {
Packit Service 084de1
        felem_square(tmp, ftmp2);
Packit Service 084de1
        felem_reduce(ftmp2, tmp);
Packit Service 084de1
    }                           /* 2^92 - 2^4 */
Packit Service 084de1
    felem_mul(tmp, ftmp2, e4);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^92 - 2^0 */
Packit Service 084de1
    felem_square(tmp, ftmp2);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^93 - 2^1 */
Packit Service 084de1
    felem_square(tmp, ftmp2);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^94 - 2^2 */
Packit Service 084de1
    felem_mul(tmp, ftmp2, e2);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^94 - 2^0 */
Packit Service 084de1
    felem_square(tmp, ftmp2);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^95 - 2^1 */
Packit Service 084de1
    felem_square(tmp, ftmp2);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^96 - 2^2 */
Packit Service 084de1
    felem_mul(tmp, ftmp2, in);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);   /* 2^96 - 3 */
Packit Service 084de1
Packit Service 084de1
    felem_mul(tmp, ftmp2, ftmp);
Packit Service 084de1
    felem_reduce(out, tmp);     /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void smallfelem_inv_contract(smallfelem out, const smallfelem in)
Packit Service 084de1
{
Packit Service 084de1
    felem tmp;
Packit Service 084de1
Packit Service 084de1
    smallfelem_expand(tmp, in);
Packit Service 084de1
    felem_inv(tmp, tmp);
Packit Service 084de1
    felem_contract(out, tmp);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * Group operations
Packit Service 084de1
 * ----------------
Packit Service 084de1
 *
Packit Service 084de1
 * Building on top of the field operations we have the operations on the
Packit Service 084de1
 * elliptic curve group itself. Points on the curve are represented in Jacobian
Packit Service 084de1
 * coordinates
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * point_double calculates 2*(x_in, y_in, z_in)
Packit Service 084de1
 *
Packit Service 084de1
 * The method is taken from:
Packit Service 084de1
 *   http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
Packit Service 084de1
 *
Packit Service 084de1
 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
Packit Service 084de1
 * while x_out == y_in is not (maybe this works, but it's not tested).
Packit Service 084de1
 */
Packit Service 084de1
static void
Packit Service 084de1
point_double(felem x_out, felem y_out, felem z_out,
Packit Service 084de1
             const felem x_in, const felem y_in, const felem z_in)
Packit Service 084de1
{
Packit Service 084de1
    longfelem tmp, tmp2;
Packit Service 084de1
    felem delta, gamma, beta, alpha, ftmp, ftmp2;
Packit Service 084de1
    smallfelem small1, small2;
Packit Service 084de1
Packit Service 084de1
    felem_assign(ftmp, x_in);
Packit Service 084de1
    /* ftmp[i] < 2^106 */
Packit Service 084de1
    felem_assign(ftmp2, x_in);
Packit Service 084de1
    /* ftmp2[i] < 2^106 */
Packit Service 084de1
Packit Service 084de1
    /* delta = z^2 */
Packit Service 084de1
    felem_square(tmp, z_in);
Packit Service 084de1
    felem_reduce(delta, tmp);
Packit Service 084de1
    /* delta[i] < 2^101 */
Packit Service 084de1
Packit Service 084de1
    /* gamma = y^2 */
Packit Service 084de1
    felem_square(tmp, y_in);
Packit Service 084de1
    felem_reduce(gamma, tmp);
Packit Service 084de1
    /* gamma[i] < 2^101 */
Packit Service 084de1
    felem_shrink(small1, gamma);
Packit Service 084de1
Packit Service 084de1
    /* beta = x*gamma */
Packit Service 084de1
    felem_small_mul(tmp, small1, x_in);
Packit Service 084de1
    felem_reduce(beta, tmp);
Packit Service 084de1
    /* beta[i] < 2^101 */
Packit Service 084de1
Packit Service 084de1
    /* alpha = 3*(x-delta)*(x+delta) */
Packit Service 084de1
    felem_diff(ftmp, delta);
Packit Service 084de1
    /* ftmp[i] < 2^105 + 2^106 < 2^107 */
Packit Service 084de1
    felem_sum(ftmp2, delta);
Packit Service 084de1
    /* ftmp2[i] < 2^105 + 2^106 < 2^107 */
Packit Service 084de1
    felem_scalar(ftmp2, 3);
Packit Service 084de1
    /* ftmp2[i] < 3 * 2^107 < 2^109 */
Packit Service 084de1
    felem_mul(tmp, ftmp, ftmp2);
Packit Service 084de1
    felem_reduce(alpha, tmp);
Packit Service 084de1
    /* alpha[i] < 2^101 */
Packit Service 084de1
    felem_shrink(small2, alpha);
Packit Service 084de1
Packit Service 084de1
    /* x' = alpha^2 - 8*beta */
Packit Service 084de1
    smallfelem_square(tmp, small2);
Packit Service 084de1
    felem_reduce(x_out, tmp);
Packit Service 084de1
    felem_assign(ftmp, beta);
Packit Service 084de1
    felem_scalar(ftmp, 8);
Packit Service 084de1
    /* ftmp[i] < 8 * 2^101 = 2^104 */
Packit Service 084de1
    felem_diff(x_out, ftmp);
Packit Service 084de1
    /* x_out[i] < 2^105 + 2^101 < 2^106 */
Packit Service 084de1
Packit Service 084de1
    /* z' = (y + z)^2 - gamma - delta */
Packit Service 084de1
    felem_sum(delta, gamma);
Packit Service 084de1
    /* delta[i] < 2^101 + 2^101 = 2^102 */
Packit Service 084de1
    felem_assign(ftmp, y_in);
Packit Service 084de1
    felem_sum(ftmp, z_in);
Packit Service 084de1
    /* ftmp[i] < 2^106 + 2^106 = 2^107 */
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(z_out, tmp);
Packit Service 084de1
    felem_diff(z_out, delta);
Packit Service 084de1
    /* z_out[i] < 2^105 + 2^101 < 2^106 */
Packit Service 084de1
Packit Service 084de1
    /* y' = alpha*(4*beta - x') - 8*gamma^2 */
Packit Service 084de1
    felem_scalar(beta, 4);
Packit Service 084de1
    /* beta[i] < 4 * 2^101 = 2^103 */
Packit Service 084de1
    felem_diff_zero107(beta, x_out);
Packit Service 084de1
    /* beta[i] < 2^107 + 2^103 < 2^108 */
Packit Service 084de1
    felem_small_mul(tmp, small2, beta);
Packit Service 084de1
    /* tmp[i] < 7 * 2^64 < 2^67 */
Packit Service 084de1
    smallfelem_square(tmp2, small1);
Packit Service 084de1
    /* tmp2[i] < 7 * 2^64 */
Packit Service 084de1
    longfelem_scalar(tmp2, 8);
Packit Service 084de1
    /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */
Packit Service 084de1
    longfelem_diff(tmp, tmp2);
Packit Service 084de1
    /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
Packit Service 084de1
    felem_reduce_zero105(y_out, tmp);
Packit Service 084de1
    /* y_out[i] < 2^106 */
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * point_double_small is the same as point_double, except that it operates on
Packit Service 084de1
 * smallfelems
Packit Service 084de1
 */
Packit Service 084de1
static void
Packit Service 084de1
point_double_small(smallfelem x_out, smallfelem y_out, smallfelem z_out,
Packit Service 084de1
                   const smallfelem x_in, const smallfelem y_in,
Packit Service 084de1
                   const smallfelem z_in)
Packit Service 084de1
{
Packit Service 084de1
    felem felem_x_out, felem_y_out, felem_z_out;
Packit Service 084de1
    felem felem_x_in, felem_y_in, felem_z_in;
Packit Service 084de1
Packit Service 084de1
    smallfelem_expand(felem_x_in, x_in);
Packit Service 084de1
    smallfelem_expand(felem_y_in, y_in);
Packit Service 084de1
    smallfelem_expand(felem_z_in, z_in);
Packit Service 084de1
    point_double(felem_x_out, felem_y_out, felem_z_out,
Packit Service 084de1
                 felem_x_in, felem_y_in, felem_z_in);
Packit Service 084de1
    felem_shrink(x_out, felem_x_out);
Packit Service 084de1
    felem_shrink(y_out, felem_y_out);
Packit Service 084de1
    felem_shrink(z_out, felem_z_out);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* copy_conditional copies in to out iff mask is all ones. */
Packit Service 084de1
static void copy_conditional(felem out, const felem in, limb mask)
Packit Service 084de1
{
Packit Service 084de1
    unsigned i;
Packit Service 084de1
    for (i = 0; i < NLIMBS; ++i) {
Packit Service 084de1
        const limb tmp = mask & (in[i] ^ out[i]);
Packit Service 084de1
        out[i] ^= tmp;
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* copy_small_conditional copies in to out iff mask is all ones. */
Packit Service 084de1
static void copy_small_conditional(felem out, const smallfelem in, limb mask)
Packit Service 084de1
{
Packit Service 084de1
    unsigned i;
Packit Service 084de1
    const u64 mask64 = mask;
Packit Service 084de1
    for (i = 0; i < NLIMBS; ++i) {
Packit Service 084de1
        out[i] = ((limb) (in[i] & mask64)) | (out[i] & ~mask);
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * point_add calculates (x1, y1, z1) + (x2, y2, z2)
Packit Service 084de1
 *
Packit Service 084de1
 * The method is taken from:
Packit Service 084de1
 *   http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
Packit Service 084de1
 * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
Packit Service 084de1
 *
Packit Service 084de1
 * This function includes a branch for checking whether the two input points
Packit Service 084de1
 * are equal, (while not equal to the point at infinity). This case never
Packit Service 084de1
 * happens during single point multiplication, so there is no timing leak for
Packit Service 084de1
 * ECDH or ECDSA signing.
Packit Service 084de1
 */
Packit Service 084de1
static void point_add(felem x3, felem y3, felem z3,
Packit Service 084de1
                      const felem x1, const felem y1, const felem z1,
Packit Service 084de1
                      const int mixed, const smallfelem x2,
Packit Service 084de1
                      const smallfelem y2, const smallfelem z2)
Packit Service 084de1
{
Packit Service 084de1
    felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
Packit Service 084de1
    longfelem tmp, tmp2;
Packit Service 084de1
    smallfelem small1, small2, small3, small4, small5;
Packit Service 084de1
    limb x_equal, y_equal, z1_is_zero, z2_is_zero;
Packit Service 084de1
    limb points_equal;
Packit Service 084de1
Packit Service 084de1
    felem_shrink(small3, z1);
Packit Service 084de1
Packit Service 084de1
    z1_is_zero = smallfelem_is_zero(small3);
Packit Service 084de1
    z2_is_zero = smallfelem_is_zero(z2);
Packit Service 084de1
Packit Service 084de1
    /* ftmp = z1z1 = z1**2 */
Packit Service 084de1
    smallfelem_square(tmp, small3);
Packit Service 084de1
    felem_reduce(ftmp, tmp);
Packit Service 084de1
    /* ftmp[i] < 2^101 */
Packit Service 084de1
    felem_shrink(small1, ftmp);
Packit Service 084de1
Packit Service 084de1
    if (!mixed) {
Packit Service 084de1
        /* ftmp2 = z2z2 = z2**2 */
Packit Service 084de1
        smallfelem_square(tmp, z2);
Packit Service 084de1
        felem_reduce(ftmp2, tmp);
Packit Service 084de1
        /* ftmp2[i] < 2^101 */
Packit Service 084de1
        felem_shrink(small2, ftmp2);
Packit Service 084de1
Packit Service 084de1
        felem_shrink(small5, x1);
Packit Service 084de1
Packit Service 084de1
        /* u1 = ftmp3 = x1*z2z2 */
Packit Service 084de1
        smallfelem_mul(tmp, small5, small2);
Packit Service 084de1
        felem_reduce(ftmp3, tmp);
Packit Service 084de1
        /* ftmp3[i] < 2^101 */
Packit Service 084de1
Packit Service 084de1
        /* ftmp5 = z1 + z2 */
Packit Service 084de1
        felem_assign(ftmp5, z1);
Packit Service 084de1
        felem_small_sum(ftmp5, z2);
Packit Service 084de1
        /* ftmp5[i] < 2^107 */
Packit Service 084de1
Packit Service 084de1
        /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */
Packit Service 084de1
        felem_square(tmp, ftmp5);
Packit Service 084de1
        felem_reduce(ftmp5, tmp);
Packit Service 084de1
        /* ftmp2 = z2z2 + z1z1 */
Packit Service 084de1
        felem_sum(ftmp2, ftmp);
Packit Service 084de1
        /* ftmp2[i] < 2^101 + 2^101 = 2^102 */
Packit Service 084de1
        felem_diff(ftmp5, ftmp2);
Packit Service 084de1
        /* ftmp5[i] < 2^105 + 2^101 < 2^106 */
Packit Service 084de1
Packit Service 084de1
        /* ftmp2 = z2 * z2z2 */
Packit Service 084de1
        smallfelem_mul(tmp, small2, z2);
Packit Service 084de1
        felem_reduce(ftmp2, tmp);
Packit Service 084de1
Packit Service 084de1
        /* s1 = ftmp2 = y1 * z2**3 */
Packit Service 084de1
        felem_mul(tmp, y1, ftmp2);
Packit Service 084de1
        felem_reduce(ftmp6, tmp);
Packit Service 084de1
        /* ftmp6[i] < 2^101 */
Packit Service 084de1
    } else {
Packit Service 084de1
        /*
Packit Service 084de1
         * We'll assume z2 = 1 (special case z2 = 0 is handled later)
Packit Service 084de1
         */
Packit Service 084de1
Packit Service 084de1
        /* u1 = ftmp3 = x1*z2z2 */
Packit Service 084de1
        felem_assign(ftmp3, x1);
Packit Service 084de1
        /* ftmp3[i] < 2^106 */
Packit Service 084de1
Packit Service 084de1
        /* ftmp5 = 2z1z2 */
Packit Service 084de1
        felem_assign(ftmp5, z1);
Packit Service 084de1
        felem_scalar(ftmp5, 2);
Packit Service 084de1
        /* ftmp5[i] < 2*2^106 = 2^107 */
Packit Service 084de1
Packit Service 084de1
        /* s1 = ftmp2 = y1 * z2**3 */
Packit Service 084de1
        felem_assign(ftmp6, y1);
Packit Service 084de1
        /* ftmp6[i] < 2^106 */
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    /* u2 = x2*z1z1 */
Packit Service 084de1
    smallfelem_mul(tmp, x2, small1);
Packit Service 084de1
    felem_reduce(ftmp4, tmp);
Packit Service 084de1
Packit Service 084de1
    /* h = ftmp4 = u2 - u1 */
Packit Service 084de1
    felem_diff_zero107(ftmp4, ftmp3);
Packit Service 084de1
    /* ftmp4[i] < 2^107 + 2^101 < 2^108 */
Packit Service 084de1
    felem_shrink(small4, ftmp4);
Packit Service 084de1
Packit Service 084de1
    x_equal = smallfelem_is_zero(small4);
Packit Service 084de1
Packit Service 084de1
    /* z_out = ftmp5 * h */
Packit Service 084de1
    felem_small_mul(tmp, small4, ftmp5);
Packit Service 084de1
    felem_reduce(z_out, tmp);
Packit Service 084de1
    /* z_out[i] < 2^101 */
Packit Service 084de1
Packit Service 084de1
    /* ftmp = z1 * z1z1 */
Packit Service 084de1
    smallfelem_mul(tmp, small1, small3);
Packit Service 084de1
    felem_reduce(ftmp, tmp);
Packit Service 084de1
Packit Service 084de1
    /* s2 = tmp = y2 * z1**3 */
Packit Service 084de1
    felem_small_mul(tmp, y2, ftmp);
Packit Service 084de1
    felem_reduce(ftmp5, tmp);
Packit Service 084de1
Packit Service 084de1
    /* r = ftmp5 = (s2 - s1)*2 */
Packit Service 084de1
    felem_diff_zero107(ftmp5, ftmp6);
Packit Service 084de1
    /* ftmp5[i] < 2^107 + 2^107 = 2^108 */
Packit Service 084de1
    felem_scalar(ftmp5, 2);
Packit Service 084de1
    /* ftmp5[i] < 2^109 */
Packit Service 084de1
    felem_shrink(small1, ftmp5);
Packit Service 084de1
    y_equal = smallfelem_is_zero(small1);
Packit Service 084de1
Packit Service 084de1
    /*
Packit Service 084de1
     * The formulae are incorrect if the points are equal, in affine coordinates
Packit Service 084de1
     * (X_1, Y_1) == (X_2, Y_2), so we check for this and do doubling if this
Packit Service 084de1
     * happens.
Packit Service 084de1
     *
Packit Service 084de1
     * We use bitwise operations to avoid potential side-channels introduced by
Packit Service 084de1
     * the short-circuiting behaviour of boolean operators.
Packit Service 084de1
     *
Packit Service 084de1
     * The special case of either point being the point at infinity (z1 and/or
Packit Service 084de1
     * z2 are zero), is handled separately later on in this function, so we
Packit Service 084de1
     * avoid jumping to point_double here in those special cases.
Packit Service 084de1
     */
Packit Service 084de1
    points_equal = (x_equal & y_equal & (~z1_is_zero) & (~z2_is_zero));
Packit Service 084de1
Packit Service 084de1
    if (points_equal) {
Packit Service 084de1
        /*
Packit Service 084de1
         * This is obviously not constant-time but, as mentioned before, this
Packit Service 084de1
         * case never happens during single point multiplication, so there is no
Packit Service 084de1
         * timing leak for ECDH or ECDSA signing.
Packit Service 084de1
         */
Packit Service 084de1
        point_double(x3, y3, z3, x1, y1, z1);
Packit Service 084de1
        return;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    /* I = ftmp = (2h)**2 */
Packit Service 084de1
    felem_assign(ftmp, ftmp4);
Packit Service 084de1
    felem_scalar(ftmp, 2);
Packit Service 084de1
    /* ftmp[i] < 2*2^108 = 2^109 */
Packit Service 084de1
    felem_square(tmp, ftmp);
Packit Service 084de1
    felem_reduce(ftmp, tmp);
Packit Service 084de1
Packit Service 084de1
    /* J = ftmp2 = h * I */
Packit Service 084de1
    felem_mul(tmp, ftmp4, ftmp);
Packit Service 084de1
    felem_reduce(ftmp2, tmp);
Packit Service 084de1
Packit Service 084de1
    /* V = ftmp4 = U1 * I */
Packit Service 084de1
    felem_mul(tmp, ftmp3, ftmp);
Packit Service 084de1
    felem_reduce(ftmp4, tmp);
Packit Service 084de1
Packit Service 084de1
    /* x_out = r**2 - J - 2V */
Packit Service 084de1
    smallfelem_square(tmp, small1);
Packit Service 084de1
    felem_reduce(x_out, tmp);
Packit Service 084de1
    felem_assign(ftmp3, ftmp4);
Packit Service 084de1
    felem_scalar(ftmp4, 2);
Packit Service 084de1
    felem_sum(ftmp4, ftmp2);
Packit Service 084de1
    /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */
Packit Service 084de1
    felem_diff(x_out, ftmp4);
Packit Service 084de1
    /* x_out[i] < 2^105 + 2^101 */
Packit Service 084de1
Packit Service 084de1
    /* y_out = r(V-x_out) - 2 * s1 * J */
Packit Service 084de1
    felem_diff_zero107(ftmp3, x_out);
Packit Service 084de1
    /* ftmp3[i] < 2^107 + 2^101 < 2^108 */
Packit Service 084de1
    felem_small_mul(tmp, small1, ftmp3);
Packit Service 084de1
    felem_mul(tmp2, ftmp6, ftmp2);
Packit Service 084de1
    longfelem_scalar(tmp2, 2);
Packit Service 084de1
    /* tmp2[i] < 2*2^67 = 2^68 */
Packit Service 084de1
    longfelem_diff(tmp, tmp2);
Packit Service 084de1
    /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
Packit Service 084de1
    felem_reduce_zero105(y_out, tmp);
Packit Service 084de1
    /* y_out[i] < 2^106 */
Packit Service 084de1
Packit Service 084de1
    copy_small_conditional(x_out, x2, z1_is_zero);
Packit Service 084de1
    copy_conditional(x_out, x1, z2_is_zero);
Packit Service 084de1
    copy_small_conditional(y_out, y2, z1_is_zero);
Packit Service 084de1
    copy_conditional(y_out, y1, z2_is_zero);
Packit Service 084de1
    copy_small_conditional(z_out, z2, z1_is_zero);
Packit Service 084de1
    copy_conditional(z_out, z1, z2_is_zero);
Packit Service 084de1
    felem_assign(x3, x_out);
Packit Service 084de1
    felem_assign(y3, y_out);
Packit Service 084de1
    felem_assign(z3, z_out);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * point_add_small is the same as point_add, except that it operates on
Packit Service 084de1
 * smallfelems
Packit Service 084de1
 */
Packit Service 084de1
static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3,
Packit Service 084de1
                            smallfelem x1, smallfelem y1, smallfelem z1,
Packit Service 084de1
                            smallfelem x2, smallfelem y2, smallfelem z2)
Packit Service 084de1
{
Packit Service 084de1
    felem felem_x3, felem_y3, felem_z3;
Packit Service 084de1
    felem felem_x1, felem_y1, felem_z1;
Packit Service 084de1
    smallfelem_expand(felem_x1, x1);
Packit Service 084de1
    smallfelem_expand(felem_y1, y1);
Packit Service 084de1
    smallfelem_expand(felem_z1, z1);
Packit Service 084de1
    point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0,
Packit Service 084de1
              x2, y2, z2);
Packit Service 084de1
    felem_shrink(x3, felem_x3);
Packit Service 084de1
    felem_shrink(y3, felem_y3);
Packit Service 084de1
    felem_shrink(z3, felem_z3);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*-
Packit Service 084de1
 * Base point pre computation
Packit Service 084de1
 * --------------------------
Packit Service 084de1
 *
Packit Service 084de1
 * Two different sorts of precomputed tables are used in the following code.
Packit Service 084de1
 * Each contain various points on the curve, where each point is three field
Packit Service 084de1
 * elements (x, y, z).
Packit Service 084de1
 *
Packit Service 084de1
 * For the base point table, z is usually 1 (0 for the point at infinity).
Packit Service 084de1
 * This table has 2 * 16 elements, starting with the following:
Packit Service 084de1
 * index | bits    | point
Packit Service 084de1
 * ------+---------+------------------------------
Packit Service 084de1
 *     0 | 0 0 0 0 | 0G
Packit Service 084de1
 *     1 | 0 0 0 1 | 1G
Packit Service 084de1
 *     2 | 0 0 1 0 | 2^64G
Packit Service 084de1
 *     3 | 0 0 1 1 | (2^64 + 1)G
Packit Service 084de1
 *     4 | 0 1 0 0 | 2^128G
Packit Service 084de1
 *     5 | 0 1 0 1 | (2^128 + 1)G
Packit Service 084de1
 *     6 | 0 1 1 0 | (2^128 + 2^64)G
Packit Service 084de1
 *     7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
Packit Service 084de1
 *     8 | 1 0 0 0 | 2^192G
Packit Service 084de1
 *     9 | 1 0 0 1 | (2^192 + 1)G
Packit Service 084de1
 *    10 | 1 0 1 0 | (2^192 + 2^64)G
Packit Service 084de1
 *    11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
Packit Service 084de1
 *    12 | 1 1 0 0 | (2^192 + 2^128)G
Packit Service 084de1
 *    13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
Packit Service 084de1
 *    14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
Packit Service 084de1
 *    15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
Packit Service 084de1
 * followed by a copy of this with each element multiplied by 2^32.
Packit Service 084de1
 *
Packit Service 084de1
 * The reason for this is so that we can clock bits into four different
Packit Service 084de1
 * locations when doing simple scalar multiplies against the base point,
Packit Service 084de1
 * and then another four locations using the second 16 elements.
Packit Service 084de1
 *
Packit Service 084de1
 * Tables for other points have table[i] = iG for i in 0 .. 16. */
Packit Service 084de1
Packit Service 084de1
/* gmul is the table of precomputed base points */
Packit Service 084de1
static const smallfelem gmul[2][16][3] = {
Packit Service 084de1
    {{{0, 0, 0, 0},
Packit Service 084de1
      {0, 0, 0, 0},
Packit Service 084de1
      {0, 0, 0, 0}},
Packit Service 084de1
     {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2,
Packit Service 084de1
       0x6b17d1f2e12c4247},
Packit Service 084de1
      {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16,
Packit Service 084de1
       0x4fe342e2fe1a7f9b},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de,
Packit Service 084de1
       0x0fa822bc2811aaa5},
Packit Service 084de1
      {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b,
Packit Service 084de1
       0xbff44ae8f5dba80d},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789,
Packit Service 084de1
       0x300a4bbc89d6726f},
Packit Service 084de1
      {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f,
Packit Service 084de1
       0x72aac7e0d09b4644},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e,
Packit Service 084de1
       0x447d739beedb5e67},
Packit Service 084de1
      {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7,
Packit Service 084de1
       0x2d4825ab834131ee},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60,
Packit Service 084de1
       0xef9519328a9c72ff},
Packit Service 084de1
      {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c,
Packit Service 084de1
       0x611e9fc37dbb2c9b},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf,
Packit Service 084de1
       0x550663797b51f5d8},
Packit Service 084de1
      {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5,
Packit Service 084de1
       0x157164848aecb851},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391,
Packit Service 084de1
       0xeb5d7745b21141ea},
Packit Service 084de1
      {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee,
Packit Service 084de1
       0xeafd72ebdbecc17b},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5,
Packit Service 084de1
       0xa6d39677a7849276},
Packit Service 084de1
      {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf,
Packit Service 084de1
       0x674f84749b0b8816},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb,
Packit Service 084de1
       0x4e769e7672c9ddad},
Packit Service 084de1
      {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281,
Packit Service 084de1
       0x42b99082de830663},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478,
Packit Service 084de1
       0x78878ef61c6ce04d},
Packit Service 084de1
      {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def,
Packit Service 084de1
       0xb6cb3f5d7b72c321},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae,
Packit Service 084de1
       0x0c88bc4d716b1287},
Packit Service 084de1
      {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa,
Packit Service 084de1
       0xdd5ddea3f3901dc6},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3,
Packit Service 084de1
       0x68f344af6b317466},
Packit Service 084de1
      {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3,
Packit Service 084de1
       0x31b9c405f8540a20},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0,
Packit Service 084de1
       0x4052bf4b6f461db9},
Packit Service 084de1
      {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8,
Packit Service 084de1
       0xfecf4d5190b0fc61},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a,
Packit Service 084de1
       0x1eddbae2c802e41a},
Packit Service 084de1
      {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0,
Packit Service 084de1
       0x43104d86560ebcfc},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a,
Packit Service 084de1
       0xb48e26b484f7a21c},
Packit Service 084de1
      {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668,
Packit Service 084de1
       0xfac015404d4d3dab},
Packit Service 084de1
      {1, 0, 0, 0}}},
Packit Service 084de1
    {{{0, 0, 0, 0},
Packit Service 084de1
      {0, 0, 0, 0},
Packit Service 084de1
      {0, 0, 0, 0}},
Packit Service 084de1
     {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da,
Packit Service 084de1
       0x7fe36b40af22af89},
Packit Service 084de1
      {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1,
Packit Service 084de1
       0xe697d45825b63624},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902,
Packit Service 084de1
       0x4a5b506612a677a6},
Packit Service 084de1
      {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40,
Packit Service 084de1
       0xeb13461ceac089f1},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857,
Packit Service 084de1
       0x0781b8291c6a220a},
Packit Service 084de1
      {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434,
Packit Service 084de1
       0x690cde8df0151593},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326,
Packit Service 084de1
       0x8a535f566ec73617},
Packit Service 084de1
      {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf,
Packit Service 084de1
       0x0455c08468b08bd7},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279,
Packit Service 084de1
       0x06bada7ab77f8276},
Packit Service 084de1
      {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70,
Packit Service 084de1
       0x5b476dfd0e6cb18a},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8,
Packit Service 084de1
       0x3e29864e8a2ec908},
Packit Service 084de1
      {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed,
Packit Service 084de1
       0x239b90ea3dc31e7e},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4,
Packit Service 084de1
       0x820f4dd949f72ff7},
Packit Service 084de1
      {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3,
Packit Service 084de1
       0x140406ec783a05ec},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe,
Packit Service 084de1
       0x68f6b8542783dfee},
Packit Service 084de1
      {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028,
Packit Service 084de1
       0xcbe1feba92e40ce6},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927,
Packit Service 084de1
       0xd0b2f94d2f420109},
Packit Service 084de1
      {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a,
Packit Service 084de1
       0x971459828b0719e5},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687,
Packit Service 084de1
       0x961610004a866aba},
Packit Service 084de1
      {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c,
Packit Service 084de1
       0x7acb9fadcee75e44},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea,
Packit Service 084de1
       0x24eb9acca333bf5b},
Packit Service 084de1
      {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d,
Packit Service 084de1
       0x69f891c5acd079cc},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514,
Packit Service 084de1
       0xe51f547c5972a107},
Packit Service 084de1
      {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06,
Packit Service 084de1
       0x1c309a2b25bb1387},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828,
Packit Service 084de1
       0x20b87b8aa2c4e503},
Packit Service 084de1
      {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044,
Packit Service 084de1
       0xf5c6fa49919776be},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56,
Packit Service 084de1
       0x1ed7d1b9332010b9},
Packit Service 084de1
      {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24,
Packit Service 084de1
       0x3a2b03f03217257a},
Packit Service 084de1
      {1, 0, 0, 0}},
Packit Service 084de1
     {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b,
Packit Service 084de1
       0x15fee545c78dd9f6},
Packit Service 084de1
      {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb,
Packit Service 084de1
       0x4ab5b6b2b8753f81},
Packit Service 084de1
      {1, 0, 0, 0}}}
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * select_point selects the |idx|th point from a precomputation table and
Packit Service 084de1
 * copies it to out.
Packit Service 084de1
 */
Packit Service 084de1
static void select_point(const u64 idx, unsigned int size,
Packit Service 084de1
                         const smallfelem pre_comp[16][3], smallfelem out[3])
Packit Service 084de1
{
Packit Service 084de1
    unsigned i, j;
Packit Service 084de1
    u64 *outlimbs = &out[0][0];
Packit Service 084de1
Packit Service 084de1
    memset(out, 0, sizeof(*out) * 3);
Packit Service 084de1
Packit Service 084de1
    for (i = 0; i < size; i++) {
Packit Service 084de1
        const u64 *inlimbs = (u64 *)&pre_comp[i][0][0];
Packit Service 084de1
        u64 mask = i ^ idx;
Packit Service 084de1
        mask |= mask >> 4;
Packit Service 084de1
        mask |= mask >> 2;
Packit Service 084de1
        mask |= mask >> 1;
Packit Service 084de1
        mask &= 1;
Packit Service 084de1
        mask--;
Packit Service 084de1
        for (j = 0; j < NLIMBS * 3; j++)
Packit Service 084de1
            outlimbs[j] |= inlimbs[j] & mask;
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* get_bit returns the |i|th bit in |in| */
Packit Service 084de1
static char get_bit(const felem_bytearray in, int i)
Packit Service 084de1
{
Packit Service 084de1
    if ((i < 0) || (i >= 256))
Packit Service 084de1
        return 0;
Packit Service 084de1
    return (in[i >> 3] >> (i & 7)) & 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * Interleaved point multiplication using precomputed point multiples: The
Packit Service 084de1
 * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars
Packit Service 084de1
 * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the
Packit Service 084de1
 * generator, using certain (large) precomputed multiples in g_pre_comp.
Packit Service 084de1
 * Output point (X, Y, Z) is stored in x_out, y_out, z_out
Packit Service 084de1
 */
Packit Service 084de1
static void batch_mul(felem x_out, felem y_out, felem z_out,
Packit Service 084de1
                      const felem_bytearray scalars[],
Packit Service 084de1
                      const unsigned num_points, const u8 *g_scalar,
Packit Service 084de1
                      const int mixed, const smallfelem pre_comp[][17][3],
Packit Service 084de1
                      const smallfelem g_pre_comp[2][16][3])
Packit Service 084de1
{
Packit Service 084de1
    int i, skip;
Packit Service 084de1
    unsigned num, gen_mul = (g_scalar != NULL);
Packit Service 084de1
    felem nq[3], ftmp;
Packit Service 084de1
    smallfelem tmp[3];
Packit Service 084de1
    u64 bits;
Packit Service 084de1
    u8 sign, digit;
Packit Service 084de1
Packit Service 084de1
    /* set nq to the point at infinity */
Packit Service 084de1
    memset(nq, 0, sizeof(nq));
Packit Service 084de1
Packit Service 084de1
    /*
Packit Service 084de1
     * Loop over all scalars msb-to-lsb, interleaving additions of multiples
Packit Service 084de1
     * of the generator (two in each of the last 32 rounds) and additions of
Packit Service 084de1
     * other points multiples (every 5th round).
Packit Service 084de1
     */
Packit Service 084de1
    skip = 1;                   /* save two point operations in the first
Packit Service 084de1
                                 * round */
Packit Service 084de1
    for (i = (num_points ? 255 : 31); i >= 0; --i) {
Packit Service 084de1
        /* double */
Packit Service 084de1
        if (!skip)
Packit Service 084de1
            point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
Packit Service 084de1
Packit Service 084de1
        /* add multiples of the generator */
Packit Service 084de1
        if (gen_mul && (i <= 31)) {
Packit Service 084de1
            /* first, look 32 bits upwards */
Packit Service 084de1
            bits = get_bit(g_scalar, i + 224) << 3;
Packit Service 084de1
            bits |= get_bit(g_scalar, i + 160) << 2;
Packit Service 084de1
            bits |= get_bit(g_scalar, i + 96) << 1;
Packit Service 084de1
            bits |= get_bit(g_scalar, i + 32);
Packit Service 084de1
            /* select the point to add, in constant time */
Packit Service 084de1
            select_point(bits, 16, g_pre_comp[1], tmp);
Packit Service 084de1
Packit Service 084de1
            if (!skip) {
Packit Service 084de1
                /* Arg 1 below is for "mixed" */
Packit Service 084de1
                point_add(nq[0], nq[1], nq[2],
Packit Service 084de1
                          nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]);
Packit Service 084de1
            } else {
Packit Service 084de1
                smallfelem_expand(nq[0], tmp[0]);
Packit Service 084de1
                smallfelem_expand(nq[1], tmp[1]);
Packit Service 084de1
                smallfelem_expand(nq[2], tmp[2]);
Packit Service 084de1
                skip = 0;
Packit Service 084de1
            }
Packit Service 084de1
Packit Service 084de1
            /* second, look at the current position */
Packit Service 084de1
            bits = get_bit(g_scalar, i + 192) << 3;
Packit Service 084de1
            bits |= get_bit(g_scalar, i + 128) << 2;
Packit Service 084de1
            bits |= get_bit(g_scalar, i + 64) << 1;
Packit Service 084de1
            bits |= get_bit(g_scalar, i);
Packit Service 084de1
            /* select the point to add, in constant time */
Packit Service 084de1
            select_point(bits, 16, g_pre_comp[0], tmp);
Packit Service 084de1
            /* Arg 1 below is for "mixed" */
Packit Service 084de1
            point_add(nq[0], nq[1], nq[2],
Packit Service 084de1
                      nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]);
Packit Service 084de1
        }
Packit Service 084de1
Packit Service 084de1
        /* do other additions every 5 doublings */
Packit Service 084de1
        if (num_points && (i % 5 == 0)) {
Packit Service 084de1
            /* loop over all scalars */
Packit Service 084de1
            for (num = 0; num < num_points; ++num) {
Packit Service 084de1
                bits = get_bit(scalars[num], i + 4) << 5;
Packit Service 084de1
                bits |= get_bit(scalars[num], i + 3) << 4;
Packit Service 084de1
                bits |= get_bit(scalars[num], i + 2) << 3;
Packit Service 084de1
                bits |= get_bit(scalars[num], i + 1) << 2;
Packit Service 084de1
                bits |= get_bit(scalars[num], i) << 1;
Packit Service 084de1
                bits |= get_bit(scalars[num], i - 1);
Packit Service 084de1
                ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
Packit Service 084de1
Packit Service 084de1
                /*
Packit Service 084de1
                 * select the point to add or subtract, in constant time
Packit Service 084de1
                 */
Packit Service 084de1
                select_point(digit, 17, pre_comp[num], tmp);
Packit Service 084de1
                smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative
Packit Service 084de1
                                               * point */
Packit Service 084de1
                copy_small_conditional(ftmp, tmp[1], (((limb) sign) - 1));
Packit Service 084de1
                felem_contract(tmp[1], ftmp);
Packit Service 084de1
Packit Service 084de1
                if (!skip) {
Packit Service 084de1
                    point_add(nq[0], nq[1], nq[2],
Packit Service 084de1
                              nq[0], nq[1], nq[2],
Packit Service 084de1
                              mixed, tmp[0], tmp[1], tmp[2]);
Packit Service 084de1
                } else {
Packit Service 084de1
                    smallfelem_expand(nq[0], tmp[0]);
Packit Service 084de1
                    smallfelem_expand(nq[1], tmp[1]);
Packit Service 084de1
                    smallfelem_expand(nq[2], tmp[2]);
Packit Service 084de1
                    skip = 0;
Packit Service 084de1
                }
Packit Service 084de1
            }
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
    felem_assign(x_out, nq[0]);
Packit Service 084de1
    felem_assign(y_out, nq[1]);
Packit Service 084de1
    felem_assign(z_out, nq[2]);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* Precomputation for the group generator. */
Packit Service 084de1
struct nistp256_pre_comp_st {
Packit Service 084de1
    smallfelem g_pre_comp[2][16][3];
Packit Service 084de1
    CRYPTO_REF_COUNT references;
Packit Service 084de1
    CRYPTO_RWLOCK *lock;
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
const EC_METHOD *EC_GFp_nistp256_method(void)
Packit Service 084de1
{
Packit Service 084de1
    static const EC_METHOD ret = {
Packit Service 084de1
        EC_FLAGS_DEFAULT_OCT,
Packit Service 084de1
        NID_X9_62_prime_field,
Packit Service 084de1
        ec_GFp_nistp256_group_init,
Packit Service 084de1
        ec_GFp_simple_group_finish,
Packit Service 084de1
        ec_GFp_simple_group_clear_finish,
Packit Service 084de1
        ec_GFp_nist_group_copy,
Packit Service 084de1
        ec_GFp_nistp256_group_set_curve,
Packit Service 084de1
        ec_GFp_simple_group_get_curve,
Packit Service 084de1
        ec_GFp_simple_group_get_degree,
Packit Service 084de1
        ec_group_simple_order_bits,
Packit Service 084de1
        ec_GFp_simple_group_check_discriminant,
Packit Service 084de1
        ec_GFp_simple_point_init,
Packit Service 084de1
        ec_GFp_simple_point_finish,
Packit Service 084de1
        ec_GFp_simple_point_clear_finish,
Packit Service 084de1
        ec_GFp_simple_point_copy,
Packit Service 084de1
        ec_GFp_simple_point_set_to_infinity,
Packit Service 084de1
        ec_GFp_simple_set_Jprojective_coordinates_GFp,
Packit Service 084de1
        ec_GFp_simple_get_Jprojective_coordinates_GFp,
Packit Service 084de1
        ec_GFp_simple_point_set_affine_coordinates,
Packit Service 084de1
        ec_GFp_nistp256_point_get_affine_coordinates,
Packit Service 084de1
        0 /* point_set_compressed_coordinates */ ,
Packit Service 084de1
        0 /* point2oct */ ,
Packit Service 084de1
        0 /* oct2point */ ,
Packit Service 084de1
        ec_GFp_simple_add,
Packit Service 084de1
        ec_GFp_simple_dbl,
Packit Service 084de1
        ec_GFp_simple_invert,
Packit Service 084de1
        ec_GFp_simple_is_at_infinity,
Packit Service 084de1
        ec_GFp_simple_is_on_curve,
Packit Service 084de1
        ec_GFp_simple_cmp,
Packit Service 084de1
        ec_GFp_simple_make_affine,
Packit Service 084de1
        ec_GFp_simple_points_make_affine,
Packit Service 084de1
        ec_GFp_nistp256_points_mul,
Packit Service 084de1
        ec_GFp_nistp256_precompute_mult,
Packit Service 084de1
        ec_GFp_nistp256_have_precompute_mult,
Packit Service 084de1
        ec_GFp_nist_field_mul,
Packit Service 084de1
        ec_GFp_nist_field_sqr,
Packit Service 084de1
        0 /* field_div */ ,
Packit Service 084de1
        ec_GFp_simple_field_inv,
Packit Service 084de1
        0 /* field_encode */ ,
Packit Service 084de1
        0 /* field_decode */ ,
Packit Service 084de1
        0,                      /* field_set_to_one */
Packit Service 084de1
        ec_key_simple_priv2oct,
Packit Service 084de1
        ec_key_simple_oct2priv,
Packit Service 084de1
        0, /* set private */
Packit Service 084de1
        ec_key_simple_generate_key,
Packit Service 084de1
        ec_key_simple_check_key,
Packit Service 084de1
        ec_key_simple_generate_public_key,
Packit Service 084de1
        0, /* keycopy */
Packit Service 084de1
        0, /* keyfinish */
Packit Service 084de1
        ecdh_simple_compute_key,
Packit Service 084de1
        ecdsa_simple_sign_setup,
Packit Service 084de1
        ecdsa_simple_sign_sig,
Packit Service 084de1
        ecdsa_simple_verify_sig,
Packit Service 084de1
        0, /* field_inverse_mod_ord */
Packit Service 084de1
        0, /* blind_coordinates */
Packit Service 084de1
        0, /* ladder_pre */
Packit Service 084de1
        0, /* ladder_step */
Packit Service 084de1
        0  /* ladder_post */
Packit Service 084de1
    };
Packit Service 084de1
Packit Service 084de1
    return &ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/******************************************************************************/
Packit Service 084de1
/*
Packit Service 084de1
 * FUNCTIONS TO MANAGE PRECOMPUTATION
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
static NISTP256_PRE_COMP *nistp256_pre_comp_new(void)
Packit Service 084de1
{
Packit Service 084de1
    NISTP256_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
Packit Service 084de1
Packit Service 084de1
    if (ret == NULL) {
Packit Service 084de1
        ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
Packit Service 084de1
        return ret;
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    ret->references = 1;
Packit Service 084de1
Packit Service 084de1
    ret->lock = CRYPTO_THREAD_lock_new();
Packit Service 084de1
    if (ret->lock == NULL) {
Packit Service 084de1
        ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
Packit Service 084de1
        OPENSSL_free(ret);
Packit Service 084de1
        return NULL;
Packit Service 084de1
    }
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *p)
Packit Service 084de1
{
Packit Service 084de1
    int i;
Packit Service 084de1
    if (p != NULL)
Packit Service 084de1
        CRYPTO_UP_REF(&p->references, &i, p->lock);
Packit Service 084de1
    return p;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre)
Packit Service 084de1
{
Packit Service 084de1
    int i;
Packit Service 084de1
Packit Service 084de1
    if (pre == NULL)
Packit Service 084de1
        return;
Packit Service 084de1
Packit Service 084de1
    CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
Packit Service 084de1
    REF_PRINT_COUNT("EC_nistp256", x);
Packit Service 084de1
    if (i > 0)
Packit Service 084de1
        return;
Packit Service 084de1
    REF_ASSERT_ISNT(i < 0);
Packit Service 084de1
Packit Service 084de1
    CRYPTO_THREAD_lock_free(pre->lock);
Packit Service 084de1
    OPENSSL_free(pre);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/******************************************************************************/
Packit Service 084de1
/*
Packit Service 084de1
 * OPENSSL EC_METHOD FUNCTIONS
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
int ec_GFp_nistp256_group_init(EC_GROUP *group)
Packit Service 084de1
{
Packit Service 084de1
    int ret;
Packit Service 084de1
    ret = ec_GFp_simple_group_init(group);
Packit Service 084de1
    group->a_is_minus3 = 1;
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
Packit Service 084de1
                                    const BIGNUM *a, const BIGNUM *b,
Packit Service 084de1
                                    BN_CTX *ctx)
Packit Service 084de1
{
Packit Service 084de1
    int ret = 0;
Packit Service 084de1
    BN_CTX *new_ctx = NULL;
Packit Service 084de1
    BIGNUM *curve_p, *curve_a, *curve_b;
Packit Service 084de1
Packit Service 084de1
    if (ctx == NULL)
Packit Service 084de1
        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
Packit Service 084de1
            return 0;
Packit Service 084de1
    BN_CTX_start(ctx);
Packit Service 084de1
    curve_p = BN_CTX_get(ctx);
Packit Service 084de1
    curve_a = BN_CTX_get(ctx);
Packit Service 084de1
    curve_b = BN_CTX_get(ctx);
Packit Service 084de1
    if (curve_b == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
Packit Service 084de1
    BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
Packit Service 084de1
    BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
Packit Service 084de1
    if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) {
Packit Service 084de1
        ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE,
Packit Service 084de1
              EC_R_WRONG_CURVE_PARAMETERS);
Packit Service 084de1
        goto err;
Packit Service 084de1
    }
Packit Service 084de1
    group->field_mod_func = BN_nist_mod_256;
Packit Service 084de1
    ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
Packit Service 084de1
 err:
Packit Service 084de1
    BN_CTX_end(ctx);
Packit Service 084de1
    BN_CTX_free(new_ctx);
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
Packit Service 084de1
 * (X/Z^2, Y/Z^3)
Packit Service 084de1
 */
Packit Service 084de1
int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
Packit Service 084de1
                                                 const EC_POINT *point,
Packit Service 084de1
                                                 BIGNUM *x, BIGNUM *y,
Packit Service 084de1
                                                 BN_CTX *ctx)
Packit Service 084de1
{
Packit Service 084de1
    felem z1, z2, x_in, y_in;
Packit Service 084de1
    smallfelem x_out, y_out;
Packit Service 084de1
    longfelem tmp;
Packit Service 084de1
Packit Service 084de1
    if (EC_POINT_is_at_infinity(group, point)) {
Packit Service 084de1
        ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
Packit Service 084de1
              EC_R_POINT_AT_INFINITY);
Packit Service 084de1
        return 0;
Packit Service 084de1
    }
Packit Service 084de1
    if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) ||
Packit Service 084de1
        (!BN_to_felem(z1, point->Z)))
Packit Service 084de1
        return 0;
Packit Service 084de1
    felem_inv(z2, z1);
Packit Service 084de1
    felem_square(tmp, z2);
Packit Service 084de1
    felem_reduce(z1, tmp);
Packit Service 084de1
    felem_mul(tmp, x_in, z1);
Packit Service 084de1
    felem_reduce(x_in, tmp);
Packit Service 084de1
    felem_contract(x_out, x_in);
Packit Service 084de1
    if (x != NULL) {
Packit Service 084de1
        if (!smallfelem_to_BN(x, x_out)) {
Packit Service 084de1
            ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
Packit Service 084de1
                  ERR_R_BN_LIB);
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
    felem_mul(tmp, z1, z2);
Packit Service 084de1
    felem_reduce(z1, tmp);
Packit Service 084de1
    felem_mul(tmp, y_in, z1);
Packit Service 084de1
    felem_reduce(y_in, tmp);
Packit Service 084de1
    felem_contract(y_out, y_in);
Packit Service 084de1
    if (y != NULL) {
Packit Service 084de1
        if (!smallfelem_to_BN(y, y_out)) {
Packit Service 084de1
            ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
Packit Service 084de1
                  ERR_R_BN_LIB);
Packit Service 084de1
            return 0;
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */
Packit Service 084de1
static void make_points_affine(size_t num, smallfelem points[][3],
Packit Service 084de1
                               smallfelem tmp_smallfelems[])
Packit Service 084de1
{
Packit Service 084de1
    /*
Packit Service 084de1
     * Runs in constant time, unless an input is the point at infinity (which
Packit Service 084de1
     * normally shouldn't happen).
Packit Service 084de1
     */
Packit Service 084de1
    ec_GFp_nistp_points_make_affine_internal(num,
Packit Service 084de1
                                             points,
Packit Service 084de1
                                             sizeof(smallfelem),
Packit Service 084de1
                                             tmp_smallfelems,
Packit Service 084de1
                                             (void (*)(void *))smallfelem_one,
Packit Service 084de1
                                             smallfelem_is_zero_int,
Packit Service 084de1
                                             (void (*)(void *, const void *))
Packit Service 084de1
                                             smallfelem_assign,
Packit Service 084de1
                                             (void (*)(void *, const void *))
Packit Service 084de1
                                             smallfelem_square_contract,
Packit Service 084de1
                                             (void (*)
Packit Service 084de1
                                              (void *, const void *,
Packit Service 084de1
                                               const void *))
Packit Service 084de1
                                             smallfelem_mul_contract,
Packit Service 084de1
                                             (void (*)(void *, const void *))
Packit Service 084de1
                                             smallfelem_inv_contract,
Packit Service 084de1
                                             /* nothing to contract */
Packit Service 084de1
                                             (void (*)(void *, const void *))
Packit Service 084de1
                                             smallfelem_assign);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
/*
Packit Service 084de1
 * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL
Packit Service 084de1
 * values Result is stored in r (r can equal one of the inputs).
Packit Service 084de1
 */
Packit Service 084de1
int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
Packit Service 084de1
                               const BIGNUM *scalar, size_t num,
Packit Service 084de1
                               const EC_POINT *points[],
Packit Service 084de1
                               const BIGNUM *scalars[], BN_CTX *ctx)
Packit Service 084de1
{
Packit Service 084de1
    int ret = 0;
Packit Service 084de1
    int j;
Packit Service 084de1
    int mixed = 0;
Packit Service 084de1
    BIGNUM *x, *y, *z, *tmp_scalar;
Packit Service 084de1
    felem_bytearray g_secret;
Packit Service 084de1
    felem_bytearray *secrets = NULL;
Packit Service 084de1
    smallfelem (*pre_comp)[17][3] = NULL;
Packit Service 084de1
    smallfelem *tmp_smallfelems = NULL;
Packit Service 084de1
    unsigned i;
Packit Service 084de1
    int num_bytes;
Packit Service 084de1
    int have_pre_comp = 0;
Packit Service 084de1
    size_t num_points = num;
Packit Service 084de1
    smallfelem x_in, y_in, z_in;
Packit Service 084de1
    felem x_out, y_out, z_out;
Packit Service 084de1
    NISTP256_PRE_COMP *pre = NULL;
Packit Service 084de1
    const smallfelem(*g_pre_comp)[16][3] = NULL;
Packit Service 084de1
    EC_POINT *generator = NULL;
Packit Service 084de1
    const EC_POINT *p = NULL;
Packit Service 084de1
    const BIGNUM *p_scalar = NULL;
Packit Service 084de1
Packit Service 084de1
    BN_CTX_start(ctx);
Packit Service 084de1
    x = BN_CTX_get(ctx);
Packit Service 084de1
    y = BN_CTX_get(ctx);
Packit Service 084de1
    z = BN_CTX_get(ctx);
Packit Service 084de1
    tmp_scalar = BN_CTX_get(ctx);
Packit Service 084de1
    if (tmp_scalar == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
Packit Service 084de1
    if (scalar != NULL) {
Packit Service 084de1
        pre = group->pre_comp.nistp256;
Packit Service 084de1
        if (pre)
Packit Service 084de1
            /* we have precomputation, try to use it */
Packit Service 084de1
            g_pre_comp = (const smallfelem(*)[16][3])pre->g_pre_comp;
Packit Service 084de1
        else
Packit Service 084de1
            /* try to use the standard precomputation */
Packit Service 084de1
            g_pre_comp = &gmul[0];
Packit Service 084de1
        generator = EC_POINT_new(group);
Packit Service 084de1
        if (generator == NULL)
Packit Service 084de1
            goto err;
Packit Service 084de1
        /* get the generator from precomputation */
Packit Service 084de1
        if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) ||
Packit Service 084de1
            !smallfelem_to_BN(y, g_pre_comp[0][1][1]) ||
Packit Service 084de1
            !smallfelem_to_BN(z, g_pre_comp[0][1][2])) {
Packit Service 084de1
            ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
Packit Service 084de1
            goto err;
Packit Service 084de1
        }
Packit Service 084de1
        if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
Packit Service 084de1
                                                      generator, x, y, z,
Packit Service 084de1
                                                      ctx))
Packit Service 084de1
            goto err;
Packit Service 084de1
        if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
Packit Service 084de1
            /* precomputation matches generator */
Packit Service 084de1
            have_pre_comp = 1;
Packit Service 084de1
        else
Packit Service 084de1
            /*
Packit Service 084de1
             * we don't have valid precomputation: treat the generator as a
Packit Service 084de1
             * random point
Packit Service 084de1
             */
Packit Service 084de1
            num_points++;
Packit Service 084de1
    }
Packit Service 084de1
    if (num_points > 0) {
Packit Service 084de1
        if (num_points >= 3) {
Packit Service 084de1
            /*
Packit Service 084de1
             * unless we precompute multiples for just one or two points,
Packit Service 084de1
             * converting those into affine form is time well spent
Packit Service 084de1
             */
Packit Service 084de1
            mixed = 1;
Packit Service 084de1
        }
Packit Service 084de1
        secrets = OPENSSL_malloc(sizeof(*secrets) * num_points);
Packit Service 084de1
        pre_comp = OPENSSL_malloc(sizeof(*pre_comp) * num_points);
Packit Service 084de1
        if (mixed)
Packit Service 084de1
            tmp_smallfelems =
Packit Service 084de1
              OPENSSL_malloc(sizeof(*tmp_smallfelems) * (num_points * 17 + 1));
Packit Service 084de1
        if ((secrets == NULL) || (pre_comp == NULL)
Packit Service 084de1
            || (mixed && (tmp_smallfelems == NULL))) {
Packit Service 084de1
            ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
Packit Service 084de1
            goto err;
Packit Service 084de1
        }
Packit Service 084de1
Packit Service 084de1
        /*
Packit Service 084de1
         * we treat NULL scalars as 0, and NULL points as points at infinity,
Packit Service 084de1
         * i.e., they contribute nothing to the linear combination
Packit Service 084de1
         */
Packit Service 084de1
        memset(secrets, 0, sizeof(*secrets) * num_points);
Packit Service 084de1
        memset(pre_comp, 0, sizeof(*pre_comp) * num_points);
Packit Service 084de1
        for (i = 0; i < num_points; ++i) {
Packit Service 084de1
            if (i == num) {
Packit Service 084de1
                /*
Packit Service 084de1
                 * we didn't have a valid precomputation, so we pick the
Packit Service 084de1
                 * generator
Packit Service 084de1
                 */
Packit Service 084de1
                p = EC_GROUP_get0_generator(group);
Packit Service 084de1
                p_scalar = scalar;
Packit Service 084de1
            } else {
Packit Service 084de1
                /* the i^th point */
Packit Service 084de1
                p = points[i];
Packit Service 084de1
                p_scalar = scalars[i];
Packit Service 084de1
            }
Packit Service 084de1
            if ((p_scalar != NULL) && (p != NULL)) {
Packit Service 084de1
                /* reduce scalar to 0 <= scalar < 2^256 */
Packit Service 084de1
                if ((BN_num_bits(p_scalar) > 256)
Packit Service 084de1
                    || (BN_is_negative(p_scalar))) {
Packit Service 084de1
                    /*
Packit Service 084de1
                     * this is an unusual input, and we don't guarantee
Packit Service 084de1
                     * constant-timeness
Packit Service 084de1
                     */
Packit Service 084de1
                    if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) {
Packit Service 084de1
                        ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
Packit Service 084de1
                        goto err;
Packit Service 084de1
                    }
Packit Service 084de1
                    num_bytes = BN_bn2lebinpad(tmp_scalar,
Packit Service 084de1
                                               secrets[i], sizeof(secrets[i]));
Packit Service 084de1
                } else {
Packit Service 084de1
                    num_bytes = BN_bn2lebinpad(p_scalar,
Packit Service 084de1
                                               secrets[i], sizeof(secrets[i]));
Packit Service 084de1
                }
Packit Service 084de1
                if (num_bytes < 0) {
Packit Service 084de1
                    ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
Packit Service 084de1
                    goto err;
Packit Service 084de1
                }
Packit Service 084de1
                /* precompute multiples */
Packit Service 084de1
                if ((!BN_to_felem(x_out, p->X)) ||
Packit Service 084de1
                    (!BN_to_felem(y_out, p->Y)) ||
Packit Service 084de1
                    (!BN_to_felem(z_out, p->Z)))
Packit Service 084de1
                    goto err;
Packit Service 084de1
                felem_shrink(pre_comp[i][1][0], x_out);
Packit Service 084de1
                felem_shrink(pre_comp[i][1][1], y_out);
Packit Service 084de1
                felem_shrink(pre_comp[i][1][2], z_out);
Packit Service 084de1
                for (j = 2; j <= 16; ++j) {
Packit Service 084de1
                    if (j & 1) {
Packit Service 084de1
                        point_add_small(pre_comp[i][j][0], pre_comp[i][j][1],
Packit Service 084de1
                                        pre_comp[i][j][2], pre_comp[i][1][0],
Packit Service 084de1
                                        pre_comp[i][1][1], pre_comp[i][1][2],
Packit Service 084de1
                                        pre_comp[i][j - 1][0],
Packit Service 084de1
                                        pre_comp[i][j - 1][1],
Packit Service 084de1
                                        pre_comp[i][j - 1][2]);
Packit Service 084de1
                    } else {
Packit Service 084de1
                        point_double_small(pre_comp[i][j][0],
Packit Service 084de1
                                           pre_comp[i][j][1],
Packit Service 084de1
                                           pre_comp[i][j][2],
Packit Service 084de1
                                           pre_comp[i][j / 2][0],
Packit Service 084de1
                                           pre_comp[i][j / 2][1],
Packit Service 084de1
                                           pre_comp[i][j / 2][2]);
Packit Service 084de1
                    }
Packit Service 084de1
                }
Packit Service 084de1
            }
Packit Service 084de1
        }
Packit Service 084de1
        if (mixed)
Packit Service 084de1
            make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
Packit Service 084de1
    }
Packit Service 084de1
Packit Service 084de1
    /* the scalar for the generator */
Packit Service 084de1
    if ((scalar != NULL) && (have_pre_comp)) {
Packit Service 084de1
        memset(g_secret, 0, sizeof(g_secret));
Packit Service 084de1
        /* reduce scalar to 0 <= scalar < 2^256 */
Packit Service 084de1
        if ((BN_num_bits(scalar) > 256) || (BN_is_negative(scalar))) {
Packit Service 084de1
            /*
Packit Service 084de1
             * this is an unusual input, and we don't guarantee
Packit Service 084de1
             * constant-timeness
Packit Service 084de1
             */
Packit Service 084de1
            if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
Packit Service 084de1
                ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
Packit Service 084de1
                goto err;
Packit Service 084de1
            }
Packit Service 084de1
            num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret));
Packit Service 084de1
        } else {
Packit Service 084de1
            num_bytes = BN_bn2lebinpad(scalar, g_secret, sizeof(g_secret));
Packit Service 084de1
        }
Packit Service 084de1
        /* do the multiplication with generator precomputation */
Packit Service 084de1
        batch_mul(x_out, y_out, z_out,
Packit Service 084de1
                  (const felem_bytearray(*))secrets, num_points,
Packit Service 084de1
                  g_secret,
Packit Service 084de1
                  mixed, (const smallfelem(*)[17][3])pre_comp, g_pre_comp);
Packit Service 084de1
    } else {
Packit Service 084de1
        /* do the multiplication without generator precomputation */
Packit Service 084de1
        batch_mul(x_out, y_out, z_out,
Packit Service 084de1
                  (const felem_bytearray(*))secrets, num_points,
Packit Service 084de1
                  NULL, mixed, (const smallfelem(*)[17][3])pre_comp, NULL);
Packit Service 084de1
    }
Packit Service 084de1
    /* reduce the output to its unique minimal representation */
Packit Service 084de1
    felem_contract(x_in, x_out);
Packit Service 084de1
    felem_contract(y_in, y_out);
Packit Service 084de1
    felem_contract(z_in, z_out);
Packit Service 084de1
    if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) ||
Packit Service 084de1
        (!smallfelem_to_BN(z, z_in))) {
Packit Service 084de1
        ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
Packit Service 084de1
        goto err;
Packit Service 084de1
    }
Packit Service 084de1
    ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
Packit Service 084de1
Packit Service 084de1
 err:
Packit Service 084de1
    BN_CTX_end(ctx);
Packit Service 084de1
    EC_POINT_free(generator);
Packit Service 084de1
    OPENSSL_free(secrets);
Packit Service 084de1
    OPENSSL_free(pre_comp);
Packit Service 084de1
    OPENSSL_free(tmp_smallfelems);
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
Packit Service 084de1
{
Packit Service 084de1
    int ret = 0;
Packit Service 084de1
    NISTP256_PRE_COMP *pre = NULL;
Packit Service 084de1
    int i, j;
Packit Service 084de1
    BN_CTX *new_ctx = NULL;
Packit Service 084de1
    BIGNUM *x, *y;
Packit Service 084de1
    EC_POINT *generator = NULL;
Packit Service 084de1
    smallfelem tmp_smallfelems[32];
Packit Service 084de1
    felem x_tmp, y_tmp, z_tmp;
Packit Service 084de1
Packit Service 084de1
    /* throw away old precomputation */
Packit Service 084de1
    EC_pre_comp_free(group);
Packit Service 084de1
    if (ctx == NULL)
Packit Service 084de1
        if ((ctx = new_ctx = BN_CTX_new()) == NULL)
Packit Service 084de1
            return 0;
Packit Service 084de1
    BN_CTX_start(ctx);
Packit Service 084de1
    x = BN_CTX_get(ctx);
Packit Service 084de1
    y = BN_CTX_get(ctx);
Packit Service 084de1
    if (y == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    /* get the generator */
Packit Service 084de1
    if (group->generator == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    generator = EC_POINT_new(group);
Packit Service 084de1
    if (generator == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    BN_bin2bn(nistp256_curve_params[3], sizeof(felem_bytearray), x);
Packit Service 084de1
    BN_bin2bn(nistp256_curve_params[4], sizeof(felem_bytearray), y);
Packit Service 084de1
    if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx))
Packit Service 084de1
        goto err;
Packit Service 084de1
    if ((pre = nistp256_pre_comp_new()) == NULL)
Packit Service 084de1
        goto err;
Packit Service 084de1
    /*
Packit Service 084de1
     * if the generator is the standard one, use built-in precomputation
Packit Service 084de1
     */
Packit Service 084de1
    if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) {
Packit Service 084de1
        memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
Packit Service 084de1
        goto done;
Packit Service 084de1
    }
Packit Service 084de1
    if ((!BN_to_felem(x_tmp, group->generator->X)) ||
Packit Service 084de1
        (!BN_to_felem(y_tmp, group->generator->Y)) ||
Packit Service 084de1
        (!BN_to_felem(z_tmp, group->generator->Z)))
Packit Service 084de1
        goto err;
Packit Service 084de1
    felem_shrink(pre->g_pre_comp[0][1][0], x_tmp);
Packit Service 084de1
    felem_shrink(pre->g_pre_comp[0][1][1], y_tmp);
Packit Service 084de1
    felem_shrink(pre->g_pre_comp[0][1][2], z_tmp);
Packit Service 084de1
    /*
Packit Service 084de1
     * compute 2^64*G, 2^128*G, 2^192*G for the first table, 2^32*G, 2^96*G,
Packit Service 084de1
     * 2^160*G, 2^224*G for the second one
Packit Service 084de1
     */
Packit Service 084de1
    for (i = 1; i <= 8; i <<= 1) {
Packit Service 084de1
        point_double_small(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1],
Packit Service 084de1
                           pre->g_pre_comp[1][i][2], pre->g_pre_comp[0][i][0],
Packit Service 084de1
                           pre->g_pre_comp[0][i][1],
Packit Service 084de1
                           pre->g_pre_comp[0][i][2]);
Packit Service 084de1
        for (j = 0; j < 31; ++j) {
Packit Service 084de1
            point_double_small(pre->g_pre_comp[1][i][0],
Packit Service 084de1
                               pre->g_pre_comp[1][i][1],
Packit Service 084de1
                               pre->g_pre_comp[1][i][2],
Packit Service 084de1
                               pre->g_pre_comp[1][i][0],
Packit Service 084de1
                               pre->g_pre_comp[1][i][1],
Packit Service 084de1
                               pre->g_pre_comp[1][i][2]);
Packit Service 084de1
        }
Packit Service 084de1
        if (i == 8)
Packit Service 084de1
            break;
Packit Service 084de1
        point_double_small(pre->g_pre_comp[0][2 * i][0],
Packit Service 084de1
                           pre->g_pre_comp[0][2 * i][1],
Packit Service 084de1
                           pre->g_pre_comp[0][2 * i][2],
Packit Service 084de1
                           pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1],
Packit Service 084de1
                           pre->g_pre_comp[1][i][2]);
Packit Service 084de1
        for (j = 0; j < 31; ++j) {
Packit Service 084de1
            point_double_small(pre->g_pre_comp[0][2 * i][0],
Packit Service 084de1
                               pre->g_pre_comp[0][2 * i][1],
Packit Service 084de1
                               pre->g_pre_comp[0][2 * i][2],
Packit Service 084de1
                               pre->g_pre_comp[0][2 * i][0],
Packit Service 084de1
                               pre->g_pre_comp[0][2 * i][1],
Packit Service 084de1
                               pre->g_pre_comp[0][2 * i][2]);
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
    for (i = 0; i < 2; i++) {
Packit Service 084de1
        /* g_pre_comp[i][0] is the point at infinity */
Packit Service 084de1
        memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0]));
Packit Service 084de1
        /* the remaining multiples */
Packit Service 084de1
        /* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */
Packit Service 084de1
        point_add_small(pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1],
Packit Service 084de1
                        pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0],
Packit Service 084de1
                        pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2],
Packit Service 084de1
                        pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
Packit Service 084de1
                        pre->g_pre_comp[i][2][2]);
Packit Service 084de1
        /* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */
Packit Service 084de1
        point_add_small(pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1],
Packit Service 084de1
                        pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0],
Packit Service 084de1
                        pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
Packit Service 084de1
                        pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
Packit Service 084de1
                        pre->g_pre_comp[i][2][2]);
Packit Service 084de1
        /* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */
Packit Service 084de1
        point_add_small(pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1],
Packit Service 084de1
                        pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0],
Packit Service 084de1
                        pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
Packit Service 084de1
                        pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1],
Packit Service 084de1
                        pre->g_pre_comp[i][4][2]);
Packit Service 084de1
        /*
Packit Service 084de1
         * 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G
Packit Service 084de1
         */
Packit Service 084de1
        point_add_small(pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1],
Packit Service 084de1
                        pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0],
Packit Service 084de1
                        pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
Packit Service 084de1
                        pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
Packit Service 084de1
                        pre->g_pre_comp[i][2][2]);
Packit Service 084de1
        for (j = 1; j < 8; ++j) {
Packit Service 084de1
            /* odd multiples: add G resp. 2^32*G */
Packit Service 084de1
            point_add_small(pre->g_pre_comp[i][2 * j + 1][0],
Packit Service 084de1
                            pre->g_pre_comp[i][2 * j + 1][1],
Packit Service 084de1
                            pre->g_pre_comp[i][2 * j + 1][2],
Packit Service 084de1
                            pre->g_pre_comp[i][2 * j][0],
Packit Service 084de1
                            pre->g_pre_comp[i][2 * j][1],
Packit Service 084de1
                            pre->g_pre_comp[i][2 * j][2],
Packit Service 084de1
                            pre->g_pre_comp[i][1][0],
Packit Service 084de1
                            pre->g_pre_comp[i][1][1],
Packit Service 084de1
                            pre->g_pre_comp[i][1][2]);
Packit Service 084de1
        }
Packit Service 084de1
    }
Packit Service 084de1
    make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems);
Packit Service 084de1
Packit Service 084de1
 done:
Packit Service 084de1
    SETPRECOMP(group, nistp256, pre);
Packit Service 084de1
    pre = NULL;
Packit Service 084de1
    ret = 1;
Packit Service 084de1
Packit Service 084de1
 err:
Packit Service 084de1
    BN_CTX_end(ctx);
Packit Service 084de1
    EC_POINT_free(generator);
Packit Service 084de1
    BN_CTX_free(new_ctx);
Packit Service 084de1
    EC_nistp256_pre_comp_free(pre);
Packit Service 084de1
    return ret;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group)
Packit Service 084de1
{
Packit Service 084de1
    return HAVEPRECOMP(group, nistp256);
Packit Service 084de1
}
Packit Service 084de1
#endif