免责声明:我花了4到5个小时的时间来寻找答案,在弄清楚之后,我决定把它发到这里给在同一个地方的人。
OP-TEE是一个很好的开发TAs和CA的环境,但是,没有一种简单的方法可以获取格式正确的日期时间。也没有struct tm。因此,这让我想知道如何在OP TAs中获得日期时间格式?
我花了很长时间试图利用已经支持的mbedTLS库,对于一个新来的人来说,这些库似乎确实支持获取日期时间格式。毕竟,他们确实有gmtime,它应该返回这个值。
然而,不幸的是,gmtime和相关功能还没有在ARMv8平台上实现.这可真倒霉。
那么,你是如何在接受采访的助教中获得UTC时间的呢?
发布于 2021-07-27 11:30:53
所有针对ARMv8的OP开发都是使用C完成的,但是它缺乏对libc的主要支持。实际上,它有非常少的库(例如string.h.h),这些库是从原来的libc相应库中筛选出来的。
这样,OP中提供的<time.h>只包含一个time_t的typedef,仅此而已。
这个问题可以分为两部分:
自1970年1月1日00:00:00:00以来,你如何获得新时代?
这是一个有趣的问题,而直接的解决方案是简单地这样做:
TEE_Time tt;
TEE_GetREETime(&tt); 对于许多不想依赖REE(,AKA易受攻击环境)计算的人来说,这个解决方案可能并不令人满意。对于安全敏感操作来说,这可能是个问题,因为需要时间才能合法,而且REE没有空间对其进行修改以执行特定的攻击。
在上述情况下,您将必须从硬件时钟获得的时代,这将取决于您正在开发的TA硬件板。您甚至可以从位置设备中检索它,这些设备还可以在NMEA语句中返回UTC时间。虽然它可能不是100%的精确到第二,它可能只是足够。如果您需要非常高的精度,您将需要从硬件设备安全地获得它。
不管是哪种方式,你都得想办法自己创造新的时代。这个答案集中在第二部分:获取日期时间。
gmtime。它没有实现。而且您需要一个极简的实现来保持简单。幸运的是,我找到了this answer。它链接到newlib库,这些库是为免费的BSD开发的,这是嵌入式系统的理想选择。因此,它在这里是有用的!
我从它们的实现中将它们组合在一起,您可以在这里使用它:
gmtime_r.h:
#include <inttypes.h>
#define SECSPERMIN 60L
#define MINSPERHOUR 60L
#define HOURSPERDAY 24L
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
#define DAYSPERWEEK 7
#define MONSPERYEAR 12
#define YEAR_BASE 1900
#define EPOCH_YEAR 1970
#define EPOCH_WDAY 4
#define EPOCH_YEARS_SINCE_LEAP 2
#define EPOCH_YEARS_SINCE_CENTURY 70
#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
typedef int64_t time_t;
struct tm
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
struct tm* gmtime_r (time_t tim_p, struct tm* res);gmtime_r.c:
#include "gmtime_r.h"
#define EPOCH_ADJUSTMENT_DAYS 719468L
/* year to which the adjustment was made */
#define ADJUSTED_EPOCH_YEAR 0
/* 1st March of year 0 is Wednesday */
#define ADJUSTED_EPOCH_WDAY 3
/* there are 97 leap years in 400-year periods. ((400 - 97) * 365 + 97 * 366) */
#define DAYS_PER_ERA 146097L
/* there are 24 leap years in 100-year periods. ((100 - 24) * 365 + 24 * 366) */
#define DAYS_PER_CENTURY 36524L
/* there is one leap year every 4 years */
#define DAYS_PER_4_YEARS (3 * 365 + 366)
/* number of days in a non-leap year */
#define DAYS_PER_YEAR 365
/* number of days in January */
#define DAYS_IN_JANUARY 31
/* number of days in non-leap February */
#define DAYS_IN_FEBRUARY 28
/* number of years per era */
#define YEARS_PER_ERA 400
struct tm* gmtime_r (time_t tim_p, struct tm* res)
{
time_t days, rem;
const time_t lcltime = tim_p;
int era, weekday, year;
unsigned erayear, yearday, month, day;
unsigned long eraday;
days = lcltime / SECSPERDAY + EPOCH_ADJUSTMENT_DAYS;
rem = lcltime % SECSPERDAY;
if (rem < 0)
{
rem += SECSPERDAY;
--days;
}
/* compute hour, min, and sec */
res->tm_hour = (int) (rem / SECSPERHOUR);
rem %= SECSPERHOUR;
res->tm_min = (int) (rem / SECSPERMIN);
res->tm_sec = (int) (rem % SECSPERMIN);
/* compute day of week */
if ((weekday = ((ADJUSTED_EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
weekday += DAYSPERWEEK;
res->tm_wday = weekday;
/* compute year, month, day & day of year */
/* for description of this algorithm see
* http://howardhinnant.github.io/date_algorithms.html#civil_from_days */
era = (days >= 0 ? days : days - (DAYS_PER_ERA - 1)) / DAYS_PER_ERA;
eraday = days - era * DAYS_PER_ERA; /* [0, 146096] */
erayear = (eraday - eraday / (DAYS_PER_4_YEARS - 1) + eraday / DAYS_PER_CENTURY -
eraday / (DAYS_PER_ERA - 1)) / 365; /* [0, 399] */
yearday = eraday - (DAYS_PER_YEAR * erayear + erayear / 4 - erayear / 100); /* [0, 365] */
month = (5 * yearday + 2) / 153; /* [0, 11] */
day = yearday - (153 * month + 2) / 5 + 1; /* [1, 31] */
month += month < 10 ? 2 : -10;
year = ADJUSTED_EPOCH_YEAR + erayear + era * YEARS_PER_ERA + (month <= 1);
res->tm_yday = yearday >= DAYS_PER_YEAR - DAYS_IN_JANUARY - DAYS_IN_FEBRUARY ?
yearday - (DAYS_PER_YEAR - DAYS_IN_JANUARY - DAYS_IN_FEBRUARY) :
yearday + DAYS_IN_JANUARY + DAYS_IN_FEBRUARY + isleap(erayear);
res->tm_year = year - YEAR_BASE;
res->tm_mon = month;
res->tm_mday = day;
res->tm_isdst = 0;
return (res);
}您可以将这两个文件都放在TA文件夹中,并确保将gmtime.c添加到sub.mk的源列表中。最后,在TA本身,您可以使用它:
TEE_Time tt;
TEE_GetREETime(&tt);
struct tm *lt, temp;
lt = gmtime((time_t)tt.seconds, &temp);
DMSG("%4d-%2d-%2d %2d:%2d:%2d", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); 这将以适当的格式打印时间和日期。
目前,我还没有移植strftime的实现,但很快我也会这样做,它将自动格式化tm结构,并将1900添加到tm_year,将1添加到tm_mon。
同时,我希望这能找到需要帮助的人。
发布于 2022-09-20 21:41:16
计时器安全性
要检索自1970-01-01年以来的当前时间(毫秒),请调用TEE_GetSystemTime。安全级别取决于特定系统上可用的安全时钟。绝对最小保证是,在运行受信任的应用程序时,此值不能减少,但REE可能能够控制该值的运行速度。在重新启动的过程中没有保证。
OP T附带了一个基于implementation of TEE_GetSystemTime的CNTPCT。这可以配置为任何TrustZone芯片上的armv8安全世界所独有的,但我不知道是否所有的芯片制造商都这样做。
当计时器是安全的,这是一个保证短期延迟将得到尊重。例如,如果您想阻止至少1秒的身份验证尝试,这就足够了。
许多平台无法安全地保存这个日期,因为这需要一个总是开着电源的时钟,而这个时钟需要一个没有耗尽的电池。通常,不受信任的世界可以安排在系统重置后将时间设置为任意值。因此,如果您需要具有足够精确性的当前日期来验证证书是否过期,那就不够好,您需要做一些事情,比如建立到安全时间服务器的连接。这是一个引导问题,因为您无法验证时间服务器的证书是否已过期。
打破时间
OP-TEE提供了一个瘦C库,不包括任何类似gmtime的内容。如果要从时代时间计算日期和时间,则需要provide your own implementation。
Mbed是gmtime (更确切地说是gmtime_r)的消费者,而不是提供者。它使用这个函数来检查证书的有效性。
https://stackoverflow.com/questions/68544061
复制相似问题