Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions cli/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2346,6 +2346,7 @@ static int fw_read(int argc, char **argv)
int bl2;
int key;
int pmap;
int debug_token;
int no_progress_bar;
} cfg = {
.out_fd = -1
Expand All @@ -2364,21 +2365,26 @@ static int fw_read(int argc, char **argv)
{"bl2", 'b', "", CFG_NONE, &cfg.bl2, no_argument,
"read the BL2 partiton instead of the main firmware"},
{"key", 'k', "", CFG_NONE, &cfg.key, no_argument,
"read the key manifest partiton instead of the main firmware - Gen5 and below only"},
"read the key manifest partiton instead of the main firmware"},
{"pmap", 'm', "", CFG_NONE, &cfg.pmap, no_argument,
"read the partition map instead of the main firmware - Gen6"},
{"token", 't', "", CFG_NONE, &cfg.debug_token, no_argument,
"read the debug token instead of the main firmware - Gen6"},
{"no-progress", 'p', "", CFG_NONE, &cfg.no_progress_bar, no_argument,
"don't print progress to stdout"},
{NULL}};

argconfig_parse(argc, argv, CMD_DESC_FW_READ, opts, &cfg, sizeof(cfg));

if (!switchtec_is_gen6(cfg.dev) && cfg.pmap) {
fprintf(stderr, "Getting the parition map is only available on Gen6 Switchtec device!\n");
fprintf(stderr, "Getting the parition map is only available \
on Gen6 Switchtec device!\n");
return -1;
}
if (switchtec_is_gen6(cfg.dev) && cfg.key) {
fprintf(stderr, "Getting the key manifest is not available on Gen6 Switchtec device!\n");

if (!switchtec_is_gen6(cfg.dev) && cfg.debug_token) {
fprintf(stderr, "Getting the debug token is only available \
on Gen6 Switchtec device!\n");
return -1;
}

Expand All @@ -2405,9 +2411,13 @@ static int fw_read(int argc, char **argv)
fw_typ_gen6 = SWITCHTEC_IMG_PART_TYPE_BL2;
} else if (cfg.key) {
inf = cfg.inactive ? sum->key.inactive : sum->key.active;
fw_typ_gen6 = SWITCHTEC_IMG_PART_TYPE_KMT;
} else if (cfg.pmap) {
inf = cfg.inactive ? sum->map.inactive : sum->map.active;
fw_typ_gen6 = SWITCHTEC_IMG_PART_TYPE_MAP;
} else if (cfg.debug_token) {
inf = cfg.inactive ? sum->token.inactive : sum->token.active;
fw_typ_gen6 = SWITCHTEC_IMG_PART_TYPE_DEBUG_TOKEN;
} else {
inf = cfg.inactive ? sum->img.inactive : sum->img.active;
fw_typ_gen6 = SWITCHTEC_IMG_PART_TYPE_FW;
Expand Down Expand Up @@ -2446,11 +2456,12 @@ static int fw_read(int argc, char **argv)
fw_slot = (fw_slot % 2) ? 0 : 1;
progress_start();
if (cfg.no_progress_bar)
ret = switchtec_fw_img_get(cfg.dev, cfg.out_fd, fw_typ_gen6,
fw_slot, NULL);
ret = switchtec_fw_img_get(cfg.dev, cfg.out_fd,
fw_typ_gen6, fw_slot, NULL);
else
ret = switchtec_fw_img_get(cfg.dev, cfg.out_fd, fw_typ_gen6,
fw_slot, progress_update);
ret = switchtec_fw_img_get(cfg.dev, cfg.out_fd,
fw_typ_gen6, fw_slot,
progress_update);
} else {
ret = switchtec_fw_img_write_hdr(cfg.out_fd, inf);
if (ret < 0) {
Expand All @@ -2460,11 +2471,11 @@ static int fw_read(int argc, char **argv)

progress_start();
if (cfg.no_progress_bar)
ret = switchtec_fw_body_read_fd(cfg.dev, cfg.out_fd,
inf, NULL);
ret = switchtec_fw_body_read_fd(cfg.dev, cfg.out_fd,
inf, NULL);
else
ret = switchtec_fw_body_read_fd(cfg.dev, cfg.out_fd,
inf, progress_update);
inf, progress_update);
}
switchtec_fw_part_summary_free(sum);
progress_finish(cfg.no_progress_bar);
Expand Down
110 changes: 89 additions & 21 deletions cli/mfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ static int info(int argc, char **argv)
printf("Secure Unlock Version: \t\t\t0x%08x\n", sn_info.ver_sec_unlock);
}

if (phase_id == SWITCHTEC_BOOT_PHASE_BL2) {
if (!switchtec_is_gen6(cfg.dev) && phase_id == SWITCHTEC_BOOT_PHASE_BL2) {
printf("\nOther secure settings are only shown in the BL1 or Main Firmware phase.\n\n");
return 0;
}
Expand Down Expand Up @@ -1342,6 +1342,7 @@ static int debug_unlock(int argc, char **argv)
int ret;
struct switchtec_pubkey pubk;
struct switchtec_signature sig;
struct switchtec_gen6_token token;

const char *desc = CMD_DESC_DEBUG_UNLOCK "\n\n"
"This command unlocks the EJTAG port, Command Line "
Expand All @@ -1355,6 +1356,8 @@ static int debug_unlock(int argc, char **argv)
unsigned long serial;
FILE *sig_fimg;
char *sig_file;
FILE *tkn_fimg;
char *tkn_file;
} cfg = {
.unlock_version = 0xffff,
};
Expand All @@ -1376,6 +1379,10 @@ static int debug_unlock(int argc, char **argv)
.value_addr=&cfg.sig_fimg,
.argument_type=required_argument,
.help="signature file"},
{"token_file", 't', .cfg_type=CFG_FILE_R,
.value_addr=&cfg.tkn_fimg,
.argument_type=required_argument,
.help="token file - Gen6 only"},
{NULL}
};

Expand Down Expand Up @@ -1405,6 +1412,18 @@ static int debug_unlock(int argc, char **argv)
return -1;
}

if (cfg.tkn_file == NULL && switchtec_is_gen6(cfg.dev)) {
fprintf(stderr,
"Token file must be set for Gen6 devices using this command!\n");
return -1;
}

if(cfg.tkn_file != NULL && !switchtec_is_gen6(cfg.dev)) {
fprintf(stderr,
"Ignoring token file parameter, this device is not Gen6!\n");
cfg.tkn_file = NULL;
}

ret = switchtec_read_pubk_file(cfg.pubkey_fimg, &pubk);
fclose(cfg.pubkey_fimg);

Expand All @@ -1423,8 +1442,19 @@ static int debug_unlock(int argc, char **argv)
return -3;
}

if (switchtec_is_gen6(cfg.dev)) {
ret = switchtec_read_token_file(cfg.tkn_fimg, &token);
fclose(cfg.tkn_fimg);

if (ret) {
fprintf(stderr, "Invalid token file %s!\n",
cfg.tkn_file);
return -3;
}
}

ret = switchtec_dbg_unlock(cfg.dev, cfg.serial, cfg.unlock_version,
&pubk, &sig);
&pubk, &sig, &token);
if (ret)
switchtec_perror("mfg dbg-unlock");

Expand Down Expand Up @@ -1577,6 +1607,10 @@ static int debug_unlock_token(int argc, char **argv)
"Generate token for signature file required for command 'mfg debug-unlock' (default)"},
{"UNLOCK_VERSION_UPDATE", TOKEN_VERSION_UPDATE,
"Generate token for signature file required for command 'mfg debug-lock-update'"},
{"GEN6_STATIC_TOKEN", GEN6_TOKEN_STATIC,
"Generate static token for signature file required for command 'mfg debug-unlock' on Gen6 devices"},
{"GEN6_EPHEMERAL_TOKEN", GEN6_TOKEN_EPHEMERAL,
"Generate ephemeral token for signature file required for command 'mfg debug-unlock' on Gen6 devices"},
{}
};

Expand Down Expand Up @@ -1604,30 +1638,64 @@ static int debug_unlock_token(int argc, char **argv)

argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg));

ret = switchtec_sn_ver_get(cfg.dev, &sn_info);
if (ret) {
switchtec_perror("mfg debug unlock token");
return ret;
}
if (switchtec_is_gen6(cfg.dev))
{
if (cfg.type != GEN6_TOKEN_STATIC &&
cfg.type != GEN6_TOKEN_EPHEMERAL) {
fprintf(stderr,
"On Gen6 devices, only GEN6_STATIC_TOKEN \
and GEN6_EPHEMERAL_TOKEN types are supported.\n");
return -1;
}

struct switchtec_gen6_token token;

ret = switchtec_dbg_unlock_get_token_gen6(cfg.dev, &token, cfg.type);
if (ret) {
switchtec_perror("mfg debug unlock token");
return ret;
}

token.serial = htole32(sn_info.chip_serial);
ret = write(cfg.out_fd, &token, sizeof(token));
if(ret <= 0) {
switchtec_perror("mfg debug gen6 unlock token");
return ret;
}

if (cfg.type == TOKEN_RESOURCE_UNLOCK) {
token.id = htole32(1);
token.version = htole32(sn_info.ver_sec_unlock);
fprintf(stderr, "\nToken data saved to %s\n", cfg.out_filename);
close(cfg.out_fd);
} else {
token.id = htole32(2);
token.version = htole32(sn_info.ver_sec_unlock) + 1;
}
if (cfg.type == GEN6_TOKEN_STATIC ||
cfg.type == GEN6_TOKEN_EPHEMERAL) {
fprintf(stderr,
"Gen6 types are not supported on this device.\n");
return -1;
}
ret = switchtec_sn_ver_get(cfg.dev, &sn_info);
if (ret) {
switchtec_perror("mfg debug unlock token");
return ret;
}

ret = write(cfg.out_fd, &token, sizeof(token));
if(ret <= 0) {
switchtec_perror("mfg debug unlock token");
return ret;
}
token.serial = htole32(sn_info.chip_serial);

fprintf(stderr, "\nToken data saved to %s\n", cfg.out_filename);
close(cfg.out_fd);
if (cfg.type == TOKEN_RESOURCE_UNLOCK) {
token.id = htole32(1);
token.version = htole32(sn_info.ver_sec_unlock);
} else {
token.id = htole32(2);
token.version = htole32(sn_info.ver_sec_unlock) + 1;
}

ret = write(cfg.out_fd, &token, sizeof(token));
if(ret <= 0) {
switchtec_perror("mfg debug unlock token");
return ret;
}

fprintf(stderr, "\nToken data saved to %s\n", cfg.out_filename);
close(cfg.out_fd);
}

return 0;
}
Expand Down
40 changes: 39 additions & 1 deletion inc/switchtec/mfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
#define SWITCHTEC_KMSK_NUM_MAX 10
#define SWITCHTEC_KMSK_NUM_GEN6 12
#define SWITCHTEC_KMSK_LEN_DWORDS (SWITCHTEC_KMSK_LEN / 4)
#define SWITCHTEC_GEN6_TOKEN_LEN 104

#define OTP_MULTI_DWORD_UID_UNIQUEID_DWORDS 16
#define OTP_MULTI_DWORD_CUSTOMER_PSID0_DWORDS 4

#define SWITCHTEC_SECURITY_SPI_RATE_MAX_NUM 16

Expand Down Expand Up @@ -208,6 +212,20 @@ struct switchtec_security_cfg_state {
struct switchtec_attestation_state attn_state;
};

/**
* @brief Supported KMT Signature Formats. Value stored in KMT Prefix in 4 bit field.
*/
enum kmt_signature_types_e
{
KMT_SIG_FORMAT_CRC = 0,
KMT_SIG_FORMAT_RSA3KSHA2 = 1,
KMT_SIG_FORMAT_RSA4KSHA2 = 2,
KMT_SIG_FORMAT_ECDSAP384SHA2 = 3,
KMT_SIG_FORMAT_ECDSAP521SHA2 = 4,
KMT_SIG_FORMAT_DILITHIUM5 = 5,
KMT_SIG_FORMAT_MAX
};

enum switchtec_otp_key_status {
UNPROGRAMMED = 0x00,
PROGRAMMED = 0x01,
Expand Down Expand Up @@ -259,6 +277,17 @@ enum switchtec_bl2_recovery_mode {
SWITCHTEC_BL2_RECOVERY_I2C_AND_XMODEM = 3
};

#define TOKEN_RESOURCE_UNLOCK 0
#define TOKEN_VERSION_UPDATE 1
#define GEN6_TOKEN_STATIC 2
#define GEN6_TOKEN_EPHEMERAL 3

enum secure_token_get_types_e {
SECURE_TOKEN_GET_TYPE_STATIC = 0,
SECURE_TOKEN_GET_TYPE_EPHEMERAL = 1,
SECURE_TOKEN_GET_TYPE_MAX
};

struct switchtec_kmsk {
uint8_t kmsk[SWITCHTEC_KMSK_LEN];
};
Expand All @@ -272,6 +301,10 @@ struct switchtec_signature{
uint8_t signature[SWITCHTEC_SIG_LEN];
};

struct switchtec_gen6_token{
uint8_t token[SWITCHTEC_GEN6_TOKEN_LEN];
};

struct switchtec_uds {
unsigned char uds[SWITCHTEC_UDS_LEN];
};
Expand Down Expand Up @@ -312,19 +345,24 @@ int switchtec_secure_state_set(struct switchtec_dev *dev,
int switchtec_dbg_unlock(struct switchtec_dev *dev, uint32_t serial,
uint32_t ver_sec_unlock,
struct switchtec_pubkey *public_key,
struct switchtec_signature *signature);
struct switchtec_signature *signature,
struct switchtec_gen6_token *token);
int switchtec_dbg_unlock_version_update(struct switchtec_dev *dev,
uint32_t serial,
uint32_t ver_sec_unlock,
struct switchtec_pubkey *public_key,
struct switchtec_signature *signature);
int switchtec_dbg_unlock_get_token_gen6(struct switchtec_dev *dev,
struct switchtec_gen6_token *token,
int token_type);
int switchtec_read_sec_cfg_file(struct switchtec_dev *dev,
FILE *setting_file,
struct switchtec_security_cfg_set *set);
int switchtec_read_pubk_file(FILE *pubk_file, struct switchtec_pubkey *pubk);
int switchtec_read_kmsk_file(FILE *kmsk_file, struct switchtec_kmsk *kmsk);
int switchtec_read_signature_file(FILE *sig_file,
struct switchtec_signature *sigature);
int switchtec_read_token_file(FILE *tkn_file, struct switchtec_gen6_token *token);
int switchtec_read_uds_file(FILE *uds_file, struct switchtec_uds *uds);
int
switchtec_security_state_has_kmsk(struct switchtec_security_cfg_state *state,
Expand Down
7 changes: 7 additions & 0 deletions inc/switchtec/mrpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,13 @@ enum mrpc_sub_cmd {
MRPC_DBG_UNLOCK_DATA = 1,
MRPC_DBG_UNLOCK_UPDATE = 2,

MRPC_GEN6_DBG_UNLOCK_PKEY = 0,
MRPC_GEN6_DBG_UNLOCK_SIG = 1,
MRPC_GEN6_DBG_UNLOCK_STATIC = 2,
MRPC_GEN6_DBG_SEC_VER_UPDATE = 3,
MRPC_GEN6_DBG_UNLOCK_STATIC_DISABLE = 4,
MRPC_GEN6_DBG_UNLOCK_TOKEN_GET = 5,

MRPC_KMSK_ENTRY_SET_PKEY = 0,
MRPC_KMSK_ENTRY_SET_SIG = 1,
MRPC_KMSK_ENTRY_SET_KMSK = 2,
Expand Down
2 changes: 1 addition & 1 deletion inc/switchtec/switchtec.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ struct switchtec_fw_image_info {
struct switchtec_fw_part_summary {
struct switchtec_fw_part_type {
struct switchtec_fw_image_info *active, *inactive;
} boot, map, img, cfg, nvlog, seeprom, key, bl2, riot;
} boot, map, img, cfg, nvlog, seeprom, key, bl2, riot, token;

struct switchtec_fw_image_info *mult_cfg;

Expand Down
Loading