nuttx-apps/testing/drivers/crypto/pbkdf2.c
Vlad Pruteanu cd2b0c0e87 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>
2026-03-27 21:46:08 +08:00

278 lines
6.5 KiB
C

/****************************************************************************
* 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;
}