Added bcrypt

This commit is contained in:
R. Eric Wheeler 2016-03-09 08:41:12 -08:00
parent 13e7596fdd
commit 48686835c6
32 changed files with 3574 additions and 0 deletions

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "src/3rdparty/fundamentals"]
path = src/3rdparty/fundamentals
url = https://github.com/fundamentalslib/fundamentals5
[submodule "src/3rdparty/crypt/scrypt"]
path = src/3rdparty/crypt/scrypt
url = https://github.com/Tarsnap/scrypt.git

121
src/3rdparty/crypt/bcrypt/COPYING vendored Normal file
View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

121
src/3rdparty/crypt/bcrypt/LICENSE vendored Normal file
View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

24
src/3rdparty/crypt/bcrypt/Makefile vendored Normal file
View File

@ -0,0 +1,24 @@
CC = gcc
CFLAGS = $(shell grep '^CFLAGS = ' crypt_blowfish/Makefile | cut -d= -f2-)
.PHONY: crypt_blowfish
all: bcrypt.a
test: bcrypt.c crypt_blowfish
$(CC) $(CFLAGS) -DTEST_BCRYPT -c bcrypt.c
$(CC) -o bcrypt_test bcrypt.o crypt_blowfish/*.o
bcrypt.a: bcrypt.o crypt_blowfish
ar r bcrypt.a bcrypt.o crypt_blowfish/*.o
ln -s bcrypt.o libbcrypt.so
bcrypt.o: bcrypt.c
$(CC) $(CFLAGS) -c bcrypt.c
crypt_blowfish:
$(MAKE) -C crypt_blowfish
clean:
rm -f *.o bcrypt_test bcrypt.a *~ core
rm -f libbcrypt.so
$(MAKE) -C crypt_blowfish clean

21
src/3rdparty/crypt/bcrypt/README.md vendored Normal file
View File

@ -0,0 +1,21 @@
# BCrypt $2y
This is a modified version of [https://github.com/rg3/bcrypt](rg3/bcrypt).
The only change is support for the newer $2y hash used in php's
password_hash.
This library is a simple wrapper providing a convenient reentrant interface for
the bcrypt password hashing algorithm implementation as provided by Solar
Designer at http://www.openwall.com/crypt/. An exact copy of that source code
is included in the crypt_blowfish subdirectory.
The provided C interface is inspired in the bcrypt Python module that can be
found at http://code.google.com/p/py-bcrypt/, and consists of a function to
generate salts with the characteristic work factor parameter, one to generate
password hashes which can also used to verify passwords and one designed
specifically to verify passwords and avoid timing attacks. Please check the
header bcrypt.h. It contains the prototypes and lots of comments with examples.
All this code is released to the public domain under the terms of CC0. See the
COPYING file for the legal text.

195
src/3rdparty/crypt/bcrypt/bcrypt.c vendored Normal file
View File

@ -0,0 +1,195 @@
/*
* bcrypt wrapper library
*
* Written in 2011, 2013, 2014, 2015 by Ricardo Garcia <r@rg3.name>
*
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "bcrypt.h"
#include "crypt_blowfish/ow-crypt.h"
#define RANDBYTES (22)
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;
ssize_t partial;
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
* this method is commonly used in crypto libraries like NaCl.
*
* Return value is zero if both strings are equal and nonzero otherwise.
*/
static int timing_safe_strcmp(const char *str1, const char *str2)
{
const unsigned char *u1;
const unsigned char *u2;
int ret;
int i;
int len1 = strlen(str1);
int len2 = strlen(str2);
/* In our context both strings should always have the same length
* because they will be hashed passwords. */
if (len1 != len2)
return 1;
/* Force unsigned for bitwise operations. */
u1 = (const unsigned char *)str1;
u2 = (const unsigned char *)str2;
ret = 0;
for (i = 0; i < len1; ++i)
ret |= (u1[i] ^ u2[i]);
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("$2y$", 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;
aux = crypt_rn(passwd, salt, hash, BCRYPT_HASHSIZE);
return (aux == NULL)?1:0;
}
int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE])
{
int ret;
char outhash[BCRYPT_HASHSIZE];
ret = bcrypt_hashpw(passwd, hash, outhash);
if (ret != 0)
return -1;
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

97
src/3rdparty/crypt/bcrypt/bcrypt.h vendored Normal file
View File

@ -0,0 +1,97 @@
#ifndef BCRYPT_H_
#define BCRYPT_H_
/*
* bcrypt wrapper library
*
* Written in 2011, 2013, 2014, 2015 by Ricardo Garcia <r@rg3.name>
*
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#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
* parameters should have room for BCRYPT_HASHSIZE characters at least.
*
* It can also be used to verify a hashed password. In that case, provide the
* expected hash in the salt parameter and verify the output hash is the same
* as the input hash. However, to avoid timing attacks, it's better to use
* bcrypt_checkpw when verifying a password.
*
* The return value is zero if the password could be hashed and nonzero
* otherwise.
*/
int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE],
char hash[BCRYPT_HASHSIZE]);
/*
* This function expects a password and a hash to verify the password against.
* The internal implementation is tuned to avoid timing attacks.
*
* The return value will be -1 in case of errors, zero if the provided password
* matches the given hash and greater than zero if no errors are found and the
* passwords don't match.
*
*/
int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE]);
/*
* Brief Example
* -------------
*
* Hashing a password:
*
* char salt[BCRYPT_HASHSIZE];
* char hash[BCRYPT_HASHSIZE];
* int ret;
*
* ret = bcrypt_gensalt(12, salt);
* assert(ret == 0);
* ret = bcrypt_hashpw("thepassword", salt, hash);
* assert(ret == 0);
*
*
* Verifying a password:
*
* int ret;
*
* ret = bcrypt_checkpw("thepassword", "expectedhash");
* assert(ret != -1);
*
* if (ret == 0) {
* printf("The password matches\n");
* } else {
* printf("The password does NOT match\n");
* }
*
*/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,29 @@
New versions of this package (crypt_blowfish):
http://www.openwall.com/crypt/
A paper on the algorithm that explains its design decisions:
http://www.usenix.org/events/usenix99/provos.html
Unix Seventh Edition Manual, Volume 2: the password scheme (1978):
http://plan9.bell-labs.com/7thEdMan/vol2/password
The Openwall GNU/*/Linux (Owl) tcb suite implementing the alternative
password shadowing scheme. This includes a PAM module which
supersedes pam_unix and uses the password hashing framework provided
with crypt_blowfish when setting new passwords.
http://www.openwall.com/tcb/
pam_passwdqc, a password strength checking and policy enforcement
module for PAM-aware password changing programs:
http://www.openwall.com/passwdqc/
John the Ripper password cracker:
http://www.openwall.com/john/
$Owl: Owl/packages/glibc/crypt_blowfish/LINKS,v 1.4 2005/11/16 13:09:47 solar Exp $

View File

@ -0,0 +1,77 @@
#
# Written and revised by Solar Designer <solar at openwall.com> 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.
#
CC = gcc
AS = $(CC)
LD = $(CC)
RM = rm -f
CFLAGS = -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wundef -Wpointer-arith -O2 -fomit-frame-pointer -funroll-loops
ASFLAGS = -c
LDFLAGS = -s
BLOWFISH_OBJS = \
crypt_blowfish.o x86.o
CRYPT_OBJS = \
$(BLOWFISH_OBJS) crypt_gensalt.o wrapper.o
TEST_OBJS = \
$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test.o
TEST_THREADS_OBJS = \
$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test_threads.o
EXTRA_MANS = \
crypt_r.3 crypt_rn.3 crypt_ra.3 \
crypt_gensalt.3 crypt_gensalt_rn.3 crypt_gensalt_ra.3
all: $(CRYPT_OBJS) man
check: crypt_test
./crypt_test
crypt_test: $(TEST_OBJS)
$(LD) $(LDFLAGS) $(TEST_OBJS) -o $@
crypt_test.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
$(CC) -c $(CFLAGS) wrapper.c -DTEST -o $@
check_threads: crypt_test_threads
./crypt_test_threads
crypt_test_threads: $(TEST_THREADS_OBJS)
$(LD) $(LDFLAGS) $(TEST_THREADS_OBJS) -lpthread -o $@
crypt_test_threads.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
$(CC) -c $(CFLAGS) wrapper.c -DTEST -DTEST_THREADS=4 -o $@
man: $(EXTRA_MANS)
$(EXTRA_MANS):
echo '.so man3/crypt.3' > $@
crypt_blowfish.o: crypt_blowfish.h
crypt_gensalt.o: crypt_gensalt.h
wrapper.o: crypt.h ow-crypt.h crypt_blowfish.h crypt_gensalt.h
.c.o:
$(CC) -c $(CFLAGS) $*.c
.S.o:
$(AS) $(ASFLAGS) $*.S
clean:
$(RM) crypt_test crypt_test_threads *.o $(EXTRA_MANS) core

View File

@ -0,0 +1,30 @@
These numbers are for 32 iterations ("$2a$05"):
OpenBSD 3.0 bcrypt(*) crypt_blowfish 0.4.4
Pentium III, 840 MHz 99 c/s 121 c/s (+22%)
Alpha 21164PC, 533 MHz 55.5 c/s 76.9 c/s (+38%)
UltraSparc IIi, 400 MHz 49.9 c/s 52.5 c/s (+5%)
Pentium, 120 MHz 8.8 c/s 20.1 c/s (+128%)
PA-RISC 7100LC, 80 MHz 8.5 c/s 16.3 c/s (+92%)
(*) built with -fomit-frame-pointer -funroll-loops, which I don't
think happens for libcrypt.
Starting with version 1.1 released in June 2011, default builds of
crypt_blowfish invoke a quick self-test on every hash computation.
This has roughly a 4.8% performance impact at "$2a$05", but only a 0.6%
impact at a more typical setting of "$2a$08".
The large speedup for the original Pentium is due to the assembly
code and the weird optimizations this processor requires.
The numbers for password cracking are 2 to 10% higher than those for
crypt_blowfish as certain things may be done out of the loop and the
code doesn't need to be reentrant.
Recent versions of John the Ripper (1.6.25-dev and newer) achieve an
additional 15% speedup on the Pentium Pro family of processors (which
includes Pentium III) with a separate version of the assembly code and
run-time CPU detection.
$Owl: Owl/packages/glibc/crypt_blowfish/PERFORMANCE,v 1.6 2011/06/21 12:09:20 solar Exp $

View File

@ -0,0 +1,68 @@
This is an implementation of a password hashing method, provided via the
crypt(3) and a reentrant interface. It is fully compatible with
OpenBSD's bcrypt.c for prefix "$2b$", originally by Niels Provos and
David Mazieres. (Please refer to the included crypt(3) man page for
information on minor compatibility issues for other bcrypt prefixes.)
I've placed this code in the public domain, with fallback to a
permissive license. Please see the comment in crypt_blowfish.c for
more information.
You can use the provided routines in your own packages, or link them
into a C library. I've provided hooks for linking into GNU libc, but
it shouldn't be too hard to get this into another C library. Note
that simply adding this code into your libc is probably not enough to
make your system use the new password hashing algorithm. Changes to
passwd(1), PAM modules, or whatever else your system uses will likely
be needed as well. These are not a part of this package, but see
LINKS for a pointer to our tcb suite.
Instructions on using the routines in one of the two common ways are
given below. It is recommended that you test the routines on your
system before you start. Type "make check" or "make check_threads"
(if you have the POSIX threads library), then "make clean".
1. Using the routines in your programs.
The available interfaces are in ow-crypt.h, and this is the file you
should include. You won't need crypt.h. When linking, add all of the
C files and x86.S (you can compile and link it even on a non-x86, it
will produce no code in this case).
2. Building the routines into GNU C library.
For versions 2.13 and 2.14 (and likely other nearby ones), extract the
library sources as usual. Apply the patch for glibc 2.14 provided in
this package. Enter crypt/ and rename crypt.h to gnu-crypt.h within
that directory. Copy the C sources, header, and assembly (x86.S) files
from this package in there as well (but be sure you don't overwrite the
Makefile). Configure, build, and install the library as usual.
For versions 2.2 to 2.3.6 (and likely also for some newer ones),
extract the library sources and maybe its optional add-ons as usual.
Apply the patch for glibc 2.3.6 provided in this package. Enter
crypt/ and rename crypt.h to gnu-crypt.h within that directory. Copy
the C sources, header, and assembly (x86.S) files from this package in
there as well (but be sure you don't overwrite the Makefile).
Configure, build, and install the library as usual.
For versions 2.1 to 2.1.3, extract the library sources and the crypt
and linuxthreads add-ons as usual. Apply the patch for glibc 2.1.3
provided in this package. Enter crypt/sysdeps/unix/, and rename
crypt.h to gnu-crypt.h within that directory. Copy C sources, header,
and assembly (x86.S) files from this package in there as well (but be
sure you don't overwrite the Makefile). Configure, build, and install
the library as usual.
Programs that want to use the provided interfaces will need to include
crypt.h (but not ow-crypt.h directly). By default, prototypes for the
new routines aren't defined (but the extra functionality of crypt(3)
is indeed available). You need to define _OW_SOURCE to obtain the new
routines as well.
--
Solar Designer <solar at openwall.com>
$Owl: Owl/packages/glibc/crypt_blowfish/README,v 1.10 2014/07/07 15:19:04 solar Exp $

View File

@ -0,0 +1,575 @@
.\" Written and revised by Solar Designer <solar at openwall.com> in 2000-2011.
.\" No copyright is claimed, and this man page is hereby placed in the public
.\" domain. In case this attempt to disclaim copyright and place the man page
.\" in the public domain is deemed null and void, then the man page 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.
.\"
.\" This manual page in its current form is intended for use on systems
.\" based on the GNU C Library with crypt_blowfish patched into libcrypt.
.\"
.TH CRYPT 3 "July 7, 2014" "Openwall Project" "Library functions"
.ad l
.\" No macros in NAME to keep makewhatis happy.
.SH NAME
\fBcrypt\fR, \fBcrypt_r\fR, \fBcrypt_rn\fR, \fBcrypt_ra\fR,
\fBcrypt_gensalt\fR, \fBcrypt_gensalt_rn\fR, \fBcrypt_gensalt_ra\fR
\- password hashing
.SH SYNOPSIS
.B #define _XOPEN_SOURCE
.br
.B #include <unistd.h>
.sp
.in +8
.ti -8
.BI "char *crypt(const char *" key ", const char *" setting );
.in -8
.sp
.B #define _GNU_SOURCE
.br
.B #include <crypt.h>
.sp
.in +8
.ti -8
.BI "char *crypt_r(const char *" key ", const char *" setting ", struct crypt_data *" data );
.in -8
.sp
.B #define _OW_SOURCE
.br
.B #include <crypt.h>
.sp
.in +8
.ti -8
.BI "char *crypt_rn(const char *" key ", const char *" setting ", void *" data ", int " size );
.ti -8
.BI "char *crypt_ra(const char *" key ", const char *" setting ", void **" data ", int *" size );
.ti -8
.BI "char *crypt_gensalt(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
.ti -8
.BI "char *crypt_gensalt_rn(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ", char *" output ", int " output_size );
.ti -8
.BI "char *crypt_gensalt_ra(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
.ad b
.de crypt
.BR crypt ,
.BR crypt_r ,
.BR crypt_rn ", \\$1"
.ie "\\$2"" .B crypt_ra
.el .BR crypt_ra "\\$2"
..
.de crypt_gensalt
.BR crypt_gensalt ,
.BR crypt_gensalt_rn ", \\$1"
.ie "\\$2"" .B crypt_gensalt_ra
.el .BR crypt_gensalt_ra "\\$2"
..
.SH DESCRIPTION
The
.crypt and
functions calculate a cryptographic hash function of
.I key
with one of a number of supported methods as requested with
.IR setting ,
which is also used to pass a salt and possibly other parameters to
the chosen method.
The hashing methods are explained below.
.PP
Unlike
.BR crypt ,
the functions
.BR crypt_r ,
.BR crypt_rn " and"
.B crypt_ra
are reentrant.
They place their result and possibly their private data in a
.I data
area of
.I size
bytes as passed to them by an application and/or in memory they
allocate dynamically. Some hashing algorithms may use the data area to
cache precomputed intermediate values across calls. Thus, applications
must properly initialize the data area before its first use.
.B crypt_r
requires that only
.I data->initialized
be reset to zero;
.BR crypt_rn " and " crypt_ra
require that either the entire data area is zeroed or, in the case of
.BR crypt_ra ,
.I *data
is NULL. When called with a NULL
.I *data
or insufficient
.I *size
for the requested hashing algorithm,
.B crypt_ra
uses
.BR realloc (3)
to allocate the required amount of memory dynamically. Thus,
.B crypt_ra
has the additional requirement that
.IR *data ,
when non-NULL, must point to an area allocated either with a previous
call to
.B crypt_ra
or with a
.BR malloc (3)
family call.
The memory allocated by
.B crypt_ra
should be freed with
.BR free "(3)."
.PP
The
.crypt_gensalt and
functions compile a string for use as
.I setting
\- with the given
.I prefix
(used to choose a hashing method), the iteration
.I count
(if supported by the chosen method) and up to
.I size
cryptographically random
.I input
bytes for use as the actual salt.
If
.I count
is 0, a low default will be picked.
The random bytes may be obtained from
.BR /dev/urandom .
Unlike
.BR crypt_gensalt ,
the functions
.BR crypt_gensalt_rn " and " crypt_gensalt_ra
are reentrant.
.B crypt_gensalt_rn
places its result in the
.I output
buffer of
.I output_size
bytes.
.B crypt_gensalt_ra
allocates memory for its result dynamically. The memory should be
freed with
.BR free "(3)."
.SH RETURN VALUE
Upon successful completion, the functions
.crypt and
return a pointer to a string containing the setting that was actually used
and a printable encoding of the hash function value.
The entire string is directly usable as
.I setting
with other calls to
.crypt and
and as
.I prefix
with calls to
.crypt_gensalt and .
.PP
The behavior of
.B crypt
on errors isn't well standardized. Some implementations simply can't fail
(unless the process dies, in which case they obviously can't return),
others return NULL or a fixed string. Most implementations don't set
.IR errno ,
but some do. SUSv2 specifies only returning NULL and setting
.I errno
as a valid behavior, and defines only one possible error
.RB "(" ENOSYS ,
"The functionality is not supported on this implementation.")
Unfortunately, most existing applications aren't prepared to handle
NULL returns from
.BR crypt .
The description below corresponds to this implementation of
.BR crypt " and " crypt_r
only, and to
.BR crypt_rn " and " crypt_ra .
The behavior may change to match standards, other implementations or
existing applications.
.PP
.BR crypt " and " crypt_r
may only fail (and return) when passed an invalid or unsupported
.IR setting ,
in which case they return a pointer to a magic string that is
shorter than 13 characters and is guaranteed to differ from
.IR setting .
This behavior is safe for older applications which assume that
.B crypt
can't fail, when both setting new passwords and authenticating against
existing password hashes.
.BR crypt_rn " and " crypt_ra
return NULL to indicate failure. All four functions set
.I errno
when they fail.
.PP
The functions
.crypt_gensalt and
return a pointer to the compiled string for
.IR setting ,
or NULL on error in which case
.I errno
is set.
.SH ERRORS
.TP
.B EINVAL
.crypt "" :
.I setting
is invalid or not supported by this implementation;
.sp
.crypt_gensalt "" :
.I prefix
is invalid or not supported by this implementation;
.I count
is invalid for the requested
.IR prefix ;
the input
.I size
is insufficient for the smallest valid salt with the requested
.IR prefix ;
.I input
is NULL.
.TP
.B ERANGE
.BR crypt_rn :
the provided data area
.I size
is insufficient for the requested hashing algorithm;
.sp
.BR crypt_gensalt_rn :
.I output_size
is too small to hold the compiled
.I setting
string.
.TP
.B ENOMEM
.B crypt
(original glibc only):
failed to allocate memory for the output buffer (which subsequent calls
would re-use);
.sp
.BR crypt_ra :
.I *data
is NULL or
.I *size
is insufficient for the requested hashing algorithm and
.BR realloc (3)
failed;
.sp
.BR crypt_gensalt_ra :
failed to allocate memory for the compiled
.I setting
string.
.TP
.B ENOSYS
.B crypt
(SUSv2):
the functionality is not supported on this implementation;
.sp
.BR crypt ,
.B crypt_r
(glibc 2.0 to 2.0.1 only):
.de no-crypt-add-on
the crypt add-on is not compiled in and
.I setting
requests something other than the MD5-based algorithm.
..
.no-crypt-add-on
.TP
.B EOPNOTSUPP
.BR crypt ,
.B crypt_r
(glibc 2.0.2 to 2.1.3 only):
.no-crypt-add-on
.SH HASHING METHODS
The implemented hashing methods are intended specifically for processing
user passwords for storage and authentication;
they are at best inefficient for most other purposes.
.PP
It is important to understand that password hashing is not a replacement
for strong passwords.
It is always possible for an attacker with access to password hashes
to try guessing candidate passwords against the hashes.
There are, however, certain properties a password hashing method may have
which make these key search attacks somewhat harder.
.PP
All of the hashing methods use salts such that the same
.I key
may produce many possible hashes.
Proper use of salts may defeat a number of attacks, including:
.TP
1.
The ability to try candidate passwords against multiple hashes at the
price of one.
.TP
2.
The use of pre-hashed lists of candidate passwords.
.TP
3.
The ability to determine whether two users (or two accounts of one user)
have the same or different passwords without actually having to guess
one of the passwords.
.PP
The key search attacks depend on computing hashes of large numbers of
candidate passwords.
Thus, the computational cost of a good password hashing method must be
high \- but of course not too high to render it impractical.
.PP
All hashing methods implemented within the
.crypt and
interfaces use multiple iterations of an underlying cryptographic
primitive specifically in order to increase the cost of trying a
candidate password.
Unfortunately, due to hardware improvements, the hashing methods which
have a fixed cost become increasingly less secure over time.
.PP
In addition to salts, modern password hashing methods accept a variable
iteration
.IR count .
This makes it possible to adapt their cost to the hardware improvements
while still maintaining compatibility.
.PP
The following hashing methods are or may be implemented within the
described interfaces:
.PP
.de hash
.ad l
.TP
.I prefix
.ie "\\$1"" \{\
"" (empty string);
.br
a string matching ^[./0-9A-Za-z]{2} (see
.BR regex (7))
.\}
.el "\\$1"
.TP
.B Encoding syntax
\\$2
.TP
.B Maximum password length
\\$3 (uses \\$4-bit characters)
.TP
.B Effective key size
.ie "\\$5"" limited by the hash size only
.el up to \\$5 bits
.TP
.B Hash size
\\$6 bits
.TP
.B Salt size
\\$7 bits
.TP
.B Iteration count
\\$8
.ad b
..
.ti -2
.B Traditional DES-based
.br
This method is supported by almost all implementations of
.BR crypt .
Unfortunately, it no longer offers adequate security because of its many
limitations.
Thus, it should not be used for new passwords unless you absolutely have
to be able to migrate the password hashes to other systems.
.hash "" "[./0-9A-Za-z]{13}" 8 7 56 64 12 25
.PP
.ti -2
.B Extended BSDI-style DES-based
.br
This method is used on BSDI and is also available on at least NetBSD,
OpenBSD, and FreeBSD due to the use of David Burren's FreeSec library.
.hash _ "_[./0-9A-Za-z]{19}" unlimited 7 56 64 24 "1 to 2**24-1 (must be odd)"
.PP
.ti -2
.B FreeBSD-style MD5-based
.br
This is Poul-Henning Kamp's MD5-based password hashing method originally
developed for FreeBSD.
It is currently supported on many free Unix-like systems, on Solaris 10
and newer, and it is part of the official glibc.
Its main disadvantage is the fixed iteration count, which is already
too low for the currently available hardware.
.hash "$1$" "\e$1\e$[^$]{1,8}\e$[./0-9A-Za-z]{22}" unlimited 8 "" 128 "6 to 48" 1000
.PP
.ti -2
.BR "OpenBSD-style Blowfish-based" " (" bcrypt )
.br
.B bcrypt
was originally developed by Niels Provos and David Mazieres for OpenBSD
and is also supported on recent versions of FreeBSD and NetBSD,
on Solaris 10 and newer, and on several GNU/*/Linux distributions.
It is, however, not part of the official glibc.
.PP
While both
.B bcrypt
and the BSDI-style DES-based hashing offer a variable iteration count,
.B bcrypt
may scale to even faster hardware, doesn't allow for certain optimizations
specific to password cracking only, doesn't have the effective key size
limitation, and uses 8-bit characters in passwords.
.hash "$2b$" "\e$2[abxy]\e$[0-9]{2}\e$[./A-Za-z0-9]{53}" 72 8 "" 184 128 "2**4 to 2**99 (current implementations are limited to 2**31 iterations)"
.PP
With
.BR bcrypt ,
the
.I count
passed to
.crypt_gensalt and
is the base-2 logarithm of the actual iteration count.
.PP
.B bcrypt
hashes used the "$2a$" prefix since 1997.
However, in 2011 an implementation bug was discovered in crypt_blowfish
(versions up to 1.0.4 inclusive) affecting handling of password characters with
the 8th bit set.
Besides fixing the bug,
to provide for upgrade strategies for existing systems, two new prefixes were
introduced: "$2x$", which fully re-introduces the bug, and "$2y$", which
guarantees correct handling of both 7- and 8-bit characters.
OpenBSD 5.5 introduced the "$2b$" prefix for behavior that exactly matches
crypt_blowfish's "$2y$", and current crypt_blowfish supports it as well.
Unfortunately, the behavior of "$2a$" on password characters with the 8th bit
set has to be considered system-specific.
When generating new password hashes, the "$2b$" or "$2y$" prefix should be used.
(If such hashes ever need to be migrated to a system that does not yet support
these new prefixes, the prefix in migrated copies of the already-generated
hashes may be changed to "$2a$".)
.PP
.crypt_gensalt and
support the "$2b$", "$2y$", and "$2a$" prefixes (the latter for legacy programs
or configurations), but not "$2x$" (which must not be used for new hashes).
.crypt and
support all four of these prefixes.
.SH PORTABILITY NOTES
Programs using any of these functions on a glibc 2.x system must be
linked against
.BR libcrypt .
However, many Unix-like operating systems and older versions of the
GNU C Library include the
.BR crypt " function in " libc .
.PP
The
.BR crypt_r ,
.BR crypt_rn ,
.BR crypt_ra ,
.crypt_gensalt and
functions are very non-portable.
.PP
The set of supported hashing methods is implementation-dependent.
.SH CONFORMING TO
The
.B crypt
function conforms to SVID, X/OPEN, and is available on BSD 4.3.
The strings returned by
.B crypt
are not required to be portable among conformant systems.
.PP
.B crypt_r
is a GNU extension.
There's also a
.B crypt_r
function on HP-UX and MKS Toolkit, but the prototypes and semantics differ.
.PP
.B crypt_gensalt
is an Openwall extension.
There's also a
.B crypt_gensalt
function on Solaris 10 and newer, but the prototypes and semantics differ.
.PP
.BR crypt_rn ,
.BR crypt_ra ,
.BR crypt_gensalt_rn ,
and
.B crypt_gensalt_ra
are Openwall extensions.
.SH HISTORY
A rotor-based
.B crypt
function appeared in Version 6 AT&T UNIX.
The "traditional"
.B crypt
first appeared in Version 7 AT&T UNIX.
.PP
The
.B crypt_r
function was introduced during glibc 2.0 development.
.SH BUGS
The return values of
.BR crypt " and " crypt_gensalt
point to static buffers that are overwritten by subsequent calls.
These functions are not thread-safe.
.RB ( crypt
on recent versions of Solaris uses thread-specific data and actually is
thread-safe.)
.PP
The strings returned by certain other implementations of
.B crypt
on error may be stored in read-only locations or only initialized once,
which makes it unsafe to always attempt to zero out the buffer normally
pointed to by the
.B crypt
return value as it would otherwise be preferable for security reasons.
The problem could be avoided with the use of
.BR crypt_r ,
.BR crypt_rn ,
or
.B crypt_ra
where the application has full control over output buffers of these functions
(and often over some of their private data as well).
Unfortunately, the functions aren't (yet?) available on platforms where
.B crypt
has this undesired property.
.PP
Applications using the thread-safe
.B crypt_r
need to allocate address space for the large (over 128 KB)
.I struct crypt_data
structure. Each thread needs a separate instance of the structure. The
.B crypt_r
interface makes it impossible to implement a hashing algorithm which
would need to keep an even larger amount of private data, without breaking
binary compatibility.
.B crypt_ra
allows for dynamically increasing the allocation size as required by the
hashing algorithm that is actually used. Unfortunately,
.B crypt_ra
is even more non-portable than
.BR crypt_r .
.PP
Multi-threaded applications or library functions which are meant to be
thread-safe should use
.BR crypt_gensalt_rn " or " crypt_gensalt_ra
rather than
.BR crypt_gensalt .
.SH SEE ALSO
.BR login (1),
.BR passwd (1),
.BR crypto (3),
.BR encrypt (3),
.BR free (3),
.BR getpass (3),
.BR getpwent (3),
.BR malloc (3),
.BR realloc (3),
.BR shadow (3),
.BR passwd (5),
.BR shadow (5),
.BR regex (7),
.BR pam (8)
.sp
Niels Provos and David Mazieres. A Future-Adaptable Password Scheme.
Proceedings of the 1999 USENIX Annual Technical Conference, June 1999.
.br
http://www.usenix.org/events/usenix99/provos.html
.sp
Robert Morris and Ken Thompson. Password Security: A Case History.
Unix Seventh Edition Manual, Volume 2, April 1978.
.br
http://plan9.bell-labs.com/7thEdMan/vol2/password

View File

@ -0,0 +1,24 @@
/*
* Written by Solar Designer <solar at openwall.com> 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 <gnu-crypt.h>
#if defined(_OW_SOURCE) || defined(__USE_OW)
#define __SKIP_GNU
#undef __SKIP_OW
#include <ow-crypt.h>
#undef __SKIP_GNU
#endif

View File

@ -0,0 +1,907 @@
/*
* The crypt_blowfish homepage is:
*
* http://www.openwall.com/crypt/
*
* This code comes from John the Ripper password cracker, with reentrant
* and crypt(3) interfaces added, but optimizations specific to password
* cracking removed.
*
* Written by Solar Designer <solar at openwall.com> in 1998-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) 1998-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.
*
* It is my intent that you should be able to use this on your system,
* as part of a software package, or anywhere else to improve security,
* ensure compatibility, or for any other purpose. I would appreciate
* it if you give credit where it is due and keep your modifications in
* the public domain as well, but I don't require that in order to let
* you place this code and any modifications you make under a license
* of your choice.
*
* This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
* "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses
* some of his ideas. The password hashing algorithm was designed by David
* Mazieres <dm at lcs.mit.edu>. For information on the level of
* compatibility for bcrypt hash prefixes other than "$2b$", please refer to
* the comments in BF_set_key() below and to the included crypt(3) man page.
*
* There's a paper on the algorithm that explains its design decisions:
*
* http://www.usenix.org/events/usenix99/provos.html
*
* Some of the tricks in BF_ROUND might be inspired by Eric Young's
* Blowfish library (I can't be sure if I would think of something if I
* hadn't seen his code).
*/
#include <string.h>
#include <errno.h>
#ifndef __set_errno
#define __set_errno(val) errno = (val)
#endif
/* Just to make sure the prototypes match the actual definitions */
#include "crypt_blowfish.h"
#ifdef __i386__
#define BF_ASM 1
#define BF_SCALE 1
#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
#define BF_ASM 0
#define BF_SCALE 1
#else
#define BF_ASM 0
#define BF_SCALE 0
#endif
typedef unsigned int BF_word;
typedef signed int BF_word_signed;
/* Number of Blowfish rounds, this is also hardcoded into a few places */
#define BF_N 16
typedef BF_word BF_key[BF_N + 2];
typedef struct {
BF_word S[4][0x100];
BF_key P;
} BF_ctx;
/*
* Magic IV for 64 Blowfish encryptions that we do at the end.
* The string is "OrpheanBeholderScryDoubt" on big-endian.
*/
static BF_word BF_magic_w[6] = {
0x4F727068, 0x65616E42, 0x65686F6C,
0x64657253, 0x63727944, 0x6F756274
};
/*
* P-box and S-box tables initialized with digits of Pi.
*/
static BF_ctx BF_init_state = {
{
{
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
}, {
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
}, {
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
}, {
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
}
}, {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b
}
};
static unsigned char BF_itoa64[64 + 1] =
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
static unsigned char BF_atoi64[0x60] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
};
#define BF_safe_atoi64(dst, src) \
{ \
tmp = (unsigned char)(src); \
if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
tmp = BF_atoi64[tmp]; \
if (tmp > 63) return -1; \
(dst) = tmp; \
}
static int BF_decode(BF_word *dst, const char *src, int size)
{
unsigned char *dptr = (unsigned char *)dst;
unsigned char *end = dptr + size;
const unsigned char *sptr = (const unsigned char *)src;
unsigned int tmp, c1, c2, c3, c4;
do {
BF_safe_atoi64(c1, *sptr++);
BF_safe_atoi64(c2, *sptr++);
*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
if (dptr >= end) break;
BF_safe_atoi64(c3, *sptr++);
*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
if (dptr >= end) break;
BF_safe_atoi64(c4, *sptr++);
*dptr++ = ((c3 & 0x03) << 6) | c4;
} while (dptr < end);
return 0;
}
static void BF_encode(char *dst, const BF_word *src, int size)
{
const unsigned char *sptr = (const unsigned char *)src;
const unsigned char *end = sptr + size;
unsigned char *dptr = (unsigned char *)dst;
unsigned int c1, c2;
do {
c1 = *sptr++;
*dptr++ = BF_itoa64[c1 >> 2];
c1 = (c1 & 0x03) << 4;
if (sptr >= end) {
*dptr++ = BF_itoa64[c1];
break;
}
c2 = *sptr++;
c1 |= c2 >> 4;
*dptr++ = BF_itoa64[c1];
c1 = (c2 & 0x0f) << 2;
if (sptr >= end) {
*dptr++ = BF_itoa64[c1];
break;
}
c2 = *sptr++;
c1 |= c2 >> 6;
*dptr++ = BF_itoa64[c1];
*dptr++ = BF_itoa64[c2 & 0x3f];
} while (sptr < end);
}
static void BF_swap(BF_word *x, int count)
{
static int endianness_check = 1;
char *is_little_endian = (char *)&endianness_check;
BF_word tmp;
if (*is_little_endian)
do {
tmp = *x;
tmp = (tmp << 16) | (tmp >> 16);
*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
} while (--count);
}
#if BF_SCALE
/* Architectures which can shift addresses left by 2 bits with no extra cost */
#define BF_ROUND(L, R, N) \
tmp1 = L & 0xFF; \
tmp2 = L >> 8; \
tmp2 &= 0xFF; \
tmp3 = L >> 16; \
tmp3 &= 0xFF; \
tmp4 = L >> 24; \
tmp1 = data.ctx.S[3][tmp1]; \
tmp2 = data.ctx.S[2][tmp2]; \
tmp3 = data.ctx.S[1][tmp3]; \
tmp3 += data.ctx.S[0][tmp4]; \
tmp3 ^= tmp2; \
R ^= data.ctx.P[N + 1]; \
tmp3 += tmp1; \
R ^= tmp3;
#else
/* Architectures with no complicated addressing modes supported */
#define BF_INDEX(S, i) \
(*((BF_word *)(((unsigned char *)S) + (i))))
#define BF_ROUND(L, R, N) \
tmp1 = L & 0xFF; \
tmp1 <<= 2; \
tmp2 = L >> 6; \
tmp2 &= 0x3FC; \
tmp3 = L >> 14; \
tmp3 &= 0x3FC; \
tmp4 = L >> 22; \
tmp4 &= 0x3FC; \
tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
tmp3 ^= tmp2; \
R ^= data.ctx.P[N + 1]; \
tmp3 += tmp1; \
R ^= tmp3;
#endif
/*
* Encrypt one block, BF_N is hardcoded here.
*/
#define BF_ENCRYPT \
L ^= data.ctx.P[0]; \
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); \
tmp4 = R; \
R = L; \
L = tmp4 ^ data.ctx.P[BF_N + 1];
#if BF_ASM
#define BF_body() \
_BF_body_r(&data.ctx);
#else
#define BF_body() \
L = R = 0; \
ptr = data.ctx.P; \
do { \
ptr += 2; \
BF_ENCRYPT; \
*(ptr - 2) = L; \
*(ptr - 1) = R; \
} while (ptr < &data.ctx.P[BF_N + 2]); \
\
ptr = data.ctx.S[0]; \
do { \
ptr += 2; \
BF_ENCRYPT; \
*(ptr - 2) = L; \
*(ptr - 1) = R; \
} while (ptr < &data.ctx.S[3][0xFF]);
#endif
static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
unsigned char flags)
{
const char *ptr = key;
unsigned int bug, i, j;
BF_word safety, sign, diff, tmp[2];
/*
* There was a sign extension bug in older revisions of this function. While
* we would have liked to simply fix the bug and move on, we have to provide
* a backwards compatibility feature (essentially the bug) for some systems and
* a safety measure for some others. The latter is needed because for certain
* multiple inputs to the buggy algorithm there exist easily found inputs to
* the correct algorithm that produce the same hash. Thus, we optionally
* deviate from the correct algorithm just enough to avoid such collisions.
* While the bug itself affected the majority of passwords containing
* characters with the 8th bit set (although only a percentage of those in a
* collision-producing way), the anti-collision safety measure affects
* only a subset of passwords containing the '\xff' character (not even all of
* those passwords, just some of them). This character is not found in valid
* UTF-8 sequences and is rarely used in popular 8-bit character encodings.
* Thus, the safety measure is unlikely to cause much annoyance, and is a
* reasonable tradeoff to use when authenticating against existing hashes that
* are not reliably known to have been computed with the correct algorithm.
*
* We use an approach that tries to minimize side-channel leaks of password
* information - that is, we mostly use fixed-cost bitwise operations instead
* of branches or table lookups. (One conditional branch based on password
* length remains. It is not part of the bug aftermath, though, and is
* difficult and possibly unreasonable to avoid given the use of C strings by
* the caller, which results in similar timing leaks anyway.)
*
* For actual implementation, we set an array index in the variable "bug"
* (0 means no bug, 1 means sign extension bug emulation) and a flag in the
* variable "safety" (bit 16 is set when the safety measure is requested).
* Valid combinations of settings are:
*
* Prefix "$2a$": bug = 0, safety = 0x10000
* Prefix "$2b$": bug = 0, safety = 0
* Prefix "$2x$": bug = 1, safety = 0
* Prefix "$2y$": bug = 0, safety = 0
*/
bug = (unsigned int)flags & 1;
safety = ((BF_word)flags & 2) << 15;
sign = diff = 0;
for (i = 0; i < BF_N + 2; i++) {
tmp[0] = tmp[1] = 0;
for (j = 0; j < 4; j++) {
tmp[0] <<= 8;
tmp[0] |= (unsigned char)*ptr; /* correct */
tmp[1] <<= 8;
tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
/*
* Sign extension in the first char has no effect - nothing to overwrite yet,
* and those extra 24 bits will be fully shifted out of the 32-bit word. For
* chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
* extension in tmp[1] occurs. Once this flag is set, it remains set.
*/
if (j)
sign |= tmp[1] & 0x80;
if (!*ptr)
ptr = key;
else
ptr++;
}
diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
expanded[i] = tmp[bug];
initial[i] = BF_init_state.P[i] ^ tmp[bug];
}
/*
* At this point, "diff" is zero iff the correct and buggy algorithms produced
* exactly the same result. If so and if "sign" is non-zero, which indicates
* that there was a non-benign sign extension, this means that we have a
* collision between the correctly computed hash for this password and a set of
* passwords that could be supplied to the buggy algorithm. Our safety measure
* is meant to protect from such many-buggy to one-correct collisions, by
* deviating from the correct algorithm in such cases. Let's check for this.
*/
diff |= diff >> 16; /* still zero iff exact match */
diff &= 0xffff; /* ditto */
diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
sign &= ~diff & safety; /* action needed? */
/*
* If we have determined that we need to deviate from the correct algorithm,
* flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
* let's stick to it now. It came out of the approach we used above, and it's
* not any worse than any other choice we could make.)
*
* It is crucial that we don't do the same to the expanded key used in the main
* Eksblowfish loop. By doing it to only one of these two, we deviate from a
* state that could be directly specified by a password to the buggy algorithm
* (and to the fully correct one as well, but that's a side-effect).
*/
initial[0] ^= sign;
}
static const unsigned char flags_by_subtype[26] =
{2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
static char *BF_crypt(const char *key, const char *setting,
char *output, int size,
BF_word min)
{
#if BF_ASM
extern void _BF_body_r(BF_ctx *ctx);
#endif
struct {
BF_ctx ctx;
BF_key expanded_key;
union {
BF_word salt[4];
BF_word output[6];
} binary;
} data;
BF_word L, R;
BF_word tmp1, tmp2, tmp3, tmp4;
BF_word *ptr;
BF_word count;
int i;
if (size < 7 + 22 + 31 + 1) {
__set_errno(ERANGE);
return NULL;
}
if (setting[0] != '$' ||
setting[1] != '2' ||
setting[2] < 'a' || setting[2] > 'z' ||
!flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
setting[3] != '$' ||
setting[4] < '0' || setting[4] > '3' ||
setting[5] < '0' || setting[5] > '9' ||
(setting[4] == '3' && setting[5] > '1') ||
setting[6] != '$') {
__set_errno(EINVAL);
return NULL;
}
count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
__set_errno(EINVAL);
return NULL;
}
BF_swap(data.binary.salt, 4);
BF_set_key(key, data.expanded_key, data.ctx.P,
flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
L = R = 0;
for (i = 0; i < BF_N + 2; i += 2) {
L ^= data.binary.salt[i & 2];
R ^= data.binary.salt[(i & 2) + 1];
BF_ENCRYPT;
data.ctx.P[i] = L;
data.ctx.P[i + 1] = R;
}
ptr = data.ctx.S[0];
do {
ptr += 4;
L ^= data.binary.salt[(BF_N + 2) & 3];
R ^= data.binary.salt[(BF_N + 3) & 3];
BF_ENCRYPT;
*(ptr - 4) = L;
*(ptr - 3) = R;
L ^= data.binary.salt[(BF_N + 4) & 3];
R ^= data.binary.salt[(BF_N + 5) & 3];
BF_ENCRYPT;
*(ptr - 2) = L;
*(ptr - 1) = R;
} while (ptr < &data.ctx.S[3][0xFF]);
do {
int done;
for (i = 0; i < BF_N + 2; i += 2) {
data.ctx.P[i] ^= data.expanded_key[i];
data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
}
done = 0;
do {
BF_body();
if (done)
break;
done = 1;
tmp1 = data.binary.salt[0];
tmp2 = data.binary.salt[1];
tmp3 = data.binary.salt[2];
tmp4 = data.binary.salt[3];
for (i = 0; i < BF_N; i += 4) {
data.ctx.P[i] ^= tmp1;
data.ctx.P[i + 1] ^= tmp2;
data.ctx.P[i + 2] ^= tmp3;
data.ctx.P[i + 3] ^= tmp4;
}
data.ctx.P[16] ^= tmp1;
data.ctx.P[17] ^= tmp2;
} while (1);
} while (--count);
for (i = 0; i < 6; i += 2) {
L = BF_magic_w[i];
R = BF_magic_w[i + 1];
count = 64;
do {
BF_ENCRYPT;
} while (--count);
data.binary.output[i] = L;
data.binary.output[i + 1] = R;
}
memcpy(output, setting, 7 + 22 - 1);
output[7 + 22 - 1] = BF_itoa64[(int)
BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
/* This has to be bug-compatible with the original implementation, so
* only encode 23 of the 24 bytes. :-) */
BF_swap(data.binary.output, 6);
BF_encode(&output[7 + 22], data.binary.output, 23);
output[7 + 22 + 31] = '\0';
return output;
}
int _crypt_output_magic(const char *setting, char *output, int size)
{
if (size < 3)
return -1;
output[0] = '*';
output[1] = '0';
output[2] = '\0';
if (setting[0] == '*' && setting[1] == '0')
output[1] = '1';
return 0;
}
/*
* Please preserve the runtime self-test. It serves two purposes at once:
*
* 1. We really can't afford the risk of producing incompatible hashes e.g.
* when there's something like gcc bug 26587 again, whereas an application or
* library integrating this code might not also integrate our external tests or
* it might not run them after every build. Even if it does, the miscompile
* might only occur on the production build, but not on a testing build (such
* as because of different optimization settings). It is painful to recover
* from incorrectly-computed hashes - merely fixing whatever broke is not
* enough. Thus, a proactive measure like this self-test is needed.
*
* 2. We don't want to leave sensitive data from our actual password hash
* computation on the stack or in registers. Previous revisions of the code
* would do explicit cleanups, but simply running the self-test after hash
* computation is more reliable.
*
* The performance cost of this quick self-test is around 0.6% at the "$2a$08"
* setting.
*/
char *_crypt_blowfish_rn(const char *key, const char *setting,
char *output, int size)
{
const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
static const char * const test_hashes[2] =
{"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */
"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */
const char *test_hash = test_hashes[0];
char *retval;
const char *p;
int save_errno, ok;
struct {
char s[7 + 22 + 1];
char o[7 + 22 + 31 + 1 + 1 + 1];
} buf;
/* Hash the supplied password */
_crypt_output_magic(setting, output, size);
retval = BF_crypt(key, setting, output, size, 16);
save_errno = errno;
/*
* Do a quick self-test. It is important that we make both calls to BF_crypt()
* from the same scope such that they likely use the same stack locations,
* which makes the second call overwrite the first call's sensitive data on the
* stack and makes it more likely that any alignment related issues would be
* detected by the self-test.
*/
memcpy(buf.s, test_setting, sizeof(buf.s));
if (retval) {
unsigned int flags = flags_by_subtype[
(unsigned int)(unsigned char)setting[2] - 'a'];
test_hash = test_hashes[flags & 1];
buf.s[2] = setting[2];
}
memset(buf.o, 0x55, sizeof(buf.o));
buf.o[sizeof(buf.o) - 1] = 0;
p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
ok = (p == buf.o &&
!memcmp(p, buf.s, 7 + 22) &&
!memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1));
{
const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
BF_key ae, ai, ye, yi;
BF_set_key(k, ae, ai, 2); /* $2a$ */
BF_set_key(k, ye, yi, 4); /* $2y$ */
ai[0] ^= 0x10000; /* undo the safety (for comparison) */
ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
!memcmp(ae, ye, sizeof(ae)) &&
!memcmp(ai, yi, sizeof(ai));
}
__set_errno(save_errno);
if (ok)
return retval;
/* Should not happen */
_crypt_output_magic(setting, output, size);
__set_errno(EINVAL); /* pretend we don't support this hash type */
return NULL;
}
char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
const char *input, int size, char *output, int output_size)
{
if (size < 16 || output_size < 7 + 22 + 1 ||
(count && (count < 4 || count > 31)) ||
prefix[0] != '$' || prefix[1] != '2' ||
(prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) {
if (output_size > 0) output[0] = '\0';
__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
return NULL;
}
if (!count) count = 5;
output[0] = '$';
output[1] = '2';
output[2] = prefix[2];
output[3] = '$';
output[4] = '0' + count / 10;
output[5] = '0' + count % 10;
output[6] = '$';
BF_encode(&output[7], (const BF_word *)input, 16);
output[7 + 22] = '\0';
return output;
}

View File

@ -0,0 +1,27 @@
/*
* Written by Solar Designer <solar at openwall.com> 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_BLOWFISH_H
#define _CRYPT_BLOWFISH_H
extern int _crypt_output_magic(const char *setting, char *output, int size);
extern char *_crypt_blowfish_rn(const char *key, const char *setting,
char *output, int size);
extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
unsigned long count,
const char *input, int size, char *output, int output_size);
#endif

View File

@ -0,0 +1,124 @@
/*
* Written by Solar Designer <solar at openwall.com> 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 <string.h>
#include <errno.h>
#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;
}

View File

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

View File

@ -0,0 +1,53 @@
--- glibc-2.1.3.orig/crypt/sysdeps/unix/Makefile 1997-03-05 00:33:59 +0000
+++ glibc-2.1.3/crypt/sysdeps/unix/Makefile 2000-06-11 03:13:41 +0000
@@ -1,4 +1,4 @@
ifeq ($(subdir),md5-crypt)
-libcrypt-routines += crypt crypt_util
-dont_distribute += crypt.c crypt_util.c
+libcrypt-routines += crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper
+dont_distribute += crypt.c crypt_util.c crypt_blowfish.c x86.S crypt_gensalt.c wrapper.c
endif
--- glibc-2.1.3.orig/crypt/sysdeps/unix/crypt-entry.c 1998-12-10 12:49:04 +0000
+++ glibc-2.1.3/crypt/sysdeps/unix/crypt-entry.c 2000-06-11 03:14:57 +0000
@@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar;
*/
char *
-__crypt_r (key, salt, data)
+__des_crypt_r (key, salt, data)
const char *key;
const char *salt;
struct crypt_data * __restrict data;
@@ -115,6 +115,7 @@ __crypt_r (key, salt, data)
_ufc_output_conversion_r (res[0], res[1], salt, data);
return data->crypt_3_buf;
}
+#if 0
weak_alias (__crypt_r, crypt_r)
char *
@@ -147,3 +148,4 @@ __fcrypt (key, salt)
return crypt (key, salt);
}
#endif
+#endif
--- glibc-2.1.3.orig/md5-crypt/Makefile 1998-07-02 22:46:47 +0000
+++ glibc-2.1.3/md5-crypt/Makefile 2000-06-11 03:12:34 +0000
@@ -21,7 +21,7 @@
#
subdir := md5-crypt
-headers := crypt.h
+headers := crypt.h gnu-crypt.h ow-crypt.h
distribute := md5.h
--- glibc-2.1.3.orig/md5-crypt/Versions 1998-07-02 22:32:07 +0000
+++ glibc-2.1.3/md5-crypt/Versions 2000-06-11 09:11:03 +0000
@@ -1,5 +1,6 @@
libcrypt {
GLIBC_2.0 {
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
+ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
}
}

View File

@ -0,0 +1,55 @@
diff -urp glibc-2.14.orig/crypt/Makefile glibc-2.14/crypt/Makefile
--- glibc-2.14.orig/crypt/Makefile 2011-05-31 04:12:33 +0000
+++ glibc-2.14/crypt/Makefile 2011-07-16 21:40:56 +0000
@@ -22,6 +22,7 @@
subdir := crypt
headers := crypt.h
+headers += gnu-crypt.h ow-crypt.h
extra-libs := libcrypt
extra-libs-others := $(extra-libs)
@@ -29,6 +30,8 @@ extra-libs-others := $(extra-libs)
libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
crypt_util
+libcrypt-routines += crypt_blowfish x86 crypt_gensalt wrapper
+
tests := cert md5c-test sha256c-test sha512c-test
distribute := ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \
diff -urp glibc-2.14.orig/crypt/Versions glibc-2.14/crypt/Versions
--- glibc-2.14.orig/crypt/Versions 2011-05-31 04:12:33 +0000
+++ glibc-2.14/crypt/Versions 2011-07-16 21:40:56 +0000
@@ -1,5 +1,6 @@
libcrypt {
GLIBC_2.0 {
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
+ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
}
}
diff -urp glibc-2.14.orig/crypt/crypt-entry.c glibc-2.14/crypt/crypt-entry.c
--- glibc-2.14.orig/crypt/crypt-entry.c 2011-05-31 04:12:33 +0000
+++ glibc-2.14/crypt/crypt-entry.c 2011-07-16 21:40:56 +0000
@@ -82,7 +82,7 @@ extern struct crypt_data _ufc_foobar;
*/
char *
-__crypt_r (key, salt, data)
+__des_crypt_r (key, salt, data)
const char *key;
const char *salt;
struct crypt_data * __restrict data;
@@ -137,6 +137,7 @@ __crypt_r (key, salt, data)
_ufc_output_conversion_r (res[0], res[1], salt, data);
return data->crypt_3_buf;
}
+#if 0
weak_alias (__crypt_r, crypt_r)
char *
@@ -177,3 +178,4 @@ __fcrypt (key, salt)
return crypt (key, salt);
}
#endif
+#endif

View File

@ -0,0 +1,52 @@
--- glibc-2.3.6.orig/crypt/Makefile 2001-07-06 04:54:45 +0000
+++ glibc-2.3.6/crypt/Makefile 2004-02-27 00:23:48 +0000
@@ -21,14 +21,14 @@
#
subdir := crypt
-headers := crypt.h
+headers := crypt.h gnu-crypt.h ow-crypt.h
distribute := md5.h
extra-libs := libcrypt
extra-libs-others := $(extra-libs)
-libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util
+libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper
tests = cert md5test md5c-test
--- glibc-2.3.6.orig/crypt/Versions 2000-03-04 00:47:30 +0000
+++ glibc-2.3.6/crypt/Versions 2004-02-27 00:25:15 +0000
@@ -1,5 +1,6 @@
libcrypt {
GLIBC_2.0 {
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
+ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
}
}
--- glibc-2.3.6.orig/crypt/crypt-entry.c 2001-07-06 05:18:49 +0000
+++ glibc-2.3.6/crypt/crypt-entry.c 2004-02-27 00:12:32 +0000
@@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar;
*/
char *
-__crypt_r (key, salt, data)
+__des_crypt_r (key, salt, data)
const char *key;
const char *salt;
struct crypt_data * __restrict data;
@@ -115,6 +115,7 @@ __crypt_r (key, salt, data)
_ufc_output_conversion_r (res[0], res[1], salt, data);
return data->crypt_3_buf;
}
+#if 0
weak_alias (__crypt_r, crypt_r)
char *
@@ -147,3 +148,4 @@ __fcrypt (key, salt)
return crypt (key, salt);
}
#endif
+#endif

Binary file not shown.

View File

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

View File

@ -0,0 +1,551 @@
/*
* Written by Solar Designer <solar at openwall.com> 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#ifndef __set_errno
#define __set_errno(val) errno = (val)
#endif
#ifdef TEST
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#ifdef TEST_THREADS
#include <pthread.h>
#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

View File

@ -0,0 +1,203 @@
/*
* 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

1
src/3rdparty/crypt/scrypt vendored Submodule

@ -0,0 +1 @@
Subproject commit d8147ba393b69df55214dfa6b4563974eab0d12b

1
src/3rdparty/fundamentals vendored Submodule

@ -0,0 +1 @@
Subproject commit 71130922450ecdab56a4072bd76aaaf02b23dd8e

View File

@ -0,0 +1,14 @@
Program Renegade.Lib.Password.Bcrypt.Test;
Uses
Renegade.Lib.Password;
Var
Password, Hash : String;
Begin
Password := 'Hashed';
Hash := PasswordHash( Password, [BCrypt] );
WriteLn(Hash);
End.

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
define('BCRYPT_COST', 12);
if( version_compare(PHP_VERSION, '7.0.0', '>=') ) {
function passwordVerify( String $password, String $hash ) {
var_dump( password_verify( $password, $hash ) );
}
} else {
function passwordVerify( $password, $hash ) {
if( !is_string($password) ) {
throw new InvalidArgumentException(sprintf('Argument 1 passed to passwordVerify() must be of the type string, %s given.', gettype($password) ) );
} elseif( !is_string($hash) ) {
throw new InvalidArgumentException(sprintf('Argument 2 passed to passwordVerify() must be of the type string, %s given.', gettype($hash) ) );
} else {
var_dump( password_verify( $password, $hash ) );
}
}
}
$hash = '$2y$12$c7pW/hNolSHA8tR7HjI1newUBfCuoK/Ov6/cXMJPt4T6IlvcOxxhC';
$password = 'Hashed';
$badPassword = 'NotHashed';
print PHP_EOL . PHP_EOL . "Password Need Rehash? Should be false. -- ";
assert(password_needs_rehash( $hash, PASSWORD_DEFAULT, ['cost' => BCRYPT_COST] ) === false, 'Should be false');
print var_export(password_needs_rehash( $hash, PASSWORD_DEFAULT, ['cost' => BCRYPT_COST] ) ) . PHP_EOL;
print "Good Password -- true\n";
passwordVerify( $password, $hash );
print "Bad Password -- false\n";
passwordVerify( $badPassword, $hash );

View File

@ -0,0 +1,38 @@
Unit Renegade.Lib.Password.BCrypt;
{$A+,H-,V-}
{$MACRO ON}
{$DEFINE BCRYPT_STRING_LEN := 64}
{$LIBRARYPATH ../3rdparty/crypt/bcrypt}
{$LIBRARYPATH /home/eric/Desktop/bcrypt}
{$OBJECTPATH .}
{$INCLUDEPATH ../3rdparty/crypt/bcrypt}
{$SMARTLINK ON}
{$PACKRECORDS c}
Interface
Uses
SysUtils, Ctypes;
Type
Str64 = Array [0..BCRYPT_STRING_LEN] of Char;
BStr = Str64;
Function bcrypt_gensalt( Workfactor : CInt; var Salt: Str64): CInt; External 'bcrypt';
Function bcrypt_hashpw( Password, Salt : Str64; var Hash : Str64): CInt; External 'bcrypt';
Function bcrypt_checkpw( Password, Hash : Str64): CInt; External 'bcrypt';
Implementation
{$linklib c }
{$link x86 }
{$link wrapper }
{$link crypt_blowfish }
{$link crypt_gensalt }
{$linklib bcrypt }
Function bcrypt_gensalt( Workfactor : Integer; var Salt: Str64): PcInt; External;
Function bcrypt_hashpw( Password, Salt : Str64; var Hash : Str64): PcInt; External;
Function bcrypt_checkpw( Password, Hash : Str64): PcInt; External;
End.

View File

@ -0,0 +1,30 @@
Unit Renegade.Lib.Password;
Interface
Uses
Renegade.Lib.Password.BCrypt;
Type
HashTypes = (BCrypt, Scrypt);
THashType = Set Of HashTypes;
Function PasswordHash( Password : String; HashType : THashType ) : String;
Implementation
Function PasswordHash( Password : String; HashType : THashType ) : String;
Var
Hash, Salt : Str64;
Success : Word;
Begin
bcrypt_gensalt( 12, Salt );
Success := bcrypt_hashpw( Password, Salt, Hash );
If Success = 0 Then
PasswordHash := Hash
Else
WriteLn( 'Couldn''t create password.' );
End;
End.

View File

@ -0,0 +1,25 @@
#include <stdio.h>
#include <libscrypt.h>
#ifdef SCRYPT_SAFE_N
#undef SCRYPT_SAFE_N
#define SCRYPT_SAFE_N 16
#endif
#define SCRYPT_PASSWORD_LEN 60
int main() {
char hash[SCRYPT_MCF_LEN], password[60];
int returnCode;
printf("\nEnter a password : ");
scanf("%s", password);
if( libscrypt_hash(hash, password, SCRYPT_N, SCRYPT_r, SCRYPT_p) > 0 ) {
printf("%s", hash);
} else {
printf("We were not able to create the hash.");
}
return returnCode;
}