micro-ECC for mbed, ported from GCC version from Github,
Dependents: mbed_microECC Wallet_v1
uECC.h@0:b6fdeddc0bc9, 2017-09-07 (annotated)
- Committer:
- allankliu
- Date:
- Thu Sep 07 12:10:11 2017 +0000
- Revision:
- 0:b6fdeddc0bc9
Init version, ported from GCC version of uECC of Github. Assembly optimization for thumb2 is disabled.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
allankliu | 0:b6fdeddc0bc9 | 1 | /* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ |
allankliu | 0:b6fdeddc0bc9 | 2 | |
allankliu | 0:b6fdeddc0bc9 | 3 | #ifndef _UECC_H_ |
allankliu | 0:b6fdeddc0bc9 | 4 | #define _UECC_H_ |
allankliu | 0:b6fdeddc0bc9 | 5 | |
allankliu | 0:b6fdeddc0bc9 | 6 | #include <stdint.h> |
allankliu | 0:b6fdeddc0bc9 | 7 | |
allankliu | 0:b6fdeddc0bc9 | 8 | /* Platform selection options. |
allankliu | 0:b6fdeddc0bc9 | 9 | If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros. |
allankliu | 0:b6fdeddc0bc9 | 10 | Possible values for uECC_PLATFORM are defined below: */ |
allankliu | 0:b6fdeddc0bc9 | 11 | #define uECC_arch_other 0 |
allankliu | 0:b6fdeddc0bc9 | 12 | #define uECC_x86 1 |
allankliu | 0:b6fdeddc0bc9 | 13 | #define uECC_x86_64 2 |
allankliu | 0:b6fdeddc0bc9 | 14 | #define uECC_arm 3 |
allankliu | 0:b6fdeddc0bc9 | 15 | #define uECC_arm_thumb 4 |
allankliu | 0:b6fdeddc0bc9 | 16 | #define uECC_arm_thumb2 5 |
allankliu | 0:b6fdeddc0bc9 | 17 | #define uECC_arm64 6 |
allankliu | 0:b6fdeddc0bc9 | 18 | #define uECC_avr 7 |
allankliu | 0:b6fdeddc0bc9 | 19 | |
allankliu | 0:b6fdeddc0bc9 | 20 | /* Defined arch to others to allow mbed compiler go through building first */ |
allankliu | 0:b6fdeddc0bc9 | 21 | #define uECC_PLATFORM uECC_arch_other |
allankliu | 0:b6fdeddc0bc9 | 22 | |
allankliu | 0:b6fdeddc0bc9 | 23 | /* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes). |
allankliu | 0:b6fdeddc0bc9 | 24 | If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your |
allankliu | 0:b6fdeddc0bc9 | 25 | platform. */ |
allankliu | 0:b6fdeddc0bc9 | 26 | |
allankliu | 0:b6fdeddc0bc9 | 27 | /* Optimization level; trade speed for code size. |
allankliu | 0:b6fdeddc0bc9 | 28 | Larger values produce code that is faster but larger. |
allankliu | 0:b6fdeddc0bc9 | 29 | Currently supported values are 0 - 4; 0 is unusably slow for most applications. |
allankliu | 0:b6fdeddc0bc9 | 30 | Optimization level 4 currently only has an effect ARM platforms where more than one |
allankliu | 0:b6fdeddc0bc9 | 31 | curve is enabled. */ |
allankliu | 0:b6fdeddc0bc9 | 32 | #ifndef uECC_OPTIMIZATION_LEVEL |
allankliu | 0:b6fdeddc0bc9 | 33 | #define uECC_OPTIMIZATION_LEVEL 2 |
allankliu | 0:b6fdeddc0bc9 | 34 | #endif |
allankliu | 0:b6fdeddc0bc9 | 35 | |
allankliu | 0:b6fdeddc0bc9 | 36 | /* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be |
allankliu | 0:b6fdeddc0bc9 | 37 | used for (scalar) squaring instead of the generic multiplication function. This can make things |
allankliu | 0:b6fdeddc0bc9 | 38 | faster somewhat faster, but increases the code size. */ |
allankliu | 0:b6fdeddc0bc9 | 39 | #ifndef uECC_SQUARE_FUNC |
allankliu | 0:b6fdeddc0bc9 | 40 | #define uECC_SQUARE_FUNC 0 |
allankliu | 0:b6fdeddc0bc9 | 41 | #endif |
allankliu | 0:b6fdeddc0bc9 | 42 | |
allankliu | 0:b6fdeddc0bc9 | 43 | /* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native |
allankliu | 0:b6fdeddc0bc9 | 44 | little-endian format for *all* arrays passed in and out of the public API. This includes public |
allankliu | 0:b6fdeddc0bc9 | 45 | and private keys, shared secrets, signatures and message hashes. |
allankliu | 0:b6fdeddc0bc9 | 46 | Using this switch reduces the amount of call stack memory used by uECC, since less intermediate |
allankliu | 0:b6fdeddc0bc9 | 47 | translations are required. |
allankliu | 0:b6fdeddc0bc9 | 48 | Note that this will *only* work on native little-endian processors and it will treat the uint8_t |
allankliu | 0:b6fdeddc0bc9 | 49 | arrays passed into the public API as word arrays, therefore requiring the provided byte arrays |
allankliu | 0:b6fdeddc0bc9 | 50 | to be word aligned on architectures that do not support unaligned accesses. |
allankliu | 0:b6fdeddc0bc9 | 51 | IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible |
allankliu | 0:b6fdeddc0bc9 | 52 | with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use |
allankliu | 0:b6fdeddc0bc9 | 53 | the same endianness. */ |
allankliu | 0:b6fdeddc0bc9 | 54 | #ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN |
allankliu | 0:b6fdeddc0bc9 | 55 | #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0 |
allankliu | 0:b6fdeddc0bc9 | 56 | #endif |
allankliu | 0:b6fdeddc0bc9 | 57 | |
allankliu | 0:b6fdeddc0bc9 | 58 | /* Curve support selection. Set to 0 to remove that curve. */ |
allankliu | 0:b6fdeddc0bc9 | 59 | #ifndef uECC_SUPPORTS_secp160r1 |
allankliu | 0:b6fdeddc0bc9 | 60 | #define uECC_SUPPORTS_secp160r1 1 |
allankliu | 0:b6fdeddc0bc9 | 61 | #endif |
allankliu | 0:b6fdeddc0bc9 | 62 | #ifndef uECC_SUPPORTS_secp192r1 |
allankliu | 0:b6fdeddc0bc9 | 63 | #define uECC_SUPPORTS_secp192r1 1 |
allankliu | 0:b6fdeddc0bc9 | 64 | #endif |
allankliu | 0:b6fdeddc0bc9 | 65 | #ifndef uECC_SUPPORTS_secp224r1 |
allankliu | 0:b6fdeddc0bc9 | 66 | #define uECC_SUPPORTS_secp224r1 1 |
allankliu | 0:b6fdeddc0bc9 | 67 | #endif |
allankliu | 0:b6fdeddc0bc9 | 68 | #ifndef uECC_SUPPORTS_secp256r1 |
allankliu | 0:b6fdeddc0bc9 | 69 | #define uECC_SUPPORTS_secp256r1 1 |
allankliu | 0:b6fdeddc0bc9 | 70 | #endif |
allankliu | 0:b6fdeddc0bc9 | 71 | #ifndef uECC_SUPPORTS_secp256k1 |
allankliu | 0:b6fdeddc0bc9 | 72 | #define uECC_SUPPORTS_secp256k1 1 |
allankliu | 0:b6fdeddc0bc9 | 73 | #endif |
allankliu | 0:b6fdeddc0bc9 | 74 | |
allankliu | 0:b6fdeddc0bc9 | 75 | /* Specifies whether compressed point format is supported. |
allankliu | 0:b6fdeddc0bc9 | 76 | Set to 0 to disable point compression/decompression functions. */ |
allankliu | 0:b6fdeddc0bc9 | 77 | #ifndef uECC_SUPPORT_COMPRESSED_POINT |
allankliu | 0:b6fdeddc0bc9 | 78 | #define uECC_SUPPORT_COMPRESSED_POINT 1 |
allankliu | 0:b6fdeddc0bc9 | 79 | #endif |
allankliu | 0:b6fdeddc0bc9 | 80 | |
allankliu | 0:b6fdeddc0bc9 | 81 | struct uECC_Curve_t; |
allankliu | 0:b6fdeddc0bc9 | 82 | typedef const struct uECC_Curve_t * uECC_Curve; |
allankliu | 0:b6fdeddc0bc9 | 83 | |
allankliu | 0:b6fdeddc0bc9 | 84 | #ifdef __cplusplus |
allankliu | 0:b6fdeddc0bc9 | 85 | extern "C" |
allankliu | 0:b6fdeddc0bc9 | 86 | { |
allankliu | 0:b6fdeddc0bc9 | 87 | #endif |
allankliu | 0:b6fdeddc0bc9 | 88 | |
allankliu | 0:b6fdeddc0bc9 | 89 | #if uECC_SUPPORTS_secp160r1 |
allankliu | 0:b6fdeddc0bc9 | 90 | uECC_Curve uECC_secp160r1(void); |
allankliu | 0:b6fdeddc0bc9 | 91 | #endif |
allankliu | 0:b6fdeddc0bc9 | 92 | #if uECC_SUPPORTS_secp192r1 |
allankliu | 0:b6fdeddc0bc9 | 93 | uECC_Curve uECC_secp192r1(void); |
allankliu | 0:b6fdeddc0bc9 | 94 | #endif |
allankliu | 0:b6fdeddc0bc9 | 95 | #if uECC_SUPPORTS_secp224r1 |
allankliu | 0:b6fdeddc0bc9 | 96 | uECC_Curve uECC_secp224r1(void); |
allankliu | 0:b6fdeddc0bc9 | 97 | #endif |
allankliu | 0:b6fdeddc0bc9 | 98 | #if uECC_SUPPORTS_secp256r1 |
allankliu | 0:b6fdeddc0bc9 | 99 | uECC_Curve uECC_secp256r1(void); |
allankliu | 0:b6fdeddc0bc9 | 100 | #endif |
allankliu | 0:b6fdeddc0bc9 | 101 | #if uECC_SUPPORTS_secp256k1 |
allankliu | 0:b6fdeddc0bc9 | 102 | uECC_Curve uECC_secp256k1(void); |
allankliu | 0:b6fdeddc0bc9 | 103 | #endif |
allankliu | 0:b6fdeddc0bc9 | 104 | |
allankliu | 0:b6fdeddc0bc9 | 105 | /* uECC_RNG_Function type |
allankliu | 0:b6fdeddc0bc9 | 106 | The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if |
allankliu | 0:b6fdeddc0bc9 | 107 | 'dest' was filled with random data, or 0 if the random data could not be generated. |
allankliu | 0:b6fdeddc0bc9 | 108 | The filled-in values should be either truly random, or from a cryptographically-secure PRNG. |
allankliu | 0:b6fdeddc0bc9 | 109 | |
allankliu | 0:b6fdeddc0bc9 | 110 | A correctly functioning RNG function must be set (using uECC_set_rng()) before calling |
allankliu | 0:b6fdeddc0bc9 | 111 | uECC_make_key() or uECC_sign(). |
allankliu | 0:b6fdeddc0bc9 | 112 | |
allankliu | 0:b6fdeddc0bc9 | 113 | Setting a correctly functioning RNG function improves the resistance to side-channel attacks |
allankliu | 0:b6fdeddc0bc9 | 114 | for uECC_shared_secret() and uECC_sign_deterministic(). |
allankliu | 0:b6fdeddc0bc9 | 115 | |
allankliu | 0:b6fdeddc0bc9 | 116 | A correct RNG function is set by default when building for Windows, Linux, or OS X. |
allankliu | 0:b6fdeddc0bc9 | 117 | If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom, |
allankliu | 0:b6fdeddc0bc9 | 118 | you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined |
allankliu | 0:b6fdeddc0bc9 | 119 | RNG function; you must provide your own. |
allankliu | 0:b6fdeddc0bc9 | 120 | */ |
allankliu | 0:b6fdeddc0bc9 | 121 | typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size); |
allankliu | 0:b6fdeddc0bc9 | 122 | |
allankliu | 0:b6fdeddc0bc9 | 123 | /* uECC_set_rng() function. |
allankliu | 0:b6fdeddc0bc9 | 124 | Set the function that will be used to generate random bytes. The RNG function should |
allankliu | 0:b6fdeddc0bc9 | 125 | return 1 if the random data was generated, or 0 if the random data could not be generated. |
allankliu | 0:b6fdeddc0bc9 | 126 | |
allankliu | 0:b6fdeddc0bc9 | 127 | On platforms where there is no predefined RNG function (eg embedded platforms), this must |
allankliu | 0:b6fdeddc0bc9 | 128 | be called before uECC_make_key() or uECC_sign() are used. |
allankliu | 0:b6fdeddc0bc9 | 129 | |
allankliu | 0:b6fdeddc0bc9 | 130 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 131 | rng_function - The function that will be used to generate random bytes. |
allankliu | 0:b6fdeddc0bc9 | 132 | */ |
allankliu | 0:b6fdeddc0bc9 | 133 | void uECC_set_rng(uECC_RNG_Function rng_function); |
allankliu | 0:b6fdeddc0bc9 | 134 | |
allankliu | 0:b6fdeddc0bc9 | 135 | /* uECC_get_rng() function. |
allankliu | 0:b6fdeddc0bc9 | 136 | |
allankliu | 0:b6fdeddc0bc9 | 137 | Returns the function that will be used to generate random bytes. |
allankliu | 0:b6fdeddc0bc9 | 138 | */ |
allankliu | 0:b6fdeddc0bc9 | 139 | uECC_RNG_Function uECC_get_rng(void); |
allankliu | 0:b6fdeddc0bc9 | 140 | |
allankliu | 0:b6fdeddc0bc9 | 141 | /* uECC_curve_private_key_size() function. |
allankliu | 0:b6fdeddc0bc9 | 142 | |
allankliu | 0:b6fdeddc0bc9 | 143 | Returns the size of a private key for the curve in bytes. |
allankliu | 0:b6fdeddc0bc9 | 144 | */ |
allankliu | 0:b6fdeddc0bc9 | 145 | int uECC_curve_private_key_size(uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 146 | |
allankliu | 0:b6fdeddc0bc9 | 147 | /* uECC_curve_public_key_size() function. |
allankliu | 0:b6fdeddc0bc9 | 148 | |
allankliu | 0:b6fdeddc0bc9 | 149 | Returns the size of a public key for the curve in bytes. |
allankliu | 0:b6fdeddc0bc9 | 150 | */ |
allankliu | 0:b6fdeddc0bc9 | 151 | int uECC_curve_public_key_size(uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 152 | |
allankliu | 0:b6fdeddc0bc9 | 153 | /* uECC_make_key() function. |
allankliu | 0:b6fdeddc0bc9 | 154 | Create a public/private key pair. |
allankliu | 0:b6fdeddc0bc9 | 155 | |
allankliu | 0:b6fdeddc0bc9 | 156 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 157 | public_key - Will be filled in with the public key. Must be at least 2 * the curve size |
allankliu | 0:b6fdeddc0bc9 | 158 | (in bytes) long. For example, if the curve is secp256r1, public_key must be 64 |
allankliu | 0:b6fdeddc0bc9 | 159 | bytes long. |
allankliu | 0:b6fdeddc0bc9 | 160 | private_key - Will be filled in with the private key. Must be as long as the curve order; this |
allankliu | 0:b6fdeddc0bc9 | 161 | is typically the same as the curve size, except for secp160r1. For example, if the |
allankliu | 0:b6fdeddc0bc9 | 162 | curve is secp256r1, private_key must be 32 bytes long. |
allankliu | 0:b6fdeddc0bc9 | 163 | |
allankliu | 0:b6fdeddc0bc9 | 164 | For secp160r1, private_key must be 21 bytes long! Note that the first byte will |
allankliu | 0:b6fdeddc0bc9 | 165 | almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero). |
allankliu | 0:b6fdeddc0bc9 | 166 | |
allankliu | 0:b6fdeddc0bc9 | 167 | Returns 1 if the key pair was generated successfully, 0 if an error occurred. |
allankliu | 0:b6fdeddc0bc9 | 168 | */ |
allankliu | 0:b6fdeddc0bc9 | 169 | int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 170 | |
allankliu | 0:b6fdeddc0bc9 | 171 | /* uECC_shared_secret() function. |
allankliu | 0:b6fdeddc0bc9 | 172 | Compute a shared secret given your secret key and someone else's public key. |
allankliu | 0:b6fdeddc0bc9 | 173 | Note: It is recommended that you hash the result of uECC_shared_secret() before using it for |
allankliu | 0:b6fdeddc0bc9 | 174 | symmetric encryption or HMAC. |
allankliu | 0:b6fdeddc0bc9 | 175 | |
allankliu | 0:b6fdeddc0bc9 | 176 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 177 | public_key - The public key of the remote party. |
allankliu | 0:b6fdeddc0bc9 | 178 | private_key - Your private key. |
allankliu | 0:b6fdeddc0bc9 | 179 | |
allankliu | 0:b6fdeddc0bc9 | 180 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 181 | secret - Will be filled in with the shared secret value. Must be the same size as the |
allankliu | 0:b6fdeddc0bc9 | 182 | curve size; for example, if the curve is secp256r1, secret must be 32 bytes long. |
allankliu | 0:b6fdeddc0bc9 | 183 | |
allankliu | 0:b6fdeddc0bc9 | 184 | Returns 1 if the shared secret was generated successfully, 0 if an error occurred. |
allankliu | 0:b6fdeddc0bc9 | 185 | */ |
allankliu | 0:b6fdeddc0bc9 | 186 | int uECC_shared_secret(const uint8_t *public_key, |
allankliu | 0:b6fdeddc0bc9 | 187 | const uint8_t *private_key, |
allankliu | 0:b6fdeddc0bc9 | 188 | uint8_t *secret, |
allankliu | 0:b6fdeddc0bc9 | 189 | uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 190 | |
allankliu | 0:b6fdeddc0bc9 | 191 | #if uECC_SUPPORT_COMPRESSED_POINT |
allankliu | 0:b6fdeddc0bc9 | 192 | /* uECC_compress() function. |
allankliu | 0:b6fdeddc0bc9 | 193 | Compress a public key. |
allankliu | 0:b6fdeddc0bc9 | 194 | |
allankliu | 0:b6fdeddc0bc9 | 195 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 196 | public_key - The public key to compress. |
allankliu | 0:b6fdeddc0bc9 | 197 | |
allankliu | 0:b6fdeddc0bc9 | 198 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 199 | compressed - Will be filled in with the compressed public key. Must be at least |
allankliu | 0:b6fdeddc0bc9 | 200 | (curve size + 1) bytes long; for example, if the curve is secp256r1, |
allankliu | 0:b6fdeddc0bc9 | 201 | compressed must be 33 bytes long. |
allankliu | 0:b6fdeddc0bc9 | 202 | */ |
allankliu | 0:b6fdeddc0bc9 | 203 | void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 204 | |
allankliu | 0:b6fdeddc0bc9 | 205 | /* uECC_decompress() function. |
allankliu | 0:b6fdeddc0bc9 | 206 | Decompress a compressed public key. |
allankliu | 0:b6fdeddc0bc9 | 207 | |
allankliu | 0:b6fdeddc0bc9 | 208 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 209 | compressed - The compressed public key. |
allankliu | 0:b6fdeddc0bc9 | 210 | |
allankliu | 0:b6fdeddc0bc9 | 211 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 212 | public_key - Will be filled in with the decompressed public key. |
allankliu | 0:b6fdeddc0bc9 | 213 | */ |
allankliu | 0:b6fdeddc0bc9 | 214 | void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 215 | #endif /* uECC_SUPPORT_COMPRESSED_POINT */ |
allankliu | 0:b6fdeddc0bc9 | 216 | |
allankliu | 0:b6fdeddc0bc9 | 217 | /* uECC_valid_public_key() function. |
allankliu | 0:b6fdeddc0bc9 | 218 | Check to see if a public key is valid. |
allankliu | 0:b6fdeddc0bc9 | 219 | |
allankliu | 0:b6fdeddc0bc9 | 220 | Note that you are not required to check for a valid public key before using any other uECC |
allankliu | 0:b6fdeddc0bc9 | 221 | functions. However, you may wish to avoid spending CPU time computing a shared secret or |
allankliu | 0:b6fdeddc0bc9 | 222 | verifying a signature using an invalid public key. |
allankliu | 0:b6fdeddc0bc9 | 223 | |
allankliu | 0:b6fdeddc0bc9 | 224 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 225 | public_key - The public key to check. |
allankliu | 0:b6fdeddc0bc9 | 226 | |
allankliu | 0:b6fdeddc0bc9 | 227 | Returns 1 if the public key is valid, 0 if it is invalid. |
allankliu | 0:b6fdeddc0bc9 | 228 | */ |
allankliu | 0:b6fdeddc0bc9 | 229 | int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 230 | |
allankliu | 0:b6fdeddc0bc9 | 231 | /* uECC_compute_public_key() function. |
allankliu | 0:b6fdeddc0bc9 | 232 | Compute the corresponding public key for a private key. |
allankliu | 0:b6fdeddc0bc9 | 233 | |
allankliu | 0:b6fdeddc0bc9 | 234 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 235 | private_key - The private key to compute the public key for |
allankliu | 0:b6fdeddc0bc9 | 236 | |
allankliu | 0:b6fdeddc0bc9 | 237 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 238 | public_key - Will be filled in with the corresponding public key |
allankliu | 0:b6fdeddc0bc9 | 239 | |
allankliu | 0:b6fdeddc0bc9 | 240 | Returns 1 if the key was computed successfully, 0 if an error occurred. |
allankliu | 0:b6fdeddc0bc9 | 241 | */ |
allankliu | 0:b6fdeddc0bc9 | 242 | int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 243 | |
allankliu | 0:b6fdeddc0bc9 | 244 | /* uECC_sign() function. |
allankliu | 0:b6fdeddc0bc9 | 245 | Generate an ECDSA signature for a given hash value. |
allankliu | 0:b6fdeddc0bc9 | 246 | |
allankliu | 0:b6fdeddc0bc9 | 247 | Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to |
allankliu | 0:b6fdeddc0bc9 | 248 | this function along with your private key. |
allankliu | 0:b6fdeddc0bc9 | 249 | |
allankliu | 0:b6fdeddc0bc9 | 250 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 251 | private_key - Your private key. |
allankliu | 0:b6fdeddc0bc9 | 252 | message_hash - The hash of the message to sign. |
allankliu | 0:b6fdeddc0bc9 | 253 | hash_size - The size of message_hash in bytes. |
allankliu | 0:b6fdeddc0bc9 | 254 | |
allankliu | 0:b6fdeddc0bc9 | 255 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 256 | signature - Will be filled in with the signature value. Must be at least 2 * curve size long. |
allankliu | 0:b6fdeddc0bc9 | 257 | For example, if the curve is secp256r1, signature must be 64 bytes long. |
allankliu | 0:b6fdeddc0bc9 | 258 | |
allankliu | 0:b6fdeddc0bc9 | 259 | Returns 1 if the signature generated successfully, 0 if an error occurred. |
allankliu | 0:b6fdeddc0bc9 | 260 | */ |
allankliu | 0:b6fdeddc0bc9 | 261 | int uECC_sign(const uint8_t *private_key, |
allankliu | 0:b6fdeddc0bc9 | 262 | const uint8_t *message_hash, |
allankliu | 0:b6fdeddc0bc9 | 263 | unsigned hash_size, |
allankliu | 0:b6fdeddc0bc9 | 264 | uint8_t *signature, |
allankliu | 0:b6fdeddc0bc9 | 265 | uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 266 | |
allankliu | 0:b6fdeddc0bc9 | 267 | /* uECC_HashContext structure. |
allankliu | 0:b6fdeddc0bc9 | 268 | This is used to pass in an arbitrary hash function to uECC_sign_deterministic(). |
allankliu | 0:b6fdeddc0bc9 | 269 | The structure will be used for multiple hash computations; each time a new hash |
allankliu | 0:b6fdeddc0bc9 | 270 | is computed, init_hash() will be called, followed by one or more calls to |
allankliu | 0:b6fdeddc0bc9 | 271 | update_hash(), and finally a call to finish_hash() to produce the resulting hash. |
allankliu | 0:b6fdeddc0bc9 | 272 | |
allankliu | 0:b6fdeddc0bc9 | 273 | The intention is that you will create a structure that includes uECC_HashContext |
allankliu | 0:b6fdeddc0bc9 | 274 | followed by any hash-specific data. For example: |
allankliu | 0:b6fdeddc0bc9 | 275 | |
allankliu | 0:b6fdeddc0bc9 | 276 | typedef struct SHA256_HashContext { |
allankliu | 0:b6fdeddc0bc9 | 277 | uECC_HashContext uECC; |
allankliu | 0:b6fdeddc0bc9 | 278 | SHA256_CTX ctx; |
allankliu | 0:b6fdeddc0bc9 | 279 | } SHA256_HashContext; |
allankliu | 0:b6fdeddc0bc9 | 280 | |
allankliu | 0:b6fdeddc0bc9 | 281 | void init_SHA256(uECC_HashContext *base) { |
allankliu | 0:b6fdeddc0bc9 | 282 | SHA256_HashContext *context = (SHA256_HashContext *)base; |
allankliu | 0:b6fdeddc0bc9 | 283 | SHA256_Init(&context->ctx); |
allankliu | 0:b6fdeddc0bc9 | 284 | } |
allankliu | 0:b6fdeddc0bc9 | 285 | |
allankliu | 0:b6fdeddc0bc9 | 286 | void update_SHA256(uECC_HashContext *base, |
allankliu | 0:b6fdeddc0bc9 | 287 | const uint8_t *message, |
allankliu | 0:b6fdeddc0bc9 | 288 | unsigned message_size) { |
allankliu | 0:b6fdeddc0bc9 | 289 | SHA256_HashContext *context = (SHA256_HashContext *)base; |
allankliu | 0:b6fdeddc0bc9 | 290 | SHA256_Update(&context->ctx, message, message_size); |
allankliu | 0:b6fdeddc0bc9 | 291 | } |
allankliu | 0:b6fdeddc0bc9 | 292 | |
allankliu | 0:b6fdeddc0bc9 | 293 | void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) { |
allankliu | 0:b6fdeddc0bc9 | 294 | SHA256_HashContext *context = (SHA256_HashContext *)base; |
allankliu | 0:b6fdeddc0bc9 | 295 | SHA256_Final(hash_result, &context->ctx); |
allankliu | 0:b6fdeddc0bc9 | 296 | } |
allankliu | 0:b6fdeddc0bc9 | 297 | |
allankliu | 0:b6fdeddc0bc9 | 298 | ... when signing ... |
allankliu | 0:b6fdeddc0bc9 | 299 | { |
allankliu | 0:b6fdeddc0bc9 | 300 | uint8_t tmp[32 + 32 + 64]; |
allankliu | 0:b6fdeddc0bc9 | 301 | SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}}; |
allankliu | 0:b6fdeddc0bc9 | 302 | uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature); |
allankliu | 0:b6fdeddc0bc9 | 303 | } |
allankliu | 0:b6fdeddc0bc9 | 304 | */ |
allankliu | 0:b6fdeddc0bc9 | 305 | typedef struct uECC_HashContext { |
allankliu | 0:b6fdeddc0bc9 | 306 | void (*init_hash)(const struct uECC_HashContext *context); |
allankliu | 0:b6fdeddc0bc9 | 307 | void (*update_hash)(const struct uECC_HashContext *context, |
allankliu | 0:b6fdeddc0bc9 | 308 | const uint8_t *message, |
allankliu | 0:b6fdeddc0bc9 | 309 | unsigned message_size); |
allankliu | 0:b6fdeddc0bc9 | 310 | void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result); |
allankliu | 0:b6fdeddc0bc9 | 311 | unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */ |
allankliu | 0:b6fdeddc0bc9 | 312 | unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */ |
allankliu | 0:b6fdeddc0bc9 | 313 | uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */ |
allankliu | 0:b6fdeddc0bc9 | 314 | } uECC_HashContext; |
allankliu | 0:b6fdeddc0bc9 | 315 | |
allankliu | 0:b6fdeddc0bc9 | 316 | /* uECC_sign_deterministic() function. |
allankliu | 0:b6fdeddc0bc9 | 317 | Generate an ECDSA signature for a given hash value, using a deterministic algorithm |
allankliu | 0:b6fdeddc0bc9 | 318 | (see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling |
allankliu | 0:b6fdeddc0bc9 | 319 | this function; however, if the RNG is defined it will improve resistance to side-channel |
allankliu | 0:b6fdeddc0bc9 | 320 | attacks. |
allankliu | 0:b6fdeddc0bc9 | 321 | |
allankliu | 0:b6fdeddc0bc9 | 322 | Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to |
allankliu | 0:b6fdeddc0bc9 | 323 | this function along with your private key and a hash context. Note that the message_hash |
allankliu | 0:b6fdeddc0bc9 | 324 | does not need to be computed with the same hash function used by hash_context. |
allankliu | 0:b6fdeddc0bc9 | 325 | |
allankliu | 0:b6fdeddc0bc9 | 326 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 327 | private_key - Your private key. |
allankliu | 0:b6fdeddc0bc9 | 328 | message_hash - The hash of the message to sign. |
allankliu | 0:b6fdeddc0bc9 | 329 | hash_size - The size of message_hash in bytes. |
allankliu | 0:b6fdeddc0bc9 | 330 | hash_context - A hash context to use. |
allankliu | 0:b6fdeddc0bc9 | 331 | |
allankliu | 0:b6fdeddc0bc9 | 332 | Outputs: |
allankliu | 0:b6fdeddc0bc9 | 333 | signature - Will be filled in with the signature value. |
allankliu | 0:b6fdeddc0bc9 | 334 | |
allankliu | 0:b6fdeddc0bc9 | 335 | Returns 1 if the signature generated successfully, 0 if an error occurred. |
allankliu | 0:b6fdeddc0bc9 | 336 | */ |
allankliu | 0:b6fdeddc0bc9 | 337 | int uECC_sign_deterministic(const uint8_t *private_key, |
allankliu | 0:b6fdeddc0bc9 | 338 | const uint8_t *message_hash, |
allankliu | 0:b6fdeddc0bc9 | 339 | unsigned hash_size, |
allankliu | 0:b6fdeddc0bc9 | 340 | const uECC_HashContext *hash_context, |
allankliu | 0:b6fdeddc0bc9 | 341 | uint8_t *signature, |
allankliu | 0:b6fdeddc0bc9 | 342 | uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 343 | |
allankliu | 0:b6fdeddc0bc9 | 344 | /* uECC_verify() function. |
allankliu | 0:b6fdeddc0bc9 | 345 | Verify an ECDSA signature. |
allankliu | 0:b6fdeddc0bc9 | 346 | |
allankliu | 0:b6fdeddc0bc9 | 347 | Usage: Compute the hash of the signed data using the same hash as the signer and |
allankliu | 0:b6fdeddc0bc9 | 348 | pass it to this function along with the signer's public key and the signature values (r and s). |
allankliu | 0:b6fdeddc0bc9 | 349 | |
allankliu | 0:b6fdeddc0bc9 | 350 | Inputs: |
allankliu | 0:b6fdeddc0bc9 | 351 | public_key - The signer's public key. |
allankliu | 0:b6fdeddc0bc9 | 352 | message_hash - The hash of the signed data. |
allankliu | 0:b6fdeddc0bc9 | 353 | hash_size - The size of message_hash in bytes. |
allankliu | 0:b6fdeddc0bc9 | 354 | signature - The signature value. |
allankliu | 0:b6fdeddc0bc9 | 355 | |
allankliu | 0:b6fdeddc0bc9 | 356 | Returns 1 if the signature is valid, 0 if it is invalid. |
allankliu | 0:b6fdeddc0bc9 | 357 | */ |
allankliu | 0:b6fdeddc0bc9 | 358 | int uECC_verify(const uint8_t *public_key, |
allankliu | 0:b6fdeddc0bc9 | 359 | const uint8_t *message_hash, |
allankliu | 0:b6fdeddc0bc9 | 360 | unsigned hash_size, |
allankliu | 0:b6fdeddc0bc9 | 361 | const uint8_t *signature, |
allankliu | 0:b6fdeddc0bc9 | 362 | uECC_Curve curve); |
allankliu | 0:b6fdeddc0bc9 | 363 | |
allankliu | 0:b6fdeddc0bc9 | 364 | #ifdef __cplusplus |
allankliu | 0:b6fdeddc0bc9 | 365 | } /* end of extern "C" */ |
allankliu | 0:b6fdeddc0bc9 | 366 | #endif |
allankliu | 0:b6fdeddc0bc9 | 367 | |
allankliu | 0:b6fdeddc0bc9 | 368 | #endif /* _UECC_H_ */ |