├── jni ├── Android.mk ├── sqlite3 │ └── Android.mk ├── libcrypt │ ├── Makefile │ ├── Android.mk │ ├── crypt.c │ ├── crypt_stub.c │ ├── libcrypt.h │ ├── crypt.h │ ├── Makefile.in │ ├── md5.c │ └── des.c └── python │ └── Android.mk ├── .gitignore ├── standalone_python.sh ├── virtualenv.sh ├── README ├── ldshared ├── bootstrap.sh ├── pip_install.sh ├── package.sh └── patch ├── Python-2.7.2-xcompile.patch └── Python-2.7.2-android.patch /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(call all-subdir-makefiles) 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Python-2.7.2.tgz 2 | Python-host/ 3 | Python/ 4 | build/ 5 | hostpgen 6 | hostpython 7 | prebuilt/ 8 | obj/ 9 | libs/ 10 | release/ 11 | openssl/ 12 | -------------------------------------------------------------------------------- /jni/sqlite3/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_SRC_FILES := sqlite3.c 6 | 7 | LOCAL_MODULE := sqlite3 8 | 9 | include $(BUILD_SHARED_LIBRARY) 10 | -------------------------------------------------------------------------------- /standalone_python.sh: -------------------------------------------------------------------------------- 1 | export PYTHONHOME=/data/data//files/python 2 | export PYTHONPATH=/mnt/sdcard//extras/python:/mnt/sdcard//extras/python/site-packages 3 | export PATH=$PYTHONHOME/bin:$PATH 4 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/data//files/python/lib:/data/data//files/python/lib/python2.7/lib-dynload 5 | -------------------------------------------------------------------------------- /virtualenv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROOTDIR=$(cd `dirname $BASH_SOURCE` && pwd) 4 | 5 | PYTHONHOME="$ROOTDIR/prebuilt" 6 | PYTHONPATH="$PYTHONHOME:$PYTHONHOME/lib/python2.7:$PYTHONHOME/lib/python2.7/site-packages" 7 | LD_LIBRARY_PATH="$PYTHONHOME/lib/python2.7/lib-dynload" 8 | export PATH="$ROOTDIR:$PYTHONHOME/bin:$PATH" 9 | 10 | . virtualenvwrapper.sh 11 | -------------------------------------------------------------------------------- /jni/libcrypt/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for uClibc 2 | # 3 | # Copyright (C) 2000-2005 Erik Andersen 4 | # 5 | # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. 6 | # 7 | 8 | top_srcdir=../ 9 | top_builddir=../ 10 | include $(top_builddir)Rules.mak 11 | all: libs 12 | include Makefile.in 13 | include $(top_srcdir)Makerules 14 | -------------------------------------------------------------------------------- /jni/libcrypt/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := _crypt 6 | LOCAL_MODULE_FILENAME := libcrypt 7 | LOCAL_SRC_FILES := crypt.c \ 8 | des.c \ 9 | md5.c 10 | LOCAL_CFLAGS := -D__USE_GNU -D_LIBC -DHAVE_LIMITS_H -D__GNU_LIBRARY__ 11 | LOCAL_C_EXPORTS := $(LOCAL_PATH) 12 | 13 | include $(BUILD_SHARED_LIBRARY) 14 | -------------------------------------------------------------------------------- /jni/python/Android.mk: -------------------------------------------------------------------------------- 1 | #LOCAL_PATH := $(call my-dir) 2 | 3 | #include $(CLEAR_VARS) 4 | 5 | #LOCAL_MODULE := libpython2.7-prebuilt 6 | #LOCAL_SRC_FILES := /../../build/lib/libpython2.7.so 7 | #LOCAL_EXPORT_C_INCLUDES := \ 8 | $(LOCAL_PATH)/../../build/include/python2.7 \ 9 | $(LOCAL_PATH)/../../Python/Include 10 | #LOCAL_LDLIBS := -llog -lm 11 | 12 | #include $(PREBUILT_SHARED_LIBRARY) 13 | -------------------------------------------------------------------------------- /jni/libcrypt/crypt.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * crypt() for uClibc 4 | * Copyright (C) 2000-2006 by Erik Andersen 5 | * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. 6 | */ 7 | 8 | #define __FORCE_GLIBC 9 | #include "crypt.h" 10 | #include 11 | #include "libcrypt.h" 12 | 13 | char *crypt(const char *key, const char *salt) 14 | { 15 | /* First, check if we are supposed to be using the MD5 replacement 16 | * instead of DES... */ 17 | if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') 18 | return __md5_crypt((unsigned char*)key, (unsigned char*)salt); 19 | else 20 | return __des_crypt((unsigned char*)key, (unsigned char*)salt); 21 | } 22 | -------------------------------------------------------------------------------- /jni/libcrypt/crypt_stub.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * crypt() for uClibc 4 | * Copyright (C) 2008 by Erik Andersen 5 | * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. 6 | */ 7 | 8 | #define __FORCE_GLIBC 9 | #include 10 | #include 11 | #include "libcrypt.h" 12 | #include 13 | 14 | char *crypt(const char *key attribute_unused, const char *salt attribute_unused) 15 | { 16 | __set_errno(ENOSYS); 17 | return NULL; 18 | } 19 | 20 | void 21 | setkey(const char *key attribute_unused) 22 | { 23 | __set_errno(ENOSYS); 24 | } 25 | 26 | void 27 | encrypt(char *block attribute_unused, int flag attribute_unused) 28 | { 29 | __set_errno(ENOSYS); 30 | } 31 | -------------------------------------------------------------------------------- /jni/libcrypt/libcrypt.h: -------------------------------------------------------------------------------- 1 | /* prototypes for internal crypt functions 2 | * 3 | * Copyright (C) 2000-2006 by Erik Andersen 4 | * 5 | * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. 6 | */ 7 | 8 | #ifndef __LIBCRYPT_H__ 9 | #define __LIBCRYPT_H__ 10 | 11 | char *__md5_crypt(const unsigned char *pw, const unsigned char *salt); 12 | char *__des_crypt(const unsigned char *pw, const unsigned char *salt); 13 | 14 | /* shut up gcc-4.x signed warnings */ 15 | #define strcpy(dst,src) strcpy((char*)dst,(char*)src) 16 | #define strlen(s) strlen((char*)s) 17 | #define strncat(dst,src,n) strncat((char*)dst,(char*)src,n) 18 | #define strncmp(s1,s2,n) strncmp((char*)s1,(char*)s2,n) 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Reference: 2 | http://randomsplat.com/id5-cross-compiling-python-for-embedded-linux.html 3 | http://pygame.renpy.org/ 4 | http://code.google.com/p/python-for-android/ 5 | 6 | ./bootstrap.sh 7 | Downloads Python-2.7.2 source 8 | patches Python for android 9 | builds hostpython and hostpgen 10 | 11 | ./build.sh 12 | builds python library for android 13 | 14 | ./package.sh 15 | installs python on android device //thanks to anthony prieur 16 | 17 | ./pip_install.sh 18 | install python packages using pip. 19 | example: 20 | ./pip_install.sh python-twitter 21 | 22 | current status: 23 | Python build finished, but the necessary bits to build these modules were not found: 24 | _bsddb _curses _curses_panel 25 | _tkinter bsddb185 bz2 26 | dbm dl gdbm 27 | imageop linuxaudiodev nis 28 | ossaudiodev readline sunaudiodev 29 | To find the necessary bits, look in setup.py in detect_modules() for the module's name. 30 | 31 | 32 | Failed to build these modules: 33 | _ctypes_test _locale audioop 34 | grp spwd 35 | -------------------------------------------------------------------------------- /ldshared: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import subprocess 5 | 6 | libs = [ ] 7 | objects = [ ] 8 | output = None 9 | 10 | 11 | i = 1 12 | while i < len(sys.argv): 13 | opt = sys.argv[i] 14 | i += 1 15 | 16 | if opt == "-o": 17 | output = sys.argv[i] 18 | i += 1 19 | continue 20 | 21 | if opt.startswith("-l") or opt.startswith("-L"): 22 | libs.append(opt) 23 | continue 24 | 25 | if opt == "-r": 26 | continue 27 | 28 | if opt.startswith("-I"): 29 | continue 30 | 31 | if opt.startswith("-m"): 32 | continue 33 | 34 | if opt.startswith("-f"): 35 | continue 36 | 37 | if opt.startswith("-O"): 38 | continue 39 | 40 | if opt == "--sysroot": 41 | i += 1 42 | continue 43 | 44 | if opt.startswith("-D"): 45 | continue 46 | 47 | if opt.startswith("-"): 48 | print sys.argv 49 | print "Unknown option: ", opt 50 | sys.exit(1) 51 | 52 | objects.append(opt) 53 | 54 | 55 | f = file(output, "w") 56 | f.close() 57 | 58 | f = file(output + ".libs", "w") 59 | f.write(" ".join(libs)) 60 | f.close() 61 | 62 | subprocess.call([ "arm-linux-androideabi-ld", "-r", "-o", output + ".o" ] + objects) 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ROOTDIR=$(dirname $(readlink -f $0)) 4 | 5 | if [ ! -e 'Python-2.7.2.tgz' ]; then 6 | wget http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz 7 | fi 8 | 9 | if [ ! -e 'Python-host' ]; then 10 | tar zxvf Python-2.7.2.tgz 11 | mv Python-2.7.2 Python-host 12 | fi 13 | 14 | if [ ! -e 'Python' ]; then 15 | tar zxvf Python-2.7.2.tgz 16 | mv Python-2.7.2 Python 17 | cd $ROOTDIR/Python 18 | patch -p1 < ../patch/Python-2.7.2-xcompile.patch 19 | patch -p1 < ../patch/Python-2.7.2-android.patch 20 | fi 21 | 22 | if [ ! -e "$ROOTDIR/hostpython" -o ! -e "$ROOTDIR/hostpgen" -o ! -e "$ROOTDIR/prebuilt" ]; then 23 | cd $ROOTDIR/Python-host 24 | ./configure --prefix=$ROOTDIR/prebuilt 25 | make -j4 26 | make install 27 | mv python $ROOTDIR/hostpython 28 | mv Parser/pgen $ROOTDIR/hostpgen 29 | curl http://python-distribute.org/distribute_setup.py | $ROOTDIR/hostpython 30 | curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | $ROOTDIR/hostpython 31 | $ROOTDIR/prebuilt/bin/pip install virtualenv 32 | $ROOTDIR/prebuilt/bin/pip install virtualenvwrapper 33 | make distclean 34 | fi 35 | 36 | cd $ROOTDIR 37 | 38 | if [ ! -e 'openssl' ]; then 39 | git clone https://github.com/guardianproject/openssl-android.git openssl 40 | fi 41 | -------------------------------------------------------------------------------- /jni/libcrypt/crypt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crypt(3) implementation for uClibc 3 | * 4 | * The uClibc Library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * The GNU C Library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with the GNU C Library; if not, write to the Free 16 | * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 17 | * 02111-1307 USA. 18 | * 19 | */ 20 | 21 | #ifndef _CRYPT_H 22 | #define _CRYPT_H 1 23 | 24 | #include 25 | 26 | /* Encrypt characters from KEY using salt to perturb the encryption method. 27 | * If salt begins with "$1$", MD5 hashing is used instead of DES. */ 28 | char *crypt (const char *__key, const char *__salt); 29 | 30 | /* Setup DES tables according KEY. */ 31 | void setkey (const char *__key); 32 | 33 | /* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt 34 | block in place. */ 35 | void encrypt (char *__block, int __edflag); 36 | 37 | #endif /* crypt.h */ 38 | -------------------------------------------------------------------------------- /pip_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | export ROOTDIR=$(dirname $(readlink -f $0)) 4 | export HOSTPYTHON=$ROOTDIR/hostpython 5 | export HOSTPGEN=$ROOTDIR/hostpgen 6 | 7 | export NDK="$HOME/source/android-ndk" 8 | export SDK="$HOME/source/android-sdk/" 9 | export NDKPLATFORM="$NDK/platforms/android-9/arch-arm" 10 | 11 | export PATH="$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/:$NDK:$SDK/tools:$PATH" 12 | export PATH="$ROOTDIR/prebuilt:$PATH" 13 | 14 | export PYVERSION="2.7.2" 15 | 16 | export ARCH="armeabi" 17 | #export ARCH="armeabi-v7a" 18 | 19 | # to override the default optimization, set OFLAG 20 | #export OFLAG="-Os" 21 | #export OFLAG="-O2" 22 | 23 | export CFLAGS="-mandroid $OFLAG -fomit-frame-pointer --sysroot $NDKPLATFORM -DNO_MALLINFO=1 -I$ROOTDIR/build/include/python2.7" 24 | #if [ $ARCH == "armeabi-v7a" ]; then 25 | # CFLAGS+=" -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mthumb" 26 | #fi 27 | export CXXFLAGS="$CFLAGS" 28 | 29 | export CC="arm-linux-androideabi-gcc $CFLAGS" 30 | export CXX="arm-linux-androideabi-g++ $CXXFLAGS" 31 | export AR="arm-linux-androideabi-ar" 32 | export RANLIB="arm-linux-androideabi-ranlib" 33 | export STRIP="arm-linux-androideabi-strip --strip-unneeded" 34 | export BLDSHARED="arm-linux-androideabi-gcc -shared $CFLAGS" 35 | export LDSHARED="$ROOTDIR/ldshared" 36 | export MAKE="make -j4" 37 | 38 | export PYTHONHOME="$ROOTDIR/prebuilt" 39 | export PYTHONPATH="$PYTHONHOME:$PYTHONHOME/lib/python2.7" 40 | export LD_LIBRARY_PATH="$PYTHONHOME/lib/python2.7/lib-dynload" 41 | export PATH="$PYTHONHOME/bin:$PATH" 42 | 43 | export PIP_REQUIRE_VIRTUALENV=true 44 | export PIP_RESPECT_VIRTUALENV=true 45 | 46 | pip install \ 47 | --install-option="--prefix=$VIRTUAL_ENV" \ 48 | $@ 49 | -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ $# -ne 1 ]; then 4 | echo "Usage: ./package.sh " 5 | exit 0 6 | fi 7 | 8 | export ROOTDIR=$(dirname $(readlink -f $0)) 9 | export PACKAGE=$1 10 | 11 | yes | rm -r $ROOTDIR/release/$PACKAGE 12 | 13 | mkdir -p $ROOTDIR/release/$PACKAGE/files/python/bin 14 | mkdir -p $ROOTDIR/release/$PACKAGE/files/python/include 15 | mkdir -p $ROOTDIR/release/$PACKAGE/files/python/lib/python2.7/lib-dynload 16 | mkdir -p $ROOTDIR/release/$PACKAGE/files/python/lib/python2.7/config 17 | mkdir -p $ROOTDIR/release/$PACKAGE/extras/python 18 | 19 | cat $ROOTDIR/standalone_python.sh | sed -e s"//$PACKAGE/g" > $ROOTDIR/release/$PACKAGE/files/python/bin/standalone_python.sh 20 | cp -r $ROOTDIR/build/bin/python $ROOTDIR/release/$PACKAGE/files/python/bin/python 21 | cp -r $ROOTDIR/build/include/* $ROOTDIR/release/$PACKAGE/files/python/include/ 22 | cp -r $ROOTDIR/build/lib/libpython2.7.so $ROOTDIR/release/$PACKAGE/files/python/lib/libpython2.7.so 23 | cp -r $ROOTDIR/libs/armeabi/libsqlite3.so $ROOTDIR/release/$PACKAGE/files/python/lib/libsqlite3.so 24 | cp -r $ROOTDIR/build/lib/python2.7/lib-dynload/* $ROOTDIR/release/$PACKAGE/files/python/lib/python2.7/lib-dynload/ 25 | cp -r $ROOTDIR/build/lib/python2.7/config/* $ROOTDIR/release/$PACKAGE/files/python/lib/python2.7/config/ 26 | cp -r $ROOTDIR/build/lib/python2.7/* $ROOTDIR/release/$PACKAGE/extras/python/ 27 | 28 | #virtualenv 29 | cp -r $VIRTUAL_ENV/lib/python2.7/site-packages $ROOTDIR/release/$PACKAGE/files/python/lib/python2.7/site-packages 30 | 31 | cd $ROOTDIR/release/$PACKAGE/extras/python/ 32 | rm `find . | grep -v "so$\|py$"` 33 | rm -r `find . | grep test` 34 | 35 | adb push $ROOTDIR/release/$PACKAGE/files/ /data/data/$PACKAGE/files 36 | adb push $ROOTDIR/release/$PACKAGE/extras/ /mnt/sdcard/$PACKAGE/extras 37 | -------------------------------------------------------------------------------- /jni/libcrypt/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile for uClibc 2 | # 3 | # Copyright (C) 2000-2008 Erik Andersen 4 | # 5 | # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. 6 | # 7 | 8 | subdirs += libcrypt 9 | 10 | CFLAGS-libcrypt := -DNOT_IN_libc -DIS_IN_libcrypt $(SSP_ALL_CFLAGS) 11 | 12 | LDFLAGS-libcrypt.so := $(LDFLAGS) 13 | 14 | LIBS-libcrypt.so := $(LIBS) 15 | 16 | libcrypt_FULL_NAME := libcrypt-$(VERSION).so 17 | 18 | libcrypt_DIR := $(top_srcdir)libcrypt 19 | libcrypt_OUT := $(top_builddir)libcrypt 20 | 21 | libcrypt_SRC-y := 22 | libcrypt_SRC-$(UCLIBC_HAS_CRYPT_IMPL) += crypt.c des.c md5.c 23 | libcrypt_SRC-$(UCLIBC_HAS_CRYPT_STUB) += crypt_stub.c 24 | 25 | libcrypt_SRC := $(addprefix $(libcrypt_DIR)/,$(libcrypt_SRC-y)) 26 | libcrypt_OBJ := $(patsubst $(libcrypt_DIR)/%.c,$(libcrypt_OUT)/%.o,$(libcrypt_SRC)) 27 | 28 | ifeq ($(DOPIC),y) 29 | libcrypt-a-y := $(libcrypt_OBJ:.o=.os) 30 | else 31 | libcrypt-a-y := $(libcrypt_OBJ) 32 | endif 33 | libcrypt-so-y := $(libcrypt_OBJ:.o=.os) 34 | 35 | lib-a-$(UCLIBC_HAS_CRYPT) += $(top_builddir)lib/libcrypt.a 36 | lib-so-$(UCLIBC_HAS_CRYPT) += $(top_builddir)lib/libcrypt.so 37 | objclean-y += CLEAN_libcrypt 38 | 39 | ifeq ($(DOMULTI),n) 40 | ifeq ($(DOPIC),y) 41 | $(top_builddir)lib/libcrypt.so: $(top_builddir)lib/libcrypt.a $(libc.depend) 42 | else 43 | $(top_builddir)lib/libcrypt.so: $(libcrypt_OUT)/libcrypt_so.a $(libc.depend) 44 | endif 45 | $(call link.so,$(libcrypt_FULL_NAME),$(ABI_VERSION)) 46 | else 47 | $(top_builddir)lib/libcrypt.so: $(libcrypt_OUT)/libcrypt.oS | $(libc.depend) 48 | $(call linkm.so,$(libcrypt_FULL_NAME),$(ABI_VERSION)) 49 | endif 50 | 51 | $(libcrypt_OUT)/libcrypt_so.a: $(libcrypt-so-y) 52 | $(Q)$(RM) $@ 53 | $(do_ar) 54 | 55 | $(libcrypt_OUT)/libcrypt.oS: $(libcrypt_SRC) 56 | $(Q)$(RM) $@ 57 | $(compile-m) 58 | 59 | $(top_builddir)lib/libcrypt.a: $(libcrypt-a-y) 60 | $(Q)$(INSTALL) -d $(dir $@) 61 | $(Q)$(RM) $@ 62 | $(do_ar) 63 | 64 | CLEAN_libcrypt: 65 | $(do_rm) $(addprefix $(libcrypt_OUT)/*., o os oS a) 66 | -------------------------------------------------------------------------------- /patch/Python-2.7.2-xcompile.patch: -------------------------------------------------------------------------------- 1 | diff -urN Python-2.7.2/configure ltib/rpm/BUILD/Python-2.7.2/configure 2 | --- Python-2.7.2/configure 2011-06-11 11:46:28.000000000 -0400 3 | +++ ltib/rpm/BUILD/Python-2.7.2/configure 2011-11-14 12:10:41.011373524 -0500 4 | @@ -13673,7 +13673,7 @@ 5 | $as_echo_n "(cached) " >&6 6 | else 7 | if test "$cross_compiling" = yes; then : 8 | - ac_cv_have_long_long_format=no 9 | + ac_cv_have_long_long_format="cross -- assuming yes" 10 | else 11 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext 12 | /* end confdefs.h. */ 13 | @@ -13725,7 +13725,7 @@ 14 | $as_echo "$ac_cv_have_long_long_format" >&6; } 15 | fi 16 | 17 | -if test "$ac_cv_have_long_long_format" = yes 18 | +if test "$ac_cv_have_long_long_format" != no 19 | then 20 | 21 | $as_echo "#define PY_FORMAT_LONG_LONG \"ll\"" >>confdefs.h 22 | diff -urN Python-2.7.2/Makefile.pre.in ltib/rpm/BUILD/Python-2.7.2/Makefile.pre.in 23 | --- Python-2.7.2/Makefile.pre.in 2011-06-11 11:46:26.000000000 -0400 24 | +++ ltib/rpm/BUILD/Python-2.7.2/Makefile.pre.in 2011-11-14 12:10:41.013373444 -0500 25 | @@ -182,6 +182,7 @@ 26 | 27 | PYTHON= python$(EXE) 28 | BUILDPYTHON= python$(BUILDEXE) 29 | +HOSTPYTHON= ./$(BUILDPYTHON) 30 | 31 | # The task to run while instrument when building the profile-opt target 32 | PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck 33 | @@ -215,6 +216,8 @@ 34 | # Parser 35 | PGEN= Parser/pgen$(EXE) 36 | 37 | +HOSTPGEN= $(PGEN) 38 | + 39 | POBJS= \ 40 | Parser/acceler.o \ 41 | Parser/grammar1.o \ 42 | @@ -407,8 +410,8 @@ 43 | # Build the shared modules 44 | sharedmods: $(BUILDPYTHON) 45 | @case $$MAKEFLAGS in \ 46 | - *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \ 47 | - *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \ 48 | + *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' PYTHONXCPREFIX='$(DESTDIR)$(prefix)' $(HOSTPYTHON) -E $(srcdir)/setup.py -q build;; \ 49 | + *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' PYTHONXCPREFIX='$(DESTDIR)$(prefix)' $(HOSTPYTHON) -E $(srcdir)/setup.py build;; \ 50 | esac 51 | 52 | # Build static library 53 | @@ -542,7 +545,7 @@ 54 | $(GRAMMAR_H) $(GRAMMAR_C): Parser/pgen.stamp 55 | Parser/pgen.stamp: $(PGEN) $(GRAMMAR_INPUT) 56 | -@$(INSTALL) -d Include 57 | - $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) 58 | + -$(HOSTPGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) 59 | -touch Parser/pgen.stamp 60 | 61 | $(PGEN): $(PGENOBJS) 62 | @@ -925,26 +928,26 @@ 63 | done; \ 64 | done 65 | $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt 66 | - PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 67 | - ./$(BUILDPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ 68 | + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 69 | + $(HOSTPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ 70 | -d $(LIBDEST) -f \ 71 | -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ 72 | $(DESTDIR)$(LIBDEST) 73 | - PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 74 | - ./$(BUILDPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ 75 | + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 76 | + $(HOSTPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ 77 | -d $(LIBDEST) -f \ 78 | -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ 79 | $(DESTDIR)$(LIBDEST) 80 | -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 81 | - ./$(BUILDPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ 82 | + $(HOSTPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ 83 | -d $(LIBDEST)/site-packages -f \ 84 | -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages 85 | -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 86 | - ./$(BUILDPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ 87 | + $(HOSTPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ 88 | -d $(LIBDEST)/site-packages -f \ 89 | -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages 90 | -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 91 | - ./$(BUILDPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" 92 | + $(HOSTPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" 93 | 94 | # Create the PLATDIR source directory, if one wasn't distributed.. 95 | $(srcdir)/Lib/$(PLATDIR): 96 | @@ -1049,7 +1052,9 @@ 97 | # Install the dynamically loadable modules 98 | # This goes into $(exec_prefix) 99 | sharedinstall: sharedmods 100 | - $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \ 101 | + CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ 102 | + $(RUNSHARED) $(HOSTPYTHON) -E $(srcdir)/setup.py install \ 103 | + --skip-build \ 104 | --prefix=$(prefix) \ 105 | --install-scripts=$(BINDIR) \ 106 | --install-platlib=$(DESTSHARED) \ 107 | diff -urN Python-2.7.2/setup.py ltib/rpm/BUILD/Python-2.7.2/setup.py 108 | --- Python-2.7.2/setup.py 2011-06-11 11:46:28.000000000 -0400 109 | +++ ltib/rpm/BUILD/Python-2.7.2/setup.py 2011-11-14 12:13:02.175758583 -0500 110 | @@ -145,6 +145,7 @@ 111 | def __init__(self, dist): 112 | build_ext.__init__(self, dist) 113 | self.failed = [] 114 | + self.cross_compile = os.environ.get('CROSS_COMPILE_TARGET') == 'yes' 115 | 116 | def build_extensions(self): 117 | 118 | @@ -278,6 +279,14 @@ 119 | (ext.name, sys.exc_info()[1])) 120 | self.failed.append(ext.name) 121 | return 122 | + 123 | + # Import check will not work when cross-compiling. 124 | + if os.environ.has_key('PYTHONXCPREFIX'): 125 | + self.announce( 126 | + 'WARNING: skipping import check for cross-compiled: "%s"' % 127 | + ext.name) 128 | + return 129 | + 130 | # Workaround for Mac OS X: The Carbon-based modules cannot be 131 | # reliably imported into a command-line Python 132 | if 'Carbon' in ext.extra_link_args: 133 | @@ -369,9 +378,10 @@ 134 | 135 | def detect_modules(self): 136 | # Ensure that /usr/local is always used 137 | - add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') 138 | - add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') 139 | - self.add_multiarch_paths() 140 | + if not self.cross_compile: 141 | + add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') 142 | + add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') 143 | + self.add_multiarch_paths() 144 | 145 | # Add paths specified in the environment variables LDFLAGS and 146 | # CPPFLAGS for header and library files. 147 | @@ -408,7 +418,8 @@ 148 | add_dir_to_list(dir_list, directory) 149 | 150 | if os.path.normpath(sys.prefix) != '/usr' \ 151 | - and not sysconfig.get_config_var('PYTHONFRAMEWORK'): 152 | + and not sysconfig.get_config_var('PYTHONFRAMEWORK') \ 153 | + and not self.cross_compile: 154 | # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework 155 | # (PYTHONFRAMEWORK is set) to avoid # linking problems when 156 | # building a framework with different architectures than 157 | @@ -426,11 +437,14 @@ 158 | # lib_dirs and inc_dirs are used to search for files; 159 | # if a file is found in one of those directories, it can 160 | # be assumed that no additional -I,-L directives are needed. 161 | - lib_dirs = self.compiler.library_dirs + [ 162 | - '/lib64', '/usr/lib64', 163 | - '/lib', '/usr/lib', 164 | - ] 165 | - inc_dirs = self.compiler.include_dirs + ['/usr/include'] 166 | + lib_dirs = self.compiler.library_dirs 167 | + inc_dirs = self.compiler.include_dirs 168 | + if not self.cross_compile: 169 | + lib_dirs += [ 170 | + '/lib64', '/usr/lib64', 171 | + '/lib', '/usr/lib', 172 | + ] 173 | + inc_dirs += ['/usr/include'] 174 | exts = [] 175 | missing = [] 176 | 177 | @@ -1864,8 +1878,15 @@ 178 | 179 | # Pass empty CFLAGS because we'll just append the resulting 180 | # CFLAGS to Python's; -g or -O2 is to be avoided. 181 | - cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \ 182 | - % (ffi_builddir, ffi_srcdir, " ".join(config_args)) 183 | + if self.cross_compile: 184 | + cmd = "cd %s && env CFLAGS='' %s/configure --host=%s --build=%s %s" \ 185 | + % (ffi_builddir, ffi_srcdir, 186 | + os.environ.get('HOSTARCH'), 187 | + os.environ.get('BUILDARCH'), 188 | + " ".join(config_args)) 189 | + else: 190 | + cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \ 191 | + % (ffi_builddir, ffi_srcdir, " ".join(config_args)) 192 | 193 | res = os.system(cmd) 194 | if res or not os.path.exists(ffi_configfile): 195 | -------------------------------------------------------------------------------- /patch/Python-2.7.2-android.patch: -------------------------------------------------------------------------------- 1 | diff -Naur Python-2.7.2orig//Modules/_multiprocessing/multiprocessing.c Python-2.7.2/Modules/_multiprocessing/multiprocessing.c 2 | --- Python-2.7.2orig//Modules/_multiprocessing/multiprocessing.c 2011-06-11 10:46:27.000000000 -0500 3 | +++ Python-2.7.2/Modules/_multiprocessing/multiprocessing.c 2011-12-12 23:18:45.000000000 -0600 4 | @@ -122,7 +122,7 @@ 5 | cmsg->cmsg_type = SCM_RIGHTS; 6 | cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 7 | msg.msg_controllen = cmsg->cmsg_len; 8 | - *CMSG_DATA(cmsg) = fd; 9 | + *(int*)CMSG_DATA(cmsg) = fd; 10 | 11 | Py_BEGIN_ALLOW_THREADS 12 | res = sendmsg(conn, &msg, 0); 13 | @@ -165,7 +165,7 @@ 14 | if (res < 0) 15 | return PyErr_SetFromErrno(PyExc_OSError); 16 | 17 | - fd = *CMSG_DATA(cmsg); 18 | + fd = *(int*)CMSG_DATA(cmsg); 19 | return Py_BuildValue("i", fd); 20 | } 21 | 22 | diff -Naur Python-2.7.2orig//Modules/posixmodule.c Python-2.7.2/Modules/posixmodule.c 23 | --- Python-2.7.2orig//Modules/posixmodule.c 2011-06-11 10:46:27.000000000 -0500 24 | +++ Python-2.7.2/Modules/posixmodule.c 2011-12-12 23:18:45.000000000 -0600 25 | @@ -3787,13 +3787,6 @@ 26 | slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ 27 | if (slave_fd < 0) 28 | return posix_error(); 29 | -#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) 30 | - ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ 31 | - ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ 32 | -#ifndef __hpux 33 | - ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ 34 | -#endif /* __hpux */ 35 | -#endif /* HAVE_CYGWIN */ 36 | #endif /* HAVE_OPENPTY */ 37 | 38 | return Py_BuildValue("(ii)", master_fd, slave_fd); 39 | diff -Naur Python-2.7.2orig//Modules/pwdmodule.c Python-2.7.2/Modules/pwdmodule.c 40 | --- Python-2.7.2orig//Modules/pwdmodule.c 2011-06-11 10:46:27.000000000 -0500 41 | +++ Python-2.7.2/Modules/pwdmodule.c 2011-12-12 23:18:45.000000000 -0600 42 | @@ -75,11 +75,7 @@ 43 | #endif 44 | SETI(setIndex++, p->pw_uid); 45 | SETI(setIndex++, p->pw_gid); 46 | -#ifdef __VMS 47 | SETS(setIndex++, ""); 48 | -#else 49 | - SETS(setIndex++, p->pw_gecos); 50 | -#endif 51 | SETS(setIndex++, p->pw_dir); 52 | SETS(setIndex++, p->pw_shell); 53 | 54 | diff -Naur Python-2.7.2orig//Modules/termios.c Python-2.7.2/Modules/termios.c 55 | --- Python-2.7.2orig//Modules/termios.c 2011-06-11 10:46:27.000000000 -0500 56 | +++ Python-2.7.2/Modules/termios.c 2011-12-12 23:18:45.000000000 -0600 57 | @@ -227,6 +227,7 @@ 58 | return Py_None; 59 | } 60 | 61 | +#if 0 // No tcdrain defined for Android. 62 | PyDoc_STRVAR(termios_tcdrain__doc__, 63 | "tcdrain(fd) -> None\n\ 64 | \n\ 65 | @@ -246,6 +247,7 @@ 66 | Py_INCREF(Py_None); 67 | return Py_None; 68 | } 69 | +#endif 70 | 71 | PyDoc_STRVAR(termios_tcflush__doc__, 72 | "tcflush(fd, queue) -> None\n\ 73 | @@ -301,8 +303,8 @@ 74 | METH_VARARGS, termios_tcsetattr__doc__}, 75 | {"tcsendbreak", termios_tcsendbreak, 76 | METH_VARARGS, termios_tcsendbreak__doc__}, 77 | - {"tcdrain", termios_tcdrain, 78 | - METH_VARARGS, termios_tcdrain__doc__}, 79 | + // {"tcdrain", termios_tcdrain, 80 | + // METH_VARARGS, termios_tcdrain__doc__}, 81 | {"tcflush", termios_tcflush, 82 | METH_VARARGS, termios_tcflush__doc__}, 83 | {"tcflow", termios_tcflow, 84 | diff -Naur Python-2.7.2orig//Objects/stringlib/formatter.h Python-2.7.2/Objects/stringlib/formatter.h 85 | --- Python-2.7.2orig//Objects/stringlib/formatter.h 2011-06-11 10:46:27.000000000 -0500 86 | +++ Python-2.7.2/Objects/stringlib/formatter.h 2011-12-12 23:18:45.000000000 -0600 87 | @@ -639,13 +639,7 @@ 88 | get_locale_info(int type, LocaleInfo *locale_info) 89 | { 90 | switch (type) { 91 | - case LT_CURRENT_LOCALE: { 92 | - struct lconv *locale_data = localeconv(); 93 | - locale_info->decimal_point = locale_data->decimal_point; 94 | - locale_info->thousands_sep = locale_data->thousands_sep; 95 | - locale_info->grouping = locale_data->grouping; 96 | - break; 97 | - } 98 | + case LT_CURRENT_LOCALE: 99 | case LT_DEFAULT_LOCALE: 100 | locale_info->decimal_point = "."; 101 | locale_info->thousands_sep = ","; 102 | diff -Naur Python-2.7.2orig//Objects/stringlib/localeutil.h Python-2.7.2/Objects/stringlib/localeutil.h 103 | --- Python-2.7.2orig//Objects/stringlib/localeutil.h 2011-06-11 10:46:27.000000000 -0500 104 | +++ Python-2.7.2/Objects/stringlib/localeutil.h 2011-12-12 23:18:45.000000000 -0600 105 | @@ -202,9 +202,8 @@ 106 | Py_ssize_t n_digits, 107 | Py_ssize_t min_width) 108 | { 109 | - struct lconv *locale_data = localeconv(); 110 | - const char *grouping = locale_data->grouping; 111 | - const char *thousands_sep = locale_data->thousands_sep; 112 | + const char *grouping = "\3\0"; 113 | + const char *thousands_sep = ","; 114 | 115 | return _Py_InsertThousandsGrouping(buffer, n_buffer, digits, n_digits, 116 | min_width, grouping, thousands_sep); 117 | diff -Naur Python-2.7.2orig//Python/pystrtod.c Python-2.7.2/Python/pystrtod.c 118 | --- Python-2.7.2orig//Python/pystrtod.c 2011-06-11 10:46:27.000000000 -0500 119 | +++ Python-2.7.2/Python/pystrtod.c 2011-12-12 23:18:45.000000000 -0600 120 | @@ -138,8 +138,7 @@ 121 | 122 | fail_pos = NULL; 123 | 124 | - locale_data = localeconv(); 125 | - decimal_point = locale_data->decimal_point; 126 | + decimal_point = "."; 127 | decimal_point_len = strlen(decimal_point); 128 | 129 | assert(decimal_point_len != 0); 130 | @@ -375,8 +374,7 @@ 131 | Py_LOCAL_INLINE(void) 132 | change_decimal_from_locale_to_dot(char* buffer) 133 | { 134 | - struct lconv *locale_data = localeconv(); 135 | - const char *decimal_point = locale_data->decimal_point; 136 | + const char *decimal_point = "."; 137 | 138 | if (decimal_point[0] != '.' || decimal_point[1] != 0) { 139 | size_t decimal_point_len = strlen(decimal_point); 140 | diff -Naur Python-2.7.2orig//setup.py Python-2.7.2/setup.py 141 | --- Python-2.7.2orig//setup.py 2011-12-06 23:46:54.000000000 -0600 142 | +++ Python-2.7.2/setup.py 2011-12-12 23:18:52.000000000 -0600 143 | @@ -703,11 +703,13 @@ 144 | 145 | # crypt module. 146 | 147 | - if self.compiler.find_library_file(lib_dirs, 'crypt'): 148 | + crypt_libdir = ['../obj/local/'+os.environ['ARCH']] 149 | + 150 | + if self.compiler.find_library_file(crypt_libdir, 'crypt'): 151 | libs = ['crypt'] 152 | else: 153 | libs = [] 154 | - exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) ) 155 | + exts.append( Extension('crypt', ['cryptmodule.c'], library_dirs=crypt_libdir, libraries=libs) ) 156 | 157 | # CSV files 158 | exts.append( Extension('_csv', ['_csv.c']) ) 159 | @@ -733,6 +735,9 @@ 160 | '/usr/contrib/ssl/lib/' 161 | ] ) 162 | 163 | + ssl_incs = ['../openssl/include'] 164 | + ssl_libs = ['../openssl/obj/local/'+os.environ['ARCH']] 165 | + 166 | if (ssl_incs is not None and 167 | ssl_libs is not None): 168 | exts.append( Extension('_ssl', ['_ssl.c'], 169 | @@ -767,8 +772,8 @@ 170 | 171 | min_openssl_ver = 0x00907000 172 | have_any_openssl = ssl_incs is not None and ssl_libs is not None 173 | - have_usable_openssl = (have_any_openssl and 174 | - openssl_ver >= min_openssl_ver) 175 | + have_usable_openssl = (have_any_openssl and True) 176 | + #openssl_ver >= min_openssl_ver) 177 | 178 | if have_any_openssl: 179 | if have_usable_openssl: 180 | @@ -1075,6 +1080,9 @@ 181 | if sqlite_libfile: 182 | sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))] 183 | 184 | + sqlite_incdir = '../jni/sqlite3' 185 | + sqlite_libdir = ['../obj/local/'+os.environ['ARCH']] 186 | + 187 | if sqlite_incdir and sqlite_libdir: 188 | sqlite_srcs = ['_sqlite/cache.c', 189 | '_sqlite/connection.c', 190 | @@ -1302,7 +1310,8 @@ 191 | # 192 | # You can upgrade zlib to version 1.1.4 yourself by going to 193 | # http://www.gzip.org/zlib/ 194 | - zlib_inc = find_file('zlib.h', [], inc_dirs) 195 | + zlib_inc = [os.path.join(os.environ['NDKPLATFORM'], 'usr/include')] 196 | + zlib_libdir = [os.path.join(os.environ['NDKPLATFORM'], 'usr/lib')] 197 | have_zlib = False 198 | if zlib_inc is not None: 199 | zlib_h = zlib_inc[0] + '/zlib.h' 200 | @@ -1317,12 +1326,13 @@ 201 | version = line.split()[2] 202 | break 203 | if version >= version_req: 204 | - if (self.compiler.find_library_file(lib_dirs, 'z')): 205 | + if (self.compiler.find_library_file(zlib_libdir, 'z')): 206 | if sys.platform == "darwin": 207 | zlib_extra_link_args = ('-Wl,-search_paths_first',) 208 | else: 209 | zlib_extra_link_args = () 210 | exts.append( Extension('zlib', ['zlibmodule.c'], 211 | + library_dirs=zlib_libdir, 212 | libraries = ['z'], 213 | extra_link_args = zlib_extra_link_args)) 214 | have_zlib = True 215 | -------------------------------------------------------------------------------- /jni/libcrypt/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm 3 | * 4 | * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 5 | * rights reserved. 6 | * 7 | * License to copy and use this software is granted provided that it 8 | * is identified as the "RSA Data Security, Inc. MD5 Message-Digest 9 | * Algorithm" in all material mentioning or referencing this software 10 | * or this function. 11 | * 12 | * License is also granted to make and use derivative works provided 13 | * that such works are identified as "derived from the RSA Data 14 | * Security, Inc. MD5 Message-Digest Algorithm" in all material 15 | * mentioning or referencing the derived work. 16 | * 17 | * RSA Data Security, Inc. makes no representations concerning either 18 | * the merchantability of this software or the suitability of this 19 | * software for any particular purpose. It is provided "as is" 20 | * without express or implied warranty of any kind. 21 | * 22 | * These notices must be retained in any copies of any part of this 23 | * documentation and/or software. 24 | * 25 | * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $ 26 | * 27 | * This code is the same as the code published by RSA Inc. It has been 28 | * edited for clarity and style only. 29 | * 30 | * ---------------------------------------------------------------------------- 31 | * The md5_crypt() function was taken from freeBSD's libcrypt and contains 32 | * this license: 33 | * "THE BEER-WARE LICENSE" (Revision 42): 34 | * wrote this file. As long as you retain this notice you 35 | * can do whatever you want with this stuff. If we meet some day, and you think 36 | * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 37 | * 38 | * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $ 39 | * 40 | * ---------------------------------------------------------------------------- 41 | * On April 19th, 2001 md5_crypt() was modified to make it reentrant 42 | * by Erik Andersen 43 | * 44 | * 45 | * June 28, 2001 Manuel Novoa III 46 | * 47 | * "Un-inlined" code using loops and static const tables in order to 48 | * reduce generated code size (on i386 from approx 4k to approx 2.5k). 49 | * 50 | * June 29, 2001 Manuel Novoa III 51 | * 52 | * Completely removed static PADDING array. 53 | * 54 | * Reintroduced the loop unrolling in MD5_Transform and added the 55 | * MD5_SIZE_OVER_SPEED option for configurability. Define below as: 56 | * 0 fully unrolled loops 57 | * 1 partially unrolled (4 ops per loop) 58 | * 2 no unrolling -- introduces the need to swap 4 variables (slow) 59 | * 3 no unrolling and all 4 loops merged into one with switch 60 | * in each loop (glacial) 61 | * On i386, sizes are roughly (-Os -fno-builtin): 62 | * 0: 3k 1: 2.5k 2: 2.2k 3: 2k 63 | * 64 | * 65 | * Since SuSv3 does not require crypt_r, modified again August 7, 2002 66 | * by Erik Andersen to remove reentrance stuff... 67 | */ 68 | 69 | /* 70 | * Valid values are 1 (fastest/largest) to 3 (smallest/slowest). 71 | */ 72 | #define MD5_SIZE_OVER_SPEED 3 73 | 74 | /**********************************************************************/ 75 | 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include "crypt.h" 81 | #include 82 | #include "libcrypt.h" 83 | 84 | /* MD5 context. */ 85 | struct MD5Context { 86 | u_int32_t state[4]; /* state (ABCD) */ 87 | u_int32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ 88 | unsigned char buffer[64]; /* input buffer */ 89 | }; 90 | 91 | static void __md5_Init (struct MD5Context *); 92 | static void __md5_Update (struct MD5Context *, const unsigned char *, unsigned int); 93 | static void __md5_Pad (struct MD5Context *); 94 | static void __md5_Final (unsigned char [16], struct MD5Context *); 95 | static void __md5_Transform __P((u_int32_t [4], const unsigned char [64])); 96 | 97 | 98 | #define MD5_MAGIC_STR "$1$" 99 | #define MD5_MAGIC_LEN (sizeof(MD5_MAGIC_STR) - 1) 100 | static const unsigned char __md5__magic[] = MD5_MAGIC_STR; 101 | static const unsigned char __md5_itoa64[] = /* 0 ... 63 => ascii - 64 */ 102 | "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 103 | 104 | 105 | #ifdef i386 106 | #define __md5_Encode memcpy 107 | #define __md5_Decode memcpy 108 | #else /* i386 */ 109 | 110 | /* 111 | * __md5_Encodes input (u_int32_t) into output (unsigned char). Assumes len is 112 | * a multiple of 4. 113 | */ 114 | 115 | static void 116 | __md5_Encode (unsigned char *output, u_int32_t *input, unsigned int len) 117 | { 118 | unsigned int i, j; 119 | 120 | for (i = 0, j = 0; j < len; i++, j += 4) { 121 | output[j] = (unsigned char)(input[i] & 0xff); 122 | output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 123 | output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 124 | output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 125 | } 126 | } 127 | 128 | /* 129 | * __md5_Decodes input (unsigned char) into output (u_int32_t). Assumes len is 130 | * a multiple of 4. 131 | */ 132 | 133 | static void 134 | __md5_Decode (u_int32_t *output, const unsigned char *input, unsigned int len) 135 | { 136 | unsigned int i, j; 137 | 138 | for (i = 0, j = 0; j < len; i++, j += 4) 139 | output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) | 140 | (((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24); 141 | } 142 | #endif /* i386 */ 143 | 144 | /* F, G, H and I are basic MD5 functions. */ 145 | #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 146 | #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 147 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 148 | #define I(x, y, z) ((y) ^ ((x) | (~z))) 149 | 150 | /* ROTATE_LEFT rotates x left n bits. */ 151 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 152 | 153 | /* 154 | * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 155 | * Rotation is separate from addition to prevent recomputation. 156 | */ 157 | #define FF(a, b, c, d, x, s, ac) { \ 158 | (a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ 159 | (a) = ROTATE_LEFT ((a), (s)); \ 160 | (a) += (b); \ 161 | } 162 | #define GG(a, b, c, d, x, s, ac) { \ 163 | (a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ 164 | (a) = ROTATE_LEFT ((a), (s)); \ 165 | (a) += (b); \ 166 | } 167 | #define HH(a, b, c, d, x, s, ac) { \ 168 | (a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ 169 | (a) = ROTATE_LEFT ((a), (s)); \ 170 | (a) += (b); \ 171 | } 172 | #define II(a, b, c, d, x, s, ac) { \ 173 | (a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ 174 | (a) = ROTATE_LEFT ((a), (s)); \ 175 | (a) += (b); \ 176 | } 177 | 178 | /* MD5 initialization. Begins an MD5 operation, writing a new context. */ 179 | 180 | static void __md5_Init (struct MD5Context *context) 181 | { 182 | context->count[0] = context->count[1] = 0; 183 | 184 | /* Load magic initialization constants. */ 185 | context->state[0] = 0x67452301; 186 | context->state[1] = 0xefcdab89; 187 | context->state[2] = 0x98badcfe; 188 | context->state[3] = 0x10325476; 189 | } 190 | 191 | /* 192 | * MD5 block update operation. Continues an MD5 message-digest 193 | * operation, processing another message block, and updating the 194 | * context. 195 | */ 196 | 197 | static void __md5_Update ( struct MD5Context *context, const unsigned char *input, unsigned int inputLen) 198 | { 199 | unsigned int i, idx, partLen; 200 | 201 | /* Compute number of bytes mod 64 */ 202 | idx = (unsigned int)((context->count[0] >> 3) & 0x3F); 203 | 204 | /* Update number of bits */ 205 | if ((context->count[0] += ((u_int32_t)inputLen << 3)) 206 | < ((u_int32_t)inputLen << 3)) 207 | context->count[1]++; 208 | context->count[1] += ((u_int32_t)inputLen >> 29); 209 | 210 | partLen = 64 - idx; 211 | 212 | /* Transform as many times as possible. */ 213 | if (inputLen >= partLen) { 214 | memcpy((void *)&context->buffer[idx], (const void *)input, 215 | partLen); 216 | __md5_Transform (context->state, context->buffer); 217 | 218 | for (i = partLen; i + 63 < inputLen; i += 64) 219 | __md5_Transform (context->state, &input[i]); 220 | 221 | idx = 0; 222 | } 223 | else 224 | i = 0; 225 | 226 | /* Buffer remaining input */ 227 | memcpy ((void *)&context->buffer[idx], (const void *)&input[i], 228 | inputLen-i); 229 | } 230 | 231 | /* 232 | * MD5 padding. Adds padding followed by original length. 233 | */ 234 | 235 | static void __md5_Pad ( struct MD5Context *context) 236 | { 237 | unsigned char bits[8]; 238 | unsigned int idx, padLen; 239 | unsigned char PADDING[64]; 240 | 241 | memset(PADDING, 0, sizeof(PADDING)); 242 | PADDING[0] = 0x80; 243 | 244 | /* Save number of bits */ 245 | __md5_Encode (bits, context->count, 8); 246 | 247 | /* Pad out to 56 mod 64. */ 248 | idx = (unsigned int)((context->count[0] >> 3) & 0x3f); 249 | padLen = (idx < 56) ? (56 - idx) : (120 - idx); 250 | __md5_Update (context, PADDING, padLen); 251 | 252 | /* Append length (before padding) */ 253 | __md5_Update (context, bits, 8); 254 | } 255 | 256 | /* 257 | * MD5 finalization. Ends an MD5 message-digest operation, writing the 258 | * the message digest and zeroizing the context. 259 | */ 260 | 261 | static void __md5_Final ( unsigned char digest[16], struct MD5Context *context) 262 | { 263 | /* Do padding. */ 264 | __md5_Pad (context); 265 | 266 | /* Store state in digest */ 267 | __md5_Encode (digest, context->state, 16); 268 | 269 | /* Zeroize sensitive information. */ 270 | memset ((void *)context, 0, sizeof (*context)); 271 | } 272 | 273 | /* MD5 basic transformation. Transforms state based on block. */ 274 | 275 | static void __md5_Transform (u_int32_t state[4], const unsigned char block[64]) 276 | { 277 | u_int32_t a, b, c, d, x[16]; 278 | #if MD5_SIZE_OVER_SPEED > 1 279 | u_int32_t temp; 280 | const char *ps; 281 | 282 | static const char S[] = { 283 | 7, 12, 17, 22, 284 | 5, 9, 14, 20, 285 | 4, 11, 16, 23, 286 | 6, 10, 15, 21 287 | }; 288 | #endif /* MD5_SIZE_OVER_SPEED > 1 */ 289 | 290 | #if MD5_SIZE_OVER_SPEED > 0 291 | const u_int32_t *pc; 292 | const char *pp; 293 | int i; 294 | 295 | static const u_int32_t C[] = { 296 | /* round 1 */ 297 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 298 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 299 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 300 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 301 | /* round 2 */ 302 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 303 | 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 304 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 305 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 306 | /* round 3 */ 307 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 308 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 309 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 310 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 311 | /* round 4 */ 312 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 313 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 314 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 315 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 316 | }; 317 | 318 | static const char P[] = { 319 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ 320 | 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ 321 | 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ 322 | 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ 323 | }; 324 | 325 | #endif /* MD5_SIZE_OVER_SPEED > 0 */ 326 | 327 | __md5_Decode (x, block, 64); 328 | 329 | a = state[0]; b = state[1]; c = state[2]; d = state[3]; 330 | 331 | #if MD5_SIZE_OVER_SPEED > 2 332 | pc = C; pp = P; ps = S - 4; 333 | 334 | for ( i = 0 ; i < 64 ; i++ ) { 335 | if ((i&0x0f) == 0) ps += 4; 336 | temp = a; 337 | switch (i>>4) { 338 | case 0: 339 | temp += F(b,c,d); 340 | break; 341 | case 1: 342 | temp += G(b,c,d); 343 | break; 344 | case 2: 345 | temp += H(b,c,d); 346 | break; 347 | case 3: 348 | temp += I(b,c,d); 349 | break; 350 | } 351 | temp += x[(int)(*pp++)] + *pc++; 352 | temp = ROTATE_LEFT(temp, ps[i&3]); 353 | temp += b; 354 | a = d; d = c; c = b; b = temp; 355 | } 356 | #elif MD5_SIZE_OVER_SPEED > 1 357 | pc = C; pp = P; ps = S; 358 | 359 | /* Round 1 */ 360 | for ( i = 0 ; i < 16 ; i++ ) { 361 | FF (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); 362 | temp = d; d = c; c = b; b = a; a = temp; 363 | } 364 | 365 | /* Round 2 */ 366 | ps += 4; 367 | for ( ; i < 32 ; i++ ) { 368 | GG (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); 369 | temp = d; d = c; c = b; b = a; a = temp; 370 | } 371 | /* Round 3 */ 372 | ps += 4; 373 | for ( ; i < 48 ; i++ ) { 374 | HH (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); 375 | temp = d; d = c; c = b; b = a; a = temp; 376 | } 377 | 378 | /* Round 4 */ 379 | ps += 4; 380 | for ( ; i < 64 ; i++ ) { 381 | II (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); 382 | temp = d; d = c; c = b; b = a; a = temp; 383 | } 384 | #elif MD5_SIZE_OVER_SPEED > 0 385 | pc = C; pp = P; 386 | 387 | /* Round 1 */ 388 | for ( i = 0 ; i < 4 ; i++ ) { 389 | FF (a, b, c, d, x[(int)(*pp++)], 7, *pc++); 390 | FF (d, a, b, c, x[(int)(*pp++)], 12, *pc++); 391 | FF (c, d, a, b, x[(int)(*pp++)], 17, *pc++); 392 | FF (b, c, d, a, x[(int)(*pp++)], 22, *pc++); 393 | } 394 | 395 | /* Round 2 */ 396 | for ( i = 0 ; i < 4 ; i++ ) { 397 | GG (a, b, c, d, x[(int)(*pp++)], 5, *pc++); 398 | GG (d, a, b, c, x[(int)(*pp++)], 9, *pc++); 399 | GG (c, d, a, b, x[(int)(*pp++)], 14, *pc++); 400 | GG (b, c, d, a, x[(int)(*pp++)], 20, *pc++); 401 | } 402 | /* Round 3 */ 403 | for ( i = 0 ; i < 4 ; i++ ) { 404 | HH (a, b, c, d, x[(int)(*pp++)], 4, *pc++); 405 | HH (d, a, b, c, x[(int)(*pp++)], 11, *pc++); 406 | HH (c, d, a, b, x[(int)(*pp++)], 16, *pc++); 407 | HH (b, c, d, a, x[(int)(*pp++)], 23, *pc++); 408 | } 409 | 410 | /* Round 4 */ 411 | for ( i = 0 ; i < 4 ; i++ ) { 412 | II (a, b, c, d, x[(int)(*pp++)], 6, *pc++); 413 | II (d, a, b, c, x[(int)(*pp++)], 10, *pc++); 414 | II (c, d, a, b, x[(int)(*pp++)], 15, *pc++); 415 | II (b, c, d, a, x[(int)(*pp++)], 21, *pc++); 416 | } 417 | #else 418 | /* Round 1 */ 419 | #define S11 7 420 | #define S12 12 421 | #define S13 17 422 | #define S14 22 423 | FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ 424 | FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ 425 | FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ 426 | FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ 427 | FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ 428 | FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ 429 | FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ 430 | FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ 431 | FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ 432 | FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ 433 | FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 434 | FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 435 | FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 436 | FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 437 | FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 438 | FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 439 | 440 | /* Round 2 */ 441 | #define S21 5 442 | #define S22 9 443 | #define S23 14 444 | #define S24 20 445 | GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ 446 | GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ 447 | GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 448 | GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 449 | GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ 450 | GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 451 | GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 452 | GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ 453 | GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ 454 | GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 455 | GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ 456 | GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ 457 | GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 458 | GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ 459 | GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ 460 | GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 461 | 462 | /* Round 3 */ 463 | #define S31 4 464 | #define S32 11 465 | #define S33 16 466 | #define S34 23 467 | HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ 468 | HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ 469 | HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 470 | HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 471 | HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ 472 | HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ 473 | HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ 474 | HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 475 | HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 476 | HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ 477 | HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ 478 | HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ 479 | HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ 480 | HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 481 | HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 482 | HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ 483 | 484 | /* Round 4 */ 485 | #define S41 6 486 | #define S42 10 487 | #define S43 15 488 | #define S44 21 489 | II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ 490 | II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ 491 | II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 492 | II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ 493 | II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 494 | II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ 495 | II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 496 | II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ 497 | II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ 498 | II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 499 | II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ 500 | II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 501 | II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ 502 | II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 503 | II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ 504 | II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ 505 | #endif 506 | 507 | state[0] += a; 508 | state[1] += b; 509 | state[2] += c; 510 | state[3] += d; 511 | 512 | /* Zeroize sensitive information. */ 513 | memset ((void *)x, 0, sizeof (x)); 514 | } 515 | 516 | 517 | static void __md5_to64( char *s, unsigned long v, int n) 518 | { 519 | while (--n >= 0) { 520 | *s++ = __md5_itoa64[v&0x3f]; 521 | v >>= 6; 522 | } 523 | } 524 | 525 | /* 526 | * UNIX password 527 | * 528 | * Use MD5 for what it is best at... 529 | */ 530 | 531 | char *__md5_crypt(const unsigned char *pw, const unsigned char *salt) 532 | { 533 | /* Static stuff */ 534 | /* "$1$" + salt_up_to_8_chars + "$" + 22_bytes_of_hash + NUL */ 535 | static char passwd[3 + 8 + 1 + 22 + 1]; 536 | 537 | const unsigned char *sp, *ep; 538 | char *p; 539 | unsigned char final[17]; /* final[16] exists only to aid in looping */ 540 | int sl,pl,i,pw_len; 541 | struct MD5Context ctx,ctx1; 542 | unsigned long l; 543 | 544 | /* Refine the Salt first */ 545 | sp = salt; 546 | 547 | /* If it starts with the magic string, then skip that */ 548 | if(!strncmp(sp,__md5__magic,MD5_MAGIC_LEN)) 549 | sp += MD5_MAGIC_LEN; 550 | 551 | /* It stops at the first '$', max 8 chars */ 552 | for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) 553 | continue; 554 | 555 | /* get the length of the true salt */ 556 | sl = ep - sp; 557 | 558 | __md5_Init(&ctx); 559 | 560 | /* The password first, since that is what is most unknown */ 561 | pw_len = strlen(pw); 562 | __md5_Update(&ctx,pw,pw_len); 563 | 564 | /* Then our magic string */ 565 | __md5_Update(&ctx,__md5__magic,MD5_MAGIC_LEN); 566 | 567 | /* Then the raw salt */ 568 | __md5_Update(&ctx,sp,sl); 569 | 570 | /* Then just as many characters of the MD5(pw,salt,pw) */ 571 | __md5_Init(&ctx1); 572 | __md5_Update(&ctx1,pw,pw_len); 573 | __md5_Update(&ctx1,sp,sl); 574 | __md5_Update(&ctx1,pw,pw_len); 575 | __md5_Final(final,&ctx1); 576 | for(pl = pw_len; pl > 0; pl -= 16) 577 | __md5_Update(&ctx,final,pl>16 ? 16 : pl); 578 | 579 | /* Don't leave anything around in vm they could use. */ 580 | memset(final,0,sizeof final); 581 | 582 | /* Then something really weird... */ 583 | for (i = pw_len; i ; i >>= 1) { 584 | __md5_Update(&ctx, ((i&1) ? final : (const unsigned char *) pw), 1); 585 | } 586 | 587 | /* Now make the output string */ 588 | strcpy(passwd,__md5__magic); /* 3 bytes */ 589 | strncpy(passwd+MD5_MAGIC_LEN,(char*)sp,sl); /* 8 or less */ 590 | passwd[MD5_MAGIC_LEN+sl] = '$'; 591 | 592 | __md5_Final(final,&ctx); 593 | 594 | /* 595 | * and now, just to make sure things don't run too fast 596 | * On a 60 Mhz Pentium this takes 34 msec, so you would 597 | * need 30 seconds to build a 1000 entry dictionary... 598 | */ 599 | for(i=0;i<1000;i++) { 600 | __md5_Init(&ctx1); 601 | if(i & 1) 602 | __md5_Update(&ctx1,pw,pw_len); 603 | else 604 | __md5_Update(&ctx1,final,16); 605 | 606 | if(i % 3) 607 | __md5_Update(&ctx1,sp,sl); 608 | 609 | if(i % 7) 610 | __md5_Update(&ctx1,pw,pw_len); 611 | 612 | if(i & 1) 613 | __md5_Update(&ctx1,final,16); 614 | else 615 | __md5_Update(&ctx1,pw,pw_len); 616 | __md5_Final(final,&ctx1); 617 | } 618 | 619 | /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */ 620 | p = passwd + MD5_MAGIC_LEN + sl + 1; 621 | final[16] = final[5]; 622 | for ( i=0 ; i < 5 ; i++ ) { 623 | l = (final[i]<<16) | (final[i+6]<<8) | final[i+12]; 624 | __md5_to64(p,l,4); 625 | p += 4; 626 | } 627 | l = final[11]; 628 | __md5_to64(p,l,2); 629 | p += 2; 630 | *p = '\0'; 631 | 632 | /* Don't leave anything around in vm they could use. */ 633 | memset(final,0,sizeof final); 634 | 635 | return passwd; 636 | } 637 | 638 | -------------------------------------------------------------------------------- /jni/libcrypt/des.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeSec: libcrypt for NetBSD 3 | * 4 | * Copyright (c) 1994 David Burren 5 | * All rights reserved. 6 | * 7 | * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet 8 | * this file should now *only* export crypt(), in order to make 9 | * binaries of libcrypt exportable from the USA 10 | * 11 | * Adapted for FreeBSD-4.0 by Mark R V Murray 12 | * this file should now *only* export crypt_des(), in order to make 13 | * a module that can be optionally included in libcrypt. 14 | * 15 | * Redistribution and use in source and binary forms, with or without 16 | * modification, are permitted provided that the following conditions 17 | * are met: 18 | * 1. Redistributions of source code must retain the above copyright 19 | * notice, this list of conditions and the following disclaimer. 20 | * 2. Redistributions in binary form must reproduce the above copyright 21 | * notice, this list of conditions and the following disclaimer in the 22 | * documentation and/or other materials provided with the distribution. 23 | * 3. Neither the name of the author nor the names of other contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 | * SUCH DAMAGE. 38 | * 39 | * This is an original implementation of the DES and the crypt(3) interfaces 40 | * by David Burren . 41 | * 42 | * An excellent reference on the underlying algorithm (and related 43 | * algorithms) is: 44 | * 45 | * B. Schneier, Applied Cryptography: protocols, algorithms, 46 | * and source code in C, John Wiley & Sons, 1994. 47 | * 48 | * Note that in that book's description of DES the lookups for the initial, 49 | * pbox, and final permutations are inverted (this has been brought to the 50 | * attention of the author). A list of errata for this book has been 51 | * posted to the sci.crypt newsgroup by the author and is available for FTP. 52 | * 53 | * ARCHITECTURE ASSUMPTIONS: 54 | * It is assumed that the 8-byte arrays passed by reference can be 55 | * addressed as arrays of u_int32_t's (ie. the CPU is not picky about 56 | * alignment). 57 | */ 58 | 59 | #define __FORCE_GLIBC 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include "crypt.h" 67 | #include "libcrypt.h" 68 | 69 | /* Re-entrantify me -- all this junk needs to be in 70 | * struct crypt_data to make this really reentrant... */ 71 | static u_char inv_key_perm[64]; 72 | static u_char inv_comp_perm[56]; 73 | static u_char un_pbox[32]; 74 | static u_int32_t en_keysl[16], en_keysr[16]; 75 | static u_int32_t de_keysl[16], de_keysr[16]; 76 | static u_int32_t ip_maskl[8][256], ip_maskr[8][256]; 77 | static u_int32_t fp_maskl[8][256], fp_maskr[8][256]; 78 | static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; 79 | static u_int32_t comp_maskl[8][128], comp_maskr[8][128]; 80 | static u_int32_t saltbits; 81 | static u_int32_t old_salt; 82 | static u_int32_t old_rawkey0, old_rawkey1; 83 | 84 | 85 | /* Static stuff that stays resident and doesn't change after 86 | * being initialized, and therefore doesn't need to be made 87 | * reentrant. */ 88 | static u_char init_perm[64], final_perm[64]; 89 | static u_char m_sbox[4][4096]; 90 | static u_int32_t psbox[4][256]; 91 | 92 | 93 | 94 | 95 | /* A pile of data */ 96 | static const u_char ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 97 | 98 | static const u_char IP[64] = { 99 | 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 100 | 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 101 | 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 102 | 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 103 | }; 104 | 105 | static const u_char key_perm[56] = { 106 | 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 107 | 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 108 | 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 109 | 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 110 | }; 111 | 112 | static const u_char key_shifts[16] = { 113 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 114 | }; 115 | 116 | static const u_char comp_perm[48] = { 117 | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 118 | 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 119 | 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 120 | 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 121 | }; 122 | 123 | /* 124 | * No E box is used, as it's replaced by some ANDs, shifts, and ORs. 125 | */ 126 | 127 | static const u_char sbox[8][64] = { 128 | { 129 | 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 130 | 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 131 | 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 132 | 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 133 | }, 134 | { 135 | 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 136 | 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 137 | 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 138 | 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 139 | }, 140 | { 141 | 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 142 | 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 143 | 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 144 | 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 145 | }, 146 | { 147 | 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 148 | 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 149 | 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 150 | 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 151 | }, 152 | { 153 | 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 154 | 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 155 | 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 156 | 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 157 | }, 158 | { 159 | 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 160 | 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 161 | 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 162 | 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 163 | }, 164 | { 165 | 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 166 | 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 167 | 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 168 | 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 169 | }, 170 | { 171 | 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 172 | 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 173 | 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 174 | 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 175 | } 176 | }; 177 | 178 | static const u_char pbox[32] = { 179 | 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 180 | 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 181 | }; 182 | 183 | static const u_int32_t bits32[32] = 184 | { 185 | 0x80000000, 0x40000000, 0x20000000, 0x10000000, 186 | 0x08000000, 0x04000000, 0x02000000, 0x01000000, 187 | 0x00800000, 0x00400000, 0x00200000, 0x00100000, 188 | 0x00080000, 0x00040000, 0x00020000, 0x00010000, 189 | 0x00008000, 0x00004000, 0x00002000, 0x00001000, 190 | 0x00000800, 0x00000400, 0x00000200, 0x00000100, 191 | 0x00000080, 0x00000040, 0x00000020, 0x00000010, 192 | 0x00000008, 0x00000004, 0x00000002, 0x00000001 193 | }; 194 | 195 | static const u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; 196 | 197 | 198 | static int 199 | ascii_to_bin(char ch) 200 | { 201 | if (ch > 'z') 202 | return(0); 203 | if (ch >= 'a') 204 | return(ch - 'a' + 38); 205 | if (ch > 'Z') 206 | return(0); 207 | if (ch >= 'A') 208 | return(ch - 'A' + 12); 209 | if (ch > '9') 210 | return(0); 211 | if (ch >= '.') 212 | return(ch - '.'); 213 | return(0); 214 | } 215 | 216 | static void 217 | des_init(void) 218 | { 219 | static int des_initialised = 0; 220 | 221 | int i, j, b, k, inbit, obit; 222 | u_int32_t *p, *il, *ir, *fl, *fr; 223 | const u_int32_t *bits28, *bits24; 224 | u_char u_sbox[8][64]; 225 | 226 | if (des_initialised==1) 227 | return; 228 | 229 | old_rawkey0 = old_rawkey1 = 0L; 230 | saltbits = 0L; 231 | old_salt = 0L; 232 | bits24 = (bits28 = bits32 + 4) + 4; 233 | 234 | /* 235 | * Invert the S-boxes, reordering the input bits. 236 | */ 237 | for (i = 0; i < 8; i++) 238 | for (j = 0; j < 64; j++) { 239 | b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); 240 | u_sbox[i][j] = sbox[i][b]; 241 | } 242 | 243 | /* 244 | * Convert the inverted S-boxes into 4 arrays of 8 bits. 245 | * Each will handle 12 bits of the S-box input. 246 | */ 247 | for (b = 0; b < 4; b++) 248 | for (i = 0; i < 64; i++) 249 | for (j = 0; j < 64; j++) 250 | m_sbox[b][(i << 6) | j] = 251 | (u_char)((u_sbox[(b << 1)][i] << 4) | 252 | u_sbox[(b << 1) + 1][j]); 253 | 254 | /* 255 | * Set up the initial & final permutations into a useful form, and 256 | * initialise the inverted key permutation. 257 | */ 258 | for (i = 0; i < 64; i++) { 259 | init_perm[final_perm[i] = IP[i] - 1] = (u_char)i; 260 | inv_key_perm[i] = 255; 261 | } 262 | 263 | /* 264 | * Invert the key permutation and initialise the inverted key 265 | * compression permutation. 266 | */ 267 | for (i = 0; i < 56; i++) { 268 | inv_key_perm[key_perm[i] - 1] = (u_char)i; 269 | inv_comp_perm[i] = 255; 270 | } 271 | 272 | /* 273 | * Invert the key compression permutation. 274 | */ 275 | for (i = 0; i < 48; i++) { 276 | inv_comp_perm[comp_perm[i] - 1] = (u_char)i; 277 | } 278 | 279 | /* 280 | * Set up the OR-mask arrays for the initial and final permutations, 281 | * and for the key initial and compression permutations. 282 | */ 283 | for (k = 0; k < 8; k++) { 284 | for (i = 0; i < 256; i++) { 285 | *(il = &ip_maskl[k][i]) = 0L; 286 | *(ir = &ip_maskr[k][i]) = 0L; 287 | *(fl = &fp_maskl[k][i]) = 0L; 288 | *(fr = &fp_maskr[k][i]) = 0L; 289 | for (j = 0; j < 8; j++) { 290 | inbit = 8 * k + j; 291 | if (i & bits8[j]) { 292 | if ((obit = init_perm[inbit]) < 32) 293 | *il |= bits32[obit]; 294 | else 295 | *ir |= bits32[obit-32]; 296 | if ((obit = final_perm[inbit]) < 32) 297 | *fl |= bits32[obit]; 298 | else 299 | *fr |= bits32[obit - 32]; 300 | } 301 | } 302 | } 303 | for (i = 0; i < 128; i++) { 304 | *(il = &key_perm_maskl[k][i]) = 0L; 305 | *(ir = &key_perm_maskr[k][i]) = 0L; 306 | for (j = 0; j < 7; j++) { 307 | inbit = 8 * k + j; 308 | if (i & bits8[j + 1]) { 309 | if ((obit = inv_key_perm[inbit]) == 255) 310 | continue; 311 | if (obit < 28) 312 | *il |= bits28[obit]; 313 | else 314 | *ir |= bits28[obit - 28]; 315 | } 316 | } 317 | *(il = &comp_maskl[k][i]) = 0L; 318 | *(ir = &comp_maskr[k][i]) = 0L; 319 | for (j = 0; j < 7; j++) { 320 | inbit = 7 * k + j; 321 | if (i & bits8[j + 1]) { 322 | if ((obit=inv_comp_perm[inbit]) == 255) 323 | continue; 324 | if (obit < 24) 325 | *il |= bits24[obit]; 326 | else 327 | *ir |= bits24[obit - 24]; 328 | } 329 | } 330 | } 331 | } 332 | 333 | /* 334 | * Invert the P-box permutation, and convert into OR-masks for 335 | * handling the output of the S-box arrays setup above. 336 | */ 337 | for (i = 0; i < 32; i++) 338 | un_pbox[pbox[i] - 1] = (u_char)i; 339 | 340 | for (b = 0; b < 4; b++) 341 | for (i = 0; i < 256; i++) { 342 | *(p = &psbox[b][i]) = 0L; 343 | for (j = 0; j < 8; j++) { 344 | if (i & bits8[j]) 345 | *p |= bits32[un_pbox[8 * b + j]]; 346 | } 347 | } 348 | 349 | des_initialised = 1; 350 | } 351 | 352 | 353 | static void 354 | setup_salt(u_int32_t salt) 355 | { 356 | u_int32_t obit, saltbit; 357 | int i; 358 | 359 | if (salt == old_salt) 360 | return; 361 | old_salt = salt; 362 | 363 | saltbits = 0L; 364 | saltbit = 1; 365 | obit = 0x800000; 366 | for (i = 0; i < 24; i++) { 367 | if (salt & saltbit) 368 | saltbits |= obit; 369 | saltbit <<= 1; 370 | obit >>= 1; 371 | } 372 | } 373 | 374 | 375 | static void 376 | des_setkey(const char *key) 377 | { 378 | u_int32_t k0, k1, rawkey0, rawkey1; 379 | int shifts, round; 380 | 381 | des_init(); 382 | 383 | rawkey0 = ntohl(*(const u_int32_t *) key); 384 | rawkey1 = ntohl(*(const u_int32_t *) (key + 4)); 385 | 386 | if ((rawkey0 | rawkey1) 387 | && rawkey0 == old_rawkey0 388 | && rawkey1 == old_rawkey1) { 389 | /* 390 | * Already setup for this key. 391 | * This optimisation fails on a zero key (which is weak and 392 | * has bad parity anyway) in order to simplify the starting 393 | * conditions. 394 | */ 395 | return; 396 | } 397 | old_rawkey0 = rawkey0; 398 | old_rawkey1 = rawkey1; 399 | 400 | /* 401 | * Do key permutation and split into two 28-bit subkeys. 402 | */ 403 | k0 = key_perm_maskl[0][rawkey0 >> 25] 404 | | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] 405 | | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] 406 | | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] 407 | | key_perm_maskl[4][rawkey1 >> 25] 408 | | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] 409 | | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] 410 | | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; 411 | k1 = key_perm_maskr[0][rawkey0 >> 25] 412 | | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] 413 | | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] 414 | | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] 415 | | key_perm_maskr[4][rawkey1 >> 25] 416 | | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] 417 | | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] 418 | | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; 419 | /* 420 | * Rotate subkeys and do compression permutation. 421 | */ 422 | shifts = 0; 423 | for (round = 0; round < 16; round++) { 424 | u_int32_t t0, t1; 425 | 426 | shifts += key_shifts[round]; 427 | 428 | t0 = (k0 << shifts) | (k0 >> (28 - shifts)); 429 | t1 = (k1 << shifts) | (k1 >> (28 - shifts)); 430 | 431 | de_keysl[15 - round] = 432 | en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] 433 | | comp_maskl[1][(t0 >> 14) & 0x7f] 434 | | comp_maskl[2][(t0 >> 7) & 0x7f] 435 | | comp_maskl[3][t0 & 0x7f] 436 | | comp_maskl[4][(t1 >> 21) & 0x7f] 437 | | comp_maskl[5][(t1 >> 14) & 0x7f] 438 | | comp_maskl[6][(t1 >> 7) & 0x7f] 439 | | comp_maskl[7][t1 & 0x7f]; 440 | 441 | de_keysr[15 - round] = 442 | en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f] 443 | | comp_maskr[1][(t0 >> 14) & 0x7f] 444 | | comp_maskr[2][(t0 >> 7) & 0x7f] 445 | | comp_maskr[3][t0 & 0x7f] 446 | | comp_maskr[4][(t1 >> 21) & 0x7f] 447 | | comp_maskr[5][(t1 >> 14) & 0x7f] 448 | | comp_maskr[6][(t1 >> 7) & 0x7f] 449 | | comp_maskr[7][t1 & 0x7f]; 450 | } 451 | } 452 | 453 | 454 | static int 455 | do_des( u_int32_t l_in, u_int32_t r_in, u_int32_t *l_out, u_int32_t *r_out, int count) 456 | { 457 | /* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. */ 458 | u_int32_t l, r, *kl, *kr, *kl1, *kr1; 459 | u_int32_t f, r48l, r48r; 460 | int round; 461 | 462 | if (count == 0) { 463 | return 1; 464 | } 465 | if (count > 0) { 466 | /* Encrypting */ 467 | kl1 = en_keysl; 468 | kr1 = en_keysr; 469 | } else { 470 | /* Decrypting */ 471 | count = -count; 472 | kl1 = de_keysl; 473 | kr1 = de_keysr; 474 | } 475 | 476 | /* Do initial permutation (IP). */ 477 | l = ip_maskl[0][l_in >> 24] 478 | | ip_maskl[1][(l_in >> 16) & 0xff] 479 | | ip_maskl[2][(l_in >> 8) & 0xff] 480 | | ip_maskl[3][l_in & 0xff] 481 | | ip_maskl[4][r_in >> 24] 482 | | ip_maskl[5][(r_in >> 16) & 0xff] 483 | | ip_maskl[6][(r_in >> 8) & 0xff] 484 | | ip_maskl[7][r_in & 0xff]; 485 | r = ip_maskr[0][l_in >> 24] 486 | | ip_maskr[1][(l_in >> 16) & 0xff] 487 | | ip_maskr[2][(l_in >> 8) & 0xff] 488 | | ip_maskr[3][l_in & 0xff] 489 | | ip_maskr[4][r_in >> 24] 490 | | ip_maskr[5][(r_in >> 16) & 0xff] 491 | | ip_maskr[6][(r_in >> 8) & 0xff] 492 | | ip_maskr[7][r_in & 0xff]; 493 | 494 | while (count--) { 495 | /* Do each round. */ 496 | kl = kl1; 497 | kr = kr1; 498 | round = 16; 499 | do { 500 | /* Expand R to 48 bits (simulate the E-box). */ 501 | r48l = ((r & 0x00000001) << 23) 502 | | ((r & 0xf8000000) >> 9) 503 | | ((r & 0x1f800000) >> 11) 504 | | ((r & 0x01f80000) >> 13) 505 | | ((r & 0x001f8000) >> 15); 506 | r48r = ((r & 0x0001f800) << 7) 507 | | ((r & 0x00001f80) << 5) 508 | | ((r & 0x000001f8) << 3) 509 | | ((r & 0x0000001f) << 1) 510 | | ((r & 0x80000000) >> 31); 511 | /* 512 | * Do salting for crypt() and friends, and 513 | * XOR with the permuted key. 514 | */ 515 | f = (r48l ^ r48r) & saltbits; 516 | r48l ^= f ^ *kl++; 517 | r48r ^= f ^ *kr++; 518 | /* 519 | * Do sbox lookups (which shrink it back to 32 bits) 520 | * and do the pbox permutation at the same time. 521 | */ 522 | f = psbox[0][m_sbox[0][r48l >> 12]] 523 | | psbox[1][m_sbox[1][r48l & 0xfff]] 524 | | psbox[2][m_sbox[2][r48r >> 12]] 525 | | psbox[3][m_sbox[3][r48r & 0xfff]]; 526 | /* Now that we've permuted things, complete f(). */ 527 | f ^= l; 528 | l = r; 529 | r = f; 530 | } while (--round); 531 | r = l; 532 | l = f; 533 | } 534 | /* Do final permutation (inverse of IP). */ 535 | *l_out = fp_maskl[0][l >> 24] 536 | | fp_maskl[1][(l >> 16) & 0xff] 537 | | fp_maskl[2][(l >> 8) & 0xff] 538 | | fp_maskl[3][l & 0xff] 539 | | fp_maskl[4][r >> 24] 540 | | fp_maskl[5][(r >> 16) & 0xff] 541 | | fp_maskl[6][(r >> 8) & 0xff] 542 | | fp_maskl[7][r & 0xff]; 543 | *r_out = fp_maskr[0][l >> 24] 544 | | fp_maskr[1][(l >> 16) & 0xff] 545 | | fp_maskr[2][(l >> 8) & 0xff] 546 | | fp_maskr[3][l & 0xff] 547 | | fp_maskr[4][r >> 24] 548 | | fp_maskr[5][(r >> 16) & 0xff] 549 | | fp_maskr[6][(r >> 8) & 0xff] 550 | | fp_maskr[7][r & 0xff]; 551 | return(0); 552 | } 553 | 554 | 555 | #if 0 556 | static int 557 | des_cipher(const char *in, char *out, u_int32_t salt, int count) 558 | { 559 | u_int32_t l_out, r_out, rawl, rawr; 560 | int retval; 561 | union { 562 | u_int32_t *ui32; 563 | const char *c; 564 | } trans; 565 | 566 | des_init(); 567 | 568 | setup_salt(salt); 569 | 570 | trans.c = in; 571 | rawl = ntohl(*trans.ui32++); 572 | rawr = ntohl(*trans.ui32); 573 | 574 | retval = do_des(rawl, rawr, &l_out, &r_out, count); 575 | 576 | trans.c = out; 577 | *trans.ui32++ = htonl(l_out); 578 | *trans.ui32 = htonl(r_out); 579 | return(retval); 580 | } 581 | #endif 582 | 583 | 584 | void 585 | setkey(const char *key) 586 | { 587 | int i, j; 588 | u_int32_t packed_keys[2]; 589 | u_char *p; 590 | 591 | p = (u_char *) packed_keys; 592 | 593 | for (i = 0; i < 8; i++) { 594 | p[i] = 0; 595 | for (j = 0; j < 8; j++) 596 | if (*key++ & 1) 597 | p[i] |= bits8[j]; 598 | } 599 | des_setkey((char *)p); 600 | } 601 | 602 | 603 | void 604 | encrypt(char *block, int flag) 605 | { 606 | u_int32_t io[2]; 607 | u_char *p; 608 | int i, j; 609 | 610 | des_init(); 611 | 612 | setup_salt(0L); 613 | p = (u_char*)block; 614 | for (i = 0; i < 2; i++) { 615 | io[i] = 0L; 616 | for (j = 0; j < 32; j++) 617 | if (*p++ & 1) 618 | io[i] |= bits32[j]; 619 | } 620 | do_des(io[0], io[1], io, io + 1, flag ? -1 : 1); 621 | for (i = 0; i < 2; i++) 622 | for (j = 0; j < 32; j++) 623 | block[(i << 5) | j] = (io[i] & bits32[j]) ? 1 : 0; 624 | } 625 | 626 | char *__des_crypt(const unsigned char *key, const unsigned char *setting) 627 | { 628 | u_int32_t count, salt, l, r0, r1, keybuf[2]; 629 | u_char *p, *q; 630 | static char output[21]; 631 | 632 | des_init(); 633 | 634 | /* 635 | * Copy the key, shifting each character up by one bit 636 | * and padding with zeros. 637 | */ 638 | q = (u_char *)keybuf; 639 | while (q - (u_char *)keybuf - 8) { 640 | *q++ = *key << 1; 641 | if (*(q - 1)) 642 | key++; 643 | } 644 | des_setkey((char *)keybuf); 645 | 646 | #if 0 647 | if (*setting == _PASSWORD_EFMT1) { 648 | int i; 649 | /* 650 | * "new"-style: 651 | * setting - underscore, 4 bytes of count, 4 bytes of salt 652 | * key - unlimited characters 653 | */ 654 | for (i = 1, count = 0L; i < 5; i++) 655 | count |= ascii_to_bin(setting[i]) << ((i - 1) * 6); 656 | 657 | for (i = 5, salt = 0L; i < 9; i++) 658 | salt |= ascii_to_bin(setting[i]) << ((i - 5) * 6); 659 | 660 | while (*key) { 661 | /* 662 | * Encrypt the key with itself. 663 | */ 664 | if (des_cipher((char *)keybuf, (char *)keybuf, 0L, 1)) 665 | return(NULL); 666 | /* 667 | * And XOR with the next 8 characters of the key. 668 | */ 669 | q = (u_char *)keybuf; 670 | while (q - (u_char *)keybuf - 8 && *key) 671 | *q++ ^= *key++ << 1; 672 | 673 | des_setkey((char *)keybuf); 674 | } 675 | strncpy(output, setting, 9); 676 | 677 | /* 678 | * Double check that we weren't given a short setting. 679 | * If we were, the above code will probably have created 680 | * wierd values for count and salt, but we don't really care. 681 | * Just make sure the output string doesn't have an extra 682 | * NUL in it. 683 | */ 684 | output[9] = '\0'; 685 | p = (u_char *)output + strlen(output); 686 | } else 687 | #endif 688 | { 689 | /* 690 | * "old"-style: 691 | * setting - 2 bytes of salt 692 | * key - up to 8 characters 693 | */ 694 | count = 25; 695 | 696 | salt = (ascii_to_bin(setting[1]) << 6) 697 | | ascii_to_bin(setting[0]); 698 | 699 | output[0] = setting[0]; 700 | /* 701 | * If the encrypted password that the salt was extracted from 702 | * is only 1 character long, the salt will be corrupted. We 703 | * need to ensure that the output string doesn't have an extra 704 | * NUL in it! 705 | */ 706 | output[1] = setting[1] ? setting[1] : output[0]; 707 | 708 | p = (u_char *)output + 2; 709 | } 710 | setup_salt(salt); 711 | /* 712 | * Do it. 713 | */ 714 | if (do_des(0L, 0L, &r0, &r1, (int)count)) 715 | return(NULL); 716 | /* 717 | * Now encode the result... 718 | */ 719 | l = (r0 >> 8); 720 | *p++ = ascii64[(l >> 18) & 0x3f]; 721 | *p++ = ascii64[(l >> 12) & 0x3f]; 722 | *p++ = ascii64[(l >> 6) & 0x3f]; 723 | *p++ = ascii64[l & 0x3f]; 724 | 725 | l = (r0 << 16) | ((r1 >> 16) & 0xffff); 726 | *p++ = ascii64[(l >> 18) & 0x3f]; 727 | *p++ = ascii64[(l >> 12) & 0x3f]; 728 | *p++ = ascii64[(l >> 6) & 0x3f]; 729 | *p++ = ascii64[l & 0x3f]; 730 | 731 | l = r1 << 2; 732 | *p++ = ascii64[(l >> 12) & 0x3f]; 733 | *p++ = ascii64[(l >> 6) & 0x3f]; 734 | *p++ = ascii64[l & 0x3f]; 735 | *p = 0; 736 | 737 | return(output); 738 | } 739 | 740 | --------------------------------------------------------------------------------