- size_t size = timingsToCollect;
-
- result = sysctl(mib,4, buffer, &size, NULL, 0);
- if (result == -1) {
- Syslog::alert("entropy measurement returned no entropy (errno=%d)", errno);
- }
- else if (size == 0)
- {
- Syslog::alert("entropy measurement returned no entropy.");
- }
-
- // add a little more jitter to the buffer
- mach_timebase_info_data_t sTimebaseInfo;
- mach_timebase_info(&sTimebaseInfo);
- double seconds = (double) mach_absolute_time() * sTimebaseInfo.numer / sTimebaseInfo.denom * 1000000000.0;
- buffer[numTimings].tv_sec = (int) seconds;
- buffer[numTimings].tv_nsec = (int) ((seconds - buffer[numTimings].tv_sec) * 1000000000.0);
-
- /*
- Yes, we don't check to see if we filled the entire buffer.
- In entropy collection, something is better than nothing.
- Please don't fiddle with this code unless you really
- have determined that you know what you are doing.
- */
-
- SECURITYD_ENTROPY_SEED((void *)buffer, sizeof(buffer));
- addEntropy(buffer, sizeof(buffer));
+ double bytesRemaining = kBytesOfEntropyToCollect;
+
+ int loopCount = 0;
+
+ while (bytesRemaining >= 0)
+ {
+ size_t size = sizeof(mach_timespec_t) * timingsToCollect;
+
+ result = sysctl(mib,4, buffer, &size, NULL, 0);
+ if (result == -1) {
+ Syslog::alert("entropy measurement returned no entropy (errno=%d)", errno);
+ sleep(1);
+ }
+ else if (size == 0)
+ {
+ Syslog::alert("entropy measurement returned no entropy.");
+ sleep(1);
+ }
+
+ // remove the non-entropic pieces from the buffer
+ u_int16_t nonEnt[timingsToCollect];
+
+ // treat the received buffer as an array of u_int16 and only take the first two bytes of each
+ u_int16_t *rawEnt = (u_int16_t*) buffer;
+
+ int i;
+ for (i = 0; i < timingsToCollect; ++i)
+ {
+ nonEnt[i] = *rawEnt;
+ rawEnt += 4;
+ }
+
+ SECURITYD_ENTROPY_SEED((void *)nonEnt, (unsigned int) sizeof(nonEnt));
+ addEntropy(nonEnt, sizeof(nonEnt));
+
+ double entropyRead = CalculateEntropy(nonEnt, sizeof(nonEnt));
+ bytesRemaining -= entropyRead;
+
+ loopCount += 1;
+ }
+
+ if (loopCount > kExpectedLoops)
+ {
+ Syslog::alert("Entropy collection fulfillment took %d loops", loopCount);
+ }