TEE_Result tee_svc_wait(uint32_t timeout) { TEE_Result res = TEE_SUCCESS; uint32_t mytime = 0; struct tee_ta_session *s; TEE_Time base_time; TEE_Time current_time; res = tee_ta_get_current_session(&s); if (res != TEE_SUCCESS) return res; res = tee_time_get_sys_time(&base_time); if (res != TEE_SUCCESS) return res; while (true) { res = tee_time_get_sys_time(¤t_time); if (res != TEE_SUCCESS) return res; if (session_is_cancelled(s, ¤t_time)) return TEE_ERROR_CANCEL; mytime = (current_time.seconds - base_time.seconds) * 1000 + (int)current_time.millis - (int)base_time.millis; if (mytime >= timeout) return TEE_SUCCESS; tee_wait_specific(timeout - mytime); } return res; }
__weak void plat_rng_init(void) { TEE_Result res = TEE_SUCCESS; TEE_Time t; #ifndef CFG_SECURE_TIME_SOURCE_REE /* * This isn't much of a seed. Ideally we should either get a seed from * a hardware RNG or from a previously saved seed. * * Seeding with hardware RNG is currently up to the platform to * override this function. * * Seeding with a saved seed will require cooperation from normal * world, this is still TODO. */ res = tee_time_get_sys_time(&t); #else EMSG("Warning: seeding RNG with zeroes"); memset(&t, 0, sizeof(t)); #endif if (!res) res = crypto_rng_init(&t, sizeof(t)); if (res) { EMSG("Failed to initialize RNG: %#" PRIx32, res); panic(); } }
TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time) { TEE_Result res; const TEE_Time *offs; bool positive; TEE_Time t; TEE_Time t2; res = tee_time_ta_get_offs(uuid, &offs, &positive); if (res != TEE_SUCCESS) return res; res = tee_time_get_sys_time(&t); if (res != TEE_SUCCESS) return res; if (positive) { TEE_TIME_ADD(t, *offs, t2); /* Detect wrapping, the wrapped time should be returned. */ if (TEE_TIME_LT(t2, t)) res = TEE_ERROR_OVERFLOW; } else { TEE_TIME_SUB(t, *offs, t2); /* Detect wrapping, the wrapped time should be returned. */ if (TEE_TIME_LE(t, t2)) res = TEE_ERROR_OVERFLOW; } *time = t2; return res; }
TEE_Result tee_svc_get_time(enum utee_time_category cat, TEE_Time *mytime) { TEE_Result res, res2; struct tee_ta_session *s = NULL; TEE_Time t; res = tee_ta_get_current_session(&s); if (res != TEE_SUCCESS) return res; switch (cat) { case UTEE_TIME_CAT_SYSTEM: res = tee_time_get_sys_time(&t); break; case UTEE_TIME_CAT_TA_PERSISTENT: res = tee_time_get_ta_time((const void *)&s->ctx->head->uuid, &t); break; case UTEE_TIME_CAT_REE: res = tee_time_get_ree_time(&t); break; default: res = TEE_ERROR_BAD_PARAMETERS; break; } if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) { res2 = tee_svc_copy_to_user(s, mytime, &t, sizeof(t)); if (res2 != TEE_SUCCESS) res = res2; } return res; }
static bool session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time) { TEE_Time current_time; if (s->cancel_mask) return false; if (s->cancel) return true; if (s->cancel_time.seconds == UINT32_MAX) return false; if (curr_time != NULL) current_time = *curr_time; else if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) return false; if (current_time.seconds > s->cancel_time.seconds || (current_time.seconds == s->cancel_time.seconds && current_time.millis >= s->cancel_time.millis)) { return true; } return false; }
/* * Override this in your platform code to feed the PRNG platform-specific * jitter entropy. This implementation does not efficiently deliver entropy * and is here for backwards-compatibility. */ __weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum) { TEE_Time current; #ifdef CFG_SECURE_TIME_SOURCE_REE if (CRYPTO_RNG_SRC_IS_QUICK(sid)) return; /* Can't read REE time here */ #endif if (tee_time_get_sys_time(¤t) == TEE_SUCCESS) crypto_rng_add_event(sid, pnum, ¤t, sizeof(current)); }
TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time) { TEE_Result res; TEE_Time offs; TEE_Time t; /* Check that time is normalized. */ if (time->millis >= TEE_TIME_MILLIS_BASE) return TEE_ERROR_BAD_PARAMETERS; res = tee_time_get_sys_time(&t); if (res != TEE_SUCCESS) return res; if (TEE_TIME_LT(t, *time)) { TEE_TIME_SUB(*time, t, offs); return tee_time_ta_set_offs(uuid, &offs, true); } else { TEE_TIME_SUB(t, *time, offs); return tee_time_ta_set_offs(uuid, &offs, false); } }