-diff -urN glibc-2.1.91.orig/crypt/Makefile glibc-2.1.91/crypt/Makefile
---- glibc-2.1.91.orig/crypt/Makefile Wed Jun 14 05:49:02 2000
-+++ glibc-2.1.91/crypt/Makefile Sat Jul 15 00:58:39 2000
-@@ -26,7 +26,7 @@
- extra-libs := libcrypt
- extra-libs-others := $(extra-libs)
-
--libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
-+libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt arc4random bcrypt blowfish crypt \
- crypt_util
-
- tests := cert md5c-test sha256c-test sha512c-test
-diff -urN glibc-2.1.91.orig/crypt/arc4random.c glibc-2.1.91/crypt/arc4random.c
---- glibc-2.1.91.orig/crypt/arc4random.c Thu Jan 1 01:00:00 1970
-+++ glibc-2.1.91/crypt/arc4random.c Sat Jul 15 00:56:30 2000
-@@ -0,0 +1,174 @@
+Index: crypt/crypt_blowfish.c
+===================================================================
+--- /dev/null
++++ crypt/crypt_blowfish.c
+@@ -0,0 +1,743 @@
+/*
-+ * Arc4 random number generator for OpenBSD.
-+ * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
++ * This code comes from John the Ripper password cracker, with reentrant
++ * and crypt(3) interfaces added, but optimizations specific to password
++ * cracking removed.
+ *
-+ * Modification and redistribution in source and binary forms is
-+ * permitted provided that due credit is given to the author and the
-+ * OpenBSD project (for instance by leaving this copyright notice
-+ * intact).
-+ */
-+
-+/*
-+ * This code is derived from section 17.1 of Applied Cryptography,
-+ * second edition, which describes a stream cipher allegedly
-+ * compatible with RSA Labs "RC4" cipher (the actual description of
-+ * which is a trade secret). The same algorithm is used as a stream
-+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
++ * Written by Solar Designer <solar at openwall.com> in 1998-2002 and
++ * placed in the public domain.
+ *
-+ * Here the stream cipher has been modified always to include the time
-+ * when initializing the state. That makes it impossible to
-+ * regenerate the same random sequence twice, so this can't be used
-+ * for encryption, but will generate good random numbers.
++ * There's absolutely no warranty.
+ *
-+ * RC4 is a registered trademark of RSA Laboratories.
-+ */
-+
-+#include <fcntl.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <sys/time.h>
-+
-+#ifdef __GNUC__
-+#define inline __inline
-+#else /* !__GNUC__ */
-+#define inline
-+#endif /* !__GNUC__ */
-+
-+struct arc4_stream {
-+ u_int8_t i;
-+ u_int8_t j;
-+ u_int8_t s[256];
-+};
-+
-+int rs_initialized;
-+static struct arc4_stream rs;
-+
-+static inline void
-+arc4_init(as)
-+ struct arc4_stream *as;
-+{
-+ int n;
-+
-+ for (n = 0; n < 256; n++)
-+ as->s[n] = n;
-+ as->i = 0;
-+ as->j = 0;
-+}
-+
-+static inline void
-+arc4_addrandom(as, dat, datlen)
-+ struct arc4_stream *as;
-+ u_char *dat;
-+ int datlen;
-+{
-+ int n;
-+ u_int8_t si;
-+
-+ as->i--;
-+ for (n = 0; n < 256; n++) {
-+ as->i = (as->i + 1);
-+ si = as->s[as->i];
-+ as->j = (as->j + si + dat[n % datlen]);
-+ as->s[as->i] = as->s[as->j];
-+ as->s[as->j] = si;
-+ }
-+}
-+
-+static void
-+arc4_stir(as)
-+ struct arc4_stream *as;
-+{
-+ int fd;
-+ struct {
-+ struct timeval tv;
-+ u_int8_t rnd[128 - sizeof(struct timeval)];
-+ } rdat;
-+
-+ gettimeofday(&rdat.tv, NULL);
-+ fd = open("/dev/random", O_RDONLY);
-+ if (fd >= 0) {
-+ read(fd, rdat.rnd, sizeof(rdat.rnd));
-+ close(fd);
-+ }
-+ /* fd < 0? Ah, what the heck. We'll just take whatever was on the
-+ * stack... */
-+
-+ arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
-+}
-+
-+static inline u_int8_t
-+arc4_getbyte(as)
-+ struct arc4_stream *as;
-+{
-+ u_int8_t si, sj;
-+
-+ as->i = (as->i + 1);
-+ si = as->s[as->i];
-+ as->j = (as->j + si);
-+ sj = as->s[as->j];
-+ as->s[as->i] = sj;
-+ as->s[as->j] = si;
-+ return (as->s[(si + sj) & 0xff]);
-+}
-+
-+static inline u_int32_t
-+arc4_getword(as)
-+ struct arc4_stream *as;
-+{
-+ u_int32_t val;
-+ val = arc4_getbyte(as) << 24;
-+ val |= arc4_getbyte(as) << 16;
-+ val |= arc4_getbyte(as) << 8;
-+ val |= arc4_getbyte(as);
-+ return val;
-+}
-+
-+void
-+arc4random_stir()
-+{
-+ if (!rs_initialized) {
-+ arc4_init(&rs);
-+ rs_initialized = 1;
-+ }
-+ arc4_stir(&rs);
-+}
-+
-+void
-+arc4random_addrandom(dat, datlen)
-+ u_char *dat;
-+ int datlen;
-+{
-+ if (!rs_initialized)
-+ arc4random_stir();
-+ arc4_addrandom(&rs, dat, datlen);
-+}
-+
-+u_int32_t
-+arc4random()
-+{
-+ if (!rs_initialized)
-+ arc4random_stir();
-+ return arc4_getword(&rs);
-+}
-+
-+#if 0
-+/*-------- Test code for i386 --------*/
-+#include <stdio.h>
-+#include <machine/pctr.h>
-+int
-+main(int argc, char **argv)
-+{
-+ const int iter = 1000000;
-+ int i;
-+ pctrval v;
-+
-+ v = rdtsc();
-+ for (i = 0; i < iter; i++)
-+ arc4random();
-+ v = rdtsc() - v;
-+ v /= iter;
-+
-+ printf("%qd cycles\n", v);
-+}
-+#endif
-diff -urN glibc-2.1.91.orig/crypt/bcrypt.c glibc-2.1.91/crypt/bcrypt.c
---- glibc-2.1.91.orig/crypt/bcrypt.c Thu Jan 1 01:00:00 1970
-+++ glibc-2.1.91/crypt/bcrypt.c Sat Jul 15 00:56:30 2000
-@@ -0,0 +1,360 @@
-+/*
-+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
-+ * All rights reserved.
++ * It is my intent that you should be able to use this on your system,
++ * as a 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.
+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * 3. All advertising materials mentioning features or use of this software
-+ * must display the following acknowledgement:
-+ * This product includes software developed by Niels Provos.
-+ * 4. The name of the author may not be used to endorse or promote products
-+ * derived from this software without specific prior written permission.
++ * This implementation is compatible with OpenBSD bcrypt.c (version 2a)
++ * by Niels Provos <provos at citi.umich.edu>, and uses some of his
++ * ideas. The password hashing algorithm was designed by David Mazieres
++ * <dm at lcs.mit.edu>.
+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+/* This password hashing algorithm was designed by David Mazieres
-+ * <dm@lcs.mit.edu> and works as follows:
++ * There's a paper on the algorithm that explains its design decisions:
+ *
-+ * 1. state := InitState ()
-+ * 2. state := ExpandKey (state, salt, password) 3.
-+ * REPEAT rounds:
-+ * state := ExpandKey (state, 0, salt)
-+ * state := ExpandKey(state, 0, password)
-+ * 4. ctext := "OrpheanBeholderScryDoubt"
-+ * 5. REPEAT 64:
-+ * ctext := Encrypt_ECB (state, ctext);
-+ * 6. RETURN Concatenate (salt, ctext);
++ * 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).
+ */
+
-+#if 0
-+#include <stdio.h>
-+#endif
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <sys/types.h>
+#include <string.h>
-+#include <pwd.h>
-+#include "blf.h"
-+
-+/* This implementation is adaptable to current computing power.
-+ * You can have up to 2^31 rounds which should be enough for some
-+ * time to come.
-+ */
-+
-+#define BCRYPT_VERSION '2'
-+#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
-+#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
-+#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
-+
-+char *bcrypt_gensalt __P((u_int8_t));
-+
-+static void encode_salt __P((char *, u_int8_t *, u_int16_t, u_int8_t));
-+static void encode_base64 __P((u_int8_t *, u_int8_t *, u_int16_t));
-+static void decode_base64 __P((u_int8_t *, u_int16_t, u_int8_t *));
-+
-+static char encrypted[128];
-+static char gsalt[BCRYPT_MAXSALT * 4 / 3 + 1];
-+static char error[] = ":";
-+
-+const static u_int8_t Base64Code[] =
-+"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-+
-+const static u_int8_t index_64[128] =
-+{
-+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-+ 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
-+ 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
-+ 255, 255, 255, 255, 255, 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,
-+ 255, 255, 255, 255, 255, 255, 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, 255, 255, 255, 255, 255
-+};
-+#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
-+
-+#ifdef __STDC__
-+static void
-+decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data)
-+#else
-+static void
-+decode_base64(buffer, len, data)
-+ u_int8_t *buffer;
-+ u_int16_t len;
-+ u_int8_t *data;
-+#endif
-+{
-+ u_int8_t *bp = buffer;
-+ u_int8_t *p = data;
-+ u_int8_t c1, c2, c3, c4;
-+ while (bp < buffer + len) {
-+ c1 = CHAR64(*p);
-+ c2 = CHAR64(*(p + 1));
-+
-+ /* Invalid data */
-+ if (c1 == 255 || c2 == 255)
-+ break;
-+
-+ *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
-+ if (bp >= buffer + len)
-+ break;
-+
-+ c3 = CHAR64(*(p + 2));
-+ if (c3 == 255)
-+ break;
-+
-+ *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
-+ if (bp >= buffer + len)
-+ break;
+
-+ c4 = CHAR64(*(p + 3));
-+ if (c4 == 255)
-+ break;
-+ *bp++ = ((c3 & 0x03) << 6) | c4;
-+
-+ p += 4;
-+ }
-+}
-+
-+#ifdef __STDC__
-+static void
-+encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
-+#else
-+static void
-+encode_salt(salt, csalt, clen, logr)
-+ char *salt;
-+ u_int8_t *csalt;
-+ u_int16_t clen;
-+ u_int8_t logr;
++#include <errno.h>
++#ifndef __set_errno
++#define __set_errno(val) errno = (val)
+#endif
-+{
-+ salt[0] = '$';
-+ salt[1] = BCRYPT_VERSION;
-+ salt[2] = 'a';
-+ salt[3] = '$';
-+
-+ snprintf(salt + 4, 4, "%2.2u$", logr);
-+
-+ encode_base64((u_int8_t *) salt + 7, csalt, clen);
-+}
-+/* Generates a salt for this version of crypt.
-+ Since versions may change. Keeping this here
-+ seems sensible.
-+ */
+
-+#ifdef __STDC__
-+char *
-+bcrypt_gensalt(u_int8_t log_rounds)
++#undef __CONST
++#ifdef __GNUC__
++#define __CONST __const
+#else
-+char *
-+bcrypt_gensalt(log_rounds)
-+ u_int8_t log_rounds;
++#define __CONST
+#endif
-+{
-+ u_int8_t csalt[BCRYPT_MAXSALT];
-+ u_int16_t i;
-+ u_int32_t seed = 0;
-+
-+ for (i = 0; i < BCRYPT_MAXSALT; i++) {
-+ if (i % 4 == 0)
-+ seed = arc4random();
-+ csalt[i] = seed & 0xff;
-+ seed = seed >> 8;
-+ }
-+
-+ if (log_rounds < 4)
-+ log_rounds = 4;
-+
-+ encode_salt(gsalt, csalt, BCRYPT_MAXSALT, log_rounds);
-+ return gsalt;
-+}
-+/* We handle $Vers$log2(NumRounds)$salt+passwd$
-+ i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
-+
-+char *
-+bcrypt(key, salt)
-+ const char *key;
-+ const char *salt;
-+{
-+ blf_ctx state;
-+ u_int32_t rounds, i, k;
-+ u_int16_t j;
-+ u_int8_t key_len, salt_len, logr, minor;
-+ u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
-+ u_int8_t csalt[BCRYPT_MAXSALT];
-+ u_int32_t cdata[BCRYPT_BLOCKS];
-+
-+ /* Discard "$" identifier */
-+ salt++;
-+
-+ if (*salt > BCRYPT_VERSION) {
-+ /* How do I handle errors ? Return ':' */
-+ return error;
-+ }
-+
-+ /* Check for minor versions */
-+ if (salt[1] != '$') {
-+ switch (salt[1]) {
-+ case 'a':
-+ /* 'ab' should not yield the same as 'abab' */
-+ minor = salt[1];
-+ salt++;
-+ break;
-+ default:
-+ return error;
-+ }
-+ } else
-+ minor = 0;
-+
-+ /* Discard version + "$" identifier */
-+ salt += 2;
-+
-+ if (salt[2] != '$')
-+ /* Out of sync with passwd entry */
-+ return error;
-+
-+ /* Computer power doesnt increase linear, 2^x should be fine */
-+ if ((rounds = (u_int32_t) 1 << (logr = atoi(salt))) < BCRYPT_MINROUNDS)
-+ return error;
+
-+ /* Discard num rounds + "$" identifier */
-+ salt += 3;
-+
-+ /* We dont want the base64 salt but the raw data */
-+ decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
-+ salt_len = BCRYPT_MAXSALT;
-+ key_len = strlen(key) + (minor >= 'a' ? 1 : 0);
-+
-+ /* Setting up S-Boxes and Subkeys */
-+ Blowfish_initstate(&state);
-+ Blowfish_expandstate(&state, csalt, salt_len,
-+ (u_int8_t *) key, key_len);
-+ for (k = 0; k < rounds; k++) {
-+ Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
-+ Blowfish_expand0state(&state, csalt, salt_len);
-+ }
-+
-+ /* This can be precomputed later */
-+ j = 0;
-+ for (i = 0; i < BCRYPT_BLOCKS; i++)
-+ cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
-+
-+ /* Now do the encryption */
-+ for (k = 0; k < 64; k++)
-+ blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
-+
-+ for (i = 0; i < BCRYPT_BLOCKS; i++) {
-+ ciphertext[4 * i + 3] = cdata[i] & 0xff;
-+ cdata[i] = cdata[i] >> 8;
-+ ciphertext[4 * i + 2] = cdata[i] & 0xff;
-+ cdata[i] = cdata[i] >> 8;
-+ ciphertext[4 * i + 1] = cdata[i] & 0xff;
-+ cdata[i] = cdata[i] >> 8;
-+ ciphertext[4 * i + 0] = cdata[i] & 0xff;
-+ }
-+
-+
-+ i = 0;
-+ encrypted[i++] = '$';
-+ encrypted[i++] = BCRYPT_VERSION;
-+ if (minor)
-+ encrypted[i++] = minor;
-+ encrypted[i++] = '$';
-+
-+ snprintf(encrypted + i, 4, "%2.2u$", logr);
-+
-+ encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
-+ encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
-+ 4 * BCRYPT_BLOCKS - 1);
-+ return encrypted;
-+}
-+
-+#ifdef __STDC__
-+static void
-+encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
++#ifdef __i386__
++#define BF_ASM 0 /* original OW patch has 1 */
++#define BF_SCALE 1
++#elif defined(__alpha__) || defined(__hppa__) || defined(__x86_64__)
++#define BF_ASM 0
++#define BF_SCALE 1
+#else
-+static void
-+encode_base64(buffer, data, len)
-+ u_int8_t *buffer;
-+ u_int8_t *data;
-+ u_int16_t len;
++#define BF_ASM 0
++#define BF_SCALE 0
+#endif
-+{
-+ u_int8_t *bp = buffer;
-+ u_int8_t *p = data;
-+ u_int8_t c1, c2;
-+ while (p < data + len) {
-+ c1 = *p++;
-+ *bp++ = Base64Code[(c1 >> 2)];
-+ c1 = (c1 & 0x03) << 4;
-+ if (p >= data + len) {
-+ *bp++ = Base64Code[c1];
-+ break;
-+ }
-+ c2 = *p++;
-+ c1 |= (c2 >> 4) & 0x0f;
-+ *bp++ = Base64Code[c1];
-+ c1 = (c2 & 0x0f) << 2;
-+ if (p >= data + len) {
-+ *bp++ = Base64Code[c1];
-+ break;
-+ }
-+ c2 = *p++;
-+ c1 |= (c2 >> 6) & 0x03;
-+ *bp++ = Base64Code[c1];
-+ *bp++ = Base64Code[c2 & 0x3f];
-+ }
-+ *bp = '\0';
-+}
-+#if 0
-+void
-+main()
-+{
-+ char blubber[73];
-+ char salt[100];
-+ char *p;
-+ salt[0] = '$';
-+ salt[1] = BCRYPT_VERSION;
-+ salt[2] = '$';
-+
-+ snprintf(salt + 3, 4, "%2.2u$", 5);
-+
-+ printf("24 bytes of salt: ");
-+ fgets(salt + 6, 94, stdin);
-+ salt[99] = 0;
-+ printf("72 bytes of password: ");
-+ fpurge(stdin);
-+ fgets(blubber, 73, stdin);
-+ blubber[72] = 0;
-+
-+ p = crypt(blubber, salt);
-+ printf("Passwd entry: %s\n\n", p);
-+
-+ p = bcrypt_gensalt(5);
-+ printf("Generated salt: %s\n", p);
-+ p = crypt(blubber, p);
-+ printf("Passwd entry: %s\n", p);
-+}
-+#endif
-diff -urN glibc-2.1.91.orig/crypt/blf.h glibc-2.1.91/crypt/blf.h
---- glibc-2.1.91.orig/crypt/blf.h Thu Jan 1 01:00:00 1970
-+++ glibc-2.1.91/crypt/blf.h Sat Jul 15 00:56:30 2000
-@@ -0,0 +1,80 @@
-+/*
-+ * Blowfish - a fast block cipher designed by Bruce Schneier
-+ *
-+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * 3. All advertising materials mentioning features or use of this software
-+ * must display the following acknowledgement:
-+ * This product includes software developed by Niels Provos.
-+ * 4. The name of the author may not be used to endorse or promote products
-+ * derived from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ */
-+
-+#ifndef _BLF_H_
-+#define _BLF_H_
+
-+/* Schneier states the maximum key length to be 56 bytes.
-+ * The way how the subkeys are initalized by the key up
-+ * to (N+2)*4 i.e. 72 bytes are utilized.
-+ * Warning: For normal blowfish encryption only 56 bytes
-+ * of the key affect all cipherbits.
-+ */
-+
-+#define BLF_N 16 /* Number of Subkeys */
-+#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
-+
-+/* Blowfish context */
-+typedef struct BlowfishContext {
-+ u_int32_t S[4][256]; /* S-Boxes */
-+ u_int32_t P[BLF_N + 2]; /* Subkeys */
-+} blf_ctx;
-+
-+/* Raw access to customized Blowfish
-+ * blf_key is just:
-+ * Blowfish_initstate( state )
-+ * Blowfish_expand0state( state, key, keylen )
-+ */
++typedef unsigned int BF_word;
+
-+void Blowfish_encipher __P((blf_ctx *, u_int32_t *, u_int32_t *));
-+void Blowfish_decipher __P((blf_ctx *, u_int32_t *, u_int32_t *));
-+void Blowfish_initstate __P((blf_ctx *));
-+void Blowfish_expand0state __P((blf_ctx *, const u_int8_t *, u_int16_t));
-+void Blowfish_expandstate
-+ __P((blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t));
++/* Number of Blowfish rounds, this is also hardcoded into a few places */
++#define BF_N 16
+
-+/* Standard Blowfish */
++typedef BF_word BF_key[BF_N + 2];
+
-+void blf_key __P((blf_ctx *, const u_int8_t *, u_int16_t));
-+void blf_enc __P((blf_ctx *, u_int32_t *, u_int16_t));
-+void blf_dec __P((blf_ctx *, u_int32_t *, u_int16_t));
++typedef struct {
++ BF_word S[4][0x100];
++ BF_key P;
++} BF_ctx;
+
-+void blf_ecb_encrypt __P((blf_ctx *, u_int8_t *, u_int32_t));
-+void blf_ecb_decrypt __P((blf_ctx *, u_int8_t *, u_int32_t));
-+
-+void blf_cbc_encrypt __P((blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t));
-+void blf_cbc_decrypt __P((blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t));
-+
-+/* Converts u_int8_t to u_int32_t */
-+u_int32_t Blowfish_stream2word __P((const u_int8_t *, u_int16_t , u_int16_t *));
-+
-+#endif
-diff -urN glibc-2.1.91.orig/crypt/blowfish.c glibc-2.1.91/crypt/blowfish.c
---- glibc-2.1.91.orig/crypt/blowfish.c Thu Jan 1 01:00:00 1970
-+++ glibc-2.1.91/crypt/blowfish.c Sat Jul 15 00:56:30 2000
-@@ -0,0 +1,773 @@
+/*
-+ * Blowfish block cipher for OpenBSD
-+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
-+ * All rights reserved.
-+ *
-+ * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in the
-+ * documentation and/or other materials provided with the distribution.
-+ * 3. All advertising materials mentioning features or use of this software
-+ * must display the following acknowledgement:
-+ * This product includes software developed by Niels Provos.
-+ * 4. The name of the author may not be used to endorse or promote products
-+ * derived from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ * 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
++};
+
+/*
-+ * This code is derived from section 14.3 and the given source
-+ * in section V of Applied Cryptography, second edition.
-+ * Blowfish is an unpatented fast block cipher designed by
-+ * Bruce Schneier.
++ * P-box and S-box tables initialized with digits of Pi.
+ */
-+
-+#if 0
-+#include <stdio.h> /* used for debugging */
-+#include <string.h>
-+#endif
-+
-+#include <sys/types.h>
-+#include "blf.h"
-+
-+#undef inline
-+#ifdef __GNUC__
-+#define inline __inline
-+#else /* !__GNUC__ */
-+#define inline
-+#endif /* !__GNUC__ */
-+
-+/* Function for Feistel Networks */
-+
-+#define F(bc, x) ((((bc)->S[0][((x) & 0xFF000000) >> 24] \
-+ + (bc)->S[1][((x) &0xFF0000 ) >> 16]) \
-+ ^ (bc)->S[2][((x) & 0xFF00) >> 8]) \
-+ + (bc)->S[3][(x) & 0x00FF])
-+
-+#define BLFRND(bc,i,j,n) (i ^= F(bc,j) ^ (bc)->P[n])
-+
-+void
-+Blowfish_encipher(c, xl, xr)
-+ blf_ctx *c;
-+ u_int32_t *xl;
-+ u_int32_t *xr;
-+{
-+ u_int32_t Xl;
-+ u_int32_t Xr;
-+
-+ Xl = *xl;
-+ Xr = *xr;
-+
-+ Xl ^= c->P[0];
-+ BLFRND(c, Xr, Xl, 1); BLFRND(c, Xl, Xr, 2);
-+ BLFRND(c, Xr, Xl, 3); BLFRND(c, Xl, Xr, 4);
-+ BLFRND(c, Xr, Xl, 5); BLFRND(c, Xl, Xr, 6);
-+ BLFRND(c, Xr, Xl, 7); BLFRND(c, Xl, Xr, 8);
-+ BLFRND(c, Xr, Xl, 9); BLFRND(c, Xl, Xr, 10);
-+ BLFRND(c, Xr, Xl, 11); BLFRND(c, Xl, Xr, 12);
-+ BLFRND(c, Xr, Xl, 13); BLFRND(c, Xl, Xr, 14);
-+ BLFRND(c, Xr, Xl, 15); BLFRND(c, Xl, Xr, 16);
-+
-+ *xl = Xr ^ c->P[17];
-+ *xr = Xl;
-+}
-+
-+void
-+Blowfish_decipher(c, xl, xr)
-+ blf_ctx *c;
-+ u_int32_t *xl;
-+ u_int32_t *xr;
-+{
-+ u_int32_t Xl;
-+ u_int32_t Xr;
-+
-+ Xl = *xl;
-+ Xr = *xr;
-+
-+ Xl ^= c->P[17];
-+ BLFRND(c, Xr, Xl, 16); BLFRND(c, Xl, Xr, 15);
-+ BLFRND(c, Xr, Xl, 14); BLFRND(c, Xl, Xr, 13);
-+ BLFRND(c, Xr, Xl, 12); BLFRND(c, Xl, Xr, 11);
-+ BLFRND(c, Xr, Xl, 10); BLFRND(c, Xl, Xr, 9);
-+ BLFRND(c, Xr, Xl, 8); BLFRND(c, Xl, Xr, 7);
-+ BLFRND(c, Xr, Xl, 6); BLFRND(c, Xl, Xr, 5);
-+ BLFRND(c, Xr, Xl, 4); BLFRND(c, Xl, Xr, 3);
-+ BLFRND(c, Xr, Xl, 2); BLFRND(c, Xl, Xr, 1);
-+
-+ *xl = Xr ^ c->P[0];
-+ *xr = Xl;
-+}
-+
-+void
-+Blowfish_initstate(c)
-+ blf_ctx *c;
-+{
-+
-+/* P-box and S-box tables initialized with digits of Pi */
-+
-+ const blf_ctx initstate =
-+
-+ { {
++static BF_ctx BF_init_state = {
++ {
+ {
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
-+ {
++ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
++ }, {
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
-+ {
++ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
++ }, {
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
-+ {
++ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
++ }, {
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
-+ },
-+ {
++ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
++ }
++ }, {
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b
-+ } };
++ }
++};
+
-+ *c = initstate;
++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
++};
+
-+#ifdef __STDC__
-+u_int32_t
-+Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes, u_int16_t *current)
-+#else
-+u_int32_t
-+Blowfish_stream2word(data, databytes, current)
-+ const u_int8_t *data;
-+ u_int16_t databytes;
-+ u_int16_t *current;
-+#endif
++/*
++ * This may be optimized out if built with function inlining and no BF_ASM.
++ */
++static void clean(void *data, int size)
+{
-+ u_int8_t i;
-+ u_int16_t j;
-+ u_int32_t temp;
-+
-+ temp = 0x00000000;
-+ j = *current;
-+
-+ for (i = 0; i < 4; i++, j++) {
-+ if (j >= databytes)
-+ j = 0;
-+ temp = (temp << 8) | data[j];
-+ }
++#if BF_ASM
++ extern void _BF_clean(void *data);
++#endif
++ memset(data, 0, size);
++#if BF_ASM
++ _BF_clean(data);
++#endif
++}
+
-+ *current = j;
-+ return temp;
++#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; \
+}
+
-+#if __STDC__
-+void
-+Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes)
-+#else
-+void
-+Blowfish_expand0state(c, key, keybytes)
-+ blf_ctx *c;
-+ const u_int8_t *key;
-+ u_int16_t keybytes;
-+#endif
++static int BF_decode(BF_word *dst, __CONST char *src, int size)
+{
-+ u_int16_t i;
-+ u_int16_t j;
-+ u_int16_t k;
-+ u_int32_t temp;
-+ u_int32_t datal;
-+ u_int32_t datar;
-+
-+ j = 0;
-+ for (i = 0; i < BLF_N + 2; i++) {
-+ /* Extract 4 int8 to 1 int32 from keystream */
-+ temp = Blowfish_stream2word(key, keybytes, &j);
-+ c->P[i] = c->P[i] ^ temp;
-+ }
-+
-+ j = 0;
-+ datal = 0x00000000;
-+ datar = 0x00000000;
-+ for (i = 0; i < BLF_N + 2; i += 2) {
-+ Blowfish_encipher(c, &datal, &datar);
-+
-+ c->P[i] = datal;
-+ c->P[i + 1] = datar;
-+ }
-+
-+ for (i = 0; i < 4; i++) {
-+ for (k = 0; k < 256; k += 2) {
-+ Blowfish_encipher(c, &datal, &datar);
-+
-+ c->S[i][k] = datal;
-+ c->S[i][k + 1] = datar;
-+ }
-+ }
++ unsigned char *dptr = (unsigned char *)dst;
++ unsigned char *end = dptr + size;
++ unsigned char *sptr = (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;
+}
+
-+
-+#if __STDC__
-+void
-+Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes,
-+ const u_int8_t *key, u_int16_t keybytes)
-+#else
-+void
-+Blowfish_expandstate(c, data, databytes, key, keybytes)
-+ blf_ctx *c;
-+ const u_int8_t *data;
-+ u_int16_t databytes;
-+ const u_int8_t *key;
-+ u_int16_t keybytes;
-+#endif
++static void BF_encode(char *dst, __CONST BF_word *src, int size)
+{
-+ u_int16_t i;
-+ u_int16_t j;
-+ u_int16_t k;
-+ u_int32_t temp;
-+ u_int32_t datal;
-+ u_int32_t datar;
-+
-+ j = 0;
-+ for (i = 0; i < BLF_N + 2; i++) {
-+ /* Extract 4 int8 to 1 int32 from keystream */
-+ temp = Blowfish_stream2word(key, keybytes, &j);
-+ c->P[i] = c->P[i] ^ temp;
-+ }
-+
-+ j = 0;
-+ datal = 0x00000000;
-+ datar = 0x00000000;
-+ for (i = 0; i < BLF_N + 2; i += 2) {
-+ datal ^= Blowfish_stream2word(data, databytes, &j);
-+ datar ^= Blowfish_stream2word(data, databytes, &j);
-+ Blowfish_encipher(c, &datal, &datar);
-+
-+ c->P[i] = datal;
-+ c->P[i + 1] = datar;
-+ }
-+
-+ for (i = 0; i < 4; i++) {
-+ for (k = 0; k < 256; k += 2) {
-+ datal ^= Blowfish_stream2word(data, databytes, &j);
-+ datar ^= Blowfish_stream2word(data, databytes, &j);
-+ Blowfish_encipher(c, &datal, &datar);
++ unsigned char *sptr = (unsigned char *)src;
++ 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;
++ }
+
-+ c->S[i][k] = datal;
-+ c->S[i][k + 1] = datar;
++ 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);
+}
+
-+#if __STDC__
-+void
-+blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len)
-+#else
-+void
-+blf_key(c, k, len)
-+ blf_ctx *c;
-+ const u_int8_t *k;
-+ u_int16_t len;
-+#endif
++static void BF_swap(BF_word *x, int count)
+{
-+ /* Initalize S-boxes and subkeys with Pi */
-+ Blowfish_initstate(c);
-+
-+ /* Transform S-boxes and subkeys with key */
-+ Blowfish_expand0state(c, k, len);
++ 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 __STDC__
-+void
-+blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
++#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
-+void
-+blf_enc(c, data, blocks)
-+ blf_ctx *c;
-+ u_int32_t *data;
-+ u_int16_t blocks;
++/* 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
-+{
-+ u_int32_t *d;
-+ u_int16_t i;
+
-+ d = data;
-+ for (i = 0; i < blocks; i++) {
-+ Blowfish_encipher(c, d, d + 1);
-+ d += 2;
-+ }
-+}
-+
-+#if __STDC__
-+void
-+blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
++/*
++ * 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
-+void
-+blf_dec(c, data, blocks)
-+ blf_ctx *c;
-+ u_int32_t *data;
-+ u_int16_t blocks;
++#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
-+{
-+ u_int32_t *d;
-+ u_int16_t i;
-+
-+ d = data;
-+ for (i = 0; i < blocks; i++) {
-+ Blowfish_decipher(c, d, d + 1);
-+ d += 2;
-+ }
-+}
+
-+#if __STDC__
-+void
-+blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
-+#else
-+void
-+blf_ecb_encrypt(c, data, len)
-+ blf_ctx *c;
-+ u_int8_t *data;
-+ u_int32_t len;
-+#endif
++static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial)
+{
-+ u_int32_t l, r;
-+ u_int32_t i;
++ __CONST char *ptr = key;
++ int i, j;
++ BF_word tmp;
+
-+ for (i = 0; i < len; i += 8) {
-+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
-+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
-+ Blowfish_encipher(c, &l, &r);
-+ data[0] = l >> 24 & 0xff;
-+ data[1] = l >> 16 & 0xff;
-+ data[2] = l >> 8 & 0xff;
-+ data[3] = l & 0xff;
-+ data[4] = r >> 24 & 0xff;
-+ data[5] = r >> 16 & 0xff;
-+ data[6] = r >> 8 & 0xff;
-+ data[7] = r & 0xff;
-+ data += 8;
-+ }
-+}
++ for (i = 0; i < BF_N + 2; i++) {
++ tmp = 0;
++ for (j = 0; j < 4; j++) {
++ tmp <<= 8;
++ tmp |= *ptr;
+
-+#if __STDC__
-+void
-+blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
-+#else
-+void
-+blf_ecb_decrypt(c, data, len)
-+ blf_ctx *c;
-+ u_int8_t *data;
-+ u_int32_t len;
-+#endif
-+{
-+ u_int32_t l, r;
-+ u_int32_t i;
++ if (!*ptr) ptr = key; else ptr++;
++ }
+
-+ for (i = 0; i < len; i += 8) {
-+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
-+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
-+ Blowfish_decipher(c, &l, &r);
-+ data[0] = l >> 24 & 0xff;
-+ data[1] = l >> 16 & 0xff;
-+ data[2] = l >> 8 & 0xff;
-+ data[3] = l & 0xff;
-+ data[4] = r >> 24 & 0xff;
-+ data[5] = r >> 16 & 0xff;
-+ data[6] = r >> 8 & 0xff;
-+ data[7] = r & 0xff;
-+ data += 8;
++ expanded[i] = tmp;
++ initial[i] = BF_init_state.P[i] ^ tmp;
+ }
+}
+
-+#if __STDC__
-+void
-+blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len)
-+#else
-+void
-+blf_cbc_encrypt(c, iv, data, len)
-+ blf_ctx *c;
-+ u_int8_t *iv;
-+ u_int8_t *data;
-+ u_int32_t len;
-+#endif
++char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
++ char *output, int size)
+{
-+ u_int32_t l, r;
-+ u_int32_t i, j;
-+
-+ for (i = 0; i < len; i += 8) {
-+ for (j = 0; j < 8; j++)
-+ data[j] ^= iv[j];
-+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
-+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
-+ Blowfish_encipher(c, &l, &r);
-+ data[0] = l >> 24 & 0xff;
-+ data[1] = l >> 16 & 0xff;
-+ data[2] = l >> 8 & 0xff;
-+ data[3] = l & 0xff;
-+ data[4] = r >> 24 & 0xff;
-+ data[5] = r >> 16 & 0xff;
-+ data[6] = r >> 8 & 0xff;
-+ data[7] = r & 0xff;
-+ iv = data;
-+ data += 8;
++#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 __STDC__
-+void
-+blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len)
-+#else
-+void
-+blf_cbc_decrypt(c, iva, data, len)
-+ blf_ctx *c;
-+ u_int8_t *iva;
-+ u_int8_t *data;
-+ u_int32_t len;
-+#endif
-+{
-+ u_int32_t l, r;
-+ u_int8_t *iv;
-+ u_int32_t i, j;
++ if (setting[0] != '$' ||
++ setting[1] != '2' ||
++ setting[2] != 'a' ||
++ setting[3] != '$' ||
++ setting[4] < '0' || setting[4] > '3' ||
++ setting[5] < '0' || setting[5] > '9' ||
++ setting[6] != '$') {
++ __set_errno(EINVAL);
++ return NULL;
++ }
+
-+ iv = data + len - 16;
-+ data = data + len - 8;
-+ for (i = len - 8; i >= 8; i -= 8) {
-+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
-+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
-+ Blowfish_decipher(c, &l, &r);
-+ data[0] = l >> 24 & 0xff;
-+ data[1] = l >> 16 & 0xff;
-+ data[2] = l >> 8 & 0xff;
-+ data[3] = l & 0xff;
-+ data[4] = r >> 24 & 0xff;
-+ data[5] = r >> 16 & 0xff;
-+ data[6] = r >> 8 & 0xff;
-+ data[7] = r & 0xff;
-+ for (j = 0; j < 8; j++)
-+ data[j] ^= iv[j];
-+ iv = data;
-+ data -= 8;
++ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
++ if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) {
++ clean(data.binary.salt, sizeof(data.binary.salt));
++ __set_errno(EINVAL);
++ return NULL;
+ }
-+ l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
-+ r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
-+ Blowfish_decipher(c, &l, &r);
-+ data[0] = l >> 24 & 0xff;
-+ data[1] = l >> 16 & 0xff;
-+ data[2] = l >> 8 & 0xff;
-+ data[3] = l & 0xff;
-+ data[4] = r >> 24 & 0xff;
-+ data[5] = r >> 16 & 0xff;
-+ data[6] = r >> 8 & 0xff;
-+ data[7] = r & 0xff;
-+ for (j = 0; j < 8; j++)
-+ data[j] ^= iva[j];
-+}
++ BF_swap(data.binary.salt, 4);
+
-+#if 0
-+void
-+report(u_int32_t data[], u_int16_t len)
-+{
-+ u_int16_t i;
-+ for (i = 0; i < len; i += 2)
-+ printf("Block %0hd: %08lx %08lx.\n",
-+ i / 2, data[i], data[i + 1]);
-+}
-+void
-+main(void)
-+{
++ BF_set_key(key, data.expanded_key, data.ctx.P);
+
-+ blf_ctx c;
-+ char key[] = "AAAAA";
-+ char key2[] = "abcdefghijklmnopqrstuvwxyz";
++ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
+
-+ u_int32_t data[10];
-+ u_int32_t data2[] =
-+ {0x424c4f57l, 0x46495348l};
++ 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;
++ }
+
-+ u_int16_t i;
++ 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 {
++ data.ctx.P[0] ^= data.expanded_key[0];
++ data.ctx.P[1] ^= data.expanded_key[1];
++ data.ctx.P[2] ^= data.expanded_key[2];
++ data.ctx.P[3] ^= data.expanded_key[3];
++ data.ctx.P[4] ^= data.expanded_key[4];
++ data.ctx.P[5] ^= data.expanded_key[5];
++ data.ctx.P[6] ^= data.expanded_key[6];
++ data.ctx.P[7] ^= data.expanded_key[7];
++ data.ctx.P[8] ^= data.expanded_key[8];
++ data.ctx.P[9] ^= data.expanded_key[9];
++ data.ctx.P[10] ^= data.expanded_key[10];
++ data.ctx.P[11] ^= data.expanded_key[11];
++ data.ctx.P[12] ^= data.expanded_key[12];
++ data.ctx.P[13] ^= data.expanded_key[13];
++ data.ctx.P[14] ^= data.expanded_key[14];
++ data.ctx.P[15] ^= data.expanded_key[15];
++ data.ctx.P[16] ^= data.expanded_key[16];
++ data.ctx.P[17] ^= data.expanded_key[17];
++
++ BF_body();
++
++ tmp1 = data.binary.salt[0];
++ tmp2 = data.binary.salt[1];
++ tmp3 = data.binary.salt[2];
++ tmp4 = data.binary.salt[3];
++ data.ctx.P[0] ^= tmp1;
++ data.ctx.P[1] ^= tmp2;
++ data.ctx.P[2] ^= tmp3;
++ data.ctx.P[3] ^= tmp4;
++ data.ctx.P[4] ^= tmp1;
++ data.ctx.P[5] ^= tmp2;
++ data.ctx.P[6] ^= tmp3;
++ data.ctx.P[7] ^= tmp4;
++ data.ctx.P[8] ^= tmp1;
++ data.ctx.P[9] ^= tmp2;
++ data.ctx.P[10] ^= tmp3;
++ data.ctx.P[11] ^= tmp4;
++ data.ctx.P[12] ^= tmp1;
++ data.ctx.P[13] ^= tmp2;
++ data.ctx.P[14] ^= tmp3;
++ data.ctx.P[15] ^= tmp4;
++ data.ctx.P[16] ^= tmp1;
++ data.ctx.P[17] ^= tmp2;
++
++ BF_body();
++ } 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];
+
-+ /* First test */
-+ for (i = 0; i < 10; i++)
-+ data[i] = i;
++/* 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';
+
-+ blf_key(&c, (u_int8_t *) key, 5);
-+ blf_enc(&c, data, 5);
-+ blf_dec(&c, data, 1);
-+ blf_dec(&c, data + 2, 4);
-+ printf("Should read as 0 - 9.\n");
-+ report(data, 10);
++/* Overwrite the most obvious sensitive data we have on the stack. Note
++ * that this does not guarantee there's no sensitive data left on the
++ * stack and/or in registers; I'm not aware of portable code that does. */
++ clean(&data, sizeof(data));
+
-+ /* Second test */
-+ blf_key(&c, (u_int8_t *) key2, strlen(key2));
-+ blf_enc(&c, data2, 1);
-+ printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
-+ report(data2, 2);
-+ blf_dec(&c, data2, 1);
-+ report(data2, 2);
++ return output;
+}
-+#endif
-diff -urN glibc-2.1.91.orig/crypt/blowfish.h glibc-2.1.91/crypt/blowfish.h
---- glibc-2.1.91.orig/crypt/blowfish.h Thu Jan 1 01:00:00 1970
-+++ glibc-2.1.91/crypt/blowfish.h Sat Jul 15 00:56:30 2000
-@@ -0,0 +1,10 @@
+
-+#ifndef BLOWFISH_H
-+#define BLOWFISH_H
++char *_crypt_gensalt_blowfish_rn(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))) {
++ if (output_size > 0) output[0] = '\0';
++ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
++ return NULL;
++ }
+
-+#include <sys/types.h>
++ if (!count) count = 5;
+
-+char *bcrypt(const char *key, const char *salt);
-+char *bcrypt_gensalt(u_int8_t log_rounds);
++ output[0] = '$';
++ output[1] = '2';
++ output[2] = 'a';
++ output[3] = '$';
++ output[4] = '0' + count / 10;
++ output[5] = '0' + count % 10;
++ output[6] = '$';
+
-+#endif /* BLOWFISH_H */
-diff -urN glibc-2.1.91.orig/crypt/crypt-entry.c glibc-2.1.91/crypt/crypt-entry.c
---- glibc-2.1.91.orig/crypt/crypt-entry.c Sat Mar 4 01:47:30 2000
-+++ glibc-2.1.91/crypt/crypt-entry.c Sat Jul 15 00:56:30 2000
-@@ -45,6 +45,8 @@
- #include "crypt.h"
- #include "crypt-private.h"
-
-+#include "blowfish.h"
++ BF_encode(&output[7], (BF_word *)input, 16);
++ output[7 + 22] = '\0';
+
- /* Prototypes for local functions. */
- #if __STDC__ - 0
- #ifndef __GNU_LIBRARY__
-@@ -61,6 +63,7 @@
- replacement. This is meant to be the same as for other MD5 based
- encryption implementations. */
- static const char md5_salt_prefix[] = "$1$";
-+static const char blowfish_salt_prefix[] = "$2";
++ return output;
++}
+Index: crypt/Makefile
+===================================================================
+--- crypt/Makefile.orig
++++ crypt/Makefile
+@@ -27,7 +27,7 @@ extra-libs := libcrypt
+ extra-libs-others := $(extra-libs)
+
+ libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
+- crypt_util
++ crypt_util crypt_blowfish
+
+ tests := cert md5c-test sha256c-test sha512c-test
+
+Index: crypt/crypt-entry.c
+===================================================================
+--- crypt/crypt-entry.c.orig
++++ crypt/crypt-entry.c
+@@ -61,6 +61,8 @@ extern char *__sha256_crypt (const char
+ extern char *__sha512_crypt_r (const char *key, const char *salt,
+ char *buffer, int buflen);
+ extern char *__sha512_crypt (const char *key, const char *salt);
++extern char *_crypt_blowfish_rn (const char *key, const char *setting,
++ char *output, int size);
+ #endif
+ /* Define our magic string to mark salt for MD5 encryption
+@@ -74,6 +76,9 @@ static const char sha256_salt_prefix[] =
+ /* Magic string for SHA512 encryption. */
+ static const char sha512_salt_prefix[] = "$6$";
+
++/* Magic string for Blowfish encryption. */
++static const char blowfish_salt_prefix[] = "$2a$";
++
/* For use by the old, non-reentrant routines (crypt/encrypt/setkey) */
extern struct crypt_data _ufc_foobar;
-@@ -109,6 +109,10 @@
+
+@@ -106,6 +111,11 @@ __crypt_r (key, salt, data)
if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
return __sha512_crypt_r (key, salt, (char *) data,
sizeof (struct crypt_data));
+
+ /* Try to find out whether we have to use Blowfish encryption replacement. */
+ if (strncmp (blowfish_salt_prefix, salt, sizeof (blowfish_salt_prefix) - 1) == 0)
-+ return bcrypt (key, salt);
++ return _crypt_blowfish_rn (key, salt, (char *) data,
++ sizeof (struct crypt_data));
#endif
/*
-@@ -159,6 +163,9 @@
- /* Try to find out whether we have to use SHA512 encryption replacement. */
- if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
- return __sha512_crypt (key, salt);
-+
-+ if (strncmp (blowfish_salt_prefix, salt, sizeof (blowfish_salt_prefix) - 1) == 0)
-+ return bcrypt (key, salt);
- #endif
-
- return __crypt_r (key, salt, &_ufc_foobar);
-