testing/crypto: add rsa testcase
Signed-off-by: makejian <makejian@xiaomi.com>
This commit is contained in:
parent
b1f2e63a6b
commit
7cd9919a46
@ -159,4 +159,18 @@ if(CONFIG_TESTING_CRYPTO)
|
||||
dhm.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_TESTING_CRYPTO_RSA)
|
||||
nuttx_add_application(
|
||||
NAME
|
||||
rsa
|
||||
PRIORITY
|
||||
${CONFIG_TESTING_CRYPTO_PRIORITY}
|
||||
STACKSIZE
|
||||
${CONFIG_TESTING_CRYPTO_STACKSIZE}
|
||||
MODULE
|
||||
${CONFIG_TESTING_CRYPTO}
|
||||
SRCS
|
||||
rsa.c)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
@ -46,6 +46,10 @@ config TESTING_CRYPTO_ECDH
|
||||
bool "ecdh crypto test"
|
||||
default n
|
||||
|
||||
config TESTING_CRYPTO_RSA
|
||||
bool "rsa crypto test"
|
||||
default n
|
||||
|
||||
config TESTING_CRYPTO_PRIORITY
|
||||
int "crypto test task priority"
|
||||
default 100
|
||||
|
@ -71,6 +71,11 @@ PROGNAME += dhm
|
||||
MAINSRC += dhm.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TESTING_CRYPTO_RSA),y)
|
||||
PROGNAME += rsa
|
||||
MAINSRC += rsa.c
|
||||
endif
|
||||
|
||||
PRIORITY = $(CONFIG_TESTING_CRYPTO_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_TESTING_CRYPTO_STACKSIZE)
|
||||
MODULE = $(CONFIG_TESTING_CRYPTO)
|
||||
|
402
testing/crypto/rsa.c
Normal file
402
testing/crypto/rsa.c
Normal file
@ -0,0 +1,402 @@
|
||||
/****************************************************************************
|
||||
* apps/testing/crypto/rsa.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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/endian.h>
|
||||
#include <crypto/cryptodev.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define MOD_LEN 128
|
||||
#define PRIVATE_KEYLEN 128
|
||||
#define PUBLIC_KEYLEN 5
|
||||
#define PLAIN_LEN 24
|
||||
#define PADDING_LEN (MOD_LEN - PLAIN_LEN)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef struct rsa_data_s
|
||||
{
|
||||
unsigned char e[PUBLIC_KEYLEN];
|
||||
unsigned char d[PRIVATE_KEYLEN];
|
||||
unsigned char n[MOD_LEN];
|
||||
}
|
||||
rsa_data_t;
|
||||
|
||||
typedef struct crypto_context_s
|
||||
{
|
||||
int fd;
|
||||
int cryptodev_fd;
|
||||
}
|
||||
crypto_context_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Example RSA-1024 keypair, for test purposes */
|
||||
|
||||
static const unsigned char g_rsa_n[] =
|
||||
"9292758453063D803DD603D5E777D788"
|
||||
"8ED1D5BF35786190FA2F23EBC0848AEA"
|
||||
"DDA92CA6C3D80B32C4D109BE0F36D6AE"
|
||||
"7130B9CED7ACDF54CFC7555AC14EEBAB"
|
||||
"93A89813FBF3C4F8066D2D800F7C38A8"
|
||||
"1AE31942917403FF4946B0A83D3D3E05"
|
||||
"EE57C6F5F5606FB5D4BC6CD34EE0801A"
|
||||
"5E94BB77B07507233A0BC7BAC8F90F79";
|
||||
|
||||
static const unsigned char g_rsa_e[] = "10001";
|
||||
|
||||
static const unsigned char g_rsa_d[] =
|
||||
"24BF6185468786FDD303083D25E64EFC"
|
||||
"66CA472BC44D253102F8B4A9D3BFA750"
|
||||
"91386C0077937FE33FA3252D28855837"
|
||||
"AE1B484A8A9A45F7EE8C0C634F99E8CD"
|
||||
"DF79C5CE07EE72C7F123142198164234"
|
||||
"CABB724CF78B8173B9F880FC86322407"
|
||||
"AF1FEDFDDE2BEB674CA15F3E81A1521E"
|
||||
"071513A1E85B5DFA031F21ECAE91A34D";
|
||||
|
||||
static const unsigned char g_message[] =
|
||||
"\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF"
|
||||
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD";
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void pkcs1_v15_padding(FAR unsigned char *padding,
|
||||
size_t pad_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* this padding is only for rsa sign */
|
||||
|
||||
*padding++ = 0;
|
||||
*padding++ = 0x02;
|
||||
for (i = 0; i < pad_len - 3; i++)
|
||||
{
|
||||
*padding++ = rand() % 256;
|
||||
}
|
||||
|
||||
*padding++ = 0;
|
||||
}
|
||||
|
||||
static void rsa_be32toh(FAR uint8_t *dst, size_t len, FAR const uint8_t *src)
|
||||
{
|
||||
int i;
|
||||
size_t rlen = len / 4;
|
||||
uint32_t *dst32 = (uint32_t *)dst;
|
||||
uint32_t *src32 = (uint32_t *)src;
|
||||
|
||||
for (i = 0; i < rlen; i++)
|
||||
{
|
||||
dst32[i] = be32toh(src32[rlen - i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void mpi_get_digit(FAR uint8_t *d, char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
*d = c - '0';
|
||||
}
|
||||
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
*d = c - 'A' + 10;
|
||||
}
|
||||
|
||||
if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
*d = c - 'a' + 10;
|
||||
}
|
||||
}
|
||||
|
||||
static void mpi_from_string(FAR unsigned char *buf,
|
||||
FAR const unsigned char *s,
|
||||
size_t slen)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
uint8_t d = 0;
|
||||
|
||||
for (i = slen, j = 0; i > 0; i--, j++)
|
||||
{
|
||||
mpi_get_digit(&d, s[i - 1]);
|
||||
buf[j / 2] |= d << ((j % 2) << 2);
|
||||
}
|
||||
}
|
||||
|
||||
static int rsa_data_init(FAR rsa_data_t *data,
|
||||
FAR const unsigned char *e, size_t elen,
|
||||
FAR const unsigned char *d, size_t dlen,
|
||||
FAR const unsigned char *n, size_t nlen)
|
||||
{
|
||||
memset(data, 0, sizeof(rsa_data_t));
|
||||
mpi_from_string(data->e, e, elen);
|
||||
mpi_from_string(data->d, d, dlen);
|
||||
mpi_from_string(data->n, n, nlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cryptodev_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 cryptodev_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");
|
||||
cryptodev_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ioctl(ctx->fd, CRIOGET, &ctx->cryptodev_fd) == -1)
|
||||
{
|
||||
perror("CRIOGET");
|
||||
cryptodev_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cryptodev_rsa_calc(FAR crypto_context_t *ctx,
|
||||
FAR rsa_data_t *data,
|
||||
FAR const unsigned char *input, size_t ilen,
|
||||
FAR const unsigned char *output, size_t olen,
|
||||
bool is_priv)
|
||||
{
|
||||
struct crypt_kop cryptk;
|
||||
|
||||
memset(&cryptk, 0, sizeof(struct crypt_kop));
|
||||
cryptk.crk_op = CRK_MOD_EXP;
|
||||
cryptk.crk_iparams = 3;
|
||||
cryptk.crk_oparams = 1;
|
||||
cryptk.crk_param[0].crp_p = (caddr_t)input;
|
||||
cryptk.crk_param[0].crp_nbits = ilen * 8;
|
||||
if (is_priv)
|
||||
{
|
||||
cryptk.crk_param[1].crp_p = (caddr_t)data->d;
|
||||
cryptk.crk_param[1].crp_nbits = sizeof(data->d) * 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
cryptk.crk_param[1].crp_p = (caddr_t)data->e;
|
||||
cryptk.crk_param[1].crp_nbits = sizeof(data->e) * 8;
|
||||
}
|
||||
|
||||
cryptk.crk_param[2].crp_p = (caddr_t)data->n;
|
||||
cryptk.crk_param[2].crp_nbits = sizeof(data->n) * 8;
|
||||
cryptk.crk_param[3].crp_p = (caddr_t)output;
|
||||
cryptk.crk_param[3].crp_nbits = olen * 8;
|
||||
|
||||
if (ioctl(ctx->cryptodev_fd, CIOCKEY, &cryptk) == -1)
|
||||
{
|
||||
perror("rsa calculate failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cryptk.crk_status;
|
||||
}
|
||||
|
||||
static int cryptodev_rsa_verify(
|
||||
FAR crypto_context_t *ctx, FAR rsa_data_t *data,
|
||||
FAR const unsigned char *sig, size_t sig_len,
|
||||
FAR const unsigned char *hash, size_t hash_len,
|
||||
FAR const unsigned char *padding, size_t pad_len)
|
||||
{
|
||||
struct crypt_kop cryptk;
|
||||
|
||||
memset(&cryptk, 0, sizeof(struct crypt_kop));
|
||||
cryptk.crk_op = CRK_RSA_PKCS15_VERIFY;
|
||||
cryptk.crk_iparams = 5;
|
||||
cryptk.crk_oparams = 0;
|
||||
|
||||
cryptk.crk_param[0].crp_p = (caddr_t)data->e;
|
||||
cryptk.crk_param[0].crp_nbits = sizeof(data->e) * 8;
|
||||
cryptk.crk_param[1].crp_p = (caddr_t)data->n;
|
||||
cryptk.crk_param[1].crp_nbits = sizeof(data->n) * 8;
|
||||
cryptk.crk_param[2].crp_p = (caddr_t)sig;
|
||||
cryptk.crk_param[2].crp_nbits = sig_len * 8;
|
||||
cryptk.crk_param[3].crp_p = (caddr_t)hash;
|
||||
cryptk.crk_param[3].crp_nbits = hash_len * 8;
|
||||
cryptk.crk_param[4].crp_p = (caddr_t)padding;
|
||||
cryptk.crk_param[4].crp_nbits = pad_len * 8;
|
||||
|
||||
if (ioctl(ctx->cryptodev_fd, CIOCKEY, &cryptk) == -1)
|
||||
{
|
||||
perror("CIOCKEY");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cryptk.crk_status;
|
||||
}
|
||||
|
||||
static int rsa_test(void)
|
||||
{
|
||||
crypto_context_t ctx;
|
||||
rsa_data_t rsa_data;
|
||||
unsigned char cipher[MOD_LEN];
|
||||
unsigned char plain[PLAIN_LEN];
|
||||
unsigned char data[MOD_LEN];
|
||||
unsigned char padding[PADDING_LEN];
|
||||
unsigned char sig[MOD_LEN];
|
||||
unsigned char data_he[MOD_LEN];
|
||||
unsigned char pad_he[PADDING_LEN];
|
||||
unsigned char hash_he[MOD_LEN];
|
||||
int ret = 0;
|
||||
|
||||
ret = cryptodev_init(&ctx);
|
||||
if (ret != 0)
|
||||
{
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = rsa_data_init(&rsa_data, g_rsa_e, sizeof(g_rsa_e) - 1,
|
||||
g_rsa_d, sizeof(g_rsa_d) - 1,
|
||||
g_rsa_n, sizeof(g_rsa_n) - 1);
|
||||
if (ret != 0)
|
||||
{
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* test 1: encrypt with private key and decrypt with public key */
|
||||
|
||||
memset(cipher, 0, MOD_LEN);
|
||||
memset(plain, 0, PLAIN_LEN);
|
||||
|
||||
/* encrypt with private key: g_message ^ ctx.data.d % n = cipher */
|
||||
|
||||
ret = cryptodev_rsa_calc(&ctx, &rsa_data, g_message, PLAIN_LEN,
|
||||
cipher, MOD_LEN, TRUE);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("rsa encrypt with private key failed\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* dencrypt with public key: cipher ^ ctx.data.e % n = plain */
|
||||
|
||||
ret = cryptodev_rsa_calc(&ctx, &rsa_data, cipher, MOD_LEN, plain,
|
||||
PLAIN_LEN, FALSE);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("rsa decrypt with pulic key failed\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
ret = memcmp(g_message, plain, PLAIN_LEN);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("rsa test case 1 failed\n");
|
||||
goto free;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rsa test case 1 success\n");
|
||||
}
|
||||
|
||||
/* test 2: rsa sign and verify */
|
||||
|
||||
memset(data, 0, MOD_LEN);
|
||||
memset(padding, 0, PADDING_LEN);
|
||||
memset(sig, 0, MOD_LEN);
|
||||
|
||||
/* pkcs15 v1 padding for sign: 0x00 0x02 (... random) 0x00 */
|
||||
|
||||
pkcs1_v15_padding(padding, PADDING_LEN);
|
||||
memcpy(data, padding, PADDING_LEN);
|
||||
memcpy(data + PADDING_LEN, g_message, PLAIN_LEN);
|
||||
|
||||
rsa_be32toh(data_he, MOD_LEN, data);
|
||||
rsa_be32toh(pad_he, PADDING_LEN, padding);
|
||||
rsa_be32toh(hash_he, PLAIN_LEN, g_message);
|
||||
|
||||
/* sign with private key: (hash + padding) ^ d % n = sig */
|
||||
|
||||
ret = cryptodev_rsa_calc(&ctx, &rsa_data, data_he, MOD_LEN, sig,
|
||||
MOD_LEN, TRUE);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("rsa sign failed\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
/* verify with public key: sig ^ e % n = (hash + padding) */
|
||||
|
||||
ret = cryptodev_rsa_verify(&ctx, &rsa_data, sig, MOD_LEN, hash_he,
|
||||
PLAIN_LEN, pad_he, PADDING_LEN);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("rsa verify failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rsa test case 2 success\n");
|
||||
}
|
||||
|
||||
free:
|
||||
cryptodev_free(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (rsa_test() == 0)
|
||||
{
|
||||
printf("rsa test success\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rsa test failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user