/src/openssl/crypto/bn/bn_exp2.c
Line  | Count  | Source  | 
1  |  | /*  | 
2  |  |  * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.  | 
3  |  |  *  | 
4  |  |  * Licensed under the Apache License 2.0 (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 <stdio.h>  | 
11  |  | #include "internal/cryptlib.h"  | 
12  |  | #include "bn_local.h"  | 
13  |  |  | 
14  |  | #define TABLE_SIZE      32  | 
15  |  |  | 
16  |  | int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,  | 
17  |  |                      const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,  | 
18  |  |                      BN_CTX *ctx, BN_MONT_CTX *in_mont)  | 
19  | 0  | { | 
20  | 0  |     int i, j, bits, b, bits1, bits2, ret =  | 
21  | 0  |         0, wpos1, wpos2, window1, window2, wvalue1, wvalue2;  | 
22  | 0  |     int r_is_one = 1;  | 
23  | 0  |     BIGNUM *d, *r;  | 
24  | 0  |     const BIGNUM *a_mod_m;  | 
25  |  |     /* Tables of variables obtained from 'ctx' */  | 
26  | 0  |     BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE];  | 
27  | 0  |     BN_MONT_CTX *mont = NULL;  | 
28  |  | 
  | 
29  | 0  |     bn_check_top(a1);  | 
30  | 0  |     bn_check_top(p1);  | 
31  | 0  |     bn_check_top(a2);  | 
32  | 0  |     bn_check_top(p2);  | 
33  | 0  |     bn_check_top(m);  | 
34  |  | 
  | 
35  | 0  |     if (!BN_is_odd(m)) { | 
36  | 0  |         ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);  | 
37  | 0  |         return 0;  | 
38  | 0  |     }  | 
39  | 0  |     bits1 = BN_num_bits(p1);  | 
40  | 0  |     bits2 = BN_num_bits(p2);  | 
41  | 0  |     if ((bits1 == 0) && (bits2 == 0)) { | 
42  | 0  |         ret = BN_one(rr);  | 
43  | 0  |         return ret;  | 
44  | 0  |     }  | 
45  |  |  | 
46  | 0  |     bits = (bits1 > bits2) ? bits1 : bits2;  | 
47  |  | 
  | 
48  | 0  |     BN_CTX_start(ctx);  | 
49  | 0  |     d = BN_CTX_get(ctx);  | 
50  | 0  |     r = BN_CTX_get(ctx);  | 
51  | 0  |     val1[0] = BN_CTX_get(ctx);  | 
52  | 0  |     val2[0] = BN_CTX_get(ctx);  | 
53  | 0  |     if (val2[0] == NULL)  | 
54  | 0  |         goto err;  | 
55  |  |  | 
56  | 0  |     if (in_mont != NULL)  | 
57  | 0  |         mont = in_mont;  | 
58  | 0  |     else { | 
59  | 0  |         if ((mont = BN_MONT_CTX_new()) == NULL)  | 
60  | 0  |             goto err;  | 
61  | 0  |         if (!BN_MONT_CTX_set(mont, m, ctx))  | 
62  | 0  |             goto err;  | 
63  | 0  |     }  | 
64  |  |  | 
65  | 0  |     window1 = BN_window_bits_for_exponent_size(bits1);  | 
66  | 0  |     window2 = BN_window_bits_for_exponent_size(bits2);  | 
67  |  |  | 
68  |  |     /*  | 
69  |  |      * Build table for a1:   val1[i] := a1^(2*i + 1) mod m  for i = 0 .. 2^(window1-1)  | 
70  |  |      */  | 
71  | 0  |     if (a1->neg || BN_ucmp(a1, m) >= 0) { | 
72  | 0  |         if (!BN_mod(val1[0], a1, m, ctx))  | 
73  | 0  |             goto err;  | 
74  | 0  |         a_mod_m = val1[0];  | 
75  | 0  |     } else  | 
76  | 0  |         a_mod_m = a1;  | 
77  | 0  |     if (BN_is_zero(a_mod_m)) { | 
78  | 0  |         BN_zero(rr);  | 
79  | 0  |         ret = 1;  | 
80  | 0  |         goto err;  | 
81  | 0  |     }  | 
82  |  |  | 
83  | 0  |     if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx))  | 
84  | 0  |         goto err;  | 
85  | 0  |     if (window1 > 1) { | 
86  | 0  |         if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx))  | 
87  | 0  |             goto err;  | 
88  |  |  | 
89  | 0  |         j = 1 << (window1 - 1);  | 
90  | 0  |         for (i = 1; i < j; i++) { | 
91  | 0  |             if (((val1[i] = BN_CTX_get(ctx)) == NULL) ||  | 
92  | 0  |                 !BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx))  | 
93  | 0  |                 goto err;  | 
94  | 0  |         }  | 
95  | 0  |     }  | 
96  |  |  | 
97  |  |     /*  | 
98  |  |      * Build table for a2:   val2[i] := a2^(2*i + 1) mod m  for i = 0 .. 2^(window2-1)  | 
99  |  |      */  | 
100  | 0  |     if (a2->neg || BN_ucmp(a2, m) >= 0) { | 
101  | 0  |         if (!BN_mod(val2[0], a2, m, ctx))  | 
102  | 0  |             goto err;  | 
103  | 0  |         a_mod_m = val2[0];  | 
104  | 0  |     } else  | 
105  | 0  |         a_mod_m = a2;  | 
106  | 0  |     if (BN_is_zero(a_mod_m)) { | 
107  | 0  |         BN_zero(rr);  | 
108  | 0  |         ret = 1;  | 
109  | 0  |         goto err;  | 
110  | 0  |     }  | 
111  | 0  |     if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx))  | 
112  | 0  |         goto err;  | 
113  | 0  |     if (window2 > 1) { | 
114  | 0  |         if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx))  | 
115  | 0  |             goto err;  | 
116  |  |  | 
117  | 0  |         j = 1 << (window2 - 1);  | 
118  | 0  |         for (i = 1; i < j; i++) { | 
119  | 0  |             if (((val2[i] = BN_CTX_get(ctx)) == NULL) ||  | 
120  | 0  |                 !BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx))  | 
121  | 0  |                 goto err;  | 
122  | 0  |         }  | 
123  | 0  |     }  | 
124  |  |  | 
125  |  |     /* Now compute the power product, using independent windows. */  | 
126  | 0  |     r_is_one = 1;  | 
127  | 0  |     wvalue1 = 0;                /* The 'value' of the first window */  | 
128  | 0  |     wvalue2 = 0;                /* The 'value' of the second window */  | 
129  | 0  |     wpos1 = 0;                  /* If wvalue1 > 0, the bottom bit of the  | 
130  |  |                                  * first window */  | 
131  | 0  |     wpos2 = 0;                  /* If wvalue2 > 0, the bottom bit of the  | 
132  |  |                                  * second window */  | 
133  |  | 
  | 
134  | 0  |     if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))  | 
135  | 0  |         goto err;  | 
136  | 0  |     for (b = bits - 1; b >= 0; b--) { | 
137  | 0  |         if (!r_is_one) { | 
138  | 0  |             if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))  | 
139  | 0  |                 goto err;  | 
140  | 0  |         }  | 
141  |  |  | 
142  | 0  |         if (!wvalue1)  | 
143  | 0  |             if (BN_is_bit_set(p1, b)) { | 
144  |  |                 /*  | 
145  |  |                  * consider bits b-window1+1 .. b for this window  | 
146  |  |                  */  | 
147  | 0  |                 i = b - window1 + 1;  | 
148  | 0  |                 while (!BN_is_bit_set(p1, i)) /* works for i<0 */  | 
149  | 0  |                     i++;  | 
150  | 0  |                 wpos1 = i;  | 
151  | 0  |                 wvalue1 = 1;  | 
152  | 0  |                 for (i = b - 1; i >= wpos1; i--) { | 
153  | 0  |                     wvalue1 <<= 1;  | 
154  | 0  |                     if (BN_is_bit_set(p1, i))  | 
155  | 0  |                         wvalue1++;  | 
156  | 0  |                 }  | 
157  | 0  |             }  | 
158  |  | 
  | 
159  | 0  |         if (!wvalue2)  | 
160  | 0  |             if (BN_is_bit_set(p2, b)) { | 
161  |  |                 /*  | 
162  |  |                  * consider bits b-window2+1 .. b for this window  | 
163  |  |                  */  | 
164  | 0  |                 i = b - window2 + 1;  | 
165  | 0  |                 while (!BN_is_bit_set(p2, i))  | 
166  | 0  |                     i++;  | 
167  | 0  |                 wpos2 = i;  | 
168  | 0  |                 wvalue2 = 1;  | 
169  | 0  |                 for (i = b - 1; i >= wpos2; i--) { | 
170  | 0  |                     wvalue2 <<= 1;  | 
171  | 0  |                     if (BN_is_bit_set(p2, i))  | 
172  | 0  |                         wvalue2++;  | 
173  | 0  |                 }  | 
174  | 0  |             }  | 
175  |  | 
  | 
176  | 0  |         if (wvalue1 && b == wpos1) { | 
177  |  |             /* wvalue1 is odd and < 2^window1 */  | 
178  | 0  |             if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx))  | 
179  | 0  |                 goto err;  | 
180  | 0  |             wvalue1 = 0;  | 
181  | 0  |             r_is_one = 0;  | 
182  | 0  |         }  | 
183  |  |  | 
184  | 0  |         if (wvalue2 && b == wpos2) { | 
185  |  |             /* wvalue2 is odd and < 2^window2 */  | 
186  | 0  |             if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx))  | 
187  | 0  |                 goto err;  | 
188  | 0  |             wvalue2 = 0;  | 
189  | 0  |             r_is_one = 0;  | 
190  | 0  |         }  | 
191  | 0  |     }  | 
192  | 0  |     if (!BN_from_montgomery(rr, r, mont, ctx))  | 
193  | 0  |         goto err;  | 
194  | 0  |     ret = 1;  | 
195  | 0  |  err:  | 
196  | 0  |     if (in_mont == NULL)  | 
197  | 0  |         BN_MONT_CTX_free(mont);  | 
198  | 0  |     BN_CTX_end(ctx);  | 
199  | 0  |     bn_check_top(rr);  | 
200  | 0  |     return ret;  | 
201  | 0  | }  |