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