372 lines
10 KiB
C
372 lines
10 KiB
C
/****************************************************************************
|
|
* 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 <fcntl.h>
|
|
#include <libgen.h>
|
|
#include <nuttx/crypto/se05x.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
/****************************************************************************
|
|
* 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] <secure element device>\n", prg);
|
|
fprintf(f, "Options:\n");
|
|
fprintf(f, " -b <id> (use base address <id>\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;
|
|
}
|