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