Exemplo n.º 1
0
int ctr_nand_crypto_interface_initialize(ctr_nand_crypto_interface *crypto_io, uint8_t keySlot, ctr_nand_crypto_type crypto_type, ctr_io_interface *lower_io)
{
	crypto_io->base = nand_crypto_base;

	//Get the nonces for CTRNAND and TWL decryption
	uint32_t mode;
	uint32_t NandCid[4];
	alignas(4) uint8_t shasum[32];

	sdmmc_get_cid(true, NandCid);
	uint32_t ctr[4];

	switch (crypto_type)
	{
		case NAND_CTR:
			check_and_do_n3ds_init();
			sha_init(SHA256_MODE);
			sha_update((uint8_t*)NandCid, 16);
			sha_get(shasum);
			memcpy(ctr, shasum, 16);
			mode = AES_CNT_CTRNAND_MODE;
			break;

		case NAND_TWL:
			check_and_do_twl_init();
			sha_init(SHA1_MODE);
			sha_update((uint8_t*)NandCid, 16);
			sha_get(shasum);
			for(uint32_t i = 0; i < 16u; i++) // little endian and reversed order
			{
				((uint8_t*)ctr)[i] = shasum[15-i];
			}
			mode = AES_CNT_TWLNAND_MODE;
			break;

		default:
			return 1; //Unknown type
	}

	ctr_crypto_interface_initialize(&crypto_io->crypto_io, keySlot, mode, CTR_CRYPTO_ENCRYPTED, CRYPTO_CTR, (uint8_t*)ctr, lower_io);
	return 0;
}
Exemplo n.º 2
0
// Protocol
// 4.2.3 Card Initialization and Identification Process
static sdmmc_rt sdmmc_card_init(void) {
	sdmmc_rt r;
	int i;

	sd_sm->rca = 0;
	sd_sm->is_mmc = 0;
	sd_sm->is_bus4bit = 0;
	sd_sm->ci_stat = SDP_IDLE;

	for (i = 0; i < 1000; i++);

	sdmmc_cmd_noarg(CMD0_GO_IDLE_STATE);
	printk("SDPROT\tIdle State(idle)\n");

	r = sdmmc_cmd(CMD8R7_SEND_IF_COND, CMD8_VHS_27to36 | CMD8_CHECK_PATTERN);
	printk("SDMMC cmd8() %s\n", sdmmc_err_string(r));

	if (r == SDMMC_NO_RSP) {
		printk("SDPROT\tVer2.00 or later SD Memory Card(voltage mismatch)\n");
		printk("\tor Ver1.X SD Memory Card\n");
		printk("\tor not SD Memory Card\n");
	} else if ((sdmmc_resp() & CMD8_CHECK_PATTERN_MASK) == CMD8_CHECK_PATTERN) {
		printk("SDPROT\tVer2.00 or later SD Memory Card\n");
	} else {
		// unsupported
		return SDMMC_UNSUP;
	}

	if ((r = ACMD41()) == SDMMC_OK) {
		printk("SDPROT\tCard returns ready\n");
		printk("\tVer1.X Standard Capacity SD Memory Card\n");
	} else {
		printk("SDPROT\tNo Response(Non valid command)\n");
		printk("\tMust be a MultiMediaCard\n");
		printk("SDPORT\tStart MultiMediaCard initialization process\n");
		printk("\tstarting at CMD1\n");

		if ((r = CMD1()) != SDMMC_OK) {
			return r;
		}
		sd_sm->is_mmc = 1;
		sd_sm->rca = MMC_RCA;
	}

	printk("SDPROT\tReady State(ready)\n");

	for (i = 0; i < SDMMC_CMD_RETRY; i++) {
		r = sdmmc_cmd_noarg(CMD2R2_ALL_SEND_CID);
		if (r == SDMMC_OK) break;
	}
	if (r != SDMMC_OK) {
		return r;
	}
	printk("SDPROT\tIdentification State(ident)\n");

	sdmmc_get_cid();
	// sdprot_print_cid(&sd_sm->cid);

	for (i = 0; i < SDMMC_CMD_RETRY; i++) {
		uint32_t arg = 0;

		if (sd_sm->is_mmc) {
			arg = sd_sm->rca << 16;
		}
		r = sdmmc_cmd(CMD3R6_SEND_RELATIVE, arg);
		if (r == SDMMC_OK) break;
	}
	if (r != SDMMC_OK) {
		return r;
	}

	printk("SDPROT\tCard responds with new RCA\n");

	if (!sd_sm->is_mmc) {
		sd_sm->rca = (sdmmc_resp() >> 16);
	}
Exemplo n.º 3
0
u32 SdPadgen(u32 param)
{
    (void) (param); // param is unused here
    SdInfo *info = (SdInfo*) 0x20316000;

    // setup AES key from SD
    SetupSdKeyY0x34(false, NULL);
    
    if (!DebugFileOpen("SDinfo.bin"))
        return 1;
    if (!DebugFileRead(info, 4, 0)) {
        FileClose();
        return 1;
    }
    if (!info->n_entries || info->n_entries > MAX_ENTRIES) {
        FileClose();
        Debug("Bad number of entries!");
        return 1;
    }
    if (!DebugFileRead(info->entries, info->n_entries * sizeof(SdInfoEntry), 4)) {
        FileClose();
        return 1;
    }
    FileClose();
    
    Debug("Number of entries: %i", info->n_entries);
    for(u32 i = 0; i < info->n_entries; i++) {
        PadInfo padInfo = {.keyslot = 0x34, .setKeyY = 0, .size_mb = info->entries[i].size_mb, .mode = AES_CNT_CTRNAND_MODE};
        memcpy(padInfo.ctr, info->entries[i].ctr, 16);
        memcpy(padInfo.filename, info->entries[i].filename, 180);
        Debug ("%2i: %s (%iMB)", i, info->entries[i].filename, info->entries[i].size_mb);
        if (CreatePad(&padInfo) != 0)
            return 1; // this can't fail anyways
    }

    return 0;
}

u32 SdPadgenDirect(u32 param)
{
    (void) (param); // param is unused here
    SdInfo *info = (SdInfo*) 0x20316000;
    char basepath[256];
    u8 movable_keyY[16];
    
    if (SetupSdKeyY0x34(true, movable_keyY) != 0)
        return 1; // movable.sed has to be present in NAND
    
    Debug("");
    if (SdFolderSelector(basepath, movable_keyY) != 0)
        return 1;
    Debug("");
    if (SdInfoGen(info, basepath) != 0)
        return 1;
    if (!info->n_entries) {
        Debug("Nothing found in folder");
        return 1;
    }
    
    Debug("Number of entries: %i", info->n_entries);
    for(u32 i = 0; i < info->n_entries; i++) {
        PadInfo padInfo = {.keyslot = 0x34, .setKeyY = 0, .size_mb = info->entries[i].size_mb, .mode = AES_CNT_CTRNAND_MODE};
        memcpy(padInfo.ctr, info->entries[i].ctr, 16);
        memcpy(padInfo.filename, info->entries[i].filename, 180);
        Debug ("%2i: %s (%iMB)", i, info->entries[i].filename, info->entries[i].size_mb);
        if (CreatePad(&padInfo) != 0)
            return 1; // this can't fail anyways
    }

    return 0;
}

u32 AnyPadgen(u32 param)
{
    (void) (param); // param is unused here
    AnyPadInfo *info = (AnyPadInfo*) 0x20316000;
    
    // get header
    if ((FileGetData("anypad.bin", info, 16, 0) != 16) || !info->n_entries || info->n_entries > MAX_ENTRIES) {
        Debug("Corrupt or not existing: anypad.bin");
        return 1;
    }
    
    // get data
    u32 data_size = info->n_entries * sizeof(AnyPadInfoEntry);
    if (FileGetData("anypad.bin", (u8*) info + 16, data_size, 16) != data_size) {
        Debug("File is missing data: anypad.bin");
        return 1;
    }
    
    Debug("Processing anypad.bin...");
    Debug("Number of entries: %i", info->n_entries);
    for (u32 i = 0; i < info->n_entries; i++) { // this translates all entries to a standard padInfo struct
        AnyPadInfoEntry* entry = &(info->entries[i]);
        PadInfo padInfo = {.keyslot = entry->keyslot, .setKeyY = 0, .size_mb = 0, .size_b = entry->size_b, .mode = entry->mode};
        memcpy(padInfo.filename, entry->filename, 80);
        memcpy(padInfo.ctr, entry->ctr, 16);
        // process keys
        if (entry->setNormalKey)
            setup_aeskey(entry->keyslot, entry->normalKey);
        if (entry->setKeyX)
            setup_aeskeyX(entry->keyslot, entry->keyX);
        if (entry->setKeyY)
            setup_aeskeyY(entry->keyslot, entry->keyY);
        use_aeskey(entry->keyslot);
        // process flags
        if (entry->flags & (AP_USE_NAND_CTR|AP_USE_SD_CTR)) {
            u32 ctr_add = getbe32(padInfo.ctr + 12);
            u8 shasum[32];
            u8 cid[16];
            sdmmc_get_cid((entry->flags & AP_USE_NAND_CTR) ? 1 : 0, (uint32_t*) cid);
            if (entry->mode == AES_CNT_TWLNAND_MODE) {
                sha_quick(shasum, cid, 16, SHA1_MODE);
                for (u32 i = 0; i < 16; i++)
                    padInfo.ctr[i] = shasum[15-i];
            } else {
                sha_quick(shasum, cid, 16, SHA256_MODE);
                memcpy(padInfo.ctr, shasum, 16);
            }
            add_ctr(padInfo.ctr, ctr_add);
        }
        // create the pad
        Debug ("%2i: %s (%ikB)", i, entry->filename, entry->size_b / 1024);
        if (CreatePad(&padInfo) != 0)
            return 1; // this can't fail anyways
    }

    return 0;
}

u32 CtrNandPadgen(u32 param)
{
    char* filename = (param & PG_FORCESLOT4) ? "nand.fat16.slot0x04.xorpad" : "nand.fat16.xorpad";
    u32 keyslot;
    u32 nand_size;

    // legacy sizes & offset, to work with Python 3DSFAT16Tool
    if (GetUnitPlatform() == PLATFORM_3DS) {
        if (param & PG_FORCESLOT4) {
            Debug("This is a N3DS only feature");
            return 1;
        }
        keyslot = 0x4;
        nand_size = 758;
    } else {
        keyslot = (param & PG_FORCESLOT4) ? 0x4 : 0x5;
        nand_size = 1055;
    }

    Debug("Creating NAND FAT16 xorpad. Size (MB): %u", nand_size);
    Debug("Filename: %s", filename);

    PadInfo padInfo = {
        .keyslot = keyslot,
        .setKeyY = 0,
        .size_mb = nand_size,
        .mode = AES_CNT_CTRNAND_MODE
    };
    strncpy(padInfo.filename, filename, 64);
    if(GetNandCtr(padInfo.ctr, 0xB930000) != 0)
        return 1;

    return CreatePad(&padInfo);
}

u32 TwlNandPadgen(u32 param)
{
    (void) (param); // param is unused here
    PartitionInfo* twln_info = GetPartitionInfo(P_TWLN);
    u32 size_mb = (twln_info->size + (1024 * 1024) - 1) / (1024 * 1024);
    Debug("Creating TWLN FAT16 xorpad. Size (MB): %u", size_mb);
    Debug("Filename: twlnand.fat16.xorpad");

    PadInfo padInfo = {
        .keyslot = twln_info->keyslot,
        .setKeyY = 0,
        .size_mb = size_mb,
        .filename = "twlnand.fat16.xorpad",
        .mode = AES_CNT_TWLNAND_MODE
    };
    if(GetNandCtr(padInfo.ctr, twln_info->offset) != 0)
        return 1;

    return CreatePad(&padInfo);
}

u32 Firm0Firm1Padgen(u32 param)
{
    (void) (param); // param is unused here
    PartitionInfo* firm0_info = GetPartitionInfo(P_FIRM0);
    PartitionInfo* firm1_info = GetPartitionInfo(P_FIRM1);
    u32 size_mb = (firm0_info->size + firm1_info->size + (1024 * 1024) - 1) / (1024 * 1024);
    Debug("Creating FIRM0FIRM1 xorpad. Size (MB): %u", size_mb);
    Debug("Filename: firm0firm1.xorpad");

    PadInfo padInfo = {
        .keyslot = firm0_info->keyslot,
        .setKeyY = 0,
        .size_mb = size_mb,
        .filename = "firm0firm1.xorpad",
        .mode = AES_CNT_CTRNAND_MODE
    };
    if(GetNandCtr(padInfo.ctr, firm0_info->offset) != 0)
        return 1;

    return CreatePad(&padInfo);
}
Exemplo n.º 4
0
u32 SelfTest(u32 param)
{
    u8* test_data = (u8*) 0x20316000;
    const u8 teststr[16] = { 'D', '9', ' ', 'S', 'E', 'L', 'F', 'T', 'E', 'S', 'T', ' ', ' ', ' ', ' ' };
    const u8 zeroes[16] = { 0x00 };
    bool selftest = !(param & ST_REFERENCE);
    
    // check keyslots
    Debug("Checking keyslots...");
    Debug("0x05 KeyY: %s", (CheckKeySlot(0x05, 'Y') == 0) ? "set up" : "not set up");
    Debug("0x25 KeyX: %s", (CheckKeySlot(0x25, 'X') == 0) ? "set up" : "not set up");
    Debug("0x18 KeyX: %s", (CheckKeySlot(0x18, 'X') == 0) ? "set up" : "not set up");
    Debug("0x1B KeyX: %s", (CheckKeySlot(0x1B, 'X') == 0) ? "set up" : "not set up");
    Debug("");
    
    Debug((selftest) ? "Running selftest..." : "Creating selftest reference data...");
    
    // process all subtests
    u32 num_tests = sizeof(TestList) / sizeof(SubTestInfo);
    u8* test_ptr = test_data;
    u32 fsize_test = 0;
    for (u32 i = 0; i < num_tests; i++) {
        u32 size = TestList[i].size;
        u32 size_a = align(size, 16);
        u32 type = TestList[i].type;
        u32 tparam = TestList[i].param;
        
        memset(test_ptr, 0x00, 16 + size_a);
        strncpy((char*) test_ptr, TestList[i].name, 16);
        test_ptr += 16;
        
        if (type == ST_NAND_CID_HARD) {
            sdmmc_get_cid(1, (uint32_t*) test_ptr);
        } else if (type == ST_NAND_CID_MEM) {
            memcpy(test_ptr, (void*) 0x01FFCD84, 16);
        } else if (type == ST_SHA) {
            sha_quick(test_ptr, teststr, 16, tparam);
        } else if ((type == ST_AES_MODE) || (type == ST_AES_KEYSLOT) || (type == ST_AES_KEYSLOT_Y)) {
            CryptBufferInfo info = {.setKeyY = 0, .size = 16, .buffer = test_ptr};
            if (type == ST_AES_MODE) {
                info.mode = tparam;
                info.keyslot = 0x11;
                setup_aeskey(0x11, (void*) zeroes);
            } else {
                if (type == ST_AES_KEYSLOT_Y) {
                    info.setKeyY = 1;
                    memcpy(info.keyY, zeroes, 16);
                }
                info.mode = AES_CNT_CTRNAND_MODE;
                info.keyslot = tparam;
            }
            memset(info.ctr, 0x00, 16);
            memcpy(test_ptr, teststr, 16);
            CryptBuffer(&info);
        } else if (type == ST_TITLEKEYS) {
            TitleKeyEntry titlekey;
            memset(&titlekey, 0x00, sizeof(TitleKeyEntry));
            for (titlekey.commonKeyIndex = 0; titlekey.commonKeyIndex < 6; titlekey.commonKeyIndex++) {
                memset(titlekey.titleId, 0x00, 8);
                memset(titlekey.titleKey, 0x00, 16);
                CryptTitlekey(&titlekey, false);
                memcpy(test_ptr + (titlekey.commonKeyIndex * 16), titlekey.titleKey, 16);
            }     
        }
        
        test_ptr += size_a;
        fsize_test += 16 + size_a;
    }