makejian 8545512dd7 testing/crypto: add ECDSA P256 testing case for asynchronous call
1. Add asynchronous call test into ecdsa test case.
2. Add command line parameters to facilitate subsequent expansion.
Now can test synchronous call through 'ecdsa -s SECP256R1' and test asynchronous call through 'ecdsa -a SECP256R1'

Signed-off-by: makejian <makejian@xiaomi.com>
2024-09-28 10:46:53 +08:00

479 lines
12 KiB
C

/****************************************************************************
* apps/testing/crypto/ecdsa.c
*
* 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;
}