/**************************************************************************** * apps/testing/setest/setest.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /* Copyright 2023 NXP */ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define DEFAULT_SETTINGS \ { \ .se05x_dev = default_se05x_device, .skip_process = FALSE, \ .base_id = 0x230000 \ } /**************************************************************************** * Private Types ****************************************************************************/ struct settings_t { FAR char *se05x_dev; bool skip_process; uint32_t base_id; }; /**************************************************************************** * Private Data ****************************************************************************/ static char default_se05x_device[] = "/dev/se05x"; /**************************************************************************** * Private Functions ****************************************************************************/ static void print_usage(FAR FILE *f, char *prg) { fprintf(f, "%s - Secure Element Test\n", prg); fprintf(f, "\nUsage: %s [options] \n", prg); fprintf(f, "Options:\n"); fprintf(f, " -b (use base address \n"); fprintf(f, " default = 0x230000)\n"); } static int parse_arguments(int argc, FAR char *argv[], FAR struct settings_t *settings) { int result = 0; int opt; FAR char *prg = basename(argv[0]); while (((opt = getopt(argc, argv, "b:h")) != -1) && (result == 0)) { switch (opt) { case 'b': settings->base_id = (uint32_t)strtoul(optarg, NULL, 0); break; case 'h': print_usage(stdout, prg); settings->skip_process = TRUE; break; default: print_usage(stderr, prg); result = -EINVAL; break; } } if ((result == 0) && (!settings->skip_process)) { settings->se05x_dev = default_se05x_device; /* if device is specified as positional argument */ if (optind != argc) { settings->se05x_dev = argv[optind]; } } return result; } static uint32_t get_se05x_id(FAR struct settings_t *settings, uint32_t id) { return settings->base_id + id; } static void print_result(bool success) { if (success) { puts(" SUCCESS"); } else { puts(" FAIL"); } } static int invert_result(int result) { return result != 0 ? 0 : -1; } static int run_tests(int fd, FAR struct settings_t *settings) { int result = 0; puts("Setup"); for (uint32_t id = get_se05x_id(settings, 1); id < get_se05x_id(settings, 5); id++) { /* result is neglected because already empty entries result with * errors */ (void)ioctl(fd, SEIOC_DELETE_KEY, id); } puts("Generate 3 keypairs"); for (uint32_t id = get_se05x_id(settings, 1); (id < get_se05x_id(settings, 4)) && (result == 0); id++) { struct se05x_generate_keypair_s args = { .id = id, .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256 }; result = ioctl(fd, SEIOC_GENERATE_KEYPAIR, &args); } print_result(result == 0); uint8_t public_key[300]; size_t public_key_size; if (result == 0) { puts("Read from pub #1"); struct se05x_key_transmission_s args = { .entry = {.id = get_se05x_id(settings, 1), .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256}, .content = {.buffer = public_key, .buffer_size = sizeof(public_key)} }; result = ioctl(fd, SEIOC_GET_KEY, &args); public_key_size = args.content.buffer_content_size; print_result(result == 0); } if (result == 0) { puts("Write to pub #4"); struct se05x_key_transmission_s args = { .entry = {.id = get_se05x_id(settings, 4), .cipher = SE05X_ASYM_CIPHER_EC_NIST_P_256}, .content = {.buffer = public_key, .buffer_size = public_key_size, .buffer_content_size = public_key_size} }; result = ioctl(fd, SEIOC_SET_KEY, &args); print_result(result == 0); } uint8_t hash[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; uint8_t signature[300]; size_t signature_content_size; if (result == 0) { puts("Create signature with priv #1"); struct se05x_signature_s args = { .key_id = get_se05x_id(settings, 1), .algorithm = SE05X_ALGORITHM_SHA256, .tbs = {.buffer = hash, .buffer_size = sizeof(hash), .buffer_content_size = sizeof(hash)}, .signature = {.buffer = signature, .buffer_size = sizeof(signature)}, }; result = ioctl(fd, SEIOC_CREATE_SIGNATURE, &args); signature_content_size = args.signature.buffer_content_size; print_result(result == 0); } if (result == 0) { puts("Verify signature with pub #4"); struct se05x_signature_s args = { .key_id = get_se05x_id(settings, 4), .algorithm = SE05X_ALGORITHM_SHA256, .tbs = {.buffer = hash, .buffer_size = sizeof(hash), .buffer_content_size = sizeof(hash)}, .signature = {.buffer = signature, .buffer_content_size = signature_content_size}, }; result = ioctl(fd, SEIOC_VERIFY_SIGNATURE, &args); print_result(result == 0); } if (result == 0) { puts("Verification of signature with pub #2 should be dissapproved"); struct se05x_signature_s args = { .key_id = get_se05x_id(settings, 2), .algorithm = SE05X_ALGORITHM_SHA256, .tbs = {.buffer = hash, .buffer_size = sizeof(hash)}, .signature = {.buffer = signature, .buffer_content_size = signature_content_size}, }; result = invert_result(ioctl(fd, SEIOC_VERIFY_SIGNATURE, &args)); print_result(result == 0); } uint8_t symm_key_a[32]; if (result == 0) { puts("Derive symm key #a from priv #1 and pub #2"); struct se05x_derive_key_s args = { .private_key_id = get_se05x_id(settings, 1), .public_key_id = get_se05x_id(settings, 2), .content = {.buffer = symm_key_a, .buffer_size = sizeof(symm_key_a)}, }; result = ioctl(fd, SEIOC_DERIVE_SYMM_KEY, &args); print_result(result == 0); } uint8_t symm_key_b[32]; if (result == 0) { puts("Derive symm key #b from priv #2 and pub #1"); struct se05x_derive_key_s args = { .private_key_id = get_se05x_id(settings, 2), .public_key_id = get_se05x_id(settings, 1), .content = {.buffer = symm_key_b, .buffer_size = sizeof(symm_key_b)}, }; result = ioctl(fd, SEIOC_DERIVE_SYMM_KEY, &args); print_result(result == 0); } uint8_t symm_key_c[32]; if (result == 0) { puts("Derive symm key #c from priv #1 and pub #3"); struct se05x_derive_key_s args = { .private_key_id = get_se05x_id(settings, 1), .public_key_id = get_se05x_id(settings, 3), .content = {.buffer = symm_key_c, .buffer_size = sizeof(symm_key_c)}, }; result = ioctl(fd, SEIOC_DERIVE_SYMM_KEY, &args); print_result(result == 0); } if (result == 0) { puts("Symm key #a and #b should be equal"); result = memcmp(symm_key_a, symm_key_b, sizeof(symm_key_a)); print_result(result == 0); } if (result == 0) { puts("Symm key #a and #c should be different"); result = invert_result(memcmp(symm_key_a, symm_key_c, sizeof(symm_key_a))); print_result(result == 0); } if (result == 0) { puts("All tests succeeded!\n"); } return result; } /**************************************************************************** * Public Functions ****************************************************************************/ int main(int argc, FAR char *argv[]) { struct settings_t settings = DEFAULT_SETTINGS; int result = parse_arguments(argc, argv, &settings); int fd; if ((result == 0) && (!settings.skip_process)) { fd = open(settings.se05x_dev, O_RDONLY); if (fd == -1) { result = -ENODEV; } else { run_tests(fd, &settings); close(fd); } } if (result != 0) { fprintf(stderr, "err %i: %s\n", -result, strerror(-result)); } return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }