Skip to content

Commit da08a76

Browse files
committed
Added a quick self-test invoked on every use.
CVS-ID: crypt_blowfish.c 1.11
1 parent 3fa91ad commit da08a76

File tree

1 file changed

+57
-3
lines changed

1 file changed

+57
-3
lines changed

crypt_blowfish.c

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* cracking removed.
55
*
66
* Written by Solar Designer <solar at openwall.com> in 1998-2002 and
7+
* placed in the public domain. Quick self-test added in 2011 and also
78
* placed in the public domain.
89
*
910
* There's absolutely no warranty.
@@ -44,6 +45,13 @@
4445
#define __CONST
4546
#endif
4647

48+
/*
49+
* Please keep this enabled. We really don't want incompatible hashes to be
50+
* produced. The performance cost of this quick self-test is around 0.6% at
51+
* the "$2a$08" setting.
52+
*/
53+
#define BF_SELF_TEST
54+
4755
#ifdef __i386__
4856
#define BF_ASM 1
4957
#define BF_SCALE 1
@@ -569,8 +577,9 @@ static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial,
569577
}
570578
}
571579

572-
char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
573-
char *output, int size)
580+
static char *BF_crypt(__CONST char *key, __CONST char *setting,
581+
char *output, int size,
582+
BF_word min)
574583
{
575584
#if BF_ASM
576585
extern void _BF_body_r(BF_ctx *ctx);
@@ -607,7 +616,7 @@ char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
607616
}
608617

609618
count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
610-
if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) {
619+
if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
611620
clean(data.binary.salt, sizeof(data.binary.salt));
612621
__set_errno(EINVAL);
613622
return NULL;
@@ -714,14 +723,59 @@ char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
714723
BF_encode(&output[7 + 22], data.binary.output, 23);
715724
output[7 + 22 + 31] = '\0';
716725

726+
#ifndef BF_SELF_TEST
717727
/* Overwrite the most obvious sensitive data we have on the stack. Note
718728
* that this does not guarantee there's no sensitive data left on the
719729
* stack and/or in registers; I'm not aware of portable code that does. */
720730
clean(&data, sizeof(data));
731+
#endif
721732

722733
return output;
723734
}
724735

736+
char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
737+
char *output, int size)
738+
{
739+
#ifdef BF_SELF_TEST
740+
__CONST char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
741+
__CONST char *test_2a =
742+
"$2a$00$abcdefghijklmnopqrstuui1D709vfamulimlGcq0qq3UvuUasvEa"
743+
"\0"
744+
"canary";
745+
__CONST char *test_2x =
746+
"$2x$00$abcdefghijklmnopqrstuuVUrPmXD6q/nVSSp7pNDhCR9071IfIRe"
747+
"\0"
748+
"canary";
749+
__CONST char *test_hash, *p;
750+
int ok;
751+
char buf[7 + 22 + 31 + 1 + 6 + 1];
752+
753+
output = BF_crypt(key, setting, output, size, 16);
754+
755+
/* Do a quick self-test. This also happens to overwrite BF_crypt()'s data. */
756+
test_hash = (setting[2] == 'x') ? test_2x : test_2a;
757+
memcpy(buf, test_hash, sizeof(buf));
758+
memset(buf, -1, sizeof(buf) - (6 + 1)); /* keep "canary" only */
759+
p = BF_crypt(test_key, test_hash, buf, sizeof(buf) - 6, 1);
760+
761+
ok = (p == buf && !memcmp(p, test_hash, sizeof(buf)));
762+
763+
/* This could reveal what hash type we were using last. Unfortunately, we
764+
* can't reliably clean the test_hash pointer. */
765+
clean(&buf, sizeof(buf));
766+
767+
if (ok)
768+
return output;
769+
770+
/* Should not happen */
771+
__set_errno(EINVAL); /* pretend we don't support this hash type */
772+
return NULL;
773+
#else
774+
#warning Self-test is disabled, please enable
775+
return BF_crypt(key, setting, output, size, 16);
776+
#endif
777+
}
778+
725779
char *_crypt_gensalt_blowfish_rn(unsigned long count,
726780
__CONST char *input, int size, char *output, int output_size)
727781
{

0 commit comments

Comments
 (0)