The NAND CID: 16 bytes burnt into this console's internal storage, reachable only by asking FS (already initialised, so no service of our own to open and no way for this to start failing later). Deliberately NOT the SD CID as well — that would tie a sealed credential to the card it sits on, and cloning an SD onto a bigger one is a thing users routinely do; the console is what we mean to bind to.
| 275 | // card it sits on, and cloning an SD onto a bigger one is a thing users |
| 276 | // routinely do; the console is what we mean to bind to. |
| 277 | int deviceSecret(uint8_t* out, int want) override |
| 278 | { |
| 279 | if (want != DeviceKeySourceBest && want != DeviceKeySourceCtrNand) { |
| 280 | return -1; |
| 281 | } |
| 282 | u8 cid[16] = {0}; |
| 283 | if (R_FAILED(FSUSER_GetNandCid(cid, sizeof(cid)))) { |
| 284 | return -1; |
| 285 | } |
| 286 | // Hashed rather than handed over raw, so the only thing that ever |
| 287 | // leaves this function is a value the CID cannot be read back out of. |
| 288 | mbedtls_sha256_context ctx; |
| 289 | mbedtls_sha256_init(&ctx); |
| 290 | mbedtls_sha256_starts_ret(&ctx, 0); |
| 291 | mbedtls_sha256_update_ret(&ctx, (const unsigned char*)"Checkpoint 3DS NAND CID v1", 26); |
| 292 | mbedtls_sha256_update_ret(&ctx, cid, sizeof(cid)); |
| 293 | mbedtls_sha256_finish_ret(&ctx, out); |
| 294 | mbedtls_sha256_free(&ctx); |
| 295 | memset(cid, 0, sizeof(cid)); |
| 296 | return DeviceKeySourceCtrNand; |
| 297 | } |
| 298 | |
| 299 | bool randomBytes(void* out, size_t size) override |
| 300 | { |
no outgoing calls
no test coverage detected