Jilles Tjoelker
2015-Feb-14 23:17 UTC
[patch] libcrypt & friends - modular crypt format support in /etc/login.conf
On Tue, Feb 10, 2015 at 07:26:07AM -0500, Derek (freebsd lists) wrote:> I've been working on this for a while, and I've produced a patch > that does a few things with the base system:> 1. allows modular crypt to be specified as passwd_format in > /etc/login.conf > - this allows setting the algorithm *and rounds*, i.e. $2b$10$ > for users of varying classes. > - this will allow any future algorithms and parameters > supported by crypt(3) to be supported by the tools around login.confOK.> 2. introduces a new api, crypt_makesalt which will generate an > appropriate salt for any algorithm selectedI like the idea.> 3. updates userland to use this API, and removes totally the > {crypt_set_format, login_setcryptfmt, login_getcryptfmt} APIsRemoving API functions completely requires a SHLIB_MAJOR bump. I think this can be avoided by replacing the functions with a stub instead, so they would behave as if the default always applied and not allow changes to it.> 4. switches crypt algorithms to use thread-local storage, so the > good old global crypt buffer is thread-localThis uses quite a bit of memory for each thread created, even if it does not call crypt() at all. Fortunately, libcrypt is not commonly used. Given that crypt() has never been thread-safe, consider implementing crypt_r() as in glibc and leaving crypt() thread-unsafe. Thread-local storage via pthread_key_create() (one key for libcrypt) is still "magic" but reduces the memory waste for threads that do not call crypt().> 5. includes a bunch of new test vectors for libcrypt ATF testsOK. Some remarks about the code: lib/libcrypt/crypt.c crypt_makesalt()> b64_from_24bit((uint8_t) rand_buf[2], (uint8_t) rand_buf[1], (uint8_t) > rand_buf[0], diff, (int *) &(diff), &out);All these casts can be avoided by making the affected variables the proper type in the first place. The cast of &diff causes a strict-aliasing violation and is definitely wrong on 64-bit big-endian systems. rand_buf is a salt, not a secret, so clearing it afterwards is unnecessary. Consider memcpy() and adding '\0' afterward instead of strncpy(). It seems unnecessary to clear the buffer completely. -- Jilles Tjoelker
John-Mark Gurney
2015-Feb-14 23:42 UTC
[patch] libcrypt & friends - modular crypt format support in /etc/login.conf
Jilles Tjoelker wrote this message on Sun, Feb 15, 2015 at 00:17 +0100:> On Tue, Feb 10, 2015 at 07:26:07AM -0500, Derek (freebsd lists) wrote: > > 3. updates userland to use this API, and removes totally the > > {crypt_set_format, login_setcryptfmt, login_getcryptfmt} APIs > > Removing API functions completely requires a SHLIB_MAJOR bump. I think > this can be avoided by replacing the functions with a stub instead, so > they would behave as if the default always applied and not allow changes > to it.It shouldn't be hard to support crypt_{get,set}_format, since default is supported for find_format... As for login_getcryptfmt, I can't find it... and if we keep crypt_{get,set}_format, we can keep login_setcryptfmt, but just mark them as deprecated...> > 4. switches crypt algorithms to use thread-local storage, so the > > good old global crypt buffer is thread-local > > This uses quite a bit of memory for each thread created, even if it does > not call crypt() at all. Fortunately, libcrypt is not commonly used.And not linked against normally, so, I don't see an issue...> Given that crypt() has never been thread-safe, consider implementing > crypt_r() as in glibc and leaving crypt() thread-unsafe.We should go full thread safe, though that requirese some work on most of the functions, as it appears that only sha256 and sha512 are safe...> Thread-local storage via pthread_key_create() (one key for libcrypt) is > still "magic" but reduces the memory waste for threads that do not call > crypt().With the way the crypt is pluggable, sharing storage between implementations doesn't seem doable... Also, I just realized that crypt_sha256 and crypt_sha512 are not safe in their use of __thread... As the buffer isn't static, if the same thread calls again, it could be previously returns memory gets free'd by the realloc call...> rand_buf is a salt, not a secret, so clearing it afterwards is > unnecessary. > > Consider memcpy() and adding '\0' afterward instead of strncpy(). It > seems unnecessary to clear the buffer completely.I had thought of both of these before, and agree that the salt is not a secret (it is kept hidden), but, it leaks information, and _makesalt is called so rarely, that saving the time doesn't make sense... So, I'd prefer to keep the code as is WRT these points.. -- John-Mark Gurney Voice: +1 415 225 5579 "All that I will do, has been done, All that I have, has not."