1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com).
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL.
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to.  The following conditions
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA,
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed.
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used.
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package.
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in the
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    documentation and/or other materials provided with the distribution.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    must display the following acknowledgement:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes cryptographic software written by
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *     Eric Young (eay@cryptsoft.com)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    The word 'cryptographic' can be left out if the rouines from the library
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    being used are not cryptographic related :-).
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the apps directory (application code) you must include an acknowledgement:
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE.
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h>
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <assert.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h"
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin/* This file has two other implementations: x86 assembly language in
654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin * asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if defined(OPENSSL_NO_ASM) || \
674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
694139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#ifdef BN_ULLONG
7095add82835138f09cf7bb4a51c04c6320c241674David Benjamin#define mul_add(r, a, w, c)               \
7195add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                                    \
7295add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULLONG t;                          \
7395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    t = (BN_ULLONG)(w) * (a) + (r) + (c); \
7495add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (r) = Lw(t);                          \
7595add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c) = Hw(t);                          \
7695add82835138f09cf7bb4a51c04c6320c241674David Benjamin  } while (0)
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
7895add82835138f09cf7bb4a51c04c6320c241674David Benjamin#define mul(r, a, w, c)             \
7995add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                              \
8095add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULLONG t;                    \
8195add82835138f09cf7bb4a51c04c6320c241674David Benjamin    t = (BN_ULLONG)(w) * (a) + (c); \
8295add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (r) = Lw(t);                    \
8395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c) = Hw(t);                    \
8495add82835138f09cf7bb4a51c04c6320c241674David Benjamin  } while (0)
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define sqr(r0, r1, a)        \
8795add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                        \
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULLONG t;              \
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = (BN_ULLONG)(a) * (a); \
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (r0) = Lw(t);             \
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (r1) = Hw(t);             \
9295add82835138f09cf7bb4a51c04c6320c241674David Benjamin  } while (0)
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
944969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin#else
954969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define mul_add(r, a, w, c)             \
9795add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                                  \
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG high, low, ret, tmp = (a); \
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ret = (r);                          \
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_UMULT_LOHI(low, high, w, tmp);   \
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ret += (c);                         \
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (c) = (ret < (c)) ? 1 : 0;          \
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (c) += high;                        \
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ret += low;                         \
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (c) += (ret < low) ? 1 : 0;         \
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (r) = ret;                          \
10795add82835138f09cf7bb4a51c04c6320c241674David Benjamin  } while (0)
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define mul(r, a, w, c)                \
11095add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                                 \
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG high, low, ret, ta = (a); \
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_UMULT_LOHI(low, high, w, ta);   \
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ret = low + (c);                   \
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (c) = high;                        \
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (c) += (ret < low) ? 1 : 0;        \
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    (r) = ret;                         \
11795add82835138f09cf7bb4a51c04c6320c241674David Benjamin  } while (0)
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define sqr(r0, r1, a)               \
12095add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                               \
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG tmp = (a);              \
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_UMULT_LOHI(r0, r1, tmp, tmp); \
12395add82835138f09cf7bb4a51c04c6320c241674David Benjamin  } while (0)
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1254139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#endif /* !BN_ULLONG */
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
127d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                          BN_ULONG w) {
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c1 = 0;
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  assert(num >= 0);
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (num <= 0) {
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return c1;
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (num & ~3) {
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul_add(rp[0], ap[0], w, c1);
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul_add(rp[1], ap[1], w, c1);
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul_add(rp[2], ap[2], w, c1);
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul_add(rp[3], ap[3], w, c1);
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ap += 4;
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rp += 4;
143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    num -= 4;
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (num) {
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul_add(rp[0], ap[0], w, c1);
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ap++;
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rp++;
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    num--;
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return c1;
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
156d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c1 = 0;
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  assert(num >= 0);
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (num <= 0) {
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return c1;
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (num & ~3) {
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul(rp[0], ap[0], w, c1);
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul(rp[1], ap[1], w, c1);
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul(rp[2], ap[2], w, c1);
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul(rp[3], ap[3], w, c1);
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ap += 4;
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rp += 4;
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    num -= 4;
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (num) {
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    mul(rp[0], ap[0], w, c1);
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ap++;
176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    rp++;
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    num--;
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return c1;
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  assert(n >= 0);
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (n <= 0) {
185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n & ~3) {
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    sqr(r[0], r[1], a[0]);
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    sqr(r[2], r[3], a[1]);
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    sqr(r[4], r[5], a[2]);
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    sqr(r[6], r[7], a[3]);
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a += 4;
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r += 8;
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n -= 4;
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n) {
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    sqr(r[0], r[1], a[0]);
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a++;
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r += 2;
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n--;
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2054139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#ifdef BN_ULLONG
206d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                      int n) {
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULLONG ll = 0;
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  assert(n >= 0);
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (n <= 0) {
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return (BN_ULONG)0;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n & ~3) {
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll += (BN_ULLONG)a[0] + b[0];
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[0] = (BN_ULONG)ll & BN_MASK2;
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll >>= BN_BITS2;
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll += (BN_ULLONG)a[1] + b[1];
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[1] = (BN_ULONG)ll & BN_MASK2;
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll >>= BN_BITS2;
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll += (BN_ULLONG)a[2] + b[2];
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[2] = (BN_ULONG)ll & BN_MASK2;
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll >>= BN_BITS2;
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll += (BN_ULLONG)a[3] + b[3];
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[3] = (BN_ULONG)ll & BN_MASK2;
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll >>= BN_BITS2;
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a += 4;
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    b += 4;
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r += 4;
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n -= 4;
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n) {
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll += (BN_ULLONG)a[0] + b[0];
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[0] = (BN_ULONG)ll & BN_MASK2;
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ll >>= BN_BITS2;
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a++;
238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    b++;
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r++;
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n--;
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return (BN_ULONG)ll;
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
2454139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#else /* !BN_ULLONG */
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
247d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                      int n) {
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c, l, t;
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  assert(n >= 0);
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (n <= 0) {
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return (BN_ULONG)0;
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c = 0;
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n & ~3) {
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = a[0];
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = (t + c) & BN_MASK2;
260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c = (t < c);
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    l = (t + b[0]) & BN_MASK2;
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c += (l < t);
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[0] = l;
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = a[1];
265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = (t + c) & BN_MASK2;
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c = (t < c);
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    l = (t + b[1]) & BN_MASK2;
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c += (l < t);
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[1] = l;
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = a[2];
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = (t + c) & BN_MASK2;
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c = (t < c);
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    l = (t + b[2]) & BN_MASK2;
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c += (l < t);
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[2] = l;
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = a[3];
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = (t + c) & BN_MASK2;
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c = (t < c);
279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    l = (t + b[3]) & BN_MASK2;
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c += (l < t);
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[3] = l;
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a += 4;
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    b += 4;
284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r += 4;
285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n -= 4;
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n) {
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = a[0];
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t = (t + c) & BN_MASK2;
290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c = (t < c);
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    l = (t + b[0]) & BN_MASK2;
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    c += (l < t);
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[0] = l;
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a++;
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    b++;
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r++;
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n--;
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return (BN_ULONG)c;
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3024139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#endif /* !BN_ULLONG */
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
304d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                      int n) {
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG t1, t2;
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int c = 0;
308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  assert(n >= 0);
310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (n <= 0) {
311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return (BN_ULONG)0;
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n & ~3) {
315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t1 = a[0];
316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t2 = b[0];
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[0] = (t1 - t2 - c) & BN_MASK2;
318e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (t1 != t2) {
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      c = (t1 < t2);
320e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t1 = a[1];
322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t2 = b[1];
323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[1] = (t1 - t2 - c) & BN_MASK2;
324e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (t1 != t2) {
325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      c = (t1 < t2);
326e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t1 = a[2];
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t2 = b[2];
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[2] = (t1 - t2 - c) & BN_MASK2;
330e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (t1 != t2) {
331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      c = (t1 < t2);
332e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t1 = a[3];
334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t2 = b[3];
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[3] = (t1 - t2 - c) & BN_MASK2;
336e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (t1 != t2) {
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      c = (t1 < t2);
338e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a += 4;
340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    b += 4;
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r += 4;
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n -= 4;
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  while (n) {
345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t1 = a[0];
346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    t2 = b[0];
347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r[0] = (t1 - t2 - c) & BN_MASK2;
348e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (t1 != t2) {
349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      c = (t1 < t2);
350e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a++;
352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    b++;
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    r++;
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    n--;
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return c;
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* mul_add_c(a,b,c0,c1,c2)  -- c+=a*b for three word number c=(c2,c1,c0) */
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* sqr_add_c(a,i,c0,c1,c2)  -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */
363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3644139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#ifdef BN_ULLONG
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Keep in mind that additions to multiplication result can not overflow,
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * because its high half cannot be all-ones. */
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define mul_add_c(a, b, c0, c1, c2)     \
369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  do {                                  \
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG hi;                        \
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULLONG t = (BN_ULLONG)(a) * (b); \
37295add82835138f09cf7bb4a51c04c6320c241674David Benjamin    t += (c0); /* no carry */           \
37395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) = (BN_ULONG)Lw(t);             \
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    hi = (BN_ULONG)Hw(t);               \
37595add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) = ((c1) + (hi)) & BN_MASK2;    \
37695add82835138f09cf7bb4a51c04c6320c241674David Benjamin    if ((c1) < hi) {                    \
37795add82835138f09cf7bb4a51c04c6320c241674David Benjamin      (c2)++;                           \
37895add82835138f09cf7bb4a51c04c6320c241674David Benjamin    }                                   \
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (0)
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
38195add82835138f09cf7bb4a51c04c6320c241674David Benjamin#define mul_add_c2(a, b, c0, c1, c2)        \
38295add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                                      \
38395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULONG hi;                            \
38495add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULLONG t = (BN_ULLONG)(a) * (b);     \
38595add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULLONG tt = t + (c0); /* no carry */ \
38695add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) = (BN_ULONG)Lw(tt);                \
38795add82835138f09cf7bb4a51c04c6320c241674David Benjamin    hi = (BN_ULONG)Hw(tt);                  \
38895add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) = ((c1) + hi) & BN_MASK2;          \
38995add82835138f09cf7bb4a51c04c6320c241674David Benjamin    if ((c1) < hi) {                        \
39095add82835138f09cf7bb4a51c04c6320c241674David Benjamin      (c2)++;                               \
39195add82835138f09cf7bb4a51c04c6320c241674David Benjamin    }                                       \
39295add82835138f09cf7bb4a51c04c6320c241674David Benjamin    t += (c0); /* no carry */               \
39395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) = (BN_ULONG)Lw(t);                 \
39495add82835138f09cf7bb4a51c04c6320c241674David Benjamin    hi = (BN_ULONG)Hw(t);                   \
39595add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) = ((c1) + hi) & BN_MASK2;          \
39695add82835138f09cf7bb4a51c04c6320c241674David Benjamin    if ((c1) < hi) {                        \
39795add82835138f09cf7bb4a51c04c6320c241674David Benjamin      (c2)++;                               \
39895add82835138f09cf7bb4a51c04c6320c241674David Benjamin    }                                       \
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (0)
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
40195add82835138f09cf7bb4a51c04c6320c241674David Benjamin#define sqr_add_c(a, i, c0, c1, c2)           \
40295add82835138f09cf7bb4a51c04c6320c241674David Benjamin  do {                                        \
40395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULONG hi;                              \
40495add82835138f09cf7bb4a51c04c6320c241674David Benjamin    BN_ULLONG t = (BN_ULLONG)(a)[i] * (a)[i]; \
40595add82835138f09cf7bb4a51c04c6320c241674David Benjamin    t += (c0); /* no carry */                 \
40695add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) = (BN_ULONG)Lw(t);                   \
40795add82835138f09cf7bb4a51c04c6320c241674David Benjamin    hi = (BN_ULONG)Hw(t);                     \
40895add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) = ((c1) + hi) & BN_MASK2;            \
40995add82835138f09cf7bb4a51c04c6320c241674David Benjamin    if ((c1) < hi) {                          \
41095add82835138f09cf7bb4a51c04c6320c241674David Benjamin      (c2)++;                                 \
41195add82835138f09cf7bb4a51c04c6320c241674David Benjamin    }                                         \
412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (0)
413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin#else
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Keep in mind that additions to hi can not overflow, because the high word of
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * a multiplication result cannot be all-ones. */
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define mul_add_c(a, b, c0, c1, c2) \
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  do {                              \
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG ta = (a), tb = (b);    \
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG lo, hi;                \
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_UMULT_LOHI(lo, hi, ta, tb);  \
42595add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) += lo;                     \
42695add82835138f09cf7bb4a51c04c6320c241674David Benjamin    hi += ((c0) < lo) ? 1 : 0;      \
42795add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) += hi;                     \
42895add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c2) += ((c1) < hi) ? 1 : 0;    \
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (0)
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define mul_add_c2(a, b, c0, c1, c2) \
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  do {                               \
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG ta = (a), tb = (b);     \
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG lo, hi, tt;             \
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_UMULT_LOHI(lo, hi, ta, tb);   \
43695add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) += lo;                      \
43795add82835138f09cf7bb4a51c04c6320c241674David Benjamin    tt = hi + (((c0) < lo) ? 1 : 0); \
43895add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) += tt;                      \
43995add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c2) += ((c1) < tt) ? 1 : 0;     \
44095add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) += lo;                      \
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    hi += (c0 < lo) ? 1 : 0;         \
44295add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) += hi;                      \
44395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c2) += ((c1) < hi) ? 1 : 0;     \
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (0)
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define sqr_add_c(a, i, c0, c1, c2) \
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  do {                              \
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG ta = (a)[i];           \
449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_ULONG lo, hi;                \
450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_UMULT_LOHI(lo, hi, ta, ta);  \
45195add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c0) += lo;                     \
452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    hi += (c0 < lo) ? 1 : 0;        \
45395add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c1) += hi;                     \
45495add82835138f09cf7bb4a51c04c6320c241674David Benjamin    (c2) += ((c1) < hi) ? 1 : 0;    \
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (0)
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4594139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#endif /* !BN_ULLONG */
460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
461d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c1, c2, c3;
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[0], c1, c2, c3);
468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[0] = c1;
469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[1], c2, c3, c1);
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[0], c2, c3, c1);
472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[1] = c2;
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
474d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[0], c3, c1, c2);
475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[1], c3, c1, c2);
476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[2], c3, c1, c2);
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[2] = c3;
478d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
479d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[3], c1, c2, c3);
480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[2], c1, c2, c3);
481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[1], c1, c2, c3);
482d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[0], c1, c2, c3);
483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[3] = c1;
484d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
485d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[0], c2, c3, c1);
486d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[1], c2, c3, c1);
487d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[2], c2, c3, c1);
488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[3], c2, c3, c1);
489d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[4], c2, c3, c1);
490d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[4] = c2;
491d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
492d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[5], c3, c1, c2);
493d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[4], c3, c1, c2);
494d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[3], c3, c1, c2);
495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[2], c3, c1, c2);
496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[1], c3, c1, c2);
497d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[0], c3, c1, c2);
498d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[5] = c3;
499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[0], c1, c2, c3);
501d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[1], c1, c2, c3);
502d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[2], c1, c2, c3);
503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[3], c1, c2, c3);
504d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[4], c1, c2, c3);
505d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[5], c1, c2, c3);
506d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[6], c1, c2, c3);
507d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[6] = c1;
508d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
509d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[7], c2, c3, c1);
510d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[6], c2, c3, c1);
511d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[5], c2, c3, c1);
512d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[4], c2, c3, c1);
513d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[3], c2, c3, c1);
514d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[2], c2, c3, c1);
515d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[1], c2, c3, c1);
516d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[0], c2, c3, c1);
517d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[7] = c2;
518d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
519d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[1], c3, c1, c2);
520d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[2], c3, c1, c2);
521d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[3], c3, c1, c2);
522d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[4], c3, c1, c2);
523d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[5], c3, c1, c2);
524d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[6], c3, c1, c2);
525d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[7], c3, c1, c2);
526d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[8] = c3;
527d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
528d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[7], c1, c2, c3);
529d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[6], c1, c2, c3);
530d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[5], c1, c2, c3);
531d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[4], c1, c2, c3);
532d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[3], c1, c2, c3);
533d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[2], c1, c2, c3);
534d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[9] = c1;
535d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
536d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[3], c2, c3, c1);
537d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[4], c2, c3, c1);
538d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[5], c2, c3, c1);
539d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[6], c2, c3, c1);
540d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[7], c2, c3, c1);
541d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[10] = c2;
542d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
543d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[4], b[7], c3, c1, c2);
544d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[6], c3, c1, c2);
545d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[5], c3, c1, c2);
546d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[4], c3, c1, c2);
547d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[11] = c3;
548d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
549d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[5], c1, c2, c3);
550d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[6], c1, c2, c3);
551d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[5], b[7], c1, c2, c3);
552d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[12] = c1;
553d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
554d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[6], b[7], c2, c3, c1);
555d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[6], c2, c3, c1);
556d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[13] = c2;
557d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
558d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[7], b[7], c3, c1, c2);
559d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[14] = c3;
560d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[15] = c1;
561d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
562d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
563d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
564d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c1, c2, c3;
565d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
566d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
567d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
568d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
569d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[0], c1, c2, c3);
570d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[0] = c1;
571d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
572d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[1], c2, c3, c1);
573d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[0], c2, c3, c1);
574d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[1] = c2;
575d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
576d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[0], c3, c1, c2);
577d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[1], c3, c1, c2);
578d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[2], c3, c1, c2);
579d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[2] = c3;
580d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
581d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[0], b[3], c1, c2, c3);
582d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[2], c1, c2, c3);
583d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[1], c1, c2, c3);
584d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[0], c1, c2, c3);
585d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[3] = c1;
586d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
587d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[1], c2, c3, c1);
588d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[2], c2, c3, c1);
589d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[1], b[3], c2, c3, c1);
590d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[4] = c2;
591d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
592d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[2], b[3], c3, c1, c2);
593d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[2], c3, c1, c2);
594d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[5] = c3;
595d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
596d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  mul_add_c(a[3], b[3], c1, c2, c3);
597d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[6] = c1;
598d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[7] = c2;
599d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
600d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
601d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
602d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c1, c2, c3;
603d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
604d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
605d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
606d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
607d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 0, c1, c2, c3);
608d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[0] = c1;
609d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
610d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 1, 0, c2, c3, c1);
611d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[1] = c2;
612d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
613d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 1, c3, c1, c2);
614d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 2, 0, c3, c1, c2);
615d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[2] = c3;
616d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
617d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 3, 0, c1, c2, c3);
618d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 2, 1, c1, c2, c3);
619d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[3] = c1;
620d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
621d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 2, c2, c3, c1);
622d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 3, 1, c2, c3, c1);
623d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 4, 0, c2, c3, c1);
624d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[4] = c2;
625d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
626d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 5, 0, c3, c1, c2);
627d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 4, 1, c3, c1, c2);
628d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 3, 2, c3, c1, c2);
629d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[5] = c3;
630d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
631d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 3, c1, c2, c3);
632d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 4, 2, c1, c2, c3);
633d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 5, 1, c1, c2, c3);
634d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 6, 0, c1, c2, c3);
635d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[6] = c1;
636d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
637d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 0, c2, c3, c1);
638d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 6, 1, c2, c3, c1);
639d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 5, 2, c2, c3, c1);
640d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 4, 3, c2, c3, c1);
641d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[7] = c2;
642d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
643d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 4, c3, c1, c2);
644d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 5, 3, c3, c1, c2);
645d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 6, 2, c3, c1, c2);
646d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 1, c3, c1, c2);
647d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[8] = c3;
648d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
649d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 2, c1, c2, c3);
650d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 6, 3, c1, c2, c3);
651d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 5, 4, c1, c2, c3);
652d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[9] = c1;
653d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
654d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 5, c2, c3, c1);
655d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 6, 4, c2, c3, c1);
656d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 3, c2, c3, c1);
657d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[10] = c2;
658d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
659d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 4, c3, c1, c2);
660d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 6, 5, c3, c1, c2);
661d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[11] = c3;
662d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
663d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 6, c1, c2, c3);
664d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 5, c1, c2, c3);
665d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[12] = c1;
666d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
667d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 7, 6, c2, c3, c1);
668d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[13] = c2;
669d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
670d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 7, c3, c1, c2);
671d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[14] = c3;
672d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[15] = c1;
673d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
674d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
675d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
676d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_ULONG c1, c2, c3;
677d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
678d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
679d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
680d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
681d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 0, c1, c2, c3);
682d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[0] = c1;
683d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
684d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 1, 0, c2, c3, c1);
685d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[1] = c2;
686d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
687d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 1, c3, c1, c2);
688d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 2, 0, c3, c1, c2);
689d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[2] = c3;
690d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
691d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 3, 0, c1, c2, c3);
692d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 2, 1, c1, c2, c3);
693d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[3] = c1;
694d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c1 = 0;
695d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 2, c2, c3, c1);
696d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 3, 1, c2, c3, c1);
697d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[4] = c2;
698d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c2 = 0;
699d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c2(a, 3, 2, c3, c1, c2);
700d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[5] = c3;
701d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  c3 = 0;
702d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  sqr_add_c(a, 3, c1, c2, c3);
703d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[6] = c1;
704d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r[7] = c2;
705d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
706d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
707d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif
708