mirror of
https://github.com/apache/nuttx-apps.git
synced 2025-07-08 04:41:13 +08:00

follow the dissusion from: https://github.com/apache/nuttx-apps/pull/2931 Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
481 lines
12 KiB
C
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;
|
|
}
|