| 297 | } |
| 298 | |
| 299 | bool randomBytes(void* out, size_t size) override |
| 300 | { |
| 301 | // ps:ps owns the hardware RNG. Opened and closed around the call |
| 302 | // rather than held: this runs a handful of times per script run. |
| 303 | if (R_SUCCEEDED(psInit())) { |
| 304 | const Result res = PS_GenerateRandomBytes(out, size); |
| 305 | psExit(); |
| 306 | if (R_SUCCEEDED(res)) { |
| 307 | return true; |
| 308 | } |
| 309 | } |
| 310 | // ps unavailable. Every seal draws a fresh salt as well as a fresh |
| 311 | // nonce, and the salt is what the key is derived from, so what this |
| 312 | // fallback has to guarantee is not secrecy but that two seals never |
| 313 | // come out with the same pair — a tick counter that never repeats |
| 314 | // within a boot, hashed with a call counter, does that. |
| 315 | static u32 calls = 0; |
| 316 | uint8_t* dest = (uint8_t*)out; |
| 317 | while (size > 0) { |
| 318 | const u64 tick = svcGetSystemTick(); |
| 319 | const u64 now = osGetTime(); |
| 320 | const u32 seq = calls++; |
| 321 | uint8_t digest[32]; |
| 322 | mbedtls_sha256_context ctx; |
| 323 | mbedtls_sha256_init(&ctx); |
| 324 | mbedtls_sha256_starts_ret(&ctx, 0); |
| 325 | mbedtls_sha256_update_ret(&ctx, (const unsigned char*)&tick, sizeof(tick)); |
| 326 | mbedtls_sha256_update_ret(&ctx, (const unsigned char*)&now, sizeof(now)); |
| 327 | mbedtls_sha256_update_ret(&ctx, (const unsigned char*)&seq, sizeof(seq)); |
| 328 | mbedtls_sha256_finish_ret(&ctx, digest); |
| 329 | mbedtls_sha256_free(&ctx); |
| 330 | const size_t chunk = size < sizeof(digest) ? size : sizeof(digest); |
| 331 | memcpy(dest, digest, chunk); |
| 332 | dest += chunk; |
| 333 | size -= chunk; |
| 334 | } |
| 335 | return true; |
| 336 | } |
| 337 | |
| 338 | void lowerPriority(void) override |
| 339 | { |