• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <openssl/rsa.h>
11
12#include <string.h>
13
14#include <openssl/bn.h>
15#include <openssl/err.h>
16#include <openssl/mem.h>
17
18#include "../../internal.h"
19#include "internal.h"
20
21
22#define BN_BLINDING_COUNTER 32
23
24struct bn_blinding_st {
25  BIGNUM *A;   // The base blinding factor, Montgomery-encoded.
26  BIGNUM *Ai;  // The inverse of the blinding factor, Montgomery-encoded.
27  unsigned counter;
28};
29
30static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
31                                    const BN_MONT_CTX *mont, BN_CTX *ctx);
32
33BN_BLINDING *BN_BLINDING_new(void) {
34  BN_BLINDING *ret =
35      reinterpret_cast<BN_BLINDING *>(OPENSSL_zalloc(sizeof(BN_BLINDING)));
36  if (ret == NULL) {
37    return NULL;
38  }
39
40  ret->A = BN_new();
41  if (ret->A == NULL) {
42    goto err;
43  }
44
45  ret->Ai = BN_new();
46  if (ret->Ai == NULL) {
47    goto err;
48  }
49
50  // The blinding values need to be created before this blinding can be used.
51  ret->counter = BN_BLINDING_COUNTER - 1;
52
53  return ret;
54
55err:
56  BN_BLINDING_free(ret);
57  return NULL;
58}
59
60void BN_BLINDING_free(BN_BLINDING *r) {
61  if (r == nullptr) {
62    return;
63  }
64  BN_free(r->A);
65  BN_free(r->Ai);
66  OPENSSL_free(r);
67}
68
69void BN_BLINDING_invalidate(BN_BLINDING *b) {
70  b->counter = BN_BLINDING_COUNTER - 1;
71}
72
73static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e,
74                              const BN_MONT_CTX *mont, BN_CTX *ctx) {
75  if (++b->counter == BN_BLINDING_COUNTER) {
76    // re-create blinding parameters
77    if (!bn_blinding_create_param(b, e, mont, ctx)) {
78      goto err;
79    }
80    b->counter = 0;
81  } else {
82    if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) ||
83        !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) {
84      goto err;
85    }
86  }
87
88  return 1;
89
90err:
91  // |A| and |Ai| may be in an inconsistent state so they both need to be
92  // replaced the next time this blinding is used. Note that this is only
93  // sufficient because support for |BN_BLINDING_NO_UPDATE| and
94  // |BN_BLINDING_NO_RECREATE| was previously dropped.
95  b->counter = BN_BLINDING_COUNTER - 1;
96
97  return 0;
98}
99
100int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
101                        const BN_MONT_CTX *mont, BN_CTX *ctx) {
102  // |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
103  // cancels one Montgomery factor, so the resulting value of |n| is unencoded.
104  if (!bn_blinding_update(b, e, mont, ctx) ||
105      !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
106    return 0;
107  }
108
109  return 1;
110}
111
112int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont,
113                       BN_CTX *ctx) {
114  // |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
115  // cancels one Montgomery factor, so the resulting value of |n| is unencoded.
116  return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
117}
118
119static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
120                                    const BN_MONT_CTX *mont, BN_CTX *ctx) {
121  int no_inverse;
122  if (!BN_rand_range_ex(b->A, 1, &mont->N) ||
123      // Compute |b->A|^-1 in Montgomery form. Note |BN_from_montgomery| +
124      // |BN_mod_inverse_blinded| is equivalent to, but more efficient than,
125      // |BN_mod_inverse_blinded| + |BN_to_montgomery|.
126      //
127      // We do not retry if |b->A| has no inverse. Finding a non-invertible
128      // value of |b->A| is equivalent to factoring |mont->N|. There is
129      // negligible probability of stumbling on one at random.
130      !BN_from_montgomery(b->Ai, b->A, mont, ctx) ||
131      !BN_mod_inverse_blinded(b->Ai, &no_inverse, b->Ai, mont, ctx) ||
132      // TODO(davidben): |BN_mod_exp_mont| internally computes the result in
133      // Montgomery form. Save a pair of Montgomery reductions and a
134      // multiplication by returning that value directly.
135      !BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont) ||
136      !BN_to_montgomery(b->A, b->A, mont, ctx)) {
137    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
138    return 0;
139  }
140
141  return 1;
142}
143