1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
|
/* Copyright (c) 2020-2021 tevador <tevador@gmail.com> */
/* See LICENSE for licensing information */
#ifndef POLYSEED_H
#define POLYSEED_H
#include <stddef.h>
#include <stdint.h>
#include <time.h>
/* Number of words in the mnemonic phrase */
#define POLYSEED_NUM_WORDS 16
/* The size of the serialized seed */
#define POLYSEED_SIZE 32
/* The serialized seed. The contents are platform-independent. */
typedef uint8_t polyseed_storage[POLYSEED_SIZE];
/* The maximum possible length of a mnemonic phrase */
#define POLYSEED_STR_SIZE 360
/* Mnemonic phrase buffer */
typedef char polyseed_str[POLYSEED_STR_SIZE];
/* Dependency injection definitions */
typedef void polyseed_randbytes(void* result, size_t n);
typedef void polyseed_pbkdf2(const uint8_t* pw, size_t pwlen,
const uint8_t* salt, size_t saltlen, uint64_t iterations,
uint8_t* key, size_t keylen);
typedef size_t polyseed_transform(const char* str, polyseed_str norm);
typedef time_t polyseed_time(time_t* t);
typedef void polyseed_memzero(void* const ptr, const size_t len);
typedef void* polyseed_malloc(size_t n);
typedef void polyseed_mfree(void* ptr);
typedef struct polyseed_dependency {
/* Function to generate cryptographically secure random bytes */
polyseed_randbytes* randbytes;
/* Function to calculate PBKDF2 based on HMAC-SHA256 */
polyseed_pbkdf2* pbkdf2_sha256;
/* Function to securely erase memory */
polyseed_memzero* memzero;
/* Function to convert a UTF8 string to the composed canonical form. */
polyseed_transform* u8_nfc;
/* Function to convert a UTF8 string to the decomposed canonical form. */
polyseed_transform* u8_nfkd;
/* OPTIONAL: Function to get the current unix time */
polyseed_time* time;
/* OPTIONAL: Function to allocate memory */
polyseed_malloc* alloc;
/* OPTIONAL: Function to free memory */
polyseed_mfree* free;
} polyseed_dependency;
/* List of coins. The seeds for different coins are incompatible. */
typedef enum polyseed_coin {
POLYSEED_MONERO = 0,
POLYSEED_AEON = 1,
/* Other coins should be added here sequentially. */
/* The maximum supported value is 2047. */
/* When adding a new coin, please open a pull request: */
/* https://github.com/tevador/polyseed */
} polyseed_coin;
typedef enum polyseed_status {
/* Success */
POLYSEED_OK = 0,
/* Wrong number of words in the phrase */
POLYSEED_ERR_NUM_WORDS = 1,
/* Unknown language or unsupported words */
POLYSEED_ERR_LANG = 2,
/* Checksum mismatch */
POLYSEED_ERR_CHECKSUM = 3,
/* Unsupported seed features */
POLYSEED_ERR_UNSUPPORTED = 4,
/* Invalid seed format */
POLYSEED_ERR_FORMAT = 5,
/* Memory allocation failure */
POLYSEED_ERR_MEMORY = 6,
} polyseed_status;
/* Opaque struct with the seed data */
typedef struct polyseed_data polyseed_data;
/* Opaque struct with language data */
typedef struct polyseed_lang polyseed_lang;
/*
Shared/static library definitions
- define POLYSEED_SHARED when building a shared library
- define POLYSEED_STATIC when building a static library
- define POLYSEED_STATIC when linking to the static library
*/
#if defined(_WIN32) || defined(__CYGWIN__)
#ifdef POLYSEED_SHARED
#define POLYSEED_API __declspec(dllexport)
#elif !defined(POLYSEED_STATIC)
#define POLYSEED_API __declspec(dllimport)
#else
#define POLYSEED_API
#endif
#define POLYSEED_PRIVATE
#else
#ifdef POLYSEED_SHARED
#define POLYSEED_API __attribute__ ((visibility ("default")))
#elif defined(POLYSEED_STATIC)
#define POLYSEED_API __attribute__ ((visibility ("hidden")))
#else
#define POLYSEED_API
#endif
#define POLYSEED_PRIVATE __attribute__ ((visibility ("hidden")))
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* Injects the dependencies of polyseed. Must be called before using the other
* API functions.
*
* @param deps is a pointer to the structure with dependencies. May point to
* a temporary variable (the struct gets copied internally).
* Must not be NULL.
*/
POLYSEED_API
void polyseed_inject(const polyseed_dependency* deps);
/**
* @return the number of supported languages.
*/
POLYSEED_API
int polyseed_get_num_langs(void);
/**
* Returns a language by its index.
*
* @param i is the language index. Valid values are from zero to one less than
* the number of supported languages.
* WARNING: Callers should not rely on languages having a specific index.
* The internal order of languages may change in future versions.
*
* @return opaque pointer to the language structure.
*/
POLYSEED_API
const polyseed_lang* polyseed_get_lang(int i);
/**
* Returns the native name of a language.
*
* @param lang is the pointer to a language structure. Must not be NULL.
*
* @return the native name of the language in UTF8.
*/
POLYSEED_API
const char* polyseed_get_lang_name(const polyseed_lang* lang);
/**
* Returns the English name of a language.
*
* @param lang is the pointer to a language structure. Must not be NULL.
*
* @return the English name of the language.
*/
POLYSEED_API
const char* polyseed_get_lang_name_en(const polyseed_lang* lang);
/**
* Enables the optional seed features. Up to 3 different boolean flags are
* supported. By default, all 3 features are disabled.
*
* @param mask is a bitmask of the enabled features. Only the least
* significant 3 bits are used.
*
* @return the number of features that were enabled (0, 1, 2 or 3).
*/
POLYSEED_API
int polyseed_enable_features(unsigned mask);
/**
* Creates a new seed with specific features.
*
* @param features are the values of the boolean features for this seed. Only
* the least significant 3 bits are used.
* @param seed_out is a pointer where the seed pointer will be stored.
* Must not be NULL.
*
* @return POLYSEED_OK if the operation was successful.
* POLYSEED_ERR_UNSUPPORTED if requesting features that have not been
* enabled.
* POLYSEED_ERR_MEMORY if memory allocation fails.
* In case of an error, *seed_out is undefined.
*/
POLYSEED_API
polyseed_status polyseed_create(unsigned features, polyseed_data** seed_out);
/**
* Securely erases the seed data and releases the allocated memory.
* This function should be called for pointers obtained from the following
* functions:
* - polyseed_create
* - polyseed_decode
* - polyseed_load
*
* @param seed is the pointer to be freed. If NULL, no action is performed.
*/
POLYSEED_API
void polyseed_free(polyseed_data* seed);
/**
* Gets the approximate date when the seed was created.
*
* @param seed is the pointer to the seed data. Must not be NULL.
*
* @return Unix timestamp with the approximate date when the seed was created.
*/
POLYSEED_API
uint64_t polyseed_get_birthday(const polyseed_data* seed);
/**
* Gets the value of a seed feature flag.
*
* @param seed is the pointer to the seed data. Must not be NULL.
* @param mask is the mask of the feature that is requested.
*
* @return nonzero value if the feature is set, zero otherwise.
*/
POLYSEED_API
unsigned polyseed_get_feature(const polyseed_data* seed, unsigned mask);
/**
* Derives a secret key from the mnemonic seed.
*
* @param seed is a pointer to the seed data. Must not be NULL.
* @param coin is the coin the secret key is intended for.
* $param key_size is the required key size.
* @param key_out is the buffer where the secret key will be stored.
* Must not be NULL.
*/
POLYSEED_API
void polyseed_keygen(const polyseed_data* seed, polyseed_coin coin,
size_t key_size, uint8_t* key_out);
/**
* Encodes the mnemonic seed into a string.
*
* @param seed is a pointer to the seed data. Must not be NULL.
* @param lang is a pointer to the language to encode the seed.
* Must not be NULL.
* @param coin is the coin the mnemonic phrase is intended for.
* @param str_out is the buffer where the mnemonic phrase will be stored
* as a C-style string. Must not be NULL.
*
* @return the length of the mnemonic phrase, excluding the terminating null.
*/
POLYSEED_API
size_t polyseed_encode(const polyseed_data* seed, const polyseed_lang* lang,
polyseed_coin coin, polyseed_str str_out);
/**
* Decodes the seed from a mnemonic phrase.
*
* @param str is the mnemonic phrase as a C-style string. Must not be NULL.
* @param coin is the coin the mnemonic phrase is intended for.
* @param lang_out is an optional pointer. IF not NULL, the detected language
* of the mnemonic phrase will be stored there.
* @param seed_out is a pointer where the seed pointer will be stored.
* Must not be NULL.
*
* @return POLYSEED_OK if the operation was successful. Other values indicate
* an error (in that case, *lang_out and *seed_out are undefined).
*/
POLYSEED_API
polyseed_status polyseed_decode(const char* str, polyseed_coin coin,
const polyseed_lang** lang_out, polyseed_data** seed_out);
/**
* Serializes the seed data in a platform-independent way.
*
* @param seed is the pointer to the seed data. Must not be NULL.
* @param storage is the buffer where the seed will be stored.
* Must not be NULL.
*/
POLYSEED_API
void polyseed_store(const polyseed_data* seed, polyseed_storage storage);
/**
* Loads a serialized seed.
*
* @param storage is the buffer with the serialized seed.
* Must not be NULL.
* @param seed_out is a pointer where the seed pointer will be stored.
* Must not be NULL.
*
* @return POLYSEED_OK if the operation was successful. Other values indicate
* an error (in that case, *seed_out is undefined).
*/
POLYSEED_API
polyseed_status polyseed_load(const polyseed_storage storage,
polyseed_data** seed_out);
/**
* Encrypts or decrypts the seed data with a password.
*
* @param seed is the pointer to the seed data. Must not be NULL.
* @param password is a user-provided password in UTF8. Must not be NULL.
*/
POLYSEED_API
void polyseed_crypt(polyseed_data* seed, const char* password);
/**
* Determine if the seed contents are encrypted. The seed is considered
* encrypted if the polyseed_crypt function has been applied to it
* odd-number of times.
*
* @param seed is the pointer to the seed data. Must not be NULL.
*
* @return 1 if the seed is encrypted, 0 otherwise.
*/
POLYSEED_API
int polyseed_is_encrypted(const polyseed_data* seed);
#ifdef __cplusplus
}
#endif
#endif
|