[yocto] [meta-openssl102-fips][PATCH 14/15] openssh: add CAVS tests for FIPS validation
Mark Hatle
mark.hatle at kernel.crashing.org
Mon Sep 23 07:49:11 PDT 2019
Please include the commit from fedora for these files.
Also, I like how the cavs were packaged. An additional test should be added to
the ptest if the cavs are installed.
--Mark
On 9/22/19 9:57 AM, Hongxu Jia wrote:
> Refer the latest Fedora to add cavs test binary for the aes-ctr [1]
> and SSH KDF CAVS test driver [2]
>
> [1] http://pkgs.fedoraproject.org/cgit/rpms/openssh.git/plain/openssh-6.6p1-ctr-cavstest.patch
> [2] http://pkgs.fedoraproject.org/cgit/rpms/openssh.git/plain/openssh-6.7p1-kdf-cavs.patch
>
> Signed-off-by: Hongxu Jia <hongxu.jia at windriver.com>
> ---
> .../openssh/openssh-6.6p1-ctr-cavstest.patch | 289 +++++++++
> .../openssh/openssh/openssh-6.7p1-kdf-cavs.patch | 654 +++++++++++++++++++++
> recipes-connectivity/openssh/openssh_fips.inc | 9 +
> 3 files changed, 952 insertions(+)
> create mode 100644 recipes-connectivity/openssh/openssh/openssh-6.6p1-ctr-cavstest.patch
> create mode 100644 recipes-connectivity/openssh/openssh/openssh-6.7p1-kdf-cavs.patch
>
> diff --git a/recipes-connectivity/openssh/openssh/openssh-6.6p1-ctr-cavstest.patch b/recipes-connectivity/openssh/openssh/openssh-6.6p1-ctr-cavstest.patch
> new file mode 100644
> index 0000000..038efa0
> --- /dev/null
> +++ b/recipes-connectivity/openssh/openssh/openssh-6.6p1-ctr-cavstest.patch
> @@ -0,0 +1,289 @@
> +From a94a3d95439018dc7d276ec72de91af369ea413e Mon Sep 17 00:00:00 2001
> +From: Hongxu Jia <hongxu.jia at windriver.com>
> +Date: Sun, 22 Sep 2019 21:32:18 +0800
> +Subject: [PATCH 1/2] add CAVS test driver for the aes-ctr ciphers
> +
> +Original submission to Fedora, see:
> + https://lists.fedoraproject.org/pipermail/scm-commits/2012-January/715044.html
> +
> +this version download from:
> + http://pkgs.fedoraproject.org/cgit/rpms/openssh.git/plain/openssh-6.6p1-ctr-cavstest.patch
> + (as of commit 991b66246f5151884b63c6d1232610a4569642a5)
> +
> +Makefile.in slightly modified for integration
> +
> +This is the makefile.in change for the normal configuration.
> +
> +Signed-off-by: Mark Hatle <mark.hatle at windriver.com>
> +
> +Upstream-Status: Inappropriate [oe specific]
> +Signed-off-by: Hongxu Jia <hongxu.jia at windriver.com>
> +---
> + Makefile.in | 7 +-
> + ctr-cavstest.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> + 2 files changed, 221 insertions(+), 1 deletion(-)
> + create mode 100644 ctr-cavstest.c
> +
> +diff --git a/Makefile.in b/Makefile.in
> +index ddd1804..cb34681 100644
> +--- a/Makefile.in
> ++++ b/Makefile.in
> +@@ -23,6 +23,7 @@ SSH_PROGRAM=@bindir@/ssh
> + ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
> + SFTP_SERVER=$(libexecdir)/sftp-server
> + SSH_KEYSIGN=$(libexecdir)/ssh-keysign
> ++CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
> + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
> + PRIVSEP_PATH=@PRIVSEP_PATH@
> + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
> +@@ -60,7 +61,7 @@ EXEEXT=@EXEEXT@
> + MANFMT=@MANFMT@
> + MKDIR_P=@MKDIR_P@
> +
> +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
> ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ctr-cavstest$(EXEEXT)
> +
> + XMSS_OBJS=\
> + ssh-xmss.o \
> +@@ -193,6 +194,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o c
> + ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
> + $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
> +
> ++ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
> ++ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
> ++
> + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
> + $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
> +
> +@@ -343,6 +347,7 @@ install-files:
> + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
> + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
> ++ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
> +diff --git a/ctr-cavstest.c b/ctr-cavstest.c
> +new file mode 100644
> +index 0000000..0d4776b
> +--- /dev/null
> ++++ b/ctr-cavstest.c
> +@@ -0,0 +1,215 @@
> ++/*
> ++ *
> ++ * invocation (all of the following are equal):
> ++ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6
> ++ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000
> ++ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt
> ++ */
> ++
> ++#include "includes.h"
> ++
> ++#include <sys/types.h>
> ++#include <sys/param.h>
> ++#include <stdarg.h>
> ++#include <stdio.h>
> ++#include <stdlib.h>
> ++#include <string.h>
> ++#include <ctype.h>
> ++
> ++#include "xmalloc.h"
> ++#include "log.h"
> ++#include "ssherr.h"
> ++#include "cipher.h"
> ++
> ++/* compatibility with old or broken OpenSSL versions */
> ++#include "openbsd-compat/openssl-compat.h"
> ++
> ++void usage(void) {
> ++ fprintf(stderr, "Usage: ctr-cavstest --algo <ssh-crypto-algorithm>\n"
> ++ " --key <hexadecimal-key> --mode <encrypt|decrypt>\n"
> ++ " [--iv <hexadecimal-iv>] --data <hexadecimal-data>\n\n"
> ++ "Hexadecimal output is printed to stdout.\n"
> ++ "Hexadecimal input data can be alternatively read from stdin.\n");
> ++ exit(1);
> ++}
> ++
> ++void *fromhex(char *hex, size_t *len)
> ++{
> ++ unsigned char *bin;
> ++ char *p;
> ++ size_t n = 0;
> ++ int shift = 4;
> ++ unsigned char out = 0;
> ++ unsigned char *optr;
> ++
> ++ bin = xmalloc(strlen(hex)/2);
> ++ optr = bin;
> ++
> ++ for (p = hex; *p != '\0'; ++p) {
> ++ unsigned char c;
> ++
> ++ c = *p;
> ++ if (isspace(c))
> ++ continue;
> ++
> ++ if (c >= '0' && c <= '9') {
> ++ c = c - '0';
> ++ } else if (c >= 'A' && c <= 'F') {
> ++ c = c - 'A' + 10;
> ++ } else if (c >= 'a' && c <= 'f') {
> ++ c = c - 'a' + 10;
> ++ } else {
> ++ /* truncate on nonhex cipher */
> ++ break;
> ++ }
> ++
> ++ out |= c << shift;
> ++ shift = (shift + 4) % 8;
> ++
> ++ if (shift) {
> ++ *(optr++) = out;
> ++ out = 0;
> ++ ++n;
> ++ }
> ++ }
> ++
> ++ *len = n;
> ++ return bin;
> ++}
> ++
> ++#define READ_CHUNK 4096
> ++#define MAX_READ_SIZE 1024*1024*100
> ++char *read_stdin(void)
> ++{
> ++ char *buf;
> ++ size_t n, total = 0;
> ++
> ++ buf = xmalloc(READ_CHUNK);
> ++
> ++ do {
> ++ n = fread(buf + total, 1, READ_CHUNK, stdin);
> ++ if (n < READ_CHUNK) /* terminate on short read */
> ++ break;
> ++
> ++ total += n;
> ++ buf = xreallocarray(buf, total + READ_CHUNK, 1);
> ++ } while(total < MAX_READ_SIZE);
> ++ return buf;
> ++}
> ++
> ++int main (int argc, char *argv[])
> ++{
> ++
> ++ const struct sshcipher *c;
> ++ struct sshcipher_ctx *cc;
> ++ char *algo = "aes128-ctr";
> ++ char *hexkey = NULL;
> ++ char *hexiv = "00000000000000000000000000000000";
> ++ char *hexdata = NULL;
> ++ char *p;
> ++ int i, r;
> ++ int encrypt = 1;
> ++ void *key;
> ++ size_t keylen;
> ++ void *iv;
> ++ size_t ivlen;
> ++ void *data;
> ++ size_t datalen;
> ++ void *outdata;
> ++
> ++ for (i = 1; i < argc; ++i) {
> ++ if (strcmp(argv[i], "--algo") == 0) {
> ++ algo = argv[++i];
> ++ } else if (strcmp(argv[i], "--key") == 0) {
> ++ hexkey = argv[++i];
> ++ } else if (strcmp(argv[i], "--mode") == 0) {
> ++ ++i;
> ++ if (argv[i] == NULL) {
> ++ usage();
> ++ }
> ++ if (strncmp(argv[i], "enc", 3) == 0) {
> ++ encrypt = 1;
> ++ } else if (strncmp(argv[i], "dec", 3) == 0) {
> ++ encrypt = 0;
> ++ } else {
> ++ usage();
> ++ }
> ++ } else if (strcmp(argv[i], "--iv") == 0) {
> ++ hexiv = argv[++i];
> ++ } else if (strcmp(argv[i], "--data") == 0) {
> ++ hexdata = argv[++i];
> ++ }
> ++ }
> ++
> ++ if (hexkey == NULL || algo == NULL) {
> ++ usage();
> ++ }
> ++
> ++ OpenSSL_add_all_algorithms();
> ++
> ++ c = cipher_by_name(algo);
> ++ if (c == NULL) {
> ++ fprintf(stderr, "Error: unknown algorithm\n");
> ++ return 2;
> ++ }
> ++
> ++ if (hexdata == NULL) {
> ++ hexdata = read_stdin();
> ++ } else {
> ++ hexdata = xstrdup(hexdata);
> ++ }
> ++
> ++ key = fromhex(hexkey, &keylen);
> ++
> ++ if (keylen != 16 && keylen != 24 && keylen == 32) {
> ++ fprintf(stderr, "Error: unsupported key length\n");
> ++ return 2;
> ++ }
> ++
> ++ iv = fromhex(hexiv, &ivlen);
> ++
> ++ if (ivlen != 16) {
> ++ fprintf(stderr, "Error: unsupported iv length\n");
> ++ return 2;
> ++ }
> ++
> ++ data = fromhex(hexdata, &datalen);
> ++
> ++ if (data == NULL || datalen == 0) {
> ++ fprintf(stderr, "Error: no data to encrypt/decrypt\n");
> ++ return 2;
> ++ }
> ++
> ++ if ((r = cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt)) != 0) {
> ++ fprintf(stderr, "Error: cipher_init failed: %s\n", ssh_err(r));
> ++ return 2;
> ++ }
> ++
> ++ free(key);
> ++ free(iv);
> ++
> ++ outdata = malloc(datalen);
> ++ if(outdata == NULL) {
> ++ fprintf(stderr, "Error: memory allocation failure\n");
> ++ return 2;
> ++ }
> ++
> ++ if ((r = cipher_crypt(cc, 0, outdata, data, datalen, 0, 0)) != 0) {
> ++ fprintf(stderr, "Error: cipher_crypt failed: %s\n", ssh_err(r));
> ++ return 2;
> ++ }
> ++
> ++ free(data);
> ++
> ++ cipher_free(cc);
> ++
> ++ for (p = outdata; datalen > 0; ++p, --datalen) {
> ++ printf("%02X", (unsigned char)*p);
> ++ }
> ++
> ++ free(outdata);
> ++
> ++ printf("\n");
> ++ return 0;
> ++}
> ++
> +--
> +2.7.4
> +
> diff --git a/recipes-connectivity/openssh/openssh/openssh-6.7p1-kdf-cavs.patch b/recipes-connectivity/openssh/openssh/openssh-6.7p1-kdf-cavs.patch
> new file mode 100644
> index 0000000..f49821c
> --- /dev/null
> +++ b/recipes-connectivity/openssh/openssh/openssh-6.7p1-kdf-cavs.patch
> @@ -0,0 +1,654 @@
> +From 210d15fd146ff7037f03fff5e0ba6fcf0bfde683 Mon Sep 17 00:00:00 2001
> +From: Hongxu Jia <hongxu.jia at windriver.com>
> +Date: Sun, 22 Sep 2019 21:40:51 +0800
> +Subject: [PATCH 2/2] add KDF CAVS test driver
> +
> +Original submission to Fedora, see:
> + https://lists.fedoraproject.org/pipermail/scm-commits/Week-of-Mon-20150216/1514788.html
> +
> +this version download from:
> + http://pkgs.fedoraproject.org/cgit/rpms/openssh.git/plain/openssh-6.7p1-kdf-cavs.patch
> + (as of commit 991b66246f5151884b63c6d1232610a4569642a5)
> +
> +Makefile.in slightly modified for integration
> +
> +This is the makefile.in change for the normal configuration.
> +
> +Signed-off-by: Mark Hatle <mark.hatle at windriver.com>
> +
> +Upstream-Status: Inappropriate [oe specific]
> +Signed-off-by: Hongxu Jia <hongxu.jia at windriver.com>
> +---
> + Makefile.in | 8 +-
> + ssh-cavs.c | 387 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> + ssh-cavs_driver.pl | 184 +++++++++++++++++++++++++
> + 3 files changed, 578 insertions(+), 1 deletion(-)
> + create mode 100644 ssh-cavs.c
> + create mode 100644 ssh-cavs_driver.pl
> +
> +diff --git a/Makefile.in b/Makefile.in
> +index cb34681..368097e 100644
> +--- a/Makefile.in
> ++++ b/Makefile.in
> +@@ -24,6 +24,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
> + SFTP_SERVER=$(libexecdir)/sftp-server
> + SSH_KEYSIGN=$(libexecdir)/ssh-keysign
> + CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
> ++SSH_CAVS=$(libexecdir)/ssh-cavs
> + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
> + PRIVSEP_PATH=@PRIVSEP_PATH@
> + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
> +@@ -61,7 +62,7 @@ EXEEXT=@EXEEXT@
> + MANFMT=@MANFMT@
> + MKDIR_P=@MKDIR_P@
> +
> +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ctr-cavstest$(EXEEXT)
> ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT)
> +
> + XMSS_OBJS=\
> + ssh-xmss.o \
> +@@ -197,6 +198,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11
> + ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
> + $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
> +
> ++ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o
> ++ $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
> ++
> + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
> + $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
> +
> +@@ -348,6 +352,8 @@ install-files:
> + $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
> + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT)
> ++ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-cavs$(EXEEXT)
> ++ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs_driver.pl $(DESTDIR)$(libexecdir)/ssh-cavs_driver.pl
> + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
> + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
> +diff --git a/ssh-cavs.c b/ssh-cavs.c
> +new file mode 100644
> +index 0000000..b74ae7f
> +--- /dev/null
> ++++ b/ssh-cavs.c
> +@@ -0,0 +1,387 @@
> ++/*
> ++ * Copyright (C) 2015, Stephan Mueller <smueller at chronox.de>
> ++ *
> ++ * Redistribution and use in source and binary forms, with or without
> ++ * modification, are permitted provided that the following conditions
> ++ * are met:
> ++ * 1. Redistributions of source code must retain the above copyright
> ++ * notice, and the entire permission notice in its entirety,
> ++ * including the disclaimer of warranties.
> ++ * 2. Redistributions in binary form must reproduce the above copyright
> ++ * notice, this list of conditions and the following disclaimer in the
> ++ * documentation and/or other materials provided with the distribution.
> ++ * 3. The name of the author may not be used to endorse or promote
> ++ * products derived from this software without specific prior
> ++ * written permission.
> ++ *
> ++ * ALTERNATIVELY, this product may be distributed under the terms of
> ++ * the GNU General Public License, in which case the provisions of the GPL2
> ++ * are required INSTEAD OF the above restrictions. (This clause is
> ++ * necessary due to a potential bad interaction between the GPL and
> ++ * the restrictions contained in a BSD-style copyright.)
> ++ *
> ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
> ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
> ++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
> ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
> ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> ++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> ++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> ++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
> ++ * DAMAGE.
> ++ */
> ++
> ++#include "includes.h"
> ++
> ++#include <stdio.h>
> ++#include <stdlib.h>
> ++#include <errno.h>
> ++#include <sys/types.h>
> ++#include <string.h>
> ++
> ++#include <openssl/bn.h>
> ++
> ++#include "xmalloc.h"
> ++#include "sshbuf.h"
> ++#include "sshkey.h"
> ++#include "cipher.h"
> ++#include "kex.h"
> ++#include "packet.h"
> ++#include "digest.h"
> ++
> ++static int bin_char(unsigned char hex)
> ++{
> ++ if (48 <= hex && 57 >= hex)
> ++ return (hex - 48);
> ++ if (65 <= hex && 70 >= hex)
> ++ return (hex - 55);
> ++ if (97 <= hex && 102 >= hex)
> ++ return (hex - 87);
> ++ return 0;
> ++}
> ++
> ++/*
> ++ * Convert hex representation into binary string
> ++ * @hex input buffer with hex representation
> ++ * @hexlen length of hex
> ++ * @bin output buffer with binary data
> ++ * @binlen length of already allocated bin buffer (should be at least
> ++ * half of hexlen -- if not, only a fraction of hexlen is converted)
> ++ */
> ++static void hex2bin(const char *hex, size_t hexlen,
> ++ unsigned char *bin, size_t binlen)
> ++{
> ++ size_t i = 0;
> ++ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
> ++
> ++ for (i = 0; i < chars; i++) {
> ++ bin[i] = bin_char(hex[(i*2)]) << 4;
> ++ bin[i] |= bin_char(hex[((i*2)+1)]);
> ++ }
> ++}
> ++
> ++/*
> ++ * Allocate sufficient space for binary representation of hex
> ++ * and convert hex into bin
> ++ *
> ++ * Caller must free bin
> ++ * @hex input buffer with hex representation
> ++ * @hexlen length of hex
> ++ * @bin return value holding the pointer to the newly allocated buffer
> ++ * @binlen return value holding the allocated size of bin
> ++ *
> ++ * return: 0 on success, !0 otherwise
> ++ */
> ++static int hex2bin_alloc(const char *hex, size_t hexlen,
> ++ unsigned char **bin, size_t *binlen)
> ++{
> ++ unsigned char *out = NULL;
> ++ size_t outlen = 0;
> ++
> ++ if (!hexlen)
> ++ return -EINVAL;
> ++
> ++ outlen = (hexlen + 1) / 2;
> ++
> ++ out = calloc(1, outlen);
> ++ if (!out)
> ++ return -errno;
> ++
> ++ hex2bin(hex, hexlen, out, outlen);
> ++ *bin = out;
> ++ *binlen = outlen;
> ++ return 0;
> ++}
> ++
> ++static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> ++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
> ++static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
> ++ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
> ++static char hex_char(unsigned int bin, int u)
> ++{
> ++ if (bin < sizeof(hex_char_map_l))
> ++ return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
> ++ return 'X';
> ++}
> ++
> ++/*
> ++ * Convert binary string into hex representation
> ++ * @bin input buffer with binary data
> ++ * @binlen length of bin
> ++ * @hex output buffer to store hex data
> ++ * @hexlen length of already allocated hex buffer (should be at least
> ++ * twice binlen -- if not, only a fraction of binlen is converted)
> ++ * @u case of hex characters (0=>lower case, 1=>upper case)
> ++ */
> ++static void bin2hex(const unsigned char *bin, size_t binlen,
> ++ char *hex, size_t hexlen, int u)
> ++{
> ++ size_t i = 0;
> ++ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
> ++
> ++ for (i = 0; i < chars; i++) {
> ++ hex[(i*2)] = hex_char((bin[i] >> 4), u);
> ++ hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
> ++ }
> ++}
> ++
> ++struct kdf_cavs {
> ++ unsigned char *K;
> ++ size_t Klen;
> ++ unsigned char *H;
> ++ size_t Hlen;
> ++ unsigned char *session_id;
> ++ size_t session_id_len;
> ++
> ++ unsigned int iv_len;
> ++ unsigned int ek_len;
> ++ unsigned int ik_len;
> ++};
> ++
> ++static int sshkdf_cavs(struct kdf_cavs *test)
> ++{
> ++ int ret = 0;
> ++ struct kex kex;
> ++ struct sshbuf *Kb = NULL;
> ++ BIGNUM *Kbn = NULL;
> ++ int mode = 0;
> ++ struct newkeys *ctoskeys;
> ++ struct newkeys *stockeys;
> ++ struct ssh *ssh = NULL;
> ++
> ++#define HEXOUTLEN 500
> ++ char hex[HEXOUTLEN];
> ++
> ++ memset(&kex, 0, sizeof(struct kex));
> ++
> ++ Kbn = BN_new();
> ++ BN_bin2bn(test->K, test->Klen, Kbn);
> ++ if (!Kbn) {
> ++ printf("cannot convert K into bignum\n");
> ++ ret = 1;
> ++ goto out;
> ++ }
> ++ Kb = sshbuf_new();
> ++ if (!Kb) {
> ++ printf("cannot convert K into sshbuf\n");
> ++ ret = 1;
> ++ goto out;
> ++ }
> ++ sshbuf_put_bignum2(Kb, Kbn);
> ++
> ++ kex.session_id = test->session_id;
> ++ kex.session_id_len = test->session_id_len;
> ++
> ++ /* setup kex */
> ++
> ++ /* select the right hash based on struct ssh_digest digests */
> ++ switch (test->ik_len) {
> ++ case 20:
> ++ kex.hash_alg = SSH_DIGEST_SHA1;
> ++ break;
> ++ case 32:
> ++ kex.hash_alg = SSH_DIGEST_SHA256;
> ++ break;
> ++ case 48:
> ++ kex.hash_alg = SSH_DIGEST_SHA384;
> ++ break;
> ++ case 64:
> ++ kex.hash_alg = SSH_DIGEST_SHA512;
> ++ break;
> ++ default:
> ++ printf("Wrong hash type %u\n", test->ik_len);
> ++ ret = 1;
> ++ goto out;
> ++ }
> ++
> ++ /* implement choose_enc */
> ++ for (mode = 0; mode < 2; mode++) {
> ++ kex.newkeys[mode] = calloc(1, sizeof(struct newkeys));
> ++ if (!kex.newkeys[mode]) {
> ++ printf("allocation of newkeys failed\n");
> ++ ret = 1;
> ++ goto out;
> ++ }
> ++ kex.newkeys[mode]->enc.iv_len = test->iv_len;
> ++ kex.newkeys[mode]->enc.key_len = test->ek_len;
> ++ kex.newkeys[mode]->enc.block_size = (test->iv_len == 64) ? 8 : 16;
> ++ kex.newkeys[mode]->mac.key_len = test->ik_len;
> ++ }
> ++
> ++ /* implement kex_choose_conf */
> ++ kex.we_need = kex.newkeys[0]->enc.key_len;
> ++ if (kex.we_need < kex.newkeys[0]->enc.block_size)
> ++ kex.we_need = kex.newkeys[0]->enc.block_size;
> ++ if (kex.we_need < kex.newkeys[0]->enc.iv_len)
> ++ kex.we_need = kex.newkeys[0]->enc.iv_len;
> ++ if (kex.we_need < kex.newkeys[0]->mac.key_len)
> ++ kex.we_need = kex.newkeys[0]->mac.key_len;
> ++
> ++ /* MODE_OUT (1) -> server to client
> ++ * MODE_IN (0) -> client to server */
> ++ kex.server = 1;
> ++
> ++ /* do it */
> ++ if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL){
> ++ printf("Allocation error\n");
> ++ goto out;
> ++ }
> ++ ssh->kex = &kex;
> ++ kex_derive_keys(ssh, test->H, test->Hlen, Kb);
> ++
> ++ ctoskeys = kex.newkeys[0];
> ++ stockeys = kex.newkeys[1];
> ++
> ++ /* get data */
> ++ memset(hex, 0, HEXOUTLEN);
> ++ bin2hex(ctoskeys->enc.iv, (size_t)ctoskeys->enc.iv_len,
> ++ hex, HEXOUTLEN, 0);
> ++ printf("Initial IV (client to server) = %s\n", hex);
> ++ memset(hex, 0, HEXOUTLEN);
> ++ bin2hex(stockeys->enc.iv, (size_t)stockeys->enc.iv_len,
> ++ hex, HEXOUTLEN, 0);
> ++ printf("Initial IV (server to client) = %s\n", hex);
> ++
> ++ memset(hex, 0, HEXOUTLEN);
> ++ bin2hex(ctoskeys->enc.key, (size_t)ctoskeys->enc.key_len,
> ++ hex, HEXOUTLEN, 0);
> ++ printf("Encryption key (client to server) = %s\n", hex);
> ++ memset(hex, 0, HEXOUTLEN);
> ++ bin2hex(stockeys->enc.key, (size_t)stockeys->enc.key_len,
> ++ hex, HEXOUTLEN, 0);
> ++ printf("Encryption key (server to client) = %s\n", hex);
> ++
> ++ memset(hex, 0, HEXOUTLEN);
> ++ bin2hex(ctoskeys->mac.key, (size_t)ctoskeys->mac.key_len,
> ++ hex, HEXOUTLEN, 0);
> ++ printf("Integrity key (client to server) = %s\n", hex);
> ++ memset(hex, 0, HEXOUTLEN);
> ++ bin2hex(stockeys->mac.key, (size_t)stockeys->mac.key_len,
> ++ hex, HEXOUTLEN, 0);
> ++ printf("Integrity key (server to client) = %s\n", hex);
> ++
> ++out:
> ++ if (Kbn)
> ++ BN_free(Kbn);
> ++ if (Kb)
> ++ sshbuf_free(Kb);
> ++ if (ssh)
> ++ ssh_packet_close(ssh);
> ++ return ret;
> ++}
> ++
> ++static void usage(void)
> ++{
> ++ fprintf(stderr, "\nOpenSSH KDF CAVS Test\n\n");
> ++ fprintf(stderr, "Usage:\n");
> ++ fprintf(stderr, "\t-K\tShared secret string\n");
> ++ fprintf(stderr, "\t-H\tHash string\n");
> ++ fprintf(stderr, "\t-s\tSession ID string\n");
> ++ fprintf(stderr, "\t-i\tIV length to be generated\n");
> ++ fprintf(stderr, "\t-e\tEncryption key length to be generated\n");
> ++ fprintf(stderr, "\t-m\tMAC key length to be generated\n");
> ++}
> ++
> ++/*
> ++ * Test command example:
> ++ * ./ssh-cavs -K 0055d50f2d163cc07cd8a93cc7c3430c30ce786b572c01ad29fec7597000cf8618d664e2ec3dcbc8bb7a1a7eb7ef67f61cdaf291625da879186ac0a5cb27af571b59612d6a6e0627344d846271959fda61c78354aa498773d59762f8ca2d0215ec590d8633de921f920d41e47b3de6ab9a3d0869e1c826d0e4adebf8e3fb646a15dea20a410b44e969f4b791ed6a67f13f1b74234004d5fa5e87eff7abc32d49bbdf44d7b0107e8f10609233b7e2b7eff74a4daf25641de7553975dac6ac1e5117df6f6dbaa1c263d23a6c3e5a3d7d49ae8a828c1e333ac3f85fbbf57b5c1a45be45e43a7be1a4707eac779b8285522d1f531fe23f890fd38a004339932b93eda4 -H d3ab91a850febb417a25d892ec48ed5952c7a5de -s d3ab91a850febb417a25d892ec48ed5952c7a5de -i 8 -e 24 -m 20
> ++ *
> ++ * Initial IV (client to server) = 4bb320d1679dfd3a
> ++ * Initial IV (server to client) = 43dea6fdf263a308
> ++ * Encryption key (client to server) = 13048cc600b9d3cf9095aa6cf8e2ff9cf1c54ca0520c89ed
> ++ * Encryption key (server to client) = 1e483c5134e901aa11fc4e0a524e7ec7b75556148a222bb0
> ++ * Integrity key (client to server) = ecef63a092b0dcc585bdc757e01b2740af57d640
> ++ * Integrity key (server to client) = 7424b05f3c44a72b4ebd281fb71f9cbe7b64d479
> ++ */
> ++int main(int argc, char *argv[])
> ++{
> ++ struct kdf_cavs test;
> ++ int ret = 1;
> ++ int opt = 0;
> ++
> ++ memset(&test, 0, sizeof(struct kdf_cavs));
> ++ while((opt = getopt(argc, argv, "K:H:s:i:e:m:")) != -1)
> ++ {
> ++ size_t len = 0;
> ++ switch(opt)
> ++ {
> ++ /*
> ++ * CAVS K is MPINT
> ++ * we want a hex (i.e. the caller must ensure the
> ++ * following transformations already happened):
> ++ * 1. cut off first four bytes
> ++ * 2. if most significant bit of value is
> ++ * 1, prepend 0 byte
> ++ */
> ++ case 'K':
> ++ len = strlen(optarg);
> ++ ret = hex2bin_alloc(optarg, len,
> ++ &test.K, &test.Klen);
> ++ if (ret)
> ++ goto out;
> ++ break;
> ++ case 'H':
> ++ len = strlen(optarg);
> ++ ret = hex2bin_alloc(optarg, len,
> ++ &test.H, &test.Hlen);
> ++ if (ret)
> ++ goto out;
> ++ break;
> ++ case 's':
> ++ len = strlen(optarg);
> ++ ret = hex2bin_alloc(optarg, len,
> ++ &test.session_id,
> ++ &test.session_id_len);
> ++ if (ret)
> ++ goto out;
> ++ break;
> ++ case 'i':
> ++ test.iv_len = strtoul(optarg, NULL, 10);
> ++ break;
> ++ case 'e':
> ++ test.ek_len = strtoul(optarg, NULL, 10);
> ++ break;
> ++ case 'm':
> ++ test.ik_len = strtoul(optarg, NULL, 10);
> ++ break;
> ++ default:
> ++ usage();
> ++ goto out;
> ++ }
> ++ }
> ++
> ++ ret = sshkdf_cavs(&test);
> ++
> ++out:
> ++ if (test.session_id)
> ++ free(test.session_id);
> ++ if (test.K)
> ++ free(test.K);
> ++ if (test.H)
> ++ free(test.H);
> ++ return ret;
> ++
> ++}
> +diff --git a/ssh-cavs_driver.pl b/ssh-cavs_driver.pl
> +new file mode 100644
> +index 0000000..6ed8f26
> +--- /dev/null
> ++++ b/ssh-cavs_driver.pl
> +@@ -0,0 +1,184 @@
> ++#!/usr/bin/env perl
> ++#
> ++# CAVS test driver for OpenSSH
> ++#
> ++# Copyright (C) 2015, Stephan Mueller <smueller at chronox.de>
> ++#
> ++# Permission is hereby granted, free of charge, to any person obtaining a copy
> ++# of this software and associated documentation files (the "Software"), to deal
> ++# in the Software without restriction, including without limitation the rights
> ++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> ++# copies of the Software, and to permit persons to whom the Software is
> ++# furnished to do so, subject to the following conditions:
> ++#
> ++# The above copyright notice and this permission notice shall be included in
> ++# all copies or substantial portions of the Software.
> ++#
> ++# NO WARRANTY
> ++#
> ++# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
> ++# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
> ++# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
> ++# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
> ++# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> ++# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
> ++# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
> ++# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
> ++# REPAIR OR CORRECTION.
> ++#
> ++# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
> ++# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
> ++# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
> ++# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
> ++# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
> ++# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
> ++# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
> ++# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
> ++# POSSIBILITY OF SUCH DAMAGES.
> ++#
> ++use strict;
> ++use warnings;
> ++use IPC::Open2;
> ++
> ++# Executing a program by feeding STDIN and retrieving
> ++# STDOUT
> ++# $1: data string to be piped to the app on STDIN
> ++# rest: program and args
> ++# returns: STDOUT of program as string
> ++sub pipe_through_program($@) {
> ++ my $in = shift;
> ++ my @args = @_;
> ++
> ++ my ($CO, $CI);
> ++ my $pid = open2($CO, $CI, @args);
> ++
> ++ my $out = "";
> ++ my $len = length($in);
> ++ my $first = 1;
> ++ while (1) {
> ++ my $rin = "";
> ++ my $win = "";
> ++ # Output of prog is FD that we read
> ++ vec($rin,fileno($CO),1) = 1;
> ++ # Input of prog is FD that we write
> ++ # check for $first is needed because we can have NULL input
> ++ # that is to be written to the app
> ++ if ( $len > 0 || $first) {
> ++ (vec($win,fileno($CI),1) = 1);
> ++ $first=0;
> ++ }
> ++ # Let us wait for 100ms
> ++ my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1);
> ++ if ( $wout ) {
> ++ my $written = syswrite($CI, $in, $len);
> ++ die "broken pipe" if !defined $written;
> ++ $len -= $written;
> ++ substr($in, 0, $written) = "";
> ++ if ($len <= 0) {
> ++ close $CI or die "broken pipe: $!";
> ++ }
> ++ }
> ++ if ( $rout ) {
> ++ my $tmp_out = "";
> ++ my $bytes_read = sysread($CO, $tmp_out, 4096);
> ++ $out .= $tmp_out;
> ++ last if ($bytes_read == 0);
> ++ }
> ++ }
> ++ close $CO or die "broken pipe: $!";
> ++ waitpid $pid, 0;
> ++
> ++ return $out;
> ++}
> ++
> ++# Parser of CAVS test vector file
> ++# $1: Test vector file
> ++# $2: Output file for test results
> ++# return: nothing
> ++sub parse($$) {
> ++ my $infile = shift;
> ++ my $outfile = shift;
> ++
> ++ my $out = "";
> ++
> ++ my $K = "";
> ++ my $H = "";
> ++ my $session_id = "";
> ++ my $ivlen = 0;
> ++ my $eklen = "";
> ++ my $iklen = "";
> ++
> ++ open(IN, "<$infile");
> ++ while(<IN>) {
> ++
> ++ my $line = $_;
> ++ chomp($line);
> ++ $line =~ s/\r//;
> ++
> ++ if ($line =~ /\[SHA-1\]/) {
> ++ $iklen = 20;
> ++ } elsif ($line =~ /\[SHA-256\]/) {
> ++ $iklen = 32;
> ++ } elsif ($line =~ /\[SHA-384\]/) {
> ++ $iklen = 48;
> ++ } elsif ($line =~ /\[SHA-512\]/) {
> ++ $iklen = 64;
> ++ } elsif ($line =~ /^\[IV length\s*=\s*(.*)\]/) {
> ++ $ivlen = $1;
> ++ $ivlen = $ivlen / 8;
> ++ } elsif ($line =~ /^\[encryption key length\s*=\s*(.*)\]/) {
> ++ $eklen = $1;
> ++ $eklen = $eklen / 8;
> ++ } elsif ($line =~ /^K\s*=\s*(.*)/) {
> ++ $K = $1;
> ++ $K = substr($K, 8);
> ++ $K = "00" . $K;
> ++ } elsif ($line =~ /^H\s*=\s*(.*)/) {
> ++ $H = $1;
> ++ } elsif ($line =~ /^session_id\s*=\s*(.*)/) {
> ++ $session_id = $1;
> ++ }
> ++ $out .= $line . "\n";
> ++
> ++ if ($K ne "" && $H ne "" && $session_id ne "" &&
> ++ $ivlen ne "" && $eklen ne "" && $iklen > 0) {
> ++ $out .= pipe_through_program("", "./ssh-cavs -H $H -K $K -s $session_id -i $ivlen -e $eklen -m $iklen");
> ++
> ++ $K = "";
> ++ $H = "";
> ++ $session_id = "";
> ++ }
> ++ }
> ++ close IN;
> ++ $out =~ s/\n/\r\n/g; # make it a dos file
> ++ open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?";
> ++ print OUT $out;
> ++ close OUT;
> ++}
> ++
> ++############################################################
> ++#
> ++# let us pretend to be C :-)
> ++sub main() {
> ++
> ++ my $infile=$ARGV[0];
> ++ die "Error: Test vector file $infile not found" if (! -f $infile);
> ++
> ++ my $outfile = $infile;
> ++ # let us add .rsp regardless whether we could strip .req
> ++ $outfile =~ s/\.req$//;
> ++ $outfile .= ".rsp";
> ++ if (-f $outfile) {
> ++ die "Output file $outfile could not be removed: $?"
> ++ unless unlink($outfile);
> ++ }
> ++ print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n";
> ++
> ++ # Do the job
> ++ parse($infile, $outfile);
> ++}
> ++
> ++###########################################
> ++# Call it
> ++main();
> ++1;
> +--
> +2.7.4
> +
> diff --git a/recipes-connectivity/openssh/openssh_fips.inc b/recipes-connectivity/openssh/openssh_fips.inc
> index 33a84c9..5df3106 100644
> --- a/recipes-connectivity/openssh/openssh_fips.inc
> +++ b/recipes-connectivity/openssh/openssh_fips.inc
> @@ -6,6 +6,8 @@ DEPENDS += " \
> SRC_URI += " \
> file://0001-openssh-8.0p1-fips.patch \
> file://0001-conditional-enable-fips-mode.patch \
> + file://openssh-6.6p1-ctr-cavstest.patch \
> + file://openssh-6.7p1-kdf-cavs.patch \
> "
>
> do_install_append() {
> @@ -32,4 +34,11 @@ pkg_postinst_append_${PN}-sshd () {
> fi
> }
>
> +PACKAGES =+ "${PN}-cavs"
> +SUMMARY_${PN}-cavs = "CAVS tests for FIPS validation"
> +FILES_${PN}-cavs = " \
> + ${libexecdir}/ctr-cavstest \
> + ${libexecdir}/ssh-cavs \
> + ${libexecdir}/ssh-cavs_driver.pl"
> +
> FILES_${PN} += "${libdir}/fipscheck"
>
More information about the yocto
mailing list