From a0e6452d27ca4733c6c256f312dc60edeb032646 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Thu, 29 Jul 2010 16:34:00 +0200
Subject: [PATCH 1/7] Move crypto functions into its own subdir

A refactoring patch that creates a common util/crypto subdir with
per-implementation subdirectories for each underlying crypto library
supported by SSSD.
---
 Makefile.am                                    |   13 +-
 src/db/sysdb_ops.c                             |    2 +-
 src/responder/pam/pam_LOCAL_domain.c           |    2 +-
 src/util/crypto/libcrypto/crypto_sha512crypt.c |  381 +++++++++++++++++++++
 src/util/crypto/nss/nss_sha512crypt.c          |  386 ++++++++++++++++++++++
 src/util/crypto/nss/nss_util.c                 |   72 ++++
 src/util/crypto/nss/nss_util.h                 |   27 ++
 src/util/crypto/sss_crypto.h                   |    4 +
 src/util/crypto_sha512crypt.c                  |  382 ---------------------
 src/util/nss_sha512crypt.c                     |  419 ------------------------
 src/util/sha512crypt.h                         |    4 -
 11 files changed, 881 insertions(+), 811 deletions(-)
 create mode 100644 src/util/crypto/libcrypto/crypto_sha512crypt.c
 create mode 100644 src/util/crypto/nss/nss_sha512crypt.c
 create mode 100644 src/util/crypto/nss/nss_util.c
 create mode 100644 src/util/crypto/nss/nss_util.h
 create mode 100644 src/util/crypto/sss_crypto.h
 delete mode 100644 src/util/crypto_sha512crypt.c
 delete mode 100644 src/util/nss_sha512crypt.c
 delete mode 100644 src/util/sha512crypt.h

diff --git a/Makefile.am b/Makefile.am
index 7482e81..33e5c84 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -118,11 +118,12 @@ noinst_LTLIBRARIES = \
     libsss_crypt.la
 
 if HAVE_NSS
-    SSS_CRYPT_SOURCES = src/util/nss_sha512crypt.c
+    SSS_CRYPT_SOURCES = src/util/crypto/nss/nss_sha512crypt.c \
+                        src/util/crypto/nss/nss_util.c
     SSS_CRYPT_CFLAGS = $(NSS_CFLAGS)
     SSS_CRYPT_LIBS = $(NSS_LIBS)
 else
-    SSS_CRYPT_SOURCES = src/util/crypto_sha512crypt.c
+    SSS_CRYPT_SOURCES = src/util/crypto/libcrypto/crypto_sha512crypt.c
     SSS_CRYPT_CFLAGS = $(CRYPTO_CFLAGS)
     SSS_CRYPT_LIBS = $(CRYPTO_LIBS)
 endif
@@ -297,7 +298,7 @@ endif
 
 dist_noinst_HEADERS = \
     src/monitor/monitor.h \
-    src/util/sha512crypt.h \
+    src/util/crypto/sss_crypto.h \
     src/util/dlinklist.h \
     src/util/util.h \
     src/util/strtonum.h \
@@ -350,6 +351,10 @@ dist_noinst_HEADERS = \
     src/resolv/ares/ares_data.h \
     src/tests/common.h
 
+if HAVE_NSS
+    dist_noinst_HEADERS += src/util/crypto/nss/nss_util.h
+endif
+
 
 ####################
 # Program Binaries #
@@ -937,7 +942,7 @@ dist_man_MANS = \
     src/man/sssd.8 src/man/sssd.conf.5 src/man/sssd-ldap.5 \
     src/man/sssd-krb5.5 src/man/sssd-ipa.5 src/man/sssd-simple.5 \
     src/man/sssd_krb5_locator_plugin.8 src/man/sss_groupshow.8 \
-    src/man/pam_sss.8
+    src/man/pam_sss.8 src/man/sss_obfuscate.8
 
 SUFFIXES = .1.xml .1 .3.xml .3 .5.xml .5 .8.xml .8
 .1.xml.1:
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index d86c35d..017f8eb 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -21,7 +21,7 @@
 
 #include "util/util.h"
 #include "db/sysdb_private.h"
-#include "util/sha512crypt.h"
+#include "util/crypto/sss_crypto.h"
 #include <time.h>
 
 static int add_string(struct ldb_message *msg, int flags,
diff --git a/src/responder/pam/pam_LOCAL_domain.c b/src/responder/pam/pam_LOCAL_domain.c
index d6c532e..0df9499 100644
--- a/src/responder/pam/pam_LOCAL_domain.c
+++ b/src/responder/pam/pam_LOCAL_domain.c
@@ -24,7 +24,7 @@
 
 #include "util/util.h"
 #include "db/sysdb.h"
-#include "util/sha512crypt.h"
+#include "util/crypto/sss_crypto.h"
 #include "providers/data_provider.h"
 #include "responder/pam/pamsrv.h"
 
diff --git a/src/util/crypto/libcrypto/crypto_sha512crypt.c b/src/util/crypto/libcrypto/crypto_sha512crypt.c
new file mode 100644
index 0000000..29900cc
--- /dev/null
+++ b/src/util/crypto/libcrypto/crypto_sha512crypt.c
@@ -0,0 +1,381 @@
+/* This file is based on nss_sha512crypt.c which is based on the work of
+ * Ulrich Drepper (http://people.redhat.com/drepper/SHA-crypt.txt).
+ *
+ * libcrypto is used to provide SHA512 and random number generation.
+ * (http://www.openssl.org/docs/crypto/crypto.html).
+ *
+ *  Sumit Bose <sbose@redhat.com>
+ *  George McCollister <georgem@novatech-llc.com>
+ */
+/* SHA512-based Unix crypt implementation.
+   Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.  */
+
+#define _GNU_SOURCE
+#include <endian.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include "util/util.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
+const char sha512_salt_prefix[] = "$6$";
+#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
+
+/* Prefix for optional rounds specification. */
+const char sha512_rounds_prefix[] = "rounds=";
+#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
+
+#define SALT_LEN_MAX 16
+#define ROUNDS_DEFAULT 5000
+#define ROUNDS_MIN 1000
+#define ROUNDS_MAX 999999999
+
+/* Table with characters for base64 transformation.  */
+const char b64t[64] =
+    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+/* base64 conversion function */
+static inline void b64_from_24bit(char **dest, size_t *len, size_t n,
+                                  uint8_t b2, uint8_t b1, uint8_t b0)
+{
+    uint32_t w;
+    size_t i;
+
+    if (*len < n) n = *len;
+
+    w = (b2 << 16) | (b1 << 8) | b0;
+    for (i = 0; i < n; i++) {
+        (*dest)[i] = b64t[w & 0x3f];
+        w >>= 6;
+    }
+
+    *len -= i;
+    *dest += i;
+}
+
+#define PTR_2_INT(x) ((x) - ((__typeof__ (x)) NULL))
+#define ALIGN64 __alignof__(uint64_t)
+
+static int sha512_crypt_r(const char *key,
+                          const char *salt,
+                          char *buffer, size_t buflen)
+{
+    unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
+    unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
+    size_t rounds = ROUNDS_DEFAULT;
+    bool rounds_custom = false;
+    EVP_MD_CTX alt_ctx;
+    EVP_MD_CTX ctx;
+    size_t salt_len;
+    size_t key_len;
+    size_t cnt;
+    char *copied_salt = NULL;
+    char *copied_key = NULL;
+    char *p_bytes = NULL;
+    char *s_bytes = NULL;
+    int p1, p2, p3, pt, n;
+    unsigned int part;
+    char *cp, *tmp;
+    int ret;
+
+    /* Find beginning of salt string. The prefix should normally always be
+     * present. Just in case it is not. */
+    if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
+        /* Skip salt prefix.  */
+        salt += SALT_PREF_SIZE;
+    }
+
+    if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
+        unsigned long int srounds;
+        const char *num;
+        char *endp;
+
+        num = salt + ROUNDS_SIZE;
+        srounds = strtoul(num, &endp, 10);
+        if (*endp == '$') {
+            salt = endp + 1;
+            if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
+            if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
+            rounds = srounds;
+            rounds_custom = true;
+        }
+    }
+
+    salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
+    key_len = strlen(key);
+
+    if ((PTR_2_INT(key) % ALIGN64) != 0) {
+        tmp = (char *)alloca(key_len + ALIGN64);
+        key = copied_key = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, key, key_len);
+    }
+
+    if (PTR_2_INT(salt) % ALIGN64 != 0) {
+        tmp = (char *)alloca(salt_len + ALIGN64);
+        salt = copied_salt = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, salt, salt_len);
+    }
+
+    EVP_MD_CTX_init(&ctx);
+
+    EVP_MD_CTX_init(&alt_ctx);
+
+    /* Prepare for the real work.  */
+    if (!EVP_DigestInit_ex(&ctx, EVP_sha512(), NULL)) {
+        ret = EIO;
+        goto done;
+    }
+
+    /* Add the key string.  */
+    EVP_DigestUpdate(&ctx, (const unsigned char *)key, key_len);
+
+    /* The last part is the salt string. This must be at most 16
+     * characters and it ends at the first `$' character (for
+     * compatibility with existing implementations). */
+    EVP_DigestUpdate(&ctx, (const unsigned char *)salt, salt_len);
+
+
+    /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.
+     * The final result will be added to the first context. */
+    if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
+        ret = EIO;
+        goto done;
+    }
+
+    /* Add key. */
+    EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
+
+    /* Add salt. */
+    EVP_DigestUpdate(&alt_ctx, (const unsigned char *)salt, salt_len);
+
+    /* Add key again. */
+    EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
+
+    /* Now get result of this (64 bytes) and add it to the other context. */
+    EVP_DigestFinal_ex(&alt_ctx, alt_result, &part);
+
+    /* Add for any character in the key one byte of the alternate sum. */
+    for (cnt = key_len; cnt > 64; cnt -= 64) {
+        EVP_DigestUpdate(&ctx, alt_result, 64);
+    }
+    EVP_DigestUpdate(&ctx, alt_result, cnt);
+
+    /* 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) {
+            EVP_DigestUpdate(&ctx, alt_result, 64);
+        } else {
+            EVP_DigestUpdate(&ctx, (const unsigned char *)key, key_len);
+        }
+    }
+
+    /* Create intermediate result. */
+    EVP_DigestFinal_ex(&ctx, alt_result, &part);
+
+    /* Start computation of P byte sequence. */
+    if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
+        ret = EIO;
+        goto done;
+    }
+
+    /* For every character in the password add the entire password. */
+    for (cnt = 0; cnt < key_len; cnt++) {
+        EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
+    }
+
+    /* Finish the digest. */
+    EVP_DigestFinal_ex(&alt_ctx, temp_result, &part);
+
+    /* Create byte sequence P. */
+    cp = p_bytes = alloca(key_len);
+    for (cnt = key_len; cnt >= 64; cnt -= 64) {
+        cp = mempcpy(cp, temp_result, 64);
+    }
+    memcpy(cp, temp_result, cnt);
+
+    /* Start computation of S byte sequence. */
+    if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
+        ret = EIO;
+        goto done;
+    }
+
+    /* For every character in the password add the entire salt. */
+    for (cnt = 0; cnt < 16 + alt_result[0]; cnt++) {
+        EVP_DigestUpdate(&alt_ctx, (const unsigned char *)salt, salt_len);
+    }
+
+    /* Finish the digest. */
+    EVP_DigestFinal_ex(&alt_ctx, temp_result, &part);
+
+    /* Create byte sequence S.  */
+    cp = s_bytes = alloca(salt_len);
+    for (cnt = salt_len; cnt >= 64; cnt -= 64) {
+        cp = mempcpy(cp, temp_result, 64);
+    }
+    memcpy(cp, temp_result, cnt);
+
+    /* Repeatedly run the collected hash value through SHA512 to burn CPU cycles. */
+    for (cnt = 0; cnt < rounds; cnt++) {
+
+        if (!EVP_DigestInit_ex(&ctx, EVP_sha512(), NULL)) {
+            ret = EIO;
+            goto done;
+        }
+
+        /* Add key or last result. */
+        if ((cnt & 1) != 0) {
+            EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
+        } else {
+            EVP_DigestUpdate(&ctx, alt_result, 64);
+        }
+
+        /* Add salt for numbers not divisible by 3. */
+        if (cnt % 3 != 0) {
+            EVP_DigestUpdate(&ctx, (const unsigned char *)s_bytes, salt_len);
+        }
+
+        /* Add key for numbers not divisible by 7. */
+        if (cnt % 7 != 0) {
+            EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
+        }
+
+        /* Add key or last result. */
+        if ((cnt & 1) != 0) {
+            EVP_DigestUpdate(&ctx, alt_result, 64);
+        } else {
+            EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
+        }
+
+        /* Create intermediate result. */
+        EVP_DigestFinal_ex(&ctx, alt_result, &part);
+    }
+
+    /* Now we can construct the result string.
+     * It consists of three parts. */
+    if (buflen <= SALT_PREF_SIZE) {
+        ret = ERANGE;
+        goto done;
+    }
+
+    cp = __stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
+    buflen -= SALT_PREF_SIZE;
+
+    if (rounds_custom) {
+        n = snprintf(cp, buflen, "%s%zu$",
+                     sha512_rounds_prefix, rounds);
+        if (n < 0 || n >= buflen) {
+            ret = ERANGE;
+            goto done;
+        }
+        cp += n;
+        buflen -= n;
+    }
+
+    if (buflen <= salt_len + 1) {
+        ret = ERANGE;
+        goto done;
+    }
+    cp = __stpncpy(cp, salt, salt_len);
+    *cp++ = '$';
+    buflen -= salt_len + 1;
+
+    /* fuzzyfill the base 64 string */
+    p1 = 0;
+    p2 = 21;
+    p3 = 42;
+    for (n = 0; n < 21; n++) {
+        b64_from_24bit(&cp, &buflen, 4, alt_result[p1], alt_result[p2], alt_result[p3]);
+        if (buflen == 0) {
+            ret = ERANGE;
+            goto done;
+        }
+        pt = p1;
+        p1 = p2 + 1;
+        p2 = p3 + 1;
+        p3 = pt + 1;
+    }
+    /* 64th and last byte */
+    b64_from_24bit(&cp, &buflen, 2, 0, 0, alt_result[p3]);
+    if (buflen == 0) {
+        ret = ERANGE;
+        goto done;
+    }
+
+    *cp = '\0';
+    ret = EOK;
+
+done:
+    /* Clear the buffer for the intermediate result so that people 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.  */
+    EVP_MD_CTX_cleanup(&ctx);
+    EVP_MD_CTX_cleanup(&alt_ctx);
+    if (p_bytes) memset(p_bytes, '\0', key_len);
+    if (s_bytes) memset(s_bytes, '\0', salt_len);
+    if (copied_key) memset(copied_key, '\0', key_len);
+    if (copied_salt) memset(copied_salt, '\0', salt_len);
+    memset(temp_result, '\0', sizeof(temp_result));
+
+    return ret;
+}
+
+int s3crypt_sha512(TALLOC_CTX *memctx,
+                   const char *key, const char *salt, char **_hash)
+{
+    char *hash;
+    int hlen = (sizeof (sha512_salt_prefix) - 1
+                + sizeof (sha512_rounds_prefix) + 9 + 1
+                + strlen (salt) + 1 + 86 + 1);
+    int ret;
+
+    hash = talloc_size(memctx, hlen);
+    if (!hash) return ENOMEM;
+
+    ret = sha512_crypt_r(key, salt, hash, hlen);
+    if (ret) return ret;
+
+    *_hash = hash;
+    return ret;
+}
+
+#define SALT_RAND_LEN 12
+
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt)
+{
+    uint8_t rb[SALT_RAND_LEN];
+    char *salt, *cp;
+    size_t slen;
+    int ret;
+
+    salt = talloc_size(memctx, SALT_LEN_MAX + 1);
+    if (!salt) {
+        return ENOMEM;
+    }
+
+    ret = RAND_bytes(rb, SALT_RAND_LEN);
+    if (ret == 0) {
+        return EIO;
+    }
+
+    slen = SALT_LEN_MAX;
+    cp = salt;
+    b64_from_24bit(&cp, &slen, 4, rb[0], rb[1], rb[2]);
+    b64_from_24bit(&cp, &slen, 4, rb[3], rb[4], rb[5]);
+    b64_from_24bit(&cp, &slen, 4, rb[6], rb[7], rb[8]);
+    b64_from_24bit(&cp, &slen, 4, rb[9], rb[10], rb[11]);
+    *cp = '\0';
+
+    *_salt = salt;
+
+    return EOK;
+}
diff --git a/src/util/crypto/nss/nss_sha512crypt.c b/src/util/crypto/nss/nss_sha512crypt.c
new file mode 100644
index 0000000..514e4d9
--- /dev/null
+++ b/src/util/crypto/nss/nss_sha512crypt.c
@@ -0,0 +1,386 @@
+/* This file is based on the work of Ulrich Drepper
+ * (http://people.redhat.com/drepper/SHA-crypt.txt). I have replaced the
+ * included SHA512 implementation by calls to NSS
+ * (http://www.mozilla.org/projects/security/pki/nss/).
+ *
+ *  Sumit Bose <sbose@redhat.com>
+ */
+/* SHA512-based Unix crypt implementation.
+   Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.  */
+
+#define _GNU_SOURCE
+#include <endian.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include "util/util.h"
+#include "util/crypto/nss/nss_util.h"
+
+#include <prinit.h>
+#include <nss.h>
+#include <sechash.h>
+#include <pk11func.h>
+
+/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
+const char sha512_salt_prefix[] = "$6$";
+#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
+
+/* Prefix for optional rounds specification. */
+const char sha512_rounds_prefix[] = "rounds=";
+#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
+
+#define SALT_LEN_MAX 16
+#define ROUNDS_DEFAULT 5000
+#define ROUNDS_MIN 1000
+#define ROUNDS_MAX 999999999
+
+/* Table with characters for base64 transformation.  */
+const char b64t[64] =
+    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+/* base64 conversion function */
+static inline void b64_from_24bit(char **dest, size_t *len, size_t n,
+                                  uint8_t b2, uint8_t b1, uint8_t b0)
+{
+    uint32_t w;
+    size_t i;
+
+    if (*len < n) n = *len;
+
+    w = (b2 << 16) | (b1 << 8) | b0;
+    for (i = 0; i < n; i++) {
+        (*dest)[i] = b64t[w & 0x3f];
+        w >>= 6;
+    }
+
+    *len -= i;
+    *dest += i;
+}
+
+#define PTR_2_INT(x) ((x) - ((__typeof__ (x)) NULL))
+#define ALIGN64 __alignof__(uint64_t)
+
+static int sha512_crypt_r(const char *key,
+                          const char *salt,
+                          char *buffer, size_t buflen)
+{
+    unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
+    unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
+    size_t rounds = ROUNDS_DEFAULT;
+    bool rounds_custom = false;
+    HASHContext *alt_ctx = NULL;
+    HASHContext *ctx = NULL;
+    size_t salt_len;
+    size_t key_len;
+    size_t cnt;
+    char *copied_salt = NULL;
+    char *copied_key = NULL;
+    char *p_bytes = NULL;
+    char *s_bytes = NULL;
+    int p1, p2, p3, pt, n;
+    unsigned int part;
+    char *cp, *tmp;
+    int ret;
+
+    /* Find beginning of salt string. The prefix should normally always be
+     * present. Just in case it is not. */
+    if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
+        /* Skip salt prefix.  */
+        salt += SALT_PREF_SIZE;
+    }
+
+    if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
+        unsigned long int srounds;
+        const char *num;
+        char *endp;
+
+        num = salt + ROUNDS_SIZE;
+        srounds = strtoul(num, &endp, 10);
+        if (*endp == '$') {
+            salt = endp + 1;
+            if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
+            if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
+            rounds = srounds;
+            rounds_custom = true;
+        }
+    }
+
+    salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
+    key_len = strlen(key);
+
+    if ((PTR_2_INT(key) % ALIGN64) != 0) {
+        tmp = (char *)alloca(key_len + ALIGN64);
+        key = copied_key = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, key, key_len);
+    }
+
+    if (PTR_2_INT(salt) % ALIGN64 != 0) {
+        tmp = (char *)alloca(salt_len + ALIGN64);
+        salt = copied_salt = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, salt, salt_len);
+    }
+
+    ret = nspr_nss_init();
+    if (ret != EOK) {
+        ret = EIO;
+        goto done;
+    }
+
+    ctx = HASH_Create(HASH_AlgSHA512);
+    if (!ctx) {
+        ret = EIO;
+        goto done;
+    }
+
+    alt_ctx = HASH_Create(HASH_AlgSHA512);
+    if (!alt_ctx) {
+        ret = EIO;
+        goto done;
+    }
+
+    /* Prepare for the real work.  */
+    HASH_Begin(ctx);
+
+    /* Add the key string.  */
+    HASH_Update(ctx, (const unsigned char *)key, key_len);
+
+    /* The last part is the salt string. This must be at most 16
+     * characters and it ends at the first `$' character (for
+     * compatibility with existing implementations). */
+    HASH_Update(ctx, (const unsigned char *)salt, salt_len);
+
+
+    /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.
+     * The final result will be added to the first context. */
+    HASH_Begin(alt_ctx);
+
+    /* Add key. */
+    HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
+
+    /* Add salt. */
+    HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
+
+    /* Add key again. */
+    HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
+
+    /* Now get result of this (64 bytes) and add it to the other context. */
+    HASH_End(alt_ctx, alt_result, &part, HASH_ResultLenContext(alt_ctx));
+
+    /* Add for any character in the key one byte of the alternate sum. */
+    for (cnt = key_len; cnt > 64; cnt -= 64) {
+        HASH_Update(ctx, alt_result, 64);
+    }
+    HASH_Update(ctx, alt_result, cnt);
+
+    /* 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) {
+            HASH_Update(ctx, alt_result, 64);
+        } else {
+            HASH_Update(ctx, (const unsigned char *)key, key_len);
+        }
+    }
+
+    /* Create intermediate result. */
+    HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
+
+    /* Start computation of P byte sequence. */
+    HASH_Begin(alt_ctx);
+
+    /* For every character in the password add the entire password. */
+    for (cnt = 0; cnt < key_len; cnt++) {
+        HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
+    }
+
+    /* Finish the digest. */
+    HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
+
+    /* Create byte sequence P. */
+    cp = p_bytes = alloca(key_len);
+    for (cnt = key_len; cnt >= 64; cnt -= 64) {
+        cp = mempcpy(cp, temp_result, 64);
+    }
+    memcpy(cp, temp_result, cnt);
+
+    /* Start computation of S byte sequence. */
+    HASH_Begin(alt_ctx);
+
+    /* For every character in the password add the entire salt. */
+    for (cnt = 0; cnt < 16 + alt_result[0]; cnt++) {
+        HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
+    }
+
+    /* Finish the digest. */
+    HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
+
+    /* Create byte sequence S.  */
+    cp = s_bytes = alloca(salt_len);
+    for (cnt = salt_len; cnt >= 64; cnt -= 64) {
+        cp = mempcpy(cp, temp_result, 64);
+    }
+    memcpy(cp, temp_result, cnt);
+
+    /* Repeatedly run the collected hash value through SHA512 to burn CPU cycles. */
+    for (cnt = 0; cnt < rounds; cnt++) {
+
+        HASH_Begin(ctx);
+
+        /* Add key or last result. */
+        if ((cnt & 1) != 0) {
+            HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
+        } else {
+            HASH_Update(ctx, alt_result, 64);
+        }
+
+        /* Add salt for numbers not divisible by 3. */
+        if (cnt % 3 != 0) {
+            HASH_Update(ctx, (const unsigned char *)s_bytes, salt_len);
+        }
+
+        /* Add key for numbers not divisible by 7. */
+        if (cnt % 7 != 0) {
+            HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
+        }
+
+        /* Add key or last result. */
+        if ((cnt & 1) != 0) {
+            HASH_Update(ctx, alt_result, 64);
+        } else {
+            HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
+        }
+
+        /* Create intermediate result. */
+        HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
+    }
+
+    /* Now we can construct the result string.
+     * It consists of three parts. */
+    if (buflen <= SALT_PREF_SIZE) {
+        ret = ERANGE;
+        goto done;
+    }
+
+    cp = __stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
+    buflen -= SALT_PREF_SIZE;
+
+    if (rounds_custom) {
+        n = snprintf(cp, buflen, "%s%zu$",
+                     sha512_rounds_prefix, rounds);
+        if (n < 0 || n >= buflen) {
+            ret = ERANGE;
+            goto done;
+        }
+        cp += n;
+        buflen -= n;
+    }
+
+    if (buflen <= salt_len + 1) {
+        ret = ERANGE;
+        goto done;
+    }
+    cp = __stpncpy(cp, salt, salt_len);
+    *cp++ = '$';
+    buflen -= salt_len + 1;
+
+    /* fuzzyfill the base 64 string */
+    p1 = 0;
+    p2 = 21;
+    p3 = 42;
+    for (n = 0; n < 21; n++) {
+        b64_from_24bit(&cp, &buflen, 4, alt_result[p1], alt_result[p2], alt_result[p3]);
+        if (buflen == 0) {
+            ret = ERANGE;
+            goto done;
+        }
+        pt = p1;
+        p1 = p2 + 1;
+        p2 = p3 + 1;
+        p3 = pt + 1;
+    }
+    /* 64th and last byte */
+    b64_from_24bit(&cp, &buflen, 2, 0, 0, alt_result[p3]);
+    if (buflen == 0) {
+        ret = ERANGE;
+        goto done;
+    }
+
+    *cp = '\0';
+    ret = EOK;
+
+done:
+    /* Clear the buffer for the intermediate result so that people 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.  */
+    if (ctx) HASH_Destroy(ctx);
+    if (alt_ctx) HASH_Destroy(alt_ctx);
+    if (p_bytes) memset(p_bytes, '\0', key_len);
+    if (s_bytes) memset(s_bytes, '\0', salt_len);
+    if (copied_key) memset(copied_key, '\0', key_len);
+    if (copied_salt) memset(copied_salt, '\0', salt_len);
+    memset(temp_result, '\0', sizeof(temp_result));
+
+    return ret;
+}
+
+int s3crypt_sha512(TALLOC_CTX *memctx,
+                   const char *key, const char *salt, char **_hash)
+{
+    char *hash;
+    int hlen = (sizeof (sha512_salt_prefix) - 1
+                + sizeof (sha512_rounds_prefix) + 9 + 1
+                + strlen (salt) + 1 + 86 + 1);
+    int ret;
+
+    hash = talloc_size(memctx, hlen);
+    if (!hash) return ENOMEM;
+
+    ret = sha512_crypt_r(key, salt, hash, hlen);
+    if (ret) return ret;
+
+    *_hash = hash;
+    return ret;
+}
+
+#define SALT_RAND_LEN 12
+
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt)
+{
+    uint8_t rb[SALT_RAND_LEN];
+    char *salt, *cp;
+    size_t slen;
+    int ret;
+
+    ret = nspr_nss_init();
+    if (ret != EOK) {
+        return EIO;
+    }
+
+    salt = talloc_size(memctx, SALT_LEN_MAX + 1);
+    if (!salt) {
+        return ENOMEM;
+    }
+
+    ret = PK11_GenerateRandom(rb, SALT_RAND_LEN);
+    if (ret != SECSuccess) {
+        return EIO;
+    }
+
+    slen = SALT_LEN_MAX;
+    cp = salt;
+    b64_from_24bit(&cp, &slen, 4, rb[0], rb[1], rb[2]);
+    b64_from_24bit(&cp, &slen, 4, rb[3], rb[4], rb[5]);
+    b64_from_24bit(&cp, &slen, 4, rb[6], rb[7], rb[8]);
+    b64_from_24bit(&cp, &slen, 4, rb[9], rb[10], rb[11]);
+    *cp = '\0';
+
+    *_salt = salt;
+
+    return EOK;
+}
diff --git a/src/util/crypto/nss/nss_util.c b/src/util/crypto/nss/nss_util.c
new file mode 100644
index 0000000..e00a145
--- /dev/null
+++ b/src/util/crypto/nss/nss_util.c
@@ -0,0 +1,72 @@
+/*
+   SSSD
+
+   NSS crypto wrappers
+
+   Authors:
+        Sumit Bose <sbose@redhat.com>
+        Jakub Hrozek <jhrozek@redhat.com>
+
+   Copyright (C) Red Hat, Inc 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <prinit.h>
+#include <prerror.h>
+#include <nss.h>
+#include <pk11func.h>
+
+#include "util/util.h"
+
+static int nspr_nss_init_done = 0;
+
+int nspr_nss_init(void)
+{
+    SECStatus sret;
+
+    /* nothing to do */
+    if (nspr_nss_init_done == 1) return SECSuccess;
+
+    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+    sret = NSS_NoDB_Init(NULL);
+    if (sret != SECSuccess) {
+        DEBUG(1, ("Error initializing connection to NSS [%d]\n",
+                  PR_GetError()));
+        return EIO;
+    }
+
+    nspr_nss_init_done = 1;
+    return EOK;
+}
+
+int nspr_nss_cleanup(void)
+{
+    SECStatus sret;
+
+    /* nothing to do */
+    if (nspr_nss_init_done == 0) return SECSuccess;
+
+    sret = NSS_Shutdown();
+    if (sret != SECSuccess) {
+        DEBUG(1, ("Error shutting down connection to NSS [%d]\n",
+                  PR_GetError()));
+        return EIO;
+    }
+
+    PR_Cleanup();
+    nspr_nss_init_done = 0;
+    return EOK;
+}
diff --git a/src/util/crypto/nss/nss_util.h b/src/util/crypto/nss/nss_util.h
new file mode 100644
index 0000000..7387b9a
--- /dev/null
+++ b/src/util/crypto/nss/nss_util.h
@@ -0,0 +1,27 @@
+/*
+   SSSD
+
+   NSS crypto wrappers
+
+   Authors:
+        Jakub Hrozek <jhrozek@redhat.com>
+
+   Copyright (C) Red Hat, Inc 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+int nspr_nss_init(void);
+int nspr_nss_cleanup(void);
diff --git a/src/util/crypto/sss_crypto.h b/src/util/crypto/sss_crypto.h
new file mode 100644
index 0000000..5512c5d
--- /dev/null
+++ b/src/util/crypto/sss_crypto.h
@@ -0,0 +1,4 @@
+
+int s3crypt_sha512(TALLOC_CTX *mmectx,
+                   const char *key, const char *salt, char **_hash);
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt);
diff --git a/src/util/crypto_sha512crypt.c b/src/util/crypto_sha512crypt.c
deleted file mode 100644
index 9cd03a1..0000000
--- a/src/util/crypto_sha512crypt.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/* This file is based on nss_sha512crypt.c which is based on the work of
- * Ulrich Drepper (http://people.redhat.com/drepper/SHA-crypt.txt).
- *
- * libcrypto is used to provide SHA512 and random number generation.
- * (http://www.openssl.org/docs/crypto/crypto.html).
- *
- *  Sumit Bose <sbose@redhat.com>
- *  George McCollister <georgem@novatech-llc.com>
- */
-/* SHA512-based Unix crypt implementation.
-   Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.  */
-
-#define _GNU_SOURCE
-#include <endian.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include "util/util.h"
-
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-
-/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
-const char sha512_salt_prefix[] = "$6$";
-#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
-
-/* Prefix for optional rounds specification. */
-const char sha512_rounds_prefix[] = "rounds=";
-#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
-
-#define SALT_LEN_MAX 16
-#define ROUNDS_DEFAULT 5000
-#define ROUNDS_MIN 1000
-#define ROUNDS_MAX 999999999
-
-/* Table with characters for base64 transformation.  */
-const char b64t[64] =
-    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-/* base64 conversion function */
-static inline void b64_from_24bit(char **dest, size_t *len, size_t n,
-                                  uint8_t b2, uint8_t b1, uint8_t b0)
-{
-    uint32_t w;
-    size_t i;
-
-    if (*len < n) n = *len;
-
-    w = (b2 << 16) | (b1 << 8) | b0;
-    for (i = 0; i < n; i++) {
-        (*dest)[i] = b64t[w & 0x3f];
-        w >>= 6;
-    }
-
-    *len -= i;
-    *dest += i;
-}
-
-#define PTR_2_INT(x) ((x) - ((__typeof__ (x)) NULL))
-#define ALIGN64 __alignof__(uint64_t)
-
-static int sha512_crypt_r(const char *key,
-                          const char *salt,
-                          char *buffer, size_t buflen)
-{
-    unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
-    unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
-    size_t rounds = ROUNDS_DEFAULT;
-    bool rounds_custom = false;
-    EVP_MD_CTX alt_ctx;
-    EVP_MD_CTX ctx;
-    size_t salt_len;
-    size_t key_len;
-    size_t cnt;
-    char *copied_salt = NULL;
-    char *copied_key = NULL;
-    char *p_bytes = NULL;
-    char *s_bytes = NULL;
-    int p1, p2, p3, pt, n;
-    unsigned int part;
-    char *cp, *tmp;
-    int ret;
-
-    /* Find beginning of salt string. The prefix should normally always be
-     * present. Just in case it is not. */
-    if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
-        /* Skip salt prefix.  */
-        salt += SALT_PREF_SIZE;
-    }
-
-    if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
-        unsigned long int srounds;
-        const char *num;
-        char *endp;
-
-        num = salt + ROUNDS_SIZE;
-        srounds = strtoul(num, &endp, 10);
-        if (*endp == '$') {
-            salt = endp + 1;
-            if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
-            if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
-            rounds = srounds;
-            rounds_custom = true;
-        }
-    }
-
-    salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
-    key_len = strlen(key);
-
-    if ((PTR_2_INT(key) % ALIGN64) != 0) {
-        tmp = (char *)alloca(key_len + ALIGN64);
-        key = copied_key = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, key, key_len);
-    }
-
-    if (PTR_2_INT(salt) % ALIGN64 != 0) {
-        tmp = (char *)alloca(salt_len + ALIGN64);
-        salt = copied_salt = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, salt, salt_len);
-    }
-
-    EVP_MD_CTX_init(&ctx);
-
-    EVP_MD_CTX_init(&alt_ctx);
-
-    /* Prepare for the real work.  */
-    if (!EVP_DigestInit_ex(&ctx, EVP_sha512(), NULL)) {
-        ret = EIO;
-        goto done;
-    }
-
-    /* Add the key string.  */
-    EVP_DigestUpdate(&ctx, (const unsigned char *)key, key_len);
-
-    /* The last part is the salt string. This must be at most 16
-     * characters and it ends at the first `$' character (for
-     * compatibility with existing implementations). */
-    EVP_DigestUpdate(&ctx, (const unsigned char *)salt, salt_len);
-
-
-    /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.
-     * The final result will be added to the first context. */
-    if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
-        ret = EIO;
-        goto done;
-    }
-
-    /* Add key. */
-    EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
-
-    /* Add salt. */
-    EVP_DigestUpdate(&alt_ctx, (const unsigned char *)salt, salt_len);
-
-    /* Add key again. */
-    EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
-
-    /* Now get result of this (64 bytes) and add it to the other context. */
-    EVP_DigestFinal_ex(&alt_ctx, alt_result, &part);
-
-    /* Add for any character in the key one byte of the alternate sum. */
-    for (cnt = key_len; cnt > 64; cnt -= 64) {
-        EVP_DigestUpdate(&ctx, alt_result, 64);
-    }
-    EVP_DigestUpdate(&ctx, alt_result, cnt);
-
-    /* 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) {
-            EVP_DigestUpdate(&ctx, alt_result, 64);
-        } else {
-            EVP_DigestUpdate(&ctx, (const unsigned char *)key, key_len);
-        }
-    }
-
-    /* Create intermediate result. */
-    EVP_DigestFinal_ex(&ctx, alt_result, &part);
-
-    /* Start computation of P byte sequence. */
-    if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
-        ret = EIO;
-        goto done;
-    }
-
-    /* For every character in the password add the entire password. */
-    for (cnt = 0; cnt < key_len; cnt++) {
-        EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
-    }
-
-    /* Finish the digest. */
-    EVP_DigestFinal_ex(&alt_ctx, temp_result, &part);
-
-    /* Create byte sequence P. */
-    cp = p_bytes = alloca(key_len);
-    for (cnt = key_len; cnt >= 64; cnt -= 64) {
-        cp = mempcpy(cp, temp_result, 64);
-    }
-    memcpy(cp, temp_result, cnt);
-
-    /* Start computation of S byte sequence. */
-    if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
-        ret = EIO;
-        goto done;
-    }
-
-    /* For every character in the password add the entire salt. */
-    for (cnt = 0; cnt < 16 + alt_result[0]; cnt++) {
-        EVP_DigestUpdate(&alt_ctx, (const unsigned char *)salt, salt_len);
-    }
-
-    /* Finish the digest. */
-    EVP_DigestFinal_ex(&alt_ctx, temp_result, &part);
-
-    /* Create byte sequence S.  */
-    cp = s_bytes = alloca(salt_len);
-    for (cnt = salt_len; cnt >= 64; cnt -= 64) {
-        cp = mempcpy(cp, temp_result, 64);
-    }
-    memcpy(cp, temp_result, cnt);
-
-    /* Repeatedly run the collected hash value through SHA512 to burn CPU cycles. */
-    for (cnt = 0; cnt < rounds; cnt++) {
-
-        if (!EVP_DigestInit_ex(&ctx, EVP_sha512(), NULL)) {
-            ret = EIO;
-            goto done;
-        }
-
-        /* Add key or last result. */
-        if ((cnt & 1) != 0) {
-            EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
-        } else {
-            EVP_DigestUpdate(&ctx, alt_result, 64);
-        }
-
-        /* Add salt for numbers not divisible by 3. */
-        if (cnt % 3 != 0) {
-            EVP_DigestUpdate(&ctx, (const unsigned char *)s_bytes, salt_len);
-        }
-
-        /* Add key for numbers not divisible by 7. */
-        if (cnt % 7 != 0) {
-            EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
-        }
-
-        /* Add key or last result. */
-        if ((cnt & 1) != 0) {
-            EVP_DigestUpdate(&ctx, alt_result, 64);
-        } else {
-            EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
-        }
-
-        /* Create intermediate result. */
-        EVP_DigestFinal_ex(&ctx, alt_result, &part);
-    }
-
-    /* Now we can construct the result string.
-     * It consists of three parts. */
-    if (buflen <= SALT_PREF_SIZE) {
-        ret = ERANGE;
-        goto done;
-    }
-
-    cp = __stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-    buflen -= SALT_PREF_SIZE;
-
-    if (rounds_custom) {
-        n = snprintf(cp, buflen, "%s%zu$",
-                     sha512_rounds_prefix, rounds);
-        if (n < 0 || n >= buflen) {
-            ret = ERANGE;
-            goto done;
-        }
-        cp += n;
-        buflen -= n;
-    }
-
-    if (buflen <= salt_len + 1) {
-        ret = ERANGE;
-        goto done;
-    }
-    cp = __stpncpy(cp, salt, salt_len);
-    *cp++ = '$';
-    buflen -= salt_len + 1;
-
-    /* fuzzyfill the base 64 string */
-    p1 = 0;
-    p2 = 21;
-    p3 = 42;
-    for (n = 0; n < 21; n++) {
-        b64_from_24bit(&cp, &buflen, 4, alt_result[p1], alt_result[p2], alt_result[p3]);
-        if (buflen == 0) {
-            ret = ERANGE;
-            goto done;
-        }
-        pt = p1;
-        p1 = p2 + 1;
-        p2 = p3 + 1;
-        p3 = pt + 1;
-    }
-    /* 64th and last byte */
-    b64_from_24bit(&cp, &buflen, 2, 0, 0, alt_result[p3]);
-    if (buflen == 0) {
-        ret = ERANGE;
-        goto done;
-    }
-
-    *cp = '\0';
-    ret = EOK;
-
-done:
-    /* Clear the buffer for the intermediate result so that people 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.  */
-    EVP_MD_CTX_cleanup(&ctx);
-    EVP_MD_CTX_cleanup(&alt_ctx);
-    if (p_bytes) memset(p_bytes, '\0', key_len);
-    if (s_bytes) memset(s_bytes, '\0', salt_len);
-    if (copied_key) memset(copied_key, '\0', key_len);
-    if (copied_salt) memset(copied_salt, '\0', salt_len);
-    memset(temp_result, '\0', sizeof(temp_result));
-
-    return ret;
-}
-
-int s3crypt_sha512(TALLOC_CTX *memctx,
-                   const char *key, const char *salt, char **_hash)
-{
-    char *hash;
-    int hlen = (sizeof (sha512_salt_prefix) - 1
-                + sizeof (sha512_rounds_prefix) + 9 + 1
-                + strlen (salt) + 1 + 86 + 1);
-    int ret;
-
-    hash = talloc_size(memctx, hlen);
-    if (!hash) return ENOMEM;
-
-    ret = sha512_crypt_r(key, salt, hash, hlen);
-    if (ret) return ret;
-
-    *_hash = hash;
-    return ret;
-}
-
-#define SALT_RAND_LEN 12
-
-int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt)
-{
-    uint8_t rb[SALT_RAND_LEN];
-    char *salt, *cp;
-    size_t slen;
-    int ret;
-
-    salt = talloc_size(memctx, SALT_LEN_MAX + 1);
-    if (!salt) {
-        return ENOMEM;
-    }
-
-    ret = RAND_bytes(rb, SALT_RAND_LEN);
-    if (ret == 0) {
-        return EIO;
-    }
-
-    slen = SALT_LEN_MAX;
-    cp = salt;
-    b64_from_24bit(&cp, &slen, 4, rb[0], rb[1], rb[2]);
-    b64_from_24bit(&cp, &slen, 4, rb[3], rb[4], rb[5]);
-    b64_from_24bit(&cp, &slen, 4, rb[6], rb[7], rb[8]);
-    b64_from_24bit(&cp, &slen, 4, rb[9], rb[10], rb[11]);
-    *cp = '\0';
-
-    *_salt = salt;
-
-    return EOK;
-}
-
diff --git a/src/util/nss_sha512crypt.c b/src/util/nss_sha512crypt.c
deleted file mode 100644
index 8ba16d4..0000000
--- a/src/util/nss_sha512crypt.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* This file is based on the work of Ulrich Drepper
- * (http://people.redhat.com/drepper/SHA-crypt.txt). I have replaced the
- * included SHA512 implementation by calls to NSS
- * (http://www.mozilla.org/projects/security/pki/nss/).
- *
- *  Sumit Bose <sbose@redhat.com>
- */
-/* SHA512-based Unix crypt implementation.
-   Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.  */
-
-#define _GNU_SOURCE
-#include <endian.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include "util/util.h"
-
-#include <prinit.h>
-#include <nss.h>
-#include <sechash.h>
-#include <pk11func.h>
-
-static int nspr_nss_init_done = 0;
-
-static int nspr_nss_init(void)
-{
-    int ret;
-    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
-    ret = NSS_NoDB_Init(NULL);
-    if (ret != SECSuccess) {
-        return ret;
-    }
-    nspr_nss_init_done = 1;
-    return 0;
-}
-
-/* added for completness, so far not used */
-#if 0
-static int nspr_nss_cleanup(void)
-{
-    int ret;
-    ret = NSS_Shutdown();
-    if (ret != SECSuccess) {
-        return ret;
-    }
-    PR_Cleanup();
-    nspr_nss_init_done = 0;
-    return 0;
-}
-#endif
-
-/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
-const char sha512_salt_prefix[] = "$6$";
-#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
-
-/* Prefix for optional rounds specification. */
-const char sha512_rounds_prefix[] = "rounds=";
-#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
-
-#define SALT_LEN_MAX 16
-#define ROUNDS_DEFAULT 5000
-#define ROUNDS_MIN 1000
-#define ROUNDS_MAX 999999999
-
-/* Table with characters for base64 transformation.  */
-const char b64t[64] =
-    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-/* base64 conversion function */
-static inline void b64_from_24bit(char **dest, size_t *len, size_t n,
-                                  uint8_t b2, uint8_t b1, uint8_t b0)
-{
-    uint32_t w;
-    size_t i;
-
-    if (*len < n) n = *len;
-
-    w = (b2 << 16) | (b1 << 8) | b0;
-    for (i = 0; i < n; i++) {
-        (*dest)[i] = b64t[w & 0x3f];
-        w >>= 6;
-    }
-
-    *len -= i;
-    *dest += i;
-}
-
-#define PTR_2_INT(x) ((x) - ((__typeof__ (x)) NULL))
-#define ALIGN64 __alignof__(uint64_t)
-
-static int sha512_crypt_r(const char *key,
-                          const char *salt,
-                          char *buffer, size_t buflen)
-{
-    unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
-    unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
-    size_t rounds = ROUNDS_DEFAULT;
-    bool rounds_custom = false;
-    HASHContext *alt_ctx = NULL;
-    HASHContext *ctx = NULL;
-    size_t salt_len;
-    size_t key_len;
-    size_t cnt;
-    char *copied_salt = NULL;
-    char *copied_key = NULL;
-    char *p_bytes = NULL;
-    char *s_bytes = NULL;
-    int p1, p2, p3, pt, n;
-    unsigned int part;
-    char *cp, *tmp;
-    int ret;
-
-    /* Find beginning of salt string. The prefix should normally always be
-     * present. Just in case it is not. */
-    if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
-        /* Skip salt prefix.  */
-        salt += SALT_PREF_SIZE;
-    }
-
-    if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
-        unsigned long int srounds;
-        const char *num;
-        char *endp;
-
-        num = salt + ROUNDS_SIZE;
-        srounds = strtoul(num, &endp, 10);
-        if (*endp == '$') {
-            salt = endp + 1;
-            if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
-            if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
-            rounds = srounds;
-            rounds_custom = true;
-        }
-    }
-
-    salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
-    key_len = strlen(key);
-
-    if ((PTR_2_INT(key) % ALIGN64) != 0) {
-        tmp = (char *)alloca(key_len + ALIGN64);
-        key = copied_key = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, key, key_len);
-    }
-
-    if (PTR_2_INT(salt) % ALIGN64 != 0) {
-        tmp = (char *)alloca(salt_len + ALIGN64);
-        salt = copied_salt = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, salt, salt_len);
-    }
-
-    if (!nspr_nss_init_done) {
-        ret = nspr_nss_init();
-        if (ret != SECSuccess) {
-            ret = EIO;
-            goto done;
-        }
-    }
-
-    ctx = HASH_Create(HASH_AlgSHA512);
-    if (!ctx) {
-        ret = EIO;
-        goto done;
-    }
-
-    alt_ctx = HASH_Create(HASH_AlgSHA512);
-    if (!alt_ctx) {
-        ret = EIO;
-        goto done;
-    }
-
-    /* Prepare for the real work.  */
-    HASH_Begin(ctx);
-
-    /* Add the key string.  */
-    HASH_Update(ctx, (const unsigned char *)key, key_len);
-
-    /* The last part is the salt string. This must be at most 16
-     * characters and it ends at the first `$' character (for
-     * compatibility with existing implementations). */
-    HASH_Update(ctx, (const unsigned char *)salt, salt_len);
-
-
-    /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.
-     * The final result will be added to the first context. */
-    HASH_Begin(alt_ctx);
-
-    /* Add key. */
-    HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
-
-    /* Add salt. */
-    HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
-
-    /* Add key again. */
-    HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
-
-    /* Now get result of this (64 bytes) and add it to the other context. */
-    HASH_End(alt_ctx, alt_result, &part, HASH_ResultLenContext(alt_ctx));
-
-    /* Add for any character in the key one byte of the alternate sum. */
-    for (cnt = key_len; cnt > 64; cnt -= 64) {
-        HASH_Update(ctx, alt_result, 64);
-    }
-    HASH_Update(ctx, alt_result, cnt);
-
-    /* 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) {
-            HASH_Update(ctx, alt_result, 64);
-        } else {
-            HASH_Update(ctx, (const unsigned char *)key, key_len);
-        }
-    }
-
-    /* Create intermediate result. */
-    HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
-
-    /* Start computation of P byte sequence. */
-    HASH_Begin(alt_ctx);
-
-    /* For every character in the password add the entire password. */
-    for (cnt = 0; cnt < key_len; cnt++) {
-        HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
-    }
-
-    /* Finish the digest. */
-    HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
-
-    /* Create byte sequence P. */
-    cp = p_bytes = alloca(key_len);
-    for (cnt = key_len; cnt >= 64; cnt -= 64) {
-        cp = mempcpy(cp, temp_result, 64);
-    }
-    memcpy(cp, temp_result, cnt);
-
-    /* Start computation of S byte sequence. */
-    HASH_Begin(alt_ctx);
-
-    /* For every character in the password add the entire salt. */
-    for (cnt = 0; cnt < 16 + alt_result[0]; cnt++) {
-        HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
-    }
-
-    /* Finish the digest. */
-    HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
-
-    /* Create byte sequence S.  */
-    cp = s_bytes = alloca(salt_len);
-    for (cnt = salt_len; cnt >= 64; cnt -= 64) {
-        cp = mempcpy(cp, temp_result, 64);
-    }
-    memcpy(cp, temp_result, cnt);
-
-    /* Repeatedly run the collected hash value through SHA512 to burn CPU cycles. */
-    for (cnt = 0; cnt < rounds; cnt++) {
-
-        HASH_Begin(ctx);
-
-        /* Add key or last result. */
-        if ((cnt & 1) != 0) {
-            HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
-        } else {
-            HASH_Update(ctx, alt_result, 64);
-        }
-
-        /* Add salt for numbers not divisible by 3. */
-        if (cnt % 3 != 0) {
-            HASH_Update(ctx, (const unsigned char *)s_bytes, salt_len);
-        }
-
-        /* Add key for numbers not divisible by 7. */
-        if (cnt % 7 != 0) {
-            HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
-        }
-
-        /* Add key or last result. */
-        if ((cnt & 1) != 0) {
-            HASH_Update(ctx, alt_result, 64);
-        } else {
-            HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
-        }
-
-        /* Create intermediate result. */
-        HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
-    }
-
-    /* Now we can construct the result string.
-     * It consists of three parts. */
-    if (buflen <= SALT_PREF_SIZE) {
-        ret = ERANGE;
-        goto done;
-    }
-
-    cp = __stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-    buflen -= SALT_PREF_SIZE;
-
-    if (rounds_custom) {
-        n = snprintf(cp, buflen, "%s%zu$",
-                     sha512_rounds_prefix, rounds);
-        if (n < 0 || n >= buflen) {
-            ret = ERANGE;
-            goto done;
-        }
-        cp += n;
-        buflen -= n;
-    }
-
-    if (buflen <= salt_len + 1) {
-        ret = ERANGE;
-        goto done;
-    }
-    cp = __stpncpy(cp, salt, salt_len);
-    *cp++ = '$';
-    buflen -= salt_len + 1;
-
-    /* fuzzyfill the base 64 string */
-    p1 = 0;
-    p2 = 21;
-    p3 = 42;
-    for (n = 0; n < 21; n++) {
-        b64_from_24bit(&cp, &buflen, 4, alt_result[p1], alt_result[p2], alt_result[p3]);
-        if (buflen == 0) {
-            ret = ERANGE;
-            goto done;
-        }
-        pt = p1;
-        p1 = p2 + 1;
-        p2 = p3 + 1;
-        p3 = pt + 1;
-    }
-    /* 64th and last byte */
-    b64_from_24bit(&cp, &buflen, 2, 0, 0, alt_result[p3]);
-    if (buflen == 0) {
-        ret = ERANGE;
-        goto done;
-    }
-
-    *cp = '\0';
-    ret = EOK;
-
-done:
-    /* Clear the buffer for the intermediate result so that people 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.  */
-    if (ctx) HASH_Destroy(ctx);
-    if (alt_ctx) HASH_Destroy(alt_ctx);
-    if (p_bytes) memset(p_bytes, '\0', key_len);
-    if (s_bytes) memset(s_bytes, '\0', salt_len);
-    if (copied_key) memset(copied_key, '\0', key_len);
-    if (copied_salt) memset(copied_salt, '\0', salt_len);
-    memset(temp_result, '\0', sizeof(temp_result));
-
-    return ret;
-}
-
-int s3crypt_sha512(TALLOC_CTX *memctx,
-                   const char *key, const char *salt, char **_hash)
-{
-    char *hash;
-    int hlen = (sizeof (sha512_salt_prefix) - 1
-                + sizeof (sha512_rounds_prefix) + 9 + 1
-                + strlen (salt) + 1 + 86 + 1);
-    int ret;
-
-    hash = talloc_size(memctx, hlen);
-    if (!hash) return ENOMEM;
-
-    ret = sha512_crypt_r(key, salt, hash, hlen);
-    if (ret) return ret;
-
-    *_hash = hash;
-    return ret;
-}
-
-#define SALT_RAND_LEN 12
-
-int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt)
-{
-    uint8_t rb[SALT_RAND_LEN];
-    char *salt, *cp;
-    size_t slen;
-    int ret;
-
-    if (!nspr_nss_init_done) {
-        ret = nspr_nss_init();
-        if (ret != SECSuccess) {
-            return EIO;
-        }
-    }
-
-    salt = talloc_size(memctx, SALT_LEN_MAX + 1);
-    if (!salt) {
-        return ENOMEM;
-    }
-
-    ret = PK11_GenerateRandom(rb, SALT_RAND_LEN);
-    if (ret != SECSuccess) {
-        return EIO;
-    }
-
-    slen = SALT_LEN_MAX;
-    cp = salt;
-    b64_from_24bit(&cp, &slen, 4, rb[0], rb[1], rb[2]);
-    b64_from_24bit(&cp, &slen, 4, rb[3], rb[4], rb[5]);
-    b64_from_24bit(&cp, &slen, 4, rb[6], rb[7], rb[8]);
-    b64_from_24bit(&cp, &slen, 4, rb[9], rb[10], rb[11]);
-    *cp = '\0';
-
-    *_salt = salt;
-
-    return EOK;
-}
-
diff --git a/src/util/sha512crypt.h b/src/util/sha512crypt.h
deleted file mode 100644
index 5512c5d..0000000
--- a/src/util/sha512crypt.h
+++ /dev/null
@@ -1,4 +0,0 @@
-
-int s3crypt_sha512(TALLOC_CTX *mmectx,
-                   const char *key, const char *salt, char **_hash);
-int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt);
-- 
1.7.2.2

