Switchtec Userspace  PROJECT_NUMBER = PROJECT_NUMBER=PROJECT_NUMBER = 2.2
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 #if HAVE_LIBCRYPTO
63 #include <openssl/pem.h>
64 #endif
65 
66 #define SWITCHTEC_ACTV_IMG_ID_KMAN 1
67 #define SWITCHTEC_ACTV_IMG_ID_BL2 2
68 #define SWITCHTEC_ACTV_IMG_ID_CFG 3
69 #define SWITCHTEC_ACTV_IMG_ID_FW 4
70 
71 #define SWITCHTEC_MB_MAX_ENTRIES 8
72 #define SWITCHTEC_ACTV_IDX_MAX_ENTRIES 32
73 #define SWITCHTEC_ACTV_IDX_SET_ENTRIES 4
74 
75 #define SWITCHTEC_CLK_RATE_BITSHIFT 10
76 #define SWITCHTEC_CLK_RATE_BITMASK 0x0f
77 #define SWITCHTEC_RC_TMO_BITSHIFT 14
78 #define SWITCHTEC_RC_TMO_BITMASK 0x0f
79 #define SWITCHTEC_I2C_PORT_BITSHIFT 18
80 #define SWITCHTEC_I2C_PORT_BITMASK 0x0f
81 #define SWITCHTEC_I2C_ADDR_BITSHIFT 22
82 #define SWITCHTEC_I2C_ADDR_BITMASK 0x7f
83 #define SWITCHTEC_CMD_MAP_BITSHIFT 29
84 #define SWITCHTEC_CMD_MAP_BITMASK 0xfff
85 
86 #define SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK 0x40
87 #define SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK 0x80
88 #define SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK 0x0100
89 #define SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK 0x0200
90 
91 #if (HAVE_LIBCRYPTO && !HAVE_DECL_RSA_GET0_KEY)
92 
96 static void RSA_get0_key(const RSA *r, const BIGNUM **n,
97  const BIGNUM **e, const BIGNUM **d)
98 {
99  if (n != NULL)
100  *n = r->n;
101  if (e != NULL)
102  *e = r->e;
103  if (d != NULL)
104  *d = r->d;
105 }
106 #endif
107 
108 static int switchtec_mfg_cmd(struct switchtec_dev *dev, uint32_t cmd,
109  const void *payload, size_t payload_len,
110  void *resp, size_t resp_len)
111 {
112  if (dev->ops->flags & SWITCHTEC_OPS_FLAG_NO_MFG) {
113  errno = ERR_UART_NOT_SUPPORTED | SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
114  return -1;
115  }
116 
117  return switchtec_cmd(dev, cmd, payload, payload_len,
118  resp, resp_len);
119 }
120 
127 int switchtec_sn_ver_get(struct switchtec_dev *dev,
128  struct switchtec_sn_ver_info *info)
129 {
130  int ret;
131 
132  ret = switchtec_mfg_cmd(dev, MRPC_SN_VER_GET, NULL, 0, info,
133  sizeof(struct switchtec_sn_ver_info));
134  if (ret)
135  return ret;
136 
137  info->chip_serial = le32toh(info->chip_serial);
138  info->ver_bl2 = le32toh(info->ver_bl2);
139  info->ver_km = le32toh(info->ver_km);
140  info->ver_main = le32toh(info->ver_main);
141  info->ver_sec_unlock = le32toh(info->ver_sec_unlock);
142 
143  return 0;
144 }
145 
152 int switchtec_security_config_get(struct switchtec_dev *dev,
153  struct switchtec_security_cfg_state *state)
154 {
155  int ret;
156  struct cfg_reply {
157  uint32_t valid;
158  uint32_t rsvd1;
159  uint64_t cfg;
160  uint32_t public_key_exponent;
161  uint8_t rsvd2;
162  uint8_t public_key_num;
163  uint8_t public_key_ver;
164  uint8_t rsvd3;
165  uint8_t public_key[SWITCHTEC_KMSK_NUM][SWITCHTEC_KMSK_LEN];
166  uint8_t rsvd4[32];
167  } reply;
168 
169  ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_GET, NULL, 0,
170  &reply, sizeof(reply));
171  if (ret)
172  return ret;
173 
174  reply.valid = le32toh(reply.valid);
175  reply.cfg = le64toh(reply.cfg);
176  reply.public_key_exponent = le32toh(reply.public_key_exponent);
177 
178  state->basic_setting_valid = !!(reply.valid & 0x01);
179  state->public_key_exp_valid = !!(reply.valid & 0x02);
180  state->public_key_num_valid = !!(reply.valid & 0x04);
181  state->public_key_ver_valid = !!(reply.valid & 0x08);
182  state->public_key_valid = !!(reply.valid & 0x10);
183 
184  state->debug_mode = reply.cfg & 0x03;
185  state->secure_state = (reply.cfg>>2) & 0x03;
186 
187  state->jtag_lock_after_reset = !!(reply.cfg & 0x40);
188  state->jtag_lock_after_bl1 = !!(reply.cfg & 0x80);
189  state->jtag_bl1_unlock_allowed = !!(reply.cfg & 0x0100);
190  state->jtag_post_bl1_unlock_allowed = !!(reply.cfg & 0x0200);
191 
192  state->spi_clk_rate =
193  (reply.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) & 0x0f;
194  if (state->spi_clk_rate == 0)
195  state->spi_clk_rate = SWITCHTEC_SPI_RATE_25M;
196 
197  state->i2c_recovery_tmo =
198  (reply.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) & 0x0f;
199  state->i2c_port = (reply.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) & 0xf;
200  state->i2c_addr = (reply.cfg >> SWITCHTEC_I2C_ADDR_BITSHIFT) & 0x7f;
201  state->i2c_cmd_map =
202  (reply.cfg >> SWITCHTEC_CMD_MAP_BITSHIFT) & 0xfff;
203 
204  state->public_key_exponent = reply.public_key_exponent;
205  state->public_key_num = reply.public_key_num;
206  state->public_key_ver = reply.public_key_ver;
207  memcpy(state->public_key, reply.public_key,
208  SWITCHTEC_KMSK_NUM * SWITCHTEC_KMSK_LEN);
209 
210  return 0;
211 }
212 
219 int switchtec_mailbox_to_file(struct switchtec_dev *dev, int fd)
220 {
221  int ret;
222  int num_to_read = htole32(SWITCHTEC_MB_MAX_ENTRIES);
223  struct mb_reply {
224  uint8_t num_returned;
225  uint8_t num_remaining;
226  uint8_t rsvd[2];
227  uint8_t data[SWITCHTEC_MB_MAX_ENTRIES *
228  SWITCHTEC_MB_LOG_LEN];
229  } reply;
230 
231  do {
232  ret = switchtec_mfg_cmd(dev, MRPC_MAILBOX_GET, &num_to_read,
233  sizeof(int), &reply, sizeof(reply));
234  if (ret)
235  return ret;
236 
237  reply.num_remaining = le32toh(reply.num_remaining);
238  reply.num_returned = le32toh(reply.num_returned);
239 
240  ret = write(fd, reply.data,
241  (reply.num_returned) * SWITCHTEC_MB_LOG_LEN);
242  if (ret < 0)
243  return ret;
244  } while (reply.num_remaining > 0);
245 
246  return 0;
247 }
248 
255 int switchtec_security_config_set(struct switchtec_dev *dev,
256  struct switchtec_security_cfg_set *setting)
257 {
258  int ret;
259  struct setting_data {
260  uint64_t cfg;
261  uint32_t pub_key_exponent;
262  uint8_t rsvd[4];
263  } sd;
264  uint64_t ldata = 0;
265 
266  memset(&sd, 0, sizeof(sd));
267 
268  sd.cfg |= setting->jtag_lock_after_reset?
269  SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK : 0;
270  sd.cfg |= setting->jtag_lock_after_bl1?
271  SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK : 0;
272  sd.cfg |= setting->jtag_bl1_unlock_allowed?
273  SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK : 0;
274  sd.cfg |= setting->jtag_post_bl1_unlock_allowed?
275  SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK : 0;
276 
277  sd.cfg |= (setting->spi_clk_rate & SWITCHTEC_CLK_RATE_BITMASK) <<
278  SWITCHTEC_CLK_RATE_BITSHIFT;
279 
280  sd.cfg |= (setting->i2c_recovery_tmo & SWITCHTEC_RC_TMO_BITMASK) <<
281  SWITCHTEC_RC_TMO_BITSHIFT;
282  sd.cfg |= (setting->i2c_port & SWITCHTEC_I2C_PORT_BITMASK) <<
283  SWITCHTEC_I2C_PORT_BITSHIFT;
284  sd.cfg |= (setting->i2c_addr & SWITCHTEC_I2C_ADDR_BITMASK) <<
285  SWITCHTEC_I2C_ADDR_BITSHIFT;
286 
287  ldata = setting->i2c_cmd_map & SWITCHTEC_CMD_MAP_BITMASK;
288  ldata <<= SWITCHTEC_CMD_MAP_BITSHIFT;
289  sd.cfg |= ldata;
290 
291  sd.cfg = htole64(sd.cfg);
292 
293  sd.pub_key_exponent = htole32(setting->public_key_exponent);
294 
295  ret = switchtec_mfg_cmd(dev, MRPC_SECURITY_CONFIG_SET, &sd, sizeof(sd),
296  NULL, 0);
297  return ret;
298 }
299 
306 int switchtec_active_image_index_get(struct switchtec_dev *dev,
307  struct switchtec_active_index *index)
308 {
309  int ret;
310  struct active_indices {
311  uint8_t index[SWITCHTEC_ACTV_IDX_MAX_ENTRIES];
312  } reply;
313 
314  ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_GET, NULL,
315  0, &reply, sizeof(reply));
316  if (ret)
317  return ret;
318 
319  index->keyman = reply.index[SWITCHTEC_ACTV_IMG_ID_KMAN];
320  index->bl2 = reply.index[SWITCHTEC_ACTV_IMG_ID_BL2];
321  index->config = reply.index[SWITCHTEC_ACTV_IMG_ID_CFG];
322  index->firmware = reply.index[SWITCHTEC_ACTV_IMG_ID_FW];
323 
324  return 0;
325 }
326 
333 int switchtec_active_image_index_set(struct switchtec_dev *dev,
334  struct switchtec_active_index *index)
335 {
336  int ret;
337  int i = 0;
338  struct active_idx {
339  uint32_t count;
340  struct entry {
341  uint8_t image_id;
342  uint8_t index;
343  } idx[SWITCHTEC_ACTV_IDX_SET_ENTRIES];
344  } set;
345 
346  memset(&set, 0, sizeof(set));
347 
348  if (index->keyman != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
349  set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_KMAN;
350  set.idx[i].index = index->keyman;
351  i++;
352  }
353 
354  if (index->bl2 != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
355  set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_BL2;
356  set.idx[i].index = index->bl2;
357  i++;
358  }
359 
360  if (index->config != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
361  set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_CFG;
362  set.idx[i].index = index->config;
363  i++;
364  }
365 
366  if (index->firmware != SWITCHTEC_ACTIVE_INDEX_NOT_SET) {
367  set.idx[i].image_id = SWITCHTEC_ACTV_IMG_ID_FW;
368  set.idx[i].index = index->firmware;
369  i++;
370  }
371 
372  if (i == 0)
373  return 0;
374 
375  set.count = htole32(i);
376 
377  ret = switchtec_mfg_cmd(dev, MRPC_ACT_IMG_IDX_SET, &set,
378  sizeof(set), NULL, 0);
379  return ret;
380 }
381 
388 int switchtec_fw_exec(struct switchtec_dev *dev,
389  enum switchtec_bl2_recovery_mode recovery_mode)
390 {
391  struct fw_exec_struct {
392  uint8_t subcmd;
393  uint8_t recovery_mode;
394  uint8_t rsvd[2];
395  } cmd;
396 
397  memset(&cmd, 0, sizeof(cmd));
398  cmd.subcmd = MRPC_FW_TX_EXEC;
399  cmd.recovery_mode = recovery_mode;
400 
401  return switchtec_mfg_cmd(dev, MRPC_FW_TX, &cmd, sizeof(cmd), NULL, 0);
402 }
403 
416 int switchtec_boot_resume(struct switchtec_dev *dev)
417 {
418  return switchtec_mfg_cmd(dev, MRPC_BOOTUP_RESUME, NULL, 0,
419  NULL, 0);
420 }
421 
428 int switchtec_secure_state_set(struct switchtec_dev *dev,
429  enum switchtec_secure_state state)
430 {
431  uint32_t data;
432 
433  if ((state != SWITCHTEC_INITIALIZED_UNSECURED)
434  && (state != SWITCHTEC_INITIALIZED_SECURED)) {
435  return ERR_PARAM_INVALID;
436  }
437  data = htole32(state);
438 
439  return switchtec_mfg_cmd(dev, MRPC_SECURE_STATE_SET, &data,
440  sizeof(data), NULL, 0);
441 }
442 
443 static int dbg_unlock_send_pubkey(struct switchtec_dev *dev,
444  struct switchtec_pubkey *public_key)
445 {
446  struct public_key_cmd {
447  uint8_t subcmd;
448  uint8_t rsvd[3];
449  uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
450  uint32_t pub_key_exp;
451  } cmd = {};
452 
453  cmd.subcmd = MRPC_DBG_UNLOCK_PKEY;
454  memcpy(cmd.pub_key, public_key->pubkey, SWITCHTEC_PUB_KEY_LEN);
455  cmd.pub_key_exp = htole32(public_key->pubkey_exp);
456 
457  return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
458  sizeof(cmd), NULL, 0);
459 }
460 
470 int switchtec_dbg_unlock(struct switchtec_dev *dev, uint32_t serial,
471  uint32_t ver_sec_unlock,
472  struct switchtec_pubkey *public_key,
473  struct switchtec_signature *signature)
474 {
475  int ret;
476  struct unlock_cmd {
477  uint8_t subcmd;
478  uint8_t rsvd[3];
479  uint32_t serial;
480  uint32_t unlock_ver;
481  uint8_t signature[SWITCHTEC_SIG_LEN];
482  } cmd = {};
483 
484  ret = dbg_unlock_send_pubkey(dev, public_key);
485  if (ret)
486  return ret;
487 
488  cmd.subcmd = MRPC_DBG_UNLOCK_DATA;
489  cmd.serial = htole32(serial);
490  cmd.unlock_ver = htole32(ver_sec_unlock);
491  memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
492 
493  return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd,
494  sizeof(cmd), NULL, 0);
495 }
496 
506 int switchtec_dbg_unlock_version_update(struct switchtec_dev *dev,
507  uint32_t serial,
508  uint32_t ver_sec_unlock,
509  struct switchtec_pubkey *public_key,
510  struct switchtec_signature *signature)
511 {
512  int ret;
513  struct update_cmd {
514  uint8_t subcmd;
515  uint8_t rsvd[3];
516  uint32_t serial;
517  uint32_t unlock_ver;
518  uint8_t signature[SWITCHTEC_SIG_LEN];
519  } cmd = {};
520 
521  ret = dbg_unlock_send_pubkey(dev, public_key);
522  if (ret)
523  return ret;
524 
525  cmd.subcmd = MRPC_DBG_UNLOCK_UPDATE;
526  cmd.serial = htole32(serial);
527  cmd.unlock_ver = htole32(ver_sec_unlock);
528  memcpy(cmd.signature, signature->signature, SWITCHTEC_SIG_LEN);
529 
530  return switchtec_mfg_cmd(dev, MRPC_DBG_UNLOCK, &cmd, sizeof(cmd),
531  NULL, 0);
532 }
533 
540 int switchtec_read_sec_cfg_file(FILE *setting_file,
541  struct switchtec_security_cfg_set *set)
542 {
543  ssize_t rlen;
544  char magic[4] = {'S', 'S', 'F', 'F'};
545  uint32_t crc;
546  struct setting_file_header {
547  uint8_t magic[4];
548  uint32_t version;
549  uint32_t rsvd;
550  uint32_t crc;
551  };
552  struct setting_file_data {
553  uint64_t cfg;
554  uint32_t pub_key_exponent;
555  uint8_t rsvd[36];
556  };
557  struct setting_file {
558  struct setting_file_header header;
559  struct setting_file_data data;
560  } file_data;
561 
562  rlen = fread(&file_data, 1, sizeof(file_data), setting_file);
563 
564  if (rlen < sizeof(file_data))
565  return -EBADF;
566 
567  if (memcmp(file_data.header.magic, magic, sizeof(magic)))
568  return -EBADF;
569 
570  crc = crc32((uint8_t*)&file_data.data,
571  sizeof(file_data.data), 0, 1, 1);
572  if (crc != le32toh(file_data.header.crc))
573  return -EBADF;
574 
575  memset(set, 0, sizeof(struct switchtec_security_cfg_set));
576 
577  file_data.data.cfg = le64toh(file_data.data.cfg);
578 
579  set->jtag_lock_after_reset =
580  !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_RST_BITMASK);
581  set->jtag_lock_after_bl1 =
582  !!(file_data.data.cfg & SWITCHTEC_JTAG_LOCK_AFT_BL1_BITMASK);
583  set->jtag_bl1_unlock_allowed =
584  !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_BL1_BITMASK);
585  set->jtag_post_bl1_unlock_allowed =
586  !!(file_data.data.cfg & SWITCHTEC_JTAG_UNLOCK_AFT_BL1_BITMASK);
587 
588  set->spi_clk_rate =
589  (file_data.data.cfg >> SWITCHTEC_CLK_RATE_BITSHIFT) &
590  SWITCHTEC_CLK_RATE_BITMASK;
591  set->i2c_recovery_tmo =
592  (file_data.data.cfg >> SWITCHTEC_RC_TMO_BITSHIFT) &
593  SWITCHTEC_RC_TMO_BITMASK;
594  set->i2c_port =
595  (file_data.data.cfg >> SWITCHTEC_I2C_PORT_BITSHIFT) &
596  SWITCHTEC_I2C_PORT_BITMASK;
597  set->i2c_addr =
598  (file_data.data.cfg >> SWITCHTEC_I2C_ADDR_BITSHIFT) &
599  SWITCHTEC_I2C_ADDR_BITMASK;
600  set->i2c_cmd_map =
601  (file_data.data.cfg >> SWITCHTEC_CMD_MAP_BITSHIFT) &
602  SWITCHTEC_CMD_MAP_BITMASK;
603 
604  set->public_key_exponent = le32toh(file_data.data.pub_key_exponent);
605 
606  return 0;
607 }
608 
609 static int kmsk_set_send_pubkey(struct switchtec_dev *dev,
610  struct switchtec_pubkey *public_key)
611 {
612  struct kmsk_pubk_cmd {
613  uint8_t subcmd;
614  uint8_t reserved[3];
615  uint8_t pub_key[SWITCHTEC_PUB_KEY_LEN];
616  uint32_t pub_key_exponent;
617  } cmd = {};
618 
619  cmd.subcmd = MRPC_KMSK_ENTRY_SET_PKEY;
620  memcpy(cmd.pub_key, public_key->pubkey,
621  SWITCHTEC_PUB_KEY_LEN);
622  cmd.pub_key_exponent = htole32(public_key->pubkey_exp);
623 
624  return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
625  sizeof(cmd), NULL, 0);
626 }
627 
628 static int kmsk_set_send_signature(struct switchtec_dev *dev,
629  struct switchtec_signature *signature)
630 {
631  struct kmsk_signature_cmd {
632  uint8_t subcmd;
633  uint8_t reserved[3];
634  uint8_t signature[SWITCHTEC_SIG_LEN];
635  } cmd = {};
636 
637  cmd.subcmd = MRPC_KMSK_ENTRY_SET_SIG;
638  memcpy(cmd.signature, signature->signature,
639  SWITCHTEC_SIG_LEN);
640 
641  return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd,
642  sizeof(cmd), NULL, 0);
643 }
644 
645 static int kmsk_set_send_kmsk(struct switchtec_dev *dev,
646  struct switchtec_kmsk *kmsk)
647 {
648  struct kmsk_kmsk_cmd {
649  uint8_t subcmd;
650  uint8_t num_entries;
651  uint8_t reserved[2];
652  uint8_t kmsk[SWITCHTEC_KMSK_LEN];
653  } cmd = {};
654 
655  cmd.subcmd = MRPC_KMSK_ENTRY_SET_KMSK;
656  cmd.num_entries = 1;
657  memcpy(cmd.kmsk, kmsk->kmsk, SWITCHTEC_KMSK_LEN);
658 
659  return switchtec_mfg_cmd(dev, MRPC_KMSK_ENTRY_SET, &cmd, sizeof(cmd),
660  NULL, 0);
661 }
662 
675 int switchtec_kmsk_set(struct switchtec_dev *dev,
676  struct switchtec_pubkey *public_key,
677  struct switchtec_signature *signature,
678  struct switchtec_kmsk *kmsk)
679 {
680  int ret;
681 
682  if (public_key) {
683  ret = kmsk_set_send_pubkey(dev, public_key);
684  if (ret)
685  return ret;
686  }
687 
688  if (signature) {
689  ret = kmsk_set_send_signature(dev, signature);
690  if (ret)
691  return ret;
692  }
693 
694  return kmsk_set_send_kmsk(dev, kmsk);
695 }
696 
697 #if HAVE_LIBCRYPTO
698 
704 int switchtec_read_pubk_file(FILE *pubk_file, struct switchtec_pubkey *pubk)
705 {
706  RSA *RSAKey = NULL;
707  const BIGNUM *modulus_bn;
708  const BIGNUM *exponent_bn;
709  uint32_t exponent_tmp = 0;
710 
711  RSAKey = PEM_read_RSA_PUBKEY(pubk_file, NULL, NULL, NULL);
712  if (RSAKey == NULL) {
713  fseek(pubk_file, 0L, SEEK_SET);
714  RSAKey = PEM_read_RSAPrivateKey(pubk_file, NULL, NULL, NULL);
715  if (RSAKey == NULL)
716  return -1;
717  }
718 
719  RSA_get0_key(RSAKey, &modulus_bn, &exponent_bn, NULL);
720 
721  BN_bn2bin(modulus_bn, pubk->pubkey);
722  BN_bn2bin(exponent_bn, (uint8_t *)&exponent_tmp);
723 
724  pubk->pubkey_exp = be32toh(exponent_tmp);
725  RSA_free(RSAKey);
726 
727  return 0;
728 }
729 #endif
730 
737 int switchtec_read_kmsk_file(FILE *kmsk_file, struct switchtec_kmsk *kmsk)
738 {
739  ssize_t rlen;
740  struct kmsk_struct {
741  uint8_t magic[4];
742  uint32_t version;
743  uint32_t reserved;
744  uint32_t crc32;
745  uint8_t kmsk[SWITCHTEC_KMSK_LEN];
746  } data;
747 
748  char magic[4] = {'K', 'M', 'S', 'K'};
749  uint32_t crc;
750 
751  rlen = fread(&data, 1, sizeof(data), kmsk_file);
752 
753  if (rlen < sizeof(data))
754  return -EBADF;
755 
756  if (memcmp(data.magic, magic, sizeof(magic)))
757  return -EBADF;
758 
759  crc = crc32(data.kmsk, SWITCHTEC_KMSK_LEN, 0, 1, 1);
760  if (crc != le32toh(data.crc32))
761  return -EBADF;
762 
763  memcpy(kmsk->kmsk, data.kmsk, SWITCHTEC_KMSK_LEN);
764 
765  return 0;
766 }
767 
774 int switchtec_read_signature_file(FILE *sig_file,
775  struct switchtec_signature *signature)
776 {
777  ssize_t rlen;
778 
779  rlen = fread(signature->signature, 1, SWITCHTEC_SIG_LEN, sig_file);
780 
781  if (rlen < SWITCHTEC_SIG_LEN)
782  return -EBADF;
783 
784  return 0;
785 }
786 
797 int
799  struct switchtec_kmsk *kmsk)
800 {
801  int key_idx;
802 
803  for(key_idx = 0; key_idx < state->public_key_num; key_idx++) {
804  if (memcmp(state->public_key[key_idx], kmsk->kmsk,
805  SWITCHTEC_KMSK_LEN) == 0)
806  return 1;
807  }
808 
809  return 0;
810 }
811 
int switchtec_active_image_index_get(struct switchtec_dev *dev, struct switchtec_active_index *index)
Get active image index.
Definition: mfg.c:306
int switchtec_fw_exec(struct switchtec_dev *dev, enum switchtec_bl2_recovery_mode recovery_mode)
Execute the transferred firmware.
Definition: mfg.c:388
int switchtec_kmsk_set(struct switchtec_dev *dev, struct switchtec_pubkey *public_key, struct switchtec_signature *signature, struct switchtec_kmsk *kmsk)
Set KMSK entry KMSK stands for Key Manifest Secure Key. It is a key used to verify Key Manifest parti...
Definition: mfg.c:675
int switchtec_mailbox_to_file(struct switchtec_dev *dev, int fd)
Retrieve mailbox entries.
Definition: mfg.c:219
int switchtec_read_sec_cfg_file(FILE *setting_file, struct switchtec_security_cfg_set *set)
Read security settings from config file.
Definition: mfg.c:540
int switchtec_secure_state_set(struct switchtec_dev *dev, enum switchtec_secure_state state)
Set device secure state.
Definition: mfg.c:428
int switchtec_read_signature_file(FILE *sig_file, struct switchtec_signature *signature)
Read signature data from signature file.
Definition: mfg.c:774
int switchtec_sn_ver_get(struct switchtec_dev *dev, struct switchtec_sn_ver_info *info)
Get serial number and security version.
Definition: mfg.c:127
int switchtec_security_config_set(struct switchtec_dev *dev, struct switchtec_security_cfg_set *setting)
Set secure settings.
Definition: mfg.c:255
int switchtec_dbg_unlock_version_update(struct switchtec_dev *dev, uint32_t serial, uint32_t ver_sec_unlock, struct switchtec_pubkey *public_key, struct switchtec_signature *signature)
Update firmware debug secure unlock version number.
Definition: mfg.c:506
int switchtec_read_kmsk_file(FILE *kmsk_file, struct switchtec_kmsk *kmsk)
Read KMSK data from KMSK file.
Definition: mfg.c:737
Main Switchtec header.
int switchtec_security_config_get(struct switchtec_dev *dev, struct switchtec_security_cfg_state *state)
Get secure boot configurations.
Definition: mfg.c:152
int switchtec_dbg_unlock(struct switchtec_dev *dev, uint32_t serial, uint32_t ver_sec_unlock, struct switchtec_pubkey *public_key, struct switchtec_signature *signature)
Unlock firmware debug features.
Definition: mfg.c:470
int switchtec_boot_resume(struct switchtec_dev *dev)
Resume device boot. Note that after calling this function, the current &#39;dev&#39; pointer is no longer val...
Definition: mfg.c:416
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:132
int switchtec_security_state_has_kmsk(struct switchtec_security_cfg_state *state, struct switchtec_kmsk *kmsk)
Check if secure config already has a KMSK entry KMSK stands for Key Manifest Secure Key...
Definition: mfg.c:798
int switchtec_active_image_index_set(struct switchtec_dev *dev, struct switchtec_active_index *index)
Set active image index.
Definition: mfg.c:333