Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / sshd / libtomcrypt / bits.c
1 /* portable way to get secure random bits to feed a PRNG */
2 #include "mycrypt.h"
3
4 #ifdef DEVRANDOM
5 /* on *NIX read /dev/random */
6 static unsigned long rng_nix(unsigned char *buf, unsigned long len, 
7                              void (*callback)(void))
8 {
9 #ifdef NO_FILE
10     return 0;
11 #else
12     FILE *f;
13     unsigned long x;
14 #ifdef TRY_URANDOM_FIRST
15     f = fopen("/dev/urandom", "rb");
16     if (f == NULL)
17 #endif /* TRY_URANDOM_FIRST */
18        f = fopen("/dev/random", "rb");
19
20     if (f == NULL) {
21        return 0;
22     }
23     
24     /* disable buffering */
25     if (setvbuf(f, NULL, _IONBF, 0) != 0) {
26        fclose(f);
27        return 0;
28     }   
29  
30     x = (unsigned long)fread(buf, 1, (size_t)len, f);
31     fclose(f);
32     return x;
33 #endif /* NO_FILE */
34 }
35
36 #endif /* DEVRANDOM */
37
38 #ifdef SONY_PS2
39 #include <eetypes.h>
40 #include <eeregs.h>
41 #define min(a,b) ((a) < (b) ? (a) : (b))
42 // Very simple/stupid MD5-based RNG that samples "entropy" from various PS2 control registers
43 static unsigned long rng_ps2(unsigned char *buf, unsigned long len, 
44                              void (*callback)(void))
45 {
46   static unsigned long lastx[2] = { 0xaab7cb4b2fd3b2b9, 0xcec58aff72afe49f }; // md5sum of bits.c
47   unsigned long j;
48   unsigned int samples[10];  // number of sample data sources
49   int l;
50   hash_state md;
51
52   for (j = 0; j < len; j += sizeof(lastx)) {
53     md5_init(&md);
54     samples[0] = *T2_COUNT;
55     samples[1] = *T3_COUNT;
56     samples[2] = *IPU_TOP;
57     samples[3] = *GIF_TAG0;
58     samples[4] = *GIF_TAG1;
59     samples[5] = *GIF_TAG2;
60     samples[6] = *VIF1_CODE;
61     samples[7] = *VIF0_CODE;
62     samples[8] = *D0_MADR;
63     samples[9] = *D1_MADR;
64     md5_process(&md, (unsigned char *)(&samples[0]), sizeof(samples));
65     // include previous round
66     md5_process(&md, (unsigned char *)(&lastx[0]), sizeof(lastx));
67     md5_done(&md, (unsigned char *)(&lastx[0]));
68     l = min(sizeof(lastx), len-j);
69     memcpy(buf+j, &lastx[0], l); //min(sizeof(lastx), len-j));
70   }
71   return len;
72 }
73 #endif /* SONY_PS2 */
74
75 /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
76 #if !defined(SONY_PS2) && defined(CLOCKS_PER_SEC)
77
78 #define ANSI_RNG
79
80 static unsigned long rng_ansic(unsigned char *buf, unsigned long len, 
81                                void (*callback)(void))
82 {
83    clock_t t1;
84    int l, acc, bits, a, b;
85
86    if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
87       return 0;
88    }
89
90    l = len;
91    bits = 8;
92    acc  = a = b = 0;
93    while (len--) {
94        if (callback != NULL) callback();
95        while (bits--) {
96           do {
97              t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
98              t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
99           } while (a == b);
100           acc = (acc << 1) | a;
101        }
102        *buf++ = acc; 
103        acc  = 0;
104        bits = 8;
105    }
106    acc = bits = a = b = 0;
107    return l;
108 }
109
110 #endif 
111
112 /* Try the Microsoft CSP */
113 #ifdef WIN32
114 #define _WIN32_WINNT 0x0400
115 #include <windows.h>
116 #include <wincrypt.h>
117
118 static unsigned long rng_win32(unsigned char *buf, unsigned long len, 
119                                void (*callback)(void))
120 {
121    HCRYPTPROV hProv = 0;
122    if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 
123                             (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && 
124        !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 
125                             CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
126       return 0;
127
128    if (CryptGenRandom(hProv, len, buf) == TRUE) {
129       CryptReleaseContext(hProv, 0);
130       return len;
131    } else {
132       CryptReleaseContext(hProv, 0);
133       return 0;
134    }
135 }
136
137 #endif /* WIN32 */
138
139 unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, 
140                             void (*callback)(void))
141 {
142    unsigned long x;
143
144    _ARGCHK(buf != NULL);
145
146 #ifdef SONY_PS2
147    x = rng_ps2(buf, len, callback);   if (x != 0) { return x; }
148 #elif defined(DEVRANDOM)
149    x = rng_nix(buf, len, callback);   if (x != 0) { return x; }
150 #endif
151 #ifdef WIN32
152    x = rng_win32(buf, len, callback); if (x != 0) { return x; }
153 #endif
154 #ifdef ANSI_RNG
155    x = rng_ansic(buf, len, callback); if (x != 0) { return x; }
156 #endif
157    return 0;
158 }
159
160 int rng_make_prng(int bits, int wprng, prng_state *prng, 
161                   void (*callback)(void))
162 {
163    unsigned char buf[256];
164    int err;
165    
166    _ARGCHK(prng != NULL);
167
168    /* check parameter */
169    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
170       return err;
171    }
172
173    if (bits < 64 || bits > 1024) {
174       return CRYPT_INVALID_PRNGSIZE;
175    }
176
177    if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
178       return err;
179    }
180
181    bits = ((bits/8)+((bits&7)!=0?1:0)) * 2;
182    if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {
183       return CRYPT_ERROR_READPRNG;
184    }
185
186    if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {
187       return err;
188    }
189
190    if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
191       return err;
192    }
193
194    #ifdef CLEAN_STACK
195       zeromem(buf, sizeof(buf));
196    #endif
197    return CRYPT_OK;
198 }
199