From owner-freebsd-security@FreeBSD.ORG Sun Jul 7 17:42:10 2013 Return-Path: Delivered-To: FreeBSD-security@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id E2B21A11 for ; Sun, 7 Jul 2013 17:42:10 +0000 (UTC) (envelope-from nanoman@nanoman.ca) Received: from mail.nanoman.ca (mail.nanoman.ca [76.10.173.222]) by mx1.freebsd.org (Postfix) with ESMTP id 5454F1D75 for ; Sun, 7 Jul 2013 17:42:09 +0000 (UTC) Received: from nanocomputer.nanoman.ca (nanocomputer.nanoman.ca [192.168.1.9]) by mail.nanoman.ca (Postfix) with ESMTP id D08DB11602 for ; Sun, 7 Jul 2013 13:36:22 -0400 (EDT) Received: by nanocomputer.nanoman.ca (Postfix, from userid 62661) id 5257017288; Sun, 7 Jul 2013 13:36:22 -0400 (EDT) Date: Sun, 7 Jul 2013 13:36:22 -0400 From: "A.J. Kehoe IV (Nanoman)" To: FreeBSD-security@FreeBSD.org Subject: Better Password Hashes Message-ID: <20130707173622.GA21102@nanocomputer.nanoman.ca> MIME-Version: 1.0 Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg=sha1; boundary="dc+cDN39EJAMEtIO" Content-Disposition: inline Organization: Nanoman's Company User-Agent: Mutt (FreeBSD) X-BeenThere: freebsd-security@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: nanoman@nanoman.ca List-Id: "Security issues \[members-only posting\]" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 07 Jul 2013 17:42:11 -0000 --dc+cDN39EJAMEtIO Content-Type: multipart/mixed; boundary="n8g4imXOkfNTN/H1" Content-Disposition: inline --n8g4imXOkfNTN/H1 Content-Type: text/plain; charset=iso-8859-1; format=flowed Content-Disposition: inline Content-Transfer-Encoding: quoted-printable My friend and fellow FreeBSD enthusiast Derek Marcotte recently pointed out= that FreeBSD has no easy way to set the logarithmic rounds for bcrypt pass= word hashes. Doing so is trivial in OpenBSD, and considering the capabilit= ies of current GPU attacks, I want this functionality. This issue was raised over eight years ago in kern/75934 by Steven Alexande= r Jr., who included a patch to add this feature. Unfortunately, this seems= to have been completely overlooked, and there were no public responses to = this PR. I commissioned Derek to come up with a solution by either updating Steven's= patch or by devising a new method. To paraphrase Derek's comments: -----BEGIN PARAPHRASIS----- I did some research into what other *BSDs are doing. OpenBSD and NetBSD us= e the algorithm name, a comma, and then the number of rounds: http://www.openbsd.org/cgi-bin/man.cgi?query=3Dlogin.conf&sektion=3D5 localcipher=3Dblowfish,6 http://netbsd.gw.com/cgi-bin/man-cgi?passwd.conf+5+NetBSD-current localcipher=3Dblowfish,6 To me, this isn't a good way to do it because we'd need special rules to pa= rse this extra field out of the previously unstructured data. This parsing= would be algorithm dependant. Everyone knows about modular crypt, so why not feed the modular crypt salt = string as the parameter directly? Instead of messing with different names,= give the power to the system admin to control this directly, so when crypt= is updated, pam_unix can take advantage. Each implementation of crypt alg= orithms already includes parsing of the salt magic. I found that patching pam_unix was the least invasive way to handle configu= rable hashes for login. I've added a passwd_modular parameter that will su= persede passwd_format when defined. passwd_modular will feed directly into= crypt, so any options that are passed to crypt via the salt are immediatel= y available for use in the master.passwd file. For example: :passwd_modular=3D$2a$11$:\ Now you can also set the rounds for sha512: :passwd_modular=3D$6$rounds=3D1000000$:\ To disable passwd_modular and revert to passwd_format: :passwd_modular=3Ddisabled:\ This also lets admins shoot themselves in the foot by supplying invalid or = bad salts. For example: :passwd_modular=3D$1$constantsalt:\ I had considered setting a second variable like ":passwd_param=3D8:\", but = then you really have to mess with crypt to make it work. I think it would = be a much more invasive change, and unnecessary, providing the documentatio= n for login.conf is brought up to date. FreeBSD 8.* doesn't have access to the SHA family of hashes. If this is me= rged back into 8, it will give much stronger password security when using $= 2a$08$ (or higher) than is currently available. bcrypt is preferable to sha512 because of its resilience to current GPU att= acks. This is expected to change. Hopefully, my patch will lay some groun= dwork to incorporate scrypt. -----END PARAPHRASIS----- I've attached a copy of Derek's patches for the FreeBSD 9-STABLE versions o= f pam_unix and the login.conf man page. These may have to be adjusted for = HEAD. I really like Derek's solution. It's working perfectly for bcrypt on my ow= n network, and I'm planning to distribute it to the hundreds of FreeBSD ser= vers that I am responsible for maintaining. In my opinion, committing Dere= k's patches will allow kern/75934 to be closed. --=20 A.J. Kehoe IV (Nanoman) | /"\ ASCII Ribbon Campaign Nanoman's Company | \ / - No HTML/RTF in E-mail E-mail: nanoman@nanoman.ca | X - No proprietary attachments WWW: http://www.nanoman.ca/ | / \ - Respect for open standards --n8g4imXOkfNTN/H1 Content-Type: text/x-diff; charset=iso-8859-1 Content-Disposition: attachment; filename="pam_unix.c.patch" Content-Transfer-Encoding: quoted-printable --- /usr/src/lib/libpam/modules/pam_unix/pam_unix.c.orig 2013-07-07 10:20:4= 6.000000000 -0400 +++ /usr/src/lib/libpam/modules/pam_unix/pam_unix.c 2013-07-07 12:53:28.000= 000000 -0400 @@ -68,8 +68,9 @@ #include =20 #define PASSWORD_HASH "md5" +#define NOMODULAR "disabled" #define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ -#define SALTSIZE 32 +#define SALTSIZE 64 =20 #define LOCKED_PREFIX "*LOCKED*" #define LOCKED_PREFIX_LEN (sizeof(LOCKED_PREFIX) - 1) @@ -77,6 +78,7 @@ static void makesalt(char []); =20 static char password_hash[] =3D PASSWORD_HASH; +static char password_nomodular[] =3D NOMODULAR; =20 #define PAM_OPT_LOCAL_PASS "local_pass" #define PAM_OPT_NIS_PASS "nis_pass" @@ -272,7 +274,7 @@ char salt[SALTSIZE + 1]; login_cap_t *lc; struct passwd *pwd, *old_pwd; - const char *user, *old_pass, *new_pass; + const char *user, *old_pass, *new_pass, *modular_salt; char *encrypted; time_t passwordtime; int pfd, tfd, retval; @@ -378,16 +380,23 @@ return (PAM_BUF_ERR); =20 lc =3D login_getclass(pwd->pw_class); - if (login_setcryptfmt(lc, password_hash, NULL) =3D=3D NULL) - openpam_log(PAM_LOG_ERROR, - "can't set password cipher, relying on default"); - =09 + + memset(salt, 0, sizeof(salt)); + modular_salt =3D login_getcapstr(lc, "passwd_modular", password_nomodula= r, NULL); + if (strcmp(modular_salt, password_nomodular) =3D=3D 0) { + if (login_setcryptfmt(lc, password_hash, NULL) =3D=3D NULL) + openpam_log(PAM_LOG_ERROR, + "can't set password cipher, relying on default"); + } else { + strncpy(salt, modular_salt, sizeof(salt) - 1); + } + /* set password expiry date */ pwd->pw_change =3D 0; passwordtime =3D login_getcaptime(lc, "passwordtime", 0, 0); if (passwordtime > 0) pwd->pw_change =3D time(NULL) + passwordtime; - =09 + login_close(lc); makesalt(salt); pwd->pw_passwd =3D crypt(new_pass, salt); @@ -464,13 +473,25 @@ makesalt(char salt[SALTSIZE]) { int i; + int remainder; + + /* If a salt magic has already been set, skip to the free area */ + for (i =3D 0; i < SALTSIZE; i++) { + if (salt[i] =3D=3D '\0') { + break; + } + } =20 /* These are not really random numbers, they are just * numbers that change to thwart construction of a * dictionary. This is exposed to the public. */ - for (i =3D 0; i < SALTSIZE; i +=3D 4) - to64(&salt[i], arc4random(), 4); + while (i < SALTSIZE) { + remainder =3D SALTSIZE - i; + to64(&salt[i], arc4random(), (remainder < 4 ? remainder : 4) ); + i +=3D 4; + } + salt[SALTSIZE] =3D '\0'; } =20 --n8g4imXOkfNTN/H1 Content-Type: text/x-diff; charset=iso-8859-1 Content-Disposition: attachment; filename="login.conf.5.patch" Content-Transfer-Encoding: quoted-printable --- /usr/src/lib/libutil/login.conf.5.orig 2013-07-04 10:16:42.000000000 -0= 400 +++ /usr/src/lib/libutil/login.conf.5 2013-07-04 10:31:59.000000000 -0400 @@ -275,6 +275,14 @@ NIS clients using a .No non- Ns Fx NIS server should probably use "des". +.It "passwd_modular string $02$08$ The encryption format that new or" +changed passwords will use, based on the=20 +.Xr crypt 3=20 +magic constants. Overrides passwd_format when set. Valid values include "= disabled" to fall back to passwd_format, $02$08$ would be blf with work fac= tor 8, or $6$rounds=3D5000$ would be sha512 with 5000 rounds, will accept a= ny of the magic salt values from +.Xr crypt 3 +Be aware that setting this to an invalid crypt magic will likely fall back= to des. Appending text to after the salt magic, (e.g. $02$08$dontdothis) w= ill weaken the salt. Please refer to +.Xr crypt 3 +for proper syntax and useage. .It "passwd_prompt string The password prompt presented by .Xr login 1 .It "times.allow list List of time periods during which --n8g4imXOkfNTN/H1-- --dc+cDN39EJAMEtIO Content-Type: application/x-pkcs7-signature Content-Disposition: attachment; filename="smime.p7s" Content-Transfer-Encoding: base64 MIIPUAYJKoZIhvcNAQcCoIIPQTCCDz0CAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHAaCC DLwwggV3MIIDX6ADAgECAgMM9zQwDQYJKoZIhvcNAQEFBQAweTEQMA4GA1UEChMHUm9vdCBD QTEeMBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0IFNp Z25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2VydC5vcmcwHhcN MTMwMzExMjMyMzI2WhcNMTMwOTA3MjMyMzI2WjA9MRgwFgYDVQQDEw9DQWNlcnQgV29UIFVz ZXIxITAfBgkqhkiG9w0BCQEWEm5hbm9tYW5AbmFub21hbi5jYTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAK9WRGqRDUDjWwNIfZTBp4FL5bI0kY3ZqvM6tEO+Sqp5YxATre8F a+BYbeNp/8MKfuPrRgE2jRzlePAx7kpvZUhRTGAZpncmHC7Z3FDl8Ugid4193ReCfPypb9Gs 3ZgPfzJyNuDeCM3amz/cDXC/makJLpmLzu95D91hD+V30iActE5j1tNewMq9qJRoEdr5Tqus bUjjDm8kiK5sz9JzQjFoufuaWIR57w2Sm1gDVZ0MH46fxZ/SwLDDzt4VC2u+1oS4KSmVUm6X Wv1/Fmdf2sOOu9Ro2xVjJHW+j16lsFPPj+lkDv5tb0G7I2vBoKEQg/s+h8J4F+l/xPL3O5xB c68CAwEAAaOCAUIwggE+MAwGA1UdEwEB/wQCMAAwVgYJYIZIAYb4QgENBEkWR1RvIGdldCB5 b3VyIG93biBjZXJ0aWZpY2F0ZSBmb3IgRlJFRSBoZWFkIG92ZXIgdG8gaHR0cDovL3d3dy5D QWNlcnQub3JnMA4GA1UdDwEB/wQEAwIDqDBABgNVHSUEOTA3BggrBgEFBQcDBAYIKwYBBQUH AwIGCisGAQQBgjcKAwQGCisGAQQBgjcKAwMGCWCGSAGG+EIEATAyBggrBgEFBQcBAQQmMCQw IgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLmNhY2VydC5vcmcwMQYDVR0fBCowKDAmoCSgIoYg aHR0cDovL2NybC5jYWNlcnQub3JnL3Jldm9rZS5jcmwwHQYDVR0RBBYwFIESbmFub21hbkBu YW5vbWFuLmNhMA0GCSqGSIb3DQEBBQUAA4ICAQCnV4v+VWIuG3iB7apL1Ht4m86rttYwtG/r JTuacyE7NB2nhK5/MIj3+bVy73g9hxco7FF+L+wMvEm7J19Z6f97p7LlfN0JASWEEDpnzzyZ RCHktiO7IYWGNWGEhR1WDJfalqupo33x0Z7vs51koZuxW1yJV+ZQTzBIJRKWcENA3r2pVhRm L32yzw0qx+JXGSimcpKRv45xl2bPQjF0vEFr69ur74YDQc9k0DH/ZWzbOayq3PDzrRBzQTZ5 8rS95EqFNAR3lNDZ9OABCD/L6XcJB5KIntY3DrL9p1zni9NhWPkcXYDY9xfyfI4dMbQUD/WY tgn13Ihu5QUgNZ9VePIAKbtJZBsptEoKSHnQx2upcEYmyEIaH8lm6iOsC6uBfCSjYyp3W1BK eW95/pRkMWWBt65WEe55sxEEMM40SBT4+ycjvw1UWB2R4aRdgDlLLZK5/uvBP0mVzYO0Mi3g E8UD+tNKEhlo8H9t8AXLrij1mStSFsF3C76DN5YuBFaKr4odQHaJskyz9oxAX0nwqwJbjoYI Z3RhxNXd1DK1hIEWclEqdnuRSICEqqI3htG85SyVr62OZJg2zml2swhZLg2Q9yrCnZGCy46N lLAzoV3tEG9Oh4MTsa+1hzJeNLXnvUWE5jHku9SeClmDM6J0Bp9FnsSnDNlUEYYL443qFBz7 zzCCBz0wggUloAMCAQICAQAwDQYJKoZIhvcNAQEEBQAweTEQMA4GA1UEChMHUm9vdCBDQTEe MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0IFNpZ25p bmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2VydC5vcmcwHhcNMDMw MzMwMTIyOTQ5WhcNMzMwMzI5MTIyOTQ5WjB5MRAwDgYDVQQKEwdSb290IENBMR4wHAYDVQQL ExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNBIENlcnQgU2lnbmluZyBBdXRo b3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRAY2FjZXJ0Lm9yZzCCAiIwDQYJKoZIhvcN AQEBBQADggIPADCCAgoCggIBAM4iwOJGfew2KAdQlvKgM0CMS/E7Zj8x5WsCNtvWfPbxiI9O dzYFQZX5CfASz0aGc2C3bn7owFhkrs2wrUUXDGP6Zwro1tK/PueYxPBM+uADuzVdbCHeniDZ us1mMjdy+vcI9cfNWMmO5w5e6j7+HKEUChVshoRbZGYqeqlLU3n1iKJ77i8KYSuNsn5NVqUT 7Orakp6sREEeWGBlBWb4wES9y5T3Qn4L92VomFEF8PMFkQQdGxeC7MhXu8NreojxsHLMJVsg kewWAhKPMukXGEjQxwUuAjBCuCWcBWs/qjqn61NI9+jStgeY3BvGNH9/yRyCegVYKwhb8zii qxddZsmY154Qi6LS3XSa93EMcmDfzW+YM52WNHY+JHqSsA6VHm/moEU4R6rXQe1KtxL21xuD ig8u2Am2WdeqBP/Sk31oLt2LS6tYui+N6pWnoMNUiaX724tRIp2yw74RviyRhouWeK0g04ov Gj/G0FFlhyGxGQFlf0Uch/V80EFMTymYIf0zH3UMBFH6GXfb1BQc7oHDHfWYt2kGkSLdAFDM gTGsEgd7ONpoW+Yr1H7JX63o63JM8wHlSyC/mqZXypEAAYuhdSE3tWMNZz5GT3AgZ87F1lnb AuDw0svNumK3kEHo3SDkKbxkKULIItx4mv9D7JgbCVFLWlrCcfHEy3Op5aELAgMBAAGjggHO MIIByjAdBgNVHQ4EFgQUFrUyG9TH8+DmjvO90rA67rI5GNEwgaMGA1UdIwSBmzCBmIAUFrUy G9TH8+DmjvO90rA67rI5GNGhfaR7MHkxEDAOBgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0 dHA6Ly93d3cuY2FjZXJ0Lm9yZzEiMCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0 eTEhMB8GCSqGSIb3DQEJARYSc3VwcG9ydEBjYWNlcnQub3JnggEAMA8GA1UdEwEB/wQFMAMB Af8wMgYDVR0fBCswKTAnoCWgI4YhaHR0cHM6Ly93d3cuY2FjZXJ0Lm9yZy9yZXZva2UuY3Js MDAGCWCGSAGG+EIBBAQjFiFodHRwczovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwNAYJ YIZIAYb4QgEIBCcWJWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZy9pbmRleC5waHA/aWQ9MTAwVgYJ YIZIAYb4QgENBEkWR1RvIGdldCB5b3VyIG93biBjZXJ0aWZpY2F0ZSBmb3IgRlJFRSBoZWFk IG92ZXIgdG8gaHR0cDovL3d3dy5jYWNlcnQub3JnMA0GCSqGSIb3DQEBBAUAA4ICAQAox+6c ggK6XIASyjUKHYFviWqZzPJoD3+n4Y1YlT698gbDkFqstWD2mUMBo4hwnJ1inaSHr2dYDTA2 O+atSNPLdAKGcT7iKwNo8TRiQEY7U+oo9Kz7ZpVTik1d/TvZYNfKeWk7sWWSpsaBglyczetN AYql3xFVqhXKHzfAgphwYdtqfJajji5UPk8hqZDv3IK/3OhFrU2Qcwg8lGWwBJl2f+K8wmoV qpcENyTYHpRObQ5RvtbEj8qWbfdD3+gwZSc7e7tDQ2PEQ/ey7GjM4RmOIvuY4XtaPgE3O4sI sKLzlU4ay5vNmrHbsnDwLUrb2LDjb0VIMxL//jwyKlT3xPeK8Igjwkf+ZHpxwNEepmOwB36k L9MBj9yfK7bGCKkPk0gl/BL9n0Lc88Q+9lew191p0QZ3NApL0sqg/xzGjMkWvsTMMjdoc18I +1H3SVM2BQqVAkzyeRoQ9tg6dZzzHfGiDXBnhhuzFvUv5aTreYb5PQvCcwulmaxv/Ge45S8L phgkjXvRSDUpGECsk2DhloZQtHpZ2I8hC5/PgpHGO79r3AeRuZdWI6q2bJTGSAY85M5OquT2 LwncU28u/HTrOmOZwqasibynskSgDYoQ42zyJMv6m59wRy7eFIvUsiAJlqJk8SQc3KE1nBWy 1LxVLn0G9ZwOVfRa1pPadq0lc0zFQzGCAlwwggJYAgEBMIGAMHkxEDAOBgNVBAoTB1Jvb3Qg Q0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEiMCAGA1UEAxMZQ0EgQ2VydCBT aWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJARYSc3VwcG9ydEBjYWNlcnQub3JnAgMM 9zQwCQYFKw4DAhoFAKCBsTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ BTEPFw0xMzA3MDcxNzM2MjJaMCMGCSqGSIb3DQEJBDEWBBR0mKxlfZbMuxrxKXqfXBRnyBgB SjBSBgkqhkiG9w0BCQ8xRTBDMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG 9w0DAgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQAbiqNA WEXKX7girXm3MT5pp98eEe5GMEMWfaIRtJWvpTLPkkAghBwyWcU2+2Z4vxUUJOABNnJmJznD zrv4DQwaZ2DcmdArhvgyq28drWeB7qL1hsPACKm1MZ2HD53ZKBwl0GiMR8IVqC4G6AtDwIhb NAY6HJu98Xrg4zZaKIoRr66AWq95fQgOKButaf3AuZ3tfI8Bnht8MbnlicDCkc8Hn8DPdOT1 B3+k0r3q1qWtMPifo3wkSQKzS0RxXauz6owDYGrg252mgWWz2/B2hVGfl27HWva7lvFHComL iVwNK39jwZ11C2dGd0CFQVkry/M9eEX6+CHp4akZjxkyo/Al --dc+cDN39EJAMEtIO--