46 #include "switchtec_priv.h" 48 #include "switchtec/mfg.h" 49 #include "switchtec/errors.h" 50 #include "switchtec/endian.h" 51 #include "switchtec/mrpc.h" 52 #include "switchtec/errors.h" 63 #include <openssl/pem.h> 66 #define SWITCHTEC_ACTV_IMG_ID_KMAN 1 67 #define SWITCHTEC_ACTV_IMG_ID_BL2 2 68 #define SWITCHTEC_ACTV_IMG_ID_CFG 3 69 #define SWITCHTEC_ACTV_IMG_ID_FW 4 71 #define SWITCHTEC_MB_MAX_ENTRIES 8 72 #define SWITCHTEC_ACTV_IDX_MAX_ENTRIES 32 73 #define SWITCHTEC_ACTV_IDX_SET_ENTRIES 4 75 #define SWITCHTEC_CLK_RATE_BITSHIFT 10 76 #define SWITCHTEC_CLK_RATE_BITMASK 0x0f 77 #define SWITCHTEC_RC_TMO_BITSHIFT 14 78 #define SWITCHTEC_RC_TMO_BITMASK 0x0f 79 #define SWITCHTEC_I2C_PORT_BITSHIFT 18 80 #define SWITCHTEC_I2C_PORT_BITMASK 0x0f 81 #define SWITCHTEC_I2C_ADDR_BITSHIFT 22 82 #define SWITCHTEC_I2C_ADDR_BITMASK 0x7f 83 #define SWITCHTEC_CMD_MAP_BITSHIFT 29 84 #define SWITCHTEC_CMD_MAP_BITMASK 0xfff 86 #define SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK 0x40 87 #define SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK 0x80 88 #define SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK 0x0100 89 #define SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK 0x0200 91 #if (HAVE_LIBCRYPTO && !HAVE_DECL_RSA_GET0_KEY) 96 static void RSA_get0_key(
const RSA *r,
const BIGNUM **n,
97 const BIGNUM **e,
const BIGNUM **d)
108 static int switchtec_mfg_cmd(
struct switchtec_dev *dev, uint32_t cmd,
109 const void *payload,
size_t payload_len,
110 void *resp,
size_t resp_len)
112 if (dev->ops->flags & SWITCHTEC_OPS_FLAG_NO_MFG) {
113 errno = ERR_UART_NOT_SUPPORTED | SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
132 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET, NULL, 0, info,
137 info->chip_serial = le32toh(info->chip_serial);
138 info->ver_bl2 = le32toh(info->ver_bl2);
139 info->ver_km = le32toh(info->ver_km);
140 info->ver_main = le32toh(info->ver_main);
141 info->ver_sec_unlock = le32toh(info->ver_sec_unlock);
160 uint32_t public_key_exponent;
162 uint8_t public_key_num;
163 uint8_t public_key_ver;
165 uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
169 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET, NULL, 0,
170 &reply,
sizeof(reply));
174 reply.valid = le32toh(reply.valid);
175 reply.cfg = le64toh(reply.cfg);
176 reply.public_key_exponent = le32toh(reply.public_key_exponent);
178 state->basic_setting_valid = !!(reply.valid & 0x01);
179 state->public_key_exp_valid = !!(reply.valid & 0x02);
180 state->public_key_num_valid = !!(reply.valid & 0x04);
181 state->public_key_ver_valid = !!(reply.valid & 0x08);
182 state->public_key_valid = !!(reply.valid & 0x10);
184 state->debug_mode = reply.cfg & 0x03;
185 state->secure_state = (reply.cfg>>2) & 0x03;
187 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
188 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
189 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
190 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
192 state->spi_clk_rate =
193 (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
194 if (state->spi_clk_rate == 0)
195 state->spi_clk_rate = SWITCHTEC_SPI_RATE_25M;
197 state->i2c_recovery_tmo =
198 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
199 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
200 state->i2c_addr = (reply.cfg >> SWITCHTEC_I2C_ADDR_BITSHIFT) & 0x7f;
202 (reply.cfg >> SWITCHTEC_CMD_MAP_BITSHIFT) & 0xfff;
204 state->public_key_exponent = reply.public_key_exponent;
205 state->public_key_num = reply.public_key_num;
206 state->public_key_ver = reply.public_key_ver;
207 memcpy(state->public_key, reply.public_key,
208 SWITCHTEC_KMSK_NUM * SWITCHTEC_KMSK_LEN);
222 int num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
224 uint8_t num_returned;
225 uint8_t num_remaining;
227 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
228 SWITCHTEC_MB_LOG_LEN];
232 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET, &num_to_read,
233 sizeof(
int), &reply,
sizeof(reply));
237 reply.num_remaining = le32toh(reply.num_remaining);
238 reply.num_returned = le32toh(reply.num_returned);
240 ret = write(fd, reply.data,
241 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
244 }
while (reply.num_remaining > 0);
259 struct setting_data {
261 uint32_t pub_key_exponent;
266 memset(&sd, 0,
sizeof(sd));
268 sd.cfg |= setting->jtag_lock_after_reset?
269 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
270 sd.cfg |= setting->jtag_lock_after_bl1?
271 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
272 sd.cfg |= setting->jtag_bl1_unlock_allowed?
273 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
274 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
275 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
277 sd.cfg |= (setting->spi_clk_rate & SWITCHTEC_CLK_RATE_BITMASK) <<
278 SWITCHTEC_CLK_RATE_BITSHIFT;
280 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
281 SWITCHTEC_RC_TMO_BITSHIFT;
282 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
283 SWITCHTEC_I2C_PORT_BITSHIFT;
284 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
285 SWITCHTEC_I2C_ADDR_BITSHIFT;
287 ldata = setting->i2c_cmd_map & SWITCHTEC_CMD_MAP_BITMASK;
288 ldata <<= SWITCHTEC_CMD_MAP_BITSHIFT;
291 sd.cfg = htole64(sd.cfg);
293 sd.pub_key_exponent = htole32(setting->public_key_exponent);
295 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET, &sd,
sizeof(sd),
310 struct active_indices {
311 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
314 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET, NULL,
315 0, &reply,
sizeof(reply));
319 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN];
320 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2];
321 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG];
322 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW];
343 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
346 memset(&
set, 0,
sizeof(
set));
348 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
349 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN;
350 set.idx[i].index = index->keyman;
354 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
355 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2;
356 set.idx[i].index = index->bl2;
360 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
361 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG;
362 set.idx[i].index = index->config;
366 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
367 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW;
368 set.idx[i].index = index->firmware;
375 set.count = htole32(i);
377 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET, &
set,
378 sizeof(
set), NULL, 0);
389 enum switchtec_bl2_recovery_mode recovery_mode)
391 struct fw_exec_struct {
393 uint8_t recovery_mode;
397 memset(&cmd, 0,
sizeof(cmd));
398 cmd.subcmd = MRPC_FW_TX_EXEC;
399 cmd.recovery_mode = recovery_mode;
401 return switchtec_mfg_cmd(dev, MRPC_FW_TX, &cmd,
sizeof(cmd), NULL, 0);
418 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME, NULL, 0,
429 enum switchtec_secure_state state)
433 if ((state != SWITCHTEC_INITIALIZED_UNSECURED)
434 && (state != SWITCHTEC_INITIALIZED_SECURED)) {
435 return ERR_PARAM_INVALID;
437 data = htole32(state);
439 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET, &data,
440 sizeof(data), NULL, 0);
443 static int dbg_unlock_send_pubkey(
struct switchtec_dev *dev,
446 struct public_key_cmd {
449 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
450 uint32_t pub_key_exp;
453 cmd.subcmd = MRPC_DBG_UNLOCK_PKEY;
454 memcpy(cmd.pub_key, public_key->pubkey, SWITCHTEC_PUB_KEY_LEN);
455 cmd.pub_key_exp = htole32(public_key->pubkey_exp);
457 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
458 sizeof(cmd), NULL, 0);
471 uint32_t ver_sec_unlock,
481 uint8_t signature[SWITCHTEC_SIG_LEN];
484 ret = dbg_unlock_send_pubkey(dev, public_key);
488 cmd.subcmd = MRPC_DBG_UNLOCK_DATA;
489 cmd.serial = htole32(serial);
490 cmd.unlock_ver = htole32(ver_sec_unlock);
491 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
493 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
494 sizeof(cmd), NULL, 0);
508 uint32_t ver_sec_unlock,
518 uint8_t signature[SWITCHTEC_SIG_LEN];
521 ret = dbg_unlock_send_pubkey(dev, public_key);
525 cmd.subcmd = MRPC_DBG_UNLOCK_UPDATE;
526 cmd.serial = htole32(serial);
527 cmd.unlock_ver = htole32(ver_sec_unlock);
528 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
530 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
sizeof(cmd),
544 char magic[4] = {
'S',
'S',
'F',
'F'};
546 struct setting_file_header {
552 struct setting_file_data {
554 uint32_t pub_key_exponent;
557 struct setting_file {
558 struct setting_file_header header;
559 struct setting_file_data data;
562 rlen = fread(&file_data, 1,
sizeof(file_data), setting_file);
564 if (rlen <
sizeof(file_data))
567 if (memcmp(file_data.header.magic, magic,
sizeof(magic)))
570 crc = crc32((uint8_t*)&file_data.data,
571 sizeof(file_data.data), 0, 1, 1);
572 if (crc != le32toh(file_data.header.crc))
577 file_data.data.cfg = le64toh(file_data.data.cfg);
579 set->jtag_lock_after_reset =
580 !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
581 set->jtag_lock_after_bl1 =
582 !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
583 set->jtag_bl1_unlock_allowed =
584 !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
585 set->jtag_post_bl1_unlock_allowed =
586 !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
589 (file_data.data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
590 SWITCHTEC_CLK_RATE_BITMASK;
591 set->i2c_recovery_tmo =
592 (file_data.data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
593 SWITCHTEC_RC_TMO_BITMASK;
595 (file_data.data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
596 SWITCHTEC_I2C_PORT_BITMASK;
598 (file_data.data.cfg >> SWITCHTEC_I2C_ADDR_BITSHIFT) &
599 SWITCHTEC_I2C_ADDR_BITMASK;
601 (file_data.data.cfg >> SWITCHTEC_CMD_MAP_BITSHIFT) &
602 SWITCHTEC_CMD_MAP_BITMASK;
604 set->public_key_exponent = le32toh(file_data.data.pub_key_exponent);
609 static int kmsk_set_send_pubkey(
struct switchtec_dev *dev,
612 struct kmsk_pubk_cmd {
615 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
616 uint32_t pub_key_exponent;
619 cmd.subcmd = MRPC_KMSK_ENTRY_SET_PKEY;
620 memcpy(cmd.pub_key, public_key->pubkey,
621 SWITCHTEC_PUB_KEY_LEN);
622 cmd.pub_key_exponent = htole32(public_key->pubkey_exp);
624 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
625 sizeof(cmd), NULL, 0);
628 static int kmsk_set_send_signature(
struct switchtec_dev *dev,
631 struct kmsk_signature_cmd {
634 uint8_t signature[SWITCHTEC_SIG_LEN];
637 cmd.subcmd = MRPC_KMSK_ENTRY_SET_SIG;
638 memcpy(cmd.signature, signature->signature,
641 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
642 sizeof(cmd), NULL, 0);
645 static int kmsk_set_send_kmsk(
struct switchtec_dev *dev,
648 struct kmsk_kmsk_cmd {
652 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
655 cmd.subcmd = MRPC_KMSK_ENTRY_SET_KMSK;
657 memcpy(cmd.kmsk, kmsk->kmsk, SWITCHTEC_KMSK_LEN);
659 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
sizeof(cmd),
683 ret = kmsk_set_send_pubkey(dev, public_key);
689 ret = kmsk_set_send_signature(dev, signature);
694 return kmsk_set_send_kmsk(dev, kmsk);
704 int switchtec_read_pubk_file(FILE *pubk_file,
struct switchtec_pubkey *pubk)
707 const BIGNUM *modulus_bn;
708 const BIGNUM *exponent_bn;
709 uint32_t exponent_tmp = 0;
711 RSAKey = PEM_read_RSA_PUBKEY(pubk_file, NULL, NULL, NULL);
712 if (RSAKey == NULL) {
713 fseek(pubk_file, 0L, SEEK_SET);
714 RSAKey = PEM_read_RSAPrivateKey(pubk_file, NULL, NULL, NULL);
719 RSA_get0_key(RSAKey, &modulus_bn, &exponent_bn, NULL);
721 BN_bn2bin(modulus_bn, pubk->pubkey);
722 BN_bn2bin(exponent_bn, (uint8_t *)&exponent_tmp);
724 pubk->pubkey_exp = be32toh(exponent_tmp);
745 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
748 char magic[4] = {
'K',
'M',
'S',
'K'};
751 rlen = fread(&data, 1,
sizeof(data), kmsk_file);
753 if (rlen <
sizeof(data))
756 if (memcmp(data.magic, magic,
sizeof(magic)))
759 crc = crc32(data.kmsk, SWITCHTEC_KMSK_LEN, 0, 1, 1);
760 if (crc != le32toh(data.crc32))
763 memcpy(kmsk->kmsk, data.kmsk, SWITCHTEC_KMSK_LEN);
779 rlen = fread(signature->signature, 1, SWITCHTEC_SIG_LEN, sig_file);
781 if (rlen < SWITCHTEC_SIG_LEN)
803 for(key_idx = 0; key_idx < state->public_key_num; key_idx++) {
804 if (memcmp(state->public_key[key_idx], kmsk->kmsk,
805 SWITCHTEC_KMSK_LEN) == 0)
int switchtec_active_image_index_get(struct switchtec_dev *dev, struct switchtec_active_index *index)
Get active image index.
int switchtec_fw_exec(struct switchtec_dev *dev, enum switchtec_bl2_recovery_mode recovery_mode)
Execute the transferred firmware.
int switchtec_kmsk_set(struct switchtec_dev *dev, struct switchtec_pubkey *public_key, struct switchtec_signature *signature, struct switchtec_kmsk *kmsk)
Set KMSK entry KMSK stands for Key Manifest Secure Key. It is a key used to verify Key Manifest parti...
int switchtec_mailbox_to_file(struct switchtec_dev *dev, int fd)
Retrieve mailbox entries.
int switchtec_read_sec_cfg_file(FILE *setting_file, struct switchtec_security_cfg_set *set)
Read security settings from config file.
int switchtec_secure_state_set(struct switchtec_dev *dev, enum switchtec_secure_state state)
Set device secure state.
int switchtec_read_signature_file(FILE *sig_file, struct switchtec_signature *signature)
Read signature data from signature file.
int switchtec_sn_ver_get(struct switchtec_dev *dev, struct switchtec_sn_ver_info *info)
Get serial number and security version.
int switchtec_security_config_set(struct switchtec_dev *dev, struct switchtec_security_cfg_set *setting)
Set secure settings.
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)
Update firmware debug secure unlock version number.
int switchtec_read_kmsk_file(FILE *kmsk_file, struct switchtec_kmsk *kmsk)
Read KMSK data from KMSK file.
int switchtec_security_config_get(struct switchtec_dev *dev, struct switchtec_security_cfg_state *state)
Get secure boot configurations.
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)
Unlock firmware debug features.
int switchtec_boot_resume(struct switchtec_dev *dev)
Resume device boot. Note that after calling this function, the current 'dev' pointer is no longer val...
int switchtec_cmd(struct switchtec_dev *dev, uint32_t cmd, const void *payload, size_t payload_len, void *resp, size_t resp_len)
Execute an MRPC command.
int switchtec_security_state_has_kmsk(struct switchtec_security_cfg_state *state, struct switchtec_kmsk *kmsk)
Check if secure config already has a KMSK entry KMSK stands for Key Manifest Secure Key...
int switchtec_active_image_index_set(struct switchtec_dev *dev, struct switchtec_active_index *index)
Set active image index.