81b895ce379f21cc9ebf17e5c9bc86fbe2f67a00
[openssl.git] / crypto / bn / bn_blind.c
1 /* ====================================================================
2  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This product includes cryptographic software written by Eric Young
50  * (eay@cryptsoft.com).  This product includes software written by Tim
51  * Hudson (tjh@cryptsoft.com).
52  *
53  */
54 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
55  * All rights reserved.
56  *
57  * This package is an SSL implementation written
58  * by Eric Young (eay@cryptsoft.com).
59  * The implementation was written so as to conform with Netscapes SSL.
60  *
61  * This library is free for commercial and non-commercial use as long as
62  * the following conditions are aheared to.  The following conditions
63  * apply to all code found in this distribution, be it the RC4, RSA,
64  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
65  * included with this distribution is covered by the same copyright terms
66  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
67  *
68  * Copyright remains Eric Young's, and as such any Copyright notices in
69  * the code are not to be removed.
70  * If this package is used in a product, Eric Young should be given attribution
71  * as the author of the parts of the library used.
72  * This can be in the form of a textual message at program startup or
73  * in documentation (online or textual) provided with the package.
74  *
75  * Redistribution and use in source and binary forms, with or without
76  * modification, are permitted provided that the following conditions
77  * are met:
78  * 1. Redistributions of source code must retain the copyright
79  *    notice, this list of conditions and the following disclaimer.
80  * 2. Redistributions in binary form must reproduce the above copyright
81  *    notice, this list of conditions and the following disclaimer in the
82  *    documentation and/or other materials provided with the distribution.
83  * 3. All advertising materials mentioning features or use of this software
84  *    must display the following acknowledgement:
85  *    "This product includes cryptographic software written by
86  *     Eric Young (eay@cryptsoft.com)"
87  *    The word 'cryptographic' can be left out if the rouines from the library
88  *    being used are not cryptographic related :-).
89  * 4. If you include any Windows specific code (or a derivative thereof) from
90  *    the apps directory (application code) you must include an acknowledgement:
91  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
92  *
93  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
94  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
95  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
96  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
97  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
98  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
99  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
101  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
102  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
103  * SUCH DAMAGE.
104  *
105  * The licence and distribution terms for any publically available version or
106  * derivative of this code cannot be changed.  i.e. this code cannot simply be
107  * copied and put under another distribution licence
108  * [including the GNU Public Licence.]
109  */
110
111 #include <openssl/opensslconf.h>
112 #include "internal/cryptlib.h"
113 #include "internal/threads.h"
114 #include "bn_lcl.h"
115
116 #define BN_BLINDING_COUNTER     32
117
118 struct bn_blinding_st {
119     BIGNUM *A;
120     BIGNUM *Ai;
121     BIGNUM *e;
122     BIGNUM *mod;                /* just a reference */
123     CRYPTO_THREAD_ID tid;
124     int counter;
125     unsigned long flags;
126     BN_MONT_CTX *m_ctx;
127     int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
128                        const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
129     CRYPTO_RWLOCK *lock;
130 };
131
132 BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
133 {
134     BN_BLINDING *ret = NULL;
135
136     bn_check_top(mod);
137
138     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
139         BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
140         return NULL;
141     }
142
143     ret->lock = CRYPTO_THREAD_lock_new();
144     if (ret->lock == NULL) {
145         BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
146         OPENSSL_free(ret);
147         return NULL;
148     }
149
150     BN_BLINDING_set_current_thread(ret);
151
152     if (A != NULL) {
153         if ((ret->A = BN_dup(A)) == NULL)
154             goto err;
155     }
156
157     if (Ai != NULL) {
158         if ((ret->Ai = BN_dup(Ai)) == NULL)
159             goto err;
160     }
161
162     /* save a copy of mod in the BN_BLINDING structure */
163     if ((ret->mod = BN_dup(mod)) == NULL)
164         goto err;
165
166     if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
167         BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
168
169     /*
170      * Set the counter to the special value -1 to indicate that this is
171      * never-used fresh blinding that does not need updating before first
172      * use.
173      */
174     ret->counter = -1;
175
176     return ret;
177
178  err:
179     BN_BLINDING_free(ret);
180     return NULL;
181 }
182
183 void BN_BLINDING_free(BN_BLINDING *r)
184 {
185     if (r == NULL)
186         return;
187
188     BN_free(r->A);
189     BN_free(r->Ai);
190     BN_free(r->e);
191     BN_free(r->mod);
192     CRYPTO_THREAD_lock_free(r->lock);
193     OPENSSL_free(r);
194 }
195
196 int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
197 {
198     int ret = 0;
199
200     if ((b->A == NULL) || (b->Ai == NULL)) {
201         BNerr(BN_F_BN_BLINDING_UPDATE, BN_R_NOT_INITIALIZED);
202         goto err;
203     }
204
205     if (b->counter == -1)
206         b->counter = 0;
207
208     if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
209         !(b->flags & BN_BLINDING_NO_RECREATE)) {
210         /* re-create blinding parameters */
211         if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL))
212             goto err;
213     } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
214         if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx))
215             goto err;
216         if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx))
217             goto err;
218     }
219
220     ret = 1;
221  err:
222     if (b->counter == BN_BLINDING_COUNTER)
223         b->counter = 0;
224     return (ret);
225 }
226
227 int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
228 {
229     return BN_BLINDING_convert_ex(n, NULL, b, ctx);
230 }
231
232 int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
233 {
234     int ret = 1;
235
236     bn_check_top(n);
237
238     if ((b->A == NULL) || (b->Ai == NULL)) {
239         BNerr(BN_F_BN_BLINDING_CONVERT_EX, BN_R_NOT_INITIALIZED);
240         return (0);
241     }
242
243     if (b->counter == -1)
244         /* Fresh blinding, doesn't need updating. */
245         b->counter = 0;
246     else if (!BN_BLINDING_update(b, ctx))
247         return (0);
248
249     if (r != NULL) {
250         if (!BN_copy(r, b->Ai))
251             ret = 0;
252     }
253
254     if (!BN_mod_mul(n, n, b->A, b->mod, ctx))
255         ret = 0;
256
257     return ret;
258 }
259
260 int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
261 {
262     return BN_BLINDING_invert_ex(n, NULL, b, ctx);
263 }
264
265 int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
266                           BN_CTX *ctx)
267 {
268     int ret;
269
270     bn_check_top(n);
271
272     if (r != NULL)
273         ret = BN_mod_mul(n, n, r, b->mod, ctx);
274     else {
275         if (b->Ai == NULL) {
276             BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED);
277             return (0);
278         }
279         ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
280     }
281
282     bn_check_top(n);
283     return (ret);
284 }
285
286 int BN_BLINDING_is_current_thread(BN_BLINDING *b)
287 {
288     return CRYPTO_THREAD_compare_id(CRYPTO_THREAD_get_current_id(), b->tid);
289 }
290
291 void BN_BLINDING_set_current_thread(BN_BLINDING *b)
292 {
293     b->tid = CRYPTO_THREAD_get_current_id();
294 }
295
296 int BN_BLINDING_lock(BN_BLINDING *b)
297 {
298     return CRYPTO_THREAD_write_lock(b->lock);
299 }
300
301 int BN_BLINDING_unlock(BN_BLINDING *b)
302 {
303     return CRYPTO_THREAD_unlock(b->lock);
304 }
305
306 unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
307 {
308     return b->flags;
309 }
310
311 void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags)
312 {
313     b->flags = flags;
314 }
315
316 BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
317                                       const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
318                                       int (*bn_mod_exp) (BIGNUM *r,
319                                                          const BIGNUM *a,
320                                                          const BIGNUM *p,
321                                                          const BIGNUM *m,
322                                                          BN_CTX *ctx,
323                                                          BN_MONT_CTX *m_ctx),
324                                       BN_MONT_CTX *m_ctx)
325 {
326     int retry_counter = 32;
327     BN_BLINDING *ret = NULL;
328
329     if (b == NULL)
330         ret = BN_BLINDING_new(NULL, NULL, m);
331     else
332         ret = b;
333
334     if (ret == NULL)
335         goto err;
336
337     if (ret->A == NULL && (ret->A = BN_new()) == NULL)
338         goto err;
339     if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL)
340         goto err;
341
342     if (e != NULL) {
343         BN_free(ret->e);
344         ret->e = BN_dup(e);
345     }
346     if (ret->e == NULL)
347         goto err;
348
349     if (bn_mod_exp != NULL)
350         ret->bn_mod_exp = bn_mod_exp;
351     if (m_ctx != NULL)
352         ret->m_ctx = m_ctx;
353
354     do {
355         int rv;
356         if (!BN_rand_range(ret->A, ret->mod))
357             goto err;
358         if (!int_bn_mod_inverse(ret->Ai, ret->A, ret->mod, ctx, &rv)) {
359             /*
360              * this should almost never happen for good RSA keys
361              */
362             if (rv) {
363                 if (retry_counter-- == 0) {
364                     BNerr(BN_F_BN_BLINDING_CREATE_PARAM,
365                           BN_R_TOO_MANY_ITERATIONS);
366                     goto err;
367                 }
368             } else
369                 goto err;
370         } else
371             break;
372     } while (1);
373
374     if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) {
375         if (!ret->bn_mod_exp
376             (ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx))
377             goto err;
378     } else {
379         if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx))
380             goto err;
381     }
382
383     return ret;
384  err:
385     if (b == NULL) {
386         BN_BLINDING_free(ret);
387         ret = NULL;
388     }
389
390     return ret;
391 }