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