]> git.saurik.com Git - apple/security.git/blob - SecurityServer/MacYarrow/YarrowServer/YarrowServer_OS9.c
Security-28.tar.gz
[apple/security.git] / SecurityServer / MacYarrow / YarrowServer / YarrowServer_OS9.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: YarrowServer_OS9.c
21
22 Contains: Yarrow Server, OS 9 version.
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved.
27
28 Change History (most recent first):
29
30 02/29/00 dpm Created.
31
32 */
33
34 #include <yarrowUtils.h>
35 #include "YarrowServer_OS9.h"
36 #include "entropyFile.h"
37 #include <debug.h>
38 #include <yarrow.h>
39 #include <Errors.h>
40 #include <Timer.h> /* Microseconds() */
41 #include <LowMem.h> /* LMGetTicks() */
42
43 /* the single system-wide yarrow PRNG object */
44 static PrngRef prng = NULL;
45
46 /*
47 * We collect system entropy every ENTROPY_COLLECT_INTERVAL seconds.
48 */
49 #define ENTROPY_COLLECT_INTERVAL (10 * 60)
50
51 /*
52 * When collecting system entropy, try for this many bytes.
53 */
54 #define SYSTEM_ENTROPY_SIZE 20
55
56 /*
57 * Maintain an entropy file of this size.
58 */
59 #define ENTROPY_FILE_SIZE 20
60
61 /*
62 * Microseconds to crunch in prngAllowReseed()
63 */
64 #define RESEED_TICKS 100
65
66
67 #pragma mark -
68 #pragma mark * * * Private Functions * * *
69
70 #ifdef __cplusplus
71 extern "C" {
72 #endif
73 OSErr _init(void *initBlk);
74 void _fini(void);
75 int main();
76 #ifdef __cplusplus
77 }
78 #endif
79
80 static void
81 systemEntropy(
82 UInt8 *buf,
83 UInt32 bufSize,
84 UInt32 *numBytes, // RETURNED - number of bytes obtained
85 UInt32 *bitsOfEntropy); // RETURNED - est. amount of entropy
86
87
88 /*
89 * Called once on initial library load.
90 */
91 OSErr
92 _init(void *initBlk)
93 {
94 prng_error_status prtn;
95 UInt8 entropyFileData[ENTROPY_FILE_SIZE];
96 UInt8 sysEntropyData[SYSTEM_ENTROPY_SIZE];
97 UInt32 actLen;
98 OSErr ortn;
99 UInt32 entropyBits;
100
101 /* set up prng and its lock */
102 prtn = prngInitialize(&prng);
103 if(prtn) {
104 errorLog1("_init: prngInitialize returned %s\n", perrorString(prtn));
105 return perrorToOSErr(prtn);
106 }
107
108 /* TBD - the mutex */
109
110 /*
111 * read entropy file, add contents to system entropy pool.
112 * It's not an error if there is no entropy file; this
113 * should only happen the first time this server runs on a given
114 * system.
115 */
116 ortn = readEntropyFile(entropyFileData,
117 ENTROPY_FILE_SIZE,
118 &actLen);
119 if((ortn == noErr) && (actLen > 0)) {
120 prtn = prngInput(prng,
121 entropyFileData,
122 actLen,
123 ENTROPY_FILE_SOURCE,
124 actLen * 8); // assume total entropy here
125 if(prtn) {
126 errorLog1("_init: prngInput returned %s\n",
127 perrorString(prtn));
128 return perrorToOSErr(prtn);
129 }
130 }
131 trashMemory(entropyFileData, actLen);
132
133 /*
134 * collect system entropy, add to system entropy pool
135 */
136 systemEntropy(sysEntropyData,
137 SYSTEM_ENTROPY_SIZE,
138 &actLen,
139 &entropyBits);
140 if(actLen > 0) {
141 prtn = prngInput(prng,
142 entropyFileData,
143 actLen,
144 SYSTEM_SOURCE,
145 entropyBits);
146 if(prtn) {
147 errorLog1("_init: prngInput returned %s\n",
148 perrorString(prtn));
149 return perrorToOSErr(prtn);
150 }
151 }
152 trashMemory(sysEntropyData, actLen);
153
154 /*
155 * force reseed
156 */
157 prtn = prngForceReseed(prng, RESEED_TICKS);
158 if(prtn) {
159 errorLog1("_init: prngForceReseed returned %s\n",
160 perrorString(prtn));
161 return perrorToOSErr(prtn);
162 }
163
164 /*
165 * get 20 bytes of random data, write to entropy file
166 */
167 prtn = prngOutput(prng, entropyFileData, ENTROPY_FILE_SIZE);
168 if(prtn) {
169 errorLog1("_init: prngOutput returned %s\n",
170 perrorString(prtn));
171 return perrorToOSErr(prtn);
172 }
173 ortn = writeEntropyFile(entropyFileData, ENTROPY_FILE_SIZE, false);
174 if(ortn) {
175 return ortn;
176 }
177 /* FIXME - schedule an entropyCollector() call; */
178
179 return noErr;
180 }
181
182 void
183 _fini(void)
184 {
185 /* free prng and lock */
186 if(prng != NULL) {
187 prngDestroy(prng);
188 prng = NULL;
189 }
190 }
191
192 /*
193 * FIXME - RuntimePPC.dll is referring to this somehow...
194 *
195 int main()
196 {
197 errorLog0("YarrowServer main() called\n");
198 }
199 */
200
201 /*
202 * Lock/unlock prngMutex - I guess these are not technically necessary
203 * on OS 9
204 */
205 static void
206 prngLock()
207 {
208
209 }
210
211 static void
212 prngUnlock()
213 {
214
215 }
216
217 /*
218 * Get some system entropy. On OS 9 this is pretty lame.
219 */
220 static void
221 systemEntropy(
222 UInt8 *buf,
223 UInt32 bufSize,
224 UInt32 *numBytes, // RETURNED - number of bytes obtained
225 UInt32 *bitsOfEntropy) // RETURNED - est. amount of entropy
226 {
227 UnsignedWide curTime; /* low 16 bits are pretty good, use 32 */
228 unsigned ticks = 0; /* low 8 bits are OK, use 16 bits */
229 UInt8 pool[6];
230 UInt8 *pp = pool;
231
232 Microseconds(&curTime); /* low 16 bits are pretty good */
233 //ticks = LMGetTicks();
234 *pp++ = curTime.lo & 0xff;
235 *pp++ = curTime.lo >> 8;
236 *pp++ = curTime.lo >> 16;
237 *pp++ = curTime.lo >> 24;
238 *pp++ = ticks & 0xff;
239 *pp = ticks >> 8;
240 if(bufSize > 6) {
241 bufSize = 6;
242 }
243 BlockMove(pool, buf, bufSize);
244 *numBytes = bufSize;
245 *bitsOfEntropy = 3 * 8; /* three bytes worth */
246 }
247
248 /*
249 * Entropy collector - called every ENTROPY_COLLECT_INTERVAL seconds.
250 */
251 static void
252 entropyCollector()
253 {
254 /* grab some system entropy
255 * add to pool
256 * allow reseed
257 * if enough time has elapsed {
258 * update seed file
259 * }
260 * schedule another call
261 */
262 }
263
264 #pragma mark -
265 #pragma mark * * * Public Functions * * *
266
267 /*
268 * Add some entropy to the pool. The only "known" failure here is a
269 * result of a failure of this library'e early init.
270 */
271 OSErr yarrowAddEntropy(
272 UInt8 *bytes,
273 UInt32 numBytes,
274 UInt32 bitsOfEntropy)
275 {
276 UInt8 sysEntropy[SYSTEM_ENTROPY_SIZE];
277 UInt32 numSysBytes;
278 UInt32 numSysEntropyBits;
279 prng_error_status prtn;
280 OSErr ortn = noErr;
281
282 if(prng == NULL) {
283 return notOpenErr;
284 }
285 prngLock();
286
287 /* add client entropy */
288 prtn = prngInput(prng, bytes, numBytes, CLIENT_SOURCE, bitsOfEntropy);
289 if(prtn) {
290 errorLog1("prngInput returned %s\n", perrorString(prtn));
291 ortn = ioErr;
292 goto done;
293 }
294
295 /* and some system entropy too - this prevents client from overwhelming
296 * the entropy pool with its own (untrusted) data */
297 systemEntropy(sysEntropy, SYSTEM_ENTROPY_SIZE, &numSysBytes,
298 &numSysEntropyBits);
299 prtn = prngInput(prng, sysEntropy, numSysBytes, SYSTEM_SOURCE,
300 numSysEntropyBits);
301 if(prtn) {
302 errorLog1("prngInput returned %s\n", perrorString(prtn));
303 ortn = ioErr;
304 goto done;
305 }
306 prngAllowReseed(prng, RESEED_TICKS);
307
308 done:
309 prngUnlock();
310 return ortn;
311 }
312
313 /*
314 * Get some random data. Caller mallocs the memory.
315 */
316 OSErr yarrowGetRandomBytes(
317 UInt8 *bytes,
318 UInt32 numBytes)
319 {
320 if(prng == NULL) {
321 return notOpenErr;
322 }
323 prngLock();
324 prngOutput(prng, bytes, numBytes);
325 prngUnlock();
326 return noErr;
327 }
328