Mistake on this page?
Report an issue in GitHub or email us
uECC.h
1 /* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
2 
3 #ifndef _MICRO_ECC_H_
4 #define _MICRO_ECC_H_
5 
6 #include "wsf_types.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_avr 5
17 #define uECC_arm_thumb2 6
18 
19 /* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
20 If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
21 platform. */
22 
23 /* Inline assembly options.
24 uECC_asm_none - Use standard C99 only.
25 uECC_asm_small - Use GCC inline assembly for the target platform (if available), optimized for
26  minimum size.
27 uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */
28 #define uECC_asm_none 0
29 #define uECC_asm_small 1
30 #define uECC_asm_fast 2
31 #ifndef uECC_ASM
32  #define uECC_ASM uECC_asm_fast
33 #endif
34 
35 /* Curve selection options. */
36 #define uECC_secp160r1 1
37 #define uECC_secp192r1 2
38 #define uECC_secp256r1 3
39 #define uECC_secp256k1 4
40 #define uECC_secp224r1 5
41 #ifndef uECC_CURVE
42  #define uECC_CURVE uECC_secp256r1
43 #endif
44 
45 /* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
46 used for (scalar) squaring instead of the generic multiplication function. This will make things
47 faster by about 8% but increases the code size. */
48 #ifndef uECC_SQUARE_FUNC
49  #define uECC_SQUARE_FUNC 1
50 #endif
51 
52 #define uECC_CONCAT1(a, b) a##b
53 #define uECC_CONCAT(a, b) uECC_CONCAT1(a, b)
54 
55 #define uECC_size_1 20 /* secp160r1 */
56 #define uECC_size_2 24 /* secp192r1 */
57 #define uECC_size_3 32 /* secp256r1 */
58 #define uECC_size_4 32 /* secp256k1 */
59 #define uECC_size_5 28 /* secp224r1 */
60 
61 #define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE)
62 
63 #ifdef __cplusplus
64 extern "C"
65 {
66 #endif
67 
68 /* uECC_RNG_Function type
69 The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
70 'dest' was filled with random data, or 0 if the random data could not be generated.
71 The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
72 
73 A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
74 uECC_make_key() or uECC_sign().
75 
76 Setting a correctly functioning RNG function improves the resistance to side-channel attacks
77 for uECC_shared_secret() and uECC_sign_deterministic().
78 
79 A correct RNG function is set by default when building for Windows, Linux, or OS X.
80 If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
81 you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
82 RNG function; you must provide your own.
83 */
84 typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
85 
86 /* uECC_set_rng() function.
87 Set the function that will be used to generate random bytes. The RNG function should
88 return 1 if the random data was generated, or 0 if the random data could not be generated.
89 
90 On platforms where there is no predefined RNG function (eg embedded platforms), this must
91 be called before uECC_make_key() or uECC_sign() are used.
92 
93 Inputs:
94  rng_function - The function that will be used to generate random bytes.
95 */
96 void uECC_set_rng(uECC_RNG_Function rng_function);
97 
98 /* uECC_make_key() function.
99 Create a public/private key pair.
100 
101 Outputs:
102  public_key - Will be filled in with the public key.
103  private_key - Will be filled in with the private key.
104 
105 Returns 1 if the key pair was generated successfully, 0 if an error occurred.
106 */
107 int uECC_make_key(uint8_t public_key[uECC_BYTES*2], uint8_t private_key[uECC_BYTES]);
108 
109 /* uECC_shared_secret() function.
110 Compute a shared secret given your secret key and someone else's public key.
111 Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
112 symmetric encryption or HMAC.
113 
114 Inputs:
115  public_key - The public key of the remote party.
116  private_key - Your private key.
117 
118 Outputs:
119  secret - Will be filled in with the shared secret value.
120 
121 Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
122 */
123 int uECC_shared_secret(const uint8_t public_key[uECC_BYTES*2],
124  const uint8_t private_key[uECC_BYTES],
125  uint8_t secret[uECC_BYTES]);
126 
127 /* uECC_sign() function.
128 Generate an ECDSA signature for a given hash value.
129 
130 Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
131 this function along with your private key.
132 
133 Inputs:
134  private_key - Your private key.
135  message_hash - The hash of the message to sign.
136 
137 Outputs:
138  signature - Will be filled in with the signature value.
139 
140 Returns 1 if the signature generated successfully, 0 if an error occurred.
141 */
142 int uECC_sign(const uint8_t private_key[uECC_BYTES],
143  const uint8_t message_hash[uECC_BYTES],
144  uint8_t signature[uECC_BYTES*2]);
145 
146 /* uECC_HashContext structure.
147 This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
148 The structure will be used for multiple hash computations; each time a new hash
149 is computed, init_hash() will be called, followed by one or more calls to
150 update_hash(), and finally a call to finish_hash() to prudoce the resulting hash.
151 
152 The intention is that you will create a structure that includes uECC_HashContext
153 followed by any hash-specific data. For example:
154 
155 typedef struct SHA256_HashContext {
156  uECC_HashContext uECC;
157  SHA256_CTX ctx;
158 } SHA256_HashContext;
159 
160 void init_SHA256(uECC_HashContext *base) {
161  SHA256_HashContext *context = (SHA256_HashContext *)base;
162  SHA256_Init(&context->ctx);
163 }
164 
165 void update_SHA256(uECC_HashContext *base,
166  const uint8_t *message,
167  unsigned message_size) {
168  SHA256_HashContext *context = (SHA256_HashContext *)base;
169  SHA256_Update(&context->ctx, message, message_size);
170 }
171 
172 void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
173  SHA256_HashContext *context = (SHA256_HashContext *)base;
174  SHA256_Final(hash_result, &context->ctx);
175 }
176 
177 ... when signing ...
178 {
179  uint8_t tmp[32 + 32 + 64];
180  SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
181  uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
182 }
183 */
184 typedef struct uECC_HashContext {
185  void (*init_hash)(struct uECC_HashContext *context);
186  void (*update_hash)(struct uECC_HashContext *context,
187  const uint8_t *message,
188  unsigned message_size);
189  void (*finish_hash)(struct uECC_HashContext *context, uint8_t *hash_result);
190  unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
191  unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
192  uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
194 
195 /* uECC_sign_deterministic() function.
196 Generate an ECDSA signature for a given hash value, using a deterministic algorithm
197 (see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling
198 this function; however, if the RNG is defined it will improve resistance to side-channel
199 attacks.
200 
201 Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
202 this function along with your private key and a hash context.
203 
204 Inputs:
205  private_key - Your private key.
206  message_hash - The hash of the message to sign.
207  hash_context - A hash context to use.
208 
209 Outputs:
210  signature - Will be filled in with the signature value.
211 
212 Returns 1 if the signature generated successfully, 0 if an error occurred.
213 */
214 int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
215  const uint8_t message_hash[uECC_BYTES],
216  uECC_HashContext *hash_context,
217  uint8_t signature[uECC_BYTES*2]);
218 
219 /* uECC_verify() function.
220 Verify an ECDSA signature.
221 
222 Usage: Compute the hash of the signed data using the same hash as the signer and
223 pass it to this function along with the signer's public key and the signature values (r and s).
224 
225 Inputs:
226  public_key - The signer's public key
227  hash - The hash of the signed data.
228  signature - The signature value.
229 
230 Returns 1 if the signature is valid, 0 if it is invalid.
231 */
232 int uECC_verify(const uint8_t private_key[uECC_BYTES*2],
233  const uint8_t hash[uECC_BYTES],
234  const uint8_t signature[uECC_BYTES*2]);
235 
236 /* uECC_compress() function.
237 Compress a public key.
238 
239 Inputs:
240  public_key - The public key to compress.
241 
242 Outputs:
243  compressed - Will be filled in with the compressed public key.
244 */
245 void uECC_compress(const uint8_t public_key[uECC_BYTES*2], uint8_t compressed[uECC_BYTES+1]);
246 
247 /* uECC_decompress() function.
248 Decompress a compressed public key.
249 
250 Inputs:
251  compressed - The compressed public key.
252 
253 Outputs:
254  public_key - Will be filled in with the decompressed public key.
255 */
256 void uECC_decompress(const uint8_t compressed[uECC_BYTES+1], uint8_t public_key[uECC_BYTES*2]);
257 
258 /* uECC_valid_public_key() function.
259 Check to see if a public key is valid.
260 
261 Note that you are not required to check for a valid public key before using any other uECC
262 functions. However, you may wish to avoid spending CPU time computing a shared secret or
263 verifying a signature using an invalid public key.
264 
265 Inputs:
266  public_key - The public key to check.
267 
268 Returns 1 if the public key is valid, 0 if it is invalid.
269 */
270 int uECC_valid_public_key(const uint8_t public_key[uECC_BYTES*2]);
271 
272 /* uECC_compute_public_key() function.
273 Compute the corresponding public key for a private key.
274 
275 Inputs:
276  private_key - The private key to compute the public key for
277 
278 Outputs:
279  public_key - Will be filled in with the corresponding public key
280 
281 Returns 1 if the key was computed successfully, 0 if an error occurred.
282 */
283 int uECC_compute_public_key(const uint8_t private_key[uECC_BYTES],
284  uint8_t public_key[uECC_BYTES * 2]);
285 
286 
287 /* uECC_bytes() function.
288 Returns the value of uECC_BYTES. Helpful for foreign-interfaces to higher-level languages.
289 */
290 int uECC_bytes(void);
291 
292 /* uECC_curve() function.
293 Returns the value of uECC_CURVE. Helpful for foreign-interfaces to higher-level languages.
294 */
295 int uECC_curve(void);
296 
297 #ifdef __cplusplus
298 } /* end of extern "C" */
299 #endif
300 
301 #endif /* _MICRO_ECC_H_ */
Platform-independent data types.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.