micro-ECC for mbed, ported from GCC version from Github,

Dependents:   mbed_microECC Wallet_v1

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?

UserRevisionLine numberNew 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_ */