From 22a0cc20633a4ddd61233410563c9fabe6b515ed Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Tue, 5 Jul 2011 17:25:12 +0200 Subject: [PATCH crypt_blowfish 1/2] support for sha256 and sha512 --- crypt_gensalt.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ wrapper.c | 28 +++++++++++++ 2 files changed, 147 insertions(+), 0 deletions(-) diff --git a/crypt_gensalt.c b/crypt_gensalt.c index 43b0f6c..4600e30 100644 --- a/crypt_gensalt.c +++ b/crypt_gensalt.c @@ -7,6 +7,11 @@ * entirely in crypt_blowfish.c. */ +/* asprintf&free */ +#define _GNU_SOURCE +#include +#include + #include #include @@ -105,3 +110,117 @@ char *_crypt_gensalt_md5_rn(unsigned long count, return output; } + +char *_crypt_gensalt_sha256_rn (unsigned long count, + const char *input, int size, char *output, int output_size) +{ + unsigned long value; + char *buf; + char buf2[12]; + + if (count > 0) { + if (asprintf (&buf, "$5$rounds=%ld$", count) < 0) { + if (output_size > 0) + output[0] = '\0'; + errno = ENOMEM; + return NULL; + } + } else { + if (asprintf (&buf, "$5$") < 0) { + if (output_size > 0) + output[0] = '\0'; + errno = ENOMEM; + return NULL; + } + } + + if (size < 3 || output_size < (int)strlen (buf) + 4 + 1) { + free (buf); + if (output_size > 0) + output[0] = '\0'; + errno = ERANGE; + return NULL; + } + + value = (unsigned long)(unsigned char)input[0] | + ((unsigned long)(unsigned char)input[1] << 8) | + ((unsigned long)(unsigned char)input[2] << 16); + buf2[0] = _crypt_itoa64[value & 0x3f]; + buf2[1] = _crypt_itoa64[(value >> 6) & 0x3f]; + buf2[2] = _crypt_itoa64[(value >> 12) & 0x3f]; + buf2[3] = _crypt_itoa64[(value >> 18) & 0x3f]; + buf2[4] = '\0'; + + if (size >= 6 && output_size >= (int)strlen (buf) + 4 + 4 + 1) { + value = (unsigned long)(unsigned char)input[3] | + ((unsigned long)(unsigned char)input[4] << 8) | + ((unsigned long)(unsigned char)input[5] << 16); + buf2[4] = _crypt_itoa64[value & 0x3f]; + buf2[5] = _crypt_itoa64[(value >> 6) & 0x3f]; + buf2[6] = _crypt_itoa64[(value >> 12) & 0x3f]; + buf2[7] = _crypt_itoa64[(value >> 18) & 0x3f]; + buf2[8] = '\0'; + } + + snprintf (output, output_size, "%s%s", buf, buf2); + free (buf); + + return output; +} + +char *_crypt_gensalt_sha512_rn (unsigned long count, + const char *input, int size, char *output, int output_size) +{ + unsigned long value; + char *buf; + char buf2[12]; + + if (count > 0) { + if (asprintf (&buf, "$6$rounds=%ld$", count) < 0) { + if (output_size > 0) + output[0] = '\0'; + errno = ENOMEM; + return NULL; + } + } else { + if (asprintf (&buf, "$6$") < 0) { + if (output_size > 0) + output[0] = '\0'; + errno = ENOMEM; + return NULL; + } + } + + if (size < 3 || output_size < (int)strlen (buf) + 4 + 1) { + free (buf); + if (output_size > 0) + output[0] = '\0'; + __set_errno(ERANGE); + return NULL; + } + + value = (unsigned long)(unsigned char)input[0] | + ((unsigned long)(unsigned char)input[1] << 8) | + ((unsigned long)(unsigned char)input[2] << 16); + buf2[0] = _crypt_itoa64[value & 0x3f]; + buf2[1] = _crypt_itoa64[(value >> 6) & 0x3f]; + buf2[2] = _crypt_itoa64[(value >> 12) & 0x3f]; + buf2[3] = _crypt_itoa64[(value >> 18) & 0x3f]; + buf2[4] = '\0'; + + if (size >= 6 && output_size >= (int)strlen (buf) + 4 + 4 + 1) { + value = (unsigned long)(unsigned char)input[3] | + ((unsigned long)(unsigned char)input[4] << 8) | + ((unsigned long)(unsigned char)input[5] << 16); + buf2[4] = _crypt_itoa64[value & 0x3f]; + buf2[5] = _crypt_itoa64[(value >> 6) & 0x3f]; + buf2[6] = _crypt_itoa64[(value >> 12) & 0x3f]; + buf2[7] = _crypt_itoa64[(value >> 18) & 0x3f]; + buf2[8] = '\0'; + } + + snprintf (output, output_size, "%s%s", buf, buf2); + free (buf); + + return output; +} diff --git a/wrapper.c b/wrapper.c index af441bc..07772bc 100644 --- a/wrapper.c +++ b/wrapper.c @@ -33,12 +33,20 @@ #include "crypt_blowfish.h" #include "crypt_gensalt.h" +extern char *_crypt_gensalt_sha256_rn(unsigned long count, + const char *input, int size, char *output, int output_size); +extern char *_crypt_gensalt_sha512_rn(unsigned long count, + const char *input, int size, char *output, int output_size); #if defined(__GLIBC__) && defined(_LIBC) /* crypt.h from glibc-crypt-2.1 will define struct crypt_data for us */ #include "crypt.h" extern char *__md5_crypt_r(const char *key, const char *salt, char *buffer, int buflen); +extern char *__sha256_crypt_r (const char *key, const char *salt, + char *buffer, int buflen); +extern char *__sha512_crypt_r (const char *key, const char *salt, + char *buffer, int buflen); /* crypt-entry.c needs to be patched to define __des_crypt_r rather than * __crypt_r, and not define crypt_r and crypt at all */ extern char *__des_crypt_r(const char *key, const char *salt, @@ -101,6 +109,10 @@ static char *_crypt_retval_magic(char *retval, const char *setting, char *__crypt_rn(__const char *key, __const char *setting, void *data, int size) { + if (setting[0] == '$' && setting[1] == '6') + return __sha512_crypt_r(key, setting, (char *)data, size); + if (setting[0] == '$' && setting[1] == '5') + return __sha256_crypt_r(key, setting, (char *)data, size); if (setting[0] == '$' && setting[1] == '2') return _crypt_blowfish_rn(key, setting, (char *)data, size); if (setting[0] == '$' && setting[1] == '1') @@ -118,6 +130,16 @@ char *__crypt_rn(__const char *key, __const char *setting, char *__crypt_ra(__const char *key, __const char *setting, void **data, int *size) { + if (setting[0] == '$' && setting[1] == '6') { + if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) + return NULL; + return __sha512_crypt_r(key, setting, (char *)*data, *size); + } + if (setting[0] == '$' && setting[1] == '5') { + if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) + return NULL; + return __sha256_crypt_r(key, setting, (char *)*data, *size); + } if (setting[0] == '$' && setting[1] == '2') { if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) return NULL; @@ -199,6 +221,12 @@ char *__crypt_gensalt_rn(const char *prefix, unsigned long count, return NULL; } + if (!strncmp(prefix, "$6$", 3)) + use = _crypt_gensalt_sha512_rn; + else + if (!strncmp(prefix, "$5$", 3)) + use = _crypt_gensalt_sha256_rn; + else if (!strncmp(prefix, "$2a$", 4) || !strncmp(prefix, "$2y$", 4)) use = _crypt_gensalt_blowfish_rn; else -- 1.7.3.4