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:
parent
5f1005d5ce
commit
e0fda9a0ff
5 changed files with 103 additions and 350 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
87
src/bcrypt/crypt_blowfish.md
Normal file
87
src/bcrypt/crypt_blowfish.md
Normal 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.
|
|
@ -14,7 +14,6 @@
|
|||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Add table
Reference in a new issue