A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 351 lines 8.2 kB view raw
1/* 2 * random.c: Internal random number generator, guaranteed to work 3 * the same way on all platforms. Used when generating an initial 4 * game state from a random game seed; required to ensure that game 5 * seeds can be exchanged between versions of a puzzle compiled for 6 * different platforms. 7 * 8 * The generator is based on SHA-1. This is almost certainly 9 * overkill, but I had the SHA-1 code kicking around and it was 10 * easier to reuse it than to do anything else! 11 */ 12 13#include <assert.h> 14#include <string.h> 15#include <stdio.h> 16 17#include "puzzles.h" 18 19/* ---------------------------------------------------------------------- 20 * Core SHA algorithm: processes 16-word blocks into a message digest. 21 */ 22 23#define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) ) 24 25static void SHA_Core_Init(uint32 h[5]) 26{ 27 h[0] = 0x67452301; 28 h[1] = 0xefcdab89; 29 h[2] = 0x98badcfe; 30 h[3] = 0x10325476; 31 h[4] = 0xc3d2e1f0; 32} 33 34static void SHATransform(uint32 * digest, uint32 * block) 35{ 36 uint32 w[80]; 37 uint32 a, b, c, d, e; 38 int t; 39 40 for (t = 0; t < 16; t++) 41 w[t] = block[t]; 42 43 for (t = 16; t < 80; t++) { 44 uint32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]; 45 w[t] = rol(tmp, 1); 46 } 47 48 a = digest[0]; 49 b = digest[1]; 50 c = digest[2]; 51 d = digest[3]; 52 e = digest[4]; 53 54 for (t = 0; t < 20; t++) { 55 uint32 tmp = 56 rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999; 57 e = d; 58 d = c; 59 c = rol(b, 30); 60 b = a; 61 a = tmp; 62 } 63 for (t = 20; t < 40; t++) { 64 uint32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1; 65 e = d; 66 d = c; 67 c = rol(b, 30); 68 b = a; 69 a = tmp; 70 } 71 for (t = 40; t < 60; t++) { 72 uint32 tmp = rol(a, 73 5) + ((b & c) | (b & d) | (c & d)) + e + w[t] + 74 0x8f1bbcdc; 75 e = d; 76 d = c; 77 c = rol(b, 30); 78 b = a; 79 a = tmp; 80 } 81 for (t = 60; t < 80; t++) { 82 uint32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6; 83 e = d; 84 d = c; 85 c = rol(b, 30); 86 b = a; 87 a = tmp; 88 } 89 90 digest[0] += a; 91 digest[1] += b; 92 digest[2] += c; 93 digest[3] += d; 94 digest[4] += e; 95} 96 97/* ---------------------------------------------------------------------- 98 * Outer SHA algorithm: take an arbitrary length byte string, 99 * convert it into 16-word blocks with the prescribed padding at 100 * the end, and pass those blocks to the core SHA algorithm. 101 */ 102 103void SHA_Init(SHA_State * s) 104{ 105 SHA_Core_Init(s->h); 106 s->blkused = 0; 107 s->lenhi = s->lenlo = 0; 108} 109 110void SHA_Bytes(SHA_State * s, const void *p, int len) 111{ 112 const unsigned char *q = (const unsigned char *) p; 113 uint32 wordblock[16]; 114 uint32 lenw = len; 115 int i; 116 117 /* 118 * Update the length field. 119 */ 120 s->lenlo += lenw; 121 s->lenhi += (s->lenlo < lenw); 122 123 if (s->blkused && s->blkused + len < 64) { 124 /* 125 * Trivial case: just add to the block. 126 */ 127 memcpy(s->block + s->blkused, q, len); 128 s->blkused += len; 129 } else { 130 /* 131 * We must complete and process at least one block. 132 */ 133 while (s->blkused + len >= 64) { 134 memcpy(s->block + s->blkused, q, 64 - s->blkused); 135 q += 64 - s->blkused; 136 len -= 64 - s->blkused; 137 /* Now process the block. Gather bytes big-endian into words */ 138 for (i = 0; i < 16; i++) { 139 wordblock[i] = 140 (((uint32) s->block[i * 4 + 0]) << 24) | 141 (((uint32) s->block[i * 4 + 1]) << 16) | 142 (((uint32) s->block[i * 4 + 2]) << 8) | 143 (((uint32) s->block[i * 4 + 3]) << 0); 144 } 145 SHATransform(s->h, wordblock); 146 s->blkused = 0; 147 } 148 memcpy(s->block, q, len); 149 s->blkused = len; 150 } 151} 152 153void SHA_Final(SHA_State * s, unsigned char *output) 154{ 155 int i; 156 int pad; 157 unsigned char c[64]; 158 uint32 lenhi, lenlo; 159 160 if (s->blkused >= 56) 161 pad = 56 + 64 - s->blkused; 162 else 163 pad = 56 - s->blkused; 164 165 lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3)); 166 lenlo = (s->lenlo << 3); 167 168 memset(c, 0, pad); 169 c[0] = 0x80; 170 SHA_Bytes(s, &c, pad); 171 172 c[0] = (unsigned char)((lenhi >> 24) & 0xFF); 173 c[1] = (unsigned char)((lenhi >> 16) & 0xFF); 174 c[2] = (unsigned char)((lenhi >> 8) & 0xFF); 175 c[3] = (unsigned char)((lenhi >> 0) & 0xFF); 176 c[4] = (unsigned char)((lenlo >> 24) & 0xFF); 177 c[5] = (unsigned char)((lenlo >> 16) & 0xFF); 178 c[6] = (unsigned char)((lenlo >> 8) & 0xFF); 179 c[7] = (unsigned char)((lenlo >> 0) & 0xFF); 180 181 SHA_Bytes(s, &c, 8); 182 183 for (i = 0; i < 5; i++) { 184 output[i * 4] = (unsigned char)((s->h[i] >> 24) & 0xFF); 185 output[i * 4 + 1] = (unsigned char)((s->h[i] >> 16) & 0xFF); 186 output[i * 4 + 2] = (unsigned char)((s->h[i] >> 8) & 0xFF); 187 output[i * 4 + 3] = (unsigned char)((s->h[i]) & 0xFF); 188 } 189} 190 191void SHA_Simple(const void *p, int len, unsigned char *output) 192{ 193 SHA_State s; 194 195 SHA_Init(&s); 196 SHA_Bytes(&s, p, len); 197 SHA_Final(&s, output); 198} 199 200/* ---------------------------------------------------------------------- 201 * The random number generator. 202 */ 203 204struct random_state { 205 unsigned char seedbuf[40]; 206 unsigned char databuf[20]; 207 int pos; 208}; 209 210random_state *random_new(const char *seed, int len) 211{ 212 random_state *state; 213 214 state = snew(random_state); 215 216 SHA_Simple(seed, len, state->seedbuf); 217 SHA_Simple(state->seedbuf, 20, state->seedbuf + 20); 218 SHA_Simple(state->seedbuf, 40, state->databuf); 219 state->pos = 0; 220 221 return state; 222} 223 224random_state *random_copy(random_state *tocopy) 225{ 226 random_state *result; 227 result = snew(random_state); 228 memcpy(result->seedbuf, tocopy->seedbuf, sizeof(result->seedbuf)); 229 memcpy(result->databuf, tocopy->databuf, sizeof(result->databuf)); 230 result->pos = tocopy->pos; 231 return result; 232} 233 234unsigned long random_bits(random_state *state, int bits) 235{ 236 unsigned long ret = 0; 237 int n; 238 239 for (n = 0; n < bits; n += 8) { 240 if (state->pos >= 20) { 241 int i; 242 243 for (i = 0; i < 20; i++) { 244 if (state->seedbuf[i] != 0xFF) { 245 state->seedbuf[i]++; 246 break; 247 } else 248 state->seedbuf[i] = 0; 249 } 250 SHA_Simple(state->seedbuf, 40, state->databuf); 251 state->pos = 0; 252 } 253 ret = (ret << 8) | state->databuf[state->pos++]; 254 } 255 256 /* 257 * `(1UL << bits) - 1' is not good enough, since if bits==32 on a 258 * 32-bit machine, behaviour is undefined and Intel has a nasty 259 * habit of shifting left by zero instead. We'll shift by 260 * bits-1 and then separately shift by one. 261 */ 262 ret &= (1UL << (bits-1)) * 2 - 1; 263 return ret; 264} 265 266unsigned long random_upto(random_state *state, unsigned long limit) 267{ 268 int bits = 0; 269 unsigned long max, divisor, data; 270 271 while ((limit >> bits) != 0) 272 bits++; 273 274 bits += 3; 275 assert(bits < 32); 276 277 max = 1L << bits; 278 divisor = max / limit; 279 max = limit * divisor; 280 281 do { 282 data = random_bits(state, bits); 283 } while (data >= max); 284 285 return data / divisor; 286} 287 288void random_free(random_state *state) 289{ 290 sfree(state); 291} 292 293char *random_state_encode(random_state *state) 294{ 295 char retbuf[256]; 296 int len = 0, i; 297 298 for (i = 0; i < lenof(state->seedbuf); i++) 299 len += sprintf(retbuf+len, "%02x", state->seedbuf[i]); 300 for (i = 0; i < lenof(state->databuf); i++) 301 len += sprintf(retbuf+len, "%02x", state->databuf[i]); 302 len += sprintf(retbuf+len, "%02x", state->pos); 303 304 return dupstr(retbuf); 305} 306 307random_state *random_state_decode(const char *input) 308{ 309 random_state *state; 310 int pos, byte, digits; 311 312 state = snew(random_state); 313 314 memset(state->seedbuf, 0, sizeof(state->seedbuf)); 315 memset(state->databuf, 0, sizeof(state->databuf)); 316 state->pos = 0; 317 318 byte = digits = 0; 319 pos = 0; 320 while (*input) { 321 int v = *input++; 322 323 if (v >= '0' && v <= '9') 324 v = v - '0'; 325 else if (v >= 'A' && v <= 'F') 326 v = v - 'A' + 10; 327 else if (v >= 'a' && v <= 'f') 328 v = v - 'a' + 10; 329 else 330 v = 0; 331 332 byte = (byte << 4) | v; 333 digits++; 334 335 if (digits == 2) { 336 /* 337 * We have a byte. Put it somewhere. 338 */ 339 if (pos < lenof(state->seedbuf)) 340 state->seedbuf[pos++] = byte; 341 else if (pos < lenof(state->seedbuf) + lenof(state->databuf)) 342 state->databuf[pos++ - lenof(state->seedbuf)] = byte; 343 else if (pos == lenof(state->seedbuf) + lenof(state->databuf) && 344 byte <= lenof(state->databuf)) 345 state->pos = byte; 346 byte = digits = 0; 347 } 348 } 349 350 return state; 351}