mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-10 05:59:08 -07:00
Even more ported apps
This commit is contained in:
21
applications/external/flashlight/LICENSE
vendored
21
applications/external/flashlight/LICENSE
vendored
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 MX
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
17
applications/external/flashlight/application.fam
vendored
17
applications/external/flashlight/application.fam
vendored
@@ -1,17 +0,0 @@
|
||||
App(
|
||||
appid="flashlight",
|
||||
name="[LED] Flashlight",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="flashlight_app",
|
||||
cdefines=["APP_FLASHLIGHT"],
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
stack_size=2 * 1024,
|
||||
fap_icon="flash10px.png",
|
||||
fap_category="GPIO",
|
||||
fap_author="@xMasterX",
|
||||
fap_weburl="https://github.com/xMasterX/flipper-flashlight",
|
||||
fap_version="1.0",
|
||||
fap_description="Enables 3.3v on pin 7/C3 when you press Ok and leaves it on when you exit app",
|
||||
)
|
||||
BIN
applications/external/flashlight/flash10px.png
vendored
BIN
applications/external/flashlight/flash10px.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 148 B |
130
applications/external/flashlight/flashlight.c
vendored
130
applications/external/flashlight/flashlight.c
vendored
@@ -1,130 +0,0 @@
|
||||
// by @xMasterX
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
#include <stdlib.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
EventType type;
|
||||
InputEvent input;
|
||||
} PluginEvent;
|
||||
|
||||
typedef struct {
|
||||
FuriMutex* mutex;
|
||||
bool is_on;
|
||||
} PluginState;
|
||||
|
||||
static void render_callback(Canvas* const canvas, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
const PluginState* plugin_state = ctx;
|
||||
furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Flashlight");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
if(!plugin_state->is_on) {
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 64, 28, AlignCenter, AlignTop, "Press OK button turn on");
|
||||
} else {
|
||||
elements_multiline_text_aligned(canvas, 64, 28, AlignCenter, AlignTop, "Light is on!");
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 64, 40, AlignCenter, AlignTop, "Press OK button to off");
|
||||
}
|
||||
|
||||
furi_mutex_release(plugin_state->mutex);
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
|
||||
PluginEvent event = {.type = EventTypeKey, .input = *input_event};
|
||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void flash_toggle(PluginState* const plugin_state) {
|
||||
furi_hal_gpio_write(&gpio_ext_pc3, false);
|
||||
furi_hal_gpio_init(&gpio_ext_pc3, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
|
||||
if(plugin_state->is_on) {
|
||||
furi_hal_gpio_write(&gpio_ext_pc3, false);
|
||||
plugin_state->is_on = false;
|
||||
} else {
|
||||
furi_hal_gpio_write(&gpio_ext_pc3, true);
|
||||
plugin_state->is_on = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t flashlight_app() {
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
|
||||
|
||||
PluginState* plugin_state = malloc(sizeof(PluginState));
|
||||
|
||||
plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
if(!plugin_state->mutex) {
|
||||
FURI_LOG_E("flashlight", "cannot create mutex\r\n");
|
||||
furi_message_queue_free(event_queue);
|
||||
free(plugin_state);
|
||||
return 255;
|
||||
}
|
||||
|
||||
// Set system callbacks
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, render_callback, plugin_state);
|
||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
PluginEvent event;
|
||||
for(bool processing = true; processing;) {
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
||||
|
||||
furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
|
||||
|
||||
if(event_status == FuriStatusOk) {
|
||||
// press events
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.input.type == InputTypePress) {
|
||||
switch(event.input.key) {
|
||||
case InputKeyUp:
|
||||
case InputKeyDown:
|
||||
case InputKeyRight:
|
||||
case InputKeyLeft:
|
||||
break;
|
||||
case InputKeyOk:
|
||||
flash_toggle(plugin_state);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
processing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view_port_update(view_port);
|
||||
furi_mutex_release(plugin_state->mutex);
|
||||
}
|
||||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
furi_record_close(RECORD_GUI);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_mutex_free(plugin_state->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
applications/external/flipbip/LICENSE
vendored
21
applications/external/flipbip/LICENSE
vendored
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Struan Clark
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
21
applications/external/flipbip/application.fam
vendored
21
applications/external/flipbip/application.fam
vendored
@@ -1,21 +0,0 @@
|
||||
App(
|
||||
appid="flipbip",
|
||||
name="FlipBIP Crypto Wallet",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="flipbip_app",
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
stack_size=3 * 1024,
|
||||
fap_icon="flipbip_10px.png",
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
name="crypto",
|
||||
),
|
||||
],
|
||||
fap_category="Tools",
|
||||
fap_author="Struan Clark (xtruan)",
|
||||
fap_weburl="https://github.com/xtruan/FlipBIP",
|
||||
fap_version=(1, 13),
|
||||
fap_description="Crypto wallet for Flipper",
|
||||
)
|
||||
204
applications/external/flipbip/flipbip.c
vendored
204
applications/external/flipbip/flipbip.c
vendored
@@ -1,204 +0,0 @@
|
||||
#include "flipbip.h"
|
||||
#include "helpers/flipbip_file.h"
|
||||
// From: lib/crypto
|
||||
#include <memzero.h>
|
||||
#include <bip39.h>
|
||||
|
||||
#define MNEMONIC_MENU_DEFAULT "Import mnemonic seed"
|
||||
#define MNEMONIC_MENU_SUCCESS "Import seed (success)"
|
||||
#define MNEMONIC_MENU_FAILURE "Import seed (failed!)"
|
||||
|
||||
bool flipbip_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
FlipBip* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
void flipbip_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
FlipBip* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
//leave app if back button pressed
|
||||
bool flipbip_navigation_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
FlipBip* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void text_input_callback(void* context) {
|
||||
furi_assert(context);
|
||||
FlipBip* app = context;
|
||||
bool handled = false;
|
||||
|
||||
// check that there is text in the input
|
||||
if(strlen(app->input_text) > 0) {
|
||||
if(app->input_state == FlipBipTextInputPassphrase) {
|
||||
if(app->passphrase == FlipBipPassphraseOn) {
|
||||
strcpy(app->passphrase_text, app->input_text);
|
||||
}
|
||||
// clear input text
|
||||
memzero(app->input_text, TEXT_BUFFER_SIZE);
|
||||
// reset input state
|
||||
app->input_state = FlipBipTextInputDefault;
|
||||
handled = true;
|
||||
// switch back to settings view
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FlipBipViewIdSettings);
|
||||
} else if(app->input_state == FlipBipTextInputMnemonic) {
|
||||
if(app->import_from_mnemonic == 1) {
|
||||
strcpy(app->import_mnemonic_text, app->input_text);
|
||||
|
||||
int status = FlipBipStatusSuccess;
|
||||
// Check if the mnemonic is valid
|
||||
if(mnemonic_check(app->import_mnemonic_text) == 0)
|
||||
status = FlipBipStatusMnemonicCheckError; // 13 = mnemonic check error
|
||||
// Save the mnemonic to persistent storage
|
||||
else if(!flipbip_save_file_secure(app->import_mnemonic_text))
|
||||
status = FlipBipStatusSaveError; // 12 = save error
|
||||
|
||||
if(status == FlipBipStatusSuccess) {
|
||||
app->mnemonic_menu_text = MNEMONIC_MENU_SUCCESS;
|
||||
//notification_message(app->notification, &sequence_blink_cyan_100);
|
||||
//flipbip_play_happy_bump(app);
|
||||
} else {
|
||||
app->mnemonic_menu_text = MNEMONIC_MENU_FAILURE;
|
||||
//notification_message(app->notification, &sequence_blink_red_100);
|
||||
//flipbip_play_long_bump(app);
|
||||
}
|
||||
|
||||
memzero(app->import_mnemonic_text, TEXT_BUFFER_SIZE);
|
||||
}
|
||||
// clear input text
|
||||
memzero(app->input_text, TEXT_BUFFER_SIZE);
|
||||
// reset input state
|
||||
app->input_state = FlipBipTextInputDefault;
|
||||
handled = true;
|
||||
// exit scene 1 instance that's being used for text input and go back to menu
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
//view_dispatcher_switch_to_view(app->view_dispatcher, FlipBipViewIdMenu);
|
||||
}
|
||||
}
|
||||
|
||||
if(!handled) {
|
||||
// clear input text
|
||||
memzero(app->input_text, TEXT_BUFFER_SIZE);
|
||||
// reset input state
|
||||
app->input_state = FlipBipTextInputDefault;
|
||||
// something went wrong, switch to menu view
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FlipBipViewIdMenu);
|
||||
}
|
||||
}
|
||||
|
||||
FlipBip* flipbip_app_alloc() {
|
||||
FlipBip* app = malloc(sizeof(FlipBip));
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
//app->notification = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// Turn backlight on, believe me this makes testing your app easier
|
||||
//notification_message(app->notification, &sequence_display_backlight_on);
|
||||
|
||||
// Scene additions
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
|
||||
app->scene_manager = scene_manager_alloc(&flipbip_scene_handlers, app);
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, flipbip_navigation_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, flipbip_tick_event_callback, 100);
|
||||
view_dispatcher_set_custom_event_callback(app->view_dispatcher, flipbip_custom_event_callback);
|
||||
app->submenu = submenu_alloc();
|
||||
|
||||
// Settings
|
||||
app->bip39_strength = FlipBipStrength256; // 256 bits (24 words)
|
||||
app->passphrase = FlipBipPassphraseOff;
|
||||
|
||||
// Main menu
|
||||
app->bip44_coin = FlipBipCoinBTC0; // 0 (BTC)
|
||||
app->overwrite_saved_seed = 0;
|
||||
app->import_from_mnemonic = 0;
|
||||
app->mnemonic_menu_text = MNEMONIC_MENU_DEFAULT;
|
||||
|
||||
// Text input
|
||||
app->input_state = FlipBipTextInputDefault;
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, FlipBipViewIdMenu, submenu_get_view(app->submenu));
|
||||
app->flipbip_scene_1 = flipbip_scene_1_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, FlipBipViewIdScene1, flipbip_scene_1_get_view(app->flipbip_scene_1));
|
||||
app->variable_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
FlipBipViewIdSettings,
|
||||
variable_item_list_get_view(app->variable_item_list));
|
||||
|
||||
app->text_input = text_input_alloc();
|
||||
text_input_set_result_callback(
|
||||
app->text_input,
|
||||
text_input_callback,
|
||||
(void*)app,
|
||||
app->input_text,
|
||||
TEXT_BUFFER_SIZE,
|
||||
// clear default text
|
||||
true);
|
||||
//text_input_set_header_text(app->text_input, "Input");
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, FlipBipViewIdTextInput, text_input_get_view(app->text_input));
|
||||
|
||||
// End Scene Additions
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void flipbip_app_free(FlipBip* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Scene manager
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
text_input_free(app->text_input);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FlipBipViewIdMenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FlipBipViewIdScene1);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FlipBipViewIdSettings);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FlipBipViewIdTextInput);
|
||||
submenu_free(app->submenu);
|
||||
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
app->gui = NULL;
|
||||
//app->notification = NULL;
|
||||
|
||||
//Remove whatever is left
|
||||
memzero(app, sizeof(FlipBip));
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t flipbip_app(void* p) {
|
||||
UNUSED(p);
|
||||
FlipBip* app = flipbip_app_alloc();
|
||||
|
||||
// Disabled because causes exit on custom firmwares such as RM
|
||||
/*if(!furi_hal_region_is_provisioned()) {
|
||||
flipbip_app_free(app);
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, FlipBipSceneMenu); //Start with menu
|
||||
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
flipbip_app_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
88
applications/external/flipbip/flipbip.h
vendored
88
applications/external/flipbip/flipbip.h
vendored
@@ -1,88 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
#include <stdlib.h>
|
||||
//#include <notification/notification_messages.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include "scenes/flipbip_scene.h"
|
||||
#include "views/flipbip_scene_1.h"
|
||||
|
||||
#define FLIPBIP_VERSION "v1.13"
|
||||
|
||||
#define COIN_BTC 0
|
||||
#define COIN_DOGE 3
|
||||
#define COIN_ETH 60
|
||||
#define COIN_ZEC 133
|
||||
|
||||
#define TEXT_BUFFER_SIZE 256
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
// NotificationApp* notification;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
SceneManager* scene_manager;
|
||||
VariableItemList* variable_item_list;
|
||||
TextInput* text_input;
|
||||
FlipBipScene1* flipbip_scene_1;
|
||||
char* mnemonic_menu_text;
|
||||
// Settings options
|
||||
int bip39_strength;
|
||||
int passphrase;
|
||||
// Main menu options
|
||||
int bip44_coin;
|
||||
int overwrite_saved_seed;
|
||||
int import_from_mnemonic;
|
||||
// Text input
|
||||
int input_state;
|
||||
char passphrase_text[TEXT_BUFFER_SIZE];
|
||||
char import_mnemonic_text[TEXT_BUFFER_SIZE];
|
||||
char input_text[TEXT_BUFFER_SIZE];
|
||||
} FlipBip;
|
||||
|
||||
typedef enum {
|
||||
FlipBipViewIdStartscreen,
|
||||
FlipBipViewIdMenu,
|
||||
FlipBipViewIdScene1,
|
||||
FlipBipViewIdSettings,
|
||||
FlipBipViewIdTextInput,
|
||||
} FlipBipViewId;
|
||||
|
||||
typedef enum {
|
||||
FlipBipStrength128,
|
||||
FlipBipStrength192,
|
||||
FlipBipStrength256,
|
||||
} FlipBipStrengthState;
|
||||
|
||||
typedef enum {
|
||||
FlipBipPassphraseOff,
|
||||
FlipBipPassphraseOn,
|
||||
} FlipBipPassphraseState;
|
||||
|
||||
typedef enum {
|
||||
FlipBipCoinBTC0,
|
||||
FlipBipCoinETH60,
|
||||
FlipBipCoinDOGE3,
|
||||
FlipBipCoinZEC133,
|
||||
} FlipBipCoin;
|
||||
|
||||
typedef enum {
|
||||
FlipBipTextInputDefault,
|
||||
FlipBipTextInputPassphrase,
|
||||
FlipBipTextInputMnemonic
|
||||
} FlipBipTextInputState;
|
||||
|
||||
typedef enum {
|
||||
FlipBipStatusSuccess = 0,
|
||||
FlipBipStatusReturn = 10,
|
||||
FlipBipStatusLoadError = 11,
|
||||
FlipBipStatusSaveError = 12,
|
||||
FlipBipStatusMnemonicCheckError = 13,
|
||||
} FlipBipStatus;
|
||||
BIN
applications/external/flipbip/flipbip_10px.png
vendored
BIN
applications/external/flipbip/flipbip_10px.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 183 B |
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
FlipBipCustomEventScene1Up,
|
||||
FlipBipCustomEventScene1Down,
|
||||
FlipBipCustomEventScene1Left,
|
||||
FlipBipCustomEventScene1Right,
|
||||
FlipBipCustomEventScene1Ok,
|
||||
FlipBipCustomEventScene1Back,
|
||||
} FlipBipCustomEvent;
|
||||
314
applications/external/flipbip/helpers/flipbip_file.c
vendored
314
applications/external/flipbip/helpers/flipbip_file.c
vendored
@@ -1,314 +0,0 @@
|
||||
#include "flipbip_file.h"
|
||||
#include <storage/storage.h>
|
||||
#include <loader/loader.h>
|
||||
#include "../helpers/flipbip_string.h"
|
||||
// From: lib/crypto
|
||||
#include <memzero.h>
|
||||
#include <rand.h>
|
||||
|
||||
// #define FLIPBIP_APP_BASE_FOLDER APP_DATA_PATH("flipbip")
|
||||
#define FLIPBIP_APP_BASE_FOLDER EXT_PATH("apps_data/flipbip")
|
||||
#define FLIPBIP_APP_BASE_FOLDER_PATH(path) FLIPBIP_APP_BASE_FOLDER "/" path
|
||||
#define FLIPBIP_DAT_FILE_NAME ".flipbip.dat"
|
||||
// #define FLIPBIP_DAT_FILE_NAME ".flipbip.dat.txt"
|
||||
#define FLIPBIP_DAT_FILE_NAME_BAK ".flipbip.dat.bak"
|
||||
#define FLIPBIP_KEY_FILE_NAME ".flipbip.key"
|
||||
// #define FLIPBIP_KEY_FILE_NAME ".flipbip.key.txt"
|
||||
#define FLIPBIP_KEY_FILE_NAME_BAK ".flipbip.key.bak"
|
||||
#define FLIPBIP_DAT_PATH FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_DAT_FILE_NAME)
|
||||
#define FLIPBIP_DAT_PATH_BAK FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_DAT_FILE_NAME_BAK)
|
||||
#define FLIPBIP_KEY_PATH FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_KEY_FILE_NAME)
|
||||
#define FLIPBIP_KEY_PATH_BAK FLIPBIP_APP_BASE_FOLDER_PATH(FLIPBIP_KEY_FILE_NAME_BAK)
|
||||
|
||||
const char* TEXT_QRFILE = "Filetype: QRCode\n"
|
||||
"Version: 0\n"
|
||||
"Message: "; // 37 chars + 1 null
|
||||
#define FILE_HLEN 4
|
||||
#define FILE_KLEN 256
|
||||
#define FILE_SLEN 512
|
||||
#define FILE_MAX_PATH_LEN 48
|
||||
#define FILE_MAX_QRFILE_CONTENT 90
|
||||
const char* FILE_HSTR = "fb01";
|
||||
const char* FILE_K1 = "fb0131d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a"
|
||||
"baefe6d9ceb651842260e0d1e05e3b90d15e7d5ffaaabc0207bf200a117793a2";
|
||||
|
||||
bool flipbip_load_file(
|
||||
char* settings,
|
||||
size_t slen,
|
||||
const FlipBipFile file_type,
|
||||
const char* file_name) {
|
||||
bool ret = false;
|
||||
const char* path;
|
||||
if(file_type == FlipBipFileKey) {
|
||||
path = FLIPBIP_KEY_PATH;
|
||||
} else if(file_type == FlipBipFileDat) {
|
||||
path = FLIPBIP_DAT_PATH;
|
||||
} else {
|
||||
char path_buf[FILE_MAX_PATH_LEN] = {0};
|
||||
strcpy(path_buf, FLIPBIP_APP_BASE_FOLDER); // 22
|
||||
strcpy(path_buf + strlen(path_buf), "/");
|
||||
strcpy(path_buf + strlen(path_buf), file_name);
|
||||
path = path_buf;
|
||||
}
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
File* settings_file = storage_file_alloc(fs_api);
|
||||
if(storage_file_open(settings_file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
char chr;
|
||||
size_t i = 0;
|
||||
while((storage_file_read(settings_file, &chr, 1) == 1) &&
|
||||
!storage_file_eof(settings_file) && !isspace(chr)) {
|
||||
if(i < slen) {
|
||||
settings[i] = chr;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ret = true;
|
||||
} else {
|
||||
memzero(settings, strlen(settings));
|
||||
settings[0] = '\0';
|
||||
ret = false;
|
||||
}
|
||||
storage_file_close(settings_file);
|
||||
storage_file_free(settings_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
if(strlen(settings) > 0) {
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
FileInfo layout_file_info;
|
||||
FS_Error file_check_err = storage_common_stat(fs_api, path, &layout_file_info);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
if(file_check_err != FSE_OK) {
|
||||
memzero(settings, strlen(settings));
|
||||
settings[0] = '\0';
|
||||
ret = false;
|
||||
}
|
||||
// if(layout_file_info.size != 256) {
|
||||
// memzero(settings, strlen(settings));
|
||||
// settings[0] = '\0';
|
||||
// }
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool flipbip_has_file(const FlipBipFile file_type, const char* file_name, const bool remove) {
|
||||
bool ret = false;
|
||||
const char* path;
|
||||
if(file_type == FlipBipFileKey) {
|
||||
path = FLIPBIP_KEY_PATH;
|
||||
} else if(file_type == FlipBipFileDat) {
|
||||
path = FLIPBIP_DAT_PATH;
|
||||
} else {
|
||||
char path_buf[FILE_MAX_PATH_LEN] = {0};
|
||||
strcpy(path_buf, FLIPBIP_APP_BASE_FOLDER); // 22
|
||||
strcpy(path_buf + strlen(path_buf), "/");
|
||||
strcpy(path_buf + strlen(path_buf), file_name);
|
||||
path = path_buf;
|
||||
}
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
if(remove) {
|
||||
ret = storage_simply_remove(fs_api, path);
|
||||
} else {
|
||||
ret = storage_file_exists(fs_api, path);
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool flipbip_save_file(
|
||||
const char* settings,
|
||||
const FlipBipFile file_type,
|
||||
const char* file_name,
|
||||
const bool append) {
|
||||
bool ret = false;
|
||||
const char* path;
|
||||
const char* path_bak;
|
||||
if(file_type == FlipBipFileKey) {
|
||||
path = FLIPBIP_KEY_PATH;
|
||||
path_bak = FLIPBIP_KEY_PATH_BAK;
|
||||
} else if(file_type == FlipBipFileDat) {
|
||||
path = FLIPBIP_DAT_PATH;
|
||||
path_bak = FLIPBIP_DAT_PATH_BAK;
|
||||
} else {
|
||||
char path_buf[FILE_MAX_PATH_LEN] = {0};
|
||||
strcpy(path_buf, FLIPBIP_APP_BASE_FOLDER); // 22
|
||||
strcpy(path_buf + strlen(path_buf), "/");
|
||||
strcpy(path_buf + strlen(path_buf), file_name);
|
||||
path = path_buf;
|
||||
path_bak = NULL;
|
||||
}
|
||||
int open_mode = FSOM_OPEN_ALWAYS;
|
||||
if(append) {
|
||||
open_mode = FSOM_OPEN_APPEND;
|
||||
}
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
// // if the key file exists, we don't want to overwrite it
|
||||
// if (key_file && storage_file_exists(fs_api, path)) {
|
||||
// furi_record_close(RECORD_STORAGE);
|
||||
// ret = true;
|
||||
// return ret;
|
||||
// }
|
||||
// try to create the folder
|
||||
storage_simply_mkdir(fs_api, FLIPBIP_APP_BASE_FOLDER);
|
||||
|
||||
File* settings_file = storage_file_alloc(fs_api);
|
||||
if(storage_file_open(settings_file, path, FSAM_WRITE, open_mode)) {
|
||||
storage_file_write(settings_file, settings, strlen(settings));
|
||||
storage_file_write(settings_file, "\n", 1);
|
||||
ret = true;
|
||||
}
|
||||
storage_file_close(settings_file);
|
||||
storage_file_free(settings_file);
|
||||
|
||||
if(path_bak != NULL) {
|
||||
File* settings_file_bak = storage_file_alloc(fs_api);
|
||||
if(storage_file_open(settings_file_bak, path_bak, FSAM_WRITE, open_mode)) {
|
||||
storage_file_write(settings_file_bak, settings, strlen(settings));
|
||||
storage_file_write(settings_file_bak, "\n", 1);
|
||||
}
|
||||
storage_file_close(settings_file_bak);
|
||||
storage_file_free(settings_file_bak);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool flipbip_save_qrfile(
|
||||
const char* qr_msg_prefix,
|
||||
const char* qr_msg_content,
|
||||
const char* file_name) {
|
||||
char qr_buf[FILE_MAX_QRFILE_CONTENT] = {0};
|
||||
strcpy(qr_buf, TEXT_QRFILE);
|
||||
strcpy(qr_buf + strlen(qr_buf), qr_msg_prefix);
|
||||
strcpy(qr_buf + strlen(qr_buf), qr_msg_content);
|
||||
return flipbip_save_file(qr_buf, FlipBipFileOther, file_name, false);
|
||||
}
|
||||
|
||||
bool flipbip_load_file_secure(char* settings) {
|
||||
const size_t dlen = FILE_HLEN + FILE_SLEN + 1;
|
||||
|
||||
// allocate memory for key/data
|
||||
char* data = malloc(dlen);
|
||||
memzero(data, dlen);
|
||||
|
||||
// load k2 from file
|
||||
if(!flipbip_load_file(data, dlen, FlipBipFileKey, NULL)) return false;
|
||||
|
||||
// check header
|
||||
if(data[0] != FILE_HSTR[0] || data[1] != FILE_HSTR[1] || data[2] != FILE_HSTR[2] ||
|
||||
data[3] != FILE_HSTR[3]) {
|
||||
memzero(data, dlen);
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
// seek --> header
|
||||
data += FILE_HLEN;
|
||||
|
||||
// prepare k1
|
||||
uint8_t k1[64];
|
||||
flipbip_xtob(FILE_K1, k1, strlen(FILE_K1) / 2);
|
||||
|
||||
// load k2 from file buffer (secured by k1)
|
||||
flipbip_cipher(k1, strlen(FILE_K1) / 2, data, data, FILE_KLEN);
|
||||
uint8_t k2[128];
|
||||
flipbip_xtob(data, k2, FILE_KLEN / 2);
|
||||
// zero k2 buffer
|
||||
memzero(data, FILE_KLEN);
|
||||
// seek <-- header
|
||||
data -= FILE_HLEN;
|
||||
|
||||
// load data from file
|
||||
if(!flipbip_load_file(data, dlen, FlipBipFileDat, NULL)) return false;
|
||||
|
||||
// check header
|
||||
if(data[0] != FILE_HSTR[0] || data[1] != FILE_HSTR[1] || data[2] != FILE_HSTR[2] ||
|
||||
data[3] != FILE_HSTR[3]) {
|
||||
memzero(data, dlen);
|
||||
free(data);
|
||||
memzero(k1, strlen(FILE_K1) / 2);
|
||||
memzero(k2, FILE_KLEN / 2);
|
||||
return false;
|
||||
}
|
||||
// seek --> header
|
||||
data += FILE_HLEN;
|
||||
|
||||
// load settings from file buffer (secured by k2)
|
||||
flipbip_cipher(k2, FILE_KLEN / 2, data, data, FILE_SLEN);
|
||||
flipbip_xtob(data, (unsigned char*)data, FILE_SLEN / 2);
|
||||
|
||||
// copy to output
|
||||
strcpy(settings, data);
|
||||
|
||||
// seek <-- header
|
||||
data -= FILE_HLEN;
|
||||
|
||||
// clear memory
|
||||
memzero(data, dlen);
|
||||
free(data);
|
||||
memzero(k1, strlen(FILE_K1) / 2);
|
||||
memzero(k2, FILE_KLEN / 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool flipbip_save_file_secure(const char* settings) {
|
||||
const size_t dlen = FILE_HLEN + FILE_SLEN + 1;
|
||||
|
||||
// cap settings to 256 bytes
|
||||
size_t len = strlen(settings);
|
||||
if(len > (FILE_SLEN / 2)) len = FILE_SLEN / 2;
|
||||
|
||||
// allocate memory for key/data
|
||||
char* data = malloc(dlen);
|
||||
memzero(data, dlen);
|
||||
|
||||
// write header
|
||||
strncpy(data, FILE_HSTR, FILE_HLEN);
|
||||
// seek --> header
|
||||
data += FILE_HLEN;
|
||||
|
||||
// prepare k1
|
||||
uint8_t k1[64];
|
||||
flipbip_xtob(FILE_K1, k1, strlen(FILE_K1) / 2);
|
||||
|
||||
// generate k2
|
||||
uint8_t k2[128];
|
||||
random_buffer(k2, FILE_KLEN / 2);
|
||||
|
||||
// write k2 to file buffer (secured by k1)
|
||||
flipbip_btox(k2, FILE_KLEN / 2, data);
|
||||
flipbip_cipher(k1, strlen(FILE_K1) / 2, data, data, FILE_KLEN);
|
||||
|
||||
// seek <-- header
|
||||
data -= FILE_HLEN;
|
||||
// save k2 to file
|
||||
flipbip_save_file(data, FlipBipFileKey, NULL, false);
|
||||
// seek --> header
|
||||
data += FILE_HLEN;
|
||||
// zero k2 memory
|
||||
memzero(data, FILE_KLEN);
|
||||
|
||||
// write settings to file buffer (secured by k2)
|
||||
flipbip_btox((uint8_t*)settings, len, data);
|
||||
flipbip_cipher(k2, FILE_KLEN / 2, data, data, FILE_SLEN);
|
||||
|
||||
// seek <-- header
|
||||
data -= FILE_HLEN;
|
||||
// save data to file
|
||||
flipbip_save_file(data, FlipBipFileDat, NULL, false);
|
||||
|
||||
// clear memory
|
||||
memzero(data, dlen);
|
||||
free(data);
|
||||
memzero(k1, strlen(FILE_K1) / 2);
|
||||
memzero(k2, FILE_KLEN / 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
FlipBipFileDat,
|
||||
FlipBipFileKey,
|
||||
FlipBipFileOther,
|
||||
} FlipBipFile;
|
||||
|
||||
bool flipbip_has_file(const FlipBipFile file_type, const char* file_name, const bool remove);
|
||||
bool flipbip_load_file(
|
||||
char* settings,
|
||||
size_t slen,
|
||||
const FlipBipFile file_type,
|
||||
const char* file_name);
|
||||
bool flipbip_save_file(
|
||||
const char* settings,
|
||||
const FlipBipFile file_type,
|
||||
const char* file_name,
|
||||
const bool append);
|
||||
|
||||
bool flipbip_save_qrfile(
|
||||
const char* qr_msg_prefix,
|
||||
const char* qr_msg_content,
|
||||
const char* file_name);
|
||||
|
||||
bool flipbip_load_file_secure(char* settings);
|
||||
bool flipbip_save_file_secure(const char* settings);
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1988 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
#include "flipbip_string.h"
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
// From: lib/crypto
|
||||
#include <memzero.h>
|
||||
#include <rc4.h>
|
||||
|
||||
char* flipbip_strtok(char* s, const char* delim) {
|
||||
static char* last;
|
||||
return flipbip_strtok_r(s, delim, &last);
|
||||
}
|
||||
char* flipbip_strtok_r(char* s, const char* delim, char** last) {
|
||||
char* spanp;
|
||||
int c, sc;
|
||||
char* tok;
|
||||
if(s == NULL && (s = *last) == NULL) return (NULL);
|
||||
/*
|
||||
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
|
||||
*/
|
||||
cont:
|
||||
c = *s++;
|
||||
for(spanp = (char*)delim; (sc = *spanp++) != 0;) {
|
||||
if(c == sc) goto cont;
|
||||
}
|
||||
if(c == 0) { /* no non-delimiter characters */
|
||||
*last = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
tok = s - 1;
|
||||
/*
|
||||
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
|
||||
* Note that delim must have one NUL; we stop if we see that, too.
|
||||
*/
|
||||
for(;;) {
|
||||
c = *s++;
|
||||
spanp = (char*)delim;
|
||||
do {
|
||||
if((sc = *spanp++) == c) {
|
||||
if(c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*last = s;
|
||||
return (tok);
|
||||
}
|
||||
} while(sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void flipbip_btox(const unsigned char* in, int in_len, char* str) {
|
||||
for(int i = 0; i < in_len; i++) {
|
||||
unsigned char n;
|
||||
unsigned char x = in[i];
|
||||
|
||||
str += 2;
|
||||
*(str + (i * 2)) = '\0';
|
||||
|
||||
for(n = 2; n != 0; --n) {
|
||||
*(--str + (i * 2)) = "0123456789abcdef"[x & 0x0F];
|
||||
x >>= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
void flipbip_xtob(const char* str, unsigned char* out, int out_len) {
|
||||
int len = strlen(str) / 2;
|
||||
if(len > out_len) len = out_len;
|
||||
for(int i = 0; i < len; i++) {
|
||||
char c = 0;
|
||||
if(str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4;
|
||||
if((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F')
|
||||
c += (10 + (str[i * 2] & ~0x20) - 'A') << 4;
|
||||
if(str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') c += (str[i * 2 + 1] - '0');
|
||||
if((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F')
|
||||
c += (10 + (str[i * 2 + 1] & ~0x20) - 'A');
|
||||
out[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
void flipbip_cipher(
|
||||
const unsigned char* key_in,
|
||||
const unsigned int key_len,
|
||||
const char* in,
|
||||
char* out,
|
||||
const unsigned int io_len) {
|
||||
if(io_len > 512) return;
|
||||
|
||||
RC4_CTX ctx;
|
||||
uint8_t buf[256];
|
||||
memzero(buf, 256);
|
||||
|
||||
flipbip_xtob(in, buf, io_len / 2);
|
||||
|
||||
rc4_init(&ctx, key_in, key_len);
|
||||
rc4_encrypt(&ctx, buf, 256);
|
||||
|
||||
flipbip_btox(buf, io_len / 2, out);
|
||||
|
||||
memzero(buf, 256);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
char* flipbip_strtok(char* s, const char* delim);
|
||||
char* flipbip_strtok_r(char* s, const char* delim, char** last);
|
||||
|
||||
void flipbip_btox(const unsigned char* in, int in_len, char* str);
|
||||
void flipbip_xtob(const char* str, unsigned char* out, int out_len);
|
||||
|
||||
void flipbip_cipher(
|
||||
const unsigned char* key_in,
|
||||
const unsigned int key_len,
|
||||
const char* in,
|
||||
char* out,
|
||||
const unsigned int io_len);
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
@@ -1,2 +0,0 @@
|
||||
Tomas Dzetkulic <dzetkulic@gmail.com>
|
||||
Pavol Rusnak <stick@gk2.sk>
|
||||
@@ -1,17 +0,0 @@
|
||||
Tomas Dzetkulic <dzetkulic@gmail.com>
|
||||
Pavol Rusnak <stick@gk2.sk>
|
||||
Jochen Hoenicke <hoenicke@gmail.com>
|
||||
Dustin Laurence <dustin@laurences.net>
|
||||
Ondrej Mikle <ondrej.mikle@nic.cz>
|
||||
Roman Zeyde <roman.zeyde@gmail.com>
|
||||
Alex Beregszaszi <alex@rtfs.hu>
|
||||
netanelkl <netanel.keidar@gmail.com>
|
||||
Jan Pochyla <jpochyla@gmail.com>
|
||||
Ondrej Mikle <ondrej.mikle@gmail.com>
|
||||
Josh Billings <jdb6167@rit.edu>
|
||||
Adam Mackler <AdamMackler@gmail.com>
|
||||
Oleg Andreev <oleganza@gmail.com>
|
||||
mog <mog@rush.rldn.net>
|
||||
John Dvorak <johndvorak26@gmail.com>
|
||||
Christian Reitter <invd@inhq.net>
|
||||
Struan Clark <xtruan@users.noreply.github.com>
|
||||
22
applications/external/flipbip/lib/crypto/LICENSE
vendored
22
applications/external/flipbip/lib/crypto/LICENSE
vendored
@@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Tomas Dzetkulic
|
||||
Copyright (c) 2013 Pavol Rusnak
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
187
applications/external/flipbip/lib/crypto/Makefile
vendored
187
applications/external/flipbip/lib/crypto/Makefile
vendored
@@ -1,187 +0,0 @@
|
||||
# CLANG_VERSION is empty if the compiler is not clang-based
|
||||
CLANG_VERSION = $(shell $(CC) --version | sed -nr 's/^.*clang version ([0-9.]+).*$$/\1/p')
|
||||
CLANG_VERSION_MAJOR = $(shell echo $(CLANG_VERSION) | cut -f1 -d.)
|
||||
|
||||
# determine specific version ranges
|
||||
ifneq ($(CLANG_VERSION),)
|
||||
$(if $(shell [ $(CLANG_VERSION_MAJOR) -ge 13 ] && echo "OK"), \
|
||||
$(eval CLANG_AT_LEAST_13 := true), \
|
||||
$(eval CLANG_AT_LEAST_13 := false))
|
||||
endif
|
||||
|
||||
ifeq ($(FUZZER),1)
|
||||
CC ?= clang
|
||||
LD ?= $(CC)
|
||||
SANFLAGS += -fsanitize=fuzzer
|
||||
|
||||
# only clang versions >= 13 support this feature
|
||||
ifeq ($(CLANG_AT_LEAST_13),true)
|
||||
$(info "info: using -fsanitize-ignorelist")
|
||||
SANFLAGS += -fsanitize-ignorelist=fuzzer/sanitizer_ignorelist.txt
|
||||
else
|
||||
$(info "info: not using -fsanitize-ignorelist")
|
||||
endif
|
||||
|
||||
# TODO is there a better solution, for example by disabling a specific optimization technique?
|
||||
# there is a clang optimization issue in relation with the blake2 code at -fsanitize=undefined
|
||||
$(warning "warning: disabling optimization on blake2 code as workaround")
|
||||
blake2b.o: OPTFLAGS += -O0
|
||||
blake2s.o: OPTFLAGS += -O0
|
||||
|
||||
else ifeq ($(ADDRESS_SANITIZER),1)
|
||||
SANFLAGS += -fsanitize=address,undefined
|
||||
endif
|
||||
|
||||
CC ?= cc
|
||||
|
||||
OPTFLAGS ?= -O3 -g
|
||||
|
||||
CFLAGS += $(OPTFLAGS) \
|
||||
$(SANFLAGS) \
|
||||
-std=gnu99 \
|
||||
-W \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wimplicit-function-declaration \
|
||||
-Wredundant-decls \
|
||||
-Wstrict-prototypes \
|
||||
-Wundef \
|
||||
-Wshadow \
|
||||
-Wpointer-arith \
|
||||
-Wformat \
|
||||
-Wreturn-type \
|
||||
-Wsign-compare \
|
||||
-Wmultichar \
|
||||
-Wformat-nonliteral \
|
||||
-Winit-self \
|
||||
-Wuninitialized \
|
||||
-Wformat-security \
|
||||
-Wno-missing-braces \
|
||||
-Werror
|
||||
|
||||
ZKP_CFLAGS = \
|
||||
-DECMULT_GEN_PREC_BITS=4 \
|
||||
-DECMULT_WINDOW_SIZE=8 \
|
||||
-DENABLE_MODULE_GENERATOR \
|
||||
-DENABLE_MODULE_RECOVERY \
|
||||
-DENABLE_MODULE_SCHNORRSIG \
|
||||
-DENABLE_MODULE_EXTRAKEYS
|
||||
ZKP_PATH = ../vendor/secp256k1-zkp
|
||||
# this is specific for 64-bit builds
|
||||
CFLAGS += -DSECP256K1_CONTEXT_SIZE=208
|
||||
|
||||
VALGRIND ?= 1
|
||||
ifeq ($(VALGRIND),1)
|
||||
CFLAGS += -DVALGRIND
|
||||
endif
|
||||
|
||||
CFLAGS += -I.
|
||||
CFLAGS += -I..
|
||||
CFLAGS += -DUSE_ETHEREUM=1
|
||||
CFLAGS += -DUSE_KECCAK=1
|
||||
CFLAGS += -DUSE_MONERO=1
|
||||
CFLAGS += -DUSE_NEM=1
|
||||
CFLAGS += -DUSE_CARDANO=1
|
||||
CFLAGS += $(shell pkg-config --cflags openssl)
|
||||
|
||||
# disable certain optimizations and features when small footprint is required
|
||||
ifdef SMALL
|
||||
CFLAGS += -DUSE_PRECOMPUTED_CP=0
|
||||
endif
|
||||
|
||||
SRCS = bignum.c ecdsa.c curves.c secp256k1.c nist256p1.c rand.c hmac.c bip32.c bip39.c bip39_english.c pbkdf2.c base58.c base32.c
|
||||
SRCS += address.c
|
||||
SRCS += script.c
|
||||
SRCS += ripemd160.c
|
||||
SRCS += sha2.c
|
||||
SRCS += sha3.c
|
||||
SRCS += hasher.c
|
||||
SRCS += aes/aescrypt.c aes/aeskey.c aes/aestab.c aes/aes_modes.c
|
||||
SRCS += ed25519_donna/curve25519_donna_32bit.c ed25519_donna/curve25519_donna_helpers.c ed25519_donna/modm_donna_32bit.c
|
||||
SRCS += ed25519_donna/ed25519_donna_basepoint_table.c ed25519_donna/ed25519_donna_32bit_tables.c ed25519_donna/ed25519_donna_impl_base.c
|
||||
SRCS += ed25519_donna/ed25519.c ed25519_donna/curve25519_donna_scalarmult_base.c ed25519_donna/ed25519_sha3.c ed25519_donna/ed25519_keccak.c
|
||||
SRCS += monero/base58.c
|
||||
SRCS += monero/serialize.c
|
||||
SRCS += monero/xmr.c
|
||||
SRCS += blake256.c
|
||||
SRCS += blake2b.c blake2s.c
|
||||
SRCS += chacha_drbg.c
|
||||
SRCS += groestl.c
|
||||
SRCS += chacha20poly1305/chacha20poly1305.c chacha20poly1305/chacha_merged.c chacha20poly1305/poly1305_donna.c chacha20poly1305/rfc7539.c
|
||||
SRCS += rc4.c
|
||||
SRCS += nem.c
|
||||
SRCS += segwit_addr.c cash_addr.c
|
||||
SRCS += memzero.c
|
||||
SRCS += shamir.c
|
||||
SRCS += hmac_drbg.c
|
||||
SRCS += rfc6979.c
|
||||
SRCS += slip39.c
|
||||
SRCS += zkp_context.c
|
||||
SRCS += zkp_ecdsa.c
|
||||
SRCS += zkp_bip340.c
|
||||
SRCS += cardano.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
OBJS += secp256k1-zkp.o
|
||||
OBJS += precomputed_ecmult.o
|
||||
OBJS += precomputed_ecmult_gen.o
|
||||
|
||||
TESTLIBS = $(shell pkg-config --libs check) -lpthread -lm
|
||||
TESTSSLLIBS = $(shell pkg-config --libs openssl)
|
||||
|
||||
all: tools tests
|
||||
|
||||
%.o: %.c %.h options.h
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
tests: tests/test_check tests/test_openssl tests/test_speed tests/libtrezor-crypto.so tests/aestst
|
||||
|
||||
tests/aestst: aes/aestst.o aes/aescrypt.o aes/aeskey.o aes/aestab.o
|
||||
$(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
tests/test_check.o: tests/test_check_cardano.h tests/test_check_monero.h tests/test_check_cashaddr.h tests/test_check_segwit.h
|
||||
|
||||
tests/test_check: tests/test_check.o $(OBJS)
|
||||
$(CC) $(CFLAGS) tests/test_check.o $(OBJS) $(TESTLIBS) -o tests/test_check
|
||||
|
||||
tests/test_speed: tests/test_speed.o $(OBJS)
|
||||
$(CC) $(CFLAGS) tests/test_speed.o $(OBJS) -o tests/test_speed
|
||||
|
||||
tests/test_openssl: tests/test_openssl.o $(OBJS)
|
||||
$(CC) $(CFLAGS) tests/test_openssl.o $(OBJS) $(TESTSSLLIBS) -o tests/test_openssl
|
||||
|
||||
tests/libtrezor-crypto.so: $(SRCS) secp256k1-zkp.o precomputed_ecmult.o precomputed_ecmult_gen.o
|
||||
$(CC) $(CFLAGS) -DAES_128 -DAES_192 -fPIC -shared $(SRCS) secp256k1-zkp.o precomputed_ecmult.o precomputed_ecmult_gen.o -o tests/libtrezor-crypto.so
|
||||
|
||||
tools: tools/xpubaddrgen tools/mktable tools/bip39bruteforce
|
||||
|
||||
tools/xpubaddrgen: tools/xpubaddrgen.o $(OBJS)
|
||||
$(CC) $(CFLAGS) tools/xpubaddrgen.o $(OBJS) -o tools/xpubaddrgen
|
||||
|
||||
tools/mktable: tools/mktable.o $(OBJS)
|
||||
$(CC) $(CFLAGS) tools/mktable.o $(OBJS) -o tools/mktable
|
||||
|
||||
tools/bip39bruteforce: tools/bip39bruteforce.o $(OBJS)
|
||||
$(CC) $(CFLAGS) tools/bip39bruteforce.o $(OBJS) -o tools/bip39bruteforce
|
||||
|
||||
fuzzer: fuzzer/fuzzer.o $(OBJS)
|
||||
$(CC) $(CFLAGS) fuzzer/fuzzer.o $(OBJS) -o fuzzer/fuzzer
|
||||
|
||||
precomputed_ecmult.o:
|
||||
$(CC) $(CFLAGS) -Wno-unused-function $(ZKP_CFLAGS) -fPIC -c $(ZKP_PATH)/src/precomputed_ecmult.c -o precomputed_ecmult.o
|
||||
|
||||
precomputed_ecmult_gen.o:
|
||||
$(CC) $(CFLAGS) -Wno-unused-function $(ZKP_CFLAGS) -fPIC -c $(ZKP_PATH)/src/precomputed_ecmult_gen.c -o precomputed_ecmult_gen.o
|
||||
|
||||
secp256k1-zkp.o:
|
||||
$(CC) $(CFLAGS) -Wno-unused-function $(ZKP_CFLAGS) -fPIC -I$(ZKP_PATH) -I$(ZKP_PATH)/src -c $(ZKP_PATH)/src/secp256k1.c -o secp256k1-zkp.o
|
||||
|
||||
clean:
|
||||
rm -f *.o aes/*.o chacha20poly1305/*.o ed25519_donna/*.o monero/*.o
|
||||
rm -f tests/*.o tests/test_check tests/test_speed tests/test_openssl tests/libtrezor-crypto.so tests/aestst
|
||||
rm -f tools/*.o tools/xpubaddrgen tools/mktable tools/bip39bruteforce
|
||||
rm -f fuzzer/*.o fuzzer/fuzzer
|
||||
rm -f secp256k1-zkp.o precomputed_ecmult.o precomputed_ecmult_gen.o
|
||||
|
||||
clean-fuzzer: clean
|
||||
rm -f crash-* fuzz-*.log slow-unit-* timeout-*
|
||||
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016 Daira Hopwood
|
||||
* Copyright (c) 2016 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "address.h"
|
||||
#include "bignum.h"
|
||||
|
||||
size_t address_prefix_bytes_len(uint32_t address_type) {
|
||||
if(address_type <= 0xFF) return 1;
|
||||
if(address_type <= 0xFFFF) return 2;
|
||||
if(address_type <= 0xFFFFFF) return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
void address_write_prefix_bytes(uint32_t address_type, uint8_t* out) {
|
||||
if(address_type > 0xFFFFFF) *(out++) = address_type >> 24;
|
||||
if(address_type > 0xFFFF) *(out++) = (address_type >> 16) & 0xFF;
|
||||
if(address_type > 0xFF) *(out++) = (address_type >> 8) & 0xFF;
|
||||
*(out++) = address_type & 0xFF;
|
||||
}
|
||||
|
||||
bool address_check_prefix(const uint8_t* addr, uint32_t address_type) {
|
||||
if(address_type <= 0xFF) {
|
||||
return address_type == (uint32_t)(addr[0]);
|
||||
}
|
||||
if(address_type <= 0xFFFF) {
|
||||
return address_type == (((uint32_t)addr[0] << 8) | ((uint32_t)addr[1]));
|
||||
}
|
||||
if(address_type <= 0xFFFFFF) {
|
||||
return address_type ==
|
||||
(((uint32_t)addr[0] << 16) | ((uint32_t)addr[1] << 8) | ((uint32_t)addr[2]));
|
||||
}
|
||||
return address_type == (((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) |
|
||||
((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]));
|
||||
}
|
||||
|
||||
#if USE_ETHEREUM
|
||||
#include "sha3.h"
|
||||
|
||||
void ethereum_address_checksum(const uint8_t* addr, char* address, bool rskip60, uint64_t chain_id) {
|
||||
const char* hex = "0123456789abcdef";
|
||||
address[0] = '0';
|
||||
address[1] = 'x';
|
||||
for(int i = 0; i < 20; i++) {
|
||||
address[2 + i * 2] = hex[(addr[i] >> 4) & 0xF];
|
||||
address[2 + i * 2 + 1] = hex[addr[i] & 0xF];
|
||||
}
|
||||
address[42] = 0;
|
||||
|
||||
SHA3_CTX ctx = {0};
|
||||
uint8_t hash[32] = {0};
|
||||
keccak_256_Init(&ctx);
|
||||
if(rskip60) {
|
||||
char prefix[16] = {0};
|
||||
int prefix_size =
|
||||
bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, 0, prefix, sizeof(prefix));
|
||||
keccak_Update(&ctx, (const uint8_t*)prefix, prefix_size);
|
||||
}
|
||||
keccak_Update(&ctx, (const uint8_t*)(address + 2), 40);
|
||||
keccak_Final(&ctx, hash);
|
||||
|
||||
for(int i = 0; i < 20; i++) {
|
||||
if((hash[i] & 0x80) && address[2 + i * 2] >= 'a' && address[2 + i * 2] <= 'f') {
|
||||
address[2 + i * 2] -= 0x20;
|
||||
}
|
||||
if((hash[i] & 0x08) && address[2 + i * 2 + 1] >= 'a' && address[2 + i * 2 + 1] <= 'f') {
|
||||
address[2 + i * 2 + 1] -= 0x20;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016 Daira Hopwood
|
||||
* Copyright (c) 2016 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __ADDRESS_H__
|
||||
#define __ADDRESS_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "options.h"
|
||||
|
||||
size_t address_prefix_bytes_len(uint32_t address_type);
|
||||
void address_write_prefix_bytes(uint32_t address_type, uint8_t* out);
|
||||
bool address_check_prefix(const uint8_t* addr, uint32_t address_type);
|
||||
#if USE_ETHEREUM
|
||||
void ethereum_address_checksum(const uint8_t* addr, char* address, bool rskip60, uint64_t chain_id);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
256
applications/external/flipbip/lib/crypto/aes/aes.h
vendored
256
applications/external/flipbip/lib/crypto/aes/aes.h
vendored
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 02/08/2018
|
||||
|
||||
This file contains the definitions required to use AES in C. See aesopt.h
|
||||
for optimisation details.
|
||||
*/
|
||||
|
||||
#ifndef _AES_H
|
||||
#define _AES_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define VOID_RETURN void
|
||||
#define INT_RETURN int
|
||||
#define ALIGN_OFFSET(x, n) (((intptr_t)(x)) & ((n)-1))
|
||||
#define ALIGN_FLOOR(x, n) ((uint8_t*)(x) - (((intptr_t)(x)) & ((n)-1)))
|
||||
#define ALIGN_CEIL(x, n) ((uint8_t*)(x) + (-((intptr_t)(x)) & ((n)-1)))
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// #define AES_128 /* if a fast 128 bit key scheduler is needed */
|
||||
// #define AES_192 /* if a fast 192 bit key scheduler is needed */
|
||||
#define AES_256 /* if a fast 256 bit key scheduler is needed */
|
||||
// #define AES_VAR /* if variable key size scheduler is needed */
|
||||
#if 1
|
||||
#define AES_MODES /* if support is needed for modes in the C code */
|
||||
#endif /* (these will use AES_NI if it is present) */
|
||||
#if 0 /* add this to make direct calls to the AES_NI */
|
||||
#/* implemented CBC and CTR modes available */
|
||||
#define ADD_AESNI_MODE_CALLS
|
||||
#endif
|
||||
|
||||
/* The following must also be set in assembler files if being used */
|
||||
|
||||
#define AES_ENCRYPT /* if support for encryption is needed */
|
||||
#define AES_DECRYPT /* if support for decryption is needed */
|
||||
|
||||
#define AES_BLOCK_SIZE_P2 4 /* AES block size as a power of 2 */
|
||||
#define AES_BLOCK_SIZE (1 << AES_BLOCK_SIZE_P2) /* AES block size */
|
||||
#define N_COLS 4 /* the number of columns in the state */
|
||||
|
||||
/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */
|
||||
/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */
|
||||
/* or 44, 52 or 60 32-bit words. */
|
||||
|
||||
#if defined(AES_VAR) || defined(AES_256)
|
||||
#define KS_LENGTH 60
|
||||
#elif defined(AES_192)
|
||||
#define KS_LENGTH 52
|
||||
#else
|
||||
#define KS_LENGTH 44
|
||||
#endif
|
||||
|
||||
#define AES_RETURN INT_RETURN
|
||||
|
||||
/* the character array 'inf' in the following structures is used */
|
||||
/* to hold AES context information. This AES code uses cx->inf.b[0] */
|
||||
/* to hold the number of rounds multiplied by 16. The other three */
|
||||
/* elements can be used by code that implements additional modes */
|
||||
|
||||
typedef union {
|
||||
uint32_t l;
|
||||
uint8_t b[4];
|
||||
} aes_inf;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(_WIN64)
|
||||
#define ALIGNED_(x) __declspec(align(x))
|
||||
#elif defined(__GNUC__) && defined(__x86_64__)
|
||||
#define ALIGNED_(x) __attribute__((aligned(x)))
|
||||
#else
|
||||
#define ALIGNED_(x)
|
||||
#endif
|
||||
|
||||
typedef struct ALIGNED_(16) {
|
||||
uint32_t ks[KS_LENGTH];
|
||||
aes_inf inf;
|
||||
} aes_encrypt_ctx;
|
||||
|
||||
typedef struct ALIGNED_(16) {
|
||||
uint32_t ks[KS_LENGTH];
|
||||
aes_inf inf;
|
||||
} aes_decrypt_ctx;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(default : 4324)
|
||||
#endif
|
||||
|
||||
/* This routine must be called before first use if non-static */
|
||||
/* tables are being used */
|
||||
|
||||
AES_RETURN aes_init(void);
|
||||
|
||||
/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */
|
||||
/* those in the range 128 <= key_len <= 256 are given in bits */
|
||||
|
||||
#if defined(AES_ENCRYPT)
|
||||
|
||||
#if defined(AES_128) || defined(AES_VAR)
|
||||
AES_RETURN aes_encrypt_key128(const unsigned char* key, aes_encrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
#if defined(AES_192) || defined(AES_VAR)
|
||||
AES_RETURN aes_encrypt_key192(const unsigned char* key, aes_encrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
#if defined(AES_256) || defined(AES_VAR)
|
||||
AES_RETURN aes_encrypt_key256(const unsigned char* key, aes_encrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
#if defined(AES_VAR)
|
||||
AES_RETURN aes_encrypt_key(const unsigned char* key, int key_len, aes_encrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
AES_RETURN aes_encrypt(const unsigned char* in, unsigned char* out, const aes_encrypt_ctx cx[1]);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_DECRYPT)
|
||||
|
||||
#if defined(AES_128) || defined(AES_VAR)
|
||||
AES_RETURN aes_decrypt_key128(const unsigned char* key, aes_decrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
#if defined(AES_192) || defined(AES_VAR)
|
||||
AES_RETURN aes_decrypt_key192(const unsigned char* key, aes_decrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
#if defined(AES_256) || defined(AES_VAR)
|
||||
AES_RETURN aes_decrypt_key256(const unsigned char* key, aes_decrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
#if defined(AES_VAR)
|
||||
AES_RETURN aes_decrypt_key(const unsigned char* key, int key_len, aes_decrypt_ctx cx[1]);
|
||||
#endif
|
||||
|
||||
AES_RETURN aes_decrypt(const unsigned char* in, unsigned char* out, const aes_decrypt_ctx cx[1]);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_MODES)
|
||||
|
||||
/* Multiple calls to the following subroutines for multiple block */
|
||||
/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */
|
||||
/* long messages incrementally provided that the context AND the iv */
|
||||
/* are preserved between all such calls. For the ECB and CBC modes */
|
||||
/* each individual call within a series of incremental calls must */
|
||||
/* process only full blocks (i.e. len must be a multiple of 16) but */
|
||||
/* the CFB, OFB and CTR mode calls can handle multiple incremental */
|
||||
/* calls of any length. Each mode is reset when a new AES key is */
|
||||
/* set but ECB needs no reset and CBC can be reset without setting */
|
||||
/* a new key by setting a new IV value. To reset CFB, OFB and CTR */
|
||||
/* without setting the key, aes_mode_reset() must be called and the */
|
||||
/* IV must be set. NOTE: All these calls update the IV on exit so */
|
||||
/* this has to be reset if a new operation with the same IV as the */
|
||||
/* previous one is required (or decryption follows encryption with */
|
||||
/* the same IV array). */
|
||||
|
||||
AES_RETURN aes_test_alignment_detection(unsigned int n);
|
||||
|
||||
AES_RETURN aes_ecb_encrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
const aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_ecb_decrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
const aes_decrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_cbc_encrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
const aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_cbc_decrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
const aes_decrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_cfb_encrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_cfb_decrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
aes_encrypt_ctx cx[1]);
|
||||
|
||||
#define aes_ofb_encrypt aes_ofb_crypt
|
||||
#define aes_ofb_decrypt aes_ofb_crypt
|
||||
|
||||
AES_RETURN aes_ofb_crypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
aes_encrypt_ctx cx[1]);
|
||||
|
||||
typedef void cbuf_inc(unsigned char* cbuf);
|
||||
|
||||
#define aes_ctr_encrypt aes_ctr_crypt
|
||||
#define aes_ctr_decrypt aes_ctr_crypt
|
||||
|
||||
AES_RETURN aes_ctr_crypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* cbuf,
|
||||
cbuf_inc ctr_inc,
|
||||
aes_encrypt_ctx cx[1]);
|
||||
|
||||
void aes_ctr_cbuf_inc(unsigned char* cbuf);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,932 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
|
||||
These subroutines implement multiple block AES modes for ECB, CBC, CFB,
|
||||
OFB and CTR encryption, The code provides support for the VIA Advanced
|
||||
Cryptography Engine (ACE).
|
||||
|
||||
NOTE: In the following subroutines, the AES contexts (ctx) must be
|
||||
16 byte aligned if VIA ACE is being used
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "aesopt.h"
|
||||
|
||||
#if defined(AES_MODES)
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER > 800)
|
||||
#pragma intrinsic(memcpy)
|
||||
#endif
|
||||
|
||||
#define BFR_BLOCKS 8
|
||||
|
||||
/* These values are used to detect long word alignment in order to */
|
||||
/* speed up some buffer operations. This facility may not work on */
|
||||
/* some machines so this define can be commented out if necessary */
|
||||
|
||||
#define FAST_BUFFER_OPERATIONS
|
||||
|
||||
#define lp32(x) ((uint32_t*)(x))
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
#include "aes_via_ace.h"
|
||||
|
||||
#pragma pack(16)
|
||||
|
||||
aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA;
|
||||
aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA;
|
||||
aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;
|
||||
aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA;
|
||||
aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA;
|
||||
aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;
|
||||
|
||||
/* NOTE: These control word macros must only be used after */
|
||||
/* a key has been set up because they depend on key size */
|
||||
/* See the VIA ACE documentation for key type information */
|
||||
/* and aes_via_ace.h for non-default NEH_KEY_TYPE values */
|
||||
|
||||
#ifndef NEH_KEY_TYPE
|
||||
#define NEH_KEY_TYPE NEH_HYBRID
|
||||
#endif
|
||||
|
||||
#if NEH_KEY_TYPE == NEH_LOAD
|
||||
#define kd_adr(c) ((uint8_t*)(c)->ks)
|
||||
#elif NEH_KEY_TYPE == NEH_GENERATE
|
||||
#define kd_adr(c) ((uint8_t*)(c)->ks + (c)->inf.b[0])
|
||||
#elif NEH_KEY_TYPE == NEH_HYBRID
|
||||
#define kd_adr(c) ((uint8_t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))
|
||||
#else
|
||||
#error no key type defined for VIA ACE
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define aligned_array(type, name, no, stride) type name[no]
|
||||
#define aligned_auto(type, name, no, stride) type name[no]
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
|
||||
#define via_cwd(cwd, ty, dir, len) unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))
|
||||
|
||||
#else
|
||||
|
||||
#define via_cwd(cwd, ty, dir, len) \
|
||||
aligned_auto(unsigned long, cwd, 4, 16); \
|
||||
cwd[1] = cwd[2] = cwd[3] = 0; \
|
||||
cwd[0] = neh_##dir##_##ty##_key(len)
|
||||
|
||||
#endif
|
||||
|
||||
/* test the code for detecting and setting pointer alignment */
|
||||
|
||||
AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */
|
||||
{
|
||||
uint8_t p[16];
|
||||
uint32_t i = 0, count_eq = 0, count_neq = 0;
|
||||
|
||||
if(n < 4 || n > 16) return EXIT_FAILURE;
|
||||
|
||||
for(i = 0; i < n; ++i) {
|
||||
uint8_t *qf = ALIGN_FLOOR(p + i, n), *qh = ALIGN_CEIL(p + i, n);
|
||||
|
||||
if(qh == qf)
|
||||
++count_eq;
|
||||
else if(qh == qf + n)
|
||||
++count_neq;
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1]) {
|
||||
ctx->inf.b[2] = 0;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ecb_encrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
const aes_encrypt_ctx ctx[1]) {
|
||||
int nb = len >> AES_BLOCK_SIZE_P2;
|
||||
|
||||
if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
uint8_t* ksp = (uint8_t*)(ctx->ks);
|
||||
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
|
||||
via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
|
||||
} else {
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_ecb_op5(ksp, cwd, ip, op, m);
|
||||
|
||||
if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
nb -= m;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(ASSUME_VIA_ACE_PRESENT)
|
||||
while(nb--) {
|
||||
if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ecb_decrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
const aes_decrypt_ctx ctx[1]) {
|
||||
int nb = len >> AES_BLOCK_SIZE_P2;
|
||||
|
||||
if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
uint8_t* ksp = kd_adr(ctx);
|
||||
via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
|
||||
via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
|
||||
} else {
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_ecb_op5(ksp, cwd, ip, op, m);
|
||||
|
||||
if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
nb -= m;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(ASSUME_VIA_ACE_PRESENT)
|
||||
while(nb--) {
|
||||
if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_cbc_encrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
const aes_encrypt_ctx ctx[1]) {
|
||||
int nb = len >> AES_BLOCK_SIZE_P2;
|
||||
|
||||
if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
|
||||
aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
|
||||
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
|
||||
{
|
||||
ivp = liv;
|
||||
memcpy(liv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16) && !ALIGN_OFFSET(iv, 16)) {
|
||||
via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
|
||||
} else {
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp);
|
||||
|
||||
if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
nb -= m;
|
||||
}
|
||||
}
|
||||
|
||||
if(iv != ivp) memcpy(iv, ivp, AES_BLOCK_SIZE);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(ASSUME_VIA_ACE_PRESENT)
|
||||
#ifdef FAST_BUFFER_OPERATIONS
|
||||
if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(iv, 4))
|
||||
while(nb--) {
|
||||
lp32(iv)[0] ^= lp32(ibuf)[0];
|
||||
lp32(iv)[1] ^= lp32(ibuf)[1];
|
||||
lp32(iv)[2] ^= lp32(ibuf)[2];
|
||||
lp32(iv)[3] ^= lp32(ibuf)[3];
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
memcpy(obuf, iv, AES_BLOCK_SIZE);
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while(nb--) {
|
||||
iv[0] ^= ibuf[0];
|
||||
iv[1] ^= ibuf[1];
|
||||
iv[2] ^= ibuf[2];
|
||||
iv[3] ^= ibuf[3];
|
||||
iv[4] ^= ibuf[4];
|
||||
iv[5] ^= ibuf[5];
|
||||
iv[6] ^= ibuf[6];
|
||||
iv[7] ^= ibuf[7];
|
||||
iv[8] ^= ibuf[8];
|
||||
iv[9] ^= ibuf[9];
|
||||
iv[10] ^= ibuf[10];
|
||||
iv[11] ^= ibuf[11];
|
||||
iv[12] ^= ibuf[12];
|
||||
iv[13] ^= ibuf[13];
|
||||
iv[14] ^= ibuf[14];
|
||||
iv[15] ^= ibuf[15];
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
memcpy(obuf, iv, AES_BLOCK_SIZE);
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_cbc_decrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
const aes_decrypt_ctx ctx[1]) {
|
||||
unsigned char tmp[AES_BLOCK_SIZE];
|
||||
int nb = len >> AES_BLOCK_SIZE_P2;
|
||||
|
||||
if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
uint8_t *ksp = kd_adr(ctx), *ivp = iv;
|
||||
aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
|
||||
via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
|
||||
{
|
||||
ivp = liv;
|
||||
memcpy(liv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16) && !ALIGN_OFFSET(iv, 16)) {
|
||||
via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp);
|
||||
} else {
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_cbc_op6(ksp, cwd, ip, op, m, ivp);
|
||||
|
||||
if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
nb -= m;
|
||||
}
|
||||
}
|
||||
|
||||
if(iv != ivp) memcpy(iv, ivp, AES_BLOCK_SIZE);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ASSUME_VIA_ACE_PRESENT)
|
||||
#ifdef FAST_BUFFER_OPERATIONS
|
||||
if(!ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
|
||||
while(nb--) {
|
||||
memcpy(tmp, ibuf, AES_BLOCK_SIZE);
|
||||
if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
lp32(obuf)[0] ^= lp32(iv)[0];
|
||||
lp32(obuf)[1] ^= lp32(iv)[1];
|
||||
lp32(obuf)[2] ^= lp32(iv)[2];
|
||||
lp32(obuf)[3] ^= lp32(iv)[3];
|
||||
memcpy(iv, tmp, AES_BLOCK_SIZE);
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while(nb--) {
|
||||
memcpy(tmp, ibuf, AES_BLOCK_SIZE);
|
||||
if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
obuf[0] ^= iv[0];
|
||||
obuf[1] ^= iv[1];
|
||||
obuf[2] ^= iv[2];
|
||||
obuf[3] ^= iv[3];
|
||||
obuf[4] ^= iv[4];
|
||||
obuf[5] ^= iv[5];
|
||||
obuf[6] ^= iv[6];
|
||||
obuf[7] ^= iv[7];
|
||||
obuf[8] ^= iv[8];
|
||||
obuf[9] ^= iv[9];
|
||||
obuf[10] ^= iv[10];
|
||||
obuf[11] ^= iv[11];
|
||||
obuf[12] ^= iv[12];
|
||||
obuf[13] ^= iv[13];
|
||||
obuf[14] ^= iv[14];
|
||||
obuf[15] ^= iv[15];
|
||||
memcpy(iv, tmp, AES_BLOCK_SIZE);
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_cfb_encrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
aes_encrypt_ctx ctx[1]) {
|
||||
int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
|
||||
|
||||
if(b_pos) /* complete any partial block */
|
||||
{
|
||||
while(b_pos < AES_BLOCK_SIZE && cnt < len) {
|
||||
*obuf++ = (iv[b_pos++] ^= *ibuf++);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
|
||||
}
|
||||
|
||||
if((nb = (len - cnt) >> AES_BLOCK_SIZE_P2) != 0) /* process whole blocks */
|
||||
{
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
int m;
|
||||
uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
|
||||
aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
|
||||
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
|
||||
{
|
||||
ivp = liv;
|
||||
memcpy(liv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
|
||||
via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
|
||||
ibuf += nb * AES_BLOCK_SIZE;
|
||||
obuf += nb * AES_BLOCK_SIZE;
|
||||
cnt += nb * AES_BLOCK_SIZE;
|
||||
} else /* input, output or both are unaligned */
|
||||
{
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
|
||||
|
||||
if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
cnt += m * AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE);
|
||||
}
|
||||
#else
|
||||
#ifdef FAST_BUFFER_OPERATIONS
|
||||
if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
|
||||
while(cnt + AES_BLOCK_SIZE <= len) {
|
||||
assert(b_pos == 0);
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
|
||||
lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
|
||||
lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
|
||||
lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
cnt += AES_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while(cnt + AES_BLOCK_SIZE <= len) {
|
||||
assert(b_pos == 0);
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
obuf[0] = iv[0] ^= ibuf[0];
|
||||
obuf[1] = iv[1] ^= ibuf[1];
|
||||
obuf[2] = iv[2] ^= ibuf[2];
|
||||
obuf[3] = iv[3] ^= ibuf[3];
|
||||
obuf[4] = iv[4] ^= ibuf[4];
|
||||
obuf[5] = iv[5] ^= ibuf[5];
|
||||
obuf[6] = iv[6] ^= ibuf[6];
|
||||
obuf[7] = iv[7] ^= ibuf[7];
|
||||
obuf[8] = iv[8] ^= ibuf[8];
|
||||
obuf[9] = iv[9] ^= ibuf[9];
|
||||
obuf[10] = iv[10] ^= ibuf[10];
|
||||
obuf[11] = iv[11] ^= ibuf[11];
|
||||
obuf[12] = iv[12] ^= ibuf[12];
|
||||
obuf[13] = iv[13] ^= ibuf[13];
|
||||
obuf[14] = iv[14] ^= ibuf[14];
|
||||
obuf[15] = iv[15] ^= ibuf[15];
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
cnt += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while(cnt < len) {
|
||||
if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
|
||||
while(cnt < len && b_pos < AES_BLOCK_SIZE) {
|
||||
*obuf++ = (iv[b_pos++] ^= *ibuf++);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
|
||||
}
|
||||
|
||||
ctx->inf.b[2] = (uint8_t)b_pos;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_cfb_decrypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
aes_encrypt_ctx ctx[1]) {
|
||||
int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
|
||||
|
||||
if(b_pos) /* complete any partial block */
|
||||
{
|
||||
uint8_t t;
|
||||
|
||||
while(b_pos < AES_BLOCK_SIZE && cnt < len) {
|
||||
t = *ibuf++;
|
||||
*obuf++ = t ^ iv[b_pos];
|
||||
iv[b_pos++] = t;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
|
||||
}
|
||||
|
||||
if((nb = (len - cnt) >> AES_BLOCK_SIZE_P2) != 0) /* process whole blocks */
|
||||
{
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
int m;
|
||||
uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
|
||||
aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
|
||||
via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
|
||||
{
|
||||
ivp = liv;
|
||||
memcpy(liv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
|
||||
via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
|
||||
ibuf += nb * AES_BLOCK_SIZE;
|
||||
obuf += nb * AES_BLOCK_SIZE;
|
||||
cnt += nb * AES_BLOCK_SIZE;
|
||||
} else /* input, output or both are unaligned */
|
||||
{
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) /* input buffer is not aligned */
|
||||
memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_cfb_op6(ksp, cwd, ip, op, m, ivp);
|
||||
|
||||
if(op != obuf) /* output buffer is not aligned */
|
||||
memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
cnt += m * AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE);
|
||||
}
|
||||
#else
|
||||
#ifdef FAST_BUFFER_OPERATIONS
|
||||
if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
|
||||
while(cnt + AES_BLOCK_SIZE <= len) {
|
||||
uint32_t t;
|
||||
|
||||
assert(b_pos == 0);
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
|
||||
t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
|
||||
t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
|
||||
t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
cnt += AES_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while(cnt + AES_BLOCK_SIZE <= len) {
|
||||
uint8_t t;
|
||||
|
||||
assert(b_pos == 0);
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
t = ibuf[0], obuf[0] = t ^ iv[0], iv[0] = t;
|
||||
t = ibuf[1], obuf[1] = t ^ iv[1], iv[1] = t;
|
||||
t = ibuf[2], obuf[2] = t ^ iv[2], iv[2] = t;
|
||||
t = ibuf[3], obuf[3] = t ^ iv[3], iv[3] = t;
|
||||
t = ibuf[4], obuf[4] = t ^ iv[4], iv[4] = t;
|
||||
t = ibuf[5], obuf[5] = t ^ iv[5], iv[5] = t;
|
||||
t = ibuf[6], obuf[6] = t ^ iv[6], iv[6] = t;
|
||||
t = ibuf[7], obuf[7] = t ^ iv[7], iv[7] = t;
|
||||
t = ibuf[8], obuf[8] = t ^ iv[8], iv[8] = t;
|
||||
t = ibuf[9], obuf[9] = t ^ iv[9], iv[9] = t;
|
||||
t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
|
||||
t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
|
||||
t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
|
||||
t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
|
||||
t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
|
||||
t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
cnt += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while(cnt < len) {
|
||||
uint8_t t;
|
||||
|
||||
if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
|
||||
while(cnt < len && b_pos < AES_BLOCK_SIZE) {
|
||||
t = *ibuf++;
|
||||
*obuf++ = t ^ iv[b_pos];
|
||||
iv[b_pos++] = t;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
|
||||
}
|
||||
|
||||
ctx->inf.b[2] = (uint8_t)b_pos;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ofb_crypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* iv,
|
||||
aes_encrypt_ctx ctx[1]) {
|
||||
int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
|
||||
|
||||
if(b_pos) /* complete any partial block */
|
||||
{
|
||||
while(b_pos < AES_BLOCK_SIZE && cnt < len) {
|
||||
*obuf++ = iv[b_pos++] ^ *ibuf++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
|
||||
}
|
||||
|
||||
if((nb = (len - cnt) >> AES_BLOCK_SIZE_P2) != 0) /* process whole blocks */
|
||||
{
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
int m;
|
||||
uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
|
||||
aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
|
||||
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
|
||||
|
||||
if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
|
||||
if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
|
||||
{
|
||||
ivp = liv;
|
||||
memcpy(liv, iv, AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
|
||||
via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
|
||||
ibuf += nb * AES_BLOCK_SIZE;
|
||||
obuf += nb * AES_BLOCK_SIZE;
|
||||
cnt += nb * AES_BLOCK_SIZE;
|
||||
} else /* input, output or both are unaligned */
|
||||
{
|
||||
aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
|
||||
uint8_t *ip = NULL, *op = NULL;
|
||||
|
||||
while(nb) {
|
||||
m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
|
||||
|
||||
ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
|
||||
op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
|
||||
|
||||
if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
|
||||
|
||||
via_ofb_op6(ksp, cwd, ip, op, m, ivp);
|
||||
|
||||
if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
|
||||
|
||||
ibuf += m * AES_BLOCK_SIZE;
|
||||
obuf += m * AES_BLOCK_SIZE;
|
||||
cnt += m * AES_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE);
|
||||
}
|
||||
#else
|
||||
#ifdef FAST_BUFFER_OPERATIONS
|
||||
if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
|
||||
while(cnt + AES_BLOCK_SIZE <= len) {
|
||||
assert(b_pos == 0);
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
|
||||
lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
|
||||
lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
|
||||
lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
cnt += AES_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while(cnt + AES_BLOCK_SIZE <= len) {
|
||||
assert(b_pos == 0);
|
||||
if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
obuf[0] = iv[0] ^ ibuf[0];
|
||||
obuf[1] = iv[1] ^ ibuf[1];
|
||||
obuf[2] = iv[2] ^ ibuf[2];
|
||||
obuf[3] = iv[3] ^ ibuf[3];
|
||||
obuf[4] = iv[4] ^ ibuf[4];
|
||||
obuf[5] = iv[5] ^ ibuf[5];
|
||||
obuf[6] = iv[6] ^ ibuf[6];
|
||||
obuf[7] = iv[7] ^ ibuf[7];
|
||||
obuf[8] = iv[8] ^ ibuf[8];
|
||||
obuf[9] = iv[9] ^ ibuf[9];
|
||||
obuf[10] = iv[10] ^ ibuf[10];
|
||||
obuf[11] = iv[11] ^ ibuf[11];
|
||||
obuf[12] = iv[12] ^ ibuf[12];
|
||||
obuf[13] = iv[13] ^ ibuf[13];
|
||||
obuf[14] = iv[14] ^ ibuf[14];
|
||||
obuf[15] = iv[15] ^ ibuf[15];
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
cnt += AES_BLOCK_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while(cnt < len) {
|
||||
if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
|
||||
while(cnt < len && b_pos < AES_BLOCK_SIZE) {
|
||||
*obuf++ = iv[b_pos++] ^ *ibuf++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
|
||||
}
|
||||
|
||||
ctx->inf.b[2] = (uint8_t)b_pos;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE)
|
||||
|
||||
AES_RETURN aes_ctr_crypt(
|
||||
const unsigned char* ibuf,
|
||||
unsigned char* obuf,
|
||||
int len,
|
||||
unsigned char* cbuf,
|
||||
cbuf_inc ctr_inc,
|
||||
aes_encrypt_ctx ctx[1]) {
|
||||
unsigned char* ip;
|
||||
int i = 0, blen = 0, b_pos = (int)(ctx->inf.b[2]);
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
aligned_auto(uint8_t, buf, BFR_LENGTH, 16);
|
||||
if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
|
||||
#else
|
||||
uint8_t buf[BFR_LENGTH] = {0};
|
||||
#endif
|
||||
|
||||
if(b_pos) {
|
||||
memcpy(buf, cbuf, AES_BLOCK_SIZE);
|
||||
if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
|
||||
|
||||
while(b_pos < AES_BLOCK_SIZE && len) {
|
||||
*obuf++ = *ibuf++ ^ buf[b_pos++];
|
||||
--len;
|
||||
}
|
||||
|
||||
if(len) ctr_inc(cbuf), b_pos = 0;
|
||||
}
|
||||
|
||||
while(len) {
|
||||
blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
|
||||
|
||||
for(i = 0, ip = buf; i < (blen >> AES_BLOCK_SIZE_P2); ++i) {
|
||||
memcpy(ip, cbuf, AES_BLOCK_SIZE);
|
||||
ctr_inc(cbuf);
|
||||
ip += AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if(blen & (AES_BLOCK_SIZE - 1)) memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
|
||||
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
if(ctx->inf.b[1] == 0xff) {
|
||||
via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
|
||||
via_ecb_op5((ctx->ks), cwd, buf, buf, i);
|
||||
} else
|
||||
#endif
|
||||
if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
i = 0;
|
||||
ip = buf;
|
||||
#ifdef FAST_BUFFER_OPERATIONS
|
||||
if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(ip, 4))
|
||||
while(i + AES_BLOCK_SIZE <= blen) {
|
||||
lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
|
||||
lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
|
||||
lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
|
||||
lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
|
||||
i += AES_BLOCK_SIZE;
|
||||
ip += AES_BLOCK_SIZE;
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
while(i + AES_BLOCK_SIZE <= blen) {
|
||||
obuf[0] = ibuf[0] ^ ip[0];
|
||||
obuf[1] = ibuf[1] ^ ip[1];
|
||||
obuf[2] = ibuf[2] ^ ip[2];
|
||||
obuf[3] = ibuf[3] ^ ip[3];
|
||||
obuf[4] = ibuf[4] ^ ip[4];
|
||||
obuf[5] = ibuf[5] ^ ip[5];
|
||||
obuf[6] = ibuf[6] ^ ip[6];
|
||||
obuf[7] = ibuf[7] ^ ip[7];
|
||||
obuf[8] = ibuf[8] ^ ip[8];
|
||||
obuf[9] = ibuf[9] ^ ip[9];
|
||||
obuf[10] = ibuf[10] ^ ip[10];
|
||||
obuf[11] = ibuf[11] ^ ip[11];
|
||||
obuf[12] = ibuf[12] ^ ip[12];
|
||||
obuf[13] = ibuf[13] ^ ip[13];
|
||||
obuf[14] = ibuf[14] ^ ip[14];
|
||||
obuf[15] = ibuf[15] ^ ip[15];
|
||||
i += AES_BLOCK_SIZE;
|
||||
ip += AES_BLOCK_SIZE;
|
||||
ibuf += AES_BLOCK_SIZE;
|
||||
obuf += AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
while(i++ < blen) *obuf++ = *ibuf++ ^ ip[b_pos++];
|
||||
}
|
||||
|
||||
ctx->inf.b[2] = (uint8_t)b_pos;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void aes_ctr_cbuf_inc(unsigned char* cbuf) {
|
||||
int i = AES_BLOCK_SIZE - 1;
|
||||
while(i >= 0) {
|
||||
cbuf[i]++;
|
||||
if(cbuf[i]) return; // if there was no overflow
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
*/
|
||||
|
||||
#include "aesopt.h"
|
||||
#include "aestab.h"
|
||||
|
||||
#if defined(USE_INTEL_AES_IF_PRESENT)
|
||||
#include "aes_ni.h"
|
||||
#else
|
||||
/* map names here to provide the external API ('name' -> 'aes_name') */
|
||||
#define aes_xi(x) aes_##x
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define si(y, x, k, c) (s(y, c) = word_in(x, c) ^ (k)[c])
|
||||
#define so(y, x, c) word_out(y, c, s(x, c))
|
||||
|
||||
#if defined(ARRAYS)
|
||||
#define locals(y, x) x[4], y[4]
|
||||
#else
|
||||
#define locals(y, x) x##0, x##1, x##2, x##3, y##0, y##1, y##2, y##3
|
||||
#endif
|
||||
|
||||
#define l_copy(y, x) \
|
||||
s(y, 0) = s(x, 0); \
|
||||
s(y, 1) = s(x, 1); \
|
||||
s(y, 2) = s(x, 2); \
|
||||
s(y, 3) = s(x, 3);
|
||||
#define state_in(y, x, k) \
|
||||
si(y, x, k, 0); \
|
||||
si(y, x, k, 1); \
|
||||
si(y, x, k, 2); \
|
||||
si(y, x, k, 3)
|
||||
#define state_out(y, x) \
|
||||
so(y, x, 0); \
|
||||
so(y, x, 1); \
|
||||
so(y, x, 2); \
|
||||
so(y, x, 3)
|
||||
#define round(rm, y, x, k) \
|
||||
rm(y, x, k, 0); \
|
||||
rm(y, x, k, 1); \
|
||||
rm(y, x, k, 2); \
|
||||
rm(y, x, k, 3)
|
||||
|
||||
#if(FUNCS_IN_C & ENCRYPTION_IN_C)
|
||||
|
||||
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
|
||||
Pentium optimiation with small code but this is poor for decryption
|
||||
so we need to control this with the following VC++ pragmas
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64) && !defined(__clang__)
|
||||
#pragma optimize("s", on)
|
||||
#endif
|
||||
|
||||
/* Given the column (c) of the output state variable, the following
|
||||
macros give the input state variables which are needed in its
|
||||
computation for each row (r) of the state. All the alternative
|
||||
macros give the same end values but expand into different ways
|
||||
of calculating these values. In particular the complex macro
|
||||
used for dynamically variable block sizes is designed to expand
|
||||
to a compile time constant whenever possible but will expand to
|
||||
conditional clauses on some branches (I am grateful to Frank
|
||||
Yellin for this construction)
|
||||
*/
|
||||
|
||||
#define fwd_var(x, r, c) \
|
||||
(r == 0 ? (c == 0 ? s(x, 0) : \
|
||||
c == 1 ? s(x, 1) : \
|
||||
c == 2 ? s(x, 2) : \
|
||||
s(x, 3)) : \
|
||||
r == 1 ? (c == 0 ? s(x, 1) : \
|
||||
c == 1 ? s(x, 2) : \
|
||||
c == 2 ? s(x, 3) : \
|
||||
s(x, 0)) : \
|
||||
r == 2 ? (c == 0 ? s(x, 2) : \
|
||||
c == 1 ? s(x, 3) : \
|
||||
c == 2 ? s(x, 0) : \
|
||||
s(x, 1)) : \
|
||||
(c == 0 ? s(x, 3) : \
|
||||
c == 1 ? s(x, 0) : \
|
||||
c == 2 ? s(x, 1) : \
|
||||
s(x, 2)))
|
||||
|
||||
#if defined(FT4_SET)
|
||||
#undef dec_fmvars
|
||||
#define fwd_rnd(y, x, k, c) (s(y, c) = (k)[c] ^ four_tables(x, t_use(f, n), fwd_var, rf1, c))
|
||||
#elif defined(FT1_SET)
|
||||
#undef dec_fmvars
|
||||
#define fwd_rnd(y, x, k, c) (s(y, c) = (k)[c] ^ one_table(x, upr, t_use(f, n), fwd_var, rf1, c))
|
||||
#else
|
||||
#define fwd_rnd(y, x, k, c) \
|
||||
(s(y, c) = (k)[c] ^ fwd_mcol(no_table(x, t_use(s, box), fwd_var, rf1, c)))
|
||||
#endif
|
||||
|
||||
#if defined(FL4_SET)
|
||||
#define fwd_lrnd(y, x, k, c) (s(y, c) = (k)[c] ^ four_tables(x, t_use(f, l), fwd_var, rf1, c))
|
||||
#elif defined(FL1_SET)
|
||||
#define fwd_lrnd(y, x, k, c) (s(y, c) = (k)[c] ^ one_table(x, ups, t_use(f, l), fwd_var, rf1, c))
|
||||
#else
|
||||
#define fwd_lrnd(y, x, k, c) (s(y, c) = (k)[c] ^ no_table(x, t_use(s, box), fwd_var, rf1, c))
|
||||
#endif
|
||||
|
||||
AES_RETURN
|
||||
aes_xi(encrypt)(const unsigned char* in, unsigned char* out, const aes_encrypt_ctx cx[1]) {
|
||||
uint32_t locals(b0, b1);
|
||||
const uint32_t* kp = NULL;
|
||||
#if defined(dec_fmvars)
|
||||
dec_fmvars; /* declare variables for fwd_mcol() if needed */
|
||||
#endif
|
||||
|
||||
if(cx->inf.b[0] != 10 * AES_BLOCK_SIZE && cx->inf.b[0] != 12 * AES_BLOCK_SIZE &&
|
||||
cx->inf.b[0] != 14 * AES_BLOCK_SIZE)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
kp = cx->ks;
|
||||
state_in(b0, in, kp);
|
||||
|
||||
#if(ENC_UNROLL == FULL)
|
||||
|
||||
switch(cx->inf.b[0]) {
|
||||
case 14 * AES_BLOCK_SIZE:
|
||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
||||
kp += 2 * N_COLS;
|
||||
//-fallthrough
|
||||
case 12 * AES_BLOCK_SIZE:
|
||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
||||
kp += 2 * N_COLS;
|
||||
//-fallthrough
|
||||
case 10 * AES_BLOCK_SIZE:
|
||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 3 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 4 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 5 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 6 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 7 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 8 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 9 * N_COLS);
|
||||
round(fwd_lrnd, b0, b1, kp + 10 * N_COLS);
|
||||
//-fallthrough
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if(ENC_UNROLL == PARTIAL)
|
||||
{
|
||||
uint32_t rnd;
|
||||
for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) {
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b1, b0, kp);
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b0, b1, kp);
|
||||
}
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b1, b0, kp);
|
||||
#else
|
||||
{
|
||||
uint32_t rnd;
|
||||
for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) {
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b1, b0, kp);
|
||||
l_copy(b0, b1);
|
||||
}
|
||||
#endif
|
||||
kp += N_COLS;
|
||||
round(fwd_lrnd, b0, b1, kp);
|
||||
}
|
||||
#endif
|
||||
|
||||
state_out(out, b0);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if(FUNCS_IN_C & DECRYPTION_IN_C)
|
||||
|
||||
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
|
||||
Pentium optimiation with small code but this is poor for decryption
|
||||
so we need to control this with the following VC++ pragmas
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WIN64) && !defined(__clang__)
|
||||
#pragma optimize("t", on)
|
||||
#endif
|
||||
|
||||
/* Given the column (c) of the output state variable, the following
|
||||
macros give the input state variables which are needed in its
|
||||
computation for each row (r) of the state. All the alternative
|
||||
macros give the same end values but expand into different ways
|
||||
of calculating these values. In particular the complex macro
|
||||
used for dynamically variable block sizes is designed to expand
|
||||
to a compile time constant whenever possible but will expand to
|
||||
conditional clauses on some branches (I am grateful to Frank
|
||||
Yellin for this construction)
|
||||
*/
|
||||
|
||||
#define inv_var(x, r, c) \
|
||||
(r == 0 ? (c == 0 ? s(x, 0) : \
|
||||
c == 1 ? s(x, 1) : \
|
||||
c == 2 ? s(x, 2) : \
|
||||
s(x, 3)) : \
|
||||
r == 1 ? (c == 0 ? s(x, 3) : \
|
||||
c == 1 ? s(x, 0) : \
|
||||
c == 2 ? s(x, 1) : \
|
||||
s(x, 2)) : \
|
||||
r == 2 ? (c == 0 ? s(x, 2) : \
|
||||
c == 1 ? s(x, 3) : \
|
||||
c == 2 ? s(x, 0) : \
|
||||
s(x, 1)) : \
|
||||
(c == 0 ? s(x, 1) : \
|
||||
c == 1 ? s(x, 2) : \
|
||||
c == 2 ? s(x, 3) : \
|
||||
s(x, 0)))
|
||||
|
||||
#if defined(IT4_SET)
|
||||
#undef dec_imvars
|
||||
#define inv_rnd(y, x, k, c) (s(y, c) = (k)[c] ^ four_tables(x, t_use(i, n), inv_var, rf1, c))
|
||||
#elif defined(IT1_SET)
|
||||
#undef dec_imvars
|
||||
#define inv_rnd(y, x, k, c) (s(y, c) = (k)[c] ^ one_table(x, upr, t_use(i, n), inv_var, rf1, c))
|
||||
#else
|
||||
#define inv_rnd(y, x, k, c) \
|
||||
(s(y, c) = inv_mcol((k)[c] ^ no_table(x, t_use(i, box), inv_var, rf1, c)))
|
||||
#endif
|
||||
|
||||
#if defined(IL4_SET)
|
||||
#define inv_lrnd(y, x, k, c) (s(y, c) = (k)[c] ^ four_tables(x, t_use(i, l), inv_var, rf1, c))
|
||||
#elif defined(IL1_SET)
|
||||
#define inv_lrnd(y, x, k, c) (s(y, c) = (k)[c] ^ one_table(x, ups, t_use(i, l), inv_var, rf1, c))
|
||||
#else
|
||||
#define inv_lrnd(y, x, k, c) (s(y, c) = (k)[c] ^ no_table(x, t_use(i, box), inv_var, rf1, c))
|
||||
#endif
|
||||
|
||||
/* This code can work with the decryption key schedule in the */
|
||||
/* order that is used for encrytpion (where the 1st decryption */
|
||||
/* round key is at the high end ot the schedule) or with a key */
|
||||
/* schedule that has been reversed to put the 1st decryption */
|
||||
/* round key at the low end of the schedule in memory (when */
|
||||
/* AES_REV_DKS is defined) */
|
||||
|
||||
#ifdef AES_REV_DKS
|
||||
#define key_ofs 0
|
||||
#define rnd_key(n) (kp + n * N_COLS)
|
||||
#else
|
||||
#define key_ofs 1
|
||||
#define rnd_key(n) (kp - n * N_COLS)
|
||||
#endif
|
||||
|
||||
AES_RETURN
|
||||
aes_xi(decrypt)(const unsigned char* in, unsigned char* out, const aes_decrypt_ctx cx[1]) {
|
||||
uint32_t locals(b0, b1);
|
||||
#if defined(dec_imvars)
|
||||
dec_imvars; /* declare variables for inv_mcol() if needed */
|
||||
#endif
|
||||
const uint32_t* kp = NULL;
|
||||
|
||||
if(cx->inf.b[0] != 10 * AES_BLOCK_SIZE && cx->inf.b[0] != 12 * AES_BLOCK_SIZE &&
|
||||
cx->inf.b[0] != 14 * AES_BLOCK_SIZE)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0);
|
||||
state_in(b0, in, kp);
|
||||
|
||||
#if(DEC_UNROLL == FULL)
|
||||
|
||||
kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2));
|
||||
switch(cx->inf.b[0]) {
|
||||
case 14 * AES_BLOCK_SIZE:
|
||||
round(inv_rnd, b1, b0, rnd_key(-13));
|
||||
round(inv_rnd, b0, b1, rnd_key(-12));
|
||||
//-fallthrough
|
||||
case 12 * AES_BLOCK_SIZE:
|
||||
round(inv_rnd, b1, b0, rnd_key(-11));
|
||||
round(inv_rnd, b0, b1, rnd_key(-10));
|
||||
//-fallthrough
|
||||
case 10 * AES_BLOCK_SIZE:
|
||||
round(inv_rnd, b1, b0, rnd_key(-9));
|
||||
round(inv_rnd, b0, b1, rnd_key(-8));
|
||||
round(inv_rnd, b1, b0, rnd_key(-7));
|
||||
round(inv_rnd, b0, b1, rnd_key(-6));
|
||||
round(inv_rnd, b1, b0, rnd_key(-5));
|
||||
round(inv_rnd, b0, b1, rnd_key(-4));
|
||||
round(inv_rnd, b1, b0, rnd_key(-3));
|
||||
round(inv_rnd, b0, b1, rnd_key(-2));
|
||||
round(inv_rnd, b1, b0, rnd_key(-1));
|
||||
round(inv_lrnd, b0, b1, rnd_key(0));
|
||||
//-fallthrough
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if(DEC_UNROLL == PARTIAL)
|
||||
{
|
||||
uint32_t rnd;
|
||||
for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) {
|
||||
kp = rnd_key(1);
|
||||
round(inv_rnd, b1, b0, kp);
|
||||
kp = rnd_key(1);
|
||||
round(inv_rnd, b0, b1, kp);
|
||||
}
|
||||
kp = rnd_key(1);
|
||||
round(inv_rnd, b1, b0, kp);
|
||||
#else
|
||||
{
|
||||
uint32_t rnd;
|
||||
for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) {
|
||||
kp = rnd_key(1);
|
||||
round(inv_rnd, b1, b0, kp);
|
||||
l_copy(b0, b1);
|
||||
}
|
||||
#endif
|
||||
kp = rnd_key(1);
|
||||
round(inv_lrnd, b0, b1, kp);
|
||||
}
|
||||
#endif
|
||||
|
||||
state_out(out, b0);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -1,662 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
*/
|
||||
|
||||
#include "aesopt.h"
|
||||
#include "aestab.h"
|
||||
|
||||
#if defined(USE_INTEL_AES_IF_PRESENT)
|
||||
#include "aes_ni.h"
|
||||
#else
|
||||
/* map names here to provide the external API ('name' -> 'aes_name') */
|
||||
#define aes_xi(x) aes_##x
|
||||
#endif
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
#include "aes_via_ace.h"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initialise the key schedule from the user supplied key. The key
|
||||
length can be specified in bytes, with legal values of 16, 24
|
||||
and 32, or in bits, with legal values of 128, 192 and 256. These
|
||||
values correspond with Nk values of 4, 6 and 8 respectively.
|
||||
|
||||
The following macros implement a single cycle in the key
|
||||
schedule generation process. The number of cycles needed
|
||||
for each cx->n_col and nk value is:
|
||||
|
||||
nk = 4 5 6 7 8
|
||||
------------------------------
|
||||
cx->n_col = 4 10 9 8 7 7
|
||||
cx->n_col = 5 14 11 10 9 9
|
||||
cx->n_col = 6 19 15 12 11 11
|
||||
cx->n_col = 7 21 19 16 13 14
|
||||
cx->n_col = 8 29 23 19 17 14
|
||||
*/
|
||||
|
||||
#if defined(REDUCE_CODE_SIZE)
|
||||
#define ls_box ls_sub
|
||||
uint32_t ls_sub(const uint32_t t, const uint32_t n);
|
||||
#define inv_mcol im_sub
|
||||
uint32_t im_sub(const uint32_t x);
|
||||
#ifdef ENC_KS_UNROLL
|
||||
#undef ENC_KS_UNROLL
|
||||
#endif
|
||||
#ifdef DEC_KS_UNROLL
|
||||
#undef DEC_KS_UNROLL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if(FUNCS_IN_C & ENC_KEYING_IN_C)
|
||||
|
||||
#if defined(AES_128) || defined(AES_VAR)
|
||||
|
||||
#define ke4(k, i) \
|
||||
{ \
|
||||
k[4 * (i) + 4] = ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \
|
||||
k[4 * (i) + 5] = ss[1] ^= ss[0]; \
|
||||
k[4 * (i) + 6] = ss[2] ^= ss[1]; \
|
||||
k[4 * (i) + 7] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
AES_RETURN aes_xi(encrypt_key128)(const unsigned char* key, aes_encrypt_ctx cx[1]) {
|
||||
uint32_t ss[4];
|
||||
|
||||
cx->ks[0] = ss[0] = word_in(key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(key, 3);
|
||||
|
||||
#ifdef ENC_KS_UNROLL
|
||||
ke4(cx->ks, 0);
|
||||
ke4(cx->ks, 1);
|
||||
ke4(cx->ks, 2);
|
||||
ke4(cx->ks, 3);
|
||||
ke4(cx->ks, 4);
|
||||
ke4(cx->ks, 5);
|
||||
ke4(cx->ks, 6);
|
||||
ke4(cx->ks, 7);
|
||||
ke4(cx->ks, 8);
|
||||
#else
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < 9; ++i) ke4(cx->ks, i);
|
||||
}
|
||||
#endif
|
||||
ke4(cx->ks, 9);
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 10 * AES_BLOCK_SIZE;
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff;
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_192) || defined(AES_VAR)
|
||||
|
||||
#define kef6(k, i) \
|
||||
{ \
|
||||
k[6 * (i) + 6] = ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \
|
||||
k[6 * (i) + 7] = ss[1] ^= ss[0]; \
|
||||
k[6 * (i) + 8] = ss[2] ^= ss[1]; \
|
||||
k[6 * (i) + 9] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#define ke6(k, i) \
|
||||
{ \
|
||||
kef6(k, i); \
|
||||
k[6 * (i) + 10] = ss[4] ^= ss[3]; \
|
||||
k[6 * (i) + 11] = ss[5] ^= ss[4]; \
|
||||
}
|
||||
|
||||
AES_RETURN aes_xi(encrypt_key192)(const unsigned char* key, aes_encrypt_ctx cx[1]) {
|
||||
uint32_t ss[6];
|
||||
|
||||
cx->ks[0] = ss[0] = word_in(key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(key, 3);
|
||||
cx->ks[4] = ss[4] = word_in(key, 4);
|
||||
cx->ks[5] = ss[5] = word_in(key, 5);
|
||||
|
||||
#ifdef ENC_KS_UNROLL
|
||||
ke6(cx->ks, 0);
|
||||
ke6(cx->ks, 1);
|
||||
ke6(cx->ks, 2);
|
||||
ke6(cx->ks, 3);
|
||||
ke6(cx->ks, 4);
|
||||
ke6(cx->ks, 5);
|
||||
ke6(cx->ks, 6);
|
||||
#else
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < 7; ++i) ke6(cx->ks, i);
|
||||
}
|
||||
#endif
|
||||
kef6(cx->ks, 7);
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 12 * AES_BLOCK_SIZE;
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff;
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_256) || defined(AES_VAR)
|
||||
|
||||
#define kef8(k, i) \
|
||||
{ \
|
||||
k[8 * (i) + 8] = ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \
|
||||
k[8 * (i) + 9] = ss[1] ^= ss[0]; \
|
||||
k[8 * (i) + 10] = ss[2] ^= ss[1]; \
|
||||
k[8 * (i) + 11] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#define ke8(k, i) \
|
||||
{ \
|
||||
kef8(k, i); \
|
||||
k[8 * (i) + 12] = ss[4] ^= ls_box(ss[3], 0); \
|
||||
k[8 * (i) + 13] = ss[5] ^= ss[4]; \
|
||||
k[8 * (i) + 14] = ss[6] ^= ss[5]; \
|
||||
k[8 * (i) + 15] = ss[7] ^= ss[6]; \
|
||||
}
|
||||
|
||||
AES_RETURN aes_xi(encrypt_key256)(const unsigned char* key, aes_encrypt_ctx cx[1]) {
|
||||
uint32_t ss[8];
|
||||
|
||||
cx->ks[0] = ss[0] = word_in(key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(key, 3);
|
||||
cx->ks[4] = ss[4] = word_in(key, 4);
|
||||
cx->ks[5] = ss[5] = word_in(key, 5);
|
||||
cx->ks[6] = ss[6] = word_in(key, 6);
|
||||
cx->ks[7] = ss[7] = word_in(key, 7);
|
||||
|
||||
#ifdef ENC_KS_UNROLL
|
||||
ke8(cx->ks, 0);
|
||||
ke8(cx->ks, 1);
|
||||
ke8(cx->ks, 2);
|
||||
ke8(cx->ks, 3);
|
||||
ke8(cx->ks, 4);
|
||||
ke8(cx->ks, 5);
|
||||
#else
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < 6; ++i) ke8(cx->ks, i);
|
||||
}
|
||||
#endif
|
||||
kef8(cx->ks, 6);
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 14 * AES_BLOCK_SIZE;
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff;
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if(FUNCS_IN_C & DEC_KEYING_IN_C)
|
||||
|
||||
/* this is used to store the decryption round keys */
|
||||
/* in forward or reverse order */
|
||||
|
||||
#ifdef AES_REV_DKS
|
||||
#define v(n, i) ((n) - (i) + 2 * ((i)&3))
|
||||
#else
|
||||
#define v(n, i) (i)
|
||||
#endif
|
||||
|
||||
#if DEC_ROUND == NO_TABLES
|
||||
#define ff(x) (x)
|
||||
#else
|
||||
#define ff(x) inv_mcol(x)
|
||||
#if defined(dec_imvars)
|
||||
#define d_vars dec_imvars
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(AES_128) || defined(AES_VAR)
|
||||
|
||||
#define k4e(k, i) \
|
||||
{ \
|
||||
k[v(40, (4 * (i)) + 4)] = ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ss[1] ^= ss[0]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ss[2] ^= ss[1]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#if 1
|
||||
|
||||
#define kdf4(k, i) \
|
||||
{ \
|
||||
ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \
|
||||
ss[1] = ss[1] ^ ss[3]; \
|
||||
ss[2] = ss[2] ^ ss[3]; \
|
||||
ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ t_use(r, c)[i]; \
|
||||
ss[i % 4] ^= ss[4]; \
|
||||
ss[4] ^= k[v(40, (4 * (i)))]; \
|
||||
k[v(40, (4 * (i)) + 4)] = ff(ss[4]); \
|
||||
ss[4] ^= k[v(40, (4 * (i)) + 1)]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ff(ss[4]); \
|
||||
ss[4] ^= k[v(40, (4 * (i)) + 2)]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ff(ss[4]); \
|
||||
ss[4] ^= k[v(40, (4 * (i)) + 3)]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ff(ss[4]); \
|
||||
}
|
||||
|
||||
#define kd4(k, i) \
|
||||
{ \
|
||||
ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ t_use(r, c)[i]; \
|
||||
ss[i % 4] ^= ss[4]; \
|
||||
ss[4] = ff(ss[4]); \
|
||||
k[v(40, (4 * (i)) + 4)] = ss[4] ^= k[v(40, (4 * (i)))]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ss[4] ^= k[v(40, (4 * (i)) + 1)]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ss[4] ^= k[v(40, (4 * (i)) + 2)]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ss[4] ^= k[v(40, (4 * (i)) + 3)]; \
|
||||
}
|
||||
|
||||
#define kdl4(k, i) \
|
||||
{ \
|
||||
ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ t_use(r, c)[i]; \
|
||||
ss[i % 4] ^= ss[4]; \
|
||||
k[v(40, (4 * (i)) + 4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ss[1] ^ ss[3]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ss[0]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ss[1]; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define kdf4(k, i) \
|
||||
{ \
|
||||
ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(40, (4 * (i)) + 4)] = ff(ss[0]); \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ff(ss[1]); \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ff(ss[2]); \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ff(ss[3]); \
|
||||
}
|
||||
|
||||
#define kd4(k, i) \
|
||||
{ \
|
||||
ss[4] = ls_box(ss[3], 3) ^ t_use(r, c)[i]; \
|
||||
ss[0] ^= ss[4]; \
|
||||
ss[4] = ff(ss[4]); \
|
||||
k[v(40, (4 * (i)) + 4)] = ss[4] ^= k[v(40, (4 * (i)))]; \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ss[4] ^= k[v(40, (4 * (i)) + 1)]; \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ss[4] ^= k[v(40, (4 * (i)) + 2)]; \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ss[4] ^= k[v(40, (4 * (i)) + 3)]; \
|
||||
}
|
||||
|
||||
#define kdl4(k, i) \
|
||||
{ \
|
||||
ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(40, (4 * (i)) + 4)] = ss[0]; \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(40, (4 * (i)) + 5)] = ss[1]; \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(40, (4 * (i)) + 6)] = ss[2]; \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(40, (4 * (i)) + 7)] = ss[3]; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
AES_RETURN aes_xi(decrypt_key128)(const unsigned char* key, aes_decrypt_ctx cx[1]) {
|
||||
uint32_t ss[5];
|
||||
#if defined(d_vars)
|
||||
d_vars;
|
||||
#endif
|
||||
|
||||
cx->ks[v(40, (0))] = ss[0] = word_in(key, 0);
|
||||
cx->ks[v(40, (1))] = ss[1] = word_in(key, 1);
|
||||
cx->ks[v(40, (2))] = ss[2] = word_in(key, 2);
|
||||
cx->ks[v(40, (3))] = ss[3] = word_in(key, 3);
|
||||
|
||||
#ifdef DEC_KS_UNROLL
|
||||
kdf4(cx->ks, 0);
|
||||
kd4(cx->ks, 1);
|
||||
kd4(cx->ks, 2);
|
||||
kd4(cx->ks, 3);
|
||||
kd4(cx->ks, 4);
|
||||
kd4(cx->ks, 5);
|
||||
kd4(cx->ks, 6);
|
||||
kd4(cx->ks, 7);
|
||||
kd4(cx->ks, 8);
|
||||
kdl4(cx->ks, 9);
|
||||
#else
|
||||
{
|
||||
uint32_t i;
|
||||
for(i = 0; i < 10; ++i) k4e(cx->ks, i);
|
||||
#if !(DEC_ROUND == NO_TABLES)
|
||||
for(i = N_COLS; i < 10 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 10 * AES_BLOCK_SIZE;
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff;
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_192) || defined(AES_VAR)
|
||||
|
||||
#define k6ef(k, i) \
|
||||
{ \
|
||||
k[v(48, (6 * (i)) + 6)] = ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(48, (6 * (i)) + 7)] = ss[1] ^= ss[0]; \
|
||||
k[v(48, (6 * (i)) + 8)] = ss[2] ^= ss[1]; \
|
||||
k[v(48, (6 * (i)) + 9)] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#define k6e(k, i) \
|
||||
{ \
|
||||
k6ef(k, i); \
|
||||
k[v(48, (6 * (i)) + 10)] = ss[4] ^= ss[3]; \
|
||||
k[v(48, (6 * (i)) + 11)] = ss[5] ^= ss[4]; \
|
||||
}
|
||||
|
||||
#define kdf6(k, i) \
|
||||
{ \
|
||||
ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(48, (6 * (i)) + 6)] = ff(ss[0]); \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(48, (6 * (i)) + 7)] = ff(ss[1]); \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(48, (6 * (i)) + 8)] = ff(ss[2]); \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(48, (6 * (i)) + 9)] = ff(ss[3]); \
|
||||
ss[4] ^= ss[3]; \
|
||||
k[v(48, (6 * (i)) + 10)] = ff(ss[4]); \
|
||||
ss[5] ^= ss[4]; \
|
||||
k[v(48, (6 * (i)) + 11)] = ff(ss[5]); \
|
||||
}
|
||||
|
||||
#define kd6(k, i) \
|
||||
{ \
|
||||
ss[6] = ls_box(ss[5], 3) ^ t_use(r, c)[i]; \
|
||||
ss[0] ^= ss[6]; \
|
||||
ss[6] = ff(ss[6]); \
|
||||
k[v(48, (6 * (i)) + 6)] = ss[6] ^= k[v(48, (6 * (i)))]; \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(48, (6 * (i)) + 7)] = ss[6] ^= k[v(48, (6 * (i)) + 1)]; \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(48, (6 * (i)) + 8)] = ss[6] ^= k[v(48, (6 * (i)) + 2)]; \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(48, (6 * (i)) + 9)] = ss[6] ^= k[v(48, (6 * (i)) + 3)]; \
|
||||
ss[4] ^= ss[3]; \
|
||||
k[v(48, (6 * (i)) + 10)] = ss[6] ^= k[v(48, (6 * (i)) + 4)]; \
|
||||
ss[5] ^= ss[4]; \
|
||||
k[v(48, (6 * (i)) + 11)] = ss[6] ^= k[v(48, (6 * (i)) + 5)]; \
|
||||
}
|
||||
|
||||
#define kdl6(k, i) \
|
||||
{ \
|
||||
ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(48, (6 * (i)) + 6)] = ss[0]; \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(48, (6 * (i)) + 7)] = ss[1]; \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(48, (6 * (i)) + 8)] = ss[2]; \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(48, (6 * (i)) + 9)] = ss[3]; \
|
||||
}
|
||||
|
||||
AES_RETURN aes_xi(decrypt_key192)(const unsigned char* key, aes_decrypt_ctx cx[1]) {
|
||||
uint32_t ss[7];
|
||||
#if defined(d_vars)
|
||||
d_vars;
|
||||
#endif
|
||||
|
||||
cx->ks[v(48, (0))] = ss[0] = word_in(key, 0);
|
||||
cx->ks[v(48, (1))] = ss[1] = word_in(key, 1);
|
||||
cx->ks[v(48, (2))] = ss[2] = word_in(key, 2);
|
||||
cx->ks[v(48, (3))] = ss[3] = word_in(key, 3);
|
||||
|
||||
#ifdef DEC_KS_UNROLL
|
||||
ss[4] = word_in(key, 4);
|
||||
ss[5] = word_in(key, 5);
|
||||
cx->ks[v(48, (4))] = ff(ss[4]);
|
||||
cx->ks[v(48, (5))] = ff(ss[5]);
|
||||
kdf6(cx->ks, 0);
|
||||
kd6(cx->ks, 1);
|
||||
kd6(cx->ks, 2);
|
||||
kd6(cx->ks, 3);
|
||||
kd6(cx->ks, 4);
|
||||
kd6(cx->ks, 5);
|
||||
kd6(cx->ks, 6);
|
||||
kdl6(cx->ks, 7);
|
||||
#else
|
||||
cx->ks[v(48, (4))] = ss[4] = word_in(key, 4);
|
||||
cx->ks[v(48, (5))] = ss[5] = word_in(key, 5);
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 7; ++i) k6e(cx->ks, i);
|
||||
k6ef(cx->ks, 7);
|
||||
#if !(DEC_ROUND == NO_TABLES)
|
||||
for(i = N_COLS; i < 12 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 12 * AES_BLOCK_SIZE;
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff;
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_256) || defined(AES_VAR)
|
||||
|
||||
#define k8ef(k, i) \
|
||||
{ \
|
||||
k[v(56, (8 * (i)) + 8)] = ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(56, (8 * (i)) + 9)] = ss[1] ^= ss[0]; \
|
||||
k[v(56, (8 * (i)) + 10)] = ss[2] ^= ss[1]; \
|
||||
k[v(56, (8 * (i)) + 11)] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#define k8e(k, i) \
|
||||
{ \
|
||||
k8ef(k, i); \
|
||||
k[v(56, (8 * (i)) + 12)] = ss[4] ^= ls_box(ss[3], 0); \
|
||||
k[v(56, (8 * (i)) + 13)] = ss[5] ^= ss[4]; \
|
||||
k[v(56, (8 * (i)) + 14)] = ss[6] ^= ss[5]; \
|
||||
k[v(56, (8 * (i)) + 15)] = ss[7] ^= ss[6]; \
|
||||
}
|
||||
|
||||
#define kdf8(k, i) \
|
||||
{ \
|
||||
ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(56, (8 * (i)) + 8)] = ff(ss[0]); \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(56, (8 * (i)) + 9)] = ff(ss[1]); \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(56, (8 * (i)) + 10)] = ff(ss[2]); \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(56, (8 * (i)) + 11)] = ff(ss[3]); \
|
||||
ss[4] ^= ls_box(ss[3], 0); \
|
||||
k[v(56, (8 * (i)) + 12)] = ff(ss[4]); \
|
||||
ss[5] ^= ss[4]; \
|
||||
k[v(56, (8 * (i)) + 13)] = ff(ss[5]); \
|
||||
ss[6] ^= ss[5]; \
|
||||
k[v(56, (8 * (i)) + 14)] = ff(ss[6]); \
|
||||
ss[7] ^= ss[6]; \
|
||||
k[v(56, (8 * (i)) + 15)] = ff(ss[7]); \
|
||||
}
|
||||
|
||||
#define kd8(k, i) \
|
||||
{ \
|
||||
ss[8] = ls_box(ss[7], 3) ^ t_use(r, c)[i]; \
|
||||
ss[0] ^= ss[8]; \
|
||||
ss[8] = ff(ss[8]); \
|
||||
k[v(56, (8 * (i)) + 8)] = ss[8] ^= k[v(56, (8 * (i)))]; \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(56, (8 * (i)) + 9)] = ss[8] ^= k[v(56, (8 * (i)) + 1)]; \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(56, (8 * (i)) + 10)] = ss[8] ^= k[v(56, (8 * (i)) + 2)]; \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(56, (8 * (i)) + 11)] = ss[8] ^= k[v(56, (8 * (i)) + 3)]; \
|
||||
ss[8] = ls_box(ss[3], 0); \
|
||||
ss[4] ^= ss[8]; \
|
||||
ss[8] = ff(ss[8]); \
|
||||
k[v(56, (8 * (i)) + 12)] = ss[8] ^= k[v(56, (8 * (i)) + 4)]; \
|
||||
ss[5] ^= ss[4]; \
|
||||
k[v(56, (8 * (i)) + 13)] = ss[8] ^= k[v(56, (8 * (i)) + 5)]; \
|
||||
ss[6] ^= ss[5]; \
|
||||
k[v(56, (8 * (i)) + 14)] = ss[8] ^= k[v(56, (8 * (i)) + 6)]; \
|
||||
ss[7] ^= ss[6]; \
|
||||
k[v(56, (8 * (i)) + 15)] = ss[8] ^= k[v(56, (8 * (i)) + 7)]; \
|
||||
}
|
||||
|
||||
#define kdl8(k, i) \
|
||||
{ \
|
||||
ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \
|
||||
k[v(56, (8 * (i)) + 8)] = ss[0]; \
|
||||
ss[1] ^= ss[0]; \
|
||||
k[v(56, (8 * (i)) + 9)] = ss[1]; \
|
||||
ss[2] ^= ss[1]; \
|
||||
k[v(56, (8 * (i)) + 10)] = ss[2]; \
|
||||
ss[3] ^= ss[2]; \
|
||||
k[v(56, (8 * (i)) + 11)] = ss[3]; \
|
||||
}
|
||||
|
||||
AES_RETURN aes_xi(decrypt_key256)(const unsigned char* key, aes_decrypt_ctx cx[1]) {
|
||||
uint32_t ss[9];
|
||||
#if defined(d_vars)
|
||||
d_vars;
|
||||
#endif
|
||||
|
||||
cx->ks[v(56, (0))] = ss[0] = word_in(key, 0);
|
||||
cx->ks[v(56, (1))] = ss[1] = word_in(key, 1);
|
||||
cx->ks[v(56, (2))] = ss[2] = word_in(key, 2);
|
||||
cx->ks[v(56, (3))] = ss[3] = word_in(key, 3);
|
||||
|
||||
#ifdef DEC_KS_UNROLL
|
||||
ss[4] = word_in(key, 4);
|
||||
ss[5] = word_in(key, 5);
|
||||
ss[6] = word_in(key, 6);
|
||||
ss[7] = word_in(key, 7);
|
||||
cx->ks[v(56, (4))] = ff(ss[4]);
|
||||
cx->ks[v(56, (5))] = ff(ss[5]);
|
||||
cx->ks[v(56, (6))] = ff(ss[6]);
|
||||
cx->ks[v(56, (7))] = ff(ss[7]);
|
||||
kdf8(cx->ks, 0);
|
||||
kd8(cx->ks, 1);
|
||||
kd8(cx->ks, 2);
|
||||
kd8(cx->ks, 3);
|
||||
kd8(cx->ks, 4);
|
||||
kd8(cx->ks, 5);
|
||||
kdl8(cx->ks, 6);
|
||||
#else
|
||||
cx->ks[v(56, (4))] = ss[4] = word_in(key, 4);
|
||||
cx->ks[v(56, (5))] = ss[5] = word_in(key, 5);
|
||||
cx->ks[v(56, (6))] = ss[6] = word_in(key, 6);
|
||||
cx->ks[v(56, (7))] = ss[7] = word_in(key, 7);
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i = 0; i < 6; ++i) k8e(cx->ks, i);
|
||||
k8ef(cx->ks, 6);
|
||||
#if !(DEC_ROUND == NO_TABLES)
|
||||
for(i = N_COLS; i < 14 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 14 * AES_BLOCK_SIZE;
|
||||
|
||||
#ifdef USE_VIA_ACE_IF_PRESENT
|
||||
if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff;
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_VAR)
|
||||
|
||||
AES_RETURN aes_encrypt_key(const unsigned char* key, int key_len, aes_encrypt_ctx cx[1]) {
|
||||
switch(key_len) {
|
||||
case 16:
|
||||
case 128:
|
||||
return aes_encrypt_key128(key, cx);
|
||||
case 24:
|
||||
case 192:
|
||||
return aes_encrypt_key192(key, cx);
|
||||
case 32:
|
||||
case 256:
|
||||
return aes_encrypt_key256(key, cx);
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
AES_RETURN aes_decrypt_key(const unsigned char* key, int key_len, aes_decrypt_ctx cx[1]) {
|
||||
switch(key_len) {
|
||||
case 16:
|
||||
case 128:
|
||||
return aes_decrypt_key128(key, cx);
|
||||
case 24:
|
||||
case 192:
|
||||
return aes_decrypt_key192(key, cx);
|
||||
case 32:
|
||||
case 256:
|
||||
return aes_decrypt_key256(key, cx);
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -1,793 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
|
||||
This file contains the compilation options for AES (Rijndael) and code
|
||||
that is common across encryption, key scheduling and table generation.
|
||||
|
||||
OPERATION
|
||||
|
||||
These source code files implement the AES algorithm Rijndael designed by
|
||||
Joan Daemen and Vincent Rijmen. This version is designed for the standard
|
||||
block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24
|
||||
and 32 bytes).
|
||||
|
||||
This version is designed for flexibility and speed using operations on
|
||||
32-bit words rather than operations on bytes. It can be compiled with
|
||||
either big or little endian internal byte order but is faster when the
|
||||
native byte order for the processor is used.
|
||||
|
||||
THE CIPHER INTERFACE
|
||||
|
||||
The cipher interface is implemented as an array of bytes in which lower
|
||||
AES bit sequence indexes map to higher numeric significance within bytes.
|
||||
|
||||
uint8_t (an unsigned 8-bit type)
|
||||
uint32_t (an unsigned 32-bit type)
|
||||
struct aes_encrypt_ctx (structure for the cipher encryption context)
|
||||
struct aes_decrypt_ctx (structure for the cipher decryption context)
|
||||
AES_RETURN the function return type
|
||||
|
||||
C subroutine calls:
|
||||
|
||||
AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const aes_decrypt_ctx cx[1]);
|
||||
|
||||
IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that
|
||||
you call aes_init() before AES is used so that the tables are initialised.
|
||||
|
||||
C++ aes class subroutines:
|
||||
|
||||
Class AESencrypt for encryption
|
||||
|
||||
Constructors:
|
||||
AESencrypt(void)
|
||||
AESencrypt(const unsigned char *key) - 128 bit key
|
||||
Members:
|
||||
AES_RETURN key128(const unsigned char *key)
|
||||
AES_RETURN key192(const unsigned char *key)
|
||||
AES_RETURN key256(const unsigned char *key)
|
||||
AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const
|
||||
|
||||
Class AESdecrypt for encryption
|
||||
Constructors:
|
||||
AESdecrypt(void)
|
||||
AESdecrypt(const unsigned char *key) - 128 bit key
|
||||
Members:
|
||||
AES_RETURN key128(const unsigned char *key)
|
||||
AES_RETURN key192(const unsigned char *key)
|
||||
AES_RETURN key256(const unsigned char *key)
|
||||
AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const
|
||||
*/
|
||||
|
||||
#if !defined(_AESOPT_H)
|
||||
#define _AESOPT_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include "aescpp.h"
|
||||
#else
|
||||
#include "aes.h"
|
||||
#endif
|
||||
|
||||
/* PLATFORM SPECIFIC INCLUDES */
|
||||
|
||||
#define IS_BIG_ENDIAN 4321
|
||||
#define IS_LITTLE_ENDIAN 1234
|
||||
#define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||
|
||||
/* CONFIGURATION - THE USE OF DEFINES
|
||||
|
||||
Later in this section there are a number of defines that control the
|
||||
operation of the code. In each section, the purpose of each define is
|
||||
explained so that the relevant form can be included or excluded by
|
||||
setting either 1's or 0's respectively on the branches of the related
|
||||
#if clauses. The following local defines should not be changed.
|
||||
*/
|
||||
|
||||
#define ENCRYPTION_IN_C 1
|
||||
#define DECRYPTION_IN_C 2
|
||||
#define ENC_KEYING_IN_C 4
|
||||
#define DEC_KEYING_IN_C 8
|
||||
|
||||
#define NO_TABLES 0
|
||||
#define ONE_TABLE 1
|
||||
#define FOUR_TABLES 4
|
||||
#define NONE 0
|
||||
#define PARTIAL 1
|
||||
#define FULL 2
|
||||
|
||||
/* --- START OF USER CONFIGURED OPTIONS --- */
|
||||
|
||||
/* 1. BYTE ORDER WITHIN 32 BIT WORDS
|
||||
|
||||
The fundamental data processing units in Rijndael are 8-bit bytes. The
|
||||
input, output and key input are all enumerated arrays of bytes in which
|
||||
bytes are numbered starting at zero and increasing to one less than the
|
||||
number of bytes in the array in question. This enumeration is only used
|
||||
for naming bytes and does not imply any adjacency or order relationship
|
||||
from one byte to another. When these inputs and outputs are considered
|
||||
as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to
|
||||
byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.
|
||||
In this implementation bits are numbered from 0 to 7 starting at the
|
||||
numerically least significant end of each byte (bit n represents 2^n).
|
||||
|
||||
However, Rijndael can be implemented more efficiently using 32-bit
|
||||
words by packing bytes into words so that bytes 4*n to 4*n+3 are placed
|
||||
into word[n]. While in principle these bytes can be assembled into words
|
||||
in any positions, this implementation only supports the two formats in
|
||||
which bytes in adjacent positions within words also have adjacent byte
|
||||
numbers. This order is called big-endian if the lowest numbered bytes
|
||||
in words have the highest numeric significance and little-endian if the
|
||||
opposite applies.
|
||||
|
||||
This code can work in either order irrespective of the order used by the
|
||||
machine on which it runs. Normally the internal byte order will be set
|
||||
to the order of the processor on which the code is to be run but this
|
||||
define can be used to reverse this in special situations
|
||||
|
||||
WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set.
|
||||
This define will hence be redefined later (in section 4) if necessary
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
|
||||
#elif 0
|
||||
#define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN
|
||||
#elif 0
|
||||
#define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN
|
||||
#else
|
||||
#error The algorithm byte order is not defined
|
||||
#endif
|
||||
|
||||
/* 2. Intel AES AND VIA ACE SUPPORT */
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__) && !defined(__BEOS__) || \
|
||||
defined(_WIN32) && defined(_M_IX86) && \
|
||||
!(defined(_WIN64) || defined(_WIN32_WCE) || defined(_MSC_VER) && (_MSC_VER <= 800))
|
||||
#define VIA_ACE_POSSIBLE
|
||||
#endif
|
||||
|
||||
/* AESNI is supported by all Windows x64 compilers, but for Linux/GCC
|
||||
we have to test for SSE 2, SSE 3, and AES to before enabling it; */
|
||||
#if !defined(INTEL_AES_POSSIBLE)
|
||||
#if defined(_WIN64) && defined(_MSC_VER) || defined(__GNUC__) && defined(__x86_64__) && \
|
||||
defined(__SSE2__) && defined(__SSE3__) && \
|
||||
defined(__AES__)
|
||||
#define INTEL_AES_POSSIBLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define this option if support for the Intel AESNI is required
|
||||
If USE_INTEL_AES_IF_PRESENT is defined then AESNI will be used
|
||||
if it is detected (both present and enabled).
|
||||
|
||||
AESNI uses a decryption key schedule with the first decryption
|
||||
round key at the high end of the key scedule with the following
|
||||
round keys at lower positions in memory. So AES_REV_DKS must NOT
|
||||
be defined when AESNI will be used. Although it is unlikely that
|
||||
assembler code will be used with an AESNI build, if it is then
|
||||
AES_REV_DKS must NOT be defined when the assembler files are
|
||||
built (the definition of USE_INTEL_AES_IF_PRESENT in the assembler
|
||||
code files must match that here if they are used).
|
||||
*/
|
||||
|
||||
#if 0 && defined(INTEL_AES_POSSIBLE) && !defined(USE_INTEL_AES_IF_PRESENT)
|
||||
#define USE_INTEL_AES_IF_PRESENT
|
||||
#endif
|
||||
|
||||
/* Define this option if support for the VIA ACE is required. This uses
|
||||
inline assembler instructions and is only implemented for the Microsoft,
|
||||
Intel and GCC compilers. If VIA ACE is known to be present, then defining
|
||||
ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption
|
||||
code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if
|
||||
it is detected (both present and enabled) but the normal AES code will
|
||||
also be present.
|
||||
|
||||
When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte
|
||||
aligned; other input/output buffers do not need to be 16 byte aligned
|
||||
but there are very large performance gains if this can be arranged.
|
||||
VIA ACE also requires the decryption key schedule to be in reverse
|
||||
order (which later checks below ensure).
|
||||
|
||||
AES_REV_DKS must be set for assembler code used with a VIA ACE build
|
||||
*/
|
||||
|
||||
#if 0 && defined(VIA_ACE_POSSIBLE) && !defined(USE_VIA_ACE_IF_PRESENT)
|
||||
#define USE_VIA_ACE_IF_PRESENT
|
||||
#endif
|
||||
|
||||
#if 0 && defined(VIA_ACE_POSSIBLE) && !defined(ASSUME_VIA_ACE_PRESENT)
|
||||
#define ASSUME_VIA_ACE_PRESENT
|
||||
#endif
|
||||
|
||||
/* 3. ASSEMBLER SUPPORT
|
||||
|
||||
This define (which can be on the command line) enables the use of the
|
||||
assembler code routines for encryption, decryption and key scheduling
|
||||
as follows:
|
||||
|
||||
ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for
|
||||
encryption and decryption and but with key scheduling in C
|
||||
ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for
|
||||
encryption, decryption and key scheduling
|
||||
ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for
|
||||
encryption and decryption and but with key scheduling in C
|
||||
ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for
|
||||
encryption and decryption and but with key scheduling in C
|
||||
|
||||
Change one 'if 0' below to 'if 1' to select the version or define
|
||||
as a compilation option.
|
||||
*/
|
||||
|
||||
#if 0 && !defined(ASM_X86_V1C)
|
||||
#define ASM_X86_V1C
|
||||
#elif 0 && !defined(ASM_X86_V2)
|
||||
#define ASM_X86_V2
|
||||
#elif 0 && !defined(ASM_X86_V2C)
|
||||
#define ASM_X86_V2C
|
||||
#elif 0 && !defined(ASM_AMD64_C)
|
||||
#define ASM_AMD64_C
|
||||
#endif
|
||||
|
||||
#if defined(__i386) || defined(_M_IX86)
|
||||
#define A32_
|
||||
#elif defined(__x86_64__) || defined(_M_X64)
|
||||
#define A64_
|
||||
#endif
|
||||
|
||||
#if(defined(ASM_X86_V1C) || defined(ASM_X86_V2) || defined(ASM_X86_V2C)) && !defined(A32_) || \
|
||||
defined(ASM_AMD64_C) && !defined(A64_)
|
||||
#error Assembler code is only available for x86 and AMD64 systems
|
||||
#endif
|
||||
|
||||
/* 4. FAST INPUT/OUTPUT OPERATIONS.
|
||||
|
||||
On some machines it is possible to improve speed by transferring the
|
||||
bytes in the input and output arrays to and from the internal 32-bit
|
||||
variables by addressing these arrays as if they are arrays of 32-bit
|
||||
words. On some machines this will always be possible but there may
|
||||
be a large performance penalty if the byte arrays are not aligned on
|
||||
the normal word boundaries. On other machines this technique will
|
||||
lead to memory access errors when such 32-bit word accesses are not
|
||||
properly aligned. The option SAFE_IO avoids such problems but will
|
||||
often be slower on those machines that support misaligned access
|
||||
(especially so if care is taken to align the input and output byte
|
||||
arrays on 32-bit word boundaries). If SAFE_IO is not defined it is
|
||||
assumed that access to byte arrays as if they are arrays of 32-bit
|
||||
words will not cause problems when such accesses are misaligned.
|
||||
*/
|
||||
#if 1 && !defined(_MSC_VER)
|
||||
#define SAFE_IO
|
||||
#endif
|
||||
|
||||
/* 5. LOOP UNROLLING
|
||||
|
||||
The code for encryption and decrytpion cycles through a number of rounds
|
||||
that can be implemented either in a loop or by expanding the code into a
|
||||
long sequence of instructions, the latter producing a larger program but
|
||||
one that will often be much faster. The latter is called loop unrolling.
|
||||
There are also potential speed advantages in expanding two iterations in
|
||||
a loop with half the number of iterations, which is called partial loop
|
||||
unrolling. The following options allow partial or full loop unrolling
|
||||
to be set independently for encryption and decryption
|
||||
*/
|
||||
#if 1
|
||||
#define ENC_UNROLL FULL
|
||||
#elif 0
|
||||
#define ENC_UNROLL PARTIAL
|
||||
#else
|
||||
#define ENC_UNROLL NONE
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define DEC_UNROLL FULL
|
||||
#elif 0
|
||||
#define DEC_UNROLL PARTIAL
|
||||
#else
|
||||
#define DEC_UNROLL NONE
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define ENC_KS_UNROLL
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define DEC_KS_UNROLL
|
||||
#endif
|
||||
|
||||
/* 6. FAST FINITE FIELD OPERATIONS
|
||||
|
||||
If this section is included, tables are used to provide faster finite
|
||||
field arithmetic (this has no effect if STATIC_TABLES is defined).
|
||||
*/
|
||||
#if 1
|
||||
#define FF_TABLES
|
||||
#endif
|
||||
|
||||
/* 7. INTERNAL STATE VARIABLE FORMAT
|
||||
|
||||
The internal state of Rijndael is stored in a number of local 32-bit
|
||||
word varaibles which can be defined either as an array or as individual
|
||||
names variables. Include this section if you want to store these local
|
||||
varaibles in arrays. Otherwise individual local variables will be used.
|
||||
*/
|
||||
#if 1
|
||||
#define ARRAYS
|
||||
#endif
|
||||
|
||||
/* 8. FIXED OR DYNAMIC TABLES
|
||||
|
||||
When this section is included the tables used by the code are compiled
|
||||
statically into the binary file. Otherwise the subroutine aes_init()
|
||||
must be called to compute them before the code is first used.
|
||||
*/
|
||||
#if 1 && !(defined(_MSC_VER) && (_MSC_VER <= 800))
|
||||
#define STATIC_TABLES
|
||||
#endif
|
||||
|
||||
/* 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES
|
||||
|
||||
In some systems it is better to mask longer values to extract bytes
|
||||
rather than using a cast. This option allows this choice.
|
||||
*/
|
||||
#if 0
|
||||
#define to_byte(x) ((uint8_t)(x))
|
||||
#else
|
||||
#define to_byte(x) ((x)&0xff)
|
||||
#endif
|
||||
|
||||
/* 10. TABLE ALIGNMENT
|
||||
|
||||
On some sytsems speed will be improved by aligning the AES large lookup
|
||||
tables on particular boundaries. This define should be set to a power of
|
||||
two giving the desired alignment. It can be left undefined if alignment
|
||||
is not needed. This option is specific to the Microsft VC++ compiler -
|
||||
it seems to sometimes cause trouble for the VC++ version 6 compiler.
|
||||
*/
|
||||
|
||||
#if 1 && defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
#define TABLE_ALIGN 32
|
||||
#endif
|
||||
|
||||
/* 11. REDUCE CODE AND TABLE SIZE
|
||||
|
||||
This replaces some expanded macros with function calls if AES_ASM_V2 or
|
||||
AES_ASM_V2C are defined
|
||||
*/
|
||||
|
||||
#if 1 && (defined(ASM_X86_V2) || defined(ASM_X86_V2C))
|
||||
#define REDUCE_CODE_SIZE
|
||||
#endif
|
||||
|
||||
/* 12. TABLE OPTIONS
|
||||
|
||||
This cipher proceeds by repeating in a number of cycles known as 'rounds'
|
||||
which are implemented by a round function which can optionally be speeded
|
||||
up using tables. The basic tables are each 256 32-bit words, with either
|
||||
one or four tables being required for each round function depending on
|
||||
how much speed is required. The encryption and decryption round functions
|
||||
are different and the last encryption and decrytpion round functions are
|
||||
different again making four different round functions in all.
|
||||
|
||||
This means that:
|
||||
1. Normal encryption and decryption rounds can each use either 0, 1
|
||||
or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
|
||||
2. The last encryption and decryption rounds can also use either 0, 1
|
||||
or 4 tables and table spaces of 0, 1024 or 4096 bytes each.
|
||||
|
||||
Include or exclude the appropriate definitions below to set the number
|
||||
of tables used by this implementation.
|
||||
*/
|
||||
|
||||
#if 1 /* set tables for the normal encryption round */
|
||||
#define ENC_ROUND FOUR_TABLES
|
||||
#elif 0
|
||||
#define ENC_ROUND ONE_TABLE
|
||||
#else
|
||||
#define ENC_ROUND NO_TABLES
|
||||
#endif
|
||||
|
||||
#if 1 /* set tables for the last encryption round */
|
||||
#define LAST_ENC_ROUND FOUR_TABLES
|
||||
#elif 0
|
||||
#define LAST_ENC_ROUND ONE_TABLE
|
||||
#else
|
||||
#define LAST_ENC_ROUND NO_TABLES
|
||||
#endif
|
||||
|
||||
#if 1 /* set tables for the normal decryption round */
|
||||
#define DEC_ROUND FOUR_TABLES
|
||||
#elif 0
|
||||
#define DEC_ROUND ONE_TABLE
|
||||
#else
|
||||
#define DEC_ROUND NO_TABLES
|
||||
#endif
|
||||
|
||||
#if 1 /* set tables for the last decryption round */
|
||||
#define LAST_DEC_ROUND FOUR_TABLES
|
||||
#elif 0
|
||||
#define LAST_DEC_ROUND ONE_TABLE
|
||||
#else
|
||||
#define LAST_DEC_ROUND NO_TABLES
|
||||
#endif
|
||||
|
||||
/* The decryption key schedule can be speeded up with tables in the same
|
||||
way that the round functions can. Include or exclude the following
|
||||
defines to set this requirement.
|
||||
*/
|
||||
#if 1
|
||||
#define KEY_SCHED FOUR_TABLES
|
||||
#elif 0
|
||||
#define KEY_SCHED ONE_TABLE
|
||||
#else
|
||||
#define KEY_SCHED NO_TABLES
|
||||
#endif
|
||||
|
||||
/* ---- END OF USER CONFIGURED OPTIONS ---- */
|
||||
|
||||
/* VIA ACE support is only available for VC++ and GCC */
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(__GNUC__)
|
||||
#if defined(ASSUME_VIA_ACE_PRESENT)
|
||||
#undef ASSUME_VIA_ACE_PRESENT
|
||||
#endif
|
||||
#if defined(USE_VIA_ACE_IF_PRESENT)
|
||||
#undef USE_VIA_ACE_IF_PRESENT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ASSUME_VIA_ACE_PRESENT) && !defined(USE_VIA_ACE_IF_PRESENT)
|
||||
#define USE_VIA_ACE_IF_PRESENT
|
||||
#endif
|
||||
|
||||
/* define to reverse decryption key schedule */
|
||||
#if 1 || defined(USE_VIA_ACE_IF_PRESENT) && !defined(AES_REV_DKS)
|
||||
#define AES_REV_DKS
|
||||
#endif
|
||||
|
||||
/* Intel AESNI uses a decryption key schedule in the encryption order */
|
||||
#if defined(USE_INTEL_AES_IF_PRESENT) && defined(AES_REV_DKS)
|
||||
#undef AES_REV_DKS
|
||||
#endif
|
||||
|
||||
/* Assembler support requires the use of platform byte order */
|
||||
|
||||
#if(defined(ASM_X86_V1C) || defined(ASM_X86_V2C) || defined(ASM_AMD64_C)) && \
|
||||
(ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER)
|
||||
#undef ALGORITHM_BYTE_ORDER
|
||||
#define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER
|
||||
#endif
|
||||
|
||||
/* In this implementation the columns of the state array are each held in
|
||||
32-bit words. The state array can be held in various ways: in an array
|
||||
of words, in a number of individual word variables or in a number of
|
||||
processor registers. The following define maps a variable name x and
|
||||
a column number c to the way the state array variable is to be held.
|
||||
The first define below maps the state into an array x[c] whereas the
|
||||
second form maps the state into a number of individual variables x0,
|
||||
x1, etc. Another form could map individual state colums to machine
|
||||
register names.
|
||||
*/
|
||||
|
||||
#if defined(ARRAYS)
|
||||
#define s(x, c) x[c]
|
||||
#else
|
||||
#define s(x, c) x##c
|
||||
#endif
|
||||
|
||||
/* This implementation provides subroutines for encryption, decryption
|
||||
and for setting the three key lengths (separately) for encryption
|
||||
and decryption. Since not all functions are needed, masks are set
|
||||
up here to determine which will be implemented in C
|
||||
*/
|
||||
|
||||
#if !defined(AES_ENCRYPT)
|
||||
#define EFUNCS_IN_C 0
|
||||
#elif defined(ASSUME_VIA_ACE_PRESENT) || defined(ASM_X86_V1C) || defined(ASM_X86_V2C) || \
|
||||
defined(ASM_AMD64_C)
|
||||
#define EFUNCS_IN_C ENC_KEYING_IN_C
|
||||
#elif !defined(ASM_X86_V2)
|
||||
#define EFUNCS_IN_C (ENCRYPTION_IN_C | ENC_KEYING_IN_C)
|
||||
#else
|
||||
#define EFUNCS_IN_C 0
|
||||
#endif
|
||||
|
||||
#if !defined(AES_DECRYPT)
|
||||
#define DFUNCS_IN_C 0
|
||||
#elif defined(ASSUME_VIA_ACE_PRESENT) || defined(ASM_X86_V1C) || defined(ASM_X86_V2C) || \
|
||||
defined(ASM_AMD64_C)
|
||||
#define DFUNCS_IN_C DEC_KEYING_IN_C
|
||||
#elif !defined(ASM_X86_V2)
|
||||
#define DFUNCS_IN_C (DECRYPTION_IN_C | DEC_KEYING_IN_C)
|
||||
#else
|
||||
#define DFUNCS_IN_C 0
|
||||
#endif
|
||||
|
||||
#define FUNCS_IN_C (EFUNCS_IN_C | DFUNCS_IN_C)
|
||||
|
||||
/* END OF CONFIGURATION OPTIONS */
|
||||
|
||||
#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
|
||||
|
||||
/* Disable or report errors on some combinations of options */
|
||||
|
||||
#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES
|
||||
#undef LAST_ENC_ROUND
|
||||
#define LAST_ENC_ROUND NO_TABLES
|
||||
#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES
|
||||
#undef LAST_ENC_ROUND
|
||||
#define LAST_ENC_ROUND ONE_TABLE
|
||||
#endif
|
||||
|
||||
#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE
|
||||
#undef ENC_UNROLL
|
||||
#define ENC_UNROLL NONE
|
||||
#endif
|
||||
|
||||
#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES
|
||||
#undef LAST_DEC_ROUND
|
||||
#define LAST_DEC_ROUND NO_TABLES
|
||||
#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES
|
||||
#undef LAST_DEC_ROUND
|
||||
#define LAST_DEC_ROUND ONE_TABLE
|
||||
#endif
|
||||
|
||||
#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE
|
||||
#undef DEC_UNROLL
|
||||
#define DEC_UNROLL NONE
|
||||
#endif
|
||||
|
||||
#if defined(bswap32)
|
||||
#define aes_sw32 bswap32
|
||||
#elif defined(bswap_32)
|
||||
#define aes_sw32 bswap_32
|
||||
#else
|
||||
#define brot(x, n) (((uint32_t)(x) << n) | ((uint32_t)(x) >> (32 - n)))
|
||||
#define aes_sw32(x) ((brot((x), 8) & 0x00ff00ff) | (brot((x), 24) & 0xff00ff00))
|
||||
#endif
|
||||
|
||||
/* upr(x,n): rotates bytes within words by n positions, moving bytes to
|
||||
higher index positions with wrap around into low positions
|
||||
ups(x,n): moves bytes by n positions to higher index positions in
|
||||
words but without wrap around
|
||||
bval(x,n): extracts a byte from a word
|
||||
|
||||
WARNING: The definitions given here are intended only for use with
|
||||
unsigned variables and with shift counts that are compile
|
||||
time constants
|
||||
*/
|
||||
|
||||
#if(ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN)
|
||||
#define upr(x, n) (((uint32_t)(x) << (8 * (n))) | ((uint32_t)(x) >> (32 - 8 * (n))))
|
||||
#define ups(x, n) ((uint32_t)(x) << (8 * (n)))
|
||||
#define bval(x, n) to_byte((x) >> (8 * (n)))
|
||||
#define bytes2word(b0, b1, b2, b3) \
|
||||
(((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
|
||||
#endif
|
||||
|
||||
#if(ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN)
|
||||
#define upr(x, n) (((uint32_t)(x) >> (8 * (n))) | ((uint32_t)(x) << (32 - 8 * (n))))
|
||||
#define ups(x, n) ((uint32_t)(x) >> (8 * (n)))
|
||||
#define bval(x, n) to_byte((x) >> (24 - 8 * (n)))
|
||||
#define bytes2word(b0, b1, b2, b3) \
|
||||
(((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3))
|
||||
#endif
|
||||
|
||||
#if defined(SAFE_IO)
|
||||
#define word_in(x, c) \
|
||||
bytes2word( \
|
||||
((const uint8_t*)(x) + 4 * c)[0], \
|
||||
((const uint8_t*)(x) + 4 * c)[1], \
|
||||
((const uint8_t*)(x) + 4 * c)[2], \
|
||||
((const uint8_t*)(x) + 4 * c)[3])
|
||||
#define word_out(x, c, v) \
|
||||
{ \
|
||||
((uint8_t*)(x) + 4 * c)[0] = bval(v, 0); \
|
||||
((uint8_t*)(x) + 4 * c)[1] = bval(v, 1); \
|
||||
((uint8_t*)(x) + 4 * c)[2] = bval(v, 2); \
|
||||
((uint8_t*)(x) + 4 * c)[3] = bval(v, 3); \
|
||||
}
|
||||
#elif(ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER)
|
||||
#define word_in(x, c) (*((uint32_t*)(x) + (c)))
|
||||
#define word_out(x, c, v) (*((uint32_t*)(x) + (c)) = (v))
|
||||
#else
|
||||
#define word_in(x, c) aes_sw32(*((uint32_t*)(x) + (c)))
|
||||
#define word_out(x, c, v) (*((uint32_t*)(x) + (c)) = aes_sw32(v))
|
||||
#endif
|
||||
|
||||
/* the finite field modular polynomial and elements */
|
||||
|
||||
#define WPOLY 0x011b
|
||||
#define BPOLY 0x1b
|
||||
|
||||
/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
|
||||
|
||||
#define gf_c1 0x80808080
|
||||
#define gf_c2 0x7f7f7f7f
|
||||
#define gf_mulx(x) ((((x)&gf_c2) << 1) ^ ((((x)&gf_c1) >> 7) * BPOLY))
|
||||
|
||||
/* The following defines provide alternative definitions of gf_mulx that might
|
||||
give improved performance if a fast 32-bit multiply is not available. Note
|
||||
that a temporary variable u needs to be defined where gf_mulx is used.
|
||||
|
||||
#define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6))
|
||||
#define gf_c4 (0x01010101 * BPOLY)
|
||||
#define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4)
|
||||
*/
|
||||
|
||||
/* Work out which tables are needed for the different options */
|
||||
|
||||
#if defined(ASM_X86_V1C)
|
||||
#if defined(ENC_ROUND)
|
||||
#undef ENC_ROUND
|
||||
#endif
|
||||
#define ENC_ROUND FOUR_TABLES
|
||||
#if defined(LAST_ENC_ROUND)
|
||||
#undef LAST_ENC_ROUND
|
||||
#endif
|
||||
#define LAST_ENC_ROUND FOUR_TABLES
|
||||
#if defined(DEC_ROUND)
|
||||
#undef DEC_ROUND
|
||||
#endif
|
||||
#define DEC_ROUND FOUR_TABLES
|
||||
#if defined(LAST_DEC_ROUND)
|
||||
#undef LAST_DEC_ROUND
|
||||
#endif
|
||||
#define LAST_DEC_ROUND FOUR_TABLES
|
||||
#if defined(KEY_SCHED)
|
||||
#undef KEY_SCHED
|
||||
#define KEY_SCHED FOUR_TABLES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if(FUNCS_IN_C & ENCRYPTION_IN_C) || defined(ASM_X86_V1C)
|
||||
#if ENC_ROUND == ONE_TABLE
|
||||
#define FT1_SET
|
||||
#elif ENC_ROUND == FOUR_TABLES
|
||||
#define FT4_SET
|
||||
#else
|
||||
#define SBX_SET
|
||||
#endif
|
||||
#if LAST_ENC_ROUND == ONE_TABLE
|
||||
#define FL1_SET
|
||||
#elif LAST_ENC_ROUND == FOUR_TABLES
|
||||
#define FL4_SET
|
||||
#elif !defined(SBX_SET)
|
||||
#define SBX_SET
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if(FUNCS_IN_C & DECRYPTION_IN_C) || defined(ASM_X86_V1C)
|
||||
#if DEC_ROUND == ONE_TABLE
|
||||
#define IT1_SET
|
||||
#elif DEC_ROUND == FOUR_TABLES
|
||||
#define IT4_SET
|
||||
#else
|
||||
#define ISB_SET
|
||||
#endif
|
||||
#if LAST_DEC_ROUND == ONE_TABLE
|
||||
#define IL1_SET
|
||||
#elif LAST_DEC_ROUND == FOUR_TABLES
|
||||
#define IL4_SET
|
||||
#elif !defined(ISB_SET)
|
||||
#define ISB_SET
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !(defined(REDUCE_CODE_SIZE) && (defined(ASM_X86_V2) || defined(ASM_X86_V2C)))
|
||||
#if((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C))
|
||||
#if KEY_SCHED == ONE_TABLE
|
||||
#if !defined(FL1_SET) && !defined(FL4_SET)
|
||||
#define LS1_SET
|
||||
#endif
|
||||
#elif KEY_SCHED == FOUR_TABLES
|
||||
#if !defined(FL4_SET)
|
||||
#define LS4_SET
|
||||
#endif
|
||||
#elif !defined(SBX_SET)
|
||||
#define SBX_SET
|
||||
#endif
|
||||
#endif
|
||||
#if(FUNCS_IN_C & DEC_KEYING_IN_C)
|
||||
#if KEY_SCHED == ONE_TABLE
|
||||
#define IM1_SET
|
||||
#elif KEY_SCHED == FOUR_TABLES
|
||||
#define IM4_SET
|
||||
#elif !defined(SBX_SET)
|
||||
#define SBX_SET
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* generic definitions of Rijndael macros that use tables */
|
||||
|
||||
#define no_table(x, box, vf, rf, c) \
|
||||
bytes2word( \
|
||||
box[bval(vf(x, 0, c), rf(0, c))], \
|
||||
box[bval(vf(x, 1, c), rf(1, c))], \
|
||||
box[bval(vf(x, 2, c), rf(2, c))], \
|
||||
box[bval(vf(x, 3, c), rf(3, c))])
|
||||
|
||||
#define one_table(x, op, tab, vf, rf, c) \
|
||||
(tab[bval(vf(x, 0, c), rf(0, c))] ^ op(tab[bval(vf(x, 1, c), rf(1, c))], 1) ^ \
|
||||
op(tab[bval(vf(x, 2, c), rf(2, c))], 2) ^ op(tab[bval(vf(x, 3, c), rf(3, c))], 3))
|
||||
|
||||
#define four_tables(x, tab, vf, rf, c) \
|
||||
(tab[0][bval(vf(x, 0, c), rf(0, c))] ^ tab[1][bval(vf(x, 1, c), rf(1, c))] ^ \
|
||||
tab[2][bval(vf(x, 2, c), rf(2, c))] ^ tab[3][bval(vf(x, 3, c), rf(3, c))])
|
||||
|
||||
#define vf1(x, r, c) (x)
|
||||
#define rf1(r, c) (r)
|
||||
#define rf2(r, c) ((8 + r - c) & 3)
|
||||
|
||||
/* perform forward and inverse column mix operation on four bytes in long word x in */
|
||||
/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */
|
||||
|
||||
#if !(defined(REDUCE_CODE_SIZE) && (defined(ASM_X86_V2) || defined(ASM_X86_V2C)))
|
||||
|
||||
#if defined(FM4_SET) /* not currently used */
|
||||
#define fwd_mcol(x) four_tables(x, t_use(f, m), vf1, rf1, 0)
|
||||
#elif defined(FM1_SET) /* not currently used */
|
||||
#define fwd_mcol(x) one_table(x, upr, t_use(f, m), vf1, rf1, 0)
|
||||
#else
|
||||
#define dec_fmvars uint32_t g2
|
||||
#define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1))
|
||||
#endif
|
||||
|
||||
#if defined(IM4_SET)
|
||||
#define inv_mcol(x) four_tables(x, t_use(i, m), vf1, rf1, 0)
|
||||
#elif defined(IM1_SET)
|
||||
#define inv_mcol(x) one_table(x, upr, t_use(i, m), vf1, rf1, 0)
|
||||
#else
|
||||
#define dec_imvars uint32_t g2, g4, g9
|
||||
#define inv_mcol(x) \
|
||||
(g2 = gf_mulx(x), \
|
||||
g4 = gf_mulx(g2), \
|
||||
g9 = (x) ^ gf_mulx(g4), \
|
||||
g4 ^= g9, \
|
||||
(x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1))
|
||||
#endif
|
||||
|
||||
#if defined(FL4_SET)
|
||||
#define ls_box(x, c) four_tables(x, t_use(f, l), vf1, rf2, c)
|
||||
#elif defined(LS4_SET)
|
||||
#define ls_box(x, c) four_tables(x, t_use(l, s), vf1, rf2, c)
|
||||
#elif defined(FL1_SET)
|
||||
#define ls_box(x, c) one_table(x, upr, t_use(f, l), vf1, rf2, c)
|
||||
#elif defined(LS1_SET)
|
||||
#define ls_box(x, c) one_table(x, upr, t_use(l, s), vf1, rf2, c)
|
||||
#else
|
||||
#define ls_box(x, c) no_table(x, t_use(s, box), vf1, rf2, c)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ASM_X86_V1C) && defined(AES_DECRYPT) && !defined(ISB_SET)
|
||||
#define ISB_SET
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,403 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
*/
|
||||
|
||||
#define DO_TABLES
|
||||
|
||||
#include "aes.h"
|
||||
#include "aesopt.h"
|
||||
|
||||
#if defined(STATIC_TABLES)
|
||||
|
||||
#define sb_data(w) \
|
||||
{ \
|
||||
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5), w(0x30), w(0x01), \
|
||||
w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76), w(0xca), w(0x82), w(0xc9), \
|
||||
w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0), w(0xad), w(0xd4), w(0xa2), w(0xaf), \
|
||||
w(0x9c), w(0xa4), w(0x72), w(0xc0), w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), \
|
||||
w(0x3f), w(0xf7), w(0xcc), w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), \
|
||||
w(0x31), w(0x15), w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), \
|
||||
w(0x9a), w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75), \
|
||||
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0), w(0x52), \
|
||||
w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84), w(0x53), w(0xd1), \
|
||||
w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b), w(0x6a), w(0xcb), w(0xbe), \
|
||||
w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), w(0xd0), w(0xef), w(0xaa), w(0xfb), \
|
||||
w(0x43), w(0x4d), w(0x33), w(0x85), w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), \
|
||||
w(0x3c), w(0x9f), w(0xa8), w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), \
|
||||
w(0x38), w(0xf5), w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), \
|
||||
w(0xd2), w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17), \
|
||||
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73), w(0x60), \
|
||||
w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), w(0x46), w(0xee), \
|
||||
w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), w(0xe0), w(0x32), w(0x3a), \
|
||||
w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), w(0xc2), w(0xd3), w(0xac), w(0x62), \
|
||||
w(0x91), w(0x95), w(0xe4), w(0x79), w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), \
|
||||
w(0xd5), w(0x4e), w(0xa9), w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), \
|
||||
w(0xae), w(0x08), w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), \
|
||||
w(0xc6), w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), \
|
||||
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), w(0x61), \
|
||||
w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), w(0xe1), w(0xf8), \
|
||||
w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94), w(0x9b), w(0x1e), w(0x87), \
|
||||
w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf), w(0x8c), w(0xa1), w(0x89), w(0x0d), \
|
||||
w(0xbf), w(0xe6), w(0x42), w(0x68), w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), \
|
||||
w(0x54), w(0xbb), w(0x16) \
|
||||
}
|
||||
|
||||
#define isb_data(w) \
|
||||
{ \
|
||||
w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38), w(0xbf), w(0x40), \
|
||||
w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb), w(0x7c), w(0xe3), w(0x39), \
|
||||
w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87), w(0x34), w(0x8e), w(0x43), w(0x44), \
|
||||
w(0xc4), w(0xde), w(0xe9), w(0xcb), w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), \
|
||||
w(0xc2), w(0x23), w(0x3d), w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), \
|
||||
w(0xc3), w(0x4e), w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), \
|
||||
w(0xb2), w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25), \
|
||||
w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16), w(0xd4), \
|
||||
w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92), w(0x6c), w(0x70), \
|
||||
w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda), w(0x5e), w(0x15), w(0x46), \
|
||||
w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84), w(0x90), w(0xd8), w(0xab), w(0x00), \
|
||||
w(0x8c), w(0xbc), w(0xd3), w(0x0a), w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), \
|
||||
w(0xb3), w(0x45), w(0x06), w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), \
|
||||
w(0x0f), w(0x02), w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), \
|
||||
w(0x6b), w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea), \
|
||||
w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73), w(0x96), \
|
||||
w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85), w(0xe2), w(0xf9), \
|
||||
w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e), w(0x47), w(0xf1), w(0x1a), \
|
||||
w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89), w(0x6f), w(0xb7), w(0x62), w(0x0e), \
|
||||
w(0xaa), w(0x18), w(0xbe), w(0x1b), w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), \
|
||||
w(0xd2), w(0x79), w(0x20), w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), \
|
||||
w(0x5a), w(0xf4), w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), \
|
||||
w(0x31), w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f), \
|
||||
w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d), w(0x2d), \
|
||||
w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef), w(0xa0), w(0xe0), \
|
||||
w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0), w(0xc8), w(0xeb), w(0xbb), \
|
||||
w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61), w(0x17), w(0x2b), w(0x04), w(0x7e), \
|
||||
w(0xba), w(0x77), w(0xd6), w(0x26), w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), \
|
||||
w(0x21), w(0x0c), w(0x7d) \
|
||||
}
|
||||
|
||||
#define mm_data(w) \
|
||||
{ \
|
||||
w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07), w(0x08), w(0x09), \
|
||||
w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f), w(0x10), w(0x11), w(0x12), \
|
||||
w(0x13), w(0x14), w(0x15), w(0x16), w(0x17), w(0x18), w(0x19), w(0x1a), w(0x1b), \
|
||||
w(0x1c), w(0x1d), w(0x1e), w(0x1f), w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), \
|
||||
w(0x25), w(0x26), w(0x27), w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), \
|
||||
w(0x2e), w(0x2f), w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), \
|
||||
w(0x37), w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f), \
|
||||
w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47), w(0x48), \
|
||||
w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f), w(0x50), w(0x51), \
|
||||
w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57), w(0x58), w(0x59), w(0x5a), \
|
||||
w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f), w(0x60), w(0x61), w(0x62), w(0x63), \
|
||||
w(0x64), w(0x65), w(0x66), w(0x67), w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), \
|
||||
w(0x6d), w(0x6e), w(0x6f), w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), \
|
||||
w(0x76), w(0x77), w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), \
|
||||
w(0x7f), w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87), \
|
||||
w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f), w(0x90), \
|
||||
w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97), w(0x98), w(0x99), \
|
||||
w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f), w(0xa0), w(0xa1), w(0xa2), \
|
||||
w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7), w(0xa8), w(0xa9), w(0xaa), w(0xab), \
|
||||
w(0xac), w(0xad), w(0xae), w(0xaf), w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), \
|
||||
w(0xb5), w(0xb6), w(0xb7), w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), \
|
||||
w(0xbe), w(0xbf), w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), \
|
||||
w(0xc7), w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf), \
|
||||
w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7), w(0xd8), \
|
||||
w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf), w(0xe0), w(0xe1), \
|
||||
w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7), w(0xe8), w(0xe9), w(0xea), \
|
||||
w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef), w(0xf0), w(0xf1), w(0xf2), w(0xf3), \
|
||||
w(0xf4), w(0xf5), w(0xf6), w(0xf7), w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), \
|
||||
w(0xfd), w(0xfe), w(0xff) \
|
||||
}
|
||||
|
||||
#define rc_data(w) \
|
||||
{ w(0x01), w(0x02), w(0x04), w(0x08), w(0x10), w(0x20), w(0x40), w(0x80), w(0x1b), w(0x36) }
|
||||
|
||||
#define h0(x) (x)
|
||||
|
||||
#define w0(p) bytes2word(p, 0, 0, 0)
|
||||
#define w1(p) bytes2word(0, p, 0, 0)
|
||||
#define w2(p) bytes2word(0, 0, p, 0)
|
||||
#define w3(p) bytes2word(0, 0, 0, p)
|
||||
|
||||
#define u0(p) bytes2word(f2(p), p, p, f3(p))
|
||||
#define u1(p) bytes2word(f3(p), f2(p), p, p)
|
||||
#define u2(p) bytes2word(p, f3(p), f2(p), p)
|
||||
#define u3(p) bytes2word(p, p, f3(p), f2(p))
|
||||
|
||||
#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
|
||||
#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
|
||||
#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
|
||||
#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(STATIC_TABLES) || !defined(FF_TABLES)
|
||||
|
||||
#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
|
||||
#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
|
||||
#define f8(x) \
|
||||
((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) ^ (((x >> 5) & 4) * WPOLY))
|
||||
#define f3(x) (f2(x) ^ x)
|
||||
#define f9(x) (f8(x) ^ x)
|
||||
#define fb(x) (f8(x) ^ f2(x) ^ x)
|
||||
#define fd(x) (f8(x) ^ f4(x) ^ x)
|
||||
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
|
||||
|
||||
#else
|
||||
|
||||
#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
|
||||
#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
|
||||
#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
|
||||
#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
|
||||
#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
|
||||
#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
|
||||
|
||||
#endif
|
||||
|
||||
#include "aestab.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(STATIC_TABLES)
|
||||
|
||||
/* implemented in case of wrong call for fixed tables */
|
||||
|
||||
AES_RETURN aes_init(void) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#else /* Generate the tables for the dynamic table option */
|
||||
|
||||
#if defined(FF_TABLES)
|
||||
|
||||
#define gf_inv(x) ((x) ? pow[255 - log[x]] : 0)
|
||||
|
||||
#else
|
||||
|
||||
/* It will generally be sensible to use tables to compute finite
|
||||
field multiplies and inverses but where memory is scarse this
|
||||
code might sometimes be better. But it only has effect during
|
||||
initialisation so its pretty unimportant in overall terms.
|
||||
*/
|
||||
|
||||
/* return 2 ^ (n - 1) where n is the bit number of the highest bit
|
||||
set in x with x in the range 1 < x < 0x00000200. This form is
|
||||
used so that locals within fi can be bytes rather than words
|
||||
*/
|
||||
|
||||
static uint8_t hibit(const uint32_t x) {
|
||||
uint8_t r = (uint8_t)((x >> 1) | (x >> 2));
|
||||
|
||||
r |= (r >> 2);
|
||||
r |= (r >> 4);
|
||||
return (r + 1) >> 1;
|
||||
}
|
||||
|
||||
/* return the inverse of the finite field element x */
|
||||
|
||||
static uint8_t gf_inv(const uint8_t x) {
|
||||
uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
|
||||
|
||||
if(x < 2) return x;
|
||||
|
||||
for(;;) {
|
||||
if(n1)
|
||||
while(n2 >= n1) /* divide polynomial p2 by p1 */
|
||||
{
|
||||
n2 /= n1; /* shift smaller polynomial left */
|
||||
p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */
|
||||
v2 ^= v1 * n2; /* shift accumulated value and */
|
||||
n2 = hibit(p2); /* add into result */
|
||||
}
|
||||
else
|
||||
return v1;
|
||||
|
||||
if(n2) /* repeat with values swapped */
|
||||
while(n1 >= n2) {
|
||||
n1 /= n2;
|
||||
p1 ^= p2 * n1;
|
||||
v1 ^= v2 * n1;
|
||||
n1 = hibit(p1);
|
||||
}
|
||||
else
|
||||
return v2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* The forward and inverse affine transformations used in the S-box */
|
||||
uint8_t fwd_affine(const uint8_t x) {
|
||||
uint32_t w = x;
|
||||
w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
|
||||
return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
|
||||
}
|
||||
|
||||
uint8_t inv_affine(const uint8_t x) {
|
||||
uint32_t w = x;
|
||||
w = (w << 1) ^ (w << 3) ^ (w << 6);
|
||||
return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
|
||||
}
|
||||
|
||||
static int init = 0;
|
||||
|
||||
AES_RETURN aes_init(void) {
|
||||
uint32_t i, w;
|
||||
|
||||
#if defined(FF_TABLES)
|
||||
|
||||
uint8_t pow[512] = {0}, log[256] = {0};
|
||||
|
||||
if(init) return EXIT_SUCCESS;
|
||||
/* log and power tables for GF(2^8) finite field with
|
||||
WPOLY as modular polynomial - the simplest primitive
|
||||
root is 0x03, used here to generate the tables
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
w = 1;
|
||||
do {
|
||||
pow[i] = (uint8_t)w;
|
||||
pow[i + 255] = (uint8_t)w;
|
||||
log[w] = (uint8_t)i++;
|
||||
w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
|
||||
} while(w != 1);
|
||||
|
||||
#else
|
||||
if(init) return EXIT_SUCCESS;
|
||||
#endif
|
||||
|
||||
for(i = 0, w = 1; i < RC_LENGTH; ++i) {
|
||||
t_set(r, c)[i] = bytes2word(w, 0, 0, 0);
|
||||
w = f2(w);
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; ++i) {
|
||||
uint8_t b;
|
||||
|
||||
b = fwd_affine(gf_inv((uint8_t)i));
|
||||
w = bytes2word(f2(b), b, b, f3(b));
|
||||
|
||||
#if defined(SBX_SET)
|
||||
t_set(s, box)[i] = b;
|
||||
#endif
|
||||
|
||||
#if defined(FT1_SET) /* tables for a normal encryption round */
|
||||
t_set(f, n)[i] = w;
|
||||
#endif
|
||||
#if defined(FT4_SET)
|
||||
t_set(f, n)[0][i] = w;
|
||||
t_set(f, n)[1][i] = upr(w, 1);
|
||||
t_set(f, n)[2][i] = upr(w, 2);
|
||||
t_set(f, n)[3][i] = upr(w, 3);
|
||||
#endif
|
||||
w = bytes2word(b, 0, 0, 0);
|
||||
|
||||
#if defined(FL1_SET) /* tables for last encryption round (may also */
|
||||
t_set(f, l)[i] = w; /* be used in the key schedule) */
|
||||
#endif
|
||||
#if defined(FL4_SET)
|
||||
t_set(f, l)[0][i] = w;
|
||||
t_set(f, l)[1][i] = upr(w, 1);
|
||||
t_set(f, l)[2][i] = upr(w, 2);
|
||||
t_set(f, l)[3][i] = upr(w, 3);
|
||||
#endif
|
||||
|
||||
#if defined(LS1_SET) /* table for key schedule if t_set(f,l) above is*/
|
||||
t_set(l, s)[i] = w; /* not of the required form */
|
||||
#endif
|
||||
#if defined(LS4_SET)
|
||||
t_set(l, s)[0][i] = w;
|
||||
t_set(l, s)[1][i] = upr(w, 1);
|
||||
t_set(l, s)[2][i] = upr(w, 2);
|
||||
t_set(l, s)[3][i] = upr(w, 3);
|
||||
#endif
|
||||
|
||||
b = gf_inv(inv_affine((uint8_t)i));
|
||||
w = bytes2word(fe(b), f9(b), fd(b), fb(b));
|
||||
|
||||
#if defined(IM1_SET) /* tables for the inverse mix column operation */
|
||||
t_set(i, m)[b] = w;
|
||||
#endif
|
||||
#if defined(IM4_SET)
|
||||
t_set(i, m)[0][b] = w;
|
||||
t_set(i, m)[1][b] = upr(w, 1);
|
||||
t_set(i, m)[2][b] = upr(w, 2);
|
||||
t_set(i, m)[3][b] = upr(w, 3);
|
||||
#endif
|
||||
|
||||
#if defined(ISB_SET)
|
||||
t_set(i, box)[i] = b;
|
||||
#endif
|
||||
#if defined(IT1_SET) /* tables for a normal decryption round */
|
||||
t_set(i, n)[i] = w;
|
||||
#endif
|
||||
#if defined(IT4_SET)
|
||||
t_set(i, n)[0][i] = w;
|
||||
t_set(i, n)[1][i] = upr(w, 1);
|
||||
t_set(i, n)[2][i] = upr(w, 2);
|
||||
t_set(i, n)[3][i] = upr(w, 3);
|
||||
#endif
|
||||
w = bytes2word(b, 0, 0, 0);
|
||||
#if defined(IL1_SET) /* tables for last decryption round */
|
||||
t_set(i, l)[i] = w;
|
||||
#endif
|
||||
#if defined(IL4_SET)
|
||||
t_set(i, l)[0][i] = w;
|
||||
t_set(i, l)[1][i] = upr(w, 1);
|
||||
t_set(i, l)[2][i] = upr(w, 2);
|
||||
t_set(i, l)[3][i] = upr(w, 3);
|
||||
#endif
|
||||
}
|
||||
init = 1;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
Automatic code initialisation (suggested by by Henrik S. Gaßmann)
|
||||
based on code provided by Joe Lowe and placed in the public domain at:
|
||||
http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma section(".CRT$XCU", read)
|
||||
|
||||
__declspec(allocate(".CRT$XCU")) void(__cdecl* aes_startup)(void) = aes_init;
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
static void aes_startup(void) __attribute__((constructor));
|
||||
|
||||
static void aes_startup(void) {
|
||||
aes_init();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#pragma message("dynamic tables must be initialised manually on your system")
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
|
||||
This file contains the code for declaring the tables needed to implement
|
||||
AES. The file aesopt.h is assumed to be included before this header file.
|
||||
If there are no global variables, the definitions here can be used to put
|
||||
the AES tables in a structure so that a pointer can then be added to the
|
||||
AES context to pass them to the AES routines that need them. If this
|
||||
facility is used, the calling program has to ensure that this pointer is
|
||||
managed appropriately. In particular, the value of the t_dec(in,it) item
|
||||
in the table structure must be set to zero in order to ensure that the
|
||||
tables are initialised. In practice the three code sequences in aeskey.c
|
||||
that control the calls to aes_init() and the aes_init() routine itself will
|
||||
have to be changed for a specific implementation. If global variables are
|
||||
available it will generally be preferable to use them with the precomputed
|
||||
STATIC_TABLES option that uses static global tables.
|
||||
|
||||
The following defines can be used to control the way the tables
|
||||
are defined, initialised and used in embedded environments that
|
||||
require special features for these purposes
|
||||
|
||||
the 't_dec' construction is used to declare fixed table arrays
|
||||
the 't_set' construction is used to set fixed table values
|
||||
the 't_use' construction is used to access fixed table values
|
||||
|
||||
256 byte tables:
|
||||
|
||||
t_xxx(s,box) => forward S box
|
||||
t_xxx(i,box) => inverse S box
|
||||
|
||||
256 32-bit word OR 4 x 256 32-bit word tables:
|
||||
|
||||
t_xxx(f,n) => forward normal round
|
||||
t_xxx(f,l) => forward last round
|
||||
t_xxx(i,n) => inverse normal round
|
||||
t_xxx(i,l) => inverse last round
|
||||
t_xxx(l,s) => key schedule table
|
||||
t_xxx(i,m) => key schedule table
|
||||
|
||||
Other variables and tables:
|
||||
|
||||
t_xxx(r,c) => the rcon table
|
||||
*/
|
||||
|
||||
#if !defined(_AESTAB_H)
|
||||
#define _AESTAB_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define t_dec(m, n) t_##m##n
|
||||
#define t_set(m, n) t_##m##n
|
||||
#define t_use(m, n) t_##m##n
|
||||
|
||||
#if defined(STATIC_TABLES)
|
||||
#if !defined(__GNUC__) && (defined(__MSDOS__) || defined(__WIN16__))
|
||||
/* make tables far data to avoid using too much DGROUP space (PG) */
|
||||
#define CONST const far
|
||||
#else
|
||||
#define CONST const
|
||||
#endif
|
||||
#else
|
||||
#define CONST
|
||||
#endif
|
||||
|
||||
#if defined(DO_TABLES)
|
||||
#define EXTERN
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(TABLE_ALIGN)
|
||||
#define ALIGN __declspec(align(TABLE_ALIGN))
|
||||
#else
|
||||
#define ALIGN
|
||||
#endif
|
||||
|
||||
#if defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
|
||||
#define XP_DIR __cdecl
|
||||
#else
|
||||
#define XP_DIR
|
||||
#endif
|
||||
|
||||
#if defined(DO_TABLES) && defined(STATIC_TABLES)
|
||||
#define d_1(t, n, b, e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e)
|
||||
#define d_4(t, n, b, e, f, g, h) EXTERN ALIGN CONST XP_DIR t n[4][256] = {b(e), b(f), b(g), b(h)}
|
||||
EXTERN ALIGN CONST uint32_t t_dec(r, c)[RC_LENGTH] = rc_data(w0);
|
||||
#else
|
||||
#define d_1(t, n, b, e) EXTERN ALIGN CONST XP_DIR t n[256]
|
||||
#define d_4(t, n, b, e, f, g, h) EXTERN ALIGN CONST XP_DIR t n[4][256]
|
||||
EXTERN ALIGN CONST uint32_t t_dec(r, c)[RC_LENGTH];
|
||||
#endif
|
||||
|
||||
#if defined(SBX_SET)
|
||||
d_1(uint8_t, t_dec(s, box), sb_data, h0);
|
||||
#endif
|
||||
#if defined(ISB_SET)
|
||||
d_1(uint8_t, t_dec(i, box), isb_data, h0);
|
||||
#endif
|
||||
|
||||
#if defined(FT1_SET)
|
||||
d_1(uint32_t, t_dec(f, n), sb_data, u0);
|
||||
#endif
|
||||
#if defined(FT4_SET)
|
||||
d_4(uint32_t, t_dec(f, n), sb_data, u0, u1, u2, u3);
|
||||
#endif
|
||||
|
||||
#if defined(FL1_SET)
|
||||
d_1(uint32_t, t_dec(f, l), sb_data, w0);
|
||||
#endif
|
||||
#if defined(FL4_SET)
|
||||
d_4(uint32_t, t_dec(f, l), sb_data, w0, w1, w2, w3);
|
||||
#endif
|
||||
|
||||
#if defined(IT1_SET)
|
||||
d_1(uint32_t, t_dec(i, n), isb_data, v0);
|
||||
#endif
|
||||
#if defined(IT4_SET)
|
||||
d_4(uint32_t, t_dec(i, n), isb_data, v0, v1, v2, v3);
|
||||
#endif
|
||||
|
||||
#if defined(IL1_SET)
|
||||
d_1(uint32_t, t_dec(i, l), isb_data, w0);
|
||||
#endif
|
||||
#if defined(IL4_SET)
|
||||
d_4(uint32_t, t_dec(i, l), isb_data, w0, w1, w2, w3);
|
||||
#endif
|
||||
|
||||
#if defined(LS1_SET)
|
||||
#if defined(FL1_SET)
|
||||
#undef LS1_SET
|
||||
#else
|
||||
d_1(uint32_t, t_dec(l, s), sb_data, w0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LS4_SET)
|
||||
#if defined(FL4_SET)
|
||||
#undef LS4_SET
|
||||
#else
|
||||
d_4(uint32_t, t_dec(l, s), sb_data, w0, w1, w2, w3);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(IM1_SET)
|
||||
d_1(uint32_t, t_dec(i, m), mm_data, v0);
|
||||
#endif
|
||||
#if defined(IM4_SET)
|
||||
d_4(uint32_t, t_dec(i, m), mm_data, v0, v1, v2, v3);
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
1. source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
2. binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation;
|
||||
|
||||
3. the name of the copyright holder is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
*/
|
||||
|
||||
// Correct Output (for variable block size - AES_BLOCK_SIZE undefined):
|
||||
|
||||
// lengths: block = 16 bytes, key = 16 bytes
|
||||
// key = 2b7e151628aed2a6abf7158809cf4f3c
|
||||
// input = 3243f6a8885a308d313198a2e0370734
|
||||
// encrypt = 3925841d02dc09fbdc118597196a0b32
|
||||
// decrypt = 3243f6a8885a308d313198a2e0370734
|
||||
|
||||
// lengths: block = 16 bytes, key = 24 bytes
|
||||
// key = 2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5
|
||||
// input = 3243f6a8885a308d313198a2e0370734
|
||||
// encrypt = f9fb29aefc384a250340d833b87ebc00
|
||||
// decrypt = 3243f6a8885a308d313198a2e0370734
|
||||
|
||||
// lengths: block = 16 bytes, key = 32 bytes
|
||||
// key = 2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe
|
||||
// input = 3243f6a8885a308d313198a2e0370734
|
||||
// encrypt = 1a6e6c2c662e7da6501ffb62bc9e93f3
|
||||
// decrypt = 3243f6a8885a308d313198a2e0370734
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aes.h"
|
||||
#include "aestst.h"
|
||||
|
||||
void out_state(long s0, long s1, long s2, long s3) {
|
||||
printf("\n%08lx%08lx%08lx%08lx", s0, s1, s2, s3);
|
||||
}
|
||||
|
||||
void oblk(char m[], unsigned char v[], unsigned long n) {
|
||||
unsigned long i;
|
||||
|
||||
printf("\n%s", m);
|
||||
|
||||
for(i = 0; i < n; ++i) printf("%02x", v[i]);
|
||||
}
|
||||
|
||||
void message(const char* s) {
|
||||
printf("%s", s);
|
||||
}
|
||||
|
||||
unsigned char pih[32] = // hex digits of pi
|
||||
{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98,
|
||||
0xa2, 0xe0, 0x37, 0x07, 0x34, 0x4a, 0x40, 0x93, 0x82, 0x22, 0x99,
|
||||
0xf3, 0x1d, 0x00, 0x82, 0xef, 0xa9, 0x8e, 0xc4, 0xe6, 0xc8};
|
||||
|
||||
unsigned char exh[32] = // hex digits of e
|
||||
{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15,
|
||||
0x88, 0x09, 0xcf, 0x4f, 0x3c, 0x76, 0x2e, 0x71, 0x60, 0xf3, 0x8b,
|
||||
0x4d, 0xa5, 0x6a, 0x78, 0x4d, 0x90, 0x45, 0x19, 0x0c, 0xfe};
|
||||
|
||||
unsigned char res[3][32] = {
|
||||
{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32},
|
||||
{0xf9, 0xfb, 0x29, 0xae, 0xfc, 0x38, 0x4a, 0x25, 0x03, 0x40, 0xd8, 0x33, 0xb8, 0x7e, 0xbc, 0x00},
|
||||
{0x1a, 0x6e, 0x6c, 0x2c, 0x66, 0x2e, 0x7d, 0xa6, 0x50, 0x1f, 0xfb, 0x62, 0xbc, 0x9e, 0x93, 0xf3}};
|
||||
|
||||
// void cycles(volatile uint64_t *rtn)
|
||||
// {
|
||||
// #if defined( _MSCVER )
|
||||
// __asm // read the Pentium Time Stamp Counter
|
||||
// { cpuid
|
||||
// rdtsc
|
||||
// mov ecx,rtn
|
||||
// mov [ecx],eax
|
||||
// mov [ecx+4],edx
|
||||
// cpuid
|
||||
// }
|
||||
// #elif defined( __GNUC__ )
|
||||
// #if defined(__aarch64__)
|
||||
// __asm__ __volatile__("mrs %0, cntvct_el0": "=r" (*rtn));
|
||||
// #else
|
||||
// __asm__ __volatile__("rdtsc": "=A" (*rtn));
|
||||
// #endif
|
||||
// #endif
|
||||
// }
|
||||
|
||||
int main(void) {
|
||||
unsigned char out[32], ret[32], err = 0;
|
||||
f_ectx alge[1];
|
||||
f_dctx algd[1];
|
||||
|
||||
aes_init();
|
||||
|
||||
message("\nRun tests for the AES algorithm");
|
||||
|
||||
memset(&alge, 0, sizeof(aes_encrypt_ctx));
|
||||
memset(&algd, 0, sizeof(aes_decrypt_ctx));
|
||||
|
||||
#if defined(AES_128)
|
||||
memset(out, 0xcc, 16);
|
||||
memset(ret, 0xcc, 16);
|
||||
printf("\n\n// lengths: block = 16, bytes, key = 16 bytes");
|
||||
f_enc_key128(alge, exh);
|
||||
oblk("// key = ", exh, 16);
|
||||
oblk("// input = ", pih, 16);
|
||||
do_enc(alge, pih, out, 1);
|
||||
oblk("// encrypt = ", out, 16);
|
||||
if(memcmp(out, res[0], 16)) {
|
||||
message(" error");
|
||||
err += 1;
|
||||
}
|
||||
f_dec_key128(algd, exh);
|
||||
do_dec(algd, out, ret, 1);
|
||||
oblk("// decrypt = ", ret, 16);
|
||||
if(memcmp(ret, pih, 16)) {
|
||||
message(" error");
|
||||
err += 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AES_192)
|
||||
memset(out, 0xcc, 16);
|
||||
memset(ret, 0xcc, 16);
|
||||
printf("\n\n// lengths: block = 16, bytes, key = 24 bytes");
|
||||
f_enc_key192(alge, exh);
|
||||
oblk("// key = ", exh, 24);
|
||||
oblk("// input = ", pih, 16);
|
||||
do_enc(alge, pih, out, 1);
|
||||
oblk("// encrypt = ", out, 16);
|
||||
if(memcmp(out, res[1], 16)) {
|
||||
message(" error");
|
||||
err += 4;
|
||||
}
|
||||
f_dec_key192(algd, exh);
|
||||
do_dec(algd, out, ret, 1);
|
||||
oblk("// decrypt = ", ret, 16);
|
||||
if(memcmp(ret, pih, 16)) {
|
||||
message(" error");
|
||||
err += 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AES_256)
|
||||
memset(out, 0xcc, 16);
|
||||
memset(ret, 0xcc, 16);
|
||||
printf("\n\n// lengths: block = 16, bytes, key = 32 bytes");
|
||||
f_enc_key256(alge, exh);
|
||||
oblk("// key = ", exh, 32);
|
||||
oblk("// input = ", pih, 16);
|
||||
do_enc(alge, pih, out, 1);
|
||||
oblk("// encrypt = ", out, 16);
|
||||
if(memcmp(out, res[2], 16)) {
|
||||
message(" error");
|
||||
err += 16;
|
||||
}
|
||||
f_dec_key256(algd, exh);
|
||||
do_dec(algd, out, ret, 1);
|
||||
oblk("// decrypt = ", ret, 16);
|
||||
if(memcmp(ret, pih, 16)) {
|
||||
message(" error");
|
||||
err += 32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!err)
|
||||
message("\n\nThese values are all correct\n\n");
|
||||
else
|
||||
message("\n\nSome values are in error\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 20/12/2007
|
||||
*/
|
||||
|
||||
// The following definitions are required for testing only, They are not needed
|
||||
// for AES (Rijndael) implementation. They are used to allow C, C++ and DLL
|
||||
// data access and subroutine calls to be expressed in the same form in the
|
||||
// testing code.
|
||||
|
||||
#ifndef AESTST_H
|
||||
#define AESTST_H
|
||||
|
||||
#define f_info(x) (x)->inf.b[2]
|
||||
#define f_ectx aes_encrypt_ctx
|
||||
#define f_enc_key128(a, b) aes_encrypt_key128((b), (a))
|
||||
#define f_enc_key192(a, b) aes_encrypt_key192((b), (a))
|
||||
#define f_enc_key256(a, b) aes_encrypt_key256((b), (a))
|
||||
#define f_enc_key(a, b, c) aes_encrypt_key((b), (c), (a))
|
||||
#define f_enc_blk(a, b, c) aes_encrypt((b), (c), (a))
|
||||
|
||||
#define f_dctx aes_decrypt_ctx
|
||||
#define f_dec_key128(a, b) aes_decrypt_key128((b), (a))
|
||||
#define f_dec_key192(a, b) aes_decrypt_key192((b), (a))
|
||||
#define f_dec_key256(a, b) aes_decrypt_key256((b), (a))
|
||||
#define f_dec_key(a, b, c) aes_decrypt_key((b), (c), (a))
|
||||
#define f_dec_blk(a, b, c) aes_decrypt((b), (c), (a))
|
||||
|
||||
#define f_talign(a, b) aes_test_alignment_detection(b)
|
||||
#define f_mode_reset(a) aes_mode_reset(a)
|
||||
#define f_ecb_enc(a, b, c, d) aes_ecb_encrypt((b), (c), (d), (a))
|
||||
#define f_ecb_dec(a, b, c, d) aes_ecb_decrypt((b), (c), (d), (a))
|
||||
#define f_cbc_enc(a, b, c, d, e) aes_cbc_encrypt((b), (c), (d), (e), (a))
|
||||
#define f_cbc_dec(a, b, c, d, e) aes_cbc_decrypt((b), (c), (d), (e), (a))
|
||||
#define f_cfb_enc(a, b, c, d, e) aes_cfb_encrypt((b), (c), (d), (e), (a))
|
||||
#define f_cfb_dec(a, b, c, d, e) aes_cfb_decrypt((b), (c), (d), (e), (a))
|
||||
#define f_ofb_cry(a, b, c, d, e) aes_ofb_crypt((b), (c), (d), (e), (a))
|
||||
#define f_ctr_cry(a, b, c, d, e, f) aes_ctr_crypt((b), (c), (d), (e), (f), (a))
|
||||
|
||||
#define ek_name128 "aes_encrypt_key128"
|
||||
#define ek_name192 "aes_encrypt_key192"
|
||||
#define ek_name256 "aes_encrypt_key256"
|
||||
#define ek_name "aes_encrypt_key"
|
||||
#define eb_name "aes_encrypt"
|
||||
|
||||
#define dk_name128 "aes_decrypt_key128"
|
||||
#define dk_name192 "aes_decrypt_key192"
|
||||
#define dk_name256 "aes_decrypt_key256"
|
||||
#define dk_name "aes_decrypt_key"
|
||||
#define db_name "aes_decrypt"
|
||||
|
||||
#define eres_name "aes_mode_reset"
|
||||
#define ecbe_name "aes_ecb_encrypt"
|
||||
#define ecbd_name "aes_ecb_decrypt"
|
||||
#define cbce_name "aes_cbc_encrypt"
|
||||
#define cbcd_name "aes_cbc_decrypt"
|
||||
#define cfbe_name "aes_cfb_encrypt"
|
||||
#define cfbd_name "aes_cfb_decrypt"
|
||||
#define ofb_name "aes_ofb_crypt"
|
||||
#define ctr_name "aes_ctr_crypt"
|
||||
|
||||
#ifndef AES_N_BLOCK
|
||||
#define do_enc(a, b, c, d) f_enc_blk(a, b, c)
|
||||
#define do_dec(a, b, c, d) f_dec_blk(a, b, c)
|
||||
#else
|
||||
#define do_enc(a, b, c, d) f_ecb_enc(a, b, c, 1)
|
||||
#define do_dec(a, b, c, d) f_ecb_dec(a, b, c, 1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
241
applications/external/flipbip/lib/crypto/base32.c
vendored
241
applications/external/flipbip/lib/crypto/base32.c
vendored
@@ -1,241 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017 Saleem Rashid
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, E1PRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "base32.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
const char* BASE32_ALPHABET_RFC4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ23456789";
|
||||
|
||||
static inline void base32_5to8(const uint8_t* in, uint8_t length, uint8_t* out);
|
||||
static inline bool
|
||||
base32_8to5(const uint8_t* in, uint8_t length, uint8_t* out, const char* alphabet);
|
||||
static inline void base32_8to5_raw(const uint8_t* in, uint8_t length, uint8_t* out);
|
||||
|
||||
static inline int base32_encode_character(uint8_t decoded, const char* alphabet);
|
||||
static inline int base32_decode_character(char encoded, const char* alphabet);
|
||||
|
||||
char* base32_encode(
|
||||
const uint8_t* in,
|
||||
size_t inlen,
|
||||
char* out,
|
||||
size_t outlen,
|
||||
const char* alphabet) {
|
||||
size_t length = base32_encoded_length(inlen);
|
||||
if(outlen <= length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
base32_encode_unsafe(in, inlen, (uint8_t*)out);
|
||||
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int ret = base32_encode_character(out[i], alphabet);
|
||||
|
||||
if(ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
out[i] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
out[length] = '\0';
|
||||
return &out[length];
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
base32_decode(const char* in, size_t inlen, uint8_t* out, size_t outlen, const char* alphabet) {
|
||||
size_t length = base32_decoded_length(inlen);
|
||||
if(outlen < length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!base32_decode_unsafe((uint8_t*)in, inlen, (uint8_t*)out, alphabet)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &out[length];
|
||||
}
|
||||
|
||||
void base32_encode_unsafe(const uint8_t* in, size_t inlen, uint8_t* out) {
|
||||
uint8_t remainder = inlen % 5;
|
||||
size_t limit = inlen - remainder;
|
||||
|
||||
size_t i = 0, j = 0;
|
||||
for(i = 0, j = 0; i < limit; i += 5, j += 8) {
|
||||
base32_5to8(&in[i], 5, &out[j]);
|
||||
}
|
||||
|
||||
if(remainder) base32_5to8(&in[i], remainder, &out[j]);
|
||||
}
|
||||
|
||||
bool base32_decode_unsafe(const uint8_t* in, size_t inlen, uint8_t* out, const char* alphabet) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
size_t limit = inlen - remainder;
|
||||
|
||||
size_t i = 0, j = 0;
|
||||
for(i = 0, j = 0; i < limit; i += 8, j += 5) {
|
||||
if(!base32_8to5(&in[i], 8, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(remainder && !base32_8to5(&in[i], remainder, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t base32_encoded_length(size_t inlen) {
|
||||
uint8_t remainder = inlen % 5;
|
||||
|
||||
return (inlen / 5) * 8 + (remainder * 8 + 4) / 5;
|
||||
}
|
||||
|
||||
size_t base32_decoded_length(size_t inlen) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
|
||||
return (inlen / 8) * 5 + (remainder * 5) / 8;
|
||||
}
|
||||
|
||||
void base32_5to8(const uint8_t* in, uint8_t length, uint8_t* out) {
|
||||
if(length >= 1) {
|
||||
out[0] = (in[0] >> 3);
|
||||
out[1] = (in[0] & 7) << 2;
|
||||
}
|
||||
|
||||
if(length >= 2) {
|
||||
out[1] |= (in[1] >> 6);
|
||||
out[2] = (in[1] >> 1) & 31;
|
||||
out[3] = (in[1] & 1) << 4;
|
||||
}
|
||||
|
||||
if(length >= 3) {
|
||||
out[3] |= (in[2] >> 4);
|
||||
out[4] = (in[2] & 15) << 1;
|
||||
}
|
||||
|
||||
if(length >= 4) {
|
||||
out[4] |= (in[3] >> 7);
|
||||
out[5] = (in[3] >> 2) & 31;
|
||||
out[6] = (in[3] & 3) << 3;
|
||||
}
|
||||
|
||||
if(length >= 5) {
|
||||
out[6] |= (in[4] >> 5);
|
||||
out[7] = (in[4] & 31);
|
||||
}
|
||||
}
|
||||
|
||||
bool base32_8to5(const uint8_t* in, uint8_t length, uint8_t* out, const char* alphabet) {
|
||||
if(length == 1 || length == 3 || length == 6 || length > 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(alphabet) {
|
||||
uint8_t decoded[length];
|
||||
memset(decoded, 0, sizeof(decoded));
|
||||
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int ret = base32_decode_character(in[i], alphabet);
|
||||
|
||||
if(ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
decoded[i] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
base32_8to5_raw(decoded, length, out);
|
||||
} else {
|
||||
base32_8to5_raw(in, length, out);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void base32_8to5_raw(const uint8_t* in, uint8_t length, uint8_t* out) {
|
||||
if(length >= 2) {
|
||||
out[0] = (in[0] << 3);
|
||||
out[0] |= (in[1] >> 2);
|
||||
}
|
||||
|
||||
if(length >= 4) {
|
||||
out[1] = (in[1] & 3) << 6;
|
||||
out[1] |= (in[2] << 1);
|
||||
out[1] |= (in[3] >> 4);
|
||||
}
|
||||
|
||||
if(length >= 5) {
|
||||
out[2] = (in[3] & 15) << 4;
|
||||
out[2] |= (in[4] >> 1);
|
||||
}
|
||||
|
||||
if(length >= 7) {
|
||||
out[3] = (in[4] & 1) << 7;
|
||||
out[3] |= (in[5] << 2);
|
||||
out[3] |= (in[6] >> 3);
|
||||
}
|
||||
|
||||
if(length >= 8) {
|
||||
out[4] = (in[6] & 7) << 5;
|
||||
out[4] |= (in[7] & 31);
|
||||
}
|
||||
}
|
||||
|
||||
int base32_encode_character(uint8_t decoded, const char* alphabet) {
|
||||
if(decoded >> 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if(decoded < 26) {
|
||||
return 'A' + decoded;
|
||||
} else {
|
||||
return '2' - 26 + decoded;
|
||||
}
|
||||
}
|
||||
|
||||
return alphabet[decoded];
|
||||
}
|
||||
|
||||
int base32_decode_character(char encoded, const char* alphabet) {
|
||||
if(alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if(encoded >= 'A' && encoded <= 'Z') {
|
||||
return encoded - 'A';
|
||||
} else if(encoded >= 'a' && encoded <= 'z') {
|
||||
return encoded - 'a';
|
||||
} else if(encoded >= '2' && encoded <= '7') {
|
||||
return encoded - '2' + 26;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char* occurrence = strchr(alphabet, encoded);
|
||||
|
||||
if(occurrence) {
|
||||
return occurrence - alphabet;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2017 Saleem Rashid
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BASE32_H__
|
||||
#define __BASE32_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern const char* BASE32_ALPHABET_RFC4648;
|
||||
|
||||
char* base32_encode(const uint8_t* in, size_t inlen, char* out, size_t outlen, const char* alphabet);
|
||||
void base32_encode_unsafe(const uint8_t* in, size_t inlen, uint8_t* out);
|
||||
|
||||
uint8_t*
|
||||
base32_decode(const char* in, size_t inlen, uint8_t* out, size_t outlen, const char* alphabet);
|
||||
bool base32_decode_unsafe(const uint8_t* in, size_t inlen, uint8_t* out, const char* alphabet);
|
||||
|
||||
size_t base32_encoded_length(size_t inlen);
|
||||
size_t base32_decoded_length(size_t inlen);
|
||||
|
||||
#endif
|
||||
219
applications/external/flipbip/lib/crypto/base58.c
vendored
219
applications/external/flipbip/lib/crypto/base58.c
vendored
@@ -1,219 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2012-2014 Luke Dashjr
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "base58.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "memzero.h"
|
||||
#include "ripemd160.h"
|
||||
#include "sha2.h"
|
||||
|
||||
const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
const int8_t b58digits_map[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
30, 31, 32, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,
|
||||
};
|
||||
|
||||
typedef uint64_t b58_maxint_t;
|
||||
typedef uint32_t b58_almostmaxint_t;
|
||||
#define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8)
|
||||
static const b58_almostmaxint_t b58_almostmaxint_mask =
|
||||
((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1);
|
||||
|
||||
// Decodes a null-terminated Base58 string `b58` to binary and writes the result
|
||||
// at the end of the buffer `bin` of size `*binszp`. On success `*binszp` is set
|
||||
// to the number of valid bytes at the end of the buffer.
|
||||
bool b58tobin(void* bin, size_t* binszp, const char* b58) {
|
||||
size_t binsz = *binszp;
|
||||
|
||||
if(binsz == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char* b58u = (const unsigned char*)b58;
|
||||
unsigned char* binu = bin;
|
||||
size_t outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t);
|
||||
b58_almostmaxint_t outi[outisz];
|
||||
b58_maxint_t t = 0;
|
||||
b58_almostmaxint_t c = 0;
|
||||
size_t i = 0, j = 0;
|
||||
uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t);
|
||||
b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
|
||||
size_t b58sz = strlen(b58);
|
||||
|
||||
memzero(outi, sizeof(outi));
|
||||
|
||||
// Leading zeros, just count
|
||||
for(i = 0; i < b58sz && b58u[i] == '1'; ++i) ++zerocount;
|
||||
|
||||
for(; i < b58sz; ++i) {
|
||||
if(b58u[i] & 0x80)
|
||||
// High-bit set on invalid digit
|
||||
return false;
|
||||
if(b58digits_map[b58u[i]] == -1)
|
||||
// Invalid base58 digit
|
||||
return false;
|
||||
c = (unsigned)b58digits_map[b58u[i]];
|
||||
for(j = outisz; j--;) {
|
||||
t = ((b58_maxint_t)outi[j]) * 58 + c;
|
||||
c = t >> b58_almostmaxint_bits;
|
||||
outi[j] = t & b58_almostmaxint_mask;
|
||||
}
|
||||
if(c)
|
||||
// Output number too big (carry to the next int32)
|
||||
return false;
|
||||
if(outi[0] & zeromask)
|
||||
// Output number too big (last int32 filled too far)
|
||||
return false;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
if(bytesleft) {
|
||||
for(i = bytesleft; i > 0; --i) {
|
||||
*(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
|
||||
for(; j < outisz; ++j) {
|
||||
for(i = sizeof(*outi); i > 0; --i) {
|
||||
*(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
// locate the most significant byte
|
||||
binu = bin;
|
||||
for(i = 0; i < binsz; ++i) {
|
||||
if(binu[i]) break;
|
||||
}
|
||||
|
||||
// prepend the correct number of null-bytes
|
||||
if(zerocount > i) {
|
||||
/* result too large */
|
||||
return false;
|
||||
}
|
||||
*binszp = binsz - i + zerocount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int b58check(const void* bin, size_t binsz, HasherType hasher_type, const char* base58str) {
|
||||
unsigned char buf[32] = {0};
|
||||
const uint8_t* binc = bin;
|
||||
unsigned i = 0;
|
||||
if(binsz < 4) return -4;
|
||||
hasher_Raw(hasher_type, bin, binsz - 4, buf);
|
||||
if(memcmp(&binc[binsz - 4], buf, 4)) return -1;
|
||||
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid
|
||||
// possibility of accessing base58str beyond the end)
|
||||
for(i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) {
|
||||
} // Just finding the end of zeros, nothing to do in loop
|
||||
if(binc[i] == '\0' || base58str[i] == '1') return -3;
|
||||
|
||||
return binc[0];
|
||||
}
|
||||
|
||||
bool b58enc(char* b58, size_t* b58sz, const void* data, size_t binsz) {
|
||||
const uint8_t* bin = data;
|
||||
int carry = 0;
|
||||
size_t i = 0, j = 0, high = 0, zcount = 0;
|
||||
size_t size = 0;
|
||||
|
||||
while(zcount < binsz && !bin[zcount]) ++zcount;
|
||||
|
||||
size = (binsz - zcount) * 138 / 100 + 1;
|
||||
uint8_t buf[size];
|
||||
memzero(buf, size);
|
||||
|
||||
for(i = zcount, high = size - 1; i < binsz; ++i, high = j) {
|
||||
for(carry = bin[i], j = size - 1; (j > high) || carry; --j) {
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
if(!j) {
|
||||
// Otherwise j wraps to maxint which is > high
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < size && !buf[j]; ++j)
|
||||
;
|
||||
|
||||
if(*b58sz <= zcount + size - j) {
|
||||
*b58sz = zcount + size - j + 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(zcount) memset(b58, '1', zcount);
|
||||
for(i = zcount; j < size; ++i, ++j) b58[i] = b58digits_ordered[buf[j]];
|
||||
b58[i] = '\0';
|
||||
*b58sz = i + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int base58_encode_check(
|
||||
const uint8_t* data,
|
||||
int datalen,
|
||||
HasherType hasher_type,
|
||||
char* str,
|
||||
int strsize) {
|
||||
if(datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
uint8_t* hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
hasher_Raw(hasher_type, data, datalen, hash);
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
}
|
||||
|
||||
int base58_decode_check(const char* str, HasherType hasher_type, uint8_t* data, int datalen) {
|
||||
if(datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
memset(d, 0, sizeof(d));
|
||||
size_t res = datalen + 4;
|
||||
if(b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t* nd = d + datalen + 4 - res;
|
||||
if(b58check(nd, res, hasher_type, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BASE58_H__
|
||||
#define __BASE58_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
extern const char b58digits_ordered[];
|
||||
extern const int8_t b58digits_map[];
|
||||
|
||||
int base58_encode_check(
|
||||
const uint8_t* data,
|
||||
int len,
|
||||
HasherType hasher_type,
|
||||
char* str,
|
||||
int strsize);
|
||||
int base58_decode_check(const char* str, HasherType hasher_type, uint8_t* data, int datalen);
|
||||
|
||||
// Private
|
||||
bool b58tobin(void* bin, size_t* binszp, const char* b58);
|
||||
int b58check(const void* bin, size_t binsz, HasherType hasher_type, const char* base58str);
|
||||
bool b58enc(char* b58, size_t* b58sz, const void* data, size_t binsz);
|
||||
|
||||
#endif
|
||||
1834
applications/external/flipbip/lib/crypto/bignum.c
vendored
1834
applications/external/flipbip/lib/crypto/bignum.c
vendored
File diff suppressed because it is too large
Load Diff
195
applications/external/flipbip/lib/crypto/bignum.h
vendored
195
applications/external/flipbip/lib/crypto/bignum.h
vendored
@@ -1,195 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
* Copyright (c) 2016 Alex Beregszaszi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BIGNUM_H__
|
||||
#define __BIGNUM_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "options.h"
|
||||
|
||||
#define BN_LIMBS 9
|
||||
#define BN_BITS_PER_LIMB 29
|
||||
#define BN_BASE (1u << BN_BITS_PER_LIMB)
|
||||
#define BN_LIMB_MASK ((1u << BN_BITS_PER_LIMB) - 1)
|
||||
#define BN_EXTRA_BITS (32 - BN_BITS_PER_LIMB)
|
||||
#define BN_BITS_LAST_LIMB (256 - (BN_LIMBS - 1) * BN_BITS_PER_LIMB)
|
||||
|
||||
// Represents the number sum([val[i] * 2**(29*i) for i in range(9))
|
||||
typedef struct {
|
||||
uint32_t val[BN_LIMBS];
|
||||
} bignum256;
|
||||
|
||||
static inline uint32_t read_be(const uint8_t* data) {
|
||||
return (((uint32_t)data[0]) << 24) | (((uint32_t)data[1]) << 16) | (((uint32_t)data[2]) << 8) |
|
||||
(((uint32_t)data[3]));
|
||||
}
|
||||
|
||||
static inline void write_be(uint8_t* data, uint32_t x) {
|
||||
data[0] = x >> 24;
|
||||
data[1] = x >> 16;
|
||||
data[2] = x >> 8;
|
||||
data[3] = x;
|
||||
}
|
||||
|
||||
static inline uint32_t read_le(const uint8_t* data) {
|
||||
return (((uint32_t)data[3]) << 24) | (((uint32_t)data[2]) << 16) | (((uint32_t)data[1]) << 8) |
|
||||
(((uint32_t)data[0]));
|
||||
}
|
||||
|
||||
static inline void write_le(uint8_t* data, uint32_t x) {
|
||||
data[3] = x >> 24;
|
||||
data[2] = x >> 16;
|
||||
data[1] = x >> 8;
|
||||
data[0] = x;
|
||||
}
|
||||
|
||||
void bn_read_be(const uint8_t* in_number, bignum256* out_number);
|
||||
void bn_write_be(const bignum256* in_number, uint8_t* out_number);
|
||||
void bn_read_le(const uint8_t* in_number, bignum256* out_number);
|
||||
void bn_write_le(const bignum256* in_number, uint8_t* out_number);
|
||||
void bn_read_uint32(uint32_t in_number, bignum256* out_number);
|
||||
void bn_read_uint64(uint64_t in_number, bignum256* out_number);
|
||||
int bn_bitcount(const bignum256* x);
|
||||
unsigned int bn_digitcount(const bignum256* x);
|
||||
void bn_zero(bignum256* x);
|
||||
void bn_one(bignum256* x);
|
||||
int bn_is_zero(const bignum256* x);
|
||||
int bn_is_one(const bignum256* x);
|
||||
int bn_is_less(const bignum256* x, const bignum256* y);
|
||||
int bn_is_equal(const bignum256* x, const bignum256* y);
|
||||
void bn_cmov(
|
||||
bignum256* res,
|
||||
volatile uint32_t cond,
|
||||
const bignum256* truecase,
|
||||
const bignum256* falsecase);
|
||||
void bn_cnegate(volatile uint32_t cond, bignum256* x, const bignum256* prime);
|
||||
void bn_lshift(bignum256* x);
|
||||
void bn_rshift(bignum256* x);
|
||||
void bn_setbit(bignum256* x, uint16_t i);
|
||||
void bn_clearbit(bignum256* x, uint16_t i);
|
||||
uint32_t bn_testbit(const bignum256* x, uint16_t i);
|
||||
void bn_xor(bignum256* res, const bignum256* x, const bignum256* y);
|
||||
void bn_mult_half(bignum256* x, const bignum256* prime);
|
||||
void bn_mult_k(bignum256* x, uint8_t k, const bignum256* prime);
|
||||
void bn_mod(bignum256* x, const bignum256* prime);
|
||||
void bn_multiply(const bignum256* k, bignum256* x, const bignum256* prime);
|
||||
void bn_fast_mod(bignum256* x, const bignum256* prime);
|
||||
void bn_power_mod(const bignum256* x, const bignum256* e, const bignum256* prime, bignum256* res);
|
||||
void bn_sqrt(bignum256* x, const bignum256* prime);
|
||||
uint32_t inverse_mod_power_two(uint32_t a, uint32_t n);
|
||||
void bn_divide_base(bignum256* x, const bignum256* prime);
|
||||
void bn_normalize(bignum256* x);
|
||||
void bn_add(bignum256* x, const bignum256* y);
|
||||
void bn_addmod(bignum256* x, const bignum256* y, const bignum256* prime);
|
||||
void bn_addi(bignum256* x, uint32_t y);
|
||||
void bn_subi(bignum256* x, uint32_t y, const bignum256* prime);
|
||||
void bn_subtractmod(const bignum256* x, const bignum256* y, bignum256* res, const bignum256* prime);
|
||||
void bn_subtract(const bignum256* x, const bignum256* y, bignum256* res);
|
||||
void bn_long_division(bignum256* x, uint32_t d, bignum256* q, uint32_t* r);
|
||||
void bn_divmod58(bignum256* x, uint32_t* r);
|
||||
void bn_divmod1000(bignum256* x, uint32_t* r);
|
||||
void bn_inverse(bignum256* x, const bignum256* prime);
|
||||
size_t bn_format(
|
||||
const bignum256* amount,
|
||||
const char* prefix,
|
||||
const char* suffix,
|
||||
unsigned int decimals,
|
||||
int exponent,
|
||||
bool trailing,
|
||||
char thousands,
|
||||
char* output,
|
||||
size_t output_length);
|
||||
|
||||
// Returns (uint32_t) in_number
|
||||
// Assumes in_number < 2**32
|
||||
// Assumes in_number is normalized
|
||||
static inline uint32_t bn_write_uint32(const bignum256* in_number) {
|
||||
return in_number->val[0] | (in_number->val[1] << BN_BITS_PER_LIMB);
|
||||
}
|
||||
|
||||
// Returns (uint64_t) in_number
|
||||
// Assumes in_number < 2**64
|
||||
// Assumes in_number is normalized
|
||||
static inline uint64_t bn_write_uint64(const bignum256* in_number) {
|
||||
uint64_t acc;
|
||||
acc = in_number->val[2];
|
||||
acc <<= BN_BITS_PER_LIMB;
|
||||
acc |= in_number->val[1];
|
||||
acc <<= BN_BITS_PER_LIMB;
|
||||
acc |= in_number->val[0];
|
||||
return acc;
|
||||
}
|
||||
|
||||
// y = x
|
||||
static inline void bn_copy(const bignum256* x, bignum256* y) {
|
||||
*y = *x;
|
||||
}
|
||||
|
||||
// Returns x % 2 == 0
|
||||
static inline int bn_is_even(const bignum256* x) {
|
||||
return (x->val[0] & 1) == 0;
|
||||
}
|
||||
|
||||
// Returns x % 2 == 0
|
||||
static inline int bn_is_odd(const bignum256* x) {
|
||||
return (x->val[0] & 1) == 1;
|
||||
}
|
||||
|
||||
static inline size_t bn_format_uint64(
|
||||
uint64_t amount,
|
||||
const char* prefix,
|
||||
const char* suffix,
|
||||
unsigned int decimals,
|
||||
int exponent,
|
||||
bool trailing,
|
||||
char thousands,
|
||||
char* output,
|
||||
size_t output_length) {
|
||||
bignum256 bn_amount;
|
||||
bn_read_uint64(amount, &bn_amount);
|
||||
|
||||
return bn_format(
|
||||
&bn_amount, prefix, suffix, decimals, exponent, trailing, thousands, output, output_length);
|
||||
}
|
||||
|
||||
static inline size_t bn_format_amount(
|
||||
uint64_t amount,
|
||||
const char* prefix,
|
||||
const char* suffix,
|
||||
unsigned int decimals,
|
||||
char* output,
|
||||
size_t output_length) {
|
||||
return bn_format_uint64(
|
||||
amount, prefix, suffix, decimals, 0, false, ',', output, output_length);
|
||||
}
|
||||
|
||||
#if USE_BN_PRINT
|
||||
void bn_print(const bignum256* x);
|
||||
void bn_print_raw(const bignum256* x);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
887
applications/external/flipbip/lib/crypto/bip32.c
vendored
887
applications/external/flipbip/lib/crypto/bip32.c
vendored
@@ -1,887 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2016 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2016 Pavol Rusnak
|
||||
* Copyright (c) 2015-2016 Jochen Hoenicke
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#if USE_NEM
|
||||
#include "aes/aes.h"
|
||||
#endif
|
||||
#include "base58.h"
|
||||
#include "bignum.h"
|
||||
#include "bip32.h"
|
||||
#include "cardano.h"
|
||||
#include "curves.h"
|
||||
#include "ecdsa.h"
|
||||
#include "ed25519_donna/ed25519_sha3.h"
|
||||
#include "ed25519_donna/ed25519.h"
|
||||
#include "hmac.h"
|
||||
#include "nist256p1.h"
|
||||
#include "secp256k1.h"
|
||||
#include "sha2.h"
|
||||
#include "sha3.h"
|
||||
#if USE_KECCAK
|
||||
#include "ed25519_donna/ed25519_keccak.h"
|
||||
#endif
|
||||
#if USE_NEM
|
||||
#include "nem.h"
|
||||
#endif
|
||||
#include "memzero.h"
|
||||
|
||||
const curve_info ed25519_info = {
|
||||
.bip32_name = ED25519_SEED_NAME,
|
||||
.params = NULL,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
||||
const curve_info ed25519_sha3_info = {
|
||||
.bip32_name = "ed25519-sha3 seed",
|
||||
.params = NULL,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
||||
#if USE_KECCAK
|
||||
const curve_info ed25519_keccak_info = {
|
||||
.bip32_name = "ed25519-keccak seed",
|
||||
.params = NULL,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
#endif
|
||||
|
||||
const curve_info curve25519_info = {
|
||||
.bip32_name = "curve25519 seed",
|
||||
.params = NULL,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
||||
int hdnode_from_xpub(
|
||||
uint32_t depth,
|
||||
uint32_t child_num,
|
||||
const uint8_t* chain_code,
|
||||
const uint8_t* public_key,
|
||||
const char* curve,
|
||||
HDNode* out) {
|
||||
const curve_info* info = get_curve_by_name(curve);
|
||||
if(info == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(public_key[0] != 0x02 && public_key[0] != 0x03) { // invalid pubkey
|
||||
return 0;
|
||||
}
|
||||
out->curve = info;
|
||||
out->depth = depth;
|
||||
out->child_num = child_num;
|
||||
memcpy(out->chain_code, chain_code, 32);
|
||||
memzero(out->private_key, 32);
|
||||
memzero(out->private_key_extension, 32);
|
||||
memcpy(out->public_key, public_key, 33);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_from_xprv(
|
||||
uint32_t depth,
|
||||
uint32_t child_num,
|
||||
const uint8_t* chain_code,
|
||||
const uint8_t* private_key,
|
||||
const char* curve,
|
||||
HDNode* out) {
|
||||
bool failed = false;
|
||||
const curve_info* info = get_curve_by_name(curve);
|
||||
if(info == 0) {
|
||||
failed = true;
|
||||
} else if(info->params) {
|
||||
bignum256 a = {0};
|
||||
bn_read_be(private_key, &a);
|
||||
if(bn_is_zero(&a)) { // == 0
|
||||
failed = true;
|
||||
} else {
|
||||
if(!bn_is_less(&a, &info->params->order)) { // >= order
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
memzero(&a, sizeof(a));
|
||||
}
|
||||
|
||||
if(failed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out->curve = info;
|
||||
out->depth = depth;
|
||||
out->child_num = child_num;
|
||||
memcpy(out->chain_code, chain_code, 32);
|
||||
memcpy(out->private_key, private_key, 32);
|
||||
memzero(out->public_key, sizeof(out->public_key));
|
||||
memzero(out->private_key_extension, sizeof(out->private_key_extension));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_from_seed(const uint8_t* seed, int seed_len, const char* curve, HDNode* out) {
|
||||
static CONFIDENTIAL uint8_t I[32 + 32];
|
||||
memzero(out, sizeof(HDNode));
|
||||
out->depth = 0;
|
||||
out->child_num = 0;
|
||||
out->curve = get_curve_by_name(curve);
|
||||
if(out->curve == 0) {
|
||||
return 0;
|
||||
}
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX ctx;
|
||||
hmac_sha512_Init(&ctx, (const uint8_t*)out->curve->bip32_name, strlen(out->curve->bip32_name));
|
||||
hmac_sha512_Update(&ctx, seed, seed_len);
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
|
||||
if(out->curve->params) {
|
||||
bignum256 a = {0};
|
||||
while(true) {
|
||||
bn_read_be(I, &a);
|
||||
if(!bn_is_zero(&a) // != 0
|
||||
&& bn_is_less(&a, &out->curve->params->order)) { // < order
|
||||
break;
|
||||
}
|
||||
hmac_sha512_Init(
|
||||
&ctx, (const uint8_t*)out->curve->bip32_name, strlen(out->curve->bip32_name));
|
||||
hmac_sha512_Update(&ctx, I, sizeof(I));
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
}
|
||||
memzero(&a, sizeof(a));
|
||||
}
|
||||
memcpy(out->private_key, I, 32);
|
||||
memcpy(out->chain_code, I + 32, 32);
|
||||
memzero(out->public_key, sizeof(out->public_key));
|
||||
memzero(I, sizeof(I));
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t hdnode_fingerprint(HDNode* node) {
|
||||
uint8_t digest[32] = {0};
|
||||
uint32_t fingerprint = 0;
|
||||
|
||||
hdnode_fill_public_key(node);
|
||||
hasher_Raw(node->curve->hasher_pubkey, node->public_key, 33, digest);
|
||||
fingerprint = ((uint32_t)digest[0] << 24) + (digest[1] << 16) + (digest[2] << 8) + digest[3];
|
||||
memzero(digest, sizeof(digest));
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
int hdnode_private_ckd_bip32(HDNode* inout, uint32_t i) {
|
||||
static CONFIDENTIAL uint8_t data[1 + 32 + 4];
|
||||
static CONFIDENTIAL uint8_t I[32 + 32];
|
||||
static CONFIDENTIAL bignum256 a, b;
|
||||
|
||||
#if USE_CARDANO
|
||||
if(inout->curve == &ed25519_cardano_info) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(i & 0x80000000) { // private derivation
|
||||
data[0] = 0;
|
||||
memcpy(data + 1, inout->private_key, 32);
|
||||
} else { // public derivation
|
||||
if(!inout->curve->params) {
|
||||
return 0;
|
||||
}
|
||||
if(hdnode_fill_public_key(inout) != 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, inout->public_key, 33);
|
||||
}
|
||||
write_be(data + 33, i);
|
||||
|
||||
bn_read_be(inout->private_key, &a);
|
||||
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX ctx;
|
||||
hmac_sha512_Init(&ctx, inout->chain_code, 32);
|
||||
hmac_sha512_Update(&ctx, data, sizeof(data));
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
|
||||
if(inout->curve->params) {
|
||||
while(true) {
|
||||
bool failed = false;
|
||||
bn_read_be(I, &b);
|
||||
if(!bn_is_less(&b, &inout->curve->params->order)) { // >= order
|
||||
failed = true;
|
||||
} else {
|
||||
bn_add(&b, &a);
|
||||
bn_mod(&b, &inout->curve->params->order);
|
||||
if(bn_is_zero(&b)) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!failed) {
|
||||
bn_write_be(&b, inout->private_key);
|
||||
break;
|
||||
}
|
||||
|
||||
data[0] = 1;
|
||||
memcpy(data + 1, I + 32, 32);
|
||||
hmac_sha512_Init(&ctx, inout->chain_code, 32);
|
||||
hmac_sha512_Update(&ctx, data, sizeof(data));
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
}
|
||||
} else {
|
||||
memcpy(inout->private_key, I, 32);
|
||||
}
|
||||
|
||||
memcpy(inout->chain_code, I + 32, 32);
|
||||
inout->depth++;
|
||||
inout->child_num = i;
|
||||
memzero(inout->public_key, sizeof(inout->public_key));
|
||||
|
||||
// making sure to wipe our memory
|
||||
memzero(&a, sizeof(a));
|
||||
memzero(&b, sizeof(b));
|
||||
memzero(I, sizeof(I));
|
||||
memzero(data, sizeof(data));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_private_ckd(HDNode* inout, uint32_t i) {
|
||||
#if USE_CARDANO
|
||||
if(inout->curve == &ed25519_cardano_info) {
|
||||
return hdnode_private_ckd_cardano(inout, i);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return hdnode_private_ckd_bip32(inout, i);
|
||||
}
|
||||
}
|
||||
|
||||
int hdnode_public_ckd_cp(
|
||||
const ecdsa_curve* curve,
|
||||
const curve_point* parent,
|
||||
const uint8_t* parent_chain_code,
|
||||
uint32_t i,
|
||||
curve_point* child,
|
||||
uint8_t* child_chain_code) {
|
||||
uint8_t data[(1 + 32) + 4] = {0};
|
||||
uint8_t I[32 + 32] = {0};
|
||||
bignum256 c = {0};
|
||||
|
||||
if(i & 0x80000000) { // private derivation
|
||||
return 0;
|
||||
}
|
||||
|
||||
data[0] = 0x02 | (parent->y.val[0] & 0x01);
|
||||
bn_write_be(&parent->x, data + 1);
|
||||
write_be(data + 33, i);
|
||||
|
||||
while(true) {
|
||||
hmac_sha512(parent_chain_code, 32, data, sizeof(data), I);
|
||||
bn_read_be(I, &c);
|
||||
if(bn_is_less(&c, &curve->order)) { // < order
|
||||
scalar_multiply(curve, &c, child); // b = c * G
|
||||
point_add(curve, parent, child); // b = a + b
|
||||
if(!point_is_infinity(child)) {
|
||||
if(child_chain_code) {
|
||||
memcpy(child_chain_code, I + 32, 32);
|
||||
}
|
||||
|
||||
// Wipe all stack data.
|
||||
memzero(data, sizeof(data));
|
||||
memzero(I, sizeof(I));
|
||||
memzero(&c, sizeof(c));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
data[0] = 1;
|
||||
memcpy(data + 1, I + 32, 32);
|
||||
}
|
||||
}
|
||||
|
||||
int hdnode_public_ckd(HDNode* inout, uint32_t i) {
|
||||
curve_point parent = {0}, child = {0};
|
||||
|
||||
if(!ecdsa_read_pubkey(inout->curve->params, inout->public_key, &parent)) {
|
||||
return 0;
|
||||
}
|
||||
if(!hdnode_public_ckd_cp(
|
||||
inout->curve->params, &parent, inout->chain_code, i, &child, inout->chain_code)) {
|
||||
return 0;
|
||||
}
|
||||
memzero(inout->private_key, 32);
|
||||
inout->depth++;
|
||||
inout->child_num = i;
|
||||
inout->public_key[0] = 0x02 | (child.y.val[0] & 0x01);
|
||||
bn_write_be(&child.x, inout->public_key + 1);
|
||||
|
||||
// Wipe all stack data.
|
||||
memzero(&parent, sizeof(parent));
|
||||
memzero(&child, sizeof(child));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void hdnode_public_ckd_address_optimized(
|
||||
const curve_point* pub,
|
||||
const uint8_t* chain_code,
|
||||
uint32_t i,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
HasherType hasher_base58,
|
||||
char* addr,
|
||||
int addrsize,
|
||||
int addrformat) {
|
||||
uint8_t child_pubkey[33] = {0};
|
||||
curve_point b = {0};
|
||||
|
||||
hdnode_public_ckd_cp(&secp256k1, pub, chain_code, i, &b, NULL);
|
||||
child_pubkey[0] = 0x02 | (b.y.val[0] & 0x01);
|
||||
bn_write_be(&b.x, child_pubkey + 1);
|
||||
|
||||
switch(addrformat) {
|
||||
case 1: // Segwit-in-P2SH
|
||||
ecdsa_get_address_segwit_p2sh(
|
||||
child_pubkey, version, hasher_pubkey, hasher_base58, addr, addrsize);
|
||||
break;
|
||||
default: // normal address
|
||||
ecdsa_get_address(child_pubkey, version, hasher_pubkey, hasher_base58, addr, addrsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_BIP32_CACHE
|
||||
static bool private_ckd_cache_root_set = false;
|
||||
static CONFIDENTIAL HDNode private_ckd_cache_root;
|
||||
static int private_ckd_cache_index = 0;
|
||||
|
||||
static CONFIDENTIAL struct {
|
||||
bool set;
|
||||
size_t depth;
|
||||
uint32_t i[BIP32_CACHE_MAXDEPTH];
|
||||
HDNode node;
|
||||
} private_ckd_cache[BIP32_CACHE_SIZE];
|
||||
|
||||
void bip32_cache_clear(void) {
|
||||
private_ckd_cache_root_set = false;
|
||||
private_ckd_cache_index = 0;
|
||||
memzero(&private_ckd_cache_root, sizeof(private_ckd_cache_root));
|
||||
memzero(private_ckd_cache, sizeof(private_ckd_cache));
|
||||
}
|
||||
|
||||
int hdnode_private_ckd_cached(
|
||||
HDNode* inout,
|
||||
const uint32_t* i,
|
||||
size_t i_count,
|
||||
uint32_t* fingerprint) {
|
||||
if(i_count == 0) {
|
||||
// no way how to compute parent fingerprint
|
||||
return 1;
|
||||
}
|
||||
if(i_count == 1) {
|
||||
if(fingerprint) {
|
||||
*fingerprint = hdnode_fingerprint(inout);
|
||||
}
|
||||
if(hdnode_private_ckd(inout, i[0]) == 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
// if root is not set or not the same
|
||||
if(!private_ckd_cache_root_set ||
|
||||
memcmp(&private_ckd_cache_root, inout, sizeof(HDNode)) != 0) {
|
||||
// clear the cache
|
||||
private_ckd_cache_index = 0;
|
||||
memzero(private_ckd_cache, sizeof(private_ckd_cache));
|
||||
// setup new root
|
||||
memcpy(&private_ckd_cache_root, inout, sizeof(HDNode));
|
||||
private_ckd_cache_root_set = true;
|
||||
} else {
|
||||
// try to find parent
|
||||
int j = 0;
|
||||
for(j = 0; j < BIP32_CACHE_SIZE; j++) {
|
||||
if(private_ckd_cache[j].set && private_ckd_cache[j].depth == i_count - 1 &&
|
||||
memcmp(private_ckd_cache[j].i, i, (i_count - 1) * sizeof(uint32_t)) == 0 &&
|
||||
private_ckd_cache[j].node.curve == inout->curve) {
|
||||
memcpy(inout, &(private_ckd_cache[j].node), sizeof(HDNode));
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else derive parent
|
||||
if(!found) {
|
||||
size_t k = 0;
|
||||
for(k = 0; k < i_count - 1; k++) {
|
||||
if(hdnode_private_ckd(inout, i[k]) == 0) return 0;
|
||||
}
|
||||
// and save it
|
||||
memzero(
|
||||
&(private_ckd_cache[private_ckd_cache_index]),
|
||||
sizeof(private_ckd_cache[private_ckd_cache_index]));
|
||||
private_ckd_cache[private_ckd_cache_index].set = true;
|
||||
private_ckd_cache[private_ckd_cache_index].depth = i_count - 1;
|
||||
memcpy(private_ckd_cache[private_ckd_cache_index].i, i, (i_count - 1) * sizeof(uint32_t));
|
||||
memcpy(&(private_ckd_cache[private_ckd_cache_index].node), inout, sizeof(HDNode));
|
||||
private_ckd_cache_index = (private_ckd_cache_index + 1) % BIP32_CACHE_SIZE;
|
||||
}
|
||||
|
||||
if(fingerprint) {
|
||||
*fingerprint = hdnode_fingerprint(inout);
|
||||
}
|
||||
if(hdnode_private_ckd(inout, i[i_count - 1]) == 0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int hdnode_get_address_raw(HDNode* node, uint32_t version, uint8_t* addr_raw) {
|
||||
if(hdnode_fill_public_key(node) != 0) {
|
||||
return 1;
|
||||
}
|
||||
ecdsa_get_address_raw(node->public_key, version, node->curve->hasher_pubkey, addr_raw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdnode_get_address(HDNode* node, uint32_t version, char* addr, int addrsize) {
|
||||
if(hdnode_fill_public_key(node) != 0) {
|
||||
return 1;
|
||||
}
|
||||
ecdsa_get_address(
|
||||
node->public_key,
|
||||
version,
|
||||
node->curve->hasher_pubkey,
|
||||
node->curve->hasher_base58,
|
||||
addr,
|
||||
addrsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdnode_fill_public_key(HDNode* node) {
|
||||
if(node->public_key[0] != 0) return 0;
|
||||
|
||||
#if USE_BIP32_25519_CURVES
|
||||
if(node->curve->params) {
|
||||
if(ecdsa_get_public_key33(node->curve->params, node->private_key, node->public_key) != 0) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
node->public_key[0] = 1;
|
||||
if(node->curve == &ed25519_info) {
|
||||
ed25519_publickey(node->private_key, node->public_key + 1);
|
||||
} else if(node->curve == &ed25519_sha3_info) {
|
||||
ed25519_publickey_sha3(node->private_key, node->public_key + 1);
|
||||
#if USE_KECCAK
|
||||
} else if(node->curve == &ed25519_keccak_info) {
|
||||
ed25519_publickey_keccak(node->private_key, node->public_key + 1);
|
||||
#endif
|
||||
} else if(node->curve == &curve25519_info) {
|
||||
curve25519_scalarmult_basepoint(node->public_key + 1, node->private_key);
|
||||
#if USE_CARDANO
|
||||
} else if(node->curve == &ed25519_cardano_info) {
|
||||
ed25519_publickey_ext(node->private_key, node->public_key + 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
if(ecdsa_get_public_key33(node->curve->params, node->private_key, node->public_key) != 0) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if USE_ETHEREUM
|
||||
int hdnode_get_ethereum_pubkeyhash(const HDNode* node, uint8_t* pubkeyhash) {
|
||||
uint8_t buf[65] = {0};
|
||||
//SHA3_CTX ctx = {0};
|
||||
SHA3_CTX* ctx = malloc(sizeof(SHA3_CTX));
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
|
||||
/* get uncompressed public key */
|
||||
if(ecdsa_get_public_key65(node->curve->params, node->private_key, buf) != 0) {
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* compute sha3 of x and y coordinate without 04 prefix */
|
||||
sha3_256_Init(ctx);
|
||||
sha3_Update(ctx, buf + 1, 64);
|
||||
keccak_Final(ctx, buf);
|
||||
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
free(ctx);
|
||||
|
||||
/* result are the least significant 160 bits */
|
||||
memcpy(pubkeyhash, buf + 12, 20);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_NEM
|
||||
int hdnode_get_nem_address(HDNode* node, uint8_t version, char* address) {
|
||||
if(node->curve != &ed25519_keccak_info) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(hdnode_fill_public_key(node) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nem_get_address(&node->public_key[1], version, address);
|
||||
}
|
||||
|
||||
int hdnode_get_nem_shared_key(
|
||||
const HDNode* node,
|
||||
const ed25519_public_key peer_public_key,
|
||||
const uint8_t* salt,
|
||||
ed25519_public_key mul,
|
||||
uint8_t* shared_key) {
|
||||
if(node->curve != &ed25519_keccak_info) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sizeof(ed25519_public_key) == SHA3_256_DIGEST_LENGTH
|
||||
if(mul == NULL) mul = shared_key;
|
||||
|
||||
if(ed25519_scalarmult_keccak(mul, node->private_key, peer_public_key)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 32; i++) {
|
||||
shared_key[i] = mul[i] ^ salt[i];
|
||||
}
|
||||
|
||||
keccak_256(shared_key, 32, shared_key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_nem_encrypt(
|
||||
const HDNode* node,
|
||||
const ed25519_public_key public_key,
|
||||
const uint8_t* iv_immut,
|
||||
const uint8_t* salt,
|
||||
const uint8_t* payload,
|
||||
size_t size,
|
||||
uint8_t* buffer) {
|
||||
uint8_t last_block[AES_BLOCK_SIZE] = {0};
|
||||
uint8_t remainder = size % AES_BLOCK_SIZE;
|
||||
|
||||
// Round down to last whole block
|
||||
size -= remainder;
|
||||
// Copy old last block
|
||||
memcpy(last_block, &payload[size], remainder);
|
||||
// Pad new last block with number of missing bytes
|
||||
memset(&last_block[remainder], AES_BLOCK_SIZE - remainder, AES_BLOCK_SIZE - remainder);
|
||||
|
||||
// the IV gets mutated, so we make a copy not to touch the original
|
||||
uint8_t iv[AES_BLOCK_SIZE] = {0};
|
||||
memcpy(iv, iv_immut, AES_BLOCK_SIZE);
|
||||
|
||||
uint8_t shared_key[SHA3_256_DIGEST_LENGTH] = {0};
|
||||
if(!hdnode_get_nem_shared_key(node, public_key, salt, NULL, shared_key)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aes_encrypt_ctx ctx = {0};
|
||||
|
||||
int ret = aes_encrypt_key256(shared_key, &ctx);
|
||||
memzero(shared_key, sizeof(shared_key));
|
||||
|
||||
if(ret != EXIT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(aes_cbc_encrypt(payload, buffer, size, iv, &ctx) != EXIT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(aes_cbc_encrypt(last_block, &buffer[size], sizeof(last_block), iv, &ctx) != EXIT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_nem_decrypt(
|
||||
const HDNode* node,
|
||||
const ed25519_public_key public_key,
|
||||
uint8_t* iv,
|
||||
const uint8_t* salt,
|
||||
const uint8_t* payload,
|
||||
size_t size,
|
||||
uint8_t* buffer) {
|
||||
uint8_t shared_key[SHA3_256_DIGEST_LENGTH] = {0};
|
||||
|
||||
if(!hdnode_get_nem_shared_key(node, public_key, salt, NULL, shared_key)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aes_decrypt_ctx ctx = {0};
|
||||
|
||||
int ret = aes_decrypt_key256(shared_key, &ctx);
|
||||
memzero(shared_key, sizeof(shared_key));
|
||||
|
||||
if(ret != EXIT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(aes_cbc_decrypt(payload, buffer, size, iv, &ctx) != EXIT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// msg is a data to be signed
|
||||
// msg_len is the message length
|
||||
int hdnode_sign(
|
||||
HDNode* node,
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
HasherType hasher_sign,
|
||||
uint8_t* sig,
|
||||
uint8_t* pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64])) {
|
||||
if(node->curve->params) {
|
||||
return ecdsa_sign(
|
||||
node->curve->params,
|
||||
hasher_sign,
|
||||
node->private_key,
|
||||
msg,
|
||||
msg_len,
|
||||
sig,
|
||||
pby,
|
||||
is_canonical);
|
||||
} else if(node->curve == &curve25519_info) {
|
||||
return 1; // signatures are not supported
|
||||
} else {
|
||||
if(node->curve == &ed25519_info) {
|
||||
ed25519_sign(msg, msg_len, node->private_key, sig);
|
||||
} else if(node->curve == &ed25519_sha3_info) {
|
||||
ed25519_sign_sha3(msg, msg_len, node->private_key, sig);
|
||||
#if USE_KECCAK
|
||||
} else if(node->curve == &ed25519_keccak_info) {
|
||||
ed25519_sign_keccak(msg, msg_len, node->private_key, sig);
|
||||
#endif
|
||||
} else {
|
||||
return 1; // unknown or unsupported curve
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int hdnode_sign_digest(
|
||||
HDNode* node,
|
||||
const uint8_t* digest,
|
||||
uint8_t* sig,
|
||||
uint8_t* pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64])) {
|
||||
if(node->curve->params) {
|
||||
return ecdsa_sign_digest(
|
||||
node->curve->params, node->private_key, digest, sig, pby, is_canonical);
|
||||
} else if(node->curve == &curve25519_info) {
|
||||
return 1; // signatures are not supported
|
||||
} else {
|
||||
return hdnode_sign(node, digest, 32, 0, sig, pby, is_canonical);
|
||||
}
|
||||
}
|
||||
|
||||
int hdnode_get_shared_key(
|
||||
const HDNode* node,
|
||||
const uint8_t* peer_public_key,
|
||||
uint8_t* session_key,
|
||||
int* result_size) {
|
||||
// Use elliptic curve Diffie-Helman to compute shared session key
|
||||
if(node->curve->params) {
|
||||
if(ecdh_multiply(node->curve->params, node->private_key, peer_public_key, session_key) !=
|
||||
0) {
|
||||
return 1;
|
||||
}
|
||||
*result_size = 65;
|
||||
return 0;
|
||||
} else if(node->curve == &curve25519_info) {
|
||||
session_key[0] = 0x04;
|
||||
if(peer_public_key[0] != 0x40) {
|
||||
return 1; // Curve25519 public key should start with 0x40 byte.
|
||||
}
|
||||
curve25519_scalarmult(session_key + 1, node->private_key, peer_public_key + 1);
|
||||
*result_size = 33;
|
||||
return 0;
|
||||
} else {
|
||||
*result_size = 0;
|
||||
return 1; // ECDH is not supported
|
||||
}
|
||||
}
|
||||
|
||||
static int hdnode_serialize(
|
||||
const HDNode* node,
|
||||
uint32_t fingerprint,
|
||||
uint32_t version,
|
||||
bool use_private,
|
||||
char* str,
|
||||
int strsize) {
|
||||
uint8_t node_data[78] = {0};
|
||||
write_be(node_data, version);
|
||||
node_data[4] = node->depth;
|
||||
write_be(node_data + 5, fingerprint);
|
||||
write_be(node_data + 9, node->child_num);
|
||||
memcpy(node_data + 13, node->chain_code, 32);
|
||||
if(use_private) {
|
||||
node_data[45] = 0;
|
||||
memcpy(node_data + 46, node->private_key, 32);
|
||||
} else {
|
||||
memcpy(node_data + 45, node->public_key, 33);
|
||||
}
|
||||
int ret = base58_encode_check(
|
||||
node_data, sizeof(node_data), node->curve->hasher_base58, str, strsize);
|
||||
memzero(node_data, sizeof(node_data));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hdnode_serialize_public(
|
||||
const HDNode* node,
|
||||
uint32_t fingerprint,
|
||||
uint32_t version,
|
||||
char* str,
|
||||
int strsize) {
|
||||
return hdnode_serialize(node, fingerprint, version, false, str, strsize);
|
||||
}
|
||||
|
||||
int hdnode_serialize_private(
|
||||
const HDNode* node,
|
||||
uint32_t fingerprint,
|
||||
uint32_t version,
|
||||
char* str,
|
||||
int strsize) {
|
||||
return hdnode_serialize(node, fingerprint, version, true, str, strsize);
|
||||
}
|
||||
|
||||
// check for validity of curve point in case of public data not performed
|
||||
static int hdnode_deserialize(
|
||||
const char* str,
|
||||
uint32_t version,
|
||||
bool use_private,
|
||||
const char* curve,
|
||||
HDNode* node,
|
||||
uint32_t* fingerprint) {
|
||||
uint8_t node_data[78] = {0};
|
||||
memzero(node, sizeof(HDNode));
|
||||
node->curve = get_curve_by_name(curve);
|
||||
if(base58_decode_check(str, node->curve->hasher_base58, node_data, sizeof(node_data)) !=
|
||||
sizeof(node_data)) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t ver = read_be(node_data);
|
||||
if(ver != version) {
|
||||
return -3; // invalid version
|
||||
}
|
||||
if(use_private) {
|
||||
// invalid data
|
||||
if(node_data[45]) {
|
||||
return -2;
|
||||
}
|
||||
memcpy(node->private_key, node_data + 46, 32);
|
||||
memzero(node->public_key, sizeof(node->public_key));
|
||||
} else {
|
||||
memzero(node->private_key, sizeof(node->private_key));
|
||||
memcpy(node->public_key, node_data + 45, 33);
|
||||
}
|
||||
node->depth = node_data[4];
|
||||
if(fingerprint) {
|
||||
*fingerprint = read_be(node_data + 5);
|
||||
}
|
||||
node->child_num = read_be(node_data + 9);
|
||||
memcpy(node->chain_code, node_data + 13, 32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdnode_deserialize_public(
|
||||
const char* str,
|
||||
uint32_t version,
|
||||
const char* curve,
|
||||
HDNode* node,
|
||||
uint32_t* fingerprint) {
|
||||
return hdnode_deserialize(str, version, false, curve, node, fingerprint);
|
||||
}
|
||||
|
||||
int hdnode_deserialize_private(
|
||||
const char* str,
|
||||
uint32_t version,
|
||||
const char* curve,
|
||||
HDNode* node,
|
||||
uint32_t* fingerprint) {
|
||||
return hdnode_deserialize(str, version, true, curve, node, fingerprint);
|
||||
}
|
||||
|
||||
const curve_info* get_curve_by_name(const char* curve_name) {
|
||||
if(curve_name == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(strcmp(curve_name, SECP256K1_NAME) == 0) {
|
||||
return &secp256k1_info;
|
||||
}
|
||||
if(strcmp(curve_name, SECP256K1_DECRED_NAME) == 0) {
|
||||
return &secp256k1_decred_info;
|
||||
}
|
||||
if(strcmp(curve_name, SECP256K1_GROESTL_NAME) == 0) {
|
||||
return &secp256k1_groestl_info;
|
||||
}
|
||||
if(strcmp(curve_name, SECP256K1_SMART_NAME) == 0) {
|
||||
return &secp256k1_smart_info;
|
||||
}
|
||||
if(strcmp(curve_name, NIST256P1_NAME) == 0) {
|
||||
return &nist256p1_info;
|
||||
}
|
||||
if(strcmp(curve_name, ED25519_NAME) == 0) {
|
||||
return &ed25519_info;
|
||||
}
|
||||
#if USE_CARDANO
|
||||
if(strcmp(curve_name, ED25519_CARDANO_NAME) == 0) {
|
||||
return &ed25519_cardano_info;
|
||||
}
|
||||
#endif
|
||||
if(strcmp(curve_name, ED25519_SHA3_NAME) == 0) {
|
||||
return &ed25519_sha3_info;
|
||||
}
|
||||
#if USE_KECCAK
|
||||
if(strcmp(curve_name, ED25519_KECCAK_NAME) == 0) {
|
||||
return &ed25519_keccak_info;
|
||||
}
|
||||
#endif
|
||||
if(strcmp(curve_name, CURVE25519_NAME) == 0) {
|
||||
return &curve25519_info;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
202
applications/external/flipbip/lib/crypto/bip32.h
vendored
202
applications/external/flipbip/lib/crypto/bip32.h
vendored
@@ -1,202 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BIP32_H__
|
||||
#define __BIP32_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "ecdsa.h"
|
||||
#include "ed25519_donna/ed25519.h"
|
||||
#include "options.h"
|
||||
|
||||
// Maximum length of a Base58Check-encoded extended public or private key.
|
||||
#define XPUB_MAXLEN 112
|
||||
|
||||
// Maximum length of a Base58Check-encoded address.
|
||||
#define ADDRESS_MAXLEN 39
|
||||
|
||||
typedef struct {
|
||||
const char* bip32_name; // string for generating BIP32 xprv from seed
|
||||
const ecdsa_curve* params; // ecdsa curve parameters, null for ed25519
|
||||
|
||||
HasherType hasher_base58;
|
||||
HasherType hasher_sign;
|
||||
HasherType hasher_pubkey;
|
||||
HasherType hasher_script;
|
||||
} curve_info;
|
||||
|
||||
typedef struct {
|
||||
uint32_t depth;
|
||||
uint32_t child_num;
|
||||
uint8_t chain_code[32];
|
||||
|
||||
uint8_t private_key[32];
|
||||
uint8_t private_key_extension[32];
|
||||
|
||||
uint8_t public_key[33];
|
||||
const curve_info* curve;
|
||||
} HDNode;
|
||||
|
||||
int hdnode_from_xpub(
|
||||
uint32_t depth,
|
||||
uint32_t child_num,
|
||||
const uint8_t* chain_code,
|
||||
const uint8_t* public_key,
|
||||
const char* curve,
|
||||
HDNode* out);
|
||||
|
||||
int hdnode_from_xprv(
|
||||
uint32_t depth,
|
||||
uint32_t child_num,
|
||||
const uint8_t* chain_code,
|
||||
const uint8_t* private_key,
|
||||
const char* curve,
|
||||
HDNode* out);
|
||||
|
||||
int hdnode_from_seed(const uint8_t* seed, int seed_len, const char* curve, HDNode* out);
|
||||
|
||||
#define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000))
|
||||
|
||||
int hdnode_private_ckd(HDNode* inout, uint32_t i);
|
||||
|
||||
int hdnode_public_ckd_cp(
|
||||
const ecdsa_curve* curve,
|
||||
const curve_point* parent,
|
||||
const uint8_t* parent_chain_code,
|
||||
uint32_t i,
|
||||
curve_point* child,
|
||||
uint8_t* child_chain_code);
|
||||
|
||||
int hdnode_public_ckd(HDNode* inout, uint32_t i);
|
||||
|
||||
void hdnode_public_ckd_address_optimized(
|
||||
const curve_point* pub,
|
||||
const uint8_t* chain_code,
|
||||
uint32_t i,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
HasherType hasher_base58,
|
||||
char* addr,
|
||||
int addrsize,
|
||||
int addrformat);
|
||||
|
||||
#if USE_BIP32_CACHE
|
||||
void bip32_cache_clear(void);
|
||||
int hdnode_private_ckd_cached(
|
||||
HDNode* inout,
|
||||
const uint32_t* i,
|
||||
size_t i_count,
|
||||
uint32_t* fingerprint);
|
||||
#endif
|
||||
|
||||
uint32_t hdnode_fingerprint(HDNode* node);
|
||||
|
||||
int hdnode_fill_public_key(HDNode* node);
|
||||
|
||||
#if USE_ETHEREUM
|
||||
int hdnode_get_ethereum_pubkeyhash(const HDNode* node, uint8_t* pubkeyhash);
|
||||
#endif
|
||||
|
||||
#if USE_NEM
|
||||
int hdnode_get_nem_address(HDNode* node, uint8_t version, char* address);
|
||||
int hdnode_get_nem_shared_key(
|
||||
const HDNode* node,
|
||||
const ed25519_public_key peer_public_key,
|
||||
const uint8_t* salt,
|
||||
ed25519_public_key mul,
|
||||
uint8_t* shared_key);
|
||||
int hdnode_nem_encrypt(
|
||||
const HDNode* node,
|
||||
const ed25519_public_key public_key,
|
||||
const uint8_t* iv,
|
||||
const uint8_t* salt,
|
||||
const uint8_t* payload,
|
||||
size_t size,
|
||||
uint8_t* buffer);
|
||||
int hdnode_nem_decrypt(
|
||||
const HDNode* node,
|
||||
const ed25519_public_key public_key,
|
||||
uint8_t* iv,
|
||||
const uint8_t* salt,
|
||||
const uint8_t* payload,
|
||||
size_t size,
|
||||
uint8_t* buffer);
|
||||
#endif
|
||||
|
||||
int hdnode_sign(
|
||||
HDNode* node,
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
HasherType hasher_sign,
|
||||
uint8_t* sig,
|
||||
uint8_t* pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int hdnode_sign_digest(
|
||||
HDNode* node,
|
||||
const uint8_t* digest,
|
||||
uint8_t* sig,
|
||||
uint8_t* pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
|
||||
int hdnode_get_shared_key(
|
||||
const HDNode* node,
|
||||
const uint8_t* peer_public_key,
|
||||
uint8_t* session_key,
|
||||
int* result_size);
|
||||
|
||||
int hdnode_serialize_public(
|
||||
const HDNode* node,
|
||||
uint32_t fingerprint,
|
||||
uint32_t version,
|
||||
char* str,
|
||||
int strsize);
|
||||
|
||||
int hdnode_serialize_private(
|
||||
const HDNode* node,
|
||||
uint32_t fingerprint,
|
||||
uint32_t version,
|
||||
char* str,
|
||||
int strsize);
|
||||
|
||||
int hdnode_deserialize_public(
|
||||
const char* str,
|
||||
uint32_t version,
|
||||
const char* curve,
|
||||
HDNode* node,
|
||||
uint32_t* fingerprint);
|
||||
|
||||
int hdnode_deserialize_private(
|
||||
const char* str,
|
||||
uint32_t version,
|
||||
const char* curve,
|
||||
HDNode* node,
|
||||
uint32_t* fingerprint);
|
||||
|
||||
int hdnode_get_address_raw(HDNode* node, uint32_t version, uint8_t* addr_raw);
|
||||
int hdnode_get_address(HDNode* node, uint32_t version, char* addr, int addrsize);
|
||||
|
||||
const curve_info* get_curve_by_name(const char* curve_name);
|
||||
|
||||
#endif
|
||||
288
applications/external/flipbip/lib/crypto/bip39.c
vendored
288
applications/external/flipbip/lib/crypto/bip39.c
vendored
@@ -1,288 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bip39.h"
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
#include "pbkdf2.h"
|
||||
#include "rand.h"
|
||||
#include "sha2.h"
|
||||
|
||||
#if USE_BIP39_CACHE
|
||||
|
||||
static int bip39_cache_index = 0;
|
||||
|
||||
static CONFIDENTIAL struct {
|
||||
bool set;
|
||||
char mnemonic[256];
|
||||
char passphrase[64];
|
||||
uint8_t seed[512 / 8];
|
||||
} bip39_cache[BIP39_CACHE_SIZE];
|
||||
|
||||
void bip39_cache_clear(void) {
|
||||
memzero(bip39_cache, sizeof(bip39_cache));
|
||||
bip39_cache_index = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char* mnemonic_generate(int strength) {
|
||||
if(strength % 32 || strength < 128 || strength > 256) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t data[32] = {0};
|
||||
random_buffer(data, 32);
|
||||
const char* r = mnemonic_from_data(data, strength / 8);
|
||||
memzero(data, sizeof(data));
|
||||
return r;
|
||||
}
|
||||
|
||||
static CONFIDENTIAL char mnemo[24 * 10];
|
||||
|
||||
const char* mnemonic_from_data(const uint8_t* data, int len) {
|
||||
if(len % 4 || len < 16 || len > 32) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
|
||||
sha256_Raw(data, len, bits);
|
||||
// checksum
|
||||
bits[len] = bits[0];
|
||||
// data
|
||||
memcpy(bits, data, len);
|
||||
|
||||
int mlen = len * 3 / 4;
|
||||
|
||||
int i = 0, j = 0, idx = 0;
|
||||
char* p = mnemo;
|
||||
for(i = 0; i < mlen; i++) {
|
||||
idx = 0;
|
||||
for(j = 0; j < 11; j++) {
|
||||
idx <<= 1;
|
||||
idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;
|
||||
}
|
||||
strcpy(p, BIP39_WORDLIST_ENGLISH[idx]);
|
||||
p += strlen(BIP39_WORDLIST_ENGLISH[idx]);
|
||||
*p = (i < mlen - 1) ? ' ' : 0;
|
||||
p++;
|
||||
}
|
||||
memzero(bits, sizeof(bits));
|
||||
|
||||
return mnemo;
|
||||
}
|
||||
|
||||
void mnemonic_clear(void) {
|
||||
memzero(mnemo, sizeof(mnemo));
|
||||
}
|
||||
|
||||
int mnemonic_to_bits(const char* mnemonic, uint8_t* bits) {
|
||||
if(!mnemonic) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i = 0, n = 0;
|
||||
|
||||
while(mnemonic[i]) {
|
||||
if(mnemonic[i] == ' ') {
|
||||
n++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
n++;
|
||||
|
||||
// check that number of words is valid for BIP-39:
|
||||
// (a) between 128 and 256 bits of initial entropy (12 - 24 words)
|
||||
// (b) number of bits divisible by 33 (1 checksum bit per 32 input bits)
|
||||
// - that is, (n * 11) % 33 == 0, so n % 3 == 0
|
||||
if(n < 12 || n > 24 || (n % 3)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char current_word[10] = {0};
|
||||
uint32_t j = 0, ki = 0, bi = 0;
|
||||
uint8_t result[32 + 1] = {0};
|
||||
|
||||
memzero(result, sizeof(result));
|
||||
i = 0;
|
||||
while(mnemonic[i]) {
|
||||
j = 0;
|
||||
while(mnemonic[i] != ' ' && mnemonic[i] != 0) {
|
||||
if(j >= sizeof(current_word) - 1) {
|
||||
return 0;
|
||||
}
|
||||
current_word[j] = mnemonic[i];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
current_word[j] = 0;
|
||||
if(mnemonic[i] != 0) {
|
||||
i++;
|
||||
}
|
||||
int k = mnemonic_find_word(current_word);
|
||||
if(k < 0) { // word not found
|
||||
return 0;
|
||||
}
|
||||
for(ki = 0; ki < 11; ki++) {
|
||||
if(k & (1 << (10 - ki))) {
|
||||
result[bi / 8] |= 1 << (7 - (bi % 8));
|
||||
}
|
||||
bi++;
|
||||
}
|
||||
}
|
||||
if(bi != n * 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(bits, result, sizeof(result));
|
||||
memzero(result, sizeof(result));
|
||||
|
||||
// returns amount of entropy + checksum BITS
|
||||
return n * 11;
|
||||
}
|
||||
|
||||
int mnemonic_check(const char* mnemonic) {
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
int mnemonic_bits_len = mnemonic_to_bits(mnemonic, bits);
|
||||
if(mnemonic_bits_len != (12 * 11) && mnemonic_bits_len != (18 * 11) &&
|
||||
mnemonic_bits_len != (24 * 11)) {
|
||||
return 0;
|
||||
}
|
||||
int words = mnemonic_bits_len / 11;
|
||||
|
||||
uint8_t checksum = bits[words * 4 / 3];
|
||||
sha256_Raw(bits, words * 4 / 3, bits);
|
||||
if(words == 12) {
|
||||
return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits
|
||||
} else if(words == 18) {
|
||||
return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits
|
||||
} else if(words == 24) {
|
||||
return bits[0] == checksum; // compare 8 bits
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// passphrase must be at most 256 characters otherwise it would be truncated
|
||||
void mnemonic_to_seed(
|
||||
const char* mnemonic,
|
||||
const char* passphrase,
|
||||
uint8_t seed[512 / 8],
|
||||
void (*progress_callback)(uint32_t current, uint32_t total)) {
|
||||
int mnemoniclen = strlen(mnemonic);
|
||||
int passphraselen = strlen(passphrase);
|
||||
if(passphraselen > 256) passphraselen = 256;
|
||||
#if USE_BIP39_CACHE
|
||||
// check cache
|
||||
if(mnemoniclen < 256 && passphraselen < 64) {
|
||||
for(int i = 0; i < BIP39_CACHE_SIZE; i++) {
|
||||
if(!bip39_cache[i].set) continue;
|
||||
if(strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;
|
||||
if(strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;
|
||||
// found the correct entry
|
||||
memcpy(seed, bip39_cache[i].seed, 512 / 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
uint8_t salt[8 + 256] = {0};
|
||||
memcpy(salt, "mnemonic", 8);
|
||||
memcpy(salt + 8, passphrase, passphraselen);
|
||||
static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(
|
||||
&pctx, (const uint8_t*)mnemonic, mnemoniclen, salt, passphraselen + 8, 1);
|
||||
if(progress_callback) {
|
||||
progress_callback(0, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
for(int i = 0; i < 16; i++) {
|
||||
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);
|
||||
if(progress_callback) {
|
||||
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
}
|
||||
pbkdf2_hmac_sha512_Final(&pctx, seed);
|
||||
memzero(salt, sizeof(salt));
|
||||
#if USE_BIP39_CACHE
|
||||
// store to cache
|
||||
if(mnemoniclen < 256 && passphraselen < 64) {
|
||||
bip39_cache[bip39_cache_index].set = true;
|
||||
strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic);
|
||||
strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase);
|
||||
memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8);
|
||||
bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// binary search for finding the word in the wordlist
|
||||
int mnemonic_find_word(const char* word) {
|
||||
int lo = 0, hi = BIP39_WORD_COUNT - 1;
|
||||
while(lo <= hi) {
|
||||
int mid = lo + (hi - lo) / 2;
|
||||
int cmp = strcmp(word, BIP39_WORDLIST_ENGLISH[mid]);
|
||||
if(cmp == 0) {
|
||||
return mid;
|
||||
}
|
||||
if(cmp > 0) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* mnemonic_complete_word(const char* prefix, int len) {
|
||||
// we need to perform linear search,
|
||||
// because we want to return the first match
|
||||
for(int i = 0; i < BIP39_WORD_COUNT; i++) {
|
||||
if(strncmp(BIP39_WORDLIST_ENGLISH[i], prefix, len) == 0) {
|
||||
return BIP39_WORDLIST_ENGLISH[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* mnemonic_get_word(int index) {
|
||||
if(index >= 0 && index < BIP39_WORD_COUNT) {
|
||||
return BIP39_WORDLIST_ENGLISH[index];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mnemonic_word_completion_mask(const char* prefix, int len) {
|
||||
if(len <= 0) {
|
||||
return 0x3ffffff; // all letters (bits 1-26 set)
|
||||
}
|
||||
uint32_t res = 0;
|
||||
for(int i = 0; i < BIP39_WORD_COUNT; i++) {
|
||||
const char* word = BIP39_WORDLIST_ENGLISH[i];
|
||||
if(strncmp(word, prefix, len) == 0 && word[len] >= 'a' && word[len] <= 'z') {
|
||||
res |= 1 << (word[len] - 'a');
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
61
applications/external/flipbip/lib/crypto/bip39.h
vendored
61
applications/external/flipbip/lib/crypto/bip39.h
vendored
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BIP39_H__
|
||||
#define __BIP39_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "options.h"
|
||||
|
||||
#define BIP39_WORD_COUNT 2048
|
||||
#define BIP39_PBKDF2_ROUNDS 2048
|
||||
|
||||
#if USE_BIP39_CACHE
|
||||
void bip39_cache_clear(void);
|
||||
#endif
|
||||
|
||||
extern const char* const BIP39_WORDLIST_ENGLISH[BIP39_WORD_COUNT];
|
||||
|
||||
const char* mnemonic_generate(int strength); // strength in bits
|
||||
const char* mnemonic_from_data(const uint8_t* data, int len);
|
||||
void mnemonic_clear(void);
|
||||
|
||||
int mnemonic_check(const char* mnemonic);
|
||||
|
||||
int mnemonic_to_bits(const char* mnemonic, uint8_t* bits);
|
||||
|
||||
// passphrase must be at most 256 characters otherwise it would be truncated
|
||||
void mnemonic_to_seed(
|
||||
const char* mnemonic,
|
||||
const char* passphrase,
|
||||
uint8_t seed[512 / 8],
|
||||
void (*progress_callback)(uint32_t current, uint32_t total));
|
||||
|
||||
int mnemonic_find_word(const char* word);
|
||||
const char* mnemonic_complete_word(const char* prefix, int len);
|
||||
const char* mnemonic_get_word(int index);
|
||||
uint32_t mnemonic_word_completion_mask(const char* prefix, int len);
|
||||
|
||||
#endif
|
||||
@@ -1,283 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bip39.h"
|
||||
|
||||
const char* const BIP39_WORDLIST_ENGLISH[BIP39_WORD_COUNT] = {
|
||||
"abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract",
|
||||
"absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid",
|
||||
"acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual",
|
||||
"adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance",
|
||||
"advice", "aerobic", "affair", "afford", "afraid", "again", "age", "agent",
|
||||
"agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album",
|
||||
"alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone",
|
||||
"alpha", "already", "also", "alter", "always", "amateur", "amazing", "among",
|
||||
"amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry",
|
||||
"animal", "ankle", "announce", "annual", "another", "answer", "antenna", "antique",
|
||||
"anxiety", "any", "apart", "apology", "appear", "apple", "approve", "april",
|
||||
"arch", "arctic", "area", "arena", "argue", "arm", "armed", "armor",
|
||||
"army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact",
|
||||
"artist", "artwork", "ask", "aspect", "assault", "asset", "assist", "assume",
|
||||
"asthma", "athlete", "atom", "attack", "attend", "attitude", "attract", "auction",
|
||||
"audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado",
|
||||
"avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis",
|
||||
"baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball",
|
||||
"bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base",
|
||||
"basic", "basket", "battle", "beach", "bean", "beauty", "because", "become",
|
||||
"beef", "before", "begin", "behave", "behind", "believe", "below", "belt",
|
||||
"bench", "benefit", "best", "betray", "better", "between", "beyond", "bicycle",
|
||||
"bid", "bike", "bind", "biology", "bird", "birth", "bitter", "black",
|
||||
"blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood",
|
||||
"blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body",
|
||||
"boil", "bomb", "bone", "bonus", "book", "boost", "border", "boring",
|
||||
"borrow", "boss", "bottom", "bounce", "box", "boy", "bracket", "brain",
|
||||
"brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief",
|
||||
"bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother",
|
||||
"brown", "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb",
|
||||
"bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus",
|
||||
"business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable",
|
||||
"cactus", "cage", "cake", "call", "calm", "camera", "camp", "can",
|
||||
"canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable",
|
||||
"capital", "captain", "car", "carbon", "card", "cargo", "carpet", "carry",
|
||||
"cart", "case", "cash", "casino", "castle", "casual", "cat", "catalog",
|
||||
"catch", "category", "cattle", "caught", "cause", "caution", "cave", "ceiling",
|
||||
"celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk",
|
||||
"champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap",
|
||||
"check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child",
|
||||
"chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar",
|
||||
"cinnamon", "circle", "citizen", "city", "civil", "claim", "clap", "clarify",
|
||||
"claw", "clay", "clean", "clerk", "clever", "click", "client", "cliff",
|
||||
"climb", "clinic", "clip", "clock", "clog", "close", "cloth", "cloud",
|
||||
"clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut",
|
||||
"code", "coffee", "coil", "coin", "collect", "color", "column", "combine",
|
||||
"come", "comfort", "comic", "common", "company", "concert", "conduct", "confirm",
|
||||
"congress", "connect", "consider", "control", "convince", "cook", "cool", "copper",
|
||||
"copy", "coral", "core", "corn", "correct", "cost", "cotton", "couch",
|
||||
"country", "couple", "course", "cousin", "cover", "coyote", "crack", "cradle",
|
||||
"craft", "cram", "crane", "crash", "crater", "crawl", "crazy", "cream",
|
||||
"credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop",
|
||||
"cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch",
|
||||
"crush", "cry", "crystal", "cube", "culture", "cup", "cupboard", "curious",
|
||||
"current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad",
|
||||
"damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn",
|
||||
"day", "deal", "debate", "debris", "decade", "december", "decide", "decline",
|
||||
"decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay",
|
||||
"deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend",
|
||||
"deposit", "depth", "deputy", "derive", "describe", "desert", "design", "desk",
|
||||
"despair", "destroy", "detail", "detect", "develop", "device", "devote", "diagram",
|
||||
"dial", "diamond", "diary", "dice", "diesel", "diet", "differ", "digital",
|
||||
"dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree", "discover",
|
||||
"disease", "dish", "dismiss", "disorder", "display", "distance", "divert", "divide",
|
||||
"divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin", "domain",
|
||||
"donate", "donkey", "donor", "door", "dose", "double", "dove", "draft",
|
||||
"dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill",
|
||||
"drink", "drip", "drive", "drop", "drum", "dry", "duck", "dumb",
|
||||
"dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic", "eager",
|
||||
"eagle", "early", "earn", "earth", "easily", "east", "easy", "echo",
|
||||
"ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight",
|
||||
"either", "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator",
|
||||
"elite", "else", "embark", "embody", "embrace", "emerge", "emotion", "employ",
|
||||
"empower", "empty", "enable", "enact", "end", "endless", "endorse", "enemy",
|
||||
"energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough",
|
||||
"enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode",
|
||||
"equal", "equip", "era", "erase", "erode", "erosion", "error", "erupt",
|
||||
"escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil",
|
||||
"evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude",
|
||||
"excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit",
|
||||
"exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend",
|
||||
"extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint",
|
||||
"faith", "fall", "false", "fame", "family", "famous", "fan", "fancy",
|
||||
"fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue", "fault",
|
||||
"favorite", "feature", "february", "federal", "fee", "feed", "feel", "female",
|
||||
"fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field",
|
||||
"figure", "file", "film", "filter", "final", "find", "fine", "finger",
|
||||
"finish", "fire", "firm", "first", "fiscal", "fish", "fit", "fitness",
|
||||
"fix", "flag", "flame", "flash", "flat", "flavor", "flee", "flight",
|
||||
"flip", "float", "flock", "floor", "flower", "fluid", "flush", "fly",
|
||||
"foam", "focus", "fog", "foil", "fold", "follow", "food", "foot",
|
||||
"force", "forest", "forget", "fork", "fortune", "forum", "forward", "fossil",
|
||||
"foster", "found", "fox", "fragile", "frame", "frequent", "fresh", "friend",
|
||||
"fringe", "frog", "front", "frost", "frown", "frozen", "fruit", "fuel",
|
||||
"fun", "funny", "furnace", "fury", "future", "gadget", "gain", "galaxy",
|
||||
"gallery", "game", "gap", "garage", "garbage", "garden", "garlic", "garment",
|
||||
"gas", "gasp", "gate", "gather", "gauge", "gaze", "general", "genius",
|
||||
"genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift", "giggle",
|
||||
"ginger", "giraffe", "girl", "give", "glad", "glance", "glare", "glass",
|
||||
"glide", "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue",
|
||||
"goat", "goddess", "gold", "good", "goose", "gorilla", "gospel", "gossip",
|
||||
"govern", "gown", "grab", "grace", "grain", "grant", "grape", "grass",
|
||||
"gravity", "great", "green", "grid", "grief", "grit", "grocery", "group",
|
||||
"grow", "grunt", "guard", "guess", "guide", "guilt", "guitar", "gun",
|
||||
"gym", "habit", "hair", "half", "hammer", "hamster", "hand", "happy",
|
||||
"harbor", "hard", "harsh", "harvest", "hat", "have", "hawk", "hazard",
|
||||
"head", "health", "heart", "heavy", "hedgehog", "height", "hello", "helmet",
|
||||
"help", "hen", "hero", "hidden", "high", "hill", "hint", "hip",
|
||||
"hire", "history", "hobby", "hockey", "hold", "hole", "holiday", "hollow",
|
||||
"home", "honey", "hood", "hope", "horn", "horror", "horse", "hospital",
|
||||
"host", "hotel", "hour", "hover", "hub", "huge", "human", "humble",
|
||||
"humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt", "husband",
|
||||
"hybrid", "ice", "icon", "idea", "identify", "idle", "ignore", "ill",
|
||||
"illegal", "illness", "image", "imitate", "immense", "immune", "impact", "impose",
|
||||
"improve", "impulse", "inch", "include", "income", "increase", "index", "indicate",
|
||||
"indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit", "initial",
|
||||
"inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane",
|
||||
"insect", "inside", "inspire", "install", "intact", "interest", "into", "invest",
|
||||
"invite", "involve", "iron", "island", "isolate", "issue", "item", "ivory",
|
||||
"jacket", "jaguar", "jar", "jazz", "jealous", "jeans", "jelly", "jewel",
|
||||
"job", "join", "joke", "journey", "joy", "judge", "juice", "jump",
|
||||
"jungle", "junior", "junk", "just", "kangaroo", "keen", "keep", "ketchup",
|
||||
"key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit",
|
||||
"kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock", "know",
|
||||
"lab", "label", "labor", "ladder", "lady", "lake", "lamp", "language",
|
||||
"laptop", "large", "later", "latin", "laugh", "laundry", "lava", "law",
|
||||
"lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn", "leave",
|
||||
"lecture", "left", "leg", "legal", "legend", "leisure", "lemon", "lend",
|
||||
"length", "lens", "leopard", "lesson", "letter", "level", "liar", "liberty",
|
||||
"library", "license", "life", "lift", "light", "like", "limb", "limit",
|
||||
"link", "lion", "liquid", "list", "little", "live", "lizard", "load",
|
||||
"loan", "lobster", "local", "lock", "logic", "lonely", "long", "loop",
|
||||
"lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage", "lumber",
|
||||
"lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet",
|
||||
"maid", "mail", "main", "major", "make", "mammal", "man", "manage",
|
||||
"mandate", "mango", "mansion", "manual", "maple", "marble", "march", "margin",
|
||||
"marine", "market", "marriage", "mask", "mass", "master", "match", "material",
|
||||
"math", "matrix", "matter", "maximum", "maze", "meadow", "mean", "measure",
|
||||
"meat", "mechanic", "medal", "media", "melody", "melt", "member", "memory",
|
||||
"mention", "menu", "mercy", "merge", "merit", "merry", "mesh", "message",
|
||||
"metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind",
|
||||
"minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake",
|
||||
"mix", "mixed", "mixture", "mobile", "model", "modify", "mom", "moment",
|
||||
"monitor", "monkey", "monster", "month", "moon", "moral", "more", "morning",
|
||||
"mosquito", "mother", "motion", "motor", "mountain", "mouse", "move", "movie",
|
||||
"much", "muffin", "mule", "multiply", "muscle", "museum", "mushroom", "music",
|
||||
"must", "mutual", "myself", "mystery", "myth", "naive", "name", "napkin",
|
||||
"narrow", "nasty", "nation", "nature", "near", "neck", "need", "negative",
|
||||
"neglect", "neither", "nephew", "nerve", "nest", "net", "network", "neutral",
|
||||
"never", "news", "next", "nice", "night", "noble", "noise", "nominee",
|
||||
"noodle", "normal", "north", "nose", "notable", "note", "nothing", "notice",
|
||||
"novel", "now", "nuclear", "number", "nurse", "nut", "oak", "obey",
|
||||
"object", "oblige", "obscure", "observe", "obtain", "obvious", "occur", "ocean",
|
||||
"october", "odor", "off", "offer", "office", "often", "oil", "okay",
|
||||
"old", "olive", "olympic", "omit", "once", "one", "onion", "online",
|
||||
"only", "open", "opera", "opinion", "oppose", "option", "orange", "orbit",
|
||||
"orchard", "order", "ordinary", "organ", "orient", "original", "orphan", "ostrich",
|
||||
"other", "outdoor", "outer", "output", "outside", "oval", "oven", "over",
|
||||
"own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle", "page",
|
||||
"pair", "palace", "palm", "panda", "panel", "panic", "panther", "paper",
|
||||
"parade", "parent", "park", "parrot", "party", "pass", "patch", "path",
|
||||
"patient", "patrol", "pattern", "pause", "pave", "payment", "peace", "peanut",
|
||||
"pear", "peasant", "pelican", "pen", "penalty", "pencil", "people", "pepper",
|
||||
"perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical",
|
||||
"piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot",
|
||||
"pink", "pioneer", "pipe", "pistol", "pitch", "pizza", "place", "planet",
|
||||
"plastic", "plate", "play", "please", "pledge", "pluck", "plug", "plunge",
|
||||
"poem", "poet", "point", "polar", "pole", "police", "pond", "pony",
|
||||
"pool", "popular", "portion", "position", "possible", "post", "potato", "pottery",
|
||||
"poverty", "powder", "power", "practice", "praise", "predict", "prefer", "prepare",
|
||||
"present", "pretty", "prevent", "price", "pride", "primary", "print", "priority",
|
||||
"prison", "private", "prize", "problem", "process", "produce", "profit", "program",
|
||||
"project", "promote", "proof", "property", "prosper", "protect", "proud", "provide",
|
||||
"public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch", "pupil",
|
||||
"puppy", "purchase", "purity", "purpose", "purse", "push", "put", "puzzle",
|
||||
"pyramid", "quality", "quantum", "quarter", "question", "quick", "quit", "quiz",
|
||||
"quote", "rabbit", "raccoon", "race", "rack", "radar", "radio", "rail",
|
||||
"rain", "raise", "rally", "ramp", "ranch", "random", "range", "rapid",
|
||||
"rare", "rate", "rather", "raven", "raw", "razor", "ready", "real",
|
||||
"reason", "rebel", "rebuild", "recall", "receive", "recipe", "record", "recycle",
|
||||
"reduce", "reflect", "reform", "refuse", "region", "regret", "regular", "reject",
|
||||
"relax", "release", "relief", "rely", "remain", "remember", "remind", "remove",
|
||||
"render", "renew", "rent", "reopen", "repair", "repeat", "replace", "report",
|
||||
"require", "rescue", "resemble", "resist", "resource", "response", "result", "retire",
|
||||
"retreat", "return", "reunion", "reveal", "review", "reward", "rhythm", "rib",
|
||||
"ribbon", "rice", "rich", "ride", "ridge", "rifle", "right", "rigid",
|
||||
"ring", "riot", "ripple", "risk", "ritual", "rival", "river", "road",
|
||||
"roast", "robot", "robust", "rocket", "romance", "roof", "rookie", "room",
|
||||
"rose", "rotate", "rough", "round", "route", "royal", "rubber", "rude",
|
||||
"rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness",
|
||||
"safe", "sail", "salad", "salmon", "salon", "salt", "salute", "same",
|
||||
"sample", "sand", "satisfy", "satoshi", "sauce", "sausage", "save", "say",
|
||||
"scale", "scan", "scare", "scatter", "scene", "scheme", "school", "science",
|
||||
"scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub", "sea",
|
||||
"search", "season", "seat", "second", "secret", "section", "security", "seed",
|
||||
"seek", "segment", "select", "sell", "seminar", "senior", "sense", "sentence",
|
||||
"series", "service", "session", "settle", "setup", "seven", "shadow", "shaft",
|
||||
"shallow", "share", "shed", "shell", "sheriff", "shield", "shift", "shine",
|
||||
"ship", "shiver", "shock", "shoe", "shoot", "shop", "short", "shoulder",
|
||||
"shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick", "side",
|
||||
"siege", "sight", "sign", "silent", "silk", "silly", "silver", "similar",
|
||||
"simple", "since", "sing", "siren", "sister", "situate", "six", "size",
|
||||
"skate", "sketch", "ski", "skill", "skin", "skirt", "skull", "slab",
|
||||
"slam", "sleep", "slender", "slice", "slide", "slight", "slim", "slogan",
|
||||
"slot", "slow", "slush", "small", "smart", "smile", "smoke", "smooth",
|
||||
"snack", "snake", "snap", "sniff", "snow", "soap", "soccer", "social",
|
||||
"sock", "soda", "soft", "solar", "soldier", "solid", "solution", "solve",
|
||||
"someone", "song", "soon", "sorry", "sort", "soul", "sound", "soup",
|
||||
"source", "south", "space", "spare", "spatial", "spawn", "speak", "special",
|
||||
"speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin",
|
||||
"spirit", "split", "spoil", "sponsor", "spoon", "sport", "spot", "spray",
|
||||
"spread", "spring", "spy", "square", "squeeze", "squirrel", "stable", "stadium",
|
||||
"staff", "stage", "stairs", "stamp", "stand", "start", "state", "stay",
|
||||
"steak", "steel", "stem", "step", "stereo", "stick", "still", "sting",
|
||||
"stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street",
|
||||
"strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject",
|
||||
"submit", "subway", "success", "such", "sudden", "suffer", "sugar", "suggest",
|
||||
"suit", "summer", "sun", "sunny", "sunset", "super", "supply", "supreme",
|
||||
"sure", "surface", "surge", "surprise", "surround", "survey", "suspect", "sustain",
|
||||
"swallow", "swamp", "swap", "swarm", "swear", "sweet", "swift", "swim",
|
||||
"swing", "switch", "sword", "symbol", "symptom", "syrup", "system", "table",
|
||||
"tackle", "tag", "tail", "talent", "talk", "tank", "tape", "target",
|
||||
"task", "taste", "tattoo", "taxi", "teach", "team", "tell", "ten",
|
||||
"tenant", "tennis", "tent", "term", "test", "text", "thank", "that",
|
||||
"theme", "then", "theory", "there", "they", "thing", "this", "thought",
|
||||
"three", "thrive", "throw", "thumb", "thunder", "ticket", "tide", "tiger",
|
||||
"tilt", "timber", "time", "tiny", "tip", "tired", "tissue", "title",
|
||||
"toast", "tobacco", "today", "toddler", "toe", "together", "toilet", "token",
|
||||
"tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth", "top",
|
||||
"topic", "topple", "torch", "tornado", "tortoise", "toss", "total", "tourist",
|
||||
"toward", "tower", "town", "toy", "track", "trade", "traffic", "tragic",
|
||||
"train", "transfer", "trap", "trash", "travel", "tray", "treat", "tree",
|
||||
"trend", "trial", "tribe", "trick", "trigger", "trim", "trip", "trophy",
|
||||
"trouble", "truck", "true", "truly", "trumpet", "trust", "truth", "try",
|
||||
"tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn", "turtle",
|
||||
"twelve", "twenty", "twice", "twin", "twist", "two", "type", "typical",
|
||||
"ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under", "undo",
|
||||
"unfair", "unfold", "unhappy", "uniform", "unique", "unit", "universe", "unknown",
|
||||
"unlock", "until", "unusual", "unveil", "update", "upgrade", "uphold", "upon",
|
||||
"upper", "upset", "urban", "urge", "usage", "use", "used", "useful",
|
||||
"useless", "usual", "utility", "vacant", "vacuum", "vague", "valid", "valley",
|
||||
"valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle",
|
||||
"velvet", "vendor", "venture", "venue", "verb", "verify", "version", "very",
|
||||
"vessel", "veteran", "viable", "vibrant", "vicious", "victory", "video", "view",
|
||||
"village", "vintage", "violin", "virtual", "virus", "visa", "visit", "visual",
|
||||
"vital", "vivid", "vocal", "voice", "void", "volcano", "volume", "vote",
|
||||
"voyage", "wage", "wagon", "wait", "walk", "wall", "walnut", "want",
|
||||
"warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave",
|
||||
"way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding",
|
||||
"weekend", "weird", "welcome", "west", "wet", "whale", "what", "wheat",
|
||||
"wheel", "when", "where", "whip", "whisper", "wide", "width", "wife",
|
||||
"wild", "will", "win", "window", "wine", "wing", "wink", "winner",
|
||||
"winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman",
|
||||
"wonder", "wood", "wool", "word", "work", "world", "worry", "worth",
|
||||
"wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard", "year",
|
||||
"yellow", "you", "young", "youth", "zebra", "zero", "zone", "zoo",
|
||||
};
|
||||
222
applications/external/flipbip/lib/crypto/blake256.c
vendored
222
applications/external/flipbip/lib/crypto/blake256.c
vendored
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
BLAKE reference C implementation
|
||||
|
||||
Copyright (c) 2012 Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
|
||||
|
||||
To the extent possible under law, the author(s) have dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide. This software is distributed without any warranty.
|
||||
|
||||
You should have received a copy of the CC0 Public Domain Dedication along with
|
||||
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#include "blake256.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define U8TO32_BIG(p) \
|
||||
(((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | ((uint32_t)((p)[2]) << 8) | \
|
||||
((uint32_t)((p)[3])))
|
||||
|
||||
#define U32TO8_BIG(p, v) \
|
||||
(p)[0] = (uint8_t)((v) >> 24); \
|
||||
(p)[1] = (uint8_t)((v) >> 16); \
|
||||
(p)[2] = (uint8_t)((v) >> 8); \
|
||||
(p)[3] = (uint8_t)((v));
|
||||
|
||||
static const uint8_t sigma[][16] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
|
||||
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
|
||||
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
|
||||
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
|
||||
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9}};
|
||||
|
||||
static const uint32_t u256[16] = {
|
||||
0x243f6a88,
|
||||
0x85a308d3,
|
||||
0x13198a2e,
|
||||
0x03707344,
|
||||
0xa4093822,
|
||||
0x299f31d0,
|
||||
0x082efa98,
|
||||
0xec4e6c89,
|
||||
0x452821e6,
|
||||
0x38d01377,
|
||||
0xbe5466cf,
|
||||
0x34e90c6c,
|
||||
0xc0ac29b7,
|
||||
0xc97c50dd,
|
||||
0x3f84d5b5,
|
||||
0xb5470917};
|
||||
|
||||
static const uint8_t padding[129] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
static void blake256_compress(BLAKE256_CTX* S, const uint8_t* block) {
|
||||
uint32_t v[16] = {0}, m[16] = {0}, i = 0;
|
||||
#define ROT(x, n) (((x) << (32 - n)) | ((x) >> (n)))
|
||||
#define G(a, b, c, d, e) \
|
||||
v[a] += (m[sigma[i][e]] ^ u256[sigma[i][e + 1]]) + v[b]; \
|
||||
v[d] = ROT(v[d] ^ v[a], 16); \
|
||||
v[c] += v[d]; \
|
||||
v[b] = ROT(v[b] ^ v[c], 12); \
|
||||
v[a] += (m[sigma[i][e + 1]] ^ u256[sigma[i][e]]) + v[b]; \
|
||||
v[d] = ROT(v[d] ^ v[a], 8); \
|
||||
v[c] += v[d]; \
|
||||
v[b] = ROT(v[b] ^ v[c], 7);
|
||||
|
||||
for(i = 0; i < 16; ++i) m[i] = U8TO32_BIG(block + i * 4);
|
||||
|
||||
for(i = 0; i < 8; ++i) v[i] = S->h[i];
|
||||
|
||||
v[8] = S->s[0] ^ u256[0];
|
||||
v[9] = S->s[1] ^ u256[1];
|
||||
v[10] = S->s[2] ^ u256[2];
|
||||
v[11] = S->s[3] ^ u256[3];
|
||||
v[12] = u256[4];
|
||||
v[13] = u256[5];
|
||||
v[14] = u256[6];
|
||||
v[15] = u256[7];
|
||||
|
||||
/* don't xor t when the block is only padding */
|
||||
if(!S->nullt) {
|
||||
v[12] ^= S->t[0];
|
||||
v[13] ^= S->t[0];
|
||||
v[14] ^= S->t[1];
|
||||
v[15] ^= S->t[1];
|
||||
}
|
||||
|
||||
for(i = 0; i < 14; ++i) {
|
||||
/* column step */
|
||||
G(0, 4, 8, 12, 0);
|
||||
G(1, 5, 9, 13, 2);
|
||||
G(2, 6, 10, 14, 4);
|
||||
G(3, 7, 11, 15, 6);
|
||||
/* diagonal step */
|
||||
G(0, 5, 10, 15, 8);
|
||||
G(1, 6, 11, 12, 10);
|
||||
G(2, 7, 8, 13, 12);
|
||||
G(3, 4, 9, 14, 14);
|
||||
}
|
||||
|
||||
for(i = 0; i < 16; ++i) S->h[i % 8] ^= v[i];
|
||||
|
||||
for(i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4];
|
||||
}
|
||||
|
||||
void blake256_Init(BLAKE256_CTX* S) {
|
||||
S->h[0] = 0x6a09e667;
|
||||
S->h[1] = 0xbb67ae85;
|
||||
S->h[2] = 0x3c6ef372;
|
||||
S->h[3] = 0xa54ff53a;
|
||||
S->h[4] = 0x510e527f;
|
||||
S->h[5] = 0x9b05688c;
|
||||
S->h[6] = 0x1f83d9ab;
|
||||
S->h[7] = 0x5be0cd19;
|
||||
S->t[0] = S->t[1] = S->buflen = S->nullt = 0;
|
||||
S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0;
|
||||
}
|
||||
|
||||
void blake256_Update(BLAKE256_CTX* S, const uint8_t* in, size_t inlen) {
|
||||
size_t left = S->buflen;
|
||||
size_t fill = 64 - left;
|
||||
|
||||
/* data left and data received fill a block */
|
||||
if(left && (inlen >= fill)) {
|
||||
memcpy((void*)(S->buf + left), (void*)in, fill);
|
||||
S->t[0] += 512;
|
||||
|
||||
if(S->t[0] == 0) S->t[1]++;
|
||||
|
||||
blake256_compress(S, S->buf);
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
/* compress blocks of data received */
|
||||
while(inlen >= 64) {
|
||||
S->t[0] += 512;
|
||||
|
||||
if(S->t[0] == 0) S->t[1]++;
|
||||
|
||||
blake256_compress(S, in);
|
||||
in += 64;
|
||||
inlen -= 64;
|
||||
}
|
||||
|
||||
/* store any data left */
|
||||
if(inlen > 0) {
|
||||
memcpy((void*)(S->buf + left), (void*)in, (size_t)inlen);
|
||||
}
|
||||
S->buflen = left + inlen;
|
||||
}
|
||||
|
||||
void blake256_Final(BLAKE256_CTX* S, uint8_t* out) {
|
||||
uint8_t msglen[8] = {0}, zo = 0x01, oo = 0x81;
|
||||
uint32_t lo = S->t[0] + (S->buflen << 3), hi = S->t[1];
|
||||
|
||||
/* support for hashing more than 2^32 bits */
|
||||
if(lo < (S->buflen << 3)) hi++;
|
||||
|
||||
U32TO8_BIG(msglen + 0, hi);
|
||||
U32TO8_BIG(msglen + 4, lo);
|
||||
|
||||
if(S->buflen == 55) /* one padding byte */
|
||||
{
|
||||
S->t[0] -= 8;
|
||||
blake256_Update(S, &oo, 1);
|
||||
} else {
|
||||
if(S->buflen < 55) /* enough space to fill the block */
|
||||
{
|
||||
if(!S->buflen) S->nullt = 1;
|
||||
|
||||
S->t[0] -= 440 - (S->buflen << 3);
|
||||
blake256_Update(S, padding, 55 - S->buflen);
|
||||
} else /* need 2 compressions */
|
||||
{
|
||||
S->t[0] -= 512 - (S->buflen << 3);
|
||||
blake256_Update(S, padding, 64 - S->buflen);
|
||||
S->t[0] -= 440;
|
||||
blake256_Update(S, padding + 1, 55);
|
||||
S->nullt = 1;
|
||||
}
|
||||
|
||||
blake256_Update(S, &zo, 1);
|
||||
S->t[0] -= 8;
|
||||
}
|
||||
|
||||
S->t[0] -= 64;
|
||||
blake256_Update(S, msglen, 8);
|
||||
U32TO8_BIG(out + 0, S->h[0]);
|
||||
U32TO8_BIG(out + 4, S->h[1]);
|
||||
U32TO8_BIG(out + 8, S->h[2]);
|
||||
U32TO8_BIG(out + 12, S->h[3]);
|
||||
U32TO8_BIG(out + 16, S->h[4]);
|
||||
U32TO8_BIG(out + 20, S->h[5]);
|
||||
U32TO8_BIG(out + 24, S->h[6]);
|
||||
U32TO8_BIG(out + 28, S->h[7]);
|
||||
}
|
||||
|
||||
void blake256(const uint8_t* in, size_t inlen, uint8_t* out) {
|
||||
BLAKE256_CTX S = {0};
|
||||
blake256_Init(&S);
|
||||
blake256_Update(&S, in, inlen);
|
||||
blake256_Final(&S, out);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright (c) 2014-2017, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. 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.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#ifndef __BLAKE256_H__
|
||||
#define __BLAKE256_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define BLAKE256_DIGEST_LENGTH 32
|
||||
#define BLAKE256_BLOCK_LENGTH 64
|
||||
|
||||
typedef struct {
|
||||
uint32_t h[8], s[4], t[2];
|
||||
size_t buflen;
|
||||
uint8_t nullt;
|
||||
uint8_t buf[64];
|
||||
} BLAKE256_CTX;
|
||||
|
||||
void blake256_Init(BLAKE256_CTX*);
|
||||
void blake256_Update(BLAKE256_CTX*, const uint8_t*, size_t);
|
||||
void blake256_Final(BLAKE256_CTX*, uint8_t*);
|
||||
|
||||
void blake256(const uint8_t*, size_t, uint8_t*);
|
||||
|
||||
#endif /* __BLAKE256_H__ */
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
#include "byte_order.h"
|
||||
|
||||
static inline uint32_t load32(const void* src) {
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
REVERSE32(w, w);
|
||||
#endif
|
||||
return w;
|
||||
}
|
||||
|
||||
static inline uint64_t load64(const void* src) {
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
REVERSE64(w, w);
|
||||
#endif
|
||||
return w;
|
||||
}
|
||||
|
||||
static inline void store16(void* dst, uint16_t w) {
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline void store32(void* dst, uint32_t w) {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
REVERSE32(w, w);
|
||||
#endif
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline void store64(void* dst, uint64_t w) {
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
REVERSE64(w, w);
|
||||
#endif
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32(const uint32_t w, const unsigned c) {
|
||||
return (w >> c) | (w << (32 - c));
|
||||
}
|
||||
|
||||
static inline uint64_t rotr64(const uint64_t w, const unsigned c) {
|
||||
return (w >> c) | (w << (64 - c));
|
||||
}
|
||||
313
applications/external/flipbip/lib/crypto/blake2b.c
vendored
313
applications/external/flipbip/lib/crypto/blake2b.c
vendored
@@ -1,313 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "blake2b.h"
|
||||
#include "blake2_common.h"
|
||||
#include "memzero.h"
|
||||
|
||||
typedef struct blake2b_param__ {
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint32_t xof_length; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
} __attribute__((packed)) blake2b_param;
|
||||
|
||||
static const uint64_t blake2b_IV[8] = {
|
||||
0x6a09e667f3bcc908ULL,
|
||||
0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL,
|
||||
0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL,
|
||||
0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL,
|
||||
0x5be0cd19137e2179ULL};
|
||||
|
||||
static const uint8_t blake2b_sigma[12][16] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
|
||||
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
|
||||
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
|
||||
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
|
||||
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3}};
|
||||
|
||||
static void blake2b_set_lastnode(blake2b_state* S) {
|
||||
S->f[1] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2b_is_lastblock(const blake2b_state* S) {
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2b_set_lastblock(blake2b_state* S) {
|
||||
if(S->last_node) blake2b_set_lastnode(S);
|
||||
|
||||
S->f[0] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
static void blake2b_increment_counter(blake2b_state* S, const uint64_t inc) {
|
||||
S->t[0] += inc;
|
||||
S->t[1] += (S->t[0] < inc);
|
||||
}
|
||||
|
||||
static void blake2b_init0(blake2b_state* S) {
|
||||
size_t i = 0;
|
||||
memzero(S, sizeof(blake2b_state));
|
||||
|
||||
for(i = 0; i < 8; ++i) S->h[i] = blake2b_IV[i];
|
||||
}
|
||||
|
||||
/* init xors IV with input parameter block */
|
||||
int blake2b_init_param(blake2b_state* S, const blake2b_param* P) {
|
||||
const uint8_t* p = (const uint8_t*)(P);
|
||||
size_t i = 0;
|
||||
|
||||
blake2b_init0(S);
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for(i = 0; i < 8; ++i) S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sequential blake2b initialization */
|
||||
int blake2b_Init(blake2b_state* S, size_t outlen) {
|
||||
blake2b_param P[1] = {0};
|
||||
|
||||
if((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32(&P->leaf_length, 0);
|
||||
store32(&P->node_offset, 0);
|
||||
store32(&P->xof_length, 0);
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memzero(P->reserved, sizeof(P->reserved));
|
||||
memzero(P->salt, sizeof(P->salt));
|
||||
memzero(P->personal, sizeof(P->personal));
|
||||
return blake2b_init_param(S, P);
|
||||
}
|
||||
|
||||
int blake2b_InitPersonal(
|
||||
blake2b_state* S,
|
||||
size_t outlen,
|
||||
const void* personal,
|
||||
size_t personal_len) {
|
||||
blake2b_param P[1] = {0};
|
||||
|
||||
if((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1;
|
||||
if((!personal) || (personal_len != BLAKE2B_PERSONALBYTES)) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32(&P->leaf_length, 0);
|
||||
store32(&P->node_offset, 0);
|
||||
store32(&P->xof_length, 0);
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memzero(P->reserved, sizeof(P->reserved));
|
||||
memzero(P->salt, sizeof(P->salt));
|
||||
memcpy(P->personal, personal, BLAKE2B_PERSONALBYTES);
|
||||
return blake2b_init_param(S, P);
|
||||
}
|
||||
|
||||
int blake2b_InitKey(blake2b_state* S, size_t outlen, const void* key, size_t keylen) {
|
||||
blake2b_param P[1] = {0};
|
||||
|
||||
if((!outlen) || (outlen > BLAKE2B_OUTBYTES)) return -1;
|
||||
|
||||
if(!key || !keylen || keylen > BLAKE2B_KEYBYTES) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32(&P->leaf_length, 0);
|
||||
store32(&P->node_offset, 0);
|
||||
store32(&P->xof_length, 0);
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
memzero(P->reserved, sizeof(P->reserved));
|
||||
memzero(P->salt, sizeof(P->salt));
|
||||
memzero(P->personal, sizeof(P->personal));
|
||||
|
||||
if(blake2b_init_param(S, P) < 0) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES] = {0};
|
||||
memzero(block, BLAKE2B_BLOCKBYTES);
|
||||
memcpy(block, key, keylen);
|
||||
blake2b_Update(S, block, BLAKE2B_BLOCKBYTES);
|
||||
memzero(block, BLAKE2B_BLOCKBYTES); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r, i, a, b, c, d) \
|
||||
do { \
|
||||
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r, 0, v[0], v[4], v[8], v[12]); \
|
||||
G(r, 1, v[1], v[5], v[9], v[13]); \
|
||||
G(r, 2, v[2], v[6], v[10], v[14]); \
|
||||
G(r, 3, v[3], v[7], v[11], v[15]); \
|
||||
G(r, 4, v[0], v[5], v[10], v[15]); \
|
||||
G(r, 5, v[1], v[6], v[11], v[12]); \
|
||||
G(r, 6, v[2], v[7], v[8], v[13]); \
|
||||
G(r, 7, v[3], v[4], v[9], v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2b_compress(blake2b_state* S, const uint8_t block[BLAKE2B_BLOCKBYTES]) {
|
||||
uint64_t m[16] = {0};
|
||||
uint64_t v[16] = {0};
|
||||
size_t i = 0;
|
||||
|
||||
for(i = 0; i < 16; ++i) {
|
||||
m[i] = load64(block + i * sizeof(m[i]));
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; ++i) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[8] = blake2b_IV[0];
|
||||
v[9] = blake2b_IV[1];
|
||||
v[10] = blake2b_IV[2];
|
||||
v[11] = blake2b_IV[3];
|
||||
v[12] = blake2b_IV[4] ^ S->t[0];
|
||||
v[13] = blake2b_IV[5] ^ S->t[1];
|
||||
v[14] = blake2b_IV[6] ^ S->f[0];
|
||||
v[15] = blake2b_IV[7] ^ S->f[1];
|
||||
|
||||
ROUND(0);
|
||||
ROUND(1);
|
||||
ROUND(2);
|
||||
ROUND(3);
|
||||
ROUND(4);
|
||||
ROUND(5);
|
||||
ROUND(6);
|
||||
ROUND(7);
|
||||
ROUND(8);
|
||||
ROUND(9);
|
||||
ROUND(10);
|
||||
ROUND(11);
|
||||
|
||||
for(i = 0; i < 8; ++i) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2b_Update(blake2b_state* S, const void* pin, size_t inlen) {
|
||||
const unsigned char* in = (const unsigned char*)pin;
|
||||
if(inlen > 0) {
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2B_BLOCKBYTES - left;
|
||||
if(inlen > fill) {
|
||||
S->buflen = 0;
|
||||
memcpy(S->buf + left, in, fill); /* Fill buffer */
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress(S, S->buf); /* Compress */
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
while(inlen > BLAKE2B_BLOCKBYTES) {
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress(S, in);
|
||||
in += BLAKE2B_BLOCKBYTES;
|
||||
inlen -= BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy(S->buf + S->buflen, in, inlen);
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_Final(blake2b_state* S, void* out, size_t outlen) {
|
||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||
size_t i = 0;
|
||||
|
||||
if(out == NULL || outlen < S->outlen) return -1;
|
||||
|
||||
if(blake2b_is_lastblock(S)) return -1;
|
||||
|
||||
blake2b_increment_counter(S, S->buflen);
|
||||
blake2b_set_lastblock(S);
|
||||
memzero(S->buf + S->buflen, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
|
||||
blake2b_compress(S, S->buf);
|
||||
|
||||
for(i = 0; i < 8; ++i) /* Output full hash to temp buffer */
|
||||
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
|
||||
|
||||
memcpy(out, buffer, S->outlen);
|
||||
memzero(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b(const uint8_t* msg, uint32_t msg_len, void* out, size_t outlen) {
|
||||
BLAKE2B_CTX ctx;
|
||||
if(0 != blake2b_Init(&ctx, outlen)) return -1;
|
||||
if(0 != blake2b_Update(&ctx, msg, msg_len)) return -1;
|
||||
if(0 != blake2b_Final(&ctx, out, outlen)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_Key(
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
const void* key,
|
||||
size_t keylen,
|
||||
void* out,
|
||||
size_t outlen) {
|
||||
BLAKE2B_CTX ctx;
|
||||
if(0 != blake2b_InitKey(&ctx, outlen, key, keylen)) return -1;
|
||||
if(0 != blake2b_Update(&ctx, msg, msg_len)) return -1;
|
||||
if(0 != blake2b_Final(&ctx, out, outlen)) return -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifndef __BLAKE2B_H__
|
||||
#define __BLAKE2B_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum blake2b_constant {
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
typedef struct __blake2b_state {
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
#define BLAKE2B_CTX blake2b_state
|
||||
#define BLAKE2B_BLOCK_LENGTH BLAKE2B_BLOCKBYTES
|
||||
#define BLAKE2B_DIGEST_LENGTH BLAKE2B_OUTBYTES
|
||||
#define BLAKE2B_KEY_LENGTH BLAKE2B_KEYBYTES
|
||||
|
||||
int blake2b_Init(blake2b_state* S, size_t outlen);
|
||||
int blake2b_InitKey(blake2b_state* S, size_t outlen, const void* key, size_t keylen);
|
||||
int blake2b_InitPersonal(
|
||||
blake2b_state* S,
|
||||
size_t outlen,
|
||||
const void* personal,
|
||||
size_t personal_len);
|
||||
int blake2b_Update(blake2b_state* S, const void* pin, size_t inlen);
|
||||
int blake2b_Final(blake2b_state* S, void* out, size_t outlen);
|
||||
|
||||
int blake2b(const uint8_t* msg, uint32_t msg_len, void* out, size_t outlen);
|
||||
int blake2b_Key(
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
const void* key,
|
||||
size_t keylen,
|
||||
void* out,
|
||||
size_t outlen);
|
||||
|
||||
#endif
|
||||
310
applications/external/flipbip/lib/crypto/blake2s.c
vendored
310
applications/external/flipbip/lib/crypto/blake2s.c
vendored
@@ -1,310 +0,0 @@
|
||||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "blake2s.h"
|
||||
#include "blake2_common.h"
|
||||
#include "memzero.h"
|
||||
|
||||
typedef struct blake2s_param__ {
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint16_t xof_length; /* 14 */
|
||||
uint8_t node_depth; /* 15 */
|
||||
uint8_t inner_length; /* 16 */
|
||||
/* uint8_t reserved[0]; */
|
||||
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
|
||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
|
||||
} __attribute__((packed)) blake2s_param;
|
||||
|
||||
static const uint32_t blake2s_IV[8] = {
|
||||
0x6A09E667UL,
|
||||
0xBB67AE85UL,
|
||||
0x3C6EF372UL,
|
||||
0xA54FF53AUL,
|
||||
0x510E527FUL,
|
||||
0x9B05688CUL,
|
||||
0x1F83D9ABUL,
|
||||
0x5BE0CD19UL};
|
||||
|
||||
static const uint8_t blake2s_sigma[10][16] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
|
||||
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
|
||||
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
|
||||
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
|
||||
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
|
||||
};
|
||||
|
||||
static void blake2s_set_lastnode(blake2s_state* S) {
|
||||
S->f[1] = (uint32_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2s_is_lastblock(const blake2s_state* S) {
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2s_set_lastblock(blake2s_state* S) {
|
||||
if(S->last_node) blake2s_set_lastnode(S);
|
||||
|
||||
S->f[0] = (uint32_t)-1;
|
||||
}
|
||||
|
||||
static void blake2s_increment_counter(blake2s_state* S, const uint32_t inc) {
|
||||
S->t[0] += inc;
|
||||
S->t[1] += (S->t[0] < inc);
|
||||
}
|
||||
|
||||
static void blake2s_init0(blake2s_state* S) {
|
||||
size_t i = 0;
|
||||
memzero(S, sizeof(blake2s_state));
|
||||
|
||||
for(i = 0; i < 8; ++i) S->h[i] = blake2s_IV[i];
|
||||
}
|
||||
|
||||
/* init2 xors IV with input parameter block */
|
||||
int blake2s_init_param(blake2s_state* S, const blake2s_param* P) {
|
||||
const unsigned char* p = (const unsigned char*)(P);
|
||||
size_t i = 0;
|
||||
|
||||
blake2s_init0(S);
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for(i = 0; i < 8; ++i) S->h[i] ^= load32(&p[i * 4]);
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sequential blake2s initialization */
|
||||
int blake2s_Init(blake2s_state* S, size_t outlen) {
|
||||
blake2s_param P[1] = {0};
|
||||
|
||||
if((!outlen) || (outlen > BLAKE2S_OUTBYTES)) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32(&P->leaf_length, 0);
|
||||
store32(&P->node_offset, 0);
|
||||
store16(&P->xof_length, 0);
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memzero(P->reserved, sizeof(P->reserved) ); */
|
||||
memzero(P->salt, sizeof(P->salt));
|
||||
memzero(P->personal, sizeof(P->personal));
|
||||
return blake2s_init_param(S, P);
|
||||
}
|
||||
|
||||
int blake2s_InitPersonal(
|
||||
blake2s_state* S,
|
||||
size_t outlen,
|
||||
const void* personal,
|
||||
size_t personal_len) {
|
||||
blake2s_param P[1] = {0};
|
||||
|
||||
if((!outlen) || (outlen > BLAKE2S_OUTBYTES)) return -1;
|
||||
if((!personal) || (personal_len != BLAKE2S_PERSONALBYTES)) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32(&P->leaf_length, 0);
|
||||
store32(&P->node_offset, 0);
|
||||
store16(&P->xof_length, 0);
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memzero(P->reserved, sizeof(P->reserved) ); */
|
||||
memzero(P->salt, sizeof(P->salt));
|
||||
memcpy(P->personal, personal, BLAKE2S_PERSONALBYTES);
|
||||
return blake2s_init_param(S, P);
|
||||
}
|
||||
|
||||
int blake2s_InitKey(blake2s_state* S, size_t outlen, const void* key, size_t keylen) {
|
||||
blake2s_param P[1] = {0};
|
||||
|
||||
if((!outlen) || (outlen > BLAKE2S_OUTBYTES)) return -1;
|
||||
|
||||
if(!key || !keylen || keylen > BLAKE2S_KEYBYTES) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32(&P->leaf_length, 0);
|
||||
store32(&P->node_offset, 0);
|
||||
store16(&P->xof_length, 0);
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memzero(P->reserved, sizeof(P->reserved) ); */
|
||||
memzero(P->salt, sizeof(P->salt));
|
||||
memzero(P->personal, sizeof(P->personal));
|
||||
|
||||
if(blake2s_init_param(S, P) < 0) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES] = {0};
|
||||
memzero(block, BLAKE2S_BLOCKBYTES);
|
||||
memcpy(block, key, keylen);
|
||||
blake2s_Update(S, block, BLAKE2S_BLOCKBYTES);
|
||||
memzero(block, BLAKE2S_BLOCKBYTES); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r, i, a, b, c, d) \
|
||||
do { \
|
||||
a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \
|
||||
d = rotr32(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 12); \
|
||||
a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \
|
||||
d = rotr32(d ^ a, 8); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 7); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r, 0, v[0], v[4], v[8], v[12]); \
|
||||
G(r, 1, v[1], v[5], v[9], v[13]); \
|
||||
G(r, 2, v[2], v[6], v[10], v[14]); \
|
||||
G(r, 3, v[3], v[7], v[11], v[15]); \
|
||||
G(r, 4, v[0], v[5], v[10], v[15]); \
|
||||
G(r, 5, v[1], v[6], v[11], v[12]); \
|
||||
G(r, 6, v[2], v[7], v[8], v[13]); \
|
||||
G(r, 7, v[3], v[4], v[9], v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2s_compress(blake2s_state* S, const uint8_t in[BLAKE2S_BLOCKBYTES]) {
|
||||
uint32_t m[16] = {0};
|
||||
uint32_t v[16] = {0};
|
||||
size_t i = 0;
|
||||
|
||||
for(i = 0; i < 16; ++i) {
|
||||
m[i] = load32(in + i * sizeof(m[i]));
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; ++i) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[8] = blake2s_IV[0];
|
||||
v[9] = blake2s_IV[1];
|
||||
v[10] = blake2s_IV[2];
|
||||
v[11] = blake2s_IV[3];
|
||||
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||
|
||||
ROUND(0);
|
||||
ROUND(1);
|
||||
ROUND(2);
|
||||
ROUND(3);
|
||||
ROUND(4);
|
||||
ROUND(5);
|
||||
ROUND(6);
|
||||
ROUND(7);
|
||||
ROUND(8);
|
||||
ROUND(9);
|
||||
|
||||
for(i = 0; i < 8; ++i) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2s_Update(blake2s_state* S, const void* pin, size_t inlen) {
|
||||
const unsigned char* in = (const unsigned char*)pin;
|
||||
if(inlen > 0) {
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2S_BLOCKBYTES - left;
|
||||
if(inlen > fill) {
|
||||
S->buflen = 0;
|
||||
memcpy(S->buf + left, in, fill); /* Fill buffer */
|
||||
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
|
||||
blake2s_compress(S, S->buf); /* Compress */
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
while(inlen > BLAKE2S_BLOCKBYTES) {
|
||||
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
|
||||
blake2s_compress(S, in);
|
||||
in += BLAKE2S_BLOCKBYTES;
|
||||
inlen -= BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy(S->buf + S->buflen, in, inlen);
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s_Final(blake2s_state* S, void* out, size_t outlen) {
|
||||
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
||||
size_t i = 0;
|
||||
|
||||
if(out == NULL || outlen < S->outlen) return -1;
|
||||
|
||||
if(blake2s_is_lastblock(S)) return -1;
|
||||
|
||||
blake2s_increment_counter(S, (uint32_t)S->buflen);
|
||||
blake2s_set_lastblock(S);
|
||||
memzero(S->buf + S->buflen, BLAKE2S_BLOCKBYTES - S->buflen); /* Padding */
|
||||
blake2s_compress(S, S->buf);
|
||||
|
||||
for(i = 0; i < 8; ++i) /* Output full hash to temp buffer */
|
||||
store32(buffer + sizeof(S->h[i]) * i, S->h[i]);
|
||||
|
||||
memcpy(out, buffer, outlen);
|
||||
memzero(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s(const uint8_t* msg, uint32_t msg_len, void* out, size_t outlen) {
|
||||
BLAKE2S_CTX ctx;
|
||||
if(0 != blake2s_Init(&ctx, outlen)) return -1;
|
||||
if(0 != blake2s_Update(&ctx, msg, msg_len)) return -1;
|
||||
if(0 != blake2s_Final(&ctx, out, outlen)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s_Key(
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
const void* key,
|
||||
size_t keylen,
|
||||
void* out,
|
||||
size_t outlen) {
|
||||
BLAKE2S_CTX ctx;
|
||||
if(0 != blake2s_InitKey(&ctx, outlen, key, keylen)) return -1;
|
||||
if(0 != blake2s_Update(&ctx, msg, msg_len)) return -1;
|
||||
if(0 != blake2s_Final(&ctx, out, outlen)) return -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifndef __BLAKE2S_H__
|
||||
#define __BLAKE2S_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum blake2s_constant {
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32,
|
||||
BLAKE2S_KEYBYTES = 32,
|
||||
BLAKE2S_SALTBYTES = 8,
|
||||
BLAKE2S_PERSONALBYTES = 8
|
||||
};
|
||||
|
||||
typedef struct __blake2s_state {
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
uint32_t buflen;
|
||||
uint8_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2s_state;
|
||||
|
||||
#define BLAKE2S_CTX blake2s_state
|
||||
#define BLAKE2S_BLOCK_LENGTH BLAKE2S_BLOCKBYTES
|
||||
#define BLAKE2S_DIGEST_LENGTH BLAKE2S_OUTBYTES
|
||||
#define BLAKE2S_KEY_LENGTH BLAKE2S_KEYBYTES
|
||||
|
||||
int blake2s_Init(blake2s_state* S, size_t outlen);
|
||||
int blake2s_InitKey(blake2s_state* S, size_t outlen, const void* key, size_t keylen);
|
||||
int blake2s_InitPersonal(
|
||||
blake2s_state* S,
|
||||
size_t outlen,
|
||||
const void* personal,
|
||||
size_t personal_len);
|
||||
int blake2s_Update(blake2s_state* S, const void* pin, size_t inlen);
|
||||
int blake2s_Final(blake2s_state* S, void* out, size_t outlen);
|
||||
|
||||
int blake2s(const uint8_t* msg, uint32_t msg_len, void* out, size_t outlen);
|
||||
int blake2s_Key(
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
const void* key,
|
||||
size_t keylen,
|
||||
void* out,
|
||||
size_t outlen);
|
||||
|
||||
#endif
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifndef __BYTE_ORDER_H__
|
||||
#define __BYTE_ORDER_H__
|
||||
|
||||
// FROM sha2.h:
|
||||
/*
|
||||
* BYTE_ORDER NOTE:
|
||||
*
|
||||
* Please make sure that your system defines BYTE_ORDER. If your
|
||||
* architecture is little-endian, make sure it also defines
|
||||
* LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
|
||||
* equivalent.
|
||||
*
|
||||
* If your system does not define the above, then you can do so by
|
||||
* hand like this:
|
||||
*
|
||||
* #define LITTLE_ENDIAN 1234
|
||||
* #define BIG_ENDIAN 4321
|
||||
*
|
||||
* And for little-endian machines, add:
|
||||
*
|
||||
* #define BYTE_ORDER LITTLE_ENDIAN
|
||||
*
|
||||
* Or for big-endian machines:
|
||||
*
|
||||
* #define BYTE_ORDER BIG_ENDIAN
|
||||
*
|
||||
* The FreeBSD machine this was written on defines BYTE_ORDER
|
||||
* appropriately by including <sys/types.h> (which in turn includes
|
||||
* <machine/endian.h> where the appropriate definitions are actually
|
||||
* made).
|
||||
*/
|
||||
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define REVERSE32(w, x) \
|
||||
{ \
|
||||
uint32_t tmp = (w); \
|
||||
tmp = (tmp >> 16) | (tmp << 16); \
|
||||
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
|
||||
}
|
||||
|
||||
#define REVERSE64(w, x) \
|
||||
{ \
|
||||
uint64_t tmp = (w); \
|
||||
tmp = (tmp >> 32) | (tmp << 32); \
|
||||
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
|
||||
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | ((tmp & 0x0000ffff0000ffffULL) << 16); \
|
||||
}
|
||||
|
||||
#endif
|
||||
307
applications/external/flipbip/lib/crypto/cardano.c
vendored
307
applications/external/flipbip/lib/crypto/cardano.c
vendored
@@ -1,307 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2021 SatoshiLabs
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bignum.h"
|
||||
#include "bip32.h"
|
||||
#include "cardano.h"
|
||||
#include "curves.h"
|
||||
#include "hasher.h"
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
#include "pbkdf2.h"
|
||||
#include "sha2.h"
|
||||
|
||||
#if USE_CARDANO
|
||||
|
||||
#define CARDANO_MAX_NODE_DEPTH 1048576
|
||||
|
||||
const curve_info ed25519_cardano_info = {
|
||||
.bip32_name = ED25519_CARDANO_NAME,
|
||||
.params = NULL,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
||||
static void scalar_multiply8(const uint8_t* src, int bytes, uint8_t* dst) {
|
||||
uint8_t prev_acc = 0;
|
||||
for(int i = 0; i < bytes; i++) {
|
||||
dst[i] = (src[i] << 3) + (prev_acc & 0x7);
|
||||
prev_acc = src[i] >> 5;
|
||||
}
|
||||
dst[bytes] = src[bytes - 1] >> 5;
|
||||
}
|
||||
|
||||
static void scalar_add_256bits(const uint8_t* src1, const uint8_t* src2, uint8_t* dst) {
|
||||
uint16_t r = 0;
|
||||
for(int i = 0; i < 32; i++) {
|
||||
r = r + (uint16_t)src1[i] + (uint16_t)src2[i];
|
||||
dst[i] = r & 0xff;
|
||||
r >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void cardano_ed25519_tweak_bits(uint8_t private_key[32]) {
|
||||
private_key[0] &= 0xf8;
|
||||
private_key[31] &= 0x1f;
|
||||
private_key[31] |= 0x40;
|
||||
}
|
||||
|
||||
int hdnode_private_ckd_cardano(HDNode* inout, uint32_t index) {
|
||||
if(inout->curve != &ed25519_cardano_info) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(inout->depth >= CARDANO_MAX_NODE_DEPTH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// checks for hardened/non-hardened derivation, keysize 32 means we are
|
||||
// dealing with public key and thus non-h, keysize 64 is for private key
|
||||
int keysize = 32;
|
||||
if(index & 0x80000000) {
|
||||
keysize = 64;
|
||||
}
|
||||
|
||||
static CONFIDENTIAL uint8_t data[1 + 64 + 4];
|
||||
static CONFIDENTIAL uint8_t z[32 + 32];
|
||||
static CONFIDENTIAL uint8_t priv_key[64];
|
||||
static CONFIDENTIAL uint8_t res_key[64];
|
||||
|
||||
write_le(data + keysize + 1, index);
|
||||
|
||||
memcpy(priv_key, inout->private_key, 32);
|
||||
memcpy(priv_key + 32, inout->private_key_extension, 32);
|
||||
|
||||
if(keysize == 64) { // private derivation
|
||||
data[0] = 0;
|
||||
memcpy(data + 1, inout->private_key, 32);
|
||||
memcpy(data + 1 + 32, inout->private_key_extension, 32);
|
||||
} else { // public derivation
|
||||
if(hdnode_fill_public_key(inout) != 0) {
|
||||
return 0;
|
||||
}
|
||||
data[0] = 2;
|
||||
memcpy(data + 1, inout->public_key + 1, 32);
|
||||
}
|
||||
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX ctx;
|
||||
hmac_sha512_Init(&ctx, inout->chain_code, 32);
|
||||
hmac_sha512_Update(&ctx, data, 1 + keysize + 4);
|
||||
hmac_sha512_Final(&ctx, z);
|
||||
|
||||
static CONFIDENTIAL uint8_t zl8[32];
|
||||
memzero(zl8, 32);
|
||||
|
||||
/* get 8 * Zl */
|
||||
scalar_multiply8(z, 28, zl8);
|
||||
/* Kl = 8*Zl + parent(K)l */
|
||||
scalar_add_256bits(zl8, priv_key, res_key);
|
||||
|
||||
/* Kr = Zr + parent(K)r */
|
||||
scalar_add_256bits(z + 32, priv_key + 32, res_key + 32);
|
||||
|
||||
memcpy(inout->private_key, res_key, 32);
|
||||
memcpy(inout->private_key_extension, res_key + 32, 32);
|
||||
|
||||
if(keysize == 64) {
|
||||
data[0] = 1;
|
||||
} else {
|
||||
data[0] = 3;
|
||||
}
|
||||
hmac_sha512_Init(&ctx, inout->chain_code, 32);
|
||||
hmac_sha512_Update(&ctx, data, 1 + keysize + 4);
|
||||
hmac_sha512_Final(&ctx, z);
|
||||
|
||||
memcpy(inout->chain_code, z + 32, 32);
|
||||
inout->depth++;
|
||||
inout->child_num = index;
|
||||
memzero(inout->public_key, sizeof(inout->public_key));
|
||||
|
||||
// making sure to wipe our memory
|
||||
memzero(z, sizeof(z));
|
||||
memzero(data, sizeof(data));
|
||||
memzero(priv_key, sizeof(priv_key));
|
||||
memzero(res_key, sizeof(res_key));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_from_secret_cardano(const uint8_t secret[CARDANO_SECRET_LENGTH], HDNode* out) {
|
||||
memzero(out, sizeof(HDNode));
|
||||
out->depth = 0;
|
||||
out->child_num = 0;
|
||||
out->curve = &ed25519_cardano_info;
|
||||
memcpy(out->private_key, secret, 32);
|
||||
memcpy(out->private_key_extension, secret + 32, 32);
|
||||
memcpy(out->chain_code, secret + 64, 32);
|
||||
|
||||
cardano_ed25519_tweak_bits(out->private_key);
|
||||
|
||||
out->public_key[0] = 0;
|
||||
if(hdnode_fill_public_key(out) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Derives the root Cardano secret from a master secret, aka seed, as defined in
|
||||
// SLIP-0023.
|
||||
int secret_from_seed_cardano_slip23(
|
||||
const uint8_t* seed,
|
||||
int seed_len,
|
||||
uint8_t secret_out[CARDANO_SECRET_LENGTH]) {
|
||||
static CONFIDENTIAL uint8_t I[SHA512_DIGEST_LENGTH];
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX ctx;
|
||||
|
||||
hmac_sha512_Init(&ctx, (const uint8_t*)ED25519_CARDANO_NAME, strlen(ED25519_CARDANO_NAME));
|
||||
hmac_sha512_Update(&ctx, seed, seed_len);
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
|
||||
sha512_Raw(I, 32, secret_out);
|
||||
|
||||
memcpy(secret_out + SHA512_DIGEST_LENGTH, I + 32, 32);
|
||||
cardano_ed25519_tweak_bits(secret_out);
|
||||
|
||||
memzero(I, sizeof(I));
|
||||
memzero(&ctx, sizeof(ctx));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Derives the root Cardano secret from a BIP-32 master secret via the Ledger
|
||||
// derivation:
|
||||
// https://github.com/cardano-foundation/CIPs/blob/09d7d8ee1bd64f7e6b20b5a6cae088039dce00cb/CIP-0003/Ledger.md
|
||||
int secret_from_seed_cardano_ledger(
|
||||
const uint8_t* seed,
|
||||
int seed_len,
|
||||
uint8_t secret_out[CARDANO_SECRET_LENGTH]) {
|
||||
static CONFIDENTIAL uint8_t chain_code[SHA256_DIGEST_LENGTH];
|
||||
static CONFIDENTIAL uint8_t root_key[SHA512_DIGEST_LENGTH];
|
||||
static CONFIDENTIAL HMAC_SHA256_CTX ctx;
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX sctx;
|
||||
|
||||
const uint8_t* intermediate_result = seed;
|
||||
int intermediate_result_len = seed_len;
|
||||
do {
|
||||
// STEP 1: derive a master secret like in BIP-32/SLIP-10
|
||||
hmac_sha512_Init(&sctx, (const uint8_t*)ED25519_SEED_NAME, strlen(ED25519_SEED_NAME));
|
||||
hmac_sha512_Update(&sctx, intermediate_result, intermediate_result_len);
|
||||
hmac_sha512_Final(&sctx, root_key);
|
||||
|
||||
// STEP 2: check that the resulting key does not have a particular bit set,
|
||||
// otherwise iterate like in SLIP-10
|
||||
intermediate_result = root_key;
|
||||
intermediate_result_len = sizeof(root_key);
|
||||
} while(root_key[31] & 0x20);
|
||||
|
||||
// STEP 3: calculate the chain code as a HMAC-SHA256 of "\x01" + seed,
|
||||
// key is "ed25519 seed"
|
||||
hmac_sha256_Init(&ctx, (const unsigned char*)ED25519_SEED_NAME, strlen(ED25519_SEED_NAME));
|
||||
hmac_sha256_Update(&ctx, (const unsigned char*)"\x01", 1);
|
||||
hmac_sha256_Update(&ctx, seed, seed_len);
|
||||
hmac_sha256_Final(&ctx, chain_code);
|
||||
|
||||
// STEP 4: extract information into output
|
||||
_Static_assert(
|
||||
SHA512_DIGEST_LENGTH + SHA256_DIGEST_LENGTH == CARDANO_SECRET_LENGTH,
|
||||
"Invalid configuration of Cardano secret size");
|
||||
memcpy(secret_out, root_key, SHA512_DIGEST_LENGTH);
|
||||
memcpy(secret_out + SHA512_DIGEST_LENGTH, chain_code, SHA256_DIGEST_LENGTH);
|
||||
|
||||
// STEP 5: tweak bits of the private key
|
||||
cardano_ed25519_tweak_bits(secret_out);
|
||||
|
||||
memzero(&ctx, sizeof(ctx));
|
||||
memzero(&sctx, sizeof(sctx));
|
||||
memzero(root_key, sizeof(root_key));
|
||||
memzero(chain_code, sizeof(chain_code));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define CARDANO_ICARUS_STEPS 32
|
||||
_Static_assert(
|
||||
CARDANO_ICARUS_PBKDF2_ROUNDS % CARDANO_ICARUS_STEPS == 0,
|
||||
"CARDANO_ICARUS_STEPS does not divide CARDANO_ICARUS_PBKDF2_ROUNDS");
|
||||
#define CARDANO_ICARUS_ROUNDS_PER_STEP (CARDANO_ICARUS_PBKDF2_ROUNDS / CARDANO_ICARUS_STEPS)
|
||||
|
||||
// Derives the root Cardano HDNode from a passphrase and the entropy encoded in
|
||||
// a BIP-0039 mnemonic using the Icarus derivation scheme, aka V2 derivation
|
||||
// scheme:
|
||||
// https://github.com/cardano-foundation/CIPs/blob/09d7d8ee1bd64f7e6b20b5a6cae088039dce00cb/CIP-0003/Icarus.md
|
||||
int secret_from_entropy_cardano_icarus(
|
||||
const uint8_t* pass,
|
||||
int pass_len,
|
||||
const uint8_t* entropy,
|
||||
int entropy_len,
|
||||
uint8_t secret_out[CARDANO_SECRET_LENGTH],
|
||||
void (*progress_callback)(uint32_t, uint32_t)) {
|
||||
static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
static CONFIDENTIAL uint8_t digest[SHA512_DIGEST_LENGTH];
|
||||
uint32_t progress = 0;
|
||||
|
||||
// PASS 1: first 64 bytes
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, pass_len, entropy, entropy_len, 1);
|
||||
if(progress_callback) {
|
||||
progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2);
|
||||
}
|
||||
for(int i = 0; i < CARDANO_ICARUS_STEPS; i++) {
|
||||
pbkdf2_hmac_sha512_Update(&pctx, CARDANO_ICARUS_ROUNDS_PER_STEP);
|
||||
if(progress_callback) {
|
||||
progress += CARDANO_ICARUS_ROUNDS_PER_STEP;
|
||||
progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2);
|
||||
}
|
||||
}
|
||||
pbkdf2_hmac_sha512_Final(&pctx, digest);
|
||||
|
||||
memcpy(secret_out, digest, SHA512_DIGEST_LENGTH);
|
||||
|
||||
// PASS 2: remaining 32 bytes
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, pass_len, entropy, entropy_len, 2);
|
||||
if(progress_callback) {
|
||||
progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2);
|
||||
}
|
||||
for(int i = 0; i < CARDANO_ICARUS_STEPS; i++) {
|
||||
pbkdf2_hmac_sha512_Update(&pctx, CARDANO_ICARUS_ROUNDS_PER_STEP);
|
||||
if(progress_callback) {
|
||||
progress += CARDANO_ICARUS_ROUNDS_PER_STEP;
|
||||
progress_callback(progress, CARDANO_ICARUS_PBKDF2_ROUNDS * 2);
|
||||
}
|
||||
}
|
||||
pbkdf2_hmac_sha512_Final(&pctx, digest);
|
||||
|
||||
memcpy(
|
||||
secret_out + SHA512_DIGEST_LENGTH, digest, CARDANO_SECRET_LENGTH - SHA512_DIGEST_LENGTH);
|
||||
|
||||
cardano_ed25519_tweak_bits(secret_out);
|
||||
|
||||
memzero(&pctx, sizeof(pctx));
|
||||
memzero(digest, sizeof(digest));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // USE_CARDANO
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2021 SatoshiLabs
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CARDANO_H__
|
||||
#define __CARDANO_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bip32.h"
|
||||
#include "options.h"
|
||||
|
||||
#if USE_CARDANO
|
||||
|
||||
#define CARDANO_SECRET_LENGTH 96
|
||||
#define CARDANO_ICARUS_PBKDF2_ROUNDS 4096
|
||||
|
||||
extern const curve_info ed25519_cardano_info;
|
||||
|
||||
int hdnode_private_ckd_cardano(HDNode* inout, uint32_t i);
|
||||
|
||||
int secret_from_entropy_cardano_icarus(
|
||||
const uint8_t* pass,
|
||||
int pass_len,
|
||||
const uint8_t* entropy,
|
||||
int entropy_len,
|
||||
uint8_t secret_out[CARDANO_SECRET_LENGTH],
|
||||
void (*progress_callback)(uint32_t current, uint32_t total));
|
||||
int secret_from_seed_cardano_ledger(
|
||||
const uint8_t* seed,
|
||||
int seed_len,
|
||||
uint8_t secret_out[CARDANO_SECRET_LENGTH]);
|
||||
int secret_from_seed_cardano_slip23(
|
||||
const uint8_t* seed,
|
||||
int seed_len,
|
||||
uint8_t secret_out[CARDANO_SECRET_LENGTH]);
|
||||
|
||||
int hdnode_from_secret_cardano(const uint8_t secret[CARDANO_SECRET_LENGTH], HDNode* out);
|
||||
|
||||
#endif // USE_CARDANO
|
||||
|
||||
#endif // __CARDANO_H__
|
||||
188
applications/external/flipbip/lib/crypto/cash_addr.c
vendored
188
applications/external/flipbip/lib/crypto/cash_addr.c
vendored
@@ -1,188 +0,0 @@
|
||||
/* Copyright (c) 2017 Jochen Hoenicke
|
||||
* based on code Copyright (c) 2017 Peter Wuille
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cash_addr.h"
|
||||
|
||||
#define MAX_CASHADDR_SIZE 129
|
||||
#define MAX_BASE32_SIZE 104
|
||||
#define MAX_DATA_SIZE 65
|
||||
#define MAX_HRP_SIZE 20
|
||||
#define CHECKSUM_SIZE 8
|
||||
|
||||
uint64_t cashaddr_polymod_step(uint64_t pre) {
|
||||
uint8_t b = pre >> 35;
|
||||
return ((pre & 0x7FFFFFFFFULL) << 5) ^ (-((b >> 0) & 1) & 0x98f2bc8e61ULL) ^
|
||||
(-((b >> 1) & 1) & 0x79b76d99e2ULL) ^ (-((b >> 2) & 1) & 0xf33e5fb3c4ULL) ^
|
||||
(-((b >> 3) & 1) & 0xae2eabe2a8ULL) ^ (-((b >> 4) & 1) & 0x1e4f43e470ULL);
|
||||
}
|
||||
|
||||
static const char* charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
||||
|
||||
static const int8_t charset_rev[128] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1, -1, 29,
|
||||
-1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14,
|
||||
6, 4, 2, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27,
|
||||
19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1};
|
||||
|
||||
int cash_encode(char* output, const char* hrp, const uint8_t* data, size_t data_len) {
|
||||
uint64_t chk = 1;
|
||||
size_t i = 0;
|
||||
while(hrp[i] != 0) {
|
||||
int ch = hrp[i];
|
||||
if(ch < 33 || ch > 126) {
|
||||
return 0;
|
||||
}
|
||||
*(output++) = ch;
|
||||
chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f);
|
||||
++i;
|
||||
}
|
||||
if(i + 1 + data_len + CHECKSUM_SIZE > MAX_CASHADDR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
*(output++) = ':';
|
||||
for(i = 0; i < data_len; ++i) {
|
||||
if(*data >> 5) return 0;
|
||||
chk = cashaddr_polymod_step(chk) ^ (*data);
|
||||
*(output++) = charset[*(data++)];
|
||||
}
|
||||
for(i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
}
|
||||
chk ^= 1;
|
||||
for(i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
*(output++) = charset[(chk >> ((CHECKSUM_SIZE - 1 - i) * 5)) & 0x1f];
|
||||
}
|
||||
*output = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cash_decode(char* hrp, uint8_t* data, size_t* data_len, const char* input) {
|
||||
uint64_t chk = 1;
|
||||
size_t i = 0;
|
||||
size_t input_len = strlen(input);
|
||||
size_t hrp_len = 0;
|
||||
int have_lower = 0, have_upper = 0;
|
||||
if(input_len < CHECKSUM_SIZE || input_len > MAX_CASHADDR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
*data_len = 0;
|
||||
while(*data_len < input_len && input[(input_len - 1) - *data_len] != ':') {
|
||||
++(*data_len);
|
||||
}
|
||||
hrp_len = input_len - (1 + *data_len);
|
||||
if(1 + *data_len >= input_len || hrp_len > MAX_HRP_SIZE || *data_len < CHECKSUM_SIZE ||
|
||||
*data_len > CHECKSUM_SIZE + MAX_BASE32_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
// subtract checksum
|
||||
*(data_len) -= CHECKSUM_SIZE;
|
||||
for(i = 0; i < hrp_len; ++i) {
|
||||
int ch = input[i];
|
||||
if(ch < 33 || ch > 126) {
|
||||
return 0;
|
||||
}
|
||||
if(ch >= 'a' && ch <= 'z') {
|
||||
have_lower = 1;
|
||||
} else if(ch >= 'A' && ch <= 'Z') {
|
||||
have_upper = 1;
|
||||
ch = (ch - 'A') + 'a';
|
||||
}
|
||||
hrp[i] = ch;
|
||||
chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f);
|
||||
}
|
||||
hrp[i] = 0;
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
++i;
|
||||
while(i < input_len) {
|
||||
int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]];
|
||||
if(input[i] >= 'a' && input[i] <= 'z') have_lower = 1;
|
||||
if(input[i] >= 'A' && input[i] <= 'Z') have_upper = 1;
|
||||
if(v == -1) {
|
||||
return 0;
|
||||
}
|
||||
chk = cashaddr_polymod_step(chk) ^ v;
|
||||
if(i + CHECKSUM_SIZE < input_len) {
|
||||
data[i - (1 + hrp_len)] = v;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if(have_lower && have_upper) {
|
||||
return 0;
|
||||
}
|
||||
return chk == 1;
|
||||
}
|
||||
|
||||
static int convert_bits(
|
||||
uint8_t* out,
|
||||
size_t* outlen,
|
||||
int outbits,
|
||||
const uint8_t* in,
|
||||
size_t inlen,
|
||||
int inbits,
|
||||
int pad) {
|
||||
uint32_t val = 0;
|
||||
int bits = 0;
|
||||
uint32_t maxv = (((uint32_t)1) << outbits) - 1;
|
||||
while(inlen--) {
|
||||
val = (val << inbits) | *(in++);
|
||||
bits += inbits;
|
||||
while(bits >= outbits) {
|
||||
bits -= outbits;
|
||||
out[(*outlen)++] = (val >> bits) & maxv;
|
||||
}
|
||||
}
|
||||
if(pad) {
|
||||
if(bits) {
|
||||
out[(*outlen)++] = (val << (outbits - bits)) & maxv;
|
||||
}
|
||||
} else if(((val << (outbits - bits)) & maxv) || bits >= inbits) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cash_addr_encode(char* output, const char* hrp, const uint8_t* data, size_t data_len) {
|
||||
uint8_t base32[MAX_BASE32_SIZE] = {0};
|
||||
size_t base32len = 0;
|
||||
if(data_len < 2 || data_len > MAX_DATA_SIZE) return 0;
|
||||
convert_bits(base32, &base32len, 5, data, data_len, 8, 1);
|
||||
return cash_encode(output, hrp, base32, base32len);
|
||||
}
|
||||
|
||||
int cash_addr_decode(uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) {
|
||||
uint8_t data[MAX_BASE32_SIZE] = {0};
|
||||
char hrp_actual[MAX_HRP_SIZE + 1] = {0};
|
||||
size_t data_len = 0;
|
||||
if(!cash_decode(hrp_actual, data, &data_len, addr)) return 0;
|
||||
if(data_len == 0 || data_len > MAX_BASE32_SIZE) return 0;
|
||||
if(strncmp(hrp, hrp_actual, MAX_HRP_SIZE + 1) != 0) return 0;
|
||||
*witdata_len = 0;
|
||||
if(!convert_bits(witdata, witdata_len, 8, data, data_len, 5, 0)) return 0;
|
||||
if(*witdata_len < 2 || *witdata_len > MAX_DATA_SIZE) return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/* Copyright (c) 2017 Jochen Hoenicke, Pieter Wuille
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CASH_ADDR_H_
|
||||
#define _CASH_ADDR_H_ 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Encode a Cashaddr address
|
||||
*
|
||||
* Out: output: Pointer to a buffer of size 105 + strlen(hrp) that will be
|
||||
* updated to contain the null-terminated address.
|
||||
* In: hrp: Pointer to the null-terminated human readable part to use
|
||||
* (chain/network specific).
|
||||
* prog: Data bytes for the hash (between 21 and 65 bytes).
|
||||
* prog_len: Number of data bytes in prog.
|
||||
* Returns 1 if successful.
|
||||
*/
|
||||
int cash_addr_encode(char* output, const char* hrp, const uint8_t* prog, size_t prog_len);
|
||||
|
||||
/** Decode a CashAddr address
|
||||
*
|
||||
* Out: prog: Pointer to a buffer of size 65 that will be updated to
|
||||
* contain the witness program bytes.
|
||||
* prog_len: Pointer to a size_t that will be updated to contain the
|
||||
* length of bytes in prog. hrp: Pointer to the null-terminated human
|
||||
* readable part that is expected (chain/network specific). addr: Pointer to
|
||||
* the null-terminated address. Returns 1 if successful.
|
||||
*/
|
||||
int cash_addr_decode(uint8_t* prog, size_t* prog_len, const char* hrp, const char* addr);
|
||||
|
||||
/** Encode a Cash string
|
||||
*
|
||||
* Out: output: Pointer to a buffer of size strlen(hrp) + data_len + 8 that
|
||||
* will be updated to contain the null-terminated Cash string.
|
||||
* In: hrp : Pointer to the null-terminated human readable part.
|
||||
* data : Pointer to an array of 5-bit values.
|
||||
* data_len: Length of the data array.
|
||||
* Returns 1 if successful.
|
||||
*/
|
||||
int cash_encode(char* output, const char* hrp, const uint8_t* data, size_t data_len);
|
||||
|
||||
/** Decode a Cash string
|
||||
*
|
||||
* Out: hrp: Pointer to a buffer of size strlen(input) - 6. Will be
|
||||
* updated to contain the null-terminated human readable part.
|
||||
* data: Pointer to a buffer of size strlen(input) - 8 that will
|
||||
* hold the encoded 5-bit data values.
|
||||
* data_len: Pointer to a size_t that will be updated to be the number
|
||||
* of entries in data.
|
||||
* In: input: Pointer to a null-terminated Cash string.
|
||||
* Returns 1 if succesful.
|
||||
*/
|
||||
int cash_decode(char* hrp, uint8_t* data, size_t* data_len, const char* input);
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2016 Will Glozer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,63 +0,0 @@
|
||||
// Implementations of the XChaCha20 + Poly1305 and ChaCha20 + Poly1305
|
||||
// AEAD constructions with a goal of simplicity and correctness rather
|
||||
// than performance.
|
||||
|
||||
#include "chacha20poly1305.h"
|
||||
#include "ecrypt_portable.h"
|
||||
|
||||
void hchacha20(ECRYPT_ctx* x, u8* c);
|
||||
|
||||
// Initialize the XChaCha20 + Poly1305 context for encryption or decryption
|
||||
// using a 32 byte key and 24 byte nonce. The key and the first 16 bytes of
|
||||
// the nonce are used as input to HChaCha20 to derive the Chacha20 key.
|
||||
void xchacha20poly1305_init(
|
||||
chacha20poly1305_ctx* ctx,
|
||||
const uint8_t key[32],
|
||||
const uint8_t nonce[24]) {
|
||||
unsigned char subkey[32] = {0};
|
||||
unsigned char block0[64] = {0};
|
||||
ECRYPT_ctx tmp = {0};
|
||||
|
||||
// Generate the Chacha20 key by applying HChaCha20 to the
|
||||
// original key and the first 16 bytes of the nonce.
|
||||
ECRYPT_keysetup(&tmp, key, 256, 16);
|
||||
tmp.input[12] = U8TO32_LITTLE(nonce + 0);
|
||||
tmp.input[13] = U8TO32_LITTLE(nonce + 4);
|
||||
tmp.input[14] = U8TO32_LITTLE(nonce + 8);
|
||||
tmp.input[15] = U8TO32_LITTLE(nonce + 12);
|
||||
hchacha20(&tmp, subkey);
|
||||
|
||||
// Initialize Chacha20 with the newly generated key and
|
||||
// the last 8 bytes of the nonce.
|
||||
ECRYPT_keysetup(&ctx->chacha20, subkey, 256, 16);
|
||||
ECRYPT_ivsetup(&ctx->chacha20, nonce + 16);
|
||||
|
||||
// Encrypt 64 bytes of zeros and use the first 32 bytes
|
||||
// as the Poly1305 key.
|
||||
ECRYPT_encrypt_bytes(&ctx->chacha20, block0, block0, 64);
|
||||
poly1305_init(&ctx->poly1305, block0);
|
||||
}
|
||||
|
||||
// Encrypt n bytes of plaintext where n must be evenly divisible by the
|
||||
// Chacha20 blocksize of 64, except for the final n bytes of plaintext.
|
||||
void chacha20poly1305_encrypt(chacha20poly1305_ctx* ctx, const uint8_t* in, uint8_t* out, size_t n) {
|
||||
ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n);
|
||||
poly1305_update(&ctx->poly1305, out, n);
|
||||
}
|
||||
|
||||
// Decrypt n bytes of ciphertext where n must be evenly divisible by the
|
||||
// Chacha20 blocksize of 64, except for the final n bytes of ciphertext.
|
||||
void chacha20poly1305_decrypt(chacha20poly1305_ctx* ctx, const uint8_t* in, uint8_t* out, size_t n) {
|
||||
poly1305_update(&ctx->poly1305, in, n);
|
||||
ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n);
|
||||
}
|
||||
|
||||
// Include authenticated data in the Poly1305 MAC.
|
||||
void chacha20poly1305_auth(chacha20poly1305_ctx* ctx, const uint8_t* in, size_t n) {
|
||||
poly1305_update(&ctx->poly1305, in, n);
|
||||
}
|
||||
|
||||
// Compute NaCl secretbox-style Poly1305 MAC.
|
||||
void chacha20poly1305_finish(chacha20poly1305_ctx* ctx, uint8_t mac[16]) {
|
||||
poly1305_finish(&ctx->poly1305, mac);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef CHACHA20POLY1305_H
|
||||
#define CHACHA20POLY1305_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ecrypt_sync.h"
|
||||
#include "poly1305_donna.h"
|
||||
|
||||
typedef struct {
|
||||
ECRYPT_ctx chacha20;
|
||||
poly1305_context poly1305;
|
||||
} chacha20poly1305_ctx;
|
||||
|
||||
void xchacha20poly1305_init(
|
||||
chacha20poly1305_ctx* ctx,
|
||||
const uint8_t key[32],
|
||||
const uint8_t nonce[24]);
|
||||
void chacha20poly1305_encrypt(chacha20poly1305_ctx* ctx, const uint8_t* in, uint8_t* out, size_t n);
|
||||
void chacha20poly1305_decrypt(chacha20poly1305_ctx* ctx, const uint8_t* in, uint8_t* out, size_t n);
|
||||
void chacha20poly1305_auth(chacha20poly1305_ctx* ctx, const uint8_t* in, size_t n);
|
||||
void chacha20poly1305_finish(chacha20poly1305_ctx* ctx, uint8_t mac[16]);
|
||||
|
||||
#endif // CHACHA20POLY1305_H
|
||||
@@ -1,251 +0,0 @@
|
||||
/*
|
||||
chacha-merged.c version 20080118
|
||||
D. J. Bernstein
|
||||
Public domain.
|
||||
*/
|
||||
|
||||
#include "ecrypt_sync.h"
|
||||
#include "ecrypt_portable.h"
|
||||
|
||||
#define ROTATE(v, c) (ROTL32(v, c))
|
||||
#define XOR(v, w) ((v) ^ (w))
|
||||
#define PLUS(v, w) (U32V((v) + (w)))
|
||||
#define PLUSONE(v) (PLUS((v), 1))
|
||||
|
||||
#define QUARTERROUND(a, b, c, d) \
|
||||
a = PLUS(a, b); \
|
||||
d = ROTATE(XOR(d, a), 16); \
|
||||
c = PLUS(c, d); \
|
||||
b = ROTATE(XOR(b, c), 12); \
|
||||
a = PLUS(a, b); \
|
||||
d = ROTATE(XOR(d, a), 8); \
|
||||
c = PLUS(c, d); \
|
||||
b = ROTATE(XOR(b, c), 7);
|
||||
|
||||
void ECRYPT_init(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const char sigma[16] = "expand 32-byte k";
|
||||
static const char tau[16] = "expand 16-byte k";
|
||||
|
||||
void ECRYPT_keysetup(ECRYPT_ctx* x, const u8* k, u32 kbits, u32 ivbits) {
|
||||
(void)ivbits;
|
||||
const char* constants = (const char*)0;
|
||||
|
||||
x->input[4] = U8TO32_LITTLE(k + 0);
|
||||
x->input[5] = U8TO32_LITTLE(k + 4);
|
||||
x->input[6] = U8TO32_LITTLE(k + 8);
|
||||
x->input[7] = U8TO32_LITTLE(k + 12);
|
||||
if(kbits == 256) { /* recommended */
|
||||
k += 16;
|
||||
constants = sigma;
|
||||
} else { /* kbits == 128 */
|
||||
constants = tau;
|
||||
}
|
||||
x->input[8] = U8TO32_LITTLE(k + 0);
|
||||
x->input[9] = U8TO32_LITTLE(k + 4);
|
||||
x->input[10] = U8TO32_LITTLE(k + 8);
|
||||
x->input[11] = U8TO32_LITTLE(k + 12);
|
||||
x->input[0] = U8TO32_LITTLE(constants + 0);
|
||||
x->input[1] = U8TO32_LITTLE(constants + 4);
|
||||
x->input[2] = U8TO32_LITTLE(constants + 8);
|
||||
x->input[3] = U8TO32_LITTLE(constants + 12);
|
||||
}
|
||||
|
||||
void ECRYPT_ivsetup(ECRYPT_ctx* x, const u8* iv) {
|
||||
x->input[12] = 0;
|
||||
x->input[13] = 0;
|
||||
x->input[14] = U8TO32_LITTLE(iv + 0);
|
||||
x->input[15] = U8TO32_LITTLE(iv + 4);
|
||||
}
|
||||
|
||||
void ECRYPT_ctrsetup(ECRYPT_ctx* x, const u8* ctr) {
|
||||
x->input[12] = U8TO32_LITTLE(ctr + 0);
|
||||
x->input[13] = U8TO32_LITTLE(ctr + 4);
|
||||
}
|
||||
|
||||
void ECRYPT_encrypt_bytes(ECRYPT_ctx* x, const u8* m, u8* c, u32 bytes) {
|
||||
u32 x0 = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0, x7 = 0, x8 = 0, x9 = 0, x10 = 0,
|
||||
x11 = 0, x12 = 0, x13 = 0, x14 = 0, x15 = 0;
|
||||
u32 j0 = 0, j1 = 0, j2 = 0, j3 = 0, j4 = 0, j5 = 0, j6 = 0, j7 = 0, j8 = 0, j9 = 0, j10 = 0,
|
||||
j11 = 0, j12 = 0, j13 = 0, j14 = 0, j15 = 0;
|
||||
u8* ctarget = 0;
|
||||
u8 tmp[64] = {0};
|
||||
int i = 0;
|
||||
|
||||
if(!bytes) return;
|
||||
|
||||
j0 = x->input[0];
|
||||
j1 = x->input[1];
|
||||
j2 = x->input[2];
|
||||
j3 = x->input[3];
|
||||
j4 = x->input[4];
|
||||
j5 = x->input[5];
|
||||
j6 = x->input[6];
|
||||
j7 = x->input[7];
|
||||
j8 = x->input[8];
|
||||
j9 = x->input[9];
|
||||
j10 = x->input[10];
|
||||
j11 = x->input[11];
|
||||
j12 = x->input[12];
|
||||
j13 = x->input[13];
|
||||
j14 = x->input[14];
|
||||
j15 = x->input[15];
|
||||
|
||||
for(;;) {
|
||||
if(bytes < 64) {
|
||||
for(i = 0; i < (int)bytes; ++i) tmp[i] = m[i];
|
||||
m = tmp;
|
||||
ctarget = c;
|
||||
c = tmp;
|
||||
}
|
||||
x0 = j0;
|
||||
x1 = j1;
|
||||
x2 = j2;
|
||||
x3 = j3;
|
||||
x4 = j4;
|
||||
x5 = j5;
|
||||
x6 = j6;
|
||||
x7 = j7;
|
||||
x8 = j8;
|
||||
x9 = j9;
|
||||
x10 = j10;
|
||||
x11 = j11;
|
||||
x12 = j12;
|
||||
x13 = j13;
|
||||
x14 = j14;
|
||||
x15 = j15;
|
||||
for(i = 20; i > 0; i -= 2) {
|
||||
QUARTERROUND(x0, x4, x8, x12)
|
||||
QUARTERROUND(x1, x5, x9, x13)
|
||||
QUARTERROUND(x2, x6, x10, x14)
|
||||
QUARTERROUND(x3, x7, x11, x15)
|
||||
QUARTERROUND(x0, x5, x10, x15)
|
||||
QUARTERROUND(x1, x6, x11, x12)
|
||||
QUARTERROUND(x2, x7, x8, x13)
|
||||
QUARTERROUND(x3, x4, x9, x14)
|
||||
}
|
||||
x0 = PLUS(x0, j0);
|
||||
x1 = PLUS(x1, j1);
|
||||
x2 = PLUS(x2, j2);
|
||||
x3 = PLUS(x3, j3);
|
||||
x4 = PLUS(x4, j4);
|
||||
x5 = PLUS(x5, j5);
|
||||
x6 = PLUS(x6, j6);
|
||||
x7 = PLUS(x7, j7);
|
||||
x8 = PLUS(x8, j8);
|
||||
x9 = PLUS(x9, j9);
|
||||
x10 = PLUS(x10, j10);
|
||||
x11 = PLUS(x11, j11);
|
||||
x12 = PLUS(x12, j12);
|
||||
x13 = PLUS(x13, j13);
|
||||
x14 = PLUS(x14, j14);
|
||||
x15 = PLUS(x15, j15);
|
||||
|
||||
x0 = XOR(x0, U8TO32_LITTLE(m + 0));
|
||||
x1 = XOR(x1, U8TO32_LITTLE(m + 4));
|
||||
x2 = XOR(x2, U8TO32_LITTLE(m + 8));
|
||||
x3 = XOR(x3, U8TO32_LITTLE(m + 12));
|
||||
x4 = XOR(x4, U8TO32_LITTLE(m + 16));
|
||||
x5 = XOR(x5, U8TO32_LITTLE(m + 20));
|
||||
x6 = XOR(x6, U8TO32_LITTLE(m + 24));
|
||||
x7 = XOR(x7, U8TO32_LITTLE(m + 28));
|
||||
x8 = XOR(x8, U8TO32_LITTLE(m + 32));
|
||||
x9 = XOR(x9, U8TO32_LITTLE(m + 36));
|
||||
x10 = XOR(x10, U8TO32_LITTLE(m + 40));
|
||||
x11 = XOR(x11, U8TO32_LITTLE(m + 44));
|
||||
x12 = XOR(x12, U8TO32_LITTLE(m + 48));
|
||||
x13 = XOR(x13, U8TO32_LITTLE(m + 52));
|
||||
x14 = XOR(x14, U8TO32_LITTLE(m + 56));
|
||||
x15 = XOR(x15, U8TO32_LITTLE(m + 60));
|
||||
|
||||
j12 = PLUSONE(j12);
|
||||
if(!j12) {
|
||||
j13 = PLUSONE(j13);
|
||||
/* stopping at 2^70 bytes per nonce is user's responsibility */
|
||||
}
|
||||
|
||||
U32TO8_LITTLE(c + 0, x0);
|
||||
U32TO8_LITTLE(c + 4, x1);
|
||||
U32TO8_LITTLE(c + 8, x2);
|
||||
U32TO8_LITTLE(c + 12, x3);
|
||||
U32TO8_LITTLE(c + 16, x4);
|
||||
U32TO8_LITTLE(c + 20, x5);
|
||||
U32TO8_LITTLE(c + 24, x6);
|
||||
U32TO8_LITTLE(c + 28, x7);
|
||||
U32TO8_LITTLE(c + 32, x8);
|
||||
U32TO8_LITTLE(c + 36, x9);
|
||||
U32TO8_LITTLE(c + 40, x10);
|
||||
U32TO8_LITTLE(c + 44, x11);
|
||||
U32TO8_LITTLE(c + 48, x12);
|
||||
U32TO8_LITTLE(c + 52, x13);
|
||||
U32TO8_LITTLE(c + 56, x14);
|
||||
U32TO8_LITTLE(c + 60, x15);
|
||||
|
||||
if(bytes <= 64) {
|
||||
if(bytes < 64) {
|
||||
for(i = 0; i < (int)bytes; ++i) ctarget[i] = c[i];
|
||||
}
|
||||
x->input[12] = j12;
|
||||
x->input[13] = j13;
|
||||
return;
|
||||
}
|
||||
bytes -= 64;
|
||||
c += 64;
|
||||
m += 64;
|
||||
}
|
||||
}
|
||||
|
||||
void ECRYPT_decrypt_bytes(ECRYPT_ctx* x, const u8* c, u8* m, u32 bytes) {
|
||||
ECRYPT_encrypt_bytes(x, c, m, bytes);
|
||||
}
|
||||
|
||||
void ECRYPT_keystream_bytes(ECRYPT_ctx* x, u8* stream, u32 bytes) {
|
||||
u32 i = 0;
|
||||
for(i = 0; i < bytes; ++i) stream[i] = 0;
|
||||
ECRYPT_encrypt_bytes(x, stream, stream, bytes);
|
||||
}
|
||||
|
||||
void hchacha20(ECRYPT_ctx* x, u8* c) {
|
||||
u32 x0 = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0, x7 = 0, x8 = 0, x9 = 0, x10 = 0,
|
||||
x11 = 0, x12 = 0, x13 = 0, x14 = 0, x15 = 0;
|
||||
int i = 0;
|
||||
|
||||
x0 = x->input[0];
|
||||
x1 = x->input[1];
|
||||
x2 = x->input[2];
|
||||
x3 = x->input[3];
|
||||
x4 = x->input[4];
|
||||
x5 = x->input[5];
|
||||
x6 = x->input[6];
|
||||
x7 = x->input[7];
|
||||
x8 = x->input[8];
|
||||
x9 = x->input[9];
|
||||
x10 = x->input[10];
|
||||
x11 = x->input[11];
|
||||
x12 = x->input[12];
|
||||
x13 = x->input[13];
|
||||
x14 = x->input[14];
|
||||
x15 = x->input[15];
|
||||
|
||||
for(i = 20; i > 0; i -= 2) {
|
||||
QUARTERROUND(x0, x4, x8, x12)
|
||||
QUARTERROUND(x1, x5, x9, x13)
|
||||
QUARTERROUND(x2, x6, x10, x14)
|
||||
QUARTERROUND(x3, x7, x11, x15)
|
||||
QUARTERROUND(x0, x5, x10, x15)
|
||||
QUARTERROUND(x1, x6, x11, x12)
|
||||
QUARTERROUND(x2, x7, x8, x13)
|
||||
QUARTERROUND(x3, x4, x9, x14)
|
||||
}
|
||||
|
||||
U32TO8_LITTLE(c + 0, x0);
|
||||
U32TO8_LITTLE(c + 4, x1);
|
||||
U32TO8_LITTLE(c + 8, x2);
|
||||
U32TO8_LITTLE(c + 12, x3);
|
||||
U32TO8_LITTLE(c + 16, x12);
|
||||
U32TO8_LITTLE(c + 20, x13);
|
||||
U32TO8_LITTLE(c + 24, x14);
|
||||
U32TO8_LITTLE(c + 28, x15);
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
/* ecrypt_config.h */
|
||||
|
||||
/* *** Normally, it should not be necessary to edit this file. *** */
|
||||
|
||||
#ifndef ECRYPT_CONFIG
|
||||
#define ECRYPT_CONFIG
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Guess the endianness of the target architecture. */
|
||||
|
||||
/*
|
||||
* The LITTLE endian machines:
|
||||
*/
|
||||
#if defined(__ultrix) /* Older MIPS */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(__alpha) /* Alpha */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(i386) /* x86 (gcc) */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(__i386) /* x86 (gcc) */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(__x86_64) /* x86_64 (gcc) */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(_M_IX86) /* x86 (MSC, Borland) */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(_MSC_VER) /* x86 (surely MSC) */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
#elif defined(__INTEL_COMPILER) /* x86 (surely Intel compiler icl.exe) */
|
||||
#define ECRYPT_LITTLE_ENDIAN
|
||||
|
||||
/*
|
||||
* The BIG endian machines:
|
||||
*/
|
||||
#elif defined(__sparc) /* Newer Sparc's */
|
||||
#define ECRYPT_BIG_ENDIAN
|
||||
#elif defined(__powerpc__) /* PowerPC */
|
||||
#define ECRYPT_BIG_ENDIAN
|
||||
#elif defined(__ppc__) /* PowerPC */
|
||||
#define ECRYPT_BIG_ENDIAN
|
||||
#elif defined(__hppa) /* HP-PA */
|
||||
#define ECRYPT_BIG_ENDIAN
|
||||
|
||||
/*
|
||||
* Finally machines with UNKNOWN endianness:
|
||||
*/
|
||||
#elif defined(_AIX) /* RS6000 */
|
||||
#define ECRYPT_UNKNOWN
|
||||
#elif defined(__aux) /* 68K */
|
||||
#define ECRYPT_UNKNOWN
|
||||
#elif defined(__dgux) /* 88K (but P6 in latest boxes) */
|
||||
#define ECRYPT_UNKNOWN
|
||||
#elif defined(__sgi) /* Newer MIPS */
|
||||
#define ECRYPT_UNKNOWN
|
||||
#else /* Any other processor */
|
||||
#define ECRYPT_UNKNOWN
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Find minimal-width types to store 8-bit, 16-bit, 32-bit, and 64-bit
|
||||
* integers.
|
||||
*
|
||||
* Note: to enable 64-bit types on 32-bit compilers, it might be
|
||||
* necessary to switch from ISO C90 mode to ISO C99 mode (e.g., gcc
|
||||
* -std=c99), or to allow compiler-specific extensions.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* --- check char --- */
|
||||
|
||||
#if(UCHAR_MAX / 0xFU > 0xFU)
|
||||
#ifndef I8T
|
||||
#define I8T char
|
||||
#define U8C(v) (v##U)
|
||||
|
||||
#if(UCHAR_MAX == 0xFFU)
|
||||
#define ECRYPT_I8T_IS_BYTE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if(UCHAR_MAX / 0xFFU > 0xFFU)
|
||||
#ifndef I16T
|
||||
#define I16T char
|
||||
#define U16C(v) (v##U)
|
||||
#endif
|
||||
|
||||
#if(UCHAR_MAX / 0xFFFFU > 0xFFFFU)
|
||||
#ifndef I32T
|
||||
#define I32T char
|
||||
#define U32C(v) (v##U)
|
||||
#endif
|
||||
|
||||
#if(UCHAR_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
|
||||
#ifndef I64T
|
||||
#define I64T char
|
||||
#define U64C(v) (v##U)
|
||||
#define ECRYPT_NATIVE64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* --- check short --- */
|
||||
|
||||
#if(USHRT_MAX / 0xFU > 0xFU)
|
||||
#ifndef I8T
|
||||
#define I8T short
|
||||
#define U8C(v) (v##U)
|
||||
|
||||
#if(USHRT_MAX == 0xFFU)
|
||||
#define ECRYPT_I8T_IS_BYTE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if(USHRT_MAX / 0xFFU > 0xFFU)
|
||||
#ifndef I16T
|
||||
#define I16T short
|
||||
#define U16C(v) (v##U)
|
||||
#endif
|
||||
|
||||
#if(USHRT_MAX / 0xFFFFU > 0xFFFFU)
|
||||
#ifndef I32T
|
||||
#define I32T short
|
||||
#define U32C(v) (v##U)
|
||||
#endif
|
||||
|
||||
#if(USHRT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
|
||||
#ifndef I64T
|
||||
#define I64T short
|
||||
#define U64C(v) (v##U)
|
||||
#define ECRYPT_NATIVE64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* --- check int --- */
|
||||
|
||||
#if(UINT_MAX / 0xFU > 0xFU)
|
||||
#ifndef I8T
|
||||
#define I8T int
|
||||
#define U8C(v) (v##U)
|
||||
|
||||
#if(ULONG_MAX == 0xFFU)
|
||||
#define ECRYPT_I8T_IS_BYTE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if(UINT_MAX / 0xFFU > 0xFFU)
|
||||
#ifndef I16T
|
||||
#define I16T int
|
||||
#define U16C(v) (v##U)
|
||||
#endif
|
||||
|
||||
#if(UINT_MAX / 0xFFFFU > 0xFFFFU)
|
||||
#ifndef I32T
|
||||
#define I32T int
|
||||
#define U32C(v) (v##U)
|
||||
#endif
|
||||
|
||||
#if(UINT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
|
||||
#ifndef I64T
|
||||
#define I64T int
|
||||
#define U64C(v) (v##U)
|
||||
#define ECRYPT_NATIVE64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* --- check long --- */
|
||||
|
||||
#if(ULONG_MAX / 0xFUL > 0xFUL)
|
||||
#ifndef I8T
|
||||
#define I8T long
|
||||
#define U8C(v) (v##UL)
|
||||
|
||||
#if(ULONG_MAX == 0xFFUL)
|
||||
#define ECRYPT_I8T_IS_BYTE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if(ULONG_MAX / 0xFFUL > 0xFFUL)
|
||||
#ifndef I16T
|
||||
#define I16T long
|
||||
#define U16C(v) (v##UL)
|
||||
#endif
|
||||
|
||||
#if(ULONG_MAX / 0xFFFFUL > 0xFFFFUL)
|
||||
#ifndef I32T
|
||||
#define I32T long
|
||||
#define U32C(v) (v##UL)
|
||||
#endif
|
||||
|
||||
#if(ULONG_MAX / 0xFFFFFFFFUL > 0xFFFFFFFFUL)
|
||||
#ifndef I64T
|
||||
#define I64T long
|
||||
#define U64C(v) (v##UL)
|
||||
#define ECRYPT_NATIVE64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* --- check long long --- */
|
||||
|
||||
#ifdef ULLONG_MAX
|
||||
|
||||
#if(ULLONG_MAX / 0xFULL > 0xFULL)
|
||||
#ifndef I8T
|
||||
#define I8T long long
|
||||
#define U8C(v) (v##ULL)
|
||||
|
||||
#if(ULLONG_MAX == 0xFFULL)
|
||||
#define ECRYPT_I8T_IS_BYTE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if(ULLONG_MAX / 0xFFULL > 0xFFULL)
|
||||
#ifndef I16T
|
||||
#define I16T long long
|
||||
#define U16C(v) (v##ULL)
|
||||
#endif
|
||||
|
||||
#if(ULLONG_MAX / 0xFFFFULL > 0xFFFFULL)
|
||||
#ifndef I32T
|
||||
#define I32T long long
|
||||
#define U32C(v) (v##ULL)
|
||||
#endif
|
||||
|
||||
#if(ULLONG_MAX / 0xFFFFFFFFULL > 0xFFFFFFFFULL)
|
||||
#ifndef I64T
|
||||
#define I64T long long
|
||||
#define U64C(v) (v##ULL)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* --- check __int64 --- */
|
||||
|
||||
#if !defined(__STDC__) && defined(_UI64_MAX)
|
||||
|
||||
#ifndef I64T
|
||||
#define I64T __int64
|
||||
#define U64C(v) (v##ui64)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* --- if platform doesn't announce anything, use most common choices --- */
|
||||
|
||||
#ifndef I8T
|
||||
#define I8T char
|
||||
#define U8C(v) (v##U)
|
||||
#endif
|
||||
#ifndef I16T
|
||||
#define I16T short
|
||||
#define U16C(v) (v##U)
|
||||
#endif
|
||||
#ifndef I32T
|
||||
#define I32T int
|
||||
#define U32C(v) (v##U)
|
||||
#endif
|
||||
#ifndef I64T
|
||||
#define I64T long long
|
||||
#define U64C(v) (v##ULL)
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* find the largest type on this platform (used for alignment) */
|
||||
|
||||
#if defined(__SSE__) || (defined(_MSC_VER) && (_MSC_VER >= 1300))
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#define MAXT __m128
|
||||
|
||||
#elif defined(__MMX__)
|
||||
|
||||
#include <mmintrin.h>
|
||||
#define MAXT __m64
|
||||
|
||||
#elif defined(__ALTIVEC__)
|
||||
|
||||
#define MAXT __vector int
|
||||
|
||||
#else
|
||||
|
||||
#define MAXT long
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/* ecrypt_machine.h */
|
||||
|
||||
/*
|
||||
* This file is included by 'ecrypt_portable.h'. It allows to override
|
||||
* the default macros for specific platforms. Please carefully check
|
||||
* the machine code generated by your compiler (with optimisations
|
||||
* turned on) before deciding to edit this file.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#if(defined(ECRYPT_DEFAULT_ROT) && !defined(ECRYPT_MACHINE_ROT))
|
||||
|
||||
#define ECRYPT_MACHINE_ROT
|
||||
|
||||
#if(defined(WIN32) && defined(_MSC_VER))
|
||||
|
||||
#undef ROTL32
|
||||
#undef ROTR32
|
||||
#undef ROTL64
|
||||
#undef ROTR64
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#pragma intrinsic(_lrotl) /* compile rotations "inline" */
|
||||
#pragma intrinsic(_lrotr)
|
||||
|
||||
#define ROTL32(v, n) _lrotl(v, n)
|
||||
#define ROTR32(v, n) _lrotr(v, n)
|
||||
#define ROTL64(v, n) _rotl64(v, n)
|
||||
#define ROTR64(v, n) _rotr64(v, n)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#if(defined(ECRYPT_DEFAULT_SWAP) && !defined(ECRYPT_MACHINE_SWAP))
|
||||
|
||||
#define ECRYPT_MACHINE_SWAP
|
||||
|
||||
/*
|
||||
* If you want to overwrite the default swap macros, put it here. And so on.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -1,246 +0,0 @@
|
||||
/* ecrypt_portable.h */
|
||||
|
||||
/*
|
||||
* WARNING: the conversions defined below are implemented as macros,
|
||||
* and should be used carefully. They should NOT be used with
|
||||
* parameters which perform some action. E.g., the following two lines
|
||||
* are not equivalent:
|
||||
*
|
||||
* 1) ++x; y = ROTL32(x, n);
|
||||
* 2) y = ROTL32(++x, n);
|
||||
*/
|
||||
|
||||
/*
|
||||
* *** Please do not edit this file. ***
|
||||
*
|
||||
* The default macros can be overridden for specific architectures by
|
||||
* editing 'ecrypt_machine.h'.
|
||||
*/
|
||||
|
||||
#ifndef ECRYPT_PORTABLE
|
||||
#define ECRYPT_PORTABLE
|
||||
|
||||
#include "ecrypt_config.h"
|
||||
#include "ecrypt_types.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The following macros are used to obtain exact-width results.
|
||||
*/
|
||||
|
||||
#define U8V(v) ((u8)(v)&U8C(0xFF))
|
||||
#define U16V(v) ((u16)(v)&U16C(0xFFFF))
|
||||
#define U32V(v) ((u32)(v)&U32C(0xFFFFFFFF))
|
||||
#define U64V(v) ((u64)(v)&U64C(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The following macros return words with their bits rotated over n
|
||||
* positions to the left/right.
|
||||
*/
|
||||
|
||||
#define ECRYPT_DEFAULT_ROT
|
||||
|
||||
#define ROTL8(v, n) (U8V((v) << (n)) | ((v) >> (8 - (n))))
|
||||
|
||||
#define ROTL16(v, n) (U16V((v) << (n)) | ((v) >> (16 - (n))))
|
||||
|
||||
#define ROTL32(v, n) (U32V((v) << (n)) | ((v) >> (32 - (n))))
|
||||
|
||||
#define ROTL64(v, n) (U64V((v) << (n)) | ((v) >> (64 - (n))))
|
||||
|
||||
#define ROTR8(v, n) ROTL8(v, 8 - (n))
|
||||
#define ROTR16(v, n) ROTL16(v, 16 - (n))
|
||||
#define ROTR32(v, n) ROTL32(v, 32 - (n))
|
||||
#define ROTR64(v, n) ROTL64(v, 64 - (n))
|
||||
|
||||
#include "ecrypt_machine.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The following macros return a word with bytes in reverse order.
|
||||
*/
|
||||
|
||||
#define ECRYPT_DEFAULT_SWAP
|
||||
|
||||
#define SWAP16(v) ROTL16(v, 8)
|
||||
|
||||
#define SWAP32(v) ((ROTL32(v, 8) & U32C(0x00FF00FF)) | (ROTL32(v, 24) & U32C(0xFF00FF00)))
|
||||
|
||||
#ifdef ECRYPT_NATIVE64
|
||||
#define SWAP64(v) \
|
||||
((ROTL64(v, 8) & U64C(0x000000FF000000FF)) | (ROTL64(v, 24) & U64C(0x0000FF000000FF00)) | \
|
||||
(ROTL64(v, 40) & U64C(0x00FF000000FF0000)) | (ROTL64(v, 56) & U64C(0xFF000000FF000000)))
|
||||
#else
|
||||
#define SWAP64(v) (((u64)SWAP32(U32V(v)) << 32) | (u64)SWAP32(U32V(v >> 32)))
|
||||
#endif
|
||||
|
||||
#include "ecrypt_machine.h"
|
||||
|
||||
#define ECRYPT_DEFAULT_WTOW
|
||||
|
||||
#ifdef ECRYPT_LITTLE_ENDIAN
|
||||
#define U16TO16_LITTLE(v) (v)
|
||||
#define U32TO32_LITTLE(v) (v)
|
||||
#define U64TO64_LITTLE(v) (v)
|
||||
|
||||
#define U16TO16_BIG(v) SWAP16(v)
|
||||
#define U32TO32_BIG(v) SWAP32(v)
|
||||
#define U64TO64_BIG(v) SWAP64(v)
|
||||
#endif
|
||||
|
||||
#ifdef ECRYPT_BIG_ENDIAN
|
||||
#define U16TO16_LITTLE(v) SWAP16(v)
|
||||
#define U32TO32_LITTLE(v) SWAP32(v)
|
||||
#define U64TO64_LITTLE(v) SWAP64(v)
|
||||
|
||||
#define U16TO16_BIG(v) (v)
|
||||
#define U32TO32_BIG(v) (v)
|
||||
#define U64TO64_BIG(v) (v)
|
||||
#endif
|
||||
|
||||
#include "ecrypt_machine.h"
|
||||
|
||||
/*
|
||||
* The following macros load words from an array of bytes with
|
||||
* different types of endianness, and vice versa.
|
||||
*/
|
||||
|
||||
#define ECRYPT_DEFAULT_BTOW
|
||||
|
||||
#if(!defined(ECRYPT_UNKNOWN) && defined(ECRYPT_I8T_IS_BYTE))
|
||||
|
||||
#define U8TO16_LITTLE(p) U16TO16_LITTLE(((u16*)(p))[0])
|
||||
#define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0])
|
||||
#define U8TO64_LITTLE(p) U64TO64_LITTLE(((u64*)(p))[0])
|
||||
|
||||
#define U8TO16_BIG(p) U16TO16_BIG(((u16*)(p))[0])
|
||||
#define U8TO32_BIG(p) U32TO32_BIG(((u32*)(p))[0])
|
||||
#define U8TO64_BIG(p) U64TO64_BIG(((u64*)(p))[0])
|
||||
|
||||
#define U16TO8_LITTLE(p, v) (((u16*)(p))[0] = U16TO16_LITTLE(v))
|
||||
#define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v))
|
||||
#define U64TO8_LITTLE(p, v) (((u64*)(p))[0] = U64TO64_LITTLE(v))
|
||||
|
||||
#define U16TO8_BIG(p, v) (((u16*)(p))[0] = U16TO16_BIG(v))
|
||||
#define U32TO8_BIG(p, v) (((u32*)(p))[0] = U32TO32_BIG(v))
|
||||
#define U64TO8_BIG(p, v) (((u64*)(p))[0] = U64TO64_BIG(v))
|
||||
|
||||
#else
|
||||
|
||||
#define U8TO16_LITTLE(p) (((u16)((p)[0])) | ((u16)((p)[1]) << 8))
|
||||
|
||||
#define U8TO32_LITTLE(p) \
|
||||
(((u32)((p)[0])) | ((u32)((p)[1]) << 8) | ((u32)((p)[2]) << 16) | ((u32)((p)[3]) << 24))
|
||||
|
||||
#ifdef ECRYPT_NATIVE64
|
||||
#define U8TO64_LITTLE(p) \
|
||||
(((u64)((p)[0])) | ((u64)((p)[1]) << 8) | ((u64)((p)[2]) << 16) | ((u64)((p)[3]) << 24) | \
|
||||
((u64)((p)[4]) << 32) | ((u64)((p)[5]) << 40) | ((u64)((p)[6]) << 48) | \
|
||||
((u64)((p)[7]) << 56))
|
||||
#else
|
||||
#define U8TO64_LITTLE(p) ((u64)U8TO32_LITTLE(p) | ((u64)U8TO32_LITTLE((p) + 4) << 32))
|
||||
#endif
|
||||
|
||||
#define U8TO16_BIG(p) (((u16)((p)[0]) << 8) | ((u16)((p)[1])))
|
||||
|
||||
#define U8TO32_BIG(p) \
|
||||
(((u32)((p)[0]) << 24) | ((u32)((p)[1]) << 16) | ((u32)((p)[2]) << 8) | ((u32)((p)[3])))
|
||||
|
||||
#ifdef ECRYPT_NATIVE64
|
||||
#define U8TO64_BIG(p) \
|
||||
(((u64)((p)[0]) << 56) | ((u64)((p)[1]) << 48) | ((u64)((p)[2]) << 40) | \
|
||||
((u64)((p)[3]) << 32) | ((u64)((p)[4]) << 24) | ((u64)((p)[5]) << 16) | \
|
||||
((u64)((p)[6]) << 8) | ((u64)((p)[7])))
|
||||
#else
|
||||
#define U8TO64_BIG(p) (((u64)U8TO32_BIG(p) << 32) | (u64)U8TO32_BIG((p) + 4))
|
||||
#endif
|
||||
|
||||
#define U16TO8_LITTLE(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v)); \
|
||||
(p)[1] = U8V((v) >> 8); \
|
||||
} while(0)
|
||||
|
||||
#define U32TO8_LITTLE(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v)); \
|
||||
(p)[1] = U8V((v) >> 8); \
|
||||
(p)[2] = U8V((v) >> 16); \
|
||||
(p)[3] = U8V((v) >> 24); \
|
||||
} while(0)
|
||||
|
||||
#ifdef ECRYPT_NATIVE64
|
||||
#define U64TO8_LITTLE(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v)); \
|
||||
(p)[1] = U8V((v) >> 8); \
|
||||
(p)[2] = U8V((v) >> 16); \
|
||||
(p)[3] = U8V((v) >> 24); \
|
||||
(p)[4] = U8V((v) >> 32); \
|
||||
(p)[5] = U8V((v) >> 40); \
|
||||
(p)[6] = U8V((v) >> 48); \
|
||||
(p)[7] = U8V((v) >> 56); \
|
||||
} while(0)
|
||||
#else
|
||||
#define U64TO8_LITTLE(p, v) \
|
||||
do { \
|
||||
U32TO8_LITTLE((p), U32V((v))); \
|
||||
U32TO8_LITTLE((p) + 4, U32V((v) >> 32)); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#define U16TO8_BIG(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v)); \
|
||||
(p)[1] = U8V((v) >> 8); \
|
||||
} while(0)
|
||||
|
||||
#define U32TO8_BIG(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v) >> 24); \
|
||||
(p)[1] = U8V((v) >> 16); \
|
||||
(p)[2] = U8V((v) >> 8); \
|
||||
(p)[3] = U8V((v)); \
|
||||
} while(0)
|
||||
|
||||
#ifdef ECRYPT_NATIVE64
|
||||
#define U64TO8_BIG(p, v) \
|
||||
do { \
|
||||
(p)[0] = U8V((v) >> 56); \
|
||||
(p)[1] = U8V((v) >> 48); \
|
||||
(p)[2] = U8V((v) >> 40); \
|
||||
(p)[3] = U8V((v) >> 32); \
|
||||
(p)[4] = U8V((v) >> 24); \
|
||||
(p)[5] = U8V((v) >> 16); \
|
||||
(p)[6] = U8V((v) >> 8); \
|
||||
(p)[7] = U8V((v)); \
|
||||
} while(0)
|
||||
#else
|
||||
#define U64TO8_BIG(p, v) \
|
||||
do { \
|
||||
U32TO8_BIG((p), U32V((v) >> 32)); \
|
||||
U32TO8_BIG((p) + 4, U32V((v))); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "ecrypt_machine.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define AT_LEAST_ONE(n) (((n) < 1) ? 1 : (n))
|
||||
|
||||
#define ALIGN(t, v, n) \
|
||||
union { \
|
||||
t b[n]; \
|
||||
MAXT l[AT_LEAST_ONE(n * sizeof(t) / sizeof(MAXT))]; \
|
||||
} v
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
@@ -1,282 +0,0 @@
|
||||
#define ECRYPT_VARIANT 1
|
||||
#define ECRYPT_API
|
||||
/* ecrypt_sync.h */
|
||||
|
||||
/*
|
||||
* Header file for synchronous stream ciphers without authentication
|
||||
* mechanism.
|
||||
*
|
||||
* *** Please only edit parts marked with "[edit]". ***
|
||||
*/
|
||||
|
||||
#ifndef ECRYPT_SYNC
|
||||
#define ECRYPT_SYNC
|
||||
|
||||
#include "ecrypt_types.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Cipher parameters */
|
||||
|
||||
/*
|
||||
* The name of your cipher.
|
||||
*/
|
||||
#define ECRYPT_NAME "ChaCha20"
|
||||
#define ECRYPT_PROFILE "_____"
|
||||
|
||||
/*
|
||||
* Specify which key and IV sizes are supported by your cipher. A user
|
||||
* should be able to enumerate the supported sizes by running the
|
||||
* following code:
|
||||
*
|
||||
* for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i)
|
||||
* {
|
||||
* keysize = ECRYPT_KEYSIZE(i);
|
||||
*
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* All sizes are in bits.
|
||||
*/
|
||||
|
||||
#define ECRYPT_MAXKEYSIZE 256 /* [edit] */
|
||||
#define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */
|
||||
|
||||
#define ECRYPT_MAXIVSIZE 64 /* [edit] */
|
||||
#define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Data structures */
|
||||
|
||||
/*
|
||||
* ECRYPT_ctx is the structure containing the representation of the
|
||||
* internal state of your cipher.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
u32 input[16]; /* could be compressed */
|
||||
/*
|
||||
* [edit]
|
||||
*
|
||||
* Put here all state variable needed during the encryption process.
|
||||
*/
|
||||
} ECRYPT_ctx;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Mandatory functions */
|
||||
|
||||
/*
|
||||
* Key and message independent initialization. This function will be
|
||||
* called once when the program starts (e.g., to build expanded S-box
|
||||
* tables).
|
||||
*/
|
||||
void ECRYPT_init(void);
|
||||
|
||||
/*
|
||||
* Key setup. It is the user's responsibility to select the values of
|
||||
* keysize and ivsize from the set of supported values specified
|
||||
* above.
|
||||
*/
|
||||
void ECRYPT_keysetup(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* key,
|
||||
u32 keysize, /* Key size in bits. */
|
||||
u32 ivsize); /* IV size in bits. */
|
||||
|
||||
/*
|
||||
* IV setup. After having called ECRYPT_keysetup(), the user is
|
||||
* allowed to call ECRYPT_ivsetup() different times in order to
|
||||
* encrypt/decrypt different messages with the same key but different
|
||||
* IV's. ECRYPT_ivsetup() also sets block counter to zero.
|
||||
*/
|
||||
void ECRYPT_ivsetup(ECRYPT_ctx* ctx, const u8* iv);
|
||||
|
||||
/*
|
||||
* Block counter setup. It is used only for special purposes,
|
||||
* since block counter is usually initialized with ECRYPT_ivsetup.
|
||||
* ECRYPT_ctrsetup has to be called after ECRYPT_ivsetup.
|
||||
*/
|
||||
void ECRYPT_ctrsetup(ECRYPT_ctx* ctx, const u8* ctr);
|
||||
|
||||
/*
|
||||
* Encryption/decryption of arbitrary length messages.
|
||||
*
|
||||
* For efficiency reasons, the API provides two types of
|
||||
* encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function
|
||||
* (declared here) encrypts byte strings of arbitrary length, while
|
||||
* the ECRYPT_encrypt_blocks() function (defined later) only accepts
|
||||
* lengths which are multiples of ECRYPT_BLOCKLENGTH.
|
||||
*
|
||||
* The user is allowed to make multiple calls to
|
||||
* ECRYPT_encrypt_blocks() to incrementally encrypt a long message,
|
||||
* but he is NOT allowed to make additional encryption calls once he
|
||||
* has called ECRYPT_encrypt_bytes() (unless he starts a new message
|
||||
* of course). For example, this sequence of calls is acceptable:
|
||||
*
|
||||
* ECRYPT_keysetup();
|
||||
*
|
||||
* ECRYPT_ivsetup();
|
||||
* ECRYPT_encrypt_blocks();
|
||||
* ECRYPT_encrypt_blocks();
|
||||
* ECRYPT_encrypt_bytes();
|
||||
*
|
||||
* ECRYPT_ivsetup();
|
||||
* ECRYPT_encrypt_blocks();
|
||||
* ECRYPT_encrypt_blocks();
|
||||
*
|
||||
* ECRYPT_ivsetup();
|
||||
* ECRYPT_encrypt_bytes();
|
||||
*
|
||||
* The following sequence is not:
|
||||
*
|
||||
* ECRYPT_keysetup();
|
||||
* ECRYPT_ivsetup();
|
||||
* ECRYPT_encrypt_blocks();
|
||||
* ECRYPT_encrypt_bytes();
|
||||
* ECRYPT_encrypt_blocks();
|
||||
*/
|
||||
|
||||
void ECRYPT_encrypt_bytes(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* plaintext,
|
||||
u8* ciphertext,
|
||||
u32 msglen); /* Message length in bytes. */
|
||||
|
||||
void ECRYPT_decrypt_bytes(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* ciphertext,
|
||||
u8* plaintext,
|
||||
u32 msglen); /* Message length in bytes. */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Optional features */
|
||||
|
||||
/*
|
||||
* For testing purposes it can sometimes be useful to have a function
|
||||
* which immediately generates keystream without having to provide it
|
||||
* with a zero plaintext. If your cipher cannot provide this function
|
||||
* (e.g., because it is not strictly a synchronous cipher), please
|
||||
* reset the ECRYPT_GENERATES_KEYSTREAM flag.
|
||||
*/
|
||||
|
||||
#define ECRYPT_GENERATES_KEYSTREAM
|
||||
#ifdef ECRYPT_GENERATES_KEYSTREAM
|
||||
|
||||
void ECRYPT_keystream_bytes(
|
||||
ECRYPT_ctx* ctx,
|
||||
u8* keystream,
|
||||
u32 length); /* Length of keystream in bytes. */
|
||||
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Optional optimizations */
|
||||
|
||||
/*
|
||||
* By default, the functions in this section are implemented using
|
||||
* calls to functions declared above. However, you might want to
|
||||
* implement them differently for performance reasons.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All-in-one encryption/decryption of (short) packets.
|
||||
*
|
||||
* The default definitions of these functions can be found in
|
||||
* "ecrypt-sync.c". If you want to implement them differently, please
|
||||
* undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag.
|
||||
*/
|
||||
#define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */
|
||||
|
||||
void ECRYPT_encrypt_packet(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* iv,
|
||||
const u8* plaintext,
|
||||
u8* ciphertext,
|
||||
u32 msglen);
|
||||
|
||||
void ECRYPT_decrypt_packet(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* iv,
|
||||
const u8* ciphertext,
|
||||
u8* plaintext,
|
||||
u32 msglen);
|
||||
|
||||
/*
|
||||
* Encryption/decryption of blocks.
|
||||
*
|
||||
* By default, these functions are defined as macros. If you want to
|
||||
* provide a different implementation, please undef the
|
||||
* ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions
|
||||
* declared below.
|
||||
*/
|
||||
|
||||
#define ECRYPT_BLOCKLENGTH 64 /* [edit] */
|
||||
|
||||
#define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */
|
||||
#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS
|
||||
|
||||
#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \
|
||||
ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, (blocks)*ECRYPT_BLOCKLENGTH)
|
||||
|
||||
#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \
|
||||
ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, (blocks)*ECRYPT_BLOCKLENGTH)
|
||||
|
||||
#ifdef ECRYPT_GENERATES_KEYSTREAM
|
||||
|
||||
#define ECRYPT_keystream_blocks(ctx, keystream, blocks) \
|
||||
ECRYPT_keystream_bytes(ctx, keystream, (blocks)*ECRYPT_BLOCKLENGTH)
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
void ECRYPT_encrypt_blocks(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* plaintext,
|
||||
u8* ciphertext,
|
||||
u32 blocks); /* Message length in blocks. */
|
||||
|
||||
void ECRYPT_decrypt_blocks(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* ciphertext,
|
||||
u8* plaintext,
|
||||
u32 blocks); /* Message length in blocks. */
|
||||
|
||||
#ifdef ECRYPT_GENERATES_KEYSTREAM
|
||||
|
||||
void ECRYPT_keystream_blocks(
|
||||
ECRYPT_ctx* ctx,
|
||||
const u8* keystream,
|
||||
u32 blocks); /* Keystream length in blocks. */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If your cipher can be implemented in different ways, you can use
|
||||
* the ECRYPT_VARIANT parameter to allow the user to choose between
|
||||
* them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please
|
||||
* only use this possibility if you really think it could make a
|
||||
* significant difference and keep the number of variants
|
||||
* (ECRYPT_MAXVARIANT) as small as possible (definitely not more than
|
||||
* 10). Note also that all variants should have exactly the same
|
||||
* external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.).
|
||||
*/
|
||||
#define ECRYPT_MAXVARIANT 1 /* [edit] */
|
||||
|
||||
#ifndef ECRYPT_VARIANT
|
||||
#define ECRYPT_VARIANT 1
|
||||
#endif
|
||||
|
||||
#if(ECRYPT_VARIANT > ECRYPT_MAXVARIANT)
|
||||
#error this variant does not exist
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
/* ecrypt_types.h */
|
||||
|
||||
/*
|
||||
* *** Please do not edit this file. ***
|
||||
*
|
||||
* The default macros can be overridden for specific architectures by
|
||||
* editing 'ecrypt_machine.h'.
|
||||
*/
|
||||
|
||||
#ifndef ECRYPT_TYPES
|
||||
#define ECRYPT_TYPES
|
||||
|
||||
#include "ecrypt_config.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* The following types are defined (if available):
|
||||
*
|
||||
* u8: unsigned integer type, at least 8 bits
|
||||
* u16: unsigned integer type, at least 16 bits
|
||||
* u32: unsigned integer type, at least 32 bits
|
||||
* u64: unsigned integer type, at least 64 bits
|
||||
*
|
||||
* s8, s16, s32, s64 -> signed counterparts of u8, u16, u32, u64
|
||||
*
|
||||
* The selection of minimum-width integer types is taken care of by
|
||||
* 'ecrypt_config.h'. Note: to enable 64-bit types on 32-bit
|
||||
* compilers, it might be necessary to switch from ISO C90 mode to ISO
|
||||
* C99 mode (e.g., gcc -std=c99).
|
||||
*/
|
||||
|
||||
#ifdef I8T
|
||||
typedef signed I8T s8;
|
||||
typedef unsigned I8T u8;
|
||||
#endif
|
||||
|
||||
#ifdef I16T
|
||||
typedef signed I16T s16;
|
||||
typedef unsigned I16T u16;
|
||||
#endif
|
||||
|
||||
#ifdef I32T
|
||||
typedef signed I32T s32;
|
||||
typedef unsigned I32T u32;
|
||||
#endif
|
||||
|
||||
#ifdef I64T
|
||||
typedef signed I64T s64;
|
||||
typedef unsigned I64T u64;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,208 +0,0 @@
|
||||
#include "poly1305_donna.h"
|
||||
#include "poly1305_donna_32.h"
|
||||
|
||||
void poly1305_update(poly1305_context* ctx, const unsigned char* m, size_t bytes) {
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
size_t i = 0;
|
||||
|
||||
/* handle leftover */
|
||||
if(st->leftover) {
|
||||
size_t want = (poly1305_block_size - st->leftover);
|
||||
if(want > bytes) want = bytes;
|
||||
for(i = 0; i < want; i++) st->buffer[st->leftover + i] = m[i];
|
||||
bytes -= want;
|
||||
m += want;
|
||||
st->leftover += want;
|
||||
if(st->leftover < poly1305_block_size) return;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
st->leftover = 0;
|
||||
}
|
||||
|
||||
/* process full blocks */
|
||||
if(bytes >= poly1305_block_size) {
|
||||
size_t want = (bytes & ~(poly1305_block_size - 1));
|
||||
poly1305_blocks(st, m, want);
|
||||
m += want;
|
||||
bytes -= want;
|
||||
}
|
||||
|
||||
/* store leftover */
|
||||
if(bytes) {
|
||||
for(i = 0; i < bytes; i++) st->buffer[st->leftover + i] = m[i];
|
||||
st->leftover += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
void poly1305_auth(
|
||||
unsigned char mac[16],
|
||||
const unsigned char* m,
|
||||
size_t bytes,
|
||||
const unsigned char key[32]) {
|
||||
poly1305_context ctx = {0};
|
||||
poly1305_init(&ctx, key);
|
||||
poly1305_update(&ctx, m, bytes);
|
||||
poly1305_finish(&ctx, mac);
|
||||
}
|
||||
|
||||
int poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]) {
|
||||
size_t i = 0;
|
||||
unsigned int dif = 0;
|
||||
for(i = 0; i < 16; i++) dif |= (mac1[i] ^ mac2[i]);
|
||||
dif = (dif - 1) >> ((sizeof(unsigned int) * 8) - 1);
|
||||
return (dif & 1);
|
||||
}
|
||||
|
||||
/* test a few basic operations */
|
||||
int poly1305_power_on_self_test(void) {
|
||||
/* example from nacl */
|
||||
static const unsigned char nacl_key[32] = {
|
||||
0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, 0x6d, 0x11, 0xc2,
|
||||
0xcb, 0x21, 0x4d, 0x3c, 0x25, 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23,
|
||||
0x4e, 0x65, 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80,
|
||||
};
|
||||
|
||||
static const unsigned char nacl_msg[131] = {
|
||||
0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76,
|
||||
0xce, 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1,
|
||||
0x18, 0x6a, 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, 0xf0, 0x11, 0xec,
|
||||
0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, 0x27, 0x0d, 0x6f, 0xb8,
|
||||
0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, 0xb9, 0x32, 0x16,
|
||||
0x45, 0x48, 0xe5, 0x26, 0xae, 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b,
|
||||
0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 0x56,
|
||||
0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
|
||||
0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, 0xe3, 0x55, 0xa5};
|
||||
|
||||
static const unsigned char nacl_mac[16] = {
|
||||
0xf3,
|
||||
0xff,
|
||||
0xc7,
|
||||
0x70,
|
||||
0x3f,
|
||||
0x94,
|
||||
0x00,
|
||||
0xe5,
|
||||
0x2a,
|
||||
0x7d,
|
||||
0xfb,
|
||||
0x4b,
|
||||
0x3d,
|
||||
0x33,
|
||||
0x05,
|
||||
0xd9};
|
||||
|
||||
/* generates a final value of (2^130 - 2) == 3 */
|
||||
static const unsigned char wrap_key[32] = {
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char wrap_msg[16] = {
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff};
|
||||
|
||||
static const unsigned char wrap_mac[16] = {
|
||||
0x03,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
|
||||
/*
|
||||
mac of the macs of messages of length 0 to 256, where the key and messages
|
||||
have all their values set to the length
|
||||
*/
|
||||
static const unsigned char total_key[32] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
static const unsigned char total_mac[16] = {
|
||||
0x64,
|
||||
0xaf,
|
||||
0xe2,
|
||||
0xe8,
|
||||
0xd6,
|
||||
0xad,
|
||||
0x7b,
|
||||
0xbd,
|
||||
0xd2,
|
||||
0x87,
|
||||
0xf9,
|
||||
0x7c,
|
||||
0x44,
|
||||
0x62,
|
||||
0x3d,
|
||||
0x39};
|
||||
|
||||
poly1305_context ctx = {0};
|
||||
poly1305_context total_ctx = {0};
|
||||
unsigned char all_key[32] = {0};
|
||||
unsigned char all_msg[256] = {0};
|
||||
unsigned char mac[16] = {0};
|
||||
size_t i = 0, j = 0;
|
||||
int result = 1;
|
||||
|
||||
for(i = 0; i < sizeof(mac); i++) mac[i] = 0;
|
||||
poly1305_auth(mac, nacl_msg, sizeof(nacl_msg), nacl_key);
|
||||
result &= poly1305_verify(nacl_mac, mac);
|
||||
|
||||
for(i = 0; i < sizeof(mac); i++) mac[i] = 0;
|
||||
poly1305_init(&ctx, nacl_key);
|
||||
poly1305_update(&ctx, nacl_msg + 0, 32);
|
||||
poly1305_update(&ctx, nacl_msg + 32, 64);
|
||||
poly1305_update(&ctx, nacl_msg + 96, 16);
|
||||
poly1305_update(&ctx, nacl_msg + 112, 8);
|
||||
poly1305_update(&ctx, nacl_msg + 120, 4);
|
||||
poly1305_update(&ctx, nacl_msg + 124, 2);
|
||||
poly1305_update(&ctx, nacl_msg + 126, 1);
|
||||
poly1305_update(&ctx, nacl_msg + 127, 1);
|
||||
poly1305_update(&ctx, nacl_msg + 128, 1);
|
||||
poly1305_update(&ctx, nacl_msg + 129, 1);
|
||||
poly1305_update(&ctx, nacl_msg + 130, 1);
|
||||
poly1305_finish(&ctx, mac);
|
||||
result &= poly1305_verify(nacl_mac, mac);
|
||||
|
||||
for(i = 0; i < sizeof(mac); i++) mac[i] = 0;
|
||||
poly1305_auth(mac, wrap_msg, sizeof(wrap_msg), wrap_key);
|
||||
result &= poly1305_verify(wrap_mac, mac);
|
||||
|
||||
poly1305_init(&total_ctx, total_key);
|
||||
for(i = 0; i < 256; i++) {
|
||||
/* set key and message to 'i,i,i..' */
|
||||
for(j = 0; j < sizeof(all_key); j++) all_key[j] = i;
|
||||
for(j = 0; j < i; j++) all_msg[j] = i;
|
||||
poly1305_auth(mac, all_msg, i, all_key);
|
||||
poly1305_update(&total_ctx, mac, 16);
|
||||
}
|
||||
poly1305_finish(&total_ctx, mac);
|
||||
result &= poly1305_verify(total_mac, mac);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef POLY1305_DONNA_H
|
||||
#define POLY1305_DONNA_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct poly1305_context {
|
||||
size_t aligner;
|
||||
unsigned char opaque[136];
|
||||
} poly1305_context;
|
||||
|
||||
void poly1305_init(poly1305_context* ctx, const unsigned char key[32]);
|
||||
void poly1305_update(poly1305_context* ctx, const unsigned char* m, size_t bytes);
|
||||
void poly1305_finish(poly1305_context* ctx, unsigned char mac[16]);
|
||||
void poly1305_auth(
|
||||
unsigned char mac[16],
|
||||
const unsigned char* m,
|
||||
size_t bytes,
|
||||
const unsigned char key[32]);
|
||||
|
||||
int poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]);
|
||||
int poly1305_power_on_self_test(void);
|
||||
|
||||
#endif /* POLY1305_DONNA_H */
|
||||
@@ -1,252 +0,0 @@
|
||||
/*
|
||||
poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define POLY1305_NOINLINE __declspec(noinline)
|
||||
#elif defined(__GNUC__)
|
||||
#define POLY1305_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
#define POLY1305_NOINLINE
|
||||
#endif
|
||||
|
||||
#define poly1305_block_size 16
|
||||
|
||||
/* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */
|
||||
typedef struct poly1305_state_internal_t {
|
||||
unsigned long r[5];
|
||||
unsigned long h[5];
|
||||
unsigned long pad[4];
|
||||
size_t leftover;
|
||||
unsigned char buffer[poly1305_block_size];
|
||||
unsigned char final;
|
||||
} poly1305_state_internal_t;
|
||||
|
||||
/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */
|
||||
static unsigned long U8TO32(const unsigned char* p) {
|
||||
return (
|
||||
((unsigned long)(p[0] & 0xff)) | ((unsigned long)(p[1] & 0xff) << 8) |
|
||||
((unsigned long)(p[2] & 0xff) << 16) | ((unsigned long)(p[3] & 0xff) << 24));
|
||||
}
|
||||
|
||||
/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */
|
||||
static void U32TO8(unsigned char* p, unsigned long v) {
|
||||
p[0] = (v)&0xff;
|
||||
p[1] = (v >> 8) & 0xff;
|
||||
p[2] = (v >> 16) & 0xff;
|
||||
p[3] = (v >> 24) & 0xff;
|
||||
}
|
||||
|
||||
void poly1305_init(poly1305_context* ctx, const unsigned char key[32]) {
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
|
||||
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
|
||||
st->r[0] = (U8TO32(&key[0])) & 0x3ffffff;
|
||||
st->r[1] = (U8TO32(&key[3]) >> 2) & 0x3ffff03;
|
||||
st->r[2] = (U8TO32(&key[6]) >> 4) & 0x3ffc0ff;
|
||||
st->r[3] = (U8TO32(&key[9]) >> 6) & 0x3f03fff;
|
||||
st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
|
||||
|
||||
/* h = 0 */
|
||||
st->h[0] = 0;
|
||||
st->h[1] = 0;
|
||||
st->h[2] = 0;
|
||||
st->h[3] = 0;
|
||||
st->h[4] = 0;
|
||||
|
||||
/* save pad for later */
|
||||
st->pad[0] = U8TO32(&key[16]);
|
||||
st->pad[1] = U8TO32(&key[20]);
|
||||
st->pad[2] = U8TO32(&key[24]);
|
||||
st->pad[3] = U8TO32(&key[28]);
|
||||
|
||||
st->leftover = 0;
|
||||
st->final = 0;
|
||||
}
|
||||
|
||||
static void poly1305_blocks(poly1305_state_internal_t* st, const unsigned char* m, size_t bytes) {
|
||||
const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */
|
||||
unsigned long r0, r1, r2, r3, r4;
|
||||
unsigned long s1, s2, s3, s4;
|
||||
unsigned long h0, h1, h2, h3, h4;
|
||||
unsigned long long d0, d1, d2, d3, d4;
|
||||
unsigned long c;
|
||||
|
||||
r0 = st->r[0];
|
||||
r1 = st->r[1];
|
||||
r2 = st->r[2];
|
||||
r3 = st->r[3];
|
||||
r4 = st->r[4];
|
||||
|
||||
s1 = r1 * 5;
|
||||
s2 = r2 * 5;
|
||||
s3 = r3 * 5;
|
||||
s4 = r4 * 5;
|
||||
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
while(bytes >= poly1305_block_size) {
|
||||
/* h += m[i] */
|
||||
h0 += (U8TO32(m + 0)) & 0x3ffffff;
|
||||
h1 += (U8TO32(m + 3) >> 2) & 0x3ffffff;
|
||||
h2 += (U8TO32(m + 6) >> 4) & 0x3ffffff;
|
||||
h3 += (U8TO32(m + 9) >> 6) & 0x3ffffff;
|
||||
h4 += (U8TO32(m + 12) >> 8) | hibit;
|
||||
|
||||
/* h *= r */
|
||||
d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) +
|
||||
((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) +
|
||||
((unsigned long long)h4 * s1);
|
||||
d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) +
|
||||
((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) +
|
||||
((unsigned long long)h4 * s2);
|
||||
d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) +
|
||||
((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) +
|
||||
((unsigned long long)h4 * s3);
|
||||
d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) +
|
||||
((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) +
|
||||
((unsigned long long)h4 * s4);
|
||||
d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) +
|
||||
((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) +
|
||||
((unsigned long long)h4 * r0);
|
||||
|
||||
/* (partial) h %= p */
|
||||
c = (unsigned long)(d0 >> 26);
|
||||
h0 = (unsigned long)d0 & 0x3ffffff;
|
||||
d1 += c;
|
||||
c = (unsigned long)(d1 >> 26);
|
||||
h1 = (unsigned long)d1 & 0x3ffffff;
|
||||
d2 += c;
|
||||
c = (unsigned long)(d2 >> 26);
|
||||
h2 = (unsigned long)d2 & 0x3ffffff;
|
||||
d3 += c;
|
||||
c = (unsigned long)(d3 >> 26);
|
||||
h3 = (unsigned long)d3 & 0x3ffffff;
|
||||
d4 += c;
|
||||
c = (unsigned long)(d4 >> 26);
|
||||
h4 = (unsigned long)d4 & 0x3ffffff;
|
||||
h0 += c * 5;
|
||||
c = (h0 >> 26);
|
||||
h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
m += poly1305_block_size;
|
||||
bytes -= poly1305_block_size;
|
||||
}
|
||||
|
||||
st->h[0] = h0;
|
||||
st->h[1] = h1;
|
||||
st->h[2] = h2;
|
||||
st->h[3] = h3;
|
||||
st->h[4] = h4;
|
||||
}
|
||||
|
||||
POLY1305_NOINLINE void poly1305_finish(poly1305_context* ctx, unsigned char mac[16]) {
|
||||
poly1305_state_internal_t* st = (poly1305_state_internal_t*)ctx;
|
||||
unsigned long h0, h1, h2, h3, h4, c;
|
||||
unsigned long g0, g1, g2, g3, g4;
|
||||
unsigned long long f;
|
||||
unsigned long mask;
|
||||
|
||||
/* process the remaining block */
|
||||
if(st->leftover) {
|
||||
size_t i = st->leftover;
|
||||
st->buffer[i++] = 1;
|
||||
for(; i < poly1305_block_size; i++) st->buffer[i] = 0;
|
||||
st->final = 1;
|
||||
poly1305_blocks(st, st->buffer, poly1305_block_size);
|
||||
}
|
||||
|
||||
/* fully carry h */
|
||||
h0 = st->h[0];
|
||||
h1 = st->h[1];
|
||||
h2 = st->h[2];
|
||||
h3 = st->h[3];
|
||||
h4 = st->h[4];
|
||||
|
||||
c = h1 >> 26;
|
||||
h1 = h1 & 0x3ffffff;
|
||||
h2 += c;
|
||||
c = h2 >> 26;
|
||||
h2 = h2 & 0x3ffffff;
|
||||
h3 += c;
|
||||
c = h3 >> 26;
|
||||
h3 = h3 & 0x3ffffff;
|
||||
h4 += c;
|
||||
c = h4 >> 26;
|
||||
h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5;
|
||||
c = h0 >> 26;
|
||||
h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
/* compute h + -p */
|
||||
g0 = h0 + 5;
|
||||
c = g0 >> 26;
|
||||
g0 &= 0x3ffffff;
|
||||
g1 = h1 + c;
|
||||
c = g1 >> 26;
|
||||
g1 &= 0x3ffffff;
|
||||
g2 = h2 + c;
|
||||
c = g2 >> 26;
|
||||
g2 &= 0x3ffffff;
|
||||
g3 = h3 + c;
|
||||
c = g3 >> 26;
|
||||
g3 &= 0x3ffffff;
|
||||
g4 = h4 + c - (1UL << 26);
|
||||
|
||||
/* select h if h < p, or h + -p if h >= p */
|
||||
mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
|
||||
g0 &= mask;
|
||||
g1 &= mask;
|
||||
g2 &= mask;
|
||||
g3 &= mask;
|
||||
g4 &= mask;
|
||||
mask = ~mask;
|
||||
h0 = (h0 & mask) | g0;
|
||||
h1 = (h1 & mask) | g1;
|
||||
h2 = (h2 & mask) | g2;
|
||||
h3 = (h3 & mask) | g3;
|
||||
h4 = (h4 & mask) | g4;
|
||||
|
||||
/* h = h % (2^128) */
|
||||
h0 = ((h0) | (h1 << 26)) & 0xffffffff;
|
||||
h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
|
||||
h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
|
||||
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
|
||||
|
||||
/* mac = (h + pad) % (2^128) */
|
||||
f = (unsigned long long)h0 + st->pad[0];
|
||||
h0 = (unsigned long)f;
|
||||
f = (unsigned long long)h1 + st->pad[1] + (f >> 32);
|
||||
h1 = (unsigned long)f;
|
||||
f = (unsigned long long)h2 + st->pad[2] + (f >> 32);
|
||||
h2 = (unsigned long)f;
|
||||
f = (unsigned long long)h3 + st->pad[3] + (f >> 32);
|
||||
h3 = (unsigned long)f;
|
||||
|
||||
U32TO8(mac + 0, h0);
|
||||
U32TO8(mac + 4, h1);
|
||||
U32TO8(mac + 8, h2);
|
||||
U32TO8(mac + 12, h3);
|
||||
|
||||
/* zero out the state */
|
||||
st->h[0] = 0;
|
||||
st->h[1] = 0;
|
||||
st->h[2] = 0;
|
||||
st->h[3] = 0;
|
||||
st->h[4] = 0;
|
||||
st->r[0] = 0;
|
||||
st->r[1] = 0;
|
||||
st->r[2] = 0;
|
||||
st->r[3] = 0;
|
||||
st->r[4] = 0;
|
||||
st->pad[0] = 0;
|
||||
st->pad[1] = 0;
|
||||
st->pad[2] = 0;
|
||||
st->pad[3] = 0;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Implementation of the ChaCha20 + Poly1305 AEAD construction
|
||||
// as described in RFC 7539.
|
||||
|
||||
#include <string.h>
|
||||
#include "rfc7539.h"
|
||||
#include "ecrypt_portable.h"
|
||||
|
||||
// Initialize the ChaCha20 + Poly1305 context for encryption or decryption
|
||||
// using a 32 byte key and 12 byte nonce as in the RFC 7539 style.
|
||||
void rfc7539_init(chacha20poly1305_ctx* ctx, const uint8_t key[32], const uint8_t nonce[12]) {
|
||||
unsigned char block0[64] = {0};
|
||||
|
||||
ECRYPT_keysetup(&ctx->chacha20, key, 256, 16);
|
||||
ctx->chacha20.input[12] = 0;
|
||||
ctx->chacha20.input[13] = U8TO32_LITTLE(nonce + 0);
|
||||
ctx->chacha20.input[14] = U8TO32_LITTLE(nonce + 4);
|
||||
ctx->chacha20.input[15] = U8TO32_LITTLE(nonce + 8);
|
||||
|
||||
// Encrypt 64 bytes of zeros and use the first 32 bytes
|
||||
// as the Poly1305 key.
|
||||
ECRYPT_encrypt_bytes(&ctx->chacha20, block0, block0, 64);
|
||||
poly1305_init(&ctx->poly1305, block0);
|
||||
}
|
||||
|
||||
// Include authenticated data in the Poly1305 MAC using the RFC 7539
|
||||
// style with 16 byte padding. This must only be called once and prior
|
||||
// to encryption or decryption.
|
||||
void rfc7539_auth(chacha20poly1305_ctx* ctx, const uint8_t* in, size_t n) {
|
||||
uint8_t padding[16] = {0};
|
||||
poly1305_update(&ctx->poly1305, in, n);
|
||||
if(n % 16 != 0) poly1305_update(&ctx->poly1305, padding, 16 - n % 16);
|
||||
}
|
||||
|
||||
// Compute RFC 7539-style Poly1305 MAC.
|
||||
void rfc7539_finish(chacha20poly1305_ctx* ctx, int64_t alen, int64_t plen, uint8_t mac[16]) {
|
||||
uint8_t padding[16] = {0};
|
||||
uint8_t lengths[16] = {0};
|
||||
|
||||
memcpy(lengths, &alen, sizeof(int64_t));
|
||||
memcpy(lengths + 8, &plen, sizeof(int64_t));
|
||||
|
||||
if(plen % 16 != 0) poly1305_update(&ctx->poly1305, padding, 16 - plen % 16);
|
||||
poly1305_update(&ctx->poly1305, lengths, 16);
|
||||
|
||||
poly1305_finish(&ctx->poly1305, mac);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef RFC7539_H
|
||||
#define RFC7539_H
|
||||
|
||||
#include "chacha20poly1305.h"
|
||||
|
||||
void rfc7539_init(chacha20poly1305_ctx* ctx, const uint8_t key[32], const uint8_t nonce[12]);
|
||||
void rfc7539_auth(chacha20poly1305_ctx* ctx, const uint8_t* in, size_t n);
|
||||
void rfc7539_finish(chacha20poly1305_ctx* ctx, int64_t alen, int64_t plen, uint8_t mac[16]);
|
||||
|
||||
#endif // RFC7539_H
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "chacha_drbg.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chacha20poly1305/ecrypt_portable.h"
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
#define CHACHA_DRBG_KEY_LENGTH 32
|
||||
#define CHACHA_DRBG_COUNTER_LENGTH 8
|
||||
#define CHACHA_DRBG_IV_LENGTH 8
|
||||
#define CHACHA_DRBG_SEED_LENGTH \
|
||||
(CHACHA_DRBG_KEY_LENGTH + CHACHA_DRBG_COUNTER_LENGTH + CHACHA_DRBG_IV_LENGTH)
|
||||
|
||||
#define MAX(a, b) (a) > (b) ? (a) : (b)
|
||||
|
||||
static void derivation_function(
|
||||
const uint8_t* input1,
|
||||
size_t input1_length,
|
||||
const uint8_t* input2,
|
||||
size_t input2_length,
|
||||
uint8_t* output,
|
||||
size_t output_length) {
|
||||
// Implementation of Hash_df from NIST SP 800-90A
|
||||
uint32_t block_count = (output_length - 1) / SHA256_DIGEST_LENGTH + 1;
|
||||
size_t partial_block_length = output_length % SHA256_DIGEST_LENGTH;
|
||||
assert(block_count <= 255);
|
||||
|
||||
uint32_t output_length_bits = output_length * 8;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(output_length_bits, output_length_bits);
|
||||
#endif
|
||||
|
||||
SHA256_CTX ctx = {0};
|
||||
|
||||
for(uint8_t counter = 1; counter <= block_count; counter++) {
|
||||
sha256_Init(&ctx);
|
||||
sha256_Update(&ctx, &counter, sizeof(counter));
|
||||
sha256_Update(&ctx, (uint8_t*)&output_length_bits, sizeof(output_length_bits));
|
||||
sha256_Update(&ctx, input1, input1_length);
|
||||
sha256_Update(&ctx, input2, input2_length);
|
||||
|
||||
if(counter != block_count || partial_block_length == 0) {
|
||||
sha256_Final(&ctx, output);
|
||||
output += SHA256_DIGEST_LENGTH;
|
||||
} else { // last block is partial
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
|
||||
sha256_Final(&ctx, digest);
|
||||
memcpy(output, digest, partial_block_length);
|
||||
memzero(digest, sizeof(digest));
|
||||
}
|
||||
}
|
||||
|
||||
memzero(&ctx, sizeof(ctx));
|
||||
}
|
||||
|
||||
void chacha_drbg_init(
|
||||
CHACHA_DRBG_CTX* ctx,
|
||||
const uint8_t* entropy,
|
||||
size_t entropy_length,
|
||||
const uint8_t* nonce,
|
||||
size_t nonce_length) {
|
||||
uint8_t buffer[MAX(CHACHA_DRBG_KEY_LENGTH, CHACHA_DRBG_IV_LENGTH)] = {0};
|
||||
ECRYPT_keysetup(
|
||||
&ctx->chacha_ctx, buffer, CHACHA_DRBG_KEY_LENGTH * 8, CHACHA_DRBG_IV_LENGTH * 8);
|
||||
ECRYPT_ivsetup(&ctx->chacha_ctx, buffer);
|
||||
|
||||
chacha_drbg_reseed(ctx, entropy, entropy_length, nonce, nonce_length);
|
||||
}
|
||||
|
||||
static void chacha_drbg_update(CHACHA_DRBG_CTX* ctx, const uint8_t data[CHACHA_DRBG_SEED_LENGTH]) {
|
||||
uint8_t seed[CHACHA_DRBG_SEED_LENGTH] = {0};
|
||||
|
||||
if(data)
|
||||
ECRYPT_encrypt_bytes(&ctx->chacha_ctx, data, seed, CHACHA_DRBG_SEED_LENGTH);
|
||||
else
|
||||
ECRYPT_keystream_bytes(&ctx->chacha_ctx, seed, CHACHA_DRBG_SEED_LENGTH);
|
||||
|
||||
ECRYPT_keysetup(&ctx->chacha_ctx, seed, CHACHA_DRBG_KEY_LENGTH * 8, CHACHA_DRBG_IV_LENGTH * 8);
|
||||
|
||||
ECRYPT_ivsetup(&ctx->chacha_ctx, seed + CHACHA_DRBG_KEY_LENGTH + CHACHA_DRBG_COUNTER_LENGTH);
|
||||
|
||||
ECRYPT_ctrsetup(&ctx->chacha_ctx, seed + CHACHA_DRBG_KEY_LENGTH);
|
||||
|
||||
memzero(seed, sizeof(seed));
|
||||
}
|
||||
|
||||
void chacha_drbg_generate(CHACHA_DRBG_CTX* ctx, uint8_t* output, size_t output_length) {
|
||||
assert(output_length < 65536);
|
||||
assert(ctx->reseed_counter + 1 != 0);
|
||||
|
||||
ECRYPT_keystream_bytes(&ctx->chacha_ctx, output, output_length);
|
||||
chacha_drbg_update(ctx, NULL);
|
||||
ctx->reseed_counter++;
|
||||
}
|
||||
|
||||
void chacha_drbg_reseed(
|
||||
CHACHA_DRBG_CTX* ctx,
|
||||
const uint8_t* entropy,
|
||||
size_t entropy_length,
|
||||
const uint8_t* additional_input,
|
||||
size_t additional_input_length) {
|
||||
uint8_t seed[CHACHA_DRBG_SEED_LENGTH] = {0};
|
||||
derivation_function(
|
||||
entropy, entropy_length, additional_input, additional_input_length, seed, sizeof(seed));
|
||||
chacha_drbg_update(ctx, seed);
|
||||
memzero(seed, sizeof(seed));
|
||||
|
||||
ctx->reseed_counter = 1;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __CHACHA_DRBG__
|
||||
#define __CHACHA_DRBG__
|
||||
|
||||
#include "chacha20poly1305/chacha20poly1305.h"
|
||||
#include "sha2.h"
|
||||
|
||||
// A very fast deterministic random bit generator based on CTR_DRBG in NIST SP
|
||||
// 800-90A. Chacha is used instead of a block cipher in the counter mode, SHA256
|
||||
// is used as a derivation function. The highest supported security strength is
|
||||
// at least 256 bits. Reseeding is left up to caller.
|
||||
|
||||
// Length of inputs of chacha_drbg_init (entropy and nonce) or
|
||||
// chacha_drbg_reseed (entropy and additional_input) that fill exactly
|
||||
// block_count blocks of hash function in derivation_function. There is no need
|
||||
// the input to have this length, it's just an optimalization.
|
||||
#define CHACHA_DRBG_OPTIMAL_RESEED_LENGTH(block_count) \
|
||||
((block_count)*SHA256_BLOCK_LENGTH - 1 - 4 - 9)
|
||||
// 1 = sizeof(counter), 4 = sizeof(output_length) in
|
||||
// derivation_function, 9 is length of SHA256 padding of message
|
||||
// aligned to bytes
|
||||
|
||||
typedef struct _CHACHA_DRBG_CTX {
|
||||
ECRYPT_ctx chacha_ctx;
|
||||
uint32_t reseed_counter;
|
||||
} CHACHA_DRBG_CTX;
|
||||
|
||||
void chacha_drbg_init(
|
||||
CHACHA_DRBG_CTX* ctx,
|
||||
const uint8_t* entropy,
|
||||
size_t entropy_length,
|
||||
const uint8_t* nonce,
|
||||
size_t nonce_length);
|
||||
void chacha_drbg_generate(CHACHA_DRBG_CTX* ctx, uint8_t* output, size_t output_length);
|
||||
void chacha_drbg_reseed(
|
||||
CHACHA_DRBG_CTX* ctx,
|
||||
const uint8_t* entropy,
|
||||
size_t entropy_length,
|
||||
const uint8_t* additional_input,
|
||||
size_t additional_input_length);
|
||||
#endif // __CHACHA_DRBG__
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef CHECK_MEM_H
|
||||
#define CHECK_MEM_H
|
||||
|
||||
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 11
|
||||
|
||||
#define _ck_assert_mem(X, Y, L, OP) \
|
||||
do { \
|
||||
const char* _ck_x = (const char*)(void*)(X); \
|
||||
const char* _ck_y = (const char*)(void*)(Y); \
|
||||
size_t _ck_l = (L); \
|
||||
char _ck_x_str[129]; \
|
||||
char _ck_y_str[129]; \
|
||||
static char _ck_hexdigits[] = "0123456789abcdef"; \
|
||||
size_t _ck_i; \
|
||||
for(_ck_i = 0; _ck_i < ((_ck_l > 64) ? 64 : _ck_l); _ck_i++) { \
|
||||
_ck_x_str[_ck_i * 2] = _ck_hexdigits[(_ck_x[_ck_i] >> 4) & 0xF]; \
|
||||
_ck_y_str[_ck_i * 2] = _ck_hexdigits[(_ck_y[_ck_i] >> 4) & 0xF]; \
|
||||
_ck_x_str[_ck_i * 2 + 1] = _ck_hexdigits[_ck_x[_ck_i] & 0xF]; \
|
||||
_ck_y_str[_ck_i * 2 + 1] = _ck_hexdigits[_ck_y[_ck_i] & 0xF]; \
|
||||
} \
|
||||
_ck_x_str[_ck_i * 2] = 0; \
|
||||
_ck_y_str[_ck_i * 2] = 0; \
|
||||
ck_assert_msg( \
|
||||
0 OP memcmp(_ck_y, _ck_x, _ck_l), \
|
||||
"Assertion '" #X #OP #Y "' failed: " #X "==\"%s\", " #Y "==\"%s\"", \
|
||||
_ck_x_str, \
|
||||
_ck_y_str); \
|
||||
} while(0)
|
||||
#define ck_assert_mem_eq(X, Y, L) _ck_assert_mem(X, Y, L, ==)
|
||||
#define ck_assert_mem_ne(X, Y, L) _ck_assert_mem(X, Y, L, !=)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016 Jochen Hoenicke
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "curves.h"
|
||||
|
||||
const char SECP256K1_NAME[] = "secp256k1";
|
||||
const char SECP256K1_DECRED_NAME[] = "secp256k1-decred";
|
||||
const char SECP256K1_GROESTL_NAME[] = "secp256k1-groestl";
|
||||
const char SECP256K1_SMART_NAME[] = "secp256k1-smart";
|
||||
const char NIST256P1_NAME[] = "nist256p1";
|
||||
const char ED25519_NAME[] = "ed25519";
|
||||
const char ED25519_SEED_NAME[] = "ed25519 seed";
|
||||
#if USE_CARDANO
|
||||
const char ED25519_CARDANO_NAME[] = "ed25519 cardano seed";
|
||||
#endif
|
||||
const char ED25519_SHA3_NAME[] = "ed25519-sha3";
|
||||
#if USE_KECCAK
|
||||
const char ED25519_KECCAK_NAME[] = "ed25519-keccak";
|
||||
#endif
|
||||
const char CURVE25519_NAME[] = "curve25519";
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2016 Jochen Hoenicke
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CURVES_H__
|
||||
#define __CURVES_H__
|
||||
|
||||
#include "options.h"
|
||||
|
||||
extern const char SECP256K1_NAME[];
|
||||
extern const char SECP256K1_DECRED_NAME[];
|
||||
extern const char SECP256K1_GROESTL_NAME[];
|
||||
extern const char SECP256K1_SMART_NAME[];
|
||||
extern const char NIST256P1_NAME[];
|
||||
extern const char ED25519_NAME[];
|
||||
extern const char ED25519_SEED_NAME[];
|
||||
extern const char ED25519_CARDANO_NAME[];
|
||||
extern const char ED25519_SHA3_NAME[];
|
||||
#if USE_KECCAK
|
||||
extern const char ED25519_KECCAK_NAME[];
|
||||
#endif
|
||||
extern const char CURVE25519_NAME[];
|
||||
|
||||
#endif
|
||||
1284
applications/external/flipbip/lib/crypto/ecdsa.c
vendored
1284
applications/external/flipbip/lib/crypto/ecdsa.c
vendored
File diff suppressed because it is too large
Load Diff
167
applications/external/flipbip/lib/crypto/ecdsa.h
vendored
167
applications/external/flipbip/lib/crypto/ecdsa.h
vendored
@@ -1,167 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2013-2014 Tomas Dzetkulic
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __ECDSA_H__
|
||||
#define __ECDSA_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bignum.h"
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
// curve point x and y
|
||||
typedef struct {
|
||||
bignum256 x, y;
|
||||
} curve_point;
|
||||
|
||||
typedef struct {
|
||||
bignum256 prime; // prime order of the finite field
|
||||
curve_point G; // initial curve point
|
||||
bignum256 order; // order of G
|
||||
bignum256 order_half; // order of G divided by 2
|
||||
int a; // coefficient 'a' of the elliptic curve
|
||||
bignum256 b; // coefficient 'b' of the elliptic curve
|
||||
|
||||
#if USE_PRECOMPUTED_CP
|
||||
const curve_point cp[64][8];
|
||||
#endif
|
||||
|
||||
} ecdsa_curve;
|
||||
|
||||
// 4 byte prefix + 40 byte data (segwit)
|
||||
// 1 byte prefix + 64 byte data (cashaddr)
|
||||
#define MAX_ADDR_RAW_SIZE 65
|
||||
// bottle neck is cashaddr
|
||||
// segwit is at most 90 characters plus NUL separator
|
||||
// cashaddr: human readable prefix + 1 separator + 104 data + 8 checksum + 1 NUL
|
||||
// we choose 130 as maximum (including NUL character)
|
||||
#define MAX_ADDR_SIZE 130
|
||||
// 4 byte prefix + 32 byte privkey + 1 byte compressed marker
|
||||
#define MAX_WIF_RAW_SIZE (4 + 32 + 1)
|
||||
// (4 + 32 + 1 + 4 [checksum]) * 8 / log2(58) plus NUL.
|
||||
#define MAX_WIF_SIZE (57)
|
||||
|
||||
void point_copy(const curve_point* cp1, curve_point* cp2);
|
||||
void point_add(const ecdsa_curve* curve, const curve_point* cp1, curve_point* cp2);
|
||||
void point_double(const ecdsa_curve* curve, curve_point* cp);
|
||||
int point_multiply(
|
||||
const ecdsa_curve* curve,
|
||||
const bignum256* k,
|
||||
const curve_point* p,
|
||||
curve_point* res);
|
||||
void point_set_infinity(curve_point* p);
|
||||
int point_is_infinity(const curve_point* p);
|
||||
int point_is_equal(const curve_point* p, const curve_point* q);
|
||||
int point_is_negative_of(const curve_point* p, const curve_point* q);
|
||||
int scalar_multiply(const ecdsa_curve* curve, const bignum256* k, curve_point* res);
|
||||
int ecdh_multiply(
|
||||
const ecdsa_curve* curve,
|
||||
const uint8_t* priv_key,
|
||||
const uint8_t* pub_key,
|
||||
uint8_t* session_key);
|
||||
void compress_coords(const curve_point* cp, uint8_t* compressed);
|
||||
void uncompress_coords(const ecdsa_curve* curve, uint8_t odd, const bignum256* x, bignum256* y);
|
||||
int ecdsa_uncompress_pubkey(
|
||||
const ecdsa_curve* curve,
|
||||
const uint8_t* pub_key,
|
||||
uint8_t* uncompressed);
|
||||
|
||||
int ecdsa_sign(
|
||||
const ecdsa_curve* curve,
|
||||
HasherType hasher_sign,
|
||||
const uint8_t* priv_key,
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len,
|
||||
uint8_t* sig,
|
||||
uint8_t* pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int ecdsa_sign_digest(
|
||||
const ecdsa_curve* curve,
|
||||
const uint8_t* priv_key,
|
||||
const uint8_t* digest,
|
||||
uint8_t* sig,
|
||||
uint8_t* pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int ecdsa_get_public_key33(const ecdsa_curve* curve, const uint8_t* priv_key, uint8_t* pub_key);
|
||||
int ecdsa_get_public_key65(const ecdsa_curve* curve, const uint8_t* priv_key, uint8_t* pub_key);
|
||||
void ecdsa_get_pubkeyhash(const uint8_t* pub_key, HasherType hasher_pubkey, uint8_t* pubkeyhash);
|
||||
void ecdsa_get_address_raw(
|
||||
const uint8_t* pub_key,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
uint8_t* addr_raw);
|
||||
void ecdsa_get_address(
|
||||
const uint8_t* pub_key,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
HasherType hasher_base58,
|
||||
char* addr,
|
||||
int addrsize);
|
||||
void ecdsa_get_address_segwit_p2sh_raw(
|
||||
const uint8_t* pub_key,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
uint8_t* addr_raw);
|
||||
void ecdsa_get_address_segwit_p2sh(
|
||||
const uint8_t* pub_key,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
HasherType hasher_base58,
|
||||
char* addr,
|
||||
int addrsize);
|
||||
void ecdsa_get_wif(
|
||||
const uint8_t* priv_key,
|
||||
uint32_t version,
|
||||
HasherType hasher_base58,
|
||||
char* wif,
|
||||
int wifsize);
|
||||
|
||||
int ecdsa_address_decode(
|
||||
const char* addr,
|
||||
uint32_t version,
|
||||
HasherType hasher_base58,
|
||||
uint8_t* out);
|
||||
int ecdsa_read_pubkey(const ecdsa_curve* curve, const uint8_t* pub_key, curve_point* pub);
|
||||
int ecdsa_validate_pubkey(const ecdsa_curve* curve, const curve_point* pub);
|
||||
int ecdsa_verify(
|
||||
const ecdsa_curve* curve,
|
||||
HasherType hasher_sign,
|
||||
const uint8_t* pub_key,
|
||||
const uint8_t* sig,
|
||||
const uint8_t* msg,
|
||||
uint32_t msg_len);
|
||||
int ecdsa_verify_digest(
|
||||
const ecdsa_curve* curve,
|
||||
const uint8_t* pub_key,
|
||||
const uint8_t* sig,
|
||||
const uint8_t* digest);
|
||||
int ecdsa_recover_pub_from_sig(
|
||||
const ecdsa_curve* curve,
|
||||
uint8_t* pub_key,
|
||||
const uint8_t* sig,
|
||||
const uint8_t* digest,
|
||||
int recid);
|
||||
int ecdsa_sig_to_der(const uint8_t* sig, uint8_t* der);
|
||||
int ecdsa_sig_from_der(const uint8_t* der, size_t der_len, uint8_t sig[64]);
|
||||
|
||||
#endif
|
||||
@@ -1,953 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
See: https://github.com/floodyberry/curve25519-donna
|
||||
|
||||
32 bit integer curve25519 implementation
|
||||
*/
|
||||
|
||||
#include "ed25519_donna.h"
|
||||
|
||||
static const uint32_t reduce_mask_25 = (1 << 25) - 1;
|
||||
static const uint32_t reduce_mask_26 = (1 << 26) - 1;
|
||||
|
||||
/* out = in */
|
||||
void curve25519_copy(bignum25519 out, const bignum25519 in) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[4] = in[4];
|
||||
out[5] = in[5];
|
||||
out[6] = in[6];
|
||||
out[7] = in[7];
|
||||
out[8] = in[8];
|
||||
out[9] = in[9];
|
||||
}
|
||||
|
||||
/* out = a + b */
|
||||
void curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
out[2] = a[2] + b[2];
|
||||
out[3] = a[3] + b[3];
|
||||
out[4] = a[4] + b[4];
|
||||
out[5] = a[5] + b[5];
|
||||
out[6] = a[6] + b[6];
|
||||
out[7] = a[7] + b[7];
|
||||
out[8] = a[8] + b[8];
|
||||
out[9] = a[9] + b[9];
|
||||
}
|
||||
|
||||
void curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
uint32_t c = 0;
|
||||
out[0] = a[0] + b[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = a[1] + b[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = a[2] + b[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = a[3] + b[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = a[4] + b[4] + c;
|
||||
c = (out[4] >> 26);
|
||||
out[4] &= reduce_mask_26;
|
||||
out[5] = a[5] + b[5] + c;
|
||||
c = (out[5] >> 25);
|
||||
out[5] &= reduce_mask_25;
|
||||
out[6] = a[6] + b[6] + c;
|
||||
c = (out[6] >> 26);
|
||||
out[6] &= reduce_mask_26;
|
||||
out[7] = a[7] + b[7] + c;
|
||||
c = (out[7] >> 25);
|
||||
out[7] &= reduce_mask_25;
|
||||
out[8] = a[8] + b[8] + c;
|
||||
c = (out[8] >> 26);
|
||||
out[8] &= reduce_mask_26;
|
||||
out[9] = a[9] + b[9] + c;
|
||||
c = (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
void curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
uint32_t c = 0;
|
||||
out[0] = a[0] + b[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = a[1] + b[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = a[2] + b[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = a[3] + b[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = a[4] + b[4] + c;
|
||||
c = (out[4] >> 26);
|
||||
out[4] &= reduce_mask_26;
|
||||
out[5] = a[5] + b[5] + c;
|
||||
c = (out[5] >> 25);
|
||||
out[5] &= reduce_mask_25;
|
||||
out[6] = a[6] + b[6] + c;
|
||||
c = (out[6] >> 26);
|
||||
out[6] &= reduce_mask_26;
|
||||
out[7] = a[7] + b[7] + c;
|
||||
c = (out[7] >> 25);
|
||||
out[7] &= reduce_mask_25;
|
||||
out[8] = a[8] + b[8] + c;
|
||||
c = (out[8] >> 26);
|
||||
out[8] &= reduce_mask_26;
|
||||
out[9] = a[9] + b[9] + c;
|
||||
c = (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
/* multiples of p */
|
||||
static const uint32_t twoP0 = 0x07ffffda;
|
||||
static const uint32_t twoP13579 = 0x03fffffe;
|
||||
static const uint32_t twoP2468 = 0x07fffffe;
|
||||
static const uint32_t fourP0 = 0x0fffffb4;
|
||||
static const uint32_t fourP13579 = 0x07fffffc;
|
||||
static const uint32_t fourP2468 = 0x0ffffffc;
|
||||
|
||||
/* out = a - b */
|
||||
void curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
uint32_t c = 0;
|
||||
out[0] = twoP0 + a[0] - b[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = twoP13579 + a[1] - b[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = twoP2468 + a[2] - b[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = twoP13579 + a[3] - b[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = twoP2468 + a[4] - b[4] + c;
|
||||
out[5] = twoP13579 + a[5] - b[5];
|
||||
out[6] = twoP2468 + a[6] - b[6];
|
||||
out[7] = twoP13579 + a[7] - b[7];
|
||||
out[8] = twoP2468 + a[8] - b[8];
|
||||
out[9] = twoP13579 + a[9] - b[9];
|
||||
}
|
||||
|
||||
/* out = in * scalar */
|
||||
void curve25519_scalar_product(bignum25519 out, const bignum25519 in, const uint32_t scalar) {
|
||||
uint64_t a = 0;
|
||||
uint32_t c = 0;
|
||||
a = mul32x32_64(in[0], scalar);
|
||||
out[0] = (uint32_t)a & reduce_mask_26;
|
||||
c = (uint32_t)(a >> 26);
|
||||
a = mul32x32_64(in[1], scalar) + c;
|
||||
out[1] = (uint32_t)a & reduce_mask_25;
|
||||
c = (uint32_t)(a >> 25);
|
||||
a = mul32x32_64(in[2], scalar) + c;
|
||||
out[2] = (uint32_t)a & reduce_mask_26;
|
||||
c = (uint32_t)(a >> 26);
|
||||
a = mul32x32_64(in[3], scalar) + c;
|
||||
out[3] = (uint32_t)a & reduce_mask_25;
|
||||
c = (uint32_t)(a >> 25);
|
||||
a = mul32x32_64(in[4], scalar) + c;
|
||||
out[4] = (uint32_t)a & reduce_mask_26;
|
||||
c = (uint32_t)(a >> 26);
|
||||
a = mul32x32_64(in[5], scalar) + c;
|
||||
out[5] = (uint32_t)a & reduce_mask_25;
|
||||
c = (uint32_t)(a >> 25);
|
||||
a = mul32x32_64(in[6], scalar) + c;
|
||||
out[6] = (uint32_t)a & reduce_mask_26;
|
||||
c = (uint32_t)(a >> 26);
|
||||
a = mul32x32_64(in[7], scalar) + c;
|
||||
out[7] = (uint32_t)a & reduce_mask_25;
|
||||
c = (uint32_t)(a >> 25);
|
||||
a = mul32x32_64(in[8], scalar) + c;
|
||||
out[8] = (uint32_t)a & reduce_mask_26;
|
||||
c = (uint32_t)(a >> 26);
|
||||
a = mul32x32_64(in[9], scalar) + c;
|
||||
out[9] = (uint32_t)a & reduce_mask_25;
|
||||
c = (uint32_t)(a >> 25);
|
||||
out[0] += c * 19;
|
||||
}
|
||||
|
||||
/* out = a - b, where a is the result of a basic op (add,sub) */
|
||||
void curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
uint32_t c = 0;
|
||||
out[0] = fourP0 + a[0] - b[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = fourP13579 + a[1] - b[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = fourP2468 + a[2] - b[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = fourP13579 + a[3] - b[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = fourP2468 + a[4] - b[4] + c;
|
||||
c = (out[4] >> 26);
|
||||
out[4] &= reduce_mask_26;
|
||||
out[5] = fourP13579 + a[5] - b[5] + c;
|
||||
c = (out[5] >> 25);
|
||||
out[5] &= reduce_mask_25;
|
||||
out[6] = fourP2468 + a[6] - b[6] + c;
|
||||
c = (out[6] >> 26);
|
||||
out[6] &= reduce_mask_26;
|
||||
out[7] = fourP13579 + a[7] - b[7] + c;
|
||||
c = (out[7] >> 25);
|
||||
out[7] &= reduce_mask_25;
|
||||
out[8] = fourP2468 + a[8] - b[8] + c;
|
||||
c = (out[8] >> 26);
|
||||
out[8] &= reduce_mask_26;
|
||||
out[9] = fourP13579 + a[9] - b[9] + c;
|
||||
c = (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
void curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
uint32_t c = 0;
|
||||
out[0] = fourP0 + a[0] - b[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = fourP13579 + a[1] - b[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = fourP2468 + a[2] - b[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = fourP13579 + a[3] - b[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = fourP2468 + a[4] - b[4] + c;
|
||||
c = (out[4] >> 26);
|
||||
out[4] &= reduce_mask_26;
|
||||
out[5] = fourP13579 + a[5] - b[5] + c;
|
||||
c = (out[5] >> 25);
|
||||
out[5] &= reduce_mask_25;
|
||||
out[6] = fourP2468 + a[6] - b[6] + c;
|
||||
c = (out[6] >> 26);
|
||||
out[6] &= reduce_mask_26;
|
||||
out[7] = fourP13579 + a[7] - b[7] + c;
|
||||
c = (out[7] >> 25);
|
||||
out[7] &= reduce_mask_25;
|
||||
out[8] = fourP2468 + a[8] - b[8] + c;
|
||||
c = (out[8] >> 26);
|
||||
out[8] &= reduce_mask_26;
|
||||
out[9] = fourP13579 + a[9] - b[9] + c;
|
||||
c = (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
/* out = -a */
|
||||
void curve25519_neg(bignum25519 out, const bignum25519 a) {
|
||||
uint32_t c = 0;
|
||||
out[0] = twoP0 - a[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = twoP13579 - a[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = twoP2468 - a[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = twoP13579 - a[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = twoP2468 - a[4] + c;
|
||||
c = (out[4] >> 26);
|
||||
out[4] &= reduce_mask_26;
|
||||
out[5] = twoP13579 - a[5] + c;
|
||||
c = (out[5] >> 25);
|
||||
out[5] &= reduce_mask_25;
|
||||
out[6] = twoP2468 - a[6] + c;
|
||||
c = (out[6] >> 26);
|
||||
out[6] &= reduce_mask_26;
|
||||
out[7] = twoP13579 - a[7] + c;
|
||||
c = (out[7] >> 25);
|
||||
out[7] &= reduce_mask_25;
|
||||
out[8] = twoP2468 - a[8] + c;
|
||||
c = (out[8] >> 26);
|
||||
out[8] &= reduce_mask_26;
|
||||
out[9] = twoP13579 - a[9] + c;
|
||||
c = (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
/* out = a * b */
|
||||
#define curve25519_mul_noinline curve25519_mul
|
||||
void curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
uint32_t r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0;
|
||||
uint32_t s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0, s6 = 0, s7 = 0, s8 = 0, s9 = 0;
|
||||
uint64_t m0 = 0, m1 = 0, m2 = 0, m3 = 0, m4 = 0, m5 = 0, m6 = 0, m7 = 0, m8 = 0, m9 = 0, c = 0;
|
||||
uint32_t p = 0;
|
||||
|
||||
r0 = b[0];
|
||||
r1 = b[1];
|
||||
r2 = b[2];
|
||||
r3 = b[3];
|
||||
r4 = b[4];
|
||||
r5 = b[5];
|
||||
r6 = b[6];
|
||||
r7 = b[7];
|
||||
r8 = b[8];
|
||||
r9 = b[9];
|
||||
|
||||
s0 = a[0];
|
||||
s1 = a[1];
|
||||
s2 = a[2];
|
||||
s3 = a[3];
|
||||
s4 = a[4];
|
||||
s5 = a[5];
|
||||
s6 = a[6];
|
||||
s7 = a[7];
|
||||
s8 = a[8];
|
||||
s9 = a[9];
|
||||
|
||||
m1 = mul32x32_64(r0, s1) + mul32x32_64(r1, s0);
|
||||
m3 = mul32x32_64(r0, s3) + mul32x32_64(r1, s2) + mul32x32_64(r2, s1) + mul32x32_64(r3, s0);
|
||||
m5 = mul32x32_64(r0, s5) + mul32x32_64(r1, s4) + mul32x32_64(r2, s3) + mul32x32_64(r3, s2) +
|
||||
mul32x32_64(r4, s1) + mul32x32_64(r5, s0);
|
||||
m7 = mul32x32_64(r0, s7) + mul32x32_64(r1, s6) + mul32x32_64(r2, s5) + mul32x32_64(r3, s4) +
|
||||
mul32x32_64(r4, s3) + mul32x32_64(r5, s2) + mul32x32_64(r6, s1) + mul32x32_64(r7, s0);
|
||||
m9 = mul32x32_64(r0, s9) + mul32x32_64(r1, s8) + mul32x32_64(r2, s7) + mul32x32_64(r3, s6) +
|
||||
mul32x32_64(r4, s5) + mul32x32_64(r5, s4) + mul32x32_64(r6, s3) + mul32x32_64(r7, s2) +
|
||||
mul32x32_64(r8, s1) + mul32x32_64(r9, s0);
|
||||
|
||||
r1 *= 2;
|
||||
r3 *= 2;
|
||||
r5 *= 2;
|
||||
r7 *= 2;
|
||||
|
||||
m0 = mul32x32_64(r0, s0);
|
||||
m2 = mul32x32_64(r0, s2) + mul32x32_64(r1, s1) + mul32x32_64(r2, s0);
|
||||
m4 = mul32x32_64(r0, s4) + mul32x32_64(r1, s3) + mul32x32_64(r2, s2) + mul32x32_64(r3, s1) +
|
||||
mul32x32_64(r4, s0);
|
||||
m6 = mul32x32_64(r0, s6) + mul32x32_64(r1, s5) + mul32x32_64(r2, s4) + mul32x32_64(r3, s3) +
|
||||
mul32x32_64(r4, s2) + mul32x32_64(r5, s1) + mul32x32_64(r6, s0);
|
||||
m8 = mul32x32_64(r0, s8) + mul32x32_64(r1, s7) + mul32x32_64(r2, s6) + mul32x32_64(r3, s5) +
|
||||
mul32x32_64(r4, s4) + mul32x32_64(r5, s3) + mul32x32_64(r6, s2) + mul32x32_64(r7, s1) +
|
||||
mul32x32_64(r8, s0);
|
||||
|
||||
r1 *= 19;
|
||||
r2 *= 19;
|
||||
r3 = (r3 / 2) * 19;
|
||||
r4 *= 19;
|
||||
r5 = (r5 / 2) * 19;
|
||||
r6 *= 19;
|
||||
r7 = (r7 / 2) * 19;
|
||||
r8 *= 19;
|
||||
r9 *= 19;
|
||||
|
||||
m1 +=
|
||||
(mul32x32_64(r9, s2) + mul32x32_64(r8, s3) + mul32x32_64(r7, s4) + mul32x32_64(r6, s5) +
|
||||
mul32x32_64(r5, s6) + mul32x32_64(r4, s7) + mul32x32_64(r3, s8) + mul32x32_64(r2, s9));
|
||||
m3 +=
|
||||
(mul32x32_64(r9, s4) + mul32x32_64(r8, s5) + mul32x32_64(r7, s6) + mul32x32_64(r6, s7) +
|
||||
mul32x32_64(r5, s8) + mul32x32_64(r4, s9));
|
||||
m5 += (mul32x32_64(r9, s6) + mul32x32_64(r8, s7) + mul32x32_64(r7, s8) + mul32x32_64(r6, s9));
|
||||
m7 += (mul32x32_64(r9, s8) + mul32x32_64(r8, s9));
|
||||
|
||||
r3 *= 2;
|
||||
r5 *= 2;
|
||||
r7 *= 2;
|
||||
r9 *= 2;
|
||||
|
||||
m0 +=
|
||||
(mul32x32_64(r9, s1) + mul32x32_64(r8, s2) + mul32x32_64(r7, s3) + mul32x32_64(r6, s4) +
|
||||
mul32x32_64(r5, s5) + mul32x32_64(r4, s6) + mul32x32_64(r3, s7) + mul32x32_64(r2, s8) +
|
||||
mul32x32_64(r1, s9));
|
||||
m2 +=
|
||||
(mul32x32_64(r9, s3) + mul32x32_64(r8, s4) + mul32x32_64(r7, s5) + mul32x32_64(r6, s6) +
|
||||
mul32x32_64(r5, s7) + mul32x32_64(r4, s8) + mul32x32_64(r3, s9));
|
||||
m4 +=
|
||||
(mul32x32_64(r9, s5) + mul32x32_64(r8, s6) + mul32x32_64(r7, s7) + mul32x32_64(r6, s8) +
|
||||
mul32x32_64(r5, s9));
|
||||
m6 += (mul32x32_64(r9, s7) + mul32x32_64(r8, s8) + mul32x32_64(r7, s9));
|
||||
m8 += (mul32x32_64(r9, s9));
|
||||
|
||||
r0 = (uint32_t)m0 & reduce_mask_26;
|
||||
c = (m0 >> 26);
|
||||
m1 += c;
|
||||
r1 = (uint32_t)m1 & reduce_mask_25;
|
||||
c = (m1 >> 25);
|
||||
m2 += c;
|
||||
r2 = (uint32_t)m2 & reduce_mask_26;
|
||||
c = (m2 >> 26);
|
||||
m3 += c;
|
||||
r3 = (uint32_t)m3 & reduce_mask_25;
|
||||
c = (m3 >> 25);
|
||||
m4 += c;
|
||||
r4 = (uint32_t)m4 & reduce_mask_26;
|
||||
c = (m4 >> 26);
|
||||
m5 += c;
|
||||
r5 = (uint32_t)m5 & reduce_mask_25;
|
||||
c = (m5 >> 25);
|
||||
m6 += c;
|
||||
r6 = (uint32_t)m6 & reduce_mask_26;
|
||||
c = (m6 >> 26);
|
||||
m7 += c;
|
||||
r7 = (uint32_t)m7 & reduce_mask_25;
|
||||
c = (m7 >> 25);
|
||||
m8 += c;
|
||||
r8 = (uint32_t)m8 & reduce_mask_26;
|
||||
c = (m8 >> 26);
|
||||
m9 += c;
|
||||
r9 = (uint32_t)m9 & reduce_mask_25;
|
||||
p = (uint32_t)(m9 >> 25);
|
||||
m0 = r0 + mul32x32_64(p, 19);
|
||||
r0 = (uint32_t)m0 & reduce_mask_26;
|
||||
p = (uint32_t)(m0 >> 26);
|
||||
r1 += p;
|
||||
|
||||
out[0] = r0;
|
||||
out[1] = r1;
|
||||
out[2] = r2;
|
||||
out[3] = r3;
|
||||
out[4] = r4;
|
||||
out[5] = r5;
|
||||
out[6] = r6;
|
||||
out[7] = r7;
|
||||
out[8] = r8;
|
||||
out[9] = r9;
|
||||
}
|
||||
|
||||
/* out = in * in */
|
||||
void curve25519_square(bignum25519 out, const bignum25519 in) {
|
||||
uint32_t r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0;
|
||||
uint32_t d6 = 0, d7 = 0, d8 = 0, d9 = 0;
|
||||
uint64_t m0 = 0, m1 = 0, m2 = 0, m3 = 0, m4 = 0, m5 = 0, m6 = 0, m7 = 0, m8 = 0, m9 = 0, c = 0;
|
||||
uint32_t p = 0;
|
||||
|
||||
r0 = in[0];
|
||||
r1 = in[1];
|
||||
r2 = in[2];
|
||||
r3 = in[3];
|
||||
r4 = in[4];
|
||||
r5 = in[5];
|
||||
r6 = in[6];
|
||||
r7 = in[7];
|
||||
r8 = in[8];
|
||||
r9 = in[9];
|
||||
|
||||
m0 = mul32x32_64(r0, r0);
|
||||
r0 *= 2;
|
||||
m1 = mul32x32_64(r0, r1);
|
||||
m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2);
|
||||
r1 *= 2;
|
||||
m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2);
|
||||
m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2);
|
||||
r2 *= 2;
|
||||
m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4) + mul32x32_64(r2, r3);
|
||||
m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) +
|
||||
mul32x32_64(r3, r3 * 2);
|
||||
r3 *= 2;
|
||||
m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4);
|
||||
m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) +
|
||||
mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4);
|
||||
m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8) + mul32x32_64(r2, r7) + mul32x32_64(r3, r6) +
|
||||
mul32x32_64(r4, r5 * 2);
|
||||
|
||||
d6 = r6 * 19;
|
||||
d7 = r7 * 2 * 19;
|
||||
d8 = r8 * 19;
|
||||
d9 = r9 * 2 * 19;
|
||||
|
||||
m0 +=
|
||||
(mul32x32_64(d9, r1) + mul32x32_64(d8, r2) + mul32x32_64(d7, r3) +
|
||||
mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19));
|
||||
m1 +=
|
||||
(mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3) + mul32x32_64(d7, r4) +
|
||||
mul32x32_64(d6, r5 * 2));
|
||||
m2 +=
|
||||
(mul32x32_64(d9, r3) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) +
|
||||
mul32x32_64(d6, r6));
|
||||
m3 += (mul32x32_64(d9, r4) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6));
|
||||
m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7));
|
||||
m5 += (mul32x32_64(d9, r6) + mul32x32_64(d8, r7 * 2));
|
||||
m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8));
|
||||
m7 += (mul32x32_64(d9, r8));
|
||||
m8 += (mul32x32_64(d9, r9));
|
||||
|
||||
r0 = (uint32_t)m0 & reduce_mask_26;
|
||||
c = (m0 >> 26);
|
||||
m1 += c;
|
||||
r1 = (uint32_t)m1 & reduce_mask_25;
|
||||
c = (m1 >> 25);
|
||||
m2 += c;
|
||||
r2 = (uint32_t)m2 & reduce_mask_26;
|
||||
c = (m2 >> 26);
|
||||
m3 += c;
|
||||
r3 = (uint32_t)m3 & reduce_mask_25;
|
||||
c = (m3 >> 25);
|
||||
m4 += c;
|
||||
r4 = (uint32_t)m4 & reduce_mask_26;
|
||||
c = (m4 >> 26);
|
||||
m5 += c;
|
||||
r5 = (uint32_t)m5 & reduce_mask_25;
|
||||
c = (m5 >> 25);
|
||||
m6 += c;
|
||||
r6 = (uint32_t)m6 & reduce_mask_26;
|
||||
c = (m6 >> 26);
|
||||
m7 += c;
|
||||
r7 = (uint32_t)m7 & reduce_mask_25;
|
||||
c = (m7 >> 25);
|
||||
m8 += c;
|
||||
r8 = (uint32_t)m8 & reduce_mask_26;
|
||||
c = (m8 >> 26);
|
||||
m9 += c;
|
||||
r9 = (uint32_t)m9 & reduce_mask_25;
|
||||
p = (uint32_t)(m9 >> 25);
|
||||
m0 = r0 + mul32x32_64(p, 19);
|
||||
r0 = (uint32_t)m0 & reduce_mask_26;
|
||||
p = (uint32_t)(m0 >> 26);
|
||||
r1 += p;
|
||||
|
||||
out[0] = r0;
|
||||
out[1] = r1;
|
||||
out[2] = r2;
|
||||
out[3] = r3;
|
||||
out[4] = r4;
|
||||
out[5] = r5;
|
||||
out[6] = r6;
|
||||
out[7] = r7;
|
||||
out[8] = r8;
|
||||
out[9] = r9;
|
||||
}
|
||||
|
||||
/* out = in ^ (2 * count) */
|
||||
void curve25519_square_times(bignum25519 out, const bignum25519 in, int count) {
|
||||
uint32_t r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0;
|
||||
uint32_t d6 = 0, d7 = 0, d8 = 0, d9 = 0;
|
||||
uint64_t m0 = 0, m1 = 0, m2 = 0, m3 = 0, m4 = 0, m5 = 0, m6 = 0, m7 = 0, m8 = 0, m9 = 0, c = 0;
|
||||
uint32_t p = 0;
|
||||
|
||||
r0 = in[0];
|
||||
r1 = in[1];
|
||||
r2 = in[2];
|
||||
r3 = in[3];
|
||||
r4 = in[4];
|
||||
r5 = in[5];
|
||||
r6 = in[6];
|
||||
r7 = in[7];
|
||||
r8 = in[8];
|
||||
r9 = in[9];
|
||||
|
||||
do {
|
||||
m0 = mul32x32_64(r0, r0);
|
||||
r0 *= 2;
|
||||
m1 = mul32x32_64(r0, r1);
|
||||
m2 = mul32x32_64(r0, r2) + mul32x32_64(r1, r1 * 2);
|
||||
r1 *= 2;
|
||||
m3 = mul32x32_64(r0, r3) + mul32x32_64(r1, r2);
|
||||
m4 = mul32x32_64(r0, r4) + mul32x32_64(r1, r3 * 2) + mul32x32_64(r2, r2);
|
||||
r2 *= 2;
|
||||
m5 = mul32x32_64(r0, r5) + mul32x32_64(r1, r4) + mul32x32_64(r2, r3);
|
||||
m6 = mul32x32_64(r0, r6) + mul32x32_64(r1, r5 * 2) + mul32x32_64(r2, r4) +
|
||||
mul32x32_64(r3, r3 * 2);
|
||||
r3 *= 2;
|
||||
m7 = mul32x32_64(r0, r7) + mul32x32_64(r1, r6) + mul32x32_64(r2, r5) + mul32x32_64(r3, r4);
|
||||
m8 = mul32x32_64(r0, r8) + mul32x32_64(r1, r7 * 2) + mul32x32_64(r2, r6) +
|
||||
mul32x32_64(r3, r5 * 2) + mul32x32_64(r4, r4);
|
||||
m9 = mul32x32_64(r0, r9) + mul32x32_64(r1, r8) + mul32x32_64(r2, r7) +
|
||||
mul32x32_64(r3, r6) + mul32x32_64(r4, r5 * 2);
|
||||
|
||||
d6 = r6 * 19;
|
||||
d7 = r7 * 2 * 19;
|
||||
d8 = r8 * 19;
|
||||
d9 = r9 * 2 * 19;
|
||||
|
||||
m0 +=
|
||||
(mul32x32_64(d9, r1) + mul32x32_64(d8, r2) + mul32x32_64(d7, r3) +
|
||||
mul32x32_64(d6, r4 * 2) + mul32x32_64(r5, r5 * 2 * 19));
|
||||
m1 +=
|
||||
(mul32x32_64(d9, r2 / 2) + mul32x32_64(d8, r3) + mul32x32_64(d7, r4) +
|
||||
mul32x32_64(d6, r5 * 2));
|
||||
m2 +=
|
||||
(mul32x32_64(d9, r3) + mul32x32_64(d8, r4 * 2) + mul32x32_64(d7, r5 * 2) +
|
||||
mul32x32_64(d6, r6));
|
||||
m3 += (mul32x32_64(d9, r4) + mul32x32_64(d8, r5 * 2) + mul32x32_64(d7, r6));
|
||||
m4 += (mul32x32_64(d9, r5 * 2) + mul32x32_64(d8, r6 * 2) + mul32x32_64(d7, r7));
|
||||
m5 += (mul32x32_64(d9, r6) + mul32x32_64(d8, r7 * 2));
|
||||
m6 += (mul32x32_64(d9, r7 * 2) + mul32x32_64(d8, r8));
|
||||
m7 += (mul32x32_64(d9, r8));
|
||||
m8 += (mul32x32_64(d9, r9));
|
||||
|
||||
r0 = (uint32_t)m0 & reduce_mask_26;
|
||||
c = (m0 >> 26);
|
||||
m1 += c;
|
||||
r1 = (uint32_t)m1 & reduce_mask_25;
|
||||
c = (m1 >> 25);
|
||||
m2 += c;
|
||||
r2 = (uint32_t)m2 & reduce_mask_26;
|
||||
c = (m2 >> 26);
|
||||
m3 += c;
|
||||
r3 = (uint32_t)m3 & reduce_mask_25;
|
||||
c = (m3 >> 25);
|
||||
m4 += c;
|
||||
r4 = (uint32_t)m4 & reduce_mask_26;
|
||||
c = (m4 >> 26);
|
||||
m5 += c;
|
||||
r5 = (uint32_t)m5 & reduce_mask_25;
|
||||
c = (m5 >> 25);
|
||||
m6 += c;
|
||||
r6 = (uint32_t)m6 & reduce_mask_26;
|
||||
c = (m6 >> 26);
|
||||
m7 += c;
|
||||
r7 = (uint32_t)m7 & reduce_mask_25;
|
||||
c = (m7 >> 25);
|
||||
m8 += c;
|
||||
r8 = (uint32_t)m8 & reduce_mask_26;
|
||||
c = (m8 >> 26);
|
||||
m9 += c;
|
||||
r9 = (uint32_t)m9 & reduce_mask_25;
|
||||
p = (uint32_t)(m9 >> 25);
|
||||
m0 = r0 + mul32x32_64(p, 19);
|
||||
r0 = (uint32_t)m0 & reduce_mask_26;
|
||||
p = (uint32_t)(m0 >> 26);
|
||||
r1 += p;
|
||||
} while(--count);
|
||||
|
||||
out[0] = r0;
|
||||
out[1] = r1;
|
||||
out[2] = r2;
|
||||
out[3] = r3;
|
||||
out[4] = r4;
|
||||
out[5] = r5;
|
||||
out[6] = r6;
|
||||
out[7] = r7;
|
||||
out[8] = r8;
|
||||
out[9] = r9;
|
||||
}
|
||||
|
||||
/* Take a little-endian, 32-byte number and expand it into polynomial form */
|
||||
void curve25519_expand(bignum25519 out, const unsigned char in[32]) {
|
||||
uint32_t x0 = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0, x7 = 0;
|
||||
#define F(s) \
|
||||
((((uint32_t)in[s + 0])) | (((uint32_t)in[s + 1]) << 8) | (((uint32_t)in[s + 2]) << 16) | \
|
||||
(((uint32_t)in[s + 3]) << 24))
|
||||
x0 = F(0);
|
||||
x1 = F(4);
|
||||
x2 = F(8);
|
||||
x3 = F(12);
|
||||
x4 = F(16);
|
||||
x5 = F(20);
|
||||
x6 = F(24);
|
||||
x7 = F(28);
|
||||
#undef F
|
||||
|
||||
out[0] = (x0)&reduce_mask_26;
|
||||
out[1] = ((((uint64_t)x1 << 32) | x0) >> 26) & reduce_mask_25;
|
||||
out[2] = ((((uint64_t)x2 << 32) | x1) >> 19) & reduce_mask_26;
|
||||
out[3] = ((((uint64_t)x3 << 32) | x2) >> 13) & reduce_mask_25;
|
||||
out[4] = ((x3) >> 6) & reduce_mask_26;
|
||||
out[5] = (x4)&reduce_mask_25;
|
||||
out[6] = ((((uint64_t)x5 << 32) | x4) >> 25) & reduce_mask_26;
|
||||
out[7] = ((((uint64_t)x6 << 32) | x5) >> 19) & reduce_mask_25;
|
||||
out[8] = ((((uint64_t)x7 << 32) | x6) >> 12) & reduce_mask_26;
|
||||
out[9] = ((x7) >> 6) & reduce_mask_25; /* ignore the top bit */
|
||||
}
|
||||
|
||||
/* Take a fully reduced polynomial form number and contract it into a
|
||||
* little-endian, 32-byte array
|
||||
*/
|
||||
void curve25519_contract(unsigned char out[32], const bignum25519 in) {
|
||||
bignum25519 f = {0};
|
||||
curve25519_copy(f, in);
|
||||
|
||||
#define carry_pass() \
|
||||
f[1] += f[0] >> 26; \
|
||||
f[0] &= reduce_mask_26; \
|
||||
f[2] += f[1] >> 25; \
|
||||
f[1] &= reduce_mask_25; \
|
||||
f[3] += f[2] >> 26; \
|
||||
f[2] &= reduce_mask_26; \
|
||||
f[4] += f[3] >> 25; \
|
||||
f[3] &= reduce_mask_25; \
|
||||
f[5] += f[4] >> 26; \
|
||||
f[4] &= reduce_mask_26; \
|
||||
f[6] += f[5] >> 25; \
|
||||
f[5] &= reduce_mask_25; \
|
||||
f[7] += f[6] >> 26; \
|
||||
f[6] &= reduce_mask_26; \
|
||||
f[8] += f[7] >> 25; \
|
||||
f[7] &= reduce_mask_25; \
|
||||
f[9] += f[8] >> 26; \
|
||||
f[8] &= reduce_mask_26;
|
||||
|
||||
#define carry_pass_full() \
|
||||
carry_pass() f[0] += 19 * (f[9] >> 25); \
|
||||
f[9] &= reduce_mask_25;
|
||||
|
||||
#define carry_pass_final() carry_pass() f[9] &= reduce_mask_25;
|
||||
|
||||
carry_pass_full() carry_pass_full()
|
||||
|
||||
/* now t is between 0 and 2^255-1, properly carried. */
|
||||
/* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
|
||||
f[0] += 19;
|
||||
carry_pass_full()
|
||||
|
||||
/* now between 19 and 2^255-1 in both cases, and offset by 19. */
|
||||
f[0] += (reduce_mask_26 + 1) - 19;
|
||||
f[1] += (reduce_mask_25 + 1) - 1;
|
||||
f[2] += (reduce_mask_26 + 1) - 1;
|
||||
f[3] += (reduce_mask_25 + 1) - 1;
|
||||
f[4] += (reduce_mask_26 + 1) - 1;
|
||||
f[5] += (reduce_mask_25 + 1) - 1;
|
||||
f[6] += (reduce_mask_26 + 1) - 1;
|
||||
f[7] += (reduce_mask_25 + 1) - 1;
|
||||
f[8] += (reduce_mask_26 + 1) - 1;
|
||||
f[9] += (reduce_mask_25 + 1) - 1;
|
||||
|
||||
/* now between 2^255 and 2^256-20, and offset by 2^255. */
|
||||
carry_pass_final()
|
||||
|
||||
#undef carry_pass
|
||||
#undef carry_full
|
||||
#undef carry_final
|
||||
|
||||
f[1] <<= 2;
|
||||
f[2] <<= 3;
|
||||
f[3] <<= 5;
|
||||
f[4] <<= 6;
|
||||
f[6] <<= 1;
|
||||
f[7] <<= 3;
|
||||
f[8] <<= 4;
|
||||
f[9] <<= 6;
|
||||
|
||||
#define F(i, s) \
|
||||
out[s + 0] |= (unsigned char)(f[i] & 0xff); \
|
||||
out[s + 1] = (unsigned char)((f[i] >> 8) & 0xff); \
|
||||
out[s + 2] = (unsigned char)((f[i] >> 16) & 0xff); \
|
||||
out[s + 3] = (unsigned char)((f[i] >> 24) & 0xff);
|
||||
|
||||
out[0] = 0;
|
||||
out[16] = 0;
|
||||
F(0, 0);
|
||||
F(1, 3);
|
||||
F(2, 6);
|
||||
F(3, 9);
|
||||
F(4, 12);
|
||||
F(5, 16);
|
||||
F(6, 19);
|
||||
F(7, 22);
|
||||
F(8, 25);
|
||||
F(9, 28);
|
||||
#undef F
|
||||
}
|
||||
|
||||
/* if (iswap) swap(a, b) */
|
||||
void curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint32_t iswap) {
|
||||
const uint32_t swap = (uint32_t)(-(int32_t)iswap);
|
||||
uint32_t x0 = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0, x7 = 0, x8 = 0, x9 = 0;
|
||||
|
||||
x0 = swap & (a[0] ^ b[0]);
|
||||
a[0] ^= x0;
|
||||
b[0] ^= x0;
|
||||
x1 = swap & (a[1] ^ b[1]);
|
||||
a[1] ^= x1;
|
||||
b[1] ^= x1;
|
||||
x2 = swap & (a[2] ^ b[2]);
|
||||
a[2] ^= x2;
|
||||
b[2] ^= x2;
|
||||
x3 = swap & (a[3] ^ b[3]);
|
||||
a[3] ^= x3;
|
||||
b[3] ^= x3;
|
||||
x4 = swap & (a[4] ^ b[4]);
|
||||
a[4] ^= x4;
|
||||
b[4] ^= x4;
|
||||
x5 = swap & (a[5] ^ b[5]);
|
||||
a[5] ^= x5;
|
||||
b[5] ^= x5;
|
||||
x6 = swap & (a[6] ^ b[6]);
|
||||
a[6] ^= x6;
|
||||
b[6] ^= x6;
|
||||
x7 = swap & (a[7] ^ b[7]);
|
||||
a[7] ^= x7;
|
||||
b[7] ^= x7;
|
||||
x8 = swap & (a[8] ^ b[8]);
|
||||
a[8] ^= x8;
|
||||
b[8] ^= x8;
|
||||
x9 = swap & (a[9] ^ b[9]);
|
||||
a[9] ^= x9;
|
||||
b[9] ^= x9;
|
||||
}
|
||||
|
||||
void curve25519_set(bignum25519 r, uint32_t x) {
|
||||
r[0] = x & reduce_mask_26;
|
||||
x >>= 26;
|
||||
r[1] = x & reduce_mask_25;
|
||||
r[2] = 0;
|
||||
r[3] = 0;
|
||||
r[4] = 0;
|
||||
r[5] = 0;
|
||||
r[6] = 0;
|
||||
r[7] = 0;
|
||||
r[8] = 0;
|
||||
r[9] = 0;
|
||||
}
|
||||
|
||||
void curve25519_set_d(bignum25519 r) {
|
||||
curve25519_copy(r, ge25519_ecd);
|
||||
}
|
||||
|
||||
void curve25519_set_2d(bignum25519 r) {
|
||||
curve25519_copy(r, ge25519_ec2d);
|
||||
}
|
||||
|
||||
void curve25519_set_sqrtneg1(bignum25519 r) {
|
||||
curve25519_copy(r, ge25519_sqrtneg1);
|
||||
}
|
||||
|
||||
int curve25519_isnegative(const bignum25519 f) {
|
||||
unsigned char s[32] = {0};
|
||||
curve25519_contract(s, f);
|
||||
return s[0] & 1;
|
||||
}
|
||||
|
||||
int curve25519_isnonzero(const bignum25519 f) {
|
||||
unsigned char s[32] = {0};
|
||||
curve25519_contract(s, f);
|
||||
return ((((int)(s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] | s[9] | s[10] | s[11] | s[12] | s[13] | s[14] | s[15] | s[16] | s[17] | s[18] | s[19] | s[20] | s[21] | s[22] | s[23] | s[24] | s[25] | s[26] | s[27] | s[28] | s[29] | s[30] | s[31]) -
|
||||
1) >>
|
||||
8) +
|
||||
1) &
|
||||
0x1;
|
||||
}
|
||||
|
||||
void curve25519_reduce(bignum25519 out, const bignum25519 in) {
|
||||
uint32_t c = 0;
|
||||
out[0] = in[0];
|
||||
c = (out[0] >> 26);
|
||||
out[0] &= reduce_mask_26;
|
||||
out[1] = in[1] + c;
|
||||
c = (out[1] >> 25);
|
||||
out[1] &= reduce_mask_25;
|
||||
out[2] = in[2] + c;
|
||||
c = (out[2] >> 26);
|
||||
out[2] &= reduce_mask_26;
|
||||
out[3] = in[3] + c;
|
||||
c = (out[3] >> 25);
|
||||
out[3] &= reduce_mask_25;
|
||||
out[4] = in[4] + c;
|
||||
c = (out[4] >> 26);
|
||||
out[4] &= reduce_mask_26;
|
||||
out[5] = in[5] + c;
|
||||
c = (out[5] >> 25);
|
||||
out[5] &= reduce_mask_25;
|
||||
out[6] = in[6] + c;
|
||||
c = (out[6] >> 26);
|
||||
out[6] &= reduce_mask_26;
|
||||
out[7] = in[7] + c;
|
||||
c = (out[7] >> 25);
|
||||
out[7] &= reduce_mask_25;
|
||||
out[8] = in[8] + c;
|
||||
c = (out[8] >> 26);
|
||||
out[8] &= reduce_mask_26;
|
||||
out[9] = in[9] + c;
|
||||
c = (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
void curve25519_divpowm1(bignum25519 r, const bignum25519 u, const bignum25519 v) {
|
||||
bignum25519 v3 = {0}, uv7 = {0}, t0 = {0}, t1 = {0}, t2 = {0};
|
||||
int i = 0;
|
||||
|
||||
curve25519_square(v3, v);
|
||||
curve25519_mul(v3, v3, v); /* v3 = v^3 */
|
||||
curve25519_square(uv7, v3);
|
||||
curve25519_mul(uv7, uv7, v);
|
||||
curve25519_mul(uv7, uv7, u); /* uv7 = uv^7 */
|
||||
|
||||
/*fe_pow22523(uv7, uv7);*/
|
||||
/* From fe_pow22523.c */
|
||||
|
||||
curve25519_square(t0, uv7);
|
||||
curve25519_square(t1, t0);
|
||||
curve25519_square(t1, t1);
|
||||
curve25519_mul(t1, uv7, t1);
|
||||
curve25519_mul(t0, t0, t1);
|
||||
curve25519_square(t0, t0);
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t1, t0);
|
||||
for(i = 0; i < 4; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t1, t0);
|
||||
for(i = 0; i < 9; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t1, t1, t0);
|
||||
curve25519_square(t2, t1);
|
||||
for(i = 0; i < 19; ++i) {
|
||||
curve25519_square(t2, t2);
|
||||
}
|
||||
curve25519_mul(t1, t2, t1);
|
||||
for(i = 0; i < 10; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t1, t0);
|
||||
for(i = 0; i < 49; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t1, t1, t0);
|
||||
curve25519_square(t2, t1);
|
||||
for(i = 0; i < 99; ++i) {
|
||||
curve25519_square(t2, t2);
|
||||
}
|
||||
curve25519_mul(t1, t2, t1);
|
||||
for(i = 0; i < 50; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t0, t0);
|
||||
curve25519_square(t0, t0);
|
||||
curve25519_mul(t0, t0, uv7);
|
||||
|
||||
/* End fe_pow22523.c */
|
||||
/* t0 = (uv^7)^((q-5)/8) */
|
||||
curve25519_mul(t0, t0, v3);
|
||||
curve25519_mul(r, t0, u); /* u^(m+1)v^(-(m+1)) */
|
||||
}
|
||||
|
||||
void curve25519_expand_reduce(bignum25519 out, const unsigned char in[32]) {
|
||||
uint32_t x0 = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0, x7 = 0;
|
||||
#define F(s) \
|
||||
((((uint32_t)in[s + 0])) | (((uint32_t)in[s + 1]) << 8) | (((uint32_t)in[s + 2]) << 16) | \
|
||||
(((uint32_t)in[s + 3]) << 24))
|
||||
x0 = F(0);
|
||||
x1 = F(4);
|
||||
x2 = F(8);
|
||||
x3 = F(12);
|
||||
x4 = F(16);
|
||||
x5 = F(20);
|
||||
x6 = F(24);
|
||||
x7 = F(28);
|
||||
#undef F
|
||||
|
||||
out[0] = (x0)&reduce_mask_26;
|
||||
out[1] = ((((uint64_t)x1 << 32) | x0) >> 26) & reduce_mask_25;
|
||||
out[2] = ((((uint64_t)x2 << 32) | x1) >> 19) & reduce_mask_26;
|
||||
out[3] = ((((uint64_t)x3 << 32) | x2) >> 13) & reduce_mask_25;
|
||||
out[4] = ((x3) >> 6) & reduce_mask_26;
|
||||
out[5] = (x4)&reduce_mask_25;
|
||||
out[6] = ((((uint64_t)x5 << 32) | x4) >> 25) & reduce_mask_26;
|
||||
out[7] = ((((uint64_t)x6 << 32) | x5) >> 19) & reduce_mask_25;
|
||||
out[8] = ((((uint64_t)x7 << 32) | x6) >> 12) & reduce_mask_26;
|
||||
out[9] = ((x7) >> 6); // & reduce_mask_25; /* ignore the top bit */
|
||||
out[0] += 19 * (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
See: https://github.com/floodyberry/curve25519-donna
|
||||
|
||||
32 bit integer curve25519 implementation
|
||||
*/
|
||||
|
||||
typedef uint32_t bignum25519[10];
|
||||
|
||||
/* out = in */
|
||||
void curve25519_copy(bignum25519 out, const bignum25519 in);
|
||||
|
||||
/* out = a + b */
|
||||
void curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
void curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
void curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
/* out = a - b */
|
||||
void curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
/* out = in * scalar */
|
||||
void curve25519_scalar_product(bignum25519 out, const bignum25519 in, const uint32_t scalar);
|
||||
|
||||
/* out = a - b, where a is the result of a basic op (add,sub) */
|
||||
void curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
void curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
/* out = -a */
|
||||
void curve25519_neg(bignum25519 out, const bignum25519 a);
|
||||
|
||||
/* out = a * b */
|
||||
#define curve25519_mul_noinline curve25519_mul
|
||||
void curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b);
|
||||
|
||||
/* out = in * in */
|
||||
void curve25519_square(bignum25519 out, const bignum25519 in);
|
||||
|
||||
/* out = in ^ (2 * count) */
|
||||
void curve25519_square_times(bignum25519 out, const bignum25519 in, int count);
|
||||
|
||||
/* Take a little-endian, 32-byte number and expand it into polynomial form */
|
||||
void curve25519_expand(bignum25519 out, const unsigned char in[32]);
|
||||
|
||||
/* Take a fully reduced polynomial form number and contract it into a
|
||||
* little-endian, 32-byte array
|
||||
*/
|
||||
void curve25519_contract(unsigned char out[32], const bignum25519 in);
|
||||
|
||||
/* if (iswap) swap(a, b) */
|
||||
void curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint32_t iswap);
|
||||
|
||||
/* uint32_t to Zmod(2^255-19) */
|
||||
void curve25519_set(bignum25519 r, uint32_t x);
|
||||
|
||||
/* set d */
|
||||
void curve25519_set_d(bignum25519 r);
|
||||
|
||||
/* set 2d */
|
||||
void curve25519_set_2d(bignum25519 r);
|
||||
|
||||
/* set sqrt(-1) */
|
||||
void curve25519_set_sqrtneg1(bignum25519 r);
|
||||
|
||||
/* constant time Zmod(2^255-19) negative test */
|
||||
int curve25519_isnegative(const bignum25519 f);
|
||||
|
||||
/* constant time Zmod(2^255-19) non-zero test */
|
||||
int curve25519_isnonzero(const bignum25519 f);
|
||||
|
||||
/* reduce Zmod(2^255-19) */
|
||||
void curve25519_reduce(bignum25519 r, const bignum25519 in);
|
||||
|
||||
void curve25519_divpowm1(bignum25519 r, const bignum25519 u, const bignum25519 v);
|
||||
|
||||
/* Zmod(2^255-19) from byte array to bignum25519 expansion with modular reduction */
|
||||
void curve25519_expand_reduce(bignum25519 out, const unsigned char in[32]);
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
See: https://github.com/floodyberry/curve25519-donna
|
||||
|
||||
Curve25519 implementation agnostic helpers
|
||||
*/
|
||||
|
||||
#include "ed25519_donna.h"
|
||||
|
||||
/*
|
||||
* In: b = 2^5 - 2^0
|
||||
* Out: b = 2^250 - 2^0
|
||||
*/
|
||||
void curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) {
|
||||
bignum25519 ALIGN(16) t0 = {0}, c = {0};
|
||||
|
||||
/* 2^5 - 2^0 */ /* b */
|
||||
/* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5);
|
||||
/* 2^10 - 2^0 */ curve25519_mul_noinline(b, t0, b);
|
||||
/* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10);
|
||||
/* 2^20 - 2^0 */ curve25519_mul_noinline(c, t0, b);
|
||||
/* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20);
|
||||
/* 2^40 - 2^0 */ curve25519_mul_noinline(t0, t0, c);
|
||||
/* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10);
|
||||
/* 2^50 - 2^0 */ curve25519_mul_noinline(b, t0, b);
|
||||
/* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50);
|
||||
/* 2^100 - 2^0 */ curve25519_mul_noinline(c, t0, b);
|
||||
/* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100);
|
||||
/* 2^200 - 2^0 */ curve25519_mul_noinline(t0, t0, c);
|
||||
/* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50);
|
||||
/* 2^250 - 2^0 */ curve25519_mul_noinline(b, t0, b);
|
||||
}
|
||||
|
||||
/*
|
||||
* z^(p - 2) = z(2^255 - 21)
|
||||
*/
|
||||
void curve25519_recip(bignum25519 out, const bignum25519 z) {
|
||||
bignum25519 ALIGN(16) a = {0}, t0 = {0}, b = {0};
|
||||
|
||||
/* 2 */ curve25519_square_times(a, z, 1); /* a = 2 */
|
||||
/* 8 */ curve25519_square_times(t0, a, 2);
|
||||
/* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */
|
||||
/* 11 */ curve25519_mul_noinline(a, b, a); /* a = 11 */
|
||||
/* 22 */ curve25519_square_times(t0, a, 1);
|
||||
/* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b);
|
||||
/* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
|
||||
/* 2^255 - 2^5 */ curve25519_square_times(b, b, 5);
|
||||
/* 2^255 - 21 */ curve25519_mul_noinline(out, b, a);
|
||||
}
|
||||
|
||||
/*
|
||||
* z^((p-5)/8) = z^(2^252 - 3)
|
||||
*/
|
||||
void curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z) {
|
||||
bignum25519 ALIGN(16) b, c, t0;
|
||||
|
||||
/* 2 */ curve25519_square_times(c, z, 1); /* c = 2 */
|
||||
/* 8 */ curve25519_square_times(t0, c, 2); /* t0 = 8 */
|
||||
/* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */
|
||||
/* 11 */ curve25519_mul_noinline(c, b, c); /* c = 11 */
|
||||
/* 22 */ curve25519_square_times(t0, c, 1);
|
||||
/* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b);
|
||||
/* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
|
||||
/* 2^252 - 2^2 */ curve25519_square_times(b, b, 2);
|
||||
/* 2^252 - 3 */ curve25519_mul_noinline(two252m3, b, z);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
See: https://github.com/floodyberry/curve25519-donna
|
||||
|
||||
Curve25519 implementation agnostic helpers
|
||||
*/
|
||||
|
||||
/*
|
||||
* In: b = 2^5 - 2^0
|
||||
* Out: b = 2^250 - 2^0
|
||||
*/
|
||||
void curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b);
|
||||
|
||||
/*
|
||||
* z^(p - 2) = z(2^255 - 21)
|
||||
*/
|
||||
void curve25519_recip(bignum25519 out, const bignum25519 z);
|
||||
|
||||
/*
|
||||
* z^((p-5)/8) = z^(2^252 - 3)
|
||||
*/
|
||||
void curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z);
|
||||
@@ -1,70 +0,0 @@
|
||||
#include "ed25519_donna.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
/* Calculates nQ where Q is the x-coordinate of a point on the curve
|
||||
*
|
||||
* mypublic: the packed little endian x coordinate of the resulting curve point
|
||||
* n: a little endian, 32-byte number
|
||||
* basepoint: a packed little endian point of the curve
|
||||
*/
|
||||
|
||||
void curve25519_scalarmult_donna(
|
||||
curve25519_key mypublic,
|
||||
const curve25519_key n,
|
||||
const curve25519_key basepoint) {
|
||||
bignum25519 nqpqx = {1}, nqpqz = {0}, nqz = {1}, nqx = {0};
|
||||
bignum25519 q = {0}, qx = {0}, qpqx = {0}, qqx = {0}, zzz = {0}, zmone = {0};
|
||||
size_t bit = 0, lastbit = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
curve25519_expand(q, basepoint);
|
||||
curve25519_copy(nqx, q);
|
||||
|
||||
/* bit 255 is always 0, and bit 254 is always 1, so skip bit 255 and
|
||||
start pre-swapped on bit 254 */
|
||||
lastbit = 1;
|
||||
|
||||
/* we are doing bits 254..3 in the loop, but are swapping in bits 253..2 */
|
||||
for(i = 253; i >= 2; i--) {
|
||||
curve25519_add(qx, nqx, nqz);
|
||||
curve25519_sub(nqz, nqx, nqz);
|
||||
curve25519_add(qpqx, nqpqx, nqpqz);
|
||||
curve25519_sub(nqpqz, nqpqx, nqpqz);
|
||||
curve25519_mul(nqpqx, qpqx, nqz);
|
||||
curve25519_mul(nqpqz, qx, nqpqz);
|
||||
curve25519_add(qqx, nqpqx, nqpqz);
|
||||
curve25519_sub(nqpqz, nqpqx, nqpqz);
|
||||
curve25519_square(nqpqz, nqpqz);
|
||||
curve25519_square(nqpqx, qqx);
|
||||
curve25519_mul(nqpqz, nqpqz, q);
|
||||
curve25519_square(qx, qx);
|
||||
curve25519_square(nqz, nqz);
|
||||
curve25519_mul(nqx, qx, nqz);
|
||||
curve25519_sub(nqz, qx, nqz);
|
||||
curve25519_scalar_product(zzz, nqz, 121665);
|
||||
curve25519_add(zzz, zzz, qx);
|
||||
curve25519_mul(nqz, nqz, zzz);
|
||||
|
||||
bit = (n[i / 8] >> (i & 7)) & 1;
|
||||
curve25519_swap_conditional(nqx, nqpqx, bit ^ lastbit);
|
||||
curve25519_swap_conditional(nqz, nqpqz, bit ^ lastbit);
|
||||
lastbit = bit;
|
||||
}
|
||||
|
||||
/* the final 3 bits are always zero, so we only need to double */
|
||||
for(i = 0; i < 3; i++) {
|
||||
curve25519_add(qx, nqx, nqz);
|
||||
curve25519_sub(nqz, nqx, nqz);
|
||||
curve25519_square(qx, qx);
|
||||
curve25519_square(nqz, nqz);
|
||||
curve25519_mul(nqx, qx, nqz);
|
||||
curve25519_sub(nqz, qx, nqz);
|
||||
curve25519_scalar_product(zzz, nqz, 121665);
|
||||
curve25519_add(zzz, zzz, qx);
|
||||
curve25519_mul(nqz, nqz, zzz);
|
||||
}
|
||||
|
||||
curve25519_recip(zmone, nqz);
|
||||
curve25519_mul(nqz, nqx, zmone);
|
||||
curve25519_contract(mypublic, nqz);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/* Calculates nQ where Q is the x-coordinate of a point on the curve
|
||||
*
|
||||
* mypublic: the packed little endian x coordinate of the resulting curve point
|
||||
* n: a little endian, 32-byte number
|
||||
* basepoint: a packed little endian point of the curve
|
||||
*/
|
||||
|
||||
void curve25519_scalarmult_donna(
|
||||
curve25519_key mypublic,
|
||||
const curve25519_key n,
|
||||
const curve25519_key basepoint);
|
||||
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
|
||||
Ed25519 reference implementation using Ed25519-donna
|
||||
*/
|
||||
|
||||
/* define ED25519_SUFFIX to have it appended to the end of each public function */
|
||||
#ifdef ED25519_SUFFIX
|
||||
#define ED25519_FN3(fn, suffix) fn##suffix
|
||||
#define ED25519_FN2(fn, suffix) ED25519_FN3(fn, suffix)
|
||||
#define ED25519_FN(fn) ED25519_FN2(fn, ED25519_SUFFIX)
|
||||
#else
|
||||
#define ED25519_FN(fn) fn
|
||||
#endif
|
||||
|
||||
#include "ed25519_donna.h"
|
||||
#include "ed25519.h"
|
||||
|
||||
#include "ed25519_hash_custom.h"
|
||||
#include "../rand.h"
|
||||
#include "../memzero.h"
|
||||
|
||||
/*
|
||||
Generates a (extsk[0..31]) and aExt (extsk[32..63])
|
||||
*/
|
||||
DONNA_INLINE static void ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) {
|
||||
ed25519_hash(extsk, sk, 32);
|
||||
extsk[0] &= 248;
|
||||
extsk[31] &= 127;
|
||||
extsk[31] |= 64;
|
||||
}
|
||||
|
||||
static void ed25519_hram(
|
||||
hash_512bits hram,
|
||||
const ed25519_public_key R,
|
||||
const ed25519_public_key pk,
|
||||
const unsigned char* m,
|
||||
size_t mlen) {
|
||||
ed25519_hash_context ctx;
|
||||
ed25519_hash_init(&ctx);
|
||||
ed25519_hash_update(&ctx, R, 32);
|
||||
ed25519_hash_update(&ctx, pk, 32);
|
||||
ed25519_hash_update(&ctx, m, mlen);
|
||||
ed25519_hash_final(&ctx, hram);
|
||||
}
|
||||
|
||||
void ED25519_FN(ed25519_publickey)(const ed25519_secret_key sk, ed25519_public_key pk) {
|
||||
hash_512bits extsk = {0};
|
||||
ed25519_extsk(extsk, sk);
|
||||
ed25519_publickey_ext(extsk, pk);
|
||||
memzero(&extsk, sizeof(extsk));
|
||||
}
|
||||
|
||||
void ED25519_FN(ed25519_cosi_commit)(ed25519_secret_key nonce, ed25519_public_key commitment) {
|
||||
bignum256modm r = {0};
|
||||
ge25519 ALIGN(16) R;
|
||||
unsigned char extnonce[64] = {0};
|
||||
|
||||
/* r = random512 mod L */
|
||||
random_buffer(extnonce, sizeof(extnonce));
|
||||
expand256_modm(r, extnonce, sizeof(extnonce));
|
||||
memzero(&extnonce, sizeof(extnonce));
|
||||
contract256_modm(nonce, r);
|
||||
|
||||
/* R = rB */
|
||||
ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
|
||||
memzero(&r, sizeof(r));
|
||||
ge25519_pack(commitment, &R);
|
||||
}
|
||||
|
||||
int ED25519_FN(ed25519_cosi_sign)(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_secret_key nonce,
|
||||
const ed25519_public_key R,
|
||||
const ed25519_public_key pk,
|
||||
ed25519_cosi_signature sig) {
|
||||
bignum256modm r = {0}, S = {0}, a = {0};
|
||||
hash_512bits extsk = {0}, hram = {0};
|
||||
|
||||
ed25519_extsk(extsk, sk);
|
||||
|
||||
/* r */
|
||||
expand_raw256_modm(r, nonce);
|
||||
if(!is_reduced256_modm(r)) return -1;
|
||||
|
||||
/* S = H(R,A,m).. */
|
||||
ed25519_hram(hram, R, pk, m, mlen);
|
||||
expand256_modm(S, hram, 64);
|
||||
|
||||
/* S = H(R,A,m)a */
|
||||
expand256_modm(a, extsk, 32);
|
||||
memzero(&extsk, sizeof(extsk));
|
||||
mul256_modm(S, S, a);
|
||||
memzero(&a, sizeof(a));
|
||||
|
||||
/* S = (r + H(R,A,m)a) */
|
||||
add256_modm(S, S, r);
|
||||
memzero(&r, sizeof(r));
|
||||
|
||||
/* S = (r + H(R,A,m)a) mod L */
|
||||
contract256_modm(sig, S);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ED25519_FN(ed25519_sign_ext)(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_secret_key skext,
|
||||
ed25519_signature RS) {
|
||||
ed25519_hash_context ctx;
|
||||
bignum256modm r = {0}, S = {0}, a = {0};
|
||||
ge25519 ALIGN(16) R = {0};
|
||||
ge25519 ALIGN(16) A = {0};
|
||||
ed25519_public_key pk = {0};
|
||||
hash_512bits extsk = {0}, hashr = {0}, hram = {0};
|
||||
|
||||
/* we don't stretch the key through hashing first since its already 64 bytes */
|
||||
|
||||
memcpy(extsk, sk, 32);
|
||||
memcpy(extsk + 32, skext, 32);
|
||||
|
||||
/* r = H(aExt[32..64], m) */
|
||||
ed25519_hash_init(&ctx);
|
||||
ed25519_hash_update(&ctx, extsk + 32, 32);
|
||||
ed25519_hash_update(&ctx, m, mlen);
|
||||
ed25519_hash_final(&ctx, hashr);
|
||||
expand256_modm(r, hashr, 64);
|
||||
memzero(&hashr, sizeof(hashr));
|
||||
|
||||
/* R = rB */
|
||||
ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
|
||||
ge25519_pack(RS, &R);
|
||||
|
||||
/* a = aExt[0..31] */
|
||||
expand256_modm(a, extsk, 32);
|
||||
memzero(&extsk, sizeof(extsk));
|
||||
|
||||
/* A = aB */
|
||||
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
|
||||
ge25519_pack(pk, &A);
|
||||
|
||||
/* S = H(R,A,m).. */
|
||||
ed25519_hram(hram, RS, pk, m, mlen);
|
||||
expand256_modm(S, hram, 64);
|
||||
|
||||
/* S = H(R,A,m)a */
|
||||
mul256_modm(S, S, a);
|
||||
memzero(&a, sizeof(a));
|
||||
|
||||
/* S = (r + H(R,A,m)a) */
|
||||
add256_modm(S, S, r);
|
||||
memzero(&r, sizeof(r));
|
||||
|
||||
/* S = (r + H(R,A,m)a) mod L */
|
||||
contract256_modm(RS + 32, S);
|
||||
}
|
||||
|
||||
void ED25519_FN(ed25519_sign)(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
ed25519_signature RS) {
|
||||
hash_512bits extsk = {0};
|
||||
ed25519_extsk(extsk, sk);
|
||||
ED25519_FN(ed25519_sign_ext)(m, mlen, extsk, extsk + 32, RS);
|
||||
memzero(&extsk, sizeof(extsk));
|
||||
}
|
||||
|
||||
int ED25519_FN(ed25519_sign_open)(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_public_key pk,
|
||||
const ed25519_signature RS) {
|
||||
ge25519 ALIGN(16) R = {0}, A = {0};
|
||||
hash_512bits hash = {0};
|
||||
bignum256modm hram = {0}, S = {0};
|
||||
unsigned char checkR[32] = {0};
|
||||
|
||||
if((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) return -1;
|
||||
|
||||
/* hram = H(R,A,m) */
|
||||
ed25519_hram(hash, RS, pk, m, mlen);
|
||||
expand256_modm(hram, hash, 64);
|
||||
|
||||
/* S */
|
||||
expand_raw256_modm(S, RS + 32);
|
||||
if(!is_reduced256_modm(S)) return -1;
|
||||
|
||||
/* SB - H(R,A,m)A */
|
||||
ge25519_double_scalarmult_vartime(&R, &A, hram, S);
|
||||
ge25519_pack(checkR, &R);
|
||||
|
||||
/* check that R = SB - H(R,A,m)A */
|
||||
return ed25519_verify(RS, checkR, 32) ? 0 : -1;
|
||||
}
|
||||
|
||||
int ED25519_FN(ed25519_scalarmult)(
|
||||
ed25519_public_key res,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_public_key pk) {
|
||||
bignum256modm a = {0};
|
||||
ge25519 ALIGN(16) A = {0}, P = {0};
|
||||
hash_512bits extsk = {0};
|
||||
|
||||
ed25519_extsk(extsk, sk);
|
||||
expand256_modm(a, extsk, 32);
|
||||
memzero(&extsk, sizeof(extsk));
|
||||
|
||||
if(!ge25519_unpack_negative_vartime(&P, pk)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ge25519_scalarmult(&A, &P, a);
|
||||
memzero(&a, sizeof(a));
|
||||
curve25519_neg(A.x, A.x);
|
||||
ge25519_pack(res, &A);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ED25519_SUFFIX
|
||||
|
||||
#include "curve25519_donna_scalarmult_base.h"
|
||||
|
||||
void ed25519_publickey_ext(const ed25519_secret_key extsk, ed25519_public_key pk) {
|
||||
bignum256modm a = {0};
|
||||
ge25519 ALIGN(16) A = {0};
|
||||
|
||||
expand256_modm(a, extsk, 32);
|
||||
|
||||
/* A = aB */
|
||||
ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a);
|
||||
memzero(&a, sizeof(a));
|
||||
ge25519_pack(pk, &A);
|
||||
}
|
||||
|
||||
int ed25519_cosi_combine_publickeys(
|
||||
ed25519_public_key res,
|
||||
CONST ed25519_public_key* pks,
|
||||
size_t n) {
|
||||
size_t i = 0;
|
||||
ge25519 P = {0};
|
||||
ge25519_pniels sump = {0};
|
||||
ge25519_p1p1 sump1 = {0};
|
||||
|
||||
if(n == 1) {
|
||||
memcpy(res, pks, sizeof(ed25519_public_key));
|
||||
return 0;
|
||||
}
|
||||
if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
|
||||
return -1;
|
||||
}
|
||||
ge25519_full_to_pniels(&sump, &P);
|
||||
while(i < n - 1) {
|
||||
if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
|
||||
return -1;
|
||||
}
|
||||
ge25519_pnielsadd(&sump, &P, &sump);
|
||||
}
|
||||
if(!ge25519_unpack_negative_vartime(&P, pks[i++])) {
|
||||
return -1;
|
||||
}
|
||||
ge25519_pnielsadd_p1p1(&sump1, &P, &sump, 0);
|
||||
ge25519_p1p1_to_partial(&P, &sump1);
|
||||
curve25519_neg(P.x, P.x);
|
||||
ge25519_pack(res, &P);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ed25519_cosi_combine_signatures(
|
||||
ed25519_signature res,
|
||||
const ed25519_public_key R,
|
||||
CONST ed25519_cosi_signature* sigs,
|
||||
size_t n) {
|
||||
bignum256modm s = {0}, t = {0};
|
||||
size_t i = 0;
|
||||
|
||||
expand256_modm(s, sigs[i++], 32);
|
||||
while(i < n) {
|
||||
expand256_modm(t, sigs[i++], 32);
|
||||
add256_modm(s, s, t);
|
||||
}
|
||||
memcpy(res, R, 32);
|
||||
contract256_modm(res + 32, s);
|
||||
}
|
||||
|
||||
/*
|
||||
Fast Curve25519 basepoint scalar multiplication
|
||||
*/
|
||||
void curve25519_scalarmult_basepoint(curve25519_key pk, const curve25519_key e) {
|
||||
curve25519_key ec = {0};
|
||||
bignum256modm s = {0};
|
||||
bignum25519 ALIGN(16) yplusz = {0}, zminusy = {0};
|
||||
ge25519 ALIGN(16) p = {0};
|
||||
size_t i = 0;
|
||||
|
||||
/* clamp */
|
||||
for(i = 0; i < 32; i++) ec[i] = e[i];
|
||||
ec[0] &= 248;
|
||||
ec[31] &= 127;
|
||||
ec[31] |= 64;
|
||||
|
||||
expand_raw256_modm(s, ec);
|
||||
memzero(&ec, sizeof(ec));
|
||||
|
||||
/* scalar * basepoint */
|
||||
ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s);
|
||||
memzero(&s, sizeof(s));
|
||||
|
||||
/* u = (y + z) / (z - y) */
|
||||
curve25519_add(yplusz, p.y, p.z);
|
||||
curve25519_sub(zminusy, p.z, p.y);
|
||||
curve25519_recip(zminusy, zminusy);
|
||||
curve25519_mul(yplusz, yplusz, zminusy);
|
||||
curve25519_contract(pk, yplusz);
|
||||
}
|
||||
|
||||
void curve25519_scalarmult(
|
||||
curve25519_key mypublic,
|
||||
const curve25519_key secret,
|
||||
const curve25519_key basepoint) {
|
||||
curve25519_key e = {0};
|
||||
size_t i = 0;
|
||||
|
||||
for(i = 0; i < 32; ++i) e[i] = secret[i];
|
||||
e[0] &= 0xf8;
|
||||
e[31] &= 0x7f;
|
||||
e[31] |= 0x40;
|
||||
curve25519_scalarmult_donna(mypublic, e, basepoint);
|
||||
memzero(&e, sizeof(e));
|
||||
}
|
||||
|
||||
#endif // ED25519_SUFFIX
|
||||
@@ -1,78 +0,0 @@
|
||||
#ifndef ED25519_H
|
||||
#define ED25519_H
|
||||
|
||||
#include "../options.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned char ed25519_signature[64];
|
||||
typedef unsigned char ed25519_public_key[32];
|
||||
typedef unsigned char ed25519_secret_key[32];
|
||||
|
||||
typedef unsigned char curve25519_key[32];
|
||||
|
||||
typedef unsigned char ed25519_cosi_signature[32];
|
||||
|
||||
void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk);
|
||||
void ed25519_publickey_ext(const ed25519_secret_key extsk, ed25519_public_key pk);
|
||||
|
||||
int ed25519_sign_open(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_public_key pk,
|
||||
const ed25519_signature RS);
|
||||
void ed25519_sign(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
ed25519_signature RS);
|
||||
void ed25519_sign_ext(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_secret_key skext,
|
||||
ed25519_signature RS);
|
||||
|
||||
int ed25519_scalarmult(
|
||||
ed25519_public_key res,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_public_key pk);
|
||||
|
||||
void curve25519_scalarmult(
|
||||
curve25519_key mypublic,
|
||||
const curve25519_key secret,
|
||||
const curve25519_key basepoint);
|
||||
void curve25519_scalarmult_basepoint(curve25519_key mypublic, const curve25519_key secret);
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__ > 4
|
||||
#define CONST const
|
||||
#else
|
||||
#define CONST
|
||||
#endif
|
||||
|
||||
int ed25519_cosi_combine_publickeys(
|
||||
ed25519_public_key res,
|
||||
CONST ed25519_public_key* pks,
|
||||
size_t n);
|
||||
void ed25519_cosi_combine_signatures(
|
||||
ed25519_signature res,
|
||||
const ed25519_public_key R,
|
||||
CONST ed25519_cosi_signature* sigs,
|
||||
size_t n);
|
||||
void ed25519_cosi_commit(ed25519_secret_key nonce, ed25519_public_key commitment);
|
||||
int ed25519_cosi_sign(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key key,
|
||||
const ed25519_secret_key nonce,
|
||||
const ed25519_public_key R,
|
||||
const ed25519_public_key pk,
|
||||
ed25519_cosi_signature sig);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ED25519_H
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
Modified from the amd64-51-30k implementation by
|
||||
Daniel J. Bernstein
|
||||
Niels Duif
|
||||
Tanja Lange
|
||||
Peter Schwabe
|
||||
Bo-Yin Yang
|
||||
*/
|
||||
|
||||
#ifndef ED25519_DONNA_H
|
||||
#define ED25519_DONNA_H
|
||||
|
||||
#include "ed25519_donna_portable.h"
|
||||
|
||||
#include "curve25519_donna_32bit.h"
|
||||
|
||||
#include "curve25519_donna_helpers.h"
|
||||
|
||||
#include "modm_donna_32bit.h"
|
||||
|
||||
typedef unsigned char hash_512bits[64];
|
||||
|
||||
/*
|
||||
* Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2
|
||||
* with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555
|
||||
* Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960);
|
||||
*/
|
||||
|
||||
typedef struct ge25519_t {
|
||||
bignum25519 x, y, z, t;
|
||||
} ge25519;
|
||||
|
||||
typedef struct ge25519_p1p1_t {
|
||||
bignum25519 x, y, z, t;
|
||||
} ge25519_p1p1;
|
||||
|
||||
typedef struct ge25519_niels_t {
|
||||
bignum25519 ysubx, xaddy, t2d;
|
||||
} ge25519_niels;
|
||||
|
||||
typedef struct ge25519_pniels_t {
|
||||
bignum25519 ysubx, xaddy, z, t2d;
|
||||
} ge25519_pniels;
|
||||
|
||||
#include "ed25519_donna_basepoint_table.h"
|
||||
|
||||
#include "ed25519_donna_32bit_tables.h"
|
||||
|
||||
#include "ed25519_donna_impl_base.h"
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
extern const ge25519 ALIGN(16) ge25519_basepoint;
|
||||
|
||||
/*
|
||||
d
|
||||
*/
|
||||
|
||||
extern const bignum25519 ALIGN(16) ge25519_ecd;
|
||||
|
||||
extern const bignum25519 ALIGN(16) ge25519_ec2d;
|
||||
|
||||
/*
|
||||
sqrt(-1)
|
||||
*/
|
||||
|
||||
extern const bignum25519 ALIGN(16) ge25519_sqrtneg1;
|
||||
|
||||
extern const ge25519_niels ALIGN(16) ge25519_niels_sliding_multiples[32];
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
/* multiples of the base point in packed {ysubx, xaddy, t2d} form */
|
||||
extern const uint8_t ALIGN(16) ge25519_niels_base_multiples[256][96];
|
||||
@@ -1,829 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include "ed25519_donna.h"
|
||||
#include "../memzero.h"
|
||||
|
||||
/* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */
|
||||
/* d = -121665 / 121666 */
|
||||
#if !defined(NDEBUG)
|
||||
static const bignum25519 ALIGN(16) fe_d = {
|
||||
0x35978a3,
|
||||
0x0d37284,
|
||||
0x3156ebd,
|
||||
0x06a0a0e,
|
||||
0x001c029,
|
||||
0x179e898,
|
||||
0x3a03cbb,
|
||||
0x1ce7198,
|
||||
0x2e2b6ff,
|
||||
0x1480db3}; /* d */
|
||||
#endif
|
||||
static const bignum25519 ALIGN(16) fe_sqrtm1 = {
|
||||
0x20ea0b0,
|
||||
0x186c9d2,
|
||||
0x08f189d,
|
||||
0x035697f,
|
||||
0x0bd0c60,
|
||||
0x1fbd7a7,
|
||||
0x2804c9e,
|
||||
0x1e16569,
|
||||
0x004fc1d,
|
||||
0x0ae0c92}; /* sqrt(-1) */
|
||||
//static const bignum25519 ALIGN(16) fe_d2 = {
|
||||
// 0x2b2f159, 0x1a6e509, 0x22add7a, 0x0d4141d, 0x0038052, 0x0f3d130, 0x3407977, 0x19ce331, 0x1c56dff, 0x0901b67}; /* 2 * d */
|
||||
|
||||
/* A = 2 * (1 - d) / (1 + d) = 486662 */
|
||||
static const bignum25519 ALIGN(16) fe_ma2 = {
|
||||
0x33de3c9,
|
||||
0x1fff236,
|
||||
0x3ffffff,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff}; /* -A^2 */
|
||||
static const bignum25519 ALIGN(16) fe_ma = {
|
||||
0x3f892e7,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff,
|
||||
0x3ffffff,
|
||||
0x1ffffff}; /* -A */
|
||||
static const bignum25519 ALIGN(16) fe_fffb1 = {
|
||||
0x1e3bdff,
|
||||
0x025a2b3,
|
||||
0x18e5bab,
|
||||
0x0ba36ac,
|
||||
0x0b9afed,
|
||||
0x004e61c,
|
||||
0x31d645f,
|
||||
0x09d1bea,
|
||||
0x102529e,
|
||||
0x0063810}; /* sqrt(-2 * A * (A + 2)) */
|
||||
static const bignum25519 ALIGN(16) fe_fffb2 = {
|
||||
0x383650d,
|
||||
0x066df27,
|
||||
0x10405a4,
|
||||
0x1cfdd48,
|
||||
0x2b887f2,
|
||||
0x1e9a041,
|
||||
0x1d7241f,
|
||||
0x0612dc5,
|
||||
0x35fba5d,
|
||||
0x0cbe787}; /* sqrt(2 * A * (A + 2)) */
|
||||
static const bignum25519 ALIGN(16) fe_fffb3 = {
|
||||
0x0cfd387,
|
||||
0x1209e3a,
|
||||
0x3bad4fc,
|
||||
0x18ad34d,
|
||||
0x2ff6c02,
|
||||
0x0f25d12,
|
||||
0x15cdfe0,
|
||||
0x0e208ed,
|
||||
0x32eb3df,
|
||||
0x062d7bb}; /* sqrt(-sqrt(-1) * A * (A + 2)) */
|
||||
static const bignum25519 ALIGN(16) fe_fffb4 = {
|
||||
0x2b39186,
|
||||
0x14640ed,
|
||||
0x14930a7,
|
||||
0x04509fa,
|
||||
0x3b91bf0,
|
||||
0x0f7432e,
|
||||
0x07a443f,
|
||||
0x17f24d8,
|
||||
0x031067d,
|
||||
0x0690fcc}; /* sqrt(sqrt(-1) * A * (A + 2)) */
|
||||
|
||||
/*
|
||||
Timing safe memory compare
|
||||
*/
|
||||
int ed25519_verify(const unsigned char* x, const unsigned char* y, size_t len) {
|
||||
size_t differentbits = 0;
|
||||
while(len--) differentbits |= (*x++ ^ *y++);
|
||||
return (int)(1 & ((differentbits - 1) >> 8));
|
||||
}
|
||||
|
||||
/*
|
||||
conversions
|
||||
*/
|
||||
|
||||
void ge25519_p1p1_to_partial(ge25519* r, const ge25519_p1p1* p) {
|
||||
curve25519_mul(r->x, p->x, p->t);
|
||||
curve25519_mul(r->y, p->y, p->z);
|
||||
curve25519_mul(r->z, p->z, p->t);
|
||||
}
|
||||
|
||||
void ge25519_p1p1_to_full(ge25519* r, const ge25519_p1p1* p) {
|
||||
curve25519_mul(r->x, p->x, p->t);
|
||||
curve25519_mul(r->y, p->y, p->z);
|
||||
curve25519_mul(r->z, p->z, p->t);
|
||||
curve25519_mul(r->t, p->x, p->y);
|
||||
}
|
||||
|
||||
void ge25519_full_to_pniels(ge25519_pniels* p, const ge25519* r) {
|
||||
curve25519_sub(p->ysubx, r->y, r->x);
|
||||
curve25519_add(p->xaddy, r->y, r->x);
|
||||
curve25519_copy(p->z, r->z);
|
||||
curve25519_mul(p->t2d, r->t, ge25519_ec2d);
|
||||
}
|
||||
|
||||
/*
|
||||
adding & doubling
|
||||
*/
|
||||
|
||||
void ge25519_double_p1p1(ge25519_p1p1* r, const ge25519* p) {
|
||||
bignum25519 a = {0}, b = {0}, c = {0};
|
||||
|
||||
curve25519_square(a, p->x);
|
||||
curve25519_square(b, p->y);
|
||||
curve25519_square(c, p->z);
|
||||
curve25519_add_reduce(c, c, c);
|
||||
curve25519_add(r->x, p->x, p->y);
|
||||
curve25519_square(r->x, r->x);
|
||||
curve25519_add(r->y, b, a);
|
||||
curve25519_sub(r->z, b, a);
|
||||
curve25519_sub_after_basic(r->x, r->x, r->y);
|
||||
curve25519_sub_after_basic(r->t, c, r->z);
|
||||
}
|
||||
|
||||
#ifndef ED25519_NO_PRECOMP
|
||||
void ge25519_nielsadd2_p1p1(
|
||||
ge25519_p1p1* r,
|
||||
const ge25519* p,
|
||||
const ge25519_niels* q,
|
||||
unsigned char signbit) {
|
||||
const bignum25519* qb = (const bignum25519*)q;
|
||||
bignum25519* rb = (bignum25519*)r;
|
||||
bignum25519 a = {0}, b = {0}, c = {0};
|
||||
|
||||
curve25519_sub(a, p->y, p->x);
|
||||
curve25519_add(b, p->y, p->x);
|
||||
curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */
|
||||
curve25519_mul(r->x, b, qb[signbit ^ 1]); /* y for +, x for - */
|
||||
curve25519_add(r->y, r->x, a);
|
||||
curve25519_sub(r->x, r->x, a);
|
||||
curve25519_mul(c, p->t, q->t2d);
|
||||
curve25519_add_reduce(r->t, p->z, p->z);
|
||||
curve25519_copy(r->z, r->t);
|
||||
curve25519_add(rb[2 + signbit], rb[2 + signbit], c); /* z for +, t for - */
|
||||
curve25519_sub(rb[2 + (signbit ^ 1)], rb[2 + (signbit ^ 1)], c); /* t for +, z for - */
|
||||
}
|
||||
#endif
|
||||
|
||||
void ge25519_pnielsadd_p1p1(
|
||||
ge25519_p1p1* r,
|
||||
const ge25519* p,
|
||||
const ge25519_pniels* q,
|
||||
unsigned char signbit) {
|
||||
const bignum25519* qb = (const bignum25519*)q;
|
||||
bignum25519* rb = (bignum25519*)r;
|
||||
bignum25519 a = {0}, b = {0}, c = {0};
|
||||
|
||||
curve25519_sub(a, p->y, p->x);
|
||||
curve25519_add(b, p->y, p->x);
|
||||
curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */
|
||||
curve25519_mul(r->x, b, qb[signbit ^ 1]); /* xaddy for +, ysubx for - */
|
||||
curve25519_add(r->y, r->x, a);
|
||||
curve25519_sub(r->x, r->x, a);
|
||||
curve25519_mul(c, p->t, q->t2d);
|
||||
curve25519_mul(r->t, p->z, q->z);
|
||||
curve25519_add_reduce(r->t, r->t, r->t);
|
||||
curve25519_copy(r->z, r->t);
|
||||
curve25519_add(rb[2 + signbit], rb[2 + signbit], c); /* z for +, t for - */
|
||||
curve25519_sub(rb[2 + (signbit ^ 1)], rb[2 + (signbit ^ 1)], c); /* t for +, z for - */
|
||||
}
|
||||
|
||||
void ge25519_double_partial(ge25519* r, const ge25519* p) {
|
||||
ge25519_p1p1 t = {0};
|
||||
ge25519_double_p1p1(&t, p);
|
||||
ge25519_p1p1_to_partial(r, &t);
|
||||
}
|
||||
|
||||
void ge25519_double(ge25519* r, const ge25519* p) {
|
||||
ge25519_p1p1 t = {0};
|
||||
ge25519_double_p1p1(&t, p);
|
||||
ge25519_p1p1_to_full(r, &t);
|
||||
}
|
||||
|
||||
void ge25519_nielsadd2(ge25519* r, const ge25519_niels* q) {
|
||||
bignum25519 a = {0}, b = {0}, c = {0}, e = {0}, f = {0}, g = {0}, h = {0};
|
||||
|
||||
curve25519_sub(a, r->y, r->x);
|
||||
curve25519_add(b, r->y, r->x);
|
||||
curve25519_mul(a, a, q->ysubx);
|
||||
curve25519_mul(e, b, q->xaddy);
|
||||
curve25519_add(h, e, a);
|
||||
curve25519_sub(e, e, a);
|
||||
curve25519_mul(c, r->t, q->t2d);
|
||||
curve25519_add(f, r->z, r->z);
|
||||
curve25519_add_after_basic(g, f, c);
|
||||
curve25519_sub_after_basic(f, f, c);
|
||||
curve25519_mul(r->x, e, f);
|
||||
curve25519_mul(r->y, h, g);
|
||||
curve25519_mul(r->z, g, f);
|
||||
curve25519_mul(r->t, e, h);
|
||||
}
|
||||
|
||||
void ge25519_pnielsadd(ge25519_pniels* r, const ge25519* p, const ge25519_pniels* q) {
|
||||
bignum25519 a = {0}, b = {0}, c = {0}, x = {0}, y = {0}, z = {0}, t = {0};
|
||||
|
||||
curve25519_sub(a, p->y, p->x);
|
||||
curve25519_add(b, p->y, p->x);
|
||||
curve25519_mul(a, a, q->ysubx);
|
||||
curve25519_mul(x, b, q->xaddy);
|
||||
curve25519_add(y, x, a);
|
||||
curve25519_sub(x, x, a);
|
||||
curve25519_mul(c, p->t, q->t2d);
|
||||
curve25519_mul(t, p->z, q->z);
|
||||
curve25519_add(t, t, t);
|
||||
curve25519_add_after_basic(z, t, c);
|
||||
curve25519_sub_after_basic(t, t, c);
|
||||
curve25519_mul(r->xaddy, x, t);
|
||||
curve25519_mul(r->ysubx, y, z);
|
||||
curve25519_mul(r->z, z, t);
|
||||
curve25519_mul(r->t2d, x, y);
|
||||
curve25519_copy(y, r->ysubx);
|
||||
curve25519_sub(r->ysubx, r->ysubx, r->xaddy);
|
||||
curve25519_add(r->xaddy, r->xaddy, y);
|
||||
curve25519_mul(r->t2d, r->t2d, ge25519_ec2d);
|
||||
}
|
||||
|
||||
/*
|
||||
pack & unpack
|
||||
*/
|
||||
|
||||
void ge25519_pack(unsigned char r[32], const ge25519* p) {
|
||||
bignum25519 tx = {0}, ty = {0}, zi = {0};
|
||||
unsigned char parity[32] = {0};
|
||||
curve25519_recip(zi, p->z);
|
||||
curve25519_mul(tx, p->x, zi);
|
||||
curve25519_mul(ty, p->y, zi);
|
||||
curve25519_contract(r, ty);
|
||||
curve25519_contract(parity, tx);
|
||||
r[31] ^= ((parity[0] & 1) << 7);
|
||||
}
|
||||
|
||||
int ge25519_unpack_negative_vartime(ge25519* r, const unsigned char p[32]) {
|
||||
const unsigned char zero[32] = {0};
|
||||
const bignum25519 one = {1};
|
||||
unsigned char parity = p[31] >> 7;
|
||||
unsigned char check[32] = {0};
|
||||
bignum25519 t = {0}, root = {0}, num = {0}, den = {0}, d3 = {0};
|
||||
|
||||
curve25519_expand(r->y, p);
|
||||
curve25519_copy(r->z, one);
|
||||
curve25519_square(num, r->y); /* x = y^2 */
|
||||
curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */
|
||||
curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */
|
||||
curve25519_add(den, den, r->z); /* den = dy^2 + 1 */
|
||||
|
||||
/* Computation of sqrt(num/den) */
|
||||
/* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */
|
||||
curve25519_square(t, den);
|
||||
curve25519_mul(d3, t, den);
|
||||
curve25519_square(r->x, d3);
|
||||
curve25519_mul(r->x, r->x, den);
|
||||
curve25519_mul(r->x, r->x, num);
|
||||
curve25519_pow_two252m3(r->x, r->x);
|
||||
|
||||
/* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */
|
||||
curve25519_mul(r->x, r->x, d3);
|
||||
curve25519_mul(r->x, r->x, num);
|
||||
|
||||
/* 3. Check if either of the roots works: */
|
||||
curve25519_square(t, r->x);
|
||||
curve25519_mul(t, t, den);
|
||||
curve25519_sub_reduce(root, t, num);
|
||||
curve25519_contract(check, root);
|
||||
if(!ed25519_verify(check, zero, 32)) {
|
||||
curve25519_add_reduce(t, t, num);
|
||||
curve25519_contract(check, t);
|
||||
if(!ed25519_verify(check, zero, 32)) return 0;
|
||||
curve25519_mul(r->x, r->x, ge25519_sqrtneg1);
|
||||
}
|
||||
|
||||
curve25519_contract(check, r->x);
|
||||
if((check[0] & 1) == parity) {
|
||||
curve25519_copy(t, r->x);
|
||||
curve25519_neg(r->x, t);
|
||||
}
|
||||
curve25519_mul(r->t, r->x, r->y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
scalarmults
|
||||
*/
|
||||
|
||||
void ge25519_set_neutral(ge25519* r) {
|
||||
memzero(r, sizeof(ge25519));
|
||||
r->y[0] = 1;
|
||||
r->z[0] = 1;
|
||||
}
|
||||
|
||||
#define S1_SWINDOWSIZE 5
|
||||
#define S1_TABLE_SIZE (1 << (S1_SWINDOWSIZE - 2))
|
||||
#ifdef ED25519_NO_PRECOMP
|
||||
#define S2_SWINDOWSIZE 5
|
||||
#else
|
||||
#define S2_SWINDOWSIZE 7
|
||||
#endif
|
||||
#define S2_TABLE_SIZE (1 << (S2_SWINDOWSIZE - 2))
|
||||
|
||||
/* computes [s1]p1 + [s2]base */
|
||||
void ge25519_double_scalarmult_vartime(
|
||||
ge25519* r,
|
||||
const ge25519* p1,
|
||||
const bignum256modm s1,
|
||||
const bignum256modm s2) {
|
||||
signed char slide1[256] = {0}, slide2[256] = {0};
|
||||
ge25519_pniels pre1[S1_TABLE_SIZE] = {0};
|
||||
#ifdef ED25519_NO_PRECOMP
|
||||
ge25519_pniels pre2[S2_TABLE_SIZE] = {0};
|
||||
#endif
|
||||
ge25519 dp = {0};
|
||||
ge25519_p1p1 t = {0};
|
||||
int32_t i = 0;
|
||||
|
||||
memzero(&t, sizeof(ge25519_p1p1));
|
||||
contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
|
||||
contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE);
|
||||
|
||||
ge25519_double(&dp, p1);
|
||||
ge25519_full_to_pniels(pre1, p1);
|
||||
for(i = 0; i < S1_TABLE_SIZE - 1; i++) ge25519_pnielsadd(&pre1[i + 1], &dp, &pre1[i]);
|
||||
|
||||
#ifdef ED25519_NO_PRECOMP
|
||||
ge25519_double(&dp, &ge25519_basepoint);
|
||||
ge25519_full_to_pniels(pre2, &ge25519_basepoint);
|
||||
for(i = 0; i < S2_TABLE_SIZE - 1; i++) ge25519_pnielsadd(&pre2[i + 1], &dp, &pre2[i]);
|
||||
#endif
|
||||
|
||||
ge25519_set_neutral(r);
|
||||
|
||||
i = 255;
|
||||
while((i >= 0) && !(slide1[i] | slide2[i])) i--;
|
||||
|
||||
for(; i >= 0; i--) {
|
||||
ge25519_double_p1p1(&t, r);
|
||||
|
||||
if(slide1[i]) {
|
||||
ge25519_p1p1_to_full(r, &t);
|
||||
ge25519_pnielsadd_p1p1(
|
||||
&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
|
||||
}
|
||||
|
||||
if(slide2[i]) {
|
||||
ge25519_p1p1_to_full(r, &t);
|
||||
#ifdef ED25519_NO_PRECOMP
|
||||
ge25519_pnielsadd_p1p1(
|
||||
&t, r, &pre2[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
|
||||
#else
|
||||
ge25519_nielsadd2_p1p1(
|
||||
&t,
|
||||
r,
|
||||
&ge25519_niels_sliding_multiples[abs(slide2[i]) / 2],
|
||||
(unsigned char)slide2[i] >> 7);
|
||||
#endif
|
||||
}
|
||||
|
||||
ge25519_p1p1_to_partial(r, &t);
|
||||
}
|
||||
curve25519_mul(r->t, t.x, t.y);
|
||||
memzero(slide1, sizeof(slide1));
|
||||
memzero(slide2, sizeof(slide2));
|
||||
}
|
||||
|
||||
/* computes [s1]p1 + [s2]p2 */
|
||||
#if USE_MONERO
|
||||
void ge25519_double_scalarmult_vartime2(
|
||||
ge25519* r,
|
||||
const ge25519* p1,
|
||||
const bignum256modm s1,
|
||||
const ge25519* p2,
|
||||
const bignum256modm s2) {
|
||||
signed char slide1[256] = {0}, slide2[256] = {0};
|
||||
ge25519_pniels pre1[S1_TABLE_SIZE] = {0};
|
||||
ge25519_pniels pre2[S1_TABLE_SIZE] = {0};
|
||||
ge25519 dp = {0};
|
||||
ge25519_p1p1 t = {0};
|
||||
int32_t i = 0;
|
||||
|
||||
memzero(&t, sizeof(ge25519_p1p1));
|
||||
contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
|
||||
contract256_slidingwindow_modm(slide2, s2, S1_SWINDOWSIZE);
|
||||
|
||||
ge25519_double(&dp, p1);
|
||||
ge25519_full_to_pniels(pre1, p1);
|
||||
for(i = 0; i < S1_TABLE_SIZE - 1; i++) ge25519_pnielsadd(&pre1[i + 1], &dp, &pre1[i]);
|
||||
|
||||
ge25519_double(&dp, p2);
|
||||
ge25519_full_to_pniels(pre2, p2);
|
||||
for(i = 0; i < S1_TABLE_SIZE - 1; i++) ge25519_pnielsadd(&pre2[i + 1], &dp, &pre2[i]);
|
||||
|
||||
ge25519_set_neutral(r);
|
||||
|
||||
i = 255;
|
||||
while((i >= 0) && !(slide1[i] | slide2[i])) i--;
|
||||
|
||||
for(; i >= 0; i--) {
|
||||
ge25519_double_p1p1(&t, r);
|
||||
|
||||
if(slide1[i]) {
|
||||
ge25519_p1p1_to_full(r, &t);
|
||||
ge25519_pnielsadd_p1p1(
|
||||
&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
|
||||
}
|
||||
|
||||
if(slide2[i]) {
|
||||
ge25519_p1p1_to_full(r, &t);
|
||||
ge25519_pnielsadd_p1p1(
|
||||
&t, r, &pre2[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
|
||||
}
|
||||
|
||||
ge25519_p1p1_to_partial(r, &t);
|
||||
}
|
||||
curve25519_mul(r->t, t.x, t.y);
|
||||
memzero(slide1, sizeof(slide1));
|
||||
memzero(slide2, sizeof(slide2));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following conditional move stuff uses conditional moves.
|
||||
* I will check on which compilers this works, and provide suitable
|
||||
* workarounds for those where it doesn't.
|
||||
*
|
||||
* This works on gcc 4.x and above with -O3. Don't use -O2, this will
|
||||
* cause the code to not generate conditional moves. Don't use any -march=
|
||||
* with less than i686 on x86
|
||||
*/
|
||||
static void ge25519_cmove_stride4(long* r, long* p, long* pos, long* n, int stride) {
|
||||
long x0 = r[0], x1 = r[1], x2 = r[2], x3 = r[3], y0 = 0, y1 = 0, y2 = 0, y3 = 0;
|
||||
for(; p < n; p += stride) {
|
||||
volatile int flag = (p == pos);
|
||||
y0 = p[0];
|
||||
y1 = p[1];
|
||||
y2 = p[2];
|
||||
y3 = p[3];
|
||||
x0 = flag ? y0 : x0;
|
||||
x1 = flag ? y1 : x1;
|
||||
x2 = flag ? y2 : x2;
|
||||
x3 = flag ? y3 : x3;
|
||||
}
|
||||
r[0] = x0;
|
||||
r[1] = x1;
|
||||
r[2] = x2;
|
||||
r[3] = x3;
|
||||
}
|
||||
#define HAS_CMOVE_STRIDE4
|
||||
|
||||
static void ge25519_cmove_stride4b(long* r, long* p, long* pos, long* n, int stride) {
|
||||
long x0 = p[0], x1 = p[1], x2 = p[2], x3 = p[3], y0 = 0, y1 = 0, y2 = 0, y3 = 0;
|
||||
for(p += stride; p < n; p += stride) {
|
||||
volatile int flag = (p == pos);
|
||||
y0 = p[0];
|
||||
y1 = p[1];
|
||||
y2 = p[2];
|
||||
y3 = p[3];
|
||||
x0 = flag ? y0 : x0;
|
||||
x1 = flag ? y1 : x1;
|
||||
x2 = flag ? y2 : x2;
|
||||
x3 = flag ? y3 : x3;
|
||||
}
|
||||
r[0] = x0;
|
||||
r[1] = x1;
|
||||
r[2] = x2;
|
||||
r[3] = x3;
|
||||
}
|
||||
#define HAS_CMOVE_STRIDE4B
|
||||
|
||||
void ge25519_move_conditional_pniels_array(
|
||||
ge25519_pniels* r,
|
||||
const ge25519_pniels* p,
|
||||
int pos,
|
||||
int n) {
|
||||
#ifdef HAS_CMOVE_STRIDE4B
|
||||
size_t i = 0;
|
||||
for(i = 0; i < sizeof(ge25519_pniels) / sizeof(long); i += 4) {
|
||||
ge25519_cmove_stride4b(
|
||||
((long*)r) + i,
|
||||
((long*)p) + i,
|
||||
((long*)(p + pos)) + i,
|
||||
((long*)(p + n)) + i,
|
||||
sizeof(ge25519_pniels) / sizeof(long));
|
||||
}
|
||||
#else
|
||||
size_t i = 0;
|
||||
for(i = 0; i < n; i++) {
|
||||
ge25519_move_conditional_pniels(r, p + i, pos == i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ge25519_move_conditional_niels_array(ge25519_niels* r, const uint8_t p[8][96], int pos, int n) {
|
||||
size_t i = 0;
|
||||
for(i = 0; i < 96 / sizeof(long); i += 4) {
|
||||
ge25519_cmove_stride4(
|
||||
((long*)r) + i,
|
||||
((long*)p) + i,
|
||||
((long*)(p + pos)) + i,
|
||||
((long*)(p + n)) + i,
|
||||
96 / sizeof(long));
|
||||
}
|
||||
}
|
||||
|
||||
/* computes [s1]p1, constant time */
|
||||
void ge25519_scalarmult(ge25519* r, const ge25519* p1, const bignum256modm s1) {
|
||||
signed char slide1[64] = {0};
|
||||
ge25519_pniels pre1[9] = {0};
|
||||
ge25519_pniels pre = {0};
|
||||
ge25519 d1 = {0};
|
||||
ge25519_p1p1 t = {0};
|
||||
int32_t i = 0;
|
||||
|
||||
contract256_window4_modm(slide1, s1);
|
||||
|
||||
ge25519_full_to_pniels(pre1 + 1, p1);
|
||||
ge25519_double(&d1, p1);
|
||||
|
||||
ge25519_set_neutral(r);
|
||||
ge25519_full_to_pniels(pre1, r);
|
||||
|
||||
ge25519_full_to_pniels(pre1 + 2, &d1);
|
||||
for(i = 1; i < 7; i++) {
|
||||
ge25519_pnielsadd(&pre1[i + 2], &d1, &pre1[i]);
|
||||
}
|
||||
|
||||
for(i = 63; i >= 0; i--) {
|
||||
int k = abs(slide1[i]);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double_p1p1(&t, r);
|
||||
ge25519_move_conditional_pniels_array(&pre, pre1, k, 9);
|
||||
ge25519_p1p1_to_full(r, &t);
|
||||
ge25519_pnielsadd_p1p1(&t, r, &pre, (unsigned char)slide1[i] >> 7);
|
||||
ge25519_p1p1_to_partial(r, &t);
|
||||
}
|
||||
curve25519_mul(r->t, t.x, t.y);
|
||||
memzero(slide1, sizeof(slide1));
|
||||
}
|
||||
|
||||
void ge25519_scalarmult_base_choose_niels(
|
||||
ge25519_niels* t,
|
||||
const uint8_t table[256][96],
|
||||
uint32_t pos,
|
||||
signed char b) {
|
||||
bignum25519 neg = {0};
|
||||
uint32_t sign = (uint32_t)((unsigned char)b >> 7);
|
||||
uint32_t mask = ~(sign - 1);
|
||||
uint32_t u = (b + mask) ^ mask;
|
||||
|
||||
/* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */
|
||||
uint8_t packed[96] = {0};
|
||||
packed[0] = 1;
|
||||
packed[32] = 1;
|
||||
|
||||
ge25519_move_conditional_niels_array((ge25519_niels*)packed, &table[pos * 8], u - 1, 8);
|
||||
|
||||
/* expand in to t */
|
||||
curve25519_expand(t->ysubx, packed + 0);
|
||||
curve25519_expand(t->xaddy, packed + 32);
|
||||
curve25519_expand(t->t2d, packed + 64);
|
||||
|
||||
/* adjust for sign */
|
||||
curve25519_swap_conditional(t->ysubx, t->xaddy, sign);
|
||||
curve25519_neg(neg, t->t2d);
|
||||
curve25519_swap_conditional(t->t2d, neg, sign);
|
||||
}
|
||||
|
||||
/* computes [s]basepoint */
|
||||
void ge25519_scalarmult_base_niels(
|
||||
ge25519* r,
|
||||
const uint8_t basepoint_table[256][96],
|
||||
const bignum256modm s) {
|
||||
signed char b[64] = {0};
|
||||
uint32_t i = 0;
|
||||
ge25519_niels t = {0};
|
||||
|
||||
contract256_window4_modm(b, s);
|
||||
|
||||
ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]);
|
||||
curve25519_sub_reduce(r->x, t.xaddy, t.ysubx);
|
||||
curve25519_add_reduce(r->y, t.xaddy, t.ysubx);
|
||||
memzero(r->z, sizeof(bignum25519));
|
||||
curve25519_copy(r->t, t.t2d);
|
||||
r->z[0] = 2;
|
||||
for(i = 3; i < 64; i += 2) {
|
||||
ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
|
||||
ge25519_nielsadd2(r, &t);
|
||||
}
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double(r, r);
|
||||
ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]);
|
||||
curve25519_mul(t.t2d, t.t2d, ge25519_ecd);
|
||||
ge25519_nielsadd2(r, &t);
|
||||
for(i = 2; i < 64; i += 2) {
|
||||
ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
|
||||
ge25519_nielsadd2(r, &t);
|
||||
}
|
||||
}
|
||||
|
||||
int ge25519_check(const ge25519* r) {
|
||||
/* return (z % q != 0 and
|
||||
x * y % q == z * t % q and
|
||||
(y * y - x * x - z * z - ed25519.d * t * t) % q == 0)
|
||||
*/
|
||||
|
||||
bignum25519 z = {0}, lhs = {0}, rhs = {0}, tmp = {0}, res = {0};
|
||||
curve25519_reduce(z, r->z);
|
||||
|
||||
curve25519_mul(lhs, r->x, r->y);
|
||||
curve25519_mul(rhs, r->z, r->t);
|
||||
curve25519_sub_reduce(lhs, lhs, rhs);
|
||||
|
||||
curve25519_square(res, r->y);
|
||||
curve25519_square(tmp, r->x);
|
||||
curve25519_sub_reduce(res, res, tmp);
|
||||
curve25519_square(tmp, r->z);
|
||||
curve25519_sub_reduce(res, res, tmp);
|
||||
curve25519_square(tmp, r->t);
|
||||
curve25519_mul(tmp, tmp, ge25519_ecd);
|
||||
curve25519_sub_reduce(res, res, tmp);
|
||||
|
||||
const int c1 = curve25519_isnonzero(z);
|
||||
const int c2 = curve25519_isnonzero(lhs);
|
||||
const int c3 = curve25519_isnonzero(res);
|
||||
return c1 & (c2 ^ 0x1) & (c3 ^ 0x1);
|
||||
}
|
||||
|
||||
int ge25519_eq(const ge25519* a, const ge25519* b) {
|
||||
int eq = 1;
|
||||
bignum25519 t1 = {0}, t2 = {0};
|
||||
|
||||
eq &= ge25519_check(a);
|
||||
eq &= ge25519_check(b);
|
||||
|
||||
curve25519_mul(t1, a->x, b->z);
|
||||
curve25519_mul(t2, b->x, a->z);
|
||||
curve25519_sub_reduce(t1, t1, t2);
|
||||
eq &= curve25519_isnonzero(t1) ^ 1;
|
||||
|
||||
curve25519_mul(t1, a->y, b->z);
|
||||
curve25519_mul(t2, b->y, a->z);
|
||||
curve25519_sub_reduce(t1, t1, t2);
|
||||
eq &= curve25519_isnonzero(t1) ^ 1;
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
void ge25519_copy(ge25519* dst, const ge25519* src) {
|
||||
curve25519_copy(dst->x, src->x);
|
||||
curve25519_copy(dst->y, src->y);
|
||||
curve25519_copy(dst->z, src->z);
|
||||
curve25519_copy(dst->t, src->t);
|
||||
}
|
||||
|
||||
void ge25519_set_base(ge25519* r) {
|
||||
ge25519_copy(r, &ge25519_basepoint);
|
||||
}
|
||||
|
||||
void ge25519_mul8(ge25519* r, const ge25519* t) {
|
||||
ge25519_double_partial(r, t);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double(r, r);
|
||||
}
|
||||
|
||||
void ge25519_neg_partial(ge25519* r) {
|
||||
curve25519_neg(r->x, r->x);
|
||||
}
|
||||
|
||||
void ge25519_neg_full(ge25519* r) {
|
||||
curve25519_neg(r->x, r->x);
|
||||
curve25519_neg(r->t, r->t);
|
||||
}
|
||||
|
||||
void ge25519_reduce(ge25519* r, const ge25519* t) {
|
||||
curve25519_reduce(r->x, t->x);
|
||||
curve25519_reduce(r->y, t->y);
|
||||
curve25519_reduce(r->z, t->z);
|
||||
curve25519_reduce(r->t, t->t);
|
||||
}
|
||||
|
||||
void ge25519_norm(ge25519* r, const ge25519* t) {
|
||||
bignum25519 zinv = {0};
|
||||
curve25519_recip(zinv, t->z);
|
||||
curve25519_mul(r->x, t->x, zinv);
|
||||
curve25519_mul(r->y, t->y, zinv);
|
||||
curve25519_mul(r->t, r->x, r->y);
|
||||
curve25519_set(r->z, 1);
|
||||
}
|
||||
|
||||
void ge25519_add(ge25519* r, const ge25519* p, const ge25519* q, unsigned char signbit) {
|
||||
ge25519_pniels P_ni = {0};
|
||||
ge25519_p1p1 P_11 = {0};
|
||||
|
||||
ge25519_full_to_pniels(&P_ni, q);
|
||||
ge25519_pnielsadd_p1p1(&P_11, p, &P_ni, signbit);
|
||||
ge25519_p1p1_to_full(r, &P_11);
|
||||
}
|
||||
|
||||
void ge25519_fromfe_frombytes_vartime(ge25519* r, const unsigned char* s) {
|
||||
bignum25519 u = {0}, v = {0}, w = {0}, x = {0}, y = {0}, z = {0};
|
||||
unsigned char sign = 0;
|
||||
|
||||
curve25519_expand_reduce(u, s);
|
||||
|
||||
curve25519_square(v, u);
|
||||
curve25519_add_reduce(v, v, v); /* 2 * u^2 */
|
||||
curve25519_set(w, 1);
|
||||
curve25519_add_reduce(w, v, w); /* w = 2 * u^2 + 1 */
|
||||
|
||||
curve25519_square(x, w); /* w^2 */
|
||||
curve25519_mul(y, fe_ma2, v); /* -2 * A^2 * u^2 */
|
||||
curve25519_add_reduce(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */
|
||||
|
||||
curve25519_divpowm1(r->x, w, x); /* (w / x)^(m + 1) */
|
||||
curve25519_square(y, r->x);
|
||||
curve25519_mul(x, y, x);
|
||||
curve25519_sub_reduce(y, w, x);
|
||||
curve25519_copy(z, fe_ma);
|
||||
|
||||
if(curve25519_isnonzero(y)) {
|
||||
curve25519_add_reduce(y, w, x);
|
||||
if(curve25519_isnonzero(y)) {
|
||||
goto negative;
|
||||
} else {
|
||||
curve25519_mul(r->x, r->x, fe_fffb1);
|
||||
}
|
||||
} else {
|
||||
curve25519_mul(r->x, r->x, fe_fffb2);
|
||||
}
|
||||
curve25519_mul(r->x, r->x, u); /* u * sqrt(2 * A * (A + 2) * w / x) */
|
||||
curve25519_mul(z, z, v); /* -2 * A * u^2 */
|
||||
sign = 0;
|
||||
goto setsign;
|
||||
negative:
|
||||
curve25519_mul(x, x, fe_sqrtm1);
|
||||
curve25519_sub_reduce(y, w, x);
|
||||
if(curve25519_isnonzero(y)) {
|
||||
assert((curve25519_add_reduce(y, w, x), !curve25519_isnonzero(y)));
|
||||
curve25519_mul(r->x, r->x, fe_fffb3);
|
||||
} else {
|
||||
curve25519_mul(r->x, r->x, fe_fffb4);
|
||||
}
|
||||
/* r->x = sqrt(A * (A + 2) * w / x) */
|
||||
/* z = -A */
|
||||
sign = 1;
|
||||
setsign:
|
||||
if(curve25519_isnegative(r->x) != sign) {
|
||||
assert(curve25519_isnonzero(r->x));
|
||||
curve25519_neg(r->x, r->x);
|
||||
}
|
||||
curve25519_add_reduce(r->z, z, w);
|
||||
curve25519_sub_reduce(r->y, z, w);
|
||||
curve25519_mul(r->x, r->x, r->z);
|
||||
|
||||
// Partial form, saving from T coord computation .
|
||||
// Later is mul8 discarding T anyway.
|
||||
// rt = ((rx * ry % q) * inv(rz)) % q
|
||||
// curve25519_mul(x, r->x, r->y);
|
||||
// curve25519_recip(z, r->z);
|
||||
// curve25519_mul(r->t, x, z);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
{
|
||||
bignum25519 check_x = {0}, check_y = {0}, check_iz = {0}, check_v = {0};
|
||||
curve25519_recip(check_iz, r->z);
|
||||
curve25519_mul(check_x, r->x, check_iz);
|
||||
curve25519_mul(check_y, r->y, check_iz);
|
||||
curve25519_square(check_x, check_x);
|
||||
curve25519_square(check_y, check_y);
|
||||
curve25519_mul(check_v, check_x, check_y);
|
||||
curve25519_mul(check_v, fe_d, check_v);
|
||||
curve25519_add_reduce(check_v, check_v, check_x);
|
||||
curve25519_sub_reduce(check_v, check_v, check_y);
|
||||
curve25519_set(check_x, 1);
|
||||
curve25519_add_reduce(check_v, check_v, check_x);
|
||||
assert(!curve25519_isnonzero(check_v));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int ge25519_unpack_vartime(ge25519* r, const unsigned char* s) {
|
||||
int res = ge25519_unpack_negative_vartime(r, s);
|
||||
ge25519_neg_full(r);
|
||||
return res;
|
||||
}
|
||||
|
||||
void ge25519_scalarmult_base_wrapper(ge25519* r, const bignum256modm s) {
|
||||
ge25519_scalarmult_base_niels(r, ge25519_niels_base_multiples, s);
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
Timing safe memory compare
|
||||
*/
|
||||
int ed25519_verify(const unsigned char* x, const unsigned char* y, size_t len);
|
||||
|
||||
/*
|
||||
conversions
|
||||
*/
|
||||
|
||||
void ge25519_p1p1_to_partial(ge25519* r, const ge25519_p1p1* p);
|
||||
|
||||
void ge25519_p1p1_to_full(ge25519* r, const ge25519_p1p1* p);
|
||||
|
||||
void ge25519_full_to_pniels(ge25519_pniels* p, const ge25519* r);
|
||||
|
||||
/*
|
||||
adding & doubling
|
||||
*/
|
||||
|
||||
void ge25519_double_p1p1(ge25519_p1p1* r, const ge25519* p);
|
||||
|
||||
#ifndef ED25519_NO_PRECOMP
|
||||
void ge25519_nielsadd2_p1p1(
|
||||
ge25519_p1p1* r,
|
||||
const ge25519* p,
|
||||
const ge25519_niels* q,
|
||||
unsigned char signbit);
|
||||
#endif
|
||||
|
||||
/* computes [s1]p1 + [s2]p2 */
|
||||
//#if USE_MONERO
|
||||
void ge25519_double_scalarmult_vartime2(
|
||||
ge25519* r,
|
||||
const ge25519* p1,
|
||||
const bignum256modm s1,
|
||||
const ge25519* p2,
|
||||
const bignum256modm s2);
|
||||
//#endif
|
||||
|
||||
void ge25519_pnielsadd_p1p1(
|
||||
ge25519_p1p1* r,
|
||||
const ge25519* p,
|
||||
const ge25519_pniels* q,
|
||||
unsigned char signbit);
|
||||
|
||||
void ge25519_double_partial(ge25519* r, const ge25519* p);
|
||||
|
||||
void ge25519_double(ge25519* r, const ge25519* p);
|
||||
|
||||
void ge25519_nielsadd2(ge25519* r, const ge25519_niels* q);
|
||||
|
||||
void ge25519_pnielsadd(ge25519_pniels* r, const ge25519* p, const ge25519_pniels* q);
|
||||
|
||||
/*
|
||||
pack & unpack
|
||||
*/
|
||||
|
||||
void ge25519_pack(unsigned char r[32], const ge25519* p);
|
||||
|
||||
int ge25519_unpack_negative_vartime(ge25519* r, const unsigned char p[32]);
|
||||
|
||||
/*
|
||||
scalarmults
|
||||
*/
|
||||
|
||||
void ge25519_set_neutral(ge25519* r);
|
||||
|
||||
/* computes [s1]p1 + [s2]base */
|
||||
void ge25519_double_scalarmult_vartime(
|
||||
ge25519* r,
|
||||
const ge25519* p1,
|
||||
const bignum256modm s1,
|
||||
const bignum256modm s2);
|
||||
|
||||
/* computes [s1]p1, constant time */
|
||||
void ge25519_scalarmult(ge25519* r, const ge25519* p1, const bignum256modm s1);
|
||||
|
||||
void ge25519_scalarmult_base_choose_niels(
|
||||
ge25519_niels* t,
|
||||
const uint8_t table[256][96],
|
||||
uint32_t pos,
|
||||
signed char b);
|
||||
|
||||
/* computes [s]basepoint */
|
||||
void ge25519_scalarmult_base_niels(
|
||||
ge25519* r,
|
||||
const uint8_t basepoint_table[256][96],
|
||||
const bignum256modm s);
|
||||
|
||||
/* check if r is on curve */
|
||||
int ge25519_check(const ge25519* r);
|
||||
|
||||
/* a == b */
|
||||
int ge25519_eq(const ge25519* a, const ge25519* b);
|
||||
|
||||
/* copies one point to another */
|
||||
void ge25519_copy(ge25519* dst, const ge25519* src);
|
||||
|
||||
/* sets B point to r */
|
||||
void ge25519_set_base(ge25519* r);
|
||||
|
||||
/* 8*P */
|
||||
void ge25519_mul8(ge25519* r, const ge25519* t);
|
||||
|
||||
/* -P */
|
||||
void ge25519_neg_partial(ge25519* r);
|
||||
|
||||
/* -P */
|
||||
void ge25519_neg_full(ge25519* r);
|
||||
|
||||
/* reduce all coords */
|
||||
void ge25519_reduce(ge25519* r, const ge25519* t);
|
||||
|
||||
/* normalizes coords. (x, y, 1, x*y) */
|
||||
void ge25519_norm(ge25519* r, const ge25519* t);
|
||||
|
||||
/* Simple addition */
|
||||
void ge25519_add(ge25519* r, const ge25519* a, const ge25519* b, unsigned char signbit);
|
||||
|
||||
/* point from bytes, used in H_p() */
|
||||
void ge25519_fromfe_frombytes_vartime(ge25519* r, const unsigned char* s);
|
||||
|
||||
/* point from bytes */
|
||||
int ge25519_unpack_vartime(ge25519* r, const unsigned char* s);
|
||||
|
||||
/* aG, wrapper for niels base mult. */
|
||||
void ge25519_scalarmult_base_wrapper(ge25519* r, const bignum256modm s);
|
||||
@@ -1,22 +0,0 @@
|
||||
#define mul32x32_64(a, b) (((uint64_t)(a)) * (b))
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define DONNA_INLINE
|
||||
#undef ALIGN
|
||||
#define ALIGN(x) __attribute__((aligned(x)))
|
||||
|
||||
static inline void U32TO8_LE(unsigned char* p, const uint32_t v) {
|
||||
p[0] = (unsigned char)(v);
|
||||
p[1] = (unsigned char)(v >> 8);
|
||||
p[2] = (unsigned char)(v >> 16);
|
||||
p[3] = (unsigned char)(v >> 24);
|
||||
}
|
||||
|
||||
static inline uint32_t U8TO32_LE(const unsigned char* p) {
|
||||
return (
|
||||
((uint32_t)(p[0])) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) |
|
||||
((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
a custom hash must have a 512bit digest and implement:
|
||||
|
||||
struct ed25519_hash_context;
|
||||
|
||||
void ed25519_hash_init(ed25519_hash_context *ctx);
|
||||
void ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen);
|
||||
void ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash);
|
||||
void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen);
|
||||
*/
|
||||
|
||||
#ifndef ED25519_HASH_CUSTOM
|
||||
#define ED25519_HASH_CUSTOM
|
||||
|
||||
#include "../sha2.h"
|
||||
|
||||
#define ed25519_hash_context SHA512_CTX
|
||||
#define ed25519_hash_init(ctx) sha512_Init(ctx)
|
||||
#define ed25519_hash_update(ctx, in, inlen) sha512_Update((ctx), (in), (inlen))
|
||||
#define ed25519_hash_final(ctx, hash) sha512_Final((ctx), (hash))
|
||||
#define ed25519_hash(hash, in, inlen) sha512_Raw((in), (inlen), (hash))
|
||||
|
||||
#endif // ED25519_HASH_CUSTOM
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
a custom hash must have a 512bit digest and implement:
|
||||
|
||||
struct ed25519_hash_context;
|
||||
|
||||
void ed25519_hash_init(ed25519_hash_context *ctx);
|
||||
void ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen);
|
||||
void ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash);
|
||||
void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen);
|
||||
*/
|
||||
|
||||
#include "../options.h"
|
||||
|
||||
#if USE_KECCAK
|
||||
|
||||
#ifndef ED25519_HASH_CUSTOM
|
||||
#define ED25519_HASH_CUSTOM
|
||||
|
||||
#include "../sha3.h"
|
||||
|
||||
#define ed25519_hash_context SHA3_CTX
|
||||
#define ed25519_hash_init(ctx) keccak_512_Init(ctx)
|
||||
#define ed25519_hash_update(ctx, in, inlen) keccak_Update((ctx), (in), (inlen))
|
||||
#define ed25519_hash_final(ctx, hash) keccak_Final((ctx), (hash))
|
||||
#define ed25519_hash(hash, in, inlen) keccak_512((in), (inlen), (hash))
|
||||
|
||||
#endif // ED25519_HASH_CUSTOM
|
||||
|
||||
#endif // USE_KECCAK
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
a custom hash must have a 512bit digest and implement:
|
||||
|
||||
struct ed25519_hash_context;
|
||||
|
||||
void ed25519_hash_init(ed25519_hash_context *ctx);
|
||||
void ed25519_hash_update(ed25519_hash_context *ctx, const uint8_t *in, size_t inlen);
|
||||
void ed25519_hash_final(ed25519_hash_context *ctx, uint8_t *hash);
|
||||
void ed25519_hash(uint8_t *hash, const uint8_t *in, size_t inlen);
|
||||
*/
|
||||
|
||||
#ifndef ED25519_HASH_CUSTOM
|
||||
#define ED25519_HASH_CUSTOM
|
||||
|
||||
#include "../sha3.h"
|
||||
|
||||
#define ed25519_hash_context SHA3_CTX
|
||||
#define ed25519_hash_init(ctx) sha3_512_Init(ctx)
|
||||
#define ed25519_hash_update(ctx, in, inlen) sha3_Update((ctx), (in), (inlen))
|
||||
#define ed25519_hash_final(ctx, hash) sha3_Final((ctx), (hash))
|
||||
#define ed25519_hash(hash, in, inlen) sha3_512((in), (inlen), (hash))
|
||||
|
||||
#endif // ED25519_HASH_CUSTOM
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "../options.h"
|
||||
|
||||
#if USE_KECCAK
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ed25519_keccak.h"
|
||||
#include "ed25519_hash_custom_keccak.h"
|
||||
|
||||
#define ED25519_SUFFIX _keccak
|
||||
|
||||
#include "ed25519.c"
|
||||
|
||||
#endif // USE_KECCAK
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "../options.h"
|
||||
|
||||
#if USE_KECCAK
|
||||
|
||||
#ifndef ED25519_KECCAK_H
|
||||
#define ED25519_KECCAK_H
|
||||
|
||||
#include "ed25519.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ed25519_publickey_keccak(const ed25519_secret_key sk, ed25519_public_key pk);
|
||||
|
||||
int ed25519_sign_open_keccak(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_public_key pk,
|
||||
const ed25519_signature RS);
|
||||
void ed25519_sign_keccak(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
ed25519_signature RS);
|
||||
|
||||
int ed25519_scalarmult_keccak(
|
||||
ed25519_public_key res,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_public_key pk);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ED25519_KECCAK_H
|
||||
|
||||
#endif // USE_KECCAK
|
||||
@@ -1,8 +0,0 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ed25519_sha3.h"
|
||||
#include "ed25519_hash_custom_sha3.h"
|
||||
|
||||
#define ED25519_SUFFIX _sha3
|
||||
|
||||
#include "ed25519.c"
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef ED25519_SHA3_H
|
||||
#define ED25519_SHA3_H
|
||||
|
||||
#include "ed25519.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ed25519_publickey_sha3(const ed25519_secret_key sk, ed25519_public_key pk);
|
||||
|
||||
int ed25519_sign_open_sha3(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_public_key pk,
|
||||
const ed25519_signature RS);
|
||||
void ed25519_sign_sha3(
|
||||
const unsigned char* m,
|
||||
size_t mlen,
|
||||
const ed25519_secret_key sk,
|
||||
ed25519_signature RS);
|
||||
|
||||
int ed25519_scalarmult_sha3(
|
||||
ed25519_public_key res,
|
||||
const ed25519_secret_key sk,
|
||||
const ed25519_public_key pk);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ED25519_SHA3_H
|
||||
@@ -1,800 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ed25519_donna.h"
|
||||
|
||||
/*
|
||||
Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989
|
||||
|
||||
k = 32
|
||||
b = 1 << 8 = 256
|
||||
m = 2^252 + 27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
|
||||
mu = floor( b^(k*2) / m ) = 0xfffffffffffffffffffffffffffffffeb2106215d086329a7ed9ce5a30a2c131b
|
||||
*/
|
||||
|
||||
static const bignum256modm modm_m = {
|
||||
0x1cf5d3ed,
|
||||
0x20498c69,
|
||||
0x2f79cd65,
|
||||
0x37be77a8,
|
||||
0x00000014,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00001000};
|
||||
|
||||
static const bignum256modm modm_mu = {
|
||||
0x0a2c131b,
|
||||
0x3673968c,
|
||||
0x06329a7e,
|
||||
0x01885742,
|
||||
0x3fffeb21,
|
||||
0x3fffffff,
|
||||
0x3fffffff,
|
||||
0x3fffffff,
|
||||
0x000fffff};
|
||||
|
||||
static bignum256modm_element_t lt_modm(bignum256modm_element_t a, bignum256modm_element_t b) {
|
||||
return (a - b) >> 31;
|
||||
}
|
||||
|
||||
/* see HAC, Alg. 14.42 Step 4 */
|
||||
void reduce256_modm(bignum256modm r) {
|
||||
bignum256modm t = {0};
|
||||
bignum256modm_element_t b = 0, pb = 0, mask = 0;
|
||||
|
||||
/* t = r - m */
|
||||
pb = 0;
|
||||
pb += modm_m[0];
|
||||
b = lt_modm(r[0], pb);
|
||||
t[0] = (r[0] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[1];
|
||||
b = lt_modm(r[1], pb);
|
||||
t[1] = (r[1] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[2];
|
||||
b = lt_modm(r[2], pb);
|
||||
t[2] = (r[2] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[3];
|
||||
b = lt_modm(r[3], pb);
|
||||
t[3] = (r[3] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[4];
|
||||
b = lt_modm(r[4], pb);
|
||||
t[4] = (r[4] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[5];
|
||||
b = lt_modm(r[5], pb);
|
||||
t[5] = (r[5] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[6];
|
||||
b = lt_modm(r[6], pb);
|
||||
t[6] = (r[6] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[7];
|
||||
b = lt_modm(r[7], pb);
|
||||
t[7] = (r[7] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += modm_m[8];
|
||||
b = lt_modm(r[8], pb);
|
||||
t[8] = (r[8] - pb + (b << 16));
|
||||
|
||||
/* keep r if r was smaller than m */
|
||||
mask = b - 1;
|
||||
r[0] ^= mask & (r[0] ^ t[0]);
|
||||
r[1] ^= mask & (r[1] ^ t[1]);
|
||||
r[2] ^= mask & (r[2] ^ t[2]);
|
||||
r[3] ^= mask & (r[3] ^ t[3]);
|
||||
r[4] ^= mask & (r[4] ^ t[4]);
|
||||
r[5] ^= mask & (r[5] ^ t[5]);
|
||||
r[6] ^= mask & (r[6] ^ t[6]);
|
||||
r[7] ^= mask & (r[7] ^ t[7]);
|
||||
r[8] ^= mask & (r[8] ^ t[8]);
|
||||
}
|
||||
|
||||
/*
|
||||
Barrett reduction, see HAC, Alg. 14.42
|
||||
|
||||
Instead of passing in x, pre-process in to q1 and r1 for efficiency
|
||||
*/
|
||||
void barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1) {
|
||||
bignum256modm q3 = {0}, r2 = {0};
|
||||
uint64_t c = 0;
|
||||
bignum256modm_element_t f = 0, b = 0, pb = 0;
|
||||
|
||||
/* q1 = x >> 248 = 264 bits = 9 30 bit elements
|
||||
q2 = mu * q1
|
||||
q3 = (q2 / 256(32+1)) = q2 / (2^8)^(32+1) = q2 >> 264 */
|
||||
c = mul32x32_64(modm_mu[0], q1[7]) + mul32x32_64(modm_mu[1], q1[6]) +
|
||||
mul32x32_64(modm_mu[2], q1[5]) + mul32x32_64(modm_mu[3], q1[4]) +
|
||||
mul32x32_64(modm_mu[4], q1[3]) + mul32x32_64(modm_mu[5], q1[2]) +
|
||||
mul32x32_64(modm_mu[6], q1[1]) + mul32x32_64(modm_mu[7], q1[0]);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[0], q1[8]) + mul32x32_64(modm_mu[1], q1[7]) +
|
||||
mul32x32_64(modm_mu[2], q1[6]) + mul32x32_64(modm_mu[3], q1[5]) +
|
||||
mul32x32_64(modm_mu[4], q1[4]) + mul32x32_64(modm_mu[5], q1[3]) +
|
||||
mul32x32_64(modm_mu[6], q1[2]) + mul32x32_64(modm_mu[7], q1[1]) +
|
||||
mul32x32_64(modm_mu[8], q1[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[0] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[1], q1[8]) + mul32x32_64(modm_mu[2], q1[7]) +
|
||||
mul32x32_64(modm_mu[3], q1[6]) + mul32x32_64(modm_mu[4], q1[5]) +
|
||||
mul32x32_64(modm_mu[5], q1[4]) + mul32x32_64(modm_mu[6], q1[3]) +
|
||||
mul32x32_64(modm_mu[7], q1[2]) + mul32x32_64(modm_mu[8], q1[1]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[0] |= (f << 6) & 0x3fffffff;
|
||||
q3[1] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[2], q1[8]) + mul32x32_64(modm_mu[3], q1[7]) +
|
||||
mul32x32_64(modm_mu[4], q1[6]) + mul32x32_64(modm_mu[5], q1[5]) +
|
||||
mul32x32_64(modm_mu[6], q1[4]) + mul32x32_64(modm_mu[7], q1[3]) +
|
||||
mul32x32_64(modm_mu[8], q1[2]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[1] |= (f << 6) & 0x3fffffff;
|
||||
q3[2] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[3], q1[8]) + mul32x32_64(modm_mu[4], q1[7]) +
|
||||
mul32x32_64(modm_mu[5], q1[6]) + mul32x32_64(modm_mu[6], q1[5]) +
|
||||
mul32x32_64(modm_mu[7], q1[4]) + mul32x32_64(modm_mu[8], q1[3]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[2] |= (f << 6) & 0x3fffffff;
|
||||
q3[3] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[4], q1[8]) + mul32x32_64(modm_mu[5], q1[7]) +
|
||||
mul32x32_64(modm_mu[6], q1[6]) + mul32x32_64(modm_mu[7], q1[5]) +
|
||||
mul32x32_64(modm_mu[8], q1[4]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[3] |= (f << 6) & 0x3fffffff;
|
||||
q3[4] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[5], q1[8]) + mul32x32_64(modm_mu[6], q1[7]) +
|
||||
mul32x32_64(modm_mu[7], q1[6]) + mul32x32_64(modm_mu[8], q1[5]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[4] |= (f << 6) & 0x3fffffff;
|
||||
q3[5] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[6], q1[8]) + mul32x32_64(modm_mu[7], q1[7]) +
|
||||
mul32x32_64(modm_mu[8], q1[6]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[5] |= (f << 6) & 0x3fffffff;
|
||||
q3[6] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[7], q1[8]) + mul32x32_64(modm_mu[8], q1[7]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[6] |= (f << 6) & 0x3fffffff;
|
||||
q3[7] = (f >> 24) & 0x3f;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_mu[8], q1[8]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q3[7] |= (f << 6) & 0x3fffffff;
|
||||
q3[8] = (bignum256modm_element_t)(c >> 24);
|
||||
|
||||
/* r1 = (x mod 256^(32+1)) = x mod (2^8)(32+1) = x & ((1 << 264) - 1)
|
||||
r2 = (q3 * m) mod (256^(32+1)) = (q3 * m) & ((1 << 264) - 1) */
|
||||
c = mul32x32_64(modm_m[0], q3[0]);
|
||||
r2[0] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[1]) + mul32x32_64(modm_m[1], q3[0]);
|
||||
r2[1] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[2]) + mul32x32_64(modm_m[1], q3[1]) +
|
||||
mul32x32_64(modm_m[2], q3[0]);
|
||||
r2[2] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[3]) + mul32x32_64(modm_m[1], q3[2]) +
|
||||
mul32x32_64(modm_m[2], q3[1]) + mul32x32_64(modm_m[3], q3[0]);
|
||||
r2[3] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[4]) + mul32x32_64(modm_m[1], q3[3]) +
|
||||
mul32x32_64(modm_m[2], q3[2]) + mul32x32_64(modm_m[3], q3[1]) +
|
||||
mul32x32_64(modm_m[4], q3[0]);
|
||||
r2[4] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[5]) + mul32x32_64(modm_m[1], q3[4]) +
|
||||
mul32x32_64(modm_m[2], q3[3]) + mul32x32_64(modm_m[3], q3[2]) +
|
||||
mul32x32_64(modm_m[4], q3[1]) + mul32x32_64(modm_m[5], q3[0]);
|
||||
r2[5] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[6]) + mul32x32_64(modm_m[1], q3[5]) +
|
||||
mul32x32_64(modm_m[2], q3[4]) + mul32x32_64(modm_m[3], q3[3]) +
|
||||
mul32x32_64(modm_m[4], q3[2]) + mul32x32_64(modm_m[5], q3[1]) +
|
||||
mul32x32_64(modm_m[6], q3[0]);
|
||||
r2[6] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[7]) + mul32x32_64(modm_m[1], q3[6]) +
|
||||
mul32x32_64(modm_m[2], q3[5]) + mul32x32_64(modm_m[3], q3[4]) +
|
||||
mul32x32_64(modm_m[4], q3[3]) + mul32x32_64(modm_m[5], q3[2]) +
|
||||
mul32x32_64(modm_m[6], q3[1]) + mul32x32_64(modm_m[7], q3[0]);
|
||||
r2[7] = (bignum256modm_element_t)(c & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(modm_m[0], q3[8]) + mul32x32_64(modm_m[1], q3[7]) +
|
||||
mul32x32_64(modm_m[2], q3[6]) + mul32x32_64(modm_m[3], q3[5]) +
|
||||
mul32x32_64(modm_m[4], q3[4]) + mul32x32_64(modm_m[5], q3[3]) +
|
||||
mul32x32_64(modm_m[6], q3[2]) + mul32x32_64(modm_m[7], q3[1]) +
|
||||
mul32x32_64(modm_m[8], q3[0]);
|
||||
r2[8] = (bignum256modm_element_t)(c & 0xffffff);
|
||||
|
||||
/* r = r1 - r2
|
||||
if (r < 0) r += (1 << 264) */
|
||||
pb = 0;
|
||||
pb += r2[0];
|
||||
b = lt_modm(r1[0], pb);
|
||||
r[0] = (r1[0] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[1];
|
||||
b = lt_modm(r1[1], pb);
|
||||
r[1] = (r1[1] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[2];
|
||||
b = lt_modm(r1[2], pb);
|
||||
r[2] = (r1[2] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[3];
|
||||
b = lt_modm(r1[3], pb);
|
||||
r[3] = (r1[3] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[4];
|
||||
b = lt_modm(r1[4], pb);
|
||||
r[4] = (r1[4] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[5];
|
||||
b = lt_modm(r1[5], pb);
|
||||
r[5] = (r1[5] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[6];
|
||||
b = lt_modm(r1[6], pb);
|
||||
r[6] = (r1[6] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[7];
|
||||
b = lt_modm(r1[7], pb);
|
||||
r[7] = (r1[7] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += r2[8];
|
||||
b = lt_modm(r1[8], pb);
|
||||
r[8] = (r1[8] - pb + (b << 24));
|
||||
|
||||
reduce256_modm(r);
|
||||
reduce256_modm(r);
|
||||
}
|
||||
|
||||
/* addition modulo m */
|
||||
void add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
|
||||
bignum256modm_element_t c = 0;
|
||||
|
||||
c = x[0] + y[0];
|
||||
r[0] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[1] + y[1];
|
||||
r[1] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[2] + y[2];
|
||||
r[2] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[3] + y[3];
|
||||
r[3] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[4] + y[4];
|
||||
r[4] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[5] + y[5];
|
||||
r[5] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[6] + y[6];
|
||||
r[6] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[7] + y[7];
|
||||
r[7] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += x[8] + y[8];
|
||||
r[8] = c;
|
||||
|
||||
reduce256_modm(r);
|
||||
}
|
||||
|
||||
/* -x modulo m */
|
||||
void neg256_modm(bignum256modm r, const bignum256modm x) {
|
||||
bignum256modm_element_t b = 0, pb = 0;
|
||||
|
||||
/* r = m - x */
|
||||
pb = 0;
|
||||
pb += x[0];
|
||||
b = lt_modm(modm_m[0], pb);
|
||||
r[0] = (modm_m[0] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[1];
|
||||
b = lt_modm(modm_m[1], pb);
|
||||
r[1] = (modm_m[1] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[2];
|
||||
b = lt_modm(modm_m[2], pb);
|
||||
r[2] = (modm_m[2] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[3];
|
||||
b = lt_modm(modm_m[3], pb);
|
||||
r[3] = (modm_m[3] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[4];
|
||||
b = lt_modm(modm_m[4], pb);
|
||||
r[4] = (modm_m[4] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[5];
|
||||
b = lt_modm(modm_m[5], pb);
|
||||
r[5] = (modm_m[5] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[6];
|
||||
b = lt_modm(modm_m[6], pb);
|
||||
r[6] = (modm_m[6] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[7];
|
||||
b = lt_modm(modm_m[7], pb);
|
||||
r[7] = (modm_m[7] - pb + (b << 30));
|
||||
pb = b;
|
||||
pb += x[8];
|
||||
b = lt_modm(modm_m[8], pb);
|
||||
r[8] = (modm_m[8] - pb + (b << 16));
|
||||
|
||||
// if x==0, reduction is required
|
||||
reduce256_modm(r);
|
||||
}
|
||||
|
||||
/* consts for subtraction, > p */
|
||||
/* Emilia Kasper trick, https://www.imperialviolet.org/2010/12/04/ecc.html */
|
||||
static const uint32_t twoP[] = {
|
||||
0x5cf5d3ed,
|
||||
0x60498c68,
|
||||
0x6f79cd64,
|
||||
0x77be77a7,
|
||||
0x40000013,
|
||||
0x3fffffff,
|
||||
0x3fffffff,
|
||||
0x3fffffff,
|
||||
0xfff};
|
||||
|
||||
/* subtraction x-y % m */
|
||||
void sub256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
|
||||
bignum256modm_element_t c = 0;
|
||||
c = twoP[0] + x[0] - y[0];
|
||||
r[0] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[1] + x[1] - y[1];
|
||||
r[1] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[2] + x[2] - y[2];
|
||||
r[2] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[3] + x[3] - y[3];
|
||||
r[3] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[4] + x[4] - y[4];
|
||||
r[4] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[5] + x[5] - y[5];
|
||||
r[5] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[6] + x[6] - y[6];
|
||||
r[6] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[7] + x[7] - y[7];
|
||||
r[7] = c & 0x3fffffff;
|
||||
c >>= 30;
|
||||
c += twoP[8] + x[8] - y[8];
|
||||
r[8] = c;
|
||||
reduce256_modm(r);
|
||||
}
|
||||
|
||||
/* multiplication modulo m */
|
||||
void mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y) {
|
||||
bignum256modm r1 = {0}, q1 = {0};
|
||||
uint64_t c = 0;
|
||||
bignum256modm_element_t f = 0;
|
||||
|
||||
/* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1)
|
||||
q1 = x >> 248 = 264 bits = 9 30 bit elements */
|
||||
c = mul32x32_64(x[0], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[0] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[1]) + mul32x32_64(x[1], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[1] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[2]) + mul32x32_64(x[1], y[1]) + mul32x32_64(x[2], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[2] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[3]) + mul32x32_64(x[1], y[2]) + mul32x32_64(x[2], y[1]) +
|
||||
mul32x32_64(x[3], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[3] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[4]) + mul32x32_64(x[1], y[3]) + mul32x32_64(x[2], y[2]) +
|
||||
mul32x32_64(x[3], y[1]) + mul32x32_64(x[4], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[4] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[5]) + mul32x32_64(x[1], y[4]) + mul32x32_64(x[2], y[3]) +
|
||||
mul32x32_64(x[3], y[2]) + mul32x32_64(x[4], y[1]) + mul32x32_64(x[5], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[5] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[6]) + mul32x32_64(x[1], y[5]) + mul32x32_64(x[2], y[4]) +
|
||||
mul32x32_64(x[3], y[3]) + mul32x32_64(x[4], y[2]) + mul32x32_64(x[5], y[1]) +
|
||||
mul32x32_64(x[6], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[6] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[7]) + mul32x32_64(x[1], y[6]) + mul32x32_64(x[2], y[5]) +
|
||||
mul32x32_64(x[3], y[4]) + mul32x32_64(x[4], y[3]) + mul32x32_64(x[5], y[2]) +
|
||||
mul32x32_64(x[6], y[1]) + mul32x32_64(x[7], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[7] = (f & 0x3fffffff);
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[0], y[8]) + mul32x32_64(x[1], y[7]) + mul32x32_64(x[2], y[6]) +
|
||||
mul32x32_64(x[3], y[5]) + mul32x32_64(x[4], y[4]) + mul32x32_64(x[5], y[3]) +
|
||||
mul32x32_64(x[6], y[2]) + mul32x32_64(x[7], y[1]) + mul32x32_64(x[8], y[0]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
r1[8] = (f & 0x00ffffff);
|
||||
q1[0] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[1], y[8]) + mul32x32_64(x[2], y[7]) + mul32x32_64(x[3], y[6]) +
|
||||
mul32x32_64(x[4], y[5]) + mul32x32_64(x[5], y[4]) + mul32x32_64(x[6], y[3]) +
|
||||
mul32x32_64(x[7], y[2]) + mul32x32_64(x[8], y[1]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[0] = (q1[0] | (f << 22)) & 0x3fffffff;
|
||||
q1[1] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[2], y[8]) + mul32x32_64(x[3], y[7]) + mul32x32_64(x[4], y[6]) +
|
||||
mul32x32_64(x[5], y[5]) + mul32x32_64(x[6], y[4]) + mul32x32_64(x[7], y[3]) +
|
||||
mul32x32_64(x[8], y[2]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[1] = (q1[1] | (f << 22)) & 0x3fffffff;
|
||||
q1[2] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[3], y[8]) + mul32x32_64(x[4], y[7]) + mul32x32_64(x[5], y[6]) +
|
||||
mul32x32_64(x[6], y[5]) + mul32x32_64(x[7], y[4]) + mul32x32_64(x[8], y[3]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[2] = (q1[2] | (f << 22)) & 0x3fffffff;
|
||||
q1[3] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[4], y[8]) + mul32x32_64(x[5], y[7]) + mul32x32_64(x[6], y[6]) +
|
||||
mul32x32_64(x[7], y[5]) + mul32x32_64(x[8], y[4]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[3] = (q1[3] | (f << 22)) & 0x3fffffff;
|
||||
q1[4] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[5], y[8]) + mul32x32_64(x[6], y[7]) + mul32x32_64(x[7], y[6]) +
|
||||
mul32x32_64(x[8], y[5]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[4] = (q1[4] | (f << 22)) & 0x3fffffff;
|
||||
q1[5] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[6], y[8]) + mul32x32_64(x[7], y[7]) + mul32x32_64(x[8], y[6]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[5] = (q1[5] | (f << 22)) & 0x3fffffff;
|
||||
q1[6] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[7], y[8]) + mul32x32_64(x[8], y[7]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[6] = (q1[6] | (f << 22)) & 0x3fffffff;
|
||||
q1[7] = (f >> 8) & 0x3fffff;
|
||||
c >>= 30;
|
||||
c += mul32x32_64(x[8], y[8]);
|
||||
f = (bignum256modm_element_t)c;
|
||||
q1[7] = (q1[7] | (f << 22)) & 0x3fffffff;
|
||||
q1[8] = (f >> 8) & 0x3fffff;
|
||||
|
||||
barrett_reduce256_modm(r, q1, r1);
|
||||
}
|
||||
|
||||
void expand256_modm(bignum256modm out, const unsigned char* in, size_t len) {
|
||||
unsigned char work[64] = {0};
|
||||
bignum256modm_element_t x[16] = {0};
|
||||
bignum256modm q1 = {0};
|
||||
|
||||
memcpy(work, in, len);
|
||||
x[0] = U8TO32_LE(work + 0);
|
||||
x[1] = U8TO32_LE(work + 4);
|
||||
x[2] = U8TO32_LE(work + 8);
|
||||
x[3] = U8TO32_LE(work + 12);
|
||||
x[4] = U8TO32_LE(work + 16);
|
||||
x[5] = U8TO32_LE(work + 20);
|
||||
x[6] = U8TO32_LE(work + 24);
|
||||
x[7] = U8TO32_LE(work + 28);
|
||||
x[8] = U8TO32_LE(work + 32);
|
||||
x[9] = U8TO32_LE(work + 36);
|
||||
x[10] = U8TO32_LE(work + 40);
|
||||
x[11] = U8TO32_LE(work + 44);
|
||||
x[12] = U8TO32_LE(work + 48);
|
||||
x[13] = U8TO32_LE(work + 52);
|
||||
x[14] = U8TO32_LE(work + 56);
|
||||
x[15] = U8TO32_LE(work + 60);
|
||||
|
||||
/* r1 = (x mod 256^(32+1)) = x mod (2^8)(31+1) = x & ((1 << 264) - 1) */
|
||||
out[0] = (x[0]) & 0x3fffffff;
|
||||
out[1] = ((x[0] >> 30) | (x[1] << 2)) & 0x3fffffff;
|
||||
out[2] = ((x[1] >> 28) | (x[2] << 4)) & 0x3fffffff;
|
||||
out[3] = ((x[2] >> 26) | (x[3] << 6)) & 0x3fffffff;
|
||||
out[4] = ((x[3] >> 24) | (x[4] << 8)) & 0x3fffffff;
|
||||
out[5] = ((x[4] >> 22) | (x[5] << 10)) & 0x3fffffff;
|
||||
out[6] = ((x[5] >> 20) | (x[6] << 12)) & 0x3fffffff;
|
||||
out[7] = ((x[6] >> 18) | (x[7] << 14)) & 0x3fffffff;
|
||||
out[8] = ((x[7] >> 16) | (x[8] << 16)) & 0x00ffffff;
|
||||
|
||||
/* 8*31 = 248 bits, no need to reduce */
|
||||
if(len < 32) return;
|
||||
|
||||
/* q1 = x >> 248 = 264 bits = 9 30 bit elements */
|
||||
q1[0] = ((x[7] >> 24) | (x[8] << 8)) & 0x3fffffff;
|
||||
q1[1] = ((x[8] >> 22) | (x[9] << 10)) & 0x3fffffff;
|
||||
q1[2] = ((x[9] >> 20) | (x[10] << 12)) & 0x3fffffff;
|
||||
q1[3] = ((x[10] >> 18) | (x[11] << 14)) & 0x3fffffff;
|
||||
q1[4] = ((x[11] >> 16) | (x[12] << 16)) & 0x3fffffff;
|
||||
q1[5] = ((x[12] >> 14) | (x[13] << 18)) & 0x3fffffff;
|
||||
q1[6] = ((x[13] >> 12) | (x[14] << 20)) & 0x3fffffff;
|
||||
q1[7] = ((x[14] >> 10) | (x[15] << 22)) & 0x3fffffff;
|
||||
q1[8] = ((x[15] >> 8));
|
||||
|
||||
barrett_reduce256_modm(out, q1, out);
|
||||
}
|
||||
|
||||
void expand_raw256_modm(bignum256modm out, const unsigned char in[32]) {
|
||||
bignum256modm_element_t x[8] = {0};
|
||||
|
||||
x[0] = U8TO32_LE(in + 0);
|
||||
x[1] = U8TO32_LE(in + 4);
|
||||
x[2] = U8TO32_LE(in + 8);
|
||||
x[3] = U8TO32_LE(in + 12);
|
||||
x[4] = U8TO32_LE(in + 16);
|
||||
x[5] = U8TO32_LE(in + 20);
|
||||
x[6] = U8TO32_LE(in + 24);
|
||||
x[7] = U8TO32_LE(in + 28);
|
||||
|
||||
out[0] = (x[0]) & 0x3fffffff;
|
||||
out[1] = ((x[0] >> 30) | (x[1] << 2)) & 0x3fffffff;
|
||||
out[2] = ((x[1] >> 28) | (x[2] << 4)) & 0x3fffffff;
|
||||
out[3] = ((x[2] >> 26) | (x[3] << 6)) & 0x3fffffff;
|
||||
out[4] = ((x[3] >> 24) | (x[4] << 8)) & 0x3fffffff;
|
||||
out[5] = ((x[4] >> 22) | (x[5] << 10)) & 0x3fffffff;
|
||||
out[6] = ((x[5] >> 20) | (x[6] << 12)) & 0x3fffffff;
|
||||
out[7] = ((x[6] >> 18) | (x[7] << 14)) & 0x3fffffff;
|
||||
out[8] = ((x[7] >> 16)) & 0x0000ffff;
|
||||
}
|
||||
|
||||
int is_reduced256_modm(const bignum256modm in) {
|
||||
int i = 0;
|
||||
uint32_t res1 = 0;
|
||||
uint32_t res2 = 0;
|
||||
for(i = 8; i >= 0; i--) {
|
||||
res1 = (res1 << 1) | (in[i] < modm_m[i]);
|
||||
res2 = (res2 << 1) | (in[i] > modm_m[i]);
|
||||
}
|
||||
return res1 > res2;
|
||||
}
|
||||
|
||||
void contract256_modm(unsigned char out[32], const bignum256modm in) {
|
||||
U32TO8_LE(out + 0, (in[0]) | (in[1] << 30));
|
||||
U32TO8_LE(out + 4, (in[1] >> 2) | (in[2] << 28));
|
||||
U32TO8_LE(out + 8, (in[2] >> 4) | (in[3] << 26));
|
||||
U32TO8_LE(out + 12, (in[3] >> 6) | (in[4] << 24));
|
||||
U32TO8_LE(out + 16, (in[4] >> 8) | (in[5] << 22));
|
||||
U32TO8_LE(out + 20, (in[5] >> 10) | (in[6] << 20));
|
||||
U32TO8_LE(out + 24, (in[6] >> 12) | (in[7] << 18));
|
||||
U32TO8_LE(out + 28, (in[7] >> 14) | (in[8] << 16));
|
||||
}
|
||||
|
||||
void contract256_window4_modm(signed char r[64], const bignum256modm in) {
|
||||
char carry = 0;
|
||||
signed char* quads = r;
|
||||
bignum256modm_element_t i = 0, j = 0, v = 0;
|
||||
|
||||
for(i = 0; i < 8; i += 2) {
|
||||
v = in[i];
|
||||
for(j = 0; j < 7; j++) {
|
||||
*quads++ = (v & 15);
|
||||
v >>= 4;
|
||||
}
|
||||
v |= (in[i + 1] << 2);
|
||||
for(j = 0; j < 8; j++) {
|
||||
*quads++ = (v & 15);
|
||||
v >>= 4;
|
||||
}
|
||||
}
|
||||
v = in[8];
|
||||
*quads++ = (v & 15);
|
||||
v >>= 4;
|
||||
*quads++ = (v & 15);
|
||||
v >>= 4;
|
||||
*quads++ = (v & 15);
|
||||
v >>= 4;
|
||||
*quads++ = (v & 15);
|
||||
v >>= 4;
|
||||
|
||||
/* making it signed */
|
||||
carry = 0;
|
||||
for(i = 0; i < 63; i++) {
|
||||
r[i] += carry;
|
||||
r[i + 1] += (r[i] >> 4);
|
||||
r[i] &= 15;
|
||||
carry = (r[i] >> 3);
|
||||
r[i] -= (carry << 4);
|
||||
}
|
||||
r[63] += carry;
|
||||
}
|
||||
|
||||
void contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize) {
|
||||
int i = 0, j = 0, k = 0, b = 0;
|
||||
int m = (1 << (windowsize - 1)) - 1, soplen = 256;
|
||||
signed char* bits = r;
|
||||
bignum256modm_element_t v = 0;
|
||||
|
||||
/* first put the binary expansion into r */
|
||||
for(i = 0; i < 8; i++) {
|
||||
v = s[i];
|
||||
for(j = 0; j < 30; j++, v >>= 1) *bits++ = (v & 1);
|
||||
}
|
||||
v = s[8];
|
||||
for(j = 0; j < 16; j++, v >>= 1) *bits++ = (v & 1);
|
||||
|
||||
/* Making it sliding window */
|
||||
for(j = 0; j < soplen; j++) {
|
||||
if(!r[j]) continue;
|
||||
|
||||
for(b = 1; (b < (soplen - j)) && (b <= 6); b++) {
|
||||
if((r[j] + (r[j + b] << b)) <= m) {
|
||||
r[j] += r[j + b] << b;
|
||||
r[j + b] = 0;
|
||||
} else if((r[j] - (r[j + b] << b)) >= -m) {
|
||||
r[j] -= r[j + b] << b;
|
||||
for(k = j + b; k < soplen; k++) {
|
||||
if(!r[k]) {
|
||||
r[k] = 1;
|
||||
break;
|
||||
}
|
||||
r[k] = 0;
|
||||
}
|
||||
} else if(r[j + b]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set256_modm(bignum256modm r, uint64_t v) {
|
||||
r[0] = (bignum256modm_element_t)(v & 0x3fffffff);
|
||||
v >>= 30;
|
||||
r[1] = (bignum256modm_element_t)(v & 0x3fffffff);
|
||||
v >>= 30;
|
||||
r[2] = (bignum256modm_element_t)(v & 0x3fffffff);
|
||||
r[3] = 0;
|
||||
r[4] = 0;
|
||||
r[5] = 0;
|
||||
r[6] = 0;
|
||||
r[7] = 0;
|
||||
r[8] = 0;
|
||||
}
|
||||
|
||||
int get256_modm(uint64_t* v, const bignum256modm r) {
|
||||
*v = 0;
|
||||
int con1 = 0;
|
||||
|
||||
#define NONZ(x) ((((((int64_t)(x)) - 1) >> 32) + 1) & 1)
|
||||
bignum256modm_element_t c = 0;
|
||||
c = r[0];
|
||||
*v += (uint64_t)c & 0x3fffffff;
|
||||
c >>= 30; // 30
|
||||
c += r[1];
|
||||
*v += ((uint64_t)c & 0x3fffffff) << 30;
|
||||
c >>= 30; // 60
|
||||
c += r[2];
|
||||
*v += ((uint64_t)c & 0xf) << 60;
|
||||
con1 |= NONZ(c >> 4);
|
||||
c >>= 30; // 64 bits
|
||||
c += r[3];
|
||||
con1 |= NONZ(c);
|
||||
c >>= 30;
|
||||
c += r[4];
|
||||
con1 |= NONZ(c);
|
||||
c >>= 30;
|
||||
c += r[5];
|
||||
con1 |= NONZ(c);
|
||||
c >>= 30;
|
||||
c += r[6];
|
||||
con1 |= NONZ(c);
|
||||
c >>= 30;
|
||||
c += r[7];
|
||||
con1 |= NONZ(c);
|
||||
c >>= 30;
|
||||
c += r[8];
|
||||
con1 |= NONZ(c);
|
||||
c >>= 30;
|
||||
con1 |= NONZ(c);
|
||||
#undef NONZ
|
||||
|
||||
return con1 ^ 1;
|
||||
}
|
||||
|
||||
int eq256_modm(const bignum256modm x, const bignum256modm y) {
|
||||
size_t differentbits = 0;
|
||||
int len = bignum256modm_limb_size;
|
||||
while(len--) {
|
||||
differentbits |= (*x++ ^ *y++);
|
||||
}
|
||||
return (int)(1 & ((differentbits - 1) >> bignum256modm_bits_per_limb));
|
||||
}
|
||||
|
||||
int cmp256_modm(const bignum256modm x, const bignum256modm y) {
|
||||
int len = 2 * bignum256modm_limb_size;
|
||||
uint32_t a_gt = 0;
|
||||
uint32_t b_gt = 0;
|
||||
|
||||
// 16B chunks
|
||||
while(len--) {
|
||||
const uint32_t ln = (const uint32_t)len;
|
||||
const uint32_t a = (x[ln >> 1] >> 16 * (ln & 1)) & 0xffff;
|
||||
const uint32_t b = (y[ln >> 1] >> 16 * (ln & 1)) & 0xffff;
|
||||
|
||||
const uint32_t limb_a_gt = ((b - a) >> 16) & 1;
|
||||
const uint32_t limb_b_gt = ((a - b) >> 16) & 1;
|
||||
a_gt |= limb_a_gt & ~b_gt;
|
||||
b_gt |= limb_b_gt & ~a_gt;
|
||||
}
|
||||
|
||||
return a_gt - b_gt;
|
||||
}
|
||||
|
||||
int iszero256_modm(const bignum256modm x) {
|
||||
size_t differentbits = 0;
|
||||
int len = bignum256modm_limb_size;
|
||||
while(len--) {
|
||||
differentbits |= (*x++);
|
||||
}
|
||||
return (int)(1 & ((differentbits - 1) >> bignum256modm_bits_per_limb));
|
||||
}
|
||||
|
||||
void copy256_modm(bignum256modm r, const bignum256modm x) {
|
||||
r[0] = x[0];
|
||||
r[1] = x[1];
|
||||
r[2] = x[2];
|
||||
r[3] = x[3];
|
||||
r[4] = x[4];
|
||||
r[5] = x[5];
|
||||
r[6] = x[6];
|
||||
r[7] = x[7];
|
||||
r[8] = x[8];
|
||||
}
|
||||
|
||||
int check256_modm(const bignum256modm x) {
|
||||
int ok = 1;
|
||||
bignum256modm t = {0}, z = {0};
|
||||
|
||||
ok &= iszero256_modm(x) ^ 1;
|
||||
barrett_reduce256_modm(t, z, x);
|
||||
ok &= eq256_modm(t, x);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void mulsub256_modm(
|
||||
bignum256modm r,
|
||||
const bignum256modm a,
|
||||
const bignum256modm b,
|
||||
const bignum256modm c) {
|
||||
//(cc - aa * bb) % l
|
||||
bignum256modm t = {0};
|
||||
mul256_modm(t, a, b);
|
||||
sub256_modm(r, c, t);
|
||||
}
|
||||
|
||||
void muladd256_modm(
|
||||
bignum256modm r,
|
||||
const bignum256modm a,
|
||||
const bignum256modm b,
|
||||
const bignum256modm c) {
|
||||
//(cc + aa * bb) % l
|
||||
bignum256modm t = {0};
|
||||
mul256_modm(t, a, b);
|
||||
add256_modm(r, c, t);
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Public domain by Andrew M. <liquidsun@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
Arithmetic modulo the group order n = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989
|
||||
|
||||
k = 32
|
||||
b = 1 << 8 = 256
|
||||
m = 2^252 + 27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
|
||||
mu = floor( b^(k*2) / m ) = 0xfffffffffffffffffffffffffffffffeb2106215d086329a7ed9ce5a30a2c131b
|
||||
*/
|
||||
|
||||
#define bignum256modm_bits_per_limb 30
|
||||
#define bignum256modm_limb_size 9
|
||||
|
||||
typedef uint32_t bignum256modm_element_t;
|
||||
typedef bignum256modm_element_t bignum256modm[9];
|
||||
|
||||
/* see HAC, Alg. 14.42 Step 4 */
|
||||
void reduce256_modm(bignum256modm r);
|
||||
|
||||
/*
|
||||
Barrett reduction, see HAC, Alg. 14.42
|
||||
|
||||
Instead of passing in x, pre-process in to q1 and r1 for efficiency
|
||||
*/
|
||||
void barrett_reduce256_modm(bignum256modm r, const bignum256modm q1, const bignum256modm r1);
|
||||
|
||||
/* addition modulo m */
|
||||
void add256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y);
|
||||
|
||||
/* -x modulo m */
|
||||
void neg256_modm(bignum256modm r, const bignum256modm x);
|
||||
|
||||
/* subtraction x-y modulo m */
|
||||
void sub256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y);
|
||||
|
||||
/* multiplication modulo m */
|
||||
void mul256_modm(bignum256modm r, const bignum256modm x, const bignum256modm y);
|
||||
|
||||
void expand256_modm(bignum256modm out, const unsigned char* in, size_t len);
|
||||
|
||||
void expand_raw256_modm(bignum256modm out, const unsigned char in[32]);
|
||||
|
||||
int is_reduced256_modm(const bignum256modm in);
|
||||
|
||||
void contract256_modm(unsigned char out[32], const bignum256modm in);
|
||||
|
||||
void contract256_window4_modm(signed char r[64], const bignum256modm in);
|
||||
|
||||
void contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize);
|
||||
|
||||
/* 64bit uint to scalar value */
|
||||
void set256_modm(bignum256modm r, uint64_t v);
|
||||
|
||||
/* scalar value to 64bit uint */
|
||||
int get256_modm(uint64_t* v, const bignum256modm r);
|
||||
|
||||
/* equality test on two reduced scalar values */
|
||||
int eq256_modm(const bignum256modm x, const bignum256modm y);
|
||||
|
||||
/* comparison of two reduced scalar values */
|
||||
int cmp256_modm(const bignum256modm x, const bignum256modm y);
|
||||
|
||||
/* scalar null check, has to be reduced */
|
||||
int iszero256_modm(const bignum256modm x);
|
||||
|
||||
/* simple copy, no reduction */
|
||||
void copy256_modm(bignum256modm r, const bignum256modm x);
|
||||
|
||||
/* check if nonzero && same after reduction */
|
||||
int check256_modm(const bignum256modm x);
|
||||
|
||||
/* (cc - aa * bb) % l */
|
||||
void mulsub256_modm(
|
||||
bignum256modm r,
|
||||
const bignum256modm a,
|
||||
const bignum256modm b,
|
||||
const bignum256modm c);
|
||||
|
||||
/* (cc + aa * bb) % l */
|
||||
void muladd256_modm(
|
||||
bignum256modm r,
|
||||
const bignum256modm a,
|
||||
const bignum256modm b,
|
||||
const bignum256modm c);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user