Skip to content

Commit

Permalink
Clean up Blowfish Cryptography
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
GregoryLundberg committed Feb 22, 2018
1 parent 5f1005d commit e0fda9a
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 350 deletions.
143 changes: 9 additions & 134 deletions src/bcrypt/bcrypt.c
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
19 changes: 7 additions & 12 deletions src/bcrypt/bcrypt.h
Expand Up @@ -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
Expand Down
87 changes: 87 additions & 0 deletions 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 <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.
1 change: 0 additions & 1 deletion src/bcrypt/crypt_blowfish/wrapper.c
Expand Up @@ -14,7 +14,6 @@
* See crypt_blowfish.c for more information.
*/

#define _GNU_SOURCE 1
#include <stdlib.h>
#include <string.h>

Expand Down

0 comments on commit e0fda9a

Please sign in to comment.