summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_rand.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_rand.c')
-rw-r--r--src/lib/libcrypto/bn/bn_rand.c107
1 files changed, 94 insertions, 13 deletions
diff --git a/src/lib/libcrypto/bn/bn_rand.c b/src/lib/libcrypto/bn/bn_rand.c
index 21ecbc04ed..acd0619921 100644
--- a/src/lib/libcrypto/bn/bn_rand.c
+++ b/src/lib/libcrypto/bn/bn_rand.c
@@ -76,7 +76,7 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
76 76
77 bytes=(bits+7)/8; 77 bytes=(bits+7)/8;
78 bit=(bits-1)%8; 78 bit=(bits-1)%8;
79 mask=0xff<<bit; 79 mask=0xff<<(bit+1);
80 80
81 buf=(unsigned char *)OPENSSL_malloc(bytes); 81 buf=(unsigned char *)OPENSSL_malloc(bytes);
82 if (buf == NULL) 82 if (buf == NULL)
@@ -100,25 +100,48 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
100 goto err; 100 goto err;
101 } 101 }
102 102
103 if (top) 103#if 1
104 if (pseudorand == 2)
104 { 105 {
105 if (bit == 0) 106 /* generate patterns that are more likely to trigger BN
107 library bugs */
108 int i;
109 unsigned char c;
110
111 for (i = 0; i < bytes; i++)
112 {
113 RAND_pseudo_bytes(&c, 1);
114 if (c >= 128 && i > 0)
115 buf[i] = buf[i-1];
116 else if (c < 42)
117 buf[i] = 0;
118 else if (c < 84)
119 buf[i] = 255;
120 }
121 }
122#endif
123
124 if (top != -1)
125 {
126 if (top)
106 { 127 {
107 buf[0]=1; 128 if (bit == 0)
108 buf[1]|=0x80; 129 {
130 buf[0]=1;
131 buf[1]|=0x80;
132 }
133 else
134 {
135 buf[0]|=(3<<(bit-1));
136 }
109 } 137 }
110 else 138 else
111 { 139 {
112 buf[0]|=(3<<(bit-1)); 140 buf[0]|=(1<<bit);
113 buf[0]&= ~(mask<<1);
114 } 141 }
115 } 142 }
116 else 143 buf[0] &= ~mask;
117 { 144 if (bottom) /* set bottom bit if requested */
118 buf[0]|=(1<<bit);
119 buf[0]&= ~(mask<<1);
120 }
121 if (bottom) /* set bottom bits to whatever odd is */
122 buf[bytes-1]|=1; 145 buf[bytes-1]|=1;
123 if (!BN_bin2bn(buf,bytes,rnd)) goto err; 146 if (!BN_bin2bn(buf,bytes,rnd)) goto err;
124 ret=1; 147 ret=1;
@@ -140,3 +163,61 @@ int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
140 { 163 {
141 return bnrand(1, rnd, bits, top, bottom); 164 return bnrand(1, rnd, bits, top, bottom);
142 } 165 }
166
167#if 1
168int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
169 {
170 return bnrand(2, rnd, bits, top, bottom);
171 }
172#endif
173
174/* random number r: 0 <= r < range */
175int BN_rand_range(BIGNUM *r, BIGNUM *range)
176 {
177 int n;
178
179 if (range->neg || BN_is_zero(range))
180 {
181 BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE);
182 return 0;
183 }
184
185 n = BN_num_bits(range); /* n > 0 */
186
187 if (n == 1)
188 {
189 if (!BN_zero(r)) return 0;
190 }
191 else if (BN_is_bit_set(range, n - 2))
192 {
193 do
194 {
195 /* range = 11..._2, so each iteration succeeds with probability >= .75 */
196 if (!BN_rand(r, n, -1, 0)) return 0;
197 }
198 while (BN_cmp(r, range) >= 0);
199 }
200 else
201 {
202 /* range = 10..._2,
203 * so 3*range (= 11..._2) is exactly one bit longer than range */
204 do
205 {
206 if (!BN_rand(r, n + 1, -1, 0)) return 0;
207 /* If r < 3*range, use r := r MOD range
208 * (which is either r, r - range, or r - 2*range).
209 * Otherwise, iterate once more.
210 * Since 3*range = 11..._2, each iteration succeeds with
211 * probability >= .75. */
212 if (BN_cmp(r ,range) >= 0)
213 {
214 if (!BN_sub(r, r, range)) return 0;
215 if (BN_cmp(r, range) >= 0)
216 if (!BN_sub(r, r, range)) return 0;
217 }
218 }
219 while (BN_cmp(r, range) >= 0);
220 }
221
222 return 1;
223 }