testing/crypto: Add pbkdf2 test app

This adds support for testing PBKDF2 implementation. Test
vectors for SHA1 are taken from RFC6070. SHA256 vectors
were extrapolated using an online PBKDF2 generator which
was checked against RFC6070.

Signed-off-by: Vlad Pruteanu <pruteanuvlad1611@yahoo.com>
This commit is contained in:
Vlad Pruteanu 2026-03-26 00:12:49 +02:00 committed by Xiang Xiao
parent e564816e1d
commit cd2b0c0e87
4 changed files with 301 additions and 0 deletions

View file

@ -175,4 +175,18 @@ if(CONFIG_TESTING_CRYPTO)
rsa.c)
endif()
if(CONFIG_TESTING_CRYPTO_PBKDF2)
nuttx_add_application(
NAME
pbkdf2
PRIORITY
${CONFIG_TESTING_CRYPTO_PRIORITY}
STACKSIZE
${CONFIG_TESTING_CRYPTO_STACKSIZE}
MODULE
${CONFIG_TESTING_CRYPTO}
SRCS
pbkdf2.c)
endif()
endif()

View file

@ -74,6 +74,10 @@ config TESTING_CRYPTO_RSA
bool "rsa crypto test"
default n
config TESTING_CRYPTO_PBKDF2
bool "pbkdf2 crypto test"
default n
config TESTING_CRYPTO_PRIORITY
int "crypto test task priority"
default 100

View file

@ -78,6 +78,11 @@ PROGNAME += rsa
MAINSRC += rsa.c
endif
ifeq ($(CONFIG_TESTING_CRYPTO_PBKDF2),y)
PROGNAME += pbkdf2
MAINSRC += pbkdf2.c
endif
PRIORITY = $(CONFIG_TESTING_CRYPTO_PRIORITY)
STACKSIZE = $(CONFIG_TESTING_CRYPTO_STACKSIZE)
MODULE = $(CONFIG_TESTING_CRYPTO)

View file

@ -0,0 +1,278 @@
/****************************************************************************
* apps/testing/drivers/crypto/pbkdf2.c
*
* SPDX-License-Identifier: Apache-2.0
*
* 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.
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <err.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <crypto/cryptodev.h>
struct tb
{
FAR char *key;
int keylen;
FAR char *data;
int datalen;
int iterations;
int dklen;
}
pbkdf2_testcases[] =
{
{
"password",
8,
"salt",
4,
1,
20,
},
{
"password",
8,
"salt",
4,
2,
20,
},
{
"password",
8,
"salt",
4,
4096,
20,
},
{
"password",
8,
"salt",
4,
16777216,
20,
},
{
"passwordPASSWORDpassword",
24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
36,
4096,
25,
},
{
"pass\0word",
9,
"sa\0lt",
5,
4096,
16,
},
};
FAR char *pbkdf2_sha1_result[] =
{
"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06"
"\x2f\xe0\x37\xa6",
"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0"
"\xd8\xde\x89\x57",
"\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0"
"\x65\xa4\x29\xc1",
"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94\x5b\x3d\x6b\xa2\x15\x8c"
"\x26\x34\xe9\x84",
"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62\xc0\xe4\x4a"
"\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38",
"\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34\x25\xe0\xc3",
};
FAR char *pbkdf2_sha256_result[] =
{
"\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52\x56\xc4\xf8\x37"
"\xa8\x65\x48\xc9",
"\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9\x28\xf0\x6d\xd0"
"\x2a\x30\x3f\x8e",
"\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6\x84\x5c\x4c\x8d"
"\x96\x28\x93\xa0",
"\xcf\x81\xc6\x6f\xe8\xcf\xc0\x4d\x1f\x31\xec\xb6\x5d\xab\x40\x89"
"\xf7\xf1\x79\xe8",
"\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11\x6e\x84\xcf"
"\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c",
"\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65\x0a\x86\x87",
};
int syspbkdf2(int mac, FAR const char *key, size_t keylen,
FAR const char *s, size_t len, int iterations,
size_t dklen, FAR char *out)
{
struct session_op session;
struct crypt_op cryp;
int cryptodev_fd = -1;
int fd = -1;
if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0)
{
warn("/dev/crypto");
goto err;
}
if (ioctl(fd, CRIOGET, &cryptodev_fd) == -1)
{
warn("CRIOGET");
goto err;
}
memset(&session, 0, sizeof(session));
session.cipher = 0;
session.mac = mac;
session.mackey = (caddr_t)key;
session.mackeylen = keylen;
if (ioctl(cryptodev_fd, CIOCGSESSION, &session) == -1)
{
warn("CIOCGSESSION");
goto err;
}
memset(&cryp, 0, sizeof(cryp));
cryp.ses = session.ses;
cryp.flags = 0;
cryp.src = (caddr_t)s;
cryp.len = len;
cryp.dst = 0;
cryp.mac = (caddr_t) out;
cryp.iv = 0;
cryp.iterations = iterations;
cryp.olen = dklen;
if (ioctl(cryptodev_fd, CIOCCRYPT, &cryp) == -1)
{
warn("CIOCCRYPT");
goto err;
}
close(cryptodev_fd);
close(fd);
return 0;
err:
if (cryptodev_fd != -1)
{
close(cryptodev_fd);
}
if (fd != -1)
{
close(fd);
}
return 1;
}
static int match(unsigned char *a, unsigned char *b, size_t len)
{
int i;
if (memcmp(a, b, len) == 0)
return (0);
warnx("pbkdf2 mismatch\n");
for (i = 0; i < len; i++)
{
printf("%02x", a[i]);
}
printf("\n");
for (i = 0; i < len; i++)
{
printf("%02x", b[i]);
}
printf("\n");
return (1);
}
/****************************************************************************
* Public Functions
****************************************************************************/
int main(void)
{
char output[40];
int ret = 0;
for (int i = 0; i < 6; i++)
{
ret = syspbkdf2(CRYPTO_PBKDF2_HMAC_SHA1, pbkdf2_testcases[i].key,
pbkdf2_testcases[i].keylen,
pbkdf2_testcases[i].data,
pbkdf2_testcases[i].datalen,
pbkdf2_testcases[i].iterations,
pbkdf2_testcases[i].dklen, output);
if (ret)
{
printf("PBKDF2 SHA1 failed\n");
}
ret += match((unsigned char *)pbkdf2_sha1_result[i],
(unsigned char *)output,
pbkdf2_testcases[i].dklen);
if (ret)
{
printf("match PBKDF2 SHA1 failed\n");
}
else
{
printf("hmac PBKDF2 SHA1 success\n");
}
}
for (int i = 0; i < 6; i++)
{
ret = syspbkdf2(CRYPTO_PBKDF2_HMAC_SHA256, pbkdf2_testcases[i].key,
pbkdf2_testcases[i].keylen,
pbkdf2_testcases[i].data,
pbkdf2_testcases[i].datalen,
pbkdf2_testcases[i].iterations,
pbkdf2_testcases[i].dklen, output);
if (ret)
{
printf("PBKDF2 SHA256 failed\n");
}
ret += match((unsigned char *)pbkdf2_sha256_result[i],
(unsigned char *)output,
pbkdf2_testcases[i].dklen);
if (ret)
{
printf("match PBKDF2 SHA256 failed\n");
}
else
{
printf("hmac PBKDF2 SHA256 success\n");
}
}
return 0;
}