1f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
3f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// found in the LICENSE file.
4f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
5f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// This is an implementation of the P224 elliptic curve group. It's written to
6f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// be short and simple rather than fast, although it's still constant-time.
7f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
8f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
9f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
10f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/p224.h"
11f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
1224854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko#include <stddef.h>
1324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko#include <stdint.h>
14f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <string.h>
15f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
16f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "base/sys_byteorder.h"
17f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
18f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace {
19f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
20f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkousing base::HostToNet32;
21f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkousing base::NetToHost32;
22f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
23f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Field element functions.
24f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
25f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
26f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
27f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Field elements are represented by a FieldElement, which is a typedef to an
2824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko// array of 8 uint32_t's. The value of a FieldElement, a, is:
29f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//   a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
30f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
31f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Using 28-bit limbs means that there's only 4 bits of headroom, which is less
32f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// than we would really like. But it has the useful feature that we hit 2**224
33f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// exactly, making the reflections during a reduce much nicer.
34f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
35f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkousing crypto::p224::FieldElement;
36f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
37f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// kP is the P224 prime.
38f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkoconst FieldElement kP = {
39f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  1, 0, 0, 268431360,
40f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  268435455, 268435455, 268435455, 268435455,
41f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko};
42f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
43f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Contract(FieldElement* inout);
44f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
45f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise.
4624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkouint32_t IsZero(const FieldElement& a) {
47f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement minimal;
48f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  memcpy(&minimal, &a, sizeof(minimal));
49f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Contract(&minimal);
50f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
5124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t is_zero = 0, is_p = 0;
52f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (unsigned i = 0; i < 8; i++) {
53f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    is_zero |= minimal[i];
54f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    is_p |= minimal[i] - kP[i];
55f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
56f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
57f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // If either is_zero or is_p is 0, then we should return 1.
58f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero |= is_zero >> 16;
59f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero |= is_zero >> 8;
60f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero |= is_zero >> 4;
61f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero |= is_zero >> 2;
62f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero |= is_zero >> 1;
63f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
64f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_p |= is_p >> 16;
65f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_p |= is_p >> 8;
66f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_p |= is_p >> 4;
67f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_p |= is_p >> 2;
68f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_p |= is_p >> 1;
69f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
70f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // For is_zero and is_p, the LSB is 0 iff all the bits are zero.
71f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero &= is_p & 1;
72f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  is_zero = (~is_zero) << 31;
7324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  is_zero = static_cast<int32_t>(is_zero) >> 31;
74f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return is_zero;
75f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
76f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
77f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Add computes *out = a+b
78f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
79f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// a[i] + b[i] < 2**32
80f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Add(FieldElement* out, const FieldElement& a, const FieldElement& b) {
81f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
82f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    (*out)[i] = a[i] + b[i];
83f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
84f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
85f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
8624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint32_t kTwo31p3 = (1u << 31) + (1u << 3);
8724854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint32_t kTwo31m3 = (1u << 31) - (1u << 3);
8824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint32_t kTwo31m15m3 = (1u << 31) - (1u << 15) - (1u << 3);
89f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// kZero31ModP is 0 mod p where bit 31 is set in all limbs so that we can
90f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// subtract smaller amounts without underflow. See the section "Subtraction" in
91f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// [1] for why.
92f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkostatic const FieldElement kZero31ModP = {
93f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  kTwo31p3, kTwo31m3, kTwo31m3, kTwo31m15m3,
94f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  kTwo31m3, kTwo31m3, kTwo31m3, kTwo31m3
95f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko};
96f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
97f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Subtract computes *out = a-b
98f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
99f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// a[i], b[i] < 2**30
100f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// out[i] < 2**32
101f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Subtract(FieldElement* out, const FieldElement& a, const FieldElement& b) {
102f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
103f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // See the section on "Subtraction" in [1] for details.
104f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    (*out)[i] = a[i] + kZero31ModP[i] - b[i];
105f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
106f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
107f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
10824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint64_t kTwo63p35 = (1ull << 63) + (1ull << 35);
10924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint64_t kTwo63m35 = (1ull << 63) - (1ull << 35);
11024854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint64_t kTwo63m35m19 = (1ull << 63) - (1ull << 35) - (1ull << 19);
111f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// kZero63ModP is 0 mod p where bit 63 is set in all limbs. See the section
112f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// "Subtraction" in [1] for why.
11324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint64_t kZero63ModP[8] = {
11424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko    kTwo63p35,    kTwo63m35, kTwo63m35, kTwo63m35,
11524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko    kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35,
116f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko};
117f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
11824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkostatic const uint32_t kBottom28Bits = 0xfffffff;
119f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
120f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// LargeFieldElement also represents an element of the field. The limbs are
121f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// still spaced 28-bits apart and in little-endian order. So the limbs are at
122f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// 0, 28, 56, ..., 392 bits, each 64-bits wide.
12324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkotypedef uint64_t LargeFieldElement[15];
124f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
125f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// ReduceLarge converts a LargeFieldElement to a FieldElement.
126f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
127f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// in[i] < 2**62
128f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid ReduceLarge(FieldElement* out, LargeFieldElement* inptr) {
129f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  LargeFieldElement& in(*inptr);
130f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
131f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
132f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    in[i] += kZero63ModP[i];
133f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
134f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
135f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Eliminate the coefficients at 2**224 and greater while maintaining the
136f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // same value mod p.
137f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 14; i >= 8; i--) {
138f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    in[i-8] -= in[i];  // reflection off the "+1" term of p.
139f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    in[i-5] += (in[i] & 0xffff) << 12;  // part of the "-2**96" reflection.
140f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    in[i-4] += in[i] >> 16;  // the rest of the "-2**96" reflection.
141f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
142f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  in[8] = 0;
143f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // in[0..8] < 2**64
144f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
145f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // As the values become small enough, we start to store them in |out| and use
146f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // 32-bit operations.
147f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 1; i < 8; i++) {
148f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    in[i+1] += in[i] >> 28;
14924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko    (*out)[i] = static_cast<uint32_t>(in[i] & kBottom28Bits);
150f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
151f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Eliminate the term at 2*224 that we introduced while keeping the same
152f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // value mod p.
153f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  in[0] -= in[8];  // reflection off the "+1" term of p.
15424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  (*out)[3] += static_cast<uint32_t>(in[8] & 0xffff) << 12;  // "-2**96" term
15524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  (*out)[4] += static_cast<uint32_t>(in[8] >> 16);  // rest of "-2**96" term
156f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // in[0] < 2**64
157f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[3] < 2**29
158f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[4] < 2**29
159f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[1,2,5..7] < 2**28
160f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
16124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  (*out)[0] = static_cast<uint32_t>(in[0] & kBottom28Bits);
16224854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  (*out)[1] += static_cast<uint32_t>((in[0] >> 28) & kBottom28Bits);
16324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  (*out)[2] += static_cast<uint32_t>(in[0] >> 56);
164f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[0] < 2**28
165f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[1..4] < 2**29
166f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[5..7] < 2**28
167f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
168f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
169f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Mul computes *out = a*b
170f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
171f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// a[i] < 2**29, b[i] < 2**30 (or vice versa)
172f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// out[i] < 2**29
173f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Mul(FieldElement* out, const FieldElement& a, const FieldElement& b) {
174f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  LargeFieldElement tmp;
175f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  memset(&tmp, 0, sizeof(tmp));
176f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
177f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
178f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    for (int j = 0; j < 8; j++) {
17924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      tmp[i + j] += static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(b[j]);
180f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
181f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
182f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
183f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  ReduceLarge(out, &tmp);
184f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
185f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
186f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Square computes *out = a*a
187f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
188f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// a[i] < 2**29
189f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// out[i] < 2**29
190f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Square(FieldElement* out, const FieldElement& a) {
191f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  LargeFieldElement tmp;
192f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  memset(&tmp, 0, sizeof(tmp));
193f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
194f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
195f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    for (int j = 0; j <= i; j++) {
19624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      uint64_t r = static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(a[j]);
197f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      if (i == j) {
198f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko        tmp[i+j] += r;
199f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      } else {
200f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko        tmp[i+j] += r << 1;
201f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      }
202f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
203f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
204f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
205f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  ReduceLarge(out, &tmp);
206f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
207f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
208f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Reduce reduces the coefficients of in_out to smaller bounds.
209f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
210f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// On entry: a[i] < 2**31 + 2**30
211f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// On exit: a[i] < 2**29
212f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Reduce(FieldElement* in_out) {
213f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement& a = *in_out;
214f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
215f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 7; i++) {
216f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    a[i+1] += a[i] >> 28;
217f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    a[i] &= kBottom28Bits;
218f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
21924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t top = a[7] >> 28;
220f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[7] &= kBottom28Bits;
221f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
222f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // top < 2**4
223f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Constant-time: mask = (top != 0) ? 0xffffffff : 0
22424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t mask = top;
225f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  mask |= mask >> 2;
226f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  mask |= mask >> 1;
227f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  mask <<= 31;
22824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  mask = static_cast<uint32_t>(static_cast<int32_t>(mask) >> 31);
229f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
230f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Eliminate top while maintaining the same value mod p.
231f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[0] -= top;
232f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[3] += top << 12;
233f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
234f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // We may have just made a[0] negative but, if we did, then we must
235f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // have added something to a[3], thus it's > 2**12. Therefore we can
236f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // carry down to a[0].
237f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[3] -= 1 & mask;
238f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[2] += mask & ((1<<28) - 1);
239f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[1] += mask & ((1<<28) - 1);
240f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  a[0] += mask & (1<<28);
241f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
242f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
243f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Invert calcuates *out = in**-1 by computing in**(2**224 - 2**96 - 1), i.e.
244f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Fermat's little theorem.
245f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Invert(FieldElement* out, const FieldElement& in) {
246f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement f1, f2, f3, f4;
247f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
248f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f1, in);                        // 2
249f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f1, f1, in);                       // 2**2 - 1
250f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f1, f1);                        // 2**3 - 2
251f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f1, f1, in);                       // 2**3 - 1
252f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f2, f1);                        // 2**4 - 2
253f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f2, f2);                        // 2**5 - 4
254f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f2, f2);                        // 2**6 - 8
255f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f1, f1, f2);                       // 2**6 - 1
256f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f2, f1);                        // 2**7 - 2
257f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 5; i++) {           // 2**12 - 2**6
258f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f2, f2);
259f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
260f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f2, f2, f1);                       // 2**12 - 1
261f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f3, f2);                        // 2**13 - 2
262f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 11; i++) {          // 2**24 - 2**12
263f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f3, f3);
264f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
265f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f2, f3, f2);                       // 2**24 - 1
266f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f3, f2);                        // 2**25 - 2
267f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 23; i++) {          // 2**48 - 2**24
268f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f3, f3);
269f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
270f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f3, f3, f2);                       // 2**48 - 1
271f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f4, f3);                        // 2**49 - 2
272f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 47; i++) {          // 2**96 - 2**48
273f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f4, f4);
274f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
275f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f3, f3, f4);                       // 2**96 - 1
276f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f4, f3);                        // 2**97 - 2
277f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 23; i++) {          // 2**120 - 2**24
278f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f4, f4);
279f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
280f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f2, f4, f2);                       // 2**120 - 1
281f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 6; i++) {           // 2**126 - 2**6
282f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f2, f2);
283f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
284f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f1, f1, f2);                       // 2**126 - 1
285f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&f1, f1);                        // 2**127 - 2
286f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&f1, f1, in);                       // 2**127 - 1
287f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 97; i++) {          // 2**224 - 2**97
288f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    Square(&f1, f1);
289f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
290f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(out, f1, f3);                       // 2**224 - 2**96 - 1
291f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
292f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
293f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Contract converts a FieldElement to its minimal, distinguished form.
294f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
295f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// On entry, in[i] < 2**29
296f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// On exit, in[i] < 2**28
297f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Contract(FieldElement* inout) {
298f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement& out = *inout;
299f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
300f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Reduce the coefficients to < 2**28.
301f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 7; i++) {
302f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i+1] += out[i] >> 28;
303f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i] &= kBottom28Bits;
304f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
30524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t top = out[7] >> 28;
306f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[7] &= kBottom28Bits;
307f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
308f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Eliminate top while maintaining the same value mod p.
309f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[0] -= top;
310f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[3] += top << 12;
311f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
312f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // We may just have made out[0] negative. So we carry down. If we made
313f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // out[0] negative then we know that out[3] is sufficiently positive
314f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // because we just added to it.
315f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 3; i++) {
31624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko    uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31);
317f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i] += (1 << 28) & mask;
318f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i+1] -= 1 & mask;
319f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
320f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
321f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // We might have pushed out[3] over 2**28 so we perform another, partial
322f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // carry chain.
323f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 3; i < 7; i++) {
324f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i+1] += out[i] >> 28;
325f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i] &= kBottom28Bits;
326f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
327f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top = out[7] >> 28;
328f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[7] &= kBottom28Bits;
329f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
330f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Eliminate top while maintaining the same value mod p.
331f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[0] -= top;
332f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[3] += top << 12;
333f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
334f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // There are two cases to consider for out[3]:
335f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //   1) The first time that we eliminated top, we didn't push out[3] over
336f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      2**28. In this case, the partial carry chain didn't change any values
337f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      and top is zero.
338f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //   2) We did push out[3] over 2**28 the first time that we eliminated top.
339f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      The first value of top was in [0..16), therefore, prior to eliminating
340f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after
341f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      overflowing and being reduced by the second carry chain, out[3] <=
342f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      0xf000. Thus it cannot have overflowed when we eliminated top for the
343f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      second time.
344f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
345f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Again, we may just have made out[0] negative, so do the same carry down.
346f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // As before, if we made out[0] negative then we know that out[3] is
347f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // sufficiently positive.
348f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 3; i++) {
34924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko    uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31);
350f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i] += (1 << 28) & mask;
351f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out[i+1] -= 1 & mask;
352f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
353f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
354f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // The value is < 2**224, but maybe greater than p. In order to reduce to a
355f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // unique, minimal value we see if the value is >= p and, if so, subtract p.
356f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
357f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // First we build a mask from the top four limbs, which must all be
358f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones
359f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // ends up with any zero bits in the bottom 28 bits, then this wasn't
360f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // true.
36124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t top_4_all_ones = 0xffffffffu;
362f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 4; i < 8; i++) {
363f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    top_4_all_ones &= out[i];
364f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
365f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones |= 0xf0000000;
366f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Now we replicate any zero bits to all the bits in top_4_all_ones.
367f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones &= top_4_all_ones >> 16;
368f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones &= top_4_all_ones >> 8;
369f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones &= top_4_all_ones >> 4;
370f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones &= top_4_all_ones >> 2;
371f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones &= top_4_all_ones >> 1;
372f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  top_4_all_ones =
37324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      static_cast<uint32_t>(static_cast<int32_t>(top_4_all_ones << 31) >> 31);
374f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
375f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Now we test whether the bottom three limbs are non-zero.
37624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t bottom_3_non_zero = out[0] | out[1] | out[2];
377f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bottom_3_non_zero |= bottom_3_non_zero >> 16;
378f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bottom_3_non_zero |= bottom_3_non_zero >> 8;
379f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bottom_3_non_zero |= bottom_3_non_zero >> 4;
380f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bottom_3_non_zero |= bottom_3_non_zero >> 2;
381f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bottom_3_non_zero |= bottom_3_non_zero >> 1;
382f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bottom_3_non_zero =
38324854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      static_cast<uint32_t>(static_cast<int32_t>(bottom_3_non_zero) >> 31);
384f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
385f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Everything depends on the value of out[3].
386f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //    If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p
387f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //    If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0,
388f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //      then the whole value is >= p
389f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  //    If it's < 0xffff000, then the whole value is < p
39024854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t n = out[3] - 0xffff000;
39124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t out_3_equal = n;
392f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out_3_equal |= out_3_equal >> 16;
393f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out_3_equal |= out_3_equal >> 8;
394f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out_3_equal |= out_3_equal >> 4;
395f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out_3_equal |= out_3_equal >> 2;
396f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out_3_equal |= out_3_equal >> 1;
397f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out_3_equal =
39824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      ~static_cast<uint32_t>(static_cast<int32_t>(out_3_equal << 31) >> 31);
399f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
400f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // If out[3] > 0xffff000 then n's MSB will be zero.
40124854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t out_3_gt =
40224854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      ~static_cast<uint32_t>(static_cast<int32_t>(n << 31) >> 31);
403f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
40424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t mask =
40524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt);
406f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[0] -= 1 & mask;
407f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[3] -= 0xffff000 & mask;
408f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[4] -= 0xfffffff & mask;
409f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[5] -= 0xfffffff & mask;
410f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[6] -= 0xfffffff & mask;
411f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[7] -= 0xfffffff & mask;
412f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
413f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
414f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
415f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Group element functions.
416f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko//
417f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// These functions deal with group elements. The group is an elliptic curve
418f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// group with a = -3 defined in FIPS 186-3, section D.2.2.
419f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
420f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkousing crypto::p224::Point;
421f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
422f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// kB is parameter of the elliptic curve.
423f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkoconst FieldElement kB = {
424f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  55967668, 11768882, 265861671, 185302395,
425f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  39211076, 180311059, 84673715, 188764328,
426f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko};
427f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
42824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid CopyConditional(Point* out, const Point& a, uint32_t mask);
429f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid DoubleJacobian(Point* out, const Point& a);
430f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
431f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// AddJacobian computes *out = a+b where a != b.
432f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid AddJacobian(Point *out,
433f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko                 const Point& a,
434f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko                 const Point& b) {
435f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
436f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v;
437f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
43824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t z1_is_zero = IsZero(a.z);
43924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t z2_is_zero = IsZero(b.z);
440f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
441f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Z1Z1 = Z1²
442f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&z1z1, a.z);
443f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
444f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Z2Z2 = Z2²
445f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&z2z2, b.z);
446f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
447f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // U1 = X1*Z2Z2
448f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&u1, a.x, z2z2);
449f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
450f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // U2 = X2*Z1Z1
451f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&u2, b.x, z1z1);
452f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
453f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // S1 = Y1*Z2*Z2Z2
454f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&s1, b.z, z2z2);
455f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&s1, a.y, s1);
456f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
457f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // S2 = Y2*Z1*Z1Z1
458f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&s2, a.z, z1z1);
459f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&s2, b.y, s2);
460f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
461f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // H = U2-U1
462f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&h, u2, u1);
463f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&h);
46424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t x_equal = IsZero(h);
465f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
466f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // I = (2*H)²
467f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int k = 0; k < 8; k++) {
468f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    i[k] = h[k] << 1;
469f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
470f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&i);
471f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&i, i);
472f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
473f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // J = H*I
474f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&j, h, i);
475f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // r = 2*(S2-S1)
476f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&r, s2, s1);
477f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&r);
47824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t y_equal = IsZero(r);
479f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
480f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
481f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // The two input points are the same therefore we must use the dedicated
482f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // doubling function as the slope of the line is undefined.
483f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    DoubleJacobian(out, a);
484f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return;
485f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
486f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
487f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int k = 0; k < 8; k++) {
488f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    r[k] <<= 1;
489f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
490f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&r);
491f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
492f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // V = U1*I
493f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&v, u1, i);
494f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
495f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
496f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Add(&z1z1, z1z1, z2z2);
497f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Add(&z2z2, a.z, b.z);
498f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&z2z2);
499f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&z2z2, z2z2);
500f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->z, z2z2, z1z1);
501f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->z);
502f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&out->z, out->z, h);
503f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
504f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // X3 = r²-J-2*V
505f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int k = 0; k < 8; k++) {
506f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    z1z1[k] = v[k] << 1;
507f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
508f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Add(&z1z1, j, z1z1);
509f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&z1z1);
510f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&out->x, r);
511f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->x, out->x, z1z1);
512f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->x);
513f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
514f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Y3 = r*(V-X3)-2*S1*J
515f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int k = 0; k < 8; k++) {
516f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    s1[k] <<= 1;
517f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
518f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&s1, s1, j);
519f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&z1z1, v, out->x);
520f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&z1z1);
521f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&z1z1, z1z1, r);
522f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->y, z1z1, s1);
523f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->y);
524f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
525f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  CopyConditional(out, a, z2_is_zero);
526f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  CopyConditional(out, b, z1_is_zero);
527f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
528f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
529f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// DoubleJacobian computes *out = a+a.
530f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid DoubleJacobian(Point* out, const Point& a) {
531f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
532f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement delta, gamma, beta, alpha, t;
533f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
534f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&delta, a.z);
535f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&gamma, a.y);
536f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&beta, a.x, gamma);
537f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
538f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // alpha = 3*(X1-delta)*(X1+delta)
539f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Add(&t, a.x, delta);
540f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
541f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko          t[i] += t[i] << 1;
542f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
543f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&t);
544f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&alpha, a.x, delta);
545f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&alpha);
546f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&alpha, alpha, t);
547f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
548f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Z3 = (Y1+Z1)²-gamma-delta
549f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Add(&out->z, a.y, a.z);
550f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->z);
551f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&out->z, out->z);
552f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->z, out->z, gamma);
553f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->z);
554f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->z, out->z, delta);
555f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->z);
556f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
557f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // X3 = alpha²-8*beta
558f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
559f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko          delta[i] = beta[i] << 3;
560f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
561f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&delta);
562f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&out->x, alpha);
563f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->x, out->x, delta);
564f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->x);
565f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
566f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Y3 = alpha*(4*beta-X3)-8*gamma²
567f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
568f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko          beta[i] <<= 2;
569f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
570f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&beta);
571f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&beta, beta, out->x);
572f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&beta);
573f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&gamma, gamma);
574f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
575f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko          gamma[i] <<= 3;
576f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
577f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&gamma);
578f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&out->y, alpha, beta);
579f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->y, out->y, gamma);
580f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->y);
581f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
582f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
583f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// CopyConditional sets *out=a if mask is 0xffffffff. mask must be either 0 of
584f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// 0xffffffff.
58524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid CopyConditional(Point* out, const Point& a, uint32_t mask) {
586f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
587f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out->x[i] ^= mask & (a.x[i] ^ out->x[i]);
588f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out->y[i] ^= mask & (a.y[i] ^ out->y[i]);
589f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    out->z[i] ^= mask & (a.z[i] ^ out->z[i]);
590f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
591f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
592f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
593f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// ScalarMult calculates *out = a*scalar where scalar is a big-endian number of
594f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// length scalar_len and != 0.
59524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid ScalarMult(Point* out,
59624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko                const Point& a,
59724854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko                const uint8_t* scalar,
59824854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko                size_t scalar_len) {
599f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  memset(out, 0, sizeof(*out));
600f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Point tmp;
601f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
602f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (size_t i = 0; i < scalar_len; i++) {
603f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    for (unsigned int bit_num = 0; bit_num < 8; bit_num++) {
604f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      DoubleJacobian(out, *out);
60524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko      uint32_t bit = static_cast<uint32_t>(static_cast<int32_t>(
606f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko          (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31));
607f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      AddJacobian(&tmp, a, *out);
608f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      CopyConditional(out, tmp, bit);
609f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    }
610f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
611f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
612f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
613f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Get224Bits reads 7 words from in and scatters their contents in
614f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// little-endian form into 8 words at out, 28 bits per output word.
61524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid Get224Bits(uint32_t* out, const uint32_t* in) {
616f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[0] = NetToHost32(in[6]) & kBottom28Bits;
617f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[1] = ((NetToHost32(in[5]) << 4) |
618f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko            (NetToHost32(in[6]) >> 28)) & kBottom28Bits;
619f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[2] = ((NetToHost32(in[4]) << 8) |
620f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko            (NetToHost32(in[5]) >> 24)) & kBottom28Bits;
621f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[3] = ((NetToHost32(in[3]) << 12) |
622f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko            (NetToHost32(in[4]) >> 20)) & kBottom28Bits;
623f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[4] = ((NetToHost32(in[2]) << 16) |
624f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko            (NetToHost32(in[3]) >> 16)) & kBottom28Bits;
625f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[5] = ((NetToHost32(in[1]) << 20) |
626f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko            (NetToHost32(in[2]) >> 12)) & kBottom28Bits;
627f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[6] = ((NetToHost32(in[0]) << 24) |
628f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko            (NetToHost32(in[1]) >> 8)) & kBottom28Bits;
629f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[7] = (NetToHost32(in[0]) >> 4) & kBottom28Bits;
630f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
631f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
632f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from
633f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// each of 8 input words and writing them in big-endian order to 7 words at
634f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// out.
63524854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid Put224Bits(uint32_t* out, const uint32_t* in) {
636f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28));
637f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24));
638f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20));
639f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[3] = HostToNet32((in[3] >> 12) | (in[4] << 16));
640f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[2] = HostToNet32((in[4] >> 16) | (in[5] << 12));
641f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[1] = HostToNet32((in[5] >> 20) | (in[6] << 8));
642f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4));
643f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
644f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
645f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // anonymous namespace
646f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
647f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace crypto {
648f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
649f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace p224 {
650f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
651f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkobool Point::SetFromString(const base::StringPiece& in) {
652f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (in.size() != 2*28)
653f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return false;
65424854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  const uint32_t* inwords = reinterpret_cast<const uint32_t*>(in.data());
655f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Get224Bits(x, inwords);
656f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Get224Bits(y, inwords + 7);
657f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  memset(&z, 0, sizeof(z));
658f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  z[0] = 1;
659f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
660f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Check that the point is on the curve, i.e. that y² = x³ - 3x + b.
661f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement lhs;
662f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&lhs, y);
663f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Contract(&lhs);
664f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
665f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement rhs;
666f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&rhs, x);
667f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&rhs, x, rhs);
668f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
669f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement three_x;
670f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  for (int i = 0; i < 8; i++) {
671f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    three_x[i] = x[i] * 3;
672f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
673f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&three_x);
674f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&rhs, rhs, three_x);
675f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&rhs);
676f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
677f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  ::Add(&rhs, rhs, kB);
678f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Contract(&rhs);
679f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
680f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
681f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
682f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkostd::string Point::ToString() const {
683f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement zinv, zinv_sq, xx, yy;
684f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
685f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // If this is the point at infinity we return a string of all zeros.
686f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (IsZero(this->z)) {
687f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    static const char zeros[56] = {0};
688f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return std::string(zeros, sizeof(zeros));
689f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
690f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
691f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Invert(&zinv, this->z);
692f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&zinv_sq, zinv);
693f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&xx, x, zinv_sq);
694f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&zinv_sq, zinv_sq, zinv);
695f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&yy, y, zinv_sq);
696f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
697f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Contract(&xx);
698f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Contract(&yy);
699f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
70024854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenko  uint32_t outwords[14];
701f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Put224Bits(outwords, xx);
702f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Put224Bits(outwords + 7, yy);
703f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return std::string(reinterpret_cast<const char*>(outwords), sizeof(outwords));
704f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
705f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
70624854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid ScalarMult(const Point& in, const uint8_t* scalar, Point* out) {
707f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  ::ScalarMult(out, in, scalar, 28);
708f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
709f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
710f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// kBasePoint is the base point (generator) of the elliptic curve group.
711f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkostatic const Point kBasePoint = {
712f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  {22813985, 52956513, 34677300, 203240812,
713f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko   12143107, 133374265, 225162431, 191946955},
714f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  {83918388, 223877528, 122119236, 123340192,
715f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko   266784067, 263504429, 146143011, 198407736},
716f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  {1, 0, 0, 0, 0, 0, 0, 0},
717f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko};
718f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
71924854748fba09df2a29f0d08d558c3acea70e7a1Alex Vakulenkovoid ScalarBaseMult(const uint8_t* scalar, Point* out) {
720f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  ::ScalarMult(out, kBasePoint, scalar, 28);
721f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
722f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
723f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Add(const Point& a, const Point& b, Point* out) {
724f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  AddJacobian(out, a, b);
725f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
726f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
727f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkovoid Negate(const Point& in, Point* out) {
728f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Guide to elliptic curve cryptography, page 89 suggests that (X : X+Y : Z)
729f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // is the negative in Jacobian coordinates, but it doesn't actually appear to
730f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // be true in testing so this performs the negation in affine coordinates.
731f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  FieldElement zinv, zinv_sq, y;
732f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Invert(&zinv, in.z);
733f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Square(&zinv_sq, zinv);
734f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&out->x, in.x, zinv_sq);
735f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&zinv_sq, zinv_sq, zinv);
736f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Mul(&y, in.y, zinv_sq);
737f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
738f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Subtract(&out->y, kP, y);
739f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  Reduce(&out->y);
740f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
741f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  memset(&out->z, 0, sizeof(out->z));
742f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  out->z[0] = 1;
743f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
744f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
745f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // namespace p224
746f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
747f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // namespace crypto
748