diff --git a/3p/crypt_blowfish/crypt_blowfish.c b/3p/crypt_blowfish.c similarity index 100% rename from 3p/crypt_blowfish/crypt_blowfish.c rename to 3p/crypt_blowfish.c diff --git a/3p/crypt_blowfish/crypt_blowfish.h b/3p/crypt_blowfish.h similarity index 100% rename from 3p/crypt_blowfish/crypt_blowfish.h rename to 3p/crypt_blowfish.h diff --git a/3p/crypt_blowfish/crypt.h b/3p/crypt_blowfish/crypt.h deleted file mode 100644 index 12e6705..0000000 --- a/3p/crypt_blowfish/crypt.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Written by Solar Designer in 2000-2002. - * No copyright is claimed, and the software is hereby placed in the public - * domain. In case this attempt to disclaim copyright and place the software - * in the public domain is deemed null and void, then the software is - * Copyright (c) 2000-2002 Solar Designer and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See crypt_blowfish.c for more information. - */ - -#include - -#if defined(_OW_SOURCE) || defined(__USE_OW) -#define __SKIP_GNU -#undef __SKIP_OW -#include -#undef __SKIP_GNU -#endif diff --git a/3p/crypt_blowfish/crypt_gensalt.c b/3p/crypt_blowfish/crypt_gensalt.c deleted file mode 100644 index 73c15a1..0000000 --- a/3p/crypt_blowfish/crypt_gensalt.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Written by Solar Designer in 2000-2011. - * No copyright is claimed, and the software is hereby placed in the public - * domain. In case this attempt to disclaim copyright and place the software - * in the public domain is deemed null and void, then the software is - * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See crypt_blowfish.c for more information. - * - * This file contains salt generation functions for the traditional and - * other common crypt(3) algorithms, except for bcrypt which is defined - * entirely in crypt_blowfish.c. - */ - -#include - -#include -#ifndef __set_errno -#define __set_errno(val) errno = (val) -#endif - -/* Just to make sure the prototypes match the actual definitions */ -#include "crypt_gensalt.h" - -unsigned char _crypt_itoa64[64 + 1] = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - -char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count, - const char *input, int size, char *output, int output_size) -{ - (void) prefix; - - if (size < 2 || output_size < 2 + 1 || (count && count != 25)) { - if (output_size > 0) output[0] = '\0'; - __set_errno((output_size < 2 + 1) ? ERANGE : EINVAL); - return NULL; - } - - output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f]; - output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f]; - output[2] = '\0'; - - return output; -} - -char *_crypt_gensalt_extended_rn(const char *prefix, unsigned long count, - const char *input, int size, char *output, int output_size) -{ - unsigned long value; - - (void) prefix; - -/* Even iteration counts make it easier to detect weak DES keys from a look - * at the hash, so they should be avoided */ - if (size < 3 || output_size < 1 + 4 + 4 + 1 || - (count && (count > 0xffffff || !(count & 1)))) { - if (output_size > 0) output[0] = '\0'; - __set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL); - return NULL; - } - - if (!count) count = 725; - - output[0] = '_'; - output[1] = _crypt_itoa64[count & 0x3f]; - output[2] = _crypt_itoa64[(count >> 6) & 0x3f]; - output[3] = _crypt_itoa64[(count >> 12) & 0x3f]; - output[4] = _crypt_itoa64[(count >> 18) & 0x3f]; - value = (unsigned long)(unsigned char)input[0] | - ((unsigned long)(unsigned char)input[1] << 8) | - ((unsigned long)(unsigned char)input[2] << 16); - output[5] = _crypt_itoa64[value & 0x3f]; - output[6] = _crypt_itoa64[(value >> 6) & 0x3f]; - output[7] = _crypt_itoa64[(value >> 12) & 0x3f]; - output[8] = _crypt_itoa64[(value >> 18) & 0x3f]; - output[9] = '\0'; - - return output; -} - -char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count, - const char *input, int size, char *output, int output_size) -{ - unsigned long value; - - (void) prefix; - - if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) { - if (output_size > 0) output[0] = '\0'; - __set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL); - return NULL; - } - - output[0] = '$'; - output[1] = '1'; - output[2] = '$'; - value = (unsigned long)(unsigned char)input[0] | - ((unsigned long)(unsigned char)input[1] << 8) | - ((unsigned long)(unsigned char)input[2] << 16); - output[3] = _crypt_itoa64[value & 0x3f]; - output[4] = _crypt_itoa64[(value >> 6) & 0x3f]; - output[5] = _crypt_itoa64[(value >> 12) & 0x3f]; - output[6] = _crypt_itoa64[(value >> 18) & 0x3f]; - output[7] = '\0'; - - if (size >= 6 && output_size >= 3 + 4 + 4 + 1) { - value = (unsigned long)(unsigned char)input[3] | - ((unsigned long)(unsigned char)input[4] << 8) | - ((unsigned long)(unsigned char)input[5] << 16); - output[7] = _crypt_itoa64[value & 0x3f]; - output[8] = _crypt_itoa64[(value >> 6) & 0x3f]; - output[9] = _crypt_itoa64[(value >> 12) & 0x3f]; - output[10] = _crypt_itoa64[(value >> 18) & 0x3f]; - output[11] = '\0'; - } - - return output; -} diff --git a/3p/crypt_blowfish/crypt_gensalt.h b/3p/crypt_blowfish/crypt_gensalt.h deleted file mode 100644 index 457bbfe..0000000 --- a/3p/crypt_blowfish/crypt_gensalt.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Written by Solar Designer in 2000-2011. - * No copyright is claimed, and the software is hereby placed in the public - * domain. In case this attempt to disclaim copyright and place the software - * in the public domain is deemed null and void, then the software is - * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See crypt_blowfish.c for more information. - */ - -#ifndef _CRYPT_GENSALT_H -#define _CRYPT_GENSALT_H - -extern unsigned char _crypt_itoa64[]; -extern char *_crypt_gensalt_traditional_rn(const char *prefix, - unsigned long count, - const char *input, int size, char *output, int output_size); -extern char *_crypt_gensalt_extended_rn(const char *prefix, - unsigned long count, - const char *input, int size, char *output, int output_size); -extern char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count, - const char *input, int size, char *output, int output_size); - -#endif diff --git a/3p/crypt_blowfish/ow-crypt.h b/3p/crypt_blowfish/ow-crypt.h deleted file mode 100644 index 2e48794..0000000 --- a/3p/crypt_blowfish/ow-crypt.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Written by Solar Designer in 2000-2011. - * No copyright is claimed, and the software is hereby placed in the public - * domain. In case this attempt to disclaim copyright and place the software - * in the public domain is deemed null and void, then the software is - * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See crypt_blowfish.c for more information. - */ - -#ifndef _OW_CRYPT_H -#define _OW_CRYPT_H - -#ifndef __GNUC__ -#undef __const -#define __const const -#endif - -#ifndef __SKIP_GNU -extern char *crypt(__const char *key, __const char *setting); -extern char *crypt_r(__const char *key, __const char *setting, void *data); -#endif - -#ifndef __SKIP_OW -extern char *crypt_rn(__const char *key, __const char *setting, - void *data, int size); -extern char *crypt_ra(__const char *key, __const char *setting, - void **data, int *size); -extern char *crypt_gensalt(__const char *prefix, unsigned long count, - __const char *input, int size); -extern char *crypt_gensalt_rn(__const char *prefix, unsigned long count, - __const char *input, int size, char *output, int output_size); -extern char *crypt_gensalt_ra(__const char *prefix, unsigned long count, - __const char *input, int size); -#endif - -#endif diff --git a/3p/crypt_blowfish/wrapper.c b/3p/crypt_blowfish/wrapper.c deleted file mode 100644 index 1e49c90..0000000 --- a/3p/crypt_blowfish/wrapper.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Written by Solar Designer in 2000-2014. - * No copyright is claimed, and the software is hereby placed in the public - * domain. In case this attempt to disclaim copyright and place the software - * in the public domain is deemed null and void, then the software is - * Copyright (c) 2000-2014 Solar Designer and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See crypt_blowfish.c for more information. - */ - -#include -#include - -#include -#ifndef __set_errno -#define __set_errno(val) errno = (val) -#endif - -#ifdef TEST -#include -#include -#include -#include -#include -#include -#ifdef TEST_THREADS -#include -#endif -#endif - -#define CRYPT_OUTPUT_SIZE (7 + 22 + 31 + 1) -#define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1) - -#if defined(__GLIBC__) && defined(_LIBC) -#define __SKIP_GNU -#endif -#include "ow-crypt.h" - -#include "crypt_blowfish.h" -#include "crypt_gensalt.h" - -#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); -/* 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, - struct crypt_data *data); -extern struct crypt_data _ufc_foobar; -#endif - -static int _crypt_data_alloc(void **data, int *size, int need) -{ - void *updated; - - if (*data && *size >= need) return 0; - - updated = realloc(*data, need); - - if (!updated) { -#ifndef __GLIBC__ - /* realloc(3) on glibc sets errno, so we don't need to bother */ - __set_errno(ENOMEM); -#endif - return -1; - } - -#if defined(__GLIBC__) && defined(_LIBC) - if (need >= sizeof(struct crypt_data)) - ((struct crypt_data *)updated)->initialized = 0; -#endif - - *data = updated; - *size = need; - - return 0; -} - -static char *_crypt_retval_magic(char *retval, const char *setting, - char *output, int size) -{ - if (retval) - return retval; - - if (_crypt_output_magic(setting, output, size)) - return NULL; /* shouldn't happen */ - - return output; -} - -#if defined(__GLIBC__) && defined(_LIBC) -/* - * Applications may re-use the same instance of struct crypt_data without - * resetting the initialized field in order to let crypt_r() skip some of - * its initialization code. Thus, it is important that our multiple hashing - * algorithms either don't conflict with each other in their use of the - * data area or reset the initialized field themselves whenever required. - * Currently, the hashing algorithms simply have no conflicts: the first - * field of struct crypt_data is the 128-byte large DES key schedule which - * __des_crypt_r() calculates each time it is called while the two other - * hashing algorithms use less than 128 bytes of the data area. - */ - -char *__crypt_rn(__const char *key, __const char *setting, - void *data, int size) -{ - if (setting[0] == '$' && setting[1] == '2') - return _crypt_blowfish_rn(key, setting, (char *)data, size); - if (setting[0] == '$' && setting[1] == '1') - return __md5_crypt_r(key, setting, (char *)data, size); - if (setting[0] == '$' || setting[0] == '_') { - __set_errno(EINVAL); - return NULL; - } - if (size >= sizeof(struct crypt_data)) - return __des_crypt_r(key, setting, (struct crypt_data *)data); - __set_errno(ERANGE); - return NULL; -} - -char *__crypt_ra(__const char *key, __const char *setting, - void **data, int *size) -{ - if (setting[0] == '$' && setting[1] == '2') { - if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) - return NULL; - return _crypt_blowfish_rn(key, setting, (char *)*data, *size); - } - if (setting[0] == '$' && setting[1] == '1') { - if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) - return NULL; - return __md5_crypt_r(key, setting, (char *)*data, *size); - } - if (setting[0] == '$' || setting[0] == '_') { - __set_errno(EINVAL); - return NULL; - } - if (_crypt_data_alloc(data, size, sizeof(struct crypt_data))) - return NULL; - return __des_crypt_r(key, setting, (struct crypt_data *)*data); -} - -char *__crypt_r(__const char *key, __const char *setting, - struct crypt_data *data) -{ - return _crypt_retval_magic( - __crypt_rn(key, setting, data, sizeof(*data)), - setting, (char *)data, sizeof(*data)); -} - -char *__crypt(__const char *key, __const char *setting) -{ - return _crypt_retval_magic( - __crypt_rn(key, setting, &_ufc_foobar, sizeof(_ufc_foobar)), - setting, (char *)&_ufc_foobar, sizeof(_ufc_foobar)); -} -#else -char *crypt_rn(const char *key, const char *setting, void *data, int size) -{ - return _crypt_blowfish_rn(key, setting, (char *)data, size); -} - -char *crypt_ra(const char *key, const char *setting, - void **data, int *size) -{ - if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) - return NULL; - return _crypt_blowfish_rn(key, setting, (char *)*data, *size); -} - -char *crypt_r(const char *key, const char *setting, void *data) -{ - return _crypt_retval_magic( - crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE), - setting, (char *)data, CRYPT_OUTPUT_SIZE); -} - -char *crypt(const char *key, const char *setting) -{ - static char output[CRYPT_OUTPUT_SIZE]; - - return _crypt_retval_magic( - crypt_rn(key, setting, output, sizeof(output)), - setting, output, sizeof(output)); -} - -#define __crypt_gensalt_rn crypt_gensalt_rn -#define __crypt_gensalt_ra crypt_gensalt_ra -#define __crypt_gensalt crypt_gensalt -#endif - -char *__crypt_gensalt_rn(const char *prefix, unsigned long count, - const char *input, int size, char *output, int output_size) -{ - char *(*use)(const char *_prefix, unsigned long _count, - const char *_input, int _size, - char *_output, int _output_size); - - /* This may be supported on some platforms in the future */ - if (!input) { - __set_errno(EINVAL); - return NULL; - } - - if (!strncmp(prefix, "$2a$", 4) || !strncmp(prefix, "$2b$", 4) || - !strncmp(prefix, "$2y$", 4)) - use = _crypt_gensalt_blowfish_rn; - else - if (!strncmp(prefix, "$1$", 3)) - use = _crypt_gensalt_md5_rn; - else - if (prefix[0] == '_') - use = _crypt_gensalt_extended_rn; - else - if (!prefix[0] || - (prefix[0] && prefix[1] && - memchr(_crypt_itoa64, prefix[0], 64) && - memchr(_crypt_itoa64, prefix[1], 64))) - use = _crypt_gensalt_traditional_rn; - else { - __set_errno(EINVAL); - return NULL; - } - - return use(prefix, count, input, size, output, output_size); -} - -char *__crypt_gensalt_ra(const char *prefix, unsigned long count, - const char *input, int size) -{ - char output[CRYPT_GENSALT_OUTPUT_SIZE]; - char *retval; - - retval = __crypt_gensalt_rn(prefix, count, - input, size, output, sizeof(output)); - - if (retval) { - retval = strdup(retval); -#ifndef __GLIBC__ - /* strdup(3) on glibc sets errno, so we don't need to bother */ - if (!retval) - __set_errno(ENOMEM); -#endif - } - - return retval; -} - -char *__crypt_gensalt(const char *prefix, unsigned long count, - const char *input, int size) -{ - static char output[CRYPT_GENSALT_OUTPUT_SIZE]; - - return __crypt_gensalt_rn(prefix, count, - input, size, output, sizeof(output)); -} - -#if defined(__GLIBC__) && defined(_LIBC) -weak_alias(__crypt_rn, crypt_rn) -weak_alias(__crypt_ra, crypt_ra) -weak_alias(__crypt_r, crypt_r) -weak_alias(__crypt, crypt) -weak_alias(__crypt_gensalt_rn, crypt_gensalt_rn) -weak_alias(__crypt_gensalt_ra, crypt_gensalt_ra) -weak_alias(__crypt_gensalt, crypt_gensalt) -weak_alias(crypt, fcrypt) -#endif - -#ifdef TEST -static const char *tests[][3] = { - {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", - "U*U"}, - {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", - "U*U*"}, - {"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", - "U*U*U"}, - {"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", - "0123456789abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - "chars after 72 are ignored"}, - {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", - "\xa3"}, - {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", - "\xff\xff\xa3"}, - {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", - "\xff\xff\xa3"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85.", - "\xff\xff\xa3"}, - {"$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", - "\xff\xff\xa3"}, - {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", - "\xa3"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", - "\xa3"}, - {"$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", - "\xa3"}, - {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", - "1\xa3" "345"}, - {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", - "\xff\xa3" "345"}, - {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", - "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, - {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", - "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd.", - "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, - {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e", - "\xff\xa3" "345"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e", - "\xff\xa3" "345"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", - "\xa3" "ab"}, - {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", - "\xa3" "ab"}, - {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", - "\xa3" "ab"}, - {"$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS", - "\xd1\x91"}, - {"$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS", - "\xd0\xc1\xd2\xcf\xcc\xd8"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6", - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "chars after 72 are ignored as usual"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy", - "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" - "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" - "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" - "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" - "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" - "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"}, - {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe", - "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" - "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" - "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" - "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" - "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" - "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"}, - {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", - ""}, - {"*0", "", "$2a$03$CCCCCCCCCCCCCCCCCCCCC."}, - {"*0", "", "$2a$32$CCCCCCCCCCCCCCCCCCCCC."}, - {"*0", "", "$2c$05$CCCCCCCCCCCCCCCCCCCCC."}, - {"*0", "", "$2z$05$CCCCCCCCCCCCCCCCCCCCC."}, - {"*0", "", "$2`$05$CCCCCCCCCCCCCCCCCCCCC."}, - {"*0", "", "$2{$05$CCCCCCCCCCCCCCCCCCCCC."}, - {"*1", "", "*0"}, - {NULL} -}; - -#define which tests[0] - -static volatile sig_atomic_t running; - -static void handle_timer(int signum) -{ - (void) signum; - running = 0; -} - -static void *run(void *arg) -{ - unsigned long count = 0; - int i = 0; - void *data = NULL; - int size = 0x12345678; - - do { - const char *hash = tests[i][0]; - const char *key = tests[i][1]; - const char *setting = tests[i][2]; - - if (!tests[++i][0]) - i = 0; - - if (setting && strlen(hash) < 30) /* not for benchmark */ - continue; - - if (strcmp(crypt_ra(key, hash, &data, &size), hash)) { - printf("%d: FAILED (crypt_ra/%d/%lu)\n", - (int)((char *)arg - (char *)0), i, count); - free(data); - return NULL; - } - count++; - } while (running); - - free(data); - return count + (char *)0; -} - -int main(void) -{ - struct itimerval it; - struct tms buf; - clock_t clk_tck, start_real, start_virtual, end_real, end_virtual; - unsigned long count; - void *data; - int size; - char *setting1, *setting2; - int i; -#ifdef TEST_THREADS - pthread_t t[TEST_THREADS]; - void *t_retval; -#endif - - data = NULL; - size = 0x12345678; - - for (i = 0; tests[i][0]; i++) { - const char *hash = tests[i][0]; - const char *key = tests[i][1]; - const char *setting = tests[i][2]; - const char *p; - int ok = !setting || strlen(hash) >= 30; - int o_size; - char s_buf[30], o_buf[61]; - if (!setting) { - memcpy(s_buf, hash, sizeof(s_buf) - 1); - s_buf[sizeof(s_buf) - 1] = 0; - setting = s_buf; - } - - __set_errno(0); - p = crypt(key, setting); - if ((!ok && !errno) || strcmp(p, hash)) { - printf("FAILED (crypt/%d)\n", i); - return 1; - } - - if (ok && strcmp(crypt(key, hash), hash)) { - printf("FAILED (crypt/%d)\n", i); - return 1; - } - - for (o_size = -1; o_size <= (int)sizeof(o_buf); o_size++) { - int ok_n = ok && o_size == (int)sizeof(o_buf); - const char *x = "abc"; - strcpy(o_buf, x); - if (o_size >= 3) { - x = "*0"; - if (setting[0] == '*' && setting[1] == '0') - x = "*1"; - } - __set_errno(0); - p = crypt_rn(key, setting, o_buf, o_size); - if ((ok_n && (!p || strcmp(p, hash))) || - (!ok_n && (!errno || p || strcmp(o_buf, x)))) { - printf("FAILED (crypt_rn/%d)\n", i); - return 1; - } - } - - __set_errno(0); - p = crypt_ra(key, setting, &data, &size); - if ((ok && (!p || strcmp(p, hash))) || - (!ok && (!errno || p || strcmp((char *)data, hash)))) { - printf("FAILED (crypt_ra/%d)\n", i); - return 1; - } - } - - setting1 = crypt_gensalt(which[0], 12, data, size); - if (!setting1 || strncmp(setting1, "$2a$12$", 7)) { - puts("FAILED (crypt_gensalt)\n"); - return 1; - } - - setting2 = crypt_gensalt_ra(setting1, 12, data, size); - if (strcmp(setting1, setting2)) { - puts("FAILED (crypt_gensalt_ra/1)\n"); - return 1; - } - - (*(char *)data)++; - setting1 = crypt_gensalt_ra(setting2, 12, data, size); - if (!strcmp(setting1, setting2)) { - puts("FAILED (crypt_gensalt_ra/2)\n"); - return 1; - } - - free(setting1); - free(setting2); - free(data); - -#if defined(_SC_CLK_TCK) || !defined(CLK_TCK) - clk_tck = sysconf(_SC_CLK_TCK); -#else - clk_tck = CLK_TCK; -#endif - - running = 1; - signal(SIGALRM, handle_timer); - - memset(&it, 0, sizeof(it)); - it.it_value.tv_sec = 5; - setitimer(ITIMER_REAL, &it, NULL); - - start_real = times(&buf); - start_virtual = buf.tms_utime + buf.tms_stime; - - count = (char *)run((char *)0) - (char *)0; - - end_real = times(&buf); - end_virtual = buf.tms_utime + buf.tms_stime; - if (end_virtual == start_virtual) end_virtual++; - - printf("%.1f c/s real, %.1f c/s virtual\n", - (float)count * clk_tck / (end_real - start_real), - (float)count * clk_tck / (end_virtual - start_virtual)); - -#ifdef TEST_THREADS - running = 1; - it.it_value.tv_sec = 60; - setitimer(ITIMER_REAL, &it, NULL); - start_real = times(&buf); - - for (i = 0; i < TEST_THREADS; i++) - if (pthread_create(&t[i], NULL, run, i + (char *)0)) { - perror("pthread_create"); - return 1; - } - - for (i = 0; i < TEST_THREADS; i++) { - if (pthread_join(t[i], &t_retval)) { - perror("pthread_join"); - continue; - } - if (!t_retval) continue; - count = (char *)t_retval - (char *)0; - end_real = times(&buf); - printf("%d: %.1f c/s real\n", i, - (float)count * clk_tck / (end_real - start_real)); - } -#endif - - return 0; -} -#endif diff --git a/3p/crypt_blowfish/x86.S b/3p/crypt_blowfish/x86.S deleted file mode 100644 index b0f1cd2..0000000 --- a/3p/crypt_blowfish/x86.S +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Written by Solar Designer in 1998-2010. - * No copyright is claimed, and the software is hereby placed in the public - * domain. In case this attempt to disclaim copyright and place the software - * in the public domain is deemed null and void, then the software is - * Copyright (c) 1998-2010 Solar Designer and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See crypt_blowfish.c for more information. - */ - -#ifdef __i386__ - -#if defined(__OpenBSD__) && !defined(__ELF__) -#define UNDERSCORES -#define ALIGN_LOG -#endif - -#if defined(__CYGWIN32__) || defined(__MINGW32__) -#define UNDERSCORES -#endif - -#ifdef __DJGPP__ -#define UNDERSCORES -#define ALIGN_LOG -#endif - -#ifdef UNDERSCORES -#define _BF_body_r __BF_body_r -#endif - -#ifdef ALIGN_LOG -#define DO_ALIGN(log) .align (log) -#elif defined(DUMBAS) -#define DO_ALIGN(log) .align 1 << log -#else -#define DO_ALIGN(log) .align (1 << (log)) -#endif - -#define BF_FRAME 0x200 -#define ctx %esp - -#define BF_ptr (ctx) - -#define S(N, r) N+BF_FRAME(ctx,r,4) -#ifdef DUMBAS -#define P(N) 0x1000+N+N+N+N+BF_FRAME(ctx) -#else -#define P(N) 0x1000+4*N+BF_FRAME(ctx) -#endif - -/* - * This version of the assembly code is optimized primarily for the original - * Intel Pentium but is also careful to avoid partial register stalls on the - * Pentium Pro family of processors (tested up to Pentium III Coppermine). - * - * It is possible to do 15% faster on the Pentium Pro family and probably on - * many non-Intel x86 processors, but, unfortunately, that would make things - * twice slower for the original Pentium. - * - * An additional 2% speedup may be achieved with non-reentrant code. - */ - -#define L %esi -#define R %edi -#define tmp1 %eax -#define tmp1_lo %al -#define tmp2 %ecx -#define tmp2_hi %ch -#define tmp3 %edx -#define tmp3_lo %dl -#define tmp4 %ebx -#define tmp4_hi %bh -#define tmp5 %ebp - -.text - -#define BF_ROUND(L, R, N) \ - xorl L,tmp2; \ - xorl tmp1,tmp1; \ - movl tmp2,L; \ - shrl $16,tmp2; \ - movl L,tmp4; \ - movb tmp2_hi,tmp1_lo; \ - andl $0xFF,tmp2; \ - movb tmp4_hi,tmp3_lo; \ - andl $0xFF,tmp4; \ - movl S(0,tmp1),tmp1; \ - movl S(0x400,tmp2),tmp5; \ - addl tmp5,tmp1; \ - movl S(0x800,tmp3),tmp5; \ - xorl tmp5,tmp1; \ - movl S(0xC00,tmp4),tmp5; \ - addl tmp1,tmp5; \ - movl 4+P(N),tmp2; \ - xorl tmp5,R - -#define BF_ENCRYPT_START \ - BF_ROUND(L, R, 0); \ - BF_ROUND(R, L, 1); \ - BF_ROUND(L, R, 2); \ - BF_ROUND(R, L, 3); \ - BF_ROUND(L, R, 4); \ - BF_ROUND(R, L, 5); \ - BF_ROUND(L, R, 6); \ - BF_ROUND(R, L, 7); \ - BF_ROUND(L, R, 8); \ - BF_ROUND(R, L, 9); \ - BF_ROUND(L, R, 10); \ - BF_ROUND(R, L, 11); \ - BF_ROUND(L, R, 12); \ - BF_ROUND(R, L, 13); \ - BF_ROUND(L, R, 14); \ - BF_ROUND(R, L, 15); \ - movl BF_ptr,tmp5; \ - xorl L,tmp2; \ - movl P(17),L - -#define BF_ENCRYPT_END \ - xorl R,L; \ - movl tmp2,R - -DO_ALIGN(5) -.globl _BF_body_r -_BF_body_r: - movl 4(%esp),%eax - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - subl $BF_FRAME-8,%eax - xorl L,L - cmpl %esp,%eax - ja BF_die - xchgl %eax,%esp - xorl R,R - pushl %eax - leal 0x1000+BF_FRAME-4(ctx),%eax - movl 0x1000+BF_FRAME-4(ctx),tmp2 - pushl %eax - xorl tmp3,tmp3 -BF_loop_P: - BF_ENCRYPT_START - addl $8,tmp5 - BF_ENCRYPT_END - leal 0x1000+18*4+BF_FRAME(ctx),tmp1 - movl tmp5,BF_ptr - cmpl tmp5,tmp1 - movl L,-8(tmp5) - movl R,-4(tmp5) - movl P(0),tmp2 - ja BF_loop_P - leal BF_FRAME(ctx),tmp5 - xorl tmp3,tmp3 - movl tmp5,BF_ptr -BF_loop_S: - BF_ENCRYPT_START - BF_ENCRYPT_END - movl P(0),tmp2 - movl L,(tmp5) - movl R,4(tmp5) - BF_ENCRYPT_START - BF_ENCRYPT_END - movl P(0),tmp2 - movl L,8(tmp5) - movl R,12(tmp5) - BF_ENCRYPT_START - BF_ENCRYPT_END - movl P(0),tmp2 - movl L,16(tmp5) - movl R,20(tmp5) - BF_ENCRYPT_START - addl $32,tmp5 - BF_ENCRYPT_END - leal 0x1000+BF_FRAME(ctx),tmp1 - movl tmp5,BF_ptr - cmpl tmp5,tmp1 - movl P(0),tmp2 - movl L,-8(tmp5) - movl R,-4(tmp5) - ja BF_loop_S - movl 4(%esp),%esp - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - -BF_die: -/* Oops, need to re-compile with a larger BF_FRAME. */ - hlt - jmp BF_die - -#endif - -#if defined(__ELF__) && defined(__linux__) -.section .note.GNU-stack,"",@progbits -#endif diff --git a/TODO b/TODO index f7bf301..f57b812 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,5 @@ bcrypt passwords session management using proper random tokens CSRF protection -input validation to avoid XSS and injection \ No newline at end of file +input validation to avoid XSS and injection +only allow signup, login ecc over HTTPS diff --git a/misc/schema.sql b/misc/schema.sql index 1cdbda7..a5d3e17 100644 --- a/misc/schema.sql +++ b/misc/schema.sql @@ -1,7 +1,7 @@ CREATE TABLE IF NOT EXISTS Users ( id INTEGER PRIMARY KEY, username TEXT NOT NULL UNIQUE, - password TEXT NOT NULL, + hash TEXT NOT NULL, email TEXT NOT NULL UNIQUE, signup_time DATETIME DEFAULT CURRENT_TIMESTAMP ); diff --git a/src/bcrypt.c b/src/bcrypt.c index e69de29..7c25535 100644 --- a/src/bcrypt.c +++ b/src/bcrypt.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include "bcrypt.h" + +int hash_password(char *pass, int passlen, int cost, PasswordHash *hash) +{ + char passzt[128]; + if (passlen >= (int) sizeof(passzt)) + return -1; + memcpy(passzt, pass, passlen); + passzt[passlen] = '\0'; + + unsigned char random[16] = { + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, // TODO + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + }; + + char salt[30]; + if (_crypt_gensalt_blowfish_rn("$2b$", cost, (char*) random, sizeof(random), salt, sizeof(salt)) == NULL) + return -1; + + if (_crypt_blowfish_rn(passzt, salt, hash->data, (int) sizeof(hash->data)) == NULL) + return -1; + + return 0; +} + +int check_password(char *pass, int passlen, PasswordHash hash) +{ + char passzt[128]; + if (passlen >= (int) sizeof(passzt)) + return -1; + memcpy(passzt, pass, passlen); + passzt[passlen] = '\0'; + + PasswordHash new_hash; + if (_crypt_blowfish_rn(passzt, hash.data, new_hash.data, sizeof(new_hash.data)) == NULL) + return -1; + + if (strcmp(hash.data, new_hash.data)) // TODO: should be constant-time + return 1; + + return 0; +} diff --git a/src/bcrypt.h b/src/bcrypt.h new file mode 100644 index 0000000..a9505e1 --- /dev/null +++ b/src/bcrypt.h @@ -0,0 +1,11 @@ +#ifndef BCRYPT_INCLUDED +#define BCRYPT_INCLUDED + +typedef struct { + char data[61]; +} PasswordHash; + +int hash_password(char *pass, int passlen, int cost, PasswordHash *hash); +int check_password(char *pass, int passlen, PasswordHash hash); + +#endif // BCRYPT_INCLUDED diff --git a/src/main.c b/src/main.c index 372f293..39ab5c2 100644 --- a/src/main.c +++ b/src/main.c @@ -4,8 +4,9 @@ #include #include #include -#include "sqlite3.h" #include "chttp.h" +#include "bcrypt.h" +#include "sqlite3.h" #include "sqlite3utils.h" #include "template.h" @@ -45,9 +46,13 @@ int load_file(char *file, char **data, long *size) int create_user(SQLiteCache *dbcache, HTTP_String name, HTTP_String email, HTTP_String pass) { + PasswordHash hash; + int ret = hash_password(pass.ptr, pass.len, 12, &hash); + if (ret) return -500; + sqlite3_stmt *stmt; - int ret = sqlite3utils_prepare_and_bind(dbcache, &stmt, - "INSERT INTO Users(username, email, password) VALUES (?, ?, ?)", name, email, pass); + ret = sqlite3utils_prepare_and_bind(dbcache, &stmt, + "INSERT INTO Users(username, email, hash) VALUES (?, ?, ?)", name, email, ((HTTP_String) { hash.data, strlen(hash.data) })); if (ret != SQLITE_OK) return -500; @@ -80,7 +85,7 @@ int user_exists(SQLiteCache *dbcache, HTTP_String name, HTTP_String pass) { sqlite3_stmt *stmt; int ret = sqlite3utils_prepare_and_bind(dbcache, &stmt, - "SELECT id FROM Users WHERE username=? AND password=?", name, pass); + "SELECT id, hash FROM Users WHERE username=?", name); if (ret != SQLITE_OK) return -500; @@ -100,6 +105,30 @@ int user_exists(SQLiteCache *dbcache, HTTP_String name, HTTP_String pass) return -500; } + const char *rawhash = (const char*) sqlite3_column_text(stmt, 1); + if (rawhash == NULL) { + sqlite3_reset(stmt); + return -500; + } + int rawhashlen = sqlite3_column_bytes(stmt, 1); + + PasswordHash hash; + if (rawhashlen >= sizeof(hash.data)) { + sqlite3_reset(stmt); + return -500; + } + strcpy(hash.data, rawhash); + + ret = check_password(pass.ptr, pass.len, hash); + if (ret < 0) { + sqlite3_reset(stmt); + return -500; + } + if (ret > 0) { + sqlite3_reset(stmt); + return -400; + } + ret = sqlite3_reset(stmt); if (ret != SQLITE_OK) return -500; @@ -382,7 +411,7 @@ int main(void) { http_global_init(); - printf("%s\n", sqlite3_libversion()); + printf("%s\n", sqlite3_libversion()); sqlite3 *db; int ret = sqlite3_open(":memory:", &db); diff --git a/src/sqlite3utils.c b/src/sqlite3utils.c index cad2b40..9985b5e 100644 --- a/src/sqlite3utils.c +++ b/src/sqlite3utils.c @@ -83,7 +83,7 @@ static int lookup(SQLiteCache *cache, char *fmt, int fmtlen) return -1; } -int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, const char *fmt, int fmtlen) +int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, char *fmt, int fmtlen) { if (fmtlen < 0) fmtlen = strlen(fmt); @@ -118,7 +118,7 @@ int sqlite3utils_prepare(SQLiteCache *cache, sqlite3_stmt **pstmt, const char *f } int sqlite3utils_prepare_and_bind_impl(SQLiteCache *cache, - sqlite3_stmt **pstmt, const char *fmt, VArgs args) + sqlite3_stmt **pstmt, char *fmt, VArgs args) { sqlite3_stmt *stmt; int ret = sqlite3utils_prepare(cache, &stmt, fmt, strlen(fmt)); diff --git a/src/sqlite3utils.h b/src/sqlite3utils.h index 321ef55..9deeab4 100644 --- a/src/sqlite3utils.h +++ b/src/sqlite3utils.h @@ -13,9 +13,9 @@ void sqlite_cache_free(SQLiteCache *cache); sqlite3* sqlite_cache_getdb(SQLiteCache *cache); int sqlite3utils_prepare(SQLiteCache *cache, - sqlite3_stmt **pstmt, const char *fmt, int fmtlen); + sqlite3_stmt **pstmt, char *fmt, int fmtlen); int sqlite3utils_prepare_and_bind_impl(SQLiteCache *cache, - sqlite3_stmt **pstmt, const char *fmt, VArgs args); + sqlite3_stmt **pstmt, char *fmt, VArgs args); #endif // SQLITE3UTILS_INCLUDED \ No newline at end of file