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@xxxxxxxxx> * Copyright (c) 1995 Tatu Ylonen <ylo@xxxxxxxxx>, 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@xxxxxxxxx> * Copyright (c) 1995 Tatu Ylonen <ylo@xxxxxxxxx>, 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@xxxxxxxxxxxxxx", + 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@xxxxxxxxxxx", + SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, + { "aes256-gcm@xxxxxxxxxxx", + SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, +#endif + { "chacha20-poly1305@xxxxxxxxxxx", + 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@xxxxxxxxxxx," \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@xxxxxxxxxxxxxx" +#define KEX_FIPS_140_2_ENCRYPT \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "aes128-cbc,3des-cbc," \ + "aes192-cbc,aes256-cbc,rijndael-cbc@xxxxxxxxxxxxxx" #define KEX_DEFAULT_MAC \ "hmac-md5-etm@xxxxxxxxxxx," \ @@ -129,6 +133,10 @@ "hmac-ripemd160@xxxxxxxxxxx," \ "hmac-sha1-96," \ "hmac-md5-96" +#define KEX_FIPS_140_2_MAC \ + "hmac-sha1," \ + SHA2_HMAC_MODES + #define KEX_DEFAULT_COMP "none,zlib@xxxxxxxxxxx,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@xxxxxxxxxxxxxxxxxxxxx] Sent: Monday, February 17, 2014 5:35 PM To: openssh-unix-dev@xxxxxxxxxxx Cc: manish.jagtap@xxxxxxxxxxxxxxxxxxxx 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@xxxxxxxxxxxxxxxxxxxxx marquess@xxxxxxxxxxx gpg/pgp key: http://openssl.com/docs/0xCE69424E.asc _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev