Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions tests/pkg/micro-ecc/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include ../Makefile.pkg_common

USEMODULE += hashes
USEMODULE += od
USEPKG += micro-ecc

include $(RIOTBASE)/Makefile.include
Expand All @@ -9,3 +10,6 @@ include $(RIOTBASE)/Makefile.include
ifneq (,$(filter avr8_common,$(USEMODULE)))
CFLAGS += -DTHREAD_STACKSIZE_MAIN=THREAD_STACKSIZE_LARGE
endif

# Access internal API for unit tests
CFLAGS += -DuECC_ENABLE_VLI_API=1
262 changes: 260 additions & 2 deletions tests/pkg/micro-ecc/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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));
Comment on lines +163 to +164
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long lines

}

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
Copy link
Member

Choose a reason for hiding this comment

The 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));
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link
Member

Choose a reason for hiding this comment

The 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));
Copy link
Member

Choose a reason for hiding this comment

The 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));
Copy link
Member

Choose a reason for hiding this comment

The 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));
Copy link
Member

Choose a reason for hiding this comment

The 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) {
Expand Down