Xiang Xiao b7f05e89ba testing: Move crypto/setest to drivers and open_memstream to libc
follow the dissusion from:
https://github.com/apache/nuttx-apps/pull/2931

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2025-01-26 07:32:53 +01:00

481 lines
12 KiB
C

/****************************************************************************
* apps/testing/drivers/crypto/ecdsa.c
*
* SPDX-License-Identifier: ISC
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <crypto/cryptodev.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define ECC_KEYLEN_MAX 64
#define SECP256R1_KEYLEN 32
typedef enum
{
SYNC = 0,
ASYNC,
}
crypto_mode_t;
typedef struct ecdsa_data_s
{
unsigned char x[ECC_KEYLEN_MAX];
unsigned char y[ECC_KEYLEN_MAX];
unsigned char z[ECC_KEYLEN_MAX];
unsigned char d[ECC_KEYLEN_MAX];
unsigned char r[ECC_KEYLEN_MAX];
unsigned char s[ECC_KEYLEN_MAX];
size_t xlen;
size_t ylen;
size_t zlen;
size_t dlen;
size_t rlen;
size_t slen;
}
ecdsa_data_t;
typedef struct crypto_context_s
{
int fd;
int cryptodev_fd;
}
crypto_context_t;
typedef struct ecdsa_test_s
{
const char *name;
int (*function)(int);
}
ecdsa_test_t;
/****************************************************************************
* Private Data
****************************************************************************/
static unsigned char sha256_message[32] =
{
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
};
/****************************************************************************
* Private Functions
****************************************************************************/
static void show_usage(FAR const char *progname, int exitcode)
{
printf("Usage: %s -a/-s <curve> \n", progname);
printf(" [-s] selects synchronous mode.\n");
printf(" [-a] selects asynchronous mode.\n");
printf(" [curve] selects the support curve.\n"
" support: SECP256R1\n");
exit(exitcode);
}
static int ecdsa_data_init(FAR ecdsa_data_t *data,
size_t xlen, size_t ylen, size_t zlen,
size_t dlen, size_t rlen, size_t slen)
{
memset(data, 0, sizeof(ecdsa_data_t));
data->xlen = xlen;
data->ylen = ylen;
data->zlen = zlen;
data->dlen = dlen;
data->rlen = rlen;
data->slen = slen;
return 0;
}
static void crypto_free(FAR crypto_context_t *ctx)
{
if (ctx->cryptodev_fd != 0)
{
close(ctx->cryptodev_fd);
ctx->cryptodev_fd = 0;
}
if (ctx->fd != 0)
{
close(ctx->fd);
ctx->fd = 0;
}
}
static int crypto_init(FAR crypto_context_t *ctx)
{
memset(ctx, 0, sizeof(crypto_context_t));
if ((ctx->fd = open("/dev/crypto", O_RDWR, 0)) < 0)
{
perror("CRIOGET");
crypto_free(ctx);
return 1;
}
if (ioctl(ctx->fd, CRIOGET, &ctx->cryptodev_fd) == -1)
{
perror("CRIOGET");
crypto_free(ctx);
return 1;
}
return 0;
}
static int ecdsa_sign(int op, FAR struct pollfd *fds,
FAR crypto_context_t *ctx, FAR ecdsa_data_t *data,
FAR const unsigned char *buf, size_t buflen)
{
struct crypt_kop cryptk;
memset(&cryptk, 0, sizeof(cryptk));
cryptk.crk_op = op;
cryptk.crk_iparams = 2;
cryptk.crk_oparams = 2;
cryptk.crk_param[0].crp_p = (caddr_t)data->d;
cryptk.crk_param[0].crp_nbits = data->dlen * 8;
cryptk.crk_param[1].crp_p = (caddr_t)buf;
cryptk.crk_param[1].crp_nbits = buflen * 8;
cryptk.crk_param[2].crp_p = (caddr_t)data->r;
cryptk.crk_param[2].crp_nbits = data->rlen * 8;
cryptk.crk_param[3].crp_p = (caddr_t)data->s;
cryptk.crk_param[3].crp_nbits = data->slen * 8;
if (fds != NULL)
{
cryptk.crk_flags |= CRYPTO_F_CBIMM;
}
if (ioctl(ctx->cryptodev_fd, CIOCKEY, &cryptk) == -1)
{
perror("CIOCKEY");
return -1;
}
if (fds != NULL)
{
memset(fds, 0, sizeof(struct pollfd));
fds->fd = ctx->cryptodev_fd;
fds->events = POLLIN;
if (poll(fds, 1, -1) < 0)
{
perror("poll");
return -1;
}
if (fds->revents & POLLIN)
{
if (ioctl(ctx->cryptodev_fd, CIOCKEYRET, &cryptk) == -1)
{
perror("CIOCKEYRET");
return -1;
}
}
else
{
perror("poll back");
return -1;
}
}
return cryptk.crk_status;
}
static int ecdsa_verify(int op, FAR struct pollfd *fds,
FAR crypto_context_t *ctx, FAR ecdsa_data_t *data,
FAR const unsigned char *buf, size_t buflen)
{
struct crypt_kop cryptk;
memset(&cryptk, 0, sizeof(cryptk));
cryptk.crk_op = op;
cryptk.crk_iparams = 6;
cryptk.crk_oparams = 0;
cryptk.crk_param[0].crp_p = (caddr_t)data->x;
cryptk.crk_param[0].crp_nbits = data->xlen * 8;
cryptk.crk_param[1].crp_p = (caddr_t)data->y;
cryptk.crk_param[1].crp_nbits = data->ylen * 8;
cryptk.crk_param[2].crp_p = (caddr_t)data->z;
cryptk.crk_param[2].crp_nbits = data->zlen * 8;
cryptk.crk_param[3].crp_p = (caddr_t)data->r;
cryptk.crk_param[3].crp_nbits = data->rlen * 8;
cryptk.crk_param[4].crp_p = (caddr_t)data->s;
cryptk.crk_param[4].crp_nbits = data->slen * 8;
cryptk.crk_param[5].crp_p = (caddr_t)buf;
cryptk.crk_param[5].crp_nbits = buflen * 8;
if (fds != NULL)
{
cryptk.crk_flags |= CRYPTO_F_CBIMM;
}
if (ioctl(ctx->cryptodev_fd, CIOCKEY, &cryptk) == -1)
{
perror("CIOCKEY");
return -1;
}
if (fds != NULL)
{
memset(fds, 0, sizeof(struct pollfd));
fds->fd = ctx->cryptodev_fd;
fds->events = POLLIN;
if (poll(fds, 1, -1) < 0)
{
perror("poll");
return -1;
}
if (fds->revents & POLLIN)
{
if (ioctl(ctx->cryptodev_fd, CIOCKEYRET, &cryptk) == -1)
{
perror("CIOCKEYRET");
return -1;
}
}
else
{
perror("poll back");
return -1;
}
}
return cryptk.crk_status;
}
static int ecdsa_genkey(int op, FAR struct pollfd *fds,
FAR crypto_context_t *ctx, FAR ecdsa_data_t *data)
{
struct crypt_kop cryptk;
memset(&cryptk, 0, sizeof(cryptk));
cryptk.crk_op = op;
cryptk.crk_iparams = 0;
cryptk.crk_oparams = 4;
cryptk.crk_param[0].crp_p = (caddr_t)data->d;
cryptk.crk_param[0].crp_nbits = data->dlen * 8;
cryptk.crk_param[1].crp_p = (caddr_t)data->x;
cryptk.crk_param[1].crp_nbits = data->xlen * 8;
cryptk.crk_param[2].crp_p = (caddr_t)data->y;
cryptk.crk_param[2].crp_nbits = data->ylen * 8;
cryptk.crk_param[3].crp_p = (caddr_t)data->z;
cryptk.crk_param[3].crp_nbits = data->zlen * 8;
if (fds != NULL)
{
cryptk.crk_flags |= CRYPTO_F_CBIMM;
}
if (ioctl(ctx->cryptodev_fd, CIOCKEY, &cryptk) == -1)
{
perror("CIOCKEY");
return -1;
}
if (fds != NULL)
{
memset(fds, 0, sizeof(struct pollfd));
fds->fd = ctx->cryptodev_fd;
fds->events = POLLIN;
if (poll(fds, 1, -1) < 0)
{
perror("poll");
return -1;
}
if (fds->revents & POLLIN)
{
if (ioctl(ctx->cryptodev_fd, CIOCKEYRET, &cryptk) == -1)
{
perror("CIOCKEYRET");
return -1;
}
}
else
{
perror("poll back");
return -1;
}
}
return cryptk.crk_status;
}
/* Test curve SECP256R1 */
static int test_p256(int mode)
{
crypto_context_t ctx;
ecdsa_data_t data;
struct pollfd fds;
int ret = 0;
int len = SECP256R1_KEYLEN;
ret = crypto_init(&ctx);
if (ret != 0)
{
goto free;
}
ret = ecdsa_data_init(&data, len, len, len, len, len, len);
if (ret != 0)
{
goto free;
}
ret = ecdsa_genkey(CRK_ECDSA_SECP256R1_GENKEY, mode == SYNC ? NULL : &fds,
&ctx, &data);
if (ret != 0)
{
printf("p256 generate key %s failed\n",
mode == SYNC ? "sync" : "async");
goto free;
}
else
{
printf("p256 generate key %s success\n",
mode == SYNC ? "sync" : "async");
}
ret = ecdsa_sign(CRK_ECDSA_SECP256R1_SIGN, mode == SYNC ? NULL : &fds,
&ctx, &data, sha256_message, len);
if (ret != 0)
{
printf("p256 sign %s failed\n", mode == SYNC ? "sync" : "async");
goto free;
}
else
{
printf("p256 sign %s success\n", mode == SYNC ? "sync" : "async");
}
ret = ecdsa_verify(CRK_ECDSA_SECP256R1_VERIFY, mode == SYNC ? NULL : &fds,
&ctx, &data, sha256_message, len);
if (ret != 0)
{
printf("p256 verify %s failed\n", mode == SYNC ? "sync" : "async");
goto free;
}
else
{
printf("p256 verify %s success\n", mode == SYNC ? "sync" : "async");
}
free:
crypto_free(&ctx);
return ret;
}
static const ecdsa_test_t g_ecdsa_test[] =
{
{
"SECP256R1", test_p256,
},
/* end test case */
{
NULL, NULL,
},
};
/****************************************************************************
* Public Functions
****************************************************************************/
int main(int argc, FAR char *argv[])
{
char **argp;
crypto_mode_t mode = SYNC;
const ecdsa_test_t *test;
for (argp = argv + (argc >= 1 ? 1 : argc); *argp != NULL; ++argp)
{
if (strcmp(*argp, "-s") == 0)
{
mode = SYNC;
}
else if (strcmp(*argp, "-a") == 0)
{
mode = ASYNC;
}
else if (strcmp(*argp, "-h") == 0)
{
show_usage(argv[0], EXIT_FAILURE);
}
else
{
break;
}
}
if (*argp != NULL)
{
for (; *argp != NULL; argp++)
{
for (test = g_ecdsa_test; test->name != NULL; test++)
{
if (strcmp(*argp, test->name) == 0)
{
if (test->function(mode) != 0)
{
printf("Test %s case failed\n\n", *argp);
}
else
{
printf("Test %s case success\n\n", *argp);
}
break;
}
}
}
}
else
{
for (test = g_ecdsa_test; test->name != NULL; test++)
{
if (test->function(mode) != 0)
{
printf("Test %s case failed\n\n", test->name);
break;
}
else
{
printf("Test %s case success\n\n", test->name);
}
}
}
return 0;
}