Switchtec Userspace PROJECT_NUMBER = 4.0
Loading...
Searching...
No Matches
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_ACTV_IMG_ID_KMAN_GEN5 1
74#define SWITCHTEC_ACTV_IMG_ID_RC_GEN5 2
75#define SWITCHTEC_ACTV_IMG_ID_BL2_GEN5 3
76#define SWITCHTEC_ACTV_IMG_ID_CFG_GEN5 4
77#define SWITCHTEC_ACTV_IMG_ID_FW_GEN5 5
78
79#define SWITCHTEC_MB_MAX_ENTRIES 16
80#define SWITCHTEC_ACTV_IDX_MAX_ENTRIES 32
81#define SWITCHTEC_ACTV_IDX_SET_ENTRIES 5
82
83#define SWITCHTEC_ATTEST_BITSHIFT 4
84#define SWITCHTEC_ATTEST_BITMASK 0x03
85#define SWITCHTEC_CLK_RATE_BITSHIFT 10
86#define SWITCHTEC_CLK_RATE_BITMASK 0x0f
87#define SWITCHTEC_RC_TMO_BITSHIFT 14
88#define SWITCHTEC_RC_TMO_BITMASK 0x0f
89#define SWITCHTEC_I2C_PORT_BITSHIFT 18
90#define SWITCHTEC_I2C_PORT_BITMASK 0x0f
91#define SWITCHTEC_I2C_ADDR_BITSHIFT 22
92#define SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5 23
93#define SWITCHTEC_I2C_ADDR_BITMASK 0x7f
94#define SWITCHTEC_CMD_MAP_BITSHIFT 29
95#define SWITCHTEC_CMD_MAP_BITSHIFT_GEN5 30
96#define SWITCHTEC_CMD_MAP_BITMASK 0xfff
97#define SWITCHTEC_CMD_MAP_BITMASK_GEN5 0x3fff
98#define SWITCHTEC_UDS_SELFGEN_BITSHIFT 44
99#define SWITCHTEC_UDS_SELFGEN_BITMASK 0x01
100
101#define SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK 0x40
102#define SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK 0x80
103#define SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK 0x0100
104#define SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK 0x0200
105
106static int switchtec_mfg_cmd(struct switchtec_dev *dev, uint32_t cmd,
107 const void *payload, size_t payload_len,
108 void *resp, size_t resp_len);
109
110#if (HAVE_LIBCRYPTO && !HAVE_DECL_RSA_GET0_KEY)
115static void RSA_get0_key(const RSA *r, const BIGNUM **n,
116 const BIGNUM **e, const BIGNUM **d)
117{
118 if (n != NULL)
119 *n = r->n;
120 if (e != NULL)
121 *e = r->e;
122 if (d != NULL)
123 *d = r->d;
124}
125#endif
126
127static void get_i2c_operands(enum switchtec_gen gen, uint32_t *addr_shift,
128 uint32_t *map_shift, uint32_t *map_mask)
129{
130 if (gen > SWITCHTEC_GEN4) {
131 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT_GEN5;
132 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT_GEN5;
133 *map_mask = SWITCHTEC_CMD_MAP_BITMASK_GEN5;
134 } else {
135 *addr_shift = SWITCHTEC_I2C_ADDR_BITSHIFT;
136 *map_shift = SWITCHTEC_CMD_MAP_BITSHIFT;
137 *map_mask = SWITCHTEC_CMD_MAP_BITMASK;
138 }
139}
140
141static float spi_clk_rate_float[] = {
142 100, 67, 50, 40, 33.33, 28.57, 25, 22.22, 20, 18.18
143};
144
145static float spi_clk_hi_rate_float[] = {
146 120, 80, 60, 48, 40, 34, 30, 26.67, 24, 21.82
147};
148
149struct get_cfgs_reply {
150 uint32_t valid;
151 uint32_t rsvd1;
152 uint64_t cfg;
153 uint32_t public_key_exponent;
154 uint8_t rsvd2;
155 uint8_t public_key_num;
156 uint8_t public_key_ver;
157 uint8_t spi_core_clk_high;
158 uint8_t public_key[4][SWITCHTEC_KMSK_LEN];
159 uint8_t rsvd4[32];
160};
161
162struct get_cfgs_reply_gen5 {
163 uint32_t valid0;
164 uint32_t valid1;
165 uint64_t cfg;
166 uint32_t public_key_exponent;
167 uint8_t rsvd2;
168 uint8_t public_key_num;
169 uint8_t public_key_ver;
170 uint8_t spi_core_clk_high;
171 uint8_t public_key[10][SWITCHTEC_KMSK_LEN];
172 uint32_t cdi_efuse_inc_mask;
173 uint8_t uds_data[32];
174};
175
176static int get_configs(struct switchtec_dev *dev,
177 struct get_cfgs_reply *cfgs,
178 int *otp_valid)
179{
180 uint8_t subcmd = 0;
181 int ret;
182
183 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET_EXT,
184 &subcmd, sizeof(subcmd),
185 cfgs, sizeof(struct get_cfgs_reply));
186 if (ret && ERRNO_MRPC(errno) != ERR_CMD_INVALID)
187 return ret;
188
189 if (!ret) {
190 *otp_valid = true;
191 return ret;
192 }
193
194 *otp_valid = false;
195 ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET,
196 NULL, 0, cfgs,
197 sizeof(struct get_cfgs_reply));
198
199 return ret;
200}
201
202static int get_configs_gen5(struct switchtec_dev *dev,
203 struct get_cfgs_reply_gen5 *cfgs)
204{
205 uint32_t subcmd = 0;
206
207 return switchtec_mfg_cmd(dev,
208 MRPC_SECURITY_CONFIG_GET_GEN5,
209 &subcmd, sizeof(subcmd),
210 cfgs, sizeof(struct get_cfgs_reply_gen5));
211}
212
213int switchtec_security_spi_avail_rate_get(struct switchtec_dev *dev,
215{
216 int ret;
217 struct get_cfgs_reply reply;
218 int otp_valid;
219
220 ret = get_configs(dev, &reply, &otp_valid);
221 if (ret)
222 return ret;
223
224 rates->num_rates = 10;
225 if (reply.spi_core_clk_high)
226 memcpy(rates->rates, spi_clk_hi_rate_float,
227 sizeof(spi_clk_hi_rate_float));
228 else
229 memcpy(rates->rates, spi_clk_rate_float,
230 sizeof(spi_clk_rate_float));
231
232 return 0;
233}
234
235static void parse_otp_settings(struct switchtec_security_cfg_otp_region *otp,
236 uint32_t flags)
237{
238 otp->basic_valid = !!(flags & BIT(5));
239 otp->basic = !!(flags & BIT(6));
240 otp->mixed_ver_valid = !!(flags & BIT(7));
241 otp->mixed_ver = !!(flags & BIT(8));
242 otp->main_fw_ver_valid = !!(flags & BIT(9));
243 otp->main_fw_ver = !!(flags & BIT(10));
244 otp->sec_unlock_ver_valid = !!(flags & BIT(11));
245 otp->sec_unlock_ver = !!(flags & BIT(12));
246 otp->kmsk_valid[0] = !!(flags & BIT(13));
247 otp->kmsk[0] = !!(flags & BIT(14));
248 otp->kmsk_valid[1] = !!(flags & BIT(15));
249 otp->kmsk[1] = !!(flags & BIT(16));
250 otp->kmsk_valid[2] = !!(flags & BIT(17));
251 otp->kmsk[2] = !!(flags & BIT(18));
252 otp->kmsk_valid[3] = !!(flags & BIT(19));
253 otp->kmsk[3] = !!(flags & BIT(20));
254}
255
256static void parse_otp_settings_gen5(
258 uint32_t flags0, uint32_t flags1)
259{
260 otp->basic_valid = !!(flags0 & BIT(8));
261 otp->basic = !!(flags0 & BIT(9));
262 otp->debug_mode_valid = !!(flags0 & BIT(10));
263 otp->debug_mode = !!(flags0 & BIT(11));
264 otp->key_ver_valid = !!(flags0 & BIT(12));
265 otp->key_ver = !!(flags0 & BIT(13));
266 otp->rc_ver_valid = !!(flags0 & BIT(14));
267 otp->rc_ver = !!(flags0 & BIT(15));
268 otp->bl2_ver_valid = !!(flags0 & BIT(16));
269 otp->bl2_ver = !!(flags0 & BIT(17));
270 otp->main_fw_ver_valid = !!(flags0 & BIT(18));
271 otp->main_fw_ver = !!(flags0 & BIT(19));
272 otp->sec_unlock_ver_valid = !!(flags0 & BIT(20));
273 otp->sec_unlock_ver = !!(flags0 & BIT(21));
274 otp->kmsk_valid[0] = !!(flags0 & BIT(22));
275 otp->kmsk[0] = !!(flags0 & BIT(23));
276 otp->kmsk_valid[1] = !!(flags0 & BIT(24));
277 otp->kmsk[1] = !!(flags0 & BIT(25));
278 otp->kmsk_valid[2] = !!(flags0 & BIT(26));
279 otp->kmsk[2] = !!(flags0 & BIT(27));
280 otp->kmsk_valid[3] = !!(flags0 & BIT(28));
281 otp->kmsk[3] = !!(flags0 & BIT(29));
282 otp->kmsk_valid[4] = !!(flags0 & BIT(30));
283 otp->kmsk[4] = !!(flags0 & BIT(31));
284 otp->kmsk_valid[5] = !!(flags1 & BIT(0));
285 otp->kmsk[5] = !!(flags1 & BIT(1));
286 otp->kmsk_valid[6] = !!(flags1 & BIT(2));
287 otp->kmsk[6] = !!(flags1 & BIT(3));
288 otp->kmsk_valid[7] = !!(flags1 & BIT(4));
289 otp->kmsk[7] = !!(flags1 & BIT(5));
290 otp->kmsk_valid[8] = !!(flags1 & BIT(6));
291 otp->kmsk[8] = !!(flags1 & BIT(7));
292 otp->kmsk_valid[9] = !!(flags1 & BIT(8));
293 otp->kmsk[9] = !!(flags1 & BIT(9));
294 otp->cdi_efuse_inc_mask_valid = !!(flags1 & BIT(10));
295 otp->cdi_efuse_inc_mask = !!(flags1 & BIT(11));
296 otp->uds_valid = !!(flags1 & BIT(12));
297 otp->uds = !!(flags1 & BIT(13));
298 otp->uds_mask_valid = !!(flags1 & BIT(14));
299 otp->uds_mask = !!(flags1 & BIT(15));
300 otp->mchp_uds_valid = !!(flags1 & BIT(16));
301 otp->mchp_uds = !!(flags1 & BIT(17));
302 otp->mchp_uds_mask_valid = !!(flags1 & BIT(18));
303 otp->mchp_uds_mask = !!(flags1 & BIT(19));
304 otp->did_cert0_valid = !!(flags1 & BIT(20));
305 otp->did_cert0 = !!(flags1 & BIT(21));
306 otp->did_cert1_valid = !!(flags1 & BIT(22));
307 otp->did_cert1 = !!(flags1 & BIT(23));
308}
309
310static int security_config_get(struct switchtec_dev *dev,
311 struct switchtec_security_cfg_state *state)
312{
313 int ret;
314 uint32_t addr_shift;
315 uint32_t map_shift;
316 uint32_t map_mask;
317 int spi_clk;
318 struct get_cfgs_reply reply;
319 int otp_valid;
320
321 ret = get_configs(dev, &reply, &otp_valid);
322 if (ret)
323 return ret;
324
325 reply.valid = le32toh(reply.valid);
326 reply.cfg = le64toh(reply.cfg);
327 reply.public_key_exponent = le32toh(reply.public_key_exponent);
328
329 state->basic_setting_valid = !!(reply.valid & 0x01);
330 state->public_key_exp_valid = !!(reply.valid & 0x02);
331 state->public_key_num_valid = !!(reply.valid & 0x04);
332 state->public_key_ver_valid = !!(reply.valid & 0x08);
333 state->public_key_valid = !!(reply.valid & 0x10);
334
335 state->debug_mode_valid = state->basic_setting_valid;
336
337 state->otp_valid = otp_valid;
338 if (otp_valid)
339 parse_otp_settings(&state->otp, reply.valid);
340
341 state->use_otp_ext = false;
342
343 state->debug_mode = reply.cfg & 0x03;
344 state->secure_state = (reply.cfg>>2) & 0x03;
345
346 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
347 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
348 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
349 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
350
351 spi_clk = (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
352 if (spi_clk == 0) {
353 if (switchtec_gen(dev) == SWITCHTEC_GEN5)
354 spi_clk = 9;
355 else
356 spi_clk = 7;
357 }
358
359 if (reply.spi_core_clk_high)
360 state->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
361 else
362 state->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
363
364 state->i2c_recovery_tmo =
365 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
366 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
367
368 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
369 &map_mask);
370 state->i2c_addr =
371 (reply.cfg >> addr_shift) & SWITCHTEC_I2C_ADDR_BITMASK;
372 state->i2c_cmd_map = (reply.cfg >> map_shift) & map_mask;
373
374 state->public_key_exponent = reply.public_key_exponent;
375 state->public_key_num = reply.public_key_num;
376 state->public_key_ver = reply.public_key_ver;
377
378 if (state->public_key_num)
379 memcpy(state->public_key, reply.public_key,
380 state->public_key_num * SWITCHTEC_KMSK_LEN);
381
382 state->attn_state.attestation_mode =
383 SWITCHTEC_ATTESTATION_MODE_NOT_SUPPORTED;
384
385 return 0;
386}
387
388static int security_config_get_gen5(struct switchtec_dev *dev,
389 struct switchtec_security_cfg_state *state)
390{
391 int ret;
392 uint32_t addr_shift;
393 uint32_t map_shift;
394 uint32_t map_mask;
395 int spi_clk;
396 struct get_cfgs_reply_gen5 reply;
397 int attn_mode;
398
399 ret = get_configs_gen5(dev, &reply);
400 if (ret)
401 return ret;
402
403 reply.valid0 = le32toh(reply.valid0);
404 reply.valid1 = le32toh(reply.valid1);
405
406 reply.cfg = le64toh(reply.cfg);
407 reply.public_key_exponent = le32toh(reply.public_key_exponent);
408
409 state->basic_setting_valid = !!(reply.valid0 & 0x01);
410 state->public_key_exp_valid = !!(reply.valid0 & 0x04);
411 state->public_key_num_valid = !!(reply.valid0 & 0x08);
412 state->public_key_ver_valid = !!(reply.valid0 & 0x10);
413 state->public_key_valid = !!(reply.valid0 & 0x20);
414
415 state->debug_mode_valid = !!(reply.valid0 & 0x02);
416 state->attn_state.cdi_efuse_inc_mask_valid = !!(reply.valid0 & 0x40);
417
418 state->otp_valid = true;
419 parse_otp_settings_gen5(&state->otp_ext, reply.valid0,
420 reply.valid1);
421
422 state->use_otp_ext = true;
423
424 state->debug_mode = reply.cfg & 0x03;
425 state->secure_state = (reply.cfg>>2) & 0x03;
426
427 state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
428 state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
429 state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
430 state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
431
432 spi_clk = (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
433 if (spi_clk == 0) {
434 if (switchtec_gen(dev) == SWITCHTEC_GEN5)
435 spi_clk = 9;
436 else
437 spi_clk = 7;
438 }
439
440 if (reply.spi_core_clk_high)
441 state->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
442 else
443 state->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
444
445 state->i2c_recovery_tmo =
446 (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
447 state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
448
449 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
450 &map_mask);
451 state->i2c_addr =
452 (reply.cfg >> addr_shift) & SWITCHTEC_I2C_ADDR_BITMASK;
453 state->i2c_cmd_map = (reply.cfg >> map_shift) & map_mask;
454
455 state->public_key_exponent = reply.public_key_exponent;
456 state->public_key_num = reply.public_key_num;
457 state->public_key_ver = reply.public_key_ver;
458 memcpy(state->public_key, reply.public_key,
459 state->public_key_num * SWITCHTEC_KMSK_LEN);
460
461 attn_mode = (reply.cfg >> SWITCHTEC_ATTEST_BITSHIFT) &
462 SWITCHTEC_ATTEST_BITMASK;
463 if (attn_mode == 1)
464 state->attn_state.attestation_mode =
465 SWITCHTEC_ATTESTATION_MODE_DICE;
466 else
467 state->attn_state.attestation_mode =
468 SWITCHTEC_ATTESTATION_MODE_NONE;
469
470 state->attn_state.uds_selfgen =
471 (reply.cfg >> SWITCHTEC_UDS_SELFGEN_BITSHIFT) &
472 SWITCHTEC_UDS_SELFGEN_BITMASK;
473 state->attn_state.cdi_efuse_inc_mask =
474 le32toh(reply.cdi_efuse_inc_mask);
475
476 if (state->secure_state == SWITCHTEC_UNINITIALIZED_UNSECURED &&
477 state->attn_state.attestation_mode ==
478 SWITCHTEC_ATTESTATION_MODE_DICE &&
479 !state->attn_state.uds_selfgen)
480 state->attn_state.uds_visible = true;
481 else
482 state->attn_state.uds_visible = false;
483
484 if (state->attn_state.uds_visible)
485 memcpy(state->attn_state.uds_data, reply.uds_data, 32);
486
487 return 0;
488}
489
496int switchtec_security_config_get(struct switchtec_dev *dev,
497 struct switchtec_security_cfg_state *state)
498{
499 if (switchtec_is_gen5(dev))
500 return security_config_get_gen5(dev, state);
501 else
502 return security_config_get(dev, state);
503}
504
505static int mailbox_to_file(struct switchtec_dev *dev, int fd)
506{
507 int ret;
508 int num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
509 struct mb_reply {
510 uint8_t num_returned;
511 uint8_t num_remaining;
512 uint8_t rsvd[2];
513 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
514 SWITCHTEC_MB_LOG_LEN];
515 } reply;
516
517 do {
518 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET, &num_to_read,
519 sizeof(int), &reply, sizeof(reply));
520 if (ret)
521 return ret;
522
523 reply.num_remaining = le32toh(reply.num_remaining);
524 reply.num_returned = le32toh(reply.num_returned);
525
526 ret = write(fd, reply.data,
527 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
528 if (ret < 0)
529 return ret;
530 } while (reply.num_remaining > 0);
531
532 return 0;
533}
534
535static int mailbox_to_file_gen5(struct switchtec_dev *dev, int fd)
536{
537 int ret;
538 struct mb_read {
539 uint32_t subcmd;
540 uint32_t num_to_read;
541 } read;
542 struct mb_reply {
543 uint8_t num_returned;
544 uint8_t num_remaining;
545 uint8_t rsvd[2];
546 uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
547 SWITCHTEC_MB_LOG_LEN];
548 } reply;
549
550 read.subcmd = 0;
551 read.num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
552
553 do {
554 ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET_GEN5,
555 &read, sizeof(read),
556 &reply, sizeof(reply));
557 if (ret)
558 return ret;
559
560 reply.num_remaining = le32toh(reply.num_remaining);
561 reply.num_returned = le32toh(reply.num_returned);
562
563 ret = write(fd, reply.data,
564 (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
565 if (ret < 0)
566 return ret;
567 } while (reply.num_remaining > 0);
568
569 return 0;
570}
571
578int switchtec_mailbox_to_file(struct switchtec_dev *dev, int fd)
579{
580 if (switchtec_is_gen5(dev))
581 return mailbox_to_file_gen5(dev, fd);
582 else
583 return mailbox_to_file(dev, fd);
584}
585
586static int convert_spi_clk_rate(float clk_float, int hi_rate)
587{
588 int i;
589 float *p;
590
591 if (hi_rate)
592 p = spi_clk_hi_rate_float;
593 else
594 p = spi_clk_rate_float;
595
596 for (i = 0; i < 10; i++)
597 if ((clk_float < p[i] + 0.1) && (clk_float > p[i] - 0.1))
598 return i + 1;
599
600 return -1;
601}
602
603static int security_config_set_gen4(struct switchtec_dev *dev,
604 struct switchtec_security_cfg_set *setting)
605{
606 int ret;
607 struct setting_data {
608 uint64_t cfg;
609 uint32_t pub_key_exponent;
610 uint8_t rsvd[4];
611 } sd;
612 struct get_cfgs_reply reply;
613 uint64_t ldata = 0;
614 uint32_t addr_shift;
615 uint32_t map_shift;
616 uint32_t map_mask;
617 int spi_clk;
618 int otp_valid;
619
620 /* Gen4 device does not support attestation feature */
621 if (setting->attn_set.attestation_mode !=
622 SWITCHTEC_ATTESTATION_MODE_NOT_SUPPORTED)
623 return -EINVAL;
624
625 ret = get_configs(dev, &reply, &otp_valid);
626 if (ret)
627 return ret;
628
629 memset(&sd, 0, sizeof(sd));
630
631 sd.cfg |= setting->jtag_lock_after_reset?
632 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
633 sd.cfg |= setting->jtag_lock_after_bl1?
634 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
635 sd.cfg |= setting->jtag_bl1_unlock_allowed?
636 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
637 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
638 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
639
640 spi_clk = convert_spi_clk_rate(setting->spi_clk_rate,
641 reply.spi_core_clk_high);
642 if (spi_clk < 0) {
643 errno = EINVAL;
644 return -1;
645 }
646
647 sd.cfg |= (spi_clk & SWITCHTEC_CLK_RATE_BITMASK) <<
648 SWITCHTEC_CLK_RATE_BITSHIFT;
649
650 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
651 SWITCHTEC_RC_TMO_BITSHIFT;
652 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
653 SWITCHTEC_I2C_PORT_BITSHIFT;
654
655 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
656 &map_mask);
657 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
658 addr_shift;
659
660 ldata = setting->i2c_cmd_map & map_mask;
661 ldata <<= map_shift;
662 sd.cfg |= ldata;
663
664 sd.cfg = htole64(sd.cfg);
665
666 sd.pub_key_exponent = htole32(setting->public_key_exponent);
667
668 return switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET,
669 &sd, sizeof(sd), NULL, 0);
670}
671
672static int security_config_set_gen5(struct switchtec_dev *dev,
673 struct switchtec_security_cfg_set *setting)
674{
675 int ret;
676 struct setting_data {
677 uint64_t cfg;
678 uint32_t pub_key_exponent;
679 uint8_t uds_valid;
680 uint8_t rsvd[3];
681 uint32_t cdi_efuse_inc_mask;
682 uint8_t uds[32];
683 } sd;
684 struct get_cfgs_reply_gen5 reply;
685 uint64_t ldata = 0;
686 uint32_t addr_shift;
687 uint32_t map_shift;
688 uint32_t map_mask;
689 int spi_clk;
690 uint8_t cmd_buf[64]={};
691
692 ret = get_configs_gen5(dev, &reply);
693 if (ret)
694 return ret;
695
696 memset(&sd, 0, sizeof(sd));
697
698 sd.cfg = setting->jtag_lock_after_reset?
699 SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
700 sd.cfg |= setting->jtag_lock_after_bl1?
701 SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
702 sd.cfg |= setting->jtag_bl1_unlock_allowed?
703 SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
704 sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
705 SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
706
707 spi_clk = convert_spi_clk_rate(setting->spi_clk_rate,
708 reply.spi_core_clk_high);
709 if (spi_clk < 0) {
710 errno = EINVAL;
711 return -1;
712 }
713
714 sd.cfg |= (spi_clk & SWITCHTEC_CLK_RATE_BITMASK) <<
715 SWITCHTEC_CLK_RATE_BITSHIFT;
716
717 sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
718 SWITCHTEC_RC_TMO_BITSHIFT;
719 sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
720 SWITCHTEC_I2C_PORT_BITSHIFT;
721
722 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
723 &map_mask);
724 sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
725 addr_shift;
726
727 ldata = setting->i2c_cmd_map & map_mask;
728 ldata <<= map_shift;
729 sd.cfg |= ldata;
730
731 sd.cfg = htole64(sd.cfg);
732
733 sd.pub_key_exponent = htole32(setting->public_key_exponent);
734
735 if (setting->attn_set.attestation_mode ==
736 SWITCHTEC_ATTESTATION_MODE_DICE) {
737 sd.cfg |= 0x10;
738 sd.cdi_efuse_inc_mask = setting->attn_set.cdi_efuse_inc_mask;
739
740 ldata = setting->attn_set.uds_selfgen? 1 : 0;
741 ldata <<= 44;
742 sd.cfg |= ldata;
743
744 sd.uds_valid = setting->attn_set.uds_valid;
745 if (sd.uds_valid)
746 memcpy(sd.uds, setting->attn_set.uds_data, 32);
747 }
748
749 memcpy(cmd_buf + 4, &sd, sizeof(sd));
750 return switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET_GEN5,
751 cmd_buf, sizeof(cmd_buf), NULL, 0);
752}
753
760int switchtec_security_config_set(struct switchtec_dev *dev,
761 struct switchtec_security_cfg_set *setting)
762{
763 if (switchtec_is_gen5(dev))
764 return security_config_set_gen5(dev, setting);
765 else
766 return security_config_set_gen4(dev, setting);
767}
768
769static int active_image_index_get(struct switchtec_dev *dev,
770 struct switchtec_active_index *index)
771{
772 int ret;
773 struct active_indices {
774 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
775 } reply;
776
777 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET, NULL,
778 0, &reply, sizeof(reply));
779 if (ret)
780 return ret;
781
782 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN];
783 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2];
784 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG];
785 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW];
786 index->riot = SWITCHTEC_ACTIVE_INDEX_NOT_SET;
787
788 return 0;
789}
790
791static int active_image_index_get_gen5(struct switchtec_dev *dev,
792 struct switchtec_active_index *index)
793{
794 int ret;
795 uint32_t subcmd = 0;
796 struct active_indices {
797 uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
798 } reply;
799
800 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET_GEN5, &subcmd,
801 sizeof(subcmd), &reply, sizeof(reply));
802 if (ret)
803 return ret;
804
805 index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN_GEN5];
806 index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2_GEN5];
807 index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG_GEN5];
808 index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW_GEN5];
809 index->riot = reply.index[SWITCHTEC_ACTV_IMG_ID_RC_GEN5];
810
811 return 0;
812}
813
820int switchtec_active_image_index_get(struct switchtec_dev *dev,
821 struct switchtec_active_index *index)
822{
823 if (switchtec_is_gen5(dev))
824 return active_image_index_get_gen5(dev, index);
825 else
826 return active_image_index_get(dev, index);
827}
828
829static int active_image_index_set(struct switchtec_dev *dev,
830 struct switchtec_active_index *index)
831{
832 int ret;
833 int i = 0;
834 struct active_idx {
835 uint32_t count;
836 struct entry {
837 uint8_t image_id;
838 uint8_t index;
839 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
840 } set;
841
842 /* RIOT image is not available on Gen4 device */
843 if (index->riot != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
844 errno = EINVAL;
845 return -EINVAL;
846 }
847
848 memset(&set, 0, sizeof(set));
849
850 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
851 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN;
852 set.idx[i].index = index->keyman;
853 i++;
854 }
855
856 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
857 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2;
858 set.idx[i].index = index->bl2;
859 i++;
860 }
861
862 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
863 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG;
864 set.idx[i].index = index->config;
865 i++;
866 }
867
868 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
869 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW;
870 set.idx[i].index = index->firmware;
871 i++;
872 }
873
874 if (i == 0)
875 return 0;
876
877 set.count = htole32(i);
878
879 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET, &set,
880 sizeof(set), NULL, 0);
881 return ret;
882}
883
884static int active_image_index_set_gen5(struct switchtec_dev *dev,
885 struct switchtec_active_index *index)
886{
887 int ret;
888 int i = 0;
889 struct active_idx {
890 uint32_t subcmd;
891 uint32_t count;
892 struct entry {
893 uint8_t image_id;
894 uint8_t index;
895 } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
896 } set = {};
897
898 if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
899 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN_GEN5;
900 set.idx[i].index = index->keyman;
901 i++;
902 }
903
904 if (index->riot != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
905 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_RC_GEN5;
906 set.idx[i].index = index->riot;
907 i++;
908 }
909
910 if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
911 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2_GEN5;
912 set.idx[i].index = index->bl2;
913 i++;
914 }
915
916 if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
917 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG_GEN5;
918 set.idx[i].index = index->config;
919 i++;
920 }
921
922 if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
923 set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW_GEN5;
924 set.idx[i].index = index->firmware;
925 i++;
926 }
927
928 if (i == 0)
929 return 0;
930
931 set.count = htole32(i);
932
933 ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET_GEN5, &set,
934 sizeof(set), NULL, 0);
935 return ret;
936}
937
944int switchtec_active_image_index_set(struct switchtec_dev *dev,
945 struct switchtec_active_index *index)
946{
947 if (switchtec_is_gen5(dev))
948 return active_image_index_set_gen5(dev, index);
949 else
950 return active_image_index_set(dev, index);
951}
952
959int switchtec_fw_exec(struct switchtec_dev *dev,
960 enum switchtec_bl2_recovery_mode recovery_mode)
961{
962 uint32_t cmd_id = MRPC_FW_TX;
963 struct fw_exec_struct {
964 uint8_t subcmd;
965 uint8_t recovery_mode;
966 uint8_t rsvd[2];
967 } cmd;
968
969 memset(&cmd, 0, sizeof(cmd));
970 cmd.subcmd = MRPC_FW_TX_EXEC;
971 cmd.recovery_mode = recovery_mode;
972
973 if (switchtec_is_gen5(dev))
974 cmd_id = MRPC_FW_TX_GEN5;
975
976 return switchtec_mfg_cmd(dev, cmd_id, &cmd, sizeof(cmd), NULL, 0);
977}
978
991int switchtec_boot_resume(struct switchtec_dev *dev)
992{
993 uint32_t subcmd = 0;
994
995 if (switchtec_is_gen5(dev))
996 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME_GEN5,
997 &subcmd, sizeof(subcmd),
998 NULL, 0);
999 else
1000 return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME,
1001 NULL, 0, NULL, 0);
1002}
1003
1004static int secure_state_set(struct switchtec_dev *dev,
1005 enum switchtec_secure_state state)
1006{
1007 uint32_t data;
1008
1009 data = htole32(state);
1010
1011 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET,
1012 &data, sizeof(data), NULL, 0);
1013}
1014
1015static int secure_state_set_gen5(struct switchtec_dev *dev,
1016 enum switchtec_secure_state state)
1017{
1018 struct state_set {
1019 uint32_t subcmd;
1020 uint32_t state;
1021 } data;
1022
1023 data.subcmd = 0;
1024 data.state = htole32(state);
1025
1026 return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET_GEN5,
1027 &data, sizeof(data), NULL, 0);
1028}
1029
1036int switchtec_secure_state_set(struct switchtec_dev *dev,
1037 enum switchtec_secure_state state)
1038{
1039 if ((state != SWITCHTEC_INITIALIZED_UNSECURED)
1040 && (state != SWITCHTEC_INITIALIZED_SECURED)) {
1041 return ERR_PARAM_INVALID;
1042 }
1043
1044 if (switchtec_is_gen5(dev))
1045 return secure_state_set_gen5(dev, state);
1046 else
1047 return secure_state_set(dev, state);
1048}
1049
1050static int dbg_unlock_send_pubkey(struct switchtec_dev *dev,
1051 struct switchtec_pubkey *public_key,
1052 uint32_t cmd_id)
1053{
1054 struct public_key_cmd {
1055 uint8_t subcmd;
1056 uint8_t rsvd[3];
1057 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
1058 uint32_t pub_key_exp;
1059 } cmd = {};
1060
1061 cmd.subcmd = MRPC_DBG_UNLOCK_PKEY;
1062 memcpy(cmd.pub_key, public_key->pubkey, SWITCHTEC_PUB_KEY_LEN);
1063 cmd.pub_key_exp = htole32(public_key->pubkey_exp);
1064
1065 return switchtec_mfg_cmd(dev, cmd_id, &cmd, sizeof(cmd), NULL, 0);
1066}
1067
1077int switchtec_dbg_unlock(struct switchtec_dev *dev, uint32_t serial,
1078 uint32_t ver_sec_unlock,
1079 struct switchtec_pubkey *public_key,
1080 struct switchtec_signature *signature)
1081{
1082 int ret;
1083 struct unlock_cmd {
1084 uint8_t subcmd;
1085 uint8_t rsvd[3];
1086 uint32_t serial;
1087 uint32_t unlock_ver;
1088 uint8_t signature[SWITCHTEC_SIG_LEN];
1089 } cmd = {};
1090 uint32_t cmd_id;
1091
1092 if (switchtec_is_gen5(dev))
1093 cmd_id = MRPC_DBG_UNLOCK_GEN5;
1094 else
1095 cmd_id = MRPC_DBG_UNLOCK;
1096
1097 ret = dbg_unlock_send_pubkey(dev, public_key, cmd_id);
1098 if (ret)
1099 return ret;
1100
1101 cmd.subcmd = MRPC_DBG_UNLOCK_DATA;
1102 cmd.serial = htole32(serial);
1103 cmd.unlock_ver = htole32(ver_sec_unlock);
1104 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
1105
1106 return switchtec_mfg_cmd(dev, cmd_id, &cmd, sizeof(cmd), NULL, 0);
1107}
1108
1118int switchtec_dbg_unlock_version_update(struct switchtec_dev *dev,
1119 uint32_t serial,
1120 uint32_t ver_sec_unlock,
1121 struct switchtec_pubkey *public_key,
1122 struct switchtec_signature *signature)
1123{
1124 int ret;
1125 struct update_cmd {
1126 uint8_t subcmd;
1127 uint8_t rsvd[3];
1128 uint32_t serial;
1129 uint32_t unlock_ver;
1130 uint8_t signature[SWITCHTEC_SIG_LEN];
1131 } cmd = {};
1132 uint32_t cmd_id;
1133
1134 if (switchtec_is_gen5(dev))
1135 cmd_id = MRPC_DBG_UNLOCK_GEN5;
1136 else
1137 cmd_id = MRPC_DBG_UNLOCK;
1138
1139 ret = dbg_unlock_send_pubkey(dev, public_key, cmd_id);
1140 if (ret)
1141 return ret;
1142
1143 cmd.subcmd = MRPC_DBG_UNLOCK_UPDATE;
1144 cmd.serial = htole32(serial);
1145 cmd.unlock_ver = htole32(ver_sec_unlock);
1146 memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
1147
1148 return switchtec_mfg_cmd(dev, cmd_id, &cmd, sizeof(cmd), NULL, 0);
1149}
1150
1151static int check_sec_cfg_header(struct switchtec_dev *dev,
1152 FILE *setting_file)
1153{
1154 ssize_t rlen;
1155 enum switchtec_gen gen;
1156 char magic[4] = {'S', 'S', 'F', 'F'};
1157 uint32_t crc;
1158 struct setting_file_header {
1159 uint8_t magic[4];
1160 uint32_t version;
1161 uint8_t hw_gen;
1162 uint8_t rsvd[3];
1163 uint32_t crc;
1164 } hdr;
1165 int data_len;
1166 uint8_t data[64];
1167
1168 rlen = fread(&hdr, sizeof(hdr), 1, setting_file);
1169
1170 if (rlen != 1)
1171 return -EBADF;
1172
1173 if (memcmp(hdr.magic, magic, sizeof(magic)))
1174 return -EBADF;
1175
1176 switch (hdr.hw_gen) {
1177 case 0:
1178 gen = SWITCHTEC_GEN4;
1179 break;
1180 case 1:
1181 gen = SWITCHTEC_GEN5;
1182 break;
1183 default:
1184 return -EBADF;
1185 }
1186
1187 if (gen != switchtec_gen(dev))
1188 return -ENODEV;
1189
1190 fseek(setting_file, 0, SEEK_END);
1191 data_len = ftell(setting_file) - sizeof(hdr);
1192 fseek(setting_file, sizeof(hdr), SEEK_SET);
1193
1194 rlen = fread(data, 1, data_len, setting_file);
1195 if (rlen < data_len)
1196 return -EBADF;
1197
1198 crc = crc32(data, data_len, 0, 1, 1);
1199 if (crc != le32toh(hdr.crc))
1200 return -EBADF;
1201
1202 fseek(setting_file, sizeof(hdr), SEEK_SET);
1203 return 0;
1204}
1205
1206static int read_sec_cfg_file(struct switchtec_dev *dev,
1207 FILE *setting_file,
1208 struct switchtec_security_cfg_set *set)
1209{
1210 struct setting_file_data {
1211 uint64_t cfg;
1212 uint32_t pub_key_exponent;
1213 uint8_t rsvd[36];
1214 } data;
1215 struct get_cfgs_reply reply;
1216 uint32_t addr_shift;
1217 uint32_t map_shift;
1218 uint32_t map_mask;
1219 int spi_clk;
1220 int ret;
1221 int otp_valid;
1222
1223 ret = get_configs(dev, &reply, &otp_valid);
1224 if (ret)
1225 return ret;
1226
1227 memset(set, 0, sizeof(struct switchtec_security_cfg_set));
1228
1229 ret = fread(&data, sizeof(data), 1, setting_file);
1230
1231 if (ret != 1)
1232 return -EBADF;
1233
1234 data.cfg = le64toh(data.cfg);
1235
1236 set->jtag_lock_after_reset =
1237 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
1238 set->jtag_lock_after_bl1 =
1239 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
1240 set->jtag_bl1_unlock_allowed =
1241 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
1242 set->jtag_post_bl1_unlock_allowed =
1243 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
1244
1245 spi_clk = (data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
1246 SWITCHTEC_CLK_RATE_BITMASK;
1247 if (reply.spi_core_clk_high)
1248 set->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
1249 else
1250 set->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
1251
1252 set->i2c_recovery_tmo =
1253 (data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
1254 SWITCHTEC_RC_TMO_BITMASK;
1255 set->i2c_port =
1256 (data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
1257 SWITCHTEC_I2C_PORT_BITMASK;
1258
1259 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
1260 &map_mask);
1261 set->i2c_addr =
1262 (data.cfg >> addr_shift) &
1263 SWITCHTEC_I2C_ADDR_BITMASK;
1264 set->i2c_cmd_map = (data.cfg >> map_shift) & map_mask;
1265
1266 set->public_key_exponent = le32toh(data.pub_key_exponent);
1267
1268 set->attn_set.attestation_mode =
1269 SWITCHTEC_ATTESTATION_MODE_NOT_SUPPORTED;
1270
1271 return 0;
1272}
1273
1274static int read_sec_cfg_file_gen5(struct switchtec_dev *dev,
1275 FILE *setting_file,
1276 struct switchtec_security_cfg_set *set)
1277{
1278 struct setting_data {
1279 uint64_t cfg;
1280 uint32_t pub_key_exponent;
1281 uint8_t rsvd[4];
1282 uint32_t cdi_efuse_inc_mask;
1283 } data;
1284 struct get_cfgs_reply_gen5 reply;
1285 uint32_t addr_shift;
1286 uint32_t map_shift;
1287 uint32_t map_mask;
1288 int spi_clk;
1289 int ret;
1290 int attest_mode;
1291
1292 ret = get_configs_gen5(dev, &reply);
1293 if (ret)
1294 return ret;
1295
1296 memset(set, 0, sizeof(struct switchtec_security_cfg_set));
1297
1298 ret = fread(&data, sizeof(data), 1, setting_file);
1299
1300 if (ret != 1)
1301 return -EBADF;
1302
1303 data.cfg = le64toh(data.cfg);
1304
1305 set->jtag_lock_after_reset =
1306 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
1307 set->jtag_lock_after_bl1 =
1308 !!(data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
1309 set->jtag_bl1_unlock_allowed =
1310 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
1311 set->jtag_post_bl1_unlock_allowed =
1312 !!(data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
1313
1314 spi_clk = (data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
1315 SWITCHTEC_CLK_RATE_BITMASK;
1316 if (reply.spi_core_clk_high)
1317 set->spi_clk_rate = spi_clk_hi_rate_float[spi_clk - 1];
1318 else
1319 set->spi_clk_rate = spi_clk_rate_float[spi_clk - 1];
1320
1321 set->i2c_recovery_tmo =
1322 (data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
1323 SWITCHTEC_RC_TMO_BITMASK;
1324 set->i2c_port =
1325 (data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
1326 SWITCHTEC_I2C_PORT_BITMASK;
1327
1328 get_i2c_operands(switchtec_gen(dev), &addr_shift, &map_shift,
1329 &map_mask);
1330 set->i2c_addr =
1331 (data.cfg >> addr_shift) &
1332 SWITCHTEC_I2C_ADDR_BITMASK;
1333 set->i2c_cmd_map = (data.cfg >> map_shift) & map_mask;
1334
1335 set->public_key_exponent = le32toh(data.pub_key_exponent);
1336
1337 attest_mode = (data.cfg >> SWITCHTEC_ATTEST_BITSHIFT) &
1338 SWITCHTEC_ATTEST_BITMASK;
1339 if (attest_mode == 1) {
1340 set->attn_set.attestation_mode =
1341 SWITCHTEC_ATTESTATION_MODE_DICE;
1342 set->attn_set.cdi_efuse_inc_mask = data.cdi_efuse_inc_mask;
1343 set->attn_set.uds_selfgen = (data.cfg >> 44) & 0x1;
1344 } else {
1345 set->attn_set.attestation_mode =
1346 SWITCHTEC_ATTESTATION_MODE_NONE;
1347 }
1348
1349 return 0;
1350}
1351
1359int switchtec_read_sec_cfg_file(struct switchtec_dev *dev,
1360 FILE *setting_file,
1361 struct switchtec_security_cfg_set *set)
1362{
1363 int ret;
1364
1365 ret = check_sec_cfg_header(dev, setting_file);
1366 if (ret)
1367 return ret;
1368
1369 if (switchtec_is_gen4(dev))
1370 return read_sec_cfg_file(dev, setting_file, set);
1371 else
1372 return read_sec_cfg_file_gen5(dev, setting_file, set);
1373}
1374
1375static int kmsk_set_send_pubkey(struct switchtec_dev *dev,
1376 struct switchtec_pubkey *public_key,
1377 uint32_t cmd_id)
1378{
1379 struct kmsk_pubk_cmd {
1380 uint8_t subcmd;
1381 uint8_t reserved[3];
1382 uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
1383 uint32_t pub_key_exponent;
1384 } cmd = {};
1385
1386 cmd.subcmd = MRPC_KMSK_ENTRY_SET_PKEY;
1387 memcpy(cmd.pub_key, public_key->pubkey,
1388 SWITCHTEC_PUB_KEY_LEN);
1389 cmd.pub_key_exponent = htole32(public_key->pubkey_exp);
1390
1391 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
1392 sizeof(cmd), NULL, 0);
1393}
1394
1395static int kmsk_set_send_signature(struct switchtec_dev *dev,
1396 struct switchtec_signature *signature,
1397 uint32_t cmd_id)
1398{
1399 struct kmsk_signature_cmd {
1400 uint8_t subcmd;
1401 uint8_t reserved[3];
1402 uint8_t signature[SWITCHTEC_SIG_LEN];
1403 } cmd = {};
1404
1405 cmd.subcmd = MRPC_KMSK_ENTRY_SET_SIG;
1406 memcpy(cmd.signature, signature->signature,
1407 SWITCHTEC_SIG_LEN);
1408
1409 return switchtec_mfg_cmd(dev, cmd_id, &cmd,
1410 sizeof(cmd), NULL, 0);
1411}
1412
1413static int kmsk_set_send_kmsk(struct switchtec_dev *dev,
1414 struct switchtec_kmsk *kmsk,
1415 uint32_t cmd_id)
1416{
1417 struct kmsk_kmsk_cmd {
1418 uint8_t subcmd;
1419 uint8_t num_entries;
1420 uint8_t reserved[2];
1421 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
1422 } cmd = {};
1423
1424 cmd.subcmd = MRPC_KMSK_ENTRY_SET_KMSK;
1425 cmd.num_entries = 1;
1426 memcpy(cmd.kmsk, kmsk->kmsk, SWITCHTEC_KMSK_LEN);
1427
1428 return switchtec_mfg_cmd(dev, cmd_id, &cmd, sizeof(cmd),
1429 NULL, 0);
1430}
1431
1444int switchtec_kmsk_set(struct switchtec_dev *dev,
1445 struct switchtec_pubkey *public_key,
1446 struct switchtec_signature *signature,
1447 struct switchtec_kmsk *kmsk)
1448{
1449 int ret;
1450 uint32_t cmd_id;
1451
1452 if (switchtec_is_gen5(dev))
1453 cmd_id = MRPC_KMSK_ENTRY_SET_GEN5;
1454 else
1455 cmd_id = MRPC_KMSK_ENTRY_SET;
1456
1457 if (public_key) {
1458 ret = kmsk_set_send_pubkey(dev, public_key, cmd_id);
1459 if (ret)
1460 return ret;
1461 }
1462
1463 if (signature) {
1464 ret = kmsk_set_send_signature(dev, signature, cmd_id);
1465 if (ret)
1466 return ret;
1467 }
1468
1469 return kmsk_set_send_kmsk(dev, kmsk, cmd_id);
1470}
1471
1472#if HAVE_LIBCRYPTO
1479int switchtec_read_pubk_file(FILE *pubk_file, struct switchtec_pubkey *pubk)
1480{
1481 RSA *RSAKey = NULL;
1482 const BIGNUM *modulus_bn;
1483 const BIGNUM *exponent_bn;
1484 uint32_t exponent_tmp = 0;
1485
1486 RSAKey = PEM_read_RSA_PUBKEY(pubk_file, NULL, NULL, NULL);
1487 if (RSAKey == NULL) {
1488 fseek(pubk_file, 0L, SEEK_SET);
1489 RSAKey = PEM_read_RSAPrivateKey(pubk_file, NULL, NULL, NULL);
1490 if (RSAKey == NULL)
1491 return -1;
1492 }
1493
1494 RSA_get0_key(RSAKey, &modulus_bn, &exponent_bn, NULL);
1495
1496 BN_bn2bin(modulus_bn, pubk->pubkey);
1497 BN_bn2bin(exponent_bn, (uint8_t *)&exponent_tmp);
1498
1499 pubk->pubkey_exp = be32toh(exponent_tmp);
1500 RSA_free(RSAKey);
1501
1502 return 0;
1503}
1504#endif
1505
1512int switchtec_read_kmsk_file(FILE *kmsk_file, struct switchtec_kmsk *kmsk)
1513{
1514 ssize_t rlen;
1515 struct kmsk_struct {
1516 uint8_t magic[4];
1517 uint32_t version;
1518 uint32_t reserved;
1519 uint32_t crc32;
1520 uint8_t kmsk[SWITCHTEC_KMSK_LEN];
1521 } data;
1522
1523 char magic[4] = {'K', 'M', 'S', 'K'};
1524 uint32_t crc;
1525
1526 rlen = fread(&data, 1, sizeof(data), kmsk_file);
1527
1528 if (rlen < sizeof(data))
1529 return -EBADF;
1530
1531 if (memcmp(data.magic, magic, sizeof(magic)))
1532 return -EBADF;
1533
1534 crc = crc32(data.kmsk, SWITCHTEC_KMSK_LEN, 0, 1, 1);
1535 if (crc != le32toh(data.crc32))
1536 return -EBADF;
1537
1538 memcpy(kmsk->kmsk, data.kmsk, SWITCHTEC_KMSK_LEN);
1539
1540 return 0;
1541}
1542
1549int switchtec_read_signature_file(FILE *sig_file,
1550 struct switchtec_signature *signature)
1551{
1552 ssize_t rlen;
1553
1554 rlen = fread(signature->signature, 1, SWITCHTEC_SIG_LEN, sig_file);
1555
1556 if (rlen < SWITCHTEC_SIG_LEN)
1557 return -EBADF;
1558
1559 return 0;
1560}
1561
1568int switchtec_read_uds_file(FILE *uds_file, struct switchtec_uds *uds)
1569{
1570 ssize_t rlen;
1571
1572 rlen = fread(uds->uds, 1, SWITCHTEC_UDS_LEN, uds_file);
1573
1574 if (rlen < SWITCHTEC_UDS_LEN)
1575 return -EBADF;
1576
1577 return 0;
1578}
1579
1590int
1591switchtec_security_state_has_kmsk(struct switchtec_security_cfg_state *state,
1592 struct switchtec_kmsk *kmsk)
1593{
1594 int key_idx;
1595
1596 for(key_idx = 0; key_idx < state->public_key_num; key_idx++) {
1597 if (memcmp(state->public_key[key_idx], kmsk->kmsk,
1598 SWITCHTEC_KMSK_LEN) == 0)
1599 return 1;
1600 }
1601
1602 return 0;
1603}
1604
1605#endif /* __linux__ */
1606
1607static int switchtec_mfg_cmd(struct switchtec_dev *dev, uint32_t cmd,
1608 const void *payload, size_t payload_len,
1609 void *resp, size_t resp_len)
1610{
1611 if (dev->ops->flags & SWITCHTEC_OPS_FLAG_NO_MFG) {
1612 errno = ERR_UART_NOT_SUPPORTED | SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
1613 return -1;
1614 }
1615
1616 return switchtec_cmd(dev, cmd, payload, payload_len,
1617 resp, resp_len);
1618}
1619
1620static int sn_ver_get_gen4(struct switchtec_dev *dev,
1621 struct switchtec_sn_ver_info *info)
1622{
1623 int ret;
1624 struct reply_t {
1625 uint32_t chip_serial;
1626 uint32_t ver_km;
1627 uint32_t ver_bl2;
1628 uint32_t ver_main;
1629 uint32_t ver_sec_unlock;
1630 } reply;
1631
1632 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET, NULL, 0,
1633 &reply, sizeof(reply));
1634 if (ret)
1635 return ret;
1636
1637 info->chip_serial = reply.chip_serial;
1638 info->ver_bl2 = reply.ver_bl2;
1639 info->ver_km = reply.ver_km;
1640 info->riot_ver_valid = false;
1641 info->ver_sec_unlock = reply.ver_sec_unlock;
1642 info->ver_main = reply.ver_main;
1643
1644 return 0;
1645}
1646
1647static int sn_ver_get_gen5(struct switchtec_dev *dev,
1648 struct switchtec_sn_ver_info *info)
1649{
1650 int ret;
1651 uint32_t subcmd = 0;
1652 struct reply_t {
1653 uint32_t chip_serial;
1654 uint32_t ver_km;
1655 uint16_t ver_riot;
1656 uint16_t ver_bl2;
1657 uint32_t ver_main;
1658 uint32_t ver_sec_unlock;
1659 } reply;
1660
1661 ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET_GEN5, &subcmd, 4,
1662 &reply, sizeof(reply));
1663 if (ret)
1664 return ret;
1665
1666 info->chip_serial = reply.chip_serial;
1667 info->ver_bl2 = reply.ver_bl2;
1668 info->ver_km = reply.ver_km;
1669 info->riot_ver_valid = true;
1670 info->ver_riot = reply.ver_riot;
1671 info->ver_sec_unlock = reply.ver_sec_unlock;
1672 info->ver_main = reply.ver_main;
1673
1674 return 0;
1675}
1676
1683int switchtec_sn_ver_get(struct switchtec_dev *dev,
1684 struct switchtec_sn_ver_info *info)
1685{
1686 if (switchtec_is_gen5(dev))
1687 return sn_ver_get_gen5(dev, info);
1688 else
1689 return sn_ver_get_gen4(dev, info);
1690}
1691
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:1683
Main Switchtec header.
switchtec_gen
The PCIe generations.
Definition: switchtec.h:86
static int switchtec_is_gen4(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 4 device.
Definition: switchtec.h:431
static int switchtec_is_gen5(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 5 device.
Definition: switchtec.h:439