Add trezor bip39 code
This commit is contained in:
3
src/crypto/bip39/README.md
Normal file
3
src/crypto/bip39/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# trezor-firmware bip39
|
||||
|
||||
Imported from https://github.com/trezor/trezor-firmware/commit/047fcffde1f8530d3aee279b731e5e5f5901590a
|
||||
281
src/crypto/bip39/bip39.c
Normal file
281
src/crypto/bip39/bip39.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/**
|
||||
* 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 "bip39_english.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];
|
||||
|
||||
#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, wordlist[idx]);
|
||||
p += strlen(wordlist[idx]);
|
||||
*p = (i < mlen - 1) ? ' ' : 0;
|
||||
p++;
|
||||
}
|
||||
memzero(bits, sizeof(bits));
|
||||
|
||||
return mnemo;
|
||||
}
|
||||
|
||||
void mnemonic_clear(void) { memzero(mnemo, sizeof(mnemo)); }
|
||||
|
||||
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) {
|
||||
if (!mnemonic) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i = 0, n = 0;
|
||||
|
||||
while (mnemonic[i]) {
|
||||
if (mnemonic[i] == ' ') {
|
||||
n++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
n++;
|
||||
|
||||
// check number of words
|
||||
if (n != 12 && n != 18 && n != 24) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char current_word[10] = {0};
|
||||
uint32_t j = 0, k = 0, ki = 0, bi = 0;
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
|
||||
memzero(bits, sizeof(bits));
|
||||
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++;
|
||||
}
|
||||
k = 0;
|
||||
for (;;) {
|
||||
if (!wordlist[k]) { // word not found
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k
|
||||
for (ki = 0; ki < 11; ki++) {
|
||||
if (k & (1 << (10 - ki))) {
|
||||
bits[bi / 8] |= 1 << (7 - (bi % 8));
|
||||
}
|
||||
bi++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
if (bi != n * 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(entropy, bits, sizeof(bits));
|
||||
return n * 11;
|
||||
}
|
||||
|
||||
int mnemonic_check(const char *mnemonic) {
|
||||
uint8_t bits[32 + 1] = {0};
|
||||
int seed_len = mnemonic_to_entropy(mnemonic, bits);
|
||||
if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) {
|
||||
return 0;
|
||||
}
|
||||
int words = seed_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 = strnlen(passphrase, 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_WORDS - 1;
|
||||
while (lo <= hi) {
|
||||
int mid = lo + (hi - lo) / 2;
|
||||
int cmp = strcmp(word, wordlist[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 (const char *const *w = wordlist; *w != 0; w++) {
|
||||
if (strncmp(*w, prefix, len) == 0) {
|
||||
return *w;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *mnemonic_get_word(int index) {
|
||||
if (index >= 0 && index < BIP39_WORDS) {
|
||||
return wordlist[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 (const char *const *w = wordlist; *w != 0; w++) {
|
||||
const char *word = *w;
|
||||
if (strncmp(word, prefix, len) == 0 && word[len] >= 'a' &&
|
||||
word[len] <= 'z') {
|
||||
res |= 1 << (word[len] - 'a');
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
52
src/crypto/bip39/bip39.h
Normal file
52
src/crypto/bip39/bip39.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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>
|
||||
|
||||
#define BIP39_WORDS 2048
|
||||
#define BIP39_PBKDF2_ROUNDS 2048
|
||||
|
||||
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_entropy(const char *mnemonic, uint8_t *entropy);
|
||||
|
||||
// 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
|
||||
367
src/crypto/bip39/bip39_english.h
Normal file
367
src/crypto/bip39/bip39_english.h
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
static const char* const wordlist[] = {
|
||||
"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", 0,
|
||||
};
|
||||
176
src/crypto/bip39/hmac.c
Normal file
176
src/crypto/bip39/hmac.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* 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 <string.h>
|
||||
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen) {
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
sha256_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen) {
|
||||
sha256_Update(&(hctx->ctx), msg, msglen);
|
||||
}
|
||||
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) {
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH);
|
||||
sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH);
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac) {
|
||||
static CONFIDENTIAL HMAC_SHA256_CTX hctx;
|
||||
hmac_sha256_Init(&hctx, key, keylen);
|
||||
hmac_sha256_Update(&hctx, msg, msglen);
|
||||
hmac_sha256_Final(&hctx, hmac);
|
||||
}
|
||||
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint32_t *opad_digest, uint32_t *ipad_digest) {
|
||||
static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA256_CTX context;
|
||||
sha256_Init(&context);
|
||||
sha256_Update(&context, key, keylen);
|
||||
sha256_Final(&context, (uint8_t *)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
|
||||
uint32_t data = 0;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(key_pad[i], data);
|
||||
#else
|
||||
data = key_pad[i];
|
||||
#endif
|
||||
key_pad[i] = data ^ 0x5c5c5c5c;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest);
|
||||
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen) {
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
sha512_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen) {
|
||||
sha512_Update(&(hctx->ctx), msg, msglen);
|
||||
}
|
||||
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) {
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH);
|
||||
sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH);
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA512_CTX));
|
||||
}
|
||||
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac) {
|
||||
HMAC_SHA512_CTX hctx = {0};
|
||||
hmac_sha512_Init(&hctx, key, keylen);
|
||||
hmac_sha512_Update(&hctx, msg, msglen);
|
||||
hmac_sha512_Final(&hctx, hmac);
|
||||
}
|
||||
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint64_t *opad_digest, uint64_t *ipad_digest) {
|
||||
static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA512_CTX context;
|
||||
sha512_Init(&context);
|
||||
sha512_Update(&context, key, keylen);
|
||||
sha512_Final(&context, (uint8_t *)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
|
||||
uint64_t data = 0;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE64(key_pad[i], data);
|
||||
#else
|
||||
data = key_pad[i];
|
||||
#endif
|
||||
key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest);
|
||||
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
}
|
||||
60
src/crypto/bip39/hmac.h
Normal file
60
src/crypto/bip39/hmac.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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 HMAC_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 __HMAC_H__
|
||||
#define __HMAC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sha2.h"
|
||||
|
||||
typedef struct _HMAC_SHA256_CTX {
|
||||
uint8_t o_key_pad[SHA256_BLOCK_LENGTH];
|
||||
SHA256_CTX ctx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
typedef struct _HMAC_SHA512_CTX {
|
||||
uint8_t o_key_pad[SHA512_BLOCK_LENGTH];
|
||||
SHA512_CTX ctx;
|
||||
} HMAC_SHA512_CTX;
|
||||
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen);
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen);
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac);
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint32_t *opad_digest, uint32_t *ipad_digest);
|
||||
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen);
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen);
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac);
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint64_t *opad_digest, uint64_t *ipad_digest);
|
||||
|
||||
#endif
|
||||
130
src/crypto/bip39/hmac_drbg.c
Normal file
130
src/crypto/bip39/hmac_drbg.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Andrew R. Kozlik
|
||||
*
|
||||
* 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 "hmac_drbg.h"
|
||||
#include <string.h>
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
static void update_k(HMAC_DRBG_CTX *ctx, uint8_t domain, const uint8_t *data1,
|
||||
size_t len1, const uint8_t *data2, size_t len2) {
|
||||
// Computes K = HMAC(K, V || domain || data1 || data 2).
|
||||
|
||||
// First hash operation of HMAC.
|
||||
uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
|
||||
if (len1 + len2 == 0) {
|
||||
ctx->v[8] = 0x00800000;
|
||||
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
|
||||
sha256_Transform(ctx->idig, ctx->v, h);
|
||||
ctx->v[8] = 0x80000000;
|
||||
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
} else {
|
||||
SHA256_CTX sha_ctx = {0};
|
||||
memcpy(sha_ctx.state, ctx->idig, SHA256_DIGEST_LENGTH);
|
||||
for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(ctx->v[i], sha_ctx.buffer[i]);
|
||||
#else
|
||||
sha_ctx.buffer[i] = ctx->v[i];
|
||||
#endif
|
||||
}
|
||||
((uint8_t *)sha_ctx.buffer)[SHA256_DIGEST_LENGTH] = domain;
|
||||
sha_ctx.bitcount = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH + 1) * 8;
|
||||
sha256_Update(&sha_ctx, data1, len1);
|
||||
sha256_Update(&sha_ctx, data2, len2);
|
||||
sha256_Final(&sha_ctx, (uint8_t *)h);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (size_t i = 0; i < SHA256_DIGEST_LENGTH / sizeof(uint32_t); i++)
|
||||
REVERSE32(h[i], h[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Second hash operation of HMAC.
|
||||
h[8] = 0x80000000;
|
||||
h[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
sha256_Transform(ctx->odig, h, h);
|
||||
|
||||
// Precompute the inner digest and outer digest of K.
|
||||
h[8] = 0;
|
||||
h[15] = 0;
|
||||
for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
|
||||
h[i] ^= 0x36363636;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
|
||||
|
||||
for (size_t i = 0; i < SHA256_BLOCK_LENGTH / sizeof(uint32_t); i++) {
|
||||
h[i] = h[i] ^ 0x36363636 ^ 0x5c5c5c5c;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
|
||||
memzero(h, sizeof(h));
|
||||
}
|
||||
|
||||
static void update_v(HMAC_DRBG_CTX *ctx) {
|
||||
sha256_Transform(ctx->idig, ctx->v, ctx->v);
|
||||
sha256_Transform(ctx->odig, ctx->v, ctx->v);
|
||||
}
|
||||
|
||||
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *entropy,
|
||||
size_t entropy_len, const uint8_t *nonce,
|
||||
size_t nonce_len) {
|
||||
uint32_t h[SHA256_BLOCK_LENGTH / sizeof(uint32_t)] = {0};
|
||||
|
||||
// Precompute the inner digest and outer digest of K = 0x00 ... 0x00.
|
||||
memset(h, 0x36, sizeof(h));
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->idig);
|
||||
memset(h, 0x5c, sizeof(h));
|
||||
sha256_Transform(sha256_initial_hash_value, h, ctx->odig);
|
||||
|
||||
// Let V = 0x01 ... 0x01.
|
||||
memset(ctx->v, 1, SHA256_DIGEST_LENGTH);
|
||||
for (size_t i = 9; i < 15; i++) ctx->v[i] = 0;
|
||||
ctx->v[8] = 0x80000000;
|
||||
ctx->v[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
|
||||
hmac_drbg_reseed(ctx, entropy, entropy_len, nonce, nonce_len);
|
||||
|
||||
memzero(h, sizeof(h));
|
||||
}
|
||||
|
||||
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *entropy, size_t len,
|
||||
const uint8_t *addin, size_t addin_len) {
|
||||
update_k(ctx, 0, entropy, len, addin, addin_len);
|
||||
update_v(ctx);
|
||||
if (len == 0) return;
|
||||
update_k(ctx, 1, entropy, len, addin, addin_len);
|
||||
update_v(ctx);
|
||||
}
|
||||
|
||||
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len) {
|
||||
size_t i = 0;
|
||||
while (i < len) {
|
||||
update_v(ctx);
|
||||
for (size_t j = 0; j < 8 && i < len; j++) {
|
||||
uint32_t r = ctx->v[j];
|
||||
for (int k = 24; k >= 0 && i < len; k -= 8) {
|
||||
buf[i++] = (r >> k) & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
update_k(ctx, 0, NULL, 0, NULL, 0);
|
||||
update_v(ctx);
|
||||
}
|
||||
43
src/crypto/bip39/hmac_drbg.h
Normal file
43
src/crypto/bip39/hmac_drbg.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Andrew R. Kozlik
|
||||
*
|
||||
* 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 __HMAC_DRBG_H__
|
||||
#define __HMAC_DRBG_H__
|
||||
|
||||
#include <sha2.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// HMAC based Deterministic Random Bit Generator with SHA-256
|
||||
|
||||
typedef struct _HMAC_DRBG_CTX {
|
||||
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t v[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
} HMAC_DRBG_CTX;
|
||||
|
||||
void hmac_drbg_init(HMAC_DRBG_CTX *ctx, const uint8_t *buf, size_t len,
|
||||
const uint8_t *nonce, size_t nonce_len);
|
||||
void hmac_drbg_reseed(HMAC_DRBG_CTX *ctx, const uint8_t *buf, size_t len,
|
||||
const uint8_t *addin, size_t addin_len);
|
||||
void hmac_drbg_generate(HMAC_DRBG_CTX *ctx, uint8_t *buf, size_t len);
|
||||
|
||||
#endif
|
||||
8
src/crypto/bip39/memzero.h
Normal file
8
src/crypto/bip39/memzero.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef __MEMZERO_H__
|
||||
#define __MEMZERO_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void memzero(void* const pnt, const size_t len);
|
||||
|
||||
#endif
|
||||
99
src/crypto/bip39/options.h
Normal file
99
src/crypto/bip39/options.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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 __OPTIONS_H__
|
||||
#define __OPTIONS_H__
|
||||
|
||||
// use precomputed Curve Points (some scalar multiples of curve base point G)
|
||||
#ifndef USE_PRECOMPUTED_CP
|
||||
#define USE_PRECOMPUTED_CP 1
|
||||
#endif
|
||||
|
||||
// use fast inverse method
|
||||
#ifndef USE_INVERSE_FAST
|
||||
#define USE_INVERSE_FAST 1
|
||||
#endif
|
||||
|
||||
// support for printing bignum256 structures via printf
|
||||
#ifndef USE_BN_PRINT
|
||||
#define USE_BN_PRINT 0
|
||||
#endif
|
||||
|
||||
// use deterministic signatures
|
||||
#ifndef USE_RFC6979
|
||||
#define USE_RFC6979 1
|
||||
#endif
|
||||
|
||||
// implement BIP32 caching
|
||||
#ifndef USE_BIP32_CACHE
|
||||
#define USE_BIP32_CACHE 1
|
||||
#define BIP32_CACHE_SIZE 10
|
||||
#define BIP32_CACHE_MAXDEPTH 8
|
||||
#endif
|
||||
|
||||
// support constructing BIP32 nodes from ed25519 and curve25519 curves.
|
||||
#ifndef USE_BIP32_25519_CURVES
|
||||
#define USE_BIP32_25519_CURVES 1
|
||||
#endif
|
||||
|
||||
// implement BIP39 caching
|
||||
#ifndef USE_BIP39_CACHE
|
||||
#define USE_BIP39_CACHE 1
|
||||
#define BIP39_CACHE_SIZE 4
|
||||
#endif
|
||||
|
||||
// support Ethereum operations
|
||||
#ifndef USE_ETHEREUM
|
||||
#define USE_ETHEREUM 0
|
||||
#endif
|
||||
|
||||
// support Graphene operations (STEEM, BitShares)
|
||||
#ifndef USE_GRAPHENE
|
||||
#define USE_GRAPHENE 0
|
||||
#endif
|
||||
|
||||
// support NEM operations
|
||||
#ifndef USE_NEM
|
||||
#define USE_NEM 0
|
||||
#endif
|
||||
|
||||
// support MONERO operations
|
||||
#ifndef USE_MONERO
|
||||
#define USE_MONERO 0
|
||||
#endif
|
||||
|
||||
// support CARDANO operations
|
||||
#ifndef USE_CARDANO
|
||||
#define USE_CARDANO 0
|
||||
#endif
|
||||
|
||||
// support Keccak hashing
|
||||
#ifndef USE_KECCAK
|
||||
#define USE_KECCAK 1
|
||||
#endif
|
||||
|
||||
// add way how to mark confidential data
|
||||
#ifndef CONFIDENTIAL
|
||||
#define CONFIDENTIAL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
179
src/crypto/bip39/pbkdf2.c
Normal file
179
src/crypto/bip39/pbkdf2.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* 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 "pbkdf2.h"
|
||||
#include <string.h>
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr) {
|
||||
SHA256_CTX ctx = {0};
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
|
||||
hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x80000000;
|
||||
pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
|
||||
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount = SHA256_BLOCK_LENGTH * 8;
|
||||
sha256_Update(&ctx, salt, saltlen);
|
||||
sha256_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
|
||||
sha256_Final(&ctx, (uint8_t *)pctx->g);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
#endif
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
|
||||
uint32_t iterations) {
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha256_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH / sizeof(uint32_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
#endif
|
||||
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen) {
|
||||
uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA256_CTX pctx = {0};
|
||||
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha256_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH] = {0};
|
||||
pbkdf2_hmac_sha256_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr) {
|
||||
SHA512_CTX ctx = {0};
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
|
||||
hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x8000000000000000;
|
||||
pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
|
||||
|
||||
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
|
||||
ctx.bitcount[1] = 0;
|
||||
sha512_Update(&ctx, salt, saltlen);
|
||||
sha512_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
|
||||
sha512_Final(&ctx, (uint8_t *)pctx->g);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
#endif
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
|
||||
uint32_t iterations) {
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha512_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
#endif
|
||||
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen) {
|
||||
uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA512_CTX pctx = {0};
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha512_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA512_DIGEST_LENGTH] = {0};
|
||||
pbkdf2_hmac_sha512_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/crypto/bip39/pbkdf2.h
Normal file
66
src/crypto/bip39/pbkdf2.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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 __PBKDF2_H__
|
||||
#define __PBKDF2_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sha2.h"
|
||||
|
||||
typedef struct _PBKDF2_HMAC_SHA256_CTX {
|
||||
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
char first;
|
||||
} PBKDF2_HMAC_SHA256_CTX;
|
||||
|
||||
typedef struct _PBKDF2_HMAC_SHA512_CTX {
|
||||
uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
char first;
|
||||
} PBKDF2_HMAC_SHA512_CTX;
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
|
||||
uint32_t iterations);
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key);
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen);
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
|
||||
uint32_t iterations);
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key);
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen);
|
||||
|
||||
#endif
|
||||
81
src/crypto/bip39/rand.c
Normal file
81
src/crypto/bip39/rand.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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 "rand.h"
|
||||
|
||||
#ifndef RAND_PLATFORM_INDEPENDENT
|
||||
|
||||
#pragma message( \
|
||||
"NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.")
|
||||
|
||||
// The following code is not supposed to be used in a production environment.
|
||||
// It's included only to make the library testable.
|
||||
// The message above tries to prevent any accidental use outside of the test
|
||||
// environment.
|
||||
//
|
||||
// You are supposed to replace the random8() and random32() function with your
|
||||
// own secure code. There is also a possibility to replace the random_buffer()
|
||||
// function as it is defined as a weak symbol.
|
||||
|
||||
static uint32_t seed = 0;
|
||||
|
||||
void random_reseed(const uint32_t value) { seed = value; }
|
||||
|
||||
uint32_t random32(void) {
|
||||
// Linear congruential generator from Numerical Recipes
|
||||
// https://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
seed = 1664525 * seed + 1013904223;
|
||||
return seed;
|
||||
}
|
||||
|
||||
#endif /* RAND_PLATFORM_INDEPENDENT */
|
||||
|
||||
//
|
||||
// The following code is platform independent
|
||||
//
|
||||
|
||||
void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) {
|
||||
uint32_t r = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i % 4 == 0) {
|
||||
r = random32();
|
||||
}
|
||||
buf[i] = (r >> ((i % 4) * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t random_uniform(uint32_t n) {
|
||||
uint32_t x = 0, max = 0xFFFFFFFF - (0xFFFFFFFF % n);
|
||||
while ((x = random32()) >= max)
|
||||
;
|
||||
return x / (max / n);
|
||||
}
|
||||
|
||||
void random_permute(char *str, size_t len) {
|
||||
for (int i = len - 1; i >= 1; i--) {
|
||||
int j = random_uniform(i + 1);
|
||||
char t = str[j];
|
||||
str[j] = str[i];
|
||||
str[i] = t;
|
||||
}
|
||||
}
|
||||
37
src/crypto/bip39/rand.h
Normal file
37
src/crypto/bip39/rand.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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 __RAND_H__
|
||||
#define __RAND_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void random_reseed(const uint32_t value);
|
||||
uint32_t random32(void);
|
||||
void random_buffer(uint8_t *buf, size_t len);
|
||||
|
||||
uint32_t random_uniform(uint32_t n);
|
||||
void random_permute(char *buf, size_t len);
|
||||
|
||||
#endif
|
||||
1283
src/crypto/bip39/sha2.c
Normal file
1283
src/crypto/bip39/sha2.c
Normal file
File diff suppressed because it is too large
Load Diff
116
src/crypto/bip39/sha2.h
Normal file
116
src/crypto/bip39/sha2.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2001 Aaron D. Gifford
|
||||
* Copyright (c) 2013-2014 Pavol Rusnak
|
||||
* 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 contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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.
|
||||
*/
|
||||
|
||||
#ifndef __SHA2_H__
|
||||
#define __SHA2_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define SHA1_BLOCK_LENGTH 64
|
||||
#define SHA1_DIGEST_LENGTH 20
|
||||
#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1)
|
||||
#define SHA256_BLOCK_LENGTH 64
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
|
||||
#define SHA512_BLOCK_LENGTH 128
|
||||
#define SHA512_DIGEST_LENGTH 64
|
||||
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
|
||||
|
||||
typedef struct _SHA1_CTX {
|
||||
uint32_t state[5];
|
||||
uint64_t bitcount;
|
||||
uint32_t buffer[SHA1_BLOCK_LENGTH/sizeof(uint32_t)];
|
||||
} SHA1_CTX;
|
||||
typedef struct _SHA256_CTX {
|
||||
uint32_t state[8];
|
||||
uint64_t bitcount;
|
||||
uint32_t buffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];
|
||||
} SHA256_CTX;
|
||||
typedef struct _SHA512_CTX {
|
||||
uint64_t state[8];
|
||||
uint64_t bitcount[2];
|
||||
uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];
|
||||
} SHA512_CTX;
|
||||
|
||||
/*** ENDIAN REVERSAL MACROS *******************************************/
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#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 /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
|
||||
extern const uint32_t sha256_initial_hash_value[8];
|
||||
extern const uint64_t sha512_initial_hash_value[8];
|
||||
|
||||
void sha1_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
|
||||
void sha1_Init(SHA1_CTX *);
|
||||
void sha1_Update(SHA1_CTX*, const uint8_t*, size_t);
|
||||
void sha1_Final(SHA1_CTX*, uint8_t[SHA1_DIGEST_LENGTH]);
|
||||
char* sha1_End(SHA1_CTX*, char[SHA1_DIGEST_STRING_LENGTH]);
|
||||
void sha1_Raw(const uint8_t*, size_t, uint8_t[SHA1_DIGEST_LENGTH]);
|
||||
char* sha1_Data(const uint8_t*, size_t, char[SHA1_DIGEST_STRING_LENGTH]);
|
||||
|
||||
void sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
|
||||
void sha256_Init(SHA256_CTX *);
|
||||
void sha256_Update(SHA256_CTX*, const uint8_t*, size_t);
|
||||
void sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]);
|
||||
char* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
|
||||
void sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]);
|
||||
char* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
|
||||
|
||||
void sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out);
|
||||
void sha512_Init(SHA512_CTX*);
|
||||
void sha512_Update(SHA512_CTX*, const uint8_t*, size_t);
|
||||
void sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]);
|
||||
char* sha512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
|
||||
void sha512_Raw(const uint8_t*, size_t, uint8_t[SHA512_DIGEST_LENGTH]);
|
||||
char* sha512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
|
||||
|
||||
#endif
|
||||
397
src/crypto/bip39/sha3.c
Normal file
397
src/crypto/bip39/sha3.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
|
||||
* based on the
|
||||
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
|
||||
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
|
||||
*
|
||||
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha3.h"
|
||||
#include "memzero.h"
|
||||
|
||||
#define I64(x) x##LL
|
||||
#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
|
||||
#define le2me_64(x) (x)
|
||||
#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
|
||||
# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
|
||||
|
||||
/* constants */
|
||||
#define NumberOfRounds 24
|
||||
|
||||
/* SHA3 (Keccak) constants for 24 rounds */
|
||||
static uint64_t keccak_round_constants[NumberOfRounds] = {
|
||||
I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
|
||||
I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
|
||||
I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
|
||||
I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
|
||||
I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
|
||||
I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
|
||||
};
|
||||
|
||||
/* Initializing a sha3 context for given number of output bits */
|
||||
static void keccak_Init(SHA3_CTX *ctx, unsigned bits)
|
||||
{
|
||||
/* NB: The Keccak capacity parameter = bits * 2 */
|
||||
unsigned rate = 1600 - bits * 2;
|
||||
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
ctx->block_size = rate / 8;
|
||||
assert(rate <= 1600 && (rate % 64) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_224_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 224);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_256_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_384_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 384);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void sha3_512_Init(SHA3_CTX *ctx)
|
||||
{
|
||||
keccak_Init(ctx, 512);
|
||||
}
|
||||
|
||||
/* Keccak theta() transformation */
|
||||
static void keccak_theta(uint64_t *A)
|
||||
{
|
||||
unsigned int x = 0;
|
||||
uint64_t C[5] = {0}, D[5] = {0};
|
||||
|
||||
for (x = 0; x < 5; x++) {
|
||||
C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
|
||||
}
|
||||
D[0] = ROTL64(C[1], 1) ^ C[4];
|
||||
D[1] = ROTL64(C[2], 1) ^ C[0];
|
||||
D[2] = ROTL64(C[3], 1) ^ C[1];
|
||||
D[3] = ROTL64(C[4], 1) ^ C[2];
|
||||
D[4] = ROTL64(C[0], 1) ^ C[3];
|
||||
|
||||
for (x = 0; x < 5; x++) {
|
||||
A[x] ^= D[x];
|
||||
A[x + 5] ^= D[x];
|
||||
A[x + 10] ^= D[x];
|
||||
A[x + 15] ^= D[x];
|
||||
A[x + 20] ^= D[x];
|
||||
}
|
||||
}
|
||||
|
||||
/* Keccak pi() transformation */
|
||||
static void keccak_pi(uint64_t *A)
|
||||
{
|
||||
uint64_t A1 = 0;
|
||||
A1 = A[1];
|
||||
A[ 1] = A[ 6];
|
||||
A[ 6] = A[ 9];
|
||||
A[ 9] = A[22];
|
||||
A[22] = A[14];
|
||||
A[14] = A[20];
|
||||
A[20] = A[ 2];
|
||||
A[ 2] = A[12];
|
||||
A[12] = A[13];
|
||||
A[13] = A[19];
|
||||
A[19] = A[23];
|
||||
A[23] = A[15];
|
||||
A[15] = A[ 4];
|
||||
A[ 4] = A[24];
|
||||
A[24] = A[21];
|
||||
A[21] = A[ 8];
|
||||
A[ 8] = A[16];
|
||||
A[16] = A[ 5];
|
||||
A[ 5] = A[ 3];
|
||||
A[ 3] = A[18];
|
||||
A[18] = A[17];
|
||||
A[17] = A[11];
|
||||
A[11] = A[ 7];
|
||||
A[ 7] = A[10];
|
||||
A[10] = A1;
|
||||
/* note: A[ 0] is left as is */
|
||||
}
|
||||
|
||||
/* Keccak chi() transformation */
|
||||
static void keccak_chi(uint64_t *A)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < 25; i += 5) {
|
||||
uint64_t A0 = A[0 + i], A1 = A[1 + i];
|
||||
A[0 + i] ^= ~A1 & A[2 + i];
|
||||
A[1 + i] ^= ~A[2 + i] & A[3 + i];
|
||||
A[2 + i] ^= ~A[3 + i] & A[4 + i];
|
||||
A[3 + i] ^= ~A[4 + i] & A0;
|
||||
A[4 + i] ^= ~A0 & A1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sha3_permutation(uint64_t *state)
|
||||
{
|
||||
int round = 0;
|
||||
for (round = 0; round < NumberOfRounds; round++)
|
||||
{
|
||||
keccak_theta(state);
|
||||
|
||||
/* apply Keccak rho() transformation */
|
||||
state[ 1] = ROTL64(state[ 1], 1);
|
||||
state[ 2] = ROTL64(state[ 2], 62);
|
||||
state[ 3] = ROTL64(state[ 3], 28);
|
||||
state[ 4] = ROTL64(state[ 4], 27);
|
||||
state[ 5] = ROTL64(state[ 5], 36);
|
||||
state[ 6] = ROTL64(state[ 6], 44);
|
||||
state[ 7] = ROTL64(state[ 7], 6);
|
||||
state[ 8] = ROTL64(state[ 8], 55);
|
||||
state[ 9] = ROTL64(state[ 9], 20);
|
||||
state[10] = ROTL64(state[10], 3);
|
||||
state[11] = ROTL64(state[11], 10);
|
||||
state[12] = ROTL64(state[12], 43);
|
||||
state[13] = ROTL64(state[13], 25);
|
||||
state[14] = ROTL64(state[14], 39);
|
||||
state[15] = ROTL64(state[15], 41);
|
||||
state[16] = ROTL64(state[16], 45);
|
||||
state[17] = ROTL64(state[17], 15);
|
||||
state[18] = ROTL64(state[18], 21);
|
||||
state[19] = ROTL64(state[19], 8);
|
||||
state[20] = ROTL64(state[20], 18);
|
||||
state[21] = ROTL64(state[21], 2);
|
||||
state[22] = ROTL64(state[22], 61);
|
||||
state[23] = ROTL64(state[23], 56);
|
||||
state[24] = ROTL64(state[24], 14);
|
||||
|
||||
keccak_pi(state);
|
||||
keccak_chi(state);
|
||||
|
||||
/* apply iota(state, round) */
|
||||
*state ^= keccak_round_constants[round];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process the specified block of data.
|
||||
*
|
||||
* @param hash the algorithm state
|
||||
* @param block the message block to process
|
||||
* @param block_size the size of the processed block in bytes
|
||||
*/
|
||||
static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
|
||||
{
|
||||
/* expanded loop */
|
||||
hash[ 0] ^= le2me_64(block[ 0]);
|
||||
hash[ 1] ^= le2me_64(block[ 1]);
|
||||
hash[ 2] ^= le2me_64(block[ 2]);
|
||||
hash[ 3] ^= le2me_64(block[ 3]);
|
||||
hash[ 4] ^= le2me_64(block[ 4]);
|
||||
hash[ 5] ^= le2me_64(block[ 5]);
|
||||
hash[ 6] ^= le2me_64(block[ 6]);
|
||||
hash[ 7] ^= le2me_64(block[ 7]);
|
||||
hash[ 8] ^= le2me_64(block[ 8]);
|
||||
/* if not sha3-512 */
|
||||
if (block_size > 72) {
|
||||
hash[ 9] ^= le2me_64(block[ 9]);
|
||||
hash[10] ^= le2me_64(block[10]);
|
||||
hash[11] ^= le2me_64(block[11]);
|
||||
hash[12] ^= le2me_64(block[12]);
|
||||
/* if not sha3-384 */
|
||||
if (block_size > 104) {
|
||||
hash[13] ^= le2me_64(block[13]);
|
||||
hash[14] ^= le2me_64(block[14]);
|
||||
hash[15] ^= le2me_64(block[15]);
|
||||
hash[16] ^= le2me_64(block[16]);
|
||||
/* if not sha3-256 */
|
||||
if (block_size > 136) {
|
||||
hash[17] ^= le2me_64(block[17]);
|
||||
#ifdef FULL_SHA3_FAMILY_SUPPORT
|
||||
/* if not sha3-224 */
|
||||
if (block_size > 144) {
|
||||
hash[18] ^= le2me_64(block[18]);
|
||||
hash[19] ^= le2me_64(block[19]);
|
||||
hash[20] ^= le2me_64(block[20]);
|
||||
hash[21] ^= le2me_64(block[21]);
|
||||
hash[22] ^= le2me_64(block[22]);
|
||||
hash[23] ^= le2me_64(block[23]);
|
||||
hash[24] ^= le2me_64(block[24]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
/* make a permutation of the hash */
|
||||
sha3_permutation(hash);
|
||||
}
|
||||
|
||||
#define SHA3_FINALIZED 0x80000000
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void sha3_Update(SHA3_CTX *ctx, const unsigned char *msg, size_t size)
|
||||
{
|
||||
size_t idx = (size_t)ctx->rest;
|
||||
size_t block_size = (size_t)ctx->block_size;
|
||||
|
||||
if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
|
||||
ctx->rest = (unsigned)((ctx->rest + size) % block_size);
|
||||
|
||||
/* fill partial block */
|
||||
if (idx) {
|
||||
size_t left = block_size - idx;
|
||||
memcpy((char*)ctx->message + idx, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= block_size) {
|
||||
uint64_t *aligned_message_block = NULL;
|
||||
if (IS_ALIGNED_64(msg)) {
|
||||
/* the most common case is processing of an already aligned message
|
||||
without copying it */
|
||||
aligned_message_block = (uint64_t*)(void*)msg;
|
||||
} else {
|
||||
memcpy(ctx->message, msg, block_size);
|
||||
aligned_message_block = ctx->message;
|
||||
}
|
||||
|
||||
sha3_process_block(ctx->hash, aligned_message_block, block_size);
|
||||
msg += block_size;
|
||||
size -= block_size;
|
||||
}
|
||||
if (size) {
|
||||
memcpy(ctx->message, msg, size); /* save leftovers */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void sha3_Final(SHA3_CTX *ctx, unsigned char* result)
|
||||
{
|
||||
size_t digest_length = 100 - ctx->block_size / 2;
|
||||
const size_t block_size = ctx->block_size;
|
||||
|
||||
if (!(ctx->rest & SHA3_FINALIZED))
|
||||
{
|
||||
/* clear the rest of the data queue */
|
||||
memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest);
|
||||
((char*)ctx->message)[ctx->rest] |= 0x06;
|
||||
((char*)ctx->message)[block_size - 1] |= 0x80;
|
||||
|
||||
/* process final block */
|
||||
sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
|
||||
}
|
||||
|
||||
assert(block_size > digest_length);
|
||||
if (result) me64_to_le_str(result, ctx->hash, digest_length);
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
}
|
||||
|
||||
#if USE_KECCAK
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void keccak_Final(SHA3_CTX *ctx, unsigned char* result)
|
||||
{
|
||||
size_t digest_length = 100 - ctx->block_size / 2;
|
||||
const size_t block_size = ctx->block_size;
|
||||
|
||||
if (!(ctx->rest & SHA3_FINALIZED))
|
||||
{
|
||||
/* clear the rest of the data queue */
|
||||
memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest);
|
||||
((char*)ctx->message)[ctx->rest] |= 0x01;
|
||||
((char*)ctx->message)[block_size - 1] |= 0x80;
|
||||
|
||||
/* process final block */
|
||||
sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
|
||||
}
|
||||
|
||||
assert(block_size > digest_length);
|
||||
if (result) me64_to_le_str(result, ctx->hash, digest_length);
|
||||
memzero(ctx, sizeof(SHA3_CTX));
|
||||
}
|
||||
|
||||
void keccak_256(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
keccak_256_Init(&ctx);
|
||||
keccak_Update(&ctx, data, len);
|
||||
keccak_Final(&ctx, digest);
|
||||
}
|
||||
|
||||
void keccak_512(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
keccak_512_Init(&ctx);
|
||||
keccak_Update(&ctx, data, len);
|
||||
keccak_Final(&ctx, digest);
|
||||
}
|
||||
#endif /* USE_KECCAK */
|
||||
|
||||
void sha3_256(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
sha3_256_Init(&ctx);
|
||||
sha3_Update(&ctx, data, len);
|
||||
sha3_Final(&ctx, digest);
|
||||
}
|
||||
|
||||
void sha3_512(const unsigned char* data, size_t len, unsigned char* digest)
|
||||
{
|
||||
SHA3_CTX ctx = {0};
|
||||
sha3_512_Init(&ctx);
|
||||
sha3_Update(&ctx, data, len);
|
||||
sha3_Final(&ctx, digest);
|
||||
}
|
||||
89
src/crypto/bip39/sha3.h
Normal file
89
src/crypto/bip39/sha3.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak).
|
||||
* based on the
|
||||
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
|
||||
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
|
||||
*
|
||||
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#ifndef __SHA3_H__
|
||||
#define __SHA3_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "options.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define sha3_224_hash_size 28
|
||||
#define sha3_256_hash_size 32
|
||||
#define sha3_384_hash_size 48
|
||||
#define sha3_512_hash_size 64
|
||||
#define sha3_max_permutation_size 25
|
||||
#define sha3_max_rate_in_qwords 24
|
||||
|
||||
#define SHA3_224_BLOCK_LENGTH 144
|
||||
#define SHA3_256_BLOCK_LENGTH 136
|
||||
#define SHA3_384_BLOCK_LENGTH 104
|
||||
#define SHA3_512_BLOCK_LENGTH 72
|
||||
|
||||
#define SHA3_224_DIGEST_LENGTH sha3_224_hash_size
|
||||
#define SHA3_256_DIGEST_LENGTH sha3_256_hash_size
|
||||
#define SHA3_384_DIGEST_LENGTH sha3_384_hash_size
|
||||
#define SHA3_512_DIGEST_LENGTH sha3_512_hash_size
|
||||
|
||||
/**
|
||||
* SHA3 Algorithm context.
|
||||
*/
|
||||
typedef struct SHA3_CTX
|
||||
{
|
||||
/* 1600 bits algorithm hashing state */
|
||||
uint64_t hash[sha3_max_permutation_size];
|
||||
/* 1536-bit buffer for leftovers */
|
||||
uint64_t message[sha3_max_rate_in_qwords];
|
||||
/* count of bytes in the message[] buffer */
|
||||
unsigned rest;
|
||||
/* size of a message block processed at once */
|
||||
unsigned block_size;
|
||||
} SHA3_CTX;
|
||||
|
||||
/* methods for calculating the hash function */
|
||||
|
||||
void sha3_224_Init(SHA3_CTX *ctx);
|
||||
void sha3_256_Init(SHA3_CTX *ctx);
|
||||
void sha3_384_Init(SHA3_CTX *ctx);
|
||||
void sha3_512_Init(SHA3_CTX *ctx);
|
||||
void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size);
|
||||
void sha3_Final(SHA3_CTX *ctx, unsigned char* result);
|
||||
|
||||
#if USE_KECCAK
|
||||
#define keccak_224_Init sha3_224_Init
|
||||
#define keccak_256_Init sha3_256_Init
|
||||
#define keccak_384_Init sha3_384_Init
|
||||
#define keccak_512_Init sha3_512_Init
|
||||
#define keccak_Update sha3_Update
|
||||
void keccak_Final(SHA3_CTX *ctx, unsigned char* result);
|
||||
void keccak_256(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
void keccak_512(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
#endif
|
||||
|
||||
void sha3_256(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
void sha3_512(const unsigned char* data, size_t len, unsigned char* digest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __SHA3_H__ */
|
||||
Reference in New Issue
Block a user