| /** |
| * @file |
| * @brief ECIES Library |
| * |
| * @defgroup ecc ECIES Library |
| * @brief The ECIES implementation based on Phrack Stuff's code from #63. |
| * @{ |
| * |
| * It includes key generation, validation, encryption and decryption calls. |
| * |
| * Differences from original code: |
| * |
| * - Data types for public/private keys and stream. |
| * - Hex bit strings replaced by binary strings. |
| * - Static initialization using compile-time constants. |
| * - Encryption/decryption in-place instead of data copy. |
| * - Some optimizations for embedded platforms. |
| * |
| * For example of usage see `demo.c` and `tool.c`. |
| * |
| */ |
| |
| #ifndef _ECC_H_ |
| #define _ECC_H_ "ecc.h" |
| |
| /* sect163r2 |
| #define ECIES_DEGREE 163 |
| #define ECIES_POLY 0x000000c9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8 |
| #define ECIES_COEFF_B 0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x2 |
| #define ECIES_BASE_X 0xe8343e36, 0xd4994637, 0xa0991168, 0x86a2d57e, 0xf0eba162, 0x3 |
| #define ECIES_BASE_Y 0x797324f1, 0xb11c5c0c, 0xa2cdd545, 0x71a0094f, 0xd51fbc6c, 0x0 |
| #define ECIES_BASE_ORDER 0xa4234c33, 0x77e70c12, 0x000292fe, 0x00000000, 0x00000000, 0x4 |
| */ |
| |
| /* sect233r1 |
| #define ECIES_DEGREE 233 |
| #define ECIES_POLY 0x00000001, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x200 |
| #define ECIES_COEFF_B 0x7d8f90ad, 0x81fe115f, 0x20e9ce42, 0x213b333b, 0x0923bb58, 0x332c7f8c, 0x647ede6c, 0x066 |
| #define ECIES_BASE_X 0x71fd558b, 0xf8f8eb73, 0x391f8b36, 0x5fef65bc, 0x39f1bb75, 0x8313bb21, 0xc9dfcbac, 0x0fa |
| #define ECIES_BASE_Y 0x01f81052, 0x36716f7e, 0xf867a7ca, 0xbf8a0bef, 0xe58528be, 0x03350678, 0x6a08a419, 0x100 |
| #define ECIES_BASE_ORDER 0x03CFE0D7, 0x22031D26, 0xE72F8A69, 0x0013E974, 0x00000000, 0x00000000, 0x00000000, 0x100 |
| */ |
| |
| /* sect283r1 |
| #define ECIES_DEGREE 283 |
| #define ECIES_POLY 0x000010a1, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000000 |
| #define ECIES_COEFF_B 0x3b79a2f5, 0xf6263e31, 0xa581485a, 0x45309fa2, 0xca97fd76, 0x19a0303f, 0xa5a4af8a, 0xc8b8596d, 0x27b680a |
| #define ECIES_BASE_X 0x86b12053, 0xf8cdbecd, 0x80e2e198, 0x557eac9c, 0x2eed25b8, 0x70b0dfec, 0xe1934f8c, 0x8db7dd90, 0x5f93925 |
| #define ECIES_BASE_Y 0xbe8112f4, 0x13f0df45, 0x826779c8, 0x350eddb0, 0x516ff702, 0xb20d02b4, 0xb98fe6d4, 0xfe24141c, 0x3676854 |
| #define ECIES_BASE_ORDER 0xefadb307, 0x5b042a7c, 0x938a9016, 0x399660fc, 0xffffef90, 0xffffffff, 0xffffffff, 0xffffffff, 0x3ffffff |
| */ |
| |
| /* sect409r1 |
| #define ECIES_DEGREE 409 |
| #define ECIES_POLY 0x00000001, 0x00000000, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2000000 |
| #define ECIES_COEFF_B 0x7b13545f, 0x4f50ae31, 0xd57a55aa, 0x72822f6c, 0xa9a197b2, 0xd6ac27c8, 0x4761fa99, 0xf1f3dd67, 0x7fd6422e, 0x3b7b476b, 0x5c4b9a75, 0xc8ee9feb, 0x021a5c2 |
| #define ECIES_BASE_X 0xbb7996a7, 0x60794e54, 0x5603aeab, 0x8a118051, 0xdc255a86, 0x34e59703, 0xb01ffe5b, 0xf1771d4d, 0x441cde4a, 0x64756260, 0x496b0c60, 0xd088ddb3, 0x15d4860 |
| #define ECIES_BASE_Y 0x0273c706, 0x81c364ba, 0xd2181b36, 0xdf4b4f40, 0x38514f1f, 0x5488d08f, 0x0158aa4f, 0xa7bd198d, 0x7636b9c5, 0x24ed106a, 0x2bbfa783, 0xab6be5f3, 0x061b1cf |
| #define ECIES_BASE_ORDER 0xd9a21173, 0x8164cd37, 0x9e052f83, 0x5fa47c3c, 0xf33307be, 0xaad6a612, 0x000001e2, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000000 |
| */ |
| |
| /* sect571r1 */ |
| #define ECIES_DEGREE 571 |
| #define ECIES_POLY 0x00000425, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000000 |
| #define ECIES_COEFF_B 0x2955727a, 0x7ffeff7f, 0x39baca0c, 0x520e4de7, 0x78ff12aa, 0x4afd185a, 0x56a66e29, 0x2be7ad67, 0x8efa5933, 0x84ffabbd, 0x4a9a18ad, 0xcd6ba8ce, 0xcb8ceff1, 0x5c6a97ff, 0xb7f3d62f, 0xde297117, 0x2221f295, 0x2f40e7e |
| #define ECIES_BASE_X 0x8eec2d19, 0xe1e7769c, 0xc850d927, 0x4abfa3b4, 0x8614f139, 0x99ae6003, 0x5b67fb14, 0xcdd711a3, 0xf4c0d293, 0xbde53950, 0xdb7b2abd, 0xa5f40fc8, 0x955fa80a, 0x0a93d1d2, 0x0d3cd775, 0x6c16c0d4, 0x34b85629, 0x303001d |
| #define ECIES_BASE_Y 0x1b8ac15b, 0x1a4827af, 0x6e23dd3c, 0x16e2f151, 0x0485c19b, 0xb3531d2f, 0x461bb2a8, 0x6291af8f, 0xbab08a57, 0x84423e43, 0x3921e8a6, 0x1980f853, 0x009cbbca, 0x8c6c27a6, 0xb73d69d7, 0x6dccfffe, 0x42da639b, 0x37bf273 |
| #define ECIES_BASE_ORDER 0x2fe84e47, 0x8382e9bb, 0x5174d66e, 0x161de93d, 0xc7dd9ca1, 0x6823851e, 0x08059b18, 0xff559873, 0xe661ce18, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x3ffffff |
| |
| |
| /* don't touch this */ |
| #define ECIES_MARGIN 3 |
| #define ECIES_NUMWORDS ((ECIES_DEGREE + ECIES_MARGIN + 31) / 32) |
| |
| #define ECIES_OVERHEAD (8 * ECIES_NUMWORDS + 8) |
| |
| #define ECIES_KEY_SIZE ((ECIES_DEGREE + 7) / 8) |
| |
| |
| #include <stdint.h> |
| |
| typedef unsigned int ECIES_size_t; |
| typedef unsigned char ECIES_byte_t; |
| typedef ECIES_byte_t ECIES_key_t[ECIES_KEY_SIZE]; |
| |
| /** |
| * @brief Public key type. |
| */ |
| typedef struct { |
| ECIES_key_t x, y; |
| } ECIES_pubkey_t; |
| |
| /** |
| * @brief Private key type. |
| */ |
| typedef struct { |
| ECIES_key_t k; |
| } ECIES_privkey_t; |
| |
| |
| typedef unsigned int (*key_bytes_func_t)(void); |
| typedef void (*ctr_crypt_func_t)(ECIES_byte_t *data, ECIES_size_t size, const ECIES_byte_t *key); |
| typedef void (*cbc_mac_func_t)(ECIES_byte_t *mac, const ECIES_byte_t *data, ECIES_size_t size, const ECIES_byte_t *key); |
| typedef void (*davies_meyer_func_t)(ECIES_byte_t *out, const ECIES_byte_t *in, int); |
| |
| void ECIES_set_symmetric_crypt_functions(key_bytes_func_t, ctr_crypt_func_t, cbc_mac_func_t, davies_meyer_func_t); |
| void ECIES_set_symmetric_crypt_nonce_location(ECIES_byte_t *nonce, const ECIES_size_t *nonce_size); |
| |
| |
| /** |
| * @brief Generate public/private key pair. |
| * |
| * It uses `random()` function to get random numbers, so you may use `srandom()` to set initial random seed. |
| * |
| * @param[out] priv The result private key. |
| * @param[out] pub The result public key. |
| */ |
| void ECIES_generate_keys(ECIES_privkey_t *priv, ECIES_pubkey_t *pub); |
| |
| /** |
| * @brief Validate public key. |
| * |
| * @param[in] pubkey The target public key. |
| */ |
| int ECIES_validate_pubkey(const ECIES_pubkey_t *pubkey); |
| |
| /** |
| * @brief Encrypt data. |
| * |
| * @param[out] msg The destination buffer for the encrypted data. |
| * @param[in] raw The source data buffer. |
| * @param[in] len The source data length in chars. |
| * @param[in] pubkey The public key which will be used for encryption. |
| * |
| * Encrypted data will be `len + ECIES_OVERHEAD` bytes long. |
| */ |
| void ECIES_encrypt(ECIES_byte_t *msg, const char *raw, ECIES_size_t len, const ECIES_pubkey_t *pubkey); |
| |
| /** |
| * @brief Decrypt data. |
| * |
| * @param[out] raw The destination buffer for decrypted data. |
| * @param[in] len The destination data length. |
| * @param[in] msg The source encrypted data buffer. |
| * @param[in] privkey The private key wich will be used for decryption. |
| * @return 1 when success, < 0 when error reached. |
| * |
| * Encrypted data must be `len + ECIES_OVERHEAD` bytes long. |
| */ |
| int ECIES_decrypt(char *raw, ECIES_size_t len, const ECIES_byte_t *msg, const ECIES_privkey_t *privkey); |
| |
| /** |
| * @brief The starting overhead of encrypted data in bytes. |
| */ |
| #define ECIES_START_OVERHEAD (8 * ECIES_NUMWORDS) |
| |
| /** |
| * @brief The per-chunk overhead of encrypted data in bytes. |
| */ |
| #define ECIES_CHUNK_OVERHEAD (8) |
| |
| /** |
| * @brief Encryption/decryption stream data. |
| */ |
| typedef struct { |
| //ECIES_byte_t k1[16], k2[16]; |
| ECIES_byte_t *k1, *k2; |
| } ECIES_stream_t; |
| |
| /** |
| * @brief Start the encryption. |
| * |
| * @param[out] stm The stream data. |
| * @param[out] msg The destination encrypted data buffer. |
| * @param[in] pubkey The public key which will be used for encryption. |
| * |
| * Starting sequence (@p msg) will be `ECIES_START_OVERHEAD` bytes long. |
| */ |
| void ECIES_encrypt_start(ECIES_stream_t *stm, ECIES_byte_t *msg, const ECIES_pubkey_t *pubkey); |
| |
| /** |
| * @brief Encrypt data chunk. |
| * |
| * @param[in] stm The stream data. |
| * @param[in,out] msg The source raw data and destination encrypted data buffer. |
| * @param[in] len The length of source raw data in bytes. |
| * |
| * Encryption is performed in-place on @p msg parameter. |
| * Encrypted data will be `len + ECIES_CHUNK_OVERHEAD` bytes long. |
| */ |
| void ECIES_encrypt_chunk(const ECIES_stream_t *stm, ECIES_byte_t *msg, ECIES_size_t len); |
| |
| /** |
| * @brief Start the decryption. |
| * |
| * @param[out] stm The stream data. |
| * @param[in] msg The source encrypted data buffer. |
| * @param[in] privkey The private key wich will be used for decryption. |
| * @return 1 when success, < 0 when error reached. |
| * |
| * Starting sequence (@p msg) must be `ECIES_START_OVERHEAD` bytes long. |
| */ |
| int ECIES_decrypt_start(ECIES_stream_t *stm, const ECIES_byte_t *msg, const ECIES_privkey_t *privkey); |
| |
| /** |
| * @brief Decrypt data chunk. |
| * |
| * @param[in] stm The stream data. |
| * @param[in,out] msg The source encrypted data and destination decrypted raw data buffer. |
| * @param[in] len The length of destination decrypted raw data in bytes. |
| * @return 1 when success, < 0 when error reached. |
| * |
| * Decryption is performed in-place on @p msg parameter. |
| * Encrypted data must be `len + ECIES_CHUNK_OVERHEAD` bytes long. |
| */ |
| int ECIES_decrypt_chunk(const ECIES_stream_t *stm, ECIES_byte_t *msg, ECIES_size_t len); |
| |
| void ECIES_free_stream(ECIES_stream_t *stm); |
| |
| |
| static inline uint32_t __swap32(uint32_t val){ |
| return |
| ((((uint32_t)(val)) & 0x000000ff) << 24) | |
| ((((uint32_t)(val)) & 0x0000ff00) << 8) | |
| ((((uint32_t)(val)) & 0x00ff0000) >> 8) | |
| ((((uint32_t)(val)) & 0xff000000) >> 24); |
| } |
| |
| #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
| # ifndef be32toh |
| # define be32toh(val) (val) |
| # endif |
| # ifndef htobe32 |
| # define htobe32(val) (val) |
| # endif |
| #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
| # ifndef be32toh |
| # define be32toh(val) __swap32(val) |
| # endif |
| # ifndef htobe32 |
| # define htobe32(val) __swap32(val) |
| # endif |
| #endif |
| |
| #define MACRO(A) do { A; } while(0) |
| #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| #define CHARS2INT(ptr) ( be32toh(*(uint32_t*)(ptr)) ) |
| #define INT2CHARS(ptr, val) MACRO( (*(uint32_t*)(ptr)) = htobe32(val) ) |
| |
| |
| #endif/*_ECC_H_*/ |
| /** |
| * @} |
| */ |