1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
21ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard * All rights reserved.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * This package is an SSL implementation written
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * by Eric Young (eay@cryptsoft.com).
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * The implementation was written so as to conform with Netscapes SSL.
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
8361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * This library is free for commercial and non-commercial use as long as
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the following conditions are aheared to.  The following conditions
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * apply to all code found in this distribution, be it the RC4, RSA,
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * included with this distribution is covered by the same copyright terms
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * Copyright remains Eric Young's, and as such any Copyright notices in
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the code are not to be removed.
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * If this package is used in a product, Eric Young should be given attribution
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * as the author of the parts of the library used.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * This can be in the form of a textual message at program startup or
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * in documentation (online or textual) provided with the package.
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * Redistribution and use in source and binary forms, with or without
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * modification, are permitted provided that the following conditions
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * are met:
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * 1. Redistributions of source code must retain the copyright
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *    notice, this list of conditions and the following disclaimer.
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * 2. Redistributions in binary form must reproduce the above copyright
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *    notice, this list of conditions and the following disclaimer in the
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    documentation and/or other materials provided with the distribution.
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 3. All advertising materials mentioning features or use of this software
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    must display the following acknowledgement:
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    "This product includes cryptographic software written by
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *     Eric Young (eay@cryptsoft.com)"
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    The word 'cryptographic' can be left out if the rouines from the library
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    being used are not cryptographic related :-).
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 4. If you include any Windows specific code (or a derivative thereof) from
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    the apps directory (application code) you must include an acknowledgement:
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
421ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * SUCH DAMAGE.
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * The licence and distribution terms for any publically available version or
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * derivative of this code cannot be changed.  i.e. this code cannot simply be
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * copied and put under another distribution licence
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * [including the GNU Public Licence.]
56b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath */
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* ====================================================================
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Redistribution and use in source and binary forms, with or without
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * modification, are permitted provided that the following conditions
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * are met:
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 1. Redistributions of source code must retain the above copyright
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    notice, this list of conditions and the following disclaimer.
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 2. Redistributions in binary form must reproduce the above copyright
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    notice, this list of conditions and the following disclaimer in
69a9039623c272f458a53f09009c2a0e1d6e60491dJakub Jelinek *    the documentation and/or other materials provided with the
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    distribution.
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 3. All advertising materials mentioning features or use of this
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    software must display the following acknowledgment:
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    "This product includes software developed by the OpenSSL Project
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    endorse or promote products derived from this software without
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    prior written permission. For written permission, please contact
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    openssl-core@openssl.org.
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 5. Products derived from this software may not be called "OpenSSL"
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    nor may "OpenSSL" appear in their names without prior written
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    permission of the OpenSSL Project.
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * 6. Redistributions of any form whatsoever must retain the following
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    acknowledgment:
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    "This product includes software developed by the OpenSSL Project
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98a9039623c272f458a53f09009c2a0e1d6e60491dJakub Jelinek * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * OF THE POSSIBILITY OF SUCH DAMAGE.
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * ====================================================================
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * This product includes cryptographic software written by Eric Young
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * (eay@cryptsoft.com).  This product includes software written by Tim
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Hudson (tjh@cryptsoft.com). */
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <openssl/bn.h>
110b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <openssl/err.h>
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <openssl/mem.h>
115#include <openssl/thread.h>
116
117#include "internal.h"
118#include "../internal.h"
119
120
121#if !defined(OPENSSL_NO_ASM) &&                         \
122    (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
123     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
124#define OPENSSL_BN_ASM_MONT
125#endif
126
127BN_MONT_CTX *BN_MONT_CTX_new(void) {
128  BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
129
130  if (ret == NULL) {
131    return NULL;
132  }
133
134  memset(ret, 0, sizeof(BN_MONT_CTX));
135  BN_init(&ret->RR);
136  BN_init(&ret->N);
137
138  return ret;
139}
140
141void BN_MONT_CTX_free(BN_MONT_CTX *mont) {
142  if (mont == NULL) {
143    return;
144  }
145
146  BN_free(&mont->RR);
147  BN_free(&mont->N);
148  OPENSSL_free(mont);
149}
150
151BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, const BN_MONT_CTX *from) {
152  if (to == from) {
153    return to;
154  }
155
156  if (!BN_copy(&to->RR, &from->RR) ||
157      !BN_copy(&to->N, &from->N)) {
158    return NULL;
159  }
160  to->n0[0] = from->n0[0];
161  to->n0[1] = from->n0[1];
162  return to;
163}
164
165int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
166  int ret = 0;
167  BIGNUM *Ri, *R;
168  BIGNUM tmod;
169  BN_ULONG buf[2];
170
171  if (BN_is_zero(mod)) {
172    OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
173    return 0;
174  }
175
176  BN_CTX_start(ctx);
177  Ri = BN_CTX_get(ctx);
178  if (Ri == NULL) {
179    goto err;
180  }
181  R = &mont->RR; /* grab RR as a temp */
182  if (!BN_copy(&mont->N, mod)) {
183    goto err; /* Set N */
184  }
185  mont->N.neg = 0;
186
187  BN_init(&tmod);
188  tmod.d = buf;
189  tmod.dmax = 2;
190  tmod.neg = 0;
191
192#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
193  /* Only certain BN_BITS2<=32 platforms actually make use of
194   * n0[1], and we could use the #else case (with a shorter R
195   * value) for the others.  However, currently only the assembler
196   * files do know which is which. */
197
198  BN_zero(R);
199  if (!BN_set_bit(R, 2 * BN_BITS2)) {
200    goto err;
201  }
202
203  tmod.top = 0;
204  if ((buf[0] = mod->d[0])) {
205    tmod.top = 1;
206  }
207  if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) {
208    tmod.top = 2;
209  }
210
211  if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
212    goto err;
213  }
214  if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) {
215    goto err; /* R*Ri */
216  }
217  if (!BN_is_zero(Ri)) {
218    if (!BN_sub_word(Ri, 1)) {
219      goto err;
220    }
221  } else {
222    /* if N mod word size == 1 */
223    if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) {
224      goto err;
225    }
226    /* Ri-- (mod double word size) */
227    Ri->neg = 0;
228    Ri->d[0] = BN_MASK2;
229    Ri->d[1] = BN_MASK2;
230    Ri->top = 2;
231  }
232
233  if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
234    goto err;
235  }
236  /* Ni = (R*Ri-1)/N,
237   * keep only couple of least significant words: */
238  mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
239  mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
240#else
241  BN_zero(R);
242  if (!BN_set_bit(R, BN_BITS2)) {
243    goto err; /* R */
244  }
245
246  buf[0] = mod->d[0]; /* tmod = N mod word size */
247  buf[1] = 0;
248  tmod.top = buf[0] != 0 ? 1 : 0;
249  /* Ri = R^-1 mod N*/
250  if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
251    goto err;
252  }
253  if (!BN_lshift(Ri, Ri, BN_BITS2)) {
254    goto err; /* R*Ri */
255  }
256  if (!BN_is_zero(Ri)) {
257    if (!BN_sub_word(Ri, 1)) {
258      goto err;
259    }
260  } else {
261    /* if N mod word size == 1 */
262    if (!BN_set_word(Ri, BN_MASK2)) {
263      goto err; /* Ri-- (mod word size) */
264    }
265  }
266  if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
267    goto err;
268  }
269  /* Ni = (R*Ri-1)/N,
270   * keep only least significant word: */
271  mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
272  mont->n0[1] = 0;
273#endif
274
275  /* RR = (2^ri)^2 == 2^(ri*2) == 1 << (ri*2), which has its (ri*2)th bit set. */
276  int ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
277  BN_zero(&(mont->RR));
278  if (!BN_set_bit(&(mont->RR), ri * 2)) {
279    goto err;
280  }
281  if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
282    goto err;
283  }
284
285  ret = 1;
286
287err:
288  BN_CTX_end(ctx);
289  return ret;
290}
291
292BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
293                                    const BIGNUM *mod, BN_CTX *bn_ctx) {
294  CRYPTO_MUTEX_lock_read(lock);
295  BN_MONT_CTX *ctx = *pmont;
296  CRYPTO_MUTEX_unlock(lock);
297
298  if (ctx) {
299    return ctx;
300  }
301
302  CRYPTO_MUTEX_lock_write(lock);
303  ctx = *pmont;
304  if (ctx) {
305    goto out;
306  }
307
308  ctx = BN_MONT_CTX_new();
309  if (ctx == NULL) {
310    goto out;
311  }
312  if (!BN_MONT_CTX_set(ctx, mod, bn_ctx)) {
313    BN_MONT_CTX_free(ctx);
314    ctx = NULL;
315    goto out;
316  }
317  *pmont = ctx;
318
319out:
320  CRYPTO_MUTEX_unlock(lock);
321  return ctx;
322}
323
324int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
325                     BN_CTX *ctx) {
326  return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
327}
328
329#if 0
330static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
331                                   const BN_MONT_CTX *mont) {
332  const BIGNUM *n;
333  BN_ULONG *ap, *np, *rp, n0, v, carry;
334  int nl, max, i;
335
336  n = &mont->N;
337  nl = n->top;
338  if (nl == 0) {
339    ret->top = 0;
340    return 1;
341  }
342
343  max = (2 * nl); /* carry is stored separately */
344  if (bn_wexpand(r, max) == NULL) {
345    return 0;
346  }
347
348  r->neg ^= n->neg;
349  np = n->d;
350  rp = r->d;
351
352  /* clear the top words of T */
353  if (max > r->top) {
354    memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
355  }
356
357  r->top = max;
358  n0 = mont->n0[0];
359
360  for (carry = 0, i = 0; i < nl; i++, rp++) {
361    v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
362    v = (v + carry + rp[nl]) & BN_MASK2;
363    carry |= (v != rp[nl]);
364    carry &= (v <= rp[nl]);
365    rp[nl] = v;
366  }
367
368  if (bn_wexpand(ret, nl) == NULL) {
369    return 0;
370  }
371  ret->top = nl;
372  ret->neg = r->neg;
373
374  rp = ret->d;
375  ap = &(r->d[nl]);
376
377  {
378    BN_ULONG *nrp;
379    size_t m;
380
381    v = bn_sub_words(rp, ap, np, nl) - carry;
382    /* if subtraction result is real, then trick unconditional memcpy below to
383     * perform in-place "refresh" instead of actual copy. */
384    m = (0 - (size_t)v);
385    nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
386
387    for (i = 0, nl -= 4; i < nl; i += 4) {
388      BN_ULONG t1, t2, t3, t4;
389
390      t1 = nrp[i + 0];
391      t2 = nrp[i + 1];
392      t3 = nrp[i + 2];
393      ap[i + 0] = 0;
394      t4 = nrp[i + 3];
395      ap[i + 1] = 0;
396      rp[i + 0] = t1;
397      ap[i + 2] = 0;
398      rp[i + 1] = t2;
399      ap[i + 3] = 0;
400      rp[i + 2] = t3;
401      rp[i + 3] = t4;
402    }
403
404    for (nl += 4; i < nl; i++) {
405      rp[i] = nrp[i], ap[i] = 0;
406    }
407  }
408
409  bn_correct_top(r);
410  bn_correct_top(ret);
411
412  return 1;
413}
414#endif
415
416#define PTR_SIZE_INT size_t
417
418static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
419	{
420	BIGNUM *n;
421	BN_ULONG *ap,*np,*rp,n0,v,carry;
422	int nl,max,i;
423
424	n= (BIGNUM*) &(mont->N);
425	nl=n->top;
426	if (nl == 0) { ret->top=0; return(1); }
427
428	max=(2*nl); /* carry is stored separately */
429	if (bn_wexpand(r,max) == NULL) return(0);
430
431	r->neg^=n->neg;
432	np=n->d;
433	rp=r->d;
434
435	/* clear the top words of T */
436#if 1
437	for (i=r->top; i<max; i++) /* memset? XXX */
438		rp[i]=0;
439#else
440	memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
441#endif
442
443	r->top=max;
444	n0=mont->n0[0];
445
446	for (carry=0, i=0; i<nl; i++, rp++)
447		{
448		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
449		v = (v+carry+rp[nl])&BN_MASK2;
450		carry |= (v != rp[nl]);
451		carry &= (v <= rp[nl]);
452		rp[nl]=v;
453		}
454
455	if (bn_wexpand(ret,nl) == NULL) return(0);
456	ret->top=nl;
457	ret->neg=r->neg;
458
459	rp=ret->d;
460	ap=&(r->d[nl]);
461
462	{
463	BN_ULONG *nrp;
464	size_t m;
465
466	v=bn_sub_words(rp,ap,np,nl)-carry;
467	/* if subtraction result is real, then
468	 * trick unconditional memcpy below to perform in-place
469	 * "refresh" instead of actual copy. */
470	m=(0-(size_t)v);
471	nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
472
473	for (i=0,nl-=4; i<nl; i+=4)
474		{
475		BN_ULONG t1,t2,t3,t4;
476
477		t1=nrp[i+0];
478		t2=nrp[i+1];
479		t3=nrp[i+2];	ap[i+0]=0;
480		t4=nrp[i+3];	ap[i+1]=0;
481		rp[i+0]=t1;	ap[i+2]=0;
482		rp[i+1]=t2;	ap[i+3]=0;
483		rp[i+2]=t3;
484		rp[i+3]=t4;
485		}
486	for (nl+=4; i<nl; i++)
487		rp[i]=nrp[i], ap[i]=0;
488	}
489	bn_correct_top(r);
490	bn_correct_top(ret);
491
492	return(1);
493	}
494
495int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
496                       BN_CTX *ctx) {
497  int retn = 0;
498  BIGNUM *t;
499
500  BN_CTX_start(ctx);
501  t = BN_CTX_get(ctx);
502  if (t == NULL) {
503    return 0;
504  }
505
506  if (BN_copy(t, a)) {
507    retn = BN_from_montgomery_word(ret, t, mont);
508  }
509  BN_CTX_end(ctx);
510
511  return retn;
512}
513
514int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
515                          const BN_MONT_CTX *mont, BN_CTX *ctx) {
516  BIGNUM *tmp;
517  int ret = 0;
518
519#if defined(OPENSSL_BN_ASM_MONT)
520  int num = mont->N.top;
521
522  if (num > 1 && a->top == num && b->top == num) {
523    if (bn_wexpand(r, num) == NULL) {
524      return 0;
525    }
526    if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
527      r->neg = a->neg ^ b->neg;
528      r->top = num;
529      bn_correct_top(r);
530      return 1;
531    }
532  }
533#endif
534
535  BN_CTX_start(ctx);
536  tmp = BN_CTX_get(ctx);
537  if (tmp == NULL) {
538    goto err;
539  }
540
541  if (a == b) {
542    if (!BN_sqr(tmp, a, ctx)) {
543      goto err;
544    }
545  } else {
546    if (!BN_mul(tmp, a, b, ctx)) {
547      goto err;
548    }
549  }
550
551  /* reduce from aRR to aR */
552  if (!BN_from_montgomery_word(r, tmp, mont)) {
553    goto err;
554  }
555
556  ret = 1;
557
558err:
559  BN_CTX_end(ctx);
560  return ret;
561}
562