# Blowfish-crypt support (based on crypt_blowfish-1.0.1 by Solar Designer). # Gensalt interface. # Export UFC-crypt and MD5-crypt interface. # Export MD5 library. --- glibc-2.5.orig/Makerules +++ glibc-2.5/Makerules @@ -598,6 +598,8 @@ # But we still want to link libc.so agai LDLIBS-c.so += $(libc.so-gnulib) # Give libc.so an entry point and make it directly runnable itself. LDFLAGS-c.so += -e __libc_main +# Give libcrypt.so an entry point and make it directly runnable itself. +LDFLAGS-crypt.so += -e __libc_main # If lazy relocation is disabled add the -z now flag. ifeq ($(bind-now),yes) LDFLAGS-c.so += -Wl,-z,now --- glibc-2.5.orig/Versions.def +++ glibc-2.5/Versions.def @@ -32,6 +32,8 @@ libc { } libcrypt { GLIBC_2.0 + GLIBC_2.2.1 + GLIBC_2.2.2 } libdl { GLIBC_2.0 --- glibc-2.5.orig/crypt/Makefile +++ glibc-2.5/crypt/Makefile @@ -21,17 +21,17 @@ # Sub-makefile for crypt() portion of th # subdir := crypt -headers := crypt.h +headers := crypt.h 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 version wrapper -tests := cert md5test md5c-test +tests := cert md5test md5c-test bcrypt-test distribute := ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \ - Banner md5.h + Banner md5-private.h ow-crypt.h include ../Makeconfig --- glibc-2.5.orig/crypt/Versions +++ glibc-2.5/crypt/Versions @@ -2,4 +2,15 @@ libcrypt { GLIBC_2.0 { crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r; } + GLIBC_2.2.1 { + md5_init_ctx; md5_process_block; md5_process_bytes; md5_finish_ctx; md5_read_ctx; md5_stream; md5_buffer; + libc_crypt; crypt_rn; + crypt_md5; crypt_md5_rn; + crypt_ufc; crypt_ufc_r; + crypt_blowfish_rn; + crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_traditional_rn; crypt_gensalt_extended_rn; crypt_gensalt_md5_rn; crypt_gensalt_blowfish_rn; + } + GLIBC_2.2.2 { + crypt_ra; crypt_gensalt_ra; + } } --- /dev/null +++ glibc-2.5/crypt/bcrypt-test.c @@ -0,0 +1,117 @@ +/* + * Written by Solar Designer and placed in the public domain. + * Updated by Dmitry V. Levin , 2001-2006. + * See crypt_blowfish.c for more information. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "crypt.h" + +static struct { + const char *hash; + const char *pw; +} tests[] = { + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", + "U*U"}, + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", + "U*U*"}, + {"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", + "U*U*U"}, + {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", + ""}, + {"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", + "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"}, + {0, 0} +}; + +#define which tests[0] + +static volatile int running; + +static void handle_timer(int signum) +{ + running = 0; +} + +int main(void) +{ + struct itimerval it; + struct tms buf; + clock_t start_real, start_virtual, end_real, end_virtual; + unsigned long count; + void *data; + int size; + char *setting1, *setting2; + int i; + + for (i = 0; tests[i].hash; i++) + if (strcmp(crypt(tests[i].pw, tests[i].hash), tests[i].hash)) { + printf("FAILED (crypt/%d)\n", i); + return 1; + } + + data = NULL; + size = 0x12345678; + for (i = 0; tests[i].hash; i++) + if (strcmp(crypt_ra(tests[i].pw, tests[i].hash, &data, &size), + tests[i].hash)) { + printf("FAILED (crypt_ra/%d)\n", i); + return 1; + } + + setting1 = crypt_gensalt(which.hash, 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); + + 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 = 0; + + do { + crypt(which.pw, which.hash); + count++; + } while (running); + + 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 * CLOCKS_PER_SEC / (end_real - start_real), + (float)count * CLOCKS_PER_SEC / (end_virtual - start_virtual)); + + return 0; +} --- glibc-2.5.orig/crypt/crypt-entry.c +++ glibc-2.5/crypt/crypt-entry.c @@ -52,16 +52,8 @@ void _ufc_clearmem (char *start, int cnt #else #define _ufc_clearmem(start, cnt) memset(start, 0, cnt) #endif -extern char *__md5_crypt_r (const char *key, const char *salt, char *buffer, - int buflen); -extern char *__md5_crypt (const char *key, const char *salt); #endif -/* Define our magic string to mark salt for MD5 encryption - replacement. This is meant to be the same as for other MD5 based - encryption implementations. */ -static const char md5_salt_prefix[] = "$1$"; - /* For use by the old, non-reentrant routines (crypt/encrypt/setkey) */ extern struct crypt_data _ufc_foobar; @@ -69,23 +61,12 @@ extern struct crypt_data _ufc_foobar; * UNIX crypt function */ -char * -__crypt_r (key, salt, data) - const char *key; - const char *salt; - struct crypt_data * __restrict data; +char *__ufc_crypt_r (const char *key, const char *salt, struct crypt_data * __restrict data) { ufc_long res[4]; char ktab[9]; ufc_long xx = 25; /* to cope with GCC long long compiler bugs */ -#ifdef _LIBC - /* Try to find out whether we have to use MD5 encryption replacement. */ - if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) - return __md5_crypt_r (key, salt, (char *) data, - sizeof (struct crypt_data)); -#endif - /* * Hack DES tables according to salt */ @@ -115,35 +96,13 @@ #endif _ufc_output_conversion_r (res[0], res[1], salt, data); return data->crypt_3_buf; } -weak_alias (__crypt_r, crypt_r) -char * -crypt (key, salt) - const char *key; - const char *salt; +char *__ufc_crypt(const char *key, const char *salt) { -#ifdef _LIBC - /* Try to find out whether we have to use MD5 encryption replacement. */ - if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0) - return __md5_crypt (key, salt); -#endif - - return __crypt_r (key, salt, &_ufc_foobar); + return __ufc_crypt_r(key, salt, &_ufc_foobar); } - -/* - * To make fcrypt users happy. - * They don't need to call init_des. - */ -#ifdef _LIBC -weak_alias (crypt, fcrypt) -#else -char * -__fcrypt (key, salt) - const char *key; - const char *salt; -{ - return crypt (key, salt); -} +#ifdef _LIBC +weak_alias( __ufc_crypt_r, crypt_ufc_r ) +weak_alias( __ufc_crypt, crypt_ufc ) #endif --- glibc-2.5.orig/crypt/crypt-private.h +++ glibc-2.5/crypt/crypt-private.h @@ -53,8 +53,8 @@ extern void __encrypt_r (char * __restri struct crypt_data * __restrict __data); /* crypt-entry.c */ -extern char *__crypt_r (__const char *__key, __const char *__salt, - struct crypt_data * __restrict __data); +extern char *__ufc_crypt_r (__const char *__key, __const char *__salt, + struct crypt_data * __restrict __data) __THROW; extern char *fcrypt (__const char *key, __const char *salt); #endif /* crypt-private.h */ --- glibc-2.5.orig/crypt/crypt.h +++ glibc-2.5/crypt/crypt.h @@ -1,5 +1,7 @@ /* * UFC-crypt: ultra fast crypt(3) implementation + * md5-crypt: one way encryption based on MD5 sum + * blowfish-crypt: compatible with OpenBSD bcrypt (version 2a) * * Copyright (C) 1991,92,93,96,97,98,2000,2004 Free Software Foundation, Inc. * @@ -30,7 +32,7 @@ #include __BEGIN_DECLS /* Encrypt at most 8 characters from KEY using salt to perturb DES. */ -extern char *crypt (__const char *__key, __const char *__salt) +extern char *crypt (__const char *__key, __const char *__setting) __THROW __nonnull ((1, 2)); /* Setup DES tables according KEY. */ @@ -57,7 +59,17 @@ struct crypt_data int direction, initialized; }; -extern char *crypt_r (__const char *__key, __const char *__salt, +/* Encrypt characters from KEY using salt to initialize encryption algorithm. + It's same function as crypt but another call entry. */ +extern char *fcrypt (__const char *__key, __const char *__setting) + __THROW __nonnull ((1, 2)); + +/* Encrypt characters from KEY using salt to initialize encryption algorithm. + It's same function as crypt but another call entry. */ +extern char *libc_crypt (__const char *__key, __const char *__setting) + __THROW __nonnull ((1, 2)); + +extern char *crypt_r (__const char *__key, __const char *__setting, struct crypt_data * __restrict __data) __THROW __nonnull ((1, 2, 3)); @@ -68,6 +80,69 @@ extern void setkey_r (__const char *__ke extern void encrypt_r (char *__block, int __edflag, struct crypt_data * __restrict __data) __THROW __nonnull ((1, 3)); + +extern char *crypt_rn (__const char *__key, __const char *__setting, + void *__data, int __size) + __THROW __nonnull ((1, 2, 3)); + +extern char *crypt_ra (__const char *__key, __const char *__setting, + void **__data, int *__size) + __THROW __nonnull ((1, 2, 3, 4)); + +extern char *crypt_ufc (__const char *__key, __const char *__setting) + __THROW __nonnull ((1, 2)); + +extern char *crypt_ufc_r (__const char *__key, __const char *__setting, + struct crypt_data *__restrict __data) + __THROW __nonnull ((1, 2, 3)); + +extern char *crypt_md5 (__const char *__key, __const char *__setting) + __THROW __nonnull ((1, 2)); + +extern char *crypt_md5_rn (__const char *__key, __const char *__setting, + char *__output, int __size) + __THROW __nonnull ((1, 2, 3)); + +extern char *crypt_blowfish_rn (__const char *__key, + __const char *__setting, char *__output, + int __size) + __THROW __nonnull ((1, 2, 3)); + +extern char *crypt_gensalt (__const char *__prefix, unsigned long __count, + __const char *__input, int __size) + __THROW __nonnull ((1, 3)); + +extern char *crypt_gensalt_rn (__const char *__prefix, unsigned long __count, + __const char *__input, int __input_size, + char *__output, int __output_size) + __THROW __nonnull ((1, 3, 5)); + +extern char *crypt_gensalt_ra (__const char *prefix, unsigned long __count, + __const char *__input, int __size) + __THROW __nonnull ((1, 3)); + +extern char *crypt_gensalt_traditional_rn (unsigned long __count, + __const char *__input, + int __input_size, char *__output, + int __output_size) + __THROW __nonnull ((2, 4)); + +extern char *crypt_gensalt_extended_rn (unsigned long __count, + __const char *__input, + int __input_size, char *__output, + int __output_size) + __THROW __nonnull ((2, 4)); + +extern char *crypt_gensalt_md5_rn (unsigned long __count, + __const char *__input, int __input_size, + char *__output, int __output_size) + __THROW __nonnull ((2, 4)); + +extern char *crypt_gensalt_blowfish_rn (unsigned long __count, + __const char *__input, + int __input_size, char *__output, + int __output_size) + __THROW __nonnull ((2, 4)); #endif __END_DECLS --- /dev/null +++ glibc-2.5/crypt/crypt_blowfish.c @@ -0,0 +1,740 @@ +/* + * 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 in 1998-2002 and + * placed in the public domain. + * + * There's absolutely no warranty. + * + * 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. + * + * This implementation is compatible with OpenBSD bcrypt.c (version 2a) + * by Niels Provos , and uses some of his + * ideas. The password hashing algorithm was designed by David Mazieres + * . + * + * 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 + +#include +#ifndef __set_errno +#define __set_errno(val) errno = (val) +#endif + +#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; + +/* 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[] = "./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 +}; + +/* + * This may be optimized out if built with function inlining and no BF_ASM. + */ +static void clean(void *data, int size) +{ +#if BF_ASM + extern void _BF_clean(void *data); +#endif + memset(data, 0, size); +#if BF_ASM + _BF_clean(data); +#endif +} + +#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; + 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; +} + +static void BF_encode(char *dst, const BF_word *src, int size) +{ + 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; + } + + 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) +{ + const char *ptr = key; + int i, j; + BF_word tmp; + + for (i = 0; i < BF_N + 2; i++) { + tmp = 0; + for (j = 0; j < 4; j++) { + tmp <<= 8; + tmp |= *ptr; + + if (!*ptr) ptr = key; else ptr++; + } + + expanded[i] = tmp; + initial[i] = BF_init_state.P[i] ^ tmp; + } +} + +char *__crypt_blowfish_rn(const char *key, const char *setting, + char *output, int size) +{ +#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[3] != '$' || + setting[4] < '0' || setting[4] > '3' || + setting[5] < '0' || setting[5] > '9' || + setting[6] != '$') { + __set_errno(EINVAL); + return NULL; + } + + 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; + } + BF_swap(data.binary.salt, 4); + + BF_set_key(key, data.expanded_key, data.ctx.P); + + 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 { + 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]; + +/* 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'; + +/* 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)); + + return output; +} + +char *__crypt_gensalt_blowfish_rn(unsigned long count, + const char *input, int input_size, char *output, int output_size) +{ + if (input_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; + } + + if (!count) count = 5; + + output[0] = '$'; + output[1] = '2'; + output[2] = 'a'; + output[3] = '$'; + output[4] = '0' + count / 10; + output[5] = '0' + count % 10; + output[6] = '$'; + + BF_encode(&output[7], (BF_word *)input, 16); + output[7 + 22] = '\0'; + + return output; +} + +#ifdef _LIBC +weak_alias( __crypt_blowfish_rn, crypt_blowfish_rn ) +weak_alias( __crypt_gensalt_blowfish_rn, crypt_gensalt_blowfish_rn ) +#endif --- /dev/null +++ glibc-2.5/crypt/crypt_gensalt.c @@ -0,0 +1,110 @@ +/* + * Written by Solar Designer and placed in the public domain. + * Updated by Dmitry V. Levin , 2001-2006. + * 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 + +#include +#ifndef __set_errno +#define __set_errno(val) errno = (val) +#endif + +unsigned char _crypt_itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +char *__crypt_gensalt_traditional_rn(unsigned long count, + const char *input, int input_size, char *output, int output_size) +{ + if (input_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(unsigned long count, + const char *input, int input_size, char *output, int output_size) +{ + unsigned long value; + +/* Even iteration counts make it easier to detect weak DES keys from a look + * at the hash, so they should be avoided */ + if (input_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(unsigned long count, + const char *input, int input_size, char *output, int output_size) +{ + unsigned long value; + + if (input_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 (input_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; +} + +#ifdef _LIBC +weak_alias( __crypt_gensalt_traditional_rn, crypt_gensalt_traditional_rn ) +weak_alias( __crypt_gensalt_extended_rn, crypt_gensalt_extended_rn ) +weak_alias( __crypt_gensalt_md5_rn, crypt_gensalt_md5_rn ) +#endif --- glibc-2.5.orig/crypt/md5-crypt.c +++ glibc-2.5/crypt/md5-crypt.c @@ -26,7 +26,7 @@ #include #include #include -#include "md5.h" +#include "md5-private.h" /* Define our magic string to mark salt for MD5 "encryption" @@ -35,24 +35,10 @@ #include "md5.h" static const char md5_salt_prefix[] = "$1$"; /* Table with characters for base64 transformation. */ -static const char b64t[64] = -"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +extern unsigned char _crypt_itoa64[0x40]; - -/* Prototypes for local functions. */ -extern char *__md5_crypt_r (const char *key, const char *salt, - char *buffer, int buflen); -extern char *__md5_crypt (const char *key, const char *salt); - - -/* This entry point is equivalent to the `crypt' function in Unix - libcs. */ -char * -__md5_crypt_r (key, salt, buffer, buflen) - const char *key; - const char *salt; - char *buffer; - int buflen; +/* This entry point is equivalent to the `crypt' function in Unix libcs. */ +char *__md5_crypt_rn (const char *key, const char *salt, char *buffer, int buflen) { unsigned char alt_result[16] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); @@ -198,7 +184,7 @@ #define b64_from_24bit(B2, B1, B0, N) int n = (N); \ while (n-- > 0 && buflen > 0) \ { \ - *cp++ = b64t[w & 0x3f]; \ + *cp++ = _crypt_itoa64[w & 0x3f]; \ --buflen; \ w >>= 6; \ } \ @@ -245,7 +231,7 @@ __md5_crypt (const char *key, const char { /* We don't want to have an arbitrary limit in the size of the password. We can compute the size of the result in advance and - so we can prepare the buffer we pass to `md5_crypt_r'. */ + so we can prepare the buffer we pass to `__md5_crypt_rn'. */ static int buflen; int needed = 3 + strlen (salt) + 1 + 26 + 1; @@ -259,7 +245,7 @@ __md5_crypt (const char *key, const char buflen = needed; } - return __md5_crypt_r (key, salt, buffer, buflen); + return __md5_crypt_rn (key, salt, buffer, buflen); } #ifndef _LIBC @@ -270,3 +256,8 @@ free_mem (void) free (buffer); } #endif + +#ifdef _LIBC +weak_alias( __md5_crypt_rn, crypt_md5_rn ) +weak_alias( __md5_crypt, crypt_md5 ) +#endif --- /dev/null +++ glibc-2.5/crypt/md5-private.h @@ -0,0 +1,47 @@ +/* Declaration of private functions used for MD5 sum computing library functions. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _MD5_PRIVATE_H +#define _MD5_PRIVATE_H 1 + +#include "md5.h" + +#ifdef _LIBC +extern void __md5_init_ctx( struct md5_ctx *ctx ) __THROW; +extern void __md5_process_block( const void *buffer, size_t len, struct md5_ctx *ctx ) __THROW; +extern void __md5_process_bytes( const void *buffer, size_t len, struct md5_ctx *ctx ) __THROW; +extern void *__md5_finish_ctx( struct md5_ctx *ctx, void *resbuf ) __THROW; +extern void *__md5_read_ctx( const struct md5_ctx *ctx, void *resbuf ) __THROW; +extern int __md5_stream( FILE *stream, void *resblock ); +extern void *__md5_buffer( const char *buffer, size_t len, void *resblock ) __THROW; +extern char *__md5_crypt (const char *key, const char *salt); +extern char *__md5_crypt_rn (const char *key, const char *salt, char *data, int size) __THROW; +#else +#define __md5_init_ctx md5_init_ctx +#define __md5_process_block md5_process_block +#define __md5_process_bytes md5_process_bytes +#define __md5_finish_ctx md5_finish_ctx +#define __md5_read_ctx md5_read_ctx +#define __md5_stream md5_stream +#define __md5_buffer md5_buffer +#define __md5_crypt crypt_md5 +#define __md5_crypt_rn crypt_md5_rn +#endif /* _LIBC */ + +#endif /* md5-private.h */ --- glibc-2.5.orig/crypt/md5.c +++ glibc-2.5/crypt/md5.c @@ -36,22 +36,13 @@ # define memcpy(d, s, n) (bcopy ((s), ( # endif #endif -#include "md5.h" +#include "md5-private.h" #ifdef _LIBC # include # if __BYTE_ORDER == __BIG_ENDIAN # define WORDS_BIGENDIAN 1 # endif -/* We need to keep the namespace clean so define the MD5 function - protected using leading __ . */ -# define md5_init_ctx __md5_init_ctx -# define md5_process_block __md5_process_block -# define md5_process_bytes __md5_process_bytes -# define md5_finish_ctx __md5_finish_ctx -# define md5_read_ctx __md5_read_ctx -# define md5_stream __md5_stream -# define md5_buffer __md5_buffer #endif #ifdef WORDS_BIGENDIAN @@ -70,7 +61,7 @@ static const unsigned char fillbuf[64] = /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ void -md5_init_ctx (ctx) +__md5_init_ctx (ctx) struct md5_ctx *ctx; { ctx->A = 0x67452301; @@ -88,7 +79,7 @@ md5_init_ctx (ctx) IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * -md5_read_ctx (ctx, resbuf) +__md5_read_ctx (ctx, resbuf) const struct md5_ctx *ctx; void *resbuf; { @@ -106,7 +97,7 @@ md5_read_ctx (ctx, resbuf) IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * -md5_finish_ctx (ctx, resbuf) +__md5_finish_ctx (ctx, resbuf) struct md5_ctx *ctx; void *resbuf; { @@ -128,16 +119,16 @@ md5_finish_ctx (ctx, resbuf) (ctx->total[0] >> 29)); /* Process last bytes. */ - md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + __md5_process_block (ctx->buffer, bytes + pad + 8, ctx); - return md5_read_ctx (ctx, resbuf); + return __md5_read_ctx (ctx, resbuf); } /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ int -md5_stream (stream, resblock) +__md5_stream (stream, resblock) FILE *stream; void *resblock; { @@ -148,7 +139,7 @@ #define BLOCKSIZE 4096 size_t sum; /* Initialize the computation context. */ - md5_init_ctx (&ctx); + __md5_init_ctx (&ctx); /* Iterate over full file contents. */ while (1) @@ -177,15 +168,15 @@ #define BLOCKSIZE 4096 /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ - md5_process_block (buffer, BLOCKSIZE, &ctx); + __md5_process_block (buffer, BLOCKSIZE, &ctx); } /* Add the last bytes if necessary. */ if (sum > 0) - md5_process_bytes (buffer, sum, &ctx); + __md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ - md5_finish_ctx (&ctx, resblock); + __md5_finish_ctx (&ctx, resblock); return 0; } @@ -194,7 +185,7 @@ #define BLOCKSIZE 4096 output yields to the wanted ASCII representation of the message digest. */ void * -md5_buffer (buffer, len, resblock) +__md5_buffer (buffer, len, resblock) const char *buffer; size_t len; void *resblock; @@ -202,18 +193,18 @@ md5_buffer (buffer, len, resblock) struct md5_ctx ctx; /* Initialize the computation context. */ - md5_init_ctx (&ctx); + __md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ - md5_process_bytes (buffer, len, &ctx); + __md5_process_bytes (buffer, len, &ctx); /* Put result in desired memory area. */ - return md5_finish_ctx (&ctx, resblock); + return __md5_finish_ctx (&ctx, resblock); } void -md5_process_bytes (buffer, len, ctx) +__md5_process_bytes (buffer, len, ctx) const void *buffer; size_t len; struct md5_ctx *ctx; @@ -230,7 +221,7 @@ md5_process_bytes (buffer, len, ctx) if (ctx->buflen > 64) { - md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + __md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ctx->buflen &= 63; /* The regions in the following copy operation cannot overlap. */ @@ -256,14 +247,14 @@ # endif if (UNALIGNED_P (buffer)) while (len > 64) { - md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + __md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); buffer = (const char *) buffer + 64; len -= 64; } else #endif { - md5_process_block (buffer, len & ~63, ctx); + __md5_process_block (buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } @@ -278,7 +269,7 @@ #endif left_over += len; if (left_over >= 64) { - md5_process_block (ctx->buffer, 64, ctx); + __md5_process_block (ctx->buffer, 64, ctx); left_over -= 64; memcpy (ctx->buffer, &ctx->buffer[64], left_over); } @@ -300,7 +291,7 @@ #define FI(b, c, d) (c ^ (b | ~d)) It is assumed that LEN % 64 == 0. */ void -md5_process_block (buffer, len, ctx) +__md5_process_block (buffer, len, ctx) const void *buffer; size_t len; struct md5_ctx *ctx; @@ -456,3 +447,13 @@ #define OP(f, a, b, c, d, k, s, T) \ ctx->C = C; ctx->D = D; } + +#ifdef _LIBC +weak_alias( __md5_init_ctx, md5_init_ctx ) +weak_alias( __md5_process_block, md5_process_block ) +weak_alias( __md5_process_bytes, md5_process_bytes ) +weak_alias( __md5_finish_ctx, md5_finish_ctx ) +weak_alias( __md5_read_ctx, md5_read_ctx ) +weak_alias( __md5_stream, md5_stream ) +weak_alias( __md5_buffer, md5_buffer ) +#endif --- glibc-2.5.orig/crypt/md5.h +++ glibc-2.5/crypt/md5.h @@ -31,52 +31,9 @@ #endif #define MD5_DIGEST_SIZE 16 #define MD5_BLOCK_SIZE 64 -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - doing that would require that the configure script compile and *run* - the resulting executable. Locally running cross-compiled executables - is usually not possible. */ - -#ifdef _LIBC -# include +#include typedef uint32_t md5_uint32; typedef uintptr_t md5_uintptr; -#else -# if defined __STDC__ && __STDC__ -# define UINT_MAX_32_BITS 4294967295U -# else -# define UINT_MAX_32_BITS 0xFFFFFFFF -# endif - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -# ifndef UINT_MAX -# define UINT_MAX UINT_MAX_32_BITS -# endif - -# if UINT_MAX == UINT_MAX_32_BITS - typedef unsigned int md5_uint32; -# else -# if USHRT_MAX == UINT_MAX_32_BITS - typedef unsigned short md5_uint32; -# else -# if ULONG_MAX == UINT_MAX_32_BITS - typedef unsigned long md5_uint32; -# else - /* The following line is intended to evoke an error. - Using #error is not portable enough. */ - "Cannot determine unsigned 32-bit data type." -# endif -# endif -# endif -/* We have to make a guess about the integer type equivalent in size - to pointers which should always be correct. */ -typedef unsigned long int md5_uintptr; -#endif /* Structure to save state of computation between the single steps. */ struct md5_ctx @@ -98,20 +55,20 @@ struct md5_ctx /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ -extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; +extern void md5_init_ctx (struct md5_ctx *ctx) __THROW; /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is necessary that LEN is a multiple of 64!!! */ -extern void __md5_process_block (const void *buffer, size_t len, +extern void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) __THROW; /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ -extern void __md5_process_bytes (const void *buffer, size_t len, +extern void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) __THROW; /* Process the remaining bytes in the buffer and put result from CTX @@ -121,7 +78,7 @@ extern void __md5_process_bytes (const v IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ -extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; +extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; /* Put result from CTX in first 16 bytes following RESBUF. The result is @@ -130,19 +87,19 @@ extern void *__md5_finish_ctx (struct md IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ -extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; +extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ -extern int __md5_stream (FILE *stream, void *resblock) __THROW; +extern int md5_stream (FILE *stream, void *resblock) __THROW; /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ -extern void *__md5_buffer (const char *buffer, size_t len, +extern void *md5_buffer (const char *buffer, size_t len, void *resblock) __THROW; #endif /* md5.h */ --- glibc-2.5.orig/crypt/md5test.c +++ glibc-2.5/crypt/md5test.c @@ -37,15 +37,15 @@ main (int argc, char *argv[]) { int i; - __md5_init_ctx (&ctx); - __md5_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx); - __md5_finish_ctx (&ctx, sum); + md5_init_ctx (&ctx); + md5_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx); + md5_finish_ctx (&ctx, sum); result |= memcmp (tests[cnt].result, sum, 16); - __md5_init_ctx (&ctx); + md5_init_ctx (&ctx); for (i = 0; tests[cnt].input[i] != '\0'; ++i) - __md5_process_bytes (&tests[cnt].input[i], 1, &ctx); - __md5_finish_ctx (&ctx, sum); + md5_process_bytes (&tests[cnt].input[i], 1, &ctx); + md5_finish_ctx (&ctx, sum); result |= memcmp (tests[cnt].result, sum, 16); } --- /dev/null +++ glibc-2.5/crypt/ow-crypt.h @@ -0,0 +1,62 @@ +/* + * blowfish-crypt: compatible with OpenBSD bcrypt (version 2a) + * + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU C Library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _OW_CRYPT_H +#define _OW_CRYPT_H 1 + +#include "crypt.h" + +#ifdef _LIBC + +extern char *__crypt_rn(const char *key, const char *setting, + void *data, int size) __THROW; +extern char *__crypt_ra(const char *key, const char *setting, + void **data, int *size) __THROW; +extern char *__crypt_gensalt(const char *prefix, unsigned long count, + const char *input, int size) __THROW; +extern char *__crypt_gensalt_rn(const char *prefix, unsigned long count, + const char *input, int input_size, char *output, int output_size) __THROW; + +extern char *__crypt_blowfish_rn(const char *key, const char *setting, + char *output, int size) __THROW; +extern char *__crypt_gensalt_blowfish_rn(unsigned long count, + const char *input, int input_size, char *output, int output_size) __THROW; + +extern unsigned char _crypt_itoa64[0x40]; + +extern char *__crypt_gensalt_traditional_rn(unsigned long count, + const char *input, int input_size, char *output, int output_size) __THROW; +extern char *__crypt_gensalt_extended_rn(unsigned long count, + const char *input, int input_size, char *output, int output_size) __THROW; +extern char *__crypt_gensalt_md5_rn(unsigned long count, + const char *input, int input_size, char *output, int output_size) __THROW; + +extern char *__md5_crypt_rn(const char *key, const char *setting, + char *buffer, int buflen) __THROW; +extern char *__ufc_crypt_r(const char *key, const char *setting, + struct crypt_data *data) __THROW; + +extern struct crypt_data _ufc_foobar; + +#endif + +#endif /* ow-crypt.h */ --- /dev/null +++ glibc-2.5/crypt/version.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1992-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "version.h" +#include + +#ifdef HAVE_ELF + +static const char banner[] = +"Crypt add-on for GNU C Library "RELEASE" release version "VERSION".\n\ +Copyright (C) 1991-2002 Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions.\n\ +There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ +PARTICULAR PURPOSE.\n\ +Compiled by GNU CC version "__VERSION__".\n\ +Implementations:\n\ + UFC-crypt by Michael Glad .\n\ + MD5-crypt by Ulrich Drepper .\n\ + Blowfish-crypt by Solar Designer .\n\ +Report bugs using the `glibcbug' script to\n\ + and .\n"; + +/* This function is the entry point for the shared object. + Running the library as a program will get here. */ + +void __attribute__ ((noreturn)) +__libc_main (void) +{ + write (STDOUT_FILENO, banner, sizeof banner - 1); + _exit (0); +} + +#endif --- /dev/null +++ glibc-2.5/crypt/wrapper.c @@ -0,0 +1,185 @@ +/* + * Written by Solar Designer and placed in the public domain. + * Updated by Dmitry V. Levin , 2001-2006. + * See crypt_blowfish.c for more information. + */ + +#include +#include + +#include +#ifndef __set_errno +#define __set_errno(val) errno = (val) +#endif + +#include "ow-crypt.h" + +#define CRYPT_OUTPUT_SIZE (7 + 22 + 31 + 1) +#define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1) + +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) { + return -1; + } + + if (need >= sizeof(struct crypt_data)) + ((struct crypt_data *)updated)->initialized = 0; + + *data = updated; + *size = need; + + return 0; +} + +static char *_crypt_retval_magic(char *retval, const char *setting, + char *output) +{ + if (retval) return retval; + + output[0] = '*'; + output[1] = '0'; + output[2] = '\0'; + + if (setting[0] == '*' && setting[1] == '0') + output[1] = '1'; + + return output; +} + +/* + * 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_rn( key, setting, (char *)data, size ); + if ( setting[0] == '$' || setting[0] == '_' ) { + __set_errno(EINVAL); + return NULL; + } + if ( size >= sizeof(struct crypt_data) ) + return __ufc_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_rn( 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 __ufc_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 ); +} + +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 ); +} + +char *__crypt_gensalt_rn(const char *prefix, unsigned long count, + const char *input, int input_size, char *output, int output_size) +{ + char *(*use)(unsigned long count, + const char *input, int input_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)) + 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(count, input, input_size, output, output_size); +} + +char *__crypt_gensalt_ra(const char *prefix, unsigned long count, + const char *input, int input_size) +{ + char output[CRYPT_GENSALT_OUTPUT_SIZE]; + char *retval = __crypt_gensalt_rn(prefix, count, + input, input_size, output, sizeof(output)); + + if (retval) + retval = strdup(retval); + + return retval; +} + +char *__crypt_gensalt(const char *prefix, unsigned long count, + const char *input, int input_size) +{ + static char output[CRYPT_GENSALT_OUTPUT_SIZE]; + + return __crypt_gensalt_rn(prefix, count, + input, input_size, output, sizeof(output)); +} + +#ifdef _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, fcrypt ) +weak_alias( __crypt, libc_crypt ) +weak_alias( __crypt_gensalt_rn, crypt_gensalt_rn ) +weak_alias( __crypt_gensalt_ra, crypt_gensalt_ra ) +weak_alias( __crypt_gensalt, crypt_gensalt ) +#endif --- /dev/null +++ glibc-2.5/crypt/x86.S @@ -0,0 +1,211 @@ +/* + * Written by Solar Designer and placed in the public domain. + * 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 +#define _BF_clean __BF_clean +#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 0x500 +#define BF_CLEAN 0x600 +#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 + +.globl _BF_clean +_BF_clean: + leal -32(%esp),%ecx + xorl %eax,%eax + leal -BF_CLEAN(%esp),%edx +BF_loop_clean: + movl %ecx,%esp + movl %eax,(%ecx) + movl %eax,4(%ecx) + movl %eax,8(%ecx) + movl %eax,12(%ecx) + subl $32,%ecx + movl %eax,16(%esp) + movl %eax,20(%esp) + movl %eax,24(%esp) + movl %eax,28(%esp) + cmpl %edx,%esp + ja BF_loop_clean + leal BF_CLEAN(%edx),%esp + ret + +BF_die: +/* Oops, need to re-compile with a larger BF_FRAME. */ + hlt + jmp BF_die + +#endif --- glibc-2.5.orig/locale/programs/locarchive.c +++ glibc-2.5/locale/programs/locarchive.c @@ -43,6 +43,8 @@ #include "../localeinfo.h" #include "../locarchive.h" #include "localedef.h" +#define __md5_buffer md5_buffer + /* Define the hash function. We define the function as static inline. We must change the name so as not to conflict with simple-hash.h. */ #define compute_hashval static inline archive_hashval --- glibc-2.5.orig/locale/programs/locfile.c +++ glibc-2.5/locale/programs/locfile.c @@ -35,6 +35,7 @@ #include "simple-hash.h" #include "locfile-kw.h" +#define __md5_buffer md5_buffer /* Temporary storage of the locale data before writing it to the archive. */ static locale_data_t to_archive;