--- blowfish-bcrypt.c | 56 ++++++++++++++++++++++++----------------------- blowfish.h | 14 +++++++----- nettle.texinfo | 27 +++++++++++++---------- 3 files changed, 52 insertions(+), 45 deletions(-)
diff --git a/blowfish-bcrypt.c b/blowfish-bcrypt.c index c06f9e90..491aab82 100644 --- a/blowfish-bcrypt.c +++ b/blowfish-bcrypt.c @@ -76,13 +76,14 @@ static const char radix64_encode_table[64] = "0123456789";
int -blowfish_bcrypt_verify(const char *key, - const char *hashed) +blowfish_bcrypt_verify(size_t lenkey, const char *key, + size_t lenhashed, const char *hashed) { char newhash[BLOWFISH_BCRYPT_HASH_SIZE];
- return blowfish_bcrypt_hash(sizeof newhash, - newhash, key, hashed, -1, (void*)0) + return blowfish_bcrypt_hash(newhash, + lenkey, key, lenhashed, hashed, + -1, (void*)0) && !strcmp(newhash, hashed); }
@@ -159,10 +160,12 @@ static void swap32(uint32_t *x, int count) #endif }
-static void set_xkey(const char *key, bf_key expanded, bf_key initial, - unsigned bug, uint32_t safety) +static void set_xkey(size_t lenkey, const char *key, + bf_key expanded, bf_key initial, + unsigned bug, uint32_t safety) { const char *ptr = key; + size_t n = lenkey; unsigned i, j; uint32_t sign, diff, tmp[2];
@@ -219,10 +222,10 @@ static void set_xkey(const char *key, bf_key expanded, bf_key initial, */ if (j) sign |= tmp[1] & 0x80; - if (!*ptr) - ptr = key; - else + if (n--) ptr++; + else + ptr = key, n = lenkey; } diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
@@ -259,8 +262,9 @@ static void set_xkey(const char *key, bf_key expanded, bf_key initial, initial[0] ^= sign; }
-static int ibcrypt(size_t length, char *dst, - const char *key, const char *scheme, +static int ibcrypt(char *dst, + size_t lenkey, const char *key, + size_t lenscheme, const char *scheme, int minlog2rounds, int log2rounds, const uint8_t *salt) { @@ -277,12 +281,10 @@ static int ibcrypt(size_t length, char *dst, uint32_t *ptr; uint32_t count; int i; - size_t lenscheme = strlen(scheme); unsigned cscheme; unsigned bug = 0; uint32_t safety = 0; - if (length < BLOWFISH_BCRYPT_HASH_SIZE || - lenscheme < 2) + if (lenscheme < 2) return 0;
if (lenscheme >= 3 && *scheme++ != '$') @@ -336,7 +338,7 @@ static int ibcrypt(size_t length, char *dst, return 0; count = (uint32_t)1 << log2rounds;
- set_xkey(key, data.expanded_key, data.ctx.p, bug, safety); + set_xkey(lenkey, key, data.expanded_key, data.ctx.p, bug, safety); memcpy(data.ctx.s, _nettle_blowfish_initial_ctx.s, sizeof(data.ctx.s));
L = R = 0; @@ -461,12 +463,13 @@ static int ibcrypt(size_t length, char *dst, * The performance cost of this quick self-test is around 0.6% at the "$2a$08" * setting. */ -int blowfish_bcrypt_hash(size_t length, char *dst, - const char *key, const char *scheme, +int blowfish_bcrypt_hash(char *dst, + size_t lenkey, const char *key, + size_t lenscheme, const char *scheme, int log2rounds, const uint8_t *salt) { - const char *test_pw = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; - const char *test_scheme = "$2a$00$abcdefghijklmnopqrstuu"; + const char test_pw[] = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; + const char test_scheme[] = "$2a$00$abcdefghijklmnopqrstuu"; static const char * const test_hashes[2] = {"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */ "VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */ @@ -478,10 +481,9 @@ int blowfish_bcrypt_hash(size_t length, char *dst, char o[HASHOFFSET + 31 + 1 + 1 + 1]; } buf;
- if (length) - *dst = '\0'; + *dst = '\0'; /* Hash the supplied password */ - cscheme = ibcrypt(length, dst, key, scheme, 4, log2rounds, salt); + cscheme = ibcrypt(dst, lenkey, key, lenscheme, scheme, 4, log2rounds, salt);
/* * Do a quick self-test. It is important that we make both calls to ibcrypt() @@ -497,18 +499,18 @@ int blowfish_bcrypt_hash(size_t length, char *dst,
memset(buf.o, 0x55, sizeof(buf.o)); buf.o[sizeof(buf.o) - 1] = 0; - ok = ibcrypt(sizeof(buf.o) - (1 + 1), buf.o, test_pw, - buf.s, 0, -1, (void*)0); + ok = ibcrypt(buf.o, sizeof(test_pw), test_pw, + sizeof(buf.s), buf.s, 0, -1, (void*)0);
ok = (ok && !memcmp(buf.o, buf.s, HASHOFFSET) && !memcmp(buf.o + HASHOFFSET, test_hash, 31 + 1 + 1 + 1));
{ - const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"; + const char k[] = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"; bf_key ae, ai, ye, yi; - set_xkey(k, ae, ai, 0, 0x10000); /* $2a$ */ - set_xkey(k, ye, yi, 0, 0); /* $2y$ */ + set_xkey(sizeof(k), k, ae, ai, 0, 0x10000); /* $2a$ */ + set_xkey(sizeof(k), k, ye, yi, 0, 0); /* $2y$ */ ai[0] ^= 0x10000; /* undo the safety (for comparison) */ ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 && !memcmp(ae, ye, sizeof(ae)) && diff --git a/blowfish.h b/blowfish.h index af48e20f..1c5bdbe1 100644 --- a/blowfish.h +++ b/blowfish.h @@ -86,16 +86,18 @@ void blowfish_decrypt(const struct blowfish_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src); + +/* dst parameter must point to a buffer of minimally + * BLOWFISH_BCRYPT_HASH_SIZE bytes */ int -blowfish_bcrypt_hash(size_t length, - char *dst, - const char *key, - const char *scheme, +blowfish_bcrypt_hash(char *dst, + size_t lenkey, const char *key, + size_t lenscheme, const char *scheme, int log2rounds, const uint8_t *salt); int -blowfish_bcrypt_verify(const char *key, - const char *hashed); +blowfish_bcrypt_verify(size_t lenkey, const char *key, + size_t lenhashed, const char *hashed);
#ifdef __cplusplus } diff --git a/nettle.texinfo b/nettle.texinfo index 75e18b58..2269e11d 100644 --- a/nettle.texinfo +++ b/nettle.texinfo @@ -1513,7 +1513,7 @@ in any other way. Analogous to @code{blowfish_encrypt} @end deftypefun
-@deftypefun int blowfish_bcrypt_hash (size_t @var{length}, char *@var{dst}, const char *@var{key}, const char *@var{scheme}, int @var{log2rounds}, const uint8_t *@var{salt}) +@deftypefun int blowfish_bcrypt_hash (char *@var{dst}, size_t @var{lenkey}, const char *@var{key}, size_t @var{lenscheme}, const char *@var{scheme}, int @var{log2rounds}, const uint8_t *@var{salt}) Compute the bcrypt password hash. The function will return @code{0} if the hash cannot be computed due to invalid input. @@ -1522,13 +1522,13 @@ in the array pointed to by @var{dst}. The hash is computed based on the chosen @var{scheme}, number of rounds @var{log2rounds} and specified @var{salt}.
-@var{length} must be at least @code{BLOWFISH_BCRYPT_HASH_SIZE}. +@var{dst} must point to a character array of at least + @code{BLOWFISH_BCRYPT_HASH_SIZE} bytes.
-@var{dst} must point to a character array of the specified @var{length}. +@var{key} contains the plaintext password string of size @var{lenkey}.
-@var{key} contains the zero terminated plaintext password string. - -@var{scheme} contains either just the chosen scheme (valid schemes +@var{scheme} is of size @var{lenscheme} and contains either just the +chosen scheme (valid schemes are: @code{2a}, @code{2b}, @code{2x} or @code{2y}), or (the prefix of) an existing hashed password (typically @code{$2b$10$...}).
@@ -1543,26 +1543,28 @@ the salt will be extracted from @var{scheme}. Sample code to generate a bcrypt hash: @example char cleartxtpassword[] = "ExamplePassword"; +char scheme[] = "2b"; uint8_t salt[BLOWFISH_BCRYPT_BINSALT_SIZE]; @dots{} /* Make sure that salt is filled with random bytes */ @dots{} char hashedresult[BLOWFISH_BCRYPT_HASH_SIZE]; -int result = blowfish_bcrypt(sizeof(hashedresult), hashedresult, - cleartxtpassword, "2b", 10, salt); +int result = blowfish_bcrypt(hashedresult, + sizeof(cleartxtpassword), cleartxtpassword, + sizeof(scheme), scheme, 10, salt); if (result) printf("%s\n", hashedresult); @end example @end deftypefun
-@deftypefun int blowfish_bcrypt_verify (const char *@var{key}, const char *@var{hashed}) +@deftypefun int blowfish_bcrypt_verify (size_t @var{lenkey}, const char *@var{key}, size_t @var{lenhashed}, const char *@var{hashed}) Verifies the bcrypt password hash against the supplied plaintext password. The function will return @code{0} if the password does not match. The function will return @code{1} if the password matches.
-@var{key} contains the zero terminated plaintext password string. +@var{key} contains the plaintext password string of size @var{lenkey}.
-@var{hashed} contains the zero terminated hashed string to compare with. +@var{hashed} contains the hashed string of size @var{lenhashed} to compare with.
Sample code to verify a bcrypt hash: @example @@ -1573,7 +1575,8 @@ char existinghashed[] = "$" /* separator */ "1b2lPgo4XumibnJGN3r3sO" /* base64 encoded 16-byte salt */ "u7wE7xNfYDKlAxZffJDCJdVfFTAyevu"; /* Hashedpart */ -if (blowfish_bcrypt_verify(cleartxtpassword, existinghashed)) +if (blowfish_bcrypt_verify(sizeof(cleartxtpassword), cleartxtpassword, + sizeof(existinghashed), existinghashed)) printf("Password is correct."); else printf("Password is incorrect.");