Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit35c675a

Browse files
committed
Fortuna fixes. Marko Kreen
1 parent2787db9 commit35c675a

File tree

5 files changed

+193
-88
lines changed

5 files changed

+193
-88
lines changed

‎contrib/pgcrypto/fortuna.c

Lines changed: 108 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2727
* SUCH DAMAGE.
2828
*
29-
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.3 2005/07/18 17:09:01 tgl Exp $
29+
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.4 2005/07/18 17:12:54 tgl Exp $
3030
*/
3131

3232
#include"postgres.h"
@@ -94,14 +94,16 @@
9494
/* for one big request, reseed after this many bytes */
9595
#defineRESEED_BYTES(1024*1024)
9696

97+
/*
98+
* Skip reseed if pool 0 has less than this many
99+
* bytes added since last reseed.
100+
*/
101+
#definePOOL0_FILL(256/8)
97102

98103
/*
99104
* Algorithm constants
100105
*/
101106

102-
/* max sources */
103-
#defineMAX_SOURCES8
104-
105107
/* Both cipher key size and hash result size */
106108
#defineBLOCK32
107109

@@ -118,9 +120,11 @@ struct fortuna_state {
118120
uint8key[BLOCK];
119121
MD_CTXpool[NUM_POOLS];
120122
CIPH_CTXciph;
121-
unsignedsource_pos[MAX_SOURCES];
122123
unsignedreseed_count;
123124
structtimevallast_reseed_time;
125+
unsignedpool0_bytes;
126+
unsignedrnd_pos;
127+
intcounter_init;
124128
};
125129
typedefstructfortuna_stateFState;
126130

@@ -161,7 +165,6 @@ static void md_result(MD_CTX *ctx, uint8 *dst)
161165
memset(&tmp,0,sizeof(tmp));
162166
}
163167

164-
165168
/*
166169
* initialize state
167170
*/
@@ -173,6 +176,32 @@ static void init_state(FState *st)
173176
md_init(&st->pool[i]);
174177
}
175178

179+
/*
180+
* Endianess does not matter.
181+
* It just needs to change without repeating.
182+
*/
183+
staticvoidinc_counter(FState*st)
184+
{
185+
uint32*val= (uint32*)st->counter;
186+
if (++val[0])
187+
return;
188+
if (++val[1])
189+
return;
190+
if (++val[2])
191+
return;
192+
++val[3];
193+
}
194+
195+
/*
196+
* This is called 'cipher in counter mode'.
197+
*/
198+
staticvoidencrypt_counter(FState*st,uint8*dst)
199+
{
200+
ciph_encrypt(&st->ciph,st->counter,dst);
201+
inc_counter(st);
202+
}
203+
204+
176205
/*
177206
* The time between reseed must be at least RESEED_INTERVAL
178207
* microseconds.
@@ -207,9 +236,8 @@ static void reseed(FState *st)
207236
MD_CTXkey_md;
208237
uint8buf[BLOCK];
209238

210-
/* check frequency */
211-
if (too_often(st))
212-
return;
239+
/* set pool as empty */
240+
st->pool0_bytes=0;
213241

214242
/*
215243
* Both #0 and #1 reseed would use only pool 0.
@@ -243,82 +271,99 @@ static void reseed(FState *st)
243271
memset(buf,0,BLOCK);
244272
}
245273

274+
/*
275+
* Pick a random pool. This uses key bytes as random source.
276+
*/
277+
staticunsignedget_rand_pool(FState*st)
278+
{
279+
unsignedrnd;
280+
281+
/*
282+
* This slightly prefers lower pools - thats OK.
283+
*/
284+
rnd=st->key[st->rnd_pos] %NUM_POOLS;
285+
286+
st->rnd_pos++;
287+
if (st->rnd_pos >=BLOCK)
288+
st->rnd_pos=0;
289+
290+
returnrnd;
291+
}
292+
246293
/*
247294
* update pools
248295
*/
249-
staticvoidadd_entropy(FState*st,unsignedsrc_id,constuint8*data,unsignedlen)
296+
staticvoidadd_entropy(FState*st,constuint8*data,unsignedlen)
250297
{
251298
unsignedpos;
252299
uint8hash[BLOCK];
253300
MD_CTXmd;
254301

255-
/* just in case there's a bug somewhere */
256-
if (src_id >=MAX_SOURCES)
257-
src_id=USER_ENTROPY;
258-
259302
/* hash given data */
260303
md_init(&md);
261304
md_update(&md,data,len);
262305
md_result(&md,hash);
263306

264-
/* update pools round-robin manner */
265-
pos=st->source_pos[src_id];
307+
/*
308+
* Make sure the pool 0 is initialized,
309+
* then update randomly.
310+
*/
311+
if (st->reseed_count==0&&st->pool0_bytes<POOL0_FILL)
312+
pos=0;
313+
else
314+
pos=get_rand_pool(st);
266315
md_update(&st->pool[pos],hash,BLOCK);
267316

268-
if (++pos >=NUM_POOLS)
269-
pos=0;
270-
st->source_pos[src_id]=pos;
317+
if (pos==0)
318+
st->pool0_bytes+=len;
271319

272320
memset(hash,0,BLOCK);
273321
memset(&md,0,sizeof(md));
274322
}
275323

276324
/*
277-
* Endianess does not matter.
278-
* It just needs to change without repeating.
325+
* Just take 2 next blocks as new key
279326
*/
280-
staticvoidinc_counter(FState*st)
327+
staticvoidrekey(FState*st)
281328
{
282-
uint32*val= (uint32*)st->counter;
283-
if (++val[0])
284-
return;
285-
if (++val[1])
286-
return;
287-
if (++val[2])
288-
return;
289-
++val[3];
329+
encrypt_counter(st,st->key);
330+
encrypt_counter(st,st->key+CIPH_BLOCK);
331+
ciph_init(&st->ciph,st->key,BLOCK);
332+
}
333+
334+
/*
335+
* Fortuna relies on AES standing known-plaintext attack.
336+
* In case it does not, slow down the attacker by initialising
337+
* the couter to random value.
338+
*/
339+
staticvoidinit_counter(FState*st)
340+
{
341+
/* Use next block as counter. */
342+
encrypt_counter(st,st->counter);
343+
344+
/* Hide the key. */
345+
rekey(st);
346+
347+
/* The counter can be shuffled only once. */
348+
st->counter_init=1;
290349
}
291350

292351
staticvoidextract_data(FState*st,unsignedcount,uint8*dst)
293352
{
294353
unsignedn;
295354
unsignedblock_nr=0;
296355

297-
/*
298-
* Every request should be with different key,
299-
* if possible.
300-
*/
301-
reseed(st);
356+
/* Can we reseed? */
357+
if (st->pool0_bytes >=POOL0_FILL&& !too_often(st))
358+
reseed(st);
302359

303-
/*
304-
* If the reseed didn't happen, don't use the old data
305-
* rather encrypt again.
306-
*/
360+
/* Is counter initialized? */
361+
if (!st->counter_init)
362+
init_counter(st);
307363

308364
while (count>0) {
309-
/* must not give out too many bytes with one key */
310-
if (block_nr> (RESEED_BYTES /CIPH_BLOCK))
311-
{
312-
reseed(st);
313-
block_nr=0;
314-
}
315-
316365
/* produce bytes */
317-
ciph_encrypt(&st->ciph,st->counter,st->result);
318-
block_nr++;
319-
320-
/* prepare for next time */
321-
inc_counter(st);
366+
encrypt_counter(st,st->result);
322367

323368
/* copy result */
324369
if (count>CIPH_BLOCK)
@@ -328,7 +373,17 @@ static void extract_data(FState *st, unsigned count, uint8 *dst)
328373
memcpy(dst,st->result,n);
329374
dst+=n;
330375
count-=n;
376+
377+
/* must not give out too many bytes with one key */
378+
block_nr++;
379+
if (block_nr> (RESEED_BYTES /CIPH_BLOCK))
380+
{
381+
rekey(st);
382+
block_nr=0;
383+
}
331384
}
385+
/* Set new key for next request. */
386+
rekey(st);
332387
}
333388

334389
/*
@@ -338,7 +393,7 @@ static void extract_data(FState *st, unsigned count, uint8 *dst)
338393
staticFStatemain_state;
339394
staticintinit_done=0;
340395

341-
voidfortuna_add_entropy(unsignedsrc_id,constuint8*data,unsignedlen)
396+
voidfortuna_add_entropy(constuint8*data,unsignedlen)
342397
{
343398
if (!init_done)
344399
{
@@ -347,7 +402,7 @@ void fortuna_add_entropy(unsigned src_id, const uint8 *data, unsigned len)
347402
}
348403
if (!data|| !len)
349404
return;
350-
add_entropy(&main_state,src_id,data,len);
405+
add_entropy(&main_state,data,len);
351406
}
352407

353408
voidfortuna_get_bytes(unsignedlen,uint8*dst)

‎contrib/pgcrypto/fortuna.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,14 @@
2626
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2727
* SUCH DAMAGE.
2828
*
29-
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.h,v 1.1 2005/07/10 13:46:28 momjian Exp $
29+
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.h,v 1.2 2005/07/18 17:12:54 tgl Exp $
3030
*/
3131

3232
#ifndef__FORTUNA_H
3333
#define__FORTUNA_H
3434

35-
/*
36-
* Event source ID's
37-
*/
38-
#defineSYSTEM_ENTROPY0
39-
#defineUSER_ENTROPY1
40-
4135
voidfortuna_get_bytes(unsignedlen,uint8*dst);
42-
voidfortuna_add_entropy(unsignedsrc_id,constuint8*data,unsignedlen);
36+
voidfortuna_add_entropy(constuint8*data,unsignedlen);
4337

4438
#endif
4539

‎contrib/pgcrypto/internal.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2727
* SUCH DAMAGE.
2828
*
29-
* $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.21 2005/07/18 17:09:01 tgl Exp $
29+
* $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.22 2005/07/18 17:12:54 tgl Exp $
3030
*/
3131

3232
#include"postgres.h"
@@ -42,9 +42,22 @@
4242
#include"fortuna.h"
4343

4444
/*
45-
*How often to try to acquire system entropy. (In seconds)
45+
*System reseeds should be separated at least this much.
4646
*/
47-
#defineSYSTEM_RESEED_FREQ(3*60*60)
47+
#defineSYSTEM_RESEED_MIN(20*60)/* 20 min */
48+
/*
49+
* How often to roll dice.
50+
*/
51+
#defineSYSTEM_RESEED_CHECK_TIME(10*60)/* 10 min */
52+
/*
53+
* The chance is x/256 that the reseed happens.
54+
*/
55+
#defineSYSTEM_RESEED_CHANCE(4)/* 256/4 * 10min ~ 10h */
56+
57+
/*
58+
* If this much time has passed, force reseed.
59+
*/
60+
#defineSYSTEM_RESEED_MAX(12*60*60)/* 12h */
4861

4962

5063
#ifndefMD5_DIGEST_LENGTH
@@ -823,20 +836,40 @@ px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
823836
}
824837

825838
statictime_tseed_time=0;
839+
statictime_tcheck_time=0;
826840

827841
staticvoidsystem_reseed(void)
828842
{
829843
uint8buf[1024];
830844
intn;
831845
time_tt;
846+
intskip=1;
832847

833848
t=time(NULL);
834-
if (seed_time&& (t-seed_time)<SYSTEM_RESEED_FREQ)
849+
850+
if (seed_time==0)
851+
skip=0;
852+
elseif ((t-seed_time)<SYSTEM_RESEED_MIN)
853+
skip=1;
854+
elseif ((t-seed_time)>SYSTEM_RESEED_MAX)
855+
skip=0;
856+
elseif (!check_time|| (t-check_time)>SYSTEM_RESEED_CHECK_TIME)
857+
{
858+
check_time=t;
859+
860+
/* roll dice */
861+
px_get_random_bytes(buf,1);
862+
skip=buf[0] >=SYSTEM_RESEED_CHANCE;
863+
}
864+
/* clear 1 byte */
865+
memset(buf,0,sizeof(buf));
866+
867+
if (skip)
835868
return;
836869

837870
n=px_acquire_system_randomness(buf);
838871
if (n>0)
839-
fortuna_add_entropy(SYSTEM_ENTROPY,buf,n);
872+
fortuna_add_entropy(buf,n);
840873

841874
seed_time=t;
842875
memset(buf,0,sizeof(buf));
@@ -854,7 +887,7 @@ int
854887
px_add_entropy(constuint8*data,unsignedcount)
855888
{
856889
system_reseed();
857-
fortuna_add_entropy(USER_ENTROPY,data,count);
890+
fortuna_add_entropy(data,count);
858891
return0;
859892
}
860893

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp