diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-04-02 17:00:46 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-04-02 17:00:46 +0000 |
commit | ff886b82a2b65758950bdb4687cf5a1238f697a1 (patch) | |
tree | 46f1826abb9c0fba4227b39fc7ff7e91b3e94c2c /crypt | |
parent | 900d7961d48f704b8396841efb916435faf9c374 (diff) | |
download | glibc-ff886b82a2b65758950bdb4687cf5a1238f697a1.zip glibc-ff886b82a2b65758950bdb4687cf5a1238f697a1.tar.gz glibc-ff886b82a2b65758950bdb4687cf5a1238f697a1.tar.bz2 |
* configure.in: Recognize --enable-nss-crypt.
* config.make.in: Add nss-crypt entry.
* crypt/Makefile: If nss-crypt==yes, don't build md5.c, sha256.c,
sha512.c. Don't run md5test, sha256test, sha512test. Pass -DUSE_NSS
and include path for NSS directory to compiler for md5-crypt,
sha256-crypt, sha512-crypt. Link libcrypt.so with -lfreebl3.
* crypt/md5-crypt.c: If USE_NSS is defined, don't use local hash
function implementation, use NSS. Introduce wrappers around the
hash function calls. Little code size optimization.
* crypt/sha256-crypt.c: Likewise.
* crypt/sha512-crypt.c: Likewise.
* scripts/check-local-headers.sh: Ignore nss3 directory.
* configure.in: Rename pic_default to libc_cv_pic_default.
* config.make.in: Likewise.
Diffstat (limited to 'crypt')
-rw-r--r-- | crypt/Makefile | 19 | ||||
-rw-r--r-- | crypt/md5-crypt.c | 138 | ||||
-rw-r--r-- | crypt/sha256-crypt.c | 149 | ||||
-rw-r--r-- | crypt/sha512-crypt.c | 149 |
4 files changed, 328 insertions, 127 deletions
diff --git a/crypt/Makefile b/crypt/Makefile index 28f8219..3f73d25 100644 --- a/crypt/Makefile +++ b/crypt/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1996, 2000, 2001, 2007 Free Software Foundation, Inc. +# Copyright (C) 1996, 2000, 2001, 2007, 2009 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -26,10 +26,10 @@ headers := crypt.h extra-libs := libcrypt extra-libs-others := $(extra-libs) -libcrypt-routines := crypt-entry md5-crypt md5 sha256-crypt sha256 \ - sha512-crypt sha512 crypt crypt_util +libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \ + crypt_util -tests := cert md5test md5c-test sha256test sha256c-test sha512test sha512c-test +tests := cert md5c-test sha256c-test sha512c-test distribute := ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \ Banner md5.h sha256.h sha512.h @@ -40,9 +40,20 @@ ifeq ($(crypt-in-libc),yes) routines += $(libcrypt-routines) endif +ifeq ($(nss-crypt),yes) +CPPFLAGS-sha256-crypt.c = -DUSE_NSS -I$(shell nss-config --includedir) +CPPFLAGS-sha512-crypt.c = -DUSE_NSS -I$(shell nss-config --includedir) +CPPFLAGS-md5-crypt.c = -DUSE_NSS -I$(shell nss-config --includedir) +$(objpfx)libcrypt.so: -lfreebl3 +else +libcrypt-routines += md5 sha256 sha512 + +tests += md5test sha256test sha512test + $(objpfx)md5test: $(objpfx)md5.o $(objpfx)sha256test: $(objpfx)sha256.o $(objpfx)sha512test: $(objpfx)sha512.o +endif include ../Rules diff --git a/crypt/md5-crypt.c b/crypt/md5-crypt.c index 8a000f0..403cb2b 100644 --- a/crypt/md5-crypt.c +++ b/crypt/md5-crypt.c @@ -1,6 +1,6 @@ /* One way encryption based on MD5 sum. Compatible with the behavior of MD5 crypt introduced in FreeBSD 2.0. - Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2004 + Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2004, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -29,6 +29,52 @@ #include "md5.h" +#ifdef USE_NSS +typedef int PRBool; +# include <hasht.h> +# include <nsslowhash.h> + +# define md5_init_ctx(ctxp, nss_ctxp) \ + do \ + { \ + if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgMD5)) \ + == NULL)) \ + { \ + if (nss_ctx != NULL) \ + NSSLOWHASH_Destroy (nss_ctx); \ + if (nss_alt_ctx != NULL) \ + NSSLOWHASH_Destroy (nss_alt_ctx); \ + return NULL; \ + } \ + NSSLOWHASH_Begin (nss_ctxp); \ + } \ + while (0) + +# define md5_process_bytes(buf, len, ctxp, nss_ctxp) \ + NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len) + +# define md5_finish_ctx(ctxp, nss_ctxp, result) \ + do \ + { \ + unsigned int ret; \ + NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \ + assert (ret == sizeof (result)); \ + NSSLOWHASH_Destroy (nss_ctxp); \ + nss_ctxp = NULL; \ + } \ + while (0) +#else +# define md5_init_ctx(ctxp, nss_ctxp) \ + __md5_init_ctx (ctxp) + +# define md5_process_bytes(buf, len, ctxp, nss_ctxp) \ + __md5_process_bytes(buf, len, ctxp) + +# define md5_finish_ctx(ctxp, nss_ctxp, result) \ + __md5_finish_ctx (ctxp, result) +#endif + + /* Define our magic string to mark salt for MD5 "encryption" replacement. This is meant to be the same as for other MD5 based encryption implementations. */ @@ -56,8 +102,6 @@ __md5_crypt_r (key, salt, buffer, buflen) { unsigned char alt_result[16] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); - struct md5_ctx ctx; - struct md5_ctx alt_ctx; size_t salt_len; size_t key_len; size_t cnt; @@ -94,43 +138,56 @@ __md5_crypt_r (key, salt, buffer, buflen) assert ((salt - (char *) 0) % __alignof__ (md5_uint32) == 0); } +#ifdef USE_NSS + /* Initialize libfreebl3. */ + NSSLOWInitContext *nss_ictx = NSSLOW_Init (); + if (nss_ictx == NULL) + return NULL; + NSSLOWHASHContext *nss_ctx = NULL; + NSSLOWHASHContext *nss_alt_ctx = NULL; +#else + struct md5_ctx ctx; + struct md5_ctx alt_ctx; +#endif + /* Prepare for the real work. */ - __md5_init_ctx (&ctx); + md5_init_ctx (&ctx, nss_ctx); /* Add the key string. */ - __md5_process_bytes (key, key_len, &ctx); + md5_process_bytes (key, key_len, &ctx, nss_ctx); /* Because the SALT argument need not always have the salt prefix we add it separately. */ - __md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx); + md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, + &ctx, nss_ctx); /* The last part is the salt string. This must be at most 8 characters and it ends at the first `$' character (for compatibility with existing implementations). */ - __md5_process_bytes (salt, salt_len, &ctx); + md5_process_bytes (salt, salt_len, &ctx, nss_ctx); /* Compute alternate MD5 sum with input KEY, SALT, and KEY. The final result will be added to the first context. */ - __md5_init_ctx (&alt_ctx); + md5_init_ctx (&alt_ctx, nss_alt_ctx); /* Add key. */ - __md5_process_bytes (key, key_len, &alt_ctx); + md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Add salt. */ - __md5_process_bytes (salt, salt_len, &alt_ctx); + md5_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx); /* Add key again. */ - __md5_process_bytes (key, key_len, &alt_ctx); + md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Now get result of this (16 bytes) and add it to the other context. */ - __md5_finish_ctx (&alt_ctx, alt_result); + md5_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 16; cnt -= 16) - __md5_process_bytes (alt_result, 16, &ctx); - __md5_process_bytes (alt_result, cnt, &ctx); + md5_process_bytes (alt_result, 16, &ctx, nss_ctx); + md5_process_bytes (alt_result, cnt, &ctx, nss_ctx); /* For the following code we need a NUL byte. */ *alt_result = '\0'; @@ -140,11 +197,12 @@ __md5_crypt_r (key, salt, buffer, buflen) bit the first character of the key. This does not seem to be what was intended but we have to follow this to be compatible. */ for (cnt = key_len; cnt > 0; cnt >>= 1) - __md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1, - &ctx); + md5_process_bytes ((cnt & 1) != 0 + ? (const void *) alt_result : (const void *) key, 1, + &ctx, nss_ctx); /* Create intermediate result. */ - __md5_finish_ctx (&ctx, alt_result); + md5_finish_ctx (&ctx, nss_ctx, alt_result); /* Now comes another weirdness. In fear of password crackers here comes a quite long loop which just processes the output of the @@ -152,32 +210,37 @@ __md5_crypt_r (key, salt, buffer, buflen) for (cnt = 0; cnt < 1000; ++cnt) { /* New context. */ - __md5_init_ctx (&ctx); + md5_init_ctx (&ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) - __md5_process_bytes (key, key_len, &ctx); + md5_process_bytes (key, key_len, &ctx, nss_ctx); else - __md5_process_bytes (alt_result, 16, &ctx); + md5_process_bytes (alt_result, 16, &ctx, nss_ctx); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) - __md5_process_bytes (salt, salt_len, &ctx); + md5_process_bytes (salt, salt_len, &ctx, nss_ctx); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) - __md5_process_bytes (key, key_len, &ctx); + md5_process_bytes (key, key_len, &ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) - __md5_process_bytes (alt_result, 16, &ctx); + md5_process_bytes (alt_result, 16, &ctx, nss_ctx); else - __md5_process_bytes (key, key_len, &ctx); + md5_process_bytes (key, key_len, &ctx, nss_ctx); /* Create intermediate result. */ - __md5_finish_ctx (&ctx, alt_result); + md5_finish_ctx (&ctx, nss_ctx, alt_result); } +#ifdef USE_NSS + /* Free libfreebl3 resources. */ + NSSLOW_Shutdown (nss_ictx); +#endif + /* Now we can construct the result string. It consists of three parts. */ cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen)); @@ -192,18 +255,17 @@ __md5_crypt_r (key, salt, buffer, buflen) --buflen; } -#define b64_from_24bit(B2, B1, B0, N) \ - do { \ - unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ - int n = (N); \ - while (n-- > 0 && buflen > 0) \ - { \ - *cp++ = b64t[w & 0x3f]; \ - --buflen; \ - w >>= 6; \ - } \ - } while (0) - + void b64_from_24bit (unsigned int b2, unsigned int b1, unsigned int b0, + int n) + { + unsigned int w = (b2 << 16) | (b1 << 8) | b0; + while (n-- > 0 && buflen > 0) + { + *cp++ = b64t[w & 0x3f]; + --buflen; + w >>= 6; + } + } b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4); b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4); @@ -223,10 +285,12 @@ __md5_crypt_r (key, salt, buffer, buflen) attaching to processes or reading core dumps cannot get any information. We do it in this way to clear correct_words[] inside the MD5 implementation as well. */ +#ifndef USE_NSS __md5_init_ctx (&ctx); __md5_finish_ctx (&ctx, alt_result); memset (&ctx, '\0', sizeof (ctx)); memset (&alt_ctx, '\0', sizeof (alt_ctx)); +#endif if (copied_key != NULL) memset (copied_key, '\0', key_len); if (copied_salt != NULL) diff --git a/crypt/sha256-crypt.c b/crypt/sha256-crypt.c index dbd29e0..0131c80 100644 --- a/crypt/sha256-crypt.c +++ b/crypt/sha256-crypt.c @@ -1,5 +1,5 @@ /* One way encryption based on SHA256 sum. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2007. @@ -28,6 +28,52 @@ #include "sha256.h" +#ifdef USE_NSS +typedef int PRBool; +# include <hasht.h> +# include <nsslowhash.h> + +# define sha256_init_ctx(ctxp, nss_ctxp) \ + do \ + { \ + if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA256)) \ + == NULL)) \ + { \ + if (nss_ctx != NULL) \ + NSSLOWHASH_Destroy (nss_ctx); \ + if (nss_alt_ctx != NULL) \ + NSSLOWHASH_Destroy (nss_alt_ctx); \ + return NULL; \ + } \ + NSSLOWHASH_Begin (nss_ctxp); \ + } \ + while (0) + +# define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \ + NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len) + +# define sha256_finish_ctx(ctxp, nss_ctxp, result) \ + do \ + { \ + unsigned int ret; \ + NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \ + assert (ret == sizeof (result)); \ + NSSLOWHASH_Destroy (nss_ctxp); \ + nss_ctxp = NULL; \ + } \ + while (0) +#else +# define sha256_init_ctx(ctxp, nss_ctxp) \ + __sha256_init_ctx (ctxp) + +# define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \ + __sha256_process_bytes(buf, len, ctxp) + +# define sha256_finish_ctx(ctxp, nss_ctxp, result) \ + __sha256_finish_ctx (ctxp, result) +#endif + + /* Define our magic string to mark salt for SHA256 "encryption" replacement. */ static const char sha256_salt_prefix[] = "$5$"; @@ -66,8 +112,6 @@ __sha256_crypt_r (key, salt, buffer, buflen) __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); unsigned char temp_result[32] __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); - struct sha256_ctx ctx; - struct sha256_ctx alt_ctx; size_t salt_len; size_t key_len; size_t cnt; @@ -123,59 +167,71 @@ __sha256_crypt_r (key, salt, buffer, buflen) assert ((salt - (char *) 0) % __alignof__ (uint32_t) == 0); } +#ifdef USE_NSS + /* Initialize libfreebl3. */ + NSSLOWInitContext *nss_ictx = NSSLOW_Init (); + if (nss_ictx == NULL) + return NULL; + NSSLOWHASHContext *nss_ctx = NULL; + NSSLOWHASHContext *nss_alt_ctx = NULL; +#else + struct sha256_ctx ctx; + struct sha256_ctx alt_ctx; +#endif + /* Prepare for the real work. */ - __sha256_init_ctx (&ctx); + sha256_init_ctx (&ctx, nss_ctx); /* Add the key string. */ - __sha256_process_bytes (key, key_len, &ctx); + sha256_process_bytes (key, key_len, &ctx, nss_ctx); /* The last part is the salt string. This must be at most 16 characters and it ends at the first `$' character. */ - __sha256_process_bytes (salt, salt_len, &ctx); + sha256_process_bytes (salt, salt_len, &ctx, nss_ctx); /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The final result will be added to the first context. */ - __sha256_init_ctx (&alt_ctx); + sha256_init_ctx (&alt_ctx, nss_alt_ctx); /* Add key. */ - __sha256_process_bytes (key, key_len, &alt_ctx); + sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Add salt. */ - __sha256_process_bytes (salt, salt_len, &alt_ctx); + sha256_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx); /* Add key again. */ - __sha256_process_bytes (key, key_len, &alt_ctx); + sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Now get result of this (32 bytes) and add it to the other context. */ - __sha256_finish_ctx (&alt_ctx, alt_result); + sha256_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 32; cnt -= 32) - __sha256_process_bytes (alt_result, 32, &ctx); - __sha256_process_bytes (alt_result, cnt, &ctx); + sha256_process_bytes (alt_result, 32, &ctx, nss_ctx); + sha256_process_bytes (alt_result, cnt, &ctx, nss_ctx); /* Take the binary representation of the length of the key and for every 1 add the alternate sum, for every 0 the key. */ for (cnt = key_len; cnt > 0; cnt >>= 1) if ((cnt & 1) != 0) - __sha256_process_bytes (alt_result, 32, &ctx); + sha256_process_bytes (alt_result, 32, &ctx, nss_ctx); else - __sha256_process_bytes (key, key_len, &ctx); + sha256_process_bytes (key, key_len, &ctx, nss_ctx); /* Create intermediate result. */ - __sha256_finish_ctx (&ctx, alt_result); + sha256_finish_ctx (&ctx, nss_ctx, alt_result); /* Start computation of P byte sequence. */ - __sha256_init_ctx (&alt_ctx); + sha256_init_ctx (&alt_ctx, nss_alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < key_len; ++cnt) - __sha256_process_bytes (key, key_len, &alt_ctx); + sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Finish the digest. */ - __sha256_finish_ctx (&alt_ctx, temp_result); + sha256_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result); /* Create byte sequence P. */ cp = p_bytes = alloca (key_len); @@ -184,14 +240,14 @@ __sha256_crypt_r (key, salt, buffer, buflen) memcpy (cp, temp_result, cnt); /* Start computation of S byte sequence. */ - __sha256_init_ctx (&alt_ctx); + sha256_init_ctx (&alt_ctx, nss_alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) - __sha256_process_bytes (salt, salt_len, &alt_ctx); + sha256_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx); /* Finish the digest. */ - __sha256_finish_ctx (&alt_ctx, temp_result); + sha256_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result); /* Create byte sequence S. */ cp = s_bytes = alloca (salt_len); @@ -204,32 +260,37 @@ __sha256_crypt_r (key, salt, buffer, buflen) for (cnt = 0; cnt < rounds; ++cnt) { /* New context. */ - __sha256_init_ctx (&ctx); + sha256_init_ctx (&ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) - __sha256_process_bytes (p_bytes, key_len, &ctx); + sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx); else - __sha256_process_bytes (alt_result, 32, &ctx); + sha256_process_bytes (alt_result, 32, &ctx, nss_ctx); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) - __sha256_process_bytes (s_bytes, salt_len, &ctx); + sha256_process_bytes (s_bytes, salt_len, &ctx, nss_ctx); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) - __sha256_process_bytes (p_bytes, key_len, &ctx); + sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) - __sha256_process_bytes (alt_result, 32, &ctx); + sha256_process_bytes (alt_result, 32, &ctx, nss_ctx); else - __sha256_process_bytes (p_bytes, key_len, &ctx); + sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx); /* Create intermediate result. */ - __sha256_finish_ctx (&ctx, alt_result); + sha256_finish_ctx (&ctx, nss_ctx, alt_result); } +#ifdef USE_NSS + /* Free libfreebl3 resources. */ + NSSLOW_Shutdown (nss_ictx); +#endif + /* Now we can construct the result string. It consists of three parts. */ cp = __stpncpy (buffer, sha256_salt_prefix, MAX (0, buflen)); @@ -252,17 +313,17 @@ __sha256_crypt_r (key, salt, buffer, buflen) --buflen; } -#define b64_from_24bit(B2, B1, B0, N) \ - do { \ - unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ - int n = (N); \ - while (n-- > 0 && buflen > 0) \ - { \ - *cp++ = b64t[w & 0x3f]; \ - --buflen; \ - w >>= 6; \ - } \ - } while (0) + void b64_from_24bit (unsigned int b2, unsigned int b1, unsigned int b0, + int n) + { + unsigned int w = (b2 << 16) | (b1 << 8) | b0; + while (n-- > 0 && buflen > 0) + { + *cp++ = b64t[w & 0x3f]; + --buflen; + w >>= 6; + } + } b64_from_24bit (alt_result[0], alt_result[10], alt_result[20], 4); b64_from_24bit (alt_result[21], alt_result[1], alt_result[11], 4); @@ -287,13 +348,15 @@ __sha256_crypt_r (key, salt, buffer, buflen) attaching to processes or reading core dumps cannot get any information. We do it in this way to clear correct_words[] inside the SHA256 implementation as well. */ +#ifndef USE_NSS __sha256_init_ctx (&ctx); __sha256_finish_ctx (&ctx, alt_result); + memset (&ctx, '\0', sizeof (ctx)); + memset (&alt_ctx, '\0', sizeof (alt_ctx)); +#endif memset (temp_result, '\0', sizeof (temp_result)); memset (p_bytes, '\0', key_len); memset (s_bytes, '\0', salt_len); - memset (&ctx, '\0', sizeof (ctx)); - memset (&alt_ctx, '\0', sizeof (alt_ctx)); if (copied_key != NULL) memset (copied_key, '\0', key_len); if (copied_salt != NULL) diff --git a/crypt/sha512-crypt.c b/crypt/sha512-crypt.c index ea96e52..523659e 100644 --- a/crypt/sha512-crypt.c +++ b/crypt/sha512-crypt.c @@ -1,5 +1,5 @@ /* One way encryption based on SHA512 sum. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2007. @@ -28,6 +28,52 @@ #include "sha512.h" +#ifdef USE_NSS +typedef int PRBool; +# include <hasht.h> +# include <nsslowhash.h> + +# define sha512_init_ctx(ctxp, nss_ctxp) \ + do \ + { \ + if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA512)) \ + == NULL)) \ + { \ + if (nss_ctx != NULL) \ + NSSLOWHASH_Destroy (nss_ctx); \ + if (nss_alt_ctx != NULL) \ + NSSLOWHASH_Destroy (nss_alt_ctx); \ + return NULL; \ + } \ + NSSLOWHASH_Begin (nss_ctxp); \ + } \ + while (0) + +# define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \ + NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len) + +# define sha512_finish_ctx(ctxp, nss_ctxp, result) \ + do \ + { \ + unsigned int ret; \ + NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \ + assert (ret == sizeof (result)); \ + NSSLOWHASH_Destroy (nss_ctxp); \ + nss_ctxp = NULL; \ + } \ + while (0) +#else +# define sha512_init_ctx(ctxp, nss_ctxp) \ + __sha512_init_ctx (ctxp) + +# define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \ + __sha512_process_bytes(buf, len, ctxp) + +# define sha512_finish_ctx(ctxp, nss_ctxp, result) \ + __sha512_finish_ctx (ctxp, result) +#endif + + /* Define our magic string to mark salt for SHA512 "encryption" replacement. */ static const char sha512_salt_prefix[] = "$6$"; @@ -66,8 +112,6 @@ __sha512_crypt_r (key, salt, buffer, buflen) __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); unsigned char temp_result[64] __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); - struct sha512_ctx ctx; - struct sha512_ctx alt_ctx; size_t salt_len; size_t key_len; size_t cnt; @@ -123,59 +167,71 @@ __sha512_crypt_r (key, salt, buffer, buflen) assert ((salt - (char *) 0) % __alignof__ (uint64_t) == 0); } +#ifdef USE_NSS + /* Initialize libfreebl3. */ + NSSLOWInitContext *nss_ictx = NSSLOW_Init (); + if (nss_ictx == NULL) + return NULL; + NSSLOWHASHContext *nss_ctx = NULL; + NSSLOWHASHContext *nss_alt_ctx = NULL; +#else + struct sha512_ctx ctx; + struct sha512_ctx alt_ctx; +#endif + /* Prepare for the real work. */ - __sha512_init_ctx (&ctx); + sha512_init_ctx (&ctx, nss_ctx); /* Add the key string. */ - __sha512_process_bytes (key, key_len, &ctx); + sha512_process_bytes (key, key_len, &ctx, nss_ctx); /* The last part is the salt string. This must be at most 16 characters and it ends at the first `$' character. */ - __sha512_process_bytes (salt, salt_len, &ctx); + sha512_process_bytes (salt, salt_len, &ctx, nss_ctx); /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The final result will be added to the first context. */ - __sha512_init_ctx (&alt_ctx); + sha512_init_ctx (&alt_ctx, nss_alt_ctx); /* Add key. */ - __sha512_process_bytes (key, key_len, &alt_ctx); + sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Add salt. */ - __sha512_process_bytes (salt, salt_len, &alt_ctx); + sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx); /* Add key again. */ - __sha512_process_bytes (key, key_len, &alt_ctx); + sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Now get result of this (64 bytes) and add it to the other context. */ - __sha512_finish_ctx (&alt_ctx, alt_result); + sha512_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 64; cnt -= 64) - __sha512_process_bytes (alt_result, 64, &ctx); - __sha512_process_bytes (alt_result, cnt, &ctx); + sha512_process_bytes (alt_result, 64, &ctx, nss_ctx); + sha512_process_bytes (alt_result, cnt, &ctx, nss_ctx); /* Take the binary representation of the length of the key and for every 1 add the alternate sum, for every 0 the key. */ for (cnt = key_len; cnt > 0; cnt >>= 1) if ((cnt & 1) != 0) - __sha512_process_bytes (alt_result, 64, &ctx); + sha512_process_bytes (alt_result, 64, &ctx, nss_ctx); else - __sha512_process_bytes (key, key_len, &ctx); + sha512_process_bytes (key, key_len, &ctx, nss_ctx); /* Create intermediate result. */ - __sha512_finish_ctx (&ctx, alt_result); + sha512_finish_ctx (&ctx, nss_ctx, alt_result); /* Start computation of P byte sequence. */ - __sha512_init_ctx (&alt_ctx); + sha512_init_ctx (&alt_ctx, nss_alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < key_len; ++cnt) - __sha512_process_bytes (key, key_len, &alt_ctx); + sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx); /* Finish the digest. */ - __sha512_finish_ctx (&alt_ctx, temp_result); + sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result); /* Create byte sequence P. */ cp = p_bytes = alloca (key_len); @@ -184,14 +240,14 @@ __sha512_crypt_r (key, salt, buffer, buflen) memcpy (cp, temp_result, cnt); /* Start computation of S byte sequence. */ - __sha512_init_ctx (&alt_ctx); + sha512_init_ctx (&alt_ctx, nss_alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) - __sha512_process_bytes (salt, salt_len, &alt_ctx); + sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx); /* Finish the digest. */ - __sha512_finish_ctx (&alt_ctx, temp_result); + sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result); /* Create byte sequence S. */ cp = s_bytes = alloca (salt_len); @@ -204,32 +260,37 @@ __sha512_crypt_r (key, salt, buffer, buflen) for (cnt = 0; cnt < rounds; ++cnt) { /* New context. */ - __sha512_init_ctx (&ctx); + sha512_init_ctx (&ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) - __sha512_process_bytes (p_bytes, key_len, &ctx); + sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx); else - __sha512_process_bytes (alt_result, 64, &ctx); + sha512_process_bytes (alt_result, 64, &ctx, nss_ctx); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) - __sha512_process_bytes (s_bytes, salt_len, &ctx); + sha512_process_bytes (s_bytes, salt_len, &ctx, nss_ctx); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) - __sha512_process_bytes (p_bytes, key_len, &ctx); + sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx); /* Add key or last result. */ if ((cnt & 1) != 0) - __sha512_process_bytes (alt_result, 64, &ctx); + sha512_process_bytes (alt_result, 64, &ctx, nss_ctx); else - __sha512_process_bytes (p_bytes, key_len, &ctx); + sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx); /* Create intermediate result. */ - __sha512_finish_ctx (&ctx, alt_result); + sha512_finish_ctx (&ctx, nss_ctx, alt_result); } +#ifdef USE_NSS + /* Free libfreebl3 resources. */ + NSSLOW_Shutdown (nss_ictx); +#endif + /* Now we can construct the result string. It consists of three parts. */ cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen)); @@ -252,17 +313,17 @@ __sha512_crypt_r (key, salt, buffer, buflen) --buflen; } -#define b64_from_24bit(B2, B1, B0, N) \ - do { \ - unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ - int n = (N); \ - while (n-- > 0 && buflen > 0) \ - { \ - *cp++ = b64t[w & 0x3f]; \ - --buflen; \ - w >>= 6; \ - } \ - } while (0) + void b64_from_24bit (unsigned int b2, unsigned int b1, unsigned int b0, + int n) + { + unsigned int w = (b2 << 16) | (b1 << 8) | b0; + while (n-- > 0 && buflen > 0) + { + *cp++ = b64t[w & 0x3f]; + --buflen; + w >>= 6; + } + } b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4); b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4); @@ -299,13 +360,15 @@ __sha512_crypt_r (key, salt, buffer, buflen) attaching to processes or reading core dumps cannot get any information. We do it in this way to clear correct_words[] inside the SHA512 implementation as well. */ +#ifndef USE_NSS __sha512_init_ctx (&ctx); __sha512_finish_ctx (&ctx, alt_result); + memset (&ctx, '\0', sizeof (ctx)); + memset (&alt_ctx, '\0', sizeof (alt_ctx)); +#endif memset (temp_result, '\0', sizeof (temp_result)); memset (p_bytes, '\0', key_len); memset (s_bytes, '\0', salt_len); - memset (&ctx, '\0', sizeof (ctx)); - memset (&alt_ctx, '\0', sizeof (alt_ctx)); if (copied_key != NULL) memset (copied_key, '\0', key_len); if (copied_salt != NULL) |