En ole aiemmin kuvannut makefile tiedostoa, tämä on ensimmäinen. Makefile:n avulla voidaan automatisoida ohjelman käännökset kuvaamalla ne ns makefile tiedostoon. Seuraavassa makefile:ssä määritellään viisi tavoitetta: newressu, newressuw, newressum, fort ja sha256. Newressu on versio newressusta, jossa on mukana fort (sha256) ja ei ole web satunnaislukujen hakua. Newressuw on kuten edellinen, mutta mukana on myös web satunnaislukujen haku. newressum on ns vanha versio, jossa ei ole fort:ia.
Näissä tavoitteissa tarvittavat objektitiedostot on listattu objs loppuisissa listoissa kuten: newressuobjs, newressuwobjs jne…
Joissakin kohteissa tarvitaan erilaisia #define määrityksiä, ja ne on eroteltu tiedoston nimen lisäjatkeella kuten newressu.mfs.o, jossa jatke on mfs ja tarvittavat #define määritteet ovat MAIN, FORT ja SHA256.
CC = cc
CFLAGS = -g -Wall -Wno-pointer-sign
newressuobjs = newressu.mfs.o fort.o sha256.o intelrandom.o webrandom.o commandrandom.o
newressuwobjs = newressu.mfs.o fort.w.o sha256.o intelrandom.o webrandom.o commandrandom.o
newressumobjs = newressu.m.o
sha256objs = sha256.m.o
fortobjs = fort.m.o sha256.o newressu.o intelrandom.o webrandom.o commandrandom.o
all: newressu newressuw newressum sha256 fort
newressu: $(newressuobjs)
cc $(CFLAGS) $(newressuobjs) -o newressu -lssl
newressuw: $(newressuwobjs)
cc $(CFLAGS) $(newressuwobjs) -o newressuw -lssl
newressum: $(newressumobjs)
cc $(CFLAGS) $(newressumobjs) -o newressum
sha256: $(sha256objs)
cc $(CFLAGS) $(sha256objs) -o sha256
fort: $(fortobjs)
cc $(CFLAGS) $(fortobjs) -o fort -lssl
%.mfs.o: %.c
$(CC) $(CFLAGS) -DMAIN -DFORT -DSHA256 -c -o $@ $<
%.m.o: %.c
$(CC) $(CFLAGS) -DMAIN -c -o $@ $<
%.w.o: %.c
$(CC) $(CFLAGS) -DFORT_USE_WEB -c -o $@ $<
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f *~ \#*\# *.o
Komennolla make clean all voidaan poistaa aiempi versio ja tehdä kaikki käännökset uudestaan: Ensimmäinen rm rivi on ns clean tavoitteen rivi. Seuraavat 6 riviä kääntävät newressu:n sorsia muodostaen objekteja. Seitsemäs rivi linkkaa newressun objektit ajettavaksi tiedostoksi newressu. Loput rivit tekevät saman newressuw:lle newressum:lle sha256:lle ja fort:lle.
Jos muuttelet clean tavoitteen rm komentoa, kannattaa olla huolellinen, tai jopa tehdä kopio hakemistosta tai levystä. Pieni virhe rm komennossa voi aiheuttaa koko hakemiston tai pahimmassa tapauksessa levyn tyhjentymisen.
$ make clean all
rm -f *~ \#*\# *.o
cc -g -Wall -Wno-pointer-sign -DMAIN -DFORT -DSHA256 -c -o newressu.mfs.o newressu.c
cc -g -Wall -Wno-pointer-sign -c -o fort.o fort.c
cc -g -Wall -Wno-pointer-sign -c -o sha256.o sha256.c
cc -g -Wall -Wno-pointer-sign -c -o intelrandom.o intelrandom.c
cc -g -Wall -Wno-pointer-sign -c -o webrandom.o webrandom.c
cc -g -Wall -Wno-pointer-sign -c -o commandrandom.o commandrandom.c
cc -g -Wall -Wno-pointer-sign newressu.mfs.o fort.o sha256.o intelrandom.o webrandom.o commandrandom.o -o newressu -lssl
cc -g -Wall -Wno-pointer-sign -DFORT_USE_WEB -c -o fort.w.o fort.c
cc -g -Wall -Wno-pointer-sign newressu.mfs.o fort.w.o sha256.o intelrandom.o webrandom.o commandrandom.o -o newressuw -lssl
cc -g -Wall -Wno-pointer-sign -DMAIN -c -o newressu.m.o newressu.c
cc -g -Wall -Wno-pointer-sign newressu.m.o -o newressum
cc -g -Wall -Wno-pointer-sign -DMAIN -c -o sha256.m.o sha256.c
cc -g -Wall -Wno-pointer-sign sha256.m.o -o sha256
cc -g -Wall -Wno-pointer-sign -DMAIN -c -o fort.m.o fort.c
cc -g -Wall -Wno-pointer-sign -c -o newressu.o newressu.c
cc -g -Wall -Wno-pointer-sign fort.m.o sha256.o newressu.o intelrandom.o webrandom.o commandrandom.o -o fort -lssl
Make kääntää vain ne tiedostot, jotka tarvitsevat käännöstä. Seuraava kuva näyttää kun sha256.c tiedoston päiväykset päivitetään touch komennolla, näin se näyttää uudemmalta kuin sen kohdetiedosto sha256.o. Tällöin se käännetään ja näin muodostetaan uusi sha256.o tiedosto. Seuraavaksi tehdään tiedoston sha256.o sisältävät linkkaukset uudestaan.
$ touch sha256.c
$ make
cc -g -Wall -Wno-pointer-sign -c -o sha256.o sha256.c
cc -g -Wall -Wno-pointer-sign newressu.mfs.o fort.o sha256.o intelrandom.o webrandom.o commandrandom.o -o newressu -lssl
cc -g -Wall -Wno-pointer-sign newressu.mfs.o fort.w.o sha256.o intelrandom.o webrandom.o commandrandom.o -o newressuw -lssl
cc -g -Wall -Wno-pointer-sign -DMAIN -c -o sha256.m.o sha256.c
cc -g -Wall -Wno-pointer-sign sha256.m.o -o sha256
cc -g -Wall -Wno-pointer-sign fort.m.o sha256.o newressu.o intelrandom.o webrandom.o commandrandom.o -o fort -lssl
Sitten fort:in varsinaisiin sorsamuutoksiin: aiemmin tapahtuman käsittelyssä oli enemmän modeja, päättelin kuitenkin että tasapainoisen tuloksen saa, jos täytetään modella 1 peräkkäisiä puskureita puskureiden alusta loppuun. Jos täytetään vain tyhjät puskurit muihin puskureihin ei kerry paljon satunnaisuutta. Jos kuitenkin haluat, voit tietenkin kopioida haluamasi moden aiemmasta postista.
void fort_add_random_event(int *pool, int source, int mode, int len, unsigned char *buf)
{
while(len>1 && buf[len-1]==0)
len--;
HashUpdate(&fort_pools[*pool].pool, buf, len);
fort_pools[*pool].length+=len; // (unsigned long)2097152*16384;
#ifdef DEBUG10
if(event_id < 65536) {
FILE *fp1;
if((fp1=fopen(fort_events_file, "a"))!=NULL) {
fprintf(fp1,"id=%d", event_id);
fprintf(fp1,", source=%02d", source);
fprintf(fp1,", pool=%02d", *pool);
fprintf(fp1,", mode=%d", mode);
fprintf(fp1,", len=%d", len);
fprintf(fp1,", data=");
for(int c=0;c<len;c++)
fprintf(fp1,"%02x", buf[c]);
fprintf(fp1,"\n");
fflush(fp1);
fclose(fp1);
event_id++;
}
}
#endif
switch(mode) {
case 1:
(*pool) = ((*pool)+1) % FORT_POOLS;
break;
case 3:
break; // caller decides next pool
}
}
Reseed rutiinista on poistettu fort_pools raportti: nyt fort_pools raportti tulostetaan konsolille (stdout).
void fort_reseed(int len, unsigned char *buf)
{
HashCtx hash;
FORT_INTERNAL_EVENTS_START(22)
hash_init(&hash);
hash_update(&hash, fort_key, sizeof(fort_key));
hash_update(&hash, (unsigned char *)&cvar,
sizeof(cvar));
hash_update(&hash, buf, len);
hash_final(fort_key, &hash);
inccvar();
memset(&hash, 0, sizeof(hash));
if(fort_next_save != 0) {
IUTIME seconds;
seconds = getseconds();
char timezone[10];
strftime(timezone, sizeof(timezone), "%Z",
localtime((time_t *)&seconds) );
if(strcmp(current_timezone,timezone)) {
fort_next_save=1;
strcpy(current_timezone,timezone);
}
if(fort_next_save != 0 &&
seconds >= fort_next_save) {
IUTIME diff=
timegm(localtime((time_t *)&seconds))-seconds;
fort_next_save = seconds -
((seconds+diff) %
FORT_SECONDS_BETWEEN_SAVES) +
FORT_SECONDS_BETWEEN_SAVES;
fort_save();
}
}
FORT_INTERNAL_EVENTS_END(23)
}
fort_random_datasta on poistettu koodi, joka haki “vajaaseen” puskuriin lisäbittejä ressu:sta: Nyt koodi toimii siten, että uudelleenavainnus tehdään jos edellisestä avainnuksesta on kulunut 1/10 sekuntia ja ensimmäiseen puskuriin on kertynyt FORT_MIN_POOL_SIZE merkkiä.
Aliohjelmaan on myös lisätty dump_pools_data kutsu, jolla tulostetaan tämänhetkinen puskureiden tilanne stdout:tiin (jos –fortverbose on päällä). Aliohjelmaan on myös lisätty fort_mix kutsu, joka hakee satunnaisuutta verkosta tai paikallisista lähteistä.
void fort_random_data(int len, unsigned char *buf)
{
int c;
IUTIME tenths;
HashCtx hash;
unsigned char buffer[HashLen];
FORT_INTERNAL_EVENTS_START(24)
if(fort_verbose)
dump_pools_data(stdout,"reseed start");
tenths=gettenths();
if( (fort_next_reseed == 0) ||
(fort_next_reseed <= tenths &&
fort_pools[0].length >=
FORT_MIN_POOL_SIZE) ) {
fort_mix();
// next tenth of a second
fort_next_reseed = tenths + 1;
fort_reseed_count++;
hash_init(&hash);
c=0;
while(c < FORT_POOLS && (fort_reseed_count
% (1<<c)) == 0) {
FORT_INTERNAL_EVENTS_START(25)
hash_final(buffer, &fort_pools[c].pool);
hash_update(&hash, buffer, sizeof(buffer));
fort_pools[c].length = 0;
HashInit(&fort_pools[c].pool);
// save earlier pool to new one
hash_update(&fort_pools[c].pool,
buffer, sizeof(buffer));
c++;
FORT_INTERNAL_EVENTS_END(26)
}
hash_update(&hash, (unsigned char *)
&cvar, sizeof(cvar));
hash_final(buffer, &hash);
fort_reseed(sizeof(buffer), buffer);
// Forget hash context
memset(&hash, 0, sizeof(hash));
// Forget reseed key
memset(buffer, 0, sizeof(buffer));
inccvar();
if(fort_verbose)
dump_pools_data(stdout,"reseed end");
}
fort_pseudo_random_data(len, buf);
FORT_INTERNAL_EVENTS_END(27)
}
Lisätty _xor loppuiset versiot kutsuista fort_pseudo_random_data ja fort_random_data.
void fort_pseudo_random_data_xor(int len,
unsigned char *buf)
{
unsigned char tmp[HashLen];
unsigned int n, blockbytes;
#ifdef DEBUG18
int d=0;
#endif
FORT_INTERNAL_EVENTS_START(18)
blockbytes = 0;
while(len != 0) {
FORT_INTERNAL_EVENTS_START(19)
fort_rekey(tmp);
n = (len<HashLen) ? len : HashLen;
#ifdef DEBUG18
if(fort_partial_line)
fprintf(stdout,"\n");
fprintf(stdout,"buf(%02x): ",d++);
for(int c=0;c<n;c++)
fprintf(stdout," %02x",buf[c]);
fprintf(stdout,"\ntmp: ");
for(int c=0;c<n;c++)
fprintf(stdout," %02x",tmp[c]);
fprintf(stdout,"\nsum: ");
for(int c=0;c<n;c++)
fprintf(stdout," %02x",buf[c]^tmp[c]);
fprintf(stdout,"\n");
#endif
for(int c=0;c<n;c++)
buf[c]^=tmp[c];
buf += n;
len -= n;
blockbytes += n;
// rekey every 1048576 bytes if data left
if(blockbytes >= FORT_PSEUDO_LIMIT &&
len > 0) {
fort_rekey(fort_key);
blockbytes = 0;
}
FORT_INTERNAL_EVENTS_END(20)
}
fort_rekey(fort_key);
// Forget last bytes
memset(tmp, 0, sizeof(tmp));
FORT_INTERNAL_EVENTS_END(21)
}
void fort_random_data_xor(int len, unsigned char *buf)
{
int c;
IUTIME tenths;
HashCtx hash;
unsigned char buffer[HashLen];
FORT_INTERNAL_EVENTS_START(24)
if(fort_verbose)
dump_pools_data(stdout,"reseed start");
tenths=gettenths();
if( (fort_next_reseed == 0) ||
(fort_next_reseed <= tenths &&
fort_pools[0].length >=
FORT_MIN_POOL_SIZE) ) {
fort_mix();
// next tenth of a second
fort_next_reseed = tenths + 1;
fort_reseed_count++;
hash_init(&hash);
c=0;
while(c < FORT_POOLS && (fort_reseed_count
% (1<<c)) == 0) {
FORT_INTERNAL_EVENTS_START(25)
hash_final(buffer, &fort_pools[c].pool);
hash_update(&hash, buffer, sizeof(buffer));
fort_pools[c].length = 0;
HashInit(&fort_pools[c].pool);
// save earlier pool to new one
hash_update(&fort_pools[c].pool,
buffer, sizeof(buffer));
c++;
FORT_INTERNAL_EVENTS_END(26)
}
hash_update(&hash, (unsigned char *)
&cvar, sizeof(cvar));
hash_final(buffer, &hash);
fort_reseed(sizeof(buffer), buffer);
// Forget hash context
memset(&hash, 0, sizeof(hash));
// Forget reseed key
memset(buffer, 0, sizeof(buffer));
inccvar();
if(fort_verbose)
dump_pools_data(stdout,"random_data_xor end");
}
fort_pseudo_random_data_xor(len, buf);
FORT_INTERNAL_EVENTS_END(27)
}
Muutettu dump_pools rutiinia siten että se tekee raportin stdout:iin:
void dump_pools_data(FILE *fp1, char *header)
{
int c;
unsigned char readable[10];
if(fort_partial_line) {
fprintf(fp1,"\n");
fort_partial_line=0;
}
fprintf(fp1,"%-27s", header);
for(c=0;c<FORT_POOLS;c++) {
if(c>0 && c%FORT_DUMP_POOLS_WIDTH==0)
fprintf(fp1,"\n%-27s","");
readable_length(readable,
fort_pools[c].length);
fprintf(fp1,"%*s",
FORT_DUMP_POOLS_FIELD_WIDTH,
readable);
}
fprintf(fp1,"\n");
}
void dump_pools(char *header)
{
if(fort_verbose)
dump_pools_data(stdout,header);
}
Lisätty fort_mix rutiini, joka hakee satunnaisuutta webistä tai/ja paikallisista lähteistä: Seuraavat määritykset kertovat kuinka usein satunnaisuutta päivitetään. Paikalliset haetaan tässä tunnin välein ja web satunnaisuus 12 tunnin välein. Jos satunnaisuutta haetaan web lähteistä sitä haetaan aina sen jälkeen myös paikallisista lähteistä.
Satunnaisuuden haku web:istä on melko hidasta, ja näin web haku onkin poistettu newressu perusversiosta. Jos haluat web:in satunnaisuuden mukaan käytä newressuw komentoa.
Paikallisissa komennoissa ei voi olla newressu:n –fort kytkintä, se jää rekursiivisena komentona “luuppiin”.
static IUTIME fort_next_localmix = 0;
#define FORT_SECONDS_BETWEEN_LOCALMIXES 60*60
static IUTIME fort_next_webmix = 0;
#define FORT_SECONDS_BETWEEN_WEBMIXES 12*3600
void fort_mix()
{
int webmix=0, localmix=0;
unsigned char temp[64];
IUTIME seconds;
if(fort_verbose)
dump_pools_data(stdout,"fort_mix");
seconds = getseconds();
webmix=0;
localmix=0;
if(fort_next_webmix == 0 ||
fort_next_webmix <= seconds) {
fort_next_webmix=seconds+FORT_SECONDS_BETWEEN_WEBMIXES;
webmix=1;
localmix=1;
}
if(fort_next_localmix == 0 ||
fort_next_localmix <= seconds) {
fort_next_localmix=seconds+FORT_SECONDS_BETWEEN_LOCALMIXES;
localmix=1;
}
if(!webmix && !localmix)
return;
if(fort_verbose) {
char timebuf[128];
strftime(timebuf, sizeof(timebuf), TIMEFORMAT,
localtime((time_t *)&seconds));
fprintf(stdout,"Fort mix time: %s\n",timebuf);
strftime(timebuf, sizeof(timebuf), TIMEFORMAT,
localtime((time_t *)&fort_next_webmix));
fprintf(stdout,"Next fort webmix: %s\n",timebuf);
strftime(timebuf, sizeof(timebuf), TIMEFORMAT,
localtime((time_t *)&fort_next_localmix));
fprintf(stdout,"Next fort localmix: %s\n",timebuf);
}
fort_internal_random_data_1(sizeof(temp), temp);
fort_reseed(sizeof(temp), temp);
dump_pools("Randomness from ressu");
#if defined FORT_USE_WEB || \
defined FORT_USE_RDRAND || \
defined FORT_USE_RDSEED || \
defined FORT_USE_NEWRESSU_COMMAND
unsigned char hash[HashLen];
#endif
#ifdef FORT_USE_WEB
if(webmix) {
char *webpages[] = {
"https://moijari.com:5001/",
"https://moijari.com:5005/",
"https://moijari.com:5006/",
};
for(int c=0;c<sizeof(webpages)/sizeof(webpages[0]);c++) {
unsigned char *p;
unsigned char scheme[32];
unsigned char host[32];
unsigned char port[10];
unsigned char rest[128];
p=webpages[c];
parse_string(scheme,sizeof(scheme),&p);
if(check_string("://",p)) {
p+=3;
parse_string(host,sizeof(host),&p);
} else {
strcpy(host,scheme);
strcpy(scheme,"http");
}
if(check_string(":",p)) {
p++;
parse_string(port,sizeof(port),&p);
} else {
strcpy(port,"80");
}
if(*p!='/')
strcpy(rest,"/");
else
strcpy(rest,p);
if(fort_verbose) {
fprintf(stdout,"URL:%s ",webpages[c]);
fprintf(stdout,"[scheme:%s]",scheme);
fprintf(stdout,"[host:%s]",host);
fprintf(stdout,"[port:%s]",port);
fprintf(stdout,"[rest:%s]",p);
fflush(stdout);
}
if(!strcmp(scheme,"http"))
fort_hash_http_page(host, port, p, hash);
else if(!strcmp(scheme,"https"))
fort_hash_https_page(host, port, p, hash);
if(fort_verbose) {
fprintf(stdout,"\n");
fflush(stdout);
}
fort_reseed(sizeof(hash), hash);
}
}
#endif // #ifdef FORT_USE_WEB
if(localmix) {
#ifdef FORT_USE_URANDOM
memset(temp, 0, sizeof(temp));
fort_readfile_xor(sizeof(temp), temp,
"/dev/urandom");
fort_reseed(sizeof(temp), temp);
dump_pools("Randomness from urandom");
#endif
#ifdef FORT_USE_RANDOM
memset(temp, 0, sizeof(temp));
fort_readfile_xor(sizeof(temp), temp,
"/dev/random");
fort_reseed(sizeof(temp), temp);
dump_pools("Randomness from random");
#endif
#if defined FORT_USE_RDRAND || \
defined FORT_USE_RDSEED
HashCtx hashctx;
#endif
#ifdef FORT_USE_RDRAND
memset(temp,0,sizeof(temp));
if(rdrand_bytes(sizeof(temp),temp)) {
HashInit(&hashctx);
HashUpdate(&hashctx, (unsigned char *) &cvar,
sizeof(cvar));
HashUpdate(&hashctx, temp, sizeof(temp));
HashFinal(hash, &hashctx);
if(fort_verbose) {
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
fprintf(stdout,"\n");
fflush(stdout);
}
fort_reseed(sizeof(hash), hash);
inccvar();
}
#endif // #ifdef FORT_USE_RDRAND
#ifdef FORT_USE_RDSEED
memset(temp,0,sizeof(temp));
if(rdseed_bytes(sizeof(temp),temp)) {
HashInit(&hashctx);
HashUpdate(&hashctx, (unsigned char *) &cvar,
sizeof(cvar));
HashUpdate(&hashctx, temp, sizeof(temp));
HashFinal(hash, &hashctx);
if(fort_verbose) {
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
fprintf(stdout,"\n");
fflush(stdout);
}
fort_reseed(sizeof(hash), hash);
inccvar();
}
#endif // #ifdef FORT_USE_RDSEED
#ifdef FORT_USE_NEWRESSU_COMMAND
char *commands[] = {
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --bits1024",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --bits2048",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --fast",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --single",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --urandom",
};
for(int c=0;c<sizeof(commands)/sizeof(commands[0]);c++) {
if(strstr(commands[c], "--fort")) {
fprintf(stderr,"%s: fort_mix(): cannot call fort recursively \"%s\"\n",
procname,commands[c]);
} else {
fort_hash_command(commands[c], hash);
fort_reseed(sizeof(hash), hash);
dump_pools("Rand. from newressu");
}
}
#endif // #ifdef FORT_USE_NEWRESSU_COMMAND
}
}
Lyhennetty fort_init() rutiinia: siirretty paikalliset ja web satunnaislukurutiinit edelliseen fort_mix() aliohjelmaan.
void fort_init()
{
int c;
unsigned char temp[64];
if(fort_verbose) {
fprintf(stdout,"hash: %s",
HashName);
fprintf(stdout,", pools: %d*%ld", FORT_POOLS,
sizeof(struct fort_pool));
fprintf(stdout,", HashCtx: %ld",
sizeof(HashCtx));
fprintf(stdout,", hashsize: %d",
HashLen);
fprintf(stdout,"\n");
}
unsigned int save_fort_internal_events;
save_fort_internal_events=fort_internal_events;
fort_internal_events=1;
fort_next_save = 0;
clearcvar();
// first key to fort_key
fort_internal_random_data_1(sizeof(fort_key), fort_key);
dump_pools("Generate fort key w ressu");
// Initialize buffers
for(c=0; c<FORT_POOLS; c++) {
fort_pools[c].length = 0;
HashInit(&fort_pools[c].pool);
}
dump_pools("Initialize buffers");
#ifdef DEBUG10
FILE *fp1;
// Empty events file
if((fp1 = fopen(fort_events_file, "w"))!=NULL)
fclose(fp1);
event_id = 0;
dump_pools("Emptying events");
#endif // #ifdef DEBUG10
// Mix fort key with web + local
// random numbers
fort_mix();
for(c=0; c<FORT_POOLS; c++) {
FORT_INTERNAL_EVENTS_START(31)
fort_internal_random_data_2(sizeof(temp), temp);
hash_update(&fort_pools[c].pool,
temp, sizeof(temp));
FORT_INTERNAL_EVENTS_END(32)
}
dump_pools("Initialize buffers 2");
#ifdef FORT_INTERNAL_EVENTS
if(fort_internal_events) {
// Create some internal events
for(c=0; c<128; c++) {
FORT_INTERNAL_EVENTS_START(34)
fort_internal_random_data_3(sizeof(temp), temp);
FORT_INTERNAL_EVENTS_END(35)
}
}
dump_pools("Internal events");
#endif // #ifdef FORT_INTERNAL_EVENTS
fort_reseed_count = 0;
fort_next_reseed = 0;
// Reseed fort_key with new events
fort_internal_random_data_3(sizeof(temp), temp);
fort_reseed(sizeof(temp), temp);
dump_pools("Reseed");
fort_restore();
dump_pools("Restore");
// Forget temp
memset(temp,0,sizeof(temp));
fort_internal_events = save_fort_internal_events;
//fort_reseed_count = 0;
//fort_next_reseed = 0;
fort_next_save = 1;
}
Newressu:un fortin käyttöön liittyvät uudet rivit:
Fort kytkimen #define
#define INPUT_SINGLE 3
#define INPUT_FORT 6
#define INPUT_URANDOM 8
Fort muutokset ressu_genbyte rutiiniin:
int ressu_genbyte()
{
static unsigned char gent[GENT_SIZE];
static unsigned int gent_pos=0;
unsigned char ch;
if(input==INPUT_RESSU) { // ressu prod
ressu_genbytes(sizeof(ch), &ch);
} else if(input==INPUT_DEBUG) { // ressu debug
ressu_genbytes_debug(sizeof(ch), &ch);
} else {
if(gent_pos==0) {
if(input==INPUT_FAST) // ressu_fast
ressu_genbytes_fast(sizeof(gent),gent);
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(gent),gent);
#ifdef FORT
else if(input==INPUT_FORT) // ressu fort
fort_random_data_xor(sizeof(gent),gent);
#endif
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(gent),gent,urandomfilename);
#ifdef USE_RANDOM
else if(input==INPUT_RANDOM) // random
readfile_xor(sizeof(gent),gent,randomfilename);
#endif
} // if(gent_pos==0
ch=gent[gent_pos];
gent_pos=(gent_pos+1)%sizeof(gent);
}
return(ch);
}
Muutokset newressu:n parametreihin:
} else if(!strcmp("--single",argv[c])) {
input=INPUT_SINGLE;
#ifdef FORT
} else if(!strcmp("--fort",argv[c])) {
input=INPUT_FORT;
} else if(!strcmp("--fortverbose",argv[c])) {
fort_verbose=!fort_verbose;
#endif
} else if(!strcmp("--urandom",argv[c])) {
input=INPUT_URANDOM;
Fort käyttöön tarvittavat rivit newressun sample rutiinissa:
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(buffer),buffer);
#ifdef FORT
else if(input==INPUT_FORT) // ressu fort
fort_random_data_xor(sizeof(buffer),buffer);
#endif
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(buffer),buffer,urandomfilename);
Fort:in tarvitsemat muutokset help() rutiinissa:
{ "newressu --single", "use randomness from single round of ressu" },
#ifdef FORT
{ "newressu --fort", "use randomness from fort" },
#endif
{ "newressu --urandom", "use randomness from /dev/urandom" },
Fort_init():in ajo newressun main rutiinin alussa: newressussa ei yleensä lueta/kirjoiteta satunnaisuustiedostoa, mutta fort sellaisen kirjoittaa. Muutetaan tiedoston nimi newressulle sopivammaksi newressufort.rnd:ksi.
#ifdef FORT
if(input==INPUT_FORT) {
strcpy(fort_random_file,"newressufort.rnd");
//fort_verbose=0;
fort_init();
}
#endif
Fort_save:n ajo newressu main():in lopussa:
#ifdef FORT
if(input==INPUT_FORT) {
fort_save();
}
#endif
Lopuksi pikkumuutos ressun ytimeen, vaihdettu edelliset int muuttujat e ja byte char muuttujiin, koodi nopeutuu parin ändin verran.
#define RR8(byte,bits) ( ((byte) >> (bits)) | ((byte) << (8 - (bits))) )
#define RL8(byte,bits) ( ((byte) >> (8 - (bits))) | ((byte) << (bits)) )
void ressu_genbytes_single(int size, unsigned char *buffer)
{
int c, d;
unsigned char e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = RL8(e,1); // rotate byte left 1 bits
//e = RL8(e,3); // rotate byte left 3 bits
//e = RR8(e,1); // rotate byte right 1 bits
byte = ressu_clockbyte();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
Vielä satunnaisbittejä fort:illa:
$ ./newressu --fort
00000 59818670444809425543162104354361562640340355844080837840544433641
00001 86429255670425150916832717631514962701533107502652385464513081919
00002 76979793152447531086342437196445054777513582519487476941378535629
00003 40767991408879135401047593100792228272345030462623728007130573104
00004 14157104978698455671252478532622021194214885537707758473380527610
00005 57195382289148516698441240384630711158933262341475159938820939915
00006 41857440959364726778308992867020790449123381830117395560384712047
00007 65902370722617522378841616480412046354128476919104801535402728895
00008 69621109409433594842482505526285668086461153173873973262446568296
00009 38436993219274697910526589849396741791725743176705486096314555338
Tässä uuden version kaikki sorsat: ensin Makefile:
CC = cc
CFLAGS = -g -Wall -Wno-pointer-sign
newressuobjs = newressu.mfs.o fort.o sha256.o intelrandom.o webrandom.o commandrandom.o
newressuwobjs = newressu.mfs.o fort.w.o sha256.o intelrandom.o webrandom.o commandrandom.o
newressumobjs = newressu.m.o
sha256objs = sha256.m.o
fortobjs = fort.m.o sha256.o newressu.o intelrandom.o webrandom.o commandrandom.o
all: newressu newressuw newressum sha256 fort
newressu: $(newressuobjs)
cc $(CFLAGS) $(newressuobjs) -o newressu -lssl
newressuw: $(newressuwobjs)
cc $(CFLAGS) $(newressuwobjs) -o newressuw -lssl
newressum: $(newressumobjs)
cc $(CFLAGS) $(newressumobjs) -o newressum
sha256: $(sha256objs)
cc $(CFLAGS) $(sha256objs) -o sha256
fort: $(fortobjs)
cc $(CFLAGS) $(fortobjs) -o fort -lssl
%.mfs.o: %.c
$(CC) $(CFLAGS) -DMAIN -DFORT -DSHA256 -c -o $@ $<
%.m.o: %.c
$(CC) $(CFLAGS) -DMAIN -c -o $@ $<
%.w.o: %.c
$(CC) $(CFLAGS) -DFORT_USE_WEB -c -o $@ $<
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f *~ \#*\# *.o
Sitten fort.c:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/time.h>
#include <errno.h>
#include <openssl/ssl.h>
#include "sha256.h"
#include "newressu.h"
#include "intelrandom.h"
extern unsigned char *procname;
static unsigned char *programname = "fort version 0.51 ©";
static unsigned char *copyright = "Copyright (c) 2020-2021 Jari Kuivaniemi, Helsinki, Finland. Kaikki oikeudet pidätetään!";
#define FORT_INTERNAL_EVENTS 2
#define aDEBUG10 2
#define aDEBUG18 2
#define FORT_XOR_VERSION 2
#define FORT_ORIGINAL_VERSION 2
#include "fort.h"
int fort_events = 1;
int fort_verbose = 0;
#define DEBUG 2
#define FORT_MIN_POOL_SIZE 64
static unsigned int fort_internal_events = 1;
static unsigned int fort_internal_event_mode = 1;
int fort_partial_line = 0;
//#define FORT_USE_WEB 2 // in Makefile
#define FORT_USE_URANDOM 2
#define aFORT_USE_RANDOM 2
#define FORT_USE_NEWRESSU_COMMAND 2
unsigned char fort_random_file[128] = "fort.rnd";
#ifdef DEBUG10
static int event_id = 0;
static char fort_events_file[128] = "fortevents.deb";
#endif
#define FORT_64_POOLS 2
#ifdef FORT_64_POOLS
#define FORT_POOLS 64
typedef unsigned long FORT_COUNTER;
#else
#define FORT_POOLS 32
typedef unsigned int FORT_COUNTER;
#endif
void fort_mix();
unsigned char cvar[16];
void inccvar()
{
int c = 0;
/* 16 bytes, LSB first */
while(++cvar[c] == 0 && c < sizeof(cvar)-1)
c++;
}
void clearcvar()
{
int c;
for(c=0; c < sizeof(cvar); c++)
cvar[c] = 0;
}
static IUTIME gettenths()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return((IUTIME)tv.tv_sec*10 +
(int)tv.tv_usec/100000);
}
static IUTIME getmicroseconds()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return((IUTIME)tv.tv_sec*1000000 +
tv.tv_usec);
}
static IUTIME getseconds()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return((IUTIME)tv.tv_sec);
}
struct fort_pool {
unsigned long length;
HashCtx pool;
};
static struct fort_pool fort_pools[FORT_POOLS];
void fort_add_random_event(int *pool, int source, int mode, int len, unsigned char *buf)
{
while(len>1 && buf[len-1]==0)
len--;
HashUpdate(&fort_pools[*pool].pool, buf, len);
fort_pools[*pool].length+=len; // (unsigned long)2097152*16384;
#ifdef DEBUG10
if(event_id < 65536) {
FILE *fp1;
if((fp1=fopen(fort_events_file, "a"))!=NULL) {
fprintf(fp1,"id=%d", event_id);
fprintf(fp1,", source=%02d", source);
fprintf(fp1,", pool=%02d", *pool);
fprintf(fp1,", mode=%d", mode);
fprintf(fp1,", len=%d", len);
fprintf(fp1,", data=");
for(int c=0;c<len;c++)
fprintf(fp1,"%02x", buf[c]);
fprintf(fp1,"\n");
fflush(fp1);
fclose(fp1);
event_id++;
}
}
#endif
switch(mode) {
case 1:
(*pool) = ((*pool)+1) % FORT_POOLS;
break;
case 3:
break; // caller decides next pool
}
}
void fort_add_random_event_timer_start(IUTIME *micros)
{
*micros = getmicroseconds();
}
void fort_add_random_event_timer_do(int *pool, int source, int mode, IUTIME *micros)
{
unsigned char temp[2];
IUTIME t;
t = getmicroseconds()-*micros;
temp[0] = t & 0xff;
temp[1] = (t>>8) & 0xff;
fort_add_random_event(pool, source, mode,
sizeof(temp), temp);
}
void fort_add_random_event_time(int *pool, int source, int mode)
{
int len;
unsigned char temp[2];
IUTIME t;
static int prev_second=-1;
t = getmicroseconds();
temp[0] = t & 0xff;
temp[1] = (t>>8) & 0xff;
len=2;
if(prev_second==temp[1]) {
len--;
} else {
prev_second=temp[1];
}
fort_add_random_event(pool, source, mode,
len, temp);
}
void fort_add_random_event_split(int *pool, int source, int mode, int len, unsigned char *buf, int size)
{
int n;
while(len != 0) {
n = (size<len)? size:len;
fort_add_random_event(pool, source,
mode, n, buf);
buf += n;
len -= n;
}
}
void hash_init(HashCtx *hash)
{
FORT_INTERNAL_EVENTS_START(10)
HashInit(hash);
FORT_INTERNAL_EVENTS_END(11)
}
void hash_update(HashCtx *hash, unsigned char *data, int len)
{
FORT_INTERNAL_EVENTS_START(12)
HashUpdate(hash, data, len);
FORT_INTERNAL_EVENTS_END(13)
}
void hash_final(unsigned char digest[HashLen], HashCtx *hash)
{
FORT_INTERNAL_EVENTS_START(14)
HashFinal(digest, hash);
FORT_INTERNAL_EVENTS_END(15)
}
static unsigned char fort_key[HashLen];
void fort_rekey(unsigned char *buf)
{
HashCtx hash;
FORT_INTERNAL_EVENTS_START(16)
hash_init(&hash);
hash_update(&hash, fort_key, sizeof(fort_key));
hash_update(&hash, (unsigned char *)&cvar,
sizeof(cvar));
hash_final(buf, &hash);
inccvar();
// Forget hash
memset(&hash, 0, sizeof(hash));
FORT_INTERNAL_EVENTS_END(17)
}
#define FORT_PSEUDO_LIMIT 1048576
#ifdef FORT_ORIGINAL_VERSION
void fort_pseudo_random_data(int len,
unsigned char *buf)
{
unsigned char tmp[HashLen];
unsigned int n, blockbytes;
#ifdef DEBUG18
int d=0;
#endif
FORT_INTERNAL_EVENTS_START(18)
blockbytes = 0;
while(len != 0) {
FORT_INTERNAL_EVENTS_START(19)
fort_rekey(tmp);
n = (len<HashLen) ? len : HashLen;
#ifdef DEBUG18
fprintf(stdout,"\nbuf(%02x): ",d++);
for(int c=0;c<n;c++)
fprintf(stdout," %02x",buf[c]);
fprintf(stdout,"\ntmp: ");
for(int c=0;c<n;c++)
fprintf(stdout," %02x",tmp[c]);
fprintf(stdout,"\nsum: ");
for(int c=0;c<n;c++)
fprintf(stdout," %02x",buf[c]^tmp[c]);
#endif // #ifdef DEBUG18
memcpy(buf, tmp, n);
buf += n;
len -= n;
blockbytes += n;
// rekey every 1048576 bytes if data left
if(blockbytes >= FORT_PSEUDO_LIMIT &&
len > 0) {
fort_rekey(fort_key);
blockbytes = 0;
}
FORT_INTERNAL_EVENTS_END(20)
}
fort_rekey(fort_key);
// Forget last bytes
memset(tmp, 0, sizeof(tmp));
FORT_INTERNAL_EVENTS_END(21)
}
#endif
// use
// $ ./newressu --fort -x -w32 -s2 -l2000 --space | more
// to debug...
#ifdef FORT_XOR_VERSION
void fort_pseudo_random_data_xor(int len,
unsigned char *buf)
{
unsigned char tmp[HashLen];
unsigned int n, blockbytes;
#ifdef DEBUG18
int d=0;
#endif
FORT_INTERNAL_EVENTS_START(18)
blockbytes = 0;
while(len != 0) {
FORT_INTERNAL_EVENTS_START(19)
fort_rekey(tmp);
n = (len<HashLen) ? len : HashLen;
#ifdef DEBUG18
if(fort_partial_line)
fprintf(stdout,"\n");
fprintf(stdout,"buf(%02x): ",d++);
for(int c=0;c<n;c++)
fprintf(stdout," %02x",buf[c]);
fprintf(stdout,"\ntmp: ");
for(int c=0;c<n;c++)
fprintf(stdout," %02x",tmp[c]);
fprintf(stdout,"\nsum: ");
for(int c=0;c<n;c++)
fprintf(stdout," %02x",buf[c]^tmp[c]);
fprintf(stdout,"\n");
#endif
for(int c=0;c<n;c++)
buf[c]^=tmp[c];
buf += n;
len -= n;
blockbytes += n;
// rekey every 1048576 bytes if data left
if(blockbytes >= FORT_PSEUDO_LIMIT &&
len > 0) {
fort_rekey(fort_key);
blockbytes = 0;
}
FORT_INTERNAL_EVENTS_END(20)
}
fort_rekey(fort_key);
// Forget last bytes
memset(tmp, 0, sizeof(tmp));
FORT_INTERNAL_EVENTS_END(21)
}
#endif // #ifdef FORT_XOR_VERSION
// choose one of
// 60 (1 minute)
// 300 (5 minutes)
// 600 (10 minutes)
// 900 (15 minutes)
// 1200 (20 minutes)
// 1800 (30 minutes)
// 3600 (hour)
// 7200 (2 hours)
// 10800 (3 hours)
// 14400 (4 hours)
// 21600 (6 hours)
// 28800 (8 hours)
// 43200 (12 hours)
// 86400 (24 hours)
// to get readable report..
#define FORT_SECONDS_BETWEEN_SAVES 10*60
static IUTIME fort_next_save = 0;
#define TIMEFORMAT "%Z%Y%m%d%H%M%S"
void dump_pools(char *header);
void fort_save();
static char current_timezone[10];
void fort_reseed(int len, unsigned char *buf)
{
HashCtx hash;
FORT_INTERNAL_EVENTS_START(22)
hash_init(&hash);
hash_update(&hash, fort_key, sizeof(fort_key));
hash_update(&hash, (unsigned char *)&cvar,
sizeof(cvar));
hash_update(&hash, buf, len);
hash_final(fort_key, &hash);
inccvar();
memset(&hash, 0, sizeof(hash));
if(fort_next_save != 0) {
IUTIME seconds;
seconds = getseconds();
char timezone[10];
strftime(timezone, sizeof(timezone), "%Z",
localtime((time_t *)&seconds) );
if(strcmp(current_timezone,timezone)) {
fort_next_save=1;
strcpy(current_timezone,timezone);
}
if(fort_next_save != 0 &&
seconds >= fort_next_save) {
IUTIME diff=
timegm(localtime((time_t *)&seconds))-seconds;
fort_next_save = seconds -
((seconds+diff) %
FORT_SECONDS_BETWEEN_SAVES) +
FORT_SECONDS_BETWEEN_SAVES;
fort_save();
}
}
FORT_INTERNAL_EVENTS_END(23)
}
void dump_pools_data(FILE *fp1, char *header);
static FORT_COUNTER fort_reseed_count = 0;
static IUTIME fort_next_reseed = 0;
#ifdef FORT_ORIGINAL_VERSION
void fort_random_data(int len, unsigned char *buf)
{
int c;
IUTIME tenths;
HashCtx hash;
unsigned char buffer[HashLen];
FORT_INTERNAL_EVENTS_START(24)
if(fort_verbose)
dump_pools_data(stdout,"reseed start");
tenths=gettenths();
if( (fort_next_reseed == 0) ||
(fort_next_reseed <= tenths &&
fort_pools[0].length >=
FORT_MIN_POOL_SIZE) ) {
fort_mix();
// next tenth of a second
fort_next_reseed = tenths + 1;
fort_reseed_count++;
hash_init(&hash);
c=0;
while(c < FORT_POOLS && (fort_reseed_count
% (1<<c)) == 0) {
FORT_INTERNAL_EVENTS_START(25)
hash_final(buffer, &fort_pools[c].pool);
hash_update(&hash, buffer, sizeof(buffer));
fort_pools[c].length = 0;
HashInit(&fort_pools[c].pool);
// save earlier pool to new one
hash_update(&fort_pools[c].pool,
buffer, sizeof(buffer));
c++;
FORT_INTERNAL_EVENTS_END(26)
}
hash_update(&hash, (unsigned char *)
&cvar, sizeof(cvar));
hash_final(buffer, &hash);
fort_reseed(sizeof(buffer), buffer);
// Forget hash context
memset(&hash, 0, sizeof(hash));
// Forget reseed key
memset(buffer, 0, sizeof(buffer));
inccvar();
if(fort_verbose)
dump_pools_data(stdout,"reseed end");
}
fort_pseudo_random_data(len, buf);
FORT_INTERNAL_EVENTS_END(27)
}
#endif // #ifdef FORT_ORIGINAL_VERSION
#ifdef FORT_XOR_VERSION
void fort_random_data_xor(int len, unsigned char *buf)
{
int c;
IUTIME tenths;
HashCtx hash;
unsigned char buffer[HashLen];
FORT_INTERNAL_EVENTS_START(24)
if(fort_verbose)
dump_pools_data(stdout,"reseed start");
tenths=gettenths();
if( (fort_next_reseed == 0) ||
(fort_next_reseed <= tenths &&
fort_pools[0].length >=
FORT_MIN_POOL_SIZE) ) {
fort_mix();
// next tenth of a second
fort_next_reseed = tenths + 1;
fort_reseed_count++;
hash_init(&hash);
c=0;
while(c < FORT_POOLS && (fort_reseed_count
% (1<<c)) == 0) {
FORT_INTERNAL_EVENTS_START(25)
hash_final(buffer, &fort_pools[c].pool);
hash_update(&hash, buffer, sizeof(buffer));
fort_pools[c].length = 0;
HashInit(&fort_pools[c].pool);
// save earlier pool to new one
hash_update(&fort_pools[c].pool,
buffer, sizeof(buffer));
c++;
FORT_INTERNAL_EVENTS_END(26)
}
hash_update(&hash, (unsigned char *)
&cvar, sizeof(cvar));
hash_final(buffer, &hash);
fort_reseed(sizeof(buffer), buffer);
// Forget hash context
memset(&hash, 0, sizeof(hash));
// Forget reseed key
memset(buffer, 0, sizeof(buffer));
inccvar();
if(fort_verbose)
dump_pools_data(stdout,"random_data_xor end");
}
fort_pseudo_random_data_xor(len, buf);
FORT_INTERNAL_EVENTS_END(27)
}
#endif // #ifdef FORT_XOR_VERSION
#define FORTCNT 128
static unsigned int fort_cnt = FORTCNT;
static unsigned char fort_bytes[FORTCNT];
static int fort_byte = 999999999;
int fort_random_data_byte()
{
if(fort_byte >= fort_cnt) {
fort_random_data(fort_cnt, fort_bytes);
fort_byte = 0;
}
return(fort_bytes[fort_byte++]);
}
void fort_clear()
{
memset(fort_bytes, 0, fort_cnt);
fort_byte = 999999998;
}
int fort_random_data_byte_limit(int limit)
{
int c;
while((c = fort_random_data_byte())>=
(256/limit)*limit);
return(c % limit);
}
void fort_random_data_buffer(int size,
unsigned char *buffer)
{
int c;
for(c=0; c<size; c++)
buffer[c] ^= fort_random_data_byte();
}
#define aFORT_DUMP_POOLS_BIN 2
#ifdef FORT_DUMP_POOLS_BIN
#define FORT_DUMP_POOLS_HIGH 1023
#define FORT_DUMP_POOLS_DIVIDER 1024
#define FORT_DUMP_POOLS_FIELD_WIDTH 6
#else
#define FORT_DUMP_POOLS_HIGH 999
#define FORT_DUMP_POOLS_DIVIDER 1000
#define FORT_DUMP_POOLS_FIELD_WIDTH 5
#endif
#define FORT_DUMP_POOLS_WIDTH 32
static void readable_length(char *buf,
unsigned long length)
{
int c, low;
// B = byte
// K = kilo 10^3 2^10
// M = mega 10^6 2^20
// G = giga 10^9 2^30
// T = tera 10^12 2^40
// P = peta 10^15 2^50
// E = exa 10^18 2^60
// Z = zetta 10^21 2^70
// Y = yotta 10^24 2^80
char units[] = "BKMGTPEZY";
strcpy(buf,"***");
low=0;
for(c=0; length>=low &&
c<sizeof(units)-1; c++) {
if(length>=low &&
length<=FORT_DUMP_POOLS_HIGH) {
if(units[c]!='B')
sprintf(buf,"%ld%c", length, units[c]);
else
sprintf(buf,"%ld", length);
break;
}
length/=FORT_DUMP_POOLS_DIVIDER;
low=1;
}
}
void dump_pools_data(FILE *fp1, char *header)
{
int c;
unsigned char readable[10];
if(fort_partial_line) {
fprintf(fp1,"\n");
fort_partial_line=0;
}
fprintf(fp1,"%-27s", header);
for(c=0;c<FORT_POOLS;c++) {
if(c>0 && c%FORT_DUMP_POOLS_WIDTH==0)
fprintf(fp1,"\n%-27s","");
readable_length(readable,
fort_pools[c].length);
fprintf(fp1,"%*s",
FORT_DUMP_POOLS_FIELD_WIDTH,
readable);
}
fprintf(fp1,"\n");
}
void dump_pools(char *header)
{
if(fort_verbose)
dump_pools_data(stdout,header);
}
#define FORT_SAVE_SIZE 1024
void fort_save()
{
FILE *fp1;
unsigned char buffer[FORT_SAVE_SIZE];
if((fp1 = fopen(fort_random_file, "w"))
!= NULL) {
fort_pseudo_random_data(sizeof(buffer), buffer);
fwrite(buffer, 1, sizeof(buffer), fp1);
memset(buffer, 0, sizeof(buffer));
fclose(fp1);
}
}
void fort_restore()
{
int d;
FILE *fp1;
unsigned char buffer[FORT_SAVE_SIZE];
if((fp1 = fopen(fort_random_file, "rb"))
!= NULL) {
d = fread(buffer, 1, sizeof(buffer), fp1);
fclose(fp1);
} else {
fort_pseudo_random_data(sizeof(buffer), buffer);
ressu_genbytes(sizeof(buffer), buffer);
d = sizeof(buffer);
}
fort_reseed(d, buffer);
memset(buffer, 0, sizeof(buffer));
fort_save();
}
#if defined FORT_USE_URANDOM || \
defined FORT_USE_RANDOM
static void fort_readfile_xor(int len,
unsigned char *buf,
unsigned char *filename)
{
int c, n, n2;
unsigned char temp[64];
FILE *fp1;
if((fp1 = fopen(filename, "rb"))
!= NULL) {
while(len != 0) {
n = (len < sizeof(temp)) ?
len : sizeof(temp);
n2=fread(temp, 1, n, fp1);
for(c = 0; c < n2; c++)
buf[c] ^= temp[c];
len -= n2;
buf += n2;
}
fclose(fp1);
}
}
#endif
#ifdef FORT_USE_WEB
static void parse_string(unsigned char *string, int size, unsigned char **p2)
{
int count;
unsigned char *p, *q;
p=*p2;
q=string;
count=0;
// uppercase & lowercase letters, '.'
// or utf-8
while(isalnum(*p)||*p=='.'||*p>0x80) {
if(++count<size)
*q++=*p;
p++;
}
*q='\0';
*p2=p;
}
#endif // #ifdef FORT_USE_WEB
#ifdef FORT_USE_WEB
static int check_string(unsigned char *string, unsigned char *p)
{
int ok;
ok=0;
if(!strncmp(string,p,strlen(string))) {
ok=1;
}
return(ok);
}
#endif // #ifdef FORT_USE_WEB
void fort_internal_random_data_1(int size, char *buf)
{
ressu_genbytes(size, buf);
#ifdef FORT_XOR_VERSION
fort_pseudo_random_data_xor(size, buf);
#endif
}
void fort_internal_random_data_2(int size, char *buf)
{
#ifdef FORT_XOR_VERSION
fort_pseudo_random_data_xor(size, buf);
#else
fort_pseudo_random_data(size, buf);
#endif
ressu_genbytes(size, buf);
}
void fort_internal_random_data_3(int size, char *buf)
{
#ifdef FORT_XOR_VERSION
fort_random_data_xor(size, buf);
#else
fort_random_data(size, buf);
#endif
}
static IUTIME fort_next_localmix = 0;
#define FORT_SECONDS_BETWEEN_LOCALMIXES 60*60
static IUTIME fort_next_webmix = 0;
#define FORT_SECONDS_BETWEEN_WEBMIXES 12*3600
void fort_mix()
{
int webmix=0, localmix=0;
unsigned char temp[64];
IUTIME seconds;
if(fort_verbose)
dump_pools_data(stdout,"fort_mix");
seconds = getseconds();
webmix=0;
localmix=0;
if(fort_next_webmix == 0 ||
fort_next_webmix <= seconds) {
fort_next_webmix=seconds+FORT_SECONDS_BETWEEN_WEBMIXES;
webmix=1;
localmix=1;
}
if(fort_next_localmix == 0 ||
fort_next_localmix <= seconds) {
fort_next_localmix=seconds+FORT_SECONDS_BETWEEN_LOCALMIXES;
localmix=1;
}
if(!webmix && !localmix)
return;
if(fort_verbose) {
char timebuf[128];
strftime(timebuf, sizeof(timebuf), TIMEFORMAT,
localtime((time_t *)&seconds));
fprintf(stdout,"Fort mix time: %s\n",timebuf);
strftime(timebuf, sizeof(timebuf), TIMEFORMAT,
localtime((time_t *)&fort_next_webmix));
fprintf(stdout,"Next fort webmix: %s\n",timebuf);
strftime(timebuf, sizeof(timebuf), TIMEFORMAT,
localtime((time_t *)&fort_next_localmix));
fprintf(stdout,"Next fort localmix: %s\n",timebuf);
}
fort_internal_random_data_1(sizeof(temp), temp);
fort_reseed(sizeof(temp), temp);
dump_pools("Randomness from ressu");
#if defined FORT_USE_WEB || \
defined FORT_USE_RDRAND || \
defined FORT_USE_RDSEED || \
defined FORT_USE_NEWRESSU_COMMAND
unsigned char hash[HashLen];
#endif
#ifdef FORT_USE_WEB
if(webmix) {
char *webpages[] = {
"https://moijari.com:5001/",
"https://moijari.com:5005/",
"https://moijari.com:5006/",
};
for(int c=0;c<sizeof(webpages)/sizeof(webpages[0]);c++) {
unsigned char *p;
unsigned char scheme[32];
unsigned char host[32];
unsigned char port[10];
unsigned char rest[128];
p=webpages[c];
parse_string(scheme,sizeof(scheme),&p);
if(check_string("://",p)) {
p+=3;
parse_string(host,sizeof(host),&p);
} else {
strcpy(host,scheme);
strcpy(scheme,"http");
}
if(check_string(":",p)) {
p++;
parse_string(port,sizeof(port),&p);
} else {
strcpy(port,"80");
}
if(*p!='/')
strcpy(rest,"/");
else
strcpy(rest,p);
if(fort_verbose) {
fprintf(stdout,"URL:%s ",webpages[c]);
fprintf(stdout,"[scheme:%s]",scheme);
fprintf(stdout,"[host:%s]",host);
fprintf(stdout,"[port:%s]",port);
fprintf(stdout,"[rest:%s]",p);
fflush(stdout);
}
if(!strcmp(scheme,"http"))
fort_hash_http_page(host, port, p, hash);
else if(!strcmp(scheme,"https"))
fort_hash_https_page(host, port, p, hash);
if(fort_verbose) {
fprintf(stdout,"\n");
fflush(stdout);
}
fort_reseed(sizeof(hash), hash);
}
}
#endif // #ifdef FORT_USE_WEB
if(localmix) {
#ifdef FORT_USE_URANDOM
memset(temp, 0, sizeof(temp));
fort_readfile_xor(sizeof(temp), temp,
"/dev/urandom");
fort_reseed(sizeof(temp), temp);
dump_pools("Randomness from urandom");
#endif
#ifdef FORT_USE_RANDOM
memset(temp, 0, sizeof(temp));
fort_readfile_xor(sizeof(temp), temp,
"/dev/random");
fort_reseed(sizeof(temp), temp);
dump_pools("Randomness from random");
#endif
#if defined FORT_USE_RDRAND || \
defined FORT_USE_RDSEED
HashCtx hashctx;
#endif
#ifdef FORT_USE_RDRAND
memset(temp,0,sizeof(temp));
if(rdrand_bytes(sizeof(temp),temp)) {
HashInit(&hashctx);
HashUpdate(&hashctx, (unsigned char *) &cvar,
sizeof(cvar));
HashUpdate(&hashctx, temp, sizeof(temp));
HashFinal(hash, &hashctx);
if(fort_verbose) {
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
fprintf(stdout,"\n");
fflush(stdout);
}
fort_reseed(sizeof(hash), hash);
inccvar();
}
#endif // #ifdef FORT_USE_RDRAND
#ifdef FORT_USE_RDSEED
memset(temp,0,sizeof(temp));
if(rdseed_bytes(sizeof(temp),temp)) {
HashInit(&hashctx);
HashUpdate(&hashctx, (unsigned char *) &cvar,
sizeof(cvar));
HashUpdate(&hashctx, temp, sizeof(temp));
HashFinal(hash, &hashctx);
if(fort_verbose) {
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
fprintf(stdout,"\n");
fflush(stdout);
}
fort_reseed(sizeof(hash), hash);
inccvar();
}
#endif // #ifdef FORT_USE_RDSEED
#ifdef FORT_USE_NEWRESSU_COMMAND
char *commands[] = {
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --bits1024",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --bits2048",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --fast",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --single",
"/bin/newressu -2 -s16 -w8 -l16 --space --lineno --urandom",
};
for(int c=0;c<sizeof(commands)/sizeof(commands[0]);c++) {
if(strstr(commands[c], "--fort")) {
fprintf(stderr,"%s: fort_mix(): cannot call fort recursively \"%s\"\n",
procname,commands[c]);
} else {
fort_hash_command(commands[c], hash);
fort_reseed(sizeof(hash), hash);
dump_pools("Rand. from newressu");
}
}
#endif // #ifdef FORT_USE_NEWRESSU_COMMAND
}
}
void fort_init()
{
int c;
unsigned char temp[64];
if(fort_verbose) {
fprintf(stdout,"hash: %s",
HashName);
fprintf(stdout,", pools: %d*%ld", FORT_POOLS,
sizeof(struct fort_pool));
fprintf(stdout,", HashCtx: %ld",
sizeof(HashCtx));
fprintf(stdout,", hashsize: %d",
HashLen);
fprintf(stdout,"\n");
}
unsigned int save_fort_internal_events;
save_fort_internal_events=fort_internal_events;
fort_internal_events=1;
fort_next_save = 0;
clearcvar();
// first key to fort_key
fort_internal_random_data_1(sizeof(fort_key), fort_key);
dump_pools("Generate fort key w ressu");
// Initialize buffers
for(c=0; c<FORT_POOLS; c++) {
fort_pools[c].length = 0;
HashInit(&fort_pools[c].pool);
}
dump_pools("Initialize buffers");
#ifdef DEBUG10
FILE *fp1;
// Empty events file
if((fp1 = fopen(fort_events_file, "w"))!=NULL)
fclose(fp1);
event_id = 0;
dump_pools("Emptying events");
#endif // #ifdef DEBUG10
// Mix fort key with web + local
// random numbers
fort_mix();
for(c=0; c<FORT_POOLS; c++) {
FORT_INTERNAL_EVENTS_START(31)
fort_internal_random_data_2(sizeof(temp), temp);
hash_update(&fort_pools[c].pool,
temp, sizeof(temp));
FORT_INTERNAL_EVENTS_END(32)
}
dump_pools("Initialize buffers 2");
#ifdef FORT_INTERNAL_EVENTS
if(fort_internal_events) {
// Create some internal events
for(c=0; c<128; c++) {
FORT_INTERNAL_EVENTS_START(34)
fort_internal_random_data_3(sizeof(temp), temp);
FORT_INTERNAL_EVENTS_END(35)
}
}
dump_pools("Internal events");
#endif // #ifdef FORT_INTERNAL_EVENTS
fort_reseed_count = 0;
fort_next_reseed = 0;
// Reseed fort_key with new events
fort_internal_random_data_3(sizeof(temp), temp);
fort_reseed(sizeof(temp), temp);
dump_pools("Reseed");
fort_restore();
dump_pools("Restore");
// Forget temp
memset(temp,0,sizeof(temp));
fort_internal_events = save_fort_internal_events;
//fort_reseed_count = 0;
//fort_next_reseed = 0;
fort_next_save = 1;
}
void fort_version()
{
fprintf(stderr,"%s",programname); // touch these outside MAIN
fprintf(stderr,", %s\n",copyright);
}
#define aMAIN 2
#ifdef MAIN
unsigned char *procname;
int main(int argc, char *argv[])
{
procname=argv[0];
fort_version();
fort_init();
return(0);
}
#endif // #ifdef MAIN
Fort.h:
/* Perustuu Bruce Schneierin kirjassa esittämään fortuna järjestelmään.
* Written by Jari Kuivaniemi
*/
typedef unsigned long long IUTIME;
extern int fort_verbose;
extern int fort_partial_line;
extern unsigned char fort_random_file[128];
extern unsigned char fort_pools_file[128];
#ifdef DEBUG10
static char fort_events_file[128] = "fortevents.deb";
#endif
unsigned char cvar[16];
void inccvar();
void clearcvar();
void fort_add_random_event(int *pool, int source, int mode, int len, unsigned char *buf);
void fort_add_random_event_timer_start(IUTIME *micros);
void fort_add_random_event_timer_do(int *pool, int source, int mode, IUTIME *millis);
void fort_add_random_event_split(int *pool, int source, int mode, int len, unsigned char *buf,int size);
void fort_add_random_event_time(int *pool, int source, int mode);
void fort_rekey(unsigned char *buf);
void fort_pseudo_random_data(int len,unsigned char *buf);
void fort_pseudo_random_data_xor(int len,unsigned char *buf);
void fort_reseed(int len,unsigned char *buf);
void fort_random_data(int len,unsigned char *buf);
void fort_random_data_xor(int len,unsigned char *buf);
int fort_random_data_byte();
void fort_clear();
int fort_random_data_byte_limit(int limit);
void fort_random_data_buffer(int size, unsigned char *buffer);
void fort_save();
void fort_read_file();
void fort_mix();
void fort_init();
void hash_init(HashCtx *hash);
void hash_update(HashCtx *hash, unsigned char *data, int len);
void hash_final(unsigned char digest[HashLen], HashCtx *hash);
void fort_hash_http_page(unsigned char *host,unsigned char *port, unsigned char *page, unsigned char *hash);
void fort_hash_https_page(unsigned char *host,unsigned char *port, unsigned char *page, unsigned char *hash);
void fort_hash_command(unsigned char *command, unsigned char *hash);
#ifdef FORT_INTERNAL_EVENTS
#define FORT_INTERNAL_EVENTS_START(source) \
IUTIME micros; \
static int \
pool=0, pool2=0; \
if(fort_internal_events) { \
fort_add_random_event_time(&pool, \
source, fort_internal_event_mode); \
fort_add_random_event_timer_start(µs); \
}
#else
#define FORT_INTERNAL_EVENTS_START(source)
#endif
#ifdef FORT_INTERNAL_EVENTS
#define FORT_INTERNAL_EVENTS_END(source) \
if(fort_internal_events) \
fort_add_random_event_timer_do(&pool2, \
source, fort_internal_event_mode, \
µs);
#else
#define FORT_INTERNAL_EVENTS_END(source)
#endif
#ifdef FORT_EVENTS
#define FORT_EVENTS_START(source) \
IUTIME micros; \
static int \
pool=0, pool2=0; \
if(fort_events) { \
fort_add_random_event_time(&pool, \
source, fort_event_mode); \
fort_add_random_event_timer_start(µs); \
}
#else
#define FORT_EVENTS_START(source)
#endif
#ifdef FORT_EVENTS
#define FORT_EVENTS_END(source) \
if(fort_events) \
fort_add_random_event_timer_do(&pool2, \
source, fort_event_mode, \
µs);
#else
#define FORT_EVENTS_END(source)
#endif
Intelrandom.c
#include <stdio.h>
#include <memory.h>
#include "intelrandom.h"
#if defined FORT_USE_RDRAND || \
defined FORT_USE_RDSEED
// see: https://software.intel.com/content/www/us/en/develop/articles/intel-digital-random-number-generator-drng-software-implementation-guide.html
void _cpuid(unsigned int leaf, unsigned int subleaf,
unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d)
{
asm volatile("cpuid"
: "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
: "a" (leaf), "c" (subleaf) );
}
int _is_cpu_vendor(unsigned char *cpuvendor)
{
int ok=0;
unsigned int a, b, c, d;
_cpuid(0, 0, &a, &b, &c, &d);
if(memcmp((char *)(&b), cpuvendor,4)==0 &&
memcmp((char *)(&d), cpuvendor+4,4)==0 &&
memcmp((char *)(&c), cpuvendor+8,4)==0)
ok=1;
return(ok);
}
#endif
#ifdef FORT_USE_RDRAND
int _has_rdrand()
{
int ok=0;
unsigned int a, b, c, d;
_cpuid(1, 0, &a, &b, &c, &d);
if((c & 0x40000000) == 0x40000000) {
ok=1;
}
return(ok);
}
int _rdrand_long(unsigned long *therand)
{
unsigned char ret;
asm volatile("rdrand %0; setc %1"
: "=r" (*therand), "=qm" (ret) );
return(int) ret;
}
int rdrand_bytes(int buflen, unsigned char *buf)
{
int n, ret = 0;
unsigned long l;
if(_is_cpu_vendor("GenuineIntel") && _has_rdrand()) {
if(fort_verbose)
fprintf(stdout,"Intel rdrand");
ret=1;
} else if(_is_cpu_vendor("AuthenticAMD") && _has_rdrand()) {
if(fort_verbose)
fprintf(stdout,"AMD rdrand");
ret=1;
}
if(ret) {
while(buflen > 0) {
if((ret = _rdrand_long(&l)) == 0) // 1 ok, 0 fail
break;
if(fort_verbose)
fprintf(stdout," %016lx",l);
n = (buflen < sizeof(l) ? buflen : sizeof(l));
memcpy(buf, (unsigned char *)&l, n);
buf+=n;
buflen-=n;
}
}
return(ret);
}
#endif // #ifdef FORT_USE_RDRAND
#ifdef FORT_USE_RDSEED
int _has_rdseed()
{
int ok=0;
unsigned int a, b, c, d;
_cpuid(7, 0, &a, &b, &c, &d);
if((b & 0x40000) == 0x40000) {
ok=1;
}
return(ok);
}
int _rdseed_long(unsigned long *therand)
{
unsigned char ret;
asm volatile("rdseed %0; setc %1"
: "=r" (*therand), "=qm" (ret) );
return(int) ret;
}
int rdseed_bytes(int buflen, unsigned char *buf)
{
int n, ret = 0;
unsigned long l;
if(_is_cpu_vendor("GenuineIntel") && _has_rdseed()) {
if(fort_verbose)
fprintf(stdout,"Intel rdseed");
ret=1;
} else if(_is_cpu_vendor("AuthenticAMD") && _has_rdseed()) {
if(fort_verbose)
fprintf(stdout,"AMD rdseed");
ret=1;
}
if(ret) {
while(buflen > 0) {
if((ret = _rdseed_long(&l)) == 0) // 1 ok, 0 fail
break;
if(fort_verbose)
fprintf(stdout," %016lx",l);
n = (buflen < sizeof(l) ? buflen : sizeof(l));
memcpy(buf, (unsigned char *)&l, n);
buf+=n;
buflen-=n;
}
}
return(ret);
}
#endif // #ifdef FORT_USE_RDSEED
Intelrandom.h
#define aFORT_USE_RDRAND 2
#define aFORT_USE_RDSEED 2
int rdrand_bytes(int buflen, unsigned char *buf);
int rdseed_bytes(int buflen, unsigned char *buf);
extern int intelrandom_verbose;
Webrandom.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
#include <errno.h>
#include <openssl/ssl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "sha256.h"
#include "fort.h"
extern unsigned char *procname;
extern int fort_verbose;
#include <stdarg.h>
void dbs_printf(unsigned char **buf, size_t *buf_length, const unsigned char *format, ...)
{
int count;
va_list args;;
va_start(args, format);
count = vsnprintf(*buf, *buf_length, format, args) + 1;
va_end(args);
if(*buf_length < count) {
*buf_length = count;
*buf = realloc(*buf, *buf_length);
va_start(args, format);
count = vsnprintf(*buf, *buf_length, format, args) + 1;
va_end(args);
}
}
int fort_connect(unsigned char *host, unsigned char *port)
{
struct addrinfo hints, *res, *resp;
int s, status;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if((status = getaddrinfo(host, port, &hints, &res)) != 0) {
fprintf(stderr,"\n%s: getaddrinfo", procname);
fprintf(stderr,", status %d", status);
fprintf(stderr,", gai_strerror(): %s", gai_strerror(status));
fprintf(stderr,", errno %d\n", errno);
fflush(stderr);
}
for(resp=res; resp!=NULL; resp = resp->ai_next) {
if((s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol))<0)
continue;
if(connect(s, resp->ai_addr, resp->ai_addrlen) == 0)
break;
close(s);
}
freeaddrinfo(res);
return(s);
}
void fort_hash_http_page(unsigned char *host,unsigned char *port, unsigned char *page, unsigned char *hash) // 202011 JariK
{
int s,status,bytes,total;
if((s = fort_connect(host, port))<0) {
fprintf(stderr,"\n%s: cannot fort_connect()", procname);
fprintf(stderr,", status: %d", s);
fprintf(stderr,", errno: %d" , errno);
perror("fort_connect");
fflush(stderr);
}
unsigned char *format =
"GET %s HTTP/1.0\r\n"
"Host: %s\r\n";
static unsigned char *msg = NULL;
static size_t msg_length=0;
dbs_printf(&msg, &msg_length, format, page, host);
if((status=write(s, msg, strlen(msg)))<0) {
fprintf(stderr, "\n%s: write(), error: %d\n", procname, errno);
perror("write");
fflush(stderr);
}
HashCtx ctx;
char buffer[1024];
HashInit(&ctx);
total=0;
while((bytes = read(s, buffer, sizeof(buffer)))>0) {
//write(1,buffer,bytes);
HashUpdate(&ctx, buffer, bytes);
total+=bytes;
}
HashFinal(hash, &ctx);
if(fort_verbose) {
fprintf(stdout,"fort_hash_http_page:");
fprintf(stdout," %d bytes read", total);
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
}
close(s);
}
void fort_hash_https_page(unsigned char *host,unsigned char *port, unsigned char *page, unsigned char *hash) // 202011 JariK
{
int s, status, bytes, total;
SSL_METHOD *method=NULL;
SSL_CTX *ctx=NULL;
SSL *ssl;
SSL_library_init(); //see: http://h30266.www3.hpe.com/odl/axpos/opsys/vmsos84/BA554_90007/ch04s03.html
OpenSSL_add_ssl_algorithms();
SSL_load_error_strings();
if((method = (SSL_METHOD *)
SSLv23_client_method()) == NULL) {
fprintf(stderr,"\n%s: cannot SSLv3_server_method()", procname);
fflush(stderr);
}
if((ctx=SSL_CTX_new(method)) == NULL) {
fprintf(stderr,"\n%s: cannot SSL_CTX_new()", procname);
fflush(stderr);
}
if((ssl=SSL_new(ctx)) == NULL) {
fprintf(stderr,"\n%s: cannot SSL_new()", procname);
fflush(stderr);
}
if((s = fort_connect(host, port))<0) {
fprintf(stderr,"\n%s: cannot fort_connect()", procname);
fprintf(stderr,", status: %d", s);
fprintf(stderr,", errno: %d" , errno);
perror("fort_connect");
fflush(stderr);
}
SSL_set_fd(ssl,s);
if((status=SSL_connect(ssl))<=0) {
fprintf(stderr,"\n%s: cannot SSL_connect()", procname);
fprintf(stderr,", status: %d", status);
fprintf(stderr,", errno: %d" , errno);
fprintf(stderr,", SSL_get_error(): %d\n", SSL_get_error(ssl,status));
perror("SSL_connect");
fflush(stderr);
}
unsigned char *format =
"GET %s HTTP/1.0\r\n"
"Host: %s\r\n";
static unsigned char *msg = NULL;
static size_t msg_length=0;
dbs_printf(&msg, &msg_length, format, page, host);
if((status=SSL_write(ssl, msg, strlen(msg)))<0) {
fprintf(stderr,"\n%s: SSL_write()", procname);
fprintf(stderr,", status: %d", status);
fprintf(stderr,", errno: %d", errno);
fprintf(stderr,", SSL_get_error(): %d", SSL_get_error(ssl,status));
perror("SSL_write");
fflush(stderr);
}
fflush(stdout);
HashCtx hashctx;
char buffer[1024];
HashInit(&hashctx);
total=0;
while((bytes=SSL_read(ssl, buffer, sizeof(buffer)))>0) {
//write(1,buffer,bytes);
HashUpdate(&hashctx, buffer, bytes);
total+=bytes;
}
fflush(stdout);
if(bytes<0) {
fprintf(stderr, "\n%s: SSL_read()", procname);
fprintf(stderr, ", status: %d", status);
fprintf(stderr, ", errno: %d", errno);
fprintf(stderr,", SSL_get_error(): %d", SSL_get_error(ssl,status));
perror("SSL_read");
fflush(stderr);
}
fflush(stdout);
HashFinal(hash, &hashctx);
if(fort_verbose) {
fprintf(stdout,"fort_hash_https_page:");
fprintf(stdout," %d bytes read", total);
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
}
SSL_shutdown(ssl);
SSL_free(ssl);
SSL_CTX_free(ctx);
close(s);
}
Commandrandom.c
#include <stdio.h>
#include <stdlib.h>
#include "sha256.h"
#include "fort.h"
void fort_hash_command(unsigned char *command, unsigned char *hash)
{
int c,length;
FILE *fp1;
unsigned char buffer[1024];
HashCtx hashctx;
length=0;
if((fp1=popen(command, "r"))!=NULL) {
HashInit(&hashctx);
HashUpdate(&hashctx, (unsigned char *)&cvar,sizeof(cvar));
inccvar();
if(fort_verbose) {
fprintf(stdout,"fort_hash_command: %s",command);
fflush(stdout);
}
while((c=fread(buffer,1,sizeof(buffer),fp1))>0) {
//fwrite(buffer,1,c,stdout);
HashUpdate(&hashctx, buffer, c);
length+=c;
}
pclose(fp1);
if(fort_verbose)
fprintf(stdout,", %d bytes read",length);
HashFinal(hash, &hashctx);
if(fort_verbose) {
fprintf(stdout,", sha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stdout,"%02x", hash[c]);
}
fprintf(stdout,"\n");
fflush(stdout);
}
}
}
sha256.c
/* Written from SHA256 documents by Jari Kuivaniemi, read "http://en.wikipedia.org/wiki/SHA-2" */
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include "sha256.h"
extern unsigned char *procname;
//#ifdef MAIN // in Makefile
unsigned char *sha_name="SHA256 v1.0";
void SHA256Init(SHA256_CONTEXT *sha256)
{
sha256->state[0] = 0x6a09e667;
sha256->state[1] = 0xbb67ae85;
sha256->state[2] = 0x3c6ef372;
sha256->state[3] = 0xa54ff53a;
sha256->state[4] = 0x510e527f;
sha256->state[5] = 0x9b05688c;
sha256->state[6] = 0x1f83d9ab;
sha256->state[7] = 0x5be0cd19;
sha256->count = 0;
}
IUWORD k256[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
#define RR32(word,bits) ( ((word) >> (bits)) | ((word) << (32 - (bits))) )
#define RS32(word,bits) ( ((word) >> (bits)) )
void SHA256Transform(IUWORD state[8], IUBYTE buffer[64])
{
int i;
IUWORD w[64], s0;
IUWORD a, b, c, d, e, f, g, h;
IUWORD maj, t2, s1;
IUWORD ch, t1;
for(i=0;i<16;i++) {
w[i] =
(IUWORD)buffer[i*4+0] << 24 |
(IUWORD)buffer[i*4+1] << 16 |
(IUWORD)buffer[i*4+2] << 8 |
(IUWORD)buffer[i*4+3];
}
for(i=16;i<64;i++) {
s0 = (RR32(w[i-15],7)) ^ (RR32(w[i-15],18)) ^ (RS32(w[i-15],3));
s1 = (RR32(w[i-2],17)) ^ (RR32(w[i-2],19)) ^ (RS32(w[i-2],10));
w[i] = w[i-16] + s0 + w[i-7] + s1;
}
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
for(i=0;i<64;i++) {
s0 = (RR32(a,2)) ^ (RR32(a,13)) ^ (RR32(a,22));
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
s1 = (RR32(e,6)) ^ (RR32(e,11)) ^ (RR32(e,25));
ch = (e & f) ^ ((~ e) & g);
t1 = h + s1 + ch + k256[i] + w[i];
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
state[0] = state[0] + a;
state[1] = state[1] + b;
state[2] = state[2] + c;
state[3] = state[3] + d;
state[4] = state[4] + e;
state[5] = state[5] + f;
state[6] = state[6] + g;
state[7] = state[7] + h;
}
void SHA256Update(SHA256_CONTEXT *sha256, unsigned char *data, int len)
{
int i,j;
j = (int)sha256->count & 63;
sha256->count+=len;
if((j+len)>63) {
memcpy(&sha256->buffer[j],data,64-j); /* last bytes of next block */
SHA256Transform(sha256->state, sha256->buffer);
for (i = 64 - j ; i + 63 < len; i += 64) {
SHA256Transform(sha256->state, &data[i]);
}
j = 0;
} else
i=0;
memcpy(&sha256->buffer[j],&data[i],len-i);
}
void SHA256Final(unsigned char digest[32], SHA256_CONTEXT *sha256)
{
int i,j;
unsigned char filelenght[8];
IULONG count;
count=sha256->count << 3;
SHA256Update(sha256,"\200",1);
while((sha256->count & 63) != 56)
SHA256Update(sha256,"\0",1);
filelenght[0]=(unsigned char)(count >> 56)&0xff;
filelenght[1]=(unsigned char)(count >> 48)&0xff;
filelenght[2]=(unsigned char)(count >> 40)&0xff;
filelenght[3]=(unsigned char)(count >> 32)&0xff;
filelenght[4]=(unsigned char)(count >> 24)&0xff;
filelenght[5]=(unsigned char)(count >> 16)&0xff;
filelenght[6]=(unsigned char)(count >> 8 )&0xff;
filelenght[7]=(unsigned char)(count&0xff);
SHA256Update(sha256,filelenght,sizeof(filelenght));
for(i=0,j=0;i<8;i++) {
digest[j++]=(unsigned char) (sha256->state[i] >> 24)&0xff;
digest[j++]=(unsigned char) (sha256->state[i] >> 16)&0xff;
digest[j++]=(unsigned char) (sha256->state[i] >> 8)&0xff;
digest[j++]=(unsigned char) (sha256->state[i] )&0xff;
}
}
#ifdef MAIN
void printhex(char *name, unsigned char *digest, int len)
{
int c;
fprintf(stdout,"%s=",name);
for(c=0;c<len;c++) {
fprintf(stdout,"%02x",digest[c]);
}
fflush(stdout);
}
int shahexdigit(int c)
{
if(c>='0' && c<='9') return(c-'0');
else if(c>='a' && c<='f') return(c-'a'+10);
else if(c>='A' && c<='F') return(c-'A'+10);
return(0);
}
void sha_test()
{
int c,d,e,ok,allok;
SHA256_CONTEXT sha256;
unsigned char result[32],*p;
fprintf(stdout,"%s",sha_name);
fprintf(stdout,", Context size: %ld", sizeof(SHA256_CONTEXT));
fprintf(stdout,", Hash size: 32");
fprintf(stdout,", IUBYTE size: %ld", sizeof(IUBYTE));
fprintf(stdout,", IUWORD size: %ld", sizeof(IUWORD));
fprintf(stdout,", IULONG size: %ld", sizeof(IULONG));
struct test {
unsigned char *string;
int count;
unsigned char *result;
} tests[] = {
{ "abc",1,"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",1,"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" },
{ "a",1000000,"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0" },
{ "The quick brown fox jumps over the lazy dog",1,"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592" },
};
allok=1;
for(c=0;c<sizeof(tests)/sizeof(tests[0]);c++) {
SHA256Init(&sha256);
for(d=0;d<tests[c].count;d++)
SHA256Update(&sha256,tests[c].string,strlen(tests[c].string));
SHA256Final(result,&sha256);
p=tests[c].result;
d=0;
ok=1;
while(*p!='\0') {
if(*p!='\0')
e=shahexdigit(*p++);
if(*p!='\0')
e=e*16+shahexdigit(*p++);
if(e!=result[d])
ok=0;
d++;
}
if(ok) {
fprintf(stdout,"\nsha256 test ");
fprintf(stdout,"string: %s",tests[c].string);
fprintf(stdout,", count: %d, ",tests[c].count);
printhex("tmp32",result,sizeof(result));
fprintf(stdout,", result: %s",tests[c].result);
fprintf(stdout," ok!!!!");
fflush(stdout);
} else {
fprintf(stdout,"\nsha256 test ");
fprintf(stdout,"string: %s",tests[c].string);
fprintf(stdout,", count: %d, ",tests[c].count);
printhex("tmp32",result,sizeof(result));
fprintf(stdout,", result: %s",tests[c].result);
fprintf(stdout," failed!!!!");
fflush(stdout);
allok=0;
}
}
if(allok) {
fprintf(stdout,", sha256 tests ok!!!!\n");
} else {
fprintf(stdout,", sha256 tests failed!!!!\n");
}
fflush(stdout);
}
int main(int argc, char *argv[])
{
sha_test();
}
#endif
sha256.h
#ifndef SHA256_H
#define SHA256_H
#define HashName "SHA256"
#define HashInit SHA256Init
#define HashUpdate SHA256Update
#define HashFinal SHA256Final
#define HashLen 32
#define HashCtx SHA256_CONTEXT
typedef unsigned char IUBYTE;
typedef unsigned int IUWORD;
typedef unsigned long long IULONG;
typedef struct {
IUWORD state[8];
IULONG count;
IUBYTE buffer[64];
} SHA256_CONTEXT;
void SHA256Init(SHA256_CONTEXT *sha256);
void SHA256Update(SHA256_CONTEXT* sha256, unsigned char *data, int len);
void SHA256Final(unsigned char digest[32], SHA256_CONTEXT *sha256);
void sha_test();
#endif
Newressu.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <sys/time.h>
#include <time.h>
//#define SHA256 2 // in Makefile
#ifdef SHA256
#include "sha256.h"
#endif
//#define FORT 2 // in Makefile
#ifdef FORT
#include "fort.h"
#endif
//#define MAIN 2 // in Makefile
#include "newressu.h"
#include "intelrandom.h"
extern unsigned char *procname;
static unsigned char *programname = "Newressu version 2.4 ©";
static unsigned char *copyright = "Copyright (c) 2013-2021 Jari Kuivaniemi, Helsinki, Finland. Kaikki oikeudet pidätetään!";
static unsigned long periods[1024];
static unsigned long genbytes=0;
static unsigned long clockbytes=0;
#define RESSUT_BYTES 1024
#define RESSU_BITS_NEEDED 128
#define RESSU_MIN_ROUNDS 2
#define RESSU_MIN_CLOCKBYTES 16384+1024
#define aWRITE_SAMPLE 2
#define aUSE_RANDOM 2
#define aDEBUG4 2
#define DEBUG_SORTED 2
#ifdef MAIN
static unsigned char samplefilename[128]="newressusample.rnd";
#endif
#ifdef DEBUG4
static unsigned char debugfilename[128]="newressu.deb";
#endif
static unsigned char urandomfilename[128]="/dev/urandom";
#ifdef USE_RANDOM
static unsigned char randomfilename[128]="/dev/random";
#endif
static int ressu_bits_needed = RESSU_BITS_NEEDED;
static int ressut_bytes = RESSUT_BYTES;
static int stats=0;
static unsigned char ressu_clockbyte() /* JariK 2013 */
{
struct timeval tv;
gettimeofday(&tv, NULL);
return(tv.tv_usec & 0xff);
}
#define RR8(byte,bits) ( ((byte) >> (bits)) | ((byte) << (8 - (bits))) )
#define RL8(byte,bits) ( ((byte) >> (8 - (bits))) | ((byte) << (bits)) )
void ressu_genbytes_single(int size, unsigned char *buffer)
{
int c, d;
unsigned char e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = RL8(e,1); // rotate byte left 1 bits
//e = RL8(e,3); // rotate byte left 3 bits
//e = RR8(e,1); // rotate byte right 1 bits
byte = ressu_clockbyte();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
#ifdef OLD1
void ressu_genbytes_single(int size, unsigned char *buffer)
{
int c, d, e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = ((e&0x80)>>7) | ((e&0x7f)<<1); // rotate left 1
//e = ((e&0xe0)>>5) | ((e&0x1f)<<3); // rotate left 3
//e = ((e&0xfe)>>1) | ((e&0x1)<<7); // rotate right 1
byte = ressu_clockbyte();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
#endif
void ressu_genbytes_fast(int size, unsigned char *buffer)
{
int c;
clockbytes=0;
for(c=0; c<RESSU_MIN_ROUNDS ||
clockbytes < RESSU_MIN_CLOCKBYTES;c++) {
ressu_genbytes_single(size,buffer);
}
}
void ressu_genbytes(int size, unsigned char *buffer) // 6.5.2021 JariK
{
int c, d, e, f;
static int ressut_first=1,
ressut_pos = 0,
ressut_f = 0;
static unsigned char ressut[RESSUT_BYTES];
unsigned long prevperiods[1024];
for(c=0; c<size; c++) {
if(ressut_pos == 0) {
if(ressut_first) {
memset(ressut,0,ressut_bytes);
ressut_first=0;
}
clockbytes=0;
for(d=0;d<1024;d++) {
periods[d]=0;
}
int rndbits=0;
int lim, lim1=0, lim2=0;
int lim1a, lim1b;
int high1, high2;
for(d=0; rndbits<ressu_bits_needed ||
d<RESSU_MIN_ROUNDS ||
clockbytes < RESSU_MIN_CLOCKBYTES; d++) {
// save previous round
for(e=0;e<1024;e++) {
prevperiods[e]=periods[e];
}
ressu_genbytes_single(ressut_bytes,ressut);
// find new lim1
lim=lim1;
f=-1;
for(e=0;e<1024;e++) {
if(prevperiods[e]>0 && prevperiods[e]==lim) {
if(f==-1 || (periods[e]>0 && f<periods[e])) {
f=periods[e];
}
}
}
if(f!=-1)
lim=f;
lim1a=lim;
// find highest amount of chains
high1=-1;
for(e=0;e<1024;e++) {
if(high1==-1 || high1<periods[e]) {
high1=periods[e];
}
}
// and second highest
high2=-1;
for(e=0;e<1024;e++) {
if( (high2==-1 && periods[e]<high1) ||
(high2<periods[e] && periods[e]<high1) ) {
high2=periods[e];
}
}
// and average
int psum=0;
int pcnt=0;
for(e=0;e<1024;e++) {
if(periods[e]>0) {
psum+=periods[e];
pcnt++;
}
}
lim1b=(int)((double)psum/pcnt);
// find next smaller than average
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]<lim1b) ||
(f<periods[e] && periods[e]<lim1b) ) {
f=periods[e];
}
}
if(f!=-1)
lim1b=f;
if(lim==0 || lim>lim1b)
lim=lim1b;
// if lim greater that second highest,
// set to second highest
if(lim>high2) {
lim=high2;
}
lim1=lim;
// find next greater than lim
f=-1;
for(e=0;e<1024;e++) {
if(periods[e]>lim &&
(f==-1 || periods[e]<f))
f=periods[e];
}
if(f!=-1)
lim=f;
lim2=lim;
// calculate bits
rndbits=0;
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
rndbits+=periods[e];
}
}
} // for(d=0;
if(stats) {
fprintf(stdout,"rounds: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout,", high1:%d",high1);
fprintf(stdout,", high2:%d",high2);
fprintf(stdout,", lim1a:%d",lim1a);
fprintf(stdout,", lim1b:%d",lim1b);
fprintf(stdout,", lim1:%d",lim1);
fprintf(stdout,", lim2:%d",lim2);
fprintf(stdout,", div:%f",(double)lim2/lim1);
fprintf(stdout,", clockbytes:%ld",clockbytes);
fprintf(stdout,", rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
} // if(ressut_pos == 0)
ressut_f = (ressut_f + ressut[ressut_pos]) % ressut_bytes;
buffer[c] ^= ressut[ressut_f];
ressut_pos = (ressut_pos+1) % ressut_bytes;
} // for(c=0; c<size; c++)
genbytes+=size;
}
#ifdef DEBUG4
static unsigned char cc[256*1048576]; // clock_chain
static unsigned char *ccp;
static int cc_bytes;
#endif
static unsigned char ressu_clockbyte_debug() /* JariK 2013 */
{
unsigned char c;
struct timeval tv;
gettimeofday(&tv, NULL);
c=tv.tv_usec & 0xff;
#ifdef DEBUG4
if(cc_bytes<sizeof(cc)) {
*ccp++ = c;
cc_bytes++;
}
#endif
return(c);
}
void ressu_genbytes_single_debug(int size, unsigned char *buffer)
{
int c, d;
unsigned char e, byte;
static int f = 0, prevbyte = -1, count = 0;
for(c=0; c<8; c++) {
for(d=0; d<size; d++) {
e = buffer[d];
e = RL8(e,1); // rotate byte left 1 bits
//e = RL8(e,3); // rotate byte left 3 bits
//e = RR8(e,1); // rotate byte right 1 bits
byte = ressu_clockbyte_debug();
if(prevbyte==-1)
prevbyte=byte;
buffer[d] = e^byte;
if(prevbyte!=byte) {
periods[count]++;
clockbytes+=count;
count=0;
prevbyte=byte;
}
count++;
}
for(d=0; d<size; d++) {
f = (f + buffer[d]) % size;
e = buffer[d];
buffer[d] = buffer[f];
buffer[f] = e;
}
}
}
void ressu_genbytes_debug(int size, unsigned char *buffer) // 6.5.2021 JariK
{
int c, d, e, f;
static int ressut_first=1,
ressut_pos = 0,
ressut_f = 0;
static unsigned char ressut[RESSUT_BYTES];
unsigned long prevperiods[1024];
for(c=0; c<size; c++) {
if(ressut_pos == 0) {
if(ressut_first) {
memset(ressut,0,ressut_bytes);
ressut_first=0;
}
clockbytes=0;
for(d=0;d<1024;d++)
periods[d]=0;
#ifdef DEBUG4
ccp=cc;
cc_bytes=0;
while(ressu_clockbyte_debug()!=0);
while(ressu_clockbyte_debug()==0);
ccp=cc;
cc_bytes=0;
#endif
int rndbits=0;
int lim, lim1=0, lim2=0;
int lim1a, lim1b;
int high1, high2;
for(d=0; rndbits<ressu_bits_needed ||
d<RESSU_MIN_ROUNDS; d++) {
// save previous round
for(e=0;e<1024;e++) {
prevperiods[e]=periods[e];
}
ressu_genbytes_single_debug(ressut_bytes,ressut);
// find new lim1
lim=lim1;
f=-1;
for(e=0;e<1024;e++) {
if(prevperiods[e]>0 && prevperiods[e]==lim) {
if(f==-1 || (periods[e]>0 && f<periods[e])) {
f=periods[e];
}
}
}
if(f!=-1)
lim=f;
lim1a=lim;
// find highest amount of chains
high1=-1;
for(e=0;e<1024;e++) {
if(high1==-1 || high1<periods[e]) {
high1=periods[e];
}
}
// and second highest
high2=-1;
for(e=0;e<1024;e++) {
if( (high2==-1 && periods[e]<high1) ||
(high2<periods[e] && periods[e]<high1) ) {
high2=periods[e];
}
}
// and average
int psum=0;
int pcnt=0;
for(e=0;e<1024;e++) {
if(periods[e]>0) {
psum+=periods[e];
pcnt++;
}
}
lim1b=(int)((double)psum/pcnt);
// find next smaller than average
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]<lim1b) ||
(f<periods[e] && periods[e]<lim1b) ) {
f=periods[e];
}
}
if(f!=-1)
lim1b=f;
if(lim==0 || lim>lim1b)
lim=lim1b;
// if lim greater that second highest,
// set to second highest
if(lim>high2) {
lim=high2;
}
lim1=lim;
// find next greater than lim
f=-1;
for(e=0;e<1024;e++) {
if(periods[e]>lim &&
(f==-1 || periods[e]<f))
f=periods[e];
}
if(f!=-1)
lim=f;
lim2=lim;
// calculate bits
rndbits=0;
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
rndbits+=periods[e];
}
}
if(stats) {
fprintf(stdout," round: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout," high1:%d",high1);
fprintf(stdout," high2:%d",high2);
fprintf(stdout," lim1a:%d",lim1a);
fprintf(stdout," lim1b:%d",lim1b);
fprintf(stdout," lim1:%d",lim1);
fprintf(stdout," lim2:%d",lim2);
fprintf(stdout," clockbytes:%ld",clockbytes);
fprintf(stdout," rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
} // for(d=0;
if(stats) {
fprintf(stdout,"rounds: %d",d);
for(e=0;e<1024;e++) {
if(periods[e]>0)
fprintf(stdout," %d:%lu",e,periods[e]);
}
#ifdef DEBUG_SORTED
fprintf(stdout,", sorted:");
int g=0;
for(;;) {
f=-1;
for(e=0;e<1024;e++) {
if( (f==-1 && periods[e]>g) ||
(periods[e]>g && f>periods[e]) )
f=periods[e];
}
if(f==-1)
break;
g=f;
fprintf(stdout," %d",g);
}
#endif
fprintf(stdout," high1:%d",high1);
fprintf(stdout," high2:%d",high2);
fprintf(stdout," lim1a:%d",lim1a);
fprintf(stdout," lim1b:%d",lim1b);
fprintf(stdout," lim1:%d",lim1);
fprintf(stdout," lim2:%d",lim2);
fprintf(stdout," clockbytes:%ld",clockbytes);
fprintf(stdout," rndbits:%d",rndbits);
fprintf(stdout,"\n");
fflush(stdout);
}
#ifdef DEBUG4
FILE *fp1;
if((fp1=fopen(debugfilename,"a"))!=NULL) {
//if(lim1==-1 || lim2==-1 || lim1==lim2) {
for(e=0;e<32;e++)
fprintf(fp1,"%02x",ressut[e]);
fprintf(fp1,", ressut_bytes: %d",ressut_bytes);
fprintf(fp1,", ressu_bits_needed: %d",ressu_bits_needed);
fprintf(fp1,", ressu_min_rounds: %d",RESSU_MIN_ROUNDS);
fprintf(fp1,", clockbytes: %ld",clockbytes);
unsigned long total=0;
fprintf(fp1,", fluctuations:");
for(e=0;e<1024;e++) {
if(periods[e]!=0) {
fprintf(fp1," %d:%lu",e,periods[e]);
total+=(periods[e]*e);
}
}
fprintf(fp1,", total: %lu",total);
fprintf(fp1,", high1: %d",high1);
fprintf(fp1,", high2: %d",high2);
fprintf(fp1,", limit1: %d",lim1);
fprintf(fp1,", limit2: %d",lim2);
fprintf(fp1,", limit: %d",lim);
fprintf(fp1,", skipped:");
for(e=0;e<1024;e++) {
if(periods[e]>=lim) {
fprintf(fp1," %d:%lu",e,periods[e]);
}
}
fprintf(fp1,", counted:");
for(e=0;e<1024;e++) {
if(periods[e]>0 && periods[e]<lim) {
fprintf(fp1," %d:%lu",e,periods[e]);
}
}
fprintf(fp1,", rndbits: %d",rndbits);
fprintf(fp1,", rounds: %d",d);
int prevbyte=-1, count=0, count2=0;
unsigned char byte, small=-1;
fprintf(fp1,", small chains:");
for(e=0;e<cc_bytes;e++) {
byte=cc[e];
if(prevbyte==-1) {
prevbyte=byte;
count=1;
}
if(prevbyte!=byte) {
if(periods[count]>=lim) {
if(small==1 || small==-1)
fprintf(fp1," *");
small=0;
} else small=1;
if(small) {
fprintf(fp1," %d",count);
count2++;
}
count=0;
prevbyte=byte;
}
count++;
}
if(small) {
fprintf(fp1," %d",count);
count2++;
}
fprintf(fp1,", count: %d",count2);
fprintf(fp1,"\n");
fflush(fp1);
//}
fclose(fp1);
} // if((fp1=fopen
#endif
} // if(ressut_pos == 0)
ressut_f = (ressut_f + ressut[ressut_pos]) % ressut_bytes;
buffer[c] ^= ressut[ressut_f];
ressut_pos = (ressut_pos+1) % ressut_bytes;
} // for(c=0; c<size; c++)
genbytes+=size;
}
static void readfile_xor(int len,
unsigned char *buf,
unsigned char *filename)
{
int c, n, n2;
unsigned char temp[64];
FILE *fp1;
if((fp1 = fopen(filename, "rb"))
!= NULL) {
while(len != 0) {
n = (len < sizeof(temp)) ?
len : sizeof(temp);
n2=fread(temp, 1, n, fp1);
for(c = 0; c < n2; c++)
buf[c] ^= temp[c];
len -= n2;
buf += n2;
}
fclose(fp1);
}
}
#define INPUT_RESSU 0
#define INPUT_DEBUG 1
#define INPUT_FAST 2
#define INPUT_SINGLE 3
#define INPUT_FORT 6
#define INPUT_URANDOM 8
#define INPUT_RANDOM 9
static int input=0;
#define GENT_SIZE 1024
#define aDEBUG9 2
char *randomgen[] = { "ressu", "debug","fast","single","4","5","6","7","urandom","random" };
int ressu_genbyte()
{
static unsigned char gent[GENT_SIZE];
static unsigned int gent_pos=0;
unsigned char ch;
if(input==INPUT_RESSU) { // ressu prod
ressu_genbytes(sizeof(ch), &ch);
} else if(input==INPUT_DEBUG) { // ressu debug
ressu_genbytes_debug(sizeof(ch), &ch);
} else {
if(gent_pos==0) {
if(input==INPUT_FAST) // ressu_fast
ressu_genbytes_fast(sizeof(gent),gent);
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(gent),gent);
#ifdef FORT
else if(input==INPUT_FORT) // ressu fort
fort_random_data_xor(sizeof(gent),gent);
#endif
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(gent),gent,urandomfilename);
#ifdef USE_RANDOM
else if(input==INPUT_RANDOM) // random
readfile_xor(sizeof(gent),gent,randomfilename);
#endif
} // if(gent_pos==0
ch=gent[gent_pos];
gent_pos=(gent_pos+1)%sizeof(gent);
}
return(ch);
}
int ressu_genbyte_limit(int limit)
{
int c;
while((c=ressu_genbyte()) >= (256/limit)*limit);
return(c%limit);
}
int ressu_genshort()
{
return(ressu_genbyte() | ressu_genbyte()<<8);
}
int ressu_genshort_limit(int limit)
{
int c;
while((c=ressu_genshort()) >= (65536/limit)*limit);
return(c%limit);
}
unsigned int ressu_genint()
{
return(ressu_genshort() | ressu_genshort()<<16);
}
unsigned int ressu_genint_limit(unsigned long limit)
{
unsigned int c;
while((c=ressu_genint()) >= (((unsigned long)65536*65536)/limit)*limit);
return(c%limit);
}
unsigned long ressu_genlong()
{
return(((unsigned long)ressu_genint()) | ((unsigned long)ressu_genint())<<32);
}
unsigned long ressu_genlong_limit(unsigned long limit)
{
unsigned long c;
while((c=ressu_genlong()) >= (((unsigned long)0xffffffffffffffff)/limit)*limit);
return(c%limit);
}
unsigned long ressu_gen_limit(unsigned long limit)
{
if(limit<=256)
return(ressu_genbyte_limit(limit));
else if(limit<=65536)
return(ressu_genshort_limit(limit));
else if(limit<=(unsigned long)65536*65536)
return(ressu_genint_limit(limit));
else if(limit<=(unsigned long)0xffffffffffffffff)
return(ressu_genlong_limit(limit));
else
return(-1);
}
void newressu_version()
{
fprintf(stderr,"%s",programname); // touch these outside MAIN
fprintf(stderr,", %s",copyright);
}
#ifdef MAIN
#include <stdarg.h>
#define aDEBUG31
static int stat_line_chars=0;
static int stat_line_edchars=0;
unsigned char *procname=NULL;
static void stat_line_begin()
{
#ifdef DEBUG31
fprintf(stderr,"\n");
#else
fprintf(stderr,"\r");
#endif
stat_line_edchars=stat_line_chars;
stat_line_chars=0;
}
static void stat_line_printf(const unsigned char *format, ...)
{
int count;
va_list args;
static unsigned char *stat_line_buf;
static size_t stat_line_buf_length;
va_start(args, format);
count = vsnprintf(stat_line_buf, stat_line_buf_length, format, args) + 1;
va_end(args);
if(stat_line_buf_length < count) {
stat_line_buf_length=count;
stat_line_buf=realloc(stat_line_buf, stat_line_buf_length);
va_start(args, format);
count = vsnprintf(stat_line_buf, stat_line_buf_length, format, args) + 1;
va_end(args);
}
fprintf(stderr,"%s",stat_line_buf);
stat_line_chars+=strlen(stat_line_buf);
}
#define READABLE_NUMBER_BIN 2
#ifdef READABLE_NUMBER_BIN
#define READABLE_NUMBER_HIGH 1023
#define READABLE_NUMBER_DIVIDER 1024
#else
#define READABLE_NUMBER_HIGH 999
#define READABLE_NUMBER_DIVIDER 1000
#endif
#define READABLE_NUMBER_WIDTH 32
static void stat_line_readable(unsigned long length)
{
int c, low;
double length2;
unsigned char buf10[10];
// B = byte
// K = kilo 10^3 2^10
// M = mega 10^6 2^20
// G = giga 10^9 2^30
// T = tera 10^12 2^40
// P = peta 10^15 2^50
// E = exa 10^18 2^60
// Z = zetta 10^21 2^70
// Y = yotta 10^24 2^80
char units[] = "BKMGTPEZY";
strcpy(buf10,"***");
low=0;
for(c=0; length>=low &&
c<sizeof(units)-1; c++) {
if(length>=low &&
length<=READABLE_NUMBER_HIGH) {
if(units[c]=='B')
sprintf(buf10,"%ld", length);
else if(units[c]=='K')
sprintf(buf10,"%ld%cB", length, units[c]);
else if(length==length2)
sprintf(buf10,"%ld%cB", length, units[c]);
else
sprintf(buf10,"%.1f%cB", length2, units[c]);
break;
}
length2=(double)length/READABLE_NUMBER_DIVIDER;
length/=READABLE_NUMBER_DIVIDER;
low=1;
}
stat_line_printf("%s",buf10);
}
void stat_line_end()
{
int c,d;
// previous line longer than this one,
// overwrite with spaces and backspace to
// end
if(stat_line_edchars>stat_line_chars) {
d=stat_line_edchars-stat_line_chars;
for(c=0;c<d;c++) {
#ifdef DEBUG31
fprintf(stderr,"*");
#else
fprintf(stderr," ");
#endif
}
for(c=0;c<d;c++)
fprintf(stderr,"\b");
}
fflush(stderr);
}
int help=0;
static int utf8len(unsigned char *buf)
{
int len;
unsigned char *p;
p=buf;
len=0;
while(*p!='\0') {
if(*p<0x80 || // ascii char
*p>0xbf) // first utf8 byte
len++;
p++;
}
return(len);
}
#define aDEBUG38 2
static void utf8getchar(int size, unsigned char *buf, int n, unsigned char *string)
{
int d;
unsigned char *p,*q;
d=0;
p=string;
q=buf;
// find first byte of character
while(*p!='\0') {
if(*p<0x80 || // ascii char
*p>0xbf) { // first utf8 char
if(d==n)
break;
d++;
}
p++;
}
// copy first byte and rest
// of character
if(*p!='\0') {
*q++=*p; // copy first byte
if(*p>0xbf) { // if first is utf8 char
p++;
for(;;) {
if(*p>0xbf || // first utf8 char
*p<0x80 || // ascii char
*p=='\0') // end of file
break;
*q++=*p++; // copy rest of the bytes
}
}
}
*q='\0';
#ifdef DEBUG38
fprintf(stdout,"%s: utf8getchar:",procname);
fprintf(stdout," string: %s",string);
fprintf(stdout,", n: %d",n);
fprintf(stdout,", character: %s",buf);
fprintf(stdout,"\n");
#endif
}
#define aDEBUG45
static void out_word(int size, unsigned char *buf, unsigned char *digits, unsigned long word2) // 8.5.2021 JariK
{
int c, d, len, digitslen;
unsigned long word;
unsigned char string[132], character[32];
digitslen = utf8len(digits);
word=word2;
len=0;
string[0]='\0';
if(word==0 || digitslen<2) {
// zero
utf8getchar(sizeof(character),character,0,digits);
if(len+strlen(character)<sizeof(string)) {
strcat(string,character);
len+=strlen(character);
}
} else {
// non zero
while(word>0) {
utf8getchar(sizeof(character),character,word%digitslen,digits);
if(len+strlen(character)<sizeof(string)) {
strcat(string,character);
len+=strlen(character);
}
word/=digitslen;
}
}
// reverse string
*buf='\0';
len=0;
d=utf8len(string);
for(c=d-1;c>=0;c--) {
utf8getchar(sizeof(character),character,c,string);
if(len+strlen(character)<size) {
strcat(buf,character);
len+=strlen(character);
}
}
#ifdef DEBUG45
fprintf(stdout,"]\n%s: out_word: ",procname);
fprintf(stdout," reverse string: %s",string);
fprintf(stdout,", digits: %s",digits);
fprintf(stdout,", int: %lu",word2);
fprintf(stdout,"\n[");
#endif
}
#define aDEBUG58 2
static void in_word(unsigned long *word, unsigned char *digits, unsigned char *buf)
{
int c,d,e,f,ok;
unsigned char character[32], character2[32];
*word=0;
d=utf8len(buf);
f=utf8len(digits);
for(c=0;c<d;c++) {
utf8getchar(sizeof(character2),character2,c,buf);
ok=0;
for(e=0;e<f;e++) {
utf8getchar(sizeof(character),character,e,digits);
if(!strcmp(character,character2)) {
ok=1;
break;
}
}
if(ok) {
*word=((*word)*f)+e;
} else {
fprintf(stdout,"%s: in_word:",procname);
fprintf(stdout," illegal digit '%s'\n",character2);
help=1;
}
}
#ifdef DEBUG58
fprintf(stdout,"%s: in_word:",procname);
fprintf(stdout," word: %lu",*word);
fprintf(stdout,", digits: %s",digits);
fprintf(stdout,", string: %s",buf);
fprintf(stdout,"\n");
#endif
}
static void line_clear(int *len, unsigned char **buf)
{
if(*len<1) {
*len=129;
*buf=realloc(*buf,*len);
}
**buf='\0';
}
static int line_add_string_sort(int *len, unsigned char **buf, unsigned char *string)
{
int cmp,count,add;
unsigned char *p;
p=*buf;
add=1;
while(*p!='\0') {
cmp=strncmp(string,p,strlen(string));
if(cmp>0) {
while(*p!=' ' && *p!='\0') // find next space
p++;
while(*p==' ' && *p!='\0') // find next non space
p++;
} else if(cmp==0) {
add=0;
break;
} else {
break;
}
}
if(add) {
count=strlen(*buf)+strlen(string)+1+1;
if(*buf==NULL || count>*len) {
int diff=p-*buf;
*len = *len + 128;
*buf=realloc(*buf,*len);
p=*buf+diff;
}
memmove(p+strlen(string)+1,p,strlen(p)+1);
memmove(p,string,strlen(string));
p+=strlen(string);
*p=' ';
}
return(add);
}
static void line_get_string(int len, unsigned char *buf, int n, unsigned char *string)
{
int e,ok,count;
unsigned char *p,*q;
ok=0;
p=string;
e=0;
while(*p!='\0') {
if(e==n) {
ok=1;
break;
}
while(*p!=' ' && *p!='\0') // find next space
p++;
while(*p==' ' && *p!='\0') // find next non space
p++;
e++;
}
if(ok) {
q=buf;
count=0;
while(*q!=' ' && *q!='\0') {
if(++count<len)
*q++=*p;
p++;
}
*q='\0';
} else {
buf[0]='\0';
}
}
static int size=5, zero=1, sspace=0, snewline=1,
scrlf=1, chars=72, pchars=0, words=0, pwords=0,
lines=10, plines=0, plinesdigits=5, slineno=1,
quiet=0, sort=0, unique=0, sample=0;
static unsigned long limit, word;
static unsigned char *digits="0123456789", character[32];
static unsigned char digitstemp[256];
static unsigned char linenobuf[1024];
static void readword(unsigned char *buf)
{
int d,e;
unsigned char temp1024[1024];
if(limit!=0) {
word=0;
if(zero) {
word=ressu_gen_limit(limit); // include zeroes
//fprintf(stdout,"(%02ld)",word);
} else if(limit>=1) {
while((word=ressu_gen_limit(limit))==0); // skip zeroes
}
out_word(sizeof(temp1024),temp1024,digits,word);
// fill leading zeroes
buf[0]='\0';
utf8getchar(sizeof(character),character,0,digits);
for(d=size-utf8len(temp1024);d>0;d--) {
strcat(buf,character);
}
// rest of the number
strcat(buf,temp1024);
} else if(digits!=NULL) {
int digitslen;
buf[0]='\0';
digitslen=utf8len(digits);
// fill whole word digit by digit
//fprintf(stdout,"[");
for(d=0;d<size;d++) {
if(digits[0]=='0' && !zero)
e=ressu_gen_limit(digitslen-1)+1;
else
e=ressu_gen_limit(digitslen);
utf8getchar(sizeof(temp1024),temp1024,e,digits);
//fprintf(stdout,"%s",temp1024);
strcat(buf,temp1024);
}
//fprintf(stdout,"]");
}
}
static int line_number_length()
{
int c;
out_word(sizeof(linenobuf),linenobuf,"0123456789",lines-1);
c=strlen(linenobuf);
if(c<5)
c=5;
return(c);
}
static void print_line_number()
{
unsigned char linenobuf[1024];
if(pwords==0 && slineno) {
sprintf(linenobuf,"%0*d",plinesdigits,plines);
fprintf(stdout,"%s",linenobuf);
fprintf(stdout," ");
}
}
static void calc_spaces()
{
if(sspace>=2 &&
( (pwords>0 && pwords%sspace==0) ||
(slineno && pwords==0) ) )
pchars++;
if(sspace &&
( (pwords>0) ||
(slineno && pwords==0) ) )
pchars++;
}
static void print_spaces()
{
if(sspace>=2 &&
// space between word groups
( (pwords>0 && pwords%sspace==0) ||
// space after linenumber
(slineno && pwords==0) ) )
fprintf(stdout," ");
if(sspace &&
// space between words
( (pwords>0) ||
// space after linenumber
(slineno && pwords==0) ) )
fprintf(stdout," ");
}
static void print_word(unsigned char *buf)
{
if(size!=0) {
fprintf(stdout,"%*s",size,buf);
} else {
fprintf(stdout,"%s",buf);
}
}
#ifdef SHA256
static void newressu_file_digest(char *filename,unsigned char *hash)
{
int c;
unsigned char buffer[1024];
FILE *fp1;
HashCtx ctx;
HashInit(&ctx);
if((fp1 = fopen(filename, "rb"))!=NULL) {
while((c=fread(buffer, 1, sizeof(buffer), fp1)) > 0)
HashUpdate(&ctx, buffer, c);
fclose(fp1);
}
HashFinal(hash, &ctx);
}
#endif
int main(int argc, char *argv[])
{
int c, d, status=0;
procname=argv[0];
limit=0;
#ifdef DEBUG4
ccp=cc;
cc_bytes=0;
#endif
clockbytes=0;
for(d=0;d<1024;d++)
periods[d]=0;
// look thru command line parameters
for(c=1;c<argc;c++) {
if(!strncmp("-",argv[c],1)) {
if(!strcmp("--lineno",argv[c])) {
slineno=!slineno;
} else if(!strcmp("--crlf",argv[c])) {
scrlf=!scrlf;
slineno=0;
} else if(!strcmp("--quiet",argv[c])) {
quiet=!quiet;
} else if(!strcmp("--stats",argv[c]) ||
!strcmp("--stat",argv[c])) {
stats=!stats;
} else if(!strcmp("--rand",argv[c])) {
digits = "0123456789";
sspace=2;
snewline=5;
slineno=1;
words=10;
chars=0;
limit=100000;
//size=5;
//lines=20000;
} else if(!strncmp("--space",argv[c],7)) {
if(*(argv[c]+7)!='\0' && atoi(argv[c]+7)>1) {
sspace=atoi(argv[c]+7);
} else if(c+1<argc && atoi(argv[c+1])>1) {
sspace=atoi(argv[c+1]);
c++;
} else {
sspace=!sspace;
}
} else if(!strncmp("--newline",argv[c],9)) {
if(*(argv[c]+9)!='\0' && atoi(argv[c]+9)>1) {
snewline=atoi(argv[c]+9);
} else if(c+1<argc && atoi(argv[c+1])>1) {
snewline=atoi(argv[c+1]);
c++;
} else {
snewline=!snewline;
}
} else if(!strcmp("--zero",argv[c])) {
zero=!zero;
} else if(!strcmp("--sort",argv[c])) {
sort=!sort;
if(sspace==0)
sspace=1;
} else if(!strcmp("--unique",argv[c])) {
unique=!unique;
if(sspace==0)
sspace=1;
} else if(!strcmp("--lotto",argv[c])) {
sort=!sort;
if(sspace==0)
sspace=1;
//sort=1;
//unique=1;
} else if(!strcmp("--sample",argv[c])) {
sample=!sample;
} else if(!strcmp("--copyright",argv[c]) ||
!strcmp("--version",argv[c])) {
newressu_version();
#ifdef SHA256
unsigned char filedigest[HashLen];
newressu_file_digest("/proc/self/exe", filedigest);
fprintf(stderr,"\nsha256: ");
for(int c = 0;c < HashLen; c++) {
fprintf(stderr,"%02x", filedigest[c]);
}
#endif
fprintf(stderr,"\n\n");
help=1;
} else if(!strncmp("--lim",argv[c],5)) {
if(*(argv[c]+5)!='\0') {
in_word(&limit, digits, argv[c]+5);
} else if(c+1<argc) {
in_word(&limit, digits, argv[c+1]);
c++;
}
if(sspace<1) // 23.6.2021
sspace=1;
} else if(!strncmp("-s",argv[c],2)) {
if(*(argv[c]+2)!='\0') {
size=atoi(argv[c]+2);
} else if(c+1<argc) {
size=atoi(argv[c+1]);
c++;
}
limit=0; // 23.6.2021
if(size==0)
size=1;
if(size>1024)
size=1024;
} else if(!strncmp("--bits",argv[c],6)) {
if(*(argv[c]+6)!='\0') {
ressu_bits_needed=atoi(argv[c]+6);
} else if(c+1<argc) {
ressu_bits_needed=atoi(argv[c+1]);
c++;
}
} else if(!strncmp("--bytes",argv[c],7)) {
if(*(argv[c]+7)!='\0') {
ressut_bytes=atoi(argv[c]+7);
} else if(c+1<argc) {
ressut_bytes=atoi(argv[c+1]);
c++;
}
} else if(!strncmp("-w",argv[c],2)) { // words per line
if(*(argv[c]+2)!='\0') {
words=atoi(argv[c]+2);
} else if(c+1<argc) {
words=atoi(argv[c+1]);
c++;
}
if(words<1)
words=1;
chars = 0;
} else if(!strncmp("-c",argv[c],2)) { // characters per line
if(*(argv[c]+2)!='\0') {
chars=atoi(argv[c]+2);
} else if(c+1<argc) {
chars=atoi(argv[c+1]);
c++;
}
words=0;
} else if(!strncmp("-l",argv[c],2)) { // lines
if(*(argv[c]+2)!='\0') {
lines=atoi(argv[c]+2);
} else if(c+1<argc) {
lines=atoi(argv[c+1]);
c++;
}
if(lines<1)
lines=1;
} else if(!strcmp("-x",argv[c])) {
digits = "0123456789abcdef";
size=4;
} else if(!strcmp("-d",argv[c])) {
digits = "0123456789";
size=5;
} else if(!strcmp("-o",argv[c])) {
digits = "01234567";
size=3;
} else if(!strcmp("-b",argv[c])) {
digits = "01";
size=8;
} else if(!strcmp("-1",argv[c])) {
digits=
"0123456789" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz";
size=8;
} else if(!strcmp("-11",argv[c])) {
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
size=8;
} else if(!strcmp("-12",argv[c])) {
digits=
"0123456789";
size=8;
} else if(!strcmp("-2",argv[c])) {
digits=
"0123456789" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz" \
"_-";
size=8;
} else if(!strcmp("-3",argv[c])) { // 9.5.2021 JariK
digits=
"!\"#$%&'()*+,-./0123456789:;<=>?@" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
"abcdefghijklmnopqrstuvwxyz{|}~";
size=8;
} else if(!strcmp("--rus",argv[c])) { // russian alphabet
digits=
"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" \
"абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
size=8;
} else if(!strcmp("--dnk",argv[c]) || // danish alphabet
!strcmp("--nor",argv[c])) { // norwegian alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ" \
"abcdefghijklmnopqrstuvwxyzæøå";
size=8;
} else if(!strcmp("--fin",argv[c]) || // finnish alphabet
!strcmp("--swe",argv[c])) { // swedish alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ" \
"abcdefghijklmnopqrstuvwxyzåäö";
size=8;
} else if(!strcmp("--est",argv[c])) { // estonian alphabet
digits=
"ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY" \
"abcdefghijklmnopqrsšzžtuvwõäöüxy";
size=8;
} else if(!strcmp("--ltu",argv[c])) { // lithuanian alphabet
digits=
"AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ" \
"aąbcčdeęėfghiįyjklmnoprsštuųūvzž";
size=8;
} else if(!strcmp("--lva",argv[c])) { // latvian alphabet
digits=
"AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ" \
"aābcčdeēfgģhiījkķlļmnņoprsštuūvzž";
size=8;
} else if(!strcmp("--fra",argv[c]) // french alphabet
||!strcmp("--gbr",argv[c]) // great britain alphabet
||!strcmp("--usa",argv[c]) // united states alphabet
||!strcmp("--ita",argv[c]) // italian alphabet
) {
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz";
size=8;
} else if(!strcmp("--deu",argv[c])) { // deutche alphabet
digits=
"ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜẞ" \
"abcdefghijklmnopqrstuvwxyzäöüß";
size=8;
} else if(!strcmp("--grc",argv[c])) { // greek alphabet
digits=
"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ" \
"αβγδεζηθικλμνξοπρστυφχψω";
size=8;
} else if(!strcmp("--cards",argv[c])) {
digits=
"🂡🂢🂣🂤🂥🂦🂧🂨🂩🂪🂫🂭🂮" \
"🂱🂲🂳🂴🂵🂶🂷🂸🂹🂺🂻🂽🂾" \
"🃁🃂🃃🃄🃅🃆🃇🃈🃉🃊🃋🃍🃎" \
"🃑🃒🃓🃔🃕🃖🃗🃘🃙🃚🃛🃝🃞";
size=1;
} else if(!strcmp("--isalnum",argv[c]) || // 9.5.2021 JariK
!strcmp("--isalpha",argv[c]) ||
!strcmp("--isdigit",argv[c]) ||
!strcmp("--isgraph",argv[c]) ||
!strcmp("--islower",argv[c]) ||
!strcmp("--isprint",argv[c]) ||
!strcmp("--ispunct",argv[c]) ||
!strcmp("--isupper",argv[c]) ||
!strcmp("--isxdigit",argv[c])) {
unsigned char *p=digitstemp;
for(d=0;d<256;d++) {
if((!strcmp("--isalnum",argv[c]) && isalnum(d)) ||
(!strcmp("--isalpha",argv[c]) && isalpha(d)) ||
(!strcmp("--isdigit",argv[c]) && isdigit(d)) ||
(!strcmp("--isgraph",argv[c]) && isgraph(d)) ||
(!strcmp("--islower",argv[c]) && islower(d)) ||
(!strcmp("--isprint",argv[c]) && isprint(d)) ||
(!strcmp("--ispunct",argv[c]) && ispunct(d)) ||
(!strcmp("--isupper",argv[c]) && isupper(d)) ||
(!strcmp("--isxdigit",argv[c]) && isxdigit(d))) {
*p++=d;
}
}
*p='\0';
digits=digitstemp;
size=8;
} else if(!strncmp("-i",argv[c],2)) {
digits=NULL;
if(*(argv[c]+2)!='\0') {
digits=argv[c]+2;
} else if(c+1 < argc) {
digits=argv[c+1];
c++;
}
if(digits==NULL || utf8len(digits)<2) {
fprintf(stderr,"%s: not enough digits \"%s\"\n",procname,argv[c]);
help = 1;
}
size=1;
} else if(!strcmp("--ressu",argv[c])) {
input=INPUT_RESSU;
} else if(!strcmp("--debug",argv[c])) {
input=INPUT_DEBUG;
} else if(!strcmp("--fast",argv[c])) {
input=INPUT_FAST;
} else if(!strcmp("--single",argv[c])) {
input=INPUT_SINGLE;
#ifdef FORT
} else if(!strcmp("--fort",argv[c])) {
input=INPUT_FORT;
} else if(!strcmp("--fortverbose",argv[c])) {
fort_verbose=!fort_verbose;
#endif
} else if(!strcmp("--urandom",argv[c])) {
input=INPUT_URANDOM;
#ifdef USE_RANDOM
} else if(!strcmp("--random",argv[c])) {
input=INPUT_RANDOM;
#endif
} else {
fprintf(stderr,"%s: invalid option %s\n",procname,argv[c]);
status=1;
help = 1;
}
} else {
help = 1;
} // if(!strncmp
} // for(c=0
#ifdef FORT
if(input==INPUT_FORT) {
strcpy(fort_random_file,"newressufort.rnd");
//fort_verbose=0;
fort_init();
}
#endif
if(sample) {
//sample file size = CLIM*DLIM*BLKSIZE
#define CLIM 8192 // outer loop
#define DLIM 256 // inner loop
#define BLKSIZE 4096 // block size
#define STAT_LINE_READY 2
#define STAT_LINE_NOW 2
#define STAT_LINE_ANIM 2
#define TIMEFORMAT "%H:%M %Z"
#define TIMEFORMAT2 "%a %H:%M %Z"
#define DATEFORMAT "%a %d %b %Y"
unsigned int c, d;
unsigned char buffer[BLKSIZE];
FILE *fp1;
time_t secondsstart, secondsnow;
#ifdef STAT_LINE_ANIM
long int secs, prev_secs=-1;
int crs=0;
#endif
if((fp1=fopen(samplefilename,"a")) != NULL) {
secondsstart=time(NULL);
for(c=0;c<CLIM;c++) {
secondsnow=time(NULL);
// print status line:
// blk 10, written 10MB, 269KB/sec, left 8 h 38 m, ready at Sat 17 Jul 2021 01:57:43 EEST, now Fri 17:19:32 EEST
stat_line_begin();
stat_line_printf("\rblk %d, written ",c);
stat_line_readable((unsigned long)c*DLIM*BLKSIZE);
if(c>0) {
stat_line_printf(", ");
stat_line_readable((unsigned long)((double)c*DLIM*BLKSIZE/(secondsnow-secondsstart)) );
stat_line_printf("/sec");
char timebuf[128], timebuf2[128];
#ifdef STAT_LINE_NOW
// print now
stat_line_printf(", now");
strftime(timebuf,sizeof(timebuf),TIMEFORMAT2,
localtime((time_t *)&secondsnow));
stat_line_printf(" %s",timebuf);
#endif
// print left
long int secondsleft=(int)((((double)secondsnow-secondsstart)/c)*(CLIM-c) );
long int secondsleft2;
long int temp,timeprinted=0;
secondsleft2=secondsleft;
stat_line_printf(", left");
temp=secondsleft2/(24*3600);
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dd",temp);
secondsleft2-=temp*(24*3600);
}
temp=secondsleft2/3600;
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dh",temp);
secondsleft2-=temp*3600;
}
temp=secondsleft2/60;
if(temp>0) {
timeprinted=1;
stat_line_printf(" %dm",temp);
secondsleft2-=temp*60;
}
temp=secondsleft2;
if(!timeprinted) {
stat_line_printf(" %d seconds",temp);
}
#ifdef STAT_LINE_READY
long int secondsend=(int)secondsstart+((((double)secondsnow-secondsstart)/c)*CLIM);
// print end date if different7
stat_line_printf(", ready at");
strftime(timebuf,sizeof(timebuf),DATEFORMAT,
localtime((time_t *)&secondsend));
strftime(timebuf2,sizeof(timebuf2),DATEFORMAT,
localtime((time_t *)&secondsnow));
if(strcmp(timebuf,timebuf2)) {
stat_line_printf(" %s",timebuf);
}
// print end time
strftime(timebuf,sizeof(timebuf),TIMEFORMAT,
localtime((time_t *)&secondsend));
stat_line_printf(" %s",timebuf);
#endif
}
stat_line_end();
// do the work
#ifdef STAT_LINE_ANIM
unsigned char cursor[4] = { '|', '/', '-', '\\' };
fprintf(stderr," ");
#endif
for(d=0;d<DLIM;d++) {
#ifdef STAT_LINE_ANIM
secs=time(NULL)%sizeof(cursor);
if(prev_secs!=secs) {
if(prev_secs!=-1)
crs=(crs+1)%sizeof(cursor);
fprintf(stderr,"\b%c",cursor[crs]);
fflush(stderr);
prev_secs=secs;
}
#endif
if(input==INPUT_RESSU) // ressu prod
ressu_genbytes(sizeof(buffer),buffer);
else if(input==INPUT_DEBUG) // ressu debug
ressu_genbytes_debug(sizeof(buffer),buffer);
else if(input==INPUT_FAST) // ressu fast
ressu_genbytes_fast(sizeof(buffer),buffer);
else if(input==INPUT_SINGLE) // ressu single
ressu_genbytes_single(sizeof(buffer),buffer);
#ifdef FORT
else if(input==INPUT_FORT) // ressu fort
fort_random_data_xor(sizeof(buffer),buffer);
#endif
else if(input==INPUT_URANDOM) // urandom
readfile_xor(sizeof(buffer),buffer,urandomfilename);
#ifdef USE_RANDOM
else if(input==INPUT_RANDOM) // random
readfile_xor(sizeof(buffer),buffer,randomfilename);
#endif
#ifdef WRITE_SAMPLE
fwrite(buffer,1,sizeof(buffer),fp1);
#endif
} // for(d=0;
#ifdef STAT_LINE_ANIM
fprintf(stderr,"\b \b");
prev_secs=-1;
#endif
}
fclose(fp1);
} // if((fp1=fopen
// remove last status line
stat_line_begin();
stat_line_printf("Done!");
stat_line_end();
fprintf(stdout,"\n");
fflush(stdout);
exit(status);
} // if(sample)
// get linenumber length in digits
plinesdigits=line_number_length();
// get data length in digits
if(limit!=0) {
unsigned char wordbuf[128];
out_word(sizeof(wordbuf),wordbuf,digits,limit-1);
size=utf8len(wordbuf);
}
pchars=0;
pwords=0;
int linew=0;
// in beginning of line, count printed line number
if(!quiet && slineno) {
sprintf(linenobuf,"%0*d",plinesdigits,plines);
pchars += strlen(linenobuf);
pchars++;
}
// count words
while((chars>0 && pchars+size < chars) ||
(words>0 && pwords < words)) {
linew++;
calc_spaces();
pchars+=size;
pwords++;
}
unsigned long wordvalues=1;
for(c=0;c<size;c++) {
if(wordvalues!=0 && wordvalues*utf8len(digits)<(unsigned long)65536*65536*65536) {
wordvalues*=utf8len(digits);
} else {
wordvalues=0;
}
}
if(limit > 0) {
if(sort==1 && limit-!zero<words) {
fprintf(stderr,"%s: limit is less than words (zero)",procname);
fprintf(stderr,", limit:%lu",limit);
fprintf(stderr,", words:%d",words);
fprintf(stderr,", zero:%d",zero);
fprintf(stderr,"\n");
help=1;
lines=0;
}
} else {
if(sort==1 && size>0 && wordvalues>0 && wordvalues<linew) {
fprintf(stderr,"%s:",procname);
fprintf(stderr," digits is less than calculated words");
fprintf(stderr,", digits:%d(%lu)",utf8len(digits),wordvalues);
fprintf(stderr,", words:%d\n",linew);
help=1;
lines=0;
}
}
// small words as single ressu_gen_limit() call
if(limit==0 && wordvalues>0)
limit=wordvalues;
if(stats) {
fprintf(stdout,"randomsource: %s",randomgen[input]);
fprintf(stdout,", size: %d",size);
fprintf(stdout,", linew: %d",linew);
fprintf(stdout,", pchars: %d",pchars);
fprintf(stdout,", pwords: %d",pwords);
fprintf(stdout,", tchars: %d",size*linew*lines);
fprintf(stdout,", digitslen: %d",utf8len(digits));
if(wordvalues>0)
fprintf(stdout,", wordvalues: %lu",wordvalues);
if(limit>0)
fprintf(stdout,", limit: %lu",limit);
fprintf(stdout,"\n");
}
if(help) {
struct helpline {
char *command;
char *text;
} helplines[] = {
{ "newressu -d", "print random decimal digits (default)" },
{ "newressu -o", "print octal digits" },
{ "newressu -x", "print hexadecimal digits" },
{ "newressu -b", "print binary digits" },
{ "newressu -d --space", "print decimal digits, with spaces between \"words\"" },
{ "newressu -b --space", "print binary digits, with spaces between \"words\"" },
{ "newressu -d -l30", "print decimal digits, 30 lines" },
{ "newressu -d -l30 --lineno", "print decimal digits, 30 lines, no linenumbers" },
{ "newressu -d -c128", "print decimal digits, 128 characters per line" },
{ "newressu -d --lim10", "print decimal numbers between 0-9" },
{ "newressu -d --lim10 -x","print hexadecimal numbers with decimal limit" },
{ "newressu -d -s10 --space","print decimal numbers with spaces and wordsize 10" },
{ "newressu -d --space --zero --lim7","print rollings of dice (1-6)" },
{ "newressu -b -s1 --space","print throws of coin (0,1)" },
{ "newressu -d --lim41 -w7 --zero --lotto","print lotto numbers for finnish lotto 7x(1-40)" },
{ "newressu -d -s5 --sort -w16","print 16 sorted decimal numbers from 0 to 99999" },
{ "newressu --isalnum", "print alphanumeric characters" },
{ "newressu --isalpha", "print alphabetic characters" },
{ "newressu --isgraph", "print printables excluding space" },
{ "newressu --islower", "print lowercase characters" },
{ "newressu --ispunct", "print punctuation characters" },
{ "newressu --isupper", "print uppercase characters" },
{ "newressu -1", "print material for passwords" },
{ "newressu -iаэыуояеёюи", "print russian vowels" },
{ "newressu --ressu", "use randomness from ressu (default)" },
{ "newressu --debug", "use randomness from debugging ressu" },
{ "newressu --fast", "use randomness from fast ressu" },
{ "newressu --single", "use randomness from single round of ressu" },
#ifdef FORT
{ "newressu --fort", "use randomness from fort" },
#endif
{ "newressu --urandom", "use randomness from /dev/urandom" },
#ifdef USE_RANDOM
{ "newressu --random", "use randomness from /dev/random" },
#endif
};
for(c=0;c<sizeof(helplines)/sizeof(helplines[0]);c++) {
fprintf(stderr,"%-50s",helplines[c].text);
fprintf(stderr,"%-25s",helplines[c].command);
fprintf(stderr,"\n");
}
for(c=0;c<chars;c++)
fprintf(stdout,"*");
fprintf(stdout,"\n");
if(lines>1)
lines=1; // print one line below help as a sample
}
if(lines==0)
exit(status);
int linecnt=0;
unsigned char *line=NULL;
unsigned char wordbuf[1025];
for(;;) {
if(!sort) { // also lotto
pwords=0;
while(pwords<linew) {
readword(wordbuf);
if(!quiet) {
#ifdef FORT
fort_partial_line = 1;
#endif
// in beginning of line, print line number
print_line_number();
// want to print spaces between "words"?
print_spaces();
// print word
print_word(wordbuf);
}
pwords++;
} // while(pwords<linew) {
} else { // if(!sort)
pwords=0;
line_clear(&linecnt,&line);
// fetch and save words on this row
while(pwords<linew) {
readword(wordbuf);
if(line_add_string_sort(&linecnt,&line,wordbuf)) {
pwords++;
}
} // while(pwords<linew) {
pwords=0;
// print words on this row
while(pwords<linew) {
line_get_string(sizeof(wordbuf),wordbuf,pwords,line);
if(!quiet) {
#ifdef FORT
fort_partial_line = 1;
#endif
// in beginning of line, print line number
print_line_number();
// want to print spaces between "words"?
print_spaces();
// print word
print_word(wordbuf);
}
pwords++;
} // while(pwords<linew) {
} // if(!sort)
if(!quiet) {
fprintf(stdout,"\n");
}
plines++;
if(!quiet && snewline>1 &&
plines<lines &&
plines%snewline==0)
fprintf(stdout,"\n");
#ifdef FORT
fort_partial_line = 0;
#endif
// all needed lines printed?
if(plines >= lines)
break;
} // for(;;)
fflush(stdout);
#ifdef FORT
if(input==INPUT_FORT) {
fort_save();
}
#endif
exit(status);
}
#endif // MAIN
newressu.h:
void ressu_genbytes(int size, unsigned char *buffer);