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