451 lines
15 KiB
C
451 lines
15 KiB
C
#define LOG_MODULE "ezusb-iidx-emu-node-sec-plug"
|
|
|
|
#include <string.h>
|
|
|
|
#include "ezusb-iidx-emu/node-eeprom.h"
|
|
#include "ezusb-iidx-emu/node-security-mem.h"
|
|
#include "ezusb-iidx-emu/node-security-plug.h"
|
|
#include "ezusb-iidx/secplug-cmd.h"
|
|
|
|
#include "security/rp.h"
|
|
#include "security/rp2.h"
|
|
#include "security/util.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
static struct security_mcode ezusb_iidx_emu_node_security_plug_boot_version;
|
|
static uint32_t ezusb_iidx_emu_node_security_plug_boot_seeds[3];
|
|
|
|
static struct security_mcode ezusb_iidx_emu_node_security_plug_black_mcode;
|
|
static struct security_mcode ezusb_iidx_emu_node_security_plug_white_mcode;
|
|
|
|
static struct security_id ezusb_iidx_emu_node_security_plug_pcbid;
|
|
static struct security_id ezusb_iidx_emu_node_security_plug_eamid;
|
|
|
|
static enum ezusb_iidx_secplug_dongle_slot
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot;
|
|
static enum ezusb_iidx_secplug_dongle_memory
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem;
|
|
static uint8_t ezusb_iidx_emu_node_security_plug_enc_rom_data_seed;
|
|
|
|
static void ezusb_iidx_emu_node_security_plug_encrypt_rom_data(
|
|
uint8_t *buffer, uint8_t length);
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
void ezusb_iidx_emu_node_security_plug_set_boot_version(
|
|
const struct security_mcode *boot_version)
|
|
{
|
|
char *tmp;
|
|
|
|
log_assert(boot_version);
|
|
|
|
tmp = security_mcode_to_str(boot_version);
|
|
|
|
log_misc("boot version: %s", tmp);
|
|
free(tmp);
|
|
|
|
memcpy(
|
|
&ezusb_iidx_emu_node_security_plug_boot_version,
|
|
boot_version,
|
|
sizeof(struct security_mcode));
|
|
}
|
|
|
|
void ezusb_iidx_emu_node_security_plug_set_boot_seeds(const uint32_t *seeds)
|
|
{
|
|
log_assert(seeds);
|
|
|
|
log_misc("boot seeds: %d %d %d", seeds[0], seeds[1], seeds[2]);
|
|
|
|
memcpy(
|
|
&ezusb_iidx_emu_node_security_plug_boot_seeds,
|
|
seeds,
|
|
sizeof(ezusb_iidx_emu_node_security_plug_boot_seeds));
|
|
}
|
|
|
|
void ezusb_iidx_emu_node_security_plug_set_plug_black_mcode(
|
|
const struct security_mcode *mcode)
|
|
{
|
|
char *tmp;
|
|
|
|
log_assert(mcode);
|
|
|
|
tmp = security_mcode_to_str(mcode);
|
|
|
|
log_misc("black mcode: %s", tmp);
|
|
free(tmp);
|
|
|
|
memcpy(
|
|
&ezusb_iidx_emu_node_security_plug_black_mcode,
|
|
mcode,
|
|
sizeof(struct security_mcode));
|
|
}
|
|
|
|
void ezusb_iidx_emu_node_security_plug_set_plug_white_mcode(
|
|
const struct security_mcode *mcode)
|
|
{
|
|
char *tmp;
|
|
|
|
log_assert(mcode);
|
|
|
|
tmp = security_mcode_to_str(mcode);
|
|
|
|
log_misc("white mcode: %s", tmp);
|
|
free(tmp);
|
|
|
|
memcpy(
|
|
&ezusb_iidx_emu_node_security_plug_white_mcode,
|
|
mcode,
|
|
sizeof(struct security_mcode));
|
|
}
|
|
|
|
void ezusb_iidx_emu_node_security_plug_set_pcbid(
|
|
const struct security_id *pcbid)
|
|
{
|
|
char *tmp;
|
|
|
|
tmp = security_id_to_str(pcbid, false);
|
|
|
|
log_misc("PCBID: %s", tmp);
|
|
free(tmp);
|
|
|
|
memcpy(
|
|
&ezusb_iidx_emu_node_security_plug_pcbid,
|
|
pcbid,
|
|
sizeof(struct security_id));
|
|
}
|
|
|
|
void ezusb_iidx_emu_node_security_plug_set_eamid(
|
|
const struct security_id *eamid)
|
|
{
|
|
char *tmp;
|
|
|
|
tmp = security_id_to_str(eamid, false);
|
|
|
|
log_misc("EAMID: %s", tmp);
|
|
free(tmp);
|
|
|
|
memcpy(
|
|
&ezusb_iidx_emu_node_security_plug_eamid,
|
|
eamid,
|
|
sizeof(struct security_id));
|
|
}
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
uint8_t ezusb_iidx_emu_node_security_plug_process_cmd_v1(
|
|
uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2)
|
|
{
|
|
switch (cmd_id) {
|
|
case EZUSB_IIDX_SECPLUG_CMD_V1_READ_ROM:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_READ_ROM");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM;
|
|
ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V1_READ_DATA:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_READ_DATA");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V1_SECURITY_CONVERSION:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_SECURITY_CONVERSION");
|
|
/* TODO ? */
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_BLACK_DONGLE:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_BLACK_DONGLE");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_WHITE_DONGLE:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V1_SELECT_WHITE_DONGLE");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_OK;
|
|
|
|
default:
|
|
log_warning("Unrecognised security plug v1 command: %02x", cmd_id);
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V1_FAULT;
|
|
}
|
|
}
|
|
|
|
uint8_t ezusb_iidx_emu_node_security_plug_process_cmd_v2(
|
|
uint8_t cmd_id, uint8_t cmd_data, uint8_t cmd_data2)
|
|
{
|
|
switch (cmd_id) {
|
|
case EZUSB_IIDX_SECPLUG_CMD_V2_INIT:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_INIT");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM;
|
|
ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_READ_DATA");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_DATA_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_READ_ROM");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM;
|
|
ezusb_iidx_emu_node_security_plug_enc_rom_data_seed = cmd_data;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_ROM_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE_2:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE_2");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_BLACK_DONGLE:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_BLACK_DONGLE");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
|
|
|
|
case EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE:
|
|
log_misc("EZUSB_IIDX_SECPLUG_CMD_V2_SELECT_WHITE_DONGLE");
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot =
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE;
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_SECURITY_SEL_OK;
|
|
|
|
default:
|
|
log_warning("Unrecognised security plug v2 command: %02x", cmd_id);
|
|
return EZUSB_IIDX_SECPLUG_CMD_STATUS_V2_FAIL;
|
|
}
|
|
}
|
|
|
|
bool ezusb_iidx_emu_node_security_plug_read_packet_v1(
|
|
struct ezusb_iidx_msg_bulk_packet *pkg)
|
|
{
|
|
char *tmp;
|
|
|
|
memset(pkg, 0x00, sizeof(struct ezusb_iidx_msg_bulk_packet));
|
|
|
|
if (ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM) {
|
|
tmp =
|
|
security_id_to_str(&ezusb_iidx_emu_node_security_plug_pcbid, false);
|
|
|
|
log_misc("Reading security plug v1 black rom, PCBID %s", tmp);
|
|
|
|
free(tmp);
|
|
|
|
if (!security_id_verify(&ezusb_iidx_emu_node_security_plug_pcbid)) {
|
|
log_fatal("PCBID verification failed");
|
|
return false;
|
|
}
|
|
|
|
pkg->node = 0x11;
|
|
pkg->page = 0x00;
|
|
|
|
memcpy(
|
|
pkg->payload,
|
|
&ezusb_iidx_emu_node_security_plug_pcbid,
|
|
sizeof(struct security_id));
|
|
|
|
ezusb_iidx_emu_node_security_plug_encrypt_rom_data(pkg->payload, 10);
|
|
} else if (
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA) {
|
|
log_misc("Reading security plug v1 black data");
|
|
|
|
pkg->node = 0x12;
|
|
pkg->page = 0x00;
|
|
|
|
security_rp_generate_signed_eeprom_data(
|
|
&ezusb_iidx_emu_node_security_plug_boot_version,
|
|
ezusb_iidx_emu_node_security_plug_boot_seeds,
|
|
&ezusb_iidx_emu_node_security_plug_black_mcode,
|
|
&ezusb_iidx_emu_node_security_plug_pcbid,
|
|
(struct security_rp_eeprom *) pkg->payload);
|
|
|
|
/* the signed test vector will be compared to the eeprom contents
|
|
write test vector to eeprom to pass checks */
|
|
ezusb_iidx_emu_node_eeprom_write_memory(pkg->payload, 6, 6);
|
|
} else if (
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM) {
|
|
tmp =
|
|
security_id_to_str(&ezusb_iidx_emu_node_security_plug_eamid, false);
|
|
|
|
log_misc("Reading security plug v1 white rom, EAMID %s", tmp);
|
|
|
|
free(tmp);
|
|
|
|
if (!security_id_verify(&ezusb_iidx_emu_node_security_plug_eamid)) {
|
|
log_fatal("EAMID verification failed");
|
|
return false;
|
|
}
|
|
|
|
pkg->node = 0x11;
|
|
pkg->page = 0x00;
|
|
|
|
memcpy(
|
|
pkg->payload,
|
|
&ezusb_iidx_emu_node_security_plug_eamid,
|
|
sizeof(struct security_id));
|
|
|
|
ezusb_iidx_emu_node_security_plug_encrypt_rom_data(pkg->payload, 10);
|
|
} else if (
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA) {
|
|
log_misc("Reading security plug v1 white data");
|
|
|
|
pkg->node = 0x12;
|
|
pkg->page = 0x00;
|
|
|
|
security_rp_generate_signed_eeprom_data(
|
|
&ezusb_iidx_emu_node_security_plug_boot_version,
|
|
ezusb_iidx_emu_node_security_plug_boot_seeds,
|
|
&ezusb_iidx_emu_node_security_plug_white_mcode,
|
|
&ezusb_iidx_emu_node_security_plug_eamid,
|
|
(struct security_rp_eeprom *) pkg->payload);
|
|
|
|
/* XXX position 0 not verified, guess
|
|
the test vector will be compared against eeprom contents
|
|
write test vector to eeprom to pass checks */
|
|
ezusb_iidx_emu_node_eeprom_write_memory(pkg->payload, 0, 6);
|
|
} else {
|
|
log_warning("Invalid security plug v1 read");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ezusb_iidx_emu_node_security_plug_read_packet_v2(
|
|
struct ezusb_iidx_msg_bulk_packet *pkg)
|
|
{
|
|
char *tmp;
|
|
|
|
log_misc("Reading security plug v2 packet");
|
|
|
|
memset(pkg, 0x00, sizeof(struct ezusb_iidx_msg_bulk_packet));
|
|
|
|
if (ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM) {
|
|
tmp =
|
|
security_id_to_str(&ezusb_iidx_emu_node_security_plug_pcbid, false);
|
|
|
|
log_misc("Reading security plug v2 black rom, PCBID %s", tmp);
|
|
|
|
free(tmp);
|
|
|
|
if (!security_id_verify(&ezusb_iidx_emu_node_security_plug_pcbid)) {
|
|
log_fatal("PCBID verification failed");
|
|
return false;
|
|
}
|
|
|
|
pkg->node = 0x11;
|
|
pkg->page = 0x00;
|
|
|
|
memcpy(
|
|
pkg->payload,
|
|
&ezusb_iidx_emu_node_security_plug_pcbid,
|
|
sizeof(struct security_id));
|
|
|
|
ezusb_iidx_emu_node_security_plug_encrypt_rom_data(pkg->payload, 10);
|
|
} else if (
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_BLACK &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA) {
|
|
log_misc("Reading security plug v2 black data");
|
|
|
|
pkg->node = 0x12;
|
|
pkg->page = 0x00;
|
|
|
|
security_rp2_generate_signed_eeprom_data(
|
|
SECURITY_RP_UTIL_RP_TYPE_BLACK,
|
|
&ezusb_iidx_emu_node_security_plug_boot_version,
|
|
&ezusb_iidx_emu_node_security_plug_black_mcode,
|
|
&ezusb_iidx_emu_node_security_plug_pcbid,
|
|
(struct security_rp2_eeprom *) pkg->payload);
|
|
} else if (
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_ROM) {
|
|
tmp =
|
|
security_id_to_str(&ezusb_iidx_emu_node_security_plug_eamid, false);
|
|
|
|
log_misc("Reading security plug v2 white rom, EAMID %s", tmp);
|
|
|
|
free(tmp);
|
|
|
|
if (!security_id_verify(&ezusb_iidx_emu_node_security_plug_eamid)) {
|
|
log_fatal("EAMID verification failed");
|
|
return false;
|
|
}
|
|
|
|
pkg->node = 0x11;
|
|
pkg->page = 0x00;
|
|
|
|
memcpy(
|
|
pkg->payload,
|
|
&ezusb_iidx_emu_node_security_plug_eamid,
|
|
sizeof(struct security_id));
|
|
|
|
ezusb_iidx_emu_node_security_plug_encrypt_rom_data(pkg->payload, 10);
|
|
} else if (
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_slot ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_SLOT_WHITE &&
|
|
ezusb_iidx_emu_node_security_plug_active_dongle_mem ==
|
|
EZUSB_IIDX_SECPLUG_DONGLE_MEM_DATA) {
|
|
log_misc("Reading security plug v2 white data");
|
|
|
|
pkg->node = 0x12;
|
|
pkg->page = 0x00;
|
|
|
|
security_rp2_generate_signed_eeprom_data(
|
|
SECURITY_RP_UTIL_RP_TYPE_WHITE,
|
|
&ezusb_iidx_emu_node_security_plug_boot_version,
|
|
&ezusb_iidx_emu_node_security_plug_white_mcode,
|
|
&ezusb_iidx_emu_node_security_plug_eamid,
|
|
(struct security_rp2_eeprom *) pkg->payload);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ezusb_iidx_emu_node_security_plug_write_packet(
|
|
const struct ezusb_iidx_msg_bulk_packet *pkg)
|
|
{
|
|
log_misc("Writing security plug packet");
|
|
return true;
|
|
}
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
static void ezusb_iidx_emu_node_security_plug_encrypt_rom_data(
|
|
uint8_t *buffer, uint8_t length)
|
|
{
|
|
uint8_t data;
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
data = ezusb_iidx_emu_node_security_mem_read_memory(
|
|
(ezusb_iidx_emu_node_security_plug_enc_rom_data_seed + i) & 0xFF);
|
|
/*
|
|
log_misc("Encrypting %02X, seed %02X with sec mem lookup %02X",
|
|
buffer[i], ezusb_iidx_emu_node_security_plug_enc_rom_data_seed,
|
|
data);
|
|
*/
|
|
buffer[i] ^= data;
|
|
}
|
|
} |