mirror of git://git.gnupg.org/gnupg.git
Update head to match stable 1.0
This commit is contained in:
parent
98a05e4239
commit
151ee2f47b
113
checks/ChangeLog
113
checks/ChangeLog
|
@ -1,23 +1,110 @@
|
|||
Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de>
|
||||
2002-05-10 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* run-gpg: redirect fgrep output to stderr
|
||||
* Makefile.am: Add gpg_dearmor to all targets where it is used.
|
||||
Noted by Andreas Haumer.
|
||||
|
||||
Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
2002-04-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* genkey1024.test: Does not use --quick-random anymore.
|
||||
* signencrypt-dsa.test, sigs-dsa.test: Don't check with MD5 as
|
||||
this is not valid with DSA signatures.
|
||||
|
||||
Thu Oct 28 16:17:46 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
2001-12-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* options.in: Add no-permission-warning.
|
||||
|
||||
2001-12-21 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am (distclean-local): prefix mkdemodirs with srcdir
|
||||
(DISTCLEANFILES): Add random_seed.
|
||||
|
||||
2001-12-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* options.in: Remove load-extension tiger
|
||||
* Makefile.am (./options): append it if there is such a module.
|
||||
|
||||
2001-10-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* defs.inc, Makefile.am: Do not use $srcdir when invoking gpg.
|
||||
Write the logfile to the current directory.
|
||||
|
||||
2001-09-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* defs.inc: Write a log file for each test.
|
||||
* run-gpg, run-gpgm, run-gpg.patterns: Removed. Replaced in all
|
||||
tests by a simple macro from defs.inc.
|
||||
* Makefile.am (CLEANFILES): Remove log files.
|
||||
(./gpg_dearmor): create it and use it instead of the macro.
|
||||
This is needed in multisig.test due to IFS tricks.
|
||||
|
||||
* armsignencrypt.test, signencrypt-dsa.test, signencrypt.test,
|
||||
armencryptp.test, armencrypt.test, encryptp.test, seat.test,
|
||||
encrypt-dsa.test, encrypt.test: Use --always-trust because the
|
||||
test are not designed to check the validity.
|
||||
|
||||
2001-09-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* genkey1024.test: Simplified by using a parameter file.
|
||||
|
||||
2001-05-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* multisig.test (IFS): Reset IFS just before the test.
|
||||
|
||||
2001-04-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* multisig.test: Add an set +x to avoid ksh problems
|
||||
|
||||
2001-04-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* run-gpg.patterns: a v3 test key expired yesterday, suppress the
|
||||
messages.
|
||||
|
||||
2001-03-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* defs.inc: Removed creation of options file.
|
||||
* options.in: New.
|
||||
* Makefile.am: Create options file and fixed import of pubdemo.asc.
|
||||
|
||||
* run-gpg.patterns (gpg): Add some more patterns.
|
||||
|
||||
2001-03-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am: Import the pubdemo.asc file
|
||||
|
||||
* sigs.test (hash_algo_list): s/tiger/tiger192/
|
||||
|
||||
2001-03-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* mkdemodirs (GPGDEMO): Add --allow-secret-key-import to all gpg
|
||||
invocations. Use echon -n instead of an argument with \c.
|
||||
|
||||
2001-02-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* multisig.test: new
|
||||
* Makefile.am (TESTS): Added.
|
||||
|
||||
2000-10-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* conventional-mdc.test: Add Rijndael and fix for empty plain texts.
|
||||
|
||||
Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* mkdemodirs: Fixed the --clean loop.
|
||||
|
||||
Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* defs.inc (chdir): Removed becuase it is unsused an plain old sh
|
||||
does not like this name. Reported by Alec Habig.
|
||||
|
||||
Tue Oct 26 20:02:23 1999 Werner Koch (wk@gnupg.org)
|
||||
|
||||
* Makefile.am (GPG_DEARMOR): New and use --no-options.
|
||||
|
||||
Tue Aug 31 17:20:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* defs.inc: set LC_ALL empty
|
||||
|
||||
Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* defs.inc (echo_n): New and used instead of /bin/echo "\c"
|
||||
|
||||
Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
@ -70,3 +157,15 @@ Mon May 18 15:40:02 1998 Werner Koch (wk@isil.d.shuttle.de)
|
|||
|
||||
* ChangeLog: New.
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
## Process this file with automake to create Makefile.in
|
||||
# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG 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.
|
||||
#
|
||||
# GnuPG 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; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
GPG_DEARMOR = ../g10/gpg --no-options --quiet --yes --dearmor
|
||||
# Process this file with automake to create Makefile.in
|
||||
|
||||
GPG_IMPORT = ../g10/gpg --homedir . --quiet --yes --import
|
||||
|
||||
TESTS = version.test mds.test \
|
||||
decrypt.test decrypt-dsa.test \
|
||||
|
@ -11,54 +29,67 @@ TESTS = version.test mds.test \
|
|||
signencrypt.test signencrypt-dsa.test \
|
||||
armsignencrypt.test armdetach.test \
|
||||
armdetachm.test detachm.test genkey1024.test \
|
||||
conventional.test
|
||||
conventional.test conventional-mdc.test \
|
||||
multisig.test
|
||||
|
||||
|
||||
TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
|
||||
plain-1.asc plain-2.asc plain-3.asc plain-1-pgp.asc \
|
||||
pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc
|
||||
pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc options.in
|
||||
|
||||
DATA_FILES = data-500 data-9000 data-32000 data-80000 plain-large
|
||||
|
||||
EXTRA_DIST = defs.inc run-gpg run-gpg.patterns $(TESTS) $(TEST_FILES) \
|
||||
EXTRA_DIST = defs.inc $(TESTS) $(TEST_FILES) \
|
||||
mkdemodirs signdemokey
|
||||
CLEANFILES = prepared.stamp x y yy z out err $(DATA_FILES) \
|
||||
plain-1 plain-2 plain-3 options trustdb.gpg *.lock .\#lk* \
|
||||
plain-1 plain-2 plain-3 trustdb.gpg *.lock .\#lk* \
|
||||
*.test.log options gpg_dearmor \
|
||||
pubring.gpg secring.gpg pubring.pkr secring.skr
|
||||
DISTCLEANFILES = pubring.gpg~
|
||||
DISTCLEANFILES = pubring.gpg~ random_seed
|
||||
|
||||
|
||||
all-local: prepared.stamp
|
||||
|
||||
distclean-local:
|
||||
./mkdemodirs --clean
|
||||
$(srcdir)/mkdemodirs --clean
|
||||
|
||||
prepared.stamp: ./pubring.gpg ./secring.gpg ./plain-1 ./plain-2 ./plain-3 \
|
||||
./pubring.pkr ./secring.skr $(DATA_FILES)
|
||||
./pubring.pkr ./secring.skr ./options ./gpg_dearmor \
|
||||
$(DATA_FILES)
|
||||
$(GPG_IMPORT) $(srcdir)/pubdemo.asc
|
||||
echo timestamp >./prepared.stamp
|
||||
|
||||
./options: $(srcdir)/options.in
|
||||
cat $(srcdir)/options.in >./options
|
||||
@set -e; if echo "@DYNAMIC_CIPHER_MODS@" |grep tiger >/dev/null ;then \
|
||||
echo load-extension ../cipher/tiger >>./options; fi
|
||||
|
||||
./pubring.gpg: $(srcdir)/pubring.asc
|
||||
$(GPG_DEARMOR) -o ./pubring.gpg $(srcdir)/pubring.asc
|
||||
./gpg_dearmor:
|
||||
echo '#!/bin/sh' >./gpg_dearmor
|
||||
echo "../g10/gpg --no-options --no-greeting \
|
||||
--no-secmem-warning --batch --dearmor" >>./gpg_dearmor
|
||||
chmod 755 ./gpg_dearmor
|
||||
|
||||
./secring.gpg: $(srcdir)/secring.asc
|
||||
$(GPG_DEARMOR) -o ./secring.gpg $(srcdir)/secring.asc
|
||||
./pubring.gpg: $(srcdir)/pubring.asc $(srcdir)/pubdemo.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./pubring.gpg < $(srcdir)/pubring.asc
|
||||
|
||||
./pubring.pkr: $(srcdir)/pubring.pkr.asc
|
||||
$(GPG_DEARMOR) -o ./pubring.pkr $(srcdir)/pubring.pkr.asc
|
||||
./secring.gpg: $(srcdir)/secring.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./secring.gpg < $(srcdir)/secring.asc
|
||||
|
||||
./secring.skr: $(srcdir)/secring.skr.asc
|
||||
$(GPG_DEARMOR) -o ./secring.skr $(srcdir)/secring.skr.asc
|
||||
./pubring.pkr: $(srcdir)/pubring.pkr.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./pubring.pkr < $(srcdir)/pubring.pkr.asc
|
||||
|
||||
./plain-1: $(srcdir)/plain-1o.asc
|
||||
$(GPG_DEARMOR) -o ./plain-1 $(srcdir)/plain-1o.asc
|
||||
./secring.skr: $(srcdir)/secring.skr.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./secring.skr < $(srcdir)/secring.skr.asc
|
||||
|
||||
./plain-2: $(srcdir)/plain-2o.asc
|
||||
$(GPG_DEARMOR) -o ./plain-2 $(srcdir)/plain-2o.asc
|
||||
./plain-1: $(srcdir)/plain-1o.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./plain-1 < $(srcdir)/plain-1o.asc
|
||||
|
||||
./plain-3: $(srcdir)/plain-3o.asc
|
||||
$(GPG_DEARMOR) -o ./plain-3 $(srcdir)/plain-3o.asc
|
||||
./plain-2: $(srcdir)/plain-2o.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./plain-2 < $(srcdir)/plain-2o.asc
|
||||
|
||||
./plain-3: $(srcdir)/plain-3o.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./plain-3 < $(srcdir)/plain-3o.asc
|
||||
|
||||
|
||||
data-500:
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#info Checking armored detached signatures
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -sab -o x --yes $i
|
||||
$srcdir/run-gpg -o /dev/null --yes x <$i || error "$i: bad signature"
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sab -o x --yes $i
|
||||
$GPG -o /dev/null --yes x <$i || error "$i: bad signature"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
#info Checking armored detached signatures of multiple files
|
||||
i="$plain_files $data_files"
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -sab -o x --yes $i
|
||||
cat $i | $srcdir/run-gpg -o /dev/null --yes x || error "$i: bad signature"
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sab -o x --yes $i
|
||||
cat $i | $GPG -o /dev/null --yes x || error "$i: bad signature"
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#info Checking armored encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg -ea -o x --yes -r "$usrname2" $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
$GPG --always-trust -ea -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
#info Checking armored encryption with a pipe
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg -ea --yes -r "$usrname2" < $i | tee x | $srcdir/run-gpg -o y --yes
|
||||
$GPG --always-trust -ea --yes -r "$usrname2" < $i | tee x | $GPG -o y --yes
|
||||
cmp $i y || error "$i: mismatch"
|
||||
$srcdir/run-gpg --yes < x > y
|
||||
$GPG --yes < x > y
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
#info Checking armored signing and encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" \
|
||||
| $srcdir/run-gpg --passphrase-fd 0 -sae -o x --yes -r "$usrname2" $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust \
|
||||
-sae -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#info Checking armored signatures
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -sa -o x --yes $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sa -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -14,17 +14,17 @@
|
|||
# it is clear text and not binary text.
|
||||
# ======================================
|
||||
for i in $plain_files plain-large ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -sat -o x --yes $i
|
||||
$srcdir/run-gpg --verify x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sat -o x --yes $i
|
||||
$GPG --verify x
|
||||
done
|
||||
|
||||
# ======================================
|
||||
# and once more to check rfc1991
|
||||
# ======================================
|
||||
for i in $plain_files plain-large ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 \
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 \
|
||||
--rfc1991 --digest-algo md5 -sat -o x --yes $i
|
||||
$srcdir/run-gpg --verify x
|
||||
$GPG --verify x
|
||||
done
|
||||
|
||||
# ======================================
|
||||
|
@ -35,8 +35,8 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|||
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
EOF
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$srcdir/run-gpg --verify x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
# ======================================
|
||||
# and one with only one long lines
|
||||
|
@ -44,14 +44,15 @@ $srcdir/run-gpg --verify x
|
|||
cat >y <<EOF
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyx
|
||||
EOF
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$srcdir/run-gpg --verify x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
# ======================================
|
||||
# and one with an empty body
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
EOF
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$srcdir/run-gpg --verify x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
# ======================================
|
||||
# and one with one empty line at the end
|
||||
|
@ -63,20 +64,39 @@ line 3
|
|||
there is a blank line after this
|
||||
|
||||
EOF
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$srcdir/run-gpg --verify x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
|
||||
# ======================================
|
||||
# I think this file will be contructed wrong (gpg 0.9.3)
|
||||
# I think this file will be constructed wrong (gpg 0.9.3)
|
||||
# but it should verify okay anyway.
|
||||
# bash's builtin echo needs the option -e so we use the external one.
|
||||
# ======================================
|
||||
echo "this is a sig test" >y
|
||||
echo_n " " >>y
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$srcdir/run-gpg --verify x
|
||||
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
|
||||
# ======================================
|
||||
# check our special diff mode
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
--- mainproc.c Tue Jun 27 09:28:11 2000
|
||||
+++ mainproc.c~ Thu Jun 8 22:50:25 2000
|
||||
@@ -1190,16 +1190,13 @@
|
||||
md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
|
||||
}
|
||||
/* ask for file and hash it */
|
||||
- if( c->sigs_only ) {
|
||||
+ if( c->sigs_only )
|
||||
rc = hash_datafiles( c->mfx.md, NULL,
|
||||
c->signed_data, c->sigfilename,
|
||||
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
|
||||
EOF
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 \
|
||||
--not-dash-escaped --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking conventional encryption
|
||||
for i in 0 1 2 3 9 10 11 19 20 21 22 23 39 40 41 8192 32000 ; do
|
||||
for ciph in 3des cast5 blowfish twofish rijndael; do
|
||||
# *BSD's dd can't cope with a count of 0
|
||||
if test "$i" = "0"; then
|
||||
: >z
|
||||
else
|
||||
dd if=data-80000 of=z bs=1 count=$i 2>/dev/null
|
||||
fi
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \
|
||||
--force-mdc --cipher $ciph -c -o x --yes z
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \
|
||||
-o y --yes x
|
||||
cmp z y || error "$ciph/$i: mismatch"
|
||||
done
|
||||
done
|
||||
|
|
@ -2,22 +2,22 @@
|
|||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
# temp. hack cause the format for 128 biut blocksize messages may change
|
||||
# temp. hack cause the format for 128 bit blocksize messages may change
|
||||
GNUPG_ENABLE_TWOFISH=1
|
||||
export GNUPG_ENABLE_TWOFISH
|
||||
|
||||
#info Checking conventional encryption
|
||||
for i in plain-2 data-32000 ; do
|
||||
echo "Hier spricht HAL" | $srcdir/run-gpg --passphrase-fd 0 -c -o x --yes $i
|
||||
echo "Hier spricht HAL" | $srcdir/run-gpg --passphrase-fd 0 -o y --yes x
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -c -o x --yes $i
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
for a in cast5 3des twofish; do
|
||||
for i in plain-1 data-80000 ; do
|
||||
echo "Hier spricht HAL" | $srcdir/run-gpg --passphrase-fd 0 \
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \
|
||||
--cipher-algo $a -c -o x --yes $i
|
||||
echo "Hier spricht HAL" | $srcdir/run-gpg --passphrase-fd 0 -o y --yes x
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x
|
||||
cmp $i y || error "$i: ($a) mismatch"
|
||||
done
|
||||
done
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#info Checking decryption of supplied DSA encrypted file
|
||||
for i in "plain-1" ; do
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes $srcdir/$i-pgp.asc
|
||||
$GPG $dsa_keyrings -o y --yes $srcdir/$i-pgp.asc
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
#info Checking decryption of supplied files
|
||||
for i in $plain_files ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 \
|
||||
-o y --yes $srcdir/$i.asc
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -o y --yes $srcdir/$i.asc
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -49,9 +49,6 @@ info () {
|
|||
echo "$pgmname:" $* >&2
|
||||
}
|
||||
|
||||
chdir () {
|
||||
cd $1 || fatal "cannot cd to $1"
|
||||
}
|
||||
|
||||
echo_n_init=no
|
||||
echo_n () {
|
||||
|
@ -101,11 +98,9 @@ pgmname=`basename $0`
|
|||
|
||||
[ -z "$srcdir" ] && fatal "not called from make"
|
||||
|
||||
cat <<EOF >./options
|
||||
no-greeting
|
||||
no-secmem-warning
|
||||
load-extension ../cipher/tiger
|
||||
batch
|
||||
emulate-md-encode-bug
|
||||
EOF
|
||||
GPG="../g10/gpg --homedir . "
|
||||
|
||||
exec 2> ${pgmname}.log
|
||||
|
||||
:
|
||||
# end
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#info Checking detached signatures
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -sb -o x --yes $i
|
||||
$srcdir/run-gpg -o /dev/null --yes x <$i || error "$i: bad signature"
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sb -o x --yes $i
|
||||
$GPG -o /dev/null --yes x <$i || error "$i: bad signature"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
#info Checking detached signatures of multiple files
|
||||
i="$plain_files $data_files"
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -sb -o x --yes $i
|
||||
cat $i | $srcdir/run-gpg -o /dev/null --yes x || error "$i: bad signature"
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sb -o x --yes $i
|
||||
cat $i | $GPG -o /dev/null --yes x || error "$i: bad signature"
|
||||
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
#info Checking encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg $dsa_keyrings -e -o x --yes -r "$dsa_usrname2" $i
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes x
|
||||
$GPG $dsa_keyrings --always-trust -e -o x --yes -r "$dsa_usrname2" $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
# and with cast
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg $dsa_keyrings --cipher-algo cast5 -e \
|
||||
$GPG $dsa_keyrings --always-trust --cipher-algo cast5 -e \
|
||||
-o x --yes -r "$dsa_usrname2" $i
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes x
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
#info Checking encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg -e -o x --yes -r "$usrname2" $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
$GPG --always-trust -e -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg -e -o x --yes -r "$usrname2" --cipher-algo cast5 $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
$GPG --always-trust -e -o x --yes -r "$usrname2" --cipher-algo cast5 $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#info Checking encryption with a pipe
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg -e --yes -r "$usrname2" <$i | tee yy | $srcdir/run-gpg --yes > y
|
||||
$GPG --always-trust -e --yes -r "$usrname2" <$i | $GPG --yes > y
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -1,105 +1,26 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo "test is currently disabled"
|
||||
exit 0
|
||||
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
ignore_errors=yes
|
||||
|
||||
|
||||
if (expect -v) < /dev/null > /dev/null 2>&1 ; then
|
||||
:
|
||||
else
|
||||
echo "\"expect\" needed but not found - test skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LANG=
|
||||
LANGUAGE=
|
||||
|
||||
expect - <<EOF >/dev/null
|
||||
#set timeout -1
|
||||
set timeout 8
|
||||
match_max 100000
|
||||
spawn ../g10/gpg --no-batch --homedir . --gen-key
|
||||
expect {
|
||||
-exact "Please select what kind of key you want:\r
|
||||
(1) DSA and ElGamal (default)\r
|
||||
(2) DSA (sign only)\r
|
||||
(4) ElGamal (sign and encrypt)\r
|
||||
Your selection? " { send -- "1\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "1\r
|
||||
\r \rDSA keypair will have 1024 bits.\r
|
||||
About to generate a new ELG-E keypair.\r
|
||||
minimum keysize is 768 bits\r
|
||||
default keysize is 1024 bits\r
|
||||
highest suggested keysize is 2048 bits\r
|
||||
What keysize do you want? (1024) " { send -- "\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "\r
|
||||
\r \rRequested keysize is 1024 bits\r
|
||||
Please specify how long the key should be valid.\r
|
||||
0 = key does not expire\r
|
||||
<n> = key expires in n days\r
|
||||
<n>w = key expires in n weeks\r
|
||||
<n>m = key expires in n months\r
|
||||
<n>y = key expires in n years\r
|
||||
Key is valid for? (0) " { send -- "1\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "1\r
|
||||
\r \rKey expires at " { }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-re "(.*)\r
|
||||
" {}
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "Is this correct (y/n)? " { send -- "y\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "y\r
|
||||
\r \r\r
|
||||
You need a User-ID to identify your key; the software constructs the user id\r
|
||||
from Real Name, Comment and Email Address in this form:\r
|
||||
\"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\r
|
||||
\r
|
||||
Real name: " { send -- "Harry H.\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "Harry H.\r
|
||||
\r \rEmail address: " { send -- "hh@ddorf.de\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "hh@ddorf.de\r
|
||||
\r \rComment: " { send -- "a test\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "a test\r
|
||||
\r \rYou selected this USER-ID:\r
|
||||
\"Harry H. (a test) <hh@ddorf.de>\"\r
|
||||
\r
|
||||
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " { send -- "o\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-exact "o\r
|
||||
\r \rYou need a Passphrase to protect your secret key.\r
|
||||
\r
|
||||
Enter passphrase: " { sleep 1; send -- "abc\r" }
|
||||
timeout { exit 1 } }
|
||||
expect {
|
||||
-ex "\r \rRepeat passphrase: " { sleep 1; send -- "abc\r" }
|
||||
timeout { exit 1 } }
|
||||
set timeout 600
|
||||
expect {
|
||||
-re "^.*\r\npublic and secret key" { exit 0 }
|
||||
eof { exit 1 }
|
||||
}
|
||||
exit 1
|
||||
../g10/gpg --quiet --batch --quick-random --homedir . --gen-key <<EOF
|
||||
Key-Type: DSA
|
||||
Key-Length: 1024
|
||||
Subkey-Type: ELG-E
|
||||
Subkey-Length: 1024
|
||||
Name-Real: Harry H.
|
||||
Name-Comment: test key
|
||||
Name-Email: hh@@ddorf.de
|
||||
Expire-Date: 1
|
||||
Passphrase: abc
|
||||
%commit
|
||||
Key-Type: RSA
|
||||
Key-Length: 1024
|
||||
Key-Usage: sign,encrypt
|
||||
Name-Real: Harry A.
|
||||
Name-Comment: RSA test key
|
||||
Name-Email: hh@@ddorf.de
|
||||
Expire-Date: 2
|
||||
Passphrase: abc
|
||||
%commit
|
||||
EOF
|
||||
|
||||
#*-*wedit:notab*-*
|
||||
|
|
|
@ -13,7 +13,7 @@ test_one () {
|
|||
failed=""
|
||||
|
||||
#info Checking message digests
|
||||
cat /dev/null | $srcdir/run-gpg -v --print-mds >y
|
||||
cat /dev/null | $GPG -v --print-mds >y
|
||||
test_one "MD5" "D41D8CD98F00B204E9800998ECF8427E"
|
||||
test_one "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
||||
test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31"
|
||||
|
@ -25,7 +25,7 @@ fi
|
|||
|
||||
[ "$failed" != "" ] && error "$failed failed for empty string"
|
||||
|
||||
echo_n "abcdefghijklmnopqrstuvwxyz" | $srcdir/run-gpg --print-mds >y
|
||||
echo_n "abcdefghijklmnopqrstuvwxyz" | $GPG --print-mds >y
|
||||
test_one "MD5" "C3FCD3D76192E4007DFB496CCA67E13B"
|
||||
test_one "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89"
|
||||
test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC"
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
set -e
|
||||
|
||||
GPG="../g10/gpg --batch --quiet --no-secmem-warning"
|
||||
GPG="../g10/gpg --batch --quiet --no-secmem-warning --allow-secret-key-import"
|
||||
NAMES='Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India
|
||||
Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo
|
||||
Sierra Tango Uniform Victor Whisky XRay Yankee Zulu'
|
||||
|
||||
if [ "$1" = "--clean" ]; then
|
||||
for i in $NAMES; do
|
||||
(for i in $NAMES; do
|
||||
[ -d $i ] && rm -r $i
|
||||
done
|
||||
done) || true
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
@ -19,15 +19,15 @@ $GPG --dearmor -o pubdemo.gpg --yes ../checks/pubdemo.asc
|
|||
[ -f ./tdb.tmp ] && rm ./tdb.tmp
|
||||
GPGDEMO="$GPG --homedir . --trustdb-name ./tdb.tmp --no-default-keyring
|
||||
--keyring pubdemo.gpg --secret-keyring secdemo.gpg"
|
||||
/bin/echo "Creating:\c"
|
||||
echo -n "Creating:"
|
||||
for name in $NAMES; do
|
||||
/bin/echo " $name\c"
|
||||
echo -n " $name"
|
||||
[ -d $name ] && rm -r $name
|
||||
mkdir $name
|
||||
$GPGDEMO --export-secret-key -o - $name | tee $name/Secret.gpg | \
|
||||
$GPG --homedir $name --import
|
||||
$GPGDEMO --export -o - $name | tee $name/Public.gpg | \
|
||||
$GPG --homedir $name --import
|
||||
$GPGDEMO --export-secret-key -o - $name > $name/Secret.gpg
|
||||
$GPG --homedir $name --import $name/Secret.gpg
|
||||
$GPGDEMO --export -o - $name > $name/Public.gpg
|
||||
$GPG --homedir $name --import $name/Public.gpg
|
||||
[ -f $name/pubring.gpg~ ] && rm $name/pubring.gpg~
|
||||
done
|
||||
echo "."
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
#!/bin/sh
|
||||
# Check that gpg verifies only signatures where there is no ambiguity
|
||||
# in the order of packets. Needs the Demo Keys Lima and Mike.
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
# (variable intialization was created using:
|
||||
# for i in files; do echo "`echo $i | sed 's,[.-],_,g'`='"; \
|
||||
# gpg --no-version --enarmor <$i | grep -v ^Comment:; echo "'" ; done
|
||||
# )
|
||||
|
||||
sig_1ls1ls_valid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg
|
||||
ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e
|
||||
8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOZANAwACETfKtR+3kQP4AawnYgV0ZXh0
|
||||
MTqIKvRJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCr0N8q1H7eR
|
||||
A/gRAto6AKCWkmlzmRLUmakO/NByFxu+3vDwewCeMAqa5mhUztHwWk3Fw7hDgXQF
|
||||
pzk=
|
||||
=8jSC
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_ls_valid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
|
||||
K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
|
||||
QDUFTH2PvZRxjw==
|
||||
=J+lb
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_sl_valid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
|
||||
tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n
|
||||
dCBkbyB0aGF0Cg==
|
||||
=N9MP
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_11lss_valid_but_is_not='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g
|
||||
c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT
|
||||
mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy
|
||||
XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB
|
||||
Q341WRXKS/at
|
||||
=Ekrs
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_11lss11lss_valid_but_is_not='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g
|
||||
c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT
|
||||
mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy
|
||||
XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB
|
||||
Q341WRXKS/atkA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQx
|
||||
OogyXUkgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED
|
||||
+BECwQAAnRXTmXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp
|
||||
5Yg/AwUAOogyXTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0
|
||||
P01WmbgZJoZBQ341WRXKS/at
|
||||
=P1Mu
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_ssl_valid_but_is_not='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
|
||||
tH60PslLE0A1BUx9j72UcY+IPwMFADqIK0s3yrUft5ED+BECLQMAn2jZUNOpB4Ou
|
||||
urSQkc2TRfg6ek02AJ9+oJS0frQ+yUsTQDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJ
|
||||
IGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQK
|
||||
=Zven
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_1lsls_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg
|
||||
ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e
|
||||
8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOawnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5
|
||||
LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeD
|
||||
rrq0kJHNk0X4OnpNNgCffqCUtH60PslLE0A1BUx9j72UcY8=
|
||||
=nkeu
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_lsls_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
|
||||
K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
|
||||
QDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRo
|
||||
YXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCf
|
||||
fqCUtH60PslLE0A1BUx9j72UcY8=
|
||||
=BlZH
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_lss_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
|
||||
K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
|
||||
QDUFTH2PvZRxj4g/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF
|
||||
+Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGP
|
||||
=jmt6
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_slsl_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
|
||||
tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n
|
||||
dCBkbyB0aGF0Cog/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF
|
||||
+Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGPrCdiBXRleHQxOogrS0kgYW0gc29y
|
||||
cnksIEkgY2FuJ3QgZG8gdGhhdAo=
|
||||
=phBF
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
|
||||
save_IFS="${IFS}"
|
||||
IFS=""
|
||||
for i in "$sig_1ls1ls_valid" "$sig_ls_valid" "$sig_sl_valid"; do
|
||||
echo "$i" | ./gpg_dearmor >x
|
||||
IFS="${save_IFS}"
|
||||
$GPG --verify x 2>/dev/null || error "valid is invalid"
|
||||
IFS=""
|
||||
done
|
||||
#for i in "$sig_11lss_valid_but_is_not" "$sig_11lss11lss_valid_but_is_not" \
|
||||
# "$sig_ssl_valid_but_is_not"; do
|
||||
# echo "$i" | $GPG --dearmor >x
|
||||
# $GPG --verify <x 2>/dev/null || error "valid is invalid"
|
||||
#done
|
||||
|
||||
# without the +e ksh seems to terminate the for loop
|
||||
set +e
|
||||
for i in "$sig_1lsls_invalid" "$sig_lsls_invalid" \
|
||||
"$sig_lss_invalid" "$sig_slsl_invalid" ; do
|
||||
echo "$i" | ./gpg_dearmor >x
|
||||
IFS="${save_IFS}"
|
||||
$GPG --verify <x 2>/dev/null && error "invalid is valid"
|
||||
IFS=""
|
||||
done
|
||||
IFS="${save_IFS}"
|
|
@ -0,0 +1,6 @@
|
|||
no-greeting
|
||||
no-secmem-warning
|
||||
no-permission-warning
|
||||
batch
|
||||
emulate-md-encode-bug
|
||||
no-auto-check-trustdb
|
|
@ -0,0 +1,14 @@
|
|||
Type Bits/KeyID Date User ID
|
||||
pub 888/A50283F1 2001/11/08 pgp2.6.3-test-key
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: 2.6.3a
|
||||
|
||||
mQB8AzvqRosAAAEDeNMKLJMJQeGC2RG5Nec6R2mzC12N1wGLiYYJCsmSQd1Y8mht
|
||||
A2Sc+4k/q5+l6GHtfqUR/RTCIIudAZUzrQVIMhHDKF+5de9lsE5QxQS1u43QGVCb
|
||||
/9IYrOLOizYQ2pkBtD9LCrf7W2DccMEkpQKD8QAFE7QRcGdwMi42LjMtdGVzdC1r
|
||||
ZXmJAIQDBRA76kaL3HDBJKUCg/EBAZMoA3Yqqdix6B2RAzywi9bKSLqwAFVL+MMw
|
||||
W+BnYeBXF9u+bPpQvtyxgi0vx8F9r84B3HAhZNEjBWODF6vctIQhXhAhXIniDTSj
|
||||
HNzQ/+nbWnebQn18XUV2SdM1PzMOblD+nISte7+WUfWzlD7YUJPkFPw=
|
||||
=b498
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -0,0 +1,18 @@
|
|||
Type Bits/KeyID Date User ID
|
||||
sec 888/A50283F1 2001/11/08 pgp2.6.3-test-key
|
||||
|
||||
-----BEGIN PGP SECRET KEY BLOCK-----
|
||||
Version: 2.6.3a
|
||||
|
||||
lQGdAzvqRosAAAEDeNMKLJMJQeGC2RG5Nec6R2mzC12N1wGLiYYJCsmSQd1Y8mht
|
||||
A2Sc+4k/q5+l6GHtfqUR/RTCIIudAZUzrQVIMhHDKF+5de9lsE5QxQS1u43QGVCb
|
||||
/9IYrOLOizYQ2pkBtD9LCrf7W2DccMEkpQKD8QAFEwADd0Kk5aeyFM3zbPgfikkE
|
||||
7iFg9h2LG3nARmA4wAnCZaQ3CS5zRHCdXOf5KLkm6xFza1yMat4iWx6ULvuuNpIc
|
||||
RmkHccyXYkRi3Hvacd5A9VCNw1UKtCdaCKgacsfplU0s1xYWGZd4J8Jg8boSfW5W
|
||||
gwG8Dc9R20HHno8uD2vfr5rg8ElWvbFyJI/j4eCVAd+NYAGNvB8I3VP38IIYcavh
|
||||
YYcGjrpxbGVRybsBvA9IJltpGaVulxwpeCp5NecCGgoAUsN4Ktf42Pg7HXDlQL6r
|
||||
Xs/YggMztj4NzEgBHXAOLShdKKhDAbEByVSKXZD9A8J+RejXBl6VbuJmD/5qOvph
|
||||
GAPKS3ahPDj8438HyD7yIDLYYVRKfxjWHLubc46Pgui0EXBncDIuNi4zLXRlc3Qt
|
||||
a2V5
|
||||
=l/aV
|
||||
-----END PGP SECRET KEY BLOCK-----
|
|
@ -1,78 +1,734 @@
|
|||
This is a test public keyring simply stored by GNUPG so that
|
||||
it is easier to make diff files.
|
||||
|
||||
pub 768G/9D266E0F 1998-04-28 Test one (pp=def) <one@test.nowhere.nil>
|
||||
sig 9D266E0F 1998-04-28 Test one (pp=def) <one@test.nowhere.nil>
|
||||
sig 2E5FA4F4 1998-04-28 test two (no pp) <two@test.nowhere.nil>
|
||||
sig 6D11D6D3 1998-04-28 test three (pp=abc) <three@test.nowhere.nil>
|
||||
pub 800G/2E5FA4F4 1998-04-28 test two (no pp) <two@test.nowhere.nil>
|
||||
sig 2E5FA4F4 1998-04-28 test two (no pp) <two@test.nowhere.nil>
|
||||
sig 9D266E0F 1998-04-28 Test one (pp=def) <one@test.nowhere.nil>
|
||||
sig 6D11D6D3 1998-04-28 test three (pp=abc) <three@test.nowhere.nil>
|
||||
pub 768G/6D11D6D3 1998-04-28 test three (pp=abc) <three@test.nowhere.nil>
|
||||
sig 6D11D6D3 1998-04-28 test three (pp=abc) <three@test.nowhere.nil>
|
||||
sig 9D266E0F 1998-04-28 Test one (pp=def) <one@test.nowhere.nil>
|
||||
sig 2E5FA4F4 1998-04-28 test two (no pp) <two@test.nowhere.nil>
|
||||
|
||||
|
||||
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GNUPG v0.2.15a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
Comment: Use "gpgm --dearmor" for unpacking
|
||||
Version: GnuPG v1.0.7 (GNU/Linux)
|
||||
Comment: Use "gpg --dearmor" for unpacking
|
||||
|
||||
mM8DNUWBuARHEAMA8bSQw1VFSXbgZ+nNXhM9xeDD+OpKQU4hUaCKfuTtRHoY5QxTPz3DFWRl
|
||||
FewsA50Ou28jlPWxIKZaaGxMqbDtqyUsm6AEz/vRi5VKiVHf28XUkMryQSTHvjwJFVb7+6Wb
|
||||
AAMFAwDXZiawNtgYsjwVedv/xXdhTsrf0Tn/8HCj3S9N/MAT0zCnXL0flYeqhqL/okuBcrwM
|
||||
A4amAIWGVW7ws7k7QgrfJoWG2SELxIT9MovMLvq5Kh55J7H6Yn6uoFzIOX0A43HQIiNjcmVh
|
||||
dGVkIGJ5IEdOVVBHIHYwLjIuMTVhIChMaW51eCm0KFRlc3Qgb25lIChwcD1kZWYpIDxvbmVA
|
||||
dGVzdC5ub3doZXJlLm5pbD6I1wMFEzVFgbg8a7vmnSZuDxADD/4DAK0FELG1gICh/fxO5dXu
|
||||
lV+S1CY9YPQwRxQN7zYlixA7vedTCN9jutMC6fOlmMXqfivF2CMux3uz0oTJgjF/myh+jkcO
|
||||
sE+iUgcO+fdMIn4oY53Pval5zuCcmqqbszP6mQMAqIYYNtE2BI6acRU8sqwIxx/GiVqELwzX
|
||||
4QGp5N/4oURoZJ4Ybb8+6eEePI1vzIpLq9TO0ttQzDv9hO8WNyYEPVAoe9gOIoMYOh9E0W9R
|
||||
u0wf4sh67KCrRvc7yrFTMwHtiN8DBRA1RYLMDvng6C5fpPQQAzlHAx4qEZmAhoAtCfgQmlmq
|
||||
HIwcOa2xI/eOsqexT6eYMty8f/vsNznGhTh5gJ3PDDy8U/Lj1KRJWPeDSZJ/6tZ/3DUd/x+K
|
||||
jPzVVnm1zlJSflR5AWLS7IQiyJzz7uo2dUiCs2nO4rZcAyDaLbj/2aWwI92UQzKjWvcS49lW
|
||||
r2wp0QURUomqvNexKkHHDyIRhwspXwT9glETyn+focZKRBJTv0QtxOMVQeGaUnIuAcsDgpZu
|
||||
ZkXBcdXgPbmj39rN+nNUW1UI0fKsnBl5cnSgiNcDBRA1RYLaZE80um0R1tMQAwq4Av9rzmMg
|
||||
XgDtJy+mauJJ5FUEE5GY3bIul1MuIbaMv6T99uWgwD9q2HsV0z9/T552cOTJ/DIkSjdusZ6+
|
||||
PlY8jYDK4xTYwcglPuMH5/EsKW8zZwcwYiqnGMbmY4F70SxZW2EC/1p760rM7MrNCDAWnEle
|
||||
gTvEMvutfK+K3DOu+Ba+KxU3zfgWr4z6B74QV2TvHrF0Zgu9UpXOp0FghufA6JevCvYhzNDM
|
||||
4VJV24QaF3bt16JoHQyiS9jtYcMl4IzexeeO0JjXAzVFggEAABADINyO1leIKxvoee6oi0zk
|
||||
I9SCJ6dSTEH7/kETqetNArjqClenO1K0AVd+MqMajl97bg5iUYGam55PECkkozOlscDzDF9e
|
||||
xWY6sey44dBREQhgXLVWE4GZ1G3sy85aD+sVHgxwlz8AAwUDILAV8w6FL7PpgiedAOHslMtq
|
||||
f7sh1IeNSkCjRdqvMCKgKroSLQto9WprXMUv3KHmTL7TpZNad+8xJUK7R5GHUTR1OIFQMJvT
|
||||
odG8RU6JOaGoeTqWgs61v00fFgwY6sYO11ckmsfQIiNjcmVhdGVkIGJ5IEdOVVBHIHYwLjIu
|
||||
MTVhIChMaW51eCm0J3Rlc3QgdHdvIChubyBwcCkgPHR3b0B0ZXN0Lm5vd2hlcmUubmlsPojf
|
||||
AwUTNUWCAQ754OguX6T0EAOQsQMfXrBhe1g+hBCwQH94+08VqNGS/+Fs8s4FRmEP1Y0TuT6U
|
||||
qf9QLHtfbPgKbJL1NwGgy6dn4TfWo2PRj0U8ai+YIIPZopl4hnrj+v1f94V/IbMd3N77K0F0
|
||||
rJrHzL4egHi95BUVdgMgr00QAYcbbZItd/wIb2TNSu/DRlzEXezA3xRuCIBnTdsrHMPc2B4l
|
||||
mCQsyx9/fmBlwrVLlaftBTvrOUa/yXf8hHwPv48avRwgClaoChExhFMdEA9Df5ju4192VldJ
|
||||
yJgPVz0Ze4jXAwUQNUWCsTxru+adJm4PEAOeIwMAhzYyjVb5vlae3V3VO+5+Zsx4SVRB2NeC
|
||||
Y74FIN5vXMoWJyt/UjmXC9CmI82PvVD3F8RXKUZqZC9gXcGyDYyZ87oooYc9HbQ7lhyOWsv/
|
||||
0dWztX9UQQrHdScQ0TbZcC2aAvwJF7WESAGhOGssVKWaUkXZJV1sCpyyEtkUP/UJtcGha/Op
|
||||
PlmG6vC9XW5ymtRk0XhFkvG4dLopbRIZgAI0CmHSloKIL5Y4JzOfc5bccNCB/tiI+3Y1JIr3
|
||||
AYMqaSTjoGOI1gMFEDVFgwJkTzS6bRHW0xAD83sC93MCuEN8MCJGTZX//I7QVsg5DJ9xJRdy
|
||||
5Te6MNA1Ie1o7+EJZ1MqDVF/6+HkITqGWFOPD/GYPmgdP5QALfHW6z9YddHOHH6Skt2fC2NW
|
||||
Tip4e+/t8iAOR/ynwocPpyHkAwCHsxTXtRlaCbIt40/3d0LFPoN4JYBVDM+pWfNgNAWUzgME
|
||||
Mua2P24g4P4NZnW3fsJuYQ6Ro7jqu6oolfFkxVOYd2/KrnH5Mggu3D8q+gg68kzXTj62QW9v
|
||||
TBax5Ve0Kk+YzwM1RYJlAAAQAwCWZQsoNJJI8u1nV+5VZaXZqZBn+uk3fp/my7l9YLQeV5S9
|
||||
U76Ogdw0la/YiWX2m8Aw+hO47pYswsyRi2lu/FE/dr0o0CB53LB4EnFJPiBHrB8rm3wI142B
|
||||
QeJ9Dj5YU/MAAwYC/1gB0NoFl2QhbYY83tuLg/UlIkM8CZtxtXR9vfQq0UgrVuDoeLx0/mln
|
||||
Wm8pmJsHR+0r8sL2yjl7P0RQ+FJtiaMTVHihJyhXukCO1bPM3PX8L/QsmXFzWcfmavk11xpP
|
||||
NdAiI2NyZWF0ZWQgYnkgR05VUEcgdjAuMi4xNWEgKExpbnV4KbQsdGVzdCB0aHJlZSAocHA9
|
||||
YWJjKSA8dGhyZWVAdGVzdC5ub3doZXJlLm5pbD6I1wMFEzVFgmVkTzS6bRHW0xADVtEDAIWy
|
||||
FsZZgyT9wLmEsVbLcv2WNK/z7XweyDOV203Z3Po5lo75+c8bFkRPNcD/0R/nD5wbyNPACFHx
|
||||
e7VUm+wLHZFq5Hw8TuAegqNq0ZlgeR/vLgs54m1eOi3jbDfyZMJASAL/XKRGnGu3oi6SjknK
|
||||
sKhFOprdn7DeMW0q7YP5WtRTnnrJjIhDl0c+mi82Yj2OVEOLg3SaILBDZJd9muLPHQLAp95X
|
||||
sKZ0nHfBzlFFsr0V5BvWF4UV+U9JHxyDuXLWyEDbiNcDBRA1RYK7PGu75p0mbg8QA3mwAvsH
|
||||
XEo6HotEGw0stskTnV/Dp32bSJ8yRq2kOWfQAgaY1ZZWVRSPtHBDAJZJ/LpfWXPke90M3B72
|
||||
v0a9gAxOx5VfevaaXJAdp/ZjrVh1TE90LujbPVNeHt4a1dD0bQa9EbwC/1NTZMfb8LDHxYds
|
||||
JdDdZxsxfCDy2U7BWC1e3LLQCJOeNfSx76ICJBLq+HOpCgP2AodGgV9Rx01O3Fz8Gx3iVRgZ
|
||||
bKnyS8perkS3AFayedGat/6reUI6KJtddro0SIeBxIjfAwUQNUWDEw754OguX6T0EAPKMgMe
|
||||
L8YKAj4KvkJBWNxt1W+WTjF2YBj4pYmrWisXxgmRZWEwwyDHYecH1zE2L12o82QGprbU8BW+
|
||||
GUXQVxbRt0rvlDqfGPN5HAgdjES7sK3qVZLsVeMcnhpjDDQkpYkCIsWueCKKRwMfSiqZ1S3o
|
||||
BHIz3CVzbQkdMp6FbpSYXRR55CyzVdUZDb9ynXKxQCk3Pmn0bTFsRWRFOlRe3oVpS2lM2EQF
|
||||
u5cWheypAt2y86ZuoevHPkcpsR0UXD129IzwOV3cstGm3jCAhdGMmA==
|
||||
=eCl1
|
||||
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
|
||||
=Xw/z
|
||||
-----END PGP ARMORED FILE-----
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
[ -n "$show_cmds" ] && echo "../g10/gpg --homedir . $*" >&2
|
||||
|
||||
if ../g10/gpg --homedir . $* 2>err.tmp.$$ ; then
|
||||
:
|
||||
else
|
||||
echo "(../g10/gpg --homedir . $*) failed" >&2
|
||||
cat err.tmp.$$ >&2
|
||||
rm err.tmp.$$
|
||||
exit 1
|
||||
fi
|
||||
fgrep -v -f $srcdir/run-gpg.patterns err.tmp.$$ >&2
|
||||
rm err.tmp.$$
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
gpg: Good signature from
|
||||
gpg: aka "
|
||||
gpg: Signature made
|
||||
gpg: ./trustdb.gpg: trustdb created
|
||||
gpg: NOTE: cipher algorithm 3 not found in preferences
|
||||
gpg: NOTE: cipher algorithm 4 not found in preferences
|
||||
gpg: NOTE: secret key 2E5FA4F4 is NOT protected.
|
||||
gpg: NOTE: secret key 439F02CA is NOT protected.
|
||||
gpg: WARNING: using insecure random number generator
|
||||
gpg: NOTE: signature key expired
|
||||
NOTE: this is a development version!
|
||||
secret key without public key - skipped
|
||||
gpg: using secondary key CB879DE9 instead of primary key 439F02CA
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
if ../g10/gpgm --homedir . $* 2>err.tmp.$$ ; then
|
||||
:
|
||||
else
|
||||
echo "(../g10/gpgm --homedir . $*) failed" >&2
|
||||
cat err.tmp.$$ >&2
|
||||
rm err.tmp.$$
|
||||
exit 1
|
||||
fi
|
||||
rm err.tmp.$$
|
||||
|
|
@ -3,8 +3,9 @@
|
|||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
for i in $plain_files ; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -seat -r two -o x --yes $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust -seat \
|
||||
-r two -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo "test is currently disabled"
|
||||
exit 0
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
#info Checking signing and encryption for DSA
|
||||
for i in $plain_files $data_files ; do
|
||||
$srcdir/run-gpg $dsa_keyrings -se -o x --yes \
|
||||
$GPG $dsa_keyrings --always-trust -se -o x --yes \
|
||||
-u "$dsa_usrname1" -r "$dsa_usrname2" $i
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes x
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
for da in ripemd160 sha1 md5; do
|
||||
for da in ripemd160 sha1; do
|
||||
for i in $plain_files; do
|
||||
$srcdir/run-gpg $dsa_keyrings -se -o x --yes --digest-algo $da \
|
||||
$GPG $dsa_keyrings --always-trust -se -o x --yes --digest-algo $da \
|
||||
-u "$dsa_usrname1" -r "$dsa_usrname2" $i
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes x
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
# process only the first one
|
||||
break
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
#info Checking signing and encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" \
|
||||
| $srcdir/run-gpg --passphrase-fd 0 -se -o x --yes -r "$usrname2" $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust \
|
||||
-se -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo "test is currently disabled"
|
||||
exit 0
|
||||
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
#info Checking DSA signatures (default digest algo)
|
||||
for i in $plain_files $data_files; do
|
||||
$srcdir/run-gpg $dsa_keyrings -s -o x --yes -u $dsa_usrname1 $i
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes x
|
||||
$GPG $dsa_keyrings -s -o x --yes -u $dsa_usrname1 $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
for da in ripemd160 sha1 md5; do
|
||||
for da in ripemd160 sha1; do
|
||||
for i in $plain_files; do
|
||||
$srcdir/run-gpg $dsa_keyrings --digest-algo $da \
|
||||
$GPG $dsa_keyrings --digest-algo $da \
|
||||
-s -o x --yes -u $dsa_usrname1 $i
|
||||
$srcdir/run-gpg $dsa_keyrings -o y --yes x
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
# process only the first one
|
||||
break
|
||||
|
|
|
@ -4,21 +4,21 @@
|
|||
|
||||
#info Checking signatures
|
||||
for i in $plain_files $data_files; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 -s -o x --yes $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -s -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
hash_algo_list="ripemd160 sha1 md5"
|
||||
if have_hash_algo "TIGER"; then
|
||||
hash_algo_list="$hash_algo_list tiger"
|
||||
if have_hash_algo "TIGER192"; then
|
||||
hash_algo_list="$hash_algo_list tiger192"
|
||||
fi
|
||||
|
||||
for da in $hash_algo_list ; do
|
||||
for i in $plain_files; do
|
||||
echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --digest-algo $da \
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --digest-algo $da \
|
||||
-s -o x --yes $i
|
||||
$srcdir/run-gpg -o y --yes x
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
# process only the first one
|
||||
break
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
# print the GPG version
|
||||
$srcdir/run-gpg --version
|
||||
$GPG --version
|
||||
|
||||
#fixme: check that the output is correct
|
||||
|
||||
|
|
|
@ -0,0 +1,902 @@
|
|||
2002-05-07 Stefan Bellon <sbellon@sbellon.de>
|
||||
|
||||
* md.c (md_start_debug): Use EXTSEP_S instead of ".".
|
||||
|
||||
2002-04-24 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* tiger.c (tiger_final): Removed superfluous token pasting operators.
|
||||
* md5.c (md5_final): Ditto.
|
||||
|
||||
2002-04-22 Stefan Bellon <sbellon@sbellon.de>
|
||||
|
||||
* rndriscos.c (func_table): Made func a function pointer.
|
||||
(init_device): Improved loading of CryptRandom module.
|
||||
|
||||
2002-04-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndlinux.c, rndegd.c, rndunix.c (func_table): Made func a
|
||||
function pointer. Note that we still need to change the module
|
||||
interface to cope with data vs function pointer problems. Hmmm,
|
||||
even dlsym has a problem with this.
|
||||
|
||||
2002-04-10 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* cipher.c (setup_cipher_table, cipher_open, cipher_encrypt,
|
||||
cipher_decrypt, dummy_setkey, dummy_encrypt_block,
|
||||
dummy_decrypt_block): the dummy cipher should only be built on
|
||||
development versions.
|
||||
|
||||
2002-04-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rijndael.c (rijndael_get_info): We do only support a 128 bit
|
||||
blocksize so it makes sense to change the algorithm strings to
|
||||
AES.
|
||||
* cipher.c (string_to_cipher_algo): Map "RIJNDAEL" to "AES".
|
||||
|
||||
2002-02-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* random.c (mix_pool): Removed the failsafe stuff again. It makes
|
||||
the code more complicate and may give the path to more bugs.
|
||||
|
||||
2002-02-10 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* random.c (mix_pool): Carry an extra failsafe_digest buffer
|
||||
around to make the function more robust.
|
||||
|
||||
2002-02-08 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* random.c (add_randomness): Xor new data into the pool and not
|
||||
just copy it. This avoids any choosen input attacks which are not
|
||||
serious in our setting because an outsider won't be able to mix
|
||||
data in and even then we keep going with a PRNG. Thanks to Stefan
|
||||
Keller for pointing this out.
|
||||
|
||||
2002-01-02 Stefan Bellon <sbellon@sbellon.de>
|
||||
|
||||
* rndriscos.c [__riscos__]: Updated include file name.
|
||||
|
||||
2001-12-21 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am (DISCLEANFILES): Add construct.c
|
||||
|
||||
2001-12-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndw32.c [CYGWIN32]: Include winioctl.h. By Disastry.
|
||||
|
||||
2001-11-08 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* primegen.c (gen_prime): Set 2 high order bits for secret primes.
|
||||
* rsa.c (generate): Loop until we find the exact modulus size.
|
||||
Changed the exponent to 41.
|
||||
|
||||
2001-10-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am: Need to use $(EXEEXT) where approriate.
|
||||
|
||||
2001-09-09 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rsa.c (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings.
|
||||
|
||||
2001-08-24 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* md.c (md_write): Made buf arg const.
|
||||
|
||||
2001-08-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* random.c (fast_random_poll): Don't use gethrtime if it is broken.
|
||||
|
||||
2001-08-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
Applied patches from Stefan Bellon <sbellon@sbellon.de> to support
|
||||
RISC OS. Nearly all of these patches are identified by the
|
||||
__riscos__ macro.
|
||||
* blowfish.c, twofish.c: Added pragmas for use with a Norcraft
|
||||
compiler.
|
||||
* dynload.c, md5.c, rmd160.c, sha1.c: Minor patches for RISC OS.
|
||||
* rndriscos.c: New.
|
||||
* rnd-internal.h: Added prototype.
|
||||
* random.c (fast_random_poll): Use '#if defined' instead of just
|
||||
'defined'; needed for RISC OS.
|
||||
* primegen.c (gen_prime): count? are now ints for consistence
|
||||
with is_prime().
|
||||
|
||||
2001-08-08 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndw32.c (gather_random): Use toolhelp in addition to the NT
|
||||
gatherer for Windows2000. Suggested by Sami Tolvanen.
|
||||
|
||||
* random.c (read_pool): Fixed length check, this used to be one
|
||||
byte to strict. Made an assert out of it because the caller has
|
||||
already made sure that only poolsize bytes are requested.
|
||||
Reported by Marcus Brinkmann.
|
||||
|
||||
2001-07-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndlinux.c (gather_random): casted a size_t arg to int so that
|
||||
the format string is correct. Casting is okay here and avoids
|
||||
translation changes.
|
||||
|
||||
2001-06-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* cipher.c (string_to_cipher_algo): Use ascii_strcasecmp().
|
||||
* md.c (string_to_digest_algo): Ditto.
|
||||
* pubkey.c (string_to_pubkey_algo): Ditto.
|
||||
* rndw32.c (slow_gatherer_windowsNT): Ditto. Not really needed
|
||||
here but anyway.
|
||||
|
||||
2001-04-29 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* random.c (fast_random_poll): Do not check the return code of
|
||||
getrusage.
|
||||
|
||||
2001-04-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndunix.c: Add a signal.h header to avoid warnings on Solaris 7
|
||||
and 8.
|
||||
|
||||
2001-04-16 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* dynload.c [__MINGW32__]: Applied patch from Timo Schulz to make
|
||||
it work under W32. This patches is based on the one from
|
||||
Disastry@saiknes.lv
|
||||
|
||||
2001-04-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rijndael.c, des.c, blowfish.c, twofish.c, cast5.c (burn_stack):
|
||||
New. Add wrappers for most functions to be able to call
|
||||
burn_stack after the function invocation. This methods seems to be
|
||||
the most portable way to zeroise the stack used. It does only work
|
||||
on stack frame based machines but it is highly portable and has no
|
||||
side effects. Just setting the automatic variables at the end of
|
||||
a function to zero does not work well because the compiler will
|
||||
optimize them away - marking them as volatile would be bad for
|
||||
performance.
|
||||
* md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise.
|
||||
* random.c (burn_stack): New.
|
||||
(mix_pool): Use it here to burn the stack of the mixblock function.
|
||||
|
||||
2001-04-02 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* primegen.c (generate_elg_prime): I was not initialized for mode
|
||||
!= 1. Freed q at 3 places. Thanks to Tommi Komulainen.
|
||||
|
||||
2001-03-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* md5.c (md5_final): Fixed calculation of hashed length. Thanks
|
||||
to disastry@saiknes.lv for pointing out that it was horrible wrong
|
||||
for more than 512MB of input.
|
||||
* sha1.c (sha1_final): Ditto.
|
||||
* rmd160.c (rmd160_final): Ditto.
|
||||
* tiger.c (tiger_final): Ditto.
|
||||
|
||||
2001-03-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to
|
||||
avoid name clahses with an encrypt function in stdlib.h of
|
||||
Dynix/PIX. Thanks to Gene Carter.
|
||||
* elgamal.c (encrypt,do_encrypt): Ditto.
|
||||
|
||||
2001-03-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* twofish.c (gnupgext_enum_func): Add some static when comnpiled
|
||||
as a module.
|
||||
|
||||
* tiger.c (tiger_get_info): Return "TIGER192" and not just
|
||||
"TIGER". By Edwin Woudt.
|
||||
|
||||
2001-03-08 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* random.c: Always include time.h - standard requirement. Thanks
|
||||
to James Troup.
|
||||
|
||||
2001-01-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndw32.c: Fixed typo and wrong ifdef for VER_PLATFORM* macro
|
||||
|
||||
2001-01-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* cipher.c (cipher_encrypt,cipher_encrypt): Use blocksize and
|
||||
not 8 for CBC mode (However: we don't use CBS in OpenPGP).
|
||||
|
||||
2000-11-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rndegd.c (gather_random): Fixed default socket to be '=entropy'.
|
||||
Thanks to Tomasz Kozlowski.
|
||||
|
||||
2000-10-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* rijndael.c: New.
|
||||
* cipher.c: Add Rijndael support.
|
||||
|
||||
Wed Oct 4 15:50:18 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* sha1.c (transform): Use rol() macro. Actually this is not needed
|
||||
for a newer gcc but there are still aoter compilers.
|
||||
|
||||
Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* random.c (fast_random_poll): Check ENOSYS for getrusage.
|
||||
* rndunix.c: Add 2 sources for QNX. By Sam Roberts.
|
||||
|
||||
Wed Sep 13 18:12:34 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* rsa.c (secret): Speed up by using the CRT. For a 2k keys this
|
||||
is about 3 times faster.
|
||||
(stronger_key_check): New but unused code to check the secret key.
|
||||
|
||||
Wed Sep 6 17:55:47 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* rsa.c: Changed the comment about the patent.
|
||||
* Makefile.am: Included rsa.[ch].
|
||||
* pubkey.c: Enabled RSA support.
|
||||
(pubkey_get_npkey): Removed RSA workaround.
|
||||
|
||||
Fri Aug 25 16:05:38 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* rndlinux.c (open_device): Loose random device checking.
|
||||
By Nils Ellmenreich.
|
||||
|
||||
* rndegd.c (gather_random): Name of socket is nom configurable.
|
||||
|
||||
Wed Jun 28 11:54:44 CEST 2000 Werner Koch <wk@>
|
||||
|
||||
* rsa.c, rsa.h: New based on the old module version (only in CVS for now).
|
||||
* pubkey.c (setup_pubkey_table): Added commented support for RSA.
|
||||
|
||||
Fri Jun 9 10:09:52 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra.
|
||||
(my_popen): Do the FD_CLOEXEC only if it is available
|
||||
(start_gatherer): Cope with missing _SC_OPEN_MAX
|
||||
|
||||
Sun May 28 13:55:17 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* random.c (read_seed_file): Binary open for DOSish system
|
||||
(update_random_seed_file): Ditto.
|
||||
|
||||
* rndw32.c: Add some debuging code enabled by an environment variable.
|
||||
|
||||
Tue May 23 09:19:00 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* rndw32.c: Started with alternative code to replace entropy.dll
|
||||
|
||||
Thu May 18 11:38:54 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* primegen.c (register_primegen_progress): New.
|
||||
* dsa.c (register_pk_dsa_progress): New.
|
||||
* elgamal.c (register_pk_elg_progress): New.
|
||||
|
||||
Fri Apr 14 19:37:08 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* twofish.c (twofish_get_info): Fixed warning about cast.
|
||||
|
||||
Tue Mar 28 14:26:58 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* random.c [MINGW32]: Include process.h for getpid.
|
||||
|
||||
Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* random.c (fast_random_poll): Add clock_gettime() as fallback for
|
||||
system which support this POSIX.4 fucntion. By Sam Roberts.
|
||||
|
||||
* rndunix.c: Add some more headers for QNX. By Sam Roberts.
|
||||
|
||||
* random.c (read_seed_file): Removed the S_ISLNK test becuase it
|
||||
is already covered by !S_ISREG and is not defined in Unixware.
|
||||
Reported by Dave Dykstra.
|
||||
|
||||
* sha1.c (sha1_get_info): Removed those stupid double lines. Dave
|
||||
is really a good lint.
|
||||
|
||||
Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* twofish.c (twofish_get_info): Add some const to the casts. By Martin
|
||||
Kahlert.
|
||||
|
||||
Mon Feb 14 14:30:20 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
(update_random_seed_file): Silently ignore update request when pool
|
||||
is not filled.
|
||||
|
||||
Fri Feb 11 17:44:40 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* random.c (read_seed_file): New.
|
||||
(set_random_seed_file): New.
|
||||
(read_pool): Try to read the seeding file.
|
||||
(update_random_seed_file): New.
|
||||
|
||||
(read_pool): Do an initial extra seeding when level 2 quality random
|
||||
is requested the first time. This requestes at least POOLSIZE/2 bytes
|
||||
of entropy. Compined with the seeding file this should make normal
|
||||
random bytes cheaper and increase the quality of the random bytes
|
||||
used for key generation.
|
||||
|
||||
* rndegd.c (gather_random): Shortcut level 0.
|
||||
* rndunix.c (gather_random): Ditto.
|
||||
* rndw32.c (gather_random): Ditto.
|
||||
|
||||
Fri Jan 14 18:32:01 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* rmd160.c (rmd160_get_info): Moved casting to the left side due to a
|
||||
problem with UTS4.3. Suggested by Dave Dykstra.
|
||||
* sha1.c (sha1_get_info): Ditto.
|
||||
* tiger.c (tiger_get_info): Ditto.
|
||||
* md5.c (md5_get_info): Ditto
|
||||
* des.c (des_get_info): Ditto.
|
||||
* blowfish.c (blowfish_get_info): Ditto.
|
||||
* cast5.c (cast5_get_info): Ditto.
|
||||
* twofish.c (twofish_get_info): Ditto.
|
||||
|
||||
Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* elgamal.c (wiener_map): New.
|
||||
(gen_k): Use a much smaller k.
|
||||
(generate): Calculate the qbits using the wiener map and
|
||||
choose an x at a size comparable to the one choosen in gen_k
|
||||
|
||||
* random.c (read_pool): Print a more friendly error message in
|
||||
cases when too much random is requested in one call.
|
||||
|
||||
* Makefile.am (tiger): Replaced -O1 by -O. Suggested by Alec Habig.
|
||||
|
||||
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* primegen.c (generate_elg_prime): All primes are now generated with
|
||||
the lowest random quality level. Becuase they are public anyway we
|
||||
don't need stronger random and by this we do not drain the systems
|
||||
entropy so much.
|
||||
|
||||
Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* random.c (fast_random_poll): Check whether RUSAGE_SELF is defined;
|
||||
this is not the case for some ESIX and Unixware, although they have
|
||||
getrusage().
|
||||
|
||||
* elgamal.c (sign): Hugh found strange code here. Replaced by BUG().
|
||||
|
||||
Mon Oct 11 09:24:12 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* rndw32.c (gather_random): Handle PCP_SEEDER_TOO_SMALL.
|
||||
|
||||
Sat Oct 9 20:34:41 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* Makefile.am: Tweaked module build and removed libtool
|
||||
|
||||
Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* rndw32.c (load_and_init_winseed): Use the Registry to locate the DLL
|
||||
|
||||
Mon Oct 4 21:23:04 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* md.c (md_reset): Clear finalized; thanks to Ulf Moeller for
|
||||
fixing this bug.
|
||||
|
||||
Sat Sep 18 12:51:51 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* Makefile.am: Never compile mingw32 as module
|
||||
|
||||
Wed Sep 15 14:39:59 CEST 1999 Michael Roth <mroth@nessie.de>
|
||||
|
||||
* des.c: Various speed improvements: One bit pre rotation
|
||||
trick after initial permutation (Richard Outerbridge).
|
||||
Finished test of SSLeay Tripple-DES patterns.
|
||||
|
||||
Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndw32.c: New.
|
||||
|
||||
Mon Sep 13 10:51:29 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* bithelp.h: New.
|
||||
* rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h
|
||||
|
||||
Tue Sep 7 16:23:36 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* Makefile.am: Fixed seds for latest egcc. By Ollivier Robert.
|
||||
|
||||
Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* des.c (selftest): Add some testpattern
|
||||
|
||||
Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using
|
||||
in place encryption. Pointed out by Frank Stajano.
|
||||
|
||||
Mon Jul 26 09:34:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* md5.c (md5_final): Fix for a SCO cpp bug.
|
||||
|
||||
Thu Jul 15 10:15:35 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* elgamal.c (elg_check_secret_key,elg_encrypt
|
||||
elg_decrypt,elg_sign,elg_verify): Sanity check on the args.
|
||||
* dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto.
|
||||
|
||||
* pubkey.c (disable_pubkey_algo): New.
|
||||
(check_pubkey_algo2): Look at disabled algo table.
|
||||
* cipher.c (disable_cipher_algo): New.
|
||||
(check_cipher_algo): Look at disabled algo table.
|
||||
|
||||
Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* Makefile.am: Support for libtool.
|
||||
|
||||
Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* dsa.c (gen_k): Changed algorithm to consume less random bytes
|
||||
* elgamal.c (gen_k): Ditto.
|
||||
|
||||
* random.c (random_dump_stats): New.
|
||||
|
||||
Thu Jul 1 12:47:31 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* primegen.c, elgamal.c, dsa.c (progess): New and replaced all
|
||||
fputc with a call to this function.
|
||||
|
||||
Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs.
|
||||
|
||||
* cipher.c (do_cbc_encrypt, do_cbc_decrypt): New.
|
||||
|
||||
* dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra).
|
||||
* Makefile.am (install-exec-hook): Removed.
|
||||
|
||||
Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* cipher.c (setup_cipher_table): Enable Twofish
|
||||
|
||||
* random.c (fast_random_poll): Disable use of times() for mingw32.
|
||||
|
||||
Mon May 17 21:54:43 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* dynload.c (register_internal_cipher_extension): Minor init fix.
|
||||
|
||||
Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* primegen.c (gen_prime): Readded the Fermat test. Fixed the bug
|
||||
that we didn't correct for step when passing the prime to the
|
||||
Rabin-Miller test which led to bad performance (Stefan Keller).
|
||||
(check_prime): Add a first Fermat test.
|
||||
|
||||
Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* cipher.c (cipher_setiv): Add ivlen arg, changed all callers.
|
||||
|
||||
* random.c (randomize_buffer): alway use secure memory because
|
||||
we can't use m_is_secure() on a statically allocated buffer.
|
||||
|
||||
* twofish.c: Replaced some macros by a loop to reduce text size.
|
||||
* Makefile.am (twofish): No more need for sed editing.
|
||||
|
||||
Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* cipher.c (cipher_open): Reversed the changes for AUTO_CFB.
|
||||
|
||||
* blowfish.c: Dropped the Blowfish 160 mode.
|
||||
* cipher.c (cipher_open): Ditto.
|
||||
(setup_cipher_table): Ditto. And removed support of twofish128
|
||||
|
||||
Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* random.c (get_random_bits): Can now handle requests > POOLSIZE
|
||||
|
||||
* cipher.c (cipher_open): Now uses standard CFB for automode if
|
||||
the blocksize is gt 8 (according to rfc2440).
|
||||
|
||||
* twofish.c: Applied Matthew Skala's patches for 256 bit key.
|
||||
|
||||
Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* random.c (get_random_bits): Can now handle requests > POOLSIZE
|
||||
|
||||
* cipher.c (cipher_open): Now uses standard CFB for automode if
|
||||
the blocksize is gt 8 (according to rfc2440).
|
||||
|
||||
Sat Mar 20 11:44:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndlinux.c (tty_printf) [IS_MODULE]: Removed.
|
||||
|
||||
* rndegd.c (gather_random): Some fixes.
|
||||
|
||||
Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndegd.c (do_read): New.
|
||||
(gather_random): Changed the implementation.
|
||||
|
||||
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed.
|
||||
|
||||
Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* md.c: Nearly a total rewrote.
|
||||
|
||||
Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* cipher.c (context): Fixed alignment
|
||||
* md.c: Ditto.
|
||||
|
||||
* rndegd.c: New
|
||||
|
||||
Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndegd.c: New.
|
||||
|
||||
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* Makefile.am: Modules are now figured out by configure
|
||||
* construct.c: New. Generated by configure. Changed all modules
|
||||
to work with that.
|
||||
* sha1.h: Removed.
|
||||
* md5.h: Removed.
|
||||
|
||||
* twofish.c: Changed interface to allow Twofish/256
|
||||
|
||||
* rndunix.c (start_gatherer): Die on SIGPIPE.
|
||||
|
||||
Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndunix.c (gather_random): Fix to avoid infinite loop.
|
||||
|
||||
Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* des.c (is_weak_key): Replace system memcmp due to bugs
|
||||
in SunOS's memcmp.
|
||||
(des_get_info): Return error on failed selftest.
|
||||
* twofish.c (twofish_setkey): Return error on failed selftest or
|
||||
invalid keylength.
|
||||
* cast5.c (cast_setkey): Ditto.
|
||||
* blowfish.c (bf_setkey): Return error on failed selftest.
|
||||
|
||||
Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* random.c (random_is_faked): New.
|
||||
|
||||
* tiger.c: Only compile if we have the u64 type
|
||||
|
||||
Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndunix.c (gather_random): check for setuid.
|
||||
|
||||
* Makefile.am: Add a way to staically link random modules
|
||||
|
||||
Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* md.c (md_stop_debug): Do a flush first.
|
||||
(md_open): size of buffer now depends on the secure parameter
|
||||
|
||||
Sun Jan 3 15:28:44 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* rndunix.c (start_gatherer): Fixed stupid ==/= bug
|
||||
|
||||
1998-12-31 Geoff Keating <geoffk@ozemail.com.au>
|
||||
|
||||
* des.c (is_weak_key): Rewrite loop end condition.
|
||||
|
||||
Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* random.c: add unistd.h for getpid().
|
||||
(RAND_MAX): Fallback value for Sun.
|
||||
|
||||
Wed Dec 23 17:12:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* md.c (md_copy): Reset debug.
|
||||
|
||||
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* random.c (read_random_source): Changed the interface to the
|
||||
random gathering function.
|
||||
(gather_faked): Use new interface.
|
||||
* dynload.c (dynload_getfnc_fast_random_poll): Ditto.
|
||||
(dynload_getfnc_gather_random): Ditto.
|
||||
* rndlinux.c (gather_random): Ditto.
|
||||
* rndunix.c (gather_random): Ditto.
|
||||
|
||||
Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* dynload.c (SYMBOL_VERSION): New to cope with system which needs
|
||||
underscores.
|
||||
|
||||
* rndunix.c: Rewrote large parts
|
||||
|
||||
Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* dynload.c (load_extension): increased needed verbosity level.
|
||||
|
||||
* random.c (fast_random_poll): Fallback to a default fast random
|
||||
poll function.
|
||||
(read_random_source): Always use the faked entroy gatherer if no
|
||||
gather module is available.
|
||||
* rndlinux.c (fast_poll): Removed.
|
||||
* rndunix.c (fast_poll): Removed.
|
||||
|
||||
|
||||
Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rand-*.c: Removed.
|
||||
* rndlinux.c : New.
|
||||
* rndunix.c : New.
|
||||
* random.c : Restructured the interface to the gather modules.
|
||||
(intialize): Call constructor functions
|
||||
(read_radnom_source): Moved to here.
|
||||
* dynload.c (dynload_getfnc_gather_random): New.
|
||||
(dynload_getfnc_fast_random_poll): New.
|
||||
(register_internal_cipher_extension): New.
|
||||
(register_cipher_extension): Support of internal modules.
|
||||
|
||||
Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rand-unix.c (read_random_source): Removed the assert.
|
||||
|
||||
Mon Oct 19 18:34:30 1998 me,,, (wk@tobold)
|
||||
|
||||
* pubkey.c: Hack to allow us to give some info about RSA keys back.
|
||||
|
||||
Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* dynload.c: Support for DLD
|
||||
|
||||
Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rand-unix.c: Now uses names from configure for /dev/random.
|
||||
|
||||
1998-10-10 SL Baur <steve@altair.xemacs.org>
|
||||
|
||||
* Makefile.am: fix sed -O substitutions to catch -O6, etc.
|
||||
|
||||
Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-)
|
||||
* rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto.
|
||||
|
||||
Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md.c (md_digest): New.
|
||||
(md_reset): New.
|
||||
|
||||
Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned.
|
||||
|
||||
Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none))
|
||||
|
||||
* des.c: Some patches from Michael.
|
||||
|
||||
Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none))
|
||||
|
||||
* des.c : New file from Michael Roth <mroth@nessie.de>
|
||||
|
||||
Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none))
|
||||
|
||||
* blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys.
|
||||
|
||||
Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none))
|
||||
|
||||
* dynload.c (RTLD_NOW): Now defined to 1 if it is undefined.
|
||||
|
||||
Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none))
|
||||
|
||||
* Makefile.am: Fixes to allow a different build directory
|
||||
|
||||
Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold)
|
||||
|
||||
* random.c (get_random_byte): Removed and changed all callers
|
||||
to use get_random_bits()
|
||||
|
||||
Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none))
|
||||
|
||||
* cipher.c : Support for other blocksizes
|
||||
(cipher_get_blocksize): New.
|
||||
* twofish.c: New.
|
||||
* Makefile.am: Add twofish module.
|
||||
|
||||
Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* random.c (read_pool): Simple alloc if secure_alloc is not set.
|
||||
(get_random_bits): Ditto.
|
||||
|
||||
Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* dynload.c (load_extension): Function now nbails out if
|
||||
the program is run setuid.
|
||||
|
||||
Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rmd160.c (rmd160_hash_buffer): New.
|
||||
|
||||
Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* cipher.c (cipher_open): algos >=100 use standard CFB
|
||||
|
||||
Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* Makefile.am: Support for extensions
|
||||
|
||||
Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* random.c (mix_pool): simpler handling for level 0
|
||||
|
||||
Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* tiger.c: Removed from dist, will reappear as dynload module
|
||||
|
||||
Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* pubkey.c: Major changes to allow extensions. Changed the inteface
|
||||
of all public key ciphers and added the ability to load extensions
|
||||
on demand.
|
||||
|
||||
* misc.c: Removed.
|
||||
|
||||
Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold)
|
||||
|
||||
* dynload.c: New.
|
||||
* cipher.c: Major changes to allow extensions.
|
||||
|
||||
Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* cipher.c: Major internal chnages to support extensions.
|
||||
* blowfish.c (blowfish_get_info): New and made all internal
|
||||
functions static, changed heder.
|
||||
* cast5.c (cast5_get_info): Likewise.
|
||||
|
||||
Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* tiger.c (transform): Fix for big endian
|
||||
|
||||
* cipher.c (do_cfb_decrypt): Big endian fix.
|
||||
|
||||
Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md.c (md_get_oid): Add a new one for TIGER.
|
||||
|
||||
Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* cipher.c: Add support for a dummy cipher
|
||||
|
||||
Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rmd160.c (transform): fixed sigbus - I should better
|
||||
add Christian von Roques's new implemenation of rmd160_write.
|
||||
|
||||
Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New
|
||||
* random.c: Moved system specific functions to rand-****.c
|
||||
|
||||
Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* random.c (fast_random_poll): add call to gethrtime.
|
||||
|
||||
Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* elgamal.c (elg_generate): choosing x was not correct, could
|
||||
yield 6 bytes which are not from the random pool, tsss, tsss..
|
||||
|
||||
Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* primegen.c (generate_elg_prime): Add arg mode, changed all
|
||||
callers and implemented mode 1.
|
||||
|
||||
Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* cipher.c (cipher_get_keylen): New.
|
||||
|
||||
Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* tiger.c, tiger.h: New.
|
||||
|
||||
Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* misc.c (check_pubkey_algo2): New.
|
||||
|
||||
Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* cipher.c: New
|
||||
* misc.c (check_cipher_algo): Moved to cipher.c
|
||||
* cast5.c: Moved many functions to cipher.c
|
||||
* blowfish.c: Likewise.
|
||||
|
||||
Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* cast5.c: Implemented and tested.
|
||||
|
||||
Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* elgamal.c (elg_generate): Faster generation of x in some cases.
|
||||
|
||||
Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* blowfish.c (blowfish_decode_cfb): changed XOR operation
|
||||
(blowfish_encode_cfb): Ditto.
|
||||
|
||||
Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* sha1.c (transform): Rewrote
|
||||
|
||||
* blowfish.c (encrypt): Unrolled for rounds == 16
|
||||
(decrypt): Ditto.
|
||||
|
||||
Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rmd160.c (transform): Unrolled the loop.
|
||||
|
||||
Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* random.c (read_pool): Add pool_balance stuff.
|
||||
(get_random_bits): New.
|
||||
|
||||
* elgamal.c (elg_generate): Now uses get_random_bits to generate x.
|
||||
|
||||
|
||||
Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md.c (md_digest_length): New.
|
||||
|
||||
Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* dsa.c (dsa_verify): Works.
|
||||
|
||||
Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* dsa.c, dsa.h: Removed some unused code.
|
||||
|
||||
Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md.c (md_open): Add call to fast_random_poll.
|
||||
blowfish.c (blowfish_setkey): Ditto.
|
||||
|
||||
Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* rmd160.c (rmd160_mixblock): New.
|
||||
* random.c: Restructured to start with a new RNG implementation.
|
||||
* random.h: New.
|
||||
|
||||
Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* gost.c, gost.h: Removed because they did only conatin trash.
|
||||
|
||||
Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* random.c (fill_buffer): removed error message if n == -1.
|
||||
|
||||
Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md.c (md_enable): No init if called twice.
|
||||
|
||||
Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* primegen.c (generate_elg_prime): Changed the progress printing.
|
||||
(gen_prime): Ditto.
|
||||
|
||||
Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md5.c, md.5 : Replaced by a modified version of md5.c from
|
||||
GNU textutils 1.22.
|
||||
|
||||
Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* md.c, md.h : New debugging support
|
||||
|
||||
Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* misc.c (cipher_algo_to_string): New
|
||||
(pubkey_algo_to_string): New.
|
||||
(digest_algo_to_string): New.
|
||||
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG 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.
|
||||
#
|
||||
# GnuPG 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; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
|
||||
INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
||||
|
||||
noinst_LIBRARIES = libcipher.a
|
||||
|
||||
# The configure script greps the module names from the EXTRA_PROGRAMS line
|
||||
EXTRA_PROGRAMS = rndlinux rndunix rndegd rndw32 sha1 rmd160 md5 tiger
|
||||
|
||||
EXTRA_rndlinux_SOURCES = rndlinux.c
|
||||
EXTRA_rndunix_SOURCES = rndunix.c
|
||||
EXTRA_rndegd_SOURCES = rndegd.c
|
||||
EXTRA_rndw32_SOURCES = rndw32.c
|
||||
EXTRA_md5_SOURCES = md5.c
|
||||
EXTRA_rmd160_SOURCES = rmd160.c
|
||||
EXTRA_sha1_SOURCES = sha1.c
|
||||
EXTRA_tiger_SOURCES = tiger.c
|
||||
|
||||
|
||||
if ENABLE_GNUPG_EXTENSIONS
|
||||
pkglib_PROGRAMS = @DYNAMIC_CIPHER_MODS@
|
||||
else
|
||||
pkglib_PROGRAMS =
|
||||
endif
|
||||
|
||||
|
||||
DYNLINK_MOD_CFLAGS = -DIS_MODULE @DYNLINK_MOD_CFLAGS@
|
||||
|
||||
#libcipher_a_LDFLAGS =
|
||||
libcipher_a_SOURCES = cipher.c \
|
||||
pubkey.c \
|
||||
md.c \
|
||||
dynload.c \
|
||||
dynload.h \
|
||||
bithelp.h \
|
||||
des.c \
|
||||
des.h \
|
||||
twofish.c \
|
||||
blowfish.c \
|
||||
blowfish.h \
|
||||
cast5.c \
|
||||
cast5.h \
|
||||
rijndael.c \
|
||||
elgamal.c \
|
||||
elgamal.h \
|
||||
rsa.c rsa.h \
|
||||
primegen.c \
|
||||
random.h \
|
||||
random.c \
|
||||
rand-internal.h \
|
||||
rmd.h \
|
||||
dsa.h \
|
||||
dsa.c \
|
||||
g10c.c \
|
||||
smallprime.c \
|
||||
construct.c
|
||||
|
||||
# configure creates the constructor file
|
||||
BUILT_SOURCES = construct.c
|
||||
DISTCLEANFILES = construct.c
|
||||
|
||||
libcipher_a_DEPENDENCIES = @STATIC_CIPHER_OBJS@
|
||||
libcipher_a_LIBADD = @STATIC_CIPHER_OBJS@
|
||||
|
||||
|
||||
# If I remember it correct, automake 1.4 has a feature to set
|
||||
# fooFLAGS depending on the program. So we should check it out.
|
||||
|
||||
tiger$(EXEEXT): $(srcdir)/tiger.c
|
||||
`echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o tiger $(srcdir)/tiger.c | \
|
||||
sed -e 's/-O[2-9s]*/-O/g' `
|
||||
|
||||
tiger.o: $(srcdir)/tiger.c
|
||||
`echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' `
|
||||
|
||||
#twofish: $(srcdir)/twofish.c
|
||||
# `echo $(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c | \
|
||||
# sed -e 's/-O[0-9s]*/ /g' `
|
||||
|
||||
twofish: $(srcdir)/twofish.c
|
||||
$(COMPILE) $(DYNLINK_MOD_CFLAGS) -o twofish $(srcdir)/twofish.c
|
||||
|
||||
#twofish.o: $(srcdir)/twofish.c
|
||||
# `echo $(COMPILE) -c $(srcdir)/twofish.c | sed -e 's/-O[0-9s]*/ /g' `
|
||||
|
||||
|
||||
rndunix$(EXEEXT): $(srcdir)/rndunix.c
|
||||
$(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndunix $(srcdir)/rndunix.c
|
||||
|
||||
rndlinux$(EXEEXT): $(srcdir)/rndlinux.c
|
||||
$(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndlinux $(srcdir)/rndlinux.c
|
||||
|
||||
rndegd$(EXEEXT): $(srcdir)/rndegd.c
|
||||
$(COMPILE) $(DYNLINK_MOD_CFLAGS) -o rndegd $(srcdir)/rndegd.c
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* bithelp.h - Some bit manipulation helpers
|
||||
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_BITHELP_H
|
||||
#define G10_BITHELP_H
|
||||
|
||||
|
||||
/****************
|
||||
* Rotate a 32 bit integer by n bytes
|
||||
*/
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
static inline u32
|
||||
rol( u32 x, int n)
|
||||
{
|
||||
__asm__("roll %%cl,%0"
|
||||
:"=r" (x)
|
||||
:"0" (x),"c" (n));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*G10_BITHELP_H*/
|
|
@ -0,0 +1,633 @@
|
|||
/* blowfish.c - Blowfish encryption
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* For a description of the algorithm, see:
|
||||
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
|
||||
* ISBN 0-471-11709-9. Pages 336 ff.
|
||||
*/
|
||||
|
||||
/* Test values:
|
||||
* key "abcdefghijklmnopqrstuvwxyz";
|
||||
* plain "BLOWFISH"
|
||||
* cipher 32 4E D0 FE F4 13 A2 03
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "types.h"
|
||||
#include "errors.h"
|
||||
#include "blowfish.h"
|
||||
#include "dynload.h"
|
||||
|
||||
|
||||
|
||||
#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */
|
||||
|
||||
#define BLOWFISH_BLOCKSIZE 8
|
||||
#define BLOWFISH_ROUNDS 16
|
||||
|
||||
typedef struct {
|
||||
u32 s0[256];
|
||||
u32 s1[256];
|
||||
u32 s2[256];
|
||||
u32 s3[256];
|
||||
u32 p[BLOWFISH_ROUNDS+2];
|
||||
} BLOWFISH_context;
|
||||
|
||||
static int bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen );
|
||||
static void encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf );
|
||||
static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf );
|
||||
|
||||
|
||||
/* precomputed S boxes */
|
||||
static const u32 ks0[256] = {
|
||||
0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96,
|
||||
0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16,
|
||||
0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658,
|
||||
0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013,
|
||||
0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E,
|
||||
0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60,
|
||||
0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6,
|
||||
0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A,
|
||||
0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C,
|
||||
0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193,
|
||||
0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1,
|
||||
0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239,
|
||||
0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A,
|
||||
0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3,
|
||||
0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176,
|
||||
0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE,
|
||||
0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706,
|
||||
0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B,
|
||||
0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B,
|
||||
0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463,
|
||||
0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C,
|
||||
0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3,
|
||||
0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A,
|
||||
0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8,
|
||||
0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760,
|
||||
0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB,
|
||||
0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8,
|
||||
0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B,
|
||||
0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33,
|
||||
0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4,
|
||||
0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0,
|
||||
0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C,
|
||||
0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777,
|
||||
0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299,
|
||||
0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705,
|
||||
0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF,
|
||||
0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E,
|
||||
0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA,
|
||||
0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9,
|
||||
0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915,
|
||||
0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F,
|
||||
0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664,
|
||||
0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A };
|
||||
|
||||
static const u32 ks1[256] = {
|
||||
0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D,
|
||||
0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1,
|
||||
0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65,
|
||||
0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1,
|
||||
0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9,
|
||||
0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737,
|
||||
0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D,
|
||||
0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD,
|
||||
0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC,
|
||||
0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41,
|
||||
0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908,
|
||||
0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF,
|
||||
0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124,
|
||||
0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C,
|
||||
0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908,
|
||||
0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD,
|
||||
0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B,
|
||||
0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E,
|
||||
0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA,
|
||||
0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A,
|
||||
0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D,
|
||||
0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66,
|
||||
0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5,
|
||||
0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84,
|
||||
0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96,
|
||||
0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14,
|
||||
0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA,
|
||||
0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7,
|
||||
0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77,
|
||||
0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99,
|
||||
0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054,
|
||||
0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73,
|
||||
0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA,
|
||||
0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105,
|
||||
0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646,
|
||||
0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285,
|
||||
0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA,
|
||||
0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB,
|
||||
0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E,
|
||||
0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC,
|
||||
0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD,
|
||||
0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20,
|
||||
0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 };
|
||||
|
||||
static const u32 ks2[256] = {
|
||||
0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7,
|
||||
0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF,
|
||||
0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF,
|
||||
0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504,
|
||||
0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4,
|
||||
0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE,
|
||||
0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC,
|
||||
0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B,
|
||||
0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332,
|
||||
0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527,
|
||||
0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58,
|
||||
0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C,
|
||||
0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22,
|
||||
0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17,
|
||||
0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60,
|
||||
0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115,
|
||||
0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99,
|
||||
0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0,
|
||||
0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74,
|
||||
0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D,
|
||||
0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3,
|
||||
0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3,
|
||||
0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979,
|
||||
0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C,
|
||||
0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA,
|
||||
0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A,
|
||||
0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086,
|
||||
0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC,
|
||||
0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24,
|
||||
0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2,
|
||||
0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84,
|
||||
0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C,
|
||||
0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09,
|
||||
0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10,
|
||||
0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE,
|
||||
0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027,
|
||||
0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0,
|
||||
0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634,
|
||||
0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188,
|
||||
0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC,
|
||||
0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8,
|
||||
0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837,
|
||||
0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 };
|
||||
|
||||
static const u32 ks3[256] = {
|
||||
0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742,
|
||||
0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B,
|
||||
0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79,
|
||||
0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6,
|
||||
0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A,
|
||||
0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4,
|
||||
0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1,
|
||||
0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59,
|
||||
0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797,
|
||||
0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28,
|
||||
0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6,
|
||||
0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28,
|
||||
0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA,
|
||||
0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A,
|
||||
0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5,
|
||||
0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F,
|
||||
0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE,
|
||||
0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680,
|
||||
0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD,
|
||||
0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB,
|
||||
0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB,
|
||||
0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370,
|
||||
0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC,
|
||||
0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048,
|
||||
0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC,
|
||||
0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9,
|
||||
0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A,
|
||||
0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F,
|
||||
0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A,
|
||||
0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1,
|
||||
0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B,
|
||||
0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E,
|
||||
0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E,
|
||||
0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F,
|
||||
0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623,
|
||||
0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC,
|
||||
0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A,
|
||||
0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6,
|
||||
0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3,
|
||||
0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060,
|
||||
0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C,
|
||||
0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F,
|
||||
0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 };
|
||||
|
||||
static const u32 ps[BLOWFISH_ROUNDS+2] = {
|
||||
0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0,
|
||||
0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C,
|
||||
0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B };
|
||||
|
||||
|
||||
|
||||
#if BLOWFISH_ROUNDS != 16
|
||||
static inline u32
|
||||
function_F( BLOWFISH_context *bc, u32 x )
|
||||
{
|
||||
u16 a, b, c, d;
|
||||
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
a = ((byte*)&x)[0];
|
||||
b = ((byte*)&x)[1];
|
||||
c = ((byte*)&x)[2];
|
||||
d = ((byte*)&x)[3];
|
||||
#else
|
||||
a = ((byte*)&x)[3];
|
||||
b = ((byte*)&x)[2];
|
||||
c = ((byte*)&x)[1];
|
||||
d = ((byte*)&x)[0];
|
||||
#endif
|
||||
|
||||
return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
#define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \
|
||||
^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] )
|
||||
#else
|
||||
#define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \
|
||||
^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] )
|
||||
#endif
|
||||
#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0)
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
|
||||
{
|
||||
#if BLOWFISH_ROUNDS == 16
|
||||
u32 xl, xr, *s0, *s1, *s2, *s3, *p;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
s0 = bc->s0;
|
||||
s1 = bc->s1;
|
||||
s2 = bc->s2;
|
||||
s3 = bc->s3;
|
||||
|
||||
R( xl, xr, 0);
|
||||
R( xr, xl, 1);
|
||||
R( xl, xr, 2);
|
||||
R( xr, xl, 3);
|
||||
R( xl, xr, 4);
|
||||
R( xr, xl, 5);
|
||||
R( xl, xr, 6);
|
||||
R( xr, xl, 7);
|
||||
R( xl, xr, 8);
|
||||
R( xr, xl, 9);
|
||||
R( xl, xr, 10);
|
||||
R( xr, xl, 11);
|
||||
R( xl, xr, 12);
|
||||
R( xr, xl, 13);
|
||||
R( xl, xr, 14);
|
||||
R( xr, xl, 15);
|
||||
|
||||
xl ^= p[BLOWFISH_ROUNDS];
|
||||
xr ^= p[BLOWFISH_ROUNDS+1];
|
||||
|
||||
*ret_xl = xr;
|
||||
*ret_xr = xl;
|
||||
|
||||
#else
|
||||
u32 xl, xr, temp, *p;
|
||||
int i;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
|
||||
for(i=0; i < BLOWFISH_ROUNDS; i++ ) {
|
||||
xl ^= p[i];
|
||||
xr ^= function_F(bc, xl);
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
}
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
|
||||
xr ^= p[BLOWFISH_ROUNDS];
|
||||
xl ^= p[BLOWFISH_ROUNDS+1];
|
||||
|
||||
*ret_xl = xl;
|
||||
*ret_xr = xr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
|
||||
{
|
||||
#if BLOWFISH_ROUNDS == 16
|
||||
u32 xl, xr, *s0, *s1, *s2, *s3, *p;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
s0 = bc->s0;
|
||||
s1 = bc->s1;
|
||||
s2 = bc->s2;
|
||||
s3 = bc->s3;
|
||||
|
||||
R( xl, xr, 17);
|
||||
R( xr, xl, 16);
|
||||
R( xl, xr, 15);
|
||||
R( xr, xl, 14);
|
||||
R( xl, xr, 13);
|
||||
R( xr, xl, 12);
|
||||
R( xl, xr, 11);
|
||||
R( xr, xl, 10);
|
||||
R( xl, xr, 9);
|
||||
R( xr, xl, 8);
|
||||
R( xl, xr, 7);
|
||||
R( xr, xl, 6);
|
||||
R( xl, xr, 5);
|
||||
R( xr, xl, 4);
|
||||
R( xl, xr, 3);
|
||||
R( xr, xl, 2);
|
||||
|
||||
xl ^= p[1];
|
||||
xr ^= p[0];
|
||||
|
||||
*ret_xl = xr;
|
||||
*ret_xr = xl;
|
||||
|
||||
#else
|
||||
u32 xl, xr, temp, *p;
|
||||
int i;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
|
||||
for(i=BLOWFISH_ROUNDS+1; i > 1; i-- ) {
|
||||
xl ^= p[i];
|
||||
xr ^= function_F(bc, xl);
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
}
|
||||
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
|
||||
xr ^= p[1];
|
||||
xl ^= p[0];
|
||||
|
||||
*ret_xl = xl;
|
||||
*ret_xr = xr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef F
|
||||
#undef R
|
||||
|
||||
static void
|
||||
do_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 d1, d2;
|
||||
|
||||
d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
do_encrypt( bc, &d1, &d2 );
|
||||
outbuf[0] = (d1 >> 24) & 0xff;
|
||||
outbuf[1] = (d1 >> 16) & 0xff;
|
||||
outbuf[2] = (d1 >> 8) & 0xff;
|
||||
outbuf[3] = d1 & 0xff;
|
||||
outbuf[4] = (d2 >> 24) & 0xff;
|
||||
outbuf[5] = (d2 >> 16) & 0xff;
|
||||
outbuf[6] = (d2 >> 8) & 0xff;
|
||||
outbuf[7] = d2 & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_encrypt_block (bc, outbuf, inbuf);
|
||||
burn_stack (64);
|
||||
}
|
||||
|
||||
static void
|
||||
do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 d1, d2;
|
||||
|
||||
d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
decrypt( bc, &d1, &d2 );
|
||||
outbuf[0] = (d1 >> 24) & 0xff;
|
||||
outbuf[1] = (d1 >> 16) & 0xff;
|
||||
outbuf[2] = (d1 >> 8) & 0xff;
|
||||
outbuf[3] = d1 & 0xff;
|
||||
outbuf[4] = (d2 >> 24) & 0xff;
|
||||
outbuf[5] = (d2 >> 16) & 0xff;
|
||||
outbuf[6] = (d2 >> 8) & 0xff;
|
||||
outbuf[7] = d2 & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_decrypt_block (bc, outbuf, inbuf);
|
||||
burn_stack (64);
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
selftest(void)
|
||||
{
|
||||
BLOWFISH_context c;
|
||||
byte plain[] = "BLOWFISH";
|
||||
byte buffer[8];
|
||||
byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 };
|
||||
byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 };
|
||||
byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 };
|
||||
|
||||
bf_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 );
|
||||
encrypt_block( &c, buffer, plain );
|
||||
if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) )
|
||||
return "Blowfish selftest failed (1).";
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain, 8 ) )
|
||||
return "Blowfish selftest failed (2).";
|
||||
|
||||
bf_setkey( &c, key3, 8 );
|
||||
encrypt_block( &c, buffer, plain3 );
|
||||
if( memcmp( buffer, cipher3, 8 ) )
|
||||
return "Blowfish selftest failed (3).";
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain3, 8 ) )
|
||||
return "Blowfish selftest failed (4).";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
/* need to switch off CSE optimisation for Norcroft C (Acorn/Pace) */
|
||||
#pragma no_optimise_cse
|
||||
#endif /* __riscos__ */
|
||||
|
||||
static int
|
||||
do_bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
int i, j;
|
||||
u32 data, datal, datar;
|
||||
static int initialized;
|
||||
static const char *selftest_failed;
|
||||
|
||||
if( !initialized ) {
|
||||
initialized = 1;
|
||||
selftest_failed = selftest();
|
||||
if( selftest_failed )
|
||||
fprintf(stderr,"%s\n", selftest_failed );
|
||||
}
|
||||
if( selftest_failed )
|
||||
return G10ERR_SELFTEST_FAILED;
|
||||
|
||||
for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
|
||||
c->p[i] = ps[i];
|
||||
for(i=0; i < 256; i++ ) {
|
||||
c->s0[i] = ks0[i];
|
||||
c->s1[i] = ks1[i];
|
||||
c->s2[i] = ks2[i];
|
||||
c->s3[i] = ks3[i];
|
||||
}
|
||||
|
||||
for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) {
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
((byte*)&data)[0] = key[j];
|
||||
((byte*)&data)[1] = key[(j+1)%keylen];
|
||||
((byte*)&data)[2] = key[(j+2)%keylen];
|
||||
((byte*)&data)[3] = key[(j+3)%keylen];
|
||||
#else
|
||||
((byte*)&data)[3] = key[j];
|
||||
((byte*)&data)[2] = key[(j+1)%keylen];
|
||||
((byte*)&data)[1] = key[(j+2)%keylen];
|
||||
((byte*)&data)[0] = key[(j+3)%keylen];
|
||||
#endif
|
||||
c->p[i] ^= data;
|
||||
j = (j+4) % keylen;
|
||||
}
|
||||
|
||||
datal = datar = 0;
|
||||
for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->p[i] = datal;
|
||||
c->p[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s0[i] = datal;
|
||||
c->s0[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s1[i] = datal;
|
||||
c->s1[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s2[i] = datal;
|
||||
c->s2[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s3[i] = datal;
|
||||
c->s3[i+1] = datar;
|
||||
}
|
||||
|
||||
|
||||
/* Check for weak key. A weak key is a key in which a value in */
|
||||
/* the P-array (here c) occurs more than once per table. */
|
||||
for(i=0; i < 255; i++ ) {
|
||||
for( j=i+1; j < 256; j++) {
|
||||
if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) ||
|
||||
(c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) )
|
||||
return G10ERR_WEAK_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
#pragma optimise_cse
|
||||
#endif /* __riscos__ */
|
||||
|
||||
static int
|
||||
bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
int rc = do_bf_setkey (c, key, keylen);
|
||||
burn_stack (64);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
const char *
|
||||
blowfish_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**r_setkey)( void *c, byte *key, unsigned keylen ),
|
||||
void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf )
|
||||
)
|
||||
{
|
||||
*keylen = 128;
|
||||
*blocksize = BLOWFISH_BLOCKSIZE;
|
||||
*contextsize = sizeof(BLOWFISH_context);
|
||||
*(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey
|
||||
= bf_setkey;
|
||||
*(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt
|
||||
= encrypt_block;
|
||||
*(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt
|
||||
= decrypt_block;
|
||||
|
||||
if( algo == CIPHER_ALGO_BLOWFISH )
|
||||
return "BLOWFISH";
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/* blowfish.h
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_BLOWFISH_H
|
||||
#define G10_BLOWFISH_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
const char *
|
||||
blowfish_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
/* this is just a kludge for the time we have not yet chnaged the cipher
|
||||
* stuff to the scheme we use for random and digests */
|
||||
const char *
|
||||
twofish_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
/* this is just a kludge for the time we have not yet chnaged the cipher
|
||||
* stuff to the scheme we use for random and digests */
|
||||
const char *
|
||||
rijndael_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
#endif /*G10_BLOWFISH_H*/
|
|
@ -0,0 +1,654 @@
|
|||
/* cast5.c - CAST5 cipher (RFC2144)
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* Test vectors:
|
||||
*
|
||||
* 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
|
||||
* plaintext = 01 23 45 67 89 AB CD EF
|
||||
* ciphertext = 23 8B 4F E5 84 7E 44 B2
|
||||
*
|
||||
* 80-bit key = 01 23 45 67 12 34 56 78 23 45
|
||||
* = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
|
||||
* plaintext = 01 23 45 67 89 AB CD EF
|
||||
* ciphertext = EB 6A 71 1A 2C 02 27 1B
|
||||
*
|
||||
* 40-bit key = 01 23 45 67 12
|
||||
* = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
|
||||
* plaintext = 01 23 45 67 89 AB CD EF
|
||||
* ciphertext = 7A C8 16 D1 6E 9B 30 2E
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "errors.h"
|
||||
#include "cast5.h"
|
||||
|
||||
|
||||
#define CIPHER_ALGO_CAST5 3
|
||||
|
||||
#define CAST5_BLOCKSIZE 8
|
||||
|
||||
typedef struct {
|
||||
u32 Km[16];
|
||||
byte Kr[16];
|
||||
} CAST5_context;
|
||||
|
||||
static int cast_setkey( CAST5_context *c, byte *key, unsigned keylen );
|
||||
static void encrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf );
|
||||
static void decrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf );
|
||||
|
||||
|
||||
|
||||
|
||||
static const u32 s1[256] = {
|
||||
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
|
||||
0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
|
||||
0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
|
||||
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
|
||||
0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
|
||||
0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
|
||||
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
|
||||
0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
|
||||
0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
|
||||
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
|
||||
0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
|
||||
0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
|
||||
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
|
||||
0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
|
||||
0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
|
||||
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
|
||||
0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
|
||||
0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
|
||||
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
|
||||
0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
|
||||
0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
|
||||
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
|
||||
0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
|
||||
0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
|
||||
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
|
||||
0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
|
||||
0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
|
||||
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
|
||||
0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
|
||||
0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
|
||||
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
|
||||
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
|
||||
};
|
||||
static const u32 s2[256] = {
|
||||
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
|
||||
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
|
||||
0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
|
||||
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
|
||||
0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
|
||||
0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
|
||||
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
|
||||
0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
|
||||
0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
|
||||
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
|
||||
0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
|
||||
0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
|
||||
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
|
||||
0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
|
||||
0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
|
||||
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
|
||||
0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
|
||||
0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
|
||||
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
|
||||
0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
|
||||
0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
|
||||
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
|
||||
0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
|
||||
0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
|
||||
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
|
||||
0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
|
||||
0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
|
||||
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
|
||||
0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
|
||||
0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
|
||||
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
|
||||
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
|
||||
};
|
||||
static const u32 s3[256] = {
|
||||
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
|
||||
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
|
||||
0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
|
||||
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
|
||||
0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
|
||||
0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
|
||||
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
|
||||
0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
|
||||
0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
|
||||
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
|
||||
0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
|
||||
0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
|
||||
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
|
||||
0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
|
||||
0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
|
||||
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
|
||||
0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
|
||||
0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
|
||||
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
|
||||
0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
|
||||
0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
|
||||
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
|
||||
0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
|
||||
0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
|
||||
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
|
||||
0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
|
||||
0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
|
||||
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
|
||||
0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
|
||||
0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
|
||||
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
|
||||
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
|
||||
};
|
||||
static const u32 s4[256] = {
|
||||
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
|
||||
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
|
||||
0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
|
||||
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
|
||||
0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
|
||||
0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
|
||||
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
|
||||
0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
|
||||
0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
|
||||
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
|
||||
0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
|
||||
0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
|
||||
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
|
||||
0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
|
||||
0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
|
||||
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
|
||||
0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
|
||||
0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
|
||||
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
|
||||
0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
|
||||
0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
|
||||
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
|
||||
0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
|
||||
0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
|
||||
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
|
||||
0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
|
||||
0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
|
||||
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
|
||||
0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
|
||||
0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
|
||||
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
|
||||
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
|
||||
};
|
||||
static const u32 s5[256] = {
|
||||
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
|
||||
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
|
||||
0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
|
||||
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
|
||||
0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
|
||||
0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
|
||||
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
|
||||
0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
|
||||
0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
|
||||
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
|
||||
0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
|
||||
0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
|
||||
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
|
||||
0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
|
||||
0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
|
||||
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
|
||||
0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
|
||||
0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
|
||||
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
|
||||
0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
|
||||
0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
|
||||
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
|
||||
0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
|
||||
0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
|
||||
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
|
||||
0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
|
||||
0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
|
||||
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
|
||||
0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
|
||||
0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
|
||||
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
|
||||
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
|
||||
};
|
||||
static const u32 s6[256] = {
|
||||
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
|
||||
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
|
||||
0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
|
||||
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
|
||||
0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
|
||||
0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
|
||||
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
|
||||
0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
|
||||
0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
|
||||
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
|
||||
0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
|
||||
0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
|
||||
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
|
||||
0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
|
||||
0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
|
||||
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
|
||||
0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
|
||||
0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
|
||||
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
|
||||
0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
|
||||
0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
|
||||
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
|
||||
0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
|
||||
0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
|
||||
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
|
||||
0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
|
||||
0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
|
||||
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
|
||||
0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
|
||||
0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
|
||||
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
|
||||
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
|
||||
};
|
||||
static const u32 s7[256] = {
|
||||
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
|
||||
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
|
||||
0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
|
||||
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
|
||||
0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
|
||||
0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
|
||||
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
|
||||
0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
|
||||
0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
|
||||
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
|
||||
0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
|
||||
0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
|
||||
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
|
||||
0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
|
||||
0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
|
||||
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
|
||||
0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
|
||||
0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
|
||||
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
|
||||
0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
|
||||
0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
|
||||
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
|
||||
0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
|
||||
0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
|
||||
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
|
||||
0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
|
||||
0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
|
||||
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
|
||||
0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
|
||||
0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
|
||||
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
|
||||
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
|
||||
};
|
||||
static const u32 s8[256] = {
|
||||
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
|
||||
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
|
||||
0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
|
||||
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
|
||||
0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
|
||||
0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
|
||||
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
|
||||
0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
|
||||
0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
|
||||
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
|
||||
0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
|
||||
0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
|
||||
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
|
||||
0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
|
||||
0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
|
||||
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
|
||||
0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
|
||||
0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
|
||||
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
|
||||
0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
|
||||
0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
|
||||
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
|
||||
0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
|
||||
0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
|
||||
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
|
||||
0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
|
||||
0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
|
||||
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
|
||||
0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
|
||||
0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
|
||||
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
|
||||
0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
|
||||
};
|
||||
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
static inline u32
|
||||
rol(int n, u32 x)
|
||||
{
|
||||
__asm__("roll %%cl,%0"
|
||||
:"=r" (x)
|
||||
:"0" (x),"c" (n));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
|
||||
#endif
|
||||
|
||||
#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \
|
||||
(((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
|
||||
#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \
|
||||
(((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
|
||||
#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \
|
||||
(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 l, r, t;
|
||||
u32 I; /* used by the Fx macros */
|
||||
u32 *Km;
|
||||
byte *Kr;
|
||||
|
||||
Km = c->Km;
|
||||
Kr = c->Kr;
|
||||
|
||||
/* (L0,R0) <-- (m1...m64). (Split the plaintext into left and
|
||||
* right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
|
||||
*/
|
||||
l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
|
||||
/* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
|
||||
* Li = Ri-1;
|
||||
* Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
|
||||
* Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1.
|
||||
* Rounds 2, 5, 8, 11, and 14 use f function Type 2.
|
||||
* Rounds 3, 6, 9, 12, and 15 use f function Type 3.
|
||||
*/
|
||||
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
|
||||
|
||||
/* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and
|
||||
* concatenate to form the ciphertext.) */
|
||||
outbuf[0] = (r >> 24) & 0xff;
|
||||
outbuf[1] = (r >> 16) & 0xff;
|
||||
outbuf[2] = (r >> 8) & 0xff;
|
||||
outbuf[3] = r & 0xff;
|
||||
outbuf[4] = (l >> 24) & 0xff;
|
||||
outbuf[5] = (l >> 16) & 0xff;
|
||||
outbuf[6] = (l >> 8) & 0xff;
|
||||
outbuf[7] = l & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_encrypt_block (c, outbuf, inbuf);
|
||||
burn_stack (20+4*sizeof(void*));
|
||||
}
|
||||
|
||||
static void
|
||||
do_decrypt_block (CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 l, r, t;
|
||||
u32 I;
|
||||
u32 *Km;
|
||||
byte *Kr;
|
||||
|
||||
Km = c->Km;
|
||||
Kr = c->Kr;
|
||||
|
||||
l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
|
||||
t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
|
||||
|
||||
outbuf[0] = (r >> 24) & 0xff;
|
||||
outbuf[1] = (r >> 16) & 0xff;
|
||||
outbuf[2] = (r >> 8) & 0xff;
|
||||
outbuf[3] = r & 0xff;
|
||||
outbuf[4] = (l >> 24) & 0xff;
|
||||
outbuf[5] = (l >> 16) & 0xff;
|
||||
outbuf[6] = (l >> 8) & 0xff;
|
||||
outbuf[7] = l & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_decrypt_block (c, outbuf, inbuf);
|
||||
burn_stack (20+4*sizeof(void*));
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
selftest(void)
|
||||
{
|
||||
CAST5_context c;
|
||||
byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
|
||||
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A };
|
||||
byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
|
||||
byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 };
|
||||
byte buffer[8];
|
||||
|
||||
cast_setkey( &c, key, 16 );
|
||||
encrypt_block( &c, buffer, plain );
|
||||
if( memcmp( buffer, cipher, 8 ) )
|
||||
return "1";
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain, 8 ) )
|
||||
return "2";
|
||||
|
||||
#if 0 /* full maintenance test */
|
||||
{
|
||||
int i;
|
||||
byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
|
||||
0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
|
||||
byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
|
||||
0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
|
||||
byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6,
|
||||
0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 };
|
||||
byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71,
|
||||
0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E };
|
||||
|
||||
for(i=0; i < 1000000; i++ ) {
|
||||
cast_setkey( &c, b0, 16 );
|
||||
encrypt_block( &c, a0, a0 );
|
||||
encrypt_block( &c, a0+8, a0+8 );
|
||||
cast_setkey( &c, a0, 16 );
|
||||
encrypt_block( &c, b0, b0 );
|
||||
encrypt_block( &c, b0+8, b0+8 );
|
||||
}
|
||||
if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) )
|
||||
return "3";
|
||||
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
key_schedule( u32 *x, u32 *z, u32 *k )
|
||||
{
|
||||
|
||||
#define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
|
||||
#define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
|
||||
|
||||
z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
|
||||
z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
|
||||
z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
|
||||
z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
|
||||
k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)];
|
||||
k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)];
|
||||
k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)];
|
||||
k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)];
|
||||
|
||||
x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
|
||||
x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
|
||||
x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
|
||||
x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
|
||||
k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)];
|
||||
k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)];
|
||||
k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)];
|
||||
k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)];
|
||||
|
||||
z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
|
||||
z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
|
||||
z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
|
||||
z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
|
||||
k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)];
|
||||
k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)];
|
||||
k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)];
|
||||
k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)];
|
||||
|
||||
x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
|
||||
x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
|
||||
x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
|
||||
x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
|
||||
k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)];
|
||||
k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)];
|
||||
k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)];
|
||||
k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)];
|
||||
|
||||
#undef xi
|
||||
#undef zi
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
static int initialized;
|
||||
static const char* selftest_failed;
|
||||
int i;
|
||||
u32 x[4];
|
||||
u32 z[4];
|
||||
u32 k[16];
|
||||
|
||||
if( !initialized ) {
|
||||
initialized = 1;
|
||||
selftest_failed = selftest();
|
||||
if( selftest_failed )
|
||||
fprintf(stderr,"CAST5 selftest failed (%s).\n", selftest_failed );
|
||||
}
|
||||
if( selftest_failed )
|
||||
return G10ERR_SELFTEST_FAILED;
|
||||
|
||||
if( keylen != 16 )
|
||||
return G10ERR_WRONG_KEYLEN;
|
||||
|
||||
x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3];
|
||||
x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7];
|
||||
x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11];
|
||||
x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15];
|
||||
|
||||
key_schedule( x, z, k );
|
||||
for(i=0; i < 16; i++ )
|
||||
c->Km[i] = k[i];
|
||||
key_schedule( x, z, k );
|
||||
for(i=0; i < 16; i++ )
|
||||
c->Kr[i] = k[i] & 0x1f;
|
||||
|
||||
memset(&x,0, sizeof x);
|
||||
memset(&z,0, sizeof z);
|
||||
memset(&k,0, sizeof k);
|
||||
|
||||
#undef xi
|
||||
#undef zi
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
int rc = do_cast_setkey (c, key, keylen);
|
||||
burn_stack (96+7*sizeof(void*));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
const char *
|
||||
cast5_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**r_setkey)( void *c, byte *key, unsigned keylen ),
|
||||
void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf )
|
||||
)
|
||||
{
|
||||
*keylen = 128;
|
||||
*blocksize = CAST5_BLOCKSIZE;
|
||||
*contextsize = sizeof(CAST5_context);
|
||||
*(int (**)(CAST5_context*, byte*, unsigned))r_setkey
|
||||
= cast_setkey;
|
||||
*(void (**)(CAST5_context*, byte*, byte*))r_encrypt
|
||||
= encrypt_block;
|
||||
*(void (**)(CAST5_context*, byte*, byte*))r_decrypt
|
||||
= decrypt_block;
|
||||
|
||||
|
||||
if( algo == CIPHER_ALGO_CAST5 )
|
||||
return "CAST5";
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/* cast5.h
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_CAST5_H
|
||||
#define G10_CAST5_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
const char *
|
||||
cast5_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
#endif /*G10_CAST5_H*/
|
|
@ -0,0 +1,712 @@
|
|||
/* cipher.c - cipher dispatcher
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "errors.h"
|
||||
#include "cipher.h"
|
||||
#include "des.h"
|
||||
#include "blowfish.h"
|
||||
#include "cast5.h"
|
||||
#include "dynload.h"
|
||||
|
||||
|
||||
#define MAX_BLOCKSIZE 16
|
||||
#define TABLE_SIZE 14
|
||||
|
||||
struct cipher_table_s {
|
||||
const char *name;
|
||||
int algo;
|
||||
size_t blocksize;
|
||||
size_t keylen;
|
||||
size_t contextsize; /* allocate this amount of context */
|
||||
int (*setkey)( void *c, byte *key, unsigned keylen );
|
||||
void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
};
|
||||
|
||||
static struct cipher_table_s cipher_table[TABLE_SIZE];
|
||||
static int disabled_algos[TABLE_SIZE];
|
||||
|
||||
|
||||
struct cipher_handle_s {
|
||||
int algo;
|
||||
int mode;
|
||||
size_t blocksize;
|
||||
byte iv[MAX_BLOCKSIZE]; /* (this should be ulong aligned) */
|
||||
byte lastiv[MAX_BLOCKSIZE];
|
||||
int unused; /* in IV */
|
||||
int (*setkey)( void *c, byte *key, unsigned keylen );
|
||||
void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
PROPERLY_ALIGNED_TYPE context;
|
||||
};
|
||||
|
||||
|
||||
#ifdef IS_DEVELOPMENT_VERSION
|
||||
static int
|
||||
dummy_setkey( void *c, byte *key, unsigned keylen ) { return 0; }
|
||||
static void
|
||||
dummy_encrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); }
|
||||
static void
|
||||
dummy_decrypt_block( void *c, byte *outbuf, byte *inbuf ) { BUG(); }
|
||||
#endif
|
||||
|
||||
|
||||
/****************
|
||||
* Put the static entries into the table.
|
||||
*/
|
||||
static void
|
||||
setup_cipher_table(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL;
|
||||
cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL192;
|
||||
cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL256;
|
||||
cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_TWOFISH;
|
||||
cipher_table[i].name = twofish_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_BLOWFISH;
|
||||
cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_CAST5;
|
||||
cipher_table[i].name = cast5_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_3DES;
|
||||
cipher_table[i].name = des_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
|
||||
#ifdef IS_DEVELOPMENT_VERSION
|
||||
cipher_table[i].algo = CIPHER_ALGO_DUMMY;
|
||||
cipher_table[i].name = "DUMMY";
|
||||
cipher_table[i].blocksize = 8;
|
||||
cipher_table[i].keylen = 128;
|
||||
cipher_table[i].contextsize = 0;
|
||||
cipher_table[i].setkey = dummy_setkey;
|
||||
cipher_table[i].encrypt = dummy_encrypt_block;
|
||||
cipher_table[i].decrypt = dummy_decrypt_block;
|
||||
i++;
|
||||
#endif
|
||||
|
||||
for( ; i < TABLE_SIZE; i++ )
|
||||
cipher_table[i].name = NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Try to load all modules and return true if new modules are available
|
||||
*/
|
||||
static int
|
||||
load_cipher_modules(void)
|
||||
{
|
||||
static int done = 0;
|
||||
static int initialized = 0;
|
||||
void *context = NULL;
|
||||
struct cipher_table_s *ct;
|
||||
int ct_idx;
|
||||
int i;
|
||||
const char *name;
|
||||
int any = 0;
|
||||
|
||||
if( !initialized ) {
|
||||
cipher_modules_constructor();
|
||||
setup_cipher_table(); /* load static modules on the first call */
|
||||
initialized = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( done )
|
||||
return 0;
|
||||
done = 1;
|
||||
|
||||
for(ct_idx=0, ct = cipher_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
|
||||
if( !ct->name )
|
||||
break;
|
||||
}
|
||||
if( ct_idx >= TABLE_SIZE-1 )
|
||||
BUG(); /* table already full */
|
||||
/* now load all extensions */
|
||||
while( (name = enum_gnupgext_ciphers( &context, &ct->algo,
|
||||
&ct->keylen, &ct->blocksize, &ct->contextsize,
|
||||
&ct->setkey, &ct->encrypt, &ct->decrypt)) ) {
|
||||
if( ct->blocksize != 8 && ct->blocksize != 16 ) {
|
||||
log_info("skipping cipher %d: unsupported blocksize\n", ct->algo);
|
||||
continue;
|
||||
}
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == ct->algo )
|
||||
break;
|
||||
if( cipher_table[i].name ) {
|
||||
log_info("skipping cipher %d: already loaded\n", ct->algo );
|
||||
continue;
|
||||
}
|
||||
/* put it into the table */
|
||||
if( g10_opt_verbose > 1 )
|
||||
log_info("loaded cipher %d (%s)\n", ct->algo, name);
|
||||
ct->name = name;
|
||||
ct_idx++;
|
||||
ct++;
|
||||
any = 1;
|
||||
/* check whether there are more available table slots */
|
||||
if( ct_idx >= TABLE_SIZE-1 ) {
|
||||
log_info("cipher table full; ignoring other extensions\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
enum_gnupgext_ciphers( &context, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL );
|
||||
return any;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Map a string to the cipher algo
|
||||
*/
|
||||
int
|
||||
string_to_cipher_algo( const char *string )
|
||||
{
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
/* kludge to alias RIJNDAEL to AES */
|
||||
if ( *string == 'R' || *string == 'r')
|
||||
{
|
||||
if (!ascii_strcasecmp (string, "RIJNDAEL"))
|
||||
string = "AES";
|
||||
else if (!ascii_strcasecmp (string, "RIJNDAEL192"))
|
||||
string = "AES192";
|
||||
else if (!ascii_strcasecmp (string, "RIJNDAEL256"))
|
||||
string = "AES256";
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
for(i=0; (s=cipher_table[i].name); i++ )
|
||||
{
|
||||
if( !ascii_strcasecmp( s, string ) )
|
||||
return cipher_table[i].algo;
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Map a cipher algo to a string
|
||||
*/
|
||||
const char *
|
||||
cipher_algo_to_string( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == algo )
|
||||
return cipher_table[i].name;
|
||||
} while( load_cipher_modules() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
disable_cipher_algo( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < DIM(disabled_algos); i++ ) {
|
||||
if( !disabled_algos[i] || disabled_algos[i] == algo ) {
|
||||
disabled_algos[i] = algo;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* fixme: we should use a linked list */
|
||||
log_fatal("can't disable cipher algo %d: table full\n", algo );
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return 0 if the cipher algo is available
|
||||
*/
|
||||
int
|
||||
check_cipher_algo( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == algo ) {
|
||||
for(i=0; i < DIM(disabled_algos); i++ ) {
|
||||
if( disabled_algos[i] == algo )
|
||||
return G10ERR_CIPHER_ALGO;
|
||||
}
|
||||
return 0; /* okay */
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
return G10ERR_CIPHER_ALGO;
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
cipher_get_keylen( int algo )
|
||||
{
|
||||
int i;
|
||||
unsigned len = 0;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ ) {
|
||||
if( cipher_table[i].algo == algo ) {
|
||||
len = cipher_table[i].keylen;
|
||||
if( !len )
|
||||
log_bug("cipher %d w/o key length\n", algo );
|
||||
return len;
|
||||
}
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
log_bug("cipher %d not found\n", algo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
cipher_get_blocksize( int algo )
|
||||
{
|
||||
int i;
|
||||
unsigned len = 0;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ ) {
|
||||
if( cipher_table[i].algo == algo ) {
|
||||
len = cipher_table[i].blocksize;
|
||||
if( !len )
|
||||
log_bug("cipher %d w/o blocksize\n", algo );
|
||||
return len;
|
||||
}
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
log_bug("cipher %d not found\n", algo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Open a cipher handle for use with algorithm ALGO, in mode MODE
|
||||
* and put it into secure memory if SECURE is true.
|
||||
*/
|
||||
CIPHER_HANDLE
|
||||
cipher_open( int algo, int mode, int secure )
|
||||
{
|
||||
CIPHER_HANDLE hd;
|
||||
int i;
|
||||
|
||||
fast_random_poll();
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == algo )
|
||||
break;
|
||||
} while( !cipher_table[i].name && load_cipher_modules() );
|
||||
if( !cipher_table[i].name ) {
|
||||
log_fatal("cipher_open: algorithm %d not available\n", algo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ? perform selftest here and mark this with a flag in cipher_table ? */
|
||||
|
||||
hd = secure ? m_alloc_secure_clear( sizeof *hd
|
||||
+ cipher_table[i].contextsize
|
||||
- sizeof(PROPERLY_ALIGNED_TYPE) )
|
||||
: m_alloc_clear( sizeof *hd + cipher_table[i].contextsize
|
||||
- sizeof(PROPERLY_ALIGNED_TYPE) );
|
||||
hd->algo = algo;
|
||||
hd->blocksize = cipher_table[i].blocksize;
|
||||
hd->setkey = cipher_table[i].setkey;
|
||||
hd->encrypt = cipher_table[i].encrypt;
|
||||
hd->decrypt = cipher_table[i].decrypt;
|
||||
|
||||
if( mode == CIPHER_MODE_AUTO_CFB ) {
|
||||
if( algo >= 100 )
|
||||
hd->mode = CIPHER_MODE_CFB;
|
||||
else
|
||||
hd->mode = CIPHER_MODE_PHILS_CFB;
|
||||
}
|
||||
else
|
||||
hd->mode = mode;
|
||||
|
||||
#ifdef IS_DEVELOPMENT_VERSION
|
||||
if( algo == CIPHER_ALGO_DUMMY )
|
||||
hd->mode = CIPHER_MODE_DUMMY;
|
||||
#endif
|
||||
|
||||
return hd;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cipher_close( CIPHER_HANDLE c )
|
||||
{
|
||||
m_free(c);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen )
|
||||
{
|
||||
return (*c->setkey)( &c->context.c, key, keylen );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen )
|
||||
{
|
||||
memset( c->iv, 0, c->blocksize );
|
||||
if( iv ) {
|
||||
if( ivlen != c->blocksize )
|
||||
log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
|
||||
ivlen, (unsigned)c->blocksize );
|
||||
if( ivlen > c->blocksize )
|
||||
ivlen = c->blocksize;
|
||||
memcpy( c->iv, iv, ivlen );
|
||||
}
|
||||
c->unused = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
(*c->encrypt)( &c->context.c, outbuf, inbuf );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
(*c->decrypt)( &c->context.c, outbuf, inbuf );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cbc_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned int n;
|
||||
byte *ivp;
|
||||
int i;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
/* fixme: the xor should works on words and not on
|
||||
* bytes. Maybe it is a good idea to enhance the cipher backend
|
||||
* API to allow for CBC handling in the backend */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
outbuf[i] = inbuf[i] ^ *ivp++;
|
||||
(*c->encrypt)( &c->context.c, outbuf, outbuf );
|
||||
memcpy(c->iv, outbuf, blocksize );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cbc_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned int n;
|
||||
byte *ivp;
|
||||
int i;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
/* because outbuf and inbuf might be the same, we have
|
||||
* to save the original ciphertext block. We use lastiv
|
||||
* for this here because it is not used otherwise */
|
||||
memcpy(c->lastiv, inbuf, blocksize );
|
||||
(*c->decrypt)( &c->context.c, outbuf, inbuf );
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
outbuf[i] ^= *ivp++;
|
||||
memcpy(c->iv, c->lastiv, blocksize );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
byte *ivp;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
if( nbytes <= c->unused ) {
|
||||
/* short enough to be encoded by the remaining XOR mask */
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
return;
|
||||
}
|
||||
|
||||
if( c->unused ) {
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
nbytes -= c->unused;
|
||||
for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
}
|
||||
|
||||
/* now we can process complete blocks */
|
||||
while( nbytes >= blocksize ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
nbytes -= blocksize;
|
||||
}
|
||||
if( nbytes ) { /* process the remaining bytes */
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
c->unused = blocksize;
|
||||
/* and apply the xor */
|
||||
c->unused -= nbytes;
|
||||
for(ivp=c->iv; nbytes; nbytes-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
byte *ivp;
|
||||
ulong temp;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
if( nbytes <= c->unused ) {
|
||||
/* short enough to be encoded by the remaining XOR mask */
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( c->unused ) {
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
nbytes -= c->unused;
|
||||
for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* now we can process complete blocks */
|
||||
while( nbytes >= blocksize ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
nbytes -= blocksize;
|
||||
}
|
||||
if( nbytes ) { /* process the remaining bytes */
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
c->unused = blocksize;
|
||||
/* and apply the xor */
|
||||
c->unused -= nbytes;
|
||||
for(ivp=c->iv; nbytes; nbytes-- ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Encrypt INBUF to OUTBUF with the mode selected at open.
|
||||
* inbuf and outbuf may overlap or be the same.
|
||||
* Depending on the mode some some contraints apply to NBYTES.
|
||||
*/
|
||||
void
|
||||
cipher_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
switch( c->mode ) {
|
||||
case CIPHER_MODE_ECB:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CBC:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CFB:
|
||||
case CIPHER_MODE_PHILS_CFB:
|
||||
do_cfb_encrypt(c, outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#ifdef IS_DEVELOPMENT_VERSION
|
||||
case CIPHER_MODE_DUMMY:
|
||||
if( inbuf != outbuf )
|
||||
memmove( outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#endif
|
||||
default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Decrypt INBUF to OUTBUF with the mode selected at open.
|
||||
* inbuf and outbuf may overlap or be the same.
|
||||
* Depending on the mode some some contraints apply to NBYTES.
|
||||
*/
|
||||
void
|
||||
cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
switch( c->mode ) {
|
||||
case CIPHER_MODE_ECB:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CBC:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CFB:
|
||||
case CIPHER_MODE_PHILS_CFB:
|
||||
do_cfb_decrypt(c, outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#ifdef IS_DEVELOPMENT_VERSION
|
||||
case CIPHER_MODE_DUMMY:
|
||||
if( inbuf != outbuf )
|
||||
memmove( outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#endif
|
||||
default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Used for PGP's somewhat strange CFB mode. Only works if
|
||||
* the handle is in PHILS_CFB mode
|
||||
*/
|
||||
void
|
||||
cipher_sync( CIPHER_HANDLE c )
|
||||
{
|
||||
if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) {
|
||||
memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused );
|
||||
memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused);
|
||||
c->unused = 0;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,34 @@
|
|||
/* des.h
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_DES_H
|
||||
#define G10_DES_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
const char *
|
||||
des_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
#endif /*G10_DES_H*/
|
|
@ -0,0 +1,483 @@
|
|||
/* dsa.c - DSA signature algorithm
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "dsa.h"
|
||||
|
||||
typedef struct {
|
||||
MPI p; /* prime */
|
||||
MPI q; /* group order */
|
||||
MPI g; /* group generator */
|
||||
MPI y; /* g^x mod p */
|
||||
} DSA_public_key;
|
||||
|
||||
|
||||
typedef struct {
|
||||
MPI p; /* prime */
|
||||
MPI q; /* group order */
|
||||
MPI g; /* group generator */
|
||||
MPI y; /* g^x mod p */
|
||||
MPI x; /* secret exponent */
|
||||
} DSA_secret_key;
|
||||
|
||||
|
||||
static MPI gen_k( MPI q );
|
||||
static void test_keys( DSA_secret_key *sk, unsigned qbits );
|
||||
static int check_secret_key( DSA_secret_key *sk );
|
||||
static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
|
||||
static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
|
||||
static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
|
||||
|
||||
|
||||
static void (*progress_cb) ( void *, int );
|
||||
static void *progress_cb_data;
|
||||
|
||||
void
|
||||
register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data )
|
||||
{
|
||||
progress_cb = cb;
|
||||
progress_cb_data = cb_data;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
progress( int c )
|
||||
{
|
||||
if ( progress_cb )
|
||||
progress_cb ( progress_cb_data, c );
|
||||
else
|
||||
fputc( c, stderr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a random secret exponent k less than q
|
||||
*/
|
||||
static MPI
|
||||
gen_k( MPI q )
|
||||
{
|
||||
MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
|
||||
unsigned int nbits = mpi_get_nbits(q);
|
||||
unsigned int nbytes = (nbits+7)/8;
|
||||
char *rndbuf = NULL;
|
||||
|
||||
if( DBG_CIPHER )
|
||||
log_debug("choosing a random k ");
|
||||
for(;;) {
|
||||
if( DBG_CIPHER )
|
||||
progress('.');
|
||||
|
||||
if( !rndbuf || nbits < 32 ) {
|
||||
m_free(rndbuf);
|
||||
rndbuf = get_random_bits( nbits, 1, 1 );
|
||||
}
|
||||
else { /* change only some of the higher bits */
|
||||
/* we could imporove this by directly requesting more memory
|
||||
* at the first call to get_random_bits() and use this the here
|
||||
* maybe it is easier to do this directly in random.c */
|
||||
char *pp = get_random_bits( 32, 1, 1 );
|
||||
memcpy( rndbuf,pp, 4 );
|
||||
m_free(pp);
|
||||
}
|
||||
mpi_set_buffer( k, rndbuf, nbytes, 0 );
|
||||
if( mpi_test_bit( k, nbits-1 ) )
|
||||
mpi_set_highbit( k, nbits-1 );
|
||||
else {
|
||||
mpi_set_highbit( k, nbits-1 );
|
||||
mpi_clear_bit( k, nbits-1 );
|
||||
}
|
||||
|
||||
if( !(mpi_cmp( k, q ) < 0) ) { /* check: k < q */
|
||||
if( DBG_CIPHER )
|
||||
progress('+');
|
||||
continue; /* no */
|
||||
}
|
||||
if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
|
||||
if( DBG_CIPHER )
|
||||
progress('-');
|
||||
continue; /* no */
|
||||
}
|
||||
break; /* okay */
|
||||
}
|
||||
m_free(rndbuf);
|
||||
if( DBG_CIPHER )
|
||||
progress('\n');
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_keys( DSA_secret_key *sk, unsigned qbits )
|
||||
{
|
||||
DSA_public_key pk;
|
||||
MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||
MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||
MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||
|
||||
pk.p = sk->p;
|
||||
pk.q = sk->q;
|
||||
pk.g = sk->g;
|
||||
pk.y = sk->y;
|
||||
/*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
|
||||
{ char *p = get_random_bits( qbits, 0, 0 );
|
||||
mpi_set_buffer( test, p, (qbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
sign( out1_a, out1_b, test, sk );
|
||||
if( !verify( out1_a, out1_b, test, &pk ) )
|
||||
log_fatal("DSA:: sign, verify failed\n");
|
||||
|
||||
mpi_free( test );
|
||||
mpi_free( out1_a );
|
||||
mpi_free( out1_b );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a DSA key pair with a key of size NBITS
|
||||
* Returns: 2 structures filled with all needed values
|
||||
* and an array with the n-1 factors of (p-1)
|
||||
*/
|
||||
static void
|
||||
generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
|
||||
{
|
||||
MPI p; /* the prime */
|
||||
MPI q; /* the 160 bit prime factor */
|
||||
MPI g; /* the generator */
|
||||
MPI y; /* g^x mod p */
|
||||
MPI x; /* the secret exponent */
|
||||
MPI h, e; /* helper */
|
||||
unsigned qbits;
|
||||
byte *rndbuf;
|
||||
|
||||
assert( nbits >= 512 && nbits <= 1024 );
|
||||
|
||||
qbits = 160;
|
||||
p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
|
||||
/* get q out of factors */
|
||||
q = mpi_copy((*ret_factors)[0]);
|
||||
if( mpi_get_nbits(q) != qbits )
|
||||
BUG();
|
||||
|
||||
/* find a generator g (h and e are helpers)*/
|
||||
/* e = (p-1)/q */
|
||||
e = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
mpi_sub_ui( e, p, 1 );
|
||||
mpi_fdiv_q( e, e, q );
|
||||
g = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
|
||||
do {
|
||||
mpi_add_ui( h, h, 1 );
|
||||
/* g = h^e mod p */
|
||||
mpi_powm( g, h, e, p );
|
||||
} while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */
|
||||
|
||||
/* select a random number which has these properties:
|
||||
* 0 < x < q-1
|
||||
* This must be a very good random number because this
|
||||
* is the secret part. */
|
||||
if( DBG_CIPHER )
|
||||
log_debug("choosing a random x ");
|
||||
assert( qbits >= 160 );
|
||||
x = mpi_alloc_secure( mpi_get_nlimbs(q) );
|
||||
mpi_sub_ui( h, q, 1 ); /* put q-1 into h */
|
||||
rndbuf = NULL;
|
||||
do {
|
||||
if( DBG_CIPHER )
|
||||
progress('.');
|
||||
if( !rndbuf )
|
||||
rndbuf = get_random_bits( qbits, 2, 1 );
|
||||
else { /* change only some of the higher bits (= 2 bytes)*/
|
||||
char *r = get_random_bits( 16, 2, 1 );
|
||||
memcpy(rndbuf, r, 16/8 );
|
||||
m_free(r);
|
||||
}
|
||||
mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
|
||||
mpi_clear_highbit( x, qbits+1 );
|
||||
} while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
|
||||
m_free(rndbuf);
|
||||
mpi_free( e );
|
||||
mpi_free( h );
|
||||
|
||||
/* y = g^x mod p */
|
||||
y = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
mpi_powm( y, g, x, p );
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
progress('\n');
|
||||
log_mpidump("dsa p= ", p );
|
||||
log_mpidump("dsa q= ", q );
|
||||
log_mpidump("dsa g= ", g );
|
||||
log_mpidump("dsa y= ", y );
|
||||
log_mpidump("dsa x= ", x );
|
||||
}
|
||||
|
||||
/* copy the stuff to the key structures */
|
||||
sk->p = p;
|
||||
sk->q = q;
|
||||
sk->g = g;
|
||||
sk->y = y;
|
||||
sk->x = x;
|
||||
|
||||
/* now we can test our keys (this should never fail!) */
|
||||
test_keys( sk, qbits );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Test whether the secret key is valid.
|
||||
* Returns: if this is a valid key.
|
||||
*/
|
||||
static int
|
||||
check_secret_key( DSA_secret_key *sk )
|
||||
{
|
||||
int rc;
|
||||
MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
|
||||
|
||||
mpi_powm( y, sk->g, sk->x, sk->p );
|
||||
rc = !mpi_cmp( y, sk->y );
|
||||
mpi_free( y );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Make a DSA signature from HASH and put it into r and s.
|
||||
*
|
||||
* Without generating the k this function runs in
|
||||
* about 26ms on a 300 Mhz Mobile Pentium
|
||||
*/
|
||||
|
||||
static void
|
||||
sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
|
||||
{
|
||||
MPI k;
|
||||
MPI kinv;
|
||||
MPI tmp;
|
||||
|
||||
/* select a random k with 0 < k < q */
|
||||
k = gen_k( skey->q );
|
||||
|
||||
/* r = (a^k mod p) mod q */
|
||||
mpi_powm( r, skey->g, k, skey->p );
|
||||
mpi_fdiv_r( r, r, skey->q );
|
||||
|
||||
/* kinv = k^(-1) mod q */
|
||||
kinv = mpi_alloc( mpi_get_nlimbs(k) );
|
||||
mpi_invm(kinv, k, skey->q );
|
||||
|
||||
/* s = (kinv * ( hash + x * r)) mod q */
|
||||
tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
|
||||
mpi_mul( tmp, skey->x, r );
|
||||
mpi_add( tmp, tmp, hash );
|
||||
mpi_mulm( s , kinv, tmp, skey->q );
|
||||
|
||||
mpi_free(k);
|
||||
mpi_free(kinv);
|
||||
mpi_free(tmp);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Returns true if the signature composed from R and S is valid.
|
||||
*
|
||||
* Without the checks this function runs in
|
||||
* about 31ms on a 300 Mhz Mobile Pentium
|
||||
*/
|
||||
static int
|
||||
verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
|
||||
{
|
||||
int rc;
|
||||
MPI w, u1, u2, v;
|
||||
MPI base[3];
|
||||
MPI exp[3];
|
||||
|
||||
|
||||
if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
|
||||
return 0; /* assertion 0 < r < q failed */
|
||||
if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
|
||||
return 0; /* assertion 0 < s < q failed */
|
||||
|
||||
w = mpi_alloc( mpi_get_nlimbs(pkey->q) );
|
||||
u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
|
||||
u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
|
||||
v = mpi_alloc( mpi_get_nlimbs(pkey->p) );
|
||||
|
||||
/* w = s^(-1) mod q */
|
||||
mpi_invm( w, s, pkey->q );
|
||||
|
||||
/* u1 = (hash * w) mod q */
|
||||
mpi_mulm( u1, hash, w, pkey->q );
|
||||
|
||||
/* u2 = r * w mod q */
|
||||
mpi_mulm( u2, r, w, pkey->q );
|
||||
|
||||
/* v = g^u1 * y^u2 mod p mod q */
|
||||
base[0] = pkey->g; exp[0] = u1;
|
||||
base[1] = pkey->y; exp[1] = u2;
|
||||
base[2] = NULL; exp[2] = NULL;
|
||||
mpi_mulpowm( v, base, exp, pkey->p );
|
||||
mpi_fdiv_r( v, v, pkey->q );
|
||||
|
||||
rc = !mpi_cmp( v, r );
|
||||
|
||||
mpi_free(w);
|
||||
mpi_free(u1);
|
||||
mpi_free(u2);
|
||||
mpi_free(v);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
************** interface ******************
|
||||
*********************************************/
|
||||
|
||||
int
|
||||
dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
{
|
||||
DSA_secret_key sk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
generate( &sk, nbits, retfactors );
|
||||
skey[0] = sk.p;
|
||||
skey[1] = sk.q;
|
||||
skey[2] = sk.g;
|
||||
skey[3] = sk.y;
|
||||
skey[4] = sk.x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dsa_check_secret_key( int algo, MPI *skey )
|
||||
{
|
||||
DSA_secret_key sk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.q = skey[1];
|
||||
sk.g = skey[2];
|
||||
sk.y = skey[3];
|
||||
sk.x = skey[4];
|
||||
if( !check_secret_key( &sk ) )
|
||||
return G10ERR_BAD_SECKEY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
{
|
||||
DSA_secret_key sk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.q = skey[1];
|
||||
sk.g = skey[2];
|
||||
sk.y = skey[3];
|
||||
sk.x = skey[4];
|
||||
resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
|
||||
resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
|
||||
sign( resarr[0], resarr[1], data, &sk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev )
|
||||
{
|
||||
DSA_public_key pk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data[0] || !data[1] || !hash
|
||||
|| !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
pk.p = pkey[0];
|
||||
pk.q = pkey[1];
|
||||
pk.g = pkey[2];
|
||||
pk.y = pkey[3];
|
||||
if( !verify( data[0], data[1], hash, &pk ) )
|
||||
return G10ERR_BAD_SIGN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
dsa_get_nbits( int algo, MPI *pkey )
|
||||
{
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return 0;
|
||||
return mpi_get_nbits( pkey[0] );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
* Usage: Bit 0 set : allows signing
|
||||
* 1 set : allows encryption
|
||||
*/
|
||||
const char *
|
||||
dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
|
||||
int *use )
|
||||
{
|
||||
*npkey = 4;
|
||||
*nskey = 5;
|
||||
*nenc = 0;
|
||||
*nsig = 2;
|
||||
|
||||
switch( algo ) {
|
||||
case PUBKEY_ALGO_DSA: *use = PUBKEY_USAGE_SIG; return "DSA";
|
||||
default: *use = 0; return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/* dsa.h - DSA signature algorithm
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_DSA_H
|
||||
#define G10_DSA_H
|
||||
|
||||
int dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
|
||||
int dsa_check_secret_key( int algo, MPI *skey );
|
||||
int dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
|
||||
int dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev );
|
||||
unsigned dsa_get_nbits( int algo, MPI *pkey );
|
||||
const char *dsa_get_info( int algo, int *npkey, int *nskey,
|
||||
int *nenc, int *nsig, int *use );
|
||||
|
||||
#endif /*G10_DSA_H*/
|
|
@ -0,0 +1,681 @@
|
|||
/* dynload.c - load cipher extensions
|
||||
* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
#include <dlfcn.h>
|
||||
#elif defined(HAVE_DLD_DLD_LINK)
|
||||
#include <dld.h>
|
||||
#elif defined(HAVE_DL_SHL_LOAD)
|
||||
#include <dl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "util.h"
|
||||
#include "cipher.h"
|
||||
#include "dynload.h"
|
||||
|
||||
#ifdef WITH_SYMBOL_UNDERSCORE
|
||||
#define SYMBOL_VERSION "_gnupgext_version"
|
||||
#define SYMBOL_ENUM "_gnupgext_enum_func"
|
||||
#else
|
||||
#define SYMBOL_VERSION "gnupgext_version"
|
||||
#define SYMBOL_ENUM "gnupgext_enum_func"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef RTLD_NOW
|
||||
#define RTLD_NOW 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DL_SHL_LOAD /* HPUX has shl_load instead of dlopen */
|
||||
#define HAVE_DL_DLOPEN
|
||||
#define dlopen(PATHNAME,MODE) \
|
||||
((void *) shl_load(PATHNAME, DYNAMIC_PATH | \
|
||||
(((MODE) & RTLD_NOW) ? BIND_IMMEDIATE : BIND_DEFERRED), 0L))
|
||||
#define dlclose(HANDLE) shl_unload((shl_t) (HANDLE))
|
||||
#define dlerror() (errno == 0 ? NULL : strerror(errno))
|
||||
|
||||
static void *
|
||||
dlsym(void *handle, char *name)
|
||||
{
|
||||
void *addr;
|
||||
if (shl_findsym((shl_t *)&handle,name,(short)TYPE_UNDEFINED,&addr) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
#endif /*HAVE_DL_SHL_LOAD*/
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define HAVE_DL_DLOPEN
|
||||
#define USE_DYNAMIC_LINKING
|
||||
|
||||
static int last_error = 0;
|
||||
|
||||
void*
|
||||
dlopen(const char *pathname, int mode)
|
||||
{
|
||||
void *h = LoadLibrary( pathname );
|
||||
if (!h) {
|
||||
log_error( "LoadLibrary failed ec=%d\n", (int)GetLastError() );
|
||||
last_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
int
|
||||
dlclose( void *handle )
|
||||
{
|
||||
last_error = 0;
|
||||
return FreeLibrary( handle );
|
||||
}
|
||||
|
||||
char*
|
||||
dlerror(void)
|
||||
{
|
||||
static char dlerrstr[10];
|
||||
if (last_error) {
|
||||
sprintf(dlerrstr, "%d", (int)GetLastError() );
|
||||
return dlerrstr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
dlsym( void *handle, const char *name )
|
||||
{
|
||||
void *h = GetProcAddress( handle, name );
|
||||
if (!h) {
|
||||
log_error( "GetProcAddress failed ec=%d\n", (int)GetLastError() );
|
||||
last_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
#endif /*__MINGW32__*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct ext_list {
|
||||
struct ext_list *next;
|
||||
int internal;
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
void *handle; /* handle from dlopen() */
|
||||
#else
|
||||
int handle; /* if the function has been loaded, this is true */
|
||||
#endif
|
||||
int failed; /* already tried but failed */
|
||||
void * (*enumfunc)(int, int*, int*, int*);
|
||||
char *hintstr; /* pointer into name */
|
||||
char name[1];
|
||||
} *EXTLIST;
|
||||
|
||||
static EXTLIST extensions;
|
||||
|
||||
typedef struct {
|
||||
EXTLIST r;
|
||||
int seq1;
|
||||
int seq2;
|
||||
void *sym;
|
||||
int reqalgo;
|
||||
} ENUMCONTEXT;
|
||||
|
||||
|
||||
#ifdef HAVE_DLD_DLD_LINK
|
||||
static char *mainpgm_path;
|
||||
static int did_dld_init;
|
||||
static int dld_available;
|
||||
#endif
|
||||
|
||||
|
||||
/****************
|
||||
* Register an extension module. The last registered module will
|
||||
* be loaded first. A name may have a list of classes
|
||||
* appended; e.g:
|
||||
* mymodule.so(1:17,3:20,3:109)
|
||||
* means that this module provides digest algorithm 17 and public key
|
||||
* algorithms 20 and 109. This is only a hint but if it is there the
|
||||
* loader may decide to only load a module which claims to have a
|
||||
* requested algorithm.
|
||||
*
|
||||
* mainpgm is the path to the program which wants to load a module
|
||||
* it is only used in some environments.
|
||||
*/
|
||||
void
|
||||
register_cipher_extension( const char *mainpgm, const char *fname )
|
||||
{
|
||||
EXTLIST r, el, intex;
|
||||
char *p, *pe;
|
||||
|
||||
#ifdef HAVE_DLD_DLD_LINK
|
||||
if( !mainpgm_path && mainpgm && *mainpgm )
|
||||
mainpgm_path = m_strdup(mainpgm);
|
||||
#endif
|
||||
if( *fname != DIRSEP_C ) { /* do tilde expansion etc */
|
||||
char *tmp;
|
||||
|
||||
if( strchr(fname, DIRSEP_C) )
|
||||
tmp = make_filename(fname, NULL);
|
||||
else
|
||||
tmp = make_filename(GNUPG_LIBDIR, fname, NULL);
|
||||
el = m_alloc_clear( sizeof *el + strlen(tmp) );
|
||||
strcpy(el->name, tmp );
|
||||
m_free(tmp);
|
||||
}
|
||||
else {
|
||||
el = m_alloc_clear( sizeof *el + strlen(fname) );
|
||||
strcpy(el->name, fname );
|
||||
}
|
||||
/* check whether we have a class hint */
|
||||
if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) {
|
||||
*p = *pe = 0;
|
||||
el->hintstr = p+1;
|
||||
}
|
||||
else
|
||||
el->hintstr = NULL;
|
||||
|
||||
/* check that it is not already registered */
|
||||
intex = NULL;
|
||||
for(r = extensions; r; r = r->next ) {
|
||||
if( !compare_filenames(r->name, el->name) ) {
|
||||
log_info("extension `%s' already registered\n", el->name );
|
||||
m_free(el);
|
||||
return;
|
||||
}
|
||||
else if( r->internal )
|
||||
intex = r;
|
||||
}
|
||||
/* and register */
|
||||
/* we put them after the internal extension modules */
|
||||
/* this is so that the external modules do not get loaded */
|
||||
/* as soon as the internal modules are requested */
|
||||
if( intex ) {
|
||||
el->next = intex->next;
|
||||
intex->next = el;
|
||||
}
|
||||
else {
|
||||
el->next = extensions;
|
||||
extensions = el;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
register_internal_cipher_extension(
|
||||
const char *module_id,
|
||||
void * (*enumfunc)(int, int*, int*, int*)
|
||||
)
|
||||
{
|
||||
EXTLIST r, el;
|
||||
|
||||
el = m_alloc_clear( sizeof *el + strlen(module_id) );
|
||||
strcpy(el->name, module_id );
|
||||
el->internal = 1;
|
||||
|
||||
/* check that it is not already registered */
|
||||
for(r = extensions; r; r = r->next ) {
|
||||
if( !compare_filenames(r->name, el->name) ) {
|
||||
log_info("extension `%s' already registered\n", el->name );
|
||||
m_free(el);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* and register */
|
||||
el->enumfunc = enumfunc;
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
el->handle = (void*)1;
|
||||
#else
|
||||
el->handle = 1;
|
||||
#endif
|
||||
el->next = extensions;
|
||||
extensions = el;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
load_extension( EXTLIST el )
|
||||
{
|
||||
#ifdef USE_DYNAMIC_LINKING
|
||||
char **name;
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
const char *err;
|
||||
int seq = 0;
|
||||
int class, vers;
|
||||
void *sym;
|
||||
#else
|
||||
unsigned long addr;
|
||||
int rc;
|
||||
#endif
|
||||
|
||||
#ifndef __MINGW32__
|
||||
/* make sure we are not setuid */
|
||||
if( getuid() != geteuid() )
|
||||
log_bug("trying to load an extension while still setuid\n");
|
||||
#endif
|
||||
|
||||
/* now that we are not setuid anymore, we can safely load modules */
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
el->handle = dlopen(el->name, RTLD_NOW);
|
||||
if( !el->handle ) {
|
||||
log_error("%s: error loading extension: %s\n", el->name, dlerror() );
|
||||
goto failure;
|
||||
}
|
||||
name = (char**)dlsym(el->handle, SYMBOL_VERSION);
|
||||
if( (err=dlerror()) ) {
|
||||
log_error("%s: not a gnupg extension: %s\n", el->name, err );
|
||||
goto failure;
|
||||
}
|
||||
#else /* have dld */
|
||||
if( !did_dld_init ) {
|
||||
did_dld_init = 1;
|
||||
if( !mainpgm_path )
|
||||
log_error("DLD is not correctly initialized\n");
|
||||
else {
|
||||
rc = dld_init( dld_find_executable(mainpgm_path) );
|
||||
if( rc )
|
||||
log_error("DLD init failed: %s\n", dld_strerror(rc) );
|
||||
else
|
||||
dld_available = 1;
|
||||
}
|
||||
}
|
||||
if( !dld_available ) {
|
||||
log_error("%s: DLD not available\n", el->name );
|
||||
goto failure;
|
||||
}
|
||||
|
||||
rc = dld_link( el->name );
|
||||
if( rc ) {
|
||||
log_error("%s: error loading extension: %s\n",
|
||||
el->name, dld_strerror(rc) );
|
||||
goto failure;
|
||||
}
|
||||
addr = dld_get_symbol(SYMBOL_VERSION);
|
||||
if( !addr ) {
|
||||
log_error("%s: not a gnupg extension: %s\n",
|
||||
el->name, dld_strerror(dld_errno) );
|
||||
goto failure;
|
||||
}
|
||||
name = (char**)addr;
|
||||
#endif
|
||||
|
||||
if( g10_opt_verbose > 1 )
|
||||
log_info("%s: %s%s%s%s\n", el->name, *name,
|
||||
el->hintstr? " (":"",
|
||||
el->hintstr? el->hintstr:"",
|
||||
el->hintstr? ")":"");
|
||||
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
sym = dlsym(el->handle, SYMBOL_ENUM);
|
||||
if( (err=dlerror()) ) {
|
||||
log_error("%s: invalid gnupg extension: %s\n", el->name, err );
|
||||
goto failure;
|
||||
}
|
||||
el->enumfunc = (void *(*)(int,int*,int*,int*))sym;
|
||||
#else /* dld */
|
||||
addr = dld_get_func(SYMBOL_ENUM);
|
||||
if( !addr ) {
|
||||
log_error("%s: invalid gnupg extension: %s\n",
|
||||
el->name, dld_strerror(dld_errno) );
|
||||
goto failure;
|
||||
}
|
||||
rc = dld_function_executable_p(SYMBOL_ENUM);
|
||||
if( rc ) {
|
||||
log_error("%s: extension function is not executable: %s\n",
|
||||
el->name, dld_strerror(rc) );
|
||||
goto failure;
|
||||
}
|
||||
el->enumfunc = (void *(*)(int,int*,int*,int*))addr;
|
||||
el->handle = 1; /* mark as usable */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
if( g10_opt_verbose > 2 ) {
|
||||
/* list the contents of the module */
|
||||
while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) {
|
||||
if( vers != 1 ) {
|
||||
log_info("%s: ignoring func with version %d\n",el->name,vers);
|
||||
continue;
|
||||
}
|
||||
switch( class ) {
|
||||
case 11:
|
||||
case 21:
|
||||
case 31:
|
||||
log_info("%s: provides %s algorithm %d\n", el->name,
|
||||
class == 11? "md" :
|
||||
class == 21? "cipher" : "pubkey",
|
||||
*(int*)sym);
|
||||
break;
|
||||
default:
|
||||
/*log_debug("%s: skipping class %d\n", el->name, class);*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
#ifdef HAVE_DL_DLOPEN
|
||||
if( el->handle ) {
|
||||
dlclose(el->handle);
|
||||
el->handle = NULL;
|
||||
}
|
||||
#endif
|
||||
el->failed = 1;
|
||||
#endif /*USE_DYNAMIC_LINKING*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
typedef
|
||||
const char *(*DIGESTS_CAST)(int, size_t*,byte**, int*, int*,
|
||||
void (**)(void*),
|
||||
void (**)(void*,byte*,size_t),
|
||||
void (**)(void*),byte *(**)(void*));
|
||||
#endif /* __riscos__ */
|
||||
|
||||
int
|
||||
enum_gnupgext_digests( void **enum_context,
|
||||
int *algo,
|
||||
const char *(**r_get_info)( int, size_t*,byte**, int*, int*,
|
||||
void (**)(void*),
|
||||
void (**)(void*,byte*,size_t),
|
||||
void (**)(void*),byte *(**)(void*)) )
|
||||
{
|
||||
EXTLIST r;
|
||||
ENUMCONTEXT *ctx;
|
||||
|
||||
if( !*enum_context ) { /* init context */
|
||||
ctx = m_alloc_clear( sizeof( *ctx ) );
|
||||
ctx->r = extensions;
|
||||
ctx->reqalgo = *algo;
|
||||
*enum_context = ctx;
|
||||
}
|
||||
else if( !algo ) { /* release the context */
|
||||
m_free(*enum_context);
|
||||
*enum_context = NULL;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
ctx = *enum_context;
|
||||
|
||||
for( r = ctx->r; r; r = r->next ) {
|
||||
int class, vers;
|
||||
|
||||
if( r->failed )
|
||||
continue;
|
||||
if( !r->handle && load_extension(r) )
|
||||
continue;
|
||||
/* get a digest info function */
|
||||
if( ctx->sym )
|
||||
goto inner_loop;
|
||||
while( (ctx->sym = (*r->enumfunc)(10, &ctx->seq1, &class, &vers)) ) {
|
||||
void *sym;
|
||||
/* must check class because enumfunc may be wrong coded */
|
||||
if( vers != 1 || class != 10 )
|
||||
continue;
|
||||
inner_loop:
|
||||
#ifndef __riscos__
|
||||
*r_get_info = ctx->sym;
|
||||
#else /* __riscos__ */
|
||||
*r_get_info = (DIGESTS_CAST) ctx->sym;
|
||||
#endif /* __riscos__ */
|
||||
while( (sym = (*r->enumfunc)(11, &ctx->seq2, &class, &vers)) ) {
|
||||
if( vers != 1 || class != 11 )
|
||||
continue;
|
||||
*algo = *(int*)sym;
|
||||
ctx->r = r;
|
||||
return 1;
|
||||
}
|
||||
ctx->seq2 = 0;
|
||||
}
|
||||
ctx->seq1 = 0;
|
||||
}
|
||||
ctx->r = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
typedef
|
||||
const char *(*CIPHERS_CAST)(int, size_t*, size_t*, size_t*,
|
||||
int (**)( void *, byte *, unsigned),
|
||||
void (**)( void *, byte *, byte *),
|
||||
void (**)( void *, byte *, byte *));
|
||||
#endif /* __riscos__ */
|
||||
|
||||
const char *
|
||||
enum_gnupgext_ciphers( void **enum_context, int *algo,
|
||||
size_t *keylen, size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
)
|
||||
{
|
||||
EXTLIST r;
|
||||
ENUMCONTEXT *ctx;
|
||||
const char * (*finfo)(int, size_t*, size_t*, size_t*,
|
||||
int (**)( void *, byte *, unsigned),
|
||||
void (**)( void *, byte *, byte *),
|
||||
void (**)( void *, byte *, byte *));
|
||||
|
||||
if( !*enum_context ) { /* init context */
|
||||
ctx = m_alloc_clear( sizeof( *ctx ) );
|
||||
ctx->r = extensions;
|
||||
*enum_context = ctx;
|
||||
}
|
||||
else if( !algo ) { /* release the context */
|
||||
m_free(*enum_context);
|
||||
*enum_context = NULL;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
ctx = *enum_context;
|
||||
|
||||
for( r = ctx->r; r; r = r->next ) {
|
||||
int class, vers;
|
||||
|
||||
if( r->failed )
|
||||
continue;
|
||||
if( !r->handle && load_extension(r) )
|
||||
continue;
|
||||
/* get a cipher info function */
|
||||
if( ctx->sym )
|
||||
goto inner_loop;
|
||||
while( (ctx->sym = (*r->enumfunc)(20, &ctx->seq1, &class, &vers)) ) {
|
||||
void *sym;
|
||||
/* must check class because enumfunc may be wrong coded */
|
||||
if( vers != 1 || class != 20 )
|
||||
continue;
|
||||
inner_loop:
|
||||
#ifndef __riscos__
|
||||
finfo = ctx->sym;
|
||||
#else /* __riscos__ */
|
||||
finfo = (CIPHERS_CAST) ctx->sym;
|
||||
#endif /* __riscos__ */
|
||||
while( (sym = (*r->enumfunc)(21, &ctx->seq2, &class, &vers)) ) {
|
||||
const char *algname;
|
||||
if( vers != 1 || class != 21 )
|
||||
continue;
|
||||
*algo = *(int*)sym;
|
||||
algname = (*finfo)( *algo, keylen, blocksize, contextsize,
|
||||
setkeyf, encryptf, decryptf );
|
||||
if( algname ) {
|
||||
ctx->r = r;
|
||||
return algname;
|
||||
}
|
||||
}
|
||||
ctx->seq2 = 0;
|
||||
}
|
||||
ctx->seq1 = 0;
|
||||
}
|
||||
ctx->r = r;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
typedef
|
||||
const char *(*PUBKEYS_CAST)(int, int *, int *, int *, int *, int *,
|
||||
int (**)(int, unsigned, MPI *, MPI **),
|
||||
int (**)(int, MPI *),
|
||||
int (**)(int, MPI *, MPI , MPI *),
|
||||
int (**)(int, MPI *, MPI *, MPI *),
|
||||
int (**)(int, MPI *, MPI , MPI *),
|
||||
int (**)(int, MPI , MPI *, MPI *,
|
||||
int (*)(void*,MPI), void *),
|
||||
unsigned (**)( int , MPI *));
|
||||
#endif /* __riscos__ */
|
||||
|
||||
const char *
|
||||
enum_gnupgext_pubkeys( void **enum_context, int *algo,
|
||||
int *npkey, int *nskey, int *nenc, int *nsig, int *use,
|
||||
int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
|
||||
int (**check_secret_key)( int algo, MPI *skey ),
|
||||
int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ),
|
||||
int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ),
|
||||
int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ),
|
||||
int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev ),
|
||||
unsigned (**get_nbits)( int algo, MPI *pkey ) )
|
||||
{
|
||||
EXTLIST r;
|
||||
ENUMCONTEXT *ctx;
|
||||
const char * (*finfo)( int, int *, int *, int *, int *, int *,
|
||||
int (**)( int, unsigned, MPI *, MPI **),
|
||||
int (**)( int, MPI * ),
|
||||
int (**)( int, MPI *, MPI , MPI * ),
|
||||
int (**)( int, MPI *, MPI *, MPI * ),
|
||||
int (**)( int, MPI *, MPI , MPI * ),
|
||||
int (**)( int, MPI , MPI *, MPI *,
|
||||
int (*)(void*,MPI), void *),
|
||||
unsigned (**)( int , MPI * ) );
|
||||
|
||||
if( !*enum_context ) { /* init context */
|
||||
ctx = m_alloc_clear( sizeof( *ctx ) );
|
||||
ctx->r = extensions;
|
||||
*enum_context = ctx;
|
||||
}
|
||||
else if( !algo ) { /* release the context */
|
||||
m_free(*enum_context);
|
||||
*enum_context = NULL;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
ctx = *enum_context;
|
||||
|
||||
for( r = ctx->r; r; r = r->next ) {
|
||||
int class, vers;
|
||||
|
||||
if( r->failed )
|
||||
continue;
|
||||
if( !r->handle && load_extension(r) )
|
||||
continue;
|
||||
/* get a pubkey info function */
|
||||
if( ctx->sym )
|
||||
goto inner_loop;
|
||||
while( (ctx->sym = (*r->enumfunc)(30, &ctx->seq1, &class, &vers)) ) {
|
||||
void *sym;
|
||||
if( vers != 1 || class != 30 )
|
||||
continue;
|
||||
inner_loop:
|
||||
#ifndef __riscos__
|
||||
finfo = ctx->sym;
|
||||
#else /* __riscos__ */
|
||||
finfo = (PUBKEYS_CAST) ctx->sym;
|
||||
#endif /* __riscos__ */
|
||||
while( (sym = (*r->enumfunc)(31, &ctx->seq2, &class, &vers)) ) {
|
||||
const char *algname;
|
||||
if( vers != 1 || class != 31 )
|
||||
continue;
|
||||
*algo = *(int*)sym;
|
||||
algname = (*finfo)( *algo, npkey, nskey, nenc, nsig, use,
|
||||
generate, check_secret_key, encryptf,
|
||||
decryptf, sign, verify, get_nbits );
|
||||
if( algname ) {
|
||||
ctx->r = r;
|
||||
return algname;
|
||||
}
|
||||
}
|
||||
ctx->seq2 = 0;
|
||||
}
|
||||
ctx->seq1 = 0;
|
||||
}
|
||||
ctx->r = r;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int (*
|
||||
dynload_getfnc_gather_random())(void (*)(const void*, size_t, int), int,
|
||||
size_t, int)
|
||||
{
|
||||
EXTLIST r;
|
||||
void *sym;
|
||||
|
||||
for( r = extensions; r; r = r->next ) {
|
||||
int seq, class, vers;
|
||||
|
||||
if( r->failed )
|
||||
continue;
|
||||
if( !r->handle && load_extension(r) )
|
||||
continue;
|
||||
seq = 0;
|
||||
while( (sym = (*r->enumfunc)(40, &seq, &class, &vers)) ) {
|
||||
if( vers != 1 || class != 40 )
|
||||
continue;
|
||||
return (int (*)(void (*)(const void*, size_t, int), int,
|
||||
size_t, int))sym;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void (*
|
||||
dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int), int)
|
||||
{
|
||||
EXTLIST r;
|
||||
void *sym;
|
||||
|
||||
for( r = extensions; r; r = r->next ) {
|
||||
int seq, class, vers;
|
||||
|
||||
if( r->failed )
|
||||
continue;
|
||||
if( !r->handle && load_extension(r) )
|
||||
continue;
|
||||
seq = 0;
|
||||
while( (sym = (*r->enumfunc)(41, &seq, &class, &vers)) ) {
|
||||
if( vers != 1 || class != 41 )
|
||||
continue;
|
||||
return (void (*)( void (*)(const void*, size_t, int), int))sym;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* dynload.h
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_CIPHER_DYNLOAD_H
|
||||
#define G10_CIPHER_DYNLOAD_H
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
|
||||
void register_internal_cipher_extension( const char *module_id,
|
||||
void * (*enumfunc)(int, int*, int*, int*) );
|
||||
|
||||
int
|
||||
enum_gnupgext_digests( void **enum_context,
|
||||
int *algo,
|
||||
const char *(**r_get_info)( int, size_t*,byte**, int*, int*,
|
||||
void (**)(void*),
|
||||
void (**)(void*,byte*,size_t),
|
||||
void (**)(void*),byte *(**)(void*)) );
|
||||
|
||||
const char *
|
||||
enum_gnupgext_ciphers( void **enum_context, int *algo,
|
||||
size_t *keylen, size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
|
||||
const char *
|
||||
enum_gnupgext_pubkeys( void **enum_context, int *algo,
|
||||
int *npkey, int *nskey, int *nenc, int *nsig, int *use,
|
||||
int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
|
||||
int (**check_secret_key)( int algo, MPI *skey ),
|
||||
int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ),
|
||||
int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ),
|
||||
int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ),
|
||||
int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev ),
|
||||
unsigned (**get_nbits)( int algo, MPI *pkey ) );
|
||||
|
||||
|
||||
int (*dynload_getfnc_gather_random(void))( void (*)(const void*, size_t, int),
|
||||
int, size_t, int);
|
||||
void (*dynload_getfnc_fast_random_poll(void)
|
||||
)( void (*)(const void*, size_t, int), int );
|
||||
|
||||
|
||||
/** This function is in construct.c **/
|
||||
void cipher_modules_constructor(void);
|
||||
|
||||
#endif /*G10_CIPHER_DYNLOAD_H*/
|
|
@ -0,0 +1,666 @@
|
|||
/* elgamal.c - ElGamal Public Key encryption
|
||||
* Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* For a description of the algorithm, see:
|
||||
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
|
||||
* ISBN 0-471-11709-9. Pages 476 ff.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "elgamal.h"
|
||||
|
||||
typedef struct {
|
||||
MPI p; /* prime */
|
||||
MPI g; /* group generator */
|
||||
MPI y; /* g^x mod p */
|
||||
} ELG_public_key;
|
||||
|
||||
|
||||
typedef struct {
|
||||
MPI p; /* prime */
|
||||
MPI g; /* group generator */
|
||||
MPI y; /* g^x mod p */
|
||||
MPI x; /* secret exponent */
|
||||
} ELG_secret_key;
|
||||
|
||||
|
||||
static void test_keys( ELG_secret_key *sk, unsigned nbits );
|
||||
static MPI gen_k( MPI p );
|
||||
static void generate( ELG_secret_key *sk, unsigned nbits, MPI **factors );
|
||||
static int check_secret_key( ELG_secret_key *sk );
|
||||
static void do_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey );
|
||||
static void decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey );
|
||||
static void sign(MPI a, MPI b, MPI input, ELG_secret_key *skey);
|
||||
static int verify(MPI a, MPI b, MPI input, ELG_public_key *pkey);
|
||||
|
||||
|
||||
static void (*progress_cb) ( void *, int );
|
||||
static void *progress_cb_data;
|
||||
|
||||
void
|
||||
register_pk_elg_progress ( void (*cb)( void *, int), void *cb_data )
|
||||
{
|
||||
progress_cb = cb;
|
||||
progress_cb_data = cb_data;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
progress( int c )
|
||||
{
|
||||
if ( progress_cb )
|
||||
progress_cb ( progress_cb_data, c );
|
||||
else
|
||||
fputc( c, stderr );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Michael Wiener's table about subgroup sizes to match field sizes
|
||||
* (floating around somewhere - Fixme: need a reference)
|
||||
*/
|
||||
static unsigned int
|
||||
wiener_map( unsigned int n )
|
||||
{
|
||||
static struct { unsigned int p_n, q_n; } t[] =
|
||||
{ /* p q attack cost */
|
||||
{ 512, 119 }, /* 9 x 10^17 */
|
||||
{ 768, 145 }, /* 6 x 10^21 */
|
||||
{ 1024, 165 }, /* 7 x 10^24 */
|
||||
{ 1280, 183 }, /* 3 x 10^27 */
|
||||
{ 1536, 198 }, /* 7 x 10^29 */
|
||||
{ 1792, 212 }, /* 9 x 10^31 */
|
||||
{ 2048, 225 }, /* 8 x 10^33 */
|
||||
{ 2304, 237 }, /* 5 x 10^35 */
|
||||
{ 2560, 249 }, /* 3 x 10^37 */
|
||||
{ 2816, 259 }, /* 1 x 10^39 */
|
||||
{ 3072, 269 }, /* 3 x 10^40 */
|
||||
{ 3328, 279 }, /* 8 x 10^41 */
|
||||
{ 3584, 288 }, /* 2 x 10^43 */
|
||||
{ 3840, 296 }, /* 4 x 10^44 */
|
||||
{ 4096, 305 }, /* 7 x 10^45 */
|
||||
{ 4352, 313 }, /* 1 x 10^47 */
|
||||
{ 4608, 320 }, /* 2 x 10^48 */
|
||||
{ 4864, 328 }, /* 2 x 10^49 */
|
||||
{ 5120, 335 }, /* 3 x 10^50 */
|
||||
{ 0, 0 }
|
||||
};
|
||||
int i;
|
||||
|
||||
for(i=0; t[i].p_n; i++ ) {
|
||||
if( n <= t[i].p_n )
|
||||
return t[i].q_n;
|
||||
}
|
||||
/* not in table - use some arbitrary high number ;-) */
|
||||
return n / 8 + 200;
|
||||
}
|
||||
|
||||
static void
|
||||
test_keys( ELG_secret_key *sk, unsigned nbits )
|
||||
{
|
||||
ELG_public_key pk;
|
||||
MPI test = mpi_alloc( 0 );
|
||||
MPI out1_a = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
|
||||
MPI out1_b = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
|
||||
MPI out2 = mpi_alloc( nbits / BITS_PER_MPI_LIMB );
|
||||
|
||||
pk.p = sk->p;
|
||||
pk.g = sk->g;
|
||||
pk.y = sk->y;
|
||||
|
||||
/*mpi_set_bytes( test, nbits, get_random_byte, 0 );*/
|
||||
{ char *p = get_random_bits( nbits, 0, 0 );
|
||||
mpi_set_buffer( test, p, (nbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
do_encrypt( out1_a, out1_b, test, &pk );
|
||||
decrypt( out2, out1_a, out1_b, sk );
|
||||
if( mpi_cmp( test, out2 ) )
|
||||
log_fatal("ElGamal operation: encrypt, decrypt failed\n");
|
||||
|
||||
sign( out1_a, out1_b, test, sk );
|
||||
if( !verify( out1_a, out1_b, test, &pk ) )
|
||||
log_fatal("ElGamal operation: sign, verify failed\n");
|
||||
|
||||
mpi_free( test );
|
||||
mpi_free( out1_a );
|
||||
mpi_free( out1_b );
|
||||
mpi_free( out2 );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* generate a random secret exponent k from prime p, so
|
||||
* that k is relatively prime to p-1
|
||||
*/
|
||||
static MPI
|
||||
gen_k( MPI p )
|
||||
{
|
||||
MPI k = mpi_alloc_secure( 0 );
|
||||
MPI temp = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
MPI p_1 = mpi_copy(p);
|
||||
unsigned int orig_nbits = mpi_get_nbits(p);
|
||||
unsigned int nbits;
|
||||
unsigned int nbytes;
|
||||
char *rndbuf = NULL;
|
||||
|
||||
/* IMO using a k much lesser than p is sufficient and it greatly
|
||||
* improves the encryption performance. We use Wiener's table
|
||||
* and add a large safety margin.
|
||||
*/
|
||||
nbits = wiener_map( orig_nbits ) * 3 / 2;
|
||||
if( nbits >= orig_nbits )
|
||||
BUG();
|
||||
|
||||
nbytes = (nbits+7)/8;
|
||||
if( DBG_CIPHER )
|
||||
log_debug("choosing a random k of %u bits", nbits);
|
||||
mpi_sub_ui( p_1, p, 1);
|
||||
for(;;) {
|
||||
if( !rndbuf || nbits < 32 ) {
|
||||
m_free(rndbuf);
|
||||
rndbuf = get_random_bits( nbits, 1, 1 );
|
||||
}
|
||||
else { /* change only some of the higher bits */
|
||||
/* we could impprove this by directly requesting more memory
|
||||
* at the first call to get_random_bits() and use this the here
|
||||
* maybe it is easier to do this directly in random.c
|
||||
* Anyway, it is highly inlikely that we will ever reach this code
|
||||
*/
|
||||
char *pp = get_random_bits( 32, 1, 1 );
|
||||
memcpy( rndbuf,pp, 4 );
|
||||
m_free(pp);
|
||||
log_debug("gen_k: tsss, never expected to reach this\n");
|
||||
}
|
||||
mpi_set_buffer( k, rndbuf, nbytes, 0 );
|
||||
|
||||
for(;;) {
|
||||
/* Hmm, actually we don't need this step here
|
||||
* because we use k much smaller than p - we do it anyway
|
||||
* just in case the keep on adding a one to k ;) */
|
||||
if( !(mpi_cmp( k, p_1 ) < 0) ) { /* check: k < (p-1) */
|
||||
if( DBG_CIPHER )
|
||||
progress('+');
|
||||
break; /* no */
|
||||
}
|
||||
if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
|
||||
if( DBG_CIPHER )
|
||||
progress('-');
|
||||
break; /* no */
|
||||
}
|
||||
if( mpi_gcd( temp, k, p_1 ) )
|
||||
goto found; /* okay, k is relatively prime to (p-1) */
|
||||
mpi_add_ui( k, k, 1 );
|
||||
if( DBG_CIPHER )
|
||||
progress('.');
|
||||
}
|
||||
}
|
||||
found:
|
||||
m_free(rndbuf);
|
||||
if( DBG_CIPHER )
|
||||
progress('\n');
|
||||
mpi_free(p_1);
|
||||
mpi_free(temp);
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Generate a key pair with a key of size NBITS
|
||||
* Returns: 2 structures filles with all needed values
|
||||
* and an array with n-1 factors of (p-1)
|
||||
*/
|
||||
static void
|
||||
generate( ELG_secret_key *sk, unsigned int nbits, MPI **ret_factors )
|
||||
{
|
||||
MPI p; /* the prime */
|
||||
MPI p_min1;
|
||||
MPI g;
|
||||
MPI x; /* the secret exponent */
|
||||
MPI y;
|
||||
MPI temp;
|
||||
unsigned int qbits;
|
||||
unsigned int xbits;
|
||||
byte *rndbuf;
|
||||
|
||||
p_min1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
temp = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
qbits = wiener_map( nbits );
|
||||
if( qbits & 1 ) /* better have a even one */
|
||||
qbits++;
|
||||
g = mpi_alloc(1);
|
||||
p = generate_elg_prime( 0, nbits, qbits, g, ret_factors );
|
||||
mpi_sub_ui(p_min1, p, 1);
|
||||
|
||||
|
||||
/* select a random number which has these properties:
|
||||
* 0 < x < p-1
|
||||
* This must be a very good random number because this is the
|
||||
* secret part. The prime is public and may be shared anyway,
|
||||
* so a random generator level of 1 is used for the prime.
|
||||
*
|
||||
* I don't see a reason to have a x of about the same size
|
||||
* as the p. It should be sufficient to have one about the size
|
||||
* of q or the later used k plus a large safety margin. Decryption
|
||||
* will be much faster with such an x.
|
||||
*/
|
||||
xbits = qbits * 3 / 2;
|
||||
if( xbits >= nbits )
|
||||
BUG();
|
||||
x = mpi_alloc_secure( xbits/BITS_PER_MPI_LIMB );
|
||||
if( DBG_CIPHER )
|
||||
log_debug("choosing a random x of size %u", xbits );
|
||||
rndbuf = NULL;
|
||||
do {
|
||||
if( DBG_CIPHER )
|
||||
progress('.');
|
||||
if( rndbuf ) { /* change only some of the higher bits */
|
||||
if( xbits < 16 ) {/* should never happen ... */
|
||||
m_free(rndbuf);
|
||||
rndbuf = get_random_bits( xbits, 2, 1 );
|
||||
}
|
||||
else {
|
||||
char *r = get_random_bits( 16, 2, 1 );
|
||||
memcpy(rndbuf, r, 16/8 );
|
||||
m_free(r);
|
||||
}
|
||||
}
|
||||
else
|
||||
rndbuf = get_random_bits( xbits, 2, 1 );
|
||||
mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 );
|
||||
mpi_clear_highbit( x, xbits+1 );
|
||||
} while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) );
|
||||
m_free(rndbuf);
|
||||
|
||||
y = mpi_alloc(nbits/BITS_PER_MPI_LIMB);
|
||||
mpi_powm( y, g, x, p );
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
progress('\n');
|
||||
log_mpidump("elg p= ", p );
|
||||
log_mpidump("elg g= ", g );
|
||||
log_mpidump("elg y= ", y );
|
||||
log_mpidump("elg x= ", x );
|
||||
}
|
||||
|
||||
/* copy the stuff to the key structures */
|
||||
sk->p = p;
|
||||
sk->g = g;
|
||||
sk->y = y;
|
||||
sk->x = x;
|
||||
|
||||
/* now we can test our keys (this should never fail!) */
|
||||
test_keys( sk, nbits - 64 );
|
||||
|
||||
mpi_free( p_min1 );
|
||||
mpi_free( temp );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Test whether the secret key is valid.
|
||||
* Returns: if this is a valid key.
|
||||
*/
|
||||
static int
|
||||
check_secret_key( ELG_secret_key *sk )
|
||||
{
|
||||
int rc;
|
||||
MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
|
||||
|
||||
mpi_powm( y, sk->g, sk->x, sk->p );
|
||||
rc = !mpi_cmp( y, sk->y );
|
||||
mpi_free( y );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey )
|
||||
{
|
||||
MPI k;
|
||||
|
||||
/* Note: maybe we should change the interface, so that it
|
||||
* is possible to check that input is < p and return an
|
||||
* error code.
|
||||
*/
|
||||
|
||||
k = gen_k( pkey->p );
|
||||
mpi_powm( a, pkey->g, k, pkey->p );
|
||||
/* b = (y^k * input) mod p
|
||||
* = ((y^k mod p) * (input mod p)) mod p
|
||||
* and because input is < p
|
||||
* = ((y^k mod p) * input) mod p
|
||||
*/
|
||||
mpi_powm( b, pkey->y, k, pkey->p );
|
||||
mpi_mulm( b, b, input, pkey->p );
|
||||
#if 0
|
||||
if( DBG_CIPHER ) {
|
||||
log_mpidump("elg encrypted y= ", pkey->y);
|
||||
log_mpidump("elg encrypted p= ", pkey->p);
|
||||
log_mpidump("elg encrypted k= ", k);
|
||||
log_mpidump("elg encrypted M= ", input);
|
||||
log_mpidump("elg encrypted a= ", a);
|
||||
log_mpidump("elg encrypted b= ", b);
|
||||
}
|
||||
#endif
|
||||
mpi_free(k);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey )
|
||||
{
|
||||
MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
|
||||
|
||||
/* output = b/(a^x) mod p */
|
||||
mpi_powm( t1, a, skey->x, skey->p );
|
||||
mpi_invm( t1, t1, skey->p );
|
||||
mpi_mulm( output, b, t1, skey->p );
|
||||
#if 0
|
||||
if( DBG_CIPHER ) {
|
||||
log_mpidump("elg decrypted x= ", skey->x);
|
||||
log_mpidump("elg decrypted p= ", skey->p);
|
||||
log_mpidump("elg decrypted a= ", a);
|
||||
log_mpidump("elg decrypted b= ", b);
|
||||
log_mpidump("elg decrypted M= ", output);
|
||||
}
|
||||
#endif
|
||||
mpi_free(t1);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Make an Elgamal signature out of INPUT
|
||||
*/
|
||||
|
||||
static void
|
||||
sign(MPI a, MPI b, MPI input, ELG_secret_key *skey )
|
||||
{
|
||||
MPI k;
|
||||
MPI t = mpi_alloc( mpi_get_nlimbs(a) );
|
||||
MPI inv = mpi_alloc( mpi_get_nlimbs(a) );
|
||||
MPI p_1 = mpi_copy(skey->p);
|
||||
|
||||
/*
|
||||
* b = (t * inv) mod (p-1)
|
||||
* b = (t * inv(k,(p-1),(p-1)) mod (p-1)
|
||||
* b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1)
|
||||
*
|
||||
*/
|
||||
mpi_sub_ui(p_1, p_1, 1);
|
||||
k = gen_k( skey->p );
|
||||
mpi_powm( a, skey->g, k, skey->p );
|
||||
mpi_mul(t, skey->x, a );
|
||||
mpi_subm(t, input, t, p_1 );
|
||||
while( mpi_is_neg(t) ) {
|
||||
BUG(); /* That is nonsense code - left over from a very early test?*/
|
||||
mpi_add(t, t, p_1);
|
||||
}
|
||||
mpi_invm(inv, k, p_1 );
|
||||
mpi_mulm(b, t, inv, p_1 );
|
||||
|
||||
#if 0
|
||||
if( DBG_CIPHER ) {
|
||||
log_mpidump("elg sign p= ", skey->p);
|
||||
log_mpidump("elg sign g= ", skey->g);
|
||||
log_mpidump("elg sign y= ", skey->y);
|
||||
log_mpidump("elg sign x= ", skey->x);
|
||||
log_mpidump("elg sign k= ", k);
|
||||
log_mpidump("elg sign M= ", input);
|
||||
log_mpidump("elg sign a= ", a);
|
||||
log_mpidump("elg sign b= ", b);
|
||||
}
|
||||
#endif
|
||||
mpi_free(k);
|
||||
mpi_free(t);
|
||||
mpi_free(inv);
|
||||
mpi_free(p_1);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Returns true if the signature composed of A and B is valid.
|
||||
*/
|
||||
static int
|
||||
verify(MPI a, MPI b, MPI input, ELG_public_key *pkey )
|
||||
{
|
||||
int rc;
|
||||
MPI t1;
|
||||
MPI t2;
|
||||
MPI base[4];
|
||||
MPI exp[4];
|
||||
|
||||
if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) )
|
||||
return 0; /* assertion 0 < a < p failed */
|
||||
|
||||
t1 = mpi_alloc( mpi_get_nlimbs(a) );
|
||||
t2 = mpi_alloc( mpi_get_nlimbs(a) );
|
||||
|
||||
#if 0
|
||||
/* t1 = (y^a mod p) * (a^b mod p) mod p */
|
||||
mpi_powm( t1, pkey->y, a, pkey->p );
|
||||
mpi_powm( t2, a, b, pkey->p );
|
||||
mpi_mulm( t1, t1, t2, pkey->p );
|
||||
|
||||
/* t2 = g ^ input mod p */
|
||||
mpi_powm( t2, pkey->g, input, pkey->p );
|
||||
|
||||
rc = !mpi_cmp( t1, t2 );
|
||||
#elif 0
|
||||
/* t1 = (y^a mod p) * (a^b mod p) mod p */
|
||||
base[0] = pkey->y; exp[0] = a;
|
||||
base[1] = a; exp[1] = b;
|
||||
base[2] = NULL; exp[2] = NULL;
|
||||
mpi_mulpowm( t1, base, exp, pkey->p );
|
||||
|
||||
/* t2 = g ^ input mod p */
|
||||
mpi_powm( t2, pkey->g, input, pkey->p );
|
||||
|
||||
rc = !mpi_cmp( t1, t2 );
|
||||
#else
|
||||
/* t1 = g ^ - input * y ^ a * a ^ b mod p */
|
||||
mpi_invm(t2, pkey->g, pkey->p );
|
||||
base[0] = t2 ; exp[0] = input;
|
||||
base[1] = pkey->y; exp[1] = a;
|
||||
base[2] = a; exp[2] = b;
|
||||
base[3] = NULL; exp[3] = NULL;
|
||||
mpi_mulpowm( t1, base, exp, pkey->p );
|
||||
rc = !mpi_cmp_ui( t1, 1 );
|
||||
|
||||
#endif
|
||||
|
||||
mpi_free(t1);
|
||||
mpi_free(t2);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
************** interface ******************
|
||||
*********************************************/
|
||||
|
||||
int
|
||||
elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
{
|
||||
ELG_secret_key sk;
|
||||
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
generate( &sk, nbits, retfactors );
|
||||
skey[0] = sk.p;
|
||||
skey[1] = sk.g;
|
||||
skey[2] = sk.y;
|
||||
skey[3] = sk.x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
elg_check_secret_key( int algo, MPI *skey )
|
||||
{
|
||||
ELG_secret_key sk;
|
||||
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !skey[0] || !skey[1] || !skey[2] || !skey[3] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.g = skey[1];
|
||||
sk.y = skey[2];
|
||||
sk.x = skey[3];
|
||||
if( !check_secret_key( &sk ) )
|
||||
return G10ERR_BAD_SECKEY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
{
|
||||
ELG_public_key pk;
|
||||
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data || !pkey[0] || !pkey[1] || !pkey[2] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
pk.p = pkey[0];
|
||||
pk.g = pkey[1];
|
||||
pk.y = pkey[2];
|
||||
resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.p ) );
|
||||
resarr[1] = mpi_alloc( mpi_get_nlimbs( pk.p ) );
|
||||
do_encrypt( resarr[0], resarr[1], data, &pk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
|
||||
{
|
||||
ELG_secret_key sk;
|
||||
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data[0] || !data[1]
|
||||
|| !skey[0] || !skey[1] || !skey[2] || !skey[3] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.g = skey[1];
|
||||
sk.y = skey[2];
|
||||
sk.x = skey[3];
|
||||
*result = mpi_alloc_secure( mpi_get_nlimbs( sk.p ) );
|
||||
decrypt( *result, data[0], data[1], &sk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
elg_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
{
|
||||
ELG_secret_key sk;
|
||||
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.g = skey[1];
|
||||
sk.y = skey[2];
|
||||
sk.x = skey[3];
|
||||
resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
|
||||
resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
|
||||
sign( resarr[0], resarr[1], data, &sk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
elg_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev )
|
||||
{
|
||||
ELG_public_key pk;
|
||||
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data[0] || !data[1] || !hash
|
||||
|| !pkey[0] || !pkey[1] || !pkey[2] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
pk.p = pkey[0];
|
||||
pk.g = pkey[1];
|
||||
pk.y = pkey[2];
|
||||
if( !verify( data[0], data[1], hash, &pk ) )
|
||||
return G10ERR_BAD_SIGN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
elg_get_nbits( int algo, MPI *pkey )
|
||||
{
|
||||
if( !is_ELGAMAL(algo) )
|
||||
return 0;
|
||||
return mpi_get_nbits( pkey[0] );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
* Usage: Bit 0 set : allows signing
|
||||
* 1 set : allows encryption
|
||||
* NOTE: This function allows signing also for ELG-E, which is not
|
||||
* okay but a bad hack to allow to work with old gpg keys. The real check
|
||||
* is done in the gnupg ocde depending on the packet version.
|
||||
*/
|
||||
const char *
|
||||
elg_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
|
||||
int *use )
|
||||
{
|
||||
*npkey = 3;
|
||||
*nskey = 4;
|
||||
*nenc = 2;
|
||||
*nsig = 2;
|
||||
|
||||
switch( algo ) {
|
||||
case PUBKEY_ALGO_ELGAMAL:
|
||||
*use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
|
||||
return "ELG";
|
||||
case PUBKEY_ALGO_ELGAMAL_E:
|
||||
*use = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
|
||||
return "ELG-E";
|
||||
default: *use = 0; return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* elgamal.h
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_ELGAMAL_H
|
||||
#define G10_ELGAMAL_H
|
||||
|
||||
int elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
|
||||
int elg_check_secret_key( int algo, MPI *skey );
|
||||
int elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey );
|
||||
int elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
|
||||
int elg_sign( int algo, MPI *resarr, MPI data, MPI *skey );
|
||||
int elg_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev );
|
||||
unsigned elg_get_nbits( int algo, MPI *pkey );
|
||||
const char *elg_get_info( int algo, int *npkey, int *nskey,
|
||||
int *nenc, int *nsig, int *use );
|
||||
|
||||
|
||||
#endif /*G10_ELGAMAL_H*/
|
|
@ -0,0 +1,46 @@
|
|||
/* g10c.c - Wrapper for cipher functions
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include "mpi.h"
|
||||
#include "random.h"
|
||||
#include "cipher.h"
|
||||
|
||||
|
||||
/* FIXME: The modules should use functions from libgcrypt */
|
||||
|
||||
|
||||
const char *g10c_revision_string(int dummy) { return "$Revision$"; }
|
||||
|
||||
MPI
|
||||
g10c_generate_secret_prime( unsigned nbits )
|
||||
{
|
||||
return generate_secret_prime( nbits );
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
g10c_get_random_bits( unsigned nbits, int level, int secure )
|
||||
{
|
||||
return (char*)get_random_bits( nbits, level, secure );
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* gost.c - GOST encryption
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* The description of GOST (and the used S-boxes) are taken from:
|
||||
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
|
||||
* ISBN 0-471-11709-9. .
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "types.h"
|
||||
#include "gost.h"
|
||||
|
||||
#error don't use this
|
||||
|
||||
|
||||
void
|
||||
gost_setkey( GOST_context *c, byte *key )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gost_setiv( GOST_context *c, byte *iv )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gost_encode( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gost_decode( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cfbshift( byte *iv, byte *buf, unsigned count)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
gost_encode_cfb( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nbytes)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gost_decode_cfb( GOST_context *c, byte *outbuf, byte *inbuf, unsigned nbytes)
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/* gost.h
|
||||
* Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_GOST_H
|
||||
#define G10_GOST_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define GOST_KEYSIZE 16
|
||||
#define GOST_BLOCKSIZE 8
|
||||
#define GOST_ROUNDS 8
|
||||
#define GOST_KEYLEN (6*GOST_ROUNDS+4)
|
||||
|
||||
typedef struct {
|
||||
u16 ek[GOST_KEYLEN];
|
||||
u16 dk[GOST_KEYLEN];
|
||||
byte iv[GOST_BLOCKSIZE];
|
||||
} GOST_context;
|
||||
|
||||
void gost_setkey( GOST_context *c, byte *key );
|
||||
void gost_setiv( GOST_context *c, byte *iv );
|
||||
void gost_encode( GOST_context *c, byte *out, byte *in, unsigned nblocks );
|
||||
void gost_decode( GOST_context *c, byte *out, byte *in, unsigned nblocks );
|
||||
void gost_encode_cfb( GOST_context *c, byte *outbuf,
|
||||
byte *inbuf, unsigned nbytes);
|
||||
void gost_decode_cfb( GOST_context *c, byte *outbuf,
|
||||
byte *inbuf, unsigned nbytes);
|
||||
|
||||
|
||||
#endif /*G10_GOST_H*/
|
|
@ -0,0 +1,524 @@
|
|||
/* md.c - message digest dispatcher
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "cipher.h"
|
||||
#include "errors.h"
|
||||
#include "dynload.h"
|
||||
#include "rmd.h"
|
||||
|
||||
|
||||
/****************
|
||||
* This structure is used for the list of available algorithms
|
||||
* and for the list of algorithms in MD_HANDLE.
|
||||
*/
|
||||
struct md_digest_list_s {
|
||||
struct md_digest_list_s *next;
|
||||
const char *name;
|
||||
int algo;
|
||||
byte *asnoid;
|
||||
int asnlen;
|
||||
int mdlen;
|
||||
void (*init)( void *c );
|
||||
void (*write)( void *c, byte *buf, size_t nbytes );
|
||||
void (*final)( void *c );
|
||||
byte *(*read)( void *c );
|
||||
size_t contextsize; /* allocate this amount of context */
|
||||
PROPERLY_ALIGNED_TYPE context;
|
||||
};
|
||||
|
||||
static struct md_digest_list_s *digest_list;
|
||||
|
||||
|
||||
static struct md_digest_list_s *
|
||||
new_list_item( int algo,
|
||||
const char *(*get_info)( int, size_t*,byte**, int*, int*,
|
||||
void (**)(void*),
|
||||
void (**)(void*,byte*,size_t),
|
||||
void (**)(void*),byte *(**)(void*)) )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
r = m_alloc_clear( sizeof *r );
|
||||
r->algo = algo,
|
||||
r->name = (*get_info)( algo, &r->contextsize,
|
||||
&r->asnoid, &r->asnlen, &r->mdlen,
|
||||
&r->init, &r->write, &r->final, &r->read );
|
||||
if( !r->name ) {
|
||||
m_free(r);
|
||||
r = NULL;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Try to load the modules with the requeste algorithm
|
||||
* and return true if new modules are available
|
||||
* If req_alog is -1 try to load all digest algorithms.
|
||||
*/
|
||||
static int
|
||||
load_digest_module( int req_algo )
|
||||
{
|
||||
static int initialized = 0;
|
||||
static u32 checked_algos[256/32];
|
||||
static int checked_all = 0;
|
||||
struct md_digest_list_s *r;
|
||||
void *context = NULL;
|
||||
int algo;
|
||||
int any = 0;
|
||||
const char *(*get_info)( int, size_t*,byte**, int*, int*,
|
||||
void (**)(void*),
|
||||
void (**)(void*,byte*,size_t),
|
||||
void (**)(void*),byte *(**)(void*));
|
||||
|
||||
if( !initialized ) {
|
||||
cipher_modules_constructor();
|
||||
initialized = 1;
|
||||
}
|
||||
algo = req_algo;
|
||||
if( algo > 255 || !algo )
|
||||
return 0; /* algorithm number too high (does not fit into out bitmap)*/
|
||||
if( checked_all )
|
||||
return 0; /* already called with -1 */
|
||||
if( algo < 0 )
|
||||
checked_all = 1;
|
||||
else if( (checked_algos[algo/32] & (1 << (algo%32))) )
|
||||
return 0; /* already checked and not found */
|
||||
else
|
||||
checked_algos[algo/32] |= (1 << (algo%32));
|
||||
|
||||
while( enum_gnupgext_digests( &context, &algo, &get_info ) ) {
|
||||
if( req_algo != -1 && algo != req_algo )
|
||||
continue;
|
||||
for(r=digest_list; r; r = r->next )
|
||||
if( r->algo == algo )
|
||||
break;
|
||||
if( r ) {
|
||||
log_info("skipping digest %d: already loaded\n", algo );
|
||||
continue;
|
||||
}
|
||||
r = new_list_item( algo, get_info );
|
||||
if( ! r ) {
|
||||
log_info("skipping digest %d: no name\n", algo );
|
||||
continue;
|
||||
}
|
||||
/* put it into the list */
|
||||
if( g10_opt_verbose > 1 )
|
||||
log_info("loaded digest %d\n", algo);
|
||||
r->next = digest_list;
|
||||
digest_list = r;
|
||||
any = 1;
|
||||
if( req_algo != -1 )
|
||||
break;
|
||||
}
|
||||
enum_gnupgext_digests( &context, NULL, NULL );
|
||||
return any;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Map a string to the digest algo
|
||||
*/
|
||||
int
|
||||
string_to_digest_algo( const char *string )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
do {
|
||||
for(r = digest_list; r; r = r->next )
|
||||
if( !ascii_strcasecmp( r->name, string ) )
|
||||
return r->algo;
|
||||
} while( !r && load_digest_module(-1) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Map a digest algo to a string
|
||||
*/
|
||||
const char *
|
||||
digest_algo_to_string( int algo )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
do {
|
||||
for(r = digest_list; r; r = r->next )
|
||||
if( r->algo == algo )
|
||||
return r->name;
|
||||
} while( !r && load_digest_module( algo ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
check_digest_algo( int algo )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
do {
|
||||
for(r = digest_list; r; r = r->next )
|
||||
if( r->algo == algo )
|
||||
return 0;
|
||||
} while( !r && load_digest_module(algo) );
|
||||
return G10ERR_DIGEST_ALGO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Open a message digest handle for use with algorithm ALGO.
|
||||
* More algorithms may be added by md_enable(). The initial algorithm
|
||||
* may be 0.
|
||||
*/
|
||||
MD_HANDLE
|
||||
md_open( int algo, int secure )
|
||||
{
|
||||
MD_HANDLE hd;
|
||||
int bufsize;
|
||||
|
||||
if( secure ) {
|
||||
bufsize = 512 - sizeof( *hd );
|
||||
hd = m_alloc_secure_clear( sizeof *hd + bufsize );
|
||||
}
|
||||
else {
|
||||
bufsize = 1024 - sizeof( *hd );
|
||||
hd = m_alloc_clear( sizeof *hd + bufsize );
|
||||
}
|
||||
|
||||
hd->bufsize = bufsize+1; /* hd has already one byte allocated */
|
||||
hd->secure = secure;
|
||||
if( algo )
|
||||
md_enable( hd, algo );
|
||||
fast_random_poll();
|
||||
return hd;
|
||||
}
|
||||
|
||||
void
|
||||
md_enable( MD_HANDLE h, int algo )
|
||||
{
|
||||
struct md_digest_list_s *r, *ac;
|
||||
|
||||
for( ac=h->list; ac; ac = ac->next )
|
||||
if( ac->algo == algo )
|
||||
return ; /* already enabled */
|
||||
/* find the algorithm */
|
||||
do {
|
||||
for(r = digest_list; r; r = r->next )
|
||||
if( r->algo == algo )
|
||||
break;
|
||||
} while( !r && load_digest_module( algo ) );
|
||||
if( !r ) {
|
||||
log_error("md_enable: algorithm %d not available\n", algo );
|
||||
return;
|
||||
}
|
||||
/* and allocate a new list entry */
|
||||
ac = h->secure? m_alloc_secure( sizeof *ac + r->contextsize
|
||||
- sizeof(r->context) )
|
||||
: m_alloc( sizeof *ac + r->contextsize
|
||||
- sizeof(r->context) );
|
||||
*ac = *r;
|
||||
ac->next = h->list;
|
||||
h->list = ac;
|
||||
/* and init this instance */
|
||||
(*ac->init)( &ac->context.c );
|
||||
}
|
||||
|
||||
|
||||
MD_HANDLE
|
||||
md_copy( MD_HANDLE a )
|
||||
{
|
||||
MD_HANDLE b;
|
||||
struct md_digest_list_s *ar, *br;
|
||||
|
||||
if( a->bufcount )
|
||||
md_write( a, NULL, 0 );
|
||||
b = a->secure ? m_alloc_secure( sizeof *b + a->bufsize - 1 )
|
||||
: m_alloc( sizeof *b + a->bufsize - 1 );
|
||||
memcpy( b, a, sizeof *a + a->bufsize - 1 );
|
||||
b->list = NULL;
|
||||
b->debug = NULL;
|
||||
/* and now copy the complete list of algorithms */
|
||||
/* I know that the copied list is reversed, but that doesn't matter */
|
||||
for( ar=a->list; ar; ar = ar->next ) {
|
||||
br = a->secure ? m_alloc_secure( sizeof *br + ar->contextsize
|
||||
- sizeof(ar->context) )
|
||||
: m_alloc( sizeof *br + ar->contextsize
|
||||
- sizeof(ar->context) );
|
||||
memcpy( br, ar, sizeof(*br) + ar->contextsize
|
||||
- sizeof(ar->context) );
|
||||
br->next = b->list;
|
||||
b->list = br;
|
||||
}
|
||||
|
||||
if( a->debug )
|
||||
md_start_debug( b, "unknown" );
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Reset all contexts and discard any buffered stuff. This may be used
|
||||
* instead of a md_close(); md_open().
|
||||
*/
|
||||
void
|
||||
md_reset( MD_HANDLE a )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
a->bufcount = a->finalized = 0;
|
||||
for( r=a->list; r; r = r->next ) {
|
||||
memset( r->context.c, 0, r->contextsize );
|
||||
(*r->init)( &r->context.c );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md_close(MD_HANDLE a)
|
||||
{
|
||||
struct md_digest_list_s *r, *r2;
|
||||
|
||||
if( !a )
|
||||
return;
|
||||
if( a->debug )
|
||||
md_stop_debug(a);
|
||||
for(r=a->list; r; r = r2 ) {
|
||||
r2 = r->next;
|
||||
m_free(r);
|
||||
}
|
||||
m_free(a);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md_write( MD_HANDLE a, const byte *inbuf, size_t inlen)
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
if( a->debug ) {
|
||||
if( a->bufcount && fwrite(a->buffer, a->bufcount, 1, a->debug ) != 1 )
|
||||
BUG();
|
||||
if( inlen && fwrite(inbuf, inlen, 1, a->debug ) != 1 )
|
||||
BUG();
|
||||
}
|
||||
for(r=a->list; r; r = r->next ) {
|
||||
(*r->write)( &r->context.c, a->buffer, a->bufcount );
|
||||
/* Fixme: all ->write fnc should take a const byte* */
|
||||
(*r->write)( &r->context.c, (byte*)inbuf, inlen );
|
||||
}
|
||||
a->bufcount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
md_final(MD_HANDLE a)
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
if( a->finalized )
|
||||
return;
|
||||
|
||||
if( a->bufcount )
|
||||
md_write( a, NULL, 0 );
|
||||
|
||||
for(r=a->list; r; r = r->next ) {
|
||||
(*r->final)( &r->context.c );
|
||||
}
|
||||
a->finalized = 1;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* if ALGO is null get the digest for the used algo (which should be only one)
|
||||
*/
|
||||
byte *
|
||||
md_read( MD_HANDLE a, int algo )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
if( !algo ) { /* return the first algorithm */
|
||||
if( (r=a->list) ) {
|
||||
if( r->next )
|
||||
log_debug("more than algorithm in md_read(0)\n");
|
||||
return (*r->read)( &r->context.c );
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(r=a->list; r; r = r->next )
|
||||
if( r->algo == algo )
|
||||
return (*r->read)( &r->context.c );
|
||||
}
|
||||
BUG();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* This function combines md_final and md_read but keeps the context
|
||||
* intact. This function can be used to calculate intermediate
|
||||
* digests. The digest is copied into buffer and the digestlength is
|
||||
* returned. If buffer is NULL only the needed size for buffer is returned.
|
||||
* buflen gives the max size of buffer. If the buffer is too shourt to
|
||||
* hold the complete digest, the buffer is filled with as many bytes are
|
||||
* possible and this value is returned.
|
||||
*/
|
||||
int
|
||||
md_digest( MD_HANDLE a, int algo, byte *buffer, int buflen )
|
||||
{
|
||||
struct md_digest_list_s *r = NULL;
|
||||
char *context;
|
||||
char *digest;
|
||||
|
||||
if( a->bufcount )
|
||||
md_write( a, NULL, 0 );
|
||||
|
||||
if( !algo ) { /* return digest for the first algorithm */
|
||||
if( (r=a->list) && r->next )
|
||||
log_debug("more than algorithm in md_digest(0)\n");
|
||||
}
|
||||
else {
|
||||
for(r=a->list; r; r = r->next )
|
||||
if( r->algo == algo )
|
||||
break;
|
||||
}
|
||||
if( !r )
|
||||
BUG();
|
||||
|
||||
if( !buffer )
|
||||
return r->mdlen;
|
||||
|
||||
/* I don't want to change the interface, so I simply work on a copy
|
||||
* the context (extra overhead - should be fixed)*/
|
||||
context = a->secure ? m_alloc_secure( r->contextsize )
|
||||
: m_alloc( r->contextsize );
|
||||
memcpy( context, r->context.c, r->contextsize );
|
||||
(*r->final)( context );
|
||||
digest = (*r->read)( context );
|
||||
|
||||
if( buflen > r->mdlen )
|
||||
buflen = r->mdlen;
|
||||
memcpy( buffer, digest, buflen );
|
||||
|
||||
m_free(context);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
md_get_algo( MD_HANDLE a )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
if( (r=a->list) ) {
|
||||
if( r->next )
|
||||
log_error("WARNING: more than algorithm in md_get_algo()\n");
|
||||
return r->algo;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return the length of the digest
|
||||
*/
|
||||
int
|
||||
md_digest_length( int algo )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
do {
|
||||
for(r = digest_list; r; r = r->next ) {
|
||||
if( r->algo == algo )
|
||||
return r->mdlen;
|
||||
}
|
||||
} while( !r && load_digest_module( algo ) );
|
||||
log_error("WARNING: no length for md algo %d\n", algo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Hmmm: add a mode to enumerate the OIDs
|
||||
* to make g10/sig-check.c more portable */
|
||||
const byte *
|
||||
md_asn_oid( int algo, size_t *asnlen, size_t *mdlen )
|
||||
{
|
||||
struct md_digest_list_s *r;
|
||||
|
||||
do {
|
||||
for(r = digest_list; r; r = r->next ) {
|
||||
if( r->algo == algo ) {
|
||||
if( asnlen )
|
||||
*asnlen = r->asnlen;
|
||||
if( mdlen )
|
||||
*mdlen = r->mdlen;
|
||||
return r->asnoid;
|
||||
}
|
||||
}
|
||||
} while( !r && load_digest_module( algo ) );
|
||||
log_bug("no asn for md algo %d\n", algo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md_start_debug( MD_HANDLE md, const char *suffix )
|
||||
{
|
||||
static int idx=0;
|
||||
char buf[25];
|
||||
|
||||
if( md->debug ) {
|
||||
log_debug("Oops: md debug already started\n");
|
||||
return;
|
||||
}
|
||||
idx++;
|
||||
sprintf(buf, "dbgmd-%05d" EXTSEP_S "%.10s", idx, suffix );
|
||||
md->debug = fopen(buf, "w");
|
||||
if( !md->debug )
|
||||
log_debug("md debug: can't open %s\n", buf );
|
||||
}
|
||||
|
||||
void
|
||||
md_stop_debug( MD_HANDLE md )
|
||||
{
|
||||
if( md->debug ) {
|
||||
if( md->bufcount )
|
||||
md_write( md, NULL, 0 );
|
||||
fclose(md->debug);
|
||||
md->debug = NULL;
|
||||
}
|
||||
#ifdef HAVE_U64_TYPEDEF
|
||||
{ /* a kludge to pull in the __muldi3 for Solaris */
|
||||
volatile u32 a = (u32)(ulong)md;
|
||||
volatile u64 b = 42;
|
||||
volatile u64 c;
|
||||
c = a * b;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,427 @@
|
|||
/* md5.c - MD5 Message-Digest Algorithm
|
||||
* Copyright (C) 1995, 1996, 1998, 1999,
|
||||
* 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* 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, 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; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* According to the definition of MD5 in RFC 1321 from April 1992.
|
||||
* NOTE: This is *not* the same file as the one from glibc.
|
||||
*/
|
||||
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
|
||||
/* Heavily modified for GnuPG by <wk@gnupg.org> */
|
||||
|
||||
/* Test values:
|
||||
* "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E
|
||||
* "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61
|
||||
* "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72
|
||||
* "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "dynload.h"
|
||||
|
||||
#include "bithelp.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
u32 A,B,C,D; /* chaining variables */
|
||||
u32 nblocks;
|
||||
byte buf[64];
|
||||
int count;
|
||||
} MD5_CONTEXT;
|
||||
|
||||
|
||||
static void
|
||||
md5_init( MD5_CONTEXT *ctx )
|
||||
{
|
||||
ctx->A = 0x67452301;
|
||||
ctx->B = 0xefcdab89;
|
||||
ctx->C = 0x98badcfe;
|
||||
ctx->D = 0x10325476;
|
||||
|
||||
ctx->nblocks = 0;
|
||||
ctx->count = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* These are the four functions used in the four steps of the MD5 algorithm
|
||||
and defined in the RFC 1321. The first function is a little bit optimized
|
||||
(as found in Colin Plumbs public domain implementation). */
|
||||
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
|
||||
#define FF(b, c, d) (d ^ (b & (c ^ d)))
|
||||
#define FG(b, c, d) FF (d, b, c)
|
||||
#define FH(b, c, d) (b ^ c ^ d)
|
||||
#define FI(b, c, d) (c ^ (b | ~d))
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* transform n*64 bytes
|
||||
*/
|
||||
static void
|
||||
/*transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )*/
|
||||
transform( MD5_CONTEXT *ctx, byte *data )
|
||||
{
|
||||
u32 correct_words[16];
|
||||
u32 A = ctx->A;
|
||||
u32 B = ctx->B;
|
||||
u32 C = ctx->C;
|
||||
u32 D = ctx->D;
|
||||
u32 *cwp = correct_words;
|
||||
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
{ int i;
|
||||
byte *p2, *p1;
|
||||
for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) {
|
||||
p2[3] = *p1++;
|
||||
p2[2] = *p1++;
|
||||
p2[1] = *p1++;
|
||||
p2[0] = *p1++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
memcpy( correct_words, data, 64 );
|
||||
#endif
|
||||
|
||||
|
||||
#define OP(a, b, c, d, s, T) \
|
||||
do \
|
||||
{ \
|
||||
a += FF (b, c, d) + (*cwp++) + T; \
|
||||
a = rol(a, s); \
|
||||
a += b; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Before we start, one word about the strange constants.
|
||||
They are defined in RFC 1321 as
|
||||
|
||||
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
|
||||
*/
|
||||
|
||||
/* Round 1. */
|
||||
OP (A, B, C, D, 7, 0xd76aa478);
|
||||
OP (D, A, B, C, 12, 0xe8c7b756);
|
||||
OP (C, D, A, B, 17, 0x242070db);
|
||||
OP (B, C, D, A, 22, 0xc1bdceee);
|
||||
OP (A, B, C, D, 7, 0xf57c0faf);
|
||||
OP (D, A, B, C, 12, 0x4787c62a);
|
||||
OP (C, D, A, B, 17, 0xa8304613);
|
||||
OP (B, C, D, A, 22, 0xfd469501);
|
||||
OP (A, B, C, D, 7, 0x698098d8);
|
||||
OP (D, A, B, C, 12, 0x8b44f7af);
|
||||
OP (C, D, A, B, 17, 0xffff5bb1);
|
||||
OP (B, C, D, A, 22, 0x895cd7be);
|
||||
OP (A, B, C, D, 7, 0x6b901122);
|
||||
OP (D, A, B, C, 12, 0xfd987193);
|
||||
OP (C, D, A, B, 17, 0xa679438e);
|
||||
OP (B, C, D, A, 22, 0x49b40821);
|
||||
|
||||
#undef OP
|
||||
#define OP(f, a, b, c, d, k, s, T) \
|
||||
do \
|
||||
{ \
|
||||
a += f (b, c, d) + correct_words[k] + T; \
|
||||
a = rol(a, s); \
|
||||
a += b; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Round 2. */
|
||||
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
|
||||
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
|
||||
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
|
||||
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
|
||||
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
|
||||
OP (FG, D, A, B, C, 10, 9, 0x02441453);
|
||||
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
|
||||
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
|
||||
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
|
||||
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
|
||||
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
|
||||
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
|
||||
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
|
||||
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
|
||||
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
|
||||
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
|
||||
|
||||
/* Round 3. */
|
||||
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
|
||||
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
|
||||
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
|
||||
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
|
||||
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
|
||||
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
|
||||
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
|
||||
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
|
||||
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
|
||||
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
|
||||
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
|
||||
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
|
||||
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
|
||||
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
|
||||
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
|
||||
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
|
||||
|
||||
/* Round 4. */
|
||||
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
|
||||
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
|
||||
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
|
||||
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
|
||||
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
|
||||
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
|
||||
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
|
||||
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
|
||||
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
|
||||
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
|
||||
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
|
||||
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
|
||||
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
|
||||
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
|
||||
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
|
||||
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->A += A;
|
||||
ctx->B += B;
|
||||
ctx->C += C;
|
||||
ctx->D += D;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The routine updates the message-digest context to
|
||||
* account for the presence of each of the characters inBuf[0..inLen-1]
|
||||
* in the message whose digest is being computed.
|
||||
*/
|
||||
static void
|
||||
md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen)
|
||||
{
|
||||
if( hd->count == 64 ) { /* flush the buffer */
|
||||
transform( hd, hd->buf );
|
||||
burn_stack (80+6*sizeof(void*));
|
||||
hd->count = 0;
|
||||
hd->nblocks++;
|
||||
}
|
||||
if( !inbuf )
|
||||
return;
|
||||
if( hd->count ) {
|
||||
for( ; inlen && hd->count < 64; inlen-- )
|
||||
hd->buf[hd->count++] = *inbuf++;
|
||||
md5_write( hd, NULL, 0 );
|
||||
if( !inlen )
|
||||
return;
|
||||
}
|
||||
|
||||
while( inlen >= 64 ) {
|
||||
transform( hd, inbuf );
|
||||
hd->count = 0;
|
||||
hd->nblocks++;
|
||||
inlen -= 64;
|
||||
inbuf += 64;
|
||||
}
|
||||
burn_stack (80+6*sizeof(void*));
|
||||
for( ; inlen && hd->count < 64; inlen-- )
|
||||
hd->buf[hd->count++] = *inbuf++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The routine final terminates the message-digest computation and
|
||||
* ends with the desired message digest in mdContext->digest[0...15].
|
||||
* The handle is prepared for a new MD5 cycle.
|
||||
* Returns 16 bytes representing the digest.
|
||||
*/
|
||||
|
||||
static void
|
||||
md5_final( MD5_CONTEXT *hd )
|
||||
{
|
||||
u32 t, msb, lsb;
|
||||
byte *p;
|
||||
|
||||
md5_write(hd, NULL, 0); /* flush */;
|
||||
|
||||
t = hd->nblocks;
|
||||
/* multiply by 64 to make a byte count */
|
||||
lsb = t << 6;
|
||||
msb = t >> 26;
|
||||
/* add the count */
|
||||
t = lsb;
|
||||
if( (lsb += hd->count) < t )
|
||||
msb++;
|
||||
/* multiply by 8 to make a bit count */
|
||||
t = lsb;
|
||||
lsb <<= 3;
|
||||
msb <<= 3;
|
||||
msb |= t >> 29;
|
||||
|
||||
if( hd->count < 56 ) { /* enough room */
|
||||
hd->buf[hd->count++] = 0x80; /* pad */
|
||||
while( hd->count < 56 )
|
||||
hd->buf[hd->count++] = 0; /* pad */
|
||||
}
|
||||
else { /* need one extra block */
|
||||
hd->buf[hd->count++] = 0x80; /* pad character */
|
||||
while( hd->count < 64 )
|
||||
hd->buf[hd->count++] = 0;
|
||||
md5_write(hd, NULL, 0); /* flush */;
|
||||
memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
|
||||
}
|
||||
/* append the 64 bit count */
|
||||
hd->buf[56] = lsb ;
|
||||
hd->buf[57] = lsb >> 8;
|
||||
hd->buf[58] = lsb >> 16;
|
||||
hd->buf[59] = lsb >> 24;
|
||||
hd->buf[60] = msb ;
|
||||
hd->buf[61] = msb >> 8;
|
||||
hd->buf[62] = msb >> 16;
|
||||
hd->buf[63] = msb >> 24;
|
||||
transform( hd, hd->buf );
|
||||
burn_stack (80+6*sizeof(void*));
|
||||
|
||||
p = hd->buf;
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
#define X(a) do { *p++ = hd-> a ; *p++ = hd-> a >> 8; \
|
||||
*p++ = hd-> a >> 16; *p++ = hd-> a >> 24; } while(0)
|
||||
#else /* little endian */
|
||||
#define X(a) do { *(u32*)p = hd-> a ; p += 4; } while(0)
|
||||
#endif
|
||||
X(A);
|
||||
X(B);
|
||||
X(C);
|
||||
X(D);
|
||||
#undef X
|
||||
|
||||
}
|
||||
|
||||
static byte *
|
||||
md5_read( MD5_CONTEXT *hd )
|
||||
{
|
||||
return hd->buf;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
static const char *
|
||||
md5_get_info( int algo, size_t *contextsize,
|
||||
byte **r_asnoid, int *r_asnlen, int *r_mdlen,
|
||||
void (**r_init)( void *c ),
|
||||
void (**r_write)( void *c, byte *buf, size_t nbytes ),
|
||||
void (**r_final)( void *c ),
|
||||
byte *(**r_read)( void *c )
|
||||
)
|
||||
{
|
||||
static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */
|
||||
{ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
|
||||
0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
|
||||
|
||||
if( algo != 1 )
|
||||
return NULL;
|
||||
|
||||
*contextsize = sizeof(MD5_CONTEXT);
|
||||
*r_asnoid = asn;
|
||||
*r_asnlen = DIM(asn);
|
||||
*r_mdlen = 16;
|
||||
*(void (**)(MD5_CONTEXT *))r_init = md5_init;
|
||||
*(void (**)(MD5_CONTEXT *, byte*, size_t))r_write = md5_write;
|
||||
*(void (**)(MD5_CONTEXT *))r_final = md5_final;
|
||||
*(byte *(**)(MD5_CONTEXT *))r_read = md5_read;
|
||||
|
||||
return "MD5";
|
||||
}
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "MD5 ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int value;
|
||||
void (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 10, 1, 0, (void(*)(void))md5_get_info },
|
||||
{ 11, 1, 1 },
|
||||
};
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if( i >= DIM(func_table) || i < 0 )
|
||||
return NULL;
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
switch( *class ) {
|
||||
case 11: case 21: case 31: ret = &func_table[i].value; break;
|
||||
#ifndef __riscos__
|
||||
default: ret = func_table[i].func; break;
|
||||
#else /* __riscos__ */
|
||||
default: ret = (void *) func_table[i].func; break;
|
||||
#endif /* __riscos__ */
|
||||
}
|
||||
i++;
|
||||
} while( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
md5_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* end of file */
|
|
@ -0,0 +1,583 @@
|
|||
/* primegen.c - prime number generator
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* ***********************************************************************
|
||||
* The algorithm used to generate practically save primes is due to
|
||||
* Lim and Lee as described in the CRYPTO '97 proceedings (ISBN3540633847)
|
||||
* page 260.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
|
||||
static int no_of_small_prime_numbers;
|
||||
static MPI gen_prime( unsigned nbits, int mode, int randomlevel );
|
||||
static int check_prime( MPI prime, MPI val_2 );
|
||||
static int is_prime( MPI n, int steps, int *count );
|
||||
static void m_out_of_n( char *array, int m, int n );
|
||||
|
||||
static void (*progress_cb) ( void *, int );
|
||||
static void *progress_cb_data;
|
||||
|
||||
void
|
||||
register_primegen_progress ( void (*cb)( void *, int), void *cb_data )
|
||||
{
|
||||
progress_cb = cb;
|
||||
progress_cb_data = cb_data;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
progress( int c )
|
||||
{
|
||||
if ( progress_cb )
|
||||
progress_cb ( progress_cb_data, c );
|
||||
else
|
||||
fputc( c, stderr );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a prime number (stored in secure memory)
|
||||
*/
|
||||
MPI
|
||||
generate_secret_prime( unsigned nbits )
|
||||
{
|
||||
MPI prime;
|
||||
|
||||
prime = gen_prime( nbits, 1, 2 );
|
||||
progress('\n');
|
||||
return prime;
|
||||
}
|
||||
|
||||
MPI
|
||||
generate_public_prime( unsigned nbits )
|
||||
{
|
||||
MPI prime;
|
||||
|
||||
prime = gen_prime( nbits, 0, 2 );
|
||||
progress('\n');
|
||||
return prime;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* We do not need to use the strongest RNG because we gain no extra
|
||||
* security from it - The prime number is public and we could also
|
||||
* offer the factors for those who are willing to check that it is
|
||||
* indeed a strong prime.
|
||||
*
|
||||
* mode 0: Standard
|
||||
* 1: Make sure that at least one factor is of size qbits.
|
||||
*/
|
||||
MPI
|
||||
generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
|
||||
MPI g, MPI **ret_factors )
|
||||
{
|
||||
int n; /* number of factors */
|
||||
int m; /* number of primes in pool */
|
||||
unsigned fbits; /* length of prime factors */
|
||||
MPI *factors; /* current factors */
|
||||
MPI *pool; /* pool of primes */
|
||||
MPI q; /* first prime factor (variable)*/
|
||||
MPI prime; /* prime test value */
|
||||
MPI q_factor; /* used for mode 1 */
|
||||
byte *perms = NULL;
|
||||
int i, j;
|
||||
int count1, count2;
|
||||
unsigned nprime;
|
||||
unsigned req_qbits = qbits; /* the requested q bits size */
|
||||
MPI val_2 = mpi_alloc_set_ui( 2 );
|
||||
|
||||
/* find number of needed prime factors */
|
||||
for(n=1; (pbits - qbits - 1) / n >= qbits; n++ )
|
||||
;
|
||||
n--;
|
||||
if( !n || (mode==1 && n < 2) )
|
||||
log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits );
|
||||
if( mode == 1 ) {
|
||||
n--;
|
||||
fbits = (pbits - 2*req_qbits -1) / n;
|
||||
qbits = pbits - req_qbits - n*fbits;
|
||||
}
|
||||
else {
|
||||
fbits = (pbits - req_qbits -1) / n;
|
||||
qbits = pbits - n*fbits;
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
|
||||
pbits, req_qbits, qbits, fbits, n );
|
||||
prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB );
|
||||
q = gen_prime( qbits, 0, 0 );
|
||||
q_factor = mode==1? gen_prime( req_qbits, 0, 0 ) : NULL;
|
||||
|
||||
/* allocate an array to hold the factors + 2 for later usage */
|
||||
factors = m_alloc_clear( (n+2) * sizeof *factors );
|
||||
|
||||
/* make a pool of 3n+5 primes (this is an arbitrary value) */
|
||||
m = n*3+5;
|
||||
if( mode == 1 )
|
||||
m += 5; /* need some more for DSA */
|
||||
if( m < 25 )
|
||||
m = 25;
|
||||
pool = m_alloc_clear( m * sizeof *pool );
|
||||
|
||||
/* permutate over the pool of primes */
|
||||
count1=count2=0;
|
||||
do {
|
||||
next_try:
|
||||
if( !perms ) {
|
||||
/* allocate new primes */
|
||||
for(i=0; i < m; i++ ) {
|
||||
mpi_free(pool[i]);
|
||||
pool[i] = NULL;
|
||||
}
|
||||
/* init m_out_of_n() */
|
||||
perms = m_alloc_clear( m );
|
||||
for(i=0; i < n; i++ ) {
|
||||
perms[i] = 1;
|
||||
pool[i] = gen_prime( fbits, 0, 0 );
|
||||
factors[i] = pool[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_out_of_n( perms, n, m );
|
||||
for(i=j=0; i < m && j < n ; i++ )
|
||||
if( perms[i] ) {
|
||||
if( !pool[i] )
|
||||
pool[i] = gen_prime( fbits, 0, 0 );
|
||||
factors[j++] = pool[i];
|
||||
}
|
||||
if( i == n ) {
|
||||
m_free(perms); perms = NULL;
|
||||
progress('!');
|
||||
goto next_try; /* allocate new primes */
|
||||
}
|
||||
}
|
||||
|
||||
mpi_set( prime, q );
|
||||
mpi_mul_ui( prime, prime, 2 );
|
||||
if( mode == 1 )
|
||||
mpi_mul( prime, prime, q_factor );
|
||||
for(i=0; i < n; i++ )
|
||||
mpi_mul( prime, prime, factors[i] );
|
||||
mpi_add_ui( prime, prime, 1 );
|
||||
nprime = mpi_get_nbits(prime);
|
||||
if( nprime < pbits ) {
|
||||
if( ++count1 > 20 ) {
|
||||
count1 = 0;
|
||||
qbits++;
|
||||
progress('>');
|
||||
mpi_free (q);
|
||||
q = gen_prime( qbits, 0, 0 );
|
||||
goto next_try;
|
||||
}
|
||||
}
|
||||
else
|
||||
count1 = 0;
|
||||
if( nprime > pbits ) {
|
||||
if( ++count2 > 20 ) {
|
||||
count2 = 0;
|
||||
qbits--;
|
||||
progress('<');
|
||||
mpi_free (q);
|
||||
q = gen_prime( qbits, 0, 0 );
|
||||
goto next_try;
|
||||
}
|
||||
}
|
||||
else
|
||||
count2 = 0;
|
||||
} while( !(nprime == pbits && check_prime( prime, val_2 )) );
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
progress('\n');
|
||||
log_mpidump( "prime : ", prime );
|
||||
log_mpidump( "factor q: ", q );
|
||||
if( mode == 1 )
|
||||
log_mpidump( "factor q0: ", q_factor );
|
||||
for(i=0; i < n; i++ )
|
||||
log_mpidump( "factor pi: ", factors[i] );
|
||||
log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
|
||||
if( mode == 1 )
|
||||
fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) );
|
||||
for(i=0; i < n; i++ )
|
||||
fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
|
||||
progress('\n');
|
||||
}
|
||||
|
||||
if( ret_factors ) { /* caller wants the factors */
|
||||
*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
|
||||
i = 0;
|
||||
if( mode == 1 ) {
|
||||
(*ret_factors)[i++] = mpi_copy( q_factor );
|
||||
for(; i <= n; i++ )
|
||||
(*ret_factors)[i] = mpi_copy( factors[i] );
|
||||
}
|
||||
else {
|
||||
for(; i < n; i++ )
|
||||
(*ret_factors)[i] = mpi_copy( factors[i] );
|
||||
}
|
||||
}
|
||||
|
||||
if( g ) { /* create a generator (start with 3)*/
|
||||
MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) );
|
||||
MPI b = mpi_alloc( mpi_get_nlimbs(prime) );
|
||||
MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) );
|
||||
|
||||
if( mode == 1 )
|
||||
BUG(); /* not yet implemented */
|
||||
factors[n] = q;
|
||||
factors[n+1] = mpi_alloc_set_ui(2);
|
||||
mpi_sub_ui( pmin1, prime, 1 );
|
||||
mpi_set_ui(g,2);
|
||||
do {
|
||||
mpi_add_ui(g, g, 1);
|
||||
if( DBG_CIPHER ) {
|
||||
log_debug("checking g: ");
|
||||
mpi_print( stderr, g, 1 );
|
||||
}
|
||||
else
|
||||
progress('^');
|
||||
for(i=0; i < n+2; i++ ) {
|
||||
/*fputc('~', stderr);*/
|
||||
mpi_fdiv_q(tmp, pmin1, factors[i] );
|
||||
/* (no mpi_pow(), but it is okay to use this with mod prime) */
|
||||
mpi_powm(b, g, tmp, prime );
|
||||
if( !mpi_cmp_ui(b, 1) )
|
||||
break;
|
||||
}
|
||||
if( DBG_CIPHER )
|
||||
progress('\n');
|
||||
} while( i < n+2 );
|
||||
mpi_free(factors[n+1]);
|
||||
mpi_free(tmp);
|
||||
mpi_free(b);
|
||||
mpi_free(pmin1);
|
||||
}
|
||||
if( !DBG_CIPHER )
|
||||
progress('\n');
|
||||
|
||||
m_free( factors ); /* (factors are shallow copies) */
|
||||
for(i=0; i < m; i++ )
|
||||
mpi_free( pool[i] );
|
||||
m_free( pool );
|
||||
m_free(perms);
|
||||
mpi_free(val_2);
|
||||
mpi_free(q);
|
||||
return prime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static MPI
|
||||
gen_prime( unsigned nbits, int secret, int randomlevel )
|
||||
{
|
||||
unsigned nlimbs;
|
||||
MPI prime, ptest, pminus1, val_2, val_3, result;
|
||||
int i;
|
||||
unsigned x, step;
|
||||
int count1, count2;
|
||||
int *mods;
|
||||
|
||||
if( 0 && DBG_CIPHER )
|
||||
log_debug("generate a prime of %u bits ", nbits );
|
||||
|
||||
if( !no_of_small_prime_numbers ) {
|
||||
for(i=0; small_prime_numbers[i]; i++ )
|
||||
no_of_small_prime_numbers++;
|
||||
}
|
||||
mods = m_alloc( no_of_small_prime_numbers * sizeof *mods );
|
||||
/* make nbits fit into MPI implementation */
|
||||
nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB;
|
||||
val_2 = mpi_alloc_set_ui( 2 );
|
||||
val_3 = mpi_alloc_set_ui( 3);
|
||||
prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs );
|
||||
result = mpi_alloc_like( prime );
|
||||
pminus1= mpi_alloc_like( prime );
|
||||
ptest = mpi_alloc_like( prime );
|
||||
count1 = count2 = 0;
|
||||
for(;;) { /* try forvever */
|
||||
int dotcount=0;
|
||||
|
||||
/* generate a random number */
|
||||
{ char *p = get_random_bits( nbits, randomlevel, secret );
|
||||
mpi_set_buffer( prime, p, (nbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
/* Set high order bit to 1, set low order bit to 0.
|
||||
If we are generating a secret prime we are most probably
|
||||
doing that for RSA, to make sure that the modulus does have
|
||||
the requested keysize we set the 2 high order bits */
|
||||
mpi_set_highbit( prime, nbits-1 );
|
||||
if (secret)
|
||||
mpi_set_bit (prime, nbits-2);
|
||||
mpi_set_bit( prime, 0 );
|
||||
|
||||
/* calculate all remainders */
|
||||
for(i=0; (x = small_prime_numbers[i]); i++ )
|
||||
mods[i] = mpi_fdiv_r_ui(NULL, prime, x);
|
||||
|
||||
/* now try some primes starting with prime */
|
||||
for(step=0; step < 20000; step += 2 ) {
|
||||
/* check against all the small primes we have in mods */
|
||||
count1++;
|
||||
for(i=0; (x = small_prime_numbers[i]); i++ ) {
|
||||
while( mods[i] + step >= x )
|
||||
mods[i] -= x;
|
||||
if( !(mods[i] + step) )
|
||||
break;
|
||||
}
|
||||
if( x )
|
||||
continue; /* found a multiple of an already known prime */
|
||||
|
||||
mpi_add_ui( ptest, prime, step );
|
||||
|
||||
/* do a faster Fermat test */
|
||||
count2++;
|
||||
mpi_sub_ui( pminus1, ptest, 1);
|
||||
mpi_powm( result, val_2, pminus1, ptest );
|
||||
if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */
|
||||
/* perform stronger tests */
|
||||
if( is_prime(ptest, 5, &count2 ) ) {
|
||||
if( !mpi_test_bit( ptest, nbits-1 ) ) {
|
||||
progress('\n');
|
||||
log_debug("overflow in prime generation\n");
|
||||
break; /* step loop, continue with a new prime */
|
||||
}
|
||||
|
||||
mpi_free(val_2);
|
||||
mpi_free(val_3);
|
||||
mpi_free(result);
|
||||
mpi_free(pminus1);
|
||||
mpi_free(prime);
|
||||
m_free(mods);
|
||||
return ptest;
|
||||
}
|
||||
}
|
||||
if( ++dotcount == 10 ) {
|
||||
progress('.');
|
||||
dotcount = 0;
|
||||
}
|
||||
}
|
||||
progress(':'); /* restart with a new random value */
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* Returns: true if this may be a prime
|
||||
*/
|
||||
static int
|
||||
check_prime( MPI prime, MPI val_2 )
|
||||
{
|
||||
int i;
|
||||
unsigned x;
|
||||
int count=0;
|
||||
|
||||
/* check against small primes */
|
||||
for(i=0; (x = small_prime_numbers[i]); i++ ) {
|
||||
if( mpi_divisible_ui( prime, x ) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* a quick fermat test */
|
||||
{
|
||||
MPI result = mpi_alloc_like( prime );
|
||||
MPI pminus1 = mpi_alloc_like( prime );
|
||||
mpi_sub_ui( pminus1, prime, 1);
|
||||
mpi_powm( result, val_2, pminus1, prime );
|
||||
mpi_free( pminus1 );
|
||||
if( mpi_cmp_ui( result, 1 ) ) { /* if composite */
|
||||
mpi_free( result );
|
||||
progress('.');
|
||||
return 0;
|
||||
}
|
||||
mpi_free( result );
|
||||
}
|
||||
|
||||
/* perform stronger tests */
|
||||
if( is_prime(prime, 5, &count ) )
|
||||
return 1; /* is probably a prime */
|
||||
progress('.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return true if n is probably a prime
|
||||
*/
|
||||
static int
|
||||
is_prime( MPI n, int steps, int *count )
|
||||
{
|
||||
MPI x = mpi_alloc( mpi_get_nlimbs( n ) );
|
||||
MPI y = mpi_alloc( mpi_get_nlimbs( n ) );
|
||||
MPI z = mpi_alloc( mpi_get_nlimbs( n ) );
|
||||
MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) );
|
||||
MPI a2 = mpi_alloc_set_ui( 2 );
|
||||
MPI q;
|
||||
unsigned i, j, k;
|
||||
int rc = 0;
|
||||
unsigned nbits = mpi_get_nbits( n );
|
||||
|
||||
mpi_sub_ui( nminus1, n, 1 );
|
||||
|
||||
/* find q and k, so that n = 1 + 2^k * q */
|
||||
q = mpi_copy( nminus1 );
|
||||
k = mpi_trailing_zeros( q );
|
||||
mpi_tdiv_q_2exp(q, q, k);
|
||||
|
||||
for(i=0 ; i < steps; i++ ) {
|
||||
++*count;
|
||||
if( !i ) {
|
||||
mpi_set_ui( x, 2 );
|
||||
}
|
||||
else {
|
||||
/*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/
|
||||
{ char *p = get_random_bits( nbits, 0, 0 );
|
||||
mpi_set_buffer( x, p, (nbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
}
|
||||
/* make sure that the number is smaller than the prime
|
||||
* and keep the randomness of the high bit */
|
||||
if( mpi_test_bit( x, nbits-2 ) ) {
|
||||
mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */
|
||||
}
|
||||
else {
|
||||
mpi_set_highbit( x, nbits-2 );
|
||||
mpi_clear_bit( x, nbits-2 );
|
||||
}
|
||||
assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 );
|
||||
}
|
||||
mpi_powm( y, x, q, n);
|
||||
if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) {
|
||||
for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) {
|
||||
mpi_powm(y, y, a2, n);
|
||||
if( !mpi_cmp_ui( y, 1 ) )
|
||||
goto leave; /* not a prime */
|
||||
}
|
||||
if( mpi_cmp( y, nminus1 ) )
|
||||
goto leave; /* not a prime */
|
||||
}
|
||||
progress('+');
|
||||
}
|
||||
rc = 1; /* may be a prime */
|
||||
|
||||
leave:
|
||||
mpi_free( x );
|
||||
mpi_free( y );
|
||||
mpi_free( z );
|
||||
mpi_free( nminus1 );
|
||||
mpi_free( q );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
m_out_of_n( char *array, int m, int n )
|
||||
{
|
||||
int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0;
|
||||
|
||||
if( !m || m >= n )
|
||||
return;
|
||||
|
||||
if( m == 1 ) { /* special case */
|
||||
for(i=0; i < n; i++ )
|
||||
if( array[i] ) {
|
||||
array[i++] = 0;
|
||||
if( i >= n )
|
||||
i = 0;
|
||||
array[i] = 1;
|
||||
return;
|
||||
}
|
||||
BUG();
|
||||
}
|
||||
|
||||
for(j=1; j < n; j++ ) {
|
||||
if( array[n-1] == array[n-j-1] )
|
||||
continue;
|
||||
j1 = j;
|
||||
break;
|
||||
}
|
||||
|
||||
if( m & 1 ) { /* m is odd */
|
||||
if( array[n-1] ) {
|
||||
if( j1 & 1 ) {
|
||||
k1 = n - j1;
|
||||
k2 = k1+2;
|
||||
if( k2 > n )
|
||||
k2 = n;
|
||||
goto leave;
|
||||
}
|
||||
goto scan;
|
||||
}
|
||||
k2 = n - j1 - 1;
|
||||
if( k2 == 0 ) {
|
||||
k1 = i;
|
||||
k2 = n - j1;
|
||||
}
|
||||
else if( array[k2] && array[k2-1] )
|
||||
k1 = n;
|
||||
else
|
||||
k1 = k2 + 1;
|
||||
}
|
||||
else { /* m is even */
|
||||
if( !array[n-1] ) {
|
||||
k1 = n - j1;
|
||||
k2 = k1 + 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( !(j1 & 1) ) {
|
||||
k1 = n - j1;
|
||||
k2 = k1+2;
|
||||
if( k2 > n )
|
||||
k2 = n;
|
||||
goto leave;
|
||||
}
|
||||
scan:
|
||||
jp = n - j1 - 1;
|
||||
for(i=1; i <= jp; i++ ) {
|
||||
i1 = jp + 2 - i;
|
||||
if( array[i1-1] ) {
|
||||
if( array[i1-2] ) {
|
||||
k1 = i1 - 1;
|
||||
k2 = n - j1;
|
||||
}
|
||||
else {
|
||||
k1 = i1 - 1;
|
||||
k2 = n + 1 - j1;
|
||||
}
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
k1 = 1;
|
||||
k2 = n + 1 - m;
|
||||
}
|
||||
leave:
|
||||
array[k1-1] = !array[k1-1];
|
||||
array[k2-1] = !array[k2-1];
|
||||
}
|
||||
|
|
@ -0,0 +1,618 @@
|
|||
/* pubkey.c - pubkey dispatcher
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "errors.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "elgamal.h"
|
||||
#include "dsa.h"
|
||||
#include "rsa.h"
|
||||
#include "dynload.h"
|
||||
|
||||
|
||||
#define TABLE_SIZE 10
|
||||
|
||||
struct pubkey_table_s {
|
||||
const char *name;
|
||||
int algo;
|
||||
int npkey;
|
||||
int nskey;
|
||||
int nenc;
|
||||
int nsig;
|
||||
int use;
|
||||
int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
|
||||
int (*check_secret_key)( int algo, MPI *skey );
|
||||
int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey );
|
||||
int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey );
|
||||
int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey );
|
||||
int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev );
|
||||
unsigned (*get_nbits)( int algo, MPI *pkey );
|
||||
};
|
||||
|
||||
static struct pubkey_table_s pubkey_table[TABLE_SIZE];
|
||||
static int disabled_algos[TABLE_SIZE];
|
||||
|
||||
|
||||
static int
|
||||
dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
{ log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
|
||||
|
||||
static int
|
||||
dummy_check_secret_key( int algo, MPI *skey )
|
||||
{ log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
|
||||
|
||||
static int
|
||||
dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
{ log_bug("no encrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
|
||||
|
||||
static int
|
||||
dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
|
||||
{ log_bug("no decrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
|
||||
|
||||
static int
|
||||
dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
{ log_bug("no sign() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
|
||||
|
||||
static int
|
||||
dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev )
|
||||
{ log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
|
||||
|
||||
static unsigned
|
||||
dummy_get_nbits( int algo, MPI *pkey )
|
||||
{ log_bug("no get_nbits() for %d\n", algo ); return 0; }
|
||||
|
||||
|
||||
/****************
|
||||
* Put the static entries into the table.
|
||||
* This is out constructor function which fill the table
|
||||
* of algorithms with the one we have statically linked.
|
||||
*/
|
||||
static void
|
||||
setup_pubkey_table(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL;
|
||||
pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
&pubkey_table[i].nskey,
|
||||
&pubkey_table[i].nenc,
|
||||
&pubkey_table[i].nsig,
|
||||
&pubkey_table[i].use );
|
||||
pubkey_table[i].generate = elg_generate;
|
||||
pubkey_table[i].check_secret_key = elg_check_secret_key;
|
||||
pubkey_table[i].encrypt = elg_encrypt;
|
||||
pubkey_table[i].decrypt = elg_decrypt;
|
||||
pubkey_table[i].sign = elg_sign;
|
||||
pubkey_table[i].verify = elg_verify;
|
||||
pubkey_table[i].get_nbits = elg_get_nbits;
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E;
|
||||
pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
&pubkey_table[i].nskey,
|
||||
&pubkey_table[i].nenc,
|
||||
&pubkey_table[i].nsig,
|
||||
&pubkey_table[i].use );
|
||||
pubkey_table[i].generate = elg_generate;
|
||||
pubkey_table[i].check_secret_key = elg_check_secret_key;
|
||||
pubkey_table[i].encrypt = elg_encrypt;
|
||||
pubkey_table[i].decrypt = elg_decrypt;
|
||||
pubkey_table[i].sign = elg_sign;
|
||||
pubkey_table[i].verify = elg_verify;
|
||||
pubkey_table[i].get_nbits = elg_get_nbits;
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_DSA;
|
||||
pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
&pubkey_table[i].nskey,
|
||||
&pubkey_table[i].nenc,
|
||||
&pubkey_table[i].nsig,
|
||||
&pubkey_table[i].use );
|
||||
pubkey_table[i].generate = dsa_generate;
|
||||
pubkey_table[i].check_secret_key = dsa_check_secret_key;
|
||||
pubkey_table[i].encrypt = dummy_encrypt;
|
||||
pubkey_table[i].decrypt = dummy_decrypt;
|
||||
pubkey_table[i].sign = dsa_sign;
|
||||
pubkey_table[i].verify = dsa_verify;
|
||||
pubkey_table[i].get_nbits = dsa_get_nbits;
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_RSA;
|
||||
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
&pubkey_table[i].nskey,
|
||||
&pubkey_table[i].nenc,
|
||||
&pubkey_table[i].nsig,
|
||||
&pubkey_table[i].use );
|
||||
pubkey_table[i].generate = rsa_generate;
|
||||
pubkey_table[i].check_secret_key = rsa_check_secret_key;
|
||||
pubkey_table[i].encrypt = rsa_encrypt;
|
||||
pubkey_table[i].decrypt = rsa_decrypt;
|
||||
pubkey_table[i].sign = rsa_sign;
|
||||
pubkey_table[i].verify = rsa_verify;
|
||||
pubkey_table[i].get_nbits = rsa_get_nbits;
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_RSA_E;
|
||||
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
&pubkey_table[i].nskey,
|
||||
&pubkey_table[i].nenc,
|
||||
&pubkey_table[i].nsig,
|
||||
&pubkey_table[i].use );
|
||||
pubkey_table[i].generate = rsa_generate;
|
||||
pubkey_table[i].check_secret_key = rsa_check_secret_key;
|
||||
pubkey_table[i].encrypt = rsa_encrypt;
|
||||
pubkey_table[i].decrypt = rsa_decrypt;
|
||||
pubkey_table[i].sign = dummy_sign;
|
||||
pubkey_table[i].verify = dummy_verify;
|
||||
pubkey_table[i].get_nbits = rsa_get_nbits;
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
pubkey_table[i].algo = PUBKEY_ALGO_RSA_S;
|
||||
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
|
||||
&pubkey_table[i].npkey,
|
||||
&pubkey_table[i].nskey,
|
||||
&pubkey_table[i].nenc,
|
||||
&pubkey_table[i].nsig,
|
||||
&pubkey_table[i].use );
|
||||
pubkey_table[i].generate = rsa_generate;
|
||||
pubkey_table[i].check_secret_key = rsa_check_secret_key;
|
||||
pubkey_table[i].encrypt = dummy_encrypt;
|
||||
pubkey_table[i].decrypt = dummy_decrypt;
|
||||
pubkey_table[i].sign = rsa_sign;
|
||||
pubkey_table[i].verify = rsa_verify;
|
||||
pubkey_table[i].get_nbits = rsa_get_nbits;
|
||||
if( !pubkey_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
|
||||
for( ; i < TABLE_SIZE; i++ )
|
||||
pubkey_table[i].name = NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Try to load all modules and return true if new modules are available
|
||||
*/
|
||||
static int
|
||||
load_pubkey_modules(void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
static int done = 0;
|
||||
void *context = NULL;
|
||||
struct pubkey_table_s *ct;
|
||||
int ct_idx;
|
||||
int i;
|
||||
const char *name;
|
||||
int any = 0;
|
||||
|
||||
|
||||
if( !initialized ) {
|
||||
cipher_modules_constructor();
|
||||
setup_pubkey_table();
|
||||
initialized = 1;
|
||||
return 1;
|
||||
}
|
||||
if( done )
|
||||
return 0;
|
||||
done = 1;
|
||||
for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
|
||||
if( !ct->name )
|
||||
break;
|
||||
}
|
||||
if( ct_idx >= TABLE_SIZE-1 )
|
||||
BUG(); /* table already full */
|
||||
/* now load all extensions */
|
||||
while( (name = enum_gnupgext_pubkeys( &context, &ct->algo,
|
||||
&ct->npkey, &ct->nskey, &ct->nenc,
|
||||
&ct->nsig, &ct->use,
|
||||
&ct->generate,
|
||||
&ct->check_secret_key,
|
||||
&ct->encrypt,
|
||||
&ct->decrypt,
|
||||
&ct->sign,
|
||||
&ct->verify,
|
||||
&ct->get_nbits )) ) {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == ct->algo )
|
||||
break;
|
||||
if( pubkey_table[i].name ) {
|
||||
log_info("skipping pubkey %d: already loaded\n", ct->algo );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !ct->generate ) ct->generate = dummy_generate;
|
||||
if( !ct->check_secret_key ) ct->check_secret_key =
|
||||
dummy_check_secret_key;
|
||||
if( !ct->encrypt ) ct->encrypt = dummy_encrypt;
|
||||
if( !ct->decrypt ) ct->decrypt = dummy_decrypt;
|
||||
if( !ct->sign ) ct->sign = dummy_sign;
|
||||
if( !ct->verify ) ct->verify = dummy_verify;
|
||||
if( !ct->get_nbits ) ct->get_nbits= dummy_get_nbits;
|
||||
/* put it into the table */
|
||||
if( g10_opt_verbose > 1 )
|
||||
log_info("loaded pubkey %d (%s)\n", ct->algo, name);
|
||||
ct->name = name;
|
||||
ct_idx++;
|
||||
ct++;
|
||||
any = 1;
|
||||
/* check whether there are more available table slots */
|
||||
if( ct_idx >= TABLE_SIZE-1 ) {
|
||||
log_info("pubkey table full; ignoring other extensions\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
return any;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Map a string to the pubkey algo
|
||||
*/
|
||||
int
|
||||
string_to_pubkey_algo( const char *string )
|
||||
{
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
do {
|
||||
for(i=0; (s=pubkey_table[i].name); i++ )
|
||||
if( !ascii_strcasecmp( s, string ) )
|
||||
return pubkey_table[i].algo;
|
||||
} while( load_pubkey_modules() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Map a pubkey algo to a string
|
||||
*/
|
||||
const char *
|
||||
pubkey_algo_to_string( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].name;
|
||||
} while( load_pubkey_modules() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
disable_pubkey_algo( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < DIM(disabled_algos); i++ ) {
|
||||
if( !disabled_algos[i] || disabled_algos[i] == algo ) {
|
||||
disabled_algos[i] = algo;
|
||||
return;
|
||||
}
|
||||
}
|
||||
log_fatal("can't disable pubkey algo %d: table full\n", algo );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
check_pubkey_algo( int algo )
|
||||
{
|
||||
return check_pubkey_algo2( algo, 0 );
|
||||
}
|
||||
|
||||
/****************
|
||||
* a use of 0 means: don't care
|
||||
*/
|
||||
int
|
||||
check_pubkey_algo2( int algo, unsigned use )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo ) {
|
||||
if( (use & PUBKEY_USAGE_SIG)
|
||||
&& !(pubkey_table[i].use & PUBKEY_USAGE_SIG) )
|
||||
return G10ERR_WR_PUBKEY_ALGO;
|
||||
if( (use & PUBKEY_USAGE_ENC)
|
||||
&& !(pubkey_table[i].use & PUBKEY_USAGE_ENC) )
|
||||
return G10ERR_WR_PUBKEY_ALGO;
|
||||
|
||||
for(i=0; i < DIM(disabled_algos); i++ ) {
|
||||
if( disabled_algos[i] == algo )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
}
|
||||
return 0; /* okay */
|
||||
}
|
||||
} while( load_pubkey_modules() );
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Return the number of public key material numbers
|
||||
*/
|
||||
int
|
||||
pubkey_get_npkey( int algo )
|
||||
{
|
||||
int i;
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].npkey;
|
||||
} while( load_pubkey_modules() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return the number of secret key material numbers
|
||||
*/
|
||||
int
|
||||
pubkey_get_nskey( int algo )
|
||||
{
|
||||
int i;
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].nskey;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 6; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return the number of signature material numbers
|
||||
*/
|
||||
int
|
||||
pubkey_get_nsig( int algo )
|
||||
{
|
||||
int i;
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].nsig;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 1; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return the number of encryption material numbers
|
||||
*/
|
||||
int
|
||||
pubkey_get_nenc( int algo )
|
||||
{
|
||||
int i;
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return pubkey_table[i].nenc;
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* special hack, so that we are able to */
|
||||
return 1; /* see the RSA keyids */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Get the number of nbits from the public key
|
||||
*/
|
||||
unsigned
|
||||
pubkey_nbits( int algo, MPI *pkey )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return (*pubkey_table[i].get_nbits)( algo, pkey );
|
||||
} while( load_pubkey_modules() );
|
||||
if( is_RSA(algo) ) /* we always wanna see the length of a key :-) */
|
||||
return mpi_get_nbits( pkey[0] );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return (*pubkey_table[i].generate)( algo, nbits,
|
||||
skey, retfactors );
|
||||
} while( load_pubkey_modules() );
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pubkey_check_secret_key( int algo, MPI *skey )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo )
|
||||
return (*pubkey_table[i].check_secret_key)( algo, skey );
|
||||
} while( load_pubkey_modules() );
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* This is the interface to the public key encryption.
|
||||
* Encrypt DATA with PKEY and put it into RESARR which
|
||||
* should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
|
||||
* algorithm allows this - check with pubkey_get_nenc() )
|
||||
*/
|
||||
int
|
||||
pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
log_debug("pubkey_encrypt: algo=%d\n", algo );
|
||||
for(i=0; i < pubkey_get_npkey(algo); i++ )
|
||||
log_mpidump(" pkey:", pkey[i] );
|
||||
log_mpidump(" data:", data );
|
||||
}
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo ) {
|
||||
rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
|
||||
goto ready;
|
||||
}
|
||||
} while( load_pubkey_modules() );
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
ready:
|
||||
if( !rc && DBG_CIPHER ) {
|
||||
for(i=0; i < pubkey_get_nenc(algo); i++ )
|
||||
log_mpidump(" encr:", resarr[i] );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* This is the interface to the public key decryption.
|
||||
* ALGO gives the algorithm to use and this implicitly determines
|
||||
* the size of the arrays.
|
||||
* result is a pointer to a mpi variable which will receive a
|
||||
* newly allocated mpi or NULL in case of an error.
|
||||
*/
|
||||
int
|
||||
pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
*result = NULL; /* so the caller can always do an mpi_free */
|
||||
if( DBG_CIPHER ) {
|
||||
log_debug("pubkey_decrypt: algo=%d\n", algo );
|
||||
for(i=0; i < pubkey_get_nskey(algo); i++ )
|
||||
log_mpidump(" skey:", skey[i] );
|
||||
for(i=0; i < pubkey_get_nenc(algo); i++ )
|
||||
log_mpidump(" data:", data[i] );
|
||||
}
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo ) {
|
||||
rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
|
||||
goto ready;
|
||||
}
|
||||
} while( load_pubkey_modules() );
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
ready:
|
||||
if( !rc && DBG_CIPHER ) {
|
||||
log_mpidump(" plain:", *result );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* This is the interface to the public key signing.
|
||||
* Sign data with skey and put the result into resarr which
|
||||
* should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
|
||||
* algorithm allows this - check with pubkey_get_nsig() )
|
||||
*/
|
||||
int
|
||||
pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
log_debug("pubkey_sign: algo=%d\n", algo );
|
||||
for(i=0; i < pubkey_get_nskey(algo); i++ )
|
||||
log_mpidump(" skey:", skey[i] );
|
||||
log_mpidump(" data:", data );
|
||||
}
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo ) {
|
||||
rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
|
||||
goto ready;
|
||||
}
|
||||
} while( load_pubkey_modules() );
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
ready:
|
||||
if( !rc && DBG_CIPHER ) {
|
||||
for(i=0; i < pubkey_get_nsig(algo); i++ )
|
||||
log_mpidump(" sig:", resarr[i] );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Verify a public key signature.
|
||||
* Return 0 if the signature is good
|
||||
*/
|
||||
int
|
||||
pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev )
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
do {
|
||||
for(i=0; pubkey_table[i].name; i++ )
|
||||
if( pubkey_table[i].algo == algo ) {
|
||||
rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
|
||||
cmp, opaquev );
|
||||
goto ready;
|
||||
}
|
||||
} while( load_pubkey_modules() );
|
||||
rc = G10ERR_PUBKEY_ALGO;
|
||||
ready:
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* rand-internal.h - header to glue the random functions
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_RAND_INTERNAL_H
|
||||
#define G10_RAND_INTERNAL_H
|
||||
|
||||
void rndlinux_constructor(void);
|
||||
void rndunix_constructor(void);
|
||||
void rndw32_constructor(void);
|
||||
void rndos2_constructor(void);
|
||||
void rndatari_constructor(void);
|
||||
void rndmvs_constructor(void);
|
||||
void rndriscos_constructor(void);
|
||||
|
||||
#endif /*G10_RAND_INTERNAL_H*/
|
|
@ -0,0 +1,687 @@
|
|||
/* random.c - random number generator
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
/****************
|
||||
* This random number generator is modelled after the one described
|
||||
* in Peter Gutmann's Paper: "Software Generation of Practically
|
||||
* Strong Random Numbers".
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_GETHRTIME
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
#include <process.h>
|
||||
#endif
|
||||
#include "util.h"
|
||||
#include "rmd.h"
|
||||
#include "ttyio.h"
|
||||
#include "i18n.h"
|
||||
#include "random.h"
|
||||
#include "rand-internal.h"
|
||||
#include "dynload.h"
|
||||
|
||||
|
||||
#ifndef RAND_MAX /* for SunOS */
|
||||
#define RAND_MAX 32767
|
||||
#endif
|
||||
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
#define ADD_VALUE 0xa5a5a5a5a5a5a5a5
|
||||
#elif SIZEOF_UNSIGNED_LONG == 4
|
||||
#define ADD_VALUE 0xa5a5a5a5
|
||||
#else
|
||||
#error weird size for an unsigned long
|
||||
#endif
|
||||
|
||||
#define BLOCKLEN 64 /* hash this amount of bytes */
|
||||
#define DIGESTLEN 20 /* into a digest of this length (rmd160) */
|
||||
/* poolblocks is the number of digests which make up the pool
|
||||
* and poolsize must be a multiple of the digest length
|
||||
* to make the AND operations faster, the size should also be
|
||||
* a multiple of ulong
|
||||
*/
|
||||
#define POOLBLOCKS 30
|
||||
#define POOLSIZE (POOLBLOCKS*DIGESTLEN)
|
||||
#if (POOLSIZE % SIZEOF_UNSIGNED_LONG)
|
||||
#error Please make sure that poolsize is a multiple of ulong
|
||||
#endif
|
||||
#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG)
|
||||
|
||||
|
||||
static int is_initialized;
|
||||
#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0)
|
||||
static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */
|
||||
static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */
|
||||
static size_t pool_readpos;
|
||||
static size_t pool_writepos;
|
||||
static int pool_filled;
|
||||
static int pool_balance;
|
||||
static int just_mixed;
|
||||
static int did_initial_extra_seeding;
|
||||
static char *seed_file_name;
|
||||
static int allow_seed_file_update;
|
||||
|
||||
static int secure_alloc;
|
||||
static int quick_test;
|
||||
static int faked_rng;
|
||||
|
||||
|
||||
static void read_pool( byte *buffer, size_t length, int level );
|
||||
static void add_randomness( const void *buffer, size_t length, int source );
|
||||
static void random_poll(void);
|
||||
static void read_random_source( int requester, size_t length, int level);
|
||||
static int gather_faked( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level );
|
||||
|
||||
static struct {
|
||||
ulong mixrnd;
|
||||
ulong mixkey;
|
||||
ulong slowpolls;
|
||||
ulong fastpolls;
|
||||
ulong getbytes1;
|
||||
ulong ngetbytes1;
|
||||
ulong getbytes2;
|
||||
ulong ngetbytes2;
|
||||
ulong addbytes;
|
||||
ulong naddbytes;
|
||||
} rndstats;
|
||||
|
||||
static void
|
||||
initialize(void)
|
||||
{
|
||||
/* The data buffer is allocated somewhat larger, so that
|
||||
* we can use this extra space (which is allocated in secure memory)
|
||||
* as a temporary hash buffer */
|
||||
rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
|
||||
: m_alloc_clear(POOLSIZE+BLOCKLEN);
|
||||
keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN)
|
||||
: m_alloc_clear(POOLSIZE+BLOCKLEN);
|
||||
is_initialized = 1;
|
||||
cipher_modules_constructor();
|
||||
}
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
void
|
||||
random_dump_stats()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n"
|
||||
" outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n",
|
||||
POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls,
|
||||
rndstats.naddbytes, rndstats.addbytes,
|
||||
rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
|
||||
rndstats.ngetbytes2, rndstats.getbytes2 );
|
||||
}
|
||||
|
||||
void
|
||||
secure_random_alloc()
|
||||
{
|
||||
secure_alloc = 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
quick_random_gen( int onoff )
|
||||
{
|
||||
int last;
|
||||
|
||||
read_random_source(0,0,0); /* init */
|
||||
last = quick_test;
|
||||
if( onoff != -1 )
|
||||
quick_test = onoff;
|
||||
return faked_rng? 1 : last;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Fill the buffer with LENGTH bytes of cryptographically strong
|
||||
* random bytes. level 0 is not very strong, 1 is strong enough
|
||||
* for most usage, 2 is good for key generation stuff but may be very slow.
|
||||
*/
|
||||
void
|
||||
randomize_buffer( byte *buffer, size_t length, int level )
|
||||
{
|
||||
char *p = get_random_bits( length*8, level, 1 );
|
||||
memcpy( buffer, p, length );
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
random_is_faked()
|
||||
{
|
||||
if( !is_initialized )
|
||||
initialize();
|
||||
return faked_rng || quick_test;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return a pointer to a randomized buffer of level 0 and LENGTH bits
|
||||
* caller must free the buffer.
|
||||
* Note: The returned value is rounded up to bytes.
|
||||
*/
|
||||
byte *
|
||||
get_random_bits( size_t nbits, int level, int secure )
|
||||
{
|
||||
byte *buf, *p;
|
||||
size_t nbytes = (nbits+7)/8;
|
||||
|
||||
if( quick_test && level > 1 )
|
||||
level = 1;
|
||||
MASK_LEVEL(level);
|
||||
if( level == 1 ) {
|
||||
rndstats.getbytes1 += nbytes;
|
||||
rndstats.ngetbytes1++;
|
||||
}
|
||||
else if( level >= 2 ) {
|
||||
rndstats.getbytes2 += nbytes;
|
||||
rndstats.ngetbytes2++;
|
||||
}
|
||||
|
||||
buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes );
|
||||
for( p = buf; nbytes > 0; ) {
|
||||
size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes;
|
||||
read_pool( p, n, level );
|
||||
nbytes -= n;
|
||||
p += n;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Mix the pool
|
||||
*/
|
||||
static void
|
||||
mix_pool(byte *pool)
|
||||
{
|
||||
char *hashbuf = pool + POOLSIZE;
|
||||
char *p, *pend;
|
||||
int i, n;
|
||||
RMD160_CONTEXT md;
|
||||
|
||||
rmd160_init( &md );
|
||||
#if DIGESTLEN != 20
|
||||
#error must have a digest length of 20 for ripe-md-160
|
||||
#endif
|
||||
/* loop over the pool */
|
||||
pend = pool + POOLSIZE;
|
||||
memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN );
|
||||
memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN);
|
||||
rmd160_mixblock( &md, hashbuf);
|
||||
memcpy(pool, hashbuf, 20 );
|
||||
|
||||
p = pool;
|
||||
for( n=1; n < POOLBLOCKS; n++ ) {
|
||||
memcpy(hashbuf, p, DIGESTLEN );
|
||||
|
||||
p += DIGESTLEN;
|
||||
if( p+DIGESTLEN+BLOCKLEN < pend )
|
||||
memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN);
|
||||
else {
|
||||
char *pp = p+DIGESTLEN;
|
||||
for(i=DIGESTLEN; i < BLOCKLEN; i++ ) {
|
||||
if( pp >= pend )
|
||||
pp = pool;
|
||||
hashbuf[i] = *pp++;
|
||||
}
|
||||
}
|
||||
|
||||
rmd160_mixblock( &md, hashbuf);
|
||||
memcpy(p, hashbuf, 20 );
|
||||
}
|
||||
burn_stack (384); /* for the rmd160_mixblock() */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
set_random_seed_file( const char *name )
|
||||
{
|
||||
if( seed_file_name )
|
||||
BUG();
|
||||
seed_file_name = m_strdup( name );
|
||||
}
|
||||
|
||||
/****************
|
||||
* Read in a seed form the random_seed file
|
||||
* and return true if this was successful
|
||||
*/
|
||||
static int
|
||||
read_seed_file(void)
|
||||
{
|
||||
int fd;
|
||||
struct stat sb;
|
||||
unsigned char buffer[POOLSIZE];
|
||||
int n;
|
||||
|
||||
if( !seed_file_name )
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
fd = open( seed_file_name, O_RDONLY | O_BINARY );
|
||||
#else
|
||||
fd = open( seed_file_name, O_RDONLY );
|
||||
#endif
|
||||
if( fd == -1 && errno == ENOENT) {
|
||||
allow_seed_file_update = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( fd == -1 ) {
|
||||
log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) );
|
||||
return 0;
|
||||
}
|
||||
if( fstat( fd, &sb ) ) {
|
||||
log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if( !S_ISREG(sb.st_mode) ) {
|
||||
log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if( !sb.st_size ) {
|
||||
log_info(_("note: random_seed file is empty\n") );
|
||||
close(fd);
|
||||
allow_seed_file_update = 1;
|
||||
return 0;
|
||||
}
|
||||
if( sb.st_size != POOLSIZE ) {
|
||||
log_info(_("warning: invalid size of random_seed file - not used\n") );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
do {
|
||||
n = read( fd, buffer, POOLSIZE );
|
||||
} while( n == -1 && errno == EINTR );
|
||||
if( n != POOLSIZE ) {
|
||||
log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) );
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
add_randomness( buffer, POOLSIZE, 0 );
|
||||
/* add some minor entropy to the pool now (this will also force a mixing) */
|
||||
{ pid_t x = getpid();
|
||||
add_randomness( &x, sizeof(x), 0 );
|
||||
}
|
||||
{ time_t x = time(NULL);
|
||||
add_randomness( &x, sizeof(x), 0 );
|
||||
}
|
||||
{ clock_t x = clock();
|
||||
add_randomness( &x, sizeof(x), 0 );
|
||||
}
|
||||
/* And read a few bytes from our entropy source. By using
|
||||
* a level of 0 this will not block and might not return anything
|
||||
* with some entropy drivers, however the rndlinux driver will use
|
||||
* /dev/urandom and return some stuff - Do not read to much as we
|
||||
* want to be friendly to the scare system entropy resource. */
|
||||
read_random_source( 0, 16, 0 );
|
||||
|
||||
allow_seed_file_update = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
update_random_seed_file()
|
||||
{
|
||||
ulong *sp, *dp;
|
||||
int fd, i;
|
||||
|
||||
if( !seed_file_name || !is_initialized || !pool_filled )
|
||||
return;
|
||||
if( !allow_seed_file_update ) {
|
||||
log_info(_("note: random_seed file not updated\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* copy the entropy pool to a scratch pool and mix both of them */
|
||||
for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
|
||||
i < POOLWORDS; i++, dp++, sp++ ) {
|
||||
*dp = *sp + ADD_VALUE;
|
||||
}
|
||||
mix_pool(rndpool); rndstats.mixrnd++;
|
||||
mix_pool(keypool); rndstats.mixkey++;
|
||||
|
||||
#ifdef HAVE_DOSISH_SYSTEM
|
||||
fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
|
||||
S_IRUSR|S_IWUSR );
|
||||
#else
|
||||
fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
|
||||
#endif
|
||||
if( fd == -1 ) {
|
||||
log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
|
||||
return;
|
||||
}
|
||||
do {
|
||||
i = write( fd, keypool, POOLSIZE );
|
||||
} while( i == -1 && errno == EINTR );
|
||||
if( i != POOLSIZE ) {
|
||||
log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) );
|
||||
}
|
||||
if( close(fd) )
|
||||
log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_pool( byte *buffer, size_t length, int level )
|
||||
{
|
||||
int i;
|
||||
ulong *sp, *dp;
|
||||
|
||||
if( length > POOLSIZE ) {
|
||||
log_bug("too many random bits requested\n");
|
||||
}
|
||||
|
||||
if( !pool_filled ) {
|
||||
if( read_seed_file() )
|
||||
pool_filled = 1;
|
||||
}
|
||||
|
||||
/* For level 2 quality (key generation) we alwas make
|
||||
* sure that the pool has been seeded enough initially */
|
||||
if( level == 2 && !did_initial_extra_seeding ) {
|
||||
size_t needed;
|
||||
|
||||
pool_balance = 0;
|
||||
needed = length - pool_balance;
|
||||
if( needed < POOLSIZE/2 )
|
||||
needed = POOLSIZE/2;
|
||||
else if( needed > POOLSIZE )
|
||||
BUG();
|
||||
read_random_source( 3, needed, 2 );
|
||||
pool_balance += needed;
|
||||
did_initial_extra_seeding=1;
|
||||
}
|
||||
|
||||
/* for level 2 make sure that there is enough random in the pool */
|
||||
if( level == 2 && pool_balance < length ) {
|
||||
size_t needed;
|
||||
|
||||
if( pool_balance < 0 )
|
||||
pool_balance = 0;
|
||||
needed = length - pool_balance;
|
||||
if( needed > POOLSIZE )
|
||||
BUG();
|
||||
read_random_source( 3, needed, 2 );
|
||||
pool_balance += needed;
|
||||
}
|
||||
|
||||
/* make sure the pool is filled */
|
||||
while( !pool_filled )
|
||||
random_poll();
|
||||
|
||||
/* do always a fast random poll */
|
||||
fast_random_poll();
|
||||
|
||||
if( !level ) { /* no need for cryptographic strong random */
|
||||
/* create a new pool */
|
||||
for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
|
||||
i < POOLWORDS; i++, dp++, sp++ )
|
||||
*dp = *sp + ADD_VALUE;
|
||||
/* must mix both pools */
|
||||
mix_pool(rndpool); rndstats.mixrnd++;
|
||||
mix_pool(keypool); rndstats.mixkey++;
|
||||
memcpy( buffer, keypool, length );
|
||||
}
|
||||
else {
|
||||
/* mix the pool (if add_randomness() didn't it) */
|
||||
if( !just_mixed ) {
|
||||
mix_pool(rndpool);
|
||||
rndstats.mixrnd++;
|
||||
}
|
||||
/* create a new pool */
|
||||
for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool;
|
||||
i < POOLWORDS; i++, dp++, sp++ )
|
||||
*dp = *sp + ADD_VALUE;
|
||||
/* and mix both pools */
|
||||
mix_pool(rndpool); rndstats.mixrnd++;
|
||||
mix_pool(keypool); rndstats.mixkey++;
|
||||
/* read the required data
|
||||
* we use a readpoiter to read from a different postion each
|
||||
* time */
|
||||
while( length-- ) {
|
||||
*buffer++ = keypool[pool_readpos++];
|
||||
if( pool_readpos >= POOLSIZE )
|
||||
pool_readpos = 0;
|
||||
pool_balance--;
|
||||
}
|
||||
if( pool_balance < 0 )
|
||||
pool_balance = 0;
|
||||
/* and clear the keypool */
|
||||
memset( keypool, 0, POOLSIZE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Add LENGTH bytes of randomness from buffer to the pool.
|
||||
* source may be used to specify the randomness source.
|
||||
* Source is:
|
||||
* 0 - used ony for initialization
|
||||
* 1 - fast random poll function
|
||||
* 2 - normal poll function
|
||||
* 3 - used when level 2 random quality has been requested
|
||||
* to do an extra pool seed.
|
||||
*/
|
||||
static void
|
||||
add_randomness( const void *buffer, size_t length, int source )
|
||||
{
|
||||
const byte *p = buffer;
|
||||
|
||||
if( !is_initialized )
|
||||
initialize();
|
||||
rndstats.addbytes += length;
|
||||
rndstats.naddbytes++;
|
||||
while( length-- ) {
|
||||
rndpool[pool_writepos++] ^= *p++;
|
||||
if( pool_writepos >= POOLSIZE ) {
|
||||
if( source > 1 )
|
||||
pool_filled = 1;
|
||||
pool_writepos = 0;
|
||||
mix_pool(rndpool); rndstats.mixrnd++;
|
||||
just_mixed = !length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
random_poll()
|
||||
{
|
||||
rndstats.slowpolls++;
|
||||
read_random_source( 2, POOLSIZE/5, 1 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fast_random_poll()
|
||||
{
|
||||
static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL;
|
||||
static int initialized = 0;
|
||||
|
||||
rndstats.fastpolls++;
|
||||
if( !initialized ) {
|
||||
if( !is_initialized )
|
||||
initialize();
|
||||
initialized = 1;
|
||||
fnc = dynload_getfnc_fast_random_poll();
|
||||
}
|
||||
if( fnc ) {
|
||||
(*fnc)( add_randomness, 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
/* fall back to the generic function */
|
||||
#if defined(HAVE_GETHRTIME) && !defined(HAVE_BROKEN_GETHRTIME)
|
||||
{ hrtime_t tv;
|
||||
/* On some Solaris and HPUX system gethrtime raises an SIGILL, but we
|
||||
* checked this with configure */
|
||||
tv = gethrtime();
|
||||
add_randomness( &tv, sizeof(tv), 1 );
|
||||
}
|
||||
#elif defined (HAVE_GETTIMEOFDAY)
|
||||
{ struct timeval tv;
|
||||
if( gettimeofday( &tv, NULL ) )
|
||||
BUG();
|
||||
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
|
||||
add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 );
|
||||
}
|
||||
#elif defined (HAVE_CLOCK_GETTIME)
|
||||
{ struct timespec tv;
|
||||
if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 )
|
||||
BUG();
|
||||
add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 );
|
||||
add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 );
|
||||
}
|
||||
#else /* use times */
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
{ struct tms buf;
|
||||
times( &buf );
|
||||
add_randomness( &buf, sizeof buf, 1 );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
#ifndef RUSAGE_SELF
|
||||
#ifdef __GCC__
|
||||
#warning There is no RUSAGE_SELF on this system
|
||||
#endif
|
||||
#else
|
||||
{ struct rusage buf;
|
||||
/* QNX/Neutrino does return ENOSYS - so we just ignore it and
|
||||
* add whatever is in buf. In a chroot environment it might not
|
||||
* work at all (i.e. because /proc/ is not accessible), so we better
|
||||
* ignore all error codes and hope for the best
|
||||
*/
|
||||
getrusage( RUSAGE_SELF, &buf );
|
||||
|
||||
add_randomness( &buf, sizeof buf, 1 );
|
||||
memset( &buf, 0, sizeof buf );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* time and clock are available on all systems - so
|
||||
* we better do it just in case one of the above functions
|
||||
* didn't work */
|
||||
{ time_t x = time(NULL);
|
||||
add_randomness( &x, sizeof(x), 1 );
|
||||
}
|
||||
{ clock_t x = clock();
|
||||
add_randomness( &x, sizeof(x), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
read_random_source( int requester, size_t length, int level )
|
||||
{
|
||||
static int (*fnc)(void (*)(const void*, size_t, int), int,
|
||||
size_t, int) = NULL;
|
||||
if( !fnc ) {
|
||||
if( !is_initialized )
|
||||
initialize();
|
||||
fnc = dynload_getfnc_gather_random();
|
||||
if( !fnc ) {
|
||||
faked_rng = 1;
|
||||
fnc = gather_faked;
|
||||
}
|
||||
if( !requester && !length && !level )
|
||||
return; /* init only */
|
||||
}
|
||||
if( (*fnc)( add_randomness, requester, length, level ) < 0 )
|
||||
log_fatal("No way to gather entropy for the RNG\n");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gather_faked( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
static int initialized=0;
|
||||
size_t n;
|
||||
char *buffer, *p;
|
||||
|
||||
if( !initialized ) {
|
||||
log_info(_("WARNING: using insecure random number generator!!\n"));
|
||||
tty_printf(_("The random number generator is only a kludge to let\n"
|
||||
"it run - it is in no way a strong RNG!\n\n"
|
||||
"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n"));
|
||||
initialized=1;
|
||||
#ifdef HAVE_RAND
|
||||
srand(make_timestamp()*getpid());
|
||||
#else
|
||||
srandom(make_timestamp()*getpid());
|
||||
#endif
|
||||
}
|
||||
|
||||
p = buffer = m_alloc( length );
|
||||
n = length;
|
||||
#ifdef HAVE_RAND
|
||||
while( n-- )
|
||||
*p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1);
|
||||
#else
|
||||
while( n-- )
|
||||
*p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1);
|
||||
#endif
|
||||
add_randomness( buffer, length, requester );
|
||||
m_free(buffer);
|
||||
return 0; /* okay */
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* random.h - random functions
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_RANDOM_H
|
||||
#define G10_RANDOM_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/*-- random.c --*/
|
||||
void random_dump_stats(void);
|
||||
void secure_random_alloc(void);
|
||||
void set_random_seed_file(const char *);
|
||||
void update_random_seed_file(void);
|
||||
int quick_random_gen( int onoff );
|
||||
int random_is_faked(void);
|
||||
void randomize_buffer( byte *buffer, size_t length, int level );
|
||||
byte *get_random_bits( size_t nbits, int level, int secure );
|
||||
void fast_random_poll( void );
|
||||
|
||||
/*-- rndw32.c --*/
|
||||
#ifdef USE_STATIC_RNDW32
|
||||
void rndw32_set_dll_name( const char *name );
|
||||
#endif
|
||||
|
||||
#endif /*G10_RANDOM_H*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,35 @@
|
|||
/* rmd.h - RIPE-MD hash functions
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_RMD_H
|
||||
#define G10_RMD_H
|
||||
|
||||
|
||||
/* we need this here because random.c must have direct access */
|
||||
typedef struct {
|
||||
u32 h0,h1,h2,h3,h4;
|
||||
u32 nblocks;
|
||||
byte buf[64];
|
||||
int count;
|
||||
} RMD160_CONTEXT;
|
||||
|
||||
void rmd160_init( RMD160_CONTEXT *hd );
|
||||
void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer );
|
||||
|
||||
#endif /*G10_RMD_H*/
|
|
@ -0,0 +1,652 @@
|
|||
/* rmd160.c - RIPE-MD160
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "rmd.h"
|
||||
#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */
|
||||
#include "dynload.h"
|
||||
|
||||
#include "bithelp.h"
|
||||
|
||||
/*********************************
|
||||
* RIPEMD-160 is not patented, see (as of 25.10.97)
|
||||
* http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
|
||||
* Note that the code uses Little Endian byteorder, which is good for
|
||||
* 386 etc, but we must add some conversion when used on a big endian box.
|
||||
*
|
||||
*
|
||||
* Pseudo-code for RIPEMD-160
|
||||
*
|
||||
* RIPEMD-160 is an iterative hash function that operates on 32-bit words.
|
||||
* The round function takes as input a 5-word chaining variable and a 16-word
|
||||
* message block and maps this to a new chaining variable. All operations are
|
||||
* defined on 32-bit words. Padding is identical to that of MD4.
|
||||
*
|
||||
*
|
||||
* RIPEMD-160: definitions
|
||||
*
|
||||
*
|
||||
* nonlinear functions at bit level: exor, mux, -, mux, -
|
||||
*
|
||||
* f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15)
|
||||
* f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31)
|
||||
* f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47)
|
||||
* f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63)
|
||||
* f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79)
|
||||
*
|
||||
*
|
||||
* added constants (hexadecimal)
|
||||
*
|
||||
* K(j) = 0x00000000 (0 <= j <= 15)
|
||||
* K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2))
|
||||
* K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3))
|
||||
* K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5))
|
||||
* K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7))
|
||||
* K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2))
|
||||
* K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3))
|
||||
* K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5))
|
||||
* K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7))
|
||||
* K'(j) = 0x00000000 (64 <= j <= 79)
|
||||
*
|
||||
*
|
||||
* selection of message word
|
||||
*
|
||||
* r(j) = j (0 <= j <= 15)
|
||||
* r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8
|
||||
* r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12
|
||||
* r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2
|
||||
* r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
||||
* r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12
|
||||
* r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2
|
||||
* r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13
|
||||
* r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14
|
||||
* r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
||||
*
|
||||
*
|
||||
* amount for rotate left (rol)
|
||||
*
|
||||
* s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8
|
||||
* s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12
|
||||
* s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5
|
||||
* s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12
|
||||
* s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
||||
* s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6
|
||||
* s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11
|
||||
* s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5
|
||||
* s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8
|
||||
* s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
||||
*
|
||||
*
|
||||
* initial value (hexadecimal)
|
||||
*
|
||||
* h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476;
|
||||
* h4 = 0xC3D2E1F0;
|
||||
*
|
||||
*
|
||||
* RIPEMD-160: pseudo-code
|
||||
*
|
||||
* It is assumed that the message after padding consists of t 16-word blocks
|
||||
* that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15.
|
||||
* The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left
|
||||
* shift (rotate) over s positions.
|
||||
*
|
||||
*
|
||||
* for i := 0 to t-1 {
|
||||
* A := h0; B := h1; C := h2; D = h3; E = h4;
|
||||
* A' := h0; B' := h1; C' := h2; D' = h3; E' = h4;
|
||||
* for j := 0 to 79 {
|
||||
* T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E;
|
||||
* A := E; E := D; D := rol_10(C); C := B; B := T;
|
||||
* T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)]
|
||||
[+] K'(j)) [+] E';
|
||||
* A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T;
|
||||
* }
|
||||
* T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A';
|
||||
* h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T;
|
||||
* }
|
||||
*/
|
||||
|
||||
/* Some examples:
|
||||
* "" 9c1185a5c5e9fc54612808977ee8f548b2258d31
|
||||
* "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe
|
||||
* "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
|
||||
* "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36
|
||||
* "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc
|
||||
* "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b
|
||||
* "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189
|
||||
* 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb
|
||||
* 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528
|
||||
*/
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[150];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rmd160_init( RMD160_CONTEXT *hd )
|
||||
{
|
||||
hd->h0 = 0x67452301;
|
||||
hd->h1 = 0xEFCDAB89;
|
||||
hd->h2 = 0x98BADCFE;
|
||||
hd->h3 = 0x10325476;
|
||||
hd->h4 = 0xC3D2E1F0;
|
||||
hd->nblocks = 0;
|
||||
hd->count = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Transform the message X which consists of 16 32-bit-words
|
||||
*/
|
||||
static void
|
||||
transform( RMD160_CONTEXT *hd, byte *data )
|
||||
{
|
||||
u32 a,b,c,d,e,aa,bb,cc,dd,ee,t;
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
u32 x[16];
|
||||
{ int i;
|
||||
byte *p2, *p1;
|
||||
for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) {
|
||||
p2[3] = *p1++;
|
||||
p2[2] = *p1++;
|
||||
p2[1] = *p1++;
|
||||
p2[0] = *p1++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if 0
|
||||
u32 *x =(u32*)data;
|
||||
#else
|
||||
/* this version is better because it is always aligned;
|
||||
* The performance penalty on a 586-100 is about 6% which
|
||||
* is acceptable - because the data is more local it might
|
||||
* also be possible that this is faster on some machines.
|
||||
* This function (when compiled with -02 on gcc 2.7.2)
|
||||
* executes on a 586-100 (39.73 bogomips) at about 1900kb/sec;
|
||||
* [measured with a 4MB data and "gpgm --print-md rmd160"] */
|
||||
u32 x[16];
|
||||
memcpy( x, data, 64 );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define K0 0x00000000
|
||||
#define K1 0x5A827999
|
||||
#define K2 0x6ED9EBA1
|
||||
#define K3 0x8F1BBCDC
|
||||
#define K4 0xA953FD4E
|
||||
#define KK0 0x50A28BE6
|
||||
#define KK1 0x5C4DD124
|
||||
#define KK2 0x6D703EF3
|
||||
#define KK3 0x7A6D76E9
|
||||
#define KK4 0x00000000
|
||||
#define F0(x,y,z) ( (x) ^ (y) ^ (z) )
|
||||
#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) )
|
||||
#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) )
|
||||
#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) )
|
||||
#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) )
|
||||
#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \
|
||||
a = rol(t,s) + e; \
|
||||
c = rol(c,10); \
|
||||
} while(0)
|
||||
|
||||
/* left lane */
|
||||
a = hd->h0;
|
||||
b = hd->h1;
|
||||
c = hd->h2;
|
||||
d = hd->h3;
|
||||
e = hd->h4;
|
||||
R( a, b, c, d, e, F0, K0, 0, 11 );
|
||||
R( e, a, b, c, d, F0, K0, 1, 14 );
|
||||
R( d, e, a, b, c, F0, K0, 2, 15 );
|
||||
R( c, d, e, a, b, F0, K0, 3, 12 );
|
||||
R( b, c, d, e, a, F0, K0, 4, 5 );
|
||||
R( a, b, c, d, e, F0, K0, 5, 8 );
|
||||
R( e, a, b, c, d, F0, K0, 6, 7 );
|
||||
R( d, e, a, b, c, F0, K0, 7, 9 );
|
||||
R( c, d, e, a, b, F0, K0, 8, 11 );
|
||||
R( b, c, d, e, a, F0, K0, 9, 13 );
|
||||
R( a, b, c, d, e, F0, K0, 10, 14 );
|
||||
R( e, a, b, c, d, F0, K0, 11, 15 );
|
||||
R( d, e, a, b, c, F0, K0, 12, 6 );
|
||||
R( c, d, e, a, b, F0, K0, 13, 7 );
|
||||
R( b, c, d, e, a, F0, K0, 14, 9 );
|
||||
R( a, b, c, d, e, F0, K0, 15, 8 );
|
||||
R( e, a, b, c, d, F1, K1, 7, 7 );
|
||||
R( d, e, a, b, c, F1, K1, 4, 6 );
|
||||
R( c, d, e, a, b, F1, K1, 13, 8 );
|
||||
R( b, c, d, e, a, F1, K1, 1, 13 );
|
||||
R( a, b, c, d, e, F1, K1, 10, 11 );
|
||||
R( e, a, b, c, d, F1, K1, 6, 9 );
|
||||
R( d, e, a, b, c, F1, K1, 15, 7 );
|
||||
R( c, d, e, a, b, F1, K1, 3, 15 );
|
||||
R( b, c, d, e, a, F1, K1, 12, 7 );
|
||||
R( a, b, c, d, e, F1, K1, 0, 12 );
|
||||
R( e, a, b, c, d, F1, K1, 9, 15 );
|
||||
R( d, e, a, b, c, F1, K1, 5, 9 );
|
||||
R( c, d, e, a, b, F1, K1, 2, 11 );
|
||||
R( b, c, d, e, a, F1, K1, 14, 7 );
|
||||
R( a, b, c, d, e, F1, K1, 11, 13 );
|
||||
R( e, a, b, c, d, F1, K1, 8, 12 );
|
||||
R( d, e, a, b, c, F2, K2, 3, 11 );
|
||||
R( c, d, e, a, b, F2, K2, 10, 13 );
|
||||
R( b, c, d, e, a, F2, K2, 14, 6 );
|
||||
R( a, b, c, d, e, F2, K2, 4, 7 );
|
||||
R( e, a, b, c, d, F2, K2, 9, 14 );
|
||||
R( d, e, a, b, c, F2, K2, 15, 9 );
|
||||
R( c, d, e, a, b, F2, K2, 8, 13 );
|
||||
R( b, c, d, e, a, F2, K2, 1, 15 );
|
||||
R( a, b, c, d, e, F2, K2, 2, 14 );
|
||||
R( e, a, b, c, d, F2, K2, 7, 8 );
|
||||
R( d, e, a, b, c, F2, K2, 0, 13 );
|
||||
R( c, d, e, a, b, F2, K2, 6, 6 );
|
||||
R( b, c, d, e, a, F2, K2, 13, 5 );
|
||||
R( a, b, c, d, e, F2, K2, 11, 12 );
|
||||
R( e, a, b, c, d, F2, K2, 5, 7 );
|
||||
R( d, e, a, b, c, F2, K2, 12, 5 );
|
||||
R( c, d, e, a, b, F3, K3, 1, 11 );
|
||||
R( b, c, d, e, a, F3, K3, 9, 12 );
|
||||
R( a, b, c, d, e, F3, K3, 11, 14 );
|
||||
R( e, a, b, c, d, F3, K3, 10, 15 );
|
||||
R( d, e, a, b, c, F3, K3, 0, 14 );
|
||||
R( c, d, e, a, b, F3, K3, 8, 15 );
|
||||
R( b, c, d, e, a, F3, K3, 12, 9 );
|
||||
R( a, b, c, d, e, F3, K3, 4, 8 );
|
||||
R( e, a, b, c, d, F3, K3, 13, 9 );
|
||||
R( d, e, a, b, c, F3, K3, 3, 14 );
|
||||
R( c, d, e, a, b, F3, K3, 7, 5 );
|
||||
R( b, c, d, e, a, F3, K3, 15, 6 );
|
||||
R( a, b, c, d, e, F3, K3, 14, 8 );
|
||||
R( e, a, b, c, d, F3, K3, 5, 6 );
|
||||
R( d, e, a, b, c, F3, K3, 6, 5 );
|
||||
R( c, d, e, a, b, F3, K3, 2, 12 );
|
||||
R( b, c, d, e, a, F4, K4, 4, 9 );
|
||||
R( a, b, c, d, e, F4, K4, 0, 15 );
|
||||
R( e, a, b, c, d, F4, K4, 5, 5 );
|
||||
R( d, e, a, b, c, F4, K4, 9, 11 );
|
||||
R( c, d, e, a, b, F4, K4, 7, 6 );
|
||||
R( b, c, d, e, a, F4, K4, 12, 8 );
|
||||
R( a, b, c, d, e, F4, K4, 2, 13 );
|
||||
R( e, a, b, c, d, F4, K4, 10, 12 );
|
||||
R( d, e, a, b, c, F4, K4, 14, 5 );
|
||||
R( c, d, e, a, b, F4, K4, 1, 12 );
|
||||
R( b, c, d, e, a, F4, K4, 3, 13 );
|
||||
R( a, b, c, d, e, F4, K4, 8, 14 );
|
||||
R( e, a, b, c, d, F4, K4, 11, 11 );
|
||||
R( d, e, a, b, c, F4, K4, 6, 8 );
|
||||
R( c, d, e, a, b, F4, K4, 15, 5 );
|
||||
R( b, c, d, e, a, F4, K4, 13, 6 );
|
||||
|
||||
aa = a; bb = b; cc = c; dd = d; ee = e;
|
||||
|
||||
/* right lane */
|
||||
a = hd->h0;
|
||||
b = hd->h1;
|
||||
c = hd->h2;
|
||||
d = hd->h3;
|
||||
e = hd->h4;
|
||||
R( a, b, c, d, e, F4, KK0, 5, 8);
|
||||
R( e, a, b, c, d, F4, KK0, 14, 9);
|
||||
R( d, e, a, b, c, F4, KK0, 7, 9);
|
||||
R( c, d, e, a, b, F4, KK0, 0, 11);
|
||||
R( b, c, d, e, a, F4, KK0, 9, 13);
|
||||
R( a, b, c, d, e, F4, KK0, 2, 15);
|
||||
R( e, a, b, c, d, F4, KK0, 11, 15);
|
||||
R( d, e, a, b, c, F4, KK0, 4, 5);
|
||||
R( c, d, e, a, b, F4, KK0, 13, 7);
|
||||
R( b, c, d, e, a, F4, KK0, 6, 7);
|
||||
R( a, b, c, d, e, F4, KK0, 15, 8);
|
||||
R( e, a, b, c, d, F4, KK0, 8, 11);
|
||||
R( d, e, a, b, c, F4, KK0, 1, 14);
|
||||
R( c, d, e, a, b, F4, KK0, 10, 14);
|
||||
R( b, c, d, e, a, F4, KK0, 3, 12);
|
||||
R( a, b, c, d, e, F4, KK0, 12, 6);
|
||||
R( e, a, b, c, d, F3, KK1, 6, 9);
|
||||
R( d, e, a, b, c, F3, KK1, 11, 13);
|
||||
R( c, d, e, a, b, F3, KK1, 3, 15);
|
||||
R( b, c, d, e, a, F3, KK1, 7, 7);
|
||||
R( a, b, c, d, e, F3, KK1, 0, 12);
|
||||
R( e, a, b, c, d, F3, KK1, 13, 8);
|
||||
R( d, e, a, b, c, F3, KK1, 5, 9);
|
||||
R( c, d, e, a, b, F3, KK1, 10, 11);
|
||||
R( b, c, d, e, a, F3, KK1, 14, 7);
|
||||
R( a, b, c, d, e, F3, KK1, 15, 7);
|
||||
R( e, a, b, c, d, F3, KK1, 8, 12);
|
||||
R( d, e, a, b, c, F3, KK1, 12, 7);
|
||||
R( c, d, e, a, b, F3, KK1, 4, 6);
|
||||
R( b, c, d, e, a, F3, KK1, 9, 15);
|
||||
R( a, b, c, d, e, F3, KK1, 1, 13);
|
||||
R( e, a, b, c, d, F3, KK1, 2, 11);
|
||||
R( d, e, a, b, c, F2, KK2, 15, 9);
|
||||
R( c, d, e, a, b, F2, KK2, 5, 7);
|
||||
R( b, c, d, e, a, F2, KK2, 1, 15);
|
||||
R( a, b, c, d, e, F2, KK2, 3, 11);
|
||||
R( e, a, b, c, d, F2, KK2, 7, 8);
|
||||
R( d, e, a, b, c, F2, KK2, 14, 6);
|
||||
R( c, d, e, a, b, F2, KK2, 6, 6);
|
||||
R( b, c, d, e, a, F2, KK2, 9, 14);
|
||||
R( a, b, c, d, e, F2, KK2, 11, 12);
|
||||
R( e, a, b, c, d, F2, KK2, 8, 13);
|
||||
R( d, e, a, b, c, F2, KK2, 12, 5);
|
||||
R( c, d, e, a, b, F2, KK2, 2, 14);
|
||||
R( b, c, d, e, a, F2, KK2, 10, 13);
|
||||
R( a, b, c, d, e, F2, KK2, 0, 13);
|
||||
R( e, a, b, c, d, F2, KK2, 4, 7);
|
||||
R( d, e, a, b, c, F2, KK2, 13, 5);
|
||||
R( c, d, e, a, b, F1, KK3, 8, 15);
|
||||
R( b, c, d, e, a, F1, KK3, 6, 5);
|
||||
R( a, b, c, d, e, F1, KK3, 4, 8);
|
||||
R( e, a, b, c, d, F1, KK3, 1, 11);
|
||||
R( d, e, a, b, c, F1, KK3, 3, 14);
|
||||
R( c, d, e, a, b, F1, KK3, 11, 14);
|
||||
R( b, c, d, e, a, F1, KK3, 15, 6);
|
||||
R( a, b, c, d, e, F1, KK3, 0, 14);
|
||||
R( e, a, b, c, d, F1, KK3, 5, 6);
|
||||
R( d, e, a, b, c, F1, KK3, 12, 9);
|
||||
R( c, d, e, a, b, F1, KK3, 2, 12);
|
||||
R( b, c, d, e, a, F1, KK3, 13, 9);
|
||||
R( a, b, c, d, e, F1, KK3, 9, 12);
|
||||
R( e, a, b, c, d, F1, KK3, 7, 5);
|
||||
R( d, e, a, b, c, F1, KK3, 10, 15);
|
||||
R( c, d, e, a, b, F1, KK3, 14, 8);
|
||||
R( b, c, d, e, a, F0, KK4, 12, 8);
|
||||
R( a, b, c, d, e, F0, KK4, 15, 5);
|
||||
R( e, a, b, c, d, F0, KK4, 10, 12);
|
||||
R( d, e, a, b, c, F0, KK4, 4, 9);
|
||||
R( c, d, e, a, b, F0, KK4, 1, 12);
|
||||
R( b, c, d, e, a, F0, KK4, 5, 5);
|
||||
R( a, b, c, d, e, F0, KK4, 8, 14);
|
||||
R( e, a, b, c, d, F0, KK4, 7, 6);
|
||||
R( d, e, a, b, c, F0, KK4, 6, 8);
|
||||
R( c, d, e, a, b, F0, KK4, 2, 13);
|
||||
R( b, c, d, e, a, F0, KK4, 13, 6);
|
||||
R( a, b, c, d, e, F0, KK4, 14, 5);
|
||||
R( e, a, b, c, d, F0, KK4, 0, 15);
|
||||
R( d, e, a, b, c, F0, KK4, 3, 13);
|
||||
R( c, d, e, a, b, F0, KK4, 9, 11);
|
||||
R( b, c, d, e, a, F0, KK4, 11, 11);
|
||||
|
||||
|
||||
t = hd->h1 + d + cc;
|
||||
hd->h1 = hd->h2 + e + dd;
|
||||
hd->h2 = hd->h3 + a + ee;
|
||||
hd->h3 = hd->h4 + b + aa;
|
||||
hd->h4 = hd->h0 + c + bb;
|
||||
hd->h0 = t;
|
||||
}
|
||||
|
||||
|
||||
/* Update the message digest with the contents
|
||||
* of INBUF with length INLEN.
|
||||
*/
|
||||
static void
|
||||
rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
|
||||
{
|
||||
if( hd->count == 64 ) { /* flush the buffer */
|
||||
transform( hd, hd->buf );
|
||||
burn_stack (108+5*sizeof(void*));
|
||||
hd->count = 0;
|
||||
hd->nblocks++;
|
||||
}
|
||||
if( !inbuf )
|
||||
return;
|
||||
if( hd->count ) {
|
||||
for( ; inlen && hd->count < 64; inlen-- )
|
||||
hd->buf[hd->count++] = *inbuf++;
|
||||
rmd160_write( hd, NULL, 0 );
|
||||
if( !inlen )
|
||||
return;
|
||||
}
|
||||
|
||||
while( inlen >= 64 ) {
|
||||
transform( hd, inbuf );
|
||||
hd->count = 0;
|
||||
hd->nblocks++;
|
||||
inlen -= 64;
|
||||
inbuf += 64;
|
||||
}
|
||||
burn_stack (108+5*sizeof(void*));
|
||||
for( ; inlen && hd->count < 64; inlen-- )
|
||||
hd->buf[hd->count++] = *inbuf++;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Apply the rmd160 transform function on the buffer which must have
|
||||
* a length 64 bytes. Do not use this function together with the
|
||||
* other functions, use rmd160_init to initialize internal variables.
|
||||
* Returns: 16 bytes in buffer with the mixed contentes of buffer.
|
||||
*/
|
||||
void
|
||||
rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer )
|
||||
{
|
||||
char *p = buffer;
|
||||
transform( hd, buffer );
|
||||
#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
|
||||
X(0);
|
||||
X(1);
|
||||
X(2);
|
||||
X(3);
|
||||
X(4);
|
||||
#undef X
|
||||
}
|
||||
|
||||
|
||||
/* The routine terminates the computation
|
||||
*/
|
||||
|
||||
static void
|
||||
rmd160_final( RMD160_CONTEXT *hd )
|
||||
{
|
||||
u32 t, msb, lsb;
|
||||
byte *p;
|
||||
|
||||
rmd160_write(hd, NULL, 0); /* flush */;
|
||||
|
||||
t = hd->nblocks;
|
||||
/* multiply by 64 to make a byte count */
|
||||
lsb = t << 6;
|
||||
msb = t >> 26;
|
||||
/* add the count */
|
||||
t = lsb;
|
||||
if( (lsb += hd->count) < t )
|
||||
msb++;
|
||||
/* multiply by 8 to make a bit count */
|
||||
t = lsb;
|
||||
lsb <<= 3;
|
||||
msb <<= 3;
|
||||
msb |= t >> 29;
|
||||
|
||||
if( hd->count < 56 ) { /* enough room */
|
||||
hd->buf[hd->count++] = 0x80; /* pad */
|
||||
while( hd->count < 56 )
|
||||
hd->buf[hd->count++] = 0; /* pad */
|
||||
}
|
||||
else { /* need one extra block */
|
||||
hd->buf[hd->count++] = 0x80; /* pad character */
|
||||
while( hd->count < 64 )
|
||||
hd->buf[hd->count++] = 0;
|
||||
rmd160_write(hd, NULL, 0); /* flush */;
|
||||
memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
|
||||
}
|
||||
/* append the 64 bit count */
|
||||
hd->buf[56] = lsb ;
|
||||
hd->buf[57] = lsb >> 8;
|
||||
hd->buf[58] = lsb >> 16;
|
||||
hd->buf[59] = lsb >> 24;
|
||||
hd->buf[60] = msb ;
|
||||
hd->buf[61] = msb >> 8;
|
||||
hd->buf[62] = msb >> 16;
|
||||
hd->buf[63] = msb >> 24;
|
||||
transform( hd, hd->buf );
|
||||
burn_stack (108+5*sizeof(void*));
|
||||
|
||||
p = hd->buf;
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
#define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \
|
||||
*p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0)
|
||||
#else /* little endian */
|
||||
#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
|
||||
#endif
|
||||
X(0);
|
||||
X(1);
|
||||
X(2);
|
||||
X(3);
|
||||
X(4);
|
||||
#undef X
|
||||
}
|
||||
|
||||
static byte *
|
||||
rmd160_read( RMD160_CONTEXT *hd )
|
||||
{
|
||||
return hd->buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Shortcut functions which puts the hash value of the supplied buffer
|
||||
* into outbuf which must have a size of 20 bytes.
|
||||
*/
|
||||
void
|
||||
rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length )
|
||||
{
|
||||
RMD160_CONTEXT hd;
|
||||
|
||||
rmd160_init( &hd );
|
||||
rmd160_write( &hd, (byte*)buffer, length );
|
||||
rmd160_final( &hd );
|
||||
memcpy( outbuf, hd.buf, 20 );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
static const char *
|
||||
rmd160_get_info( int algo, size_t *contextsize,
|
||||
byte **r_asnoid, int *r_asnlen, int *r_mdlen,
|
||||
void (**r_init)( void *c ),
|
||||
void (**r_write)( void *c, byte *buf, size_t nbytes ),
|
||||
void (**r_final)( void *c ),
|
||||
byte *(**r_read)( void *c )
|
||||
)
|
||||
{
|
||||
static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */
|
||||
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
|
||||
0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
|
||||
|
||||
if( algo != 3 )
|
||||
return NULL;
|
||||
|
||||
*contextsize = sizeof(RMD160_CONTEXT);
|
||||
*r_asnoid = asn;
|
||||
*r_asnlen = DIM(asn);
|
||||
*r_mdlen = 20;
|
||||
*(void (**)(RMD160_CONTEXT *))r_init = rmd160_init;
|
||||
*(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write;
|
||||
*(void (**)(RMD160_CONTEXT *))r_final = rmd160_final;
|
||||
*(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read;
|
||||
|
||||
return "RIPEMD160";
|
||||
}
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "RMD160 ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int value;
|
||||
void (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 10, 1, 0, (void(*)(void))rmd160_get_info },
|
||||
{ 11, 1, 3 },
|
||||
};
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
switch( *class ) {
|
||||
case 11:
|
||||
case 21:
|
||||
case 31:
|
||||
ret = &func_table[i].value;
|
||||
break;
|
||||
default:
|
||||
#ifndef __riscos__
|
||||
ret = func_table[i].func;
|
||||
#else /* __riscos__ */
|
||||
ret = (void *) func_table[i].func;
|
||||
#endif /* __riscos__ */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
} while( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
rmd160_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* rmd160test.c - ripe md160 test program
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "rmd.h"
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: rmd160test\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
RMDHANDLE rmdhd;
|
||||
int i, n;
|
||||
byte buf[100], *p;
|
||||
|
||||
if( argc > 1 )
|
||||
usage();
|
||||
|
||||
rmdhd = rmd160_open(0);
|
||||
#if 1
|
||||
while( (n = fread( buf, 1, 100, stdin )) > 0 )
|
||||
rmd160_write(rmdhd, buf, n);
|
||||
#else
|
||||
for(i=0; i < 1000000; i++ )
|
||||
rmd160_putchar(rmdhd, 'a');
|
||||
#endif
|
||||
p = rmd160_final(rmdhd);
|
||||
for(i=0; i < 20; i++, p++ )
|
||||
printf("%02x", *p );
|
||||
putchar('\n');
|
||||
|
||||
rmd160_close(rmdhd);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
/* rndegd.c - interface to the EGD
|
||||
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
#include "ttyio.h"
|
||||
#include "dynload.h"
|
||||
#include "cipher.h"
|
||||
|
||||
#ifdef IS_MODULE
|
||||
#define _(a) (a)
|
||||
#else
|
||||
#include "i18n.h"
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, member) ((size_t) &((type *)0)->member)
|
||||
#endif
|
||||
|
||||
static int
|
||||
do_write( int fd, void *buf, size_t nbytes )
|
||||
{
|
||||
size_t nleft = nbytes;
|
||||
int nwritten;
|
||||
|
||||
while( nleft > 0 ) {
|
||||
nwritten = write( fd, buf, nleft);
|
||||
if( nwritten < 0 ) {
|
||||
if( errno == EINTR )
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
nleft -= nwritten;
|
||||
buf = (char*)buf + nwritten;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_read( int fd, void *buf, size_t nbytes )
|
||||
{
|
||||
int n, nread = 0;
|
||||
|
||||
do {
|
||||
do {
|
||||
n = read(fd, (char*)buf + nread, nbytes );
|
||||
} while( n == -1 && errno == EINTR );
|
||||
if( n == -1 )
|
||||
return -1;
|
||||
nread += n;
|
||||
} while( nread < nbytes );
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Note: we always use the highest level.
|
||||
* TO boost the performance we may want to add some
|
||||
* additional code for level 1
|
||||
*
|
||||
* Using a level of 0 should never block and better add nothing
|
||||
* to the pool. So this is just a dummy for EGD.
|
||||
*/
|
||||
static int
|
||||
gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
static int fd = -1;
|
||||
int n;
|
||||
byte buffer[256+2];
|
||||
int nbytes;
|
||||
int do_restart = 0;
|
||||
|
||||
if( !length )
|
||||
return 0;
|
||||
if( !level )
|
||||
return 0;
|
||||
|
||||
restart:
|
||||
if( do_restart ) {
|
||||
if( fd != -1 ) {
|
||||
close( fd );
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
if( fd == -1 ) {
|
||||
const char *bname = NULL;
|
||||
char *name;
|
||||
struct sockaddr_un addr;
|
||||
int addr_len;
|
||||
|
||||
#ifdef EGD_SOCKET_NAME
|
||||
bname = EGD_SOCKET_NAME;
|
||||
#endif
|
||||
if ( !bname || !*bname )
|
||||
bname = "=entropy";
|
||||
|
||||
if ( *bname == '=' && bname[1] )
|
||||
name = make_filename( g10_opt_homedir, bname+1 , NULL );
|
||||
else
|
||||
name = make_filename( bname , NULL );
|
||||
|
||||
if ( strlen(name)+1 >= sizeof addr.sun_path )
|
||||
g10_log_fatal ("EGD socketname is too long\n");
|
||||
|
||||
memset( &addr, 0, sizeof addr );
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy( addr.sun_path, name );
|
||||
addr_len = offsetof( struct sockaddr_un, sun_path )
|
||||
+ strlen( addr.sun_path );
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if( fd == -1 )
|
||||
g10_log_fatal("can't create unix domain socket: %s\n",
|
||||
strerror(errno) );
|
||||
if( connect( fd, (struct sockaddr*)&addr, addr_len) == -1 )
|
||||
g10_log_fatal("can't connect to `%s': %s\n",
|
||||
name, strerror(errno) );
|
||||
m_free(name);
|
||||
}
|
||||
do_restart = 0;
|
||||
|
||||
nbytes = length < 255? length : 255;
|
||||
/* first time we do it with a non blocking request */
|
||||
buffer[0] = 1; /* non blocking */
|
||||
buffer[1] = nbytes;
|
||||
if( do_write( fd, buffer, 2 ) == -1 )
|
||||
g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) );
|
||||
n = do_read( fd, buffer, 1 );
|
||||
if( n == -1 ) {
|
||||
g10_log_error("read error on EGD: %s\n", strerror(errno));
|
||||
do_restart = 1;
|
||||
goto restart;
|
||||
}
|
||||
n = buffer[0];
|
||||
if( n ) {
|
||||
n = do_read( fd, buffer, n );
|
||||
if( n == -1 ) {
|
||||
g10_log_error("read error on EGD: %s\n", strerror(errno));
|
||||
do_restart = 1;
|
||||
goto restart;
|
||||
}
|
||||
(*add)( buffer, n, requester );
|
||||
length -= n;
|
||||
}
|
||||
|
||||
if( length ) {
|
||||
#ifdef IS_MODULE
|
||||
fprintf( stderr,
|
||||
#else
|
||||
tty_printf(
|
||||
#endif
|
||||
_("Please wait, entropy is being gathered. Do some work if it would\n"
|
||||
"keep you from getting bored, because it will improve the quality\n"
|
||||
"of the entropy.\n") );
|
||||
}
|
||||
while( length ) {
|
||||
nbytes = length < 255? length : 255;
|
||||
|
||||
buffer[0] = 2; /* blocking */
|
||||
buffer[1] = nbytes;
|
||||
if( do_write( fd, buffer, 2 ) == -1 )
|
||||
g10_log_fatal("can't write to the EGD: %s\n", strerror(errno) );
|
||||
n = do_read( fd, buffer, nbytes );
|
||||
if( n == -1 ) {
|
||||
g10_log_error("read error on EGD: %s\n", strerror(errno));
|
||||
do_restart = 1;
|
||||
goto restart;
|
||||
}
|
||||
(*add)( buffer, n, requester );
|
||||
length -= n;
|
||||
}
|
||||
memset(buffer, 0, sizeof(buffer) );
|
||||
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "RNDEGD ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 40, 1, (int (*)(void))gather_random },
|
||||
};
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if ( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
ret = func_table[i].func;
|
||||
i++;
|
||||
} while ( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
rndegd_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version,
|
||||
gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
/* rndlinux.c - raw random number for OSes with /dev/random
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#if 0
|
||||
#ifdef HAVE_LINUX_RANDOM_H
|
||||
#include <sys/ioctl.h>
|
||||
#include <asm/types.h>
|
||||
#include <linux/random.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
#include "ttyio.h"
|
||||
#include "dynload.h"
|
||||
|
||||
#ifdef IS_MODULE
|
||||
#define _(a) (a)
|
||||
#else
|
||||
#include "i18n.h"
|
||||
#endif
|
||||
|
||||
static int open_device( const char *name, int minor );
|
||||
static int gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level );
|
||||
|
||||
#if 0
|
||||
#ifdef HAVE_DEV_RANDOM_IOCTL
|
||||
static ulong
|
||||
get_entropy_count( int fd )
|
||||
{
|
||||
ulong count;
|
||||
|
||||
if( ioctl( fd, RNDGETENTCNT, &count ) == -1 )
|
||||
g10_log_fatal("ioctl(RNDGETENTCNT) failed: %s\n", strerror(errno) );
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************
|
||||
* Used to open the /dev/random devices (Linux, xBSD, Solaris (if it exists), ...)
|
||||
*/
|
||||
static int
|
||||
open_device( const char *name, int minor )
|
||||
{
|
||||
int fd;
|
||||
struct stat sb;
|
||||
|
||||
fd = open( name, O_RDONLY );
|
||||
if( fd == -1 )
|
||||
g10_log_fatal("can't open %s: %s\n", name, strerror(errno) );
|
||||
if( fstat( fd, &sb ) )
|
||||
g10_log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
|
||||
/* Don't check device type for better portability */
|
||||
/* if( (!S_ISCHR(sb.st_mode)) && (!S_ISFIFO(sb.st_mode)) )
|
||||
g10_log_fatal("invalid random device!\n" ); */
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Note: Using a level of 0 should never block and better add nothing
|
||||
* to the pool. This is easy to accomplish with /dev/urandom.
|
||||
*/
|
||||
static int
|
||||
gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
static int fd_urandom = -1;
|
||||
static int fd_random = -1;
|
||||
int fd;
|
||||
int n;
|
||||
int warn=0;
|
||||
byte buffer[768];
|
||||
|
||||
if( level >= 2 ) {
|
||||
if( fd_random == -1 )
|
||||
fd_random = open_device( NAME_OF_DEV_RANDOM, 8 );
|
||||
fd = fd_random;
|
||||
}
|
||||
else {
|
||||
/* this will also be used for elve 0 but by using /dev/urandom
|
||||
* we can be sure that oit will never block. */
|
||||
if( fd_urandom == -1 )
|
||||
fd_urandom = open_device( NAME_OF_DEV_URANDOM, 9 );
|
||||
fd = fd_urandom;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef HAVE_DEV_RANDOM_IOCTL
|
||||
g10_log_info("entropy count of %d is %lu\n", fd, get_entropy_count(fd) );
|
||||
#endif
|
||||
#endif
|
||||
while( length ) {
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int rc;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fd, &rfds);
|
||||
tv.tv_sec = 3;
|
||||
tv.tv_usec = 0;
|
||||
if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) ) {
|
||||
if( !warn )
|
||||
#ifdef IS_MODULE
|
||||
fprintf(stderr,
|
||||
#else
|
||||
tty_printf(
|
||||
#endif
|
||||
_("\n"
|
||||
"Not enough random bytes available. Please do some other work to give\n"
|
||||
"the OS a chance to collect more entropy! (Need %d more bytes)\n"), (int)length );
|
||||
warn = 1;
|
||||
continue;
|
||||
}
|
||||
else if( rc == -1 ) {
|
||||
#ifdef IS_MODULE
|
||||
fprintf(stderr,
|
||||
#else
|
||||
tty_printf(
|
||||
#endif
|
||||
"select() error: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
|
||||
n = read(fd, buffer, nbytes );
|
||||
if( n >= 0 && n > nbytes ) {
|
||||
g10_log_error("bogus read from random device (n=%d)\n", n );
|
||||
n = nbytes;
|
||||
}
|
||||
} while( n == -1 && errno == EINTR );
|
||||
if( n == -1 )
|
||||
g10_log_fatal("read error on random device: %s\n", strerror(errno));
|
||||
(*add)( buffer, n, requester );
|
||||
length -= n;
|
||||
}
|
||||
memset(buffer, 0, sizeof(buffer) );
|
||||
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "RNDLINUX ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 40, 1, (int (*)(void))gather_random },
|
||||
};
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Enumerate the names of the functions together with informations about
|
||||
* this function. Set sequence to an integer with a initial value of 0 and
|
||||
* do not change it.
|
||||
* If what is 0 all kind of functions are returned.
|
||||
* Return values: class := class of function:
|
||||
* 10 = message digest algorithm info function
|
||||
* 11 = integer with available md algorithms
|
||||
* 20 = cipher algorithm info function
|
||||
* 21 = integer with available cipher algorithms
|
||||
* 30 = public key algorithm info function
|
||||
* 31 = integer with available pubkey algorithms
|
||||
* 40 = get gather_random function
|
||||
* 41 = get fast_random_poll function
|
||||
* version = interface version of the function/pointer
|
||||
* (currently this is 1 for all functions)
|
||||
*/
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if ( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
ret = func_table[i].func;
|
||||
i++;
|
||||
} while ( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
rndlinux_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version,
|
||||
gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/* rndriscos.c - raw random number for RISC OS
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <kernel.h>
|
||||
#include <swis.h>
|
||||
#include "util.h"
|
||||
#include "dynload.h"
|
||||
|
||||
static int init_device(void);
|
||||
static int gather_random(void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level);
|
||||
|
||||
#define CryptRandom_Byte 0x51980
|
||||
|
||||
/****************
|
||||
* Used to load the CryptRandom module if it isn't already loaded
|
||||
*/
|
||||
static int
|
||||
init_device(void)
|
||||
{
|
||||
_kernel_swi_regs r;
|
||||
|
||||
/* Is CryptRandom already loaded? */
|
||||
r.r[0] = 18;
|
||||
r.r[1] = (int) "CryptRandom";
|
||||
if (!_kernel_swi(OS_Module, &r, &r))
|
||||
return 1;
|
||||
|
||||
/* Is it named CryptRand and inside GnuPG$Path? */
|
||||
r.r[0] = 1;
|
||||
r.r[1] = (int) "GnuPG:CryptRand";
|
||||
if (!_kernel_swi(OS_Module, &r, &r))
|
||||
return 1;
|
||||
|
||||
/* Is it named CryptRandom and inside GnuPG$Path? */
|
||||
r.r[0] = 1;
|
||||
r.r[1] = (int) "GnuPG:CryptRandom";
|
||||
if (!_kernel_swi(OS_Module, &r, &r))
|
||||
return 1;
|
||||
|
||||
/* Can't find CryptRandom in the default locations */
|
||||
g10_log_fatal("Can't load module CryptRandom.\n");
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
*/
|
||||
static int
|
||||
gather_random(void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level)
|
||||
{
|
||||
static int initialized = 0;
|
||||
int n;
|
||||
byte buffer[768];
|
||||
_kernel_swi_regs r;
|
||||
_kernel_oserror *e;
|
||||
|
||||
if (!initialized)
|
||||
initialized = init_device();
|
||||
|
||||
while (length) {
|
||||
int nbytes = length < sizeof(buffer) ? length : sizeof(buffer);
|
||||
|
||||
for (n = 0; n < nbytes; n++) {
|
||||
if (e = _kernel_swi(CryptRandom_Byte, &r, &r))
|
||||
g10_log_fatal("CryptRandom module isn't working as expected!\n");
|
||||
buffer[n] = (byte) r.r[0];
|
||||
}
|
||||
|
||||
(*add)(buffer, n, requester);
|
||||
length -= n;
|
||||
}
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "RNDRISCOS ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 40, 1, (int (*)(void))gather_random },
|
||||
};
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if ( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
ret = (void*) func_table[i].func;
|
||||
i++;
|
||||
} while ( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
rndriscos_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version,
|
||||
gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,915 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* *
|
||||
* Unix Randomness-Gathering Code *
|
||||
* *
|
||||
* Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. *
|
||||
* Heavily modified for GnuPG by Werner Koch *
|
||||
* *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
/* This module is part of the cryptlib continuously seeded pseudorandom
|
||||
number generator. For usage conditions, see lib_rand.c
|
||||
|
||||
[Here is the notice from lib_rand.c:]
|
||||
|
||||
This module and the misc/rnd*.c modules represent the cryptlib
|
||||
continuously seeded pseudorandom number generator (CSPRNG) as described in
|
||||
my 1998 Usenix Security Symposium paper "The generation of random numbers
|
||||
for cryptographic purposes".
|
||||
|
||||
The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
|
||||
1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
|
||||
modules and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice
|
||||
and this permission notice in its entirety.
|
||||
|
||||
2. Redistributions in binary form must reproduce the copyright notice in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. A copy of any bugfixes or enhancements made must be provided to the
|
||||
author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
|
||||
baseline version of the code.
|
||||
|
||||
ALTERNATIVELY, the code may be distributed under the terms of the GNU
|
||||
General Public License, version 2 or any later version published by the
|
||||
Free Software Foundation, in which case the provisions of the GNU GPL are
|
||||
required INSTEAD OF the above restrictions.
|
||||
|
||||
Although not required under the terms of the GPL, it would still be nice if
|
||||
you could make any changes available to the author to allow a consistent
|
||||
code base to be maintained */
|
||||
|
||||
|
||||
|
||||
/* General includes */
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* OS-specific includes */
|
||||
|
||||
#ifdef __osf__
|
||||
/* Somewhere in the morass of system-specific cruft which OSF/1 pulls in
|
||||
* via the following includes are various endianness defines, so we
|
||||
* undefine the cryptlib ones, which aren't really needed for this module
|
||||
* anyway */
|
||||
#undef BIG_ENDIAN
|
||||
#undef LITTLE_ENDIAN
|
||||
#endif /* __osf__ */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#ifndef __QNX__
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ipc.h>
|
||||
#endif /* __QNX__ */
|
||||
#include <sys/time.h> /* SCO and SunOS need this before resource.h */
|
||||
#ifndef __QNX__
|
||||
#include <sys/resource.h>
|
||||
#endif /* __QNX__ */
|
||||
#if defined( _AIX ) || defined( __QNX__ )
|
||||
#include <sys/select.h>
|
||||
#endif /* _AIX || __QNX__ */
|
||||
#ifndef __QNX__
|
||||
#include <sys/shm.h>
|
||||
#include <signal.h>
|
||||
#include <sys/signal.h>
|
||||
#endif /* __QNX__ */
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h> /* Verschiedene komische Typen */
|
||||
#if defined( __hpux ) && ( OS_VERSION == 9 )
|
||||
#include <vfork.h>
|
||||
#endif /* __hpux 9.x, after that it's in unistd.h */
|
||||
#include <sys/wait.h>
|
||||
/* #include <kitchensink.h> */
|
||||
#ifdef __QNX__
|
||||
#include <signal.h>
|
||||
#include <process.h>
|
||||
#endif /* __QNX__ */
|
||||
#include <errno.h>
|
||||
|
||||
#include "types.h" /* for byte and u32 typedefs */
|
||||
#ifndef IS_MODULE
|
||||
#include "dynload.h"
|
||||
#endif
|
||||
#include "util.h"
|
||||
|
||||
#ifndef EAGAIN
|
||||
#define EAGAIN EWOULDBLOCK
|
||||
#endif
|
||||
#ifndef STDIN_FILENO
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
#endif
|
||||
|
||||
#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */
|
||||
|
||||
/* The structure containing information on random-data sources. Each
|
||||
* record contains the source and a relative estimate of its usefulness
|
||||
* (weighting) which is used to scale the number of kB of output from the
|
||||
* source (total = data_bytes / usefulness). Usually the weighting is in the
|
||||
* range 1-3 (or 0 for especially useless sources), resulting in a usefulness
|
||||
* rating of 1...3 for each kB of source output (or 0 for the useless
|
||||
* sources).
|
||||
*
|
||||
* If the source is constantly changing (certain types of network statistics
|
||||
* have this characteristic) but the amount of output is small, the weighting
|
||||
* is given as a negative value to indicate that the output should be treated
|
||||
* as if a minimum of 1K of output had been obtained. If the source produces
|
||||
* a lot of output then the scale factor is fractional, resulting in a
|
||||
* usefulness rating of < 1 for each kB of source output.
|
||||
*
|
||||
* In order to provide enough randomness to satisfy the requirements for a
|
||||
* slow poll, we need to accumulate at least 20 points of usefulness (a
|
||||
* typical system should get about 30 points).
|
||||
*
|
||||
* Some potential options are missed out because of special considerations.
|
||||
* pstat -i and pstat -f can produce amazing amounts of output (the record
|
||||
* is 600K on an Oracle server) which floods the buffer and doesn't yield
|
||||
* anything useful (apart from perhaps increasing the entropy of the vmstat
|
||||
* output a bit), so we don't bother with this. pstat in general produces
|
||||
* quite a bit of output, but it doesn't change much over time, so it gets
|
||||
* very low weightings. netstat -s produces constantly-changing output but
|
||||
* also produces quite a bit of it, so it only gets a weighting of 2 rather
|
||||
* than 3. The same holds for netstat -in, which gets 1 rather than 2.
|
||||
*
|
||||
* Some binaries are stored in different locations on different systems so
|
||||
* alternative paths are given for them. The code sorts out which one to
|
||||
* run by itself, once it finds an exectable somewhere it moves on to the
|
||||
* next source. The sources are arranged roughly in their order of
|
||||
* usefulness, occasionally sources which provide a tiny amount of
|
||||
* relatively useless data are placed ahead of ones which provide a large
|
||||
* amount of possibly useful data because another 100 bytes can't hurt, and
|
||||
* it means the buffer won't be swamped by one or two high-output sources.
|
||||
* All the high-output sources are clustered towards the end of the list
|
||||
* for this reason. Some binaries are checked for in a certain order, for
|
||||
* example under Slowaris /usr/ucb/ps understands aux as an arg, but the
|
||||
* others don't. Some systems have conditional defines enabling alternatives
|
||||
* to commands which don't understand the usual options but will provide
|
||||
* enough output (in the form of error messages) to look like they're the
|
||||
* real thing, causing alternative options to be skipped (we can't check the
|
||||
* return either because some commands return peculiar, non-zero status even
|
||||
* when they're working correctly).
|
||||
*
|
||||
* In order to maximise use of the buffer, the code performs a form of run-
|
||||
* length compression on its input where a repeated sequence of bytes is
|
||||
* replaced by the occurrence count mod 256. Some commands output an awful
|
||||
* lot of whitespace, this measure greatly increases the amount of data we
|
||||
* can fit in the buffer.
|
||||
*
|
||||
* When we scale the weighting using the SC() macro, some preprocessors may
|
||||
* give a division by zero warning for the most obvious expression
|
||||
* 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
|
||||
* trap), so we define a value SC_0 which evaluates to zero when fed to
|
||||
* '1024 / SC_0' */
|
||||
|
||||
#define SC( weight ) ( 1024 / weight ) /* Scale factor */
|
||||
#define SC_0 16384 /* SC( SC_0 ) evalutes to 0 */
|
||||
|
||||
static struct RI {
|
||||
const char *path; /* Path to check for existence of source */
|
||||
const char *arg; /* Args for source */
|
||||
const int usefulness; /* Usefulness of source */
|
||||
FILE *pipe; /* Pipe to source as FILE * */
|
||||
int pipeFD; /* Pipe to source as FD */
|
||||
pid_t pid; /* pid of child for waitpid() */
|
||||
int length; /* Quantity of output produced */
|
||||
const int hasAlternative; /* Whether source has alt.location */
|
||||
} dataSources[] = {
|
||||
|
||||
{ "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
|
||||
{ "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
|
||||
{ "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
|
||||
{ "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
|
||||
{ "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
|
||||
SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
|
||||
SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
|
||||
SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0",
|
||||
SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0",
|
||||
SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
|
||||
SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
|
||||
{ "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 },
|
||||
#if defined( __sgi ) || defined( __hpux )
|
||||
{ "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 },
|
||||
#endif /* __sgi || __hpux */
|
||||
{ "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/
|
||||
{ "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 },
|
||||
/* Unreliable source, depends on system usage */
|
||||
{ "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 },
|
||||
{ "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 },
|
||||
{ "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 },
|
||||
{ "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 },
|
||||
{ "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
|
||||
{ "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
|
||||
/* pstat is your friend */
|
||||
{ "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 },
|
||||
#ifdef __sgi
|
||||
{ "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
|
||||
#endif /* __sgi */
|
||||
#ifdef __hpux
|
||||
{ "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
|
||||
#endif /* __hpux */
|
||||
{ "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0",
|
||||
SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
|
||||
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0",
|
||||
SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
|
||||
{ "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/sbin/ripquery", "-nw 1 127.0.0.1",
|
||||
SC(0.1), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
|
||||
{ "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 },
|
||||
/* This is very environment-dependant. If network traffic is low, it'll
|
||||
* probably time out before delivering 5 packets, which is OK because
|
||||
* it'll probably be fixed stuff like ARP anyway */
|
||||
{ "/usr/sbin/advfsstat", "-b usr_domain",
|
||||
SC(SC_0), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/sbin/advfsstat", "-l 2 usr_domain",
|
||||
SC(0.5), NULL, 0, 0, 0, 0},
|
||||
{ "/usr/sbin/advfsstat", "-p usr_domain",
|
||||
SC(SC_0), NULL, 0, 0, 0, 0},
|
||||
/* This is a complex and screwball program. Some systems have things
|
||||
* like rX_dmn, x = integer, for RAID systems, but the statistics are
|
||||
* pretty dodgy */
|
||||
#ifdef __QNXNTO__
|
||||
{ "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
|
||||
NULL, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if 0
|
||||
/* The following aren't enabled since they're somewhat slow and not very
|
||||
* unpredictable, however they give an indication of the sort of sources
|
||||
* you can use (for example the finger might be more useful on a
|
||||
* firewalled internal network) */
|
||||
{ "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
|
||||
{ "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
|
||||
SC(0.9), NULL, 0, 0, 0, 0 },
|
||||
{ "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
|
||||
#endif /* 0 */
|
||||
{ NULL, NULL, 0, NULL, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static byte *gather_buffer; /* buffer for gathering random noise */
|
||||
static int gather_buffer_size; /* size of the memory buffer */
|
||||
static uid_t gatherer_uid;
|
||||
|
||||
/* The message structure used to communicate with the parent */
|
||||
typedef struct {
|
||||
int usefulness; /* usefulness of data */
|
||||
int ndata; /* valid bytes in data */
|
||||
char data[500]; /* gathered data */
|
||||
} GATHER_MSG;
|
||||
|
||||
|
||||
#ifndef HAVE_WAITPID
|
||||
pid_t
|
||||
waitpid(pid_t pid, int *statptr, int options)
|
||||
{
|
||||
#ifdef HAVE_WAIT4
|
||||
return wait4(pid, statptr, options, NULL);
|
||||
#else
|
||||
/* If wait4 is also not available, try wait3 for SVR3 variants */
|
||||
/* Less ideal because can't actually request a specific pid */
|
||||
/* For that reason, first check to see if pid is for an */
|
||||
/* existing process. */
|
||||
int tmp_pid, dummystat;;
|
||||
if (kill(pid, 0) == -1) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
if (statptr == NULL)
|
||||
statptr = &dummystat;
|
||||
while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
|
||||
(tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
|
||||
;
|
||||
return tmp_pid;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Under SunOS popen() doesn't record the pid of the child process. When
|
||||
* pclose() is called, instead of calling waitpid() for the correct child, it
|
||||
* calls wait() repeatedly until the right child is reaped. The problem is
|
||||
* that this reaps any other children that happen to have died at that
|
||||
* moment, and when their pclose() comes along, the process hangs forever.
|
||||
* The fix is to use a wrapper for popen()/pclose() which saves the pid in
|
||||
* the dataSources structure (code adapted from GNU-libc's popen() call).
|
||||
*
|
||||
* Aut viam inveniam aut faciam */
|
||||
|
||||
static FILE *
|
||||
my_popen(struct RI *entry)
|
||||
{
|
||||
|
||||
int pipedes[2];
|
||||
FILE *stream;
|
||||
|
||||
/* Create the pipe */
|
||||
if (pipe(pipedes) < 0)
|
||||
return (NULL);
|
||||
|
||||
/* Fork off the child ("vfork() is like an OS orgasm. All OS's want to
|
||||
* do it, but most just end up faking it" - Chris Wedgwood). If your OS
|
||||
* supports it, you should try to use vfork() here because it's somewhat
|
||||
* more efficient */
|
||||
#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
|
||||
defined(__hpux)
|
||||
entry->pid = vfork();
|
||||
#else /* */
|
||||
entry->pid = fork();
|
||||
#endif /* Unixen which have vfork() */
|
||||
if (entry->pid == (pid_t) - 1) {
|
||||
/* The fork failed */
|
||||
close(pipedes[0]);
|
||||
close(pipedes[1]);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (entry->pid == (pid_t) 0) {
|
||||
struct passwd *passwd;
|
||||
|
||||
/* We are the child. Make the read side of the pipe be stdout */
|
||||
if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
|
||||
exit(127);
|
||||
|
||||
/* Now that everything is set up, give up our permissions to make
|
||||
* sure we don't read anything sensitive. If the getpwnam() fails,
|
||||
* we default to -1, which is usually nobody */
|
||||
if (gatherer_uid == (uid_t)-1 && \
|
||||
(passwd = getpwnam("nobody")) != NULL)
|
||||
gatherer_uid = passwd->pw_uid;
|
||||
|
||||
setuid(gatherer_uid);
|
||||
|
||||
/* Close the pipe descriptors */
|
||||
close(pipedes[STDIN_FILENO]);
|
||||
close(pipedes[STDOUT_FILENO]);
|
||||
|
||||
/* Try and exec the program */
|
||||
execl(entry->path, entry->path, entry->arg, NULL);
|
||||
|
||||
/* Die if the exec failed */
|
||||
exit(127);
|
||||
}
|
||||
|
||||
/* We are the parent. Close the irrelevant side of the pipe and open
|
||||
* the relevant side as a new stream. Mark our side of the pipe to
|
||||
* close on exec, so new children won't see it */
|
||||
close(pipedes[STDOUT_FILENO]);
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
stream = fdopen(pipedes[STDIN_FILENO], "r");
|
||||
|
||||
if (stream == NULL) {
|
||||
int savedErrno = errno;
|
||||
|
||||
/* The stream couldn't be opened or the child structure couldn't be
|
||||
* allocated. Kill the child and close the other side of the pipe */
|
||||
kill(entry->pid, SIGKILL);
|
||||
if (stream == NULL)
|
||||
close(pipedes[STDOUT_FILENO]);
|
||||
else
|
||||
fclose(stream);
|
||||
|
||||
waitpid(entry->pid, NULL, 0);
|
||||
|
||||
entry->pid = 0;
|
||||
errno = savedErrno;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (stream);
|
||||
}
|
||||
|
||||
static int
|
||||
my_pclose(struct RI *entry)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (fclose(entry->pipe))
|
||||
return (-1);
|
||||
|
||||
/* We ignore the return value from the process because some programs
|
||||
* return funny values which would result in the input being discarded
|
||||
* even if they executed successfully. This isn't a problem because the
|
||||
* result data size threshold will filter out any programs which exit
|
||||
* with a usage message without producing useful output */
|
||||
if (waitpid(entry->pid, NULL, 0) != entry->pid)
|
||||
status = -1;
|
||||
|
||||
entry->pipe = NULL;
|
||||
entry->pid = 0;
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
/* Unix slow poll (without special support for Linux)
|
||||
*
|
||||
* If a few of the randomness sources create a large amount of output then
|
||||
* the slowPoll() stops once the buffer has been filled (but before all the
|
||||
* randomness sources have been sucked dry) so that the 'usefulness' factor
|
||||
* remains below the threshold. For this reason the gatherer buffer has to
|
||||
* be fairly sizeable on moderately loaded systems. This is something of a
|
||||
* bug since the usefulness should be influenced by the amount of output as
|
||||
* well as the source type */
|
||||
|
||||
|
||||
static int
|
||||
slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
|
||||
{
|
||||
int moreSources;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
#if defined( __hpux )
|
||||
size_t maxFD = 0;
|
||||
#else
|
||||
int maxFD = 0;
|
||||
#endif /* OS-specific brokenness */
|
||||
int bufPos, i, usefulness = 0;
|
||||
|
||||
|
||||
/* Fire up each randomness source */
|
||||
FD_ZERO(&fds);
|
||||
for (i = 0; dataSources[i].path != NULL; i++) {
|
||||
/* Since popen() is a fairly heavy function, we check to see whether
|
||||
* the executable exists before we try to run it */
|
||||
if (access(dataSources[i].path, X_OK)) {
|
||||
if( dbgfp && dbgall )
|
||||
fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
|
||||
dataSources[i].hasAlternative ?
|
||||
", has alternatives" : "");
|
||||
dataSources[i].pipe = NULL;
|
||||
}
|
||||
else
|
||||
dataSources[i].pipe = my_popen(&dataSources[i]);
|
||||
|
||||
if (dataSources[i].pipe != NULL) {
|
||||
dataSources[i].pipeFD = fileno(dataSources[i].pipe);
|
||||
if (dataSources[i].pipeFD > maxFD)
|
||||
maxFD = dataSources[i].pipeFD;
|
||||
#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
|
||||
fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
FD_SET(dataSources[i].pipeFD, &fds);
|
||||
dataSources[i].length = 0;
|
||||
|
||||
/* If there are alternatives for this command, don't try and
|
||||
* execute them */
|
||||
while (dataSources[i].hasAlternative) {
|
||||
if( dbgfp && dbgall )
|
||||
fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Suck all the data we can get from each of the sources */
|
||||
bufPos = 0;
|
||||
moreSources = 1;
|
||||
while (moreSources && bufPos <= gather_buffer_size) {
|
||||
/* Wait for data to become available from any of the sources, with a
|
||||
* timeout of 10 seconds. This adds even more randomness since data
|
||||
* becomes available in a nondeterministic fashion. Kudos to HP's QA
|
||||
* department for managing to ship a select() which breaks its own
|
||||
* prototype */
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
#if defined( __hpux ) && ( OS_VERSION == 9 )
|
||||
if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
|
||||
#else /* */
|
||||
if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
|
||||
#endif /* __hpux */
|
||||
break;
|
||||
|
||||
/* One of the sources has data available, read it into the buffer */
|
||||
for (i = 0; dataSources[i].path != NULL; i++) {
|
||||
if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
|
||||
size_t noBytes;
|
||||
|
||||
if ((noBytes = fread(gather_buffer + bufPos, 1,
|
||||
gather_buffer_size - bufPos,
|
||||
dataSources[i].pipe)) == 0) {
|
||||
if (my_pclose(&dataSources[i]) == 0) {
|
||||
int total = 0;
|
||||
|
||||
/* Try and estimate how much entropy we're getting
|
||||
* from a data source */
|
||||
if (dataSources[i].usefulness) {
|
||||
if (dataSources[i].usefulness < 0)
|
||||
total = (dataSources[i].length + 999)
|
||||
/ -dataSources[i].usefulness;
|
||||
else
|
||||
total = dataSources[i].length
|
||||
/ dataSources[i].usefulness;
|
||||
}
|
||||
if( dbgfp )
|
||||
fprintf(dbgfp,
|
||||
"%s %s contributed %d bytes, "
|
||||
"usefulness = %d\n", dataSources[i].path,
|
||||
(dataSources[i].arg != NULL) ?
|
||||
dataSources[i].arg : "",
|
||||
dataSources[i].length, total);
|
||||
if( dataSources[i].length )
|
||||
usefulness += total;
|
||||
}
|
||||
dataSources[i].pipe = NULL;
|
||||
}
|
||||
else {
|
||||
int currPos = bufPos;
|
||||
int endPos = bufPos + noBytes;
|
||||
|
||||
/* Run-length compress the input byte sequence */
|
||||
while (currPos < endPos) {
|
||||
int ch = gather_buffer[currPos];
|
||||
|
||||
/* If it's a single byte, just copy it over */
|
||||
if (ch != gather_buffer[currPos + 1]) {
|
||||
gather_buffer[bufPos++] = ch;
|
||||
currPos++;
|
||||
}
|
||||
else {
|
||||
int count = 0;
|
||||
|
||||
/* It's a run of repeated bytes, replace them
|
||||
* with the byte count mod 256 */
|
||||
while ((ch == gather_buffer[currPos])
|
||||
&& currPos < endPos) {
|
||||
count++;
|
||||
currPos++;
|
||||
}
|
||||
gather_buffer[bufPos++] = count;
|
||||
noBytes -= count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the number of (compressed) bytes of input we
|
||||
* obtained */
|
||||
dataSources[i].length += noBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if there is more input available on any of the sources */
|
||||
moreSources = 0;
|
||||
FD_ZERO(&fds);
|
||||
for (i = 0; dataSources[i].path != NULL; i++) {
|
||||
if (dataSources[i].pipe != NULL) {
|
||||
FD_SET(dataSources[i].pipeFD, &fds);
|
||||
moreSources = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( dbgfp ) {
|
||||
fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
|
||||
fflush(dbgfp);
|
||||
}
|
||||
*nbytes = bufPos;
|
||||
return usefulness;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Start the gatherer process which writes messages of
|
||||
* type GATHERER_MSG to pipedes
|
||||
*/
|
||||
static void
|
||||
start_gatherer( int pipefd )
|
||||
{
|
||||
FILE *dbgfp = NULL;
|
||||
int dbgall;
|
||||
|
||||
{
|
||||
const char *s = getenv("GNUPG_RNDUNIX_DBG");
|
||||
if( s ) {
|
||||
dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
|
||||
if( !dbgfp )
|
||||
g10_log_info("can't open debug file `%s': %s\n",
|
||||
s, strerror(errno) );
|
||||
else
|
||||
fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
|
||||
}
|
||||
dbgall = !!getenv("GNUPG_RNDUNIX_DBGALL");
|
||||
}
|
||||
/* close all files but the ones we need */
|
||||
{ int nmax, n1, n2, i;
|
||||
#ifdef _SC_OPEN_MAX
|
||||
if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
|
||||
#ifdef _POSIX_OPEN_MAX
|
||||
nmax = _POSIX_OPEN_MAX;
|
||||
#else
|
||||
nmax = 20; /* assume a reasonable value */
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
nmax = 20; /* assume a reasonable value */
|
||||
#endif
|
||||
n1 = fileno( stderr );
|
||||
n2 = dbgfp? fileno( dbgfp ) : -1;
|
||||
for(i=0; i < nmax; i++ ) {
|
||||
if( i != n1 && i != n2 && i != pipefd )
|
||||
close(i);
|
||||
}
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set up the buffer */
|
||||
gather_buffer_size = GATHER_BUFSIZE;
|
||||
gather_buffer = malloc( gather_buffer_size );
|
||||
if( !gather_buffer ) {
|
||||
g10_log_error("out of core while allocating the gatherer buffer\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* Reset the SIGC(H)LD handler to the system default. This is necessary
|
||||
* because if the program which cryptlib is a part of installs its own
|
||||
* SIGC(H)LD handler, it will end up reaping the cryptlib children before
|
||||
* cryptlib can. As a result, my_pclose() will call waitpid() on a
|
||||
* process which has already been reaped by the installed handler and
|
||||
* return an error, so the read data won't be added to the randomness
|
||||
* pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and
|
||||
* the BSD/Posix SIGCHLD, so we need to handle either possibility */
|
||||
#ifdef SIGCLD
|
||||
signal(SIGCLD, SIG_DFL);
|
||||
#else
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
#endif
|
||||
|
||||
fclose(stderr); /* Arrghh!! It's Stuart code!! */
|
||||
|
||||
for(;;) {
|
||||
GATHER_MSG msg;
|
||||
size_t nbytes;
|
||||
const char *p;
|
||||
|
||||
msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
|
||||
p = gather_buffer;
|
||||
while( nbytes ) {
|
||||
msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
|
||||
memcpy( msg.data, p, msg.ndata );
|
||||
nbytes -= msg.ndata;
|
||||
p += msg.ndata;
|
||||
|
||||
while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
|
||||
if( errno == EINTR )
|
||||
continue;
|
||||
if( errno == EAGAIN ) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
continue;
|
||||
}
|
||||
if( errno == EPIPE ) /* parent has exited, so give up */
|
||||
exit(0);
|
||||
|
||||
/* we can't do very much here because stderr is closed */
|
||||
if( dbgfp )
|
||||
fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
|
||||
strerror(errno) );
|
||||
/* we start a new poll to give the system some time */
|
||||
nbytes = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* we are killed when the parent dies */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_a_msg( int fd, GATHER_MSG *msg )
|
||||
{
|
||||
char *buffer = (char*)msg;
|
||||
size_t length = sizeof( *msg );
|
||||
int n;
|
||||
|
||||
do {
|
||||
do {
|
||||
n = read(fd, buffer, length );
|
||||
} while( n == -1 && errno == EINTR );
|
||||
if( n == -1 )
|
||||
return -1;
|
||||
buffer += n;
|
||||
length -= n;
|
||||
} while( length );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Using a level of 0 should never block and better add nothing
|
||||
* to the pool. So this is just a dummy for this gatherer.
|
||||
*/
|
||||
static int
|
||||
gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
static pid_t gatherer_pid = 0;
|
||||
static int pipedes[2];
|
||||
GATHER_MSG msg;
|
||||
size_t n;
|
||||
|
||||
if( !level )
|
||||
return 0;
|
||||
|
||||
if( !gatherer_pid ) {
|
||||
/* make sure we are not setuid */
|
||||
if( getuid() != geteuid() )
|
||||
BUG();
|
||||
/* time to start the gatherer process */
|
||||
if( pipe( pipedes ) ) {
|
||||
g10_log_error("pipe() failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
gatherer_pid = fork();
|
||||
if( gatherer_pid == -1 ) {
|
||||
g10_log_error("can't for gatherer process: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if( !gatherer_pid ) {
|
||||
start_gatherer( pipedes[1] );
|
||||
/* oops, can't happen */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* now read from the gatherer */
|
||||
while( length ) {
|
||||
int goodness;
|
||||
ulong subtract;
|
||||
|
||||
if( read_a_msg( pipedes[0], &msg ) ) {
|
||||
g10_log_error("reading from gatherer pipe failed: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if( level > 1 ) {
|
||||
if( msg.usefulness > 30 )
|
||||
goodness = 100;
|
||||
else if ( msg.usefulness )
|
||||
goodness = msg.usefulness * 100 / 30;
|
||||
else
|
||||
goodness = 0;
|
||||
}
|
||||
else if( level ) {
|
||||
if( msg.usefulness > 15 )
|
||||
goodness = 100;
|
||||
else if ( msg.usefulness )
|
||||
goodness = msg.usefulness * 100 / 15;
|
||||
else
|
||||
goodness = 0;
|
||||
}
|
||||
else
|
||||
goodness = 100; /* goodness of level 0 is always 100 % */
|
||||
|
||||
n = msg.ndata;
|
||||
if( n > length )
|
||||
n = length;
|
||||
(*add)( msg.data, n, requester );
|
||||
|
||||
/* this is the trick how e cope with the goodness */
|
||||
subtract = (ulong)n * goodness / 100;
|
||||
/* subtract at least 1 byte to avoid infinite loops */
|
||||
length -= subtract ? subtract : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "RNDUNIX ($Revision$)";
|
||||
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 40, 1, (int (*)(void))gather_random },
|
||||
};
|
||||
|
||||
/****************
|
||||
* Enumerate the names of the functions together with informations about
|
||||
* this function. Set sequence to an integer with a initial value of 0 and
|
||||
* do not change it.
|
||||
* If what is 0 all kind of functions are returned.
|
||||
* Return values: class := class of function:
|
||||
* 10 = message digest algorithm info function
|
||||
* 11 = integer with available md algorithms
|
||||
* 20 = cipher algorithm info function
|
||||
* 21 = integer with available cipher algorithms
|
||||
* 30 = public key algorithm info function
|
||||
* 31 = integer with available pubkey algorithms
|
||||
* 40 = get read_random_source() function
|
||||
* 41 = get fast_random_poll function
|
||||
* version = interface version of the function/pointer
|
||||
* (currently this is 1 for all functions)
|
||||
*/
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if ( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
ret = func_table[i].func;
|
||||
i++;
|
||||
} while ( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
rndunix_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version,
|
||||
gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,969 @@
|
|||
/* rndw32.c - W32 entropy gatherer
|
||||
* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
* Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-1999
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
*************************************************************************
|
||||
* The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann.
|
||||
* Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this
|
||||
* copyright notice:
|
||||
*
|
||||
* This module is part of the cryptlib continuously seeded pseudorandom
|
||||
* number generator. For usage conditions, see lib_rand.c
|
||||
*
|
||||
* [Here is the notice from lib_rand.c, which is now called dev_sys.c]
|
||||
*
|
||||
* This module and the misc/rnd*.c modules represent the cryptlib
|
||||
* continuously seeded pseudorandom number generator (CSPRNG) as described in
|
||||
* my 1998 Usenix Security Symposium paper "The generation of random numbers
|
||||
* for cryptographic purposes".
|
||||
*
|
||||
* The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
|
||||
* 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
|
||||
* modules and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice
|
||||
* and this permission notice in its entirety.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the copyright notice in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. A copy of any bugfixes or enhancements made must be provided to the
|
||||
* author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
|
||||
* baseline version of the code.
|
||||
*
|
||||
* ALTERNATIVELY, the code may be distributed under the terms of the GNU
|
||||
* General Public License, version 2 or any later version published by the
|
||||
* Free Software Foundation, in which case the provisions of the GNU GPL are
|
||||
* required INSTEAD OF the above restrictions.
|
||||
*
|
||||
* Although not required under the terms of the GPL, it would still be nice if
|
||||
* you could make any changes available to the author to allow a consistent
|
||||
* code base to be maintained
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <windows.h>
|
||||
#ifdef __CYGWIN32__
|
||||
# include <winioctl.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
#include "dynload.h"
|
||||
|
||||
/* We do not use the netropy DLL anymore because a standalone program is
|
||||
* easier to maintain and */
|
||||
/*#define USE_ENTROPY_DLL*/
|
||||
|
||||
|
||||
|
||||
#ifdef IS_MODULE
|
||||
#define _(a) (a)
|
||||
#else
|
||||
#include "i18n.h"
|
||||
#endif
|
||||
|
||||
|
||||
static int debug_me;
|
||||
|
||||
#ifdef USE_ENTROPY_DLL
|
||||
|
||||
#define WIN32_SLOW_SEEDER 0
|
||||
#define WIN32_FAST_SEEDER 1
|
||||
|
||||
#define PCP_SUCCESS 0
|
||||
#define PCP_NULL_POINTER 1
|
||||
#define PCP_SEEDER_FAILED 2
|
||||
#define PCP_SEEDER_NO_MEM 3
|
||||
#define PCP_SEEDER_TOO_SMALL 4
|
||||
#define PCP_DLL_LOAD_FAILED 5
|
||||
#define PCP_UNKNOWN_PLATFORM 6
|
||||
#define PCP_ERROR_VERSION 7
|
||||
#define PCP_DLL_FUNC 8
|
||||
#define PCP_UNKNOWN_SEEDER_TYPE 9
|
||||
|
||||
|
||||
/****************
|
||||
* We sometimes get a SEEDER_TOO_SMALL error, in which case we increment
|
||||
* the internal buffer by SEEDER_INC_CHUNK until we reach MAX_SEEDER_SIZE
|
||||
* MAX_SEEDER_SIZE is used as an arbitrary limit to protect against
|
||||
* bugs in Winseed.
|
||||
*/
|
||||
#define MAX_SEEDER_SIZE 500000
|
||||
#define SEEDER_INC_CHUNK 50000
|
||||
|
||||
|
||||
typedef void *WIN32_SEEDER;
|
||||
|
||||
static WIN32_SEEDER (WINAPI *create_instance)( byte type, unsigned int *reason);
|
||||
static void (WINAPI *delete_instance)( WIN32_SEEDER that );
|
||||
static unsigned int (WINAPI *get_internal_seed_size)( WIN32_SEEDER that );
|
||||
static void (WINAPI *set_internal_seed_size)( WIN32_SEEDER that,
|
||||
unsigned int new_size);
|
||||
static unsigned int (WINAPI *get_expected_seed_size)( WIN32_SEEDER that);
|
||||
static unsigned int (WINAPI *get_seed)( WIN32_SEEDER that, byte *buffer,
|
||||
unsigned int *desired_length);
|
||||
|
||||
static WIN32_SEEDER slow_seeder, fast_seeder;
|
||||
static byte *entropy_buffer;
|
||||
static size_t entropy_buffer_size;
|
||||
|
||||
/****************
|
||||
* Load and initialize the winseed DLL
|
||||
* NOTE: winseed is not part of the GnuPG distribution. It should be available
|
||||
* at the GNU crypto FTP server site.
|
||||
* We do not load the DLL on demand to have a better control over the
|
||||
* location of the library.
|
||||
*/
|
||||
static void
|
||||
load_and_init_winseed( void )
|
||||
{
|
||||
HANDLE hInstance;
|
||||
void *addr;
|
||||
unsigned int reason = 0;
|
||||
unsigned int n1, n2;
|
||||
const char *dllname;
|
||||
|
||||
dllname = read_w32_registry_string( "HKEY_LOCAL_MACHINE",
|
||||
"Software\\GNU\\GnuPG",
|
||||
"EntropyDLL" );
|
||||
if( !dllname )
|
||||
dllname = "c:/gnupg/entropy.dll";
|
||||
|
||||
hInstance = LoadLibrary( dllname );
|
||||
if( !hInstance )
|
||||
goto failure;
|
||||
if( !(addr = GetProcAddress( hInstance, "WS_create_instance" )) )
|
||||
goto failure;
|
||||
create_instance = addr;
|
||||
if( !(addr = GetProcAddress( hInstance, "WS_delete_instance" )) )
|
||||
goto failure;
|
||||
delete_instance = addr;
|
||||
if( !(addr = GetProcAddress( hInstance, "WS_get_internal_seed_size" )) )
|
||||
goto failure;
|
||||
get_internal_seed_size = addr;
|
||||
if( !(addr = GetProcAddress( hInstance, "WS_set_internal_seed_size" )) )
|
||||
goto failure;
|
||||
set_internal_seed_size = addr;
|
||||
if( !(addr = GetProcAddress( hInstance, "WS_get_expected_seed_size" )) )
|
||||
goto failure;
|
||||
get_expected_seed_size = addr;
|
||||
if( !(addr = GetProcAddress( hInstance, "WS_get_seed" )) )
|
||||
goto failure;
|
||||
get_seed = addr;
|
||||
|
||||
/* we have all the functions - init the system */
|
||||
slow_seeder = create_instance( WIN32_SLOW_SEEDER, &reason);
|
||||
if( !slow_seeder ) {
|
||||
g10_log_fatal("error creating winseed slow seeder: rc=%u\n", reason );
|
||||
goto failure;
|
||||
}
|
||||
fast_seeder = create_instance( WIN32_FAST_SEEDER, &reason);
|
||||
if( !fast_seeder ) {
|
||||
g10_log_fatal("error creating winseed fast seeder: rc=%u\n", reason );
|
||||
goto failure;
|
||||
}
|
||||
n1 = get_internal_seed_size( slow_seeder );
|
||||
/*g10_log_info("slow buffer size=%u\n", n1);*/
|
||||
n2 = get_internal_seed_size( fast_seeder );
|
||||
/*g10_log_info("fast buffer size=%u\n", n2);*/
|
||||
|
||||
entropy_buffer_size = n1 > n2? n1: n2;
|
||||
entropy_buffer = m_alloc( entropy_buffer_size );
|
||||
/*g10_log_info("using a buffer of size=%u\n", entropy_buffer_size );*/
|
||||
|
||||
return;
|
||||
|
||||
failure:
|
||||
g10_log_fatal("error loading winseed DLL `%s'\n", dllname );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Note: we always use the highest level.
|
||||
* TO boost the performance we may want to add some
|
||||
* additional code for level 1
|
||||
*/
|
||||
static int
|
||||
gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
unsigned int result;
|
||||
unsigned int nbytes;
|
||||
|
||||
if( !level )
|
||||
return 0;
|
||||
|
||||
if( !slow_seeder )
|
||||
load_and_init_winseed();
|
||||
|
||||
/* Our estimation on how much entropy we should use is very vague.
|
||||
* Winseed delivers some amount of entropy on each slow poll and
|
||||
* we add it to our random pool. Depending on the required quality
|
||||
* level we adjust the requested length so that for higher quality
|
||||
* we make sure to add more entropy to our pool. However, as we don't
|
||||
* like to waste any entropy collected by winseed, we always add
|
||||
* at least everything we got from winseed.
|
||||
*/
|
||||
if( level > 1 )
|
||||
length *= 100;
|
||||
else if( level > 0 )
|
||||
length *= 10;
|
||||
|
||||
for(;;) {
|
||||
nbytes = entropy_buffer_size;
|
||||
result = get_seed( slow_seeder, entropy_buffer, &nbytes);
|
||||
if( result == PCP_SEEDER_TOO_SMALL ) {
|
||||
unsigned int n1 = get_internal_seed_size( slow_seeder );
|
||||
|
||||
if( n1 > MAX_SEEDER_SIZE ) {
|
||||
g10_log_fatal("rndw32: internal seeder problem (size=%u)\n",
|
||||
n1);
|
||||
return -1; /* actually never reached */
|
||||
}
|
||||
n1 += SEEDER_INC_CHUNK;
|
||||
set_internal_seed_size( slow_seeder, n1 );
|
||||
if( n1 > entropy_buffer_size ) {
|
||||
entropy_buffer_size = n1;
|
||||
entropy_buffer = m_realloc( entropy_buffer,
|
||||
entropy_buffer_size );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if( result ) {
|
||||
g10_log_fatal("rndw32: get_seed(slow) failed: rc=%u\n", result);
|
||||
return -1; /* actually never reached */
|
||||
}
|
||||
/*g10_log_info("rndw32: slow poll level %d, need %u, got %u\n",
|
||||
level, (unsigned int)length, (unsigned int)nbytes );*/
|
||||
(*add)( entropy_buffer, nbytes, requester );
|
||||
if( length <= nbytes )
|
||||
return 0; /* okay */
|
||||
length -= nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
gather_random_fast( void (*add)(const void*, size_t, int), int requester )
|
||||
{
|
||||
unsigned int result;
|
||||
unsigned int nbytes;
|
||||
|
||||
if( !fast_seeder )
|
||||
load_and_init_winseed();
|
||||
|
||||
/* winseed delivers a constant ammount of entropy for a fast
|
||||
* poll. We can simply use this and add it to the pool; no need
|
||||
* a loop like it is used in the slow poll */
|
||||
nbytes = entropy_buffer_size;
|
||||
result = get_seed( fast_seeder, entropy_buffer, &nbytes);
|
||||
if( result ) {
|
||||
g10_log_fatal("rndw32: get_seed(fast) failed: rc=%u\n", result);
|
||||
return -1; /* actually never reached */
|
||||
}
|
||||
/*g10_log_info("rndw32: fast poll got %u\n", (unsigned int)nbytes );*/
|
||||
(*add)( entropy_buffer, nbytes, requester );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* !USE_ENTROPY_DLL */
|
||||
/* This is the new code which does not require the entropy.dll */
|
||||
|
||||
/*
|
||||
* Definitions which are missing from the current GNU Windows32Api
|
||||
*/
|
||||
|
||||
#ifndef TH32CS_SNAPHEAPLIST
|
||||
#define TH32CS_SNAPHEAPLIST 1
|
||||
#define TH32CS_SNAPPROCESS 2
|
||||
#define TH32CS_SNAPTHREAD 4
|
||||
#define TH32CS_SNAPMODULE 8
|
||||
#define TH32CS_SNAPALL (1|2|4|8)
|
||||
#define TH32CS_INHERIT 0x80000000
|
||||
#endif /*TH32CS_SNAPHEAPLIST*/
|
||||
|
||||
#ifndef IOCTL_DISK_PERFORMANCE
|
||||
#define IOCTL_DISK_PERFORMANCE 0x00070020
|
||||
#endif
|
||||
#ifndef VER_PLATFORM_WIN32_WINDOWS
|
||||
#define VER_PLATFORM_WIN32_WINDOWS 1
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
DWORD dwSize;
|
||||
DWORD th32ProcessID;
|
||||
DWORD th32HeapID;
|
||||
DWORD dwFlags;
|
||||
} HEAPLIST32;
|
||||
|
||||
typedef struct {
|
||||
DWORD dwSize;
|
||||
HANDLE hHandle;
|
||||
DWORD dwAddress;
|
||||
DWORD dwBlockSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwLockCount;
|
||||
DWORD dwResvd;
|
||||
DWORD th32ProcessID;
|
||||
DWORD th32HeapID;
|
||||
} HEAPENTRY32;
|
||||
|
||||
typedef struct {
|
||||
DWORD dwSize;
|
||||
DWORD cntUsage;
|
||||
DWORD th32ProcessID;
|
||||
DWORD th32DefaultHeapID;
|
||||
DWORD th32ModuleID;
|
||||
DWORD cntThreads;
|
||||
DWORD th32ParentProcessID;
|
||||
LONG pcPriClassBase;
|
||||
DWORD dwFlags;
|
||||
char szExeFile[260];
|
||||
} PROCESSENTRY32;
|
||||
|
||||
typedef struct {
|
||||
DWORD dwSize;
|
||||
DWORD cntUsage;
|
||||
DWORD th32ThreadID;
|
||||
DWORD th32OwnerProcessID;
|
||||
LONG tpBasePri;
|
||||
LONG tpDeltaPri;
|
||||
DWORD dwFlags;
|
||||
} THREADENTRY32;
|
||||
|
||||
typedef struct {
|
||||
DWORD dwSize;
|
||||
DWORD th32ModuleID;
|
||||
DWORD th32ProcessID;
|
||||
DWORD GlblcntUsage;
|
||||
DWORD ProccntUsage;
|
||||
BYTE *modBaseAddr;
|
||||
DWORD modBaseSize;
|
||||
HMODULE hModule;
|
||||
char szModule[256];
|
||||
char szExePath[260];
|
||||
} MODULEENTRY32;
|
||||
|
||||
|
||||
|
||||
/* Type definitions for function pointers to call Toolhelp32 functions
|
||||
* used with the windows95 gatherer */
|
||||
typedef BOOL (WINAPI * MODULEWALK) (HANDLE hSnapshot, MODULEENTRY32 *lpme);
|
||||
typedef BOOL (WINAPI * THREADWALK) (HANDLE hSnapshot, THREADENTRY32 *lpte);
|
||||
typedef BOOL (WINAPI * PROCESSWALK) (HANDLE hSnapshot, PROCESSENTRY32 *lppe);
|
||||
typedef BOOL (WINAPI * HEAPLISTWALK) (HANDLE hSnapshot, HEAPLIST32 *lphl);
|
||||
typedef BOOL (WINAPI * HEAPFIRST) (HEAPENTRY32 *lphe, DWORD th32ProcessID,
|
||||
DWORD th32HeapID);
|
||||
typedef BOOL (WINAPI * HEAPNEXT) (HEAPENTRY32 *lphe);
|
||||
typedef HANDLE (WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID);
|
||||
|
||||
/* Type definitions for function pointers to call NetAPI32 functions */
|
||||
typedef DWORD (WINAPI * NETSTATISTICSGET) (LPWSTR szServer, LPWSTR szService,
|
||||
DWORD dwLevel, DWORD dwOptions,
|
||||
LPBYTE * lpBuffer);
|
||||
typedef DWORD (WINAPI * NETAPIBUFFERSIZE) (LPVOID lpBuffer, LPDWORD cbBuffer);
|
||||
typedef DWORD (WINAPI * NETAPIBUFFERFREE) (LPVOID lpBuffer);
|
||||
|
||||
|
||||
/* When we query the performance counters, we allocate an initial buffer and
|
||||
* then reallocate it as required until RegQueryValueEx() stops returning
|
||||
* ERROR_MORE_DATA. The following values define the initial buffer size and
|
||||
* step size by which the buffer is increased
|
||||
*/
|
||||
#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */
|
||||
#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */
|
||||
|
||||
|
||||
static void
|
||||
slow_gatherer_windows95( void (*add)(const void*, size_t, int), int requester )
|
||||
{
|
||||
static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
|
||||
static MODULEWALK pModule32First = NULL;
|
||||
static MODULEWALK pModule32Next = NULL;
|
||||
static PROCESSWALK pProcess32First = NULL;
|
||||
static PROCESSWALK pProcess32Next = NULL;
|
||||
static THREADWALK pThread32First = NULL;
|
||||
static THREADWALK pThread32Next = NULL;
|
||||
static HEAPLISTWALK pHeap32ListFirst = NULL;
|
||||
static HEAPLISTWALK pHeap32ListNext = NULL;
|
||||
static HEAPFIRST pHeap32First = NULL;
|
||||
static HEAPNEXT pHeap32Next = NULL;
|
||||
HANDLE hSnapshot;
|
||||
|
||||
|
||||
/* initialize the Toolhelp32 function pointers */
|
||||
if ( !pCreateToolhelp32Snapshot ) {
|
||||
HANDLE hKernel;
|
||||
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_95: init toolkit\n" );
|
||||
|
||||
/* Obtain the module handle of the kernel to retrieve the addresses
|
||||
* of the Toolhelp32 functions */
|
||||
if ( ( !(hKernel = GetModuleHandle ("KERNEL32.DLL"))) ) {
|
||||
g10_log_fatal ( "rndw32: can't get module handle\n" );
|
||||
}
|
||||
|
||||
/* Now get pointers to the functions */
|
||||
pCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress (hKernel,
|
||||
"CreateToolhelp32Snapshot");
|
||||
pModule32First = (MODULEWALK) GetProcAddress (hKernel, "Module32First");
|
||||
pModule32Next = (MODULEWALK) GetProcAddress (hKernel, "Module32Next");
|
||||
pProcess32First = (PROCESSWALK) GetProcAddress (hKernel,
|
||||
"Process32First");
|
||||
pProcess32Next = (PROCESSWALK) GetProcAddress (hKernel,
|
||||
"Process32Next");
|
||||
pThread32First = (THREADWALK) GetProcAddress (hKernel, "Thread32First");
|
||||
pThread32Next = (THREADWALK) GetProcAddress (hKernel, "Thread32Next");
|
||||
pHeap32ListFirst = (HEAPLISTWALK) GetProcAddress (hKernel,
|
||||
"Heap32ListFirst");
|
||||
pHeap32ListNext = (HEAPLISTWALK) GetProcAddress (hKernel,
|
||||
"Heap32ListNext");
|
||||
pHeap32First = (HEAPFIRST) GetProcAddress (hKernel, "Heap32First");
|
||||
pHeap32Next = (HEAPNEXT) GetProcAddress (hKernel, "Heap32Next");
|
||||
|
||||
if ( !pCreateToolhelp32Snapshot
|
||||
|| !pModule32First || !pModule32Next
|
||||
|| !pProcess32First || !pProcess32Next
|
||||
|| !pThread32First || !pThread32Next
|
||||
|| !pHeap32ListFirst || !pHeap32ListNext
|
||||
|| !pHeap32First || !pHeap32Next ) {
|
||||
g10_log_fatal ( "rndw32: failed to get a toolhep function\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/* Take a snapshot of everything we can get to which is currently
|
||||
* in the system */
|
||||
if ( !(hSnapshot = pCreateToolhelp32Snapshot (TH32CS_SNAPALL, 0)) ) {
|
||||
g10_log_fatal ( "rndw32: failed to take a toolhelp snapshot\n" );
|
||||
}
|
||||
|
||||
/* Walk through the local heap */
|
||||
{ HEAPLIST32 hl32;
|
||||
hl32.dwSize = sizeof (HEAPLIST32);
|
||||
if (pHeap32ListFirst (hSnapshot, &hl32)) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_95: walk heap\n" );
|
||||
do {
|
||||
HEAPENTRY32 he32;
|
||||
|
||||
/* First add the information from the basic Heaplist32 struct */
|
||||
(*add) ( &hl32, sizeof (hl32), requester );
|
||||
|
||||
/* Now walk through the heap blocks getting information
|
||||
* on each of them */
|
||||
he32.dwSize = sizeof (HEAPENTRY32);
|
||||
if (pHeap32First (&he32, hl32.th32ProcessID, hl32.th32HeapID)){
|
||||
do {
|
||||
(*add) ( &he32, sizeof (he32), requester );
|
||||
} while (pHeap32Next (&he32));
|
||||
}
|
||||
} while (pHeap32ListNext (hSnapshot, &hl32));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Walk through all processes */
|
||||
{ PROCESSENTRY32 pe32;
|
||||
pe32.dwSize = sizeof (PROCESSENTRY32);
|
||||
if (pProcess32First (hSnapshot, &pe32)) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_95: walk processes\n" );
|
||||
do {
|
||||
(*add) ( &pe32, sizeof (pe32), requester );
|
||||
} while (pProcess32Next (hSnapshot, &pe32));
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk through all threads */
|
||||
{ THREADENTRY32 te32;
|
||||
te32.dwSize = sizeof (THREADENTRY32);
|
||||
if (pThread32First (hSnapshot, &te32)) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_95: walk threads\n" );
|
||||
do {
|
||||
(*add) ( &te32, sizeof (te32), requester );
|
||||
} while (pThread32Next (hSnapshot, &te32));
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk through all modules associated with the process */
|
||||
{ MODULEENTRY32 me32;
|
||||
me32.dwSize = sizeof (MODULEENTRY32);
|
||||
if (pModule32First (hSnapshot, &me32)) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_95: walk modules\n" );
|
||||
do {
|
||||
(*add) ( &me32, sizeof (me32), requester );
|
||||
} while (pModule32Next (hSnapshot, &me32));
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle (hSnapshot);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester )
|
||||
{
|
||||
static int is_initialized = 0;
|
||||
static NETSTATISTICSGET pNetStatisticsGet = NULL;
|
||||
static NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
|
||||
static NETAPIBUFFERFREE pNetApiBufferFree = NULL;
|
||||
static int is_workstation = 1;
|
||||
|
||||
static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
|
||||
PERF_DATA_BLOCK *pPerfData;
|
||||
HANDLE hDevice, hNetAPI32 = NULL;
|
||||
DWORD dwSize, status;
|
||||
int nDrive;
|
||||
|
||||
if ( !is_initialized ) {
|
||||
HKEY hKey;
|
||||
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" );
|
||||
/* Find out whether this is an NT server or workstation if necessary */
|
||||
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
|
||||
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||
BYTE szValue[32];
|
||||
dwSize = sizeof (szValue);
|
||||
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_nt: check product options\n" );
|
||||
status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
|
||||
szValue, &dwSize);
|
||||
if (status == ERROR_SUCCESS
|
||||
&& ascii_strcasecmp (szValue, "WinNT")) {
|
||||
/* Note: There are (at least) three cases for ProductType:
|
||||
* WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
|
||||
* NT Server acting as a Domain Controller */
|
||||
is_workstation = 0;
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32: this is a NT server\n");
|
||||
}
|
||||
RegCloseKey (hKey);
|
||||
}
|
||||
|
||||
/* Initialize the NetAPI32 function pointers if necessary */
|
||||
if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" );
|
||||
pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32,
|
||||
"NetStatisticsGet");
|
||||
pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32,
|
||||
"NetApiBufferSize");
|
||||
pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32,
|
||||
"NetApiBufferFree");
|
||||
|
||||
if ( !pNetStatisticsGet
|
||||
|| !pNetApiBufferSize || !pNetApiBufferFree ) {
|
||||
FreeLibrary (hNetAPI32);
|
||||
hNetAPI32 = NULL;
|
||||
g10_log_debug ("rndw32: No NETAPI found\n" );
|
||||
}
|
||||
}
|
||||
|
||||
is_initialized = 1;
|
||||
}
|
||||
|
||||
/* Get network statistics. Note: Both NT Workstation and NT Server by
|
||||
* default will be running both the workstation and server services. The
|
||||
* heuristic below is probably useful though on the assumption that the
|
||||
* majority of the network traffic will be via the appropriate service.
|
||||
* In any case the network statistics return almost no randomness */
|
||||
{ LPBYTE lpBuffer;
|
||||
if (hNetAPI32 && !pNetStatisticsGet (NULL,
|
||||
is_workstation ? L"LanmanWorkstation" :
|
||||
L"LanmanServer", 0, 0, &lpBuffer) ) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_nt: get netstats\n" );
|
||||
pNetApiBufferSize (lpBuffer, &dwSize);
|
||||
(*add) ( lpBuffer, dwSize,requester );
|
||||
pNetApiBufferFree (lpBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get disk I/O statistics for all the hard drives */
|
||||
for (nDrive = 0;; nDrive++) {
|
||||
DISK_PERFORMANCE diskPerformance;
|
||||
char szDevice[50];
|
||||
|
||||
/* Check whether we can access this device */
|
||||
sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive);
|
||||
hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
/* Note: This only works if you have turned on the disk performance
|
||||
* counters with 'diskperf -y'. These counters are off by default */
|
||||
if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
|
||||
&diskPerformance, sizeof (DISK_PERFORMANCE),
|
||||
&dwSize, NULL))
|
||||
{
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n",
|
||||
nDrive );
|
||||
(*add) ( &diskPerformance, dwSize, requester );
|
||||
}
|
||||
else {
|
||||
log_info ("NOTE: you should run 'diskperf -y' "
|
||||
"to enable the disk statistics\n");
|
||||
}
|
||||
CloseHandle (hDevice);
|
||||
}
|
||||
|
||||
#if 0 /* we don't need this in GnuPG */
|
||||
/* Wait for any async keyset driver binding to complete. You may be
|
||||
* wondering what this call is doing here... the reason it's necessary is
|
||||
* because RegQueryValueEx() will hang indefinitely if the async driver
|
||||
* bind is in progress. The problem occurs in the dynamic loading and
|
||||
* linking of driver DLL's, which work as follows:
|
||||
*
|
||||
* hDriver = LoadLibrary( DRIVERNAME );
|
||||
* pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 );
|
||||
* pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 );
|
||||
*
|
||||
* If RegQueryValueEx() is called while the GetProcAddress()'s are in
|
||||
* progress, it will hang indefinitely. This is probably due to some
|
||||
* synchronisation problem in the NT kernel where the GetProcAddress()
|
||||
* calls affect something like a module reference count or function
|
||||
* reference count while RegQueryValueEx() is trying to take a snapshot
|
||||
* of the statistics, which include the reference counts. Because of
|
||||
* this, we have to wait until any async driver bind has completed
|
||||
* before we can call RegQueryValueEx() */
|
||||
waitSemaphore (SEMAPHORE_DRIVERBIND);
|
||||
#endif
|
||||
|
||||
/* Get information from the system performance counters. This can take
|
||||
* a few seconds to do. In some environments the call to
|
||||
* RegQueryValueEx() can produce an access violation at some random time
|
||||
* in the future, adding a short delay after the following code block
|
||||
* makes the problem go away. This problem is extremely difficult to
|
||||
* reproduce, I haven't been able to get it to occur despite running it
|
||||
* on a number of machines. The best explanation for the problem is that
|
||||
* on the machine where it did occur, it was caused by an external driver
|
||||
* or other program which adds its own values under the
|
||||
* HKEY_PERFORMANCE_DATA key. The NT kernel calls the required external
|
||||
* modules to map in the data, if there's a synchronisation problem the
|
||||
* external module would write its data at an inappropriate moment,
|
||||
* causing the access violation. A low-level memory checker indicated
|
||||
* that ExpandEnvironmentStrings() in KERNEL32.DLL, called an
|
||||
* interminable number of calls down inside RegQueryValueEx(), was
|
||||
* overwriting memory (it wrote twice the allocated size of a buffer to a
|
||||
* buffer allocated by the NT kernel). This may be what's causing the
|
||||
* problem, but since it's in the kernel there isn't much which can be
|
||||
* done.
|
||||
*
|
||||
* In addition to these problems the code in RegQueryValueEx() which
|
||||
* estimates the amount of memory required to return the performance
|
||||
* counter information isn't very accurate, since it always returns a
|
||||
* worst-case estimate which is usually nowhere near the actual amount
|
||||
* required. For example it may report that 128K of memory is required,
|
||||
* but only return 64K of data */
|
||||
{ pPerfData = m_alloc (cbPerfData);
|
||||
for (;;) {
|
||||
dwSize = cbPerfData;
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
|
||||
status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
|
||||
NULL, (LPBYTE) pPerfData, &dwSize);
|
||||
if (status == ERROR_SUCCESS) {
|
||||
if (!memcmp (pPerfData->Signature, L"PERF", 8)) {
|
||||
(*add) ( pPerfData, dwSize, requester );
|
||||
}
|
||||
else
|
||||
g10_log_debug ( "rndw32: no PERF signature\n");
|
||||
break;
|
||||
}
|
||||
else if (status == ERROR_MORE_DATA) {
|
||||
cbPerfData += PERFORMANCE_BUFFER_STEP;
|
||||
pPerfData = m_realloc (pPerfData, cbPerfData);
|
||||
}
|
||||
else {
|
||||
g10_log_debug ( "rndw32: get performance data problem\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_free (pPerfData);
|
||||
}
|
||||
/* Although this isn't documented in the Win32 API docs, it's necessary
|
||||
to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
|
||||
implicitly opened on the first call to RegQueryValueEx()). If this
|
||||
isn't done then any system components which provide performance data
|
||||
can't be removed or changed while the handle remains active */
|
||||
RegCloseKey (HKEY_PERFORMANCE_DATA);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
gather_random( void (*add)(const void*, size_t, int), int requester,
|
||||
size_t length, int level )
|
||||
{
|
||||
static int is_initialized;
|
||||
static int is_windowsNT, has_toolhelp;
|
||||
|
||||
|
||||
if( !level )
|
||||
return 0;
|
||||
/* We don't differentiate between level 1 and 2 here because
|
||||
* there is no nternal entropy pool as a scary resource. It may
|
||||
* all work slower, but because our entropy source will never
|
||||
* block but deliver some not easy to measure entropy, we assume level 2
|
||||
*/
|
||||
|
||||
|
||||
if ( !is_initialized ) {
|
||||
OSVERSIONINFO osvi = { sizeof( osvi ) };
|
||||
DWORD platform;
|
||||
|
||||
GetVersionEx( &osvi );
|
||||
platform = osvi.dwPlatformId;
|
||||
is_windowsNT = platform == VER_PLATFORM_WIN32_NT;
|
||||
has_toolhelp = (platform == VER_PLATFORM_WIN32_WINDOWS
|
||||
|| (is_windowsNT && osvi.dwMajorVersion >= 5));
|
||||
|
||||
if ( platform == VER_PLATFORM_WIN32s ) {
|
||||
g10_log_fatal("can't run on a W32s platform\n" );
|
||||
}
|
||||
is_initialized = 1;
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#gather_random: platform=%d\n", (int)platform );
|
||||
}
|
||||
|
||||
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#gather_random: req=%d len=%u lvl=%d\n",
|
||||
requester, (unsigned int)length, level );
|
||||
|
||||
if ( has_toolhelp ) {
|
||||
slow_gatherer_windows95 ( add, requester );
|
||||
}
|
||||
if ( is_windowsNT ) {
|
||||
slow_gatherer_windowsNT ( add, requester );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
gather_random_fast( void (*add)(const void*, size_t, int), int requester )
|
||||
{
|
||||
static int addedFixedItems = 0;
|
||||
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#gather_random_fast: req=%d\n", requester );
|
||||
|
||||
/* Get various basic pieces of system information: Handle of active
|
||||
* window, handle of window with mouse capture, handle of clipboard owner
|
||||
* handle of start of clpboard viewer list, pseudohandle of current
|
||||
* process, current process ID, pseudohandle of current thread, current
|
||||
* thread ID, handle of desktop window, handle of window with keyboard
|
||||
* focus, whether system queue has any events, cursor position for last
|
||||
* message, 1 ms time for last message, handle of window with clipboard
|
||||
* open, handle of process heap, handle of procs window station, types of
|
||||
* events in input queue, and milliseconds since Windows was started */
|
||||
{ byte buffer[20*sizeof(ulong)], *bufptr;
|
||||
bufptr = buffer;
|
||||
#define ADD(f) do { ulong along = (ulong)(f); \
|
||||
memcpy (bufptr, &along, sizeof (along) ); \
|
||||
bufptr += sizeof (along); } while (0)
|
||||
ADD ( GetActiveWindow ());
|
||||
ADD ( GetCapture ());
|
||||
ADD ( GetClipboardOwner ());
|
||||
ADD ( GetClipboardViewer ());
|
||||
ADD ( GetCurrentProcess ());
|
||||
ADD ( GetCurrentProcessId ());
|
||||
ADD ( GetCurrentThread ());
|
||||
ADD ( GetCurrentThreadId ());
|
||||
ADD ( GetDesktopWindow ());
|
||||
ADD ( GetFocus ());
|
||||
ADD ( GetInputState ());
|
||||
ADD ( GetMessagePos ());
|
||||
ADD ( GetMessageTime ());
|
||||
ADD ( GetOpenClipboardWindow ());
|
||||
ADD ( GetProcessHeap ());
|
||||
ADD ( GetProcessWindowStation ());
|
||||
ADD ( GetQueueStatus (QS_ALLEVENTS));
|
||||
ADD ( GetTickCount ());
|
||||
|
||||
assert ( bufptr-buffer < sizeof (buffer) );
|
||||
(*add) ( buffer, bufptr-buffer, requester );
|
||||
#undef ADD
|
||||
}
|
||||
|
||||
/* Get multiword system information: Current caret position, current
|
||||
* mouse cursor position */
|
||||
{ POINT point;
|
||||
GetCaretPos (&point);
|
||||
(*add) ( &point, sizeof (point), requester );
|
||||
GetCursorPos (&point);
|
||||
(*add) ( &point, sizeof (point), requester );
|
||||
}
|
||||
|
||||
/* Get percent of memory in use, bytes of physical memory, bytes of free
|
||||
* physical memory, bytes in paging file, free bytes in paging file, user
|
||||
* bytes of address space, and free user bytes */
|
||||
{ MEMORYSTATUS memoryStatus;
|
||||
memoryStatus.dwLength = sizeof (MEMORYSTATUS);
|
||||
GlobalMemoryStatus (&memoryStatus);
|
||||
(*add) ( &memoryStatus, sizeof (memoryStatus), requester );
|
||||
}
|
||||
|
||||
/* Get thread and process creation time, exit time, time in kernel mode,
|
||||
and time in user mode in 100ns intervals */
|
||||
{ HANDLE handle;
|
||||
FILETIME creationTime, exitTime, kernelTime, userTime;
|
||||
DWORD minimumWorkingSetSize, maximumWorkingSetSize;
|
||||
|
||||
handle = GetCurrentThread ();
|
||||
GetThreadTimes (handle, &creationTime, &exitTime,
|
||||
&kernelTime, &userTime);
|
||||
(*add) ( &creationTime, sizeof (creationTime), requester );
|
||||
(*add) ( &exitTime, sizeof (exitTime), requester );
|
||||
(*add) ( &kernelTime, sizeof (kernelTime), requester );
|
||||
(*add) ( &userTime, sizeof (userTime), requester );
|
||||
|
||||
handle = GetCurrentProcess ();
|
||||
GetProcessTimes (handle, &creationTime, &exitTime,
|
||||
&kernelTime, &userTime);
|
||||
(*add) ( &creationTime, sizeof (creationTime), requester );
|
||||
(*add) ( &exitTime, sizeof (exitTime), requester );
|
||||
(*add) ( &kernelTime, sizeof (kernelTime), requester );
|
||||
(*add) ( &userTime, sizeof (userTime), requester );
|
||||
|
||||
/* Get the minimum and maximum working set size for the current process */
|
||||
GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
|
||||
&maximumWorkingSetSize);
|
||||
(*add) ( &minimumWorkingSetSize,
|
||||
sizeof (&minimumWorkingSetSize), requester );
|
||||
(*add) ( &maximumWorkingSetSize,
|
||||
sizeof (&maximumWorkingSetSize), requester );
|
||||
}
|
||||
|
||||
|
||||
/* The following are fixed for the lifetime of the process so we only
|
||||
* add them once */
|
||||
if (!addedFixedItems) {
|
||||
STARTUPINFO startupInfo;
|
||||
|
||||
/* Get name of desktop, console window title, new window position and
|
||||
* size, window flags, and handles for stdin, stdout, and stderr */
|
||||
startupInfo.cb = sizeof (STARTUPINFO);
|
||||
GetStartupInfo (&startupInfo);
|
||||
(*add) ( &startupInfo, sizeof (STARTUPINFO), requester );
|
||||
addedFixedItems = 1;
|
||||
}
|
||||
|
||||
/* The performance of QPC varies depending on the architecture it's
|
||||
* running on and on the OS. Under NT it reads the CPU's 64-bit timestamp
|
||||
* counter (at least on a Pentium and newer '486's, it hasn't been tested
|
||||
* on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC
|
||||
* timer. There are vague mumblings in the docs that it may fail if the
|
||||
* appropriate hardware isn't available (possibly '386's or MIPS machines
|
||||
* running NT), but who's going to run NT on a '386? */
|
||||
{ LARGE_INTEGER performanceCount;
|
||||
if (QueryPerformanceCounter (&performanceCount)) {
|
||||
if ( debug_me )
|
||||
log_debug ("rndw32#gather_random_fast: perf data\n");
|
||||
(*add) (&performanceCount, sizeof (&performanceCount), requester);
|
||||
}
|
||||
else { /* Millisecond accuracy at best... */
|
||||
DWORD aword = GetTickCount ();
|
||||
(*add) (&aword, sizeof (aword), requester );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* !USE_ENTROPY_DLL */
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "RNDW32 ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
void *func;
|
||||
} func_table[] = {
|
||||
{ 40, 1, gather_random },
|
||||
{ 41, 1, gather_random_fast },
|
||||
};
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
debug_me = !!getenv("DEBUG_RNDW32");
|
||||
|
||||
do {
|
||||
if ( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
ret = func_table[i].func;
|
||||
i++;
|
||||
} while ( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
rndw32_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version,
|
||||
gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,494 @@
|
|||
/* rsa.c - RSA function
|
||||
* Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn)
|
||||
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* This code uses an algorithm protected by U.S. Patent #4,405,829
|
||||
which expires on September 20, 2000. The patent holder placed that
|
||||
patent into the public domain on Sep 6th, 2000.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "rsa.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
MPI n; /* modulus */
|
||||
MPI e; /* exponent */
|
||||
} RSA_public_key;
|
||||
|
||||
|
||||
typedef struct {
|
||||
MPI n; /* public modulus */
|
||||
MPI e; /* public exponent */
|
||||
MPI d; /* exponent */
|
||||
MPI p; /* prime p. */
|
||||
MPI q; /* prime q. */
|
||||
MPI u; /* inverse of p mod q. */
|
||||
} RSA_secret_key;
|
||||
|
||||
|
||||
static void test_keys( RSA_secret_key *sk, unsigned nbits );
|
||||
static void generate( RSA_secret_key *sk, unsigned nbits );
|
||||
static int check_secret_key( RSA_secret_key *sk );
|
||||
static void public(MPI output, MPI input, RSA_public_key *skey );
|
||||
static void secret(MPI output, MPI input, RSA_secret_key *skey );
|
||||
|
||||
|
||||
static void
|
||||
test_keys( RSA_secret_key *sk, unsigned nbits )
|
||||
{
|
||||
RSA_public_key pk;
|
||||
MPI test = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
MPI out1 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
MPI out2 = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
|
||||
pk.n = sk->n;
|
||||
pk.e = sk->e;
|
||||
{ char *p = get_random_bits( nbits, 0, 0 );
|
||||
mpi_set_buffer( test, p, (nbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
public( out1, test, &pk );
|
||||
secret( out2, out1, sk );
|
||||
if( mpi_cmp( test, out2 ) )
|
||||
log_fatal("RSA operation: public, secret failed\n");
|
||||
secret( out1, test, sk );
|
||||
public( out2, out1, &pk );
|
||||
if( mpi_cmp( test, out2 ) )
|
||||
log_fatal("RSA operation: secret, public failed\n");
|
||||
mpi_free( test );
|
||||
mpi_free( out1 );
|
||||
mpi_free( out2 );
|
||||
}
|
||||
|
||||
/****************
|
||||
* Generate a key pair with a key of size NBITS
|
||||
* Returns: 2 structures filled with all needed values
|
||||
*/
|
||||
static void
|
||||
generate( RSA_secret_key *sk, unsigned nbits )
|
||||
{
|
||||
MPI p, q; /* the two primes */
|
||||
MPI d; /* the private key */
|
||||
MPI u;
|
||||
MPI t1, t2;
|
||||
MPI n; /* the public key */
|
||||
MPI e; /* the exponent */
|
||||
MPI phi; /* helper: (p-1)(q-1) */
|
||||
MPI g;
|
||||
MPI f;
|
||||
|
||||
/* make sure that nbits is even so that we generate p, q of equal size */
|
||||
if ( (nbits&1) )
|
||||
nbits++;
|
||||
|
||||
n = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
|
||||
p = q = NULL;
|
||||
do {
|
||||
/* select two (very secret) primes */
|
||||
if (p)
|
||||
mpi_free (p);
|
||||
if (q)
|
||||
mpi_free (q);
|
||||
p = generate_secret_prime( nbits / 2 );
|
||||
q = generate_secret_prime( nbits / 2 );
|
||||
if( mpi_cmp( p, q ) > 0 ) /* p shall be smaller than q (for calc of u)*/
|
||||
mpi_swap(p,q);
|
||||
/* calculate the modulus */
|
||||
mpi_mul( n, p, q );
|
||||
} while ( mpi_get_nbits(n) != nbits );
|
||||
|
||||
/* calculate Euler totient: phi = (p-1)(q-1) */
|
||||
t1 = mpi_alloc_secure( mpi_get_nlimbs(p) );
|
||||
t2 = mpi_alloc_secure( mpi_get_nlimbs(p) );
|
||||
phi = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
g = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
f = mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
mpi_sub_ui( t1, p, 1 );
|
||||
mpi_sub_ui( t2, q, 1 );
|
||||
mpi_mul( phi, t1, t2 );
|
||||
mpi_gcd(g, t1, t2);
|
||||
mpi_fdiv_q(f, phi, g);
|
||||
|
||||
/* find an public exponent.
|
||||
We use 41 as this is quite fast and more secure than the
|
||||
commonly used 17. Benchmarking the RSA verify function
|
||||
with a 1024 bit key yields (2001-11-08):
|
||||
e=17 0.54 ms
|
||||
e=41 0.75 ms
|
||||
e=257 0.95 ms
|
||||
e=65537 1.80 ms
|
||||
*/
|
||||
e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
mpi_set_ui( e, 41);
|
||||
if( !mpi_gcd(t1, e, phi) ) {
|
||||
mpi_set_ui( e, 257);
|
||||
if( !mpi_gcd(t1, e, phi) ) {
|
||||
mpi_set_ui( e, 65537);
|
||||
while( !mpi_gcd(t1, e, phi) ) /* (while gcd is not 1) */
|
||||
mpi_add_ui( e, e, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate the secret key d = e^1 mod phi */
|
||||
d = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
mpi_invm(d, e, f );
|
||||
/* calculate the inverse of p and q (used for chinese remainder theorem)*/
|
||||
u = mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
|
||||
mpi_invm(u, p, q );
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
log_mpidump(" p= ", p );
|
||||
log_mpidump(" q= ", q );
|
||||
log_mpidump("phi= ", phi );
|
||||
log_mpidump(" g= ", g );
|
||||
log_mpidump(" f= ", f );
|
||||
log_mpidump(" n= ", n );
|
||||
log_mpidump(" e= ", e );
|
||||
log_mpidump(" d= ", d );
|
||||
log_mpidump(" u= ", u );
|
||||
}
|
||||
|
||||
mpi_free(t1);
|
||||
mpi_free(t2);
|
||||
mpi_free(phi);
|
||||
mpi_free(f);
|
||||
mpi_free(g);
|
||||
|
||||
sk->n = n;
|
||||
sk->e = e;
|
||||
sk->p = p;
|
||||
sk->q = q;
|
||||
sk->d = d;
|
||||
sk->u = u;
|
||||
|
||||
/* now we can test our keys (this should never fail!) */
|
||||
test_keys( sk, nbits - 64 );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Test wether the secret key is valid.
|
||||
* Returns: true if this is a valid key.
|
||||
*/
|
||||
static int
|
||||
check_secret_key( RSA_secret_key *sk )
|
||||
{
|
||||
int rc;
|
||||
MPI temp = mpi_alloc( mpi_get_nlimbs(sk->p)*2 );
|
||||
|
||||
mpi_mul(temp, sk->p, sk->q );
|
||||
rc = mpi_cmp( temp, sk->n );
|
||||
mpi_free(temp);
|
||||
return !rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Public key operation. Encrypt INPUT with PKEY and put result into OUTPUT.
|
||||
*
|
||||
* c = m^e mod n
|
||||
*
|
||||
* Where c is OUTPUT, m is INPUT and e,n are elements of PKEY.
|
||||
*/
|
||||
static void
|
||||
public(MPI output, MPI input, RSA_public_key *pkey )
|
||||
{
|
||||
if( output == input ) { /* powm doesn't like output and input the same */
|
||||
MPI x = mpi_alloc( mpi_get_nlimbs(input)*2 );
|
||||
mpi_powm( x, input, pkey->e, pkey->n );
|
||||
mpi_set(output, x);
|
||||
mpi_free(x);
|
||||
}
|
||||
else
|
||||
mpi_powm( output, input, pkey->e, pkey->n );
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
stronger_key_check ( RSA_secret_key *skey )
|
||||
{
|
||||
MPI t = mpi_alloc_secure ( 0 );
|
||||
MPI t1 = mpi_alloc_secure ( 0 );
|
||||
MPI t2 = mpi_alloc_secure ( 0 );
|
||||
MPI phi = mpi_alloc_secure ( 0 );
|
||||
|
||||
/* check that n == p * q */
|
||||
mpi_mul( t, skey->p, skey->q);
|
||||
if (mpi_cmp( t, skey->n) )
|
||||
log_info ( "RSA Oops: n != p * q\n" );
|
||||
|
||||
/* check that p is less than q */
|
||||
if( mpi_cmp( skey->p, skey->q ) > 0 )
|
||||
log_info ("RSA Oops: p >= q\n");
|
||||
|
||||
|
||||
/* check that e divides neither p-1 nor q-1 */
|
||||
mpi_sub_ui(t, skey->p, 1 );
|
||||
mpi_fdiv_r(t, t, skey->e );
|
||||
if ( !mpi_cmp_ui( t, 0) )
|
||||
log_info ( "RSA Oops: e divides p-1\n" );
|
||||
mpi_sub_ui(t, skey->q, 1 );
|
||||
mpi_fdiv_r(t, t, skey->e );
|
||||
if ( !mpi_cmp_ui( t, 0) )
|
||||
log_info ( "RSA Oops: e divides q-1\n" );
|
||||
|
||||
/* check that d is correct */
|
||||
mpi_sub_ui( t1, skey->p, 1 );
|
||||
mpi_sub_ui( t2, skey->q, 1 );
|
||||
mpi_mul( phi, t1, t2 );
|
||||
mpi_gcd(t, t1, t2);
|
||||
mpi_fdiv_q(t, phi, t);
|
||||
mpi_invm(t, skey->e, t );
|
||||
if ( mpi_cmp(t, skey->d ) )
|
||||
log_info ( "RSA Oops: d is wrong\n");
|
||||
|
||||
/* check for crrectness of u */
|
||||
mpi_invm(t, skey->p, skey->q );
|
||||
if ( mpi_cmp(t, skey->u ) )
|
||||
log_info ( "RSA Oops: u is wrong\n");
|
||||
|
||||
log_info ( "RSA secret key check finished\n");
|
||||
|
||||
mpi_free (t);
|
||||
mpi_free (t1);
|
||||
mpi_free (t2);
|
||||
mpi_free (phi);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****************
|
||||
* Secret key operation. Encrypt INPUT with SKEY and put result into OUTPUT.
|
||||
*
|
||||
* m = c^d mod n
|
||||
*
|
||||
* Or faster:
|
||||
*
|
||||
* m1 = c ^ (d mod (p-1)) mod p
|
||||
* m2 = c ^ (d mod (q-1)) mod q
|
||||
* h = u * (m2 - m1) mod q
|
||||
* m = m1 + h * p
|
||||
*
|
||||
* Where m is OUTPUT, c is INPUT and d,n,p,q,u are elements of SKEY.
|
||||
*/
|
||||
static void
|
||||
secret(MPI output, MPI input, RSA_secret_key *skey )
|
||||
{
|
||||
#if 0
|
||||
mpi_powm( output, input, skey->d, skey->n );
|
||||
#else
|
||||
MPI m1 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
|
||||
MPI m2 = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
|
||||
MPI h = mpi_alloc_secure( mpi_get_nlimbs(skey->n)+1 );
|
||||
|
||||
/* m1 = c ^ (d mod (p-1)) mod p */
|
||||
mpi_sub_ui( h, skey->p, 1 );
|
||||
mpi_fdiv_r( h, skey->d, h );
|
||||
mpi_powm( m1, input, h, skey->p );
|
||||
/* m2 = c ^ (d mod (q-1)) mod q */
|
||||
mpi_sub_ui( h, skey->q, 1 );
|
||||
mpi_fdiv_r( h, skey->d, h );
|
||||
mpi_powm( m2, input, h, skey->q );
|
||||
/* h = u * ( m2 - m1 ) mod q */
|
||||
mpi_sub( h, m2, m1 );
|
||||
if ( mpi_is_neg( h ) )
|
||||
mpi_add ( h, h, skey->q );
|
||||
mpi_mulm( h, skey->u, h, skey->q );
|
||||
/* m = m2 + h * p */
|
||||
mpi_mul ( h, h, skey->p );
|
||||
mpi_add ( output, m1, h );
|
||||
/* ready */
|
||||
|
||||
mpi_free ( h );
|
||||
mpi_free ( m1 );
|
||||
mpi_free ( m2 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
************** interface ******************
|
||||
*********************************************/
|
||||
|
||||
int
|
||||
rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
{
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( !is_RSA(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
generate( &sk, nbits );
|
||||
skey[0] = sk.n;
|
||||
skey[1] = sk.e;
|
||||
skey[2] = sk.d;
|
||||
skey[3] = sk.p;
|
||||
skey[4] = sk.q;
|
||||
skey[5] = sk.u;
|
||||
/* make an empty list of factors */
|
||||
*retfactors = m_alloc_clear( 1 * sizeof **retfactors );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rsa_check_secret_key( int algo, MPI *skey )
|
||||
{
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( !is_RSA(algo) )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
sk.n = skey[0];
|
||||
sk.e = skey[1];
|
||||
sk.d = skey[2];
|
||||
sk.p = skey[3];
|
||||
sk.q = skey[4];
|
||||
sk.u = skey[5];
|
||||
if( !check_secret_key( &sk ) )
|
||||
return G10ERR_BAD_SECKEY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
|
||||
{
|
||||
RSA_public_key pk;
|
||||
|
||||
if( algo != 1 && algo != 2 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
pk.n = pkey[0];
|
||||
pk.e = pkey[1];
|
||||
resarr[0] = mpi_alloc( mpi_get_nlimbs( pk.n ) );
|
||||
public( resarr[0], data, &pk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
|
||||
{
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( algo != 1 && algo != 2 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
sk.n = skey[0];
|
||||
sk.e = skey[1];
|
||||
sk.d = skey[2];
|
||||
sk.p = skey[3];
|
||||
sk.q = skey[4];
|
||||
sk.u = skey[5];
|
||||
*result = mpi_alloc_secure( mpi_get_nlimbs( sk.n ) );
|
||||
secret( *result, data[0], &sk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
{
|
||||
RSA_secret_key sk;
|
||||
|
||||
if( algo != 1 && algo != 3 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
sk.n = skey[0];
|
||||
sk.e = skey[1];
|
||||
sk.d = skey[2];
|
||||
sk.p = skey[3];
|
||||
sk.q = skey[4];
|
||||
sk.u = skey[5];
|
||||
resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.n ) );
|
||||
secret( resarr[0], data, &sk );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *opaque, MPI tmp), void *opaquev )
|
||||
{
|
||||
RSA_public_key pk;
|
||||
MPI result;
|
||||
int rc;
|
||||
|
||||
if( algo != 1 && algo != 3 )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
pk.n = pkey[0];
|
||||
pk.e = pkey[1];
|
||||
result = mpi_alloc( (160+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB);
|
||||
public( result, data[0], &pk );
|
||||
/*rc = (*cmp)( opaquev, result );*/
|
||||
rc = mpi_cmp( result, hash )? G10ERR_BAD_SIGN:0;
|
||||
mpi_free(result);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
rsa_get_nbits( int algo, MPI *pkey )
|
||||
{
|
||||
if( !is_RSA(algo) )
|
||||
return 0;
|
||||
return mpi_get_nbits( pkey[0] );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
* Usage: Bit 0 set : allows signing
|
||||
* 1 set : allows encryption
|
||||
*/
|
||||
const char *
|
||||
rsa_get_info( int algo,
|
||||
int *npkey, int *nskey, int *nenc, int *nsig, int *r_usage )
|
||||
{
|
||||
*npkey = 2;
|
||||
*nskey = 6;
|
||||
*nenc = 1;
|
||||
*nsig = 1;
|
||||
|
||||
switch( algo ) {
|
||||
case 1: *r_usage = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC; return "RSA";
|
||||
case 2: *r_usage = PUBKEY_USAGE_ENC; return "RSA-E";
|
||||
case 3: *r_usage = PUBKEY_USAGE_SIG; return "RSA-S";
|
||||
default:*r_usage = 0; return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/* rsa.h
|
||||
* Copyright (C) 1997,1998 by Werner Koch (dd9jn)
|
||||
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_RSA_H
|
||||
#define G10_RSA_H
|
||||
|
||||
int rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
|
||||
int rsa_check_secret_key( int algo, MPI *skey );
|
||||
int rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey );
|
||||
int rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
|
||||
int rsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
|
||||
int rsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev );
|
||||
unsigned rsa_get_nbits( int algo, MPI *pkey );
|
||||
const char *rsa_get_info( int algo, int *npkey, int *nskey,
|
||||
int *nenc, int *nsig, int *use );
|
||||
|
||||
|
||||
#endif /*G10_RSA_H*/
|
|
@ -0,0 +1,425 @@
|
|||
/* sha1.c - SHA1 hash function
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* Please see below for more legal information!
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
|
||||
/* Test vectors:
|
||||
*
|
||||
* "abc"
|
||||
* A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D
|
||||
*
|
||||
* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
* 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "memory.h"
|
||||
#include "dynload.h"
|
||||
#include "bithelp.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
u32 h0,h1,h2,h3,h4;
|
||||
u32 nblocks;
|
||||
byte buf[64];
|
||||
int count;
|
||||
} SHA1_CONTEXT;
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[128];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sha1_init( SHA1_CONTEXT *hd )
|
||||
{
|
||||
hd->h0 = 0x67452301;
|
||||
hd->h1 = 0xefcdab89;
|
||||
hd->h2 = 0x98badcfe;
|
||||
hd->h3 = 0x10325476;
|
||||
hd->h4 = 0xc3d2e1f0;
|
||||
hd->nblocks = 0;
|
||||
hd->count = 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Transform the message X which consists of 16 32-bit-words
|
||||
*/
|
||||
static void
|
||||
transform( SHA1_CONTEXT *hd, byte *data )
|
||||
{
|
||||
u32 a,b,c,d,e,tm;
|
||||
u32 x[16];
|
||||
|
||||
/* get values from the chaining vars */
|
||||
a = hd->h0;
|
||||
b = hd->h1;
|
||||
c = hd->h2;
|
||||
d = hd->h3;
|
||||
e = hd->h4;
|
||||
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
memcpy( x, data, 64 );
|
||||
#else
|
||||
{ int i;
|
||||
byte *p2;
|
||||
for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) {
|
||||
p2[3] = *data++;
|
||||
p2[2] = *data++;
|
||||
p2[1] = *data++;
|
||||
p2[0] = *data++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define K1 0x5A827999L
|
||||
#define K2 0x6ED9EBA1L
|
||||
#define K3 0x8F1BBCDCL
|
||||
#define K4 0xCA62C1D6L
|
||||
#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) )
|
||||
#define F2(x,y,z) ( x ^ y ^ z )
|
||||
#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) )
|
||||
#define F4(x,y,z) ( x ^ y ^ z )
|
||||
|
||||
|
||||
#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \
|
||||
^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \
|
||||
, (x[i&0x0f] = rol(tm,1)) )
|
||||
|
||||
#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \
|
||||
+ f( b, c, d ) \
|
||||
+ k \
|
||||
+ m; \
|
||||
b = rol( b, 30 ); \
|
||||
} while(0)
|
||||
R( a, b, c, d, e, F1, K1, x[ 0] );
|
||||
R( e, a, b, c, d, F1, K1, x[ 1] );
|
||||
R( d, e, a, b, c, F1, K1, x[ 2] );
|
||||
R( c, d, e, a, b, F1, K1, x[ 3] );
|
||||
R( b, c, d, e, a, F1, K1, x[ 4] );
|
||||
R( a, b, c, d, e, F1, K1, x[ 5] );
|
||||
R( e, a, b, c, d, F1, K1, x[ 6] );
|
||||
R( d, e, a, b, c, F1, K1, x[ 7] );
|
||||
R( c, d, e, a, b, F1, K1, x[ 8] );
|
||||
R( b, c, d, e, a, F1, K1, x[ 9] );
|
||||
R( a, b, c, d, e, F1, K1, x[10] );
|
||||
R( e, a, b, c, d, F1, K1, x[11] );
|
||||
R( d, e, a, b, c, F1, K1, x[12] );
|
||||
R( c, d, e, a, b, F1, K1, x[13] );
|
||||
R( b, c, d, e, a, F1, K1, x[14] );
|
||||
R( a, b, c, d, e, F1, K1, x[15] );
|
||||
R( e, a, b, c, d, F1, K1, M(16) );
|
||||
R( d, e, a, b, c, F1, K1, M(17) );
|
||||
R( c, d, e, a, b, F1, K1, M(18) );
|
||||
R( b, c, d, e, a, F1, K1, M(19) );
|
||||
R( a, b, c, d, e, F2, K2, M(20) );
|
||||
R( e, a, b, c, d, F2, K2, M(21) );
|
||||
R( d, e, a, b, c, F2, K2, M(22) );
|
||||
R( c, d, e, a, b, F2, K2, M(23) );
|
||||
R( b, c, d, e, a, F2, K2, M(24) );
|
||||
R( a, b, c, d, e, F2, K2, M(25) );
|
||||
R( e, a, b, c, d, F2, K2, M(26) );
|
||||
R( d, e, a, b, c, F2, K2, M(27) );
|
||||
R( c, d, e, a, b, F2, K2, M(28) );
|
||||
R( b, c, d, e, a, F2, K2, M(29) );
|
||||
R( a, b, c, d, e, F2, K2, M(30) );
|
||||
R( e, a, b, c, d, F2, K2, M(31) );
|
||||
R( d, e, a, b, c, F2, K2, M(32) );
|
||||
R( c, d, e, a, b, F2, K2, M(33) );
|
||||
R( b, c, d, e, a, F2, K2, M(34) );
|
||||
R( a, b, c, d, e, F2, K2, M(35) );
|
||||
R( e, a, b, c, d, F2, K2, M(36) );
|
||||
R( d, e, a, b, c, F2, K2, M(37) );
|
||||
R( c, d, e, a, b, F2, K2, M(38) );
|
||||
R( b, c, d, e, a, F2, K2, M(39) );
|
||||
R( a, b, c, d, e, F3, K3, M(40) );
|
||||
R( e, a, b, c, d, F3, K3, M(41) );
|
||||
R( d, e, a, b, c, F3, K3, M(42) );
|
||||
R( c, d, e, a, b, F3, K3, M(43) );
|
||||
R( b, c, d, e, a, F3, K3, M(44) );
|
||||
R( a, b, c, d, e, F3, K3, M(45) );
|
||||
R( e, a, b, c, d, F3, K3, M(46) );
|
||||
R( d, e, a, b, c, F3, K3, M(47) );
|
||||
R( c, d, e, a, b, F3, K3, M(48) );
|
||||
R( b, c, d, e, a, F3, K3, M(49) );
|
||||
R( a, b, c, d, e, F3, K3, M(50) );
|
||||
R( e, a, b, c, d, F3, K3, M(51) );
|
||||
R( d, e, a, b, c, F3, K3, M(52) );
|
||||
R( c, d, e, a, b, F3, K3, M(53) );
|
||||
R( b, c, d, e, a, F3, K3, M(54) );
|
||||
R( a, b, c, d, e, F3, K3, M(55) );
|
||||
R( e, a, b, c, d, F3, K3, M(56) );
|
||||
R( d, e, a, b, c, F3, K3, M(57) );
|
||||
R( c, d, e, a, b, F3, K3, M(58) );
|
||||
R( b, c, d, e, a, F3, K3, M(59) );
|
||||
R( a, b, c, d, e, F4, K4, M(60) );
|
||||
R( e, a, b, c, d, F4, K4, M(61) );
|
||||
R( d, e, a, b, c, F4, K4, M(62) );
|
||||
R( c, d, e, a, b, F4, K4, M(63) );
|
||||
R( b, c, d, e, a, F4, K4, M(64) );
|
||||
R( a, b, c, d, e, F4, K4, M(65) );
|
||||
R( e, a, b, c, d, F4, K4, M(66) );
|
||||
R( d, e, a, b, c, F4, K4, M(67) );
|
||||
R( c, d, e, a, b, F4, K4, M(68) );
|
||||
R( b, c, d, e, a, F4, K4, M(69) );
|
||||
R( a, b, c, d, e, F4, K4, M(70) );
|
||||
R( e, a, b, c, d, F4, K4, M(71) );
|
||||
R( d, e, a, b, c, F4, K4, M(72) );
|
||||
R( c, d, e, a, b, F4, K4, M(73) );
|
||||
R( b, c, d, e, a, F4, K4, M(74) );
|
||||
R( a, b, c, d, e, F4, K4, M(75) );
|
||||
R( e, a, b, c, d, F4, K4, M(76) );
|
||||
R( d, e, a, b, c, F4, K4, M(77) );
|
||||
R( c, d, e, a, b, F4, K4, M(78) );
|
||||
R( b, c, d, e, a, F4, K4, M(79) );
|
||||
|
||||
/* update chainig vars */
|
||||
hd->h0 += a;
|
||||
hd->h1 += b;
|
||||
hd->h2 += c;
|
||||
hd->h3 += d;
|
||||
hd->h4 += e;
|
||||
}
|
||||
|
||||
|
||||
/* Update the message digest with the contents
|
||||
* of INBUF with length INLEN.
|
||||
*/
|
||||
static void
|
||||
sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
|
||||
{
|
||||
if( hd->count == 64 ) { /* flush the buffer */
|
||||
transform( hd, hd->buf );
|
||||
burn_stack (88+4*sizeof(void*));
|
||||
hd->count = 0;
|
||||
hd->nblocks++;
|
||||
}
|
||||
if( !inbuf )
|
||||
return;
|
||||
if( hd->count ) {
|
||||
for( ; inlen && hd->count < 64; inlen-- )
|
||||
hd->buf[hd->count++] = *inbuf++;
|
||||
sha1_write( hd, NULL, 0 );
|
||||
if( !inlen )
|
||||
return;
|
||||
}
|
||||
|
||||
while( inlen >= 64 ) {
|
||||
transform( hd, inbuf );
|
||||
hd->count = 0;
|
||||
hd->nblocks++;
|
||||
inlen -= 64;
|
||||
inbuf += 64;
|
||||
}
|
||||
burn_stack (88+4*sizeof(void*));
|
||||
for( ; inlen && hd->count < 64; inlen-- )
|
||||
hd->buf[hd->count++] = *inbuf++;
|
||||
}
|
||||
|
||||
|
||||
/* The routine final terminates the computation and
|
||||
* returns the digest.
|
||||
* The handle is prepared for a new cycle, but adding bytes to the
|
||||
* handle will the destroy the returned buffer.
|
||||
* Returns: 20 bytes representing the digest.
|
||||
*/
|
||||
|
||||
static void
|
||||
sha1_final(SHA1_CONTEXT *hd)
|
||||
{
|
||||
u32 t, msb, lsb;
|
||||
byte *p;
|
||||
|
||||
sha1_write(hd, NULL, 0); /* flush */;
|
||||
|
||||
t = hd->nblocks;
|
||||
/* multiply by 64 to make a byte count */
|
||||
lsb = t << 6;
|
||||
msb = t >> 26;
|
||||
/* add the count */
|
||||
t = lsb;
|
||||
if( (lsb += hd->count) < t )
|
||||
msb++;
|
||||
/* multiply by 8 to make a bit count */
|
||||
t = lsb;
|
||||
lsb <<= 3;
|
||||
msb <<= 3;
|
||||
msb |= t >> 29;
|
||||
|
||||
if( hd->count < 56 ) { /* enough room */
|
||||
hd->buf[hd->count++] = 0x80; /* pad */
|
||||
while( hd->count < 56 )
|
||||
hd->buf[hd->count++] = 0; /* pad */
|
||||
}
|
||||
else { /* need one extra block */
|
||||
hd->buf[hd->count++] = 0x80; /* pad character */
|
||||
while( hd->count < 64 )
|
||||
hd->buf[hd->count++] = 0;
|
||||
sha1_write(hd, NULL, 0); /* flush */;
|
||||
memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
|
||||
}
|
||||
/* append the 64 bit count */
|
||||
hd->buf[56] = msb >> 24;
|
||||
hd->buf[57] = msb >> 16;
|
||||
hd->buf[58] = msb >> 8;
|
||||
hd->buf[59] = msb ;
|
||||
hd->buf[60] = lsb >> 24;
|
||||
hd->buf[61] = lsb >> 16;
|
||||
hd->buf[62] = lsb >> 8;
|
||||
hd->buf[63] = lsb ;
|
||||
transform( hd, hd->buf );
|
||||
burn_stack (88+4*sizeof(void*));
|
||||
|
||||
p = hd->buf;
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
|
||||
#else /* little endian */
|
||||
#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
|
||||
*p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
|
||||
#endif
|
||||
X(0);
|
||||
X(1);
|
||||
X(2);
|
||||
X(3);
|
||||
X(4);
|
||||
#undef X
|
||||
|
||||
}
|
||||
|
||||
static byte *
|
||||
sha1_read( SHA1_CONTEXT *hd )
|
||||
{
|
||||
return hd->buf;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
static const char *
|
||||
sha1_get_info( int algo, size_t *contextsize,
|
||||
byte **r_asnoid, int *r_asnlen, int *r_mdlen,
|
||||
void (**r_init)( void *c ),
|
||||
void (**r_write)( void *c, byte *buf, size_t nbytes ),
|
||||
void (**r_final)( void *c ),
|
||||
byte *(**r_read)( void *c )
|
||||
)
|
||||
{
|
||||
static byte asn[15] = /* Object ID is 1.3.14.3.2.26 */
|
||||
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
|
||||
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
|
||||
if( algo != 2 )
|
||||
return NULL;
|
||||
|
||||
*contextsize = sizeof(SHA1_CONTEXT);
|
||||
*r_asnoid = asn;
|
||||
*r_asnlen = DIM(asn);
|
||||
*r_mdlen = 20;
|
||||
*(void (**)(SHA1_CONTEXT *))r_init = sha1_init;
|
||||
*(void (**)(SHA1_CONTEXT *, byte*, size_t))r_write = sha1_write;
|
||||
*(void (**)(SHA1_CONTEXT *))r_final = sha1_final;
|
||||
*(byte *(**)(SHA1_CONTEXT *))r_read = sha1_read;
|
||||
|
||||
return "SHA1";
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
const char * const gnupgext_version = "SHA1 ($Revision$)";
|
||||
|
||||
static struct {
|
||||
int class;
|
||||
int version;
|
||||
int value;
|
||||
void (*func)(void);
|
||||
} func_table[] = {
|
||||
{ 10, 1, 0, (void(*)(void))sha1_get_info },
|
||||
{ 11, 1, 2 },
|
||||
};
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
static
|
||||
#endif
|
||||
void *
|
||||
gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
{
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
do {
|
||||
if( i >= DIM(func_table) || i < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
*class = func_table[i].class;
|
||||
*vers = func_table[i].version;
|
||||
switch( *class ) {
|
||||
case 11:
|
||||
case 21:
|
||||
case 31:
|
||||
ret = &func_table[i].value;
|
||||
break;
|
||||
default:
|
||||
#ifndef __riscos__
|
||||
ret = func_table[i].func;
|
||||
#else /* __riscos__ */
|
||||
ret = (void *) func_table[i].func;
|
||||
#endif /* __riscos__ */
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
} while( what && what != *class );
|
||||
|
||||
*sequence = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef IS_MODULE
|
||||
void
|
||||
sha1_constructor(void)
|
||||
{
|
||||
register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/* smallprime.c - List of small primes
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG 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.
|
||||
*
|
||||
* GnuPG 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; 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 <stdlib.h>
|
||||
#include "util.h"
|
||||
#include "types.h"
|
||||
|
||||
/* Note: 2 is not included because it can be tested more easily
|
||||
* by looking at bit 0. The last entry in this list is marked by a zero
|
||||
*/
|
||||
ushort
|
||||
small_prime_numbers[] = {
|
||||
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
|
||||
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
|
||||
103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
|
||||
157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
|
||||
211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
|
||||
269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
|
||||
331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
|
||||
389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
|
||||
449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
|
||||
509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
|
||||
587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
|
||||
643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
|
||||
709, 719, 727, 733, 739, 743, 751, 757, 761, 769,
|
||||
773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
|
||||
853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
|
||||
919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
|
||||
991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
|
||||
1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
|
||||
1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
|
||||
1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
|
||||
1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277,
|
||||
1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307,
|
||||
1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
|
||||
1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
|
||||
1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
|
||||
1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
|
||||
1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
|
||||
1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
|
||||
1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
|
||||
1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,
|
||||
1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
|
||||
1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
|
||||
1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,
|
||||
1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
|
||||
2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111,
|
||||
2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161,
|
||||
2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243,
|
||||
2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
|
||||
2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
|
||||
2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411,
|
||||
2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473,
|
||||
2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
|
||||
2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633,
|
||||
2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
|
||||
2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729,
|
||||
2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
|
||||
2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851,
|
||||
2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917,
|
||||
2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
|
||||
3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061,
|
||||
3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137,
|
||||
3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209,
|
||||
3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
|
||||
3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
|
||||
3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391,
|
||||
3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467,
|
||||
3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533,
|
||||
3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583,
|
||||
3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
|
||||
3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
|
||||
3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779,
|
||||
3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
|
||||
3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917,
|
||||
3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
|
||||
4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049,
|
||||
4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111,
|
||||
4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
|
||||
4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243,
|
||||
4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
|
||||
4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391,
|
||||
4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
|
||||
4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519,
|
||||
4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597,
|
||||
4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
|
||||
4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
|
||||
4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799,
|
||||
4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
|
||||
4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951,
|
||||
4957, 4967, 4969, 4973, 4987, 4993, 4999,
|
||||
0
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,114 @@
|
|||
New features since 1.0.0
|
||||
------------------------
|
||||
|
||||
* The default symmetric cipher algorithm is now AES (aka
|
||||
Rijndael). OpenPGP uses preferences to figure out the algorithm
|
||||
to use, so this is only used if the recipient knows how to
|
||||
handles AES.
|
||||
|
||||
* RSA keys can now be used (either old PGP 2 or new OpenPGP ones).
|
||||
RSA key generation is not yet available.
|
||||
|
||||
* Unattended key generation.
|
||||
|
||||
* Faster and more robust random number generator under W32.
|
||||
|
||||
* Encryption is now much faster: About 2 times for 1k bit keys
|
||||
and 8 times for 4k keys.
|
||||
|
||||
* New encryption keys are generated in a way which allows a much
|
||||
faster decryption.
|
||||
|
||||
* GnuPG knows what the primary user ID is.
|
||||
|
||||
* Large File Support (LFS) is working.
|
||||
|
||||
* Ability to run gpg as a full controlled inferior process to speed up
|
||||
mass verification of signatures.
|
||||
|
||||
* Rewritten key selection code so that GnuPG can better cope with
|
||||
multiple subkeys, expiration dates and so on. The drawback is that it
|
||||
is slower.
|
||||
|
||||
* New utility gpgv which is a stripped down version of gpg to
|
||||
be used to verify signatures against a list of trusted keys.
|
||||
|
||||
* New command --export-secret-subkeys which outputs the
|
||||
the _primary_ key with it's secret parts deleted. This is
|
||||
useful for automated decryption/signature creation as it
|
||||
allows to keep the real secret primary key offline and
|
||||
thereby protecting the key certificates and allowing to
|
||||
create revocations for the subkeys. See the FAQ for a
|
||||
procedure to install such secret keys.
|
||||
|
||||
* New options --show-session-key and --override-session-key
|
||||
to help the British folks to somewhat minimize the danger
|
||||
of this Orwellian RIP bill.
|
||||
|
||||
* New option --no-auto-key-retrieve to disable retrieving of a
|
||||
missing public key from a keyserver, even when a keyserver has
|
||||
been configured. Useful for dial-up connections.
|
||||
|
||||
* HTTP proxy support for keyservers.
|
||||
|
||||
* Keyserver support is how also available for W32 platforms (MS
|
||||
Windows 95, 98, 2000, NT, ME).
|
||||
|
||||
* Experimental gpg-agent support to get the passphrase from a
|
||||
daemon which can pop up a query window.
|
||||
|
||||
|
||||
rfc2440bis support (PGP 6.5.8 does also handle them)
|
||||
-------------------
|
||||
|
||||
* MDC enhanced encryption is now used with the AES and Twofish
|
||||
algorithms to detect manipulated messages.
|
||||
|
||||
* The user is now asked for the reason of a revocation.
|
||||
|
||||
|
||||
Translations:
|
||||
------------
|
||||
|
||||
* Enhanced UTF-8 support
|
||||
|
||||
* New translations: Danish, Estonian, Indonesian, Portuguese and
|
||||
Turkish.
|
||||
|
||||
Serious bug fixes:
|
||||
------------------
|
||||
|
||||
* Fixed a serious bug which could lead to false signature
|
||||
verification results when more than one signature is fed to gpg.
|
||||
This is the primary reason for releasing this version.
|
||||
|
||||
* Protection against the recent Klima/Rosa attck on secret key
|
||||
rings.
|
||||
|
||||
* Corrected hash calculation for input data larger than 512M - it
|
||||
was just wrong, so you might notice bad signature in some very
|
||||
big files. It may be wise to keep an old copy of GnuPG around.
|
||||
|
||||
* Secret keys are no longer imported unless you use the new option
|
||||
--allow-secret-key-import.
|
||||
|
||||
PGP quirks
|
||||
----------
|
||||
|
||||
* Can handle (but not display) PGP's photo IDs.
|
||||
|
||||
* Better default values to increase compatibilty with PGP.
|
||||
|
||||
* Many other small enhancements to support the not fully-OpenPGP
|
||||
compliant PGP versions.
|
||||
|
||||
Manual
|
||||
------
|
||||
|
||||
* The manual called GNU Privacy Handbook (GPH) is a separate
|
||||
package and available preformatted in English, German, Italian,
|
||||
Russian and Spanish at http://www.gnupg.org/docs.html.
|
||||
[Due to the complicated build process, the source is currently
|
||||
on available from CVS]
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
Why to use GnuPG and not PGP.
|
||||
-----------------------------
|
||||
|
||||
* PGP 2 is nearly Free Software but encumbered by the IDEA patent.
|
||||
|
||||
* PGP 2 is old, hard to maintain and limited to one set of
|
||||
encryption algorithms (RSA + IDEA)
|
||||
|
||||
* PGP 2 is not a GNU or Unix Program and threfore not easy to use in
|
||||
those environments
|
||||
|
||||
* PGP 2 has a couple of minor security flaws
|
||||
|
||||
* PGP 5 and 6 are more or less OpenPGP conform but proprietray
|
||||
software. Source code is available but there is no way to be sure
|
||||
that the distributed binary versions do match the source code.
|
||||
Parts of the source code are not published. It is illegal to
|
||||
build versions of PGP from source and distribute them (IIRC, there
|
||||
is an exception for private users).
|
||||
|
||||
* PGP 5 and 6 are not fullty OpenPGP compliant
|
||||
|
||||
* PGP 7 is claimed to be OpenPGP compliant but the source code is
|
||||
not anymore published.
|
||||
|
||||
* At least versions before 6.5.8 had severe coding bugs. We don't
|
||||
know about PGP 7.
|
||||
|
||||
* PGP 5, 6 and 7 implement complicated methods for key recovering in
|
||||
corporate environments. Although this is not a hidden feature,
|
||||
this leads to more code and bugs.
|
||||
|
||||
* NAI as the vendor of PGP seems to be a major government contractor.
|
||||
|
||||
* Given the history of known backdoors in other proprietary software
|
||||
(e.g. Lotus Notes), some folks claim that there might also be
|
||||
backdoors in PGP 5, 6 and 7. Now there are even more rumors after
|
||||
Phil Zimmermann left NAI.
|
||||
|
||||
* GnuPG is Free Software under the GNU GPL. It does not use
|
||||
patented algorithms.
|
||||
|
||||
* Everyone is able to scrutinize the source code, build, distribute
|
||||
and use versions of his own or from a trusted party he chooses.
|
||||
|
||||
* The build environment is also Free Software and therefore less
|
||||
likely tampered with malicious code. The exception here is the MS
|
||||
Windows version of GnuPG where the OS is proprietary. The binary
|
||||
version however is build using an entirely Free Software OS and
|
||||
toolchain (cross-platfrom development under GNU/Linux).
|
||||
|
||||
* Security fixes are provided very fast.
|
||||
|
||||
* GnuPG is a standard tool in all GNU/Linux systems and used in many
|
||||
different environments.
|
||||
|
||||
* GnuPG gives reasonable messages and not just "Error encrypting".
|
||||
|
||||
* GnuPG supports most of the optional features of the OpenPGP standard.
|
||||
|
||||
* GnuPG comes with internationalization support for 16 languages.
|
||||
|
||||
* Graphical frontends are available and they divert the task of
|
||||
the actual cryptographic operations to GnuPG as a specialized tool
|
||||
for this. A library called GPGME is available which makes
|
||||
interfacing of GnuPG with other programs quite easy.
|
||||
|
||||
* GnuPG is available for all GNU and Unix platforms as well as for
|
||||
all MS Windows Operating systems. Porting to VMS, MAC OSX and
|
||||
OS/2 is nearly finished.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,7 +1,18 @@
|
|||
GDBM keyring support
|
||||
--------------------
|
||||
|
||||
GDBM-based keyring support is (and always) was an experimental feature
|
||||
which is likely to be removed in future versions. For that reason it
|
||||
is not compiled into the Debian package and won't be until and unless
|
||||
GDBM support stabilises.
|
||||
|
||||
Upgrading from old (<= 0.3.3) versions GnuPG
|
||||
--------------------------------------------
|
||||
|
||||
Due to a bug in the way secret keys were encrypted in versions prior
|
||||
to 0.3.3, later version of gnupg are not backwards compatible and you
|
||||
to 0.3.3, later version of GnuPG are not backwards compatible and you
|
||||
will have to convert your secret keys before using old secret keys
|
||||
with recent versions of gnupg.
|
||||
with recent versions of GnuPG.
|
||||
|
||||
The upgrade strategy is described in /usr/doc/gnupg/NEWS.gz, please
|
||||
refer to it for more details, but it requires an old copy of the gpg
|
||||
|
@ -9,8 +20,9 @@ and gpgm binaries. They may be on your system as gpg.old and
|
|||
gpgm.old, but if they're not you can find gnupg 0.3.2 source and
|
||||
binaries for i386, m68k, alpha, powerpc and hurd-i386 at:
|
||||
|
||||
<URL:http://james.nocrew.org/gnupg/>
|
||||
<URL:http://people.debian.org/~troup/gnupg/>
|
||||
|
||||
--
|
||||
James Troup <james@nocrew.org>, Bradford, UK
|
||||
Sun, 8 Nov 1998 19:11:40 +0000
|
||||
James Troup <james@nocrew.org>, Horsforth, UK
|
||||
Sun, 1 Oct 2000 13:53:12 +0100
|
||||
|
||||
|
|
|
@ -1,3 +1,155 @@
|
|||
gnupg (1.0.5-1) unstable; urgency=low
|
||||
|
||||
* New upstream version.
|
||||
* debian/README.Debian: fix spelling and update URL.
|
||||
* debian/rules (binary): remove the new info files.
|
||||
* scripts/config.{guess,sub}: sync with subversions, closes: #95729.
|
||||
|
||||
-- James Troup <james@nocrew.org> Mon, 30 Apr 2001 02:12:38 +0100
|
||||
|
||||
gnupg (1.0.4-4) unstable; urgency=low
|
||||
|
||||
* po/ru.po: patch by Ilya Martynov <m_ilya@agava.com> to replace German
|
||||
entries and add missing translations, closes: #93987.
|
||||
* g10/revoke.c (ask_revocation_reason): typo fix (s/non longer/no
|
||||
longer/g); noticed by Colin Watson <cjw44@flatline.org.uk>, closes:
|
||||
#93664.
|
||||
|
||||
* Deprecated depreciated; noticed by Vincent Broman
|
||||
<broman@spawar.navy.mil>.
|
||||
|
||||
* Following two patches are from Vincent Broman.
|
||||
* g10/mainproc.c (proc_tree): use iobuf_get_real_fname() in preference
|
||||
to iobuf_get_fname().
|
||||
* g10/openfile.c (open_sigfile): handle .sign prefixed files correctly.
|
||||
|
||||
-- James Troup <james@nocrew.org> Fri, 20 Apr 2001 23:32:44 +0100
|
||||
|
||||
gnupg (1.0.4-3) unstable; urgency=medium
|
||||
|
||||
* debian/rules (binary): make gpg binary suid, closes: #86433.
|
||||
* debian/postinst: don't use suidregister.
|
||||
* debian/postrm: removed (only called suidunregister).
|
||||
* debian/control: conflict with suidmanager << 0.50.
|
||||
* mpi/longlong.h: apply fix for ARM long long artimetic from Philip
|
||||
Blundell <philb@gnu.org>, closes: #87487.
|
||||
* debian/preinst: the old GnuPG debs have moved to people.debian.org.
|
||||
* cipher/random.c: #include <time.h> as well as <sys/time.h>
|
||||
* g10/misc.c: likewise.
|
||||
* debian/rules: define a strip alias which removes the .comment and
|
||||
.note sections.
|
||||
* debian/rules (binary-arch): use it.
|
||||
* debian/lintian.override: new file; override the SUID warning from
|
||||
lintian.
|
||||
* debian/rules (binary-arch): install it.
|
||||
|
||||
-- James Troup <james@nocrew.org> Sun, 25 Feb 2001 05:24:58 +0000
|
||||
|
||||
gnupg (1.0.4-2) stable unstable; urgency=high
|
||||
|
||||
* Apply security fix patch from Werner.
|
||||
* Apply another patch from Werner to fix bogus warning on Rijndael
|
||||
usage.
|
||||
* Change section to 'non-US'.
|
||||
|
||||
-- James Troup <james@nocrew.org> Mon, 12 Feb 2001 07:47:02 +0000
|
||||
|
||||
gnupg (1.0.4-1) stable unstable; urgency=high
|
||||
|
||||
* New upstream version.
|
||||
* Fixes a serious bug which could lead to false signature verification
|
||||
results when more than one signature is fed to gpg.
|
||||
|
||||
-- James Troup <james@nocrew.org> Tue, 17 Oct 2000 17:26:17 +0100
|
||||
|
||||
gnupg (1.0.3b-1) unstable; urgency=low
|
||||
|
||||
* New upstream snapshot version.
|
||||
|
||||
-- James Troup <james@nocrew.org> Fri, 13 Oct 2000 18:08:14 +0100
|
||||
|
||||
gnupg (1.0.3-2) unstable; urgency=low
|
||||
|
||||
* debian/control: Conflict, Replace and Provide gpg-rsa & gpg-rsaref.
|
||||
Fix long description to reflect the fact that RSA is no longer
|
||||
patented and now included. [#72177]
|
||||
* debian/rules: move faq.html to /usr/share/doc/gnupg/ and remove FAQ
|
||||
from /usr/share/gnupg/. Thanks to Robert Luberda
|
||||
<robert@pingu.ii.uj.edu.pl> for noticing. [#72151]
|
||||
* debian/control: Suggest new package gnupg-doc. [#64323, #65560]
|
||||
* utils/secmem.c (lock_pool): don't bomb out if mlock() returns ENOMEM,
|
||||
as Linux will do this if resource limits (or other reasons) prevent
|
||||
memory from being locked, instead treat it like permission was denied
|
||||
and warn but continue. Thanks to Topi Miettinen
|
||||
<Topi.Miettinen@nic.fi>. [#70446]
|
||||
* g10/hkp.c (not_implemented): s/ist/is/ in error message.
|
||||
* debian/README.Debian: add a note about GDBM support and why it is
|
||||
disabled. Upstream already fixed the manpage. [#65913]
|
||||
* debian/rules (binary-arch): fix the Spanish translation to be 'es' not
|
||||
'es_ES' at Nicolás Lichtmaier <nick@debian.org>'s request. [#57314]
|
||||
|
||||
-- James Troup <james@nocrew.org> Sun, 1 Oct 2000 14:55:03 +0100
|
||||
|
||||
gnupg (1.0.3-1) unstable; urgency=low
|
||||
|
||||
* New upstream version.
|
||||
|
||||
-- James Troup <james@nocrew.org> Mon, 18 Sep 2000 15:56:54 +0100
|
||||
|
||||
gnupg (1.0.2-1) unstable; urgency=low
|
||||
|
||||
* New upstream version.
|
||||
|
||||
-- James Troup <james@nocrew.org> Thu, 13 Jul 2000 20:26:50 +0100
|
||||
|
||||
gnupg (1.0.1-2) unstable; urgency=low
|
||||
|
||||
* debian/control (Build-Depends): added.
|
||||
* debian/copyright: corrected location of copyright file. Removed
|
||||
references to Linux. Removed warnings about beta nature of GnuPG.
|
||||
* debian/rules (binary-arch): install documentation into
|
||||
/usr/share/doc/gnupg/ and pass mandir to make install to ensure the
|
||||
manpages go to /usr/share/man/.
|
||||
* debian/postinst: create /usr/doc/gnupg symlink.
|
||||
* debian/prerm: new file; remove /usr/doc/gnupg symlink.
|
||||
* debian/rules (binary-arch): install prerm.
|
||||
* debian/control (Standards-Version): updated to 3.1.1.1.
|
||||
|
||||
-- James Troup <james@nocrew.org> Thu, 30 Dec 1999 16:16:49 +0000
|
||||
|
||||
gnupg (1.0.1-1) unstable; urgency=low
|
||||
|
||||
* New upstream version.
|
||||
* doc/gpg.1: updated to something usable from
|
||||
ftp://ftp.gnupg.org/pub/gcrypt/gnupg/gpg.1.gz.
|
||||
|
||||
-- James Troup <james@nocrew.org> Sun, 19 Dec 1999 23:47:10 +0000
|
||||
|
||||
gnupg (1.0.0-3) unstable; urgency=low
|
||||
|
||||
* debian/rules (build): remove the stunningly ill-advised --host option
|
||||
to configure. [#44698, #48212, #48281]
|
||||
|
||||
-- James Troup <james@nocrew.org> Tue, 26 Oct 1999 01:12:59 +0100
|
||||
|
||||
gnupg (1.0.0-2) unstable; urgency=low
|
||||
|
||||
* debian/rules (binary-arch): fix the permissions on the
|
||||
modules. [#47280]
|
||||
* debian/postinst, debian/postrm: fix the package name passed to
|
||||
suidregister. [#45013]
|
||||
* debian/control: update long description. [#44636]
|
||||
* debian/rules (build): pass the host explicitly to configure to avoid
|
||||
problems on sparc64. [(Should fix) #44698].
|
||||
|
||||
-- James Troup <james@nocrew.org> Wed, 20 Oct 1999 23:39:05 +0100
|
||||
|
||||
gnupg (1.0.0-1) unstable; urgency=low
|
||||
|
||||
* New upstream release. [#44545]
|
||||
|
||||
-- James Troup <james@nocrew.org> Wed, 8 Sep 1999 00:53:02 +0100
|
||||
|
||||
gnupg (0.9.10-2) unstable; urgency=low
|
||||
|
||||
* debian/rules (binary-arch): install lspgpot. Requested by Kai
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
Source: gnupg
|
||||
Section: utils
|
||||
Section: non-US
|
||||
Priority: optional
|
||||
Maintainer: James Troup <james@nocrew.org>
|
||||
Standards-Version: 2.5.0.0
|
||||
Standards-Version: 3.1.1.1
|
||||
Build-Depends: gettext, libgdbmg1-dev, libz-dev
|
||||
|
||||
Package: gnupg
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, makedev (>= 2.3.1-13)
|
||||
Suggests: gnupg-doc
|
||||
Conflicts: gpg-rsa, gpg-rsaref, suidmanager (<< 0.50)
|
||||
Replaces: gpg-rsa, gpg-rsaref
|
||||
Provides: gpg-rsa, gpg-rsaref
|
||||
Description: GNU privacy guard - a free PGP replacement.
|
||||
GnuPG is the GNU encryption and signing tool. As you can see from the
|
||||
version number, the program may have some bugs and some features may not
|
||||
work at all.
|
||||
GnuPG is GNU's tool for secure communication and data storage.
|
||||
It can be used to encrypt data and to create digital signatures.
|
||||
It includes an advanced key management facility and is compliant
|
||||
with the proposed OpenPGP Internet standard as described in RFC2440.
|
||||
.
|
||||
Due to the fact that GnuPG does not use use any patented algorithm,
|
||||
it cannot be compatible to old PGP versions, because those use
|
||||
IDEA (which is worldwide patented) and RSA (which is patented in
|
||||
the United States until Sep 20, 2000).
|
||||
.
|
||||
GnuPG is in almost all aspects compatible with other OpenPGP
|
||||
implementations. The default algorithms are DSA and ELGamal.
|
||||
Symmetric algorithms are: Blowfish and CAST5, Digest algorithms are
|
||||
MD5, RIPEMD160, SHA1 and TIGER/192.
|
||||
GnuPG does not use use any patented algorithms so it cannot be
|
||||
compatible with PGP2 because it uses IDEA (which is patented
|
||||
worldwide) and RSA. RSA's patent expired on the 20th September 2000,
|
||||
and it is now included in GnuPG.
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
This is Debian/GNU Linux's prepackaged version of GNUPG, a free PGP
|
||||
replacement. As you can see from the version number, the program may
|
||||
have some bugs and some features may not work at all.
|
||||
This is Debian GNU's prepackaged version of GnuPG, a free PGP
|
||||
replacement.
|
||||
|
||||
This package was put together by me, James Troup
|
||||
<james@nocrew.org>, from the sources, which I obtained from
|
||||
ftp://ftp.gnupg.org/pub/gcrypt/gnupg-0.9.10.tar.gz. The changes were
|
||||
minimal, namely:
|
||||
This package was put together by me, James Troup <james@nocrew.org>,
|
||||
from the sources, which I obtained from
|
||||
ftp://ftp.gnupg.org/pub/gcrypt/gnupg/gnupg-1.0.5.tar.gz. The changes
|
||||
were minimal, namely:
|
||||
|
||||
- adding support for the Debian package maintenance scheme, by adding
|
||||
various debian/* files.
|
||||
|
||||
Program Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
Modifications for Debian Copyright (C) 1998,1999 James Troup.
|
||||
Program Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
Modifications for Debian Copyright (C) 1998, 1999, 2000, 2001 James Troup.
|
||||
|
||||
GNUPG 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, or (at your option)
|
||||
any later version.
|
||||
GnuPG 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, or (at your option) any later
|
||||
version.
|
||||
|
||||
GNUPG 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.
|
||||
GnuPG 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 with
|
||||
your Debian GNU/Linux system, in /usr/doc/copyright/GPL, or with the
|
||||
Debian GNU/Linux gnupg source package as the file COPYING. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place, Suite
|
||||
330, Boston, MA 02111-1307, USA.
|
||||
your Debian GNU system, in /usr/share/common-licenses/GPL, or with the
|
||||
Debian GNU gnupg source package as the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
gnupg: setuid-binary usr/bin/gpg 4755 root/root
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
configure|abort-upgrade|abort-remove|abort-deconfigure)
|
||||
if [ -x /usr/sbin/suidregister ]; then
|
||||
suidregister -s gpg /usr/bin/gpg root root 4755
|
||||
else
|
||||
chmod 4755 /usr/bin/gpg
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
if [ -x /usr/sbin/suidunregister ]; then
|
||||
suidunregister -s gpg /usr/bin/gpg
|
||||
fi
|
||||
;;
|
||||
esac
|
|
@ -34,7 +34,7 @@ EOF
|
|||
If at any stage you need a pre-0.3.3 gnupg, you can find source and
|
||||
binaries for i386, m68k, alpha, powerpc and hurd-i386 at
|
||||
|
||||
http://james.nocrew.org/gnupg/
|
||||
http://people.debian.org/~troup/gnupg/
|
||||
|
||||
Press return to continue
|
||||
EOF
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/make -f
|
||||
# debian/rules file - for GNUPG (0.9.10)
|
||||
# debian/rules file - for GNUPG (1.0.5)
|
||||
# Based on sample debian/rules file - for GNU Hello (1.3).
|
||||
# Copyright 1994,1995 by Ian Jackson.
|
||||
# Copyright 1998 James Troup
|
||||
|
@ -9,6 +9,8 @@
|
|||
# paternity under the Copyright, Designs and Patents Act 1988.)
|
||||
# This file may have to be extensively modified
|
||||
|
||||
STRIP=strip --remove-section=.comment --remove-section=.note
|
||||
|
||||
build:
|
||||
$(checkdir)
|
||||
./configure --prefix=/usr --with-included-gettext
|
||||
|
@ -32,26 +34,36 @@ binary-arch: checkroot build # test
|
|||
$(checkdir)
|
||||
-rm -rf debian/tmp
|
||||
install -d debian/tmp/DEBIAN/
|
||||
install -m 755 debian/preinst debian/postinst debian/postrm debian/tmp/DEBIAN/
|
||||
$(MAKE) prefix=`pwd`/debian/tmp/usr install
|
||||
strip debian/tmp/usr/bin/*
|
||||
install -m 755 debian/preinst debian/prerm debian/postinst debian/tmp/DEBIAN/
|
||||
$(MAKE) prefix=`pwd`/debian/tmp/usr mandir=`pwd`/debian/tmp/usr/share/man install
|
||||
# copies of the manpage which can't be grokked by install-info
|
||||
rm debian/tmp/usr/info/*
|
||||
$(STRIP) debian/tmp/usr/bin/*
|
||||
chmod 4755 debian/tmp/usr/bin/gpg
|
||||
chmod 644 debian/tmp/usr/lib/gnupg/*
|
||||
sed -e "s#../g10/gpg#gpg#" < tools/lspgpot > debian/tmp/usr/bin/lspgpot
|
||||
chmod 755 debian/tmp/usr/bin/lspgpot
|
||||
strip --strip-unneeded debian/tmp/usr/lib/gnupg/*
|
||||
sed -e "s#/usr/local/#/usr/#" < debian/tmp/usr/man/man1/gpg.1 \
|
||||
> debian/tmp/usr/man/man1/gpg.1.new
|
||||
mv debian/tmp/usr/man/man1/gpg.1.new debian/tmp/usr/man/man1/gpg.1
|
||||
gzip -9v debian/tmp/usr/man/man1/*
|
||||
install -d debian/tmp/usr/doc/gnupg/
|
||||
install -m 644 debian/changelog debian/tmp/usr/doc/gnupg/changelog.Debian
|
||||
$(STRIP) --strip-unneeded debian/tmp/usr/lib/gnupg/*
|
||||
# In response to #53714... no idea if it's correct, will check with upstream
|
||||
mv debian/tmp/usr/share/locale/es_ES debian/tmp/usr/share/locale/es
|
||||
sed -e "s#/usr/local/#/usr/#" < debian/tmp/usr/share/man/man1/gpg.1 \
|
||||
> debian/tmp/usr/share/man/man1/gpg.1.new
|
||||
mv debian/tmp/usr/share/man/man1/gpg.1.new debian/tmp/usr/share/man/man1/gpg.1
|
||||
gzip -9v debian/tmp/usr/share/man/man1/*
|
||||
# Remove from /usr/share/gnupg that we install into /usr/share/doc/gnupg/
|
||||
rm debian/tmp/usr/share/gnupg/FAQ debian/tmp/usr/share/gnupg/faq.html
|
||||
install -d debian/tmp/usr/share/doc/gnupg/
|
||||
install -m 644 debian/changelog debian/tmp/usr/share/doc/gnupg/changelog.Debian
|
||||
install -m 644 debian/README.Debian README NEWS THANKS TODO doc/DETAILS \
|
||||
doc/FAQ doc/OpenPGP debian/tmp/usr/doc/gnupg/
|
||||
doc/FAQ doc/faq.html doc/OpenPGP debian/tmp/usr/share/doc/gnupg/
|
||||
for i in po util mpi cipher tools g10 checks include; do \
|
||||
install -m 644 $$i/ChangeLog debian/tmp/usr/doc/gnupg/changelog.$$i; done
|
||||
install -m 644 ChangeLog debian/tmp/usr/doc/gnupg/changelog.toplevel
|
||||
gzip -9v debian/tmp/usr/doc/gnupg/*
|
||||
ln -s changelog.g10.gz debian/tmp/usr/doc/gnupg/changelog.gz
|
||||
install -m 644 debian/copyright debian/tmp/usr/doc/gnupg/
|
||||
install -m 644 $$i/ChangeLog debian/tmp/usr/share/doc/gnupg/changelog.$$i; done
|
||||
install -m 644 ChangeLog debian/tmp/usr/share/doc/gnupg/changelog.toplevel
|
||||
gzip -9v debian/tmp/usr/share/doc/gnupg/*
|
||||
ln -s changelog.g10.gz debian/tmp/usr/share/doc/gnupg/changelog.gz
|
||||
install -m 644 debian/copyright debian/tmp/usr/share/doc/gnupg/
|
||||
install -d debian/tmp/usr/share/lintian/overrides/
|
||||
install -m 644 debian/lintian.override debian/tmp/usr/share/lintian/overrides/gnupg
|
||||
dpkg-shlibdeps g10/gpg
|
||||
dpkg-gencontrol -isp
|
||||
chown -R root.root debian/tmp
|
||||
|
|
355
doc/ChangeLog
355
doc/ChangeLog
|
@ -1,27 +1,365 @@
|
|||
Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
|
||||
2002-06-21 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* Makefile.am (SUBDIRS): Removed gph from this development series
|
||||
* DETAILS: Document "uat".
|
||||
|
||||
* gpg.sgml: Document
|
||||
--personal-{compress|digest|compress}-preferences, --group, and
|
||||
add comments to --expert.
|
||||
|
||||
2002-06-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Grammar fix.
|
||||
|
||||
2002-06-03 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* DETAILS: Details of ATTRIBUTE.
|
||||
|
||||
* gpg.sgml: Document --attribute-fd
|
||||
|
||||
2002-06-03 Timo Schulz <ts@winpt.org>
|
||||
|
||||
* DETAILS: Add ATTRIBUTE.
|
||||
|
||||
2002-05-31 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Add "edit/addrevoker". Document --desig-revoke. Note
|
||||
that -z and --compress are the same option. Note that
|
||||
--digest-algo can no longer violate OpenPGP with a non-160 bit
|
||||
hash with DSA. Document --cert-digest-algo with suitable warnings
|
||||
not to use it. Note the default s2k-cipher-algo is now CAST5.
|
||||
Note that --force-v3-sigs overrides --ask-sig-expire. Revise
|
||||
--expert documentation, as it is now definitely legal to have more
|
||||
than one photo ID on a key. --preference-list is now
|
||||
--default-preference-list with the new meaning. Document
|
||||
--personal-preference-list.
|
||||
|
||||
* DETAILS: Document "Revoker" for batch key generation.
|
||||
|
||||
2002-05-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: sgml syntax fix.
|
||||
|
||||
2002-05-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Fixed URL in the description section.
|
||||
|
||||
* faq.raw: Minor typo fixes noted by kromJx@myrealbox.com.
|
||||
|
||||
2002-05-11 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Typo fix.
|
||||
|
||||
2002-05-07 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Add entries for --sk-comments, --no-sk-comments,
|
||||
--pgp7, and --no-pgp7. Fix --pgp2 and --pgp6: the proper name is
|
||||
--escape-from-lines and not --escape-from.
|
||||
|
||||
2002-04-30 Timo Schulz <ts@winpt.org>
|
||||
|
||||
* gpg.sgml: Add an entry for --encrypt-files and --decrypt-files.
|
||||
|
||||
2002-04-29 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Fix minor error in --pgp6 documentation: it does not
|
||||
imply --digest-algo MD5
|
||||
|
||||
2002-04-29 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* samplekeys.asc: Added gnupg distribution key 57548DCD.
|
||||
|
||||
* faq.raw: Inserted Douglas Calvert as new maintainer. Acknowledge
|
||||
Nils. Add entry about trust packet parsing problems.
|
||||
|
||||
2002-04-24 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Add some documentation for
|
||||
--edit/{addphoto|showphoto|nrsign|nrlsign}, and the difference
|
||||
between %t and %T in photo viewer command lines.
|
||||
|
||||
2002-04-23 Stefan Bellon <sbellon@sbellon.de>
|
||||
|
||||
* gpg.sgml: Moved options from section "COMMANDS" to
|
||||
section "OPTIONS".
|
||||
|
||||
2002-04-20 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* samplekeys.asc: Added 0x5B0358A2
|
||||
|
||||
2002-04-19 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Add "%t" flag for photo IDs, a note about primary
|
||||
having different meanings for photo and regular IDs, rename
|
||||
--default-check-level to --default-cert-check-level, add
|
||||
--auto-check-trustdb, and --pgp6.
|
||||
|
||||
* DETAILS: Add EXPSIG, EXPKEYSIG, and KEYEXPIRED. Add notes to
|
||||
SIGEXPIRED (deprecated), and VALIDSIG (added expiration date).
|
||||
Add "Preferences" command to unattended key generation
|
||||
instructions. Also fixed a few typos.
|
||||
|
||||
* samplekeys.asc: new (added to EXTRA_DIST in Makefile.am as well)
|
||||
|
||||
2002-01-31 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* DETAILS: Fix a spelling error, correct IMPORTED_RES to IMPORT_RES,
|
||||
correct INV_RECP (the second occurence) to NO_RECP.
|
||||
|
||||
2002-04-03 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: auto-key-retrieve is a keyserver-option (noted by
|
||||
Roger Sondermann).
|
||||
|
||||
2002-03-27 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: --pgp2 also means --disable-mdc, --no-ask-sig-expire,
|
||||
and --no-ask-cert-expire. It does not mean --no-force-v3-sigs
|
||||
(noted by Timo).
|
||||
|
||||
2002-03-27 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Add a few notes about --pgp2 meaning MIT PGP 2.6.2,
|
||||
and keyserver details about HKP and NAI HKP.
|
||||
|
||||
2002-03-18 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Change meaning of --allow-non-selfsigned-uid to match
|
||||
change in code, and add --no-allow-non-selfsigned-uid.
|
||||
|
||||
2002-03-13 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* faq.raw: Due to a lack of time Nils can't serve anymore as a
|
||||
maintainer. Removed his address and setup a generic address.
|
||||
|
||||
2002-03-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Add an entry for --export-ownertrust. Suggested by
|
||||
Bernhard Reiter.
|
||||
|
||||
2002-01-26 Timo Schulz <ts@winpt.org>
|
||||
|
||||
* gnupg-w32.reg: New. Registry file for W32 in registry format.
|
||||
|
||||
2002-01-26 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: A few words about --gpg-agent-info and GPG_AGENT_INFO.
|
||||
|
||||
2002-01-25 Timo Schulz <ts@winpt.org>
|
||||
|
||||
* README.W32: Modify the filename because now the .exe extension
|
||||
is automatically added to the binary.
|
||||
|
||||
2002-01-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Talk about PGP 5 and higher.
|
||||
|
||||
2002-01-11 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Added documentation for --{no-}ask-cert-expire,
|
||||
--{no-}ask-sig-expire, and revise --expert (it doesn't switch on
|
||||
the expiration prompt anymore) and --default-check-level (to be
|
||||
clearer as to what makes a good key check before signing).
|
||||
|
||||
2002-01-07 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* DETAILS: Removed the comment that unattended key generation is
|
||||
experimental. It is now a standard feature.
|
||||
|
||||
2001-12-22 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Fixed a few typos.
|
||||
|
||||
* gpg.sgml: Added documentation for --show-photos,
|
||||
--no-show-photos, --photo-viewer, --nrsign-key,
|
||||
--default-check-level, --search-keys, --keyserver-options,
|
||||
--show-notation, --no-show-notation, --show-policy-url,
|
||||
--no-show-policy-url, --for-your-eyes-only,
|
||||
--no-for-your-eyes-only, --pgp2, --no-pgp2,
|
||||
--no-permission-warning, --expert, --no-expert.
|
||||
|
||||
2001-10-31 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Add a remark on how to get the long key ID. Suggested
|
||||
by Sebastian Klemke.
|
||||
|
||||
2001-10-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Add missing tag.
|
||||
|
||||
2001-09-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Add a note on option parsing.
|
||||
|
||||
2001-09-24 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Described --{update,check}-trustdb.
|
||||
|
||||
2001-09-03 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml, gpgv.sgml: Removed GDBM stuff.
|
||||
|
||||
2001-08-29 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* faq.raw: Described how to delete a secret key w/o a public key
|
||||
and changed the entry on updating the preferences.
|
||||
|
||||
2001-08-08 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Documented --print-mds and marked the --print-md * as
|
||||
deprecated because it does not work in the W32 version. Suggested
|
||||
by John Kane.
|
||||
(WARNINGS): Typo fix.
|
||||
(--with-colons): Clarified that the output is in UTF-8.
|
||||
|
||||
2001-08-01 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Added --ignore-valid-from
|
||||
|
||||
2001-04-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* faq.raw (Maintained-by): Removed note that load-extension is not
|
||||
available under Windoze.
|
||||
|
||||
* gpg.sgml: Add new --charset UTF-8.
|
||||
|
||||
2001-04-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* faq.raw: Add a note about dates displayed as ????-??-??.
|
||||
|
||||
2001-04-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am (%.texi): Add rules to create .texi from .sgml.
|
||||
However we can't automate this because automake does not like
|
||||
.texi files as BUILT_SOURCES.
|
||||
(%.dvi,%.ps): Removed these rules, because they are not needed
|
||||
and get in the way of automake's dvi target
|
||||
|
||||
* HACKING: Changed CVS description.
|
||||
|
||||
2001-04-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Small typo fixes by Florian Weimer.
|
||||
|
||||
2001-03-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Add --no-sig-cache and --no-sig-create-check.
|
||||
|
||||
2001-03-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* DETAILS: New status UNEXPECTED.
|
||||
|
||||
2001-03-13 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Described --fixed-list-mode.
|
||||
|
||||
2001-03-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpgv.sgml: Changed some gpg to gpgv. Thanks to John A. Murdie.
|
||||
|
||||
2001-03-03 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Tell something about the 0x12345678! key ID syntax.
|
||||
|
||||
2001-01-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* README.W32: Changed building instructions for MinGW32/CPD 0.3
|
||||
|
||||
2001-01-09 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* DETAILS: Fixed docs for NEED_PASSPHRASE and added USERID_HINT.
|
||||
|
||||
2000-11-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Fixed the description of --verify. Add a short note
|
||||
the warnings sections.
|
||||
|
||||
2000-10-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg.sgml: Fixed doc for --allow-non-selfsigned-uid.
|
||||
Add entry for --ignore-crc-error.
|
||||
|
||||
2000-10-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* OpenPGP: Dropped the paragraph that RSA is not implemented.
|
||||
|
||||
2000-10-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* faq.raw: Add an answer to the problem of multiple signatures.
|
||||
|
||||
Wed Oct 4 15:50:18 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* gpgv.sgml: New.
|
||||
* Makefile.am: build it.
|
||||
|
||||
Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* faq.raw: New.
|
||||
* Makefile.am: Support to build FAQs
|
||||
|
||||
Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@>
|
||||
|
||||
* gpg.sgml: Add a note about the availability of the GPH.
|
||||
|
||||
2000-07-03 13:59:24 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* DETAILS, FAQ: Typo fixes by Yosiaki IIDA.
|
||||
|
||||
2000-05-12 10:57:21 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* gpg.sgml: Documented --no-tty.
|
||||
|
||||
2000-03-09 15:01:51 Werner Koch (wk@habibti.openit.de)
|
||||
|
||||
* DETAILS: Ad a short blurb about unattended key generation.
|
||||
|
||||
Wed Feb 9 15:33:44 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* gpg.sgml: Describe --ignore-time-conflict.
|
||||
|
||||
* gpg.sgml: Fixed a few typos. Thanks to Holger Trapp.
|
||||
|
||||
Wed Jan 5 11:51:17 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* FAQ: Enhanced answer for the 3des-s2k bug.
|
||||
|
||||
Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* gpg.sgml: Add section about the user ID
|
||||
|
||||
Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* gph: Removed the directory from the dist becuase it will
|
||||
go into it's own package.
|
||||
|
||||
Thu Sep 23 09:52:58 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* README.W32: New.
|
||||
|
||||
Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* Makefile.am (SUBDIRS): New subdir gph for the manual.
|
||||
|
||||
Thu Jul 22 20:03:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* gpg.sgml (--always-trust): Added.
|
||||
|
||||
Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* Makefile.am: Create a dummy man page if docbook-to-man is missing.
|
||||
|
||||
Wed Jun 16 20:16:21 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* gpg1.pod: Removed.
|
||||
* gpg.sgml: New. Replaces the pod file
|
||||
* Makefile.am: Add rule to make a man file from sgml
|
||||
|
||||
Tue Jun 15 12:21:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* Makefile.in.in: Use DESTDIR.
|
||||
|
||||
Mon May 31 19:41:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
@ -30,7 +368,20 @@ Mon May 31 19:41:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
|||
|
||||
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
|
||||
* gpg.1pod: Spelling and grammar corrections (John A. Martin)
|
||||
* FAQ: Ditto.
|
||||
* DETAILS: Ditto.
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
|
418
doc/DETAILS
418
doc/DETAILS
|
@ -1,23 +1,47 @@
|
|||
|
||||
Format of "---with-colons" listings
|
||||
===================================
|
||||
Format of colon listings
|
||||
========================
|
||||
First an example:
|
||||
|
||||
$ gpg --fixed-list-mode --with-colons --list-keys \
|
||||
--with-fingerprint --with-fingerprint wk@gnupg.org
|
||||
|
||||
pub:f:1024:17:6C7EE1B8621CC013:899817715:1055898235::m:::scESC:
|
||||
fpr:::::::::ECAF7590EB3443B5C7CF3ACB6C7EE1B8621CC013:
|
||||
uid:f::::::::Werner Koch <wk@g10code.com>:
|
||||
uid:f::::::::Werner Koch <wk@gnupg.org>:
|
||||
sub:f:1536:16:06AD222CADF6A6E1:919537416:1036177416:::::e:
|
||||
fpr:::::::::CF8BCC4B18DE08FCD8A1615906AD222CADF6A6E1:
|
||||
sub:r:1536:20:5CE086B5B5A18FF4:899817788:1025961788:::::esc:
|
||||
fpr:::::::::AB059359A3B81F410FCFF97F5CE086B5B5A18FF4:
|
||||
|
||||
The double --with-fingerprint prints the fingerprint for the subkeys
|
||||
too, --fixed-list-mode is themodern listing way printing dates in
|
||||
seconds since Epoch and does not merge the first userID with the pub
|
||||
record.
|
||||
|
||||
sec::1024:17:6C7EE1B8621CC013:1998-07-07:0:::Werner Koch <werner.koch@guug.de>:
|
||||
ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
|
||||
|
||||
1. Field: Type of record
|
||||
pub = public key
|
||||
crt = X.509 certificate
|
||||
crs = X.509 certificate and private key available
|
||||
sub = subkey (secondary key)
|
||||
sec = secret key
|
||||
ssb = secret subkey (secondary key)
|
||||
uid = user id (only field 10 is used).
|
||||
uat = user attribute (same as user id except for field 10).
|
||||
sig = signature
|
||||
rev = revocation signature
|
||||
fpr = fingerprint: (fingerprint is in field 10)
|
||||
pkd = public key data (special field format, see below)
|
||||
grp = reserved for gpgsm
|
||||
rvk = revocation key
|
||||
|
||||
2. Field: A letter describing the calculated trust. This is a single
|
||||
letter, but be prepared that additional information may follow
|
||||
in some future versions. (not used for secret keys)
|
||||
o = Unknown (this key is new to the system)
|
||||
i = The key is invalid (e.g. due to a missing self-signature)
|
||||
d = The key has been disabled
|
||||
r = The key has been revoked
|
||||
e = The key has expired
|
||||
|
@ -33,21 +57,51 @@ ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
|
|||
17 = DSA (sometimes called DH, sign only)
|
||||
20 = ElGamal (sign and encrypt)
|
||||
(for other id's see include/cipher.h)
|
||||
5. Field: KeyID
|
||||
5. Field: KeyID either of
|
||||
6. Field: Creation Date (in UTC)
|
||||
7. Field: Key expiration date or empty if none.
|
||||
8. Field: Local ID: record number of the dir record in the trustdb.
|
||||
This value is only valid as long as the trustdb is not
|
||||
deleted. You can use "#<local-id> as the user id when
|
||||
specifying a key. This is needed because keyids may not be
|
||||
unique - a program may use this number to access keys later.
|
||||
8. Field: Used for serial number in crt records (used to be the Local-ID)
|
||||
9. Field: Ownertrust (primary public keys only)
|
||||
This is a single letter, but be prepared that additional
|
||||
information may follow in some future versions.
|
||||
10. Field: User-ID. The value is quoted like a C string to avoid
|
||||
control characters (the colon is quoted "\x3a").
|
||||
This is not used with --fixed-list-mode in gpg.
|
||||
A UAT record puts the attribute subpacket count here, a
|
||||
space, and then the total attribute subpacket size.
|
||||
In gpgsm the issuer name comes here
|
||||
An FPR record stores the fingerprint here.
|
||||
The fingerprint of an revocation key is stored here.
|
||||
11. Field: Signature class. This is a 2 digit hexnumber followed by
|
||||
either the letter 'x' for an exportable signature or the
|
||||
letter 'l' for a local-only signature.
|
||||
The class byte of an revocation key is also given here,
|
||||
'x' and 'l' ist used the same way.
|
||||
12. Field: Key capabilities:
|
||||
e = encrypt
|
||||
s = sign
|
||||
c = certify
|
||||
A key may have any combination of them. The primary key has in
|
||||
addition to these letters, uppercase version of the letter to
|
||||
denote the _usable_ capabilities of the entire key.
|
||||
13. Field: Used in FPR records for S/MIME keys to store the fingerprint of
|
||||
the issuer certificate. This is useful to build the
|
||||
certificate path based on certificates stored in the local
|
||||
keyDB; it is only filled if the issue certificate is
|
||||
available. The advantage of using this value is that it is
|
||||
guaranteed to have been been build by the same lookup
|
||||
algorithm as gpgsm uses.
|
||||
For "uid" recods this lists the preferences n the sameway the
|
||||
-edit menu does.
|
||||
14. Field Flag field used in the --edit menu output:
|
||||
|
||||
More fields may be added later.
|
||||
|
||||
All dates are displayed in the format yyyy-mm-dd unless you use the
|
||||
option --fixed-list-mode in which case they are displayed as seconds
|
||||
since Epoch. More fields may be added later, so parsers should be
|
||||
prepared for this. When parsing a number the parser should stop at the
|
||||
first non-number character so that additional information can later be
|
||||
added.
|
||||
|
||||
If field 1 has the tag "pkd", a listing looks like this:
|
||||
pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
||||
|
@ -55,7 +109,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||
! !------ for information number of bits in the value
|
||||
!--------- index (eg. DSA goes from 0 to 3: p,q,g,y)
|
||||
|
||||
|
||||
|
||||
|
||||
Format of the "--status-fd" output
|
||||
==================================
|
||||
|
@ -66,10 +120,26 @@ more arguments in future versions.
|
|||
|
||||
|
||||
GOODSIG <long keyid> <username>
|
||||
The signature with the keyid is good.
|
||||
The signature with the keyid is good. For each signature only
|
||||
one of the three codes GOODSIG, BADSIG or ERRSIG will be
|
||||
emitted and they may be used as a marker for a new signature.
|
||||
The username is the primary one encoded in UTF-8 and %XX
|
||||
escaped.
|
||||
|
||||
EXPSIG <long keyid> <username>
|
||||
The signature with the keyid is good, but the signature is
|
||||
expired. The username is the primary one encoded in UTF-8 and
|
||||
%XX escaped.
|
||||
|
||||
EXPKEYSIG <long keyid> <username>
|
||||
The signature with the keyid is good, but the signature was
|
||||
made by an expired key. The username is the primary one
|
||||
encoded in UTF-8 and %XX escaped.
|
||||
|
||||
BADSIG <long keyid> <username>
|
||||
The signature with the keyid has not been verified okay.
|
||||
The username is the primary one encoded in UTF-8 and %XX
|
||||
escaped.
|
||||
|
||||
ERRSIG <long keyid> <pubkey_algo> <hash_algo> \
|
||||
<sig_class> <timestamp> <rc>
|
||||
|
@ -80,11 +150,14 @@ more arguments in future versions.
|
|||
this signature. sig_class is a 2 byte hex-value.
|
||||
|
||||
VALIDSIG <fingerprint in hex> <sig_creation_date> <sig-timestamp>
|
||||
<expire-timestamp>
|
||||
|
||||
The signature with the keyid is good. This is the same
|
||||
as GOODSIG but has the fingerprint as the argument. Both
|
||||
status lines ere emitted for a good signature.
|
||||
status lines are emitted for a good signature.
|
||||
sig-timestamp is the signature creation time in seconds after
|
||||
the epoch.
|
||||
the epoch. expire-timestamp is the signature expiration time
|
||||
in seconds after the epoch (zero means "does not expire").
|
||||
|
||||
SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
|
||||
This is emitted only for signatures of class 0 or 1 which
|
||||
|
@ -107,34 +180,51 @@ more arguments in future versions.
|
|||
3 - Invalid packet found, this may indicate a non OpenPGP message.
|
||||
You may see more than one of these status lines.
|
||||
|
||||
TRUST_UNDEFINED
|
||||
TRUST_NEVER
|
||||
UNEXPECTED <what>
|
||||
Unexpected data has been encountered
|
||||
0 - not further specified 1
|
||||
|
||||
|
||||
TRUST_UNDEFINED <error token>
|
||||
TRUST_NEVER <error token>
|
||||
TRUST_MARGINAL
|
||||
TRUST_FULLY
|
||||
TRUST_ULTIMATE
|
||||
For good signatures one of these status lines are emitted
|
||||
to indicate how trustworthy the signature is. No arguments yet.
|
||||
to indicate how trustworthy the signature is. The error token
|
||||
values are currently only emiited by gpgsm.
|
||||
|
||||
SIGEXPIRED
|
||||
The signature key has expired. No arguments yet.
|
||||
This is deprecated in favor of KEYEXPIRED.
|
||||
|
||||
KEYEXPIRED <expire-timestamp>
|
||||
The key has expired. expire-timestamp is the expiration time
|
||||
in seconds after the epoch.
|
||||
|
||||
KEYREVOKED
|
||||
The used key has been revoked by his owner. No arguments yet.
|
||||
The used key has been revoked by its owner. No arguments yet.
|
||||
|
||||
BADARMOR
|
||||
The ASCII armor is corrupted. No arguments yet.
|
||||
|
||||
RSA_OR_IDEA
|
||||
The RSA or IDEA algorithms has been used in the data. A
|
||||
The IDEA algorithms has been used in the data. A
|
||||
program might want to fallback to another program to handle
|
||||
the data if GnuPG failed.
|
||||
the data if GnuPG failed. This status message used to be emitted
|
||||
also for RSA but this has been dropped after the RSA patent expired.
|
||||
However we can't change the name of the message.
|
||||
|
||||
SHM_INFO
|
||||
SHM_GET
|
||||
SHM_GET_BOOL
|
||||
SHM_GET_HIDDEN
|
||||
|
||||
NEED_PASSPHRASE <long keyid> <keytype> <keylength>
|
||||
GET_BOOL
|
||||
GET_LINE
|
||||
GET_HIDDEN
|
||||
GOT_IT
|
||||
|
||||
NEED_PASSPHRASE <long main keyid> <long keyid> <keytype> <keylength>
|
||||
Issued whenever a passphrase is needed.
|
||||
keytype is the numerical value of the public key algorithm
|
||||
or 0 if this is not applicable, keylength is the length
|
||||
|
@ -149,7 +239,7 @@ more arguments in future versions.
|
|||
will probably be a BAD_PASSPHRASE. However, if the application
|
||||
is a wrapper around the key edit menu functionality it might not
|
||||
make sense to stop parsing but simply ignoring the following
|
||||
PAD_PASSPHRASE.
|
||||
BAD_PASSPHRASE.
|
||||
|
||||
BAD_PASSPHRASE <long keyid>
|
||||
The supplied passphrase was wrong or not given. In the latter case
|
||||
|
@ -177,7 +267,7 @@ more arguments in future versions.
|
|||
IMPORTED <long keyid> <username>
|
||||
The keyid and name of the signature just imported
|
||||
|
||||
IMPORTED_RES <count> <no_user_id> <imported> <imported_rsa> <unchanged>
|
||||
IMPORT_RES <count> <no_user_id> <imported> <imported_rsa> <unchanged>
|
||||
<n_uids> <n_subk> <n_sigs> <n_revoc> <sec_read> <sec_imported> <sec_dups>
|
||||
Final statistics on import process (this is one long line)
|
||||
|
||||
|
@ -185,11 +275,108 @@ more arguments in future versions.
|
|||
Start processing a file <filename>. <what> indicates the performed
|
||||
operation:
|
||||
1 - verify
|
||||
2 - encrypt
|
||||
3 - decrypt
|
||||
|
||||
FILE_DONE
|
||||
Marks the end of a file processing which has been started
|
||||
by FILE_START.
|
||||
|
||||
BEGIN_DECRYPTION
|
||||
END_DECRYPTION
|
||||
Mark the start and end of the actual decryption process. These
|
||||
are also emitted when in --list-only mode.
|
||||
|
||||
BEGIN_ENCRYPTION <mdc_method> <sym_algo>
|
||||
END_ENCRYPTION
|
||||
Mark the start and end of the actual encryption process.
|
||||
|
||||
DELETE_PROBLEM reason_code
|
||||
Deleting a key failed. Reason codes are:
|
||||
1 - No such key
|
||||
2 - Must delete secret key first
|
||||
|
||||
PROGRESS what char cur total
|
||||
Used by the primegen and Public key functions to indicate progress.
|
||||
"char" is the character displayed with no --status-fd enabled, with
|
||||
the linefeed replaced by an 'X'. "cur" is the current amount
|
||||
done and "total" is amount to be done; a "total" of 0 indicates that
|
||||
the total amount is not known. 100/100 may be used to detect the
|
||||
end of operation.
|
||||
|
||||
SIG_CREATED <type> <pubkey algo> <hash algo> <class> <timestamp> <key fpr>
|
||||
A signature has been created using these parameters.
|
||||
type: 'D' = detached
|
||||
'C' = cleartext
|
||||
'S' = standard
|
||||
(only the first character should be checked)
|
||||
class: 2 hex digits with the signature class
|
||||
|
||||
KEY_CREATED <type>
|
||||
A key has been created
|
||||
type: 'B' = primary and subkey
|
||||
'P' = primary
|
||||
'S' = subkey
|
||||
|
||||
SESSION_KEY <algo>:<hexdigits>
|
||||
The session key used to decrypt the message. This message will
|
||||
only be emmited when the special option --show-session-key
|
||||
is used. The format is suitable to be passed to the option
|
||||
--override-session-key
|
||||
|
||||
NOTATION_NAME <name>
|
||||
NOTATION_DATA <string>
|
||||
name and string are %XX escaped; the data may be splitted
|
||||
among several notation_data lines.
|
||||
|
||||
USERID_HINT <long main keyid> <string>
|
||||
Give a hint about the user ID for a certain keyID.
|
||||
|
||||
POLICY_URL <string>
|
||||
string is %XX escaped
|
||||
|
||||
BEGIN_STREAM
|
||||
END_STREAM
|
||||
Issued by pipemode.
|
||||
|
||||
INV_RECP <reason> <requested_recipient>
|
||||
Issued for each unusable recipient. The reasons codes
|
||||
currently in use are:
|
||||
0 := "No specific reason given".
|
||||
1 := "Not Found"
|
||||
2 := "Ambigious specification"
|
||||
|
||||
NO_RECP <reserved>
|
||||
Issued when no recipients are usable.
|
||||
|
||||
ALREADY_SIGNED <long-keyid>
|
||||
Warning: This is experimental and might be removed at any time.
|
||||
|
||||
TRUNCATED <maxno>
|
||||
The output was truncated to MAXNO items. This status code is issued
|
||||
for certain external requests
|
||||
|
||||
ERROR <error location> <error code>
|
||||
This is a generic error status message, it might be followed
|
||||
by error location specific data. <error token> and
|
||||
<error_location> should not contain a space.
|
||||
|
||||
ATTRIBUTE <fpr> <octets> <type> <index> <count>
|
||||
<timestamp> <expiredate> <flags>
|
||||
This is one long line issued for each attribute subpacket when
|
||||
an attribute packet is seen during key listing. <fpr> is the
|
||||
fingerprint of the key. <octets> is the length of the
|
||||
attribute subpacket. <type> is the attribute type
|
||||
(1==image). <index>/<count> indicates that this is the Nth
|
||||
indexed subpacket of count total subpackets in this attribute
|
||||
packet. <timestamp> and <expiredate> are from the
|
||||
self-signature on the attribute packet. If the attribute
|
||||
packet does not have a valid self-signature, then the
|
||||
timestamp is 0. <flags> are a bitwise OR of:
|
||||
0x01 = this attribute packet is a primary uid
|
||||
0x02 = this attribute packet is revoked
|
||||
0x04 = this attribute packet is expired
|
||||
|
||||
|
||||
Key generation
|
||||
==============
|
||||
|
@ -222,6 +409,121 @@ Key generation
|
|||
Crypto '97 proceedings p. 260.
|
||||
|
||||
|
||||
Unattended key generation
|
||||
=========================
|
||||
This feature allows unattended generation of keys controlled by a
|
||||
parameter file. To use this feature, you use --gen-key together with
|
||||
--batch and feed the parameters either from stdin or from a file given
|
||||
on the commandline.
|
||||
|
||||
The format of this file is as follows:
|
||||
o Text only, line length is limited to about 1000 chars.
|
||||
o You must use UTF-8 encoding to specify non-ascii characters.
|
||||
o Empty lines are ignored.
|
||||
o Leading and trailing spaces are ignored.
|
||||
o A hash sign as the first non white space character indicates a comment line.
|
||||
o Control statements are indicated by a leading percent sign, the
|
||||
arguments are separated by white space from the keyword.
|
||||
o Parameters are specified by a keyword, followed by a colon. Arguments
|
||||
are separated by white space.
|
||||
o The first parameter must be "Key-Type", control statements
|
||||
may be placed anywhere.
|
||||
o Key generation takes place when either the end of the parameter file
|
||||
is reached, the next "Key-Type" parameter is encountered or at the
|
||||
control statement "%commit"
|
||||
o Control statements:
|
||||
%echo <text>
|
||||
Print <text>.
|
||||
%dry-run
|
||||
Suppress actual key generation (useful for syntax checking).
|
||||
%commit
|
||||
Perform the key generation. An implicit commit is done
|
||||
at the next "Key-Type" parameter.
|
||||
%pubring <filename>
|
||||
%secring <filename>
|
||||
Do not write the key to the default or commandline given
|
||||
keyring but to <filename>. This must be given before the first
|
||||
commit to take place, duplicate specification of the same filename
|
||||
is ignored, the last filename before a commit is used.
|
||||
The filename is used until a new filename is used (at commit points)
|
||||
and all keys are written to that file. If a new filename is given,
|
||||
this file is created (and overwrites an existing one).
|
||||
Both control statements must be given.
|
||||
o The order of the parameters does not matter except for "Key-Type"
|
||||
which must be the first parameter. The parameters are only for the
|
||||
generated keyblock and parameters from previous key generations are not
|
||||
used. Some syntactically checks may be performed.
|
||||
The currently defined parameters are:
|
||||
Key-Type: <algo-number>|<algo-string>
|
||||
Starts a new parameter block by giving the type of the
|
||||
primary key. The algorithm must be capable of signing.
|
||||
This is a required parameter.
|
||||
Key-Length: <length-in-bits>
|
||||
Length of the key in bits. Default is 1024.
|
||||
Key-Usage: <usage-list>
|
||||
Space or comma delimited list of key usage, allowed values are
|
||||
"encrypt" and "sign". This is used to generate the key flags.
|
||||
Please make sure that the algorithm is capable of this usage.
|
||||
Subkey-Type: <algo-number>|<algo-string>
|
||||
This generates a secondary key. Currently only one subkey
|
||||
can be handled.
|
||||
Subkey-Length: <length-in-bits>
|
||||
Length of the subkey in bits. Default is 1024.
|
||||
Subkey-Usage: <usage-list>
|
||||
Similar to Key-Usage.
|
||||
Passphrase: <string>
|
||||
If you want to specify a passphrase for the secret key,
|
||||
enter it here. Default is not to use any passphrase.
|
||||
Name-Real: <string>
|
||||
Name-Comment: <string>
|
||||
Name-Email: <string>
|
||||
The 3 parts of a key. Remember to use UTF-8 here.
|
||||
If you don't give any of them, no user ID is created.
|
||||
Expire-Date: <iso-date>|(<number>[d|w|m|y])
|
||||
Set the expiration date for the key (and the subkey). It
|
||||
may either be entered in ISO date format (2000-08-15) or as
|
||||
number of days, weeks, month or years. Without a letter days
|
||||
are assumed.
|
||||
Preferences: <string>
|
||||
Set the cipher, hash, and compression preference values for
|
||||
this key. This expects the same type of string as "setpref"
|
||||
in the --edit menu.
|
||||
Revoker: <algo>:<fpr> [sensitive]
|
||||
Add a designated revoker to the generated key. Algo is the
|
||||
public key algorithm of the designated revoker (i.e. RSA=1,
|
||||
DSA=17, etc.) Fpr is the fingerprint of the designated
|
||||
revoker. The optional "sensitive" flag marks the designated
|
||||
revoker as sensitive information. Only v4 keys may be
|
||||
designated revokers.
|
||||
|
||||
Here is an example:
|
||||
$ cat >foo <<EOF
|
||||
%echo Generating a standard key
|
||||
Key-Type: DSA
|
||||
Key-Length: 1024
|
||||
Subkey-Type: ELG-E
|
||||
Subkey-Length: 1024
|
||||
Name-Real: Joe Tester
|
||||
Name-Comment: with stupid passphrase
|
||||
Name-Email: joe@foo.bar
|
||||
Expire-Date: 0
|
||||
Passphrase: abc
|
||||
%pubring foo.pub
|
||||
%secring foo.sec
|
||||
# Do a commit here, so that we can later print "done" :-)
|
||||
%commit
|
||||
%echo done
|
||||
EOF
|
||||
$ gpg --batch --gen-key -a foo
|
||||
[...]
|
||||
$ gpg --no-default-keyring --secret-keyring foo.sec \
|
||||
--keyring foo.pub --list-secret-keys
|
||||
/home/wk/work/gnupg-stable/scratch/foo.sec
|
||||
------------------------------------------
|
||||
sec 1024D/915A878D 2000-03-09 Joe Tester (with stupid passphrase) <joe@foo.bar>
|
||||
ssb 1024g/8F70E2C0 2000-03-09
|
||||
|
||||
|
||||
|
||||
Layout of the TrustDB
|
||||
=====================
|
||||
|
@ -230,6 +532,8 @@ describes the record type. All numeric values are stored in network
|
|||
byte order. The length of each record is 40 bytes. The first record of
|
||||
the DB is always of type 1 and this is the only record of this type.
|
||||
|
||||
FIXME: The layout changed, document it here.
|
||||
|
||||
Record type 0:
|
||||
--------------
|
||||
Unused record, can be reused for any purpose.
|
||||
|
@ -259,7 +563,7 @@ the DB is always of type 1 and this is the only record of this type.
|
|||
1 u32 record number of shadow directory hash table
|
||||
It does not make sense to combine this table with the key table
|
||||
because the keyid is not in every case a part of the fingerprint.
|
||||
4 bytes reserved for version extension record
|
||||
1 u32 record number of the trusthashtbale
|
||||
|
||||
|
||||
Record type 2: (directory record)
|
||||
|
@ -316,7 +620,7 @@ the DB is always of type 1 and this is the only record of this type.
|
|||
|
||||
Record type 5: (pref record)
|
||||
--------------
|
||||
Informations about preferences
|
||||
This record type is not anymore used.
|
||||
|
||||
1 byte value 5
|
||||
1 byte reserved
|
||||
|
@ -339,16 +643,16 @@ the DB is always of type 1 and this is the only record of this type.
|
|||
1 u32 next next sigrec of this uid or 0 to indicate the
|
||||
last sigrec.
|
||||
6 times
|
||||
1 u32 Local_id of signators dir or shadow dir record
|
||||
1 u32 Local_id of signatures dir or shadow dir record
|
||||
1 byte Flag: Bit 0 = checked: Bit 1 is valid (we have a real
|
||||
directory record for this)
|
||||
1 = valid is set (but my be revoked)
|
||||
1 = valid is set (but may be revoked)
|
||||
|
||||
|
||||
|
||||
Record type 8: (shadow directory record)
|
||||
--------------
|
||||
This record is used to reserved a LID for a public key. We
|
||||
This record is used to reserve a LID for a public key. We
|
||||
need this to create the sig records of other keys, even if we
|
||||
do not yet have the public key of the signature.
|
||||
This record (the record number to be more precise) will be reused
|
||||
|
@ -477,7 +781,7 @@ There is one enhancement used with the old style packet headers:
|
|||
+ future extensions. These length markers must be inserted into the data
|
||||
+ stream just before writing the data out.
|
||||
+
|
||||
+ This 2 byte filed is large enough, because the application must buffer
|
||||
+ This 2 byte field is large enough, because the application must buffer
|
||||
+ this amount of data to prepend the length marker before writing it out.
|
||||
+ Data block sizes larger than about 32k doesn't make any sense. Note
|
||||
+ that this may also be used for compressed data streams, but we must use
|
||||
|
@ -485,10 +789,19 @@ There is one enhancement used with the old style packet headers:
|
|||
+ that this is the last packet.
|
||||
|
||||
|
||||
GNU extensions to the S2K algorithm
|
||||
===================================
|
||||
S2K mode 101 is used to identify these extensions.
|
||||
After the hash algorithm the 3 bytes "GNU" are used to make
|
||||
clear that these are extensions for GNU, the next bytes gives the
|
||||
GNU protection mode - 1000. Defined modes are:
|
||||
1001 - do not store the secret part at all
|
||||
|
||||
|
||||
Usage of gdbm files for keyrings
|
||||
================================
|
||||
The key to store the keyblock is it's fingerprint, other records
|
||||
are used for secondary keys. fingerprints are always 20 bytes
|
||||
The key to store the keyblock is its fingerprint, other records
|
||||
are used for secondary keys. Fingerprints are always 20 bytes
|
||||
where 16 bit fingerprints are appended with zero.
|
||||
The first byte of the key gives some information on the type of the
|
||||
key.
|
||||
|
@ -508,6 +821,41 @@ Usage of gdbm files for keyrings
|
|||
|
||||
|
||||
|
||||
Pipemode
|
||||
========
|
||||
This mode can be used to perform multiple operations with one call to
|
||||
gpg. It comes handy in cases where you have to verify a lot of
|
||||
signatures. Currently we support only detached signatures. This mode
|
||||
is a kludge to avoid running gpg n daemon mode and using Unix Domain
|
||||
Sockets to pass the data to it. There is no easy portable way to do
|
||||
this under Windows, so we use plain old pipes which do work well under
|
||||
Windows. Because there is no way to signal multiple EOFs in a pipe we
|
||||
have to embed control commands in the data stream: We distinguish
|
||||
between a data state and a control state. Initially the system is in
|
||||
data state but it won't accept any data. Instead it waits for
|
||||
transition to control state which is done by sending a single '@'
|
||||
character. While in control state the control command os expected and
|
||||
this command is just a single byte after which the system falls back
|
||||
to data state (but does not necesary accept data now). The simplest
|
||||
control command is a '@' which just inserts this character into the
|
||||
data stream.
|
||||
|
||||
Here is the format we use for detached signatures:
|
||||
"@<" - Begin of new stream
|
||||
"@B" - Detached signature follows.
|
||||
This emits a control packet (1,'B')
|
||||
<detached_signature>
|
||||
"@t" - Signed text follows.
|
||||
This emits the control packet (2, 'B')
|
||||
<signed_text>
|
||||
"@." - End of operation. The final control packet forces signature
|
||||
verification
|
||||
"@>" - End of stream
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Other Notes
|
||||
===========
|
||||
|
@ -596,11 +944,11 @@ The keyserver also recognizes http-POSTs to /pks/add. Use this to upload
|
|||
keys.
|
||||
|
||||
|
||||
A better way to to this would be a request like:
|
||||
A better way to do this would be a request like:
|
||||
|
||||
/pks/lookup/<gnupg_formatierte_user_id>?op=<operation>
|
||||
|
||||
this can be implemented using Hurd's translator mechanism.
|
||||
This can be implemented using Hurd's translator mechanism.
|
||||
However, I think the whole key server stuff has to be re-thought;
|
||||
I have some ideas and probably create a white paper.
|
||||
|
||||
|
|
352
doc/FAQ
352
doc/FAQ
|
@ -1,352 +0,0 @@
|
|||
GNU Privacy Guard -- Frequently Asked Questions
|
||||
=================================================
|
||||
|
||||
This FAQ is partly compiled from messages of the developers mailing list.
|
||||
|
||||
Many thanks to Kirk Fort, Brian Warner, ...
|
||||
|
||||
|
||||
Q: How does this whole thing work?
|
||||
A: To generate a secret/public keypair, run
|
||||
|
||||
gpg --gen-key
|
||||
|
||||
and choose the default values.
|
||||
|
||||
Data that is encrypted with a public key can only be decrypted by the
|
||||
matching secret key. The secret key is protected by a password, the
|
||||
public key is not.
|
||||
|
||||
So to send your friend a message, you would encrypt your message with his
|
||||
public key, and he would only be able to decrypt it by having the secret
|
||||
key and putting in the password to use his secret key.
|
||||
|
||||
GnuPG is also useful for signing things. Things that are encrypted with
|
||||
the secret key can be decrypted with the public key. To sign something, a
|
||||
hash is taken of the data, and then the hash is in some form encoded with
|
||||
the secret key. If someone has your public key, they can verify that it
|
||||
is from you and that it hasn't changed by checking the encoded form of
|
||||
the hash with the public key.
|
||||
|
||||
A keyring is just a large file that stores keys. You have a public keyring
|
||||
where you store yours and your friend's public keys. You have a secret
|
||||
keyring that you keep your secret key on, and be very careful with this
|
||||
secret keyring: Never ever give anyone else access to it and use a *good*
|
||||
passphrase to protect the data in it.
|
||||
|
||||
You can 'conventionally' encrypt something by using the option 'gpg -c'.
|
||||
It is encrypted using a passphrase, and does not use public and secret
|
||||
keys. If the person you send the data to knows that passphrase, they can
|
||||
decrypt it. This is usually most useful for encrypting things to
|
||||
yourself, although you can encrypt things to your own public key in the
|
||||
same way. It should be used for communication with partners you know and
|
||||
where it is easy to exchange the passphrases (e.g. with your boy friend or
|
||||
your wife). The advantage is that you can change the passphrase from time
|
||||
to time and decrease the risk, that many old messages may be decrypted by
|
||||
people who accidently got your passphrase.
|
||||
|
||||
You can add and copy keys to and from your keyring with the 'gpg --import'
|
||||
and 'gpg --export' option. 'gpg --export-secret-keys' will export secret
|
||||
keys. This is normally not useful, but you can generate the key on one
|
||||
machine then move it to another machine.
|
||||
|
||||
Keys can be signed under the 'gpg --edit-key' option. When you sign a
|
||||
key, you are saying that you are certain that the key belongs to the
|
||||
person it says it comes from. You should be very sure that is really
|
||||
that person: You should verify the key fingerprint
|
||||
|
||||
gpg --fingerprint user-id
|
||||
|
||||
over phone (if you really know the voice of the other person) or at
|
||||
a key signing party (which are often held at computer conferences)
|
||||
or at a meeting of your local GNU/Linux User Group.
|
||||
|
||||
Hmm, what else. You may use the option "-o filename" to force output
|
||||
to this filename (use "-" to force output to stdout). "-r" just lets you
|
||||
specify the recipient (which public key you encrypt with) on the command
|
||||
line instead of typing it interactively.
|
||||
|
||||
Oh yeah, this is important. By default all data is encrypted in some weird
|
||||
binary format. If you want to have things appear in ASCII text that is
|
||||
readable, just add the '-a' option. But the preferred method is to use
|
||||
a MIME aware mail reader (Mutt, Pine and many more).
|
||||
|
||||
There is a small security glitch in the OpenPGP (and therefore GnuPG) system;
|
||||
to avoid this you should always sign and encrypt a message instead of only
|
||||
encrypting it.
|
||||
|
||||
|
||||
Q: What is the recommended key size?
|
||||
A: 1024 bit for DSA signatures; even for plain ElGamal
|
||||
signatures this is sufficient as the size of the hash
|
||||
is probably the weakest link if the keysize is larger
|
||||
than 1024 bits. Encryption keys may have greater sizes,
|
||||
but you should than check the fingerprint of this key:
|
||||
"gpg --fingerprint --fingerprint <user ID>".
|
||||
|
||||
Q: Why are some signatures with an ELG-E key valid?
|
||||
A: These are ElGamal Key generated by GnuPG in v3 (rfc1991)
|
||||
packets. The OpenPGP draft later changed the algorithm
|
||||
identifier for ElGamal keys which are usable for signatures
|
||||
and encryption from 16 to 20. GnuPG now uses 20 when it
|
||||
generates new ElGamal keys but still accept 16 (which is
|
||||
according to OpenPGP "encryption only") if this key is in
|
||||
a v3 packet. GnuPG is the only program which had used
|
||||
these v3 ElGamal keys - so this assumption is quite safe.
|
||||
|
||||
Q: Why is PGP 5.x not able to encrypt messages with some keys?
|
||||
A: PGP Inc refuses to accept ElGamal keys of type 20 even for
|
||||
encryption. They only support type 16 (which is identical
|
||||
at least for decryption). To be more inter-operable, GnuPG
|
||||
(starting with version 0.3.3) now also uses type 16 for the
|
||||
ElGamal subkey which is created if the default key algorithm
|
||||
is chosen. You may add an type 16 ElGamal key to your public
|
||||
key which is easy as your key signatures are still valid.
|
||||
|
||||
Q: Why is PGP 5.x not able to verify my messages?
|
||||
A: PGP 5.x does not accept V4 signatures for data material but
|
||||
OpenPGP requires generation of V4 signatures for all kind of
|
||||
data. Use the option "--force-v3-sigs" to generate V3 signatures
|
||||
for data.
|
||||
|
||||
Q: I can't delete an user id because it is already deleted on my
|
||||
public keyring?
|
||||
A: Because you can only select from the public key ring, there is
|
||||
no direct way to do this. However it is not very complicated
|
||||
to do it anyway. Create a new user id with exactly the same name
|
||||
and you will see that there are now two identical user ids on the
|
||||
secret ring. Now select this user id and delete it. Both user
|
||||
ids will be removed from the secret ring.
|
||||
|
||||
Q: How can I encrypt a message so that pgp 2.x is able to decrypt it?
|
||||
A: You can't do that because pgp 2.x normally uses IDEA which is not
|
||||
supported by GnuPG because it is patented, but if you have a modified
|
||||
version of PGP you can try this:
|
||||
|
||||
gpg --rfc1991 --cipher-algo 3des ...
|
||||
|
||||
Please don't pipe the data to encrypt to gpg but give it as a filename;
|
||||
other wise, pgp 2 will not be able to handle it.
|
||||
|
||||
Q: How can I conventional encrypt a message, so that PGP can decrypt it?
|
||||
A: You can't do this for PGP 2. For PGP 5 you should use this:
|
||||
|
||||
gpg -c --cipher-algo 3des --compress-algo 1 myfile
|
||||
|
||||
You may replace "3des" by "cast5". "blowfish" does not work with
|
||||
all versions of pgp5. You may also want to put
|
||||
compress-algo 1
|
||||
into your ~/.gnupg/options file - this does not affect normal
|
||||
gnupg operation.
|
||||
|
||||
|
||||
Q: Why does it sometimes take so long to create keys?
|
||||
A: The problem here is that we need a lot of random bytes and for that
|
||||
we (on Linux the /dev/random device) must collect some random data.
|
||||
It is really not easy to fill the Linux internal entropy buffer; I
|
||||
talked to Ted Ts'o and he commented that the best way to fill the buffer
|
||||
is to play with your keyboard. Good security has it's price. What I do
|
||||
is to hit several times on the shift, control, alternate, and capslock
|
||||
keys, because these keys do not produce output to the screen. This way
|
||||
you get your keys really fast (it's the same thing pgp2 does).
|
||||
|
||||
Another problem might be another program which eats up your random bytes
|
||||
(a program (look at your daemons) that reads from /dev/[u]random).
|
||||
|
||||
Q: And it really takes long when I work on a remote system. Why?
|
||||
A: Don't do this at all! You should never create keys or even use GnuPG
|
||||
on a remote system because you normally have no physical control over
|
||||
your secret keyring (which is in most cases vulnerable to advanced
|
||||
dictionary attacks) - I strongly encourage everyone to only create keys
|
||||
on a local computer (a disconnected laptop is probably the best choice)
|
||||
and if you need it on your connected box (I know: We all do this) be
|
||||
sure to have a strong password for your account and for your secret key
|
||||
and that you can trust your system administrator.
|
||||
|
||||
When I check GnuPG on a remote system via ssh (I have no Alpha here ;-)
|
||||
I have the same problem. It takes a *very* long time to create the
|
||||
keys, so I use a special option, --quick-random, to generate insecure
|
||||
keys which are only good for some tests.
|
||||
|
||||
|
||||
Q: How does the whole trust thing work?
|
||||
A: It works more or less like PGP. The difference is that the trust is
|
||||
computed at the time it is needed. This is one of the reasons for the
|
||||
trustdb which holds a list of valid key signatures. If you are not
|
||||
running in batch mode you will be asked to assign a trust parameter
|
||||
(ownertrust) to a key.
|
||||
|
||||
You can see the validity (calculated trust value) using this command.
|
||||
|
||||
gpg --list-keys --with-colons
|
||||
|
||||
If the first field is "pub" or "uid", the second field shows you the trust:
|
||||
|
||||
o = Unknown (this key is new to the system)
|
||||
e = The key has expired
|
||||
q = Undefined (no value assigned)
|
||||
n = Don't trust this key at all
|
||||
m = There is marginal trust in this key
|
||||
f = The key is full trusted.
|
||||
u = The key is ultimately trusted; this
|
||||
is only used for keys for which
|
||||
the secret key is also available.
|
||||
r = The key has been revoked
|
||||
d = The key has been disabled
|
||||
|
||||
The value in the "pub" record is the best one of all "uid" records.
|
||||
|
||||
You can get a list of the assigned trust values (how much you trust
|
||||
the owner to correctly sign another person's key)
|
||||
|
||||
gpg --list-ownertrust
|
||||
|
||||
The first field is the fingerprint of the primary key, the second field
|
||||
is the assigned value:
|
||||
|
||||
- = No Ownertrust value yet assigned.
|
||||
n = Never trust this keyholder to correctly verify others signatures.
|
||||
m = Have marginal trust in the keyholders capability to sign other keys.
|
||||
f = Assume that the key holder really knows how to sign keys.
|
||||
u = No need to trust ourself because we have the secret key.
|
||||
|
||||
Keep these values confidential because they express your opinions
|
||||
about others. PGP stores this information with the keyring thus
|
||||
it is not a good idea to publish a PGP keyring instead of exporting the
|
||||
keyring. gnupg stores the trust in the trust-DB so it is okay
|
||||
to give a gpg keyring away (but we have a --export command too).
|
||||
|
||||
|
||||
Q: What is the difference between options and commands?
|
||||
A: If you do a "gpg --help", you will get two separate lists. The first is
|
||||
a list of commands. The second is a list of options. Whenever you run GPG,
|
||||
you *must* pick exactly one command (**with one exception, see below). You
|
||||
*may* pick one or more options. The command should, just by convention,
|
||||
come at the end of the argument list, after all the options. If the
|
||||
command takes a file (all the basic ones do), the filename comes at the
|
||||
very end. So the basic way to run gpg is:
|
||||
|
||||
gpg [--option something] [--option2] [--option3 something] --command file
|
||||
|
||||
Some options take arguments, for example the --output option (which can be
|
||||
abbreviated -o) is an option that takes a filename. The option's argument
|
||||
must follow immediately after the option itself, otherwise gpg doesn't know
|
||||
which option the argument is supposed to go with. As an option, --output and
|
||||
its filename must come before the command. The --recipient (-r) option takes
|
||||
a name or keyid to encrypt the message to, which must come right after the -r
|
||||
argument. The --encrypt (or -e) command comes after all the options followed
|
||||
by the file you wish to encrypt. So use
|
||||
|
||||
gpg -r alice -o secret.txt -e test.txt
|
||||
|
||||
If you write the options out in full, it is easier to read
|
||||
|
||||
gpg --recipient alice --output secret.txt --encrypt test.txt
|
||||
|
||||
If you're saving it in a file called ".txt" then you'd probably expect to see
|
||||
ASCII-armored text in there, so you need to add the --armor (-a) option,
|
||||
which doesn't take any arguments.
|
||||
|
||||
gpg --armor --recipient alice --output secret.txt --encrypt test.txt
|
||||
|
||||
If you imagine square brackets around the optional parts, it becomes a bit
|
||||
clearer:
|
||||
|
||||
gpg [--armor] [--recipient alice] [--output secret.txt] --encrypt test.txt
|
||||
|
||||
The optional parts can be rearranged any way you want.
|
||||
|
||||
gpg --output secret.txt --recipient alice --armor --encrypt test.txt
|
||||
|
||||
If your filename begins with a hyphen (e.g. "-a.txt"), gnupg assumes this is
|
||||
an option and may complain. To avoid this you have either to use
|
||||
"./-a.txt" or stop the option and command processing with two hyphens:
|
||||
"-- -a.txt".
|
||||
|
||||
** the exception: signing and encrypting at the same time. Use
|
||||
|
||||
gpg [--options] --sign --encrypt foo.txt
|
||||
|
||||
|
||||
Q: What kind of output is this: "key C26EE891.298, uid 09FB: ...."?
|
||||
A: This is the internal representation of an user id in the trustdb.
|
||||
"C26EE891" is the keyid, "298" is the local id (a record number
|
||||
in the trustdb) and "09FB" is the last two bytes of a ripe-md-160
|
||||
hash of the user id for this key.
|
||||
|
||||
|
||||
Q: What is trust, validity and ownertrust?
|
||||
A: "ownertrust" is used instead of "trust" to make clear that
|
||||
this is the value you have assigned to a key to express how much you
|
||||
trust the owner of this key to correctly sign (and so introduce)
|
||||
other keys. "validity", or calculated trust, is a value which
|
||||
says how much GnuPG thinks a key is valid (that it really belongs
|
||||
to the one who claims to be the owner of the key).
|
||||
For more see the chapter "The Web of Trust" in the Manual
|
||||
|
||||
Q: How do I interpret some of the informational outputs?
|
||||
A: While checking the validity of a key, GnuPG sometimes prints
|
||||
some information which is prefixed with information about
|
||||
the checked item.
|
||||
"key 12345678.3456"
|
||||
This is about the key with key ID 12345678 and the internal
|
||||
number 3456, which is the record number of the so called
|
||||
directory record in the trustdb.
|
||||
"uid 12345678.3456/ACDE"
|
||||
This is about the user ID for the same key. To identify the
|
||||
user ID the last two bytes of a ripe-md-160 over the user ID
|
||||
ring is printed.
|
||||
"sig 12345678.3456/ACDE/9A8B7C6D"
|
||||
This is about the signature with key ID 9A8B7C6D for the
|
||||
above key and user ID, if it is a signature which is direct
|
||||
on a key, the user ID part is empty (..//..).
|
||||
|
||||
|
||||
Q: How do I sign a patch file?
|
||||
A: Use "gpg --clearsign --not-dash-escaped ...".
|
||||
The problem with --clearsign is that all lines starting with a dash are
|
||||
quoted with "- "; obviously diff produces many of lines starting with a
|
||||
dash and these are then quoted and that is not good for patch ;-). To
|
||||
use a patch file without removing the cleartext signature, the special
|
||||
option --not-dash-escaped may be used to suppress generation of these
|
||||
escape sequences. You should not mail such a patch because spaces and
|
||||
line endings are also subject to the signature and a mailer may not
|
||||
preserve these. If you want to mail a file you can simply sign it
|
||||
using your MUA.
|
||||
|
||||
|
||||
Q: Where is the "encrypt-to-self" option?
|
||||
A: Use "--encrypt-to your_keyid". You can use more than one
|
||||
of these options. To temporary override the use of this additional
|
||||
keys, you can use the option "--no-encrypt-to".
|
||||
|
||||
|
||||
Q: How can I get rid of the Version and Comment headers in
|
||||
armored messages?
|
||||
A: Use "--no-version --comment ''". Note that the left over blank line
|
||||
is required by the protocol.
|
||||
|
||||
|
||||
Q: What does the "You are using the xxxx character set." mean?
|
||||
A: This note is printed when UTF8 mapping has to be done. Make sure that
|
||||
the displayed charset is the one you have activated on your system
|
||||
"iso-8859-1" is the most used one, so this is the default. You can
|
||||
change the charset with the option "--charset". It is important that
|
||||
you active character set matches the one displayed - if not, restrict
|
||||
yourself to plain 7 bit ASCII and no mapping has to be done.
|
||||
|
||||
Q: How do I transfer owner trust values from PGP to GnuPG?
|
||||
A: There is a script in the tools directory to help you:
|
||||
After you have imported the PGP keyring you can give this command:
|
||||
$ lspgpot pgpkeyring | gpg --import-ownertrust
|
||||
where pgpkeyring is the original keyring and not the GnuPG one you
|
||||
might have created in the first step.
|
||||
|
||||
Q: Are the headerlines of a cleartext signater part of the signed
|
||||
material?
|
||||
A: No. For example you can add or remove "Comment:" lines. They
|
||||
have a purpose like the mail header lines. However a "Hash:"
|
||||
line is needed for modern signatures, to tell the parser which
|
||||
hash algorithm to use.
|
||||
|
||||
|
75
doc/HACKING
75
doc/HACKING
|
@ -10,12 +10,13 @@ CVS Access
|
|||
==========
|
||||
Anonymous read-only CVS access is available:
|
||||
|
||||
cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs login
|
||||
cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg login
|
||||
|
||||
use the password "anonymous". To check out the the complete
|
||||
use the password "anoncvs". To check out the the complete
|
||||
archive use:
|
||||
|
||||
cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs checkout gnupg
|
||||
cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg \
|
||||
checkout -R STABLE-BRANCH-1-0 gnupg
|
||||
|
||||
This service is provided to help you in hunting bugs and not to deliver
|
||||
stable snapshots; it may happen that it even does not compile, so please
|
||||
|
@ -112,6 +113,74 @@ Directory Layout
|
|||
./gcrypt Stuff needed to build libgcrypt (under construction)
|
||||
|
||||
|
||||
Detailed Roadmap
|
||||
----------------
|
||||
g10/g10.c Main module with option parsing and all the stuff you have
|
||||
to do on startup. Also has the exout handler and some
|
||||
helper functions.
|
||||
g10/sign.c Create signature and optionally encrypt
|
||||
|
||||
g10/parse-packet.c
|
||||
g10/build-packet.c
|
||||
g10/free-packet.c
|
||||
Parsing and creating of OpenPGP message packets.
|
||||
|
||||
g10/getkey.c Key selection code
|
||||
g10/pkclist.c Build a list of public keys
|
||||
g10/skclist.c Build a list of secret keys
|
||||
g10/ringedit.c Keyring I/O
|
||||
g10/keydb.h
|
||||
|
||||
g10/keyid.c Helper functions to get the keyid, fingerprint etc.
|
||||
|
||||
|
||||
g10/trustdb.c
|
||||
g10/trustdb.h
|
||||
g10/tdbdump.c
|
||||
Management of the trustdb.gpg
|
||||
|
||||
g10/compress.c Filter to handle compression
|
||||
g10/filter.h Declarations for all filter functions
|
||||
g10/delkey.c Delete a key
|
||||
g10/kbnode.c Helper for the KBNODE linked list
|
||||
g10/main.h Prototypes and some constants
|
||||
g10/mainproc.c Message processing
|
||||
g10/armor.c Ascii armor filter
|
||||
g10/mdfilter.c Filter to calculate hashs
|
||||
g10/textfilter.c Filter to handle CR/LF and trailing white space
|
||||
g10/cipher.c En-/Decryption filter
|
||||
g10/misc.c Utlity functions
|
||||
g10/options.h Structure with all the command line options
|
||||
and related constants
|
||||
g10/openfile.c Create/Open Files
|
||||
g10/tdbio.c I/O handling for the trustdb.gpg
|
||||
g10/tdbio.h
|
||||
g10/hkp.h Keyserver access
|
||||
g10/hkp.c
|
||||
g10/packet.h Defintion of OpenPGP structures.
|
||||
g10/passphrase.c Passphrase handling code
|
||||
g10/pubkey-enc.c
|
||||
g10/seckey-cert.c
|
||||
g10/seskey.c
|
||||
g10/import.c
|
||||
g10/export.c
|
||||
g10/comment.c
|
||||
g10/status.c
|
||||
g10/status.h
|
||||
g10/sign.c
|
||||
g10/plaintext.c
|
||||
g10/encr-data.c
|
||||
g10/encode.c
|
||||
g10/revoke.c
|
||||
g10/keylist.c
|
||||
g10/sig-check.c
|
||||
g10/signal.c
|
||||
g10/helptext.c
|
||||
g10/verify.c
|
||||
g10/decrypt.c
|
||||
g10/keyedit.c
|
||||
g10/dearmor.c
|
||||
g10/keygen.c
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,42 +1,77 @@
|
|||
# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG 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.
|
||||
#
|
||||
# GnuPG 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; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
## Process this file with automake to create Makefile.in
|
||||
|
||||
BUILT_SOURCES = version.sgml
|
||||
AUTOMAKE_OPTIONS = no-texinfo.tex
|
||||
|
||||
EXTRA_DIST = DETAILS gpg.sgml gpg.1 gpgv.sgml gpgv.1 faq.raw FAQ faq.html \
|
||||
HACKING OpenPGP README.W32 samplekeys.asc
|
||||
|
||||
man_MANS = gpg.1 gpgv.1
|
||||
|
||||
info_TEXINFOS = gpg.texi gpgv.texi
|
||||
|
||||
# Need this to avoid building of dvis with automake 1.4
|
||||
DVIS =
|
||||
|
||||
pkgdata_DATA = FAQ faq.html
|
||||
|
||||
BUILT_SOURCES = FAQ faq.html
|
||||
# we can't add gpg.texi gpgv.texi here because automake does not like them to
|
||||
# be built files.
|
||||
|
||||
CLEANFILES = faq.raw.xref gpg.xml gpgv.xml
|
||||
|
||||
|
||||
#EXTRA_DIST = DETAILS gpg.sgml gpg.1 FAQ HACKING OpenPGP \
|
||||
# version.sgml.in $(BUILT_SOURCES)
|
||||
EXTRA_DIST = DETAILS HACKING OpenPGP FAQ
|
||||
%.texi : %.xml
|
||||
if HAVE_DOCBOOK_TO_TEXI
|
||||
docbook2texi $< | sed 's,--,---,' >$@
|
||||
else
|
||||
: Warning: missing docbook to texinfo tools, cannot make $@
|
||||
touch $@
|
||||
endif
|
||||
|
||||
#man_MANS = gpg.1
|
||||
|
||||
### pkgdata_DATA = gcryptref.html gcryptref.ps
|
||||
%.xml : %.sgml
|
||||
if HAVE_DOCBOOK_TO_TEXI
|
||||
sgml2xml -x lower $< >$@
|
||||
else
|
||||
: Warning: missing docbook to texinfo tools, cannot make $@
|
||||
touch $@
|
||||
endif
|
||||
|
||||
|
||||
# gcryptref.sgml : version.sgml
|
||||
|
||||
|
||||
if HAVE_DB2MAN
|
||||
%.1 : %.sgml
|
||||
$(DB2MAN) $< >$@
|
||||
endif
|
||||
|
||||
if HAVE_DB2TEX
|
||||
%.ps : %.dvi
|
||||
dvips -o $@ $<
|
||||
|
||||
%.tex : %.sgml
|
||||
$(DB2TEX) -V generate-book-toc $< > $@
|
||||
|
||||
%.dvi : %.tex
|
||||
$(JADETEX) $<
|
||||
endif
|
||||
|
||||
if HAVE_DB2HTML
|
||||
%.html : %.sgml
|
||||
$(DB2HTML) --nosplit $<
|
||||
if HAVE_DOCBOOK_TO_MAN
|
||||
docbook-to-man $< >$@
|
||||
else
|
||||
: Warning: missing docbook-to-man, cannot make $@
|
||||
echo ".TH $< 1" >$@
|
||||
echo "No man page due to missing docbook-to-man" >>$@
|
||||
endif
|
||||
|
||||
|
||||
FAQ : faq.raw
|
||||
$(FAQPROG) -f $< $@ || $(FAQPROG) -f $< $@
|
||||
|
||||
faq.html : faq.raw
|
||||
$(FAQPROG) -h -f $< $@ 2>&1 || $(FAQPROG) -h -f $< $@
|
||||
|
||||
|
||||
dist-hook:
|
||||
@if test "`wc -c < gpg.1`" -lt 200; then \
|
||||
echo 'ERROR: dummy man page'; false; fi
|
||||
|
|
17
doc/OpenPGP
17
doc/OpenPGP
|
@ -8,11 +8,7 @@
|
|||
|
||||
Compatibility Notes
|
||||
===================
|
||||
GnuPG (>0.4.5) is in compliance with RFC2440 despite these exceptions:
|
||||
|
||||
* (9.1) states that RSA SHOULD be implemented. This is not done
|
||||
(except with an extension, usable outside the U.S.) due to
|
||||
patent problems.
|
||||
GnuPG (>=1.0.3) is in compliance with RFC2440 despite these exceptions:
|
||||
|
||||
* (9.2) states that IDEA SHOULD be implemented. This is not done
|
||||
due to patent problems.
|
||||
|
@ -21,7 +17,7 @@
|
|||
All MAY features are implemented with this exception:
|
||||
|
||||
* multi-part armored messages are not supported.
|
||||
MIME should be used instead.
|
||||
MIME (rfc2015) should be used instead.
|
||||
|
||||
Most of the OPTIONAL stuff is implemented.
|
||||
|
||||
|
@ -33,6 +29,15 @@
|
|||
which can be considered to be in compliance with RFC1991; this
|
||||
format is only created if a special option is active.
|
||||
|
||||
GnuPG uses a S2K mode of 101 for GNU extensions to the secret key
|
||||
protection algorithms. This number is not defined in OpenPGP, but
|
||||
given the fact that this number is in a range which used at many
|
||||
other places in OpenPGP for private/experimenat algorithm identifiers,
|
||||
this should be not a so bad choice. The 3 bytes "GNU" are used
|
||||
to identify this as a GNU extension - see the file DETAILS for a
|
||||
definition of the used data formats.
|
||||
|
||||
|
||||
|
||||
Some Notes on OpenPGP / PGP Compatibility:
|
||||
==========================================
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
This is a binary version of GnuPG for MS-Windows 95, 98, WNT and W2000.
|
||||
|
||||
A FAQ comes with this package and a probably more recent one can be
|
||||
found online at http://www.gnupg.org/faq.html. See
|
||||
http://www.gnupg.org/docs-mls.html for a list of mailing lists. In
|
||||
particular the list gnupg-users@gnupg.org might be useful to answer
|
||||
questions - but please read the FAQ first.
|
||||
|
||||
Installation instructions:
|
||||
--------------------------
|
||||
1. Unpack the ZIP archive (alright, you already did this).
|
||||
2. Copy "gpg.exe" to some place where you usually store your
|
||||
binaries.
|
||||
3. Create a directory "c:\gnupg" (or any other as you like)
|
||||
4. If you did not use the default directory "c:\gnupg", you
|
||||
should enter a string with the directory into the Registry
|
||||
under the key:
|
||||
\\HKEY_CURRENT_USER\Software\GNU\GnuPG\HomeDir
|
||||
Please use forward slashes and not the backslashes when
|
||||
setting filenames for GnuPG into the Registry.
|
||||
5. Enter "gpg" and see what happens
|
||||
6. Read the file README and the online HOWTOs
|
||||
|
||||
|
||||
Internationalization support:
|
||||
-----------------------------
|
||||
1. Decide where to store the translation files for your language.
|
||||
Here we assume the directory "c:/gnu/locale/fr"
|
||||
2. Set the directory with the translations into the Registry under the key:
|
||||
\\HKEY_CURRENT_USER\Control Panel\Mingw32\NLS\MODir
|
||||
(Example entry: "c:/gnu/locale/fr")
|
||||
3. Select which language to use and copy the currect translation file
|
||||
under the name "gnupg.mo" into the directory set in step 2
|
||||
(Example: "copy fr.mo c:\gnu\locale\fr\gnupg.mo")
|
||||
4. Done.
|
||||
|
||||
Currently we only support the Codepages 437, 850 und Latin1. If you have
|
||||
problems, either delete the gnupg.mo file or don't set the environment
|
||||
variable
|
||||
|
||||
|
||||
|
||||
How to build it from the source:
|
||||
--------------------------------
|
||||
This version has been build with the Mingw32/CPD kit using the latest
|
||||
stable version of GnuPG.
|
||||
|
||||
First get the source: It has to be available at the same location you
|
||||
found this binary package - if not you should have received a written
|
||||
offer to get the source delivered to you See the file COPYING (section
|
||||
3) for details.
|
||||
|
||||
If you got this package from its canonical place (ftp.gnupg.org), the
|
||||
source is available at:
|
||||
|
||||
ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-1.0.n.tar.gz
|
||||
|
||||
or for snapshots (with a letter appended to the version number)
|
||||
|
||||
ftp://ftp.gnupg.org/gcrypt/devel/gnupg-1.0.nx.tar.gz
|
||||
|
||||
this is the same source as for the Unix version. If your binary
|
||||
version of GnuPG is called something like gnupg-w32-1.0.4-1.zip, you
|
||||
should find a patch file named gnupg-w32-1.0.4-1.0.4-1.diff.gz at the
|
||||
same location, which has to be applied to the stock gpg source file.
|
||||
Instructions are at the top of this file.
|
||||
|
||||
To build it, you need the MingW32/CPD kit, which is available at
|
||||
|
||||
ftp://ftp.gnupg.org/people/werner/cpd/mingw32-cpd-0.3.0.tar.gz
|
||||
ftp://ftp.gnupg.org/people/werner/cpd/gcc-core-2.95.2.tar.gz
|
||||
ftp://ftp.gnupg.org/people/werner/cpd/binutils-2.9.1.tar.gz
|
||||
|
||||
gcc and binutils are stock GNU source which are available
|
||||
at every GNU mirror.
|
||||
|
||||
After you have installed this environment you should be able to do this:
|
||||
|
||||
$ scripts/autogen.sh --build-w32
|
||||
$ make
|
||||
$ mingw32 strip g10/gpg.exe
|
||||
$ cp g10/gpg.exe /some_windows_drive/
|
||||
|
||||
And everything hopefully works.
|
||||
|
||||
|
||||
Don't forget that MS-Windows ist just a temporary workaround until
|
||||
you can switch to a GNU system ;-)
|
||||
|
||||
Be the source always with you.
|
||||
|
||||
Werner
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,932 @@
|
|||
[$htmltitle=GnuPG FAQ]
|
||||
[$sfaqheader=The GnuPG FAQ says:]
|
||||
[$sfaqfooter=
|
||||
The most recent version of the FAQ is available from
|
||||
<http://www.gnupg.org/>
|
||||
]
|
||||
[$usenetheader=
|
||||
]
|
||||
[$maintainer=Douglas Calvert, <faq 'at' gnupg.org> ]
|
||||
[$hGPG=http://www.gnupg.org]
|
||||
|
||||
[H body bgcolor=#ffffff text=#000000 link=#1f00ff alink=#ff0000 vlink=#9900dd]
|
||||
[H H1]GNUPG FREQUENTLY ASKED QUESTIONS[H /H1]
|
||||
|
||||
|
||||
Version: 1.5.6[H p]
|
||||
Last-Modified: Sep 14, 2001[H p]
|
||||
Maintained-by: [$maintainer]
|
||||
|
||||
|
||||
This is the GnuPG FAQ. The latest HTML version is available
|
||||
[H a href=[$hGPG]/faq.html] here[H/a].
|
||||
|
||||
The index is generated automatically, so there may be errors here. Not
|
||||
all questions may be in the section they belong to. Suggestions about
|
||||
how to improve the structure of this FAQ are welcome.
|
||||
|
||||
Please send additions and corrections to the maintainer. It would be
|
||||
most convenient if you could provide the answer to be included
|
||||
here. Your help is very much appreciated.
|
||||
|
||||
Please, don't send message like "This should be a FAQ - what's the
|
||||
answer?". If it hasn't been asked before, it isn't a FAQ. In that case
|
||||
you could search in the mailing list archive.
|
||||
|
||||
|
||||
[H HR]
|
||||
|
||||
<C>
|
||||
|
||||
[H HR]
|
||||
|
||||
<S> GENERAL
|
||||
|
||||
<Q> What is GnuPG?
|
||||
|
||||
[H a href=[$hGPG]]GnuPG[H /a] stands for GNU Privacy Guard and
|
||||
is GNU's tool for secure communication and data storage.
|
||||
It can be used to encrypt data and to create digital signatures.
|
||||
It includes an advanced key management facility and is compliant
|
||||
with the proposed OpenPGP Internet standard as described in
|
||||
[H a href=http://www.gnupg.org/rfc2440.html]RFC 2440[H/a]. As
|
||||
such, it is aimed to be compatible with PGP from NAI Inc.
|
||||
|
||||
<Q> Is GnuPG compatible with PGP?
|
||||
|
||||
In general, yes. GnuPG and newer PGP releases should be implementing
|
||||
the OpenPGP standard. But there are some interoperability
|
||||
problems. See questions <Rcompat>ff. for details.
|
||||
|
||||
<S> SOURCES of INFORMATION
|
||||
|
||||
<Q> Where can I find more information?
|
||||
|
||||
Here's a list of on-line resources: [H UL]
|
||||
|
||||
[H LI] [H a href=[$hGPG]/docs.html]<[$hGPG]/docs.html>[H/a] is the
|
||||
documentation page. Have a look at the HOWTOs and the GNU Privacy
|
||||
Handbook (GPH, available in English, Spanish and Russian). The
|
||||
latter provides a detailed user's guide to GnuPG. You'll also find a
|
||||
document about how to convert from PGP 2.x to GnuPG.
|
||||
|
||||
[H LI] On [H a href=http://lists.gnupg.org]<http://lists.gnupg.org>[H/a]
|
||||
you'll find an online archive of the GnuPG mailing lists. Most
|
||||
interesting should be gnupg-users for all user-related issues and
|
||||
gnupg-devel if you want to get in touch with the developers.
|
||||
|
||||
In addition, searchable archives can be found on MARC, e.g.:
|
||||
GnuPG-users: [H a href=http://marc.theaimsgroup.com/?l=gnupg-users&r=1&w=2]<http://marc.theaimsgroup.com/?l=gnupg-users&r=1&w=2>[H/a],
|
||||
GnuPG-devel: [H a href=http://marc.theaimsgroup.com/?l=gnupg-devel&r=1&w=2]<http://marc.theaimsgroup.com/?l=gnupg-devel&r=1&w=2>[H/a].
|
||||
|
||||
[H B]PLEASE:[H/B]
|
||||
Before posting to a list, read this FAQ and the available
|
||||
documentation. In addition, search the list archive - maybe your
|
||||
question has already been discussed. This way you help people focus
|
||||
on topics that have not yet been resolved.
|
||||
|
||||
[H LI] The GnuPG source distribution contains a subdirectory
|
||||
[H PRE]./doc[H /PRE] where some additional documentation is located
|
||||
(mainly interesting for hackers, not the casual user).
|
||||
[H /UL]
|
||||
|
||||
<Q> Where do I get GnuPG?
|
||||
|
||||
You can download the GNU Privacy Guard from its primary FTP server
|
||||
[H a href=ftp://ftp.gnupg.org/pub/gcrypt]ftp.gnupg.org[H /a] or from
|
||||
one of the mirrors: [H a href=[$hGPG]/mirrors.html]<[$hGPG]/mirror.html>[H /a]
|
||||
The current version is 1.0.4, please upgrade to this version as it
|
||||
fixes a security bug regarding the verification of multiple signatures.
|
||||
|
||||
|
||||
<S> INSTALLATION
|
||||
|
||||
<Q> Which OSes does GnuPG run on?
|
||||
|
||||
It should run on most Unices as well as Windows 95 and Windows NT. A
|
||||
list of OSes reported to be OK is presented at
|
||||
[H a href=http://www.gnupg.org/backend.html#supsys]
|
||||
http://www.gnupg.org/gnupg.html#supsys [H /a].
|
||||
|
||||
<Q> Which random gatherer should I use?
|
||||
|
||||
"Good" random numbers are crucial for the security of your
|
||||
encryption. Different operating systems provide a variety of more or
|
||||
less quality random data. Linux and *BSD provide kernel generated
|
||||
random data through /dev/random - this should be the preferred
|
||||
choice on these systems. Also Solaris users with the SUNWski package
|
||||
installed have a /dev/random. In these cases, use the configure
|
||||
option [H pre]--enable-static-rnd=linux[H/pre]. In addition, there's
|
||||
also the kernel random device by Andi Maier [H a href= http://www.cosy.sbg.ac.at/~andi]
|
||||
<http://www.cosy.sbg.ac.at/~andi>[H /a], but it's still beta. Use at
|
||||
own risk!
|
||||
|
||||
On other systems, the Entropy Gathering Daemon (EGD) is a good
|
||||
choice. It is a perl-daemon that monitors system activity and hashes
|
||||
it into random data. See the download page [H a href=http://www.gnupg.org/download.html]<http://www.gnupg.org/download.html>[H /a]
|
||||
how to obtain egd. Use [H pre]--enable-static-rnd=egd[H/pre] here.
|
||||
|
||||
If the above options do not work, you can use the random number
|
||||
generator "unix". This is [H B]very[H /B] slow and should be
|
||||
avoided. The random quality isn't very good so don't use it on
|
||||
sensitive data.
|
||||
|
||||
<Didea>
|
||||
<Q> How do I include support for RSA and IDEA?
|
||||
|
||||
RSA is included as of GnuPG 1.0.3.
|
||||
|
||||
The official GnuPG distribution does not contain IDEA due to a
|
||||
patent restriction. The patent does not expire before 2007 so don't
|
||||
expect official support before then.
|
||||
|
||||
However, there is an unofficial module to include it even
|
||||
in earlier version of GnuPG. It's available from [H a href=ftp://ftp.gnupg.org/pub/gcrypt/contrib/]
|
||||
<ftp://ftp.gnupg.org/pub/gcrypt/contrib/>[H /a]. Look for [H pre]idea.c[H /pre].
|
||||
|
||||
Compilation directives are in the headers of these files. Then add
|
||||
the following line to your ~/.gnupg/options:
|
||||
[H pre]
|
||||
load-extension idea
|
||||
[H /pre]
|
||||
|
||||
|
||||
<S> USAGE
|
||||
|
||||
<Q> What is the recommended key size?
|
||||
|
||||
1024 bit for DSA signatures; even for plain ElGamal
|
||||
signatures this is sufficient as the size of the hash
|
||||
is probably the weakest link if the key size is larger
|
||||
than 1024 bits. Encryption keys may have greater sizes,
|
||||
but you should then check the fingerprint of this key:
|
||||
"gpg --fingerprint <user ID>".
|
||||
|
||||
As for the key algorithms, you should stick with the default (i.e.,
|
||||
DSA signature and ElGamal encryption). A ElGamal signing key has the
|
||||
following disadvantages: the signature is larger, it is hard to
|
||||
create such a key useful for signatures which can withstand some
|
||||
real world attacks, you don't get any extra security compared to
|
||||
DSA, there might be compatibility problems with certain PGP
|
||||
versions. It has only been introduced because at the time it was
|
||||
not clear whether there was a patent on DSA.
|
||||
|
||||
<Q> Why does it sometimes take so long to create keys?
|
||||
|
||||
The problem here is that we need a lot of random bytes and for that
|
||||
we (on Linux the /dev/random device) must collect some random data.
|
||||
It is really not easy to fill the Linux internal entropy buffer; I
|
||||
talked to Ted Ts'o and he commented that the best way to fill the
|
||||
buffer is to play with your keyboard. Good security has its price.
|
||||
What I do is to hit several times on the shift, control, alternate,
|
||||
and caps lock keys, because these keys do not produce output to the
|
||||
screen. This way you get your keys really fast (it's the same thing
|
||||
PGP2 does).
|
||||
|
||||
Another problem might be another program which eats up your random
|
||||
bytes (a program (look at your daemons) that reads from
|
||||
/dev/[u]random).
|
||||
|
||||
<Q> And it really takes long when I work on a remote system. Why?
|
||||
|
||||
Don't do this at all! You should never create keys or even use GnuPG
|
||||
on a remote system because you normally have no physical control
|
||||
over your secret key ring (which is in most cases vulnerable to
|
||||
advanced dictionary attacks) - I strongly encourage everyone to only
|
||||
create keys on a local computer (a disconnected laptop is probably
|
||||
the best choice) and if you need it on your connected box (I know:
|
||||
We all do this) be sure to have a strong password for your account
|
||||
and for your secret key and that you can trust your system
|
||||
administrator.
|
||||
|
||||
When I check GnuPG on a remote system via ssh (I have no Alpha here
|
||||
;-) I have the same problem. It takes a *very* long time to create
|
||||
the keys, so I use a special option, --quick-random, to generate
|
||||
insecure keys which are only good for some tests.
|
||||
|
||||
<Q> What is the difference between options and commands?
|
||||
|
||||
If you do a 'gpg --help', you will get two separate lists. The first
|
||||
is a list of commands. The second is a list of options. Whenever you
|
||||
run GPG, you [H B]must[H /B] pick exactly one command (with one
|
||||
exception, see below). You [H B]may[H /B] pick one or more options.
|
||||
The command should, just by convention, come at the end of the
|
||||
argument list, after all the options. If the command takes a file
|
||||
(all the basic ones do), the filename comes at the very end. So the
|
||||
basic way to run gpg is:
|
||||
|
||||
[H pre]
|
||||
gpg [--option something] [--option2] [--option3 something] --command file
|
||||
[H/pre]
|
||||
|
||||
Some options take arguments, for example the --output option (which
|
||||
can be abbreviated -o) is an option that takes a filename. The
|
||||
option's argument must follow immediately after the option itself,
|
||||
otherwise gpg doesn't know which option the argument is supposed to
|
||||
go with. As an option, --output and its filename must come before
|
||||
the command. The --recipient (-r) option takes a name or keyid to
|
||||
encrypt the message to, which must come right after the -r argument.
|
||||
The --encrypt (or -e) command comes after all the options followed
|
||||
by the file you wish to encrypt. So use
|
||||
|
||||
[H pre]
|
||||
gpg -r alice -o secret.txt -e test.txt
|
||||
[H/pre]
|
||||
|
||||
If you write the options out in full, it is easier to read
|
||||
|
||||
[H pre]
|
||||
gpg --recipient alice --output secret.txt --encrypt test.txt
|
||||
[H/pre]
|
||||
|
||||
If you're saving it in a file called ".txt" then you'd probably
|
||||
expect to see ASCII-armored text in there, so you need to add the
|
||||
--armor (-a) option, which doesn't take any arguments.
|
||||
|
||||
[H pre]
|
||||
gpg --armor --recipient alice --output secret.txt --encrypt test.txt
|
||||
[H/pre]
|
||||
|
||||
If you imagine square brackets around the optional parts, it becomes
|
||||
a bit clearer:
|
||||
|
||||
[H pre]
|
||||
gpg [--armor] [--recipient alice] [--output secret.txt] --encrypt test.txt
|
||||
[H/pre]
|
||||
|
||||
The optional parts can be rearranged any way you want.
|
||||
|
||||
[H pre]
|
||||
gpg --output secret.txt --recipient alice --armor --encrypt test.txt
|
||||
[H/pre]
|
||||
|
||||
If your filename begins with a hyphen (e.g. "-a.txt"), gnupg assumes
|
||||
this is an option and may complain. To avoid this you have either
|
||||
to use "./-a.txt" or stop the option and command processing with two
|
||||
hyphens: "-- -a.txt".
|
||||
|
||||
[H B]The exception:[H /B] signing and encrypting at the same time. Use
|
||||
[H pre] gpg [--options] --sign --encrypt foo.txt [H/pre]
|
||||
|
||||
|
||||
<Q> I can't delete a user id because it is already deleted on my public
|
||||
keyring?
|
||||
|
||||
Because you can only select from the public key ring, there is no
|
||||
direct way to do this. However it is not very complicated to do it
|
||||
anyway. Create a new user id with exactly the same name and you
|
||||
will see that there are now two identical user ids on the secret
|
||||
ring. Now select this user id and delete it. Both user ids will be
|
||||
removed from the secret ring.
|
||||
|
||||
<Q> I can't delete the secret key because my public key disappeared?
|
||||
|
||||
To select a key a search is always done on the public keyring,
|
||||
therefore it is not possible to select an secret key without
|
||||
having the public key. Normally it shoud never happen that the
|
||||
public key got lost but the secret key is still available. The
|
||||
reality is different, so we GnuPG implements a special way to do
|
||||
deal with it: Simply use the long keyid which you can figure out
|
||||
by using the --with-colons options (it is the fifth field in the
|
||||
lines beginning with "sec").
|
||||
|
||||
<Q> What are trust, validity and ownertrust?
|
||||
|
||||
"ownertrust" is used instead of "trust" to make clear that this is
|
||||
the value you have assigned to a key to express how much you trust
|
||||
the owner of this key to correctly sign (and so introduce) other
|
||||
keys. "validity", or calculated trust, is a value which says how
|
||||
much GnuPG thinks a key is valid (that it really belongs to the one
|
||||
who claims to be the owner of the key). For more see the chapter
|
||||
"The Web of Trust" in the Manual.
|
||||
|
||||
<Q> How do I sign a patch file?
|
||||
|
||||
Use "gpg --clearsign --not-dash-escaped ...". The problem with
|
||||
--clearsign is that all lines starting with a dash are quoted with
|
||||
"- "; obviously diff produces many of lines starting with a dash and
|
||||
these are then quoted and that is not good for patch ;-). To use a
|
||||
patch file without removing the cleartext signature, the special
|
||||
option --not-dash-escaped may be used to suppress generation of
|
||||
these escape sequences. You should not mail such a patch because
|
||||
spaces and line endings are also subject to the signature and a
|
||||
mailer may not preserve these. If you want to mail a file you can
|
||||
simply sign it using your MUA.
|
||||
|
||||
<Q> Where is the "encrypt-to-self" option?
|
||||
|
||||
Use "--encrypt-to your_keyid". You can use more than one of these
|
||||
options. To temporary override the use of this additional keys, you
|
||||
can use the option "--no-encrypt-to".
|
||||
|
||||
<Q> How can I get rid of the Version and Comment headers in armored
|
||||
messages?
|
||||
|
||||
Use "--no-version --comment ''". Note that the left over blank line
|
||||
is required by the protocol.
|
||||
|
||||
<Q> What does the "You are using the xxxx character set." mean?
|
||||
|
||||
This note is printed when UTF8 mapping has to be done. Make sure
|
||||
that the displayed charset is the one you have activated on your
|
||||
system "iso-8859-1" is the most used one, so this is the default.
|
||||
You can change the charset with the option "--charset". It is
|
||||
important that you active character set matches the one displayed -
|
||||
if not, restrict yourself to plain 7 bit ASCII and no mapping has to
|
||||
be done.
|
||||
|
||||
<Q> How can a get list of key IDs used to encrypt a message?
|
||||
|
||||
[H pre] gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \
|
||||
awk '/^\[GNUPG:\] ENC_TO / { print $3 }' [H /pre]
|
||||
|
||||
<Q> I can't decrypt my symmetrical only (-c) encrypted message with
|
||||
a new version of GnuPG.
|
||||
|
||||
There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES
|
||||
or Twofish has been used for symmetric only encryption (this has
|
||||
never been the default). The bug has been fixed but to enable you
|
||||
to decrypt old messages, you should run gpg with the option
|
||||
"--emulate-3des-s2k-bug", decrypt the message and encrypt it again
|
||||
without this option. The option will be removed in 1.1, so better
|
||||
re-encrypt your message now.
|
||||
|
||||
<Q> How can I use GnuPG in an automated environment?
|
||||
|
||||
You should use the option --batch and don't use pass phrases as
|
||||
there is usually no way to store it more secure than the secret
|
||||
keyring itself. The suggested way to create the keys for the
|
||||
automated environment is:
|
||||
|
||||
On a secure machine:
|
||||
[H OL] [H LI] If you want to do automatic signing, create a signing
|
||||
subkey for your key (edit menu, choose "addkey" and the DSA). [H
|
||||
LI] Make sure that you use a passphrase (Needed by the current
|
||||
implementation) [H LI] gpg --export-secret-subkeys --no-comment foo
|
||||
>secring.auto [H LI] Copy secring.auto and the public keyring to a
|
||||
test directory. [H LI] Cd to this directory. [H LI] gpg --homedir
|
||||
. --edit foo and use "passwd" to remove the pass-phrase from the
|
||||
subkeys. You may also want to remove all unused subkeys. [H LI]
|
||||
copy secring.auto to a floppy and carry it to the target box [H /OL]
|
||||
On the target machine: [H OL] [H LI] Install secring.auto as secret
|
||||
keyring. [H LI] Now you can start your new service. It is a good
|
||||
idea to install some intrusion detection system so that you
|
||||
hopefully get a notice of an successful intrusion, so that you in
|
||||
turn can revoke all the subkeys installed on that machine and
|
||||
install new subkeys. [H /OL]
|
||||
|
||||
<Q> Which email-client can I use with GnuPG?
|
||||
|
||||
Using GnuPG to encrypt email is one of the most popular
|
||||
uses. Several mail clients or mail user-agents (MUA) support GnuPG
|
||||
at varying degrees. Simplifying a bit, there are two ways a mail can
|
||||
be encrypted with GnuPG: the "old style" ASCII armor, i.e. plain
|
||||
text encryption, and RFC2015 style (previously PGP/MIME, now
|
||||
OpenPGP). The latter has full MIME support. Some MUAs support only
|
||||
one of them, so whichever you actually use depends on your needs as
|
||||
well as the capabilities of your addressee.
|
||||
|
||||
The following list is probably not exhaustive:
|
||||
|
||||
OpenPGP: Mutt (Unix), Emacs/Mew, Becky2 (Windows, with plugin),
|
||||
TkRat (Unix). There is effort for a Mozilla plugin and
|
||||
Emacs/GNUS has support in the current CVS.
|
||||
|
||||
ASCII: Emacs/{VM,GNUS}/MailCrypt, Mutt(Unix), Pine(Unix), and
|
||||
probably many more.
|
||||
|
||||
Good overviews of OpenPGP-support can be found at
|
||||
[H a href=http://cryptorights.org/pgp-users/pgp-mail-clients.html]http://cryptorights.org/pgp-users/pgp-mail-clients.html[H /a].
|
||||
and [H a href=http://www.geocities.com/openpgp/courrier_en.html]http://www.geocities.com/openpgp/courrier_en.html[H /a].
|
||||
|
||||
|
||||
<Q> Can't we have a gpg library?
|
||||
|
||||
This has been frequently requested. However, the current viewpoint
|
||||
of the GnuPG maintainers is that this would lead to several security
|
||||
issues and will therefore not be implemented in the foreseeable
|
||||
future. However, for some areas of areas of application gpgme could
|
||||
do the trick. You'll find it at
|
||||
[H a href=ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme]ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme[H /a]
|
||||
|
||||
|
||||
<Q> I have successfully generated a revocation certificate, but I don't
|
||||
understand how to send it to the key servers.
|
||||
|
||||
Most keyservers don't accept a 'bare' revocation certificate. You
|
||||
have to import the certificate into gpg first:
|
||||
[H pre]
|
||||
gpg --import my-revocation.asc
|
||||
[H /pre]
|
||||
then send the revoked key to the keyservers:
|
||||
[H pre]
|
||||
gpg --keyserver certserver.pgp.com --send-keys mykeyid
|
||||
[H /pre]
|
||||
(or use a keyserver web interface for this).
|
||||
|
||||
|
||||
<Q> How do I put my keyring in a different directory?
|
||||
|
||||
GnuPG keeps several files in a special homedir directory. These
|
||||
include the options file, pubring.gpg, secring.gpg, the trustdb, and
|
||||
others. Gnupg will always create and use these files. On unices,
|
||||
the homedir is usually ~/.gnupg; on Windows "C:\gnupg\".
|
||||
|
||||
If you want to put your keyrings somewhere else, use
|
||||
[H pre]--homedir /my/path/[H /pre] to make gnupg create all its
|
||||
files in that directory. Your keyring will be
|
||||
"/my/path/pubring.gpg". This way you can store your secrets on a
|
||||
floppy disk. Don't use "--keyring" as its purpose is to specify
|
||||
additional keyring files.
|
||||
|
||||
|
||||
<S> COMPATIBILITY ISSUES
|
||||
|
||||
<Dcompat>
|
||||
|
||||
<Q> How can I encrypt a message with GnuPG so that PGP is able to decrypt it?
|
||||
|
||||
It depends on the PGP version.[H UL]
|
||||
|
||||
[H LI] PGP 2.x
|
||||
|
||||
You can't do that because PGP 2.x normally uses IDEA which is not
|
||||
supported by GnuPG as it is patented (see <Ridea>), but if you
|
||||
have a modified version of PGP you can try this:
|
||||
|
||||
[H pre] gpg --rfc1991 --cipher-algo 3des ... [H/pre]
|
||||
|
||||
Please don't pipe the data to encrypt to gpg but provide it using a
|
||||
filename; otherwise, PGP 2 will not be able to handle it.
|
||||
|
||||
As for conventional encryption, you can't do this for PGP 2.
|
||||
|
||||
|
||||
[H LI] PGP 5.x and higher
|
||||
|
||||
You need to provide two additional options:
|
||||
[H pre]--compress-algo 1 --cipher-algo cast5 [H/pre]
|
||||
|
||||
You may also use "3des" instead of "cast5", "blowfish" does not
|
||||
work with all versions of pgp5. You may also want to put [H pre]
|
||||
compress-algo 1 [H/pre] into your ~/.gnupg/options file - this does
|
||||
not affect normal gnupg operation.
|
||||
|
||||
This applies to conventional encryption as well.
|
||||
[H /UL]
|
||||
|
||||
<Q> How do I migrate from PGP 2.x to GnuPG?
|
||||
|
||||
PGP 2 uses the RSA and IDEA encryption algorithms. Whereas the RSA
|
||||
patent has expired and RSA is included as of GnuPG 1.0.3, the IDEA
|
||||
algorithm is still patented until 2007. Under certain conditions you
|
||||
may use IDEA even today. In that case, you may refer to Question
|
||||
<Ridea> about how to add IDEA support to GnuPG and read
|
||||
[H a href=http://www.gnupg.org/gph/en/pgp2x.html]http://www.gnupg.org/gph/en/pgp2x.html[H /a]
|
||||
to perform the migration.
|
||||
|
||||
|
||||
<Q> (removed)
|
||||
|
||||
(empty)
|
||||
|
||||
<Q> Why is PGP 5.x not able to encrypt messages with some keys?
|
||||
|
||||
PGP Inc refuses to accept ElGamal keys of type 20 even for
|
||||
encryption. They only support type 16 (which is identical at least
|
||||
for decryption). To be more inter-operable, GnuPG (starting with
|
||||
version 0.3.3) now also uses type 16 for the ElGamal subkey which is
|
||||
created if the default key algorithm is chosen. You may add an type
|
||||
16 ElGamal key to your public key which is easy as your key
|
||||
signatures are still valid.
|
||||
|
||||
<Q> Why is PGP 5.x not able to verify my messages?
|
||||
|
||||
PGP 5.x does not accept V4 signatures for data material but OpenPGP
|
||||
requests generation of V4 signatures for all kind of data, that's why
|
||||
GnuPG defaults to them. Use the option "--force-v3-sigs" to generate
|
||||
V3 signatures for data.
|
||||
|
||||
<Q> How do I transfer owner trust values from PGP to GnuPG?
|
||||
|
||||
There is a script in the tools directory to help you: After you have
|
||||
imported the PGP keyring you can give this command:
|
||||
|
||||
[H pre]
|
||||
$ lspgpot pgpkeyring | gpg --import-ownertrust
|
||||
[H /pre]
|
||||
|
||||
where pgpkeyring is the original keyring and not the GnuPG one you
|
||||
might have created in the first step.
|
||||
|
||||
<Q> PGP does not like my secret key.
|
||||
|
||||
Older PGPs probably bail out on some private comment packets used by
|
||||
GnuPG. These packets are fully in compliance with OpenPGP; however
|
||||
PGP is not really OpenPGP aware. A workaround is to export the
|
||||
secret keys with this command:
|
||||
[H pre] $ gpg --export-secret-keys --no-comment -a your-key-id [H /pre]
|
||||
|
||||
Another possibility is this: by default, GnuPG encrypts your secret
|
||||
key using the Blowfish symmetric algorithm. Older PGPs will only
|
||||
understand 3DES, CAST5, or IDEA symmetric algorithms. Using the
|
||||
following method you can re-encrypt your secret gpg key with a
|
||||
different algo:
|
||||
|
||||
[H pre]
|
||||
$ gpg --s2k-cipher-algo=CAST5 --s2k-digest-algo=SHA1 \
|
||||
--compress-algo=1 --edit-key <username>
|
||||
[H /pre]
|
||||
|
||||
Then use passwd to change the password (just change it to the same
|
||||
thing, but it will encrypt the key with CAST5 this time).
|
||||
|
||||
Now you can export it and PGP should be able to handle it.
|
||||
|
||||
For PGP 6.x the following options work to export a key:
|
||||
[H pre]
|
||||
$ gpg --s2k-cipher-algo 3des --compress-algo 1 --rfc1991 \
|
||||
--export-secret-keys <Key-ID>
|
||||
[H /pre]
|
||||
|
||||
<S> PROBLEMS and ERROR MESSAGES
|
||||
|
||||
<Q> Why do I get "gpg: Warning: using insecure memory!"
|
||||
|
||||
On many systems this program should be installed as
|
||||
setuid(root). This is necessary to lock memory pages. Locking
|
||||
memory pages prevents the operating system from writing them
|
||||
to disk and thereby keeping your secret keys really secret. If you
|
||||
get no warning message about insecure memory your operating system
|
||||
supports locking without being root. The program drops root
|
||||
privileges as soon as locked memory is allocated.
|
||||
|
||||
On UnixWare 2.x and 7.x you should install GnuPG with the
|
||||
'plock' privilege to get the same effect:
|
||||
[H pre]
|
||||
filepriv -f plock /path/to/gpg
|
||||
[H /pre]
|
||||
|
||||
If you can't or don't want to install GnuPG setuid(root), you can
|
||||
use the option "--no-secmem-warning" or put [H pre]
|
||||
no-secmem-warning [H /pre] in your ~/.gnupg/options file (this
|
||||
disables the warning).
|
||||
|
||||
On some systems (e.g., Windows) GnuPG does not lock memory pages
|
||||
and older GnuPG versions (<=1.0.4) issue the warning
|
||||
[H pre]
|
||||
gpg: Please note that you don't have secure memory
|
||||
[H /pre]
|
||||
This warning can't be switched off by the above option because it
|
||||
was thought to be a too serious issue. However, it confused users
|
||||
too much so the warning was eventually removed.
|
||||
|
||||
<Q> Large File Support doesn't work ..
|
||||
|
||||
LFS is correctly working in post-1.0.4 CVS. If configure doesn't
|
||||
detect it correctly, try a different (i.e., better) compiler. egcs
|
||||
1.1.2 works fine, other gccs sometimes don't. BTW, several
|
||||
compilation problems of GnuPG 1.0.3 and 1.0.4 on HP-UX and Solaris
|
||||
were due to broken LFS support.
|
||||
|
||||
<Q> In the edit menu the trust values is not displayed correctly after
|
||||
signing uids - why?
|
||||
|
||||
This happens because the some informations are stored immediately in
|
||||
the trustdb, but the actual trust calculation can be done after the
|
||||
save command. This is a not easy to fix design bug which will be
|
||||
addressed in some future release.
|
||||
|
||||
<Q> What does "skipping pubkey 1: already loaded" mean?
|
||||
|
||||
As of GnuPG 1.0.3, the RSA algorithm is included. If you still have
|
||||
a "load-extension rsa" in your .options files, the above message
|
||||
occurs. Just remove the load command from the .options file.
|
||||
|
||||
<Q> GnuPG 1.0.4 doesn't create ~/.gnupg ...
|
||||
|
||||
That's a known bug, already fixed in newer versions.
|
||||
|
||||
<Q> An ElGamal signature does not verify anymore since version 1.0.2 ...
|
||||
|
||||
Use the option --emulate-md-encode-bug.
|
||||
|
||||
<Q> Old versions of GnuPG can't verify ElGamal signatures
|
||||
|
||||
Update to GnuPG 1.0.2 or newer.
|
||||
|
||||
|
||||
<Q> When I use --clearsign, the plain text has sometimes extra dashes
|
||||
in it - why?
|
||||
|
||||
This is called dash-escaped text and required by OpenPGP.
|
||||
It always happens when a line starts with a dash ("-") and is needed
|
||||
to make the lines that structure signature and text
|
||||
(i.e., "-----BEGIN PGP SIGNATURE-----") to be the only lines that
|
||||
start with two dashes.
|
||||
|
||||
If you use GnuPG to process those messages, the extra dashes are removed.
|
||||
Good mail clients remove those extra dashes when displaying such a
|
||||
message.
|
||||
|
||||
<Q> What is the thing with "can't handle multiple signatures"?
|
||||
|
||||
Due to different message formats GnuPG is not always able to split a
|
||||
file with multiple signatures unambiguously into its parts. This
|
||||
error message informs you that there is something wrong with the input.
|
||||
|
||||
The only way to have multiple signatures in a file is by using the
|
||||
OpenPGP format with one-pass-signature packets (which is GnuPG's
|
||||
default) or the cleartext signed format.
|
||||
|
||||
<Q> If I submit a key to a keyserver, nothing happens ...
|
||||
|
||||
You are most likely using GnuPG on Windows 1.0.2 or older. That's
|
||||
feature isn't yet implemented, but it's a bug not to say it. Newer
|
||||
versions issue a warning. Upgrade to 1.0.4 or newer.
|
||||
|
||||
<Q> I get "gpg: waiting for lock ..."
|
||||
|
||||
A previous gpg has most likely exited abnormally and left a lock
|
||||
file. Go to ~/.gnupg and look for .*.lock files and remove them.
|
||||
|
||||
<Q> Older gpg's (e.g., 1.0) have problems with keys from newer gpgs ...
|
||||
|
||||
As of 1.0.3, keys generated with gpg are created with preferences to
|
||||
TWOFISH (and AES since 1.0.4) and that also means that they have the
|
||||
capability to use the new MDC encryption method. This will go into
|
||||
OpenPGP soon and is also suppoted by PGP 7. This new method avoids
|
||||
a (not so new) attack on all email encryption systems.
|
||||
|
||||
This in turn means that pre-1.0.3 gpg's have problems with newer
|
||||
key. Because of security fixes, you should keep your gpg
|
||||
installation in a recent state anyway. As a workaround, you can
|
||||
force gpg to use a previous default cipher algo by putting
|
||||
[H pre]cipher-algo cast5[H /pre] into your options file.
|
||||
|
||||
<Q> With 1.0.4, I get "this cipher algorithm is deprecated ..."
|
||||
|
||||
If you just generated a new key and get this message while
|
||||
encrypting, you've witnessed a bug in 1.0.4. It uses the new AES
|
||||
cipher Rijndael that is incorrectly being referred as
|
||||
"deprecated". Ignore this warning, more recent versions of gpg are
|
||||
corrected.
|
||||
|
||||
<Q> Some dates are displayed as ????-??-??, why?
|
||||
|
||||
Due to constraints in most libc implementations, dates beyond
|
||||
2038-01-19 can't be displayed correctly. 64 bit OSes are not
|
||||
affected by this problem. To avoid printing wrong dates, GnuPG
|
||||
instead prints some question marks. To see the correct value, you
|
||||
can use the options --with-colons and --fixed-list-mode.
|
||||
|
||||
<Q> I still have a problem. How do I report a bug?
|
||||
|
||||
Are you sure that it's not been mentioned somewhere on the mailing
|
||||
lists? Did you have a look at the bug list (You'll find a link to
|
||||
the list of reported bugs on the documentation page). If you're not
|
||||
sure about it being a bug, you can send mail to the gnupg-devel
|
||||
list. Otherwise, use the GUUG bug tracking system
|
||||
[H a href=http://bugs.guug.de/Reporting.html]
|
||||
http://bugs.guug.de/Reporting.html[H /a].
|
||||
|
||||
<Q> Why doesn't GnuPG support X509 certificates?
|
||||
|
||||
GnuPG, first and foremost, is an implementation of the OpenPGP
|
||||
standard (RFC 2440), which is a competing infrastructure, different
|
||||
from X509.
|
||||
|
||||
They are both public-key cryptosystems, but how the public keys are
|
||||
actually handled is different.
|
||||
|
||||
|
||||
<Q> Why do national characters in my user ID look funny?
|
||||
|
||||
According to OpenPGP, GnuPG encodes user id strings (and other
|
||||
things) using UTF-8. In this encoding of Unicode, most national
|
||||
characters get encoded as two- or three-byte sequences. For
|
||||
example, å (0xE5 in ISO-8859-1) becomes Ã¥ (0xC3,
|
||||
0xA5). This might also be the reason why keyservers can't find
|
||||
your key.
|
||||
|
||||
<Q> I get 'sed' errors when running ./configure on Mac OS X ...
|
||||
|
||||
This will be fixed after GnuPG has been upgraded to
|
||||
autoconf-2.50. Until then, find the line setting CDPATH in the
|
||||
configure script and place a [H pre]unset CDPATH[H /pre] statement
|
||||
below it.
|
||||
|
||||
<Q> Why does GnuPG 1.0.6 bail out on keyrings used with 1.0.7?
|
||||
|
||||
There is a small bug in 1.0.6 which didn't parse trust packets
|
||||
currectly. You may want to apply this patch if you can't upgrade:
|
||||
http://www.gnupg.org/developer/gpg-woody-fix.txt
|
||||
|
||||
|
||||
|
||||
<S> ADVANCED TOPICS
|
||||
|
||||
<Q> How does this whole thing work?
|
||||
|
||||
To generate a secret/public keypair, run [H pre] gpg --gen-key
|
||||
[H/pre] and choose the default values.
|
||||
|
||||
Data that is encrypted with a public key can only be decrypted by
|
||||
the matching secret key. The secret key is protected by a password,
|
||||
the public key is not.
|
||||
|
||||
So to send your friend a message, you would encrypt your message
|
||||
with his public key, and he would only be able to decrypt it by
|
||||
having the secret key and putting in the password to use his secret
|
||||
key.
|
||||
|
||||
GnuPG is also useful for signing things. Things that are encrypted
|
||||
with the secret key can be decrypted with the public key. To sign
|
||||
something, a hash is taken of the data, and then the hash is in some
|
||||
form encoded with the secret key. If someone has your public key, they
|
||||
can verify that it is from you and that it hasn't changed by checking
|
||||
the encoded form of the hash with the public key.
|
||||
|
||||
A keyring is just a large file that stores keys. You have a public
|
||||
keyring where you store yours and your friend's public keys. You have
|
||||
a secret keyring that you keep your secret key on, and be very careful
|
||||
with this secret keyring: Never ever give anyone else access to it and
|
||||
use a *good* passphrase to protect the data in it.
|
||||
|
||||
You can 'conventionally' encrypt something by using the option 'gpg
|
||||
-c'. It is encrypted using a passphrase, and does not use public and
|
||||
secret keys. If the person you send the data to knows that
|
||||
passphrase, they can decrypt it. This is usually most useful for
|
||||
encrypting things to yourself, although you can encrypt things to your
|
||||
own public key in the same way. It should be used for communication
|
||||
with partners you know and where it is easy to exchange the
|
||||
passphrases (e.g. with your boy friend or your wife). The advantage
|
||||
is that you can change the passphrase from time to time and decrease
|
||||
the risk, that many old messages may be decrypted by people who
|
||||
accidently got your passphrase.
|
||||
|
||||
You can add and copy keys to and from your keyring with the 'gpg
|
||||
--import' and 'gpg --export' option. 'gpg --export-secret-keys' will
|
||||
export secret keys. This is normally not useful, but you can generate
|
||||
the key on one machine then move it to another machine.
|
||||
|
||||
Keys can be signed under the 'gpg --edit-key' option. When you sign a
|
||||
key, you are saying that you are certain that the key belongs to the
|
||||
person it says it comes from. You should be very sure that is really
|
||||
that person: You should verify the key fingerprint
|
||||
[H pre]
|
||||
gpg --fingerprint user-id
|
||||
[H/pre]
|
||||
over phone (if you really know the voice of the other person) or at a
|
||||
key signing party (which are often held at computer conferences) or at
|
||||
a meeting of your local GNU/Linux User Group.
|
||||
|
||||
Hmm, what else. You may use the option "-o filename" to force output
|
||||
to this filename (use "-" to force output to stdout). "-r" just lets
|
||||
you specify the recipient (which public key you encrypt with) on the
|
||||
command line instead of typing it interactively.
|
||||
|
||||
Oh yeah, this is important. By default all data is encrypted in some
|
||||
weird binary format. If you want to have things appear in ASCII text
|
||||
that is readable, just add the '-a' option. But the preferred method
|
||||
is to use a MIME aware mail reader (Mutt, Pine and many more).
|
||||
|
||||
There is a small security glitch in the OpenPGP (and therefore GnuPG)
|
||||
system; to avoid this you should always sign and encrypt a message
|
||||
instead of only encrypting it.
|
||||
|
||||
|
||||
<Q> Why are some signatures with an ELG-E key valid?
|
||||
|
||||
These are ElGamal Key generated by GnuPG in v3 (rfc1991) packets.
|
||||
The OpenPGP draft later changed the algorithm identifier for ElGamal
|
||||
keys which are usable for signatures and encryption from 16 to 20.
|
||||
GnuPG now uses 20 when it generates new ElGamal keys but still
|
||||
accept 16 (which is according to OpenPGP "encryption only") if this
|
||||
key is in a v3 packet. GnuPG is the only program which had used
|
||||
these v3 ElGamal keys - so this assumption is quite safe.
|
||||
|
||||
|
||||
<Q> How does the whole trust thing work?
|
||||
|
||||
It works more or less like PGP. The difference is that the trust is
|
||||
computed at the time it is needed. This is one of the reasons for
|
||||
the trustdb which holds a list of valid key signatures. If you are
|
||||
not running in batch mode you will be asked to assign a trust
|
||||
parameter (ownertrust) to a key.
|
||||
|
||||
|
||||
|
||||
You can see the validity (calculated trust value) using this
|
||||
command.
|
||||
[H pre] gpg --list-keys --with-colons [H/pre]
|
||||
|
||||
If the first field is "pub" or "uid", the second field shows you the
|
||||
trust:
|
||||
|
||||
[H pre]
|
||||
o = Unknown (this key is new to the system)
|
||||
e = The key has expired
|
||||
q = Undefined (no value assigned)
|
||||
n = Don't trust this key at all
|
||||
m = There is marginal trust in this key
|
||||
f = The key is full trusted
|
||||
u = The key is ultimately trusted; this is only used
|
||||
for keys for which the secret key is also available.
|
||||
r = The key has been revoked
|
||||
d = The key has been disabled
|
||||
[H/pre]
|
||||
|
||||
The value in the "pub" record is the best one of all "uid" records.
|
||||
|
||||
You can get a list of the assigned trust values (how much you trust
|
||||
the owner to correctly sign another person's key)
|
||||
|
||||
[H pre] gpg --list-ownertrust [H/pre] The first field is the
|
||||
fingerprint of the primary key, the second field is the assigned
|
||||
value:
|
||||
|
||||
[H pre]
|
||||
- = No Ownertrust value yet assigned.
|
||||
n = Never trust this keyholder to correctly verify others signatures.
|
||||
m = Have marginal trust in the keyholders capability to sign other
|
||||
keys.
|
||||
f = Assume that the key holder really knows how to sign keys.
|
||||
u = No need to trust ourself because we have the secret key.
|
||||
[H/pre]
|
||||
|
||||
Keep these values confidential because they express your opinions
|
||||
about others. PGP stores this information with the keyring thus it
|
||||
is not a good idea to publish a PGP keyring instead of exporting the
|
||||
keyring. gnupg stores the trust in the trust-DB so it is okay to
|
||||
give a gpg keyring away (but we have a --export command too).
|
||||
|
||||
<Q> What kind of output is this: "key C26EE891.298, uid 09FB: ...."?
|
||||
|
||||
This is the internal representation of a user id in the trustdb.
|
||||
"C26EE891" is the keyid, "298" is the local id (a record number in
|
||||
the trustdb) and "09FB" is the last two bytes of a ripe-md-160 hash
|
||||
of the user id for this key.
|
||||
|
||||
<Q> How do I interpret some of the informational outputs?
|
||||
|
||||
While checking the validity of a key, GnuPG sometimes prints some
|
||||
information which is prefixed with information about the checked
|
||||
item. [H pre] "key 12345678.3456" [H/pre] This is about the key
|
||||
with key ID 12345678 and the internal number 3456, which is the
|
||||
record number of the so called directory record in the trustdb.
|
||||
[H pre] "uid 12345678.3456/ACDE" [H/pre] This is about the user ID for
|
||||
the same key. To identify the user ID the last two bytes of a
|
||||
ripe-md-160 over the user ID ring is printed. [H pre] "sig
|
||||
12345678.3456/ACDE/9A8B7C6D" [H/pre] This is about the signature
|
||||
with key ID 9A8B7C6D for the above key and user ID, if it is a
|
||||
signature which is direct on a key, the user ID part is empty
|
||||
(..//..).
|
||||
|
||||
<Q> Are the header lines of a cleartext signature part of the signed
|
||||
material?
|
||||
|
||||
No. For example you can add or remove "Comment:" lines. They have
|
||||
a purpose like the mail header lines. However a "Hash:" line is
|
||||
needed for OpenPGP signatures to tell the parser which hash
|
||||
algorithm to use.
|
||||
|
||||
|
||||
<Q> What is the list of preferred algorithms?
|
||||
|
||||
The list of preferred algorithms is a list of cipher, hash and
|
||||
compression algorithms stored in the self-signature of a key during
|
||||
key generation. When you encrypt a document, GnuPG uses this list
|
||||
(which is then part of a public key) to determine which algorithms
|
||||
to use. Basically it tells other people what algorithms the
|
||||
recipient is able to handle and provides an order of preference.
|
||||
|
||||
<Q> How do I change the list of preferred algorithms?
|
||||
|
||||
Use the edit menu and set the new list of preference using the
|
||||
command "setpref"; the format of this command resembles the output
|
||||
of the command "pref". The preference are not changes immediately
|
||||
but the set preference will be used when a new user ID is
|
||||
created. If you want to update the preferences for existing user
|
||||
IDs, select those user IDs (or select none to update all) and
|
||||
enter the command "updpref". Note that the timestamp of the
|
||||
self-signatures is increaded by one second when running this
|
||||
command.
|
||||
|
||||
|
||||
<S> ACKNOWLEDGEMENTS
|
||||
|
||||
Many thanks to Nils Ellmenreich for maintaining this FAQ file for
|
||||
a long time and to all posters to gnupg-users and gnupg-devel. They
|
||||
all provided most of the answers.
|
||||
|
||||
Also thanks to Casper Dik for providing me with a script to generate
|
||||
this FAQ (he uses it for the excellent Solaris2 FAQ).
|
||||
|
||||
[H HR]
|
||||
|
||||
Copyright (C) 2000, 2002 Free Software Foundation, Inc. ,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111, USA
|
||||
|
||||
Verbatim copying and distribution of this entire article is permitted in
|
||||
any medium, provided this notice is preserved.
|
|
@ -0,0 +1,17 @@
|
|||
2001-09-10 Gilbert Fernandes <gilbertf@posse-press.com>
|
||||
|
||||
* Traduction en français des documents doc/*
|
||||
|
||||
|
||||
Copyright 2001 Free Software Foundation, Inc.
|
||||
|
||||
Ce fichier est un logiciel libre ; l'auteur vous donne une autorisation
|
||||
spéciale de copies illimitées et/ou distribution illimitée avec ou sans
|
||||
modifications attendu que cette notice de copyright et note associée
|
||||
se trouve conservée dans le document.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
|
@ -0,0 +1,945 @@
|
|||
|
||||
Format des listings "---with-colons"
|
||||
====================================
|
||||
|
||||
sec::1024:17:6C7EE1B8621CC013:1998-07-07:0:::Werner Koch <werner.koch@guug.de>:
|
||||
ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
|
||||
|
||||
1. Champ: Type d'enregistrement
|
||||
pub = clef publique
|
||||
sub = sous-clef (clef secondaire)
|
||||
sec = clef secrète
|
||||
ssb = sous-clef secrète (clef secondaire)
|
||||
uid = id d'utilisateur (seul le champ 10 est utilisé)
|
||||
sig = signature
|
||||
fpr = fingerprint: (le champ 10 est le fingerprint)
|
||||
pkd = données publiques de la clef
|
||||
(champ au format spécial, voir ci-dessous)
|
||||
|
||||
2. Champ: Une lettre décrivant la confiance calculée. Ce n'est qu'une
|
||||
seule lettre, mais elle fera peut-être l'objet d'une information
|
||||
supplémentaire pour les versions futures, comme décrit ici
|
||||
(ceci ne sera pas utilisé pour les clefs privées)
|
||||
o = Inconnu (cette clef est nouvelle au système)
|
||||
i = La clef est invalide (eg. il manque sa propre signature)
|
||||
d = La clef a été désactivée
|
||||
r = La clef a été révoquée
|
||||
e = La clef a expiré
|
||||
q = Non-défini (pas de valeur attribuée)
|
||||
n = Ne jamais faire confiance à cette clef
|
||||
m = Cette clef dispose d'une confiance marginale
|
||||
f = Cette clef dispose d'une confiance totale
|
||||
u = Cette clef dispose d'une confiance ultime. Cette valeur
|
||||
n'est utilisée que pour les clefs où la clef secrète est
|
||||
également disponibles.
|
||||
3. Champ: taille de la clef en bits.
|
||||
4. Champ: Algorithme utilisé: 1 = RSA
|
||||
16 = ElGamal (chiffrement uniquement)
|
||||
17 = DSA (parfois appellé DH, signature seulement)
|
||||
20 = ElGamal (signe et chiffre)
|
||||
(pour d'autres is, consultez include/cipher.h)
|
||||
5. Champ: ID de clef (KeyID)
|
||||
6. Champ: Date de création (en UTC)
|
||||
7. Champ: Date d'expiration de la clef, vide si aucune.
|
||||
8. Champ: ID local : numéro d'enregistrement du répertoire dans la
|
||||
trustdb. Cette valeur n'est valide que tant que la
|
||||
trustdb n'est pas effacée. Vous pouvez utiliser
|
||||
"#<local-id>" comme id d'utilisateur lorsque vous spécifiez
|
||||
la clef. Ceci est requis puisque les id de clef ne sont pas
|
||||
toujours uniques - un programme peut donc utiliser ce numéro
|
||||
pour accéder aux clefs ultérieurement.
|
||||
9. Champ: Confiance propre (clef publiques primaires uniquement)
|
||||
C'est une simple lettre, mais une information supplémentaire pourrait
|
||||
se voir ajoutée dans les versions futures.
|
||||
10. Champ: ID utilisateur. La valeur est placée entre guillemets comme une
|
||||
chaîne en C, par exemple : "\x3a".
|
||||
11. Champ: Classe de signature. C'est un nombre hexadécimal à deux chiffres
|
||||
suivi par la lettre "x" si la signature peut être exportée ou la
|
||||
lettre "l" si la signature est uniquement locale.
|
||||
12. Champ: Capacités de la clef :
|
||||
e = chiffrement
|
||||
s = signature
|
||||
c = certification
|
||||
Une clef peut disposer de toute combinaison de ces caractéristiques.
|
||||
La clef primaire dispose, en plus de ces lettres, une version en
|
||||
majuscule des lettres pour marquer les capacités "d'utilisation"
|
||||
de la totalité de la clef.
|
||||
|
||||
Toutes les dates sont affichées dans le format :
|
||||
|
||||
yyyy-mm-dd
|
||||
|
||||
Sauf si vous utilisez l'option --fixed-list-mode où dans ce cas précis les
|
||||
dates sont affichées en secondes depuis Epoch. Plus de champs feront l'objet
|
||||
d'additions dans les futures versions et les parsers doivent y être préparés.
|
||||
Lorsque le parser traitera ces données, il devra s'arrêter au premier
|
||||
caractère non-numérique afin que des informations supplémentaires soient
|
||||
ajoutées à l'avenir.
|
||||
|
||||
Le champ 1 dispose d'un tag "pkd" dont le listing ressemble à ceci :
|
||||
|
||||
pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
||||
! ! !-- la valeur
|
||||
! !------ indicateur du nombre de bits de la valeur
|
||||
!--------- index (eg. DSA va de 0 à 3 : p,q,g,y)
|
||||
|
||||
|
||||
|
||||
Format de la sortie "--status-fd"
|
||||
=================================
|
||||
|
||||
Chaque ligne dispose d'un préfixe :
|
||||
|
||||
"[GNUPG:] "
|
||||
|
||||
Suivie par un mot clef indiquant le type de la ligne de statut,
|
||||
et quelques arguments selon le type (probablement aucun) ; une application
|
||||
devrait toujours assumer que des arguments supplémentaires seront
|
||||
présents dans les versions futures.
|
||||
|
||||
GOODSIG <long keyid> <username>
|
||||
La signature keyid est valide.
|
||||
Pour chaque signature seul l'un des trois codes GOODSIG, BADSIG ou
|
||||
ERRSIG seront produits et ils pourront être utilisés comme
|
||||
marqueurs pour les nouvelles signatures.
|
||||
|
||||
BADSIG <long keyid> <username>
|
||||
La signature keyid n'a pas été vérifiée correctement.
|
||||
|
||||
ERRSIG <long keyid> <pubkey_algo> <hash_algo> \
|
||||
<sig_class> <timestamp> <rc>
|
||||
Il n'a pas été possible de vérifier la signature. Ceci peut provenir
|
||||
d'une clef publique manquante, ou bien à cause d'un algorithme non-
|
||||
supporté. Un RC de 4 indique un algorithme inconnu, un 9 indique
|
||||
une clef publique manquante. Les autres champs donnent plus d'information
|
||||
sur la signature. sig_class est une valeur hexadécimale de 2 octets.
|
||||
|
||||
VALIDSIG <fingerprint in hex> <sig_creation_date> <sig-timestamp>
|
||||
La signature keyid est valide. C'est ici la même chose que GOODSIG
|
||||
mais avec le fingerprint comme argument. Les lignes de statut seront
|
||||
émises pour une bonne signature.
|
||||
sig-timestamp est la date de création de la signature en secondes
|
||||
depuis Epoch.
|
||||
|
||||
SIG_ID <radix64_string> <sig_creation_date> <sig-timestamp>
|
||||
N'est émis que pour les signatures de classe 0 ou 1 qui ont été
|
||||
vérifiées comme valides. Le chaîne est un identifiant d'utilisateur
|
||||
et peut être utilisée dans les applications pour détecter les
|
||||
attaques par rejeu de messages signés. Notez que seuls les
|
||||
algorithmes DLP offrent des identifiants uniques ; les autres peuvent
|
||||
produire des id dupliqués lorsqu'ils furent créés à la même seconde.
|
||||
|
||||
ENC_TO <long keyid> <keytype> <keylength>
|
||||
Le message est chiffré avec ce keyid.
|
||||
keytype est une valeur numérique de l'algorithme à clef publique,
|
||||
keylength est la taille de la clef ou 0 si elle n'est pas connue
|
||||
(ce qui est toujours le cas).
|
||||
|
||||
NODATA <what>
|
||||
Aucune donnée n'a été trouvée. Les codes suivants sont utilisés :
|
||||
1 - Pas de données sous ARMOR.
|
||||
2 - Un paquet attendu n'a pas été trouvé.
|
||||
3 - Paquet invalide trouvé ; ceci peut indiquer un message
|
||||
non-OpenPGP. Vous devez vous attendre à une extension
|
||||
de ces lignes de statu à l'avenir.
|
||||
|
||||
UNEXPECTED <what>
|
||||
Des données innatendues ont été rencontrées
|
||||
0 - pas de détail supplémentaire
|
||||
|
||||
TRUST_UNDEFINED
|
||||
TRUST_NEVER
|
||||
TRUST_MARGINAL
|
||||
TRUST_FULLY
|
||||
TRUST_ULTIMATE
|
||||
Pour les signatures valides, l'une de ces lignes de statut sera produite
|
||||
pour indiquer le niveau de confiance attribué à la clef. Pas d'arguments
|
||||
pour l'instant.
|
||||
|
||||
SIGEXPIRED
|
||||
La clef de signature a expiré. Pas d'arguments pour l'instant.
|
||||
|
||||
KEYREVOKED
|
||||
L'utilisateur a révoqué sa clef. Pas d'arguments pour l'instant.
|
||||
|
||||
BADARMOR
|
||||
L'ARMOR ASCII est corrompu. Pas d'arguments pour l'instant.
|
||||
|
||||
RSA_OR_IDEA
|
||||
Les algorithmes IDEA ont été utilisés sur les données. Un programme
|
||||
pourra basculer sur un autre programme de traitement si GnuPG échoue.
|
||||
Ce message de statut sera affiché pour le RSA aussi, mais ceci a été
|
||||
abandonné puisque le brevêt sur le RSA a expiré.
|
||||
Toutefois, nous ne pouvons modifier le nom du message.
|
||||
|
||||
SHM_INFO
|
||||
SHM_GET
|
||||
SHM_GET_BOOL
|
||||
SHM_GET_HIDDEN
|
||||
|
||||
GET_BOOL
|
||||
GET_LINE
|
||||
GET_HIDDEN
|
||||
GOT_IT
|
||||
|
||||
NEED_PASSPHRASE <long main keyid> <long keyid> <keytype> <keylength>
|
||||
Sera affiché à chaque fois qu'une phrase passe sera requise.
|
||||
keytype est la valeur numérique de l'algorithme à clef publique
|
||||
ou bien 0 si cela n'est pas applicable. keylength est la taille de la
|
||||
clef ou 0 si la taille n'est pas connue (ceci est actuellement
|
||||
toujours le cas).
|
||||
|
||||
NEED_PASSPHRASE_SYM <cipher_algo> <s2k_mode> <s2k_hash>
|
||||
Affiché à chaque fois qu'une phrase passe pour un chiffrement
|
||||
symétrique sera requise.
|
||||
|
||||
MISSING_PASSPHRASE
|
||||
Aucune phrase passe n'a été fournie. Une application qui rencontre
|
||||
ce message devrait stopper immédiatement le parsing car le prochain
|
||||
message sera probablement BAD_PASSPHRASE. Toutefois, si l'application
|
||||
n'est qu'un wrapper autour de la fonctionnalité d'édition de clefs,
|
||||
ceci pourrait avoir un autre sens et stopper le parsing pourrait
|
||||
être incorrect, et il faudra ignorer le BAD_PASSPHRASE.
|
||||
|
||||
BAD_PASSPHRASE <long keyid>
|
||||
La phrase passe fournie est soit invalide, soit n'a pas été fournie.
|
||||
Dans le seconde cas vous devriez voir un MISSING_PASSPHRASE.
|
||||
|
||||
GOOD_PASSPHRASE
|
||||
La phrase passe fournie est valide et le matériel de clefs secrète
|
||||
est utilisable.
|
||||
|
||||
DECRYPTION_FAILED
|
||||
La déchiffrement symétrique a échoué. Il s'agit généralement d'une
|
||||
mauvaise phrase passe ne correspondant pas au message chiffré.
|
||||
|
||||
DECRYPTION_OKAY
|
||||
Succès du déchiffrement. Ceci signifie que soit la clef secrète
|
||||
adaptée a été utilisée avec succès, soit que la phrase passe
|
||||
valide pour un chiffrement symétrique aura conduit au déchiffrement.
|
||||
Le programme pourait toutefois renvoyer un message d'erreur s'il
|
||||
n'a pas été possible de vérifier la signature.
|
||||
|
||||
NO_PUBKEY <long keyid>
|
||||
NO_SECKEY <long keyid>
|
||||
La clef n'est pas utilisable.
|
||||
|
||||
IMPORTED <long keyid> <username>
|
||||
Le keyid et la signature ont été importés.
|
||||
|
||||
IMPORTED_RES <count> <no_user_id> <imported> <imported_rsa> <unchanged>
|
||||
<n_uids> <n_subk> <n_sigs> <n_revoc> <sec_read> <sec_imported> <sec_dups>
|
||||
Statistiques finales sur le processus d'importation (cette ligne est longue!)
|
||||
|
||||
FILE_START <what> <filename>
|
||||
Début de traitement du fichier <filename>. <what> indique l'opération
|
||||
réalisée :
|
||||
1 - vérifier
|
||||
|
||||
FILE_DONE
|
||||
Marque la fin de traitement d'un fichier, ayant débuté avec FILE_START.
|
||||
|
||||
BEGIN_DECRYPTION
|
||||
END_DECRYPTION
|
||||
Marque le début et la fin du processus de déchiffrement. Ces messages
|
||||
seront également produits lors de l'utilisation du mode --list-only.
|
||||
|
||||
BEGIN_ENCRYPTION
|
||||
END_ENCRYPTION
|
||||
Marque le début et la fin du processus de chiffrement.
|
||||
|
||||
DELETE_PROBLEM reason_code
|
||||
L'effacement d'une clef a échoué. Un code indique la raison de l'erreur :
|
||||
1 - La clef spécifiée n'existe pas
|
||||
2 - La clef privée doit être détruite avant !
|
||||
|
||||
PROGRESS what char cur total
|
||||
Utilisé par les fonctions primegen et de clef publique pour indiquer
|
||||
la progression de l'opération. "char" est le caractère affiché sans
|
||||
--status-fd avec les retours à la ligne marqués par "X". "cur" indique
|
||||
la quantitité de traitement terminée et "total" indique la valeur
|
||||
finale à atteindre. Un total de 0 indique que le total n'est pas
|
||||
connu. 100/100 peut être utilisé pour détecter la fin de l'opération.
|
||||
|
||||
SIG_CREATED <type> <pubkey algo> <hash algo> <class> <timestamp> <key fpr>
|
||||
Une signature a été créée à l'aide de ces paramètres.
|
||||
type: 'D' = détachée
|
||||
'C' = en texte clair
|
||||
'S' = standard
|
||||
(seul le premier caractère doit être vérifié)
|
||||
class: 2 chiffres hexadécimaux avec la classe de signature
|
||||
|
||||
KEY_CREATED <type>
|
||||
Une clef a été créée
|
||||
type: 'B' = primaire et sous-clef
|
||||
'P' = primaire
|
||||
'S' = sous-clef
|
||||
|
||||
SESSION_KEY <algo>:<hexdigits>
|
||||
La clef de session utilisée pour déchiffrer le message. Ce message
|
||||
sera seulement affiché si l'option --show-session est utilisée.
|
||||
Le format est utilisable pour un passage direct à la fonction
|
||||
--override-session-key.
|
||||
|
||||
NOTATION_NAME <name>
|
||||
NOTATION_DATA <string>
|
||||
Le nom et la chaîne sont "escaped" à l'aide de %XX et les données
|
||||
peuvent être découpées sur plusieurs lignes notation_data.
|
||||
|
||||
USERID_HINT <long main keyid> <string>
|
||||
Donne un indice sur l'ID utilisateur pour un keyID donné.
|
||||
|
||||
POLICY_URL <string>
|
||||
La chaîne est "escaped" en %XX
|
||||
|
||||
BEGIN_STREAM
|
||||
END_STREAM
|
||||
Produit par pipemode.
|
||||
|
||||
|
||||
Génération de clef
|
||||
==================
|
||||
|
||||
La génération de clef marque sa progression à l'aide de différents caractères, dont
|
||||
voici la signification :
|
||||
|
||||
"." : les 10 derniers tests Miller-Rabin ont échoué.
|
||||
"+" : réussite du test Miller-Rabin.
|
||||
"!" : Rechargement du pool avec des nombres premiers frais.
|
||||
"^" : Vérification d'une nouvelle valeur pour le générateur.
|
||||
"<" : La taille d'un facteur a été réduite.
|
||||
">" : La taille d'un facteur a été augmentée.
|
||||
|
||||
Le nombre premier pour l'ElGamal est généré de la manière suivante :
|
||||
|
||||
1. On crée un nombre premier q de 160, 200 ou 240 bits (selon la taille
|
||||
de la clef).
|
||||
2. On sélectionne la taille de l'autre facteur premier, afin qu'elle soit
|
||||
au moins de la taille de q et on calcule le nombre de facteurs premiers
|
||||
requis.
|
||||
3. On crée un pool de nombres premiers, chacun dont la longueur fut déterminée
|
||||
à l'étape 2.
|
||||
4. On obtient une nouvelle permutation du pool et nous continuons avec
|
||||
l'étape 3 une fois toutes les permutations testées.
|
||||
5. Le premier cancidat est calculé par p = 2 * q * p[1] * ... * p[n] + 1
|
||||
6. On vérifie que ce premier dispose de la taille désirée (ceci peut changer
|
||||
q s'il ne semble pas possible de produire un premier de la taille voulue)
|
||||
7. On vérifie si ce nombre est premier à l'aide de divisions d'essai et par
|
||||
le test de Miller-Rabin.
|
||||
8. On continue à l'étape 4 si on n'a pas trouvé de premier à l'étape 7.
|
||||
9. On trouve un générateur pour ce premier.
|
||||
|
||||
Cet algorithme se base sur la suggestion de Lim et Lee du Crypto' 97 (p. 260).
|
||||
|
||||
Génération de clef innatendue
|
||||
=============================
|
||||
|
||||
Cette fonction est actuellement expérimentale et permet la production de
|
||||
clefs innatendues avec un contrôle depuis un fichier de paramètres.
|
||||
Cette fonctionnalité n'a pas fait l'objet de tests poussés ! Veuillez ne
|
||||
PAS vous plaindre si nous décidons d'apporter des modifications importantes
|
||||
à cette commande.
|
||||
|
||||
Pour utiliser cette fonctionnalité, vous devez utiliser --gen-key en
|
||||
combinaison avec --batch et fournir les paramètres soit depuis stdin,
|
||||
soit depuis un fichier dont le nom est fourni en ligne de commande.
|
||||
|
||||
Ce fichier devra utiliser le format suivant :
|
||||
|
||||
o En texte uniquement, chaque ligne étant limitée à environ 1000 caractères.
|
||||
o Vous devez utiliser un codage UTF-8 pour marquer les caractères non ASCII.
|
||||
o Les lignes vides seront ignorées.
|
||||
o Les espaces en début et fin de ligne seront ignorés.
|
||||
o Un signe "-" en tant que premier caractère "non white space" marque
|
||||
une ligne de commentaire.
|
||||
o Les commandes sont marquées par un signe "%" en début de ligne,
|
||||
suivi par la commande et ses arguments sont séparés par des espaces.
|
||||
o Les paramètres sont indiqués par un mot clef, suivi par un ":". Les
|
||||
arguments sont séparés par des espaces.
|
||||
o Le premier paramètre doit être "Key-Type" et ses contrôles peuvent
|
||||
être placés à votre discrétion.
|
||||
o La génération de clef aura lieu soit à la fin du fichier de paramètres,
|
||||
soit lorsque le premier "Key-Type" est rencontré au sein du fichier,
|
||||
dans un ensenble de contrôle "%commit".
|
||||
o Les ensembles de contrôle sont :
|
||||
%echo <texte>
|
||||
Affiche <texte>
|
||||
|
||||
%dry-run
|
||||
Ne réalise pas la production de clef (pratique pour vérifier la
|
||||
syntaxe).
|
||||
|
||||
%commit
|
||||
Réalise la production de clef. Un commit implicite est produit
|
||||
à chaque rencontre de "Key-Type".
|
||||
|
||||
%pubring <filename>
|
||||
%secring <filename>
|
||||
Ne renvoie pas la clef vers le sortie par défaut ou dans le keyring
|
||||
indiqué en ligne de commande, mais vers le fichier <filename>. Ce
|
||||
contrôle doit être utilisé avant que le commit ne soit rencontré.
|
||||
Toute double mention sera ignorée et le dernier nom de fichier
|
||||
rencontré sera celui utilisé. Le fichier sera utilisé jusqu'à ce
|
||||
qu'un nouveau fichier soit spécifié (au points de commit) sinon
|
||||
toutes les clefs seront placées dans le même fichier. Si un nouveau
|
||||
nom de fichier est indiqué, le fichier sera créé (et tout ancien
|
||||
fichier sera alors écrasé). Les deux indications doivent être
|
||||
fournies au contrôle.
|
||||
|
||||
o L'ordre des paramètres n'a pas d'importance, sauf pour "Key-Type" qui
|
||||
doit être le premier paramètre rencontré. Les paramètres ne sont
|
||||
destinés qu'au bloc keybloc généré et les paramètres des productions
|
||||
précédentes de clefs ne seront pas pris en compte. Certaines
|
||||
vérifications syntaxiques seront mises en place et peuvent être
|
||||
ou non actives. Les paramètres actuellement définis sont :
|
||||
|
||||
Key-Type: <algo-number>|<algo-string>
|
||||
Débute un nouveau bloc de paramètres indiquant le type de la clef
|
||||
primaire à produire. L'algorithme doit être capable de produire
|
||||
des signatures. Ce paramètre est indispensable !
|
||||
|
||||
Key-Length: <length-in-bits>
|
||||
Indique la taille de la clef, en bits. La valeur par défaut est
|
||||
1024.
|
||||
|
||||
Subkey-Type: <algo-number>|<algo-string>
|
||||
Permet de produire une clef secondaire. Actuellement, seule une
|
||||
sous-clef peut être gérée.
|
||||
|
||||
Subkey-Length: <length-in-bits>
|
||||
Taille de la sous-clef en bits. La valeur par défaut est
|
||||
1024.
|
||||
|
||||
Passphrase: <string>
|
||||
Si vous souhaitez spécifier une phrase passe pour la clef
|
||||
secrète vous pouvez utiliser cette commande. Par défaut,
|
||||
aucune phrase passe ne sera associée aux clefs privées.
|
||||
|
||||
Name-Real: <string>
|
||||
Name-Comment: <string>
|
||||
Name-Email: <string>
|
||||
Voici les trois composantes d'une clef. Vous devez ici
|
||||
n'utiliser que de l'UTF-8. Si vous ne fournissez aucune
|
||||
de ces indications, aucun ID d'utilisateur ne sera créé.
|
||||
|
||||
Expire-Date: <iso-date>|(<number>[d|w|m|y])
|
||||
Spécifie la date d'expiration de la clef (et de sa sous-clef)
|
||||
La date doit être entrée sous la forme d'une date au format
|
||||
ISO (année-mois-jour) ou bien sous forme d'un nombre de
|
||||
jours, de semaines, de mois ou d'années. Si vous n'utilisez
|
||||
pas de lettre pour indiquer la durée, des "jours" sont
|
||||
assumés par défaut.
|
||||
|
||||
Voici un exemple :
|
||||
$ cat >foo <<EOF
|
||||
%echo Génération d'une clef standard
|
||||
Key-Type: DSA
|
||||
Key-Length: 1024
|
||||
Subkey-Type: ELG-E
|
||||
Subkey-Length: 1024
|
||||
Name-Real: Joe le testeur
|
||||
Name-Comment: ma phrase passe est stupide
|
||||
Name-Email: joe@foo.bar
|
||||
Expire-Date: 0
|
||||
Passphrase: abc
|
||||
%pubring foo.pub
|
||||
%secring foo.sec
|
||||
# Un commit est requis ici, pour pouvoir afficher un "done" :-)
|
||||
%commit
|
||||
%echo done
|
||||
EOF
|
||||
$ gpg --batch --gen-key -a foo
|
||||
[...]
|
||||
$ gpg --no-default-keyring --secret-keyring foo.sec \
|
||||
--keyring foo.pub --list-secret-keys
|
||||
/home/wk/work/gnupg-stable/scratch/foo.sec
|
||||
------------------------------------------
|
||||
sec 1024D/915A878D 2000-03-09 Joe le testeur (ma phrase passe est stupide) <joe@foo.bar>
|
||||
ssb 1024g/8F70E2C0 2000-03-09
|
||||
|
||||
|
||||
|
||||
Composition de la TrustDB
|
||||
=========================
|
||||
|
||||
La TrustDB est construire à partir d'enregistrements à taille fixe, où le premier
|
||||
octet décrit le type d'enregistrement. Toutes les valeurs numériques sont
|
||||
conservées dans un réseau d'ordre d'octets. La longueur de chaque enregistrement
|
||||
est de 40 octets. Le premier enregistrement de la TrustDB est toujours de type 1
|
||||
et c'est le seul enregistrement de ce type.
|
||||
|
||||
Record type 0:
|
||||
--------------
|
||||
|
||||
Cet enregistrement n'est pas utilisé. Il peut être utilisé
|
||||
à votre discrétion.
|
||||
|
||||
Record type 1:
|
||||
--------------
|
||||
|
||||
Indique la version de la TrustDB. Cet enregistrement doit toujours être
|
||||
le premier enregistrement de la base de données et c'est le seul
|
||||
enregistrement de type 1.
|
||||
|
||||
1 octet valeur : 1
|
||||
3 octets 'gpg' valeur "magic"
|
||||
1 octet Version de la TrustDB (2)
|
||||
1 octet marginales requises
|
||||
1 octet complètes requises
|
||||
1 octet max_cert_depth
|
||||
|
||||
Ces trois éléments sont utilisés pour vérifier si la valeur de validité
|
||||
mise en cache dans l'enregistrement du répertoire peut être utilisée :
|
||||
|
||||
1 u32 locked flags
|
||||
1 u32 datation de la création de la trustdb
|
||||
1 u32 datation de la dernière modification
|
||||
|
||||
Cette datation pourrait affecter la validité des clefs dans la base de
|
||||
données. Cette valeur sera comparée à celle de la datation de validité
|
||||
des enregistrements dir :
|
||||
|
||||
1 u32 datation de la dernière validation
|
||||
|
||||
Cette valeur sera utilisée pour stocker le passage du temps, lorsque
|
||||
cette TrustDB sera comparée au trousseau de clefs publiques :
|
||||
|
||||
1 u32 numéro de l'enregistrement du keyhashtable
|
||||
1 u32 premier enregistrement libre
|
||||
1 u32 numéro de l'enregistrement répertoire shadow de la table de hachage
|
||||
|
||||
Cette table ne devrait pas être combinée avec la table de clefs car le
|
||||
keyid n'est pas dans chaque cas un élément du fingerprint.
|
||||
|
||||
4 bytes réservés pour l'enregistrement d'extension de version
|
||||
|
||||
|
||||
Record type 2: (enregistrement répertoire)
|
||||
--------------
|
||||
|
||||
Regroupe les informations sur un certificat de clef publique.
|
||||
Ces valeur sont statiques et ne sont jamais modifiées sans une
|
||||
interaction avec l'utilisateur :
|
||||
|
||||
1 octet valeur : 2
|
||||
1 octet réservé
|
||||
1 u32 LID . (numéro d'enregistrement de cet enregistrement)
|
||||
1 u32 Liste de key-records (le premier est la clef primaire)
|
||||
1 u32 Liste de uid-records
|
||||
1 u32 cache record
|
||||
1 octet ownertrust
|
||||
1 octet dirflag
|
||||
1 octet validité maximale de tous les id utilisateurs
|
||||
1 u32 datation de la dernière vérification de validité
|
||||
1 u32 Vérification requise lorsque cette datation sera atteinte
|
||||
(0 = pas de vérification requise)
|
||||
|
||||
|
||||
Record type 3: (enregistrement de clef)
|
||||
--------------
|
||||
|
||||
Regroupe les informations sur une clef publique primaire.
|
||||
(ces informations sont principalement utilisées pour réaliser les lookup
|
||||
dans l'enregistrement trust)
|
||||
|
||||
1 octet valeur : 3
|
||||
1 octet réservé
|
||||
1 u32 LID
|
||||
1 u32 next - prochain enregistrement
|
||||
7 octets réservés
|
||||
1 octet keyflags
|
||||
1 octet algorithme de la clef publique
|
||||
1 octet taille du fingerprint (en octets)
|
||||
20 octets fingerprint de la clef publique
|
||||
(Cette valeur est utilisée pour identifier toute clef)
|
||||
|
||||
Record type 4: (enregistrement uid)
|
||||
--------------
|
||||
|
||||
Regroupe les informations sur un id utilisateur (un "uid").
|
||||
Nous ne stockons par l'uid mais un hachage de l'uid : cela semble suffire.
|
||||
|
||||
1 octet valeur : 4
|
||||
1 octet réservé
|
||||
1 u32 LID pointe vers l'enregistrement directory
|
||||
1 u32 next le userid suivant
|
||||
1 u32 pointeur vers l'enregistrement preference
|
||||
1 u32 siglist liste de signatures valides
|
||||
1 octet uidflags
|
||||
1 octet validité de la clef calculée pour cet userid
|
||||
20 bytes ripemd160 hachage du nom de l'utilisateur
|
||||
|
||||
|
||||
Record type 5: (enregistrement pref)
|
||||
--------------
|
||||
|
||||
Regroupe les informations formant les préférences.
|
||||
|
||||
1 octet valeur : 5
|
||||
1 octet réservé
|
||||
1 u32 LID; pointe vers l'enregistrement directory (et PAS vers le uid !!!)
|
||||
(égal à 0 pour un enregistrement de préférences standard)
|
||||
1 u32 suivant
|
||||
30 byte données de préférences
|
||||
|
||||
Record type 6 (sigrec)
|
||||
-------------
|
||||
|
||||
Cet enregistrement est utilisé pour traquer les signatures de clefs. Les
|
||||
auto-signatures ne sont pas conservées. Si une clef publique ne se trouve
|
||||
pas dans la TrustDB, la signature pointe vers un enregistrement dir fantôme,
|
||||
lequel contient une liste des enregistrements qui seraient intéressés
|
||||
par cette clef (et l'enregistrement signature en fait partie).
|
||||
|
||||
1 octet valeur : 6
|
||||
1 octet réservé
|
||||
1 u32 LID pointe en retour vers l'enregistrment dir
|
||||
1 u32 next prochain sigrec de cet uid ou bien 0 pour indiquer que ce
|
||||
sigrec est le dernier.
|
||||
6 times
|
||||
1 u32 Local_id des dir signatures ou de l'enregistrement dir fantôme
|
||||
1 octet Flag: Bit 0 = vérifié: Bit 1 est valide (nous avons un
|
||||
véritable enregistrement directory)
|
||||
1 = valide est vrai (mais pourrait être révoqué)
|
||||
|
||||
|
||||
|
||||
Record type 8: (enregistrement répertoire (dir) fantôme)
|
||||
--------------
|
||||
|
||||
Cet enregistrement est utilisé pour réserver un LID pour une clef publique.
|
||||
Nous avons besoin de cet enregistrement pour créer les enregistrements sigs
|
||||
des autres clefs, même si nous ne disposons pas d'une signature de la clef
|
||||
publique.
|
||||
Cet enregistrement (le numéro d'enregistrement pour être plus précis)
|
||||
sera réutilisé dans l'enregistrement dir lorsque nous importerons la
|
||||
véritable clef publique.
|
||||
|
||||
1 octet valeur : 8
|
||||
1 octet réservé
|
||||
1 u32 LID (Ceci est simplement le numéro d'enregistrement de ce record.)
|
||||
2 u32 keyid
|
||||
1 octet algorithme de la clef publique
|
||||
3 octets réservé
|
||||
1 u32 hintlist
|
||||
|
||||
hintlist contient la liste des enregistrements qui ont des références qui pointent
|
||||
vers cette clef. Nous utilisons cet élément pour augmenter la vitesse d'accès
|
||||
des enregistrements de signature qui ne sont pas encore vérifiés. Notez que ces
|
||||
données ne sont qu'un indice, une indication ("hint") mais les enregistrements actuels
|
||||
pourraient ne pas détenir d'enregistrement de signature pour la clef, mais le
|
||||
code du programme saura prendre soin de tout cela.
|
||||
|
||||
18 octets réservés
|
||||
|
||||
|
||||
|
||||
Record Type 10 (table de hachage)
|
||||
--------------
|
||||
|
||||
Comme nous utilisons les fingerprint pour accéder aux clefs, nous devons
|
||||
implémenter un accès rapide en utilisant des méthodes de hachages simples,
|
||||
afin d'éviter une surcharge de gdbm. La propriété des fingerprint
|
||||
est qu'ils permettent un usage direct en tant que valeurs hachées (ils
|
||||
peuvent être considérés comme des nombres aléatoires cryptographiquement
|
||||
forts).
|
||||
Nous utilisons une architecture à multiples niveaux dynamique, qui combine
|
||||
les tables de hachage, les listes d'enregistrements et les listes
|
||||
chaînées.
|
||||
|
||||
Cet enregistrement est une table de hachages de 256 entrées ; une propriété
|
||||
spéciale est que tous les enregistrements sont stockés consécutivement
|
||||
pour produire une grande table. La valeur hachée est simplement le 1er,
|
||||
2nd.. octet du fingerprint (selon le niveau d'indirection).
|
||||
|
||||
Lorsque nous les utilisons pour hacher les enregistrements de répertoires
|
||||
shadow, une différente table est utilisée, et elle se trouve indexée
|
||||
par le keyid.
|
||||
|
||||
1 octet valeur : 10
|
||||
1 octet réservé
|
||||
n u32 recnum; n dépend de la taille de l'enregistrement :
|
||||
n = (reclen-2)/4 ce qui donne 9 pour la taille actuelle
|
||||
d'enregistrement de 40 octets.
|
||||
|
||||
Le nombre total de ces enregistrements constituant la table est :
|
||||
|
||||
m = (256+n-1) / n
|
||||
|
||||
ce qui donne 29 pour une taille d'enregistrement de 40.
|
||||
|
||||
Pour rechercher une clef, nous utilisons le premier octet du fingerprint
|
||||
pour obtenir le recnum de la table de hachage et nous étudions l'enregistrement
|
||||
adressé :
|
||||
|
||||
o Si cet enregistrement est une autre table de hachage, nous pouvons
|
||||
utiliser le second octet pour indexer cette table de hachage et continuer.
|
||||
|
||||
o Si cet enregistrement est une liste de hachages, nous pouvons parcourir
|
||||
toutes les entrées jusqu'à trouver la bonne.
|
||||
|
||||
o Si cet enregistrement est un enregistrement de clef, nous comparons
|
||||
le fingerprint avec celui recherché et nous déterminons s'il s'agit
|
||||
de la clef recherchée.
|
||||
|
||||
|
||||
|
||||
Record type 11 (liste hachée)
|
||||
--------------
|
||||
|
||||
Consultez la table hachée pour une explication.
|
||||
Ceci sera également utilisé à d'autres fins.
|
||||
|
||||
1 octet valeur : 11
|
||||
1 octet réservé
|
||||
1 u32 next enregistrement de liste hachée suivant
|
||||
n times n = (reclen-5)/5
|
||||
1 u32 recnum
|
||||
|
||||
Pour la taille actuelle utilisée par les enregistrements (taille 40) nous avons n = 7.
|
||||
|
||||
|
||||
|
||||
|
||||
Record type 254 (enregistrement libre)
|
||||
---------------
|
||||
|
||||
Tous ces enregistrements forment une liste chaînée d'enregistrements non-utilisés.
|
||||
|
||||
1 octet valeur 254
|
||||
1 octet réservé (0)
|
||||
1 u32 next_free
|
||||
|
||||
|
||||
|
||||
En-têtes de paquets
|
||||
===================
|
||||
|
||||
GnuPG utilise des en-têtes PGP 2 et il est aussi capable de comprendre
|
||||
les en-têtes de type OpenPGP. C'est une amélioration utilisée sur les anciens
|
||||
en-têtes de paquets :
|
||||
|
||||
Les CTB bits 10, les "packet-length length bits" ont leurs valeurs listées
|
||||
dans la table suivante :
|
||||
|
||||
00 - 1-octet champ packet-length
|
||||
01 - 2-octets champ packet-length
|
||||
10 - 4-octets champ packet-length
|
||||
11 - pas de taille de paquet fournie, taille inconnue
|
||||
|
||||
Comme indiqué dans cette table, selon la taille du packet-length les
|
||||
octets restants (1, 2, 4 ou 0) du champ de structure de paquets sont
|
||||
un "champ packet-length". Ce champ est une valeur numérique à part entière.
|
||||
La valeur du champ packet-length est définie par la valeur de la
|
||||
totalité du champ numérique.
|
||||
|
||||
La valeur 11 est actuellement utilisée dans un cas : les données
|
||||
compressées. C''est à dire qu'un bloc de données compressées
|
||||
ressemble à : <A3 01 .. .. > où A3 est le binaire "10 1000 11" et
|
||||
produit ici un paquet de taille non-définie. L'interprétation
|
||||
correcte en est : "jusqu'à la fin de la structure englobante"
|
||||
bien qu'en fait la structure englobante soit généralement
|
||||
le fichier.
|
||||
|
||||
+ Ceci sera modifié dans une future version, où la signification de la
|
||||
+ valeur 11 (voir ci-dessous) aura aussi sa place.
|
||||
+
|
||||
+ Une valeur de 11 pour d'autres paquets active un codage spécial
|
||||
+ de la taille, où la taille du paquet suivant ne pourra pas être
|
||||
+ déterminée avant l'écriture du paquet, en particulier ceci sera
|
||||
+ utilisé si de grande quantités de données sont à traiter dans
|
||||
+ un mode filtre.
|
||||
+
|
||||
+ Ceci fonctionne de la manière suivante : après le CTB (qui est un
|
||||
+ champ de longueur de 11) un champ marqueur sera utilisé, il indiquera
|
||||
+ alors la taille du bloc de données suivant. C'est un simple champ
|
||||
+ de deux octets (MSB en premier) contenant la quantité de données qui
|
||||
+ suivent le champ, sans inclure le champ de taille toutefois. Après
|
||||
+ ce bloc de données un autre champ de taille suivra, qui donnera la taille
|
||||
+ du bloc de données suivant. Une valeur de 0 indique une fin de paquet.
|
||||
+ La taille maximale d'un bloc de données est limitée à 65534, ce qui
|
||||
+ réserve la valeur 0xffff pour des extensions futures. Ces marqueurs de
|
||||
+ taille devront être insérés dans le flux de données avant que les
|
||||
+ données ne soient envoyées en sortie.
|
||||
+
|
||||
+ Ce champ de deux octets est largement suffisant, car l'application
|
||||
+ doit placer en tampon cette quantité de données pour précéder le
|
||||
+ marqueur de taille avant de produire une sortie. Les blocs de données
|
||||
+ d'une taille supérieure à 32 Ko n'ont aucun sens. Notez que ceci pourra
|
||||
+ également être utilisé pour les flux de données compressées, mais
|
||||
+ nous devrons alors utiliser une autre version de paquet afin de dire à
|
||||
+ l'application qu'elle ne peut assumer qu'il s'agit du dernier paquet.
|
||||
|
||||
|
||||
Extensions GNU à l'algorithme S2K
|
||||
=================================
|
||||
|
||||
Le S2K mode 101 est utilisé pour identifier ces extensions.
|
||||
Après l'algorithme de hachage les trois octets "GNU" sont utilisés
|
||||
pour indiquer clairement qu'il s'agit d'extensions GNU et les octets
|
||||
qui suivent donnent le mode de protection GNU utilisé : 1000. Les
|
||||
modes définis sont :
|
||||
|
||||
1001 - ne pas conserver du tout de partie secrète
|
||||
|
||||
|
||||
|
||||
Usage des fichiers gdbm pour les trousseaux de clefs
|
||||
====================================================
|
||||
|
||||
La clef utilisé pour stocker le keyblock est son propre fingerprint,
|
||||
les autres enregistrements sont utilisés pour les clefs secondaires.
|
||||
Les fingerprint font toujours 20 octets où 16 bits de fingerprint
|
||||
sont suivis par 0. Le premier octet de chaque clef indique une
|
||||
information sur le type de clef :
|
||||
|
||||
1 = la clef est un fingerprint de 20 octets (16 octets fpr "paddés" de 0)
|
||||
les données sont le keyblock
|
||||
2 = la clef est un keyid complet de 8 octets
|
||||
les données sont une liste de 20 octets fingerprints
|
||||
3 = la clef est un keyid court de 4 octets
|
||||
les données sont une liste de 20 octets fingerprints
|
||||
4 = la clef est une adresse email
|
||||
les données sont une liste de 20 octets fingerprints
|
||||
|
||||
Les données sont pre-appended (précédées) par un octet de type :
|
||||
|
||||
1 = keyblock
|
||||
2 = liste de 20 octets fingerprints "paddés"
|
||||
3 = liste de liste de fingerprints ("but how to we key them?")
|
||||
|
||||
|
||||
|
||||
Pipemode
|
||||
========
|
||||
|
||||
Ce mode est utilisé pour réaliser des opérations multiples avec un
|
||||
unique appel à gpg. C'est assez pratique lorsqu'il faut pouvoir vérifier
|
||||
un grand nombre de signatures. Actuellement nous n'avons qu'un support
|
||||
des signatures détachées. Ce mode est une astuce qui permet d'éviter
|
||||
de faire fonctionner gpg n en daemon mode et d'utiliser les Unix Domain
|
||||
Sockets pour lui faire passer les données. Il n'existe aucun moyen
|
||||
pratique de portabilité de ce concept sous Windows, alors nous utilisons
|
||||
des pipes simples pour faire fonctionner ce mode sous Windows. Comme nous
|
||||
n'avons aucun moyen de signaler des EOF multiples dans un pipe nous
|
||||
devons laisser le contrôle s'insérer dans le flux de données lui-même.
|
||||
Nous réalisons alors une distinction entre les données du flux et un
|
||||
état de contrôle. A son lancement, le système se trouve dans un état
|
||||
de données mais n'acceptera aucune donnée. Il attend en fait une
|
||||
transition vers un mode de contrôle qui s'obtient en envoyant un simple
|
||||
caractère '@'. Une fois dans le mode de contrôle, des commandes sont
|
||||
attendues et ces commandes sont à un octet après lequel le système
|
||||
revient au mode de données (mais cela n'implique pas qu'il acceptera
|
||||
des données immédiatement). La commande de contrôle la plus simple
|
||||
est '@' qui permet d'insérer ce caractère dans le flux de données.
|
||||
|
||||
Voici le format que nous utilisons pour les signatures détachées :
|
||||
|
||||
"@<" - Début d'un nouveau flux
|
||||
"@B" - La signature détachée suit.
|
||||
Ceci émet le paquet de contrôle (1,'B')
|
||||
<detached_signature>
|
||||
"@t" - Le texte signé suit.
|
||||
Ceci émet le paquet de contrôle (2, 'B')
|
||||
<signed_text>
|
||||
"@." - Fin de l'opération. Le paquet de contrôle final force la
|
||||
vérification de la signature.
|
||||
"@>" - Fin du flux.
|
||||
|
||||
|
||||
|
||||
Autres notes
|
||||
============
|
||||
|
||||
Dans la version* 3 de version de paquet nous calculons les keyid de cette manière :
|
||||
|
||||
RSA : les 64 bits de poids faible de n
|
||||
ELGAMAL : nous construisons un paquet de clef publique v3 (avec CTB 0x99)
|
||||
et nous calculons une valeur hachée rmd160 à partir de ce paquet.
|
||||
Il est utilisé comme fingerprint avec les 64 bits de poids faible
|
||||
qui produisent le keyid.
|
||||
|
||||
* Les certificats de révocation ne comportent qu'un paquet de signature ;
|
||||
"import" sait comment traiter ces paquets. L'idée derrière ce principe
|
||||
est de conserver une petite taille de paquet.
|
||||
|
||||
|
||||
|
||||
Format des messages Keyserver
|
||||
=============================
|
||||
|
||||
Le serveur de clef peut être contacté par un Unix Domain Socket ou via TCP.
|
||||
|
||||
Le format des requêtes est :
|
||||
|
||||
====
|
||||
command-tag
|
||||
"Content-length:" digits
|
||||
CRLF
|
||||
=======
|
||||
|
||||
Où le command-tag est :
|
||||
|
||||
NOOP
|
||||
GET <user-name>
|
||||
PUT
|
||||
DELETE <user-name>
|
||||
|
||||
|
||||
Le format de réponse utilisé est :
|
||||
|
||||
======
|
||||
"GNUPG/1.0" status-code status-text
|
||||
"Content-length:" digits
|
||||
CRLF
|
||||
============
|
||||
|
||||
suivi par <digits> octets de données.
|
||||
|
||||
|
||||
Les codes de statut utilisés sont :
|
||||
|
||||
o 1xx: Information: requête reçue, traitement en cours.
|
||||
|
||||
o 2xx: Succès - L'action a été reçue, comprise et acceptée.
|
||||
|
||||
o 4xx: Erreur client : la requête contient une erreur, mauvaise syntaxe
|
||||
ou demande irréalisable.
|
||||
|
||||
o 5xx: Erreur serveur - Le serveur n'a pu traiter une demande
|
||||
qui semble valide.
|
||||
|
||||
|
||||
Documentation sur HKP (le protocol de serveurs de clefs http)
|
||||
=============================================================
|
||||
|
||||
Un serveur HTTP minimal sur port 11371 reconnaît les requêtes GET
|
||||
pour /pks/lookup. Les paramètres standard encodés URL de la requête
|
||||
sont toujours ceux-ci : (toujours key=valeur)
|
||||
|
||||
- op=index (comme pgp -kv), op=vindex (comme pgp -kvv) and op=get (comme
|
||||
pgp -kxa)
|
||||
|
||||
- search=<stringlist>. Nous avons ici une liste de mots qui doivent
|
||||
apparaître dans la clef. Ces mots sont séparés par des espaces,
|
||||
points, @, etc. Les délimiteurs ne feront pas partie de la
|
||||
recherche et l'ordre des mots n'a aucune importance (mais consultez
|
||||
l'option suivante).
|
||||
|
||||
- exact=on. Ce switch permet d'indiquer au serveur hkp qu'il ne doit
|
||||
rechercher que les correspondances exactes. Dans ce cas, les
|
||||
délimiteurs et l'ordre des mots sera considéré.
|
||||
|
||||
- fingerprint=on. Renvoie également les fingerprint, lorsque utilisé
|
||||
avec 'index' ou 'vindex'
|
||||
|
||||
Les serveurs de clefs savent aussi reconnaître le format http-POST vers /pks/add.
|
||||
Vous utilisez ceci pour envoyer des clefs au serveur.
|
||||
|
||||
Le mieux pour produire une requête reste :
|
||||
|
||||
/pks/lookup/<gnupg_formatierte_user_id>?op=<operation>
|
||||
|
||||
Ceci peut être implémenté en utilisant le mécanisme de traduction Hurd.
|
||||
Toutefois, nous pensons que les traitements du serveur de clef doivent
|
||||
faire l'objet d'une refonte.
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue