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 
96 static 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)
105 static 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 
117 static 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 
131 static float spi_clk_rate_float[] = {
132  100, 67, 50, 40, 33.33, 28.57, 25, 22.22, 20, 18.18
133 };
134 
135 static float spi_clk_hi_rate_float[] = {
136  120, 80, 60, 48, 40, 34, 30, 26.67, 24, 21.82
137 };
138 
139 struct 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 
152 static 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 
188 int switchtec_security_spi_avail_rate_get(struct switchtec_dev *dev,
189  struct switchtec_security_spi_avail_rate *rates)
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 
210 static 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 
237 int 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 
312 int 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 
342 static 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 
365 int 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 
444 int 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 
471 int 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 
526 int 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 
554 int switchtec_boot_resume(struct switchtec_dev *dev)
555 {
556  return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME, NULL, 0,
557  NULL, 0);
558 }
559 
566 int 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 
581 static 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 
608 int 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 
644 int 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 
679 int 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 
779 static 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 
798 static 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 
815 static 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 
845 int 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
874 int 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 
907 int 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 
944 int 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 
967 int
968 switchtec_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 
984 static 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 
1003 int 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