• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #include <securec.h>
13 #include <sys_timer.h>
14 #include <tee_log.h>
15 #include <tee_trusted_storage_api.h>
16 #include <tee_time_adapt.h>
17 #include <tee_misc.h>
18 
19 #define PERSISTENT_TIME_BASE_FILE      "sec_storage/persistent_time"
20 #define POSITIVE_DIR                   1
21 #define NEGATIVE_DIR                   (-1)
22 struct time_offset {
23     int16_t dir;
24     uint32_t offset;
25     uint32_t base_sys_time;
26 };
27 
TEE_GetSystemTime(TEE_Time * time)28 void TEE_GetSystemTime(TEE_Time *time)
29 {
30 #ifdef CONFIG_TEE_TIME_STUB
31     (void)time;
32 #else
33     struct timer_ops_t *time_ops = NULL;
34     uint64_t time_stamp;
35 
36     if (time == NULL)
37         return;
38 
39     time_ops = get_time_ops();
40     if (time_ops == NULL)
41         return;
42 
43     time_stamp = time_ops->read_time_stamp();
44     time->seconds = UPPER_32_BITS(time_stamp);
45     time->millis  = LOWER_32_BITS(time_stamp) / NS_PER_MSEC;
46 #endif
47 }
48 
TEE_GetREETime(TEE_Time * time)49 void TEE_GetREETime(TEE_Time *time)
50 {
51 #ifdef CONFIG_TEE_TIME_STUB
52     (void)time;
53 #else
54     int32_t ret;
55     if (time == NULL) {
56         tloge("invalid param\n");
57         return;
58     }
59 
60     ret = get_time_of_data(&time->seconds, &time->millis, NULL, 0);
61     if (ret != TMR_OK) {
62         tloge("get time of data failed\n");
63         return;
64     }
65 #endif
66 }
67 
TEE_Wait(uint32_t mill_second)68 TEE_Result TEE_Wait(uint32_t mill_second)
69 {
70 #ifdef CONFIG_TEE_TIME_STUB
71     (void)mill_second;
72     return TEE_ERROR_NOT_SUPPORTED;
73 #else
74     struct timer_ops_t *time_ops = NULL;
75     time_ops = get_time_ops();
76     if (time_ops == NULL)
77         return TMR_ERR;
78 
79     return time_ops->sleep(mill_second);
80 #endif
81 }
82 
83 #ifndef CONFIG_TEE_TIME_STUB
get_rtc_time(void)84 static uint32_t get_rtc_time(void)
85 {
86     struct timer_ops_t *time_ops = NULL;
87     time_ops = get_time_ops();
88     if (time_ops == NULL)
89         return TIMER_INV_VALUE;
90 
91     return time_ops->get_rtc_seconds();
92 }
93 #endif
94 
TEE_SetTAPersistentTime(TEE_Time * time)95 TEE_Result TEE_SetTAPersistentTime(TEE_Time *time)
96 {
97 #ifdef CONFIG_TEE_TIME_STUB
98     (void)time;
99     return TEE_ERROR_NOT_SUPPORTED;
100 #else
101     struct time_offset offset_val = { 0 };
102     uint32_t seconds;
103     TEE_Result ret;
104     TEE_ObjectHandle object = NULL;
105 
106     if (time == NULL) {
107         tloge("invalid param\n");
108         return TEE_ERROR_BAD_PARAMETERS;
109     }
110 
111     /*
112      * Get sys time from RTC:always increase even if power off.
113      * Use TEE_SetTAPersistentTime and TEE_GetTAPersistentTime
114      * to get the true time that has past. A typical usecase in DRM.
115      */
116     seconds = get_rtc_time();
117     if (seconds == TIMER_INV_VALUE) {
118         tloge("Failed to get rtc time\n");
119         return TEE_ERROR_TIME_NEEDS_RESET;
120     }
121 
122     offset_val.base_sys_time = seconds;
123     if (time->seconds >= seconds) {
124         offset_val.dir    = POSITIVE_DIR;
125         offset_val.offset = time->seconds - seconds;
126     } else {
127         offset_val.dir    = NEGATIVE_DIR;
128         offset_val.offset = seconds - time->seconds;
129     }
130 
131     ret = TEE_CreatePersistentObject(TEE_OBJECT_STORAGE_PRIVATE, PERSISTENT_TIME_BASE_FILE,
132                                      strlen(PERSISTENT_TIME_BASE_FILE), TEE_DATA_FLAG_ACCESS_WRITE, TEE_HANDLE_NULL,
133                                      &offset_val, sizeof(offset_val), &object);
134     if (ret != TEE_SUCCESS) {
135         tloge("set TA persistent time error: ret is 0x%x\n", ret);
136         return ret;
137     }
138 
139     TEE_CloseObject(object);
140     return ret;
141 #endif
142 }
143 
144 #ifndef CONFIG_TEE_TIME_STUB
persistent_time_check(TEE_Time * time,const struct time_offset * offset_val)145 static TEE_Result persistent_time_check(TEE_Time *time, const struct time_offset *offset_val)
146 {
147     uint32_t seconds;
148     seconds = get_rtc_time();
149     if (seconds == TIMER_INV_VALUE) {
150         tloge("failed to get rtc time\n");
151         return TEE_ERROR_TIME_NEEDS_RESET;
152     }
153 
154     if (seconds < offset_val->base_sys_time) {
155         tloge("time rollback\n");
156         return TEE_ERROR_TIME_NEEDS_RESET;
157     }
158 
159     /*
160      * millis is always 0, because rtc accuracy is 1s.
161      * Depends on GP spec, even if time overflow we should return the actually time.
162      */
163     time->millis = 0;
164     if (offset_val->dir == NEGATIVE_DIR) {
165         time->seconds = seconds - offset_val->offset;
166         if (time->seconds > seconds) {
167             tloge("persistent time overflow\n");
168             return TEE_ERROR_OVERFLOW;
169         }
170     } else {
171         time->seconds = seconds + offset_val->offset;
172         if (time->seconds < seconds) {
173             tloge("persistent time overflow\n");
174             return TEE_ERROR_OVERFLOW;
175         }
176     }
177 
178     return TEE_SUCCESS;
179 }
180 #endif
181 
TEE_GetTAPersistentTime(TEE_Time * time)182 TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
183 {
184 #ifdef CONFIG_TEE_TIME_STUB
185     (void)time;
186     return TEE_ERROR_NOT_SUPPORTED;
187 #else
188     struct time_offset offset_val = { 0 };
189     TEE_ObjectHandle object = NULL;
190     uint32_t count = 0;
191     TEE_Result ret;
192 
193     if (time == NULL) {
194         tloge("invalid param\n");
195         return TEE_ERROR_BAD_PARAMETERS;
196     }
197 
198     /*
199      *  For an error different
200      *  from TEE_ERROR_OVERFLOW, this placeholder is filled with zeros.
201      */
202     time->seconds = 0;
203     time->millis  = 0;
204     ret = TEE_OpenPersistentObject(TEE_OBJECT_STORAGE_PRIVATE, PERSISTENT_TIME_BASE_FILE,
205                                    strlen(PERSISTENT_TIME_BASE_FILE), TEE_DATA_FLAG_ACCESS_READ, &object);
206     if (ret != TEE_SUCCESS) {
207         tloge("failed to open persistent object\n");
208         return TEE_ERROR_TIME_NOT_SET;
209     }
210 
211     ret = TEE_ReadObjectData(object, &offset_val, sizeof(offset_val), &count);
212     TEE_CloseObject(object);
213     if ((ret != TEE_SUCCESS) || (count != sizeof(offset_val))) {
214         tloge("read failed\n");
215         return TEE_ERROR_TIME_NOT_SET;
216     }
217 
218     ret = persistent_time_check(time, &offset_val);
219     if (ret != TEE_SUCCESS) {
220         tloge("failed to check\n");
221         return ret;
222     }
223 
224     return TEE_SUCCESS;
225 #endif
226 }
227