From e0fda9a0ff5f5b2c36f37d49825c81af007e53d4 Mon Sep 17 00:00:00 2001 From: Gregory A Lundberg Date: Wed, 21 Feb 2018 23:04:48 -0600 Subject: [PATCH] Clean up Blowfish Cryptography Remove dead code and Vultraz' quick hacks for MSVC. The bcrypt.c file is now compliant ISO Standard C and should port anywhere. Added a Markdown file with full documentation on how to obtain and install updates should that ever become necessary. --- src/bcrypt/bcrypt.c | 143 ++------------------ src/bcrypt/bcrypt.h | 19 +-- src/bcrypt/crypt_blowfish.md | 87 ++++++++++++ src/bcrypt/crypt_blowfish/wrapper.c | 1 - src/bcrypt/crypt_blowfish/x86.S | 203 ---------------------------- 5 files changed, 103 insertions(+), 350 deletions(-) create mode 100644 src/bcrypt/crypt_blowfish.md delete mode 100644 src/bcrypt/crypt_blowfish/x86.S diff --git a/src/bcrypt/bcrypt.c b/src/bcrypt/bcrypt.c index 9150b29d8d71..df45db74bc16 100644 --- a/src/bcrypt/bcrypt.c +++ b/src/bcrypt/bcrypt.c @@ -11,64 +11,20 @@ * with this software. If not, see * . */ + +/* + * 21FEB2018 - Gregory A Lundberg + * + * Deleted all unneeded code. This converts this source file from POSIX-only + * to fully portable, strictly compliant ISO Standard C. + */ + +#include #include -#include -#include -#include -#ifndef _WIN32 -#include -#else -#include -#endif -#include #include "bcrypt.h" #include "crypt_blowfish/ow-crypt.h" -#define RANDBYTES (16) - -static int try_close(int fd) -{ - int ret; - for (;;) { - errno = 0; - ret = close(fd); - if (ret == -1 && errno == EINTR) - continue; - break; - } - return ret; -} - -static int try_read(int fd, char *out, size_t count) -{ - size_t total; -#ifndef _WIN32 - ssize_t partial; -#else - int partial; -#endif - - total = 0; - while (total < count) - { - for (;;) { - errno = 0; - partial = read(fd, out + total, count - total); - if (partial == -1 && errno == EINTR) - continue; - break; - } - - if (partial < 1) - return -1; - - total += partial; - } - - return 0; -} - /* * This is a best effort implementation. Nothing prevents a compiler from * optimizing this function and making it vulnerable to timing attacks, but @@ -102,33 +58,6 @@ static int timing_safe_strcmp(const char *str1, const char *str2) return ret; } -int bcrypt_gensalt(int factor, char salt[BCRYPT_HASHSIZE]) -{ - int fd; - char input[RANDBYTES]; - int workf; - char *aux; - - fd = open("/dev/urandom", O_RDONLY); - if (fd == -1) - return 1; - - if (try_read(fd, input, RANDBYTES) != 0) { - if (try_close(fd) != 0) - return 4; - return 2; - } - - if (try_close(fd) != 0) - return 3; - - /* Generate salt. */ - workf = (factor < 4 || factor > 31)?12:factor; - aux = crypt_gensalt_rn("$2a$", workf, input, RANDBYTES, - salt, BCRYPT_HASHSIZE); - return (aux == NULL)?5:0; -} - int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) { char *aux; @@ -147,57 +76,3 @@ int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE]) return timing_safe_strcmp(hash, outhash); } - -#ifdef TEST_BCRYPT -#include -#include -#include -#include - -int main(void) -{ - clock_t before; - clock_t after; - char salt[BCRYPT_HASHSIZE]; - char hash[BCRYPT_HASHSIZE]; - int ret; - - const char pass[] = "hi,mom"; - const char hash1[] = "$2a$10$VEVmGHy4F4XQMJ3eOZJAUeb.MedU0W10pTPCuf53eHdKJPiSE8sMK"; - const char hash2[] = "$2a$10$3F0BVk5t8/aoS.3ddaB3l.fxg5qvafQ9NybxcpXLzMeAt.nVWn.NO"; - - ret = bcrypt_gensalt(12, salt); - assert(ret == 0); - printf("Generated salt: %s\n", salt); - before = clock(); - ret = bcrypt_hashpw("testtesttest", salt, hash); - assert(ret == 0); - after = clock(); - printf("Hashed password: %s\n", hash); - printf("Time taken: %f seconds\n", - (double)(after - before) / CLOCKS_PER_SEC); - - ret = bcrypt_hashpw(pass, hash1, hash); - assert(ret == 0); - printf("First hash check: %s\n", (strcmp(hash1, hash) == 0)?"OK":"FAIL"); - ret = bcrypt_hashpw(pass, hash2, hash); - assert(ret == 0); - printf("Second hash check: %s\n", (strcmp(hash2, hash) == 0)?"OK":"FAIL"); - - before = clock(); - ret = (bcrypt_checkpw(pass, hash1) == 0); - after = clock(); - printf("First hash check with bcrypt_checkpw: %s\n", ret?"OK":"FAIL"); - printf("Time taken: %f seconds\n", - (double)(after - before) / CLOCKS_PER_SEC); - - before = clock(); - ret = (bcrypt_checkpw(pass, hash2) == 0); - after = clock(); - printf("Second hash check with bcrypt_checkpw: %s\n", ret?"OK":"FAIL"); - printf("Time taken: %f seconds\n", - (double)(after - before) / CLOCKS_PER_SEC); - - return 0; -} -#endif diff --git a/src/bcrypt/bcrypt.h b/src/bcrypt/bcrypt.h index e45b3ca1390a..fba4d38fbc1d 100644 --- a/src/bcrypt/bcrypt.h +++ b/src/bcrypt/bcrypt.h @@ -14,24 +14,19 @@ * . */ +/* + * 21FEB2018 - Gregory A Lundberg + * + * Deleted all unneeded code. This converts this source file from POSIX-only + * to fully portable, strictly compliant ISO Standard C. + */ + #define BCRYPT_HASHSIZE (64) #ifdef __cplusplus extern "C" { #endif -/* - * This function expects a work factor between 4 and 31 and a char array to - * store the resulting generated salt. The char array should typically have - * BCRYPT_HASHSIZE bytes at least. If the provided work factor is not in the - * previous range, it will default to 12. - * - * The return value is zero if the salt could be correctly generated and - * nonzero otherwise. - * - */ -int bcrypt_gensalt(int workfactor, char salt[BCRYPT_HASHSIZE]); - /* * This function expects a password to be hashed, a salt to hash the password * with and a char array to leave the result. Both the salt and the hash diff --git a/src/bcrypt/crypt_blowfish.md b/src/bcrypt/crypt_blowfish.md new file mode 100644 index 000000000000..b82fb5d12f51 --- /dev/null +++ b/src/bcrypt/crypt_blowfish.md @@ -0,0 +1,87 @@ +# Blowfish Cryptography + +This document describes the process used to install Blowfish Cryptography 1.3 for Wesnoth. + +The goal of this process was, as much as possible, install clean, unchanged sources. +Traditionally, Wesnoth maintainers are tempted to make changes directly to the Blowfish source kit. +__This is strongly discouraged.__ +Future maintainers should strive, as much as possible, to follow a similar process. + +Future maintainers are expected to update this document as appropriate. + +## 1) Before you begin + +Be sure you are using a copy of the current master. +And be sure you are working in a private branch. + + $ cd ~/wesnoth + $ git checkout master + $ git pull --rebase upstream master + $ git checkout -b Upgrade_to_Blowfish_1.3 + +## 2) Update Blowfish Source + +Download the current source kit from [the maintainers](http://www.openwall.com/crypt/). +For Blowfish Cryptography 1.3, this was . +The following presumes you are working on Unix. +Windows is a bit more work, but generally follows the same process. + + $ cd ~ + $ wget http://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz + +Unpack into your home folder. +Note that, while the filename implies the file is compressed using GNU zip, it is actually just a plain tarball. + + $ tar -xf crypt_blowfish-1.3.tar.gz + +Change into the Blowfish Cryptography folder. + + $ cd ~/crypt_blowfish-1.3 + +We do not need, or want, the GNU libc patch files, the man page, or the x86 Assember source file, so delete them. + + $ rm *.diff crypt.3 x86.S + +Next, delete the current copy of Blowfish Cryptography in Wesnoth. + + $ cd ~/wesnoth/src/bcrypt + $ rm -fR crypt_blowfish + +Finally, move the new sources into place. + + $ mv ~/crypt_blowfish-1.3 crypt_blowfish + +## 3) Update SCons and CMake + +Remember to review the source kit for added and removed files, and change the SCons and CMake configuration, as needed. +Both build systems' build lists are in `~/wesnoth/source_lists/libwesnoth_core`. +Verify the files listed match the C source files just copied in; order is not important, headers are not listed. +The source list lists many files; you may have to search a bit. +The Blowfish Cryptography files, however, should all have names beginning with `bcrypt/crypt_blowfish/`. + +Updating the project files for other target platforms is optional at this point. + +## 4) Commit the changes + + $ cd ~/wesnoth + $ git add . + $ git commit -m 'Upgrade to Blowfish Cryptography 1.3' + +## 5) Build Wesnoth + +Run a test build. +Rarely, when upgrading Blwofish Cryptography, there are changes to the API. +Be sure to carefully check the build for errors and warnings about changed or missing Blowfish cryptography functions. +Make any adjustments necessary. +Generally, if needed, changes will appear in `~/wesnoth/src/bcrypt/bcrypt.c`. + +__Separately commit these adjustments.__ + +## 6) Create a Pull Request + +Even if you have direct access to the Wesnoth master repository, you should __never upgrade Blowfish Cryptography immediately__. +Push your local branch up to GitHub and create a Pull Request. + +Don't forget to monitor Travis/CI for your pull request to ensure a clean test run. + +Have someone else review your changes and merge them when all issues have been addressed. diff --git a/src/bcrypt/crypt_blowfish/wrapper.c b/src/bcrypt/crypt_blowfish/wrapper.c index ae5aac9d1c21..1e49c90d8542 100644 --- a/src/bcrypt/crypt_blowfish/wrapper.c +++ b/src/bcrypt/crypt_blowfish/wrapper.c @@ -14,7 +14,6 @@ * See crypt_blowfish.c for more information. */ -#define _GNU_SOURCE 1 #include #include diff --git a/src/bcrypt/crypt_blowfish/x86.S b/src/bcrypt/crypt_blowfish/x86.S deleted file mode 100644 index b0f1cd2ef124..000000000000 --- a/src/bcrypt/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