/* * Copyright (C) 2016 Freescale Semiconductor, Inc. * Copyright 2017-2019 NXP * * SPDX-License-Identifier: BSD-3-Clause */ /*! * File containing client-side RPC functions for the SECO service. These * functions are ported to clients that communicate to the SC. * * @addtogroup SECO_SVC * @{ */ /* Includes */ #include #include #include #include #include "sci_seco_rpc.h" #include /* Local Defines */ /* Local Types */ /* Local Functions */ sc_err_t sc_seco_image_load(sc_ipc_t ipc, sc_faddr_t addr_src, sc_faddr_t addr_dst, uint32_t len, sc_bool_t fw) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 7U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_IMAGE_LOAD); RPC_U32(&msg, 0U) = U32(addr_src >> 32ULL); RPC_U32(&msg, 4U) = U32(addr_src); RPC_U32(&msg, 8U) = U32(addr_dst >> 32ULL); RPC_U32(&msg, 12U) = U32(addr_dst); RPC_U32(&msg, 16U) = U32(len); RPC_U8(&msg, 20U) = B2U8(fw); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_authenticate(sc_ipc_t ipc, sc_seco_auth_cmd_t cmd, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 4U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_AUTHENTICATE); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); RPC_U8(&msg, 8U) = U8(cmd); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_enh_authenticate(sc_ipc_t ipc, sc_seco_auth_cmd_t cmd, sc_faddr_t addr, uint32_t mask1, uint32_t mask2) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 6U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_ENH_AUTHENTICATE); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); RPC_U32(&msg, 8U) = U32(mask1); RPC_U32(&msg, 12U) = U32(mask2); RPC_U8(&msg, 16U) = U8(cmd); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_forward_lifecycle(sc_ipc_t ipc, uint32_t change) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 2U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_FORWARD_LIFECYCLE); RPC_U32(&msg, 0U) = U32(change); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_return_lifecycle(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_RETURN_LIFECYCLE); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_commit(sc_ipc_t ipc, uint32_t *info) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 2U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_COMMIT); RPC_U32(&msg, 0U) = U32(*info); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); *info = (uint32_t)RPC_U32(&msg, 0U); return err; } sc_err_t sc_seco_attest_mode(sc_ipc_t ipc, uint32_t mode) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 2U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_ATTEST_MODE); RPC_U32(&msg, 0U) = U32(mode); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_attest(sc_ipc_t ipc, uint64_t nonce) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_ATTEST); RPC_U32(&msg, 0U) = U32(nonce >> 32ULL); RPC_U32(&msg, 4U) = U32(nonce); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_get_attest_pkey(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_GET_ATTEST_PKEY); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_get_attest_sign(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_GET_ATTEST_SIGN); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_attest_verify(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_ATTEST_VERIFY); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_gen_key_blob(sc_ipc_t ipc, uint32_t id, sc_faddr_t load_addr, sc_faddr_t export_addr, uint16_t max_size) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 7U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_GEN_KEY_BLOB); RPC_U32(&msg, 0U) = U32(load_addr >> 32ULL); RPC_U32(&msg, 4U) = U32(load_addr); RPC_U32(&msg, 8U) = U32(export_addr >> 32ULL); RPC_U32(&msg, 12U) = U32(export_addr); RPC_U32(&msg, 16U) = U32(id); RPC_U16(&msg, 20U) = U16(max_size); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_load_key(sc_ipc_t ipc, uint32_t id, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 4U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_LOAD_KEY); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); RPC_U32(&msg, 8U) = U32(id); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_get_mp_key(sc_ipc_t ipc, sc_faddr_t dst_addr, uint16_t dst_size) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 4U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_GET_MP_KEY); RPC_U32(&msg, 0U) = U32(dst_addr >> 32ULL); RPC_U32(&msg, 4U) = U32(dst_addr); RPC_U16(&msg, 8U) = U16(dst_size); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_update_mpmr(sc_ipc_t ipc, sc_faddr_t addr, uint8_t size, uint8_t lock) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 4U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_UPDATE_MPMR); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); RPC_U8(&msg, 8U) = U8(size); RPC_U8(&msg, 9U) = U8(lock); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_get_mp_sign(sc_ipc_t ipc, sc_faddr_t msg_addr, uint16_t msg_size, sc_faddr_t dst_addr, uint16_t dst_size) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 6U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_GET_MP_SIGN); RPC_U32(&msg, 0U) = U32(msg_addr >> 32ULL); RPC_U32(&msg, 4U) = U32(msg_addr); RPC_U32(&msg, 8U) = U32(dst_addr >> 32ULL); RPC_U32(&msg, 12U) = U32(dst_addr); RPC_U16(&msg, 16U) = U16(msg_size); RPC_U16(&msg, 18U) = U16(dst_size); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } void sc_seco_build_info(sc_ipc_t ipc, uint32_t *version, uint32_t *commit) { sc_rpc_msg_t msg; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 1U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_BUILD_INFO); sc_call_rpc(ipc, &msg, SC_FALSE); if (version != NULL) { *version = (uint32_t)RPC_U32(&msg, 0U); } if (commit != NULL) { *commit = (uint32_t)RPC_U32(&msg, 4U); } } sc_err_t sc_seco_chip_info(sc_ipc_t ipc, uint16_t *lc, uint16_t *monotonic, uint32_t *uid_l, uint32_t *uid_h) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 1U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_CHIP_INFO); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); if (uid_l != NULL) { *uid_l = (uint32_t)RPC_U32(&msg, 0U); } if (uid_h != NULL) { *uid_h = (uint32_t)RPC_U32(&msg, 4U); } if (lc != NULL) { *lc = (uint16_t)RPC_U16(&msg, 8U); } if (monotonic != NULL) { *monotonic = (uint16_t)RPC_U16(&msg, 10U); } return err; } sc_err_t sc_seco_enable_debug(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_ENABLE_DEBUG); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_get_event(sc_ipc_t ipc, uint8_t idx, uint32_t *event) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 2U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_GET_EVENT); RPC_U8(&msg, 0U) = U8(idx); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); if (event != NULL) { *event = (uint32_t)RPC_U32(&msg, 0U); } return err; } sc_err_t sc_seco_fuse_write(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_FUSE_WRITE); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_patch(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_PATCH); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_start_rng(sc_ipc_t ipc, sc_seco_rng_stat_t * status) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 1U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_START_RNG); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); if (status != NULL) { *status = (sc_seco_rng_stat_t) RPC_U32(&msg, 0U); } return err; } sc_err_t sc_seco_sab_msg(sc_ipc_t ipc, sc_faddr_t addr) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_SAB_MSG); RPC_U32(&msg, 0U) = U32(addr >> 32ULL); RPC_U32(&msg, 4U) = U32(addr); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_secvio_enable(sc_ipc_t ipc) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 1U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_SECVIO_ENABLE); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); return err; } sc_err_t sc_seco_secvio_config(sc_ipc_t ipc, uint8_t id, uint8_t access, uint32_t *data0, uint32_t *data1, uint32_t *data2, uint32_t *data3, uint32_t *data4, uint8_t size) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 7U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_SECVIO_CONFIG); RPC_U32(&msg, 0U) = U32(*data0); RPC_U32(&msg, 4U) = U32(*data1); RPC_U32(&msg, 8U) = U32(*data2); RPC_U32(&msg, 12U) = U32(*data3); RPC_U32(&msg, 16U) = U32(*data4); RPC_U8(&msg, 20U) = U8(id); RPC_U8(&msg, 21U) = U8(access); RPC_U8(&msg, 22U) = U8(size); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); *data0 = (uint32_t)RPC_U32(&msg, 0U); *data1 = (uint32_t)RPC_U32(&msg, 4U); *data2 = (uint32_t)RPC_U32(&msg, 8U); *data3 = (uint32_t)RPC_U32(&msg, 12U); *data4 = (uint32_t)RPC_U32(&msg, 16U); return err; } sc_err_t sc_seco_secvio_dgo_config(sc_ipc_t ipc, uint8_t id, uint8_t access, uint32_t *data) { sc_rpc_msg_t msg; sc_err_t err; RPC_VER(&msg) = SC_RPC_VERSION; RPC_SIZE(&msg) = 3U; RPC_SVC(&msg) = U8(SC_RPC_SVC_SECO); RPC_FUNC(&msg) = U8(SECO_FUNC_SECVIO_DGO_CONFIG); RPC_U32(&msg, 0U) = U32(*data); RPC_U8(&msg, 4U) = U8(id); RPC_U8(&msg, 5U) = U8(access); sc_call_rpc(ipc, &msg, SC_FALSE); err = (sc_err_t)RPC_R8(&msg); *data = (uint32_t)RPC_U32(&msg, 0U); return err; } /**@}*/