initial commit
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
micro-ecc
|
||||
==========
|
||||
|
||||
A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
|
||||
|
||||
The old version of micro-ecc can be found in the "old" branch.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Resistant to known side-channel attacks.
|
||||
* Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms.
|
||||
* Supports 8, 32, and 64-bit architectures.
|
||||
* Small code size.
|
||||
* No dynamic memory allocation.
|
||||
* Support for 4 standard curves: secp160r1, secp192r1, secp256r1, and secp256k1.
|
||||
* BSD 2-clause license.
|
||||
|
||||
Usage Notes
|
||||
-----------
|
||||
### Point Representation ###
|
||||
Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. `uECC_make_key()`, `uECC_shared_secret()`, `uECC_sign()`, and `uECC_verify()` only handle uncompressed points; you can use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
|
||||
|
||||
Private keys are represented in the standard format.
|
||||
|
||||
### Using the Code ###
|
||||
|
||||
I recommend just copying (or symlink) uECC.h, uECC.c, and the appropriate asm\_<arch>\_.inc (if any) into your project. Then just `#include "uECC.h"` to use the micro-ecc functions.
|
||||
|
||||
For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
|
||||
|
||||
See uECC.h for documentation for each function.
|
||||
|
||||
### Compilation Notes ###
|
||||
|
||||
* Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013).
|
||||
* If you want to change the defaults for `uECC_CURVE` and `uECC_ASM`, you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_CURVE=uECC_secp256r1` or whatever).
|
||||
* When compiling for a Thumb-1 platform with inline assembly enabled (ie, `uECC_ASM` is defined to `uECC_asm_small` or `uECC_asm_fast`), you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
|
||||
* When compiling for an ARM/Thumb-2 platform with fast inline assembly enabled (ie, `uECC_ASM` is defined to `uECC_asm_fast`), you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
|
||||
* When compiling for AVR with inline assembly enabled, you must have optimizations enabled (compile with `-O1` or higher).
|
||||
* When building for Windows, you will need to link in the `advapi32.lib` system library.
|
||||
|
||||
ARM Performance
|
||||
---------------
|
||||
|
||||
All tests were built using gcc 4.8.2 with `-O3`, and were run on a Raspberry Pi B+. `uECC_ASM` was defined to `uECC_asm_fast` and `ECC_SQUARE_FUNC` was defined to `1` in all cases. All times are in milliseconds.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>secp160r1</th>
|
||||
<th>secp192r1</th>
|
||||
<th>secp256r1</th>
|
||||
<th>secp256k1</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDH:</em></td>
|
||||
<td>2.3</td>
|
||||
<td>2.7</td>
|
||||
<td>7.9</td>
|
||||
<td>6.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDSA sign:</em></td>
|
||||
<td>2.8</td>
|
||||
<td>3.1</td>
|
||||
<td>8.6</td>
|
||||
<td>7.2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDSA verify:</em></td>
|
||||
<td>2.7</td>
|
||||
<td>3.2</td>
|
||||
<td>9.2</td>
|
||||
<td>7.0</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
AVR Performance
|
||||
---------------
|
||||
|
||||
All tests were built using avr-gcc 4.8.1 with `-Os`, and were run on a 16 MHz ATmega256RFR2. Code size refers to the space used by micro-ecc code and data.
|
||||
|
||||
#### ECDH (fast) ####
|
||||
|
||||
In these tests, `uECC_ASM` was defined to `uECC_asm_fast` and `ECC_SQUARE_FUNC` was defined to `1` in all cases.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>secp160r1</th>
|
||||
<th>secp192r1</th>
|
||||
<th>secp256r1</th>
|
||||
<th>secp256k1</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDH time (ms):</em></td>
|
||||
<td>470</td>
|
||||
<td>810</td>
|
||||
<td>2220</td>
|
||||
<td>1615</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>Code size (bytes):</em></td>
|
||||
<td>10768</td>
|
||||
<td>13112</td>
|
||||
<td>20886</td>
|
||||
<td>21126</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### ECDH (small) ####
|
||||
|
||||
In these tests, `uECC_ASM` was defined to `uECC_asm_small` and `ECC_SQUARE_FUNC` was defined to `0` in all cases.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>secp160r1</th>
|
||||
<th>secp192r1</th>
|
||||
<th>secp256r1</th>
|
||||
<th>secp256k1</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDH time (ms):</em></td>
|
||||
<td>1250</td>
|
||||
<td>1810</td>
|
||||
<td>4790</td>
|
||||
<td>4700</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>Code size (bytes):</em></td>
|
||||
<td>3244</td>
|
||||
<td>3400</td>
|
||||
<td>5274</td>
|
||||
<td>3426</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### ECDSA (fast) ####
|
||||
|
||||
In these tests, `uECC_ASM` was defined to `uECC_asm_fast` and `ECC_SQUARE_FUNC` was defined to `1` in all cases.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>secp160r1</th>
|
||||
<th>secp192r1</th>
|
||||
<th>secp256r1</th>
|
||||
<th>secp256k1</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDSA sign time (ms):</em></td>
|
||||
<td>555</td>
|
||||
<td>902</td>
|
||||
<td>2386</td>
|
||||
<td>1773</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDSA verify time (ms):</em></td>
|
||||
<td>590</td>
|
||||
<td>990</td>
|
||||
<td>2650</td>
|
||||
<td>1800</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>Code size (bytes):</em></td>
|
||||
<td>13246</td>
|
||||
<td>14798</td>
|
||||
<td>22594</td>
|
||||
<td>22826</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
#### ECDSA (small) ####
|
||||
|
||||
In these tests, `uECC_ASM` was defined to `uECC_asm_small` and `ECC_SQUARE_FUNC` was defined to `0` in all cases.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>secp160r1</th>
|
||||
<th>secp192r1</th>
|
||||
<th>secp256r1</th>
|
||||
<th>secp256k1</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDSA sign time (ms):</em></td>
|
||||
<td>1359</td>
|
||||
<td>1931</td>
|
||||
<td>4998</td>
|
||||
<td>4904</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>ECDSA verify time (ms):</em></td>
|
||||
<td>1515</td>
|
||||
<td>2160</td>
|
||||
<td>5700</td>
|
||||
<td>5220</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><em>Code size (bytes):</em></td>
|
||||
<td>5690</td>
|
||||
<td>5054</td>
|
||||
<td>6980</td>
|
||||
<td>5080</td>
|
||||
</tr>
|
||||
</table>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,301 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _MICRO_ECC_H_
|
||||
#define _MICRO_ECC_H_
|
||||
|
||||
#include "wsf_types.h"
|
||||
|
||||
/* Platform selection options.
|
||||
If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
|
||||
Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arch_other 0
|
||||
#define uECC_x86 1
|
||||
#define uECC_x86_64 2
|
||||
#define uECC_arm 3
|
||||
#define uECC_arm_thumb 4
|
||||
#define uECC_avr 5
|
||||
#define uECC_arm_thumb2 6
|
||||
|
||||
/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
|
||||
platform. */
|
||||
|
||||
/* Inline assembly options.
|
||||
uECC_asm_none - Use standard C99 only.
|
||||
uECC_asm_small - Use GCC inline assembly for the target platform (if available), optimized for
|
||||
minimum size.
|
||||
uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */
|
||||
#define uECC_asm_none 0
|
||||
#define uECC_asm_small 1
|
||||
#define uECC_asm_fast 2
|
||||
#ifndef uECC_ASM
|
||||
#define uECC_ASM uECC_asm_fast
|
||||
#endif
|
||||
|
||||
/* Curve selection options. */
|
||||
#define uECC_secp160r1 1
|
||||
#define uECC_secp192r1 2
|
||||
#define uECC_secp256r1 3
|
||||
#define uECC_secp256k1 4
|
||||
#define uECC_secp224r1 5
|
||||
#ifndef uECC_CURVE
|
||||
#define uECC_CURVE uECC_secp256r1
|
||||
#endif
|
||||
|
||||
/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
|
||||
used for (scalar) squaring instead of the generic multiplication function. This will make things
|
||||
faster by about 8% but increases the code size. */
|
||||
#ifndef uECC_SQUARE_FUNC
|
||||
#define uECC_SQUARE_FUNC 1
|
||||
#endif
|
||||
|
||||
#define uECC_CONCAT1(a, b) a##b
|
||||
#define uECC_CONCAT(a, b) uECC_CONCAT1(a, b)
|
||||
|
||||
#define uECC_size_1 20 /* secp160r1 */
|
||||
#define uECC_size_2 24 /* secp192r1 */
|
||||
#define uECC_size_3 32 /* secp256r1 */
|
||||
#define uECC_size_4 32 /* secp256k1 */
|
||||
#define uECC_size_5 28 /* secp224r1 */
|
||||
|
||||
#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
|
||||
'dest' was filled with random data, or 0 if the random data could not be generated.
|
||||
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
|
||||
uECC_make_key() or uECC_sign().
|
||||
|
||||
Setting a correctly functioning RNG function improves the resistance to side-channel attacks
|
||||
for uECC_shared_secret() and uECC_sign_deterministic().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS X.
|
||||
If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
|
||||
you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
|
||||
RNG function; you must provide your own.
|
||||
*/
|
||||
typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
|
||||
/* uECC_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function should
|
||||
return 1 if the random data was generated, or 0 if the random data could not be generated.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms), this must
|
||||
be called before uECC_make_key() or uECC_sign() are used.
|
||||
|
||||
Inputs:
|
||||
rng_function - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function);
|
||||
|
||||
/* uECC_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the public key.
|
||||
private_key - Will be filled in with the private key.
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_make_key(uint8_t public_key[uECC_BYTES*2], uint8_t private_key[uECC_BYTES]);
|
||||
|
||||
/* uECC_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key.
|
||||
Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
|
||||
symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key of the remote party.
|
||||
private_key - Your private key.
|
||||
|
||||
Outputs:
|
||||
secret - Will be filled in with the shared secret value.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t public_key[uECC_BYTES*2],
|
||||
const uint8_t private_key[uECC_BYTES],
|
||||
uint8_t secret[uECC_BYTES]);
|
||||
|
||||
/* uECC_sign() function.
|
||||
Generate an ECDSA signature for a given hash value.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
|
||||
this function along with your private key.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign(const uint8_t private_key[uECC_BYTES],
|
||||
const uint8_t message_hash[uECC_BYTES],
|
||||
uint8_t signature[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_HashContext structure.
|
||||
This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
|
||||
The structure will be used for multiple hash computations; each time a new hash
|
||||
is computed, init_hash() will be called, followed by one or more calls to
|
||||
update_hash(), and finally a call to finish_hash() to prudoce the resulting hash.
|
||||
|
||||
The intention is that you will create a structure that includes uECC_HashContext
|
||||
followed by any hash-specific data. For example:
|
||||
|
||||
typedef struct SHA256_HashContext {
|
||||
uECC_HashContext uECC;
|
||||
SHA256_CTX ctx;
|
||||
} SHA256_HashContext;
|
||||
|
||||
void init_SHA256(uECC_HashContext *base) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Init(&context->ctx);
|
||||
}
|
||||
|
||||
void update_SHA256(uECC_HashContext *base,
|
||||
const uint8_t *message,
|
||||
unsigned message_size) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Update(&context->ctx, message, message_size);
|
||||
}
|
||||
|
||||
void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
|
||||
SHA256_HashContext *context = (SHA256_HashContext *)base;
|
||||
SHA256_Final(hash_result, &context->ctx);
|
||||
}
|
||||
|
||||
... when signing ...
|
||||
{
|
||||
uint8_t tmp[32 + 32 + 64];
|
||||
SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
|
||||
uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
|
||||
}
|
||||
*/
|
||||
typedef struct uECC_HashContext {
|
||||
void (*init_hash)(struct uECC_HashContext *context);
|
||||
void (*update_hash)(struct uECC_HashContext *context,
|
||||
const uint8_t *message,
|
||||
unsigned message_size);
|
||||
void (*finish_hash)(struct uECC_HashContext *context, uint8_t *hash_result);
|
||||
unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
|
||||
unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
|
||||
uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
|
||||
} uECC_HashContext;
|
||||
|
||||
/* uECC_sign_deterministic() function.
|
||||
Generate an ECDSA signature for a given hash value, using a deterministic algorithm
|
||||
(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling
|
||||
this function; however, if the RNG is defined it will improve resistance to side-channel
|
||||
attacks.
|
||||
|
||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
|
||||
this function along with your private key and a hash context.
|
||||
|
||||
Inputs:
|
||||
private_key - Your private key.
|
||||
message_hash - The hash of the message to sign.
|
||||
hash_context - A hash context to use.
|
||||
|
||||
Outputs:
|
||||
signature - Will be filled in with the signature value.
|
||||
|
||||
Returns 1 if the signature generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
|
||||
const uint8_t message_hash[uECC_BYTES],
|
||||
uECC_HashContext *hash_context,
|
||||
uint8_t signature[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_verify() function.
|
||||
Verify an ECDSA signature.
|
||||
|
||||
Usage: Compute the hash of the signed data using the same hash as the signer and
|
||||
pass it to this function along with the signer's public key and the signature values (r and s).
|
||||
|
||||
Inputs:
|
||||
public_key - The signer's public key
|
||||
hash - The hash of the signed data.
|
||||
signature - The signature value.
|
||||
|
||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_verify(const uint8_t private_key[uECC_BYTES*2],
|
||||
const uint8_t hash[uECC_BYTES],
|
||||
const uint8_t signature[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_compress() function.
|
||||
Compress a public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to compress.
|
||||
|
||||
Outputs:
|
||||
compressed - Will be filled in with the compressed public key.
|
||||
*/
|
||||
void uECC_compress(const uint8_t public_key[uECC_BYTES*2], uint8_t compressed[uECC_BYTES+1]);
|
||||
|
||||
/* uECC_decompress() function.
|
||||
Decompress a compressed public key.
|
||||
|
||||
Inputs:
|
||||
compressed - The compressed public key.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the decompressed public key.
|
||||
*/
|
||||
void uECC_decompress(const uint8_t compressed[uECC_BYTES+1], uint8_t public_key[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_valid_public_key() function.
|
||||
Check to see if a public key is valid.
|
||||
|
||||
Note that you are not required to check for a valid public key before using any other uECC
|
||||
functions. However, you may wish to avoid spending CPU time computing a shared secret or
|
||||
verifying a signature using an invalid public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to check.
|
||||
|
||||
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_valid_public_key(const uint8_t public_key[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_compute_public_key() function.
|
||||
Compute the corresponding public key for a private key.
|
||||
|
||||
Inputs:
|
||||
private_key - The private key to compute the public key for
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the corresponding public key
|
||||
|
||||
Returns 1 if the key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_compute_public_key(const uint8_t private_key[uECC_BYTES],
|
||||
uint8_t public_key[uECC_BYTES * 2]);
|
||||
|
||||
|
||||
/* uECC_bytes() function.
|
||||
Returns the value of uECC_BYTES. Helpful for foreign-interfaces to higher-level languages.
|
||||
*/
|
||||
int uECC_bytes(void);
|
||||
|
||||
/* uECC_curve() function.
|
||||
Returns the value of uECC_CURVE. Helpful for foreign-interfaces to higher-level languages.
|
||||
*/
|
||||
int uECC_curve(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MICRO_ECC_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
|
||||
|
||||
#ifndef _MICRO_ECC_LL_H_
|
||||
#define _MICRO_ECC_LL_H_
|
||||
|
||||
#include "wsf_types.h"
|
||||
|
||||
/* Platform selection options.
|
||||
If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
|
||||
Possible values for uECC_PLATFORM are defined below: */
|
||||
#define uECC_arch_other 0
|
||||
#define uECC_x86 1
|
||||
#define uECC_x86_64 2
|
||||
#define uECC_arm 3
|
||||
#define uECC_arm_thumb 4
|
||||
#define uECC_avr 5
|
||||
#define uECC_arm_thumb2 6
|
||||
|
||||
/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
|
||||
If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
|
||||
platform. */
|
||||
|
||||
/* Inline assembly options.
|
||||
uECC_asm_none - Use standard C99 only.
|
||||
uECC_asm_small - Use GCC inline assembly for the target platform (if available), optimized for
|
||||
minimum size.
|
||||
uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */
|
||||
#define uECC_asm_none 0
|
||||
#define uECC_asm_small 1
|
||||
#define uECC_asm_fast 2
|
||||
#ifndef uECC_ASM
|
||||
#define uECC_ASM uECC_asm_fast
|
||||
#endif
|
||||
|
||||
/* Curve selection options. */
|
||||
#define uECC_secp160r1 1
|
||||
#define uECC_secp192r1 2
|
||||
#define uECC_secp256r1 3
|
||||
#define uECC_secp256k1 4
|
||||
#define uECC_secp224r1 5
|
||||
#ifndef uECC_CURVE
|
||||
#define uECC_CURVE uECC_secp256r1
|
||||
#endif
|
||||
|
||||
/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
|
||||
used for (scalar) squaring instead of the generic multiplication function. This will make things
|
||||
faster by about 8% but increases the code size. */
|
||||
#ifndef uECC_SQUARE_FUNC
|
||||
#define uECC_SQUARE_FUNC 1
|
||||
#endif
|
||||
|
||||
#define uECC_CONCAT1(a, b) a##b
|
||||
#define uECC_CONCAT(a, b) uECC_CONCAT1(a, b)
|
||||
|
||||
#define uECC_size_1 20 /* secp160r1 */
|
||||
#define uECC_size_2 24 /* secp192r1 */
|
||||
#define uECC_size_3 32 /* secp256r1 */
|
||||
#define uECC_size_4 32 /* secp256k1 */
|
||||
#define uECC_size_5 28 /* secp224r1 */
|
||||
|
||||
#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
|
||||
'dest' was filled with random data, or 0 if the random data could not be generated.
|
||||
The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
|
||||
|
||||
A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
|
||||
uECC_make_key() or uECC_sign().
|
||||
|
||||
Setting a correctly functioning RNG function improves the resistance to side-channel attacks
|
||||
for uECC_shared_secret() and uECC_sign_deterministic().
|
||||
|
||||
A correct RNG function is set by default when building for Windows, Linux, or OS X.
|
||||
If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
|
||||
you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
|
||||
RNG function; you must provide your own.
|
||||
*/
|
||||
typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
|
||||
|
||||
/* uECC_set_rng() function.
|
||||
Set the function that will be used to generate random bytes. The RNG function should
|
||||
return 1 if the random data was generated, or 0 if the random data could not be generated.
|
||||
|
||||
On platforms where there is no predefined RNG function (eg embedded platforms), this must
|
||||
be called before uECC_make_key() or uECC_sign() are used.
|
||||
|
||||
Inputs:
|
||||
rng_function - The function that will be used to generate random bytes.
|
||||
*/
|
||||
void uECC_set_rng_ll(uECC_RNG_Function rng_function);
|
||||
|
||||
/* uECC_make_key() function.
|
||||
Create a public/private key pair.
|
||||
|
||||
Outputs:
|
||||
public_key - Will be filled in with the public key.
|
||||
private_key - Will be filled in with the private key.
|
||||
|
||||
Returns 1 if the key pair was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
void uECC_make_key_start(const uint8_t private_key[uECC_BYTES]);
|
||||
int uECC_make_key_continue(void);
|
||||
void uECC_make_key_complete(uint8_t public_key[uECC_BYTES*2], uint8_t private_key[uECC_BYTES]);
|
||||
|
||||
/* uECC_valid_public_key() function.
|
||||
Check to see if a public key is valid.
|
||||
|
||||
Note that you are not required to check for a valid public key before using any other uECC
|
||||
functions. However, you may wish to avoid spending CPU time computing a shared secret or
|
||||
verifying a signature using an invalid public key.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key to check.
|
||||
|
||||
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||
*/
|
||||
int uECC_valid_public_key_ll(const uint8_t public_key[uECC_BYTES*2]);
|
||||
|
||||
/* uECC_shared_secret() function.
|
||||
Compute a shared secret given your secret key and someone else's public key.
|
||||
Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
|
||||
symmetric encryption or HMAC.
|
||||
|
||||
Inputs:
|
||||
public_key - The public key of the remote party.
|
||||
private_key - Your private key.
|
||||
|
||||
Outputs:
|
||||
secret - Will be filled in with the shared secret value.
|
||||
|
||||
Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
|
||||
*/
|
||||
void uECC_shared_secret_start(const uint8_t public_key[uECC_BYTES*2],
|
||||
const uint8_t private_key[uECC_BYTES]);
|
||||
int uECC_shared_secret_continue(void);
|
||||
void uECC_shared_secret_complete(uint8_t secret[uECC_BYTES]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _MICRO_ECC_LL_H_ */
|
||||
Reference in New Issue
Block a user