Merge branch 'dev' of https://github.com/flipperdevices/flipperzero-firmware into dev
@@ -1 +1 @@
|
||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/xtreme -e lib/nanopb -e */arm-none-eabi/*
|
||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/microtar -e lib/mlib -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/*
|
||||
|
||||
11
SConstruct
@@ -288,13 +288,17 @@ distenv.PhonyTarget(
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files
|
||||
# Here we add additional Python files residing in repo root
|
||||
firmware_env.Append(
|
||||
PY_LINT_SOURCES=[
|
||||
# Py code folders
|
||||
"site_scons",
|
||||
"scripts",
|
||||
"applications",
|
||||
"applications_user",
|
||||
"assets",
|
||||
"targets",
|
||||
# Extra files
|
||||
"SConstruct",
|
||||
"firmware.scons",
|
||||
@@ -304,7 +308,10 @@ firmware_env.Append(
|
||||
|
||||
|
||||
black_commandline = "@${PYTHON3} -m black ${PY_BLACK_ARGS} ${PY_LINT_SOURCES}"
|
||||
black_base_args = ["--include", '"\\.scons|\\.py|SConscript|SConstruct"']
|
||||
black_base_args = [
|
||||
"--include",
|
||||
'"(\\.scons|\\.py|SConscript|SConstruct|\\.fam)$"',
|
||||
]
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"lint_py",
|
||||
|
||||
@@ -13,12 +13,12 @@ struct ISO7816_Command_APDU {
|
||||
//body
|
||||
uint8_t Lc;
|
||||
uint8_t Le;
|
||||
} __attribute__((packed));
|
||||
} FURI_PACKED;
|
||||
|
||||
struct ISO7816_Response_APDU {
|
||||
uint8_t SW1;
|
||||
uint8_t SW2;
|
||||
} __attribute__((packed));
|
||||
} FURI_PACKED;
|
||||
|
||||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
||||
void iso7816_read_command_apdu(
|
||||
|
||||
@@ -4,7 +4,7 @@ App(
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="display_test_app",
|
||||
requires=["gui"],
|
||||
fap_libs=["misc"],
|
||||
fap_libs=["u8g2"],
|
||||
stack_size=1 * 1024,
|
||||
order=120,
|
||||
fap_category="Debug",
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
#include "flipper.pb.h"
|
||||
#include <core/check.h>
|
||||
#include <core/record.h>
|
||||
#include "pb_decode.h"
|
||||
#include <rpc/rpc.h>
|
||||
#include "rpc/rpc_i.h"
|
||||
#include "storage.pb.h"
|
||||
#include "storage/filesystem_api_defines.h"
|
||||
#include "storage/storage.h"
|
||||
#include <furi.h>
|
||||
#include "../minunit.h"
|
||||
#include <stdint.h>
|
||||
#include <pb.h>
|
||||
#include <pb_encode.h>
|
||||
#include <m-list.h>
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
#include <protobuf_version.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpc_i.h>
|
||||
#include <cli/cli.h>
|
||||
#include <storage/storage.h>
|
||||
#include <loader/loader.h>
|
||||
#include <storage/filesystem_api_defines.h>
|
||||
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
#include <m-list.h>
|
||||
#include "../minunit.h"
|
||||
|
||||
#include <protobuf_version.h>
|
||||
#include <pb.h>
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
#include <storage.pb.h>
|
||||
#include <flipper.pb.h>
|
||||
|
||||
LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
|
||||
#define M_OPL_MsgList_t() LIST_OPLIST(MsgList)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ App(
|
||||
entry_point="advanced_plugin1_ep",
|
||||
requires=["example_advanced_plugins"],
|
||||
sources=["plugin1.c"],
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
App(
|
||||
@@ -22,4 +23,5 @@ App(
|
||||
entry_point="advanced_plugin2_ep",
|
||||
requires=["example_advanced_plugins"],
|
||||
sources=["plugin2.c"],
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
@@ -23,7 +23,10 @@ int32_t example_advanced_plugins_app(void* p) {
|
||||
PLUGIN_APP_ID, PLUGIN_API_VERSION, composite_api_resolver_get(resolver));
|
||||
|
||||
do {
|
||||
if(plugin_manager_load_all(manager, APP_DATA_PATH("plugins")) != PluginManagerErrorNone) {
|
||||
// For built-in .fals (fal_embedded==True), use APP_ASSETS_PATH
|
||||
// Otherwise, use APP_DATA_PATH
|
||||
if(plugin_manager_load_all(manager, APP_ASSETS_PATH("plugins")) !=
|
||||
PluginManagerErrorNone) {
|
||||
FURI_LOG_E(TAG, "Failed to load all libs");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ App(
|
||||
"!plugins",
|
||||
"!nfc_cli.c",
|
||||
],
|
||||
fap_libs=["mbedtls"],
|
||||
fap_icon="icon.png",
|
||||
fap_category="NFC",
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ enum {
|
||||
SubmenuIndexUnlock = SubmenuIndexCommonMax,
|
||||
SubmenuIndexUnlockByReader,
|
||||
SubmenuIndexUnlockByPassword,
|
||||
SubmenuIndexWrite,
|
||||
};
|
||||
|
||||
static void nfc_scene_info_on_enter_mf_ultralight(NfcApp* instance) {
|
||||
@@ -106,6 +107,15 @@ static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instanc
|
||||
SubmenuIndexUnlock,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
} else if(
|
||||
data->type == MfUltralightTypeNTAG213 || data->type == MfUltralightTypeNTAG215 ||
|
||||
data->type == MfUltralightTypeNTAG216) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write",
|
||||
SubmenuIndexWrite,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +156,9 @@ static bool
|
||||
if(event == SubmenuIndexUnlock) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
||||
return true;
|
||||
} else if(event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrite);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ static NfcCommand nfc_scene_read_poller_callback_st25tb(NfcGenericEvent event, v
|
||||
NfcApp* instance = context;
|
||||
const St25tbPollerEvent* st25tb_event = event.event_data;
|
||||
|
||||
if(st25tb_event->type == St25tbPollerEventTypeReady) {
|
||||
if(st25tb_event->type == St25tbPollerEventTypeRequestMode) {
|
||||
st25tb_event->data->mode_request.mode = St25tbPollerModeRead;
|
||||
} else if(st25tb_event->type == St25tbPollerEventTypeSuccess) {
|
||||
nfc_device_set_data(
|
||||
instance->nfc_device, NfcProtocolSt25tb, nfc_poller_get_data(instance->poller));
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
|
||||
@@ -24,6 +24,10 @@ ADD_SCENE(nfc, field, Field)
|
||||
ADD_SCENE(nfc, retry_confirm, RetryConfirm)
|
||||
ADD_SCENE(nfc, exit_confirm, ExitConfirm)
|
||||
|
||||
ADD_SCENE(nfc, mf_ultralight_write, MfUltralightWrite)
|
||||
ADD_SCENE(nfc, mf_ultralight_write_success, MfUltralightWriteSuccess)
|
||||
ADD_SCENE(nfc, mf_ultralight_write_fail, MfUltralightWriteFail)
|
||||
ADD_SCENE(nfc, mf_ultralight_wrong_card, MfUltralightWrongCard)
|
||||
ADD_SCENE(nfc, mf_ultralight_unlock_menu, MfUltralightUnlockMenu)
|
||||
ADD_SCENE(nfc, mf_ultralight_unlock_warn, MfUltralightUnlockWarn)
|
||||
ADD_SCENE(nfc, mf_ultralight_key_input, MfUltralightKeyInput)
|
||||
|
||||
119
applications/main/nfc/scenes/nfc_scene_mf_ultralight_write.c
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "../nfc_app_i.h"
|
||||
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller.h>
|
||||
|
||||
enum {
|
||||
NfcSceneMfUltralightWriteStateCardSearch,
|
||||
NfcSceneMfUltralightWriteStateCardFound,
|
||||
};
|
||||
|
||||
NfcCommand nfc_scene_mf_ultralight_write_worker_callback(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.event_data);
|
||||
furi_assert(event.protocol == NfcProtocolMfUltralight);
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
NfcApp* instance = context;
|
||||
MfUltralightPollerEvent* mfu_event = event.event_data;
|
||||
|
||||
if(mfu_event->type == MfUltralightPollerEventTypeRequestMode) {
|
||||
mfu_event->data->poller_mode = MfUltralightPollerModeWrite;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeAuthRequest) {
|
||||
mfu_event->data->auth_context.skip_auth = true;
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeRequestWriteData) {
|
||||
mfu_event->data->write_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeCardMismatch) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventWrongCard);
|
||||
command = NfcCommandStop;
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeCardLocked) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
command = NfcCommandStop;
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeWriteFail) {
|
||||
command = NfcCommandStop;
|
||||
} else if(mfu_event->type == MfUltralightPollerEventTypeWriteSuccess) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_mf_ultralight_write_setup_view(NfcApp* instance) {
|
||||
Popup* popup = instance->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state =
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfUltralightWrite);
|
||||
|
||||
if(state == NfcSceneMfUltralightWriteStateCardSearch) {
|
||||
popup_set_text(
|
||||
instance->popup, "Apply the initial\ncard only", 128, 32, AlignRight, AlignCenter);
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else {
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
popup_set_icon(popup, 12, 23, &A_Loading_24);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_write_on_enter(void* context) {
|
||||
NfcApp* instance = context;
|
||||
dolphin_deed(DolphinDeedNfcEmulate);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfUltralightWrite,
|
||||
NfcSceneMfUltralightWriteStateCardSearch);
|
||||
nfc_scene_mf_ultralight_write_setup_view(instance);
|
||||
|
||||
// Setup and start worker
|
||||
FURI_LOG_D("WMFU", "Card searching...");
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfUltralight);
|
||||
nfc_poller_start(instance->poller, nfc_scene_mf_ultralight_write_worker_callback, instance);
|
||||
|
||||
nfc_blink_emulate_start(instance);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_write_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfUltralightWrite,
|
||||
NfcSceneMfUltralightWriteStateCardFound);
|
||||
nfc_scene_mf_ultralight_write_setup_view(instance);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventWrongCard) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrongCard);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventPollerSuccess) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWriteSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcCustomEventPollerFailure) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWriteFail);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_write_on_exit(void* context) {
|
||||
NfcApp* instance = context;
|
||||
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfUltralightWrite,
|
||||
NfcSceneMfUltralightWriteStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(instance->popup);
|
||||
|
||||
nfc_blink_stop(instance);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "../nfc_app_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_write_fail_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_write_fail_on_enter(void* context) {
|
||||
NfcApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Writing gone wrong!");
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
7,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"Card protected by\npassword, AUTH0\nor lock bits");
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Finish",
|
||||
nfc_scene_mf_ultralight_write_fail_widget_callback,
|
||||
instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
static bool nfc_scene_mf_ultralight_write_fail_move_to_back_scene(const NfcApp* const instance) {
|
||||
bool was_saved = scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSavedMenu);
|
||||
uint32_t scene_id = was_saved ? NfcSceneSavedMenu : NfcSceneReadMenu;
|
||||
|
||||
return scene_manager_search_and_switch_to_previous_scene(instance->scene_manager, scene_id);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_write_fail_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = nfc_scene_mf_ultralight_write_fail_move_to_back_scene(instance);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = nfc_scene_mf_ultralight_write_fail_move_to_back_scene(instance);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_write_fail_on_exit(void* context) {
|
||||
NfcApp* instance = context;
|
||||
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "../nfc_app_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_write_success_popup_callback(void* context) {
|
||||
NfcApp* instance = context;
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventViewExit);
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_write_success_on_enter(void* context) {
|
||||
NfcApp* instance = context;
|
||||
dolphin_deed(DolphinDeedNfcSave);
|
||||
|
||||
notification_message(instance->notifications, &sequence_success);
|
||||
|
||||
Popup* popup = instance->popup;
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, instance);
|
||||
popup_set_callback(popup, nfc_scene_mf_ultralight_write_success_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_write_success_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventViewExit) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneSavedMenu);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_write_success_on_exit(void* context) {
|
||||
NfcApp* instance = context;
|
||||
|
||||
// Clear view
|
||||
popup_reset(instance->popup);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "../nfc_app_i.h"
|
||||
|
||||
void nfc_scene_mf_ultralight_wrong_card_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcApp* instance = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_wrong_card_on_enter(void* context) {
|
||||
NfcApp* instance = context;
|
||||
Widget* widget = instance->widget;
|
||||
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "This is wrong card");
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
4,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"Card of the same\ntype should be\n presented");
|
||||
//"Data management\nis only possible\nwith card of same type");
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
nfc_scene_mf_ultralight_wrong_card_widget_callback,
|
||||
instance);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_scene_mf_ultralight_wrong_card_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* instance = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(instance->scene_manager);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_mf_ultralight_wrong_card_on_exit(void* context) {
|
||||
NfcApp* instance = context;
|
||||
|
||||
widget_reset(instance->widget);
|
||||
}
|
||||
@@ -7,6 +7,7 @@ App(
|
||||
icon="A_U2F_14",
|
||||
order=80,
|
||||
resources="resources",
|
||||
fap_libs=["mbedtls"],
|
||||
fap_category="USB",
|
||||
fap_icon="icon.png",
|
||||
)
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* hmac.c - HMAC
|
||||
*
|
||||
* Copyright (C) 2017 Sergei Glushchenko
|
||||
* Author: Sergei Glushchenko <gl.sergei@gmail.com>
|
||||
*
|
||||
* This file is a part of U2F firmware for STM32
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As additional permission under GNU GPL version 3 section 7, you may
|
||||
* distribute non-source form of the Program without the copy of the
|
||||
* GNU GPL normally required by section 4, provided you inform the
|
||||
* recipients of GNU GPL by a written offer.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha256.h"
|
||||
#include "hmac_sha256.h"
|
||||
|
||||
static void _hmac_sha256_init(const hmac_context* ctx) {
|
||||
hmac_sha256_context* context = (hmac_sha256_context*)ctx;
|
||||
sha256_start(&context->sha_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
_hmac_sha256_update(const hmac_context* ctx, const uint8_t* message, unsigned message_size) {
|
||||
hmac_sha256_context* context = (hmac_sha256_context*)ctx;
|
||||
sha256_update(&context->sha_ctx, message, message_size);
|
||||
}
|
||||
|
||||
static void _hmac_sha256_finish(const hmac_context* ctx, uint8_t* hash_result) {
|
||||
hmac_sha256_context* context = (hmac_sha256_context*)ctx;
|
||||
sha256_finish(&context->sha_ctx, hash_result);
|
||||
}
|
||||
|
||||
/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
|
||||
the same size as the hash result size. */
|
||||
static void hmac_init(const hmac_context* ctx, const uint8_t* K) {
|
||||
uint8_t* pad = ctx->tmp + 2 * ctx->result_size;
|
||||
unsigned i;
|
||||
for(i = 0; i < ctx->result_size; ++i) pad[i] = K[i] ^ 0x36;
|
||||
for(; i < ctx->block_size; ++i) pad[i] = 0x36;
|
||||
|
||||
ctx->init_hash(ctx);
|
||||
ctx->update_hash(ctx, pad, ctx->block_size);
|
||||
}
|
||||
|
||||
static void hmac_update(const hmac_context* ctx, const uint8_t* message, unsigned message_size) {
|
||||
ctx->update_hash(ctx, message, message_size);
|
||||
}
|
||||
|
||||
static void hmac_finish(const hmac_context* ctx, const uint8_t* K, uint8_t* result) {
|
||||
uint8_t* pad = ctx->tmp + 2 * ctx->result_size;
|
||||
unsigned i;
|
||||
for(i = 0; i < ctx->result_size; ++i) pad[i] = K[i] ^ 0x5c;
|
||||
for(; i < ctx->block_size; ++i) pad[i] = 0x5c;
|
||||
|
||||
ctx->finish_hash(ctx, result);
|
||||
|
||||
ctx->init_hash(ctx);
|
||||
ctx->update_hash(ctx, pad, ctx->block_size);
|
||||
ctx->update_hash(ctx, result, ctx->result_size);
|
||||
ctx->finish_hash(ctx, result);
|
||||
}
|
||||
|
||||
void hmac_sha256_init(hmac_sha256_context* ctx, const uint8_t* K) {
|
||||
ctx->hmac_ctx.init_hash = _hmac_sha256_init;
|
||||
ctx->hmac_ctx.update_hash = _hmac_sha256_update;
|
||||
ctx->hmac_ctx.finish_hash = _hmac_sha256_finish;
|
||||
ctx->hmac_ctx.block_size = 64;
|
||||
ctx->hmac_ctx.result_size = 32;
|
||||
ctx->hmac_ctx.tmp = ctx->tmp;
|
||||
hmac_init(&ctx->hmac_ctx, K);
|
||||
}
|
||||
|
||||
void hmac_sha256_update(
|
||||
const hmac_sha256_context* ctx,
|
||||
const uint8_t* message,
|
||||
unsigned message_size) {
|
||||
hmac_update(&ctx->hmac_ctx, message, message_size);
|
||||
}
|
||||
|
||||
void hmac_sha256_finish(const hmac_sha256_context* ctx, const uint8_t* K, uint8_t* hash_result) {
|
||||
hmac_finish(&ctx->hmac_ctx, K, hash_result);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct hmac_context {
|
||||
void (*init_hash)(const struct hmac_context* context);
|
||||
void (*update_hash)(
|
||||
const struct hmac_context* context,
|
||||
const uint8_t* message,
|
||||
unsigned message_size);
|
||||
void (*finish_hash)(const struct hmac_context* context, uint8_t* hash_result);
|
||||
unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
|
||||
unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
|
||||
uint8_t* tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
|
||||
} hmac_context;
|
||||
|
||||
typedef struct hmac_sha256_context {
|
||||
hmac_context hmac_ctx;
|
||||
sha256_context sha_ctx;
|
||||
uint8_t tmp[32 * 2 + 64];
|
||||
} hmac_sha256_context;
|
||||
|
||||
void hmac_sha256_init(hmac_sha256_context* ctx, const uint8_t* K);
|
||||
|
||||
void hmac_sha256_update(
|
||||
const hmac_sha256_context* ctx,
|
||||
const uint8_t* message,
|
||||
unsigned message_size);
|
||||
|
||||
void hmac_sha256_finish(const hmac_sha256_context* ctx, const uint8_t* K, uint8_t* hash_result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,18 +1,22 @@
|
||||
#include <furi.h>
|
||||
#include "u2f.h"
|
||||
#include "u2f_hid.h"
|
||||
#include "u2f_data.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <littlefs/lfs_util.h> // for lfs_tobe32
|
||||
|
||||
#include "toolbox/sha256.h"
|
||||
#include "hmac_sha256.h"
|
||||
#include "micro-ecc/uECC.h"
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/ecdsa.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
#define TAG "U2f"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
#define MCHECK(expr) furi_check((expr) == 0)
|
||||
|
||||
#define U2F_CMD_REGISTER 0x01
|
||||
#define U2F_CMD_AUTHENTICATE 0x02
|
||||
#define U2F_CMD_VERSION 0x03
|
||||
@@ -25,16 +29,26 @@ typedef enum {
|
||||
0x08, // "dont-enforce-user-presence-and-sign" - send auth response even if user is missing
|
||||
} U2fAuthMode;
|
||||
|
||||
#define U2F_HASH_SIZE 32
|
||||
#define U2F_NONCE_SIZE 32
|
||||
#define U2F_CHALLENGE_SIZE 32
|
||||
#define U2F_APP_ID_SIZE 32
|
||||
|
||||
#define U2F_EC_KEY_SIZE 32
|
||||
#define U2F_EC_BIGNUM_SIZE 32
|
||||
#define U2F_EC_POINT_SIZE 65
|
||||
|
||||
typedef struct {
|
||||
uint8_t format;
|
||||
uint8_t xy[64];
|
||||
} __attribute__((packed)) U2fPubKey;
|
||||
} FURI_PACKED U2fPubKey;
|
||||
_Static_assert(sizeof(U2fPubKey) == U2F_EC_POINT_SIZE, "U2fPubKey size mismatch");
|
||||
|
||||
typedef struct {
|
||||
uint8_t len;
|
||||
uint8_t hash[32];
|
||||
uint8_t nonce[32];
|
||||
} __attribute__((packed)) U2fKeyHandle;
|
||||
uint8_t hash[U2F_HASH_SIZE];
|
||||
uint8_t nonce[U2F_NONCE_SIZE];
|
||||
} FURI_PACKED U2fKeyHandle;
|
||||
|
||||
typedef struct {
|
||||
uint8_t cla;
|
||||
@@ -42,16 +56,16 @@ typedef struct {
|
||||
uint8_t p1;
|
||||
uint8_t p2;
|
||||
uint8_t len[3];
|
||||
uint8_t challenge[32];
|
||||
uint8_t app_id[32];
|
||||
} __attribute__((packed)) U2fRegisterReq;
|
||||
uint8_t challenge[U2F_CHALLENGE_SIZE];
|
||||
uint8_t app_id[U2F_APP_ID_SIZE];
|
||||
} FURI_PACKED U2fRegisterReq;
|
||||
|
||||
typedef struct {
|
||||
uint8_t reserved;
|
||||
U2fPubKey pub_key;
|
||||
U2fKeyHandle key_handle;
|
||||
uint8_t cert[];
|
||||
} __attribute__((packed)) U2fRegisterResp;
|
||||
} FURI_PACKED U2fRegisterResp;
|
||||
|
||||
typedef struct {
|
||||
uint8_t cla;
|
||||
@@ -59,16 +73,16 @@ typedef struct {
|
||||
uint8_t p1;
|
||||
uint8_t p2;
|
||||
uint8_t len[3];
|
||||
uint8_t challenge[32];
|
||||
uint8_t app_id[32];
|
||||
uint8_t challenge[U2F_CHALLENGE_SIZE];
|
||||
uint8_t app_id[U2F_APP_ID_SIZE];
|
||||
U2fKeyHandle key_handle;
|
||||
} __attribute__((packed)) U2fAuthReq;
|
||||
} FURI_PACKED U2fAuthReq;
|
||||
|
||||
typedef struct {
|
||||
uint8_t user_present;
|
||||
uint32_t counter;
|
||||
uint8_t signature[];
|
||||
} __attribute__((packed)) U2fAuthResp;
|
||||
} FURI_PACKED U2fAuthResp;
|
||||
|
||||
static const uint8_t ver_str[] = {"U2F_V2"};
|
||||
|
||||
@@ -78,19 +92,20 @@ static const uint8_t state_user_missing[] = {0x69, 0x85};
|
||||
static const uint8_t state_wrong_data[] = {0x6A, 0x80};
|
||||
|
||||
struct U2fData {
|
||||
uint8_t device_key[32];
|
||||
uint8_t cert_key[32];
|
||||
uint8_t device_key[U2F_EC_KEY_SIZE];
|
||||
uint8_t cert_key[U2F_EC_KEY_SIZE];
|
||||
uint32_t counter;
|
||||
const struct uECC_Curve_t* p_curve;
|
||||
bool ready;
|
||||
bool user_present;
|
||||
U2fEvtCallback callback;
|
||||
void* context;
|
||||
mbedtls_ecp_group group;
|
||||
};
|
||||
|
||||
static int u2f_uecc_random(uint8_t* dest, unsigned size) {
|
||||
static int u2f_uecc_random_cb(void* context, uint8_t* dest, unsigned size) {
|
||||
UNUSED(context);
|
||||
furi_hal_random_fill_buf(dest, size);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
U2fData* u2f_alloc() {
|
||||
@@ -99,6 +114,7 @@ U2fData* u2f_alloc() {
|
||||
|
||||
void u2f_free(U2fData* U2F) {
|
||||
furi_assert(U2F);
|
||||
mbedtls_ecp_group_free(&U2F->group);
|
||||
free(U2F);
|
||||
}
|
||||
|
||||
@@ -129,8 +145,8 @@ bool u2f_init(U2fData* U2F) {
|
||||
}
|
||||
}
|
||||
|
||||
U2F->p_curve = uECC_secp256r1();
|
||||
uECC_set_rng(u2f_uecc_random);
|
||||
mbedtls_ecp_group_init(&U2F->group);
|
||||
mbedtls_ecp_group_load(&U2F->group, MBEDTLS_ECP_DP_SECP256R1);
|
||||
|
||||
U2F->ready = true;
|
||||
return true;
|
||||
@@ -171,21 +187,63 @@ static uint8_t u2f_der_encode_signature(uint8_t* der, uint8_t* sig) {
|
||||
der[0] = 0x30;
|
||||
|
||||
uint8_t len = 2;
|
||||
len += u2f_der_encode_int(der + len, sig, 32);
|
||||
len += u2f_der_encode_int(der + len, sig + 32, 32);
|
||||
len += u2f_der_encode_int(der + len, sig, U2F_HASH_SIZE);
|
||||
len += u2f_der_encode_int(der + len, sig + U2F_HASH_SIZE, U2F_HASH_SIZE);
|
||||
|
||||
der[1] = len - 2;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void
|
||||
u2f_ecc_sign(mbedtls_ecp_group* grp, const uint8_t* key, uint8_t* hash, uint8_t* signature) {
|
||||
mbedtls_mpi r, s, d;
|
||||
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
mbedtls_mpi_init(&d);
|
||||
|
||||
MCHECK(mbedtls_mpi_read_binary(&d, key, U2F_EC_KEY_SIZE));
|
||||
MCHECK(mbedtls_ecdsa_sign(grp, &r, &s, &d, hash, U2F_HASH_SIZE, u2f_uecc_random_cb, NULL));
|
||||
MCHECK(mbedtls_mpi_write_binary(&r, signature, U2F_EC_BIGNUM_SIZE));
|
||||
MCHECK(mbedtls_mpi_write_binary(&s, signature + U2F_EC_BIGNUM_SIZE, U2F_EC_BIGNUM_SIZE));
|
||||
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_mpi_free(&d);
|
||||
}
|
||||
|
||||
static void u2f_ecc_compute_public_key(
|
||||
mbedtls_ecp_group* grp,
|
||||
const uint8_t* private_key,
|
||||
U2fPubKey* public_key) {
|
||||
mbedtls_ecp_point Q;
|
||||
mbedtls_mpi d;
|
||||
size_t olen;
|
||||
|
||||
mbedtls_ecp_point_init(&Q);
|
||||
mbedtls_mpi_init(&d);
|
||||
|
||||
MCHECK(mbedtls_mpi_read_binary(&d, private_key, U2F_EC_KEY_SIZE));
|
||||
MCHECK(mbedtls_ecp_mul(grp, &Q, &d, &grp->G, u2f_uecc_random_cb, NULL));
|
||||
MCHECK(mbedtls_ecp_check_privkey(grp, &d));
|
||||
|
||||
MCHECK(mbedtls_ecp_point_write_binary(
|
||||
grp, &Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, (unsigned char*)public_key, sizeof(U2fPubKey)));
|
||||
|
||||
mbedtls_ecp_point_free(&Q);
|
||||
mbedtls_mpi_free(&d);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) {
|
||||
U2fRegisterReq* req = (U2fRegisterReq*)buf;
|
||||
U2fRegisterResp* resp = (U2fRegisterResp*)buf;
|
||||
U2fKeyHandle handle;
|
||||
uint8_t private[32];
|
||||
uint8_t private[U2F_EC_KEY_SIZE];
|
||||
U2fPubKey pub_key;
|
||||
uint8_t hash[32];
|
||||
uint8_t signature[64];
|
||||
uint8_t hash[U2F_HASH_SIZE];
|
||||
uint8_t signature[U2F_EC_BIGNUM_SIZE * 2];
|
||||
|
||||
if(u2f_data_check(false) == false) {
|
||||
U2F->ready = false;
|
||||
@@ -201,40 +259,54 @@ static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) {
|
||||
}
|
||||
U2F->user_present = false;
|
||||
|
||||
hmac_sha256_context hmac_ctx;
|
||||
sha256_context sha_ctx;
|
||||
handle.len = U2F_HASH_SIZE * 2;
|
||||
|
||||
handle.len = 32 * 2;
|
||||
// Generate random nonce
|
||||
furi_hal_random_fill_buf(handle.nonce, 32);
|
||||
|
||||
{
|
||||
mbedtls_md_context_t hmac_ctx;
|
||||
mbedtls_md_init(&hmac_ctx);
|
||||
MCHECK(mbedtls_md_setup(&hmac_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1));
|
||||
MCHECK(mbedtls_md_hmac_starts(&hmac_ctx, U2F->device_key, sizeof(U2F->device_key)));
|
||||
|
||||
// Generate private key
|
||||
hmac_sha256_init(&hmac_ctx, U2F->device_key);
|
||||
hmac_sha256_update(&hmac_ctx, req->app_id, 32);
|
||||
hmac_sha256_update(&hmac_ctx, handle.nonce, 32);
|
||||
hmac_sha256_finish(&hmac_ctx, U2F->device_key, private);
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, req->app_id, sizeof(req->app_id)));
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, handle.nonce, sizeof(handle.nonce)));
|
||||
MCHECK(mbedtls_md_hmac_finish(&hmac_ctx, private));
|
||||
|
||||
MCHECK(mbedtls_md_hmac_reset(&hmac_ctx));
|
||||
|
||||
// Generate private key handle
|
||||
hmac_sha256_init(&hmac_ctx, U2F->device_key);
|
||||
hmac_sha256_update(&hmac_ctx, private, 32);
|
||||
hmac_sha256_update(&hmac_ctx, req->app_id, 32);
|
||||
hmac_sha256_finish(&hmac_ctx, U2F->device_key, handle.hash);
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, private, sizeof(private)));
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, req->app_id, sizeof(req->app_id)));
|
||||
MCHECK(mbedtls_md_hmac_finish(&hmac_ctx, handle.hash));
|
||||
}
|
||||
|
||||
// Generate public key
|
||||
pub_key.format = 0x04; // Uncompressed point
|
||||
uECC_compute_public_key(private, pub_key.xy, U2F->p_curve);
|
||||
u2f_ecc_compute_public_key(&U2F->group, private, &pub_key);
|
||||
|
||||
// Generate signature
|
||||
{
|
||||
uint8_t reserved_byte = 0;
|
||||
sha256_start(&sha_ctx);
|
||||
sha256_update(&sha_ctx, &reserved_byte, 1);
|
||||
sha256_update(&sha_ctx, req->app_id, 32);
|
||||
sha256_update(&sha_ctx, req->challenge, 32);
|
||||
sha256_update(&sha_ctx, handle.hash, handle.len);
|
||||
sha256_update(&sha_ctx, (uint8_t*)&pub_key, 65);
|
||||
sha256_finish(&sha_ctx, hash);
|
||||
|
||||
uECC_sign(U2F->cert_key, hash, 32, signature, U2F->p_curve);
|
||||
mbedtls_sha256_context sha_ctx;
|
||||
|
||||
mbedtls_sha256_init(&sha_ctx);
|
||||
mbedtls_sha256_starts(&sha_ctx, 0);
|
||||
|
||||
mbedtls_sha256_update(&sha_ctx, &reserved_byte, 1);
|
||||
mbedtls_sha256_update(&sha_ctx, req->app_id, sizeof(req->app_id));
|
||||
mbedtls_sha256_update(&sha_ctx, req->challenge, sizeof(req->challenge));
|
||||
mbedtls_sha256_update(&sha_ctx, handle.hash, handle.len);
|
||||
mbedtls_sha256_update(&sha_ctx, (uint8_t*)&pub_key, sizeof(U2fPubKey));
|
||||
|
||||
mbedtls_sha256_finish(&sha_ctx, hash);
|
||||
mbedtls_sha256_free(&sha_ctx);
|
||||
}
|
||||
|
||||
// Sign hash
|
||||
u2f_ecc_sign(&U2F->group, U2F->cert_key, hash, signature);
|
||||
|
||||
// Encode response message
|
||||
resp->reserved = 0x05;
|
||||
@@ -250,13 +322,11 @@ static uint16_t u2f_register(U2fData* U2F, uint8_t* buf) {
|
||||
static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
||||
U2fAuthReq* req = (U2fAuthReq*)buf;
|
||||
U2fAuthResp* resp = (U2fAuthResp*)buf;
|
||||
uint8_t priv_key[32];
|
||||
uint8_t priv_key[U2F_EC_KEY_SIZE];
|
||||
uint8_t mac_control[32];
|
||||
hmac_sha256_context hmac_ctx;
|
||||
sha256_context sha_ctx;
|
||||
uint8_t flags = 0;
|
||||
uint8_t hash[32];
|
||||
uint8_t signature[64];
|
||||
uint8_t hash[U2F_HASH_SIZE];
|
||||
uint8_t signature[U2F_HASH_SIZE * 2];
|
||||
uint32_t be_u2f_counter;
|
||||
|
||||
if(u2f_data_check(false) == false) {
|
||||
@@ -281,26 +351,42 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
||||
be_u2f_counter = lfs_tobe32(U2F->counter + 1);
|
||||
|
||||
// Generate hash
|
||||
sha256_start(&sha_ctx);
|
||||
sha256_update(&sha_ctx, req->app_id, 32);
|
||||
sha256_update(&sha_ctx, &flags, 1);
|
||||
sha256_update(&sha_ctx, (uint8_t*)&(be_u2f_counter), 4);
|
||||
sha256_update(&sha_ctx, req->challenge, 32);
|
||||
sha256_finish(&sha_ctx, hash);
|
||||
{
|
||||
mbedtls_sha256_context sha_ctx;
|
||||
|
||||
mbedtls_sha256_init(&sha_ctx);
|
||||
mbedtls_sha256_starts(&sha_ctx, 0);
|
||||
|
||||
mbedtls_sha256_update(&sha_ctx, req->app_id, sizeof(req->app_id));
|
||||
mbedtls_sha256_update(&sha_ctx, &flags, 1);
|
||||
mbedtls_sha256_update(&sha_ctx, (uint8_t*)&(be_u2f_counter), sizeof(be_u2f_counter));
|
||||
mbedtls_sha256_update(&sha_ctx, req->challenge, sizeof(req->challenge));
|
||||
|
||||
mbedtls_sha256_finish(&sha_ctx, hash);
|
||||
mbedtls_sha256_free(&sha_ctx);
|
||||
}
|
||||
|
||||
{
|
||||
mbedtls_md_context_t hmac_ctx;
|
||||
mbedtls_md_init(&hmac_ctx);
|
||||
MCHECK(mbedtls_md_setup(&hmac_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1));
|
||||
MCHECK(mbedtls_md_hmac_starts(&hmac_ctx, U2F->device_key, sizeof(U2F->device_key)));
|
||||
|
||||
// Recover private key
|
||||
hmac_sha256_init(&hmac_ctx, U2F->device_key);
|
||||
hmac_sha256_update(&hmac_ctx, req->app_id, 32);
|
||||
hmac_sha256_update(&hmac_ctx, req->key_handle.nonce, 32);
|
||||
hmac_sha256_finish(&hmac_ctx, U2F->device_key, priv_key);
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, req->app_id, sizeof(req->app_id)));
|
||||
MCHECK(mbedtls_md_hmac_update(
|
||||
&hmac_ctx, req->key_handle.nonce, sizeof(req->key_handle.nonce)));
|
||||
MCHECK(mbedtls_md_hmac_finish(&hmac_ctx, priv_key));
|
||||
|
||||
MCHECK(mbedtls_md_hmac_reset(&hmac_ctx));
|
||||
|
||||
// Generate and verify private key handle
|
||||
hmac_sha256_init(&hmac_ctx, U2F->device_key);
|
||||
hmac_sha256_update(&hmac_ctx, priv_key, 32);
|
||||
hmac_sha256_update(&hmac_ctx, req->app_id, 32);
|
||||
hmac_sha256_finish(&hmac_ctx, U2F->device_key, mac_control);
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, priv_key, sizeof(priv_key)));
|
||||
MCHECK(mbedtls_md_hmac_update(&hmac_ctx, req->app_id, sizeof(req->app_id)));
|
||||
MCHECK(mbedtls_md_hmac_finish(&hmac_ctx, mac_control));
|
||||
}
|
||||
|
||||
if(memcmp(req->key_handle.hash, mac_control, 32) != 0) {
|
||||
if(memcmp(req->key_handle.hash, mac_control, sizeof(mac_control)) != 0) {
|
||||
FURI_LOG_W(TAG, "Wrong handle!");
|
||||
memcpy(&buf[0], state_wrong_data, 2);
|
||||
return 2;
|
||||
@@ -311,7 +397,8 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
uECC_sign(priv_key, hash, 32, signature, U2F->p_curve);
|
||||
// Sign hash
|
||||
u2f_ecc_sign(&U2F->group, priv_key, hash, signature);
|
||||
|
||||
resp->user_present = flags;
|
||||
resp->counter = be_u2f_counter;
|
||||
|
||||
@@ -31,7 +31,7 @@ typedef struct {
|
||||
uint32_t counter;
|
||||
uint8_t random_salt[24];
|
||||
uint32_t control;
|
||||
} __attribute__((packed)) U2fCounterData;
|
||||
} FURI_PACKED U2fCounterData;
|
||||
|
||||
bool u2f_data_check(bool cert_only) {
|
||||
bool state = false;
|
||||
|
||||
@@ -242,7 +242,7 @@ uint16_t canvas_string_width(Canvas* canvas, const char* str) {
|
||||
return u8g2_GetStrWidth(&canvas->fb, str);
|
||||
}
|
||||
|
||||
uint8_t canvas_glyph_width(Canvas* canvas, char symbol) {
|
||||
uint8_t canvas_glyph_width(Canvas* canvas, uint16_t symbol) {
|
||||
furi_assert(canvas);
|
||||
return u8g2_GetGlyphWidth(&canvas->fb, symbol);
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ uint16_t canvas_string_width(Canvas* canvas, const char* str);
|
||||
*
|
||||
* @return width in pixels
|
||||
*/
|
||||
uint8_t canvas_glyph_width(Canvas* canvas, char symbol);
|
||||
uint8_t canvas_glyph_width(Canvas* canvas, uint16_t symbol);
|
||||
|
||||
/** Draw bitmap picture at position defined by x,y.
|
||||
*
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "flipper.pb.h"
|
||||
#include "rpc_i.h"
|
||||
#include "gui.pb.h"
|
||||
#include <gui/gui_i.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#include <flipper.pb.h>
|
||||
#include <gui.pb.h>
|
||||
|
||||
#define TAG "RpcGui"
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "rpc.h"
|
||||
#include "storage/filesystem_api_defines.h"
|
||||
#include <storage/filesystem_api_defines.h>
|
||||
#include <pb.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#include "flipper.pb.h"
|
||||
#include <core/common_defines.h>
|
||||
#include <core/memmgr.h>
|
||||
#include <core/record.h>
|
||||
#include "pb_decode.h"
|
||||
#include "rpc/rpc.h"
|
||||
#include "rpc_i.h"
|
||||
#include "storage.pb.h"
|
||||
#include "storage/filesystem_api_defines.h"
|
||||
#include "storage/storage.h"
|
||||
#include <stdint.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpc_i.h>
|
||||
#include <storage/filesystem_api_defines.h>
|
||||
#include <storage/storage.h>
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <update_util/lfs_backup.h>
|
||||
|
||||
#include <pb_decode.h>
|
||||
#include <storage.pb.h>
|
||||
#include <flipper.pb.h>
|
||||
|
||||
#define TAG "RpcStorage"
|
||||
|
||||
#define MAX_NAME_LENGTH 254
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "storage_move_to_sd.h"
|
||||
|
||||
#include <core/common_defines.h>
|
||||
#include <core/log.h>
|
||||
#include "loader/loader.h"
|
||||
#include <stdint.h>
|
||||
#include <loader/loader.h>
|
||||
#include <toolbox/dir_walk.h>
|
||||
#include <toolbox/path.h>
|
||||
|
||||
|
||||
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_0.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_1.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_10.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_11.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_12.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_13.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_14.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_15.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_16.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_17.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_18.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_19.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_2.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_20.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_21.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_22.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_23.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_24.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_25.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_26.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_27.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_28.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_29.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_3.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_30.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_31.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_32.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_33.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_34.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_35.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_36.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_37.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_38.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_39.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_4.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_40.png
vendored
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_41.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_42.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_43.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_44.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_45.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_46.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_47.png
vendored
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_48.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_49.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_5.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_50.png
vendored
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_51.png
vendored
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_52.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_6.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_7.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_8.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Secret_door_128x64/frame_9.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
14
assets/dolphin/external/L2_Secret_door_128x64/meta.txt
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
Filetype: Flipper Animation
|
||||
Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 29
|
||||
Active frames: 24
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
||||
Active cycles: 1
|
||||
Frame rate: 2
|
||||
Duration: 3600
|
||||
Active cooldown: 7
|
||||
|
||||
Bubble slots: 0
|
||||
7
assets/dolphin/external/manifest.txt
vendored
@@ -176,6 +176,13 @@ Min level: 22
|
||||
Max level: 30
|
||||
Weight: 4
|
||||
|
||||
Name: L2_Secret_door_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Min level: 26
|
||||
Max level: 30
|
||||
Weight: 4
|
||||
|
||||
Name: Credits_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
|
||||
@@ -17,6 +17,10 @@ extern "C" {
|
||||
#define FURI_WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_PACKED
|
||||
#define FURI_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#ifndef FURI_IS_IRQ_MASKED
|
||||
#define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
|
||||
#endif
|
||||
@@ -47,6 +51,10 @@ void __furi_critical_exit(__FuriCriticalInfo info);
|
||||
#define FURI_CRITICAL_EXIT() __furi_critical_exit(__furi_critical_info);
|
||||
#endif
|
||||
|
||||
#ifndef FURI_CHECK_RETURN
|
||||
#define FURI_CHECK_RETURN __attribute__((__warn_unused_result__))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
- `fatfs` - FatFS file system driver
|
||||
- `flipper_application` - Flipper application library, used for FAPs
|
||||
- `flipper_format` - Flipper File Format library
|
||||
- `fnv1a-hash` - FNV-1a hash library
|
||||
- `heatshrink` - Heatshrink compression library
|
||||
- `ibutton` - ibutton library, used by iButton application
|
||||
- `infrared` - Infrared library, used by Infrared application
|
||||
@@ -19,7 +18,6 @@
|
||||
- `libusb_stm32` - LibUSB for STM32 series MCU
|
||||
- `littlefs` - LittleFS file system driver, used by internal storage
|
||||
- `mbedtls` - MbedTLS cryptography library
|
||||
- `micro-ecc` - MicroECC cryptography library
|
||||
- `microtar` - MicroTAR library
|
||||
- `mlib` - M-Lib C containers library
|
||||
- `nanopb` - NanoPB library, protobuf implementation for MCU
|
||||
@@ -28,11 +26,10 @@
|
||||
- `print` - Tiny printf implementation
|
||||
- `digital_signal` - Digital Signal library used by NFC for software implemented protocols
|
||||
- `pulse_reader` - Pulse Reader library used by NFC for software implemented protocols
|
||||
- `qrcode` - QR-Code library
|
||||
- `stm32wb_cmsis` - STM32WB series CMSIS headers, extends CMSIS Core
|
||||
- `stm32wb_copro` - STM32WB Copro library: contains WPAN and radio co-processor firmware
|
||||
- `stm32wb_hal` - STM32WB HAL library, extends STM32WB CMSIS and provides HAL
|
||||
- `subghz` - Subghz library, used by SubGhz application
|
||||
- `toolbox` - Toolbox library, contains various things that is used by flipper firmware
|
||||
- `toolbox` - Toolbox library, contains various things that is used by Flipper firmware
|
||||
- `u8g2` - u8g2 graphics library, used by GUI subsystem
|
||||
- `update_util` - update utilities library, used by updater
|
||||
@@ -1,91 +1,25 @@
|
||||
Import("env")
|
||||
|
||||
env.Append(
|
||||
LINT_SOURCES=[
|
||||
Dir("app-scened-template"),
|
||||
Dir("digital_signal"),
|
||||
Dir("pulse_reader"),
|
||||
Dir("signal_reader"),
|
||||
Dir("drivers"),
|
||||
Dir("flipper_format"),
|
||||
Dir("infrared"),
|
||||
Dir("nfc"),
|
||||
Dir("subghz"),
|
||||
Dir("toolbox"),
|
||||
Dir("u8g2"),
|
||||
Dir("update_util"),
|
||||
Dir("xtreme"),
|
||||
Dir("print"),
|
||||
Dir("music_worker"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
env.Append(
|
||||
CPPPATH=[
|
||||
"#/",
|
||||
"#/lib", # TODO FL-3553: remove!
|
||||
"#/lib/mlib",
|
||||
# Ugly hack
|
||||
Dir("../assets/compiled"),
|
||||
Dir("../../icons"),
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
*(
|
||||
File(f"#/lib/mlib/m-{name}.h")
|
||||
for name in (
|
||||
"algo",
|
||||
"array",
|
||||
"bptree",
|
||||
"core",
|
||||
"deque",
|
||||
"dict",
|
||||
"list",
|
||||
"rbtree",
|
||||
"tuple",
|
||||
"variant",
|
||||
)
|
||||
),
|
||||
File("../../icons/assets_icons.h"),
|
||||
File("xtreme/xtreme.h"),
|
||||
],
|
||||
CPPDEFINES=[
|
||||
'"M_MEMORY_FULL(x)=abort()"',
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# drivers
|
||||
# fatfs
|
||||
# flipper_format
|
||||
# infrared
|
||||
# littlefs
|
||||
# subghz
|
||||
# toolbox
|
||||
# one_wire
|
||||
# micro-ecc
|
||||
# misc
|
||||
# digital_signal
|
||||
# fnv1a_hash
|
||||
# microtar
|
||||
# nfc
|
||||
# qrcode
|
||||
# u8g2
|
||||
# update_util
|
||||
# heatshrink
|
||||
# nanopb
|
||||
# apps
|
||||
# app-scened-template
|
||||
# callback-connector
|
||||
# app-template
|
||||
|
||||
|
||||
libs = env.BuildModules(
|
||||
[
|
||||
"mlib",
|
||||
"stm32wb",
|
||||
"freertos",
|
||||
"print",
|
||||
"microtar",
|
||||
"mbedtls",
|
||||
"toolbox",
|
||||
"libusb_stm32",
|
||||
"drivers",
|
||||
@@ -95,17 +29,20 @@ libs = env.BuildModules(
|
||||
"ibutton",
|
||||
"infrared",
|
||||
"littlefs",
|
||||
"mbedtls",
|
||||
"subghz",
|
||||
"nfc",
|
||||
"digital_signal",
|
||||
"pulse_reader",
|
||||
"signal_reader",
|
||||
"appframe",
|
||||
"misc",
|
||||
"u8g2",
|
||||
"lfrfid",
|
||||
"flipper_application",
|
||||
"music_worker",
|
||||
"nanopb",
|
||||
"update_util",
|
||||
"xtreme",
|
||||
"heatshrink",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ env.Append(
|
||||
"#/lib/app-scened-template",
|
||||
"#/lib/callback-connector",
|
||||
],
|
||||
LINT_SOURCES=[
|
||||
Dir("app-scened-template"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ env.Append(
|
||||
File("digital_signal.h"),
|
||||
File("digital_sequence.h"),
|
||||
],
|
||||
LINT_SOURCES=[
|
||||
Dir("."),
|
||||
],
|
||||
)
|
||||
|
||||
libenv = env.Clone(FW_LIB_NAME="digital_signal")
|
||||
|
||||
@@ -10,6 +10,9 @@ env.Append(
|
||||
File("st25r3916_reg.h"),
|
||||
File("st25r3916.h"),
|
||||
],
|
||||
LINT_SOURCES=[
|
||||
Dir("."),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "storage/storage.h"
|
||||
#include <elf.h>
|
||||
#include "elf_file.h"
|
||||
#include "elf_file_i.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <elf.h>
|
||||
#include "elf_api_interface.h"
|
||||
#include "../api_hashtable/api_hashtable.h"
|
||||
|
||||
@@ -34,7 +35,7 @@ const uint8_t trampoline_code_little_endian[TRAMPOLINE_CODE_SIZE] =
|
||||
typedef struct {
|
||||
uint8_t code[TRAMPOLINE_CODE_SIZE];
|
||||
uint32_t addr;
|
||||
} __attribute__((packed)) JMPTrampoline;
|
||||
} FURI_PACKED JMPTrampoline;
|
||||
|
||||
/**************************************************************************************************/
|
||||
/********************************************* Caches *********************************************/
|
||||
|
||||
@@ -9,6 +9,9 @@ env.Append(
|
||||
File("flipper_format_i.h"),
|
||||
File("flipper_format_stream.h"),
|
||||
],
|
||||
LINT_SOURCES=[
|
||||
Dir("."),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#include "fnv1a-hash.h"
|
||||
|
||||
// FNV-1a hash, 32-bit
|
||||
uint32_t fnv1a_buffer_hash(const uint8_t* buffer, uint32_t length, uint32_t hash)
|
||||
{
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
hash = (hash ^ buffer[i]) * 16777619ULL;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FNV_1A_INIT 2166136261UL
|
||||
|
||||
// FNV-1a hash, 32-bit
|
||||
uint32_t fnv1a_buffer_hash(const uint8_t* buffer, uint32_t length, uint32_t hash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
// constexpr FNV-1a hash for strings, 32-bit
|
||||
inline constexpr uint32_t fnv1a_string_hash(const char* str) {
|
||||
uint32_t hash = FNV_1A_INIT;
|
||||
|
||||
while(*str) {
|
||||
hash = (hash ^ *str) * 16777619ULL;
|
||||
str += 1;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
#else
|
||||
// FNV-1a hash for strings, 32-bit
|
||||
inline uint32_t fnv1a_string_hash(const char* str) {
|
||||
uint32_t hash = FNV_1A_INIT;
|
||||
|
||||
while(*str) {
|
||||
hash = (hash ^ *str) * 16777619ULL;
|
||||
str += 1;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
#endif
|
||||
23
lib/heatshrink.scons
Normal file
@@ -0,0 +1,23 @@
|
||||
from fbt.util import GLOB_FILE_EXCLUSION
|
||||
|
||||
Import("env")
|
||||
|
||||
env.Append(
|
||||
CPPPATH=[
|
||||
"#/lib/heatshrink",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
libenv = env.Clone(FW_LIB_NAME="heatshrink")
|
||||
libenv.ApplyLibFlags()
|
||||
|
||||
sources = Glob(
|
||||
"heatshrink/heatshrink_*.c*",
|
||||
exclude=GLOB_FILE_EXCLUSION,
|
||||
source=True,
|
||||
)
|
||||
|
||||
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
||||
libenv.Install("${LIB_DIST_DIR}", lib)
|
||||
Return("lib")
|
||||
@@ -10,6 +10,9 @@ env.Append(
|
||||
File("worker/infrared_worker.h"),
|
||||
File("worker/infrared_transmit.h"),
|
||||
],
|
||||
LINT_SOURCES=[
|
||||
Dir("."),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -2,13 +2,21 @@ Import("env")
|
||||
|
||||
env.Append(
|
||||
CPPPATH=[
|
||||
"#/lib/mbedtls",
|
||||
# "#/lib/mbedtls",
|
||||
"#/lib/mbedtls/include",
|
||||
],
|
||||
SDK_HEADERS=[
|
||||
File("mbedtls/include/mbedtls/des.h"),
|
||||
File("mbedtls/include/mbedtls/sha1.h"),
|
||||
File("mbedtls/include/mbedtls/sha256.h"),
|
||||
File("mbedtls/include/mbedtls/md5.h"),
|
||||
File("mbedtls/include/mbedtls/md.h"),
|
||||
File("mbedtls/include/mbedtls/ecdsa.h"),
|
||||
File("mbedtls/include/mbedtls/ecdh.h"),
|
||||
File("mbedtls/include/mbedtls/ecp.h"),
|
||||
# File("mbedtls/include/mbedtls/sha1.h"),
|
||||
],
|
||||
CPPDEFINES=[("MBEDTLS_CONFIG_FILE", '\\"mbedtls_cfg.h\\"')],
|
||||
)
|
||||
|
||||
|
||||
@@ -20,14 +28,30 @@ libenv.AppendUnique(
|
||||
# Required for lib to be linkable with .faps
|
||||
"-mword-relocations",
|
||||
"-mlong-calls",
|
||||
# Crappy code :)
|
||||
"-Wno-redundant-decls",
|
||||
],
|
||||
)
|
||||
|
||||
# If we were to build full mbedtls, we would need to use this:
|
||||
# sources = libenv.GlobRecursive("*.c*", "mbedtls/library")
|
||||
# Otherwise, we can just use the files we need:
|
||||
sources = [
|
||||
"mbedtls/library/des.c",
|
||||
"mbedtls/library/sha1.c",
|
||||
"mbedtls/library/platform_util.c",
|
||||
File("mbedtls/library/bignum.c"),
|
||||
File("mbedtls/library/bignum_core.c"),
|
||||
File("mbedtls/library/ecdsa.c"),
|
||||
File("mbedtls/library/ecp.c"),
|
||||
File("mbedtls/library/ecp_curves.c"),
|
||||
File("mbedtls/library/md.c"),
|
||||
File("mbedtls/library/md5.c"),
|
||||
File("mbedtls/library/platform_util.c"),
|
||||
File("mbedtls/library/ripemd160.c"),
|
||||
File("mbedtls/library/sha1.c"),
|
||||
File("mbedtls/library/sha256.c"),
|
||||
File("mbedtls/library/des.c"),
|
||||
]
|
||||
Depends(sources, File("mbedtls_cfg.h"))
|
||||
|
||||
|
||||
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
||||
libenv.Install("${LIB_DIST_DIR}", lib)
|
||||
|
||||
92
lib/mbedtls_cfg.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* A subset of the mbedTLS configuration options that are relevant to the
|
||||
* Flipper Zero firmware and apps. They are built to "mbedtls" library you can
|
||||
* link your apps with.
|
||||
*
|
||||
* If you need more features, either bring the full mbedtls library into your
|
||||
* app using "fap_private_libs" or open an issue on GitHub to add them to the
|
||||
* default configuration.
|
||||
**/
|
||||
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
|
||||
#define MBEDTLS_NO_UDBL_DIVISION
|
||||
#define MBEDTLS_NO_64BIT_MULTIPLICATION
|
||||
|
||||
#define MBEDTLS_DEPRECATED_WARNING
|
||||
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
// #define MBEDTLS_CHECK_RETURN_WARNING
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_CIPHER_MODE_CFB
|
||||
#define MBEDTLS_CIPHER_MODE_CTR
|
||||
#define MBEDTLS_CIPHER_MODE_OFB
|
||||
#define MBEDTLS_CIPHER_MODE_XTS
|
||||
|
||||
#define MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
|
||||
#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
|
||||
#define MBEDTLS_CIPHER_PADDING_ZEROS
|
||||
|
||||
/* Short Weierstrass curves (supporting ECP, ECDH, ECDSA) */
|
||||
// #define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
/* Montgomery curves (supporting ECP) */
|
||||
// #define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_CURVE448_ENABLED
|
||||
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
|
||||
#define MBEDTLS_GENPRIME
|
||||
// #define MBEDTLS_PKCS1_V15
|
||||
// #define MBEDTLS_PKCS1_V21
|
||||
|
||||
#define MBEDTLS_MD_C
|
||||
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_OID_C
|
||||
|
||||
// #define MBEDTLS_CHACHA20_C
|
||||
// #define MBEDTLS_CHACHAPOLY_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_DES_C
|
||||
#define MBEDTLS_DHM_C
|
||||
|
||||
#define MBEDTLS_ECDH_C
|
||||
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ECP_C
|
||||
|
||||
#define MBEDTLS_GCM_C
|
||||
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_MD5_C
|
||||
|
||||
// #define MBEDTLS_PEM_PARSE_C
|
||||
// #define MBEDTLS_PEM_WRITE_C
|
||||
|
||||
// #define MBEDTLS_PLATFORM_MEMORY
|
||||
// #define MBEDTLS_PLATFORM_C
|
||||
|
||||
// #define MBEDTLS_RIPEMD160_C
|
||||
// #define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
|
||||
#define MBEDTLS_ERROR_C
|
||||
@@ -1,21 +0,0 @@
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,41 +0,0 @@
|
||||
micro-ecc
|
||||
==========
|
||||
|
||||
A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
|
||||
|
||||
The static version of micro-ecc (ie, where the curve was selected at compile-time) can be found in the "static" branch.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Resistant to known side-channel attacks.
|
||||
* Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms.
|
||||
* Supports 8, 32, and 64-bit architectures.
|
||||
* Small code size.
|
||||
* No dynamic memory allocation.
|
||||
* Support for 5 standard curves: secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1.
|
||||
* BSD 2-clause license.
|
||||
|
||||
Usage Notes
|
||||
-----------
|
||||
### Point Representation ###
|
||||
Compressed points are represented in the standard format as defined in http://www.secg.org/sec1-v2.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_decompress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
|
||||
|
||||
Private keys are represented in the standard format.
|
||||
|
||||
### Using the Code ###
|
||||
|
||||
I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions.
|
||||
|
||||
For use with Arduino, you can use the Library Manager to download micro-ecc (**Sketch**=>**Include Library**=>**Manage Libraries**). You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
|
||||
|
||||
See uECC.h for documentation for each function.
|
||||
|
||||
### Compilation Notes ###
|
||||
|
||||
* Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013).
|
||||
* If you want to change the defaults for any of the uECC compile-time options (such as `uECC_OPTIMIZATION_LEVEL`), you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_OPTIMIZATION_LEVEL=3` or whatever).
|
||||
* When compiling for a Thumb-1 platform, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
|
||||
* When compiling for an ARM/Thumb-2 platform with `uECC_OPTIMIZATION_LEVEL` >= 3, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
|
||||
* When compiling for AVR, you must have optimizations enabled (compile with `-O1` or higher).
|
||||
* When building for Windows, you will need to link in the `advapi32.lib` system library.
|
||||
@@ -1,821 +0,0 @@
|
||||
/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _UECC_ASM_ARM_H_
|
||||
#define _UECC_ASM_ARM_H_
|
||||
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
#define uECC_MIN_WORDS 8
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 7
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 6
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
#undef uECC_MIN_WORDS
|
||||
#define uECC_MIN_WORDS 5
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb)
|
||||
#define REG_RW "+l"
|
||||
#define REG_WRITE "=l"
|
||||
#else
|
||||
#define REG_RW "+r"
|
||||
#define REG_WRITE "=r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define REG_RW_LO "+l"
|
||||
#define REG_WRITE_LO "=l"
|
||||
#else
|
||||
#define REG_RW_LO "+r"
|
||||
#define REG_WRITE_LO "=r"
|
||||
#endif
|
||||
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
#define RESUME_SYNTAX
|
||||
#else
|
||||
#define RESUME_SYNTAX ".syntax divided \n\t"
|
||||
#endif
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL >= 2)
|
||||
|
||||
uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"adr %[left], 1f \n\t"
|
||||
".align 4 \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
#endif
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adds %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"bx %[jump] \n\t"
|
||||
#endif
|
||||
"1: \n\t"
|
||||
REPEAT(DEC(uECC_MAX_WORDS),
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"adcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t")
|
||||
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
[jump] REG_RW_LO (jump),
|
||||
#endif
|
||||
[carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
|
||||
[right] REG_WRITE_LO (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wredundant-decls"
|
||||
uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
#if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
|
||||
#else /* ARM */
|
||||
uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
|
||||
#endif
|
||||
#endif
|
||||
uint32_t carry;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"movs %[carry], #0 \n\t"
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"adr %[left], 1f \n\t"
|
||||
".align 4 \n\t"
|
||||
"adds %[jump], %[left] \n\t"
|
||||
#endif
|
||||
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"subs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t"
|
||||
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
"bx %[jump] \n\t"
|
||||
#endif
|
||||
"1: \n\t"
|
||||
REPEAT(DEC(uECC_MAX_WORDS),
|
||||
"ldmia %[lptr]!, {%[left]} \n\t"
|
||||
"ldmia %[rptr]!, {%[right]} \n\t"
|
||||
"sbcs %[left], %[right] \n\t"
|
||||
"stmia %[dptr]!, {%[left]} \n\t")
|
||||
|
||||
"adcs %[carry], %[carry] \n\t"
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
|
||||
#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
|
||||
[jump] REG_RW_LO (jump),
|
||||
#endif
|
||||
[carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
|
||||
[right] REG_WRITE_LO (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
|
||||
(for some reason...) */
|
||||
}
|
||||
#define asm_sub 1
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL >= 3)
|
||||
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
|
||||
#if uECC_ARM_USE_UMAAL
|
||||
#include "asm_arm_mult_square_umaal.inc"
|
||||
#else
|
||||
#include "asm_arm_mult_square.inc"
|
||||
#endif
|
||||
|
||||
#if (uECC_OPTIMIZATION_LEVEL == 3)
|
||||
|
||||
uECC_VLI_API void uECC_vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_MULT_ASM_5
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_MULT_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_MULT_ASM_6
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_MULT_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_MULT_ASM_7
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_MULT_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_MULT_ASM_8
|
||||
#endif
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
#if (uECC_MIN_WORDS == 5)
|
||||
FAST_SQUARE_ASM_5
|
||||
#if (uECC_MAX_WORDS > 5)
|
||||
FAST_SQUARE_ASM_5_TO_6
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 6)
|
||||
FAST_SQUARE_ASM_6
|
||||
#if (uECC_MAX_WORDS > 6)
|
||||
FAST_SQUARE_ASM_6_TO_7
|
||||
#endif
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 7)
|
||||
FAST_SQUARE_ASM_7
|
||||
#if (uECC_MAX_WORDS > 7)
|
||||
FAST_SQUARE_ASM_7_TO_8
|
||||
#endif
|
||||
#elif (uECC_MIN_WORDS == 8)
|
||||
FAST_SQUARE_ASM_8
|
||||
#endif
|
||||
|
||||
"1: \n\t"
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#else /* (uECC_OPTIMIZATION_LEVEL > 3) */
|
||||
|
||||
uECC_VLI_API void uECC_vli_mult(uint32_t *result,
|
||||
const uint32_t *left,
|
||||
const uint32_t *right,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register const uint32_t *r2 __asm__("r2") = right;
|
||||
register uint32_t r3 __asm__("r3") = num_words;
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
if (num_words == 5) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_5
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
if (num_words == 6) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_6
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
if (num_words == 7) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_7
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
if (num_words == 8) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_MULT_ASM_8
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2)
|
||||
: "r" (r3)
|
||||
: "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
register uint32_t *r0 __asm__("r0") = result;
|
||||
register const uint32_t *r1 __asm__("r1") = left;
|
||||
register uint32_t r2 __asm__("r2") = num_words;
|
||||
|
||||
#if uECC_SUPPORTS_secp160r1
|
||||
if (num_words == 5) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_5
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp192r1
|
||||
if (num_words == 6) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_6
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if uECC_SUPPORTS_secp224r1
|
||||
if (num_words == 7) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_7
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
|
||||
if (num_words == 8) {
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
FAST_SQUARE_ASM_8
|
||||
RESUME_SYNTAX
|
||||
: "+r" (r0), "+r" (r1)
|
||||
: "r" (r2)
|
||||
: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL > 3) */
|
||||
|
||||
#endif /* uECC_PLATFORM != uECC_arm_thumb */
|
||||
|
||||
#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */
|
||||
|
||||
/* ---- "Small" implementations ---- */
|
||||
|
||||
#if !asm_add
|
||||
uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 0;
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"1: \n\t"
|
||||
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
|
||||
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
|
||||
"lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
|
||||
"adcs %[left], %[left], %[right] \n\t" /* Add with carry. */
|
||||
"adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
|
||||
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
|
||||
"subs %[ctr], #1 \n\t" /* Decrement counter. */
|
||||
"bne 1b \n\t" /* Loop until counter == 0. */
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[ctr] REG_RW (num_words), [carry] REG_RW (carry),
|
||||
[left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return carry;
|
||||
}
|
||||
#define asm_add 1
|
||||
#endif
|
||||
|
||||
#if !asm_sub
|
||||
uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
|
||||
uint32_t left_word;
|
||||
uint32_t right_word;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"1: \n\t"
|
||||
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
|
||||
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
|
||||
"lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
|
||||
"sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */
|
||||
"adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
|
||||
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
|
||||
"subs %[ctr], #1 \n\t" /* Decrement counter. */
|
||||
"bne 1b \n\t" /* Loop until counter == 0. */
|
||||
RESUME_SYNTAX
|
||||
: [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
|
||||
[ctr] REG_RW (num_words), [carry] REG_RW (carry),
|
||||
[left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
|
||||
:
|
||||
: "cc", "memory"
|
||||
);
|
||||
return !carry;
|
||||
}
|
||||
#define asm_sub 1
|
||||
#endif
|
||||
|
||||
#if !asm_mult
|
||||
uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t k = 0;
|
||||
uint32_t i;
|
||||
uint32_t t0, t1;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[i], #0 \n\t" /* i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[i], %[k] \n\t" /* i = k */
|
||||
"subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
|
||||
|
||||
"ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */
|
||||
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
|
||||
|
||||
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
|
||||
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"adds %[i], #4 \n\t" /* i += 4 */
|
||||
"cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
|
||||
"bgt 4f \n\t" /* if so, exit the loop */
|
||||
"cmp %[i], %[k] \n\t" /* i <= k? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"4: \n\t" /* end inner loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
|
||||
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
|
||||
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
|
||||
"movs %[c2], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[k], #4 \n\t" /* k += 4 */
|
||||
"cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
RESUME_SYNTAX
|
||||
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
|
||||
[k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
|
||||
: [result] "r" (result), [left] "r" (left), [right] "r" (right),
|
||||
[last_word] "r" ((num_words - 1) * 4)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#else /* Thumb-1 */
|
||||
uint32_t r4, r5, r6, r7;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"subs %[r3], #1 \n\t" /* r3 = num_words - 1 */
|
||||
"lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */
|
||||
"mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */
|
||||
"lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */
|
||||
"mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */
|
||||
"movs %[r3], #0 \n\t" /* c0 = 0 */
|
||||
"movs %[r4], #0 \n\t" /* c1 = 0 */
|
||||
"movs %[r5], #0 \n\t" /* c2 = 0 */
|
||||
"movs %[r6], #0 \n\t" /* k = 0 */
|
||||
|
||||
"push {%[r0]} \n\t" /* keep result on the stack */
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[r7], #0 \n\t" /* r7 = i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[r7], %[r6] \n\t" /* r7 = k */
|
||||
"mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
|
||||
"subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"mov r10, %[r3] \n\t"
|
||||
"mov r11, %[r4] \n\t"
|
||||
"mov r12, %[r5] \n\t"
|
||||
"mov r14, %[r6] \n\t"
|
||||
"subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */
|
||||
|
||||
"ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */
|
||||
"ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */
|
||||
|
||||
"lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */
|
||||
"uxth %[r0], %[r0] \n\t" /* r0 = a0 */
|
||||
|
||||
"lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */
|
||||
"uxth %[r4], %[r4] \n\t" /* r4 = b0 */
|
||||
|
||||
"movs %[r6], %[r3] \n\t" /* r6 = a1 */
|
||||
"muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */
|
||||
"muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */
|
||||
"muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */
|
||||
"muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */
|
||||
|
||||
/* Add middle terms */
|
||||
"lsls %[r4], %[r3], #16 \n\t"
|
||||
"lsrs %[r3], %[r3], #16 \n\t"
|
||||
"adds %[r0], %[r4] \n\t"
|
||||
"adcs %[r6], %[r3] \n\t"
|
||||
|
||||
"lsls %[r4], %[r5], #16 \n\t"
|
||||
"lsrs %[r5], %[r5], #16 \n\t"
|
||||
"adds %[r0], %[r4] \n\t"
|
||||
"adcs %[r6], %[r5] \n\t"
|
||||
|
||||
"mov %[r3], r10\n\t"
|
||||
"mov %[r4], r11\n\t"
|
||||
"mov %[r5], r12\n\t"
|
||||
"adds %[r3], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */
|
||||
"movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */
|
||||
"adcs %[r5], %[r0] \n\t" /* add carry to c2 */
|
||||
|
||||
"mov %[r6], r14\n\t" /* r6 = k */
|
||||
|
||||
"adds %[r7], #4 \n\t" /* i += 4 */
|
||||
"cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */
|
||||
"bgt 4f \n\t" /* if so, exit the loop */
|
||||
"cmp %[r7], %[r6] \n\t" /* i <= k? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"4: \n\t" /* end inner loop */
|
||||
|
||||
"ldr %[r0], [sp, #0] \n\t" /* r0 = result */
|
||||
|
||||
"str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */
|
||||
"mov %[r3], %[r4] \n\t" /* c0 = c1 */
|
||||
"mov %[r4], %[r5] \n\t" /* c1 = c2 */
|
||||
"movs %[r5], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[r6], #4 \n\t" /* k += 4 */
|
||||
"cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
"pop {%[r0]} \n\t" /* pop result off the stack */
|
||||
|
||||
".syntax divided \n\t"
|
||||
: [r3] "+l" (num_words), [r4] "=&l" (r4),
|
||||
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
|
||||
: [r0] "l" (result), [r1] "l" (left), [r2] "l" (right)
|
||||
: "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#define asm_mult 1
|
||||
#endif
|
||||
|
||||
#if uECC_SQUARE_FUNC
|
||||
#if !asm_square
|
||||
uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
wordcount_t num_words) {
|
||||
#if (uECC_PLATFORM != uECC_arm_thumb)
|
||||
uint32_t c0 = 0;
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t k = 0;
|
||||
uint32_t i, tt;
|
||||
uint32_t t0, t1;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[i], #0 \n\t" /* i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[i], %[k] \n\t" /* i = k */
|
||||
"subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
|
||||
|
||||
"ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */
|
||||
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
|
||||
|
||||
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
|
||||
|
||||
"cmp %[i], %[tt] \n\t" /* (i < k - i) ? */
|
||||
"bge 4f \n\t" /* if i >= k - i, skip */
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"4: \n\t"
|
||||
"adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
|
||||
"adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
|
||||
|
||||
"adds %[i], #4 \n\t" /* i += 4 */
|
||||
"cmp %[i], %[k] \n\t" /* i >= k? */
|
||||
"bge 5f \n\t" /* if so, exit the loop */
|
||||
"subs %[tt], %[k], %[i] \n\t" /* tt = k - i */
|
||||
"cmp %[i], %[tt] \n\t" /* i <= k - i? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"5: \n\t" /* end inner loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
|
||||
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
|
||||
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
|
||||
"movs %[c2], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[k], #4 \n\t" /* k += 4 */
|
||||
"cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
RESUME_SYNTAX
|
||||
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
|
||||
[k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
|
||||
: [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#else
|
||||
uint32_t r3, r4, r5, r6, r7;
|
||||
|
||||
__asm__ volatile (
|
||||
".syntax unified \n\t"
|
||||
"subs %[r2], #1 \n\t" /* r2 = num_words - 1 */
|
||||
"lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */
|
||||
"mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */
|
||||
"lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */
|
||||
"mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */
|
||||
"movs %[r2], #0 \n\t" /* c0 = 0 */
|
||||
"movs %[r3], #0 \n\t" /* c1 = 0 */
|
||||
"movs %[r4], #0 \n\t" /* c2 = 0 */
|
||||
"movs %[r5], #0 \n\t" /* k = 0 */
|
||||
|
||||
"push {%[r0]} \n\t" /* keep result on the stack */
|
||||
|
||||
"1: \n\t" /* outer loop (k < num_words) */
|
||||
"movs %[r6], #0 \n\t" /* r6 = i = 0 */
|
||||
"b 3f \n\t"
|
||||
|
||||
"2: \n\t" /* outer loop (k >= num_words) */
|
||||
"movs %[r6], %[r5] \n\t" /* r6 = k */
|
||||
"mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
|
||||
"subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */
|
||||
|
||||
"3: \n\t" /* inner loop */
|
||||
"mov r10, %[r2] \n\t"
|
||||
"mov r11, %[r3] \n\t"
|
||||
"mov r12, %[r4] \n\t"
|
||||
"mov r14, %[r5] \n\t"
|
||||
"subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
|
||||
|
||||
"ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */
|
||||
"ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */
|
||||
|
||||
"lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */
|
||||
"uxth %[r0], %[r0] \n\t" /* r0 = a0 */
|
||||
|
||||
"lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */
|
||||
"uxth %[r3], %[r3] \n\t" /* r3 = b0 */
|
||||
|
||||
"movs %[r5], %[r2] \n\t" /* r5 = a1 */
|
||||
"muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */
|
||||
"muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */
|
||||
"muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */
|
||||
"muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */
|
||||
|
||||
/* Add middle terms */
|
||||
"lsls %[r3], %[r2], #16 \n\t"
|
||||
"lsrs %[r2], %[r2], #16 \n\t"
|
||||
"adds %[r0], %[r3] \n\t"
|
||||
"adcs %[r5], %[r2] \n\t"
|
||||
|
||||
"lsls %[r3], %[r4], #16 \n\t"
|
||||
"lsrs %[r4], %[r4], #16 \n\t"
|
||||
"adds %[r0], %[r3] \n\t"
|
||||
"adcs %[r5], %[r4] \n\t"
|
||||
|
||||
/* Add to acc, doubling if necessary */
|
||||
"mov %[r2], r10\n\t"
|
||||
"mov %[r3], r11\n\t"
|
||||
"mov %[r4], r12\n\t"
|
||||
|
||||
"cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */
|
||||
"bge 4f \n\t" /* if i >= k - i, skip */
|
||||
"movs %[r7], #0 \n\t" /* r7 = 0 */
|
||||
"adds %[r2], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[r4], %[r7] \n\t" /* add carry to c2 */
|
||||
"4: \n\t"
|
||||
"movs %[r7], #0 \n\t" /* r7 = 0 */
|
||||
"adds %[r2], %[r0] \n\t" /* add low word to c0 */
|
||||
"adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
|
||||
"adcs %[r4], %[r7] \n\t" /* add carry to c2 */
|
||||
|
||||
"mov %[r5], r14\n\t" /* r5 = k */
|
||||
|
||||
"adds %[r6], #4 \n\t" /* i += 4 */
|
||||
"cmp %[r6], %[r5] \n\t" /* i >= k? */
|
||||
"bge 5f \n\t" /* if so, exit the loop */
|
||||
"subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
|
||||
"cmp %[r6], %[r7] \n\t" /* i <= k - i? */
|
||||
"ble 3b \n\t" /* if so, continue looping */
|
||||
|
||||
"5: \n\t" /* end inner loop */
|
||||
|
||||
"ldr %[r0], [sp, #0] \n\t" /* r0 = result */
|
||||
|
||||
"str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */
|
||||
"mov %[r2], %[r3] \n\t" /* c0 = c1 */
|
||||
"mov %[r3], %[r4] \n\t" /* c1 = c2 */
|
||||
"movs %[r4], #0 \n\t" /* c2 = 0 */
|
||||
"adds %[r5], #4 \n\t" /* k += 4 */
|
||||
"cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
|
||||
"ble 1b \n\t" /* if so, loop back, start with i = 0 */
|
||||
"cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
|
||||
"ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
|
||||
/* end outer loop */
|
||||
|
||||
"str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */
|
||||
"pop {%[r0]} \n\t" /* pop result off the stack */
|
||||
|
||||
".syntax divided \n\t"
|
||||
: [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4),
|
||||
[r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
|
||||
: [r0] "l" (result), [r1] "l" (left)
|
||||
: "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
#define asm_square 1
|
||||
#endif
|
||||
#endif /* uECC_SQUARE_FUNC */
|
||||
|
||||
#endif /* _UECC_ASM_ARM_H_ */
|
||||