2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski/* This file is based on the work of Ulrich Drepper
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski * (http://people.redhat.com/drepper/SHA-crypt.txt). I have replaced the
4c7f058cdd19ce67b2b5d4b7f69703d0f8a21e38Christian Maeder * included SHA512 implementation by calls to NSS
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski * (http://www.mozilla.org/projects/security/pki/nss/).
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski * Sumit Bose <sbose@redhat.com>
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski/* SHA512-based Unix crypt implementation.
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. */
50dce6b011347f92377adb8bbabaeeb80975e86dChristian Maeder/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
86b1d0c80abdd4ca36491cf7025b718a5fea5080Christian Maeder#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
a10ff6125d62484ec5961c8a5d9d1c5a3e14fa66Christian Maeder/* Prefix for optional rounds specification. */
e85b224577b78d08ba5c39fe9dcc2e53995454a2Christian Maederconst char sha512_rounds_prefix[] = "rounds=";
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
7c757dd5b0b027dfc0cd0b9535758c8992cdde2fChristian Maeder/* Table with characters for base64 transformation. */
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski/* base64 conversion function */
3a761fd74f4f3c5587a199553c0ee7383e5d8ff3Christian Maederstatic inline void b64_from_24bit(char **dest, size_t *len, size_t n,
c2db39a683438b0f3d484519f4c93db26eec9d2eWiebke Herding for (i = 0; i < n; i++) {
f7d2e793728bbb7fd185e027eb9dfd7b9dd11c21Christian Maeder#define PTR_2_INT(x) ((x) - ((__typeof__ (x)) NULL))
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
e85b224577b78d08ba5c39fe9dcc2e53995454a2Christian Maeder /* Find beginning of salt string. The prefix should normally always be
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich * present. Just in case it is not. */
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
e85b224577b78d08ba5c39fe9dcc2e53995454a2Christian Maeder /* Skip salt prefix. */
2a693c01b154f1e25931ff6c754d2d02096e2662Till Mossakowski if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
4aa35aadcb28f8a962096efc70d3bdb58ab7d9faChristian Maeder if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
0e2ae85e2453466d03c1fc5884a3d693235bb9d9Christian Maeder if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
e85b224577b78d08ba5c39fe9dcc2e53995454a2Christian Maeder salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
3a761fd74f4f3c5587a199553c0ee7383e5d8ff3Christian Maeder key = copied_key = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, key, key_len);
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich salt = copied_salt = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, salt, salt_len);
goto done;
if (!ctx) {
goto done;
if (!alt_ctx) {
goto done;
goto done;
if (rounds_custom) {
if (n < 0 || n >= buflen) {
goto done;
cp += n;
buflen -= n;
goto done;
p1 = 0;
if (buflen == 0) {
goto done;
if (buflen == 0) {
goto done;
done:
return ret;
return ret;
return EIO;
if (!salt) {
return ENOMEM;
return EIO;
return EOK;