1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2021, Foundries.io Ltd
4 */
5
6 #ifndef BINARY_PREFIX
7 #define BINARY_PREFIX "seteec"
8 #endif
9
10 #include <errno.h>
11 #include <inttypes.h>
12 #include <pthread.h>
13 #include <se_tee.h>
14 #include <signal.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <tee_client_api.h>
19 #include <teec_trace.h>
20
21 #include "pta_apdu.h"
22 #include "pta_scp03.h"
23
24 struct ta_context {
25 pthread_mutex_t lock;
26 TEEC_Context context;
27 TEEC_Session session;
28 TEEC_UUID uuid;
29 bool open;
30 };
31
32 static struct ta_context apdu_ta_ctx = {
33 .lock = PTHREAD_MUTEX_INITIALIZER,
34 .uuid = PTA_APDU_UUID,
35 };
36
37 static struct ta_context scp03_ta_ctx = {
38 .lock = PTHREAD_MUTEX_INITIALIZER,
39 .uuid = PTA_SCP03_UUID,
40 };
41
open_session(struct ta_context * ctx)42 static bool open_session(struct ta_context *ctx)
43 {
44 TEEC_Result res = TEEC_SUCCESS;
45
46 if (pthread_mutex_lock(&ctx->lock))
47 return false;
48
49 if (!ctx->open) {
50 res = TEEC_InitializeContext(NULL, &ctx->context);
51 if (!res) {
52 res = TEEC_OpenSession(&ctx->context, &ctx->session,
53 &ctx->uuid, TEEC_LOGIN_PUBLIC,
54 NULL, NULL, NULL);
55 if (!res)
56 ctx->open = true;
57 }
58 }
59
60 return !pthread_mutex_unlock(&ctx->lock) && !res;
61 }
62
do_scp03(uint32_t cmd)63 static SE_RV do_scp03(uint32_t cmd)
64 {
65 TEEC_Operation op = { 0 };
66
67 if (!open_session(&scp03_ta_ctx))
68 return SER_CANT_OPEN_SESSION;
69
70 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, 0, 0, 0);
71 op.params[0].value.a = cmd;
72
73 if (TEEC_InvokeCommand(&scp03_ta_ctx.session,
74 PTA_CMD_ENABLE_SCP03, &op, NULL))
75 return SER_ERROR_GENERIC;
76
77 return SER_OK;
78 }
79
se_scp03_enable(void)80 SE_RV se_scp03_enable(void)
81 {
82 return do_scp03(PTA_SCP03_SESSION_CURRENT_KEYS);
83 }
84
se_scp03_rotate_keys_and_enable(void)85 SE_RV se_scp03_rotate_keys_and_enable(void)
86 {
87 return do_scp03(PTA_SCP03_SESSION_ROTATE_KEYS);
88 }
89
se_apdu_request(enum se_apdu_type apdu_type,unsigned char * hdr,size_t hdr_len,unsigned char * src,size_t src_len,unsigned char * dst,size_t * dst_len)90 SE_RV se_apdu_request(enum se_apdu_type apdu_type,
91 unsigned char *hdr, size_t hdr_len,
92 unsigned char *src, size_t src_len,
93 unsigned char *dst, size_t *dst_len)
94 {
95 uint32_t type = PTA_APDU_TXRX_CASE_NO_HINT;
96 TEEC_Operation op = { 0 };
97
98 switch (apdu_type) {
99 case SE_APDU_NO_HINT:
100 type = PTA_APDU_TXRX_CASE_NO_HINT;
101 break;
102 case SE_APDU_CASE_1:
103 type = PTA_APDU_TXRX_CASE_1;
104 break;
105 case SE_APDU_CASE_2:
106 type = PTA_APDU_TXRX_CASE_2;
107 break;
108 case SE_APDU_CASE_2E:
109 type = PTA_APDU_TXRX_CASE_2E;
110 break;
111 case SE_APDU_CASE_3:
112 type = PTA_APDU_TXRX_CASE_3;
113 break;
114 case SE_APDU_CASE_3E:
115 type = PTA_APDU_TXRX_CASE_3E;
116 break;
117 case SE_APDU_CASE_4:
118 type = PTA_APDU_TXRX_CASE_4;
119 break;
120 case SE_APDU_CASE_4E:
121 type = PTA_APDU_TXRX_CASE_4E;
122 break;
123 default:
124 return SER_ERROR_GENERIC;
125 }
126
127 if (!open_session(&apdu_ta_ctx))
128 return SER_CANT_OPEN_SESSION;
129
130 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT,
131 TEEC_MEMREF_TEMP_INPUT,
132 TEEC_MEMREF_TEMP_INPUT,
133 TEEC_MEMREF_TEMP_OUTPUT);
134 op.params[0].value.a = type;
135 op.params[1].tmpref.buffer = hdr;
136 op.params[1].tmpref.size = hdr_len;
137 op.params[2].tmpref.buffer = src;
138 op.params[2].tmpref.size = src_len;
139 op.params[3].tmpref.buffer = dst;
140 op.params[3].tmpref.size = *dst_len;
141
142 if (TEEC_InvokeCommand(&apdu_ta_ctx.session,
143 PTA_CMD_TXRX_APDU_RAW_FRAME, &op, NULL))
144 return SER_ERROR_GENERIC;
145
146 *dst_len = op.params[3].tmpref.size;
147
148 return SER_OK;
149 }
150