1 /* 2 * Copyright (c) 2014, STMicroelectronics International N.V. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 #include <kernel/tee_time.h> 28 29 #include <string.h> 30 #include <stdlib.h> 31 #include <kernel/tee_rpc.h> 32 #include <kernel/tee_core_trace.h> 33 #include <utee_defines.h> 34 #include <kernel/thread.h> 35 #include <sm/teesmc.h> 36 #include <mm/core_mmu.h> 37 38 /* 39 * tee_time_get_ree_time(): this function implements the GP Internal API 40 * function TEE_GetREETime() 41 * Goal is to get the time of the Rich Execution Environment 42 * This is why this time is provided through the supplicant 43 */ 44 TEE_Result tee_time_get_ree_time(TEE_Time *time) 45 { 46 TEE_Result res = TEE_ERROR_BAD_PARAMETERS; 47 struct teesmc32_arg *arg; 48 struct teesmc32_param *params; 49 paddr_t pharg = 0; 50 paddr_t phpayload = 0; 51 paddr_t cookie = 0; 52 TEE_Time *payload; 53 54 if (!time) 55 goto exit; 56 57 pharg = thread_rpc_alloc_arg(TEESMC32_GET_ARG_SIZE(1)); 58 if (!pharg) 59 goto exit; 60 thread_st_rpc_alloc_payload(sizeof(TEE_Time), &phpayload, &cookie); 61 if (!phpayload) 62 goto exit; 63 64 if (!TEE_ALIGNMENT_IS_OK(pharg, struct teesmc32_arg) || 65 !TEE_ALIGNMENT_IS_OK(phpayload, TEE_Time)) 66 goto exit; 67 68 if (core_pa2va(pharg, (uint32_t *)&arg) || 69 core_pa2va(phpayload, (uint32_t *)&payload)) 70 goto exit; 71 72 arg->cmd = TEE_RPC_GET_TIME; 73 arg->ret = TEE_ERROR_GENERIC; 74 arg->num_params = 1; 75 params = TEESMC32_GET_PARAMS(arg); 76 params[0].attr = TEESMC_ATTR_TYPE_MEMREF_OUTPUT | 77 (TEESMC_ATTR_CACHE_I_WRITE_THR | 78 TEESMC_ATTR_CACHE_O_WRITE_THR) << 79 TEESMC_ATTR_CACHE_SHIFT; 80 params[0].u.memref.buf_ptr = phpayload; 81 params[0].u.memref.size = sizeof(TEE_Time); 82 83 thread_rpc_cmd(pharg); 84 res = arg->ret; 85 if (res != TEE_SUCCESS) 86 goto exit; 87 88 *time = *payload; 89 90 exit: 91 thread_rpc_free_arg(pharg); 92 thread_st_rpc_free_payload(cookie); 93 return res; 94 } 95 96 struct tee_ta_time_offs { 97 TEE_UUID uuid; 98 TEE_Time offs; 99 bool positive; 100 }; 101 102 static struct tee_ta_time_offs *tee_time_offs; 103 static size_t tee_time_num_offs; 104 105 static TEE_Result tee_time_ta_get_offs(const TEE_UUID *uuid, 106 const TEE_Time **offs, bool *positive) 107 { 108 size_t n; 109 110 for (n = 0; n < tee_time_num_offs; n++) { 111 if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) 112 == 0) { 113 *offs = &tee_time_offs[n].offs; 114 *positive = tee_time_offs[n].positive; 115 return TEE_SUCCESS; 116 } 117 } 118 return TEE_ERROR_TIME_NOT_SET; 119 } 120 121 static TEE_Result tee_time_ta_set_offs(const TEE_UUID *uuid, 122 const TEE_Time *offs, bool positive) 123 { 124 size_t n; 125 struct tee_ta_time_offs *o; 126 127 for (n = 0; n < tee_time_num_offs; n++) { 128 if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) 129 == 0) { 130 tee_time_offs[n].offs = *offs; 131 tee_time_offs[n].positive = positive; 132 return TEE_SUCCESS; 133 } 134 } 135 136 n = tee_time_num_offs + 1; 137 o = malloc(n * sizeof(struct tee_ta_time_offs)); 138 if (o == NULL) 139 return TEE_ERROR_OUT_OF_MEMORY; 140 memcpy(o, tee_time_offs, 141 tee_time_num_offs * sizeof(struct tee_ta_time_offs)); 142 free(tee_time_offs); 143 tee_time_offs = o; 144 tee_time_offs[tee_time_num_offs].uuid = *uuid; 145 tee_time_offs[tee_time_num_offs].offs = *offs; 146 tee_time_offs[tee_time_num_offs].positive = positive; 147 tee_time_num_offs = n; 148 return TEE_SUCCESS; 149 } 150 151 TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time) 152 { 153 TEE_Result res; 154 const TEE_Time *offs; 155 bool positive; 156 TEE_Time t; 157 TEE_Time t2; 158 159 res = tee_time_ta_get_offs(uuid, &offs, &positive); 160 if (res != TEE_SUCCESS) 161 return res; 162 163 res = tee_time_get_sys_time(&t); 164 if (res != TEE_SUCCESS) 165 return res; 166 167 if (positive) { 168 TEE_TIME_ADD(t, *offs, t2); 169 170 /* Detect wrapping, the wrapped time should be returned. */ 171 if (TEE_TIME_LT(t2, t)) 172 res = TEE_ERROR_OVERFLOW; 173 } else { 174 TEE_TIME_SUB(t, *offs, t2); 175 176 /* Detect wrapping, the wrapped time should be returned. */ 177 if (TEE_TIME_LE(t, t2)) 178 res = TEE_ERROR_OVERFLOW; 179 } 180 *time = t2; 181 182 return res; 183 } 184 185 TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time) 186 { 187 TEE_Result res; 188 TEE_Time offs; 189 TEE_Time t; 190 191 /* Check that time is normalized. */ 192 if (time->millis >= TEE_TIME_MILLIS_BASE) 193 return TEE_ERROR_BAD_PARAMETERS; 194 195 res = tee_time_get_sys_time(&t); 196 if (res != TEE_SUCCESS) 197 return res; 198 199 if (TEE_TIME_LT(t, *time)) { 200 TEE_TIME_SUB(*time, t, offs); 201 return tee_time_ta_set_offs(uuid, &offs, true); 202 } else { 203 TEE_TIME_SUB(t, *time, offs); 204 return tee_time_ta_set_offs(uuid, &offs, false); 205 } 206 } 207