From 8028159313390fcb3623c120a3b8ef05dbbfc75f Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Jul 09 2014 19:16:53 +0000 Subject: fix and rebase fips patch to 6.6.1p1 --- diff --git a/openssh-6.3p1-fips.patch b/openssh-6.3p1-fips.patch deleted file mode 100644 index 6a5a332..0000000 --- a/openssh-6.3p1-fips.patch +++ /dev/null @@ -1,611 +0,0 @@ -diff -up openssh-6.3p1/Makefile.in.fips openssh-6.3p1/Makefile.in ---- openssh-6.3p1/Makefile.in.fips 2013-10-11 22:24:32.850031186 +0200 -+++ openssh-6.3p1/Makefile.in 2013-10-11 22:24:32.870031092 +0200 -@@ -147,25 +147,25 @@ libssh.a: $(LIBSSH_OBJS) - $(RANLIB) $@ - - ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) -- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) -+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o -- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o -- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o -- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o -- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - 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) -@@ -177,7 +177,7 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh - $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS) - - 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) -+ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) - - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -diff -up openssh-6.3p1/auth-rsa.c.fips openssh-6.3p1/auth-rsa.c ---- openssh-6.3p1/auth-rsa.c.fips 2013-10-24 15:43:46.019999906 +0200 -+++ openssh-6.3p1/auth-rsa.c 2013-10-24 15:44:09.262890686 +0200 -@@ -240,7 +240,7 @@ rsa_key_allowed_in_file(struct passwd *p - "actual %d vs. announced %d.", - file, linenum, BN_num_bits(key->rsa->n), bits); - -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - debug("matching key found: file %s, line %lu %s %s", - file, linenum, key_type(key), fp); - free(fp); -diff -up openssh-6.3p1/auth2-pubkey.c.fips openssh-6.3p1/auth2-pubkey.c ---- openssh-6.3p1/auth2-pubkey.c.fips 2013-10-24 15:39:05.008319990 +0200 -+++ openssh-6.3p1/auth2-pubkey.c 2013-10-24 15:39:05.029319892 +0200 -@@ -209,7 +209,7 @@ pubkey_auth_info(Authctxt *authctxt, con - - if (key_is_cert(key)) { - fp = key_fingerprint(key->cert->signature_key, -- SSH_FP_MD5, SSH_FP_HEX); -+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", - key_type(key), key->cert->key_id, - (unsigned long long)key->cert->serial, -@@ -217,7 +217,7 @@ pubkey_auth_info(Authctxt *authctxt, con - extra == NULL ? "" : ", ", extra == NULL ? "" : extra); - free(fp); - } else { -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - auth_info(authctxt, "%s %s%s%s", key_type(key), fp, - extra == NULL ? "" : ", ", extra == NULL ? "" : extra); - free(fp); -diff -up openssh-6.3p1/authfile.c.fips openssh-6.3p1/authfile.c ---- openssh-6.3p1/authfile.c.fips 2013-10-11 22:24:32.857031153 +0200 -+++ openssh-6.3p1/authfile.c 2013-10-11 22:24:32.870031092 +0200 -@@ -148,8 +148,14 @@ key_private_rsa1_to_blob(Key *key, Buffe - /* Allocate space for the private part of the key in the buffer. */ - cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_ENCRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_ENCRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&encrypted); -+ buffer_free(&buffer); -+ return 0; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); - cipher_cleanup(&ciphercontext); -@@ -472,8 +478,13 @@ key_parse_private_rsa1(Buffer *blob, con - cp = buffer_append_space(&decrypted, buffer_len(©)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_DECRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_DECRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&decrypted); -+ goto fail; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(©), buffer_len(©), 0, 0); - cipher_cleanup(&ciphercontext); -diff -up openssh-6.3p1/cipher-ctr.c.fips openssh-6.3p1/cipher-ctr.c ---- openssh-6.3p1/cipher-ctr.c.fips 2013-06-02 00:07:32.000000000 +0200 -+++ openssh-6.3p1/cipher-ctr.c 2013-10-11 22:24:32.870031092 +0200 -@@ -138,7 +138,8 @@ evp_aes_128_ctr(void) - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } -diff -up openssh-6.3p1/cipher.c.fips openssh-6.3p1/cipher.c ---- openssh-6.3p1/cipher.c.fips 2013-10-11 22:24:32.820031327 +0200 -+++ openssh-6.3p1/cipher.c 2013-10-11 22:24:32.871031087 +0200 -@@ -40,6 +40,7 @@ - #include - - #include -+#include - - #include - #include -@@ -86,6 +87,27 @@ static const struct Cipher ciphers[] = { - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } - }; - -+static const struct Cipher fips_ciphers[] = { -+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, -+ { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, -+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, -+ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, -+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, -+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, -+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, -+ { "rijndael-cbc@lysator.liu.se", -+ SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, -+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, -+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, -+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, -+#ifdef OPENSSL_HAVE_EVPGCM -+ { "aes128-gcm@openssh.com", -+ SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, -+ { "aes256-gcm@openssh.com", -+ SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, -+#endif -+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } -+}; - /*--*/ - - /* Returns a comma-separated list of supported ciphers. */ -@@ -96,7 +118,7 @@ cipher_alg_list(void) - size_t nlen, rlen = 0; - const Cipher *c; - -- for (c = ciphers; c->name != NULL; c++) { -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) { - if (c->number != SSH_CIPHER_SSH2) - continue; - if (ret != NULL) -@@ -161,7 +183,7 @@ const Cipher * - cipher_by_name(const char *name) - { - const Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcmp(c->name, name) == 0) - return c; - return NULL; -@@ -171,7 +193,7 @@ const Cipher * - cipher_by_number(int id) - { - const Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (c->number == id) - return c; - return NULL; -@@ -215,7 +237,7 @@ cipher_number(const char *name) - const Cipher *c; - if (name == NULL) - return -1; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcasecmp(c->name, name) == 0) - return c->number; - return -1; -@@ -374,14 +396,15 @@ cipher_cleanup(CipherContext *cc) - * passphrase and using the resulting 16 bytes as the key. - */ - --void -+int - cipher_set_key_string(CipherContext *cc, const Cipher *cipher, - const char *passphrase, int do_encrypt) - { - MD5_CTX md; - u_char digest[16]; - -- MD5_Init(&md); -+ if (MD5_Init(&md) <= 0) -+ return -1; - MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); - MD5_Final(digest, &md); - -@@ -389,6 +412,7 @@ cipher_set_key_string(CipherContext *cc, - - memset(digest, 0, sizeof(digest)); - memset(&md, 0, sizeof(md)); -+ return 0; - } - - /* -diff -up openssh-6.3p1/cipher.h.fips openssh-6.3p1/cipher.h ---- openssh-6.3p1/cipher.h.fips 2013-10-11 22:24:32.820031327 +0200 -+++ openssh-6.3p1/cipher.h 2013-10-11 22:24:32.871031087 +0200 -@@ -92,7 +92,7 @@ void cipher_init(CipherContext *, const - void cipher_crypt(CipherContext *, u_char *, const u_char *, - u_int, u_int, u_int); - void cipher_cleanup(CipherContext *); --void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); -+int cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); - u_int cipher_blocksize(const Cipher *); - u_int cipher_keylen(const Cipher *); - u_int cipher_authlen(const Cipher *); -diff -up openssh-6.3p1/key.c.fips openssh-6.3p1/key.c ---- openssh-6.3p1/key.c.fips 2013-10-11 22:24:32.821031322 +0200 -+++ openssh-6.3p1/key.c 2013-10-11 22:24:32.871031087 +0200 -@@ -40,6 +40,7 @@ - #include - - #include -+#include - #include - - #include -@@ -606,9 +607,13 @@ key_fingerprint_selection(void) - char *env; - - if (!rv_defined) { -- env = getenv("SSH_FINGERPRINT_TYPE"); -- rv = (env && !strcmp (env, "sha")) ? -- SSH_FP_SHA1 : SSH_FP_MD5; -+ if (FIPS_mode()) -+ rv = SSH_FP_SHA1; -+ else { -+ env = getenv("SSH_FINGERPRINT_TYPE"); -+ rv = (env && !strcmp (env, "sha")) ? -+ SSH_FP_SHA1 : SSH_FP_MD5; -+ } - rv_defined = 1; - } - return rv; -diff -up openssh-6.3p1/mac.c.fips openssh-6.3p1/mac.c ---- openssh-6.3p1/mac.c.fips 2013-10-11 22:24:32.821031322 +0200 -+++ openssh-6.3p1/mac.c 2013-10-11 22:25:35.394737186 +0200 -@@ -28,6 +28,7 @@ - #include - - #include -+#include - - #include - #include -@@ -60,7 +61,7 @@ struct macalg { - int etm; /* Encrypt-then-MAC */ - }; - --static const struct macalg macs[] = { -+static const struct macalg all_macs[] = { - /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ - { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, - { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, -@@ -91,6 +92,18 @@ static const struct macalg macs[] = { - { NULL, 0, NULL, 0, 0, 0, 0 } - }; - -+static const struct macalg fips_macs[] = { -+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, -+ { "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 }, -+#ifdef HAVE_EVP_SHA256 -+ { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 }, -+ { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 }, -+ { "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 }, -+ { "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 }, -+#endif -+ { NULL, 0, NULL, 0, 0, 0, 0 } -+}; -+ - /* Returns a comma-separated list of supported MACs. */ - char * - mac_alg_list(void) -@@ -99,7 +112,7 @@ mac_alg_list(void) - size_t nlen, rlen = 0; - const struct macalg *m; - -- for (m = macs; m->name != NULL; m++) { -+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { - if (ret != NULL) - ret[rlen++] = '\n'; - nlen = strlen(m->name); -@@ -136,7 +149,7 @@ mac_setup(Mac *mac, char *name) - { - const struct macalg *m; - -- for (m = macs; m->name != NULL; m++) { -+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { - if (strcmp(name, m->name) != 0) - continue; - if (mac != NULL) -diff -up openssh-6.3p1/myproposal.h.fips openssh-6.3p1/myproposal.h ---- openssh-6.3p1/myproposal.h.fips 2013-06-11 04:10:02.000000000 +0200 -+++ openssh-6.3p1/myproposal.h 2013-10-11 22:24:32.872031082 +0200 -@@ -114,6 +114,19 @@ - #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" - #define KEX_DEFAULT_LANG "" - -+#define KEX_FIPS_ENCRYPT \ -+ "aes128-ctr,aes192-ctr,aes256-ctr," \ -+ "aes128-cbc,3des-cbc," \ -+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" -+#ifdef HAVE_EVP_SHA256 -+#define KEX_FIPS_MAC \ -+ "hmac-sha1," \ -+ "hmac-sha2-256," \ -+ "hmac-sha2-512" -+#else -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" -+#endif - - static char *myproposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, -diff -up openssh-6.3p1/openbsd-compat/bsd-arc4random.c.fips openssh-6.3p1/openbsd-compat/bsd-arc4random.c ---- openssh-6.3p1/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100 -+++ openssh-6.3p1/openbsd-compat/bsd-arc4random.c 2013-10-11 22:24:32.872031082 +0200 -@@ -37,25 +37,18 @@ - #define REKEY_BYTES (1 << 24) - - static int rc4_ready = 0; --static RC4_KEY rc4; - - unsigned int - arc4random(void) - { - unsigned int r = 0; -- static int first_time = 1; -+ void *rp = &r; - -- if (rc4_ready <= 0) { -- if (first_time) -- seed_rng(); -- first_time = 0; -+ if (!rc4_ready) { - arc4random_stir(); - } -+ RAND_bytes(rp, sizeof(r)); - -- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); -- -- rc4_ready -= sizeof(r); -- - return(r); - } - -@@ -63,24 +56,11 @@ void - arc4random_stir(void) - { - unsigned char rand_buf[SEED_SIZE]; -- int i; - -- memset(&rc4, 0, sizeof(rc4)); - if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) - fatal("Couldn't obtain random bytes (error %ld)", - ERR_get_error()); -- RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); -- -- /* -- * Discard early keystream, as per recommendations in: -- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps -- */ -- for(i = 0; i <= 256; i += sizeof(rand_buf)) -- RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf); -- -- memset(rand_buf, 0, sizeof(rand_buf)); -- -- rc4_ready = REKEY_BYTES; -+ rc4_ready = 1; - } - #endif /* !HAVE_ARC4RANDOM */ - -diff -up openssh-6.3p1/ssh-keygen.c.fips openssh-6.3p1/ssh-keygen.c ---- openssh-6.3p1/ssh-keygen.c.fips 2013-10-24 15:45:06.055623916 +0200 -+++ openssh-6.3p1/ssh-keygen.c 2013-10-24 15:45:36.906478986 +0200 -@@ -730,7 +730,7 @@ do_download(struct passwd *pw) - enum fp_type fptype; - char *fp, *ra; - -- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; -+ fptype = print_bubblebabble ? SSH_FP_SHA1 : (FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5); - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - - pkcs11_init(0); -@@ -740,7 +740,7 @@ do_download(struct passwd *pw) - for (i = 0; i < nkeys; i++) { - if (print_fingerprint) { - fp = key_fingerprint(keys[i], fptype, rep); -- ra = key_fingerprint(keys[i], SSH_FP_MD5, -+ ra = key_fingerprint(keys[i], FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_RANDOMART); - printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), - fp, key_type(keys[i])); -diff -up openssh-6.3p1/ssh.c.fips openssh-6.3p1/ssh.c ---- openssh-6.3p1/ssh.c.fips 2013-07-25 03:55:53.000000000 +0200 -+++ openssh-6.3p1/ssh.c 2013-10-11 22:24:32.872031082 +0200 -@@ -73,6 +73,8 @@ - - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" - -@@ -253,6 +255,13 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)) -+ if (FIPS_mode()) -+ fatal("FIPS integrity verification test failed."); -+ else -+ logit("FIPS integrity verification test failed."); - - #ifndef HAVE_SETPROCTITLE - /* Prepare for later setproctitle emulation */ -@@ -330,6 +339,9 @@ main(int ac, char **av) - "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { - switch (opt) { - case '1': -+ if (FIPS_mode()) { -+ fatal("Protocol 1 not allowed in the FIPS mode."); -+ } - options.protocol = SSH_PROTO_1; - break; - case '2': -@@ -647,7 +659,6 @@ main(int ac, char **av) - if (!host) - usage(); - -- OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - - /* Initialize the command to execute on remote host. */ -@@ -748,6 +759,10 @@ main(int ac, char **av) - - seed_rng(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); - -@@ -816,6 +831,12 @@ main(int ac, char **av) - - timeout_ms = options.connection_timeout * 1000; - -+ if (FIPS_mode()) { -+ options.protocol &= SSH_PROTO_2; -+ if (options.protocol == 0) -+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); -+ } -+ - /* Open a connection to the remote host. */ - if (ssh_connect(host, &hostaddr, options.port, - options.address_family, options.connection_attempts, &timeout_ms, -diff -up openssh-6.3p1/sshconnect2.c.fips openssh-6.3p1/sshconnect2.c ---- openssh-6.3p1/sshconnect2.c.fips 2013-10-11 22:24:32.810031374 +0200 -+++ openssh-6.3p1/sshconnect2.c 2013-10-11 22:24:32.873031077 +0200 -@@ -44,6 +44,8 @@ - #include - #endif - -+#include -+ - #include "openbsd-compat/sys-queue.h" - - #include "xmalloc.h" -@@ -170,6 +172,10 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; -+ - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -185,7 +191,11 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } -+ - if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - options.hostkeyalgorithms; -diff -up openssh-6.4p1/sshd.c.fips openssh-6.4p1/sshd.c ---- openssh-6.4p1/sshd.c.fips 2014-01-27 16:20:12.751358484 +0100 -+++ openssh-6.4p1/sshd.c 2014-01-27 16:21:12.961052163 +0100 -@@ -76,6 +76,8 @@ - #include - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - - #ifdef HAVE_SECUREWARE -@@ -1450,6 +1452,18 @@ main(int ac, char **av) - #endif - __progname = ssh_get_progname(av[0]); - -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)) { -+ openlog(__progname, LOG_PID, LOG_AUTHPRIV); -+ if (FIPS_mode()) { -+ syslog(LOG_CRIT, "FIPS integrity verification test failed."); -+ cleanup_exit(255); -+ } -+ else -+ syslog(LOG_INFO, "FIPS integrity verification test failed."); -+ closelog(); -+ } - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ - saved_argc = ac; - rexec_argc = ac; -@@ -1601,8 +1615,6 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - -- OpenSSL_add_all_algorithms(); -- - /* If requested, redirect the logs to the specified logfile. */ - if (logfile != NULL) { - log_redirect_stderr_to(logfile); -@@ -1773,6 +1785,10 @@ main(int ac, char **av) - debug("private host key: #%d type %d %s", i, keytype, - key_type(key ? key : pubkey)); - } -+ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { -+ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); -+ options.protocol &= ~SSH_PROTO_1; -+ } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; -@@ -1936,6 +1952,10 @@ main(int ac, char **av) - /* Initialize the random number generator. */ - arc4random_stir(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - if (chdir("/") == -1) -@@ -2498,6 +2518,9 @@ do_ssh2_kex(void) - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -2507,6 +2530,9 @@ do_ssh2_kex(void) - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } - if (options.compression == COMP_NONE) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = diff --git a/openssh-6.6p1-fips.patch b/openssh-6.6p1-fips.patch new file mode 100644 index 0000000..2869d2f --- /dev/null +++ b/openssh-6.6p1-fips.patch @@ -0,0 +1,808 @@ +diff --git a/Makefile.in b/Makefile.in +index 3bb7f00..294bef5 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -154,25 +154,25 @@ libssh.a: $(LIBSSH_OBJS) + $(RANLIB) $@ + + ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) +- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) ++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o + $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + + ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o +- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o +- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o +- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o +- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + 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) +@@ -187,7 +187,7 @@ 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 roaming_dummy.o +- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) ++ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +diff --git a/auth-rsa.c b/auth-rsa.c +index f225b0b..8bafcd6 100644 +--- a/auth-rsa.c ++++ b/auth-rsa.c +@@ -244,7 +244,7 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, + "actual %d vs. announced %d.", + file, linenum, BN_num_bits(key->rsa->n), bits); + +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); + debug("matching key found: file %s, line %lu %s %s", + file, linenum, key_type(key), fp); + free(fp); +diff --git a/auth2-pubkey.c b/auth2-pubkey.c +index 6d1c872..3808ec8 100644 +--- a/auth2-pubkey.c ++++ b/auth2-pubkey.c +@@ -214,8 +214,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) + } + + if (key_is_cert(key)) { +- fp = key_fingerprint(key->cert->signature_key, +- SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX); + auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", + key_type(key), key->cert->key_id, + (unsigned long long)key->cert->serial, +@@ -223,7 +222,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) + extra == NULL ? "" : ", ", extra == NULL ? "" : extra); + free(fp); + } else { +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); + auth_info(authctxt, "%s %s%s%s", key_type(key), fp, + extra == NULL ? "" : ", ", extra == NULL ? "" : extra); + free(fp); +diff --git a/authfile.c b/authfile.c +index ec4f4ff..2b3d650 100644 +--- a/authfile.c ++++ b/authfile.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + /* compatibility with old or broken OpenSSL versions */ + #include "openbsd-compat/openssl-compat.h" +@@ -1068,7 +1069,7 @@ Key * + key_parse_private(Buffer *buffer, const char *filename, + const char *passphrase, char **commentp) + { +- Key *pub, *prv; ++ Key *pub, *prv = NULL; + + /* it's a SSH v1 key if the public key part is readable */ + pub = key_parse_public_rsa1(buffer, commentp); +@@ -1080,9 +1081,10 @@ key_parse_private(Buffer *buffer, const char *filename, + *commentp = xstrdup(filename); + } else { + key_free(pub); +- /* key_parse_public_rsa1() has already loaded the comment */ +- prv = key_parse_private_type(buffer, KEY_RSA1, passphrase, +- NULL); ++ if (! FIPS_mode()) ++ /* key_parse_public_rsa1() has already loaded the comment */ ++ prv = key_parse_private_type(buffer, KEY_RSA1, passphrase, ++ NULL); + } + return prv; + } +diff --git a/cipher-ctr.c b/cipher-ctr.c +index 73e9c7c..40ee395 100644 +--- a/cipher-ctr.c ++++ b/cipher-ctr.c +@@ -179,7 +179,8 @@ evp_aes_128_ctr(void) + aes_ctr.do_cipher = ssh_aes_ctr; + #ifndef SSH_OLD_EVP + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | +- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | ++ EVP_CIPH_FLAG_FIPS; + #endif + return (&aes_ctr); + } +diff --git a/cipher.c b/cipher.c +index 226e56d..b19443c 100644 +--- a/cipher.c ++++ b/cipher.c +@@ -39,6 +39,8 @@ + + #include + ++#include ++ + #include + #include + #include +@@ -90,6 +92,25 @@ static const struct Cipher ciphers[] = { + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } + }; + ++static const struct Cipher fips_ciphers[] = { ++ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, ++ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, ++ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, ++ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, ++ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, ++ { "rijndael-cbc@lysator.liu.se", ++ SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, ++ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, ++ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, ++ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, ++#ifdef OPENSSL_HAVE_EVPGCM ++ { "aes128-gcm@openssh.com", ++ SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, ++ { "aes256-gcm@openssh.com", ++ SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, ++#endif ++ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } ++}; + /*--*/ + + /* Returns a list of supported ciphers separated by the specified char. */ +@@ -100,7 +121,7 @@ cipher_alg_list(char sep, int auth_only) + size_t nlen, rlen = 0; + const Cipher *c; + +- for (c = ciphers; c->name != NULL; c++) { ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) { + if (c->number != SSH_CIPHER_SSH2) + continue; + if (auth_only && c->auth_len == 0) +@@ -180,7 +201,7 @@ const Cipher * + cipher_by_name(const char *name) + { + const Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcmp(c->name, name) == 0) + return c; + return NULL; +@@ -190,7 +211,7 @@ const Cipher * + cipher_by_number(int id) + { + const Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (c->number == id) + return c; + return NULL; +@@ -232,7 +253,7 @@ cipher_number(const char *name) + const Cipher *c; + if (name == NULL) + return -1; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcasecmp(c->name, name) == 0) + return c->number; + return -1; +diff --git a/dh.h b/dh.h +index 48f7b68..9ff39f4 100644 +--- a/dh.h ++++ b/dh.h +@@ -45,6 +45,7 @@ int dh_estimate(int); + + /* Min and max values from RFC4419. */ + #define DH_GRP_MIN 1024 ++#define DH_GRP_MIN_FIPS 2048 + #define DH_GRP_MAX 8192 + + /* +diff --git a/entropy.c b/entropy.c +index b361a04..5616643 100644 +--- a/entropy.c ++++ b/entropy.c +@@ -222,6 +222,9 @@ seed_rng(void) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); + ++ /* clean the PRNG status when exiting the program */ ++ atexit(RAND_cleanup); ++ + #ifndef OPENSSL_PRNG_ONLY + if (RAND_status() == 1) { + debug3("RNG is ready, skipping seeding"); +diff --git a/kex.c b/kex.c +index bc3e53e..ede7b67 100644 +--- a/kex.c ++++ b/kex.c +@@ -34,6 +34,7 @@ + #include + + #include ++#include + + #include "xmalloc.h" + #include "ssh2.h" +@@ -103,6 +104,25 @@ static const struct kexalg kexalgs[] = { + { NULL, -1, -1, -1}, + }; + ++static const struct kexalg kexalgs_fips[] = { ++ { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++#ifdef HAVE_EVP_SHA256 ++ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif ++#ifdef OPENSSL_HAS_ECC ++ { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, ++ SSH_DIGEST_SHA384 }, ++# ifdef OPENSSL_HAS_NISTP521 ++ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, ++ SSH_DIGEST_SHA512 }, ++# endif ++#endif ++ { NULL, -1, -1, NULL}, ++}; ++ + char * + kex_alg_list(char sep) + { +@@ -126,7 +146,7 @@ kex_alg_by_name(const char *name) + { + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; + #ifdef GSSAPI +@@ -151,7 +171,10 @@ kex_names_valid(const char *names) + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + if (kex_alg_by_name(p) == NULL) { +- error("Unsupported KEX algorithm \"%.100s\"", p); ++ if (FIPS_mode()) ++ error("\"%.100s\" is not allowed in FIPS mode", p); ++ else ++ error("Unsupported KEX algorithm \"%.100s\"", p); + free(s); + return 0; + } +diff --git a/kexecdhc.c b/kexecdhc.c +index 2f7629c..20c9946 100644 +--- a/kexecdhc.c ++++ b/kexecdhc.c +@@ -154,6 +154,7 @@ kexecdh_client(Kex *kex) + + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); ++ memset(hash, 0, hashlen); + kex_finish(kex); + } + #else /* OPENSSL_HAS_ECC */ +diff --git a/kexecdhs.c b/kexecdhs.c +index 2700b72..0820894 100644 +--- a/kexecdhs.c ++++ b/kexecdhs.c +@@ -150,6 +150,7 @@ kexecdh_server(Kex *kex) + + kex_derive_keys_bn(kex, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); ++ memset(hash, 0, hashlen); + kex_finish(kex); + } + #else /* OPENSSL_HAS_ECC */ +diff --git a/kexgexc.c b/kexgexc.c +index 355b7ba..427e11f 100644 +--- a/kexgexc.c ++++ b/kexgexc.c +@@ -26,6 +26,8 @@ + + #include "includes.h" + ++#include ++ + #include + + #include +@@ -64,13 +66,13 @@ kexgex_client(Kex *kex) + /* Old GEX request */ + packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD); + packet_put_int(nbits); +- min = DH_GRP_MIN; ++ min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN; + max = DH_GRP_MAX; + + debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", nbits); + } else { + /* New GEX request */ +- min = DH_GRP_MIN; ++ min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN; + max = DH_GRP_MAX; + packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST); + packet_put_int(min); +diff --git a/kexgexs.c b/kexgexs.c +index 770ad28..9d4fc6d 100644 +--- a/kexgexs.c ++++ b/kexgexs.c +@@ -76,16 +76,16 @@ kexgex_server(Kex *kex) + omin = min = packet_get_int(); + onbits = nbits = packet_get_int(); + omax = max = packet_get_int(); +- min = MAX(DH_GRP_MIN, min); ++ min = MAX(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min); + max = MIN(DH_GRP_MAX, max); +- nbits = MAX(DH_GRP_MIN, nbits); ++ nbits = MAX(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits); + nbits = MIN(DH_GRP_MAX, nbits); + break; + case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: + debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); + onbits = nbits = packet_get_int(); + /* unused for old GEX */ +- omin = min = DH_GRP_MIN; ++ omin = min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN; + omax = max = DH_GRP_MAX; + break; + default: +diff --git a/key.c b/key.c +index 62f3edb..c13b644 100644 +--- a/key.c ++++ b/key.c +@@ -42,6 +42,7 @@ + #include "crypto_api.h" + + #include ++#include + #include + + #include +@@ -636,9 +637,13 @@ key_fingerprint_selection(void) + char *env; + + if (!rv_defined) { +- env = getenv("SSH_FINGERPRINT_TYPE"); +- rv = (env && !strcmp (env, "sha")) ? +- SSH_FP_SHA1 : SSH_FP_MD5; ++ if (FIPS_mode()) ++ rv = SSH_FP_SHA1; ++ else { ++ env = getenv("SSH_FINGERPRINT_TYPE"); ++ rv = (env && !strcmp (env, "sha")) ? ++ SSH_FP_SHA1 : SSH_FP_MD5; ++ } + rv_defined = 1; + } + return rv; +diff --git a/mac.c b/mac.c +index 9388af4..cd7b034 100644 +--- a/mac.c ++++ b/mac.c +@@ -27,6 +27,8 @@ + + #include + ++#include ++ + #include + #include + #include +@@ -60,7 +62,7 @@ struct macalg { + int etm; /* Encrypt-then-MAC */ + }; + +-static const struct macalg macs[] = { ++static const struct macalg all_macs[] = { + /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ + { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, + { "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 }, +@@ -91,6 +93,24 @@ static const struct macalg macs[] = { + { NULL, 0, 0, 0, 0, 0, 0 } + }; + ++static const struct macalg fips_macs[] = { ++ /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ ++ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, ++#ifdef HAVE_EVP_SHA256 ++ { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, ++ { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, ++#endif ++ ++ /* Encrypt-then-MAC variants */ ++ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, ++#ifdef HAVE_EVP_SHA256 ++ { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 }, ++ { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 }, ++#endif ++ ++ { NULL, 0, 0, 0, 0, 0, 0 } ++}; ++ + /* Returns a list of supported MACs separated by the specified char. */ + char * + mac_alg_list(char sep) +@@ -99,7 +119,7 @@ mac_alg_list(char sep) + size_t nlen, rlen = 0; + const struct macalg *m; + +- for (m = macs; m->name != NULL; m++) { ++ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(m->name); +@@ -133,7 +153,7 @@ mac_setup(Mac *mac, char *name) + { + const struct macalg *m; + +- for (m = macs; m->name != NULL; m++) { ++ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { + if (strcmp(name, m->name) != 0) + continue; + if (mac != NULL) { +diff --git a/myproposal.h b/myproposal.h +index 3a0f5ae..4f35a44 100644 +--- a/myproposal.h ++++ b/myproposal.h +@@ -88,6 +88,12 @@ + "diffie-hellman-group14-sha1," \ + "diffie-hellman-group1-sha1" + ++#define KEX_DEFAULT_KEX_FIPS \ ++ KEX_ECDH_METHODS \ ++ KEX_SHA256_METHODS \ ++ "diffie-hellman-group-exchange-sha1," \ ++ "diffie-hellman-group14-sha1" ++ + #define KEX_DEFAULT_PK_ALG \ + HOSTKEY_ECDSA_CERT_METHODS \ + "ssh-ed25519-cert-v01@openssh.com," \ +@@ -133,6 +139,22 @@ + #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" + #define KEX_DEFAULT_LANG "" + ++#define KEX_FIPS_ENCRYPT \ ++ "aes128-ctr,aes192-ctr,aes256-ctr," \ ++ "aes128-cbc,3des-cbc," \ ++ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" ++#ifdef HAVE_EVP_SHA256 ++#define KEX_FIPS_MAC \ ++ "hmac-sha1," \ ++ "hmac-sha2-256," \ ++ "hmac-sha2-512," \ ++ "hmac-sha1-etm@openssh.com," \ ++ "hmac-sha2-256-etm@openssh.com," \ ++ "hmac-sha2-512-etm@openssh.com" ++#else ++#define KEX_FIPS_MAC \ ++ "hmac-sha1" ++#endif + + static char *myproposal[PROPOSAL_MAX] = { + KEX_DEFAULT_KEX, +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 482dc1c..fd2eb94 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -195,6 +195,14 @@ type_bits_valid(int type, u_int32_t *bitsp) + fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); + exit(1); + } ++ if (FIPS_mode()) { ++ if (type == KEY_DSA) ++ fatal("DSA keys are not allowed in FIPS mode"); ++ if (type == KEY_RSA && bits != 2048 && bits != 3072) ++ fatal("RSA keys must be either 2048 bits or 3072 bits in FIPS mode"); ++ if (type == KEY_ED25519) ++ fatal("ED25519 keys are not allowed in FIPS mode"); ++ } + if (type == KEY_DSA && *bitsp != 1024) + fatal("DSA keys must be 1024 bits"); + else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768) +@@ -746,7 +754,7 @@ do_download(struct passwd *pw) + enum fp_type fptype; + char *fp, *ra; + +- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; ++ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection(); + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + + pkcs11_init(0); +@@ -756,8 +764,7 @@ do_download(struct passwd *pw) + for (i = 0; i < nkeys; i++) { + if (print_fingerprint) { + fp = key_fingerprint(keys[i], fptype, rep); +- ra = key_fingerprint(keys[i], SSH_FP_MD5, +- SSH_FP_RANDOMART); ++ ra = key_selected_fingerprint(keys[i], SSH_FP_RANDOMART); + printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]), + fp, key_type(keys[i])); + if (log_level >= SYSLOG_LEVEL_VERBOSE) +diff --git a/ssh.c b/ssh.c +index 1e6cb90..ea9193f 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -73,6 +73,8 @@ + + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" + +@@ -427,6 +429,13 @@ main(int ac, char **av) + sanitise_stdfd(); + + __progname = ssh_get_progname(av[0]); ++ SSLeay_add_all_algorithms(); ++ if (access("/etc/system-fips", F_OK) == 0) ++ if (! FIPSCHECK_verify(NULL, NULL)) ++ if (FIPS_mode()) ++ fatal("FIPS integrity verification test failed."); ++ else ++ logit("FIPS integrity verification test failed."); + + #ifndef HAVE_SETPROCTITLE + /* Prepare for later setproctitle emulation */ +@@ -504,6 +513,9 @@ main(int ac, char **av) + "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { + switch (opt) { + case '1': ++ if (FIPS_mode()) { ++ fatal("Protocol 1 not allowed in the FIPS mode."); ++ } + options.protocol = SSH_PROTO_1; + break; + case '2': +@@ -828,7 +840,6 @@ main(int ac, char **av) + + host_arg = xstrdup(host); + +- OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + /* Initialize the command to execute on remote host. */ +@@ -973,6 +984,10 @@ main(int ac, char **av) + + seed_rng(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + if (options.user == NULL) + options.user = xstrdup(pw->pw_name); + +@@ -1020,6 +1035,12 @@ main(int ac, char **av) + + timeout_ms = options.connection_timeout * 1000; + ++ if (FIPS_mode()) { ++ options.protocol &= SSH_PROTO_2; ++ if (options.protocol == 0) ++ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); ++ } ++ + /* Open a connection to the remote host. */ + if (ssh_connect(host, addrs, &hostaddr, options.port, + options.address_family, options.connection_attempts, +diff --git a/sshconnect2.c b/sshconnect2.c +index b00658b..6a1562c 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -44,6 +44,8 @@ + #include + #endif + ++#include ++ + #include "openbsd-compat/sys-queue.h" + + #include "xmalloc.h" +@@ -168,20 +170,25 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) + + #ifdef GSSAPI + if (options.gss_keyex) { +- /* Add the GSSAPI mechanisms currently supported on this +- * client to the key exchange algorithm proposal */ +- orig = myproposal[PROPOSAL_KEX_ALGS]; +- +- if (options.gss_trust_dns) +- gss_host = (char *)get_canonical_hostname(1); +- else +- gss_host = host; +- +- gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); +- if (gss) { +- debug("Offering GSSAPI proposal: %s", gss); +- xasprintf(&myproposal[PROPOSAL_KEX_ALGS], +- "%s,%s", gss, orig); ++ if (FIPS_mode()) { ++ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); ++ options.gss_keyex = 0; ++ } else { ++ /* Add the GSSAPI mechanisms currently supported on this ++ * client to the key exchange algorithm proposal */ ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ if (options.gss_trust_dns) ++ gss_host = (char *)get_canonical_hostname(1); ++ else ++ gss_host = host; ++ ++ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ } + } + } + #endif +@@ -193,6 +200,10 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; ++ + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -208,7 +219,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } ++ + if (options.hostkeyalgorithms != NULL) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + compat_pkalg_proposal(options.hostkeyalgorithms); +@@ -220,9 +235,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) + } + if (options.kex_algorithms != NULL) + myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; ++ else if (FIPS_mode()) ++ myproposal[PROPOSAL_KEX_ALGS] = KEX_DEFAULT_KEX_FIPS; ++ + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + myproposal[PROPOSAL_KEX_ALGS]); +- + #ifdef GSSAPI + /* If we've got GSSAPI algorithms, then we also support the + * 'null' hostkey, as a last resort */ +diff --git a/sshd.c b/sshd.c +index b561ec8..e977de3 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -75,6 +75,8 @@ + #include + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + + #ifdef HAVE_SECUREWARE +@@ -1468,6 +1470,18 @@ main(int ac, char **av) + #endif + __progname = ssh_get_progname(av[0]); + ++ SSLeay_add_all_algorithms(); ++ if (access("/etc/system-fips", F_OK) == 0) ++ if (! FIPSCHECK_verify(NULL, NULL)) { ++ openlog(__progname, LOG_PID, LOG_AUTHPRIV); ++ if (FIPS_mode()) { ++ syslog(LOG_CRIT, "FIPS integrity verification test failed."); ++ cleanup_exit(255); ++ } ++ else ++ syslog(LOG_INFO, "FIPS integrity verification test failed."); ++ closelog(); ++ } + /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ + saved_argc = ac; + rexec_argc = ac; +@@ -1619,8 +1633,6 @@ main(int ac, char **av) + else + closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); + +- OpenSSL_add_all_algorithms(); +- + /* If requested, redirect the logs to the specified logfile. */ + if (logfile != NULL) { + log_redirect_stderr_to(logfile); +@@ -1798,6 +1810,10 @@ main(int ac, char **av) + debug("private host key: #%d type %d %s", i, keytype, + key_type(key ? key : pubkey)); + } ++ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { ++ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); ++ options.protocol &= ~SSH_PROTO_1; ++ } + if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; +@@ -1961,6 +1977,10 @@ main(int ac, char **av) + /* Reinitialize the log (because of the fork above). */ + log_init(__progname, options.log_level, options.log_facility, log_stderr); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + /* Chdir to the root directory so that the current disk can be + unmounted if desired. */ + if (chdir("/") == -1) +@@ -2530,6 +2550,9 @@ do_ssh2_kex(void) + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -2539,6 +2562,9 @@ do_ssh2_kex(void) + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } + if (options.compression == COMP_NONE) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = +@@ -2549,6 +2575,8 @@ do_ssh2_kex(void) + } + if (options.kex_algorithms != NULL) + myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; ++ else if (FIPS_mode()) ++ myproposal[PROPOSAL_KEX_ALGS] = KEX_DEFAULT_KEX_FIPS; + + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + myproposal[PROPOSAL_KEX_ALGS]); +@@ -2575,10 +2603,14 @@ do_ssh2_kex(void) + if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) + orig = NULL; + +- if (options.gss_keyex) +- gss = ssh_gssapi_server_mechanisms(); +- else +- gss = NULL; ++ if (options.gss_keyex) { ++ if (FIPS_mode()) { ++ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); ++ options.gss_keyex = 0; ++ } else { ++ gss = ssh_gssapi_server_mechanisms(); ++ } ++ } + + if (gss && orig) + xasprintf(&newstr, "%s,%s", gss, orig); diff --git a/openssh.spec b/openssh.spec index cb5f1c5..0817c75 100644 --- a/openssh.spec +++ b/openssh.spec @@ -127,7 +127,7 @@ Patch502: openssh-6.6p1-keycat.patch #http6://bugzilla.mindrot.org/show_bug.cgi?id=1644 Patch601: openssh-6.6p1-allow-ip-opts.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1701 -Patch602: openssh-5.9p1-randclean.patch +# merged Patch602: openssh-5.9p1-randclean.patch #http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/src/crypto/dist/ssh/Attic/sftp-glob.c.diff?r1=1.13&r2=1.13.12.1&f=h Patch603: openssh-5.8p1-glob.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1893 @@ -142,7 +142,7 @@ Patch608: openssh-6.1p1-askpass-ld.patch Patch609: openssh-5.5p1-x11.patch #? -Patch700: openssh-6.3p1-fips.patch +Patch700: openssh-6.6p1-fips.patch #? # drop? Patch701: openssh-5.6p1-exit-deadlock.patch #? @@ -179,8 +179,6 @@ Patch900: openssh-6.1p1-gssapi-canohost.patch Patch901: openssh-6.6p1-kuserok.patch # use default_ccache_name from /etc/krb5.conf (#991186) Patch902: openssh-6.3p1-krb5-use-default_ccache_name.patch -# FIPS mode - adjust the key echange DH groups and ssh-keygen according to SP800-131A (#1001748) -# merge: Patch904: openssh-6.4p1-FIPS-mode-SP800-131A.patch # Run ssh-copy-id in the legacy mode when SSH_COPY_ID_LEGACY variable is set (#969375 Patch905: openssh-6.4p1-legacy-ssh-copy-id.patch # Use tty allocation for a remote scp (#985650) @@ -364,8 +362,6 @@ popd %patch502 -p1 -b .keycat %patch601 -p1 -b .ip-opts -# merge to fips -# %patch602 -p1 -b .randclean %patch603 -p1 -b .glob %patch604 -p1 -b .keyperm %patch606 -p1 -b .ipv6man @@ -373,7 +369,6 @@ popd %patch608 -p1 -b .askpass-ld %patch609 -p1 -b .x11 # -# move to the end %patch700 -p1 -b .fips # drop? %patch701 -p1 -b .exit-deadlock %patch702 -p1 -b .progress %patch703 -p1 -b .grab-info @@ -402,6 +397,7 @@ popd %patch909 -p1 -b .6.6.1 %patch200 -p1 -b .audit +%patch700 -p1 -b .fips %if 0 # Nothing here yet