]>
git.saurik.com Git - apple/securityd.git/blob - src/entropy.cpp
7a2dccc8b4a8c755e269c769e70da07d661a48a8
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
28 // EntropyManager - manage entropy on the system.
30 // Here is our mission:
31 // (1) On startup, read the entropy file and seed it into the RNG for initial use
32 // (2) Periodically, collect entropy from the system and seed it into the RNG
33 // (3) Once in a while, take entropy from the RNG and write it to the entropy file
34 // for use across reboots.
36 // This class will fail to operate if the process has (and retains) root privileges.
37 // We re-open the entropy file on each use so that we don't work with a "phantom"
38 // file that some fool administrator removed yesterday.
41 #include <sys/sysctl.h>
42 #include <mach/clock_types.h>
44 #include <security_utilities/logging.h>
45 #include <sys/sysctl.h>
46 #include <security_utilities/debugging.h>
48 /* when true, action() called every 15 seconds */
49 #define ENTROPY_QUICK_UPDATE 0
50 #if ENTROPY_QUICK_UPDATE
51 #define COLLECT_INTERVAL 15
53 #define COLLECT_INTERVAL collectInterval
54 #endif //ENTROPY_QUICK_UPDATE
56 using namespace UnixPlusPlus
;
60 // During construction, we perform initial entropy file recovery.
62 EntropyManager::EntropyManager(MachPlusPlus::MachServer
&srv
, const char *entropyFile
)
63 : DevRandomGenerator(true), server(srv
),
64 mEntropyFilePath(entropyFile
), mNextUpdate(Time::now())
66 // Read the entropy file and seed the RNG. It is not an error if we can't find one.
68 AutoFileDesc
oldEntropyFile(entropyFile
, O_RDONLY
);
69 char buffer
[entropyFileSize
];
70 if (size_t size
= oldEntropyFile
.read(buffer
))
71 addEntropy(buffer
, size
);
74 // go through a collect/update/reschedule cycle immediately
82 void EntropyManager::action()
87 server
.setTimer(this, Time::Interval(COLLECT_INTERVAL
)); // drifting reschedule (desired)
92 // Collect system timings and seed into the RNG.
93 // Note that the sysctl will block until the buffer is full or the timeout expires.
94 // We currently use a 1ms timeout, which almost always fills the buffer and
95 // does not provide enough of a delay to worry about it. If we ever get worried,
96 // we could call longTermActivity on the server object to get another thread going.
98 void EntropyManager::collectEntropy()
102 mib
[1] = KERN_KDEBUG
;
103 mib
[2] = KERN_KDGETENTROPY
;
104 mib
[3] = 1; // milliseconds maximum delay
105 mach_timespec_t timings
[timingsToCollect
];
106 size_t size
= sizeof(timings
);
107 int ret
= sysctl(mib
, 4, timings
, &size
, NULL
, 0);
109 Syslog::alert("entropy collection failed (errno=%d)", errno
);
112 char buffer
[timingsToCollect
];
113 for (unsigned n
= 0; n
< size
; n
++)
114 buffer
[n
] = timings
[n
].tv_nsec
; // truncating to LSB
115 secdebug("entropy", "Entropy size %d: %02x %02x %02x %02x %02x %02x %02x %02x...",
117 (unsigned char)buffer
[0], (unsigned char)buffer
[1], (unsigned char)buffer
[2],
118 (unsigned char)buffer
[3], (unsigned char)buffer
[4], (unsigned char)buffer
[5],
119 (unsigned char)buffer
[6], (unsigned char)buffer
[7]);
120 addEntropy(buffer
, size
);
125 // (Re)write the entropy file with random data pulled from the RNG
127 void EntropyManager::updateEntropyFile()
129 if (Time::now() >= mNextUpdate
) {
131 mNextUpdate
= Time::now() + Time::Interval(updateInterval
);
132 secdebug("entropy", "updating %s", mEntropyFilePath
.c_str());
133 char buffer
[entropyFileSize
];
134 random(buffer
, entropyFileSize
);
135 AutoFileDesc
entropyFile(mEntropyFilePath
.c_str(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0600);
136 if (entropyFile
.write(buffer
) != entropyFileSize
)
137 Syslog::warning("short write on entropy file %s", mEntropyFilePath
.c_str());
139 Syslog::warning("error writing entropy file %s", mEntropyFilePath
.c_str());