[ DRAFT PATCH ] - FIPS 140-2 patch for OpenSSH 6.5p1
Manish Jagtap
manish.jagtap at airtightnetworks.com
Tue Feb 18 00:01:16 EST 2014
Hi,
I am facing some difficulties to attach the patch as a file. Trying now to
attach with plain-text email.
In addition, here is inline patch draft which is actually based on
openssh-6.0p1.fips-revised.patch.
I have also submitted via
https://bugzilla.mindrot.org/show_bug.cgi?id=2202
Request moderators to validate this patch and update as required.
Thanks,
Manish
--- PATCH START
diff -ruN openssh-6.5p1_orig/auth2-hostbased.c
openssh-6.5p1_patched/auth2-hostbased.c
--- openssh-6.5p1_orig/auth2-hostbased.c 2013-12-31
06:55:41.000000000 +0530
+++ openssh-6.5p1_patched/auth2-hostbased.c 2014-02-06
20:18:02.000000000 +0530
@@ -207,15 +207,15 @@
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), SSH_FP_HEX);
verbose("Accepted certificate ID \"%s\" signed by
"
"%s CA %s from %s@%s", key->cert->key_id,
- key_type(key->cert->signature_key), fp,
+ key_fp_type_select(), fp,
cuser, lookup);
} else {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(),
SSH_FP_HEX);
verbose("Accepted %s public key %s from %s@%s",
- key_type(key), fp, cuser, lookup);
+ key_fp_type_select(), fp, cuser, lookup);
}
free(fp);
}
diff -ruN openssh-6.5p1_orig/auth2-pubkey.c
openssh-6.5p1_patched/auth2-pubkey.c
--- openssh-6.5p1_orig/auth2-pubkey.c 2013-12-31 06:55:41.000000000
+0530
+++ openssh-6.5p1_patched/auth2-pubkey.c 2014-02-06
20:18:32.000000000 +0530
@@ -213,7 +213,7 @@
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), 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,
@@ -221,7 +221,7 @@
extra == NULL ? "" : ", ", extra == NULL ? "" :
extra);
free(fp);
} else {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(),
SSH_FP_HEX);
auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
extra == NULL ? "" : ", ", extra == NULL ? "" :
extra);
free(fp);
@@ -365,7 +365,7 @@
continue;
if (!key_is_cert_authority)
continue;
- fp = key_fingerprint(found, SSH_FP_MD5,
+ fp = key_fingerprint(found, key_fp_type_select(),
SSH_FP_HEX);
debug("matching CA found: file %s, line %lu, %s
%s",
file, linenum, key_type(found), fp);
@@ -406,7 +406,7 @@
if (key_is_cert_authority)
continue;
found_key = 1;
- fp = key_fingerprint(found, SSH_FP_MD5,
SSH_FP_HEX);
+ fp = key_fingerprint(found, key_fp_type_select(),
SSH_FP_HEX);
debug("matching key found: file %s, line %lu %s
%s",
file, linenum, key_type(found), fp);
free(fp);
@@ -432,7 +432,7 @@
return 0;
ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), SSH_FP_HEX);
if (key_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1) != 1) {
diff -ruN openssh-6.5p1_orig/auth.c openssh-6.5p1_patched/auth.c
--- openssh-6.5p1_orig/auth.c 2013-06-02 03:11:51.000000000 +0530
+++ openssh-6.5p1_patched/auth.c 2014-02-06 20:19:07.000000000
+0530
@@ -685,7 +685,7 @@
case 1:
revoked:
/* Key revoked */
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ key_fp = key_fingerprint(key, key_fp_type_select(),
SSH_FP_HEX);
error("WARNING: authentication attempt with a revoked "
"%s key %s ", key_type(key), key_fp);
free(key_fp);
diff -ruN openssh-6.5p1_orig/auth-rsa.c openssh-6.5p1_patched/auth-rsa.c
--- openssh-6.5p1_orig/auth-rsa.c 2013-07-18 11:42:44.000000000
+0530
+++ openssh-6.5p1_patched/auth-rsa.c 2014-02-06 20:27:36.000000000
+0530
@@ -2,7 +2,7 @@
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
- * All rights reserved
+ * All rights reserved
* RSA-based authentication. This code determines whether to admit a
login
* based on RSA authentication. This file also contains functions to
check
* validity of the host key.
@@ -20,7 +20,7 @@
#include <sys/stat.h>
#include <openssl/rsa.h>
-#include <openssl/md5.h>
+#include <openssl/evp.h>
#include <pwd.h>
#include <stdio.h>
@@ -47,6 +47,7 @@
#include "monitor_wrap.h"
#include "ssh.h"
#include "misc.h"
+#include "fips.h"
/* import */
extern ServerOptions options;
@@ -88,11 +89,14 @@
}
int
-auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char
response[16])
+auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char
response[MAX_HASH_LEN])
{
- u_char buf[32], mdbuf[16];
- MD5_CTX md;
+ u_char buf[2 * MAX_HASH_LEN], mdbuf[MAX_HASH_LEN];
+ const EVP_MD *evp_md;
+ EVP_MD_CTX md;
+
int len;
+ int hash_len;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
@@ -101,19 +105,29 @@
return (0);
}
- /* The response is MD5 of decrypted challenge plus session id. */
+ hash_len = fips_hash_len(fips_hash_min());
+
+ /* The response is a hash of decrypted challenge plus session id.
+ * Normally this is MD5, in FIPS mode a stronger function is
used.*/
+
+
len = BN_num_bytes(challenge);
- if (len <= 0 || len > 32)
+ if (len <= 0 || len > (2 * hash_len))
fatal("auth_rsa_verify_response: bad challenge length %d",
len);
- memset(buf, 0, 32);
- BN_bn2bin(challenge, buf + 32 - len);
- MD5_Init(&md);
- MD5_Update(&md, buf, 32);
- MD5_Update(&md, session_id, 16);
- MD5_Final(mdbuf, &md);
+
+ memset(buf, 0, sizeof(buf));
+ BN_bn2bin(challenge, buf + 2 * hash_len - len);
+
+ if ((evp_md = fips_EVP_get_digest_min()) == NULL) {
+ fatal("auth_rsa_verify_response:
fips_EVP_get_digest_min failed");
+ }
+ EVP_DigestInit(&md, evp_md);
+ EVP_DigestUpdate(&md, buf, 2 * hash_len);
+ EVP_DigestUpdate(&md, session_id, hash_len);
+ EVP_DigestFinal(&md, mdbuf, NULL);
/* Verify that the response is the original challenge. */
- if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
+ if (timingsafe_bcmp(response, mdbuf, hash_len) != 0) {
/* Wrong answer. */
return (0);
}
@@ -131,7 +145,7 @@
auth_rsa_challenge_dialog(Key *key)
{
BIGNUM *challenge, *encrypted_challenge;
- u_char response[16];
+ u_char response[MAX_HASH_LEN];
int i, success;
if ((encrypted_challenge = BN_new()) == NULL)
@@ -151,7 +165,7 @@
/* Wait for a response. */
packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
- for (i = 0; i < 16; i++)
+ for (i = 0; i < fips_hash_len(fips_hash_min()); i++)
response[i] = (u_char)packet_get_char();
packet_check_eom();
@@ -231,7 +245,7 @@
"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, key_fp_type_select(),
SSH_FP_HEX);
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(key), fp);
free(fp);
diff -ruN openssh-6.5p1_orig/cipher.c openssh-6.5p1_patched/cipher.c
--- openssh-6.5p1_orig/cipher.c 2014-01-26 04:07:26.000000000 +0530
+++ openssh-6.5p1_patched/cipher.c 2014-02-07 00:52:15.000000000
+0530
@@ -2,7 +2,7 @@
/*
* Author: Tatu Ylonen <ylo at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
- * All rights reserved
+ * All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
@@ -49,6 +49,7 @@
#include "log.h"
#include "misc.h"
#include "cipher.h"
+#include "fips.h"
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
@@ -104,8 +105,50 @@
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
};
+struct Cipher ciphers_fips140_2[] = {
+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
+ { "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 at 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 at openssh.com",
+ SSH_CIPHER_SSH2, 16, 16, 12,
16, 0, 0, EVP_aes_128_gcm },
+ { "aes256-gcm at openssh.com",
+ SSH_CIPHER_SSH2, 16, 32, 12,
16, 0, 0, EVP_aes_256_gcm },
+#endif
+ { "chacha20-poly1305 at openssh.com",
+ SSH_CIPHER_SSH2, 8, 64, 0, 16, 0,
CFLAG_CHACHAPOLY, NULL },
+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
+};
+
/*--*/
+static struct Cipher *
+fips_select_ciphers(void)
+{
+ int fips = fips_mode();
+ switch (fips) {
+ case 0:
+ return ciphers;
+ case 1:
+ return ciphers_fips140_2;
+ default:
+ /* should not be reached */
+ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u",
+ fips, __FILE__, __LINE__);
+// return NULL;
+ }
+}
+
+
/* Returns a list of supported ciphers separated by the specified char.
*/
char *
cipher_alg_list(char sep, int auth_only)
@@ -194,7 +237,7 @@
cipher_by_name(const char *name)
{
const Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = fips_select_ciphers(); c->name != NULL; c++)
if (strcmp(c->name, name) == 0)
return c;
return NULL;
@@ -204,7 +247,7 @@
cipher_by_number(int id)
{
const Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = fips_select_ciphers(); c->name != NULL; c++)
if (c->number == id)
return c;
return NULL;
@@ -248,7 +291,7 @@
const Cipher *c;
if (name == NULL)
return -1;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = fips_select_ciphers(); c->name != NULL; c++)
if (strcasecmp(c->name, name) == 0)
return c->number;
return -1;
@@ -436,14 +479,19 @@
cipher_set_key_string(CipherContext *cc, const Cipher *cipher,
const char *passphrase, int do_encrypt)
{
- MD5_CTX md;
- u_char digest[16];
+ const EVP_MD *evp_md;
+ EVP_MD_CTX md;
+ u_char digest[MAX_HASH_LEN];
+ int dlen;
+ if ((evp_md = fips_EVP_get_digest_min()) == NULL) {
+ fatal("auth_rsa_verify_response: fips_EVP_get_digest_min
failed");
+ }
- MD5_Init(&md);
- MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
- MD5_Final(digest, &md);
+ EVP_DigestInit(&md, evp_md);
+ EVP_DigestUpdate(&md, (const u_char *)passphrase,
strlen(passphrase));
+ EVP_DigestFinal(&md, digest, &dlen);
- cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
+ cipher_init(cc, cipher, digest, dlen, NULL, 0, do_encrypt);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
diff -ruN openssh-6.5p1_orig/cipher-ctr.c
openssh-6.5p1_patched/cipher-ctr.c
--- openssh-6.5p1_orig/cipher-ctr.c 2013-06-02 03:37:32.000000000
+0530
+++ openssh-6.5p1_patched/cipher-ctr.c 2014-02-07 00:54:23.000000000
+0530
@@ -26,6 +26,7 @@
#include "xmalloc.h"
#include "log.h"
+#include "fips.h"
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
@@ -139,6 +140,9 @@
#ifndef SSH_OLD_EVP
aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
+ if (fips_mode())
+ aes_ctr.flags |= EVP_CIPH_FLAG_FIPS;
+
#endif
return (&aes_ctr);
}
diff -ruN openssh-6.5p1_orig/fips.c openssh-6.5p1_patched/fips.c
--- openssh-6.5p1_orig/fips.c 1970-01-01 05:30:00.000000000 +0530
+++ openssh-6.5p1_patched/fips.c 2014-02-07 00:56:54.000000000
+0530
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2012 Petr Cerny. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fips.h"
+
+#include "log.h"
+
+enum hgp {
+ HGP_LEN,
+ HGP_NID
+};
+
+static int fips_state = -1;
+
+static const struct Hashes {
+ enum hash_type ht;
+ int byte_length;
+ int nid;
+} hashes[] = {
+ { HASH_MD5, HASH_LEN_MD5, NID_md5 },
+ { HASH_SHA1, HASH_LEN_SHA1, NID_sha1 },
+ { HASH_SHA256, HASH_LEN_SHA256, NID_sha256 },
+ { HASH_err, -1, -1 }
+};
+
+int
+fips_mode()
+{
+ if (-1 == fips_state) {
+ fips_state = FIPS_mode();
+ if (fips_state)
+ debug("FIPS mode initialized");
+ }
+ return fips_state;
+}
+
+static int
+fips_hash_get_param(enum hash_type ht, int param)
+{
+ int i;
+ for (i = 0; i < HASH_err; i++) {
+ if (hashes[i].ht == ht) {
+ switch (param) {
+ case HGP_LEN:
+ return hashes[i].byte_length;
+ case HGP_NID:
+ return hashes[i].nid;
+ default:
+ fatal("Fatal error: internal error
at %s:%u",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ /* should not be reached */
+ fatal("Fatal error: incorrect hash type '%i' at %s:%u",
+ ht, __FILE__, __LINE__);
+// return -1;
+}
+
+int
+fips_hash2nid(enum hash_type ht)
+{
+ return fips_hash_get_param(ht, HGP_NID);
+}
+
+int
+fips_hash_len(enum hash_type ht)
+{
+ return fips_hash_get_param(ht, HGP_LEN);
+}
+
+void
+fips_correct_fp_type(enum fp_type *fp)
+{
+ int fips;
+
+ fips = fips_mode();
+ switch (fips) {
+ case 0:
+ break;
+ case 1:
+ if (SSH_FP_MD5 == *fp) {
+ *fp = SSH_FP_SHA1;
+ logit("MD5 not allowed in FIPS 140-2 mode,
"
+ "using SHA-1 for key fingerprints
instead.");
+ }
+ break;
+ default:
+ /* should not be reached */
+ fatal("Fatal error: incorrect FIPS mode '%i' at
%s:%u",
+ fips, __FILE__, __LINE__);
+ }
+
+ return;
+}
+
+void
+fips_correct_nid(int *nid)
+{
+ int fips;
+
+ fips = fips_mode();
+ switch (fips) {
+ case 0:
+ break;
+ case 1:
+ if (NID_md5 == *nid) {
+ *nid = NID_sha1;
+ logit("MD5 not allowed in FIPS 140-2 mode,
"
+ "using SHA-1 for hashing instead.");
+ }
+ break;
+ default:
+ /* should not be reached */
+ fatal("Fatal error: incorrect FIPS mode '%i' at
%s:%u",
+ fips, __FILE__, __LINE__);
+ }
+
+ return;
+}
+
+enum hash_type
+fips_hash_min(void)
+{
+ int fips;
+ enum hash_type ht;
+
+ fips = fips_mode();
+ switch (fips) {
+ case 0:
+ ht = HASH_MD5;
+ break;
+ case 1:
+ ht = HASH_SHA1;
+ break;
+ default:
+ /* should not be reached */
+ fatal("Fatal error: incorrect FIPS mode '%i' at
%s:%u",
+ fips, __FILE__, __LINE__);
+ }
+ return ht;
+}
+
+enum hash_type
+fips_hash_nid_min()
+{
+ return fips_hash2nid(fips_hash_min());
+}
+
+const EVP_MD *
+fips_EVP_get_digest_min(void)
+{
+ return EVP_get_digestbynid(fips_hash_nid_min());
+}
+
diff -ruN openssh-6.5p1_orig/fips.h openssh-6.5p1_patched/fips.h
--- openssh-6.5p1_orig/fips.h 1970-01-01 05:30:00.000000000 +0530
+++ openssh-6.5p1_patched/fips.h 2014-02-07 00:58:38.000000000
+0530
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012 Petr Cerny. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
the
+ * documentation and/or other materials provided with the
distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef FIPS_H
+#define FIPS_H
+
+#include <openssl/evp.h>
+
+#include "key.h"
+
+#define HASH_LEN_MD5 16
+#define HASH_LEN_SHA1 20
+#define HASH_LEN_SHA256 32
+#define MAX_HASH_LEN HASH_LEN_SHA256
+
+enum hash_type {
+ HASH_MD5 = 1,
+ HASH_SHA1,
+ HASH_SHA256,
+ HASH_err
+};
+
+int fips_mode(void);
+void fips_correct_fp_type(enum fp_type *);
+void fips_correct_nid(int *);
+
+enum hash_type fips_hash_min(void);
+const EVP_MD *fips_EVP_get_digest_min(void);
+int fips_hash2nid(enum hash_type);
+int fips_hash_len(enum hash_type);
+
+#endif
diff -ruN openssh-6.5p1_orig/key.c openssh-6.5p1_patched/key.c
--- openssh-6.5p1_orig/key.c 2014-01-10 05:28:53.000000000 +0530
+++ openssh-6.5p1_patched/key.c 2014-02-11 00:57:29.000000000 +0530
@@ -57,6 +57,7 @@
#include "misc.h"
#include "ssh2.h"
#include "digest.h"
+#include "fips.h"
static int to_blob(const Key *, u_char **, u_int *, int);
static Key *key_from_blob2(const u_char *, u_int, int);
@@ -425,12 +426,12 @@
}
static char *
-key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
+key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len, enum fp_type
dgst_type)
{
char *retval;
u_int i;
- retval = xcalloc(1, dgst_raw_len * 3 + 1);
+ retval = xcalloc(1, dgst_raw_len * 3 + 1 + SSH_FP_TYPE_STRLEN +
2);
for (i = 0; i < dgst_raw_len; i++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
@@ -438,7 +439,14 @@
}
/* Remove the trailing ':' character */
- retval[(dgst_raw_len * 3) - 1] = '\0';
+ retval[(dgst_raw_len * 3) - 1] = ' ';
+ /* Append hash type */
+ {
+ char hash[SSH_FP_TYPE_STRLEN + 2 + 1];
+ snprintf(hash, sizeof(hash), "[%s]",
key_fp_type_str(dgst_type));
+ strlcat(retval, hash, dgst_raw_len * 3 + 1 +
SSH_FP_TYPE_STRLEN + 2);
+ }
+
return retval;
}
@@ -523,7 +531,7 @@
#define FLDSIZE_Y (FLDBASE + 1)
#define FLDSIZE_X (FLDBASE * 2 + 1)
static char *
-key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key
*k)
+key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key
*k, enum fp_type dgst_type)
{
/*
* Chars to be used after each other every time the worm
@@ -590,8 +598,9 @@
}
/* output lower border */
- *p++ = '+';
- for (i = 0; i < FLDSIZE_X; i++)
+ i = snprintf(p, FLDSIZE_X, "+--[%s]", key_fp_type_str(dgst_type));
+ p += i;
+ for (i--; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
@@ -610,13 +619,13 @@
fatal("key_fingerprint: null from key_fingerprint_raw()");
switch (dgst_rep) {
case SSH_FP_HEX:
- retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
+ retval = key_fingerprint_hex(dgst_raw, dgst_raw_len,
dgst_type);
break;
case SSH_FP_BUBBLEBABBLE:
retval = key_fingerprint_bubblebabble(dgst_raw,
dgst_raw_len);
break;
case SSH_FP_RANDOMART:
- retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len,
k);
+ retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len,
k, dgst_type);
break;
default:
fatal("key_fingerprint: bad digest representation %d",
@@ -628,6 +637,65 @@
return retval;
}
+enum fp_type
+key_fp_type_select(void)
+{
+ static enum fp_type fp;
+ static char fp_defined = 0;
+ char *env;
+
+ if (!fp_defined) {
+ env = getenv(SSH_FP_TYPE_ENVVAR);
+ if (env) {
+ if (!strcasecmp(env, "md5") ||
+ !strcasecmp(env, "md-5"))
+ fp = SSH_FP_MD5;
+ else if (!strcasecmp(env, "sha1") ||
+ !strcasecmp(env, "sha-1"))
+ fp = SSH_FP_SHA1;
+#ifdef HAVE_EVP_SHA256
+ else if (!strcasecmp(env, "sha256") ||
+ !strcasecmp(env, "sha-256"))
+ fp = SSH_FP_SHA256;
+#endif
+ else {
+ error("invalid key type in environment
variable "
+ SSH_FP_TYPE_ENVVAR ": '%s'
- falling back to MD5.",
+ env);
+ fp = SSH_FP_MD5;
+ }
+ } else
+ fp = SSH_FP_MD5;
+
+ if (fips_mode())
+ fips_correct_fp_type(&fp);
+
+ fp_defined = 1;
+ }
+ return fp;
+}
+
+/*
+ * string lengths must be less or equal to SSH_FP_TYPE_STRLEN (defined in
+ * key.h) as to fit into the fingerprint string buffer
+ */
+char *
+key_fp_type_str(enum fp_type dgst_type)
+{
+ switch (dgst_type) {
+ case SSH_FP_MD5:
+ return "MD5";
+ case SSH_FP_SHA1:
+ return "SHA-1";
+#ifdef HAVE_EVP_SHA256
+ case SSH_FP_SHA256:
+ return "SHA-256";
+#endif
+ default:
+ fatal("%s: unknown key fingerprint hash algorithm
requested", __func__);
+ }
+}
+
/*
* Reads a multiple-precision integer in decimal from the buffer, and
advances
* the pointer. The integer must already be initialized. This function
is
diff -ruN openssh-6.5p1_orig/key.h openssh-6.5p1_patched/key.h
--- openssh-6.5p1_orig/key.h 2014-01-10 05:28:53.000000000 +0530
+++ openssh-6.5p1_patched/key.h 2014-02-07 01:09:41.000000000 +0530
@@ -58,6 +58,8 @@
SSH_FP_BUBBLEBABBLE,
SSH_FP_RANDOMART
};
+#define SSH_FP_TYPE_ENVVAR "SSH_FINGERPRINT_TYPE"
+#define SSH_FP_TYPE_STRLEN 8
/* key is stored in external hardware */
#define KEY_FLAG_EXT 0x0001
@@ -109,6 +111,9 @@
int key_write(const Key *, FILE *);
int key_read(Key *, char **);
u_int key_size(const Key *);
+enum fp_type key_fp_type_select(void);
+char *key_fp_type_str(enum fp_type);
+
Key *key_generate(int, u_int);
Key *key_from_private(const Key *);
diff -ruN openssh-6.5p1_orig/mac.c openssh-6.5p1_patched/mac.c
--- openssh-6.5p1_orig/mac.c 2014-01-10 05:07:05.000000000 +0530
+++ openssh-6.5p1_patched/mac.c 2014-02-07 01:14:38.000000000 +0530
@@ -41,6 +41,7 @@
#include "kex.h"
#include "mac.h"
#include "misc.h"
+#include "fips.h"
#include "umac.h"
@@ -60,7 +61,7 @@
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 },
@@ -90,6 +91,30 @@
{ NULL, 0, NULL, 0, 0, 0, 0 }
};
+struct macalg macs_fips140_2[] = {
+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0,
0, 0 },
+#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 },
+#endif
+ { NULL, 0, NULL, 0, 0, 0, 0 }
+};
+
+static struct macalg *
+fips_select_macs(void)
+{
+ int fips = fips_mode();
+ switch (fips) {
+ case 0:
+ return all_macs;
+ case 1:
+ return macs_fips140_2;
+ default:
+ /* should not be reached */
+ fatal("Fatal error: incorrect FIPS mode '%i' at
%s:%u", fips, __FILE__, __LINE__);
+// return NULL;
+ }
+}
/* Returns a list of supported MACs separated by the specified char. */
char *
@@ -97,9 +122,9 @@
{
char *ret = NULL;
size_t nlen, rlen = 0;
- const struct macalg *m;
+ const struct macalg *m = fips_select_macs();
- for (m = macs; m->name != NULL; m++) {
+ for (; m->name != NULL; m++) {
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(m->name);
@@ -134,9 +159,9 @@
int
mac_setup(Mac *mac, char *name)
{
- const struct macalg *m;
+ const struct macalg *m = fips_select_macs();
- for (m = macs; m->name != NULL; m++) {
+ for (; m->name != NULL; m++) {
if (strcmp(name, m->name) != 0)
continue;
if (mac != NULL)
diff -ruN openssh-6.5p1_orig/Makefile.in openssh-6.5p1_patched/Makefile.in
--- openssh-6.5p1_orig/Makefile.in 2014-01-27 12:05:04.000000000
+0530
+++ openssh-6.5p1_patched/Makefile.in 2014-02-07 01:58:20.000000000
+0530
@@ -76,7 +76,7 @@
jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \
kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
ssh-ed25519.o digest.o \
- sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o
+ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o
fips.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
diff -ruN openssh-6.5p1_orig/myproposal.h
openssh-6.5p1_patched/myproposal.h
--- openssh-6.5p1_orig/myproposal.h 2013-12-07 05:54:02.000000000
+0530
+++ openssh-6.5p1_patched/myproposal.h 2014-02-07 02:00:09.000000000
+0530
@@ -109,6 +109,10 @@
"chacha20-poly1305 at openssh.com," \
"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
"aes192-cbc,aes256-cbc,arcfour,rijndael-cbc at lysator.liu.se"
+#define KEX_FIPS_140_2_ENCRYPT \
+ "aes128-ctr,aes192-ctr,aes256-ctr," \
+ "aes128-cbc,3des-cbc," \
+ "aes192-cbc,aes256-cbc,rijndael-cbc at lysator.liu.se"
#define KEX_DEFAULT_MAC \
"hmac-md5-etm at openssh.com," \
@@ -129,6 +133,10 @@
"hmac-ripemd160 at openssh.com," \
"hmac-sha1-96," \
"hmac-md5-96"
+#define KEX_FIPS_140_2_MAC \
+ "hmac-sha1," \
+ SHA2_HMAC_MODES
+
#define KEX_DEFAULT_COMP "none,zlib at openssh.com,zlib"
#define KEX_DEFAULT_LANG ""
diff -ruN openssh-6.5p1_orig/openbsd-compat/arc4random.c
openssh-6.5p1_patched/openbsd-compat/arc4random.c
--- openssh-6.5p1_orig/openbsd-compat/arc4random.c 2013-10-09
05:14:49.000000000 +0530
+++ openssh-6.5p1_patched/openbsd-compat/arc4random.c 2014-02-07
02:02:32.000000000 +0530
@@ -37,6 +37,7 @@
#include <openssl/err.h>
#include "log.h"
+#include "fips.h"
#define KEYSTREAM_ONLY
#include "chacha_private.h"
diff -ruN openssh-6.5p1_orig/ssh-add.c openssh-6.5p1_patched/ssh-add.c
--- openssh-6.5p1_orig/ssh-add.c 2013-12-29 12:14:07.000000000
+0530
+++ openssh-6.5p1_patched/ssh-add.c 2014-02-07 02:08:54.000000000
+0530
@@ -330,7 +330,7 @@
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
- fp = key_fingerprint(key, SSH_FP_MD5,
+ fp = key_fingerprint(key,
key_fp_type_select(),
SSH_FP_HEX);
printf("%d %s %s (%s)\n",
key_size(key), fp, comment,
key_type(key));
diff -ruN openssh-6.5p1_orig/ssh-agent.c openssh-6.5p1_patched/ssh-agent.c
--- openssh-6.5p1_orig/ssh-agent.c 2013-12-29 12:15:52.000000000
+0530
+++ openssh-6.5p1_patched/ssh-agent.c 2014-02-07 02:09:21.000000000
+0530
@@ -198,7 +198,7 @@
char *p;
int ret = -1;
- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+ p = key_fingerprint(id->key, key_fp_type_select(), SSH_FP_HEX);
if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
id->comment, p))
ret = 0;
diff -ruN openssh-6.5p1_orig/ssh.c openssh-6.5p1_patched/ssh.c
--- openssh-6.5p1_orig/ssh.c 2013-12-29 12:23:40.000000000 +0530
+++ openssh-6.5p1_patched/ssh.c 2014-02-07 02:11:49.000000000 +0530
@@ -104,6 +104,7 @@
#include "uidswap.h"
#include "roaming.h"
#include "version.h"
+#include "fips.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
@@ -458,6 +459,8 @@
"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':
@@ -964,6 +967,12 @@
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 -ruN openssh-6.5p1_orig/sshconnect2.c
openssh-6.5p1_patched/sshconnect2.c
--- openssh-6.5p1_orig/sshconnect2.c 2014-01-10 05:28:53.000000000
+0530
+++ openssh-6.5p1_patched/sshconnect2.c 2014-02-07 02:16:14.000000000
+0530
@@ -72,6 +72,7 @@
#include "hostfile.h"
#include "schnorr.h"
#include "jpake.h"
+#include "fips.h"
#ifdef GSSAPI
#include "ssh-gss.h"
@@ -170,6 +171,9 @@
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_140_2_ENCRYPT;
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -185,6 +189,9 @@
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_140_2_MAC;
}
if (options.hostkeyalgorithms != NULL)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
@@ -592,7 +599,7 @@
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
debug2("input_userauth_pk_ok: fp %s", fp);
free(fp);
@@ -1204,7 +1211,7 @@
int have_sig = 1;
char *fp;
- fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(id->key, key_fp_type_select(), SSH_FP_HEX);
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
free(fp);
diff -ruN openssh-6.5p1_orig/sshconnect.c
openssh-6.5p1_patched/sshconnect.c
--- openssh-6.5p1_orig/sshconnect.c 2014-01-10 05:29:24.000000000
+0530
+++ openssh-6.5p1_patched/sshconnect.c 2014-02-07 02:17:50.000000000
+0530
@@ -911,8 +911,8 @@
"key for IP address '%.128s' to the
list "
"of known hosts.", type, ip);
} else if (options.visual_host_key) {
- fp = key_fingerprint(host_key, SSH_FP_MD5,
SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
+ fp = key_fingerprint(host_key,
key_fp_type_select(), SSH_FP_HEX);
+ ra = key_fingerprint(host_key,
key_fp_type_select(),
SSH_FP_RANDOMART);
logit("Host key fingerprint is %s\n%s\n", fp, ra);
free(ra);
@@ -952,8 +952,8 @@
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = key_fingerprint(host_key, SSH_FP_MD5,
SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
+ fp = key_fingerprint(host_key,
key_fp_type_select(), SSH_FP_HEX);
+ ra = key_fingerprint(host_key,
key_fp_type_select(),
SSH_FP_RANDOMART);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
@@ -1217,7 +1217,7 @@
int flags = 0;
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
debug("Server host key: %s %s", key_type(host_key), fp);
free(fp);
@@ -1324,8 +1324,8 @@
continue;
if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i],
&found))
continue;
- fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(found->key, SSH_FP_MD5,
SSH_FP_RANDOMART);
+ fp = key_fingerprint(found->key, key_fp_type_select(),
SSH_FP_HEX);
+ ra = key_fingerprint(found->key, key_fp_type_select(),
SSH_FP_RANDOMART);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
@@ -1346,7 +1346,7 @@
{
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
@");
diff -ruN openssh-6.5p1_orig/sshd.c openssh-6.5p1_patched/sshd.c
--- openssh-6.5p1_orig/sshd.c 2014-01-28 09:38:13.000000000 +0530
+++ openssh-6.5p1_patched/sshd.c 2014-02-07 02:22:10.000000000
+0530
@@ -121,6 +121,7 @@
#include "roaming.h"
#include "ssh-sandbox.h"
#include "version.h"
+#include "fips.h"
#ifdef LIBWRAP
#include <tcpd.h>
@@ -1717,6 +1718,10 @@
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;
@@ -2429,6 +2434,9 @@
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_140_2_ENCRYPT;
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -2438,6 +2446,9 @@
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_140_2_MAC;
}
if (options.compression == COMP_NONE) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
diff -ruN openssh-6.5p1_orig/ssh-keygen.c
openssh-6.5p1_patched/ssh-keygen.c
--- openssh-6.5p1_orig/ssh-keygen.c 2013-12-07 05:54:02.000000000
+0530
+++ openssh-6.5p1_patched/ssh-keygen.c 2014-02-07 02:27:57.000000000
+0530
@@ -746,7 +746,7 @@
enum fp_type fptype;
char *fp, *ra;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fp_type_select();
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
pkcs11_init(0);
@@ -801,7 +801,7 @@
public = key_load_public(identity_file, &comment);
if (public != NULL) {
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5,
SSH_FP_RANDOMART);
+ ra = key_fingerprint(public, key_fp_type_select(),
SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, comment,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -867,7 +867,7 @@
}
comment = *cp ? cp : comment;
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5,
SSH_FP_RANDOMART);
+ ra = key_fingerprint(public, key_fp_type_select(),
SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp,
comment ? comment : "no comment", key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -988,10 +988,10 @@
enum fp_type fptype;
char *fp, *ra;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 :
key_fp_type_select();
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE :
SSH_FP_HEX;
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5,
SSH_FP_RANDOMART);
+ ra = key_fingerprint(public, key_fp_type_select(),
SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, name,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
@@ -1878,9 +1878,9 @@
fatal("%s is not a certificate", identity_file);
v00 = key->type == KEY_RSA_CERT_V00 || key->type ==
KEY_DSA_CERT_V00;
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ key_fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), SSH_FP_HEX);
printf("%s:\n", identity_file);
printf(" Type: %s %s certificate\n", key_ssh_name(key),
@@ -2686,8 +2686,8 @@
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5,
SSH_FP_HEX);
- char *ra = key_fingerprint(public, SSH_FP_MD5,
+ char *fp = key_fingerprint(public, key_fp_type_select(),
SSH_FP_HEX);
+ char *ra = key_fingerprint(public, key_fp_type_select(),
SSH_FP_RANDOMART);
printf("Your public key has been saved in %s.\n",
identity_file);
diff -ruN openssh-6.5p1_orig/ssh-rsa.c openssh-6.5p1_patched/ssh-rsa.c
--- openssh-6.5p1_orig/ssh-rsa.c 2014-01-10 05:28:53.000000000
+0530
+++ openssh-6.5p1_patched/ssh-rsa.c 2014-02-07 02:36:26.000000000
+0530
@@ -33,6 +33,7 @@
#include "misc.h"
#include "ssh.h"
#include "digest.h"
+#include "fips.h"
static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA
*);
@@ -56,6 +57,7 @@
/* hash the data */
hash_alg = SSH_DIGEST_SHA1;
nid = NID_sha1;
+ fips_correct_nid(&nid);
if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
error("%s: bad hash algorithm %d", __func__, hash_alg);
return -1;
--- PATCH END
-----Original Message-----
From: Steve Marquess [mailto:marquess at opensslfoundation.com]
Sent: Monday, February 17, 2014 5:35 PM
To: openssh-unix-dev at mindrot.org
Cc: manish.jagtap at airtightnetworks.com
Subject: Re: [ DRAFT PATCH ] - FIPS 140-2 patch for OpenSSH 6.5p1
On 02/17/2014 01:09 AM, Manish Jagtap wrote:
> Hi,
>
>
>
> Here is FIPS 140-2 patch for OpenSSH 6.5p1. Since our expertise in
> OpenSSH code is limited, request moderators to validate this patch and
> update as required.
I didn't see any patch but the following comments apply regardless.
For a long time I hoped to see native OpenSSL FIPS module support in
OpenSSH. Over the years OSF has prepared a number of patches such as:
http://opensslfoundation.com/export/openssh/openssh-6.0p1.fips-revised.pat
ch
for interested clients.
However, with continuing evolution of OpenSSH and changing FIPS 140-2
requirements such support is becoming increasingly difficult. In order to
make any reasonable claim that an application like OpenSSH is "FIPS
140-2 compliant" *all* cryptography used by that application must be
implemented in the validated module(s). OpenSSH has always had some
inlined cryptography, but the recent introduction of "non-NIST"
cryptography exacerbates that issue.
Then there is the additional consideration that FIPS 140-2 is only
desirable in a context (USG and DoD) where x.509 support is also
mandatory. OpenSSH has adopted a different (and more robust) certificate
scheme. FIPS 140-2 has always been focused on compliance to a specific
ritualized policy and process, and thus is necessarily less secure in an
absolute sense, while OpenSSH is focused on real-world security. IMHO that
discrepancy will probably continue to grow.
So while it remains technically possible to jam the round OpenSSH peg into
the square FIPS 140-2 hole, I'm no longer sure it makes sense to attempt
it in the baseline OpenSSH.
-Steve M.
--
Steve Marquess
OpenSSL Software Foundation, Inc.
1829 Mount Ephraim Road
Adamstown, MD 21710
USA
+1 877 673 6775 s/b
+1 301 874 2571 direct
marquess at opensslfoundation.com
marquess at openssl.com
gpg/pgp key: http://openssl.com/docs/0xCE69424E.asc
More information about the openssh-unix-dev
mailing list