diff --git a/src/rescue.c b/src/rescue.c index 1018d1b..603c781 100644 --- a/src/rescue.c +++ b/src/rescue.c @@ -22,13 +22,23 @@ #ifdef PICO_PLATFORM #include "pico/bootrom.h" #include "hardware/watchdog.h" +#include "pico/aon_timer.h" +#else +#include +#include #endif #include "mbedtls/ecdsa.h" #include "mbedtls/sha256.h" #include "random.h" +#ifdef PICO_PLATFORM +extern char __flash_binary_start; +extern char __flash_binary_end; +#endif + int rescue_process_apdu(); int rescue_unload(); +bool set_rtc = false; const uint8_t rescue_aid[] = { 8, @@ -172,7 +182,9 @@ int cmd_write() { return SW_WRONG_LENGTH(); } - if (P1(apdu) == 0x1) { // PHY + uint8_t p1 = P1(apdu), p2 = P2(apdu); + + if (p1 == 0x1) { // PHY #ifndef ENABLE_EMULATION int ret = phy_unserialize_data(apdu.data, (uint16_t)apdu.nc, &phy_data); if (ret == PICOKEY_OK) { @@ -182,6 +194,41 @@ int cmd_write() { } #endif } + else if (p1 == 0x2) { // SET TIME + time_t tv_sec = 0; + if (p2 != 0x1 && p2 != 0x2) { + return SW_INCORRECT_P1P2(); + } + if (p2 == 0x1) { + if (apdu.nc != 8) { + return SW_WRONG_LENGTH(); + } + struct tm tm; + tm.tm_year = get_uint16_t_be(apdu.data) - 1900; + tm.tm_mon = apdu.data[2]; + tm.tm_mday = apdu.data[3]; + tm.tm_wday = apdu.data[4]; + tm.tm_hour = apdu.data[5]; + tm.tm_min = apdu.data[6]; + tm.tm_sec = apdu.data[7]; + tv_sec = mktime(&tm); + } + else if (p2 == 0x2) { + if (apdu.nc != 4) { + return SW_WRONG_LENGTH(); + } + uint32_t t = (apdu.data[0] << 24) | (apdu.data[1] << 16) | (apdu.data[2] << 8) | apdu.data[3]; + tv_sec = (time_t)t; + } +#ifdef PICO_PLATFORM + struct timespec tv = {.tv_sec = tv_sec, .tv_nsec = 0}; + aon_timer_set_time(&tv); +#else + struct timeval tv = {.tv_sec = tv_sec, .tv_usec = 0}; + settimeofday(&tv, NULL); +#endif + set_rtc = true; + } led_3_blinks(); return SW_OK(); } @@ -191,7 +238,7 @@ int cmd_read() { return SW_WRONG_LENGTH(); } - uint8_t p1 = P1(apdu); + uint8_t p1 = P1(apdu), p2 = P2(apdu); if (p1 == 0x1) { // PHY #ifndef ENABLE_EMULATION uint16_t len = 0; @@ -210,6 +257,12 @@ int cmd_read() { res_APDU_size += put_uint32_t_be(total, res_APDU + res_APDU_size); res_APDU_size += put_uint32_t_be(nfiles, res_APDU + res_APDU_size); res_APDU_size += put_uint32_t_be(size, res_APDU + res_APDU_size); +#ifdef PICO_PLATFORM + uintptr_t start = (uintptr_t) &__flash_binary_start; + uintptr_t end = (uintptr_t) &__flash_binary_end; + uint32_t fw_size = (uint32_t)(end - start); + res_APDU_size += put_uint32_t_be(fw_size, res_APDU + res_APDU_size); +#endif } else if (p1 == 0x3) { // OTP SECURE BOOT STATUS res_APDU_size = 0; @@ -220,6 +273,35 @@ int cmd_read() { res_APDU[res_APDU_size++] = locked ? 0x1 : 0x0; res_APDU[res_APDU_size++] = bootkey; } + else if (p1 == 0x4) { // GET TIME + if (p2 != 0x1 && p2 != 0x2) { + return SW_INCORRECT_P1P2(); + } + if (!set_rtc) { + return SW_CONDITIONS_NOT_SATISFIED(); + } + res_APDU_size = 0; +#ifdef PICO_PLATFORM + struct timespec tv; + aon_timer_get_time(&tv); +#else + struct timeval tv; + gettimeofday(&tv, NULL); +#endif + if (p2 == 0x1) { + struct tm *tm = localtime(&tv.tv_sec); + res_APDU_size += put_uint16_t_be(tm->tm_year + 1900, res_APDU); + res_APDU[res_APDU_size++] = tm->tm_mon; + res_APDU[res_APDU_size++] = tm->tm_mday; + res_APDU[res_APDU_size++] = tm->tm_wday; + res_APDU[res_APDU_size++] = tm->tm_hour; + res_APDU[res_APDU_size++] = tm->tm_min; + res_APDU[res_APDU_size++] = tm->tm_sec; + } + else if (p2 == 0x2) { + res_APDU_size += put_uint32_t_be((uint32_t)tv.tv_sec, res_APDU); + } + } return SW_OK(); }