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.
This commit is contained in:
Gregory A Lundberg 2018-02-21 23:04:48 -06:00
parent 5f1005d5ce
commit e0fda9a0ff
No known key found for this signature in database
GPG key ID: 149484078AE8AE9E
5 changed files with 103 additions and 350 deletions

View file

@ -11,64 +11,20 @@
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/*
* 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 <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef _WIN32
#include <unistd.h>
#else
#include <io.h>
#endif
#include <errno.h>
#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 <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
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

View file

@ -14,24 +14,19 @@
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/*
* 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

View file

@ -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 <http://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz>.
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.

View file

@ -14,7 +14,6 @@
* See crypt_blowfish.c for more information.
*/
#define _GNU_SOURCE 1
#include <stdlib.h>
#include <string.h>

View file

@ -1,203 +0,0 @@
/*
* Written by Solar Designer <solar at openwall.com> 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