Add new utility (make extra) - ntfsdecrypt. (Yuval)

edge.strict_endians
antona 2005-07-16 06:53:40 +00:00
parent 0b75b12544
commit 4ed406e68e
16 changed files with 1709 additions and 1285 deletions

View File

@ -18,6 +18,7 @@ xx/07/2005 - 1.11.0-WIP - Fixes and a new utility ntfsmount, a FUSE ntfsmodule.
if sector size was above 8kiB and we only reserved one sector even
when sector size was less than 512 bytes and then we wrote 512 bytes,
i.e. beyond the end of the device.) (Anton)
- Add new utility (make extra) - ntfsdecrypt. (Yuval)
20/06/2005 - 1.10.0 - Lots of new features, enhancements, and bug fixes.

View File

@ -144,7 +144,6 @@ ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
all_includes = @all_includes@
all_libraries = @all_libraries@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@

520
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

64
config.guess vendored
View File

@ -136,6 +136,16 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_MACHINE}" in
i?86)
test -z "$VENDOR" && VENDOR=pc
;;
*)
test -z "$VENDOR" && VENDOR=unknown
;;
esac
test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@ -825,25 +835,25 @@ EOF
echo ${UNAME_MACHINE}-pc-minix
exit 0 ;;
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
echo cris-axis-linux
exit 0 ;;
crisv32:Linux:*:*)
echo crisv32-axis-linux-gnu
echo crisv32-axis-linux
exit 0 ;;
frv:Linux:*:*)
echo frv-unknown-linux-gnu
echo frv-${VENDOR}-linux
exit 0 ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
mips:Linux:*:*)
eval $set_cc_for_build
@ -862,7 +872,7 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
test x"${CPU}" != x && echo "${CPU}-${VENDOR}-linux" && exit 0
;;
mips64:Linux:*:*)
eval $set_cc_for_build
@ -881,13 +891,13 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
test x"${CPU}" != x && echo "${CPU}-${VENDOR}-linux" && exit 0
;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
echo powerpc-${VENDOR}-linux
exit 0 ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
echo powerpc64-${VENDOR}-linux
exit 0 ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@ -900,34 +910,34 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
if test "$?" = 0 ; then LIBC="-libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-${VENDOR}-linux${LIBC}
exit 0 ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-gnu ;;
PA8*) echo hppa2.0-unknown-linux-gnu ;;
*) echo hppa-unknown-linux-gnu ;;
PA7*) echo hppa1.1-${VENDOR}-linux ;;
PA8*) echo hppa2.0-${VENDOR}-linux ;;
*) echo hppa-${VENDOR}-linux ;;
esac
exit 0 ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
echo hppa64-${VENDOR}-linux
exit 0 ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit 0 ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-${VENDOR}-linux
exit 0 ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
echo x86_64-${VENDOR}-linux
exit 0 ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
@ -942,18 +952,18 @@ EOF
p'`
case "$ld_supported_targets" in
elf32-i386)
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux"
;;
a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
echo "${UNAME_MACHINE}-${VENDOR}-linuxaout"
exit 0 ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
echo "${UNAME_MACHINE}-${VENDOR}-linuxcoff"
exit 0 ;;
"")
# Either a pre-BFD a.out linker (linux-gnuoldld) or
# Either a pre-BFD a.out linker (linuxoldld) or
# one that does not give us useful --help.
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
echo "${UNAME_MACHINE}-${VENDOR}-linuxoldld"
exit 0 ;;
esac
# Determine whether the default compiler is a.out or elf
@ -982,7 +992,7 @@ EOF
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}" | sed 's/linux-gnu/linux/' && exit 0
test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
;;
i*86:DYNIX/ptx:4*:*)

5
config.sub vendored
View File

@ -1172,7 +1172,7 @@ case $os in
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
| -mingw32* | -linux* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
@ -1205,9 +1205,6 @@ case $os in
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;

1216
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -119,7 +119,6 @@ ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
all_includes = @all_includes@
all_libraries = @all_libraries@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@

View File

@ -128,7 +128,6 @@ ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
all_includes = @all_includes@
all_libraries = @all_libraries@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@

View File

@ -132,7 +132,6 @@ ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
all_includes = @all_includes@
all_libraries = @all_libraries@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@

View File

@ -194,7 +194,6 @@ ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
all_includes = @all_includes@
all_libraries = @all_libraries@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@

156
ltmain.sh
View File

@ -17,7 +17,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -43,8 +43,8 @@ EXIT_FAILURE=1
PROGRAM=ltmain.sh
PACKAGE=libtool
VERSION=1.5.18
TIMESTAMP=" (1.1220.2.245 2005/05/16 08:55:27)"
VERSION=1.5.14
TIMESTAMP=" (1.1220.2.195 2005/02/12 12:12:33)"
# See if we are running on zsh, and set the options which allow our
# commands through without removal of \ escapes.
@ -112,9 +112,8 @@ if test "${LANG+set}" = set; then
fi
# Make sure IFS has a sensible default
lt_nl='
'
IFS=" $lt_nl"
: ${IFS="
"}
if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
$echo "$modename: not configured to build any kind of library" 1>&2
@ -251,14 +250,37 @@ func_extract_an_archive ()
{
f_ex_an_ar_dir="$1"; shift
f_ex_an_ar_oldlib="$1"
f_ex_an_ar_lib=`$echo "X$f_ex_an_ar_oldlib" | $Xsed -e 's%^.*/%%'`
$show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
$run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
:
else
$echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
exit $EXIT_FAILURE
$echo "$modename: warning: object name conflicts; renaming object files" 1>&2
$echo "$modename: warning: to ensure that they will not overwrite" 1>&2
$show "cp $f_ex_an_ar_oldlib $f_ex_an_ar_dir/$f_ex_an_ar_lib"
$run eval "cp \$f_ex_an_ar_oldlib \$f_ex_an_ar_dir/\$f_ex_an_ar_lib"
$AR t "$f_ex_an_ar_oldlib" | sort | uniq -c \
| $EGREP -v '^[ ]*1[ ]' | while read count name
do
i=1
while test "$i" -le "$count"
do
# Put our $i before any first dot (extension)
# Never overwrite any file
name_to="$name"
while test "X$name_to" = "X$name" || test -f "$f_ex_an_ar_dir/$name_to"
do
name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
done
$show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_lib '$name' && $mv '$name' '$name_to')"
$run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_lib '$name' && $mv '$name' '$name_to' && $AR -d \$f_ex_an_ar_lib '$name')" || exit $?
i=`expr $i + 1`
done
done
$show "$rm $f_ex_an_ar_dir/$f_ex_an_ar_lib"
$run eval "$rm \$f_ex_an_ar_dir/\$f_ex_an_ar_lib"
fi
}
@ -735,15 +757,6 @@ if test -z "$show_help"; then
esac
done
qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
case $qlibobj in
*$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
qlibobj="\"$qlibobj\"" ;;
esac
if test "X$libobj" != "X$qlibobj"; then
$echo "$modename: libobj name \`$libobj' may not contain shell special characters."
exit $EXIT_FAILURE
fi
objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
if test "X$xdir" = "X$obj"; then
@ -816,17 +829,12 @@ compiler."
$run $rm $removelist
exit $EXIT_FAILURE
fi
$echo "$srcfile" > "$lockfile"
$echo $srcfile > "$lockfile"
fi
if test -n "$fix_srcfile_path"; then
eval srcfile=\"$fix_srcfile_path\"
fi
qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
case $qsrcfile in
*$quote_scanset* | *]* | *\|* | *\&* | *\(* | *\)* | "")
qsrcfile="\"$qsrcfile\"" ;;
esac
$run $rm "$libobj" "${libobj}T"
@ -848,10 +856,10 @@ EOF
fbsd_hideous_sh_bug=$base_compile
if test "$pic_mode" != no; then
command="$base_compile $qsrcfile $pic_flag"
command="$base_compile $srcfile $pic_flag"
else
# Don't build PIC code
command="$base_compile $qsrcfile"
command="$base_compile $srcfile"
fi
if test ! -d "${xdir}$objdir"; then
@ -931,9 +939,9 @@ EOF
if test "$build_old_libs" = yes; then
if test "$pic_mode" != yes; then
# Don't build PIC code
command="$base_compile $qsrcfile"
command="$base_compile $srcfile"
else
command="$base_compile $qsrcfile $pic_flag"
command="$base_compile $srcfile $pic_flag"
fi
if test "$compiler_c_o" = yes; then
command="$command -o $obj"
@ -1357,8 +1365,6 @@ EOF
;;
darwin_framework)
compiler_flags="$compiler_flags $arg"
compile_command="$compile_command $arg"
finalize_command="$finalize_command $arg"
prev=
continue
;;
@ -1423,8 +1429,6 @@ EOF
-framework)
prev=darwin_framework
compiler_flags="$compiler_flags $arg"
compile_command="$compile_command $arg"
finalize_command="$finalize_command $arg"
continue
;;
@ -2848,13 +2852,13 @@ EOF
*) continue ;;
esac
case " $deplibs " in
*" $path "*) ;;
*) deplibs="$path $deplibs" ;;
esac
case " $deplibs " in
*" $depdepl "*) ;;
*) deplibs="$depdepl $deplibs" ;;
esac
case " $deplibs " in
*" $path "*) ;;
*) deplibs="$deplibs $path" ;;
esac
done
fi # link_all_deplibs != no
fi # linkmode = lib
@ -3120,7 +3124,7 @@ EOF
case $current in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
$echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
$echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
exit $EXIT_FAILURE
;;
@ -3129,7 +3133,7 @@ EOF
case $revision in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
$echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
$echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
exit $EXIT_FAILURE
;;
@ -3138,7 +3142,7 @@ EOF
case $age in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
$echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
$echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
$echo "$modename: \`$vinfo' is not valid version information" 1>&2
exit $EXIT_FAILURE
;;
@ -5087,63 +5091,6 @@ fi\
if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
cmds=$old_archive_from_new_cmds
else
# POSIX demands no paths to be encoded in archives. We have
# to avoid creating archives with duplicate basenames if we
# might have to extract them afterwards, e.g., when creating a
# static archive out of a convenience library, or when linking
# the entirety of a libtool archive into another (currently
# not supported by libtool).
if (for obj in $oldobjs
do
$echo "X$obj" | $Xsed -e 's%^.*/%%'
done | sort | sort -uc >/dev/null 2>&1); then
:
else
$echo "copying selected object files to avoid basename conflicts..."
if test -z "$gentop"; then
gentop="$output_objdir/${outputname}x"
generated="$generated $gentop"
$show "${rm}r $gentop"
$run ${rm}r "$gentop"
$show "$mkdir $gentop"
$run $mkdir "$gentop"
status=$?
if test "$status" -ne 0 && test ! -d "$gentop"; then
exit $status
fi
fi
save_oldobjs=$oldobjs
oldobjs=
counter=1
for obj in $save_oldobjs
do
objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
case " $oldobjs " in
" ") oldobjs=$obj ;;
*[\ /]"$objbase "*)
while :; do
# Make sure we don't pick an alternate name that also
# overlaps.
newobj=lt$counter-$objbase
counter=`expr $counter + 1`
case " $oldobjs " in
*[\ /]"$newobj "*) ;;
*) if test ! -f "$gentop/$newobj"; then break; fi ;;
esac
done
$show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
$run ln "$obj" "$gentop/$newobj" ||
$run cp "$obj" "$gentop/$newobj"
oldobjs="$oldobjs $gentop/$newobj"
;;
*) oldobjs="$oldobjs $obj" ;;
esac
done
fi
eval cmds=\"$old_archive_cmds\"
if len=`expr "X$cmds" : ".*"` &&
@ -5157,7 +5104,20 @@ fi\
objlist=
concat_cmds=
save_oldobjs=$oldobjs
# GNU ar 2.10+ was changed to match POSIX; thus no paths are
# encoded into archives. This makes 'ar r' malfunction in
# this piecewise linking case whenever conflicting object
# names appear in distinct ar calls; check, warn and compensate.
if (for obj in $save_oldobjs
do
$echo "X$obj" | $Xsed -e 's%^.*/%%'
done | sort | sort -uc >/dev/null 2>&1); then
:
else
$echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
$echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
AR_FLAGS=cq
fi
# Is there a better way of finding the last object in the list?
for obj in $save_oldobjs
do
@ -6066,14 +6026,14 @@ relink_command=\"$relink_command\""
fi
# Now prepare to actually exec the command.
exec_cmd="\$cmd$args"
exec_cmd="\"\$cmd\"$args"
else
# Display what would be done.
if test -n "$shlibpath_var"; then
eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
$echo "export $shlibpath_var"
fi
$echo "$cmd$args"
eval \$echo \"\$cmd\"$args
exit $EXIT_SUCCESS
fi
;;

View File

@ -15,7 +15,7 @@ bin_PROGRAMS = ntfsfix ntfsinfo ntfscluster ntfsls ntfscat
sbin_PROGRAMS = mkntfs ntfslabel ntfsundelete ntfsresize ntfsclone \
ntfscp
EXTRA_PROGRAMS = ntfsdump_logfile ntfswipe ntfstruncate ntfsmove \
ntfsrm ntfsmftalloc
ntfsrm ntfsmftalloc ntfsdecrypt
man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
@ -87,6 +87,10 @@ endif
# We don't distribute these
ntfsdecrypt_SOURCES = ntfsdecrypt.c decrypt.c decrypt.h utils.c utils.h
ntfsdecrypt_LDADD = $(AM_LIBS)
ntfsdecrypt_LDFLAGS = $(AM_LFLAGS) -lgcrypt
ntfsrm_SOURCES = ntfsrm.c ntfsrm.h utils.c utils.h
ntfsrm_LDADD = $(AM_LIBS)
ntfsrm_LDFLAGS = $(AM_LFLAGS)

View File

@ -14,7 +14,7 @@
@SET_MAKE@
SOURCES = $(mkntfs_SOURCES) $(ntfscat_SOURCES) $(ntfsclone_SOURCES) $(ntfscluster_SOURCES) $(ntfscp_SOURCES) $(ntfsdump_logfile_SOURCES) $(ntfsfix_SOURCES) $(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) $(ntfsls_SOURCES) $(ntfsmftalloc_SOURCES) $(ntfsmount_SOURCES) $(ntfsmove_SOURCES) $(ntfsresize_SOURCES) $(ntfsrm_SOURCES) $(ntfstruncate_SOURCES) $(ntfsundelete_SOURCES) $(ntfswipe_SOURCES)
SOURCES = $(mkntfs_SOURCES) $(ntfscat_SOURCES) $(ntfsclone_SOURCES) $(ntfscluster_SOURCES) $(ntfscp_SOURCES) $(ntfsdecrypt_SOURCES) $(ntfsdump_logfile_SOURCES) $(ntfsfix_SOURCES) $(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) $(ntfsls_SOURCES) $(ntfsmftalloc_SOURCES) $(ntfsmount_SOURCES) $(ntfsmove_SOURCES) $(ntfsresize_SOURCES) $(ntfsrm_SOURCES) $(ntfstruncate_SOURCES) $(ntfsundelete_SOURCES) $(ntfswipe_SOURCES)
srcdir = @srcdir@
top_srcdir = @top_srcdir@
@ -46,7 +46,7 @@ sbin_PROGRAMS = mkntfs$(EXEEXT) ntfslabel$(EXEEXT) \
ntfscp$(EXEEXT)
EXTRA_PROGRAMS = ntfsdump_logfile$(EXEEXT) ntfswipe$(EXEEXT) \
ntfstruncate$(EXEEXT) ntfsmove$(EXEEXT) ntfsrm$(EXEEXT) \
ntfsmftalloc$(EXEEXT)
ntfsmftalloc$(EXEEXT) ntfsdecrypt$(EXEEXT)
@ENABLE_FUSE_MODULE_TRUE@am__append_1 = ntfsmount
subdir = ntfsprogs
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@ -93,6 +93,10 @@ ntfscluster_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_ntfscp_OBJECTS = ntfscp.$(OBJEXT) utils.$(OBJEXT)
ntfscp_OBJECTS = $(am_ntfscp_OBJECTS)
ntfscp_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_ntfsdecrypt_OBJECTS = ntfsdecrypt.$(OBJEXT) decrypt.$(OBJEXT) \
utils.$(OBJEXT)
ntfsdecrypt_OBJECTS = $(am_ntfsdecrypt_OBJECTS)
ntfsdecrypt_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_ntfsdump_logfile_OBJECTS = ntfsdump_logfile.$(OBJEXT)
ntfsdump_logfile_OBJECTS = $(am_ntfsdump_logfile_OBJECTS)
ntfsdump_logfile_DEPENDENCIES = $(am__DEPENDENCIES_1)
@ -150,18 +154,19 @@ LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
CCLD = $(CC)
SOURCES = $(mkntfs_SOURCES) $(ntfscat_SOURCES) $(ntfsclone_SOURCES) \
$(ntfscluster_SOURCES) $(ntfscp_SOURCES) \
$(ntfsdump_logfile_SOURCES) $(ntfsfix_SOURCES) \
$(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) $(ntfsls_SOURCES) \
$(ntfsmftalloc_SOURCES) $(ntfsmount_SOURCES) \
$(ntfsdecrypt_SOURCES) $(ntfsdump_logfile_SOURCES) \
$(ntfsfix_SOURCES) $(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) \
$(ntfsls_SOURCES) $(ntfsmftalloc_SOURCES) $(ntfsmount_SOURCES) \
$(ntfsmove_SOURCES) $(ntfsresize_SOURCES) $(ntfsrm_SOURCES) \
$(ntfstruncate_SOURCES) $(ntfsundelete_SOURCES) \
$(ntfswipe_SOURCES)
DIST_SOURCES = $(mkntfs_SOURCES) $(ntfscat_SOURCES) \
$(ntfsclone_SOURCES) $(ntfscluster_SOURCES) $(ntfscp_SOURCES) \
$(ntfsdump_logfile_SOURCES) $(ntfsfix_SOURCES) \
$(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) $(ntfsls_SOURCES) \
$(ntfsmftalloc_SOURCES) $(am__ntfsmount_SOURCES_DIST) \
$(ntfsmove_SOURCES) $(ntfsresize_SOURCES) $(ntfsrm_SOURCES) \
$(ntfsdecrypt_SOURCES) $(ntfsdump_logfile_SOURCES) \
$(ntfsfix_SOURCES) $(ntfsinfo_SOURCES) $(ntfslabel_SOURCES) \
$(ntfsls_SOURCES) $(ntfsmftalloc_SOURCES) \
$(am__ntfsmount_SOURCES_DIST) $(ntfsmove_SOURCES) \
$(ntfsresize_SOURCES) $(ntfsrm_SOURCES) \
$(ntfstruncate_SOURCES) $(ntfsundelete_SOURCES) \
$(ntfswipe_SOURCES)
man8dir = $(mandir)/man8
@ -241,7 +246,6 @@ ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
all_includes = @all_includes@
all_libraries = @all_libraries@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
@ -344,6 +348,9 @@ ntfscp_LDFLAGS = $(AM_LFLAGS)
@ENABLE_FUSE_MODULE_TRUE@ntfsmount_CFLAGS = $(FUSE_MODULE_CFLAGS) -DFUSE_USE_VERSION=22
# We don't distribute these
ntfsdecrypt_SOURCES = ntfsdecrypt.c decrypt.c decrypt.h utils.c utils.h
ntfsdecrypt_LDADD = $(AM_LIBS)
ntfsdecrypt_LDFLAGS = $(AM_LFLAGS) -lgcrypt
ntfsrm_SOURCES = ntfsrm.c ntfsrm.h utils.c utils.h
ntfsrm_LDADD = $(AM_LIBS)
ntfsrm_LDFLAGS = $(AM_LFLAGS)
@ -492,6 +499,9 @@ ntfscluster$(EXEEXT): $(ntfscluster_OBJECTS) $(ntfscluster_DEPENDENCIES)
ntfscp$(EXEEXT): $(ntfscp_OBJECTS) $(ntfscp_DEPENDENCIES)
@rm -f ntfscp$(EXEEXT)
$(LINK) $(ntfscp_LDFLAGS) $(ntfscp_OBJECTS) $(ntfscp_LDADD) $(LIBS)
ntfsdecrypt$(EXEEXT): $(ntfsdecrypt_OBJECTS) $(ntfsdecrypt_DEPENDENCIES)
@rm -f ntfsdecrypt$(EXEEXT)
$(LINK) $(ntfsdecrypt_LDFLAGS) $(ntfsdecrypt_OBJECTS) $(ntfsdecrypt_LDADD) $(LIBS)
ntfsdump_logfile$(EXEEXT): $(ntfsdump_logfile_OBJECTS) $(ntfsdump_logfile_DEPENDENCIES)
@rm -f ntfsdump_logfile$(EXEEXT)
$(LINK) $(ntfsdump_logfile_LDFLAGS) $(ntfsdump_logfile_OBJECTS) $(ntfsdump_logfile_LDADD) $(LIBS)
@ -541,11 +551,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attrdef.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cluster.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkntfs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsclone.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscluster.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfscp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsdecrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsdump_logfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsfix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntfsinfo.Po@am__quote@

532
ntfsprogs/decrypt.c 100644
View File

@ -0,0 +1,532 @@
/*
* decrypt.c - Part of the Linux-NTFS project.
*
* Copyright (c) 2005 Yuval Fledel
*
* $EFS decryption routines.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program (in the main directory of the Linux-NTFS distribution
* in the file COPYING); if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <gcrypt.h>
#include "decrypt.h"
#ifdef __CYGWIN__
//#define USE_CRYPTOAPI_RSA 1
#define _WIN32_WINNT 0x501
#define WINVER 0x501
#include <windows.h>
#include <wincrypt.h>
/* Missing cygwin macros */
#ifndef CERT_SYSTEM_STORE_CURRENT_USER
#define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000
#endif
#ifndef CERT_CLOSE_STORE_CHECK_FLAG
#define CERT_CLOSE_STORE_CHECK_FLAG 2
#endif
#ifndef CRYPT_ACQUIRE_CACHE_FLAG
#define CRYPT_ACQUIRE_CACHE_FLAG 1
#endif
/* windows 2k+ imports */
typedef BOOL (WINAPI *LPFN_CryptAcquireCertificatePrivateKey) (PCCERT_CONTEXT,
DWORD, void *, HCRYPTPROV *, DWORD *, BOOL*);
typedef BOOL (WINAPI *LPFN_CertCloseStore) (HCERTSTORE, DWORD);
typedef PCCERT_CONTEXT (WINAPI *LPFN_CertFindCertificateInStore) (HCERTSTORE,
DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT);
typedef BOOL (WINAPI *LPFN_CertFreeCertificateContext) (PCCERT_CONTEXT);
typedef HCERTSTORE (WINAPI *LPFN_CertOpenStore) (LPCSTR, DWORD, HCRYPTPROV,
DWORD, const void*);
// NT4SP3+ WINME or 95+ w/ IE5+
static LPFN_CryptAcquireCertificatePrivateKey
fnCryptAcquireCertificatePrivateKey;
// osr2+ NT4SP3+ or NT4 w/ IE3.02:
static LPFN_CertCloseStore fnCertCloseStore;
static LPFN_CertFindCertificateInStore fnCertFindCertificateInStore;
static LPFN_CertFreeCertificateContext fnCertFreeCertificateContext;
static LPFN_CertOpenStore fnCertOpenStore;
/* global variable: handle to crypt32.dll */
static HMODULE hCrypt32 = INVALID_HANDLE_VALUE;
#else /* defined(__CYGWIN__) */
#include <malloc.h>
#include <string.h>
#define CALG_DESX (0x6603)
#define CALG_3DES (0x6604)
#define CALG_AES_256 (0x6610)
#endif /* defined(__CYGWIN__) */
typedef struct {
#ifdef __CYGWIN__
HCERTSTORE hSystemStore;
#else
int nothing; /* unused */
#endif /* defined(__CYGWIN__) */
} DECRYPT_SESSION;
typedef struct {
unsigned int gcry_algo;
char *key_data;
gcry_cipher_hd_t gcry_cipher_hd; // handle to the decrypted FEK.
gcry_sexp_t sexp_key; // the user's RSA key.
#ifdef USE_CRYPTOAPI_RSA
HCRYPTKEY hCryptKey;
#endif /* defined(__CYGWIN__) */
} DECRYPT_KEY;
#ifdef __CYGWIN__
static int cryptoAPI_init_imports(void)
{
if (hCrypt32 == INVALID_HANDLE_VALUE)
hCrypt32 = LoadLibrary("crypt32.dll");
if (!fnCryptAcquireCertificatePrivateKey)
fnCryptAcquireCertificatePrivateKey =
(LPFN_CryptAcquireCertificatePrivateKey)
GetProcAddress(hCrypt32,
"CryptAcquireCertificatePrivateKey");
if (!fnCertCloseStore)
fnCertCloseStore = (LPFN_CertCloseStore)
GetProcAddress(hCrypt32, "CertCloseStore");
if (!fnCertFindCertificateInStore)
fnCertFindCertificateInStore =
(LPFN_CertFindCertificateInStore)
GetProcAddress(hCrypt32, "CertFindCertificateInStore");
if (!fnCertFreeCertificateContext)
fnCertFreeCertificateContext =
(LPFN_CertFreeCertificateContext)
GetProcAddress(hCrypt32, "CertFreeCertificateContext");
if (!fnCertOpenStore)
fnCertOpenStore = (LPFN_CertOpenStore)
GetProcAddress(hCrypt32, "CertOpenStore");
return fnCryptAcquireCertificatePrivateKey && fnCertCloseStore &&
fnCertFindCertificateInStore &&
fnCertFreeCertificateContext && fnCertOpenStore;
}
#endif /* defined(__CYGWIN__) */
decrypt_session *decrypt_open(void) {
decrypt_session *session;
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
#ifdef __CYGWIN__
HCERTSTORE hSystemStore;
if (!cryptoAPI_init_imports()) {
fprintf(stderr, "Some imports do not exist.\n");
errno = -1;
return NULL;
}
if (!(hSystemStore = fnCertOpenStore(((LPCSTR)CERT_STORE_PROV_SYSTEM),
0, (HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER,
L"MY"))) {
fprintf(stderr, "Could not open system store.\n");
errno = -1;
return NULL;
}
#endif /* defined(__CYGWIN__) */
session = (decrypt_session *)malloc(sizeof(DECRYPT_SESSION));
#ifdef __CYGWIN__
((DECRYPT_SESSION *)session)->hSystemStore = hSystemStore;
#endif /* defined(__CYGWIN__) */
return session;
}
void decrypt_close(decrypt_session *session) {
#ifdef __CYGWIN__
if (((DECRYPT_SESSION *)session)->hSystemStore)
fnCertCloseStore(((DECRYPT_SESSION *)session)->hSystemStore,
CERT_CLOSE_STORE_CHECK_FLAG);
/* fixme: racy */
FreeLibrary(hCrypt32);
hCrypt32 = INVALID_HANDLE_VALUE;
#endif /* defined(__CYGWIN__) */
free(session);
}
static inline void reverse_buffer(unsigned char *buf, unsigned int buf_size) {
unsigned char t;
unsigned int i;
for (i=0; i<buf_size/2; i++) {
t = buf[i];
buf[i] = buf[buf_size-i-1];
buf[buf_size-i-1] = t;
}
}
decrypt_key *decrypt_user_key_open(decrypt_session *session
__attribute__((unused)),
int thumb_size, void *thumb_print) {
#ifdef __CYGWIN__
CRYPT_HASH_BLOB hash_blob;
HCRYPTPROV hCryptProv;
PCCERT_CONTEXT pCert;
BOOL fCallerFreeProv;
HCRYPTKEY hCryptKey;
decrypt_key *key;
DWORD dwKeySpec;
DWORD key_size;
BYTE key_blob[1000];
hash_blob.cbData = thumb_size;
hash_blob.pbData = thumb_print;
if (!(pCert = fnCertFindCertificateInStore(
((DECRYPT_SESSION *)session)->hSystemStore,
(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING),
0, CERT_FIND_HASH, &hash_blob, NULL))) {
fprintf(stderr, "Could not find cert in store.\n");
goto decrypt_key_open_err;
}
dwKeySpec = AT_KEYEXCHANGE;
if (!fnCryptAcquireCertificatePrivateKey(pCert,
CRYPT_ACQUIRE_CACHE_FLAG, NULL,
&hCryptProv, &dwKeySpec,
&fCallerFreeProv)) {
fprintf(stderr, "Could not aquire private key from cert.\n");
goto decrypt_key_open_err;
}
if (!CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hCryptKey)) {
fprintf(stderr, "Could not aquire user key.\n");
goto decrypt_key_open_err;
}
if (!CryptExportKey(hCryptKey, 0, PRIVATEKEYBLOB, 0, key_blob, &key_size)) {
fprintf(stderr, "Could not export key: Error 0x%x\n",
(unsigned int)GetLastError());
errno = -1;
return NULL;
}
if (!(key = (decrypt_key *)malloc(sizeof(DECRYPT_KEY))))
goto decrypt_key_open_err;
#ifdef USE_CRYPTOAPI_RSA
((DECRYPT_KEY *)key)->hCryptKey = hCryptKey;
#else
RSAPUBKEY *rsa_pub_key = (RSAPUBKEY *)(key_blob + sizeof(PUBLICKEYSTRUC));
gcry_ac_handle_t gcry_handle;
unsigned char *mpi_data;
gcry_mpi_t n,e,d,p,q,u;
gcry_sexp_t sexp_key;
gcry_error_t err;
size_t size;
int rc;
CryptDestroyKey(hCryptKey);
if ((err = gcry_ac_open(&gcry_handle, GCRY_AC_RSA, 0))) {
fprintf(stderr, "Could not init gcrypt handle\n");
errno = -1;
return NULL;
}
e = gcry_mpi_set_ui(NULL, rsa_pub_key->pubexp);
mpi_data = (key_blob + 0x14);
size = rsa_pub_key->bitlen / 8;
reverse_buffer(mpi_data, size);
if ((rc = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, mpi_data, size, &size))) {
fprintf(stderr, "error scanning n.\n");
}
mpi_data += (rsa_pub_key->bitlen / 8);
size = rsa_pub_key->bitlen / 16;
reverse_buffer(mpi_data, size);
if ((rc = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, mpi_data, size, &size))) {
fprintf(stderr, "error scanning p.\n");
}
mpi_data += (rsa_pub_key->bitlen / 16);
size = rsa_pub_key->bitlen / 16;
reverse_buffer(mpi_data, size);
if ((rc = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, mpi_data, size, &size))) {
fprintf(stderr, "error scanning q.\n");
}
mpi_data += (rsa_pub_key->bitlen / 16)*3;
size = rsa_pub_key->bitlen / 16;
reverse_buffer(mpi_data, size);
if ((rc = gcry_mpi_scan(&u, GCRYMPI_FMT_USG, mpi_data, size, &size))) {
fprintf(stderr, "error scanning u.\n");
}
mpi_data += (rsa_pub_key->bitlen / 16);
size = rsa_pub_key->bitlen / 8;
reverse_buffer(mpi_data, size);
if ((rc = gcry_mpi_scan(&d, GCRYMPI_FMT_USG, mpi_data, size, &size))) {
fprintf(stderr, "error scanning d.\n");
}
if ((rc = gcry_sexp_build(&sexp_key, NULL,
"(private-key (rsa (n %m) (e %m) (d %m) (p %m) (q %m) (u %m)))",
n, e, d, p, q, u))) {
fprintf(stderr, "Could build sexp from data, (error = 0x%x)\n", rc);
errno = -1;
return FALSE;
}
((DECRYPT_KEY *)key)->sexp_key = sexp_key;
// todo: release all
#endif
return key;
decrypt_key_open_err:
if (hCryptKey)
CryptDestroyKey(hCryptKey);
if (pCert)
fnCertFreeCertificateContext(pCert);
#endif // defined(__CYGWIN__)
errno = ENOTSUP;
return NULL;
}
void decrypt_user_key_close(decrypt_key *key) {
DECRYPT_KEY *dkey = (DECRYPT_KEY *)key;
if (dkey->gcry_cipher_hd)
gcry_cipher_close(dkey->gcry_cipher_hd);
free(key);
}
/**
* decrypt_decrypt
*
* warning: decrypting into the input buffer!
*/
unsigned int decrypt_decrypt(decrypt_key *key, unsigned int data_size,
unsigned char *data)
{
#ifdef USE_CRYPTOAPI_RSA
DWORD size = data_size;
if (!CryptDecrypt(((DECRYPT_KEY *)key)->hCryptKey, 0,
TRUE, 0, data, &size)) {
errno = -1;
return 0;
}
return size;
#else
gcry_sexp_t sexp_plain_data, sexp_enc_data;
gcry_ac_handle_t gcry_handle;
gcry_mpi_t mpi_buf;
gcry_ac_data_t in;
gcry_error_t err;
unsigned int size, padding_length, i;
int rc;
if ((err = gcry_ac_open(&gcry_handle, GCRY_AC_RSA, 0))) {
fprintf(stderr, "Could not init gcrypt handle\n");
errno = -1;
return FALSE;
}
if ((rc = gcry_ac_data_new(&in))) {
fprintf(stderr, "error allocating 'in'.\n");
}
reverse_buffer(data, data_size);
size = data_size;
if ((rc = gcry_mpi_scan(&mpi_buf, GCRYMPI_FMT_USG, data, (size_t)data_size, &size))) {
fprintf(stderr, "error scanning 'in'.\n");
}
if ((rc = gcry_sexp_build(&sexp_enc_data, &size, "(enc-val (flags) (rsa (a %m)))", mpi_buf))) {
fprintf(stderr, "Could build sexp from data, (error = 0x%x)\n", rc);
errno = -1;
return FALSE;
}
if ((rc = gcry_pk_decrypt(&sexp_plain_data, sexp_enc_data, ((DECRYPT_KEY *)key)->sexp_key))) {
fprintf(stderr, "Could not decrypt fek via s-exp, (error = 0x%x)\n", rc);
errno = -1;
return FALSE;
}
sexp_plain_data = gcry_sexp_find_token(sexp_plain_data, "value", 0);
if (!mpi_buf) {
fprintf(stderr, "Could find value in s-exp, (error = 0x%x)\n", rc);
errno = -1;
return FALSE;
}
mpi_buf = gcry_sexp_nth_mpi(sexp_plain_data, 1, GCRYMPI_FMT_USG);
if ((rc = gcry_mpi_print(GCRYMPI_FMT_USG, data, data_size, &size, mpi_buf))) {
fprintf(stderr, "Could copy decrypted data back, (error = 0x%x)\n", rc);
errno = -1;
return FALSE;
}
// remove the pkcs1 padding
for (padding_length = 1;(padding_length<size) && data[padding_length];
padding_length++);
padding_length++;
for (i = 0;i+padding_length<size;i++) // todo: should memcpy fit? (overlapping)
data[i]=data[padding_length+i];
// todo: mpi_buf->data
// todo: release all
gcry_ac_data_destroy(in);
return size - padding_length;
#endif // USER_CRYPTOAPI_RSA (else)
}
unsigned int decrypt_decrypt_sector(decrypt_key *key, void *data,
unsigned long long offset) {
gcry_error_t gcry_error2;
DECRYPT_KEY *dkey = (DECRYPT_KEY *)key;
if ((gcry_error2 = gcry_cipher_reset(dkey->gcry_cipher_hd))) {
fprintf(stderr, "gcry_error2 is %u.\n", gcry_error2);
}
if (dkey->gcry_algo == GCRY_CIPHER_DES_SK) {
/* CALG_DESX */
fprintf(stderr, "DESX is not supported yet.\n");
errno = -1;
return 0;
} else {
if ((gcry_error2 = gcry_cipher_decrypt(dkey->gcry_cipher_hd,
data, 512, NULL, 0))) {
fprintf(stderr, "gcry_error2 is %u.\n", gcry_error2);
}
}
switch (dkey->gcry_algo) {
case GCRY_CIPHER_DES_SK:
// don't know!
case GCRY_CIPHER_3DES:
((unsigned long long *)data)[0] ^=
0x169119629891ad13LL + offset;
break;
case GCRY_CIPHER_AES256:
((unsigned long long *)data)[0] ^=
0x5816657be9161312LL + offset;
((unsigned long long *)data)[1] ^=
0x1989adbe44918961LL + offset;
break;
default:
break;
}
return 512;
}
static decrypt_key *decrypt_make_gcry_key(char *key_data, int gcry_algo) {
int gcry_mode, gcry_length;
gcry_error_t gcry_error2;
DECRYPT_KEY *key;
if (!(key = (DECRYPT_KEY *)malloc(sizeof(DECRYPT_KEY)))) {
errno = -1;
return NULL;
}
switch (gcry_algo) {
case GCRY_CIPHER_DES_SK:
gcry_mode = GCRY_CIPHER_MODE_ECB;
gcry_length = 8;
break;
case GCRY_CIPHER_3DES:
gcry_mode = GCRY_CIPHER_MODE_CBC;
gcry_length = 24;
break;
case GCRY_CIPHER_AES256:
gcry_mode = GCRY_CIPHER_MODE_CBC;
gcry_length = 32;
break;
default:
errno = ENOTSUP;
return 0;
}
if ((gcry_error2 = gcry_cipher_open(&key->gcry_cipher_hd, gcry_algo,
gcry_mode, 0))!=GPG_ERR_NO_ERROR) {
errno = -1;
return 0;
}
if ((gcry_error2 = gcry_cipher_setkey(key->gcry_cipher_hd, key_data,
gcry_length))) {
fprintf(stderr, "gcry_error2 is %u.\n", gcry_error2);
}
key->gcry_algo = gcry_algo;
return (decrypt_key *)key;
}
decrypt_key *decrypt_make_key(
decrypt_session *session __attribute__((unused)),
unsigned int data_size __attribute__((unused)),
void *data) {
unsigned int key_size, alg_id;
char *key_data;
key_size = *((unsigned int *)data);
alg_id = *(((unsigned int *)data) + 2);
key_data = (((char *)data) + 16);
switch (alg_id) {
case CALG_DESX:
//fprintf(stderr, "DESX key of %u bytes\n", key_size);
fprintf(stderr, "DESX is not supported yet.\n");
errno = ENOTSUP;
return 0;
case CALG_3DES:
//fprintf(stderr, "3DES Key of %u bytes\n", key_size);
return decrypt_make_gcry_key(key_data,
GCRY_CIPHER_3DES);
case CALG_AES_256:
//fprintf(stderr, "AES Key of %u bytes\n", key_size);
return decrypt_make_gcry_key(key_data,
GCRY_CIPHER_AES256);
default:
fprintf(stderr, "Error: Unknown algorithm: 0x%x\n",
(unsigned int)alg_id);
errno = ENOTSUP;
return NULL;
}
}

View File

@ -0,0 +1,42 @@
/*
* decrypt.h - interface for decryption rutines.
* Part of the Linux-NTFS project.
*
* Copyright (c) 2005 Yuval Fledel
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_DECRYPT_H
#define _NTFS_DECRYPT_H
typedef void *decrypt_session;
typedef void *decrypt_key;
extern decrypt_session *decrypt_open(void);
extern void decrypt_close(decrypt_session *session);
extern decrypt_key *decrypt_user_key_open(decrypt_session *session,
int thumb_size, void *thumb_print);
extern void decrypt_user_key_close(decrypt_key *key);
extern unsigned int decrypt_decrypt(decrypt_key *key, unsigned int data_size,
unsigned char *data);
extern unsigned int decrypt_decrypt_sector(decrypt_key *key, void *data,
unsigned long long offset);
extern decrypt_key *decrypt_make_key(decrypt_session *session,
unsigned int data_size, void *data);
extern int decrypt_get_block_size(decrypt_key *key);
#endif /* defined _NTFS_DECRYPT_H */

View File

@ -0,0 +1,415 @@
/**
* ntfsdecrypt - Part of the Linux-NTFS project.
*
* Copyright (c) 2003 Richard Russon
* Copyright (c) 2003 Anton Altaparmakov
* Copyright (c) 2005 Yuval Fledel
*
* This utility will decrypt files and print on the standard output.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "attrib.h"
#include "utils.h"
#include "volume.h"
#include "debug.h"
#include "dir.h"
#include "layout.h"
#include "decrypt.h"
struct options {
char *device; /* Device/File to work with */
char *file; /* File to display */
s64 inode; /* Inode to work with */
ATTR_TYPES attr; /* Attribute type to display */
int force; /* Override common sense */
int quiet; /* Less output */
int verbose; /* Extra output */
};
static const char *EXEC_NAME = "ntfscat";
static struct options opts;
GEN_PRINTF (Eprintf, stderr, NULL, FALSE)
GEN_PRINTF (Vprintf, stderr, &opts.verbose, TRUE)
GEN_PRINTF (Qprintf, stderr, &opts.quiet, FALSE)
static GEN_PRINTF (Printf, stderr, NULL, FALSE)
static const wchar_t *efs_name = L"$EFS";
static const int efs_name_length = 4;
/**
* version - Print version information about the program
*
* Print a copyright statement and a brief description of the program.
*
* Return: none
*/
static void version (void)
{
Printf ("\n%s v%s - Concatenate files and print on the standard output.\n\n",
EXEC_NAME, VERSION);
Printf ("Copyright (c) 2003 Richard Russon\n");
Printf ("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
/**
* usage - Print a list of the parameters to the program
*
* Print a list of the parameters and options for the program.
*
* Return: none
*/
static void usage (void)
{
Printf ("\nUsage: %s [options] device [file]\n\n"
" -a, --attribute num Display this attribute\n"
" -i, --inode num Display this inode\n\n"
" -f --force Use less caution\n"
" -h --help Print this help\n"
" -q --quiet Less output\n"
" -V --version Version information\n"
" -v --verbose More output\n\n",
//" -N --name Display this attribute name",
//" -F --file Display this file",
//" -r --raw Display the compressed or encrypted file",
EXEC_NAME);
Printf ("%s%s\n", ntfs_bugs, ntfs_home);
}
/**
* parse_options - Read and validate the programs command line
*
* Read the command line, verify the syntax and parse the options.
* This function is very long, but quite simple.
*
* Return: 1 Success
* 0 Error, one or more problems
*/
static int parse_options (int argc, char **argv)
{
static const char *sopt = "-a:fh?i:qVv"; // F:N:
static const struct option lopt[] = {
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "inode", required_argument, NULL, 'i' },
{ "quiet", no_argument, NULL, 'q' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
// { "file", required_argument, NULL, 'F' },
// { "name", required_argument, NULL, 'N' },
{ NULL, 0, NULL, 0 }
};
char c = -1;
int err = 0;
int ver = 0;
int help = 0;
opterr = 0; /* We'll handle the errors, thank you. */
opts.inode = -1;
while ((c = getopt_long (argc, argv, sopt, lopt, NULL)) != (char)-1) {
switch (c) {
case 1: /* A non-option argument */
if (!opts.device) {
opts.device = argv[optind-1];
} else if (!opts.file) {
opts.file = argv[optind-1];
} else {
Eprintf("You must specify exactly one file.\n");
err++;
}
break;
case 'f':
opts.force++;
break;
case 'h':
case '?':
help++;
break;
case 'i':
if (opts.inode != -1)
Eprintf("You must specify exactly one inode.\n");
else if (utils_parse_size(optarg, &opts.inode, FALSE))
break;
else
Eprintf("Couldn't parse inode number.\n");
err++;
break;
case 'q':
opts.quiet++;
break;
case 'V':
ver++;
break;
case 'v':
opts.verbose++;
break;
default:
Eprintf ("Unknown option '%s'.\n", argv[optind-1]);
err++;
break;
}
}
if (help || ver) {
opts.quiet = 0;
} else {
if (opts.device == NULL) {
Eprintf ("You must specify a device.\n");
err++;
} else if (opts.file == NULL && opts.inode == -1) {
Eprintf ("You must specify a file or inode "
"with the -i option.\n");
err++;
} else if (opts.file != NULL && opts.inode != -1) {
Eprintf ("You can't specify both a file and inode.\n");
err++;
}
if (opts.quiet && opts.verbose) {
Eprintf("You may not use --quiet and --verbose at the "
"same time.\n");
err++;
}
}
if (ver)
version();
if (help || err)
usage();
return (!err && !help && !ver);
}
/**
* cat
*/
static int cat_decrypt(ntfs_inode *inode, decrypt_key *fek)
{
int bufsize = 512;
char *buffer;
ntfs_attr *attr;
s64 bytes_read, written, offset, total;
unsigned int i;
buffer = malloc (bufsize);
if (!buffer)
return 1;
attr = ntfs_attr_open (inode, AT_DATA, NULL, 0);
if (!attr) {
Eprintf ("Cannot cat a directory.\n");
free (buffer);
return 1;
}
total = attr->data_size;
// hack: make sure attr will not be commited to disk if you use this.
// clear the encrypted bit, otherwise the library won't allow reading.
NAttrClearEncrypted(attr);
// extend the size, we may need to read past the end of the stream.
attr->data_size = attr->initialized_size = attr->allocated_size;
offset = 0;
while (total>0) {
bytes_read = ntfs_attr_pread (attr, offset, 512, buffer);
if (bytes_read == -1) {
perror ("ERROR: Couldn't read file");
break;
}
if (!bytes_read)
break;
if ((i = decrypt_decrypt_sector(fek, buffer, offset))
< bytes_read) {
perror ("ERROR: Couldn't decrypt all data!");
Eprintf("%u/%lld/%lld/%lld\n", i, (long long)bytes_read,
(long long)offset, (long long)total);
break;
}
if (bytes_read > total)
bytes_read = total;
written = fwrite (buffer, 1, bytes_read, stdout);
if (written != bytes_read) {
perror ("ERROR: Couldn't output all data!");
break;
}
offset += bytes_read;
total -= bytes_read;
}
ntfs_attr_close (attr);
free (buffer);
return 0;
}
/**
* get_fek
*/
static decrypt_key *get_fek (ntfs_inode *inode)
{
ntfs_attr *na;
char *efs_buffer, *ddf, *certificate, *hash_data, *fek_buf;
u32 ddf_count, hash_size, fek_size;
unsigned int i;
decrypt_session *session;
decrypt_key *key;
/* obtain the $EFS contents */
na = ntfs_attr_open (inode, AT_LOGGED_UTILITY_STREAM,
efs_name, efs_name_length);
if (!na) {
perror("Error");
return NULL;
}
efs_buffer = malloc(na->data_size);
if (!efs_buffer) {
perror("malloc failed");
return NULL;
}
if (ntfs_attr_pread(na, 0, na->data_size, efs_buffer) !=
na->data_size) {
perror("ntfs_attr_pread failed");
free(efs_buffer);
return NULL;
}
ntfs_attr_close(na);
/* init the CryptoAPI */
if(!(session = decrypt_open())) {
perror("Could not init the cryptoAPI.");
return NULL;
}
/* iterate through the DDFs & DRFs until you obtain a key */
ddf = efs_buffer + le32_to_cpu(*(u32 *)(efs_buffer+0x40));
ddf_count = le32_to_cpu(*(u32 *)ddf);
ddf = ddf + 0x04;
for (i=0;i<ddf_count;i++) {
//Eprintf("ddf #%u.\n", i);
if (*(u32 *)(ddf+0x18))
certificate = (ddf + 0x30 +
le32_to_cpu(*(u32 *)(ddf+0x18)));
else
certificate = (ddf + 0x30);
hash_size = (unsigned int)le32_to_cpu(*(u32 *)certificate);
hash_data = certificate +
(unsigned int)le32_to_cpu(*(u32 *)(certificate+0x04));
fek_size = (unsigned int)le32_to_cpu(*(u32 *)(ddf+0x08));
fek_buf = ddf + (unsigned int)le32_to_cpu(*(u32 *)(ddf+0x0C));
if ((key = decrypt_user_key_open(session, hash_size, hash_data))) {
if ((fek_size = decrypt_decrypt(key, fek_size,
fek_buf))) {
return decrypt_make_key(session, fek_size,
fek_buf);
}
perror("error decrypting the FEK.");
decrypt_user_key_close(key);
decrypt_close(session);
errno = -1;
return NULL;
decrypt_user_key_close(key);
} else
Eprintf("Could not open key.\n");
ddf = ddf + le32_to_cpu(*(u32 *)(ddf+0x08)) +
le32_to_cpu(*(u32 *)(ddf+0x0C));
}
decrypt_close(session);
return NULL;
}
/**
* main - Begin here
*
* Start from here.
*
* Return: 0 Success, the program worked
* 1 Error, something went wrong
*/
int main (int argc, char *argv[])
{
ntfs_volume *vol;
ntfs_inode *inode;
decrypt_key *fek;
int result = 1;
if (!parse_options (argc, argv))
return 1;
utils_set_locale();
//XXX quieten errors, temporarily
vol = utils_mount_volume (opts.device, MS_RDONLY, opts.force);
if (!vol) {
perror("ERROR: couldn't mount volume");
return 1;
}
if (opts.inode != -1)
inode = ntfs_inode_open (vol, opts.inode);
else
inode = utils_pathname_to_inode (vol, NULL, opts.file);
if (!inode) {
perror("ERROR: Couldn't open inode");
return 1;
}
fek = get_fek(inode);
if (fek) {
result = cat_decrypt (inode, fek);
decrypt_user_key_close(fek);
} else {
Eprintf("Could not obtain FEK.");
result = 1;
}
ntfs_inode_close (inode);
ntfs_umount (vol, FALSE);
#if 0
if (result)
Printf ("failed\n");
else
Printf ("success\n");
#endif
return result;
}