blob: 14b2f52e4a4850ea8bae2b632fd222dbf91d2096 [file] [log] [blame] [raw]
/**
* @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_*/
/**
* @}
*/