/ entropy-gathering / entropy-stats.c
entropy-stats.c
1 /* 2 * An experiment to show how much entropy one can gather from diverse 3 * system and process counters. 4 * 5 * (with gratefulness to the folks on comp.os.vms, who kindly fed me ideas) 6 */ 7 8 /* 9 * The idea is to pick all the data into an internal state and measure how 10 * how much they change over small periods of time. A third order delta is 11 * calculated for every iteration, and the position of the highest set bit 12 * from that delta will be used as entropy estimate. Items with no entropy 13 * (i.e. third order delta == 0) will not be displayed. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <unistd.h> 20 #include <time.h> 21 #include <signal.h> 22 #include <assert.h> 23 24 /* VMSy stuff */ 25 #ifdef __VMS 26 # include <descrip.h> 27 # include <stsdef.h> 28 # include <ssdef.h> 29 # include <starlet.h> 30 # include <lib$routines.h> 31 # ifdef __DECC 32 # pragma message disable DOLLARID 33 # endif 34 35 # include "dict.h" 36 # include "entropy.h" 37 38 size_t total_bits = 0; 39 size_t total_entropy = 0; 40 size_t total_rounds = 0; 41 size_t data_sz = 0; 42 43 void final_entropy() 44 { 45 if (total_bits) 46 printf("Total bits / entropy: %d / %d (ratio = %f)\n", 47 total_bits, total_entropy, (double)total_entropy / total_bits); 48 else 49 printf("No data gathered yet\n"); 50 printf("Data was gathered in %d byte chunks\n", data_sz * sizeof(uint32_t)); 51 } 52 void sigint(int x) 53 { 54 exit(0); 55 } 56 void test_entropy(FILE *binout, size_t maxbytes) 57 { 58 /* Flag for the first run... */ 59 int first = 1; 60 size_t bytes = 0; 61 62 { 63 size_t i, j; 64 65 /* Calculate total data size */ 66 for (i = 0; i < dicts(); i++) { 67 ile3 *itms = items(i); 68 size_t num_itms = num_items(i); 69 70 for (j = 0; j < num_itms; j++) 71 data_sz += itms[j].ile3$w_length / sizeof(uint32_t); 72 } 73 init_entropy_state(data_sz); 74 } 75 76 atexit(final_entropy); 77 signal(SIGINT, sigint); 78 do { 79 size_t round_entropy = 0; 80 size_t round_bits = 0; 81 size_t pos = 0; 82 size_t i, j; 83 uint32_t status = gather_system_data(); 84 if (!($VMS_STATUS_SUCCESS(status))) 85 lib$signal(status); 86 87 for (i = 0; i < dicts(); i++) { 88 for (j = 0; j < num_items(i); j++) { 89 size_t sz = items(i)[j].ile3$w_length / sizeof(uint32_t); 90 size_t entropy = 0; 91 size_t k; 92 char buffer[1024]; 93 94 for (k = 0; k < sz; k++) { 95 entropy += 96 calculate_entropy(((uint32_t *)(items(i)[j].ile3$ps_bufaddr))[k], 97 pos++); 98 } 99 bytes += fwrite(items(i)[j].ile3$ps_bufaddr, 100 items(i)[j].ile3$w_length, 1, 101 binout) 102 * items(i)[j].ile3$w_length; 103 104 /* We must count all bits for fair measurements */ 105 round_bits += items(i)[j].ile3$w_length * 8; 106 round_entropy += entropy; 107 108 /* 109 * There's no point in using the entropy on the first run, 110 * as there isn't enough saved state. 111 */ 112 if (first) 113 continue; 114 115 /* We don't care to display zero entropy items */ 116 if (entropy == 0) 117 continue; 118 119 if (item_istime(i, items(i)[j].ile3$w_code)) { 120 size_t timlen = 0; 121 122 $DESCRIPTOR(timbuf, buffer); 123 sys$asctim(&timlen, &timbuf, items(i)[j].ile3$ps_bufaddr, 0); 124 buffer[timlen] = '\0'; 125 } else { 126 size_t buflen = 0; 127 128 if (sz > 2) { 129 strcpy(buffer, "\n "); 130 buflen = strlen(buffer); 131 } 132 for (k = 0; k < sz; k++) { 133 size_t itemlen = 0; 134 135 if (k > 0) { 136 if (k % 4 == 0) { 137 strcpy(buffer + buflen, ",\n "); 138 buflen += strlen(buffer + buflen); 139 } else { 140 strcpy(buffer + buflen, ", "); 141 buflen += strlen(buffer + buflen); 142 } 143 } 144 itemlen = snprintf(buffer + buflen, sizeof(buffer) - buflen, 145 "0x%08X", 146 ((uint32_t *)(items(i)[j].ile3$ps_bufaddr))[k]); 147 buflen += itemlen; 148 } 149 buffer[buflen] = '\0'; 150 } 151 printf("%s: (%d) ", item_name(i, items(i)[j].ile3$w_code), entropy); 152 puts(buffer); 153 } 154 } 155 first = 0; 156 total_rounds++; 157 total_bits += round_bits; 158 total_entropy += round_entropy; 159 if (round_bits) 160 printf("Total bits / entropy this round: %d / %d (ratio = %f)\n", 161 round_bits, round_entropy, (double)round_entropy / round_bits); 162 else 163 printf("No data gathered this round\n"); 164 165 printf("%lu bytes written to file so far\n", bytes); 166 if (bytes >= maxbytes) 167 break; 168 printf("%lu bytes still needed\n", maxbytes - bytes); 169 170 { 171 int sleeptime = rand() % 10 + 1; 172 printf("DEBUG: sleep %d seconds\n", sleeptime); 173 sleep(sleeptime); 174 } 175 } while (1); 176 } 177 #endif 178 179 /********************************************************************/ 180 int main() 181 { 182 FILE *binout = NULL; 183 184 srand((unsigned int)time(NULL)); 185 binout = fopen("entropy-stats.bin", "w", "ctx=bin"); 186 test_entropy(binout, 1024 * 1024); 187 fclose(binout); 188 } 189