Switchtec Userspace PROJECT_NUMBER = 3.1
mfg.c
Go to the documentation of this file.
1/*
2 * Microsemi Switchtec(tm) PCIe Management Library
3 * Copyright (c) 2019, Microsemi Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
46#include "switchtec_priv.h"
47#include "switchtec/switchtec.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"
53#include <unistd.h>
54
55#include <errno.h>
56#include <stdio.h>
57#include <string.h>
58
59#include "lib/crc.h"
60#include "config.h"
61
62#ifdef __linux__
63
64#if HAVE_LIBCRYPTO
65#include <openssl/pem.h>
66#endif
67
68#define SWITCHTEC_ACTV_IMG_ID_KMAN 1
69#define SWITCHTEC_ACTV_IMG_ID_BL2 2
70#define SWITCHTEC_ACTV_IMG_ID_CFG 3
71#define SWITCHTEC_ACTV_IMG_ID_FW 4
72
73#define SWITCHTEC_MB_MAX_ENTRIES 16
74#define SWITCHTEC_ACTV_IDX_MAX_ENTRIES 32
75#define SWITCHTEC_ACTV_IDX_SET_ENTRIES 4
76
77#define SWITCHTEC_CLK_RATE_BITSHIFT 10
78#define SWITCHTEC_CLK_RATE_BITMASK 0x0f
79#define SWITCHTEC_RC_TMO_BITSHIFT 14
80#define SWITCHTEC_RC_TMO_BITMASK 0x0f
81#define SWITCHTEC_I2C_PORT_BITSHIFT 18
82#define SWITCHTEC_I2C_PORT_BITMASK 0x0f
83#define SWITCHTEC_I2C_ADDR_BITSHIFT 22
84#define SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5 23
85#define SWITCHTEC_I2C_ADDR_BITMASK 0x7f
86#define SWITCHTEC_CMD_MAP_BITSHIFT 29
87#define SWITCHTEC_CMD_MAP_BITSHIFT_GEN5 30
88#define SWITCHTEC_CMD_MAP_BITMASK 0xfff
89#define SWITCHTEC_CMD_MAP_BITMASK_GEN5 0x3fff
90
91#define SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK 0x40
92#define SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK 0x80
93#define SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK 0x0100
94#define SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK 0x0200
95
96static int switchtec_mfg_cmd(struct switchtec_dev *dev, uint32_t cmd,
97 const void *payload, size_t payload_len,
98 void *resp, size_t resp_len);
99
100#if (HAVE_LIBCRYPTO && !HAVE_DECL_RSA_GET0_KEY)
105static void RSA_get0_key(const RSA *r, const BIGNUM **n,
106 const BIGNUM **e, const BIGNUM **d)
107{
108 if (n != NULL)
109 *n = r->n;
110 if (e != NULL)
111 *e = r->e;
112 if (d != NULL)
113 *d = r->d;
114}
115#endif
116
117static void get_i2c_operands(enum switchtec_gen gen, uint32_t *addr_shift,
118 uint32_t *map_shift, uint32_t *map_mask)
119{
120 if (gen > SWITCHTEC_GEN4) {
121 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5;
122 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT_GEN5;
123 *map_mask = SWITCHTEC_CMD_MAP_BITMASK_GEN5;
124 } else {
125 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT;
126 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT;
127 *map_mask = SWITCHTEC_CMD_MAP_BITMASK;
128 }
129}
130
131static float spi_clk_rate_float[] = {
132 100, 67, 50, 40, 33.33, 28.57, 25, 22.22, 20, 18.18
133};
134
135static float spi_clk_hi_rate_float[] = {
136 120, 80, 60, 48, 40, 34, 30, 26.67, 24, 21.82
137};
138
139struct get_cfgs_reply {
140 uint32_t valid;
141 uint32_t rsvd1;
142 uint64_t cfg;
143 uint32_t public_key_exponent;
144 uint8_t rsvd2;
145 uint8_t public_key_num;
146 uint8_t public_key_ver;
147 uint8_t spi_core_clk_high;
148 uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
149 uint8_t rsvd4[32];
150};
151
152static int get_configs(struct switchtec_dev *dev,
153 struct get_cfgs_reply *cfgs,
154 int *otp_valid)
155{
156 uint8_t subcmd = 0;
157 int ret;
158
159 if (switchtec_gen(dev) == SWITCHTEC_GEN5) {
160 subcmd = 1;
161 ret = switchtec_mfg_cmd(dev,
162 MRPC_SECURITY_CONFIG_GET_GEN5,
163 &subcmd, sizeof(subcmd),
164 cfgs, sizeof(struct get_cfgs_reply));
165 if (!ret)
166 *otp_valid = true;
167 } else {
168 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET_EXT,
169 &subcmd, sizeof(subcmd),
170 cfgs, sizeof(struct get_cfgs_reply));
171 if (ret && ERRNO_MRPC(errno) != ERR_CMD_INVALID)
172 return ret;
173
174 if (!ret) {
175 *otp_valid = true;
176 return ret;
177 }
178
179 *otp_valid = false;
180 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET,
181 NULL, 0, cfgs,
182 sizeof(struct get_cfgs_reply));
183 }
184
185 return ret;
186}
187
188int switchtec_security_spi_avail_rate_get(struct switchtec_dev *dev,
190{
191 int ret;
192 struct get_cfgs_reply reply;
193 int otp_valid;
194
195 ret = get_configs(dev, &reply, &otp_valid);
196 if (ret)
197 return ret;
198
199 rates->num_rates = 10;
200 if (reply.spi_core_clk_high)
201 memcpy(rates->rates, spi_clk_hi_rate_float,
202 sizeof(spi_clk_hi_rate_float));
203 else
204 memcpy(rates->rates, spi_clk_rate_float,
205 sizeof(spi_clk_rate_float));
206
207 return 0;
208}
209
210static void parse_otp_settings(struct switchtec_security_cfg_otp_region *otp,
211 uint32_t flags)
212{
213 otp->basic_valid = !!(flags & BIT(5));
214 otp->basic = !!(flags & BIT(6));
215 otp->mixed_ver_valid = !!(flags & BIT(7));
216 otp->mixed_ver = !!(flags & BIT(8));
217 otp->main_fw_ver_valid = !!(flags & BIT(9));
218 otp->main_fw_ver = !!(flags & BIT(10));
219 otp->sec_unlock_ver_valid = !!(flags & BIT(11));
220 otp->sec_unlock_ver = !!(flags & BIT(12));
221 otp->kmsk_valid[0] = !!(flags & BIT(13));
222 otp->kmsk[0] = !!(flags & BIT(14));
223 otp->kmsk_valid[1] = !!(flags & BIT(15));
224 otp->kmsk[1] = !!(flags & BIT(16));
225 otp->kmsk_valid[2] = !!(flags & BIT(17));
226 otp->kmsk[2] = !!(flags & BIT(18));
227 otp->kmsk_valid[3] = !!(flags & BIT(19));
228 otp->kmsk[3] = !!(flags & BIT(20));
229}
230
237int switchtec_security_config_get(struct switchtec_dev *dev,
238 struct switchtec_security_cfg_state *state)
239{
240 int ret;
241 uint32_t addr_shift;
242 uint32_t map_shift;
243 uint32_t map_mask;
244 int spi_clk;
245 struct get_cfgs_reply reply;
246 int otp_valid;
247
248 ret = get_configs(dev, &reply, &otp_valid);
249 if (ret)
250 return ret;
251
252 reply.valid = le32toh(reply.valid);
253 reply.cfg = le64toh(reply.cfg);
254 reply.public_key_exponent = le32toh(reply.public_key_exponent);
255
256 state->basic_setting_valid = !!(reply.valid & 0x01);
257 state->public_key_exp_valid = !!(reply.valid & 0x02);
258 state->public_key_num_valid = !!(reply.valid & 0x04);
259 state->public_key_ver_valid = !!(reply.valid & 0x08);
260 state->public_key_valid = !!(reply.valid & 0x10);
261
262 state->otp_valid = otp_valid;
263 if (otp_valid)
264 parse_otp_settings(&state->otp, reply.valid);
265
266 state->debug_mode = reply.cfg & 0x03;
267 state->secure_state = (reply.cfg>>2) & 0x03;
268
269 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
270 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
271 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
272 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
273
274 spi_clk = (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
275 if (spi_clk == 0) {
276 if (switchtec_gen(dev) == SWITCHTEC_GEN5)
277 spi_clk = 9;
278 else
279 spi_clk = 7;
280 }
281
282 if (reply.spi_core_clk_high)
283 state->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
284 else
285 state->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
286
287 state->i2c_recovery_tmo =
288 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
289 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
290
291 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
292 &map_mask);
293 state->i2c_addr =
294 (reply.cfg >> addr_shift) & SWITCHTEC_I2C_ADDR_BITMASK;
295 state->i2c_cmd_map = (reply.cfg >> map_shift) & map_mask;
296
297 state->public_key_exponent = reply.public_key_exponent;
298 state->public_key_num = reply.public_key_num;
299 state->public_key_ver = reply.public_key_ver;
300 memcpy(state->public_key, reply.public_key,
301 SWITCHTEC_KMSK_NUM * SWITCHTEC_KMSK_LEN);
302
303 return 0;
304}
305
312int switchtec_mailbox_to_file(struct switchtec_dev *dev, int fd)
313{
314 int ret;
315 int num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
316 struct mb_reply {
317 uint8_t num_returned;
318 uint8_t num_remaining;
319 uint8_t rsvd[2];
320 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
321 SWITCHTEC_MB_LOG_LEN];
322 } reply;
323
324 do {
325 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET, &num_to_read,
326 sizeof(int), &reply, sizeof(reply));
327 if (ret)
328 return ret;
329
330 reply.num_remaining = le32toh(reply.num_remaining);
331 reply.num_returned = le32toh(reply.num_returned);
332
333 ret = write(fd, reply.data,
334 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
335 if (ret < 0)
336 return ret;
337 } while (reply.num_remaining > 0);
338
339 return 0;
340}
341
342static int convert_spi_clk_rate(float clk_float, int hi_rate)
343{
344 int i;
345 float *p;
346
347 if (hi_rate)
348 p = spi_clk_hi_rate_float;
349 else
350 p = spi_clk_rate_float;
351
352 for (i = 0; i < 10; i++)
353 if ((clk_float < p[i] + 0.1) && (clk_float > p[i] - 0.1))
354 return i + 1;
355
356 return -1;
357}
358
365int switchtec_security_config_set(struct switchtec_dev *dev,
366 struct switchtec_security_cfg_set *setting)
367{
368 int ret;
369 struct setting_data {
370 uint64_t cfg;
371 uint32_t pub_key_exponent;
372 uint8_t rsvd[4];
373 } sd;
374 struct get_cfgs_reply reply;
375 uint64_t ldata = 0;
376 uint32_t addr_shift;
377 uint32_t map_shift;
378 uint32_t map_mask;
379 int spi_clk;
380 uint8_t cmd_buf[20] = {};
381 int otp_valid;
382
383 ret = get_configs(dev, &reply, &otp_valid);
384 if (ret)
385 return ret;
386
387 memset(&sd, 0, sizeof(sd));
388
389 sd.cfg |= setting->jtag_lock_after_reset?
390 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
391 sd.cfg |= setting->jtag_lock_after_bl1?
392 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
393 sd.cfg |= setting->jtag_bl1_unlock_allowed?
394 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
395 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
396 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
397
398 spi_clk = convert_spi_clk_rate(setting->spi_clk_rate,
399 reply.spi_core_clk_high);
400 if (spi_clk < 0) {
401 errno = EINVAL;
402 return -1;
403 }
404
405 sd.cfg |= (spi_clk & SWITCHTEC_CLK_RATE_BITMASK) <<
406 SWITCHTEC_CLK_RATE_BITSHIFT;
407
408 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
409 SWITCHTEC_RC_TMO_BITSHIFT;
410 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
411 SWITCHTEC_I2C_PORT_BITSHIFT;
412
413 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
414 &map_mask);
415 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
416 addr_shift;
417
418 ldata = setting->i2c_cmd_map & map_mask;
419 ldata <<= map_shift;
420 sd.cfg |= ldata;
421
422 sd.cfg = htole64(sd.cfg);
423
424 sd.pub_key_exponent = htole32(setting->public_key_exponent);
425
426 if (switchtec_gen(dev) == SWITCHTEC_GEN4) {
427 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET,
428 &sd, sizeof(sd), NULL, 0);
429 } else {
430 cmd_buf[0] = 1;
431 memcpy(cmd_buf + 4, &sd, sizeof(sd));
432 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET_GEN5,
433 cmd_buf, sizeof(cmd_buf), NULL, 0);
434 }
435 return ret;
436}
437
444int switchtec_active_image_index_get(struct switchtec_dev *dev,
445 struct switchtec_active_index *index)
446{
447 int ret;
448 struct active_indices {
449 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
450 } reply;
451
452 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET, NULL,
453 0, &reply, sizeof(reply));
454 if (ret)
455 return ret;
456
457 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN];
458 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2];
459 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG];
460 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW];
461
462 return 0;
463}
464
471int switchtec_active_image_index_set(struct switchtec_dev *dev,
472 struct switchtec_active_index *index)
473{
474 int ret;
475 int i = 0;
476 struct active_idx {
477 uint32_t count;
478 struct entry {
479 uint8_t image_id;
480 uint8_t index;
481 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
482 } set;
483
484 memset(&set, 0, sizeof(set));
485
486 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
487 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN;
488 set.idx[i].index = index->keyman;
489 i++;
490 }
491
492 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
493 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2;
494 set.idx[i].index = index->bl2;
495 i++;
496 }
497
498 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
499 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG;
500 set.idx[i].index = index->config;
501 i++;
502 }
503
504 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
505 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW;
506 set.idx[i].index = index->firmware;
507 i++;
508 }
509
510 if (i == 0)
511 return 0;
512
513 set.count = htole32(i);
514
515 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET, &set,
516 sizeof(set), NULL, 0);
517 return ret;
518}
519
526int switchtec_fw_exec(struct switchtec_dev *dev,
527 enum switchtec_bl2_recovery_mode recovery_mode)
528{
529 struct fw_exec_struct {
530 uint8_t subcmd;
531 uint8_t recovery_mode;
532 uint8_t rsvd[2];
533 } cmd;
534
535 memset(&cmd, 0, sizeof(cmd));
536 cmd.subcmd = MRPC_FW_TX_EXEC;
537 cmd.recovery_mode = recovery_mode;
538
539 return switchtec_mfg_cmd(dev, MRPC_FW_TX, &cmd, sizeof(cmd), NULL, 0);
540}
541
554int switchtec_boot_resume(struct switchtec_dev *dev)
555{
556 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME, NULL, 0,
557 NULL, 0);
558}
559
566int switchtec_secure_state_set(struct switchtec_dev *dev,
567 enum switchtec_secure_state state)
568{
569 uint32_t data;
570
571 if ((state != SWITCHTEC_INITIALIZED_UNSECURED)
572 && (state != SWITCHTEC_INITIALIZED_SECURED)) {
573 return ERR_PARAM_INVALID;
574 }
575 data = htole32(state);
576
577 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET, &data,
578 sizeof(data), NULL, 0);
579}
580
581static int dbg_unlock_send_pubkey(struct switchtec_dev *dev,
582 struct switchtec_pubkey *public_key)
583{
584 struct public_key_cmd {
585 uint8_t subcmd;
586 uint8_t rsvd[3];
587 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
588 uint32_t pub_key_exp;
589 } cmd = {};
590
591 cmd.subcmd = MRPC_DBG_UNLOCK_PKEY;
592 memcpy(cmd.pub_key, public_key->pubkey, SWITCHTEC_PUB_KEY_LEN);
593 cmd.pub_key_exp = htole32(public_key->pubkey_exp);
594
595 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
596 sizeof(cmd), NULL, 0);
597}
598
608int switchtec_dbg_unlock(struct switchtec_dev *dev, uint32_t serial,
609 uint32_t ver_sec_unlock,
610 struct switchtec_pubkey *public_key,
611 struct switchtec_signature *signature)
612{
613 int ret;
614 struct unlock_cmd {
615 uint8_t subcmd;
616 uint8_t rsvd[3];
617 uint32_t serial;
618 uint32_t unlock_ver;
619 uint8_t signature[SWITCHTEC_SIG_LEN];
620 } cmd = {};
621
622 ret = dbg_unlock_send_pubkey(dev, public_key);
623 if (ret)
624 return ret;
625
626 cmd.subcmd = MRPC_DBG_UNLOCK_DATA;
627 cmd.serial = htole32(serial);
628 cmd.unlock_ver = htole32(ver_sec_unlock);
629 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
630
631 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
632 sizeof(cmd), NULL, 0);
633}
634
644int switchtec_dbg_unlock_version_update(struct switchtec_dev *dev,
645 uint32_t serial,
646 uint32_t ver_sec_unlock,
647 struct switchtec_pubkey *public_key,
648 struct switchtec_signature *signature)
649{
650 int ret;
651 struct update_cmd {
652 uint8_t subcmd;
653 uint8_t rsvd[3];
654 uint32_t serial;
655 uint32_t unlock_ver;
656 uint8_t signature[SWITCHTEC_SIG_LEN];
657 } cmd = {};
658
659 ret = dbg_unlock_send_pubkey(dev, public_key);
660 if (ret)
661 return ret;
662
663 cmd.subcmd = MRPC_DBG_UNLOCK_UPDATE;
664 cmd.serial = htole32(serial);
665 cmd.unlock_ver = htole32(ver_sec_unlock);
666 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
667
668 return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd, sizeof(cmd),
669 NULL, 0);
670}
671
679int switchtec_read_sec_cfg_file(struct switchtec_dev *dev,
680 FILE *setting_file,
681 struct switchtec_security_cfg_set *set)
682{
683 ssize_t rlen;
684 char magic[4] = {'S', 'S', 'F', 'F'};
685 uint32_t crc;
686 struct setting_file_header {
687 uint8_t magic[4];
688 uint32_t version;
689 uint8_t hw_gen;
690 uint8_t rsvd[3];
691 uint32_t crc;
692 };
693 struct setting_file_data {
694 uint64_t cfg;
695 uint32_t pub_key_exponent;
696 uint8_t rsvd[36];
697 };
698 struct setting_file {
699 struct setting_file_header header;
700 struct setting_file_data data;
701 } file_data;
702 struct get_cfgs_reply reply;
703 uint32_t addr_shift;
704 uint32_t map_shift;
705 uint32_t map_mask;
706 enum switchtec_gen gen;
707 int spi_clk;
708 int ret;
709 int otp_valid;
710
711 ret = get_configs(dev, &reply, &otp_valid);
712 if (ret)
713 return ret;
714
715 rlen = fread(&file_data, 1, sizeof(file_data), setting_file);
716
717 if (rlen < sizeof(file_data))
718 return -EBADF;
719
720 if (memcmp(file_data.header.magic, magic, sizeof(magic)))
721 return -EBADF;
722
723 crc = crc32((uint8_t*)&file_data.data,
724 sizeof(file_data.data), 0, 1, 1);
725 if (crc != le32toh(file_data.header.crc))
726 return -EBADF;
727 switch (file_data.header.hw_gen) {
728 case 0:
729 gen = SWITCHTEC_GEN4;
730 break;
731 case 1:
732 gen = SWITCHTEC_GEN5;
733 break;
734 default:
735 return -EBADF;
736 }
737
738 if (gen != switchtec_gen(dev))
739 return -ENODEV;
740
741 memset(set, 0, sizeof(struct switchtec_security_cfg_set));
742
743 file_data.data.cfg = le64toh(file_data.data.cfg);
744
745 set->jtag_lock_after_reset =
746 !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
747 set->jtag_lock_after_bl1 =
748 !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
749 set->jtag_bl1_unlock_allowed =
750 !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
751 set->jtag_post_bl1_unlock_allowed =
752 !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
753
754 spi_clk = (file_data.data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
755 SWITCHTEC_CLK_RATE_BITMASK;
756 if (reply.spi_core_clk_high)
757 set->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
758 else
759 set->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
760
761 set->i2c_recovery_tmo =
762 (file_data.data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
763 SWITCHTEC_RC_TMO_BITMASK;
764 set->i2c_port =
765 (file_data.data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
766 SWITCHTEC_I2C_PORT_BITMASK;
767
768 get_i2c_operands(gen, &addr_shift, &map_shift, &map_mask);
769 set->i2c_addr =
770 (file_data.data.cfg >> addr_shift) &
771 SWITCHTEC_I2C_ADDR_BITMASK;
772 set->i2c_cmd_map = (file_data.data.cfg >> map_shift) & map_mask;
773
774 set->public_key_exponent = le32toh(file_data.data.pub_key_exponent);
775
776 return 0;
777}
778
779static int kmsk_set_send_pubkey(struct switchtec_dev *dev,
780 struct switchtec_pubkey *public_key)
781{
782 struct kmsk_pubk_cmd {
783 uint8_t subcmd;
784 uint8_t reserved[3];
785 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
786 uint32_t pub_key_exponent;
787 } cmd = {};
788
789 cmd.subcmd = MRPC_KMSK_ENTRY_SET_PKEY;
790 memcpy(cmd.pub_key, public_key->pubkey,
791 SWITCHTEC_PUB_KEY_LEN);
792 cmd.pub_key_exponent = htole32(public_key->pubkey_exp);
793
794 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
795 sizeof(cmd), NULL, 0);
796}
797
798static int kmsk_set_send_signature(struct switchtec_dev *dev,
799 struct switchtec_signature *signature)
800{
801 struct kmsk_signature_cmd {
802 uint8_t subcmd;
803 uint8_t reserved[3];
804 uint8_t signature[SWITCHTEC_SIG_LEN];
805 } cmd = {};
806
807 cmd.subcmd = MRPC_KMSK_ENTRY_SET_SIG;
808 memcpy(cmd.signature, signature->signature,
809 SWITCHTEC_SIG_LEN);
810
811 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
812 sizeof(cmd), NULL, 0);
813}
814
815static int kmsk_set_send_kmsk(struct switchtec_dev *dev,
816 struct switchtec_kmsk *kmsk)
817{
818 struct kmsk_kmsk_cmd {
819 uint8_t subcmd;
820 uint8_t num_entries;
821 uint8_t reserved[2];
822 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
823 } cmd = {};
824
825 cmd.subcmd = MRPC_KMSK_ENTRY_SET_KMSK;
826 cmd.num_entries = 1;
827 memcpy(cmd.kmsk, kmsk->kmsk, SWITCHTEC_KMSK_LEN);
828
829 return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd, sizeof(cmd),
830 NULL, 0);
831}
832
845int switchtec_kmsk_set(struct switchtec_dev *dev,
846 struct switchtec_pubkey *public_key,
847 struct switchtec_signature *signature,
848 struct switchtec_kmsk *kmsk)
849{
850 int ret;
851
852 if (public_key) {
853 ret = kmsk_set_send_pubkey(dev, public_key);
854 if (ret)
855 return ret;
856 }
857
858 if (signature) {
859 ret = kmsk_set_send_signature(dev, signature);
860 if (ret)
861 return ret;
862 }
863
864 return kmsk_set_send_kmsk(dev, kmsk);
865}
866
867#if HAVE_LIBCRYPTO
874int switchtec_read_pubk_file(FILE *pubk_file, struct switchtec_pubkey *pubk)
875{
876 RSA *RSAKey = NULL;
877 const BIGNUM *modulus_bn;
878 const BIGNUM *exponent_bn;
879 uint32_t exponent_tmp = 0;
880
881 RSAKey = PEM_read_RSA_PUBKEY(pubk_file, NULL, NULL, NULL);
882 if (RSAKey == NULL) {
883 fseek(pubk_file, 0L, SEEK_SET);
884 RSAKey = PEM_read_RSAPrivateKey(pubk_file, NULL, NULL, NULL);
885 if (RSAKey == NULL)
886 return -1;
887 }
888
889 RSA_get0_key(RSAKey, &modulus_bn, &exponent_bn, NULL);
890
891 BN_bn2bin(modulus_bn, pubk->pubkey);
892 BN_bn2bin(exponent_bn, (uint8_t *)&exponent_tmp);
893
894 pubk->pubkey_exp = be32toh(exponent_tmp);
895 RSA_free(RSAKey);
896
897 return 0;
898}
899#endif
900
907int switchtec_read_kmsk_file(FILE *kmsk_file, struct switchtec_kmsk *kmsk)
908{
909 ssize_t rlen;
910 struct kmsk_struct {
911 uint8_t magic[4];
912 uint32_t version;
913 uint32_t reserved;
914 uint32_t crc32;
915 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
916 } data;
917
918 char magic[4] = {'K', 'M', 'S', 'K'};
919 uint32_t crc;
920
921 rlen = fread(&data, 1, sizeof(data), kmsk_file);
922
923 if (rlen < sizeof(data))
924 return -EBADF;
925
926 if (memcmp(data.magic, magic, sizeof(magic)))
927 return -EBADF;
928
929 crc = crc32(data.kmsk, SWITCHTEC_KMSK_LEN, 0, 1, 1);
930 if (crc != le32toh(data.crc32))
931 return -EBADF;
932
933 memcpy(kmsk->kmsk, data.kmsk, SWITCHTEC_KMSK_LEN);
934
935 return 0;
936}
937
944int switchtec_read_signature_file(FILE *sig_file,
945 struct switchtec_signature *signature)
946{
947 ssize_t rlen;
948
949 rlen = fread(signature->signature, 1, SWITCHTEC_SIG_LEN, sig_file);
950
951 if (rlen < SWITCHTEC_SIG_LEN)
952 return -EBADF;
953
954 return 0;
955}
956
967int
968switchtec_security_state_has_kmsk(struct switchtec_security_cfg_state *state,
969 struct switchtec_kmsk *kmsk)
970{
971 int key_idx;
972
973 for(key_idx = 0; key_idx < state->public_key_num; key_idx++) {
974 if (memcmp(state->public_key[key_idx], kmsk->kmsk,
975 SWITCHTEC_KMSK_LEN) == 0)
976 return 1;
977 }
978
979 return 0;
980}
981
982#endif /* __linux__ */
983
984static int switchtec_mfg_cmd(struct switchtec_dev *dev, uint32_t cmd,
985 const void *payload, size_t payload_len,
986 void *resp, size_t resp_len)
987{
988 if (dev->ops->flags & SWITCHTEC_OPS_FLAG_NO_MFG) {
989 errno = ERR_UART_NOT_SUPPORTED | SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
990 return -1;
991 }
992
993 return switchtec_cmd(dev, cmd, payload, payload_len,
994 resp, resp_len);
995}
996
1003int switchtec_sn_ver_get(struct switchtec_dev *dev,
1004 struct switchtec_sn_ver_info *info)
1005{
1006 int ret;
1007
1008 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET, NULL, 0, info,
1009 sizeof(struct switchtec_sn_ver_info));
1010 if (ret)
1011 return ret;
1012
1013 info->chip_serial = le32toh(info->chip_serial);
1014 info->ver_bl2 = le32toh(info->ver_bl2);
1015 info->ver_km = le32toh(info->ver_km);
1016 info->ver_main = le32toh(info->ver_main);
1017 info->ver_sec_unlock = le32toh(info->ver_sec_unlock);
1018
1019 return 0;
1020}
1021
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.
Definition: platform.c:164
int switchtec_sn_ver_get(struct switchtec_dev *dev, struct switchtec_sn_ver_info *info)
Get serial number and security version.
Definition: mfg.c:1003
Main Switchtec header.
switchtec_gen
The PCIe generations.
Definition: switchtec.h:86