214 lines
6.4 KiB
Diff
214 lines
6.4 KiB
Diff
|
From 22a0cc20633a4ddd61233410563c9fabe6b515ed Mon Sep 17 00:00:00 2001
|
||
|
From: Ludwig Nussel <ludwig.nussel@suse.de>
|
||
|
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 <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
+
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <errno.h>
|
||
|
@@ -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
|
||
|
|