Skip to content

Commit e6c7f57

Browse files
committed
Merge branch 'pr/101' into unleashed
2 parents b95a8f6 + 93b1b1a commit e6c7f57

File tree

15 files changed

+797
-2
lines changed

15 files changed

+797
-2
lines changed

applications/meta/application.fam

+12-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ App(
2525
"bad_usb",
2626
"u2f",
2727
"elf_loader",
28+
"totp",
2829
],
2930
)
3031

@@ -38,6 +39,11 @@ App(
3839
"INTAPP_MouseJacker",
3940
"INTAPP_NRFSniff",
4041
"INTAPP_TouchTunes",
42+
43+
"APPS_WAVPlayer",
44+
"APPS_SpectrumAnalyzer","APPS_BluetoothRemote","APPS_DolphinRestorer",
45+
"APPS_DolphinBackup","APPS_MusicPlayer",
46+
"APPS_SentrySafe","APPS_BarcodeGenerator","APPS_MouseJiggler",
4147
],
4248
)
4349

@@ -50,6 +56,9 @@ App(
5056
"INTAPP_GameOfLife",
5157
"INTAPP_Raycast",
5258
"INTAPP_Tetris",
59+
"GAME_2048","GAME_Arkanoid","GAME_Dice",
60+
"GAME_Snake","GAME_TicTacToe",,"GAME_MandelbrotSet"
61+
"GAME_VideoPoker","GAME_FlappyBird",
5362
],
5463
)
5564

@@ -81,12 +90,13 @@ App(
8190
"INTAPP_Chip8","INTAPP_Chess",
8291
"Clock",
8392
"UniRFRemix",
93+
"totp",
8494
"APPS_WAVPlayer",
8595
"APPS_SpectrumAnalyzer","APPS_BluetoothRemote","APPS_DolphinRestorer",
86-
"APPS_DolphinBackup","GAME_MandelbrotSet","APPS_MusicPlayer",
96+
"APPS_DolphinBackup","APPS_MusicPlayer",
8797
"APPS_SentrySafe","APPS_BarcodeGenerator","APPS_MouseJiggler",
8898
"GAME_2048","GAME_Arkanoid","GAME_Dice",
89-
"GAME_Snake","GAME_TicTacToe",
99+
"GAME_Snake","GAME_TicTacToe",,"GAME_MandelbrotSet"
90100
"GAME_VideoPoker","GAME_FlappyBird",
91101
],
92102
)

applications/totp/application.fam

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
App(
2+
appid="totp",
3+
name="TOTP",
4+
apptype=FlipperAppType.APP,
5+
entry_point="totp_app",
6+
cdefines=["APP_TOTP"],
7+
requires=[
8+
"gui",
9+
"dialogs",
10+
],
11+
stack_size=2 * 1024,
12+
icon="A_U2F_14",
13+
order=80,
14+
)

applications/totp/totp_app.c

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#include <furi.h>
2+
#include <furi_hal.h>
3+
4+
#include <gui/gui.h>
5+
#include <input/input.h>
6+
7+
#include <notification/notification_messages.h>
8+
9+
#include <totp.h>
10+
#include "totp_app.h"
11+
12+
#include <base32.h>
13+
#include <time.h>
14+
15+
#include <toolbox/path.h>
16+
#include <flipper_format/flipper_format.h>
17+
18+
static const char* totp_file_header = "Flipper TOTP storage";
19+
static const uint32_t totp_file_version = 1;
20+
21+
typedef enum {
22+
TotpEventTypeTick,
23+
TotpEventTypeInput,
24+
} TotpEventType;
25+
26+
typedef struct {
27+
TotpEventType type;
28+
InputEvent input;
29+
uint32_t code;
30+
} TotpEvent;
31+
32+
uint8_t keyId = 0;
33+
uint8_t keys = 3;
34+
uint8_t* base32key[] = {
35+
(unsigned char*)"JBSWY3DPEHPK3PXP",
36+
(unsigned char*)"AMOGUSYOBABOBAAA",
37+
(unsigned char*)"AMOGUSAAAAAAAAAA"};
38+
const char* keyNames[] = {"Test Key 1", "Test Key 2", "Amogus key"};
39+
40+
int keyLengths[] = {10, 10, 10};
41+
42+
static void totp_app_draw_callback(Canvas* canvas, void* ctx) {
43+
osMessageQueueId_t event_queue = ctx;
44+
TotpEvent event;
45+
osMessageQueueGet(event_queue, &event, NULL, osWaitForever);
46+
47+
uint8_t hmacKey[20];
48+
49+
int timezone = -3;
50+
51+
canvas_clear(canvas);
52+
canvas_set_font(canvas, FontPrimary);
53+
canvas_draw_str(canvas, 2, 10, "TOTP");
54+
canvas_draw_str(canvas, 2, 30, keyNames[keyId]);
55+
56+
//FURI_LOG_I("TOTP", "key is %s", base32key[keyId]);
57+
58+
base32_decode(base32key[keyId], hmacKey, keyLengths[keyId]);
59+
//FURI_LOG_I("TOTP", "len = %d", len);
60+
61+
//uint8_t hmacKey[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0xde, 0xad, 0xbe, 0xef}; // Secret key
62+
TOTP(hmacKey, keyLengths[keyId], 30); // Secret key, Secret key length, Timestep (30s)
63+
64+
FuriHalRtcDateTime datetime = {0};
65+
furi_hal_rtc_get_datetime(&datetime);
66+
67+
struct tm date = {0};
68+
date.tm_hour = datetime.hour + timezone;
69+
date.tm_min = datetime.minute;
70+
date.tm_sec = datetime.second;
71+
date.tm_mday = datetime.day;
72+
date.tm_mon = datetime.month - 1;
73+
date.tm_year = datetime.year - 1900;
74+
// god i hate these 5 lines
75+
76+
uint32_t newCode = getCodeFromTimestamp(mktime(&date));
77+
//FURI_LOG_I("TOTP", "%06ld", newCode);
78+
char code_string[100] = "";
79+
sprintf(code_string, "%06ld", newCode);
80+
canvas_draw_str(canvas, 2, 20, code_string);
81+
sprintf(code_string, "%d seconds left", 29 - date.tm_sec % 30);
82+
canvas_draw_str(canvas, 2, 40, code_string);
83+
sprintf(
84+
code_string,
85+
"%02d:%02d:%02d %02d-%02d-%04d",
86+
datetime.hour + timezone,
87+
datetime.minute,
88+
datetime.second,
89+
datetime.day,
90+
datetime.month,
91+
datetime.year);
92+
canvas_draw_str(canvas, 2, 50, code_string);
93+
canvas_draw_box(canvas, 0, 52, (29 - (date.tm_sec % 30)) * 4.414, 10);
94+
}
95+
96+
static void totp_app_input_callback(InputEvent* input_event, void* ctx) {
97+
furi_assert(ctx);
98+
osMessageQueueId_t event_queue = ctx;
99+
100+
TotpEvent event = {.type = TotpEventTypeInput, .input = *input_event};
101+
osMessageQueuePut(event_queue, &event, 0, osWaitForever);
102+
}
103+
104+
void totp_app_update(void* ctx) {
105+
furi_assert(ctx);
106+
osMessageQueueId_t event_queue = ctx;
107+
TotpEvent event = {.type = TotpEventTypeTick};
108+
osMessageQueuePut(event_queue, &event, 0, 0);
109+
}
110+
111+
int32_t totp_app(void* p) {
112+
UNUSED(p);
113+
bool saved = false;
114+
Storage* storage = furi_record_open("storage");
115+
FlipperFormat* file = flipper_format_file_alloc(storage);
116+
string_t temp_str;
117+
char key_name[50] = "";
118+
string_init(temp_str);
119+
120+
do {
121+
// Create nfc directory if necessary
122+
if(!storage_simply_mkdir(storage, TOTP_APP_FOLDER)) break;
123+
// Open file
124+
string_printf(temp_str, "%s/%s%s", "/ext/totp", "keys", ".totp");
125+
// Open file
126+
if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break;
127+
// Write header
128+
if(!flipper_format_write_header_cstr(file, totp_file_header, totp_file_version)) break;
129+
// Write nfc device type
130+
//nfc_device_prepare_format_string(dev, temp_str);
131+
132+
for(int key = 0; key < keys; key++) {
133+
string_printf(temp_str, "%s", base32key[key]);
134+
sprintf(key_name, "%s", keyNames[key]);
135+
136+
if(!flipper_format_write_string(file, key_name, temp_str)) break;
137+
}
138+
//if(!flipper_format_write_hex(file, "Totp key 1", base32key[0], sizeof(base32key[0])))
139+
// break;
140+
// Write UID, ATQA, SAK
141+
//if(!flipper_format_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats"))
142+
// break;
143+
//if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
144+
//if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break;
145+
//if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break;
146+
// Save more data if necessary
147+
//if(dev->format == NfcDeviceSaveFormatMifareUl) {
148+
// if(!nfc_device_save_mifare_ul_data(file, dev)) break;
149+
//} else if(dev->format == NfcDeviceSaveFormatBankCard) {
150+
// if(!nfc_device_save_bank_card_data(file, dev)) break;
151+
//}
152+
saved = true;
153+
} while(0);
154+
if(saved) {
155+
flipper_format_free(file);
156+
furi_record_close("storage");
157+
} else {
158+
flipper_format_free(file);
159+
furi_record_close("storage");
160+
}
161+
162+
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(TotpEvent), NULL);
163+
// Configure view port
164+
ViewPort* view_port = view_port_alloc();
165+
view_port_input_callback_set(view_port, totp_app_input_callback, event_queue);
166+
view_port_draw_callback_set(view_port, totp_app_draw_callback, NULL);
167+
168+
// Register view port in GUI
169+
Gui* gui = furi_record_open("gui");
170+
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
171+
view_port_update(view_port);
172+
173+
osTimerId_t timer = osTimerNew(totp_app_update, osTimerPeriodic, event_queue, NULL);
174+
osTimerStart(timer, osKernelGetTickFreq());
175+
176+
TotpEvent event;
177+
178+
while(1) {
179+
view_port_update(view_port);
180+
furi_check(osMessageQueueGet(event_queue, &event, NULL, osWaitForever) == osOK);
181+
182+
if((event.input.type == InputTypeShort) && (event.input.key == InputKeyBack)) {
183+
break;
184+
} else if((event.input.type == InputTypeShort) && (event.input.key == InputKeyRight)) {
185+
if(keyId < keys - 1) {
186+
keyId++;
187+
} else {
188+
keyId = 0;
189+
}
190+
} else if((event.input.type == InputTypeShort) && (event.input.key == InputKeyLeft)) {
191+
if(keyId > 0) {
192+
keyId--;
193+
} else {
194+
keyId = keys - 1;
195+
}
196+
}
197+
}
198+
199+
osTimerDelete(timer);
200+
201+
gui_remove_view_port(gui, view_port);
202+
view_port_free(view_port);
203+
osMessageQueueDelete(event_queue);
204+
205+
furi_record_close("gui");
206+
return 0;
207+
}

applications/totp/totp_app.h

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
#define TOTP_APP_FOLDER "/any/totp"
4+
#define TOTP_APP_EXTENSION ".totp"

assets/compiled/totp.pb.c

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* Automatically generated nanopb constant definitions */
2+
/* Generated by nanopb-0.4.5 */
3+
4+
#include "totp.pb.h"
5+
#if PB_PROTO_HEADER_VERSION != 40
6+
#error Regenerate this file with the current version of nanopb generator.
7+
#endif
8+
9+
PB_BIND(PB_TOTP_TotpKey, PB_TOTP_TotpKey, AUTO)
10+
11+
12+
PB_BIND(PB_TOTP_getKeyIdsResponse, PB_TOTP_getKeyIdsResponse, AUTO)
13+
14+
15+

assets/compiled/totp.pb.h

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* Automatically generated nanopb header */
2+
/* Generated by nanopb-0.4.5 */
3+
4+
#ifndef PB_PB_TOTP_TOTP_PB_H_INCLUDED
5+
#define PB_PB_TOTP_TOTP_PB_H_INCLUDED
6+
#include <pb.h>
7+
8+
#if PB_PROTO_HEADER_VERSION != 40
9+
#error Regenerate this file with the current version of nanopb generator.
10+
#endif
11+
12+
/* Struct definitions */
13+
typedef struct _PB_TOTP_TotpKey {
14+
char *key;
15+
uint32_t keyId;
16+
} PB_TOTP_TotpKey;
17+
18+
typedef struct _PB_TOTP_getKeyIdsResponse {
19+
uint32_t keysAmount;
20+
uint32_t *keyIds;
21+
} PB_TOTP_getKeyIdsResponse;
22+
23+
24+
#ifdef __cplusplus
25+
extern "C" {
26+
#endif
27+
28+
/* Initializer values for message structs */
29+
#define PB_TOTP_TotpKey_init_default {NULL, 0}
30+
#define PB_TOTP_getKeyIdsResponse_init_default {0, NULL}
31+
#define PB_TOTP_TotpKey_init_zero {NULL, 0}
32+
#define PB_TOTP_getKeyIdsResponse_init_zero {0, NULL}
33+
34+
/* Field tags (for use in manual encoding/decoding) */
35+
#define PB_TOTP_TotpKey_key_tag 1
36+
#define PB_TOTP_TotpKey_keyId_tag 2
37+
#define PB_TOTP_getKeyIdsResponse_keysAmount_tag 1
38+
#define PB_TOTP_getKeyIdsResponse_keyIds_tag 2
39+
40+
/* Struct field encoding specification for nanopb */
41+
#define PB_TOTP_TotpKey_FIELDLIST(X, a) \
42+
X(a, POINTER, SINGULAR, STRING, key, 1) \
43+
X(a, STATIC, SINGULAR, UINT32, keyId, 2)
44+
#define PB_TOTP_TotpKey_CALLBACK NULL
45+
#define PB_TOTP_TotpKey_DEFAULT NULL
46+
47+
#define PB_TOTP_getKeyIdsResponse_FIELDLIST(X, a) \
48+
X(a, STATIC, SINGULAR, UINT32, keysAmount, 1) \
49+
X(a, POINTER, SINGULAR, UINT32, keyIds, 2)
50+
#define PB_TOTP_getKeyIdsResponse_CALLBACK NULL
51+
#define PB_TOTP_getKeyIdsResponse_DEFAULT NULL
52+
53+
extern const pb_msgdesc_t PB_TOTP_TotpKey_msg;
54+
extern const pb_msgdesc_t PB_TOTP_getKeyIdsResponse_msg;
55+
56+
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
57+
#define PB_TOTP_TotpKey_fields &PB_TOTP_TotpKey_msg
58+
#define PB_TOTP_getKeyIdsResponse_fields &PB_TOTP_getKeyIdsResponse_msg
59+
60+
/* Maximum encoded size of messages (where known) */
61+
/* PB_TOTP_TotpKey_size depends on runtime parameters */
62+
/* PB_TOTP_getKeyIdsResponse_size depends on runtime parameters */
63+
64+
#ifdef __cplusplus
65+
} /* extern "C" */
66+
#endif
67+
68+
#endif

lib/TOTP-MCU/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Weravech
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)