[openssh] Add SSH KDF CAVS test driver for future FIPS validation (#1193045)
Jakub Jelen
jjelen at fedoraproject.org
Wed Feb 18 15:34:54 UTC 2015
commit bb3e880c0198cf96213beaa7b640f06c76db9730
Author: Jakub Jelen <jjelen at redhat.com>
Date: Tue Feb 17 12:44:33 2015 +0100
Add SSH KDF CAVS test driver for future FIPS validation (#1193045)
openssh-6.7p1-fips.patch | 2 +-
openssh-6.7p1-kdf-cavs.patch | 610 ++++++++++++++++++++++++++++++++++++++++++
openssh.spec | 5 +
3 files changed, 616 insertions(+), 1 deletions(-)
---
diff --git a/openssh-6.7p1-fips.patch b/openssh-6.7p1-fips.patch
index 3d9afe7..984a038 100644
--- a/openssh-6.7p1-fips.patch
+++ b/openssh-6.7p1-fips.patch
@@ -35,7 +35,7 @@ index 9311e16..1eb2b45 100644
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)
@@ -197,7 +197,7 @@ ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
- $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
+ $(LD) -o $@ ssh-cavs.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
diff --git a/openssh-6.7p1-kdf-cavs.patch b/openssh-6.7p1-kdf-cavs.patch
new file mode 100644
index 0000000..19e1b53
--- /dev/null
+++ b/openssh-6.7p1-kdf-cavs.patch
@@ -0,0 +1,610 @@
+diff --git a/Makefile.in b/Makefile.in
+index 1eb2b45..cfa89a1 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -29,6 +29,7 @@ SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
+ SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
+ SSH_KEYCAT=$(libexecdir)/ssh-keycat
+ 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@
+@@ -67,7 +68,7 @@ EXEEXT=@EXEEXT@
+ MANFMT=@MANFMT@
+ INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
+
+-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) ssh-ldap-helper$(EXEEXT) ssh-keycat$(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) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT)
+
+ LIBOPENSSH_OBJS=\
+ ssherr.o \
+@@ -196,6 +196,9 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o
+ 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 roaming_dummy.o
++ $(LD) -o $@ ssh-cavs.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
++
+ ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
+ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
+@@ -320,6 +321,8 @@ install-files:
+ fi
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(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) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+ $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+diff --git a/ssh-cavs.c b/ssh-cavs.c
+new file mode 100644
+index 0000000..928ff80
+--- /dev/null
++++ b/ssh-cavs.c
+@@ -0,0 +1,374 @@
++/*
++ * 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 "buffer.h"
++#include "key.h"
++#include "cipher.h"
++#include "kex.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;
++ Kex kex;
++ BIGNUM *Kbn = NULL;
++ int mode = 0;
++ Newkeys *ctoskeys;
++ Newkeys *stockeys;
++
++#define HEXOUTLEN 500
++ char hex[HEXOUTLEN];
++
++ memset(&kex, 0, sizeof(Kex));
++
++ Kbn = BN_new();
++ BN_bin2bn(test->K, test->Klen, Kbn);
++ if (!Kbn) {
++ printf("cannot convert K into BIGNUM\n");
++ ret = 1;
++ goto out;
++ }
++
++ 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 = 2;
++ break;
++ case 32:
++ kex.hash_alg = 3;
++ break;
++ case 48:
++ kex.hash_alg = 4;
++ break;
++ case 64:
++ kex.hash_alg = 5;
++ 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(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 */
++ kex_derive_keys_bn(&kex, test->H, test->Hlen, Kbn);
++
++ ctoskeys = kex_get_newkeys(0);
++ stockeys = kex_get_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);
++
++ free(ctoskeys);
++ free(stockeys);
++
++out:
++ if (Kbn)
++ BN_free(Kbn);
++ if (kex.newkeys[0])
++ free(kex.newkeys[0]);
++ if (kex.newkeys[1])
++ free(kex.newkeys[1]);
++ 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;
diff --git a/openssh.spec b/openssh.spec
index f65e8bb..4d726cb 100644
--- a/openssh.spec
+++ b/openssh.spec
@@ -166,6 +166,8 @@ Patch711: openssh-6.6p1-log-usepam-no.patch
Patch712: openssh-6.3p1-ctr-evp-fast.patch
# add cavs test binary for the aes-ctr
Patch713: openssh-6.6p1-ctr-cavstest.patch
+# add SSH KDF CAVS test driver
+Patch714: openssh-6.7p1-kdf-cavs.patch
#http://www.sxw.org.uk/computing/patches/openssh.html
@@ -413,6 +415,7 @@ popd
%patch711 -p1 -b .log-usepam-no
%patch712 -p1 -b .evp-ctr
%patch713 -p1 -b .ctr-cavs
+%patch714 -p1 -b .kdf-cavs
#
%patch800 -p1 -b .gsskex
%patch801 -p1 -b .force_krb
@@ -659,6 +662,8 @@ getent passwd sshd >/dev/null || \
%attr(0755,root,root) %dir %{_libexecdir}/openssh
%attr(2111,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign
%attr(0755,root,root) %{_libexecdir}/openssh/ctr-cavstest
+%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs
+%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs_driver.pl
%attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8*
%endif
More information about the scm-commits
mailing list