The test ecdsa was done when ecdsa was only supported by hardware. So it wasn't possible to test ecdsa on sandbox, and there is a test to check that ecdsa is not supported on sandbox. Now, there is a software implementation of ecdsa. So we add a test to verify that ecdsa_verify may be used on sandbox.
Signed-off-by: Philippe Reynes <[email protected]> --- v2: - initial version v3: - no change v4: - add a test that use ecdsa_verify v5: - change secp256r1 to ecdsa256 - check that checksum and crypto are not null v6: - update commit message - remove fdt_strerror in macro CHECK - return ENOMEM when malloc fails - add a define FDT_MAX_SIZE to avoid hardcoded value v7: - change uint8_t to u8 - set required_keynode to -1 test/dm/ecdsa.c | 109 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 10 deletions(-) diff --git a/test/dm/ecdsa.c b/test/dm/ecdsa.c index d7eac7115f7..df41a4f7c9f 100644 --- a/test/dm/ecdsa.c +++ b/test/dm/ecdsa.c @@ -3,36 +3,125 @@ #include <crypto/ecdsa-uclass.h> #include <dm.h> #include <dm/test.h> +#include <malloc.h> #include <test/ut.h> #include <u-boot/ecdsa.h> +#define FDT_MAX_SIZE 512 + +#define CHECK(op) ({ \ + int err = op; \ + if (err < 0) { \ + printf("%s: function %s returns an error (%d)\n", \ + __func__, #op, err); \ + return err; \ + } \ + \ + err; \ + }) + +static int set_fdt_ecdsa_point(char *fdt, char *name, const char *data, size_t len) +{ + char *value = NULL; + int ret = 0; + + if (!fdt || !name || !data) { + ret = -EINVAL; + goto out; + } + + value = malloc(len / 2); + if (!value) { + ret = -ENOMEM; + goto out; + } + + ret = hex2bin(value, data, len / 2); + if (ret) + goto out; + + ret = fdt_property(fdt, name, value, len / 2); + if (ret) + goto out; + + out: + free(value); + return ret; +} + +static int create_fdt_with_ecdsa_key(char *fdt, size_t size, + const char *name, const char *curve, + const char *x, const char *y) +{ + CHECK(fdt_create(fdt, size)); + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_begin_node(fdt, "signature")); + CHECK(fdt_begin_node(fdt, name)); + CHECK(fdt_property_string(fdt, "algo", "sha256,ecdsa256")); + CHECK(set_fdt_ecdsa_point(fdt, "ecdsa,y-point", y, strlen(y))); + CHECK(set_fdt_ecdsa_point(fdt, "ecdsa,x-point", x, strlen(x))); + CHECK(fdt_property_string(fdt, "ecdsa,curve", curve)); + CHECK(fdt_property_string(fdt, "key-name-hint", name)); + CHECK(fdt_end_node(fdt)); /* name */ + CHECK(fdt_end_node(fdt)); /* "signature" */ + CHECK(fdt_end_node(fdt)); /* "" */ + CHECK(fdt_finish(fdt)); + CHECK(fdt_pack(fdt)); + + return 0; +} + /* * Basic test of the ECDSA uclass and ecdsa_verify() * - * ECDSA implementations in u-boot are hardware-dependent. Until we have a - * software implementation that can be compiled into the sandbox, all we can - * test is the uclass support. + * ECDSA software implementation is tested in another test, + * so we only check that the class UCLASS_ECDSA may be used. * - * The uclass_get() test is redundant since ecdsa_verify() would also fail. We - * run both functions in order to isolate the cause more clearly. i.e. is - * ecdsa_verify() failing because the UCLASS is absent/broken? + * The data used in this test come from RFC6979 */ static int dm_test_ecdsa_verify(struct unit_test_state *uts) { struct uclass *ucp; + const char *full_name = "sha256,ecdsa256"; + const char *name = "key-ecdsa-256"; + const char *curve = "prime256v1"; + const char *x = "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + const char *y = "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + const char *r = "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716"; + const char *s = "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"; + u8 sig[64]; + char fdt[FDT_MAX_SIZE]; - struct checksum_algo algo = { - .checksum_len = 256, + struct image_region region[] = { + { + .data = "sample", + .size = strlen("sample"), + }, }; struct image_sign_info info = { - .checksum = &algo, + .checksum = image_get_checksum_algo(full_name), + .crypto = image_get_crypto_algo(full_name), + .required_keynode = -1, + .fdt_blob = fdt, }; + ut_assertnonnull(info.checksum); + ut_assertnonnull(info.crypto); + + /* create a fdt with the public key */ + ut_asserteq(0, create_fdt_with_ecdsa_key(fdt, sizeof(fdt), name, curve, x, y)); + + /* prepare the signature */ + ut_asserteq(0, hex2bin(sig + 0, r, strlen(r) / 2)); + ut_asserteq(0, hex2bin(sig + 32, s, strlen(s) / 2)); + ut_assertok(uclass_get(UCLASS_ECDSA, &ucp)); ut_assertnonnull(ucp); - ut_asserteq(-ENODEV, ecdsa_verify(&info, NULL, 0, NULL, 0)); + ut_asserteq(0, ecdsa_verify(&info, region, 1, sig, sizeof(sig))); return 0; } + DM_TEST(dm_test_ecdsa_verify, UTF_SCAN_PDATA | UTF_SCAN_FDT); -- 2.43.0

