-
Notifications
You must be signed in to change notification settings - Fork 2.1k
tests/pkg/micro-ecc: add unit tests #21921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,11 +12,43 @@ | |
| * | ||
| */ | ||
|
|
||
| #include <stdalign.h> | ||
| #include <stdbool.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
|
|
||
| #include "od.h" | ||
| #include "test_utils/expect.h" | ||
| #include "hashes/sha256.h" | ||
| #include "uECC.h" | ||
| #include "uECC_vli.h" | ||
|
|
||
| /** | ||
| * @name For access to mmod_fast for the unit tests, we sadly need to | ||
| * copy-paste an internal struct definition. | ||
| * @{ | ||
| */ | ||
| #define uECC_MAX_WORDS (32 / sizeof(uECC_word_t)) | ||
| struct uECC_Curve_t { | ||
| wordcount_t num_words; | ||
| wordcount_t num_bytes; | ||
| bitcount_t num_n_bits; | ||
| uECC_word_t p[uECC_MAX_WORDS]; | ||
| uECC_word_t n[uECC_MAX_WORDS]; | ||
| uECC_word_t G[uECC_MAX_WORDS * 2]; | ||
| uECC_word_t b[uECC_MAX_WORDS]; | ||
| void (*double_jacobian)(uECC_word_t * X1, | ||
| uECC_word_t * Y1, | ||
| uECC_word_t * Z1, | ||
| uECC_Curve curve); | ||
| #if uECC_SUPPORT_COMPRESSED_POINT | ||
| void (*mod_sqrt)(uECC_word_t *a, uECC_Curve curve); | ||
| #endif | ||
| void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); | ||
| #if (uECC_OPTIMIZATION_LEVEL > 0) | ||
| void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); | ||
| #endif | ||
| }; | ||
| /** @} */ | ||
|
|
||
| #define TESTROUNDS (4) | ||
| #define MAX_PUBLIC_KEY_SIZE (64) | ||
|
|
@@ -88,16 +120,242 @@ static void _finish_sha256(const uECC_HashContext *base, uint8_t *hash_result) | |
| sha256_final(&context->ctx, hash_result); | ||
| } | ||
|
|
||
| static bool _test_compare(const char *test_name, const void *got, const void *expected, size_t len) | ||
| { | ||
| bool success = (0 == memcmp(got, expected, len)); | ||
| static const char *fail_ok[] = { "[FAIL]", "[OK] " }; | ||
| printf("%s %s\n", fail_ok[success], test_name); | ||
| if (!success) { | ||
| puts("Got:"); | ||
| od_hex_dump(got, len, 0); | ||
| puts("Expected:"); | ||
| od_hex_dump(expected, len, 0); | ||
| } | ||
|
|
||
| return success; | ||
| } | ||
|
|
||
| static bool _test_uECC_vli_mult(void) | ||
| { | ||
| const alignas(uECC_word_t) uint8_t input1[] = { | ||
| 0x09, 0xB1, 0x2E, 0xA3, 0x85, 0xBB, 0xC7, 0x88, | ||
| 0xFF, 0xD1, 0xC4, 0xEC, 0x2A, 0x6A, 0xF9, 0x7A, | ||
| 0xE9, 0x7F, 0x39, 0x09, 0x86, 0x40, 0x94, 0x7E, | ||
| 0xD3, 0x40, 0x04, 0xBC, 0xCC, 0xF9, 0xDD, 0xC3 | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t input2[] = { | ||
| 0x1F, 0xFE, 0x6A, 0x32, 0xDF, 0x35, 0xEC, 0x95, | ||
| 0x2E, 0xF0, 0x24, 0x6D, 0x42, 0x0A, 0xA9, 0xE4, | ||
| 0x4D, 0xE1, 0xAF, 0x49, 0xF9, 0x46, 0x9A, 0x0E, | ||
| 0xCB, 0x25, 0x74, 0x8C, 0x69, 0x47, 0xEF, 0x9F | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t result_expected[] = { | ||
| 0x17, 0x5E, 0x08, 0x26, 0xD7, 0x10, 0x12, 0xBD, | ||
| 0xE0, 0x7C, 0x52, 0xCA, 0x12, 0xE7, 0x85, 0xE5, | ||
| 0x7B, 0x95, 0xC5, 0x54, 0x60, 0x3F, 0x53, 0x9B, | ||
| 0xB4, 0x8A, 0xAB, 0xFE, 0xEB, 0x50, 0x8F, 0x58, | ||
| 0x5E, 0x12, 0x49, 0x86, 0x0A, 0x6D, 0xCA, 0x8F, | ||
| 0x8A, 0x68, 0x02, 0x1E, 0x69, 0x15, 0xED, 0xEF, | ||
| 0x21, 0x85, 0x65, 0x28, 0xBB, 0xDE, 0xAD, 0xC5, | ||
| 0x75, 0xAB, 0xB3, 0xB0, 0x05, 0xF1, 0x5D, 0x7A | ||
| }; | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(result_expected)]; | ||
| uECC_vli_mult((void *)result_got, (void *)input1, (void *)input2, sizeof(input1) / sizeof(uECC_word_t)); | ||
| return _test_compare("uECC_vli_mult()", result_got, result_expected, sizeof(result_expected)); | ||
| } | ||
|
|
||
| static bool _test_uECC_vli_add(void) | ||
| { | ||
| const alignas(uECC_word_t) uint8_t input1[] = { | ||
| 0x59, 0x96, 0xC8, 0x96, 0x60, 0x03, 0x1A, 0xA1, | ||
| 0xCF, 0x20, 0xC8, 0x2A, 0xC5, 0xC4, 0x93, 0x10, | ||
| 0x54, 0xD7, 0x2E, 0x21, 0xDC, 0x99, 0xC0, 0x2A, | ||
| 0xFC, 0x80, 0x8C, 0xA8, 0xD9, 0x63, 0xBE, 0x00 | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t input2[] = { | ||
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
| 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t result_expected[] = { | ||
| 0x58, 0x96, 0xC8, 0x96, 0x60, 0x03, 0x1A, 0xA1, | ||
| 0xCF, 0x20, 0xC8, 0x2A, 0xC6, 0xC4, 0x93, 0x10, | ||
| 0x54, 0xD7, 0x2E, 0x21, 0xDC, 0x99, 0xC0, 0x2A, | ||
| 0xFD, 0x80, 0x8C, 0xA8, 0xD8, 0x63, 0xBE, 0x00 | ||
| }; | ||
| const uECC_word_t carry_expected = 1; | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(result_expected)]; | ||
| uECC_word_t carry_got = uECC_vli_add((void *)result_got, (void *)input1, (void *)input2, sizeof(input1)/sizeof(uECC_word_t)); | ||
| return _test_compare("uECC_vli_add()", result_got, result_expected, sizeof(result_expected)) | ||
| && _test_compare("uECC_vli_add() carry", &carry_got, &carry_expected, sizeof(carry_expected)); | ||
|
Comment on lines
+189
to
+191
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. long lines |
||
| } | ||
|
|
||
| static bool _test_uECC_vli_sub(void) | ||
| { | ||
| const alignas(uECC_word_t) uint8_t input1[] = { | ||
| 0xD1, 0x09, 0x26, 0xCE, 0x2A, 0xE1, 0xE3, 0xBB, | ||
| 0x99, 0xCF, 0x7A, 0x32, 0xE9, 0x38, 0x7D, 0xE2, | ||
| 0x51, 0x8E, 0xCB, 0xE8, 0x68, 0xCE, 0xD7, 0x40, | ||
| 0x3A, 0x22, 0x4B, 0x2D, 0x69, 0x99, 0x4D, 0x82 | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t input2[] = { | ||
| 0xBA, 0xC1, 0x36, 0xAA, 0xB4, 0x53, 0x80, 0x30, | ||
| 0x36, 0xB7, 0xCF, 0x34, 0x58, 0x2D, 0x83, 0x56, | ||
| 0xC9, 0xEB, 0x72, 0x0D, 0xC6, 0xCC, 0x46, 0x73, | ||
| 0x1F, 0xAD, 0xE6, 0xEF, 0x96, 0x56, 0x4E, 0xAD | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t result_expected[] = { | ||
| 0x17, 0x48, 0xEF, 0x23, 0x76, 0x8D, 0x63, 0x8B, | ||
| 0x63, 0x18, 0xAB, 0xFD, 0x90, 0x0B, 0xFA, 0x8B, | ||
| 0x88, 0xA2, 0x58, 0xDB, 0xA2, 0x01, 0x91, 0xCD, | ||
| 0x1A, 0x75, 0x64, 0x3D, 0xD2, 0x42, 0xFF, 0xD4 | ||
| }; | ||
| const uECC_word_t borrow_expected = 1; | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(result_expected)]; | ||
| uECC_word_t borrow_got = uECC_vli_sub((void *)result_got, (void *)input1, (void *)input2, sizeof(input1)/sizeof(uECC_word_t)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. long line |
||
| return _test_compare("uECC_vli_sub()", result_got, result_expected, sizeof(result_expected)) | ||
| && _test_compare("uECC_vli_sub() borrow", &borrow_got, &borrow_expected, sizeof(borrow_expected)); | ||
| } | ||
|
|
||
| static const alignas(uECC_word_t) uint8_t mmod_input[] = { | ||
| 0xE8, 0x53, 0x32, 0xAB, 0x7B, 0x43, 0x11, 0x4C, | ||
| 0xBA, 0x15, 0x85, 0x07, 0x06, 0x0B, 0x4D, 0x77, | ||
| 0x1F, 0x4C, 0x00, 0x3B, 0xCB, 0xD3, 0x93, 0x5C, | ||
| 0x9D, 0x0D, 0x59, 0xB0, 0xA8, 0xC8, 0x23, 0xE3, | ||
| 0x2A, 0x25, 0x3B, 0xBD, 0x3B, 0xEF, 0xDE, 0x11, | ||
| 0x84, 0x22, 0x5B, 0x73, 0x2D, 0x94, 0x01, 0x69, | ||
| 0xCB, 0xE7, 0x8C, 0xBF, 0x4A, 0x0E, 0xEC, 0xC8, | ||
| 0x8F, 0x2A, 0x70, 0x96, 0x98, 0x66, 0x85, 0x03 | ||
| }; | ||
| static const alignas(uECC_word_t) uint8_t mmod_result_expected[] = { | ||
| 0x7B, 0xB3, 0x61, 0xF2, 0xFC, 0xCD, 0xDC, 0xAE, | ||
| 0xF8, 0x2C, 0x00, 0x81, 0x43, 0x96, 0xB6, 0xBE, | ||
| 0x1B, 0x51, 0x28, 0x5D, 0x67, 0xF5, 0x74, 0x42, | ||
| 0x62, 0x54, 0x86, 0x74, 0xD5, 0x74, 0x19, 0x46 | ||
| }; | ||
| static bool _test_uECC_vli_mmod(void) | ||
| { | ||
| static const alignas(uECC_word_t) uint8_t mod[] = { | ||
| 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
| 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF | ||
| }; | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(mmod_result_expected)]; | ||
| alignas(uECC_word_t) uint8_t product[sizeof(mmod_input)]; | ||
| memcpy(product, mmod_input, sizeof(product)); | ||
| uECC_vli_mmod((void *)result_got, (void *)product, (void *)mod, sizeof(mmod_result_expected) / sizeof(uECC_word_t)); | ||
| return _test_compare("uECC_vli_mmod()", result_got, mmod_result_expected, sizeof(mmod_result_expected)); | ||
|
Comment on lines
+248
to
+249
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Long lines |
||
| } | ||
| static bool _test_uECC_vli_mmod_fast(uECC_Curve curve) | ||
| { | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(mmod_result_expected)]; | ||
| alignas(uECC_word_t) uint8_t product[sizeof(mmod_input)]; | ||
| memcpy(product, mmod_input, sizeof(product)); | ||
| curve->mmod_fast((void *)result_got, (void *)product); | ||
| return _test_compare("curve->mmod_fast()", result_got, mmod_result_expected, sizeof(mmod_result_expected)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. long line |
||
| } | ||
|
|
||
| static bool _test_uECC_vli_modSquare_fast(const uECC_Curve curve) | ||
| { | ||
| const alignas(uECC_word_t) uint8_t input[] = { | ||
| 0xA9, 0x26, 0x99, 0xD4, 0xD1, 0x43, 0x3E, 0x22, | ||
| 0x2A, 0xC3, 0x90, 0xE0, 0xF1, 0xE6, 0xEC, 0x1C, | ||
| 0x97, 0xE7, 0x70, 0xB7, 0x79, 0xF3, 0x28, 0xB3, | ||
| 0x30, 0xDB, 0xE1, 0x7C, 0x51, 0xCF, 0xEF, 0xFA, | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t result_expected[] = { | ||
| 0x8B, 0x52, 0xAF, 0x3A, 0xD9, 0xA9, 0x88, 0xB4, | ||
| 0x2F, 0x3C, 0xD5, 0xC5, 0x67, 0x3B, 0xBB, 0x64, | ||
| 0xEC, 0xA5, 0x55, 0xCC, 0xFF, 0x6E, 0x6F, 0x02, | ||
| 0xCF, 0x23, 0xBF, 0xFA, 0x74, 0x56, 0x8D, 0xC3 | ||
| }; | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(result_expected)]; | ||
| uECC_vli_modSquare_fast((void *)result_got, (void *)input, curve); | ||
| return _test_compare("uECC_vli_modSquare_fast()", result_got, result_expected, sizeof(result_expected)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. long line |
||
| } | ||
|
|
||
| static bool _test_uECC_vli_modMult_fast(const uECC_Curve curve) | ||
| { | ||
| const alignas(uECC_word_t) uint8_t input1[] = { | ||
| 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4, | ||
| 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77, | ||
| 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8, | ||
| 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t input2[] = { | ||
| 0xC2, 0xF8, 0x5B, 0x35, 0x64, 0x8D, 0xD0, 0x25, | ||
| 0x24, 0xE9, 0xAE, 0xB5, 0x04, 0x30, 0x57, 0x7C, | ||
| 0x66, 0x9A, 0x8D, 0xE5, 0x7E, 0x26, 0x53, 0x78, | ||
| 0x0A, 0xD3, 0xE2, 0xD5, 0xBD, 0x06, 0xA1, 0x11 | ||
| }; | ||
| const alignas(uECC_word_t) uint8_t result_expected[] = { | ||
| 0xF9, 0xFD, 0xB6, 0x5C, 0x1B, 0x4F, 0x85, 0x35, | ||
| 0x5C, 0x0D, 0x14, 0x47, 0x5B, 0x20, 0xD5, 0x9E, | ||
| 0x35, 0x5C, 0x3E, 0xDE, 0xF9, 0x20, 0x37, 0x78, | ||
| 0x34, 0x12, 0xD8, 0xF7, 0x80, 0xEF, 0x6E, 0x59 | ||
| }; | ||
| uint8_t alignas(uECC_word_t) result_got[sizeof(result_expected)]; | ||
| uECC_vli_modMult_fast((void *)result_got, (void *)input1, (void *)input2, curve); | ||
| return _test_compare("uECC_vli_modMult_fast()", result_got, result_expected, sizeof(result_expected)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Long line |
||
| } | ||
|
|
||
| /** | ||
| * @brief Runs internal functions with test vectors to not only see if | ||
| * something broke, but also where | ||
| */ | ||
| static int _unit_tests(uECC_Curve curve) | ||
| { | ||
| int errorc = 0; | ||
| puts("Unit Tests\n" | ||
| "==========\n"); | ||
|
|
||
| if (!_test_uECC_vli_mult()) { | ||
| errorc++; | ||
| } | ||
|
|
||
| if (!_test_uECC_vli_add()) { | ||
| errorc++; | ||
| } | ||
|
|
||
| if (!_test_uECC_vli_sub()) { | ||
| errorc++; | ||
| } | ||
|
|
||
| if (!_test_uECC_vli_mmod()) { | ||
| errorc++; | ||
| } | ||
|
|
||
| if (!_test_uECC_vli_mmod_fast(curve)) { | ||
| errorc++; | ||
| } | ||
|
|
||
| if (!_test_uECC_vli_modSquare_fast(curve)) { | ||
| errorc++; | ||
| } | ||
|
|
||
| if (!_test_uECC_vli_modMult_fast(curve)) { | ||
| errorc++; | ||
| } | ||
|
|
||
| puts(""); | ||
| return errorc; | ||
| } | ||
|
|
||
| int main(void) | ||
| { | ||
| printf("micro-ecc compiled!\n"); | ||
|
|
||
| const struct uECC_Curve_t *curve = uECC_secp256r1(); | ||
| int errorc = 0; | ||
|
|
||
| expect(uECC_curve_private_key_size(curve) <= MAX_CURVE_SIZE); | ||
| expect(uECC_curve_public_key_size(curve) <= MAX_PUBLIC_KEY_SIZE); | ||
|
|
||
| int errorc = _unit_tests(curve); | ||
|
|
||
| puts("End to End Tests\n" | ||
| "================\n"); | ||
| printf("Testing %d random private key pairs and signature without using HWRNG\n", TESTROUNDS); | ||
|
|
||
| for (int i = 0; i < TESTROUNDS; ++i) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Long lines