| /* Copyright 2013 Kenneth MacKay. Licensed under the BSD 2-clause license. */ |
| |
| #ifndef _MICRO_ECC_H_ |
| #define _MICRO_ECC_H_ |
| |
| #include <stdint.h> |
| |
| /* Optimization settings. Define as 1 to enable an optimization, 0 to disable it. |
| ECC_SQUARE_FUNC - If enabled, this will cause a specific function to be used for (scalar) squaring instead of the generic |
| multiplication function. Improves speed by about 8% . |
| */ |
| #define ECC_SQUARE_FUNC 1 |
| |
| /* Inline assembly options. |
| Inline assembly (gcc format) is provided for selected operations for Thumb and Thumb2/ARM. |
| Improves speed by about 57% on Cortex-M0 when using ecc_asm_thumb. |
| |
| Note: You must choose the appropriate option for your target architecture, or compilation will fail |
| with strange assembler messages. |
| */ |
| #define ecc_asm_none 0 |
| #define ecc_asm_thumb 1 /* ARM Thumb assembly (including Cortex-M0) */ |
| #define ecc_asm_thumb2 2 /* ARM Thumb-2 assembly (eg Cortex-M3) */ |
| #define ecc_asm_arm 3 /* Regular ARM assembly */ |
| #ifndef ECC_ASM |
| #define ECC_ASM ecc_asm_none |
| #endif |
| |
| #define ECC_CONCAT1(a, b) a##b |
| #define ECC_CONCAT(a, b) ECC_CONCAT1(a, b) |
| |
| /* Curve selection options. */ |
| #define secp128r1 1 |
| #define secp192r1 2 |
| #define secp256r1 3 |
| #define secp384r1 4 |
| #define secp256k1 5 |
| |
| #ifndef ECC_CURVE |
| #define ECC_CURVE secp256r1 |
| #endif |
| |
| #define ecc_size_1 4 |
| #define ecc_size_2 6 |
| #define ecc_size_3 8 |
| #define ecc_size_4 12 |
| #define ecc_size_5 8 |
| |
| #define NUM_ECC_DIGITS ECC_CONCAT(ecc_size_, ECC_CURVE) |
| |
| typedef struct EccPoint |
| { |
| uint32_t x[NUM_ECC_DIGITS]; |
| uint32_t y[NUM_ECC_DIGITS]; |
| } EccPoint; |
| |
| /* ecc_make_key() function. |
| Create a public/private key pair. |
| |
| You must use a new nonpredictable random number to generate each new key pair. |
| |
| Outputs: |
| p_publicKey - Will be filled in with the point representing the public key. |
| p_privateKey - Will be filled in with the private key. |
| |
| Inputs: |
| p_random - The random number to use to generate the key pair. |
| |
| Returns 1 if the key pair was generated successfully, 0 if an error occurred. If 0 is returned, |
| try again with a different random number. |
| */ |
| int ecc_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS]); |
| |
| /* ecc_valid_public_key() function. |
| Determine whether or not a given point is on the chosen elliptic curve (ie, is a valid public key). |
| |
| Inputs: |
| p_publicKey - The point to check. |
| |
| Returns 1 if the given point is valid, 0 if it is invalid. |
| */ |
| int ecc_valid_public_key(EccPoint *p_publicKey); |
| |
| /* ecdh_shared_secret() function. |
| Compute a shared secret given your secret key and someone else's public key. |
| |
| Optionally, you can provide a random multiplier for resistance to DPA attacks. The random multiplier |
| should probably be different for each invocation of ecdh_shared_secret(). |
| |
| Outputs: |
| p_secret - Will be filled in with the shared secret value. |
| |
| Inputs: |
| p_publicKey - The public key of the remote party. |
| p_privateKey - Your private key. |
| p_random - An optional random number to resist DPA attacks. Pass in NULL if DPA attacks are not a concern. |
| |
| Returns 1 if the shared secret was computed successfully, 0 otherwise. |
| |
| Note: It is recommended that you hash the result of ecdh_shared_secret before using it for symmetric encryption or HMAC. |
| If you do not hash the shared secret, you must call ecc_valid_public_key() to verify that the remote side's public key is valid. |
| If this is not done, an attacker could create a public key that would cause your use of the shared secret to leak information |
| about your private key. */ |
| int ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], uint32_t p_random[NUM_ECC_DIGITS]); |
| |
| /* ecdsa_sign() function. |
| Generate an ECDSA signature for a given hash value. |
| |
| Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to |
| this function along with your private key and a random number. |
| You must use a new nonpredictable random number to generate each new signature. |
| |
| Outputs: |
| r, s - Will be filled in with the signature values. |
| |
| Inputs: |
| p_privateKey - Your private key. |
| p_random - The random number to use to generate the signature. |
| p_hash - The message hash to sign. |
| |
| Returns 1 if the signature generated successfully, 0 if an error occurred. If 0 is returned, |
| try again with a different random number. |
| */ |
| int ecdsa_sign(uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS], uint32_t p_privateKey[NUM_ECC_DIGITS], |
| uint32_t p_random[NUM_ECC_DIGITS], uint32_t p_hash[NUM_ECC_DIGITS]); |
| |
| /* ecdsa_verify() function. |
| Verify an ECDSA signature. |
| |
| Usage: Compute the hash of the signed data using the same hash as the signer and |
| pass it to this function along with the signer's public key and the signature values (r and s). |
| |
| Inputs: |
| p_publicKey - The signer's public key |
| p_hash - The hash of the signed data. |
| r, s - The signature values. |
| |
| Returns 1 if the signature is valid, 0 if it is invalid. |
| */ |
| int ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS]); |
| |
| /* ecc_bytes2native() function. |
| Convert an integer in standard octet representation to the native format. |
| |
| Outputs: |
| p_native - Will be filled in with the native integer value. |
| |
| Inputs: |
| p_bytes - The standard octet representation of the integer to convert. |
| */ |
| void ecc_bytes2native(uint32_t p_native[NUM_ECC_DIGITS], uint8_t p_bytes[NUM_ECC_DIGITS*4]); |
| |
| /* ecc_native2bytes() function. |
| Convert an integer in native format to the standard octet representation. |
| |
| Outputs: |
| p_bytes - Will be filled in with the standard octet representation of the integer. |
| |
| Inputs: |
| p_native - The native integer value to convert. |
| */ |
| void ecc_native2bytes(uint8_t p_bytes[NUM_ECC_DIGITS*4], uint32_t p_native[NUM_ECC_DIGITS]); |
| |
| /* ecc_point_compress() function. |
| Compress a point from native format into the standard compressed octet representation. |
| |
| Outputs: |
| p_compressed - Will be filled in with the compressed point representation. |
| |
| Inputs: |
| p_point - The point to compress. |
| */ |
| void ecc_point_compress(uint8_t p_compressed[NUM_ECC_DIGITS*4 + 1], EccPoint *p_point); |
| |
| /* ecc_point_compress() function. |
| Decompress a point from the standard compressed octet representation to native format. |
| |
| Outputs: |
| p_point - Will be filled in with the native point representation. |
| |
| Inputs: |
| p_compressed - The standard compressed octet representation of the point. |
| */ |
| void ecc_point_decompress(EccPoint *p_point, uint8_t p_compressed[NUM_ECC_DIGITS*4 + 1]); |
| |
| #endif /* _MICRO_ECC_H_ */ |