From 83b42d94bd1009da6a95052d9ef0edeb1c73c8e4 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 9 Aug 2012 21:35:19 -0400 Subject: [PATCH 01/16] add defines for number of sigset_t bytes syscalls expect yet another gratuitous mips incompatibility... --- arch/arm/bits/syscall.h | 2 ++ arch/i386/bits/syscall.h | 2 ++ arch/mips/bits/syscall.h | 2 ++ arch/x86_64/bits/syscall.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/arch/arm/bits/syscall.h b/arch/arm/bits/syscall.h index 816d7b05..9932c9e5 100644 --- a/arch/arm/bits/syscall.h +++ b/arch/arm/bits/syscall.h @@ -3,6 +3,8 @@ ((union { long long ll; long l[2]; }){ .ll = x }).l[1] #define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) +#define __SYSCALL_SSLEN 8 + long (__syscall)(long, ...); static inline long __syscall0(long n) diff --git a/arch/i386/bits/syscall.h b/arch/i386/bits/syscall.h index 37b339c0..4b574e99 100644 --- a/arch/i386/bits/syscall.h +++ b/arch/i386/bits/syscall.h @@ -3,6 +3,8 @@ ((union { long long ll; long l[2]; }){ .ll = x }).l[1] #define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) +#define __SYSCALL_SSLEN 8 + static inline long __syscall0(long __n) { unsigned long __ret; diff --git a/arch/mips/bits/syscall.h b/arch/mips/bits/syscall.h index 868ce0fe..6c51bab9 100644 --- a/arch/mips/bits/syscall.h +++ b/arch/mips/bits/syscall.h @@ -3,6 +3,8 @@ ((union { long long ll; long l[2]; }){ .ll = x }).l[1] #define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) +#define __SYSCALL_SSLEN 16 + long (__syscall)(long, ...); static inline long __syscall0(long n) diff --git a/arch/x86_64/bits/syscall.h b/arch/x86_64/bits/syscall.h index 61a67a70..567cfcb7 100644 --- a/arch/x86_64/bits/syscall.h +++ b/arch/x86_64/bits/syscall.h @@ -1,6 +1,8 @@ #define __SYSCALL_LL_E(x) (x) #define __SYSCALL_LL_O(x) (x) +#define __SYSCALL_SSLEN 8 + static inline long __syscall0(long __n) { unsigned long __ret; -- 2.20.1 From 2f437040e7911d9bef239588ea7ed6f4b9102922 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 9 Aug 2012 22:52:13 -0400 Subject: [PATCH 02/16] fix (hopefully) all hard-coded 8's for kernel sigset_t size some minor changes to how hard-coded sets for thread-related purposes are handled were also needed, since the old object sizes were not necessarily sufficient. things have gotten a bit ugly in this area, and i think a cleanup is in order at some point, but for now the goal is just to get the code working on all supported archs including mips, which was badly broken by linux rejecting syscalls with the wrong sigset_t size. --- src/internal/pthread_impl.h | 7 +++++-- src/linux/epoll_pwait.c | 2 +- src/linux/signalfd.c | 2 +- src/select/pselect.c | 2 +- src/signal/raise.c | 5 +++-- src/signal/siglongjmp.c | 4 ++-- src/signal/sigpending.c | 2 +- src/signal/sigsuspend.c | 2 +- src/signal/sigtimedwait.c | 3 ++- src/thread/pthread_create.c | 6 ++++-- src/thread/pthread_self.c | 3 ++- src/thread/pthread_sigmask.c | 4 ++-- src/thread/synccall.c | 6 ++++-- src/time/timer_create.c | 3 ++- 14 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 46d8fdd2..56b92b22 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -90,9 +90,12 @@ struct __timer { #define SIGCANCEL 33 #define SIGSYNCCALL 34 -#define SIGPT_SET ((sigset_t *)(unsigned long [1+(sizeof(long)==4)]){ \ +#define SIGALL_SET ((sigset_t *)(const unsigned long long [2]){ -1,-1 }) +#define SIGPT_SET \ + ((sigset_t *)(const unsigned long [__SYSCALL_SSLEN/sizeof(long)]){ \ [sizeof(long)==4] = 3UL<<(32*(sizeof(long)>4)) }) -#define SIGTIMER_SET ((sigset_t *)(unsigned long [1+(sizeof(long)==4)]){ \ +#define SIGTIMER_SET \ + ((sigset_t *)(const unsigned long [__SYSCALL_SSLEN/sizeof(long)]){ \ 0x80000000 }) pthread_t __pthread_self_init(void); diff --git a/src/linux/epoll_pwait.c b/src/linux/epoll_pwait.c index 39ad5b77..3ecdbb59 100644 --- a/src/linux/epoll_pwait.c +++ b/src/linux/epoll_pwait.c @@ -3,5 +3,5 @@ int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs) { - return syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, 8); + return syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, __SYSCALL_SSLEN); } diff --git a/src/linux/signalfd.c b/src/linux/signalfd.c index 99c35143..1a6c03c3 100644 --- a/src/linux/signalfd.c +++ b/src/linux/signalfd.c @@ -3,5 +3,5 @@ int signalfd(int fd, const sigset_t *sigs, int flags) { - return syscall(SYS_signalfd, fd, sigs, 8); + return syscall(SYS_signalfd, fd, sigs, __SYSCALL_SSLEN); } diff --git a/src/select/pselect.c b/src/select/pselect.c index f28887ff..48fcefed 100644 --- a/src/select/pselect.c +++ b/src/select/pselect.c @@ -4,7 +4,7 @@ int pselect(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *ts, const sigset_t *mask) { - long data[2] = { (long)mask, 8 }; + long data[2] = { (long)mask, __SYSCALL_SSLEN }; struct timespec ts_tmp; if (ts) ts_tmp = *ts; return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, ts ? &ts_tmp : 0, data); diff --git a/src/signal/raise.c b/src/signal/raise.c index 71e0505b..c0814fad 100644 --- a/src/signal/raise.c +++ b/src/signal/raise.c @@ -2,15 +2,16 @@ #include #include #include "syscall.h" +#include "pthread_impl.h" int raise(int sig) { int pid, tid, ret; sigset_t set; - __syscall(SYS_rt_sigprocmask, SIG_BLOCK, (uint64_t[]){-1}, &set, 8); + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGALL_SET, &set, __SYSCALL_SSLEN); tid = syscall(SYS_gettid); pid = syscall(SYS_getpid); ret = syscall(SYS_tgkill, pid, tid, sig); - __syscall(SYS_rt_sigprocmask, SIG_SETMASK, &set, 0, 8); + __syscall(SYS_rt_sigprocmask, SIG_SETMASK, &set, 0, __SYSCALL_SSLEN); return ret; } diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c index 9b4a5398..e9a61314 100644 --- a/src/signal/siglongjmp.c +++ b/src/signal/siglongjmp.c @@ -5,7 +5,7 @@ void siglongjmp(sigjmp_buf buf, int ret) { - if (buf->__fl) - __syscall(SYS_rt_sigprocmask, SIG_SETMASK, buf->__ss, 0, 8); + if (buf->__fl) __syscall(SYS_rt_sigprocmask, SIG_SETMASK, + buf->__ss, 0, __SYSCALL_SSLEN); longjmp(buf->__jb, ret); } diff --git a/src/signal/sigpending.c b/src/signal/sigpending.c index f6b8972e..46ce3036 100644 --- a/src/signal/sigpending.c +++ b/src/signal/sigpending.c @@ -3,5 +3,5 @@ int sigpending(sigset_t *set) { - return syscall(SYS_rt_sigpending, set, 8); + return syscall(SYS_rt_sigpending, set, __SYSCALL_SSLEN); } diff --git a/src/signal/sigsuspend.c b/src/signal/sigsuspend.c index cd3a7b59..bdfaeee0 100644 --- a/src/signal/sigsuspend.c +++ b/src/signal/sigsuspend.c @@ -4,5 +4,5 @@ int sigsuspend(const sigset_t *mask) { - return syscall_cp(SYS_rt_sigsuspend, mask, 8); + return syscall_cp(SYS_rt_sigsuspend, mask, __SYSCALL_SSLEN); } diff --git a/src/signal/sigtimedwait.c b/src/signal/sigtimedwait.c index 7eea58ab..f62db2f3 100644 --- a/src/signal/sigtimedwait.c +++ b/src/signal/sigtimedwait.c @@ -6,7 +6,8 @@ int sigtimedwait(const sigset_t *mask, siginfo_t *si, const struct timespec *timeout) { int ret; - do ret = syscall_cp(SYS_rt_sigtimedwait, mask, si, timeout, 8); + do ret = syscall_cp(SYS_rt_sigtimedwait, mask, + si, timeout, __SYSCALL_SSLEN); while (ret<0 && errno==EINTR); return ret; } diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index 94dc308d..52b48d6f 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -38,7 +38,8 @@ void pthread_exit(void *result) if (self->detached && self->map_base) { if (self->detached == 2) __syscall(SYS_set_tid_address, 0); - __syscall(SYS_rt_sigprocmask, SIG_BLOCK, (uint64_t[]){-1},0,8); + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, + SIGALL_SET, 0, __SYSCALL_SSLEN); __unmapself(self->map_base, self->map_size); } @@ -61,7 +62,8 @@ static int start(void *p) { pthread_t self = p; if (self->unblock_cancel) - __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, 8); + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, + SIGPT_SET, 0, __SYSCALL_SSLEN); pthread_exit(self->start(self->start_arg)); return 0; } diff --git a/src/thread/pthread_self.c b/src/thread/pthread_self.c index f68896f7..a8cc80b5 100644 --- a/src/thread/pthread_self.c +++ b/src/thread/pthread_self.c @@ -8,7 +8,8 @@ weak_alias(dummy, __pthread_tsd_main); static int init_main_thread() { - __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, 8); + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, + SIGPT_SET, 0, __SYSCALL_SSLEN); if (__set_thread_area(&main_thread) < 0) return -1; main_thread.canceldisable = libc.canceldisable; main_thread.tsd = (void **)__pthread_tsd_main; diff --git a/src/thread/pthread_sigmask.c b/src/thread/pthread_sigmask.c index decc38f8..cddc2bca 100644 --- a/src/thread/pthread_sigmask.c +++ b/src/thread/pthread_sigmask.c @@ -6,8 +6,8 @@ int pthread_sigmask(int how, const sigset_t *set, sigset_t *old) { int ret; - if (how > 2U) return EINVAL; - ret = -__syscall(SYS_rt_sigprocmask, how, set, old, 8); + if ((unsigned)how - SIG_BLOCK > 2U) return EINVAL; + ret = -__syscall(SYS_rt_sigprocmask, how, set, old, __SYSCALL_SSLEN); if (!ret && old) { if (sizeof old->__bits[0] == 8) { old->__bits[0] &= ~0x380000000ULL; diff --git a/src/thread/synccall.c b/src/thread/synccall.c index 1520b3b4..fd377cb3 100644 --- a/src/thread/synccall.c +++ b/src/thread/synccall.c @@ -61,7 +61,8 @@ void __synccall(void (*func)(void *), void *ctx) pthread_rwlock_wrlock(&lock); - __syscall(SYS_rt_sigprocmask, SIG_BLOCK, (uint64_t[]){-1}, &oldmask, 8); + __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGALL_SET, + &oldmask, __SYSCALL_SSLEN); sem_init(&chaindone, 0, 0); sem_init(&chainlock, 0, 1); @@ -93,7 +94,8 @@ void __synccall(void (*func)(void *), void *ctx) sa.sa_handler = SIG_IGN; __libc_sigaction(SIGSYNCCALL, &sa, 0); - __syscall(SYS_rt_sigprocmask, SIG_SETMASK, &oldmask, 0, 8); + __syscall(SYS_rt_sigprocmask, SIG_SETMASK, + &oldmask, 0, __SYSCALL_SSLEN); pthread_rwlock_unlock(&lock); } diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 6cff16fb..813678a1 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -51,7 +51,8 @@ static void install_handler() .sa_flags = SA_SIGINFO | SA_RESTART }; __libc_sigaction(SIGTIMER, &sa, 0); - __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGTIMER_SET, 0, 8); + __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, + SIGTIMER_SET, 0, __SYSCALL_SSLEN); } static void *start(void *arg) -- 2.20.1 From a02bf5fc508c32e8617ff0528d1cc89ed56e3d03 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Aug 2012 00:20:00 -0400 Subject: [PATCH 03/16] add blowfish hash support to crypt there are still some discussions going on about tweaking the code, but at least thing brings us to the point of having something working in the repository. hopefully the remaining major hashes (md5,sha) will follow soon. --- src/misc/crypt.c | 2 +- src/misc/crypt_blowfish.c | 798 ++++++++++++++++++++++++++++++++++++++ src/misc/crypt_r.c | 14 +- 3 files changed, 806 insertions(+), 8 deletions(-) create mode 100644 src/misc/crypt_blowfish.c diff --git a/src/misc/crypt.c b/src/misc/crypt.c index f35e13d8..fc5c4ee1 100644 --- a/src/misc/crypt.c +++ b/src/misc/crypt.c @@ -6,6 +6,6 @@ char *__crypt_r(const char *, const char *, struct crypt_data *); char *crypt(const char *key, const char *salt) { /* Note: update this size when we add more hash types */ - static char buf[21]; + static char buf[64]; return __crypt_r(key, salt, (struct crypt_data *)buf); } diff --git a/src/misc/crypt_blowfish.c b/src/misc/crypt_blowfish.c new file mode 100644 index 00000000..d3f79851 --- /dev/null +++ b/src/misc/crypt_blowfish.c @@ -0,0 +1,798 @@ +/* Modified by Rich Felker in for inclusion in musl libc, based on + * Solar Designer's second size-optimized version sent to the musl + * mailing list. */ + +/* + * The crypt_blowfish homepage is: + * + * http://www.openwall.com/crypt/ + * + * This code comes from John the Ripper password cracker, with reentrant + * and crypt(3) interfaces added, but optimizations specific to password + * cracking removed. + * + * Written by Solar Designer in 1998-2012. + * No copyright is claimed, and the software is hereby placed in the public + * domain. In case this attempt to disclaim copyright and place the software + * in the public domain is deemed null and void, then the software is + * Copyright (c) 1998-2012 Solar Designer and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * It is my intent that you should be able to use this on your system, + * as part of a software package, or anywhere else to improve security, + * ensure compatibility, or for any other purpose. I would appreciate + * it if you give credit where it is due and keep your modifications in + * the public domain as well, but I don't require that in order to let + * you place this code and any modifications you make under a license + * of your choice. + * + * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix + * "$2a$") by Niels Provos , and uses some of his + * ideas. The password hashing algorithm was designed by David Mazieres + * . For more information on the level of compatibility, + * please refer to the comments in BF_set_key() below and to the included + * crypt(3) man page. + * + * There's a paper on the algorithm that explains its design decisions: + * + * http://www.usenix.org/events/usenix99/provos.html + * + * Some of the tricks in BF_ROUND might be inspired by Eric Young's + * Blowfish library (I can't be sure if I would think of something if I + * hadn't seen his code). + */ + +#include +#include + +typedef uint32_t BF_word; +typedef int32_t BF_word_signed; + +/* Number of Blowfish rounds, this is also hardcoded into a few places */ +#define BF_N 16 + +typedef BF_word BF_key[BF_N + 2]; + +typedef union { + struct { + BF_key P; + BF_word S[4][0x100]; + } s; + BF_word PS[BF_N + 2 + 4 * 0x100]; +} BF_ctx; + +/* + * Magic IV for 64 Blowfish encryptions that we do at the end. + * The string is "OrpheanBeholderScryDoubt" on big-endian. + */ +static const BF_word BF_magic_w[6] = { + 0x4F727068, 0x65616E42, 0x65686F6C, + 0x64657253, 0x63727944, 0x6F756274 +}; + +/* + * P-box and S-box tables initialized with digits of Pi. + */ +static const BF_ctx BF_init_state = {{ + { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + }, { + { + 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 + } + } +}}; + +static const unsigned char BF_itoa64[64 + 1] = + "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + +static const unsigned char BF_atoi64[0x60] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, + 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64, + 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64 +}; + +#define BF_safe_atoi64(dst, src) \ +{ \ + tmp = (unsigned char)(src); \ + if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ + tmp = BF_atoi64[tmp]; \ + if (tmp > 63) return -1; \ + (dst) = tmp; \ +} + +static int BF_decode(BF_word *dst, const char *src, int size) +{ + unsigned char *dptr = (unsigned char *)dst; + unsigned char *end = dptr + size; + const unsigned char *sptr = (const unsigned char *)src; + unsigned int tmp, c1, c2, c3, c4; + + do { + BF_safe_atoi64(c1, *sptr++); + BF_safe_atoi64(c2, *sptr++); + *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); + if (dptr >= end) break; + + BF_safe_atoi64(c3, *sptr++); + *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); + if (dptr >= end) break; + + BF_safe_atoi64(c4, *sptr++); + *dptr++ = ((c3 & 0x03) << 6) | c4; + } while (dptr < end); + + return 0; +} + +static void BF_encode(char *dst, const BF_word *src, int size) +{ + const unsigned char *sptr = (const unsigned char *)src; + const unsigned char *end = sptr + size; + unsigned char *dptr = (unsigned char *)dst; + unsigned int c1, c2; + + do { + c1 = *sptr++; + *dptr++ = BF_itoa64[c1 >> 2]; + c1 = (c1 & 0x03) << 4; + if (sptr >= end) { + *dptr++ = BF_itoa64[c1]; + break; + } + + c2 = *sptr++; + c1 |= c2 >> 4; + *dptr++ = BF_itoa64[c1]; + c1 = (c2 & 0x0f) << 2; + if (sptr >= end) { + *dptr++ = BF_itoa64[c1]; + break; + } + + c2 = *sptr++; + c1 |= c2 >> 6; + *dptr++ = BF_itoa64[c1]; + *dptr++ = BF_itoa64[c2 & 0x3f]; + } while (sptr < end); +} + +static void BF_swap(BF_word *x, int count) +{ + if ((union { int i; char c; }){1}.c) + do { + BF_word tmp = *x; + tmp = (tmp << 16) | (tmp >> 16); + *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); + } while (--count); +} + +#define BF_ROUND(L, R, N) \ + tmp1 = L & 0xFF; \ + tmp2 = L >> 8; \ + tmp2 &= 0xFF; \ + tmp3 = L >> 16; \ + tmp3 &= 0xFF; \ + tmp4 = L >> 24; \ + tmp1 = ctx->s.S[3][tmp1]; \ + tmp2 = ctx->s.S[2][tmp2]; \ + tmp3 = ctx->s.S[1][tmp3]; \ + tmp3 += ctx->s.S[0][tmp4]; \ + tmp3 ^= tmp2; \ + R ^= ctx->s.P[N + 1]; \ + tmp3 += tmp1; \ + R ^= tmp3; + +static BF_word BF_encrypt(BF_ctx *ctx, + BF_word L, BF_word R, + BF_word *start, BF_word *end) +{ + BF_word tmp1, tmp2, tmp3, tmp4; + BF_word *ptr = start; + + do { + L ^= ctx->s.P[0]; +#if 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); +#else + for (int i=0; i<16; i+=2) { + BF_ROUND(L, R, i); + BF_ROUND(R, L, i+1); + } +#endif + tmp4 = R; + R = L; + L = tmp4 ^ ctx->s.P[BF_N + 1]; + *ptr++ = L; + *ptr++ = R; + } while (ptr < end); + + return L; +} + +static void BF_set_key(const char *key, BF_key expanded, BF_key initial, + unsigned char flags) +{ + const char *ptr = key; + unsigned int bug, i, j; + BF_word safety, sign, diff, tmp[2]; + +/* + * There was a sign extension bug in older revisions of this function. While + * we would have liked to simply fix the bug and move on, we have to provide + * a backwards compatibility feature (essentially the bug) for some systems and + * a safety measure for some others. The latter is needed because for certain + * multiple inputs to the buggy algorithm there exist easily found inputs to + * the correct algorithm that produce the same hash. Thus, we optionally + * deviate from the correct algorithm just enough to avoid such collisions. + * While the bug itself affected the majority of passwords containing + * characters with the 8th bit set (although only a percentage of those in a + * collision-producing way), the anti-collision safety measure affects + * only a subset of passwords containing the '\xff' character (not even all of + * those passwords, just some of them). This character is not found in valid + * UTF-8 sequences and is rarely used in popular 8-bit character encodings. + * Thus, the safety measure is unlikely to cause much annoyance, and is a + * reasonable tradeoff to use when authenticating against existing hashes that + * are not reliably known to have been computed with the correct algorithm. + * + * We use an approach that tries to minimize side-channel leaks of password + * information - that is, we mostly use fixed-cost bitwise operations instead + * of branches or table lookups. (One conditional branch based on password + * length remains. It is not part of the bug aftermath, though, and is + * difficult and possibly unreasonable to avoid given the use of C strings by + * the caller, which results in similar timing leaks anyway.) + * + * For actual implementation, we set an array index in the variable "bug" + * (0 means no bug, 1 means sign extension bug emulation) and a flag in the + * variable "safety" (bit 16 is set when the safety measure is requested). + * Valid combinations of settings are: + * + * Prefix "$2a$": bug = 0, safety = 0x10000 + * Prefix "$2x$": bug = 1, safety = 0 + * Prefix "$2y$": bug = 0, safety = 0 + */ + bug = flags & 1; + safety = ((BF_word)flags & 2) << 15; + + sign = diff = 0; + + for (i = 0; i < BF_N + 2; i++) { + tmp[0] = tmp[1] = 0; + for (j = 0; j < 4; j++) { + tmp[0] <<= 8; + tmp[0] |= (unsigned char)*ptr; /* correct */ + tmp[1] <<= 8; + tmp[1] |= (signed char)*ptr; /* bug */ +/* + * Sign extension in the first char has no effect - nothing to overwrite yet, + * and those extra 24 bits will be fully shifted out of the 32-bit word. For + * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign + * extension in tmp[1] occurs. Once this flag is set, it remains set. + */ + if (j) + sign |= tmp[1] & 0x80; + if (!*ptr) + ptr = key; + else + ptr++; + } + diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */ + + expanded[i] = tmp[bug]; + initial[i] = BF_init_state.s.P[i] ^ tmp[bug]; + } + +/* + * At this point, "diff" is zero iff the correct and buggy algorithms produced + * exactly the same result. If so and if "sign" is non-zero, which indicates + * that there was a non-benign sign extension, this means that we have a + * collision between the correctly computed hash for this password and a set of + * passwords that could be supplied to the buggy algorithm. Our safety measure + * is meant to protect from such many-buggy to one-correct collisions, by + * deviating from the correct algorithm in such cases. Let's check for this. + */ + diff |= diff >> 16; /* still zero iff exact match */ + diff &= 0xffff; /* ditto */ + diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */ + sign <<= 9; /* move the non-benign sign extension flag to bit 16 */ + sign &= ~diff & safety; /* action needed? */ + +/* + * If we have determined that we need to deviate from the correct algorithm, + * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but + * let's stick to it now. It came out of the approach we used above, and it's + * not any worse than any other choice we could make.) + * + * It is crucial that we don't do the same to the expanded key used in the main + * Eksblowfish loop. By doing it to only one of these two, we deviate from a + * state that could be directly specified by a password to the buggy algorithm + * (and to the fully correct one as well, but that's a side-effect). + */ + initial[0] ^= sign; +} + +static char *BF_crypt(const char *key, const char *setting, + char *output, BF_word min) +{ + static const unsigned char flags_by_subtype[26] = + {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0}; + struct { + BF_ctx ctx; + BF_key expanded_key; + union { + BF_word salt[4]; + BF_word output[6]; + } binary; + } data; + BF_word count; + int i; + + if (setting[0] != '$' || + setting[1] != '2' || + setting[2] - 'a' > 25U || + !flags_by_subtype[setting[2] - 'a'] || + setting[3] != '$' || + setting[4] - '0' > 1U || + setting[5] - '0' > 9U || + setting[6] != '$') { + return NULL; + } + + count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0')); + if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) { + return NULL; + } + BF_swap(data.binary.salt, 4); + + BF_set_key(key, data.expanded_key, data.ctx.s.P, + flags_by_subtype[setting[2] - 'a']); + + memcpy(data.ctx.s.S, BF_init_state.s.S, sizeof(data.ctx.s.S)); + + { + BF_word L = 0, R = 0; + BF_word *ptr = &data.ctx.PS[0]; + do { + L = BF_encrypt(&data.ctx, + L ^ data.binary.salt[0], R ^ data.binary.salt[1], + ptr, ptr); + R = *(ptr + 1); + ptr += 2; + + if (ptr >= &data.ctx.PS[BF_N + 2 + 4 * 0x100]) + break; + + L = BF_encrypt(&data.ctx, + L ^ data.binary.salt[2], R ^ data.binary.salt[3], + ptr, ptr); + R = *(ptr + 1); + ptr += 2; + } while (1); + } + + do { + int done; + + for (i = 0; i < BF_N + 2; i += 2) { + data.ctx.s.P[i] ^= data.expanded_key[i]; + data.ctx.s.P[i + 1] ^= data.expanded_key[i + 1]; + } + + done = 0; + do { + BF_encrypt(&data.ctx, 0, 0, + &data.ctx.PS[0], + &data.ctx.PS[BF_N + 2 + 4 * 0x100]); + + if (done) + break; + done = 1; + + { + BF_word tmp1, tmp2, tmp3, tmp4; + + tmp1 = data.binary.salt[0]; + tmp2 = data.binary.salt[1]; + tmp3 = data.binary.salt[2]; + tmp4 = data.binary.salt[3]; + for (i = 0; i < BF_N; i += 4) { + data.ctx.s.P[i] ^= tmp1; + data.ctx.s.P[i + 1] ^= tmp2; + data.ctx.s.P[i + 2] ^= tmp3; + data.ctx.s.P[i + 3] ^= tmp4; + } + data.ctx.s.P[16] ^= tmp1; + data.ctx.s.P[17] ^= tmp2; + } + } while (1); + } while (--count); + + for (i = 0; i < 6; i += 2) { + BF_word L, LR[2]; + + L = BF_magic_w[i]; + LR[1] = BF_magic_w[i + 1]; + + count = 64; + do { + L = BF_encrypt(&data.ctx, L, LR[1], + &LR[0], &LR[0]); + } while (--count); + + data.binary.output[i] = L; + data.binary.output[i + 1] = LR[1]; + } + + memcpy(output, setting, 7 + 22 - 1); + output[7 + 22 - 1] = BF_itoa64[ + BF_atoi64[setting[7 + 22 - 1] - 0x20] & 0x30]; + +/* This has to be bug-compatible with the original implementation, so + * only encode 23 of the 24 bytes. :-) */ + BF_swap(data.binary.output, 6); + BF_encode(&output[7 + 22], data.binary.output, 23); + output[7 + 22 + 31] = '\0'; + + return output; +} + +/* + * Please preserve the runtime self-test. It serves two purposes at once: + * + * 1. We really can't afford the risk of producing incompatible hashes e.g. + * when there's something like gcc bug 26587 again, whereas an application or + * library integrating this code might not also integrate our external tests or + * it might not run them after every build. Even if it does, the miscompile + * might only occur on the production build, but not on a testing build (such + * as because of different optimization settings). It is painful to recover + * from incorrectly-computed hashes - merely fixing whatever broke is not + * enough. Thus, a proactive measure like this self-test is needed. + * + * 2. We don't want to leave sensitive data from our actual password hash + * computation on the stack or in registers. Previous revisions of the code + * would do explicit cleanups, but simply running the self-test after hash + * computation is more reliable. + * + * The performance cost of this quick self-test is around 0.6% at the "$2a$08" + * setting. + */ +char *__crypt_blowfish(const char *key, const char *setting, char *output) +{ + const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; + const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu"; + static const char test_hash[2][34] = + {"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */ + "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */ + char *retval; + const char *p; + int ok; + struct { + char s[7 + 22 + 1]; + char o[7 + 22 + 31 + 1 + 1 + 1]; + } buf; + +/* Hash the supplied password */ + retval = BF_crypt(key, setting, output, 16); + +/* + * Do a quick self-test. It is important that we make both calls to BF_crypt() + * from the same scope such that they likely use the same stack locations, + * which makes the second call overwrite the first call's sensitive data on the + * stack and makes it more likely that any alignment related issues would be + * detected by the self-test. + */ + memcpy(buf.s, test_setting, sizeof(buf.s)); + if (retval) + buf.s[2] = setting[2]; + memset(buf.o, 0x55, sizeof(buf.o)); + buf.o[sizeof(buf.o) - 1] = 0; + p = BF_crypt(test_key, buf.s, buf.o, 1); + + ok = (p == buf.o && + !memcmp(p, buf.s, 7 + 22) && + !memcmp(p + (7 + 22), + test_hash[buf.s[2] & 1], + 31 + 1 + 1 + 1)); + + { + const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"; + BF_key ae, ai, ye, yi; + BF_set_key(k, ae, ai, 2); /* $2a$ */ + BF_set_key(k, ye, yi, 4); /* $2y$ */ + ai[0] ^= 0x10000; /* undo the safety (for comparison) */ + ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 && + !memcmp(ae, ye, sizeof(ae)) && + !memcmp(ai, yi, sizeof(ai)); + } + + if (ok && retval) + return retval; + + return "*"; +} diff --git a/src/misc/crypt_r.c b/src/misc/crypt_r.c index d16ab48d..f4716d6f 100644 --- a/src/misc/crypt_r.c +++ b/src/misc/crypt_r.c @@ -5,19 +5,19 @@ struct crypt_data; char *__crypt_des(const char *, const char *, char *); char *__crypt_md5(const char *, const char *, char *); +char *__crypt_blowfish(const char *, const char *, char *); char *__crypt_r(const char *key, const char *salt, struct crypt_data *data) { char *output = (char *)data; + if (salt[0] == '$' && salt[1] && salt[2]) { #if 0 - /* MD5 or SHA? */ - if (salt[0] == '$' && salt[1] && salt[2] == '$') { - if (salt[1] == '1') - return __crypt_md5((char *)data, key, salt); - else - return "x"; - } + if (salt[1] == '1' && salt[2] == '$') + return __crypt_md5(key, salt, output); #endif + if (salt[1] == '2' && salt[3] == '$') + return __crypt_blowfish(key, salt, output); + } return __crypt_des(key, salt, output); } -- 2.20.1 From c5875ad34b88e159e664587df9f8a9dbac86879f Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Aug 2012 14:59:20 -0400 Subject: [PATCH 04/16] fix incorrect ptrdiff_t type on mips --- arch/mips/bits/alltypes.h.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/bits/alltypes.h.sh b/arch/mips/bits/alltypes.h.sh index a5357708..c909bc37 100755 --- a/arch/mips/bits/alltypes.h.sh +++ b/arch/mips/bits/alltypes.h.sh @@ -18,7 +18,7 @@ union \1 \2;\ TYPEDEF unsigned size_t; TYPEDEF int ssize_t; -TYPEDEF long ptrdiff_t; +TYPEDEF int ptrdiff_t; TYPEDEF __builtin_va_list va_list; -- 2.20.1 From e3ebe7db5de64c193202f1c5b321c9a470e730c5 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Aug 2012 15:13:26 -0400 Subject: [PATCH 05/16] use int instead of long for ptrdiff_t on all 32-bit archs this is needed to match the underlying "ABI" standards. it's not really an ABI issue since the binary representations are the same, but having the wrong type can lead to errors when the type arising from a difference-of-pointers expression does not match the defined type of ptrdiff_t. most of the problems affect C++, not C. --- arch/arm/bits/alltypes.h.sh | 2 +- arch/i386/bits/alltypes.h.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/bits/alltypes.h.sh b/arch/arm/bits/alltypes.h.sh index 4ba3d81c..274de0df 100755 --- a/arch/arm/bits/alltypes.h.sh +++ b/arch/arm/bits/alltypes.h.sh @@ -18,7 +18,7 @@ union \1 \2;\ TYPEDEF unsigned size_t; TYPEDEF int ssize_t; -TYPEDEF long ptrdiff_t; +TYPEDEF int ptrdiff_t; TYPEDEF __builtin_va_list va_list; diff --git a/arch/i386/bits/alltypes.h.sh b/arch/i386/bits/alltypes.h.sh index 10956690..10fcf6a3 100755 --- a/arch/i386/bits/alltypes.h.sh +++ b/arch/i386/bits/alltypes.h.sh @@ -18,7 +18,7 @@ union \1 \2;\ TYPEDEF unsigned size_t; TYPEDEF int ssize_t; -TYPEDEF long ptrdiff_t; +TYPEDEF int ptrdiff_t; #if __GNUC__ >= 3 TYPEDEF __builtin_va_list va_list; -- 2.20.1 From 4c346919a9b238748de2ee85ce6d749fc3cf7059 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Aug 2012 22:18:49 -0400 Subject: [PATCH 06/16] trivial optimization to printf: avoid wasted call frame amusingly, this cuts more than 10% off the run time of printf("a"); on the machine i tested it on. sadly the same optimization is not possible for snprintf without duplicating all the pseudo-FILE setup code, which is not worth it. --- src/stdio/printf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdio/printf.c b/src/stdio/printf.c index efeb8b33..7b7c329f 100644 --- a/src/stdio/printf.c +++ b/src/stdio/printf.c @@ -6,7 +6,7 @@ int printf(const char *fmt, ...) int ret; va_list ap; va_start(ap, fmt); - ret = vprintf(fmt, ap); + ret = vfprintf(stdout, fmt, ap); va_end(ap); return ret; } -- 2.20.1 From 2b964b010e5d37cb2ff712d57a14095188d689e3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 10 Aug 2012 23:39:32 -0400 Subject: [PATCH 07/16] minor but worthwhile optimization in printf: avoid expensive strspn the strspn call was made for every format specifier and end-of-string, even though the expected return value was 1-2 for normal usage. replace with simple loop. --- src/stdio/vfprintf.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 116e1ced..d186d58b 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -430,7 +430,7 @@ static int getint(char **s) { static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type) { char *a, *z, *s=(char *)fmt; - unsigned l10n=0, litpct, fl; + unsigned l10n=0, fl; int w, p; union arg arg; int argpos; @@ -455,9 +455,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, /* Handle literal text and %% format specifiers */ for (a=s; *s && *s!='%'; s++); - litpct = strspn(s, "%")/2; /* Optimize %%%% runs */ - z = s+litpct; - s += 2*litpct; + for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2); l = z-a; if (f) out(f, a, l); if (l) continue; -- 2.20.1 From 617182734ca0beffa347747019d78b972e2038f9 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Aug 2012 18:10:38 -0400 Subject: [PATCH 08/16] add bsd fgetln function optimized to avoid allocation and return lines directly out of the stream buffer whenever possible. --- include/stdio.h | 4 ++++ src/internal/stdio_impl.h | 2 +- src/stdio/fclose.c | 1 + src/stdio/fgetln.c | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/stdio/fgetln.c diff --git a/include/stdio.h b/include/stdio.h index 3d22220f..19ab8bcd 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -172,6 +172,10 @@ int getw(FILE *); int putw(int, FILE *); #endif +#ifdef _BSD_SOURCE +char *fgetln(FILE *, size_t *); +#endif + #ifdef _GNU_SOURCE int asprintf(char **, const char *, ...); int vasprintf(char **, const char *, va_list); diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h index d54c918b..65dcfbda 100644 --- a/src/internal/stdio_impl.h +++ b/src/internal/stdio_impl.h @@ -57,7 +57,7 @@ struct __FILE_s { int waiters; void *cookie; off_t off; - void *dummy4; + char *getln_buf; void *mustbezero_2; unsigned char *shend; off_t shlim, shcnt; diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c index 373a2c76..8fdc3f7d 100644 --- a/src/stdio/fclose.c +++ b/src/stdio/fclose.c @@ -16,6 +16,7 @@ int fclose(FILE *f) r = fflush(f); r |= f->close(f); + if (f->getln_buf) free(f->getln_buf); if (!perm) free(f); return r; diff --git a/src/stdio/fgetln.c b/src/stdio/fgetln.c new file mode 100644 index 00000000..06b88837 --- /dev/null +++ b/src/stdio/fgetln.c @@ -0,0 +1,19 @@ +#include "stdio_impl.h" + +char *fgetln(FILE *f, size_t *plen) +{ + char *ret = 0, *z; + ssize_t l; + FLOCK(f); + ungetc(getc_unlocked(f), f); + if ((z=memchr(f->rpos, '\n', f->rend - f->rpos))) { + ret = (char *)f->rpos; + *plen = ++z - ret; + f->rpos = (void *)z; + } else if ((l = getline(&f->getln_buf, (size_t[]){0}, f)) > 0) { + *plen = l; + ret = f->getln_buf; + } + FUNLOCK(f); + return ret; +} -- 2.20.1 From 35c16933f03a3db49f3e2048759d850460c8a509 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Aug 2012 18:39:12 -0400 Subject: [PATCH 09/16] remove buggy short-string wcsstr implementation; always use twoway since this interface is rarely used, it's probably best to lean towards keeping code size down anyway. one-character needles will still be found immediately by the initial wcschr call anyway. --- src/string/wcsstr.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/string/wcsstr.c b/src/string/wcsstr.c index 966174f8..fc4bacec 100644 --- a/src/string/wcsstr.c +++ b/src/string/wcsstr.c @@ -3,14 +3,6 @@ #include #include -static wchar_t *naive_wcsstr(const wchar_t *h, const wchar_t *n) -{ - size_t i; - for (i=0; n[i] && h[i]; i++) - for ( ; n[i] != h[i]; h++, i=0); - return n[i] ? 0 : (wchar_t *)h; -} - #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) @@ -111,7 +103,6 @@ wchar_t *wcsstr(const wchar_t *h, const wchar_t *n) h = wcschr(h, *n); if (!h || !n[1]) return (wchar_t *)h; if (!h[1]) return 0; - if (!n[2] || !n[3] || !n[4]) return naive_wcsstr(h, n); return twoway_wcsstr(h, n); } -- 2.20.1 From f997e224fc30361fe683c6b5d0ba39718043ca8d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Aug 2012 18:40:33 -0400 Subject: [PATCH 10/16] remove unused but buggy code from strstr.c --- src/string/strstr.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/string/strstr.c b/src/string/strstr.c index 683cdd01..06491748 100644 --- a/src/string/strstr.c +++ b/src/string/strstr.c @@ -25,16 +25,6 @@ static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n) return *h ? (char *)h-3 : 0; } -#if 0 -static char *naive_strstr(const char *h, const char *n) -{ - size_t i; - for (i=0; n[i] && h[i]; i++) - for ( ; n[i] != h[i]; h++, i=0); - return n[i] ? 0 : (char *)h; -} -#endif - #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) -- 2.20.1 From 036eaa24cf573c69982ba18dd427de68f6eeba2a Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Aug 2012 19:51:21 -0400 Subject: [PATCH 11/16] avoid need for -march=mips2 to compile mips atomic.h asm linux guarantees ll/sc are always available. on mips1, they will be emulated by the kernel. thus they are part of the linux mips1 abi and safe to use. --- arch/mips/atomic.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/mips/atomic.h b/arch/mips/atomic.h index a09f98df..f3478ef2 100644 --- a/arch/mips/atomic.h +++ b/arch/mips/atomic.h @@ -27,6 +27,7 @@ static inline int a_cas(volatile int *p, int t, int s) int dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%2)\n" " bne %0, %3, 1f\n" @@ -56,6 +57,7 @@ static inline int a_swap(volatile int *x, int v) int old, dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%2)\n" " addu %1, %3, $0\n" @@ -73,6 +75,7 @@ static inline int a_fetch_add(volatile int *x, int v) int old, dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%2)\n" " addu %1, %0, %3\n" @@ -90,6 +93,7 @@ static inline void a_inc(volatile int *x) int dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%1)\n" " addu %0, %0, 1\n" @@ -106,6 +110,7 @@ static inline void a_dec(volatile int *x) int dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%1)\n" " subu %0, %0, 1\n" @@ -122,6 +127,7 @@ static inline void a_store(volatile int *p, int x) int dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%1)\n" " addu %0, %2, $0\n" @@ -147,6 +153,7 @@ static inline void a_and(volatile int *p, int v) int dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%1)\n" " and %0, %0, %2\n" @@ -163,6 +170,7 @@ static inline void a_or(volatile int *p, int v) int dummy; __asm__ __volatile__( ".set push\n" + ".set mips2\n" ".set noreorder\n" "1: ll %0, 0(%1)\n" " or %0, %0, %2\n" -- 2.20.1 From aaa9eb5101e3a748218fb9373dd9655b50582da2 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 11 Aug 2012 21:33:13 -0400 Subject: [PATCH 12/16] memcpy asm for i386 and x86_64 --- src/string/i386/memcpy.s | 29 +++++++++++++++++++++++++++++ src/string/x86_64/memcpy.s | 22 ++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/string/i386/memcpy.s create mode 100644 src/string/x86_64/memcpy.s diff --git a/src/string/i386/memcpy.s b/src/string/i386/memcpy.s new file mode 100644 index 00000000..b2977c89 --- /dev/null +++ b/src/string/i386/memcpy.s @@ -0,0 +1,29 @@ +.global memcpy +.type memcpy,@function +memcpy: + push %esi + push %edi + mov 12(%esp),%edi + mov 16(%esp),%esi + mov 20(%esp),%ecx + mov %edi,%eax + cmp $4,%ecx + jc 1f + test $3,%edi + jz 1f +2: movsb + dec %ecx + test $3,%edi + jnz 2b +1: mov %ecx,%edx + shr $2,%ecx + rep + movsl + and $3,%edx + jz 1f +2: movsb + dec %edx + jnz 2b +1: pop %edi + pop %esi + ret diff --git a/src/string/x86_64/memcpy.s b/src/string/x86_64/memcpy.s new file mode 100644 index 00000000..1282dc3b --- /dev/null +++ b/src/string/x86_64/memcpy.s @@ -0,0 +1,22 @@ +.global memcpy +.type memcpy,@function +memcpy: + mov %rdi,%rax + cmp $8,%rdx + jc 1f + test $7,%edi + jz 1f +2: movsb + dec %rdx + test $7,%edi + jnz 2b +1: mov %rdx,%rcx + shr $3,%rcx + rep + movsq + and $7,%edx + jz 1f +2: movsb + dec %edx + jnz 2b +1: ret -- 2.20.1 From 0c42beb5f90fe5583c2cae5a31c2ef68847974e3 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 13 Aug 2012 14:50:30 -0400 Subject: [PATCH 13/16] publicly expose getdents api under _BSD_SOURCE --- include/dirent.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/dirent.h b/include/dirent.h index 6241220f..a51526d4 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -54,6 +54,10 @@ int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int int versionsort(const struct dirent **, const struct dirent **); #endif +#ifdef _BSD_SOURCE +int getdents(int, struct dirent *, size_t); +#endif + #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) #define dirent64 dirent #define readdir64 readdir @@ -63,6 +67,9 @@ int versionsort(const struct dirent **, const struct dirent **); #define versionsort64 versionsort #define off64_t off_t #define ino64_t ino_t +#ifdef _BSD_SOURCE +#define getdents64 getdents +#endif #endif #ifdef __cplusplus -- 2.20.1 From 2242bf616b893e85886ed0a2348b96bf1cf7623e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 13 Aug 2012 14:51:43 -0400 Subject: [PATCH 14/16] add significand[fl] math functions --- include/math.h | 4 ++++ src/math/significand.c | 7 +++++++ src/math/significandf.c | 7 +++++++ src/math/significandl.c | 7 +++++++ 4 files changed, 25 insertions(+) create mode 100644 src/math/significand.c create mode 100644 src/math/significandf.c create mode 100644 src/math/significandl.c diff --git a/include/math.h b/include/math.h index 583dc3da..656f7868 100644 --- a/include/math.h +++ b/include/math.h @@ -400,6 +400,10 @@ long double exp10l(long double); double pow10(double); float pow10f(float); long double pow10l(long double); + +double significand(double); +float significandf(float); +long double significandl(long double); #endif #ifdef __cplusplus diff --git a/src/math/significand.c b/src/math/significand.c new file mode 100644 index 00000000..40d9aa9f --- /dev/null +++ b/src/math/significand.c @@ -0,0 +1,7 @@ +#define _GNU_SOURCE +#include + +double significand(double x) +{ + return scalbn(x, -ilogb(x)); +} diff --git a/src/math/significandf.c b/src/math/significandf.c new file mode 100644 index 00000000..8a697e1a --- /dev/null +++ b/src/math/significandf.c @@ -0,0 +1,7 @@ +#define _GNU_SOURCE +#include + +float significandf(float x) +{ + return scalbnf(x, -ilogbf(x)); +} diff --git a/src/math/significandl.c b/src/math/significandl.c new file mode 100644 index 00000000..c1d68cd7 --- /dev/null +++ b/src/math/significandl.c @@ -0,0 +1,7 @@ +#define _GNU_SOURCE +#include + +long double significandl(long double x) +{ + return scalbnl(x, -ilogbl(x)); +} -- 2.20.1 From ab76321c14e18e70c853f34202a567749292eafc Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 13 Aug 2012 16:00:31 -0400 Subject: [PATCH 15/16] remove significandl this function never existed historically; since the float/double functions it's based on are nonstandard and deprecated, there's really no justification for its existence except that glibc has it. it can be added back if there's ever really a need... --- include/math.h | 1 - src/math/significandl.c | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 src/math/significandl.c diff --git a/include/math.h b/include/math.h index 656f7868..cf9d9fbf 100644 --- a/include/math.h +++ b/include/math.h @@ -403,7 +403,6 @@ long double pow10l(long double); double significand(double); float significandf(float); -long double significandl(long double); #endif #ifdef __cplusplus diff --git a/src/math/significandl.c b/src/math/significandl.c deleted file mode 100644 index c1d68cd7..00000000 --- a/src/math/significandl.c +++ /dev/null @@ -1,7 +0,0 @@ -#define _GNU_SOURCE -#include - -long double significandl(long double x) -{ - return scalbnl(x, -ilogbl(x)); -} -- 2.20.1 From 23e6940a2cf101017df33236ebee0fd4e3383172 Mon Sep 17 00:00:00 2001 From: nsz Date: Mon, 13 Aug 2012 22:06:01 +0200 Subject: [PATCH 16/16] math: fix _BSD_SOURCE namespace in math.h --- include/math.h | 51 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/include/math.h b/include/math.h index cf9d9fbf..2fdcb7b4 100644 --- a/include/math.h +++ b/include/math.h @@ -330,6 +330,11 @@ double trunc(double); float truncf(float); long double truncl(long double); + +#if defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) +#define MAXFLOAT 3.40282347e+38F +#endif + #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define M_E 2.7182818284590452354 /* e */ #define M_LOG2E 1.4426950408889634074 /* log_2 e */ @@ -344,13 +349,7 @@ long double truncl(long double); #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ -#endif -#if defined(_XOPEN_SOURCE) -#define MAXFLOAT 3.40282347e+38F -#endif - -#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) extern int signgam; double j0(double); @@ -362,47 +361,49 @@ double y1(double); double yn(int, double); #endif -#ifdef _GNU_SOURCE -#define HUGE 3.40282347e+38F +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define HUGE 3.40282347e+38F + double scalb(double, double); float scalbf(float, float); -long double scalbl(long double, long double); -void sincos(double, double*, double*); -void sincosf(float, float*, float*); -void sincosl(long double, long double*, long double*); - -double gamma(double); -float gammaf(float); -long double gammal(long double); +double significand(double); +float significandf(float); double lgamma_r(double, int*); float lgammaf_r(float, int*); -long double lgammal_r(long double, int*); float j0f(float); -long double j0l(long double); float j1f(float); -long double j1l(long double); float jnf(int, float); -long double jnl(int, long double); float y0f(float); -long double y0l(long double); float y1f(float); -long double y1l(long double); float ynf(int, float); +#endif + +#ifdef _GNU_SOURCE +long double lgammal_r(long double, int*); + +long double j0l(long double); +long double j1l(long double); +long double jnl(int, long double); + +long double y0l(long double); +long double y1l(long double); long double ynl(int, long double); +void sincos(double, double*, double*); +void sincosf(float, float*, float*); +void sincosl(long double, long double*, long double*); + double exp10(double); float exp10f(float); long double exp10l(long double); + double pow10(double); float pow10f(float); long double pow10l(long double); - -double significand(double); -float significandf(float); #endif #ifdef __cplusplus -- 2.20.1