dice_protection_environment.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*
  2. * Copyright (c) 2024, Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <qcbor/qcbor_decode.h>
  8. #include <qcbor/qcbor_encode.h>
  9. #include <qcbor/qcbor_spiffy_decode.h>
  10. #include <common/debug.h>
  11. #include <dice.h>
  12. #include <dice_protection_environment.h>
  13. #include <psa/client.h>
  14. #include <psa_manifest/sid.h>
  15. enum dpe_command_id_t {
  16. /* Standard commands */
  17. DPE_GET_PROFILE = 1,
  18. DPE_OPEN_SESSION = 2,
  19. DPE_CLOSE_SESSION = 3,
  20. DPE_SYNC_SESSION = 4,
  21. DPE_EXPORT_SESSION = 5,
  22. DPE_IMPORT_SESSION = 6,
  23. DPE_INITIALIZE_CONTEXT = 7,
  24. DPE_DERIVE_CONTEXT = 8,
  25. DPE_CERTIFY_KEY = 9,
  26. DPE_SIGN = 10,
  27. DPE_SEAL = 11,
  28. DPE_UNSEAL = 12,
  29. DPE_DERIVE_SEALING_PUBLIC_KEY = 13,
  30. DPE_ROTATE_CONTEXT_HANDLE = 14,
  31. DPE_DESTROY_CONTEXT = 15,
  32. };
  33. enum dice_input_labels_t {
  34. DICE_CODE_HASH = 1,
  35. DICE_CODE_DESCRIPTOR = 2,
  36. DICE_CONFIG_TYPE = 3,
  37. DICE_CONFIG_VALUE = 4,
  38. DICE_CONFIG_DESCRIPTOR = 5,
  39. DICE_AUTHORITY_HASH = 6,
  40. DICE_AUTHORITY_DESCRIPTOR = 7,
  41. DICE_MODE = 8,
  42. DICE_HIDDEN = 9,
  43. };
  44. enum dpe_derive_context_input_labels_t {
  45. DPE_DERIVE_CONTEXT_CONTEXT_HANDLE = 1,
  46. DPE_DERIVE_CONTEXT_RETAIN_PARENT_CONTEXT = 2,
  47. DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_DERIVE = 3,
  48. DPE_DERIVE_CONTEXT_CREATE_CERTIFICATE = 4,
  49. DPE_DERIVE_CONTEXT_NEW_SESSION_INITIATOR_HANDSHAKE = 5,
  50. DPE_DERIVE_CONTEXT_INPUT_DATA = 6,
  51. DPE_DERIVE_CONTEXT_INTERNAL_INPUTS = 7,
  52. DPE_DERIVE_CONTEXT_TARGET_LOCALITY = 8,
  53. DPE_DERIVE_CONTEXT_RETURN_CERTIFICATE = 9,
  54. DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_EXPORT = 10,
  55. DPE_DERIVE_CONTEXT_EXPORT_CDI = 11,
  56. /* enum values 256 and onwards are reserved for custom arguments */
  57. DPE_DERIVE_CONTEXT_CERT_ID = 256,
  58. };
  59. enum dpe_derive_context_output_labels_t {
  60. DPE_DERIVE_CONTEXT_NEW_CONTEXT_HANDLE = 1,
  61. DPE_DERIVE_CONTEXT_NEW_SESSION_RESPONDER_HANDSHAKE = 2,
  62. DPE_DERIVE_CONTEXT_PARENT_CONTEXT_HANDLE = 3,
  63. DPE_DERIVE_CONTEXT_NEW_CERTIFICATE = 4,
  64. DPE_DERIVE_CONTEXT_EXPORTED_CDI = 5,
  65. };
  66. struct derive_context_input_t {
  67. int context_handle;
  68. uint32_t cert_id;
  69. bool retain_parent_context;
  70. bool allow_new_context_to_derive;
  71. bool create_certificate;
  72. const DiceInputValues *dice_inputs;
  73. int32_t target_locality;
  74. bool return_certificate;
  75. bool allow_new_context_to_export;
  76. bool export_cdi;
  77. };
  78. struct derive_context_output_t {
  79. int new_context_handle;
  80. int new_parent_context_handle;
  81. const uint8_t *new_certificate;
  82. size_t new_certificate_size;
  83. const uint8_t *exported_cdi;
  84. size_t exported_cdi_size;
  85. };
  86. static void encode_dice_inputs(QCBOREncodeContext *encode_ctx,
  87. const DiceInputValues *input)
  88. {
  89. /* Wrap the DICE inputs into a byte string */
  90. QCBOREncode_BstrWrapInMapN(encode_ctx, DPE_DERIVE_CONTEXT_INPUT_DATA);
  91. /* Inside the byte string the DICE inputs are encoded as a map */
  92. QCBOREncode_OpenMap(encode_ctx);
  93. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_CODE_HASH,
  94. (UsefulBufC) { input->code_hash,
  95. sizeof(input->code_hash) });
  96. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_CODE_DESCRIPTOR,
  97. (UsefulBufC) { input->code_descriptor,
  98. input->code_descriptor_size });
  99. QCBOREncode_AddInt64ToMapN(encode_ctx, DICE_CONFIG_TYPE,
  100. input->config_type);
  101. if (input->config_type == kDiceConfigTypeInline) {
  102. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_CONFIG_VALUE,
  103. (UsefulBufC) { input->config_value,
  104. sizeof(input->config_value) });
  105. } else {
  106. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_CONFIG_DESCRIPTOR,
  107. (UsefulBufC) { input->config_descriptor,
  108. input->config_descriptor_size });
  109. }
  110. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_AUTHORITY_HASH,
  111. (UsefulBufC) { input->authority_hash,
  112. sizeof(input->authority_hash) });
  113. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_AUTHORITY_DESCRIPTOR,
  114. (UsefulBufC) { input->authority_descriptor,
  115. input->authority_descriptor_size });
  116. QCBOREncode_AddInt64ToMapN(encode_ctx, DICE_MODE, input->mode);
  117. QCBOREncode_AddBytesToMapN(encode_ctx, DICE_HIDDEN,
  118. (UsefulBufC) { input->hidden,
  119. sizeof(input->hidden) });
  120. QCBOREncode_CloseMap(encode_ctx);
  121. QCBOREncode_CloseBstrWrap2(encode_ctx, true, NULL);
  122. }
  123. static QCBORError encode_derive_context(const struct derive_context_input_t *args,
  124. UsefulBuf buf,
  125. UsefulBufC *encoded_buf)
  126. {
  127. QCBOREncodeContext encode_ctx;
  128. QCBOREncode_Init(&encode_ctx, buf);
  129. QCBOREncode_OpenArray(&encode_ctx);
  130. QCBOREncode_AddUInt64(&encode_ctx, DPE_DERIVE_CONTEXT);
  131. /* Encode DeriveContext command */
  132. QCBOREncode_OpenMap(&encode_ctx);
  133. QCBOREncode_AddBytesToMapN(&encode_ctx,
  134. DPE_DERIVE_CONTEXT_CONTEXT_HANDLE,
  135. (UsefulBufC) { &args->context_handle,
  136. sizeof(args->context_handle) });
  137. QCBOREncode_AddUInt64ToMapN(&encode_ctx,
  138. DPE_DERIVE_CONTEXT_CERT_ID,
  139. args->cert_id);
  140. QCBOREncode_AddBoolToMapN(&encode_ctx,
  141. DPE_DERIVE_CONTEXT_RETAIN_PARENT_CONTEXT,
  142. args->retain_parent_context);
  143. QCBOREncode_AddBoolToMapN(&encode_ctx,
  144. DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_DERIVE,
  145. args->allow_new_context_to_derive);
  146. QCBOREncode_AddBoolToMapN(&encode_ctx,
  147. DPE_DERIVE_CONTEXT_CREATE_CERTIFICATE,
  148. args->create_certificate);
  149. encode_dice_inputs(&encode_ctx, args->dice_inputs);
  150. QCBOREncode_AddBytesToMapN(&encode_ctx,
  151. DPE_DERIVE_CONTEXT_TARGET_LOCALITY,
  152. (UsefulBufC) { &args->target_locality,
  153. sizeof(args->target_locality) });
  154. QCBOREncode_AddBoolToMapN(&encode_ctx,
  155. DPE_DERIVE_CONTEXT_RETURN_CERTIFICATE,
  156. args->return_certificate);
  157. QCBOREncode_AddBoolToMapN(&encode_ctx,
  158. DPE_DERIVE_CONTEXT_ALLOW_NEW_CONTEXT_TO_EXPORT,
  159. args->allow_new_context_to_export);
  160. QCBOREncode_AddBoolToMapN(&encode_ctx,
  161. DPE_DERIVE_CONTEXT_EXPORT_CDI,
  162. args->export_cdi);
  163. QCBOREncode_CloseMap(&encode_ctx);
  164. QCBOREncode_CloseArray(&encode_ctx);
  165. return QCBOREncode_Finish(&encode_ctx, encoded_buf);
  166. }
  167. static QCBORError decode_derive_context_response(UsefulBufC encoded_buf,
  168. struct derive_context_output_t *args,
  169. dpe_error_t *dpe_err)
  170. {
  171. QCBORDecodeContext decode_ctx;
  172. UsefulBufC out;
  173. int64_t response_dpe_err;
  174. QCBORDecode_Init(&decode_ctx, encoded_buf, QCBOR_DECODE_MODE_NORMAL);
  175. QCBORDecode_EnterArray(&decode_ctx, NULL);
  176. /* Get the error code from the response. DPE returns int32_t */
  177. QCBORDecode_GetInt64(&decode_ctx, &response_dpe_err);
  178. *dpe_err = (dpe_error_t)response_dpe_err;
  179. /* Decode DeriveContext response if successful */
  180. if (*dpe_err == DPE_NO_ERROR) {
  181. QCBORDecode_EnterMap(&decode_ctx, NULL);
  182. QCBORDecode_GetByteStringInMapN(&decode_ctx,
  183. DPE_DERIVE_CONTEXT_NEW_CONTEXT_HANDLE,
  184. &out);
  185. if (out.len != sizeof(args->new_context_handle)) {
  186. return QCBORDecode_Finish(&decode_ctx);
  187. }
  188. memcpy(&args->new_context_handle, out.ptr, out.len);
  189. QCBORDecode_GetByteStringInMapN(&decode_ctx,
  190. DPE_DERIVE_CONTEXT_PARENT_CONTEXT_HANDLE,
  191. &out);
  192. if (out.len != sizeof(args->new_parent_context_handle)) {
  193. return QCBORDecode_Finish(&decode_ctx);
  194. }
  195. memcpy(&args->new_parent_context_handle, out.ptr, out.len);
  196. QCBORDecode_GetByteStringInMapN(&decode_ctx,
  197. DPE_DERIVE_CONTEXT_NEW_CERTIFICATE,
  198. &out);
  199. args->new_certificate = out.ptr;
  200. args->new_certificate_size = out.len;
  201. QCBORDecode_GetByteStringInMapN(&decode_ctx,
  202. DPE_DERIVE_CONTEXT_EXPORTED_CDI,
  203. &out);
  204. args->exported_cdi = out.ptr;
  205. args->exported_cdi_size = out.len;
  206. QCBORDecode_ExitMap(&decode_ctx);
  207. }
  208. QCBORDecode_ExitArray(&decode_ctx);
  209. return QCBORDecode_Finish(&decode_ctx);
  210. }
  211. static int32_t dpe_client_call(const char *cmd_input, size_t cmd_input_size,
  212. char *cmd_output, size_t *cmd_output_size)
  213. {
  214. int32_t err;
  215. psa_invec in_vec[] = {
  216. { cmd_input, cmd_input_size },
  217. };
  218. psa_outvec out_vec[] = {
  219. { cmd_output, *cmd_output_size },
  220. };
  221. err = psa_call(RSE_DPE_SERVICE_HANDLE, 0,
  222. in_vec, IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
  223. if (err == PSA_SUCCESS) {
  224. *cmd_output_size = out_vec[0].len;
  225. }
  226. return err;
  227. }
  228. dpe_error_t dpe_derive_context(int context_handle,
  229. uint32_t cert_id,
  230. bool retain_parent_context,
  231. bool allow_new_context_to_derive,
  232. bool create_certificate,
  233. const DiceInputValues *dice_inputs,
  234. int32_t target_locality,
  235. bool return_certificate,
  236. bool allow_new_context_to_export,
  237. bool export_cdi,
  238. int *new_context_handle,
  239. int *new_parent_context_handle,
  240. uint8_t *new_certificate_buf,
  241. size_t new_certificate_buf_size,
  242. size_t *new_certificate_actual_size,
  243. uint8_t *exported_cdi_buf,
  244. size_t exported_cdi_buf_size,
  245. size_t *exported_cdi_actual_size)
  246. {
  247. int32_t service_err;
  248. dpe_error_t dpe_err;
  249. QCBORError qcbor_err;
  250. UsefulBufC encoded_buf;
  251. UsefulBuf_MAKE_STACK_UB(cmd_buf, 612);
  252. const struct derive_context_input_t in_args = {
  253. context_handle,
  254. cert_id,
  255. retain_parent_context,
  256. allow_new_context_to_derive,
  257. create_certificate,
  258. dice_inputs,
  259. target_locality,
  260. return_certificate,
  261. allow_new_context_to_export,
  262. export_cdi,
  263. };
  264. struct derive_context_output_t out_args;
  265. /*
  266. * Validate the output params here because they are not sent to the
  267. * service. Input params are validated by the DPE service.
  268. */
  269. if ((new_context_handle == NULL) ||
  270. (retain_parent_context == true && new_parent_context_handle == NULL) ||
  271. (return_certificate == true &&
  272. (new_certificate_buf == NULL || new_certificate_actual_size == NULL)) ||
  273. (export_cdi == true &&
  274. (exported_cdi_buf == NULL || exported_cdi_actual_size == NULL))) {
  275. return DPE_INVALID_ARGUMENT;
  276. }
  277. qcbor_err = encode_derive_context(&in_args, cmd_buf, &encoded_buf);
  278. if (qcbor_err != QCBOR_SUCCESS) {
  279. return DPE_INTERNAL_ERROR;
  280. }
  281. service_err = dpe_client_call(encoded_buf.ptr, encoded_buf.len,
  282. cmd_buf.ptr, &cmd_buf.len);
  283. if (service_err != 0) {
  284. return DPE_INTERNAL_ERROR;
  285. }
  286. qcbor_err = decode_derive_context_response(UsefulBuf_Const(cmd_buf),
  287. &out_args, &dpe_err);
  288. if (qcbor_err != QCBOR_SUCCESS) {
  289. return DPE_INTERNAL_ERROR;
  290. } else if (dpe_err != DPE_NO_ERROR) {
  291. return dpe_err;
  292. }
  293. /* Copy returned values into caller's memory */
  294. *new_context_handle = out_args.new_context_handle;
  295. if (retain_parent_context == true) {
  296. *new_parent_context_handle = out_args.new_parent_context_handle;
  297. }
  298. if (return_certificate == true) {
  299. if (out_args.new_certificate_size > new_certificate_buf_size) {
  300. return DPE_INVALID_ARGUMENT;
  301. }
  302. memcpy(new_certificate_buf, out_args.new_certificate,
  303. out_args.new_certificate_size);
  304. *new_certificate_actual_size = out_args.new_certificate_size;
  305. }
  306. if (export_cdi == true) {
  307. if (out_args.exported_cdi_size > exported_cdi_buf_size) {
  308. return DPE_INVALID_ARGUMENT;
  309. }
  310. memcpy(exported_cdi_buf, out_args.exported_cdi,
  311. out_args.exported_cdi_size);
  312. *exported_cdi_actual_size = out_args.exported_cdi_size;
  313. }
  314. return DPE_NO_ERROR;
  315. }