diff --git a/testing/drivers/crypto/CMakeLists.txt b/testing/drivers/crypto/CMakeLists.txt index 3918043a134..6e7fb369f3d 100644 --- a/testing/drivers/crypto/CMakeLists.txt +++ b/testing/drivers/crypto/CMakeLists.txt @@ -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() diff --git a/testing/drivers/crypto/Kconfig b/testing/drivers/crypto/Kconfig index 8eca7f72802..fe8ae58baaa 100644 --- a/testing/drivers/crypto/Kconfig +++ b/testing/drivers/crypto/Kconfig @@ -58,6 +58,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 diff --git a/testing/drivers/crypto/Makefile b/testing/drivers/crypto/Makefile index 64c6dfac744..82aeebef0a5 100644 --- a/testing/drivers/crypto/Makefile +++ b/testing/drivers/crypto/Makefile @@ -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) diff --git a/testing/drivers/crypto/pbkdf2.c b/testing/drivers/crypto/pbkdf2.c new file mode 100644 index 00000000000..10e7174efe6 --- /dev/null +++ b/testing/drivers/crypto/pbkdf2.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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; +}