Hi, I am happy to (re)send a set of patches for compiling OpenSSH 4.7p1 with FIPS 140-2 OpenSSL. These are based on previously reported patches by Steve Marquess <marquess at ieee.org> and Ben Laurie <ben at algroup.co.uk>, for ver. OpenSSH 3.8. Note that these patches are NOT OFFICIAL, and MAY be used freely by anyone. Issues [partially] handled: SSL FIPS Self test. RC4, arcfour, et. al. are not 140-2 compliant (need to use 3DES built in RNG instead) MD5 digest is not 140-2 compliant (need to use SHA instead). Make OpenSSH FIPS aware (limit the ciphers according to the FIPS mode.) fork() & FIPS RNG. openssl-fips-1.1.1 workaround. Suggestions and Todos: Retest everything. Make OpenSSH FIPS 140-2 compliant (or even certified:) Add configuration for use of SHA1 instead/in addition to/ MD5. Configure blowfish as default in non FIPS mode. Disabled RSA1 in FIPS mode. Add central [FIPS] configuration (currently each binary has its own configuration.) Improve fork() logic. Invite me for a drink. Best, Oren Nechushtan P.S. The patches are split into two due to mailing list size limitations: [openssh.spec]> %define openssldir /usr/local/ssl > %define openssllib %{openssldir}/lib > %define opensslinclude %{openssldir}/include> export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):%{openssllib} > export CC=gcc > export LD=fipsld >> # --with-md5-passwords198d221 < --with-md5-passwords \ 209a233,240> --with-ssl-dir=%{openssldir} \ > --with-fips \ > --with-cppflags="%{fsgccopts}" \ > --with-cflags="%{fsgccopts} -g" \ > --with-ldflags="%{fsgccopts} -L%{openssllib} -Wl,-rpath%{openssllib}" \> > export CC=fipsld > export FIPSLD_CC=gcc216c247 < make ---> make CC=$CC FIPSLD_CC=$FIPSLD_CC220c251,257 < %configure --libexecdir=%{_libexecdir}/openssh ---> %configure --libexecdir=%{_libexecdir}/openssh \ > --with-ssl-dir=%{openssldir} \ > --with-fips \ > --with-cppflags="%{fsgccopts}" \ > --with-cflags="%{fsgccopts}" \ > --with-ldflags="%{fsgccopts} -L%{openssllib} -Wl,-rpath%{openssllib}" \ ------------------------------------------------------------------------ -------------------- --- openssh-4.7p1/buildpkg.sh.in 25 Jul 2007 +++ openssh-4.7p1/buildpkg.sh.in 25 Jul 2007 @@ -128,3 +128,3 @@ ## Fill in some details, like prefix and sysconfdir -for confvar in prefix exec_prefix bindir sbindir libexecdir datadir mandir sysconfdir piddir srcdir +for confvar in prefix exec_prefix bindir sbindir libexecdir datadir mandir sysconfdir piddir srcdir ssldir do diff -u -r1.1 -r1.3 --- openssh-4.7p1/ChangeLog 19 May 2004 13:05:16 -0000 1.1 +++ openssh-4.7p1/ChangeLog 28 May 2004 13:30:29 -0000 1.3 @@ -1,3 +1,7 @@ +20071224 #orig 20040419 + - Oren Nechushtan <oren at forescout.com>; Added patches for FIPS 140-2; based on + - Ben Laurie <ben at algroup.co.uk>, Steve Marquess <marquess at ieee.org>; Add + support for OPENSSL FIPS mode 20070817 - (dtucker) [sshd.8] Many Linux variants use a single "!" to denote locked accounts and that's what the code looks for, so make man page and code --- openssh-4.7p1/cipher.c Mon Dec 17 18:46:43 2007 +++ openssh-4.7p1/cipher.c Mon Dec 24 04:15:12 2007 @@ -47,6 +47,7 @@ #include "xmalloc.h" #include "log.h" #include "cipher.h" +#include "fips.h" /* compatibility with old or broken OpenSSL versions */ #include "openbsd-compat/openssl-compat.h" @@ -64,30 +65,31 @@ u_int key_len; u_int discard_len; const EVP_CIPHER *(*evptype)(void); + u_int fips_allowed; } ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, 0, EVP_enc_null }, - { "des", SSH_CIPHER_DES, 8, 8, 0, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, 0, evp_ssh1_3des }, - { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, evp_ssh1_bf }, - - { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, EVP_des_ede3_cbc }, - { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_bf_cbc }, - { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_cast5_cbc }, - { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, EVP_rc4 }, - { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, EVP_rc4 }, - { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, EVP_rc4 }, - { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, EVP_aes_128_cbc }, - { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, EVP_aes_192_cbc }, - { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, + { "none", SSH_CIPHER_NONE, 8, 0, 0, EVP_enc_null, 0 }, + { "des", SSH_CIPHER_DES, 8, 8, 0, EVP_des_cbc, 0 }, + { "3des", SSH_CIPHER_3DES, 8, 16, 0, evp_ssh1_3des, 0 }, + { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, evp_ssh1_bf, 0 }, + + { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, EVP_des_ede3_cbc, 1 }, + { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_bf_cbc, 0 }, + { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_cast5_cbc, 0 }, + { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, EVP_rc4, 0 }, + { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, EVP_rc4, 0 }, + { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, EVP_rc4, 0 }, + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, EVP_aes_128_cbc, 1 }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, EVP_aes_192_cbc, 1 }, + { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc, 1 }, { "rijndael-cbc at lysator.liu.se", - SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, - { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr }, - { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_128_ctr }, - { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_128_ctr }, + SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc, 0 }, + { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr, 1 }, + { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_128_ctr, 1 }, + { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_128_ctr, 1 }, #ifdef USE_CIPHER_ACSS - { "acss at openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, EVP_acss }, + { "acss at openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, EVP_acss, 0 }, #endif - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, NULL } + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, NULL, 0 } }; /*--*/ @@ -156,6 +158,13 @@ for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); +#ifdef OPENSSL_FIPS + if (fips_mode && !(c->fips_allowed)) { + debug("cipher %s disallowed in FIPS mode [%s]", p, names); + xfree(cipher_list); + return 0; + } +#endif if (c == NULL || c->number != SSH_CIPHER_SSH2) { debug("bad cipher %s [%s]", p, names); xfree(cipher_list); @@ -291,9 +300,25 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher, const char *passphrase, int do_encrypt) { +#ifdef OPENSSL_FIPS + SHA_CTX sha; +#endif MD5_CTX md; - u_char digest[16]; + u_char digest[20]; +#ifdef OPENSSL_FIPS + if (fips_mode) { + SHA1_Init(&sha); + SHA1_Update(&sha, (const u_char *)passphrase, strlen(passphrase)); + SHA1_Final(digest, &sha); + + cipher_init(cc, cipher, digest, 20, NULL, 0, do_encrypt); + + memset(digest, 0, sizeof(digest)); + memset(&sha, 0, sizeof(sha)); + return; + } +#endif MD5_Init(&md); MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); MD5_Final(digest, &md); --- openssh-4.7p1/configure.ac Mon Dec 17 20:25:49 2007 +++ openssh-4.7p1/configure.ac Mon Dec 17 20:29:36 2007 @@ -438,6 +438,7 @@ if test -z "$GCC"; then CFLAGS="$CFLAGS -Ae" fi + HPUX=1 ;; *-*-hpux11*) AC_DEFINE(PAM_SUN_CODEBASE, 1, @@ -449,6 +450,7 @@ AC_DEFINE(USE_BTMP, 1, [Use btmp to log bad logins]) check_for_hpux_broken_getaddrinfo=1 check_for_conflicting_getspnam=1 + HPUX=1 ;; esac @@ -460,6 +462,7 @@ protected password database]) disable_ptmx_check=yes LIBS="$LIBS -lsecpw" + HPUX=1 ;; esac ;; @@ -1768,6 +1771,8 @@ case "$withval" in # Relative paths ./*|../*) withval="`pwd`/$withval" esac + ssldir=$withval + AC_SUBST(ssldir) if test -d "$withval/lib"; then if test -n "${need_dash_r}"; then @@ -2099,6 +2104,34 @@ ) fi + +# Check for OpenSSL FIPS mode +AC_ARG_WITH(fips, + [ --with-fips Enable OpenSSL FIPS mode ], + [ + if test "x$withval" != "xno" ; then + AC_CACHE_CHECK([for FIPS mode], ac_cv_fips, [ + AC_TRY_COMPILE( + [ #include <openssl/fips.h> ], + [ FIPS_mode_set(1); ], + [ ac_cv_fips="yes" ], + [ ac_cv_fips="no" ] + ) + ]) + fi + ] +) +if test "x$ac_cv_fips" = "xyes" ; then + CPPFLAGS="$CPPFLAGS -DOPENSSL_FIPS" + if test "x$HPUX" = "x" ; then + LIBS=`echo $LIBS | sed 's/-lcrypto /-Wl,-Bstatic -lcrypto -Wl,-Bdynamic /'` + else + LIBS=`echo $LIBS | sed 's/-lcrypto /-Wl,-aarchive -lcrypto -Wl,-adefault /'` + fi + FIPS_MODE=yes + AC_SUBST(FIPS_MODE) +fi + # Do we want to force the use of the rand helper? AC_ARG_WITH(rand-helper, [ --with-rand-helper Use subprocess to gather strong randomness ], diff -u -r1.1 -r1.3 --- openssh-4.7p1/mac.c Mon Dec 17 20:59:35 2007 +++ openssh-4.7p1/mac.c Mon Dec 17 21:01:42 2007 @@ -41,5 +41,6 @@ #include "kex.h" #include "mac.h" #include "misc.h" +#include "fips.h" #include "umac.h" @@ -54,15 +55,16 @@ int truncatebits; /* truncate digest if != 0 */ int key_len; /* just for UMAC */ int len; /* just for UMAC */ + int fips_allowed; } macs[] = { - { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, - { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 }, - { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 }, - { "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1, -1 }, - { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1, -1 }, - { "hmac-ripemd160 at openssh.com", SSH_EVP, EVP_ripemd160, 0, -1, -1 }, - { "umac-64 at openssh.com", SSH_UMAC, NULL, 0, 128, 64 }, - { NULL, 0, NULL, 0, -1, -1 } + { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1, 1 }, + { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1, 1 }, + { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1, 0 }, + { "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1, -1, 0 }, + { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1, -1, 0 }, + { "hmac-ripemd160 at openssh.com", SSH_EVP, EVP_ripemd160, 0, -1, -1, 0 }, + { "umac-64 at openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 }, + { NULL, 0, NULL, 0, -1, -1, 0 } }; static void @@ -91,6 +93,12 @@ for (i = 0; macs[i].name; i++) { if (strcmp(name, macs[i].name) == 0) { +#ifdef OPENSSL_FIPS + if (fips_mode && !macs[i].fips_allowed) { + debug2("mac_init: %s disallowed in fips mode", name); + return (-1); + } +#endif if (mac != NULL) mac_setup_by_id(mac, i); debug2("mac_setup: found %s", name); --- openssh-4.7p1/Makefile.in Tue Dec 18 02:42:38 2007 +++ openssh-4.7p1/Makefile.in Tue Dec 18 02:42:21 2007 @@ -18,6 +18,7 @@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ +ssldir=@ssldir@ DESTDIR VPATH=@srcdir@ @@ -29,6 +30,7 @@ PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ STRIP_OPT=@STRIP_OPT@ +FIPS_MODE=@FIPS_MODE@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ @@ -252,12 +254,18 @@ $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir) (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH)) $(INSTALL) -m 0755 $(STRIP_OPT) ssh $(DESTDIR)$(bindir)/ssh + if [ ! -z "FIPS_MODE" ]; then \ + $(INSTALL) -m 0755 $(STRIP_OPT) ssh $(DESTDIR)$(bindir)/ssh.sha1; \ + fi $(INSTALL) -m 0755 $(STRIP_OPT) scp $(DESTDIR)$(bindir)/scp $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add $(DESTDIR)$(bindir)/ssh-add $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent $(DESTDIR)$(bindir)/ssh-agent $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan $(INSTALL) -m 0755 $(STRIP_OPT) sshd $(DESTDIR)$(sbindir)/sshd + if [ ! -z "FIPS_MODE" ]; then \ + $(INSTALL) -m 0755 $(STRIP_OPT) sshd $(DESTDIR)$(bindir)/sshd.sha1; \ + fi if test ! -z "$(INSTALL_SSH_RAND_HELPER)" ; then \ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-rand-helper $(DESTDIR)$(libexecdir)/ssh-rand-helper ; \ fi diff -u -r1.1 -r1.3 --- openssh-4.7p1/myproposal.h Mon Dec 17 21:07:18 2007 +++ openssh-4.7p1/myproposal.h Mon Dec 17 21:09:50 2007 @@ -41,6 +41,7 @@ #endif #define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss" +#ifndef OPENSSL_FIPS #define KEX_DEFAULT_ENCRYPT \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ "arcfour128,arcfour256,arcfour," \ @@ -50,6 +51,16 @@ "hmac-md5,hmac-sha1,umac-64 at openssh.com,hmac-ripemd160," \ "hmac-ripemd160 at openssh.com," \ "hmac-sha1-96,hmac-md5-96" +#else + #define KEX_DEFAULT_ENCRYPT \ + "aes128-cbc,3des-cbc," \ + "aes192-cbc,aes256-cbc,rijndael-cbc at lysator.liu.se," \ + "aes128-ctr,aes192-ctr,aes256-ctr" + #define KEX_DEFAULT_MAC \ + "hmac-sha1," \ + "hmac-sha1-96" +#endif + #define KEX_DEFAULT_COMP "none,zlib at openssh.com,zlib" #define KEX_DEFAULT_LANG "" --- openssh-4.7p1/readconf.h Mon Dec 17 03:35:58 2007 +++ openssh-4.7p1/readconf.h Mon Dec 17 03:53:57 2007 @@ -120,6 +120,7 @@ char *local_command; int permit_local_command; + int fips_mode; } Options; --- openssh-4.7p1/servconf.h Mon Dec 17 04:25:51 2007 +++ openssh-4.7p1/servconf.h Mon Dec 17 04:26:31 2007 @@ -141,6 +141,7 @@ int permit_tun; int num_permitted_opens; + int fips_mode; } ServerOptions; void initialize_server_options(ServerOptions *); --- openssh-4.7p1/readconf.c Mon Dec 17 03:46:49 2007 +++ openssh-4.7p1/readconf.c Fri Dec 21 15:40:50 2007 @@ -130,6 +130,7 @@ oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oFipsMode, oDeprecated, oUnsupported } OpCodes; @@ -226,6 +227,7 @@ { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, + { "fipsmode", oFipsMode}, { NULL, oBadOption } }; @@ -915,6 +917,10 @@ intptr = &options->permit_local_command; goto parse_flag; + case oFipsMode: + intptr = &options->fips_mode; + goto parse_flag; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -1065,6 +1071,7 @@ options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; + options->fips_mode = -1; } /* @@ -1132,9 +1139,9 @@ /* Selected in ssh_login(). */ if (options->cipher == -1) options->cipher = SSH_CIPHER_NOT_SET; - /* options->ciphers, default set in myproposals.h */ - /* options->macs, default set in myproposals.h */ - /* options->hostkeyalgorithms, default set in myproposals.h */ + /* options->ciphers, default set in myproposal.h */ + /* options->macs, default set in myproposal.h */ + /* options->hostkeyalgorithms, default set in myproposal.h */ if (options->protocol == SSH_PROTO_UNKNOWN) options->protocol = SSH_PROTO_1|SSH_PROTO_2; if (options->num_identity_files == 0) { @@ -1199,6 +1206,10 @@ options->tun_remote = SSH_TUNID_ANY; if (options->permit_local_command == -1) options->permit_local_command = 0; + if (options->fips_mode == -1) + options->fips_mode = 0; + if (options->fips_mode && options->macs == NULL) + options->macs = "hmac-sha1,hmac-sha1-96"; /* options->local_command should not be set by default */ /* options->proxy_command should not be set by default */ /* options->user will be set in the main program if appropriate */ --- openssh-4.7p1/servconf.c Mon Dec 17 04:25:51 2007 +++ openssh-4.7p1/servconf.c Fri Dec 21 15:59:15 2007 @@ -104,7 +104,11 @@ options->num_allow_groups = 0; options->num_deny_groups = 0; options->ciphers = NULL; +#ifdef OPENSSL_FIPS + options->macs = "hmac-sha1,hmac-sha1-96"; +#else options->macs = NULL; +#endif options->protocol = SSH_PROTO_UNKNOWN; options->gateway_ports = -1; options->num_subsystems = 0; @@ -122,8 +126,10 @@ options->permit_tun = -1; options->num_permitted_opens = -1; options->adm_forced_command = NULL; + options->fips_mode = -1; } + void fill_default_server_options(ServerOptions *options) { @@ -249,6 +255,8 @@ options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; + if (options->fips_mode == -1) + options->fips_mode = 0; /* Turn privilege separation on by default */ if (use_privsep == -1) @@ -293,6 +301,7 @@ sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sUsePrivilegeSeparation, + sFipsMode, sDeprecated, sUnsupported } ServerOpCodes; @@ -403,6 +412,7 @@ { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, { "forcecommand", sForceCommand, SSHCFG_ALL }, + { "fipsmode", sFipsMode, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -1253,6 +1263,10 @@ options->adm_forced_command = xstrdup(cp + len); return 0; + case sFipsMode: + intptr = &options->fips_mode; + goto parse_flag; + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); --- openssh-4.7p1/ssh.c Mon Dec 17 03:23:08 2007 +++ openssh-4.7p1/ssh.c Fri Dec 21 15:55:04 2007 @@ -72,6 +72,11 @@ #include <openssl/evp.h> #include <openssl/err.h> +#ifdef OPENSSL_FIPS +#include <openssl/fips.h> +#include <openssl/rand.h> +#include <openssl/fips_rand.h> +#endif #include "xmalloc.h" #include "ssh.h" @@ -100,6 +105,16 @@ #include "monitor_fdpass.h" #include "uidswap.h" #include "version.h" +#include "fips.h" + +/* + * FIPS mode operation +*/ +#ifdef OPENSSL_FIPS + int fips_mode = 1; //refined later +#else + int fips_mode = 0; +#endif #ifdef SMARTCARD #include "scard.h" @@ -180,12 +195,17 @@ u_int control_server_pid = 0; /* Prints a help message to the user. This function never returns. */ +#ifdef OPENSSL_FIPS +# define FIPS_OPTS "y" +#else +# define FIPS_OPTS +#endif static void usage(void) { fprintf(stderr, -"usage: ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n" +"usage: ssh [-1246AaCfgKkMNnqsTtVvXx" FIPS_OPTS "Y] [-b bind_address] [-c cipher_spec]\n" " [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" " [-i identity_file] [-L [bind_address:]port:host:hostport]\n" " [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" @@ -272,8 +292,13 @@ again: while ((opt = getopt(ac, av, - "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) !-1) { + "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:X" FIPS_OPTS "Y")) != -1) { switch (opt) { +#ifdef OPENSSL_FIPS + case 'y': + fips_mode = 0; + break; +#endif case '1': options.protocol = SSH_PROTO_1; break; @@ -637,6 +662,36 @@ log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); seed_rng(); +#ifdef OPENSSL_FIPS +/* + Priority setting: + !command line + env OPENSSH_FIPS + !env OPENSSH_NO_FIPS + ssh_config options (default: false) +*/ + if (fips_mode) { /* !command line */ + if (getenv("OPENSSH_FIPS")) { /* env OPENSSH_FIPS */ + } + else if (getenv("OPENSSH_NO_FIPS")) { /* !env OPENSSH_NO_FIPS */ + fips_mode = 0; + } + else if (options.fips_mode == 0) { /* ssh_config options */ + fips_mode = 0; + } + } + if(fips_mode) + { + if(!FIPS_mode_set(1)) + { + ERR_load_crypto_strings(); + ERR_print_errors_fp(stderr); + exit(1); + } + else + fprintf(stderr,"*** IN FIPS MODE ***\n"); + } +#endif if (options.user == NULL) options.user = xstrdup(pw->pw_name);
--- openssh-4.7p1/sshd.c Mon Dec 31 05:14:10 2007
+++ openssh-4.7p1/sshd.c Mon Dec 31 17:25:36 2007
@@ -75,6 +75,12 @@
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
+#ifdef OPENSSL_FIPS
+#include <fips.h>
+#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
+#endif
+
#ifdef HAVE_SECUREWARE
#include <sys/security.h>
#include <prot.h>
@@ -136,6 +142,14 @@
extern char *__progname;
+/* FIPS mode operation indicator */
+#ifdef OPENSSL_FIPS
+ int fips_mode = 1; //refined later
+#else
+ int fips_mode = 0;
+#endif
+
+
/* Server configuration options. */
ServerOptions options;
@@ -419,7 +433,11 @@
major = PROTOCOL_MAJOR_1;
minor = PROTOCOL_MINOR_1;
}
+#ifndef OPENSSL_FIPS
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor,
SSH_VERSION);
+#else
+ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s FIPS\n", major, minor,
SSH_VERSION);
+#endif
server_version_string = xstrdup(buf);
/* Send our protocol version identification. */
@@ -582,15 +600,24 @@
privsep_preauth_child(void)
{
u_int32_t rnd[256];
+ u_char* buf=(u_char*)rnd;
gid_t gidset[1];
int i;
/* Enable challenge-response authentication for privilege separation
*/
privsep_challenge_enable();
+#ifndef OPENSSL_FIPS
for (i = 0; i < 256; i++)
rnd[i] = arc4random();
RAND_seed(rnd, sizeof(rnd));
+#else
+ for (i = 0; i < 6; i++)
+ rnd[i] = arc4random();
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
/* Demote the private keys to public keys. */
demote_sensitive_data();
@@ -621,12 +648,26 @@
{
int status;
pid_t pid;
+#ifdef OPENSSL_FIPS
+// u_int32_t rnd[6], i;
+// u_char* buf=(u_char*)rnd;
+ u_char buf[24];
+#endif
/* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */
pmonitor->m_pkex = &xxx_kex;
+#ifdef OPENSSL_FIPS
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("privsep_preauth: RAND_bytes failed");
+ }
+// for (i = 0; i < 6; i++)
+// rnd[i] = arc4random();
+#endif
pid = fork();
if (pid == -1) {
fatal("fork of unprivileged child failed");
@@ -648,6 +689,13 @@
return (1);
} else {
/* child */
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
close(pmonitor->m_sendfd);
@@ -662,6 +710,11 @@
static void
privsep_postauth(Authctxt *authctxt)
{
+#ifdef OPENSSL_FIPS
+// u_int32_t rnd[6], i;
+// u_char* buf=(u_char*)rnd;
+ u_char buf[24];
+#endif
#ifdef DISABLE_FD_PASSING
if (1) {
#else
@@ -675,6 +728,15 @@
/* New socket pair */
monitor_reinit(pmonitor);
+#ifdef OPENSSL_FIPS
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("privsep_postauth: RAND_bytes failed");
+ }
+// for (i = 0; i < 6; i++)
+// rnd[i] = arc4random();
+#endif
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
fatal("fork of unprivileged child failed");
@@ -687,7 +749,13 @@
/* NEVERREACHED */
exit(0);
}
-
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
close(pmonitor->m_sendfd);
/* Demote the private keys to public keys. */
@@ -1015,6 +1083,11 @@
struct sockaddr_storage from;
socklen_t fromlen;
pid_t pid;
+#ifdef OPENSSL_FIPS
+// u_int32_t rnd[6], k;
+// u_char* buf=(u_char*)rnd;
+ u_char buf[24];
+#endif
/* setup fd set for accept */
fdset = NULL;
@@ -1147,6 +1220,15 @@
break;
}
+#ifdef OPENSSL_FIPS
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("server_accept_loop: RAND_bytes failed");
+ }
+// for (k = 0; k < 6; k++)
+// rnd[k] = arc4random();
+#endif
/*
* Normal production daemon. Fork, and have
* the child process the connection. The
@@ -1163,6 +1245,13 @@
* the connection.
*/
platform_post_fork_child();
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
startup_pipe = startup_p[1];
close_startup_pipes();
close_listen_socks();
@@ -1421,6 +1510,36 @@
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
+#ifdef OPENSSL_FIPS
+/*
+ Priority setting:
+ env OPENSSH_FIPS
+ !env OPENSSH_NO_FIPS
+ sshd_config options (default: false)
+*/
+ if (fips_mode) {
+ if (getenv("OPENSSH_FIPS")) { /* env OPENSSH_FIPS */
+ }
+ else if (getenv("OPENSSH_NO_FIPS")) { /* !env
OPENSSH_NO_FIPS */
+ fips_mode = 0;
+ }
+ else if (options.fips_mode == 0) { /* sshd_config
options */
+ fips_mode = 0;
+ }
+ }
+ if(fips_mode)
+ {
+ if(!FIPS_mode_set(1))
+ {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+ else
+ fprintf(stderr,"*** IN FIPS MODE ***\n");
+ }
+#endif
+
/* challenge-response is implemented via keyboard interactive */
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
@@ -1572,9 +1691,28 @@
#ifdef TIOCNOTTY
int fd;
#endif /* TIOCNOTTY */
+#ifdef OPENSSL_FIPS
+// u_int32_t rnd[6], k;
+// u_char* buf=(u_char*)rnd;
+ u_char buf[24];
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("privsep_preauth: RAND_bytes failed");
+ }
+// for (i = 0; i < 6; i++)
+// rnd[i] = arc4random();
+#endif
if (daemon(0, 0) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
/* Disconnect from the controlling tty. */
#ifdef TIOCNOTTY
fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
--- openssh-4.7p1/ssh-keygen.c Tue Dec 18 02:43:34 2007
+++ openssh-4.7p1/ssh-keygen.c Wed Dec 26 17:38:59 2007
@@ -47,6 +47,14 @@
#include "match.h"
#include "hostfile.h"
#include "dns.h"
+#include "fips.h"
+
+/*
+ * FIPS mode operation
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
#ifdef SMARTCARD
#include "scard.h"
@@ -1067,6 +1075,14 @@
extern int optind;
extern char *optarg;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode = 1;
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
+
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -1435,7 +1451,7 @@
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
+ char *fp = key_fingerprint(public, dgst_type, SSH_FP_HEX);
printf("Your public key has been saved in %s.\n",
identity_file);
printf("The key fingerprint is:\n");
--- openssh-4.7p1/ssh-keysign.c Tue Dec 18 02:43:37 2007
+++ openssh-4.7p1/ssh-keysign.c Wed Dec 26 18:07:17 2007
@@ -52,6 +52,15 @@
#include "pathnames.h"
#include "readconf.h"
#include "uidswap.h"
+#include "fips.h"
+
+/*
+ * FIPS operational mode
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
+
/* XXX readconf.c needs these */
uid_t original_real_uid;
@@ -158,6 +167,10 @@
u_int slen, dlen;
u_int32_t rnd[256];
+#ifdef OPENSSL_FIPS
+ if ( getenv("OPENSSH_FIPS") ) fips_mode = 1;
+#endif
+
/* Ensure that stdin and stdout are connected */
if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
exit(1);
--- openssh-4.7p1/ssh-keyscan.c Tue Dec 18 02:43:36 2007
+++ openssh-4.7p1/ssh-keyscan.c Wed Dec 26 18:05:15 2007
@@ -45,6 +45,14 @@
#include "atomicio.h"
#include "misc.h"
#include "hostfile.h"
+#include "fips.h"
+
+/*
+ * FIPS mode operation
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
/* Flag indicating whether IPv4 or IPv6. This can be set on the
command line.
Default value is AF_UNSPEC means both IPv4 and IPv6. */
@@ -729,6 +737,10 @@
extern int optind;
extern char *optarg;
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode = 1;
+#endif
+
__progname = ssh_get_progname(argv[0]);
init_rng();
seed_rng();
--- openssh-4.7p1/fips.h Tue Dec 18 03:32:54 2007
+++ openssh-4.7p1/fips.h Tue Dec 18 03:30:50 2007
@@ -0,0 +1,3 @@
+/* $OpenBSD: version.h,v 1.40 2004/02/23 15:16:46 markus Exp $ */
+
+extern int fips_mode;
--- openssh-4.7p1/openbsd-compat/bsd-arc4random.c Thu Dec 20 13:04:50
2007
+++ openssh-4.7p1/openbsd-compat/bsd-arc4random.c Thu Dec 20 16:39:10
2007
@@ -29,6 +29,11 @@
#include <openssl/rc4.h>
#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include "fips.h"
+#endif
+
+
/* Size of key to use */
#define SEED_SIZE 20
@@ -45,13 +50,27 @@
static int first_time = 1;
if (rc4_ready <= 0) {
+#ifndef OPENSSL_FIPS
if (first_time)
seed_rng();
+#endif
first_time = 0;
arc4random_stir();
}
- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ if (RAND_bytes(&r,sizeof(r)) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ return 1/0;
+ }
+ rc4_ready -= sizeof(r);
+
+ return(r);
+ }
+#endif
+ RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char
*)&r);
rc4_ready -= sizeof(r);
@@ -64,6 +83,13 @@
unsigned char rand_buf[SEED_SIZE];
int i;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ rc4_ready = REKEY_BYTES;
+ return;
+ }
+#endif
+
memset(&rc4, 0, sizeof(rc4));
if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
fatal("Couldn't obtain random bytes (error %ld)",
--- openssh-4.7p1/ssh-rand-helper.c Thu Dec 20 13:15:00 2007
+++ openssh-4.7p1/ssh-rand-helper.c Wed Dec 26 18:10:50 2007
@@ -62,6 +62,14 @@
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
+#include "fips.h"
+
+/*
+ * FIPS operational mode
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
/* Number of bytes we write out */
#define OUTPUT_SEED_SIZE 48
@@ -820,6 +828,10 @@
extern char *optarg;
LogLevel ll;
+#ifdef OPENSSL_FIPS
+ if ( getenv("OPENSSH_FIPS") ) fips_mode = 1;
+#endif
+
__progname = ssh_get_progname(argv[0]);
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
--- openssh-4.7p1/buffer.c Thu Dec 20 12:55:07 2007
+++ openssh-4.7p1/buffer.c Thu Dec 20 12:55:38 2007
@@ -175,7 +175,8 @@
len, buffer->end - buffer->offset);
return (-1);
}
- memcpy(buf, buffer->buf + buffer->offset, len);
+ if (len > 0)
+ memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
return (0);
}
--- openssh-4.7p1/sshconnect.c Thu Dec 20 15:23:57 2007
+++ openssh-4.7p1/sshconnect.c Thu Dec 20 15:40:26 2007
@@ -57,6 +57,7 @@
#include "misc.h"
#include "dns.h"
#include "version.h"
+#include "fips.h"
char *client_version_string = NULL;
char *server_version_string = NULL;
@@ -545,6 +546,12 @@
char msg[1024];
int len, host_line, ip_line;
const char *host_file = NULL, *ip_file = NULL;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
/*
* Force accepting of the host key for loopback/localhost. The
@@ -708,7 +735,7 @@
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, dgst_type, SSH_FP_HEX);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@@ -999,11 +1006,17 @@
Key *found;
char *fp;
int line, ret;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
found = key_new(keytype);
if ((ret = lookup_key_in_hostfile_by_type(file, host,
keytype, found, &line))) {
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, dgst_type, SSH_FP_HEX);
logit("WARNING: %s key found for host %s\n"
"in %s:%d\n"
"%s key fingerprint %s.",
@@ -1053,8 +1086,14 @@
{
char *fp;
const char *type = key_type(host_key);
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, dgst_type, SSH_FP_HEX);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
@");
--- openssh-4.7p1/sshconnect2.c Mon Dec 24 13:14:28 2007
+++ openssh-4.7p1/sshconnect2.c Mon Dec 24 13:17:06 2007
@@ -64,6 +64,7 @@
#include "msg.h"
#include "pathnames.h"
#include "uidswap.h"
+#include "fips.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -433,6 +434,12 @@
u_int alen, blen;
char *pkalg, *fp;
u_char *pkblob;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
if (authctxt == NULL)
fatal("input_userauth_pk_ok: no authentication context");
@@ -466,7 +473,7 @@
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, dgst_type, SSH_FP_HEX);
debug2("input_userauth_pk_ok: fp %s", fp);
xfree(fp);
--- openssh-4.7p1/auth2-pubkey.c Thu Dec 20 15:18:22 2007
+++ openssh-4.7p1/auth2-pubkey.c Sun Dec 23 21:42:40 2007
@@ -52,6 +52,9 @@
#endif
#include "monitor_wrap.h"
#include "misc.h"
+#ifdef OPENSSL_FIPS
+#include "fips.h"
+#endif
/* import */
extern ServerOptions options;
@@ -186,6 +189,14 @@
struct stat st;
Key *found;
char *fp;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
+
+
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
@@ -250,7 +261,7 @@
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, dgst_type, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
--- openssh-4.7p1/auth-rsa.c Thu Dec 20 15:18:22 2007
+++ openssh-4.7p1/auth-rsa.c Wed Jan 2 17:01:42 2008
@@ -21,6 +21,7 @@
#include <openssl/rsa.h>
#include <openssl/md5.h>
+#include <openssl/fips_sha.h>
#include <pwd.h>
#include <stdio.h>
@@ -47,6 +48,9 @@
#include "monitor_wrap.h"
#include "ssh.h"
#include "misc.h"
+#ifdef OPENSSL_FIPS
+#include "fips.h"
+#endif
/* import */
extern ServerOptions options;
@@ -88,10 +92,11 @@
}
int
-auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char
response[16])
+auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char
response[20])
{
- u_char buf[32], mdbuf[16];
+ u_char buf[40], mdbuf[16], shabuf[20];
MD5_CTX md;
+ SHA_CTX sha;
int len;
/* don't allow short keys */
@@ -101,10 +106,37 @@
return (0);
}
- /* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
+ if (len <= 0 || len > 40)
+ fatal("auth_rsa_verify_response: bad challenge length %d", len);
+
+ /* The response is SHA1 of decrypted challenge plus session id. */
+ memset(buf, 0, 40);
+ BN_bn2bin(challenge, buf + 40 - len);
+ SHA1_Init(&sha);
+ SHA1_Update(&sha, buf, 40);
+ SHA1_Update(&sha, session_id, 16);
+ SHA1_Final(shabuf, &sha);
+
+ /* Verify that the response is the original challenge. */
+ if (memcmp(response, shabuf, 20) != 0) {
+ /* Wrong answer. */
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ return (0);
+ }
+#endif
+ }
+
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ return (1);
+ }
+#endif
+
if (len <= 0 || len > 32)
fatal("auth_rsa_verify_response: bad challenge length %d", len);
+ /* The response is MD5 of decrypted challenge plus session id. */
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
@@ -131,7 +163,7 @@
auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
- u_char response[16];
+ u_char response[20];
int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
@@ -153,6 +185,10 @@
packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
for (i = 0; i < 16; i++)
response[i] = (u_char)packet_get_char();
+#ifdef OPENSSL_FIPS
+ for (i = 16; i < 20; i++)
+ response[i] = (u_char)packet_get_char();
+#endif
packet_check_eom();
success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
@@ -304,6 +340,12 @@
Key *key;
char *fp;
struct passwd *pw = authctxt->pw;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
/* no user given */
if (!authctxt->valid)
@@ -332,7 +374,7 @@
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, dgst_type, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(key), fp);
xfree(fp);
--- openssh-4.7p1/contrib/redhat/sshd.init Mon Dec 24 13:44:26 2007
+++ openssh-4.7p1/contrib/redhat/sshd.init Wed Dec 26 13:08:06 2007
@@ -24,7 +24,11 @@
# Some functions to make the below more readable
KEYGEN=/usr/bin/ssh-keygen
SSHD=/usr/sbin/sshd
-RSA1_KEY=/etc/ssh/ssh_host_key
+if [ "$OPENSSH_FIPS" ] ; then
+ EXTRA_SSH_KEYGEN_RSA_FLAGS="-b 2048"
+else
+ RSA1_KEY=/etc/ssh/ssh_host_key
+fi
RSA_KEY=/etc/ssh/ssh_host_rsa_key
DSA_KEY=/etc/ssh/ssh_host_dsa_key
PID_FILE=/var/run/sshd.pid
@@ -32,7 +36,7 @@
do_rsa1_keygen() {
if [ ! -s $RSA1_KEY ]; then
echo -n $"Generating SSH1 RSA host key: "
- if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N ''
>&/dev/null; then
+ if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N ''
$EXTRA_SSH_KEYGEN_RSA_FLAGS >&/dev/null; then
chmod 600 $RSA1_KEY
chmod 644 $RSA1_KEY.pub
if [ -x /sbin/restorecon ]; then
@@ -51,7 +55,7 @@
do_rsa_keygen() {
if [ ! -s $RSA_KEY ]; then
echo -n $"Generating SSH2 RSA host key: "
- if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N ''
>&/dev/null; then
+ if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N ''
$EXTRA_SSH_KEYGEN_RSA_FLAGS >&/dev/null; then
chmod 600 $RSA_KEY
chmod 644 $RSA_KEY.pub
if [ -x /sbin/restorecon ]; then
@@ -70,7 +74,7 @@
do_dsa_keygen() {
if [ ! -s $DSA_KEY ]; then
echo -n $"Generating SSH2 DSA host key: "
- if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N ''
>&/dev/null; then
+ if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N ''
$EXTRA_SSH_KEYGEN_DSA_FLAGS >&/dev/null; then
chmod 600 $DSA_KEY
chmod 644 $DSA_KEY.pub
if [ -x /sbin/restorecon ]; then
--- openssh-4.7p1/ssh-add.c Wed Dec 26 17:25:22 2007
+++ openssh-4.7p1/ssh-add.c Wed Dec 26 17:35:52 2007
@@ -61,10 +61,18 @@
#include "authfile.h"
#include "pathnames.h"
#include "misc.h"
+#include "fips.h"
/* argv0 */
extern char *__progname;
+/*
+ * FIPS mode operation
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
+
/* Default files to add */
static char *default_files[] = {
_PATH_SSH_CLIENT_ID_RSA,
@@ -337,6 +345,10 @@
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode=1;
+#endif
+
__progname = ssh_get_progname(argv[0]);
init_rng();
seed_rng();
--- openssh-4.7p1/ssh-agent.c Wed Dec 26 18:09:26 2007
+++ openssh-4.7p1/ssh-agent.c Wed Dec 26 18:17:05 2007
@@ -74,6 +74,14 @@
#include "compat.h"
#include "log.h"
#include "misc.h"
+#include "fips.h"
+
+/*
+ * FIPS operational mode
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
#ifdef SMARTCARD
#include "scard.h"
@@ -1047,6 +1055,10 @@
char pidstrbuf[1 + 3 * sizeof pid];
struct timeval *tvp = NULL;
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode = 1;
+#endif
+
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
On Mon, Apr 21, 2008 at 07:08:18PM +0300, Oren Nechushtan wrote:> +#ifdef OPENSSL_FIPS > +// u_int32_t rnd[6], i; > +// u_char* buf=(u_char*)rnd; > + u_char buf[24]; > +#endif..> +// for (i = 0; i < 6; i++) > +// rnd[i] = arc4random(); > +#endifNot so nice to add so many comments. //Peter
Part 2
--- openssh-4.7p1/sshd.c Mon Dec 31 05:14:10 2007
+++ openssh-4.7p1/sshd.c Mon Dec 31 17:25:36 2007
@@ -75,6 +75,12 @@
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
+#ifdef OPENSSL_FIPS
+#include <fips.h>
+#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
+#endif
+
#ifdef HAVE_SECUREWARE
#include <sys/security.h>
#include <prot.h>
@@ -136,6 +142,14 @@
extern char *__progname;
+/* FIPS mode operation indicator */
+#ifdef OPENSSL_FIPS
+ int fips_mode = 1; //refined later
+#else
+ int fips_mode = 0;
+#endif
+
+
/* Server configuration options. */
ServerOptions options;
@@ -419,7 +433,11 @@
major = PROTOCOL_MAJOR_1;
minor = PROTOCOL_MINOR_1;
}
+#ifndef OPENSSL_FIPS
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor,
SSH_VERSION);
+#else
+ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s FIPS\n", major, minor,
SSH_VERSION);
+#endif
server_version_string = xstrdup(buf);
/* Send our protocol version identification. */
@@ -582,15 +600,24 @@
privsep_preauth_child(void)
{
u_int32_t rnd[256];
+ u_char* buf=(u_char*)rnd;
gid_t gidset[1];
int i;
/* Enable challenge-response authentication for privilege separation
*/
privsep_challenge_enable();
+#ifndef OPENSSL_FIPS
for (i = 0; i < 256; i++)
rnd[i] = arc4random();
RAND_seed(rnd, sizeof(rnd));
+#else
+ for (i = 0; i < 6; i++)
+ rnd[i] = arc4random();
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
/* Demote the private keys to public keys. */
demote_sensitive_data();
@@ -621,12 +648,22 @@
{
int status;
pid_t pid;
+#ifdef OPENSSL_FIPS
+ u_char buf[24];
+#endif
/* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */
pmonitor->m_pkex = &xxx_kex;
+#ifdef OPENSSL_FIPS
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("privsep_preauth: RAND_bytes failed");
+ }
+#endif
pid = fork();
if (pid == -1) {
fatal("fork of unprivileged child failed");
@@ -648,6 +685,13 @@
return (1);
} else {
/* child */
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
close(pmonitor->m_sendfd);
@@ -662,6 +706,9 @@
static void
privsep_postauth(Authctxt *authctxt)
{
+#ifdef OPENSSL_FIPS
+ u_char buf[24];
+#endif
#ifdef DISABLE_FD_PASSING
if (1) {
#else
@@ -675,6 +722,13 @@
/* New socket pair */
monitor_reinit(pmonitor);
+#ifdef OPENSSL_FIPS
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("privsep_postauth: RAND_bytes failed");
+ }
+#endif
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
fatal("fork of unprivileged child failed");
@@ -687,7 +741,13 @@
/* NEVERREACHED */
exit(0);
}
-
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
close(pmonitor->m_sendfd);
/* Demote the private keys to public keys. */
@@ -1015,6 +1075,9 @@
struct sockaddr_storage from;
socklen_t fromlen;
pid_t pid;
+#ifdef OPENSSL_FIPS
+ u_char buf[24];
+#endif
/* setup fd set for accept */
fdset = NULL;
@@ -1147,6 +1210,13 @@
break;
}
+#ifdef OPENSSL_FIPS
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("server_accept_loop: RAND_bytes failed");
+ }
+#endif
/*
* Normal production daemon. Fork, and have
* the child process the connection. The
@@ -1163,6 +1233,13 @@
* the connection.
*/
platform_post_fork_child();
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
startup_pipe = startup_p[1];
close_startup_pipes();
close_listen_socks();
@@ -1421,6 +1498,36 @@
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
+#ifdef OPENSSL_FIPS
+/*
+ Priority setting:
+ env OPENSSH_FIPS
+ !env OPENSSH_NO_FIPS
+ sshd_config options (default: false)
+*/
+ if (fips_mode) {
+ if (getenv("OPENSSH_FIPS")) { /* env OPENSSH_FIPS */
+ }
+ else if (getenv("OPENSSH_NO_FIPS")) { /* !env
OPENSSH_NO_FIPS */
+ fips_mode = 0;
+ }
+ else if (options.fips_mode == 0) { /* sshd_config
options */
+ fips_mode = 0;
+ }
+ }
+ if(fips_mode)
+ {
+ if(!FIPS_mode_set(1))
+ {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+ else
+ fprintf(stderr,"*** IN FIPS MODE ***\n");
+ }
+#endif
+
/* challenge-response is implemented via keyboard interactive */
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
@@ -1572,9 +1679,24 @@
#ifdef TIOCNOTTY
int fd;
#endif /* TIOCNOTTY */
+#ifdef OPENSSL_FIPS
+ u_char buf[24];
+ if(RAND_bytes(buf,sizeof buf) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ fatal("privsep_preauth: RAND_bytes failed");
+ }
+#endif
if (daemon(0, 0) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
+#ifdef OPENSSL_FIPS
+ FIPS_rand_method()->cleanup();
+ /* Always automagically seed PRNG */
+ FIPS_set_prng_key(buf,buf+8);
+ FIPS_rand_seed(buf+16,8);
+ debug2("FIPS rand reseeded");
+#endif
/* Disconnect from the controlling tty. */
#ifdef TIOCNOTTY
fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
--- openssh-4.7p1/ssh-keygen.c Tue Dec 18 02:43:34 2007
+++ openssh-4.7p1/ssh-keygen.c Wed Dec 26 17:38:59 2007
@@ -47,6 +47,14 @@
#include "match.h"
#include "hostfile.h"
#include "dns.h"
+#include "fips.h"
+
+/*
+ * FIPS mode operation
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
#ifdef SMARTCARD
#include "scard.h"
@@ -1067,6 +1075,14 @@
extern int optind;
extern char *optarg;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode = 1;
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
+
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -1435,7 +1451,7 @@
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
+ char *fp = key_fingerprint(public, dgst_type, SSH_FP_HEX);
printf("Your public key has been saved in %s.\n",
identity_file);
printf("The key fingerprint is:\n");
--- openssh-4.7p1/ssh-keysign.c Tue Dec 18 02:43:37 2007
+++ openssh-4.7p1/ssh-keysign.c Wed Dec 26 18:07:17 2007
@@ -52,6 +52,15 @@
#include "pathnames.h"
#include "readconf.h"
#include "uidswap.h"
+#include "fips.h"
+
+/*
+ * FIPS operational mode
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
+
/* XXX readconf.c needs these */
uid_t original_real_uid;
@@ -158,6 +167,10 @@
u_int slen, dlen;
u_int32_t rnd[256];
+#ifdef OPENSSL_FIPS
+ if ( getenv("OPENSSH_FIPS") ) fips_mode = 1;
+#endif
+
/* Ensure that stdin and stdout are connected */
if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
exit(1);
--- openssh-4.7p1/ssh-keyscan.c Tue Dec 18 02:43:36 2007
+++ openssh-4.7p1/ssh-keyscan.c Wed Dec 26 18:05:15 2007
@@ -45,6 +45,14 @@
#include "atomicio.h"
#include "misc.h"
#include "hostfile.h"
+#include "fips.h"
+
+/*
+ * FIPS mode operation
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
/* Flag indicating whether IPv4 or IPv6. This can be set on the
command line.
Default value is AF_UNSPEC means both IPv4 and IPv6. */
@@ -729,6 +737,10 @@
extern int optind;
extern char *optarg;
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode = 1;
+#endif
+
__progname = ssh_get_progname(argv[0]);
init_rng();
seed_rng();
--- openssh-4.7p1/fips.h Tue Dec 18 03:32:54 2007
+++ openssh-4.7p1/fips.h Tue Dec 18 03:30:50 2007
@@ -0,0 +1,3 @@
+/* $OpenBSD: version.h,v 1.40 2004/02/23 15:16:46 markus Exp $ */
+
+extern int fips_mode;
--- openssh-4.7p1/openbsd-compat/bsd-arc4random.c Thu Dec 20 13:04:50
2007
+++ openssh-4.7p1/openbsd-compat/bsd-arc4random.c Thu Dec 20 16:39:10
2007
@@ -29,6 +29,11 @@
#include <openssl/rc4.h>
#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include "fips.h"
+#endif
+
+
/* Size of key to use */
#define SEED_SIZE 20
@@ -45,13 +50,27 @@
static int first_time = 1;
if (rc4_ready <= 0) {
+#ifndef OPENSSL_FIPS
if (first_time)
seed_rng();
+#endif
first_time = 0;
arc4random_stir();
}
- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ if (RAND_bytes(&r,sizeof(r)) <= 0) {
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ return 1/0;
+ }
+ rc4_ready -= sizeof(r);
+
+ return(r);
+ }
+#endif
+ RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char
*)&r);
rc4_ready -= sizeof(r);
@@ -64,6 +83,13 @@
unsigned char rand_buf[SEED_SIZE];
int i;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ rc4_ready = REKEY_BYTES;
+ return;
+ }
+#endif
+
memset(&rc4, 0, sizeof(rc4));
if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
fatal("Couldn't obtain random bytes (error %ld)",
--- openssh-4.7p1/ssh-rand-helper.c Thu Dec 20 13:15:00 2007
+++ openssh-4.7p1/ssh-rand-helper.c Wed Dec 26 18:10:50 2007
@@ -62,6 +62,14 @@
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
+#include "fips.h"
+
+/*
+ * FIPS operational mode
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
/* Number of bytes we write out */
#define OUTPUT_SEED_SIZE 48
@@ -820,6 +828,10 @@
extern char *optarg;
LogLevel ll;
+#ifdef OPENSSL_FIPS
+ if ( getenv("OPENSSH_FIPS") ) fips_mode = 1;
+#endif
+
__progname = ssh_get_progname(argv[0]);
log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
--- openssh-4.7p1/buffer.c Thu Dec 20 12:55:07 2007
+++ openssh-4.7p1/buffer.c Thu Dec 20 12:55:38 2007
@@ -175,7 +175,8 @@
len, buffer->end - buffer->offset);
return (-1);
}
- memcpy(buf, buffer->buf + buffer->offset, len);
+ if (len > 0)
+ memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
return (0);
}
--- openssh-4.7p1/sshconnect.c Thu Dec 20 15:23:57 2007
+++ openssh-4.7p1/sshconnect.c Thu Dec 20 15:40:26 2007
@@ -57,6 +57,7 @@
#include "misc.h"
#include "dns.h"
#include "version.h"
+#include "fips.h"
char *client_version_string = NULL;
char *server_version_string = NULL;
@@ -545,6 +546,12 @@
char msg[1024];
int len, host_line, ip_line;
const char *host_file = NULL, *ip_file = NULL;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
/*
* Force accepting of the host key for loopback/localhost. The
@@ -708,7 +735,7 @@
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, dgst_type, SSH_FP_HEX);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@@ -999,11 +1006,17 @@
Key *found;
char *fp;
int line, ret;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
found = key_new(keytype);
if ((ret = lookup_key_in_hostfile_by_type(file, host,
keytype, found, &line))) {
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, dgst_type, SSH_FP_HEX);
logit("WARNING: %s key found for host %s\n"
"in %s:%d\n"
"%s key fingerprint %s.",
@@ -1053,8 +1086,14 @@
{
char *fp;
const char *type = key_type(host_key);
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, dgst_type, SSH_FP_HEX);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
@");
--- openssh-4.7p1/sshconnect2.c Mon Dec 24 13:14:28 2007
+++ openssh-4.7p1/sshconnect2.c Mon Dec 24 13:17:06 2007
@@ -64,6 +64,7 @@
#include "msg.h"
#include "pathnames.h"
#include "uidswap.h"
+#include "fips.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -433,6 +434,12 @@
u_int alen, blen;
char *pkalg, *fp;
u_char *pkblob;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
if (authctxt == NULL)
fatal("input_userauth_pk_ok: no authentication context");
@@ -466,7 +473,7 @@
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, dgst_type, SSH_FP_HEX);
debug2("input_userauth_pk_ok: fp %s", fp);
xfree(fp);
--- openssh-4.7p1/auth2-pubkey.c Thu Dec 20 15:18:22 2007
+++ openssh-4.7p1/auth2-pubkey.c Sun Dec 23 21:42:40 2007
@@ -52,6 +52,9 @@
#endif
#include "monitor_wrap.h"
#include "misc.h"
+#ifdef OPENSSL_FIPS
+#include "fips.h"
+#endif
/* import */
extern ServerOptions options;
@@ -186,6 +189,14 @@
struct stat st;
Key *found;
char *fp;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
+
+
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
@@ -250,7 +261,7 @@
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, dgst_type, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(found), fp);
xfree(fp);
--- openssh-4.7p1/auth-rsa.c Thu Dec 20 15:18:22 2007
+++ openssh-4.7p1/auth-rsa.c Wed Jan 2 17:01:42 2008
@@ -21,6 +21,7 @@
#include <openssl/rsa.h>
#include <openssl/md5.h>
+#include <openssl/fips_sha.h>
#include <pwd.h>
#include <stdio.h>
@@ -47,6 +48,9 @@
#include "monitor_wrap.h"
#include "ssh.h"
#include "misc.h"
+#ifdef OPENSSL_FIPS
+#include "fips.h"
+#endif
/* import */
extern ServerOptions options;
@@ -88,10 +92,11 @@
}
int
-auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char
response[16])
+auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char
response[20])
{
- u_char buf[32], mdbuf[16];
+ u_char buf[40], mdbuf[16], shabuf[20];
MD5_CTX md;
+ SHA_CTX sha;
int len;
/* don't allow short keys */
@@ -101,10 +106,37 @@
return (0);
}
- /* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
+ if (len <= 0 || len > 40)
+ fatal("auth_rsa_verify_response: bad challenge length %d", len);
+
+ /* The response is SHA1 of decrypted challenge plus session id. */
+ memset(buf, 0, 40);
+ BN_bn2bin(challenge, buf + 40 - len);
+ SHA1_Init(&sha);
+ SHA1_Update(&sha, buf, 40);
+ SHA1_Update(&sha, session_id, 16);
+ SHA1_Final(shabuf, &sha);
+
+ /* Verify that the response is the original challenge. */
+ if (memcmp(response, shabuf, 20) != 0) {
+ /* Wrong answer. */
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ return (0);
+ }
+#endif
+ }
+
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ return (1);
+ }
+#endif
+
if (len <= 0 || len > 32)
fatal("auth_rsa_verify_response: bad challenge length %d", len);
+ /* The response is MD5 of decrypted challenge plus session id. */
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
@@ -131,7 +163,7 @@
auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
- u_char response[16];
+ u_char response[20];
int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
@@ -153,6 +185,10 @@
packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
for (i = 0; i < 16; i++)
response[i] = (u_char)packet_get_char();
+#ifdef OPENSSL_FIPS
+ for (i = 16; i < 20; i++)
+ response[i] = (u_char)packet_get_char();
+#endif
packet_check_eom();
success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
@@ -304,6 +340,12 @@
Key *key;
char *fp;
struct passwd *pw = authctxt->pw;
+ enum fp_type dgst_type = SSH_FP_MD5;
+#ifdef OPENSSL_FIPS
+ if (fips_mode) {
+ dgst_type = SSH_FP_SHA1;
+ }
+#endif
/* no user given */
if (!authctxt->valid)
@@ -332,7 +374,7 @@
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, dgst_type, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(key), fp);
xfree(fp);
--- openssh-4.7p1/contrib/redhat/sshd.init Mon Dec 24 13:44:26 2007
+++ openssh-4.7p1/contrib/redhat/sshd.init Wed Dec 26 13:08:06 2007
@@ -24,7 +24,11 @@
# Some functions to make the below more readable
KEYGEN=/usr/bin/ssh-keygen
SSHD=/usr/sbin/sshd
-RSA1_KEY=/etc/ssh/ssh_host_key
+if [ "$OPENSSH_FIPS" ] ; then
+ EXTRA_SSH_KEYGEN_RSA_FLAGS="-b 2048"
+else
+ RSA1_KEY=/etc/ssh/ssh_host_key
+fi
RSA_KEY=/etc/ssh/ssh_host_rsa_key
DSA_KEY=/etc/ssh/ssh_host_dsa_key
PID_FILE=/var/run/sshd.pid
@@ -32,7 +36,7 @@
do_rsa1_keygen() {
if [ ! -s $RSA1_KEY ]; then
echo -n $"Generating SSH1 RSA host key: "
- if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N ''
>&/dev/null; then
+ if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N ''
$EXTRA_SSH_KEYGEN_RSA_FLAGS >&/dev/null; then
chmod 600 $RSA1_KEY
chmod 644 $RSA1_KEY.pub
if [ -x /sbin/restorecon ]; then
@@ -51,7 +55,7 @@
do_rsa_keygen() {
if [ ! -s $RSA_KEY ]; then
echo -n $"Generating SSH2 RSA host key: "
- if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N ''
>&/dev/null; then
+ if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N ''
$EXTRA_SSH_KEYGEN_RSA_FLAGS >&/dev/null; then
chmod 600 $RSA_KEY
chmod 644 $RSA_KEY.pub
if [ -x /sbin/restorecon ]; then
@@ -70,7 +74,7 @@
do_dsa_keygen() {
if [ ! -s $DSA_KEY ]; then
echo -n $"Generating SSH2 DSA host key: "
- if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N ''
>&/dev/null; then
+ if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N ''
$EXTRA_SSH_KEYGEN_DSA_FLAGS >&/dev/null; then
chmod 600 $DSA_KEY
chmod 644 $DSA_KEY.pub
if [ -x /sbin/restorecon ]; then
--- openssh-4.7p1/ssh-add.c Wed Dec 26 17:25:22 2007
+++ openssh-4.7p1/ssh-add.c Wed Dec 26 17:35:52 2007
@@ -61,10 +61,18 @@
#include "authfile.h"
#include "pathnames.h"
#include "misc.h"
+#include "fips.h"
/* argv0 */
extern char *__progname;
+/*
+ * FIPS mode operation
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
+
/* Default files to add */
static char *default_files[] = {
_PATH_SSH_CLIENT_ID_RSA,
@@ -337,6 +345,10 @@
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode=1;
+#endif
+
__progname = ssh_get_progname(argv[0]);
init_rng();
seed_rng();
--- openssh-4.7p1/ssh-agent.c Wed Dec 26 18:09:26 2007
+++ openssh-4.7p1/ssh-agent.c Wed Dec 26 18:17:05 2007
@@ -74,6 +74,14 @@
#include "compat.h"
#include "log.h"
#include "misc.h"
+#include "fips.h"
+
+/*
+ * FIPS operational mode
+*/
+#ifdef OPENSSL_FIPS
+ int fips_mode = 0;
+#endif
#ifdef SMARTCARD
#include "scard.h"
@@ -1047,6 +1055,10 @@
char pidstrbuf[1 + 3 * sizeof pid];
struct timeval *tvp = NULL;
+#ifdef OPENSSL_FIPS
+ if (getenv("OPENSSH_FIPS")) fips_mode = 1;
+#endif
+
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();