[][openwrt][common][Add libkcapi to test fips140-3]
[Description]
Add libkcapi to pass fips140-3.
Libkcapi allow user-space to access the Linux kernel crypto API.
In this package, we add two command, `kcapi-drbg` and `kcapi-mtk-digst`
The `kcapi-drbg` is to test drbg in linux kernel cryto.
Usage:
-b --bytes <BYTES> Number of bytes to generate
(required option)
-r --rng name <RNGNAME> DRNG name as advertised in
/proc/crypto(require option))
-e --entropy <RNGNAME> DRBG entropy(require option))
-n --nonce <RNGNAME> DRBG nonce(require option))
-p --personalization string <RNGNAME> DRBG personaliztion
string(require option))
--hex The random number is returned
in hexadecimal notation
-h --help This help information
For example:
kcapi-drbg -e entropy -n nonce -p personalization string \
--hex -b 80 -r drbg_nopr_hmac_sha1
The `kcapi-mtk-digest` is to test hmac and sha in linux kernel crypto.
Usage:
-k Key (hmac required option)
-n Digest name such as sha1, sha224, sha256 sha512
hmac-sha1 hmac-sha224 hmac-sha256
hmac-sha384 hmac-sha512
-e empty input
-m message(require option))
-l output len(require option))
notation
-h --help This help information
Worth a question, it only use key in hmac.
For example:
kcapi-mtk-dgst -n sha512 -m data -l 10
kcapi-mtk-dgst -k key -n hmac-sha512 -m data -l 10
[Release-log]
Change-Id: I8a7061873a4cd52cbc02c0f2e2c6b188c7de456f
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8248293
diff --git a/feed/libkcapi/patches/0001-add-command-to-test-drbg.patch b/feed/libkcapi/patches/0001-add-command-to-test-drbg.patch
new file mode 100644
index 0000000..c26cc6d
--- /dev/null
+++ b/feed/libkcapi/patches/0001-add-command-to-test-drbg.patch
@@ -0,0 +1,295 @@
+--- a/libkcapi/Makefile.am
++++ b/libkcapi/Makefile.am
+@@ -193,6 +193,16 @@ EXTRA_bin_kcapi_rng_DEPENDENCIES = libto
+
+ SCAN_FILES += $(bin_kcapi_rng_SOURCES)
+ man_MANS += apps/kcapi-rng.1
++
++bin_PROGRAMS += bin/kcapi-drbg
++
++bin_kcapi_drbg_CPPFLAGS = $(COMMON_CPPFLAGS) -I$(top_srcdir)/lib/
++bin_kcapi_drbg_LDFLAGS = $(COMMON_LDFLAGS)
++bin_kcapi_drbg_LDADD = libkcapi.la
++bin_kcapi_drbg_SOURCES = apps/kcapi-drbg.c apps/app-internal.c
++EXTRA_bin_kcapi_rng_DEPENDENCIES = libtool
++
++SCAN_FILES += $(bin_kcapi_drbg_SOURCES)
+ endif
+
+ if ENABLE_KCAPI_ENCAPP
+--- /dev/null
++++ b/libkcapi/apps/kcapi-drbg.c
+@@ -0,0 +1,273 @@
++// SPDX-License-Identifier: BSD-2-Clause
++/*
++ * Copyright (C) 2023, MediaTek Inc. All rights reserved.
++ */
++
++#define _GNU_SOURCE
++#include <unistd.h>
++#include <sys/syscall.h>
++#include <errno.h>
++#include <limits.h>
++#include <stdint.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <getopt.h>
++
++#include <kcapi.h>
++
++#include "app-internal.h"
++
++/* For efficiency reasons, this should be identical to algif_rng.c:MAXSIZE. */
++#define KCAPI_RNG_BUFSIZE 2048
++
++static struct kcapi_handle *rng = NULL;
++static char *rng_name = NULL;
++static bool hexout = false;
++static unsigned char* entropy = NULL;
++static unsigned char* nonce = NULL;
++static unsigned char* per = NULL;
++static unsigned char* additional_1 = NULL;
++static unsigned char* additional_2 = NULL;
++static uint32_t entropy_len = 0;
++static uint32_t nonce_len = 0;
++static uint32_t per_len = 0;
++static uint32_t add1_len = 0;
++static uint32_t add2_len = 0;
++
++
++
++static unsigned char* hextobin(char* hexstr, uint32_t *ret_len) {
++ uint32_t len = strlen(hexstr);
++ size_t i = 0;
++ char *pos = hexstr;
++ unsigned char *ret = (unsigned char*) malloc((len + 1) / 2);
++
++ for (i = 0; i < (len + 1) / 2; i++) {
++ if(i == 0 && (len % 2) == 1) {
++ sscanf(pos, "%1hhx", &ret[i]);
++ pos += 1;
++ } else {
++ sscanf(pos, "%2hhx", &ret[i]);
++ pos += 2;
++ }
++ }
++ *ret_len = (len + 1) / 2;
++
++ return ret;
++}
++
++static void uninit() {
++ memset(entropy, 0, entropy_len);
++ memset(nonce, 0, nonce_len);
++ memset(per, 0, per_len);
++ memset(additional_1, 0, add1_len);
++ memset(additional_2, 0, add2_len);
++ if(entropy)
++ free(entropy);
++ if(nonce)
++ free(nonce);
++ if(per)
++ free(per);
++}
++
++static void usage(void)
++{
++ fprintf(stderr, "\nKernel Crypto API DRBG\n");
++ fprintf(stderr, "Usage:\n");
++ fprintf(stderr, "\t-b --bytes <BYTES>\tNumber of bytes to generate (required option)\n");
++ fprintf(stderr, "\t-r --rng name <RNGNAME>\tDRNG name as advertised in /proc/crypto(require option))\n");
++ fprintf(stderr, "\t-e --entropy <RNGNAME>\tDRBG entropy(require option))\n");
++ fprintf(stderr, "\t-n --nonce <RNGNAME>\tDRBG nonce(require option))\n");
++ fprintf(stderr, "\t-p --personaliztion string <RNGNAME>\tDRBG personaliztion string(require option))\n");
++ fprintf(stderr, "\t --hex\t\tThe random number is returned in hexadecimal\n");
++ fprintf(stderr, "\t\t\t\tnotation\n");
++ fprintf(stderr, "\t-h --help\t\tThis help information\n");
++
++ uninit();
++ exit(1);
++}
++
++static int parse_opts(int argc, char *argv[], size_t *outlen)
++{
++ int c = 0;
++ size_t bytes = 0;
++
++ while (1) {
++ int opt_index = 0;
++ static struct option opts[] = {
++ {"entropy", required_argument, 0, 'e'},
++ {"nonce", required_argument, 0, 'n'},
++ {"bytes", required_argument, 0, 'b'},
++ {"rng_name", required_argument, 0, 'r'},
++ {"personal_strng ", required_argument, 0, 'p'},
++ {"help", no_argument, 0, 'h'},
++ {"hex", no_argument, 0, 0},
++ {"additionalinput1 ", required_argument, 0, 'a'},
++ {"additionalinput2 ", required_argument, 0, 'c'},
++ {0, 0, 0, 0}
++ };
++ c = getopt_long(argc, argv, "e:n:b:r:p:ha:c:", opts, &opt_index);
++ if (-1 == c)
++ break;
++ switch (c) {
++ case 0:
++ switch (opt_index) {
++ case 0:
++ entropy = hextobin(optarg, &entropy_len);
++ break;
++ case 1:
++ nonce = hextobin(optarg, &nonce_len);
++ break;
++ case 2:
++ bytes = strtoul(optarg, NULL, 10);
++ if (bytes == ULONG_MAX) {
++ usage();
++ return -EINVAL;
++ }
++ break;
++ case 3:
++ rng_name = optarg;
++ break;
++ case 4:
++ per = hextobin(optarg, &per_len);
++ break;
++ case 5:
++ usage();
++ break;
++ case 6:
++ hexout = true;
++ break;
++ case 7:
++ additional_1 = hextobin(optarg, &add1_len);
++ break;
++ case 8:
++ additional_2 = hextobin(optarg, &add2_len);
++ break;
++ default:
++ usage();
++ }
++ break;
++ case 'e':
++ entropy = hextobin(optarg, &entropy_len);
++ break;
++ case 'n':
++ nonce = hextobin(optarg, &nonce_len);
++ break;
++ case 'b':
++ bytes = strtoul(optarg, NULL, 10);
++ if (bytes == ULONG_MAX) {
++ usage();
++ return -EINVAL;
++ }
++ break;
++ case 'r':
++ rng_name = optarg;
++ break;
++ case 'p':
++ per = hextobin(optarg, &per_len);
++ break;
++ case 'a':
++ additional_1 = hextobin(optarg, &add1_len);
++ break;
++ case 'c':
++ additional_2 = hextobin(optarg, &add2_len);
++ break;
++ default:
++ usage();
++ }
++ }
++ if (!bytes || !nonce || !entropy || !rng_name)
++ usage();
++
++ *outlen = (size_t)bytes;
++ return 0;
++}
++
++int main(int argc, char *argv[])
++{
++ ssize_t ret = 0;
++ uint8_t buf[KCAPI_RNG_BUFSIZE] __aligned(KCAPI_APP_ALIGN);
++ uint8_t *seedbuf = buf;
++ uint32_t seedsize = 0;
++ size_t outlen = 0;
++ unsigned char *ent = NULL;
++ int count = 2;
++
++ ret = parse_opts(argc, argv, &outlen);
++ if (ret)
++ return (int)ret;
++
++ ret = kcapi_rng_init(&rng, rng_name, 0);
++ if (ret)
++ return (int)ret;
++
++ seedsize = kcapi_rng_seedsize(rng);
++
++ ent = (unsigned char*)malloc(entropy_len + nonce_len + per_len);
++ memset(ent, 0, entropy_len + nonce_len + per_len);
++ memcpy(ent, entropy, entropy_len);
++ memcpy(ent + entropy_len, nonce, nonce_len);
++ memcpy(ent + entropy_len + nonce_len, per, per_len);
++
++ kcapi_rng_setentropy(rng, ent, entropy_len + nonce_len + per_len);
++
++ ret = kcapi_rng_seed(rng, seedbuf, seedsize);
++ if (ret)
++ goto out;
++
++ while(count --) {
++ size_t len = outlen;
++ while (len) {
++ size_t todo = (len < KCAPI_RNG_BUFSIZE) ?
++ len : KCAPI_RNG_BUFSIZE;
++
++ if(count == 1 && additional_1) {
++ kcapi_rng_setaddtl(rng, additional_1, add1_len);
++ } else if(count == 0 && additional_2 ){
++ kcapi_rng_setaddtl(rng, additional_2, add2_len);
++ }
++
++ ret = kcapi_rng_generate(rng, buf, todo);
++ if (ret < 0)
++ goto out;
++
++ if ((uint32_t)ret == 0) {
++ ret = -EFAULT;
++ goto out;
++ }
++
++ if(count == 0) {
++ if (hexout) {
++ char hexbuf[2 * KCAPI_RNG_BUFSIZE];
++
++ bin2hex(buf, (size_t)ret, hexbuf, sizeof(hexbuf), 0);
++ fwrite(hexbuf, 2 * (size_t)ret, 1, stdout);
++ } else {
++ fwrite(buf, (size_t)ret, 1, stdout);
++ }
++ }
++ len -= (size_t)ret;
++ }
++ }
++
++ ret = 0;
++out:
++ if (rng)
++ kcapi_rng_destroy(rng);
++ kcapi_memset_secure(buf, 0, sizeof(buf));
++
++ if (seedbuf && (seedbuf != buf)) {
++ kcapi_memset_secure(seedbuf, 0, seedsize);
++ free(seedbuf);
++ }
++
++ uninit();
++ if(!ent)
++ free(ent);
++
++ return (int)ret;
++}