- mach_timespec_t timings[timingsToCollect];
- size_t size = sizeof(timings);
- if (sysctl(mib, 4, timings, &size, NULL, 0)) {
- Syslog::alert("entropy collection failed (errno=%d)", errno);
- return;
+
+ mach_timespec_t buffer[timingsToCollect];
+
+ int result;
+
+ 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);