1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* The high resolution timer API provides access to the hardware timer 18 * running at around 1.1MHz. The amount this changes in a time slice is 19 * varies randomly due to system events, hardware interrupts etc 20 */ 21static UCHAR randbyte_hrtimer() 22{ 23 QWORD t1, t2; 24 UCHAR byte; 25 26 DosTmrQueryTime(&t1); 27 DosSleep(5); 28 DosTmrQueryTime(&t2); 29 30 byte = (t2.ulLo - t1.ulLo) & 0xFF; 31 byte ^= (t2.ulLo - t1.ulLo) >> 8; 32 return byte; 33} 34 35 36 37/* A bunch of system information like memory & process stats. 38 * Not highly random but every bit helps.... 39 */ 40static UCHAR randbyte_sysinfo() 41{ 42 UCHAR byte = 0; 43 UCHAR SysVars[100]; 44 int b; 45 46 DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars)); 47 48 for (b = 0; b < 100; b++) { 49 byte ^= SysVars[b]; 50 } 51 52 return byte; 53} 54 55 56 57/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal 58 * counters which run at the CPU's MHz speed. We get separate 59 * idle / busy / interrupt cycle counts which should provide very good 60 * randomness due to interference of hardware events. 61 * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions 62 * which is why it's run-time linked. 63 */ 64 65static APIRET APIENTRY(*DosPerfSysCall) (ULONG ulCommand, ULONG ulParm1, 66 ULONG ulParm2, ULONG ulParm3) = NULL; 67static HMODULE hDoscalls = 0; 68#define CMD_KI_RDCNT (0x63) 69 70typedef struct _CPUUTIL { 71 ULONG ulTimeLow; /* Low 32 bits of time stamp */ 72 ULONG ulTimeHigh; /* High 32 bits of time stamp */ 73 ULONG ulIdleLow; /* Low 32 bits of idle time */ 74 ULONG ulIdleHigh; /* High 32 bits of idle time */ 75 ULONG ulBusyLow; /* Low 32 bits of busy time */ 76 ULONG ulBusyHigh; /* High 32 bits of busy time */ 77 ULONG ulIntrLow; /* Low 32 bits of interrupt time */ 78 ULONG ulIntrHigh; /* High 32 bits of interrupt time */ 79} CPUUTIL; 80 81 82static UCHAR randbyte_perf() 83{ 84 UCHAR byte = 0; 85 CPUUTIL util; 86 int c; 87 88 if (hDoscalls == 0) { 89 char failed_module[20]; 90 ULONG rc; 91 92 rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS", 93 &hDoscalls); 94 95 if (rc == 0) { 96 rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall); 97 98 if (rc) { 99 DosPerfSysCall = NULL; 100 } 101 } 102 } 103 104 if (DosPerfSysCall) { 105 if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) { 106 for (c = 0; c < sizeof(util); c++) { 107 byte ^= ((UCHAR *)&util)[c]; 108 } 109 } 110 else { 111 DosPerfSysCall = NULL; 112 } 113 } 114 115 return byte; 116} 117 118 119 120static UCHAR randbyte() 121{ 122 return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf(); 123} 124